1*7e382390SJung-uk Kim /* tables.c - tables serialization code
2*7e382390SJung-uk Kim *
3*7e382390SJung-uk Kim * Copyright (c) 1990 The Regents of the University of California.
4*7e382390SJung-uk Kim * All rights reserved.
5*7e382390SJung-uk Kim *
6*7e382390SJung-uk Kim * This code is derived from software contributed to Berkeley by
7*7e382390SJung-uk Kim * Vern Paxson.
8*7e382390SJung-uk Kim *
9*7e382390SJung-uk Kim * The United States Government has rights in this work pursuant
10*7e382390SJung-uk Kim * to contract no. DE-AC03-76SF00098 between the United States
11*7e382390SJung-uk Kim * Department of Energy and the University of California.
12*7e382390SJung-uk Kim *
13*7e382390SJung-uk Kim * This file is part of flex.
14*7e382390SJung-uk Kim *
15*7e382390SJung-uk Kim * Redistribution and use in source and binary forms, with or without
16*7e382390SJung-uk Kim * modification, are permitted provided that the following conditions
17*7e382390SJung-uk Kim * are met:
18*7e382390SJung-uk Kim *
19*7e382390SJung-uk Kim * 1. Redistributions of source code must retain the above copyright
20*7e382390SJung-uk Kim * notice, this list of conditions and the following disclaimer.
21*7e382390SJung-uk Kim * 2. Redistributions in binary form must reproduce the above copyright
22*7e382390SJung-uk Kim * notice, this list of conditions and the following disclaimer in the
23*7e382390SJung-uk Kim * documentation and/or other materials provided with the distribution.
24*7e382390SJung-uk Kim *
25*7e382390SJung-uk Kim * Neither the name of the University nor the names of its contributors
26*7e382390SJung-uk Kim * may be used to endorse or promote products derived from this software
27*7e382390SJung-uk Kim * without specific prior written permission.
28*7e382390SJung-uk Kim *
29*7e382390SJung-uk Kim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30*7e382390SJung-uk Kim * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31*7e382390SJung-uk Kim * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32*7e382390SJung-uk Kim * PURPOSE.
33*7e382390SJung-uk Kim */
34*7e382390SJung-uk Kim
35*7e382390SJung-uk Kim
36*7e382390SJung-uk Kim #include "flexdef.h"
37*7e382390SJung-uk Kim #include "tables.h"
38*7e382390SJung-uk Kim
39*7e382390SJung-uk Kim /** Convert size_t to t_flag.
40*7e382390SJung-uk Kim * @param n in {1,2,4}
41*7e382390SJung-uk Kim * @return YYTD_DATA*.
42*7e382390SJung-uk Kim */
43*7e382390SJung-uk Kim #define BYTES2TFLAG(n)\
44*7e382390SJung-uk Kim (((n) == sizeof(flex_int8_t))\
45*7e382390SJung-uk Kim ? YYTD_DATA8\
46*7e382390SJung-uk Kim :(((n)== sizeof(flex_int16_t))\
47*7e382390SJung-uk Kim ? YYTD_DATA16\
48*7e382390SJung-uk Kim : YYTD_DATA32))
49*7e382390SJung-uk Kim
50*7e382390SJung-uk Kim /** Clear YYTD_DATA* bit flags
51*7e382390SJung-uk Kim * @return the flag with the YYTD_DATA* bits cleared
52*7e382390SJung-uk Kim */
53*7e382390SJung-uk Kim #define TFLAGS_CLRDATA(flg) ((flg) & ~(YYTD_DATA8 | YYTD_DATA16 | YYTD_DATA32))
54*7e382390SJung-uk Kim
55*7e382390SJung-uk Kim int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v);
56*7e382390SJung-uk Kim int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v);
57*7e382390SJung-uk Kim int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v);
58*7e382390SJung-uk Kim int yytbl_writen (struct yytbl_writer *wr, void *v, int len);
59*7e382390SJung-uk Kim static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i);
60*7e382390SJung-uk Kim /* XXX Not used
61*7e382390SJung-uk Kim static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
62*7e382390SJung-uk Kim int j, int k);
63*7e382390SJung-uk Kim */
64*7e382390SJung-uk Kim
65*7e382390SJung-uk Kim
66*7e382390SJung-uk Kim /** Initialize the table writer.
67*7e382390SJung-uk Kim * @param wr an uninitialized writer
68*7e382390SJung-uk Kim * @param out the output file
69*7e382390SJung-uk Kim * @return 0 on success
70*7e382390SJung-uk Kim */
yytbl_writer_init(struct yytbl_writer * wr,FILE * out)71*7e382390SJung-uk Kim int yytbl_writer_init (struct yytbl_writer *wr, FILE * out)
72*7e382390SJung-uk Kim {
73*7e382390SJung-uk Kim wr->out = out;
74*7e382390SJung-uk Kim wr->total_written = 0;
75*7e382390SJung-uk Kim return 0;
76*7e382390SJung-uk Kim }
77*7e382390SJung-uk Kim
78*7e382390SJung-uk Kim /** Initialize a table header.
79*7e382390SJung-uk Kim * @param th The uninitialized structure
80*7e382390SJung-uk Kim * @param version_str the version string
81*7e382390SJung-uk Kim * @param name the name of this table set
82*7e382390SJung-uk Kim */
yytbl_hdr_init(struct yytbl_hdr * th,const char * version_str,const char * name)83*7e382390SJung-uk Kim int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str,
84*7e382390SJung-uk Kim const char *name)
85*7e382390SJung-uk Kim {
86*7e382390SJung-uk Kim memset (th, 0, sizeof (struct yytbl_hdr));
87*7e382390SJung-uk Kim
88*7e382390SJung-uk Kim th->th_magic = YYTBL_MAGIC;
89*7e382390SJung-uk Kim th->th_hsize = (flex_uint32_t) (14 + strlen (version_str) + 1 + strlen (name) + 1);
90*7e382390SJung-uk Kim th->th_hsize += yypad64 (th->th_hsize);
91*7e382390SJung-uk Kim th->th_ssize = 0; // Not known at this point.
92*7e382390SJung-uk Kim th->th_flags = 0;
93*7e382390SJung-uk Kim th->th_version = xstrdup(version_str);
94*7e382390SJung-uk Kim th->th_name = xstrdup(name);
95*7e382390SJung-uk Kim return 0;
96*7e382390SJung-uk Kim }
97*7e382390SJung-uk Kim
98*7e382390SJung-uk Kim /** Allocate and initialize a table data structure.
99*7e382390SJung-uk Kim * @param td a pointer to an uninitialized table
100*7e382390SJung-uk Kim * @param id the table identifier
101*7e382390SJung-uk Kim * @return 0 on success
102*7e382390SJung-uk Kim */
yytbl_data_init(struct yytbl_data * td,enum yytbl_id id)103*7e382390SJung-uk Kim int yytbl_data_init (struct yytbl_data *td, enum yytbl_id id)
104*7e382390SJung-uk Kim {
105*7e382390SJung-uk Kim
106*7e382390SJung-uk Kim memset (td, 0, sizeof (struct yytbl_data));
107*7e382390SJung-uk Kim td->td_id = id;
108*7e382390SJung-uk Kim td->td_flags = YYTD_DATA32;
109*7e382390SJung-uk Kim return 0;
110*7e382390SJung-uk Kim }
111*7e382390SJung-uk Kim
112*7e382390SJung-uk Kim /** Clean up table and data array.
113*7e382390SJung-uk Kim * @param td will be destroyed
114*7e382390SJung-uk Kim * @return 0 on success
115*7e382390SJung-uk Kim */
yytbl_data_destroy(struct yytbl_data * td)116*7e382390SJung-uk Kim int yytbl_data_destroy (struct yytbl_data *td)
117*7e382390SJung-uk Kim {
118*7e382390SJung-uk Kim free(td->td_data);
119*7e382390SJung-uk Kim td->td_data = 0;
120*7e382390SJung-uk Kim free (td);
121*7e382390SJung-uk Kim return 0;
122*7e382390SJung-uk Kim }
123*7e382390SJung-uk Kim
124*7e382390SJung-uk Kim /** Write enough padding to bring the file pointer to a 64-bit boundary. */
yytbl_write_pad64(struct yytbl_writer * wr)125*7e382390SJung-uk Kim static int yytbl_write_pad64 (struct yytbl_writer *wr)
126*7e382390SJung-uk Kim {
127*7e382390SJung-uk Kim int pad, bwritten = 0;
128*7e382390SJung-uk Kim
129*7e382390SJung-uk Kim pad = yypad64 (wr->total_written);
130*7e382390SJung-uk Kim while (pad-- > 0)
131*7e382390SJung-uk Kim if (yytbl_write8 (wr, 0) < 0)
132*7e382390SJung-uk Kim return -1;
133*7e382390SJung-uk Kim else
134*7e382390SJung-uk Kim bwritten++;
135*7e382390SJung-uk Kim return bwritten;
136*7e382390SJung-uk Kim }
137*7e382390SJung-uk Kim
138*7e382390SJung-uk Kim /** write the header.
139*7e382390SJung-uk Kim * @param wr the output stream
140*7e382390SJung-uk Kim * @param th table header to be written
141*7e382390SJung-uk Kim * @return -1 on error, or bytes written on success.
142*7e382390SJung-uk Kim */
yytbl_hdr_fwrite(struct yytbl_writer * wr,const struct yytbl_hdr * th)143*7e382390SJung-uk Kim int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th)
144*7e382390SJung-uk Kim {
145*7e382390SJung-uk Kim int sz, rv;
146*7e382390SJung-uk Kim int bwritten = 0;
147*7e382390SJung-uk Kim
148*7e382390SJung-uk Kim if (yytbl_write32 (wr, th->th_magic) < 0
149*7e382390SJung-uk Kim || yytbl_write32 (wr, th->th_hsize) < 0)
150*7e382390SJung-uk Kim flex_die (_("th_magic|th_hsize write32 failed"));
151*7e382390SJung-uk Kim bwritten += 8;
152*7e382390SJung-uk Kim
153*7e382390SJung-uk Kim if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0)
154*7e382390SJung-uk Kim flex_die (_("fgetpos failed"));
155*7e382390SJung-uk Kim
156*7e382390SJung-uk Kim if (yytbl_write32 (wr, th->th_ssize) < 0
157*7e382390SJung-uk Kim || yytbl_write16 (wr, th->th_flags) < 0)
158*7e382390SJung-uk Kim flex_die (_("th_ssize|th_flags write failed"));
159*7e382390SJung-uk Kim bwritten += 6;
160*7e382390SJung-uk Kim
161*7e382390SJung-uk Kim sz = (int) strlen (th->th_version) + 1;
162*7e382390SJung-uk Kim if ((rv = yytbl_writen (wr, th->th_version, sz)) != sz)
163*7e382390SJung-uk Kim flex_die (_("th_version writen failed"));
164*7e382390SJung-uk Kim bwritten += rv;
165*7e382390SJung-uk Kim
166*7e382390SJung-uk Kim sz = (int) strlen (th->th_name) + 1;
167*7e382390SJung-uk Kim if ((rv = yytbl_writen (wr, th->th_name, sz)) != sz)
168*7e382390SJung-uk Kim flex_die (_("th_name writen failed"));
169*7e382390SJung-uk Kim bwritten += rv;
170*7e382390SJung-uk Kim
171*7e382390SJung-uk Kim /* add padding */
172*7e382390SJung-uk Kim if ((rv = yytbl_write_pad64 (wr)) < 0)
173*7e382390SJung-uk Kim flex_die (_("pad64 failed"));
174*7e382390SJung-uk Kim bwritten += rv;
175*7e382390SJung-uk Kim
176*7e382390SJung-uk Kim /* Sanity check */
177*7e382390SJung-uk Kim if (bwritten != (int) th->th_hsize)
178*7e382390SJung-uk Kim flex_die (_("pad64 failed"));
179*7e382390SJung-uk Kim
180*7e382390SJung-uk Kim return bwritten;
181*7e382390SJung-uk Kim }
182*7e382390SJung-uk Kim
183*7e382390SJung-uk Kim
184*7e382390SJung-uk Kim /** Write this table.
185*7e382390SJung-uk Kim * @param wr the file writer
186*7e382390SJung-uk Kim * @param td table data to be written
187*7e382390SJung-uk Kim * @return -1 on error, or bytes written on success.
188*7e382390SJung-uk Kim */
yytbl_data_fwrite(struct yytbl_writer * wr,struct yytbl_data * td)189*7e382390SJung-uk Kim int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td)
190*7e382390SJung-uk Kim {
191*7e382390SJung-uk Kim int rv;
192*7e382390SJung-uk Kim flex_int32_t bwritten = 0;
193*7e382390SJung-uk Kim flex_int32_t i, total_len;
194*7e382390SJung-uk Kim fpos_t pos;
195*7e382390SJung-uk Kim
196*7e382390SJung-uk Kim if ((rv = yytbl_write16 (wr, td->td_id)) < 0)
197*7e382390SJung-uk Kim return -1;
198*7e382390SJung-uk Kim bwritten += rv;
199*7e382390SJung-uk Kim
200*7e382390SJung-uk Kim if ((rv = yytbl_write16 (wr, td->td_flags)) < 0)
201*7e382390SJung-uk Kim return -1;
202*7e382390SJung-uk Kim bwritten += rv;
203*7e382390SJung-uk Kim
204*7e382390SJung-uk Kim if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0)
205*7e382390SJung-uk Kim return -1;
206*7e382390SJung-uk Kim bwritten += rv;
207*7e382390SJung-uk Kim
208*7e382390SJung-uk Kim if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0)
209*7e382390SJung-uk Kim return -1;
210*7e382390SJung-uk Kim bwritten += rv;
211*7e382390SJung-uk Kim
212*7e382390SJung-uk Kim total_len = yytbl_calc_total_len (td);
213*7e382390SJung-uk Kim for (i = 0; i < total_len; i++) {
214*7e382390SJung-uk Kim switch (YYTDFLAGS2BYTES (td->td_flags)) {
215*7e382390SJung-uk Kim case sizeof (flex_int8_t):
216*7e382390SJung-uk Kim rv = yytbl_write8 (wr, (flex_uint8_t) yytbl_data_geti (td, i));
217*7e382390SJung-uk Kim break;
218*7e382390SJung-uk Kim case sizeof (flex_int16_t):
219*7e382390SJung-uk Kim rv = yytbl_write16 (wr, (flex_uint16_t) yytbl_data_geti (td, i));
220*7e382390SJung-uk Kim break;
221*7e382390SJung-uk Kim case sizeof (flex_int32_t):
222*7e382390SJung-uk Kim rv = yytbl_write32 (wr, (flex_uint32_t) yytbl_data_geti (td, i));
223*7e382390SJung-uk Kim break;
224*7e382390SJung-uk Kim default:
225*7e382390SJung-uk Kim flex_die (_("invalid td_flags detected"));
226*7e382390SJung-uk Kim }
227*7e382390SJung-uk Kim if (rv < 0) {
228*7e382390SJung-uk Kim flex_die (_("error while writing tables"));
229*7e382390SJung-uk Kim return -1;
230*7e382390SJung-uk Kim }
231*7e382390SJung-uk Kim bwritten += rv;
232*7e382390SJung-uk Kim }
233*7e382390SJung-uk Kim
234*7e382390SJung-uk Kim /* Sanity check */
235*7e382390SJung-uk Kim if (bwritten != (12 + total_len * (int) YYTDFLAGS2BYTES (td->td_flags))) {
236*7e382390SJung-uk Kim flex_die (_("insanity detected"));
237*7e382390SJung-uk Kim return -1;
238*7e382390SJung-uk Kim }
239*7e382390SJung-uk Kim
240*7e382390SJung-uk Kim /* add padding */
241*7e382390SJung-uk Kim if ((rv = yytbl_write_pad64 (wr)) < 0) {
242*7e382390SJung-uk Kim flex_die (_("pad64 failed"));
243*7e382390SJung-uk Kim return -1;
244*7e382390SJung-uk Kim }
245*7e382390SJung-uk Kim bwritten += rv;
246*7e382390SJung-uk Kim
247*7e382390SJung-uk Kim /* Now go back and update the th_hsize member */
248*7e382390SJung-uk Kim if (fgetpos (wr->out, &pos) != 0
249*7e382390SJung-uk Kim || fsetpos (wr->out, &(wr->th_ssize_pos)) != 0
250*7e382390SJung-uk Kim || yytbl_write32 (wr, (flex_uint32_t) wr->total_written) < 0
251*7e382390SJung-uk Kim || fsetpos (wr->out, &pos)) {
252*7e382390SJung-uk Kim flex_die (_("get|set|fwrite32 failed"));
253*7e382390SJung-uk Kim return -1;
254*7e382390SJung-uk Kim }
255*7e382390SJung-uk Kim else
256*7e382390SJung-uk Kim /* Don't count the int we just wrote. */
257*7e382390SJung-uk Kim wr->total_written -= (int) sizeof (flex_int32_t);
258*7e382390SJung-uk Kim return bwritten;
259*7e382390SJung-uk Kim }
260*7e382390SJung-uk Kim
261*7e382390SJung-uk Kim /** Write n bytes.
262*7e382390SJung-uk Kim * @param wr the table writer
263*7e382390SJung-uk Kim * @param v data to be written
264*7e382390SJung-uk Kim * @param len number of bytes
265*7e382390SJung-uk Kim * @return -1 on error. number of bytes written on success.
266*7e382390SJung-uk Kim */
yytbl_writen(struct yytbl_writer * wr,void * v,int len)267*7e382390SJung-uk Kim int yytbl_writen (struct yytbl_writer *wr, void *v, int len)
268*7e382390SJung-uk Kim {
269*7e382390SJung-uk Kim int rv;
270*7e382390SJung-uk Kim
271*7e382390SJung-uk Kim rv = (int) fwrite (v, 1, (size_t) len, wr->out);
272*7e382390SJung-uk Kim if (rv != len)
273*7e382390SJung-uk Kim return -1;
274*7e382390SJung-uk Kim wr->total_written += len;
275*7e382390SJung-uk Kim return len;
276*7e382390SJung-uk Kim }
277*7e382390SJung-uk Kim
278*7e382390SJung-uk Kim /** Write four bytes in network byte order
279*7e382390SJung-uk Kim * @param wr the table writer
280*7e382390SJung-uk Kim * @param v a dword in host byte order
281*7e382390SJung-uk Kim * @return -1 on error. number of bytes written on success.
282*7e382390SJung-uk Kim */
yytbl_write32(struct yytbl_writer * wr,flex_uint32_t v)283*7e382390SJung-uk Kim int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v)
284*7e382390SJung-uk Kim {
285*7e382390SJung-uk Kim flex_uint32_t vnet;
286*7e382390SJung-uk Kim int bytes, rv;
287*7e382390SJung-uk Kim
288*7e382390SJung-uk Kim vnet = htonl (v);
289*7e382390SJung-uk Kim bytes = (int) sizeof (flex_uint32_t);
290*7e382390SJung-uk Kim rv = (int) fwrite (&vnet, (size_t) bytes, 1, wr->out);
291*7e382390SJung-uk Kim if (rv != 1)
292*7e382390SJung-uk Kim return -1;
293*7e382390SJung-uk Kim wr->total_written += bytes;
294*7e382390SJung-uk Kim return bytes;
295*7e382390SJung-uk Kim }
296*7e382390SJung-uk Kim
297*7e382390SJung-uk Kim /** Write two bytes in network byte order.
298*7e382390SJung-uk Kim * @param wr the table writer
299*7e382390SJung-uk Kim * @param v a word in host byte order
300*7e382390SJung-uk Kim * @return -1 on error. number of bytes written on success.
301*7e382390SJung-uk Kim */
yytbl_write16(struct yytbl_writer * wr,flex_uint16_t v)302*7e382390SJung-uk Kim int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v)
303*7e382390SJung-uk Kim {
304*7e382390SJung-uk Kim flex_uint16_t vnet;
305*7e382390SJung-uk Kim int bytes, rv;
306*7e382390SJung-uk Kim
307*7e382390SJung-uk Kim vnet = htons (v);
308*7e382390SJung-uk Kim bytes = (int) sizeof (flex_uint16_t);
309*7e382390SJung-uk Kim rv = (int) fwrite (&vnet, (size_t) bytes, 1, wr->out);
310*7e382390SJung-uk Kim if (rv != 1)
311*7e382390SJung-uk Kim return -1;
312*7e382390SJung-uk Kim wr->total_written += bytes;
313*7e382390SJung-uk Kim return bytes;
314*7e382390SJung-uk Kim }
315*7e382390SJung-uk Kim
316*7e382390SJung-uk Kim /** Write a byte.
317*7e382390SJung-uk Kim * @param wr the table writer
318*7e382390SJung-uk Kim * @param v the value to be written
319*7e382390SJung-uk Kim * @return -1 on error. number of bytes written on success.
320*7e382390SJung-uk Kim */
yytbl_write8(struct yytbl_writer * wr,flex_uint8_t v)321*7e382390SJung-uk Kim int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v)
322*7e382390SJung-uk Kim {
323*7e382390SJung-uk Kim int bytes, rv;
324*7e382390SJung-uk Kim
325*7e382390SJung-uk Kim bytes = (int) sizeof (flex_uint8_t);
326*7e382390SJung-uk Kim rv = (int) fwrite (&v, (size_t) bytes, 1, wr->out);
327*7e382390SJung-uk Kim if (rv != 1)
328*7e382390SJung-uk Kim return -1;
329*7e382390SJung-uk Kim wr->total_written += bytes;
330*7e382390SJung-uk Kim return bytes;
331*7e382390SJung-uk Kim }
332*7e382390SJung-uk Kim
333*7e382390SJung-uk Kim
334*7e382390SJung-uk Kim /* XXX Not Used */
335*7e382390SJung-uk Kim #if 0
336*7e382390SJung-uk Kim /** Extract data element [i][j] from array data tables.
337*7e382390SJung-uk Kim * @param tbl data table
338*7e382390SJung-uk Kim * @param i index into higher dimension array. i should be zero for one-dimensional arrays.
339*7e382390SJung-uk Kim * @param j index into lower dimension array.
340*7e382390SJung-uk Kim * @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table
341*7e382390SJung-uk Kim * @return data[i][j + k]
342*7e382390SJung-uk Kim */
343*7e382390SJung-uk Kim static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
344*7e382390SJung-uk Kim int j, int k)
345*7e382390SJung-uk Kim {
346*7e382390SJung-uk Kim flex_int32_t lo;
347*7e382390SJung-uk Kim
348*7e382390SJung-uk Kim k %= 2;
349*7e382390SJung-uk Kim lo = tbl->td_lolen;
350*7e382390SJung-uk Kim
351*7e382390SJung-uk Kim switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
352*7e382390SJung-uk Kim case sizeof (flex_int8_t):
353*7e382390SJung-uk Kim return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) +
354*7e382390SJung-uk Kim k];
355*7e382390SJung-uk Kim case sizeof (flex_int16_t):
356*7e382390SJung-uk Kim return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k +
357*7e382390SJung-uk Kim 1) +
358*7e382390SJung-uk Kim k];
359*7e382390SJung-uk Kim case sizeof (flex_int32_t):
360*7e382390SJung-uk Kim return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k +
361*7e382390SJung-uk Kim 1) +
362*7e382390SJung-uk Kim k];
363*7e382390SJung-uk Kim default:
364*7e382390SJung-uk Kim flex_die (_("invalid td_flags detected"));
365*7e382390SJung-uk Kim break;
366*7e382390SJung-uk Kim }
367*7e382390SJung-uk Kim
368*7e382390SJung-uk Kim return 0;
369*7e382390SJung-uk Kim }
370*7e382390SJung-uk Kim #endif /* Not used */
371*7e382390SJung-uk Kim
372*7e382390SJung-uk Kim /** Extract data element [i] from array data tables treated as a single flat array of integers.
373*7e382390SJung-uk Kim * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
374*7e382390SJung-uk Kim * of structs.
375*7e382390SJung-uk Kim * @param tbl data table
376*7e382390SJung-uk Kim * @param i index into array.
377*7e382390SJung-uk Kim * @return data[i]
378*7e382390SJung-uk Kim */
yytbl_data_geti(const struct yytbl_data * tbl,int i)379*7e382390SJung-uk Kim static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i)
380*7e382390SJung-uk Kim {
381*7e382390SJung-uk Kim
382*7e382390SJung-uk Kim switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
383*7e382390SJung-uk Kim case sizeof (flex_int8_t):
384*7e382390SJung-uk Kim return ((flex_int8_t *) (tbl->td_data))[i];
385*7e382390SJung-uk Kim case sizeof (flex_int16_t):
386*7e382390SJung-uk Kim return ((flex_int16_t *) (tbl->td_data))[i];
387*7e382390SJung-uk Kim case sizeof (flex_int32_t):
388*7e382390SJung-uk Kim return ((flex_int32_t *) (tbl->td_data))[i];
389*7e382390SJung-uk Kim default:
390*7e382390SJung-uk Kim flex_die (_("invalid td_flags detected"));
391*7e382390SJung-uk Kim break;
392*7e382390SJung-uk Kim }
393*7e382390SJung-uk Kim return 0;
394*7e382390SJung-uk Kim }
395*7e382390SJung-uk Kim
396*7e382390SJung-uk Kim /** Set data element [i] in array data tables treated as a single flat array of integers.
397*7e382390SJung-uk Kim * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
398*7e382390SJung-uk Kim * of structs.
399*7e382390SJung-uk Kim * @param tbl data table
400*7e382390SJung-uk Kim * @param i index into array.
401*7e382390SJung-uk Kim * @param newval new value for data[i]
402*7e382390SJung-uk Kim */
yytbl_data_seti(const struct yytbl_data * tbl,int i,flex_int32_t newval)403*7e382390SJung-uk Kim static void yytbl_data_seti (const struct yytbl_data *tbl, int i,
404*7e382390SJung-uk Kim flex_int32_t newval)
405*7e382390SJung-uk Kim {
406*7e382390SJung-uk Kim
407*7e382390SJung-uk Kim switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
408*7e382390SJung-uk Kim case sizeof (flex_int8_t):
409*7e382390SJung-uk Kim ((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval;
410*7e382390SJung-uk Kim break;
411*7e382390SJung-uk Kim case sizeof (flex_int16_t):
412*7e382390SJung-uk Kim ((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval;
413*7e382390SJung-uk Kim break;
414*7e382390SJung-uk Kim case sizeof (flex_int32_t):
415*7e382390SJung-uk Kim ((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval;
416*7e382390SJung-uk Kim break;
417*7e382390SJung-uk Kim default:
418*7e382390SJung-uk Kim flex_die (_("invalid td_flags detected"));
419*7e382390SJung-uk Kim break;
420*7e382390SJung-uk Kim }
421*7e382390SJung-uk Kim }
422*7e382390SJung-uk Kim
423*7e382390SJung-uk Kim /** Calculate the number of bytes needed to hold the largest
424*7e382390SJung-uk Kim * absolute value in this data array.
425*7e382390SJung-uk Kim * @param tbl the data table
426*7e382390SJung-uk Kim * @return sizeof(n) where n in {flex_int8_t, flex_int16_t, flex_int32_t}
427*7e382390SJung-uk Kim */
min_int_size(struct yytbl_data * tbl)428*7e382390SJung-uk Kim static size_t min_int_size (struct yytbl_data *tbl)
429*7e382390SJung-uk Kim {
430*7e382390SJung-uk Kim flex_int32_t i, total_len;
431*7e382390SJung-uk Kim flex_int32_t max = 0;
432*7e382390SJung-uk Kim
433*7e382390SJung-uk Kim total_len = yytbl_calc_total_len (tbl);
434*7e382390SJung-uk Kim
435*7e382390SJung-uk Kim for (i = 0; i < total_len; i++) {
436*7e382390SJung-uk Kim flex_int32_t n;
437*7e382390SJung-uk Kim
438*7e382390SJung-uk Kim n = abs (yytbl_data_geti (tbl, i));
439*7e382390SJung-uk Kim
440*7e382390SJung-uk Kim if (max < n)
441*7e382390SJung-uk Kim max = n;
442*7e382390SJung-uk Kim }
443*7e382390SJung-uk Kim
444*7e382390SJung-uk Kim if (max <= INT8_MAX)
445*7e382390SJung-uk Kim return sizeof (flex_int8_t);
446*7e382390SJung-uk Kim else if (max <= INT16_MAX)
447*7e382390SJung-uk Kim return sizeof (flex_int16_t);
448*7e382390SJung-uk Kim else
449*7e382390SJung-uk Kim return sizeof (flex_int32_t);
450*7e382390SJung-uk Kim }
451*7e382390SJung-uk Kim
452*7e382390SJung-uk Kim /** Transform data to smallest possible of (int32, int16, int8).
453*7e382390SJung-uk Kim * For example, we may have generated an int32 array due to user options
454*7e382390SJung-uk Kim * (e.g., %option align), but if the maximum value in that array
455*7e382390SJung-uk Kim * is 80 (for example), then we can serialize it with only 1 byte per int.
456*7e382390SJung-uk Kim * This is NOT the same as compressed DFA tables. We're just trying
457*7e382390SJung-uk Kim * to save storage space here.
458*7e382390SJung-uk Kim *
459*7e382390SJung-uk Kim * @param tbl the table to be compressed
460*7e382390SJung-uk Kim */
yytbl_data_compress(struct yytbl_data * tbl)461*7e382390SJung-uk Kim void yytbl_data_compress (struct yytbl_data *tbl)
462*7e382390SJung-uk Kim {
463*7e382390SJung-uk Kim flex_int32_t i, total_len;
464*7e382390SJung-uk Kim size_t newsz;
465*7e382390SJung-uk Kim struct yytbl_data newtbl;
466*7e382390SJung-uk Kim
467*7e382390SJung-uk Kim yytbl_data_init (&newtbl, tbl->td_id);
468*7e382390SJung-uk Kim newtbl.td_hilen = tbl->td_hilen;
469*7e382390SJung-uk Kim newtbl.td_lolen = tbl->td_lolen;
470*7e382390SJung-uk Kim newtbl.td_flags = tbl->td_flags;
471*7e382390SJung-uk Kim
472*7e382390SJung-uk Kim newsz = min_int_size (tbl);
473*7e382390SJung-uk Kim
474*7e382390SJung-uk Kim
475*7e382390SJung-uk Kim if (newsz == YYTDFLAGS2BYTES (tbl->td_flags))
476*7e382390SJung-uk Kim /* No change in this table needed. */
477*7e382390SJung-uk Kim return;
478*7e382390SJung-uk Kim
479*7e382390SJung-uk Kim if (newsz > YYTDFLAGS2BYTES (tbl->td_flags)) {
480*7e382390SJung-uk Kim flex_die (_("detected negative compression"));
481*7e382390SJung-uk Kim return;
482*7e382390SJung-uk Kim }
483*7e382390SJung-uk Kim
484*7e382390SJung-uk Kim total_len = yytbl_calc_total_len (tbl);
485*7e382390SJung-uk Kim newtbl.td_data = calloc ((size_t) total_len, newsz);
486*7e382390SJung-uk Kim newtbl.td_flags = (flex_uint16_t)
487*7e382390SJung-uk Kim (TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz));
488*7e382390SJung-uk Kim
489*7e382390SJung-uk Kim for (i = 0; i < total_len; i++) {
490*7e382390SJung-uk Kim flex_int32_t g;
491*7e382390SJung-uk Kim
492*7e382390SJung-uk Kim g = yytbl_data_geti (tbl, i);
493*7e382390SJung-uk Kim yytbl_data_seti (&newtbl, i, g);
494*7e382390SJung-uk Kim }
495*7e382390SJung-uk Kim
496*7e382390SJung-uk Kim
497*7e382390SJung-uk Kim /* Now copy over the old table */
498*7e382390SJung-uk Kim free (tbl->td_data);
499*7e382390SJung-uk Kim *tbl = newtbl;
500*7e382390SJung-uk Kim }
501*7e382390SJung-uk Kim
502*7e382390SJung-uk Kim /* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */
503