/* Allocate and initialize an external filter. * @param chain the current chain or NULL for new chain * @param cmd the command to execute. * @param ... a NULL terminated list of (const char*) arguments to command, * not including argv[0]. * @return newest filter in chain */ struct filter *filter_create_ext (struct filter *chain, const char *cmd, ...) { struct filter *f; int max_args; const char *s; va_list ap; /* allocate and initialize new filter */ f = (struct filter *) flex_alloc (sizeof (struct filter)); if (!f) flexerror (_("flex_alloc failed (f) in filter_create_ext")); memset (f, 0, sizeof (*f)); f->filter_func = NULL; f->extra = NULL; f->next = NULL; f->argc = 0; if (chain != NULL) { /* append f to end of chain */ while (chain->next) chain = chain->next; chain->next = f; } /* allocate argv, and populate it with the argument list. */ max_args = 8; f->argv = (const char **) flex_alloc (sizeof (char *) * (max_args + 1)); if (!f->argv) flexerror (_("flex_alloc failed (f->argv) in filter_create_ext")); f->argv[f->argc++] = cmd; va_start (ap, cmd); while ((s = va_arg (ap, const char *)) != NULL) { if (f->argc >= max_args) { max_args += 8; f->argv = (const char **) flex_realloc (f->argv, sizeof (char *) * (max_args + 1)); } f->argv[f->argc++] = s; } f->argv[f->argc] = NULL; va_end (ap); return f; }
/* Allocate and initialize an internal filter. * @param chain the current chain or NULL for new chain * @param filter_func The function that will perform the filtering. * filter_func should return 0 if successful, and -1 * if an error occurs -- or it can simply exit(). * @param extra optional user-defined data to pass to the filter. * @return newest filter in chain */ struct filter *filter_create_int (struct filter *chain, int (*filter_func) (struct filter *), void *extra) { struct filter *f; /* allocate and initialize new filter */ f = malloc(sizeof(struct filter)); if (!f) flexerror(_("malloc failed in filter_create_int")); memset (f, 0, sizeof (*f)); f->next = NULL; f->argc = 0; f->argv = NULL; f->filter_func = filter_func; f->extra = extra; if (chain != NULL) { /* append f to end of chain */ while (chain->next) chain = chain->next; chain->next = f; } return f; }
void lerrsf(const char *msg, const char *arg) { char errmsg[MAXLINE]; (void) sprintf( errmsg, msg, arg ); flexerror( errmsg ); }
void mark_beginning_as_normal(int mach) { switch ( state_type[mach] ) { case STATE_NORMAL: /* oh, we've already visited here */ return; case STATE_TRAILING_CONTEXT: state_type[mach] = STATE_NORMAL; if ( transchar[mach] == SYM_EPSILON ) { if ( trans1[mach] != NO_TRANSITION ) mark_beginning_as_normal( trans1[mach] ); if ( trans2[mach] != NO_TRANSITION ) mark_beginning_as_normal( trans2[mach] ); } break; default: flexerror( "bad state type in mark_beginning_as_normal()" ); break; } }
void lerr (const char *msg, ...) { char errmsg[MAXLINE]; va_list args; va_start(args, msg); vsnprintf (errmsg, sizeof(errmsg), msg, args); va_end(args); flexerror (errmsg); }
/** Adjust the line numbers in the #line directives of the generated scanner. * After the m4 expansion, the line numbers are incorrect since the m4 macros * can add or remove lines. This only adjusts line numbers for generated code, * not user code. This also happens to be a good place to squeeze multiple * blank lines into a single blank line. */ int filter_fix_linedirs (struct filter *chain) { char *buf; const int readsz = 512; int lineno = 1; bool in_gen = true; /* in generated code */ bool last_was_blank = false; if (!chain) return 0; buf = malloc(readsz); if (!buf) flexerror(_("malloc failed in filter_fix_linedirs")); while (fgets (buf, readsz, stdin)) { regmatch_t m[10]; /* Check for #line directive. */ if (buf[0] == '#' && regexec (®ex_linedir, buf, 3, m, 0) == 0) { char *fname; /* extract the line number and filename */ fname = regmatch_dup (&m[2], buf); if (strcmp (fname, outfilename ? outfilename : "<stdout>") == 0 || strcmp (fname, headerfilename ? headerfilename : "<stdout>") == 0) { char *s1, *s2; char filename[MAXLINE]; s1 = fname; s2 = filename; while ((s2 - filename) < (MAXLINE - 1) && *s1) { /* Escape the backslash */ if (*s1 == '\\') *s2++ = '\\'; /* Escape the double quote */ if (*s1 == '\"') *s2++ = '\\'; /* Copy the character as usual */ *s2++ = *s1++; } *s2 = '\0'; /* Adjust the line directives. */ in_gen = true; snprintf (buf, readsz, "#line %d \"%s\"\n", lineno + 1, filename); } else { /* it's a #line directive for code we didn't write */ in_gen = false; } free (fname); last_was_blank = false; } /* squeeze blank lines from generated code */ else if (in_gen && regexec (®ex_blank_line, buf, 0, NULL, 0) == 0) { if (last_was_blank) continue; else last_was_blank = true; } else { /* it's a line of normal, non-empty code. */ last_was_blank = false; } fputs (buf, stdout); lineno++; } fflush (stdout); if (ferror (stdout)) lerr (_("error writing output file %s"), outfilename ? outfilename : "<stdout>"); else if (fclose (stdout)) lerr (_("error closing output file %s"), outfilename ? outfilename : "<stdout>"); return 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; }
/** 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; }
void readin(void) { static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;"; static char yy_nostdinit[] = "FILE *yyin = NULL, *yyout = NULL;"; line_directive_out( NULL, 1 ); if ( yyparse() ) { pinpoint_message( _( "fatal parse error" ) ); flexend( 1 ); } if ( syntaxerror ) flexend( 1 ); if ( backing_up_report ) { backing_up_file = fopen( backing_name, "w" ); if ( backing_up_file == NULL ) lerrsf( _( "could not create backing-up info file %s" ), backing_name ); } else backing_up_file = NULL; if ( yymore_really_used == true ) yymore_used = true; else if ( yymore_really_used == false ) yymore_used = false; if ( reject_really_used == true ) reject = true; else if ( reject_really_used == false ) reject = false; if ( performance_report > 0 ) { if ( lex_compat ) { fprintf( stderr, _( "-l AT&T lex compatibility option entails a large performance penalty\n" ) ); fprintf( stderr, _( " and may be the actual source of other reported performance penalties\n" ) ); } else if ( do_yylineno ) { fprintf( stderr, _( "%%option yylineno entails a large performance penalty\n" ) ); } if ( performance_report > 1 ) { if ( interactive ) fprintf( stderr, _( "-I (interactive) entails a minor performance penalty\n" ) ); if ( yymore_used ) fprintf( stderr, _( "yymore() entails a minor performance penalty\n" ) ); } if ( reject ) fprintf( stderr, _( "REJECT entails a large performance penalty\n" ) ); if ( variable_trailing_context_rules ) fprintf( stderr, _( "Variable trailing context rules entail a large performance penalty\n" ) ); } if ( reject ) real_reject = true; if ( variable_trailing_context_rules ) reject = true; if ( (fulltbl || fullspd) && reject ) { if ( real_reject ) flexerror( _( "REJECT cannot be used with -f or -F" ) ); else if ( do_yylineno ) flexerror( _( "%option yylineno cannot be used with -f or -F" ) ); else flexerror( _( "variable trailing context rules cannot be used with -f or -F" ) ); } if ( reject ) outn( "\n#define YY_USES_REJECT" ); if ( ! do_yywrap ) { outn( "\n#define yywrap() 1" ); outn( "#define YY_SKIP_YYWRAP" ); } if ( ddebug ) outn( "\n#define FLEX_DEBUG" ); if ( csize == 256 ) outn( "typedef unsigned char YY_CHAR;" ); else outn( "typedef char YY_CHAR;" ); if ( C_plus_plus ) { outn( "#define yytext_ptr yytext" ); if ( interactive ) outn( "#define YY_INTERACTIVE" ); } else { if ( do_stdinit ) { outn( yy_stdinit ); } else outn( yy_nostdinit ); } if ( fullspd ) outn( "typedef yyconst struct yy_trans_info *yy_state_type;" ); else if ( ! C_plus_plus ) outn( "typedef int yy_state_type;" ); if ( ddebug ) outn( "\n#define FLEX_DEBUG" ); if ( lex_compat ) outn( "#define YY_FLEX_LEX_COMPAT" ); if ( do_yylineno && ! C_plus_plus ) { outn( "extern int yylineno;" ); outn( "int yylineno = 1;" ); } if ( C_plus_plus ) { outn( "\n#include <FlexLexer.h>" ); if ( yyclass ) { outn( "int yyFlexLexer::yylex()" ); outn( "\t{" ); outn( "\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );" ); outn( "\treturn 0;" ); outn( "\t}" ); out_str( "\n#define YY_DECL int %s::yylex()\n", yyclass ); } } else { if ( yytext_is_array ) outn( "extern char yytext[];\n" ); else { outn( "extern char *yytext;" ); outn( "#define yytext_ptr yytext" ); } if ( yyclass ) flexerror( _( "%option yyclass only meaningful for C++ scanners" ) ); } if ( useecs ) numecs = cre8ecs( nextecm, ecgroup, csize ); else numecs = csize; /* Now map the equivalence class for NUL to its expected place. */ ecgroup[0] = ecgroup[csize]; NUL_ec = ABS( ecgroup[0] ); if ( useecs ) ccl2ecl(); }
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] */ }
void check_options(void) { int i; 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" ) ); /* Don't rely on detecting use of yymore() and REJECT, * just assume they'll be used. */ yymore_really_used = reject_really_used = true; yytext_is_array = true; do_yylineno = true; use_read = false; } if ( do_yylineno ) /* This should really be "maintain_backup_tables = true" */ reject_really_used = true; 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 ( do_yylineno ) flexerror( _( "-Cf/-CF and %option yylineno are incompatible" ) ); 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 ) { warn( _( "%array incompatible with -+ option" ) ); yytext_is_array = false; } 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 ( ! use_stdout ) { FILE *prev_stdout; if ( ! did_outfilename ) { char *suffix; if ( C_plus_plus ) suffix = "cc"; else suffix = "c"; sprintf( outfile_path, outfile_template, prefix, suffix ); outfilename = outfile_path; } prev_stdout = freopen( outfilename, "w", stdout ); if ( prev_stdout == NULL ) lerrsf( _( "could not create %s" ), outfilename ); outfile_created = 1; } if ( skelname && (skelfile = fopen( skelname, "r" )) == NULL ) lerrsf( _( "can't open skeleton file %s" ), skelname ); if ( strcmp( prefix, "yy" ) ) { #define GEN_PREFIX(name) out_str3( "#define yy%s %s%s\n", name, prefix, name ) if ( C_plus_plus ) GEN_PREFIX( "FlexLexer" ); else { GEN_PREFIX( "_create_buffer" ); GEN_PREFIX( "_delete_buffer" ); GEN_PREFIX( "_scan_buffer" ); GEN_PREFIX( "_scan_string" ); GEN_PREFIX( "_scan_bytes" ); GEN_PREFIX( "_flex_debug" ); GEN_PREFIX( "_init_buffer" ); GEN_PREFIX( "_flush_buffer" ); GEN_PREFIX( "_load_buffer_state" ); GEN_PREFIX( "_switch_to_buffer" ); GEN_PREFIX( "in" ); GEN_PREFIX( "leng" ); GEN_PREFIX( "lex" ); GEN_PREFIX( "out" ); GEN_PREFIX( "restart" ); GEN_PREFIX( "text" ); if ( do_yylineno ) GEN_PREFIX( "lineno" ); } if ( do_yywrap ) GEN_PREFIX( "wrap" ); outn( "" ); } if ( did_outfilename ) line_directive_out( stdout, 0 ); skelout(); }
/** 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; }
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); }
void flexinit(int argc, char **argv) { int i, sawcmpflag; char *arg, *flex_gettime(), *mktemp(); printstats = syntaxerror = trace = spprdflt = interactive = caseins = false; backtrack_report = performance_report = ddebug = fulltbl = fullspd = false; yymore_used = continued_action = reject = false; yymore_really_used = reject_really_used = false; gen_line_dirs = usemecs = useecs = true; sawcmpflag = false; use_stdout = false; csize = DEFAULT_CSIZE; program_name = argv[0]; /* read flags */ for ( --argc, ++argv; argc ; --argc, ++argv ) { if ( argv[0][0] != '-' || argv[0][1] == '\0' ) break; arg = argv[0]; for ( i = 1; arg[i] != '\0'; ++i ) switch ( arg[i] ) { case 'b': backtrack_report = true; break; case 'c': fprintf( stderr, "%s: Assuming use of deprecated -c flag is really intended to be -C\n", program_name ); /* fall through */ case 'C': if ( i != 1 ) flexerror( "-C flag must be given separately" ); if ( ! sawcmpflag ) { useecs = false; usemecs = false; fulltbl = false; sawcmpflag = true; } for ( ++i; arg[i] != '\0'; ++i ) switch ( arg[i] ) { case 'e': useecs = true; break; case 'F': fullspd = true; break; case 'f': fulltbl = true; break; case 'm': usemecs = true; break; default: lerrif( "unknown -C option '%c'", (int) arg[i] ); break; } goto get_next_arg; case 'd': ddebug = true; break; case 'f': useecs = usemecs = false; fulltbl = true; break; case 'F': useecs = usemecs = false; fullspd = true; break; case 'I': interactive = true; break; case 'i': caseins = true; break; case 'L': gen_line_dirs = false; break; case 'n': /* stupid do-nothing deprecated option */ break; case 'p': performance_report = true; break; case 'S': if ( i != 1 ) flexerror( "-S flag must be given separately" ); skelname = arg + i + 1; goto get_next_arg; case 's': spprdflt = true; break; case 't': use_stdout = true; break; case 'T': trace = true; break; case 'v': printstats = true; break; case '8': csize = CSIZE; break; default: lerrif( "unknown flag '%c'", (int) arg[i] ); break; } get_next_arg: /* used by -C and -S flags in lieu of a "continue 2" control */ ; } if ( (fulltbl || fullspd) && usemecs ) flexerror( "full table and -Cm don't make sense together" ); if ( (fulltbl || fullspd) && interactive ) flexerror( "full table and -I are (currently) incompatible" ); if ( fulltbl && fullspd ) flexerror( "full table and -F are mutually exclusive" ); if ( ! skelname ) { static char skeleton_name_storage[400]; skelname = skeleton_name_storage; (void) strcpy( skelname, ENQUOTE(DEFAULT_SKELETON_FILE) ); } if ( ! use_stdout ) { FILE *prev_stdout = freopen( outfile, "w", stdout ); if ( prev_stdout == NULL ) lerrsf( "could not create %s", outfile ); outfile_created = 1; } num_input_files = argc; input_files = argv; set_input_file( num_input_files > 0 ? input_files[0] : NULL ); if ( backtrack_report ) { #ifndef SHORT_FILE_NAMES backtrack_file = fopen( "lex.backtrack", "w" ); #else backtrack_file = fopen( "lex.bck", "w" ); #endif if ( backtrack_file == NULL ) flexerror( "could not create lex.backtrack" ); } else backtrack_file = NULL; lastccl = 0; lastsc = 0; /* initialize the statistics */ starttime = flex_gettime(); if ( (skelfile = fopen( skelname, "r" )) == NULL ) lerrsf( "can't open skeleton file %s", skelname ); epicsTempName ( action_file_name, sizeof ( action_file_name ) ); if ( action_file_name[0] == '\0' ) { lerrsf( "can't create temporary file name", "" ); } if ( ( temp_action_file = fopen ( action_file_name, "w" ) ) == NULL ) lerrsf( "can't open temporary action file %s", action_file_name ); lastdfa = lastnfa = num_rules = numas = numsnpairs = tmpuses = 0; numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0; numuniq = numdup = hshsave = eofseen = datapos = dataline = 0; num_backtracking = onesp = numprots = 0; variable_trailing_context_rules = bol_needed = false; linenum = sectnum = 1; firstprot = NIL; /* used in mkprot() so that the first proto goes in slot 1 * of the proto queue */ lastprot = 1; 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 */ } } set_up_initial_allocations(); }
int main(int argc, char *argv[]) { flexinit( argc, argv ); readin(); if ( syntaxerror ) flexend( 1 ); if ( yymore_really_used == REALLY_USED ) yymore_used = true; else if ( yymore_really_used == REALLY_NOT_USED ) yymore_used = false; if ( reject_really_used == REALLY_USED ) reject = true; else if ( reject_really_used == REALLY_NOT_USED ) reject = false; if ( performance_report ) { if ( interactive ) fprintf( stderr, "-I (interactive) entails a minor performance penalty\n" ); if ( yymore_used ) fprintf( stderr, "yymore() entails a minor performance penalty\n" ); if ( reject ) fprintf( stderr, "REJECT entails a large performance penalty\n" ); if ( variable_trailing_context_rules ) fprintf( stderr, "Variable trailing context rules entail a large performance penalty\n" ); } if ( reject ) real_reject = true; if ( variable_trailing_context_rules ) reject = true; if ( (fulltbl || fullspd) && reject ) { if ( real_reject ) flexerror( "REJECT cannot be used with -f or -F" ); else flexerror( "variable trailing context rules cannot be used with -f or -F" ); } ntod(); /* generate the C state transition tables from the DFA */ make_tables(); /* note, flexend does not return. It exits with its argument as status. */ flexend( 0 ); /*NOTREACHED*/ }
void flexinit(int argc, char **argv) { int i, sawcmpflag; char *arg; printstats = syntaxerror = trace = spprdflt = caseins = false; lex_compat = C_plus_plus = backing_up_report = ddebug = fulltbl = false; fullspd = long_align = nowarn = yymore_used = continued_action = false; do_yylineno = yytext_is_array = in_rule = reject = do_stdinit = false; yymore_really_used = reject_really_used = unspecified; interactive = csize = unspecified; do_yywrap = gen_line_dirs = usemecs = useecs = true; performance_report = 0; did_outfilename = 0; prefix = "yy"; yyclass = NULL; use_read = use_stdout = false; sawcmpflag = false; /* Initialize dynamic array for holding the rule actions. */ action_size = 2048; /* default size of action array in bytes */ action_array = allocate_character_array( action_size ); defs1_offset = prolog_offset = action_offset = action_index = 0; action_array[0] = '\0'; program_name = argv[0]; if ( program_name[0] != '\0' && program_name[strlen( program_name ) - 1] == '+' ) C_plus_plus = true; /* read flags */ for ( --argc, ++argv; argc ; --argc, ++argv ) { arg = argv[0]; if ( arg[0] != '-' || arg[1] == '\0' ) break; if ( arg[1] == '-' ) { /* --option */ if ( ! strcmp( arg, "--help" ) ) arg = "-h"; else if ( ! strcmp( arg, "--version" ) ) arg = "-V"; else if ( ! strcmp( arg, "--" ) ) { /* end of options */ --argc; ++argv; break; } } for ( i = 1; arg[i] != '\0'; ++i ) switch ( arg[i] ) { case '+': C_plus_plus = true; break; case 'B': interactive = false; break; case 'b': backing_up_report = true; break; case 'c': break; case 'C': if ( i != 1 ) flexerror( _( "-C flag must be given separately" ) ); if ( ! sawcmpflag ) { useecs = false; usemecs = false; fulltbl = false; sawcmpflag = true; } for ( ++i; arg[i] != '\0'; ++i ) switch ( arg[i] ) { case 'a': long_align = true; break; case 'e': useecs = true; break; case 'F': fullspd = true; break; case 'f': fulltbl = true; break; case 'm': usemecs = true; break; case 'r': use_read = true; break; default: lerrif( _( "unknown -C option '%c'" ), (int) arg[i] ); break; } goto get_next_arg; case 'd': ddebug = true; break; case 'f': useecs = usemecs = false; use_read = fulltbl = true; break; case 'F': useecs = usemecs = false; use_read = fullspd = true; break; case '?': case 'h': usage(); exit( 0 ); case 'I': interactive = true; break; case 'i': caseins = true; break; case 'l': lex_compat = true; break; case 'L': gen_line_dirs = false; break; case 'n': /* Stupid do-nothing deprecated * option. */ break; case 'o': if ( i != 1 ) flexerror( _( "-o flag must be given separately" ) ); outfilename = arg + i + 1; did_outfilename = 1; goto get_next_arg; case 'P': if ( i != 1 ) flexerror( _( "-P flag must be given separately" ) ); prefix = arg + i + 1; goto get_next_arg; case 'p': ++performance_report; break; case 'S': if ( i != 1 ) flexerror( _( "-S flag must be given separately" ) ); skelname = arg + i + 1; goto get_next_arg; case 's': spprdflt = true; break; case 't': use_stdout = true; break; case 'T': trace = true; break; case 'v': printstats = true; break; case 'V': printf( _( "%s version %s\n" ), program_name, flex_version ); exit( 0 ); case 'w': nowarn = true; break; case '7': csize = 128; break; case '8': csize = CSIZE; break; default: fprintf( stderr, _( "%s: unknown flag '%c'. For usage, try\n\t%s --help\n" ), program_name, (int) arg[i], program_name ); exit( 1 ); } /* Used by -C, -S, -o, and -P flags in lieu of a "continue 2" * control. */ get_next_arg: ; } num_input_files = argc; input_files = argv; set_input_file( num_input_files > 0 ? input_files[0] : NULL ); lastccl = lastsc = lastdfa = lastnfa = 0; num_rules = num_eof_rules = default_rule = 0; numas = numsnpairs = tmpuses = 0; numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0; numuniq = numdup = hshsave = eofseen = datapos = dataline = 0; num_backing_up = onesp = numprots = 0; variable_trailing_context_rules = bol_needed = false; out_linenum = linenum = sectnum = 1; firstprot = NIL; /* Used in mkprot() so that the first proto goes in slot 1 * of the proto queue. */ lastprot = 1; set_up_initial_allocations(); }
void readin (void) { static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;"; static char yy_nostdinit[] = "FILE *yyin = NULL, *yyout = NULL;"; line_directive_out(NULL, 1); if (yyparse ()) { pinpoint_message (_("fatal parse error")); flexend (1); } if (syntaxerror) flexend (1); /* If the user explicitly requested posix compatibility by specifing the * posix-compat option, then we check for conflicting options. However, if * the POSIXLY_CORRECT variable is set, then we quietly make flex as * posix-compatible as possible. This is the recommended behavior * according to the GNU Coding Standards. * * Note: The posix option was added to flex to provide the posix behavior * of the repeat operator in regular expressions, e.g., `ab{3}' */ if (posix_compat) { /* TODO: This is where we try to make flex behave according to * posiz, AND check for conflicting options. How far should we go * with this? Should we disable all the neat-o flex features? */ /* Update: Estes says no, since other flex features don't violate posix. */ } if (getenv ("POSIXLY_CORRECT")) { posix_compat = true; } if (backing_up_report) { backing_up_file = fopen (backing_name, "w"); if (backing_up_file == NULL) lerr (_ ("could not create backing-up info file %s"), backing_name); } else backing_up_file = NULL; if (yymore_really_used == true) yymore_used = true; else if (yymore_really_used == false) yymore_used = false; if (reject_really_used == true) reject = true; else if (reject_really_used == false) reject = false; if (performance_report > 0) { if (lex_compat) { fprintf (stderr, _ ("-l AT&T lex compatibility option entails a large performance penalty\n")); fprintf (stderr, _ (" and may be the actual source of other reported performance penalties\n")); } else if (do_yylineno) { fprintf (stderr, _ ("%%option yylineno entails a performance penalty ONLY on rules that can match newline characters\n")); } if (performance_report > 1) { if (interactive) fprintf (stderr, _ ("-I (interactive) entails a minor performance penalty\n")); if (yymore_used) fprintf (stderr, _ ("yymore() entails a minor performance penalty\n")); } if (reject) fprintf (stderr, _ ("REJECT entails a large performance penalty\n")); if (variable_trailing_context_rules) fprintf (stderr, _ ("Variable trailing context rules entail a large performance penalty\n")); } if (reject) real_reject = true; if (variable_trailing_context_rules) reject = true; if ((fulltbl || fullspd) && reject) { if (real_reject) flexerror (_ ("REJECT cannot be used with -f or -F")); else if (do_yylineno) flexerror (_ ("%option yylineno cannot be used with REJECT")); else flexerror (_ ("variable trailing context rules cannot be used with -f or -F")); } if (reject){ out_m4_define( "M4_YY_USES_REJECT", NULL); //outn ("\n#define YY_USES_REJECT"); } if (!do_yywrap) { if (!C_plus_plus) { if (reentrant) out_str ("\n#define %swrap(yyscanner) (/*CONSTCOND*/1)\n", prefix); else out_str ("\n#define %swrap() (/*CONSTCOND*/1)\n", prefix); } outn ("#define YY_SKIP_YYWRAP"); } if (ddebug) outn ("\n#define FLEX_DEBUG"); OUT_BEGIN_CODE (); outn ("typedef flex_uint8_t YY_CHAR;"); OUT_END_CODE (); if (C_plus_plus) { outn ("#define yytext_ptr yytext"); if (interactive) outn ("#define YY_INTERACTIVE"); } else { OUT_BEGIN_CODE (); /* In reentrant scanner, stdinit is handled in flex.skl. */ if (do_stdinit) { if (reentrant){ outn ("#ifdef VMS"); outn ("#ifdef __VMS_POSIX"); outn ("#define YY_STDINIT"); outn ("#endif"); outn ("#else"); outn ("#define YY_STDINIT"); outn ("#endif"); } outn ("#ifdef VMS"); outn ("#ifndef __VMS_POSIX"); outn (yy_nostdinit); outn ("#else"); outn (yy_stdinit); outn ("#endif"); outn ("#else"); outn (yy_stdinit); outn ("#endif"); } else { if(!reentrant) outn (yy_nostdinit); } OUT_END_CODE (); } OUT_BEGIN_CODE (); if (fullspd) outn ("typedef const struct yy_trans_info *yy_state_type;"); else if (!C_plus_plus) outn ("typedef int yy_state_type;"); OUT_END_CODE (); if (lex_compat) outn ("#define YY_FLEX_LEX_COMPAT"); if (!C_plus_plus && !reentrant) { outn ("extern int yylineno;"); OUT_BEGIN_CODE (); outn ("int yylineno = 1;"); OUT_END_CODE (); } if (C_plus_plus) { outn ("\n#include <FlexLexer.h>"); if (!do_yywrap) { outn("\nint yyFlexLexer::yywrap() { return 1; }"); } if (yyclass) { outn ("int yyFlexLexer::yylex()"); outn ("\t{"); outn ("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );"); outn ("\treturn 0;"); outn ("\t}"); out_str ("\n#define YY_DECL int %s::yylex()\n", yyclass); } } else { /* Watch out: yytext_ptr is a variable when yytext is an array, * but it's a macro when yytext is a pointer. */ if (yytext_is_array) { if (!reentrant) outn ("extern char yytext[];\n"); } else { if (reentrant) { outn ("#define yytext_ptr yytext_r"); } else { outn ("extern char *yytext;"); outn("#ifdef yytext_ptr"); outn("#undef yytext_ptr"); outn("#endif"); outn ("#define yytext_ptr yytext"); } } if (yyclass) flexerror (_ ("%option yyclass only meaningful for C++ scanners")); } if (useecs) numecs = cre8ecs (nextecm, ecgroup, csize); else numecs = csize; /* Now map the equivalence class for NUL to its expected place. */ ecgroup[0] = ecgroup[csize]; NUL_ec = ABS (ecgroup[0]); if (useecs) ccl2ecl (); }