/[dynamips]/upstream/dynamips-0.2.6-RC3/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

Annotation of /upstream/dynamips-0.2.6-RC3/parser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (hide annotations)
Sat Oct 6 16:05:34 2007 UTC (14 years, 10 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC2/parser.c
File MIME type: text/plain
File size: 8855 byte(s)
dynamips-0.2.6-RC2

1 dpavlin 1 /*
2     * Cisco 7200 (Predator) simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Mini-parser.
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <unistd.h>
11     #include <string.h>
12     #include <sys/types.h>
13     #include <sys/stat.h>
14     #include <sys/mman.h>
15     #include <signal.h>
16     #include <fcntl.h>
17     #include <errno.h>
18     #include <assert.h>
19     #include <stdarg.h>
20     #include <sys/ioctl.h>
21     #include <sys/types.h>
22     #include <sys/socket.h>
23     #include <arpa/inet.h>
24    
25     #include "utils.h"
26     #include "parser.h"
27    
28     #define TOKEN_MAX_SIZE 512
29    
30     /* Character types */
31     enum {
32     PARSER_CHAR_BLANK,
33     PARSER_CHAR_NEWLINE,
34     PARSER_CHAR_COMMENT,
35     PARSER_CHAR_QUOTE,
36     PARSER_CHAR_OTHER,
37     };
38    
39     /* Get a description given an error code */
40 dpavlin 2 char *parser_strerror(parser_context_t *ctx)
41 dpavlin 1 {
42 dpavlin 2 printf("error = %d\n",ctx->error);
43 dpavlin 1
44 dpavlin 2 switch(ctx->error) {
45     case 0:
46     return "no error";
47 dpavlin 1 case PARSER_ERROR_NOMEM:
48     return "insufficient memory";
49     case PARSER_ERROR_UNEXP_QUOTE:
50     return "unexpected quote";
51     case PARSER_ERROR_UNEXP_EOL:
52     return "unexpected end of line";
53     default:
54     return "unknown error";
55     }
56     }
57    
58 dpavlin 2 /* Dump a token list */
59     void parser_dump_tokens(parser_context_t *ctx)
60 dpavlin 1 {
61 dpavlin 2 parser_token_t *tok;
62 dpavlin 1
63 dpavlin 2 for(tok=ctx->tok_head;tok;tok=tok->next)
64     printf("\"%s\" ",tok->value);
65     }
66 dpavlin 1
67 dpavlin 2 /* Map a token list to an array */
68     char **parser_map_array(parser_context_t *ctx)
69     {
70     parser_token_t *tok;
71     char **map;
72     int i;
73 dpavlin 1
74 dpavlin 2 if (ctx->tok_count <= 0)
75     return NULL;
76 dpavlin 1
77 dpavlin 2 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     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 (!new_str)
97     return(-1);
98    
99     ctx->tmp_tok = new_str;
100     ctx->tmp_tot_len = new_size;
101 dpavlin 1 }
102    
103 dpavlin 2 ctx->tmp_tok[ctx->tmp_cur_len++] = c;
104     ctx->tmp_tok[ctx->tmp_cur_len] = 0;
105 dpavlin 1 return(0);
106     }
107    
108 dpavlin 2 /* 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);
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 dpavlin 1 /* Free a token list */
154     void parser_free_tokens(parser_token_t *tok_list)
155     {
156     parser_token_t *t,*next;
157 dpavlin 2
158 dpavlin 1 for(t=tok_list;t;t=next) {
159     next = t->next;
160     free(t->value);
161     free(t);
162     }
163     }
164    
165 dpavlin 2 /* Free memory used by a parser context */
166     void parser_context_free(parser_context_t *ctx)
167 dpavlin 1 {
168 dpavlin 2 parser_free_tokens(ctx->tok_head);
169 dpavlin 1
170 dpavlin 2 if (ctx->tmp_tok != NULL)
171     free(ctx->tmp_tok);
172 dpavlin 1
173 dpavlin 2 parser_context_init(ctx);
174 dpavlin 1 }
175    
176 dpavlin 2 /* Determine the type of the input character */
177     static int parser_get_char_type(u_char c)
178 dpavlin 1 {
179 dpavlin 2 switch(c) {
180     case '\n':
181     case '\r':
182     case 0:
183     return(PARSER_CHAR_NEWLINE);
184     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 dpavlin 1 }
197    
198 dpavlin 2 /* Send a buffer to the tokenizer */
199     int parser_scan_buffer(parser_context_t *ctx,u_char *buf,size_t buf_size)
200 dpavlin 1 {
201 dpavlin 2 int i,type;
202     u_char c;
203 dpavlin 1
204 dpavlin 2 for(i=0;(i<buf_size) && (ctx->state != PARSER_STATE_DONE);i++)
205 dpavlin 1 {
206 dpavlin 2 ctx->consumed_len++;
207     c = buf[i];
208 dpavlin 1
209     /* Determine character type */
210 dpavlin 2 type = parser_get_char_type(c);
211    
212     /* Basic finite state machine */
213     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 dpavlin 1 break;
220    
221     case PARSER_STATE_BLANK:
222     switch(type) {
223     case PARSER_CHAR_BLANK:
224     /* Eat space */
225     break;
226    
227     case PARSER_CHAR_COMMENT:
228 dpavlin 2 ctx->state = PARSER_STATE_SKIP;
229 dpavlin 1 break;
230    
231 dpavlin 2 case PARSER_CHAR_NEWLINE:
232     ctx->state = PARSER_STATE_DONE;
233     break;
234    
235 dpavlin 1 case PARSER_CHAR_QUOTE:
236 dpavlin 2 ctx->state = PARSER_STATE_QUOTED_STRING;
237 dpavlin 1 break;
238    
239     default:
240     /* Begin a new string */
241 dpavlin 2 if (!tmp_token_add_char(ctx,c)) {
242     ctx->state = PARSER_STATE_STRING;
243     } else {
244     ctx->state = PARSER_STATE_SKIP;
245     ctx->error = PARSER_ERROR_NOMEM;
246     }
247 dpavlin 1 }
248     break;
249    
250     case PARSER_STATE_STRING:
251     switch(type) {
252     case PARSER_CHAR_BLANK:
253 dpavlin 2 if (!parser_move_tmp_token(ctx)) {
254     ctx->state = PARSER_STATE_BLANK;
255     } else {
256     ctx->state = PARSER_STATE_SKIP;
257     ctx->error = PARSER_ERROR_NOMEM;
258     }
259 dpavlin 1 break;
260    
261     case PARSER_CHAR_NEWLINE:
262 dpavlin 2 if (parser_move_tmp_token(ctx) == -1)
263     ctx->error = PARSER_ERROR_NOMEM;
264 dpavlin 1
265 dpavlin 2 ctx->state = PARSER_STATE_DONE;
266 dpavlin 1 break;
267    
268     case PARSER_CHAR_COMMENT:
269 dpavlin 2 if (parser_move_tmp_token(ctx) == -1)
270     ctx->error = PARSER_ERROR_NOMEM;
271    
272     ctx->state = PARSER_STATE_SKIP;
273 dpavlin 1 break;
274    
275     case PARSER_CHAR_QUOTE:
276 dpavlin 2 ctx->error = PARSER_ERROR_UNEXP_QUOTE;
277     ctx->state = PARSER_STATE_SKIP;
278 dpavlin 1 break;
279    
280     default:
281     /* Add the character to the buffer */
282 dpavlin 2 if (tmp_token_add_char(ctx,c) == -1) {
283     ctx->state = PARSER_STATE_SKIP;
284     ctx->error = PARSER_ERROR_NOMEM;
285     }
286 dpavlin 1 }
287     break;
288    
289     case PARSER_STATE_QUOTED_STRING:
290     switch(type) {
291     case PARSER_CHAR_NEWLINE:
292     /* Unterminated string! */
293 dpavlin 2 ctx->error = PARSER_ERROR_UNEXP_EOL;
294     ctx->state = PARSER_STATE_DONE;
295 dpavlin 1 break;
296    
297     case PARSER_CHAR_QUOTE:
298 dpavlin 2 if (!parser_move_tmp_token(ctx)) {
299     ctx->state = PARSER_STATE_BLANK;
300     } else {
301     ctx->state = PARSER_STATE_SKIP;
302     ctx->error = PARSER_ERROR_NOMEM;
303     }
304 dpavlin 1 break;
305    
306     default:
307     /* Add the character to the buffer */
308 dpavlin 2 if (tmp_token_add_char(ctx,c) == -1) {
309     ctx->state = PARSER_STATE_SKIP;
310     ctx->error = PARSER_ERROR_NOMEM;
311     }
312 dpavlin 1 }
313     break;
314     }
315     }
316    
317 dpavlin 2 return(ctx->state == PARSER_STATE_DONE);
318 dpavlin 1 }
319    
320     /* Parser tests */
321     static char *parser_test_str[] = {
322     "c7200 show_hardware R1",
323     "c7200 show_hardware \"R1\"",
324     " c7200 show_hardware \"R1\" ",
325     "\"c7200\" \"show_hardware\" \"R1\"",
326     "hypervisor set_working_dir \"C:\\Program Files\\Dynamips Test\"",
327     "hypervisor # This is a comment set_working_dir \"C:\\Program Files\"",
328     "\"c7200\" \"show_hardware\" \"R1",
329     NULL,
330     };
331    
332     void parser_run_tests(void)
333     {
334 dpavlin 2 parser_context_t ctx;
335     int i,res;
336 dpavlin 1
337     for(i=0;parser_test_str[i];i++) {
338 dpavlin 2 parser_context_init(&ctx);
339 dpavlin 1
340 dpavlin 2 res = parser_scan_buffer(&ctx,parser_test_str[i],
341     strlen(parser_test_str[i])+1);
342    
343     printf("\n%d: Test string: [%s] => res=%d, state=%d\n",
344     i,parser_test_str[i],res,ctx.state);
345 dpavlin 1
346 dpavlin 2 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 dpavlin 1
354 dpavlin 2 parser_context_free(&ctx);
355 dpavlin 1 }
356     }

  ViewVC Help
Powered by ViewVC 1.1.26