Annotation of src/usr.bin/lex/misc.c, Revision 1.20
1.20 ! jmc 1: /* $OpenBSD: misc.c,v 1.19 2015/11/19 23:34:56 mmcc 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;
1.18 tedu 66: sko_stack = malloc(sizeof(struct sko_state) * sko_sz);
1.16 tedu 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;
1.18 tedu 73: sko_stack = realloc(sko_stack, sizeof(struct sko_state) * sko_sz);
1.16 tedu 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.18 tedu 182: mem = malloc(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.19 mmcc 198: if (!isascii((u_char) * str) || !islower((u_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.19 mmcc 214: if (!isascii((u_char) * str) || !isupper((u_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.19 mmcc 255: u_char
1.16 tedu 256: clower(c)
257: int c;
1.15 tedu 258: {
1.19 mmcc 259: return (u_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.18 tedu 279: copy = (char *) malloc(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.19 mmcc 294: u_char *
1.16 tedu 295: copy_unsigned_string(str)
1.19 mmcc 296: u_char *str;
1.15 tedu 297: {
1.19 mmcc 298: u_char *c;
299: u_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.19 mmcc 317: if (!*(const u_char *) a)
1.16 tedu 318: return 1;
1.19 mmcc 319: else if (!*(const u_char *) b)
1.16 tedu 320: return -1;
1.15 tedu 321: else
1.19 mmcc 322: return *(const u_char *) a - *(const u_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)
1.19 mmcc 396: u_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.19 mmcc 597: u_char
1.16 tedu 598: myesc(array)
1.19 mmcc 599: u_char array[];
1.15 tedu 600: {
1.19 mmcc 601: u_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)
1.19 mmcc 690: u_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:
1.20 ! jmc 699: /* out - various flavors of outputting a (possibly formatted) string for the
1.1 deraadt 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.18 tedu 842: new_array = 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.18 tedu 1002: void *result = malloc((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:
1.15 tedu 1011:
1012: /* Remove all '\n' and '\r' characters, if any, from the end of str.
1013: * str can be any null-terminated string, or NULL.
1014: * returns str. */
1.16 tedu 1015: char *
1016: chomp(str)
1017: char *str;
1.15 tedu 1018: {
1.16 tedu 1019: char *p = str;
1.15 tedu 1020:
1021: if (!str || !*str) /* s is null or empty string */
1022: return str;
1023:
1024: /* find end of string minus one */
1025: while (*p)
1026: ++p;
1027: --p;
1028:
1029: /* eat newlines */
1030: while (p >= str && (*p == '\r' || *p == '\n'))
1031: *p-- = 0;
1032: return str;
1033: }