|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471 |
- /***************************************************************
-
- bwb_cnd.c Conditional Expressions and Commands
- for Bywater BASIC Interpreter
-
- Copyright (c) 1993, Ted A. Campbell
- Bywater Software
-
- email: tcamp@delphi.com
-
- Copyright and Permissions Information:
-
- All U.S. and international rights are claimed by the author,
- Ted A. Campbell.
-
- This software is released under the terms of the GNU General
- Public License (GPL), which is distributed with this software
- in the file "COPYING". The GPL specifies the terms under
- which users may copy and use the software in this distribution.
-
- A separate license is available for commercial distribution,
- for information on which you should contact the author.
-
- ***************************************************************/
-
- /*---------------------------------------------------------------*/
- /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
- /* 11/1995 (eidetics@cerf.net). */
- /* */
- /* Those additionally marked with "DD" were at the suggestion of */
- /* Dale DePriest (daled@cadence.com). */
- /*---------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <math.h>
- #include <ctype.h>
-
- #include "bwbasic.h"
- #include "bwb_mes.h"
-
- /* declarations of functions visible to this file only */
-
- #if ANSI_C
- static int cnd_thenels( char *buffer, int position, int *then, int *els );
- static int cnd_tostep( char *buffer, int position, int *to, int *step );
- static struct bwb_line *find_wend( struct bwb_line *l );
- static struct bwb_line *find_endif( struct bwb_line *l,
- struct bwb_line **else_line );
- static int is_endif( struct bwb_line *l );
- extern int var_setnval( struct bwb_variable *v, bnumber i );
- static int case_eval( struct exp_ese *expression, struct exp_ese *minval,
- struct exp_ese *maxval );
- static struct bwb_line *find_case( struct bwb_line *l );
- static struct bwb_line *find_endselect( struct bwb_line *l );
- static int is_endselect( struct bwb_line *l );
- static struct bwb_line *bwb_caseif( struct bwb_line *l );
-
- #if STRUCT_CMDS
- static struct bwb_line *find_next( struct bwb_line *l );
- #endif
-
- #else
- static int cnd_thenels();
- static int cnd_tostep();
- static struct bwb_line *find_wend();
- static struct bwb_line *find_endif();
- static int is_endif();
- extern int var_setnval();
- static int case_eval();
- static struct bwb_line *find_case();
- static struct bwb_line *find_endselect();
- static int is_endselect();
- static struct bwb_line *bwb_caseif();
-
- #if STRUCT_CMDS
- static struct bwb_line *find_next();
- #endif
-
- #endif /* ANSI_C for prototypes */
-
- /*** IF-THEN-ELSE ***/
-
- /***************************************************************
-
- FUNCTION: bwb_if()
-
- DESCRIPTION: This function handles the BASIC IF
- statement.
-
- SYNTAX: IF expression THEN [statement [ELSE statement]]
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_if( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_if( l )
- struct bwb_line *l;
- #endif
- {
- int then, els;
- struct exp_ese *e;
- int glnumber;
- int tpos;
- static char tbuf[ MAXSTRINGSIZE + 1 ];
- static struct bwb_line gline;
- #if STRUCT_CMDS
- static struct bwb_line *else_line;
- static struct bwb_line *endif_line;
- #endif
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): entry, line <%d> buffer <%s>",
- l->number, &( l->buffer[ l->position ] ) );
- bwb_debug( bwb_ebuf );
- getchar();
- #endif
-
- #if INTENSIVE_DEBUG
- if ( l == &gline )
- {
- sprintf( bwb_ebuf, "in bwb_if(): recursive call, l = &gline" );
- bwb_debug( bwb_ebuf );
- }
- #endif
-
- /* Call bwb_exp() to evaluate the condition. This should return
- with position set to the "THEN" statement */
-
- e = bwb_exp( l->buffer, FALSE, &( l->position ) );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): line <%d> condition returns <%d>",
- l->number, exp_getnval( e ) );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* test for "THEN" and "ELSE" statements */
-
- cnd_thenels( l->buffer, l->position, &then, &els );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): return from cnd_thenelse, line is <%s>",
- l->buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* test for multiline IF statement: this presupposes ANSI-compliant
- structured BASIC */
-
- #if STRUCT_CMDS
- tpos = then + strlen( CMD_THEN ) + 1;
- if ( is_eol( l->buffer, &tpos ) == TRUE )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): found multi-line IF statement, line <%d>",
- l->number );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* find END IF and possibly ELSE[IF] line(s) */
-
- else_line = NULL;
- endif_line = find_endif( l, &else_line );
-
- /* evaluate the expression */
-
- if ( (int) exp_getnval( e ) != FALSE )
- {
- bwb_incexec();
- bwb_setexec( l->next, 0, EXEC_IFTRUE );
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
-
- else if ( else_line != NULL )
- {
- bwb_incexec();
- bwb_setexec( else_line, 0, EXEC_IFFALSE );
- else_line->position = 0;
- return else_line;
- }
- else
- {
- /* Following line incorrect, replaced by next two (bug found by DD) */
- /* bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code ); */
-
- bwb_incexec(); /* JBV */
- bwb_setexec( endif_line, 0, EXEC_IFFALSE ); /* JBV */
- endif_line->position = 0;
- return endif_line;
- }
- }
-
- #endif /* STRUCT_CMDS for Multi-line IF...THEN */
-
- /* Not a Multi-line IF...THEN: test for THEN line-number */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): not multi-line; line is <%s>",
- l->buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* evaluate and execute */
-
- if ( (int) exp_getnval( e ) != FALSE )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): expression is TRUE" );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( then == FALSE )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_if(): IF without THEN" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
- else
- {
-
- /* check for THEN followed by literal line number */
-
- tpos = then + strlen( CMD_THEN ) + 1;
- adv_element( l->buffer, &tpos, tbuf );
-
- if ( isdigit( tbuf[ 0 ] ) != 0 )
- {
-
- glnumber = atoi( tbuf );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "Detected THEN followed by line number <%d>",
- glnumber );
- bwb_debug( bwb_ebuf );
- #endif
-
- sprintf( tbuf, "%s %d", CMD_GOTO, glnumber );
- gline.buffer = tbuf;
- gline.marked = FALSE;
- gline.position = 0;
- gline.next = l->next;
- bwb_setexec( &gline, 0, CURTASK excs[ CURTASK exsc ].code );
- return &gline;
- }
-
- /* form is not THEN followed by line number */
-
- else
- {
- bwb_setexec( l, then, CURTASK excs[ CURTASK exsc ].code );
- l->position = then + strlen( CMD_THEN ) + 1;
- }
-
- return l;
- }
- }
- else
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_if(): expression is FALSE" );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( els != FALSE )
- {
- l->position = els + strlen( CMD_ELSE ) + 1;
- /* bwb_setexec( l, els, EXEC_NORM ); */ /* Nope (JBV) */
- bwb_setexec( l, els, CURTASK excs[ CURTASK exsc ].code ); /* JBV */
- return l;
- }
- }
-
- /* if neither then nor else were found, advance to next line */
- /* DO NOT advance to next segment (only if TRUE should we do that) */
-
- l->next->position = 0;
- return l->next;
-
- }
-
- /***************************************************************
-
- FUNCTION: cnd_thenelse()
-
- DESCRIPTION: This function searches through the
- <buffer> beginning at point <position>
- and attempts to find positions of THEN
- and ELSE statements.
-
- ***************************************************************/
-
- #if ANSI_C
- static int
- cnd_thenels( char *buffer, int position, int *then, int *els )
- #else
- static int
- cnd_thenels( buffer, position, then, els )
- char *buffer;
- int position;
- int *then;
- int *els;
- #endif
- {
- int loop, t_pos, b_pos, p_word;
- char tbuf[ MAXSTRINGSIZE + 1 ];
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_thenels(): entry, line is <%s>",
- &( buffer[ position ] ) );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* set then and els to 0 initially */
-
- *then = *els = 0;
-
- /* loop to find words */
-
- p_word = b_pos = position;
- t_pos = 0;
- tbuf[ 0 ] = '\0';
- loop = TRUE;
- while( loop == TRUE )
- {
-
- switch( buffer[ b_pos ] )
- {
- case '\0': /* end of string */
- case ' ': /* whitespace = end of word */
- case '\t':
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_thenels(): word is <%s>", tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( strncmp( tbuf, CMD_THEN, (size_t) strlen( CMD_THEN ) ) == 0 )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_thenels(): THEN found at position <%d>.",
- p_word );
- bwb_debug( bwb_ebuf );
- sprintf( bwb_ebuf, "in cnd_thenelse(): after THEN, line is <%s>", buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- *then = p_word;
- }
- else if ( strncmp( tbuf, CMD_ELSE, (size_t) strlen( CMD_ELSE ) ) == 0 )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_thenels(): ELSE found at position <%d>.",
- p_word );
- bwb_debug( bwb_ebuf );
- sprintf( bwb_ebuf, "in cnd_thenelse(): after ELSE, line is <%s>", buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- *els = p_word;
- }
-
- /* check for end of the line */
-
- if ( buffer[ b_pos ] == '\0' )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_thenels(): return: end of string" );
- bwb_debug( bwb_ebuf );
- #endif
- return TRUE;
- }
-
- ++b_pos;
- p_word = b_pos;
- t_pos = 0;
- tbuf[ 0 ] = '\0';
- break;
-
- default:
- if ( islower( buffer[ b_pos ] ) != FALSE )
- {
- tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );
- }
- else
- {
- tbuf[ t_pos ] = buffer[ b_pos ];
- }
- ++b_pos;
- ++t_pos;
- tbuf[ t_pos ] = '\0';
- break;
- }
-
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_thenelse(): exit, line is <%s>", buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- return FALSE;
-
- }
-
- #if STRUCT_CMDS
-
- /***************************************************************
-
- FUNCTION: bwb_else()
-
- DESCRIPTION: This function handles the BASIC ELSE
- statement.
-
- SYNTAX: ELSE
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_else( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_else( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *endif_line;
- struct bwb_line *else_line;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_else(): entered function" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* If the code is EXEC_NORM, then this is a continuation of a single-
- line IF...THEN...ELSE... statement and we should return */
-
- /*----------------------------------------------------------------------*/
- /* Well, not really... better to check for EXEC_IFTRUE or EXEC_IFFALSE, */
- /* and if not equal, then blow entirely out of current line (JBV) */
- /*----------------------------------------------------------------------*/
-
- /* Section removed by JBV */
- /* if ( CURTASK excs[ CURTASK exsc ].code == EXEC_NORM )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_else(): detected EXEC_NORM" );
- bwb_debug( bwb_ebuf );
- #endif
-
- return bwb_zline( l );
- } */
-
- /* Section added by JBV */
- if (( CURTASK excs[ CURTASK exsc ].code != EXEC_IFTRUE ) &&
- ( CURTASK excs[ CURTASK exsc ].code != EXEC_IFFALSE ))
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_else(): no EXEC_IFTRUE or EXEC_IFFALSE" );
- bwb_debug( bwb_ebuf );
- #endif
-
- l->next->position = 0;
- return l->next;
- }
-
- endif_line = find_endif( l, &else_line );
-
- if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )
- {
- endif_line->position = 0;
- return endif_line;
- }
- else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )
- {
-
- return bwb_zline( l );
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_else(): ELSE without IF" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
-
- return bwb_zline( l );
- }
-
- /***************************************************************
-
- FUNCTION: bwb_elseif()
-
- DESCRIPTION: This function handles the BASIC ELSEIF
- statement.
-
- SYNTAX: ELSEIF
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_elseif( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_elseif( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *endif_line;
- struct bwb_line *else_line;
- struct exp_ese *e;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_elseif(): entered function" );
- bwb_debug( bwb_ebuf );
- #endif
-
- else_line = NULL;
- endif_line = find_endif( l, &else_line );
-
- if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )
- {
- endif_line->position = 0;
- return endif_line;
- }
-
- else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )
- {
-
- /* Call bwb_exp() to evaluate the condition. This should return
- with position set to the "THEN" statement */
-
- e = bwb_exp( l->buffer, FALSE, &( l->position ) );
-
- if ( (int) exp_getnval( e ) != FALSE ) /* Was == TRUE (JBV 10/1996) */
- {
-
- /* ELSEIF condition is TRUE: proceed to the next line */
-
- CURTASK excs[ CURTASK exsc ].code = EXEC_IFTRUE;
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
-
- }
-
- /* ELSEIF condition FALSE: proceed to next ELSE line if there is one */
-
- else if ( else_line != NULL )
- {
- bwb_setexec( else_line, 0, EXEC_IFFALSE );
- else_line->position = 0;
- return else_line;
- }
-
- /* ELSEIF condition is FALSE and no more ELSExx lines: proceed to END IF */
-
- else
- {
- bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );
- endif_line->position = 0;
- return endif_line;
- }
-
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_elseif(): ELSEIF without IF" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_endif()
-
- DESCRIPTION: This function handles the BASIC END IF
- statement.
-
- SYNTAX: END IF
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_endif( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_endif( l )
- struct bwb_line *l;
- #endif
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_endif(): entered function" );
- bwb_debug( bwb_ebuf );
- #endif
-
- if (( CURTASK excs[ CURTASK exsc ].code != EXEC_IFTRUE )
- && ( CURTASK excs[ CURTASK exsc ].code != EXEC_IFFALSE ))
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_endif(): END IF without IF" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
-
- bwb_decexec();
-
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
-
- /***************************************************************
-
- FUNCTION: find_endif()
-
- DESCRIPTION: This C function attempts to find an
- END IF statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static struct bwb_line *
- find_endif( struct bwb_line *l, struct bwb_line **else_line )
- #else
- static struct bwb_line *
- find_endif( l, else_line )
- struct bwb_line *l;
- struct bwb_line **else_line;
- #endif
- {
- struct bwb_line *current;
- register int i_level;
- int position;
-
- *else_line = NULL;
- i_level = 1;
- for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
- {
- position = 0;
- if ( current->marked != TRUE )
- {
- line_start( current->buffer, &position, &( current->lnpos ),
- &( current->lnum ),
- &( current->cmdpos ),
- &( current->cmdnum ),
- &( current->startpos ) );
- }
- current->position = current->startpos;
-
- if ( current->cmdnum > -1 )
- {
-
- if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_if )
- {
- ++i_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_endif(): found IF at line %d, level %d",
- current->number, i_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- else if ( is_endif( current ) == TRUE )
- {
- --i_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_endif(): found END IF at line %d, level %d",
- current->number, i_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( i_level == 0 )
- {
- return current;
- }
- }
-
- else if ( ( bwb_cmdtable[ current->cmdnum ].vector == bwb_else )
- || ( bwb_cmdtable[ current->cmdnum ].vector == bwb_elseif ))
- {
-
- /* we must only report the first ELSE or ELSE IF we encounter
- at level 1 */
-
- if ( ( i_level == 1 ) && ( *else_line == NULL ))
- {
- *else_line = current;
- }
-
- }
- }
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "Multiline IF without END IF" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: is_endif()
-
- DESCRIPTION: This C function attempts to determine if
- a given line contains an END IF statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static int
- is_endif( struct bwb_line *l )
- #else
- static int
- is_endif( l )
- struct bwb_line *l;
- #endif
- {
- int position;
- char tbuf[ MAXVARNAMESIZE + 1];
-
- if ( bwb_cmdtable[ l->cmdnum ].vector != bwb_xend )
- {
- return FALSE;
- }
-
- position = l->startpos;
- adv_ws( l->buffer, &position );
- adv_element( l->buffer, &position, tbuf );
- bwb_strtoupper( tbuf );
-
- if ( strcmp( tbuf, "IF" ) == 0 )
- {
- return TRUE;
- }
-
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_select()
-
- DESCRIPTION: This C function handles the BASIC SELECT
- statement.
-
- SYNTAX: SELECT CASE expression
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_select( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_select( l )
- struct bwb_line *l;
- #endif
- {
- char tbuf[ MAXSTRINGSIZE + 1 ];
- struct exp_ese *e;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_select(): entered function" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* first element should be "CASE" */
-
- adv_element( l->buffer, &( l->position ), tbuf );
- bwb_strtoupper( tbuf );
- if ( strcmp( tbuf, "CASE" ) != 0 )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "SELECT without CASE" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
-
- return bwb_zline( l );
- #endif
- }
-
- /* increment the level and set to EXEC_SELFALSE */
-
- bwb_incexec();
- CURTASK excs[ CURTASK exsc ].code = EXEC_SELFALSE;
-
- /* evaluate the expression at this level */
-
- e = bwb_exp( l->buffer, FALSE, &( l->position ) );
-
- #if OLDWAY
- memcpy( &( CURTASK excs[ CURTASK exsc ].expression ), e,
- sizeof( struct exp_ese ) );
- #endif
-
- if ( e->type == STRING )
- {
- CURTASK excs[ CURTASK exsc ].expression.type = STRING;
- str_btob( &( CURTASK excs[ CURTASK exsc ].expression.sval ),
- &( e->sval ) );
- }
- else
- {
- CURTASK excs[ CURTASK exsc ].expression.type = NUMBER;
- CURTASK excs[ CURTASK exsc ].expression.nval
- = exp_getnval( e );
- }
-
- /* return */
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
-
- return bwb_zline( l );
- }
-
- /***************************************************************
-
- FUNCTION: bwb_case()
-
- DESCRIPTION: This C function handles the BASIC CASE
- statement.
-
- SYNTAX: CASE constant | IF partial-expression | ELSE
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_case( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_case( l )
- struct bwb_line *l;
- #endif
- {
- char tbuf[ MAXSTRINGSIZE + 1 ];
- int oldpos;
- struct exp_ese minvalue;
- struct exp_ese *maxval, *minval;
- struct bwb_line *retline;
- char cbuf1[ MAXSTRINGSIZE + 1 ];
- char cbuf2[ MAXSTRINGSIZE + 1 ];
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): entered function" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* if code is EXEC_SELTRUE, then we should jump to the end */
-
- if ( CURTASK excs[ CURTASK exsc ].code == EXEC_SELTRUE )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): exit EXEC_SELTRUE" );
- bwb_debug( bwb_ebuf );
- #endif
- retline = find_endselect( l );
- retline->position = 0;
- return retline;
- }
-
- /* read first element */
-
- oldpos = l->position;
- adv_element( l->buffer, &( l->position ), tbuf );
- bwb_strtoupper( tbuf );
-
- /* check for CASE IF */
-
- if ( strcmp( tbuf, CMD_IF ) == 0 )
- {
- return bwb_caseif( l );
- }
-
- /* check for CASE ELSE: if true, simply proceed to the next line,
- because other options should have been detected by now */
-
- else if ( strcmp( tbuf, CMD_ELSE ) == 0 )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): execute CASE ELSE" );
- bwb_debug( bwb_ebuf );
- #endif
-
- return bwb_zline( l );
- }
-
- /* neither CASE ELSE nor CASE IF; presume constant here for min value */
-
- l->position = oldpos;
- minval = bwb_exp( l->buffer, FALSE, &( l->position ));
- memcpy( &minvalue, minval, sizeof( struct exp_ese ) );
- maxval = minval = &minvalue;
-
- /* check for string value */
-
- if ( minvalue.type == STRING )
- {
-
- str_btoc( cbuf1, &( CURTASK excs[ CURTASK exsc ].expression.sval ) );
- str_btoc( cbuf2, &( minvalue.sval ) );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): compare strings <%s> and <%s>",
- cbuf1, cbuf2 );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( strncmp( cbuf1, cbuf2, MAXSTRINGSIZE ) == 0 )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): string comparison returns TRUE" );
- bwb_debug( bwb_ebuf );
- #endif
- CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
-
- else
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): string comparison returns FALSE" );
- bwb_debug( bwb_ebuf );
- #endif
- retline = find_case( l );
- retline->position = 0;
- return retline;
- }
-
- }
-
- /* not a string; advance */
-
- adv_ws( l->buffer, &( l->position ));
-
- /* check for TO */
-
- if ( is_eol( l->buffer, &( l->position )) != TRUE )
- {
-
- /* find the TO statement */
-
- adv_element( l->buffer, &( l->position ), tbuf );
- bwb_strtoupper( tbuf );
- if ( strcmp( tbuf, CMD_TO ) != 0 )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "CASE has inexplicable code following expression" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- #endif
- }
-
- /* now evaluate the MAX expression */
-
- maxval = bwb_exp( l->buffer, FALSE, &( l->position ));
-
- }
-
- /* evaluate the expression */
-
- if ( case_eval( &( CURTASK excs[ CURTASK exsc ].expression ),
- minval, maxval ) == TRUE )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_case(): evaluation returns TRUE" );
- bwb_debug( bwb_ebuf );
- #endif
- CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
-
- /* evaluation returns a FALSE value; find next CASE or END SELECT statement */
-
- else
- {
- #if INTENSIVE_DEBUGb
- sprintf( bwb_ebuf, "in bwb_case(): evaluation returns FALSE" );
- bwb_debug( bwb_ebuf );
- #endif
- retline = find_case( l );
- retline->position = 0;
- return retline;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_caseif()
-
- DESCRIPTION: This C function handles the BASIC CASE IF
- statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static struct bwb_line *
- bwb_caseif( struct bwb_line *l )
- #else
- static struct bwb_line *
- bwb_caseif( l )
- struct bwb_line *l;
- #endif
- {
- char tbuf[ MAXSTRINGSIZE + 1 ];
- int position;
- struct exp_ese *r;
- struct bwb_line *retline;
-
- if ( CURTASK excs[ CURTASK exsc ].expression.type == NUMBER )
- {
- sprintf( tbuf, "%f %s",
- (float) CURTASK excs[ CURTASK exsc ].expression.nval,
- &( l->buffer[ l->position ] ) );
- }
- else
- {
- bwb_error( err_mismatch );
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
-
- position = 0;
- r = bwb_exp( tbuf, FALSE, &position );
-
- if ( r->nval == (bnumber) TRUE )
- {
- CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
- else
- {
- retline = find_case( l );
- retline->position = 0;
- return retline;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: case_eval()
-
- DESCRIPTION: This function evaluates a case statement
- by comparing minimum and maximum values
- with a set expression. It returns either
- TRUE or FALSE
-
- ***************************************************************/
-
- #if ANSI_C
- static int
- case_eval( struct exp_ese *expression, struct exp_ese *minval,
- struct exp_ese *maxval )
- #else
- static int
- case_eval( expression, minval, maxval )
- struct exp_ese *expression;
- struct exp_ese *minval;
- struct exp_ese *maxval;
- #endif
- {
-
- /* string value */
-
- if ( expression->type == STRING )
- {
- bwb_error( err_mismatch );
- return FALSE;
- }
-
- /* numerical value */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in case_eval(): n <%f> min <%f> max <%f>",
- (float) expression->nval,
- (float) minval->nval,
- (float) maxval->nval );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( ( expression->nval >= minval->nval )
- && ( expression->nval <= maxval->nval ))
- {
- return TRUE;
- }
-
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: find_case()
-
- DESCRIPTION: This function searches for a line containing
- a CASE statement corresponding to a previous
- SELECT CASE statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static struct bwb_line *
- find_case( struct bwb_line *l )
- #else
- static struct bwb_line *
- find_case( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *current;
- register int c_level;
- int position;
-
- c_level = 1;
- for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
- {
- position = 0;
- if ( current->marked != TRUE )
- {
- line_start( current->buffer, &position, &( current->lnpos ),
- &( current->lnum ),
- &( current->cmdpos ),
- &( current->cmdnum ),
- &( current->startpos ) );
- }
- current->position = current->startpos;
-
- if ( current->cmdnum > -1 )
- {
-
- if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_select )
- {
- ++c_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_case(): found SELECT at line %d, level %d",
- current->number, c_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- else if ( is_endselect( current ) == TRUE )
- {
- --c_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_endif(): found END SELECT at line %d, level %d",
- current->number, c_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( c_level == 0 )
- {
- return current;
- }
- }
-
- else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_case )
- {
- --c_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_case(): found CASE at line %d, level %d",
- current->number, c_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( c_level == 0 )
- {
- return current;
- }
- }
- }
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "SELECT without CASE" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: find_case()
-
- DESCRIPTION: This function searches for a line containing
- an END SELECT statement corresponding to a previous
- SELECT CASE statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static struct bwb_line *
- find_endselect( struct bwb_line *l )
- #else
- static struct bwb_line *
- find_endselect( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *current;
- register int c_level;
- int position;
-
- c_level = 1;
- for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
- {
- position = 0;
- if ( current->marked != TRUE )
- {
- line_start( current->buffer, &position, &( current->lnpos ),
- &( current->lnum ),
- &( current->cmdpos ),
- &( current->cmdnum ),
- &( current->startpos ) );
- }
- current->position = current->startpos;
-
- if ( current->cmdnum > -1 )
- {
-
- if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_select )
- {
- ++c_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_case(): found SELECT at line %d, level %d",
- current->number, c_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- else if ( is_endselect( current ) == TRUE )
- {
- --c_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_endif(): found END SELECT at line %d, level %d",
- current->number, c_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( c_level == 0 )
- {
- return current;
- }
- }
- }
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "SELECT without END SELECT" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: is_endselect()
-
- DESCRIPTION: This C function attempts to determine if
- a given line contains an END SELECT statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static int
- is_endselect( struct bwb_line *l )
- #else
- static int
- is_endselect( l )
- struct bwb_line *l;
- #endif
- {
- int position;
- char tbuf[ MAXVARNAMESIZE + 1];
-
- if ( bwb_cmdtable[ l->cmdnum ].vector != bwb_xend )
- {
- return FALSE;
- }
-
- position = l->startpos;
- adv_ws( l->buffer, &position );
- adv_element( l->buffer, &position, tbuf );
- bwb_strtoupper( tbuf );
-
- if ( strcmp( tbuf, "SELECT" ) == 0 )
- {
- return TRUE;
- }
-
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_endselect()
-
- DESCRIPTION: This function handles the BASIC END
- SELECT statement.
-
- SYNTAX: END SELECT
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_endselect( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_endselect( l )
- struct bwb_line *l;
- #endif
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_endselect(): entered function" );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( ( CURTASK excs[ CURTASK exsc ].code != EXEC_SELTRUE )
- && ( CURTASK excs[ CURTASK exsc ].code != EXEC_SELFALSE ))
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_endselect(): END SELECT without SELECT" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
-
- bwb_decexec();
-
-
- #if MULTISEG_LINES
- adv_eos( l->buffer, &( l->position ));
- #endif
- return bwb_zline( l );
- }
-
- #endif /* STRUCT_CMDS */
-
- #if COMMON_CMDS || STRUCT_CMDS
-
- /*** WHILE-WEND ***/
-
- /***************************************************************
-
- FUNCTION: bwb_while()
-
- DESCRIPTION: This function handles the BASIC WHILE
- statement and also the ANSI DO WHILE
- statement.
-
- SYNTAX: WHILE expression
- DO WHILE expression
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_while( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_while( l )
- struct bwb_line *l;
- #endif
- {
- struct exp_ese *e;
- struct bwb_line *r;
-
- /* if this is the first time at this WHILE statement, note it */
-
- if ( CURTASK excs[ CURTASK exsc ].while_line != l )
- {
-
- bwb_incexec();
- CURTASK excs[ CURTASK exsc ].while_line = l;
-
- /* find the WEND statement (or LOOP statement) */
-
- #if STRUCT_CMDS
- if ( l->cmdnum == getcmdnum( CMD_DO ))
- {
- CURTASK excs[ CURTASK exsc ].wend_line = find_loop( l );
- }
- else
- {
- CURTASK excs[ CURTASK exsc ].wend_line = find_wend( l );
- }
- #else
- CURTASK excs[ CURTASK exsc ].wend_line = find_wend( l );
- #endif
-
- if ( CURTASK excs[ CURTASK exsc ].wend_line == NULL )
- {
- return bwb_zline( l );
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_while(): initialize WHILE loop, line <%d>",
- l->number );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- #if INTENSIVE_DEBUG
- else
- {
- sprintf( bwb_ebuf, "in bwb_while(): return to WHILE loop, line <%d>",
- l->number );
- bwb_debug( bwb_ebuf );
- }
- #endif
-
- /*----------------------------------------------------*/
- /* Expression evaluation was at the top of bwb_while, */
- /* and the init portion was performed only if TRUE. */
- /* The init routine should be performed regardless of */
- /* expression value, else a segmentation fault can */
- /* occur! (JBV) */
- /*----------------------------------------------------*/
-
- /* call bwb_exp() to interpret the expression */
-
- e = bwb_exp( l->buffer, FALSE, &( l->position ) );
-
- if ( (int) exp_getnval( e ) != FALSE ) /* Was == TRUE (JBV 10/1996) */
- {
- bwb_setexec( l, l->position, EXEC_WHILE );
- return bwb_zline( l );
- }
- else
- {
- CURTASK excs[ CURTASK exsc ].while_line = NULL;
- r = CURTASK excs[ CURTASK exsc ].wend_line;
- bwb_setexec( r, 0, CURTASK excs[ CURTASK exsc - 1 ].code );
- r->position = 0;
- bwb_decexec();
- return r;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_wend()
-
- DESCRIPTION: This function handles the BASIC WEND
- statement and the LOOP statement ending
- a DO WHILE loop.
-
- SYNTAX: WEND
- LOOP
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_wend( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_wend( l )
- struct bwb_line *l;
- #endif
- {
-
- /* check integrity of WHILE loop */
-
- if ( CURTASK excs[ CURTASK exsc ].code != EXEC_WHILE )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_wend(): exec stack code != EXEC_WHILE" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
-
- if ( CURTASK excs[ CURTASK exsc ].while_line == NULL )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_wend(): exec stack while_line == NULL" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
-
- /* reset to the top of the current WHILE loop */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_wend() return to line <%d>",
- CURTASK excs[ CURTASK exsc ].while_line->number );
- bwb_debug( bwb_ebuf );
- #endif
-
- CURTASK excs[ CURTASK exsc ].while_line->position = 0;
- bwb_setexec( CURTASK excs[ CURTASK exsc ].while_line, 0, EXEC_WHILE );
-
- return CURTASK excs[ CURTASK exsc ].while_line;
-
- }
-
- /***************************************************************
-
- FUNCTION: find_wend()
-
- DESCRIPTION: This function searches for a line containing
- a WEND statement corresponding to a previous
- WHILE statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static struct bwb_line *
- find_wend( struct bwb_line *l )
- #else
- static struct bwb_line *
- find_wend( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *current;
- register int w_level;
- int position;
-
- w_level = 1;
- for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
- {
- position = 0;
- if ( current->marked != TRUE )
- {
- line_start( current->buffer, &position, &( current->lnpos ),
- &( current->lnum ),
- &( current->cmdpos ),
- &( current->cmdnum ),
- &( current->startpos ) );
- }
- current->position = current->startpos;
-
- if ( current->cmdnum > -1 )
- {
-
- if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_while )
- {
- ++w_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_wend(): found WHILE at line %d, level %d",
- current->number, w_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_wend )
- {
- --w_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_wend(): found WEND at line %d, level %d",
- current->number, w_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( w_level == 0 )
- {
- return current->next;
- }
- }
- }
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in find_wend(): WHILE without WEND" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return NULL;
-
- }
-
- #if STRUCT_CMDS
-
- /***************************************************************
-
- FUNCTION: find_loop()
-
- DESCRIPTION: This function searches for a line containing
- a LOOP statement corresponding to a previous
- DO statement.
-
- ***************************************************************/
-
- #if ANSI_C
- extern struct bwb_line *
- find_loop( struct bwb_line *l )
- #else
- extern struct bwb_line *
- find_loop( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *current;
- register int w_level;
- int position;
-
- w_level = 1;
- for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
- {
- position = 0;
- if ( current->marked != TRUE )
- {
- line_start( current->buffer, &position, &( current->lnpos ),
- &( current->lnum ),
- &( current->cmdpos ),
- &( current->cmdnum ),
- &( current->startpos ) );
- }
- current->position = current->startpos;
-
- if ( current->cmdnum > -1 )
- {
-
- if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_do )
- {
- ++w_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_loop(): found DO at line %d, level %d",
- current->number, w_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_loop )
- {
- --w_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in fnd_loop(): found LOOP at line %d, level %d",
- current->number, w_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( w_level == 0 )
- {
- return current->next;
- }
- }
- }
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in find_loop(): DO without LOOP" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return NULL;
-
- }
-
- #endif /* STRUCT_CMDS */
-
- #endif /* COMMON_CMDS || STRUCT_CMDS */
-
- /*** FOR-NEXT ***/
-
- /***************************************************************
-
- FUNCTION: bwb_for()
-
- DESCRIPTION: This function handles the BASIC FOR
- statement.
-
- SYNTAX: FOR counter = start TO finish [STEP increment]
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_for( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_for( l )
- struct bwb_line *l;
- #endif
- {
- register int n;
- int e, loop;
- int to, step, p;
- int for_step, for_target;
- struct exp_ese *exp;
- struct bwb_variable *v;
- char tbuf[ MAXSTRINGSIZE + 1 ];
-
- /* get the variable name */
-
- exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
- l->position += strlen( tbuf );
- v = var_find( tbuf );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): variable name <%s>.", v->name );
- bwb_debug( bwb_ebuf );
- #endif
-
- /*--------------------------------------------------------------*/
- /* Make sure we are in the right FOR-NEXT level! */
- /* If we aren't (which could happen for legit reasons), fix the */
- /* exec stack. */
- /* JBV, 9/20/95 */
- /*--------------------------------------------------------------*/
- if (v == CURTASK excs[ CURTASK exsc].local_variable) bwb_decexec();
-
- /* at this point one should find an equals sign ('=') */
-
- adv_ws( l->buffer, &( l->position ) );
-
- if ( l->buffer[ l->position ] != '=' )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_for(): failed to find equals sign, buf <%s>",
- &( l->buffer[ l->position ] ) );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return bwb_zline( l );
- }
- else
- {
- ++( l->position );
- }
-
- /* Find the TO and STEP statements */
-
- cnd_tostep( l->buffer, l->position, &to, &step );
-
- /* if there is no TO statement, then an error has ocurred */
-
- if ( to < 1 )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "FOR statement without TO" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return bwb_zline( l );
- }
-
- /* copy initial value to buffer and evaluate it */
-
- tbuf[ 0 ] = '\0';
- p = 0;
- for ( n = l->position; n < to; ++n )
- {
- tbuf[ p ] = l->buffer[ n ];
- ++p;
- ++l->position;
- tbuf[ p ] = '\0';
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): initial value string <%s>",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- p = 0;
- exp = bwb_exp( tbuf, FALSE, &p );
- var_setnval( v, exp_getnval( exp ) );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): initial value <%d> pos <%d>",
- exp_getnval( exp ), l->position );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* copy target value to small buffer and evaluate it */
-
- tbuf[ 0 ] = '\0';
- p = 0;
- l->position = to + 2;
- if ( step < 1 )
- {
- e = strlen( l->buffer );
- }
- else
- {
- e = step - 1;
- }
-
- loop = TRUE;
- n = l->position;
- while( loop == TRUE )
- {
- tbuf[ p ] = l->buffer[ n ];
- ++p;
- ++l->position;
- tbuf[ p ] = '\0';
-
- if ( n >= e )
- {
- loop = FALSE;
- }
-
- ++n;
-
- if ( l->buffer[ n ] == ':' )
- {
- loop = FALSE;
- }
-
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): target value string <%s>",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- p = 0;
- exp = bwb_exp( tbuf, FALSE, &p );
- for_target = (int) exp_getnval( exp );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): target value <%d> pos <%d>",
- exp_getnval( exp ), l->position );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* If there is a STEP statement, copy it to a buffer
- and evaluate it */
-
- if ( step > 1 )
- {
- tbuf[ 0 ] = '\0';
- p = 0;
- l->position = step + 4;
-
- for ( n = l->position; n < (int) strlen( l->buffer ); ++n )
- {
- tbuf[ p ] = l->buffer[ n ];
- ++p;
- ++l->position;
- tbuf[ p ] = '\0';
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): step value string <%s>",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- p = 0;
- exp = bwb_exp( tbuf, FALSE, &p );
- for_step = (int) exp_getnval( exp );
-
- }
- else
- {
- for_step = 1;
- }
-
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): step value <%d>",
- for_step );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* set position in current line and increment EXEC counter */
-
- /* bwb_setexec( l, l->position, EXEC_NORM ); */ /* WRONG */
- bwb_incexec();
-
- CURTASK excs[ CURTASK exsc ].local_variable = v;
- CURTASK excs[ CURTASK exsc ].for_step = for_step;
- CURTASK excs[ CURTASK exsc ].for_target = for_target;
-
- /* set exit line to be used by EXIT FOR */
-
- #if STRUCT_CMDS
- CURTASK excs[ CURTASK exsc ].wend_line = find_next( l );
- #endif
-
- /* set top line and position to be used in multisegmented FOR-NEXT loop */
-
- #if MULTISEG_LINES
- CURTASK excs[ CURTASK exsc ].for_line = l;
- CURTASK excs[ CURTASK exsc ].for_position = l->position;
- #endif
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): setting code to EXEC_FOR",
- l->position );
- bwb_debug( bwb_ebuf );
- #endif
-
- bwb_setexec( l, l->position, EXEC_FOR );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_for(): ready to exit, position <%d>",
- l->position );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* proceed with processing */
-
- return bwb_zline( l );
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_next()
-
- DESCRIPTION: This function handles the BASIC NEXT
- statement.
-
- SYNTAX: NEXT counter
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_next( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_next( l )
- struct bwb_line *l;
- #endif
- {
- char tbuf[ MAXSTRINGSIZE + 1 ];
- struct bwb_variable *v; /* Relocated from INTENSIVE_DEBUG (JBV) */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_next(): entered function, cmdnum <%d> exsc level <%d> code <%d>",
- l->cmdnum, CURTASK exsc, CURTASK excs[ CURTASK exsc ].code );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* Check the integrity of the FOR statement */
-
- if ( CURTASK excs[ CURTASK exsc ].code != EXEC_FOR )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_next(): NEXT without FOR; code is <%d> instead of <%d>",
- CURTASK excs[ CURTASK exsc ].code, EXEC_FOR );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
-
- /* read the argument, if there is one */
-
- /* Relocated from MULTISEG_LINES (JBV) */
- exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
-
- if (strlen(tbuf) != 0)
- {
- /* Relocated from INTENSIVE_DEBUG (JBV) */
- v = var_find( tbuf );
-
- #if MULTISEG_LINES /* not currently needed otherwise */
-
- l->position += strlen( tbuf );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_next(): variable name detected <%s>.", v->name );
- bwb_debug( bwb_ebuf );
- #endif
- #endif
-
- /* decrement or increment the value */
-
- /*--------------------------------------------------------------*/
- /* Make sure we are in the right FOR-NEXT level! */
- /* If we aren't (which could happen for legit reasons), fix the */
- /* exec stack. */
- /* JBV, 9/20/95 */
- /*--------------------------------------------------------------*/
- while (v != CURTASK excs[ CURTASK exsc].local_variable) bwb_decexec();
- }
-
- var_setnval( CURTASK excs[ CURTASK exsc ].local_variable,
- var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
- + (bnumber) CURTASK excs[ CURTASK exsc ].for_step );
-
- /* check for completion of the loop */
-
- if ( CURTASK excs[ CURTASK exsc ].for_step > 0 ) /* if step is positive */
- {
- if ( (int) var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
- > CURTASK excs[ CURTASK exsc ].for_target )
- {
- bwb_decexec();
- #if MULTISEG_LINES
- bwb_setexec( l, l->position, CURTASK excs[ CURTASK exsc ].code );
- #else
- bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
- #endif
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_next(): end of loop" );
- bwb_debug( bwb_ebuf );
- #endif
-
- #ifdef OLD_WAY
- l->next->position = 0;
- return l->next;
- #else
- return bwb_zline( l );
- #endif
- }
- }
- else /* if step is negative */
- {
- if ( (int) var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
- < CURTASK excs[ CURTASK exsc ].for_target )
- {
- bwb_decexec();
- bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_next(): end of loop" );
- bwb_debug( bwb_ebuf );
- #endif
-
- #ifdef OLD_WAY
- l->next->position = 0;
- return l->next;
- #else
- return bwb_zline( l );
- #endif
- }
- }
-
- /* Target not reached: return to the top of the FOR loop */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_next(): resetting code to EXEC_FOR",
- l->position );
- bwb_debug( bwb_ebuf );
- #endif
-
- #if MULTISEG_LINES
- CURTASK excs[ CURTASK exsc ].for_line->position
- = CURTASK excs[ CURTASK exsc ].for_position;
- bwb_setexec( CURTASK excs[ CURTASK exsc ].for_line,
- CURTASK excs[ CURTASK exsc ].for_position, EXEC_FOR );
-
- return CURTASK excs[ CURTASK exsc ].for_line; /* Added (JBV) */
- #else
- bwb_setexec( CURTASK excs[ CURTASK exsc - 1 ].line,
- CURTASK excs[ CURTASK exsc - 1 ].position, EXEC_FOR );
-
- return CURTASK excs[ CURTASK exsc - 1 ].line; /* Relocated (JBV) */
- #endif
-
- }
-
- #if STRUCT_CMDS
-
- /***************************************************************
-
- FUNCTION: bwb_exitfor()
-
- DESCRIPTION: This function handles the BASIC EXIT
- FOR statement. This is a structured
- programming command compatible with ANSI
- BASIC. It is called from the bwb_exit()
- subroutine.
-
- SYNTAX: EXIT FOR
-
- ***************************************************************/
-
- #if ANSI_C
- struct bwb_line *
- bwb_exitfor( struct bwb_line *l )
- #else
- struct bwb_line *
- bwb_exitfor( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *next_line;
- int found;
- register int level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exitfor(): entered subroutine" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* Check the integrity of the FOR statement */
-
- found = FALSE;
- level = CURTASK exsc;
- do
- {
- if ( CURTASK excs[ level ].code == EXEC_FOR )
- {
- next_line = CURTASK excs[ CURTASK level ].wend_line;
- found = TRUE;
- }
- else
- {
- --level;
- }
- }
- while ( ( level >= 0 ) && ( found == FALSE ) );
-
- if ( found != TRUE )
- {
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_exitfor(): EXIT FOR without FOR" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return bwb_zline( l );
-
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exitfor(): level found is <%d>, current <%d>",
- level, CURTASK exsc );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* decrement below the level of the NEXT statement */
-
- while( CURTASK exsc >= level )
- {
- bwb_decexec();
- }
-
- /* set the next line in the exec stack */
-
- next_line->position = 0;
- /* bwb_setexec( next_line, 0, EXEC_NORM ); */ /* WRONG (JBV) */
- bwb_setexec( next_line, 0, CURTASK excs[ CURTASK exsc ].code ); /* JBV */
-
- return next_line;
-
- }
-
- /***************************************************************
-
- FUNCTION: find_next()
-
- DESCRIPTION: This function searches for a line containing
- a NEXT statement corresponding to a previous
- FOR statement.
-
- ***************************************************************/
-
- #if ANSI_C
- static struct bwb_line *
- find_next( struct bwb_line *l )
- #else
- static struct bwb_line *
- find_next( l )
- struct bwb_line *l;
- #endif
- {
- struct bwb_line *current;
- register int w_level;
- int position;
-
- w_level = 1;
- for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
- {
- position = 0;
- if ( current->marked != TRUE )
- {
- line_start( current->buffer, &position, &( current->lnpos ),
- &( current->lnum ),
- &( current->cmdpos ),
- &( current->cmdnum ),
- &( current->startpos ) );
- }
- current->position = current->startpos;
-
- if ( current->cmdnum > -1 )
- {
-
- if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_for )
- {
- ++w_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_next(): found FOR at line %d, level %d",
- current->number, w_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- }
- else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_next )
- {
- --w_level;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_next(): found NEXT at line %d, level %d",
- current->number, w_level );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( w_level == 0 )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in find_next(): found returning line <%d>",
- current->next->number );
- bwb_debug( bwb_ebuf );
- #endif
-
- return current->next;
- }
- }
- }
- }
-
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "FOR without NEXT" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
-
- return NULL;
-
- }
-
- #endif /* STRUCT_CMDS for EXIT FOR */
-
- /***************************************************************
-
- FUNCTION: cnd_tostep()
-
- DESCRIPTION: This function searches through the
- <buffer> beginning at point <position>
- and attempts to find positions of TO
- and STEP statements.
-
- ***************************************************************/
-
- #if ANSI_C
- static int
- cnd_tostep( char *buffer, int position, int *to, int *step )
- #else
- static int
- cnd_tostep( buffer, position, to, step )
- char *buffer;
- int position;
- int *to;
- int *step;
- #endif
- {
- int loop, t_pos, b_pos, p_word;
- char tbuf[ MAXSTRINGSIZE + 1 ];
-
- /* set then and els to FALSE initially */
-
- *to = *step = FALSE;
-
- /* loop to find words */
-
- p_word = b_pos = position;
- t_pos = 0;
- tbuf[ 0 ] = '\0';
- loop = TRUE;
- while ( loop == TRUE )
- {
-
- switch( buffer[ b_pos ] )
- {
- case '\0': /* end of string */
- case ':': /* end of line segment */
- return TRUE;
- case ' ': /* whitespace = end of word */
- case '\t':
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_tostep(): word is <%s>", tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( strncmp( tbuf, CMD_TO, (size_t) strlen( CMD_TO ) ) == 0 )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_tostep(): TO found at position <%d>.",
- p_word );
- bwb_debug( bwb_ebuf );
- #endif
-
- *to = p_word;
- }
- else if ( strncmp( tbuf, CMD_STEP, (size_t) strlen( CMD_STEP ) ) == 0 )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in cnd_tostep(): STEP found at position <%d>.",
- p_word );
- bwb_debug( bwb_ebuf );
- #endif
-
- *step = p_word;
- }
- ++b_pos;
- p_word = b_pos;
- t_pos = 0;
- tbuf[ 0 ] = '\0';
- break;
-
- default:
- if ( islower( buffer[ b_pos ] ) != FALSE )
- {
- tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );
- }
- else
- {
- tbuf[ t_pos ] = buffer[ b_pos ];
- }
- ++b_pos;
- ++t_pos;
- tbuf[ t_pos ] = '\0';
- break;
- }
-
- }
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: var_setnval()
-
- DESCRIPTION: This function sets the value of numerical
- variable v to the value of i.
-
- ***************************************************************/
-
- #if ANSI_C
- extern int
- var_setnval( struct bwb_variable *v, bnumber i )
- #else
- int
- var_setnval( v, i )
- struct bwb_variable *v;
- bnumber i;
- #endif
- {
-
- switch( v->type )
- {
- case NUMBER:
- * var_findnval( v, v->array_pos ) = i;
- break;
- default:
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in var_setnval(): variable <%s> is not a number",
- v->name );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_mismatch );
- #endif
- }
-
- /* successful assignment */
-
- return TRUE;
-
- }
-
|