Import flex-2.5.37 to new vendor branch
[dragonfly.git] / contrib / flex / misc.c
1 /* misc - miscellaneous flex routines */
2
3 /*  Copyright (c) 1990 The Regents of the University of California. */
4 /*  All rights reserved. */
5
6 /*  This code is derived from software contributed to Berkeley by */
7 /*  Vern Paxson. */
8
9 /*  The United States Government has rights in this work pursuant */
10 /*  to contract no. DE-AC03-76SF00098 between the United States */
11 /*  Department of Energy and the University of California. */
12
13 /*  This file is part of flex. */
14
15 /*  Redistribution and use in source and binary forms, with or without */
16 /*  modification, are permitted provided that the following conditions */
17 /*  are met: */
18
19 /*  1. Redistributions of source code must retain the above copyright */
20 /*     notice, this list of conditions and the following disclaimer. */
21 /*  2. Redistributions in binary form must reproduce the above copyright */
22 /*     notice, this list of conditions and the following disclaimer in the */
23 /*     documentation and/or other materials provided with the distribution. */
24
25 /*  Neither the name of the University nor the names of its contributors */
26 /*  may be used to endorse or promote products derived from this software */
27 /*  without specific prior written permission. */
28
29 /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
30 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
31 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
32 /*  PURPOSE. */
33
34 #include "flexdef.h"
35 #include "tables.h"
36
37 #define CMD_IF_TABLES_SER    "%if-tables-serialization"
38 #define CMD_TABLES_YYDMAP    "%tables-yydmap"
39 #define CMD_DEFINE_YYTABLES  "%define-yytables"
40 #define CMD_IF_CPP_ONLY      "%if-c++-only"
41 #define CMD_IF_C_ONLY        "%if-c-only"
42 #define CMD_IF_C_OR_CPP      "%if-c-or-c++"
43 #define CMD_NOT_FOR_HEADER   "%not-for-header"
44 #define CMD_OK_FOR_HEADER    "%ok-for-header"
45 #define CMD_PUSH             "%push"
46 #define CMD_POP              "%pop"
47 #define CMD_IF_REENTRANT     "%if-reentrant"
48 #define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
49 #define CMD_IF_BISON_BRIDGE  "%if-bison-bridge"
50 #define CMD_IF_NOT_BISON_BRIDGE  "%if-not-bison-bridge"
51 #define CMD_ENDIF            "%endif"
52
53 /* we allow the skeleton to push and pop. */
54 struct sko_state {
55     bool dc; /**< do_copy */
56 };
57 static struct sko_state *sko_stack=0;
58 static int sko_len=0,sko_sz=0;
59 static void sko_push(bool dc)
60 {
61     if(!sko_stack){
62         sko_sz = 1;
63         sko_stack = (struct sko_state*)flex_alloc(sizeof(struct sko_state)*sko_sz);
64         if (!sko_stack)
65             flexfatal(_("allocation of sko_stack failed"));
66         sko_len = 0;
67     }
68     if(sko_len >= sko_sz){
69         sko_sz *= 2;
70         sko_stack = (struct sko_state*)flex_realloc(sko_stack,sizeof(struct sko_state)*sko_sz);
71     }
72     
73     /* initialize to zero and push */
74     sko_stack[sko_len].dc = dc;
75     sko_len++;
76 }
77 static void sko_peek(bool *dc)
78 {
79     if(sko_len <= 0)
80         flex_die("peek attempt when sko stack is empty");
81     if(dc)
82         *dc = sko_stack[sko_len-1].dc;
83 }
84 static void sko_pop(bool* dc)
85 {
86     sko_peek(dc);
87     sko_len--;
88     if(sko_len < 0)
89         flex_die("popped too many times in skeleton.");
90 }
91
92 /* Append "#define defname value\n" to the running buffer. */
93 void action_define (defname, value)
94      const char *defname;
95      int value;
96 {
97         char    buf[MAXLINE];
98         char   *cpy;
99
100         if ((int) strlen (defname) > MAXLINE / 2) {
101                 format_pinpoint_message (_
102                                          ("name \"%s\" ridiculously long"),
103                                          defname);
104                 return;
105         }
106
107         snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value);
108         add_action (buf);
109
110         /* track #defines so we can undef them when we're done. */
111         cpy = copy_string (defname);
112         buf_append (&defs_buf, &cpy, 1);
113 }
114
115
116 /** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer.
117  *  @param defname The macro name.
118  *  @param value The macro value, can be NULL, which is the same as the empty string.
119  */
120 void action_m4_define (const char *defname, const char * value)
121 {
122         char    buf[MAXLINE];
123
124     flexfatal ("DO NOT USE THIS FUNCTION!");
125
126         if ((int) strlen (defname) > MAXLINE / 2) {
127                 format_pinpoint_message (_
128                                          ("name \"%s\" ridiculously long"),
129                                          defname);
130                 return;
131         }
132
133         snprintf (buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value?value:"");
134         add_action (buf);
135 }
136
137 /* Append "new_text" to the running buffer. */
138 void add_action (new_text)
139      const char   *new_text;
140 {
141         int     len = strlen (new_text);
142
143         while (len + action_index >= action_size - 10 /* slop */ ) {
144                 int     new_size = action_size * 2;
145
146                 if (new_size <= 0)
147                         /* Increase just a little, to try to avoid overflow
148                          * on 16-bit machines.
149                          */
150                         action_size += action_size / 8;
151                 else
152                         action_size = new_size;
153
154                 action_array =
155                         reallocate_character_array (action_array,
156                                                     action_size);
157         }
158
159         strcpy (&action_array[action_index], new_text);
160
161         action_index += len;
162 }
163
164
165 /* allocate_array - allocate memory for an integer array of the given size */
166
167 void   *allocate_array (size, element_size)
168      int size;
169      size_t element_size;
170 {
171         register void *mem;
172         size_t  num_bytes = element_size * size;
173
174         mem = flex_alloc (num_bytes);
175         if (!mem)
176                 flexfatal (_
177                            ("memory allocation failed in allocate_array()"));
178
179         return mem;
180 }
181
182
183 /* all_lower - true if a string is all lower-case */
184
185 int all_lower (str)
186      register char *str;
187 {
188         while (*str) {
189                 if (!isascii ((Char) * str) || !islower ((Char) * str))
190                         return 0;
191                 ++str;
192         }
193
194         return 1;
195 }
196
197
198 /* all_upper - true if a string is all upper-case */
199
200 int all_upper (str)
201      register char *str;
202 {
203         while (*str) {
204                 if (!isascii ((Char) * str) || !isupper ((Char) * str))
205                         return 0;
206                 ++str;
207         }
208
209         return 1;
210 }
211
212
213 /* intcmp - compares two integers for use by qsort. */
214
215 int intcmp (const void *a, const void *b)
216 {
217   return *(const int *) a - *(const int *) b;
218 }
219
220
221 /* check_char - checks a character to make sure it's within the range
222  *              we're expecting.  If not, generates fatal error message
223  *              and exits.
224  */
225
226 void check_char (c)
227      int c;
228 {
229         if (c >= CSIZE)
230                 lerrsf (_("bad character '%s' detected in check_char()"),
231                         readable_form (c));
232
233         if (c >= csize)
234                 lerrsf (_
235                         ("scanner requires -8 flag to use the character %s"),
236                         readable_form (c));
237 }
238
239
240
241 /* clower - replace upper-case letter to lower-case */
242
243 Char clower (c)
244      register int c;
245 {
246         return (Char) ((isascii (c) && isupper (c)) ? tolower (c) : c);
247 }
248
249
250 /* copy_string - returns a dynamically allocated copy of a string */
251
252 char   *copy_string (str)
253      register const char *str;
254 {
255         register const char *c1;
256         register char *c2;
257         char   *copy;
258         unsigned int size;
259
260         /* find length */
261         for (c1 = str; *c1; ++c1) ;
262
263         size = (c1 - str + 1) * sizeof (char);
264
265         copy = (char *) flex_alloc (size);
266
267         if (copy == NULL)
268                 flexfatal (_("dynamic memory failure in copy_string()"));
269
270         for (c2 = copy; (*c2++ = *str++) != 0;) ;
271
272         return copy;
273 }
274
275
276 /* copy_unsigned_string -
277  *    returns a dynamically allocated copy of a (potentially) unsigned string
278  */
279
280 Char   *copy_unsigned_string (str)
281      register Char *str;
282 {
283         register Char *c;
284         Char   *copy;
285
286         /* find length */
287         for (c = str; *c; ++c) ;
288
289         copy = allocate_Character_array (c - str + 1);
290
291         for (c = copy; (*c++ = *str++) != 0;) ;
292
293         return copy;
294 }
295
296
297 /* cclcmp - compares two characters for use by qsort with '\0' sorting last. */
298
299 int cclcmp (const void *a, const void *b)
300 {
301   if (!*(const Char *) a)
302         return 1;
303   else
304         if (!*(const Char *) b)
305           return - 1;
306         else
307           return *(const Char *) a - *(const Char *) b;
308 }
309
310
311 /* dataend - finish up a block of data declarations */
312
313 void dataend ()
314 {
315         /* short circuit any output */
316         if (gentables) {
317
318                 if (datapos > 0)
319                         dataflush ();
320
321                 /* add terminator for initialization; { for vi */
322                 outn ("    } ;\n");
323         }
324         dataline = 0;
325         datapos = 0;
326 }
327
328
329 /* dataflush - flush generated data statements */
330
331 void dataflush ()
332 {
333         /* short circuit any output */
334         if (!gentables)
335                 return;
336
337         outc ('\n');
338
339         if (++dataline >= NUMDATALINES) {
340                 /* Put out a blank line so that the table is grouped into
341                  * large blocks that enable the user to find elements easily.
342                  */
343                 outc ('\n');
344                 dataline = 0;
345         }
346
347         /* Reset the number of characters written on the current line. */
348         datapos = 0;
349 }
350
351
352 /* flexerror - report an error message and terminate */
353
354 void flexerror (msg)
355      const char *msg;
356 {
357         fprintf (stderr, "%s: %s\n", program_name, msg);
358         flexend (1);
359 }
360
361
362 /* flexfatal - report a fatal error message and terminate */
363
364 void flexfatal (msg)
365      const char *msg;
366 {
367         fprintf (stderr, _("%s: fatal internal error, %s\n"),
368                  program_name, msg);
369         FLEX_EXIT (1);
370 }
371
372
373 /* htoi - convert a hexadecimal digit string to an integer value */
374
375 int htoi (str)
376      Char str[];
377 {
378         unsigned int result;
379
380         (void) sscanf ((char *) str, "%x", &result);
381
382         return result;
383 }
384
385
386 /* lerrif - report an error message formatted with one integer argument */
387
388 void lerrif (msg, arg)
389      const char *msg;
390      int arg;
391 {
392         char    errmsg[MAXLINE];
393
394         snprintf (errmsg, sizeof(errmsg), msg, arg);
395         flexerror (errmsg);
396 }
397
398
399 /* lerrsf - report an error message formatted with one string argument */
400
401 void lerrsf (msg, arg)
402         const char *msg, arg[];
403 {
404         char    errmsg[MAXLINE];
405
406         snprintf (errmsg, sizeof(errmsg)-1, msg, arg);
407         errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */
408         flexerror (errmsg);
409 }
410
411
412 /* lerrsf_fatal - as lerrsf, but call flexfatal */
413
414 void lerrsf_fatal (msg, arg)
415         const char *msg, arg[];
416 {
417         char    errmsg[MAXLINE];
418
419         snprintf (errmsg, sizeof(errmsg)-1, msg, arg);
420         errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */
421         flexfatal (errmsg);
422 }
423
424
425 /* line_directive_out - spit out a "#line" statement */
426
427 void line_directive_out (output_file, do_infile)
428      FILE   *output_file;
429      int do_infile;
430 {
431         char    directive[MAXLINE], filename[MAXLINE];
432         char   *s1, *s2, *s3;
433         static const char *line_fmt = "#line %d \"%s\"\n";
434
435         if (!gen_line_dirs)
436                 return;
437
438         s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
439
440         if (do_infile && !s1)
441         s1 = "<stdin>";
442     
443         s2 = filename;
444         s3 = &filename[sizeof (filename) - 2];
445
446         while (s2 < s3 && *s1) {
447                 if (*s1 == '\\')
448                         /* Escape the '\' */
449                         *s2++ = '\\';
450
451                 *s2++ = *s1++;
452         }
453
454         *s2 = '\0';
455
456         if (do_infile)
457                 snprintf (directive, sizeof(directive), line_fmt, linenum, filename);
458         else {
459                 snprintf (directive, sizeof(directive), line_fmt, 0, filename);
460         }
461
462         /* If output_file is nil then we should put the directive in
463          * the accumulated actions.
464          */
465         if (output_file) {
466                 fputs (directive, output_file);
467         }
468         else
469                 add_action (directive);
470 }
471
472
473 /* mark_defs1 - mark the current position in the action array as
474  *               representing where the user's section 1 definitions end
475  *               and the prolog begins
476  */
477 void mark_defs1 ()
478 {
479         defs1_offset = 0;
480         action_array[action_index++] = '\0';
481         action_offset = prolog_offset = action_index;
482         action_array[action_index] = '\0';
483 }
484
485
486 /* mark_prolog - mark the current position in the action array as
487  *               representing the end of the action prolog
488  */
489 void mark_prolog ()
490 {
491         action_array[action_index++] = '\0';
492         action_offset = action_index;
493         action_array[action_index] = '\0';
494 }
495
496
497 /* mk2data - generate a data statement for a two-dimensional array
498  *
499  * Generates a data statement initializing the current 2-D array to "value".
500  */
501 void mk2data (value)
502      int value;
503 {
504         /* short circuit any output */
505         if (!gentables)
506                 return;
507
508         if (datapos >= NUMDATAITEMS) {
509                 outc (',');
510                 dataflush ();
511         }
512
513         if (datapos == 0)
514                 /* Indent. */
515                 out ("    ");
516
517         else
518                 outc (',');
519
520         ++datapos;
521
522         out_dec ("%5d", value);
523 }
524
525
526 /* mkdata - generate a data statement
527  *
528  * Generates a data statement initializing the current array element to
529  * "value".
530  */
531 void mkdata (value)
532      int value;
533 {
534         /* short circuit any output */
535         if (!gentables)
536                 return;
537
538         if (datapos >= NUMDATAITEMS) {
539                 outc (',');
540                 dataflush ();
541         }
542
543         if (datapos == 0)
544                 /* Indent. */
545                 out ("    ");
546         else
547                 outc (',');
548
549         ++datapos;
550
551         out_dec ("%5d", value);
552 }
553
554
555 /* myctoi - return the integer represented by a string of digits */
556
557 int myctoi (array)
558      const char *array;
559 {
560         int     val = 0;
561
562         (void) sscanf (array, "%d", &val);
563
564         return val;
565 }
566
567
568 /* myesc - return character corresponding to escape sequence */
569
570 Char myesc (array)
571      Char array[];
572 {
573         Char    c, esc_char;
574
575         switch (array[1]) {
576         case 'b':
577                 return '\b';
578         case 'f':
579                 return '\f';
580         case 'n':
581                 return '\n';
582         case 'r':
583                 return '\r';
584         case 't':
585                 return '\t';
586
587 #if defined (__STDC__)
588         case 'a':
589                 return '\a';
590         case 'v':
591                 return '\v';
592 #else
593         case 'a':
594                 return '\007';
595         case 'v':
596                 return '\013';
597 #endif
598
599         case '0':
600         case '1':
601         case '2':
602         case '3':
603         case '4':
604         case '5':
605         case '6':
606         case '7':
607                 {               /* \<octal> */
608                         int     sptr = 1;
609
610                         while (isascii (array[sptr]) &&
611                                isdigit (array[sptr]))
612                                 /* Don't increment inside loop control
613                                  * because if isdigit() is a macro it might
614                                  * expand into multiple increments ...
615                                  */
616                                 ++sptr;
617
618                         c = array[sptr];
619                         array[sptr] = '\0';
620
621                         esc_char = otoi (array + 1);
622
623                         array[sptr] = c;
624
625                         return esc_char;
626                 }
627
628         case 'x':
629                 {               /* \x<hex> */
630                         int     sptr = 2;
631
632                         while (isascii (array[sptr]) &&
633                                isxdigit (array[sptr]))
634                                 /* Don't increment inside loop control
635                                  * because if isdigit() is a macro it might
636                                  * expand into multiple increments ...
637                                  */
638                                 ++sptr;
639
640                         c = array[sptr];
641                         array[sptr] = '\0';
642
643                         esc_char = htoi (array + 2);
644
645                         array[sptr] = c;
646
647                         return esc_char;
648                 }
649
650         default:
651                 return array[1];
652         }
653 }
654
655
656 /* otoi - convert an octal digit string to an integer value */
657
658 int otoi (str)
659      Char str[];
660 {
661         unsigned int result;
662
663         (void) sscanf ((char *) str, "%o", &result);
664         return result;
665 }
666
667
668 /* out - various flavors of outputing a (possibly formatted) string for the
669  *       generated scanner, keeping track of the line count.
670  */
671
672 void out (str)
673      const char *str;
674 {
675         fputs (str, stdout);
676 }
677
678 void out_dec (fmt, n)
679      const char *fmt;
680      int n;
681 {
682         fprintf (stdout, fmt, n);
683 }
684
685 void out_dec2 (fmt, n1, n2)
686      const char *fmt;
687      int n1, n2;
688 {
689         fprintf (stdout, fmt, n1, n2);
690 }
691
692 void out_hex (fmt, x)
693      const char *fmt;
694      unsigned int x;
695 {
696         fprintf (stdout, fmt, x);
697 }
698
699 void out_str (fmt, str)
700      const char *fmt, str[];
701 {
702         fprintf (stdout,fmt, str);
703 }
704
705 void out_str3 (fmt, s1, s2, s3)
706      const char *fmt, s1[], s2[], s3[];
707 {
708         fprintf (stdout,fmt, s1, s2, s3);
709 }
710
711 void out_str_dec (fmt, str, n)
712      const char *fmt, str[];
713      int n;
714 {
715         fprintf (stdout,fmt, str, n);
716 }
717
718 void outc (c)
719      int c;
720 {
721         fputc (c, stdout);
722 }
723
724 void outn (str)
725      const char *str;
726 {
727         fputs (str,stdout);
728     fputc('\n',stdout);
729 }
730
731 /** Print "m4_define( [[def]], [[val]])m4_dnl\n".
732  * @param def The m4 symbol to define.
733  * @param val The definition; may be NULL.
734  * @return buf
735  */
736 void out_m4_define (const char* def, const char* val)
737 {
738     const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
739     fprintf(stdout, fmt, def, val?val:"");
740 }
741
742
743 /* readable_form - return the the human-readable form of a character
744  *
745  * The returned string is in static storage.
746  */
747
748 char   *readable_form (c)
749      register int c;
750 {
751         static char rform[10];
752
753         if ((c >= 0 && c < 32) || c >= 127) {
754                 switch (c) {
755                 case '\b':
756                         return "\\b";
757                 case '\f':
758                         return "\\f";
759                 case '\n':
760                         return "\\n";
761                 case '\r':
762                         return "\\r";
763                 case '\t':
764                         return "\\t";
765
766 #if defined (__STDC__)
767                 case '\a':
768                         return "\\a";
769                 case '\v':
770                         return "\\v";
771 #endif
772
773                 default:
774                         snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c);
775                         return rform;
776                 }
777         }
778
779         else if (c == ' ')
780                 return "' '";
781
782         else {
783                 rform[0] = c;
784                 rform[1] = '\0';
785
786                 return rform;
787         }
788 }
789
790
791 /* reallocate_array - increase the size of a dynamic array */
792
793 void   *reallocate_array (array, size, element_size)
794      void   *array;
795      int size;
796      size_t element_size;
797 {
798         register void *new_array;
799         size_t  num_bytes = element_size * size;
800
801         new_array = flex_realloc (array, num_bytes);
802         if (!new_array)
803                 flexfatal (_("attempt to increase array size failed"));
804
805         return new_array;
806 }
807
808
809 /* skelout - write out one section of the skeleton file
810  *
811  * Description
812  *    Copies skelfile or skel array to stdout until a line beginning with
813  *    "%%" or EOF is found.
814  */
815 void skelout ()
816 {
817         char    buf_storage[MAXLINE];
818         char   *buf = buf_storage;
819         bool   do_copy = true;
820
821     /* "reset" the state by clearing the buffer and pushing a '1' */
822     if(sko_len > 0)
823         sko_peek(&do_copy);
824     sko_len = 0;
825     sko_push(do_copy=true);
826
827
828         /* Loop pulling lines either from the skelfile, if we're using
829          * one, or from the skel[] array.
830          */
831         while (skelfile ?
832                (fgets (buf, MAXLINE, skelfile) != NULL) :
833                ((buf = (char *) skel[skel_ind++]) != 0)) {
834
835                 if (skelfile)
836                         chomp (buf);
837
838                 /* copy from skel array */
839                 if (buf[0] == '%') {    /* control line */
840                         /* print the control line as a comment. */
841                         if (ddebug && buf[1] != '#') {
842                                 if (buf[strlen (buf) - 1] == '\\')
843                                         out_str ("/* %s */\\\n", buf);
844                                 else
845                                         out_str ("/* %s */\n", buf);
846                         }
847
848                         /* We've been accused of using cryptic markers in the skel.
849                          * So we'll use emacs-style-hyphenated-commands.
850              * We might consider a hash if this if-else-if-else
851              * chain gets too large.
852                          */
853 #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
854
855                         if (buf[1] == '%') {
856                                 /* %% is a break point for skelout() */
857                                 return;
858                         }
859             else if (cmd_match (CMD_PUSH)){
860                 sko_push(do_copy);
861                 if(ddebug){
862                     out_str("/*(state = (%s) */",do_copy?"true":"false");
863                 }
864                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
865             }
866             else if (cmd_match (CMD_POP)){
867                 sko_pop(&do_copy);
868                 if(ddebug){
869                     out_str("/*(state = (%s) */",do_copy?"true":"false");
870                 }
871                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
872             }
873             else if (cmd_match (CMD_IF_REENTRANT)){
874                 sko_push(do_copy);
875                 do_copy = reentrant && do_copy;
876             }
877             else if (cmd_match (CMD_IF_NOT_REENTRANT)){
878                 sko_push(do_copy);
879                 do_copy = !reentrant && do_copy;
880             }
881             else if (cmd_match(CMD_IF_BISON_BRIDGE)){
882                 sko_push(do_copy);
883                 do_copy = bison_bridge_lval && do_copy;
884             }
885             else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){
886                 sko_push(do_copy);
887                 do_copy = !bison_bridge_lval && do_copy;
888             }
889             else if (cmd_match (CMD_ENDIF)){
890                 sko_pop(&do_copy);
891             }
892                         else if (cmd_match (CMD_IF_TABLES_SER)) {
893                 do_copy = do_copy && tablesext;
894                         }
895                         else if (cmd_match (CMD_TABLES_YYDMAP)) {
896                                 if (tablesext && yydmap_buf.elts)
897                                         outn ((char *) (yydmap_buf.elts));
898                         }
899             else if (cmd_match (CMD_DEFINE_YYTABLES)) {
900                 out_str("#define YYTABLES_NAME \"%s\"\n",
901                         tablesname?tablesname:"yytables");
902             }
903                         else if (cmd_match (CMD_IF_CPP_ONLY)) {
904                                 /* only for C++ */
905                 sko_push(do_copy);
906                                 do_copy = C_plus_plus;
907                         }
908                         else if (cmd_match (CMD_IF_C_ONLY)) {
909                                 /* %- only for C */
910                 sko_push(do_copy);
911                                 do_copy = !C_plus_plus;
912                         }
913                         else if (cmd_match (CMD_IF_C_OR_CPP)) {
914                                 /* %* for C and C++ */
915                 sko_push(do_copy);
916                                 do_copy = true;
917                         }
918                         else if (cmd_match (CMD_NOT_FOR_HEADER)) {
919                                 /* %c begin linkage-only (non-header) code. */
920                                 OUT_BEGIN_CODE ();
921                         }
922                         else if (cmd_match (CMD_OK_FOR_HEADER)) {
923                                 /* %e end linkage-only code. */
924                                 OUT_END_CODE ();
925                         }
926                         else if (buf[1] == '#') {
927                                 /* %# a comment in the skel. ignore. */
928                         }
929                         else {
930                                 flexfatal (_("bad line in skeleton file"));
931                         }
932                 }
933
934                 else if (do_copy) 
935             outn (buf);
936         }                       /* end while */
937 }
938
939
940 /* transition_struct_out - output a yy_trans_info structure
941  *
942  * outputs the yy_trans_info structure with the two elements, element_v and
943  * element_n.  Formats the output with spaces and carriage returns.
944  */
945
946 void transition_struct_out (element_v, element_n)
947      int element_v, element_n;
948 {
949
950         /* short circuit any output */
951         if (!gentables)
952                 return;
953
954         out_dec2 (" {%4d,%4d },", element_v, element_n);
955
956         datapos += TRANS_STRUCT_PRINT_LENGTH;
957
958         if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
959                 outc ('\n');
960
961                 if (++dataline % 10 == 0)
962                         outc ('\n');
963
964                 datapos = 0;
965         }
966 }
967
968
969 /* The following is only needed when building flex's parser using certain
970  * broken versions of bison.
971  */
972 void   *yy_flex_xmalloc (size)
973      int size;
974 {
975         void   *result = flex_alloc ((size_t) size);
976
977         if (!result)
978                 flexfatal (_
979                            ("memory allocation failed in yy_flex_xmalloc()"));
980
981         return result;
982 }
983
984
985 /* zero_out - set a region of memory to 0
986  *
987  * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero.
988  */
989
990 void zero_out (region_ptr, size_in_bytes)
991      char   *region_ptr;
992      size_t size_in_bytes;
993 {
994         register char *rp, *rp_end;
995
996         rp = region_ptr;
997         rp_end = region_ptr + size_in_bytes;
998
999         while (rp < rp_end)
1000                 *rp++ = 0;
1001 }
1002
1003 /* Remove all '\n' and '\r' characters, if any, from the end of str.
1004  * str can be any null-terminated string, or NULL.
1005  * returns str. */
1006 char   *chomp (str)
1007      char   *str;
1008 {
1009         char   *p = str;
1010
1011         if (!str || !*str)      /* s is null or empty string */
1012                 return str;
1013
1014         /* find end of string minus one */
1015         while (*p)
1016                 ++p;
1017         --p;
1018
1019         /* eat newlines */
1020         while (p >= str && (*p == '\r' || *p == '\n'))
1021                 *p-- = 0;
1022         return str;
1023 }