1228072Sbapt/* misc - miscellaneous flex routines */ 2228072Sbapt 3228072Sbapt/* Copyright (c) 1990 The Regents of the University of California. */ 4228072Sbapt/* All rights reserved. */ 5228072Sbapt 6228072Sbapt/* This code is derived from software contributed to Berkeley by */ 7228072Sbapt/* Vern Paxson. */ 8228072Sbapt 9228072Sbapt/* The United States Government has rights in this work pursuant */ 10228072Sbapt/* to contract no. DE-AC03-76SF00098 between the United States */ 11228072Sbapt/* Department of Energy and the University of California. */ 12228072Sbapt 13228072Sbapt/* This file is part of flex. */ 14228072Sbapt 15228072Sbapt/* Redistribution and use in source and binary forms, with or without */ 16228072Sbapt/* modification, are permitted provided that the following conditions */ 17228072Sbapt/* are met: */ 18228072Sbapt 19228072Sbapt/* 1. Redistributions of source code must retain the above copyright */ 20228072Sbapt/* notice, this list of conditions and the following disclaimer. */ 21228072Sbapt/* 2. Redistributions in binary form must reproduce the above copyright */ 22228072Sbapt/* notice, this list of conditions and the following disclaimer in the */ 23228072Sbapt/* documentation and/or other materials provided with the distribution. */ 24228072Sbapt 25228072Sbapt/* Neither the name of the University nor the names of its contributors */ 26228072Sbapt/* may be used to endorse or promote products derived from this software */ 27228072Sbapt/* without specific prior written permission. */ 28228072Sbapt 29228072Sbapt/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 30228072Sbapt/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 31228072Sbapt/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 32228072Sbapt/* PURPOSE. */ 33228072Sbapt 34228072Sbapt#include "flexdef.h" 35228072Sbapt#include "tables.h" 36228072Sbapt 37228072Sbapt#define CMD_IF_TABLES_SER "%if-tables-serialization" 38228072Sbapt#define CMD_TABLES_YYDMAP "%tables-yydmap" 39228072Sbapt#define CMD_DEFINE_YYTABLES "%define-yytables" 40228072Sbapt#define CMD_IF_CPP_ONLY "%if-c++-only" 41228072Sbapt#define CMD_IF_C_ONLY "%if-c-only" 42228072Sbapt#define CMD_IF_C_OR_CPP "%if-c-or-c++" 43228072Sbapt#define CMD_NOT_FOR_HEADER "%not-for-header" 44228072Sbapt#define CMD_OK_FOR_HEADER "%ok-for-header" 45228072Sbapt#define CMD_PUSH "%push" 46228072Sbapt#define CMD_POP "%pop" 47228072Sbapt#define CMD_IF_REENTRANT "%if-reentrant" 48228072Sbapt#define CMD_IF_NOT_REENTRANT "%if-not-reentrant" 49228072Sbapt#define CMD_IF_BISON_BRIDGE "%if-bison-bridge" 50228072Sbapt#define CMD_IF_NOT_BISON_BRIDGE "%if-not-bison-bridge" 51228072Sbapt#define CMD_ENDIF "%endif" 52228072Sbapt 53228072Sbapt/* we allow the skeleton to push and pop. */ 54228072Sbaptstruct sko_state { 55228072Sbapt bool dc; /**< do_copy */ 56228072Sbapt}; 57228072Sbaptstatic struct sko_state *sko_stack=0; 58228072Sbaptstatic int sko_len=0,sko_sz=0; 59228072Sbaptstatic void sko_push(bool dc) 60228072Sbapt{ 61228072Sbapt if(!sko_stack){ 62228072Sbapt sko_sz = 1; 63228072Sbapt sko_stack = (struct sko_state*)flex_alloc(sizeof(struct sko_state)*sko_sz); 64250125Sjkim if (!sko_stack) 65250125Sjkim flexfatal(_("allocation of sko_stack failed")); 66228072Sbapt sko_len = 0; 67228072Sbapt } 68228072Sbapt if(sko_len >= sko_sz){ 69228072Sbapt sko_sz *= 2; 70228072Sbapt sko_stack = (struct sko_state*)flex_realloc(sko_stack,sizeof(struct sko_state)*sko_sz); 71228072Sbapt } 72228072Sbapt 73228072Sbapt /* initialize to zero and push */ 74228072Sbapt sko_stack[sko_len].dc = dc; 75228072Sbapt sko_len++; 76228072Sbapt} 77228072Sbaptstatic void sko_peek(bool *dc) 78228072Sbapt{ 79228072Sbapt if(sko_len <= 0) 80228072Sbapt flex_die("peek attempt when sko stack is empty"); 81228072Sbapt if(dc) 82228072Sbapt *dc = sko_stack[sko_len-1].dc; 83228072Sbapt} 84228072Sbaptstatic void sko_pop(bool* dc) 85228072Sbapt{ 86228072Sbapt sko_peek(dc); 87228072Sbapt sko_len--; 88228072Sbapt if(sko_len < 0) 89228072Sbapt flex_die("popped too many times in skeleton."); 90228072Sbapt} 91228072Sbapt 92228072Sbapt/* Append "#define defname value\n" to the running buffer. */ 93228072Sbaptvoid action_define (defname, value) 94228072Sbapt const char *defname; 95228072Sbapt int value; 96228072Sbapt{ 97228072Sbapt char buf[MAXLINE]; 98228072Sbapt char *cpy; 99228072Sbapt 100228072Sbapt if ((int) strlen (defname) > MAXLINE / 2) { 101228072Sbapt format_pinpoint_message (_ 102228072Sbapt ("name \"%s\" ridiculously long"), 103228072Sbapt defname); 104228072Sbapt return; 105228072Sbapt } 106228072Sbapt 107228072Sbapt snprintf (buf, sizeof(buf), "#define %s %d\n", defname, value); 108228072Sbapt add_action (buf); 109228072Sbapt 110228072Sbapt /* track #defines so we can undef them when we're done. */ 111228072Sbapt cpy = copy_string (defname); 112228072Sbapt buf_append (&defs_buf, &cpy, 1); 113228072Sbapt} 114228072Sbapt 115228072Sbapt 116250875Sjkim#ifdef notdef 117228072Sbapt/** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer. 118228072Sbapt * @param defname The macro name. 119228072Sbapt * @param value The macro value, can be NULL, which is the same as the empty string. 120228072Sbapt */ 121228072Sbaptvoid action_m4_define (const char *defname, const char * value) 122228072Sbapt{ 123228072Sbapt char buf[MAXLINE]; 124228072Sbapt 125228072Sbapt flexfatal ("DO NOT USE THIS FUNCTION!"); 126228072Sbapt 127228072Sbapt if ((int) strlen (defname) > MAXLINE / 2) { 128228072Sbapt format_pinpoint_message (_ 129228072Sbapt ("name \"%s\" ridiculously long"), 130228072Sbapt defname); 131228072Sbapt return; 132228072Sbapt } 133228072Sbapt 134228072Sbapt snprintf (buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value?value:""); 135228072Sbapt add_action (buf); 136228072Sbapt} 137250875Sjkim#endif 138228072Sbapt 139228072Sbapt/* Append "new_text" to the running buffer. */ 140228072Sbaptvoid add_action (new_text) 141228072Sbapt const char *new_text; 142228072Sbapt{ 143228072Sbapt int len = strlen (new_text); 144228072Sbapt 145228072Sbapt while (len + action_index >= action_size - 10 /* slop */ ) { 146228072Sbapt int new_size = action_size * 2; 147228072Sbapt 148228072Sbapt if (new_size <= 0) 149228072Sbapt /* Increase just a little, to try to avoid overflow 150228072Sbapt * on 16-bit machines. 151228072Sbapt */ 152228072Sbapt action_size += action_size / 8; 153228072Sbapt else 154228072Sbapt action_size = new_size; 155228072Sbapt 156228072Sbapt action_array = 157228072Sbapt reallocate_character_array (action_array, 158228072Sbapt action_size); 159228072Sbapt } 160228072Sbapt 161228072Sbapt strcpy (&action_array[action_index], new_text); 162228072Sbapt 163228072Sbapt action_index += len; 164228072Sbapt} 165228072Sbapt 166228072Sbapt 167228072Sbapt/* allocate_array - allocate memory for an integer array of the given size */ 168228072Sbapt 169228072Sbaptvoid *allocate_array (size, element_size) 170228072Sbapt int size; 171228072Sbapt size_t element_size; 172228072Sbapt{ 173250874Sjkim void *mem; 174228072Sbapt size_t num_bytes = element_size * size; 175228072Sbapt 176228072Sbapt mem = flex_alloc (num_bytes); 177228072Sbapt if (!mem) 178228072Sbapt flexfatal (_ 179228072Sbapt ("memory allocation failed in allocate_array()")); 180228072Sbapt 181228072Sbapt return mem; 182228072Sbapt} 183228072Sbapt 184228072Sbapt 185228072Sbapt/* all_lower - true if a string is all lower-case */ 186228072Sbapt 187228072Sbaptint all_lower (str) 188250874Sjkim char *str; 189228072Sbapt{ 190228072Sbapt while (*str) { 191250125Sjkim if (!isascii ((Char) * str) || !islower ((Char) * str)) 192228072Sbapt return 0; 193228072Sbapt ++str; 194228072Sbapt } 195228072Sbapt 196228072Sbapt return 1; 197228072Sbapt} 198228072Sbapt 199228072Sbapt 200228072Sbapt/* all_upper - true if a string is all upper-case */ 201228072Sbapt 202228072Sbaptint all_upper (str) 203250874Sjkim char *str; 204228072Sbapt{ 205228072Sbapt while (*str) { 206250125Sjkim if (!isascii ((Char) * str) || !isupper ((Char) * str)) 207228072Sbapt return 0; 208228072Sbapt ++str; 209228072Sbapt } 210228072Sbapt 211228072Sbapt return 1; 212228072Sbapt} 213228072Sbapt 214228072Sbapt 215250125Sjkim/* intcmp - compares two integers for use by qsort. */ 216228072Sbapt 217250125Sjkimint intcmp (const void *a, const void *b) 218228072Sbapt{ 219250125Sjkim return *(const int *) a - *(const int *) b; 220228072Sbapt} 221228072Sbapt 222228072Sbapt 223228072Sbapt/* check_char - checks a character to make sure it's within the range 224228072Sbapt * we're expecting. If not, generates fatal error message 225228072Sbapt * and exits. 226228072Sbapt */ 227228072Sbapt 228228072Sbaptvoid check_char (c) 229228072Sbapt int c; 230228072Sbapt{ 231228072Sbapt if (c >= CSIZE) 232228072Sbapt lerrsf (_("bad character '%s' detected in check_char()"), 233228072Sbapt readable_form (c)); 234228072Sbapt 235228072Sbapt if (c >= csize) 236228072Sbapt lerrsf (_ 237228072Sbapt ("scanner requires -8 flag to use the character %s"), 238228072Sbapt readable_form (c)); 239228072Sbapt} 240228072Sbapt 241228072Sbapt 242228072Sbapt 243228072Sbapt/* clower - replace upper-case letter to lower-case */ 244228072Sbapt 245228072SbaptChar clower (c) 246250874Sjkim int c; 247228072Sbapt{ 248228072Sbapt return (Char) ((isascii (c) && isupper (c)) ? tolower (c) : c); 249228072Sbapt} 250228072Sbapt 251228072Sbapt 252228072Sbapt/* copy_string - returns a dynamically allocated copy of a string */ 253228072Sbapt 254228072Sbaptchar *copy_string (str) 255250874Sjkim const char *str; 256228072Sbapt{ 257250874Sjkim const char *c1; 258250874Sjkim char *c2; 259228072Sbapt char *copy; 260228072Sbapt unsigned int size; 261228072Sbapt 262228072Sbapt /* find length */ 263228072Sbapt for (c1 = str; *c1; ++c1) ; 264228072Sbapt 265228072Sbapt size = (c1 - str + 1) * sizeof (char); 266228072Sbapt 267228072Sbapt copy = (char *) flex_alloc (size); 268228072Sbapt 269228072Sbapt if (copy == NULL) 270228072Sbapt flexfatal (_("dynamic memory failure in copy_string()")); 271228072Sbapt 272228072Sbapt for (c2 = copy; (*c2++ = *str++) != 0;) ; 273228072Sbapt 274228072Sbapt return copy; 275228072Sbapt} 276228072Sbapt 277228072Sbapt 278228072Sbapt/* copy_unsigned_string - 279228072Sbapt * returns a dynamically allocated copy of a (potentially) unsigned string 280228072Sbapt */ 281228072Sbapt 282228072SbaptChar *copy_unsigned_string (str) 283250874Sjkim Char *str; 284228072Sbapt{ 285250874Sjkim Char *c; 286228072Sbapt Char *copy; 287228072Sbapt 288228072Sbapt /* find length */ 289228072Sbapt for (c = str; *c; ++c) ; 290228072Sbapt 291228072Sbapt copy = allocate_Character_array (c - str + 1); 292228072Sbapt 293228072Sbapt for (c = copy; (*c++ = *str++) != 0;) ; 294228072Sbapt 295228072Sbapt return copy; 296228072Sbapt} 297228072Sbapt 298228072Sbapt 299250125Sjkim/* cclcmp - compares two characters for use by qsort with '\0' sorting last. */ 300228072Sbapt 301250125Sjkimint cclcmp (const void *a, const void *b) 302228072Sbapt{ 303250125Sjkim if (!*(const Char *) a) 304250125Sjkim return 1; 305250125Sjkim else 306250125Sjkim if (!*(const Char *) b) 307250125Sjkim return - 1; 308250125Sjkim else 309250125Sjkim return *(const Char *) a - *(const Char *) b; 310228072Sbapt} 311228072Sbapt 312228072Sbapt 313228072Sbapt/* dataend - finish up a block of data declarations */ 314228072Sbapt 315228072Sbaptvoid dataend () 316228072Sbapt{ 317228072Sbapt /* short circuit any output */ 318228072Sbapt if (gentables) { 319228072Sbapt 320228072Sbapt if (datapos > 0) 321228072Sbapt dataflush (); 322228072Sbapt 323228072Sbapt /* add terminator for initialization; { for vi */ 324228072Sbapt outn (" } ;\n"); 325228072Sbapt } 326228072Sbapt dataline = 0; 327228072Sbapt datapos = 0; 328228072Sbapt} 329228072Sbapt 330228072Sbapt 331228072Sbapt/* dataflush - flush generated data statements */ 332228072Sbapt 333228072Sbaptvoid dataflush () 334228072Sbapt{ 335228072Sbapt /* short circuit any output */ 336228072Sbapt if (!gentables) 337228072Sbapt return; 338228072Sbapt 339228072Sbapt outc ('\n'); 340228072Sbapt 341228072Sbapt if (++dataline >= NUMDATALINES) { 342228072Sbapt /* Put out a blank line so that the table is grouped into 343228072Sbapt * large blocks that enable the user to find elements easily. 344228072Sbapt */ 345228072Sbapt outc ('\n'); 346228072Sbapt dataline = 0; 347228072Sbapt } 348228072Sbapt 349228072Sbapt /* Reset the number of characters written on the current line. */ 350228072Sbapt datapos = 0; 351228072Sbapt} 352228072Sbapt 353228072Sbapt 354228072Sbapt/* flexerror - report an error message and terminate */ 355228072Sbapt 356228072Sbaptvoid flexerror (msg) 357228072Sbapt const char *msg; 358228072Sbapt{ 359228072Sbapt fprintf (stderr, "%s: %s\n", program_name, msg); 360228072Sbapt flexend (1); 361228072Sbapt} 362228072Sbapt 363228072Sbapt 364228072Sbapt/* flexfatal - report a fatal error message and terminate */ 365228072Sbapt 366228072Sbaptvoid flexfatal (msg) 367228072Sbapt const char *msg; 368228072Sbapt{ 369228072Sbapt fprintf (stderr, _("%s: fatal internal error, %s\n"), 370228072Sbapt program_name, msg); 371228072Sbapt FLEX_EXIT (1); 372228072Sbapt} 373228072Sbapt 374228072Sbapt 375228072Sbapt/* htoi - convert a hexadecimal digit string to an integer value */ 376228072Sbapt 377228072Sbaptint htoi (str) 378228072Sbapt Char str[]; 379228072Sbapt{ 380228072Sbapt unsigned int result; 381228072Sbapt 382228072Sbapt (void) sscanf ((char *) str, "%x", &result); 383228072Sbapt 384228072Sbapt return result; 385228072Sbapt} 386228072Sbapt 387228072Sbapt 388228072Sbapt/* lerrif - report an error message formatted with one integer argument */ 389228072Sbapt 390228072Sbaptvoid lerrif (msg, arg) 391228072Sbapt const char *msg; 392228072Sbapt int arg; 393228072Sbapt{ 394228072Sbapt char errmsg[MAXLINE]; 395228072Sbapt 396228072Sbapt snprintf (errmsg, sizeof(errmsg), msg, arg); 397228072Sbapt flexerror (errmsg); 398228072Sbapt} 399228072Sbapt 400228072Sbapt 401228072Sbapt/* lerrsf - report an error message formatted with one string argument */ 402228072Sbapt 403228072Sbaptvoid lerrsf (msg, arg) 404250125Sjkim const char *msg, arg[]; 405228072Sbapt{ 406228072Sbapt char errmsg[MAXLINE]; 407228072Sbapt 408250125Sjkim snprintf (errmsg, sizeof(errmsg)-1, msg, arg); 409250125Sjkim errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */ 410228072Sbapt flexerror (errmsg); 411228072Sbapt} 412228072Sbapt 413228072Sbapt 414250125Sjkim/* lerrsf_fatal - as lerrsf, but call flexfatal */ 415250125Sjkim 416250125Sjkimvoid lerrsf_fatal (msg, arg) 417250125Sjkim const char *msg, arg[]; 418250125Sjkim{ 419250125Sjkim char errmsg[MAXLINE]; 420250125Sjkim 421250125Sjkim snprintf (errmsg, sizeof(errmsg)-1, msg, arg); 422250125Sjkim errmsg[sizeof(errmsg)-1] = 0; /* ensure NULL termination */ 423250125Sjkim flexfatal (errmsg); 424250125Sjkim} 425250125Sjkim 426250125Sjkim 427228072Sbapt/* line_directive_out - spit out a "#line" statement */ 428228072Sbapt 429228072Sbaptvoid line_directive_out (output_file, do_infile) 430228072Sbapt FILE *output_file; 431228072Sbapt int do_infile; 432228072Sbapt{ 433228072Sbapt char directive[MAXLINE], filename[MAXLINE]; 434228072Sbapt char *s1, *s2, *s3; 435228072Sbapt static const char *line_fmt = "#line %d \"%s\"\n"; 436228072Sbapt 437228072Sbapt if (!gen_line_dirs) 438228072Sbapt return; 439228072Sbapt 440228072Sbapt s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME"; 441228072Sbapt 442228072Sbapt if (do_infile && !s1) 443228072Sbapt s1 = "<stdin>"; 444228072Sbapt 445228072Sbapt s2 = filename; 446228072Sbapt s3 = &filename[sizeof (filename) - 2]; 447228072Sbapt 448228072Sbapt while (s2 < s3 && *s1) { 449228072Sbapt if (*s1 == '\\') 450228072Sbapt /* Escape the '\' */ 451228072Sbapt *s2++ = '\\'; 452228072Sbapt 453228072Sbapt *s2++ = *s1++; 454228072Sbapt } 455228072Sbapt 456228072Sbapt *s2 = '\0'; 457228072Sbapt 458228072Sbapt if (do_infile) 459228072Sbapt snprintf (directive, sizeof(directive), line_fmt, linenum, filename); 460228072Sbapt else { 461250125Sjkim snprintf (directive, sizeof(directive), line_fmt, 0, filename); 462228072Sbapt } 463228072Sbapt 464228072Sbapt /* If output_file is nil then we should put the directive in 465228072Sbapt * the accumulated actions. 466228072Sbapt */ 467228072Sbapt if (output_file) { 468228072Sbapt fputs (directive, output_file); 469228072Sbapt } 470228072Sbapt else 471228072Sbapt add_action (directive); 472228072Sbapt} 473228072Sbapt 474228072Sbapt 475228072Sbapt/* mark_defs1 - mark the current position in the action array as 476228072Sbapt * representing where the user's section 1 definitions end 477228072Sbapt * and the prolog begins 478228072Sbapt */ 479228072Sbaptvoid mark_defs1 () 480228072Sbapt{ 481228072Sbapt defs1_offset = 0; 482228072Sbapt action_array[action_index++] = '\0'; 483228072Sbapt action_offset = prolog_offset = action_index; 484228072Sbapt action_array[action_index] = '\0'; 485228072Sbapt} 486228072Sbapt 487228072Sbapt 488228072Sbapt/* mark_prolog - mark the current position in the action array as 489228072Sbapt * representing the end of the action prolog 490228072Sbapt */ 491228072Sbaptvoid mark_prolog () 492228072Sbapt{ 493228072Sbapt action_array[action_index++] = '\0'; 494228072Sbapt action_offset = action_index; 495228072Sbapt action_array[action_index] = '\0'; 496228072Sbapt} 497228072Sbapt 498228072Sbapt 499228072Sbapt/* mk2data - generate a data statement for a two-dimensional array 500228072Sbapt * 501228072Sbapt * Generates a data statement initializing the current 2-D array to "value". 502228072Sbapt */ 503228072Sbaptvoid mk2data (value) 504228072Sbapt int value; 505228072Sbapt{ 506228072Sbapt /* short circuit any output */ 507228072Sbapt if (!gentables) 508228072Sbapt return; 509228072Sbapt 510228072Sbapt if (datapos >= NUMDATAITEMS) { 511228072Sbapt outc (','); 512228072Sbapt dataflush (); 513228072Sbapt } 514228072Sbapt 515228072Sbapt if (datapos == 0) 516228072Sbapt /* Indent. */ 517228072Sbapt out (" "); 518228072Sbapt 519228072Sbapt else 520228072Sbapt outc (','); 521228072Sbapt 522228072Sbapt ++datapos; 523228072Sbapt 524228072Sbapt out_dec ("%5d", value); 525228072Sbapt} 526228072Sbapt 527228072Sbapt 528228072Sbapt/* mkdata - generate a data statement 529228072Sbapt * 530228072Sbapt * Generates a data statement initializing the current array element to 531228072Sbapt * "value". 532228072Sbapt */ 533228072Sbaptvoid mkdata (value) 534228072Sbapt int value; 535228072Sbapt{ 536228072Sbapt /* short circuit any output */ 537228072Sbapt if (!gentables) 538228072Sbapt return; 539228072Sbapt 540228072Sbapt if (datapos >= NUMDATAITEMS) { 541228072Sbapt outc (','); 542228072Sbapt dataflush (); 543228072Sbapt } 544228072Sbapt 545228072Sbapt if (datapos == 0) 546228072Sbapt /* Indent. */ 547228072Sbapt out (" "); 548228072Sbapt else 549228072Sbapt outc (','); 550228072Sbapt 551228072Sbapt ++datapos; 552228072Sbapt 553228072Sbapt out_dec ("%5d", value); 554228072Sbapt} 555228072Sbapt 556228072Sbapt 557228072Sbapt/* myctoi - return the integer represented by a string of digits */ 558228072Sbapt 559228072Sbaptint myctoi (array) 560228072Sbapt const char *array; 561228072Sbapt{ 562228072Sbapt int val = 0; 563228072Sbapt 564228072Sbapt (void) sscanf (array, "%d", &val); 565228072Sbapt 566228072Sbapt return val; 567228072Sbapt} 568228072Sbapt 569228072Sbapt 570228072Sbapt/* myesc - return character corresponding to escape sequence */ 571228072Sbapt 572228072SbaptChar myesc (array) 573228072Sbapt Char array[]; 574228072Sbapt{ 575228072Sbapt Char c, esc_char; 576228072Sbapt 577228072Sbapt switch (array[1]) { 578228072Sbapt case 'b': 579228072Sbapt return '\b'; 580228072Sbapt case 'f': 581228072Sbapt return '\f'; 582228072Sbapt case 'n': 583228072Sbapt return '\n'; 584228072Sbapt case 'r': 585228072Sbapt return '\r'; 586228072Sbapt case 't': 587228072Sbapt return '\t'; 588228072Sbapt 589228072Sbapt#if defined (__STDC__) 590228072Sbapt case 'a': 591228072Sbapt return '\a'; 592228072Sbapt case 'v': 593228072Sbapt return '\v'; 594228072Sbapt#else 595228072Sbapt case 'a': 596228072Sbapt return '\007'; 597228072Sbapt case 'v': 598228072Sbapt return '\013'; 599228072Sbapt#endif 600228072Sbapt 601228072Sbapt case '0': 602228072Sbapt case '1': 603228072Sbapt case '2': 604228072Sbapt case '3': 605228072Sbapt case '4': 606228072Sbapt case '5': 607228072Sbapt case '6': 608228072Sbapt case '7': 609228072Sbapt { /* \<octal> */ 610228072Sbapt int sptr = 1; 611228072Sbapt 612228072Sbapt while (isascii (array[sptr]) && 613228072Sbapt isdigit (array[sptr])) 614228072Sbapt /* Don't increment inside loop control 615228072Sbapt * because if isdigit() is a macro it might 616228072Sbapt * expand into multiple increments ... 617228072Sbapt */ 618228072Sbapt ++sptr; 619228072Sbapt 620228072Sbapt c = array[sptr]; 621228072Sbapt array[sptr] = '\0'; 622228072Sbapt 623228072Sbapt esc_char = otoi (array + 1); 624228072Sbapt 625228072Sbapt array[sptr] = c; 626228072Sbapt 627228072Sbapt return esc_char; 628228072Sbapt } 629228072Sbapt 630228072Sbapt case 'x': 631228072Sbapt { /* \x<hex> */ 632228072Sbapt int sptr = 2; 633228072Sbapt 634228072Sbapt while (isascii (array[sptr]) && 635250125Sjkim isxdigit (array[sptr])) 636228072Sbapt /* Don't increment inside loop control 637228072Sbapt * because if isdigit() is a macro it might 638228072Sbapt * expand into multiple increments ... 639228072Sbapt */ 640228072Sbapt ++sptr; 641228072Sbapt 642228072Sbapt c = array[sptr]; 643228072Sbapt array[sptr] = '\0'; 644228072Sbapt 645228072Sbapt esc_char = htoi (array + 2); 646228072Sbapt 647228072Sbapt array[sptr] = c; 648228072Sbapt 649228072Sbapt return esc_char; 650228072Sbapt } 651228072Sbapt 652228072Sbapt default: 653228072Sbapt return array[1]; 654228072Sbapt } 655228072Sbapt} 656228072Sbapt 657228072Sbapt 658228072Sbapt/* otoi - convert an octal digit string to an integer value */ 659228072Sbapt 660228072Sbaptint otoi (str) 661228072Sbapt Char str[]; 662228072Sbapt{ 663228072Sbapt unsigned int result; 664228072Sbapt 665228072Sbapt (void) sscanf ((char *) str, "%o", &result); 666228072Sbapt return result; 667228072Sbapt} 668228072Sbapt 669228072Sbapt 670228072Sbapt/* out - various flavors of outputing a (possibly formatted) string for the 671228072Sbapt * generated scanner, keeping track of the line count. 672228072Sbapt */ 673228072Sbapt 674228072Sbaptvoid out (str) 675228072Sbapt const char *str; 676228072Sbapt{ 677228072Sbapt fputs (str, stdout); 678228072Sbapt} 679228072Sbapt 680228072Sbaptvoid out_dec (fmt, n) 681228072Sbapt const char *fmt; 682228072Sbapt int n; 683228072Sbapt{ 684228072Sbapt fprintf (stdout, fmt, n); 685228072Sbapt} 686228072Sbapt 687228072Sbaptvoid out_dec2 (fmt, n1, n2) 688228072Sbapt const char *fmt; 689228072Sbapt int n1, n2; 690228072Sbapt{ 691228072Sbapt fprintf (stdout, fmt, n1, n2); 692228072Sbapt} 693228072Sbapt 694228072Sbaptvoid out_hex (fmt, x) 695228072Sbapt const char *fmt; 696228072Sbapt unsigned int x; 697228072Sbapt{ 698228072Sbapt fprintf (stdout, fmt, x); 699228072Sbapt} 700228072Sbapt 701228072Sbaptvoid out_str (fmt, str) 702228072Sbapt const char *fmt, str[]; 703228072Sbapt{ 704228072Sbapt fprintf (stdout,fmt, str); 705228072Sbapt} 706228072Sbapt 707228072Sbaptvoid out_str3 (fmt, s1, s2, s3) 708228072Sbapt const char *fmt, s1[], s2[], s3[]; 709228072Sbapt{ 710228072Sbapt fprintf (stdout,fmt, s1, s2, s3); 711228072Sbapt} 712228072Sbapt 713228072Sbaptvoid out_str_dec (fmt, str, n) 714228072Sbapt const char *fmt, str[]; 715228072Sbapt int n; 716228072Sbapt{ 717228072Sbapt fprintf (stdout,fmt, str, n); 718228072Sbapt} 719228072Sbapt 720228072Sbaptvoid outc (c) 721228072Sbapt int c; 722228072Sbapt{ 723228072Sbapt fputc (c, stdout); 724228072Sbapt} 725228072Sbapt 726228072Sbaptvoid outn (str) 727228072Sbapt const char *str; 728228072Sbapt{ 729228072Sbapt fputs (str,stdout); 730228072Sbapt fputc('\n',stdout); 731228072Sbapt} 732228072Sbapt 733228072Sbapt/** Print "m4_define( [[def]], [[val]])m4_dnl\n". 734228072Sbapt * @param def The m4 symbol to define. 735228072Sbapt * @param val The definition; may be NULL. 736228072Sbapt * @return buf 737228072Sbapt */ 738228072Sbaptvoid out_m4_define (const char* def, const char* val) 739228072Sbapt{ 740228072Sbapt const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 741228072Sbapt fprintf(stdout, fmt, def, val?val:""); 742228072Sbapt} 743228072Sbapt 744228072Sbapt 745250874Sjkim/* readable_form - return the human-readable form of a character 746228072Sbapt * 747228072Sbapt * The returned string is in static storage. 748228072Sbapt */ 749228072Sbapt 750228072Sbaptchar *readable_form (c) 751250874Sjkim int c; 752228072Sbapt{ 753228072Sbapt static char rform[10]; 754228072Sbapt 755228072Sbapt if ((c >= 0 && c < 32) || c >= 127) { 756228072Sbapt switch (c) { 757228072Sbapt case '\b': 758228072Sbapt return "\\b"; 759228072Sbapt case '\f': 760228072Sbapt return "\\f"; 761228072Sbapt case '\n': 762228072Sbapt return "\\n"; 763228072Sbapt case '\r': 764228072Sbapt return "\\r"; 765228072Sbapt case '\t': 766228072Sbapt return "\\t"; 767228072Sbapt 768228072Sbapt#if defined (__STDC__) 769228072Sbapt case '\a': 770228072Sbapt return "\\a"; 771228072Sbapt case '\v': 772228072Sbapt return "\\v"; 773228072Sbapt#endif 774228072Sbapt 775228072Sbapt default: 776228072Sbapt snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c); 777228072Sbapt return rform; 778228072Sbapt } 779228072Sbapt } 780228072Sbapt 781228072Sbapt else if (c == ' ') 782228072Sbapt return "' '"; 783228072Sbapt 784228072Sbapt else { 785228072Sbapt rform[0] = c; 786228072Sbapt rform[1] = '\0'; 787228072Sbapt 788228072Sbapt return rform; 789228072Sbapt } 790228072Sbapt} 791228072Sbapt 792228072Sbapt 793228072Sbapt/* reallocate_array - increase the size of a dynamic array */ 794228072Sbapt 795228072Sbaptvoid *reallocate_array (array, size, element_size) 796228072Sbapt void *array; 797228072Sbapt int size; 798228072Sbapt size_t element_size; 799228072Sbapt{ 800250874Sjkim void *new_array; 801228072Sbapt size_t num_bytes = element_size * size; 802228072Sbapt 803228072Sbapt new_array = flex_realloc (array, num_bytes); 804228072Sbapt if (!new_array) 805228072Sbapt flexfatal (_("attempt to increase array size failed")); 806228072Sbapt 807228072Sbapt return new_array; 808228072Sbapt} 809228072Sbapt 810228072Sbapt 811228072Sbapt/* skelout - write out one section of the skeleton file 812228072Sbapt * 813228072Sbapt * Description 814228072Sbapt * Copies skelfile or skel array to stdout until a line beginning with 815228072Sbapt * "%%" or EOF is found. 816228072Sbapt */ 817228072Sbaptvoid skelout () 818228072Sbapt{ 819228072Sbapt char buf_storage[MAXLINE]; 820228072Sbapt char *buf = buf_storage; 821228072Sbapt bool do_copy = true; 822228072Sbapt 823228072Sbapt /* "reset" the state by clearing the buffer and pushing a '1' */ 824228072Sbapt if(sko_len > 0) 825228072Sbapt sko_peek(&do_copy); 826228072Sbapt sko_len = 0; 827228072Sbapt sko_push(do_copy=true); 828228072Sbapt 829228072Sbapt 830228072Sbapt /* Loop pulling lines either from the skelfile, if we're using 831228072Sbapt * one, or from the skel[] array. 832228072Sbapt */ 833228072Sbapt while (skelfile ? 834228072Sbapt (fgets (buf, MAXLINE, skelfile) != NULL) : 835228072Sbapt ((buf = (char *) skel[skel_ind++]) != 0)) { 836228072Sbapt 837228072Sbapt if (skelfile) 838228072Sbapt chomp (buf); 839228072Sbapt 840228072Sbapt /* copy from skel array */ 841228072Sbapt if (buf[0] == '%') { /* control line */ 842228072Sbapt /* print the control line as a comment. */ 843228072Sbapt if (ddebug && buf[1] != '#') { 844228072Sbapt if (buf[strlen (buf) - 1] == '\\') 845228072Sbapt out_str ("/* %s */\\\n", buf); 846228072Sbapt else 847228072Sbapt out_str ("/* %s */\n", buf); 848228072Sbapt } 849228072Sbapt 850228072Sbapt /* We've been accused of using cryptic markers in the skel. 851228072Sbapt * So we'll use emacs-style-hyphenated-commands. 852228072Sbapt * We might consider a hash if this if-else-if-else 853228072Sbapt * chain gets too large. 854228072Sbapt */ 855228072Sbapt#define cmd_match(s) (strncmp(buf,(s),strlen(s))==0) 856228072Sbapt 857228072Sbapt if (buf[1] == '%') { 858228072Sbapt /* %% is a break point for skelout() */ 859228072Sbapt return; 860228072Sbapt } 861228072Sbapt else if (cmd_match (CMD_PUSH)){ 862228072Sbapt sko_push(do_copy); 863228072Sbapt if(ddebug){ 864228072Sbapt out_str("/*(state = (%s) */",do_copy?"true":"false"); 865228072Sbapt } 866228072Sbapt out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : ""); 867228072Sbapt } 868228072Sbapt else if (cmd_match (CMD_POP)){ 869228072Sbapt sko_pop(&do_copy); 870228072Sbapt if(ddebug){ 871228072Sbapt out_str("/*(state = (%s) */",do_copy?"true":"false"); 872228072Sbapt } 873228072Sbapt out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : ""); 874228072Sbapt } 875228072Sbapt else if (cmd_match (CMD_IF_REENTRANT)){ 876228072Sbapt sko_push(do_copy); 877228072Sbapt do_copy = reentrant && do_copy; 878228072Sbapt } 879228072Sbapt else if (cmd_match (CMD_IF_NOT_REENTRANT)){ 880228072Sbapt sko_push(do_copy); 881228072Sbapt do_copy = !reentrant && do_copy; 882228072Sbapt } 883228072Sbapt else if (cmd_match(CMD_IF_BISON_BRIDGE)){ 884228072Sbapt sko_push(do_copy); 885228072Sbapt do_copy = bison_bridge_lval && do_copy; 886228072Sbapt } 887228072Sbapt else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){ 888228072Sbapt sko_push(do_copy); 889228072Sbapt do_copy = !bison_bridge_lval && do_copy; 890228072Sbapt } 891228072Sbapt else if (cmd_match (CMD_ENDIF)){ 892228072Sbapt sko_pop(&do_copy); 893228072Sbapt } 894228072Sbapt else if (cmd_match (CMD_IF_TABLES_SER)) { 895228072Sbapt do_copy = do_copy && tablesext; 896228072Sbapt } 897228072Sbapt else if (cmd_match (CMD_TABLES_YYDMAP)) { 898228072Sbapt if (tablesext && yydmap_buf.elts) 899228072Sbapt outn ((char *) (yydmap_buf.elts)); 900228072Sbapt } 901228072Sbapt else if (cmd_match (CMD_DEFINE_YYTABLES)) { 902228072Sbapt out_str("#define YYTABLES_NAME \"%s\"\n", 903228072Sbapt tablesname?tablesname:"yytables"); 904228072Sbapt } 905228072Sbapt else if (cmd_match (CMD_IF_CPP_ONLY)) { 906228072Sbapt /* only for C++ */ 907228072Sbapt sko_push(do_copy); 908228072Sbapt do_copy = C_plus_plus; 909228072Sbapt } 910228072Sbapt else if (cmd_match (CMD_IF_C_ONLY)) { 911228072Sbapt /* %- only for C */ 912228072Sbapt sko_push(do_copy); 913228072Sbapt do_copy = !C_plus_plus; 914228072Sbapt } 915228072Sbapt else if (cmd_match (CMD_IF_C_OR_CPP)) { 916228072Sbapt /* %* for C and C++ */ 917228072Sbapt sko_push(do_copy); 918228072Sbapt do_copy = true; 919228072Sbapt } 920228072Sbapt else if (cmd_match (CMD_NOT_FOR_HEADER)) { 921228072Sbapt /* %c begin linkage-only (non-header) code. */ 922228072Sbapt OUT_BEGIN_CODE (); 923228072Sbapt } 924228072Sbapt else if (cmd_match (CMD_OK_FOR_HEADER)) { 925228072Sbapt /* %e end linkage-only code. */ 926228072Sbapt OUT_END_CODE (); 927228072Sbapt } 928228072Sbapt else if (buf[1] == '#') { 929228072Sbapt /* %# a comment in the skel. ignore. */ 930228072Sbapt } 931228072Sbapt else { 932228072Sbapt flexfatal (_("bad line in skeleton file")); 933228072Sbapt } 934228072Sbapt } 935228072Sbapt 936228072Sbapt else if (do_copy) 937228072Sbapt outn (buf); 938228072Sbapt } /* end while */ 939228072Sbapt} 940228072Sbapt 941228072Sbapt 942228072Sbapt/* transition_struct_out - output a yy_trans_info structure 943228072Sbapt * 944228072Sbapt * outputs the yy_trans_info structure with the two elements, element_v and 945228072Sbapt * element_n. Formats the output with spaces and carriage returns. 946228072Sbapt */ 947228072Sbapt 948228072Sbaptvoid transition_struct_out (element_v, element_n) 949228072Sbapt int element_v, element_n; 950228072Sbapt{ 951228072Sbapt 952228072Sbapt /* short circuit any output */ 953228072Sbapt if (!gentables) 954228072Sbapt return; 955228072Sbapt 956228072Sbapt out_dec2 (" {%4d,%4d },", element_v, element_n); 957228072Sbapt 958228072Sbapt datapos += TRANS_STRUCT_PRINT_LENGTH; 959228072Sbapt 960228072Sbapt if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) { 961228072Sbapt outc ('\n'); 962228072Sbapt 963228072Sbapt if (++dataline % 10 == 0) 964228072Sbapt outc ('\n'); 965228072Sbapt 966228072Sbapt datapos = 0; 967228072Sbapt } 968228072Sbapt} 969228072Sbapt 970228072Sbapt 971228072Sbapt/* The following is only needed when building flex's parser using certain 972228072Sbapt * broken versions of bison. 973228072Sbapt */ 974228072Sbaptvoid *yy_flex_xmalloc (size) 975228072Sbapt int size; 976228072Sbapt{ 977228072Sbapt void *result = flex_alloc ((size_t) size); 978228072Sbapt 979228072Sbapt if (!result) 980228072Sbapt flexfatal (_ 981228072Sbapt ("memory allocation failed in yy_flex_xmalloc()")); 982228072Sbapt 983228072Sbapt return result; 984228072Sbapt} 985228072Sbapt 986228072Sbapt 987228072Sbapt/* zero_out - set a region of memory to 0 988228072Sbapt * 989228072Sbapt * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero. 990228072Sbapt */ 991228072Sbapt 992228072Sbaptvoid zero_out (region_ptr, size_in_bytes) 993228072Sbapt char *region_ptr; 994228072Sbapt size_t size_in_bytes; 995228072Sbapt{ 996250874Sjkim char *rp, *rp_end; 997228072Sbapt 998228072Sbapt rp = region_ptr; 999228072Sbapt rp_end = region_ptr + size_in_bytes; 1000228072Sbapt 1001228072Sbapt while (rp < rp_end) 1002228072Sbapt *rp++ = 0; 1003228072Sbapt} 1004228072Sbapt 1005228072Sbapt/* Remove all '\n' and '\r' characters, if any, from the end of str. 1006228072Sbapt * str can be any null-terminated string, or NULL. 1007228072Sbapt * returns str. */ 1008228072Sbaptchar *chomp (str) 1009228072Sbapt char *str; 1010228072Sbapt{ 1011228072Sbapt char *p = str; 1012228072Sbapt 1013228072Sbapt if (!str || !*str) /* s is null or empty string */ 1014228072Sbapt return str; 1015228072Sbapt 1016228072Sbapt /* find end of string minus one */ 1017228072Sbapt while (*p) 1018228072Sbapt ++p; 1019228072Sbapt --p; 1020228072Sbapt 1021228072Sbapt /* eat newlines */ 1022228072Sbapt while (p >= str && (*p == '\r' || *p == '\n')) 1023228072Sbapt *p-- = 0; 1024228072Sbapt return str; 1025228072Sbapt} 1026