summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flex.texi54
-rw-r--r--flexdef.h37
-rw-r--r--gen.c443
-rw-r--r--main.c93
-rw-r--r--options.c2
-rw-r--r--options.h2
-rw-r--r--scan.l4
-rw-r--r--tables.c220
8 files changed, 660 insertions, 195 deletions
diff --git a/flex.texi b/flex.texi
index 40af567..e84ef40 100644
--- a/flex.texi
+++ b/flex.texi
@@ -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
diff --git a/flexdef.h b/flexdef.h
index b7fdd64..a571fb7 100644
--- a/flexdef.h
+++ b/flexdef.h
@@ -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);
diff --git a/gen.c b/gen.c
index 39b59a5..14bd254 100644
--- a/gen.c
+++ b/gen.c
@@ -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; \\");
diff --git a/main.c b/main.c
index 15f98b7..7ec512f 100644
--- a/main.c
+++ b/main.c
@@ -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"
diff --git a/options.c b/options.c
index a6322c1..f9515ea 100644
--- a/options.c
+++ b/options.c
@@ -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 */
diff --git a/options.h b/options.h
index b4fe066..51b13e5 100644
--- a/options.h
+++ b/options.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,
diff --git a/scan.l b/scan.l
index 43dd669..f297846 100644
--- a/scan.l
+++ b/scan.l
@@ -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 );
diff --git a/tables.c b/tables.c
index a19bcfe..71dd02a 100644
--- a/tables.c
+++ b/tables.c
@@ -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 */