/** Extract data element [i][j] from array data tables. * @param tbl data table * @param i index into higher dimension array. i should be zero for one-dimensional arrays. * @param j index into lower dimension array. * @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table * @return data[i][j + k] */ static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i, int j, int k) { flex_int32_t lo; k %= 2; lo = tbl->td_lolen; switch (YYTDFLAGS2BYTES (tbl->td_flags)) { case sizeof (flex_int8_t): return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) + k]; case sizeof (flex_int16_t): return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k + 1) + k]; case sizeof (flex_int32_t): return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k + 1) + k]; default: flex_die (_("invalid td_flags detected")); break; } return 0; }
/** Transform data to smallest possible of (int32, int16, int8). * For example, we may have generated an int32 array due to user options * (e.g., %option align), but if the maximum value in that array * is 80 (for example), then we can serialize it with only 1 byte per int. * This is NOT the same as compressed DFA tables. We're just trying * to save storage space here. * * @param tbl the table to be compressed */ void yytbl_data_compress (struct yytbl_data *tbl) { flex_int32_t i, total_len; size_t newsz; struct yytbl_data newtbl; yytbl_data_init (&newtbl, tbl->td_id); newtbl.td_hilen = tbl->td_hilen; newtbl.td_lolen = tbl->td_lolen; newtbl.td_flags = tbl->td_flags; newsz = min_int_size (tbl); if (newsz == YYTDFLAGS2BYTES (tbl->td_flags)) /* No change in this table needed. */ return; if (newsz > YYTDFLAGS2BYTES (tbl->td_flags)) { flex_die (_("detected negative compression")); return; } total_len = yytbl_calc_total_len (tbl); newtbl.td_data = calloc ((size_t) total_len, newsz); newtbl.td_flags = (flex_uint16_t) (TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz)); for (i = 0; i < total_len; i++) { flex_int32_t g; g = yytbl_data_geti (tbl, i); yytbl_data_seti (&newtbl, i, g); } /* Now copy over the old table */ free (tbl->td_data); *tbl = newtbl; }
/** Extract data element [i] from array data tables treated as a single flat array of integers. * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array * of structs. * @param tbl data table * @param i index into array. * @return data[i] */ static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i) { switch (YYTDFLAGS2BYTES (tbl->td_flags)) { case sizeof (flex_int8_t): return ((flex_int8_t *) (tbl->td_data))[i]; case sizeof (flex_int16_t): return ((flex_int16_t *) (tbl->td_data))[i]; case sizeof (flex_int32_t): return ((flex_int32_t *) (tbl->td_data))[i]; default: flex_die (_("invalid td_flags detected")); break; } return 0; }
/** Set data element [i] in array data tables treated as a single flat array of integers. * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array * of structs. * @param tbl data table * @param i index into array. * @param newval new value for data[i] */ static void yytbl_data_seti (const struct yytbl_data *tbl, int i, flex_int32_t newval) { switch (YYTDFLAGS2BYTES (tbl->td_flags)) { case sizeof (flex_int8_t): ((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval; break; case sizeof (flex_int16_t): ((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval; break; case sizeof (flex_int32_t): ((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval; break; default: flex_die (_("invalid td_flags detected")); break; } }
/** 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) { int rv; flex_int32_t bwritten = 0; flex_int32_t i, total_len; fpos_t pos; if ((rv = yytbl_write16 (wr, td->td_id)) < 0) return -1; bwritten += rv; if ((rv = yytbl_write16 (wr, td->td_flags)) < 0) return -1; bwritten += rv; if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0) return -1; bwritten += rv; if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0) return -1; bwritten += rv; total_len = yytbl_calc_total_len (td); for (i = 0; i < total_len; i++) { switch (YYTDFLAGS2BYTES (td->td_flags)) { case sizeof (flex_int8_t): rv = yytbl_write8 (wr, yytbl_data_geti (td, i)); break; case sizeof (flex_int16_t): rv = yytbl_write16 (wr, yytbl_data_geti (td, i)); break; case sizeof (flex_int32_t): rv = yytbl_write32 (wr, yytbl_data_geti (td, i)); break; default: flex_die (_("invalid td_flags detected")); } if (rv < 0) { flex_die (_("error while writing tables")); return -1; } bwritten += rv; } /* Sanity check */ if (bwritten != (int) (12 + total_len * YYTDFLAGS2BYTES (td->td_flags))) { flex_die (_("insanity detected")); return -1; } /* add padding */ if ((rv = yytbl_write_pad64 (wr)) < 0) { flex_die (_("pad64 failed")); 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_write32 (wr, wr->total_written) < 0 || fsetpos (wr->out, &pos)) { flex_die (_("get|set|fwrite32 failed")); return -1; } else /* Don't count the int we just wrote. */ wr->total_written -= sizeof (flex_int32_t); return bwritten; }