xref: /dragonfly/contrib/flex/src/misc.c (revision 388e4ddaf1c230f115961bdb4bad6a8d3e017c93)
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 #include "flexdef.h"
34 #include "tables.h"
35 
36 #define CMD_IF_TABLES_SER    "%if-tables-serialization"
37 #define CMD_TABLES_YYDMAP    "%tables-yydmap"
38 #define CMD_DEFINE_YYTABLES  "%define-yytables"
39 #define CMD_IF_CPP_ONLY      "%if-c++-only"
40 #define CMD_IF_C_ONLY        "%if-c-only"
41 #define CMD_IF_C_OR_CPP      "%if-c-or-c++"
42 #define CMD_NOT_FOR_HEADER   "%not-for-header"
43 #define CMD_OK_FOR_HEADER    "%ok-for-header"
44 #define CMD_PUSH             "%push"
45 #define CMD_POP              "%pop"
46 #define CMD_IF_REENTRANT     "%if-reentrant"
47 #define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
48 #define CMD_IF_BISON_BRIDGE  "%if-bison-bridge"
49 #define CMD_IF_NOT_BISON_BRIDGE  "%if-not-bison-bridge"
50 #define CMD_ENDIF            "%endif"
51 
52 /* we allow the skeleton to push and pop. */
53 struct sko_state {
54     bool dc; /**< do_copy */
55 };
56 static struct sko_state *sko_stack=0;
57 static int sko_len=0,sko_sz=0;
sko_push(bool dc)58 static void sko_push(bool dc)
59 {
60     if(!sko_stack){
61         sko_sz = 1;
62         sko_stack = malloc(sizeof(struct sko_state) * (size_t) sko_sz);
63         if (!sko_stack)
64             flexfatal(_("allocation of sko_stack failed"));
65         sko_len = 0;
66     }
67     if(sko_len >= sko_sz){
68         sko_sz *= 2;
69         sko_stack = realloc(sko_stack,
70                               sizeof(struct sko_state) * (size_t) sko_sz);
71     }
72 
73     /* initialize to zero and push */
74     sko_stack[sko_len].dc = dc;
75     sko_len++;
76 }
sko_peek(bool * dc)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 }
sko_pop(bool * dc)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. */
action_define(const char * defname,int value)93 void action_define (const char *defname, int value)
94 {
95           char    buf[MAXLINE];
96           char   *cpy;
97 
98           if ((int) strlen (defname) > MAXLINE / 2) {
99                     format_pinpoint_message (_
100                                                    ("name \"%s\" ridiculously long"),
101                                                    defname);
102                     return;
103           }
104 
105           snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value);
106           add_action (buf);
107 
108           /* track #defines so we can undef them when we're done. */
109           cpy = xstrdup(defname);
110           buf_append (&defs_buf, &cpy, 1);
111 }
112 
113 /* Append "new_text" to the running buffer. */
add_action(const char * new_text)114 void add_action (const char *new_text)
115 {
116           int     len = (int) strlen (new_text);
117 
118           while (len + action_index >= action_size - 10 /* slop */ ) {
119                     int     new_size = action_size * 2;
120 
121                     if (new_size <= 0)
122                               /* Increase just a little, to try to avoid overflow
123                                * on 16-bit machines.
124                                */
125                               action_size += action_size / 8;
126                     else
127                               action_size = new_size;
128 
129                     action_array =
130                               reallocate_character_array (action_array,
131                                                                 action_size);
132           }
133 
134           strcpy (&action_array[action_index], new_text);
135 
136           action_index += len;
137 }
138 
139 
140 /* allocate_array - allocate memory for an integer array of the given size */
141 
allocate_array(int size,size_t element_size)142 void   *allocate_array (int size, size_t element_size)
143 {
144           void *mem;
145 #if HAVE_REALLOCARRAY
146           /* reallocarray has built-in overflow detection */
147           mem = reallocarray(NULL, (size_t) size, element_size);
148 #else
149           size_t num_bytes = (size_t) size * element_size;
150           mem = (size && SIZE_MAX / (size_t) size < element_size) ? NULL :
151                     malloc(num_bytes);
152 #endif
153           if (!mem)
154                     flexfatal (_
155                                  ("memory allocation failed in allocate_array()"));
156 
157           return mem;
158 }
159 
160 
161 /* all_lower - true if a string is all lower-case */
162 
all_lower(char * str)163 int all_lower (char *str)
164 {
165           while (*str) {
166                     if (!isascii ((unsigned char) * str) || !islower ((unsigned char) * str))
167                               return 0;
168                     ++str;
169           }
170 
171           return 1;
172 }
173 
174 
175 /* all_upper - true if a string is all upper-case */
176 
all_upper(char * str)177 int all_upper (char *str)
178 {
179           while (*str) {
180                     if (!isascii ((unsigned char) * str) || !isupper ((unsigned char) * str))
181                               return 0;
182                     ++str;
183           }
184 
185           return 1;
186 }
187 
188 
189 /* intcmp - compares two integers for use by qsort. */
190 
intcmp(const void * a,const void * b)191 int intcmp (const void *a, const void *b)
192 {
193   return *(const int *) a - *(const int *) b;
194 }
195 
196 
197 /* check_char - checks a character to make sure it's within the range
198  *                  we're expecting.  If not, generates fatal error message
199  *                  and exits.
200  */
201 
check_char(int c)202 void check_char (int c)
203 {
204           if (c >= CSIZE)
205                     lerr (_("bad character '%s' detected in check_char()"),
206                               readable_form (c));
207 
208           if (c >= csize)
209                     lerr (_
210                               ("scanner requires -8 flag to use the character %s"),
211                               readable_form (c));
212 }
213 
214 
215 
216 /* clower - replace upper-case letter to lower-case */
217 
clower(int c)218 unsigned char clower (int c)
219 {
220           return (unsigned char) ((isascii (c) && isupper (c)) ? tolower (c) : c);
221 }
222 
223 
xstrdup(const char * s)224 char *xstrdup(const char *s)
225 {
226           char *s2;
227 
228           if ((s2 = strdup(s)) == NULL)
229                     flexfatal (_("memory allocation failure in xstrdup()"));
230 
231           return s2;
232 }
233 
234 
235 /* cclcmp - compares two characters for use by qsort with '\0' sorting last. */
236 
cclcmp(const void * a,const void * b)237 int cclcmp (const void *a, const void *b)
238 {
239   if (!*(const unsigned char *) a)
240           return 1;
241   else
242           if (!*(const unsigned char *) b)
243             return - 1;
244           else
245             return *(const unsigned char *) a - *(const unsigned char *) b;
246 }
247 
248 
249 /* dataend - finish up a block of data declarations */
250 
dataend(void)251 void dataend (void)
252 {
253           /* short circuit any output */
254           if (gentables) {
255 
256                     if (datapos > 0)
257                               dataflush ();
258 
259                     /* add terminator for initialization; { for vi */
260                     outn ("    } ;\n");
261           }
262           dataline = 0;
263           datapos = 0;
264 }
265 
266 
267 /* dataflush - flush generated data statements */
268 
dataflush(void)269 void dataflush (void)
270 {
271           /* short circuit any output */
272           if (!gentables)
273                     return;
274 
275           outc ('\n');
276 
277           if (++dataline >= NUMDATALINES) {
278                     /* Put out a blank line so that the table is grouped into
279                      * large blocks that enable the user to find elements easily.
280                      */
281                     outc ('\n');
282                     dataline = 0;
283           }
284 
285           /* Reset the number of characters written on the current line. */
286           datapos = 0;
287 }
288 
289 
290 /* flexerror - report an error message and terminate */
291 
flexerror(const char * msg)292 void flexerror (const char *msg)
293 {
294           fprintf (stderr, "%s: %s\n", program_name, msg);
295           flexend (1);
296 }
297 
298 
299 /* flexfatal - report a fatal error message and terminate */
300 
flexfatal(const char * msg)301 void flexfatal (const char *msg)
302 {
303           fprintf (stderr, _("%s: fatal internal error, %s\n"),
304                      program_name, msg);
305           FLEX_EXIT (1);
306 }
307 
308 
309 /* lerr - report an error message */
310 
lerr(const char * msg,...)311 void lerr (const char *msg, ...)
312 {
313           char    errmsg[MAXLINE];
314           va_list args;
315 
316           va_start(args, msg);
317           vsnprintf (errmsg, sizeof(errmsg), msg, args);
318           va_end(args);
319           flexerror (errmsg);
320 }
321 
322 
323 /* lerr_fatal - as lerr, but call flexfatal */
324 
lerr_fatal(const char * msg,...)325 void lerr_fatal (const char *msg, ...)
326 {
327           char    errmsg[MAXLINE];
328           va_list args;
329           va_start(args, msg);
330 
331           vsnprintf (errmsg, sizeof(errmsg), msg, args);
332           va_end(args);
333           flexfatal (errmsg);
334 }
335 
336 
337 /* line_directive_out - spit out a "#line" statement */
338 
line_directive_out(FILE * output_file,int do_infile)339 void line_directive_out (FILE *output_file, int do_infile)
340 {
341           char    directive[MAXLINE], filename[MAXLINE];
342           char   *s1, *s2, *s3;
343           static const char line_fmt[] = "#line %d \"%s\"\n";
344 
345           if (!gen_line_dirs)
346                     return;
347 
348           s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
349 
350           if (do_infile && !s1)
351         s1 = "<stdin>";
352 
353           s2 = filename;
354           s3 = &filename[sizeof (filename) - 2];
355 
356           while (s2 < s3 && *s1) {
357                     if (*s1 == '\\' || *s1 == '"')
358                               /* Escape the '\' or '"' */
359                               *s2++ = '\\';
360 
361                     *s2++ = *s1++;
362           }
363 
364           *s2 = '\0';
365 
366           if (do_infile)
367                     snprintf (directive, sizeof(directive), line_fmt, linenum, filename);
368           else {
369                     snprintf (directive, sizeof(directive), line_fmt, 0, filename);
370           }
371 
372           /* If output_file is nil then we should put the directive in
373            * the accumulated actions.
374            */
375           if (output_file) {
376                     fputs (directive, output_file);
377           }
378           else
379                     add_action (directive);
380 }
381 
382 
383 /* mark_defs1 - mark the current position in the action array as
384  *               representing where the user's section 1 definitions end
385  *                   and the prolog begins
386  */
mark_defs1(void)387 void mark_defs1 (void)
388 {
389           defs1_offset = 0;
390           action_array[action_index++] = '\0';
391           action_offset = prolog_offset = action_index;
392           action_array[action_index] = '\0';
393 }
394 
395 
396 /* mark_prolog - mark the current position in the action array as
397  *               representing the end of the action prolog
398  */
mark_prolog(void)399 void mark_prolog (void)
400 {
401           action_array[action_index++] = '\0';
402           action_offset = action_index;
403           action_array[action_index] = '\0';
404 }
405 
406 
407 /* mk2data - generate a data statement for a two-dimensional array
408  *
409  * Generates a data statement initializing the current 2-D array to "value".
410  */
mk2data(int value)411 void mk2data (int value)
412 {
413           /* short circuit any output */
414           if (!gentables)
415                     return;
416 
417           if (datapos >= NUMDATAITEMS) {
418                     outc (',');
419                     dataflush ();
420           }
421 
422           if (datapos == 0)
423                     /* Indent. */
424                     out ("    ");
425 
426           else
427                     outc (',');
428 
429           ++datapos;
430 
431           out_dec ("%5d", value);
432 }
433 
434 
435 /* mkdata - generate a data statement
436  *
437  * Generates a data statement initializing the current array element to
438  * "value".
439  */
mkdata(int value)440 void mkdata (int value)
441 {
442           /* short circuit any output */
443           if (!gentables)
444                     return;
445 
446           if (datapos >= NUMDATAITEMS) {
447                     outc (',');
448                     dataflush ();
449           }
450 
451           if (datapos == 0)
452                     /* Indent. */
453                     out ("    ");
454           else
455                     outc (',');
456 
457           ++datapos;
458 
459           out_dec ("%5d", value);
460 }
461 
462 
463 /* myctoi - return the integer represented by a string of digits */
464 
myctoi(const char * array)465 int myctoi (const char *array)
466 {
467           int     val = 0;
468 
469           (void) sscanf (array, "%d", &val);
470 
471           return val;
472 }
473 
474 
475 /* myesc - return character corresponding to escape sequence */
476 
myesc(unsigned char array[])477 unsigned char myesc (unsigned char array[])
478 {
479           unsigned char    c, esc_char;
480 
481           switch (array[1]) {
482           case 'b':
483                     return '\b';
484           case 'f':
485                     return '\f';
486           case 'n':
487                     return '\n';
488           case 'r':
489                     return '\r';
490           case 't':
491                     return '\t';
492           case 'a':
493                     return '\a';
494           case 'v':
495                     return '\v';
496           case '0':
497           case '1':
498           case '2':
499           case '3':
500           case '4':
501           case '5':
502           case '6':
503           case '7':
504                     {                   /* \<octal> */
505                               int     sptr = 1;
506 
507                               while (sptr <= 3 &&
508                                array[sptr] >= '0' && array[sptr] <= '7') {
509                                         ++sptr;
510                               }
511 
512                               c = array[sptr];
513                               array[sptr] = '\0';
514 
515                               esc_char = (unsigned char) strtoul (array + 1, NULL, 8);
516 
517                               array[sptr] = c;
518 
519                               return esc_char;
520                     }
521 
522           case 'x':
523                     {                   /* \x<hex> */
524                               int     sptr = 2;
525 
526                               while (sptr <= 3 && isxdigit (array[sptr])) {
527                                         /* Don't increment inside loop control
528                                          * because if isxdigit() is a macro it might
529                                          * expand into multiple increments ...
530                                          */
531                                         ++sptr;
532                               }
533 
534                               c = array[sptr];
535                               array[sptr] = '\0';
536 
537                               esc_char = (unsigned char) strtoul (array + 2, NULL, 16);
538 
539                               array[sptr] = c;
540 
541                               return esc_char;
542                     }
543 
544           default:
545                     return array[1];
546           }
547 }
548 
549 
550 /* out - various flavors of outputing a (possibly formatted) string for the
551  *         generated scanner, keeping track of the line count.
552  */
553 
out(const char * str)554 void out (const char *str)
555 {
556           fputs (str, stdout);
557 }
558 
out_dec(const char * fmt,int n)559 void out_dec (const char *fmt, int n)
560 {
561           fprintf (stdout, fmt, n);
562 }
563 
out_dec2(const char * fmt,int n1,int n2)564 void out_dec2 (const char *fmt, int n1, int n2)
565 {
566           fprintf (stdout, fmt, n1, n2);
567 }
568 
out_hex(const char * fmt,unsigned int x)569 void out_hex (const char *fmt, unsigned int x)
570 {
571           fprintf (stdout, fmt, x);
572 }
573 
out_str(const char * fmt,const char str[])574 void out_str (const char *fmt, const char str[])
575 {
576           fprintf (stdout,fmt, str);
577 }
578 
out_str3(const char * fmt,const char s1[],const char s2[],const char s3[])579 void out_str3 (const char *fmt, const char s1[], const char s2[], const char s3[])
580 {
581           fprintf (stdout,fmt, s1, s2, s3);
582 }
583 
out_str_dec(const char * fmt,const char str[],int n)584 void out_str_dec (const char *fmt, const char str[], int n)
585 {
586           fprintf (stdout,fmt, str, n);
587 }
588 
outc(int c)589 void outc (int c)
590 {
591           fputc (c, stdout);
592 }
593 
outn(const char * str)594 void outn (const char *str)
595 {
596           fputs (str,stdout);
597     fputc('\n',stdout);
598 }
599 
600 /** Print "m4_define( [[def]], [[val]])m4_dnl\n".
601  * @param def The m4 symbol to define.
602  * @param val The definition; may be NULL.
603  */
out_m4_define(const char * def,const char * val)604 void out_m4_define (const char* def, const char* val)
605 {
606     const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
607     fprintf(stdout, fmt, def, val?val:"");
608 }
609 
610 
611 /* readable_form - return the the human-readable form of a character
612  *
613  * The returned string is in static storage.
614  */
615 
readable_form(int c)616 char   *readable_form (int c)
617 {
618           static char rform[20];
619 
620           if ((c >= 0 && c < 32) || c >= 127) {
621                     switch (c) {
622                     case '\b':
623                               return "\\b";
624                     case '\f':
625                               return "\\f";
626                     case '\n':
627                               return "\\n";
628                     case '\r':
629                               return "\\r";
630                     case '\t':
631                               return "\\t";
632                     case '\a':
633                               return "\\a";
634                     case '\v':
635                               return "\\v";
636                     default:
637                               if(trace_hex)
638                                         snprintf (rform, sizeof(rform), "\\x%.2x", (unsigned int) c);
639                               else
640                                         snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c);
641                               return rform;
642                     }
643           }
644 
645           else if (c == ' ')
646                     return "' '";
647 
648           else {
649                     rform[0] = (char) c;
650                     rform[1] = '\0';
651 
652                     return rform;
653           }
654 }
655 
656 
657 /* reallocate_array - increase the size of a dynamic array */
658 
reallocate_array(void * array,int size,size_t element_size)659 void   *reallocate_array (void *array, int size, size_t element_size)
660 {
661           void *new_array;
662 #if HAVE_REALLOCARRAY
663           /* reallocarray has built-in overflow detection */
664           new_array = reallocarray(array, (size_t) size, element_size);
665 #else
666           size_t num_bytes = (size_t) size * element_size;
667           new_array = (size && SIZE_MAX / (size_t) size < element_size) ? NULL :
668                     realloc(array, num_bytes);
669 #endif
670           if (!new_array)
671                     flexfatal (_("attempt to increase array size failed"));
672 
673           return new_array;
674 }
675 
676 
677 /* skelout - write out one section of the skeleton file
678  *
679  * Description
680  *    Copies skelfile or skel array to stdout until a line beginning with
681  *    "%%" or EOF is found.
682  */
skelout(void)683 void skelout (void)
684 {
685           char    buf_storage[MAXLINE];
686           char   *buf = buf_storage;
687           bool   do_copy = true;
688 
689     /* "reset" the state by clearing the buffer and pushing a '1' */
690     if(sko_len > 0)
691         sko_peek(&do_copy);
692     sko_len = 0;
693     sko_push(do_copy=true);
694 
695 
696           /* Loop pulling lines either from the skelfile, if we're using
697            * one, or from the skel[] array.
698            */
699           while (skelfile ?
700                  (fgets (buf, MAXLINE, skelfile) != NULL) :
701                  ((buf = (char *) skel[skel_ind++]) != 0)) {
702 
703                     if (skelfile)
704                               chomp (buf);
705 
706                     /* copy from skel array */
707                     if (buf[0] == '%') {          /* control line */
708                               /* print the control line as a comment. */
709                               if (ddebug && buf[1] != '#') {
710                                         if (buf[strlen (buf) - 1] == '\\')
711                                                   out_str ("/* %s */\\\n", buf);
712                                         else
713                                                   out_str ("/* %s */\n", buf);
714                               }
715 
716                               /* We've been accused of using cryptic markers in the skel.
717                                * So we'll use emacs-style-hyphenated-commands.
718              * We might consider a hash if this if-else-if-else
719              * chain gets too large.
720                                */
721 #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
722 
723                               if (buf[1] == '%') {
724                                         /* %% is a break point for skelout() */
725                                         return;
726                               }
727             else if (cmd_match (CMD_PUSH)){
728                 sko_push(do_copy);
729                 if(ddebug){
730                     out_str("/*(state = (%s) */",do_copy?"true":"false");
731                 }
732                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
733             }
734             else if (cmd_match (CMD_POP)){
735                 sko_pop(&do_copy);
736                 if(ddebug){
737                     out_str("/*(state = (%s) */",do_copy?"true":"false");
738                 }
739                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
740             }
741             else if (cmd_match (CMD_IF_REENTRANT)){
742                 sko_push(do_copy);
743                 do_copy = reentrant && do_copy;
744             }
745             else if (cmd_match (CMD_IF_NOT_REENTRANT)){
746                 sko_push(do_copy);
747                 do_copy = !reentrant && do_copy;
748             }
749             else if (cmd_match(CMD_IF_BISON_BRIDGE)){
750                 sko_push(do_copy);
751                 do_copy = bison_bridge_lval && do_copy;
752             }
753             else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){
754                 sko_push(do_copy);
755                 do_copy = !bison_bridge_lval && do_copy;
756             }
757             else if (cmd_match (CMD_ENDIF)){
758                 sko_pop(&do_copy);
759             }
760                               else if (cmd_match (CMD_IF_TABLES_SER)) {
761                 do_copy = do_copy && tablesext;
762                               }
763                               else if (cmd_match (CMD_TABLES_YYDMAP)) {
764                                         if (tablesext && yydmap_buf.elts)
765                                                   outn ((char *) (yydmap_buf.elts));
766                               }
767             else if (cmd_match (CMD_DEFINE_YYTABLES)) {
768                 out_str("#define YYTABLES_NAME \"%s\"\n",
769                         tablesname?tablesname:"yytables");
770             }
771                               else if (cmd_match (CMD_IF_CPP_ONLY)) {
772                                         /* only for C++ */
773                 sko_push(do_copy);
774                                         do_copy = C_plus_plus;
775                               }
776                               else if (cmd_match (CMD_IF_C_ONLY)) {
777                                         /* %- only for C */
778                 sko_push(do_copy);
779                                         do_copy = !C_plus_plus;
780                               }
781                               else if (cmd_match (CMD_IF_C_OR_CPP)) {
782                                         /* %* for C and C++ */
783                 sko_push(do_copy);
784                                         do_copy = true;
785                               }
786                               else if (cmd_match (CMD_NOT_FOR_HEADER)) {
787                                         /* %c begin linkage-only (non-header) code. */
788                                         OUT_BEGIN_CODE ();
789                               }
790                               else if (cmd_match (CMD_OK_FOR_HEADER)) {
791                                         /* %e end linkage-only code. */
792                                         OUT_END_CODE ();
793                               }
794                               else {
795                                         flexfatal (_("bad line in skeleton file"));
796                               }
797                     }
798 
799                     else if (do_copy)
800             outn (buf);
801           }                             /* end while */
802 }
803 
804 
805 /* transition_struct_out - output a yy_trans_info structure
806  *
807  * outputs the yy_trans_info structure with the two elements, element_v and
808  * element_n.  Formats the output with spaces and carriage returns.
809  */
810 
transition_struct_out(int element_v,int element_n)811 void transition_struct_out (int element_v, int element_n)
812 {
813 
814           /* short circuit any output */
815           if (!gentables)
816                     return;
817 
818           out_dec2 (" {%4d,%4d },", element_v, element_n);
819 
820           datapos += TRANS_STRUCT_PRINT_LENGTH;
821 
822           if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
823                     outc ('\n');
824 
825                     if (++dataline % 10 == 0)
826                               outc ('\n');
827 
828                     datapos = 0;
829           }
830 }
831 
832 
833 /* The following is only needed when building flex's parser using certain
834  * broken versions of bison.
835  *
836  * XXX: this is should go soon
837  */
yy_flex_xmalloc(int size)838 void   *yy_flex_xmalloc (int size)
839 {
840           void   *result;
841 
842           result = malloc((size_t) size);
843           if (!result)
844                     flexfatal (_
845                                  ("memory allocation failed in yy_flex_xmalloc()"));
846 
847           return result;
848 }
849 
850 
851 /* Remove all '\n' and '\r' characters, if any, from the end of str.
852  * str can be any null-terminated string, or NULL.
853  * returns str. */
chomp(char * str)854 char   *chomp (char *str)
855 {
856           char   *p = str;
857 
858           if (!str || !*str)  /* s is null or empty string */
859                     return str;
860 
861           /* find end of string minus one */
862           while (*p)
863                     ++p;
864           --p;
865 
866           /* eat newlines */
867           while (p >= str && (*p == '\r' || *p == '\n'))
868                     *p-- = 0;
869           return str;
870 }
871