home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / bwbasic-2.10.sit / bwbasic-2.10 / bwb_fnc.c < prev    next >
Text File  |  1996-10-10  |  43KB  |  1,909 lines

  1. /****************************************************************
  2.  
  3.         bwb_fnc.c       Interpretation Routines
  4.             for Predefined Functions
  5.                         for Bywater BASIC Interpreter
  6.  
  7.                         Copyright (c) 1993, Ted A. Campbell
  8.                         Bywater Software
  9.  
  10.                         email: tcamp@delphi.com
  11.  
  12.         Copyright and Permissions Information:
  13.  
  14.         All U.S. and international rights are claimed by the author,
  15.         Ted A. Campbell.
  16.  
  17.     This software is released under the terms of the GNU General
  18.     Public License (GPL), which is distributed with this software
  19.     in the file "COPYING".  The GPL specifies the terms under
  20.     which users may copy and use the software in this distribution.
  21.  
  22.     A separate license is available for commercial distribution,
  23.     for information on which you should contact the author.
  24.  
  25. ****************************************************************/
  26.  
  27. #define FSTACKSIZE      32
  28.  
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include <math.h>
  32. #include <time.h>
  33.  
  34. #include "bwbasic.h"
  35. #include "bwb_mes.h"
  36.  
  37. #if UNIX_CMDS
  38. #include <sys/stat.h>
  39. #endif
  40.  
  41. #ifndef RAND_MAX            /* added in v1.11 */
  42. #define RAND_MAX    32767
  43. #endif
  44.  
  45. static time_t t;
  46. static struct tm *lt;
  47.  
  48. /***************************************************************
  49.  
  50.         FUNCTION:       fnc_init()
  51.  
  52.         DESCRIPTION:    This command initializes the function
  53.                         linked list, placing all predefined functions
  54.                         in the list.
  55.  
  56. ***************************************************************/
  57.  
  58. #if ANSI_C
  59. int fnc_init( int task )
  60. #else
  61. int
  62. fnc_init( task )
  63.    int task;
  64. #endif
  65.    {
  66.    register int n;
  67.    struct bwb_function *f;
  68.  
  69.    strcpy( LOCALTASK fnc_start.name, "FNC_START" );
  70.    LOCALTASK fnc_start.type = 'X';
  71.    LOCALTASK fnc_start.vector = fnc_null;
  72.    strcpy( LOCALTASK fnc_end.name, "FNC_END" );
  73.    LOCALTASK fnc_end.type = 'x';
  74.    LOCALTASK fnc_end.vector = fnc_null;
  75.    LOCALTASK fnc_end.next = &LOCALTASK fnc_end;
  76.  
  77.    f = &LOCALTASK fnc_start;
  78.  
  79.    /* now go through each of the preestablished functions and set up
  80.       links between them; from this point the program address the functions
  81.       only as a linked list (not as an array) */
  82.  
  83.    for ( n = 0; n < FUNCTIONS; ++n )
  84.       {
  85.       f->next = &( bwb_prefuncs[ n ] );
  86.       f = f->next;
  87.       }
  88.  
  89.    /* link the last pointer to the end; this completes the list */
  90.  
  91.    f->next = &LOCALTASK fnc_end;
  92.  
  93.    return TRUE;
  94.    }
  95.  
  96. /***************************************************************
  97.  
  98.         FUNCTION:       fnc_find()
  99.  
  100.         DESCRIPTION:    This C function attempts to locate
  101.                         a BASIC function with the specified name.
  102.                         If successful, it returns a pointer to
  103.                         the C structure for the BASIC function,
  104.                         if not successful, it returns NULL.
  105.  
  106. ***************************************************************/
  107.  
  108. #if ANSI_C
  109. struct bwb_function *
  110. fnc_find( char *buffer )
  111. #else
  112. struct bwb_function *
  113. fnc_find( buffer )
  114.    char *buffer;
  115. #endif
  116.    {
  117.    struct bwb_function * f;
  118.   // register int n;
  119.    static char *tbuf;
  120.    static int init = FALSE;
  121.  
  122.    if ( strlen( buffer ) == 0 )
  123.       {
  124.       return NULL;
  125.       }
  126.  
  127.    /* get memory for temporary buffer if necessary */
  128.  
  129.    if ( init == FALSE )
  130.       {
  131.       init = TRUE;
  132.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  133.          {
  134. #if PROG_ERRORS
  135.      bwb_error( "in fnc_find(): failed to find memory for tbuf" );
  136. #else
  137.      bwb_error( err_getmem );
  138. #endif
  139.      }
  140.       }
  141.  
  142. #if INTENSIVE_DEBUG
  143.    sprintf( bwb_ebuf, "in fnc_find(): called for <%s> ", buffer );
  144.    bwb_debug( bwb_ebuf );
  145. #endif
  146.  
  147.    strcpy( tbuf, buffer );
  148.    bwb_strtoupper( tbuf );
  149.  
  150.    for ( f = CURTASK fnc_start.next; f != &CURTASK fnc_end; f = f->next )
  151.       {
  152.       if ( strcmp( f->name, tbuf ) == 0 )
  153.          {
  154. #if INTENSIVE_DEBUG
  155.      sprintf( bwb_ebuf, "in fnc_find(): found <%s> ", f->name );
  156.      bwb_debug( bwb_ebuf );
  157. #endif
  158.          return f;
  159.          }
  160.       }
  161.  
  162.    /* search has failed: return NULL */
  163.  
  164.    return NULL;
  165.  
  166.    }
  167.  
  168. /***************************************************************
  169.  
  170.         FUNCTION:       fnc_null()
  171.  
  172.         DESCRIPTION:    This is a null function that can be used
  173.                         to fill in a required function-structure
  174.                         pointer when needed.
  175.  
  176. ***************************************************************/
  177.  
  178. #if ANSI_C
  179. struct bwb_variable *
  180. fnc_null( int argc, struct bwb_variable *argv, int unique_id )
  181. #else
  182. struct bwb_variable *
  183. fnc_null( argc, argv, unique_id )
  184.    int argc;
  185.    struct bwb_variable *argv;
  186.    int unique_id;
  187. #endif
  188.    {
  189.    static struct bwb_variable nvar;
  190.    static int init = FALSE;
  191.  
  192.    /* initialize the variable if necessary */
  193.  
  194.    if ( init == FALSE )
  195.       {
  196.       init = TRUE;
  197.       var_make( &nvar, NUMBER );
  198.       }
  199.  
  200.    return &nvar;
  201.    }
  202.  
  203. /***************************************************************
  204.  
  205.         FUNCTION:       fnc_tab()
  206.  
  207.     DESCRIPTION:    This C function implements the BASIC TAB()
  208.             function, adding tab spaces to a specified
  209.             column.
  210.  
  211.             TAB is a core function, i.e., required
  212.             for ANSI Minimal BASIC.
  213.  
  214.     SYNTAX:        TAB( number )
  215.  
  216. ***************************************************************/
  217.  
  218. #if ANSI_C
  219. struct bwb_variable *
  220. fnc_tab( int argc, struct bwb_variable *argv, int unique_id )
  221. #else
  222. struct bwb_variable *
  223. fnc_tab( argc, argv, unique_id )
  224.    int argc;
  225.    struct bwb_variable *argv;
  226.    int unique_id;
  227. #endif
  228.    {
  229.    static struct bwb_variable nvar;
  230.    static int init = FALSE;
  231.    static char t_string[ 4 ];
  232.    bstring *b;
  233.  
  234.    /* initialize nvar if necessary */
  235.  
  236.    if ( init == FALSE )
  237.       {
  238.       init = TRUE;
  239.       var_make( &nvar, (int) STRING );
  240.       }
  241.  
  242.    /* check for correct number of parameters */
  243.  
  244.    if ( argc < 1 )
  245.       {
  246. #if PROG_ERRORS
  247.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function TAB().",
  248.          argc );
  249.       bwb_error( bwb_ebuf );
  250. #else
  251.       bwb_error( err_syntax );
  252. #endif
  253.       break_handler();
  254.       return NULL;
  255.       }
  256.    else if ( argc > 1 )
  257.       {
  258. #if PROG_ERRORS
  259.       sprintf( bwb_ebuf, "Too many parameters (%d) to function TAB().",
  260.          argc );
  261.       bwb_error( bwb_ebuf );
  262. #else
  263.       bwb_error( err_syntax );
  264. #endif
  265.       break_handler();
  266.       return NULL;
  267.       }
  268.  
  269.    t_string[ 0 ] = PRN_TAB;
  270.    t_string[ 1 ] = (char) var_getnval( &( argv[ 0 ] ));
  271.    t_string[ 2 ] = '¥0';
  272.  
  273.    b = var_getsval( &nvar );
  274.    str_ctob( b, t_string );
  275.  
  276.    return &nvar;
  277.    }
  278.  
  279. #if COMMON_FUNCS
  280.  
  281. /***************************************************************
  282.  
  283.  
  284.         FUNCTION:       fnc_date()
  285.  
  286.         DESCRIPTION:    This C function implements the BASIC
  287.                         predefined DATE$ function, returning
  288.                         a string containing the year, month,
  289.                         and day of the month.
  290.  
  291.     SYNTAX:        DATE$
  292.  
  293. ***************************************************************/
  294.  
  295. #if ANSI_C
  296. struct bwb_variable *
  297. fnc_date( int argc, struct bwb_variable *argv, int unique_id )
  298. #else
  299. struct bwb_variable *
  300. fnc_date( argc, argv, unique_id )
  301.    int argc;
  302.    struct bwb_variable *argv;
  303.    int unique_id;
  304. #endif
  305.    {
  306.    static struct bwb_variable nvar;
  307.    static int init = FALSE;
  308.    static char *tbuf;
  309.  
  310.    /* initialize the variable if necessary */
  311.  
  312.    if ( init == FALSE )
  313.       {
  314.       init = TRUE;
  315.       var_make( &nvar, STRING );
  316.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  317.          {
  318. #if PROG_ERRORS
  319.          bwb_error( "in fnc_date(): failed to get memory for tbuf" );
  320. #else
  321.          bwb_error( err_getmem );
  322. #endif
  323.          }
  324.       }
  325.  
  326.    time( &t );
  327.    lt = localtime( &t );
  328.  
  329.    sprintf( tbuf, "%02d-%02d-%04d", lt->tm_mon + 1, lt->tm_mday,
  330.       1900 + lt->tm_year );
  331.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  332.  
  333.    return &nvar;
  334.    }
  335.  
  336. /***************************************************************
  337.  
  338.         FUNCTION:       fnc_time()
  339.  
  340.         DESCRIPTION:    This C function implements the BASIC
  341.                         predefined TIME$ function, returning a
  342.                         string containing the hour, minute, and
  343.                         second count.
  344.  
  345.     SYNTAX:        TIME$
  346.  
  347. ***************************************************************/
  348.  
  349. #if ANSI_C
  350. struct bwb_variable *
  351. fnc_time( int argc, struct bwb_variable *argv, int unique_id )
  352. #else
  353. struct bwb_variable *
  354. fnc_time( argc, argv, unique_id )
  355.    int argc;
  356.    struct bwb_variable *argv;
  357.    int unique_id;
  358. #endif
  359.    {
  360.    static struct bwb_variable nvar;
  361.    static char *tbuf;
  362.    static int init = FALSE;
  363.  
  364.    /* initialize the variable if necessary */
  365.  
  366.    if ( init == FALSE )
  367.       {
  368.       init = TRUE;
  369.       var_make( &nvar, STRING );
  370.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  371.          {
  372. #if PROG_ERRORS
  373.          bwb_error( "in fnc_time(): failed to get memory for tbuf" );
  374. #else
  375.          bwb_error( err_getmem );
  376. #endif
  377.          }
  378.       }
  379.  
  380.    time( &t );
  381.    lt = localtime( &t );
  382.  
  383.    sprintf( tbuf, "%02d:%02d:%02d", lt->tm_hour, lt->tm_min,
  384.       lt->tm_sec );
  385.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  386.  
  387.    return &nvar;
  388.    }
  389.  
  390. /***************************************************************
  391.  
  392.         FUNCTION:       fnc_chr()
  393.  
  394.         DESCRIPTION:    This C function implements the BASIC
  395.                         predefined CHR$ function, returning a
  396.                         string containing the single character
  397.                         whose ASCII value is the argument to
  398.                         this function.
  399.  
  400.     SYNTAX:        CHR$( number )
  401.  
  402. ***************************************************************/
  403.  
  404. #if ANSI_C
  405. struct bwb_variable *
  406. fnc_chr( int argc, struct bwb_variable *argv, int unique_id  )
  407. #else
  408. struct bwb_variable *
  409. fnc_chr( argc, argv, unique_id  )
  410.    int argc;
  411.    struct bwb_variable *argv;
  412.    int unique_id;
  413. #endif
  414.    {
  415.    static struct bwb_variable nvar;
  416.    char tbuf[ MAXSTRINGSIZE + 1 ];
  417.    static int init = FALSE;
  418. #if TEST_BSTRING
  419.    bstring *b;
  420. #endif
  421.  
  422. #if INTENSIVE_DEBUG
  423.    sprintf( bwb_ebuf, "in fnc_chr(): entered function, argc <%d>",
  424.       argc );
  425.    bwb_debug( bwb_ebuf );
  426. #endif
  427.  
  428.    /* initialize the variable if necessary */
  429.  
  430.    if ( init == FALSE )
  431.       {
  432.       init = TRUE;
  433.       var_make( &nvar, STRING );
  434. #if INTENSIVE_DEBUG
  435.       sprintf( bwb_ebuf, "in fnc_chr(): entered function, initialized nvar" );
  436.       bwb_debug( bwb_ebuf );
  437. #endif
  438.       }
  439.  
  440.    /* check arguments */
  441.  
  442. #if PROG_ERRORS
  443.    if ( argc < 1 )
  444.       {
  445.       sprintf( bwb_ebuf, "Not enough arguments to function CHR$()" );
  446.       bwb_error( bwb_ebuf );
  447.       return NULL;
  448.       }
  449.    else if ( argc > 1 )
  450.       {
  451.       sprintf( bwb_ebuf, "Too many parameters (%d) to function CHR$().",
  452.          argc );
  453.       bwb_error( bwb_ebuf );
  454.       return NULL;
  455.       }
  456. #else
  457.    if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
  458.       {
  459.       return NULL;
  460.       }
  461. #endif
  462.  
  463. #if INTENSIVE_DEBUG
  464.    sprintf( bwb_ebuf, "in fnc_chr(): entered function, checkargs ok" );
  465.    bwb_debug( bwb_ebuf );
  466. #endif
  467.  
  468.    tbuf[ 0 ] = (char) var_getnval( &( argv[ 0 ] ) );
  469.    tbuf[ 1 ] = '¥0';
  470.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  471.  
  472. #if TEST_BSTRING
  473.    b = var_findsval( &nvar, nvar.array_pos );
  474.    sprintf( bwb_ebuf, "in fnc_chr(): bstring name is <%s>", b->name );
  475.    bwb_debug( bwb_ebuf );
  476. #endif
  477. #if INTENSIVE_DEBUG
  478.    sprintf( bwb_ebuf, "in fnc_chr(): tbuf[ 0 ] is <%c>", tbuf[ 0 ] );
  479.    bwb_debug( bwb_ebuf );
  480. #endif
  481.  
  482.    return &nvar;
  483.    }
  484.  
  485. /***************************************************************
  486.  
  487.         FUNCTION:       fnc_len()
  488.  
  489.     DESCRIPTION:    This C function implements the BASIC LEN()
  490.             function, returning the length of a
  491.             specified string in bytes.
  492.  
  493.     SYNTAX:        LEN( string$ )
  494.  
  495. ***************************************************************/
  496.  
  497. #if ANSI_C
  498. struct bwb_variable *
  499. fnc_len( int argc, struct bwb_variable *argv, int unique_id )
  500. #else
  501. struct bwb_variable *
  502. fnc_len( argc, argv, unique_id )
  503.    int argc;
  504.    struct bwb_variable *argv;
  505.    int unique_id;
  506. #endif
  507.    {
  508.    static struct bwb_variable nvar;
  509.    static int init = FALSE;
  510.    static char *tbuf;
  511.  
  512.    /* initialize the variable if necessary */
  513.  
  514.    if ( init == FALSE )
  515.       {
  516.       init = TRUE;
  517.       var_make( &nvar, NUMBER );
  518.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  519.          {
  520. #if PROG_ERRORS
  521.          bwb_error( "in fnc_len(): failed to get memory for tbuf" );
  522. #else
  523.          bwb_error( err_getmem );
  524. #endif
  525.          }
  526.       }
  527.  
  528.    /* check parameters */
  529.  
  530. #if PROG_ERRORS
  531.    if ( argc < 1 )
  532.       {
  533.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function LEN().",
  534.          argc );
  535.       bwb_error( bwb_ebuf );
  536.       return NULL;
  537.       }
  538.    else if ( argc > 1 )
  539.       {
  540.       sprintf( bwb_ebuf, "Too many parameters (%d) to function LEN().",
  541.          argc );
  542.       bwb_error( bwb_ebuf );
  543.       return NULL;
  544.       }
  545. #else
  546.    if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
  547.       {
  548.       return NULL;
  549.       }
  550. #endif
  551.  
  552.    /* return length as an integer */
  553.  
  554.    str_btoc( tbuf, var_getsval( &( argv[ 0 ] )) );
  555.    * var_findnval( &nvar, nvar.array_pos )
  556.       = (bnumber) strlen( tbuf );
  557.  
  558.    return &nvar;
  559.    }
  560.  
  561. /***************************************************************
  562.  
  563.         FUNCTION:       fnc_pos()
  564.  
  565.     DESCRIPTION:    This C function implements the BASIC
  566.             POS() function, returning the current
  567.             column position for the output device.
  568.  
  569.     SYNTAX:        POS
  570.  
  571. ***************************************************************/
  572.  
  573. #if ANSI_C
  574. struct bwb_variable *
  575. fnc_pos( int argc, struct bwb_variable *argv, int unique_id )
  576. #else
  577. struct bwb_variable *
  578. fnc_pos( argc, argv, unique_id )
  579.    int argc;
  580.    struct bwb_variable *argv;
  581.    int unique_id;
  582. #endif
  583.    {
  584.    static struct bwb_variable nvar;
  585.    static int init = FALSE;
  586.  
  587.    /* initialize nvar if necessary */
  588.  
  589.    if ( init == FALSE )
  590.       {
  591.       init = TRUE;
  592.       var_make( &nvar, (int) NUMBER );
  593.       }
  594.  
  595.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) prn_col;
  596.  
  597.    return &nvar;
  598.    }
  599.  
  600. #endif                    /* COMMON_FUNCS */
  601.  
  602. #if MS_FUNCS
  603.  
  604. /***************************************************************
  605.  
  606.         FUNCTION:       fnc_timer()
  607.  
  608.         DESCRIPTION:    This C function implements the BASIC
  609.                         predefined TIMER function
  610.  
  611.     SYNTAX:        TIMER
  612.  
  613. ***************************************************************/
  614.  
  615. #if ANSI_C
  616. struct bwb_variable *
  617. fnc_timer( int argc, struct bwb_variable *argv, int unique_id  )
  618. #else
  619. struct bwb_variable *
  620. fnc_timer( argc, argv, unique_id  )
  621.    int argc;
  622.    struct bwb_variable *argv;
  623.    int unique_id;
  624. #endif
  625.    {
  626.    static struct bwb_variable nvar;
  627.    static time_t now;
  628.    static int init = FALSE;
  629.  
  630.    /* initialize the variable if necessary */
  631.  
  632.    if ( init == FALSE )
  633.       {
  634.       init = TRUE;
  635.       var_make( &nvar, NUMBER );
  636.       }
  637.  
  638.    time( &now );
  639.    * var_findnval( &nvar, nvar.array_pos )
  640.       = (float) fmod( (bnumber) now, (bnumber) (60*60*24));
  641.  
  642.    return &nvar;
  643.    }
  644.  
  645. /***************************************************************
  646.  
  647.         FUNCTION:       fnc_mid()
  648.  
  649.         DESCRIPTION:    This C function implements the BASIC
  650.                         predefined MID$ function
  651.  
  652.     SYNTAX:        MID$( string$, start-position-in-string[, number-of-spaces ] )
  653.  
  654. ***************************************************************/
  655.  
  656. #if ANSI_C
  657. struct bwb_variable *
  658. fnc_mid( int argc, struct bwb_variable *argv, int unique_id  )
  659. #else
  660. struct bwb_variable *
  661. fnc_mid( argc, argv, unique_id  )
  662.    int argc;
  663.    struct bwb_variable *argv;
  664.    int unique_id;
  665. #endif
  666.    {
  667.    static struct bwb_variable nvar;
  668.    register int c;
  669.    char target_string[ MAXSTRINGSIZE + 1 ];
  670.    int target_counter, num_spaces;
  671.    char tbuf[ MAXSTRINGSIZE + 1 ];
  672.    static int init = FALSE;
  673.  
  674.    /* initialize the variable if necessary */
  675.  
  676.    if ( init == FALSE )
  677.       {
  678.       init = TRUE;
  679.       var_make( &nvar, STRING );
  680.       }
  681.  
  682.    /* check arguments */
  683.  
  684. #if PROG_ERRORS
  685.    if ( argc < 2 )
  686.       {
  687.       sprintf( bwb_ebuf, "Not enough arguments to function MID$()" );
  688.       bwb_error( bwb_ebuf );
  689.       return &nvar;
  690.       }
  691.  
  692.    if ( argc > 3 )
  693.       {
  694.       sprintf( bwb_ebuf, "Two many arguments to function MID$()" );
  695.       bwb_error( bwb_ebuf );
  696.       return &nvar;
  697.       }
  698.  
  699. #else
  700.    if ( fnc_checkargs( argc, argv, 2, 3 ) == FALSE )
  701.       {
  702.       return NULL;
  703.       }
  704. #endif
  705.  
  706.    /* get arguments */
  707.  
  708.    str_btoc( target_string, var_getsval( &( argv[ 0 ] ) ));
  709.    target_counter = (int) var_getnval( &( argv[ 1 ] ) ) - 1;
  710.    if ( target_counter > (int) strlen( target_string ))
  711.       {
  712.       tbuf[ 0 ] = '¥0';
  713.       str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  714.       return &nvar;
  715.       }
  716.  
  717.    if ( argc == 3 )
  718.       {
  719.       num_spaces = (int) var_getnval( &( argv[ 2 ] ));
  720.       }
  721.    else
  722.       {
  723.       num_spaces = MAXSTRINGSIZE;
  724.       }
  725.  
  726. #if INTENSIVE_DEBUG
  727.    sprintf( bwb_ebuf, "in fnc_mid() string <%s> startpos <%d> spaces <%d>",
  728.       target_string, target_counter, num_spaces );
  729.    bwb_debug( bwb_ebuf );
  730. #endif
  731.  
  732.    c = 0;
  733.    tbuf[ c ] = '¥0';
  734.    while ( ( c < num_spaces ) && ( target_string[ target_counter ] != '¥0' ))
  735.       {
  736.       tbuf[ c ] = target_string[ target_counter ];
  737.       ++c;
  738.       tbuf[ c ] = '¥0';
  739.       ++target_counter;
  740.       }
  741.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  742.  
  743.    return &nvar;
  744.    }
  745.  
  746. /***************************************************************
  747.  
  748.         FUNCTION:       fnc_left()
  749.  
  750.         DESCRIPTION:    This C function implements the BASIC
  751.                         predefined LEFT$ function
  752.  
  753.     SYNTAX:        LEFT$( string$, number-of-spaces )
  754.  
  755. ***************************************************************/
  756.  
  757. #if ANSI_C
  758. struct bwb_variable *
  759. fnc_left( int argc, struct bwb_variable *argv, int unique_id  )
  760. #else
  761. struct bwb_variable *
  762. fnc_left( argc, argv, unique_id  )
  763.    int argc;
  764.    struct bwb_variable *argv;
  765.    int unique_id;
  766. #endif
  767.    {
  768.    static struct bwb_variable nvar;
  769.    register int c;
  770.    char target_string[ MAXSTRINGSIZE + 1 ];
  771.    int target_counter, num_spaces;
  772.    char tbuf[ MAXSTRINGSIZE + 1 ];
  773.    static int init = FALSE;
  774.  
  775.    /* initialize the variable if necessary */
  776.  
  777.    if ( init == FALSE )
  778.       {
  779.       init = TRUE;
  780.       var_make( &nvar, STRING );
  781.       }
  782.  
  783.    /* check arguments */
  784.  
  785. #if PROG_ERRORS
  786.    if ( argc < 2 )
  787.       {
  788.       sprintf( bwb_ebuf, "Not enough arguments to function LEFT$()" );
  789.       bwb_error( bwb_ebuf );
  790.       return &nvar;
  791.       }
  792.  
  793.    if ( argc > 2 )
  794.       {
  795.       sprintf( bwb_ebuf, "Two many arguments to function LEFT$()" );
  796.       bwb_error( bwb_ebuf );
  797.       return &nvar;
  798.       }
  799.  
  800. #else
  801.    if ( fnc_checkargs( argc, argv, 2, 2 ) == FALSE )
  802.       {
  803.       return NULL;
  804.       }
  805. #endif
  806.  
  807.    /* get arguments */
  808.  
  809.    str_btoc( tbuf, var_getsval( &( argv[ 0 ] ) ));
  810.    target_counter = 0;
  811.    num_spaces = (int) var_getnval( &( argv[ 1 ] ));
  812.  
  813. #if INTENSIVE_DEBUG
  814.    sprintf( bwb_ebuf, "in fnc_left() string <%s> startpos <%d> spaces <%d>",
  815.       tbuf, target_counter, num_spaces );
  816.    bwb_debug( bwb_ebuf );
  817. #endif
  818.  
  819.    c = 0;
  820.    target_string[ 0 ] = '¥0';
  821.    while (( c < num_spaces ) && ( tbuf[ c ] != '¥0' ))
  822.       {
  823.       target_string[ target_counter ] = tbuf[ c ];
  824.       ++target_counter;
  825.       target_string[ target_counter ] = '¥0';
  826.       ++c;
  827.       }
  828.    str_ctob( var_findsval( &nvar, nvar.array_pos ), target_string );
  829.  
  830.    return &nvar;
  831.    }
  832.  
  833. /***************************************************************
  834.  
  835.         FUNCTION:       fnc_right()
  836.  
  837.         DESCRIPTION:    This C function implements the BASIC
  838.                         predefined RIGHT$ function
  839.  
  840.     SYNTAX:        RIGHT$( string$, number-of-spaces )
  841.  
  842. ***************************************************************/
  843.  
  844. #if ANSI_C
  845. struct bwb_variable *
  846. fnc_right( int argc, struct bwb_variable *argv, int unique_id  )
  847. #else
  848. struct bwb_variable *
  849. fnc_right( argc, argv, unique_id  )
  850.    int argc;
  851.    struct bwb_variable *argv;
  852.    int unique_id;
  853. #endif
  854.    {
  855.    static struct bwb_variable nvar;
  856.    register int c;
  857.    char target_string[ MAXSTRINGSIZE + 1 ];
  858.    int target_counter, num_spaces;
  859.    char tbuf[ MAXSTRINGSIZE + 1 ];
  860.    static int init = FALSE;
  861.  
  862.    /* initialize the variable if necessary */
  863.  
  864.    if ( init == FALSE )
  865.       {
  866.       init = TRUE;
  867.       var_make( &nvar, STRING );
  868.       }
  869.  
  870.    /* check arguments */
  871.  
  872. #if PROG_ERRORS
  873.    if ( argc < 2 )
  874.       {
  875.       sprintf( bwb_ebuf, "Not enough arguments to function RIGHT$()" );
  876.       bwb_error( bwb_ebuf );
  877.       return &nvar;
  878.       }
  879.  
  880.    if ( argc > 2 )
  881.       {
  882.       sprintf( bwb_ebuf, "Two many arguments to function RIGHT$()" );
  883.       bwb_error( bwb_ebuf );
  884.       return &nvar;
  885.       }
  886.  
  887. #else
  888.    if ( fnc_checkargs( argc, argv, 2, 2 ) == FALSE )
  889.       {
  890.       return NULL;
  891.       }
  892. #endif
  893.  
  894.    /* get arguments */
  895.  
  896.    str_btoc( target_string, var_getsval( &( argv[ 0 ] ) ));
  897.    target_counter = strlen( target_string ) - (int) var_getnval( &( argv[ 1 ] ));
  898.    num_spaces = MAXSTRINGSIZE;
  899.  
  900. #if INTENSIVE_DEBUG
  901.    sprintf( bwb_ebuf, "in fnc_right() string <%s> startpos <%d> spaces <%d>",
  902.       target_string, target_counter, num_spaces );
  903.    bwb_debug( bwb_ebuf );
  904. #endif
  905.  
  906.    c = 0;
  907.    tbuf[ c ] = '¥0';
  908.    while ( ( c < num_spaces ) && ( target_string[ target_counter ] != '¥0' ))
  909.       {
  910.       tbuf[ c ] = target_string[ target_counter ];
  911.       ++c;
  912.       tbuf[ c ] = '¥0';
  913.       ++target_counter;
  914.       }
  915.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  916.  
  917.    return &nvar;
  918.    }
  919.  
  920. /***************************************************************
  921.  
  922.         FUNCTION:       fnc_asc()
  923.  
  924.         DESCRIPTION:    This function implements the predefined
  925.             BASIC ASC() function, returning the ASCII
  926.             number associated with the first character
  927.             in the string argument.
  928.  
  929.     SYNTAX:        ASC( string$ )
  930.  
  931. ***************************************************************/
  932.  
  933. #if ANSI_C
  934. struct bwb_variable *
  935. fnc_asc( int argc, struct bwb_variable *argv, int unique_id )
  936. #else
  937. struct bwb_variable *
  938. fnc_asc( argc, argv, unique_id )
  939.    int argc;
  940.    struct bwb_variable *argv;
  941.    int unique_id;
  942. #endif
  943.    {
  944.    static struct bwb_variable nvar;
  945.    static char *tbuf;
  946.    static int init = FALSE;
  947.  
  948.    /* initialize the variable if necessary */
  949.  
  950.    if ( init == FALSE )
  951.       {
  952.       init = TRUE;
  953.       var_make( &nvar, NUMBER );
  954.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  955.          {
  956. #if PROG_ERRORS
  957.          bwb_error( "in fnc_asc(): failed to get memory for tbuf" );
  958. #else
  959.          bwb_error( err_getmem );
  960. #endif
  961.          }
  962.       }
  963.  
  964.    /* check parameters */
  965.  
  966. #if PROG_ERRORS
  967.    if ( argc < 1 )
  968.       {
  969.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function ASC().",
  970.          argc );
  971.       bwb_error( bwb_ebuf );
  972.       return NULL;
  973.       }
  974.    else if ( argc > 1 )
  975.       {
  976.       sprintf( bwb_ebuf, "Too many parameters (%d) to function ASC().",
  977.          argc );
  978.       bwb_error( bwb_ebuf );
  979.       return NULL;
  980.       }
  981. #else
  982.    if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
  983.       {
  984.       return NULL;
  985.       }
  986. #endif
  987.  
  988.    if ( argv[ 0 ].type != STRING )
  989.       {
  990. #if PROG_ERRORS
  991.       sprintf( bwb_ebuf, "Argument to function ASC() must be a string." );
  992.       bwb_error( bwb_ebuf );
  993. #else
  994.       bwb_error( err_mismatch );
  995. #endif
  996.       return NULL;
  997.       }
  998.  
  999.    /* assign ASCII value of first character in the buffer */
  1000.  
  1001.    str_btoc( tbuf, var_findsval( &( argv[ 0 ] ), argv[ 0 ].array_pos ) );
  1002.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) tbuf[ 0 ];
  1003.  
  1004. #if INTENSIVE_DEBUG
  1005.    sprintf( bwb_ebuf, "in fnc_asc(): string is <%s>",
  1006.       tbuf );
  1007.    bwb_debug( bwb_ebuf );
  1008. #endif
  1009.  
  1010.    return &nvar;
  1011.    }
  1012.  
  1013. /***************************************************************
  1014.  
  1015.         FUNCTION:       fnc_string()
  1016.  
  1017.         DESCRIPTION:    This C function implements the BASIC
  1018.             STRING$() function.
  1019.  
  1020.     SYNTAX:        STRING$( number, ascii-value|string$ )
  1021.  
  1022. ***************************************************************/
  1023.  
  1024. #if ANSI_C
  1025. struct bwb_variable *
  1026. fnc_string( int argc, struct bwb_variable *argv, int unique_id )
  1027. #else
  1028. struct bwb_variable *
  1029. fnc_string( argc, argv, unique_id )
  1030.    int argc;
  1031.    struct bwb_variable *argv;
  1032.    int unique_id;
  1033. #endif
  1034.    {
  1035.    static struct bwb_variable nvar;
  1036.    int length;
  1037.    register int i;
  1038.    char c;
  1039.    static char *tbuf;
  1040.    static int init = FALSE;
  1041.  
  1042.    /* initialize the variable if necessary */
  1043.  
  1044.    if ( init == FALSE )
  1045.       {
  1046.       init = TRUE;
  1047.       var_make( &nvar, STRING );
  1048.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  1049.          {
  1050. #if PROG_ERRORS
  1051.          bwb_error( "in fnc_string(): failed to get memory for tbuf" );
  1052. #else
  1053.          bwb_error( err_getmem );
  1054. #endif
  1055.          }
  1056.       }
  1057.  
  1058.    /* check for correct number of parameters */
  1059.  
  1060. #if PROG_ERRORS
  1061.    if ( argc < 2 )
  1062.       {
  1063.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function STRING$().",
  1064.          argc );
  1065.       bwb_error( bwb_ebuf );
  1066.       return NULL;
  1067.       }
  1068.    else if ( argc > 2 )
  1069.       {
  1070.       sprintf( bwb_ebuf, "Too many parameters (%d) to function STRING$().",
  1071.          argc );
  1072.       bwb_error( bwb_ebuf );
  1073.       return NULL;
  1074.       }
  1075. #else
  1076.    if ( fnc_checkargs( argc, argv, 2, 2 ) == FALSE )
  1077.       {
  1078.       return NULL;
  1079.       }
  1080. #endif
  1081.  
  1082.    strcpy( nvar.name, "(string$)!" );
  1083.    nvar.type = STRING;
  1084.    tbuf[ 0 ] = '¥0';
  1085.    length = (int) var_getnval( &( argv[ 0 ] ));
  1086.  
  1087.    if ( argv[ 1 ].type == STRING )
  1088.       {
  1089.       str_btoc( tbuf, var_getsval( &( argv[ 1 ] )));
  1090.       c = tbuf[ 0 ];
  1091.       }
  1092.    else
  1093.       {
  1094.       c = (char) var_getnval( &( argv[ 1 ] ) );
  1095.       }
  1096.  
  1097. #if INTENSIVE_DEBUG
  1098.    sprintf( bwb_ebuf, "in fnc_string(): argument <%s> arg type <%c>, length <%d>",
  1099.       argv[ 1 ].string, argv[ 1 ].type, length );
  1100.    bwb_debug( bwb_ebuf );
  1101.    sprintf( bwb_ebuf, "in fnc_string(): type <%c>, c <0x%x>=<%c>",
  1102.       argv[ 1 ].type, c, c );
  1103.    bwb_debug( bwb_ebuf );
  1104. #endif
  1105.  
  1106.    /* add characters to the string */
  1107.  
  1108.    for ( i = 0; i < length; ++i )
  1109.       {
  1110.       tbuf[ i ] = c;
  1111.       tbuf[ i + 1 ] = '¥0';
  1112.       }
  1113.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  1114.  
  1115.    return &nvar;
  1116.    }
  1117.  
  1118. /***************************************************************
  1119.  
  1120.         FUNCTION:       fnc_instr()
  1121.  
  1122.         DESCRIPTION:    This C function implements the BASIC 
  1123.             INSTR() function, returning the position
  1124.             in string string-searched$ at which
  1125.             string-pattern$ occurs.
  1126.  
  1127.     SYNTAX:        INSTR( [start-position,] string-searched$, string-pattern$ )
  1128.  
  1129. ***************************************************************/
  1130.  
  1131. #if ANSI_C
  1132. struct bwb_variable *
  1133. fnc_instr( int argc, struct bwb_variable *argv, int unique_id )
  1134. #else
  1135. struct bwb_variable *
  1136. fnc_instr( argc, argv, unique_id )
  1137.    int argc;
  1138.    struct bwb_variable *argv;
  1139.    int unique_id;
  1140. #endif
  1141.    {
  1142.    static struct bwb_variable nvar;
  1143.    static int init = FALSE;
  1144.    int n_pos, x_pos, y_pos;
  1145.    int start_pos;
  1146.    register int n;
  1147.    char xbuf[ MAXSTRINGSIZE + 1 ];
  1148.    char ybuf[ MAXSTRINGSIZE + 1 ];
  1149.  
  1150.    /* initialize the variable if necessary */
  1151.  
  1152.    if ( init == FALSE )
  1153.       {
  1154.       init = TRUE;
  1155.       var_make( &nvar, NUMBER );
  1156.       }
  1157.  
  1158.    /* check for correct number of parameters */
  1159.  
  1160. #if PROG_ERRORS
  1161.    if ( argc < 2 )
  1162.       {
  1163.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function INSTR().",
  1164.          argc );
  1165.       bwb_error( bwb_ebuf );
  1166.       return NULL;
  1167.       }
  1168.    else if ( argc > 3 )
  1169.       {
  1170.       sprintf( bwb_ebuf, "Too many parameters (%d) to function INSTR().",
  1171.          argc );
  1172.       bwb_error( bwb_ebuf );
  1173.       return NULL;
  1174.       }
  1175. #else
  1176.    if ( fnc_checkargs( argc, argv, 2, 3 ) == FALSE )
  1177.       {
  1178.       return NULL;
  1179.       }
  1180. #endif
  1181.  
  1182.    /* determine argument positions */
  1183.  
  1184.    if ( argc == 3 )
  1185.       {
  1186.       n_pos = 0;
  1187.       x_pos = 1;
  1188.       y_pos = 2;
  1189.       }
  1190.    else
  1191.       {
  1192.       n_pos = -1;
  1193.       x_pos = 0;
  1194.       y_pos = 1;
  1195.       }
  1196.  
  1197.    /* determine starting position */
  1198.  
  1199.    if ( n_pos == 0 )
  1200.       {
  1201.       start_pos = (int) var_getnval( &( argv[ n_pos ] ) ) - 1;
  1202.       }
  1203.    else
  1204.       {
  1205.       start_pos = 0;
  1206.       }
  1207.  
  1208.    /* get x and y strings */
  1209.  
  1210.    str_btoc( xbuf, var_getsval( &( argv[ x_pos ] ) ) );
  1211.    str_btoc( ybuf, var_getsval( &( argv[ y_pos ] ) ) );
  1212.  
  1213.    /* now search for match */
  1214.  
  1215.    for ( n = start_pos; n < (int) strlen( xbuf ); ++n )
  1216.       {
  1217.       if ( strncmp( &( xbuf[ n ] ), ybuf, strlen( ybuf ) ) == 0 )
  1218.          {
  1219.          * var_findnval( &nvar, nvar.array_pos ) = (bnumber) n + 1;
  1220.          return &nvar;
  1221.          }
  1222.       }
  1223.  
  1224.    /* match not found */
  1225.  
  1226.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) 0;
  1227.    return &nvar;
  1228.  
  1229.    }
  1230.  
  1231. /***************************************************************
  1232.  
  1233.         FUNCTION:       fnc_spc()
  1234.  
  1235.     DESCRIPTION:    This C function implements the BASIC
  1236.             SPC() function, returning a string
  1237.             containing a specified number of
  1238.             (blank) spaces.
  1239.  
  1240.     SYNTAX:        SPC( number )
  1241.  
  1242. ***************************************************************/
  1243.  
  1244. #if ANSI_C
  1245. struct bwb_variable *
  1246. fnc_spc( int argc, struct bwb_variable *argv, int unique_id )
  1247. #else
  1248. struct bwb_variable *
  1249. fnc_spc( argc, argv, unique_id )
  1250.    int argc;
  1251.    struct bwb_variable *argv;
  1252.    int unique_id;
  1253. #endif
  1254.    {
  1255.    return fnc_space( argc, argv, unique_id );
  1256.    }
  1257.  
  1258. /***************************************************************
  1259.  
  1260.         FUNCTION:       fnc_space()
  1261.  
  1262.     DESCRIPTION:    This C function implements the BASIC
  1263.             SPACE() function, returning a string
  1264.             containing a specified number of
  1265.             (blank) spaces.
  1266.  
  1267.     SYNTAX:        SPACE$( number )
  1268.  
  1269. ***************************************************************/
  1270.  
  1271. #if ANSI_C
  1272. struct bwb_variable *
  1273. fnc_space( int argc, struct bwb_variable *argv, int unique_id )
  1274. #else
  1275. struct bwb_variable *
  1276. fnc_space( argc, argv, unique_id )
  1277.    int argc;
  1278.    struct bwb_variable *argv;
  1279.    int unique_id;
  1280. #endif
  1281.    {
  1282.    static struct bwb_variable nvar;
  1283.    static char *tbuf;
  1284.    static int init = FALSE;
  1285.    int spaces;
  1286.    register int i;
  1287.    bstring *b;
  1288.  
  1289.    /* check for correct number of parameters */
  1290.  
  1291.    if ( argc < 1 )
  1292.       {
  1293. #if PROG_ERRORS
  1294.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function SPACE$().",
  1295.          argc );
  1296.       bwb_error( bwb_ebuf );
  1297. #else
  1298.       bwb_error( err_syntax );
  1299. #endif
  1300.       break_handler();
  1301.       return NULL;
  1302.       }
  1303.    else if ( argc > 1 )
  1304.       {
  1305. #if PROG_ERRORS
  1306.       sprintf( bwb_ebuf, "Too many parameters (%d) to function SPACE$().",
  1307.          argc );
  1308.       bwb_error( bwb_ebuf );
  1309. #else
  1310.       bwb_error( err_syntax );
  1311. #endif
  1312.       break_handler();
  1313.       return NULL;
  1314.       }
  1315.  
  1316.    /* initialize nvar if necessary */
  1317.  
  1318.    if ( init == FALSE )
  1319.       {
  1320.       init = TRUE;
  1321.       var_make( &nvar, (int) STRING );
  1322.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  1323.          {
  1324. #if PROG_ERRORS
  1325.          bwb_error( "in fnc_space(): failed to get memory for tbuf" );
  1326. #else
  1327.          bwb_error( err_getmem );
  1328. #endif
  1329.          }
  1330.       }
  1331.  
  1332.    tbuf[ 0 ] = '¥0';
  1333.    spaces = (int) var_getnval( &( argv[ 0 ] ));
  1334.  
  1335.    /* add spaces to the string */
  1336.  
  1337.    for ( i = 0; i < spaces; ++i )
  1338.       {
  1339.       tbuf[ i ] = ' ';
  1340.       tbuf[ i + 1 ] = '¥0';
  1341.       }
  1342.  
  1343.    b = var_getsval( &nvar );
  1344.    str_ctob( b, tbuf );
  1345.  
  1346.    return &nvar;
  1347.    }
  1348.  
  1349. /***************************************************************
  1350.  
  1351.         FUNCTION:       fnc_environ()
  1352.  
  1353.         DESCRIPTION:    This C function implements the BASIC
  1354.             ENVIRON$() function, returning the value
  1355.             of a specified environment string.
  1356.  
  1357.     SYNTAX:        ENVIRON$( variable-string )
  1358.  
  1359. ***************************************************************/
  1360.  
  1361. #if ANSI_C
  1362. struct bwb_variable *
  1363. fnc_environ( int argc, struct bwb_variable *argv, int unique_id )
  1364. #else
  1365. struct bwb_variable *
  1366. fnc_environ( argc, argv, unique_id )
  1367.    int argc;
  1368.    struct bwb_variable *argv;
  1369.    int unique_id;
  1370. #endif
  1371.    {
  1372.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1373.    char tmp[ MAXSTRINGSIZE + 1 ];
  1374.    static struct bwb_variable nvar;
  1375.    static int init = FALSE;
  1376.  
  1377.    /* initialize the variable if necessary */
  1378.  
  1379.    if ( init == FALSE )
  1380.       {
  1381.       init = TRUE;
  1382.       var_make( &nvar, STRING );
  1383.       }
  1384.  
  1385.    /* check for correct number of parameters */
  1386.  
  1387. #if PROG_ERRORS
  1388.    if ( argc < 1 )
  1389.       {
  1390.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function ENVIRON$().",
  1391.          argc );
  1392.       bwb_error( bwb_ebuf );
  1393.       return NULL;
  1394.       }
  1395.    else if ( argc > 1 )
  1396.       {
  1397.       sprintf( bwb_ebuf, "Too many parameters (%d) to function ENVIRON$().",
  1398.          argc );
  1399.       bwb_error( bwb_ebuf );
  1400.       return NULL;
  1401.       }
  1402. #else
  1403.    if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
  1404.       {
  1405.       return NULL;
  1406.       }
  1407. #endif
  1408.  
  1409.    /* resolve the argument and place string value in tbuf */
  1410.  
  1411.    str_btoc( tbuf, var_getsval( &( argv[ 0 ] )));
  1412.  
  1413.    /* call getenv() then write value to string */
  1414.  
  1415.    strcpy( tmp, getenv( tbuf ));
  1416.    str_ctob( var_findsval( &nvar, nvar.array_pos ), tmp );
  1417.  
  1418.    /* return address of nvar */
  1419.  
  1420.    return &nvar;
  1421.  
  1422.    }
  1423.  
  1424. /***************************************************************
  1425.  
  1426.         FUNCTION:       fnc_err()
  1427.  
  1428.     DESCRIPTION:    This C function implements the BASIC
  1429.             ERR function, returning the error number
  1430.             for the most recent error.
  1431.  
  1432.             Please note that as of revision level
  1433.             2.10, bwBASIC does not utilize a standard
  1434.             list of error numbers, so numbers returned
  1435.             by this function will not be those found
  1436.             in either ANSI or Microsoft or other
  1437.             BASIC error tables.
  1438.  
  1439.     SYNTAX:        ERR
  1440.  
  1441. ***************************************************************/
  1442.  
  1443. #if ANSI_C
  1444. struct bwb_variable *
  1445. fnc_err( int argc, struct bwb_variable *argv, int unique_id )
  1446. #else
  1447. struct bwb_variable *
  1448. fnc_err( argc, argv, unique_id )
  1449.    int argc;
  1450.    struct bwb_variable *argv;
  1451.    int unique_id;
  1452. #endif
  1453.    {
  1454.    static struct bwb_variable nvar;
  1455.    static int init = FALSE;
  1456.  
  1457.    /* initialize nvar if necessary */
  1458.  
  1459.    if ( init == FALSE )
  1460.       {
  1461.       init = TRUE;
  1462.       var_make( &nvar, (int) NUMBER );
  1463.       }
  1464.  
  1465.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) err_number;
  1466.  
  1467.    return &nvar;
  1468.    }
  1469.  
  1470. /***************************************************************
  1471.  
  1472.         FUNCTION:       fnc_erl()
  1473.  
  1474.     DESCRIPTION:    This C function implements the BASIC
  1475.             ERL function, returning the line number
  1476.             for the most recent error.
  1477.  
  1478.     SYNTAX:        ERL
  1479.  
  1480. ***************************************************************/
  1481.  
  1482. #if ANSI_C
  1483. struct bwb_variable *
  1484. fnc_erl( int argc, struct bwb_variable *argv, int unique_id )
  1485. #else
  1486. struct bwb_variable *
  1487. fnc_erl( argc, argv, unique_id )
  1488.    int argc;
  1489.    struct bwb_variable *argv;
  1490.    int unique_id;
  1491. #endif
  1492.    {
  1493.    static struct bwb_variable nvar;
  1494.    static int init = FALSE;
  1495.  
  1496.    /* initialize nvar if necessary */
  1497.  
  1498.    if ( init == FALSE )
  1499.       {
  1500.       init = TRUE;
  1501.       var_make( &nvar, (int) NUMBER );
  1502.       }
  1503.  
  1504.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) err_line;
  1505.  
  1506.    return &nvar;
  1507.    }
  1508.  
  1509. /***************************************************************
  1510.  
  1511.         FUNCTION:       fnc_loc()
  1512.  
  1513.         DESCRIPTION:    This C function implements the BASIC
  1514.             LOC() function. As implemented here,
  1515.             this only workd for random-acess files.
  1516.  
  1517.     SYNTAX:        LOC( device-number )
  1518.  
  1519. ***************************************************************/
  1520.  
  1521. #if ANSI_C
  1522. struct bwb_variable *
  1523. fnc_loc( int argc, struct bwb_variable *argv, int unique_id )
  1524. #else
  1525. struct bwb_variable *
  1526. fnc_loc( argc, argv, unique_id )
  1527.    int argc;
  1528.    struct bwb_variable *argv;
  1529.    int unique_id;
  1530. #endif
  1531.    {
  1532.    static struct bwb_variable nvar;
  1533.    static int init = FALSE;
  1534.    int dev_number;
  1535.  
  1536. #if INTENSIVE_DEBUG
  1537.    sprintf( bwb_ebuf, "in fnc_loc(): received f_arg <%f> ",
  1538.       var_getnval( &( argv[ 0 ] ) ) );
  1539.    bwb_debug( bwb_ebuf );
  1540. #endif
  1541.  
  1542.    if ( argc < 1 )
  1543.       {
  1544. #if PROG_ERRORS
  1545.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function LOC().",
  1546.          argc );
  1547.       bwb_error( bwb_ebuf );
  1548. #else
  1549.       bwb_error( err_syntax );
  1550. #endif
  1551.       return NULL;
  1552.       }
  1553.    else if ( argc > 1 )
  1554.       {
  1555. #if PROG_ERRORS
  1556.       sprintf( bwb_ebuf, "Too many parameters (%d) to function LOC().",
  1557.          argc );
  1558.       bwb_error( bwb_ebuf );
  1559. #else
  1560.       bwb_error( err_syntax );
  1561. #endif
  1562.       return NULL;
  1563.       }
  1564.  
  1565.    dev_number = (int) var_getnval( &( argv[ 0 ] ) );
  1566.  
  1567.    if ( init == FALSE )
  1568.       {
  1569.       init = TRUE;
  1570.       var_make( &nvar, NUMBER );
  1571.       }
  1572.  
  1573.    /* note if this is the very beginning of the file */
  1574.  
  1575.    if ( dev_table[ dev_number ].loc == 0 )
  1576.       {
  1577.       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) 0;
  1578.       }
  1579.    else
  1580.       {
  1581.       * var_findnval( &nvar, nvar.array_pos ) =
  1582.          (bnumber) dev_table[ dev_number ].next_record;
  1583.       }
  1584.  
  1585.    return &nvar;
  1586.    }
  1587.  
  1588. /***************************************************************
  1589.  
  1590.         FUNCTION:       fnc_eof()
  1591.  
  1592.         DESCRIPTION:    This C function implements the BASIC
  1593.             EOF() function.
  1594.  
  1595.     SYNTAX:        EOF( device-number )
  1596.  
  1597. ***************************************************************/
  1598.  
  1599. #if ANSI_C
  1600. struct bwb_variable *
  1601. fnc_eof( int argc, struct bwb_variable *argv, int unique_id )
  1602. #else
  1603. struct bwb_variable *
  1604. fnc_eof( argc, argv, unique_id )
  1605.    int argc;
  1606.    struct bwb_variable *argv;
  1607.    int unique_id;
  1608. #endif
  1609.    {
  1610.    static struct bwb_variable nvar;
  1611.    static int init = FALSE;
  1612.    int dev_number;
  1613.  
  1614. #if INTENSIVE_DEBUG
  1615.    sprintf( bwb_ebuf, "in fnc_loc(): received f_arg <%f> ",
  1616.       var_getnval( &( argv[ 0 ] ) ) );
  1617.    bwb_debug( bwb_ebuf );
  1618. #endif
  1619.  
  1620.    if ( argc < 1 )
  1621.       {
  1622. #if PROG_ERRORS
  1623.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function EOF().",
  1624.          argc );
  1625.       bwb_error( bwb_ebuf );
  1626. #else
  1627.       bwb_error( err_syntax );
  1628. #endif
  1629.       return NULL;
  1630.       }
  1631.    else if ( argc > 1 )
  1632.       {
  1633. #if PROG_ERRORS
  1634.       sprintf( bwb_ebuf, "Too many parameters (%d) to function EOF().",
  1635.          argc );
  1636.       bwb_error( bwb_ebuf );
  1637. #else
  1638.       bwb_error( err_syntax );
  1639. #endif
  1640.       return NULL;
  1641.       }
  1642.  
  1643.    dev_number = (int) var_getnval( &( argv[ 0 ] ) );
  1644.  
  1645.    if ( init == FALSE )
  1646.       {
  1647.       init = TRUE;
  1648.       var_make( &nvar, NUMBER );
  1649.       }
  1650.  
  1651.    /* note if this is the very beginning of the file */
  1652.  
  1653.    if ( dev_table[ dev_number ].mode == DEVMODE_AVAILABLE )
  1654.       {
  1655.       bwb_error( err_devnum );
  1656.       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) TRUE;
  1657.       }
  1658.    else if ( dev_table[ dev_number ].mode == DEVMODE_CLOSED )
  1659.       {
  1660.       bwb_error( err_devnum );
  1661.       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) TRUE;
  1662.       }
  1663.    else if ( feof( dev_table[ dev_number ].cfp ) == 0 )
  1664.       {
  1665.       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) FALSE;
  1666.       }
  1667.    else
  1668.       {
  1669.       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) TRUE;
  1670.       }
  1671.  
  1672.    return &nvar;
  1673.    }
  1674.  
  1675. /***************************************************************
  1676.  
  1677.         FUNCTION:       fnc_lof()
  1678.  
  1679.         DESCRIPTION:    This C function implements the BASIC
  1680.             LOF() function.
  1681.  
  1682.     SYNTAX:        LOF( device-number )
  1683.  
  1684. ***************************************************************/
  1685.  
  1686. #if ANSI_C
  1687. struct bwb_variable *
  1688. fnc_lof( int argc, struct bwb_variable *argv, int unique_id )
  1689. #else
  1690. struct bwb_variable *
  1691. fnc_lof( argc, argv, unique_id )
  1692.    int argc;
  1693.    struct bwb_variable *argv;
  1694.    int unique_id;
  1695. #endif
  1696.    {
  1697.    static struct bwb_variable nvar;
  1698.    static int init = FALSE;
  1699.    int dev_number;
  1700. #if UNIX_CMDS
  1701.    static struct stat statbuf;
  1702.    int r;
  1703. #endif
  1704.  
  1705. #if INTENSIVE_DEBUG
  1706.    sprintf( bwb_ebuf, "in fnc_lof(): received f_arg <%f> ",
  1707.       var_getnval( &( argv[ 0 ] ) ) );
  1708.    bwb_debug( bwb_ebuf );
  1709. #endif
  1710.  
  1711.    if ( argc < 1 )
  1712.       {
  1713. #if PROG_ERRORS
  1714.       sprintf( bwb_ebuf, "Not enough parameters (%d) to function LOF().",
  1715.          argc );
  1716.       bwb_error( bwb_ebuf );
  1717. #else
  1718.       bwb_error( err_syntax );
  1719. #endif
  1720.       return NULL;
  1721.       }
  1722.    else if ( argc > 1 )
  1723.       {
  1724. #if PROG_ERRORS
  1725.       sprintf( bwb_ebuf, "Too many parameters (%d) to function LOF().",
  1726.          argc );
  1727.       bwb_error( bwb_ebuf );
  1728. #else
  1729.       bwb_error( err_syntax );
  1730. #endif
  1731.       return NULL;
  1732.       }
  1733.  
  1734.    dev_number = (int) var_getnval( &( argv[ 0 ] ) );
  1735.  
  1736.    if ( init == FALSE )
  1737.       {
  1738.       init = TRUE;
  1739.       var_make( &nvar, NUMBER );
  1740.       }
  1741.  
  1742.    /* stat the file */
  1743.  
  1744. #if UNIX_CMDS
  1745.  
  1746.    r = stat( dev_table[ dev_number ].filename, &statbuf );
  1747.  
  1748.    if ( r != 0 )
  1749.       {
  1750. #if PROG_ERRORS
  1751.       sprintf( bwb_ebuf, "in fnc_lof(): failed to find file <%s>",
  1752.          dev_table[ dev_number ].filename );
  1753.       bwb_error( bwb_ebuf );
  1754. #else
  1755.       sprintf( bwb_ebuf, ERR_OPENFILE,
  1756.          dev_table[ dev_number ].filename );
  1757.       bwb_error( bwb_ebuf );
  1758. #endif
  1759.       return NULL;
  1760.       }
  1761.  
  1762.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) statbuf.st_size;
  1763.  
  1764. #else
  1765.  
  1766.    * var_findnval( &nvar, nvar.array_pos ) = (bnumber) FALSE;
  1767.  
  1768. #endif
  1769.  
  1770.    return &nvar;
  1771.    }
  1772.  
  1773. #endif                    /* MS_FUNCS */
  1774.  
  1775. /***************************************************************
  1776.  
  1777.         FUNCTION:       fnc_test()
  1778.  
  1779.         DESCRIPTION:    This is a test function, developed in
  1780.                         order to test argument passing to
  1781.                         BASIC functions.
  1782.  
  1783. ***************************************************************/
  1784.  
  1785. #if INTENSIVE_DEBUG
  1786. #if ANSI_C
  1787. struct bwb_variable *
  1788. fnc_test( int argc, struct bwb_variable *argv, int unique_id )
  1789. #else
  1790. struct bwb_variable *
  1791. fnc_test( argc, argv, unique_id )
  1792.    int argc;
  1793.    struct bwb_variable *argv;
  1794.    int unique_id;
  1795. #endif
  1796.    {
  1797.    register int c;
  1798.    static struct bwb_variable rvar;
  1799.    static char *tbuf;
  1800.    static int init = FALSE;
  1801.  
  1802.    /* initialize the variable if necessary */
  1803.  
  1804.    if ( init == FALSE )
  1805.       {
  1806.       init = TRUE;
  1807.       var_make( &rvar, NUMBER );
  1808.       if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  1809.          {
  1810. #if PROG_ERRORS
  1811.          bwb_error( "in fnc_test(): failed to get memory for tbuf" );
  1812. #else
  1813.          bwb_error( err_getmem );
  1814. #endif
  1815.          }
  1816.       }
  1817.  
  1818.    sprintf( bwb_ebuf, "TEST function: received %d arguments: ¥n", argc );
  1819.    prn_xprintf( stderr, bwb_ebuf );
  1820.  
  1821.    for ( c = 0; c < argc; ++c )
  1822.       {
  1823.       str_btoc( tbuf, var_getsval( &argv[ c ] ) );
  1824.       sprintf( bwb_ebuf, "                  arg %d (%c): <%s> ¥n", c,
  1825.      argv[ c ].type, tbuf );
  1826.       prn_xprintf( stderr, bwb_ebuf );
  1827.       }
  1828.  
  1829.    return &rvar;
  1830.  
  1831.    }
  1832. #endif
  1833.  
  1834. /***************************************************************
  1835.  
  1836.         FUNCTION:       fnc_checkargs()
  1837.  
  1838.         DESCRIPTION:    This C function checks the arguments to
  1839.             functions.
  1840.  
  1841. ***************************************************************/
  1842.  
  1843. #if PROG_ERRORS
  1844. #else
  1845. #if ANSI_C
  1846. int fnc_checkargs( int argc, struct bwb_variable *argv, int min, int max )
  1847. #else
  1848. int
  1849. fnc_checkargs( argc, argv, min, max )
  1850.    int argc;
  1851.    struct bwb_variable *argv;
  1852.    int min;
  1853.    int max;
  1854. #endif
  1855.    {
  1856.  
  1857.    if ( argc < min )
  1858.       {
  1859.       bwb_error( err_syntax );
  1860.       return FALSE;
  1861.       }
  1862.    if ( argc > max )
  1863.       {
  1864.       bwb_error( err_syntax );
  1865.       return FALSE;
  1866.       }
  1867.  
  1868.    return TRUE;
  1869.  
  1870.    }
  1871. #endif
  1872.  
  1873. /***************************************************************
  1874.  
  1875.         FUNCTION:       fnc_fncs()
  1876.  
  1877.         DESCRIPTION:    This C function is used for debugging
  1878.                         purposes; it prints a list of all defined
  1879.                         functions.
  1880.  
  1881.     SYNTAX:        FNCS
  1882.  
  1883. ***************************************************************/
  1884.  
  1885. #if PERMANENT_DEBUG
  1886.  
  1887. #if ANSI_C
  1888. struct bwb_line *
  1889. bwb_fncs( struct bwb_line *l )
  1890. #else
  1891. struct bwb_line *
  1892. bwb_fncs( l )
  1893.    struct bwb_line *l;
  1894. #endif
  1895.    {
  1896.    struct bwb_function *f;
  1897.  
  1898.    for ( f = CURTASK fnc_start.next; f != &CURTASK fnc_end; f = f->next )
  1899.       {
  1900.       sprintf( bwb_ebuf, "%s¥t%c ¥n", f->name, f->type );
  1901.       prn_xprintf( stderr, bwb_ebuf );
  1902.       }
  1903.  
  1904.    return bwb_zline( l );
  1905.  
  1906.    }
  1907. #endif
  1908.  
  1909.