1 /* Copyright (c) 2007--2013 by Ian Piumarta
2  * All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the 'Software'),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, provided that the above copyright notice(s) and this
10  * permission notice appear in all copies of the Software.  Acknowledgement
11  * of the use of this Software in supporting documentation would be
12  * appreciated but is not required.
13  *
14  * THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.
15  *
16  * Last edited: 2013-12-18 10:09:42 by piumarta on linux32
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <assert.h>
23 
24 #ifdef WIN32
25 # undef inline
26 # define inline __inline
27 #endif
28 
29 #include "version.h"
30 #include "tree.h"
31 
yyl(void)32 static int yyl(void)
33 {
34   static int prev= 0;
35   return ++prev;
36 }
37 
charClassSet(unsigned char bits[],int c)38 static void charClassSet  (unsigned char bits[], int c)	{ bits[c >> 3] |=  (1 << (c & 7)); }
charClassClear(unsigned char bits[],int c)39 static void charClassClear(unsigned char bits[], int c)	{ bits[c >> 3] &= ~(1 << (c & 7)); }
40 
41 typedef void (*setter)(unsigned char bits[], int c);
42 
oigit(int c)43 static inline int oigit(int c)	{ return ('0' <= c && c <= '7'); }
higit(int c)44 static inline int higit(int c)	{ return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); }
45 
hexval(int c)46 static inline int hexval(int c)
47 {
48     if ('0' <= c && c <= '9') return c - '0';
49     if ('A' <= c && c <= 'F') return 10 - 'A' + c;
50     if ('a' <= c && c <= 'f') return 10 - 'a' + c;
51     return 0;
52 }
53 
cnext(unsigned char ** ccp)54 static int cnext(unsigned char **ccp)
55 {
56     unsigned char *cclass= *ccp;
57     int c= *cclass++;
58     if (c)
59     {
60 	if ('\\' == c && *cclass)
61 	{
62 	    switch (c= *cclass++)
63 	    {
64 		case 'a':  c= '\a';   break;	/* bel */
65 		case 'b':  c= '\b';   break;	/* bs */
66 		case 'e':  c= '\033'; break;	/* esc */
67 		case 'f':  c= '\f';   break;	/* ff */
68 		case 'n':  c= '\n';   break;	/* nl */
69 		case 'r':  c= '\r';   break;	/* cr */
70 		case 't':  c= '\t';   break;	/* ht */
71 		case 'v':  c= '\v';   break;	/* vt */
72 		case 'x':
73 		    c= 0;
74 		    if (higit(*cclass)) c= (c << 4) + hexval(*cclass++);
75 		    if (higit(*cclass)) c= (c << 4) + hexval(*cclass++);
76 		    break;
77 		default:
78 		    if (oigit(c))
79 		    {
80 			c -= '0';
81 			if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0';
82 			if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0';
83 		    }
84 		    break;
85 	    }
86 	}
87 	*ccp= cclass;
88     }
89     return c;
90 }
91 
makeCharClass(unsigned char * cclass)92 static char *makeCharClass(unsigned char *cclass)
93 {
94   unsigned char	 bits[32];
95   setter	 set;
96   int		 c, prev= -1;
97   static char	 string[256];
98   char		*ptr;
99 
100   if ('^' == *cclass)
101     {
102       memset(bits, 255, 32);
103       set= charClassClear;
104       ++cclass;
105     }
106   else
107     {
108       memset(bits, 0, 32);
109       set= charClassSet;
110     }
111 
112   while (*cclass)
113     {
114       if ('-' == *cclass && cclass[1] && prev >= 0)
115 	{
116 	  ++cclass;
117 	  for (c= cnext(&cclass);  prev <= c;  ++prev)
118 	    set(bits, prev);
119 	  prev= -1;
120 	}
121       else
122 	{
123 	  c= cnext(&cclass);
124 	  set(bits, prev= c);
125 	}
126     }
127 
128   ptr= string;
129   for (c= 0;  c < 32;  ++c)
130     ptr += sprintf(ptr, "\\%03o", bits[c]);
131 
132   return string;
133 }
134 
begin(void)135 static void begin(void)		{ fprintf(output, "\n  {"); }
end(void)136 static void end(void)		{ fprintf(output, "\n  }"); }
label(int n)137 static void label(int n)	{ fprintf(output, "\n  l%d:;\t", n); }
jump(int n)138 static void jump(int n)		{ fprintf(output, "  goto l%d;", n); }
save(int n)139 static void save(int n)		{ fprintf(output, "  int yypos%d= yy->__pos, yythunkpos%d= yy->__thunkpos;", n, n); }
restore(int n)140 static void restore(int n)	{ fprintf(output,     "  yy->__pos= yypos%d; yy->__thunkpos= yythunkpos%d;", n, n); }
141 
Node_compile_c_ko(Node * node,int ko)142 static void Node_compile_c_ko(Node *node, int ko)
143 {
144   assert(node);
145   switch (node->type)
146     {
147     case Rule:
148       fprintf(stderr, "\ninternal error #1 (%s)\n", node->rule.name);
149       exit(1);
150       break;
151 
152     case Dot:
153       fprintf(output, "  if (!yymatchDot(yy)) goto l%d;", ko);
154       break;
155 
156     case Name:
157       fprintf(output, "  if (!yy_%s(yy)) goto l%d;", node->name.rule->rule.name, ko);
158       if (node->name.variable)
159 	fprintf(output, "  yyDo(yy, yySet, %d, 0);", node->name.variable->variable.offset);
160       break;
161 
162     case Character:
163     case String:
164       {
165 	int len= strlen(node->string.value);
166 	if (1 == len)
167 	  {
168 	    if ('\'' == node->string.value[0])
169 	      fprintf(output, "  if (!yymatchChar(yy, '\\'')) goto l%d;", ko);
170 	    else
171 	      fprintf(output, "  if (!yymatchChar(yy, '%s')) goto l%d;", node->string.value, ko);
172 	  }
173 	else
174 	  if (2 == len && '\\' == node->string.value[0])
175 	    fprintf(output, "  if (!yymatchChar(yy, '%s')) goto l%d;", node->string.value, ko);
176 	  else
177 	    fprintf(output, "  if (!yymatchString(yy, \"%s\")) goto l%d;", node->string.value, ko);
178       }
179       break;
180 
181     case Class:
182       fprintf(output, "  if (!yymatchClass(yy, (unsigned char *)\"%s\")) goto l%d;", makeCharClass(node->cclass.value), ko);
183       break;
184 
185     case Action:
186       fprintf(output, "  yyDo(yy, yy%s, yy->__begin, yy->__end);", node->action.name);
187       break;
188 
189     case Predicate:
190       fprintf(output, "  yyText(yy, yy->__begin, yy->__end);  {\n");
191       fprintf(output, "#define yytext yy->__text\n");
192       fprintf(output, "#define yyleng yy->__textlen\n");
193       fprintf(output, "if (!(%s)) goto l%d;\n", node->action.text, ko);
194       fprintf(output, "#undef yytext\n");
195       fprintf(output, "#undef yyleng\n");
196       fprintf(output, "  }");
197       break;
198 
199     case Error:
200       {
201 	int eok= yyl(), eko= yyl();
202 	Node_compile_c_ko(node->error.element, eko);
203 	jump(eok);
204 	label(eko);
205 	fprintf(output, "  yyText(yy, yy->__begin, yy->__end);  {\n");
206 	fprintf(output, "#define yytext yy->__text\n");
207 	fprintf(output, "#define yyleng yy->__textlen\n");
208 	fprintf(output, "  %s;\n", node->error.text);
209 	fprintf(output, "#undef yytext\n");
210 	fprintf(output, "#undef yyleng\n");
211 	fprintf(output, "  }");
212 	jump(ko);
213 	label(eok);
214       }
215       break;
216 
217     case Alternate:
218       {
219 	int ok= yyl();
220 	begin();
221 	save(ok);
222 	for (node= node->alternate.first;  node;  node= node->alternate.next)
223 	  if (node->alternate.next)
224 	    {
225 	      int next= yyl();
226 	      Node_compile_c_ko(node, next);
227 	      jump(ok);
228 	      label(next);
229 	      restore(ok);
230 	    }
231 	  else
232 	    Node_compile_c_ko(node, ko);
233 	end();
234 	label(ok);
235       }
236       break;
237 
238     case Sequence:
239       for (node= node->sequence.first;  node;  node= node->sequence.next)
240 	Node_compile_c_ko(node, ko);
241       break;
242 
243     case PeekFor:
244       {
245 	int ok= yyl();
246 	begin();
247 	save(ok);
248 	Node_compile_c_ko(node->peekFor.element, ko);
249 	restore(ok);
250 	end();
251       }
252       break;
253 
254     case PeekNot:
255       {
256 	int ok= yyl();
257 	begin();
258 	save(ok);
259 	Node_compile_c_ko(node->peekFor.element, ok);
260 	jump(ko);
261 	label(ok);
262 	restore(ok);
263 	end();
264       }
265       break;
266 
267     case Query:
268       {
269 	int qko= yyl(), qok= yyl();
270 	begin();
271 	save(qko);
272 	Node_compile_c_ko(node->query.element, qko);
273 	jump(qok);
274 	label(qko);
275 	restore(qko);
276 	end();
277 	label(qok);
278       }
279       break;
280 
281     case Star:
282       {
283 	int again= yyl(), out= yyl();
284 	label(again);
285 	begin();
286 	save(out);
287 	Node_compile_c_ko(node->star.element, out);
288 	jump(again);
289 	label(out);
290 	restore(out);
291 	end();
292       }
293       break;
294 
295     case Plus:
296       {
297 	int again= yyl(), out= yyl();
298 	Node_compile_c_ko(node->plus.element, ko);
299 	label(again);
300 	begin();
301 	save(out);
302 	Node_compile_c_ko(node->plus.element, out);
303 	jump(again);
304 	label(out);
305 	restore(out);
306 	end();
307       }
308       break;
309 
310     default:
311       fprintf(stderr, "\nNode_compile_c_ko: illegal node type %d\n", node->type);
312       exit(1);
313     }
314 }
315 
316 
countVariables(Node * node)317 static int countVariables(Node *node)
318 {
319   int count= 0;
320   while (node)
321     {
322       ++count;
323       node= node->variable.next;
324     }
325   return count;
326 }
327 
defineVariables(Node * node)328 static void defineVariables(Node *node)
329 {
330   int count= 0;
331   while (node)
332     {
333       fprintf(output, "#define %s yy->__val[%d]\n", node->variable.name, --count);
334       node->variable.offset= count;
335       node= node->variable.next;
336     }
337   fprintf(output, "#define __ yy->__\n");
338   fprintf(output, "#define yypos yy->__pos\n");
339   fprintf(output, "#define yythunkpos yy->__thunkpos\n");
340 }
341 
undefineVariables(Node * node)342 static void undefineVariables(Node *node)
343 {
344   fprintf(output, "#undef yythunkpos\n");
345   fprintf(output, "#undef yypos\n");
346   fprintf(output, "#undef yy\n");
347   while (node)
348     {
349       fprintf(output, "#undef %s\n", node->variable.name);
350       node= node->variable.next;
351     }
352 }
353 
354 
Rule_compile_c2(Node * node)355 static void Rule_compile_c2(Node *node)
356 {
357   assert(node);
358   assert(Rule == node->type);
359 
360   if (!node->rule.expression)
361     fprintf(stderr, "rule '%s' used but not defined\n", node->rule.name);
362   else
363     {
364       int ko= yyl(), safe;
365 
366       if ((!(RuleUsed & node->rule.flags)) && (node != start))
367 	fprintf(stderr, "rule '%s' defined but not used\n", node->rule.name);
368 
369       safe= ((Query == node->rule.expression->type) || (Star == node->rule.expression->type));
370 
371       fprintf(output, "\nYY_RULE(int) yy_%s(yycontext *yy)\n{", node->rule.name);
372       if (!safe) save(0);
373       if (node->rule.variables)
374 	fprintf(output, "  yyDo(yy, yyPush, %d, 0);", countVariables(node->rule.variables));
375       fprintf(output, "\n  yyprintf((stderr, \"%%s\\n\", \"%s\"));", node->rule.name);
376       Node_compile_c_ko(node->rule.expression, ko);
377       fprintf(output, "\n  yyprintf((stderr, \"  ok   %%s @ %%s\\n\", \"%s\", yy->__buf+yy->__pos));", node->rule.name);
378       if (node->rule.variables)
379 	fprintf(output, "  yyDo(yy, yyPop, %d, 0);", countVariables(node->rule.variables));
380       fprintf(output, "\n  return 1;");
381       if (!safe)
382 	{
383 	  label(ko);
384 	  restore(0);
385 	  fprintf(output, "\n  yyprintf((stderr, \"  fail %%s @ %%s\\n\", \"%s\", yy->__buf+yy->__pos));", node->rule.name);
386 	  fprintf(output, "\n  return 0;");
387 	}
388       fprintf(output, "\n}");
389     }
390 
391   if (node->rule.next)
392     Rule_compile_c2(node->rule.next);
393 }
394 
395 static char *header= "\
396 #include <stdio.h>\n\
397 #include <stdlib.h>\n\
398 #include <string.h>\n\
399 ";
400 
401 static char *preamble= "\
402 #ifndef YY_MALLOC\n\
403 #define YY_MALLOC(C, N)		malloc(N)\n\
404 #endif\n\
405 #ifndef YY_REALLOC\n\
406 #define YY_REALLOC(C, P, N)	realloc(P, N)\n\
407 #endif\n\
408 #ifndef YY_FREE\n\
409 #define YY_FREE(C, P)		free(P)\n\
410 #endif\n\
411 #ifndef YY_LOCAL\n\
412 #define YY_LOCAL(T)	static T\n\
413 #endif\n\
414 #ifndef YY_ACTION\n\
415 #define YY_ACTION(T)	static T\n\
416 #endif\n\
417 #ifndef YY_RULE\n\
418 #define YY_RULE(T)	static T\n\
419 #endif\n\
420 #ifndef YY_PARSE\n\
421 #define YY_PARSE(T)	T\n\
422 #endif\n\
423 #ifndef YYPARSE\n\
424 #define YYPARSE		yyparse\n\
425 #endif\n\
426 #ifndef YYPARSEFROM\n\
427 #define YYPARSEFROM	yyparsefrom\n\
428 #endif\n\
429 #ifndef YYRELEASE\n\
430 #define YYRELEASE	yyrelease\n\
431 #endif\n\
432 #ifndef YY_BEGIN\n\
433 #define YY_BEGIN	( yy->__begin= yy->__pos, 1)\n\
434 #endif\n\
435 #ifndef YY_END\n\
436 #define YY_END		( yy->__end= yy->__pos, 1)\n\
437 #endif\n\
438 #ifdef YY_DEBUG\n\
439 # define yyprintf(args)	fprintf args\n\
440 #else\n\
441 # define yyprintf(args)\n\
442 #endif\n\
443 #ifndef YYSTYPE\n\
444 #define YYSTYPE	int\n\
445 #endif\n\
446 #ifndef YY_STACK_SIZE\n\
447 #define YY_STACK_SIZE 128\n\
448 #endif\n\
449 \n\
450 #ifndef YY_BUFFER_SIZE\n\
451 #define YY_BUFFER_SIZE 1024\n\
452 #endif\n\
453 \n\
454 #ifndef YY_PART\n\
455 \n\
456 typedef struct _yycontext yycontext;\n\
457 typedef void (*yyaction)(yycontext *yy, char *yytext, int yyleng);\n\
458 typedef struct _yythunk { int begin, end;  yyaction  action;  struct _yythunk *next; } yythunk;\n\
459 \n\
460 struct _yycontext {\n\
461   char     *__buf;\n\
462   int       __buflen;\n\
463   int       __pos;\n\
464   int       __limit;\n\
465   char     *__text;\n\
466   int       __textlen;\n\
467   int       __begin;\n\
468   int       __end;\n\
469   int       __textmax;\n\
470   yythunk  *__thunks;\n\
471   int       __thunkslen;\n\
472   int       __thunkpos;\n\
473   YYSTYPE   __;\n\
474   YYSTYPE  *__val;\n\
475   YYSTYPE  *__vals;\n\
476   int       __valslen;\n\
477 #ifdef YY_CTX_MEMBERS\n\
478   YY_CTX_MEMBERS\n\
479 #endif\n\
480 };\n\
481 \n\
482 #ifdef YY_CTX_LOCAL\n\
483 #define YY_CTX_PARAM_	yycontext *yyctx,\n\
484 #define YY_CTX_PARAM	yycontext *yyctx\n\
485 #define YY_CTX_ARG_	yyctx,\n\
486 #define YY_CTX_ARG	yyctx\n\
487 #ifndef YY_INPUT\n\
488 #define YY_INPUT(yy, buf, result, max_size)		\\\n\
489   {							\\\n\
490     int yyc= getchar();					\\\n\
491     result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1);	\\\n\
492     yyprintf((stderr, \"<%c>\", yyc));			\\\n\
493   }\n\
494 #endif\n\
495 #else\n\
496 #define YY_CTX_PARAM_\n\
497 #define YY_CTX_PARAM\n\
498 #define YY_CTX_ARG_\n\
499 #define YY_CTX_ARG\n\
500 yycontext _yyctx= { 0, 0 };\n\
501 yycontext *yyctx= &_yyctx;\n\
502 #ifndef YY_INPUT\n\
503 #define YY_INPUT(buf, result, max_size)			\\\n\
504   {							\\\n\
505     int yyc= getchar();					\\\n\
506     result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1);	\\\n\
507     yyprintf((stderr, \"<%c>\", yyc));			\\\n\
508   }\n\
509 #endif\n\
510 #endif\n\
511 \n\
512 YY_LOCAL(int) yyrefill(yycontext *yy)\n\
513 {\n\
514   int yyn;\n\
515   while (yy->__buflen - yy->__pos < 512)\n\
516     {\n\
517       yy->__buflen *= 2;\n\
518       yy->__buf= (char *)YY_REALLOC(yy, yy->__buf, yy->__buflen);\n\
519     }\n\
520 #ifdef YY_CTX_LOCAL\n\
521   YY_INPUT(yy, (yy->__buf + yy->__pos), yyn, (yy->__buflen - yy->__pos));\n\
522 #else\n\
523   YY_INPUT((yy->__buf + yy->__pos), yyn, (yy->__buflen - yy->__pos));\n\
524 #endif\n\
525   if (!yyn) return 0;\n\
526   yy->__limit += yyn;\n\
527   return 1;\n\
528 }\n\
529 \n\
530 YY_LOCAL(int) yymatchDot(yycontext *yy)\n\
531 {\n\
532   if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n\
533   ++yy->__pos;\n\
534   return 1;\n\
535 }\n\
536 \n\
537 YY_LOCAL(int) yymatchChar(yycontext *yy, int c)\n\
538 {\n\
539   if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n\
540   if ((unsigned char)yy->__buf[yy->__pos] == c)\n\
541     {\n\
542       ++yy->__pos;\n\
543       yyprintf((stderr, \"  ok   yymatchChar(yy, %c) @ %s\\n\", c, yy->__buf+yy->__pos));\n\
544       return 1;\n\
545     }\n\
546   yyprintf((stderr, \"  fail yymatchChar(yy, %c) @ %s\\n\", c, yy->__buf+yy->__pos));\n\
547   return 0;\n\
548 }\n\
549 \n\
550 YY_LOCAL(int) yymatchString(yycontext *yy, const char *s)\n\
551 {\n\
552   int yysav= yy->__pos;\n\
553   while (*s)\n\
554     {\n\
555       if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n\
556       if (yy->__buf[yy->__pos] != *s)\n\
557         {\n\
558           yy->__pos= yysav;\n\
559           return 0;\n\
560         }\n\
561       ++s;\n\
562       ++yy->__pos;\n\
563     }\n\
564   return 1;\n\
565 }\n\
566 \n\
567 YY_LOCAL(int) yymatchClass(yycontext *yy, unsigned char *bits)\n\
568 {\n\
569   int c;\n\
570   if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n\
571   c= (unsigned char)yy->__buf[yy->__pos];\n\
572   if (bits[c >> 3] & (1 << (c & 7)))\n\
573     {\n\
574       ++yy->__pos;\n\
575       yyprintf((stderr, \"  ok   yymatchClass @ %s\\n\", yy->__buf+yy->__pos));\n\
576       return 1;\n\
577     }\n\
578   yyprintf((stderr, \"  fail yymatchClass @ %s\\n\", yy->__buf+yy->__pos));\n\
579   return 0;\n\
580 }\n\
581 \n\
582 YY_LOCAL(void) yyDo(yycontext *yy, yyaction action, int begin, int end)\n\
583 {\n\
584   while (yy->__thunkpos >= yy->__thunkslen)\n\
585     {\n\
586       yy->__thunkslen *= 2;\n\
587       yy->__thunks= (yythunk *)YY_REALLOC(yy, yy->__thunks, sizeof(yythunk) * yy->__thunkslen);\n\
588     }\n\
589   yy->__thunks[yy->__thunkpos].begin=  begin;\n\
590   yy->__thunks[yy->__thunkpos].end=    end;\n\
591   yy->__thunks[yy->__thunkpos].action= action;\n\
592   ++yy->__thunkpos;\n\
593 }\n\
594 \n\
595 YY_LOCAL(int) yyText(yycontext *yy, int begin, int end)\n\
596 {\n\
597   int yyleng= end - begin;\n\
598   if (yyleng <= 0)\n\
599     yyleng= 0;\n\
600   else\n\
601     {\n\
602       while (yy->__textlen < (yyleng + 1))\n\
603 	{\n\
604 	  yy->__textlen *= 2;\n\
605 	  yy->__text= (char *)YY_REALLOC(yy, yy->__text, yy->__textlen);\n\
606 	}\n\
607       memcpy(yy->__text, yy->__buf + begin, yyleng);\n\
608     }\n\
609   yy->__text[yyleng]= '\\0';\n\
610   return yyleng;\n\
611 }\n\
612 \n\
613 YY_LOCAL(void) yyDone(yycontext *yy)\n\
614 {\n\
615   int pos;\n\
616   for (pos= 0;  pos < yy->__thunkpos;  ++pos)\n\
617     {\n\
618       yythunk *thunk= &yy->__thunks[pos];\n\
619       int yyleng= thunk->end ? yyText(yy, thunk->begin, thunk->end) : thunk->begin;\n\
620       yyprintf((stderr, \"DO [%d] %p %s\\n\", pos, thunk->action, yy->__text));\n\
621       thunk->action(yy, yy->__text, yyleng);\n\
622     }\n\
623   yy->__thunkpos= 0;\n\
624 }\n\
625 \n\
626 YY_LOCAL(void) yyCommit(yycontext *yy)\n\
627 {\n\
628   if ((yy->__limit -= yy->__pos))\n\
629     {\n\
630       memmove(yy->__buf, yy->__buf + yy->__pos, yy->__limit);\n\
631     }\n\
632   yy->__begin -= yy->__pos;\n\
633   yy->__end -= yy->__pos;\n\
634   yy->__pos= yy->__thunkpos= 0;\n\
635 }\n\
636 \n\
637 YY_LOCAL(int) yyAccept(yycontext *yy, int tp0)\n\
638 {\n\
639   if (tp0)\n\
640     {\n\
641       fprintf(stderr, \"accept denied at %d\\n\", tp0);\n\
642       return 0;\n\
643     }\n\
644   else\n\
645     {\n\
646       yyDone(yy);\n\
647       yyCommit(yy);\n\
648     }\n\
649   return 1;\n\
650 }\n\
651 \n\
652 YY_LOCAL(void) yyPush(yycontext *yy, char *text, int count)\n\
653 {\n\
654   yy->__val += count;\n\
655   while (yy->__valslen <= yy->__val - yy->__vals)\n\
656     {\n\
657       long offset= yy->__val - yy->__vals;\n\
658       yy->__valslen *= 2;\n\
659       yy->__vals= (YYSTYPE *)YY_REALLOC(yy, yy->__vals, sizeof(YYSTYPE) * yy->__valslen);\n\
660       yy->__val= yy->__vals + offset;\n\
661     }\n\
662 }\n\
663 YY_LOCAL(void) yyPop(yycontext *yy, char *text, int count)   { yy->__val -= count; }\n\
664 YY_LOCAL(void) yySet(yycontext *yy, char *text, int count)   { yy->__val[count]= yy->__; }\n\
665 \n\
666 #endif /* YY_PART */\n\
667 \n\
668 #define	YYACCEPT	yyAccept(yy, yythunkpos0)\n\
669 \n\
670 ";
671 
672 static char *footer= "\n\
673 \n\
674 #ifndef YY_PART\n\
675 \n\
676 typedef int (*yyrule)(yycontext *yy);\n\
677 \n\
678 YY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart)\n\
679 {\n\
680   int yyok;\n\
681   if (!yyctx->__buflen)\n\
682     {\n\
683       yyctx->__buflen= YY_BUFFER_SIZE;\n\
684       yyctx->__buf= (char *)YY_MALLOC(yyctx, yyctx->__buflen);\n\
685       yyctx->__textlen= YY_BUFFER_SIZE;\n\
686       yyctx->__text= (char *)YY_MALLOC(yyctx, yyctx->__textlen);\n\
687       yyctx->__thunkslen= YY_STACK_SIZE;\n\
688       yyctx->__thunks= (yythunk *)YY_MALLOC(yyctx, sizeof(yythunk) * yyctx->__thunkslen);\n\
689       yyctx->__valslen= YY_STACK_SIZE;\n\
690       yyctx->__vals= (YYSTYPE *)YY_MALLOC(yyctx, sizeof(YYSTYPE) * yyctx->__valslen);\n\
691       yyctx->__begin= yyctx->__end= yyctx->__pos= yyctx->__limit= yyctx->__thunkpos= 0;\n\
692     }\n\
693   yyctx->__begin= yyctx->__end= yyctx->__pos;\n\
694   yyctx->__thunkpos= 0;\n\
695   yyctx->__val= yyctx->__vals;\n\
696   yyok= yystart(yyctx);\n\
697   if (yyok) yyDone(yyctx);\n\
698   yyCommit(yyctx);\n\
699   return yyok;\n\
700 }\n\
701 \n\
702 YY_PARSE(int) YYPARSE(YY_CTX_PARAM)\n\
703 {\n\
704   return YYPARSEFROM(YY_CTX_ARG_ yy_%s);\n\
705 }\n\
706 \n\
707 YY_PARSE(yycontext *) YYRELEASE(yycontext *yyctx)\n\
708 {\n\
709   if (yyctx->__buflen)\n\
710     {\n\
711       yyctx->__buflen= 0;\n\
712       YY_FREE(yyctx, yyctx->__buf);\n\
713       YY_FREE(yyctx, yyctx->__text);\n\
714       YY_FREE(yyctx, yyctx->__thunks);\n\
715       YY_FREE(yyctx, yyctx->__vals);\n\
716     }\n\
717   return yyctx;\n\
718 }\n\
719 \n\
720 #endif\n\
721 ";
722 
Rule_compile_c_header(void)723 void Rule_compile_c_header(void)
724 {
725   fprintf(output, "/* A recursive-descent parser generated by peg %d.%d.%d */\n", PEG_MAJOR, PEG_MINOR, PEG_LEVEL);
726   fprintf(output, "\n");
727   fprintf(output, "%s", header);
728   fprintf(output, "#define YYRULECOUNT %d\n", ruleCount);
729 }
730 
consumesInput(Node * node)731 int consumesInput(Node *node)
732 {
733   if (!node) return 0;
734 
735   switch (node->type)
736     {
737     case Rule:
738       {
739 	int result= 0;
740 	if (RuleReached & node->rule.flags)
741 	  fprintf(stderr, "possible infinite left recursion in rule '%s'\n", node->rule.name);
742 	else
743 	  {
744 	    node->rule.flags |= RuleReached;
745 	    result= consumesInput(node->rule.expression);
746 	    node->rule.flags &= ~RuleReached;
747 	  }
748 	return result;
749       }
750       break;
751 
752     case Dot:		return 1;
753     case Name:		return consumesInput(node->name.rule);
754     case Character:
755     case String:	return strlen(node->string.value) > 0;
756     case Class:		return 1;
757     case Action:	return 0;
758     case Predicate:	return 0;
759     case Error:		return consumesInput(node->error.element);
760 
761     case Alternate:
762       {
763 	Node *n;
764 	for (n= node->alternate.first;  n;  n= n->alternate.next)
765 	  if (!consumesInput(n))
766 	    return 0;
767       }
768       return 1;
769 
770     case Sequence:
771       {
772 	Node *n;
773 	for (n= node->alternate.first;  n;  n= n->alternate.next)
774 	  if (consumesInput(n))
775 	    return 1;
776       }
777       return 0;
778 
779     case PeekFor:	return 0;
780     case PeekNot:	return 0;
781     case Query:		return 0;
782     case Star:		return 0;
783     case Plus:		return consumesInput(node->plus.element);
784 
785     default:
786       fprintf(stderr, "\nconsumesInput: illegal node type %d\n", node->type);
787       exit(1);
788     }
789   return 0;
790 }
791 
792 
Rule_compile_c(Node * node)793 void Rule_compile_c(Node *node)
794 {
795   Node *n;
796 
797   for (n= rules;  n;  n= n->rule.next)
798     consumesInput(n);
799 
800   fprintf(output, "%s", preamble);
801   for (n= node;  n;  n= n->rule.next)
802     fprintf(output, "YY_RULE(int) yy_%s(yycontext *yy); /* %d */\n", n->rule.name, n->rule.id);
803   fprintf(output, "\n");
804   for (n= actions;  n;  n= n->action.list)
805     {
806       fprintf(output, "YY_ACTION(void) yy%s(yycontext *yy, char *yytext, int yyleng)\n{\n", n->action.name);
807       defineVariables(n->action.rule->rule.variables);
808       fprintf(output, "  yyprintf((stderr, \"do yy%s\\n\"));\n", n->action.name);
809       fprintf(output, "  {\n");
810       fprintf(output, "  %s;\n", n->action.text);
811       fprintf(output, "  }\n");
812       undefineVariables(n->action.rule->rule.variables);
813       fprintf(output, "}\n");
814     }
815   Rule_compile_c2(node);
816   fprintf(output, footer, start->rule.name);
817 }
818