]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Other/Maintained/Tools/Pccts/sorcerer/lib/astlib.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Other / Maintained / Tools / Pccts / sorcerer / lib / astlib.c
CommitLineData
3eb9473e 1/*\r
2 * astlib.c\r
3 *\r
4 * SOFTWARE RIGHTS\r
5 *\r
6 * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public\r
7 * domain. An individual or company may do whatever they wish with\r
8 * source code distributed with SORCERER or the code generated by\r
9 * SORCERER, including the incorporation of SORCERER, or its output, into\r
10 * commerical software.\r
11 *\r
12 * We encourage users to develop software with SORCERER. However, we do\r
13 * ask that credit is given to us for developing SORCERER. By "credit",\r
14 * we mean that if you incorporate our source code into one of your\r
15 * programs (commercial product, research project, or otherwise) that you\r
16 * acknowledge this fact somewhere in the documentation, research report,\r
17 * etc... If you like SORCERER and have developed a nice tool with the\r
18 * output, please mention that you developed it using SORCERER. In\r
19 * addition, we ask that this header remain intact in our source code.\r
20 * As long as these guidelines are kept, we expect to continue enhancing\r
21 * this system and expect to make other tools available as they are\r
22 * completed.\r
23 *\r
24 * SORCERER 1.00B\r
25 * Terence Parr\r
26 * AHPCRC, University of Minnesota\r
27 * 1992-1994\r
28 */\r
29\r
30#include <stdio.h>\r
31#include "pcctscfg.h"\r
32#include <ctype.h>\r
33\r
34#define SORCERER_TRANSFORM\r
35\r
36#include "CASTBase.h"\r
37#include "astlib.h"\r
38\r
39#ifdef PCCTS_USE_STDARG\r
40#include <stdarg.h>\r
41#else\r
42#include <varargs.h>\r
43#endif\r
44\r
45 /* String Scanning/Parsing Stuff */\r
46\r
47#define StringScanMaxText 50\r
48\r
49typedef struct stringlexer {\r
50#ifdef __USE_PROTOS\r
51 signed int c;\r
52#else\r
53 int c;\r
54#endif\r
55 char *input;\r
56 char *p;\r
57 char text[StringScanMaxText];\r
58 } StringLexer;\r
59\r
60#define LPAREN 1\r
61#define RPAREN 2\r
62#define PERCENT 3\r
63#define INT 4\r
64#define COLON 5\r
65#define POUND 6\r
66#define PERIOD 7\r
67#define StringScanEOF -1\r
68#define VALID_SCAN_TOKEN(t) (t>=LPAREN && t<=PERIOD)\r
69\r
70static char *scan_token_tbl[] = {\r
71 "invalid", /* 0 */\r
72 "LPAREN", /* 1 */\r
73 "RPAREN", /* 2 */\r
74 "PERCENT", /* 3 */\r
75 "INT", /* 4 */\r
76 "COLON", /* 5 */\r
77 "POUND", /* 6 */\r
78 "PERIOD", /* 7 */\r
79};\r
80\r
81char *\r
82#ifdef __USE_PROTOS\r
83scan_token_str(int t)\r
84#else\r
85scan_token_str(t)\r
86int t;\r
87#endif\r
88{\r
89 if ( VALID_SCAN_TOKEN(t) ) return scan_token_tbl[t];\r
90 else if ( t==StringScanEOF ) return "<end-of-string>";\r
91 else return "<invalid-token>";\r
92}\r
93\r
94typedef struct stringparser {\r
95 int token;\r
96 StringLexer *lexer;\r
97 int num_labels;\r
98 } StringParser;\r
99\r
100 /* This type ONLY USED by ast_scan() */\r
101\r
102typedef struct _scanast {\r
103 struct _scanast *right, *down;\r
104 int token;\r
105 int label_num;\r
106 } ScanAST;\r
107\r
108#ifdef __USE_PROTOS\r
109static void stringlexer_init(StringLexer *scanner, char *input);\r
110static void stringparser_init(StringParser *, StringLexer *);\r
111static ScanAST *stringparser_parse_scanast(char *templ, int *n);\r
112static ScanAST *stringparser_parse_tree(StringParser *parser);\r
113static ScanAST *stringparser_parse_element(StringParser *parser);\r
114static void stringscan_advance(StringLexer *scanner);\r
115static int stringscan_gettok(StringLexer *scanner);\r
116#else\r
117static void stringlexer_init();\r
118static void stringparser_init();\r
119static ScanAST *stringparser_parse_scanast();\r
120static ScanAST *stringparser_parse_tree();\r
121static ScanAST *stringparser_parse_element();\r
122static void stringscan_advance();\r
123static int stringscan_gettok();\r
124#endif\r
125\r
126/* build a tree (root child1 child2 ... NULL)\r
127 * If root is NULL, simply make the children siblings and return ptr\r
128 * to 1st sibling (child1). If root is not single node, return NULL.\r
129 *\r
130 * Siblings that are actually sibling lists themselves are handled\r
131 * correctly. For example #( NULL, #( NULL, A, B, C), D) results\r
132 * in the tree ( NULL A B C D ).\r
133 *\r
134 * Requires at least two parameters with the last one being NULL. If\r
135 * both are NULL, return NULL.\r
136 *\r
137 * The ast_down and ast_right down/right pointers are used to make the tree.\r
138 */\r
139SORAST *\r
140#ifdef PCCTS_USE_STDARG\r
141ast_make(SORAST *rt, ...)\r
142#else\r
143ast_make(va_alist)\r
144va_dcl\r
145#endif\r
146{\r
147 va_list ap;\r
148 register SORAST *child, *sibling=NULL, *tail = NULL, *w;\r
149 SORAST *root;\r
150\r
151#ifdef PCCTS_USE_STDARG\r
152 va_start(ap, rt);\r
153 root = rt;\r
154#else\r
155 va_start(ap);\r
156 root = va_arg(ap, SORAST *);\r
157#endif\r
158\r
159 if ( root != NULL )\r
160 if ( root->ast_down != NULL ) return NULL;\r
161 child = va_arg(ap, SORAST *);\r
162 while ( child != NULL )\r
163 {\r
164 /* find end of child */\r
165 for (w=child; w->ast_right!=NULL; w=w->ast_right) {;}\r
166 if ( sibling == NULL ) {sibling = child; tail = w;}\r
167 else {tail->ast_right = child; tail = w;}\r
168 child = va_arg(ap, SORAST *);\r
169 }\r
170 if ( root==NULL ) root = sibling;\r
171 else root->ast_down = sibling;\r
172 va_end(ap);\r
173 return root;\r
174}\r
175\r
176/* The following push and pop routines are only used by ast_find_all() */\r
177\r
178static void\r
179#ifdef __USE_PROTOS\r
180_push(SORAST **st, int *sp, SORAST *e)\r
181#else\r
182_push(st, sp, e)\r
183SORAST **st;\r
184int *sp;\r
185SORAST *e;\r
186#endif\r
187{\r
188 (*sp)--;\r
189 require((*sp)>=0, "stack overflow");\r
190 st[(*sp)] = e;\r
191}\r
192\r
193static SORAST *\r
194#ifdef __USE_PROTOS\r
195_pop(SORAST **st, int *sp)\r
196#else\r
197_pop(st, sp)\r
198SORAST **st;\r
199int *sp;\r
200#endif\r
201{\r
202 SORAST *e = st[*sp];\r
203 (*sp)++;\r
204 require((*sp)<=MaxTreeStackDepth, "stack underflow");\r
205 return e;\r
206}\r
207\r
208/* Is 'u' a subtree of 't' beginning at the root? */\r
209int\r
210#ifdef __USE_PROTOS\r
211ast_match_partial(SORAST *t, SORAST *u)\r
212#else\r
213ast_match_partial(t, u)\r
214SORAST *t, *u;\r
215#endif\r
216{\r
217 SORAST *sib;\r
218\r
219 if ( u==NULL ) return 1;\r
220 if ( t==NULL ) if ( u!=NULL ) return 0; else return 1;\r
221\r
222 for (sib=t; sib!=NULL&&u!=NULL; sib=sib->ast_right, u=u->ast_right)\r
223 {\r
224 if ( sib->token != u->token ) return 0;\r
225 if ( sib->ast_down!=NULL )\r
226 if ( !ast_match_partial(sib->ast_down, u->ast_down) ) return 0;\r
227 }\r
228 return 1;\r
229}\r
230\r
231/* Find all occurrences of u in t.\r
232 * 'cursor' must be initialized to 't'. It eventually\r
233 * returns NULL when no more occurrences of 'u' are found.\r
234 */\r
235SORAST *\r
236#ifdef __USE_PROTOS\r
237ast_find_all(SORAST *t, SORAST *u, SORAST **cursor)\r
238#else\r
239ast_find_all(t, u, cursor)\r
240SORAST *t, *u, **cursor;\r
241#endif\r
242{\r
243 SORAST *sib;\r
244 static SORAST *template_stack[MaxTreeStackDepth];\r
245 static int tsp = MaxTreeStackDepth;\r
246\r
247 if ( *cursor == NULL ) return NULL;\r
248 if ( *cursor!=t ) sib = *cursor;\r
249 else {\r
250 /* else, first time--start at top of template 't' */\r
251 tsp = MaxTreeStackDepth;\r
252 sib = t;\r
253 /* bottom of stack is always a NULL--"cookie" indicates "done" */\r
254 _push(template_stack, &tsp, NULL);\r
255 }\r
256\r
257keep_looking:\r
258 if ( sib==NULL ) /* hit end of sibling list */\r
259 {\r
260 sib = _pop(template_stack, &tsp);\r
261 if ( sib == NULL ) { *cursor = NULL; return NULL; }\r
262 }\r
263\r
264 if ( sib->token != u->token )\r
265 {\r
266 /* look for another match */\r
267 if ( sib->ast_down!=NULL )\r
268 {\r
269 if ( sib->ast_right!=NULL ) _push(template_stack, &tsp, sib->ast_right);\r
270 sib=sib->ast_down;\r
271 goto keep_looking;\r
272 }\r
273 /* nothing below to try, try next sibling */\r
274 sib=sib->ast_right;\r
275 goto keep_looking;\r
276 }\r
277\r
278 /* found a matching root node, try to match what's below */\r
279 if ( ast_match_partial(sib, u) )\r
280 {\r
281 /* record sibling cursor so we can pick up next from there */\r
282 if ( sib->ast_down!=NULL )\r
283 {\r
284 if ( sib->ast_right!=NULL ) _push(template_stack, &tsp, sib->ast_right);\r
285 *cursor = sib->ast_down;\r
286 }\r
287 else if ( sib->ast_right!=NULL ) *cursor = sib->ast_right;\r
288 else *cursor = _pop(template_stack, &tsp);\r
289 return sib;\r
290 }\r
291\r
292 /* no match, keep searching */\r
293 if ( sib->ast_down!=NULL )\r
294 {\r
295 if ( sib->ast_right!=NULL ) _push(template_stack, &tsp, sib->ast_right);\r
296 sib=sib->ast_down;\r
297 }\r
298 else sib = sib->ast_right; /* else, try to right if zip below */\r
299 goto keep_looking;\r
300}\r
301\r
302/* are two trees exactly alike? */\r
303int\r
304#ifdef __USE_PROTOS\r
305ast_match(SORAST *t, SORAST *u)\r
306#else\r
307ast_match(t, u)\r
308SORAST *t, *u;\r
309#endif\r
310{\r
311 SORAST *sib;\r
312\r
313 if ( t==NULL ) if ( u!=NULL ) return 0; else return 1;\r
314 if ( u==NULL ) return 0;\r
315\r
316 for (sib=t; sib!=NULL&&u!=NULL; sib=sib->ast_right, u=u->ast_right)\r
317 {\r
318 if ( sib->token != u->token ) return 0;\r
319 if ( sib->ast_down!=NULL )\r
320 if ( !ast_match(sib->ast_down, u->ast_down) ) return 0;\r
321 }\r
322 return 1;\r
323}\r
324\r
325static int\r
326#ifdef __USE_PROTOS\r
327ast_scanmatch(ScanAST *t, SORAST *u, SORAST **labels[], int *n)\r
328#else\r
329ast_scanmatch(t, u, labels, n)\r
330ScanAST *t;\r
331SORAST *u;\r
332SORAST **labels[];\r
333int *n;\r
334#endif\r
335{\r
336 ScanAST *sib;\r
337\r
338 if ( t==NULL ) if ( u!=NULL ) return 0; else return 1;\r
339 if ( u==NULL ) return 0;\r
340\r
341 for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right, u=u->ast_right)\r
342 {\r
343 /* make sure tokens match; token of '0' means wildcard match */\r
344 if ( sib->token != u->token && sib->token!=0 ) return 0;\r
345 /* we have a matched token here; set label pointers if exists */\r
346 if ( sib->label_num>0 )\r
347 {\r
348 require(labels!=NULL, "label found in template, but no array of labels");\r
349 (*n)++;\r
350 *(labels[sib->label_num-1]) = u;\r
351 }\r
352 /* match what's below if something there and current node is not wildcard */\r
353 if ( sib->down!=NULL && sib->token!=0 )\r
354 if ( !ast_scanmatch(sib->down, u->ast_down, labels, n) ) return 0;\r
355 }\r
356 return 1;\r
357}\r
358\r
359void\r
360#ifdef __USE_PROTOS\r
361ast_insert_after(SORAST *a, SORAST *b)\r
362#else\r
363ast_insert_after(a, b)\r
364SORAST *a,*b;\r
365#endif\r
366{\r
367 SORAST *end;\r
368 require(a!=NULL, "ast_insert_after: NULL input tree");\r
369 if ( b==NULL ) return;\r
370 /* find end of b's child list */\r
371 for (end=b; end->ast_right!=NULL; end=end->ast_right) {;}\r
372 end->ast_right = a->ast_right;\r
373 a->ast_right = b;\r
374}\r
375\r
376void\r
377#ifdef __USE_PROTOS\r
378ast_append(SORAST *a, SORAST *b)\r
379#else\r
380ast_append(a, b)\r
381SORAST *a,*b;\r
382#endif\r
383{\r
384 SORAST *end;\r
385 require(a!=NULL&&b!=NULL, "ast_append: NULL input tree");\r
386 /* find end of child list */\r
387 for (end=a; end->ast_right!=NULL; end=end->ast_right) {;}\r
388 end->ast_right = b;\r
389}\r
390\r
391SORAST *\r
392#ifdef __USE_PROTOS\r
393ast_tail(SORAST *a)\r
394#else\r
395ast_tail(a)\r
396SORAST *a;\r
397#endif\r
398{\r
399 SORAST *end;\r
400 require(a!=NULL, "ast_tail: NULL input tree");\r
401 /* find end of child list */\r
402 for (end=a; end->ast_right!=NULL; end=end->ast_right) {;}\r
403 return end;\r
404}\r
405\r
406SORAST *\r
407#ifdef __USE_PROTOS\r
408ast_bottom(SORAST *a)\r
409#else\r
410ast_bottom(a)\r
411SORAST *a;\r
412#endif\r
413{\r
414 SORAST *end;\r
415 require(a!=NULL, "ast_bottom: NULL input tree");\r
416 /* find end of child list */\r
417 for (end=a; end->ast_down!=NULL; end=end->ast_down) {;}\r
418 return end;\r
419}\r
420\r
421SORAST *\r
422#ifdef __USE_PROTOS\r
423ast_cut_between(SORAST *a, SORAST *b)\r
424#else\r
425ast_cut_between(a, b)\r
426SORAST *a,*b;\r
427#endif\r
428{\r
429 SORAST *end, *ret;\r
430 require(a!=NULL&&b!=NULL, "ast_cut_between: NULL input tree");\r
431 /* find node pointing to b */\r
432 for (end=a; end->ast_right!=NULL&&end->ast_right!=b; end=end->ast_right)\r
433 {;}\r
434 require(end->ast_right!=NULL, "ast_cut_between: a,b not connected");\r
435 end->ast_right = NULL; /* don't want it point to 'b' anymore */\r
436 ret = a->ast_right;\r
437 a->ast_right = b;\r
438 return ret;\r
439}\r
440\r
441SList *\r
442#ifdef __USE_PROTOS\r
443ast_to_slist(SORAST *t)\r
444#else\r
445ast_to_slist(t)\r
446SORAST *t;\r
447#endif\r
448{\r
449 SList *list=NULL;\r
450 SORAST *p;\r
451\r
452 for (p=t; p!=NULL; p=p->ast_right)\r
453 {\r
454 slist_add(&list, p);\r
455 }\r
456 return list;\r
457}\r
458\r
459SORAST *\r
460#ifdef __USE_PROTOS\r
461slist_to_ast(SList *list)\r
462#else\r
463slist_to_ast(list)\r
464SList *list;\r
465#endif\r
466{\r
467 SORAST *t=NULL, *last=NULL;\r
468 SList *p;\r
469\r
470 for (p = list->next; p!=NULL; p=p->next)\r
471 {\r
472 SORAST *u = (SORAST *)p->elem;\r
473 if ( last==NULL ) last = t = u;\r
474 else { last->ast_right = u; last = u; }\r
475 }\r
476 return t;\r
477}\r
478\r
479void\r
480#ifdef __USE_PROTOS\r
481ast_free(SORAST *t)\r
482#else\r
483ast_free(t)\r
484SORAST *t;\r
485#endif\r
486{\r
487 if ( t == NULL ) return;\r
488 ast_free( t->ast_down );\r
489 ast_free( t->ast_right );\r
490 free( t );\r
491}\r
492\r
493int\r
494#ifdef __USE_PROTOS\r
495ast_nsiblings(SORAST *t)\r
496#else\r
497ast_nsiblings(t)\r
498SORAST *t;\r
499#endif\r
500{\r
501 int n=0;\r
502\r
503 while ( t!=NULL )\r
504 {\r
505 n++;\r
506 t = t->ast_right;\r
507 }\r
508 return n;\r
509}\r
510\r
511SORAST *\r
512#ifdef __USE_PROTOS\r
513ast_sibling_index(SORAST *t, int i)\r
514#else\r
515ast_sibling_index(t,i)\r
516SORAST *t;\r
517int i;\r
518#endif\r
519{\r
520 int j=1;\r
521 require(i>0, "ast_sibling_index: i<=0");\r
522\r
523 while ( t!=NULL )\r
524 {\r
525 if ( j==i ) return t;\r
526 j++;\r
527 t = t->ast_right;\r
528 }\r
529 return NULL;\r
530}\r
531\r
532static void\r
533#ifdef __USE_PROTOS\r
534scanast_free(ScanAST *t)\r
535#else\r
536scanast_free(t)\r
537ScanAST *t;\r
538#endif\r
539{\r
540 if ( t == NULL ) return;\r
541 scanast_free( t->down );\r
542 scanast_free( t->right );\r
543 free( t );\r
544}\r
545\r
546/*\r
547 * ast_scan\r
548 *\r
549 * This function is like scanf(): it attempts to match a template\r
550 * against an input tree. A variable number of tree pointers\r
551 * may be set according to the '%i' labels in the template string.\r
552 * For example:\r
553 *\r
554 * ast_scan("#( 6 #(5 %1:4 %2:3) #(1 %3:3 %4:3) )",\r
555 * t, &w, &x, &y, &z);\r
556 *\r
557 * Naturally, you'd want this converted from\r
558 *\r
559 * ast_scan("#( RangeOp #(Minus %1:IConst %2:Var) #(Plus %3:Var %4Var) )",\r
560 * t, &w, &x, &y, &z);\r
561 *\r
562 * by SORCERER.\r
563 *\r
564 * This function call must be done withing a SORCERER file because SORCERER\r
565 * must convert the token references to the associated token number.\r
566 *\r
567 * This functions parses the template and creates trees which are then\r
568 * matched against the input tree. The labels are set as they are\r
569 * encountered; hence, partial matches may leave some pointers set\r
570 * and some NULL. This routines initializes all argument pointers to NULL\r
571 * at the beginning.\r
572 *\r
573 * This function returns the number of labels matched.\r
574 */\r
575int\r
576#ifdef PCCTS_USE_STDARG\r
577ast_scan(char *templ, SORAST *tree, ...)\r
578#else\r
579ast_scan(va_alist)\r
580va_dcl\r
581#endif\r
582{\r
583 va_list ap;\r
584 ScanAST *t;\r
585 int n, i, found=0;\r
586 SORAST ***label_ptrs=NULL;\r
587\r
588#ifdef PCCTS_USE_STDARG\r
589 va_start(ap, tree);\r
590#else\r
591 char *templ;\r
592 SORAST *tree;\r
593\r
594 va_start(ap);\r
595 templ = va_arg(ap, char *);\r
596 tree = va_arg(ap, SORAST *);\r
597#endif\r
598\r
599 /* make a ScanAST tree out of the template */\r
600 t = stringparser_parse_scanast(templ, &n);\r
601\r
602 /* make an array out of the labels */\r
603 if ( n>0 )\r
604 {\r
605 label_ptrs = (SORAST ***) calloc(n, sizeof(SORAST **));\r
606 require(label_ptrs!=NULL, "ast_scan: out of memory");\r
607 for (i=1; i<=n; i++)\r
608 {\r
609 label_ptrs[i-1] = va_arg(ap, SORAST **);\r
610 *(label_ptrs[i-1]) = NULL;\r
611 }\r
612 }\r
613\r
614 /* match the input tree against the template */\r
615 ast_scanmatch(t, tree, label_ptrs, &found);\r
616\r
617 scanast_free(t);\r
618 free(label_ptrs);\r
619\r
620 return found;\r
621}\r
622\r
623static ScanAST *\r
624#ifdef __USE_PROTOS\r
625new_scanast(int tok)\r
626#else\r
627new_scanast(tok)\r
628int tok;\r
629#endif\r
630{\r
631 ScanAST *p = (ScanAST *) calloc(1, sizeof(ScanAST));\r
632 if ( p == NULL ) {fprintf(stderr, "out of mem\n"); exit(-1);}\r
633 p->token = tok;\r
634 return p;\r
635}\r
636\r
637static ScanAST *\r
638#ifdef __USE_PROTOS\r
639stringparser_parse_scanast(char *templ, int *num_labels)\r
640#else\r
641stringparser_parse_scanast(templ, num_labels)\r
642char *templ;\r
643int *num_labels;\r
644#endif\r
645{\r
646 StringLexer lex;\r
647 StringParser parser;\r
648 ScanAST *t;\r
649\r
650 stringlexer_init(&lex, templ);\r
651 stringparser_init(&parser, &lex);\r
652 t = stringparser_parse_tree(&parser);\r
653 *num_labels = parser.num_labels;\r
654 return t;\r
655}\r
656\r
657static void\r
658#ifdef __USE_PROTOS\r
659stringparser_match(StringParser *parser, int token)\r
660#else\r
661stringparser_match(parser, token)\r
662StringParser *parser;\r
663int token;\r
664#endif\r
665{\r
666 if ( parser->token != token ) sorcerer_panic("bad tree in ast_scan()");\r
667}\r
668\r
669/*\r
670 * Match a tree of the form:\r
671 * (root child1 child2 ... childn)\r
672 * or,\r
673 * node\r
674 *\r
675 * where the elements are integers or labeled integers.\r
676 */\r
677static ScanAST *\r
678#ifdef __USE_PROTOS\r
679stringparser_parse_tree(StringParser *parser)\r
680#else\r
681stringparser_parse_tree(parser)\r
682StringParser *parser;\r
683#endif\r
684{\r
685 ScanAST *t=NULL, *root, *child, *last = NULL;\r
686\r
687 if ( parser->token != POUND )\r
688 {\r
689 return stringparser_parse_element(parser);\r
690 }\r
691 stringparser_match(parser,POUND);\r
692 parser->token = stringscan_gettok(parser->lexer);\r
693 stringparser_match(parser,LPAREN);\r
694 parser->token = stringscan_gettok(parser->lexer);\r
695 root = stringparser_parse_element(parser);\r
696 while ( parser->token != RPAREN )\r
697 {\r
698 child = stringparser_parse_element(parser);\r
699 if ( t==NULL ) { t = child; last = t; }\r
700 else { last->right = child; last = child; }\r
701 }\r
702 stringparser_match(parser,RPAREN);\r
703 parser->token = stringscan_gettok(parser->lexer);\r
704 root->down = t;\r
705 return root;\r
706}\r
707\r
708static ScanAST *\r
709#ifdef __USE_PROTOS\r
710stringparser_parse_element(StringParser *parser)\r
711#else\r
712stringparser_parse_element(parser)\r
713StringParser *parser;\r
714#endif\r
715{\r
716 static char ebuf[100];\r
717 int label = 0;\r
718\r
719 if ( parser->token == POUND )\r
720 {\r
721 return stringparser_parse_tree(parser);\r
722 }\r
723 if ( parser->token == PERCENT )\r
724 {\r
725 parser->token = stringscan_gettok(parser->lexer);\r
726 stringparser_match(parser,INT);\r
727 label = atoi(parser->lexer->text);\r
728 parser->num_labels++;\r
729 if ( label==0 ) sorcerer_panic("%%0 is an invalid label");\r
730 parser->token = stringscan_gettok(parser->lexer);\r
731 stringparser_match(parser,COLON);\r
732 parser->token = stringscan_gettok(parser->lexer);\r
733 /* can label tokens and wildcards */\r
734 if ( parser->token != INT && parser->token != PERIOD )\r
735 sorcerer_panic("can only label tokens");\r
736 }\r
737 if ( parser->token == INT )\r
738 {\r
739 ScanAST *p = new_scanast(atoi(parser->lexer->text));\r
740 parser->token = stringscan_gettok(parser->lexer);\r
741 p->label_num = label;\r
742 return p;\r
743 }\r
744 if ( parser->token == PERIOD )\r
745 {\r
746 ScanAST *p = new_scanast(0); /* token of 0 is wildcard */\r
747 parser->token = stringscan_gettok(parser->lexer);\r
748 p->label_num = label;\r
749 return p;\r
750 }\r
751 sprintf(ebuf, "mismatch token in ast_scan(): %s", scan_token_str(parser->token));\r
752 sorcerer_panic(ebuf);\r
753 return NULL; /* MR20 make -Wall happy */\r
754}\r
755\r
756static void\r
757#ifdef __USE_PROTOS\r
758stringparser_init(StringParser *parser, StringLexer *input)\r
759#else\r
760stringparser_init(parser, input)\r
761StringParser *parser;\r
762StringLexer *input;\r
763#endif\r
764{\r
765 parser->lexer = input;\r
766 parser->token = stringscan_gettok(parser->lexer);\r
767 parser->num_labels = 0;\r
768}\r
769\r
770static void\r
771#ifdef __USE_PROTOS\r
772stringlexer_init(StringLexer *scanner, char *input)\r
773#else\r
774stringlexer_init(scanner, input)\r
775StringLexer *scanner;\r
776char *input;\r
777#endif\r
778{\r
779 scanner->text[0]='\0';\r
780 scanner->input = input;\r
781 scanner->p = input;\r
782 stringscan_advance(scanner);\r
783}\r
784\r
785static void\r
786#ifdef __USE_PROTOS\r
787stringscan_advance(StringLexer *scanner)\r
788#else\r
789stringscan_advance(scanner)\r
790StringLexer *scanner;\r
791#endif\r
792{\r
793 if ( *(scanner->p) == '\0' ) scanner->c = StringScanEOF;\r
794 scanner->c = *(scanner->p)++;\r
795}\r
796\r
797static int\r
798#ifdef __USE_PROTOS\r
799stringscan_gettok(StringLexer *scanner)\r
800#else\r
801stringscan_gettok(scanner)\r
802StringLexer *scanner;\r
803#endif\r
804{\r
805 char *index = &scanner->text[0];\r
806 static char ebuf[100];\r
807\r
808 while ( isspace(scanner->c) ) { stringscan_advance(scanner); }\r
809 if ( isdigit(scanner->c) )\r
810 {\r
811 int tok = INT;\r
812 while ( isdigit(scanner->c) ) {\r
813 *index++ = scanner->c;\r
814 stringscan_advance(scanner);\r
815 }\r
816 *index = '\0';\r
817 return tok;\r
818 }\r
819 switch ( scanner->c )\r
820 {\r
821 case '#' : stringscan_advance(scanner); return POUND;\r
822 case '(' : stringscan_advance(scanner); return LPAREN;\r
823 case ')' : stringscan_advance(scanner); return RPAREN;\r
824 case '%' : stringscan_advance(scanner); return PERCENT;\r
825 case ':' : stringscan_advance(scanner); return COLON;\r
826 case '.' : stringscan_advance(scanner); return PERIOD;\r
827 case '\0' : return StringScanEOF;\r
828 case StringScanEOF : return StringScanEOF;\r
829 default :\r
830 sprintf(ebuf, "invalid char in ast_scan: '%c'", scanner->c);\r
831 sorcerer_panic(ebuf);\r
832 return 0; /* MR20 Make -Wall happy */\r
833 }\r
834}\r