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