ChipMaster's bwBASIC This also includes history going back to v2.10. *WARN* some binary files might have been corrupted by CRLF.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2634 lines
62 KiB

  1. /***************************************************************
  2. bwb_var.c Variable-Handling Routines
  3. for Bywater BASIC Interpreter
  4. Commands: DIM
  5. COMMON
  6. ERASE
  7. SWAP
  8. CLEAR
  9. Copyright (c) 1993, Ted A. Campbell
  10. Bywater Software
  11. email: tcamp@delphi.com
  12. Copyright and Permissions Information:
  13. All U.S. and international rights are claimed by the author,
  14. Ted A. Campbell.
  15. This software is released under the terms of the GNU General
  16. Public License (GPL), which is distributed with this software
  17. in the file "COPYING". The GPL specifies the terms under
  18. which users may copy and use the software in this distribution.
  19. A separate license is available for commercial distribution,
  20. for information on which you should contact the author.
  21. ***************************************************************/
  22. /*---------------------------------------------------------------*/
  23. /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
  24. /* 11/1995 (eidetics@cerf.net). */
  25. /*---------------------------------------------------------------*/
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <math.h>
  29. #include "bwbasic.h"
  30. #include "bwb_mes.h"
  31. int dim_base = 0; /* set by OPTION BASE */
  32. static int dimmed = FALSE; /* has DIM been called? */
  33. static int first, last; /* first, last for DEFxxx commands */
  34. /* Prototypes for functions visible to this file only */
  35. #if ANSI_C
  36. static int dim_check( struct bwb_variable *v, int *pp );
  37. static int var_defx( struct bwb_line *l, int type );
  38. static int var_letseq( char *buffer, int *position, int *start, int *end );
  39. static size_t dim_unit( struct bwb_variable *v, int *pp );
  40. #else
  41. static int dim_check();
  42. static int var_defx();
  43. static int var_letseq();
  44. static size_t dim_unit();
  45. #endif
  46. /***************************************************************
  47. FUNCTION: var_init()
  48. DESCRIPTION: This function initializes the internal
  49. linked list of variables.
  50. ***************************************************************/
  51. #if ANSI_C
  52. int
  53. var_init( int task )
  54. #else
  55. int
  56. var_init( task )
  57. int task;
  58. #endif
  59. {
  60. LOCALTASK var_start.next = &(LOCALTASK var_end);
  61. strcpy( LOCALTASK var_start.name, "<START>" );
  62. strcpy( LOCALTASK var_end.name, "<END>" );
  63. return TRUE;
  64. }
  65. #if COMMON_CMDS
  66. /***************************************************************
  67. FUNCTION: bwb_common()
  68. DESCRIPTION: This C function implements the BASIC
  69. COMMON command.
  70. SYNTAX: COMMON variable [, variable...]
  71. ***************************************************************/
  72. #if ANSI_C
  73. struct bwb_line *
  74. bwb_common( struct bwb_line *l )
  75. #else
  76. struct bwb_line *
  77. bwb_common( l )
  78. struct bwb_line *l;
  79. #endif
  80. {
  81. register int loop;
  82. struct bwb_variable *v;
  83. char tbuf[ MAXSTRINGSIZE + 1 ];
  84. /* loop while arguments are available */
  85. loop = TRUE;
  86. while ( loop == TRUE )
  87. {
  88. /* get variable name and find variable */
  89. bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  90. if ( ( v = var_find( tbuf ) ) == NULL )
  91. {
  92. bwb_error( err_syntax );
  93. return bwb_zline( l );
  94. }
  95. v->common = TRUE; /* set common flag to true */
  96. /* check for comma */
  97. adv_ws( l->buffer, &( l->position ) );
  98. if ( l->buffer[ l->position ] != ',' )
  99. {
  100. return bwb_zline( l ); /* no comma; leave */
  101. }
  102. ++( l->position );
  103. adv_ws( l->buffer, &( l->position ) );
  104. }
  105. return bwb_zline( l );
  106. }
  107. /***********************************************************
  108. FUNCTION: bwb_erase()
  109. DESCRIPTION: This C function implements the BASIC
  110. ERASE command.
  111. SYNTAX: ERASE variable[, variable]...
  112. ***********************************************************/
  113. #if ANSI_C
  114. struct bwb_line *
  115. bwb_erase( struct bwb_line *l )
  116. #else
  117. struct bwb_line *
  118. bwb_erase( l )
  119. struct bwb_line *l;
  120. #endif
  121. {
  122. register int loop;
  123. struct bwb_variable *v;
  124. struct bwb_variable *p; /* previous variable in linked list */
  125. char tbuf[ MAXSTRINGSIZE + 1 ];
  126. bstring *sp; /* JBV */
  127. register int n; /* JBV */
  128. /* loop while arguments are available */
  129. loop = TRUE;
  130. while ( loop == TRUE )
  131. {
  132. /* get variable name and find variable */
  133. bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  134. if ( ( v = var_find( tbuf ) ) == NULL )
  135. {
  136. bwb_error( err_syntax );
  137. return bwb_zline( l );
  138. }
  139. /* be sure the variable is dimensioned */
  140. if (( v->dimensions < 1 ) || ( v->array_sizes[ 0 ] < 1 ))
  141. {
  142. bwb_error( err_dimnotarray );
  143. return bwb_zline( l );
  144. }
  145. /* find previous variable in chain */
  146. for ( p = &CURTASK var_start; p->next != v; p = p->next )
  147. {
  148. ;
  149. }
  150. /* reassign linkage */
  151. p->next = v->next;
  152. /* deallocate memory */
  153. /* Revised to FREE pass-thru calls by JBV */
  154. FREE( v->array_sizes, "bwb_erase" );
  155. v->array_sizes = NULL; /* JBV */
  156. FREE( v->array_pos , "bwb_erase");
  157. v->array_pos = NULL; /* JBV */
  158. if ( v->type == NUMBER )
  159. {
  160. /* Revised to FREE pass-thru call by JBV */
  161. FREE( v->memnum, "bwb_erase" );
  162. v->memnum = NULL; /* JBV */
  163. }
  164. else
  165. {
  166. /* Following section added by JBV */
  167. sp = v->memstr;
  168. for ( n = 0; n < (int) v->array_units; ++n )
  169. {
  170. if ( sp[ n ].sbuffer != NULL )
  171. {
  172. /* Revised to FREE pass-thru call by JBV */
  173. FREE( sp[ n ].sbuffer, "bwb_erase" );
  174. sp[ n ].sbuffer = NULL;
  175. }
  176. sp[ n ].rab = FALSE;
  177. sp[ n ].length = 0;
  178. }
  179. /* Revised to FREE pass-thru call by JBV */
  180. FREE( v->memstr, "bwb_erase" );
  181. v->memstr = NULL; /* JBV */
  182. }
  183. /* Revised to FREE pass-thru call by JBV */
  184. FREE( v, "bwb_erase" );
  185. v = NULL; /* JBV */
  186. /* check for comma */
  187. adv_ws( l->buffer, &( l->position ) );
  188. if ( l->buffer[ l->position ] != ',' )
  189. {
  190. return bwb_zline( l ); /* no comma; leave */
  191. }
  192. ++( l->position );
  193. adv_ws( l->buffer, &( l->position ) );
  194. }
  195. return bwb_zline( l );
  196. }
  197. /***********************************************************
  198. FUNCTION: bwb_swap()
  199. DESCRIPTION: This C function implements the BASIC
  200. SWAP command.
  201. SYNTAX: SWAP variable, variable
  202. ***********************************************************/
  203. #if ANSI_C
  204. struct bwb_line *
  205. bwb_swap( struct bwb_line *l )
  206. #else
  207. struct bwb_line *
  208. bwb_swap( l )
  209. struct bwb_line *l;
  210. #endif
  211. {
  212. struct bwb_variable tmp; /* temp holder */
  213. struct bwb_variable *lhs, *rhs; /* left and right- hand side of swap statement */
  214. char tbuf[ MAXSTRINGSIZE + 1 ];
  215. #if INTENSIVE_DEBUG
  216. sprintf( bwb_ebuf, "in bwb_swap(): buffer is <%s>",
  217. &( l->buffer[ l->position ] ) );
  218. bwb_debug( bwb_ebuf );
  219. #endif
  220. /* get left variable name and find variable */
  221. bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  222. #if INTENSIVE_DEBUG
  223. sprintf( bwb_ebuf, "in bwb_swap(): tbuf is <%s>", tbuf );
  224. bwb_debug( bwb_ebuf );
  225. #endif
  226. if ( ( lhs = var_find( tbuf ) ) == NULL )
  227. {
  228. bwb_error( err_syntax );
  229. return bwb_zline( l );
  230. }
  231. #if INTENSIVE_DEBUG
  232. sprintf( bwb_ebuf, "in bwb_swap(): lhs variable <%s> found",
  233. lhs->name );
  234. bwb_debug( bwb_ebuf );
  235. #endif
  236. /* check for comma */
  237. adv_ws( l->buffer, &( l->position ) );
  238. if ( l->buffer[ l->position ] != ',' )
  239. {
  240. bwb_error( err_syntax );
  241. return bwb_zline( l );
  242. }
  243. ++( l->position );
  244. adv_ws( l->buffer, &( l->position ) );
  245. /* get right variable name */
  246. #if INTENSIVE_DEBUG
  247. sprintf( bwb_ebuf, "in bwb_swap(): buffer is now <%s>",
  248. &( l->buffer[ l->position ] ) );
  249. bwb_debug( bwb_ebuf );
  250. #endif
  251. bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  252. #if INTENSIVE_DEBUG
  253. sprintf( bwb_ebuf, "in bwb_swap(): tbuf is <%s>", tbuf );
  254. bwb_debug( bwb_ebuf );
  255. #endif
  256. if ( ( rhs = var_find( tbuf ) ) == NULL )
  257. {
  258. bwb_error( err_syntax );
  259. return bwb_zline( l );
  260. }
  261. /* check to be sure that both variables are of the same type */
  262. if ( rhs->type != lhs->type )
  263. {
  264. bwb_error( err_mismatch );
  265. return bwb_zline( l );
  266. }
  267. /* copy lhs to temp, rhs to lhs, then temp to rhs */
  268. if ( lhs->type == NUMBER )
  269. {
  270. tmp.memnum = lhs->memnum;
  271. }
  272. else
  273. {
  274. tmp.memstr = lhs->memstr;
  275. }
  276. tmp.array_sizes = lhs->array_sizes;
  277. tmp.array_units = lhs->array_units;
  278. tmp.array_pos = lhs->array_pos;
  279. tmp.dimensions = lhs->dimensions;
  280. if ( lhs->type == NUMBER )
  281. {
  282. lhs->memnum = rhs->memnum;
  283. }
  284. else
  285. {
  286. lhs->memstr = rhs->memstr;
  287. }
  288. lhs->array_sizes = rhs->array_sizes;
  289. lhs->array_units = rhs->array_units;
  290. lhs->array_pos = rhs->array_pos;
  291. lhs->dimensions = rhs->dimensions;
  292. if ( lhs->type == NUMBER )
  293. {
  294. rhs->memnum = tmp.memnum;
  295. }
  296. else
  297. {
  298. rhs->memstr = tmp.memstr;
  299. }
  300. rhs->array_sizes = tmp.array_sizes;
  301. rhs->array_units = tmp.array_units;
  302. rhs->array_pos = tmp.array_pos;
  303. rhs->dimensions = tmp.dimensions;
  304. /* return */
  305. return bwb_zline( l );
  306. }
  307. #endif /* COMMON_CMDS */
  308. /***********************************************************
  309. FUNCTION: bwb_clear()
  310. DESCRIPTION: This C function implements the BASIC
  311. CLEAR command.
  312. SYNTAX: CLEAR
  313. ***********************************************************/
  314. #if ANSI_C
  315. struct bwb_line *
  316. bwb_clear( struct bwb_line *l )
  317. #else
  318. struct bwb_line *
  319. bwb_clear( l )
  320. struct bwb_line *l;
  321. #endif
  322. {
  323. struct bwb_variable *v;
  324. register int n;
  325. bstring *sp;
  326. bnumber *np;
  327. for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  328. {
  329. if ( v->preset != TRUE )
  330. {
  331. switch( v->type )
  332. {
  333. case NUMBER:
  334. np = v->memnum;
  335. for ( n = 0; n < (int) v->array_units; ++n )
  336. {
  337. np[ n ] = (bnumber) 0.0;
  338. }
  339. break;
  340. case STRING:
  341. sp = v->memstr;
  342. for ( n = 0; n < (int) v->array_units; ++n )
  343. {
  344. if ( sp[ n ].sbuffer != NULL )
  345. {
  346. /* Revised to FREE pass-thru call by JBV */
  347. FREE( sp[ n ].sbuffer, "bwb_clear" );
  348. sp[ n ].sbuffer = NULL;
  349. }
  350. sp[ n ].rab = FALSE;
  351. sp[ n ].length = 0;
  352. }
  353. break;
  354. }
  355. }
  356. }
  357. return bwb_zline( l );
  358. }
  359. /***********************************************************
  360. FUNCTION: var_delcvars()
  361. DESCRIPTION: This function deletes all variables
  362. in memory except those previously marked
  363. as common.
  364. ***********************************************************/
  365. #if ANSI_C
  366. int
  367. var_delcvars( void )
  368. #else
  369. int
  370. var_delcvars()
  371. #endif
  372. {
  373. struct bwb_variable *v;
  374. struct bwb_variable *p; /* previous variable */
  375. bstring *sp; /* JBV */
  376. register int n; /* JBV */
  377. p = &CURTASK var_start;
  378. for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  379. {
  380. if ( v->common != TRUE )
  381. {
  382. /* if the variable is dimensioned, release allocated memory */
  383. if ( v->dimensions > 0 )
  384. {
  385. /* deallocate memory */
  386. /* Revised to FREE pass-thru calls by JBV */
  387. FREE( v->array_sizes, "var_delcvars" );
  388. v->array_sizes = NULL; /* JBV */
  389. FREE( v->array_pos, "var_delcvars" );
  390. v->array_pos = NULL; /* JBV */
  391. if ( v->type == NUMBER )
  392. {
  393. /* Revised to FREE pass-thru call by JBV */
  394. FREE( v->memnum, "var_delcvars" );
  395. v->memnum = NULL; /* JBV */
  396. }
  397. else
  398. {
  399. /* Following section added by JBV */
  400. sp = v->memstr;
  401. for ( n = 0; n < (int) v->array_units; ++n )
  402. {
  403. if ( sp[ n ].sbuffer != NULL )
  404. {
  405. /* Revised to FREE pass-thru call by JBV */
  406. FREE( sp[ n ].sbuffer, "var_delcvars" );
  407. sp[ n ].sbuffer = NULL;
  408. }
  409. sp[ n ].rab = FALSE;
  410. sp[ n ].length = 0;
  411. }
  412. /* Revised to FREE pass-thru call by JBV */
  413. FREE( v->memstr, "var_delcvars" );
  414. v->memstr = NULL; /* JBV */
  415. }
  416. }
  417. /* reassign linkage */
  418. p->next = v->next;
  419. /* deallocate the variable itself */
  420. /* Revised to FREE pass-thru call by JBV */
  421. FREE( v, "var_delcvars" );
  422. v = NULL; /* JBV */
  423. }
  424. /* else reset previous variable */
  425. else
  426. {
  427. p = v;
  428. }
  429. }
  430. return TRUE;
  431. }
  432. #if MS_CMDS
  433. /***********************************************************
  434. FUNCTION: bwb_ddbl()
  435. DESCRIPTION: This function implements the BASIC
  436. DEFDBL command.
  437. SYNTAX: DEFDBL letter[-letter](, letter[-letter])...
  438. ***********************************************************/
  439. #if ANSI_C
  440. struct bwb_line *
  441. bwb_ddbl( struct bwb_line *l )
  442. #else
  443. struct bwb_line *
  444. bwb_ddbl( l )
  445. struct bwb_line *l;
  446. #endif
  447. {
  448. /* call generalized DEF handler with DOUBLE set */
  449. var_defx( l, NUMBER );
  450. return bwb_zline( l );
  451. }
  452. /***********************************************************
  453. FUNCTION: bwb_dint()
  454. DESCRIPTION: This function implements the BASIC
  455. DEFINT command.
  456. SYNTAX: DEFINT letter[-letter](, letter[-letter])...
  457. ***********************************************************/
  458. #if ANSI_C
  459. struct bwb_line *
  460. bwb_dint( struct bwb_line *l )
  461. #else
  462. struct bwb_line *
  463. bwb_dint( l )
  464. struct bwb_line *l;
  465. #endif
  466. {
  467. /* call generalized DEF handler with INTEGER set */
  468. var_defx( l, NUMBER );
  469. return bwb_zline( l );
  470. }
  471. /***********************************************************
  472. FUNCTION: bwb_dsng()
  473. DESCRIPTION: This function implements the BASIC
  474. DEFSNG command.
  475. SYNTAX: DEFSNG letter[-letter](, letter[-letter])...
  476. ***********************************************************/
  477. #if ANSI_C
  478. struct bwb_line *
  479. bwb_dsng( struct bwb_line *l )
  480. #else
  481. struct bwb_line *
  482. bwb_dsng( l )
  483. struct bwb_line *l;
  484. #endif
  485. {
  486. /* call generalized DEF handler with SINGLE set */
  487. var_defx( l, NUMBER );
  488. return bwb_zline( l );
  489. }
  490. /***********************************************************
  491. FUNCTION: bwb_dstr()
  492. DESCRIPTION: This function implements the BASIC
  493. DEFSTR command.
  494. SYNTAX: DEFSTR letter[-letter](, letter[-letter])...
  495. ***********************************************************/
  496. #if ANSI_C
  497. struct bwb_line *
  498. bwb_dstr( struct bwb_line *l )
  499. #else
  500. struct bwb_line *
  501. bwb_dstr( l )
  502. struct bwb_line *l;
  503. #endif
  504. {
  505. /* call generalized DEF handler with STRING set */
  506. var_defx( l, STRING );
  507. return bwb_zline( l );
  508. }
  509. /***********************************************************
  510. FUNCTION: bwb_mid()
  511. DESCRIPTION: This function implements the BASIC
  512. MID$ command.
  513. Same as MID$ function, except it will set
  514. the desired substring and not return its
  515. value. Added by JBV 10/95
  516. SYNTAX: MID$( string-variable$, start-position-in-string
  517. [, number-of-spaces ] ) = expression
  518. ***********************************************************/
  519. #if ANSI_C
  520. struct bwb_line *
  521. bwb_mid( struct bwb_line *l )
  522. #else
  523. struct bwb_line *
  524. bwb_mid( l )
  525. struct bwb_line *l;
  526. #endif
  527. {
  528. char tbuf[ MAXSTRINGSIZE + 1 ];
  529. char source_string[ MAXSTRINGSIZE + 1 ];
  530. struct bwb_variable *v;
  531. static int pos;
  532. bstring *d;
  533. int *pp;
  534. int n_params;
  535. int p;
  536. register int n;
  537. int startpos, numchars, endpos;
  538. int source_counter, source_length, target_length;
  539. int target_terminate;
  540. struct exp_ese *e;
  541. #if INTENSIVE_DEBUG
  542. sprintf( bwb_ebuf, "in bwb_mid(): MID$ command" );
  543. bwb_debug( bwb_ebuf );
  544. #endif
  545. /* Get past left parenthesis */
  546. adv_ws( l->buffer, &( l->position ) );
  547. ++( l->position );
  548. adv_ws( l->buffer, &( l->position ) );
  549. /* Get variable name and find variable */
  550. bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  551. v = var_find( tbuf );
  552. if ( v == NULL )
  553. {
  554. #if PROG_ERRORS
  555. sprintf( bwb_ebuf, "in bwb_mid(): failed to find variable" );
  556. bwb_error( bwb_ebuf );
  557. #else
  558. bwb_error( err_syntax );
  559. #endif
  560. }
  561. if ( v->type != STRING )
  562. {
  563. #if PROG_ERRORS
  564. sprintf( bwb_ebuf, "in bwb_mid(): assignment must be to string variable" );
  565. bwb_error( bwb_ebuf );
  566. #else
  567. bwb_error( err_syntax );
  568. #endif
  569. }
  570. /* read subscripts */
  571. pos = 0;
  572. if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
  573. {
  574. #if INTENSIVE_DEBUG
  575. sprintf( bwb_ebuf, "in bwb_mid(): variable <%s> has 1 dimension",
  576. v->name );
  577. bwb_debug( bwb_ebuf );
  578. #endif
  579. n_params = 1;
  580. pp = &p;
  581. pp[ 0 ] = dim_base;
  582. }
  583. else
  584. {
  585. #if INTENSIVE_DEBUG
  586. sprintf( bwb_ebuf, "in bwb_mid(): variable <%s> has > 1 dimensions",
  587. v->name );
  588. bwb_debug( bwb_ebuf );
  589. #endif
  590. dim_getparams( l->buffer, &( l->position ), &n_params, &pp );
  591. }
  592. CURTASK exps[ CURTASK expsc ].pos_adv = pos;
  593. for ( n = 0; n < v->dimensions; ++n )
  594. {
  595. v->array_pos[ n ] = pp[ n ];
  596. }
  597. /* get bstring pointer */
  598. d = var_findsval( v, pp );
  599. /* Get past next comma and white space */
  600. adv_ws( l->buffer, &( l->position ) );
  601. ++( l->position );
  602. adv_ws( l->buffer, &( l->position ) );
  603. /* Get starting position (expression) */
  604. adv_element( l->buffer, &( l->position ), tbuf );
  605. pos = 0;
  606. e = bwb_exp( tbuf, FALSE, &pos );
  607. startpos = (int) exp_getnval( e );
  608. #if INTENSIVE_DEBUG
  609. sprintf( bwb_ebuf, "in bwb_mid(): startpos <%d> buffer <%lX>",
  610. startpos, (long) d->sbuffer );
  611. bwb_debug( bwb_ebuf );
  612. #endif
  613. /* Get past next comma and white space (if they exist) */
  614. adv_ws( l->buffer, &( l->position ) );
  615. if (l->buffer[l->position] == ',')
  616. {
  617. target_terminate = 0;
  618. ++( l->position );
  619. adv_ws( l->buffer, &( l->position ) );
  620. adv_element( l->buffer, &( l->position ), tbuf );
  621. pos = 0;
  622. e = bwb_exp( tbuf, FALSE, &pos );
  623. numchars = (int) exp_getnval( e );
  624. if ( numchars == 0 )
  625. {
  626. #if PROG_ERRORS
  627. sprintf( bwb_ebuf, "in bwb_mid(): destination string no. of chars out of range" );
  628. bwb_error( bwb_ebuf );
  629. #else
  630. bwb_error( "Argument out of range" );
  631. #endif
  632. }
  633. }
  634. else
  635. {
  636. target_terminate = 1;
  637. numchars = 0;
  638. }
  639. if ( numchars < 0 )
  640. {
  641. #if PROG_ERRORS
  642. sprintf( bwb_ebuf, "in bwb_mid(): negative string length" );
  643. bwb_error( bwb_ebuf );
  644. #else
  645. bwb_error( "Negative string length" );
  646. #endif
  647. }
  648. #if INTENSIVE_DEBUG
  649. sprintf( bwb_ebuf, "in bwb_mid(): numchars <%d> target_terminate <%d>", numchars, target_terminate );
  650. bwb_debug( bwb_ebuf );
  651. #endif
  652. /* Get past equal sign */
  653. adv_ws( l->buffer, &( l->position ) );
  654. if (l->buffer[l->position] == ')')
  655. {
  656. ++(l->position);
  657. adv_ws( l->buffer, &( l->position ) );
  658. }
  659. ++(l->position);
  660. adv_ws( l->buffer, &( l->position ) );
  661. /* Evaluate string expression */
  662. e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  663. if ( e->type != STRING )
  664. {
  665. #if PROG_ERRORS
  666. sprintf( bwb_ebuf, "in bwb_mid(): assignment must be from string expression" );
  667. bwb_error( bwb_ebuf );
  668. #else
  669. bwb_error( err_syntax );
  670. #endif
  671. }
  672. /* Prepare to MID the string */
  673. str_btoc( source_string, exp_getsval( e ) );
  674. str_btoc( tbuf, d );
  675. target_length = strlen( tbuf );
  676. if ( startpos > ( target_length + 1 ) )
  677. {
  678. #if PROG_ERRORS
  679. sprintf( bwb_ebuf, "in bwb_mid(): non-contiguous string created" );
  680. bwb_error( bwb_ebuf );
  681. #else
  682. bwb_error( "Non-contiguous string created" );
  683. #endif
  684. }
  685. if ( startpos < 1 )
  686. {
  687. #if PROG_ERRORS
  688. sprintf( bwb_ebuf, "in bwb_mid(): destination string start position out of range" );
  689. bwb_error( bwb_ebuf );
  690. #else
  691. bwb_error( "Argument out of range" );
  692. #endif
  693. }
  694. source_length = strlen( source_string );
  695. if ( numchars == 0 ) numchars = source_length;
  696. endpos = startpos + numchars - 1;
  697. /* MID the string */
  698. if ( endpos < startpos ) tbuf[ startpos - 1 ] = '\0';
  699. else
  700. {
  701. source_counter = 0;
  702. for ( n = startpos - 1; n < endpos; ++n )
  703. {
  704. if ( source_counter < source_length )
  705. tbuf[ n ] = source_string[ source_counter ];
  706. else
  707. tbuf[ n ] = ' ';
  708. ++source_counter;
  709. }
  710. /* Terminate if indicated or characters were added */
  711. if ( ( endpos > target_length ) || ( target_terminate == 1 ) )
  712. tbuf[ endpos ] = '\0';
  713. }
  714. str_ctob( d, tbuf );
  715. #if MULTISEG_LINES
  716. adv_eos( l->buffer, &( l->position ));
  717. #endif
  718. return bwb_zline( l );
  719. }
  720. /***********************************************************
  721. Function: var_defx()
  722. DESCRIPTION: This function is a generalized DEFxxx handler.
  723. ***********************************************************/
  724. #if ANSI_C
  725. static int
  726. var_defx( struct bwb_line *l, int type )
  727. #else
  728. static int
  729. var_defx( l, type )
  730. struct bwb_line *l;
  731. int type;
  732. #endif
  733. {
  734. int loop;
  735. register int c;
  736. static char vname[ 2 ];
  737. struct bwb_variable *v;
  738. /* loop while there are variable names to process */
  739. loop = TRUE;
  740. while ( loop == TRUE )
  741. {
  742. /* check for end of line or line segment */
  743. adv_ws( l->buffer, &( l->position ) );
  744. switch( l->buffer[ l->position ] )
  745. {
  746. case '\n':
  747. case '\r':
  748. case '\0':
  749. case ':':
  750. return FALSE;
  751. }
  752. /* find a sequence of letters for variables */
  753. if ( var_letseq( l->buffer, &( l->position ), &first, &last ) == FALSE )
  754. {
  755. return FALSE;
  756. }
  757. /* loop through the list getting variables */
  758. for ( c = first; c <= last; ++c )
  759. {
  760. vname[ 0 ] = (char) c;
  761. vname[ 1 ] = '\0';
  762. #if INTENSIVE_DEBUG
  763. sprintf( bwb_ebuf, "in var_defx(): calling var_find() for <%s>",
  764. vname );
  765. bwb_debug( bwb_ebuf );
  766. #endif
  767. v = var_find( vname );
  768. /* but var_find() assigns on the basis of name endings
  769. (so all in this case should be SINGLEs), so we must
  770. force the type of the variable */
  771. var_make( v, type );
  772. }
  773. }
  774. return TRUE;
  775. }
  776. #endif /* MS_CMDS */
  777. /***********************************************************
  778. Function: var_letseq()
  779. DESCRIPTION: This function finds a sequence of letters
  780. for a DEFxxx command.
  781. ***********************************************************/
  782. #if ANSI_C
  783. static int
  784. var_letseq( char *buffer, int *position, int *start, int *end )
  785. #else
  786. static int
  787. var_letseq( buffer, position, start, end )
  788. char *buffer;
  789. int *position;
  790. int *start;
  791. int *end;
  792. #endif
  793. {
  794. #if INTENSIVE_DEBUG
  795. sprintf( bwb_ebuf, "in var_letseq(): buffer <%s>", &( buffer[ *position ] ));
  796. bwb_debug( bwb_ebuf );
  797. #endif
  798. /* advance beyond whitespace */
  799. adv_ws( buffer, position );
  800. /* check for end of line */
  801. switch( buffer[ *position ] )
  802. {
  803. case '\0':
  804. case '\n':
  805. case '\r':
  806. case ':':
  807. return TRUE;
  808. }
  809. /* character at this position must be a letter */
  810. if ( isalpha( buffer[ *position ] ) == 0 )
  811. {
  812. bwb_error( err_defchar );
  813. return FALSE;
  814. }
  815. *end = *start = buffer[ *position ];
  816. /* advance beyond character and whitespace */
  817. ++( *position );
  818. adv_ws( buffer, position );
  819. /* check for hyphen, indicating sequence of more than one letter */
  820. if ( buffer[ *position ] == '-' )
  821. {
  822. ++( *position );
  823. /* advance beyond whitespace */
  824. adv_ws( buffer, position );
  825. /* character at this position must be a letter */
  826. if ( isalpha( buffer[ *position ] ) == 0 )
  827. {
  828. *end = *start;
  829. }
  830. else
  831. {
  832. *end = buffer[ *position ];
  833. ++( *position );
  834. }
  835. }
  836. /* advance beyond comma if present */
  837. if ( buffer[ *position ] == ',' )
  838. {
  839. ++( *position );
  840. }
  841. return TRUE;
  842. }
  843. /***********************************************************
  844. FUNCTION: bwb_const()
  845. DESCRIPTION: This function takes the string in lb
  846. (the large buffer), finds a string constant
  847. (beginning and ending with quotation marks),
  848. and returns it in sb (the small buffer),
  849. appropriately incrementing the integer
  850. pointed to by n. The string in lb should NOT
  851. include the initial quotation mark.
  852. ***********************************************************/
  853. #if ANSI_C
  854. int
  855. bwb_const( char *lb, char *sb, int *n )
  856. #else
  857. int
  858. bwb_const( lb, sb, n )
  859. char *lb;
  860. char *sb;
  861. int *n;
  862. #endif
  863. {
  864. register int s;
  865. ++*n; /* advance past quotation mark */
  866. s = 0;
  867. while ( TRUE )
  868. {
  869. switch ( lb[ *n ] )
  870. {
  871. case '\"':
  872. sb[ s ] = 0;
  873. ++*n; /* advance past ending quotation mark */
  874. return TRUE;
  875. case '\n':
  876. case '\r':
  877. case 0:
  878. sb[ s ] = 0;
  879. return TRUE;
  880. default:
  881. sb[ s ] = lb[ *n ];
  882. break;
  883. }
  884. ++*n; /* advance to next character in large buffer */
  885. ++s; /* advance to next position in small buffer */
  886. sb[ s ] = 0; /* terminate with 0 */
  887. }
  888. }
  889. /***********************************************************
  890. FUNCTION: bwb_getvarname()
  891. DESCRIPTION: This function takes the string in lb
  892. (the large buffer), finds a variable name,
  893. and returns it in sb (the small buffer),
  894. appropriately incrementing the integer
  895. pointed to by n.
  896. ***********************************************************/
  897. #if ANSI_C
  898. int
  899. bwb_getvarname( char *lb, char *sb, int *n )
  900. #else
  901. int
  902. bwb_getvarname( lb, sb, n )
  903. char *lb;
  904. char *sb;
  905. int *n;
  906. #endif
  907. {
  908. register int s;
  909. s = 0;
  910. /* advance beyond whitespace */
  911. adv_ws( lb, n );
  912. while ( TRUE )
  913. {
  914. switch ( lb[ *n ] )
  915. {
  916. case ' ': /* whitespace */
  917. case '\t':
  918. case '\n': /* end of string */
  919. case '\r':
  920. case 0:
  921. case ':': /* end of expression */
  922. case ',':
  923. case ';':
  924. case '(': /* beginning of parameter list for dimensioned array */
  925. case '+': /* add variables */
  926. case '=': /* Don't forget this one (JBV) */
  927. sb[ s ] = 0;
  928. return TRUE;
  929. default:
  930. sb[ s ] = lb[ *n ];
  931. break;
  932. }
  933. ++*n; /* advance to next character in large buffer */
  934. ++s; /* advance to next position in small buffer */
  935. sb[ s ] = 0; /* terminate with 0 */
  936. #if INTENSIVE_DEBUG
  937. sprintf( bwb_ebuf, "in bwb_getvarname(): found <%s>", sb );
  938. bwb_debug( bwb_ebuf );
  939. #endif
  940. }
  941. }
  942. /***************************************************************
  943. FUNCTION: var_find()
  944. DESCRIPTION: This C function attempts to find a variable
  945. name matching the argument in buffer. If
  946. it fails to find a matching name, it
  947. sets up a new variable with that name.
  948. ***************************************************************/
  949. #if ANSI_C
  950. struct bwb_variable *
  951. var_find( char *buffer )
  952. #else
  953. struct bwb_variable *
  954. var_find( buffer )
  955. char *buffer;
  956. #endif
  957. {
  958. struct bwb_variable *v;
  959. #if INTENSIVE_DEBUG
  960. sprintf( bwb_ebuf, "in var_find(): received <%s>", buffer );
  961. bwb_debug( bwb_ebuf );
  962. #endif
  963. /* check for a local variable at this EXEC level */
  964. v = var_islocal( buffer );
  965. if ( v != NULL )
  966. {
  967. return v;
  968. }
  969. /* now run through the global variable list and try to find a match */
  970. for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  971. {
  972. if ( strcmp( v->name, buffer ) == 0 )
  973. {
  974. switch( v->type )
  975. {
  976. case STRING:
  977. case NUMBER:
  978. break;
  979. default:
  980. #if PROG_ERRORS
  981. sprintf( bwb_ebuf, "in var_find(): inappropriate precision for variable <%s>",
  982. v->name );
  983. bwb_error( bwb_ebuf );
  984. #endif
  985. break;
  986. }
  987. #if INTENSIVE_DEBUG
  988. sprintf( bwb_ebuf, "in var_find(): found global variable <%s>", v->name );
  989. bwb_debug( bwb_ebuf );
  990. #endif
  991. return v;
  992. }
  993. }
  994. /* presume this is a new variable, so initialize it... */
  995. /* check for NULL variable name */
  996. if ( strlen( buffer ) == 0 )
  997. {
  998. #if PROG_ERRORS
  999. sprintf( bwb_ebuf, "in var_find(): NULL variable name received\n" );
  1000. bwb_error( bwb_ebuf );
  1001. #else
  1002. bwb_error( err_syntax );
  1003. #endif
  1004. return NULL;
  1005. }
  1006. /* initialize new variable */
  1007. v = var_new( buffer );
  1008. /* set place at beginning of variable chain */
  1009. v->next = CURTASK var_start.next;
  1010. CURTASK var_start.next = v;
  1011. /* normally not a preset */
  1012. v->preset = FALSE;
  1013. #if INTENSIVE_DEBUG
  1014. sprintf( bwb_ebuf, "in var_find(): initialized new variable <%s> type <%c>, dim <%d>",
  1015. v->name, v->type, v->dimensions );
  1016. bwb_debug( bwb_ebuf );
  1017. getchar();
  1018. #endif
  1019. return v;
  1020. }
  1021. /***************************************************************
  1022. FUNCTION: var_new()
  1023. DESCRIPTION: This function assigns memory for a new variable.
  1024. ***************************************************************/
  1025. #if ANSI_C
  1026. struct bwb_variable *
  1027. var_new( char *name )
  1028. #else
  1029. struct bwb_variable *
  1030. var_new( name )
  1031. char *name;
  1032. #endif
  1033. {
  1034. struct bwb_variable *v;
  1035. /* get memory for new variable */
  1036. /* Revised to CALLOC pass-thru call by JBV */
  1037. if ( ( v = (struct bwb_variable *) CALLOC( 1, sizeof( struct bwb_variable ), "var_new" ))
  1038. == NULL )
  1039. {
  1040. bwb_error( err_getmem );
  1041. return NULL;
  1042. }
  1043. /* copy the name into the appropriate structure */
  1044. strcpy( v->name, name );
  1045. /* set memory in the new variable */
  1046. var_make( v, (int) v->name[ strlen( v->name ) - 1 ] );
  1047. /* and return */
  1048. return v;
  1049. }
  1050. /***************************************************************
  1051. FUNCTION: bwb_isvar()
  1052. DESCRIPTION: This function determines if the string
  1053. in 'buffer' is the name of a previously-
  1054. existing variable.
  1055. ***************************************************************/
  1056. #if ANSI_C
  1057. int
  1058. bwb_isvar( char *buffer )
  1059. #else
  1060. int
  1061. bwb_isvar( buffer )
  1062. char *buffer;
  1063. #endif
  1064. {
  1065. struct bwb_variable *v;
  1066. /* run through the variable list and try to find a match */
  1067. for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  1068. {
  1069. if ( strcmp( v->name, buffer ) == 0 )
  1070. {
  1071. return TRUE;
  1072. }
  1073. }
  1074. /* search failed */
  1075. return FALSE;
  1076. }
  1077. /***************************************************************
  1078. FUNCTION: var_getnval()
  1079. DESCRIPTION: This function returns the current value of
  1080. the variable argument as a number.
  1081. ***************************************************************/
  1082. #if ANSI_C
  1083. bnumber
  1084. var_getnval( struct bwb_variable *nvar )
  1085. #else
  1086. bnumber
  1087. var_getnval( nvar )
  1088. struct bwb_variable *nvar;
  1089. #endif
  1090. {
  1091. switch( nvar->type )
  1092. {
  1093. case NUMBER:
  1094. return *( var_findnval( nvar, nvar->array_pos ) );
  1095. }
  1096. #if PROG_ERRORS
  1097. sprintf( bwb_ebuf, "in var_getnval(): type is <%d>=<%c>.",
  1098. nvar->type, nvar->type );
  1099. bwb_error( bwb_ebuf );
  1100. #else
  1101. bwb_error( err_mismatch );
  1102. #endif
  1103. return (bnumber) 0.0;
  1104. }
  1105. /***************************************************************
  1106. FUNCTION: var_getsval()
  1107. DESCRIPTION: This function returns the current value of
  1108. the variable argument as a pointer to a BASIC
  1109. string structure.
  1110. ***************************************************************/
  1111. #if ANSI_C
  1112. bstring *
  1113. var_getsval( struct bwb_variable *nvar )
  1114. #else
  1115. bstring *
  1116. var_getsval( nvar )
  1117. struct bwb_variable *nvar;
  1118. #endif
  1119. {
  1120. static bstring b;
  1121. b.rab = FALSE;
  1122. switch( nvar->type )
  1123. {
  1124. case STRING:
  1125. return var_findsval( nvar, nvar->array_pos );
  1126. case NUMBER:
  1127. sprintf( bwb_ebuf, "%*f ", prn_precision( nvar ),
  1128. *( var_findnval( nvar, nvar->array_pos ) ) );
  1129. str_ctob( &b, bwb_ebuf );
  1130. return &b;
  1131. default:
  1132. #if PROG_ERRORS
  1133. sprintf( bwb_ebuf, "in var_getsval(): type is <%d>=<%c>.",
  1134. nvar->type, nvar->type );
  1135. bwb_error( bwb_ebuf );
  1136. #else
  1137. bwb_error( err_mismatch );
  1138. #endif
  1139. return NULL;
  1140. }
  1141. }
  1142. /***************************************************************
  1143. FUNCTION: bwb_dim()
  1144. DESCRIPTION: This function implements the BASIC DIM
  1145. statement, allocating memory for a
  1146. dimensioned array of variables.
  1147. SYNTAX: DIM variable(elements...)[variable(elements...)]...
  1148. ***************************************************************/
  1149. #if ANSI_C
  1150. struct bwb_line *
  1151. bwb_dim( struct bwb_line *l )
  1152. #else
  1153. struct bwb_line *
  1154. bwb_dim( l )
  1155. struct bwb_line *l;
  1156. #endif
  1157. {
  1158. register int n;
  1159. static int n_params; /* number of parameters */
  1160. static int *pp; /* pointer to parameter values */
  1161. struct bwb_variable *newvar;
  1162. bnumber *np;
  1163. int loop;
  1164. int old_name, old_dimensions;
  1165. char tbuf[ MAXSTRINGSIZE + 1 ];
  1166. #if INTENSIVE_DEBUG
  1167. sprintf( bwb_ebuf, "in bwb_dim(): entered function." );
  1168. bwb_debug( bwb_ebuf );
  1169. #endif
  1170. loop = TRUE;
  1171. while ( loop == TRUE )
  1172. {
  1173. old_name = FALSE;
  1174. /* Get variable name */
  1175. adv_ws( l->buffer, &( l->position ) );
  1176. bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  1177. /* check for previously used variable name */
  1178. if ( bwb_isvar( tbuf ) == TRUE )
  1179. {
  1180. #if INTENSIVE_DEBUG
  1181. sprintf( bwb_ebuf, "in bwb_dim(): variable name is already used.",
  1182. l->number );
  1183. bwb_debug( bwb_ebuf );
  1184. #endif
  1185. old_name = TRUE;
  1186. }
  1187. /* get the new variable */
  1188. newvar = var_find( tbuf );
  1189. #if INTENSIVE_DEBUG
  1190. sprintf( bwb_ebuf, "in bwb_dim(): new variable name is <%s>.",
  1191. newvar->name );
  1192. bwb_debug( bwb_ebuf );
  1193. #endif
  1194. /* note that DIM has been called */
  1195. dimmed = TRUE;
  1196. /* read parameters */
  1197. old_dimensions = newvar->dimensions;
  1198. dim_getparams( l->buffer, &( l->position ), &n_params, &pp );
  1199. newvar->dimensions = n_params;
  1200. /* Check parameters for an old variable name */
  1201. if ( old_name == TRUE )
  1202. {
  1203. /* check to be sure the number of dimensions is the same */
  1204. if ( newvar->dimensions != old_dimensions )
  1205. {
  1206. #if PROG_ERRORS
  1207. sprintf( bwb_ebuf, "in bwb_dim(): variable <%s> cannot be re-dimensioned",
  1208. newvar->name );
  1209. bwb_error( bwb_ebuf );
  1210. #else
  1211. bwb_error( err_redim );
  1212. #endif
  1213. }
  1214. /* check to be sure sizes for the old variable are the same */
  1215. for ( n = 0; n < newvar->dimensions; ++n )
  1216. {
  1217. #if INTENSIVE_DEBUG
  1218. sprintf( bwb_ebuf, "in bwb_dim(): old var <%s> parameter <%d> size <%d>.",
  1219. newvar->name, n, pp[ n ] );
  1220. bwb_debug( bwb_ebuf );
  1221. #endif
  1222. if ( ( pp[ n ] + ( 1 - dim_base )) != newvar->array_sizes[ n ] )
  1223. {
  1224. #if PROG_ERRORS
  1225. sprintf( bwb_ebuf, "in bwb_dim(): variable <%s> parameter <%d> cannot be resized",
  1226. newvar->name, n );
  1227. bwb_error( bwb_ebuf );
  1228. #else
  1229. bwb_error( err_redim );
  1230. #endif
  1231. }
  1232. }
  1233. } /* end of conditional for old variable */
  1234. /* a new variable */
  1235. else
  1236. {
  1237. /* assign memory for parameters */
  1238. /* Revised to CALLOC pass-thru call by JBV */
  1239. if ( ( newvar->array_sizes = (int *) CALLOC( n_params, sizeof( int ), "bwb_dim" )) == NULL )
  1240. {
  1241. #if PROG_ERRORS
  1242. sprintf( bwb_ebuf, "in line %d: Failed to find memory for array_sizes for <%s>",
  1243. l->number, newvar->name );
  1244. bwb_error( bwb_ebuf );
  1245. #else
  1246. bwb_error( err_getmem );
  1247. #endif
  1248. return bwb_zline( l );
  1249. }
  1250. for ( n = 0; n < newvar->dimensions; ++n )
  1251. {
  1252. newvar->array_sizes[ n ] = pp[ n ] + ( 1 - dim_base );
  1253. #if INTENSIVE_DEBUG
  1254. sprintf( bwb_ebuf, "in bwb_dim(): array_sizes dim <%d> value <%d>",
  1255. n, newvar->array_sizes[ n ] );
  1256. bwb_debug( bwb_ebuf );
  1257. #endif
  1258. }
  1259. /* assign memory for current position */
  1260. /* Revised to CALLOC pass-thru call by JBV */
  1261. if ( ( newvar->array_pos = (int *) CALLOC( n_params, sizeof( int ), "bwb_dim" )) == NULL )
  1262. {
  1263. #if PROG_ERRORS
  1264. sprintf( bwb_ebuf, "in line %d: Failed to find memory for array_pos for <%s>",
  1265. l->number, newvar->name );
  1266. bwb_error( bwb_ebuf );
  1267. #else
  1268. bwb_error( err_getmem );
  1269. #endif
  1270. return bwb_zline( l );
  1271. }
  1272. for ( n = 0; n < newvar->dimensions; ++n )
  1273. {
  1274. newvar->array_pos[ n ] = dim_base;
  1275. }
  1276. /* calculate the array size */
  1277. newvar->array_units = (size_t) MAXINTSIZE; /* avoid error in dim_unit() */
  1278. newvar->array_units = dim_unit( newvar, pp ) + 1;
  1279. #if INTENSIVE_DEBUG
  1280. sprintf( bwb_ebuf, "in bwb_dim(): array memory requires <%ld> units",
  1281. (long) newvar->array_units );
  1282. bwb_debug( bwb_ebuf );
  1283. #endif
  1284. /* assign array memory */
  1285. switch( newvar->type )
  1286. {
  1287. case STRING:
  1288. #if INTENSIVE_DEBUG
  1289. sprintf( bwb_ebuf, "in bwb_dim(): 1 STRING requires <%ld> bytes",
  1290. (long) sizeof( bstring ));
  1291. bwb_debug( bwb_ebuf );
  1292. sprintf( bwb_ebuf, "in bwb_dim(): STRING array memory requires <%ld> bytes",
  1293. (long) ( newvar->array_units + 1 ) * sizeof( bstring ));
  1294. bwb_debug( bwb_ebuf );
  1295. #endif
  1296. /*------------------------------------------------------*/
  1297. /* memnum, not memstr, was used here -- incorrect (JBV) */
  1298. /* Revised to CALLOC pass-thru call by JBV */
  1299. /*------------------------------------------------------*/
  1300. if ( ( newvar->memstr = (bstring *)
  1301. CALLOC( newvar->array_units, sizeof( bstring), "bwb_dim" )) == NULL )
  1302. {
  1303. #if PROG_ERRORS
  1304. sprintf( bwb_ebuf, "in line %d: Failed to find memory for array <%s>",
  1305. l->number, newvar->name );
  1306. bwb_error( bwb_ebuf );
  1307. #else
  1308. bwb_error( err_getmem );
  1309. #endif
  1310. return bwb_zline( l );
  1311. }
  1312. break;
  1313. case NUMBER:
  1314. #if INTENSIVE_DEBUG
  1315. sprintf( bwb_ebuf, "in bwb_dim(): 1 DOUBLE requires <%ld> bytes",
  1316. (long) sizeof( double ));
  1317. bwb_debug( bwb_ebuf );
  1318. sprintf( bwb_ebuf, "in bwb_dim(): DOUBLE array memory requires <%ld> bytes",
  1319. (long) ( newvar->array_units + 1 ) * sizeof( double ));
  1320. bwb_debug( bwb_ebuf );
  1321. #endif
  1322. /* Revised to CALLOC pass-thru call by JBV */
  1323. if ( ( np = (bnumber *)
  1324. CALLOC( newvar->array_units, sizeof( bnumber ), "bwb_dim" )) == NULL )
  1325. {
  1326. #if PROG_ERRORS
  1327. sprintf( bwb_ebuf, "in line %d: Failed to find memory for array <%s>",
  1328. l->number, newvar->name );
  1329. bwb_error( bwb_ebuf );
  1330. #else
  1331. bwb_error( err_getmem );
  1332. #endif
  1333. return bwb_zline( l );
  1334. }
  1335. newvar->memnum = np;
  1336. break;
  1337. default:
  1338. #if PROG_ERRORS
  1339. sprintf( bwb_ebuf, "in line %d: New variable has unrecognized type.",
  1340. l->number );
  1341. bwb_error( bwb_ebuf );
  1342. #else
  1343. bwb_error( err_syntax );
  1344. #endif
  1345. return bwb_zline( l );
  1346. }
  1347. } /* end of conditional for new variable */
  1348. /* now check for end of string */
  1349. if ( l->buffer[ l->position ] == ')' )
  1350. {
  1351. ++( l->position );
  1352. }
  1353. adv_ws( l->buffer, &( l->position ));
  1354. switch( l->buffer[ l->position ] )
  1355. {
  1356. case '\n': /* end of line */
  1357. case '\r':
  1358. case ':': /* end of line segment */
  1359. case '\0': /* end of string */
  1360. loop = FALSE;
  1361. break;
  1362. case ',':
  1363. ++( l->position );
  1364. adv_ws( l->buffer, &( l->position ) );
  1365. loop = TRUE;
  1366. break;
  1367. default:
  1368. #if PROG_ERRORS
  1369. sprintf( bwb_ebuf, "in bwb_dim(): unexpected end of string, buf <%s>",
  1370. &( l->buffer[ l->position ] ) );
  1371. bwb_error( bwb_ebuf );
  1372. #else
  1373. bwb_error( err_syntax );
  1374. #endif
  1375. loop = FALSE;
  1376. break;
  1377. }
  1378. } /* end of loop through variables */
  1379. /* return */
  1380. return bwb_zline( l );
  1381. }
  1382. /***************************************************************
  1383. FUNCTION: dim_unit()
  1384. DESCRIPTION: This function calculates the unit
  1385. position for an array.
  1386. ***************************************************************/
  1387. #if ANSI_C
  1388. static size_t
  1389. dim_unit( struct bwb_variable *v, int *pp )
  1390. #else
  1391. static size_t
  1392. dim_unit( v, pp )
  1393. struct bwb_variable *v;
  1394. int *pp;
  1395. #endif
  1396. {
  1397. size_t r;
  1398. size_t b;
  1399. register int n;
  1400. /* Calculate and return the address of the dimensioned array */
  1401. b = 1;
  1402. r = 0;
  1403. for ( n = 0; n < v->dimensions; ++n )
  1404. {
  1405. r += b * ( pp[ n ] - dim_base );
  1406. b *= v->array_sizes[ n ];
  1407. }
  1408. #if INTENSIVE_DEBUG
  1409. for ( n = 0; n < v->dimensions; ++n )
  1410. {
  1411. sprintf( bwb_ebuf,
  1412. "in dim_unit(): variable <%s> pos <%d> val <%d>.",
  1413. v->name, n, pp[ n ] );
  1414. bwb_debug( bwb_ebuf );
  1415. }
  1416. sprintf( bwb_ebuf, "in dim_unit(): return unit: <%ld>", (long) r );
  1417. bwb_debug( bwb_ebuf );
  1418. #endif
  1419. if ( r > v->array_units )
  1420. {
  1421. #if PROG_ERRORS
  1422. sprintf( bwb_ebuf, "in dim_unit(): unit value <%ld> exceeds array units <%ld>",
  1423. r, v->array_units );
  1424. bwb_error( bwb_ebuf );
  1425. #else
  1426. bwb_error( err_valoorange );
  1427. #endif
  1428. return 0;
  1429. }
  1430. return r;
  1431. }
  1432. /***************************************************************
  1433. FUNCTION: dim_getparams()
  1434. DESCRIPTION: This function reads a string in <buffer>
  1435. beginning at position <pos> and finds a
  1436. list of parameters surrounded by paren-
  1437. theses, returning in <n_params> the number
  1438. of parameters found, and returning in
  1439. <pp> an array of n_params integers giving
  1440. the sizes for each dimension of the array.
  1441. ***************************************************************/
  1442. #if ANSI_C
  1443. int
  1444. dim_getparams( char *buffer, int *pos, int *n_params, int **pp )
  1445. #else
  1446. int
  1447. dim_getparams( buffer, pos, n_params, pp )
  1448. char *buffer;
  1449. int *pos;
  1450. int *n_params;
  1451. int **pp;
  1452. #endif
  1453. {
  1454. int loop;
  1455. static int params[ MAX_DIMS ];
  1456. int x_pos, s_pos;
  1457. struct exp_ese *e;
  1458. char tbuf[ MAXSTRINGSIZE + 1 ];
  1459. int paren_level, quote_level; /* JBV 1/97 */
  1460. #if INTENSIVE_DEBUG
  1461. register int n;
  1462. #endif
  1463. /* set initial values */
  1464. *n_params = 0;
  1465. #if OLDSTUFF
  1466. paren_found = FALSE;
  1467. #endif
  1468. /* advance and check for undimensioned variable */
  1469. adv_ws( buffer, pos );
  1470. if ( buffer[ *pos ] != '(' )
  1471. {
  1472. *n_params = 1;
  1473. params[ 0 ] = dim_base;
  1474. *pp = params;
  1475. return TRUE;
  1476. }
  1477. else
  1478. {
  1479. ++(*pos);
  1480. }
  1481. /* Variable has DIMensions: Find each parameter */
  1482. s_pos = 0;
  1483. tbuf[ 0 ] = '\0';
  1484. loop = TRUE;
  1485. paren_level = 1; /* JBV 1/97 */
  1486. quote_level = 0; /* JBV 1/97 */
  1487. while( loop == TRUE )
  1488. {
  1489. switch( buffer[ *pos ] )
  1490. {
  1491. case ')': /* end of parameter list */
  1492. /*-----------------------------------------------------*/
  1493. /* paren_level and quote_level check added by JBV 1/97 */
  1494. /*-----------------------------------------------------*/
  1495. if ( quote_level == 0 ) --paren_level;
  1496. if ( paren_level != 0 || quote_level != 0 ) /* Still not done? */
  1497. {
  1498. tbuf[ s_pos ] = buffer[ *pos ];
  1499. ++(*pos);
  1500. ++s_pos;
  1501. tbuf[ s_pos ] = '\0';
  1502. break;
  1503. }
  1504. x_pos = 0;
  1505. if ( tbuf[ 0 ] == '\0' )
  1506. {
  1507. params[ *n_params ] = DEF_SUBSCRIPT;
  1508. }
  1509. else
  1510. {
  1511. #if INTENSIVE_DEBUG
  1512. sprintf( bwb_ebuf, "in dim_getparams(): call bwb_exp() for last element" );
  1513. bwb_debug( bwb_ebuf );
  1514. #endif
  1515. e = bwb_exp( tbuf, FALSE, &x_pos );
  1516. #if INTENSIVE_DEBUG
  1517. sprintf( bwb_ebuf, "in dim_getparams(): return from bwb_exp() for last element" );
  1518. bwb_debug( bwb_ebuf );
  1519. #endif
  1520. params[ *n_params ] = (int) exp_getnval( e );
  1521. }
  1522. ++(*n_params);
  1523. loop = FALSE;
  1524. ++( *pos );
  1525. break;
  1526. case ',': /* end of a parameter */
  1527. /*-----------------------------------------------------*/
  1528. /* paren_level and quote_level check added by JBV 1/97 */
  1529. /*-----------------------------------------------------*/
  1530. if ( paren_level != 1 || quote_level != 0 ) /* Still not done? */
  1531. {
  1532. tbuf[ s_pos ] = buffer[ *pos ];
  1533. ++(*pos);
  1534. ++s_pos;
  1535. tbuf[ s_pos ] = '\0';
  1536. break;
  1537. }
  1538. x_pos = 0;
  1539. if ( tbuf[ 0 ] == '\0' )
  1540. {
  1541. params[ *n_params ] = DEF_SUBSCRIPT;
  1542. }
  1543. else
  1544. {
  1545. #if INTENSIVE_DEBUG
  1546. sprintf( bwb_ebuf, "in dim_getparams(): call bwb_exp() for element (not last)" );
  1547. bwb_debug( bwb_ebuf );
  1548. #endif
  1549. e = bwb_exp( tbuf, FALSE, &x_pos );
  1550. params[ *n_params ] = (int) exp_getnval( e );
  1551. }
  1552. ++(*n_params);
  1553. tbuf[ 0 ] = '\0';
  1554. ++(*pos);
  1555. s_pos = 0;
  1556. break;
  1557. case ' ': /* whitespace -- skip */
  1558. case '\t':
  1559. ++(*pos);
  1560. break;
  1561. default:
  1562. if( buffer[ *pos ] == '(' && quote_level == 0 )
  1563. ++paren_level; /* JBV 1/97 */
  1564. if( buffer[ *pos ] == (char) 34 )
  1565. {
  1566. if (quote_level == 0) quote_level = 1;
  1567. else quote_level = 0;
  1568. }
  1569. tbuf[ s_pos ] = buffer[ *pos ];
  1570. ++(*pos);
  1571. ++s_pos;
  1572. tbuf[ s_pos ] = '\0';
  1573. break;
  1574. }
  1575. }
  1576. #if INTENSIVE_DEBUG
  1577. for ( n = 0; n < *n_params; ++n )
  1578. {
  1579. sprintf( bwb_ebuf, "in dim_getparams(): Parameter <%d>: <%d>",
  1580. n, params[ n ] );
  1581. bwb_debug( bwb_ebuf );
  1582. }
  1583. #endif
  1584. /* return params stack */
  1585. *pp = params;
  1586. return TRUE;
  1587. }
  1588. /***************************************************************
  1589. FUNCTION: bwb_option()
  1590. DESCRIPTION: This function implements the BASIC OPTION
  1591. BASE statement, designating the base (1 or
  1592. 0) for addressing DIM arrays.
  1593. SYNTAX: OPTION BASE number
  1594. ***************************************************************/
  1595. #if ANSI_C
  1596. struct bwb_line *
  1597. bwb_option( struct bwb_line *l )
  1598. #else
  1599. struct bwb_line *
  1600. bwb_option( l )
  1601. struct bwb_line *l;
  1602. #endif
  1603. {
  1604. register int n;
  1605. int newval;
  1606. struct exp_ese *e;
  1607. struct bwb_variable *current;
  1608. char tbuf[ MAXSTRINGSIZE ];
  1609. #if INTENSIVE_DEBUG
  1610. sprintf( bwb_ebuf, "in bwb_option(): entered function." );
  1611. bwb_debug( bwb_ebuf );
  1612. #endif
  1613. /* If DIM has already been called, do not allow OPTION BASE */
  1614. if ( dimmed != FALSE )
  1615. {
  1616. #if PROG_ERRORS
  1617. sprintf( bwb_ebuf, "at line %d: OPTION BASE must be called before DIM.",
  1618. l->number );
  1619. bwb_error( bwb_ebuf );
  1620. #else
  1621. bwb_error( err_obdim );
  1622. #endif
  1623. return bwb_zline( l );
  1624. }
  1625. /* capitalize first element in tbuf */
  1626. adv_element( l->buffer, &( l->position ), tbuf );
  1627. for ( n = 0; tbuf[ n ] != '\0'; ++n )
  1628. {
  1629. if ( islower( tbuf[ n ] ) != FALSE )
  1630. {
  1631. tbuf[ n ] = (char) toupper( tbuf[ n ] );
  1632. }
  1633. }
  1634. /* check for BASE statement */
  1635. if ( strncmp( tbuf, "BASE", (size_t) 4 ) != 0 )
  1636. {
  1637. #if PROG_ERRORS
  1638. sprintf( bwb_ebuf, "at line %d: Unknown statement <%s> following OPTION.",
  1639. l->number, tbuf );
  1640. bwb_error( bwb_ebuf );
  1641. #else
  1642. bwb_error( err_syntax );
  1643. #endif
  1644. return bwb_zline( l );
  1645. }
  1646. /* Get new value from argument. */
  1647. adv_ws( l->buffer, &( l->position ) );
  1648. e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  1649. newval = (int) exp_getnval( e );
  1650. /* Test the new value. */
  1651. #if INTENSIVE_DEBUG
  1652. sprintf( bwb_ebuf, "in bwb_option(): New value received is <%d>.", newval );
  1653. bwb_debug( bwb_ebuf );
  1654. #endif
  1655. if ( ( newval < 0 ) || ( newval > 1 ) )
  1656. {
  1657. #if PROG_ERRORS
  1658. sprintf( bwb_ebuf, "at line %d: value for OPTION BASE must be 1 or 0.",
  1659. l->number );
  1660. bwb_error( bwb_ebuf );
  1661. #else
  1662. bwb_error( err_valoorange );
  1663. #endif
  1664. return bwb_zline( l );
  1665. }
  1666. /* Set the new value. */
  1667. dim_base = newval;
  1668. /* run through the variable list and change any positions that had
  1669. set 0 before OPTION BASE was run */
  1670. for ( current = CURTASK var_start.next; current != &CURTASK var_end; current = current->next )
  1671. {
  1672. current->array_pos[ 0 ] = dim_base;
  1673. }
  1674. /* Return. */
  1675. return bwb_zline( l );
  1676. }
  1677. /***************************************************************
  1678. FUNCTION: var_findnval()
  1679. DESCRIPTION: This function returns the address of
  1680. the number for the variable <v>. If
  1681. <v> is a dimensioned array, the address
  1682. returned is for the double at the
  1683. position indicated by the integer array
  1684. <pp>.
  1685. ***************************************************************/
  1686. #if ANSI_C
  1687. bnumber *
  1688. var_findnval( struct bwb_variable *v, int *pp )
  1689. #else
  1690. bnumber *
  1691. var_findnval( v, pp )
  1692. struct bwb_variable *v;
  1693. int *pp;
  1694. #endif
  1695. {
  1696. size_t offset;
  1697. bnumber *p;
  1698. #if INTENSIVE_DEBUG
  1699. register int n;
  1700. #endif
  1701. /* Check for appropriate type */
  1702. if ( v->type != NUMBER )
  1703. {
  1704. #if PROG_ERRORS
  1705. sprintf ( bwb_ebuf, "in var_findnval(): Variable <%s> is not a number.",
  1706. v->name );
  1707. bwb_error( bwb_ebuf );
  1708. #else
  1709. bwb_error( err_mismatch );
  1710. #endif
  1711. return NULL;
  1712. }
  1713. /* Check subscripts */
  1714. if ( dim_check( v, pp ) == FALSE )
  1715. {
  1716. return NULL;
  1717. }
  1718. /* Calculate and return the address of the dimensioned array */
  1719. offset = dim_unit( v, pp );
  1720. #if INTENSIVE_DEBUG
  1721. for ( n = 0; n < v->dimensions; ++n )
  1722. {
  1723. sprintf( bwb_ebuf,
  1724. "in var_findnval(): dimensioned variable pos <%d> <%d>.",
  1725. n, pp[ n ] );
  1726. bwb_debug( bwb_ebuf );
  1727. }
  1728. #endif
  1729. p = v->memnum;
  1730. return (p + offset);
  1731. }
  1732. /***************************************************************
  1733. FUNCTION: var_findsval()
  1734. DESCRIPTION: This function returns the address of
  1735. the string for the variable <v>. If
  1736. <v> is a dimensioned array, the address
  1737. returned is for the string at the
  1738. position indicated by the integer array
  1739. <pp>.
  1740. ***************************************************************/
  1741. #if ANSI_C
  1742. bstring *
  1743. var_findsval( struct bwb_variable *v, int *pp )
  1744. #else
  1745. bstring *
  1746. var_findsval( v, pp )
  1747. struct bwb_variable *v;
  1748. int *pp;
  1749. #endif
  1750. {
  1751. size_t offset;
  1752. bstring *p;
  1753. #if INTENSIVE_DEBUG
  1754. register int n;
  1755. sprintf( bwb_ebuf, "in var_findsval(): entered, var <%s>", v->name );
  1756. bwb_debug( bwb_ebuf );
  1757. #endif
  1758. /* Check for appropriate type */
  1759. if ( v->type != STRING )
  1760. {
  1761. #if PROG_ERRORS
  1762. sprintf ( bwb_ebuf, "in var_findsval(): Variable <%s> is not a string.", v->name );
  1763. bwb_error( bwb_ebuf );
  1764. #else
  1765. bwb_error( err_mismatch );
  1766. #endif
  1767. return NULL;
  1768. }
  1769. /* Check subscripts */
  1770. if ( dim_check( v, pp ) == FALSE )
  1771. {
  1772. return NULL;
  1773. }
  1774. /* Calculate and return the address of the dimensioned array */
  1775. offset = dim_unit( v, pp );
  1776. #if INTENSIVE_DEBUG
  1777. for ( n = 0; n < v->dimensions; ++n )
  1778. {
  1779. sprintf( bwb_ebuf,
  1780. "in var_findsval(): dimensioned variable pos <%d> val <%d>.",
  1781. n, pp[ n ] );
  1782. bwb_debug( bwb_ebuf );
  1783. }
  1784. #endif
  1785. p = v->memstr;
  1786. return (p + offset);
  1787. }
  1788. /***************************************************************
  1789. FUNCTION: dim_check()
  1790. DESCRIPTION: This function checks subscripts of a
  1791. specific variable to be sure that they
  1792. are within the correct range.
  1793. ***************************************************************/
  1794. #if ANSI_C
  1795. static int
  1796. dim_check( struct bwb_variable *v, int *pp )
  1797. #else
  1798. static int
  1799. dim_check( v, pp )
  1800. struct bwb_variable *v;
  1801. int *pp;
  1802. #endif
  1803. {
  1804. register int n;
  1805. /* Check for dimensions */
  1806. if ( v->dimensions < 1 )
  1807. {
  1808. #if PROG_ERRORS
  1809. sprintf( bwb_ebuf, "in dim_check(): var <%s> dimensions <%d>",
  1810. v->name, v->dimensions );
  1811. bwb_error( bwb_ebuf );
  1812. #else
  1813. bwb_error( err_valoorange );
  1814. #endif
  1815. return FALSE;
  1816. }
  1817. /* Check for validly allocated array */
  1818. if (( v->type == NUMBER ) && ( v->memnum == NULL ))
  1819. {
  1820. #if PROG_ERRORS
  1821. sprintf( bwb_ebuf, "in dim_check(): numerical var <%s> memnum not allocated",
  1822. v->name );
  1823. bwb_error( bwb_ebuf );
  1824. #else
  1825. bwb_error( err_valoorange );
  1826. #endif
  1827. return FALSE;
  1828. }
  1829. if (( v->type == STRING ) && ( v->memstr == NULL ))
  1830. {
  1831. #if PROG_ERRORS
  1832. sprintf( bwb_ebuf, "in dim_check(): string var <%s> memstr not allocated",
  1833. v->name );
  1834. bwb_error( bwb_ebuf );
  1835. #else
  1836. bwb_error( err_valoorange );
  1837. #endif
  1838. return FALSE;
  1839. }
  1840. /* Now check subscript values */
  1841. for ( n = 0; n < v->dimensions; ++n )
  1842. {
  1843. if ( ( pp[ n ] < dim_base ) || ( ( pp[ n ] - dim_base )
  1844. > v->array_sizes[ n ] ))
  1845. {
  1846. #if PROG_ERRORS
  1847. sprintf( bwb_ebuf, "in dim_check(): array subscript var <%s> pos <%d> val <%d> out of range <%d>-<%d>.",
  1848. v->name, n, pp[ n ], dim_base, v->array_sizes[ n ] );
  1849. bwb_error( bwb_ebuf );
  1850. #else
  1851. bwb_error( err_valoorange );
  1852. #endif
  1853. return FALSE;
  1854. }
  1855. }
  1856. /* No problems found */
  1857. return TRUE;
  1858. }
  1859. /***************************************************************
  1860. FUNCTION: var_make()
  1861. DESCRIPTION: This function initializes a variable,
  1862. allocating necessary memory for it.
  1863. ***************************************************************/
  1864. #if ANSI_C
  1865. int
  1866. var_make( struct bwb_variable *v, int type )
  1867. #else
  1868. int
  1869. var_make( v, type )
  1870. struct bwb_variable *v;
  1871. int type;
  1872. #endif
  1873. {
  1874. size_t data_size;
  1875. bstring *b;
  1876. bstring *sp; /* JBV */
  1877. register int n; /* JBV */
  1878. #if TEST_BSTRING
  1879. static int tnumber = 0;
  1880. #endif
  1881. switch( type )
  1882. {
  1883. case STRING:
  1884. v->type = STRING;
  1885. data_size = sizeof( bstring );
  1886. break;
  1887. default:
  1888. v->type = NUMBER;
  1889. data_size = sizeof( bnumber );
  1890. break;
  1891. }
  1892. /* get memory for array */
  1893. /* First kleanup the joint (JBV) */
  1894. if (v->memnum != NULL)
  1895. {
  1896. /* Revised to FREE pass-thru call by JBV */
  1897. FREE(v->memnum, "var_make");
  1898. v->memnum = NULL;
  1899. }
  1900. if (v->memstr != NULL)
  1901. {
  1902. /* Remember to deallocate those far-flung branches! (JBV) */
  1903. sp = v->memstr;
  1904. for ( n = 0; n < (int) v->array_units; ++n )
  1905. {
  1906. if ( sp[ n ].sbuffer != NULL )
  1907. {
  1908. /* Revised to FREE pass-thru call by JBV */
  1909. FREE( sp[ n ].sbuffer, "var_make" );
  1910. sp[ n ].sbuffer = NULL;
  1911. }
  1912. sp[ n ].rab = FALSE;
  1913. sp[ n ].length = 0;
  1914. }
  1915. /* Revised to FREE pass-thru call by JBV */
  1916. FREE(v->memstr, "var_make");
  1917. v->memstr = NULL;
  1918. }
  1919. /* Revised to FREE pass-thru calls by JBV */
  1920. if (v->array_sizes != NULL)
  1921. {
  1922. FREE(v->array_sizes, "var_make");
  1923. v->array_sizes = NULL; /* JBV */
  1924. }
  1925. if (v->array_pos != NULL)
  1926. {
  1927. FREE(v->array_pos, "var_make");
  1928. v->array_pos = NULL; /* JBV */
  1929. }
  1930. if ( v->type == NUMBER )
  1931. {
  1932. /* Revised to CALLOC pass-thru call by JBV */
  1933. if ( ( v->memnum = CALLOC( 2, sizeof( bnumber ), "var_make" )) == NULL )
  1934. {
  1935. bwb_error( err_getmem );
  1936. return FALSE;
  1937. }
  1938. }
  1939. else
  1940. {
  1941. /* Revised to CALLOC pass-thru call by JBV */
  1942. if ( ( v->memstr = CALLOC( 2, sizeof( bstring ), "var_make" )) == NULL )
  1943. {
  1944. bwb_error( err_getmem );
  1945. return FALSE;
  1946. }
  1947. }
  1948. /* get memory for array_sizes and array_pos */
  1949. /* Revised to CALLOC pass-thru call by JBV */
  1950. if ( ( v->array_sizes = (int *) CALLOC( 2, sizeof( int ), "var_make" )) == NULL )
  1951. {
  1952. bwb_error( err_getmem );
  1953. return FALSE;
  1954. }
  1955. /* Revised to CALLOC pass-thru call by JBV */
  1956. if ( ( v->array_pos = (int *) CALLOC( 2, sizeof( int ), "var_make" )) == NULL )
  1957. {
  1958. bwb_error( err_getmem );
  1959. return FALSE;
  1960. }
  1961. v->array_pos[ 0 ] = dim_base;
  1962. v->array_sizes[ 0 ] = 1;
  1963. v->dimensions = 1;
  1964. v->common = FALSE;
  1965. v->array_units = 1;
  1966. if ( type == STRING )
  1967. {
  1968. b = var_findsval( v, v->array_pos );
  1969. b->rab = FALSE;
  1970. }
  1971. #if INTENSIVE_DEBUG
  1972. sprintf( bwb_ebuf, "in var_make(): made variable <%s> type <%c> pos[ 0 ] <%d>",
  1973. v->name, v->type, v->array_pos[ 0 ] );
  1974. bwb_debug( bwb_ebuf );
  1975. #endif
  1976. #if TEST_BSTRING
  1977. if ( type == STRING )
  1978. {
  1979. b = var_findsval( v, v->array_pos );
  1980. sprintf( b->name, "bstring# %d", tnumber );
  1981. ++tnumber;
  1982. sprintf( bwb_ebuf, "in var_make(): new string variable <%s>",
  1983. b->name );
  1984. bwb_debug( bwb_ebuf );
  1985. }
  1986. #endif
  1987. return TRUE;
  1988. }
  1989. /***************************************************************
  1990. FUNCTION: var_islocal()
  1991. DESCRIPTION: This function determines whether the string
  1992. pointed to by 'buffer' has the name of
  1993. a local variable at the present EXEC stack
  1994. level.
  1995. ***************************************************************/
  1996. #if ANSI_C
  1997. extern struct bwb_variable *
  1998. var_islocal( char *buffer )
  1999. #else
  2000. struct bwb_variable *
  2001. var_islocal( buffer )
  2002. char *buffer;
  2003. #endif
  2004. {
  2005. struct bwb_variable *v;
  2006. #if INTENSIVE_DEBUG
  2007. sprintf( bwb_ebuf, "in var_islocal(): check for local variable <%s> EXEC level <%d>",
  2008. buffer, CURTASK exsc );
  2009. bwb_debug( bwb_ebuf );
  2010. #endif
  2011. /* Prevent the expression in the initial value of the for loop below
  2012. from violating the lower bound of the "excs" array. This would
  2013. happen during startup when "exsc" is initially set to -1 and
  2014. bwbasic.exe would fail with a memory exception when compiled with
  2015. Open Watcom C. */
  2016. if ( CURTASK exsc >= 0 )
  2017. {
  2018. /* run through the local variable list and try to find a match */
  2019. for ( v = CURTASK excs[ CURTASK exsc ].local_variable; v != NULL; v = v->next )
  2020. {
  2021. #if INTENSIVE_DEBUG
  2022. sprintf( bwb_ebuf, "in var_islocal(): checking var <%s> level <%d>...",
  2023. v->name, CURTASK exsc );
  2024. bwb_debug( bwb_ebuf );
  2025. #endif
  2026. if ( strcmp( v->name, buffer ) == 0 )
  2027. {
  2028. #if PROG_ERRORS
  2029. switch( v->type )
  2030. {
  2031. case STRING:
  2032. case NUMBER:
  2033. break;
  2034. default:
  2035. sprintf( bwb_ebuf, "in var_islocal(): inappropriate precision for variable <%s>",
  2036. v->name );
  2037. bwb_error( bwb_ebuf );
  2038. break;
  2039. }
  2040. #endif
  2041. #if INTENSIVE_DEBUG
  2042. sprintf( bwb_ebuf, "in var_islocal(): found local variable <%s>", v->name );
  2043. bwb_debug( bwb_ebuf );
  2044. #endif
  2045. return v;
  2046. }
  2047. }
  2048. } /* check of exsc >= 0 */
  2049. /* search failed, return NULL */
  2050. #if INTENSIVE_DEBUG
  2051. sprintf( bwb_ebuf, "in var_islocal(): Failed to find local variable <%s> level <%d>",
  2052. buffer, CURTASK exsc );
  2053. bwb_debug( bwb_ebuf );
  2054. #endif
  2055. return NULL;
  2056. }
  2057. /***************************************************************
  2058. FUNCTION: bwb_vars()
  2059. DESCRIPTION: This function implements the Bywater-
  2060. specific debugging command VARS, which
  2061. gives a list of all variables defined
  2062. in memory.
  2063. ***************************************************************/
  2064. #if PERMANENT_DEBUG
  2065. #if ANSI_C
  2066. struct bwb_line *
  2067. bwb_vars( struct bwb_line *l )
  2068. #else
  2069. struct bwb_line *
  2070. bwb_vars( l )
  2071. struct bwb_line *l;
  2072. #endif
  2073. {
  2074. struct bwb_variable *v;
  2075. char tbuf[ MAXSTRINGSIZE + 1 ];
  2076. /* run through the variable list and print variables */
  2077. for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  2078. {
  2079. sprintf( bwb_ebuf, "variable <%s>\t", v->name );
  2080. prn_xprintf( stdout, bwb_ebuf );
  2081. switch( v->type )
  2082. {
  2083. case STRING:
  2084. str_btoc( tbuf, var_getsval( v ) );
  2085. sprintf( bwb_ebuf, "STRING\tval: <%s>\n", tbuf );
  2086. prn_xprintf( stdout, bwb_ebuf );
  2087. break;
  2088. case NUMBER:
  2089. #if NUMBER_DOUBLE
  2090. sprintf( bwb_ebuf, "NUMBER\tval: <%lf>\n", var_getnval( v ) );
  2091. prn_xprintf( stdout, bwb_ebuf );
  2092. #else
  2093. sprintf( bwb_ebuf, "NUMBER\tval: <%f>\n", var_getnval( v ) );
  2094. prn_xprintf( stdout, bwb_ebuf );
  2095. #endif
  2096. break;
  2097. default:
  2098. sprintf( bwb_ebuf, "ERROR: type is <%c>", (char) v->type );
  2099. prn_xprintf( stdout, bwb_ebuf );
  2100. break;
  2101. }
  2102. }
  2103. return bwb_zline( l );
  2104. }
  2105. #endif