home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume33
/
bwbasic
/
part01
next >
Wrap
Text File
|
1992-11-04
|
61KB
|
2,180 lines
Newsgroups: comp.sources.misc
From: tcamp@acpub.duke.edu (Ted A. Campbell)
Subject: v33i037: bwbasic - Bywater BASIC interpreter version 1.10, Part01/11
Message-ID: <csm-v33i037=bwbasic.214446@sparky.IMD.Sterling.COM>
X-Md4-Signature: 607d3ea8135051cc3b32a8ed4fa483ae
Date: Thu, 5 Nov 1992 03:46:11 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: tcamp@acpub.duke.edu (Ted A. Campbell)
Posting-number: Volume 33, Issue 37
Archive-name: bwbasic/part01
Environment: ANSI-C
Bywater Software Announces
the First Public Release of
Bywater BASIC Interpreter/Shell, version 1.10
---------------------------------------------
Copyright (c) 1992, Ted A. Campbell
for bwBASIC version 1.10, 1 November 1992
DESCRIPTION:
The Bywater BASIC Interpreter (bwBASIC) implements a large
superset of the ANSI Standard for Minimal BASIC (X3.60-1978)
implemented in ANSI C, and offers a simple interactive environ-
ment including some shell program facilities as an extension of
BASIC. The interpreter has been compiled successfully on a range
of ANSI C compilers on varying platforms with no alterations
to source code necessary.
OBTAINING THE SOURCE CODE:
The source code for bwBASIC 1.10 will be posted to network news
groups and is available immediately by anonymous ftp. To obtain
the source code, ftp to site duke.cs.duke.edu, cd to /pub/bywater
and get the appropriate files. These are as follows:
bwb110.zip Source code in ZIP compressed format, with text lines
concluded with CR-LF. This is the appropriate version
for DOS-based computers.
bwb110.tar.Z Tar'd and compressed source code with text lines con-
cluded with LF only. This is the appropriate version
for Unix-based computers.
See the READ.ME for more information.
COMMUNICATIONS:
Ted A. Campbell
Bywater Software
P.O. Box 4023
Duke Station
Durham, NC 27706
USA
email: tcamp@acpub.duke.edu
------------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: READ.ME bwb_fnc.c
# Wrapped by kent@sparky on Wed Nov 4 21:34:21 1992
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 1 (of 11)."'
if test -f 'READ.ME' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'READ.ME'\"
else
echo shar: Extracting \"'READ.ME'\" \(4568 characters\)
sed "s/^X//" >'READ.ME' <<'END_OF_FILE'
X
X
X Bywater Software Announces
X the First Public Release of
X
X
X Bywater BASIC Interpreter/Shell, version 1.10
X ---------------------------------------------
X
X Copyright (c) 1992, Ted A. Campbell
X for bwBASIC version 1.10, 1 November 1992
X
X
X
XDESCRIPTION:
X
X The Bywater BASIC Interpreter (bwBASIC) implements a large
X superset of the ANSI Standard for Minimal BASIC (X3.60-1978)
X implemented in ANSI C, and offers a simple interactive environ-
X ment including some shell program facilities as an extension of
X BASIC. The interpreter has been compiled successfully on a range
X of ANSI C compilers on varying platforms with no alterations
X to source code necessary.
X
X
XOBTAINING THE SOURCE CODE:
X
X The source code for bwBASIC 1.10 will be posted to network news
X groups and is available immediately by anonymous ftp. To obtain
X the source code, ftp to site duke.cs.duke.edu, cd to /pub/bywater
X and get the appropriate files. These are as follows:
X
X bwb110.zip Source code in ZIP compressed format, with text lines
X concluded with CR-LF. This is the appropriate version
X for DOS-based computers.
X
X bwb110.tar.Z Tar'd and compressed source code with text lines con-
X cluded with LF only. This is the appropriate version
X for Unix-based computers.
X
X
XCOMMUNICATIONS:
X
X Ted A. Campbell
X Bywater Software
X P.O. Box 4023
X Duke Station
X Durham, NC 27706
X USA
X
X email: tcamp@acpub.duke.edu
X
X
XA LIST OF BASIC COMMANDS AND FUNCTIONS IMPLEMENTED in bwBASIC 1.10:
X
X ABS( number )
X ASC( string$ )
X ATN( number )
X CHAIN [MERGE] file-name [, line-number] [, ALL]
X CHR$( number )
X CINT( number )
X CLEAR
X CLOSE [[#]file-number]...
X COMMON variable [, variable...]
X COS( number )
X CSNG( number )
X CVD( string$ )
X CVI( string$ )
X CVS( string$ )
X DATA constant[,constant]...
X DATE$
X DEF FNname(arg...)] = expression
X DEFDBL letter[-letter](, letter[-letter])...
X DEFINT letter[-letter](, letter[-letter])...
X DEFSNG letter[-letter](, letter[-letter])...
X DEFSTR letter[-letter](, letter[-letter])...
X DELETE line[-line]
X DIM variable(elements...)[variable(elements...)]...
X END
X ENVIRON variable-string = string
X ENVIRON$( variable-string )
X EOF( device-number )
X ERASE variable[, variable]...
X ERL
X ERR
X ERROR number
X EXP( number )
X FIELD [#] device-number, number AS string-variable [, number AS string-variable...]
X FOR counter = start TO finish [STEP increment]
X GET [#] device-number [, record-number]
X GOSUB line
X GOTO line
X HEX$( number )
X IF expression THEN statement [ELSE statement]
X INPUT [# device-number]|[;]["prompt string";]list of variables
X INSTR( [start-position,] string-searched$, string-pattern$ )
X INT( number )
X KILL file-name
X LEFT$( string$, number-of-spaces )
X LEN( string$ )
X LET variable = expression
X LINE INPUT [[#] device-number,]["prompt string";] string-variable$
X LIST line[-line]
X LOAD file-name
X LOC( device-number )
X LOF( device-number )
X LOG( number )
X LSET string-variable$ = expression
X MERGE file-name
X MID$( string$, start-position-in-string[, number-of-spaces ] )
X MKD$( double-value# )
X MKI$( integer-value% )
X MKS$( single-value! )
X NAME old-file-name AS new-file-name
X NEW
X NEXT counter
X OCT$( number )
X ON variable GOTO|GOSUB line[,line,line,...]
X ON ERROR GOSUB line
X OPEN O|I|R, [#]device-number, file-name [,record length]
X file-name FOR INPUT|OUTPUT|APPEND AS [#]device-number [LEN = record-length]
X OPTION BASE number
X POS
X PRINT [# device-number,][USING format-string$;] expressions...
X PUT [#] device-number [, record-number]
X RANDOMIZE number
X READ variable[, variable]...
X REM string
X RESTORE line
X RETURN
X RIGHT$( string$, number-of-spaces )
X RND( number )
X RSET string-variable$ = expression
X RUN [line][file-name]
X SAVE file-name
X SGN( number )
X SIN( number )
X SPACE$( number )
X SPC( number )
X SQR( number )
X STOP
X STR$( number )
X STRING$( number, ascii-value|string$ )
X SWAP variable, variable
X SYSTEM
X TAB( number )
X TAN( number )
X TIME$
X TIMER
X TROFF
X TRON
X VAL( string$ )
X WEND
X WHILE expression
X WIDTH [# device-number,] number
X WRITE [# device-number,] element [, element ]....
X
X If DIRECTORY_CMDS is set to TRUE when the program is compiled,
X then the following commands will be available:
X
X CHDIR pathname
X MKDIR pathname
X RMDIR pathname
X
X
END_OF_FILE
if test 4568 -ne `wc -c <'READ.ME'`; then
echo shar: \"'READ.ME'\" unpacked with wrong size!
fi
# end of 'READ.ME'
fi
if test -f 'bwb_fnc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'bwb_fnc.c'\"
else
echo shar: Extracting \"'bwb_fnc.c'\" \(50459 characters\)
sed "s/^X//" >'bwb_fnc.c' <<'END_OF_FILE'
X/****************************************************************
X
X bwb_fnc.c Function Interpretation Routines
X for Bywater BASIC Interpreter
X
X Copyright (c) 1992, Ted A. Campbell
X
X Bywater Software
X P. O. Box 4023
X Duke Station
X Durham, NC 27706
X
X email: tcamp@acpub.duke.edu
X
X Copyright and Permissions Information:
X
X All U.S. and international copyrights are claimed by the
X author. The author grants permission to use this code
X and software based on it under the following conditions:
X (a) in general, the code and software based upon it may be
X used by individuals and by non-profit organizations; (b) it
X may also be utilized by governmental agencies in any country,
X with the exception of military agencies; (c) the code and/or
X software based upon it may not be sold for a profit without
X an explicit and specific permission from the author, except
X that a minimal fee may be charged for media on which it is
X copied, and for copying and handling; (d) the code must be
X distributed in the form in which it has been released by the
X author; and (e) the code and software based upon it may not
X be used for illegal activities.
X
X****************************************************************/
X
X#define FSTACKSIZE 32
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <ctype.h>
X#include <string.h>
X#include <math.h>
X#include <time.h>
X#include "bwbasic.h"
X#include "bwb_mes.h"
X
Xstatic time_t t;
Xstatic struct tm *lt;
X
Xstruct bwb_function fnc_start, fnc_end;
X
Xint ufsc = -1; /* user function stack counter */
X
Xstruct bwb_function bwb_prefuncs[ FUNCTIONS ] =
X {
X { "ABS", DOUBLE, 1, (struct user_fnc *) NULL, fnc_abs, (struct bwb_function *) NULL },
X { "DATE$", STRING, 0, (struct user_fnc *) NULL, fnc_date, (struct bwb_function *) NULL },
X { "TIME$", STRING, 0, (struct user_fnc *) NULL, fnc_time, (struct bwb_function *) NULL },
X { "ATN", DOUBLE, 1, (struct user_fnc *) NULL, fnc_atn, (struct bwb_function *) NULL },
X { "COS", DOUBLE, 1, (struct user_fnc *) NULL, fnc_cos, (struct bwb_function *) NULL },
X { "LOG", DOUBLE, 1, (struct user_fnc *) NULL, fnc_log, (struct bwb_function *) NULL },
X { "SIN", DOUBLE, 1, (struct user_fnc *) NULL, fnc_sin, (struct bwb_function *) NULL },
X { "SQR", DOUBLE, 1, (struct user_fnc *) NULL, fnc_sqr, (struct bwb_function *) NULL },
X { "TAN", DOUBLE, 1, (struct user_fnc *) NULL, fnc_tan, (struct bwb_function *) NULL },
X { "SGN", DOUBLE, 1, (struct user_fnc *) NULL, fnc_sgn, (struct bwb_function *) NULL },
X { "INT", DOUBLE, 1, (struct user_fnc *) NULL, fnc_int, (struct bwb_function *) NULL },
X { "RND", DOUBLE, 0, (struct user_fnc *) NULL, fnc_rnd, (struct bwb_function *) NULL },
X { "CHR$", DOUBLE, 0, (struct user_fnc *) NULL, fnc_chr, (struct bwb_function *) NULL },
X { "TAB", STRING, 1, (struct user_fnc *) NULL, fnc_tab, (struct bwb_function *) NULL },
X { "SPC", STRING, 1, (struct user_fnc *) NULL, fnc_spc, (struct bwb_function *) NULL },
X { "SPACE$", STRING, 1, (struct user_fnc *) NULL, fnc_space, (struct bwb_function *) NULL },
X { "STRING$", STRING, 1, (struct user_fnc *) NULL, fnc_string, (struct bwb_function *) NULL },
X { "MID$", STRING, 3, (struct user_fnc *) NULL, fnc_mid, (struct bwb_function *) NULL },
X { "LEFT$", STRING, 2, (struct user_fnc *) NULL, fnc_left, (struct bwb_function *) NULL },
X { "RIGHT$", STRING, 2, (struct user_fnc *) NULL, fnc_right, (struct bwb_function *) NULL },
X { "TIMER", SINGLE, 0, (struct user_fnc *) NULL, fnc_timer, (struct bwb_function *) NULL },
X { "VAL", INTEGER, 1, (struct user_fnc *) NULL, fnc_val, (struct bwb_function *) NULL },
X { "POS", INTEGER, 0, (struct user_fnc *) NULL, fnc_pos, (struct bwb_function *) NULL },
X { "ERR", INTEGER, 0, (struct user_fnc *) NULL, fnc_err, (struct bwb_function *) NULL },
X { "ERL", INTEGER, 0, (struct user_fnc *) NULL, fnc_erl, (struct bwb_function *) NULL },
X { "LEN", INTEGER, 1, (struct user_fnc *) NULL, fnc_len, (struct bwb_function *) NULL },
X { "LOC", INTEGER, 1, (struct user_fnc *) NULL, fnc_loc, (struct bwb_function *) NULL },
X { "LOF", DOUBLE, 1, (struct user_fnc *) NULL, fnc_lof, (struct bwb_function *) NULL },
X { "EOF", DOUBLE, 1, (struct user_fnc *) NULL, fnc_eof, (struct bwb_function *) NULL },
X { "CSNG", SINGLE, 1, (struct user_fnc *) NULL, fnc_csng, (struct bwb_function *) NULL },
X { "EXP", SINGLE, 1, (struct user_fnc *) NULL, fnc_exp, (struct bwb_function *) NULL },
X { "INSTR", INTEGER, 1, (struct user_fnc *) NULL, fnc_instr, (struct bwb_function *) NULL },
X { "STR$", STRING, 1, (struct user_fnc *) NULL, fnc_str, (struct bwb_function *) NULL },
X { "HEX$", STRING, 1, (struct user_fnc *) NULL, fnc_hex, (struct bwb_function *) NULL },
X { "OCT$", STRING, 1, (struct user_fnc *) NULL, fnc_oct, (struct bwb_function *) NULL },
X { "CINT", SINGLE, 1, (struct user_fnc *) NULL, fnc_cint, (struct bwb_function *) NULL },
X { "ASC", SINGLE, 1, (struct user_fnc *) NULL, fnc_asc, (struct bwb_function *) NULL },
X { "ENVIRON$",STRING, 1, (struct user_fnc *) NULL, fnc_environ, (struct bwb_function *) NULL },
X #if INTENSIVE_DEBUG
X { "TEST", DOUBLE, 2, (struct user_fnc *) NULL, fnc_test, (struct bwb_function *) NULL },
X #endif
X { "MKD$", STRING, 1, (struct user_fnc *) NULL, fnc_mkd, (struct bwb_function *) NULL },
X { "MKI$", STRING, 1, (struct user_fnc *) NULL, fnc_mki, (struct bwb_function *) NULL },
X { "MKS$", STRING, 1, (struct user_fnc *) NULL, fnc_mks, (struct bwb_function *) NULL },
X { "CVD", DOUBLE, 1, (struct user_fnc *) NULL, fnc_cvd, (struct bwb_function *) NULL },
X { "CVS", SINGLE, 1, (struct user_fnc *) NULL, fnc_cvs, (struct bwb_function *) NULL },
X { "CVI", INTEGER, 1, (struct user_fnc *) NULL, fnc_cvi, (struct bwb_function *) NULL }
X };
X
X/***************************************************************
X
X FUNCTION: fnc_init()
X
X DESCRIPTION: This command initializes the function
X linked list, placing all predefined functions
X in the list.
X
X***************************************************************/
X
Xint
Xfnc_init()
X {
X register int n;
X struct bwb_function *f;
X
X strcpy( fnc_start.name, "FNC_START" );
X fnc_start.type = 'X';
X fnc_start.vector = fnc_null;
X strcpy( fnc_end.name, "FNC_END" );
X fnc_end.type = 'x';
X fnc_end.vector = fnc_null;
X fnc_end.next = &fnc_end;
X
X f = &fnc_start;
X
X /* now go through each of the preestablished functions and set up
X links between them; from this point the program address the functions
X only as a linked list (not as an array) */
X
X for ( n = 0; n < FUNCTIONS; ++n )
X {
X f->next = &( bwb_prefuncs[ n ] );
X f = f->next;
X }
X
X /* link the last pointer to the end; this completes the list */
X
X f->next = &fnc_end;
X
X return TRUE;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_find()
X
X DESCRIPTION: This C function attempts to locate
X a BASIC function with the specified name.
X If successful, it returns a pointer to
X the C structure for the BASIC function,
X if not successful, it returns NULL.
X
X***************************************************************/
X
Xstruct bwb_function *
Xfnc_find( char *buffer )
X {
X struct bwb_function * f;
X register int n;
X static char *tbuf;
X static int init = FALSE;
X
X /* get memory for temporary buffer if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_find(): called for <%s> ", buffer );
X bwb_debug( bwb_ebuf );
X #endif
X
X for ( n = 0; buffer[ n ] != 0; ++n )
X {
X if ( islower( buffer[ n ] ) )
X {
X tbuf[ n ] = toupper( buffer[ n ] );
X }
X else
X {
X tbuf[ n ] = buffer[ n ];
X }
X }
X tbuf[ n ] = 0;
X
X for ( f = fnc_start.next; f != &fnc_end; f = f->next )
X {
X if ( strcmp( f->name, tbuf ) == 0 )
X {
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_find(): found <%s> ", f->name );
X bwb_debug( bwb_ebuf );
X #endif
X return f;
X }
X }
X
X /* search has failed: return NULL */
X
X return NULL;
X
X }
X
X/***************************************************************
X
X FUNCTION: bwb_deffn()
X
X DESCRIPTION: This C function implements the BASIC
X DEF FNxx statement.
X
X***************************************************************/
X
Xstruct bwb_line *
Xbwb_deffn( struct bwb_line *l )
X {
X register int n;
X int loop, arguments, p;
X struct bwb_function *f, *fncpos;
X static char *tbuf;
X static int init = FALSE;
X
X /* get memory for temporary buffer if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in bwb_deffn(): entered function." );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* test for appropriate function name */
X
X exp_getvfname( &( l->buffer[ l->startpos ] ), tbuf ); /* name in tbuf */
X
X for ( n = 0; tbuf[ n ] != '\0'; ++n )
X {
X if ( islower( tbuf[ n ] ) != FALSE )
X {
X tbuf[ n ] = toupper( tbuf[ n ] );
X }
X }
X
X if ( strncmp( tbuf, "FN", (size_t) 2 ) != 0 )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "at line %d: User-defined function name must begin with FN.",
X l->number );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_syntax );
X #endif
X l->next->position = 0;
X return l->next;
X }
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in bwb_deffn(): function name is <%s>", tbuf );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* Allocate memory for a new function structure */
X
X if ( ( f = (struct bwb_function *) calloc( (size_t) 1, sizeof( struct bwb_function ) )) == NULL )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "Failed to find memory for function structure." );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_getmem );
X #endif
X l->next->position = 0;
X return l->next;
X }
X
X /* Allocate memory for a user function structure */
X
X if ( ( f->ufnc = (struct user_fnc *) calloc( (size_t) 1, sizeof( struct user_fnc ) )) == NULL )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "Failed to find memory for function structure." );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_getmem );
X #endif
X l->next->position = 0;
X return l->next;
X }
X
X /* Set some values for the new function */
X
X strncpy( f->name, tbuf, (size_t) MAXVARNAMESIZE );
X
X switch( f->name[ strlen( f->name ) - 1 ] )
X {
X case STRING:
X case DOUBLE:
X case INTEGER:
X f->type = f->name[ strlen( f->name ) - 1 ];
X break;
X default:
X f->type = SINGLE;
X break;
X }
X
X f->vector = NULL;
X f->arguments = 0;
X
X /* determine if there are arguments */
X
X loop = TRUE;
X arguments = FALSE;
X l->position += strlen( f->name );
X while( loop == TRUE )
X {
X
X switch( l->buffer[ l->position ] )
X {
X case ' ': /* whitespace */
X case '\t':
X ++l->position;
X break;
X case '(': /* begin parenthesis = arguments */
X ++l->position;
X loop = FALSE;
X arguments = TRUE;
X break;
X case '\n': /* unexpected end of line */
X case '\r':
X case '\0':
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "at line %d: Unexpected end of line", l->number );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_syntax );
X #endif
X l->next->position = 0;
X return l->next;
X default: /* any other character = no arguments */
X loop = FALSE;
X break;
X }
X
X }
X
X /* identify arguments */
X
X if ( arguments == TRUE )
X {
X
X loop = TRUE;
X f->arguments = 0; /* use as counter */
X p = 0;
X f->ufnc->user_vns[ f->arguments ][ 0 ] = '\0';
X while ( loop == TRUE )
X {
X switch( l->buffer[ l->position ] )
X {
X case ' ': /* whitespace */
X case '\t':
X ++l->position;
X break;
X case '\0': /* unexpected end of line */
X case '\n':
X case '\r':
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "at line %d: Unexpected end of line.",
X l->number );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_syntax );
X #endif
X l->next->position = 0;
X return l->next;
X case ')': /* end of argument list */
X ++f->arguments; /* returns total number of arguments */
X ++l->position; /* advance beyond parenthesis */
X loop = FALSE;
X break;
X
X case ',': /* end of one argument */
X
X ++f->arguments;
X ++l->position;
X p = 0;
X f->ufnc->user_vns[ f->arguments ][ 0 ] = '\0';
X break;
X default:
X
X f->ufnc->user_vns[ f->arguments ][ p ] = l->buffer[ l->position ];
X ++l->position;
X ++p;
X f->ufnc->user_vns[ f->arguments ][ p ] = '\0';
X break;
X }
X }
X
X }
X
X /* else no arguments were found */
X
X else
X {
X f->arguments = 0;
X }
X
X #if INTENSIVE_DEBUG
X for ( n = 0; n < f->arguments; ++n )
X {
X sprintf( bwb_ebuf, "in bwb_deffn(): argument <%d> name <%s>.",
X n, f->ufnc->user_vns[ n ] );
X bwb_debug( bwb_ebuf );
X }
X #endif
X
X /* find the string to be interpreted */
X
X loop = TRUE;
X arguments = FALSE;
X while( loop == TRUE )
X {
X switch( l->buffer[ l->position ] )
X {
X case '\0': /* unexpected end of line */
X case '\n':
X case '\r':
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "at line %d: Unexpected end of line.",
X l->number );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_syntax );
X #endif
X l->next->position = 0;
X return l->next;
X case ' ': /* whitespace */
X case '\t':
X ++l->position;
X break;
X
X case '=':
X ++l->position;
X arguments = TRUE;
X break;
X default:
X loop = FALSE;
X break;
X }
X }
X
X /* if the equals sign was not detected, return error */
X
X if ( arguments == FALSE )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "at line %d: Assignment operator (=) not found.",
X l->number );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_syntax );
X #endif
X l->next->position = 0;
X return l->next;
X }
X
X /* write the string to be interpreted to the user function structure */
X
X strncpy( f->ufnc->int_line, &( l->buffer[ l->position ] ),
X (size_t) MAXSTRINGSIZE );
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in bwb_deffn(): line <%s>", f->ufnc->int_line );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* Place the new function in the function linked list */
X
X for ( fncpos = &fnc_start; fncpos->next != &fnc_end; fncpos = fncpos->next )
X {
X ;
X }
X fncpos->next = f;
X f->next = &fnc_end;
X
X /* return */
X
X l->next->position = 0;
X return l->next;
X
X }
X
X/***************************************************************
X
X FUNCTION: fnc_intufnc()
X
X DESCRIPTION: This C function interprets a user-defined
X BASIC function.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_intufnc( int argc, struct bwb_variable *argv, struct bwb_function *f )
X {
X register int n;
X int l_position, f_position;
X int written;
X bstring *b;
X struct exp_ese *e;
X static struct bwb_variable nvar;
X
X #if INTENSIVE_DEBUG
X sprintf( nvar.name, "intufnc variable" );
X #endif
X
X /* increment the user function stack counter */
X
X if ( ufsc >= UFNCSTACKSIZE )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "exceeded user-defined function stack, level <%d>",
X ufsc );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_overflow );
X #endif
X }
X
X ++ufsc;
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_intufnc(): interpreting user function <%s>",
X f->name );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* print arguments to strings */
X
X for ( n = 1; n <= argc; ++n )
X {
X switch( argv[ n - 1 ].type )
X {
X case DOUBLE:
X sprintf( ufs[ ufsc ].args[ n - 1 ], "(%f)",
X var_getdval( &( argv[ n - 1 ] ) ));
X break;
X case SINGLE:
X sprintf( ufs[ ufsc ].args[ n - 1 ], "(%f)",
X var_getfval( &( argv[ n - 1 ] ) ));
X break;
X case INTEGER:
X sprintf( ufs[ ufsc ].args[ n - 1 ], "(%d)",
X var_getival( &( argv[ n - 1 ] ) ));
X break;
X case STRING:
X b = var_getsval( &( argv[ n - 1 ] ) );
X str_btoc( bwb_ebuf, b );
X sprintf( ufs[ ufsc ].args[ n - 1 ], "\"%s\"",
X bwb_ebuf );
X break;
X default:
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "Unidentified variable type in argument to user function." );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_mismatch );
X #endif
X return &nvar;
X }
X }
X
X #if INTENSIVE_DEBUG
X for ( n = 1; n <= argc; ++n )
X {
X sprintf( bwb_ebuf, "in fnc_intufnc(): arg string %d: <%s>.",
X n - 1, ufs[ ufsc ].args[ n - 1 ] );
X bwb_debug ( bwb_ebuf );
X }
X #endif
X
X /* copy the interpreted line to the buffer, substituting variable ufs[ ufsc ].args */
X
X ufs[ ufsc ].l_buffer[ 0 ] = '\0';
X l_position = 0;
X for ( f_position = 0; f->ufnc->int_line[ f_position ] != '\0'; ++f_position )
X {
X written = FALSE;
X for ( n = 0; n < argc; ++n )
X {
X if ( strncmp( &( f->ufnc->int_line[ f_position ] ), f->ufnc->user_vns[ n ],
X (size_t) strlen( f->ufnc->user_vns[ n ] ) ) == 0 )
X {
X strcat( ufs[ ufsc ].l_buffer, ufs[ ufsc ].args[ n ] );
X written = TRUE;
X f_position += strlen( f->ufnc->user_vns[ n ] + 1 );
X l_position += strlen( ufs[ ufsc ].args[ n ] );
X }
X
X }
X if ( written == FALSE )
X {
X ufs[ ufsc ].l_buffer[ l_position ] = f->ufnc->int_line[ f_position ];
X ++l_position;
X ufs[ ufsc ].l_buffer[ l_position ] = '\0';
X }
X }
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_intufnc(): reconstructed line: <%s>",
X ufs[ ufsc ].l_buffer );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* parse */
X
X ufs[ ufsc ].position = 0;
X e = bwb_exp( ufs[ ufsc ].l_buffer, FALSE,
X &( ufs[ ufsc ].position ) );
X
X var_make( &nvar, e->type );
X
X switch( e->type )
X {
X case DOUBLE:
X * var_finddval( &nvar, nvar.array_pos ) = exp_getdval( e );
X break;
X case INTEGER:
X * var_findival( &nvar, nvar.array_pos ) = exp_getival( e );
X break;
X case STRING:
X str_btob( var_findsval( &nvar, nvar.array_pos ),
X exp_getsval( e ) );
X break;
X default:
X * var_findfval( &nvar, nvar.array_pos ) = exp_getfval( e );
X break;
X }
X
X /* decrement the user function stack counter */
X
X --ufsc;
X
X return &nvar;
X
X }
X
X/***************************************************************
X
X FUNCTION: fnc_null()
X
X DESCRIPTION: This is a null function that can be used
X to fill in a required function-structure
X pointer when needed.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_null( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, INTEGER );
X }
X
X return &nvar;
X }
X
X/***************************************************************
X
X
X FUNCTION: fnc_date()
X
X DESCRIPTION: This C function implements the BASIC
X predefined DATE$ function, returning
X a string containing the year, month,
X and day of the month.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_date( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static int init = FALSE;
X static char *tbuf;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X time( &t );
X lt = localtime( &t );
X
X sprintf( tbuf, "%02d-%02d-%04d", lt->tm_mon + 1, lt->tm_mday,
X 1900 + lt->tm_year );
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_time()
X
X DESCRIPTION: This C function implements the BASIC
X predefined TIME$ function, returning a
X string containing the hour, minute, and
X second count.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_time( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X time( &t );
X lt = localtime( &t );
X
X sprintf( tbuf, "%02d:%02d:%02d", lt->tm_hour, lt->tm_min,
X lt->tm_sec );
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_test()
X
X DESCRIPTION: This is a test function, developed in
X order to test argument passing to
X BASIC functions.
X
X***************************************************************/
X
X#if INTENSIVE_DEBUG
Xstruct bwb_variable *
Xfnc_test( int argc, struct bwb_variable *argv )
X {
X register int c;
X static struct bwb_variable rvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &rvar, SINGLE );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X fprintf( stdout, "TEST function: received %d arguments: \n", argc );
X
X for ( c = 0; c < argc; ++c )
X {
X str_btoc( tbuf, var_getsval( &argv[ c ] ) );
X fprintf( stdout, " arg %d (%c): <%s> \n", c,
X argv[ c ].type, tbuf );
X }
X
X return &rvar;
X
X }
X#endif
X
X/***************************************************************
X
X FUNCTION: fnc_rnd()
X
X DESCRIPTION: This C function implements the BASIC
X predefined RND function, returning a
X pseudo-random number in the range
X 0 to 1. It is affected by the RANDOMIZE
X command statement.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_rnd( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, SINGLE );
X }
X
X * var_findfval( &nvar, nvar.array_pos ) = (float) rand() / RAND_MAX;
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_chr()
X
X DESCRIPTION: This C function implements the BASIC
X predefined CHR$ function, returning a
X string containing the single character
X whose ASCII value is the argument to
X this function.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_chr( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X char tbuf[ MAXSTRINGSIZE + 1 ];
X static int init = FALSE;
X #if TEST_BSTRING
X bstring *b;
X #endif
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_chr(): entered function, argc <%d>",
X argc );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_chr(): entered function, initialized nvar" );
X bwb_debug( bwb_ebuf );
X #endif
X }
X
X /* check arguments */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough arguments to function CHR$()" );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function CHR$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_chr(): entered function, checkargs ok" );
X bwb_debug( bwb_ebuf );
X #endif
X
X tbuf[ 0 ] = (char) var_getival( &( argv[ 0 ] ) );
X tbuf[ 1 ] = '\0';
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X #if TEST_BSTRING
X b = var_findsval( &nvar, nvar.array_pos );
X sprintf( bwb_ebuf, "in fnc_chr(): bstring name is <%s>", b->name );
X bwb_debug( bwb_ebuf );
X #endif
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_chr(): tbuf[ 0 ] is <%c>", tbuf[ 0 ] );
X bwb_debug( bwb_ebuf );
X #endif
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_mid()
X
X DESCRIPTION: This C function implements the BASIC
X predefined MID$ function
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_mid( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X register int c;
X char target_string[ MAXSTRINGSIZE + 1 ];
X int target_counter, num_spaces;
X char tbuf[ MAXSTRINGSIZE + 1 ];
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X }
X
X /* check arguments */
X
X #if PROG_ERRORS
X if ( argc < 2 )
X {
X sprintf( bwb_ebuf, "Not enough arguments to function MID$()" );
X bwb_error( bwb_ebuf );
X return &nvar;
X }
X
X if ( argc > 3 )
X {
X sprintf( bwb_ebuf, "Two many arguments to function MID$()" );
X bwb_error( bwb_ebuf );
X return &nvar;
X }
X
X #else
X if ( fnc_checkargs( argc, argv, 2, 3 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* get arguments */
X
X str_btoc( target_string, var_getsval( &( argv[ 0 ] ) ));
X target_counter = var_getival( &( argv[ 1 ] ) ) - 1;
X if ( target_counter > strlen( target_string ))
X {
X tbuf[ 0 ] = '\0';
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X return &nvar;
X }
X
X if ( argc == 3 )
X {
X num_spaces = var_getival( &( argv[ 2 ] ));
X }
X else
X {
X num_spaces = MAXSTRINGSIZE;
X }
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_mid() string <%s> startpos <%d> spaces <%d>",
X target_string, target_counter, num_spaces );
X bwb_debug( bwb_ebuf );
X #endif
X
X c = 0;
X tbuf[ c ] = '\0';
X while ( ( c < num_spaces ) && ( target_string[ target_counter ] != '\0' ))
X {
X tbuf[ c ] = target_string[ target_counter ];
X ++c;
X tbuf[ c ] = '\0';
X ++target_counter;
X }
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_left()
X
X DESCRIPTION: This C function implements the BASIC
X predefined LEFT$ function
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_left( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X register int c;
X char target_string[ MAXSTRINGSIZE + 1 ];
X int target_counter, num_spaces;
X char tbuf[ MAXSTRINGSIZE + 1 ];
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X }
X
X /* check arguments */
X
X #if PROG_ERRORS
X if ( argc < 2 )
X {
X sprintf( bwb_ebuf, "Not enough arguments to function LEFT$()" );
X bwb_error( bwb_ebuf );
X return &nvar;
X }
X
X if ( argc > 2 )
X {
X sprintf( bwb_ebuf, "Two many arguments to function LEFT$()" );
X bwb_error( bwb_ebuf );
X return &nvar;
X }
X
X #else
X if ( fnc_checkargs( argc, argv, 2, 2 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* get arguments */
X
X str_btoc( tbuf, var_getsval( &( argv[ 0 ] ) ));
X target_counter = 0;
X num_spaces = var_getival( &( argv[ 1 ] ));
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_left() string <%s> startpos <%d> spaces <%d>",
X tbuf, target_counter, num_spaces );
X bwb_debug( bwb_ebuf );
X #endif
X
X c = 0;
X target_string[ 0 ] = '\0';
X while (( c < num_spaces ) && ( tbuf[ c ] != '\0' ))
X {
X target_string[ target_counter ] = tbuf[ c ];
X ++target_counter;
X target_string[ target_counter ] = '\0';
X ++c;
X }
X str_ctob( var_findsval( &nvar, nvar.array_pos ), target_string );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_right()
X
X DESCRIPTION: This C function implements the BASIC
X predefined RIGHT$ function
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_right( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X register int c;
X char target_string[ MAXSTRINGSIZE + 1 ];
X int target_counter, num_spaces;
X char tbuf[ MAXSTRINGSIZE + 1 ];
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X }
X
X /* check arguments */
X
X #if PROG_ERRORS
X if ( argc < 2 )
X {
X sprintf( bwb_ebuf, "Not enough arguments to function RIGHT$()" );
X bwb_error( bwb_ebuf );
X return &nvar;
X }
X
X if ( argc > 2 )
X {
X sprintf( bwb_ebuf, "Two many arguments to function RIGHT$()" );
X bwb_error( bwb_ebuf );
X return &nvar;
X }
X
X #else
X if ( fnc_checkargs( argc, argv, 2, 2 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* get arguments */
X
X str_btoc( target_string, var_getsval( &( argv[ 0 ] ) ));
X target_counter = strlen( target_string ) - var_getival( &( argv[ 1 ] ));
X num_spaces = MAXSTRINGSIZE;
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_right() string <%s> startpos <%d> spaces <%d>",
X target_string, target_counter, num_spaces );
X bwb_debug( bwb_ebuf );
X #endif
X
X c = 0;
X tbuf[ c ] = '\0';
X while ( ( c < num_spaces ) && ( target_string[ target_counter ] != '\0' ))
X {
X tbuf[ c ] = target_string[ target_counter ];
X ++c;
X tbuf[ c ] = '\0';
X ++target_counter;
X }
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_timer()
X
X DESCRIPTION: This C function implements the BASIC
X predefined TIMER function
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_timer( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static time_t now;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, SINGLE );
X }
X
X time( &now );
X * var_findfval( &nvar, nvar.array_pos )
X = (float) fmod( (double) now, (double) (60*60*24));
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_val()
X
X DESCRIPTION:
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_val( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, SINGLE );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check arguments */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough arguments to function VAL()" );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function VAL().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X else if ( argv[ 0 ].type != STRING )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "Argument to function VAL() must be a string.",
X argc );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_mismatch );
X #endif
X return NULL;
X }
X
X /* read the value */
X
X str_btoc( tbuf, var_getsval( &( argv[ 0 ] ) ));
X sscanf( tbuf, "%f",
X var_findfval( &nvar, nvar.array_pos ) );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_len()
X
X DESCRIPTION:
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_len( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static int init = FALSE;
X static char *tbuf;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, INTEGER );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check parameters */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function LEN().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function LEN().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* return length as an integer */
X
X str_btoc( tbuf, var_getsval( &( argv[ 0 ] )) );
X * var_findival( &nvar, nvar.array_pos )
X = strlen( tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_hex()
X
X DESCRIPTION:
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_hex( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check parameters */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function HEX$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function HEX$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* format as hex integer */
X
X sprintf( tbuf, "%X", (int) trnc_int( (double) var_getfval( &( argv[ 0 ] )) ) );
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_oct()
X
X DESCRIPTION: This C function implements the BASIC
X OCT$() function.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_oct( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check parameters */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function OCT$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function OCT$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* format as octal integer */
X
X sprintf( tbuf, "%o", var_getival( &( argv[ 0 ] ) ) );
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_asc()
X
X DESCRIPTION: This function implements the predefined
X BASIC ASC() function.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_asc( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, INTEGER );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check parameters */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function ASC().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function ASC().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X if ( argv[ 0 ].type != STRING )
X {
X #if PROG_ERRORS
X sprintf( bwb_ebuf, "Argument to function ASC() must be a string.",
X argc );
X bwb_error( bwb_ebuf );
X #else
X bwb_error( err_mismatch );
X #endif
X return NULL;
X }
X
X /* assign ASCII value of first character in the buffer */
X
X str_btoc( tbuf, var_findsval( &( argv[ 0 ] ), argv[ 0 ].array_pos ) );
X * var_findival( &nvar, nvar.array_pos ) = (int) tbuf[ 0 ];
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_asc(): string is <%s>",
X tbuf );
X bwb_debug( bwb_ebuf );
X #endif
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_string()
X
X DESCRIPTION: This C function implements the BASIC
X STRING$() function.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_string( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X int length;
X register int i;
X char c;
X struct bwb_variable *v;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check for correct number of parameters */
X
X #if PROG_ERRORS
X if ( argc < 2 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function STRING$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 2 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function STRING$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 2, 2 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X strcpy( nvar.name, "(string$)!" );
X nvar.type = STRING;
X tbuf[ 0 ] = '\0';
X length = var_getival( &( argv[ 0 ] ));
X
X if ( argv[ 1 ].type == STRING )
X {
X str_btoc( tbuf, var_getsval( &( argv[ 1 ] )));
X c = tbuf[ 0 ];
X }
X else
X {
X c = (char) var_getival( &( argv[ 1 ] ) );
X }
X
X #if INTENSIVE_DEBUG
X sprintf( bwb_ebuf, "in fnc_string(): argument <%s> arg type <%c>, length <%d>",
X argv[ 1 ].string, argv[ 1 ].type, length );
X bwb_debug( bwb_ebuf );
X sprintf( bwb_ebuf, "in fnc_string(): type <%c>, c <0x%x>=<%c>",
X argv[ 1 ].type, c, c );
X bwb_debug( bwb_ebuf );
X #endif
X
X /* add characters to the string */
X
X for ( i = 0; i < length; ++i )
X {
X tbuf[ i ] = c;
X tbuf[ i + 1 ] = '\0';
X }
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_environ()
X
X DESCRIPTION: This C function implements the BASIC
X ENVIRON$() function.
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_environ( int argc, struct bwb_variable *argv )
X {
X char tbuf[ MAXSTRINGSIZE + 1 ];
X char tmp[ MAXSTRINGSIZE + 1 ];
X static struct bwb_variable nvar;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X }
X
X /* check for correct number of parameters */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function ENVIRON$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function ENVIRON$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* resolve the argument and place string value in tbuf */
X
X str_btoc( tbuf, var_getsval( &( argv[ 0 ] )));
X
X /* call getenv() then write value to string */
X
X strcpy( tmp, getenv( tbuf ));
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tmp );
X
X /* return address of nvar */
X
X return &nvar;
X
X }
X
X/***************************************************************
X
X FUNCTION: fnc_instr()
X
X DESCRIPTION:
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_instr( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static int init = FALSE;
X int n_pos, x_pos, y_pos;
X int start_pos;
X register int n;
X char xbuf[ MAXSTRINGSIZE + 1 ];
X char ybuf[ MAXSTRINGSIZE + 1 ];
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, INTEGER );
X }
X
X /* check for correct number of parameters */
X
X #if PROG_ERRORS
X if ( argc < 2 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function INSTR().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 3 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function INSTR().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 2, 3 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* determine argument positions */
X
X if ( argc == 3 )
X {
X n_pos = 0;
X x_pos = 1;
X y_pos = 2;
X }
X else
X {
X n_pos = -1;
X x_pos = 0;
X y_pos = 1;
X }
X
X /* determine starting position */
X
X if ( n_pos == 0 )
X {
X start_pos = var_getival( &( argv[ n_pos ] ) ) - 1;
X }
X else
X {
X start_pos = 0;
X }
X
X /* get x and y strings */
X
X str_btoc( xbuf, var_getsval( &( argv[ x_pos ] ) ) );
X str_btoc( ybuf, var_getsval( &( argv[ y_pos ] ) ) );
X
X /* now search for match */
X
X for ( n = start_pos; n < strlen( xbuf ); ++n )
X {
X if ( strncmp( &( xbuf[ n ] ), ybuf, strlen( ybuf ) ) == 0 )
X {
X * var_findival( &nvar, nvar.array_pos ) = n + 1;
X return &nvar;
X }
X }
X
X /* match not found */
X
X * var_findival( &nvar, nvar.array_pos ) = 0;
X return &nvar;
X
X }
X
X/***************************************************************
X
X FUNCTION: fnc_str()
X
X DESCRIPTION:
X
X***************************************************************/
X
Xstruct bwb_variable *
Xfnc_str( int argc, struct bwb_variable *argv )
X {
X static struct bwb_variable nvar;
X static char *tbuf;
X static int init = FALSE;
X
X /* initialize the variable if necessary */
X
X if ( init == FALSE )
X {
X init = TRUE;
X var_make( &nvar, STRING );
X if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
X {
X bwb_error( err_getmem );
X }
X }
X
X /* check parameters */
X
X #if PROG_ERRORS
X if ( argc < 1 )
X {
X sprintf( bwb_ebuf, "Not enough parameters (%d) to function STR$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X else if ( argc > 1 )
X {
X sprintf( bwb_ebuf, "Too many parameters (%d) to function STR$().",
X argc );
X bwb_error( bwb_ebuf );
X return NULL;
X }
X #else
X if ( fnc_checkargs( argc, argv, 1, 1 ) == FALSE )
X {
X return NULL;
X }
X #endif
X
X /* format as decimal number */
X
X sprintf( tbuf, " %.*f", prn_precision( &( argv[ 0 ] ) ),
X var_getfval( &( argv[ 0 ] ) ) );
X str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
X
X return &nvar;
X }
X
X/***************************************************************
X
X FUNCTION: fnc_checkargs()
X
X DESCRIPTION: This C function checks the arguments to
X functions.
X
X***************************************************************/
X
X#if PROG_ERRORS
X#else
Xint
Xfnc_checkargs( int argc, struct bwb_variable *argv, int min, int max )
X {
X
X if ( argc < min )
X {
X bwb_error( err_syntax );
X return FALSE;
X }
X if ( argc > max )
X {
X bwb_error( err_syntax );
X return FALSE;
X }
X
X return TRUE;
X
X }
X#endif
X
X/***************************************************************
X
X FUNCTION: fnc_fncs()
X
X DESCRIPTION: This C function is used for debugging
X purposes; it prints a list of all defined
X functions.
X
X***************************************************************/
X
X#if PERMANENT_DEBUG
Xstruct bwb_line *
Xbwb_fncs( struct bwb_line *l )
X {
X struct bwb_function *f;
X
X for ( f = fnc_start.next; f != &fnc_end; f = f->next )
X {
X fprintf( stdout, "%s\t%c \n", f->name, f->type );
X }
X
X l->next->position = 0;
X return l->next;
X
X }
X#endif
END_OF_FILE
if test 50459 -ne `wc -c <'bwb_fnc.c'`; then
echo shar: \"'bwb_fnc.c'\" unpacked with wrong size!
fi
# end of 'bwb_fnc.c'
fi
echo shar: End of archive 1 \(of 11\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 11 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...