home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / bwbasic / part02 < prev    next >
Encoding:
Text File  |  1993-10-29  |  70.6 KB  |  3,003 lines

  1. Newsgroups: comp.sources.misc
  2. From: tcamp@delphi.com (Ted A. Campbell)
  3. Subject: v40i053:  bwbasic - Bywater BASIC interpreter version 2.10, Part02/15
  4. Message-ID: <1993Oct29.162415.3367@sparky.sterling.com>
  5. X-Md4-Signature: 29f518cff4716c65dce6de042c946015
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Fri, 29 Oct 1993 16:24:15 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: tcamp@delphi.com (Ted A. Campbell)
  12. Posting-number: Volume 40, Issue 53
  13. Archive-name: bwbasic/part02
  14. Environment: UNIX, DOS
  15. Supersedes: bwbasic: Volume 33, Issue 37-47
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  bwbasic-2.10/bwb_cnd.c bwbasic-2.10/bwbtest/assign.bas
  22. #   bwbasic-2.10/bwx_tty.c
  23. # Wrapped by kent@sparky on Thu Oct 21 10:47:48 1993
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 2 (of 15)."'
  27. if test -f 'bwbasic-2.10/bwb_cnd.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'bwbasic-2.10/bwb_cnd.c'\"
  29. else
  30.   echo shar: Extracting \"'bwbasic-2.10/bwb_cnd.c'\" \(55621 characters\)
  31.   sed "s/^X//" >'bwbasic-2.10/bwb_cnd.c' <<'END_OF_FILE'
  32. X/***************************************************************
  33. X
  34. X        bwb_cnd.c       Conditional Expressions and Commands
  35. X                        for Bywater BASIC Interpreter
  36. X
  37. X                        Copyright (c) 1993, Ted A. Campbell
  38. X                        Bywater Software
  39. X
  40. X                        email: tcamp@delphi.com
  41. X
  42. X        Copyright and Permissions Information:
  43. X
  44. X        All U.S. and international rights are claimed by the author,
  45. X        Ted A. Campbell.
  46. X
  47. X    This software is released under the terms of the GNU General
  48. X    Public License (GPL), which is distributed with this software
  49. X    in the file "COPYING".  The GPL specifies the terms under
  50. X    which users may copy and use the software in this distribution.
  51. X
  52. X    A separate license is available for commercial distribution,
  53. X    for information on which you should contact the author.
  54. X
  55. X***************************************************************/
  56. X
  57. X#include <stdio.h>
  58. X#include <math.h>
  59. X#include <ctype.h>
  60. X
  61. X#include "bwbasic.h"
  62. X#include "bwb_mes.h"
  63. X
  64. X/* declarations of functions visible to this file only */
  65. X
  66. X#if ANSI_C
  67. Xstatic int cnd_thenels( char *buffer, int position, int *then, int *els );
  68. Xstatic int cnd_tostep( char *buffer, int position, int *to, int *step );
  69. Xstatic struct bwb_line *find_wend( struct bwb_line *l );
  70. Xstatic struct bwb_line *find_endif( struct bwb_line *l,
  71. X   struct bwb_line **else_line );
  72. Xstatic int is_endif( struct bwb_line *l );
  73. Xextern int var_setnval( struct bwb_variable *v, bnumber i );
  74. Xstatic int case_eval( struct exp_ese *expression, struct exp_ese *minval,
  75. X   struct exp_ese *maxval );
  76. Xstatic struct bwb_line *find_case( struct bwb_line *l );
  77. Xstatic struct bwb_line *find_endselect( struct bwb_line *l );
  78. Xstatic int is_endselect( struct bwb_line *l );
  79. Xstatic struct bwb_line *bwb_caseif( struct bwb_line *l );
  80. X
  81. X#if STRUCT_CMDS
  82. Xstatic struct bwb_line *find_next( struct bwb_line *l );
  83. X#endif
  84. X
  85. X#else
  86. Xstatic int cnd_thenels();
  87. Xstatic int cnd_tostep();
  88. Xstatic struct bwb_line *find_wend();
  89. Xstatic struct bwb_line *find_endif();
  90. Xstatic int is_endif();
  91. Xextern int var_setnval();
  92. Xstatic int case_eval();
  93. Xstatic struct bwb_line *find_case();
  94. Xstatic struct bwb_line *find_endselect();
  95. Xstatic int is_endselect();
  96. Xstatic struct bwb_line *bwb_caseif();
  97. X
  98. X#if STRUCT_CMDS
  99. Xstatic struct bwb_line *find_next();
  100. X#endif
  101. X
  102. X#endif                          /* ANSI_C for prototypes */
  103. X
  104. X/***    IF-THEN-ELSE ***/
  105. X
  106. X/***************************************************************
  107. X
  108. X        FUNCTION:       bwb_if()
  109. X
  110. X        DESCRIPTION:    This function handles the BASIC IF
  111. X                        statement.
  112. X
  113. X       SYNTAX:        IF expression THEN [statement [ELSE statement]]
  114. X
  115. X***************************************************************/
  116. X
  117. X#if ANSI_C
  118. Xstruct bwb_line *
  119. Xbwb_if( struct bwb_line *l )
  120. X#else
  121. Xstruct bwb_line *
  122. Xbwb_if( l )
  123. X   struct bwb_line *l;
  124. X#endif
  125. X   {
  126. X   int then, els;
  127. X   struct exp_ese *e;
  128. X   int glnumber;
  129. X   int tpos;
  130. X   static char tbuf[ MAXSTRINGSIZE + 1 ];
  131. X   static struct bwb_line gline;
  132. X#if STRUCT_CMDS
  133. X   static struct bwb_line *else_line;
  134. X   static struct bwb_line *endif_line;
  135. X#endif
  136. X
  137. X#if INTENSIVE_DEBUG
  138. X   sprintf( bwb_ebuf, "in bwb_if(): entry, line <%d> buffer <%s>",
  139. X      l->number, &( l->buffer[ l->position ] ) );
  140. X   bwb_debug( bwb_ebuf );
  141. X   getchar();
  142. X#endif
  143. X
  144. X#if INTENSIVE_DEBUG
  145. X   if ( l == &gline )
  146. X      {
  147. X      sprintf( bwb_ebuf, "in bwb_if(): recursive call, l = &gline" );
  148. X      bwb_debug( bwb_ebuf );
  149. X      }
  150. X#endif
  151. X
  152. X   /* Call bwb_exp() to evaluate the condition. This should return
  153. X      with position set to the "THEN" statement */
  154. X
  155. X   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  156. X
  157. X#if INTENSIVE_DEBUG
  158. X   sprintf( bwb_ebuf, "in bwb_if(): line <%d> condition returns <%d>",
  159. X      l->number, exp_getnval( e ) );
  160. X   bwb_debug( bwb_ebuf );
  161. X#endif
  162. X
  163. X   /* test for "THEN" and "ELSE" statements */
  164. X
  165. X   cnd_thenels( l->buffer, l->position, &then, &els );
  166. X
  167. X#if INTENSIVE_DEBUG
  168. X   sprintf( bwb_ebuf, "in bwb_if(): return from cnd_thenelse, line is <%s>",
  169. X      l->buffer );
  170. X   bwb_debug( bwb_ebuf );
  171. X#endif
  172. X
  173. X   /* test for multiline IF statement: this presupposes ANSI-compliant
  174. X      structured BASIC */
  175. X
  176. X#if STRUCT_CMDS
  177. X   tpos = then + strlen( CMD_THEN ) + 1;
  178. X   if ( is_eol( l->buffer, &tpos ) == TRUE )
  179. X      {
  180. X
  181. X#if INTENSIVE_DEBUG
  182. X      sprintf( bwb_ebuf, "in bwb_if(): found multi-line IF statement, line <%d>",
  183. X         l->number );
  184. X      bwb_debug( bwb_ebuf );
  185. X#endif
  186. X
  187. X      /* find END IF and possibly ELSE[IF] line(s) */
  188. X
  189. X      else_line = NULL;
  190. X      endif_line = find_endif( l, &else_line );
  191. X
  192. X      /* evaluate the expression */
  193. X
  194. X      if ( (int) exp_getnval( e ) != FALSE )
  195. X         {
  196. X         bwb_incexec();
  197. X         bwb_setexec( l->next, 0, EXEC_IFTRUE );
  198. X
  199. X#if MULTISEG_LINES
  200. X         adv_eos( l->buffer, &( l->position ));
  201. X#endif
  202. X         return bwb_zline( l );
  203. X         }
  204. X
  205. X      else if ( else_line != NULL )
  206. X         {
  207. X         bwb_incexec();
  208. X         bwb_setexec( else_line, 0, EXEC_IFFALSE );
  209. X         else_line->position = 0;
  210. X         return else_line;
  211. X         }
  212. X      else
  213. X         {
  214. X         bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );
  215. X         endif_line->position = 0;
  216. X         return endif_line;
  217. X         }
  218. X      }
  219. X
  220. X#endif            /* STRUCT_CMDS for Multi-line IF...THEN */
  221. X
  222. X   /* Not a Multi-line IF...THEN: test for THEN line-number */
  223. X
  224. X#if INTENSIVE_DEBUG
  225. X   sprintf( bwb_ebuf, "in bwb_if(): not multi-line; line is <%s>",
  226. X      l->buffer );
  227. X   bwb_debug( bwb_ebuf );
  228. X#endif
  229. X
  230. X   /* evaluate and execute */
  231. X
  232. X   if ( (int) exp_getnval( e ) != FALSE )
  233. X      {
  234. X
  235. X#if INTENSIVE_DEBUG
  236. X      sprintf( bwb_ebuf, "in bwb_if(): expression is TRUE" );
  237. X      bwb_debug( bwb_ebuf );
  238. X#endif
  239. X
  240. X      if ( then == FALSE )
  241. X         {
  242. X#if PROG_ERRORS
  243. X     sprintf( bwb_ebuf, "in bwb_if(): IF without THEN" );
  244. X         bwb_error( bwb_ebuf );
  245. X#else
  246. X         bwb_error( err_syntax );
  247. X#endif
  248. X         }
  249. X      else
  250. X         {
  251. X
  252. X     /* check for THEN followed by literal line number */
  253. X
  254. X     tpos = then + strlen( CMD_THEN ) + 1;
  255. X     adv_element( l->buffer, &tpos, tbuf );
  256. X
  257. X     if ( isdigit( tbuf[ 0 ] ) != 0 )
  258. X        {
  259. X
  260. X        glnumber = atoi( tbuf );
  261. X
  262. X#if INTENSIVE_DEBUG
  263. X        sprintf( bwb_ebuf, "Detected THEN followed by line number <%d>",
  264. X           glnumber );
  265. X        bwb_debug( bwb_ebuf );
  266. X#endif
  267. X
  268. X        sprintf( tbuf, "%s %d", CMD_GOTO, glnumber );
  269. X        gline.buffer = tbuf;
  270. X        gline.marked = FALSE;
  271. X        gline.position = 0;
  272. X        gline.next = l->next;
  273. X        bwb_setexec( &gline, 0, CURTASK excs[ CURTASK exsc ].code );
  274. X        return &gline;
  275. X        }
  276. X
  277. X     /* form is not THEN followed by line number */
  278. X
  279. X     else
  280. X        {
  281. X        bwb_setexec( l, then, CURTASK excs[ CURTASK exsc ].code );
  282. X        l->position = then + strlen( CMD_THEN ) + 1;
  283. X        }
  284. X
  285. X     return l;
  286. X     }
  287. X      }
  288. X   else
  289. X      {
  290. X
  291. X#if INTENSIVE_DEBUG
  292. X      sprintf( bwb_ebuf, "in bwb_if(): expression is FALSE" );
  293. X      bwb_debug( bwb_ebuf );
  294. X#endif
  295. X
  296. X      if ( els != FALSE )
  297. X         {
  298. X         l->position = els + strlen( CMD_ELSE ) + 1;
  299. X         bwb_setexec( l, els, EXEC_NORM );
  300. X     return l;
  301. X     }
  302. X      }
  303. X
  304. X   /* if neither then nor else were found, advance to next line */
  305. X   /* DO NOT advance to next segment (only if TRUE should we do that */
  306. X
  307. X   l->next->position = 0;
  308. X   return l->next;
  309. X
  310. X   }
  311. X
  312. X/***************************************************************
  313. X
  314. X        FUNCTION:       cnd_thenelse()
  315. X
  316. X        DESCRIPTION:    This function searches through the
  317. X                        <buffer> beginning at point <position>
  318. X                        and attempts to find positions of THEN
  319. X                        and ELSE statements.
  320. X
  321. X***************************************************************/
  322. X
  323. X#if ANSI_C
  324. Xstatic int
  325. Xcnd_thenels( char *buffer, int position, int *then, int *els )
  326. X#else
  327. Xstatic int
  328. Xcnd_thenels( buffer, position, then, els )
  329. X   char *buffer;
  330. X   int position;
  331. X   int *then;
  332. X   int *els;
  333. X#endif
  334. X   {
  335. X   int loop, t_pos, b_pos, p_word;
  336. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  337. X
  338. X#if INTENSIVE_DEBUG
  339. X   sprintf( bwb_ebuf, "in cnd_thenels(): entry, line is <%s>",
  340. X      &( buffer[ position ] ) );
  341. X   bwb_debug( bwb_ebuf );
  342. X#endif
  343. X
  344. X   /* set then and els to 0 initially */
  345. X
  346. X   *then = *els = 0;
  347. X
  348. X   /* loop to find words */
  349. X
  350. X   p_word = b_pos = position;
  351. X   t_pos = 0;
  352. X   tbuf[ 0 ] = '\0';
  353. X   loop = TRUE;
  354. X   while( loop == TRUE )
  355. X      {
  356. X
  357. X      switch( buffer[ b_pos ] )
  358. X         {
  359. X         case '\0':                     /* end of string */
  360. X         case ' ':                      /* whitespace = end of word */
  361. X         case '\t':
  362. X
  363. X#if INTENSIVE_DEBUG
  364. X            sprintf( bwb_ebuf, "in cnd_thenels(): word is <%s>", tbuf );
  365. X            bwb_debug( bwb_ebuf );
  366. X#endif
  367. X
  368. X            if ( strncmp( tbuf, CMD_THEN, (size_t) strlen( CMD_THEN ) ) == 0 )
  369. X               {
  370. X
  371. X#if INTENSIVE_DEBUG
  372. X               sprintf( bwb_ebuf, "in cnd_thenels(): THEN found at position <%d>.",
  373. X                  p_word );
  374. X               bwb_debug( bwb_ebuf );
  375. X               sprintf( bwb_ebuf, "in cnd_thenelse(): after THEN, line is <%s>", buffer );
  376. X               bwb_debug( bwb_ebuf );
  377. X#endif
  378. X
  379. X               *then = p_word;
  380. X               }
  381. X            else if ( strncmp( tbuf, CMD_ELSE, (size_t) strlen( CMD_ELSE ) ) == 0 )
  382. X               {
  383. X
  384. X#if INTENSIVE_DEBUG
  385. X               sprintf( bwb_ebuf, "in cnd_thenels(): ELSE found at position <%d>.",
  386. X                  p_word );
  387. X               bwb_debug( bwb_ebuf );
  388. X               sprintf( bwb_ebuf, "in cnd_thenelse(): after ELSE, line is <%s>", buffer );
  389. X               bwb_debug( bwb_ebuf );
  390. X#endif
  391. X
  392. X               *els = p_word;
  393. X               }
  394. X
  395. X            /* check for end of the line */
  396. X
  397. X            if ( buffer[ b_pos ] == '\0' )
  398. X               {
  399. X#if INTENSIVE_DEBUG
  400. X               sprintf( bwb_ebuf, "in cnd_thenels(): return: end of string" );
  401. X               bwb_debug( bwb_ebuf );
  402. X#endif
  403. X               return TRUE;
  404. X               }
  405. X
  406. X            ++b_pos;
  407. X            p_word = b_pos;
  408. X            t_pos = 0;
  409. X            tbuf[ 0 ] = '\0';
  410. X            break;
  411. X
  412. X         default:
  413. X            if ( islower( buffer[ b_pos ] ) != FALSE )
  414. X               {
  415. X               tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );
  416. X               }
  417. X            else
  418. X               {
  419. X               tbuf[ t_pos ] = buffer[ b_pos ];
  420. X               }
  421. X            ++b_pos;
  422. X            ++t_pos;
  423. X            tbuf[ t_pos ] = '\0';
  424. X            break;
  425. X         }
  426. X
  427. X      }
  428. X
  429. X#if INTENSIVE_DEBUG
  430. X   sprintf( bwb_ebuf, "in cnd_thenelse(): exit, line is <%s>", buffer );
  431. X   bwb_debug( bwb_ebuf );
  432. X#endif
  433. X
  434. X   return FALSE;
  435. X
  436. X   }
  437. X
  438. X#if STRUCT_CMDS
  439. X
  440. X/***************************************************************
  441. X
  442. X        FUNCTION:       bwb_else()
  443. X
  444. X        DESCRIPTION:    This function handles the BASIC ELSE
  445. X                        statement.
  446. X
  447. X       SYNTAX:        ELSE
  448. X
  449. X***************************************************************/
  450. X
  451. X#if ANSI_C
  452. Xstruct bwb_line *
  453. Xbwb_else( struct bwb_line *l )
  454. X#else
  455. Xstruct bwb_line *
  456. Xbwb_else( l )
  457. X   struct bwb_line *l;
  458. X#endif
  459. X   {
  460. X   struct bwb_line *endif_line;
  461. X   struct bwb_line *else_line;
  462. X
  463. X#if INTENSIVE_DEBUG
  464. X   sprintf( bwb_ebuf, "in bwb_else(): entered function" );
  465. X   bwb_debug( bwb_ebuf );
  466. X#endif
  467. X
  468. X   /* If the code is EXEC_NORM, then this is a continuation of a single-
  469. X      line IF...THEN...ELSE... statement and we should return */
  470. X
  471. X   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_NORM )
  472. X      {
  473. X
  474. X#if INTENSIVE_DEBUG
  475. X      sprintf( bwb_ebuf, "in bwb_else(): detected EXEC_NORM" );
  476. X      bwb_debug( bwb_ebuf );
  477. X#endif
  478. X
  479. X      return bwb_zline( l );
  480. X      }
  481. X
  482. X   endif_line = find_endif( l, &else_line );
  483. X
  484. X   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )
  485. X      {
  486. X      endif_line->position = 0;
  487. X      return endif_line;
  488. X      }
  489. X   else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )
  490. X      {
  491. X
  492. X      return bwb_zline( l );
  493. X      }
  494. X
  495. X#if PROG_ERRORS
  496. X   sprintf( bwb_ebuf, "in bwb_else(): ELSE without IF" );
  497. X   bwb_error( bwb_ebuf );
  498. X#else
  499. X   bwb_error( err_syntax );
  500. X#endif
  501. X
  502. X
  503. X   return bwb_zline( l );
  504. X   }
  505. X
  506. X/***************************************************************
  507. X
  508. X        FUNCTION:       bwb_elseif()
  509. X
  510. X        DESCRIPTION:    This function handles the BASIC ELSEIF
  511. X                        statement.
  512. X
  513. X    SYNTAX:        ELSEIF
  514. X
  515. X***************************************************************/
  516. X
  517. X#if ANSI_C
  518. Xstruct bwb_line *
  519. Xbwb_elseif( struct bwb_line *l )
  520. X#else
  521. Xstruct bwb_line *
  522. Xbwb_elseif( l )
  523. X   struct bwb_line *l;
  524. X#endif
  525. X   {
  526. X   struct bwb_line *endif_line;
  527. X   struct bwb_line *else_line;
  528. X   struct exp_ese *e;
  529. X
  530. X#if INTENSIVE_DEBUG
  531. X   sprintf( bwb_ebuf, "in bwb_elseif(): entered function" );
  532. X   bwb_debug( bwb_ebuf );
  533. X#endif
  534. X
  535. X   else_line = NULL;
  536. X   endif_line = find_endif( l, &else_line );
  537. X
  538. X   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )
  539. X      {
  540. X      endif_line->position = 0;
  541. X      return endif_line;
  542. X      }
  543. X
  544. X   else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )
  545. X      {
  546. X
  547. X      /* Call bwb_exp() to evaluate the condition. This should return
  548. X         with position set to the "THEN" statement */
  549. X
  550. X      e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  551. X
  552. X      if ( (int) exp_getnval( e ) == TRUE )
  553. X         {
  554. X
  555. X         /* ELSEIF condition is TRUE: proceed to the next line */
  556. X
  557. X         CURTASK excs[ CURTASK exsc ].code = EXEC_IFTRUE;
  558. X
  559. X#if MULTISEG_LINES
  560. X         adv_eos( l->buffer, &( l->position ));
  561. X#endif
  562. X         return bwb_zline( l );
  563. X
  564. X         }
  565. X
  566. X      /* ELSEIF condition FALSE: proceed to next ELSE line if there is one */
  567. X
  568. X      else if ( else_line != NULL )
  569. X         {
  570. X         bwb_setexec( else_line, 0, EXEC_IFFALSE );
  571. X         else_line->position = 0;
  572. X         return else_line;
  573. X         }
  574. X
  575. X      /* ELSEIF condition is FALSE and no more ELSExx lines: proceed to END IF */
  576. X
  577. X      else
  578. X         {
  579. X         bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );
  580. X         endif_line->position = 0;
  581. X         return endif_line;
  582. X         }
  583. X
  584. X      }
  585. X
  586. X#if PROG_ERRORS
  587. X   sprintf( bwb_ebuf, "in bwb_elseif(): ELSEIF without IF" );
  588. X   bwb_error( bwb_ebuf );
  589. X#else
  590. X   bwb_error( err_syntax );
  591. X#endif
  592. X
  593. X
  594. X#if MULTISEG_LINES
  595. X   adv_eos( l->buffer, &( l->position ));
  596. X#endif
  597. X   return bwb_zline( l );
  598. X
  599. X   }
  600. X
  601. X/***************************************************************
  602. X
  603. X        FUNCTION:       bwb_endif()
  604. X
  605. X        DESCRIPTION:    This function handles the BASIC END IF
  606. X                        statement.
  607. X
  608. X    SYNTAX:        END IF
  609. X
  610. X***************************************************************/
  611. X
  612. X#if ANSI_C
  613. Xstruct bwb_line *
  614. Xbwb_endif( struct bwb_line *l )
  615. X#else
  616. Xstruct bwb_line *
  617. Xbwb_endif( l )
  618. X   struct bwb_line *l;
  619. X#endif
  620. X   {
  621. X
  622. X#if INTENSIVE_DEBUG
  623. X   sprintf( bwb_ebuf, "in bwb_endif(): entered function" );
  624. X   bwb_debug( bwb_ebuf );
  625. X#endif
  626. X
  627. X   if (( CURTASK excs[ CURTASK exsc ].code != EXEC_IFTRUE )
  628. X      && ( CURTASK excs[ CURTASK exsc ].code != EXEC_IFFALSE ))
  629. X      {
  630. X#if PROG_ERRORS
  631. X      sprintf( bwb_ebuf, "in bwb_endif(): END IF without IF" );
  632. X      bwb_error( bwb_ebuf );
  633. X#else
  634. X      bwb_error( err_syntax );
  635. X#endif
  636. X      }
  637. X
  638. X   bwb_decexec();
  639. X
  640. X
  641. X#if MULTISEG_LINES
  642. X   adv_eos( l->buffer, &( l->position ));
  643. X#endif
  644. X   return bwb_zline( l );
  645. X   }
  646. X
  647. X/***************************************************************
  648. X
  649. X        FUNCTION:       find_endif()
  650. X
  651. X        DESCRIPTION:    This C function attempts to find an
  652. X            END IF statement.
  653. X
  654. X***************************************************************/
  655. X
  656. X#if ANSI_C
  657. Xstatic struct bwb_line *
  658. Xfind_endif( struct bwb_line *l, struct bwb_line **else_line )
  659. X#else
  660. Xstatic struct bwb_line *
  661. Xfind_endif( l, else_line )
  662. X   struct bwb_line *l;
  663. X   struct bwb_line **else_line;
  664. X#endif
  665. X   {
  666. X   struct bwb_line *current;
  667. X   register int i_level;
  668. X   int position;
  669. X
  670. X   *else_line = NULL;
  671. X   i_level = 1;
  672. X   for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  673. X      {
  674. X      position = 0;
  675. X      if ( current->marked != TRUE )
  676. X         {
  677. X         line_start( current->buffer, &position, &( current->lnpos ),
  678. X            &( current->lnum ),
  679. X            &( current->cmdpos ),
  680. X            &( current->cmdnum ),
  681. X            &( current->startpos ) );
  682. X         }
  683. X      current->position = current->startpos;
  684. X
  685. X      if ( current->cmdnum > -1 )
  686. X         {
  687. X
  688. X         if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_if )
  689. X            {
  690. X            ++i_level;
  691. X
  692. X#if INTENSIVE_DEBUG
  693. X            sprintf( bwb_ebuf, "in find_endif(): found IF at line %d, level %d",
  694. X               current->number, i_level );
  695. X            bwb_debug( bwb_ebuf );
  696. X#endif
  697. X
  698. X            }
  699. X         else if ( is_endif( current ) == TRUE )
  700. X            {
  701. X            --i_level;
  702. X
  703. X#if INTENSIVE_DEBUG
  704. X            sprintf( bwb_ebuf, "in find_endif(): found END IF at line %d, level %d",
  705. X               current->number, i_level );
  706. X            bwb_debug( bwb_ebuf );
  707. X#endif
  708. X
  709. X            if ( i_level == 0 )
  710. X               {
  711. X               return current;
  712. X               }
  713. X            }
  714. X
  715. X         else if ( ( bwb_cmdtable[ current->cmdnum ].vector == bwb_else )
  716. X            || ( bwb_cmdtable[ current->cmdnum ].vector == bwb_elseif ))
  717. X            {
  718. X
  719. X            /* we must only report the first ELSE or ELSE IF we encounter
  720. X               at level 1 */
  721. X
  722. X            if ( ( i_level == 1 ) && ( *else_line == NULL ))
  723. X               {
  724. X               *else_line = current;
  725. X               }
  726. X
  727. X            }
  728. X         }
  729. X      }
  730. X
  731. X#if PROG_ERRORS
  732. X   sprintf( bwb_ebuf, "Multiline IF without END IF" );
  733. X   bwb_error( bwb_ebuf );
  734. X#else
  735. X   bwb_error( err_syntax  );
  736. X#endif
  737. X
  738. X   return NULL;
  739. X
  740. X   }
  741. X
  742. X/***************************************************************
  743. X
  744. X    FUNCTION:       is_endif()
  745. X
  746. X    DESCRIPTION:    This C function attempts to determine if
  747. X            a given line contains an END IF statement.
  748. X
  749. X***************************************************************/
  750. X
  751. X#if ANSI_C
  752. Xstatic int
  753. Xis_endif( struct bwb_line *l )
  754. X#else
  755. Xstatic int
  756. Xis_endif( l )
  757. X   struct bwb_line *l;
  758. X#endif
  759. X   {
  760. X   int position;
  761. X   char tbuf[ MAXVARNAMESIZE + 1];
  762. X
  763. X   if ( bwb_cmdtable[ l->cmdnum ].vector != bwb_xend )
  764. X      {
  765. X      return FALSE;
  766. X      }
  767. X
  768. X   position = l->startpos;
  769. X   adv_ws( l->buffer, &position );
  770. X   adv_element( l->buffer, &position, tbuf );
  771. X   bwb_strtoupper( tbuf );
  772. X
  773. X   if ( strcmp( tbuf, "IF" ) == 0 )
  774. X      {
  775. X      return TRUE;
  776. X      }
  777. X
  778. X   return FALSE;
  779. X
  780. X   }
  781. X
  782. X/***************************************************************
  783. X
  784. X        FUNCTION:       bwb_select()
  785. X
  786. X        DESCRIPTION:    This C function handles the BASIC SELECT
  787. X                        statement.
  788. X
  789. X    SYNTAX:        SELECT CASE expression
  790. X
  791. X***************************************************************/
  792. X
  793. X#if ANSI_C
  794. Xstruct bwb_line *
  795. Xbwb_select( struct bwb_line *l )
  796. X#else
  797. Xstruct bwb_line *
  798. Xbwb_select( l )
  799. X   struct bwb_line *l;
  800. X#endif
  801. X   {
  802. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  803. X   struct exp_ese *e;
  804. X
  805. X#if INTENSIVE_DEBUG
  806. X   sprintf( bwb_ebuf, "in bwb_select(): entered function" );
  807. X   bwb_debug( bwb_ebuf );
  808. X#endif
  809. X
  810. X   /* first element should be "CASE" */
  811. X
  812. X   adv_element( l->buffer, &( l->position ), tbuf );
  813. X   bwb_strtoupper( tbuf );
  814. X   if ( strcmp( tbuf, "CASE" ) != 0 )
  815. X      {
  816. X#if PROG_ERRORS
  817. X      sprintf( bwb_ebuf, "SELECT without CASE" );
  818. X      bwb_error( bwb_ebuf );
  819. X#else
  820. X      bwb_error( err_syntax );
  821. X
  822. X      return bwb_zline( l );
  823. X#endif
  824. X      }
  825. X
  826. X   /* increment the level and set to EXEC_SELFALSE */
  827. X
  828. X   bwb_incexec();
  829. X   CURTASK excs[ CURTASK exsc ].code = EXEC_SELFALSE;
  830. X
  831. X   /* evaluate the expression at this level */
  832. X
  833. X   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  834. X
  835. X#if OLDWAY
  836. X   memcpy( &( CURTASK excs[ CURTASK exsc ].expression ), e,
  837. X      sizeof( struct exp_ese ) );
  838. X#endif
  839. X
  840. X   if ( e->type == STRING )
  841. X      {
  842. X      CURTASK excs[ CURTASK exsc ].expression.type = STRING;
  843. X      str_btob( &( CURTASK excs[ CURTASK exsc ].expression.sval ),
  844. X     &( e->sval ) );
  845. X      }
  846. X   else
  847. X      {
  848. X      CURTASK excs[ CURTASK exsc ].expression.type = NUMBER;
  849. X      CURTASK excs[ CURTASK exsc ].expression.nval
  850. X     = exp_getnval( e );
  851. X      }
  852. X
  853. X   /* return */
  854. X
  855. X#if MULTISEG_LINES
  856. X   adv_eos( l->buffer, &( l->position ));
  857. X#endif
  858. X
  859. X   return bwb_zline( l );
  860. X   }
  861. X
  862. X/***************************************************************
  863. X
  864. X        FUNCTION:       bwb_case()
  865. X
  866. X        DESCRIPTION:    This C function handles the BASIC CASE
  867. X                        statement.
  868. X
  869. X    SYNTAX:        CASE constant | IF partial-expression | ELSE
  870. X
  871. X***************************************************************/
  872. X
  873. X#if ANSI_C
  874. Xstruct bwb_line *
  875. Xbwb_case( struct bwb_line *l )
  876. X#else
  877. Xstruct bwb_line *
  878. Xbwb_case( l )
  879. X   struct bwb_line *l;
  880. X#endif
  881. X   {
  882. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  883. X   int oldpos;
  884. X   struct exp_ese minvalue;
  885. X   struct exp_ese *maxval, *minval;
  886. X   struct bwb_line *retline;
  887. X   char cbuf1[ MAXSTRINGSIZE + 1 ];
  888. X   char cbuf2[ MAXSTRINGSIZE + 1 ];
  889. X
  890. X#if INTENSIVE_DEBUG
  891. X   sprintf( bwb_ebuf, "in bwb_case(): entered function" );
  892. X   bwb_debug( bwb_ebuf );
  893. X#endif
  894. X
  895. X   /* if code is EXEC_SELTRUE, then we should jump to the end */
  896. X
  897. X   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_SELTRUE )
  898. X      {
  899. X#if INTENSIVE_DEBUG
  900. X      sprintf( bwb_ebuf, "in bwb_case(): exit EXEC_SELTRUE" );
  901. X      bwb_debug( bwb_ebuf );
  902. X#endif
  903. X      retline = find_endselect( l );
  904. X      retline->position = 0;
  905. X      return retline;
  906. X      }
  907. X
  908. X   /* read first element */
  909. X
  910. X   oldpos = l->position;
  911. X   adv_element( l->buffer, &( l->position ), tbuf );
  912. X   bwb_strtoupper( tbuf );
  913. X
  914. X   /* check for CASE IF */
  915. X
  916. X   if ( strcmp( tbuf, CMD_IF ) == 0 )
  917. X      {
  918. X      return bwb_caseif( l );
  919. X      }
  920. X
  921. X   /* check for CASE ELSE: if true, simply proceed to the next line,
  922. X      because other options should have been detected by now */
  923. X
  924. X   else if ( strcmp( tbuf, CMD_ELSE ) == 0 )
  925. X      {
  926. X#if INTENSIVE_DEBUG
  927. X      sprintf( bwb_ebuf, "in bwb_case(): execute CASE ELSE" );
  928. X      bwb_debug( bwb_ebuf );
  929. X#endif
  930. X
  931. X      return bwb_zline( l );
  932. X      }
  933. X
  934. X   /* neither CASE ELSE nor CASE IF; presume constant here for min value */
  935. X
  936. X   l->position = oldpos;
  937. X   minval = bwb_exp( l->buffer, FALSE, &( l->position ));
  938. X   memcpy( &minvalue, minval, sizeof( struct exp_ese ) );
  939. X   maxval = minval = &minvalue;
  940. X
  941. X   /* check for string value */
  942. X
  943. X   if ( minvalue.type == STRING )
  944. X      {
  945. X
  946. X      str_btoc( cbuf1, &( CURTASK excs[ CURTASK exsc ].expression.sval ) );
  947. X      str_btoc( cbuf2, &( minvalue.sval ) );
  948. X
  949. X#if INTENSIVE_DEBUG
  950. X      sprintf( bwb_ebuf, "in bwb_case(): compare strings <%s> and <%s>",
  951. X     cbuf1, cbuf2 );
  952. X      bwb_debug( bwb_ebuf );
  953. X#endif
  954. X
  955. X      if ( strncmp( cbuf1, cbuf2, MAXSTRINGSIZE ) == 0 )
  956. X     {
  957. X#if INTENSIVE_DEBUG
  958. X     sprintf( bwb_ebuf, "in bwb_case(): string comparison returns TRUE" );
  959. X     bwb_debug( bwb_ebuf );
  960. X#endif
  961. X     CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
  962. X
  963. X#if MULTISEG_LINES
  964. X         adv_eos( l->buffer, &( l->position ));
  965. X#endif
  966. X     return bwb_zline( l );
  967. X     }
  968. X
  969. X      else
  970. X     {
  971. X#if INTENSIVE_DEBUG
  972. X     sprintf( bwb_ebuf, "in bwb_case(): string comparison returns FALSE" );
  973. X     bwb_debug( bwb_ebuf );
  974. X#endif
  975. X     retline = find_case( l );
  976. X     retline->position = 0;
  977. X     return retline;
  978. X     }
  979. X
  980. X      }
  981. X
  982. X   /* not a string; advance */
  983. X
  984. X   adv_ws( l->buffer, &( l->position ));
  985. X
  986. X   /* check for TO */
  987. X
  988. X   if ( is_eol( l->buffer, &( l->position )) != TRUE )
  989. X      {
  990. X
  991. X      /* find the TO statement */
  992. X
  993. X      adv_element( l->buffer, &( l->position ), tbuf );
  994. X      bwb_strtoupper( tbuf );
  995. X      if ( strcmp( tbuf, CMD_TO ) != 0 )
  996. X         {
  997. X#if PROG_ERRORS
  998. X         sprintf( bwb_ebuf, "CASE has inexplicable code following expression" );
  999. X         bwb_error( bwb_ebuf );
  1000. X#else
  1001. X         bwb_error( err_syntax );
  1002. X
  1003. X#if MULTISEG_LINES
  1004. X         adv_eos( l->buffer, &( l->position ));
  1005. X#endif
  1006. X         return bwb_zline( l );
  1007. X#endif
  1008. X         }
  1009. X
  1010. X      /* now evaluate the MAX expression */
  1011. X
  1012. X      maxval = bwb_exp( l->buffer, FALSE, &( l->position ));
  1013. X
  1014. X      }
  1015. X
  1016. X   /* evaluate the expression */
  1017. X
  1018. X   if ( case_eval( &( CURTASK excs[ CURTASK exsc ].expression ),
  1019. X      minval, maxval ) == TRUE )
  1020. X      {
  1021. X#if INTENSIVE_DEBUG
  1022. X      sprintf( bwb_ebuf, "in bwb_case(): evaluation returns TRUE" );
  1023. X      bwb_debug( bwb_ebuf );
  1024. X#endif
  1025. X      CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
  1026. X
  1027. X#if MULTISEG_LINES
  1028. X      adv_eos( l->buffer, &( l->position ));
  1029. X#endif
  1030. X      return bwb_zline( l );
  1031. X      }
  1032. X
  1033. X   /* evaluation returns a FALSE value; find next CASE or END SELECT statement */
  1034. X
  1035. X   else
  1036. X      {
  1037. X#if INTENSIVE_DEBUGb
  1038. X      sprintf( bwb_ebuf, "in bwb_case(): evaluation returns FALSE" );
  1039. X      bwb_debug( bwb_ebuf );
  1040. X#endif
  1041. X      retline = find_case( l );
  1042. X      retline->position = 0;
  1043. X      return retline;
  1044. X      }
  1045. X
  1046. X   }
  1047. X
  1048. X/***************************************************************
  1049. X
  1050. X        FUNCTION:       bwb_caseif()
  1051. X
  1052. X        DESCRIPTION:    This C function handles the BASIC CASE IF
  1053. X                        statement.
  1054. X
  1055. X***************************************************************/
  1056. X
  1057. X#if ANSI_C
  1058. Xstatic struct bwb_line *
  1059. Xbwb_caseif( struct bwb_line *l )
  1060. X#else
  1061. Xstatic struct bwb_line *
  1062. Xbwb_caseif( l )
  1063. X   struct bwb_line *l;
  1064. X#endif
  1065. X   {
  1066. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  1067. X   int position;
  1068. X   struct exp_ese *r;
  1069. X   struct bwb_line *retline;
  1070. X
  1071. X   if ( CURTASK excs[ CURTASK exsc ].expression.type == NUMBER )
  1072. X      {
  1073. X      sprintf( tbuf, "%f %s",
  1074. X         (float) CURTASK excs[ CURTASK exsc ].expression.nval,
  1075. X         &( l->buffer[ l->position ] ) );
  1076. X      }
  1077. X   else
  1078. X      {
  1079. X      bwb_error( err_mismatch );
  1080. X#if MULTISEG_LINES
  1081. X      adv_eos( l->buffer, &( l->position ));
  1082. X#endif
  1083. X      return bwb_zline( l );
  1084. X      }
  1085. X
  1086. X   position = 0;
  1087. X   r = bwb_exp( tbuf, FALSE, &position );
  1088. X
  1089. X   if ( r->nval == (bnumber) TRUE )
  1090. X      {
  1091. X      CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
  1092. X
  1093. X#if MULTISEG_LINES
  1094. X      adv_eos( l->buffer, &( l->position ));
  1095. X#endif
  1096. X      return bwb_zline( l );
  1097. X      }
  1098. X   else
  1099. X      {
  1100. X      retline = find_case( l );
  1101. X      retline->position = 0;
  1102. X      return retline;
  1103. X      }
  1104. X
  1105. X   }
  1106. X
  1107. X/***************************************************************
  1108. X
  1109. X        FUNCTION:       case_eval()
  1110. X
  1111. X        DESCRIPTION:    This function evaluates a case statement
  1112. X            by comparing minimum and maximum values
  1113. X            with a set expression. It returns either
  1114. X            TRUE or FALSE
  1115. X
  1116. X***************************************************************/
  1117. X
  1118. X#if ANSI_C
  1119. Xstatic int
  1120. Xcase_eval( struct exp_ese *expression, struct exp_ese *minval,
  1121. X   struct exp_ese *maxval )
  1122. X#else
  1123. Xstatic int
  1124. Xcase_eval( expression, minval, maxval )
  1125. X   struct exp_ese *expression;
  1126. X   struct exp_ese *minval;
  1127. X   struct exp_ese *maxval;
  1128. X#endif
  1129. X   {
  1130. X
  1131. X   /* string value */
  1132. X
  1133. X   if ( expression->type == STRING )
  1134. X      {
  1135. X      bwb_error( err_mismatch );
  1136. X      return FALSE;
  1137. X      }
  1138. X
  1139. X   /* numerical value */
  1140. X
  1141. X#if INTENSIVE_DEBUG
  1142. X   sprintf( bwb_ebuf, "in case_eval(): n <%f> min <%f> max <%f>",
  1143. X      (float) expression->nval,
  1144. X      (float) minval->nval,
  1145. X      (float) maxval->nval );
  1146. X   bwb_debug( bwb_ebuf );
  1147. X#endif
  1148. X
  1149. X   if (  ( expression->nval >= minval->nval )
  1150. X      && ( expression->nval <= maxval->nval ))
  1151. X      {
  1152. X      return TRUE;
  1153. X      }
  1154. X
  1155. X   return FALSE;
  1156. X
  1157. X   }
  1158. X
  1159. X/***************************************************************
  1160. X
  1161. X        FUNCTION:       find_case()
  1162. X
  1163. X        DESCRIPTION:    This function searches for a line containing
  1164. X                        a CASE statement corresponding to a previous
  1165. X                        SELECT CASE statement.
  1166. X
  1167. X***************************************************************/
  1168. X
  1169. X#if ANSI_C
  1170. Xstatic struct bwb_line *
  1171. Xfind_case( struct bwb_line *l )
  1172. X#else
  1173. Xstatic struct bwb_line *
  1174. Xfind_case( l )
  1175. X   struct bwb_line *l;
  1176. X#endif
  1177. X   {
  1178. X   struct bwb_line *current;
  1179. X   register int c_level;
  1180. X   int position;
  1181. X
  1182. X   c_level = 1;
  1183. X   for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1184. X      {
  1185. X      position = 0;
  1186. X      if ( current->marked != TRUE )
  1187. X         {
  1188. X         line_start( current->buffer, &position, &( current->lnpos ),
  1189. X            &( current->lnum ),
  1190. X            &( current->cmdpos ),
  1191. X            &( current->cmdnum ),
  1192. X            &( current->startpos ) );
  1193. X         }
  1194. X      current->position = current->startpos;
  1195. X
  1196. X      if ( current->cmdnum > -1 )
  1197. X         {
  1198. X
  1199. X         if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_select )
  1200. X            {
  1201. X            ++c_level;
  1202. X
  1203. X#if INTENSIVE_DEBUG
  1204. X            sprintf( bwb_ebuf, "in find_case(): found SELECT at line %d, level %d",
  1205. X               current->number, c_level );
  1206. X            bwb_debug( bwb_ebuf );
  1207. X#endif
  1208. X
  1209. X            }
  1210. X         else if ( is_endselect( current ) == TRUE )
  1211. X            {
  1212. X            --c_level;
  1213. X
  1214. X#if INTENSIVE_DEBUG
  1215. X            sprintf( bwb_ebuf, "in find_endif(): found END SELECT at line %d, level %d",
  1216. X               current->number, c_level );
  1217. X            bwb_debug( bwb_ebuf );
  1218. X#endif
  1219. X
  1220. X            if ( c_level == 0 )
  1221. X               {
  1222. X               return current;
  1223. X               }
  1224. X            }
  1225. X
  1226. X         else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_case )
  1227. X            {
  1228. X            --c_level;
  1229. X
  1230. X#if INTENSIVE_DEBUG
  1231. X            sprintf( bwb_ebuf, "in find_case(): found CASE at line %d, level %d",
  1232. X               current->number, c_level );
  1233. X            bwb_debug( bwb_ebuf );
  1234. X#endif
  1235. X
  1236. X            if ( c_level == 0 )
  1237. X               {
  1238. X               return current;
  1239. X               }
  1240. X            }
  1241. X         }
  1242. X      }
  1243. X
  1244. X#if PROG_ERRORS
  1245. X   sprintf( bwb_ebuf, "SELECT without CASE" );
  1246. X   bwb_error( bwb_ebuf );
  1247. X#else
  1248. X   bwb_error( err_syntax  );
  1249. X#endif
  1250. X
  1251. X   return NULL;
  1252. X
  1253. X   }
  1254. X
  1255. X/***************************************************************
  1256. X
  1257. X        FUNCTION:       find_case()
  1258. X
  1259. X        DESCRIPTION:    This function searches for a line containing
  1260. X                        an END SELECT statement corresponding to a previous
  1261. X                        SELECT CASE statement.
  1262. X
  1263. X***************************************************************/
  1264. X
  1265. X#if ANSI_C
  1266. Xstatic struct bwb_line *
  1267. Xfind_endselect( struct bwb_line *l )
  1268. X#else
  1269. Xstatic struct bwb_line *
  1270. Xfind_endselect( l )
  1271. X   struct bwb_line *l;
  1272. X#endif
  1273. X   {
  1274. X   struct bwb_line *current;
  1275. X   register int c_level;
  1276. X   int position;
  1277. X
  1278. X   c_level = 1;
  1279. X   for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1280. X      {
  1281. X      position = 0;
  1282. X      if ( current->marked != TRUE )
  1283. X         {
  1284. X         line_start( current->buffer, &position, &( current->lnpos ),
  1285. X            &( current->lnum ),
  1286. X            &( current->cmdpos ),
  1287. X            &( current->cmdnum ),
  1288. X            &( current->startpos ) );
  1289. X         }
  1290. X      current->position = current->startpos;
  1291. X
  1292. X      if ( current->cmdnum > -1 )
  1293. X         {
  1294. X
  1295. X         if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_select )
  1296. X            {
  1297. X            ++c_level;
  1298. X
  1299. X#if INTENSIVE_DEBUG
  1300. X            sprintf( bwb_ebuf, "in find_case(): found SELECT at line %d, level %d",
  1301. X               current->number, c_level );
  1302. X            bwb_debug( bwb_ebuf );
  1303. X#endif
  1304. X
  1305. X            }
  1306. X         else if ( is_endselect( current ) == TRUE )
  1307. X            {
  1308. X            --c_level;
  1309. X
  1310. X#if INTENSIVE_DEBUG
  1311. X            sprintf( bwb_ebuf, "in find_endif(): found END SELECT at line %d, level %d",
  1312. X               current->number, c_level );
  1313. X            bwb_debug( bwb_ebuf );
  1314. X#endif
  1315. X
  1316. X            if ( c_level == 0 )
  1317. X               {
  1318. X               return current;
  1319. X               }
  1320. X            }
  1321. X         }
  1322. X      }
  1323. X
  1324. X#if PROG_ERRORS
  1325. X   sprintf( bwb_ebuf, "SELECT without END SELECT" );
  1326. X   bwb_error( bwb_ebuf );
  1327. X#else
  1328. X   bwb_error( err_syntax  );
  1329. X#endif
  1330. X
  1331. X   return NULL;
  1332. X
  1333. X   }
  1334. X
  1335. X/***************************************************************
  1336. X
  1337. X    FUNCTION:       is_endselect()
  1338. X
  1339. X    DESCRIPTION:    This C function attempts to determine if
  1340. X            a given line contains an END SELECT statement.
  1341. X
  1342. X***************************************************************/
  1343. X
  1344. X#if ANSI_C
  1345. Xstatic int
  1346. Xis_endselect( struct bwb_line *l )
  1347. X#else
  1348. Xstatic int
  1349. Xis_endselect( l )
  1350. X   struct bwb_line *l;
  1351. X#endif
  1352. X   {
  1353. X   int position;
  1354. X   char tbuf[ MAXVARNAMESIZE + 1];
  1355. X
  1356. X   if ( bwb_cmdtable[ l->cmdnum ].vector != bwb_xend )
  1357. X      {
  1358. X      return FALSE;
  1359. X      }
  1360. X
  1361. X   position = l->startpos;
  1362. X   adv_ws( l->buffer, &position );
  1363. X   adv_element( l->buffer, &position, tbuf );
  1364. X   bwb_strtoupper( tbuf );
  1365. X
  1366. X   if ( strcmp( tbuf, "SELECT" ) == 0 )
  1367. X      {
  1368. X      return TRUE;
  1369. X      }
  1370. X
  1371. X   return FALSE;
  1372. X
  1373. X   }
  1374. X
  1375. X/***************************************************************
  1376. X
  1377. X        FUNCTION:       bwb_endselect()
  1378. X
  1379. X        DESCRIPTION:    This function handles the BASIC END
  1380. X                        SELECT statement.
  1381. X
  1382. X    SYNTAX:        END SELECT
  1383. X
  1384. X***************************************************************/
  1385. X
  1386. X#if ANSI_C
  1387. Xstruct bwb_line *
  1388. Xbwb_endselect( struct bwb_line *l )
  1389. X#else
  1390. Xstruct bwb_line *
  1391. Xbwb_endselect( l )
  1392. X   struct bwb_line *l;
  1393. X#endif
  1394. X   {
  1395. X
  1396. X#if INTENSIVE_DEBUG
  1397. X   sprintf( bwb_ebuf, "in bwb_endselect(): entered function" );
  1398. X   bwb_debug( bwb_ebuf );
  1399. X#endif
  1400. X
  1401. X   if (  ( CURTASK excs[ CURTASK exsc ].code != EXEC_SELTRUE  )
  1402. X      && ( CURTASK excs[ CURTASK exsc ].code != EXEC_SELFALSE ))
  1403. X      {
  1404. X#if PROG_ERRORS
  1405. X      sprintf( bwb_ebuf, "in bwb_endselect(): END SELECT without SELECT" );
  1406. X      bwb_error( bwb_ebuf );
  1407. X#else
  1408. X      bwb_error( err_syntax );
  1409. X#endif
  1410. X      }
  1411. X
  1412. X   bwb_decexec();
  1413. X
  1414. X
  1415. X#if MULTISEG_LINES
  1416. X   adv_eos( l->buffer, &( l->position ));
  1417. X#endif
  1418. X   return bwb_zline( l );
  1419. X   }
  1420. X
  1421. X#endif                /* STRUCT_CMDS */
  1422. X
  1423. X#if COMMON_CMDS || STRUCT_CMDS
  1424. X
  1425. X/***    WHILE-WEND ***/
  1426. X
  1427. X/***************************************************************
  1428. X
  1429. X        FUNCTION:       bwb_while()
  1430. X
  1431. X        DESCRIPTION:    This function handles the BASIC WHILE
  1432. X            statement and also the ANSI DO WHILE
  1433. X            statement.
  1434. X
  1435. X    SYNTAX:        WHILE expression
  1436. X            DO WHILE expression
  1437. X
  1438. X***************************************************************/
  1439. X
  1440. X#if ANSI_C
  1441. Xstruct bwb_line *
  1442. Xbwb_while( struct bwb_line *l )
  1443. X#else
  1444. Xstruct bwb_line *
  1445. Xbwb_while( l )
  1446. X   struct bwb_line *l;
  1447. X#endif
  1448. X   {
  1449. X   struct exp_ese *e;
  1450. X   struct bwb_line *r;
  1451. X
  1452. X   /* call bwb_exp() to interpret the expression */
  1453. X
  1454. X   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  1455. X
  1456. X   if ( (int) exp_getnval( e ) == TRUE )
  1457. X      {
  1458. X
  1459. X      /* if this is the first time at this WHILE statement, note it */
  1460. X
  1461. X      if ( CURTASK excs[ CURTASK exsc ].while_line != l )
  1462. X         {
  1463. X
  1464. X         bwb_incexec();
  1465. X         CURTASK excs[ CURTASK exsc ].while_line = l;
  1466. X
  1467. X         /* find the WEND statement (or LOOP statement) */
  1468. X
  1469. X#if STRUCT_CMDS
  1470. X     if ( l->cmdnum == getcmdnum( CMD_DO ))
  1471. X            {
  1472. X        CURTASK excs[ CURTASK exsc ].wend_line = find_loop( l );
  1473. X            }
  1474. X         else
  1475. X            {
  1476. X        CURTASK excs[ CURTASK exsc ].wend_line = find_wend( l );
  1477. X        }
  1478. X#else
  1479. X     CURTASK excs[ CURTASK exsc ].wend_line = find_wend( l );
  1480. X#endif
  1481. X
  1482. X         if ( CURTASK excs[ CURTASK exsc ].wend_line == NULL )
  1483. X            {
  1484. X            return bwb_zline( l );
  1485. X            }
  1486. X
  1487. X#if INTENSIVE_DEBUG
  1488. X         sprintf( bwb_ebuf, "in bwb_while(): initialize WHILE loop, line <%d>",
  1489. X            l->number );
  1490. X         bwb_debug( bwb_ebuf );
  1491. X#endif
  1492. X
  1493. X         }
  1494. X#if INTENSIVE_DEBUG
  1495. X      else
  1496. X         {
  1497. X         sprintf( bwb_ebuf, "in bwb_while(): return to WHILE loop, line <%d>",
  1498. X            l->number );
  1499. X         bwb_debug( bwb_ebuf );
  1500. X         }
  1501. X#endif
  1502. X
  1503. X      bwb_setexec( l, l->position, EXEC_WHILE );
  1504. X      return bwb_zline( l );
  1505. X      }
  1506. X   else
  1507. X      {
  1508. X      CURTASK excs[ CURTASK exsc ].while_line = NULL;
  1509. X      r = CURTASK excs[ CURTASK exsc ].wend_line;
  1510. X      bwb_setexec( r, 0, CURTASK excs[ CURTASK exsc - 1 ].code );
  1511. X      r->position = 0;
  1512. X      bwb_decexec();
  1513. X      return r;
  1514. X      }
  1515. X
  1516. X   }
  1517. X
  1518. X/***************************************************************
  1519. X
  1520. X        FUNCTION:       bwb_wend()
  1521. X
  1522. X        DESCRIPTION:    This function handles the BASIC WEND
  1523. X            statement and the LOOP statement ending
  1524. X            a DO WHILE loop.
  1525. X
  1526. X    SYNTAX:        WEND
  1527. X            LOOP
  1528. X
  1529. X***************************************************************/
  1530. X
  1531. X#if ANSI_C
  1532. Xstruct bwb_line *
  1533. Xbwb_wend( struct bwb_line *l )
  1534. X#else
  1535. Xstruct bwb_line *
  1536. Xbwb_wend( l )
  1537. X   struct bwb_line *l;
  1538. X#endif
  1539. X   {
  1540. X
  1541. X   /* check integrity of WHILE loop */
  1542. X
  1543. X   if ( CURTASK excs[ CURTASK exsc ].code != EXEC_WHILE )
  1544. X      {
  1545. X#if PROG_ERRORS
  1546. X      sprintf( bwb_ebuf, "in bwb_wend(): exec stack code != EXEC_WHILE" );
  1547. X      bwb_error( bwb_ebuf );
  1548. X#else
  1549. X      bwb_error( err_syntax );
  1550. X#endif
  1551. X      }
  1552. X
  1553. X   if ( CURTASK excs[ CURTASK exsc ].while_line == NULL )
  1554. X      {
  1555. X#if PROG_ERRORS
  1556. X      sprintf( bwb_ebuf, "in bwb_wend(): exec stack while_line == NULL" );
  1557. X      bwb_error( bwb_ebuf );
  1558. X#else
  1559. X      bwb_error( err_syntax );
  1560. X#endif
  1561. X      }
  1562. X
  1563. X   /* reset to the top of the current WHILE loop */
  1564. X
  1565. X#if INTENSIVE_DEBUG
  1566. X   sprintf( bwb_ebuf, "in bwb_wend() return to line <%d>",
  1567. X      CURTASK excs[ CURTASK exsc ].while_line->number );
  1568. X   bwb_debug( bwb_ebuf );
  1569. X#endif
  1570. X
  1571. X   CURTASK excs[ CURTASK exsc ].while_line->position = 0;
  1572. X   bwb_setexec( CURTASK excs[ CURTASK exsc ].while_line, 0, EXEC_WHILE );
  1573. X
  1574. X   return CURTASK excs[ CURTASK exsc ].while_line;
  1575. X
  1576. X   }
  1577. X
  1578. X/***************************************************************
  1579. X
  1580. X        FUNCTION:       find_wend()
  1581. X
  1582. X        DESCRIPTION:    This function searches for a line containing
  1583. X                        a WEND statement corresponding to a previous
  1584. X                        WHILE statement.
  1585. X
  1586. X***************************************************************/
  1587. X
  1588. X#if ANSI_C
  1589. Xstatic struct bwb_line *
  1590. Xfind_wend( struct bwb_line *l )
  1591. X#else
  1592. Xstatic struct bwb_line *
  1593. Xfind_wend( l )
  1594. X   struct bwb_line *l;
  1595. X#endif
  1596. X   {
  1597. X   struct bwb_line *current;
  1598. X   register int w_level;
  1599. X   int position;
  1600. X
  1601. X   w_level = 1;
  1602. X   for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1603. X      {
  1604. X      position = 0;
  1605. X      if ( current->marked != TRUE )
  1606. X         {
  1607. X         line_start( current->buffer, &position, &( current->lnpos ),
  1608. X            &( current->lnum ),
  1609. X            &( current->cmdpos ),
  1610. X            &( current->cmdnum ),
  1611. X            &( current->startpos ) );
  1612. X         }
  1613. X      current->position = current->startpos;
  1614. X
  1615. X      if ( current->cmdnum > -1 )
  1616. X         {
  1617. X
  1618. X         if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_while )
  1619. X            {
  1620. X            ++w_level;
  1621. X
  1622. X#if INTENSIVE_DEBUG
  1623. X        sprintf( bwb_ebuf, "in find_wend(): found WHILE at line %d, level %d",
  1624. X               current->number, w_level );
  1625. X            bwb_debug( bwb_ebuf );
  1626. X#endif
  1627. X
  1628. X            }
  1629. X         else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_wend )
  1630. X            {
  1631. X            --w_level;
  1632. X
  1633. X#if INTENSIVE_DEBUG
  1634. X        sprintf( bwb_ebuf, "in find_wend(): found WEND at line %d, level %d",
  1635. X               current->number, w_level );
  1636. X            bwb_debug( bwb_ebuf );
  1637. X#endif
  1638. X
  1639. X            if ( w_level == 0 )
  1640. X               {
  1641. X               return current->next;
  1642. X               }
  1643. X            }
  1644. X         }
  1645. X      }
  1646. X
  1647. X#if PROG_ERRORS
  1648. X   sprintf( bwb_ebuf, "in find_wend(): WHILE without WEND" );
  1649. X   bwb_error( bwb_ebuf );
  1650. X#else
  1651. X   bwb_error( err_syntax  );
  1652. X#endif
  1653. X
  1654. X   return NULL;
  1655. X
  1656. X   }
  1657. X
  1658. X#if STRUCT_CMDS
  1659. X
  1660. X/***************************************************************
  1661. X
  1662. X    FUNCTION:       find_loop()
  1663. X
  1664. X    DESCRIPTION:    This function searches for a line containing
  1665. X            a LOOP statement corresponding to a previous
  1666. X            DO statement.
  1667. X
  1668. X***************************************************************/
  1669. X
  1670. X#if ANSI_C
  1671. Xextern struct bwb_line *
  1672. Xfind_loop( struct bwb_line *l )
  1673. X#else
  1674. Xextern struct bwb_line *
  1675. Xfind_loop( l )
  1676. X   struct bwb_line *l;
  1677. X#endif
  1678. X   {
  1679. X   struct bwb_line *current;
  1680. X   register int w_level;
  1681. X   int position;
  1682. X
  1683. X   w_level = 1;
  1684. X   for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1685. X      {
  1686. X      position = 0;
  1687. X      if ( current->marked != TRUE )
  1688. X     {
  1689. X     line_start( current->buffer, &position, &( current->lnpos ),
  1690. X        &( current->lnum ),
  1691. X        &( current->cmdpos ),
  1692. X        &( current->cmdnum ),
  1693. X        &( current->startpos ) );
  1694. X     }
  1695. X      current->position = current->startpos;
  1696. X
  1697. X      if ( current->cmdnum > -1 )
  1698. X     {
  1699. X
  1700. X     if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_do )
  1701. X        {
  1702. X        ++w_level;
  1703. X
  1704. X#if INTENSIVE_DEBUG
  1705. X        sprintf( bwb_ebuf, "in find_loop(): found DO at line %d, level %d",
  1706. X           current->number, w_level );
  1707. X        bwb_debug( bwb_ebuf );
  1708. X#endif
  1709. X
  1710. X        }
  1711. X     else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_loop )
  1712. X        {
  1713. X        --w_level;
  1714. X
  1715. X#if INTENSIVE_DEBUG
  1716. X        sprintf( bwb_ebuf, "in fnd_loop(): found LOOP at line %d, level %d",
  1717. X           current->number, w_level );
  1718. X        bwb_debug( bwb_ebuf );
  1719. X#endif
  1720. X
  1721. X        if ( w_level == 0 )
  1722. X           {
  1723. X           return current->next;
  1724. X           }
  1725. X        }
  1726. X     }
  1727. X      }
  1728. X
  1729. X#if PROG_ERRORS
  1730. X   sprintf( bwb_ebuf, "in find_loop(): DO without LOOP" );
  1731. X   bwb_error( bwb_ebuf );
  1732. X#else
  1733. X   bwb_error( err_syntax  );
  1734. X#endif
  1735. X
  1736. X   return NULL;
  1737. X
  1738. X   }
  1739. X
  1740. X#endif                          /* STRUCT_CMDS */
  1741. X
  1742. X#endif                          /* COMMON_CMDS || STRUCT_CMDS */
  1743. X
  1744. X/***    FOR-NEXT ***/
  1745. X
  1746. X/***************************************************************
  1747. X
  1748. X        FUNCTION:       bwb_for()
  1749. X
  1750. X        DESCRIPTION:    This function handles the BASIC FOR
  1751. X                        statement.
  1752. X
  1753. X    SYNTAX:        FOR counter = start TO finish [STEP increment]
  1754. X
  1755. X***************************************************************/
  1756. X
  1757. X#if ANSI_C
  1758. Xstruct bwb_line *
  1759. Xbwb_for( struct bwb_line *l )
  1760. X#else
  1761. Xstruct bwb_line *
  1762. Xbwb_for( l )
  1763. X   struct bwb_line *l;
  1764. X#endif
  1765. X   {
  1766. X   register int n;
  1767. X   int e, loop;
  1768. X   int to, step, p;
  1769. X   int for_step, for_target;
  1770. X   struct exp_ese *exp;
  1771. X   struct bwb_variable *v;
  1772. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  1773. X
  1774. X   /* get the variable name */
  1775. X
  1776. X   exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
  1777. X   l->position += strlen( tbuf );
  1778. X   v = var_find( tbuf );
  1779. X
  1780. X#if INTENSIVE_DEBUG
  1781. X   sprintf( bwb_ebuf, "in bwb_for(): variable name <%s>.", v->name );
  1782. X   bwb_debug( bwb_ebuf );
  1783. X#endif
  1784. X
  1785. X   /* at this point one should find an equals sign ('=') */
  1786. X
  1787. X   adv_ws( l->buffer, &( l->position ) );
  1788. X
  1789. X   if ( l->buffer[ l->position ] != '=' )
  1790. X      {
  1791. X#if PROG_ERRORS
  1792. X      sprintf( bwb_ebuf, "in bwb_for(): failed to find equals sign, buf <%s>",
  1793. X         &( l->buffer[ l->position ] ) );
  1794. X      bwb_error( bwb_ebuf );
  1795. X#else
  1796. X      bwb_error( err_syntax );
  1797. X#endif
  1798. X      return bwb_zline( l );
  1799. X      }
  1800. X   else
  1801. X      {
  1802. X      ++( l->position );
  1803. X      }
  1804. X
  1805. X   /* Find the TO and STEP statements */
  1806. X
  1807. X   cnd_tostep( l->buffer, l->position, &to, &step );
  1808. X
  1809. X   /* if there is no TO statement, then an error has ocurred */
  1810. X
  1811. X   if ( to < 1 )
  1812. X      {
  1813. X#if PROG_ERRORS
  1814. X      sprintf( bwb_ebuf, "FOR statement without TO" );
  1815. X      bwb_error( bwb_ebuf );
  1816. X#else
  1817. X      bwb_error( err_syntax  );
  1818. X#endif
  1819. X      return bwb_zline( l );
  1820. X      }
  1821. X
  1822. X   /* copy initial value to buffer and evaluate it */
  1823. X
  1824. X   tbuf[ 0 ] = '\0';
  1825. X   p = 0;
  1826. X   for ( n = l->position; n < to; ++n )
  1827. X      {
  1828. X      tbuf[ p ] = l->buffer[ n ];
  1829. X      ++p;
  1830. X      ++l->position;
  1831. X      tbuf[ p ] = '\0';
  1832. X      }
  1833. X
  1834. X#if INTENSIVE_DEBUG
  1835. X   sprintf( bwb_ebuf, "in bwb_for(): initial value string <%s>",
  1836. X      tbuf );
  1837. X   bwb_debug( bwb_ebuf );
  1838. X#endif
  1839. X
  1840. X   p = 0;
  1841. X   exp = bwb_exp( tbuf, FALSE, &p );
  1842. X   var_setnval( v, exp_getnval( exp ) );
  1843. X
  1844. X#if INTENSIVE_DEBUG
  1845. X   sprintf( bwb_ebuf, "in bwb_for(): initial value <%d> pos <%d>",
  1846. X      exp_getnval( exp ), l->position );
  1847. X   bwb_debug( bwb_ebuf );
  1848. X#endif
  1849. X
  1850. X   /* copy target value to small buffer and evaluate it */
  1851. X
  1852. X   tbuf[ 0 ] = '\0';
  1853. X   p = 0;
  1854. X   l->position = to + 2;
  1855. X   if ( step < 1 )
  1856. X      {
  1857. X      e = strlen( l->buffer );
  1858. X      }
  1859. X   else
  1860. X      {
  1861. X      e = step - 1;
  1862. X      }
  1863. X
  1864. X   loop = TRUE;
  1865. X   n = l->position;
  1866. X   while( loop == TRUE )
  1867. X      {
  1868. X      tbuf[ p ] = l->buffer[ n ];
  1869. X      ++p;
  1870. X      ++l->position;
  1871. X      tbuf[ p ] = '\0';
  1872. X
  1873. X      if ( n >= e )
  1874. X          {
  1875. X          loop = FALSE;
  1876. X          }
  1877. X
  1878. X      ++n;
  1879. X
  1880. X      if ( l->buffer[ n ] == ':' )
  1881. X         {
  1882. X         loop = FALSE;
  1883. X         }
  1884. X
  1885. X      }
  1886. X
  1887. X#if INTENSIVE_DEBUG
  1888. X   sprintf( bwb_ebuf, "in bwb_for(): target value string <%s>",
  1889. X      tbuf );
  1890. X   bwb_debug( bwb_ebuf );
  1891. X#endif
  1892. X
  1893. X   p = 0;
  1894. X   exp = bwb_exp( tbuf, FALSE, &p );
  1895. X   for_target = (int) exp_getnval( exp );
  1896. X
  1897. X#if INTENSIVE_DEBUG
  1898. X   sprintf( bwb_ebuf, "in bwb_for(): target value <%d> pos <%d>",
  1899. X      exp_getnval( exp ), l->position );
  1900. X   bwb_debug( bwb_ebuf );
  1901. X#endif
  1902. X
  1903. X   /* If there is a STEP statement, copy it to a buffer
  1904. X      and evaluate it */
  1905. X
  1906. X   if ( step > 1 )
  1907. X      {
  1908. X      tbuf[ 0 ] = '\0';
  1909. X      p = 0;
  1910. X      l->position = step + 4;
  1911. X
  1912. X      for ( n = l->position; n < (int) strlen( l->buffer ); ++n )
  1913. X         {
  1914. X         tbuf[ p ] = l->buffer[ n ];
  1915. X         ++p;
  1916. X         ++l->position;
  1917. X         tbuf[ p ] = '\0';
  1918. X         }
  1919. X
  1920. X#if INTENSIVE_DEBUG
  1921. X      sprintf( bwb_ebuf, "in bwb_for(): step value string <%s>",
  1922. X         tbuf );
  1923. X      bwb_debug( bwb_ebuf );
  1924. X#endif
  1925. X
  1926. X      p = 0;
  1927. X      exp = bwb_exp( tbuf, FALSE, &p );
  1928. X      for_step = (int) exp_getnval( exp );
  1929. X
  1930. X      }
  1931. X   else
  1932. X      {
  1933. X      for_step = 1;
  1934. X      }
  1935. X
  1936. X
  1937. X#if INTENSIVE_DEBUG
  1938. X   sprintf( bwb_ebuf, "in bwb_for(): step value <%d>",
  1939. X      for_step );
  1940. X   bwb_debug( bwb_ebuf );
  1941. X#endif
  1942. X
  1943. X   /* set position in current line and increment EXEC counter */
  1944. X
  1945. X   /* bwb_setexec( l, l->position, EXEC_NORM ); */  /* WRONG */
  1946. X   bwb_incexec();
  1947. X
  1948. X   CURTASK excs[ CURTASK exsc ].local_variable  = v;
  1949. X   CURTASK excs[ CURTASK exsc ].for_step   = for_step;
  1950. X   CURTASK excs[ CURTASK exsc ].for_target = for_target;
  1951. X
  1952. X   /* set exit line to be used by EXIT FOR */
  1953. X
  1954. X#if STRUCT_CMDS
  1955. X   CURTASK excs[ CURTASK exsc ].wend_line  = find_next( l );
  1956. X#endif
  1957. X
  1958. X   /* set top line and position to be used in multisegmented FOR-NEXT loop */
  1959. X
  1960. X#if MULTISEG_LINES
  1961. X   CURTASK excs[ CURTASK exsc ].for_line     = l;
  1962. X   CURTASK excs[ CURTASK exsc ].for_position = l->position;
  1963. X#endif
  1964. X
  1965. X#if INTENSIVE_DEBUG
  1966. X   sprintf( bwb_ebuf, "in bwb_for(): setting code to EXEC_FOR",
  1967. X      l->position );
  1968. X   bwb_debug( bwb_ebuf );
  1969. X#endif
  1970. X
  1971. X   bwb_setexec( l, l->position, EXEC_FOR );
  1972. X
  1973. X#if INTENSIVE_DEBUG
  1974. X   sprintf( bwb_ebuf, "in bwb_for(): ready to exit, position <%d>",
  1975. X      l->position );
  1976. X   bwb_debug( bwb_ebuf );
  1977. X#endif
  1978. X
  1979. X   /* proceed with processing */
  1980. X
  1981. X   return bwb_zline( l );
  1982. X
  1983. X   }
  1984. X
  1985. X/***************************************************************
  1986. X
  1987. X        FUNCTION:       bwb_next()
  1988. X
  1989. X        DESCRIPTION:    This function handles the BASIC NEXT
  1990. X                        statement.
  1991. X
  1992. X    SYNTAX:        NEXT counter
  1993. X
  1994. X***************************************************************/
  1995. X
  1996. X#if ANSI_C
  1997. Xstruct bwb_line *
  1998. Xbwb_next( struct bwb_line *l )
  1999. X#else
  2000. Xstruct bwb_line *
  2001. Xbwb_next( l )
  2002. X   struct bwb_line *l;
  2003. X#endif
  2004. X   {
  2005. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  2006. X#if INTENSIVE_DEBUG
  2007. X   struct bwb_variable *v;
  2008. X#endif
  2009. X
  2010. X#if INTENSIVE_DEBUG
  2011. X   sprintf( bwb_ebuf, "in bwb_next(): entered function, cmdnum <%d> exsc level <%d> code <%d>",
  2012. X      l->cmdnum, CURTASK exsc, CURTASK excs[ CURTASK exsc ].code );
  2013. X   bwb_debug( bwb_ebuf );
  2014. X#endif
  2015. X
  2016. X   /* Check the integrity of the FOR statement */
  2017. X
  2018. X   if ( CURTASK excs[ CURTASK exsc ].code != EXEC_FOR )
  2019. X      {
  2020. X#if PROG_ERRORS
  2021. X      sprintf( bwb_ebuf, "in bwb_next(): NEXT without FOR; code is <%d> instead of <%d>",
  2022. X     CURTASK excs[ CURTASK exsc ].code, EXEC_FOR );
  2023. X      bwb_error( bwb_ebuf );
  2024. X#else
  2025. X      bwb_error( err_syntax );
  2026. X#endif
  2027. X      }
  2028. X
  2029. X   /* read the argument, if there is one */
  2030. X
  2031. X#if MULTISEG_LINES                   /* not currently needed otherwise */
  2032. X
  2033. X   exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
  2034. X   l->position += strlen( tbuf );
  2035. X
  2036. X#if INTENSIVE_DEBUG
  2037. X   v = var_find( tbuf );
  2038. X   sprintf( bwb_ebuf, "in bwb_next(): variable name detected <%s>.", v->name );
  2039. X   bwb_debug( bwb_ebuf );
  2040. X#endif
  2041. X#endif
  2042. X
  2043. X   /* decrement or increment the value */
  2044. X
  2045. X   var_setnval( CURTASK excs[ CURTASK exsc ].local_variable,
  2046. X      var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
  2047. X      + (bnumber) CURTASK excs[ CURTASK exsc ].for_step );
  2048. X
  2049. X   /* check for completion of the loop */
  2050. X
  2051. X   if ( CURTASK excs[ CURTASK exsc ].for_step > 0 )            /* if step is positive */
  2052. X      {
  2053. X      if ( (int) var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
  2054. X         > CURTASK excs[ CURTASK exsc ].for_target )
  2055. X         {
  2056. X         bwb_decexec();
  2057. X#if MULTISEG_LINES
  2058. X     bwb_setexec( l, l->position, CURTASK excs[ CURTASK exsc ].code );
  2059. X#else
  2060. X     bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
  2061. X#endif
  2062. X
  2063. X#if INTENSIVE_DEBUG
  2064. X     sprintf( bwb_ebuf, "in bwb_next(): end of loop" );
  2065. X     bwb_debug( bwb_ebuf );
  2066. X#endif
  2067. X
  2068. X#ifdef OLD_WAY
  2069. X     l->next->position = 0;
  2070. X     return l->next;
  2071. X#else
  2072. X     return bwb_zline( l );
  2073. X#endif
  2074. X         }
  2075. X      }
  2076. X   else                                         /* if step is negative */
  2077. X      {
  2078. X      if ( (int) var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
  2079. X         < CURTASK excs[ CURTASK exsc ].for_target )
  2080. X         {
  2081. X         bwb_decexec();
  2082. X     bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
  2083. X
  2084. X#if INTENSIVE_DEBUG
  2085. X     sprintf( bwb_ebuf, "in bwb_next(): end of loop" );
  2086. X     bwb_debug( bwb_ebuf );
  2087. X#endif
  2088. X
  2089. X#ifdef OLD_WAY
  2090. X     l->next->position = 0;
  2091. X     return l->next;
  2092. X#else
  2093. X     return bwb_zline( l );
  2094. X#endif
  2095. X         }
  2096. X      }
  2097. X
  2098. X   /* Target not reached: return to the top of the FOR loop */
  2099. X
  2100. X#if INTENSIVE_DEBUG
  2101. X   sprintf( bwb_ebuf, "in bwb_next(): resetting code to EXEC_FOR",
  2102. X      l->position );
  2103. X   bwb_debug( bwb_ebuf );
  2104. X#endif
  2105. X
  2106. X#if MULTISEG_LINES
  2107. X   CURTASK excs[ CURTASK exsc ].for_line->position
  2108. X      = CURTASK excs[ CURTASK exsc ].for_position;
  2109. X   bwb_setexec( CURTASK excs[ CURTASK exsc ].for_line,
  2110. X      CURTASK excs[ CURTASK exsc ].for_position, EXEC_FOR );
  2111. X#else
  2112. X   bwb_setexec( CURTASK excs[ CURTASK exsc - 1 ].line,
  2113. X      CURTASK excs[ CURTASK exsc - 1 ].position, EXEC_FOR );
  2114. X#endif
  2115. X
  2116. X   return CURTASK excs[ CURTASK exsc - 1 ].line;
  2117. X
  2118. X   }
  2119. X
  2120. X#if STRUCT_CMDS
  2121. X
  2122. X/***************************************************************
  2123. X
  2124. X    FUNCTION:       bwb_exitfor()
  2125. X
  2126. X    DESCRIPTION:    This function handles the BASIC EXIT
  2127. X            FOR statement.  This is a structured
  2128. X            programming command compatible with ANSI
  2129. X            BASIC. It is called from the bwb_exit()
  2130. X            subroutine.
  2131. X
  2132. X    SYNTAX:        EXIT FOR
  2133. X            
  2134. X***************************************************************/
  2135. X
  2136. X#if ANSI_C
  2137. Xstruct bwb_line *
  2138. Xbwb_exitfor( struct bwb_line *l )
  2139. X#else
  2140. Xstruct bwb_line *
  2141. Xbwb_exitfor( l )
  2142. X   struct bwb_line *l;
  2143. X#endif
  2144. X   {
  2145. X   struct bwb_line *next_line;
  2146. X   int found;
  2147. X   register int level;
  2148. X
  2149. X#if INTENSIVE_DEBUG
  2150. X   sprintf( bwb_ebuf, "in bwb_exitfor(): entered subroutine" );
  2151. X   bwb_debug( bwb_ebuf );
  2152. X#endif
  2153. X
  2154. X   /* Check the integrity of the FOR statement */
  2155. X
  2156. X   found = FALSE;
  2157. X   level = CURTASK exsc;
  2158. X   do
  2159. X      {
  2160. X      if ( CURTASK excs[ level ].code == EXEC_FOR )
  2161. X     {
  2162. X     next_line = CURTASK excs[ CURTASK level ].wend_line;
  2163. X     found = TRUE;
  2164. X     }
  2165. X      else
  2166. X     {
  2167. X     --level;
  2168. X     }
  2169. X      }
  2170. X   while ( ( level >= 0 ) && ( found == FALSE ) );
  2171. X
  2172. X   if ( found != TRUE )
  2173. X      {
  2174. X
  2175. X#if PROG_ERRORS
  2176. X      sprintf( bwb_ebuf, "in bwb_exitfor(): EXIT FOR without FOR" );
  2177. X      bwb_error( bwb_ebuf );
  2178. X#else
  2179. X      bwb_error( err_syntax );
  2180. X#endif
  2181. X
  2182. X      return bwb_zline( l );
  2183. X
  2184. X      }
  2185. X
  2186. X#if INTENSIVE_DEBUG
  2187. X   sprintf( bwb_ebuf, "in bwb_exitfor(): level found is <%d>, current <%d>",
  2188. X      level, CURTASK exsc );
  2189. X   bwb_debug( bwb_ebuf );
  2190. X#endif
  2191. X
  2192. X   /* decrement below the level of the NEXT statement */
  2193. X
  2194. X   while( CURTASK exsc >= level )
  2195. X      {
  2196. X      bwb_decexec();
  2197. X      }
  2198. X
  2199. X   /* set the next line in the exec stack */
  2200. X
  2201. X   next_line->position = 0;
  2202. X   bwb_setexec( next_line, 0, EXEC_NORM );
  2203. X
  2204. X   return next_line;
  2205. X
  2206. X   }
  2207. X
  2208. X/***************************************************************
  2209. X
  2210. X    FUNCTION:       find_next()
  2211. X
  2212. X    DESCRIPTION:    This function searches for a line containing
  2213. X            a NEXT statement corresponding to a previous
  2214. X            FOR statement.
  2215. X
  2216. X***************************************************************/
  2217. X
  2218. X#if ANSI_C
  2219. Xstatic struct bwb_line *
  2220. Xfind_next( struct bwb_line *l )
  2221. X#else
  2222. Xstatic struct bwb_line *
  2223. Xfind_next( l )
  2224. X   struct bwb_line *l;
  2225. X#endif
  2226. X   {
  2227. X   struct bwb_line *current;
  2228. X   register int w_level;
  2229. X   int position;
  2230. X
  2231. X   w_level = 1;
  2232. X   for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  2233. X      {
  2234. X      position = 0;
  2235. X      if ( current->marked != TRUE )
  2236. X     {
  2237. X     line_start( current->buffer, &position, &( current->lnpos ),
  2238. X        &( current->lnum ),
  2239. X        &( current->cmdpos ),
  2240. X        &( current->cmdnum ),
  2241. X        &( current->startpos ) );
  2242. X     }
  2243. X      current->position = current->startpos;
  2244. X
  2245. X      if ( current->cmdnum > -1 )
  2246. X     {
  2247. X
  2248. X     if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_for )
  2249. X        {
  2250. X        ++w_level;
  2251. X
  2252. X#if INTENSIVE_DEBUG
  2253. X        sprintf( bwb_ebuf, "in find_next(): found FOR at line %d, level %d",
  2254. X           current->number, w_level );
  2255. X        bwb_debug( bwb_ebuf );
  2256. X#endif
  2257. X
  2258. X        }
  2259. X     else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_next )
  2260. X        {
  2261. X        --w_level;
  2262. X
  2263. X#if INTENSIVE_DEBUG
  2264. X        sprintf( bwb_ebuf, "in find_next(): found NEXT at line %d, level %d",
  2265. X           current->number, w_level );
  2266. X        bwb_debug( bwb_ebuf );
  2267. X#endif
  2268. X
  2269. X        if ( w_level == 0 )
  2270. X           {
  2271. X
  2272. X#if INTENSIVE_DEBUG
  2273. X           sprintf( bwb_ebuf, "in find_next(): found returning line <%d>",
  2274. X          current->next->number );
  2275. X           bwb_debug( bwb_ebuf );
  2276. X#endif
  2277. X
  2278. X           return current->next;
  2279. X           }
  2280. X        }
  2281. X     }
  2282. X      }
  2283. X
  2284. X#if PROG_ERRORS
  2285. X   sprintf( bwb_ebuf, "FOR without NEXT" );
  2286. X   bwb_error( bwb_ebuf );
  2287. X#else
  2288. X   bwb_error( err_syntax  );
  2289. X#endif
  2290. X
  2291. X   return NULL;
  2292. X
  2293. X   }
  2294. X
  2295. X#endif                /* STRUCT_CMDS for EXIT FOR */
  2296. X
  2297. X/***************************************************************
  2298. X
  2299. X    FUNCTION:    cnd_tostep()
  2300. X
  2301. X    DESCRIPTION:    This function searches through the
  2302. X            <buffer> beginning at point <position>
  2303. X            and attempts to find positions of TO
  2304. X            and STEP statements.
  2305. X
  2306. X***************************************************************/
  2307. X
  2308. X#if ANSI_C
  2309. Xstatic int
  2310. Xcnd_tostep( char *buffer, int position, int *to, int *step )
  2311. X#else
  2312. Xstatic int
  2313. Xcnd_tostep( buffer, position, to, step )
  2314. X   char *buffer;
  2315. X   int position;
  2316. X   int *to;
  2317. X   int *step;
  2318. X#endif
  2319. X   {
  2320. X   int loop, t_pos, b_pos, p_word;
  2321. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  2322. X
  2323. X   /* set then and els to FALSE initially */
  2324. X
  2325. X   *to = *step = FALSE;
  2326. X
  2327. X   /* loop to find words */
  2328. X
  2329. X   p_word = b_pos = position;
  2330. X   t_pos = 0;
  2331. X   tbuf[ 0 ] = '\0';
  2332. X   loop = TRUE;
  2333. X   while ( loop == TRUE )
  2334. X      {
  2335. X
  2336. X      switch( buffer[ b_pos ] )
  2337. X         {
  2338. X         case '\0':                     /* end of string */
  2339. X         case ':':            /* end of line segment */
  2340. X            return TRUE;
  2341. X         case ' ':                      /* whitespace = end of word */
  2342. X         case '\t':
  2343. X
  2344. X#if INTENSIVE_DEBUG
  2345. X            sprintf( bwb_ebuf, "in cnd_tostep(): word is <%s>", tbuf );
  2346. X            bwb_debug( bwb_ebuf );
  2347. X#endif
  2348. X
  2349. X            if ( strncmp( tbuf, CMD_TO, (size_t) strlen( CMD_TO ) ) == 0 )
  2350. X               {
  2351. X
  2352. X#if INTENSIVE_DEBUG
  2353. X               sprintf( bwb_ebuf, "in cnd_tostep(): TO found at position <%d>.",
  2354. X                  p_word );
  2355. X               bwb_debug( bwb_ebuf );
  2356. X#endif
  2357. X
  2358. X               *to = p_word;
  2359. X               }
  2360. X            else if ( strncmp( tbuf, CMD_STEP, (size_t) strlen( CMD_STEP ) ) == 0 )
  2361. X               {
  2362. X
  2363. X#if INTENSIVE_DEBUG
  2364. X               sprintf( bwb_ebuf, "in cnd_tostep(): STEP found at position <%d>.",
  2365. X                  p_word );
  2366. X               bwb_debug( bwb_ebuf );
  2367. X#endif
  2368. X
  2369. X               *step = p_word;
  2370. X               }
  2371. X            ++b_pos;
  2372. X            p_word = b_pos;
  2373. X            t_pos = 0;
  2374. X            tbuf[ 0 ] = '\0';
  2375. X            break;
  2376. X
  2377. X         default:
  2378. X            if ( islower( buffer[ b_pos ] ) != FALSE )
  2379. X               {
  2380. X               tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );
  2381. X               }
  2382. X            else
  2383. X               {
  2384. X               tbuf[ t_pos ] = buffer[ b_pos ];
  2385. X               }
  2386. X            ++b_pos;
  2387. X            ++t_pos;
  2388. X            tbuf[ t_pos ] = '\0';
  2389. X            break;
  2390. X         }
  2391. X
  2392. X      }
  2393. X
  2394. X   return TRUE;
  2395. X
  2396. X   }
  2397. X
  2398. X/***************************************************************
  2399. X
  2400. X    FUNCTION:       var_setnval()
  2401. X
  2402. X    DESCRIPTION:    This function sets the value of numerical
  2403. X            variable v to the value of i.
  2404. X
  2405. X***************************************************************/
  2406. X
  2407. X#if ANSI_C
  2408. Xextern int
  2409. Xvar_setnval( struct bwb_variable *v, bnumber i )
  2410. X#else
  2411. Xint
  2412. Xvar_setnval( v, i )
  2413. X   struct bwb_variable *v;
  2414. X   bnumber i;
  2415. X#endif
  2416. X   {
  2417. X
  2418. X   switch( v->type )
  2419. X      {
  2420. X      case NUMBER:
  2421. X         * var_findnval( v, v->array_pos ) = i;
  2422. X         break;
  2423. X      default:
  2424. X#if INTENSIVE_DEBUG
  2425. X         sprintf( bwb_ebuf, "in var_setnval(): variable <%s> is not a number",
  2426. X            v->name );
  2427. X         bwb_error( bwb_ebuf );
  2428. X#else
  2429. X         bwb_error( err_mismatch );
  2430. X#endif
  2431. X      }
  2432. X
  2433. X   /* successful assignment */
  2434. X
  2435. X   return TRUE;
  2436. X
  2437. X   }
  2438. X
  2439. X
  2440. END_OF_FILE
  2441.   if test 55621 -ne `wc -c <'bwbasic-2.10/bwb_cnd.c'`; then
  2442.     echo shar: \"'bwbasic-2.10/bwb_cnd.c'\" unpacked with wrong size!
  2443.   fi
  2444.   # end of 'bwbasic-2.10/bwb_cnd.c'
  2445. fi
  2446. if test -f 'bwbasic-2.10/bwbtest/assign.bas' -a "${1}" != "-c" ; then 
  2447.   echo shar: Will not clobber existing file \"'bwbasic-2.10/bwbtest/assign.bas'\"
  2448. else
  2449.   echo shar: Extracting \"'bwbasic-2.10/bwbtest/assign.bas'\" \(54 characters\)
  2450.   sed "s/^X//" >'bwbasic-2.10/bwbtest/assign.bas' <<'END_OF_FILE'
  2451. X10 Print "TEST.BAS -- TEST"
  2452. X20 X=7
  2453. X30 print "X is ";X
  2454. END_OF_FILE
  2455.   if test 54 -ne `wc -c <'bwbasic-2.10/bwbtest/assign.bas'`; then
  2456.     echo shar: \"'bwbasic-2.10/bwbtest/assign.bas'\" unpacked with wrong size!
  2457.   fi
  2458.   # end of 'bwbasic-2.10/bwbtest/assign.bas'
  2459. fi
  2460. if test -f 'bwbasic-2.10/bwx_tty.c' -a "${1}" != "-c" ; then 
  2461.   echo shar: Will not clobber existing file \"'bwbasic-2.10/bwx_tty.c'\"
  2462. else
  2463.   echo shar: Extracting \"'bwbasic-2.10/bwx_tty.c'\" \(10751 characters\)
  2464.   sed "s/^X//" >'bwbasic-2.10/bwx_tty.c' <<'END_OF_FILE'
  2465. X/***************************************************************
  2466. X
  2467. X        bwx_tty.c       Environment-dependent implementation
  2468. X                        for Bywater BASIC Interpreter
  2469. X            using simple TTY-style input/output
  2470. X
  2471. X            This file should be used as a template
  2472. X            for developing more sophisticated
  2473. X            environment-dependent implementations
  2474. X
  2475. X                        Copyright (c) 1993, Ted A. Campbell
  2476. X            Bywater Software
  2477. X
  2478. X                        email: tcamp@delphi.com
  2479. X
  2480. X        Copyright and Permissions Information:
  2481. X
  2482. X        All U.S. and international rights are claimed by the author,
  2483. X        Ted A. Campbell.
  2484. X
  2485. X    This software is released under the terms of the GNU General
  2486. X    Public License (GPL), which is distributed with this software
  2487. X    in the file "COPYING".  The GPL specifies the terms under
  2488. X    which users may copy and use the software in this distribution.
  2489. X
  2490. X    A separate license is available for commercial distribution,
  2491. X    for information on which you should contact the author.
  2492. X
  2493. X***************************************************************/
  2494. X
  2495. X#include <stdio.h>
  2496. X
  2497. X#include "bwbasic.h"
  2498. X#include "bwb_mes.h"
  2499. X
  2500. X#if HAVE_LONGJMP
  2501. X#include <setjmp.h>
  2502. X#endif
  2503. X
  2504. Xextern int prn_col;
  2505. X#if HAVE_LONGJMP
  2506. Xextern jmp_buf mark;
  2507. X#endif
  2508. X
  2509. X/***************************************************************
  2510. X
  2511. X        FUNCTION:       main()
  2512. X
  2513. X        DESCRIPTION:    As in any C program, main() is the basic
  2514. X                        function from which the rest of the
  2515. X                        program is called. Some environments,
  2516. X            however, provide their own main() functions
  2517. X            (Microsoft Windows (tm) is an example).
  2518. X            In these cases, the following code will
  2519. X            have to be included in the initialization
  2520. X            function that is called by the environment.
  2521. X
  2522. X***************************************************************/
  2523. X
  2524. X#if ANSI_C
  2525. Xvoid
  2526. Xmain( int argc, char **argv )
  2527. X#else
  2528. Xmain( argc, argv )
  2529. X   int argc;
  2530. X   char **argv;
  2531. X#endif
  2532. X   {
  2533. X
  2534. X   bwb_init( argc, argv );
  2535. X
  2536. X#if HAVE_LONGJMP
  2537. X#if INTERACTIVE
  2538. X   setjmp( mark );
  2539. X#endif
  2540. X#endif
  2541. X
  2542. X   /* main program loop */
  2543. X
  2544. X   while( !feof( stdin ) )        /* condition !feof( stdin ) added in v1.11 */
  2545. X      {
  2546. X      bwb_mainloop();
  2547. X      }
  2548. X
  2549. X      bwx_terminate();            /* allow ^D (Unix) exit with grace */
  2550. X
  2551. X
  2552. X   }
  2553. X
  2554. X/***************************************************************
  2555. X
  2556. X        FUNCTION:       bwx_signon()
  2557. X
  2558. X    DESCRIPTION:    This function prints out the sign-on
  2559. X            message for bwBASIC.
  2560. X
  2561. X***************************************************************/
  2562. X
  2563. X#if ANSI_C
  2564. Xint
  2565. Xbwx_signon( void )
  2566. X#else
  2567. Xint
  2568. Xbwx_signon()
  2569. X#endif
  2570. X   {
  2571. X
  2572. X   sprintf( bwb_ebuf, "\r%s %s\n", MES_SIGNON, VERSION );
  2573. X   prn_xprintf( stdout, bwb_ebuf );
  2574. X   sprintf( bwb_ebuf, "\r%s\n", MES_COPYRIGHT );
  2575. X   prn_xprintf( stdout, bwb_ebuf );
  2576. X#if PERMANENT_DEBUG
  2577. X   sprintf( bwb_ebuf, "\r%s\n", "Debugging Mode" );
  2578. X   prn_xprintf( stdout, bwb_ebuf );
  2579. X#else
  2580. X   sprintf( bwb_ebuf, "\r%s\n", MES_LANGUAGE );
  2581. X   prn_xprintf( stdout, bwb_ebuf );
  2582. X#endif
  2583. X
  2584. X   return TRUE;
  2585. X
  2586. X   }
  2587. X
  2588. X/***************************************************************
  2589. X
  2590. X        FUNCTION:       bwx_message()
  2591. X
  2592. X    DESCRIPTION:    This function outputs a message to the
  2593. X            default output device.
  2594. X
  2595. X***************************************************************/
  2596. X
  2597. X#if ANSI_C
  2598. Xint
  2599. Xbwx_message( char *m )
  2600. X#else
  2601. Xint
  2602. Xbwx_message( m )
  2603. X   char *m;
  2604. X#endif
  2605. X   {
  2606. X
  2607. X#if INTENSIVE_DEBUG
  2608. X   fprintf( stderr, "<MES>" );
  2609. X#endif
  2610. X
  2611. X   prn_xprintf( stdout, m );
  2612. X
  2613. X   return TRUE;
  2614. X
  2615. X   }
  2616. X
  2617. X/***************************************************************
  2618. X
  2619. X        FUNCTION:       bwx_putc()
  2620. X
  2621. X    DESCRIPTION:    This function outputs a single character
  2622. X            to the default output device.
  2623. X
  2624. X***************************************************************/
  2625. X
  2626. X#if ANSI_C
  2627. Xint
  2628. Xbwx_putc( char c )
  2629. X#else
  2630. Xint
  2631. Xbwx_putc( c )
  2632. X   char c;
  2633. X#endif
  2634. X   {
  2635. X
  2636. X   return fputc( c, stdout );
  2637. X
  2638. X   }
  2639. X
  2640. X/***************************************************************
  2641. X
  2642. X        FUNCTION:       bwx_error()
  2643. X
  2644. X    DESCRIPTION:    This function outputs a message to the
  2645. X            default error-message device.
  2646. X
  2647. X***************************************************************/
  2648. X
  2649. X#if ANSI_C
  2650. Xint
  2651. Xbwx_errmes( char *m )
  2652. X#else
  2653. Xint
  2654. Xbwx_errmes( m )
  2655. X   char *m;
  2656. X#endif
  2657. X   {
  2658. X   static char tbuf[ MAXSTRINGSIZE + 1 ];    /* this memory should be
  2659. X                           permanent in case of memory
  2660. X                           overrun errors */
  2661. X
  2662. X   if (( prn_col != 1 ) && ( errfdevice == stderr ))
  2663. X      {
  2664. X      prn_xprintf( errfdevice, "\n" );
  2665. X      }
  2666. X   if ( CURTASK number == 0 )
  2667. X      {
  2668. X      sprintf( tbuf, "\n%s: %s\n", ERRD_HEADER, m );
  2669. X      }
  2670. X   else
  2671. X      {
  2672. X      sprintf( tbuf, "\n%s %d: %s\n", ERROR_HEADER, CURTASK number, m );
  2673. X      }
  2674. X
  2675. X#if INTENSIVE_DEBUG
  2676. X   fprintf( stderr, "<ERR>" );
  2677. X#endif
  2678. X
  2679. X   prn_xprintf( errfdevice, tbuf );
  2680. X
  2681. X   return TRUE;
  2682. X
  2683. X   }
  2684. X
  2685. X/***************************************************************
  2686. X
  2687. X        FUNCTION:       bwx_input()
  2688. X
  2689. X    DESCRIPTION:    This function outputs the string pointed
  2690. X            to by 'prompt', then inputs a character
  2691. X            string.
  2692. X
  2693. X***************************************************************/
  2694. X
  2695. X#if ANSI_C
  2696. Xint
  2697. Xbwx_input( char *prompt, char *buffer )
  2698. X#else
  2699. Xint
  2700. Xbwx_input( prompt, buffer )
  2701. X   char *prompt;
  2702. X   char *buffer;
  2703. X#endif
  2704. X   {
  2705. X
  2706. X#if INTENSIVE_DEBUG
  2707. X   fprintf( stderr, "<INP>" );
  2708. X#endif
  2709. X
  2710. X   prn_xprintf( stdout, prompt );
  2711. X
  2712. X   fgets( buffer, MAXREADLINESIZE, stdin );
  2713. X   * prn_getcol( stdout ) = 1;            /* reset column */
  2714. X
  2715. X   return TRUE;
  2716. X
  2717. X   }
  2718. X
  2719. X/***************************************************************
  2720. X
  2721. X        FUNCTION:       bwx_terminate()
  2722. X
  2723. X    DESCRIPTION:    This function terminates program execution.
  2724. X
  2725. X***************************************************************/
  2726. X
  2727. X#if ANSI_C
  2728. Xvoid
  2729. Xbwx_terminate( void )
  2730. X#else
  2731. Xvoid
  2732. Xbwx_terminate()
  2733. X#endif
  2734. X   {
  2735. X   exit( 0 );
  2736. X   }
  2737. X
  2738. X/***************************************************************
  2739. X
  2740. X    FUNCTION:       bwx_shell()
  2741. X
  2742. X    DESCRIPTION:    This function runs a shell program.
  2743. X
  2744. X***************************************************************/
  2745. X
  2746. X#if COMMAND_SHELL
  2747. X
  2748. X#if ANSI_C
  2749. Xextern int
  2750. Xbwx_shell( struct bwb_line *l )
  2751. X#else
  2752. Xextern int
  2753. Xbwx_shell( l )
  2754. X   struct bwb_line *l;
  2755. X#endif
  2756. X   {
  2757. X   static char *s_buffer;
  2758. X   static int init = FALSE;
  2759. X   static int position;
  2760. X
  2761. X   /* get memory for temporary buffer if necessary */
  2762. X
  2763. X   if ( init == FALSE )
  2764. X      {
  2765. X      init = TRUE;
  2766. X      if ( ( s_buffer = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  2767. X     {
  2768. X     bwb_error( err_getmem );
  2769. X     return FALSE;
  2770. X     }
  2771. X      }
  2772. X
  2773. X   /* get the first element and check for a line number */
  2774. X
  2775. X#if INTENSIVE_DEBUG
  2776. X   sprintf( bwb_ebuf, "in bwx_shell(): line buffer is <%s>.", l->buffer );
  2777. X   bwb_debug( bwb_ebuf );
  2778. X#endif
  2779. X
  2780. X   position = 0;
  2781. X   adv_element( l->buffer, &position, s_buffer );
  2782. X   if ( is_numconst( s_buffer ) != TRUE )                  /* not a line number */
  2783. X      {
  2784. X
  2785. X#if INTENSIVE_DEBUG
  2786. X      sprintf( bwb_ebuf, "in bwx_shell(): no line number, command <%s>.",
  2787. X     l->buffer );
  2788. X      bwb_debug( bwb_ebuf );
  2789. X#endif
  2790. X
  2791. X      if ( system( l->buffer ) == 0 )
  2792. X     {
  2793. X     return TRUE;
  2794. X     }
  2795. X      else
  2796. X     {
  2797. X     return FALSE;
  2798. X     }
  2799. X      }
  2800. X
  2801. X   else                                         /* advance past line number */
  2802. X      {
  2803. X      adv_ws( l->buffer, &position );           /* advance past whitespace */
  2804. X
  2805. X#if INTENSIVE_DEBUG
  2806. X      sprintf( bwb_ebuf, "in bwx_shell(): line number, command <%s>.",
  2807. X     l->buffer );
  2808. X      bwb_debug( bwb_ebuf );
  2809. X#endif
  2810. X
  2811. X      if ( system( &( l->buffer[ position ] ) ) == 0 )
  2812. X     {
  2813. X     return TRUE;
  2814. X     }
  2815. X      else
  2816. X     {
  2817. X     return FALSE;
  2818. X     }
  2819. X      }
  2820. X   }
  2821. X#endif
  2822. X
  2823. X/***************************************************************
  2824. X
  2825. X        FUNCTION:       matherr()
  2826. X
  2827. X        DESCRIPTION:    This function is called to handle math
  2828. X                        errors in Bywater BASIC.  It displays
  2829. X                        the error message, then calls the
  2830. X                        break_handler() routine.
  2831. X
  2832. X***************************************************************/
  2833. X
  2834. X#if ANSI_C
  2835. Xint
  2836. Xmatherr( struct exception *except )
  2837. X#else
  2838. Xint
  2839. Xmatherr( except )
  2840. X   struct exception *except;
  2841. X#endif
  2842. X   {
  2843. X
  2844. X   perror( MATHERR_HEADER );
  2845. X   break_handler();
  2846. X
  2847. X   return FALSE;
  2848. X   }
  2849. X
  2850. X#if COMMON_CMDS
  2851. X
  2852. X/***************************************************************
  2853. X
  2854. X        FUNCTION:       bwb_edit()
  2855. X
  2856. X    DESCRIPTION:    This function implements the BASIC EDIT
  2857. X            program by shelling out to a default editor
  2858. X            specified by the variable BWB.EDITOR$.
  2859. X
  2860. X    SYNTAX:        EDIT
  2861. X
  2862. X***************************************************************/
  2863. X
  2864. X#if ANSI_C
  2865. Xstruct bwb_line *
  2866. Xbwb_edit( struct bwb_line *l )
  2867. X#else
  2868. Xstruct bwb_line *
  2869. Xbwb_edit( l )
  2870. X   struct bwb_line *l;
  2871. X#endif
  2872. X   {
  2873. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  2874. X   char edname[ MAXSTRINGSIZE + 1 ];
  2875. X   struct bwb_variable *ed;
  2876. X   FILE *loadfile;
  2877. X
  2878. X   ed = var_find( DEFVNAME_EDITOR );
  2879. X   str_btoc( edname, var_getsval( ed ));
  2880. X
  2881. X   sprintf( tbuf, "%s %s", edname, CURTASK progfile );
  2882. X
  2883. X#if INTENSIVE_DEBUG
  2884. X   sprintf( bwb_ebuf, "in bwb_edit(): command line <%s>", tbuf );
  2885. X   bwb_debug( bwb_ebuf );
  2886. X#else
  2887. X   system( tbuf );
  2888. X#endif
  2889. X
  2890. X   /* clear current contents */
  2891. X
  2892. X   bwb_new( l );
  2893. X
  2894. X   /* open edited file for read */
  2895. X
  2896. X   if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL )
  2897. X      {
  2898. X      sprintf( bwb_ebuf, err_openfile, CURTASK progfile );
  2899. X      bwb_error( bwb_ebuf );
  2900. X
  2901. X      return bwb_zline( l );
  2902. X      }
  2903. X
  2904. X   /* and (re)load the file into memory */
  2905. X
  2906. X   bwb_fload( loadfile );
  2907. X
  2908. X
  2909. X   return bwb_zline( l );
  2910. X   }
  2911. X
  2912. X/***************************************************************
  2913. X
  2914. X        FUNCTION:       bwb_files()
  2915. X
  2916. X    DESCRIPTION:    This function implements the BASIC FILES
  2917. X            command, in this case by shelling out to
  2918. X            a directory listing program or command
  2919. X            specified in the variable BWB.FILES$.
  2920. X
  2921. X    SYNTAX:        FILES filespec$
  2922. X
  2923. X***************************************************************/
  2924. X
  2925. X#if ANSI_C
  2926. Xstruct bwb_line *
  2927. Xbwb_files( struct bwb_line *l )
  2928. X#else
  2929. Xstruct bwb_line *
  2930. Xbwb_files( l )
  2931. X   struct bwb_line *l;
  2932. X#endif
  2933. X   {
  2934. X   char tbuf[ MAXVARNAMESIZE + 1 ];
  2935. X   char finame[ MAXVARNAMESIZE + 1 ];
  2936. X   char argument[ MAXVARNAMESIZE + 1 ];
  2937. X   struct bwb_variable *fi;
  2938. X   struct exp_ese *e;
  2939. X
  2940. X   fi = var_find( DEFVNAME_FILES );
  2941. X   str_btoc( finame, var_getsval( fi ));
  2942. X
  2943. X   /* get argument */
  2944. X
  2945. X   adv_ws( l->buffer, &( l->position ));
  2946. X   switch( l->buffer[ l->position ] )
  2947. X      {
  2948. X      case '\0':
  2949. X      case '\r':
  2950. X      case '\n':
  2951. X         argument[ 0 ] = '\0';
  2952. X         break;
  2953. X      default:
  2954. X         e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  2955. X         if ( e->type != STRING )
  2956. X            {
  2957. X            bwb_error( err_mismatch );
  2958. X            return bwb_zline( l );
  2959. X            }
  2960. X         str_btoc( argument, exp_getsval( e ) );
  2961. X         break;
  2962. X      }
  2963. X
  2964. X
  2965. X   sprintf( tbuf, "%s %s", finame, argument );
  2966. X
  2967. X#if INTENSIVE_DEBUG
  2968. X   sprintf( bwb_ebuf, "in bwb_files(): command line <%s>", tbuf );
  2969. X   bwb_debug( bwb_ebuf );
  2970. X#else
  2971. X   system( tbuf );
  2972. X#endif
  2973. X
  2974. X   return bwb_zline( l );
  2975. X
  2976. X   }
  2977. X
  2978. X#endif                    /* COMMON_CMDS */
  2979. X
  2980. END_OF_FILE
  2981.   if test 10751 -ne `wc -c <'bwbasic-2.10/bwx_tty.c'`; then
  2982.     echo shar: \"'bwbasic-2.10/bwx_tty.c'\" unpacked with wrong size!
  2983.   fi
  2984.   # end of 'bwbasic-2.10/bwx_tty.c'
  2985. fi
  2986. echo shar: End of archive 2 \(of 15\).
  2987. cp /dev/null ark2isdone
  2988. MISSING=""
  2989. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  2990.     if test ! -f ark${I}isdone ; then
  2991.     MISSING="${MISSING} ${I}"
  2992.     fi
  2993. done
  2994. if test "${MISSING}" = "" ; then
  2995.     echo You have unpacked all 15 archives.
  2996.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2997. else
  2998.     echo You still must unpack the following archives:
  2999.     echo "        " ${MISSING}
  3000. fi
  3001. exit 0
  3002. exit 0 # Just in case...
  3003.