1*51e66a47SVivek Prakash /* $NetBSD: tic.c,v 1.10 2010/02/22 23:05:39 roy Exp $ */ 2*51e66a47SVivek Prakash 3*51e66a47SVivek Prakash /* 4*51e66a47SVivek Prakash * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. 5*51e66a47SVivek Prakash * 6*51e66a47SVivek Prakash * This code is derived from software contributed to The NetBSD Foundation 7*51e66a47SVivek Prakash * by Roy Marples. 8*51e66a47SVivek Prakash * 9*51e66a47SVivek Prakash * Redistribution and use in source and binary forms, with or without 10*51e66a47SVivek Prakash * modification, are permitted provided that the following conditions 11*51e66a47SVivek Prakash * are met: 12*51e66a47SVivek Prakash * 1. Redistributions of source code must retain the above copyright 13*51e66a47SVivek Prakash * notice, this list of conditions and the following disclaimer. 14*51e66a47SVivek Prakash * 2. Redistributions in binary form must reproduce the above copyright 15*51e66a47SVivek Prakash * notice, this list of conditions and the following disclaimer in the 16*51e66a47SVivek Prakash * documentation and/or other materials provided with the distribution. 17*51e66a47SVivek Prakash * 18*51e66a47SVivek Prakash * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19*51e66a47SVivek Prakash * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20*51e66a47SVivek Prakash * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21*51e66a47SVivek Prakash * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22*51e66a47SVivek Prakash * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23*51e66a47SVivek Prakash * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*51e66a47SVivek Prakash * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*51e66a47SVivek Prakash * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*51e66a47SVivek Prakash * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27*51e66a47SVivek Prakash * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*51e66a47SVivek Prakash */ 29*51e66a47SVivek Prakash 30*51e66a47SVivek Prakash #if HAVE_NBTOOL_CONFIG_H 31*51e66a47SVivek Prakash #include "nbtool_config.h" 32*51e66a47SVivek Prakash #endif 33*51e66a47SVivek Prakash 34*51e66a47SVivek Prakash #include <sys/cdefs.h> 35*51e66a47SVivek Prakash __RCSID("$NetBSD: tic.c,v 1.10 2010/02/22 23:05:39 roy Exp $"); 36*51e66a47SVivek Prakash 37*51e66a47SVivek Prakash #include <sys/types.h> 38*51e66a47SVivek Prakash 39*51e66a47SVivek Prakash #if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H 40*51e66a47SVivek Prakash #include <sys/endian.h> 41*51e66a47SVivek Prakash #endif 42*51e66a47SVivek Prakash 43*51e66a47SVivek Prakash #include <ctype.h> 44*51e66a47SVivek Prakash #include <err.h> 45*51e66a47SVivek Prakash #include <errno.h> 46*51e66a47SVivek Prakash #include <getopt.h> 47*51e66a47SVivek Prakash #include <limits.h> 48*51e66a47SVivek Prakash #include <fcntl.h> 49*51e66a47SVivek Prakash #include <ndbm.h> 50*51e66a47SVivek Prakash #include <stdarg.h> 51*51e66a47SVivek Prakash #include <stdlib.h> 52*51e66a47SVivek Prakash #include <stdio.h> 53*51e66a47SVivek Prakash #include <string.h> 54*51e66a47SVivek Prakash #include <term_private.h> 55*51e66a47SVivek Prakash #include <term.h> 56*51e66a47SVivek Prakash 57*51e66a47SVivek Prakash /* We store the full list of terminals we have instead of iterating 58*51e66a47SVivek Prakash through the database as the sequential iterator doesn't work 59*51e66a47SVivek Prakash the the data size stored changes N amount which ours will. */ 60*51e66a47SVivek Prakash typedef struct term { 61*51e66a47SVivek Prakash struct term *next; 62*51e66a47SVivek Prakash char *name; 63*51e66a47SVivek Prakash char type; 64*51e66a47SVivek Prakash TIC *tic; 65*51e66a47SVivek Prakash } TERM; 66*51e66a47SVivek Prakash static TERM *terms; 67*51e66a47SVivek Prakash 68*51e66a47SVivek Prakash static int error_exit; 69*51e66a47SVivek Prakash static int Sflag; 70*51e66a47SVivek Prakash static char *dbname; 71*51e66a47SVivek Prakash 72*51e66a47SVivek Prakash static void 73*51e66a47SVivek Prakash do_unlink(void) 74*51e66a47SVivek Prakash { 75*51e66a47SVivek Prakash 76*51e66a47SVivek Prakash if (dbname != NULL) 77*51e66a47SVivek Prakash unlink(dbname); 78*51e66a47SVivek Prakash } 79*51e66a47SVivek Prakash 80*51e66a47SVivek Prakash static void __attribute__((__format__(__printf__, 1, 2))) 81*51e66a47SVivek Prakash dowarn(const char *fmt, ...) 82*51e66a47SVivek Prakash { 83*51e66a47SVivek Prakash va_list va; 84*51e66a47SVivek Prakash 85*51e66a47SVivek Prakash error_exit = 1; 86*51e66a47SVivek Prakash va_start(va, fmt); 87*51e66a47SVivek Prakash vwarnx(fmt, va); 88*51e66a47SVivek Prakash va_end(va); 89*51e66a47SVivek Prakash } 90*51e66a47SVivek Prakash 91*51e66a47SVivek Prakash static char * 92*51e66a47SVivek Prakash grow_tbuf(TBUF *tbuf, size_t len) 93*51e66a47SVivek Prakash { 94*51e66a47SVivek Prakash char *buf; 95*51e66a47SVivek Prakash 96*51e66a47SVivek Prakash buf = _ti_grow_tbuf(tbuf, len); 97*51e66a47SVivek Prakash if (buf == NULL) 98*51e66a47SVivek Prakash err(1, "_ti_grow_tbuf"); 99*51e66a47SVivek Prakash return buf; 100*51e66a47SVivek Prakash } 101*51e66a47SVivek Prakash 102*51e66a47SVivek Prakash static int 103*51e66a47SVivek Prakash save_term(DBM *db, TERM *term) 104*51e66a47SVivek Prakash { 105*51e66a47SVivek Prakash uint8_t *buf; 106*51e66a47SVivek Prakash ssize_t len; 107*51e66a47SVivek Prakash datum key, value; 108*51e66a47SVivek Prakash 109*51e66a47SVivek Prakash len = _ti_flatten(&buf, term->tic); 110*51e66a47SVivek Prakash if (len == -1) 111*51e66a47SVivek Prakash return -1; 112*51e66a47SVivek Prakash 113*51e66a47SVivek Prakash key.dptr = term->name; 114*51e66a47SVivek Prakash key.dsize = strlen(term->name); 115*51e66a47SVivek Prakash value.dptr = buf; 116*51e66a47SVivek Prakash value.dsize = len; 117*51e66a47SVivek Prakash if (dbm_store(db, key, value, DBM_REPLACE) == -1) 118*51e66a47SVivek Prakash err(1, "dbm_store"); 119*51e66a47SVivek Prakash free(buf); 120*51e66a47SVivek Prakash return 0; 121*51e66a47SVivek Prakash } 122*51e66a47SVivek Prakash 123*51e66a47SVivek Prakash static TERM * 124*51e66a47SVivek Prakash find_term(const char *name) 125*51e66a47SVivek Prakash { 126*51e66a47SVivek Prakash TERM *term; 127*51e66a47SVivek Prakash 128*51e66a47SVivek Prakash for (term = terms; term != NULL; term = term->next) 129*51e66a47SVivek Prakash if (strcmp(term->name, name) == 0) 130*51e66a47SVivek Prakash return term; 131*51e66a47SVivek Prakash return NULL; 132*51e66a47SVivek Prakash } 133*51e66a47SVivek Prakash 134*51e66a47SVivek Prakash static TERM * 135*51e66a47SVivek Prakash store_term(const char *name, char type) 136*51e66a47SVivek Prakash { 137*51e66a47SVivek Prakash TERM *term; 138*51e66a47SVivek Prakash 139*51e66a47SVivek Prakash term = calloc(1, sizeof(*term)); 140*51e66a47SVivek Prakash if (term == NULL) 141*51e66a47SVivek Prakash errx(1, "malloc"); 142*51e66a47SVivek Prakash term->name = strdup(name); 143*51e66a47SVivek Prakash term->type = type; 144*51e66a47SVivek Prakash if (term->name == NULL) 145*51e66a47SVivek Prakash errx(1, "malloc"); 146*51e66a47SVivek Prakash term->next = terms; 147*51e66a47SVivek Prakash terms = term; 148*51e66a47SVivek Prakash return term; 149*51e66a47SVivek Prakash } 150*51e66a47SVivek Prakash 151*51e66a47SVivek Prakash static int 152*51e66a47SVivek Prakash process_entry(TBUF *buf, int flags) 153*51e66a47SVivek Prakash { 154*51e66a47SVivek Prakash char *p, *e, *alias; 155*51e66a47SVivek Prakash TERM *term; 156*51e66a47SVivek Prakash TIC *tic; 157*51e66a47SVivek Prakash 158*51e66a47SVivek Prakash if (buf->bufpos == 0) 159*51e66a47SVivek Prakash return 0; 160*51e66a47SVivek Prakash /* Terminate the string */ 161*51e66a47SVivek Prakash buf->buf[buf->bufpos - 1] = '\0'; 162*51e66a47SVivek Prakash /* First rewind the buffer for new entries */ 163*51e66a47SVivek Prakash buf->bufpos = 0; 164*51e66a47SVivek Prakash 165*51e66a47SVivek Prakash if (isspace((unsigned char)*buf->buf)) 166*51e66a47SVivek Prakash return 0; 167*51e66a47SVivek Prakash 168*51e66a47SVivek Prakash tic = _ti_compile(buf->buf, flags); 169*51e66a47SVivek Prakash if (tic == NULL) 170*51e66a47SVivek Prakash return 0; 171*51e66a47SVivek Prakash 172*51e66a47SVivek Prakash if (find_term(tic->name) != NULL) { 173*51e66a47SVivek Prakash dowarn("%s: duplicate entry", tic->name); 174*51e66a47SVivek Prakash _ti_freetic(tic); 175*51e66a47SVivek Prakash return 0; 176*51e66a47SVivek Prakash } 177*51e66a47SVivek Prakash term = store_term(tic->name, 't'); 178*51e66a47SVivek Prakash term->tic = tic; 179*51e66a47SVivek Prakash 180*51e66a47SVivek Prakash /* Create aliased terms */ 181*51e66a47SVivek Prakash if (tic->alias != NULL) { 182*51e66a47SVivek Prakash alias = p = strdup(tic->alias); 183*51e66a47SVivek Prakash while (p != NULL && *p != '\0') { 184*51e66a47SVivek Prakash e = strchr(p, '|'); 185*51e66a47SVivek Prakash if (e != NULL) 186*51e66a47SVivek Prakash *e++ = '\0'; 187*51e66a47SVivek Prakash if (find_term(p) != NULL) { 188*51e66a47SVivek Prakash dowarn("%s: has alias for already assigned" 189*51e66a47SVivek Prakash " term %s", tic->name, p); 190*51e66a47SVivek Prakash } else { 191*51e66a47SVivek Prakash term = store_term(p, 'a'); 192*51e66a47SVivek Prakash term->tic = calloc(sizeof(*term->tic), 1); 193*51e66a47SVivek Prakash if (term->tic == NULL) 194*51e66a47SVivek Prakash err(1, "malloc"); 195*51e66a47SVivek Prakash term->tic->name = strdup(tic->name); 196*51e66a47SVivek Prakash if (term->tic->name == NULL) 197*51e66a47SVivek Prakash err(1, "malloc"); 198*51e66a47SVivek Prakash } 199*51e66a47SVivek Prakash p = e; 200*51e66a47SVivek Prakash } 201*51e66a47SVivek Prakash } 202*51e66a47SVivek Prakash 203*51e66a47SVivek Prakash return 0; 204*51e66a47SVivek Prakash } 205*51e66a47SVivek Prakash 206*51e66a47SVivek Prakash static void 207*51e66a47SVivek Prakash merge(TIC *rtic, TIC *utic, int flags) 208*51e66a47SVivek Prakash { 209*51e66a47SVivek Prakash char *cap, flag, *code, type, *str; 210*51e66a47SVivek Prakash short ind, num; 211*51e66a47SVivek Prakash size_t n; 212*51e66a47SVivek Prakash 213*51e66a47SVivek Prakash cap = utic->flags.buf; 214*51e66a47SVivek Prakash for (n = utic->flags.entries; n > 0; n--) { 215*51e66a47SVivek Prakash ind = le16dec(cap); 216*51e66a47SVivek Prakash cap += sizeof(uint16_t); 217*51e66a47SVivek Prakash flag = *cap++; 218*51e66a47SVivek Prakash if (VALID_BOOLEAN(flag) && 219*51e66a47SVivek Prakash _ti_find_cap(&rtic->flags, 'f', ind) == NULL) 220*51e66a47SVivek Prakash { 221*51e66a47SVivek Prakash _ti_grow_tbuf(&rtic->flags, sizeof(uint16_t) + 1); 222*51e66a47SVivek Prakash le16enc(rtic->flags.buf + rtic->flags.bufpos, ind); 223*51e66a47SVivek Prakash rtic->flags.bufpos += sizeof(uint16_t); 224*51e66a47SVivek Prakash rtic->flags.buf[rtic->flags.bufpos++] = flag; 225*51e66a47SVivek Prakash rtic->flags.entries++; 226*51e66a47SVivek Prakash } 227*51e66a47SVivek Prakash } 228*51e66a47SVivek Prakash 229*51e66a47SVivek Prakash cap = utic->nums.buf; 230*51e66a47SVivek Prakash for (n = utic->nums.entries; n > 0; n--) { 231*51e66a47SVivek Prakash ind = le16dec(cap); 232*51e66a47SVivek Prakash cap += sizeof(uint16_t); 233*51e66a47SVivek Prakash num = le16dec(cap); 234*51e66a47SVivek Prakash cap += sizeof(uint16_t); 235*51e66a47SVivek Prakash if (VALID_NUMERIC(num) && 236*51e66a47SVivek Prakash _ti_find_cap(&rtic->nums, 'n', ind) == NULL) 237*51e66a47SVivek Prakash { 238*51e66a47SVivek Prakash grow_tbuf(&rtic->nums, sizeof(uint16_t) * 2); 239*51e66a47SVivek Prakash le16enc(rtic->nums.buf + rtic->nums.bufpos, ind); 240*51e66a47SVivek Prakash rtic->nums.bufpos += sizeof(uint16_t); 241*51e66a47SVivek Prakash le16enc(rtic->nums.buf + rtic->nums.bufpos, num); 242*51e66a47SVivek Prakash rtic->nums.bufpos += sizeof(uint16_t); 243*51e66a47SVivek Prakash rtic->nums.entries++; 244*51e66a47SVivek Prakash } 245*51e66a47SVivek Prakash } 246*51e66a47SVivek Prakash 247*51e66a47SVivek Prakash cap = utic->strs.buf; 248*51e66a47SVivek Prakash for (n = utic->strs.entries; n > 0; n--) { 249*51e66a47SVivek Prakash ind = le16dec(cap); 250*51e66a47SVivek Prakash cap += sizeof(uint16_t); 251*51e66a47SVivek Prakash num = le16dec(cap); 252*51e66a47SVivek Prakash cap += sizeof(uint16_t); 253*51e66a47SVivek Prakash if (num > 0 && 254*51e66a47SVivek Prakash _ti_find_cap(&rtic->strs, 's', ind) == NULL) 255*51e66a47SVivek Prakash { 256*51e66a47SVivek Prakash grow_tbuf(&rtic->strs, (sizeof(uint16_t) * 2) + num); 257*51e66a47SVivek Prakash le16enc(rtic->strs.buf + rtic->strs.bufpos, ind); 258*51e66a47SVivek Prakash rtic->strs.bufpos += sizeof(uint16_t); 259*51e66a47SVivek Prakash le16enc(rtic->strs.buf + rtic->strs.bufpos, num); 260*51e66a47SVivek Prakash rtic->strs.bufpos += sizeof(uint16_t); 261*51e66a47SVivek Prakash memcpy(rtic->strs.buf + rtic->strs.bufpos, 262*51e66a47SVivek Prakash cap, num); 263*51e66a47SVivek Prakash rtic->strs.bufpos += num; 264*51e66a47SVivek Prakash rtic->strs.entries++; 265*51e66a47SVivek Prakash } 266*51e66a47SVivek Prakash cap += num; 267*51e66a47SVivek Prakash } 268*51e66a47SVivek Prakash 269*51e66a47SVivek Prakash cap = utic->extras.buf; 270*51e66a47SVivek Prakash for (n = utic->extras.entries; n > 0; n--) { 271*51e66a47SVivek Prakash num = le16dec(cap); 272*51e66a47SVivek Prakash cap += sizeof(uint16_t); 273*51e66a47SVivek Prakash code = cap; 274*51e66a47SVivek Prakash cap += num; 275*51e66a47SVivek Prakash type = *cap++; 276*51e66a47SVivek Prakash flag = 0; 277*51e66a47SVivek Prakash str = NULL; 278*51e66a47SVivek Prakash switch (type) { 279*51e66a47SVivek Prakash case 'f': 280*51e66a47SVivek Prakash flag = *cap++; 281*51e66a47SVivek Prakash if (!VALID_BOOLEAN(flag)) 282*51e66a47SVivek Prakash continue; 283*51e66a47SVivek Prakash break; 284*51e66a47SVivek Prakash case 'n': 285*51e66a47SVivek Prakash num = le16dec(cap); 286*51e66a47SVivek Prakash cap += sizeof(uint16_t); 287*51e66a47SVivek Prakash if (!VALID_NUMERIC(num)) 288*51e66a47SVivek Prakash continue; 289*51e66a47SVivek Prakash break; 290*51e66a47SVivek Prakash case 's': 291*51e66a47SVivek Prakash num = le16dec(cap); 292*51e66a47SVivek Prakash cap += sizeof(uint16_t); 293*51e66a47SVivek Prakash str = cap; 294*51e66a47SVivek Prakash cap += num; 295*51e66a47SVivek Prakash if (num == 0) 296*51e66a47SVivek Prakash continue; 297*51e66a47SVivek Prakash break; 298*51e66a47SVivek Prakash } 299*51e66a47SVivek Prakash _ti_store_extra(rtic, 0, code, type, flag, num, str, num, 300*51e66a47SVivek Prakash flags); 301*51e66a47SVivek Prakash } 302*51e66a47SVivek Prakash } 303*51e66a47SVivek Prakash 304*51e66a47SVivek Prakash static size_t 305*51e66a47SVivek Prakash merge_use(int flags) 306*51e66a47SVivek Prakash { 307*51e66a47SVivek Prakash size_t skipped, merged, memn; 308*51e66a47SVivek Prakash char *cap, *scap; 309*51e66a47SVivek Prakash uint16_t num; 310*51e66a47SVivek Prakash TIC *rtic, *utic; 311*51e66a47SVivek Prakash TERM *term, *uterm;; 312*51e66a47SVivek Prakash 313*51e66a47SVivek Prakash skipped = merged = 0; 314*51e66a47SVivek Prakash for (term = terms; term != NULL; term = term->next) { 315*51e66a47SVivek Prakash if (term->type == 'a') 316*51e66a47SVivek Prakash continue; 317*51e66a47SVivek Prakash rtic = term->tic; 318*51e66a47SVivek Prakash while ((cap = _ti_find_extra(&rtic->extras, "use")) != NULL) { 319*51e66a47SVivek Prakash if (*cap++ != 's') { 320*51e66a47SVivek Prakash dowarn("%s: use is not string", rtic->name); 321*51e66a47SVivek Prakash break; 322*51e66a47SVivek Prakash } 323*51e66a47SVivek Prakash cap += sizeof(uint16_t); 324*51e66a47SVivek Prakash if (strcmp(rtic->name, cap) == 0) { 325*51e66a47SVivek Prakash dowarn("%s: uses itself", rtic->name); 326*51e66a47SVivek Prakash goto remove; 327*51e66a47SVivek Prakash } 328*51e66a47SVivek Prakash uterm = find_term(cap); 329*51e66a47SVivek Prakash if (uterm != NULL && uterm->type == 'a') 330*51e66a47SVivek Prakash uterm = find_term(uterm->tic->name); 331*51e66a47SVivek Prakash if (uterm == NULL) { 332*51e66a47SVivek Prakash dowarn("%s: no use record for %s", 333*51e66a47SVivek Prakash rtic->name, cap); 334*51e66a47SVivek Prakash goto remove; 335*51e66a47SVivek Prakash } 336*51e66a47SVivek Prakash utic = uterm->tic; 337*51e66a47SVivek Prakash if (strcmp(utic->name, rtic->name) == 0) { 338*51e66a47SVivek Prakash dowarn("%s: uses itself", rtic->name); 339*51e66a47SVivek Prakash goto remove; 340*51e66a47SVivek Prakash } 341*51e66a47SVivek Prakash if (_ti_find_extra(&utic->extras, "use") != NULL) { 342*51e66a47SVivek Prakash skipped++; 343*51e66a47SVivek Prakash break; 344*51e66a47SVivek Prakash } 345*51e66a47SVivek Prakash cap = _ti_find_extra(&rtic->extras, "use"); 346*51e66a47SVivek Prakash merge(rtic, utic, flags); 347*51e66a47SVivek Prakash remove: 348*51e66a47SVivek Prakash /* The pointers may have changed, find the use again */ 349*51e66a47SVivek Prakash cap = _ti_find_extra(&rtic->extras, "use"); 350*51e66a47SVivek Prakash if (cap == NULL) 351*51e66a47SVivek Prakash dowarn("%s: use no longer exists - impossible", 352*51e66a47SVivek Prakash rtic->name); 353*51e66a47SVivek Prakash else { 354*51e66a47SVivek Prakash scap = cap - (4 + sizeof(uint16_t)); 355*51e66a47SVivek Prakash cap++; 356*51e66a47SVivek Prakash num = le16dec(cap); 357*51e66a47SVivek Prakash cap += sizeof(uint16_t) + num; 358*51e66a47SVivek Prakash memn = rtic->extras.bufpos - 359*51e66a47SVivek Prakash (cap - rtic->extras.buf); 360*51e66a47SVivek Prakash memcpy(scap, cap, memn); 361*51e66a47SVivek Prakash rtic->extras.bufpos -= cap - scap; 362*51e66a47SVivek Prakash cap = scap; 363*51e66a47SVivek Prakash rtic->extras.entries--; 364*51e66a47SVivek Prakash merged++; 365*51e66a47SVivek Prakash } 366*51e66a47SVivek Prakash } 367*51e66a47SVivek Prakash } 368*51e66a47SVivek Prakash 369*51e66a47SVivek Prakash if (merged == 0 && skipped != 0) 370*51e66a47SVivek Prakash dowarn("circular use detected"); 371*51e66a47SVivek Prakash return merged; 372*51e66a47SVivek Prakash } 373*51e66a47SVivek Prakash 374*51e66a47SVivek Prakash static int 375*51e66a47SVivek Prakash print_dump(int argc, char **argv) 376*51e66a47SVivek Prakash { 377*51e66a47SVivek Prakash TERM *term; 378*51e66a47SVivek Prakash uint8_t *buf; 379*51e66a47SVivek Prakash int i, n; 380*51e66a47SVivek Prakash size_t j, col; 381*51e66a47SVivek Prakash ssize_t len; 382*51e66a47SVivek Prakash 383*51e66a47SVivek Prakash printf("struct compiled_term {\n"); 384*51e66a47SVivek Prakash printf("\tconst char *name;\n"); 385*51e66a47SVivek Prakash printf("\tconst char *cap;\n"); 386*51e66a47SVivek Prakash printf("\tsize_t caplen;\n"); 387*51e66a47SVivek Prakash printf("};\n\n"); 388*51e66a47SVivek Prakash 389*51e66a47SVivek Prakash printf("const struct compiled_term compiled_terms[] = {\n"); 390*51e66a47SVivek Prakash 391*51e66a47SVivek Prakash n = 0; 392*51e66a47SVivek Prakash for (i = 0; i < argc; i++) { 393*51e66a47SVivek Prakash term = find_term(argv[i]); 394*51e66a47SVivek Prakash if (term == NULL) { 395*51e66a47SVivek Prakash warnx("%s: no description for terminal", argv[i]); 396*51e66a47SVivek Prakash continue; 397*51e66a47SVivek Prakash } 398*51e66a47SVivek Prakash if (term->type == 'a') { 399*51e66a47SVivek Prakash warnx("%s: cannot dump alias", argv[i]); 400*51e66a47SVivek Prakash continue; 401*51e66a47SVivek Prakash } 402*51e66a47SVivek Prakash /* Don't compile the aliases in, save space */ 403*51e66a47SVivek Prakash free(term->tic->alias); 404*51e66a47SVivek Prakash term->tic->alias = NULL; 405*51e66a47SVivek Prakash len = _ti_flatten(&buf, term->tic); 406*51e66a47SVivek Prakash if (len == 0 || len == -1) 407*51e66a47SVivek Prakash continue; 408*51e66a47SVivek Prakash 409*51e66a47SVivek Prakash printf("\t{\n"); 410*51e66a47SVivek Prakash printf("\t\t\"%s\",\n", argv[i]); 411*51e66a47SVivek Prakash n++; 412*51e66a47SVivek Prakash for (j = 0, col = 0; j < (size_t)len; j++) { 413*51e66a47SVivek Prakash if (col == 0) { 414*51e66a47SVivek Prakash printf("\t\t\""); 415*51e66a47SVivek Prakash col = 16; 416*51e66a47SVivek Prakash } 417*51e66a47SVivek Prakash 418*51e66a47SVivek Prakash col += printf("\\%03o", (uint8_t)buf[j]); 419*51e66a47SVivek Prakash if (col > 75) { 420*51e66a47SVivek Prakash printf("\"%s\n", 421*51e66a47SVivek Prakash j + 1 == (size_t)len ? "," : ""); 422*51e66a47SVivek Prakash col = 0; 423*51e66a47SVivek Prakash } 424*51e66a47SVivek Prakash } 425*51e66a47SVivek Prakash if (col != 0) 426*51e66a47SVivek Prakash printf("\",\n"); 427*51e66a47SVivek Prakash printf("\t\t%zu\n", len); 428*51e66a47SVivek Prakash printf("\t}"); 429*51e66a47SVivek Prakash if (i + 1 < argc) 430*51e66a47SVivek Prakash printf(","); 431*51e66a47SVivek Prakash printf("\n"); 432*51e66a47SVivek Prakash free(buf); 433*51e66a47SVivek Prakash } 434*51e66a47SVivek Prakash printf("};\n"); 435*51e66a47SVivek Prakash 436*51e66a47SVivek Prakash return n; 437*51e66a47SVivek Prakash } 438*51e66a47SVivek Prakash 439*51e66a47SVivek Prakash int 440*51e66a47SVivek Prakash main(int argc, char **argv) 441*51e66a47SVivek Prakash { 442*51e66a47SVivek Prakash int ch, cflag, sflag, flags; 443*51e66a47SVivek Prakash char *source, *p, *buf, *ofile; 444*51e66a47SVivek Prakash FILE *f; 445*51e66a47SVivek Prakash DBM *db; 446*51e66a47SVivek Prakash size_t len, buflen, nterm, nalias; 447*51e66a47SVivek Prakash TBUF tbuf; 448*51e66a47SVivek Prakash TERM *term; 449*51e66a47SVivek Prakash 450*51e66a47SVivek Prakash cflag = sflag = 0; 451*51e66a47SVivek Prakash ofile = NULL; 452*51e66a47SVivek Prakash flags = TIC_ALIAS | TIC_DESCRIPTION | TIC_WARNING; 453*51e66a47SVivek Prakash while ((ch = getopt(argc, argv, "Saco:sx")) != -1) 454*51e66a47SVivek Prakash switch (ch) { 455*51e66a47SVivek Prakash case 'S': 456*51e66a47SVivek Prakash Sflag = 1; 457*51e66a47SVivek Prakash /* We still compile aliases so that use= works. 458*51e66a47SVivek Prakash * However, it's removed before we flatten to save space. */ 459*51e66a47SVivek Prakash flags &= ~TIC_DESCRIPTION; 460*51e66a47SVivek Prakash break; 461*51e66a47SVivek Prakash case 'a': 462*51e66a47SVivek Prakash flags |= TIC_COMMENT; 463*51e66a47SVivek Prakash break; 464*51e66a47SVivek Prakash case 'c': 465*51e66a47SVivek Prakash cflag = 1; 466*51e66a47SVivek Prakash break; 467*51e66a47SVivek Prakash case 'o': 468*51e66a47SVivek Prakash ofile = optarg; 469*51e66a47SVivek Prakash break; 470*51e66a47SVivek Prakash case 's': 471*51e66a47SVivek Prakash sflag = 1; 472*51e66a47SVivek Prakash break; 473*51e66a47SVivek Prakash case 'x': 474*51e66a47SVivek Prakash flags |= TIC_EXTRA; 475*51e66a47SVivek Prakash break; 476*51e66a47SVivek Prakash case '?': /* FALLTHROUGH */ 477*51e66a47SVivek Prakash default: 478*51e66a47SVivek Prakash fprintf(stderr, "usage: %s [-acSsx] [-o file] source\n", 479*51e66a47SVivek Prakash getprogname()); 480*51e66a47SVivek Prakash return EXIT_FAILURE; 481*51e66a47SVivek Prakash } 482*51e66a47SVivek Prakash 483*51e66a47SVivek Prakash if (optind == argc) 484*51e66a47SVivek Prakash errx(1, "No source file given"); 485*51e66a47SVivek Prakash source = argv[optind++]; 486*51e66a47SVivek Prakash f = fopen(source, "r"); 487*51e66a47SVivek Prakash if (f == NULL) 488*51e66a47SVivek Prakash err(1, "fopen: %s", source); 489*51e66a47SVivek Prakash if (!cflag && !Sflag) { 490*51e66a47SVivek Prakash if (ofile == NULL) 491*51e66a47SVivek Prakash ofile = source; 492*51e66a47SVivek Prakash len = strlen(ofile) + 9; 493*51e66a47SVivek Prakash dbname = malloc(len + 4); /* For adding .db after open */ 494*51e66a47SVivek Prakash if (dbname == NULL) 495*51e66a47SVivek Prakash err(1, "malloc"); 496*51e66a47SVivek Prakash snprintf(dbname, len, "%s.tmp", ofile); 497*51e66a47SVivek Prakash db = dbm_open(dbname, O_CREAT | O_RDWR | O_TRUNC, DEFFILEMODE); 498*51e66a47SVivek Prakash if (db == NULL) 499*51e66a47SVivek Prakash err(1, "dbopen: %s", source); 500*51e66a47SVivek Prakash p = dbname + strlen(dbname); 501*51e66a47SVivek Prakash *p++ = '.'; 502*51e66a47SVivek Prakash *p++ = 'd'; 503*51e66a47SVivek Prakash *p++ = 'b'; 504*51e66a47SVivek Prakash *p++ = '\0'; 505*51e66a47SVivek Prakash atexit(do_unlink); 506*51e66a47SVivek Prakash } else 507*51e66a47SVivek Prakash db = NULL; /* satisfy gcc warning */ 508*51e66a47SVivek Prakash 509*51e66a47SVivek Prakash tbuf.buflen = tbuf.bufpos = 0; 510*51e66a47SVivek Prakash while ((buf = fgetln(f, &buflen)) != NULL) { 511*51e66a47SVivek Prakash /* Skip comments */ 512*51e66a47SVivek Prakash if (*buf == '#') 513*51e66a47SVivek Prakash continue; 514*51e66a47SVivek Prakash if (buf[buflen - 1] != '\n') { 515*51e66a47SVivek Prakash process_entry(&tbuf, flags); 516*51e66a47SVivek Prakash dowarn("last line is not a comment" 517*51e66a47SVivek Prakash " and does not end with a newline"); 518*51e66a47SVivek Prakash continue; 519*51e66a47SVivek Prakash } 520*51e66a47SVivek Prakash /* 521*51e66a47SVivek Prakash If the first char is space not a space then we have a 522*51e66a47SVivek Prakash new entry, so process it. 523*51e66a47SVivek Prakash */ 524*51e66a47SVivek Prakash if (!isspace((unsigned char)*buf) && tbuf.bufpos != 0) 525*51e66a47SVivek Prakash process_entry(&tbuf, flags); 526*51e66a47SVivek Prakash 527*51e66a47SVivek Prakash /* Grow the buffer if needed */ 528*51e66a47SVivek Prakash grow_tbuf(&tbuf, buflen); 529*51e66a47SVivek Prakash /* Append the string */ 530*51e66a47SVivek Prakash memcpy(tbuf.buf + tbuf.bufpos, buf, buflen); 531*51e66a47SVivek Prakash tbuf.bufpos += buflen; 532*51e66a47SVivek Prakash } 533*51e66a47SVivek Prakash /* Process the last entry if not done already */ 534*51e66a47SVivek Prakash process_entry(&tbuf, flags); 535*51e66a47SVivek Prakash 536*51e66a47SVivek Prakash /* Merge use entries until we have merged all we can */ 537*51e66a47SVivek Prakash while (merge_use(flags) != 0) 538*51e66a47SVivek Prakash ; 539*51e66a47SVivek Prakash 540*51e66a47SVivek Prakash if (Sflag) { 541*51e66a47SVivek Prakash print_dump(argc - optind, argv + optind); 542*51e66a47SVivek Prakash return error_exit; 543*51e66a47SVivek Prakash } 544*51e66a47SVivek Prakash 545*51e66a47SVivek Prakash if (cflag) 546*51e66a47SVivek Prakash return error_exit; 547*51e66a47SVivek Prakash 548*51e66a47SVivek Prakash /* Save the terms */ 549*51e66a47SVivek Prakash nterm = nalias = 0; 550*51e66a47SVivek Prakash for (term = terms; term != NULL; term = term->next) { 551*51e66a47SVivek Prakash save_term(db, term); 552*51e66a47SVivek Prakash if (term->type == 'a') 553*51e66a47SVivek Prakash nalias++; 554*51e66a47SVivek Prakash else 555*51e66a47SVivek Prakash nterm++; 556*51e66a47SVivek Prakash } 557*51e66a47SVivek Prakash 558*51e66a47SVivek Prakash /* done! */ 559*51e66a47SVivek Prakash dbm_close(db); 560*51e66a47SVivek Prakash 561*51e66a47SVivek Prakash /* Rename the tmp db to the real one now */ 562*51e66a47SVivek Prakash len = strlen(ofile) + 4; 563*51e66a47SVivek Prakash p = malloc(len); 564*51e66a47SVivek Prakash if (p == NULL) 565*51e66a47SVivek Prakash err(1, "malloc"); 566*51e66a47SVivek Prakash snprintf(p, len, "%s.db", ofile); 567*51e66a47SVivek Prakash if (rename(dbname, p) == -1) 568*51e66a47SVivek Prakash err(1, "rename"); 569*51e66a47SVivek Prakash free(dbname); 570*51e66a47SVivek Prakash dbname = NULL; 571*51e66a47SVivek Prakash 572*51e66a47SVivek Prakash if (sflag != 0) 573*51e66a47SVivek Prakash fprintf(stderr, "%zu entries and %zu aliases written to %s\n", 574*51e66a47SVivek Prakash nterm, nalias, p); 575*51e66a47SVivek Prakash 576*51e66a47SVivek Prakash return EXIT_SUCCESS; 577*51e66a47SVivek Prakash } 578