GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/lex/misc.c Lines: 210 343 61.2 %
Date: 2016-12-06 Branches: 111 234 47.4 %

Line Branch Exec Source
1
/*	$OpenBSD: misc.c,v 1.19 2015/11/19 23:34:56 mmcc 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
36
#include "flexdef.h"
37
#include "tables.h"
38
39
#define CMD_IF_TABLES_SER    "%if-tables-serialization"
40
#define CMD_TABLES_YYDMAP    "%tables-yydmap"
41
#define CMD_DEFINE_YYTABLES  "%define-yytables"
42
#define CMD_IF_CPP_ONLY      "%if-c++-only"
43
#define CMD_IF_C_ONLY        "%if-c-only"
44
#define CMD_IF_C_OR_CPP      "%if-c-or-c++"
45
#define CMD_NOT_FOR_HEADER   "%not-for-header"
46
#define CMD_OK_FOR_HEADER    "%ok-for-header"
47
#define CMD_PUSH             "%push"
48
#define CMD_POP              "%pop"
49
#define CMD_IF_REENTRANT     "%if-reentrant"
50
#define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
51
#define CMD_IF_BISON_BRIDGE  "%if-bison-bridge"
52
#define CMD_IF_NOT_BISON_BRIDGE  "%if-not-bison-bridge"
53
#define CMD_ENDIF            "%endif"
54
55
/* we allow the skeleton to push and pop. */
56
struct sko_state {
57
	bool dc;		/**< do_copy */
58
};
59
static struct sko_state *sko_stack = 0;
60
static int sko_len = 0, sko_sz = 0;
61
static void
62
sko_push(bool dc)
63
600
{
64
600
	if (!sko_stack) {
65
5
		sko_sz = 1;
66
5
		sko_stack = malloc(sizeof(struct sko_state) * sko_sz);
67
5
		if (!sko_stack)
68
			flexfatal(_("allocation of sko_stack failed"));
69
5
		sko_len = 0;
70
	}
71
600
	if (sko_len >= sko_sz) {
72
10
		sko_sz *= 2;
73
10
		sko_stack = realloc(sko_stack, sizeof(struct sko_state) * sko_sz);
74
	}
75
	/* initialize to zero and push */
76
600
	sko_stack[sko_len].dc = dc;
77
600
	sko_len++;
78
600
}
79
static void
80
sko_peek(bool * dc)
81
600
{
82
600
	if (sko_len <= 0)
83
		flex_die("peek attempt when sko stack is empty");
84
600
	if (dc)
85
600
		*dc = sko_stack[sko_len - 1].dc;
86
600
}
87
static void
88
sko_pop(bool * dc)
89
510
{
90
510
	sko_peek(dc);
91
510
	sko_len--;
92
510
	if (sko_len < 0)
93
		flex_die("popped too many times in skeleton.");
94
510
}
95
96
/* Append "#define defname value\n" to the running buffer. */
97
void
98
action_define(defname, value)
99
	const char *defname;
100
	int value;
101
2
{
102
	char buf[MAXLINE];
103
	char *cpy;
104
105
2
	if ((int) strlen(defname) > MAXLINE / 2) {
106
		format_pinpoint_message(_
107
		    ("name \"%s\" ridiculously long"),
108
		    defname);
109
		return;
110
	}
111
2
	snprintf(buf, sizeof(buf), "#define %s %d\n", defname, value);
112
2
	add_action(buf);
113
114
	/* track #defines so we can undef them when we're done. */
115
2
	cpy = copy_string(defname);
116
2
	buf_append(&defs_buf, &cpy, 1);
117
}
118
119
120
/** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer.
121
 *  @param defname The macro name.
122
 *  @param value The macro value, can be NULL, which is the same as the empty string.
123
 */
124
void
125
action_m4_define(const char *defname, const char *value)
126
{
127
	char buf[MAXLINE];
128
129
	flexfatal("DO NOT USE THIS FUNCTION!");
130
131
	if ((int) strlen(defname) > MAXLINE / 2) {
132
		format_pinpoint_message(_
133
		    ("name \"%s\" ridiculously long"),
134
		    defname);
135
		return;
136
	}
137
	snprintf(buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value ? value : "");
138
	add_action(buf);
139
}
140
141
/* Append "new_text" to the running buffer. */
142
void
143
add_action(new_text)
144
	const char *new_text;
145
13778
{
146
13778
	int len = strlen(new_text);
147
148
27564
	while (len + action_index >= action_size - 10 /* slop */ ) {
149
8
		int new_size = action_size * 2;
150
151
8
		if (new_size <= 0)
152
			/*
153
			 * Increase just a little, to try to avoid overflow
154
			 * on 16-bit machines.
155
			 */
156
			action_size += action_size / 8;
157
		else
158
8
			action_size = new_size;
159
160
8
		action_array =
161
		    reallocate_character_array(action_array,
162
		    action_size);
163
	}
164
165
13778
	strlcpy(&action_array[action_index], new_text,
166
	    action_size - action_index);
167
168
13778
	action_index += len;
169
13778
}
170
171
172
/* allocate_array - allocate memory for an integer array of the given size */
173
174
void *
175
allocate_array(size, element_size)
176
	int size;
177
	size_t element_size;
178
1254
{
179
	void *mem;
180
1254
	size_t num_bytes = element_size * size;
181
182
1254
	mem = malloc(num_bytes);
183
1254
	if (!mem)
184
		flexfatal(_
185
		    ("memory allocation failed in allocate_array()"));
186
187
1254
	return mem;
188
}
189
190
191
/* all_lower - true if a string is all lower-case */
192
193
int
194
all_lower(str)
195
	char *str;
196
9
{
197
72
	while (*str) {
198

54
		if (!isascii((u_char) * str) || !islower((u_char) * str))
199
			return 0;
200
54
		++str;
201
	}
202
203
9
	return 1;
204
}
205
206
207
/* all_upper - true if a string is all upper-case */
208
209
int
210
all_upper(str)
211
	char *str;
212
1
{
213
8
	while (*str) {
214

6
		if (!isascii((u_char) * str) || !isupper((u_char) * str))
215
			return 0;
216
6
		++str;
217
	}
218
219
1
	return 1;
220
}
221
222
223
/* intcmp - compares two integers for use by qsort. */
224
225
int
226
intcmp(const void *a, const void *b)
227
40154
{
228
40154
	return *(const int *) a - *(const int *) b;
229
}
230
231
232
/* check_char - checks a character to make sure it's within the range
233
 *		we're expecting.  If not, generates fatal error message
234
 *		and exits.
235
 */
236
237
void
238
check_char(c)
239
	int c;
240
2400
{
241
2400
	if (c >= CSIZE)
242
		lerrsf(_("bad character '%s' detected in check_char()"),
243
		    readable_form(c));
244
245
2400
	if (c >= csize)
246
		lerrsf(_
247
		    ("scanner requires -8 flag to use the character %s"),
248
		    readable_form(c));
249
2400
}
250
251
252
253
/* clower - replace upper-case letter to lower-case */
254
255
u_char
256
clower(c)
257
	int c;
258
{
259
	return (u_char) ((isascii(c) && isupper(c)) ? tolower(c) : c);
260
}
261
262
263
/* copy_string - returns a dynamically allocated copy of a string */
264
265
char *
266
copy_string(str)
267
	const char *str;
268
38
{
269
	const char *c1;
270
	char *c2;
271
	char *copy;
272
	unsigned int size;
273
274
	/* find length */
275
38
	for (c1 = str; *c1; ++c1);
276
277
38
	size = (c1 - str + 1) * sizeof(char);
278
279
38
	copy = (char *) malloc(size);
280
281
38
	if (copy == NULL)
282
		flexfatal(_("dynamic memory failure in copy_string()"));
283
284
38
	for (c2 = copy; (*c2++ = *str++) != 0;);
285
286
38
	return copy;
287
}
288
289
290
/* copy_unsigned_string -
291
 *    returns a dynamically allocated copy of a (potentially) unsigned string
292
 */
293
294
u_char *
295
copy_unsigned_string(str)
296
	u_char *str;
297
51
{
298
	u_char *c;
299
	u_char *copy;
300
301
	/* find length */
302
51
	for (c = str; *c; ++c);
303
304
51
	copy = allocate_Character_array(c - str + 1);
305
306
51
	for (c = copy; (*c++ = *str++) != 0;);
307
308
51
	return copy;
309
}
310
311
312
/* cclcmp - compares two characters for use by qsort with '\0' sorting last. */
313
314
int
315
cclcmp(const void *a, const void *b)
316
2017
{
317
2017
	if (!*(const u_char *) a)
318
		return 1;
319
2017
	else if (!*(const u_char *) b)
320
		return -1;
321
	else
322
2017
		return *(const u_char *) a - *(const u_char *) b;
323
}
324
325
326
/* dataend - finish up a block of data declarations */
327
328
void
329
dataend()
330
36
{
331
	/* short circuit any output */
332
36
	if (gentables) {
333
334
36
		if (datapos > 0)
335
36
			dataflush();
336
337
		/* add terminator for initialization; { for vi */
338
36
		outn("    } ;\n");
339
	}
340
36
	dataline = 0;
341
36
	datapos = 0;
342
36
}
343
344
345
/* dataflush - flush generated data statements */
346
347
void
348
dataflush()
349
1059
{
350
	/* short circuit any output */
351
1059
	if (!gentables)
352
		return;
353
354
1059
	outc('\n');
355
356
1059
	if (++dataline >= NUMDATALINES) {
357
		/*
358
		 * Put out a blank line so that the table is grouped into
359
		 * large blocks that enable the user to find elements easily.
360
		 */
361
93
		outc('\n');
362
93
		dataline = 0;
363
	}
364
	/* Reset the number of characters written on the current line. */
365
1059
	datapos = 0;
366
}
367
368
369
/* flexerror - report an error message and terminate */
370
371
void
372
flexerror(msg)
373
	const char *msg;
374
{
375
	fprintf(stderr, "%s: %s\n", program_name, msg);
376
	flexend(1);
377
}
378
379
380
/* flexfatal - report a fatal error message and terminate */
381
382
void
383
flexfatal(msg)
384
	const char *msg;
385
{
386
	fprintf(stderr, _("%s: fatal internal error, %s\n"),
387
	    program_name, msg);
388
	FLEX_EXIT(1);
389
}
390
391
392
/* htoi - convert a hexadecimal digit string to an integer value */
393
394
int
395
htoi(str)
396
	u_char str[];
397
{
398
	unsigned int result;
399
400
	(void) sscanf((char *) str, "%x", &result);
401
402
	return result;
403
}
404
405
406
/* lerrif - report an error message formatted with one integer argument */
407
408
void
409
lerrif(msg, arg)
410
	const char *msg;
411
	int arg;
412
{
413
	char errmsg[MAXLINE];
414
415
	snprintf(errmsg, sizeof(errmsg), msg, arg);
416
	flexerror(errmsg);
417
}
418
419
420
/* lerrsf - report an error message formatted with one string argument */
421
422
void
423
lerrsf(msg, arg)
424
	const char *msg, arg[];
425
{
426
	char errmsg[MAXLINE];
427
428
	snprintf(errmsg, sizeof(errmsg) - 1, msg, arg);
429
	errmsg[sizeof(errmsg) - 1] = 0;	/* ensure NULL termination */
430
	flexerror(errmsg);
431
}
432
433
434
/* lerrsf_fatal - as lerrsf, but call flexfatal */
435
436
void
437
lerrsf_fatal(msg, arg)
438
	const char *msg, arg[];
439
{
440
	char errmsg[MAXLINE];
441
442
	snprintf(errmsg, sizeof(errmsg) - 1, msg, arg);
443
	errmsg[sizeof(errmsg) - 1] = 0;	/* ensure NULL termination */
444
	flexfatal(errmsg);
445
}
446
447
448
/* line_directive_out - spit out a "#line" statement */
449
450
void
451
line_directive_out(output_file, do_infile)
452
	FILE *output_file;
453
	int do_infile;
454
217
{
455
	char directive[MAXLINE], filename[MAXLINE];
456
	char *s1, *s2, *s3;
457
	static const char *line_fmt = "#line %d \"%s\"\n";
458
459
217
	if (!gen_line_dirs)
460
		return;
461
462
217
	s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
463
464
217
	if (do_infile && !s1)
465
		s1 = "<stdin>";
466
467
217
	s2 = filename;
468
217
	s3 = &filename[sizeof(filename) - 2];
469
470

3288
	while (s2 < s3 && *s1) {
471
2854
		if (*s1 == '\\')
472
			/* Escape the '\' */
473
			*s2++ = '\\';
474
475
2854
		*s2++ = *s1++;
476
	}
477
478
217
	*s2 = '\0';
479
480
217
	if (do_infile)
481
202
		snprintf(directive, sizeof(directive), line_fmt, linenum, filename);
482
	else {
483
15
		snprintf(directive, sizeof(directive), line_fmt, 0, filename);
484
	}
485
486
	/*
487
	 * If output_file is nil then we should put the directive in the
488
	 * accumulated actions.
489
	 */
490
217
	if (output_file) {
491
20
		fputs(directive, output_file);
492
	} else
493
197
		add_action(directive);
494
}
495
496
497
/* mark_defs1 - mark the current position in the action array as
498
 *               representing where the user's section 1 definitions end
499
 *		 and the prolog begins
500
 */
501
void
502
mark_defs1()
503
5
{
504
5
	defs1_offset = 0;
505
5
	action_array[action_index++] = '\0';
506
5
	action_offset = prolog_offset = action_index;
507
5
	action_array[action_index] = '\0';
508
5
}
509
510
511
/* mark_prolog - mark the current position in the action array as
512
 *               representing the end of the action prolog
513
 */
514
void
515
mark_prolog()
516
5
{
517
5
	action_array[action_index++] = '\0';
518
5
	action_offset = action_index;
519
5
	action_array[action_index] = '\0';
520
5
}
521
522
523
/* mk2data - generate a data statement for a two-dimensional array
524
 *
525
 * Generates a data statement initializing the current 2-D array to "value".
526
 */
527
void
528
mk2data(value)
529
	int value;
530
{
531
	/* short circuit any output */
532
	if (!gentables)
533
		return;
534
535
	if (datapos >= NUMDATAITEMS) {
536
		outc(',');
537
		dataflush();
538
	}
539
	if (datapos == 0)
540
		/* Indent. */
541
		out("    ");
542
543
	else
544
		outc(',');
545
546
	++datapos;
547
548
	out_dec("%5d", value);
549
}
550
551
552
/* mkdata - generate a data statement
553
 *
554
 * Generates a data statement initializing the current array element to
555
 * "value".
556
 */
557
void
558
mkdata(value)
559
	int value;
560
10403
{
561
	/* short circuit any output */
562
10403
	if (!gentables)
563
		return;
564
565
10403
	if (datapos >= NUMDATAITEMS) {
566
1023
		outc(',');
567
1023
		dataflush();
568
	}
569
10403
	if (datapos == 0)
570
		/* Indent. */
571
1059
		out("    ");
572
	else
573
9344
		outc(',');
574
575
10403
	++datapos;
576
577
10403
	out_dec("%5d", value);
578
}
579
580
581
/* myctoi - return the integer represented by a string of digits */
582
583
int
584
myctoi(array)
585
	const char *array;
586
{
587
	int val = 0;
588
589
	(void) sscanf(array, "%d", &val);
590
591
	return val;
592
}
593
594
595
/* myesc - return character corresponding to escape sequence */
596
597
u_char
598
myesc(array)
599
	u_char array[];
600
164
{
601
	u_char c, esc_char;
602
603


164
	switch (array[1]) {
604
	case 'b':
605
		return '\b';
606
	case 'f':
607
		return '\f';
608
	case 'n':
609
21
		return '\n';
610
	case 'r':
611
10
		return '\r';
612
	case 't':
613
11
		return '\t';
614
615
#if defined (__STDC__)
616
	case 'a':
617
		return '\a';
618
	case 'v':
619
		return '\v';
620
#else
621
	case 'a':
622
		return '\007';
623
	case 'v':
624
		return '\013';
625
#endif
626
627
	case '0':
628
	case '1':
629
	case '2':
630
	case '3':
631
	case '4':
632
	case '5':
633
	case '6':
634
	case '7':
635
		{		/* \<octal> */
636
			int sptr = 1;
637
638
			while (isascii(array[sptr]) &&
639
			    isdigit(array[sptr]))
640
				/*
641
				 * Don't increment inside loop control
642
				 * because if isdigit() is a macro it might
643
				 * expand into multiple increments ...
644
				 */
645
				++sptr;
646
647
			c = array[sptr];
648
			array[sptr] = '\0';
649
650
			esc_char = otoi(array + 1);
651
652
			array[sptr] = c;
653
654
			return esc_char;
655
		}
656
657
	case 'x':
658
		{		/* \x<hex> */
659
			int sptr = 2;
660
661
			while (isascii(array[sptr]) &&
662
			    isxdigit(array[sptr]))
663
				/*
664
				 * Don't increment inside loop control
665
				 * because if isdigit() is a macro it might
666
				 * expand into multiple increments ...
667
				 */
668
				++sptr;
669
670
			c = array[sptr];
671
			array[sptr] = '\0';
672
673
			esc_char = htoi(array + 2);
674
675
			array[sptr] = c;
676
677
			return esc_char;
678
		}
679
680
	default:
681
122
		return array[1];
682
	}
683
}
684
685
686
/* otoi - convert an octal digit string to an integer value */
687
688
int
689
otoi(str)
690
	u_char str[];
691
{
692
	unsigned int result;
693
694
	(void) sscanf((char *) str, "%o", &result);
695
	return result;
696
}
697
698
699
/* out - various flavors of outputing a (possibly formatted) string for the
700
 *	 generated scanner, keeping track of the line count.
701
 */
702
703
void
704
out(str)
705
	const char *str;
706
1074
{
707
1074
	fputs(str, stdout);
708
1074
}
709
710
void
711
out_dec(fmt, n)
712
	const char *fmt;
713
	int n;
714
10438
{
715
10438
	fprintf(stdout, fmt, n);
716
10438
}
717
718
void
719
out_dec2(fmt, n1, n2)
720
	const char *fmt;
721
	int n1, n2;
722
{
723
	fprintf(stdout, fmt, n1, n2);
724
}
725
726
void
727
out_hex(fmt, x)
728
	const char *fmt;
729
	unsigned int x;
730
{
731
	fprintf(stdout, fmt, x);
732
}
733
734
void
735
out_str(fmt, str)
736
	const char *fmt, str[];
737
32
{
738
32
	fprintf(stdout, fmt, str);
739
32
}
740
741
void
742
out_str3(fmt, s1, s2, s3)
743
	const char *fmt, s1[], s2[], s3[];
744
{
745
	fprintf(stdout, fmt, s1, s2, s3);
746
}
747
748
void
749
out_str_dec(fmt, str, n)
750
	const char *fmt, str[];
751
	int n;
752
36
{
753
36
	fprintf(stdout, fmt, str, n);
754
36
}
755
756
void
757
outc(c)
758
	int c;
759
12566
{
760
12566
	fputc(c, stdout);
761
12566
}
762
763
void
764
outn(str)
765
	const char *str;
766
12371
{
767
12371
	fputs(str, stdout);
768
12371
	fputc('\n', stdout);
769
12371
}
770
771
/** Print "m4_define( [[def]], [[val]])m4_dnl\n".
772
 * @param def The m4 symbol to define.
773
 * @param val The definition; may be NULL.
774
 * @return buf
775
 */
776
void
777
out_m4_define(const char *def, const char *val)
778
1
{
779
1
	const char *fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
780
1
	fprintf(stdout, fmt, def, val ? val : "");
781
1
}
782
783
784
/* readable_form - return the human-readable form of a character
785
 *
786
 * The returned string is in static storage.
787
 */
788
789
char *
790
readable_form(c)
791
	int c;
792
{
793
	static char rform[10];
794
795
	if ((c >= 0 && c < 32) || c >= 127) {
796
		switch (c) {
797
		case '\b':
798
			return "\\b";
799
		case '\f':
800
			return "\\f";
801
		case '\n':
802
			return "\\n";
803
		case '\r':
804
			return "\\r";
805
		case '\t':
806
			return "\\t";
807
808
#if defined (__STDC__)
809
		case '\a':
810
			return "\\a";
811
		case '\v':
812
			return "\\v";
813
#endif
814
815
		default:
816
			snprintf(rform, sizeof(rform), "\\%.3o", (unsigned int) c);
817
			return rform;
818
		}
819
	} else if (c == ' ')
820
		return "' '";
821
822
	else {
823
		rform[0] = c;
824
		rform[1] = '\0';
825
826
		return rform;
827
	}
828
}
829
830
831
/* reallocate_array - increase the size of a dynamic array */
832
833
void *
834
reallocate_array(array, size, element_size)
835
	void *array;
836
	int size;
837
	size_t element_size;
838
28
{
839
	void *new_array;
840
28
	size_t num_bytes = element_size * size;
841
842
28
	new_array = realloc(array, num_bytes);
843
28
	if (!new_array)
844
		flexfatal(_("attempt to increase array size failed"));
845
846
28
	return new_array;
847
}
848
849
850
/* skelout - write out one section of the skeleton file
851
 *
852
 * Description
853
 *    Copies skelfile or skel array to stdout until a line beginning with
854
 *    "%%" or EOF is found.
855
 */
856
void
857
skelout()
858
105
{
859
	char buf_storage[MAXLINE];
860
105
	char *buf = buf_storage;
861
105
	bool do_copy = true;
862
863
	/* "reset" the state by clearing the buffer and pushing a '1' */
864
105
	if (sko_len > 0)
865
90
		sko_peek(&do_copy);
866
105
	sko_len = 0;
867
105
	sko_push(do_copy = true);
868
869
870
	/*
871
	 * Loop pulling lines either from the skelfile, if we're using one,
872
	 * or from the skel[] array.
873
	 */
874

18755
	while (skelfile ?
875
	    (fgets(buf, MAXLINE, skelfile) != NULL) :
876
	    ((buf = (char *) skel[skel_ind++]) != 0)) {
877
878
18645
		if (skelfile)
879
			chomp(buf);
880
881
		/* copy from skel array */
882
18645
		if (buf[0] == '%') {	/* control line */
883
			/* print the control line as a comment. */
884

1695
			if (ddebug && buf[1] != '#') {
885
				if (buf[strlen(buf) - 1] == '\\')
886
					out_str("/* %s */\\\n", buf);
887
				else
888
					out_str("/* %s */\n", buf);
889
			}
890
			/*
891
			 * We've been accused of using cryptic markers in the
892
			 * skel. So we'll use
893
			 * emacs-style-hyphenated-commands. We might consider
894
			 * a hash if this if-else-if-else chain gets too
895
			 * large.
896
			 */
897
#define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
898
899
1695
			if (buf[1] == '%') {
900
				/* %% is a break point for skelout() */
901
100
				return;
902
1595
			} else if (cmd_match(CMD_PUSH)) {
903
				sko_push(do_copy);
904
				if (ddebug) {
905
					out_str("/*(state = (%s) */", do_copy ? "true" : "false");
906
				}
907
				out_str("%s\n", buf[strlen(buf) - 1] == '\\' ? "\\" : "");
908
1595
			} else if (cmd_match(CMD_POP)) {
909
				sko_pop(&do_copy);
910
				if (ddebug) {
911
					out_str("/*(state = (%s) */", do_copy ? "true" : "false");
912
				}
913
				out_str("%s\n", buf[strlen(buf) - 1] == '\\' ? "\\" : "");
914
1595
			} else if (cmd_match(CMD_IF_REENTRANT)) {
915
40
				sko_push(do_copy);
916

40
				do_copy = reentrant && do_copy;
917
1555
			} else if (cmd_match(CMD_IF_NOT_REENTRANT)) {
918
35
				sko_push(do_copy);
919

35
				do_copy = !reentrant && do_copy;
920
1520
			} else if (cmd_match(CMD_IF_BISON_BRIDGE)) {
921
10
				sko_push(do_copy);
922

10
				do_copy = bison_bridge_lval && do_copy;
923
1510
			} else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)) {
924
				sko_push(do_copy);
925
				do_copy = !bison_bridge_lval && do_copy;
926
1510
			} else if (cmd_match(CMD_ENDIF)) {
927
510
				sko_pop(&do_copy);
928
1000
			} else if (cmd_match(CMD_IF_TABLES_SER)) {
929

15
				do_copy = do_copy && tablesext;
930
985
			} else if (cmd_match(CMD_TABLES_YYDMAP)) {
931

5
				if (tablesext && yydmap_buf.elts)
932
					outn((char *) (yydmap_buf.elts));
933
980
			} else if (cmd_match(CMD_DEFINE_YYTABLES)) {
934
5
				out_str("#define YYTABLES_NAME \"%s\"\n",
935
				    tablesname ? tablesname : "yytables");
936
975
			} else if (cmd_match(CMD_IF_CPP_ONLY)) {
937
				/* only for C++ */
938
155
				sko_push(do_copy);
939
155
				do_copy = C_plus_plus;
940
820
			} else if (cmd_match(CMD_IF_C_ONLY)) {
941
				/* %- only for C */
942
235
				sko_push(do_copy);
943
235
				do_copy = !C_plus_plus;
944
585
			} else if (cmd_match(CMD_IF_C_OR_CPP)) {
945
				/* %* for C and C++ */
946
20
				sko_push(do_copy);
947
20
				do_copy = true;
948
565
			} else if (cmd_match(CMD_NOT_FOR_HEADER)) {
949
				/* %c begin linkage-only (non-header) code. */
950
60
				OUT_BEGIN_CODE();
951
505
			} else if (cmd_match(CMD_OK_FOR_HEADER)) {
952
				/* %e end linkage-only code. */
953
60
				OUT_END_CODE();
954
445
			} else if (buf[1] == '#') {
955
				/* %# a comment in the skel. ignore. */
956
			} else {
957
				flexfatal(_("bad line in skeleton file"));
958
			}
959
16950
		} else if (do_copy)
960
11500
			outn(buf);
961
	}			/* end while */
962
}
963
964
965
/* transition_struct_out - output a yy_trans_info structure
966
 *
967
 * outputs the yy_trans_info structure with the two elements, element_v and
968
 * element_n.  Formats the output with spaces and carriage returns.
969
 */
970
971
void
972
transition_struct_out(element_v, element_n)
973
	int element_v, element_n;
974
{
975
976
	/* short circuit any output */
977
	if (!gentables)
978
		return;
979
980
	out_dec2(" {%4d,%4d },", element_v, element_n);
981
982
	datapos += TRANS_STRUCT_PRINT_LENGTH;
983
984
	if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
985
		outc('\n');
986
987
		if (++dataline % 10 == 0)
988
			outc('\n');
989
990
		datapos = 0;
991
	}
992
}
993
994
995
/* The following is only needed when building flex's parser using certain
996
 * broken versions of bison.
997
 */
998
void *
999
yy_flex_xmalloc(size)
1000
	int size;
1001
{
1002
	void *result = malloc((size_t) size);
1003
1004
	if (!result)
1005
		flexfatal(_
1006
		    ("memory allocation failed in yy_flex_xmalloc()"));
1007
1008
	return result;
1009
}
1010
1011
1012
/* Remove all '\n' and '\r' characters, if any, from the end of str.
1013
 * str can be any null-terminated string, or NULL.
1014
 * returns str. */
1015
char *
1016
chomp(str)
1017
	char *str;
1018
{
1019
	char *p = str;
1020
1021
	if (!str || !*str)	/* s is null or empty string */
1022
		return str;
1023
1024
	/* find end of string minus one */
1025
	while (*p)
1026
		++p;
1027
	--p;
1028
1029
	/* eat newlines */
1030
	while (p >= str && (*p == '\r' || *p == '\n'))
1031
		*p-- = 0;
1032
	return str;
1033
}