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