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