/[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

Contents of /upstream/dynamips-0.2.5/parser.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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