1228072Sbapt/*  tables.c - tables serialization code
2228072Sbapt *
3228072Sbapt *  Copyright (c) 1990 The Regents of the University of California.
4228072Sbapt *  All rights reserved.
5228072Sbapt *
6228072Sbapt *  This code is derived from software contributed to Berkeley by
7228072Sbapt *  Vern Paxson.
8228072Sbapt *
9228072Sbapt *  The United States Government has rights in this work pursuant
10228072Sbapt *  to contract no. DE-AC03-76SF00098 between the United States
11228072Sbapt *  Department of Energy and the University of California.
12228072Sbapt *
13228072Sbapt *  This file is part of flex.
14228072Sbapt *
15228072Sbapt *  Redistribution and use in source and binary forms, with or without
16228072Sbapt *  modification, are permitted provided that the following conditions
17228072Sbapt *  are met:
18228072Sbapt *
19228072Sbapt *  1. Redistributions of source code must retain the above copyright
20228072Sbapt *     notice, this list of conditions and the following disclaimer.
21228072Sbapt *  2. Redistributions in binary form must reproduce the above copyright
22228072Sbapt *     notice, this list of conditions and the following disclaimer in the
23228072Sbapt *     documentation and/or other materials provided with the distribution.
24228072Sbapt *
25228072Sbapt *  Neither the name of the University nor the names of its contributors
26228072Sbapt *  may be used to endorse or promote products derived from this software
27228072Sbapt *  without specific prior written permission.
28228072Sbapt *
29228072Sbapt *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30228072Sbapt *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31228072Sbapt *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32228072Sbapt *  PURPOSE.
33228072Sbapt */
34228072Sbapt
35228072Sbapt
36228072Sbapt#include "flexdef.h"
37228072Sbapt#include "tables.h"
38228072Sbapt
39228072Sbapt/** Convert size_t to t_flag.
40228072Sbapt *  @param n in {1,2,4}
41228072Sbapt *  @return YYTD_DATA*.
42228072Sbapt */
43228072Sbapt#define BYTES2TFLAG(n)\
44228072Sbapt    (((n) == sizeof(flex_int8_t))\
45228072Sbapt        ? YYTD_DATA8\
46228072Sbapt        :(((n)== sizeof(flex_int16_t))\
47228072Sbapt            ? YYTD_DATA16\
48228072Sbapt            : YYTD_DATA32))
49228072Sbapt
50228072Sbapt/** Clear YYTD_DATA* bit flags
51228072Sbapt * @return the flag with the YYTD_DATA* bits cleared
52228072Sbapt */
53228072Sbapt#define TFLAGS_CLRDATA(flg) ((flg) & ~(YYTD_DATA8 | YYTD_DATA16 | YYTD_DATA32))
54228072Sbapt
55228072Sbaptint     yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v);
56228072Sbaptint     yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v);
57228072Sbaptint     yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v);
58228072Sbaptint     yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len);
59228072Sbaptstatic flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i);
60250125Sjkim/* XXX Not used
61228072Sbaptstatic flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
62228072Sbapt				  int j, int k);
63250125Sjkim */
64228072Sbapt
65228072Sbapt
66228072Sbapt/** Initialize the table writer.
67228072Sbapt *  @param wr an uninitialized writer
68228072Sbapt *  @param the output file
69228072Sbapt *  @return 0 on success
70228072Sbapt */
71228072Sbaptint yytbl_writer_init (struct yytbl_writer *wr, FILE * out)
72228072Sbapt{
73228072Sbapt	wr->out = out;
74228072Sbapt	wr->total_written = 0;
75228072Sbapt	return 0;
76228072Sbapt}
77228072Sbapt
78228072Sbapt/** Initialize a table header.
79228072Sbapt *  @param th  The uninitialized structure
80228072Sbapt *  @param version_str the  version string
81228072Sbapt *  @param name the name of this table set
82228072Sbapt */
83228072Sbaptint yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str,
84228072Sbapt		    const char *name)
85228072Sbapt{
86228072Sbapt	memset (th, 0, sizeof (struct yytbl_hdr));
87228072Sbapt
88228072Sbapt	th->th_magic = YYTBL_MAGIC;
89228072Sbapt	th->th_hsize = 14 + strlen (version_str) + 1 + strlen (name) + 1;
90228072Sbapt	th->th_hsize += yypad64 (th->th_hsize);
91228072Sbapt	th->th_ssize = 0;	// Not known at this point.
92228072Sbapt	th->th_flags = 0;
93228072Sbapt	th->th_version = copy_string (version_str);
94228072Sbapt	th->th_name = copy_string (name);
95228072Sbapt	return 0;
96228072Sbapt}
97228072Sbapt
98228072Sbapt/** Allocate and initialize a table data structure.
99228072Sbapt *  @param tbl a pointer to an uninitialized table
100228072Sbapt *  @param id  the table identifier
101228072Sbapt *  @return 0 on success
102228072Sbapt */
103228072Sbaptint yytbl_data_init (struct yytbl_data *td, enum yytbl_id id)
104228072Sbapt{
105228072Sbapt
106228072Sbapt	memset (td, 0, sizeof (struct yytbl_data));
107228072Sbapt	td->td_id = id;
108228072Sbapt	td->td_flags = YYTD_DATA32;
109228072Sbapt	return 0;
110228072Sbapt}
111228072Sbapt
112228072Sbapt/** Clean up table and data array.
113228072Sbapt *  @param td will be destroyed
114228072Sbapt *  @return 0 on success
115228072Sbapt */
116228072Sbaptint yytbl_data_destroy (struct yytbl_data *td)
117228072Sbapt{
118228072Sbapt	if (td->td_data)
119228072Sbapt		free (td->td_data);
120228072Sbapt	td->td_data = 0;
121228072Sbapt	free (td);
122228072Sbapt	return 0;
123228072Sbapt}
124228072Sbapt
125228072Sbapt/** Write enough padding to bring the file pointer to a 64-bit boundary. */
126228072Sbaptstatic int yytbl_write_pad64 (struct yytbl_writer *wr)
127228072Sbapt{
128228072Sbapt	int     pad, bwritten = 0;
129228072Sbapt
130228072Sbapt	pad = yypad64 (wr->total_written);
131228072Sbapt	while (pad-- > 0)
132228072Sbapt		if (yytbl_write8 (wr, 0) < 0)
133228072Sbapt			return -1;
134228072Sbapt		else
135228072Sbapt			bwritten++;
136228072Sbapt	return bwritten;
137228072Sbapt}
138228072Sbapt
139228072Sbapt/** write the header.
140228072Sbapt *  @param out the output stream
141228072Sbapt *  @param th table header to be written
142228072Sbapt *  @return -1 on error, or bytes written on success.
143228072Sbapt */
144228072Sbaptint yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th)
145228072Sbapt{
146228072Sbapt	int  sz, rv;
147228072Sbapt	int     bwritten = 0;
148228072Sbapt
149228072Sbapt	if (yytbl_write32 (wr, th->th_magic) < 0
150228072Sbapt	    || yytbl_write32 (wr, th->th_hsize) < 0)
151228072Sbapt		flex_die (_("th_magic|th_hsize write32 failed"));
152228072Sbapt	bwritten += 8;
153228072Sbapt
154228072Sbapt	if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0)
155228072Sbapt		flex_die (_("fgetpos failed"));
156228072Sbapt
157228072Sbapt	if (yytbl_write32 (wr, th->th_ssize) < 0
158228072Sbapt	    || yytbl_write16 (wr, th->th_flags) < 0)
159228072Sbapt		flex_die (_("th_ssize|th_flags write failed"));
160228072Sbapt	bwritten += 6;
161228072Sbapt
162228072Sbapt	sz = strlen (th->th_version) + 1;
163228072Sbapt	if ((rv = yytbl_writen (wr, th->th_version, sz)) != sz)
164228072Sbapt		flex_die (_("th_version writen failed"));
165228072Sbapt	bwritten += rv;
166228072Sbapt
167228072Sbapt	sz = strlen (th->th_name) + 1;
168228072Sbapt	if ((rv = yytbl_writen (wr, th->th_name, sz)) != sz)
169228072Sbapt		flex_die (_("th_name writen failed"));
170228072Sbapt	bwritten += rv;
171228072Sbapt
172228072Sbapt	/* add padding */
173228072Sbapt	if ((rv = yytbl_write_pad64 (wr)) < 0)
174228072Sbapt		flex_die (_("pad64 failed"));
175228072Sbapt	bwritten += rv;
176228072Sbapt
177228072Sbapt	/* Sanity check */
178228072Sbapt	if (bwritten != (int) th->th_hsize)
179228072Sbapt		flex_die (_("pad64 failed"));
180228072Sbapt
181228072Sbapt	return bwritten;
182228072Sbapt}
183228072Sbapt
184228072Sbapt
185228072Sbapt/** Write this table.
186228072Sbapt *  @param out the file writer
187228072Sbapt *  @param td table data to be written
188228072Sbapt *  @return -1 on error, or bytes written on success.
189228072Sbapt */
190228072Sbaptint yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td)
191228072Sbapt{
192228072Sbapt	int  rv;
193228072Sbapt	flex_int32_t bwritten = 0;
194228072Sbapt	flex_int32_t i, total_len;
195228072Sbapt	fpos_t  pos;
196228072Sbapt
197228072Sbapt	if ((rv = yytbl_write16 (wr, td->td_id)) < 0)
198228072Sbapt		return -1;
199228072Sbapt	bwritten += rv;
200228072Sbapt
201228072Sbapt	if ((rv = yytbl_write16 (wr, td->td_flags)) < 0)
202228072Sbapt		return -1;
203228072Sbapt	bwritten += rv;
204228072Sbapt
205228072Sbapt	if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0)
206228072Sbapt		return -1;
207228072Sbapt	bwritten += rv;
208228072Sbapt
209228072Sbapt	if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0)
210228072Sbapt		return -1;
211228072Sbapt	bwritten += rv;
212228072Sbapt
213228072Sbapt	total_len = yytbl_calc_total_len (td);
214228072Sbapt	for (i = 0; i < total_len; i++) {
215228072Sbapt		switch (YYTDFLAGS2BYTES (td->td_flags)) {
216228072Sbapt		case sizeof (flex_int8_t):
217228072Sbapt			rv = yytbl_write8 (wr, yytbl_data_geti (td, i));
218228072Sbapt			break;
219228072Sbapt		case sizeof (flex_int16_t):
220228072Sbapt			rv = yytbl_write16 (wr, yytbl_data_geti (td, i));
221228072Sbapt			break;
222228072Sbapt		case sizeof (flex_int32_t):
223228072Sbapt			rv = yytbl_write32 (wr, yytbl_data_geti (td, i));
224228072Sbapt			break;
225228072Sbapt		default:
226228072Sbapt			flex_die (_("invalid td_flags detected"));
227228072Sbapt		}
228228072Sbapt		if (rv < 0) {
229228072Sbapt			flex_die (_("error while writing tables"));
230228072Sbapt			return -1;
231228072Sbapt		}
232228072Sbapt		bwritten += rv;
233228072Sbapt	}
234228072Sbapt
235228072Sbapt	/* Sanity check */
236228072Sbapt	if (bwritten != (int) (12 + total_len * YYTDFLAGS2BYTES (td->td_flags))) {
237228072Sbapt		flex_die (_("insanity detected"));
238228072Sbapt		return -1;
239228072Sbapt	}
240228072Sbapt
241228072Sbapt	/* add padding */
242228072Sbapt	if ((rv = yytbl_write_pad64 (wr)) < 0) {
243228072Sbapt		flex_die (_("pad64 failed"));
244228072Sbapt		return -1;
245228072Sbapt	}
246228072Sbapt	bwritten += rv;
247228072Sbapt
248228072Sbapt	/* Now go back and update the th_hsize member */
249228072Sbapt	if (fgetpos (wr->out, &pos) != 0
250228072Sbapt	    || fsetpos (wr->out, &(wr->th_ssize_pos)) != 0
251228072Sbapt	    || yytbl_write32 (wr, wr->total_written) < 0
252228072Sbapt	    || fsetpos (wr->out, &pos)) {
253228072Sbapt		flex_die (_("get|set|fwrite32 failed"));
254228072Sbapt		return -1;
255228072Sbapt	}
256228072Sbapt	else
257228072Sbapt		/* Don't count the int we just wrote. */
258228072Sbapt		wr->total_written -= sizeof (flex_int32_t);
259228072Sbapt	return bwritten;
260228072Sbapt}
261228072Sbapt
262228072Sbapt/** Write n bytes.
263228072Sbapt *  @param  wr   the table writer
264228072Sbapt *  @param  v    data to be written
265228072Sbapt *  @param  len  number of bytes
266228072Sbapt *  @return  -1 on error. number of bytes written on success.
267228072Sbapt */
268228072Sbaptint yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len)
269228072Sbapt{
270228072Sbapt	int  rv;
271228072Sbapt
272228072Sbapt	rv = fwrite (v, 1, len, wr->out);
273228072Sbapt	if (rv != len)
274228072Sbapt		return -1;
275228072Sbapt	wr->total_written += len;
276228072Sbapt	return len;
277228072Sbapt}
278228072Sbapt
279228072Sbapt/** Write four bytes in network byte order
280228072Sbapt *  @param  wr  the table writer
281228072Sbapt *  @param  v    a dword in host byte order
282228072Sbapt *  @return  -1 on error. number of bytes written on success.
283228072Sbapt */
284228072Sbaptint yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v)
285228072Sbapt{
286228072Sbapt	flex_uint32_t vnet;
287228072Sbapt	size_t  bytes, rv;
288228072Sbapt
289228072Sbapt	vnet = htonl (v);
290228072Sbapt	bytes = sizeof (flex_uint32_t);
291228072Sbapt	rv = fwrite (&vnet, bytes, 1, wr->out);
292228072Sbapt	if (rv != 1)
293228072Sbapt		return -1;
294228072Sbapt	wr->total_written += bytes;
295228072Sbapt	return bytes;
296228072Sbapt}
297228072Sbapt
298228072Sbapt/** Write two bytes in network byte order.
299228072Sbapt *  @param  wr  the table writer
300228072Sbapt *  @param  v    a word in host byte order
301228072Sbapt *  @return  -1 on error. number of bytes written on success.
302228072Sbapt */
303228072Sbaptint yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v)
304228072Sbapt{
305228072Sbapt	flex_uint16_t vnet;
306228072Sbapt	size_t  bytes, rv;
307228072Sbapt
308228072Sbapt	vnet = htons (v);
309228072Sbapt	bytes = sizeof (flex_uint16_t);
310228072Sbapt	rv = fwrite (&vnet, bytes, 1, wr->out);
311228072Sbapt	if (rv != 1)
312228072Sbapt		return -1;
313228072Sbapt	wr->total_written += bytes;
314228072Sbapt	return bytes;
315228072Sbapt}
316228072Sbapt
317228072Sbapt/** Write a byte.
318228072Sbapt *  @param  wr  the table writer
319228072Sbapt *  @param  v    the value to be written
320228072Sbapt *  @return  -1 on error. number of bytes written on success.
321228072Sbapt */
322228072Sbaptint yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v)
323228072Sbapt{
324228072Sbapt	size_t  bytes, rv;
325228072Sbapt
326228072Sbapt	bytes = sizeof (flex_uint8_t);
327228072Sbapt	rv = fwrite (&v, bytes, 1, wr->out);
328228072Sbapt	if (rv != 1)
329228072Sbapt		return -1;
330228072Sbapt	wr->total_written += bytes;
331228072Sbapt	return bytes;
332228072Sbapt}
333228072Sbapt
334228072Sbapt
335250125Sjkim/* XXX Not Used */
336250125Sjkim#if 0
337228072Sbapt/** Extract data element [i][j] from array data tables.
338228072Sbapt * @param tbl data table
339228072Sbapt * @param i index into higher dimension array. i should be zero for one-dimensional arrays.
340228072Sbapt * @param j index into lower dimension array.
341228072Sbapt * @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table
342228072Sbapt * @return data[i][j + k]
343228072Sbapt */
344228072Sbaptstatic flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
345228072Sbapt				  int j, int k)
346228072Sbapt{
347228072Sbapt	flex_int32_t lo;
348228072Sbapt
349228072Sbapt	k %= 2;
350228072Sbapt	lo = tbl->td_lolen;
351228072Sbapt
352228072Sbapt	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
353228072Sbapt	case sizeof (flex_int8_t):
354228072Sbapt		return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) +
355228072Sbapt						   k];
356228072Sbapt	case sizeof (flex_int16_t):
357228072Sbapt		return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k +
358228072Sbapt								    1) +
359228072Sbapt						    k];
360228072Sbapt	case sizeof (flex_int32_t):
361228072Sbapt		return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k +
362228072Sbapt								    1) +
363228072Sbapt						    k];
364228072Sbapt	default:
365228072Sbapt		flex_die (_("invalid td_flags detected"));
366228072Sbapt		break;
367228072Sbapt	}
368228072Sbapt
369228072Sbapt	return 0;
370228072Sbapt}
371250125Sjkim#endif /* Not used */
372228072Sbapt
373228072Sbapt/** Extract data element [i] from array data tables treated as a single flat array of integers.
374228072Sbapt * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
375228072Sbapt * of structs.
376228072Sbapt * @param tbl data table
377228072Sbapt * @param i index into array.
378228072Sbapt * @return data[i]
379228072Sbapt */
380228072Sbaptstatic flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i)
381228072Sbapt{
382228072Sbapt
383228072Sbapt	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
384228072Sbapt	case sizeof (flex_int8_t):
385228072Sbapt		return ((flex_int8_t *) (tbl->td_data))[i];
386228072Sbapt	case sizeof (flex_int16_t):
387228072Sbapt		return ((flex_int16_t *) (tbl->td_data))[i];
388228072Sbapt	case sizeof (flex_int32_t):
389228072Sbapt		return ((flex_int32_t *) (tbl->td_data))[i];
390228072Sbapt	default:
391228072Sbapt		flex_die (_("invalid td_flags detected"));
392228072Sbapt		break;
393228072Sbapt	}
394228072Sbapt	return 0;
395228072Sbapt}
396228072Sbapt
397228072Sbapt/** Set data element [i] in array data tables treated as a single flat array of integers.
398228072Sbapt * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
399228072Sbapt * of structs.
400228072Sbapt * @param tbl data table
401228072Sbapt * @param i index into array.
402228072Sbapt * @param newval new value for data[i]
403228072Sbapt */
404228072Sbaptstatic void yytbl_data_seti (const struct yytbl_data *tbl, int i,
405228072Sbapt			     flex_int32_t newval)
406228072Sbapt{
407228072Sbapt
408228072Sbapt	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
409228072Sbapt	case sizeof (flex_int8_t):
410228072Sbapt		((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval;
411228072Sbapt		break;
412228072Sbapt	case sizeof (flex_int16_t):
413228072Sbapt		((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval;
414228072Sbapt		break;
415228072Sbapt	case sizeof (flex_int32_t):
416228072Sbapt		((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval;
417228072Sbapt		break;
418228072Sbapt	default:
419228072Sbapt		flex_die (_("invalid td_flags detected"));
420228072Sbapt		break;
421228072Sbapt	}
422228072Sbapt}
423228072Sbapt
424228072Sbapt/** Calculate the number of bytes  needed to hold the largest
425228072Sbapt *  absolute value in this data array.
426228072Sbapt *  @param tbl  the data table
427228072Sbapt *  @return sizeof(n) where n in {flex_int8_t, flex_int16_t, flex_int32_t}
428228072Sbapt */
429228072Sbaptstatic size_t min_int_size (struct yytbl_data *tbl)
430228072Sbapt{
431228072Sbapt	flex_uint32_t i, total_len;
432228072Sbapt	flex_int32_t max = 0;
433228072Sbapt
434228072Sbapt	total_len = yytbl_calc_total_len (tbl);
435228072Sbapt
436228072Sbapt	for (i = 0; i < total_len; i++) {
437228072Sbapt		flex_int32_t n;
438228072Sbapt
439228072Sbapt		n = abs (yytbl_data_geti (tbl, i));
440228072Sbapt
441228072Sbapt		if (n > max)
442228072Sbapt			max = n;
443228072Sbapt	}
444228072Sbapt
445228072Sbapt	if (max <= INT8_MAX)
446228072Sbapt		return sizeof (flex_int8_t);
447228072Sbapt	else if (max <= INT16_MAX)
448228072Sbapt		return sizeof (flex_int16_t);
449228072Sbapt	else
450228072Sbapt		return sizeof (flex_int32_t);
451228072Sbapt}
452228072Sbapt
453228072Sbapt/** Transform data to smallest possible of (int32, int16, int8).
454228072Sbapt * For example, we may have generated an int32 array due to user options
455228072Sbapt * (e.g., %option align), but if the maximum value in that array
456228072Sbapt * is 80 (for example), then we can serialize it with only 1 byte per int.
457228072Sbapt * This is NOT the same as compressed DFA tables. We're just trying
458228072Sbapt * to save storage space here.
459228072Sbapt *
460228072Sbapt * @param tbl the table to be compressed
461228072Sbapt */
462228072Sbaptvoid yytbl_data_compress (struct yytbl_data *tbl)
463228072Sbapt{
464228072Sbapt	flex_int32_t i, newsz, total_len;
465228072Sbapt	struct yytbl_data newtbl;
466228072Sbapt
467228072Sbapt	yytbl_data_init (&newtbl, tbl->td_id);
468228072Sbapt	newtbl.td_hilen = tbl->td_hilen;
469228072Sbapt	newtbl.td_lolen = tbl->td_lolen;
470228072Sbapt	newtbl.td_flags = tbl->td_flags;
471228072Sbapt
472228072Sbapt	newsz = min_int_size (tbl);
473228072Sbapt
474228072Sbapt
475228072Sbapt	if (newsz == (int) YYTDFLAGS2BYTES (tbl->td_flags))
476228072Sbapt		/* No change in this table needed. */
477228072Sbapt		return;
478228072Sbapt
479228072Sbapt	if (newsz > (int) YYTDFLAGS2BYTES (tbl->td_flags)) {
480228072Sbapt		flex_die (_("detected negative compression"));
481228072Sbapt		return;
482228072Sbapt	}
483228072Sbapt
484228072Sbapt	total_len = yytbl_calc_total_len (tbl);
485228072Sbapt	newtbl.td_data = calloc (total_len, newsz);
486228072Sbapt	newtbl.td_flags =
487228072Sbapt		TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz);
488228072Sbapt
489228072Sbapt	for (i = 0; i < total_len; i++) {
490228072Sbapt		flex_int32_t g;
491228072Sbapt
492228072Sbapt		g = yytbl_data_geti (tbl, i);
493228072Sbapt		yytbl_data_seti (&newtbl, i, g);
494228072Sbapt	}
495228072Sbapt
496228072Sbapt
497228072Sbapt	/* Now copy over the old table */
498228072Sbapt	free (tbl->td_data);
499228072Sbapt	*tbl = newtbl;
500228072Sbapt}
501228072Sbapt
502228072Sbapt/* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */
503