home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / lex / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  14.7 KB  |  795 lines

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