xref: /minix3/external/bsd/flex/dist/tables.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: tables.c,v 1.5 2014/10/30 18:44:05 christos Exp $	*/
2357f1050SThomas Veerman 
3357f1050SThomas Veerman /*  tables.c - tables serialization code
4357f1050SThomas Veerman  *
5357f1050SThomas Veerman  *  Copyright (c) 1990 The Regents of the University of California.
6357f1050SThomas Veerman  *  All rights reserved.
7357f1050SThomas Veerman  *
8357f1050SThomas Veerman  *  This code is derived from software contributed to Berkeley by
9357f1050SThomas Veerman  *  Vern Paxson.
10357f1050SThomas Veerman  *
11357f1050SThomas Veerman  *  The United States Government has rights in this work pursuant
12357f1050SThomas Veerman  *  to contract no. DE-AC03-76SF00098 between the United States
13357f1050SThomas Veerman  *  Department of Energy and the University of California.
14357f1050SThomas Veerman  *
15357f1050SThomas Veerman  *  This file is part of flex.
16357f1050SThomas Veerman  *
17357f1050SThomas Veerman  *  Redistribution and use in source and binary forms, with or without
18357f1050SThomas Veerman  *  modification, are permitted provided that the following conditions
19357f1050SThomas Veerman  *  are met:
20357f1050SThomas Veerman  *
21357f1050SThomas Veerman  *  1. Redistributions of source code must retain the above copyright
22357f1050SThomas Veerman  *     notice, this list of conditions and the following disclaimer.
23357f1050SThomas Veerman  *  2. Redistributions in binary form must reproduce the above copyright
24357f1050SThomas Veerman  *     notice, this list of conditions and the following disclaimer in the
25357f1050SThomas Veerman  *     documentation and/or other materials provided with the distribution.
26357f1050SThomas Veerman  *
27357f1050SThomas Veerman  *  Neither the name of the University nor the names of its contributors
28357f1050SThomas Veerman  *  may be used to endorse or promote products derived from this software
29357f1050SThomas Veerman  *  without specific prior written permission.
30357f1050SThomas Veerman  *
31357f1050SThomas Veerman  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
32357f1050SThomas Veerman  *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
33357f1050SThomas Veerman  *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34357f1050SThomas Veerman  *  PURPOSE.
35357f1050SThomas Veerman  */
36*0a6a1f1dSLionel Sambuc #include "flexdef.h"
37*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: tables.c,v 1.5 2014/10/30 18:44:05 christos Exp $");
38357f1050SThomas Veerman 
39357f1050SThomas Veerman 
40357f1050SThomas Veerman #include "tables.h"
41357f1050SThomas Veerman 
42357f1050SThomas Veerman /** Convert size_t to t_flag.
43357f1050SThomas Veerman  *  @param n in {1,2,4}
44357f1050SThomas Veerman  *  @return YYTD_DATA*.
45357f1050SThomas Veerman  */
46357f1050SThomas Veerman #define BYTES2TFLAG(n)\
47357f1050SThomas Veerman     (((n) == sizeof(flex_int8_t))\
48357f1050SThomas Veerman         ? YYTD_DATA8\
49357f1050SThomas Veerman         :(((n)== sizeof(flex_int16_t))\
50357f1050SThomas Veerman             ? YYTD_DATA16\
51357f1050SThomas Veerman             : YYTD_DATA32))
52357f1050SThomas Veerman 
53357f1050SThomas Veerman /** Clear YYTD_DATA* bit flags
54357f1050SThomas Veerman  * @return the flag with the YYTD_DATA* bits cleared
55357f1050SThomas Veerman  */
56357f1050SThomas Veerman #define TFLAGS_CLRDATA(flg) ((flg) & ~(YYTD_DATA8 | YYTD_DATA16 | YYTD_DATA32))
57357f1050SThomas Veerman 
58357f1050SThomas Veerman int     yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v);
59357f1050SThomas Veerman int     yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v);
60357f1050SThomas Veerman int     yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v);
61357f1050SThomas Veerman int     yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len);
62357f1050SThomas Veerman static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i);
6384d9c625SLionel Sambuc /* XXX Not used
64357f1050SThomas Veerman static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
65357f1050SThomas Veerman 				  int j, int k);
6684d9c625SLionel Sambuc  */
67357f1050SThomas Veerman 
68357f1050SThomas Veerman 
69357f1050SThomas Veerman /** Initialize the table writer.
70357f1050SThomas Veerman  *  @param wr an uninitialized writer
71357f1050SThomas Veerman  *  @param the output file
72357f1050SThomas Veerman  *  @return 0 on success
73357f1050SThomas Veerman  */
yytbl_writer_init(struct yytbl_writer * wr,FILE * out)74357f1050SThomas Veerman int yytbl_writer_init (struct yytbl_writer *wr, FILE * out)
75357f1050SThomas Veerman {
76357f1050SThomas Veerman 	wr->out = out;
77357f1050SThomas Veerman 	wr->total_written = 0;
78357f1050SThomas Veerman 	return 0;
79357f1050SThomas Veerman }
80357f1050SThomas Veerman 
81357f1050SThomas Veerman /** Initialize a table header.
82357f1050SThomas Veerman  *  @param th  The uninitialized structure
83357f1050SThomas Veerman  *  @param version_str the  version string
84357f1050SThomas Veerman  *  @param name the name of this table set
85357f1050SThomas Veerman  */
yytbl_hdr_init(struct yytbl_hdr * th,const char * version_str,const char * name)86357f1050SThomas Veerman int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str,
87357f1050SThomas Veerman 		    const char *name)
88357f1050SThomas Veerman {
89357f1050SThomas Veerman 	memset (th, 0, sizeof (struct yytbl_hdr));
90357f1050SThomas Veerman 
91357f1050SThomas Veerman 	th->th_magic = YYTBL_MAGIC;
92357f1050SThomas Veerman 	th->th_hsize = 14 + strlen (version_str) + 1 + strlen (name) + 1;
93357f1050SThomas Veerman 	th->th_hsize += yypad64 (th->th_hsize);
94357f1050SThomas Veerman 	th->th_ssize = 0;	// Not known at this point.
95357f1050SThomas Veerman 	th->th_flags = 0;
96357f1050SThomas Veerman 	th->th_version = copy_string (version_str);
97357f1050SThomas Veerman 	th->th_name = copy_string (name);
98357f1050SThomas Veerman 	return 0;
99357f1050SThomas Veerman }
100357f1050SThomas Veerman 
101357f1050SThomas Veerman /** Allocate and initialize a table data structure.
102357f1050SThomas Veerman  *  @param tbl a pointer to an uninitialized table
103357f1050SThomas Veerman  *  @param id  the table identifier
104357f1050SThomas Veerman  *  @return 0 on success
105357f1050SThomas Veerman  */
yytbl_data_init(struct yytbl_data * td,enum yytbl_id id)106357f1050SThomas Veerman int yytbl_data_init (struct yytbl_data *td, enum yytbl_id id)
107357f1050SThomas Veerman {
108357f1050SThomas Veerman 
109357f1050SThomas Veerman 	memset (td, 0, sizeof (struct yytbl_data));
110357f1050SThomas Veerman 	td->td_id = id;
111357f1050SThomas Veerman 	td->td_flags = YYTD_DATA32;
112357f1050SThomas Veerman 	return 0;
113357f1050SThomas Veerman }
114357f1050SThomas Veerman 
115357f1050SThomas Veerman /** Clean up table and data array.
116357f1050SThomas Veerman  *  @param td will be destroyed
117357f1050SThomas Veerman  *  @return 0 on success
118357f1050SThomas Veerman  */
yytbl_data_destroy(struct yytbl_data * td)119357f1050SThomas Veerman int yytbl_data_destroy (struct yytbl_data *td)
120357f1050SThomas Veerman {
121357f1050SThomas Veerman 	if (td->td_data)
122357f1050SThomas Veerman 		free (td->td_data);
123357f1050SThomas Veerman 	td->td_data = 0;
124357f1050SThomas Veerman 	free (td);
125357f1050SThomas Veerman 	return 0;
126357f1050SThomas Veerman }
127357f1050SThomas Veerman 
128357f1050SThomas Veerman /** Write enough padding to bring the file pointer to a 64-bit boundary. */
yytbl_write_pad64(struct yytbl_writer * wr)129357f1050SThomas Veerman static int yytbl_write_pad64 (struct yytbl_writer *wr)
130357f1050SThomas Veerman {
131357f1050SThomas Veerman 	int     pad, bwritten = 0;
132357f1050SThomas Veerman 
133357f1050SThomas Veerman 	pad = yypad64 (wr->total_written);
134357f1050SThomas Veerman 	while (pad-- > 0)
135357f1050SThomas Veerman 		if (yytbl_write8 (wr, 0) < 0)
136357f1050SThomas Veerman 			return -1;
137357f1050SThomas Veerman 		else
138357f1050SThomas Veerman 			bwritten++;
139357f1050SThomas Veerman 	return bwritten;
140357f1050SThomas Veerman }
141357f1050SThomas Veerman 
142357f1050SThomas Veerman /** write the header.
143357f1050SThomas Veerman  *  @param out the output stream
144357f1050SThomas Veerman  *  @param th table header to be written
145357f1050SThomas Veerman  *  @return -1 on error, or bytes written on success.
146357f1050SThomas Veerman  */
yytbl_hdr_fwrite(struct yytbl_writer * wr,const struct yytbl_hdr * th)147357f1050SThomas Veerman int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th)
148357f1050SThomas Veerman {
149357f1050SThomas Veerman 	int  sz, rv;
150357f1050SThomas Veerman 	int     bwritten = 0;
151357f1050SThomas Veerman 
152357f1050SThomas Veerman 	if (yytbl_write32 (wr, th->th_magic) < 0
153357f1050SThomas Veerman 	    || yytbl_write32 (wr, th->th_hsize) < 0)
154357f1050SThomas Veerman 		flex_die (_("th_magic|th_hsize write32 failed"));
155357f1050SThomas Veerman 	bwritten += 8;
156357f1050SThomas Veerman 
157357f1050SThomas Veerman 	if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0)
158357f1050SThomas Veerman 		flex_die (_("fgetpos failed"));
159357f1050SThomas Veerman 
160357f1050SThomas Veerman 	if (yytbl_write32 (wr, th->th_ssize) < 0
161357f1050SThomas Veerman 	    || yytbl_write16 (wr, th->th_flags) < 0)
162357f1050SThomas Veerman 		flex_die (_("th_ssize|th_flags write failed"));
163357f1050SThomas Veerman 	bwritten += 6;
164357f1050SThomas Veerman 
165357f1050SThomas Veerman 	sz = strlen (th->th_version) + 1;
166357f1050SThomas Veerman 	if ((rv = yytbl_writen (wr, th->th_version, sz)) != sz)
167357f1050SThomas Veerman 		flex_die (_("th_version writen failed"));
168357f1050SThomas Veerman 	bwritten += rv;
169357f1050SThomas Veerman 
170357f1050SThomas Veerman 	sz = strlen (th->th_name) + 1;
171357f1050SThomas Veerman 	if ((rv = yytbl_writen (wr, th->th_name, sz)) != sz)
172357f1050SThomas Veerman 		flex_die (_("th_name writen failed"));
173357f1050SThomas Veerman 	bwritten += rv;
174357f1050SThomas Veerman 
175357f1050SThomas Veerman 	/* add padding */
176357f1050SThomas Veerman 	if ((rv = yytbl_write_pad64 (wr)) < 0)
177357f1050SThomas Veerman 		flex_die (_("pad64 failed"));
178357f1050SThomas Veerman 	bwritten += rv;
179357f1050SThomas Veerman 
180357f1050SThomas Veerman 	/* Sanity check */
181357f1050SThomas Veerman 	if (bwritten != (int) th->th_hsize)
182357f1050SThomas Veerman 		flex_die (_("pad64 failed"));
183357f1050SThomas Veerman 
184357f1050SThomas Veerman 	return bwritten;
185357f1050SThomas Veerman }
186357f1050SThomas Veerman 
187357f1050SThomas Veerman 
188357f1050SThomas Veerman /** Write this table.
189357f1050SThomas Veerman  *  @param out the file writer
190357f1050SThomas Veerman  *  @param td table data to be written
191357f1050SThomas Veerman  *  @return -1 on error, or bytes written on success.
192357f1050SThomas Veerman  */
yytbl_data_fwrite(struct yytbl_writer * wr,struct yytbl_data * td)193357f1050SThomas Veerman int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td)
194357f1050SThomas Veerman {
195357f1050SThomas Veerman 	int  rv;
196357f1050SThomas Veerman 	flex_int32_t bwritten = 0;
197357f1050SThomas Veerman 	flex_int32_t i, total_len;
198357f1050SThomas Veerman 	fpos_t  pos;
199357f1050SThomas Veerman 
200357f1050SThomas Veerman 	if ((rv = yytbl_write16 (wr, td->td_id)) < 0)
201357f1050SThomas Veerman 		return -1;
202357f1050SThomas Veerman 	bwritten += rv;
203357f1050SThomas Veerman 
204357f1050SThomas Veerman 	if ((rv = yytbl_write16 (wr, td->td_flags)) < 0)
205357f1050SThomas Veerman 		return -1;
206357f1050SThomas Veerman 	bwritten += rv;
207357f1050SThomas Veerman 
208357f1050SThomas Veerman 	if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0)
209357f1050SThomas Veerman 		return -1;
210357f1050SThomas Veerman 	bwritten += rv;
211357f1050SThomas Veerman 
212357f1050SThomas Veerman 	if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0)
213357f1050SThomas Veerman 		return -1;
214357f1050SThomas Veerman 	bwritten += rv;
215357f1050SThomas Veerman 
216357f1050SThomas Veerman 	total_len = yytbl_calc_total_len (td);
217357f1050SThomas Veerman 	for (i = 0; i < total_len; i++) {
218357f1050SThomas Veerman 		switch (YYTDFLAGS2BYTES (td->td_flags)) {
219357f1050SThomas Veerman 		case sizeof (flex_int8_t):
220357f1050SThomas Veerman 			rv = yytbl_write8 (wr, yytbl_data_geti (td, i));
221357f1050SThomas Veerman 			break;
222357f1050SThomas Veerman 		case sizeof (flex_int16_t):
223357f1050SThomas Veerman 			rv = yytbl_write16 (wr, yytbl_data_geti (td, i));
224357f1050SThomas Veerman 			break;
225357f1050SThomas Veerman 		case sizeof (flex_int32_t):
226357f1050SThomas Veerman 			rv = yytbl_write32 (wr, yytbl_data_geti (td, i));
227357f1050SThomas Veerman 			break;
228357f1050SThomas Veerman 		default:
229357f1050SThomas Veerman 			flex_die (_("invalid td_flags detected"));
230357f1050SThomas Veerman 		}
231357f1050SThomas Veerman 		if (rv < 0) {
232357f1050SThomas Veerman 			flex_die (_("error while writing tables"));
233357f1050SThomas Veerman 			return -1;
234357f1050SThomas Veerman 		}
235357f1050SThomas Veerman 		bwritten += rv;
236357f1050SThomas Veerman 	}
237357f1050SThomas Veerman 
238357f1050SThomas Veerman 	/* Sanity check */
239357f1050SThomas Veerman 	if (bwritten != (int) (12 + total_len * YYTDFLAGS2BYTES (td->td_flags))) {
240357f1050SThomas Veerman 		flex_die (_("insanity detected"));
241357f1050SThomas Veerman 		return -1;
242357f1050SThomas Veerman 	}
243357f1050SThomas Veerman 
244357f1050SThomas Veerman 	/* add padding */
245357f1050SThomas Veerman 	if ((rv = yytbl_write_pad64 (wr)) < 0) {
246357f1050SThomas Veerman 		flex_die (_("pad64 failed"));
247357f1050SThomas Veerman 		return -1;
248357f1050SThomas Veerman 	}
249357f1050SThomas Veerman 	bwritten += rv;
250357f1050SThomas Veerman 
251357f1050SThomas Veerman 	/* Now go back and update the th_hsize member */
252357f1050SThomas Veerman 	if (fgetpos (wr->out, &pos) != 0
253357f1050SThomas Veerman 	    || fsetpos (wr->out, &(wr->th_ssize_pos)) != 0
254357f1050SThomas Veerman 	    || yytbl_write32 (wr, wr->total_written) < 0
255357f1050SThomas Veerman 	    || fsetpos (wr->out, &pos)) {
256357f1050SThomas Veerman 		flex_die (_("get|set|fwrite32 failed"));
257357f1050SThomas Veerman 		return -1;
258357f1050SThomas Veerman 	}
259357f1050SThomas Veerman 	else
260357f1050SThomas Veerman 		/* Don't count the int we just wrote. */
261357f1050SThomas Veerman 		wr->total_written -= sizeof (flex_int32_t);
262357f1050SThomas Veerman 	return bwritten;
263357f1050SThomas Veerman }
264357f1050SThomas Veerman 
265357f1050SThomas Veerman /** Write n bytes.
266357f1050SThomas Veerman  *  @param  wr   the table writer
267357f1050SThomas Veerman  *  @param  v    data to be written
268357f1050SThomas Veerman  *  @param  len  number of bytes
269357f1050SThomas Veerman  *  @return  -1 on error. number of bytes written on success.
270357f1050SThomas Veerman  */
yytbl_writen(struct yytbl_writer * wr,void * v,flex_int32_t len)271357f1050SThomas Veerman int yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len)
272357f1050SThomas Veerman {
273357f1050SThomas Veerman 	int  rv;
274357f1050SThomas Veerman 
275357f1050SThomas Veerman 	rv = fwrite (v, 1, len, wr->out);
276357f1050SThomas Veerman 	if (rv != len)
277357f1050SThomas Veerman 		return -1;
278357f1050SThomas Veerman 	wr->total_written += len;
279357f1050SThomas Veerman 	return len;
280357f1050SThomas Veerman }
281357f1050SThomas Veerman 
282357f1050SThomas Veerman /** Write four bytes in network byte order
283357f1050SThomas Veerman  *  @param  wr  the table writer
284357f1050SThomas Veerman  *  @param  v    a dword in host byte order
285357f1050SThomas Veerman  *  @return  -1 on error. number of bytes written on success.
286357f1050SThomas Veerman  */
yytbl_write32(struct yytbl_writer * wr,flex_uint32_t v)287357f1050SThomas Veerman int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v)
288357f1050SThomas Veerman {
289357f1050SThomas Veerman 	flex_uint32_t vnet;
290357f1050SThomas Veerman 	size_t  bytes, rv;
291357f1050SThomas Veerman 
292357f1050SThomas Veerman 	vnet = htonl (v);
293357f1050SThomas Veerman 	bytes = sizeof (flex_uint32_t);
294357f1050SThomas Veerman 	rv = fwrite (&vnet, bytes, 1, wr->out);
295357f1050SThomas Veerman 	if (rv != 1)
296357f1050SThomas Veerman 		return -1;
297357f1050SThomas Veerman 	wr->total_written += bytes;
298357f1050SThomas Veerman 	return bytes;
299357f1050SThomas Veerman }
300357f1050SThomas Veerman 
301357f1050SThomas Veerman /** Write two bytes in network byte order.
302357f1050SThomas Veerman  *  @param  wr  the table writer
303357f1050SThomas Veerman  *  @param  v    a word in host byte order
304357f1050SThomas Veerman  *  @return  -1 on error. number of bytes written on success.
305357f1050SThomas Veerman  */
yytbl_write16(struct yytbl_writer * wr,flex_uint16_t v)306357f1050SThomas Veerman int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v)
307357f1050SThomas Veerman {
308357f1050SThomas Veerman 	flex_uint16_t vnet;
309357f1050SThomas Veerman 	size_t  bytes, rv;
310357f1050SThomas Veerman 
311357f1050SThomas Veerman 	vnet = htons (v);
312357f1050SThomas Veerman 	bytes = sizeof (flex_uint16_t);
313357f1050SThomas Veerman 	rv = fwrite (&vnet, bytes, 1, wr->out);
314357f1050SThomas Veerman 	if (rv != 1)
315357f1050SThomas Veerman 		return -1;
316357f1050SThomas Veerman 	wr->total_written += bytes;
317357f1050SThomas Veerman 	return bytes;
318357f1050SThomas Veerman }
319357f1050SThomas Veerman 
320357f1050SThomas Veerman /** Write a byte.
321357f1050SThomas Veerman  *  @param  wr  the table writer
322357f1050SThomas Veerman  *  @param  v    the value to be written
323357f1050SThomas Veerman  *  @return  -1 on error. number of bytes written on success.
324357f1050SThomas Veerman  */
yytbl_write8(struct yytbl_writer * wr,flex_uint8_t v)325357f1050SThomas Veerman int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v)
326357f1050SThomas Veerman {
327357f1050SThomas Veerman 	size_t  bytes, rv;
328357f1050SThomas Veerman 
329357f1050SThomas Veerman 	bytes = sizeof (flex_uint8_t);
330357f1050SThomas Veerman 	rv = fwrite (&v, bytes, 1, wr->out);
331357f1050SThomas Veerman 	if (rv != 1)
332357f1050SThomas Veerman 		return -1;
333357f1050SThomas Veerman 	wr->total_written += bytes;
334357f1050SThomas Veerman 	return bytes;
335357f1050SThomas Veerman }
336357f1050SThomas Veerman 
337357f1050SThomas Veerman 
33884d9c625SLionel Sambuc /* XXX Not Used */
33984d9c625SLionel Sambuc #if 0
340357f1050SThomas Veerman /** Extract data element [i][j] from array data tables.
341357f1050SThomas Veerman  * @param tbl data table
342357f1050SThomas Veerman  * @param i index into higher dimension array. i should be zero for one-dimensional arrays.
343357f1050SThomas Veerman  * @param j index into lower dimension array.
344357f1050SThomas Veerman  * @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table
345357f1050SThomas Veerman  * @return data[i][j + k]
346357f1050SThomas Veerman  */
347357f1050SThomas Veerman static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
348357f1050SThomas Veerman 				  int j, int k)
349357f1050SThomas Veerman {
350357f1050SThomas Veerman 	flex_int32_t lo;
351357f1050SThomas Veerman 
352357f1050SThomas Veerman 	k %= 2;
353357f1050SThomas Veerman 	lo = tbl->td_lolen;
354357f1050SThomas Veerman 
355357f1050SThomas Veerman 	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
356357f1050SThomas Veerman 	case sizeof (flex_int8_t):
357357f1050SThomas Veerman 		return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) +
358357f1050SThomas Veerman 						   k];
359357f1050SThomas Veerman 	case sizeof (flex_int16_t):
360357f1050SThomas Veerman 		return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k +
361357f1050SThomas Veerman 								    1) +
362357f1050SThomas Veerman 						    k];
363357f1050SThomas Veerman 	case sizeof (flex_int32_t):
364357f1050SThomas Veerman 		return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k +
365357f1050SThomas Veerman 								    1) +
366357f1050SThomas Veerman 						    k];
367357f1050SThomas Veerman 	default:
368357f1050SThomas Veerman 		flex_die (_("invalid td_flags detected"));
369357f1050SThomas Veerman 		break;
370357f1050SThomas Veerman 	}
371357f1050SThomas Veerman 
372357f1050SThomas Veerman 	return 0;
373357f1050SThomas Veerman }
37484d9c625SLionel Sambuc #endif /* Not used */
375357f1050SThomas Veerman 
376357f1050SThomas Veerman /** Extract data element [i] from array data tables treated as a single flat array of integers.
377357f1050SThomas Veerman  * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
378357f1050SThomas Veerman  * of structs.
379357f1050SThomas Veerman  * @param tbl data table
380357f1050SThomas Veerman  * @param i index into array.
381357f1050SThomas Veerman  * @return data[i]
382357f1050SThomas Veerman  */
yytbl_data_geti(const struct yytbl_data * tbl,int i)383357f1050SThomas Veerman static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i)
384357f1050SThomas Veerman {
385357f1050SThomas Veerman 
386357f1050SThomas Veerman 	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
387357f1050SThomas Veerman 	case sizeof (flex_int8_t):
388357f1050SThomas Veerman 		return ((flex_int8_t *) (tbl->td_data))[i];
389357f1050SThomas Veerman 	case sizeof (flex_int16_t):
390357f1050SThomas Veerman 		return ((flex_int16_t *) (tbl->td_data))[i];
391357f1050SThomas Veerman 	case sizeof (flex_int32_t):
392357f1050SThomas Veerman 		return ((flex_int32_t *) (tbl->td_data))[i];
393357f1050SThomas Veerman 	default:
394357f1050SThomas Veerman 		flex_die (_("invalid td_flags detected"));
395357f1050SThomas Veerman 		break;
396357f1050SThomas Veerman 	}
397357f1050SThomas Veerman 	return 0;
398357f1050SThomas Veerman }
399357f1050SThomas Veerman 
400357f1050SThomas Veerman /** Set data element [i] in array data tables treated as a single flat array of integers.
401357f1050SThomas Veerman  * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
402357f1050SThomas Veerman  * of structs.
403357f1050SThomas Veerman  * @param tbl data table
404357f1050SThomas Veerman  * @param i index into array.
405357f1050SThomas Veerman  * @param newval new value for data[i]
406357f1050SThomas Veerman  */
yytbl_data_seti(const struct yytbl_data * tbl,int i,flex_int32_t newval)407357f1050SThomas Veerman static void yytbl_data_seti (const struct yytbl_data *tbl, int i,
408357f1050SThomas Veerman 			     flex_int32_t newval)
409357f1050SThomas Veerman {
410357f1050SThomas Veerman 
411357f1050SThomas Veerman 	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
412357f1050SThomas Veerman 	case sizeof (flex_int8_t):
413357f1050SThomas Veerman 		((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval;
414357f1050SThomas Veerman 		break;
415357f1050SThomas Veerman 	case sizeof (flex_int16_t):
416357f1050SThomas Veerman 		((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval;
417357f1050SThomas Veerman 		break;
418357f1050SThomas Veerman 	case sizeof (flex_int32_t):
419357f1050SThomas Veerman 		((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval;
420357f1050SThomas Veerman 		break;
421357f1050SThomas Veerman 	default:
422357f1050SThomas Veerman 		flex_die (_("invalid td_flags detected"));
423357f1050SThomas Veerman 		break;
424357f1050SThomas Veerman 	}
425357f1050SThomas Veerman }
426357f1050SThomas Veerman 
427357f1050SThomas Veerman /** Calculate the number of bytes  needed to hold the largest
428357f1050SThomas Veerman  *  absolute value in this data array.
429357f1050SThomas Veerman  *  @param tbl  the data table
430357f1050SThomas Veerman  *  @return sizeof(n) where n in {flex_int8_t, flex_int16_t, flex_int32_t}
431357f1050SThomas Veerman  */
min_int_size(struct yytbl_data * tbl)432357f1050SThomas Veerman static size_t min_int_size (struct yytbl_data *tbl)
433357f1050SThomas Veerman {
434357f1050SThomas Veerman 	flex_uint32_t i, total_len;
435357f1050SThomas Veerman 	flex_int32_t max = 0;
436357f1050SThomas Veerman 
437357f1050SThomas Veerman 	total_len = yytbl_calc_total_len (tbl);
438357f1050SThomas Veerman 
439357f1050SThomas Veerman 	for (i = 0; i < total_len; i++) {
440357f1050SThomas Veerman 		flex_int32_t n;
441357f1050SThomas Veerman 
442357f1050SThomas Veerman 		n = abs (yytbl_data_geti (tbl, i));
443357f1050SThomas Veerman 
444357f1050SThomas Veerman 		if (n > max)
445357f1050SThomas Veerman 			max = n;
446357f1050SThomas Veerman 	}
447357f1050SThomas Veerman 
448357f1050SThomas Veerman 	if (max <= INT8_MAX)
449357f1050SThomas Veerman 		return sizeof (flex_int8_t);
450357f1050SThomas Veerman 	else if (max <= INT16_MAX)
451357f1050SThomas Veerman 		return sizeof (flex_int16_t);
452357f1050SThomas Veerman 	else
453357f1050SThomas Veerman 		return sizeof (flex_int32_t);
454357f1050SThomas Veerman }
455357f1050SThomas Veerman 
456357f1050SThomas Veerman /** Transform data to smallest possible of (int32, int16, int8).
457357f1050SThomas Veerman  * For example, we may have generated an int32 array due to user options
458357f1050SThomas Veerman  * (e.g., %option align), but if the maximum value in that array
459357f1050SThomas Veerman  * is 80 (for example), then we can serialize it with only 1 byte per int.
460357f1050SThomas Veerman  * This is NOT the same as compressed DFA tables. We're just trying
461357f1050SThomas Veerman  * to save storage space here.
462357f1050SThomas Veerman  *
463357f1050SThomas Veerman  * @param tbl the table to be compressed
464357f1050SThomas Veerman  */
yytbl_data_compress(struct yytbl_data * tbl)465357f1050SThomas Veerman void yytbl_data_compress (struct yytbl_data *tbl)
466357f1050SThomas Veerman {
467357f1050SThomas Veerman 	flex_int32_t i, newsz, total_len;
468357f1050SThomas Veerman 	struct yytbl_data newtbl;
469357f1050SThomas Veerman 
470357f1050SThomas Veerman 	yytbl_data_init (&newtbl, tbl->td_id);
471357f1050SThomas Veerman 	newtbl.td_hilen = tbl->td_hilen;
472357f1050SThomas Veerman 	newtbl.td_lolen = tbl->td_lolen;
473357f1050SThomas Veerman 	newtbl.td_flags = tbl->td_flags;
474357f1050SThomas Veerman 
475357f1050SThomas Veerman 	newsz = min_int_size (tbl);
476357f1050SThomas Veerman 
477357f1050SThomas Veerman 
478357f1050SThomas Veerman 	if (newsz == (int) YYTDFLAGS2BYTES (tbl->td_flags))
479357f1050SThomas Veerman 		/* No change in this table needed. */
480357f1050SThomas Veerman 		return;
481357f1050SThomas Veerman 
482357f1050SThomas Veerman 	if (newsz > (int) YYTDFLAGS2BYTES (tbl->td_flags)) {
483357f1050SThomas Veerman 		flex_die (_("detected negative compression"));
484357f1050SThomas Veerman 		return;
485357f1050SThomas Veerman 	}
486357f1050SThomas Veerman 
487357f1050SThomas Veerman 	total_len = yytbl_calc_total_len (tbl);
488357f1050SThomas Veerman 	newtbl.td_data = calloc (total_len, newsz);
489357f1050SThomas Veerman 	newtbl.td_flags =
490357f1050SThomas Veerman 		TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz);
491357f1050SThomas Veerman 
492357f1050SThomas Veerman 	for (i = 0; i < total_len; i++) {
493357f1050SThomas Veerman 		flex_int32_t g;
494357f1050SThomas Veerman 
495357f1050SThomas Veerman 		g = yytbl_data_geti (tbl, i);
496357f1050SThomas Veerman 		yytbl_data_seti (&newtbl, i, g);
497357f1050SThomas Veerman 	}
498357f1050SThomas Veerman 
499357f1050SThomas Veerman 
500357f1050SThomas Veerman 	/* Now copy over the old table */
501357f1050SThomas Veerman 	free (tbl->td_data);
502357f1050SThomas Veerman 	*tbl = newtbl;
503357f1050SThomas Veerman }
504357f1050SThomas Veerman 
505357f1050SThomas Veerman /* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */
506