1219019Sgabor/* $FreeBSD: stable/11/usr.bin/mkcsmapper/yacc.y 330449 2018-03-05 07:26:05Z eadler $ */
2307794Sbapt/*     $NetBSD: yacc.y,v 1.11 2016/06/28 09:22:16 wiz Exp $    */
3219019Sgabor
4219019Sgabor%{
5219019Sgabor/*-
6330449Seadler * SPDX-License-Identifier: BSD-2-Clause
7330449Seadler *
8219019Sgabor * Copyright (c)2003, 2006 Citrus Project,
9219019Sgabor * All rights reserved.
10219019Sgabor *
11219019Sgabor * Redistribution and use in source and binary forms, with or without
12219019Sgabor * modification, are permitted provided that the following conditions
13219019Sgabor * are met:
14219019Sgabor * 1. Redistributions of source code must retain the above copyright
15219019Sgabor *    notice, this list of conditions and the following disclaimer.
16219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright
17219019Sgabor *    notice, this list of conditions and the following disclaimer in the
18219019Sgabor *    documentation and/or other materials provided with the distribution.
19219019Sgabor *
20219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21219019Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23219019Sgabor * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24219019Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28219019Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29219019Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30219019Sgabor * SUCH DAMAGE.
31219019Sgabor */
32219019Sgabor
33219019Sgabor#include <sys/cdefs.h>
34219019Sgabor#include <sys/types.h>
35219019Sgabor
36219019Sgabor#include <assert.h>
37219019Sgabor#include <err.h>
38219019Sgabor#include <errno.h>
39219019Sgabor#include <limits.h>
40219019Sgabor#include <stdio.h>
41219019Sgabor#include <stdlib.h>
42219019Sgabor#include <string.h>
43219019Sgabor#include <unistd.h>
44219019Sgabor#include <arpa/inet.h>
45219019Sgabor
46219019Sgabor#include "ldef.h"
47219019Sgabor
48219019Sgabor#ifndef __packed
49219019Sgabor#define __packed
50219019Sgabor#endif
51219019Sgabor
52219019Sgabor#include "citrus_namespace.h"
53219019Sgabor#include "citrus_types.h"
54219019Sgabor#include "citrus_mapper_std_file.h"
55219019Sgabor#include "citrus_region.h"
56219019Sgabor#include "citrus_db_factory.h"
57219019Sgabor#include "citrus_db_hash.h"
58219019Sgabor#include "citrus_lookup_factory.h"
59219019Sgabor#include "citrus_pivot_factory.h"
60219019Sgabor
61219019Sgaborextern FILE		*yyin;
62219019Sgabor
63219019Sgaborint			 debug = 0;
64219019Sgabor
65219019Sgaborstatic linear_zone_t	 rowcol[_CITRUS_MAPPER_STD_ROWCOL_MAX];
66219019Sgaborstatic char		*map_name;
67219019Sgaborstatic char		*output = NULL;
68219019Sgaborstatic void		*table = NULL;
69219019Sgaborstatic size_t		 rowcol_len = 0;
70219019Sgaborstatic size_t		 table_size;
71219019Sgaborstatic u_int32_t	 done_flag = 0;
72219019Sgaborstatic u_int32_t	 dst_ilseq, dst_invalid, dst_unit_bits, oob_mode;
73219019Sgaborstatic u_int32_t	 rowcol_bits = 0, rowcol_mask = 0;
74219019Sgaborstatic u_int32_t	 src_next;
75219019Sgaborstatic int		 map_type;
76219019Sgaborstatic void		 (*putfunc)(void *, size_t, u_int32_t) = NULL;
77219019Sgabor
78219019Sgabor#define DF_TYPE			0x00000001
79219019Sgabor#define DF_NAME			0x00000002
80219019Sgabor#define DF_SRC_ZONE		0x00000004
81219019Sgabor#define DF_DST_INVALID		0x00000008
82219019Sgabor#define DF_DST_ILSEQ		0x00000010
83219019Sgabor#define DF_DST_UNIT_BITS	0x00000020
84219019Sgabor#define DF_OOB_MODE		0x00000040
85219019Sgabor
86219019Sgaborstatic void	dump_file(void);
87219019Sgaborstatic void	setup_map(void);
88219019Sgaborstatic void	set_type(int);
89219019Sgaborstatic void	set_name(char *);
90219019Sgaborstatic void	set_src_zone(u_int32_t);
91219019Sgaborstatic void	set_dst_invalid(u_int32_t);
92219019Sgaborstatic void	set_dst_ilseq(u_int32_t);
93219019Sgaborstatic void	set_dst_unit_bits(u_int32_t);
94219019Sgaborstatic void	set_oob_mode(u_int32_t);
95219019Sgaborstatic int	check_src(u_int32_t, u_int32_t);
96219019Sgaborstatic void	store(const linear_zone_t *, u_int32_t, int);
97219019Sgaborstatic void	put8(void *, size_t, u_int32_t);
98219019Sgaborstatic void	put16(void *, size_t, u_int32_t);
99219019Sgaborstatic void	put32(void *, size_t, u_int32_t);
100219019Sgaborstatic void	set_range(u_int32_t, u_int32_t);
101219019Sgaborstatic void	set_src(linear_zone_t *, u_int32_t, u_int32_t);
102219019Sgabor%}
103219019Sgabor
104219019Sgabor%union {
105219019Sgabor	u_int32_t	 i_value;
106219019Sgabor	char		*s_value;
107219019Sgabor	linear_zone_t	 lz_value;
108219019Sgabor}
109219019Sgabor
110219019Sgabor%token			R_TYPE R_NAME R_SRC_ZONE R_DST_UNIT_BITS
111219019Sgabor%token			R_DST_INVALID R_DST_ILSEQ
112219019Sgabor%token			R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL
113219019Sgabor%token			R_ILSEQ R_OOB_MODE
114219019Sgabor%token			R_LN
115219019Sgabor%token <i_value>	L_IMM
116219019Sgabor%token <s_value>	L_STRING
117219019Sgabor
118219019Sgabor%type <lz_value>	src
119219019Sgabor%type <i_value>		dst types oob_mode_sel zone
120219019Sgabor
121219019Sgabor%%
122219019Sgabor
123219019Sgaborfile		: property mapping lns
124219019Sgabor		{ dump_file(); }
125219019Sgabor
126219019Sgaborproperty	: /* empty */
127219019Sgabor		| property R_LN
128219019Sgabor		| property name
129219019Sgabor		| property type
130219019Sgabor		| property src_zone
131219019Sgabor		| property dst_invalid
132219019Sgabor		| property dst_ilseq
133219019Sgabor		| property dst_unit_bits
134219019Sgabor		| property oob_mode
135219019Sgabor
136219019Sgaborname		: R_NAME L_STRING { set_name($2); $2 = NULL; }
137219019Sgabortype		: R_TYPE types { set_type($2); }
138219019Sgabortypes		: R_ROWCOL { $$ = R_ROWCOL; }
139219019Sgaborrange		: L_IMM '-' L_IMM { set_range($1, $3); }
140219019Sgabor
141219019Sgaborranges		: /* empty */
142219019Sgabor		| ranges range '/'
143219019Sgabor
144219019Sgaborsrc_zone	: R_SRC_ZONE zone { set_src_zone($2); }
145219019Sgaborzone		: range {
146219019Sgabor			$$ = 32;
147219019Sgabor		}
148219019Sgabor		| range '/' range '/' ranges L_IMM {
149219019Sgabor			$$ = $6;
150219019Sgabor		}
151219019Sgabor
152219019Sgabordst_invalid	: R_DST_INVALID L_IMM { set_dst_invalid($2); }
153219019Sgabordst_ilseq	: R_DST_ILSEQ L_IMM { set_dst_ilseq($2); }
154219019Sgabordst_unit_bits	: R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); }
155219019Sgaboroob_mode	: R_OOB_MODE oob_mode_sel { set_oob_mode($2); }
156219019Sgabor
157219019Sgaboroob_mode_sel	: R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; }
158219019Sgabor		| R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; }
159219019Sgabor
160219019Sgabormapping		: begin_map map_elems R_END_MAP
161219019Sgaborbegin_map	: R_BEGIN_MAP lns { setup_map(); }
162219019Sgabor
163219019Sgabormap_elems	: /* empty */
164219019Sgabor		| map_elems map_elem lns
165219019Sgabor
166219019Sgabormap_elem	: src '=' dst
167219019Sgabor		{ store(&$1, $3, 0); }
168219019Sgabor		| src '=' L_IMM '-'
169219019Sgabor		{ store(&$1, $3, 1); }
170219019Sgabordst		: L_IMM
171219019Sgabor		{
172219019Sgabor			$$ = $1;
173219019Sgabor		}
174219019Sgabor		| R_INVALID
175219019Sgabor		{
176219019Sgabor			$$ = dst_invalid;
177219019Sgabor		}
178219019Sgabor		| R_ILSEQ
179219019Sgabor		{
180219019Sgabor			$$ = dst_ilseq;
181219019Sgabor		}
182219019Sgabor
183219019Sgaborsrc		: /* empty */
184219019Sgabor		{
185219019Sgabor			set_src(&$$, src_next, src_next);
186219019Sgabor		}
187219019Sgabor		| L_IMM
188219019Sgabor		{
189219019Sgabor			set_src(&$$, $1, $1);
190219019Sgabor		}
191219019Sgabor		| L_IMM '-' L_IMM
192219019Sgabor		{
193219019Sgabor			set_src(&$$, $1, $3);
194219019Sgabor		}
195219019Sgabor		| '-' L_IMM
196219019Sgabor		{
197219019Sgabor			set_src(&$$, src_next, $2);
198219019Sgabor		}
199219019Sgaborlns		: R_LN
200219019Sgabor		| lns R_LN
201219019Sgabor
202219019Sgabor%%
203219019Sgabor
204219019Sgaborstatic void
205219019Sgaborwarning(const char *s)
206219019Sgabor{
207219019Sgabor
208250984Sed	fprintf(stderr, "%s in %d\n", s, linenumber);
209219019Sgabor}
210219019Sgabor
211219019Sgaborint
212219019Sgaboryyerror(const char *s)
213219019Sgabor{
214219019Sgabor
215219019Sgabor	warning(s);
216219019Sgabor	exit(1);
217219019Sgabor}
218219019Sgabor
219219019Sgaborvoid
220219019Sgaborput8(void *ptr, size_t ofs, u_int32_t val)
221219019Sgabor{
222219019Sgabor
223219019Sgabor	*((u_int8_t *)ptr + ofs) = val;
224219019Sgabor}
225219019Sgabor
226219019Sgaborvoid
227219019Sgaborput16(void *ptr, size_t ofs, u_int32_t val)
228219019Sgabor{
229219019Sgabor
230219019Sgabor	u_int16_t oval = htons(val);
231219019Sgabor	memcpy((u_int16_t *)ptr + ofs, &oval, 2);
232219019Sgabor}
233219019Sgabor
234219019Sgaborvoid
235219019Sgaborput32(void *ptr, size_t ofs, u_int32_t val)
236219019Sgabor{
237219019Sgabor
238219019Sgabor	u_int32_t oval = htonl(val);
239219019Sgabor	memcpy((u_int32_t *)ptr + ofs, &oval, 4);
240219019Sgabor}
241219019Sgabor
242219019Sgaborstatic void
243219019Sgaboralloc_table(void)
244219019Sgabor{
245219019Sgabor	linear_zone_t *p;
246219019Sgabor	size_t i;
247219019Sgabor	uint32_t val = 0;
248219019Sgabor
249219019Sgabor	i = rowcol_len;
250219019Sgabor	p = &rowcol[--i];
251219019Sgabor	table_size = p->width;
252219019Sgabor	while (i > 0) {
253219019Sgabor		p = &rowcol[--i];
254219019Sgabor		table_size *= p->width;
255219019Sgabor	}
256219019Sgabor	table = (void *)malloc(table_size * dst_unit_bits / 8);
257219019Sgabor	if (table == NULL) {
258219019Sgabor		perror("malloc");
259219019Sgabor		exit(1);
260219019Sgabor	}
261219019Sgabor
262219019Sgabor	switch (oob_mode) {
263219019Sgabor	case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
264219019Sgabor		val = dst_invalid;
265219019Sgabor		break;
266219019Sgabor	case _CITRUS_MAPPER_STD_OOB_ILSEQ:
267219019Sgabor		val = dst_ilseq;
268219019Sgabor		break;
269219019Sgabor	default:
270219019Sgabor		break;
271219019Sgabor	}
272219019Sgabor	for (i = 0; i < table_size; i++)
273219019Sgabor		(*putfunc)(table, i, val);
274219019Sgabor}
275219019Sgabor
276219019Sgaborstatic void
277219019Sgaborsetup_map(void)
278219019Sgabor{
279219019Sgabor
280219019Sgabor	if ((done_flag & DF_SRC_ZONE)==0) {
281219019Sgabor		fprintf(stderr, "SRC_ZONE is mandatory.\n");
282219019Sgabor		exit(1);
283219019Sgabor	}
284219019Sgabor	if ((done_flag & DF_DST_UNIT_BITS)==0) {
285219019Sgabor		fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
286219019Sgabor		exit(1);
287219019Sgabor	}
288219019Sgabor
289219019Sgabor	if ((done_flag & DF_DST_INVALID) == 0)
290219019Sgabor		dst_invalid = 0xFFFFFFFF;
291219019Sgabor	if ((done_flag & DF_DST_ILSEQ) == 0)
292219019Sgabor		dst_ilseq = 0xFFFFFFFE;
293219019Sgabor	if ((done_flag & DF_OOB_MODE) == 0)
294219019Sgabor		oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
295219019Sgabor
296219019Sgabor	alloc_table();
297219019Sgabor}
298219019Sgabor
299219019Sgaborstatic void
300219019Sgaborcreate_rowcol_info(struct _region *r)
301219019Sgabor{
302219019Sgabor	void *ptr;
303219019Sgabor	size_t i, len, ofs;
304219019Sgabor
305219019Sgabor	ofs = 0;
306219019Sgabor	ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
307219019Sgabor	if (ptr == NULL)
308219019Sgabor		err(EXIT_FAILURE, "malloc");
309219019Sgabor	put32(ptr, ofs, rowcol_bits); ofs++;
310219019Sgabor	put32(ptr, ofs, dst_invalid); ofs++;
311219019Sgabor
312219019Sgabor	/* XXX: keep backward compatibility */
313219019Sgabor	switch (rowcol_len) {
314219019Sgabor	case 1:
315219019Sgabor		put32(ptr, ofs, 0); ofs++;
316219019Sgabor		put32(ptr, ofs, 0); ofs++;
317219019Sgabor	/*FALLTHROUGH*/
318219019Sgabor	case 2:
319219019Sgabor		len = 0;
320219019Sgabor		break;
321219019Sgabor	default:
322219019Sgabor		len = rowcol_len;
323219019Sgabor	}
324219019Sgabor	for (i = 0; i < rowcol_len; ++i) {
325219019Sgabor		put32(ptr, ofs, rowcol[i].begin); ofs++;
326219019Sgabor		put32(ptr, ofs, rowcol[i].end); ofs++;
327219019Sgabor	}
328219019Sgabor	put32(ptr, ofs, dst_unit_bits); ofs++;
329219019Sgabor	put32(ptr, ofs, len); ofs++;
330219019Sgabor
331219019Sgabor	_region_init(r, ptr, ofs * 4);
332219019Sgabor}
333219019Sgabor
334219019Sgabor
335219019Sgaborstatic void
336219019Sgaborcreate_rowcol_ext_ilseq_info(struct _region *r)
337219019Sgabor{
338219019Sgabor	void *ptr;
339219019Sgabor	size_t ofs;
340219019Sgabor
341219019Sgabor	ofs = 0;
342219019Sgabor	ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
343219019Sgabor	if (ptr == NULL)
344219019Sgabor		err(EXIT_FAILURE, "malloc");
345219019Sgabor
346219019Sgabor	put32(ptr, ofs, oob_mode); ofs++;
347219019Sgabor	put32(ptr, ofs, dst_ilseq); ofs++;
348219019Sgabor
349219019Sgabor	_region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
350219019Sgabor}
351219019Sgabor
352219019Sgabor#define CHKERR(ret, func, a)						\
353219019Sgabordo {									\
354219019Sgabor	ret = func a;							\
355219019Sgabor	if (ret)							\
356219019Sgabor		errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret));	\
357219019Sgabor} while (/*CONSTCOND*/0)
358219019Sgabor
359219019Sgaborstatic void
360219019Sgabordump_file(void)
361219019Sgabor{
362219019Sgabor	struct _db_factory *df;
363219019Sgabor	struct _region data;
364219019Sgabor	void *serialized;
365219019Sgabor	FILE *fp;
366219019Sgabor	size_t size;
367219019Sgabor	int ret;
368219019Sgabor
369219019Sgabor	/*
370219019Sgabor	 * build database
371219019Sgabor	 */
372219019Sgabor	CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
373219019Sgabor
374219019Sgabor	/* store type */
375219019Sgabor	CHKERR(ret, _db_factory_addstr_by_s,
376219019Sgabor	    (df, _CITRUS_MAPPER_STD_SYM_TYPE, _CITRUS_MAPPER_STD_TYPE_ROWCOL));
377219019Sgabor
378219019Sgabor	/* store info */
379219019Sgabor	create_rowcol_info(&data);
380219019Sgabor	CHKERR(ret, _db_factory_add_by_s,
381219019Sgabor	    (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1));
382219019Sgabor
383219019Sgabor	/* ilseq extension */
384219019Sgabor	create_rowcol_ext_ilseq_info(&data);
385219019Sgabor	CHKERR(ret, _db_factory_add_by_s,
386219019Sgabor	    (df, _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &data, 1));
387219019Sgabor
388219019Sgabor	/* store table */
389219019Sgabor	_region_init(&data, table, table_size*dst_unit_bits/8);
390219019Sgabor	CHKERR(ret, _db_factory_add_by_s,
391219019Sgabor	    (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1));
392219019Sgabor
393219019Sgabor	/*
394219019Sgabor	 * dump database to file
395219019Sgabor	 */
396219019Sgabor	fp = output ? fopen(output, "wb") : stdout;
397219019Sgabor
398219019Sgabor	if (fp == NULL) {
399219019Sgabor		perror("fopen");
400219019Sgabor		exit(1);
401219019Sgabor	}
402219019Sgabor
403219019Sgabor	/* dump database body */
404219019Sgabor	size = _db_factory_calc_size(df);
405219019Sgabor	serialized = malloc(size);
406219019Sgabor	_region_init(&data, serialized, size);
407219019Sgabor	CHKERR(ret, _db_factory_serialize,
408219019Sgabor	    (df, _CITRUS_MAPPER_STD_MAGIC, &data));
409219019Sgabor	if (fwrite(serialized, size, 1, fp) != 1)
410219019Sgabor		err(EXIT_FAILURE, "fwrite");
411219019Sgabor
412219019Sgabor	fclose(fp);
413219019Sgabor}
414219019Sgabor
415219019Sgaborstatic void
416219019Sgabor/*ARGSUSED*/
417219019Sgaborset_type(int type)
418219019Sgabor{
419219019Sgabor
420219019Sgabor	if (done_flag & DF_TYPE) {
421219019Sgabor		warning("TYPE is duplicated. ignored this one");
422219019Sgabor		return;
423219019Sgabor	}
424219019Sgabor
425219019Sgabor	map_type = type;
426219019Sgabor
427219019Sgabor	done_flag |= DF_TYPE;
428219019Sgabor}
429219019Sgabor
430219019Sgaborstatic void
431219019Sgabor/*ARGSUSED*/
432219019Sgaborset_name(char *str)
433219019Sgabor{
434219019Sgabor
435219019Sgabor	if (done_flag & DF_NAME) {
436219019Sgabor		warning("NAME is duplicated. ignored this one");
437219019Sgabor		return;
438219019Sgabor	}
439219019Sgabor
440219019Sgabor	map_name = str;
441219019Sgabor
442219019Sgabor	done_flag |= DF_NAME;
443219019Sgabor}
444219019Sgabor
445219019Sgaborstatic void
446219019Sgaborset_src_zone(u_int32_t val)
447219019Sgabor{
448219019Sgabor	linear_zone_t *p;
449219019Sgabor	size_t i;
450219019Sgabor
451219019Sgabor	if (done_flag & DF_SRC_ZONE) {
452219019Sgabor		warning("SRC_ZONE is duplicated. ignored this one");
453219019Sgabor		return;
454219019Sgabor	}
455219019Sgabor	rowcol_bits = val;
456219019Sgabor
457219019Sgabor	/* sanity check */
458219019Sgabor	switch (rowcol_bits) {
459219019Sgabor	case 8: case 16: case 32:
460219019Sgabor		if (rowcol_len <= 32 / rowcol_bits)
461219019Sgabor			break;
462219019Sgabor	/*FALLTHROUGH*/
463219019Sgabor	default:
464219019Sgabor		goto bad;
465219019Sgabor	}
466219019Sgabor	rowcol_mask = 1 << (rowcol_bits - 1);
467219019Sgabor	rowcol_mask |= rowcol_mask - 1;
468219019Sgabor	for (i = 0; i < rowcol_len; ++i) {
469219019Sgabor		p = &rowcol[i];
470219019Sgabor		if (p->end > rowcol_mask)
471219019Sgabor			goto bad;
472219019Sgabor	}
473219019Sgabor	done_flag |= DF_SRC_ZONE;
474219019Sgabor	return;
475219019Sgabor
476219019Sgaborbad:
477219019Sgabor	yyerror("Illegal argument for SRC_ZONE");
478219019Sgabor}
479219019Sgabor
480219019Sgaborstatic void
481219019Sgaborset_dst_invalid(u_int32_t val)
482219019Sgabor{
483219019Sgabor
484219019Sgabor	if (done_flag & DF_DST_INVALID) {
485219019Sgabor		warning("DST_INVALID is duplicated. ignored this one");
486219019Sgabor		return;
487219019Sgabor	}
488219019Sgabor
489219019Sgabor	dst_invalid = val;
490219019Sgabor
491219019Sgabor	done_flag |= DF_DST_INVALID;
492219019Sgabor}
493219019Sgabor
494219019Sgaborstatic void
495219019Sgaborset_dst_ilseq(u_int32_t val)
496219019Sgabor{
497219019Sgabor
498219019Sgabor	if (done_flag & DF_DST_ILSEQ) {
499219019Sgabor		warning("DST_ILSEQ is duplicated. ignored this one");
500219019Sgabor		return;
501219019Sgabor	}
502219019Sgabor
503219019Sgabor	dst_ilseq = val;
504219019Sgabor
505219019Sgabor	done_flag |= DF_DST_ILSEQ;
506219019Sgabor}
507219019Sgabor
508219019Sgaborstatic void
509219019Sgaborset_oob_mode(u_int32_t val)
510219019Sgabor{
511219019Sgabor
512219019Sgabor	if (done_flag & DF_OOB_MODE) {
513219019Sgabor		warning("OOB_MODE is duplicated. ignored this one");
514219019Sgabor		return;
515219019Sgabor	}
516219019Sgabor
517219019Sgabor	oob_mode = val;
518219019Sgabor
519219019Sgabor	done_flag |= DF_OOB_MODE;
520219019Sgabor}
521219019Sgabor
522219019Sgaborstatic void
523219019Sgaborset_dst_unit_bits(u_int32_t val)
524219019Sgabor{
525219019Sgabor
526219019Sgabor	if (done_flag & DF_DST_UNIT_BITS) {
527219019Sgabor		warning("DST_UNIT_BITS is duplicated. ignored this one");
528219019Sgabor		return;
529219019Sgabor	}
530219019Sgabor
531219019Sgabor	switch (val) {
532219019Sgabor	case 8:
533219019Sgabor		putfunc = &put8;
534219019Sgabor		dst_unit_bits = val;
535219019Sgabor		break;
536219019Sgabor	case 16:
537219019Sgabor		putfunc = &put16;
538219019Sgabor		dst_unit_bits = val;
539219019Sgabor		break;
540219019Sgabor	case 32:
541219019Sgabor		putfunc = &put32;
542219019Sgabor		dst_unit_bits = val;
543219019Sgabor		break;
544219019Sgabor	default:
545219019Sgabor		yyerror("Illegal argument for DST_UNIT_BITS");
546219019Sgabor	}
547219019Sgabor	done_flag |= DF_DST_UNIT_BITS;
548219019Sgabor}
549219019Sgabor
550219019Sgaborstatic int
551219019Sgaborcheck_src(u_int32_t begin, u_int32_t end)
552219019Sgabor{
553219019Sgabor	linear_zone_t *p;
554219019Sgabor	size_t i;
555219019Sgabor	u_int32_t m, n;
556219019Sgabor
557219019Sgabor	if (begin > end)
558219019Sgabor		return (1);
559219019Sgabor	if (begin < end) {
560219019Sgabor		m = begin & ~rowcol_mask;
561219019Sgabor		n = end & ~rowcol_mask;
562219019Sgabor		if (m != n)
563219019Sgabor			return (1);
564219019Sgabor	}
565219019Sgabor	for (i = rowcol_len * rowcol_bits, p = &rowcol[0]; i > 0; ++p) {
566219019Sgabor		i -= rowcol_bits;
567219019Sgabor		m = (begin >> i) & rowcol_mask;
568219019Sgabor		if (m < p->begin || m > p->end)
569219019Sgabor			return (1);
570219019Sgabor	}
571219019Sgabor	if (begin < end) {
572219019Sgabor		n = end & rowcol_mask;
573219019Sgabor		--p;
574219019Sgabor		if (n < p->begin || n > p->end)
575219019Sgabor			return (1);
576219019Sgabor	}
577219019Sgabor	return (0);
578219019Sgabor}
579219019Sgabor
580219019Sgaborstatic void
581219019Sgaborstore(const linear_zone_t *lz, u_int32_t dst, int inc)
582219019Sgabor{
583219019Sgabor	linear_zone_t *p;
584219019Sgabor	size_t i, ofs;
585219019Sgabor	u_int32_t n;
586219019Sgabor
587219019Sgabor	ofs = 0;
588219019Sgabor	for (i = rowcol_len * rowcol_bits, p = &rowcol[0]; i > 0; ++p) {
589219019Sgabor		i -= rowcol_bits;
590219019Sgabor		n = ((lz->begin >> i) & rowcol_mask) - p->begin;
591219019Sgabor		ofs = (ofs * p->width) + n;
592219019Sgabor	}
593219019Sgabor	n = lz->width;
594219019Sgabor	while (n-- > 0) {
595219019Sgabor		(*putfunc)(table, ofs++, dst);
596219019Sgabor		if (inc)
597219019Sgabor			dst++;
598219019Sgabor	}
599219019Sgabor}
600219019Sgabor
601219019Sgaborstatic void
602219019Sgaborset_range(u_int32_t begin, u_int32_t end)
603219019Sgabor{
604219019Sgabor	linear_zone_t *p;
605219019Sgabor
606219019Sgabor	if (rowcol_len >= _CITRUS_MAPPER_STD_ROWCOL_MAX)
607219019Sgabor		goto bad;
608219019Sgabor	p = &rowcol[rowcol_len++];
609219019Sgabor
610219019Sgabor	if (begin > end)
611219019Sgabor		goto bad;
612219019Sgabor	p->begin = begin, p->end = end;
613219019Sgabor	p->width = end - begin + 1;
614219019Sgabor
615219019Sgabor	return;
616219019Sgabor
617219019Sgaborbad:
618219019Sgabor	yyerror("Illegal argument for SRC_ZONE");
619219019Sgabor}
620219019Sgabor
621219019Sgaborstatic void
622219019Sgaborset_src(linear_zone_t *lz, u_int32_t begin, u_int32_t end)
623219019Sgabor{
624219019Sgabor
625219019Sgabor	if (check_src(begin, end) != 0)
626219019Sgabor		yyerror("illegal zone");
627219019Sgabor
628219019Sgabor	lz->begin = begin, lz->end = end;
629219019Sgabor	lz->width = end - begin + 1;
630219019Sgabor
631219019Sgabor	src_next = end + 1;
632219019Sgabor}
633219019Sgabor
634219019Sgaborstatic void
635219019Sgabordo_mkdb(FILE *in)
636219019Sgabor{
637219019Sgabor	FILE *out;
638219019Sgabor	int ret;
639219019Sgabor
640219019Sgabor        /* dump DB to file */
641219019Sgabor	out = output ? fopen(output, "wb") : stdout;
642219019Sgabor
643219019Sgabor	if (out == NULL)
644219019Sgabor		err(EXIT_FAILURE, "fopen");
645219019Sgabor
646219019Sgabor	ret = _lookup_factory_convert(out, in);
647219019Sgabor	fclose(out);
648219019Sgabor	if (ret && output)
649219019Sgabor		unlink(output); /* dump failure */
650219019Sgabor}
651219019Sgabor
652219019Sgaborstatic void
653219019Sgabordo_mkpv(FILE *in)
654219019Sgabor{
655219019Sgabor	FILE *out;
656219019Sgabor	int ret;
657219019Sgabor
658219019Sgabor        /* dump pivot to file */
659219019Sgabor	out = output ? fopen(output, "wb") : stdout;
660219019Sgabor
661219019Sgabor	if (out == NULL)
662219019Sgabor		err(EXIT_FAILURE, "fopen");
663219019Sgabor
664219019Sgabor	ret = _pivot_factory_convert(out, in);
665219019Sgabor	fclose(out);
666219019Sgabor	if (ret && output)
667219019Sgabor		unlink(output); /* dump failure */
668219019Sgabor	if (ret)
669308357Sbapt		errx(EXIT_FAILURE, "%s\n", strerror(ret));
670219019Sgabor}
671219019Sgabor
672219019Sgaborstatic void
673219019Sgaborusage(void)
674219019Sgabor{
675307794Sbapt	fprintf(stderr, "Usage: %s [-d] [-m|-p] [-o outfile] [infile]\n",
676307794Sbapt	    getprogname());
677307794Sbapt	exit(EXIT_FAILURE);
678219019Sgabor}
679219019Sgabor
680219019Sgaborint
681219019Sgabormain(int argc, char **argv)
682219019Sgabor{
683219019Sgabor	FILE *in = NULL;
684219019Sgabor	int ch, mkdb = 0, mkpv = 0;
685219019Sgabor
686219019Sgabor	while ((ch = getopt(argc, argv, "do:mp")) != EOF) {
687219019Sgabor		switch (ch) {
688219019Sgabor		case 'd':
689219019Sgabor			debug = 1;
690219019Sgabor			break;
691219019Sgabor		case 'o':
692219019Sgabor			output = strdup(optarg);
693219019Sgabor			break;
694219019Sgabor		case 'm':
695219019Sgabor			mkdb = 1;
696219019Sgabor			break;
697219019Sgabor		case 'p':
698219019Sgabor			mkpv = 1;
699219019Sgabor			break;
700219019Sgabor		default:
701219019Sgabor			usage();
702219019Sgabor		}
703219019Sgabor	}
704219019Sgabor
705219019Sgabor	argc -= optind;
706219019Sgabor	argv += optind;
707219019Sgabor	switch (argc) {
708219019Sgabor	case 0:
709219019Sgabor		in = stdin;
710219019Sgabor		break;
711219019Sgabor	case 1:
712219019Sgabor		in = fopen(argv[0], "r");
713219019Sgabor		if (!in)
714219019Sgabor			err(EXIT_FAILURE, "%s", argv[0]);
715219019Sgabor		break;
716219019Sgabor	default:
717219019Sgabor		usage();
718219019Sgabor	}
719219019Sgabor
720219019Sgabor	if (mkdb)
721219019Sgabor		do_mkdb(in);
722219019Sgabor	else if (mkpv)
723219019Sgabor		do_mkpv(in);
724219019Sgabor	else {
725219019Sgabor		yyin = in;
726219019Sgabor		yyparse();
727219019Sgabor	}
728219019Sgabor
729219019Sgabor	return (0);
730219019Sgabor}
731