1 /* $NetBSD: src/usr.bin/mkesdb/yacc.y,v 1.3 2004/01/02 12:09:48 itojun 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 #include <sys/types.h> 31 #include <sys/queue.h> 32 #include <assert.h> 33 #include <err.h> 34 #include <errno.h> 35 #include <limits.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include "citrus_namespace.h" 42 #include "citrus_types.h" 43 #include "citrus_region.h" 44 #include "citrus_esdb_file.h" 45 #include "citrus_db_hash.h" 46 #include "citrus_db_factory.h" 47 #include "citrus_lookup_factory.h" 48 49 #include "ldef.h" 50 51 extern FILE *yyin; 52 53 static int debug = 0, num_csids = 0; 54 static char *output = NULL; 55 static char *name, *encoding, *variable; 56 static uint32_t invalid; 57 static int use_invalid = 0; 58 static struct named_csid_list named_csids; 59 60 static void dump_file(void); 61 static void register_named_csid(char *, uint32_t); 62 static void set_prop_string(const char *, char **, char **); 63 static void set_invalid(uint32_t); 64 65 #if YYPATCH < 20180510 66 int yylex (void); 67 #endif 68 %} 69 %union { 70 uint32_t i_value; 71 char *s_value; 72 } 73 74 %token R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID 75 %token R_LN 76 %token <i_value> L_IMM 77 %token <s_value> L_STRING 78 79 %% 80 81 file : property 82 { dump_file(); } 83 84 property : /* empty */ 85 | property R_LN 86 | property name R_LN 87 | property encoding R_LN 88 | property variable R_LN 89 | property defcsid R_LN 90 | property invalid R_LN 91 92 name : R_NAME L_STRING 93 { 94 set_prop_string("NAME", &name, &$2); 95 } 96 97 encoding : R_ENCODING L_STRING 98 { 99 set_prop_string("ENCODING", &encoding, &$2); 100 } 101 variable : R_VARIABLE L_STRING 102 { 103 set_prop_string("VARIABLE", &variable, &$2); 104 } 105 defcsid : R_DEFCSID L_STRING L_IMM 106 { 107 register_named_csid($2, $3); 108 $2 = NULL; 109 } 110 invalid : R_INVALID L_IMM 111 { 112 set_invalid($2); 113 } 114 %% 115 116 int 117 yyerror(const char *s) 118 { 119 fprintf(stderr, "%s in %d\n", s, aline_number); 120 121 return (0); 122 } 123 124 #define CHKERR(ret, func, a) \ 125 do { \ 126 ret = func a; \ 127 if (ret) \ 128 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \ 129 } while (/*CONSTCOND*/0) 130 static void 131 dump_file(void) 132 { 133 int ret; 134 FILE *fp; 135 struct _db_factory *df; 136 struct _region data; 137 struct named_csid *csid; 138 char buf[100]; 139 int i; 140 void *serialized; 141 size_t size; 142 143 ret = 0; 144 if (!name) { 145 fprintf(stderr, "NAME is mandatory.\n"); 146 ret = 1; 147 } 148 if (!encoding) { 149 fprintf(stderr, "ENCODING is mandatory.\n"); 150 ret = 1; 151 } 152 if (ret) 153 exit(1); 154 155 /* 156 * build database 157 */ 158 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL)); 159 160 /* store version */ 161 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION, 162 _CITRUS_ESDB_VERSION)); 163 164 /* store encoding */ 165 CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING, 166 encoding)); 167 168 /* store variable */ 169 if (variable) 170 CHKERR(ret, _db_factory_addstr_by_s, 171 (df, _CITRUS_ESDB_SYM_VARIABLE, variable)); 172 173 /* store invalid */ 174 if (use_invalid) 175 CHKERR(ret, _db_factory_add32_by_s, (df, 176 _CITRUS_ESDB_SYM_INVALID, 177 invalid)); 178 179 /* store num of charsets */ 180 CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS, 181 num_csids)); 182 i=0; 183 STAILQ_FOREACH(csid, &named_csids, ci_entry) { 184 snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", 185 i); 186 CHKERR(ret, _db_factory_addstr_by_s, 187 (df, buf, csid->ci_symbol)); 188 snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d", 189 i); 190 CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid)); 191 i++; 192 } 193 194 /* 195 * dump database to file 196 */ 197 if (output) 198 fp = fopen(output, "wb"); 199 else 200 fp = stdout; 201 202 if (fp == NULL) { 203 perror("fopen"); 204 exit(1); 205 } 206 207 /* dump database body */ 208 size = _db_factory_calc_size(df); 209 serialized = malloc(size); 210 _region_init(&data, serialized, size); 211 CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data)); 212 if (fwrite(serialized, size, 1, fp) != 1) 213 err(EXIT_FAILURE, "fwrite"); 214 215 fclose(fp); 216 } 217 218 static void 219 set_prop_string(const char *res, char **store, char **data) 220 { 221 char buf[256]; 222 223 if (*store) { 224 snprintf(buf, sizeof(buf), 225 "%s is duplicated. ignored the one", res); 226 yyerror(buf); 227 return; 228 } 229 230 *store = *data; 231 *data = NULL; 232 } 233 234 static void 235 set_invalid(uint32_t inv) 236 { 237 invalid = inv; 238 use_invalid = 1; 239 } 240 241 static void 242 register_named_csid(char *sym, uint32_t val) 243 { 244 struct named_csid *csid; 245 246 STAILQ_FOREACH(csid, &named_csids, ci_entry) { 247 if (strcmp(csid->ci_symbol, sym) == 0) { 248 yyerror("multiply defined CSID"); 249 exit(1); 250 } 251 } 252 253 csid = malloc(sizeof(*csid)); 254 if (csid == NULL) { 255 perror("malloc"); 256 exit(1); 257 } 258 csid->ci_symbol = sym; 259 csid->ci_csid = val; 260 STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry); 261 num_csids++; 262 } 263 264 static void 265 do_mkdb(FILE *in) 266 { 267 int ret; 268 FILE *out; 269 270 /* dump DB to file */ 271 if (output) 272 out = fopen(output, "wb"); 273 else 274 out = stdout; 275 276 if (out==NULL) 277 err(EXIT_FAILURE, "fopen"); 278 279 ret = _lookup_factory_convert(out, in); 280 fclose(out); 281 if (ret && output) 282 unlink(output); /* dump failure */ 283 if (ret) 284 errx(EXIT_FAILURE, "%s\n", strerror(ret)); 285 } 286 287 static void 288 usage(void) 289 { 290 errx(EXIT_FAILURE, 291 "usage:\n" 292 "\t%s [-o outfile] [infile]\n" 293 "\t%s -m [-o outfile] [infile]", 294 getprogname(), getprogname()); 295 } 296 297 int 298 main(int argc, char **argv) 299 { 300 int ch; 301 FILE *in = NULL; 302 int mkdb = 0; 303 304 while ((ch=getopt(argc, argv, "do:m")) != -1) { 305 switch (ch) { 306 case 'd': 307 debug = 1; 308 break; 309 case 'o': 310 output = strdup(optarg); 311 break; 312 case 'm': 313 mkdb = 1; 314 break; 315 default: 316 usage(); 317 } 318 } 319 320 argc-=optind; 321 argv+=optind; 322 switch (argc) { 323 case 0: 324 in = stdin; 325 break; 326 case 1: 327 in = fopen(argv[0], "r"); 328 if (!in) 329 err(EXIT_FAILURE, "%s", argv[0]); 330 break; 331 default: 332 usage(); 333 } 334 335 if (mkdb) 336 do_mkdb(in); 337 else { 338 STAILQ_INIT(&named_csids); 339 yyin=in; 340 yyparse(); 341 } 342 343 return (0); 344 } 345