yacc.y revision 1.2
1/* $NetBSD: yacc.y,v 1.2 2003/10/27 00:12:43 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.2 2003/10/27 00:12:43 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 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 sprintf(buf, _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", i); 188 CHKERR(ret, _db_factory_addstr_by_s, 189 (df, buf, csid->ci_symbol)); 190 sprintf(buf, _CITRUS_ESDB_SYM_CSID_PREFIX "%d", i); 191 CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid)); 192 i++; 193 } 194 195 /* 196 * dump database to file 197 */ 198 if (output) 199 fp = fopen(output, "wb"); 200 else 201 fp = stdout; 202 203 if (fp == NULL) { 204 perror("fopen"); 205 exit(1); 206 } 207 208 /* dump database body */ 209 size = _db_factory_calc_size(df); 210 serialized = malloc(size); 211 _region_init(&data, serialized, size); 212 CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data)); 213 if (fwrite(serialized, size, 1, fp) != 1) 214 err(EXIT_FAILURE, "fwrite"); 215 216 fclose(fp); 217} 218 219static void 220set_prop_string(const char *res, char **store, char **data) 221{ 222 char buf[256]; 223 224 if (*store) { 225 snprintf(buf, sizeof(buf), 226 "%s is duplicated. ignored the one", res); 227 yyerror(buf); 228 return; 229 } 230 231 *store = *data; 232 *data = NULL; 233} 234 235static void 236set_invalid(u_int32_t inv) 237{ 238 invalid = inv; 239 use_invalid = 1; 240} 241 242static void 243register_named_csid(char *sym, u_int32_t val) 244{ 245 struct named_csid *csid; 246 247 SIMPLEQ_FOREACH(csid, &named_csids, ci_entry) { 248 if (strcmp(csid->ci_symbol, sym) == 0) { 249 yyerror("multiply defined CSID"); 250 exit(1); 251 } 252 } 253 254 csid = malloc(sizeof(*csid)); 255 if (csid == NULL) { 256 perror("malloc"); 257 exit(1); 258 } 259 csid->ci_symbol = sym; 260 csid->ci_csid = val; 261 SIMPLEQ_INSERT_TAIL(&named_csids, csid, ci_entry); 262 num_csids++; 263} 264 265static void 266do_mkdb(FILE *in) 267{ 268 int ret; 269 FILE *out; 270 271 /* dump DB to file */ 272 if (output) 273 out = fopen(output, "wb"); 274 else 275 out = stdout; 276 277 if (out==NULL) 278 err(EXIT_FAILURE, "fopen"); 279 280 ret = _lookup_factory_convert(out, in); 281 fclose(out); 282 if (ret && output) 283 unlink(output); /* dump failure */ 284 if (ret) 285 errx(EXIT_FAILURE, "%s\n", strerror(ret)); 286} 287 288static void 289usage(void) 290{ 291 errx(EXIT_FAILURE, 292 "usage:\n" 293 "\t%s [-o outfile] [infile]\n" 294 "\t%s -m [-o outfile] [infile]", 295 getprogname(), getprogname()); 296} 297 298int 299main(int argc, char **argv) 300{ 301 int ch; 302 extern char *optarg; 303 extern int optind; 304 FILE *in; 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, 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