⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2006 Christophe Fillot (cf@utc.fr) * * Mini-parser. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <signal.h>#include <fcntl.h>#include <errno.h>#include <assert.h>#include <stdarg.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include "utils.h"#include "parser.h"#define TOKEN_MAX_SIZE  512/* Character types */enum {   PARSER_CHAR_BLANK,   PARSER_CHAR_NEWLINE,   PARSER_CHAR_COMMENT,   PARSER_CHAR_QUOTE,   PARSER_CHAR_OTHER,};/* Get a description given an error code */char *parser_strerror(parser_context_t *ctx){   printf("error = %d\n",ctx->error);   switch(ctx->error) {      case 0:         return "no error";      case PARSER_ERROR_NOMEM:         return "insufficient memory";      case PARSER_ERROR_UNEXP_QUOTE:         return "unexpected quote";      case PARSER_ERROR_UNEXP_EOL:         return "unexpected end of line";      default:         return "unknown error";   }}/* Dump a token list */void parser_dump_tokens(parser_context_t *ctx){   parser_token_t *tok;   for(tok=ctx->tok_head;tok;tok=tok->next)      printf("\"%s\" ",tok->value);}/* Map a token list to an array */char **parser_map_array(parser_context_t *ctx){   parser_token_t *tok;   char **map;   int i;   if (ctx->tok_count <= 0)      return NULL;   if (!(map = calloc(ctx->tok_count,sizeof(char **))))      return NULL;   for(i=0,tok=ctx->tok_head;(i<ctx->tok_count) && tok;i++,tok=tok->next)      map[i] = tok->value;   return map;}/* Add a character to temporary token (resize if necessary) */static int tmp_token_add_char(parser_context_t *ctx,u_char c){   size_t new_size;   char *new_str;   if (!ctx->tmp_tok || (ctx->tmp_cur_len == (ctx->tmp_tot_len - 1))) {      new_size = ctx->tmp_tot_len + TOKEN_MAX_SIZE;      new_str  = realloc(ctx->tmp_tok,new_size);      if (!new_str)         return(-1);      ctx->tmp_tok = new_str;      ctx->tmp_tot_len = new_size;   }   ctx->tmp_tok[ctx->tmp_cur_len++] = c;   ctx->tmp_tok[ctx->tmp_cur_len] = 0;   return(0);}/* Move current token to the active token list */static int parser_move_tmp_token(parser_context_t *ctx){   parser_token_t *tok;   /* no token ... */   if (!ctx->tmp_tok)      return(0);   if (!(tok = malloc(sizeof(*tok))))      return(-1);   tok->value = ctx->tmp_tok;   tok->next  = NULL;   /* add it to the token list */   if (ctx->tok_last != NULL)      ctx->tok_last->next = tok;   else      ctx->tok_head = tok;   ctx->tok_last = tok;   ctx->tok_count++;   /* start a new token */   ctx->tmp_tok = NULL;   ctx->tmp_tot_len = ctx->tmp_cur_len = 0;   return(0);}/* Initialize parser context */void parser_context_init(parser_context_t *ctx){   ctx->tok_head = ctx->tok_last = NULL;   ctx->tok_count = 0;   ctx->tmp_tok = NULL;   ctx->tmp_tot_len = ctx->tmp_cur_len = 0;   ctx->state = PARSER_STATE_BLANK;   ctx->error = 0;   ctx->consumed_len = 0;}/* Free a token list */void parser_free_tokens(parser_token_t *tok_list){   parser_token_t *t,*next;   for(t=tok_list;t;t=next) {      next = t->next;      free(t->value);      free(t);   }}/* Free memory used by a parser context */void parser_context_free(parser_context_t *ctx){   parser_free_tokens(ctx->tok_head);   if (ctx->tmp_tok != NULL)      free(ctx->tmp_tok);   parser_context_init(ctx);}/* Determine the type of the input character */static int parser_get_char_type(u_char c){   switch(c) {      case '\n':      case '\r':      case 0:         return(PARSER_CHAR_NEWLINE);      case '\t':         //case '\r':      case ' ':         return(PARSER_CHAR_BLANK);      case '!':      case '#':         return(PARSER_CHAR_COMMENT);      case '"':         return(PARSER_CHAR_QUOTE);      default:         return(PARSER_CHAR_OTHER);   }}/* Send a buffer to the tokenizer */int parser_scan_buffer(parser_context_t *ctx,u_char *buf,size_t buf_size){   int i,type;   u_char c;   for(i=0;(i<buf_size) && (ctx->state != PARSER_STATE_DONE);i++)   {      ctx->consumed_len++;      c = buf[i];            /* Determine character type */      type = parser_get_char_type(c);      /* Basic finite state machine */      switch(ctx->state) {         case PARSER_STATE_SKIP:            if (type == PARSER_CHAR_NEWLINE)               ctx->state = PARSER_STATE_DONE;            /* Simply ignore character until we reach end of line */            break;         case PARSER_STATE_BLANK:            switch(type) {               case PARSER_CHAR_BLANK:                  /* Eat space */                  break;               case PARSER_CHAR_COMMENT:                  ctx->state = PARSER_STATE_SKIP;                  break;               case PARSER_CHAR_NEWLINE:                  ctx->state = PARSER_STATE_DONE;                  break;               case PARSER_CHAR_QUOTE:                  ctx->state = PARSER_STATE_QUOTED_STRING;                  break;                                 default:                  /* Begin a new string */                  if (!tmp_token_add_char(ctx,c)) {                     ctx->state = PARSER_STATE_STRING;                  } else {                     ctx->state = PARSER_STATE_SKIP;                     ctx->error = PARSER_ERROR_NOMEM;                  }            }            break;         case PARSER_STATE_STRING:            switch(type) {               case PARSER_CHAR_BLANK:                  if (!parser_move_tmp_token(ctx)) {                     ctx->state = PARSER_STATE_BLANK;                  } else {                     ctx->state = PARSER_STATE_SKIP;                     ctx->error = PARSER_ERROR_NOMEM;                  }                  break;               case PARSER_CHAR_NEWLINE:                  if (parser_move_tmp_token(ctx) == -1)                     ctx->error = PARSER_ERROR_NOMEM;                  ctx->state = PARSER_STATE_DONE;                  break;               case PARSER_CHAR_COMMENT:                  if (parser_move_tmp_token(ctx) == -1)                     ctx->error = PARSER_ERROR_NOMEM;                  ctx->state = PARSER_STATE_SKIP;                  break;               case PARSER_CHAR_QUOTE:                  ctx->error = PARSER_ERROR_UNEXP_QUOTE;                  ctx->state = PARSER_STATE_SKIP;                  break;               default:                  /* Add the character to the buffer */                  if (tmp_token_add_char(ctx,c) == -1) {                     ctx->state = PARSER_STATE_SKIP;                     ctx->error = PARSER_ERROR_NOMEM;                  }            }            break;         case PARSER_STATE_QUOTED_STRING:            switch(type) {               case PARSER_CHAR_NEWLINE:                  /* Unterminated string! */                  ctx->error = PARSER_ERROR_UNEXP_EOL;                  ctx->state = PARSER_STATE_DONE;                  break;               case PARSER_CHAR_QUOTE:                  if (!parser_move_tmp_token(ctx)) {                     ctx->state = PARSER_STATE_BLANK;                  } else {                     ctx->state = PARSER_STATE_SKIP;                     ctx->error = PARSER_ERROR_NOMEM;                  }                  break;               default:                  /* Add the character to the buffer */                  if (tmp_token_add_char(ctx,c) == -1) {                     ctx->state = PARSER_STATE_SKIP;                     ctx->error = PARSER_ERROR_NOMEM;                  }            }            break;      }   }   return(ctx->state == PARSER_STATE_DONE);}/* Parser tests */static char *parser_test_str[] = {   "c7200 show_hardware R1",   "c7200 show_hardware \"R1\"",   "   c7200    show_hardware   \"R1\"    ",   "\"c7200\" \"show_hardware\" \"R1\"",   "hypervisor set_working_dir \"C:\\Program Files\\Dynamips Test\"",   "hypervisor # This is a comment set_working_dir \"C:\\Program Files\"",   "\"c7200\" \"show_hardware\" \"R1",   NULL,};void parser_run_tests(void){   parser_context_t ctx;   int i,res;   for(i=0;parser_test_str[i];i++) {      parser_context_init(&ctx);      res = parser_scan_buffer(&ctx,parser_test_str[i],                               strlen(parser_test_str[i])+1);      printf("\n%d: Test string: [%s] => res=%d, state=%d\n",             i,parser_test_str[i],res,ctx.state);            if ((res != 0) && (ctx.error == 0)) {         if (ctx.tok_head) {            printf("Tokens: ");            parser_dump_tokens(&ctx);            printf("\n");         }      }      parser_context_free(&ctx);   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -