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