version 1.14, 2015/10/15 05:57:09 |
version 1.15, 2015/11/19 19:43:40 |
|
|
|
|
/* misc - miscellaneous flex routines */ |
/* misc - miscellaneous flex routines */ |
|
|
/*- |
/* Copyright (c) 1990 The Regents of the University of California. */ |
* Copyright (c) 1990 The Regents of the University of California. |
/* All rights reserved. */ |
* All rights reserved. |
|
* |
|
* This code is derived from software contributed to Berkeley by |
|
* Vern Paxson. |
|
* |
|
* The United States Government has rights in this work pursuant |
|
* to contract no. DE-AC03-76SF00098 between the United States |
|
* Department of Energy and the University of California. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
* are met: |
|
* |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* |
|
* Neither the name of the University nor the names of its contributors |
|
* may be used to endorse or promote products derived from this software |
|
* without specific prior written permission. |
|
* |
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
* PURPOSE. |
|
*/ |
|
|
|
/* $Header$ */ |
/* This code is derived from software contributed to Berkeley by */ |
|
/* Vern Paxson. */ |
|
|
|
/* The United States Government has rights in this work pursuant */ |
|
/* to contract no. DE-AC03-76SF00098 between the United States */ |
|
/* Department of Energy and the University of California. */ |
|
|
|
/* This file is part of flex. */ |
|
|
|
/* Redistribution and use in source and binary forms, with or without */ |
|
/* modification, are permitted provided that the following conditions */ |
|
/* are met: */ |
|
|
|
/* 1. Redistributions of source code must retain the above copyright */ |
|
/* notice, this list of conditions and the following disclaimer. */ |
|
/* 2. Redistributions in binary form must reproduce the above copyright */ |
|
/* notice, this list of conditions and the following disclaimer in the */ |
|
/* documentation and/or other materials provided with the distribution. */ |
|
|
|
/* Neither the name of the University nor the names of its contributors */ |
|
/* may be used to endorse or promote products derived from this software */ |
|
/* without specific prior written permission. */ |
|
|
|
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ |
|
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ |
|
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ |
|
/* PURPOSE. */ |
|
|
#include "flexdef.h" |
#include "flexdef.h" |
|
#include "tables.h" |
|
|
|
#define CMD_IF_TABLES_SER "%if-tables-serialization" |
|
#define CMD_TABLES_YYDMAP "%tables-yydmap" |
|
#define CMD_DEFINE_YYTABLES "%define-yytables" |
|
#define CMD_IF_CPP_ONLY "%if-c++-only" |
|
#define CMD_IF_C_ONLY "%if-c-only" |
|
#define CMD_IF_C_OR_CPP "%if-c-or-c++" |
|
#define CMD_NOT_FOR_HEADER "%not-for-header" |
|
#define CMD_OK_FOR_HEADER "%ok-for-header" |
|
#define CMD_PUSH "%push" |
|
#define CMD_POP "%pop" |
|
#define CMD_IF_REENTRANT "%if-reentrant" |
|
#define CMD_IF_NOT_REENTRANT "%if-not-reentrant" |
|
#define CMD_IF_BISON_BRIDGE "%if-bison-bridge" |
|
#define CMD_IF_NOT_BISON_BRIDGE "%if-not-bison-bridge" |
|
#define CMD_ENDIF "%endif" |
|
|
void action_define( defname, value ) |
/* we allow the skeleton to push and pop. */ |
char *defname; |
struct sko_state { |
int value; |
bool dc; /**< do_copy */ |
{ |
}; |
char buf[MAXLINE]; |
static struct sko_state *sko_stack=0; |
|
static int sko_len=0,sko_sz=0; |
|
static void sko_push(bool dc) |
|
{ |
|
if(!sko_stack){ |
|
sko_sz = 1; |
|
sko_stack = (struct sko_state*)flex_alloc(sizeof(struct sko_state)*sko_sz); |
|
if (!sko_stack) |
|
flexfatal(_("allocation of sko_stack failed")); |
|
sko_len = 0; |
|
} |
|
if(sko_len >= sko_sz){ |
|
sko_sz *= 2; |
|
sko_stack = (struct sko_state*)flex_realloc(sko_stack,sizeof(struct sko_state)*sko_sz); |
|
} |
|
|
|
/* initialize to zero and push */ |
|
sko_stack[sko_len].dc = dc; |
|
sko_len++; |
|
} |
|
static void sko_peek(bool *dc) |
|
{ |
|
if(sko_len <= 0) |
|
flex_die("peek attempt when sko stack is empty"); |
|
if(dc) |
|
*dc = sko_stack[sko_len-1].dc; |
|
} |
|
static void sko_pop(bool* dc) |
|
{ |
|
sko_peek(dc); |
|
sko_len--; |
|
if(sko_len < 0) |
|
flex_die("popped too many times in skeleton."); |
|
} |
|
|
if ( (int) strlen( defname ) > MAXLINE / 2 ) |
/* Append "#define defname value\n" to the running buffer. */ |
{ |
void action_define (defname, value) |
format_pinpoint_message( _( "name \"%s\" ridiculously long" ), |
const char *defname; |
defname ); |
int value; |
|
{ |
|
char buf[MAXLINE]; |
|
char *cpy; |
|
|
|
if ((int) strlen (defname) > MAXLINE / 2) { |
|
format_pinpoint_message (_ |
|
("name \"%s\" ridiculously long"), |
|
defname); |
return; |
return; |
} |
} |
|
|
snprintf( buf, sizeof buf, "#define %s %d\n", defname, value ); |
snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value); |
add_action( buf ); |
add_action (buf); |
|
|
|
/* track #defines so we can undef them when we're done. */ |
|
cpy = copy_string (defname); |
|
buf_append (&defs_buf, &cpy, 1); |
|
} |
|
|
|
|
|
/** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer. |
|
* @param defname The macro name. |
|
* @param value The macro value, can be NULL, which is the same as the empty string. |
|
*/ |
|
void action_m4_define (const char *defname, const char * value) |
|
{ |
|
char buf[MAXLINE]; |
|
|
|
flexfatal ("DO NOT USE THIS FUNCTION!"); |
|
|
|
if ((int) strlen (defname) > MAXLINE / 2) { |
|
format_pinpoint_message (_ |
|
("name \"%s\" ridiculously long"), |
|
defname); |
|
return; |
} |
} |
|
|
|
snprintf (buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value?value:""); |
|
add_action (buf); |
|
} |
|
|
void add_action( new_text ) |
/* Append "new_text" to the running buffer. */ |
char *new_text; |
void add_action (new_text) |
{ |
const char *new_text; |
int len = strlen( new_text ); |
{ |
|
int len = strlen (new_text); |
|
|
while ( len + action_index >= action_size - 10 /* slop */ ) |
while (len + action_index >= action_size - 10 /* slop */ ) { |
{ |
int new_size = action_size * 2; |
int new_size = action_size * 2; |
|
|
|
if ( new_size <= 0 ) |
if (new_size <= 0) |
/* Increase just a little, to try to avoid overflow |
/* Increase just a little, to try to avoid overflow |
* on 16-bit machines. |
* on 16-bit machines. |
*/ |
*/ |
|
|
action_size = new_size; |
action_size = new_size; |
|
|
action_array = |
action_array = |
reallocate_character_array( action_array, action_size ); |
reallocate_character_array (action_array, |
} |
action_size); |
|
} |
|
|
strlcpy( &action_array[action_index], new_text, |
strlcpy ( &action_array[action_index], new_text, |
action_size - action_index ); |
action_size - action_index ); |
|
|
action_index += len; |
action_index += len; |
} |
} |
|
|
|
|
/* allocate_array - allocate memory for an integer array of the given size */ |
/* allocate_array - allocate memory for an integer array of the given size */ |
|
|
void *allocate_array( size, element_size ) |
void *allocate_array (size, element_size) |
int size; |
int size; |
size_t element_size; |
size_t element_size; |
{ |
{ |
void *mem; |
void *mem; |
size_t num_bytes = element_size * size; |
size_t num_bytes = element_size * size; |
|
|
mem = flex_alloc( num_bytes ); |
mem = flex_alloc (num_bytes); |
if ( ! mem ) |
if (!mem) |
flexfatal( |
flexfatal (_ |
_( "memory allocation failed in allocate_array()" ) ); |
("memory allocation failed in allocate_array()")); |
|
|
return mem; |
return mem; |
} |
} |
|
|
|
|
/* all_lower - true if a string is all lower-case */ |
/* all_lower - true if a string is all lower-case */ |
|
|
int all_lower( str ) |
int all_lower (str) |
char *str; |
char *str; |
{ |
{ |
while ( *str ) |
while (*str) { |
{ |
if (!isascii ((Char) * str) || !islower ((Char) * str)) |
if ( ! isascii( (Char) *str ) || ! islower( (Char) *str ) ) |
|
return 0; |
return 0; |
++str; |
++str; |
} |
} |
|
|
return 1; |
return 1; |
} |
} |
|
|
|
|
/* all_upper - true if a string is all upper-case */ |
/* all_upper - true if a string is all upper-case */ |
|
|
int all_upper( str ) |
int all_upper (str) |
char *str; |
char *str; |
{ |
{ |
while ( *str ) |
while (*str) { |
{ |
if (!isascii ((Char) * str) || !isupper ((Char) * str)) |
if ( ! isascii( (Char) *str ) || ! isupper( (Char) *str ) ) |
|
return 0; |
return 0; |
++str; |
++str; |
} |
} |
|
|
return 1; |
return 1; |
} |
} |
|
|
|
|
/* bubble - bubble sort an integer array in increasing order |
/* intcmp - compares two integers for use by qsort. */ |
* |
|
* synopsis |
|
* int v[n], n; |
|
* void bubble( v, n ); |
|
* |
|
* description |
|
* sorts the first n elements of array v and replaces them in |
|
* increasing order. |
|
* |
|
* passed |
|
* v - the array to be sorted |
|
* n - the number of elements of 'v' to be sorted |
|
*/ |
|
|
|
void bubble( v, n ) |
int intcmp (const void *a, const void *b) |
int v[], n; |
{ |
{ |
return *(const int *) a - *(const int *) b; |
int i, j, k; |
} |
|
|
for ( i = n; i > 1; --i ) |
|
for ( j = 1; j < i; ++j ) |
|
if ( v[j] > v[j + 1] ) /* compare */ |
|
{ |
|
k = v[j]; /* exchange */ |
|
v[j] = v[j + 1]; |
|
v[j + 1] = k; |
|
} |
|
} |
|
|
|
|
|
/* check_char - checks a character to make sure it's within the range |
/* check_char - checks a character to make sure it's within the range |
* we're expecting. If not, generates fatal error message |
* we're expecting. If not, generates fatal error message |
* and exits. |
* and exits. |
*/ |
*/ |
|
|
void check_char( c ) |
void check_char (c) |
int c; |
int c; |
{ |
{ |
if ( c >= CSIZE ) |
if (c >= CSIZE) |
lerrsf( _( "bad character '%s' detected in check_char()" ), |
lerrsf (_("bad character '%s' detected in check_char()"), |
readable_form( c ) ); |
readable_form (c)); |
|
|
if ( c >= csize ) |
if (c >= csize) |
lerrsf( |
lerrsf (_ |
_( "scanner requires -8 flag to use the character %s" ), |
("scanner requires -8 flag to use the character %s"), |
readable_form( c ) ); |
readable_form (c)); |
} |
} |
|
|
|
|
|
|
/* clower - replace upper-case letter to lower-case */ |
/* clower - replace upper-case letter to lower-case */ |
|
|
Char clower( c ) |
Char clower (c) |
int c; |
int c; |
{ |
{ |
return (Char) ((isascii( c ) && isupper( c )) ? tolower( c ) : c); |
return (Char) ((isascii (c) && isupper (c)) ? tolower (c) : c); |
} |
} |
|
|
|
|
/* copy_string - returns a dynamically allocated copy of a string */ |
/* copy_string - returns a dynamically allocated copy of a string */ |
|
|
char *copy_string( str ) |
char *copy_string (str) |
const char *str; |
const char *str; |
{ |
{ |
const char *c1; |
const char *c1; |
char *c2; |
char *c2; |
char *copy; |
char *copy; |
unsigned int size; |
unsigned int size; |
|
|
/* find length */ |
/* find length */ |
for ( c1 = str; *c1; ++c1 ) |
for (c1 = str; *c1; ++c1) ; |
; |
|
|
|
size = (c1 - str + 1) * sizeof( char ); |
size = (c1 - str + 1) * sizeof (char); |
copy = (char *) flex_alloc( size ); |
|
|
|
if ( copy == NULL ) |
copy = (char *) flex_alloc (size); |
flexfatal( _( "dynamic memory failure in copy_string()" ) ); |
|
|
|
for ( c2 = copy; (*c2++ = *str++) != 0; ) |
if (copy == NULL) |
; |
flexfatal (_("dynamic memory failure in copy_string()")); |
|
|
|
for (c2 = copy; (*c2++ = *str++) != 0;) ; |
|
|
return copy; |
return copy; |
} |
} |
|
|
|
|
/* copy_unsigned_string - |
/* copy_unsigned_string - |
* returns a dynamically allocated copy of a (potentially) unsigned string |
* returns a dynamically allocated copy of a (potentially) unsigned string |
*/ |
*/ |
|
|
Char *copy_unsigned_string( str ) |
Char *copy_unsigned_string (str) |
Char *str; |
Char *str; |
{ |
{ |
Char *c; |
Char *c; |
Char *copy; |
Char *copy; |
|
|
/* find length */ |
/* find length */ |
for ( c = str; *c; ++c ) |
for (c = str; *c; ++c) ; |
; |
|
|
|
copy = allocate_Character_array( c - str + 1 ); |
copy = allocate_Character_array (c - str + 1); |
|
|
for ( c = copy; (*c++ = *str++) != 0; ) |
for (c = copy; (*c++ = *str++) != 0;) ; |
; |
|
|
|
return copy; |
return copy; |
} |
} |
|
|
|
|
/* cshell - shell sort a character array in increasing order |
/* cclcmp - compares two characters for use by qsort with '\0' sorting last. */ |
* |
|
* synopsis |
|
* |
|
* Char v[n]; |
|
* int n, special_case_0; |
|
* cshell( v, n, special_case_0 ); |
|
* |
|
* description |
|
* Does a shell sort of the first n elements of array v. |
|
* If special_case_0 is true, then any element equal to 0 |
|
* is instead assumed to have infinite weight. |
|
* |
|
* passed |
|
* v - array to be sorted |
|
* n - number of elements of v to be sorted |
|
*/ |
|
|
|
void cshell( v, n, special_case_0 ) |
int cclcmp (const void *a, const void *b) |
Char v[]; |
{ |
int n, special_case_0; |
if (!*(const Char *) a) |
{ |
return 1; |
int gap, i, j, jg; |
else |
Char k; |
if (!*(const Char *) b) |
|
return - 1; |
|
else |
|
return *(const Char *) a - *(const Char *) b; |
|
} |
|
|
for ( gap = n / 2; gap > 0; gap = gap / 2 ) |
|
for ( i = gap; i < n; ++i ) |
|
for ( j = i - gap; j >= 0; j = j - gap ) |
|
{ |
|
jg = j + gap; |
|
|
|
if ( special_case_0 ) |
|
{ |
|
if ( v[jg] == 0 ) |
|
break; |
|
|
|
else if ( v[j] != 0 && v[j] <= v[jg] ) |
|
break; |
|
} |
|
|
|
else if ( v[j] <= v[jg] ) |
|
break; |
|
|
|
k = v[j]; |
|
v[j] = v[jg]; |
|
v[jg] = k; |
|
} |
|
} |
|
|
|
|
|
/* dataend - finish up a block of data declarations */ |
/* dataend - finish up a block of data declarations */ |
|
|
void dataend() |
void dataend () |
{ |
{ |
if ( datapos > 0 ) |
/* short circuit any output */ |
dataflush(); |
if (gentables) { |
|
|
/* add terminator for initialization; { for vi */ |
if (datapos > 0) |
outn( " } ;\n" ); |
dataflush (); |
|
|
|
/* add terminator for initialization; { for vi */ |
|
outn (" } ;\n"); |
|
} |
dataline = 0; |
dataline = 0; |
datapos = 0; |
datapos = 0; |
} |
} |
|
|
|
|
/* dataflush - flush generated data statements */ |
/* dataflush - flush generated data statements */ |
|
|
void dataflush() |
void dataflush () |
{ |
{ |
outc( '\n' ); |
/* short circuit any output */ |
|
if (!gentables) |
|
return; |
|
|
if ( ++dataline >= NUMDATALINES ) |
outc ('\n'); |
{ |
|
|
if (++dataline >= NUMDATALINES) { |
/* Put out a blank line so that the table is grouped into |
/* Put out a blank line so that the table is grouped into |
* large blocks that enable the user to find elements easily. |
* large blocks that enable the user to find elements easily. |
*/ |
*/ |
outc( '\n' ); |
outc ('\n'); |
dataline = 0; |
dataline = 0; |
} |
} |
|
|
/* Reset the number of characters written on the current line. */ |
/* Reset the number of characters written on the current line. */ |
datapos = 0; |
datapos = 0; |
} |
} |
|
|
|
|
/* flexerror - report an error message and terminate */ |
/* flexerror - report an error message and terminate */ |
|
|
void flexerror( msg ) |
void flexerror (msg) |
const char msg[]; |
const char *msg; |
{ |
{ |
fprintf( stderr, "%s: %s\n", program_name, msg ); |
fprintf (stderr, "%s: %s\n", program_name, msg); |
flexend( 1 ); |
flexend (1); |
} |
} |
|
|
|
|
/* flexfatal - report a fatal error message and terminate */ |
/* flexfatal - report a fatal error message and terminate */ |
|
|
void flexfatal( msg ) |
void flexfatal (msg) |
const char msg[]; |
const char *msg; |
{ |
{ |
fprintf( stderr, _( "%s: fatal internal error, %s\n" ), |
fprintf (stderr, _("%s: fatal internal error, %s\n"), |
program_name, msg ); |
program_name, msg); |
exit( 1 ); |
FLEX_EXIT (1); |
} |
} |
|
|
|
|
/* htoi - convert a hexadecimal digit string to an integer value */ |
/* htoi - convert a hexadecimal digit string to an integer value */ |
|
|
int htoi( str ) |
int htoi (str) |
Char str[]; |
Char str[]; |
{ |
{ |
unsigned int result; |
unsigned int result; |
|
|
(void) sscanf( (char *) str, "%x", &result ); |
(void) sscanf ((char *) str, "%x", &result); |
|
|
return result; |
return result; |
} |
} |
|
|
|
|
/* lerrif - report an error message formatted with one integer argument */ |
/* lerrif - report an error message formatted with one integer argument */ |
|
|
void lerrif( msg, arg ) |
void lerrif (msg, arg) |
const char msg[]; |
const char *msg; |
int arg; |
int arg; |
{ |
{ |
char errmsg[MAXLINE]; |
char errmsg[MAXLINE]; |
(void) snprintf( errmsg, sizeof errmsg, msg, arg ); |
|
flexerror( errmsg ); |
|
} |
|
|
|
|
snprintf (errmsg, sizeof(errmsg), msg, arg); |
|
flexerror (errmsg); |
|
} |
|
|
|
|
/* lerrsf - report an error message formatted with one string argument */ |
/* lerrsf - report an error message formatted with one string argument */ |
|
|
void lerrsf( msg, arg ) |
void lerrsf (msg, arg) |
const char msg[], arg[]; |
const char *msg, arg[]; |
{ |
{ |
char errmsg[MAXLINE]; |
char errmsg[MAXLINE]; |
|
|
(void) snprintf( errmsg, sizeof errmsg, msg, arg ); |
snprintf (errmsg, sizeof(errmsg)-1, msg, arg); |
flexerror( errmsg ); |
errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */ |
} |
flexerror (errmsg); |
|
} |
|
|
|
|
|
/* lerrsf_fatal - as lerrsf, but call flexfatal */ |
|
|
|
void lerrsf_fatal (msg, arg) |
|
const char *msg, arg[]; |
|
{ |
|
char errmsg[MAXLINE]; |
|
|
|
snprintf (errmsg, sizeof(errmsg)-1, msg, arg); |
|
errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */ |
|
flexfatal (errmsg); |
|
} |
|
|
|
|
/* line_directive_out - spit out a "#line" statement */ |
/* line_directive_out - spit out a "#line" statement */ |
|
|
void line_directive_out( output_file, do_infile ) |
void line_directive_out (output_file, do_infile) |
FILE *output_file; |
FILE *output_file; |
int do_infile; |
int do_infile; |
{ |
{ |
char directive[MAXLINE], filename[MAXLINE]; |
char directive[MAXLINE], filename[MAXLINE]; |
char *s1, *s2, *s3; |
char *s1, *s2, *s3; |
static const char line_fmt[] = "#line %d \"%s\"\n"; |
static const char *line_fmt = "#line %d \"%s\"\n"; |
|
|
if ( ! gen_line_dirs ) |
if (!gen_line_dirs) |
return; |
return; |
|
|
if ( (do_infile && ! infilename) || (! do_infile && ! outfilename) ) |
s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME"; |
/* don't know the filename to use, skip */ |
|
return; |
|
|
|
s1 = do_infile ? infilename : outfilename; |
if (do_infile && !s1) |
|
s1 = "<stdin>"; |
|
|
s2 = filename; |
s2 = filename; |
s3 = &filename[sizeof( filename ) - 2]; |
s3 = &filename[sizeof (filename) - 2]; |
|
|
while ( s2 < s3 && *s1 ) |
while (s2 < s3 && *s1) { |
{ |
if (*s1 == '\\') |
if ( *s1 == '\\' ) |
|
/* Escape the '\' */ |
/* Escape the '\' */ |
*s2++ = '\\'; |
*s2++ = '\\'; |
|
|
*s2++ = *s1++; |
*s2++ = *s1++; |
} |
} |
|
|
*s2 = '\0'; |
*s2 = '\0'; |
|
|
if ( do_infile ) |
if (do_infile) |
snprintf( directive, sizeof directive, line_fmt, |
snprintf (directive, sizeof(directive), line_fmt, linenum, filename); |
linenum, filename ); |
else { |
else |
snprintf (directive, sizeof(directive), line_fmt, 0, filename); |
{ |
} |
if ( output_file == stdout ) |
|
/* Account for the line directive itself. */ |
|
++out_linenum; |
|
|
|
snprintf( directive, sizeof directive, line_fmt, |
|
out_linenum, filename ); |
|
} |
|
|
|
/* If output_file is nil then we should put the directive in |
/* If output_file is nil then we should put the directive in |
* the accumulated actions. |
* the accumulated actions. |
*/ |
*/ |
if ( output_file ) |
if (output_file) { |
{ |
fputs (directive, output_file); |
fputs( directive, output_file ); |
|
} |
|
else |
|
add_action( directive ); |
|
} |
} |
|
else |
|
add_action (directive); |
|
} |
|
|
|
|
/* mark_defs1 - mark the current position in the action array as |
/* mark_defs1 - mark the current position in the action array as |
* representing where the user's section 1 definitions end |
* representing where the user's section 1 definitions end |
* and the prolog begins |
* and the prolog begins |
*/ |
*/ |
void mark_defs1() |
void mark_defs1 () |
{ |
{ |
defs1_offset = 0; |
defs1_offset = 0; |
action_array[action_index++] = '\0'; |
action_array[action_index++] = '\0'; |
action_offset = prolog_offset = action_index; |
action_offset = prolog_offset = action_index; |
action_array[action_index] = '\0'; |
action_array[action_index] = '\0'; |
} |
} |
|
|
|
|
/* mark_prolog - mark the current position in the action array as |
/* mark_prolog - mark the current position in the action array as |
* representing the end of the action prolog |
* representing the end of the action prolog |
*/ |
*/ |
void mark_prolog() |
void mark_prolog () |
{ |
{ |
action_array[action_index++] = '\0'; |
action_array[action_index++] = '\0'; |
action_offset = action_index; |
action_offset = action_index; |
action_array[action_index] = '\0'; |
action_array[action_index] = '\0'; |
} |
} |
|
|
|
|
/* mk2data - generate a data statement for a two-dimensional array |
/* mk2data - generate a data statement for a two-dimensional array |
* |
* |
* Generates a data statement initializing the current 2-D array to "value". |
* Generates a data statement initializing the current 2-D array to "value". |
*/ |
*/ |
void mk2data( value ) |
void mk2data (value) |
int value; |
int value; |
{ |
{ |
if ( datapos >= NUMDATAITEMS ) |
/* short circuit any output */ |
{ |
if (!gentables) |
outc( ',' ); |
return; |
dataflush(); |
|
} |
|
|
|
if ( datapos == 0 ) |
if (datapos >= NUMDATAITEMS) { |
|
outc (','); |
|
dataflush (); |
|
} |
|
|
|
if (datapos == 0) |
/* Indent. */ |
/* Indent. */ |
out( " " ); |
out (" "); |
|
|
else |
else |
outc( ',' ); |
outc (','); |
|
|
++datapos; |
++datapos; |
|
|
out_dec( "%5d", value ); |
out_dec ("%5d", value); |
} |
} |
|
|
|
|
/* mkdata - generate a data statement |
/* mkdata - generate a data statement |
|
|
* Generates a data statement initializing the current array element to |
* Generates a data statement initializing the current array element to |
* "value". |
* "value". |
*/ |
*/ |
void mkdata( value ) |
void mkdata (value) |
int value; |
int value; |
{ |
{ |
if ( datapos >= NUMDATAITEMS ) |
/* short circuit any output */ |
{ |
if (!gentables) |
outc( ',' ); |
return; |
dataflush(); |
|
} |
|
|
|
if ( datapos == 0 ) |
if (datapos >= NUMDATAITEMS) { |
|
outc (','); |
|
dataflush (); |
|
} |
|
|
|
if (datapos == 0) |
/* Indent. */ |
/* Indent. */ |
out( " " ); |
out (" "); |
else |
else |
outc( ',' ); |
outc (','); |
|
|
++datapos; |
++datapos; |
|
|
out_dec( "%5d", value ); |
out_dec ("%5d", value); |
} |
} |
|
|
|
|
/* myctoi - return the integer represented by a string of digits */ |
/* myctoi - return the integer represented by a string of digits */ |
|
|
int myctoi( array ) |
int myctoi (array) |
char array[]; |
const char *array; |
{ |
{ |
int val = 0; |
int val = 0; |
|
|
(void) sscanf( array, "%d", &val ); |
(void) sscanf (array, "%d", &val); |
|
|
return val; |
return val; |
} |
} |
|
|
|
|
/* myesc - return character corresponding to escape sequence */ |
/* myesc - return character corresponding to escape sequence */ |
|
|
Char myesc( array ) |
Char myesc (array) |
Char array[]; |
Char array[]; |
{ |
{ |
Char c, esc_char; |
Char c, esc_char; |
|
|
switch ( array[1] ) |
switch (array[1]) { |
{ |
case 'b': |
case 'b': return '\b'; |
return '\b'; |
case 'f': return '\f'; |
case 'f': |
case 'n': return '\n'; |
return '\f'; |
case 'r': return '\r'; |
case 'n': |
case 't': return '\t'; |
return '\n'; |
|
case 'r': |
|
return '\r'; |
|
case 't': |
|
return '\t'; |
|
|
#ifdef __STDC__ |
#if defined (__STDC__) |
case 'a': return '\a'; |
case 'a': |
case 'v': return '\v'; |
return '\a'; |
|
case 'v': |
|
return '\v'; |
#else |
#else |
case 'a': return '\007'; |
case 'a': |
case 'v': return '\013'; |
return '\007'; |
|
case 'v': |
|
return '\013'; |
#endif |
#endif |
|
|
case '0': |
case '0': |
case '1': |
case '1': |
case '2': |
case '2': |
case '3': |
case '3': |
case '4': |
case '4': |
case '5': |
case '5': |
case '6': |
case '6': |
case '7': |
case '7': |
{ /* \<octal> */ |
{ /* \<octal> */ |
int sptr = 1; |
int sptr = 1; |
|
|
while ( isascii( array[sptr] ) && |
while (isascii (array[sptr]) && |
isdigit( array[sptr] ) ) |
isdigit (array[sptr])) |
/* Don't increment inside loop control |
/* Don't increment inside loop control |
* because if isdigit() is a macro it might |
* because if isdigit() is a macro it might |
* expand into multiple increments ... |
* expand into multiple increments ... |
|
|
c = array[sptr]; |
c = array[sptr]; |
array[sptr] = '\0'; |
array[sptr] = '\0'; |
|
|
esc_char = otoi( array + 1 ); |
esc_char = otoi (array + 1); |
|
|
array[sptr] = c; |
array[sptr] = c; |
|
|
return esc_char; |
return esc_char; |
} |
} |
|
|
case 'x': |
case 'x': |
{ /* \x<hex> */ |
{ /* \x<hex> */ |
int sptr = 2; |
int sptr = 2; |
|
|
while ( isascii( array[sptr] ) && |
while (isascii (array[sptr]) && |
isxdigit( array[sptr] ) ) |
isxdigit (array[sptr])) |
/* Don't increment inside loop control |
/* Don't increment inside loop control |
* because if isdigit() is a macro it might |
* because if isdigit() is a macro it might |
* expand into multiple increments ... |
* expand into multiple increments ... |
|
|
c = array[sptr]; |
c = array[sptr]; |
array[sptr] = '\0'; |
array[sptr] = '\0'; |
|
|
esc_char = htoi( array + 2 ); |
esc_char = htoi (array + 2); |
|
|
array[sptr] = c; |
array[sptr] = c; |
|
|
return esc_char; |
return esc_char; |
} |
|
|
|
default: |
|
return array[1]; |
|
} |
} |
|
|
|
default: |
|
return array[1]; |
} |
} |
|
} |
|
|
|
|
/* otoi - convert an octal digit string to an integer value */ |
/* otoi - convert an octal digit string to an integer value */ |
|
|
int otoi( str ) |
int otoi (str) |
Char str[]; |
Char str[]; |
{ |
{ |
unsigned int result; |
unsigned int result; |
|
|
(void) sscanf( (char *) str, "%o", &result ); |
(void) sscanf ((char *) str, "%o", &result); |
return result; |
return result; |
} |
} |
|
|
|
|
/* out - various flavors of outputing a (possibly formatted) string for the |
/* out - various flavors of outputing a (possibly formatted) string for the |
* generated scanner, keeping track of the line count. |
* generated scanner, keeping track of the line count. |
*/ |
*/ |
|
|
void out( str ) |
void out (str) |
const char str[]; |
const char *str; |
{ |
{ |
fputs( str, stdout ); |
fputs (str, stdout); |
out_line_count( str ); |
} |
} |
|
|
|
void out_dec( fmt, n ) |
void out_dec (fmt, n) |
const char fmt[]; |
const char *fmt; |
int n; |
int n; |
{ |
{ |
printf( fmt, n ); |
fprintf (stdout, fmt, n); |
out_line_count( fmt ); |
} |
} |
|
|
|
void out_dec2( fmt, n1, n2 ) |
void out_dec2 (fmt, n1, n2) |
const char fmt[]; |
const char *fmt; |
int n1, n2; |
int n1, n2; |
{ |
{ |
printf( fmt, n1, n2 ); |
fprintf (stdout, fmt, n1, n2); |
out_line_count( fmt ); |
} |
} |
|
|
|
void out_hex( fmt, x ) |
void out_hex (fmt, x) |
const char fmt[]; |
const char *fmt; |
unsigned int x; |
unsigned int x; |
{ |
{ |
printf( fmt, x ); |
fprintf (stdout, fmt, x); |
out_line_count( fmt ); |
} |
} |
|
|
|
void out_line_count( str ) |
void out_str (fmt, str) |
const char str[]; |
const char *fmt, str[]; |
{ |
{ |
int i; |
fprintf (stdout,fmt, str); |
|
} |
|
|
for ( i = 0; str[i]; ++i ) |
void out_str3 (fmt, s1, s2, s3) |
if ( str[i] == '\n' ) |
const char *fmt, s1[], s2[], s3[]; |
++out_linenum; |
{ |
} |
fprintf (stdout,fmt, s1, s2, s3); |
|
} |
|
|
void out_str( fmt, str ) |
void out_str_dec (fmt, str, n) |
const char fmt[], str[]; |
const char *fmt, str[]; |
{ |
int n; |
printf( fmt, str ); |
{ |
out_line_count( fmt ); |
fprintf (stdout,fmt, str, n); |
out_line_count( str ); |
} |
} |
|
|
|
void out_str3( fmt, s1, s2, s3 ) |
void outc (c) |
const char fmt[], s1[], s2[], s3[]; |
int c; |
{ |
{ |
printf( fmt, s1, s2, s3 ); |
fputc (c, stdout); |
out_line_count( fmt ); |
} |
out_line_count( s1 ); |
|
out_line_count( s2 ); |
|
out_line_count( s3 ); |
|
} |
|
|
|
void out_str_dec( fmt, str, n ) |
void outn (str) |
const char fmt[], str[]; |
const char *str; |
int n; |
{ |
{ |
fputs (str,stdout); |
printf( fmt, str, n ); |
fputc('\n',stdout); |
out_line_count( fmt ); |
} |
out_line_count( str ); |
|
} |
|
|
|
void outc( c ) |
/** Print "m4_define( [[def]], [[val]])m4_dnl\n". |
int c; |
* @param def The m4 symbol to define. |
{ |
* @param val The definition; may be NULL. |
putc( c, stdout ); |
* @return buf |
|
*/ |
|
void out_m4_define (const char* def, const char* val) |
|
{ |
|
const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; |
|
fprintf(stdout, fmt, def, val?val:""); |
|
} |
|
|
if ( c == '\n' ) |
|
++out_linenum; |
|
} |
|
|
|
void outn( str ) |
|
const char str[]; |
|
{ |
|
puts( str ); |
|
out_line_count( str ); |
|
++out_linenum; |
|
} |
|
|
|
|
|
/* readable_form - return the human-readable form of a character |
/* readable_form - return the human-readable form of a character |
* |
* |
* The returned string is in static storage. |
* The returned string is in static storage. |
*/ |
*/ |
|
|
char *readable_form( c ) |
char *readable_form (c) |
int c; |
int c; |
{ |
{ |
static char rform[10]; |
static char rform[10]; |
|
|
if ( (c >= 0 && c < 32) || c >= 127 ) |
if ((c >= 0 && c < 32) || c >= 127) { |
{ |
switch (c) { |
switch ( c ) |
case '\b': |
{ |
return "\\b"; |
case '\b': return "\\b"; |
case '\f': |
case '\f': return "\\f"; |
return "\\f"; |
case '\n': return "\\n"; |
case '\n': |
case '\r': return "\\r"; |
return "\\n"; |
case '\t': return "\\t"; |
case '\r': |
|
return "\\r"; |
|
case '\t': |
|
return "\\t"; |
|
|
#ifdef __STDC__ |
#if defined (__STDC__) |
case '\a': return "\\a"; |
case '\a': |
case '\v': return "\\v"; |
return "\\a"; |
|
case '\v': |
|
return "\\v"; |
#endif |
#endif |
|
|
default: |
default: |
(void) snprintf( rform, sizeof rform, |
snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c); |
"\\%.3o", (unsigned int) c ); |
return rform; |
return rform; |
|
} |
|
} |
} |
|
} |
|
|
else if ( c == ' ' ) |
else if (c == ' ') |
return "' '"; |
return "' '"; |
|
|
else |
else { |
{ |
|
rform[0] = c; |
rform[0] = c; |
rform[1] = '\0'; |
rform[1] = '\0'; |
|
|
return rform; |
return rform; |
} |
|
} |
} |
|
} |
|
|
|
|
/* reallocate_array - increase the size of a dynamic array */ |
/* reallocate_array - increase the size of a dynamic array */ |
|
|
void *reallocate_array( array, size, element_size ) |
void *reallocate_array (array, size, element_size) |
void *array; |
void *array; |
int size; |
int size; |
size_t element_size; |
size_t element_size; |
{ |
{ |
void *new_array; |
void *new_array; |
size_t num_bytes = element_size * size; |
size_t num_bytes = element_size * size; |
|
|
new_array = flex_realloc( array, num_bytes ); |
new_array = flex_realloc (array, num_bytes); |
if ( ! new_array ) |
if (!new_array) |
flexfatal( _( "attempt to increase array size failed" ) ); |
flexfatal (_("attempt to increase array size failed")); |
|
|
return new_array; |
return new_array; |
} |
} |
|
|
|
|
/* skelout - write out one section of the skeleton file |
/* skelout - write out one section of the skeleton file |
|
|
* Copies skelfile or skel array to stdout until a line beginning with |
* Copies skelfile or skel array to stdout until a line beginning with |
* "%%" or EOF is found. |
* "%%" or EOF is found. |
*/ |
*/ |
void skelout() |
void skelout () |
{ |
{ |
char buf_storage[MAXLINE]; |
char buf_storage[MAXLINE]; |
char *buf = buf_storage; |
char *buf = buf_storage; |
int do_copy = 1; |
bool do_copy = true; |
|
|
|
/* "reset" the state by clearing the buffer and pushing a '1' */ |
|
if(sko_len > 0) |
|
sko_peek(&do_copy); |
|
sko_len = 0; |
|
sko_push(do_copy=true); |
|
|
|
|
/* Loop pulling lines either from the skelfile, if we're using |
/* Loop pulling lines either from the skelfile, if we're using |
* one, or from the skel[] array. |
* one, or from the skel[] array. |
*/ |
*/ |
while ( skelfile ? |
while (skelfile ? |
(fgets( buf, MAXLINE, skelfile ) != NULL) : |
(fgets (buf, MAXLINE, skelfile) != NULL) : |
((buf = (char *) skel[skel_ind++]) != 0) ) |
((buf = (char *) skel[skel_ind++]) != 0)) { |
{ /* copy from skel array */ |
|
if ( buf[0] == '%' ) |
|
{ /* control line */ |
|
switch ( buf[1] ) |
|
{ |
|
case '%': |
|
return; |
|
|
|
case '+': |
if (skelfile) |
do_copy = C_plus_plus; |
chomp (buf); |
break; |
|
|
|
case '-': |
/* copy from skel array */ |
do_copy = ! C_plus_plus; |
if (buf[0] == '%') { /* control line */ |
break; |
/* print the control line as a comment. */ |
|
if (ddebug && buf[1] != '#') { |
|
if (buf[strlen (buf) - 1] == '\\') |
|
out_str ("/* %s */\\\n", buf); |
|
else |
|
out_str ("/* %s */\n", buf); |
|
} |
|
|
case '*': |
/* We've been accused of using cryptic markers in the skel. |
do_copy = 1; |
* So we'll use emacs-style-hyphenated-commands. |
break; |
* We might consider a hash if this if-else-if-else |
|
* chain gets too large. |
|
*/ |
|
#define cmd_match(s) (strncmp(buf,(s),strlen(s))==0) |
|
|
default: |
if (buf[1] == '%') { |
flexfatal( |
/* %% is a break point for skelout() */ |
_( "bad line in skeleton file" ) ); |
return; |
} |
|
} |
} |
|
else if (cmd_match (CMD_PUSH)){ |
else if ( do_copy ) |
sko_push(do_copy); |
{ |
if(ddebug){ |
if ( skelfile ) |
out_str("/*(state = (%s) */",do_copy?"true":"false"); |
/* Skeleton file reads include final |
} |
* newline, skel[] array does not. |
out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : ""); |
*/ |
} |
out( buf ); |
else if (cmd_match (CMD_POP)){ |
else |
sko_pop(&do_copy); |
outn( buf ); |
if(ddebug){ |
|
out_str("/*(state = (%s) */",do_copy?"true":"false"); |
|
} |
|
out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : ""); |
|
} |
|
else if (cmd_match (CMD_IF_REENTRANT)){ |
|
sko_push(do_copy); |
|
do_copy = reentrant && do_copy; |
|
} |
|
else if (cmd_match (CMD_IF_NOT_REENTRANT)){ |
|
sko_push(do_copy); |
|
do_copy = !reentrant && do_copy; |
|
} |
|
else if (cmd_match(CMD_IF_BISON_BRIDGE)){ |
|
sko_push(do_copy); |
|
do_copy = bison_bridge_lval && do_copy; |
|
} |
|
else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){ |
|
sko_push(do_copy); |
|
do_copy = !bison_bridge_lval && do_copy; |
|
} |
|
else if (cmd_match (CMD_ENDIF)){ |
|
sko_pop(&do_copy); |
|
} |
|
else if (cmd_match (CMD_IF_TABLES_SER)) { |
|
do_copy = do_copy && tablesext; |
} |
} |
|
else if (cmd_match (CMD_TABLES_YYDMAP)) { |
|
if (tablesext && yydmap_buf.elts) |
|
outn ((char *) (yydmap_buf.elts)); |
|
} |
|
else if (cmd_match (CMD_DEFINE_YYTABLES)) { |
|
out_str("#define YYTABLES_NAME \"%s\"\n", |
|
tablesname?tablesname:"yytables"); |
|
} |
|
else if (cmd_match (CMD_IF_CPP_ONLY)) { |
|
/* only for C++ */ |
|
sko_push(do_copy); |
|
do_copy = C_plus_plus; |
|
} |
|
else if (cmd_match (CMD_IF_C_ONLY)) { |
|
/* %- only for C */ |
|
sko_push(do_copy); |
|
do_copy = !C_plus_plus; |
|
} |
|
else if (cmd_match (CMD_IF_C_OR_CPP)) { |
|
/* %* for C and C++ */ |
|
sko_push(do_copy); |
|
do_copy = true; |
|
} |
|
else if (cmd_match (CMD_NOT_FOR_HEADER)) { |
|
/* %c begin linkage-only (non-header) code. */ |
|
OUT_BEGIN_CODE (); |
|
} |
|
else if (cmd_match (CMD_OK_FOR_HEADER)) { |
|
/* %e end linkage-only code. */ |
|
OUT_END_CODE (); |
|
} |
|
else if (buf[1] == '#') { |
|
/* %# a comment in the skel. ignore. */ |
|
} |
|
else { |
|
flexfatal (_("bad line in skeleton file")); |
|
} |
} |
} |
} |
|
|
|
|
else if (do_copy) |
|
outn (buf); |
|
} /* end while */ |
|
} |
|
|
|
|
/* transition_struct_out - output a yy_trans_info structure |
/* transition_struct_out - output a yy_trans_info structure |
* |
* |
* outputs the yy_trans_info structure with the two elements, element_v and |
* outputs the yy_trans_info structure with the two elements, element_v and |
* element_n. Formats the output with spaces and carriage returns. |
* element_n. Formats the output with spaces and carriage returns. |
*/ |
*/ |
|
|
void transition_struct_out( element_v, element_n ) |
void transition_struct_out (element_v, element_n) |
int element_v, element_n; |
int element_v, element_n; |
{ |
{ |
out_dec2( " {%4d,%4d },", element_v, element_n ); |
|
|
|
|
/* short circuit any output */ |
|
if (!gentables) |
|
return; |
|
|
|
out_dec2 (" {%4d,%4d },", element_v, element_n); |
|
|
datapos += TRANS_STRUCT_PRINT_LENGTH; |
datapos += TRANS_STRUCT_PRINT_LENGTH; |
|
|
if ( datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH ) |
if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) { |
{ |
outc ('\n'); |
outc( '\n' ); |
|
|
|
if ( ++dataline % 10 == 0 ) |
if (++dataline % 10 == 0) |
outc( '\n' ); |
outc ('\n'); |
|
|
datapos = 0; |
datapos = 0; |
} |
|
} |
} |
|
} |
|
|
|
|
/* The following is only needed when building flex's parser using certain |
/* The following is only needed when building flex's parser using certain |
* broken versions of bison. |
* broken versions of bison. |
*/ |
*/ |
void *yy_flex_xmalloc( size ) |
void *yy_flex_xmalloc (size) |
int size; |
int size; |
{ |
{ |
void *result = flex_alloc( (size_t) size ); |
void *result = flex_alloc ((size_t) size); |
|
|
if ( ! result ) |
if (!result) |
flexfatal( |
flexfatal (_ |
_( "memory allocation failed in yy_flex_xmalloc()" ) ); |
("memory allocation failed in yy_flex_xmalloc()")); |
|
|
return result; |
return result; |
} |
} |
|
|
|
|
/* zero_out - set a region of memory to 0 |
/* zero_out - set a region of memory to 0 |
|
|
* Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero. |
* Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero. |
*/ |
*/ |
|
|
void zero_out( region_ptr, size_in_bytes ) |
void zero_out (region_ptr, size_in_bytes) |
char *region_ptr; |
char *region_ptr; |
size_t size_in_bytes; |
size_t size_in_bytes; |
{ |
{ |
char *rp, *rp_end; |
char *rp, *rp_end; |
|
|
rp = region_ptr; |
rp = region_ptr; |
rp_end = region_ptr + size_in_bytes; |
rp_end = region_ptr + size_in_bytes; |
|
|
while ( rp < rp_end ) |
while (rp < rp_end) |
*rp++ = 0; |
*rp++ = 0; |
} |
} |
|
|
|
/* Remove all '\n' and '\r' characters, if any, from the end of str. |
|
* str can be any null-terminated string, or NULL. |
|
* returns str. */ |
|
char *chomp (str) |
|
char *str; |
|
{ |
|
char *p = str; |
|
|
|
if (!str || !*str) /* s is null or empty string */ |
|
return str; |
|
|
|
/* find end of string minus one */ |
|
while (*p) |
|
++p; |
|
--p; |
|
|
|
/* eat newlines */ |
|
while (p >= str && (*p == '\r' || *p == '\n')) |
|
*p-- = 0; |
|
return str; |
|
} |