1 /* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem 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.4 2005/06/02 02:09:25 lukem 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 60 static int debug = 0, num_csids = 0; 61 static char *output = NULL; 62 static char *name, *encoding, *variable; 63 static u_int32_t invalid; 64 static int use_invalid = 0; 65 static struct named_csid_list named_csids; 66 67 static void dump_file(void); 68 static void register_named_csid(char *, u_int32_t); 69 static void set_prop_string(const char *, char **, char **); 70 static 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 84 file : property 85 { dump_file(); } 86 87 property : /* 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 95 name : R_NAME L_STRING 96 { 97 set_prop_string("NAME", &name, &$2); 98 } 99 100 encoding : R_ENCODING L_STRING 101 { 102 set_prop_string("ENCODING", &encoding, &$2); 103 } 104 variable : R_VARIABLE L_STRING 105 { 106 set_prop_string("VARIABLE", &variable, &$2); 107 } 108 defcsid : R_DEFCSID L_STRING L_IMM 109 { 110 register_named_csid($2, $3); 111 $2 = NULL; 112 } 113 invalid : R_INVALID L_IMM 114 { 115 set_invalid($2); 116 } 117 %% 118 119 int 120 yyerror(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) \ 128 do { \ 129 ret = func a; \ 130 if (ret) \ 131 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \ 132 } while (/*CONSTCOND*/0) 133 static void 134 dump_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 221 static void 222 set_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 237 static void 238 set_invalid(u_int32_t inv) 239 { 240 invalid = inv; 241 use_invalid = 1; 242 } 243 244 static void 245 register_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 267 static void 268 do_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 errx(EXIT_FAILURE, "%s\n", strerror(ret)); 288 } 289 290 static void 291 usage(void) 292 { 293 errx(EXIT_FAILURE, 294 "usage:\n" 295 "\t%s [-o outfile] [infile]\n" 296 "\t%s -m [-o outfile] [infile]", 297 getprogname(), getprogname()); 298 } 299 300 int 301 main(int argc, char **argv) 302 { 303 int ch; 304 extern char *optarg; 305 extern int optind; 306 FILE *in = NULL; 307 int mkdb = 0; 308 309 while ((ch=getopt(argc, argv, "do:m")) != EOF) { 310 switch (ch) { 311 case 'd': 312 debug = 1; 313 break; 314 case 'o': 315 output = strdup(optarg); 316 break; 317 case 'm': 318 mkdb = 1; 319 break; 320 default: 321 usage(); 322 } 323 } 324 325 argc-=optind; 326 argv+=optind; 327 switch (argc) { 328 case 0: 329 in = stdin; 330 break; 331 case 1: 332 in = fopen(argv[0], "r"); 333 if (!in) 334 err(EXIT_FAILURE, argv[0]); 335 break; 336 default: 337 usage(); 338 } 339 340 if (mkdb) 341 do_mkdb(in); 342 else { 343 SIMPLEQ_INIT(&named_csids); 344 yyin=in; 345 yyparse(); 346 } 347 348 return (0); 349 } 350