/[dynamips]/upstream/dynamips-0.2.5/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.5/parser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Sat Oct 6 16:01:44 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 6986 byte(s)
import 0.2.5 from upstream

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     /* Parser states */
31     enum {
32     PARSER_STATE_BLANK,
33     PARSER_STATE_STRING,
34     PARSER_STATE_QUOTED_STRING,
35     };
36    
37     /* Character types */
38     enum {
39     PARSER_CHAR_BLANK,
40     PARSER_CHAR_NEWLINE,
41     PARSER_CHAR_COMMENT,
42     PARSER_CHAR_QUOTE,
43     PARSER_CHAR_OTHER,
44     };
45    
46     /* Get a description given an error code */
47     char *parser_strerror(int error)
48     {
49     printf("error = %d\n",error);
50    
51     switch(error) {
52     case PARSER_ERROR_NOMEM:
53     return "insufficient memory";
54     case PARSER_ERROR_UNEXP_QUOTE:
55     return "unexpected quote";
56     case PARSER_ERROR_UNEXP_EOL:
57     return "unexpected end of line";
58     default:
59     return "unknown error";
60     }
61     }
62    
63     /* Create a new token */
64     static int token_create(parser_token_t **head,parser_token_t **last,
65     char *value)
66     {
67     parser_token_t *t;
68    
69     if (!(t = malloc(sizeof(*t))))
70     return(-1);
71    
72     if (!(t->value = strdup(value))) {
73     free(t);
74     return(-1);
75     }
76    
77     t->next = NULL;
78    
79     if (*last) {
80     (*last)->next = t;
81     *last = t;
82     } else {
83     *head = *last = t;
84     }
85    
86     return(0);
87     }
88    
89     /* Free a token list */
90     void parser_free_tokens(parser_token_t *tok_list)
91     {
92     parser_token_t *t,*next;
93    
94     for(t=tok_list;t;t=next) {
95     next = t->next;
96     free(t->value);
97     free(t);
98     }
99     }
100    
101     /* Dump a token list */
102     void parser_dump_tokens(parser_token_t *tok_list)
103     {
104     parser_token_t *t;
105    
106     for(t=tok_list;t;t=t->next)
107     printf("\"%s\" ",t->value);
108     }
109    
110     /* Map a token list to an array */
111     char **parser_map_array(parser_token_t *tok_list,int tok_count)
112     {
113     char **map;
114     int i;
115    
116     if (tok_count <= 0)
117     return NULL;
118    
119     if (!(map = calloc(tok_count,sizeof(char **))))
120     return NULL;
121    
122     for(i=0;(i<tok_count) && tok_list;i++,tok_list=tok_list->next)
123     map[i] = tok_list->value;
124    
125     return map;
126     }
127    
128     /* Add a character to a buffer */
129     static int buffer_add_char(char *buffer,int *pos,char c)
130     {
131     if (*pos >= TOKEN_MAX_SIZE)
132     return(-1);
133    
134     buffer[(*pos)++] = c;
135     buffer[*pos] = 0;
136     return(0);
137     }
138    
139     /* Tokenize a string */
140     int parser_tokenize(char *str,struct parser_token **tokens,int *tok_count)
141     {
142     char buffer[TOKEN_MAX_SIZE+1];
143     parser_token_t *tok_head,*tok_last;
144     int i,buf_pos,type;
145     int state,error,done;
146     size_t len;
147     char c;
148    
149     len = strlen(str);
150     tok_head = tok_last = NULL;
151     *tokens = NULL;
152     *tok_count = 0;
153     state = PARSER_STATE_BLANK;
154     done = FALSE;
155     error = 0;
156     buf_pos = 0;
157    
158     for(i=0;(i<len+1) && !error && !done;i++)
159     {
160     c = str[i];
161    
162     /* Determine character type */
163     switch(c) {
164     case '\n':
165     case '\r':
166     case 0:
167     type = PARSER_CHAR_NEWLINE;
168     break;
169     case '\t':
170     case ' ':
171     type = PARSER_CHAR_BLANK;
172     break;
173     case '!':
174     case '#':
175     type = PARSER_CHAR_COMMENT;
176     break;
177     case '"':
178     type = PARSER_CHAR_QUOTE;
179     break;
180     default:
181     type = PARSER_CHAR_OTHER;
182     }
183    
184     /* Basic finite state machine */
185     switch(state) {
186     case PARSER_STATE_BLANK:
187     switch(type) {
188     case PARSER_CHAR_BLANK:
189     /* Eat space */
190     break;
191    
192     case PARSER_CHAR_NEWLINE:
193     case PARSER_CHAR_COMMENT:
194     done = TRUE;
195     break;
196    
197     case PARSER_CHAR_QUOTE:
198     state = PARSER_STATE_QUOTED_STRING;
199     buf_pos = 0;
200     break;
201    
202     default:
203     /* Begin a new string */
204     state = PARSER_STATE_STRING;
205     buf_pos = 0;
206     buffer_add_char(buffer,&buf_pos,c);
207     }
208     break;
209    
210     case PARSER_STATE_STRING:
211     switch(type) {
212     case PARSER_CHAR_BLANK:
213     if (token_create(&tok_head,&tok_last,buffer) == -1)
214     error = PARSER_ERROR_NOMEM;
215    
216     (*tok_count)++;
217     state = PARSER_STATE_BLANK;
218     break;
219    
220     case PARSER_CHAR_NEWLINE:
221     if (token_create(&tok_head,&tok_last,buffer) == -1)
222     error = PARSER_ERROR_NOMEM;
223    
224     (*tok_count)++;
225     done = TRUE;
226     break;
227    
228     case PARSER_CHAR_COMMENT:
229     done = TRUE;
230     break;
231    
232     case PARSER_CHAR_QUOTE:
233     error = PARSER_ERROR_UNEXP_QUOTE;
234     break;
235    
236     default:
237     /* Add the character to the buffer */
238     buffer_add_char(buffer,&buf_pos,c);
239     }
240     break;
241    
242     case PARSER_STATE_QUOTED_STRING:
243     switch(type) {
244     case PARSER_CHAR_NEWLINE:
245     /* Unterminated string! */
246     error = PARSER_ERROR_UNEXP_EOL;
247     break;
248    
249     case PARSER_CHAR_QUOTE:
250     if (token_create(&tok_head,&tok_last,buffer) == -1)
251     error = PARSER_ERROR_NOMEM;
252    
253     (*tok_count)++;
254     state = PARSER_STATE_BLANK;
255     break;
256    
257     default:
258     /* Add the character to the buffer */
259     buffer_add_char(buffer,&buf_pos,c);
260     }
261     break;
262     }
263     }
264    
265     if (error) {
266     parser_free_tokens(tok_head);
267     return(error);
268     }
269    
270     *tokens = tok_head;
271     return(0);
272     }
273    
274     /* Parser tests */
275     static char *parser_test_str[] = {
276     "c7200 show_hardware R1",
277     "c7200 show_hardware \"R1\"",
278     " c7200 show_hardware \"R1\" ",
279     "\"c7200\" \"show_hardware\" \"R1\"",
280     "hypervisor set_working_dir \"C:\\Program Files\\Dynamips Test\"",
281     "hypervisor # This is a comment set_working_dir \"C:\\Program Files\"",
282     "\"c7200\" \"show_hardware\" \"R1",
283     NULL,
284     };
285    
286     void parser_run_tests(void)
287     {
288     struct parser_token *tok_list;
289     int i,res,tok_count;
290    
291     for(i=0;parser_test_str[i];i++) {
292     res = parser_tokenize(parser_test_str[i],&tok_list,&tok_count);
293    
294     printf("\n%d: Test string: [%s] => res=%d\n",
295     i,parser_test_str[i],res);
296    
297     if (tok_list) {
298     printf("Tokens: ");
299     parser_dump_tokens(tok_list);
300     printf("\n");
301    
302     parser_free_tokens(tok_list);
303     }
304     }
305     }

  ViewVC Help
Powered by ViewVC 1.1.26