Annotation of src/usr.bin/lex/misc.c, Revision 1.16
1.16 ! tedu 1: /* $OpenBSD: misc.c,v 1.15 2015/11/19 19:43:40 tedu Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /* misc - miscellaneous flex routines */
4:
1.15 tedu 5: /* Copyright (c) 1990 The Regents of the University of California. */
6: /* All rights reserved. */
7:
8: /* This code is derived from software contributed to Berkeley by */
9: /* Vern Paxson. */
1.1 deraadt 10:
1.15 tedu 11: /* The United States Government has rights in this work pursuant */
12: /* to contract no. DE-AC03-76SF00098 between the United States */
13: /* Department of Energy and the University of California. */
14:
15: /* This file is part of flex. */
16:
17: /* Redistribution and use in source and binary forms, with or without */
18: /* modification, are permitted provided that the following conditions */
19: /* are met: */
20:
21: /* 1. Redistributions of source code must retain the above copyright */
22: /* notice, this list of conditions and the following disclaimer. */
23: /* 2. Redistributions in binary form must reproduce the above copyright */
24: /* notice, this list of conditions and the following disclaimer in the */
25: /* documentation and/or other materials provided with the distribution. */
26:
27: /* Neither the name of the University nor the names of its contributors */
28: /* may be used to endorse or promote products derived from this software */
29: /* without specific prior written permission. */
30:
31: /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
32: /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
33: /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
34: /* PURPOSE. */
1.1 deraadt 35:
36: #include "flexdef.h"
1.15 tedu 37: #include "tables.h"
38:
39: #define CMD_IF_TABLES_SER "%if-tables-serialization"
40: #define CMD_TABLES_YYDMAP "%tables-yydmap"
41: #define CMD_DEFINE_YYTABLES "%define-yytables"
42: #define CMD_IF_CPP_ONLY "%if-c++-only"
43: #define CMD_IF_C_ONLY "%if-c-only"
44: #define CMD_IF_C_OR_CPP "%if-c-or-c++"
45: #define CMD_NOT_FOR_HEADER "%not-for-header"
46: #define CMD_OK_FOR_HEADER "%ok-for-header"
47: #define CMD_PUSH "%push"
48: #define CMD_POP "%pop"
49: #define CMD_IF_REENTRANT "%if-reentrant"
50: #define CMD_IF_NOT_REENTRANT "%if-not-reentrant"
51: #define CMD_IF_BISON_BRIDGE "%if-bison-bridge"
52: #define CMD_IF_NOT_BISON_BRIDGE "%if-not-bison-bridge"
53: #define CMD_ENDIF "%endif"
54:
55: /* we allow the skeleton to push and pop. */
56: struct sko_state {
1.16 ! tedu 57: bool dc; /**< do_copy */
1.15 tedu 58: };
1.16 ! tedu 59: static struct sko_state *sko_stack = 0;
! 60: static int sko_len = 0, sko_sz = 0;
! 61: static void
! 62: sko_push(bool dc)
! 63: {
! 64: if (!sko_stack) {
! 65: sko_sz = 1;
! 66: sko_stack = (struct sko_state *) flex_alloc(sizeof(struct sko_state) * sko_sz);
! 67: if (!sko_stack)
! 68: flexfatal(_("allocation of sko_stack failed"));
! 69: sko_len = 0;
! 70: }
! 71: if (sko_len >= sko_sz) {
! 72: sko_sz *= 2;
! 73: sko_stack = (struct sko_state *) flex_realloc(sko_stack, sizeof(struct sko_state) * sko_sz);
! 74: }
! 75: /* initialize to zero and push */
! 76: sko_stack[sko_len].dc = dc;
! 77: sko_len++;
! 78: }
! 79: static void
! 80: sko_peek(bool * dc)
! 81: {
! 82: if (sko_len <= 0)
! 83: flex_die("peek attempt when sko stack is empty");
! 84: if (dc)
! 85: *dc = sko_stack[sko_len - 1].dc;
! 86: }
! 87: static void
! 88: sko_pop(bool * dc)
! 89: {
! 90: sko_peek(dc);
! 91: sko_len--;
! 92: if (sko_len < 0)
! 93: flex_die("popped too many times in skeleton.");
1.15 tedu 94: }
95:
96: /* Append "#define defname value\n" to the running buffer. */
1.16 ! tedu 97: void
! 98: action_define(defname, value)
! 99: const char *defname;
! 100: int value;
! 101: {
! 102: char buf[MAXLINE];
! 103: char *cpy;
! 104:
! 105: if ((int) strlen(defname) > MAXLINE / 2) {
! 106: format_pinpoint_message(_
! 107: ("name \"%s\" ridiculously long"),
! 108: defname);
1.15 tedu 109: return;
110: }
1.16 ! tedu 111: snprintf(buf, sizeof(buf), "#define %s %d\n", defname, value);
! 112: add_action(buf);
1.15 tedu 113:
114: /* track #defines so we can undef them when we're done. */
1.16 ! tedu 115: cpy = copy_string(defname);
! 116: buf_append(&defs_buf, &cpy, 1);
1.15 tedu 117: }
1.1 deraadt 118:
119:
1.15 tedu 120: /** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer.
121: * @param defname The macro name.
122: * @param value The macro value, can be NULL, which is the same as the empty string.
123: */
1.16 ! tedu 124: void
! 125: action_m4_define(const char *defname, const char *value)
1.15 tedu 126: {
1.16 ! tedu 127: char buf[MAXLINE];
1.15 tedu 128:
1.16 ! tedu 129: flexfatal("DO NOT USE THIS FUNCTION!");
1.15 tedu 130:
1.16 ! tedu 131: if ((int) strlen(defname) > MAXLINE / 2) {
! 132: format_pinpoint_message(_
! 133: ("name \"%s\" ridiculously long"),
! 134: defname);
1.1 deraadt 135: return;
136: }
1.16 ! tedu 137: snprintf(buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value ? value : "");
! 138: add_action(buf);
1.15 tedu 139: }
140:
141: /* Append "new_text" to the running buffer. */
1.16 ! tedu 142: void
! 143: add_action(new_text)
! 144: const char *new_text;
1.15 tedu 145: {
1.16 ! tedu 146: int len = strlen(new_text);
1.1 deraadt 147:
1.15 tedu 148: while (len + action_index >= action_size - 10 /* slop */ ) {
1.16 ! tedu 149: int new_size = action_size * 2;
1.1 deraadt 150:
1.15 tedu 151: if (new_size <= 0)
1.16 ! tedu 152: /*
! 153: * Increase just a little, to try to avoid overflow
1.1 deraadt 154: * on 16-bit machines.
155: */
156: action_size += action_size / 8;
157: else
158: action_size = new_size;
159:
160: action_array =
1.16 ! tedu 161: reallocate_character_array(action_array,
! 162: action_size);
1.15 tedu 163: }
1.1 deraadt 164:
1.16 ! tedu 165: strlcpy(&action_array[action_index], new_text,
! 166: action_size - action_index);
1.1 deraadt 167:
168: action_index += len;
1.15 tedu 169: }
1.1 deraadt 170:
171:
172: /* allocate_array - allocate memory for an integer array of the given size */
173:
1.16 ! tedu 174: void *
! 175: allocate_array(size, element_size)
! 176: int size;
! 177: size_t element_size;
1.15 tedu 178: {
1.6 mpech 179: void *mem;
1.16 ! tedu 180: size_t num_bytes = element_size * size;
1.1 deraadt 181:
1.16 ! tedu 182: mem = flex_alloc(num_bytes);
1.15 tedu 183: if (!mem)
1.16 ! tedu 184: flexfatal(_
! 185: ("memory allocation failed in allocate_array()"));
1.1 deraadt 186:
187: return mem;
1.15 tedu 188: }
1.1 deraadt 189:
190:
191: /* all_lower - true if a string is all lower-case */
192:
1.16 ! tedu 193: int
! 194: all_lower(str)
! 195: char *str;
1.15 tedu 196: {
197: while (*str) {
1.16 ! tedu 198: if (!isascii((Char) * str) || !islower((Char) * str))
1.1 deraadt 199: return 0;
200: ++str;
1.15 tedu 201: }
1.1 deraadt 202:
203: return 1;
1.15 tedu 204: }
1.1 deraadt 205:
206:
207: /* all_upper - true if a string is all upper-case */
208:
1.16 ! tedu 209: int
! 210: all_upper(str)
! 211: char *str;
1.15 tedu 212: {
213: while (*str) {
1.16 ! tedu 214: if (!isascii((Char) * str) || !isupper((Char) * str))
1.1 deraadt 215: return 0;
216: ++str;
1.15 tedu 217: }
1.1 deraadt 218:
219: return 1;
1.15 tedu 220: }
221:
1.1 deraadt 222:
1.15 tedu 223: /* intcmp - compares two integers for use by qsort. */
1.1 deraadt 224:
1.16 ! tedu 225: int
! 226: intcmp(const void *a, const void *b)
1.15 tedu 227: {
1.16 ! tedu 228: return *(const int *) a - *(const int *) b;
1.15 tedu 229: }
1.1 deraadt 230:
231:
232: /* check_char - checks a character to make sure it's within the range
233: * we're expecting. If not, generates fatal error message
234: * and exits.
235: */
236:
1.16 ! tedu 237: void
! 238: check_char(c)
! 239: int c;
1.15 tedu 240: {
241: if (c >= CSIZE)
1.16 ! tedu 242: lerrsf(_("bad character '%s' detected in check_char()"),
! 243: readable_form(c));
1.15 tedu 244:
245: if (c >= csize)
1.16 ! tedu 246: lerrsf(_
! 247: ("scanner requires -8 flag to use the character %s"),
! 248: readable_form(c));
1.15 tedu 249: }
1.1 deraadt 250:
251:
252:
253: /* clower - replace upper-case letter to lower-case */
254:
1.16 ! tedu 255: Char
! 256: clower(c)
! 257: int c;
1.15 tedu 258: {
1.16 ! tedu 259: return (Char) ((isascii(c) && isupper(c)) ? tolower(c) : c);
1.15 tedu 260: }
1.1 deraadt 261:
262:
263: /* copy_string - returns a dynamically allocated copy of a string */
264:
1.16 ! tedu 265: char *
! 266: copy_string(str)
! 267: const char *str;
1.15 tedu 268: {
1.6 mpech 269: const char *c1;
270: char *c2;
1.16 ! tedu 271: char *copy;
1.1 deraadt 272: unsigned int size;
273:
274: /* find length */
1.16 ! tedu 275: for (c1 = str; *c1; ++c1);
1.15 tedu 276:
1.16 ! tedu 277: size = (c1 - str + 1) * sizeof(char);
1.1 deraadt 278:
1.16 ! tedu 279: copy = (char *) flex_alloc(size);
1.1 deraadt 280:
1.15 tedu 281: if (copy == NULL)
1.16 ! tedu 282: flexfatal(_("dynamic memory failure in copy_string()"));
1.1 deraadt 283:
1.16 ! tedu 284: for (c2 = copy; (*c2++ = *str++) != 0;);
1.1 deraadt 285:
286: return copy;
1.15 tedu 287: }
1.1 deraadt 288:
289:
290: /* copy_unsigned_string -
291: * returns a dynamically allocated copy of a (potentially) unsigned string
292: */
293:
1.16 ! tedu 294: Char *
! 295: copy_unsigned_string(str)
! 296: Char *str;
1.15 tedu 297: {
1.6 mpech 298: Char *c;
1.16 ! tedu 299: Char *copy;
1.1 deraadt 300:
301: /* find length */
1.16 ! tedu 302: for (c = str; *c; ++c);
1.1 deraadt 303:
1.16 ! tedu 304: copy = allocate_Character_array(c - str + 1);
1.1 deraadt 305:
1.16 ! tedu 306: for (c = copy; (*c++ = *str++) != 0;);
1.1 deraadt 307:
308: return copy;
1.15 tedu 309: }
310:
1.1 deraadt 311:
1.15 tedu 312: /* cclcmp - compares two characters for use by qsort with '\0' sorting last. */
1.1 deraadt 313:
1.16 ! tedu 314: int
! 315: cclcmp(const void *a, const void *b)
1.15 tedu 316: {
1.16 ! tedu 317: if (!*(const Char *) a)
! 318: return 1;
! 319: else if (!*(const Char *) b)
! 320: return -1;
1.15 tedu 321: else
1.16 ! tedu 322: return *(const Char *) a - *(const Char *) b;
1.15 tedu 323: }
1.1 deraadt 324:
325:
326: /* dataend - finish up a block of data declarations */
327:
1.16 ! tedu 328: void
! 329: dataend()
1.15 tedu 330: {
331: /* short circuit any output */
332: if (gentables) {
1.1 deraadt 333:
1.15 tedu 334: if (datapos > 0)
1.16 ! tedu 335: dataflush();
1.1 deraadt 336:
1.15 tedu 337: /* add terminator for initialization; { for vi */
1.16 ! tedu 338: outn(" } ;\n");
1.15 tedu 339: }
1.1 deraadt 340: dataline = 0;
341: datapos = 0;
1.15 tedu 342: }
1.1 deraadt 343:
344:
345: /* dataflush - flush generated data statements */
346:
1.16 ! tedu 347: void
! 348: dataflush()
1.15 tedu 349: {
350: /* short circuit any output */
351: if (!gentables)
352: return;
353:
1.16 ! tedu 354: outc('\n');
1.1 deraadt 355:
1.15 tedu 356: if (++dataline >= NUMDATALINES) {
1.16 ! tedu 357: /*
! 358: * Put out a blank line so that the table is grouped into
1.1 deraadt 359: * large blocks that enable the user to find elements easily.
360: */
1.16 ! tedu 361: outc('\n');
1.1 deraadt 362: dataline = 0;
1.15 tedu 363: }
1.1 deraadt 364: /* Reset the number of characters written on the current line. */
365: datapos = 0;
1.15 tedu 366: }
1.1 deraadt 367:
368:
369: /* flexerror - report an error message and terminate */
370:
1.16 ! tedu 371: void
! 372: flexerror(msg)
! 373: const char *msg;
1.15 tedu 374: {
1.16 ! tedu 375: fprintf(stderr, "%s: %s\n", program_name, msg);
! 376: flexend(1);
1.15 tedu 377: }
1.1 deraadt 378:
379:
380: /* flexfatal - report a fatal error message and terminate */
381:
1.16 ! tedu 382: void
! 383: flexfatal(msg)
! 384: const char *msg;
! 385: {
! 386: fprintf(stderr, _("%s: fatal internal error, %s\n"),
! 387: program_name, msg);
! 388: FLEX_EXIT(1);
1.15 tedu 389: }
1.1 deraadt 390:
391:
392: /* htoi - convert a hexadecimal digit string to an integer value */
393:
1.16 ! tedu 394: int
! 395: htoi(str)
! 396: Char str[];
1.15 tedu 397: {
1.1 deraadt 398: unsigned int result;
399:
1.16 ! tedu 400: (void) sscanf((char *) str, "%x", &result);
1.1 deraadt 401:
402: return result;
1.15 tedu 403: }
1.1 deraadt 404:
405:
406: /* lerrif - report an error message formatted with one integer argument */
407:
1.16 ! tedu 408: void
! 409: lerrif(msg, arg)
! 410: const char *msg;
! 411: int arg;
1.15 tedu 412: {
1.16 ! tedu 413: char errmsg[MAXLINE];
1.15 tedu 414:
1.16 ! tedu 415: snprintf(errmsg, sizeof(errmsg), msg, arg);
! 416: flexerror(errmsg);
1.15 tedu 417: }
1.1 deraadt 418:
419:
420: /* lerrsf - report an error message formatted with one string argument */
421:
1.16 ! tedu 422: void
! 423: lerrsf(msg, arg)
1.15 tedu 424: const char *msg, arg[];
425: {
1.16 ! tedu 426: char errmsg[MAXLINE];
1.15 tedu 427:
1.16 ! tedu 428: snprintf(errmsg, sizeof(errmsg) - 1, msg, arg);
! 429: errmsg[sizeof(errmsg) - 1] = 0; /* ensure NULL termination */
! 430: flexerror(errmsg);
1.15 tedu 431: }
432:
433:
434: /* lerrsf_fatal - as lerrsf, but call flexfatal */
435:
1.16 ! tedu 436: void
! 437: lerrsf_fatal(msg, arg)
1.15 tedu 438: const char *msg, arg[];
439: {
1.16 ! tedu 440: char errmsg[MAXLINE];
1.15 tedu 441:
1.16 ! tedu 442: snprintf(errmsg, sizeof(errmsg) - 1, msg, arg);
! 443: errmsg[sizeof(errmsg) - 1] = 0; /* ensure NULL termination */
! 444: flexfatal(errmsg);
1.15 tedu 445: }
1.1 deraadt 446:
447:
448: /* line_directive_out - spit out a "#line" statement */
449:
1.16 ! tedu 450: void
! 451: line_directive_out(output_file, do_infile)
! 452: FILE *output_file;
! 453: int do_infile;
1.15 tedu 454: {
1.16 ! tedu 455: char directive[MAXLINE], filename[MAXLINE];
! 456: char *s1, *s2, *s3;
1.15 tedu 457: static const char *line_fmt = "#line %d \"%s\"\n";
1.1 deraadt 458:
1.15 tedu 459: if (!gen_line_dirs)
1.1 deraadt 460: return;
461:
1.15 tedu 462: s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME";
1.1 deraadt 463:
1.15 tedu 464: if (do_infile && !s1)
1.16 ! tedu 465: s1 = "<stdin>";
! 466:
1.1 deraadt 467: s2 = filename;
1.16 ! tedu 468: s3 = &filename[sizeof(filename) - 2];
1.1 deraadt 469:
1.15 tedu 470: while (s2 < s3 && *s1) {
471: if (*s1 == '\\')
1.1 deraadt 472: /* Escape the '\' */
473: *s2++ = '\\';
474:
475: *s2++ = *s1++;
1.15 tedu 476: }
1.1 deraadt 477:
478: *s2 = '\0';
479:
1.15 tedu 480: if (do_infile)
1.16 ! tedu 481: snprintf(directive, sizeof(directive), line_fmt, linenum, filename);
1.15 tedu 482: else {
1.16 ! tedu 483: snprintf(directive, sizeof(directive), line_fmt, 0, filename);
1.15 tedu 484: }
1.1 deraadt 485:
1.16 ! tedu 486: /*
! 487: * If output_file is nil then we should put the directive in the
! 488: * accumulated actions.
1.1 deraadt 489: */
1.15 tedu 490: if (output_file) {
1.16 ! tedu 491: fputs(directive, output_file);
! 492: } else
! 493: add_action(directive);
1.15 tedu 494: }
1.1 deraadt 495:
496:
497: /* mark_defs1 - mark the current position in the action array as
498: * representing where the user's section 1 definitions end
499: * and the prolog begins
500: */
1.16 ! tedu 501: void
! 502: mark_defs1()
1.15 tedu 503: {
1.1 deraadt 504: defs1_offset = 0;
505: action_array[action_index++] = '\0';
506: action_offset = prolog_offset = action_index;
507: action_array[action_index] = '\0';
1.15 tedu 508: }
1.1 deraadt 509:
510:
511: /* mark_prolog - mark the current position in the action array as
512: * representing the end of the action prolog
513: */
1.16 ! tedu 514: void
! 515: mark_prolog()
1.15 tedu 516: {
1.1 deraadt 517: action_array[action_index++] = '\0';
518: action_offset = action_index;
519: action_array[action_index] = '\0';
1.15 tedu 520: }
1.1 deraadt 521:
522:
523: /* mk2data - generate a data statement for a two-dimensional array
524: *
525: * Generates a data statement initializing the current 2-D array to "value".
526: */
1.16 ! tedu 527: void
! 528: mk2data(value)
! 529: int value;
1.15 tedu 530: {
531: /* short circuit any output */
532: if (!gentables)
533: return;
534:
535: if (datapos >= NUMDATAITEMS) {
1.16 ! tedu 536: outc(',');
! 537: dataflush();
1.15 tedu 538: }
539: if (datapos == 0)
1.1 deraadt 540: /* Indent. */
1.16 ! tedu 541: out(" ");
1.1 deraadt 542:
543: else
1.16 ! tedu 544: outc(',');
1.1 deraadt 545:
546: ++datapos;
547:
1.16 ! tedu 548: out_dec("%5d", value);
1.15 tedu 549: }
1.1 deraadt 550:
551:
552: /* mkdata - generate a data statement
553: *
554: * Generates a data statement initializing the current array element to
555: * "value".
556: */
1.16 ! tedu 557: void
! 558: mkdata(value)
! 559: int value;
1.15 tedu 560: {
561: /* short circuit any output */
562: if (!gentables)
563: return;
564:
565: if (datapos >= NUMDATAITEMS) {
1.16 ! tedu 566: outc(',');
! 567: dataflush();
1.15 tedu 568: }
569: if (datapos == 0)
1.1 deraadt 570: /* Indent. */
1.16 ! tedu 571: out(" ");
1.1 deraadt 572: else
1.16 ! tedu 573: outc(',');
1.1 deraadt 574:
575: ++datapos;
576:
1.16 ! tedu 577: out_dec("%5d", value);
1.15 tedu 578: }
1.1 deraadt 579:
580:
581: /* myctoi - return the integer represented by a string of digits */
582:
1.16 ! tedu 583: int
! 584: myctoi(array)
! 585: const char *array;
1.15 tedu 586: {
1.16 ! tedu 587: int val = 0;
1.1 deraadt 588:
1.16 ! tedu 589: (void) sscanf(array, "%d", &val);
1.1 deraadt 590:
591: return val;
1.15 tedu 592: }
1.1 deraadt 593:
594:
595: /* myesc - return character corresponding to escape sequence */
596:
1.16 ! tedu 597: Char
! 598: myesc(array)
! 599: Char array[];
1.15 tedu 600: {
1.16 ! tedu 601: Char c, esc_char;
1.15 tedu 602:
603: switch (array[1]) {
604: case 'b':
605: return '\b';
606: case 'f':
607: return '\f';
608: case 'n':
609: return '\n';
610: case 'r':
611: return '\r';
612: case 't':
613: return '\t';
614:
615: #if defined (__STDC__)
616: case 'a':
617: return '\a';
618: case 'v':
619: return '\v';
1.1 deraadt 620: #else
1.15 tedu 621: case 'a':
622: return '\007';
623: case 'v':
624: return '\013';
1.1 deraadt 625: #endif
626:
1.15 tedu 627: case '0':
628: case '1':
629: case '2':
630: case '3':
631: case '4':
632: case '5':
633: case '6':
634: case '7':
635: { /* \<octal> */
1.16 ! tedu 636: int sptr = 1;
1.1 deraadt 637:
1.16 ! tedu 638: while (isascii(array[sptr]) &&
! 639: isdigit(array[sptr]))
! 640: /*
! 641: * Don't increment inside loop control
1.1 deraadt 642: * because if isdigit() is a macro it might
643: * expand into multiple increments ...
644: */
645: ++sptr;
646:
647: c = array[sptr];
648: array[sptr] = '\0';
649:
1.16 ! tedu 650: esc_char = otoi(array + 1);
1.1 deraadt 651:
652: array[sptr] = c;
653:
654: return esc_char;
1.15 tedu 655: }
1.1 deraadt 656:
1.15 tedu 657: case 'x':
658: { /* \x<hex> */
1.16 ! tedu 659: int sptr = 2;
1.1 deraadt 660:
1.16 ! tedu 661: while (isascii(array[sptr]) &&
! 662: isxdigit(array[sptr]))
! 663: /*
! 664: * Don't increment inside loop control
1.1 deraadt 665: * because if isdigit() is a macro it might
666: * expand into multiple increments ...
667: */
668: ++sptr;
669:
670: c = array[sptr];
671: array[sptr] = '\0';
672:
1.16 ! tedu 673: esc_char = htoi(array + 2);
1.1 deraadt 674:
675: array[sptr] = c;
676:
677: return esc_char;
1.15 tedu 678: }
1.1 deraadt 679:
1.15 tedu 680: default:
681: return array[1];
1.1 deraadt 682: }
1.15 tedu 683: }
1.1 deraadt 684:
685:
686: /* otoi - convert an octal digit string to an integer value */
687:
1.16 ! tedu 688: int
! 689: otoi(str)
! 690: Char str[];
1.15 tedu 691: {
1.1 deraadt 692: unsigned int result;
693:
1.16 ! tedu 694: (void) sscanf((char *) str, "%o", &result);
1.1 deraadt 695: return result;
1.15 tedu 696: }
1.1 deraadt 697:
698:
699: /* out - various flavors of outputing a (possibly formatted) string for the
700: * generated scanner, keeping track of the line count.
701: */
702:
1.16 ! tedu 703: void
! 704: out(str)
! 705: const char *str;
1.15 tedu 706: {
1.16 ! tedu 707: fputs(str, stdout);
1.15 tedu 708: }
709:
1.16 ! tedu 710: void
! 711: out_dec(fmt, n)
! 712: const char *fmt;
! 713: int n;
1.15 tedu 714: {
1.16 ! tedu 715: fprintf(stdout, fmt, n);
1.15 tedu 716: }
717:
1.16 ! tedu 718: void
! 719: out_dec2(fmt, n1, n2)
! 720: const char *fmt;
! 721: int n1, n2;
1.15 tedu 722: {
1.16 ! tedu 723: fprintf(stdout, fmt, n1, n2);
1.15 tedu 724: }
725:
1.16 ! tedu 726: void
! 727: out_hex(fmt, x)
! 728: const char *fmt;
! 729: unsigned int x;
1.15 tedu 730: {
1.16 ! tedu 731: fprintf(stdout, fmt, x);
1.15 tedu 732: }
733:
1.16 ! tedu 734: void
! 735: out_str(fmt, str)
! 736: const char *fmt, str[];
1.15 tedu 737: {
1.16 ! tedu 738: fprintf(stdout, fmt, str);
1.15 tedu 739: }
740:
1.16 ! tedu 741: void
! 742: out_str3(fmt, s1, s2, s3)
! 743: const char *fmt, s1[], s2[], s3[];
1.15 tedu 744: {
1.16 ! tedu 745: fprintf(stdout, fmt, s1, s2, s3);
1.15 tedu 746: }
747:
1.16 ! tedu 748: void
! 749: out_str_dec(fmt, str, n)
! 750: const char *fmt, str[];
! 751: int n;
1.15 tedu 752: {
1.16 ! tedu 753: fprintf(stdout, fmt, str, n);
1.15 tedu 754: }
755:
1.16 ! tedu 756: void
! 757: outc(c)
! 758: int c;
1.15 tedu 759: {
1.16 ! tedu 760: fputc(c, stdout);
1.15 tedu 761: }
762:
1.16 ! tedu 763: void
! 764: outn(str)
! 765: const char *str;
1.15 tedu 766: {
1.16 ! tedu 767: fputs(str, stdout);
! 768: fputc('\n', stdout);
1.15 tedu 769: }
770:
771: /** Print "m4_define( [[def]], [[val]])m4_dnl\n".
772: * @param def The m4 symbol to define.
773: * @param val The definition; may be NULL.
774: * @return buf
775: */
1.16 ! tedu 776: void
! 777: out_m4_define(const char *def, const char *val)
1.15 tedu 778: {
1.16 ! tedu 779: const char *fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
! 780: fprintf(stdout, fmt, def, val ? val : "");
1.15 tedu 781: }
1.1 deraadt 782:
783:
1.12 miod 784: /* readable_form - return the human-readable form of a character
1.1 deraadt 785: *
786: * The returned string is in static storage.
787: */
788:
1.16 ! tedu 789: char *
! 790: readable_form(c)
! 791: int c;
1.15 tedu 792: {
1.1 deraadt 793: static char rform[10];
794:
1.15 tedu 795: if ((c >= 0 && c < 32) || c >= 127) {
796: switch (c) {
797: case '\b':
798: return "\\b";
799: case '\f':
800: return "\\f";
801: case '\n':
802: return "\\n";
803: case '\r':
804: return "\\r";
805: case '\t':
806: return "\\t";
807:
808: #if defined (__STDC__)
809: case '\a':
810: return "\\a";
811: case '\v':
812: return "\\v";
1.1 deraadt 813: #endif
814:
1.15 tedu 815: default:
1.16 ! tedu 816: snprintf(rform, sizeof(rform), "\\%.3o", (unsigned int) c);
1.15 tedu 817: return rform;
1.1 deraadt 818: }
1.16 ! tedu 819: } else if (c == ' ')
1.1 deraadt 820: return "' '";
821:
1.15 tedu 822: else {
1.1 deraadt 823: rform[0] = c;
824: rform[1] = '\0';
825:
826: return rform;
827: }
1.15 tedu 828: }
1.1 deraadt 829:
830:
831: /* reallocate_array - increase the size of a dynamic array */
832:
1.16 ! tedu 833: void *
! 834: reallocate_array(array, size, element_size)
! 835: void *array;
! 836: int size;
! 837: size_t element_size;
1.15 tedu 838: {
1.6 mpech 839: void *new_array;
1.16 ! tedu 840: size_t num_bytes = element_size * size;
1.1 deraadt 841:
1.16 ! tedu 842: new_array = flex_realloc(array, num_bytes);
1.15 tedu 843: if (!new_array)
1.16 ! tedu 844: flexfatal(_("attempt to increase array size failed"));
1.1 deraadt 845:
846: return new_array;
1.15 tedu 847: }
1.1 deraadt 848:
849:
850: /* skelout - write out one section of the skeleton file
851: *
852: * Description
853: * Copies skelfile or skel array to stdout until a line beginning with
854: * "%%" or EOF is found.
855: */
1.16 ! tedu 856: void
! 857: skelout()
1.15 tedu 858: {
1.16 ! tedu 859: char buf_storage[MAXLINE];
! 860: char *buf = buf_storage;
! 861: bool do_copy = true;
! 862:
! 863: /* "reset" the state by clearing the buffer and pushing a '1' */
! 864: if (sko_len > 0)
! 865: sko_peek(&do_copy);
! 866: sko_len = 0;
! 867: sko_push(do_copy = true);
! 868:
! 869:
! 870: /*
! 871: * Loop pulling lines either from the skelfile, if we're using one,
! 872: * or from the skel[] array.
1.1 deraadt 873: */
1.15 tedu 874: while (skelfile ?
1.16 ! tedu 875: (fgets(buf, MAXLINE, skelfile) != NULL) :
! 876: ((buf = (char *) skel[skel_ind++]) != 0)) {
1.15 tedu 877:
878: if (skelfile)
1.16 ! tedu 879: chomp(buf);
1.15 tedu 880:
881: /* copy from skel array */
882: if (buf[0] == '%') { /* control line */
883: /* print the control line as a comment. */
884: if (ddebug && buf[1] != '#') {
1.16 ! tedu 885: if (buf[strlen(buf) - 1] == '\\')
! 886: out_str("/* %s */\\\n", buf);
1.15 tedu 887: else
1.16 ! tedu 888: out_str("/* %s */\n", buf);
1.15 tedu 889: }
1.16 ! tedu 890: /*
! 891: * We've been accused of using cryptic markers in the
! 892: * skel. So we'll use
! 893: * emacs-style-hyphenated-commands. We might consider
! 894: * a hash if this if-else-if-else chain gets too
! 895: * large.
1.15 tedu 896: */
897: #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0)
898:
899: if (buf[1] == '%') {
900: /* %% is a break point for skelout() */
901: return;
1.16 ! tedu 902: } else if (cmd_match(CMD_PUSH)) {
! 903: sko_push(do_copy);
! 904: if (ddebug) {
! 905: out_str("/*(state = (%s) */", do_copy ? "true" : "false");
! 906: }
! 907: out_str("%s\n", buf[strlen(buf) - 1] == '\\' ? "\\" : "");
! 908: } else if (cmd_match(CMD_POP)) {
! 909: sko_pop(&do_copy);
! 910: if (ddebug) {
! 911: out_str("/*(state = (%s) */", do_copy ? "true" : "false");
! 912: }
! 913: out_str("%s\n", buf[strlen(buf) - 1] == '\\' ? "\\" : "");
! 914: } else if (cmd_match(CMD_IF_REENTRANT)) {
! 915: sko_push(do_copy);
! 916: do_copy = reentrant && do_copy;
! 917: } else if (cmd_match(CMD_IF_NOT_REENTRANT)) {
! 918: sko_push(do_copy);
! 919: do_copy = !reentrant && do_copy;
! 920: } else if (cmd_match(CMD_IF_BISON_BRIDGE)) {
! 921: sko_push(do_copy);
! 922: do_copy = bison_bridge_lval && do_copy;
! 923: } else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)) {
! 924: sko_push(do_copy);
! 925: do_copy = !bison_bridge_lval && do_copy;
! 926: } else if (cmd_match(CMD_ENDIF)) {
! 927: sko_pop(&do_copy);
! 928: } else if (cmd_match(CMD_IF_TABLES_SER)) {
! 929: do_copy = do_copy && tablesext;
! 930: } else if (cmd_match(CMD_TABLES_YYDMAP)) {
1.15 tedu 931: if (tablesext && yydmap_buf.elts)
1.16 ! tedu 932: outn((char *) (yydmap_buf.elts));
! 933: } else if (cmd_match(CMD_DEFINE_YYTABLES)) {
! 934: out_str("#define YYTABLES_NAME \"%s\"\n",
! 935: tablesname ? tablesname : "yytables");
! 936: } else if (cmd_match(CMD_IF_CPP_ONLY)) {
1.15 tedu 937: /* only for C++ */
1.16 ! tedu 938: sko_push(do_copy);
1.15 tedu 939: do_copy = C_plus_plus;
1.16 ! tedu 940: } else if (cmd_match(CMD_IF_C_ONLY)) {
1.15 tedu 941: /* %- only for C */
1.16 ! tedu 942: sko_push(do_copy);
1.15 tedu 943: do_copy = !C_plus_plus;
1.16 ! tedu 944: } else if (cmd_match(CMD_IF_C_OR_CPP)) {
1.15 tedu 945: /* %* for C and C++ */
1.16 ! tedu 946: sko_push(do_copy);
1.15 tedu 947: do_copy = true;
1.16 ! tedu 948: } else if (cmd_match(CMD_NOT_FOR_HEADER)) {
1.15 tedu 949: /* %c begin linkage-only (non-header) code. */
1.16 ! tedu 950: OUT_BEGIN_CODE();
! 951: } else if (cmd_match(CMD_OK_FOR_HEADER)) {
1.15 tedu 952: /* %e end linkage-only code. */
1.16 ! tedu 953: OUT_END_CODE();
! 954: } else if (buf[1] == '#') {
1.15 tedu 955: /* %# a comment in the skel. ignore. */
1.16 ! tedu 956: } else {
! 957: flexfatal(_("bad line in skeleton file"));
1.15 tedu 958: }
1.16 ! tedu 959: } else if (do_copy)
! 960: outn(buf);
1.15 tedu 961: } /* end while */
962: }
1.1 deraadt 963:
964:
965: /* transition_struct_out - output a yy_trans_info structure
966: *
967: * outputs the yy_trans_info structure with the two elements, element_v and
968: * element_n. Formats the output with spaces and carriage returns.
969: */
970:
1.16 ! tedu 971: void
! 972: transition_struct_out(element_v, element_n)
! 973: int element_v, element_n;
1.15 tedu 974: {
975:
976: /* short circuit any output */
977: if (!gentables)
978: return;
979:
1.16 ! tedu 980: out_dec2(" {%4d,%4d },", element_v, element_n);
1.1 deraadt 981:
982: datapos += TRANS_STRUCT_PRINT_LENGTH;
983:
1.15 tedu 984: if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) {
1.16 ! tedu 985: outc('\n');
1.1 deraadt 986:
1.15 tedu 987: if (++dataline % 10 == 0)
1.16 ! tedu 988: outc('\n');
1.1 deraadt 989:
990: datapos = 0;
991: }
1.15 tedu 992: }
1.1 deraadt 993:
994:
995: /* The following is only needed when building flex's parser using certain
996: * broken versions of bison.
997: */
1.16 ! tedu 998: void *
! 999: yy_flex_xmalloc(size)
! 1000: int size;
1.15 tedu 1001: {
1.16 ! tedu 1002: void *result = flex_alloc((size_t) size);
1.15 tedu 1003:
1004: if (!result)
1.16 ! tedu 1005: flexfatal(_
! 1006: ("memory allocation failed in yy_flex_xmalloc()"));
1.1 deraadt 1007:
1008: return result;
1.15 tedu 1009: }
1.1 deraadt 1010:
1011:
1012: /* zero_out - set a region of memory to 0
1013: *
1014: * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero.
1015: */
1016:
1.16 ! tedu 1017: void
! 1018: zero_out(region_ptr, size_in_bytes)
! 1019: char *region_ptr;
! 1020: size_t size_in_bytes;
1.15 tedu 1021: {
1.6 mpech 1022: char *rp, *rp_end;
1.1 deraadt 1023:
1024: rp = region_ptr;
1025: rp_end = region_ptr + size_in_bytes;
1026:
1.15 tedu 1027: while (rp < rp_end)
1.1 deraadt 1028: *rp++ = 0;
1.15 tedu 1029: }
1030:
1031: /* Remove all '\n' and '\r' characters, if any, from the end of str.
1032: * str can be any null-terminated string, or NULL.
1033: * returns str. */
1.16 ! tedu 1034: char *
! 1035: chomp(str)
! 1036: char *str;
1.15 tedu 1037: {
1.16 ! tedu 1038: char *p = str;
1.15 tedu 1039:
1040: if (!str || !*str) /* s is null or empty string */
1041: return str;
1042:
1043: /* find end of string minus one */
1044: while (*p)
1045: ++p;
1046: --p;
1047:
1048: /* eat newlines */
1049: while (p >= str && (*p == '\r' || *p == '\n'))
1050: *p-- = 0;
1051: return str;
1052: }