home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / FLEX246 / MISC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-10  |  14.3 KB  |  781 lines

  1. /* misc - miscellaneous flex routines */
  2.  
  3. /*-
  4.  * Copyright (c) 1990 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  * 
  10.  * The United States Government has rights in this work pursuant
  11.  * to contract no. DE-AC03-76SF00098 between the United States
  12.  * Department of Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted provided
  15.  * that: (1) source distributions retain this entire copyright notice and
  16.  * comment, and (2) distributions including binaries display the following
  17.  * acknowledgement:  ``This product includes software developed by the
  18.  * University of California, Berkeley and its contributors'' in the
  19.  * documentation or other materials provided with the distribution and in
  20.  * all advertising materials mentioning features or use of this software.
  21.  * Neither the name of the University nor the names of its contributors may
  22.  * be used to endorse or promote products derived from this software without
  23.  * specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  25.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  27.  */
  28.  
  29. /* $Header: misc.c,v 1.2 94/01/04 14:33:10 vern Exp $ */
  30.  
  31. #include "flexdef.h"
  32.  
  33.  
  34.  
  35. /* declare functions that have forward references */
  36.  
  37. void dataflush PROTO((void));
  38. int otoi PROTO((Char []));
  39.  
  40.  
  41. void add_action( new_text )
  42. char *new_text;
  43.     {
  44.     int len = strlen( new_text );
  45.  
  46.     while ( len + action_index >= action_size - 10 /* slop */ )
  47.         {
  48.         action_size *= 2;
  49.         action_array =
  50.             reallocate_character_array( action_array, action_size );
  51.         }
  52.  
  53.     strcpy( &action_array[action_index], new_text );
  54.  
  55.     action_index += len;
  56.     }
  57.  
  58.  
  59. /* allocate_array - allocate memory for an integer array of the given size */
  60.  
  61. void *allocate_array( size, element_size )
  62. int size, element_size;
  63.     {
  64.     register void *mem;
  65.  
  66.     /* On 16-bit int machines (e.g., 80286) we might be trying to
  67.      * allocate more than a signed int can hold, and that won't
  68.      * work.  Cheap test:
  69.      */
  70.     if ( element_size * size <= 0 )
  71.         flexfatal( "request for < 1 byte in allocate_array()" );
  72.  
  73.     mem = flex_alloc( element_size * size );
  74.  
  75.     if ( mem == NULL )
  76.         flexfatal( "memory allocation failed in allocate_array()" );
  77.  
  78.     return mem;
  79.     }
  80.  
  81.  
  82. /* all_lower - true if a string is all lower-case */
  83.  
  84. int all_lower( str )
  85. register char *str;
  86.     {
  87.     while ( *str )
  88.         {
  89.         if ( ! isascii( (Char) *str ) || ! islower( *str ) )
  90.             return 0;
  91.         ++str;
  92.         }
  93.  
  94.     return 1;
  95.     }
  96.  
  97.  
  98. /* all_upper - true if a string is all upper-case */
  99.  
  100. int all_upper( str )
  101. register char *str;
  102.     {
  103.     while ( *str )
  104.         {
  105.         if ( ! isascii( (Char) *str ) || ! isupper( *str ) )
  106.             return 0;
  107.         ++str;
  108.         }
  109.  
  110.     return 1;
  111.     }
  112.  
  113.  
  114. /* bubble - bubble sort an integer array in increasing order
  115.  *
  116.  * synopsis
  117.  *   int v[n], n;
  118.  *   void bubble( v, n );
  119.  *
  120.  * description
  121.  *   sorts the first n elements of array v and replaces them in
  122.  *   increasing order.
  123.  *
  124.  * passed
  125.  *   v - the array to be sorted
  126.  *   n - the number of elements of 'v' to be sorted
  127.  */
  128.  
  129. void bubble( v, n )
  130. int v[], n;
  131.     {
  132.     register int i, j, k;
  133.  
  134.     for ( i = n; i > 1; --i )
  135.         for ( j = 1; j < i; ++j )
  136.             if ( v[j] > v[j + 1] )    /* compare */
  137.                 {
  138.                 k = v[j];    /* exchange */
  139.                 v[j] = v[j + 1];
  140.                 v[j + 1] = k;
  141.                 }
  142.     }
  143.  
  144.  
  145. /* check_char - checks a character to make sure it's within the range
  146.  *        we're expecting.  If not, generates fatal error message
  147.  *        and exits.
  148.  */
  149.  
  150. void check_char( c )
  151. int c;
  152.     {
  153.     if ( c >= CSIZE )
  154.         lerrsf( "bad character '%s' detected in check_char()",
  155.             readable_form( c ) );
  156.  
  157.     if ( c >= csize )
  158.         lerrsf( "scanner requires -8 flag to use the character '%s'",
  159.             readable_form( c ) );
  160.     }
  161.  
  162.  
  163.  
  164. /* clower - replace upper-case letter to lower-case */
  165.  
  166. Char clower( c )
  167. register int c;
  168.     {
  169.     return (Char) ((isascii( c ) && isupper( c )) ? tolower( c ) : c);
  170.     }
  171.  
  172.  
  173. /* copy_string - returns a dynamically allocated copy of a string */
  174.  
  175. char *copy_string( str )
  176. register char *str;
  177.     {
  178.     register char *c;
  179.     char *copy;
  180.  
  181.     /* find length */
  182.     for ( c = str; *c; ++c )
  183.         ;
  184.  
  185.     copy = (char *) flex_alloc( (c - str + 1) * sizeof( char ) );
  186.  
  187.     if ( copy == NULL )
  188.         flexfatal( "dynamic memory failure in copy_string()" );
  189.  
  190.     for ( c = copy; (*c++ = *str++); )
  191.         ;
  192.  
  193.     return copy;
  194.     }
  195.  
  196.  
  197. /* copy_unsigned_string -
  198.  *    returns a dynamically allocated copy of a (potentially) unsigned string
  199.  */
  200.  
  201. Char *copy_unsigned_string( str )
  202. register Char *str;
  203.     {
  204.     register Char *c;
  205.     Char *copy;
  206.  
  207.     /* find length */
  208.     for ( c = str; *c; ++c )
  209.         ;
  210.  
  211.     copy = allocate_Character_array( c - str + 1 );
  212.  
  213.     for ( c = copy; (*c++ = *str++); )
  214.         ;
  215.  
  216.     return copy;
  217.     }
  218.  
  219.  
  220. /* cshell - shell sort a character array in increasing order
  221.  *
  222.  * synopsis
  223.  *
  224.  *   Char v[n];
  225.  *   int n, special_case_0;
  226.  *   cshell( v, n, special_case_0 );
  227.  *
  228.  * description
  229.  *   Does a shell sort of the first n elements of array v.
  230.  *   If special_case_0 is true, then any element equal to 0
  231.  *   is instead assumed to have infinite weight.
  232.  *
  233.  * passed
  234.  *   v - array to be sorted
  235.  *   n - number of elements of v to be sorted
  236.  */
  237.  
  238. void cshell( v, n, special_case_0 )
  239. Char v[];
  240. int n, special_case_0;
  241.     {
  242.     int gap, i, j, jg;
  243.     Char k;
  244.  
  245.     for ( gap = n / 2; gap > 0; gap = gap / 2 )
  246.         for ( i = gap; i < n; ++i )
  247.             for ( j = i - gap; j >= 0; j = j - gap )
  248.                 {
  249.                 jg = j + gap;
  250.  
  251.                 if ( special_case_0 )
  252.                     {
  253.                     if ( v[jg] == 0 )
  254.                         break;
  255.  
  256.                     else if ( v[j] != 0 && v[j] <= v[jg] )
  257.                         break;
  258.                     }
  259.  
  260.                 else if ( v[j] <= v[jg] )
  261.                     break;
  262.  
  263.                 k = v[j];
  264.                 v[j] = v[jg];
  265.                 v[jg] = k;
  266.                 }
  267.     }
  268.  
  269.  
  270. /* dataend - finish up a block of data declarations */
  271.  
  272. void dataend()
  273.     {
  274.     if ( datapos > 0 )
  275.         dataflush();
  276.  
  277.     /* add terminator for initialization; { for vi */
  278.     puts( "    } ;\n" );
  279.  
  280.     dataline = 0;
  281.     datapos = 0;
  282.     }
  283.  
  284.  
  285. /* dataflush - flush generated data statements */
  286.  
  287. void dataflush()
  288.     {
  289.     putchar( '\n' );
  290.  
  291.     if ( ++dataline >= NUMDATALINES )
  292.         {
  293.         /* Put out a blank line so that the table is grouped into
  294.          * large blocks that enable the user to find elements easily.
  295.          */
  296.         putchar( '\n' );
  297.         dataline = 0;
  298.         }
  299.  
  300.     /* Reset the number of characters written on the current line. */
  301.     datapos = 0;
  302.     }
  303.  
  304.  
  305. /* flexerror - report an error message and terminate */
  306.  
  307. void flexerror( msg )
  308. char msg[];
  309.     {
  310.     fprintf( stderr, "%s: %s\n", program_name, msg );
  311.     flexend( 1 );
  312.     }
  313.  
  314.  
  315. /* flexfatal - report a fatal error message and terminate */
  316.  
  317. void flexfatal( msg )
  318. char msg[];
  319.     {
  320.     fprintf( stderr, "%s: fatal internal error, %s\n", program_name, msg );
  321.     exit( 1 );
  322.     }
  323.  
  324.  
  325. /* lerrif - report an error message formatted with one integer argument */
  326.  
  327. void lerrif( msg, arg )
  328. char msg[];
  329. int arg;
  330.     {
  331.     char errmsg[MAXLINE];
  332.     (void) sprintf( errmsg, msg, arg );
  333.     flexerror( errmsg );
  334.     }
  335.  
  336.  
  337. /* lerrsf - report an error message formatted with one string argument */
  338.  
  339. void lerrsf( msg, arg )
  340. char msg[], arg[];
  341.     {
  342.     char errmsg[MAXLINE];
  343.  
  344.     (void) sprintf( errmsg, msg, arg );
  345.     flexerror( errmsg );
  346.     }
  347.  
  348.  
  349. /* htoi - convert a hexadecimal digit string to an integer value */
  350.  
  351. int htoi( str )
  352. Char str[];
  353.     {
  354.     unsigned int result;
  355.  
  356.     (void) sscanf( (char *) str, "%x", &result );
  357.  
  358.     return result;
  359.     }
  360.  
  361.  
  362. /* is_hex_digit - returns true if a character is a valid hex digit, false
  363.  *          otherwise
  364.  */
  365.  
  366. int is_hex_digit( ch )
  367. int ch;
  368.     {
  369.     if ( isdigit( ch ) )
  370.         return 1;
  371.  
  372.     switch ( clower( ch ) )
  373.         {
  374.         case 'a':
  375.         case 'b':
  376.         case 'c':
  377.         case 'd':
  378.         case 'e':
  379.         case 'f':
  380.             return 1;
  381.  
  382.         default:
  383.             return 0;
  384.         }
  385.     }
  386.  
  387.  
  388. /* line_directive_out - spit out a "# line" statement */
  389.  
  390. void line_directive_out( output_file )
  391. FILE *output_file;
  392.     {
  393.     if ( infilename && gen_line_dirs )
  394.         {
  395.         char directive[MAXLINE];
  396. #if defined(OS2) || defined(MS_DOS)
  397.         char path[MAXLINE], *p, *w;
  398.         for ( p = infilename, w = path; *p; p++, w++ )
  399.           *w = (*p == '\\') ? '/' : *p;
  400.         *w = 0;
  401.         sprintf( directive, "# line %d \"%s\"\n", linenum, path );
  402. #else
  403.         sprintf( directive, "# line %d \"%s\"\n", linenum, infilename );
  404. #endif
  405.         /* If output_file is nil then we should put the directive in
  406.          * the accumulated actions.
  407.          */
  408.         if ( output_file )
  409.             fputs( directive, output_file );
  410.         else
  411.             add_action( directive );
  412.         }
  413.     }
  414.  
  415.  
  416. /* mark_defs1 - mark the current position in the action array as
  417.  *               representing where the user's section 1 definitions end
  418.  *         and the prolog begins
  419.  */
  420. void mark_defs1()
  421.     {
  422.     defs1_offset = 0;
  423.     action_array[action_index++] = '\0';
  424.     action_offset = prolog_offset = action_index;
  425.     action_array[action_index] = '\0';
  426.     }
  427.  
  428.  
  429. /* mark_prolog - mark the current position in the action array as
  430.  *               representing the end of the action prolog
  431.  */
  432. void mark_prolog()
  433.     {
  434.     action_array[action_index++] = '\0';
  435.     action_offset = action_index;
  436.     action_array[action_index] = '\0';
  437.     }
  438.  
  439.  
  440. /* mk2data - generate a data statement for a two-dimensional array
  441.  *
  442.  * Generates a data statement initializing the current 2-D array to "value".
  443.  */
  444. void mk2data( value )
  445. int value;
  446.     {
  447.     if ( datapos >= NUMDATAITEMS )
  448.         {
  449.         putchar( ',' );
  450.         dataflush();
  451.         }
  452.  
  453.     if ( datapos == 0 )
  454.         /* Indent. */
  455.         fputs( "    ", stdout );
  456.  
  457.     else
  458.         putchar( ',' );
  459.  
  460.     ++datapos;
  461.  
  462.     printf( "%5d", value );
  463.     }
  464.  
  465.  
  466. /* mkdata - generate a data statement
  467.  *
  468.  * Generates a data statement initializing the current array element to
  469.  * "value".
  470.  */
  471. void mkdata( value )
  472. int value;
  473.     {
  474.     if ( datapos >= NUMDATAITEMS )
  475.         {
  476.         putchar( ',' );
  477.         dataflush();
  478.         }
  479.  
  480.     if ( datapos == 0 )
  481.         /* Indent. */
  482.         fputs( "    ", stdout );
  483.     else
  484.         putchar( ',' );
  485.  
  486.     ++datapos;
  487.  
  488.     printf( "%5d", value );
  489.     }
  490.  
  491.  
  492. /* myctoi - return the integer represented by a string of digits */
  493.  
  494. int myctoi( array )
  495. char array[];
  496.     {
  497.     int val = 0;
  498.  
  499.     (void) sscanf( array, "%d", &val );
  500.  
  501.     return val;
  502.     }
  503.  
  504.  
  505. /* myesc - return character corresponding to escape sequence */
  506.  
  507. Char myesc( array )
  508. Char array[];
  509.     {
  510.     Char c, esc_char;
  511.  
  512.     switch ( array[1] )
  513.         {
  514.         case 'b': return '\b';
  515.         case 'f': return '\f';
  516.         case 'n': return '\n';
  517.         case 'r': return '\r';
  518.         case 't': return '\t';
  519.  
  520. #ifdef __STDC__
  521.         case 'a': return '\a';
  522.         case 'v': return '\v';
  523. #else
  524.         case 'a': return '\007';
  525.         case 'v': return '\013';
  526. #endif
  527.  
  528.         case '0':
  529.         case '1':
  530.         case '2':
  531.         case '3':
  532.         case '4':
  533.         case '5':
  534.         case '6':
  535.         case '7':
  536.         case '8':
  537.         case '9':
  538.             { /* \<octal> */
  539.             int sptr = 1;
  540.  
  541.             while ( isascii( array[sptr] ) &&
  542.                 isdigit( array[sptr] ) )
  543.                 /* Don't increment inside loop control
  544.                  * because if isdigit() is a macro it might
  545.                  * expand into multiple increments ...
  546.                  */
  547.                 ++sptr;
  548.  
  549.             c = array[sptr];
  550.             array[sptr] = '\0';
  551.  
  552.             esc_char = otoi( array + 1 );
  553.  
  554.             array[sptr] = c;
  555.  
  556.             return esc_char;
  557.             }
  558.  
  559.         case 'x':
  560.             { /* \x<hex> */
  561.             int sptr = 2;
  562.  
  563.             while ( isascii( array[sptr] ) &&
  564.                 is_hex_digit( (char) array[sptr] ) )
  565.                 /* Don't increment inside loop control
  566.                  * because if isdigit() is a macro it might
  567.                  * expand into multiple increments ...
  568.                  */
  569.                 ++sptr;
  570.  
  571.             c = array[sptr];
  572.             array[sptr] = '\0';
  573.  
  574.             esc_char = htoi( array + 2 );
  575.  
  576.             array[sptr] = c;
  577.  
  578.             return esc_char;
  579.             }
  580.  
  581.         default:
  582.             return array[1];
  583.         }
  584.     }
  585.  
  586.  
  587. /* otoi - convert an octal digit string to an integer value */
  588.  
  589. int otoi( str )
  590. Char str[];
  591.     {
  592.     unsigned int result;
  593.  
  594.     (void) sscanf( (char *) str, "%o", &result );
  595.     return result;
  596.     }
  597.  
  598.  
  599. /* readable_form - return the the human-readable form of a character
  600.  *
  601.  * The returned string is in static storage.
  602.  */
  603.  
  604. char *readable_form( c )
  605. register int c;
  606.     {
  607.     static char rform[10];
  608.  
  609.     if ( (c >= 0 && c < 32) || c >= 127 )
  610.         {
  611.         switch ( c )
  612.             {
  613.             case '\b': return "\\b";
  614.             case '\f': return "\\f";
  615.             case '\n': return "\\n";
  616.             case '\r': return "\\r";
  617.             case '\t': return "\\t";
  618.  
  619. #ifdef __STDC__
  620.             case '\a': return "\\a";
  621.             case '\v': return "\\v";
  622. #endif
  623.  
  624.             default:
  625.                 (void) sprintf( rform, "\\%.3o",
  626.                         (unsigned int) c );
  627.                 return rform;
  628.             }
  629.         }
  630.  
  631.     else if ( c == ' ' )
  632.         return "' '";
  633.  
  634.     else
  635.         {
  636.         rform[0] = c;
  637.         rform[1] = '\0';
  638.  
  639.         return rform;
  640.         }
  641.     }
  642.  
  643.  
  644. /* reallocate_array - increase the size of a dynamic array */
  645.  
  646. void *reallocate_array( array, size, element_size )
  647. void *array;
  648. int size, element_size;
  649.     {
  650.     register void *new_array;
  651.  
  652.     /* Same worry as in allocate_array(): */
  653.     if ( size * element_size <= 0 )
  654.         flexfatal(
  655.             "attempt to increase array size by less than 1 byte" );
  656.  
  657.     new_array = flex_realloc( array, size * element_size );
  658.  
  659.     if ( new_array == NULL )
  660.         flexfatal( "attempt to increase array size failed" );
  661.  
  662.     return new_array;
  663.     }
  664.  
  665.  
  666. /* skelout - write out one section of the skeleton file
  667.  *
  668.  * Description
  669.  *    Copies skelfile or skel array to stdout until a line beginning with
  670.  *    "%%" or EOF is found.
  671.  */
  672. void skelout()
  673.     {
  674.     char buf_storage[MAXLINE];
  675.     char *buf = buf_storage;
  676.     int do_copy = 1;
  677.  
  678.     /* Loop pulling lines either from the skelfile, if we're using
  679.      * one, or from the skel[] array.
  680.      */
  681.     while ( skelfile ?
  682.         (fgets( buf, MAXLINE, skelfile ) != NULL) :
  683.         ((buf = skel[skel_ind++]) != 0) )
  684.         { /* copy from skel array */
  685.         if ( buf[0] == '%' )
  686.             { /* control line */
  687.             switch ( buf[1] )
  688.                 {
  689.                 case '%':
  690.                     return;
  691.  
  692.                 case '+':
  693.                     do_copy = C_plus_plus;
  694.                     break;
  695.  
  696.                 case '-':
  697.                     do_copy = ! C_plus_plus;
  698.                     break;
  699.  
  700.                 case '*':
  701.                     do_copy = 1;
  702.                     break;
  703.  
  704.                 default:
  705.                     flexfatal(
  706.                         "bad line in skeleton file" );
  707.                 }
  708.             }
  709.  
  710.         else if ( do_copy )
  711.             {
  712.             if ( skelfile )
  713.                 /* Skeleton file reads include final
  714.                  * newline, skel[] array does not.
  715.                  */
  716.                 fputs( buf, stdout );
  717.             else
  718.                 printf( "%s\n", buf );
  719.             }
  720.         }
  721.     }
  722.  
  723.  
  724. /* transition_struct_out - output a yy_trans_info structure
  725.  *
  726.  * outputs the yy_trans_info structure with the two elements, element_v and
  727.  * element_n.  Formats the output with spaces and carriage returns.
  728.  */
  729.  
  730. void transition_struct_out( element_v, element_n )
  731. int element_v, element_n;
  732.     {
  733.     printf( "%7d, %5d,", element_v, element_n );
  734.  
  735.     datapos += TRANS_STRUCT_PRINT_LENGTH;
  736.  
  737.     if ( datapos >= 75 )
  738.         {
  739.         putchar( '\n' );
  740.  
  741.         if ( ++dataline % 10 == 0 )
  742.             putchar( '\n' );
  743.  
  744.         datapos = 0;
  745.         }
  746.     }
  747.  
  748.  
  749. /* The following is only needed when building flex's parser using certain
  750.  * broken versions of bison.
  751.  */
  752. void *yy_flex_xmalloc( size )
  753. int size;
  754.     {
  755.     void *result = flex_alloc( size );
  756.  
  757.     if ( ! result  )
  758.         flexfatal( "memory allocation failed in yy_flex_xmalloc()" );
  759.  
  760.     return result;
  761.     }
  762.  
  763.  
  764. /* zero_out - set a region of memory to 0
  765.  *
  766.  * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero.
  767.  */
  768.  
  769. void zero_out( region_ptr, size_in_bytes )
  770. char *region_ptr;
  771. int size_in_bytes;
  772.     {
  773.     register char *rp, *rp_end;
  774.  
  775.     rp = region_ptr;
  776.     rp_end = region_ptr + size_in_bytes;
  777.  
  778.     while ( rp < rp_end )
  779.         *rp++ = 0;
  780.     }
  781.