/[dynamips]/upstream/dynamips-0.2.6-RC1/parser.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /upstream/dynamips-0.2.6-RC1/parser.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

upstream/dynamips-0.2.5/parser.c revision 1 by dpavlin, Sat Oct 6 16:01:44 2007 UTC upstream/dynamips-0.2.6-RC1/parser.c revision 2 by dpavlin, Sat Oct 6 16:03:58 2007 UTC
# Line 27  Line 27 
27    
28  #define TOKEN_MAX_SIZE  512  #define TOKEN_MAX_SIZE  512
29    
 /* Parser states */  
 enum {  
    PARSER_STATE_BLANK,  
    PARSER_STATE_STRING,  
    PARSER_STATE_QUOTED_STRING,  
 };  
   
30  /* Character types */  /* Character types */
31  enum {  enum {
32     PARSER_CHAR_BLANK,     PARSER_CHAR_BLANK,
# Line 44  enum { Line 37  enum {
37  };  };
38    
39  /* Get a description given an error code */  /* Get a description given an error code */
40  char *parser_strerror(int error)  char *parser_strerror(parser_context_t *ctx)
41  {  {
42     printf("error = %d\n",error);     printf("error = %d\n",ctx->error);
43    
44     switch(error) {     switch(ctx->error) {
45          case 0:
46             return "no error";
47        case PARSER_ERROR_NOMEM:        case PARSER_ERROR_NOMEM:
48           return "insufficient memory";           return "insufficient memory";
49        case PARSER_ERROR_UNEXP_QUOTE:        case PARSER_ERROR_UNEXP_QUOTE:
# Line 60  char *parser_strerror(int error) Line 55  char *parser_strerror(int error)
55     }     }
56  }  }
57    
58  /* Create a new token */  /* Dump a token list */
59  static int token_create(parser_token_t **head,parser_token_t **last,  void parser_dump_tokens(parser_context_t *ctx)
                         char *value)  
60  {  {
61     parser_token_t *t;     parser_token_t *tok;
62    
63     if (!(t = malloc(sizeof(*t))))     for(tok=ctx->tok_head;tok;tok=tok->next)
64        return(-1);        printf("\"%s\" ",tok->value);
65    }
66    
67     if (!(t->value = strdup(value))) {  /* Map a token list to an array */
68        free(t);  char **parser_map_array(parser_context_t *ctx)
69        return(-1);  {
70     }     parser_token_t *tok;
71       char **map;
72       int i;
73    
74       if (ctx->tok_count <= 0)
75          return NULL;
76    
77       if (!(map = calloc(ctx->tok_count,sizeof(char **))))
78          return NULL;
79    
80       for(i=0,tok=ctx->tok_head;(i<ctx->tok_count) && tok;i++,tok=tok->next)
81          map[i] = tok->value;
82    
83       return map;
84    }
85    
86    /* Add a character to temporary token (resize if necessary) */
87    static int tmp_token_add_char(parser_context_t *ctx,u_char c)
88    {
89       size_t new_size;
90       char *new_str;
91    
92     t->next = NULL;     if (!ctx->tmp_tok || (ctx->tmp_cur_len == (ctx->tmp_tot_len - 1))) {
93          new_size = ctx->tmp_tot_len + TOKEN_MAX_SIZE;
94          new_str  = realloc(ctx->tmp_tok,new_size);
95    
96     if (*last) {        if (!new_str)
97        (*last)->next = t;           return(-1);
98        *last = t;  
99     } else {        ctx->tmp_tok = new_str;
100        *head = *last = t;        ctx->tmp_tot_len = new_size;
101     }     }
102    
103       ctx->tmp_tok[ctx->tmp_cur_len++] = c;
104       ctx->tmp_tok[ctx->tmp_cur_len] = 0;
105       return(0);
106    }
107    
108    /* Move current token to the active token list */
109    static int parser_move_tmp_token(parser_context_t *ctx)
110    {
111       parser_token_t *tok;
112    
113       /* no token ... */
114       if (!ctx->tmp_tok)
115          return(0);
116    
117       if (!(tok = malloc(sizeof(*tok))))
118          return(-1);
119    
120       tok->value = ctx->tmp_tok;
121       tok->next  = NULL;
122    
123       /* add it to the token list */
124       if (ctx->tok_last != NULL)
125          ctx->tok_last->next = tok;
126       else
127          ctx->tok_head = tok;
128    
129       ctx->tok_last = tok;
130       ctx->tok_count++;
131    
132       /* start a new token */
133       ctx->tmp_tok = NULL;
134       ctx->tmp_tot_len = ctx->tmp_cur_len = 0;
135     return(0);     return(0);
136  }  }
137    
138    /* Initialize parser context */
139    void parser_context_init(parser_context_t *ctx)
140    {
141       ctx->tok_head = ctx->tok_last = NULL;
142       ctx->tok_count = 0;
143    
144       ctx->tmp_tok = NULL;
145       ctx->tmp_tot_len = ctx->tmp_cur_len = 0;
146    
147       ctx->state = PARSER_STATE_BLANK;
148       ctx->error = 0;
149    
150       ctx->consumed_len = 0;
151    }
152    
153  /* Free a token list */  /* Free a token list */
154  void parser_free_tokens(parser_token_t *tok_list)  void parser_free_tokens(parser_token_t *tok_list)
155  {  {
156     parser_token_t *t,*next;     parser_token_t *t,*next;
157      
158     for(t=tok_list;t;t=next) {     for(t=tok_list;t;t=next) {
159        next = t->next;        next = t->next;
160        free(t->value);        free(t->value);
# Line 98  void parser_free_tokens(parser_token_t * Line 162  void parser_free_tokens(parser_token_t *
162     }     }
163  }  }
164    
165  /* Dump a token list */  /* Free memory used by a parser context */
166  void parser_dump_tokens(parser_token_t *tok_list)  void parser_context_free(parser_context_t *ctx)
 {  
    parser_token_t *t;  
   
    for(t=tok_list;t;t=t->next)  
       printf("\"%s\" ",t->value);  
 }  
   
 /* Map a token list to an array */  
 char **parser_map_array(parser_token_t *tok_list,int tok_count)  
167  {  {
168     char **map;     parser_free_tokens(ctx->tok_head);
    int i;  
   
    if (tok_count <= 0)  
       return NULL;  
169    
170     if (!(map = calloc(tok_count,sizeof(char **))))     if (ctx->tmp_tok != NULL)
171        return NULL;        free(ctx->tmp_tok);
   
    for(i=0;(i<tok_count) && tok_list;i++,tok_list=tok_list->next)  
       map[i] = tok_list->value;  
172    
173     return map;     parser_context_init(ctx);
174  }  }
175    
176  /* Add a character to a buffer */  /* Determine the type of the input character */
177  static int buffer_add_char(char *buffer,int *pos,char c)  static int parser_get_char_type(u_char c)
178  {  {
179     if (*pos >= TOKEN_MAX_SIZE)     switch(c) {
180        return(-1);        case '\n':
181          case '\r':
182     buffer[(*pos)++] = c;        case 0:
183     buffer[*pos] = 0;           return(PARSER_CHAR_NEWLINE);
184     return(0);        case '\t':
185             //case '\r':
186          case ' ':
187             return(PARSER_CHAR_BLANK);
188          case '!':
189          case '#':
190             return(PARSER_CHAR_COMMENT);
191          case '"':
192             return(PARSER_CHAR_QUOTE);
193          default:
194             return(PARSER_CHAR_OTHER);
195       }
196  }  }
197    
198  /* Tokenize a string */  /* Send a buffer to the tokenizer */
199  int parser_tokenize(char *str,struct parser_token **tokens,int *tok_count)  int parser_scan_buffer(parser_context_t *ctx,u_char *buf,size_t buf_size)
200  {  {
201     char buffer[TOKEN_MAX_SIZE+1];     int i,type;
202     parser_token_t *tok_head,*tok_last;     u_char c;
    int i,buf_pos,type;  
    int state,error,done;  
    size_t len;  
    char c;  
   
    len        = strlen(str);  
    tok_head   = tok_last = NULL;  
    *tokens    = NULL;  
    *tok_count = 0;  
    state      = PARSER_STATE_BLANK;  
    done       = FALSE;  
    error      = 0;  
    buf_pos    = 0;  
203    
204     for(i=0;(i<len+1) && !error && !done;i++)     for(i=0;(i<buf_size) && (ctx->state != PARSER_STATE_DONE);i++)
205     {     {
206        c = str[i];        ctx->consumed_len++;
207          c = buf[i];
208                
209        /* Determine character type */        /* Determine character type */
210        switch(c) {        type = parser_get_char_type(c);
          case '\n':  
          case '\r':  
          case 0:  
             type = PARSER_CHAR_NEWLINE;  
             break;  
          case '\t':  
          case ' ':  
             type = PARSER_CHAR_BLANK;  
             break;  
          case '!':  
          case '#':  
             type = PARSER_CHAR_COMMENT;  
             break;  
          case '"':  
             type = PARSER_CHAR_QUOTE;  
             break;  
          default:  
             type = PARSER_CHAR_OTHER;  
       }  
211    
212        /* Basic finite state machine */        /* Basic finite state machine */
213        switch(state) {        switch(ctx->state) {
214             case PARSER_STATE_SKIP:
215                if (type == PARSER_CHAR_NEWLINE)
216                   ctx->state = PARSER_STATE_DONE;
217    
218                /* Simply ignore character until we reach end of line */
219                break;
220    
221           case PARSER_STATE_BLANK:           case PARSER_STATE_BLANK:
222              switch(type) {              switch(type) {
223                 case PARSER_CHAR_BLANK:                 case PARSER_CHAR_BLANK:
224                    /* Eat space */                    /* Eat space */
225                    break;                    break;
226    
                case PARSER_CHAR_NEWLINE:  
227                 case PARSER_CHAR_COMMENT:                 case PARSER_CHAR_COMMENT:
228                    done = TRUE;                    ctx->state = PARSER_STATE_SKIP;
229                      break;
230    
231                   case PARSER_CHAR_NEWLINE:
232                      ctx->state = PARSER_STATE_DONE;
233                    break;                    break;
234    
235                 case PARSER_CHAR_QUOTE:                 case PARSER_CHAR_QUOTE:
236                    state = PARSER_STATE_QUOTED_STRING;                    ctx->state = PARSER_STATE_QUOTED_STRING;
                   buf_pos = 0;  
237                    break;                    break;
238                                        
239                 default:                 default:
240                    /* Begin a new string */                    /* Begin a new string */
241                    state = PARSER_STATE_STRING;                                      if (!tmp_token_add_char(ctx,c)) {
242                    buf_pos = 0;                       ctx->state = PARSER_STATE_STRING;
243                    buffer_add_char(buffer,&buf_pos,c);                    } else {
244                         ctx->state = PARSER_STATE_SKIP;
245                         ctx->error = PARSER_ERROR_NOMEM;
246                      }
247              }              }
248              break;              break;
249    
250           case PARSER_STATE_STRING:           case PARSER_STATE_STRING:
251              switch(type) {              switch(type) {
252                 case PARSER_CHAR_BLANK:                 case PARSER_CHAR_BLANK:
253                    if (token_create(&tok_head,&tok_last,buffer) == -1)                    if (!parser_move_tmp_token(ctx)) {
254                       error = PARSER_ERROR_NOMEM;                       ctx->state = PARSER_STATE_BLANK;
255                      } else {
256                    (*tok_count)++;                       ctx->state = PARSER_STATE_SKIP;
257                    state = PARSER_STATE_BLANK;                       ctx->error = PARSER_ERROR_NOMEM;
258                      }
259                    break;                    break;
260    
261                 case PARSER_CHAR_NEWLINE:                 case PARSER_CHAR_NEWLINE:
262                    if (token_create(&tok_head,&tok_last,buffer) == -1)                    if (parser_move_tmp_token(ctx) == -1)
263                       error = PARSER_ERROR_NOMEM;                       ctx->error = PARSER_ERROR_NOMEM;
264    
265                    (*tok_count)++;                    ctx->state = PARSER_STATE_DONE;
                   done = TRUE;  
266                    break;                    break;
267    
268                 case PARSER_CHAR_COMMENT:                 case PARSER_CHAR_COMMENT:
269                    done = TRUE;                    if (parser_move_tmp_token(ctx) == -1)
270                         ctx->error = PARSER_ERROR_NOMEM;
271    
272                      ctx->state = PARSER_STATE_SKIP;
273                    break;                    break;
274    
275                 case PARSER_CHAR_QUOTE:                 case PARSER_CHAR_QUOTE:
276                    error = PARSER_ERROR_UNEXP_QUOTE;                    ctx->error = PARSER_ERROR_UNEXP_QUOTE;
277                      ctx->state = PARSER_STATE_SKIP;
278                    break;                    break;
279    
280                 default:                 default:
281                    /* Add the character to the buffer */                    /* Add the character to the buffer */
282                    buffer_add_char(buffer,&buf_pos,c);                    if (tmp_token_add_char(ctx,c) == -1) {
283                         ctx->state = PARSER_STATE_SKIP;
284                         ctx->error = PARSER_ERROR_NOMEM;
285                      }
286              }              }
287              break;              break;
288    
# Line 243  int parser_tokenize(char *str,struct par Line 290  int parser_tokenize(char *str,struct par
290              switch(type) {              switch(type) {
291                 case PARSER_CHAR_NEWLINE:                 case PARSER_CHAR_NEWLINE:
292                    /* Unterminated string! */                    /* Unterminated string! */
293                    error = PARSER_ERROR_UNEXP_EOL;                    ctx->error = PARSER_ERROR_UNEXP_EOL;
294                      ctx->state = PARSER_STATE_DONE;
295                    break;                    break;
296    
297                 case PARSER_CHAR_QUOTE:                 case PARSER_CHAR_QUOTE:
298                    if (token_create(&tok_head,&tok_last,buffer) == -1)                    if (!parser_move_tmp_token(ctx)) {
299                       error = PARSER_ERROR_NOMEM;                       ctx->state = PARSER_STATE_BLANK;
300                      } else {
301                    (*tok_count)++;                       ctx->state = PARSER_STATE_SKIP;
302                    state = PARSER_STATE_BLANK;                       ctx->error = PARSER_ERROR_NOMEM;
303                      }
304                    break;                    break;
305    
306                 default:                 default:
307                    /* Add the character to the buffer */                    /* Add the character to the buffer */
308                    buffer_add_char(buffer,&buf_pos,c);                    if (tmp_token_add_char(ctx,c) == -1) {
309                         ctx->state = PARSER_STATE_SKIP;
310                         ctx->error = PARSER_ERROR_NOMEM;
311                      }
312              }              }
313              break;              break;
314        }        }
315     }     }
316    
317     if (error) {     return(ctx->state == PARSER_STATE_DONE);
       parser_free_tokens(tok_head);  
       return(error);  
    }  
   
    *tokens = tok_head;  
    return(0);  
318  }  }
319    
320  /* Parser tests */  /* Parser tests */
# Line 285  static char *parser_test_str[] = { Line 331  static char *parser_test_str[] = {
331    
332  void parser_run_tests(void)  void parser_run_tests(void)
333  {  {
334     struct parser_token *tok_list;     parser_context_t ctx;
335     int i,res,tok_count;     int i,res;
336    
337     for(i=0;parser_test_str[i];i++) {     for(i=0;parser_test_str[i];i++) {
338        res = parser_tokenize(parser_test_str[i],&tok_list,&tok_count);        parser_context_init(&ctx);
339    
340        printf("\n%d: Test string: [%s] => res=%d\n",        res = parser_scan_buffer(&ctx,parser_test_str[i],
341               i,parser_test_str[i],res);                                 strlen(parser_test_str[i])+1);
         
       if (tok_list) {  
          printf("Tokens: ");  
          parser_dump_tokens(tok_list);  
          printf("\n");  
342    
343           parser_free_tokens(tok_list);        printf("\n%d: Test string: [%s] => res=%d, state=%d\n",
344                 i,parser_test_str[i],res,ctx.state);
345          
346          if ((res != 0) && (ctx.error == 0)) {
347             if (ctx.tok_head) {
348                printf("Tokens: ");
349                parser_dump_tokens(&ctx);
350                printf("\n");
351             }
352        }        }
353    
354          parser_context_free(&ctx);
355     }     }
356  }  }

Legend:
Removed from v.1  
changed lines
  Added in v.2

  ViewVC Help
Powered by ViewVC 1.1.26