diff options
Diffstat (limited to 'usr.bin/mkesdb/yacc.y')
-rw-r--r-- | usr.bin/mkesdb/yacc.y | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/usr.bin/mkesdb/yacc.y b/usr.bin/mkesdb/yacc.y new file mode 100644 index 0000000..0c01b61 --- /dev/null +++ b/usr.bin/mkesdb/yacc.y @@ -0,0 +1,332 @@ +/* $FreeBSD$ */ +/* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $ */ + +%{ +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/queue.h> + +#include <assert.h> +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_region.h" +#include "citrus_esdb_file.h" +#include "citrus_db_hash.h" +#include "citrus_db_factory.h" +#include "citrus_lookup_factory.h" + +#include "ldef.h" + +extern FILE *yyin; + +static struct named_csid_list named_csids; +static char *encoding, *name, *output = NULL, *variable; +static u_int32_t invalid; +static int debug = 0, num_csids = 0, use_invalid = 0; + +static void dump_file(void); +static void register_named_csid(char *, u_int32_t); +static void set_invalid(u_int32_t); +static void set_prop_string(const char *, char **, char **); +%} +%union { + u_int32_t i_value; + char *s_value; +} + +%token R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID +%token R_LN +%token <i_value> L_IMM +%token <s_value> L_STRING + +%% + +file : property + { dump_file(); } + +property : /* empty */ + | property R_LN + | property name R_LN + | property encoding R_LN + | property variable R_LN + | property defcsid R_LN + | property invalid R_LN + +name : R_NAME L_STRING + { + set_prop_string("NAME", &name, &$2); + } + +encoding : R_ENCODING L_STRING + { + set_prop_string("ENCODING", &encoding, &$2); + } +variable : R_VARIABLE L_STRING + { + set_prop_string("VARIABLE", &variable, &$2); + } +defcsid : R_DEFCSID L_STRING L_IMM + { + register_named_csid($2, $3); + $2 = NULL; + } +invalid : R_INVALID L_IMM + { + set_invalid($2); + } +%% + +int +yyerror(const char *s) +{ + + fprintf(stderr, "%s in %d\n", s, line_number); + + return (0); +} + +#define CHKERR(ret, func, a) \ +do { \ + ret = func a; \ + if (ret) \ + errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \ +} while (/*CONSTCOND*/0) +static void +dump_file(void) +{ + struct _db_factory *df; + struct _region data; + struct named_csid *csid; + FILE *fp; + char buf[100]; + void *serialized; + size_t size; + int i, ret; + + ret = 0; + if (!name) { + fprintf(stderr, "NAME is mandatory.\n"); + ret = 1; + } + if (!encoding) { + fprintf(stderr, "ENCODING is mandatory.\n"); + ret = 1; + } + if (ret) + exit(1); + + /* + * build database + */ + CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL)); + + /* store version */ + CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION, + _CITRUS_ESDB_VERSION)); + + /* store encoding */ + CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING, + encoding)); + + /* store variable */ + if (variable) + CHKERR(ret, _db_factory_addstr_by_s, + (df, _CITRUS_ESDB_SYM_VARIABLE, variable)); + + /* store invalid */ + if (use_invalid) + CHKERR(ret, _db_factory_add32_by_s, (df, + _CITRUS_ESDB_SYM_INVALID, invalid)); + + /* store num of charsets */ + CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS, + num_csids)); + i = 0; + STAILQ_FOREACH(csid, &named_csids, ci_entry) { + snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", + i); + CHKERR(ret, _db_factory_addstr_by_s, + (df, buf, csid->ci_symbol)); + snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d", + i); + CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid)); + i++; + } + + /* + * dump database to file + */ + fp = output ? fopen(output, "wb") : stdout; + if (fp == NULL) { + perror("fopen"); + exit(1); + } + + /* dump database body */ + size = _db_factory_calc_size(df); + serialized = malloc(size); + _region_init(&data, serialized, size); + CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data)); + if (fwrite(serialized, size, 1, fp) != 1) + err(EXIT_FAILURE, "fwrite"); + + fclose(fp); +} + +static void +set_prop_string(const char *res, char **store, char **data) +{ + char buf[256]; + + if (*store) { + snprintf(buf, sizeof(buf), + "%s is duplicated. ignored the one", res); + yyerror(buf); + return; + } + + *store = *data; + *data = NULL; +} + +static void +set_invalid(u_int32_t inv) +{ + + invalid = inv; + use_invalid = 1; +} + +static void +register_named_csid(char *sym, u_int32_t val) +{ + struct named_csid *csid; + + STAILQ_FOREACH(csid, &named_csids, ci_entry) { + if (strcmp(csid->ci_symbol, sym) == 0) { + yyerror("multiply defined CSID"); + exit(1); + } + } + + csid = malloc(sizeof(*csid)); + if (csid == NULL) { + perror("malloc"); + exit(1); + } + csid->ci_symbol = sym; + csid->ci_csid = val; + STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry); + num_csids++; +} + +static void +do_mkdb(FILE *in) +{ + FILE *out; + int ret; + + /* dump DB to file */ + out = output ? fopen(output, "wb") : stdout; + if (out == NULL) + err(EXIT_FAILURE, "fopen"); + + ret = _lookup_factory_convert(out, in); + fclose(out); + if (ret && output) + unlink(output); /* dump failure */ + if (ret) + errx(EXIT_FAILURE, "%s\n", strerror(ret)); +} + +static void +usage(void) +{ + errx(EXIT_FAILURE, + "usage:\n" + "\t%s [-o outfile] [infile]\n" + "\t%s -m [-o outfile] [infile]", + getprogname(), getprogname()); +} + +int +main(int argc, char **argv) +{ + FILE *in = NULL; + int ch, mkdb = 0; + + while ((ch = getopt(argc, argv, "do:m")) != EOF) { + switch (ch) { + case 'd': + debug = 1; + break; + case 'o': + output = strdup(optarg); + break; + case 'm': + mkdb = 1; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + switch (argc) { + case 0: + in = stdin; + break; + case 1: + in = fopen(argv[0], "r"); + if (!in) + err(EXIT_FAILURE, "%s", argv[0]); + break; + default: + usage(); + } + + if (mkdb) + do_mkdb(in); + else { + STAILQ_INIT(&named_csids); + yyin = in; + yyparse(); + } + + return (0); +} |