xref: /netbsd-src/external/bsd/flex/dist/src/misc.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: misc.c,v 1.3 2017/01/02 17:45:27 christos Exp $	*/
2 
3 /* misc - miscellaneous flex routines */
4 
5 /*  Copyright (c) 1990 The Regents of the University of California. */
6 /*  All rights reserved. */
7 
8 /*  This code is derived from software contributed to Berkeley by */
9 /*  Vern Paxson. */
10 
11 /*  The United States Government has rights in this work pursuant */
12 /*  to contract no. DE-AC03-76SF00098 between the United States */
13 /*  Department of Energy and the University of California. */
14 
15 /*  This file is part of flex. */
16 
17 /*  Redistribution and use in source and binary forms, with or without */
18 /*  modification, are permitted provided that the following conditions */
19 /*  are met: */
20 
21 /*  1. Redistributions of source code must retain the above copyright */
22 /*     notice, this list of conditions and the following disclaimer. */
23 /*  2. Redistributions in binary form must reproduce the above copyright */
24 /*     notice, this list of conditions and the following disclaimer in the */
25 /*     documentation and/or other materials provided with the distribution. */
26 
27 /*  Neither the name of the University nor the names of its contributors */
28 /*  may be used to endorse or promote products derived from this software */
29 /*  without specific prior written permission. */
30 
31 /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
32 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
33 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
34 /*  PURPOSE. */
35 #include "flexdef.h"
36 __RCSID("$NetBSD: misc.c,v 1.3 2017/01/02 17:45:27 christos Exp $");
37 
38 #include "tables.h"
39 #include <stdarg.h>
40 
41 #define CMD_IF_TABLES_SER    "%if-tables-serialization"
42 #define CMD_TABLES_YYDMAP    "%tables-yydmap"
43 #define CMD_DEFINE_YYTABLES  "%define-yytables"
44 #define CMD_IF_CPP_ONLY      "%if-c++-only"
45 #define CMD_IF_C_ONLY        "%if-c-only"
46 #define CMD_IF_C_OR_CPP      "%if-c-or-c++"
47 #define CMD_NOT_FOR_HEADER   "%not-for-header"
48 #define CMD_OK_FOR_HEADER    "%ok-for-header"
49 #define CMD_PUSH             "%push"
50 #define CMD_POP              "%pop"
51 #define CMD_IF_REENTRANT     "%if-reentrant"
52 #define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
53 #define CMD_IF_BISON_BRIDGE  "%if-bison-bridge"
54 #define CMD_IF_NOT_BISON_BRIDGE  "%if-not-bison-bridge"
55 #define CMD_ENDIF            "%endif"
56 
57 /* we allow the skeleton to push and pop. */
58 struct sko_state {
59     bool dc; /**< do_copy */
60 };
61 static struct sko_state *sko_stack=0;
62 static int sko_len=0,sko_sz=0;
63 static void sko_push(bool dc)
64 {
65     if(!sko_stack){
66         sko_sz = 1;
67         sko_stack = malloc(sizeof(struct sko_state) * (size_t) sko_sz);
68         if (!sko_stack)
69             flexfatal(_("allocation of sko_stack failed"));
70         sko_len = 0;
71     }
72     if(sko_len >= sko_sz){
73         sko_sz *= 2;
74         sko_stack = realloc(sko_stack,
75 			sizeof(struct sko_state) * (size_t) sko_sz);
76     }
77 
78     /* initialize to zero and push */
79     sko_stack[sko_len].dc = dc;
80     sko_len++;
81 }
82 static void sko_peek(bool *dc)
83 {
84     if(sko_len <= 0)
85         flex_die("peek attempt when sko stack is empty");
86     if(dc)
87         *dc = sko_stack[sko_len-1].dc;
88 }
89 static void sko_pop(bool* dc)
90 {
91     sko_peek(dc);
92     sko_len--;
93     if(sko_len < 0)
94         flex_die("popped too many times in skeleton.");
95 }
96 
97 /* Append "#define defname value\n" to the running buffer. */
98 void action_define (const char *defname, int value)
99 {
100 	char    buf[MAXLINE];
101 	char   *cpy;
102 
103 	if ((int) strlen (defname) > MAXLINE / 2) {
104 		format_pinpoint_message (_
105 					 ("name \"%s\" ridiculously long"),
106 					 defname);
107 		return;
108 	}
109 
110 	snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value);
111 	add_action (buf);
112 
113 	/* track #defines so we can undef them when we're done. */
114 	cpy = xstrdup(defname);
115 	buf_append (&defs_buf, &cpy, 1);
116 }
117 
118 /* Append "new_text" to the running buffer. */
119 void add_action (const char *new_text)
120 {
121 	int     len = (int) strlen (new_text);
122 
123 	while (len + action_index >= action_size - 10 /* slop */ ) {
124 		int     new_size = action_size * 2;
125 
126 		if (new_size <= 0)
127 			/* Increase just a little, to try to avoid overflow
128 			 * on 16-bit machines.
129 			 */
130 			action_size += action_size / 8;
131 		else
132 			action_size = new_size;
133 
134 		action_array =
135 			reallocate_character_array (action_array,
136 						    action_size);
137 	}
138 
139 	strcpy (&action_array[action_index], new_text);
140 
141 	action_index += len;
142 }
143 
144 
145 /* allocate_array - allocate memory for an integer array of the given size */
146 
147 void   *allocate_array (int size, size_t element_size)
148 {
149 	void *mem;
150 	size_t  num_bytes = element_size * (size_t) size;
151 
152 	mem = malloc(num_bytes);
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 
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 
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 
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 
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 
218 unsigned char clower (int c)
219 {
220 	return (unsigned char) ((isascii (c) && isupper (c)) ? tolower (c) : c);
221 }
222 
223 
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 
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 
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 
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 
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 
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 /* htoui - convert a hexadecimal digit string to an unsigned integer value */
310 
311 unsigned int htoui (unsigned char str[])
312 {
313 	unsigned int result;
314 
315 	(void) sscanf ((char *) str, "%x", &result);
316 
317 	return result;
318 }
319 
320 
321 /* lerr - report an error message */
322 
323 void lerr (const char *msg, ...)
324 {
325 	char    errmsg[MAXLINE];
326 	va_list args;
327 
328 	va_start(args, msg);
329 	vsnprintf (errmsg, sizeof(errmsg), msg, args);
330 	va_end(args);
331 	flexerror (errmsg);
332 }
333 
334 
335 /* lerr_fatal - as lerr, but call flexfatal */
336 
337 void lerr_fatal (const char *msg, ...)
338 {
339 	char    errmsg[MAXLINE];
340 	va_list args;
341 	va_start(args, msg);
342 
343 	vsnprintf (errmsg, sizeof(errmsg), msg, args);
344 	va_end(args);
345 	flexfatal (errmsg);
346 }
347 
348 
349 /* line_directive_out - spit out a "#line" statement */
350 
351 void line_directive_out (FILE *output_file, int do_infile)
352 {
353 	char    directive[MAXLINE], filename[MAXLINE];
354 	char   *s1, *s2, *s3;
355 	static const char line_fmt[] = "#line %d \"%s\"\n";
356 
357 	if (!gen_line_dirs)
358 		return;
359 
360 	s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
361 
362 	if (do_infile && !s1)
363         s1 = "<stdin>";
364 
365 	s2 = filename;
366 	s3 = &filename[sizeof (filename) - 2];
367 
368 	while (s2 < s3 && *s1) {
369 		if (*s1 == '\\' || *s1 == '"')
370 			/* Escape the '\' or '"' */
371 			*s2++ = '\\';
372 
373 		*s2++ = *s1++;
374 	}
375 
376 	*s2 = '\0';
377 
378 	if (do_infile)
379 		snprintf (directive, sizeof(directive), line_fmt, linenum, filename);
380 	else {
381 		snprintf (directive, sizeof(directive), line_fmt, 0, filename);
382 	}
383 
384 	/* If output_file is nil then we should put the directive in
385 	 * the accumulated actions.
386 	 */
387 	if (output_file) {
388 		fputs (directive, output_file);
389 	}
390 	else
391 		add_action (directive);
392 }
393 
394 
395 /* mark_defs1 - mark the current position in the action array as
396  *               representing where the user's section 1 definitions end
397  *		 and the prolog begins
398  */
399 void mark_defs1 (void)
400 {
401 	defs1_offset = 0;
402 	action_array[action_index++] = '\0';
403 	action_offset = prolog_offset = action_index;
404 	action_array[action_index] = '\0';
405 }
406 
407 
408 /* mark_prolog - mark the current position in the action array as
409  *               representing the end of the action prolog
410  */
411 void mark_prolog (void)
412 {
413 	action_array[action_index++] = '\0';
414 	action_offset = action_index;
415 	action_array[action_index] = '\0';
416 }
417 
418 
419 /* mk2data - generate a data statement for a two-dimensional array
420  *
421  * Generates a data statement initializing the current 2-D array to "value".
422  */
423 void mk2data (int value)
424 {
425 	/* short circuit any output */
426 	if (!gentables)
427 		return;
428 
429 	if (datapos >= NUMDATAITEMS) {
430 		outc (',');
431 		dataflush ();
432 	}
433 
434 	if (datapos == 0)
435 		/* Indent. */
436 		out ("    ");
437 
438 	else
439 		outc (',');
440 
441 	++datapos;
442 
443 	out_dec ("%5d", value);
444 }
445 
446 
447 /* mkdata - generate a data statement
448  *
449  * Generates a data statement initializing the current array element to
450  * "value".
451  */
452 void mkdata (int value)
453 {
454 	/* short circuit any output */
455 	if (!gentables)
456 		return;
457 
458 	if (datapos >= NUMDATAITEMS) {
459 		outc (',');
460 		dataflush ();
461 	}
462 
463 	if (datapos == 0)
464 		/* Indent. */
465 		out ("    ");
466 	else
467 		outc (',');
468 
469 	++datapos;
470 
471 	out_dec ("%5d", value);
472 }
473 
474 
475 /* myctoi - return the integer represented by a string of digits */
476 
477 int myctoi (const char *array)
478 {
479 	int     val = 0;
480 
481 	(void) sscanf (array, "%d", &val);
482 
483 	return val;
484 }
485 
486 
487 /* myesc - return character corresponding to escape sequence */
488 
489 unsigned char myesc (unsigned char array[])
490 {
491 	unsigned char    c, esc_char;
492 
493 	switch (array[1]) {
494 	case 'b':
495 		return '\b';
496 	case 'f':
497 		return '\f';
498 	case 'n':
499 		return '\n';
500 	case 'r':
501 		return '\r';
502 	case 't':
503 		return '\t';
504 	case 'a':
505 		return '\a';
506 	case 'v':
507 		return '\v';
508 	case '0':
509 	case '1':
510 	case '2':
511 	case '3':
512 	case '4':
513 	case '5':
514 	case '6':
515 	case '7':
516 		{		/* \<octal> */
517 			int     sptr = 1;
518 
519 			while (sptr <= 3 &&
520                                isascii (array[sptr]) &&
521 			       isdigit (array[sptr]))
522 				/* Don't increment inside loop control
523 				 * because if isdigit() is a macro it might
524 				 * expand into multiple increments ...
525 				 */
526 				++sptr;
527 
528 			c = array[sptr];
529 			array[sptr] = '\0';
530 
531 			esc_char = (unsigned char) otoui (array + 1);
532 
533 			array[sptr] = c;
534 
535 			return esc_char;
536 		}
537 
538 	case 'x':
539 		{		/* \x<hex> */
540 			int     sptr = 2;
541 
542 			while (isascii (array[sptr]) &&
543 			       isxdigit (array[sptr]))
544 				/* Don't increment inside loop control
545 				 * because if isdigit() is a macro it might
546 				 * expand into multiple increments ...
547 				 */
548 				++sptr;
549 
550 			c = array[sptr];
551 			array[sptr] = '\0';
552 
553 			esc_char = (unsigned char) htoui (array + 2);
554 
555 			array[sptr] = c;
556 
557 			return esc_char;
558 		}
559 
560 	default:
561 		return array[1];
562 	}
563 }
564 
565 
566 /* otoui - convert an octal digit string to an unsigned integer value */
567 
568 unsigned int otoui (unsigned char str[])
569 {
570 	unsigned int result;
571 
572 	(void) sscanf ((char *) str, "%o", &result);
573 	return result;
574 }
575 
576 
577 /* out - various flavors of outputing a (possibly formatted) string for the
578  *	 generated scanner, keeping track of the line count.
579  */
580 
581 void out (const char *str)
582 {
583 	fputs (str, stdout);
584 }
585 
586 void out_dec (const char *fmt, int n)
587 {
588 	fprintf (stdout, fmt, n);
589 }
590 
591 void out_dec2 (const char *fmt, int n1, int n2)
592 {
593 	fprintf (stdout, fmt, n1, n2);
594 }
595 
596 void out_hex (const char *fmt, unsigned int x)
597 {
598 	fprintf (stdout, fmt, x);
599 }
600 
601 void out_str (const char *fmt, const char str[])
602 {
603 	fprintf (stdout,fmt, str);
604 }
605 
606 void out_str3 (const char *fmt, const char s1[], const char s2[], const char s3[])
607 {
608 	fprintf (stdout,fmt, s1, s2, s3);
609 }
610 
611 void out_str_dec (const char *fmt, const char str[], int n)
612 {
613 	fprintf (stdout,fmt, str, n);
614 }
615 
616 void outc (int c)
617 {
618 	fputc (c, stdout);
619 }
620 
621 void outn (const char *str)
622 {
623 	fputs (str,stdout);
624     fputc('\n',stdout);
625 }
626 
627 /** Print "m4_define( [[def]], [[val]])m4_dnl\n".
628  * @param def The m4 symbol to define.
629  * @param val The definition; may be NULL.
630  */
631 void out_m4_define (const char* def, const char* val)
632 {
633     const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
634     fprintf(stdout, fmt, def, val?val:"");
635 }
636 
637 
638 /* readable_form - return the the human-readable form of a character
639  *
640  * The returned string is in static storage.
641  */
642 
643 char   *readable_form (int c)
644 {
645 	static char rform[20];
646 
647 	if ((c >= 0 && c < 32) || c >= 127) {
648 		switch (c) {
649 		case '\b':
650 			return "\\b";
651 		case '\f':
652 			return "\\f";
653 		case '\n':
654 			return "\\n";
655 		case '\r':
656 			return "\\r";
657 		case '\t':
658 			return "\\t";
659 		case '\a':
660 			return "\\a";
661 		case '\v':
662 			return "\\v";
663 		default:
664 			if(trace_hex)
665 				snprintf (rform, sizeof(rform), "\\x%.2x", (unsigned int) c);
666 			else
667 				snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c);
668 			return rform;
669 		}
670 	}
671 
672 	else if (c == ' ')
673 		return "' '";
674 
675 	else {
676 		rform[0] = (char) c;
677 		rform[1] = '\0';
678 
679 		return rform;
680 	}
681 }
682 
683 
684 /* reallocate_array - increase the size of a dynamic array */
685 
686 void   *reallocate_array (void *array, int size, size_t element_size)
687 {
688 	void *new_array;
689 	size_t  num_bytes = element_size * (size_t) size;
690 
691 	new_array = realloc(array, num_bytes);
692 	if (!new_array)
693 		flexfatal (_("attempt to increase array size failed"));
694 
695 	return new_array;
696 }
697 
698 
699 /* skelout - write out one section of the skeleton file
700  *
701  * Description
702  *    Copies skelfile or skel array to stdout until a line beginning with
703  *    "%%" or EOF is found.
704  */
705 void skelout (void)
706 {
707 	char    buf_storage[MAXLINE];
708 	char   *buf = buf_storage;
709 	bool   do_copy = true;
710 
711     /* "reset" the state by clearing the buffer and pushing a '1' */
712     if(sko_len > 0)
713         sko_peek(&do_copy);
714     sko_len = 0;
715     sko_push(do_copy=true);
716 
717 
718 	/* Loop pulling lines either from the skelfile, if we're using
719 	 * one, or from the skel[] array.
720 	 */
721 	while (skelfile ?
722 	       (fgets (buf, MAXLINE, skelfile) != NULL) :
723 	       ((buf = (char *) skel[skel_ind++]) != 0)) {
724 
725 		if (skelfile)
726 			chomp (buf);
727 
728 		/* copy from skel array */
729 		if (buf[0] == '%') {	/* control line */
730 			/* print the control line as a comment. */
731 			if (ddebug && buf[1] != '#') {
732 				if (buf[strlen (buf) - 1] == '\\')
733 					out_str ("/* %s */\\\n", buf);
734 				else
735 					out_str ("/* %s */\n", buf);
736 			}
737 
738 			/* We've been accused of using cryptic markers in the skel.
739 			 * So we'll use emacs-style-hyphenated-commands.
740              * We might consider a hash if this if-else-if-else
741              * chain gets too large.
742 			 */
743 #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
744 
745 			if (buf[1] == '%') {
746 				/* %% is a break point for skelout() */
747 				return;
748 			}
749             else if (cmd_match (CMD_PUSH)){
750                 sko_push(do_copy);
751                 if(ddebug){
752                     out_str("/*(state = (%s) */",do_copy?"true":"false");
753                 }
754                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
755             }
756             else if (cmd_match (CMD_POP)){
757                 sko_pop(&do_copy);
758                 if(ddebug){
759                     out_str("/*(state = (%s) */",do_copy?"true":"false");
760                 }
761                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
762             }
763             else if (cmd_match (CMD_IF_REENTRANT)){
764                 sko_push(do_copy);
765                 do_copy = reentrant && do_copy;
766             }
767             else if (cmd_match (CMD_IF_NOT_REENTRANT)){
768                 sko_push(do_copy);
769                 do_copy = !reentrant && do_copy;
770             }
771             else if (cmd_match(CMD_IF_BISON_BRIDGE)){
772                 sko_push(do_copy);
773                 do_copy = bison_bridge_lval && do_copy;
774             }
775             else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){
776                 sko_push(do_copy);
777                 do_copy = !bison_bridge_lval && do_copy;
778             }
779             else if (cmd_match (CMD_ENDIF)){
780                 sko_pop(&do_copy);
781             }
782 			else if (cmd_match (CMD_IF_TABLES_SER)) {
783                 do_copy = do_copy && tablesext;
784 			}
785 			else if (cmd_match (CMD_TABLES_YYDMAP)) {
786 				if (tablesext && yydmap_buf.elts)
787 					outn ((char *) (yydmap_buf.elts));
788 			}
789             else if (cmd_match (CMD_DEFINE_YYTABLES)) {
790                 out_str("#define YYTABLES_NAME \"%s\"\n",
791                         tablesname?tablesname:"yytables");
792             }
793 			else if (cmd_match (CMD_IF_CPP_ONLY)) {
794 				/* only for C++ */
795                 sko_push(do_copy);
796 				do_copy = C_plus_plus;
797 			}
798 			else if (cmd_match (CMD_IF_C_ONLY)) {
799 				/* %- only for C */
800                 sko_push(do_copy);
801 				do_copy = !C_plus_plus;
802 			}
803 			else if (cmd_match (CMD_IF_C_OR_CPP)) {
804 				/* %* for C and C++ */
805                 sko_push(do_copy);
806 				do_copy = true;
807 			}
808 			else if (cmd_match (CMD_NOT_FOR_HEADER)) {
809 				/* %c begin linkage-only (non-header) code. */
810 				OUT_BEGIN_CODE ();
811 			}
812 			else if (cmd_match (CMD_OK_FOR_HEADER)) {
813 				/* %e end linkage-only code. */
814 				OUT_END_CODE ();
815 			}
816 			else if (buf[1] == '#') {
817 				/* %# a comment in the skel. ignore. */
818 			}
819 			else {
820 				flexfatal (_("bad line in skeleton file"));
821 			}
822 		}
823 
824 		else if (do_copy)
825             outn (buf);
826 	}			/* end while */
827 }
828 
829 
830 /* transition_struct_out - output a yy_trans_info structure
831  *
832  * outputs the yy_trans_info structure with the two elements, element_v and
833  * element_n.  Formats the output with spaces and carriage returns.
834  */
835 
836 void transition_struct_out (int element_v, int element_n)
837 {
838 
839 	/* short circuit any output */
840 	if (!gentables)
841 		return;
842 
843 	out_dec2 (" {%4d,%4d },", element_v, element_n);
844 
845 	datapos += TRANS_STRUCT_PRINT_LENGTH;
846 
847 	if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
848 		outc ('\n');
849 
850 		if (++dataline % 10 == 0)
851 			outc ('\n');
852 
853 		datapos = 0;
854 	}
855 }
856 
857 
858 /* The following is only needed when building flex's parser using certain
859  * broken versions of bison.
860  *
861  * XXX: this is should go soon
862  */
863 void   *yy_flex_xmalloc (int size)
864 {
865 	void   *result;
866 
867 	result = malloc((size_t) size);
868 	if (!result)
869 		flexfatal (_
870 			   ("memory allocation failed in yy_flex_xmalloc()"));
871 
872 	return result;
873 }
874 
875 
876 /* Remove all '\n' and '\r' characters, if any, from the end of str.
877  * str can be any null-terminated string, or NULL.
878  * returns str. */
879 char   *chomp (char *str)
880 {
881 	char   *p = str;
882 
883 	if (!str || !*str)	/* s is null or empty string */
884 		return str;
885 
886 	/* find end of string minus one */
887 	while (*p)
888 		++p;
889 	--p;
890 
891 	/* eat newlines */
892 	while (p >= str && (*p == '\r' || *p == '\n'))
893 		*p-- = 0;
894 	return str;
895 }
896