/******************************************************************************
 *
 * Generate a large number of random symbols, strings, integers, and doubles.
 *
 * Craig C. Douglas
 * Last modified:
 *      Mon Feb 13 11:09:09 EST 2006
 *
 * Compiling:
 *      gcc -o symbols symbols.c
 *
 * Running:
 *      ./symbols [n]
 *  where n is the number of symbols you want to generate (must be at least
 *  2). The default is 200.
 *
 * Advice:
 *      Duplicate parts of the output and place elsewhere. This way you can
 *      test whether or not your lexer and symbol table routines only store
 *      symbols uniquely.
 *
 *****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

int main( int argc, char** argv ) {

    char    dbuf[20];       /* Convert ..e.. to ...d... */
    int     expo_d = 1;     /* Exponents d (1) or e (0) */
    int     i;              /* Utility variable         */
    int     j;              /* Utility variable         */
    int     nsyms = 200;    /* Number of symbols        */
    int     lenl;           /* Length of lets           */
    int     lenn;           /* Length of nums           */
    char*   pc;             /* Utility variable         */
    int     rn;             /* Random number            */
    int     rnl;            /* Random number            */
    double  val;            /* Random number            */

    /* Charatcters to choose from */
    char    lets[] = { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789" };
    char    nums[] = { "0123456789" };

    lenl = strlen( lets );
    lenn = strlen( nums );

    /**************************************************************************
     *
     * Determine the number of symbols to generate
     *
     *************************************************************************/
    if ( argc > 1 ) {
        i = atoi( argv[1] );
        if ( i > 1 ) nsyms = i;
        }

    printf( "Generating %d symbols\n\n", nsyms );

    /**************************************************************************
     *
     * Generate a random selection of goodies of random length
     *
     *************************************************************************/
    for( i = 0; i < nsyms; i++ ) {
        rn  = random() % 5;
        rnl = random();
        switch ( rn ) {
            case 0:     /* String */
                putchar( '\"' );

            case 1:     /* Symbol */
            case 2:     /* Symbol */
                putchar( lets[random() % 53] );
                rnl = rnl % 40;
                for( j = 1; j < rnl; j++ )
                    putchar( lets[random() % lenl] );
                if ( rn == 0 )
                    putchar( '\"' );
                putchar( '\n' );
                break;

            case 3:     /* Integer */
                putchar( nums[random() % lenn] );
                rnl = rnl % 12;
                for( j = 1; j < rnl; j++ )
                    putchar( nums[random() % lenn] );
                putchar( '\n' );
                break;

            case 4:     /* Double */
                rnl = (rnl % 40) - 30;
                val = (double)random() * pow( 10.0, (double)rnl );
                if ( val < 1.0e-10 || val > 1.0e+10 )
                    sprintf( dbuf, "%18.12e", val );
                else {
                    if ( random() % 2 )
                        sprintf( dbuf, "%18.12e", val );
                    else
                        sprintf( dbuf, "%12g", val );
                if ( expo_d ) {
                    pc = strrchr( dbuf, 'e' );
                    if ( pc != NULL ) *pc = 'd';
                }
                printf( "%s\n", dbuf );
                }
                break;
        }
    }

    /**************************************************************************
     *
     * C'est finis.
     *
     *************************************************************************/
    return 0;
}
