home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / bwbasic.zip / src / bwb_int.c < prev    next >
C/C++ Source or Header  |  1993-04-27  |  17KB  |  727 lines

  1. /***************************************************************f
  2.  
  3.         bwb_int.c       Line Interpretation Routines
  4.                         for Bywater BASIC Interpreter
  5.  
  6.                         Copyright (c) 1992, Ted A. Campbell
  7.  
  8.                         Bywater Software
  9.                         P. O. Box 4023
  10.                         Duke Station
  11.                         Durham, NC  27706
  12.  
  13.                         email: tcamp@acpub.duke.edu
  14.  
  15.         Copyright and Permissions Information:
  16.  
  17.         All U.S. and international copyrights are claimed by the
  18.         author. The author grants permission to use this code
  19.         and software based on it under the following conditions:
  20.         (a) in general, the code and software based upon it may be
  21.         used by individuals and by non-profit organizations; (b) it
  22.         may also be utilized by governmental agencies in any country,
  23.         with the exception of military agencies; (c) the code and/or
  24.         software based upon it may not be sold for a profit without
  25.         an explicit and specific permission from the author, except
  26.         that a minimal fee may be charged for media on which it is
  27.         copied, and for copying and handling; (d) the code must be
  28.         distributed in the form in which it has been released by the
  29.         author; and (e) the code and software based upon it may not
  30.         be used for illegal activities.
  31.  
  32. ***************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <ctype.h>
  37. #include <string.h>
  38.  
  39. #include "bwbasic.h"
  40. #include "bwb_mes.h"
  41.  
  42. /***************************************************************
  43.  
  44.         FUNCTION:       adv_element()
  45.  
  46.         DESCRIPTION:    This function reads characters in <buffer>
  47.                         beginning at <pos> and advances past a
  48.                         line element, incrementing <pos> appropri-
  49.                         ately and returning the line element in
  50.                         <element>.
  51.  
  52. ***************************************************************/
  53.  
  54. int
  55. adv_element( char *buffer, int *pos, char *element )
  56.    {
  57.    int loop;                                    /* control loop */
  58.    int e_pos;                                   /* position in element buffer */
  59.    int str_const;                               /* boolean: building a string constant */
  60.  
  61.    /* advance beyond any initial whitespace */
  62.  
  63.    adv_ws( buffer, pos );
  64.  
  65.    #if INTENSIVE_DEBUG
  66.    sprintf( bwb_ebuf, "in adv_element(): receieved <%s>.", &( buffer[ *pos ] ));
  67.    bwb_debug( bwb_ebuf );
  68.    #endif
  69.  
  70.    /* now loop while building an element and looking for an
  71.       element terminator */
  72.  
  73.    loop = TRUE;
  74.    e_pos = 0;
  75.    element[ e_pos ] = '\0';
  76.    str_const = FALSE;
  77.  
  78.    while ( loop == TRUE )
  79.       {
  80.       switch( buffer[ *pos ] )
  81.          {
  82.          case ',':                      /* element terminators */
  83.          case ';':
  84.          case ':':
  85.          case '=':
  86.          case ' ':
  87.          case '\t':
  88.          case '\0':
  89.          case '\n':
  90.          case '\r':
  91.             if ( str_const == TRUE )
  92.                {
  93.                element[ e_pos ] = buffer[ *pos ];
  94.                ++e_pos;
  95.                ++( *pos );
  96.                element[ e_pos ] = '\0';
  97.                }
  98.             else
  99.                {
  100.                return TRUE;
  101.                }
  102.             break;
  103.  
  104.          case '\"':                     /* string constant */
  105.             element[ e_pos ] = buffer[ *pos ];
  106.             ++e_pos;
  107.             ++( *pos );
  108.             element[ e_pos ] = '\0';
  109.             if ( str_const == TRUE )    /* termination of string constant */
  110.                {
  111.                return TRUE;
  112.                }
  113.             else                        /* beginning of string constant */
  114.                {
  115.                str_const = TRUE;
  116.                }
  117.             break;
  118.  
  119.          default:
  120.             element[ e_pos ] = buffer[ *pos ];
  121.             ++e_pos;
  122.             ++( *pos );
  123.             element[ e_pos ] = '\0';
  124.             break;
  125.          }
  126.       }
  127.  
  128.    /* This should not happen */
  129.  
  130.    return FALSE;
  131.  
  132.    }
  133.  
  134. /***************************************************************
  135.  
  136.         FUNCTION:       adv_ws()
  137.  
  138.         DESCRIPTION:    This function reads characters in <buffer>
  139.                         beginning at <pos> and advances past any
  140.                         whitespace, incrementing <pos> appropri-
  141.                         ately.
  142.  
  143. ***************************************************************/
  144.  
  145. int
  146. adv_ws( char *buffer, int *pos )
  147.    {
  148.    int loop;
  149.  
  150.    loop = TRUE;
  151.    while ( loop == TRUE )
  152.       {
  153.       switch( buffer[ *pos ] )
  154.          {
  155.          case ' ':
  156.          case '\t':
  157.             ++( *pos );
  158.             break;
  159.          default:
  160.             return TRUE;
  161.          }
  162.       }
  163.  
  164.    /* This should not happen */
  165.  
  166.    return FALSE;
  167.  
  168.    }
  169.  
  170. /***************************************************************
  171.  
  172.         FUNCTION:       bwb_strtoupper()
  173.  
  174.         DESCRIPTION:    This function converts the string in
  175.                         <buffer> to upper-case characters.
  176.  
  177. ***************************************************************/
  178.  
  179. int
  180. bwb_strtoupper( char *buffer )
  181.    {
  182.    char *p;
  183.  
  184.    p = buffer;
  185.    while ( *p != '\0' )
  186.       {
  187.       if ( islower( *p ) != FALSE )
  188.          {
  189.          *p = toupper( *p );
  190.          }
  191.       ++p;
  192.       }
  193.  
  194.    return TRUE;
  195.  
  196.    }
  197.  
  198. /***************************************************************
  199.  
  200.         FUNCTION:       line_start()
  201.  
  202.         DESCRIPTION:    This function reads a line buffer in
  203.                         <buffer> beginning at the position
  204.                         <pos> and attempts to determine (a)
  205.                         the position of the line number in the
  206.                         buffer (returned in <lnpos>), (b) the
  207.                         line number at this position (returned
  208.                         in <lnum>), (c) the position of the
  209.                         BASIC command in the buffer (returned
  210.                         in <cmdpos>), (d) the position of this
  211.                         BASIC command in the command table
  212.                         (returned in <cmdnum>), and (e) the
  213.                         position of the beginning of the rest
  214.                         of the line (returned in <startpos>).
  215.                         Although <startpos> must be returned
  216.                         as a positive integer, the other
  217.                         searches may fail, in which case FALSE
  218.                         will be returned in their positions.
  219.                         <pos> is not incremented.
  220.  
  221. ***************************************************************/
  222.  
  223. int
  224. line_start( char *buffer, int *pos, int *lnpos, int *lnum, int *cmdpos,
  225.    int *cmdnum, int *startpos )
  226.    {
  227.    static int position;
  228.    register int n;
  229.    static char *tbuf;
  230.    static int init = FALSE;
  231.  
  232.    /* get memory for temporary buffer if necessary */
  233.  
  234.    if ( init == FALSE )
  235.       {
  236.       init = TRUE;
  237.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  238.          {
  239.          bwb_error( err_getmem );
  240.          }
  241.       }
  242.  
  243.    #if INTENSIVE_DEBUG
  244.    sprintf( bwb_ebuf, "in line_start(): pos <%d> buffer <%s>", *pos,
  245.       buffer );
  246.    bwb_debug( bwb_ebuf );
  247.    #endif
  248.  
  249.    /* set initial values */
  250.  
  251.    *startpos = position = *pos;
  252.    *cmdpos = *lnpos = *pos;
  253.    *cmdnum = *lnum = -1;
  254.  
  255.    /* check for null line */
  256.  
  257.    adv_ws( buffer, &position );
  258.    if ( buffer[ position ] == '\0' )
  259.       {
  260.       #if INTENSIVE_DEBUG
  261.       bwb_debug( "in line_start(): found NULL line" );
  262.       #endif
  263.       *cmdnum = getcmdnum( "REM" );
  264.       return TRUE;
  265.       }
  266.  
  267.    /* advance beyond the first element */
  268.  
  269.    *lnpos = position;
  270.    adv_element( buffer, &position, tbuf );
  271.    adv_ws( buffer, &position );
  272.  
  273.    /* test for a line number in the first element */
  274.  
  275.    if ( is_numconst( tbuf ) == TRUE )               /* a line number */
  276.       {
  277.  
  278.       *lnum = atoi( tbuf );
  279.       *startpos = position;                             /* temp */
  280.       *cmdpos = position;
  281.  
  282.       adv_element( buffer, &position, tbuf );       /* advance past next element */
  283.  
  284.       #if INTENSIVE_DEBUG
  285.       sprintf( bwb_ebuf, "in line_start(): new element is <%s>", tbuf );
  286.       bwb_debug( bwb_ebuf );
  287.       #endif
  288.  
  289.       if ( is_cmd( tbuf, cmdnum ) == TRUE )
  290.          {
  291.          adv_ws( buffer, &position );
  292.          *startpos = position;
  293.          }
  294.       else if ( is_let( &( buffer[ *cmdpos ] ), cmdnum ) == TRUE )
  295.          {
  296.          *cmdpos = -1;
  297.          }
  298.       else
  299.          {
  300.          *cmdpos = *cmdnum = -1;
  301.          }
  302.       }
  303.  
  304.    /* not a line number */
  305.  
  306.    else
  307.       {
  308.       *lnum = -1;
  309.       *lnpos = -1;
  310.  
  311.       #if INTENSIVE_DEBUG
  312.       sprintf( bwb_ebuf, "in line_start(): no line number, element <%s>.",
  313.          tbuf );
  314.       bwb_debug( bwb_ebuf );
  315.       #endif
  316.  
  317.       if ( is_cmd( tbuf, cmdnum ) == TRUE )
  318.          {
  319.          adv_ws( buffer, &position );
  320.          *startpos = position;
  321.          }
  322.       else if ( is_let( &( buffer[ position ] ), cmdnum ) == TRUE )
  323.          {
  324.          adv_ws( buffer, &position );
  325.          *cmdpos = -1;
  326.          }
  327.       else
  328.          {
  329.          *cmdpos = *cmdnum = -1;
  330.          }
  331.       }
  332.  
  333.    #if INTENSIVE_DEBUG
  334.    sprintf( bwb_ebuf, "in line_start(): lnpos <%d> lnum <%d>",
  335.       *lnpos, *lnum );
  336.    bwb_debug( bwb_ebuf );
  337.    sprintf( bwb_ebuf, "in line_start(): cmdpos <%d> cmdnum <%d> startpos <%d>",
  338.       *cmdpos, *cmdnum, *startpos );
  339.    bwb_debug( bwb_ebuf );
  340.    #endif
  341.  
  342.    /* return */
  343.  
  344.    return TRUE;
  345.  
  346.    }
  347.  
  348. /***************************************************************
  349.  
  350.         FUNCTION:       is_cmd()
  351.  
  352.         DESCRIPTION:
  353.  
  354. ***************************************************************/
  355.  
  356. int
  357. is_cmd( char *buffer, int *cmdnum )
  358.    {
  359.    register int n;
  360.  
  361.    /* Convert the command name to upper case */
  362.  
  363.    bwb_strtoupper( buffer );
  364.  
  365.    /* Go through the command table and search for a match. */
  366.  
  367.    for ( n = 0; n < COMMANDS; ++n )
  368.       {
  369.       if ( strncmp( bwb_cmdtable[ n ].name, buffer,
  370.          strlen( bwb_cmdtable[ n ].name )) == 0 )
  371.          {
  372.          *cmdnum = n;
  373.          return TRUE;
  374.          }
  375.       }
  376.  
  377.    /* No command name was found */
  378.  
  379.    *cmdnum = -1;
  380.    return FALSE;
  381.  
  382.    }
  383.  
  384. /***************************************************************
  385.  
  386.         FUNCTION:       is_let()
  387.  
  388.         DESCRIPTION:    This function tries to determine if the
  389.                         expression in <buffer> is a LET statement
  390.                         without the LET command specified.
  391.  
  392. ***************************************************************/
  393.  
  394. int
  395. is_let( char *buffer, int *cmdnum )
  396.    {
  397.    register int n, i;
  398.  
  399.    #if INTENSIVE_DEBUG
  400.    sprintf( bwb_ebuf, "in is_let(): buffer <%s>", buffer );
  401.    bwb_debug( bwb_ebuf );
  402.    #endif
  403.  
  404.    /* Go through the expression and search for an assignment operator. */
  405.  
  406.    for ( n = 0; buffer[ n ] != '\0'; ++n )
  407.       {
  408.       switch( buffer[ n ] )
  409.          {
  410.          case '\"':                     /* string constant */
  411.             ++n;
  412.             while( buffer[ n ] != '\"' )
  413.                {
  414.                ++n;
  415.                if ( buffer[ n ] == '\0' )
  416.                   {
  417.                   #if PROG_ERRORS
  418.                   sprintf( bwb_ebuf, "Incomplete string constant" );
  419.                   bwb_error( bwb_ebuf );
  420.                   #else
  421.                   bwb_error( err_syntax );
  422.                   #endif
  423.                   *cmdnum = -1;
  424.                   return FALSE;
  425.                   }
  426.                }
  427.             ++n;
  428.             break;
  429.          case '=':
  430.  
  431.             #if INTENSIVE_DEBUG
  432.             sprintf( bwb_ebuf, "in is_let(): implied LET found." );
  433.             bwb_debug( bwb_ebuf );
  434.             #endif
  435.  
  436.             for ( i = 0; i < COMMANDS; ++i )
  437.                {
  438.                if ( strncmp( bwb_cmdtable[ i ].name, "LET", (size_t) 3 ) == 0 )
  439.                   {
  440.                   *cmdnum = i;
  441.                   }
  442.                }
  443.             return TRUE;
  444.          }
  445.       }
  446.  
  447.    /* No command name was found */
  448.  
  449.    *cmdnum = -1;
  450.    return FALSE;
  451.  
  452.    }
  453.  
  454. /***************************************************************
  455.  
  456.         FUNCTION:       bwb_stripcr()
  457.  
  458.         DESCRIPTION:
  459.  
  460.  
  461. ***************************************************************/
  462.  
  463. int
  464. bwb_stripcr( char *s )
  465.    {
  466.    char *p;
  467.  
  468.    p = s;
  469.    while ( *p != 0 )
  470.       {
  471.       switch( *p )
  472.          {
  473.  
  474.  
  475.          case 0x0d:
  476.          case 0x0a:
  477.             *p = 0;
  478.             return TRUE;
  479.          }
  480.       ++p;
  481.       }
  482.    *p = 0;
  483.    return TRUE;
  484.    }
  485.  
  486. /***************************************************************
  487.  
  488.         FUNCTION:       is_numconst()
  489.  
  490.         DESCRIPTION:    This function reads the string in <buffer>
  491.                         and returns TRUE if it is a numerical
  492.                         constant and FALSE if it is not. At
  493.                         this point, only decimal (base 10)
  494.                         constants are detected.
  495.  
  496. ***************************************************************/
  497.  
  498. int
  499. is_numconst( char *buffer )
  500.    {
  501.    char *p;
  502.  
  503.    #if INTENSIVE_DEBUG
  504.    sprintf( bwb_ebuf, "in is_numconst(): received string <%s>.", buffer );
  505.    bwb_debug( bwb_ebuf );
  506.    #endif
  507.  
  508.    /* Return FALSE for empty buffer */
  509.  
  510.    if ( buffer[ 0 ] == '\0' )
  511.       {
  512.       return FALSE;
  513.       }
  514.  
  515.    /* else check digits */
  516.  
  517.    p = buffer;
  518.    while( *p != '\0' )
  519.       {
  520.       switch( *p )
  521.          {
  522.          case '0':
  523.          case '1':
  524.          case '2':
  525.          case '3':
  526.          case '4':
  527.          case '5':
  528.          case '6':
  529.          case '7':
  530.          case '8':
  531.          case '9':
  532.             break;
  533.          default:
  534.             return FALSE;
  535.          }
  536.       ++p;
  537.       }
  538.  
  539.    /* only numerical characters detected */
  540.  
  541.    return TRUE;
  542.  
  543.    }
  544.  
  545. /***************************************************************
  546.  
  547.         FUNCTION:       bwb_numseq()
  548.  
  549.         DESCRIPTION:
  550.  
  551. ***************************************************************/
  552.  
  553. int
  554. bwb_numseq( char *buffer, int *start, int *end )
  555.    {
  556.    register int b, n;
  557.    int numbers;
  558.    static char *tbuf;
  559.    static int init = FALSE;
  560.  
  561.    /* get memory for temporary buffer if necessary */
  562.  
  563.    if ( init == FALSE )
  564.       {
  565.       init = TRUE;
  566.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  567.          {
  568.          bwb_error( err_getmem );
  569.          }
  570.       }
  571.  
  572.    if ( buffer[ 0 ] == 0 )
  573.       {
  574.       *start = *end = 0;
  575.       return FALSE;
  576.       }
  577.  
  578.    numbers = n = b = 0;
  579.    tbuf[ 0 ] = 0;
  580.    while( TRUE )
  581.       {
  582.       switch( buffer[ b ] )
  583.          {
  584.          case 0:                           /* end of string */
  585.          case '\n':
  586.          case '\r':
  587.             if ( n > 0 )
  588.                {
  589.                if ( numbers == 0 )
  590.                   {
  591.                   *end = 0;
  592.                   *start = atoi( tbuf );
  593.                   ++numbers;
  594.                   }
  595.                else
  596.                   {
  597.  
  598.                   *end = atoi( tbuf );
  599.                   return TRUE;
  600.                   }
  601.                }
  602.             else
  603.                {
  604.                if ( numbers == 0 )
  605.                   {
  606.                   *start = *end = 0;
  607.                   }
  608.                else if ( numbers == 1 )
  609.                   {
  610.                   *end = 0;
  611.                   }
  612.                else if ( ( numbers == 2 ) && ( tbuf[ 0 ] == 0 ))
  613.                   {
  614.                   *end = 0;
  615.                   }
  616.                }
  617.             return TRUE;
  618.  
  619.          #ifdef ALLOWWHITESPACE
  620.          case ' ':                         /* whitespace */
  621.          case '\t':
  622.          #endif
  623.  
  624.          case '-':                         /* or skip to next number */
  625.             if ( n > 0 )
  626.                {
  627.                if ( numbers == 0 )
  628.                   {
  629.                   *start = atoi( tbuf );
  630.                   ++numbers;
  631.                   }
  632.                else
  633.                   {
  634.                   *end = atoi( tbuf );
  635.                   return TRUE;
  636.                   }
  637.                }
  638.             ++b;
  639.             n = 0;
  640.             break;
  641.          case '0':
  642.          case '1':
  643.          case '2':
  644.          case '3':
  645.          case '4':
  646.          case '5':
  647.          case '6':
  648.          case '7':
  649.          case '8':
  650.          case '9':
  651.             tbuf[ n ] = buffer[ b ];
  652.             ++n;
  653.             tbuf[ n ] = 0;
  654.             ++b;
  655.             break;
  656.          default:
  657.             #if PROG_ERRORS
  658.             sprintf( bwb_ebuf,
  659.                "ERROR: character <%c> unexpected in numerical sequence",
  660.                buffer[ b ] );
  661.             ++b;
  662.             bwb_error( bwb_ebuf );
  663.             #else
  664.             bwb_error( err_syntax );
  665.             #endif
  666.             break;
  667.          }
  668.       }
  669.  
  670.    }
  671.  
  672. /***************************************************************
  673.  
  674.         FUNCTION:       bwb_freeline()
  675.  
  676.         DESCRIPTION:
  677.  
  678. ***************************************************************/
  679.  
  680. int
  681. bwb_freeline( struct bwb_line *l )
  682.    {
  683.    register int n;
  684.  
  685.    /* free arguments if there are any */
  686.    
  687.    free( l );
  688.  
  689.    return TRUE;
  690.    }
  691.    
  692. /***************************************************************
  693.  
  694.         FUNCTION:       int_qmdstr()
  695.  
  696.         DESCRIPTION:    This function .
  697.  
  698. ***************************************************************/
  699.  
  700. int
  701. int_qmdstr( char *buffer_a, char *buffer_b )
  702.    {
  703.    char *a, *b;
  704.    
  705.    a = buffer_a;
  706.    ++a;                         /* advance beyond quotation mark */
  707.    b = buffer_b;
  708.  
  709.    while( *a != '\"' )
  710.       {
  711.       *b = *a;
  712.       ++a;
  713.       ++b;
  714.       *b = '\0';
  715.       }
  716.  
  717.    return TRUE;
  718.  
  719.    }
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.