* src/**/*, tests/**/*: Sync with DbLinq r1180. Gets unit tests into
[mono.git] / mcs / jay / output.c
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Paul Corbett.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37 #ifndef lint
38 static char sccsid[] = "@(#)output.c    5.7 (Berkeley) 5/24/93";
39 #endif /* not lint */
40
41 #include "defs.h"
42 #include <string.h>
43
44 static int nvectors;
45 static int nentries;
46 static short **froms;
47 static short **tos;
48 static short *tally;
49 static short *width;
50 static short *state_count;
51 static short *order;
52 static short *base;
53 static short *pos;
54 static int maxtable;
55 static short *table;
56 static short *check;
57 static int lowzero;
58 static int high;
59 extern int csharp;
60
61 output () {
62   int lno = 0;
63   char buf [128];
64
65   free_itemsets();
66   free_shifts();
67   free_reductions();
68
69   while (fgets(buf, sizeof buf, stdin) != NULL) {
70     char * cp;
71     ++ lno;
72     if (buf[strlen(buf)-1] != '\n')
73       fprintf(stderr, "jay: line %d is too long\n", lno), done(1);
74     switch (buf[0]) {
75     case '#':   continue;
76     case 't':   if (!tflag) fputs("//t", stdout);
77     case '.':   break;
78     default:
79       cp = strtok(buf, " \t\r\n");
80       if (cp)
81         if (strcmp(cp, "actions") == 0) output_semantic_actions();
82         else if (strcmp(cp, "debug") == 0) output_debug();
83         else if (strcmp(cp, "epilog") == 0) output_trailing_text();
84         else if (strcmp(cp, "prolog") == 0)
85                 output_stored_text(prolog_file, prolog_file_name);
86         else if (strcmp(cp, "local") == 0)
87                 output_stored_text(local_file, local_file_name);
88         else if (strcmp(cp, "tables") == 0)
89           output_rule_data(), output_yydefred(), output_actions();
90         else if (strcmp(cp, "tokens") == 0)
91                 output_defines(strtok(NULL, "\r\n"));
92         else
93           fprintf(stderr, "jay: unknown call (%s) in line %d\n", cp, lno);
94       continue;
95     }
96     fputs(buf+1, stdout), ++ outline;
97   }
98   free_parser();
99 }
100
101 output_rule_data()
102 {
103     register int i;
104     register int j;
105
106
107     printf("  %s static %s short [] yyLhs  = {%16d,",
108            csharp ? "" : " protected",
109            csharp ? "" : " final",
110             symbol_value[start_symbol]);
111
112     j = 10;
113     for (i = 3; i < nrules; i++)
114     {
115         if (j >= 10)
116         {
117             ++outline;
118             putchar('\n');
119             j = 1;
120         }
121         else
122             ++j;
123
124         printf("%5d,", symbol_value[rlhs[i]]);
125     }
126     outline += 2;
127     printf("\n  };\n");
128
129     printf("  %s static %s short [] yyLen = {%12d,",
130            csharp ? "" : "protected",
131            csharp ? "" : "final",
132            2);
133
134     j = 10;
135     for (i = 3; i < nrules; i++)
136     {
137         if (j >= 10)
138         {
139             ++outline;
140             putchar('\n');
141             j = 1;
142         }
143         else
144           j++;
145
146         printf("%5d,", rrhs[i + 1] - rrhs[i] - 1);
147     }
148     outline += 2;
149     printf("\n  };\n");
150 }
151
152
153 output_yydefred()
154 {
155     register int i, j;
156
157     printf("  %s static %s short [] yyDefRed = {%13d,",
158            csharp ? "" : "protected",
159            csharp ? "" : "final",          
160             (defred[0] ? defred[0] - 2 : 0));
161
162     j = 10;
163     for (i = 1; i < nstates; i++)
164     {
165         if (j < 10)
166             ++j;
167         else
168         {
169             ++outline;
170             putchar('\n');
171             j = 1;
172         }
173
174         printf("%5d,", (defred[i] ? defred[i] - 2 : 0));
175     }
176
177     outline += 2;
178     printf("\n  };\n");
179 }
180
181
182 output_actions()
183 {
184     nvectors = 2*nstates + nvars;
185
186     froms = NEW2(nvectors, short *);
187     tos = NEW2(nvectors, short *);
188     tally = NEW2(nvectors, short);
189     width = NEW2(nvectors, short);
190
191     token_actions();
192     FREE(lookaheads);
193     FREE(LA);
194     FREE(LAruleno);
195     FREE(accessing_symbol);
196
197     goto_actions();
198     FREE(goto_map + ntokens);
199     FREE(from_state);
200     FREE(to_state);
201
202     sort_actions();
203     pack_table();
204     output_base();
205     output_table();
206     output_check();
207 }
208
209
210 token_actions()
211 {
212     register int i, j;
213     register int shiftcount, reducecount;
214     register int max, min;
215     register short *actionrow, *r, *s;
216     register action *p;
217
218     actionrow = NEW2(2*ntokens, short);
219     for (i = 0; i < nstates; ++i)
220     {
221         if (parser[i])
222         {
223             for (j = 0; j < 2*ntokens; ++j)
224             actionrow[j] = 0;
225
226             shiftcount = 0;
227             reducecount = 0;
228             for (p = parser[i]; p; p = p->next)
229             {
230                 if (p->suppressed == 0)
231                 {
232                     if (p->action_code == SHIFT)
233                     {
234                         ++shiftcount;
235                         actionrow[p->symbol] = p->number;
236                     }
237                     else if (p->action_code == REDUCE && p->number != defred[i])
238                     {
239                         ++reducecount;
240                         actionrow[p->symbol + ntokens] = p->number;
241                     }
242                 }
243             }
244
245             tally[i] = shiftcount;
246             tally[nstates+i] = reducecount;
247             width[i] = 0;
248             width[nstates+i] = 0;
249             if (shiftcount > 0)
250             {
251                 froms[i] = r = NEW2(shiftcount, short);
252                 tos[i] = s = NEW2(shiftcount, short);
253                 min = MAXSHORT;
254                 max = 0;
255                 for (j = 0; j < ntokens; ++j)
256                 {
257                     if (actionrow[j])
258                     {
259                         if (min > symbol_value[j])
260                             min = symbol_value[j];
261                         if (max < symbol_value[j])
262                             max = symbol_value[j];
263                         *r++ = symbol_value[j];
264                         *s++ = actionrow[j];
265                     }
266                 }
267                 width[i] = max - min + 1;
268             }
269             if (reducecount > 0)
270             {
271                 froms[nstates+i] = r = NEW2(reducecount, short);
272                 tos[nstates+i] = s = NEW2(reducecount, short);
273                 min = MAXSHORT;
274                 max = 0;
275                 for (j = 0; j < ntokens; ++j)
276                 {
277                     if (actionrow[ntokens+j])
278                     {
279                         if (min > symbol_value[j])
280                             min = symbol_value[j];
281                         if (max < symbol_value[j])
282                             max = symbol_value[j];
283                         *r++ = symbol_value[j];
284                         *s++ = actionrow[ntokens+j] - 2;
285                     }
286                 }
287                 width[nstates+i] = max - min + 1;
288             }
289         }
290     }
291     FREE(actionrow);
292 }
293
294 goto_actions()
295 {
296     register int i, j, k;
297
298     state_count = NEW2(nstates, short);
299
300     k = default_goto(start_symbol + 1);
301     printf("  protected static %s short [] yyDgoto  = {%14d,", csharp ? "" : "final", k);
302     save_column(start_symbol + 1, k);
303
304     j = 10;
305     for (i = start_symbol + 2; i < nsyms; i++)
306     {
307         if (j >= 10)
308         {
309             ++outline;
310             putchar('\n');
311             j = 1;
312         }
313         else
314             ++j;
315
316         k = default_goto(i);
317         printf("%5d,", k);
318         save_column(i, k);
319     }
320
321     outline += 2;
322     printf("\n  };\n");
323     FREE(state_count);
324 }
325
326 int
327 default_goto(symbol)
328 int symbol;
329 {
330     register int i;
331     register int m;
332     register int n;
333     register int default_state;
334     register int max;
335
336     m = goto_map[symbol];
337     n = goto_map[symbol + 1];
338
339     if (m == n) return (0);
340
341     for (i = 0; i < nstates; i++)
342         state_count[i] = 0;
343
344     for (i = m; i < n; i++)
345         state_count[to_state[i]]++;
346
347     max = 0;
348     default_state = 0;
349     for (i = 0; i < nstates; i++)
350     {
351         if (state_count[i] > max)
352         {
353             max = state_count[i];
354             default_state = i;
355         }
356     }
357
358     return (default_state);
359 }
360
361
362
363 save_column(symbol, default_state)
364 int symbol;
365 int default_state;
366 {
367     register int i;
368     register int m;
369     register int n;
370     register short *sp;
371     register short *sp1;
372     register short *sp2;
373     register int count;
374     register int symno;
375
376     m = goto_map[symbol];
377     n = goto_map[symbol + 1];
378
379     count = 0;
380     for (i = m; i < n; i++)
381     {
382         if (to_state[i] != default_state)
383             ++count;
384     }
385     if (count == 0) return;
386
387     symno = symbol_value[symbol] + 2*nstates;
388
389     froms[symno] = sp1 = sp = NEW2(count, short);
390     tos[symno] = sp2 = NEW2(count, short);
391
392     for (i = m; i < n; i++)
393     {
394         if (to_state[i] != default_state)
395         {
396             *sp1++ = from_state[i];
397             *sp2++ = to_state[i];
398         }
399     }
400
401     tally[symno] = count;
402     width[symno] = sp1[-1] - sp[0] + 1;
403 }
404
405 sort_actions()
406 {
407   register int i;
408   register int j;
409   register int k;
410   register int t;
411   register int w;
412
413   order = NEW2(nvectors, short);
414   nentries = 0;
415
416   for (i = 0; i < nvectors; i++)
417     {
418       if (tally[i] > 0)
419         {
420           t = tally[i];
421           w = width[i];
422           j = nentries - 1;
423
424           while (j >= 0 && (width[order[j]] < w))
425             j--;
426
427           while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
428             j--;
429
430           for (k = nentries - 1; k > j; k--)
431             order[k + 1] = order[k];
432
433           order[j + 1] = i;
434           nentries++;
435         }
436     }
437 }
438
439
440 pack_table()
441 {
442     register int i;
443     register int place;
444     register int state;
445
446     base = NEW2(nvectors, short);
447     pos = NEW2(nentries, short);
448
449     maxtable = 1000;
450     table = NEW2(maxtable, short);
451     check = NEW2(maxtable, short);
452
453     lowzero = 0;
454     high = 0;
455
456     for (i = 0; i < maxtable; i++)
457         check[i] = -1;
458
459     for (i = 0; i < nentries; i++)
460     {
461         state = matching_vector(i);
462
463         if (state < 0)
464             place = pack_vector(i);
465         else
466             place = base[state];
467
468         pos[i] = place;
469         base[order[i]] = place;
470     }
471
472     for (i = 0; i < nvectors; i++)
473     {
474         if (froms[i])
475             FREE(froms[i]);
476         if (tos[i])
477             FREE(tos[i]);
478     }
479
480     FREE(froms);
481     FREE(tos);
482     FREE(pos);
483 }
484
485
486 /*  The function matching_vector determines if the vector specified by  */
487 /*  the input parameter matches a previously considered vector.  The    */
488 /*  test at the start of the function checks if the vector represents   */
489 /*  a row of shifts over terminal symbols or a row of reductions, or a  */
490 /*  column of shifts over a nonterminal symbol.  Berkeley Yacc does not */
491 /*  check if a column of shifts over a nonterminal symbols matches a    */
492 /*  previously considered vector.  Because of the nature of LR parsing  */
493 /*  tables, no two columns can match.  Therefore, the only possible     */
494 /*  match would be between a row and a column.  Such matches are        */
495 /*  unlikely.  Therefore, to save time, no attempt is made to see if a  */
496 /*  column matches a previously considered vector.                      */
497 /*                                                                      */
498 /*  Matching_vector is poorly designed.  The test could easily be made  */
499 /*  faster.  Also, it depends on the vectors being in a specific        */
500 /*  order.                                                              */
501
502 int
503 matching_vector(vector)
504 int vector;
505 {
506     register int i;
507     register int j;
508     register int k;
509     register int t;
510     register int w;
511     register int match;
512     register int prev;
513
514     i = order[vector];
515     if (i >= 2*nstates)
516         return (-1);
517
518     t = tally[i];
519     w = width[i];
520
521     for (prev = vector - 1; prev >= 0; prev--)
522     {
523         j = order[prev];
524         if (width[j] != w || tally[j] != t)
525             return (-1);
526
527         match = 1;
528         for (k = 0; match && k < t; k++)
529         {
530             if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
531                 match = 0;
532         }
533
534         if (match)
535             return (j);
536     }
537
538     return (-1);
539 }
540
541
542
543 int
544 pack_vector(vector)
545 int vector;
546 {
547     register int i, j, k, l;
548     register int t;
549     register int loc;
550     register int ok;
551     register short *from;
552     register short *to;
553     int newmax;
554
555     i = order[vector];
556     t = tally[i];
557     assert(t);
558
559     from = froms[i];
560     to = tos[i];
561
562     j = lowzero - from[0];
563     for (k = 1; k < t; ++k)
564         if (lowzero - from[k] > j)
565             j = lowzero - from[k];
566     for (;; ++j)
567     {
568         if (j == 0)
569             continue;
570         ok = 1;
571         for (k = 0; ok && k < t; k++)
572         {
573             loc = j + from[k];
574             if (loc >= maxtable)
575             {
576                 if (loc >= MAXTABLE)
577                     fatal("maximum table size exceeded");
578
579                 newmax = maxtable;
580                 do { newmax += 200; } while (newmax <= loc);
581                 table = (short *) REALLOC(table, newmax*sizeof(short));
582                 if (table == 0) no_space();
583                 check = (short *) REALLOC(check, newmax*sizeof(short));
584                 if (check == 0) no_space();
585                 for (l  = maxtable; l < newmax; ++l)
586                 {
587                     table[l] = 0;
588                     check[l] = -1;
589                 }
590                 maxtable = newmax;
591             }
592
593             if (check[loc] != -1)
594                 ok = 0;
595         }
596         for (k = 0; ok && k < vector; k++)
597         {
598             if (pos[k] == j)
599                 ok = 0;
600         }
601         if (ok)
602         {
603             for (k = 0; k < t; k++)
604             {
605                 loc = j + from[k];
606                 table[loc] = to[k];
607                 check[loc] = from[k];
608                 if (loc > high) high = loc;
609             }
610
611             while (check[lowzero] != -1)
612                 ++lowzero;
613
614             return (j);
615         }
616     }
617 }
618
619
620
621 output_base()
622 {
623     register int i, j;
624
625     printf("  protected static %s short [] yySindex = {%13d,", csharp?"":"final", base[0]);
626
627     j = 10;
628     for (i = 1; i < nstates; i++)
629     {
630         if (j >= 10)
631         {
632             ++outline;
633             putchar('\n');
634             j = 1;
635         }
636         else
637             ++j;
638
639         printf("%5d,", base[i]);
640     }
641
642     outline += 2;
643     printf("\n  };\n  protected static %s short [] yyRindex = {%13d,",
644            csharp ? "" : "final",
645             base[nstates]);
646
647     j = 10;
648     for (i = nstates + 1; i < 2*nstates; i++)
649     {
650         if (j >= 10)
651         {
652             ++outline;
653             putchar('\n');
654             j = 1;
655         }
656         else
657             ++j;
658
659         printf("%5d,", base[i]);
660     }
661
662     outline += 2;
663     printf("\n  };\n  protected static %s short [] yyGindex = {%13d,",
664            csharp ? "" : "final",
665             base[2*nstates]);
666
667     j = 10;
668     for (i = 2*nstates + 1; i < nvectors - 1; i++)
669     {
670         if (j >= 10)
671         {
672             ++outline;
673             putchar('\n');
674             j = 1;
675         }
676         else
677             ++j;
678
679         printf("%5d,", base[i]);
680     }
681
682     outline += 2;
683     printf("\n  };\n");
684     FREE(base);
685 }
686
687
688
689 output_table()
690 {
691     register int i;
692     register int j;
693
694     printf("  protected static %s short [] yyTable = {%14d,", csharp ? "" : "final", table[0]);
695
696     j = 10;
697     for (i = 1; i <= high; i++)
698     {
699         if (j >= 10)
700         {
701             ++outline;
702             putchar('\n');
703             j = 1;
704         }
705         else
706             ++j;
707
708         printf("%5d,", table[i]);
709     }
710
711     outline += 2;
712     printf("\n  };\n");
713     FREE(table);
714 }
715
716
717
718 output_check()
719 {
720     register int i;
721     register int j;
722
723     printf("  protected static %s short [] yyCheck = {%14d,",
724            csharp ? "" : "final",
725             check[0]);
726
727     j = 10;
728     for (i = 1; i <= high; i++)
729     {
730         if (j >= 10)
731         {
732             ++outline;
733             putchar('\n');
734             j = 1;
735         }
736         else
737             ++j;
738
739         printf("%5d,", check[i]);
740     }
741
742     outline += 2;
743     printf("\n  };\n");
744     FREE(check);
745 }
746
747
748 int
749 is_C_identifier(name)
750 char *name;
751 {
752     register char *s;
753     register int c;
754
755     s = name;
756     c = *s;
757     if (c == '"')
758     {
759         c = *++s;
760         if (!isalpha(c) && c != '_' && c != '$')
761             return (0);
762         while ((c = *++s) != '"')
763         {
764             if (!isalnum(c) && c != '_' && c != '$')
765                 return (0);
766         }
767         return (1);
768     }
769
770     if (!isalpha(c) && c != '_' && c != '$')
771         return (0);
772     while (c = *++s)
773     {
774         if (!isalnum(c) && c != '_' && c != '$')
775             return (0);
776     }
777     return (1);
778 }
779
780
781 output_defines(prefix)
782 char *prefix;
783 {
784     register int c, i;
785     register char *s;
786
787     for (i = 2; i < ntokens; ++i)
788     {
789         s = symbol_name[i];
790         if (is_C_identifier(s))
791         {
792             if (prefix)
793                 printf("  %s ", prefix);
794             c = *s;
795             if (c == '"')
796             {
797                 while ((c = *++s) != '"')
798                 {
799                     putchar(c);
800                 }
801             }
802             else
803             {
804                 do
805                 {
806                     putchar(c);
807                 }
808                 while (c = *++s);
809             }
810             ++outline;
811             printf(" = %d%s\n", symbol_value[i], csharp ? ";" : ";");
812         }
813     }
814
815     ++outline;
816     printf("  %s yyErrorCode = %d%s\n", prefix ? prefix : "", symbol_value[1], csharp ? ";" : ";");
817 }
818
819
820 output_stored_text(file, name)
821 FILE *file;
822 char *name;
823 {
824     register int c;
825     register FILE *in;
826
827     fflush(file);
828     in = fopen(name, "r");
829     if (in == NULL)
830         open_error(name);
831     if ((c = getc(in)) != EOF) {
832       if (c ==  '\n')
833         ++outline;
834       putchar(c);
835       while ((c = getc(in)) != EOF)
836       {
837         if (c == '\n')
838             ++outline;
839         putchar(c);
840       }
841       printf(default_line_format, ++outline + 1);
842     }
843     fclose(in);
844 }
845
846
847 output_debug()
848 {
849     register int i, j, k, max;
850     char **symnam, *s;
851     char * prefix = tflag ? "" : "//t";
852
853     ++outline;
854     printf("  protected static %s int yyFinal = %d;\n", csharp ? "" : "final", final_state);
855
856       ++outline;
857           printf ("%s // Put this array into a separate class so it is only initialized if debugging is actually used\n", prefix);
858           printf ("%s // Use MarshalByRefObject to disable inlining\n", prefix);
859           printf("%s class YYRules %s {\n", prefix, csharp ? ": MarshalByRefObject" : "");
860       printf("%s  public static %s string [] yyRule = {\n", prefix, csharp ? "" : "final");
861       for (i = 2; i < nrules; ++i)
862       {
863           printf("%s    \"%s :", prefix, symbol_name[rlhs[i]]);
864           for (j = rrhs[i]; ritem[j] > 0; ++j)
865           {
866               s = symbol_name[ritem[j]];
867               if (s[0] == '"')
868               {
869                   printf(" \\\"");
870                   while (*++s != '"')
871                   {
872                       if (*s == '\\')
873                       {
874                           if (s[1] == '\\')
875                               printf("\\\\\\\\");
876                           else
877                               printf("\\\\%c", s[1]);
878                           ++s;
879                       }
880                       else
881                           putchar(*s);
882                   }
883                   printf("\\\"");
884               }
885               else if (s[0] == '\'')
886               {
887                   if (s[1] == '"')
888                       printf(" '\\\"'");
889                   else if (s[1] == '\\')
890                   {
891                       if (s[2] == '\\')
892                           printf(" '\\\\\\\\");
893                       else
894                           printf(" '\\\\%c", s[2]);
895                       s += 2;
896                       while (*++s != '\'')
897                           putchar(*s);
898                       putchar('\'');
899                   }
900                   else
901                       printf(" '%c'", s[1]);
902               }
903               else
904                   printf(" %s", s);
905           }
906           ++outline;
907           printf("\",\n");
908       }
909       ++ outline;
910       printf("%s  };\n", prefix);
911           printf ("%s public static string getRule (int index) {\n", prefix);
912           printf ("%s    return yyRule [index];\n", prefix);
913           printf ("%s }\n", prefix);
914           printf ("%s}\n", prefix);
915
916     max = 0;
917     for (i = 2; i < ntokens; ++i)
918         if (symbol_value[i] > max)
919             max = symbol_value[i];
920
921         /* need yyNames for yyExpecting() */
922
923       printf("  protected static %s string [] yyNames = {", csharp ? "" : "final");
924       symnam = (char **) MALLOC((max+1)*sizeof(char *));
925       if (symnam == 0) no_space();
926   
927       /* Note that it is  not necessary to initialize the element       */
928       /* symnam[max].                                                   */
929       for (i = 0; i < max; ++i)
930           symnam[i] = 0;
931       for (i = ntokens - 1; i >= 2; --i)
932           symnam[symbol_value[i]] = symbol_name[i];
933       symnam[0] = "end-of-file";
934   
935       j = 70; fputs("    ", stdout);
936       for (i = 0; i <= max; ++i)
937       {
938           if (s = symnam[i])
939           {
940               if (s[0] == '"')
941               {
942                   k = 7;
943                   while (*++s != '"')
944                   {
945                       ++k;
946                       if (*s == '\\')
947                       {
948                           k += 2;
949                           if (*++s == '\\')
950                               ++k;
951                       }
952                   }
953                   j += k;
954                   if (j > 70)
955                   {
956                       ++outline;
957                       printf("\n    ");
958                       j = k;
959                   }
960                   printf("\"\\\"");
961                   s = symnam[i];
962                   while (*++s != '"')
963                   {
964                       if (*s == '\\')
965                       {
966                           printf("\\\\");
967                           if (*++s == '\\')
968                               printf("\\\\");
969                           else
970                               putchar(*s);
971                       }
972                       else
973                           putchar(*s);
974                   }
975                   printf("\\\"\",");
976               }
977               else if (s[0] == '\'')
978               {
979                   if (s[1] == '"')
980                   {
981                       j += 7;
982                       if (j > 70)
983                       {
984                           ++outline;
985                           printf("\n    ");
986                           j = 7;
987                       }
988                       printf("\"'\\\"'\",");
989                   }
990                   else
991                   {
992                       k = 5;
993                       while (*++s != '\'')
994                       {
995                           ++k;
996                           if (*s == '\\')
997                           {
998                               k += 2;
999                               if (*++s == '\\')
1000                                   ++k;
1001                           }
1002                       }
1003                       j += k;
1004                       if (j > 70)
1005                       {
1006                           ++outline;
1007                           printf("\n    ");
1008                           j = k;
1009                       }
1010                       printf("\"'");
1011                       s = symnam[i];
1012                       while (*++s != '\'')
1013                       {
1014                           if (*s == '\\')
1015                           {
1016                               printf("\\\\");
1017                               if (*++s == '\\')
1018                                   printf("\\\\");
1019                               else
1020                                   putchar(*s);
1021                           }
1022                           else
1023                               putchar(*s);
1024                       }
1025                       printf("'\",");
1026                   }
1027               }
1028               else
1029               {
1030                   k = strlen(s) + 3;
1031                   j += k;
1032                   if (j > 70)
1033                   {
1034                       ++outline;
1035                       printf("\n    ");
1036                       j = k;
1037                   }
1038                   putchar('"');
1039                   do { putchar(*s); } while (*++s);
1040                   printf("\",");
1041               }
1042           }
1043           else
1044           {
1045               j += 5;
1046               if (j > 70)
1047               {
1048                   ++outline;
1049                   printf("\n    ");
1050                   j = 5;
1051               }
1052               printf("null,");
1053           }
1054       }
1055       outline += 2;
1056       printf("\n  };\n");
1057       FREE(symnam);
1058 }
1059
1060 output_trailing_text()
1061 {
1062     register int c, last;
1063     register FILE *in;
1064
1065     if (line == 0)
1066         return;
1067
1068     in = input_file;
1069     c = *cptr;
1070     if (c == '\n')
1071     {
1072         ++lineno;
1073         if ((c = getc(in)) == EOF)
1074             return;
1075         ++outline;
1076         printf(line_format, lineno, input_file_name);
1077         if (c == '\n')
1078             ++outline;
1079         putchar(c);
1080         last = c;
1081     }
1082     else
1083     {
1084         ++outline;
1085         printf(line_format, lineno, input_file_name);
1086         do { putchar(c); } while ((c = *++cptr) != '\n');
1087         ++outline;
1088         putchar('\n');
1089         last = '\n';
1090     }
1091
1092     while ((c = getc(in)) != EOF)
1093     {
1094         if (c == '\n')
1095             ++outline;
1096         putchar(c);
1097         last = c;
1098     }
1099
1100     if (last != '\n')
1101     {
1102         ++outline;
1103         putchar('\n');
1104     }
1105     printf(default_line_format, ++outline + 1);
1106 }
1107
1108
1109 output_semantic_actions()
1110 {
1111     register int c, last;
1112
1113     fclose(action_file);
1114     action_file = fopen(action_file_name, "r");
1115     if (action_file == NULL)
1116         open_error(action_file_name);
1117
1118     if ((c = getc(action_file)) == EOF)
1119         return;
1120
1121     last = c;
1122     if (c == '\n')
1123         ++outline;
1124     putchar(c);
1125     while ((c = getc(action_file)) != EOF)
1126     {
1127         if (c == '\n')
1128             ++outline;
1129         putchar(c);
1130         last = c;
1131     }
1132
1133     if (last != '\n')
1134     {
1135         ++outline;
1136         putchar('\n');
1137     }
1138
1139     printf(default_line_format, ++outline + 1);
1140 }
1141
1142
1143 free_itemsets()
1144 {
1145     register core *cp, *next;
1146
1147     FREE(state_table);
1148     for (cp = first_state; cp; cp = next)
1149     {
1150         next = cp->next;
1151         FREE(cp);
1152     }
1153 }
1154
1155
1156 free_shifts()
1157 {
1158     register shifts *sp, *next;
1159
1160     FREE(shift_table);
1161     for (sp = first_shift; sp; sp = next)
1162     {
1163         next = sp->next;
1164         FREE(sp);
1165     }
1166 }
1167
1168
1169
1170 free_reductions()
1171 {
1172     register reductions *rp, *next;
1173
1174     FREE(reduction_table);
1175     for (rp = first_reduction; rp; rp = next)
1176     {
1177         next = rp->next;
1178         FREE(rp);
1179     }
1180 }