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