xref: /netbsd-src/external/bsd/flex/dist/src/tables.c (revision 7977e68669c3b784eb65c933a2bd99785638ae00)
1*7977e686Schristos /*	$NetBSD: tables.c,v 1.3 2017/01/02 17:45:27 christos Exp $	*/
2a11deec2Schristos 
330da1778Schristos /*  tables.c - tables serialization code
430da1778Schristos  *
530da1778Schristos  *  Copyright (c) 1990 The Regents of the University of California.
630da1778Schristos  *  All rights reserved.
730da1778Schristos  *
830da1778Schristos  *  This code is derived from software contributed to Berkeley by
930da1778Schristos  *  Vern Paxson.
1030da1778Schristos  *
1130da1778Schristos  *  The United States Government has rights in this work pursuant
1230da1778Schristos  *  to contract no. DE-AC03-76SF00098 between the United States
1330da1778Schristos  *  Department of Energy and the University of California.
1430da1778Schristos  *
1530da1778Schristos  *  This file is part of flex.
1630da1778Schristos  *
1730da1778Schristos  *  Redistribution and use in source and binary forms, with or without
1830da1778Schristos  *  modification, are permitted provided that the following conditions
1930da1778Schristos  *  are met:
2030da1778Schristos  *
2130da1778Schristos  *  1. Redistributions of source code must retain the above copyright
2230da1778Schristos  *     notice, this list of conditions and the following disclaimer.
2330da1778Schristos  *  2. Redistributions in binary form must reproduce the above copyright
2430da1778Schristos  *     notice, this list of conditions and the following disclaimer in the
2530da1778Schristos  *     documentation and/or other materials provided with the distribution.
2630da1778Schristos  *
2730da1778Schristos  *  Neither the name of the University nor the names of its contributors
2830da1778Schristos  *  may be used to endorse or promote products derived from this software
2930da1778Schristos  *  without specific prior written permission.
3030da1778Schristos  *
3130da1778Schristos  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
3230da1778Schristos  *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
3330da1778Schristos  *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3430da1778Schristos  *  PURPOSE.
3530da1778Schristos  */
36a11deec2Schristos #include "flexdef.h"
37*7977e686Schristos __RCSID("$NetBSD: tables.c,v 1.3 2017/01/02 17:45:27 christos Exp $");
3830da1778Schristos 
3930da1778Schristos 
4030da1778Schristos #include "tables.h"
4130da1778Schristos 
4230da1778Schristos /** Convert size_t to t_flag.
4330da1778Schristos  *  @param n in {1,2,4}
4430da1778Schristos  *  @return YYTD_DATA*.
4530da1778Schristos  */
4630da1778Schristos #define BYTES2TFLAG(n)\
4730da1778Schristos     (((n) == sizeof(flex_int8_t))\
4830da1778Schristos         ? YYTD_DATA8\
4930da1778Schristos         :(((n)== sizeof(flex_int16_t))\
5030da1778Schristos             ? YYTD_DATA16\
5130da1778Schristos             : YYTD_DATA32))
5230da1778Schristos 
5330da1778Schristos /** Clear YYTD_DATA* bit flags
5430da1778Schristos  * @return the flag with the YYTD_DATA* bits cleared
5530da1778Schristos  */
5630da1778Schristos #define TFLAGS_CLRDATA(flg) ((flg) & ~(YYTD_DATA8 | YYTD_DATA16 | YYTD_DATA32))
5730da1778Schristos 
5830da1778Schristos int     yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v);
5930da1778Schristos int     yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v);
6030da1778Schristos int     yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v);
61*7977e686Schristos int     yytbl_writen (struct yytbl_writer *wr, void *v, int len);
6230da1778Schristos static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i);
6330da1778Schristos /* XXX Not used
6430da1778Schristos static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
6530da1778Schristos 				  int j, int k);
6630da1778Schristos  */
6730da1778Schristos 
6830da1778Schristos 
6930da1778Schristos /** Initialize the table writer.
7030da1778Schristos  *  @param wr an uninitialized writer
7130da1778Schristos  *  @param out the output file
7230da1778Schristos  *  @return 0 on success
7330da1778Schristos  */
yytbl_writer_init(struct yytbl_writer * wr,FILE * out)7430da1778Schristos int yytbl_writer_init (struct yytbl_writer *wr, FILE * out)
7530da1778Schristos {
7630da1778Schristos 	wr->out = out;
7730da1778Schristos 	wr->total_written = 0;
7830da1778Schristos 	return 0;
7930da1778Schristos }
8030da1778Schristos 
8130da1778Schristos /** Initialize a table header.
8230da1778Schristos  *  @param th  The uninitialized structure
8330da1778Schristos  *  @param version_str the  version string
8430da1778Schristos  *  @param name the name of this table set
8530da1778Schristos  */
yytbl_hdr_init(struct yytbl_hdr * th,const char * version_str,const char * name)8630da1778Schristos int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str,
8730da1778Schristos 		    const char *name)
8830da1778Schristos {
8930da1778Schristos 	memset (th, 0, sizeof (struct yytbl_hdr));
9030da1778Schristos 
9130da1778Schristos 	th->th_magic = YYTBL_MAGIC;
92*7977e686Schristos 	th->th_hsize = (flex_uint32_t) (14 + strlen (version_str) + 1 + strlen (name) + 1);
9330da1778Schristos 	th->th_hsize += yypad64 (th->th_hsize);
9430da1778Schristos 	th->th_ssize = 0;	// Not known at this point.
9530da1778Schristos 	th->th_flags = 0;
96*7977e686Schristos 	th->th_version = xstrdup(version_str);
97*7977e686Schristos 	th->th_name = xstrdup(name);
9830da1778Schristos 	return 0;
9930da1778Schristos }
10030da1778Schristos 
10130da1778Schristos /** Allocate and initialize a table data structure.
10230da1778Schristos  *  @param td a pointer to an uninitialized table
10330da1778Schristos  *  @param id  the table identifier
10430da1778Schristos  *  @return 0 on success
10530da1778Schristos  */
yytbl_data_init(struct yytbl_data * td,enum yytbl_id id)10630da1778Schristos int yytbl_data_init (struct yytbl_data *td, enum yytbl_id id)
10730da1778Schristos {
10830da1778Schristos 
10930da1778Schristos 	memset (td, 0, sizeof (struct yytbl_data));
11030da1778Schristos 	td->td_id = id;
11130da1778Schristos 	td->td_flags = YYTD_DATA32;
11230da1778Schristos 	return 0;
11330da1778Schristos }
11430da1778Schristos 
11530da1778Schristos /** Clean up table and data array.
11630da1778Schristos  *  @param td will be destroyed
11730da1778Schristos  *  @return 0 on success
11830da1778Schristos  */
yytbl_data_destroy(struct yytbl_data * td)11930da1778Schristos int yytbl_data_destroy (struct yytbl_data *td)
12030da1778Schristos {
12130da1778Schristos 	free(td->td_data);
12230da1778Schristos 	td->td_data = 0;
12330da1778Schristos 	free (td);
12430da1778Schristos 	return 0;
12530da1778Schristos }
12630da1778Schristos 
12730da1778Schristos /** Write enough padding to bring the file pointer to a 64-bit boundary. */
yytbl_write_pad64(struct yytbl_writer * wr)12830da1778Schristos static int yytbl_write_pad64 (struct yytbl_writer *wr)
12930da1778Schristos {
13030da1778Schristos 	int     pad, bwritten = 0;
13130da1778Schristos 
13230da1778Schristos 	pad = yypad64 (wr->total_written);
13330da1778Schristos 	while (pad-- > 0)
13430da1778Schristos 		if (yytbl_write8 (wr, 0) < 0)
13530da1778Schristos 			return -1;
13630da1778Schristos 		else
13730da1778Schristos 			bwritten++;
13830da1778Schristos 	return bwritten;
13930da1778Schristos }
14030da1778Schristos 
14130da1778Schristos /** write the header.
14230da1778Schristos  *  @param wr the output stream
14330da1778Schristos  *  @param th table header to be written
14430da1778Schristos  *  @return -1 on error, or bytes written on success.
14530da1778Schristos  */
yytbl_hdr_fwrite(struct yytbl_writer * wr,const struct yytbl_hdr * th)14630da1778Schristos int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th)
14730da1778Schristos {
14830da1778Schristos 	int  sz, rv;
14930da1778Schristos 	int     bwritten = 0;
15030da1778Schristos 
15130da1778Schristos 	if (yytbl_write32 (wr, th->th_magic) < 0
15230da1778Schristos 	    || yytbl_write32 (wr, th->th_hsize) < 0)
15330da1778Schristos 		flex_die (_("th_magic|th_hsize write32 failed"));
15430da1778Schristos 	bwritten += 8;
15530da1778Schristos 
15630da1778Schristos 	if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0)
15730da1778Schristos 		flex_die (_("fgetpos failed"));
15830da1778Schristos 
15930da1778Schristos 	if (yytbl_write32 (wr, th->th_ssize) < 0
16030da1778Schristos 	    || yytbl_write16 (wr, th->th_flags) < 0)
16130da1778Schristos 		flex_die (_("th_ssize|th_flags write failed"));
16230da1778Schristos 	bwritten += 6;
16330da1778Schristos 
164*7977e686Schristos 	sz = (int) strlen (th->th_version) + 1;
16530da1778Schristos 	if ((rv = yytbl_writen (wr, th->th_version, sz)) != sz)
16630da1778Schristos 		flex_die (_("th_version writen failed"));
16730da1778Schristos 	bwritten += rv;
16830da1778Schristos 
169*7977e686Schristos 	sz = (int) strlen (th->th_name) + 1;
17030da1778Schristos 	if ((rv = yytbl_writen (wr, th->th_name, sz)) != sz)
17130da1778Schristos 		flex_die (_("th_name writen failed"));
17230da1778Schristos 	bwritten += rv;
17330da1778Schristos 
17430da1778Schristos 	/* add padding */
17530da1778Schristos 	if ((rv = yytbl_write_pad64 (wr)) < 0)
17630da1778Schristos 		flex_die (_("pad64 failed"));
17730da1778Schristos 	bwritten += rv;
17830da1778Schristos 
17930da1778Schristos 	/* Sanity check */
18030da1778Schristos 	if (bwritten != (int) th->th_hsize)
18130da1778Schristos 		flex_die (_("pad64 failed"));
18230da1778Schristos 
18330da1778Schristos 	return bwritten;
18430da1778Schristos }
18530da1778Schristos 
18630da1778Schristos 
18730da1778Schristos /** Write this table.
18830da1778Schristos  *  @param wr the file writer
18930da1778Schristos  *  @param td table data to be written
19030da1778Schristos  *  @return -1 on error, or bytes written on success.
19130da1778Schristos  */
yytbl_data_fwrite(struct yytbl_writer * wr,struct yytbl_data * td)19230da1778Schristos int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td)
19330da1778Schristos {
19430da1778Schristos 	int  rv;
19530da1778Schristos 	flex_int32_t bwritten = 0;
19630da1778Schristos 	flex_int32_t i, total_len;
19730da1778Schristos 	fpos_t  pos;
19830da1778Schristos 
19930da1778Schristos 	if ((rv = yytbl_write16 (wr, td->td_id)) < 0)
20030da1778Schristos 		return -1;
20130da1778Schristos 	bwritten += rv;
20230da1778Schristos 
20330da1778Schristos 	if ((rv = yytbl_write16 (wr, td->td_flags)) < 0)
20430da1778Schristos 		return -1;
20530da1778Schristos 	bwritten += rv;
20630da1778Schristos 
20730da1778Schristos 	if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0)
20830da1778Schristos 		return -1;
20930da1778Schristos 	bwritten += rv;
21030da1778Schristos 
21130da1778Schristos 	if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0)
21230da1778Schristos 		return -1;
21330da1778Schristos 	bwritten += rv;
21430da1778Schristos 
21530da1778Schristos 	total_len = yytbl_calc_total_len (td);
21630da1778Schristos 	for (i = 0; i < total_len; i++) {
21730da1778Schristos 		switch (YYTDFLAGS2BYTES (td->td_flags)) {
21830da1778Schristos 		case sizeof (flex_int8_t):
219*7977e686Schristos 			rv = yytbl_write8 (wr, (flex_uint8_t) yytbl_data_geti (td, i));
22030da1778Schristos 			break;
22130da1778Schristos 		case sizeof (flex_int16_t):
222*7977e686Schristos 			rv = yytbl_write16 (wr, (flex_uint16_t) yytbl_data_geti (td, i));
22330da1778Schristos 			break;
22430da1778Schristos 		case sizeof (flex_int32_t):
225*7977e686Schristos 			rv = yytbl_write32 (wr, (flex_uint32_t) yytbl_data_geti (td, i));
22630da1778Schristos 			break;
22730da1778Schristos 		default:
22830da1778Schristos 			flex_die (_("invalid td_flags detected"));
22930da1778Schristos 		}
23030da1778Schristos 		if (rv < 0) {
23130da1778Schristos 			flex_die (_("error while writing tables"));
23230da1778Schristos 			return -1;
23330da1778Schristos 		}
23430da1778Schristos 		bwritten += rv;
23530da1778Schristos 	}
23630da1778Schristos 
23730da1778Schristos 	/* Sanity check */
238*7977e686Schristos 	if (bwritten != (12 + total_len * (int) YYTDFLAGS2BYTES (td->td_flags))) {
23930da1778Schristos 		flex_die (_("insanity detected"));
24030da1778Schristos 		return -1;
24130da1778Schristos 	}
24230da1778Schristos 
24330da1778Schristos 	/* add padding */
24430da1778Schristos 	if ((rv = yytbl_write_pad64 (wr)) < 0) {
24530da1778Schristos 		flex_die (_("pad64 failed"));
24630da1778Schristos 		return -1;
24730da1778Schristos 	}
24830da1778Schristos 	bwritten += rv;
24930da1778Schristos 
25030da1778Schristos 	/* Now go back and update the th_hsize member */
25130da1778Schristos 	if (fgetpos (wr->out, &pos) != 0
25230da1778Schristos 	    || fsetpos (wr->out, &(wr->th_ssize_pos)) != 0
253*7977e686Schristos 	    || yytbl_write32 (wr, (flex_uint32_t) wr->total_written) < 0
25430da1778Schristos 	    || fsetpos (wr->out, &pos)) {
25530da1778Schristos 		flex_die (_("get|set|fwrite32 failed"));
25630da1778Schristos 		return -1;
25730da1778Schristos 	}
25830da1778Schristos 	else
25930da1778Schristos 		/* Don't count the int we just wrote. */
260*7977e686Schristos 		wr->total_written -= (int) sizeof (flex_int32_t);
26130da1778Schristos 	return bwritten;
26230da1778Schristos }
26330da1778Schristos 
26430da1778Schristos /** Write n bytes.
26530da1778Schristos  *  @param  wr   the table writer
26630da1778Schristos  *  @param  v    data to be written
26730da1778Schristos  *  @param  len  number of bytes
26830da1778Schristos  *  @return  -1 on error. number of bytes written on success.
26930da1778Schristos  */
yytbl_writen(struct yytbl_writer * wr,void * v,int len)270*7977e686Schristos int yytbl_writen (struct yytbl_writer *wr, void *v, int len)
27130da1778Schristos {
27230da1778Schristos 	int  rv;
27330da1778Schristos 
274*7977e686Schristos 	rv = (int) fwrite (v, 1, (size_t) len, wr->out);
27530da1778Schristos 	if (rv != len)
27630da1778Schristos 		return -1;
27730da1778Schristos 	wr->total_written += len;
27830da1778Schristos 	return len;
27930da1778Schristos }
28030da1778Schristos 
28130da1778Schristos /** Write four bytes in network byte order
28230da1778Schristos  *  @param  wr  the table writer
28330da1778Schristos  *  @param  v    a dword in host byte order
28430da1778Schristos  *  @return  -1 on error. number of bytes written on success.
28530da1778Schristos  */
yytbl_write32(struct yytbl_writer * wr,flex_uint32_t v)28630da1778Schristos int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v)
28730da1778Schristos {
28830da1778Schristos 	flex_uint32_t vnet;
289*7977e686Schristos 	int  bytes, rv;
29030da1778Schristos 
29130da1778Schristos 	vnet = htonl (v);
292*7977e686Schristos 	bytes = (int) sizeof (flex_uint32_t);
293*7977e686Schristos 	rv = (int) fwrite (&vnet, (size_t) bytes, 1, wr->out);
29430da1778Schristos 	if (rv != 1)
29530da1778Schristos 		return -1;
29630da1778Schristos 	wr->total_written += bytes;
29730da1778Schristos 	return bytes;
29830da1778Schristos }
29930da1778Schristos 
30030da1778Schristos /** Write two bytes in network byte order.
30130da1778Schristos  *  @param  wr  the table writer
30230da1778Schristos  *  @param  v    a word in host byte order
30330da1778Schristos  *  @return  -1 on error. number of bytes written on success.
30430da1778Schristos  */
yytbl_write16(struct yytbl_writer * wr,flex_uint16_t v)30530da1778Schristos int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v)
30630da1778Schristos {
30730da1778Schristos 	flex_uint16_t vnet;
308*7977e686Schristos 	int  bytes, rv;
30930da1778Schristos 
31030da1778Schristos 	vnet = htons (v);
311*7977e686Schristos 	bytes = (int) sizeof (flex_uint16_t);
312*7977e686Schristos 	rv = (int) fwrite (&vnet, (size_t) bytes, 1, wr->out);
31330da1778Schristos 	if (rv != 1)
31430da1778Schristos 		return -1;
31530da1778Schristos 	wr->total_written += bytes;
31630da1778Schristos 	return bytes;
31730da1778Schristos }
31830da1778Schristos 
31930da1778Schristos /** Write a byte.
32030da1778Schristos  *  @param  wr  the table writer
32130da1778Schristos  *  @param  v    the value to be written
32230da1778Schristos  *  @return  -1 on error. number of bytes written on success.
32330da1778Schristos  */
yytbl_write8(struct yytbl_writer * wr,flex_uint8_t v)32430da1778Schristos int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v)
32530da1778Schristos {
326*7977e686Schristos 	int  bytes, rv;
32730da1778Schristos 
328*7977e686Schristos 	bytes = (int) sizeof (flex_uint8_t);
329*7977e686Schristos 	rv = (int) fwrite (&v, (size_t) bytes, 1, wr->out);
33030da1778Schristos 	if (rv != 1)
33130da1778Schristos 		return -1;
33230da1778Schristos 	wr->total_written += bytes;
33330da1778Schristos 	return bytes;
33430da1778Schristos }
33530da1778Schristos 
33630da1778Schristos 
33730da1778Schristos /* XXX Not Used */
33830da1778Schristos #if 0
33930da1778Schristos /** Extract data element [i][j] from array data tables.
34030da1778Schristos  * @param tbl data table
34130da1778Schristos  * @param i index into higher dimension array. i should be zero for one-dimensional arrays.
34230da1778Schristos  * @param j index into lower dimension array.
34330da1778Schristos  * @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table
34430da1778Schristos  * @return data[i][j + k]
34530da1778Schristos  */
34630da1778Schristos static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
34730da1778Schristos 				  int j, int k)
34830da1778Schristos {
34930da1778Schristos 	flex_int32_t lo;
35030da1778Schristos 
35130da1778Schristos 	k %= 2;
35230da1778Schristos 	lo = tbl->td_lolen;
35330da1778Schristos 
35430da1778Schristos 	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
35530da1778Schristos 	case sizeof (flex_int8_t):
35630da1778Schristos 		return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) +
35730da1778Schristos 						   k];
35830da1778Schristos 	case sizeof (flex_int16_t):
35930da1778Schristos 		return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k +
36030da1778Schristos 								    1) +
36130da1778Schristos 						    k];
36230da1778Schristos 	case sizeof (flex_int32_t):
36330da1778Schristos 		return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k +
36430da1778Schristos 								    1) +
36530da1778Schristos 						    k];
36630da1778Schristos 	default:
36730da1778Schristos 		flex_die (_("invalid td_flags detected"));
36830da1778Schristos 		break;
36930da1778Schristos 	}
37030da1778Schristos 
37130da1778Schristos 	return 0;
37230da1778Schristos }
37330da1778Schristos #endif /* Not used */
37430da1778Schristos 
37530da1778Schristos /** Extract data element [i] from array data tables treated as a single flat array of integers.
37630da1778Schristos  * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
37730da1778Schristos  * of structs.
37830da1778Schristos  * @param tbl data table
37930da1778Schristos  * @param i index into array.
38030da1778Schristos  * @return data[i]
38130da1778Schristos  */
yytbl_data_geti(const struct yytbl_data * tbl,int i)38230da1778Schristos static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i)
38330da1778Schristos {
38430da1778Schristos 
38530da1778Schristos 	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
38630da1778Schristos 	case sizeof (flex_int8_t):
38730da1778Schristos 		return ((flex_int8_t *) (tbl->td_data))[i];
38830da1778Schristos 	case sizeof (flex_int16_t):
38930da1778Schristos 		return ((flex_int16_t *) (tbl->td_data))[i];
39030da1778Schristos 	case sizeof (flex_int32_t):
39130da1778Schristos 		return ((flex_int32_t *) (tbl->td_data))[i];
39230da1778Schristos 	default:
39330da1778Schristos 		flex_die (_("invalid td_flags detected"));
39430da1778Schristos 		break;
39530da1778Schristos 	}
39630da1778Schristos 	return 0;
39730da1778Schristos }
39830da1778Schristos 
39930da1778Schristos /** Set data element [i] in array data tables treated as a single flat array of integers.
40030da1778Schristos  * Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
40130da1778Schristos  * of structs.
40230da1778Schristos  * @param tbl data table
40330da1778Schristos  * @param i index into array.
40430da1778Schristos  * @param newval new value for data[i]
40530da1778Schristos  */
yytbl_data_seti(const struct yytbl_data * tbl,int i,flex_int32_t newval)40630da1778Schristos static void yytbl_data_seti (const struct yytbl_data *tbl, int i,
40730da1778Schristos 			     flex_int32_t newval)
40830da1778Schristos {
40930da1778Schristos 
41030da1778Schristos 	switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
41130da1778Schristos 	case sizeof (flex_int8_t):
41230da1778Schristos 		((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval;
41330da1778Schristos 		break;
41430da1778Schristos 	case sizeof (flex_int16_t):
41530da1778Schristos 		((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval;
41630da1778Schristos 		break;
41730da1778Schristos 	case sizeof (flex_int32_t):
41830da1778Schristos 		((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval;
41930da1778Schristos 		break;
42030da1778Schristos 	default:
42130da1778Schristos 		flex_die (_("invalid td_flags detected"));
42230da1778Schristos 		break;
42330da1778Schristos 	}
42430da1778Schristos }
42530da1778Schristos 
42630da1778Schristos /** Calculate the number of bytes  needed to hold the largest
42730da1778Schristos  *  absolute value in this data array.
42830da1778Schristos  *  @param tbl  the data table
42930da1778Schristos  *  @return sizeof(n) where n in {flex_int8_t, flex_int16_t, flex_int32_t}
43030da1778Schristos  */
min_int_size(struct yytbl_data * tbl)43130da1778Schristos static size_t min_int_size (struct yytbl_data *tbl)
43230da1778Schristos {
433*7977e686Schristos 	flex_int32_t i, total_len;
43430da1778Schristos 	flex_int32_t max = 0;
43530da1778Schristos 
43630da1778Schristos 	total_len = yytbl_calc_total_len (tbl);
43730da1778Schristos 
43830da1778Schristos 	for (i = 0; i < total_len; i++) {
43930da1778Schristos 		flex_int32_t n;
44030da1778Schristos 
44130da1778Schristos 		n = abs (yytbl_data_geti (tbl, i));
44230da1778Schristos 
443*7977e686Schristos 		if (max < n)
44430da1778Schristos 			max = n;
44530da1778Schristos 	}
44630da1778Schristos 
44730da1778Schristos 	if (max <= INT8_MAX)
44830da1778Schristos 		return sizeof (flex_int8_t);
44930da1778Schristos 	else if (max <= INT16_MAX)
45030da1778Schristos 		return sizeof (flex_int16_t);
45130da1778Schristos 	else
45230da1778Schristos 		return sizeof (flex_int32_t);
45330da1778Schristos }
45430da1778Schristos 
45530da1778Schristos /** Transform data to smallest possible of (int32, int16, int8).
45630da1778Schristos  * For example, we may have generated an int32 array due to user options
45730da1778Schristos  * (e.g., %option align), but if the maximum value in that array
45830da1778Schristos  * is 80 (for example), then we can serialize it with only 1 byte per int.
45930da1778Schristos  * This is NOT the same as compressed DFA tables. We're just trying
46030da1778Schristos  * to save storage space here.
46130da1778Schristos  *
46230da1778Schristos  * @param tbl the table to be compressed
46330da1778Schristos  */
yytbl_data_compress(struct yytbl_data * tbl)46430da1778Schristos void yytbl_data_compress (struct yytbl_data *tbl)
46530da1778Schristos {
466*7977e686Schristos 	flex_int32_t i, total_len;
467*7977e686Schristos 	size_t newsz;
46830da1778Schristos 	struct yytbl_data newtbl;
46930da1778Schristos 
47030da1778Schristos 	yytbl_data_init (&newtbl, tbl->td_id);
47130da1778Schristos 	newtbl.td_hilen = tbl->td_hilen;
47230da1778Schristos 	newtbl.td_lolen = tbl->td_lolen;
47330da1778Schristos 	newtbl.td_flags = tbl->td_flags;
47430da1778Schristos 
47530da1778Schristos 	newsz = min_int_size (tbl);
47630da1778Schristos 
47730da1778Schristos 
478*7977e686Schristos 	if (newsz == YYTDFLAGS2BYTES (tbl->td_flags))
47930da1778Schristos 		/* No change in this table needed. */
48030da1778Schristos 		return;
48130da1778Schristos 
482*7977e686Schristos 	if (newsz > YYTDFLAGS2BYTES (tbl->td_flags)) {
48330da1778Schristos 		flex_die (_("detected negative compression"));
48430da1778Schristos 		return;
48530da1778Schristos 	}
48630da1778Schristos 
48730da1778Schristos 	total_len = yytbl_calc_total_len (tbl);
488*7977e686Schristos 	newtbl.td_data = calloc ((size_t) total_len, newsz);
489*7977e686Schristos 	newtbl.td_flags = (flex_uint16_t)
490*7977e686Schristos 		(TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz));
49130da1778Schristos 
49230da1778Schristos 	for (i = 0; i < total_len; i++) {
49330da1778Schristos 		flex_int32_t g;
49430da1778Schristos 
49530da1778Schristos 		g = yytbl_data_geti (tbl, i);
49630da1778Schristos 		yytbl_data_seti (&newtbl, i, g);
49730da1778Schristos 	}
49830da1778Schristos 
49930da1778Schristos 
50030da1778Schristos 	/* Now copy over the old table */
50130da1778Schristos 	free (tbl->td_data);
50230da1778Schristos 	*tbl = newtbl;
50330da1778Schristos }
50430da1778Schristos 
50530da1778Schristos /* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */
506