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