1219019Sgabor/* $FreeBSD: stable/11/usr.bin/mkesdb/yacc.y 330449 2018-03-05 07:26:05Z eadler $ */ 2219019Sgabor/* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $ */ 3219019Sgabor 4219019Sgabor%{ 5219019Sgabor/*- 6330449Seadler * SPDX-License-Identifier: BSD-2-Clause 7330449Seadler * 8219019Sgabor * Copyright (c)2003 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#include <sys/queue.h> 36219019Sgabor 37219019Sgabor#include <assert.h> 38219019Sgabor#include <err.h> 39219019Sgabor#include <errno.h> 40219019Sgabor#include <limits.h> 41219019Sgabor#include <stdio.h> 42219019Sgabor#include <stdlib.h> 43219019Sgabor#include <string.h> 44219019Sgabor#include <unistd.h> 45219019Sgabor 46219019Sgabor#include "citrus_namespace.h" 47219019Sgabor#include "citrus_types.h" 48219019Sgabor#include "citrus_region.h" 49219019Sgabor#include "citrus_esdb_file.h" 50219019Sgabor#include "citrus_db_hash.h" 51219019Sgabor#include "citrus_db_factory.h" 52219019Sgabor#include "citrus_lookup_factory.h" 53219019Sgabor 54219019Sgabor#include "ldef.h" 55219019Sgabor 56219019Sgaborextern FILE *yyin; 57219019Sgabor 58219019Sgaborstatic struct named_csid_list named_csids; 59219019Sgaborstatic char *encoding, *name, *output = NULL, *variable; 60219019Sgaborstatic u_int32_t invalid; 61219019Sgaborstatic int debug = 0, num_csids = 0, use_invalid = 0; 62219019Sgabor 63219019Sgaborstatic void dump_file(void); 64219019Sgaborstatic void register_named_csid(char *, u_int32_t); 65219019Sgaborstatic void set_invalid(u_int32_t); 66219019Sgaborstatic void set_prop_string(const char *, char **, char **); 67219019Sgabor%} 68219019Sgabor%union { 69219019Sgabor u_int32_t i_value; 70219019Sgabor char *s_value; 71219019Sgabor} 72219019Sgabor 73219019Sgabor%token R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID 74219019Sgabor%token R_LN 75219019Sgabor%token <i_value> L_IMM 76219019Sgabor%token <s_value> L_STRING 77219019Sgabor 78219019Sgabor%% 79219019Sgabor 80219019Sgaborfile : property 81219019Sgabor { dump_file(); } 82219019Sgabor 83219019Sgaborproperty : /* empty */ 84219019Sgabor | property R_LN 85219019Sgabor | property name R_LN 86219019Sgabor | property encoding R_LN 87219019Sgabor | property variable R_LN 88219019Sgabor | property defcsid R_LN 89219019Sgabor | property invalid R_LN 90219019Sgabor 91219019Sgaborname : R_NAME L_STRING 92219019Sgabor { 93219019Sgabor set_prop_string("NAME", &name, &$2); 94219019Sgabor } 95219019Sgabor 96219019Sgaborencoding : R_ENCODING L_STRING 97219019Sgabor { 98219019Sgabor set_prop_string("ENCODING", &encoding, &$2); 99219019Sgabor } 100219019Sgaborvariable : R_VARIABLE L_STRING 101219019Sgabor { 102219019Sgabor set_prop_string("VARIABLE", &variable, &$2); 103219019Sgabor } 104219019Sgabordefcsid : R_DEFCSID L_STRING L_IMM 105219019Sgabor { 106219019Sgabor register_named_csid($2, $3); 107219019Sgabor $2 = NULL; 108219019Sgabor } 109219019Sgaborinvalid : R_INVALID L_IMM 110219019Sgabor { 111219019Sgabor set_invalid($2); 112219019Sgabor } 113219019Sgabor%% 114219019Sgabor 115219019Sgaborint 116219019Sgaboryyerror(const char *s) 117219019Sgabor{ 118219019Sgabor 119250984Sed fprintf(stderr, "%s in %d\n", s, linenumber); 120219019Sgabor 121219019Sgabor return (0); 122219019Sgabor} 123219019Sgabor 124219019Sgabor#define CHKERR(ret, func, a) \ 125219019Sgabordo { \ 126219019Sgabor ret = func a; \ 127219019Sgabor if (ret) \ 128219019Sgabor errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \ 129219019Sgabor} while (/*CONSTCOND*/0) 130219019Sgaborstatic void 131219019Sgabordump_file(void) 132219019Sgabor{ 133219019Sgabor struct _db_factory *df; 134219019Sgabor struct _region data; 135219019Sgabor struct named_csid *csid; 136219019Sgabor FILE *fp; 137219019Sgabor char buf[100]; 138219019Sgabor void *serialized; 139219019Sgabor size_t size; 140219019Sgabor int i, ret; 141219019Sgabor 142219019Sgabor ret = 0; 143219019Sgabor if (!name) { 144219019Sgabor fprintf(stderr, "NAME is mandatory.\n"); 145219019Sgabor ret = 1; 146219019Sgabor } 147219019Sgabor if (!encoding) { 148219019Sgabor fprintf(stderr, "ENCODING is mandatory.\n"); 149219019Sgabor ret = 1; 150219019Sgabor } 151219019Sgabor if (ret) 152219019Sgabor exit(1); 153219019Sgabor 154219019Sgabor /* 155219019Sgabor * build database 156219019Sgabor */ 157219019Sgabor CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL)); 158219019Sgabor 159219019Sgabor /* store version */ 160219019Sgabor CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION, 161219019Sgabor _CITRUS_ESDB_VERSION)); 162219019Sgabor 163219019Sgabor /* store encoding */ 164219019Sgabor CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING, 165219019Sgabor encoding)); 166219019Sgabor 167219019Sgabor /* store variable */ 168219019Sgabor if (variable) 169219019Sgabor CHKERR(ret, _db_factory_addstr_by_s, 170219019Sgabor (df, _CITRUS_ESDB_SYM_VARIABLE, variable)); 171219019Sgabor 172219019Sgabor /* store invalid */ 173219019Sgabor if (use_invalid) 174219019Sgabor CHKERR(ret, _db_factory_add32_by_s, (df, 175219019Sgabor _CITRUS_ESDB_SYM_INVALID, invalid)); 176219019Sgabor 177219019Sgabor /* store num of charsets */ 178219019Sgabor CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS, 179219019Sgabor num_csids)); 180219019Sgabor i = 0; 181219019Sgabor STAILQ_FOREACH(csid, &named_csids, ci_entry) { 182219019Sgabor snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", 183219019Sgabor i); 184219019Sgabor CHKERR(ret, _db_factory_addstr_by_s, 185219019Sgabor (df, buf, csid->ci_symbol)); 186219019Sgabor snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d", 187219019Sgabor i); 188219019Sgabor CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid)); 189219019Sgabor i++; 190219019Sgabor } 191219019Sgabor 192219019Sgabor /* 193219019Sgabor * dump database to file 194219019Sgabor */ 195219019Sgabor fp = output ? fopen(output, "wb") : stdout; 196219019Sgabor if (fp == NULL) { 197219019Sgabor perror("fopen"); 198219019Sgabor exit(1); 199219019Sgabor } 200219019Sgabor 201219019Sgabor /* dump database body */ 202219019Sgabor size = _db_factory_calc_size(df); 203219019Sgabor serialized = malloc(size); 204219019Sgabor _region_init(&data, serialized, size); 205219019Sgabor CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data)); 206219019Sgabor if (fwrite(serialized, size, 1, fp) != 1) 207219019Sgabor err(EXIT_FAILURE, "fwrite"); 208219019Sgabor 209219019Sgabor fclose(fp); 210219019Sgabor} 211219019Sgabor 212219019Sgaborstatic void 213219019Sgaborset_prop_string(const char *res, char **store, char **data) 214219019Sgabor{ 215219019Sgabor char buf[256]; 216219019Sgabor 217219019Sgabor if (*store) { 218219019Sgabor snprintf(buf, sizeof(buf), 219219019Sgabor "%s is duplicated. ignored the one", res); 220219019Sgabor yyerror(buf); 221219019Sgabor return; 222219019Sgabor } 223219019Sgabor 224219019Sgabor *store = *data; 225219019Sgabor *data = NULL; 226219019Sgabor} 227219019Sgabor 228219019Sgaborstatic void 229219019Sgaborset_invalid(u_int32_t inv) 230219019Sgabor{ 231219019Sgabor 232219019Sgabor invalid = inv; 233219019Sgabor use_invalid = 1; 234219019Sgabor} 235219019Sgabor 236219019Sgaborstatic void 237219019Sgaborregister_named_csid(char *sym, u_int32_t val) 238219019Sgabor{ 239219019Sgabor struct named_csid *csid; 240219019Sgabor 241219019Sgabor STAILQ_FOREACH(csid, &named_csids, ci_entry) { 242219019Sgabor if (strcmp(csid->ci_symbol, sym) == 0) { 243219019Sgabor yyerror("multiply defined CSID"); 244219019Sgabor exit(1); 245219019Sgabor } 246219019Sgabor } 247219019Sgabor 248219019Sgabor csid = malloc(sizeof(*csid)); 249219019Sgabor if (csid == NULL) { 250219019Sgabor perror("malloc"); 251219019Sgabor exit(1); 252219019Sgabor } 253219019Sgabor csid->ci_symbol = sym; 254219019Sgabor csid->ci_csid = val; 255219019Sgabor STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry); 256219019Sgabor num_csids++; 257219019Sgabor} 258219019Sgabor 259219019Sgaborstatic void 260219019Sgabordo_mkdb(FILE *in) 261219019Sgabor{ 262219019Sgabor FILE *out; 263219019Sgabor int ret; 264219019Sgabor 265219019Sgabor /* dump DB to file */ 266219019Sgabor out = output ? fopen(output, "wb") : stdout; 267219019Sgabor if (out == NULL) 268219019Sgabor err(EXIT_FAILURE, "fopen"); 269219019Sgabor 270219019Sgabor ret = _lookup_factory_convert(out, in); 271219019Sgabor fclose(out); 272219019Sgabor if (ret && output) 273219019Sgabor unlink(output); /* dump failure */ 274219019Sgabor if (ret) 275219019Sgabor errx(EXIT_FAILURE, "%s\n", strerror(ret)); 276219019Sgabor} 277219019Sgabor 278219019Sgaborstatic void 279219019Sgaborusage(void) 280219019Sgabor{ 281219019Sgabor errx(EXIT_FAILURE, 282219019Sgabor "usage:\n" 283330325Seadler "\t%s [-d] [-o outfile] [infile]\n" 284330325Seadler "\t%s -m [-d] [-o outfile] [infile]", 285219019Sgabor getprogname(), getprogname()); 286219019Sgabor} 287219019Sgabor 288219019Sgaborint 289219019Sgabormain(int argc, char **argv) 290219019Sgabor{ 291219019Sgabor FILE *in = NULL; 292219019Sgabor int ch, mkdb = 0; 293219019Sgabor 294219019Sgabor while ((ch = getopt(argc, argv, "do:m")) != EOF) { 295219019Sgabor switch (ch) { 296219019Sgabor case 'd': 297219019Sgabor debug = 1; 298219019Sgabor break; 299219019Sgabor case 'o': 300219019Sgabor output = strdup(optarg); 301219019Sgabor break; 302219019Sgabor case 'm': 303219019Sgabor mkdb = 1; 304219019Sgabor break; 305219019Sgabor default: 306219019Sgabor usage(); 307219019Sgabor } 308219019Sgabor } 309219019Sgabor 310219019Sgabor argc -= optind; 311219019Sgabor argv += optind; 312219019Sgabor switch (argc) { 313219019Sgabor case 0: 314219019Sgabor in = stdin; 315219019Sgabor break; 316219019Sgabor case 1: 317219019Sgabor in = fopen(argv[0], "r"); 318219019Sgabor if (!in) 319219019Sgabor err(EXIT_FAILURE, "%s", argv[0]); 320219019Sgabor break; 321219019Sgabor default: 322219019Sgabor usage(); 323219019Sgabor } 324219019Sgabor 325219019Sgabor if (mkdb) 326219019Sgabor do_mkdb(in); 327219019Sgabor else { 328219019Sgabor STAILQ_INIT(&named_csids); 329219019Sgabor yyin = in; 330219019Sgabor yyparse(); 331219019Sgabor } 332219019Sgabor 333219019Sgabor return (0); 334219019Sgabor} 335