diff options
-rw-r--r-- | flex.texi | 54 | ||||
-rw-r--r-- | flexdef.h | 37 | ||||
-rw-r--r-- | gen.c | 443 | ||||
-rw-r--r-- | main.c | 93 | ||||
-rw-r--r-- | options.c | 2 | ||||
-rw-r--r-- | options.h | 2 | ||||
-rw-r--r-- | scan.l | 4 | ||||
-rw-r--r-- | tables.c | 220 |
8 files changed, 660 insertions, 195 deletions
@@ -4660,12 +4660,12 @@ indexed by name, as described below. The file format is as follows: | char th_name[]; | | uint8 th_pad64[]; | +-------------------------------+ - Table 1 | uint16 t_id; | - | uint16 t_flags; | - | uint32 t_lolen; | - | uint32 t_hilen; | - | void t_data[]; | - | uint8 t_pad64[]; | + Table 1 | uint16 td_id; | + | uint16 td_flags; | + | uint32 td_lolen; | + | uint32 td_hilen; | + | void td_data[]; | + | uint8 td_pad64[]; | +-------------------------------+ Table 2 | | . . . @@ -4723,7 +4723,7 @@ Zero or more NUL bytes, padding the entire header to the next 64-bit boundary. Fields of a table: @table @code -@item t_id +@item td_id Specifies the table identifier. Possible values are: @table @code @item YYT_ID_ACCEPT (0x01) @@ -4741,22 +4741,22 @@ Specifies the table identifier. Possible values are: @item YYT_ID_NUL_TRANS (0x07) @code{yy_NUL_trans} @item YYT_ID_NXT (0x08) -@code{yy_nxt}. This array may be two dimensional. See the @code{t_hilen} +@code{yy_nxt}. This array may be two dimensional. See the @code{td_hilen} field below. @item YYT_ID_RULE_CAN_MATCH_EOL (0x09) @code{yy_rule_can_match_eol} @item YYT_ID_START_STATE_LIST (0x0A) @code{yy_start_state_list}. This array is handled specially because it is an -array of pointers to srtucts. See the @code{t_flags} field below. +array of pointers to structs. See the @code{td_flags} field below. @item YYT_ID_TRANSITION (0x0B) @code{yy_transition}. This array is handled specially because it is an array of -structs. See the @code{t_lolen} field below. +structs. See the @code{td_lolen} field below. @end table -@item t_flags -Bit flags describing how to interpret the data in @code{t_data}. +@item td_flags +Bit flags describing how to interpret the data in @code{td_data}. The data arrays are one-dimensional by default, but may be -two dimensional as specified in the @code{t_hilen} field. +two dimensional as specified in the @code{td_hilen} field. @table @code @item YYT_DATA8 (0x01) @@ -4773,30 +4773,30 @@ in the @code{yy_transition} array. It is not guaranteed that the the offsets. @end table -@item t_lolen +@item td_lolen Specifies the number of elements in the lowest dimension array. -@item t_hilen -If @code{t_hilen} is non-zero, then the data is a two-dimensional array. -Otherwise, the data is a one-dimensional array. @code{t_hilen} contains the -number of elements in the higher dimensional array, and @code{t_lolen} contains +@item td_hilen +If @code{td_hilen} is non-zero, then the data is a two-dimensional array. +Otherwise, the data is a one-dimensional array. @code{td_hilen} contains the +number of elements in the higher dimensional array, and @code{td_lolen} contains the number of elements in the lowest dimension. -Conceptually, @code{t_data} is either @code{int t_data[t_lolen]}, -or @code{int t_data[t_hilen][t_lolen]}. It is possible for both @code{t_lolen} -and @code{t_hilen} to be zero, in which case @code{t_data} is a zero length +Conceptually, @code{td_data} is either @code{int td_data[td_lolen]}, +or @code{int td_data[td_hilen][td_lolen]}. It is possible for both @code{td_lolen} +and @code{td_hilen} to be zero, in which case @code{td_data} is a zero length array, and no data is loaded, i.e., this table is simply skipped. A special -case is made when @code{t_id} equals @code{YYT_ID_TRANSITION}, then -@code{t_lolen} is the number of structs in the array. Each struct contains two +case is made when @code{td_id} equals @code{YYT_ID_TRANSITION}, then +@code{td_lolen} is the number of structs in the array. Each struct contains two integer fields, with the @code{yy_verify} field first, followed by the @code{yy_nxt} field. -@item t_data[] +@item td_data[] The table data. This array may be a one- or two-dimensional array, of type int8, -int16, or int32, depending upon the values in the @code{t_flags}, @code{t_lolen}, and -@code{t_hilen} fields. +int16, or int32, depending upon the values in the @code{td_flags}, @code{td_lolen}, and +@code{td_hilen} fields. -@item t_pad64[] +@item td_pad64[] Zero or more NUL bytes, padding the table to the next 64-bit boundary. @end table @@ -445,16 +445,6 @@ extern int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap; extern int csize; extern int yymore_used, reject, real_reject, continued_action, in_rule; -/* - * tablesext - if true, create external tables - * tablestoggle - if true, output external tables code while processing skel - * tablesfilename - filename for external tables - * tablesout - FILE stream for external tables - */ -extern bool tablesext, tablestoggle; -extern char *tablesfilename; -extern FILE *tablesout; - extern int yymore_really_used, reject_really_used; @@ -1157,7 +1147,34 @@ extern char *chomp (char *str); /* Tables serialization API declarations. */ #include "tables_shared.h" +struct yytbl_writer { + FILE *out; + uint32_t total_written; + /**< bytes written so far */ + fpos_t th_ssize_pos; + /**< position of th_ssize */ +}; + + +/* + * tablesext - if true, create external tables + * tablestoggle - if true, output external tables code while processing skel + * tablesfilename - filename for external tables + * tableswr - writer for external tables + */ +extern bool tablesext, tablestoggle; +extern char *tablesfilename; +extern struct yytbl_writer tableswr; + +int yytbl_writer_init (struct yytbl_writer *, FILE *); +int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str, + const char *name); int yytbl_data_init (struct yytbl_data *tbl, enum yytbl_id id); +int yytbl_data_destroy (struct yytbl_data *td); +int yytbl_hdr_fwrite (struct yytbl_writer *wr, + const struct yytbl_hdr *th); +int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td); +void yytbl_data_compress (struct yytbl_data *tbl); struct yytbl_data *mkftbl (void); @@ -54,22 +54,18 @@ static int indent_level = 0; /* each level is 8 spaces */ * 0 elements of its arrays, too.) */ static const char *C_int_decl = - "static yyconst int %s[%d] =\n { 0,\n"; static const char *C_short_decl = - "static yyconst short int %s[%d] =\n { 0,\n"; static const char *C_long_decl = - "static yyconst long int %s[%d] =\n { 0,\n"; static const char *C_state_decl = - "static yyconst yy_state_type %s[%d] =\n { 0,\n"; /* Indent to the current level. */ -void do_indent () +void do_indent () { register int i = indent_level * 8; @@ -84,6 +80,31 @@ void do_indent () } } + +/** Make the table for possible eol matches. + * @return the newly allocated rule_can_match_eol table + */ +struct yytbl_data *mkeoltbl (void) +{ + int i; + int8_t *tdata = 0; + struct yytbl_data *tbl; + + tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); + yytbl_data_init (tbl, YYT_ID_RULE_CAN_MATCH_EOL); + tbl->td_flags = YYT_DATA8; + tbl->td_lolen = num_rules + 1; + tbl->td_data = tdata = + (int8_t *) calloc (tbl->td_lolen, sizeof (int8_t)); + + for (i = 0; i < num_rules; i++) + tdata[i] = rule_has_nl[i] ? 1 : 0; + + tdata[i] = rule_has_nl[i] ? 1 : 0; + + return tbl; +} + /* Generate the table for possible eol matches. */ static void geneoltbl () { @@ -91,9 +112,7 @@ static void geneoltbl () outn ("#ifdef YY_USE_LINENO"); outn ("/* Table of booleans, true if rule could match eol. */"); - out_dec - ("static const int yy_rule_can_match_eol[%d] =\n {\n ", - num_rules + 1); + out_dec ("static const int yy_rule_can_match_eol[%d] =\n {\n ", num_rules + 1); for (i = 0; i < num_rules; i++) { out_dec ("%d, ", rule_has_nl[i] ? 1 : 0); @@ -108,7 +127,7 @@ static void geneoltbl () /* Generate the code to keep backing-up information. */ -void gen_backing_up () +void gen_backing_up () { if (reject || num_backing_up == 0) return; @@ -129,7 +148,7 @@ void gen_backing_up () /* Generate the code to perform the backing up. */ -void gen_bu_action () +void gen_bu_action () { if (reject || num_backing_up == 0) return; @@ -155,18 +174,147 @@ void gen_bu_action () set_indent (0); } +/** mkctbl - make full speed compressed transition table + * This is an array of structs; each struct a pair of integers. + * You should call mkssltbl() immediately after this. + * Then, I think, mkecstbl(). Arrrg. + * @return the newly allocated trans table + */ + +struct yytbl_data *mkctbl (void) +{ + register int i; + struct yytbl_data *tbl = 0; + int32_t *tdata = 0, curr = 0; + int end_of_buffer_action = num_rules + 1; + + tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); + yytbl_data_init (tbl, YYT_ID_TRANSITION); + tbl->td_flags |= YYT_DATA32; + tbl->td_hilen = 0; + tbl->td_lolen = tblend + numecs + 1; /* number of structs */ + + tbl->td_data = tdata = + (int32_t *) calloc (tbl->td_lolen * 2, sizeof (int32_t)); + + /* We want the transition to be represented as the offset to the + * next state, not the actual state number, which is what it currently + * is. The offset is base[nxt[i]] - (base of current state)]. That's + * just the difference between the starting points of the two involved + * states (to - from). + * + * First, though, we need to find some way to put in our end-of-buffer + * flags and states. We do this by making a state with absolutely no + * transitions. We put it at the end of the table. + */ + + /* We need to have room in nxt/chk for two more slots: One for the + * action and one for the end-of-buffer transition. We now *assume* + * that we're guaranteed the only character we'll try to index this + * nxt/chk pair with is EOB, i.e., 0, so we don't have to make sure + * there's room for jam entries for other characters. + */ + + while (tblend + 2 >= current_max_xpairs) + expand_nxt_chk (); + + while (lastdfa + 1 >= current_max_dfas) + increase_max_dfas (); + + base[lastdfa + 1] = tblend + 2; + nxt[tblend + 1] = end_of_buffer_action; + chk[tblend + 1] = numecs + 1; + chk[tblend + 2] = 1; /* anything but EOB */ + + /* So that "make test" won't show arb. differences. */ + nxt[tblend + 2] = 0; + + /* Make sure every state has an end-of-buffer transition and an + * action #. + */ + for (i = 0; i <= lastdfa; ++i) { + int anum = dfaacc[i].dfaacc_state; + int offset = base[i]; + + chk[offset] = EOB_POSITION; + chk[offset - 1] = ACTION_POSITION; + nxt[offset - 1] = anum; /* action number */ + } + + for (i = 0; i <= tblend; ++i) { + if (chk[i] == EOB_POSITION) { + tdata[curr++] = 0; + tdata[curr++] = base[lastdfa + 1] - i; + } + + else if (chk[i] == ACTION_POSITION) { + tdata[curr++] = 0; + tdata[curr++] = nxt[i]; + } + + else if (chk[i] > numecs || chk[i] == 0) { + tdata[curr++] = 0; + tdata[curr++] = 0; + } + else { /* verify, transition */ + + tdata[curr++] = chk[i]; + tdata[curr++] = base[nxt[i]] - (i - chk[i]); + } + } + + + /* Here's the final, end-of-buffer state. */ + tdata[curr++] = chk[tblend + 1]; + tdata[curr++] = nxt[tblend + 1]; + + tdata[curr++] = chk[tblend + 2]; + tdata[curr++] = nxt[tblend + 2]; + + /* TODO: deal with this: + if (useecs) + genecs (); + */ + return tbl; +} + + +/** Make start_state_list table. + * @param trans_tbl The transition table created by mkctbl(). + * @return the newly allocated start_state_list table + */ +struct yytbl_data *mkssltbl (struct yytbl_data *trans_tbl) +{ + struct yytbl_data *tbl = 0; + int32_t *tdata = 0; + int32_t i; + + tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); + yytbl_data_init (tbl, YYT_ID_START_STATE_LIST); + tbl->td_flags = YYT_DATA32; + tbl->td_hilen = 0; + tbl->td_lolen = lastsc * 2 + 1; + + tbl->td_data = tdata = + (int32_t *) calloc (tbl->td_lolen, sizeof (int32_t)); + + for (i = 0; i <= lastsc * 2; ++i) + tdata[i] = base[i]; + + return tbl; +} + + /* genctbl - generates full speed compressed transition table */ -void genctbl () +void genctbl () { register int i; int end_of_buffer_action = num_rules + 1; /* Table of verify for transition and offset to next state. */ - out_dec - ("static yyconst struct yy_trans_info yy_transition[%d] =\n", - tblend + numecs + 1); + out_dec ("static yyconst struct yy_trans_info yy_transition[%d] =\n", tblend + numecs + 1); outn (" {"); /* We want the transition to be represented as the offset to the @@ -237,9 +385,7 @@ void genctbl () outn (" };\n"); /* Table of pointers to start states. */ - out_dec - ("static yyconst struct yy_trans_info *yy_start_state_list[%d] =\n", - lastsc * 2 + 1); + out_dec ("static yyconst struct yy_trans_info *yy_start_state_list[%d] =\n", lastsc * 2 + 1); outn (" {"); for (i = 0; i <= lastsc * 2; ++i) @@ -261,8 +407,8 @@ struct yytbl_data *mkecstbl (void) struct yytbl_data *tbl = 0; int32_t *tdata = 0; - tbl = (struct yytbl_data*)flex_alloc(sizeof(struct yytbl_data)); - yytbl_data_init (tbl,YYT_ID_EC); + tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); + yytbl_data_init (tbl, YYT_ID_EC); tbl->td_flags |= YYT_DATA32; tbl->td_hilen = 0; tbl->td_lolen = csize; @@ -300,7 +446,7 @@ struct yytbl_data *mkecstbl (void) /* Generate equivalence-class tables. */ -void genecs () +void genecs () { register int i, j; int numrows; @@ -338,7 +484,7 @@ void genecs () /* Generate the code to find the action number. */ -void gen_find_action () +void gen_find_action () { if (fullspd) indent_puts ("yy_act = yy_current_state[-1].yy_nxt;"); @@ -350,8 +496,7 @@ void gen_find_action () indent_puts ("yy_current_state = *--YY_G(yy_state_ptr);"); indent_puts ("YY_G(yy_lp) = yy_accept[yy_current_state];"); - outn - ("find_rule: /* we branch to this label when backing up */"); + outn ("find_rule: /* we branch to this label when backing up */"); indent_puts ("for ( ; ; ) /* until we find what rule we matched */"); @@ -484,8 +629,8 @@ struct yytbl_data *mkftbl (void) struct yytbl_data *tbl; int32_t *tdata = 0; - tbl = (struct yytbl_data*)flex_alloc(sizeof(struct yytbl_data)); - yytbl_data_init (tbl,YYT_ID_ACCEPT); + tbl = (struct yytbl_data *) calloc (1, sizeof (struct yytbl_data)); + yytbl_data_init (tbl, YYT_ID_ACCEPT); tbl->td_flags |= YYT_DATA32; tbl->td_hilen = 0; /* it's a one-dimensional array */ tbl->td_lolen = lastdfa + 1; @@ -511,7 +656,7 @@ struct yytbl_data *mkftbl (void) /* genftbl - generate full transition table */ -void genftbl () +void genftbl () { register int i; int end_of_buffer_action = num_rules + 1; @@ -544,7 +689,7 @@ void genftbl () /* Generate the code to find the next compressed-table state. */ -void gen_next_compressed_state (char_map) +void gen_next_compressed_state (char_map) char *char_map; { indent_put2s ("register YY_CHAR yy_c = %s;", char_map); @@ -589,17 +734,15 @@ void gen_next_compressed_state (char_map) /* Generate the code to find the next match. */ -void gen_next_match () +void gen_next_match () { /* NOTE - changes in here should be reflected in gen_next_state() and * gen_NUL_trans(). */ char *char_map = useecs ? - "yy_ec[YY_SC_TO_UI(*yy_cp)]" : "YY_SC_TO_UI(*yy_cp)"; char *char_map_2 = useecs ? - "yy_ec[YY_SC_TO_UI(*++yy_cp)]" : "YY_SC_TO_UI(*++yy_cp)"; if (fulltbl) { @@ -672,9 +815,7 @@ void gen_next_match () do_indent (); if (interactive) - out_dec - ("while ( yy_base[yy_current_state] != %d );\n", - jambase); + out_dec ("while ( yy_base[yy_current_state] != %d );\n", jambase); else out_dec ("while ( yy_current_state != %d );\n", jamstate); @@ -694,8 +835,8 @@ void gen_next_match () /* Generate the code to find the next state. */ -void gen_next_state (worry_about_NULs) - int worry_about_NULs; +void gen_next_state (worry_about_NULs) + int worry_about_NULs; { /* NOTE - changes in here should be reflected in gen_next_match() */ char char_map[256]; @@ -759,7 +900,7 @@ void gen_next_state (worry_about_NULs) /* Generate the code to make a NUL transition. */ -void gen_NUL_trans () +void gen_NUL_trans () { /* NOTE - changes in here should be reflected in gen_next_match() */ /* Only generate a definition for "yy_cp" if we'll generate code * that uses it. Otherwise lint and the like complain. @@ -782,9 +923,7 @@ void gen_NUL_trans () else if (fulltbl) { do_indent (); - out_dec - ("yy_current_state = yy_nxt[yy_current_state][%d];\n", - NUL_ec); + out_dec ("yy_current_state = yy_nxt[yy_current_state][%d];\n", NUL_ec); indent_puts ("yy_is_jam = (yy_current_state <= 0);"); } @@ -843,7 +982,7 @@ void gen_NUL_trans () /* Generate the code to find the start state. */ -void gen_start_state () +void gen_start_state () { if (fullspd) { if (bol_needed) { @@ -876,10 +1015,15 @@ void gen_start_state () /* gentabs - generate data statements for the transition tables */ -void gentabs () +void gentabs () { int i, j, k, *accset, nacc, *acc_array, total_states; int end_of_buffer_action = num_rules + 1; + struct yytbl_data *yyacc_tbl = 0, *yymeta_tbl = 0, *yybase_tbl = 0, + *yydef_tbl = 0, *yynxt_tbl = 0, *yychk_tbl = 0; + int32_t *yyacc_data = 0, *yybase_data = 0, *yydef_data = 0, + *yynxt_data = 0, *yychk_data = 0; + int32_t yybase_curr = 0; acc_array = allocate_integer_array (current_max_dfas); nummt = 0; @@ -977,6 +1121,8 @@ void gentabs () acc_array[i] = 0; } + /* Begin generating yy_accept */ + /* Spit out "yy_accept" array. If we're doing "reject", it'll be * pointers into the "yy_acclist" array. Otherwise it's actual * accepting numbers. In either case, we just dump the numbers. @@ -998,8 +1144,17 @@ void gentabs () out_str_dec (long_align ? C_long_decl : C_short_decl, "yy_accept", k); + yyacc_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct yytbl_data)); + yytbl_data_init (yyacc_tbl, YYT_ID_ACCEPT); + yyacc_tbl->td_lolen = k; + yyacc_tbl->td_data = yyacc_data = + (int32_t *) calloc (yyacc_tbl->td_lolen, sizeof (int32_t)); + for (i = 1; i <= lastdfa; ++i) { mkdata (acc_array[i]); + yyacc_data[i] = acc_array[i]; if (!reject && trace && acc_array[i]) fprintf (stderr, _("state # %d accepts: [%d]\n"), @@ -1008,20 +1163,42 @@ void gentabs () /* Add entry for "jam" state. */ mkdata (acc_array[i]); + yyacc_data[i] = acc_array[i]; - if (reject) + if (reject) { /* Add "cap" for the list. */ mkdata (acc_array[i]); + yyacc_data[i] = acc_array[i]; + } dataend (); + if (tablesext) { + yytbl_data_compress (yyacc_tbl); + if (yytbl_data_fwrite (&tableswr, yyacc_tbl) < 0) + flexerror (_("Could not write yyacc_tbl")); + yytbl_data_destroy (yyacc_tbl); + yyacc_tbl = NULL; + } + /* End generating yy_accept */ if (useecs) genecs (); if (usemecs) { + /* Begin generating yy_meta */ /* Write out meta-equivalence classes (used to index * templates with). */ + int32_t *yymecs_data = 0; + yymeta_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct + yytbl_data)); + yytbl_data_init (yymeta_tbl, YYT_ID_META); + yymeta_tbl->td_lolen = numecs + 1; + yymeta_tbl->td_data = yymecs_data = + (int32_t *) calloc (yymeta_tbl->td_lolen, + sizeof (int32_t)); if (trace) fputs (_("\n\nMeta-Equivalence Classes:\n"), @@ -1035,17 +1212,38 @@ void gentabs () i, ABS (tecbck[i])); mkdata (ABS (tecbck[i])); + yymecs_data[i] = ABS (tecbck[i]); } dataend (); + if (tablesext) { + yytbl_data_compress (yymeta_tbl); + if (yytbl_data_fwrite (&tableswr, yymeta_tbl) < 0) + flexerror (_ + ("Could not write yymeta_tbl")); + yytbl_data_destroy (yymeta_tbl); + yymeta_tbl = NULL; + } + /* End generating yy_meta */ } total_states = lastdfa + numtemps; + /* Begin generating yy_base */ out_str_dec ((tblend >= MAX_SHORT || long_align) ? C_long_decl : C_short_decl, "yy_base", total_states + 1); + yybase_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct yytbl_data)); + yytbl_data_init (yybase_tbl, YYT_ID_BASE); + yybase_tbl->td_lolen = total_states + 1; + yybase_tbl->td_data = yybase_data = + (int32_t *) calloc (yybase_tbl->td_lolen, + sizeof (int32_t)); + yybase_curr = 1; + for (i = 1; i <= lastdfa; ++i) { register int d = def[i]; @@ -1062,30 +1260,72 @@ void gentabs () } mkdata (base[i]); + yybase_data[yybase_curr++] = base[i]; } /* Generate jam state's base index. */ mkdata (base[i]); + yybase_data[yybase_curr++] = base[i]; for (++i /* skip jam state */ ; i <= total_states; ++i) { mkdata (base[i]); + yybase_data[yybase_curr++] = base[i]; def[i] = jamstate; } dataend (); + if (tablesext) { + yytbl_data_compress (yybase_tbl); + if (yytbl_data_fwrite (&tableswr, yybase_tbl) < 0) + flexerror (_("Could not write yybase_tbl")); + yytbl_data_destroy (yybase_tbl); + yybase_tbl = NULL; + } + /* End generating yy_base */ + + /* Begin generating yy_def */ out_str_dec ((total_states >= MAX_SHORT || long_align) ? C_long_decl : C_short_decl, "yy_def", total_states + 1); - for (i = 1; i <= total_states; ++i) + + yydef_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct yytbl_data)); + yytbl_data_init (yydef_tbl, YYT_ID_DEF); + yydef_tbl->td_lolen = total_states + 1; + yydef_tbl->td_data = yydef_data = + (int32_t *) calloc (yydef_tbl->td_lolen, sizeof (int32_t)); + + for (i = 1; i <= total_states; ++i) { mkdata (def[i]); + yydef_data[i] = base[i]; + } dataend (); + if (tablesext) { + yytbl_data_compress (yydef_tbl); + if (yytbl_data_fwrite (&tableswr, yydef_tbl) < 0) + flexerror (_("Could not write yydef_tbl")); + yytbl_data_destroy (yydef_tbl); + yydef_tbl = NULL; + } + /* End generating yy_def */ + + /* Begin generating yy_nxt */ out_str_dec ((total_states >= MAX_SHORT || long_align) ? C_long_decl : C_short_decl, "yy_nxt", tblend + 1); + yynxt_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct yytbl_data)); + yytbl_data_init (yynxt_tbl, YYT_ID_NXT); + yynxt_tbl->td_lolen = tblend + 1; + yynxt_tbl->td_data = yynxt_data = + (int32_t *) calloc (yynxt_tbl->td_lolen, sizeof (int32_t)); + for (i = 1; i <= tblend; ++i) { /* Note, the order of the following test is important. * If chk[i] is 0, then nxt[i] is undefined. @@ -1094,21 +1334,48 @@ void gentabs () nxt[i] = jamstate; /* new state is the JAM state */ mkdata (nxt[i]); + yynxt_data[i] = nxt[i]; } dataend (); + if (tablesext) { + yytbl_data_compress (yynxt_tbl); + if (yytbl_data_fwrite (&tableswr, yynxt_tbl) < 0) + flexerror (_("Could not write yynxt_tbl")); + yytbl_data_destroy (yynxt_tbl); + yynxt_tbl = NULL; + } + /* End generating yy_nxt */ + /* Begin generating yy_chk */ out_str_dec ((total_states >= MAX_SHORT || long_align) ? C_long_decl : C_short_decl, "yy_chk", tblend + 1); + yychk_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct yytbl_data)); + yytbl_data_init (yychk_tbl, YYT_ID_CHK); + yychk_tbl->td_lolen = tblend + 1; + yychk_tbl->td_data = yychk_data = + (int32_t *) calloc (yychk_tbl->td_lolen, sizeof (int32_t)); + for (i = 1; i <= tblend; ++i) { if (chk[i] == 0) ++nummt; mkdata (chk[i]); + yychk_data[i] = chk[i]; } dataend (); + if (tablesext) { + yytbl_data_compress (yychk_tbl); + if (yytbl_data_fwrite (&tableswr, yychk_tbl) < 0) + flexerror (_("Could not write yychk_tbl")); + yytbl_data_destroy (yychk_tbl); + yychk_tbl = NULL; + } + /* End generating yy_chk */ flex_free ((void *) acc_array); } @@ -1118,7 +1385,7 @@ void gentabs () * current indentation level, adding a final newline. */ -void indent_put2s (fmt, arg) +void indent_put2s (fmt, arg) const char *fmt, *arg; { do_indent (); @@ -1131,7 +1398,7 @@ void indent_put2s (fmt, arg) * newline. */ -void indent_puts (str) +void indent_puts (str) const char *str; { do_indent (); @@ -1142,10 +1409,12 @@ void indent_puts (str) /* make_tables - generate transition tables and finishes generating output file */ -void make_tables () +void make_tables () { register int i; int did_eof_rule = false; + struct yytbl_data *yynultrans_tbl; + skelout (); /* %% [2.0] - break point in skel */ @@ -1233,8 +1502,12 @@ void make_tables () indent_down (); } - if (fullspd) + if (fullspd) { genctbl (); + if (tablesext) { + /* TODO: mkctbl(); */ + } + } else if (fulltbl) genftbl (); else @@ -1257,17 +1530,44 @@ void make_tables () } if (nultrans) { + int32_t *yynultrans_data = 0; + + /* Begin generating yy_NUL_trans */ out_str_dec (C_state_decl, "yy_NUL_trans", lastdfa + 1); + yynultrans_tbl = + (struct yytbl_data *) calloc (1, + sizeof (struct + yytbl_data)); + yytbl_data_init (yynultrans_tbl, YYT_ID_NUL_TRANS); + yynultrans_tbl->td_lolen = lastdfa + 1; + yynultrans_tbl->td_data = yynultrans_data = + (int32_t *) calloc (yynultrans_tbl->td_lolen, + sizeof (int32_t)); + for (i = 1; i <= lastdfa; ++i) { - if (fullspd) + if (fullspd) { out_dec (" &yy_transition[%d],\n", base[i]); - else + yynultrans_data[i] = base[i]; + } + else { mkdata (nultrans[i]); + yynultrans_data[i] = nultrans[i]; + } } dataend (); + if (tablesext) { + yytbl_data_compress (yynultrans_tbl); + if (yytbl_data_fwrite (&tableswr, yynultrans_tbl) < + 0) + flexerror (_ + ("Could not write yynultrans_tbl")); + yytbl_data_destroy (yynultrans_tbl); + yynultrans_tbl = NULL; + } + /* End generating yy_NUL_trans */ } if (ddebug) { /* Spit out table mapping rules to line numbers. */ @@ -1287,16 +1587,14 @@ void make_tables () outn ("#ifdef YY_USES_REJECT"); /* Declare state buffer variables. */ if (!C_plus_plus && !reentrant) { - outn - ("static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;"); + outn ("static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;"); outn ("static char *yy_full_match;"); outn ("static int yy_lp;"); } if (variable_trailing_context_rules) { if (!C_plus_plus) { - outn - ("static int yy_looking_for_trail_begin = 0;"); + outn ("static int yy_looking_for_trail_begin = 0;"); outn ("static int yy_full_lp;"); outn ("static int *yy_full_state;"); } @@ -1309,18 +1607,13 @@ void make_tables () outn ("#define REJECT \\"); outn ("{ \\"); - outn - ("*yy_cp = YY_G(yy_hold_char); /* undo effects of setting up yytext */ \\"); - outn - ("yy_cp = YY_G(yy_full_match); /* restore poss. backed-over text */ \\"); + outn ("*yy_cp = YY_G(yy_hold_char); /* undo effects of setting up yytext */ \\"); + outn ("yy_cp = YY_G(yy_full_match); /* restore poss. backed-over text */ \\"); if (variable_trailing_context_rules) { - outn - ("YY_G(yy_lp) = yy_full_lp; /* restore orig. accepting pos. */ \\"); - outn - ("YY_G(yy_state_ptr) = yy_full_state; /* restore orig. state */ \\"); - outn - ("yy_current_state = *YY_G(yy_state_ptr); /* restore curr. state */ \\"); + outn ("YY_G(yy_lp) = yy_full_lp; /* restore orig. accepting pos. */ \\"); + outn ("YY_G(yy_state_ptr) = yy_full_state; /* restore orig. state */ \\"); + outn ("yy_current_state = *YY_G(yy_state_ptr); /* restore curr. state */ \\"); } outn ("++YY_G(yy_lp); \\"); @@ -1331,8 +1624,7 @@ void make_tables () } else { - outn - ("/* The intent behind this definition is that it'll catch"); + outn ("/* The intent behind this definition is that it'll catch"); outn (" * any uses of REJECT which flex missed."); outn (" */"); outn ("#define REJECT reject_used_but_not_detected"); @@ -1416,13 +1708,11 @@ void make_tables () if (!C_plus_plus) { if (use_read) { outn ("\terrno=0; \\"); - outn - ("\twhile ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \\"); + outn ("\twhile ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \\"); outn ("\t{ \\"); outn ("\t\tif( errno != EINTR) \\"); outn ("\t\t{ \\"); - outn - ("\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); + outn ("\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); outn ("\t\t\tbreak; \\"); outn ("\t\t} \\"); outn ("\t\terrno=0; \\"); @@ -1431,32 +1721,27 @@ void make_tables () } else { - outn - ("\tif ( YY_G(yy_current_buffer)->yy_is_interactive ) \\"); + outn ("\tif ( YY_G(yy_current_buffer)->yy_is_interactive ) \\"); outn ("\t\t{ \\"); outn ("\t\tint c = '*'; \\"); outn ("\t\tsize_t n; \\"); outn ("\t\tfor ( n = 0; n < max_size && \\"); - outn - ("\t\t\t (c = getc( yyin )) != EOF && c != '\\n'; ++n ) \\"); + outn ("\t\t\t (c = getc( yyin )) != EOF && c != '\\n'; ++n ) \\"); outn ("\t\t\tbuf[n] = (char) c; \\"); outn ("\t\tif ( c == '\\n' ) \\"); outn ("\t\t\tbuf[n++] = (char) c; \\"); outn ("\t\tif ( c == EOF && ferror( yyin ) ) \\"); - outn - ("\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); + outn ("\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); outn ("\t\tresult = n; \\"); outn ("\t\t} \\"); outn ("\telse \\"); outn ("\t\t{ \\"); outn ("\t\terrno=0; \\"); - outn - ("\t\twhile ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \\"); + outn ("\t\twhile ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \\"); outn ("\t\t\t{ \\"); outn ("\t\t\tif( errno != EINTR) \\"); outn ("\t\t\t\t{ \\"); - outn - ("\t\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); + outn ("\t\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\"); outn ("\t\t\t\tbreak; \\"); outn ("\t\t\t\t} \\"); outn ("\t\t\terrno=0; \\"); @@ -52,7 +52,6 @@ int interactive, caseins, lex_compat, posix_compat, do_yylineno, useecs, fulltbl, usemecs; int fullspd, gen_line_dirs, performance_report, backing_up_report; int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap, - csize; int reentrant, reentrant_bison_pure; int yymore_used, reject, real_reject, continued_action, in_rule; @@ -62,7 +61,6 @@ FILE *skelfile = NULL; int skel_ind = 0; char *action_array; int action_size, defs1_offset, prolog_offset, action_offset, - action_index; char *infilename = NULL, *outfilename = NULL, *headerfilename = NULL; int did_outfilename; @@ -109,7 +107,7 @@ int nlch = '\n'; bool tablesext, tablestoggle; char *tablesfilename; -FILE *tablesout; +struct yytbl_writer tableswr; /* Make sure program_name is initialized so we don't crash if writing * out an error message before getting the program name from argv[0]. @@ -119,9 +117,11 @@ char *program_name = "flex"; #ifndef SHORT_FILE_NAMES static char *outfile_template = "lex.%s.%s"; static char *backing_name = "lex.backup"; +static char *tablesfile_template = "lex.%s.tables"; #else static char *outfile_template = "lex%s.%s"; static char *backing_name = "lex.bck"; +static char *tablesfile_template = "lex%s.tbl"; #endif #ifdef MS_DOS @@ -136,8 +136,8 @@ int flex_main PROTO ((int argc, char *argv[])); int main PROTO ((int argc, char *argv[])); void fix_line_dirs PROTO ((char *, char *, char *, int)); -int flex_main (argc, argv) - int argc; +int flex_main (argc, argv) + int argc; char *argv[]; { int i, exit_status; @@ -167,7 +167,7 @@ int flex_main (argc, argv) if (spprdflt && !reject && rule_useful[default_rule]) line_warning (_ ("-s option given but default rule can be matched"), -rule_linenum[default_rule]); + rule_linenum[default_rule]); /* Generate the C state transition tables from the DFA. */ make_tables (); @@ -181,8 +181,8 @@ rule_linenum[default_rule]); } /* Wrapper around flex_main, so flex_main can be built as a library. */ -int main (argc, argv) - int argc; +int main (argc, argv) + int argc; char *argv[]; { #if ENABLE_NLS @@ -196,7 +196,7 @@ int main (argc, argv) /* check_options - check user-specified options */ -void check_options () +void check_options () { int i; @@ -325,6 +325,38 @@ void check_options () outfile_created = 1; } + if (tablesext) { + FILE *tablesout; + struct yytbl_hdr hdr; + char *pname = 0; + int nbytes = 0; + + if (!tablesfilename) { + nbytes = strlen (prefix) + + strlen (tablesfile_template) + 2; + tablesfilename = pname = + (char *) calloc (nbytes, 1); + sprintf (pname, tablesfile_template, prefix); + } + + if ((tablesout = fopen (tablesfilename, "w")) == NULL) + lerrsf (_("could not create %s"), tablesfilename); + if (pname) + free (pname); + tablesfilename = 0; + + yytbl_writer_init (&tableswr, tablesout); + + nbytes = strlen (prefix) + strlen ("tables") + 2; + pname = (char *) calloc (nbytes, 1); + sprintf (pname, "%stables", prefix); + yytbl_hdr_init (&hdr, "TODO", pname); + free (pname); + + if (yytbl_hdr_fwrite (&tableswr, &hdr) <= 0) + flexerror (_("could not write tables header")); + } + if (skelname && (skelfile = fopen (skelname, "r")) == NULL) lerrsf (_("can't open skeleton file %s"), skelname); @@ -418,11 +450,11 @@ void check_options () * for the generated header. We chaneg the line number and filename. * linebuf is modified in place. */ -void fix_line_dirs (linebuf, outfilename, headerfilename, nlines) +void fix_line_dirs (linebuf, outfilename, headerfilename, nlines) char *linebuf; char *outfilename; char *headerfilename; - int nlines; + int nlines; { char *pname, *p; @@ -475,8 +507,8 @@ void fix_line_dirs (linebuf, outfilename, headerfilename, nlines) * This routine does not return. */ -void flexend (exit_status) - int exit_status; +void flexend (exit_status) + int exit_status; { static int called_before = -1; /* prevent infinite recursion. */ @@ -532,10 +564,8 @@ void flexend (exit_status) while (fgets (linebuf, LINE_SZ, stdout)) { if (strstr (linebuf, "YY-DISCARD-FROM-HEADER")) discard++; - else - if (strstr - (linebuf, - "YY-END-DISCARD-FROM-HEADER")) { + else if (strstr + (linebuf, "YY-END-DISCARD-FROM-HEADER")) { discard--; continue; } @@ -971,8 +1001,8 @@ void flexend (exit_status) /* flexinit - initialize flex */ -void flexinit (argc, argv) - int argc; +void flexinit (argc, argv) + int argc; char **argv; { int i, sawcmpflag, rv, optind; @@ -997,7 +1027,6 @@ void flexinit (argc, argv) use_read = use_stdout = false; tablesext = tablestoggle = false; tablesfilename = NULL; - tablesout = NULL; sawcmpflag = false; @@ -1176,7 +1205,7 @@ void flexinit (argc, argv) else lerrif (_ ("unknown -R option '%c'"), -(int) arg[0]); + (int) arg[0]); } break; @@ -1205,8 +1234,9 @@ void flexinit (argc, argv) "1"); break; - case OPT_TABLES: + case OPT_TABLES_FILE: tablesext = true; + tablesfilename = arg; break; case OPT_TRACE: @@ -1472,11 +1502,10 @@ void flexinit (argc, argv) /* readin - read in the rules section of the input file(s) */ -void readin () +void readin () { static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;"; static char yy_nostdinit[] = - "FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;"; line_directive_out ((FILE *) 0, 1); @@ -1515,7 +1544,7 @@ void readin () if (backing_up_file == NULL) lerrsf (_ ("could not create backing-up info file %s"), -backing_name); + backing_name); } else @@ -1648,8 +1677,7 @@ backing_name); OUT_BEGIN_CODE (); if (fullspd) - outn - ("typedef yyconst struct yy_trans_info *yy_state_type;"); + outn ("typedef yyconst struct yy_trans_info *yy_state_type;"); else if (!C_plus_plus) outn ("typedef int yy_state_type;"); OUT_END_CODE (); @@ -1672,8 +1700,7 @@ backing_name); if (yyclass) { outn ("int yyFlexLexer::yylex()"); outn ("\t{"); - outn - ("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );"); + outn ("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );"); outn ("\treturn 0;"); outn ("\t}"); @@ -1722,7 +1749,7 @@ backing_name); /* set_up_initial_allocations - allocate memory for internal tables */ -void set_up_initial_allocations () +void set_up_initial_allocations () { maximum_mns = (long_align ? MAXIMUM_MNS_LONG : MAXIMUM_MNS); current_mns = INITIAL_MNS; @@ -1784,7 +1811,7 @@ void set_up_initial_allocations () * (same concept as /bin/sh `basename`, but different handling of extension). */ static char *basename2 (path, strip_ext) char *path; - int strip_ext; /* boolean */ + int strip_ext; /* boolean */ { char *b, *e = 0; @@ -1800,7 +1827,7 @@ static char *basename2 (path, strip_ext) return b; } -void usage () +void usage () { FILE *f = stdout; @@ -1838,7 +1865,7 @@ void usage () " -t, --stdout write scanner on stdout instead of %s\n" " --yyclass=NAME name of C++ class\n" " --header=FILE create a C header file in addition to the scanner\n" - " --tables[=FILE] write tables to FILE\n" "\n" + " --tables-file[=FILE] write tables to FILE\n" "\n" "Scanner behavior:\n" " -7, --7bit generate 7-bit scanner\n" " -8, --8bit generate 8-bit scanner\n" @@ -187,7 +187,7 @@ optspec_t flexopts[] = { , {"--trace", OPT_TRACE, 0} , /* Flex should run in trace mode. */ - {"--tables[=FILE]", OPT_TABLES, 0} + {"--tables-file[=FILE]", OPT_TABLES_FILE, 0} , /* Save tables to FILE */ {"--nounistd", OPT_NO_UNISTD_H, 0} , /* Do not include unistd.h */ @@ -112,7 +112,7 @@ enum flexopt_flag_t { OPT_STACK, OPT_STDINIT, OPT_STDOUT, - OPT_TABLES, + OPT_TABLES_FILE, OPT_TRACE, OPT_NO_UNISTD_H, OPT_VERBOSE, @@ -315,8 +315,8 @@ LEXOPT [aceknopr] outfile return OPT_OUTFILE; prefix return OPT_PREFIX; yyclass return OPT_YYCLASS; - header return OPT_HEADER; - tables return OPT_TABLES; + header(-file)? return OPT_HEADER; + tables-file return OPT_TABLES; \"[^"\n]*\" { strcpy( nmstr, yytext + 1 ); @@ -62,28 +62,44 @@ */ #define TFLAGS_CLRDATA(flg) ((flg) & ~(YYT_DATA8 | YYT_DATA16 | YYT_DATA32)) -int yytbl_fwrite32 (FILE * out, uint32_t v); -int yytbl_fwrite16 (FILE * out, uint16_t v); -int yytbl_fwrite8 (FILE * out, uint8_t v); +int yytbl_fwrite32 (struct yytbl_writer *wr, uint32_t v); +int yytbl_fwrite16 (struct yytbl_writer *wr, uint16_t v); +int yytbl_fwrite8 (struct yytbl_writer *wr, uint8_t v); +int yytbl_fwriten (struct yytbl_writer *wr, void *v, int32_t len); +static int32_t tbl_get_total_len (struct yytbl_data *tbl); +static int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i); + + +/** Initialize the table writer. + * @param wr an uninitialized writer + * @param the output file + * @return 0 on success + */ +int yytbl_writer_init (struct yytbl_writer *wr, FILE * out) +{ + wr->out = out; + wr->total_written = 0; + return 0; +} /** Initialize a table header. * @param th The uninitialized structure * @param version_str the version string * @param name the name of this table set */ -void yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str, - const char *name) +int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str, + const char *name) { memset (th, 0, sizeof (struct yytbl_hdr)); th->th_magic = 0xF13C57B1; - th->th_hsize = - yypad64 (20 + strlen (version_str) + 1 + strlen (name) + - 1); + th->th_hsize = 14 + strlen (version_str) + 1 + strlen (name) + 1; + th->th_hsize += yypad64 (th->th_hsize); th->th_ssize = 0; // Not known at this point. th->th_flags = 0; th->th_version = copy_string (version_str); th->th_name = copy_string (name); + return 0; } /** Allocate and initialize a table data structure. @@ -100,41 +116,64 @@ int yytbl_data_init (struct yytbl_data *td, enum yytbl_id id) return 0; } +int yytbl_data_destroy (struct yytbl_data *td) +{ + if (td->td_data) + free (td->td_data); + td->td_data = 0; + free (td); + return 0; +} +static int yytbl_fwrite_pad64 (struct yytbl_writer *wr) +{ + int pad, bwritten = 0; + + pad = yypad64 (wr->total_written); + while (pad-- > 0) + if (yytbl_fwrite8 (wr, 0) < 0) + return -1; + else + bwritten++; + return bwritten; +} + /** write the header. * @param out the output stream * @param th table header to be written * @return -1 on error, or bytes written on success. */ -int yytbl_hdr_fwrite (FILE * out, const struct yytbl_hdr *th) +int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th) { size_t sz, rv; - int pad, bwritten = 0; + int bwritten = 0; - if (yytbl_fwrite32 (out, th->th_magic) < 0 - || yytbl_fwrite32 (out, th->th_hsize) < 0 - || yytbl_fwrite32 (out, th->th_ssize) < 0 - || yytbl_fwrite16 (out, th->th_flags) < 0) + if (yytbl_fwrite32 (wr, th->th_magic) < 0 + || yytbl_fwrite32 (wr, th->th_hsize) < 0) return -1; - else - bwritten += 3 * 4 + 2; + bwritten += 8; + + if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0) + return -1; + + if (yytbl_fwrite32 (wr, th->th_ssize) < 0 + || yytbl_fwrite16 (wr, th->th_flags) < 0) + return -1; + bwritten += 6; sz = strlen (th->th_version) + 1; - if ((rv = fwrite (th->th_version, 1, sz, out)) != sz) + if ((rv = yytbl_fwriten (wr, th->th_version, sz)) != sz) return -1; bwritten += rv; sz = strlen (th->th_name) + 1; - if ((rv = fwrite (th->th_name, 1, sz, out)) != sz) + if ((rv = yytbl_fwriten (wr, th->th_name, sz)) != sz) return 1; bwritten += rv; /* add padding */ - pad = yypad64 (bwritten) - bwritten; - while (pad-- > 0) - if (yytbl_fwrite8 (out, 0) < 0) - return -1; - else - bwritten++; + if ((rv = yytbl_fwrite_pad64 (wr)) < 0) + return -1; + bwritten += rv; /* Sanity check */ if (bwritten != th->th_hsize) { @@ -145,55 +184,146 @@ int yytbl_hdr_fwrite (FILE * out, const struct yytbl_hdr *th) return bwritten; } + +/** Write this table. + * @param out the file writer + * @param td table data to be written + * @return -1 on error, or bytes written on success. + */ +int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td) +{ + size_t rv; + int32_t bwritten = 0; + int32_t i, total_len; + fpos_t pos; + + if ((rv = yytbl_fwrite16 (wr, td->td_id)) < 0) + return -1; + bwritten += rv; + + if ((rv = yytbl_fwrite16 (wr, td->td_flags)) < 0) + return -1; + bwritten += rv; + + if ((rv = yytbl_fwrite32 (wr, td->td_hilen)) < 0) + return -1; + bwritten += rv; + + if ((rv = yytbl_fwrite32 (wr, td->td_lolen)) < 0) + return -1; + bwritten += rv; + + total_len = tbl_get_total_len (td); + for (i = 0; i < total_len; i++) { + switch (TFLAGS2BYTES (td->td_flags)) { + case sizeof (int8_t): + rv = yytbl_fwrite8 (wr, yytbl_data_geti (td, i)); + break; + case sizeof (int16_t): + rv = yytbl_fwrite16 (wr, yytbl_data_geti (td, i)); + break; + case sizeof (int32_t): + rv = yytbl_fwrite32 (wr, yytbl_data_geti (td, i)); + break; + default: /* TODO: error. Something really wrong. */ + } + if (rv < 0) + return -1; + bwritten += rv; + } + + /* Sanity check */ + if (bwritten != (12 + total_len * TFLAGS2BYTES (td->td_flags))) { + /* Oops. */ + return -1; + } + + /* add padding */ + if ((rv = yytbl_fwrite_pad64 (wr)) < 0) + return -1; + bwritten += rv; + + /* Now go back and update the th_hsize member */ + if (fgetpos (wr->out, &pos) != 0 + || fsetpos (wr->out, &(wr->th_ssize_pos)) != 0 + || yytbl_fwrite32 (wr, wr->total_written) < 0 + || fsetpos (wr->out, &pos)) + return -1; + else + /* Don't count the int we just wrote. */ + wr->total_written -= sizeof (int32_t); + return bwritten; +} + +/** Write n bytes. + * @param wr the table writer + * @param v data to be written + * @param len number of bytes + * @return -1 on error. number of bytes written on success. + */ +int yytbl_fwriten (struct yytbl_writer *wr, void *v, int32_t len) +{ + size_t rv; + + rv = fwrite (v, 1, len, wr->out); + if (rv != len) + return -1; + wr->total_written += len; + return len; +} + /** Write four bytes in network byte order - * @param out the output stream + * @param wr the table writer * @param v a dword in host byte order * @return -1 on error. number of bytes written on success. */ -int yytbl_fwrite32 (FILE * out, uint32_t v) +int yytbl_fwrite32 (struct yytbl_writer *wr, uint32_t v) { uint32_t vnet; size_t bytes, rv; vnet = htonl (v); bytes = sizeof (uint32_t); - rv = fwrite (&vnet, bytes, 1, out); - if (rv != bytes) + rv = fwrite (&vnet, bytes, 1, wr->out); + if (rv != 1) return -1; + wr->total_written += bytes; return bytes; } /** Write two bytes in network byte order. - * @param out the output stream + * @param wr the table writer * @param v a word in host byte order * @return -1 on error. number of bytes written on success. */ -int yytbl_fwrite16 (FILE * out, uint16_t v) +int yytbl_fwrite16 (struct yytbl_writer *wr, uint16_t v) { uint16_t vnet; size_t bytes, rv; vnet = htons (v); bytes = sizeof (uint16_t); - rv = fwrite (&vnet, bytes, 1, out); - if (rv != bytes) + rv = fwrite (&vnet, bytes, 1, wr->out); + if (rv != 1) return -1; + wr->total_written += bytes; return bytes; } /** Write a byte. - * @param out the output stream + * @param wr the table writer * @param v the value to be written * @return -1 on error. number of bytes written on success. */ -int yytbl_fwrite8 (FILE * out, uint8_t v) +int yytbl_fwrite8 (struct yytbl_writer *wr, uint8_t v) { size_t bytes, rv; bytes = sizeof (uint8_t); - rv = fwrite (&v, bytes, 1, out); - if (rv != bytes) + rv = fwrite (&v, bytes, 1, wr->out); + if (rv != 1) return -1; + wr->total_written += bytes; return bytes; } @@ -283,16 +413,19 @@ static int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i) * @param newval new value for data[i] */ static void yytbl_data_seti (const struct yytbl_data *tbl, int i, - int newval) + int32_t newval) { switch (TFLAGS2BYTES (tbl->td_flags)) { case sizeof (int8_t): ((int8_t *) (tbl->td_data))[i] = (int8_t) newval; + break; case sizeof (int16_t): ((int16_t *) (tbl->td_data))[i] = (int16_t) newval; + break; case sizeof (int32_t): ((int32_t *) (tbl->td_data))[i] = (int32_t) newval; + break; default: /* TODO: error. major foobar somewhere. */ break; } @@ -349,7 +482,6 @@ void yytbl_data_compress (struct yytbl_data *tbl) newsz = min_int_size (tbl); - if (newsz == TFLAGS2BYTES (tbl->td_flags)) /* No change in this table needed. */ return; @@ -360,12 +492,16 @@ void yytbl_data_compress (struct yytbl_data *tbl) } total_len = tbl_get_total_len (tbl); - newtbl.td_data = flex_alloc (newsz * total_len); + newtbl.td_data = calloc (total_len, newsz); newtbl.td_flags = - TFLAGS_CLRDATA (newtbl.td_flags) & BYTES2TFLAG (newsz); + TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz); - for (i = 0; i < total_len; i++) - yytbl_data_seti (&newtbl, i, yytbl_data_geti (tbl, i)); + for (i = 0; i < total_len; i++) { + int32_t g; + + g = yytbl_data_geti (tbl, i); + yytbl_data_seti (&newtbl, i, g); + } /* Now copy over the old table */ |