1/* $FreeBSD: stable/11/usr.bin/mkesdb/yacc.y 330449 2018-03-05 07:26:05Z eadler $ */ 2/* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $ */ 3 4%{ 5/*- 6 * SPDX-License-Identifier: BSD-2-Clause 7 * 8 * Copyright (c)2003 Citrus Project, 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34#include <sys/types.h> 35#include <sys/queue.h> 36 37#include <assert.h> 38#include <err.h> 39#include <errno.h> 40#include <limits.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include <string.h> 44#include <unistd.h> 45 46#include "citrus_namespace.h" 47#include "citrus_types.h" 48#include "citrus_region.h" 49#include "citrus_esdb_file.h" 50#include "citrus_db_hash.h" 51#include "citrus_db_factory.h" 52#include "citrus_lookup_factory.h" 53 54#include "ldef.h" 55 56extern FILE *yyin; 57 58static struct named_csid_list named_csids; 59static char *encoding, *name, *output = NULL, *variable; 60static u_int32_t invalid; 61static int debug = 0, num_csids = 0, use_invalid = 0; 62 63static void dump_file(void); 64static void register_named_csid(char *, u_int32_t); 65static void set_invalid(u_int32_t); 66static void set_prop_string(const char *, char **, char **); 67%} 68%union { 69 u_int32_t i_value; 70 char *s_value; 71} 72 73%token R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID 74%token R_LN 75%token <i_value> L_IMM 76%token <s_value> L_STRING 77 78%% 79 80file : property 81 { dump_file(); } 82 83property : /* empty */ 84 | property R_LN 85 | property name R_LN 86 | property encoding R_LN 87 | property variable R_LN 88 | property defcsid R_LN 89 | property invalid R_LN 90 91name : R_NAME L_STRING 92 { 93 set_prop_string("NAME", &name, &$2); 94 } 95 96encoding : R_ENCODING L_STRING 97 { 98 set_prop_string("ENCODING", &encoding, &$2); 99 } 100variable : R_VARIABLE L_STRING 101 { 102 set_prop_string("VARIABLE", &variable, &$2); 103 } 104defcsid : R_DEFCSID L_STRING L_IMM 105 { 106 register_named_csid($2, $3); 107 $2 = NULL; 108 } 109invalid : R_INVALID L_IMM 110 { 111 set_invalid($2); 112 } 113%% 114 115int 116yyerror(const char *s) 117{ 118 119 fprintf(stderr, "%s in %d\n", s, linenumber); 120 121 return (0); 122} 123 124#define CHKERR(ret, func, a) \ 125do { \ 126 ret = func a; \ 127 if (ret) \ 128 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \ 129} while (/*CONSTCOND*/0) 130static void 131dump_file(void) 132{ 133 struct _db_factory *df; 134 struct _region data; 135 struct named_csid *csid; 136 FILE *fp; 137 char buf[100]; 138 void *serialized; 139 size_t size; 140 int i, ret; 141 142 ret = 0; 143 if (!name) { 144 fprintf(stderr, "NAME is mandatory.\n"); 145 ret = 1; 146 } 147 if (!encoding) { 148 fprintf(stderr, "ENCODING is mandatory.\n"); 149 ret = 1; 150 } 151 if (ret) 152 exit(1); 153 154 /* 155 * build database 156 */ 157 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL)); 158 159 /* store version */ 160 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION, 161 _CITRUS_ESDB_VERSION)); 162 163 /* store encoding */ 164 CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING, 165 encoding)); 166 167 /* store variable */ 168 if (variable) 169 CHKERR(ret, _db_factory_addstr_by_s, 170 (df, _CITRUS_ESDB_SYM_VARIABLE, variable)); 171 172 /* store invalid */ 173 if (use_invalid) 174 CHKERR(ret, _db_factory_add32_by_s, (df, 175 _CITRUS_ESDB_SYM_INVALID, invalid)); 176 177 /* store num of charsets */ 178 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS, 179 num_csids)); 180 i = 0; 181 STAILQ_FOREACH(csid, &named_csids, ci_entry) { 182 snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", 183 i); 184 CHKERR(ret, _db_factory_addstr_by_s, 185 (df, buf, csid->ci_symbol)); 186 snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d", 187 i); 188 CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid)); 189 i++; 190 } 191 192 /* 193 * dump database to file 194 */ 195 fp = output ? fopen(output, "wb") : stdout; 196 if (fp == NULL) { 197 perror("fopen"); 198 exit(1); 199 } 200 201 /* dump database body */ 202 size = _db_factory_calc_size(df); 203 serialized = malloc(size); 204 _region_init(&data, serialized, size); 205 CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data)); 206 if (fwrite(serialized, size, 1, fp) != 1) 207 err(EXIT_FAILURE, "fwrite"); 208 209 fclose(fp); 210} 211 212static void 213set_prop_string(const char *res, char **store, char **data) 214{ 215 char buf[256]; 216 217 if (*store) { 218 snprintf(buf, sizeof(buf), 219 "%s is duplicated. ignored the one", res); 220 yyerror(buf); 221 return; 222 } 223 224 *store = *data; 225 *data = NULL; 226} 227 228static void 229set_invalid(u_int32_t inv) 230{ 231 232 invalid = inv; 233 use_invalid = 1; 234} 235 236static void 237register_named_csid(char *sym, u_int32_t val) 238{ 239 struct named_csid *csid; 240 241 STAILQ_FOREACH(csid, &named_csids, ci_entry) { 242 if (strcmp(csid->ci_symbol, sym) == 0) { 243 yyerror("multiply defined CSID"); 244 exit(1); 245 } 246 } 247 248 csid = malloc(sizeof(*csid)); 249 if (csid == NULL) { 250 perror("malloc"); 251 exit(1); 252 } 253 csid->ci_symbol = sym; 254 csid->ci_csid = val; 255 STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry); 256 num_csids++; 257} 258 259static void 260do_mkdb(FILE *in) 261{ 262 FILE *out; 263 int ret; 264 265 /* dump DB to file */ 266 out = output ? fopen(output, "wb") : stdout; 267 if (out == NULL) 268 err(EXIT_FAILURE, "fopen"); 269 270 ret = _lookup_factory_convert(out, in); 271 fclose(out); 272 if (ret && output) 273 unlink(output); /* dump failure */ 274 if (ret) 275 errx(EXIT_FAILURE, "%s\n", strerror(ret)); 276} 277 278static void 279usage(void) 280{ 281 errx(EXIT_FAILURE, 282 "usage:\n" 283 "\t%s [-d] [-o outfile] [infile]\n" 284 "\t%s -m [-d] [-o outfile] [infile]", 285 getprogname(), getprogname()); 286} 287 288int 289main(int argc, char **argv) 290{ 291 FILE *in = NULL; 292 int ch, mkdb = 0; 293 294 while ((ch = getopt(argc, argv, "do:m")) != EOF) { 295 switch (ch) { 296 case 'd': 297 debug = 1; 298 break; 299 case 'o': 300 output = strdup(optarg); 301 break; 302 case 'm': 303 mkdb = 1; 304 break; 305 default: 306 usage(); 307 } 308 } 309 310 argc -= optind; 311 argv += optind; 312 switch (argc) { 313 case 0: 314 in = stdin; 315 break; 316 case 1: 317 in = fopen(argv[0], "r"); 318 if (!in) 319 err(EXIT_FAILURE, "%s", argv[0]); 320 break; 321 default: 322 usage(); 323 } 324 325 if (mkdb) 326 do_mkdb(in); 327 else { 328 STAILQ_INIT(&named_csids); 329 yyin = in; 330 yyparse(); 331 } 332 333 return (0); 334} 335