Exemplo n.º 1
0
int dupmachine(int mach)
{
    int i, init, state_offset;
    int state = 0;
    int last = lastst[mach];

    for ( i = firstst[mach]; i <= last; ++i )
	{
	state = mkstate( transchar[i] );

	if ( trans1[i] != NO_TRANSITION )
	    {
	    mkxtion( finalst[state], trans1[i] + state - i );

	    if ( transchar[i] == SYM_EPSILON && trans2[i] != NO_TRANSITION )
		mkxtion( finalst[state], trans2[i] + state - i );
	    }

	accptnum[state] = accptnum[i];
	}

    if ( state == 0 )
	flexfatal( "empty machine in dupmachine()" );

    state_offset = state - i + 1;

    init = mach + state_offset;
    firstst[init] = firstst[mach] + state_offset;
    finalst[init] = finalst[mach] + state_offset;
    lastst[init] = lastst[mach] + state_offset;

    return ( init );
    }
Exemplo n.º 2
0
/* copy_string - returns a dynamically allocated copy of a string */
char *
copy_string(const char *str)
{
    const char *c1;
    char *c2;
    char *copy;
    size_t size;

    /* find length */
    for (c1 = str; *c1; ++c1) {
	;
    }

    size = (unsigned) (c1 - str + 1) * sizeof(char);
    copy = (char *) flex_alloc(size);

    if (copy == NULL)
	flexfatal(_("dynamic memory failure in copy_string()"));

    assert(copy != NULL);

    for (c2 = copy; (*c2++ = *str++) != 0;) {
	;
    }

    return copy;
}
Exemplo n.º 3
0
/** Append a line directive to the string buffer.
 * @param buf A string buffer.
 * @param filename file name
 * @param lineno line number
 * @return buf
 */
struct Buf *
buf_linedir(struct Buf * buf, const char *filename, int lineno)
{
	const char *src;
	char *dst, *t;
	size_t tsz;

	tsz = strlen("#line \"\"\n") +	/* constant parts */
	    2 * strlen(filename) +	/* filename with possibly all backslashes escaped */
	    (int) (1 + log10(abs(lineno))) +	/* line number */
	    1;			/* NUL */
	t = malloc(tsz);
	if (!t)
		flexfatal(_("Allocation of buffer for line directive failed"));
	dst = t + snprintf(t, tsz, "#line %d \"", lineno);
	for (src = filename; *src; *dst++ = *src++)
		if (*src == '\\')	/* escape backslashes */
			*dst++ = '\\';
	*dst++ = '"';
	*dst++ = '\n';
	*dst = '\0';
	buf = buf_strappend(buf, t);
	free(t);
	return buf;
}
Exemplo n.º 4
0
Arquivo: misc.c Projeto: westes/flex
char *xstrdup(const char *s)
{
	char *s2;

	if ((s2 = strdup(s)) == NULL)
		flexfatal (_("memory allocation failure in xstrdup()"));

	return s2;
}
Exemplo n.º 5
0
/* The following is only needed when building flex's parser using certain
 * broken versions of bison.
 */
void *yy_flex_xmalloc(int size)
	{
	void *result = flex_alloc( (size_t) size );

	if ( ! result  )
		flexfatal(
			_( "memory allocation failed in yy_flex_xmalloc()" ) );

	return result;
	}
Exemplo n.º 6
0
Arquivo: misc.c Projeto: westes/flex
void lerr_fatal (const char *msg, ...)
{
	char    errmsg[MAXLINE];
	va_list args;
	va_start(args, msg);

	vsnprintf (errmsg, sizeof(errmsg), msg, args);
	va_end(args);
	flexfatal (errmsg);
}
Exemplo n.º 7
0
void *reallocate_array(void *array, int size, size_t element_size)
	{
	void *new_array;
	size_t num_bytes = element_size * size;

	new_array = flex_realloc( array, num_bytes );
	if ( ! new_array )
		flexfatal( _( "attempt to increase array size failed" ) );

	return new_array;
	}
Exemplo n.º 8
0
Arquivo: misc.c Projeto: westes/flex
void   *allocate_array (int size, size_t element_size)
{
	void *new_array;
#if HAVE_REALLOCARR
	new_array = NULL;
	if (reallocarr(&new_array, (size_t) size, element_size))
		flexfatal (_("memory allocation failed in allocate_array()"));
#else
# if HAVE_REALLOCARRAY
	new_array = reallocarray(NULL, (size_t) size, element_size);
# else
	/* Do manual overflow detection */
	size_t num_bytes = (size_t) size * element_size;
	new_array = (size && SIZE_MAX / (size_t) size < element_size) ? NULL :
		malloc(num_bytes);
# endif
	if (!new_array)
		flexfatal (_("memory allocation failed in allocate_array()"));
#endif
	return new_array;
}
Exemplo n.º 9
0
Arquivo: misc.c Projeto: westes/flex
void   *reallocate_array (void *array, int size, size_t element_size)
{
	void *new_array;
#if HAVE_REALLOCARR
	new_array = array;
	if (reallocarr(&new_array, (size_t) size, element_size))
		flexfatal (_("attempt to increase array size failed"));
#else
# if HAVE_REALLOCARRAY
	new_array = reallocarray(array, (size_t) size, element_size);
# else
	/* Do manual overflow detection */
	size_t num_bytes = (size_t) size * element_size;
	new_array = (size && SIZE_MAX / (size_t) size < element_size) ? NULL :
		realloc(array, num_bytes);
# endif
	if (!new_array)
		flexfatal (_("attempt to increase array size failed"));
#endif
	return new_array;
}
Exemplo n.º 10
0
void *allocate_array(int size, size_t element_size)
	{
	void *mem;
	size_t num_bytes = element_size * size;

	mem = flex_alloc( num_bytes );
	if ( ! mem )
		flexfatal(
			_( "memory allocation failed in allocate_array()" ) );

	return mem;
	}
Exemplo n.º 11
0
/* Append a "%s" formatted string to a string buffer */
struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s)
{
	char   *t;
        size_t tsz;

	t = flex_alloc (tsz = strlen (fmt) + strlen (s) + 1);
	if (!t)
	    flexfatal (_("Allocation of buffer to print string failed"));
	snprintf (t, tsz, fmt, s);
	buf = buf_strappend (buf, t);
	flex_free (t);
	return buf;
}
Exemplo n.º 12
0
/** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer.
 * @param buf A buffer as a list of strings.
 * @param def The m4 symbol to undefine.
 * @return buf
 */
struct Buf *buf_m4_undefine (struct Buf *buf, const char* def)
{
    const char * fmt = "m4_undefine( [[%s]])m4_dnl\n";
    char * str;
    size_t strsz;

    str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2);
    if (!str)
        flexfatal (_("Allocation of buffer for m4 undef failed"));

    snprintf(str, strsz, fmt, def);
    buf_append(buf, &str, 1);
    return buf;
}
Exemplo n.º 13
0
/* skelout - write out one section of the skeleton file
 *
 * Description
 *    Copies skelfile or skel array to stdout until a line beginning with
 *    "%%" or EOF is found.
 */
void skelout(void)
	{
	char buf_storage[MAXLINE];
	char *buf = buf_storage;
	int do_copy = 1;

	/* Loop pulling lines either from the skelfile, if we're using
	 * one, or from the skel[] array.
	 */
	while ( skelfile ?
		(fgets( buf, MAXLINE, skelfile ) != NULL) :
		((buf = (char *) skel[skel_ind++]) != 0) )
		{ /* copy from skel array */
		if ( buf[0] == '%' )
			{ /* control line */
			switch ( buf[1] )
				{
				case '%':
					return;

				case '+':
					do_copy = C_plus_plus;
					break;

				case '-':
					do_copy = ! C_plus_plus;
					break;

				case '*':
					do_copy = 1;
					break;

				default:
					flexfatal(
					_( "bad line in skeleton file" ) );
				}
			}

		else if ( do_copy )
			{
			if ( skelfile )
				/* Skeleton file reads include final
				 * newline, skel[] array does not.
				 */
				out( buf );
			else
				outn( buf );
			}
		}
	}
Exemplo n.º 14
0
Arquivo: regex.c Projeto: 0mp/freebsd
/** Extract a copy of the match, or NULL if no match.
 * @param m A match as returned by regexec().
 * @param src The source string that was passed to regexec().
 * @return The allocated string.
 */
char   *regmatch_dup (regmatch_t * m, const char *src)
{
	char   *str;
	int     len;

	if (m == NULL || m->rm_so < 0)
		return NULL;
	len = m->rm_eo - m->rm_so;
	str = (char *) flex_alloc ((len + 1) * sizeof (char));
	if (!str)
		flexfatal(_("Unable to allocate a copy of the match"));
	strncpy (str, src + m->rm_so, len);
	str[len] = 0;
	return str;
}
Exemplo n.º 15
0
void mkxtion(int statefrom, int stateto)
{
    if ( trans1[statefrom] == NO_TRANSITION )
	trans1[statefrom] = stateto;

    else if ( (transchar[statefrom] != SYM_EPSILON) ||
	      (trans2[statefrom] != NO_TRANSITION) )
	flexfatal( "found too many transitions in mkxtion()" );

    else
	{ /* second out-transition for an epsilon state */
	++eps2;
	trans2[statefrom] = stateto;
	}
    }
Exemplo n.º 16
0
/* reallocate_array - increase the size of a dynamic array */
void *
reallocate_array(void *array, long size, size_t element_size)
{
    void *new_array = 0;

    if (size > 0) {
	size_t num_bytes = element_size * (unsigned) size;

	new_array = flex_realloc(array, num_bytes);
    }
    if (!new_array)
	flexfatal(_("attempt to increase array size failed"));

    return new_array;
}
Exemplo n.º 17
0
Arquivo: regex.c Projeto: 0mp/freebsd
/** Compiles a regular expression or dies trying.
 * @param preg  Same as for regcomp().
 * @param regex Same as for regcomp().
 * @param cflags Same as for regcomp().
 */
void flex_regcomp(regex_t *preg, const char *regex, int cflags)
{
    int err;

	memset (preg, 0, sizeof (regex_t));

	if ((err = regcomp (preg, regex, cflags)) != 0) {
        const int errbuf_sz = 200;
        char *errbuf, *rxerr;

		errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char));
		if (!errbuf)
			flexfatal(_("Unable to allocate buffer to report regcomp"));
		rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char));
		if (!rxerr)
			flexfatal(_("Unable to allocate buffer for regerror"));
		regerror (err, preg, rxerr, errbuf_sz);
		snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr);

		flexfatal (errbuf);
        free(errbuf);
        free(rxerr);
	}
}
Exemplo n.º 18
0
/** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer.
 * @param buf A buffer as a list of strings.
 * @param def The m4 symbol to define.
 * @param val The definition; may be NULL.
 * @return buf
 */
struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val)
{
    const char * fmt = "m4_define( [[%s]], [[[[%s]]]])m4_dnl\n";
    char * str;
    size_t strsz;

    val = val?val:"";
    strsz = strlen(fmt) + strlen(def) + strlen(val) + 2;
    str = malloc(strsz);
    if (!str)
        flexfatal (_("Allocation of buffer for m4 def failed"));

    snprintf(str, strsz, fmt, def, val);
    buf_append(buf, &str, 1);
    return buf;
}
Exemplo n.º 19
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++;
}
Exemplo n.º 20
0
int addsym(char *sym, char *str_def, int int_def, hash_table table,
           int table_size)
	{
	int hash_val = hashfunct( sym, table_size );
	struct hash_entry *sym_entry = table[hash_val];
	struct hash_entry *new_entry;
	struct hash_entry *successor;

	while ( sym_entry )
		{
		if ( ! strcmp( sym, sym_entry->name ) )
			{ /* entry already exists */
			return -1;
			}

		sym_entry = sym_entry->next;
		}

	/* create new entry */
	new_entry = (struct hash_entry *)
		flex_alloc( sizeof( struct hash_entry ) );

	if ( new_entry == NULL )
		flexfatal( _( "symbol table memory allocation failed" ) );

	if ( (successor = table[hash_val]) != NULL )
		{
		new_entry->next = successor;
		successor->prev = new_entry;
		}
	else
		new_entry->next = NULL;

	new_entry->prev = NULL;
	new_entry->name = sym;
	new_entry->str_val = str_def;
	new_entry->int_val = int_def;

	table[hash_val] = new_entry;

	return 0;
	}
Exemplo n.º 21
0
/** Append a line directive to the string buffer.
 * @param buf A string buffer.
 * @param filename file name
 * @param lineno line number
 * @return buf
 */
struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno)
{
    char *dst, *src, *t;
    char *dupe;

    dupe = flex_alloc (strlen(filename) + 1);
    strncpy(dupe, filename, strlen(filename));
    t = flex_alloc (strlen ("#line \"\"\n")          +   /* constant parts */
                    2 * strlen (filename)            +   /* filename with possibly all backslashes escaped */
                    (int) (1 + log10 (abs (lineno))) +   /* line number */
                    1);                                  /* NUL */
    if (!t)
      flexfatal (_("Allocation of buffer for line directive failed"));
    for (dst = t + sprintf (t, "#line %d \"", lineno), src = dupe; *src; *dst++ = *src++)
      if (*src == '\\')   /* escape backslashes */
        *dst++ = '\\';
    *dst++ = '"';
    *dst++ = '\n';
    *dst   = '\0';
    buf = buf_strappend (buf, t);
    flex_free (t);
    return buf;
}
Exemplo n.º 22
0
Arquivo: flex.c Projeto: ukaea/epics
void flexend(int status)
{
    int tblsiz;
    char *flex_gettime();

    if ( skelfile != NULL )
	{
	if ( ferror( skelfile ) )
	    flexfatal( "error occurred when writing skeleton file" );

	else if ( fclose( skelfile ) )
	    flexfatal( "error occurred when closing skeleton file" );
	}

    if ( temp_action_file )
	{
	if ( ferror( temp_action_file ) )
	    flexfatal( "error occurred when writing temporary action file" );

	else if ( fclose( temp_action_file ) )
	    flexfatal( "error occurred when closing temporary action file" );

	else if ( unlink( action_file_name ) )
	    flexfatal( "error occurred when deleting temporary action file" );
	}

    if ( status != 0 && outfile_created )
	{
	if ( ferror( stdout ) )
	    flexfatal( "error occurred when writing output file" );

	else if ( fclose( stdout ) )
	    flexfatal( "error occurred when closing output file" );

	else if ( unlink( outfile ) )
	    flexfatal( "error occurred when deleting output file" );
	}

    if ( backtrack_report && backtrack_file )
	{
	if ( num_backtracking == 0 )
	    fprintf( backtrack_file, "No backtracking.\n" );
	else if ( fullspd || fulltbl )
	    fprintf( backtrack_file,
		     "%d backtracking (non-accepting) states.\n",
		     num_backtracking );
	else
	    fprintf( backtrack_file, "Compressed tables always backtrack.\n" );

	if ( ferror( backtrack_file ) )
	    flexfatal( "error occurred when writing backtracking file" );

	else if ( fclose( backtrack_file ) )
	    flexfatal( "error occurred when closing backtracking file" );
	}

    if ( printstats )
	{
	endtime = flex_gettime();

	fprintf( stderr, "%s version %s usage statistics:\n", program_name,
		 flex_version );
	fprintf( stderr, "  started at %s, finished at %s\n",
		 starttime, endtime );

	fprintf( stderr, "  scanner options: -" );

	if ( backtrack_report )
	    putc( 'b', stderr );
	if ( ddebug )
	    putc( 'd', stderr );
	if ( interactive )
	    putc( 'I', stderr );
	if ( caseins )
	    putc( 'i', stderr );
	if ( ! gen_line_dirs )
	    putc( 'L', stderr );
	if ( performance_report )
	    putc( 'p', stderr );
	if ( spprdflt )
	    putc( 's', stderr );
	if ( use_stdout )
	    putc( 't', stderr );
	if ( trace )
	    putc( 'T', stderr );
	if ( printstats )
	    putc( 'v', stderr );	/* always true! */
	if ( csize == 256 )
	    putc( '8', stderr );

	fprintf( stderr, " -C" );

	if ( fulltbl )
	    putc( 'f', stderr );
	if ( fullspd )
	    putc( 'F', stderr );
	if ( useecs )
	    putc( 'e', stderr );
	if ( usemecs )
	    putc( 'm', stderr );

	if ( strcmp( skelname, ENQUOTE(DEFAULT_SKELETON_FILE) ) )
	    fprintf( stderr, " -S%s", skelname );

	putc( '\n', stderr );

	fprintf( stderr, "  %d/%d NFA states\n", lastnfa, current_mns );
	fprintf( stderr, "  %d/%d DFA states (%d words)\n", lastdfa,
		 current_max_dfas, totnst );
	fprintf( stderr,
		 "  %d rules\n", num_rules - 1 /* - 1 for def. rule */ );

	if ( num_backtracking == 0 )
	    fprintf( stderr, "  No backtracking\n" );
	else if ( fullspd || fulltbl )
	    fprintf( stderr, "  %d backtracking (non-accepting) states\n",
		     num_backtracking );
	else
	    fprintf( stderr, "  compressed tables always backtrack\n" );

	if ( bol_needed )
	    fprintf( stderr, "  Beginning-of-line patterns used\n" );

	fprintf( stderr, "  %d/%d start conditions\n", lastsc,
		 current_max_scs );
	fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
		 numeps, eps2 );

	if ( lastccl == 0 )
	    fprintf( stderr, "  no character classes\n" );
	else
	    fprintf( stderr,
	"  %d/%d character classes needed %d/%d words of storage, %d reused\n",
		     lastccl, current_maxccls,
		     cclmap[lastccl] + ccllen[lastccl],
		     current_max_ccl_tbl_size, cclreuse );

	fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
	fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
		 numuniq, numdup );

	if ( fulltbl )
	    {
	    tblsiz = lastdfa * numecs;
	    fprintf( stderr, "  %d table entries\n", tblsiz );
	    }

	else
	    {
	    tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;

	    fprintf( stderr, "  %d/%d base-def entries created\n",
		     lastdfa + numtemps, current_max_dfas );
	    fprintf( stderr, "  %d/%d (peak %d) nxt-chk entries created\n",
		     tblend, current_max_xpairs, peakpairs );
	    fprintf( stderr,
		     "  %d/%d (peak %d) template nxt-chk entries created\n",
		     numtemps * nummecs, current_max_template_xpairs,
		     numtemps * numecs );
	    fprintf( stderr, "  %d empty table entries\n", nummt );
	    fprintf( stderr, "  %d protos created\n", numprots );
	    fprintf( stderr, "  %d templates created, %d uses\n",
		     numtemps, tmpuses );
	    }

	if ( useecs )
	    {
	    tblsiz = tblsiz + csize;
	    fprintf( stderr, "  %d/%d equivalence classes created\n",
		     numecs, csize );
	    }

	if ( usemecs )
	    {
	    tblsiz = tblsiz + numecs;
	    fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
		     nummecs, csize );
	    }

	fprintf( stderr, "  %d (%d saved) hash collisions, %d DFAs equal\n",
		 hshcol, hshsave, dfaeql );
	fprintf( stderr, "  %d sets of reallocations needed\n", num_reallocs );
	fprintf( stderr, "  %d total table entries needed\n", tblsiz );
	}

    exit( status );
}
Exemplo n.º 23
0
void check_options (void)
{
	int     i;
    const char * m4 = NULL;

	if (lex_compat) {
		if (C_plus_plus)
			flexerror (_("Can't use -+ with -l option"));

		if (fulltbl || fullspd)
			flexerror (_("Can't use -f or -F with -l option"));

		if (reentrant || bison_bridge_lval)
			flexerror (_
				   ("Can't use --reentrant or --bison-bridge with -l option"));

		yytext_is_array = true;
		do_yylineno = true;
		use_read = false;
	}


#if 0
	/* This makes no sense whatsoever. I'm removing it. */
	if (do_yylineno)
		/* This should really be "maintain_backup_tables = true" */
		reject_really_used = true;
#endif

	if (csize == unspecified) {
		if ((fulltbl || fullspd) && !useecs)
			csize = DEFAULT_CSIZE;
		else
			csize = CSIZE;
	}

	if (interactive == unspecified) {
		if (fulltbl || fullspd)
			interactive = false;
		else
			interactive = true;
	}

	if (fulltbl || fullspd) {
		if (usemecs)
			flexerror (_
				   ("-Cf/-CF and -Cm don't make sense together"));

		if (interactive)
			flexerror (_("-Cf/-CF and -I are incompatible"));

		if (lex_compat)
			flexerror (_
				   ("-Cf/-CF are incompatible with lex-compatibility mode"));


		if (fulltbl && fullspd)
			flexerror (_
				   ("-Cf and -CF are mutually exclusive"));
	}

	if (C_plus_plus && fullspd)
		flexerror (_("Can't use -+ with -CF option"));

	if (C_plus_plus && yytext_is_array) {
		lwarn (_("%array incompatible with -+ option"));
		yytext_is_array = false;
	}

	if (C_plus_plus && (reentrant))
		flexerror (_("Options -+ and --reentrant are mutually exclusive."));

	if (C_plus_plus && bison_bridge_lval)
		flexerror (_("bison bridge not supported for the C++ scanner."));


	if (useecs) {		/* Set up doubly-linked equivalence classes. */

		/* We loop all the way up to csize, since ecgroup[csize] is
		 * the position used for NUL characters.
		 */
		ecgroup[1] = NIL;

		for (i = 2; i <= csize; ++i) {
			ecgroup[i] = i - 1;
			nextecm[i - 1] = i;
		}

		nextecm[csize] = NIL;
	}

	else {
		/* Put everything in its own equivalence class. */
		for (i = 1; i <= csize; ++i) {
			ecgroup[i] = i;
			nextecm[i] = BAD_SUBSCRIPT;	/* to catch errors */
		}
	}

    if (extra_type)
        buf_m4_define( &m4defs_buf, "M4_EXTRA_TYPE_DEFS", extra_type);

	if (!use_stdout) {
		FILE   *prev_stdout;

		if (!did_outfilename) {
			char   *suffix;

			if (C_plus_plus)
				suffix = "cc";
			else
				suffix = "c";

			snprintf (outfile_path, sizeof(outfile_path), outfile_template,
				 prefix, suffix);

			outfilename = outfile_path;
		}

		prev_stdout = freopen (outfilename, "w+", stdout);

		if (prev_stdout == NULL)
			lerr (_("could not create %s"), outfilename);

		outfile_created = 1;
	}


    /* Setup the filter chain. */
    output_chain = filter_create_int(NULL, filter_tee_header, headerfilename);
    if ( !(m4 = getenv("M4"))) {
	    char *slash;
		m4 = M4;
		if ((slash = strrchr(M4, '/')) != NULL) {
			m4 = slash+1;
			/* break up $PATH */
			const char *path = getenv("PATH");
			if (!path) {
				m4 = M4;
			} else {
				int m4_length = strlen(m4);
				do {
					size_t length = strlen(path);
					struct stat sbuf;

					const char *endOfDir = strchr(path, ':');
					if (!endOfDir)
						endOfDir = path+length;

					{
						char *m4_path = calloc(endOfDir-path + 1 + m4_length + 1, 1);

						memcpy(m4_path, path, endOfDir-path);
						m4_path[endOfDir-path] = '/';
						memcpy(m4_path + (endOfDir-path) + 1, m4, m4_length + 1);
						if (stat(m4_path, &sbuf) == 0 &&
							(S_ISREG(sbuf.st_mode)) && sbuf.st_mode & S_IXUSR) {
							m4 = m4_path;
							break;
						}
						free(m4_path);
					}
					path = endOfDir+1;
				} while (path[0]);
				if (!path[0])
				    m4 = M4;
			}
		}
	}
    filter_create_ext(output_chain, m4, "-P", 0);
    filter_create_int(output_chain, filter_fix_linedirs, NULL);

    /* For debugging, only run the requested number of filters. */
    if (preproc_level > 0) {
        filter_truncate(output_chain, preproc_level);
        filter_apply_chain(output_chain);
    }
    yyout = stdout;


	/* always generate the tablesverify flag. */
	buf_m4_define (&m4defs_buf, "M4_YY_TABLES_VERIFY", tablesverify ? "1" : "0");
	if (tablesext)
		gentables = false;

	if (tablesverify)
		/* force generation of C tables. */
		gentables = true;


	if (tablesext) {
		FILE   *tablesout;
		struct yytbl_hdr hdr;
		char   *pname = 0;
		size_t  nbytes = 0;

		buf_m4_define (&m4defs_buf, "M4_YY_TABLES_EXTERNAL", NULL);

		if (!tablesfilename) {
			nbytes = strlen (prefix) + strlen (tablesfile_template) + 2;
			tablesfilename = pname = calloc(nbytes, 1);
			snprintf (pname, nbytes, tablesfile_template, prefix);
		}

		if ((tablesout = fopen (tablesfilename, "w")) == NULL)
			lerr (_("could not create %s"), tablesfilename);
		free(pname);
		tablesfilename = 0;

		yytbl_writer_init (&tableswr, tablesout);

		nbytes = strlen (prefix) + strlen ("tables") + 2;
		tablesname = calloc(nbytes, 1);
		snprintf (tablesname, nbytes, "%stables", prefix);
		yytbl_hdr_init (&hdr, flex_version, tablesname);

		if (yytbl_hdr_fwrite (&tableswr, &hdr) <= 0)
			flexerror (_("could not write tables header"));
	}

	if (skelname && (skelfile = fopen (skelname, "r")) == NULL)
		lerr (_("can't open skeleton file %s"), skelname);

	if (reentrant) {
        buf_m4_define (&m4defs_buf, "M4_YY_REENTRANT", NULL);
		if (yytext_is_array)
			buf_m4_define (&m4defs_buf, "M4_YY_TEXT_IS_ARRAY", NULL);
	}

	if ( bison_bridge_lval)
		buf_m4_define (&m4defs_buf, "M4_YY_BISON_LVAL", NULL);

	if ( bison_bridge_lloc)
        buf_m4_define (&m4defs_buf, "<M4_YY_BISON_LLOC>", NULL);

    if (strchr(prefix, '[') || strchr(prefix, ']'))
        flexerror(_("Prefix cannot include '[' or ']'"));
    buf_m4_define(&m4defs_buf, "M4_YY_PREFIX", prefix);

	if (did_outfilename)
		line_directive_out (stdout, 0);

	if (do_yylineno)
		buf_m4_define (&m4defs_buf, "M4_YY_USE_LINENO", NULL);

	/* Create the alignment type. */
	buf_strdefine (&userdef_buf, "YY_INT_ALIGNED",
		       long_align ? "long int" : "short int");

    /* Define the start condition macros. */
    {
        struct Buf tmpbuf;
        buf_init(&tmpbuf, sizeof(char));
        for (i = 1; i <= lastsc; i++) {
             char *str, *fmt = "#define %s %d\n";
             size_t strsz;

             strsz = strlen(fmt) + strlen(scname[i]) + (size_t)(1 + ceil (log10(i))) + 2;
             str = malloc(strsz);
             if (!str)
               flexfatal(_("allocation of macro definition failed"));
             snprintf(str, strsz, fmt,      scname[i], i - 1);
             buf_strappend(&tmpbuf, str);
             free(str);
        }
        buf_m4_define(&m4defs_buf, "M4_YY_SC_DEFS", tmpbuf.elts);
        buf_destroy(&tmpbuf);
    }

    /* This is where we begin writing to the file. */

    /* Dump the %top code. */
    if( top_buf.elts)
        outn((char*) top_buf.elts);

    /* Dump the m4 definitions. */
    buf_print_strings(&m4defs_buf, stdout);
    m4defs_buf.nelts = 0; /* memory leak here. */

    /* Place a bogus line directive, it will be fixed in the filter. */
    if (gen_line_dirs)
        outn("#line 0 \"M4_YY_OUTFILE_NAME\"\n");

	/* Dump the user defined preproc directives. */
	if (userdef_buf.elts)
		outn ((char *) (userdef_buf.elts));

	skelout ();
	/* %% [1.0] */
}
Exemplo n.º 24
0
int    *epsclosure (int *t, int *ns_addr, int accset[], int *nacc_addr, int *hv_addr)
{
	int     stkpos, ns, tsp;
	int     numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
	int     stkend, nstate;
	static int did_stk_init = false, *stk;

#define MARK_STATE(state) \
do{ trans1[state] = trans1[state] - MARKER_DIFFERENCE;} while(0)

#define IS_MARKED(state) (trans1[state] < 0)

#define UNMARK_STATE(state) \
do{ trans1[state] = trans1[state] + MARKER_DIFFERENCE;} while(0)

#define CHECK_ACCEPT(state) \
do{ \
nfaccnum = accptnum[state]; \
if ( nfaccnum != NIL ) \
accset[++nacc] = nfaccnum; \
}while(0)

#define DO_REALLOCATION() \
do { \
current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \
++num_reallocs; \
t = reallocate_integer_array( t, current_max_dfa_size ); \
stk = reallocate_integer_array( stk, current_max_dfa_size ); \
}while(0) \

#define PUT_ON_STACK(state) \
do { \
if ( ++stkend >= current_max_dfa_size ) \
DO_REALLOCATION(); \
stk[stkend] = state; \
MARK_STATE(state); \
}while(0)

#define ADD_STATE(state) \
do { \
if ( ++numstates >= current_max_dfa_size ) \
DO_REALLOCATION(); \
t[numstates] = state; \
hashval += state; \
}while(0)

#define STACK_STATE(state) \
do { \
PUT_ON_STACK(state); \
CHECK_ACCEPT(state); \
if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
ADD_STATE(state); \
}while(0)


	if (!did_stk_init) {
		stk = allocate_integer_array (current_max_dfa_size);
		did_stk_init = true;
	}

	nacc = stkend = hashval = 0;

	for (nstate = 1; nstate <= numstates; ++nstate) {
		ns = t[nstate];

		/* The state could be marked if we've already pushed it onto
		 * the stack.
		 */
		if (!IS_MARKED (ns)) {
			PUT_ON_STACK (ns);
			CHECK_ACCEPT (ns);
			hashval += ns;
		}
	}

	for (stkpos = 1; stkpos <= stkend; ++stkpos) {
		ns = stk[stkpos];
		transsym = transchar[ns];

		if (transsym == SYM_EPSILON) {
			tsp = trans1[ns] + MARKER_DIFFERENCE;

			if (tsp != NO_TRANSITION) {
				if (!IS_MARKED (tsp))
					STACK_STATE (tsp);

				tsp = trans2[ns];

				if (tsp != NO_TRANSITION
				    && !IS_MARKED (tsp))
					STACK_STATE (tsp);
			}
		}
	}

	/* Clear out "visit" markers. */

	for (stkpos = 1; stkpos <= stkend; ++stkpos) {
		if (IS_MARKED (stk[stkpos]))
			UNMARK_STATE (stk[stkpos]);
		else
			flexfatal (_
				   ("consistency check failed in epsclosure()"));
	}

	*ns_addr = numstates;
	*hv_addr = hashval;
	*nacc_addr = nacc;

	return t;
}
Exemplo n.º 25
0
void sympartition (int ds[], int numstates, int symlist[], int duplist[])
{
	int     tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;

	/* Partitioning is done by creating equivalence classes for those
	 * characters which have out-transitions from the given state.  Thus
	 * we are really creating equivalence classes of equivalence classes.
	 */

	for (i = 1; i <= numecs; ++i) {	/* initialize equivalence class list */
		duplist[i] = i - 1;
		dupfwd[i] = i + 1;
	}

	duplist[1] = NIL;
	dupfwd[numecs] = NIL;

	for (i = 1; i <= numstates; ++i) {
		ns = ds[i];
		tch = transchar[ns];

		if (tch != SYM_EPSILON) {
			if (tch < -lastccl || tch >= csize) {
				flexfatal (_
					   ("bad transition character detected in sympartition()"));
			}

			if (tch >= 0) {	/* character transition */
				int     ec = ecgroup[tch];

				mkechar (ec, dupfwd, duplist);
				symlist[ec] = 1;
			}

			else {	/* character class */
				tch = -tch;

				lenccl = ccllen[tch];
				cclp = cclmap[tch];
				mkeccl (ccltbl + cclp, lenccl, dupfwd,
					duplist, numecs, NUL_ec);

				if (cclng[tch]) {
					j = 0;

					for (k = 0; k < lenccl; ++k) {
						ich = ccltbl[cclp + k];

						if (ich == 0)
							ich = NUL_ec;

						for (++j; j < ich; ++j)
							symlist[j] = 1;
					}

					for (++j; j <= numecs; ++j)
						symlist[j] = 1;
				}

				else
					for (k = 0; k < lenccl; ++k) {
						ich = ccltbl[cclp + k];

						if (ich == 0)
							ich = NUL_ec;

						symlist[ich] = 1;
					}
			}
		}
	}
}
Exemplo n.º 26
0
void ntod (void)
{
	int    *accset, ds, nacc, newds;
	int     sym, hashval, numstates, dsize;
	int     num_full_table_rows=0;	/* used only for -f */
	int    *nset, *dset;
	int     targptr, totaltrans, i, comstate, comfreq, targ;
	int     symlist[CSIZE + 1];
	int     num_start_states;
	int     todo_head, todo_next;

	struct yytbl_data *yynxt_tbl = 0;
	flex_int32_t *yynxt_data = 0, yynxt_curr = 0;

	/* Note that the following are indexed by *equivalence classes*
	 * and not by characters.  Since equivalence classes are indexed
	 * beginning with 1, even if the scanner accepts NUL's, this
	 * means that (since every character is potentially in its own
	 * equivalence class) these arrays must have room for indices
	 * from 1 to CSIZE, so their size must be CSIZE + 1.
	 */
	int     duplist[CSIZE + 1], state[CSIZE + 1];
	int     targfreq[CSIZE + 1] = {0}, targstate[CSIZE + 1];

	/* accset needs to be large enough to hold all of the rules present
	 * in the input, *plus* their YY_TRAILING_HEAD_MASK variants.
	 */
	accset = allocate_integer_array ((num_rules + 1) * 2);
	nset = allocate_integer_array (current_max_dfa_size);

	/* The "todo" queue is represented by the head, which is the DFA
	 * state currently being processed, and the "next", which is the
	 * next DFA state number available (not in use).  We depend on the
	 * fact that snstods() returns DFA's \in increasing order/, and thus
	 * need only know the bounds of the dfas to be processed.
	 */
	todo_head = todo_next = 0;

	for (i = 0; i <= csize; ++i) {
		duplist[i] = NIL;
		symlist[i] = false;
	}

	for (i = 0; i <= num_rules; ++i)
		accset[i] = NIL;

	if (trace) {
		dumpnfa (scset[1]);
		fputs (_("\n\nDFA Dump:\n\n"), stderr);
	}

	inittbl ();

	/* Check to see whether we should build a separate table for
	 * transitions on NUL characters.  We don't do this for full-speed
	 * (-F) scanners, since for them we don't have a simple state
	 * number lying around with which to index the table.  We also
	 * don't bother doing it for scanners unless (1) NUL is in its own
	 * equivalence class (indicated by a positive value of
	 * ecgroup[NUL]), (2) NUL's equivalence class is the last
	 * equivalence class, and (3) the number of equivalence classes is
	 * the same as the number of characters.  This latter case comes
	 * about when useecs is false or when it's true but every character
	 * still manages to land in its own class (unlikely, but it's
	 * cheap to check for).  If all these things are true then the
	 * character code needed to represent NUL's equivalence class for
	 * indexing the tables is going to take one more bit than the
	 * number of characters, and therefore we won't be assured of
	 * being able to fit it into a YY_CHAR variable.  This rules out
	 * storing the transitions in a compressed table, since the code
	 * for interpreting them uses a YY_CHAR variable (perhaps it
	 * should just use an integer, though; this is worth pondering ...
	 * ###).
	 *
	 * Finally, for full tables, we want the number of entries in the
	 * table to be a power of two so the array references go fast (it
	 * will just take a shift to compute the major index).  If
	 * encoding NUL's transitions in the table will spoil this, we
	 * give it its own table (note that this will be the case if we're
	 * not using equivalence classes).
	 */

	/* Note that the test for ecgroup[0] == numecs below accomplishes
	 * both (1) and (2) above
	 */
	if (!fullspd && ecgroup[0] == numecs) {
		/* NUL is alone in its equivalence class, which is the
		 * last one.
		 */
		int     use_NUL_table = (numecs == csize);

		if (fulltbl && !use_NUL_table) {
			/* We still may want to use the table if numecs
			 * is a power of 2.
			 */
			int     power_of_two;

			for (power_of_two = 1; power_of_two <= csize;
			     power_of_two *= 2)
				if (numecs == power_of_two) {
					use_NUL_table = true;
					break;
				}
		}

		if (use_NUL_table)
			nultrans =
				allocate_integer_array (current_max_dfas);

		/* From now on, nultrans != nil indicates that we're
		 * saving null transitions for later, separate encoding.
		 */
	}


	if (fullspd) {
		for (i = 0; i <= numecs; ++i)
			state[i] = 0;

		place_state (state, 0, 0);
		dfaacc[0].dfaacc_state = 0;
	}

	else if (fulltbl) {
		if (nultrans)
			/* We won't be including NUL's transitions in the
			 * table, so build it for entries from 0 .. numecs - 1.
			 */
			num_full_table_rows = numecs;

		else
			/* Take into account the fact that we'll be including
			 * the NUL entries in the transition table.  Build it
			 * from 0 .. numecs.
			 */
			num_full_table_rows = numecs + 1;

		/* Begin generating yy_nxt[][]
		 * This spans the entire LONG function.
		 * This table is tricky because we don't know how big it will be.
		 * So we'll have to realloc() on the way...
		 * we'll wait until we can calculate yynxt_tbl->td_hilen.
		 */
		yynxt_tbl = calloc(1, sizeof (struct yytbl_data));
     
		yytbl_data_init (yynxt_tbl, YYTD_ID_NXT);
		yynxt_tbl->td_hilen = 1;
		yynxt_tbl->td_lolen = (flex_uint32_t) num_full_table_rows;
		yynxt_tbl->td_data = yynxt_data =
			calloc(yynxt_tbl->td_lolen *
					    yynxt_tbl->td_hilen,
					    sizeof (flex_int32_t));
		yynxt_curr = 0;

		buf_prints (&yydmap_buf,
			    "\t{YYTD_ID_NXT, (void**)&yy_nxt, sizeof(%s)},\n",
			    long_align ? "flex_int32_t" : "flex_int16_t");

		/* Unless -Ca, declare it "short" because it's a real
		 * long-shot that that won't be large enough.
		 */
		if (gentables)
			out_str_dec
				("static const %s yy_nxt[][%d] =\n    {\n",
				 long_align ? "flex_int32_t" : "flex_int16_t",
				 num_full_table_rows);
		else {
			out_dec ("#undef YY_NXT_LOLEN\n#define YY_NXT_LOLEN (%d)\n", num_full_table_rows);
			out_str ("static const %s *yy_nxt =0;\n",
				 long_align ? "flex_int32_t" : "flex_int16_t");
		}


		if (gentables)
			outn ("    {");

		/* Generate 0 entries for state #0. */
		for (i = 0; i < num_full_table_rows; ++i) {
			mk2data (0);
			yynxt_data[yynxt_curr++] = 0;
		}

		dataflush ();
		if (gentables)
			outn ("    },\n");
	}

	/* Create the first states. */

	num_start_states = lastsc * 2;

	for (i = 1; i <= num_start_states; ++i) {
		numstates = 1;

		/* For each start condition, make one state for the case when
		 * we're at the beginning of the line (the '^' operator) and
		 * one for the case when we're not.
		 */
		if (i % 2 == 1)
			nset[numstates] = scset[(i / 2) + 1];
		else
			nset[numstates] =
				mkbranch (scbol[i / 2], scset[i / 2]);

		nset = epsclosure (nset, &numstates, accset, &nacc,
				   &hashval);

		if (snstods (nset, numstates, accset, nacc, hashval, &ds)) {
			numas += nacc;
			totnst += numstates;
			++todo_next;

			if (variable_trailing_context_rules && nacc > 0)
				check_trailing_context (nset, numstates,
							accset, nacc);
		}
	}

	if (!fullspd) {
		if (!snstods (nset, 0, accset, 0, 0, &end_of_buffer_state))
			flexfatal (_
				   ("could not create unique end-of-buffer state"));

		++numas;
		++num_start_states;
		++todo_next;
	}


	while (todo_head < todo_next) {
		targptr = 0;
		totaltrans = 0;

		for (i = 1; i <= numecs; ++i)
			state[i] = 0;

		ds = ++todo_head;

		dset = dss[ds];
		dsize = dfasiz[ds];

		if (trace)
			fprintf (stderr, _("state # %d:\n"), ds);

		sympartition (dset, dsize, symlist, duplist);

		for (sym = 1; sym <= numecs; ++sym) {
			if (symlist[sym]) {
				symlist[sym] = 0;

				if (duplist[sym] == NIL) {
					/* Symbol has unique out-transitions. */
					numstates =
						symfollowset (dset, dsize,
							      sym, nset);
					nset = epsclosure (nset,
							   &numstates,
							   accset, &nacc,
							   &hashval);

					if (snstods
					    (nset, numstates, accset, nacc,
					     hashval, &newds)) {
						totnst = totnst +
							numstates;
						++todo_next;
						numas += nacc;

						if (variable_trailing_context_rules && nacc > 0)
							check_trailing_context
								(nset,
								 numstates,
								 accset,
								 nacc);
					}

					state[sym] = newds;

					if (trace)
						fprintf (stderr,
							 "\t%d\t%d\n", sym,
							 newds);

					targfreq[++targptr] = 1;
					targstate[targptr] = newds;
					++numuniq;
				}

				else {
					/* sym's equivalence class has the same
					 * transitions as duplist(sym)'s
					 * equivalence class.
					 */
					targ = state[duplist[sym]];
					state[sym] = targ;

					if (trace)
						fprintf (stderr,
							 "\t%d\t%d\n", sym,
							 targ);

					/* Update frequency count for
					 * destination state.
					 */

					i = 0;
					while (targstate[++i] != targ) ;

					++targfreq[i];
					++numdup;
				}

				++totaltrans;
				duplist[sym] = NIL;
			}
		}


		numsnpairs += totaltrans;

		if (ds > num_start_states)
			check_for_backing_up (ds, state);

		if (nultrans) {
			nultrans[ds] = state[NUL_ec];
			state[NUL_ec] = 0;	/* remove transition */
		}

		if (fulltbl) {

			/* Each time we hit here, it's another td_hilen, so we realloc. */
			yynxt_tbl->td_hilen++;
			yynxt_tbl->td_data = yynxt_data =
				realloc (yynxt_data,
						     yynxt_tbl->td_hilen *
						     yynxt_tbl->td_lolen *
						     sizeof (flex_int32_t));


			if (gentables)
				outn ("    {");

			/* Supply array's 0-element. */
			if (ds == end_of_buffer_state) {
				mk2data (-end_of_buffer_state);
				yynxt_data[yynxt_curr++] =
					-end_of_buffer_state;
			}
			else {
				mk2data (end_of_buffer_state);
				yynxt_data[yynxt_curr++] =
					end_of_buffer_state;
			}

			for (i = 1; i < num_full_table_rows; ++i) {
				/* Jams are marked by negative of state
				 * number.
				 */
				mk2data (state[i] ? state[i] : -ds);
				yynxt_data[yynxt_curr++] =
					state[i] ? state[i] : -ds;
			}

			dataflush ();
			if (gentables)
				outn ("    },\n");
		}

		else if (fullspd)
			place_state (state, ds, totaltrans);

		else if (ds == end_of_buffer_state)
			/* Special case this state to make sure it does what
			 * it's supposed to, i.e., jam on end-of-buffer.
			 */
			stack1 (ds, 0, 0, JAMSTATE);

		else {		/* normal, compressed state */

			/* Determine which destination state is the most
			 * common, and how many transitions to it there are.
			 */

			comfreq = 0;
			comstate = 0;

			for (i = 1; i <= targptr; ++i)
				if (targfreq[i] > comfreq) {
					comfreq = targfreq[i];
					comstate = targstate[i];
				}

			bldtbl (state, ds, totaltrans, comstate, comfreq);
		}
	}

	if (fulltbl) {
		dataend ();
		if (tablesext) {
			yytbl_data_compress (yynxt_tbl);
			if (yytbl_data_fwrite (&tableswr, yynxt_tbl) < 0)
				flexerror (_
					   ("Could not write yynxt_tbl[][]"));
		}
		if (yynxt_tbl) {
			yytbl_data_destroy (yynxt_tbl);
			yynxt_tbl = 0;
		}
	}

	else if (!fullspd) {
		cmptmps ();	/* create compressed template entries */

		/* Create tables for all the states with only one
		 * out-transition.
		 */
		while (onesp > 0) {
			mk1tbl (onestate[onesp], onesym[onesp],
				onenext[onesp], onedef[onesp]);
			--onesp;
		}

		mkdeftbl ();
	}

	free(accset);
	free(nset);
}
Exemplo n.º 27
0
/** Fork and exec entire filter chain.
 *  @param chain The head of the chain.
 *  @return true on success.
 */
bool 
filter_apply_chain(struct filter * chain)
{
	int pid, pipes[2];
	int r;
	const int readsz = 512;
	char *buf;


	/*
	 * Tricky recursion, since we want to begin the chain at the END.
	 * Why? Because we need all the forked processes to be children of
	 * the main flex process.
	 */
	if (chain)
		filter_apply_chain(chain->next);
	else
		return true;

	/*
	 * Now we are the right-most unprocessed link in the chain.
	 */

	fflush(stdout);
	fflush(stderr);


	if (pipe(pipes) == -1)
		flexerror(_("pipe failed"));

	if ((pid = fork()) == -1)
		flexerror(_("fork failed"));

	if (pid == 0) {
		/* child */

		/*
		 * We need stdin (the FILE* stdin) to connect to this new
		 * pipe. There is no portable way to set stdin to a new file
		 * descriptor, as stdin is not an lvalue on some systems
		 * (BSD). So we dup the new pipe onto the stdin descriptor
		 * and use a no-op fseek to sync the stream. This is a Hail
		 * Mary situation. It seems to work.
		 */
		close(pipes[1]);
		clearerr(stdin);
		if (dup2(pipes[0], fileno(stdin)) == -1)
			flexfatal(_("dup2(pipes[0],0)"));
		close(pipes[0]);
		fseek(stdin, 0, SEEK_CUR);

		/* run as a filter, either internally or by exec */
		if (chain->filter_func) {
			int r;

			if ((r = chain->filter_func(chain)) == -1)
				flexfatal(_("filter_func failed"));
			exit(0);
		} else {
			execvp(chain->argv[0],
			    (char **const) (chain->argv));
			lerrsf_fatal(_("exec of %s failed"),
			    chain->argv[0]);
		}

		exit(1);
	}
	/* Parent */
	close(pipes[0]);
	if (dup2(pipes[1], fileno(stdout)) == -1)
		flexfatal(_("dup2(pipes[1],1)"));
	close(pipes[1]);
	fseek(stdout, 0, SEEK_CUR);

	return true;
}
Exemplo n.º 28
0
Arquivo: misc.c Projeto: westes/flex
/* skelout - write out one section of the skeleton file
 *
 * Description
 *    Copies skelfile or skel array to stdout until a line beginning with
 *    "%%" or EOF is found.
 */
void skelout (void)
{
	char    buf_storage[MAXLINE];
	char   *buf = buf_storage;
	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
	 * one, or from the skel[] array.
	 */
	while (skelfile ?
	       (fgets (buf, MAXLINE, skelfile) != NULL) :
	       ((buf = (char *) skel[skel_ind++]) != 0)) {

		if (skelfile)
			chomp (buf);

		/* copy from skel array */
		if (buf[0] == '%') {	/* control line */
			/* 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);
			}

			/* We've been accused of using cryptic markers in the skel.
			 * So we'll use emacs-style-hyphenated-commands.
             * 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)

		if (buf[1] == '#') {
                	/* %# indicates comment line to be ignored */
            	} 
		else if (buf[1] == '%') {
				/* %% is a break point for skelout() */
				return;
			}
            else if (cmd_match (CMD_PUSH)){
                sko_push(do_copy);
                if(ddebug){
                    out_str("/*(state = (%s) */",do_copy?"true":"false");
                }
                out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : "");
            }
            else if (cmd_match (CMD_POP)){
                sko_pop(&do_copy);
                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)) {
                if ( tablesext )
                    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 {
				flexfatal (_("bad line in skeleton file"));
			}
		}

		else if (do_copy) 
            outn (buf);
	}			/* end while */
}
Exemplo n.º 29
0
/** Fork and exec entire filter chain.
 *  @param chain The head of the chain.
 *  @return true on success.
 */
bool filter_apply_chain (struct filter * chain)
{
	int     pid, pipes[2];


	/* Tricky recursion, since we want to begin the chain
	 * at the END. Why? Because we need all the forked processes
	 * to be children of the main flex process.
	 */
	if (chain)
		filter_apply_chain (chain->next);
	else
		return true;

	/* Now we are the right-most unprocessed link in the chain.
	 */

	fflush (stdout);
	fflush (stderr);


	if (pipe (pipes) == -1)
		flexerror (_("pipe failed"));

	if ((pid = fork ()) == -1)
		flexerror (_("fork failed"));

	if (pid == 0) {
		/* child */

        /* We need stdin (the FILE* stdin) to connect to this new pipe.
         * There is no portable way to set stdin to a new file descriptor,
         * as stdin is not an lvalue on some systems (BSD).
         * So we dup the new pipe onto the stdin descriptor and use a no-op fseek
         * to sync the stream. This is a Hail Mary situation. It seems to work.
         */
		close (pipes[1]);
clearerr(stdin);
		if (dup2 (pipes[0], fileno (stdin)) == -1)
			flexfatal (_("dup2(pipes[0],0)"));
		close (pipes[0]);
        fseek (stdin, 0, SEEK_CUR);
        ungetc(' ', stdin); /* still an evil hack, but one that works better */
        (void)fgetc(stdin); /* on NetBSD than the fseek attempt does */

		/* run as a filter, either internally or by exec */
		if (chain->filter_func) {
			int     r;

			if ((r = chain->filter_func (chain)) == -1)
				flexfatal (_("filter_func failed"));
			exit (0);
		}
		else {
			execvp (chain->argv[0],
				(char **const) (chain->argv));
            lerr_fatal ( _("exec of %s failed"),
                    chain->argv[0]);
		}

		exit (1);
	}

	/* Parent */
	close (pipes[0]);
	if (dup2 (pipes[1], fileno (stdout)) == -1)
		flexfatal (_("dup2(pipes[1],1)"));
	close (pipes[1]);
    fseek (stdout, 0, SEEK_CUR);

	return true;
}
Exemplo n.º 30
0
/** Splits the chain in order to write to a header file.
 *  Similar in spirit to the 'tee' program.
 *  The header file name is in extra.
 *  @return 0 (zero) on success, and -1 on failure.
 */
int filter_tee_header (struct filter *chain)
{
	/* This function reads from stdin and writes to both the C file and the
	 * header file at the same time.
	 */

	const int readsz = 512;
	char   *buf;
	int     to_cfd = -1;
	FILE   *to_c = NULL, *to_h = NULL;
	bool    write_header;

	write_header = (chain->extra != NULL);

	/* Store a copy of the stdout pipe, which is already piped to C file
	 * through the running chain. Then create a new pipe to the H file as
	 * stdout, and fork the rest of the chain again.
	 */

	if ((to_cfd = dup (1)) == -1)
		flexfatal (_("dup(1) failed"));
	to_c = fdopen (to_cfd, "w");

	if (write_header) {
		if (freopen ((char *) chain->extra, "w", stdout) == NULL)
			flexfatal (_("freopen(headerfilename) failed"));

		filter_apply_chain (chain->next);
		to_h = stdout;
	}

	/* Now to_c is a pipe to the C branch, and to_h is a pipe to the H branch.
	 */

	if (write_header) {
        fputs (check_4_gnu_m4, to_h);
		fputs ("m4_changecom`'m4_dnl\n", to_h);
		fputs ("m4_changequote`'m4_dnl\n", to_h);
		fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_h);
	    fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_h);
		fputs ("m4_define( [[M4_YY_IN_HEADER]],[[]])m4_dnl\n",
		       to_h);
		fprintf (to_h, "#ifndef %sHEADER_H\n", prefix);
		fprintf (to_h, "#define %sHEADER_H 1\n", prefix);
		fprintf (to_h, "#define %sIN_HEADER 1\n\n", prefix);
		fprintf (to_h,
			 "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",
			 headerfilename ? headerfilename : "<stdout>");

	}

    fputs (check_4_gnu_m4, to_c);
	fputs ("m4_changecom`'m4_dnl\n", to_c);
	fputs ("m4_changequote`'m4_dnl\n", to_c);
	fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_c);
	fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_c);
	fprintf (to_c, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",
		 outfilename ? outfilename : "<stdout>");

	buf = malloc(readsz);
	if (!buf)
		flexerror(_("malloc failed in filter_tee_header"));
	while (fgets (buf, readsz, stdin)) {
		fputs (buf, to_c);
		if (write_header)
			fputs (buf, to_h);
	}

	if (write_header) {
		fprintf (to_h, "\n");

		/* write a fake line number. It will get fixed by the linedir filter. */
		fprintf (to_h, "#line 4000 \"M4_YY_OUTFILE_NAME\"\n");

		fprintf (to_h, "#undef %sIN_HEADER\n", prefix);
		fprintf (to_h, "#endif /* %sHEADER_H */\n", prefix);
		fputs ("m4_undefine( [[M4_YY_IN_HEADER]])m4_dnl\n", to_h);

		fflush (to_h);
		if (ferror (to_h))
			lerr (_("error writing output file %s"),
				(char *) chain->extra);

		else if (fclose (to_h))
			lerr (_("error closing output file %s"),
				(char *) chain->extra);
	}

	fflush (to_c);
	if (ferror (to_c))
		lerr (_("error writing output file %s"),
			outfilename ? outfilename : "<stdout>");

	else if (fclose (to_c))
		lerr (_("error closing output file %s"),
			outfilename ? outfilename : "<stdout>");

	while (wait (0) > 0) ;

	exit (0);
	return 0;
}