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

  1. Newsgroups: comp.sources.misc
  2. From: tcamp@delphi.com (Ted A. Campbell)
  3. Subject: v40i066:  bwbasic - Bywater BASIC interpreter version 2.10, Part15/15
  4. Message-ID: <1993Oct29.162837.4397@sparky.sterling.com>
  5. X-Md4-Signature: 72b99ca6c5a744bf18c52a1d48ecf366
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Fri, 29 Oct 1993 16:28:37 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: tcamp@delphi.com (Ted A. Campbell)
  12. Posting-number: Volume 40, Issue 66
  13. Archive-name: bwbasic/part15
  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/bwbasic.c
  22. # Wrapped by kent@sparky on Thu Oct 21 10:47:52 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 15 (of 15)."'
  26. if test -f 'bwbasic-2.10/bwbasic.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'bwbasic-2.10/bwbasic.c'\"
  28. else
  29.   echo shar: Extracting \"'bwbasic-2.10/bwbasic.c'\" \(32822 characters\)
  30.   sed "s/^X//" >'bwbasic-2.10/bwbasic.c' <<'END_OF_FILE'
  31. X/***************************************************************
  32. X
  33. X        bwbasic.c       Main Program File
  34. X                        for Bywater BASIC Interpreter
  35. X
  36. X                        Copyright (c) 1993, Ted A. Campbell
  37. X                        Bywater Software
  38. X
  39. X            "I was no programmer, neither was I a
  40. X            programmer's son; but I was an herdman
  41. X            and a gatherer of sycomore fruit."
  42. X                 - Amos 7:14b AV, slightly adapted
  43. X
  44. X                        email: tcamp@delphi.com
  45. X
  46. X        Copyright and Permissions Information:
  47. X
  48. X        All U.S. and international rights are claimed by the author,
  49. X        Ted A. Campbell.
  50. X
  51. X    This software is released under the terms of the GNU General
  52. X    Public License (GPL), which is distributed with this software
  53. X    in the file "COPYING".  The GPL specifies the terms under
  54. X    which users may copy and use the software in this distribution.
  55. X
  56. X    A separate license is available for commercial distribution,
  57. X    for information on which you should contact the author.
  58. X
  59. X***************************************************************/
  60. X
  61. X#include <stdio.h>
  62. X#include <ctype.h>
  63. X#include <math.h>
  64. X
  65. X#include "bwbasic.h"
  66. X#include "bwb_mes.h"
  67. X
  68. X#if HAVE_SIGNAL
  69. X#include <signal.h>
  70. X#endif
  71. X
  72. X#if HAVE_LONGJUMP
  73. X#include <setjmp.h>
  74. X#endif
  75. X
  76. Xchar *bwb_ebuf;                /* error buffer */
  77. Xstatic char *read_line;
  78. Xint bwb_trace = FALSE;
  79. XFILE *errfdevice = stderr;              /* output device for error messages */
  80. X
  81. X#if HAVE_LONGJUMP
  82. Xjmp_buf mark;
  83. X#endif
  84. X
  85. Xstatic int program_run = 0;        /* has the command-line program been run? */
  86. Xint bwb_curtask = 0;            /* current task */
  87. X
  88. Xstruct bwb_variable *ed;                /* BWB.EDITOR$ variable */
  89. Xstruct bwb_variable *fi;                /* BWB.FILES$ variable */
  90. Xstruct bwb_variable *pr;                /* BWB.PROMPT$ variable */
  91. Xstruct bwb_variable *im;                /* BWB.IMPLEMENTATION$ variable */
  92. Xstruct bwb_variable *co;                /* BWB.COLORS variable */
  93. X
  94. X#if PARACT
  95. Xstruct bwb_task *bwb_tasks[ TASKS ];    /* table of task pointers */
  96. X#else
  97. Xchar progfile[ MAXARGSIZE ];        /* program file */
  98. Xint rescan = TRUE;                      /* program needs to be rescanned */
  99. Xint number = 0;                /* current line number */
  100. Xstruct bwb_line *bwb_l;            /* current line pointer */
  101. Xstruct bwb_line bwb_start;        /* starting line marker */
  102. Xstruct bwb_line bwb_end;        /* ending line marker */
  103. Xstruct bwb_line *data_line;         /* current line to read data */
  104. Xint data_pos = 0;                       /* position in data_line */
  105. Xstruct bwb_variable var_start;        /* variable list start marker */
  106. Xstruct bwb_variable var_end;        /* variable list end marker */
  107. Xstruct bwb_function fnc_start;        /* function list start marker */
  108. Xstruct bwb_function fnc_end;        /* function list end marker */
  109. Xstruct fslte fslt_start;        /* function-sub-label lookup table start marker */
  110. Xstruct fslte fslt_end;            /* function-sub-label lookup table end marker */
  111. Xint exsc = -1;                /* EXEC stack counter */
  112. Xint expsc = 0;                /* expression stack counter */
  113. Xint xtxtsc = 0;                /* eXecute TeXT stack counter */
  114. Xstruct exse *excs;            /* EXEC stack */
  115. Xstruct exp_ese *exps;            /* Expression stack */
  116. Xstruct xtxtsl *xtxts;                   /* Execute Text stack */
  117. X#endif
  118. X
  119. X/* Prototypes for functions visible only to this file */
  120. X
  121. X#if ANSI_C
  122. Xextern int is_ln( char *buffer );
  123. X#else
  124. Xextern int is_ln();
  125. X#endif
  126. X
  127. X/***************************************************************
  128. X
  129. X        FUNCTION:       bwb_init()
  130. X
  131. X        DESCRIPTION:    This function initializes bwBASIC.
  132. X
  133. X***************************************************************/
  134. X
  135. Xvoid
  136. X#if ANSI_C
  137. Xbwb_init( int argc, char **argv )
  138. X#else
  139. Xbwb_init( argc, argv )
  140. X   int argc;
  141. X   char **argv;
  142. X#endif
  143. X   {
  144. X   static FILE *input = NULL;
  145. X   register int n;
  146. X#if PROFILE
  147. X   struct bwb_variable *v;
  148. X#endif
  149. X#if REDIRECT_STDERR
  150. X   FILE *newerr;
  151. X#endif
  152. X#if PROFILE
  153. X   FILE *profile;
  154. X#endif
  155. X#if PARACT
  156. X#else
  157. X   static char start_buf[] = "\0";
  158. X   static char end_buf[] = "\0";
  159. X#endif
  160. X
  161. X#if INTENSIVE_DEBUG
  162. X   prn_xprintf( stderr, "Memory Allocation Statistics:\n" );
  163. X   prn_xprintf( stderr, "----------------------------\n" );
  164. X#if PARACT
  165. X   sprintf( bwb_ebuf, "task structure:   %ld bytes\n",
  166. X      (long) sizeof( struct bwb_task ) );
  167. X   prn_xprintf( stderr, bwb_ebuf );
  168. X   getchar();
  169. X#endif
  170. X#endif
  171. X
  172. X   /* set all task pointers to NULL */
  173. X
  174. X#if PARACT
  175. X
  176. X   for ( n = 0; n < TASKS; ++n )
  177. X      {
  178. X      bwb_tasks[ n ] = NULL;
  179. X      }
  180. X
  181. X#else
  182. X
  183. X   /* Memory allocation */
  184. X   /* eXecute TeXT stack */
  185. X
  186. X   if ( ( xtxts = calloc( XTXTSTACKSIZE, sizeof( struct xtxtsl ) ) ) == NULL )
  187. X      {
  188. X#if PROG_ERRORS
  189. X      bwb_error( "in bwb_init(): failed to find memory for xtxts" );
  190. X#else
  191. X      bwb_error( err_getmem );
  192. X#endif
  193. X      }
  194. X
  195. X   /* expression stack */
  196. X
  197. X   if ( ( exps = calloc( ESTACKSIZE, sizeof( struct exp_ese ) ) ) == NULL )
  198. X      {
  199. X#if PROG_ERRORS
  200. X      bwb_error( "in bwb_init(): failed to find memory for exps" );
  201. X#else
  202. X      bwb_error( err_getmem );
  203. X#endif
  204. X      }
  205. X
  206. X   /* EXEC stack */
  207. X
  208. X   if ( ( excs = calloc( EXECLEVELS, sizeof( struct exse ) ) ) == NULL )
  209. X      {
  210. X#if PROG_ERRORS
  211. X      bwb_error( "in bwb_init(): failed to find memory for excs" );
  212. X#else
  213. X      bwb_error( err_getmem );
  214. X#endif
  215. X      }
  216. X
  217. X   /* initialize tables of variables, functions */
  218. X
  219. X   bwb_start.number = 0;
  220. X   bwb_start.next = &bwb_end;
  221. X   bwb_end.number = MAXLINENO + 1;
  222. X   bwb_end.next = &bwb_end;
  223. X   bwb_start.buffer = start_buf;
  224. X   bwb_end.buffer = end_buf;
  225. X   data_line = &bwb_start;
  226. X   data_pos = 0;
  227. X   exsc = -1;
  228. X   expsc = 0;
  229. X   xtxtsc = 0;
  230. X   bwb_start.position = 0;
  231. X   bwb_l = &bwb_start; 
  232. X
  233. X   var_init( 0 );
  234. X   fnc_init( 0 );
  235. X   fslt_init( 0 );
  236. X
  237. X#endif
  238. X
  239. X   /* character buffers */
  240. X
  241. X   if ( ( bwb_ebuf = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
  242. X      {
  243. X#if PROG_ERRORS
  244. X      bwb_error( "in bwb_init(): failed to find memory for bwb_ebuf" );
  245. X#else
  246. X      bwb_error( err_getmem );
  247. X#endif
  248. X      }
  249. X   if ( ( read_line = calloc( MAXREADLINESIZE + 1, sizeof(char) ) ) == NULL )
  250. X      {
  251. X#if PROG_ERRORS
  252. X      bwb_error( "in bwb_init(): failed to find memory for read_line" );
  253. X#else
  254. X      bwb_error( err_getmem );
  255. X#endif
  256. X      }
  257. X
  258. X#if PARACT
  259. X
  260. X   /* request task 0 as current (base) task */
  261. X
  262. X   bwb_curtask = bwb_newtask( 0 );
  263. X
  264. X   if ( bwb_curtask == -1 )
  265. X      {
  266. X      return;                /* error message has already been called*/
  267. X      }
  268. X
  269. X#endif
  270. X
  271. X#if TEST_BSTRING
  272. X   for ( n = 0; n < ESTACKSIZE; ++n )
  273. X      {
  274. X      sprintf( CURTASK exps[ n ].sval.name, "<Exp stack bstring %d>", n );
  275. X      }
  276. X#endif
  277. X
  278. X   /* assign memory for the device table */
  279. X
  280. X#if COMMON_CMDS
  281. X   if ( ( dev_table = calloc( DEF_DEVICES, sizeof( struct dev_element ) ) ) == NULL )
  282. X      {
  283. X#if PROG_ERRORS
  284. X      bwb_error( "in bwb_init(): failed to find memory for dev_table" );
  285. X#else
  286. X      bwb_error( err_getmem );
  287. X#endif
  288. X      bwx_terminate();
  289. X      }
  290. X
  291. X   /* initialize all devices to DEVMODE_AVAILABLE */
  292. X
  293. X   for ( n = 0; n < DEF_DEVICES; ++n )
  294. X      {
  295. X      dev_table[ n ].mode = DEVMODE_AVAILABLE;
  296. X      dev_table[ n ].reclen = -1;
  297. X      dev_table[ n ].cfp = NULL;
  298. X      dev_table[ n ].buffer = NULL;
  299. X      dev_table[ n ].width = DEF_WIDTH;
  300. X      dev_table[ n ].col = 1;
  301. X      }
  302. X#endif            /* COMMON_CMDS */
  303. X
  304. X   /* initialize preset variables */
  305. X
  306. X   ed = var_find( DEFVNAME_EDITOR );
  307. X   ed->preset = TRUE;
  308. X   ed->common = TRUE;
  309. X   str_ctob( var_findsval( ed, ed->array_pos ), DEF_EDITOR );
  310. X
  311. X   fi = var_find( DEFVNAME_FILES );
  312. X   fi->preset = TRUE;
  313. X   fi->common = TRUE;
  314. X   str_ctob( var_findsval( fi, fi->array_pos ), DEF_FILES );
  315. X
  316. X   pr = var_find( DEFVNAME_PROMPT );
  317. X   pr->preset = TRUE;
  318. X   pr->common = TRUE;
  319. X   str_ctob( var_findsval( pr, pr->array_pos ), PROMPT );
  320. X
  321. X   im = var_find( DEFVNAME_IMPL );
  322. X   im->preset = TRUE;
  323. X   im->common = TRUE;
  324. X   str_ctob( var_findsval( im, im->array_pos ), IMP_IDSTRING );
  325. X
  326. X   co = var_find( DEFVNAME_COLORS );
  327. X   co->preset = TRUE;
  328. X   co->common = TRUE;
  329. X   * var_findnval( co, co->array_pos ) = (bnumber) DEF_COLORS;
  330. X
  331. X   /* Signon message */
  332. X
  333. X   bwx_signon();
  334. X
  335. X   /* Redirect stderr if specified */
  336. X
  337. X#if REDIRECT_STDERR
  338. X   newerr = freopen( ERRFILE, "w", stderr );
  339. X   if ( newerr == NULL )
  340. X      {
  341. X      sprintf( bwb_ebuf, "Failed to redirect error messages to file <%s>\n",
  342. X         ERRFILE );
  343. X      errfdevice = stdout;
  344. X      prn_xprintf( errfdevice, bwb_ebuf );
  345. X      }
  346. X   else
  347. X      {
  348. X      sprintf( bwb_ebuf, "NOTE: Error messages are redirected to file <%s>\n",
  349. X         ERRFILE );
  350. X      prn_xprintf( errfdevice, bwb_ebuf );
  351. X      errfdevice = stderr;
  352. X      }
  353. X#else
  354. X   errfdevice = stdout;
  355. X#endif
  356. X
  357. X   /* if there is a profile.bas, execute it */
  358. X
  359. X#if PROFILE
  360. X   if ( ( profile = fopen( PROFILENAME, "r" )) != NULL )
  361. X      {
  362. X      bwb_fload( profile );    /* load profile */
  363. X      bwb_run( &CURTASK bwb_start );    /* run profile */
  364. X
  365. X      /* profile must be run immediately, not by scheduler */
  366. X
  367. X      while ( CURTASK exsc > -1 )
  368. X           {
  369. X           bwb_execline();
  370. X           }
  371. X
  372. X      /* mark all profiled variables as preset */
  373. X
  374. X      for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  375. X         {
  376. X
  377. X#if INTENSIVE_DEBUG
  378. X         sprintf( bwb_ebuf, "in bwb_init(): marked variable <%s> preset TRUE",
  379. X            v->name );
  380. X         bwb_debug( bwb_ebuf );
  381. X#endif
  382. X
  383. X         v->preset = TRUE;
  384. X         }
  385. X
  386. X      bwb_new( &CURTASK bwb_start );     /* remove profile from memory */
  387. X      }
  388. X#endif
  389. X
  390. X#if INTENSIVE_DEBUG
  391. X   sprintf( bwb_ebuf, "in main(): Ready to save jump MARKER" );
  392. X   bwb_debug( bwb_ebuf );
  393. X#endif
  394. X
  395. X   /* set a buffer for jump: program execution returns to this point
  396. X      in case of a jump (error, interrupt, or finish program) */
  397. X
  398. X#if INTERACTIVE
  399. X
  400. X#if HAVE_SIGNAL
  401. X   signal( SIGINT, break_mes );
  402. X#endif
  403. X
  404. X#if HAVE_LONGJUMP
  405. X   setjmp( mark );
  406. X#endif
  407. X
  408. X#if INTENSIVE_DEBUG
  409. X   sprintf( bwb_ebuf, "in bwb_init(): Return from jump MARKER, program run <%d>",
  410. X      program_run + 1 );
  411. X   bwb_debug( bwb_ebuf );
  412. X   getchar();
  413. X#endif
  414. X
  415. X   /* if INTERACTIVE is FALSE, then we must have a program file */
  416. X
  417. X#else
  418. X
  419. X   if ( argc < 2 )
  420. X      {
  421. X      bwb_error( err_noprogfile );
  422. X      }
  423. X
  424. X#endif                /* INTERACTIVE */
  425. X
  426. X   /* check to see if there is a program file: but do this only the first
  427. X      time around! */
  428. X
  429. X   ++program_run;
  430. X   if (( argc > 1 ) && ( program_run == 1 ))
  431. X      {
  432. X      if ( ( input = fopen( argv[ 1 ], "r" )) == NULL )
  433. X         {
  434. X         strcpy( CURTASK progfile, argv[ 1 ] );
  435. X         strcat( CURTASK progfile, ".bas" );
  436. X         if ( ( input = fopen( CURTASK progfile, "r" )) == NULL )
  437. X            {
  438. X            CURTASK progfile[ 0 ] = 0;
  439. X            sprintf( bwb_ebuf, err_openfile, argv[ 1 ] );
  440. X            bwb_error( bwb_ebuf );
  441. X            }
  442. X         }
  443. X      if ( input != NULL )
  444. X         {
  445. X         strcpy( CURTASK progfile, argv[ 1 ] );
  446. X#if INTENSIVE_DEBUG
  447. X         sprintf( bwb_ebuf, "in main(): progfile is <%s>.", CURTASK progfile );
  448. X         bwb_debug( bwb_ebuf );
  449. X#endif
  450. X
  451. X         bwb_fload( input );
  452. X         bwb_run( &CURTASK bwb_start );
  453. X         }
  454. X      }
  455. X
  456. X   }
  457. X
  458. X/***************************************************************
  459. X
  460. X        FUNCTION:       bwb_interact()
  461. X
  462. X        DESCRIPTION:     This function gets a line from the user
  463. X            and processes it.
  464. X
  465. X***************************************************************/
  466. X
  467. X#if INTERACTIVE
  468. Xint
  469. X#if ANSI_C
  470. Xbwb_interact( void )
  471. X#else
  472. Xbwb_interact()
  473. X#endif
  474. X   {
  475. X
  476. X#if INTENSIVE_DEBUG
  477. X   sprintf( bwb_ebuf, "in bwb_interact(): ready to read from keyboard" );
  478. X   bwb_debug( bwb_ebuf );
  479. X#endif
  480. X
  481. X   /* take input from keyboard */
  482. X
  483. X   bwb_gets( read_line );
  484. X
  485. X   /* If there is no line number, execute the line as received */
  486. X
  487. X   if ( is_ln( read_line ) == FALSE )
  488. X      {
  489. X      bwb_xtxtline( read_line );
  490. X      }
  491. X
  492. X   /* If there is a line number, add the line to the file in memory */
  493. X
  494. X   else
  495. X      {
  496. X      bwb_ladd( read_line, TRUE );
  497. X#if INTENSIVE_DEBUG
  498. X      bwb_debug( "Return from bwb_ladd()" );
  499. X#endif
  500. X      }
  501. X
  502. X   return TRUE;
  503. X
  504. X   }
  505. X
  506. X#endif                /* INTERACTIVE == TRUE */
  507. X
  508. X/***************************************************************
  509. X
  510. X        FUNCTION:       bwb_fload()
  511. X
  512. X        DESCRIPTION:     This function loads a BASIC program
  513. X            file into memory given a FILE pointer.
  514. X
  515. X***************************************************************/
  516. X
  517. Xint
  518. X#if ANSI_C
  519. Xbwb_fload( FILE *file )
  520. X#else
  521. Xbwb_fload( file )
  522. X   FILE *file;
  523. X#endif
  524. X   {
  525. X
  526. X   while ( feof( file ) == FALSE )
  527. X      {
  528. X      read_line[ 0 ] = '\0';
  529. X      fgets( read_line, MAXREADLINESIZE, file );
  530. X      if ( file == stdin )
  531. X         {
  532. X         * prn_getcol( stdout ) = 1;        /* reset column */
  533. X         }
  534. X      bwb_stripcr( read_line );
  535. X
  536. X      /* be sure that this is not EOF with a NULL line */
  537. X
  538. X      if (( feof( file ) == FALSE ) || ( strlen( read_line ) > 0 ))
  539. X     {
  540. X     bwb_ladd( read_line, FALSE );
  541. X     }
  542. X      }
  543. X
  544. X   /* close file stream */
  545. X
  546. X   fclose( file );
  547. X
  548. X   return TRUE;
  549. X   }
  550. X
  551. X/***************************************************************
  552. X
  553. X        FUNCTION:       bwb_ladd()
  554. X
  555. X        DESCRIPTION:    This function adds a new line (in the
  556. X                        buffer) to the program in memory.
  557. X
  558. X***************************************************************/
  559. X
  560. Xint
  561. X#if ANSI_C
  562. Xbwb_ladd( char *buffer, int replace )
  563. X#else
  564. Xbwb_ladd( buffer, replace )
  565. X   char *buffer;
  566. X   int replace;
  567. X#endif
  568. X   {
  569. X   struct bwb_line *l, *previous, *p;
  570. X   static char *s_buffer;
  571. X   static int init = FALSE;
  572. X   static int prev_num = 0;
  573. X   char *newbuffer;
  574. X
  575. X#if INTENSIVE_DEBUG
  576. X   sprintf( bwb_ebuf, "in bwb_ladd(): add line <%s>",
  577. X      buffer );
  578. X   bwb_debug( bwb_ebuf );
  579. X#endif
  580. X
  581. X   /* get memory for temporary buffer if necessary */
  582. X
  583. X   if ( init == FALSE )
  584. X      {
  585. X      init = TRUE;
  586. X      if ( ( s_buffer = calloc( (size_t) MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  587. X     {
  588. X#if PROG_ERRORS
  589. X     bwb_error( "in bwb_ladd(): failed to find memory for s_buffer" );
  590. X#else
  591. X     bwb_error( err_getmem );
  592. X#endif
  593. X     return FALSE;
  594. X         }
  595. X      }
  596. X
  597. X#if INTENSIVE_DEBUG
  598. X   sprintf( bwb_ebuf, "in bwb_ladd(): s_buffer initialized " );
  599. X   bwb_debug( bwb_ebuf );
  600. X#endif
  601. X
  602. X   /* get memory for this line */
  603. X
  604. X   if ( ( l = (struct bwb_line *) calloc( (size_t) 1, sizeof( struct bwb_line ) )) == NULL )
  605. X      {
  606. X#if PROG_ERRORS
  607. X      bwb_error( "in bwb_ladd(): failed to find memory for new line" );
  608. X#else
  609. X      bwb_error( err_getmem );
  610. X#endif
  611. X      return FALSE;
  612. X      }
  613. X
  614. X#if INTENSIVE_DEBUG
  615. X   sprintf( bwb_ebuf, "in bwb_ladd(): got memory." );
  616. X   bwb_debug( bwb_ebuf );
  617. X#endif
  618. X
  619. X   /* note that line is not yet marked and the program must be rescanned */
  620. X
  621. X   l->marked = FALSE;
  622. X   CURTASK rescan = TRUE;        /* program needs to be scanned again */
  623. X   l->xnum = FALSE;
  624. X
  625. X   /* get the first element and test for a line number */
  626. X
  627. X   adv_element( buffer, &( l->position ), s_buffer );
  628. X
  629. X   /* set line number in line structure */
  630. X
  631. X   if ( is_numconst( s_buffer ) == TRUE )
  632. X      {
  633. X
  634. X      l->number = atoi( s_buffer );
  635. X
  636. X#if INTENSIVE_DEBUG
  637. X      sprintf( bwb_ebuf, "in bwb_ladd(): line is numbered, number is <%d>",
  638. X     l->number );
  639. X      bwb_debug( bwb_ebuf );
  640. X#endif
  641. X
  642. X      prev_num = l->number;
  643. X      l->xnum = TRUE;
  644. X      ++( l->position );
  645. X      newbuffer = &( buffer[ l->position ] );
  646. X
  647. X      /* allocate memory and assign buffer to line buffer */
  648. X
  649. X      ln_asbuf( l, newbuffer );
  650. X
  651. X      }
  652. X
  653. X   /* There is not a line number */
  654. X
  655. X   else
  656. X      {
  657. X
  658. X#if INTENSIVE_DEBUG
  659. X      sprintf( bwb_ebuf, "in bwb_ladd(): line is not numbered, using prev <%d>",
  660. X         prev_num );
  661. X      bwb_debug( bwb_ebuf );
  662. X#endif
  663. X
  664. X      newbuffer = buffer;
  665. X
  666. X      /* allocate memory and assign buffer to line buffer */
  667. X
  668. X      ln_asbuf( l, newbuffer );
  669. X
  670. X      l->xnum = FALSE;
  671. X      l->number = prev_num;
  672. X      }
  673. X
  674. X   /* find the place of the current line */
  675. X
  676. X   for ( previous = &CURTASK bwb_start; previous != &CURTASK bwb_end; previous = previous->next )
  677. X      {
  678. X
  679. X      /* replace a previously existing line */
  680. X
  681. X      if ( ( l->xnum == TRUE )
  682. X         && ( previous->number == l->number )
  683. X     && ( replace == TRUE )
  684. X     )
  685. X         {
  686. X
  687. X#if INTENSIVE_DEBUG
  688. X         sprintf( bwb_ebuf, "in bwb_ladd(): writing to previous number <%d>",
  689. X            l->number );
  690. X         bwb_debug( bwb_ebuf );
  691. X#endif
  692. X
  693. X         /* allocate memory and assign buffer to line buffer */
  694. X
  695. X     ln_asbuf( previous, newbuffer );
  696. X
  697. X         /* free the current line */
  698. X
  699. X         free( l );
  700. X
  701. X         /* and return */
  702. X
  703. X         return TRUE;
  704. X
  705. X         }
  706. X
  707. X      /* add after previously existing line: this is to allow unnumbered
  708. X         lines that follow in sequence after a previously numbered line */
  709. X
  710. X      else if (( previous->number == l->number )
  711. X     && ( replace == FALSE )
  712. X     )
  713. X         {
  714. X#if INTENSIVE_DEBUG
  715. X     sprintf( bwb_ebuf, "in bwb_ladd(): adding doubled number <%d>",
  716. X        l->number );
  717. X     bwb_debug( bwb_ebuf);
  718. X#endif
  719. X
  720. X         /* if there are multiple instances of this particular line number,
  721. X            then it is incumbent upon us to find the very last one */
  722. X
  723. X         for ( p = previous; p->number == l->number; p = p->next )
  724. X            {
  725. X#if INTENSIVE_DEBUG
  726. X        bwb_debug( "in bwb_ladd(): advancing..." );
  727. X#endif
  728. X            previous = p;
  729. X            }
  730. X
  731. X         l->next = previous->next;
  732. X         previous->next = l;
  733. X         return TRUE;
  734. X         }
  735. X
  736. X      /* add a new line */
  737. X
  738. X      else if ( ( previous->number < l->number )
  739. X         && ( previous->next->number > l->number ))
  740. X         {
  741. X         l->next = previous->next;
  742. X         previous->next = l;
  743. X
  744. X#if INTENSIVE_DEBUG
  745. X     sprintf( bwb_ebuf, "in bwb_ladd(): added new line <%d> buffer <%s>",
  746. X        l->number, l->buffer );
  747. X     bwb_debug( bwb_ebuf );
  748. X#endif
  749. X
  750. X         return TRUE;
  751. X         }
  752. X
  753. X      }
  754. X
  755. X   /* attempt to link line number has failed; free memory */
  756. X
  757. X   free( l->buffer );
  758. X   free( l );
  759. X
  760. X   sprintf( bwb_ebuf, ERR_LINENO );
  761. X   bwb_error( bwb_ebuf );
  762. X
  763. X#if INTENSIVE_DEBUG
  764. X   sprintf( bwb_ebuf, "in bwb_ladd(): attempt to add line has failed" );
  765. X   bwb_debug( bwb_ebuf );
  766. X#endif
  767. X
  768. X   return FALSE;
  769. X
  770. X   }
  771. X
  772. X/***************************************************************
  773. X
  774. X        FUNCTION:       bwb_xtxtline()
  775. X
  776. X        DESCRIPTION:    This function executes a text line, i.e.,
  777. X                        places it in memory and then relinquishes
  778. X                        control.
  779. X
  780. X***************************************************************/
  781. X
  782. Xstruct bwb_line *
  783. X#if ANSI_C
  784. Xbwb_xtxtline( char *buffer )
  785. X#else
  786. Xbwb_xtxtline( buffer )
  787. X   char *buffer;
  788. X#endif
  789. X   {
  790. X   struct bwb_line *c;
  791. X   char *p;
  792. X   int loop;
  793. X
  794. X#if INTENSIVE_DEBUG
  795. X   sprintf( bwb_ebuf, "in bwb_xtxtline(): received <%s>", buffer );
  796. X   bwb_debug( bwb_ebuf );
  797. X#endif
  798. X
  799. X   /* increment xtxt stack counter */
  800. X
  801. X   if ( CURTASK xtxtsc >= XTXTSTACKSIZE )
  802. X      {
  803. X      sprintf( bwb_ebuf, "Exceeded maximum xtxt stack <%d>",
  804. X         CURTASK xtxtsc );
  805. X      return &CURTASK bwb_end;
  806. X      }
  807. X
  808. X   ++CURTASK xtxtsc;
  809. X
  810. X   /* advance past whitespace */
  811. X
  812. X   p = buffer;
  813. X   loop = TRUE;
  814. X   while( loop == TRUE )
  815. X      {
  816. X
  817. X      switch( *p )
  818. X         {
  819. X         case '\0':                     /* end of string */
  820. X
  821. X#if INTENSIVE_DEBUG
  822. X            sprintf( bwb_ebuf, "Null command line received." );
  823. X            bwb_debug( bwb_ebuf );
  824. X#endif
  825. X            --CURTASK xtxtsc;
  826. X            return &CURTASK bwb_end;
  827. X         case ' ':                      /* whitespace */
  828. X         case '\t':
  829. X            ++p;
  830. X            break;
  831. X         default:
  832. X            loop = FALSE;
  833. X            break;
  834. X         }
  835. X
  836. X      }
  837. X
  838. X#if INTENSIVE_DEBUG
  839. X   sprintf( bwb_ebuf, "in bwb_xtxtline(): ready to get memory" );
  840. X   bwb_debug( bwb_ebuf );
  841. X#endif
  842. X
  843. X   if ( CURTASK xtxts[ CURTASK xtxtsc ].l.buffer != NULL )
  844. X      {
  845. X#if INTENSIVE_DEBUG
  846. X      sprintf( bwb_ebuf, "in bwb_xtxtline(): freeing buffer memory" );
  847. X      bwb_debug( bwb_ebuf );
  848. X#endif
  849. X      free( CURTASK xtxts[ CURTASK xtxtsc ].l.buffer );
  850. X      }
  851. X
  852. X   /* copy the whole line to the line structure buffer */
  853. X
  854. X   ln_asbuf( &( CURTASK xtxts[ CURTASK xtxtsc ].l ), buffer );
  855. X
  856. X#if INTENSIVE_DEBUG
  857. X   sprintf( bwb_ebuf, "in bwb_xtxtline(): copied to line buffer <%s>.",
  858. X      CURTASK xtxts[ CURTASK xtxtsc ].l.buffer );
  859. X   bwb_debug( bwb_ebuf );
  860. X#endif
  861. X
  862. X   /* set line number in line structure */
  863. X
  864. X   CURTASK xtxts[ CURTASK xtxtsc ].l.number = 0;
  865. X   CURTASK xtxts[ CURTASK xtxtsc ].l.marked = FALSE;
  866. X
  867. X   /* execute the line as BASIC command line */
  868. X
  869. X   CURTASK xtxts[ CURTASK xtxtsc ].l.next = &CURTASK bwb_end;
  870. X   c = &( CURTASK xtxts[ CURTASK xtxtsc ].l );
  871. X   c->position = 0;
  872. X
  873. X#if THEOLDWAY
  874. X   do
  875. X      {
  876. X      c = bwb_xline( c );
  877. X      }
  878. X
  879. X   while( c != &CURTASK bwb_end );
  880. X#endif
  881. X
  882. X   bwb_incexec();        /* increment EXEC stack */
  883. X   bwb_setexec( c, 0, EXEC_NORM );        /* and set current line in it */
  884. X
  885. X   /* decrement xtxt stack counter ??? */
  886. X
  887. X   --CURTASK xtxtsc;
  888. X
  889. X   return c;
  890. X
  891. X   }
  892. X
  893. X/***************************************************************
  894. X
  895. X        FUNCTION:       bwb_incexec()
  896. X
  897. X        DESCRIPTION:    This function increments the EXEC
  898. X            stack counter.
  899. X
  900. X***************************************************************/
  901. X
  902. X#if ANSI_C
  903. Xextern void
  904. Xbwb_incexec( void )
  905. X   {
  906. X#else
  907. Xvoid
  908. Xbwb_incexec()
  909. X   {
  910. X#endif
  911. X   ++CURTASK exsc;
  912. X
  913. X   if ( CURTASK exsc >= EXECLEVELS )
  914. X      {
  915. X      --CURTASK exsc;
  916. X#if PROG_ERRORS
  917. X      sprintf( bwb_ebuf, "in bwb_incexec(): incremented EXEC stack past max <%d>",
  918. X         EXECLEVELS );
  919. X      bwb_error( bwb_ebuf );
  920. X#else
  921. X      bwb_error( err_overflow );
  922. X#endif
  923. X      }
  924. X
  925. X   CURTASK excs[ CURTASK exsc ].while_line = NULL;
  926. X   CURTASK excs[ CURTASK exsc ].wend_line  = NULL;
  927. X   CURTASK excs[ CURTASK exsc ].n_cvs = 0;
  928. X   CURTASK excs[ CURTASK exsc ].local_variable = NULL;
  929. X
  930. X   }
  931. X
  932. X/***************************************************************
  933. X
  934. X        FUNCTION:       bwb_decexec()
  935. X
  936. X        DESCRIPTION:    This function decrements the EXEC
  937. X            stack counter.
  938. X
  939. X***************************************************************/
  940. X
  941. X#if ANSI_C
  942. Xextern void
  943. Xbwb_decexec( void )
  944. X   {
  945. X#else
  946. Xvoid
  947. Xbwb_decexec()
  948. X   {
  949. X#endif
  950. X
  951. X   /* decrement the exec stack counter */
  952. X
  953. X   --CURTASK exsc;
  954. X
  955. X   if ( CURTASK exsc < -1 )
  956. X      {
  957. X      CURTASK exsc = -1;
  958. X#if PROG_ERRORS
  959. X      sprintf( bwb_ebuf, "in bwb_decexec(): decremented EXEC stack past min <-1>" );
  960. X      bwb_error( bwb_ebuf );
  961. X#else
  962. X      bwb_error( err_overflow );
  963. X#endif
  964. X      }
  965. X
  966. X   /* check for EXEC_ON and decrement recursively */
  967. X
  968. X   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_ON )
  969. X      {
  970. X
  971. X      free( CURTASK excs[ CURTASK exsc ].while_line->buffer );
  972. X      free( CURTASK excs[ CURTASK exsc ].while_line );
  973. X
  974. X      bwb_decexec();
  975. X      }
  976. X
  977. X   }
  978. X
  979. X/***************************************************************
  980. X
  981. X        FUNCTION:       bwb_setexec()
  982. X
  983. X        DESCRIPTION:    This function sets the line and position
  984. X            for the next call to bwb_execline();
  985. X
  986. X***************************************************************/
  987. X
  988. X#if ANSI_C
  989. Xextern int
  990. Xbwb_setexec( struct bwb_line *l, int position, int code )
  991. X   {
  992. X#else
  993. Xint
  994. Xbwb_setexec( l, position, code )
  995. X   struct bwb_line *l;
  996. X   int position;
  997. X   int code;
  998. X   {
  999. X#endif
  1000. X
  1001. X   CURTASK excs[ CURTASK exsc ].line = l;
  1002. X   CURTASK excs[ CURTASK exsc ].position = position;
  1003. X   CURTASK excs[ CURTASK exsc ].code = code;
  1004. X
  1005. X   return TRUE;
  1006. X
  1007. X   }
  1008. X
  1009. X/***************************************************************
  1010. X
  1011. X        FUNCTION:       bwb_mainloop()
  1012. X
  1013. X        DESCRIPTION:    This C function performs one iteration
  1014. X                        of the interpreter. In a non-preemptive
  1015. X                        scheduler, this function should be called
  1016. X                        by the scheduler, not by bwBASIC code.
  1017. X
  1018. X***************************************************************/
  1019. X
  1020. Xvoid
  1021. X#if ANSI_C
  1022. Xbwb_mainloop( void )
  1023. X#else
  1024. Xbwb_mainloop()
  1025. X#endif
  1026. X   {
  1027. X   if ( CURTASK exsc > -1 )
  1028. X      {
  1029. X      bwb_execline();            /* execute one line of program */
  1030. X      }
  1031. X#if INTERACTIVE
  1032. X   else
  1033. X      {
  1034. X      bwb_interact();            /* get user interaction */
  1035. X      }
  1036. X#endif
  1037. X   }
  1038. X
  1039. X/***************************************************************
  1040. X
  1041. X        FUNCTION:       bwb_execline()
  1042. X
  1043. X        DESCRIPTION:    This function executes a single line of
  1044. X                        a program in memory. This function is
  1045. X            called by bwb_mainloop().
  1046. X
  1047. X***************************************************************/
  1048. X
  1049. Xvoid
  1050. X#if ANSI_C
  1051. Xbwb_execline( void )
  1052. X#else
  1053. Xbwb_execline()
  1054. X#endif
  1055. X   {
  1056. X   struct bwb_line *r, *l;
  1057. X
  1058. X   l = CURTASK excs[ CURTASK exsc ].line;
  1059. X
  1060. X   /* if the line is &CURTASK bwb_end, then break out of EXEC loops */
  1061. X
  1062. X   if ( l == &CURTASK bwb_end )
  1063. X      {
  1064. X      CURTASK exsc = -1;
  1065. X      return;
  1066. X      }
  1067. X
  1068. X   /* Check for wacko line numbers  */
  1069. X
  1070. X#if INTENSIVE_DEBUG
  1071. X   if ( l->number < -1 )
  1072. X      {
  1073. X#if PROG_ERRORS
  1074. X      sprintf( bwb_ebuf, "in bwb_execline(): received line number <%d> < -1",
  1075. X         l->number );
  1076. X      bwb_error( bwb_ebuf );
  1077. X#else
  1078. X      bwb_error( err_syntax );
  1079. X#endif
  1080. X      return;
  1081. X      }
  1082. X
  1083. X   if ( l->number > MAXLINENO )
  1084. X      {
  1085. X#if PROG_ERRORS
  1086. X      sprintf( bwb_ebuf, "in bwb_execline(): received line number <%d> > MAX <%d>",
  1087. X         l->number, MAXLINENO );
  1088. X      bwb_error( bwb_ebuf );
  1089. X#else
  1090. X      bwb_error( err_syntax );
  1091. X#endif
  1092. X      return;
  1093. X      }
  1094. X#endif
  1095. X
  1096. X#if INTENSIVE_DEBUG
  1097. X   sprintf( bwb_ebuf, "in bwb_execline(): buffer <%s>",
  1098. X      &( l->buffer[ l->position ] ) );
  1099. X   bwb_debug( bwb_ebuf );
  1100. X#endif
  1101. X
  1102. X   /* Print line number if trace is on */
  1103. X
  1104. X   if ( bwb_trace == TRUE )
  1105. X      {
  1106. X#if INTENSIVE_DEBUG
  1107. X      sprintf( bwb_ebuf, "[ %d ]", l->number );
  1108. X      prn_xprintf( errfdevice, bwb_ebuf );
  1109. X#else
  1110. X      if ( l->number > 0 )
  1111. X         {
  1112. X         sprintf( bwb_ebuf, "[ %d ]", l->number );
  1113. X     prn_xprintf( errfdevice, bwb_ebuf );
  1114. X         }
  1115. X#endif
  1116. X      }
  1117. X
  1118. X   /* Set current line for error/break handling */
  1119. X
  1120. X   CURTASK number = l->number;
  1121. X   CURTASK bwb_l = l;
  1122. X
  1123. X   /* advance beyond whitespace */
  1124. X
  1125. X   adv_ws( l->buffer, &( l->position ) );
  1126. X
  1127. X   /*  advance past segment delimiter and warn */
  1128. X
  1129. X#if MULTISEG_LINES
  1130. X   if ( l->buffer[ l->position ] == ':' )
  1131. X      {
  1132. X      ++( l->position );
  1133. X      adv_ws( l->buffer, &( l->position ) );
  1134. X      }
  1135. X   l->marked = FALSE;
  1136. X#else
  1137. X#if PROG_ERRORS
  1138. X   if ( l->buffer[ l->position ] == ':' )
  1139. X      {
  1140. X      ++( l->position );
  1141. X      adv_ws( l->buffer, &( l->position ) );
  1142. X      sprintf( bwb_ebuf, "Enable MULTISEG_LINES for multi-segmented lines",
  1143. X         VERSION );
  1144. X      bwb_error( bwb_ebuf );
  1145. X      }
  1146. X#endif
  1147. X#endif
  1148. X
  1149. X   /* set positions in buffer */
  1150. X
  1151. X#if MULTISEG_LINES
  1152. X   if ( ( l->marked != TRUE ) || ( l->position > l->startpos ))
  1153. X      {
  1154. X      line_start( l->buffer, &( l->position ), &( l->lnpos ), &( l->lnum ),
  1155. X         &( l->cmdpos ), &( l->cmdnum ), &( l->startpos ) );
  1156. X      l->marked = TRUE;
  1157. X      }
  1158. X   else
  1159. X      {
  1160. X#if INTENSIVE_DEBUG
  1161. X      sprintf( bwb_ebuf, "in bwb_execline(): line <%d> is already marked",
  1162. X          l->number );
  1163. X      bwb_debug( bwb_ebuf );
  1164. X#endif
  1165. X      }
  1166. X   l->position = l->startpos;
  1167. X#else                /* not MULTISEG_LINES */
  1168. X   line_start( l->buffer, &( l->position ), &( l->lnpos ), &( l->lnum ),
  1169. X      &( l->cmdpos ), &( l->cmdnum ), &( l->startpos ) );
  1170. X   if ( l->position < l->startpos )
  1171. X      {
  1172. X      l->position = l->startpos;
  1173. X      }
  1174. X#endif
  1175. X
  1176. X   /* if there is a BASIC command in the line, execute it here */
  1177. X
  1178. X   if ( l->cmdnum > -1 )
  1179. X      {
  1180. X
  1181. X#if INTENSIVE_DEBUG
  1182. X      sprintf( bwb_ebuf, "in bwb_execline(): executing <%s>", l->buffer );
  1183. X      bwb_debug( bwb_ebuf );
  1184. X#endif
  1185. X
  1186. X      /* execute the command vector */
  1187. X
  1188. X      r = bwb_cmdtable[ l->cmdnum ].vector ( l );
  1189. X
  1190. X      }
  1191. X
  1192. X   /* No BASIC command; try to execute it as a shell command */
  1193. X
  1194. X#if COMMAND_SHELL
  1195. X   else
  1196. X      {
  1197. X
  1198. X#if INTENSIVE_DEBUG
  1199. X      sprintf( bwb_ebuf, "Breaking out to shell, line num <%d> buf <%s> cmd <%d> pos <%d>",
  1200. X         l->number, &( l->buffer[ l->position ] ), l->cmdnum, l->position );
  1201. X      bwb_debug( bwb_ebuf );
  1202. X      getchar();
  1203. X#endif
  1204. X
  1205. X      bwx_shell( l );
  1206. X      bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
  1207. X      return;
  1208. X      }
  1209. X
  1210. X#else                /* COMMAND_SHELL == FALSE */
  1211. X
  1212. X   else
  1213. X     {
  1214. X     bwb_error( err_uc );
  1215. X     }
  1216. X
  1217. X#endif
  1218. X
  1219. X   /* check for end of line: if so, advance to next line and return */
  1220. X
  1221. X   adv_ws( r->buffer, &( r->position ) );
  1222. X   switch( r->buffer[ r->position ] )
  1223. X      {
  1224. X      case '\n':
  1225. X      case '\r':
  1226. X      case '\0':
  1227. X
  1228. X#if INTENSIVE_DEBUG
  1229. X     sprintf( bwb_ebuf, "in bwb_execline(): detected end of line" );
  1230. X     bwb_debug( bwb_ebuf );
  1231. X#endif
  1232. X
  1233. X     r->next->position = 0;
  1234. X         bwb_setexec( r->next, 0, CURTASK excs[ CURTASK exsc ].code );
  1235. X         return;            /* and return */
  1236. X      }
  1237. X
  1238. X   /* else reset with the value in r */
  1239. X
  1240. X   bwb_setexec( r, r->position, CURTASK excs[ CURTASK exsc ].code );
  1241. X
  1242. X#if INTENSIVE_DEBUG
  1243. X   sprintf( bwb_ebuf, "in bwb_execline(): exit setting line number <%d>",
  1244. X      r->number );
  1245. X   bwb_debug( bwb_ebuf );
  1246. X#endif
  1247. X
  1248. X   }
  1249. X
  1250. X/***************************************************************
  1251. X
  1252. X        FUNCTION:       ln_asbuf()
  1253. X
  1254. X        DESCRIPTION:    This function allocates memory and copies
  1255. X            a null-terminated string to a line buffer.
  1256. X
  1257. X***************************************************************/
  1258. X
  1259. Xint
  1260. X#if ANSI_C
  1261. Xln_asbuf( struct bwb_line *l, char *s )
  1262. X#else
  1263. Xln_asbuf( l, s )
  1264. X   struct bwb_line *l;
  1265. X   char *s;
  1266. X#endif
  1267. X   {
  1268. X
  1269. X#if DONTDOTHIS            /* but why not? */
  1270. X   if ( l->buffer != NULL )
  1271. X      {
  1272. X      free( l->buffer );
  1273. X      }
  1274. X#endif
  1275. X
  1276. X   if ( ( l->buffer = calloc( strlen( s ) + 2, sizeof( char ) ) )
  1277. X      == NULL )
  1278. X      {
  1279. X#if PROG_ERRORS
  1280. X      bwb_error( "in ln_asbuf(): failed to find memory for new line" );
  1281. X#else
  1282. X      bwb_error( err_getmem );
  1283. X#endif
  1284. X      return FALSE;
  1285. X      }
  1286. X
  1287. X   /* copy the whole line to the line structure buffer */
  1288. X
  1289. X   strcpy( l->buffer, s );
  1290. X
  1291. X#if INTENSIVE_DEBUG
  1292. X   sprintf( bwb_ebuf, "in ln_asbuf(): allocated buffer <%s>", l->buffer );
  1293. X   bwb_debug( bwb_ebuf );
  1294. X#endif
  1295. X
  1296. X   /* strip CR from the buffer */
  1297. X
  1298. X   bwb_stripcr( l->buffer );
  1299. X
  1300. X#if INTENSIVE_DEBUG
  1301. X   sprintf( bwb_ebuf, "in ln_asbuf(): stripped CRs" );
  1302. X   bwb_debug( bwb_ebuf );
  1303. X#endif
  1304. X
  1305. X   return TRUE;
  1306. X
  1307. X   }
  1308. X
  1309. X/***************************************************************
  1310. X
  1311. X        FUNCTION:       bwb_gets()
  1312. X
  1313. X        DESCRIPTION:    This function reads a single line from
  1314. X                        the specified buffer.
  1315. X
  1316. X***************************************************************/
  1317. X
  1318. Xint
  1319. X#if ANSI_C
  1320. Xbwb_gets( char *buffer )
  1321. X#else
  1322. Xbwb_gets( buffer )
  1323. X   char *buffer;
  1324. X#endif
  1325. X   {
  1326. X   struct bwb_variable *v;
  1327. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  1328. X#if PARACT
  1329. X   char ubuf[ MAXSTRINGSIZE + 1 ];
  1330. X#endif
  1331. X
  1332. X   CURTASK number = 0;
  1333. X
  1334. X   v = var_find( DEFVNAME_PROMPT );
  1335. X   str_btoc( tbuf, var_getsval( v ) );
  1336. X#if PARACT
  1337. X   sprintf( ubuf, "TASK %d %s", bwb_curtask, tbuf );
  1338. X   strcpy( tbuf, ubuf );
  1339. X#endif
  1340. X
  1341. X   bwx_input( tbuf, buffer );
  1342. X
  1343. X   return TRUE;
  1344. X   }
  1345. X
  1346. X/***************************************************************
  1347. X
  1348. X        FUNCTION:       break_mes()
  1349. X
  1350. X        DESCRIPTION:    This function is called (a) by a SIGINT
  1351. X            signal or (b) by error-handling routines.
  1352. X            It prints an error message then calls
  1353. X            break_handler() to handle the program
  1354. X            interruption.
  1355. X
  1356. X***************************************************************/
  1357. X
  1358. Xvoid
  1359. X#if ANSI_C
  1360. Xbreak_mes( int x )
  1361. X#else
  1362. Xbreak_mes( x )
  1363. X   int x;
  1364. X#endif
  1365. X   {
  1366. X   static char *tmp_buffer;
  1367. X   static int init = FALSE;
  1368. X
  1369. X   /* get memory for temporary buffer if necessary */
  1370. X
  1371. X   if ( init == FALSE )
  1372. X      {
  1373. X      init = TRUE;
  1374. X      if ( ( tmp_buffer = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  1375. X         {
  1376. X#if PROG_ERRORS
  1377. X     bwb_error( "in break_mes(): failed to find memory for tmp_buffer" );
  1378. X#else
  1379. X     bwb_error( err_getmem );
  1380. X#endif
  1381. X     }
  1382. X      }
  1383. X
  1384. X   CURTASK expsc = 0;
  1385. X
  1386. X   sprintf( tmp_buffer, "\r%s %d\n", MES_BREAK, CURTASK number );
  1387. X   prn_xprintf( errfdevice, tmp_buffer );
  1388. X
  1389. X   break_handler();
  1390. X
  1391. X   }
  1392. X
  1393. X/***************************************************************
  1394. X
  1395. X    FUNCTION:       break_handler()
  1396. X
  1397. X    DESCRIPTION:    This function is called by break_mes()
  1398. X            and handles program interruption by break
  1399. X            (or by the STOP command).
  1400. X
  1401. X***************************************************************/
  1402. X
  1403. Xvoid
  1404. X#if ANSI_C
  1405. Xbreak_handler( void )
  1406. X#else
  1407. Xbreak_handler()
  1408. X#endif
  1409. X   {
  1410. X
  1411. X#if INTERACTIVE        /* INTERACTIVE: reset counters and jump back to mark */
  1412. X
  1413. X   /* reset all stack counters */
  1414. X
  1415. X   CURTASK exsc = -1;
  1416. X   CURTASK expsc = 0;
  1417. X   CURTASK xtxtsc = 0;
  1418. X   err_gosubl[ 0 ] = '\0';
  1419. X
  1420. X   /* reset the break handler */
  1421. X
  1422. X#if HAVE_SIGNAL
  1423. X   signal( SIGINT, break_mes );
  1424. X#endif
  1425. X
  1426. X#if HAVE_LONGJUMP
  1427. X   longjmp( mark, -1 );
  1428. X#else        /* HAVE_LONGJUMP = FALSE; no jump available; terminate */   
  1429. X   bwx_terminate();
  1430. X#endif   
  1431. X
  1432. X#else        /* nonINTERACTIVE:  terminate immediately */
  1433. X
  1434. X   bwx_terminate();
  1435. X
  1436. X#endif
  1437. X
  1438. X   }
  1439. X
  1440. X
  1441. X/***************************************************************
  1442. X
  1443. X    FUNCTION:       is_ln()
  1444. X
  1445. X    DESCRIPTION:    This function determines whether a program
  1446. X            line (in buffer) begins with a line number.
  1447. X
  1448. X***************************************************************/
  1449. X
  1450. Xint
  1451. X#if ANSI_C
  1452. Xis_ln( char *buffer )
  1453. X#else
  1454. Xis_ln( buffer )
  1455. X   char *buffer;
  1456. X#endif
  1457. X   {
  1458. X   static int position;
  1459. X
  1460. X   position = 0;
  1461. X   adv_ws( buffer, &position );
  1462. X   switch( buffer[ position ] )
  1463. X      {
  1464. X      case '0':
  1465. X      case '1':
  1466. X      case '2':
  1467. X      case '3':
  1468. X      case '4':
  1469. X      case '5':
  1470. X      case '6':
  1471. X      case '7':
  1472. X      case '8':
  1473. X      case '9':
  1474. X         return TRUE;
  1475. X      default:
  1476. X         return FALSE;
  1477. X      }
  1478. X   }
  1479. X
  1480. X
  1481. END_OF_FILE
  1482.   if test 32822 -ne `wc -c <'bwbasic-2.10/bwbasic.c'`; then
  1483.     echo shar: \"'bwbasic-2.10/bwbasic.c'\" unpacked with wrong size!
  1484.   fi
  1485.   # end of 'bwbasic-2.10/bwbasic.c'
  1486. fi
  1487. echo shar: End of archive 15 \(of 15\).
  1488. cp /dev/null ark15isdone
  1489. MISSING=""
  1490. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1491.     if test ! -f ark${I}isdone ; then
  1492.     MISSING="${MISSING} ${I}"
  1493.     fi
  1494. done
  1495. if test "${MISSING}" = "" ; then
  1496.     echo You have unpacked all 15 archives.
  1497.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1498. else
  1499.     echo You still must unpack the following archives:
  1500.     echo "        " ${MISSING}
  1501. fi
  1502. exit 0
  1503. exit 0 # Just in case...
  1504.