xref: /netbsd-src/external/bsd/flex/dist/src/misc.c (revision 596f930c293ef11c72f1fc18967768d00c27abef)
1*596f930cSchristos /*	$NetBSD: misc.c,v 1.4 2018/12/23 16:27:17 christos Exp $	*/
2a11deec2Schristos 
330da1778Schristos /* misc - miscellaneous flex routines */
430da1778Schristos 
530da1778Schristos /*  Copyright (c) 1990 The Regents of the University of California. */
630da1778Schristos /*  All rights reserved. */
730da1778Schristos 
830da1778Schristos /*  This code is derived from software contributed to Berkeley by */
930da1778Schristos /*  Vern Paxson. */
1030da1778Schristos 
1130da1778Schristos /*  The United States Government has rights in this work pursuant */
1230da1778Schristos /*  to contract no. DE-AC03-76SF00098 between the United States */
1330da1778Schristos /*  Department of Energy and the University of California. */
1430da1778Schristos 
1530da1778Schristos /*  This file is part of flex. */
1630da1778Schristos 
1730da1778Schristos /*  Redistribution and use in source and binary forms, with or without */
1830da1778Schristos /*  modification, are permitted provided that the following conditions */
1930da1778Schristos /*  are met: */
2030da1778Schristos 
2130da1778Schristos /*  1. Redistributions of source code must retain the above copyright */
2230da1778Schristos /*     notice, this list of conditions and the following disclaimer. */
2330da1778Schristos /*  2. Redistributions in binary form must reproduce the above copyright */
2430da1778Schristos /*     notice, this list of conditions and the following disclaimer in the */
2530da1778Schristos /*     documentation and/or other materials provided with the distribution. */
2630da1778Schristos 
2730da1778Schristos /*  Neither the name of the University nor the names of its contributors */
2830da1778Schristos /*  may be used to endorse or promote products derived from this software */
2930da1778Schristos /*  without specific prior written permission. */
3030da1778Schristos 
3130da1778Schristos /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
3230da1778Schristos /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
3330da1778Schristos /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
3430da1778Schristos /*  PURPOSE. */
3530da1778Schristos #include "flexdef.h"
36*596f930cSchristos __RCSID("$NetBSD: misc.c,v 1.4 2018/12/23 16:27:17 christos Exp $");
37a11deec2Schristos 
3830da1778Schristos #include "tables.h"
39a11deec2Schristos #include <stdarg.h>
4030da1778Schristos 
4130da1778Schristos #define CMD_IF_TABLES_SER    "%if-tables-serialization"
4230da1778Schristos #define CMD_TABLES_YYDMAP    "%tables-yydmap"
4330da1778Schristos #define CMD_DEFINE_YYTABLES  "%define-yytables"
4430da1778Schristos #define CMD_IF_CPP_ONLY      "%if-c++-only"
4530da1778Schristos #define CMD_IF_C_ONLY        "%if-c-only"
4630da1778Schristos #define CMD_IF_C_OR_CPP      "%if-c-or-c++"
4730da1778Schristos #define CMD_NOT_FOR_HEADER   "%not-for-header"
4830da1778Schristos #define CMD_OK_FOR_HEADER    "%ok-for-header"
4930da1778Schristos #define CMD_PUSH             "%push"
5030da1778Schristos #define CMD_POP              "%pop"
5130da1778Schristos #define CMD_IF_REENTRANT     "%if-reentrant"
5230da1778Schristos #define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
5330da1778Schristos #define CMD_IF_BISON_BRIDGE  "%if-bison-bridge"
5430da1778Schristos #define CMD_IF_NOT_BISON_BRIDGE  "%if-not-bison-bridge"
5530da1778Schristos #define CMD_ENDIF            "%endif"
5630da1778Schristos 
5730da1778Schristos /* we allow the skeleton to push and pop. */
5830da1778Schristos struct sko_state {
5930da1778Schristos     bool dc; /**< do_copy */
6030da1778Schristos };
6130da1778Schristos static struct sko_state *sko_stack=0;
6230da1778Schristos static int sko_len=0,sko_sz=0;
sko_push(bool dc)6330da1778Schristos static void sko_push(bool dc)
6430da1778Schristos {
6530da1778Schristos     if(!sko_stack){
6630da1778Schristos         sko_sz = 1;
677977e686Schristos         sko_stack = malloc(sizeof(struct sko_state) * (size_t) sko_sz);
6830da1778Schristos         if (!sko_stack)
6930da1778Schristos             flexfatal(_("allocation of sko_stack failed"));
7030da1778Schristos         sko_len = 0;
7130da1778Schristos     }
7230da1778Schristos     if(sko_len >= sko_sz){
7330da1778Schristos         sko_sz *= 2;
747977e686Schristos         sko_stack = realloc(sko_stack,
757977e686Schristos 			sizeof(struct sko_state) * (size_t) sko_sz);
7630da1778Schristos     }
7730da1778Schristos 
7830da1778Schristos     /* initialize to zero and push */
7930da1778Schristos     sko_stack[sko_len].dc = dc;
8030da1778Schristos     sko_len++;
8130da1778Schristos }
sko_peek(bool * dc)8230da1778Schristos static void sko_peek(bool *dc)
8330da1778Schristos {
8430da1778Schristos     if(sko_len <= 0)
8530da1778Schristos         flex_die("peek attempt when sko stack is empty");
8630da1778Schristos     if(dc)
8730da1778Schristos         *dc = sko_stack[sko_len-1].dc;
8830da1778Schristos }
sko_pop(bool * dc)8930da1778Schristos static void sko_pop(bool* dc)
9030da1778Schristos {
9130da1778Schristos     sko_peek(dc);
9230da1778Schristos     sko_len--;
9330da1778Schristos     if(sko_len < 0)
9430da1778Schristos         flex_die("popped too many times in skeleton.");
9530da1778Schristos }
9630da1778Schristos 
9730da1778Schristos /* Append "#define defname value\n" to the running buffer. */
action_define(const char * defname,int value)987977e686Schristos void action_define (const char *defname, int value)
9930da1778Schristos {
10030da1778Schristos 	char    buf[MAXLINE];
10130da1778Schristos 	char   *cpy;
10230da1778Schristos 
10330da1778Schristos 	if ((int) strlen (defname) > MAXLINE / 2) {
10430da1778Schristos 		format_pinpoint_message (_
10530da1778Schristos 					 ("name \"%s\" ridiculously long"),
10630da1778Schristos 					 defname);
10730da1778Schristos 		return;
10830da1778Schristos 	}
10930da1778Schristos 
11030da1778Schristos 	snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value);
11130da1778Schristos 	add_action (buf);
11230da1778Schristos 
11330da1778Schristos 	/* track #defines so we can undef them when we're done. */
1147977e686Schristos 	cpy = xstrdup(defname);
11530da1778Schristos 	buf_append (&defs_buf, &cpy, 1);
11630da1778Schristos }
11730da1778Schristos 
11830da1778Schristos /* Append "new_text" to the running buffer. */
add_action(const char * new_text)1197977e686Schristos void add_action (const char *new_text)
12030da1778Schristos {
1217977e686Schristos 	int     len = (int) strlen (new_text);
12230da1778Schristos 
12330da1778Schristos 	while (len + action_index >= action_size - 10 /* slop */ ) {
12430da1778Schristos 		int     new_size = action_size * 2;
12530da1778Schristos 
12630da1778Schristos 		if (new_size <= 0)
12730da1778Schristos 			/* Increase just a little, to try to avoid overflow
12830da1778Schristos 			 * on 16-bit machines.
12930da1778Schristos 			 */
13030da1778Schristos 			action_size += action_size / 8;
13130da1778Schristos 		else
13230da1778Schristos 			action_size = new_size;
13330da1778Schristos 
13430da1778Schristos 		action_array =
13530da1778Schristos 			reallocate_character_array (action_array,
13630da1778Schristos 						    action_size);
13730da1778Schristos 	}
13830da1778Schristos 
13930da1778Schristos 	strcpy (&action_array[action_index], new_text);
14030da1778Schristos 
14130da1778Schristos 	action_index += len;
14230da1778Schristos }
14330da1778Schristos 
14430da1778Schristos 
14530da1778Schristos /* allocate_array - allocate memory for an integer array of the given size */
14630da1778Schristos 
allocate_array(int size,size_t element_size)1477977e686Schristos void   *allocate_array (int size, size_t element_size)
14830da1778Schristos {
14930da1778Schristos 	void *mem;
150*596f930cSchristos #if HAVE_REALLOCARRAY
151*596f930cSchristos 	/* reallocarray has built-in overflow detection */
152*596f930cSchristos 	mem = reallocarray(NULL, (size_t) size, element_size);
153*596f930cSchristos #else
154*596f930cSchristos 	size_t num_bytes = (size_t) size * element_size;
155*596f930cSchristos 	mem = (size && SIZE_MAX / (size_t) size < element_size) ? NULL :
156*596f930cSchristos 		malloc(num_bytes);
157*596f930cSchristos #endif
15830da1778Schristos 	if (!mem)
15930da1778Schristos 		flexfatal (_
16030da1778Schristos 			   ("memory allocation failed in allocate_array()"));
16130da1778Schristos 
16230da1778Schristos 	return mem;
16330da1778Schristos }
16430da1778Schristos 
16530da1778Schristos 
16630da1778Schristos /* all_lower - true if a string is all lower-case */
16730da1778Schristos 
all_lower(char * str)1687977e686Schristos int all_lower (char *str)
16930da1778Schristos {
17030da1778Schristos 	while (*str) {
1717977e686Schristos 		if (!isascii ((unsigned char) * str) || !islower ((unsigned char) * str))
17230da1778Schristos 			return 0;
17330da1778Schristos 		++str;
17430da1778Schristos 	}
17530da1778Schristos 
17630da1778Schristos 	return 1;
17730da1778Schristos }
17830da1778Schristos 
17930da1778Schristos 
18030da1778Schristos /* all_upper - true if a string is all upper-case */
18130da1778Schristos 
all_upper(char * str)1827977e686Schristos int all_upper (char *str)
18330da1778Schristos {
18430da1778Schristos 	while (*str) {
1857977e686Schristos 		if (!isascii ((unsigned char) * str) || !isupper ((unsigned char) * str))
18630da1778Schristos 			return 0;
18730da1778Schristos 		++str;
18830da1778Schristos 	}
18930da1778Schristos 
19030da1778Schristos 	return 1;
19130da1778Schristos }
19230da1778Schristos 
19330da1778Schristos 
19430da1778Schristos /* intcmp - compares two integers for use by qsort. */
19530da1778Schristos 
intcmp(const void * a,const void * b)19630da1778Schristos int intcmp (const void *a, const void *b)
19730da1778Schristos {
19830da1778Schristos   return *(const int *) a - *(const int *) b;
19930da1778Schristos }
20030da1778Schristos 
20130da1778Schristos 
20230da1778Schristos /* check_char - checks a character to make sure it's within the range
20330da1778Schristos  *		we're expecting.  If not, generates fatal error message
20430da1778Schristos  *		and exits.
20530da1778Schristos  */
20630da1778Schristos 
check_char(int c)2077977e686Schristos void check_char (int c)
20830da1778Schristos {
20930da1778Schristos 	if (c >= CSIZE)
21030da1778Schristos 		lerr (_("bad character '%s' detected in check_char()"),
21130da1778Schristos 			readable_form (c));
21230da1778Schristos 
21330da1778Schristos 	if (c >= csize)
21430da1778Schristos 		lerr (_
21530da1778Schristos 			("scanner requires -8 flag to use the character %s"),
21630da1778Schristos 			readable_form (c));
21730da1778Schristos }
21830da1778Schristos 
21930da1778Schristos 
22030da1778Schristos 
22130da1778Schristos /* clower - replace upper-case letter to lower-case */
22230da1778Schristos 
clower(int c)2237977e686Schristos unsigned char clower (int c)
22430da1778Schristos {
2257977e686Schristos 	return (unsigned char) ((isascii (c) && isupper (c)) ? tolower (c) : c);
22630da1778Schristos }
22730da1778Schristos 
22830da1778Schristos 
xstrdup(const char * s)2297977e686Schristos char *xstrdup(const char *s)
23030da1778Schristos {
2317977e686Schristos 	char *s2;
23230da1778Schristos 
2337977e686Schristos 	if ((s2 = strdup(s)) == NULL)
2347977e686Schristos 		flexfatal (_("memory allocation failure in xstrdup()"));
23530da1778Schristos 
2367977e686Schristos 	return s2;
23730da1778Schristos }
23830da1778Schristos 
23930da1778Schristos 
24030da1778Schristos /* cclcmp - compares two characters for use by qsort with '\0' sorting last. */
24130da1778Schristos 
cclcmp(const void * a,const void * b)24230da1778Schristos int cclcmp (const void *a, const void *b)
24330da1778Schristos {
2447977e686Schristos   if (!*(const unsigned char *) a)
24530da1778Schristos 	return 1;
24630da1778Schristos   else
2477977e686Schristos 	if (!*(const unsigned char *) b)
24830da1778Schristos 	  return - 1;
24930da1778Schristos 	else
2507977e686Schristos 	  return *(const unsigned char *) a - *(const unsigned char *) b;
25130da1778Schristos }
25230da1778Schristos 
25330da1778Schristos 
25430da1778Schristos /* dataend - finish up a block of data declarations */
25530da1778Schristos 
dataend(void)2567977e686Schristos void dataend (void)
25730da1778Schristos {
25830da1778Schristos 	/* short circuit any output */
25930da1778Schristos 	if (gentables) {
26030da1778Schristos 
26130da1778Schristos 		if (datapos > 0)
26230da1778Schristos 			dataflush ();
26330da1778Schristos 
26430da1778Schristos 		/* add terminator for initialization; { for vi */
26530da1778Schristos 		outn ("    } ;\n");
26630da1778Schristos 	}
26730da1778Schristos 	dataline = 0;
26830da1778Schristos 	datapos = 0;
26930da1778Schristos }
27030da1778Schristos 
27130da1778Schristos 
27230da1778Schristos /* dataflush - flush generated data statements */
27330da1778Schristos 
dataflush(void)2747977e686Schristos void dataflush (void)
27530da1778Schristos {
27630da1778Schristos 	/* short circuit any output */
27730da1778Schristos 	if (!gentables)
27830da1778Schristos 		return;
27930da1778Schristos 
28030da1778Schristos 	outc ('\n');
28130da1778Schristos 
28230da1778Schristos 	if (++dataline >= NUMDATALINES) {
28330da1778Schristos 		/* Put out a blank line so that the table is grouped into
28430da1778Schristos 		 * large blocks that enable the user to find elements easily.
28530da1778Schristos 		 */
28630da1778Schristos 		outc ('\n');
28730da1778Schristos 		dataline = 0;
28830da1778Schristos 	}
28930da1778Schristos 
29030da1778Schristos 	/* Reset the number of characters written on the current line. */
29130da1778Schristos 	datapos = 0;
29230da1778Schristos }
29330da1778Schristos 
29430da1778Schristos 
29530da1778Schristos /* flexerror - report an error message and terminate */
29630da1778Schristos 
flexerror(const char * msg)2977977e686Schristos void flexerror (const char *msg)
29830da1778Schristos {
29930da1778Schristos 	fprintf (stderr, "%s: %s\n", program_name, msg);
30030da1778Schristos 	flexend (1);
30130da1778Schristos }
30230da1778Schristos 
30330da1778Schristos 
30430da1778Schristos /* flexfatal - report a fatal error message and terminate */
30530da1778Schristos 
flexfatal(const char * msg)3067977e686Schristos void flexfatal (const char *msg)
30730da1778Schristos {
30830da1778Schristos 	fprintf (stderr, _("%s: fatal internal error, %s\n"),
30930da1778Schristos 		 program_name, msg);
31030da1778Schristos 	FLEX_EXIT (1);
31130da1778Schristos }
31230da1778Schristos 
31330da1778Schristos 
31430da1778Schristos /* lerr - report an error message */
31530da1778Schristos 
lerr(const char * msg,...)3167977e686Schristos void lerr (const char *msg, ...)
3177977e686Schristos {
31830da1778Schristos 	char    errmsg[MAXLINE];
31930da1778Schristos 	va_list args;
32030da1778Schristos 
32130da1778Schristos 	va_start(args, msg);
32230da1778Schristos 	vsnprintf (errmsg, sizeof(errmsg), msg, args);
32330da1778Schristos 	va_end(args);
32430da1778Schristos 	flexerror (errmsg);
32530da1778Schristos }
32630da1778Schristos 
32730da1778Schristos 
32830da1778Schristos /* lerr_fatal - as lerr, but call flexfatal */
32930da1778Schristos 
lerr_fatal(const char * msg,...)33030da1778Schristos void lerr_fatal (const char *msg, ...)
33130da1778Schristos {
33230da1778Schristos 	char    errmsg[MAXLINE];
33330da1778Schristos 	va_list args;
33430da1778Schristos 	va_start(args, msg);
33530da1778Schristos 
33630da1778Schristos 	vsnprintf (errmsg, sizeof(errmsg), msg, args);
33730da1778Schristos 	va_end(args);
33830da1778Schristos 	flexfatal (errmsg);
33930da1778Schristos }
34030da1778Schristos 
34130da1778Schristos 
34230da1778Schristos /* line_directive_out - spit out a "#line" statement */
34330da1778Schristos 
line_directive_out(FILE * output_file,int do_infile)3447977e686Schristos void line_directive_out (FILE *output_file, int do_infile)
34530da1778Schristos {
34630da1778Schristos 	char    directive[MAXLINE], filename[MAXLINE];
34730da1778Schristos 	char   *s1, *s2, *s3;
348a11deec2Schristos 	static const char line_fmt[] = "#line %d \"%s\"\n";
34930da1778Schristos 
35030da1778Schristos 	if (!gen_line_dirs)
35130da1778Schristos 		return;
35230da1778Schristos 
35330da1778Schristos 	s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
35430da1778Schristos 
35530da1778Schristos 	if (do_infile && !s1)
35630da1778Schristos         s1 = "<stdin>";
35730da1778Schristos 
35830da1778Schristos 	s2 = filename;
35930da1778Schristos 	s3 = &filename[sizeof (filename) - 2];
36030da1778Schristos 
36130da1778Schristos 	while (s2 < s3 && *s1) {
3627977e686Schristos 		if (*s1 == '\\' || *s1 == '"')
3637977e686Schristos 			/* Escape the '\' or '"' */
36430da1778Schristos 			*s2++ = '\\';
36530da1778Schristos 
36630da1778Schristos 		*s2++ = *s1++;
36730da1778Schristos 	}
36830da1778Schristos 
36930da1778Schristos 	*s2 = '\0';
37030da1778Schristos 
37130da1778Schristos 	if (do_infile)
37230da1778Schristos 		snprintf (directive, sizeof(directive), line_fmt, linenum, filename);
37330da1778Schristos 	else {
37430da1778Schristos 		snprintf (directive, sizeof(directive), line_fmt, 0, filename);
37530da1778Schristos 	}
37630da1778Schristos 
37730da1778Schristos 	/* If output_file is nil then we should put the directive in
37830da1778Schristos 	 * the accumulated actions.
37930da1778Schristos 	 */
38030da1778Schristos 	if (output_file) {
38130da1778Schristos 		fputs (directive, output_file);
38230da1778Schristos 	}
38330da1778Schristos 	else
38430da1778Schristos 		add_action (directive);
38530da1778Schristos }
38630da1778Schristos 
38730da1778Schristos 
38830da1778Schristos /* mark_defs1 - mark the current position in the action array as
38930da1778Schristos  *               representing where the user's section 1 definitions end
39030da1778Schristos  *		 and the prolog begins
39130da1778Schristos  */
mark_defs1(void)3927977e686Schristos void mark_defs1 (void)
39330da1778Schristos {
39430da1778Schristos 	defs1_offset = 0;
39530da1778Schristos 	action_array[action_index++] = '\0';
39630da1778Schristos 	action_offset = prolog_offset = action_index;
39730da1778Schristos 	action_array[action_index] = '\0';
39830da1778Schristos }
39930da1778Schristos 
40030da1778Schristos 
40130da1778Schristos /* mark_prolog - mark the current position in the action array as
40230da1778Schristos  *               representing the end of the action prolog
40330da1778Schristos  */
mark_prolog(void)4047977e686Schristos void mark_prolog (void)
40530da1778Schristos {
40630da1778Schristos 	action_array[action_index++] = '\0';
40730da1778Schristos 	action_offset = action_index;
40830da1778Schristos 	action_array[action_index] = '\0';
40930da1778Schristos }
41030da1778Schristos 
41130da1778Schristos 
41230da1778Schristos /* mk2data - generate a data statement for a two-dimensional array
41330da1778Schristos  *
41430da1778Schristos  * Generates a data statement initializing the current 2-D array to "value".
41530da1778Schristos  */
mk2data(int value)4167977e686Schristos void mk2data (int value)
41730da1778Schristos {
41830da1778Schristos 	/* short circuit any output */
41930da1778Schristos 	if (!gentables)
42030da1778Schristos 		return;
42130da1778Schristos 
42230da1778Schristos 	if (datapos >= NUMDATAITEMS) {
42330da1778Schristos 		outc (',');
42430da1778Schristos 		dataflush ();
42530da1778Schristos 	}
42630da1778Schristos 
42730da1778Schristos 	if (datapos == 0)
42830da1778Schristos 		/* Indent. */
42930da1778Schristos 		out ("    ");
43030da1778Schristos 
43130da1778Schristos 	else
43230da1778Schristos 		outc (',');
43330da1778Schristos 
43430da1778Schristos 	++datapos;
43530da1778Schristos 
43630da1778Schristos 	out_dec ("%5d", value);
43730da1778Schristos }
43830da1778Schristos 
43930da1778Schristos 
44030da1778Schristos /* mkdata - generate a data statement
44130da1778Schristos  *
44230da1778Schristos  * Generates a data statement initializing the current array element to
44330da1778Schristos  * "value".
44430da1778Schristos  */
mkdata(int value)4457977e686Schristos void mkdata (int value)
44630da1778Schristos {
44730da1778Schristos 	/* short circuit any output */
44830da1778Schristos 	if (!gentables)
44930da1778Schristos 		return;
45030da1778Schristos 
45130da1778Schristos 	if (datapos >= NUMDATAITEMS) {
45230da1778Schristos 		outc (',');
45330da1778Schristos 		dataflush ();
45430da1778Schristos 	}
45530da1778Schristos 
45630da1778Schristos 	if (datapos == 0)
45730da1778Schristos 		/* Indent. */
45830da1778Schristos 		out ("    ");
45930da1778Schristos 	else
46030da1778Schristos 		outc (',');
46130da1778Schristos 
46230da1778Schristos 	++datapos;
46330da1778Schristos 
46430da1778Schristos 	out_dec ("%5d", value);
46530da1778Schristos }
46630da1778Schristos 
46730da1778Schristos 
46830da1778Schristos /* myctoi - return the integer represented by a string of digits */
46930da1778Schristos 
myctoi(const char * array)4707977e686Schristos int myctoi (const char *array)
47130da1778Schristos {
47230da1778Schristos 	int     val = 0;
47330da1778Schristos 
47430da1778Schristos 	(void) sscanf (array, "%d", &val);
47530da1778Schristos 
47630da1778Schristos 	return val;
47730da1778Schristos }
47830da1778Schristos 
47930da1778Schristos 
48030da1778Schristos /* myesc - return character corresponding to escape sequence */
48130da1778Schristos 
myesc(unsigned char array[])4827977e686Schristos unsigned char myesc (unsigned char array[])
48330da1778Schristos {
4847977e686Schristos 	unsigned char    c, esc_char;
48530da1778Schristos 
48630da1778Schristos 	switch (array[1]) {
48730da1778Schristos 	case 'b':
48830da1778Schristos 		return '\b';
48930da1778Schristos 	case 'f':
49030da1778Schristos 		return '\f';
49130da1778Schristos 	case 'n':
49230da1778Schristos 		return '\n';
49330da1778Schristos 	case 'r':
49430da1778Schristos 		return '\r';
49530da1778Schristos 	case 't':
49630da1778Schristos 		return '\t';
49730da1778Schristos 	case 'a':
49830da1778Schristos 		return '\a';
49930da1778Schristos 	case 'v':
50030da1778Schristos 		return '\v';
50130da1778Schristos 	case '0':
50230da1778Schristos 	case '1':
50330da1778Schristos 	case '2':
50430da1778Schristos 	case '3':
50530da1778Schristos 	case '4':
50630da1778Schristos 	case '5':
50730da1778Schristos 	case '6':
50830da1778Schristos 	case '7':
50930da1778Schristos 		{		/* \<octal> */
51030da1778Schristos 			int     sptr = 1;
51130da1778Schristos 
5127977e686Schristos 			while (sptr <= 3 &&
513*596f930cSchristos                                array[sptr] >= '0' && array[sptr] <= '7') {
51430da1778Schristos 				++sptr;
515*596f930cSchristos 			}
51630da1778Schristos 
51730da1778Schristos 			c = array[sptr];
51830da1778Schristos 			array[sptr] = '\0';
51930da1778Schristos 
520*596f930cSchristos 			esc_char = (unsigned char) strtoul ((const char *)array + 1, NULL, 8);
52130da1778Schristos 
52230da1778Schristos 			array[sptr] = c;
52330da1778Schristos 
52430da1778Schristos 			return esc_char;
52530da1778Schristos 		}
52630da1778Schristos 
52730da1778Schristos 	case 'x':
52830da1778Schristos 		{		/* \x<hex> */
52930da1778Schristos 			int     sptr = 2;
53030da1778Schristos 
531*596f930cSchristos 			while (sptr <= 3 && isxdigit (array[sptr])) {
53230da1778Schristos 				/* Don't increment inside loop control
533*596f930cSchristos 				 * because if isxdigit() is a macro it might
53430da1778Schristos 				 * expand into multiple increments ...
53530da1778Schristos 				 */
53630da1778Schristos 				++sptr;
537*596f930cSchristos 			}
53830da1778Schristos 
53930da1778Schristos 			c = array[sptr];
54030da1778Schristos 			array[sptr] = '\0';
54130da1778Schristos 
542*596f930cSchristos 			esc_char = (unsigned char) strtoul ((const char *)array + 2, NULL, 16);
54330da1778Schristos 
54430da1778Schristos 			array[sptr] = c;
54530da1778Schristos 
54630da1778Schristos 			return esc_char;
54730da1778Schristos 		}
54830da1778Schristos 
54930da1778Schristos 	default:
55030da1778Schristos 		return array[1];
55130da1778Schristos 	}
55230da1778Schristos }
55330da1778Schristos 
55430da1778Schristos 
55530da1778Schristos /* out - various flavors of outputing a (possibly formatted) string for the
55630da1778Schristos  *	 generated scanner, keeping track of the line count.
55730da1778Schristos  */
55830da1778Schristos 
out(const char * str)5597977e686Schristos void out (const char *str)
56030da1778Schristos {
56130da1778Schristos 	fputs (str, stdout);
56230da1778Schristos }
56330da1778Schristos 
out_dec(const char * fmt,int n)5647977e686Schristos void out_dec (const char *fmt, int n)
56530da1778Schristos {
56630da1778Schristos 	fprintf (stdout, fmt, n);
56730da1778Schristos }
56830da1778Schristos 
out_dec2(const char * fmt,int n1,int n2)5697977e686Schristos void out_dec2 (const char *fmt, int n1, int n2)
57030da1778Schristos {
57130da1778Schristos 	fprintf (stdout, fmt, n1, n2);
57230da1778Schristos }
57330da1778Schristos 
out_hex(const char * fmt,unsigned int x)5747977e686Schristos void out_hex (const char *fmt, unsigned int x)
57530da1778Schristos {
57630da1778Schristos 	fprintf (stdout, fmt, x);
57730da1778Schristos }
57830da1778Schristos 
out_str(const char * fmt,const char str[])5797977e686Schristos void out_str (const char *fmt, const char str[])
58030da1778Schristos {
58130da1778Schristos 	fprintf (stdout,fmt, str);
58230da1778Schristos }
58330da1778Schristos 
out_str3(const char * fmt,const char s1[],const char s2[],const char s3[])5847977e686Schristos void out_str3 (const char *fmt, const char s1[], const char s2[], const char s3[])
58530da1778Schristos {
58630da1778Schristos 	fprintf (stdout,fmt, s1, s2, s3);
58730da1778Schristos }
58830da1778Schristos 
out_str_dec(const char * fmt,const char str[],int n)5897977e686Schristos void out_str_dec (const char *fmt, const char str[], int n)
59030da1778Schristos {
59130da1778Schristos 	fprintf (stdout,fmt, str, n);
59230da1778Schristos }
59330da1778Schristos 
outc(int c)5947977e686Schristos void outc (int c)
59530da1778Schristos {
59630da1778Schristos 	fputc (c, stdout);
59730da1778Schristos }
59830da1778Schristos 
outn(const char * str)5997977e686Schristos void outn (const char *str)
60030da1778Schristos {
60130da1778Schristos 	fputs (str,stdout);
60230da1778Schristos     fputc('\n',stdout);
60330da1778Schristos }
60430da1778Schristos 
60530da1778Schristos /** Print "m4_define( [[def]], [[val]])m4_dnl\n".
60630da1778Schristos  * @param def The m4 symbol to define.
60730da1778Schristos  * @param val The definition; may be NULL.
60830da1778Schristos  */
out_m4_define(const char * def,const char * val)60930da1778Schristos void out_m4_define (const char* def, const char* val)
61030da1778Schristos {
61130da1778Schristos     const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
61230da1778Schristos     fprintf(stdout, fmt, def, val?val:"");
61330da1778Schristos }
61430da1778Schristos 
61530da1778Schristos 
61630da1778Schristos /* readable_form - return the the human-readable form of a character
61730da1778Schristos  *
61830da1778Schristos  * The returned string is in static storage.
61930da1778Schristos  */
62030da1778Schristos 
readable_form(int c)6217977e686Schristos char   *readable_form (int c)
62230da1778Schristos {
62330da1778Schristos 	static char rform[20];
62430da1778Schristos 
62530da1778Schristos 	if ((c >= 0 && c < 32) || c >= 127) {
62630da1778Schristos 		switch (c) {
62730da1778Schristos 		case '\b':
62830da1778Schristos 			return "\\b";
62930da1778Schristos 		case '\f':
63030da1778Schristos 			return "\\f";
63130da1778Schristos 		case '\n':
63230da1778Schristos 			return "\\n";
63330da1778Schristos 		case '\r':
63430da1778Schristos 			return "\\r";
63530da1778Schristos 		case '\t':
63630da1778Schristos 			return "\\t";
63730da1778Schristos 		case '\a':
63830da1778Schristos 			return "\\a";
63930da1778Schristos 		case '\v':
64030da1778Schristos 			return "\\v";
64130da1778Schristos 		default:
64230da1778Schristos 			if(trace_hex)
64330da1778Schristos 				snprintf (rform, sizeof(rform), "\\x%.2x", (unsigned int) c);
64430da1778Schristos 			else
64530da1778Schristos 				snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c);
64630da1778Schristos 			return rform;
64730da1778Schristos 		}
64830da1778Schristos 	}
64930da1778Schristos 
65030da1778Schristos 	else if (c == ' ')
65130da1778Schristos 		return "' '";
65230da1778Schristos 
65330da1778Schristos 	else {
6547977e686Schristos 		rform[0] = (char) c;
65530da1778Schristos 		rform[1] = '\0';
65630da1778Schristos 
65730da1778Schristos 		return rform;
65830da1778Schristos 	}
65930da1778Schristos }
66030da1778Schristos 
66130da1778Schristos 
66230da1778Schristos /* reallocate_array - increase the size of a dynamic array */
66330da1778Schristos 
reallocate_array(void * array,int size,size_t element_size)6647977e686Schristos void   *reallocate_array (void *array, int size, size_t element_size)
66530da1778Schristos {
66630da1778Schristos 	void *new_array;
667*596f930cSchristos #if HAVE_REALLOCARRAY
668*596f930cSchristos 	/* reallocarray has built-in overflow detection */
669*596f930cSchristos 	new_array = reallocarray(array, (size_t) size, element_size);
670*596f930cSchristos #else
671*596f930cSchristos 	size_t num_bytes = (size_t) size * element_size;
672*596f930cSchristos 	new_array = (size && SIZE_MAX / (size_t) size < element_size) ? NULL :
673*596f930cSchristos 		realloc(array, num_bytes);
674*596f930cSchristos #endif
67530da1778Schristos 	if (!new_array)
67630da1778Schristos 		flexfatal (_("attempt to increase array size failed"));
67730da1778Schristos 
67830da1778Schristos 	return new_array;
67930da1778Schristos }
68030da1778Schristos 
68130da1778Schristos 
68230da1778Schristos /* skelout - write out one section of the skeleton file
68330da1778Schristos  *
68430da1778Schristos  * Description
68530da1778Schristos  *    Copies skelfile or skel array to stdout until a line beginning with
68630da1778Schristos  *    "%%" or EOF is found.
68730da1778Schristos  */
skelout(void)6887977e686Schristos void skelout (void)
68930da1778Schristos {
69030da1778Schristos 	char    buf_storage[MAXLINE];
69130da1778Schristos 	char   *buf = buf_storage;
69230da1778Schristos 	bool   do_copy = true;
69330da1778Schristos 
69430da1778Schristos     /* "reset" the state by clearing the buffer and pushing a '1' */
69530da1778Schristos     if(sko_len > 0)
69630da1778Schristos         sko_peek(&do_copy);
69730da1778Schristos     sko_len = 0;
69830da1778Schristos     sko_push(do_copy=true);
69930da1778Schristos 
70030da1778Schristos 
70130da1778Schristos 	/* Loop pulling lines either from the skelfile, if we're using
70230da1778Schristos 	 * one, or from the skel[] array.
70330da1778Schristos 	 */
70430da1778Schristos 	while (skelfile ?
70530da1778Schristos 	       (fgets (buf, MAXLINE, skelfile) != NULL) :
70630da1778Schristos 	       ((buf = (char *) skel[skel_ind++]) != 0)) {
70730da1778Schristos 
70830da1778Schristos 		if (skelfile)
70930da1778Schristos 			chomp (buf);
71030da1778Schristos 
71130da1778Schristos 		/* copy from skel array */
71230da1778Schristos 		if (buf[0] == '%') {	/* control line */
71330da1778Schristos 			/* print the control line as a comment. */
71430da1778Schristos 			if (ddebug && buf[1] != '#') {
71530da1778Schristos 				if (buf[strlen (buf) - 1] == '\\')
71630da1778Schristos 					out_str ("/* %s */\\\n", buf);
71730da1778Schristos 				else
71830da1778Schristos 					out_str ("/* %s */\n", buf);
71930da1778Schristos 			}
72030da1778Schristos 
72130da1778Schristos 			/* We've been accused of using cryptic markers in the skel.
72230da1778Schristos 			 * So we'll use emacs-style-hyphenated-commands.
72330da1778Schristos              * We might consider a hash if this if-else-if-else
72430da1778Schristos              * chain gets too large.
72530da1778Schristos 			 */
72630da1778Schristos #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
72730da1778Schristos 
72830da1778Schristos 			if (buf[1] == '%') {
72930da1778Schristos 				/* %% is a break point for skelout() */
73030da1778Schristos 				return;
73130da1778Schristos 			}
73230da1778Schristos             else if (cmd_match (CMD_PUSH)){
73330da1778Schristos                 sko_push(do_copy);
73430da1778Schristos                 if(ddebug){
73530da1778Schristos                     out_str("/*(state = (%s) */",do_copy?"true":"false");
73630da1778Schristos                 }
73730da1778Schristos                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
73830da1778Schristos             }
73930da1778Schristos             else if (cmd_match (CMD_POP)){
74030da1778Schristos                 sko_pop(&do_copy);
74130da1778Schristos                 if(ddebug){
74230da1778Schristos                     out_str("/*(state = (%s) */",do_copy?"true":"false");
74330da1778Schristos                 }
74430da1778Schristos                 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
74530da1778Schristos             }
74630da1778Schristos             else if (cmd_match (CMD_IF_REENTRANT)){
74730da1778Schristos                 sko_push(do_copy);
74830da1778Schristos                 do_copy = reentrant && do_copy;
74930da1778Schristos             }
75030da1778Schristos             else if (cmd_match (CMD_IF_NOT_REENTRANT)){
75130da1778Schristos                 sko_push(do_copy);
75230da1778Schristos                 do_copy = !reentrant && do_copy;
75330da1778Schristos             }
75430da1778Schristos             else if (cmd_match(CMD_IF_BISON_BRIDGE)){
75530da1778Schristos                 sko_push(do_copy);
75630da1778Schristos                 do_copy = bison_bridge_lval && do_copy;
75730da1778Schristos             }
75830da1778Schristos             else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){
75930da1778Schristos                 sko_push(do_copy);
76030da1778Schristos                 do_copy = !bison_bridge_lval && do_copy;
76130da1778Schristos             }
76230da1778Schristos             else if (cmd_match (CMD_ENDIF)){
76330da1778Schristos                 sko_pop(&do_copy);
76430da1778Schristos             }
76530da1778Schristos 			else if (cmd_match (CMD_IF_TABLES_SER)) {
76630da1778Schristos                 do_copy = do_copy && tablesext;
76730da1778Schristos 			}
76830da1778Schristos 			else if (cmd_match (CMD_TABLES_YYDMAP)) {
76930da1778Schristos 				if (tablesext && yydmap_buf.elts)
77030da1778Schristos 					outn ((char *) (yydmap_buf.elts));
77130da1778Schristos 			}
77230da1778Schristos             else if (cmd_match (CMD_DEFINE_YYTABLES)) {
77330da1778Schristos                 out_str("#define YYTABLES_NAME \"%s\"\n",
77430da1778Schristos                         tablesname?tablesname:"yytables");
77530da1778Schristos             }
77630da1778Schristos 			else if (cmd_match (CMD_IF_CPP_ONLY)) {
77730da1778Schristos 				/* only for C++ */
77830da1778Schristos                 sko_push(do_copy);
77930da1778Schristos 				do_copy = C_plus_plus;
78030da1778Schristos 			}
78130da1778Schristos 			else if (cmd_match (CMD_IF_C_ONLY)) {
78230da1778Schristos 				/* %- only for C */
78330da1778Schristos                 sko_push(do_copy);
78430da1778Schristos 				do_copy = !C_plus_plus;
78530da1778Schristos 			}
78630da1778Schristos 			else if (cmd_match (CMD_IF_C_OR_CPP)) {
78730da1778Schristos 				/* %* for C and C++ */
78830da1778Schristos                 sko_push(do_copy);
78930da1778Schristos 				do_copy = true;
79030da1778Schristos 			}
79130da1778Schristos 			else if (cmd_match (CMD_NOT_FOR_HEADER)) {
79230da1778Schristos 				/* %c begin linkage-only (non-header) code. */
79330da1778Schristos 				OUT_BEGIN_CODE ();
79430da1778Schristos 			}
79530da1778Schristos 			else if (cmd_match (CMD_OK_FOR_HEADER)) {
79630da1778Schristos 				/* %e end linkage-only code. */
79730da1778Schristos 				OUT_END_CODE ();
79830da1778Schristos 			}
79930da1778Schristos 			else {
80030da1778Schristos 				flexfatal (_("bad line in skeleton file"));
80130da1778Schristos 			}
80230da1778Schristos 		}
80330da1778Schristos 
80430da1778Schristos 		else if (do_copy)
80530da1778Schristos             outn (buf);
80630da1778Schristos 	}			/* end while */
80730da1778Schristos }
80830da1778Schristos 
80930da1778Schristos 
81030da1778Schristos /* transition_struct_out - output a yy_trans_info structure
81130da1778Schristos  *
81230da1778Schristos  * outputs the yy_trans_info structure with the two elements, element_v and
81330da1778Schristos  * element_n.  Formats the output with spaces and carriage returns.
81430da1778Schristos  */
81530da1778Schristos 
transition_struct_out(int element_v,int element_n)8167977e686Schristos void transition_struct_out (int element_v, int element_n)
81730da1778Schristos {
81830da1778Schristos 
81930da1778Schristos 	/* short circuit any output */
82030da1778Schristos 	if (!gentables)
82130da1778Schristos 		return;
82230da1778Schristos 
82330da1778Schristos 	out_dec2 (" {%4d,%4d },", element_v, element_n);
82430da1778Schristos 
82530da1778Schristos 	datapos += TRANS_STRUCT_PRINT_LENGTH;
82630da1778Schristos 
82730da1778Schristos 	if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
82830da1778Schristos 		outc ('\n');
82930da1778Schristos 
83030da1778Schristos 		if (++dataline % 10 == 0)
83130da1778Schristos 			outc ('\n');
83230da1778Schristos 
83330da1778Schristos 		datapos = 0;
83430da1778Schristos 	}
83530da1778Schristos }
83630da1778Schristos 
83730da1778Schristos 
83830da1778Schristos /* The following is only needed when building flex's parser using certain
83930da1778Schristos  * broken versions of bison.
8407977e686Schristos  *
8417977e686Schristos  * XXX: this is should go soon
84230da1778Schristos  */
yy_flex_xmalloc(int size)8437977e686Schristos void   *yy_flex_xmalloc (int size)
84430da1778Schristos {
8457977e686Schristos 	void   *result;
84630da1778Schristos 
8477977e686Schristos 	result = malloc((size_t) size);
84830da1778Schristos 	if (!result)
84930da1778Schristos 		flexfatal (_
85030da1778Schristos 			   ("memory allocation failed in yy_flex_xmalloc()"));
85130da1778Schristos 
85230da1778Schristos 	return result;
85330da1778Schristos }
85430da1778Schristos 
85530da1778Schristos 
85630da1778Schristos /* Remove all '\n' and '\r' characters, if any, from the end of str.
85730da1778Schristos  * str can be any null-terminated string, or NULL.
85830da1778Schristos  * returns str. */
chomp(char * str)8597977e686Schristos char   *chomp (char *str)
86030da1778Schristos {
86130da1778Schristos 	char   *p = str;
86230da1778Schristos 
86330da1778Schristos 	if (!str || !*str)	/* s is null or empty string */
86430da1778Schristos 		return str;
86530da1778Schristos 
86630da1778Schristos 	/* find end of string minus one */
86730da1778Schristos 	while (*p)
86830da1778Schristos 		++p;
86930da1778Schristos 	--p;
87030da1778Schristos 
87130da1778Schristos 	/* eat newlines */
87230da1778Schristos 	while (p >= str && (*p == '\r' || *p == '\n'))
87330da1778Schristos 		*p-- = 0;
87430da1778Schristos 	return str;
87530da1778Schristos }
876