1228072Sbapt/* misc - miscellaneous flex routines */
2228072Sbapt
3228072Sbapt/*  Copyright (c) 1990 The Regents of the University of California. */
4228072Sbapt/*  All rights reserved. */
5228072Sbapt
6228072Sbapt/*  This code is derived from software contributed to Berkeley by */
7228072Sbapt/*  Vern Paxson. */
8228072Sbapt
9228072Sbapt/*  The United States Government has rights in this work pursuant */
10228072Sbapt/*  to contract no. DE-AC03-76SF00098 between the United States */
11228072Sbapt/*  Department of Energy and the University of California. */
12228072Sbapt
13228072Sbapt/*  This file is part of flex. */
14228072Sbapt
15228072Sbapt/*  Redistribution and use in source and binary forms, with or without */
16228072Sbapt/*  modification, are permitted provided that the following conditions */
17228072Sbapt/*  are met: */
18228072Sbapt
19228072Sbapt/*  1. Redistributions of source code must retain the above copyright */
20228072Sbapt/*     notice, this list of conditions and the following disclaimer. */
21228072Sbapt/*  2. Redistributions in binary form must reproduce the above copyright */
22228072Sbapt/*     notice, this list of conditions and the following disclaimer in the */
23228072Sbapt/*     documentation and/or other materials provided with the distribution. */
24228072Sbapt
25228072Sbapt/*  Neither the name of the University nor the names of its contributors */
26228072Sbapt/*  may be used to endorse or promote products derived from this software */
27228072Sbapt/*  without specific prior written permission. */
28228072Sbapt
29228072Sbapt/*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
30228072Sbapt/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
31228072Sbapt/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
32228072Sbapt/*  PURPOSE. */
33228072Sbapt
34228072Sbapt#include "flexdef.h"
35228072Sbapt#include "tables.h"
36228072Sbapt
37228072Sbapt#define CMD_IF_TABLES_SER    "%if-tables-serialization"
38228072Sbapt#define CMD_TABLES_YYDMAP    "%tables-yydmap"
39228072Sbapt#define CMD_DEFINE_YYTABLES  "%define-yytables"
40228072Sbapt#define CMD_IF_CPP_ONLY      "%if-c++-only"
41228072Sbapt#define CMD_IF_C_ONLY        "%if-c-only"
42228072Sbapt#define CMD_IF_C_OR_CPP      "%if-c-or-c++"
43228072Sbapt#define CMD_NOT_FOR_HEADER   "%not-for-header"
44228072Sbapt#define CMD_OK_FOR_HEADER    "%ok-for-header"
45228072Sbapt#define CMD_PUSH             "%push"
46228072Sbapt#define CMD_POP              "%pop"
47228072Sbapt#define CMD_IF_REENTRANT     "%if-reentrant"
48228072Sbapt#define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
49228072Sbapt#define CMD_IF_BISON_BRIDGE  "%if-bison-bridge"
50228072Sbapt#define CMD_IF_NOT_BISON_BRIDGE  "%if-not-bison-bridge"
51228072Sbapt#define CMD_ENDIF            "%endif"
52228072Sbapt
53228072Sbapt/* we allow the skeleton to push and pop. */
54228072Sbaptstruct sko_state {
55228072Sbapt    bool dc; /**< do_copy */
56228072Sbapt};
57228072Sbaptstatic struct sko_state *sko_stack=0;
58228072Sbaptstatic int sko_len=0,sko_sz=0;
59228072Sbaptstatic void sko_push(bool dc)
60228072Sbapt{
61228072Sbapt    if(!sko_stack){
62228072Sbapt        sko_sz = 1;
63228072Sbapt        sko_stack = (struct sko_state*)flex_alloc(sizeof(struct sko_state)*sko_sz);
64250125Sjkim        if (!sko_stack)
65250125Sjkim            flexfatal(_("allocation of sko_stack failed"));
66228072Sbapt        sko_len = 0;
67228072Sbapt    }
68228072Sbapt    if(sko_len >= sko_sz){
69228072Sbapt        sko_sz *= 2;
70228072Sbapt        sko_stack = (struct sko_state*)flex_realloc(sko_stack,sizeof(struct sko_state)*sko_sz);
71228072Sbapt    }
72228072Sbapt
73228072Sbapt    /* initialize to zero and push */
74228072Sbapt    sko_stack[sko_len].dc = dc;
75228072Sbapt    sko_len++;
76228072Sbapt}
77228072Sbaptstatic void sko_peek(bool *dc)
78228072Sbapt{
79228072Sbapt    if(sko_len <= 0)
80228072Sbapt        flex_die("peek attempt when sko stack is empty");
81228072Sbapt    if(dc)
82228072Sbapt        *dc = sko_stack[sko_len-1].dc;
83228072Sbapt}
84228072Sbaptstatic void sko_pop(bool* dc)
85228072Sbapt{
86228072Sbapt    sko_peek(dc);
87228072Sbapt    sko_len--;
88228072Sbapt    if(sko_len < 0)
89228072Sbapt        flex_die("popped too many times in skeleton.");
90228072Sbapt}
91228072Sbapt
92228072Sbapt/* Append "#define defname value\n" to the running buffer. */
93228072Sbaptvoid action_define (defname, value)
94228072Sbapt     const char *defname;
95228072Sbapt     int value;
96228072Sbapt{
97228072Sbapt	char    buf[MAXLINE];
98228072Sbapt	char   *cpy;
99228072Sbapt
100228072Sbapt	if ((int) strlen (defname) > MAXLINE / 2) {
101228072Sbapt		format_pinpoint_message (_
102228072Sbapt					 ("name \"%s\" ridiculously long"),
103228072Sbapt					 defname);
104228072Sbapt		return;
105228072Sbapt	}
106228072Sbapt
107228072Sbapt	snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value);
108228072Sbapt	add_action (buf);
109228072Sbapt
110228072Sbapt	/* track #defines so we can undef them when we're done. */
111228072Sbapt	cpy = copy_string (defname);
112228072Sbapt	buf_append (&defs_buf, &cpy, 1);
113228072Sbapt}
114228072Sbapt
115228072Sbapt
116250875Sjkim#ifdef notdef
117228072Sbapt/** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer.
118228072Sbapt *  @param defname The macro name.
119228072Sbapt *  @param value The macro value, can be NULL, which is the same as the empty string.
120228072Sbapt */
121228072Sbaptvoid action_m4_define (const char *defname, const char * value)
122228072Sbapt{
123228072Sbapt	char    buf[MAXLINE];
124228072Sbapt
125228072Sbapt    flexfatal ("DO NOT USE THIS FUNCTION!");
126228072Sbapt
127228072Sbapt	if ((int) strlen (defname) > MAXLINE / 2) {
128228072Sbapt		format_pinpoint_message (_
129228072Sbapt					 ("name \"%s\" ridiculously long"),
130228072Sbapt					 defname);
131228072Sbapt		return;
132228072Sbapt	}
133228072Sbapt
134228072Sbapt	snprintf (buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value?value:"");
135228072Sbapt	add_action (buf);
136228072Sbapt}
137250875Sjkim#endif
138228072Sbapt
139228072Sbapt/* Append "new_text" to the running buffer. */
140228072Sbaptvoid add_action (new_text)
141228072Sbapt     const char   *new_text;
142228072Sbapt{
143228072Sbapt	int     len = strlen (new_text);
144228072Sbapt
145228072Sbapt	while (len + action_index >= action_size - 10 /* slop */ ) {
146228072Sbapt		int     new_size = action_size * 2;
147228072Sbapt
148228072Sbapt		if (new_size <= 0)
149228072Sbapt			/* Increase just a little, to try to avoid overflow
150228072Sbapt			 * on 16-bit machines.
151228072Sbapt			 */
152228072Sbapt			action_size += action_size / 8;
153228072Sbapt		else
154228072Sbapt			action_size = new_size;
155228072Sbapt
156228072Sbapt		action_array =
157228072Sbapt			reallocate_character_array (action_array,
158228072Sbapt						    action_size);
159228072Sbapt	}
160228072Sbapt
161228072Sbapt	strcpy (&action_array[action_index], new_text);
162228072Sbapt
163228072Sbapt	action_index += len;
164228072Sbapt}
165228072Sbapt
166228072Sbapt
167228072Sbapt/* allocate_array - allocate memory for an integer array of the given size */
168228072Sbapt
169228072Sbaptvoid   *allocate_array (size, element_size)
170228072Sbapt     int size;
171228072Sbapt     size_t element_size;
172228072Sbapt{
173250874Sjkim	void *mem;
174228072Sbapt	size_t  num_bytes = element_size * size;
175228072Sbapt
176228072Sbapt	mem = flex_alloc (num_bytes);
177228072Sbapt	if (!mem)
178228072Sbapt		flexfatal (_
179228072Sbapt			   ("memory allocation failed in allocate_array()"));
180228072Sbapt
181228072Sbapt	return mem;
182228072Sbapt}
183228072Sbapt
184228072Sbapt
185228072Sbapt/* all_lower - true if a string is all lower-case */
186228072Sbapt
187228072Sbaptint all_lower (str)
188250874Sjkim     char *str;
189228072Sbapt{
190228072Sbapt	while (*str) {
191250125Sjkim		if (!isascii ((Char) * str) || !islower ((Char) * str))
192228072Sbapt			return 0;
193228072Sbapt		++str;
194228072Sbapt	}
195228072Sbapt
196228072Sbapt	return 1;
197228072Sbapt}
198228072Sbapt
199228072Sbapt
200228072Sbapt/* all_upper - true if a string is all upper-case */
201228072Sbapt
202228072Sbaptint all_upper (str)
203250874Sjkim     char *str;
204228072Sbapt{
205228072Sbapt	while (*str) {
206250125Sjkim		if (!isascii ((Char) * str) || !isupper ((Char) * str))
207228072Sbapt			return 0;
208228072Sbapt		++str;
209228072Sbapt	}
210228072Sbapt
211228072Sbapt	return 1;
212228072Sbapt}
213228072Sbapt
214228072Sbapt
215250125Sjkim/* intcmp - compares two integers for use by qsort. */
216228072Sbapt
217250125Sjkimint intcmp (const void *a, const void *b)
218228072Sbapt{
219250125Sjkim  return *(const int *) a - *(const int *) b;
220228072Sbapt}
221228072Sbapt
222228072Sbapt
223228072Sbapt/* check_char - checks a character to make sure it's within the range
224228072Sbapt *		we're expecting.  If not, generates fatal error message
225228072Sbapt *		and exits.
226228072Sbapt */
227228072Sbapt
228228072Sbaptvoid check_char (c)
229228072Sbapt     int c;
230228072Sbapt{
231228072Sbapt	if (c >= CSIZE)
232228072Sbapt		lerrsf (_("bad character '%s' detected in check_char()"),
233228072Sbapt			readable_form (c));
234228072Sbapt
235228072Sbapt	if (c >= csize)
236228072Sbapt		lerrsf (_
237228072Sbapt			("scanner requires -8 flag to use the character %s"),
238228072Sbapt			readable_form (c));
239228072Sbapt}
240228072Sbapt
241228072Sbapt
242228072Sbapt
243228072Sbapt/* clower - replace upper-case letter to lower-case */
244228072Sbapt
245228072SbaptChar clower (c)
246250874Sjkim     int c;
247228072Sbapt{
248228072Sbapt	return (Char) ((isascii (c) && isupper (c)) ? tolower (c) : c);
249228072Sbapt}
250228072Sbapt
251228072Sbapt
252228072Sbapt/* copy_string - returns a dynamically allocated copy of a string */
253228072Sbapt
254228072Sbaptchar   *copy_string (str)
255250874Sjkim     const char *str;
256228072Sbapt{
257250874Sjkim	const char *c1;
258250874Sjkim	char *c2;
259228072Sbapt	char   *copy;
260228072Sbapt	unsigned int size;
261228072Sbapt
262228072Sbapt	/* find length */
263228072Sbapt	for (c1 = str; *c1; ++c1) ;
264228072Sbapt
265228072Sbapt	size = (c1 - str + 1) * sizeof (char);
266228072Sbapt
267228072Sbapt	copy = (char *) flex_alloc (size);
268228072Sbapt
269228072Sbapt	if (copy == NULL)
270228072Sbapt		flexfatal (_("dynamic memory failure in copy_string()"));
271228072Sbapt
272228072Sbapt	for (c2 = copy; (*c2++ = *str++) != 0;) ;
273228072Sbapt
274228072Sbapt	return copy;
275228072Sbapt}
276228072Sbapt
277228072Sbapt
278228072Sbapt/* copy_unsigned_string -
279228072Sbapt *    returns a dynamically allocated copy of a (potentially) unsigned string
280228072Sbapt */
281228072Sbapt
282228072SbaptChar   *copy_unsigned_string (str)
283250874Sjkim     Char *str;
284228072Sbapt{
285250874Sjkim	Char *c;
286228072Sbapt	Char   *copy;
287228072Sbapt
288228072Sbapt	/* find length */
289228072Sbapt	for (c = str; *c; ++c) ;
290228072Sbapt
291228072Sbapt	copy = allocate_Character_array (c - str + 1);
292228072Sbapt
293228072Sbapt	for (c = copy; (*c++ = *str++) != 0;) ;
294228072Sbapt
295228072Sbapt	return copy;
296228072Sbapt}
297228072Sbapt
298228072Sbapt
299250125Sjkim/* cclcmp - compares two characters for use by qsort with '\0' sorting last. */
300228072Sbapt
301250125Sjkimint cclcmp (const void *a, const void *b)
302228072Sbapt{
303250125Sjkim  if (!*(const Char *) a)
304250125Sjkim	return 1;
305250125Sjkim  else
306250125Sjkim	if (!*(const Char *) b)
307250125Sjkim	  return - 1;
308250125Sjkim	else
309250125Sjkim	  return *(const Char *) a - *(const Char *) b;
310228072Sbapt}
311228072Sbapt
312228072Sbapt
313228072Sbapt/* dataend - finish up a block of data declarations */
314228072Sbapt
315228072Sbaptvoid dataend ()
316228072Sbapt{
317228072Sbapt	/* short circuit any output */
318228072Sbapt	if (gentables) {
319228072Sbapt
320228072Sbapt		if (datapos > 0)
321228072Sbapt			dataflush ();
322228072Sbapt
323228072Sbapt		/* add terminator for initialization; { for vi */
324228072Sbapt		outn ("    } ;\n");
325228072Sbapt	}
326228072Sbapt	dataline = 0;
327228072Sbapt	datapos = 0;
328228072Sbapt}
329228072Sbapt
330228072Sbapt
331228072Sbapt/* dataflush - flush generated data statements */
332228072Sbapt
333228072Sbaptvoid dataflush ()
334228072Sbapt{
335228072Sbapt	/* short circuit any output */
336228072Sbapt	if (!gentables)
337228072Sbapt		return;
338228072Sbapt
339228072Sbapt	outc ('\n');
340228072Sbapt
341228072Sbapt	if (++dataline >= NUMDATALINES) {
342228072Sbapt		/* Put out a blank line so that the table is grouped into
343228072Sbapt		 * large blocks that enable the user to find elements easily.
344228072Sbapt		 */
345228072Sbapt		outc ('\n');
346228072Sbapt		dataline = 0;
347228072Sbapt	}
348228072Sbapt
349228072Sbapt	/* Reset the number of characters written on the current line. */
350228072Sbapt	datapos = 0;
351228072Sbapt}
352228072Sbapt
353228072Sbapt
354228072Sbapt/* flexerror - report an error message and terminate */
355228072Sbapt
356228072Sbaptvoid flexerror (msg)
357228072Sbapt     const char *msg;
358228072Sbapt{
359228072Sbapt	fprintf (stderr, "%s: %s\n", program_name, msg);
360228072Sbapt	flexend (1);
361228072Sbapt}
362228072Sbapt
363228072Sbapt
364228072Sbapt/* flexfatal - report a fatal error message and terminate */
365228072Sbapt
366228072Sbaptvoid flexfatal (msg)
367228072Sbapt     const char *msg;
368228072Sbapt{
369228072Sbapt	fprintf (stderr, _("%s: fatal internal error, %s\n"),
370228072Sbapt		 program_name, msg);
371228072Sbapt	FLEX_EXIT (1);
372228072Sbapt}
373228072Sbapt
374228072Sbapt
375228072Sbapt/* htoi - convert a hexadecimal digit string to an integer value */
376228072Sbapt
377228072Sbaptint htoi (str)
378228072Sbapt     Char str[];
379228072Sbapt{
380228072Sbapt	unsigned int result;
381228072Sbapt
382228072Sbapt	(void) sscanf ((char *) str, "%x", &result);
383228072Sbapt
384228072Sbapt	return result;
385228072Sbapt}
386228072Sbapt
387228072Sbapt
388228072Sbapt/* lerrif - report an error message formatted with one integer argument */
389228072Sbapt
390228072Sbaptvoid lerrif (msg, arg)
391228072Sbapt     const char *msg;
392228072Sbapt     int arg;
393228072Sbapt{
394228072Sbapt	char    errmsg[MAXLINE];
395228072Sbapt
396228072Sbapt	snprintf (errmsg, sizeof(errmsg), msg, arg);
397228072Sbapt	flexerror (errmsg);
398228072Sbapt}
399228072Sbapt
400228072Sbapt
401228072Sbapt/* lerrsf - report an error message formatted with one string argument */
402228072Sbapt
403228072Sbaptvoid lerrsf (msg, arg)
404250125Sjkim	const char *msg, arg[];
405228072Sbapt{
406228072Sbapt	char    errmsg[MAXLINE];
407228072Sbapt
408250125Sjkim	snprintf (errmsg, sizeof(errmsg)-1, msg, arg);
409250125Sjkim	errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */
410228072Sbapt	flexerror (errmsg);
411228072Sbapt}
412228072Sbapt
413228072Sbapt
414250125Sjkim/* lerrsf_fatal - as lerrsf, but call flexfatal */
415250125Sjkim
416250125Sjkimvoid lerrsf_fatal (msg, arg)
417250125Sjkim	const char *msg, arg[];
418250125Sjkim{
419250125Sjkim	char    errmsg[MAXLINE];
420250125Sjkim
421250125Sjkim	snprintf (errmsg, sizeof(errmsg)-1, msg, arg);
422250125Sjkim	errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */
423250125Sjkim	flexfatal (errmsg);
424250125Sjkim}
425250125Sjkim
426250125Sjkim
427228072Sbapt/* line_directive_out - spit out a "#line" statement */
428228072Sbapt
429228072Sbaptvoid line_directive_out (output_file, do_infile)
430228072Sbapt     FILE   *output_file;
431228072Sbapt     int do_infile;
432228072Sbapt{
433228072Sbapt	char    directive[MAXLINE], filename[MAXLINE];
434228072Sbapt	char   *s1, *s2, *s3;
435228072Sbapt	static const char *line_fmt = "#line %d \"%s\"\n";
436228072Sbapt
437228072Sbapt	if (!gen_line_dirs)
438228072Sbapt		return;
439228072Sbapt
440228072Sbapt	s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
441228072Sbapt
442228072Sbapt	if (do_infile && !s1)
443228072Sbapt        s1 = "<stdin>";
444228072Sbapt
445228072Sbapt	s2 = filename;
446228072Sbapt	s3 = &filename[sizeof (filename) - 2];
447228072Sbapt
448228072Sbapt	while (s2 < s3 && *s1) {
449228072Sbapt		if (*s1 == '\\')
450228072Sbapt			/* Escape the '\' */
451228072Sbapt			*s2++ = '\\';
452228072Sbapt
453228072Sbapt		*s2++ = *s1++;
454228072Sbapt	}
455228072Sbapt
456228072Sbapt	*s2 = '\0';
457228072Sbapt
458228072Sbapt	if (do_infile)
459228072Sbapt		snprintf (directive, sizeof(directive), line_fmt, linenum, filename);
460228072Sbapt	else {
461250125Sjkim		snprintf (directive, sizeof(directive), line_fmt, 0, filename);
462228072Sbapt	}
463228072Sbapt
464228072Sbapt	/* If output_file is nil then we should put the directive in
465228072Sbapt	 * the accumulated actions.
466228072Sbapt	 */
467228072Sbapt	if (output_file) {
468228072Sbapt		fputs (directive, output_file);
469228072Sbapt	}
470228072Sbapt	else
471228072Sbapt		add_action (directive);
472228072Sbapt}
473228072Sbapt
474228072Sbapt
475228072Sbapt/* mark_defs1 - mark the current position in the action array as
476228072Sbapt *               representing where the user's section 1 definitions end
477228072Sbapt *		 and the prolog begins
478228072Sbapt */
479228072Sbaptvoid mark_defs1 ()
480228072Sbapt{
481228072Sbapt	defs1_offset = 0;
482228072Sbapt	action_array[action_index++] = '\0';
483228072Sbapt	action_offset = prolog_offset = action_index;
484228072Sbapt	action_array[action_index] = '\0';
485228072Sbapt}
486228072Sbapt
487228072Sbapt
488228072Sbapt/* mark_prolog - mark the current position in the action array as
489228072Sbapt *               representing the end of the action prolog
490228072Sbapt */
491228072Sbaptvoid mark_prolog ()
492228072Sbapt{
493228072Sbapt	action_array[action_index++] = '\0';
494228072Sbapt	action_offset = action_index;
495228072Sbapt	action_array[action_index] = '\0';
496228072Sbapt}
497228072Sbapt
498228072Sbapt
499228072Sbapt/* mk2data - generate a data statement for a two-dimensional array
500228072Sbapt *
501228072Sbapt * Generates a data statement initializing the current 2-D array to "value".
502228072Sbapt */
503228072Sbaptvoid mk2data (value)
504228072Sbapt     int value;
505228072Sbapt{
506228072Sbapt	/* short circuit any output */
507228072Sbapt	if (!gentables)
508228072Sbapt		return;
509228072Sbapt
510228072Sbapt	if (datapos >= NUMDATAITEMS) {
511228072Sbapt		outc (',');
512228072Sbapt		dataflush ();
513228072Sbapt	}
514228072Sbapt
515228072Sbapt	if (datapos == 0)
516228072Sbapt		/* Indent. */
517228072Sbapt		out ("    ");
518228072Sbapt
519228072Sbapt	else
520228072Sbapt		outc (',');
521228072Sbapt
522228072Sbapt	++datapos;
523228072Sbapt
524228072Sbapt	out_dec ("%5d", value);
525228072Sbapt}
526228072Sbapt
527228072Sbapt
528228072Sbapt/* mkdata - generate a data statement
529228072Sbapt *
530228072Sbapt * Generates a data statement initializing the current array element to
531228072Sbapt * "value".
532228072Sbapt */
533228072Sbaptvoid mkdata (value)
534228072Sbapt     int value;
535228072Sbapt{
536228072Sbapt	/* short circuit any output */
537228072Sbapt	if (!gentables)
538228072Sbapt		return;
539228072Sbapt
540228072Sbapt	if (datapos >= NUMDATAITEMS) {
541228072Sbapt		outc (',');
542228072Sbapt		dataflush ();
543228072Sbapt	}
544228072Sbapt
545228072Sbapt	if (datapos == 0)
546228072Sbapt		/* Indent. */
547228072Sbapt		out ("    ");
548228072Sbapt	else
549228072Sbapt		outc (',');
550228072Sbapt
551228072Sbapt	++datapos;
552228072Sbapt
553228072Sbapt	out_dec ("%5d", value);
554228072Sbapt}
555228072Sbapt
556228072Sbapt
557228072Sbapt/* myctoi - return the integer represented by a string of digits */
558228072Sbapt
559228072Sbaptint myctoi (array)
560228072Sbapt     const char *array;
561228072Sbapt{
562228072Sbapt	int     val = 0;
563228072Sbapt
564228072Sbapt	(void) sscanf (array, "%d", &val);
565228072Sbapt
566228072Sbapt	return val;
567228072Sbapt}
568228072Sbapt
569228072Sbapt
570228072Sbapt/* myesc - return character corresponding to escape sequence */
571228072Sbapt
572228072SbaptChar myesc (array)
573228072Sbapt     Char array[];
574228072Sbapt{
575228072Sbapt	Char    c, esc_char;
576228072Sbapt
577228072Sbapt	switch (array[1]) {
578228072Sbapt	case 'b':
579228072Sbapt		return '\b';
580228072Sbapt	case 'f':
581228072Sbapt		return '\f';
582228072Sbapt	case 'n':
583228072Sbapt		return '\n';
584228072Sbapt	case 'r':
585228072Sbapt		return '\r';
586228072Sbapt	case 't':
587228072Sbapt		return '\t';
588228072Sbapt
589228072Sbapt#if defined (__STDC__)
590228072Sbapt	case 'a':
591228072Sbapt		return '\a';
592228072Sbapt	case 'v':
593228072Sbapt		return '\v';
594228072Sbapt#else
595228072Sbapt	case 'a':
596228072Sbapt		return '\007';
597228072Sbapt	case 'v':
598228072Sbapt		return '\013';
599228072Sbapt#endif
600228072Sbapt
601228072Sbapt	case '0':
602228072Sbapt	case '1':
603228072Sbapt	case '2':
604228072Sbapt	case '3':
605228072Sbapt	case '4':
606228072Sbapt	case '5':
607228072Sbapt	case '6':
608228072Sbapt	case '7':
609228072Sbapt		{		/* \<octal> */
610228072Sbapt			int     sptr = 1;
611228072Sbapt
612228072Sbapt			while (isascii (array[sptr]) &&
613228072Sbapt			       isdigit (array[sptr]))
614228072Sbapt				/* Don't increment inside loop control
615228072Sbapt				 * because if isdigit() is a macro it might
616228072Sbapt				 * expand into multiple increments ...
617228072Sbapt				 */
618228072Sbapt				++sptr;
619228072Sbapt
620228072Sbapt			c = array[sptr];
621228072Sbapt			array[sptr] = '\0';
622228072Sbapt
623228072Sbapt			esc_char = otoi (array + 1);
624228072Sbapt
625228072Sbapt			array[sptr] = c;
626228072Sbapt
627228072Sbapt			return esc_char;
628228072Sbapt		}
629228072Sbapt
630228072Sbapt	case 'x':
631228072Sbapt		{		/* \x<hex> */
632228072Sbapt			int     sptr = 2;
633228072Sbapt
634228072Sbapt			while (isascii (array[sptr]) &&
635250125Sjkim			       isxdigit (array[sptr]))
636228072Sbapt				/* Don't increment inside loop control
637228072Sbapt				 * because if isdigit() is a macro it might
638228072Sbapt				 * expand into multiple increments ...
639228072Sbapt				 */
640228072Sbapt				++sptr;
641228072Sbapt
642228072Sbapt			c = array[sptr];
643228072Sbapt			array[sptr] = '\0';
644228072Sbapt
645228072Sbapt			esc_char = htoi (array + 2);
646228072Sbapt
647228072Sbapt			array[sptr] = c;
648228072Sbapt
649228072Sbapt			return esc_char;
650228072Sbapt		}
651228072Sbapt
652228072Sbapt	default:
653228072Sbapt		return array[1];
654228072Sbapt	}
655228072Sbapt}
656228072Sbapt
657228072Sbapt
658228072Sbapt/* otoi - convert an octal digit string to an integer value */
659228072Sbapt
660228072Sbaptint otoi (str)
661228072Sbapt     Char str[];
662228072Sbapt{
663228072Sbapt	unsigned int result;
664228072Sbapt
665228072Sbapt	(void) sscanf ((char *) str, "%o", &result);
666228072Sbapt	return result;
667228072Sbapt}
668228072Sbapt
669228072Sbapt
670228072Sbapt/* out - various flavors of outputing a (possibly formatted) string for the
671228072Sbapt *	 generated scanner, keeping track of the line count.
672228072Sbapt */
673228072Sbapt
674228072Sbaptvoid out (str)
675228072Sbapt     const char *str;
676228072Sbapt{
677228072Sbapt	fputs (str, stdout);
678228072Sbapt}
679228072Sbapt
680228072Sbaptvoid out_dec (fmt, n)
681228072Sbapt     const char *fmt;
682228072Sbapt     int n;
683228072Sbapt{
684228072Sbapt	fprintf (stdout, fmt, n);
685228072Sbapt}
686228072Sbapt
687228072Sbaptvoid out_dec2 (fmt, n1, n2)
688228072Sbapt     const char *fmt;
689228072Sbapt     int n1, n2;
690228072Sbapt{
691228072Sbapt	fprintf (stdout, fmt, n1, n2);
692228072Sbapt}
693228072Sbapt
694228072Sbaptvoid out_hex (fmt, x)
695228072Sbapt     const char *fmt;
696228072Sbapt     unsigned int x;
697228072Sbapt{
698228072Sbapt	fprintf (stdout, fmt, x);
699228072Sbapt}
700228072Sbapt
701228072Sbaptvoid out_str (fmt, str)
702228072Sbapt     const char *fmt, str[];
703228072Sbapt{
704228072Sbapt	fprintf (stdout,fmt, str);
705228072Sbapt}
706228072Sbapt
707228072Sbaptvoid out_str3 (fmt, s1, s2, s3)
708228072Sbapt     const char *fmt, s1[], s2[], s3[];
709228072Sbapt{
710228072Sbapt	fprintf (stdout,fmt, s1, s2, s3);
711228072Sbapt}
712228072Sbapt
713228072Sbaptvoid out_str_dec (fmt, str, n)
714228072Sbapt     const char *fmt, str[];
715228072Sbapt     int n;
716228072Sbapt{
717228072Sbapt	fprintf (stdout,fmt, str, n);
718228072Sbapt}
719228072Sbapt
720228072Sbaptvoid outc (c)
721228072Sbapt     int c;
722228072Sbapt{
723228072Sbapt	fputc (c, stdout);
724228072Sbapt}
725228072Sbapt
726228072Sbaptvoid outn (str)
727228072Sbapt     const char *str;
728228072Sbapt{
729228072Sbapt	fputs (str,stdout);
730228072Sbapt    fputc('\n',stdout);
731228072Sbapt}
732228072Sbapt
733228072Sbapt/** Print "m4_define( [[def]], [[val]])m4_dnl\n".
734228072Sbapt * @param def The m4 symbol to define.
735228072Sbapt * @param val The definition; may be NULL.
736228072Sbapt * @return buf
737228072Sbapt */
738228072Sbaptvoid out_m4_define (const char* def, const char* val)
739228072Sbapt{
740228072Sbapt    const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
741228072Sbapt    fprintf(stdout, fmt, def, val?val:"");
742228072Sbapt}
743228072Sbapt
744228072Sbapt
745250874Sjkim/* readable_form - return the human-readable form of a character
746228072Sbapt *
747228072Sbapt * The returned string is in static storage.
748228072Sbapt */
749228072Sbapt
750228072Sbaptchar   *readable_form (c)
751250874Sjkim     int c;
752228072Sbapt{
753228072Sbapt	static char rform[10];
754228072Sbapt
755228072Sbapt	if ((c >= 0 && c < 32) || c >= 127) {
756228072Sbapt		switch (c) {
757228072Sbapt		case '\b':
758228072Sbapt			return "\\b";
759228072Sbapt		case '\f':
760228072Sbapt			return "\\f";
761228072Sbapt		case '\n':
762228072Sbapt			return "\\n";
763228072Sbapt		case '\r':
764228072Sbapt			return "\\r";
765228072Sbapt		case '\t':
766228072Sbapt			return "\\t";
767228072Sbapt
768228072Sbapt#if defined (__STDC__)
769228072Sbapt		case '\a':
770228072Sbapt			return "\\a";
771228072Sbapt		case '\v':
772228072Sbapt			return "\\v";
773228072Sbapt#endif
774228072Sbapt
775228072Sbapt		default:
776228072Sbapt			snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c);
777228072Sbapt			return rform;
778228072Sbapt		}
779228072Sbapt	}
780228072Sbapt
781228072Sbapt	else if (c == ' ')
782228072Sbapt		return "' '";
783228072Sbapt
784228072Sbapt	else {
785228072Sbapt		rform[0] = c;
786228072Sbapt		rform[1] = '\0';
787228072Sbapt
788228072Sbapt		return rform;
789228072Sbapt	}
790228072Sbapt}
791228072Sbapt
792228072Sbapt
793228072Sbapt/* reallocate_array - increase the size of a dynamic array */
794228072Sbapt
795228072Sbaptvoid   *reallocate_array (array, size, element_size)
796228072Sbapt     void   *array;
797228072Sbapt     int size;
798228072Sbapt     size_t element_size;
799228072Sbapt{
800250874Sjkim	void *new_array;
801228072Sbapt	size_t  num_bytes = element_size * size;
802228072Sbapt
803228072Sbapt	new_array = flex_realloc (array, num_bytes);
804228072Sbapt	if (!new_array)
805228072Sbapt		flexfatal (_("attempt to increase array size failed"));
806228072Sbapt
807228072Sbapt	return new_array;
808228072Sbapt}
809228072Sbapt
810228072Sbapt
811228072Sbapt/* skelout - write out one section of the skeleton file
812228072Sbapt *
813228072Sbapt * Description
814228072Sbapt *    Copies skelfile or skel array to stdout until a line beginning with
815228072Sbapt *    "%%" or EOF is found.
816228072Sbapt */
817228072Sbaptvoid skelout ()
818228072Sbapt{
819228072Sbapt	char    buf_storage[MAXLINE];
820228072Sbapt	char   *buf = buf_storage;
821228072Sbapt	bool   do_copy = true;
822228072Sbapt
823228072Sbapt    /* "reset" the state by clearing the buffer and pushing a '1' */
824228072Sbapt    if(sko_len > 0)
825228072Sbapt        sko_peek(&do_copy);
826228072Sbapt    sko_len = 0;
827228072Sbapt    sko_push(do_copy=true);
828228072Sbapt
829228072Sbapt
830228072Sbapt	/* Loop pulling lines either from the skelfile, if we're using
831228072Sbapt	 * one, or from the skel[] array.
832228072Sbapt	 */
833228072Sbapt	while (skelfile ?
834228072Sbapt	       (fgets (buf, MAXLINE, skelfile) != NULL) :
835228072Sbapt	       ((buf = (char *) skel[skel_ind++]) != 0)) {
836228072Sbapt
837228072Sbapt		if (skelfile)
838228072Sbapt			chomp (buf);
839228072Sbapt
840228072Sbapt		/* copy from skel array */
841228072Sbapt		if (buf[0] == '%') {	/* control line */
842228072Sbapt			/* print the control line as a comment. */
843228072Sbapt			if (ddebug && buf[1] != '#') {
844228072Sbapt				if (buf[strlen (buf) - 1] == '\\')
845228072Sbapt					out_str ("/* %s */\\\n", buf);
846228072Sbapt				else
847228072Sbapt					out_str ("/* %s */\n", buf);
848228072Sbapt			}
849228072Sbapt
850228072Sbapt			/* We've been accused of using cryptic markers in the skel.
851228072Sbapt			 * So we'll use emacs-style-hyphenated-commands.
852228072Sbapt             * We might consider a hash if this if-else-if-else
853228072Sbapt             * chain gets too large.
854228072Sbapt			 */
855228072Sbapt#define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
856228072Sbapt
857228072Sbapt			if (buf[1] == '%') {
858228072Sbapt				/* %% is a break point for skelout() */
859228072Sbapt				return;
860228072Sbapt			}
861228072Sbapt            else if (cmd_match (CMD_PUSH)){
862228072Sbapt                sko_push(do_copy);
863228072Sbapt                if(ddebug){
864228072Sbapt                    out_str("/*(state = (%s) */",do_copy?"true":"false");
865228072Sbapt                }
866228072Sbapt                out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
867228072Sbapt            }
868228072Sbapt            else if (cmd_match (CMD_POP)){
869228072Sbapt                sko_pop(&do_copy);
870228072Sbapt                if(ddebug){
871228072Sbapt                    out_str("/*(state = (%s) */",do_copy?"true":"false");
872228072Sbapt                }
873228072Sbapt                out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
874228072Sbapt            }
875228072Sbapt            else if (cmd_match (CMD_IF_REENTRANT)){
876228072Sbapt                sko_push(do_copy);
877228072Sbapt                do_copy = reentrant && do_copy;
878228072Sbapt            }
879228072Sbapt            else if (cmd_match (CMD_IF_NOT_REENTRANT)){
880228072Sbapt                sko_push(do_copy);
881228072Sbapt                do_copy = !reentrant && do_copy;
882228072Sbapt            }
883228072Sbapt            else if (cmd_match(CMD_IF_BISON_BRIDGE)){
884228072Sbapt                sko_push(do_copy);
885228072Sbapt                do_copy = bison_bridge_lval && do_copy;
886228072Sbapt            }
887228072Sbapt            else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){
888228072Sbapt                sko_push(do_copy);
889228072Sbapt                do_copy = !bison_bridge_lval && do_copy;
890228072Sbapt            }
891228072Sbapt            else if (cmd_match (CMD_ENDIF)){
892228072Sbapt                sko_pop(&do_copy);
893228072Sbapt            }
894228072Sbapt			else if (cmd_match (CMD_IF_TABLES_SER)) {
895228072Sbapt                do_copy = do_copy && tablesext;
896228072Sbapt			}
897228072Sbapt			else if (cmd_match (CMD_TABLES_YYDMAP)) {
898228072Sbapt				if (tablesext && yydmap_buf.elts)
899228072Sbapt					outn ((char *) (yydmap_buf.elts));
900228072Sbapt			}
901228072Sbapt            else if (cmd_match (CMD_DEFINE_YYTABLES)) {
902228072Sbapt                out_str("#define YYTABLES_NAME \"%s\"\n",
903228072Sbapt                        tablesname?tablesname:"yytables");
904228072Sbapt            }
905228072Sbapt			else if (cmd_match (CMD_IF_CPP_ONLY)) {
906228072Sbapt				/* only for C++ */
907228072Sbapt                sko_push(do_copy);
908228072Sbapt				do_copy = C_plus_plus;
909228072Sbapt			}
910228072Sbapt			else if (cmd_match (CMD_IF_C_ONLY)) {
911228072Sbapt				/* %- only for C */
912228072Sbapt                sko_push(do_copy);
913228072Sbapt				do_copy = !C_plus_plus;
914228072Sbapt			}
915228072Sbapt			else if (cmd_match (CMD_IF_C_OR_CPP)) {
916228072Sbapt				/* %* for C and C++ */
917228072Sbapt                sko_push(do_copy);
918228072Sbapt				do_copy = true;
919228072Sbapt			}
920228072Sbapt			else if (cmd_match (CMD_NOT_FOR_HEADER)) {
921228072Sbapt				/* %c begin linkage-only (non-header) code. */
922228072Sbapt				OUT_BEGIN_CODE ();
923228072Sbapt			}
924228072Sbapt			else if (cmd_match (CMD_OK_FOR_HEADER)) {
925228072Sbapt				/* %e end linkage-only code. */
926228072Sbapt				OUT_END_CODE ();
927228072Sbapt			}
928228072Sbapt			else if (buf[1] == '#') {
929228072Sbapt				/* %# a comment in the skel. ignore. */
930228072Sbapt			}
931228072Sbapt			else {
932228072Sbapt				flexfatal (_("bad line in skeleton file"));
933228072Sbapt			}
934228072Sbapt		}
935228072Sbapt
936228072Sbapt		else if (do_copy)
937228072Sbapt            outn (buf);
938228072Sbapt	}			/* end while */
939228072Sbapt}
940228072Sbapt
941228072Sbapt
942228072Sbapt/* transition_struct_out - output a yy_trans_info structure
943228072Sbapt *
944228072Sbapt * outputs the yy_trans_info structure with the two elements, element_v and
945228072Sbapt * element_n.  Formats the output with spaces and carriage returns.
946228072Sbapt */
947228072Sbapt
948228072Sbaptvoid transition_struct_out (element_v, element_n)
949228072Sbapt     int element_v, element_n;
950228072Sbapt{
951228072Sbapt
952228072Sbapt	/* short circuit any output */
953228072Sbapt	if (!gentables)
954228072Sbapt		return;
955228072Sbapt
956228072Sbapt	out_dec2 (" {%4d,%4d },", element_v, element_n);
957228072Sbapt
958228072Sbapt	datapos += TRANS_STRUCT_PRINT_LENGTH;
959228072Sbapt
960228072Sbapt	if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
961228072Sbapt		outc ('\n');
962228072Sbapt
963228072Sbapt		if (++dataline % 10 == 0)
964228072Sbapt			outc ('\n');
965228072Sbapt
966228072Sbapt		datapos = 0;
967228072Sbapt	}
968228072Sbapt}
969228072Sbapt
970228072Sbapt
971228072Sbapt/* The following is only needed when building flex's parser using certain
972228072Sbapt * broken versions of bison.
973228072Sbapt */
974228072Sbaptvoid   *yy_flex_xmalloc (size)
975228072Sbapt     int size;
976228072Sbapt{
977228072Sbapt	void   *result = flex_alloc ((size_t) size);
978228072Sbapt
979228072Sbapt	if (!result)
980228072Sbapt		flexfatal (_
981228072Sbapt			   ("memory allocation failed in yy_flex_xmalloc()"));
982228072Sbapt
983228072Sbapt	return result;
984228072Sbapt}
985228072Sbapt
986228072Sbapt
987228072Sbapt/* zero_out - set a region of memory to 0
988228072Sbapt *
989228072Sbapt * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero.
990228072Sbapt */
991228072Sbapt
992228072Sbaptvoid zero_out (region_ptr, size_in_bytes)
993228072Sbapt     char   *region_ptr;
994228072Sbapt     size_t size_in_bytes;
995228072Sbapt{
996250874Sjkim	char *rp, *rp_end;
997228072Sbapt
998228072Sbapt	rp = region_ptr;
999228072Sbapt	rp_end = region_ptr + size_in_bytes;
1000228072Sbapt
1001228072Sbapt	while (rp < rp_end)
1002228072Sbapt		*rp++ = 0;
1003228072Sbapt}
1004228072Sbapt
1005228072Sbapt/* Remove all '\n' and '\r' characters, if any, from the end of str.
1006228072Sbapt * str can be any null-terminated string, or NULL.
1007228072Sbapt * returns str. */
1008228072Sbaptchar   *chomp (str)
1009228072Sbapt     char   *str;
1010228072Sbapt{
1011228072Sbapt	char   *p = str;
1012228072Sbapt
1013228072Sbapt	if (!str || !*str)	/* s is null or empty string */
1014228072Sbapt		return str;
1015228072Sbapt
1016228072Sbapt	/* find end of string minus one */
1017228072Sbapt	while (*p)
1018228072Sbapt		++p;
1019228072Sbapt	--p;
1020228072Sbapt
1021228072Sbapt	/* eat newlines */
1022228072Sbapt	while (p >= str && (*p == '\r' || *p == '\n'))
1023228072Sbapt		*p-- = 0;
1024228072Sbapt	return str;
1025228072Sbapt}
1026