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.
 
 
 
 
 
 

2590 lines
60 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. #if INTENSIVE_DEBUG
  1460. register int n;
  1461. #endif
  1462. /* set initial values */
  1463. *n_params = 0;
  1464. #if OLDSTUFF
  1465. paren_found = FALSE;
  1466. #endif
  1467. /* advance and check for undimensioned variable */
  1468. adv_ws( buffer, pos );
  1469. if ( buffer[ *pos ] != '(' )
  1470. {
  1471. *n_params = 1;
  1472. params[ 0 ] = dim_base;
  1473. *pp = params;
  1474. return TRUE;
  1475. }
  1476. else
  1477. {
  1478. ++(*pos);
  1479. }
  1480. /* Variable has DIMensions: Find each parameter */
  1481. s_pos = 0;
  1482. tbuf[ 0 ] = '\0';
  1483. loop = TRUE;
  1484. while( loop == TRUE )
  1485. {
  1486. switch( buffer[ *pos ] )
  1487. {
  1488. case ')': /* end of parameter list */
  1489. x_pos = 0;
  1490. if ( tbuf[ 0 ] == '\0' )
  1491. {
  1492. params[ *n_params ] = DEF_SUBSCRIPT;
  1493. }
  1494. else
  1495. {
  1496. #if INTENSIVE_DEBUG
  1497. sprintf( bwb_ebuf, "in dim_getparams(): call bwb_exp() for last element" );
  1498. bwb_debug( bwb_ebuf );
  1499. #endif
  1500. e = bwb_exp( tbuf, FALSE, &x_pos );
  1501. #if INTENSIVE_DEBUG
  1502. sprintf( bwb_ebuf, "in dim_getparams(): return from bwb_exp() for last element" );
  1503. bwb_debug( bwb_ebuf );
  1504. #endif
  1505. params[ *n_params ] = (int) exp_getnval( e );
  1506. }
  1507. ++(*n_params);
  1508. loop = FALSE;
  1509. ++( *pos );
  1510. break;
  1511. case ',': /* end of a parameter */
  1512. x_pos = 0;
  1513. if ( tbuf[ 0 ] == '\0' )
  1514. {
  1515. params[ *n_params ] = DEF_SUBSCRIPT;
  1516. }
  1517. else
  1518. {
  1519. #if INTENSIVE_DEBUG
  1520. sprintf( bwb_ebuf, "in dim_getparams(): call bwb_exp() for element (not last)" );
  1521. bwb_debug( bwb_ebuf );
  1522. #endif
  1523. e = bwb_exp( tbuf, FALSE, &x_pos );
  1524. params[ *n_params ] = (int) exp_getnval( e );
  1525. }
  1526. ++(*n_params);
  1527. tbuf[ 0 ] = '\0';
  1528. ++(*pos);
  1529. s_pos = 0;
  1530. break;
  1531. case ' ': /* whitespace -- skip */
  1532. case '\t':
  1533. ++(*pos);
  1534. break;
  1535. default:
  1536. tbuf[ s_pos ] = buffer[ *pos ];
  1537. ++(*pos);
  1538. ++s_pos;
  1539. tbuf[ s_pos ] = '\0';
  1540. break;
  1541. }
  1542. }
  1543. #if INTENSIVE_DEBUG
  1544. for ( n = 0; n < *n_params; ++n )
  1545. {
  1546. sprintf( bwb_ebuf, "in dim_getparams(): Parameter <%d>: <%d>",
  1547. n, params[ n ] );
  1548. bwb_debug( bwb_ebuf );
  1549. }
  1550. #endif
  1551. /* return params stack */
  1552. *pp = params;
  1553. return TRUE;
  1554. }
  1555. /***************************************************************
  1556. FUNCTION: bwb_option()
  1557. DESCRIPTION: This function implements the BASIC OPTION
  1558. BASE statement, designating the base (1 or
  1559. 0) for addressing DIM arrays.
  1560. SYNTAX: OPTION BASE number
  1561. ***************************************************************/
  1562. #if ANSI_C
  1563. struct bwb_line *
  1564. bwb_option( struct bwb_line *l )
  1565. #else
  1566. struct bwb_line *
  1567. bwb_option( l )
  1568. struct bwb_line *l;
  1569. #endif
  1570. {
  1571. register int n;
  1572. int newval;
  1573. struct exp_ese *e;
  1574. struct bwb_variable *current;
  1575. char tbuf[ MAXSTRINGSIZE ];
  1576. #if INTENSIVE_DEBUG
  1577. sprintf( bwb_ebuf, "in bwb_option(): entered function." );
  1578. bwb_debug( bwb_ebuf );
  1579. #endif
  1580. /* If DIM has already been called, do not allow OPTION BASE */
  1581. if ( dimmed != FALSE )
  1582. {
  1583. #if PROG_ERRORS
  1584. sprintf( bwb_ebuf, "at line %d: OPTION BASE must be called before DIM.",
  1585. l->number );
  1586. bwb_error( bwb_ebuf );
  1587. #else
  1588. bwb_error( err_obdim );
  1589. #endif
  1590. return bwb_zline( l );
  1591. }
  1592. /* capitalize first element in tbuf */
  1593. adv_element( l->buffer, &( l->position ), tbuf );
  1594. for ( n = 0; tbuf[ n ] != '\0'; ++n )
  1595. {
  1596. if ( islower( tbuf[ n ] ) != FALSE )
  1597. {
  1598. tbuf[ n ] = (char) toupper( tbuf[ n ] );
  1599. }
  1600. }
  1601. /* check for BASE statement */
  1602. if ( strncmp( tbuf, "BASE", (size_t) 4 ) != 0 )
  1603. {
  1604. #if PROG_ERRORS
  1605. sprintf( bwb_ebuf, "at line %d: Unknown statement <%s> following OPTION.",
  1606. l->number, tbuf );
  1607. bwb_error( bwb_ebuf );
  1608. #else
  1609. bwb_error( err_syntax );
  1610. #endif
  1611. return bwb_zline( l );
  1612. }
  1613. /* Get new value from argument. */
  1614. adv_ws( l->buffer, &( l->position ) );
  1615. e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  1616. newval = (int) exp_getnval( e );
  1617. /* Test the new value. */
  1618. #if INTENSIVE_DEBUG
  1619. sprintf( bwb_ebuf, "in bwb_option(): New value received is <%d>.", newval );
  1620. bwb_debug( bwb_ebuf );
  1621. #endif
  1622. if ( ( newval < 0 ) || ( newval > 1 ) )
  1623. {
  1624. #if PROG_ERRORS
  1625. sprintf( bwb_ebuf, "at line %d: value for OPTION BASE must be 1 or 0.",
  1626. l->number );
  1627. bwb_error( bwb_ebuf );
  1628. #else
  1629. bwb_error( err_valoorange );
  1630. #endif
  1631. return bwb_zline( l );
  1632. }
  1633. /* Set the new value. */
  1634. dim_base = newval;
  1635. /* run through the variable list and change any positions that had
  1636. set 0 before OPTION BASE was run */
  1637. for ( current = CURTASK var_start.next; current != &CURTASK var_end; current = current->next )
  1638. {
  1639. current->array_pos[ 0 ] = dim_base;
  1640. }
  1641. /* Return. */
  1642. return bwb_zline( l );
  1643. }
  1644. /***************************************************************
  1645. FUNCTION: var_findnval()
  1646. DESCRIPTION: This function returns the address of
  1647. the number for the variable <v>. If
  1648. <v> is a dimensioned array, the address
  1649. returned is for the double at the
  1650. position indicated by the integer array
  1651. <pp>.
  1652. ***************************************************************/
  1653. #if ANSI_C
  1654. bnumber *
  1655. var_findnval( struct bwb_variable *v, int *pp )
  1656. #else
  1657. bnumber *
  1658. var_findnval( v, pp )
  1659. struct bwb_variable *v;
  1660. int *pp;
  1661. #endif
  1662. {
  1663. size_t offset;
  1664. bnumber *p;
  1665. #if INTENSIVE_DEBUG
  1666. register int n;
  1667. #endif
  1668. /* Check for appropriate type */
  1669. if ( v->type != NUMBER )
  1670. {
  1671. #if PROG_ERRORS
  1672. sprintf ( bwb_ebuf, "in var_findnval(): Variable <%s> is not a number.",
  1673. v->name );
  1674. bwb_error( bwb_ebuf );
  1675. #else
  1676. bwb_error( err_mismatch );
  1677. #endif
  1678. return NULL;
  1679. }
  1680. /* Check subscripts */
  1681. if ( dim_check( v, pp ) == FALSE )
  1682. {
  1683. return NULL;
  1684. }
  1685. /* Calculate and return the address of the dimensioned array */
  1686. offset = dim_unit( v, pp );
  1687. #if INTENSIVE_DEBUG
  1688. for ( n = 0; n < v->dimensions; ++n )
  1689. {
  1690. sprintf( bwb_ebuf,
  1691. "in var_findnval(): dimensioned variable pos <%d> <%d>.",
  1692. n, pp[ n ] );
  1693. bwb_debug( bwb_ebuf );
  1694. }
  1695. #endif
  1696. p = v->memnum;
  1697. return (p + offset);
  1698. }
  1699. /***************************************************************
  1700. FUNCTION: var_findsval()
  1701. DESCRIPTION: This function returns the address of
  1702. the string for the variable <v>. If
  1703. <v> is a dimensioned array, the address
  1704. returned is for the string at the
  1705. position indicated by the integer array
  1706. <pp>.
  1707. ***************************************************************/
  1708. #if ANSI_C
  1709. bstring *
  1710. var_findsval( struct bwb_variable *v, int *pp )
  1711. #else
  1712. bstring *
  1713. var_findsval( v, pp )
  1714. struct bwb_variable *v;
  1715. int *pp;
  1716. #endif
  1717. {
  1718. size_t offset;
  1719. bstring *p;
  1720. #if INTENSIVE_DEBUG
  1721. register int n;
  1722. sprintf( bwb_ebuf, "in var_findsval(): entered, var <%s>", v->name );
  1723. bwb_debug( bwb_ebuf );
  1724. #endif
  1725. /* Check for appropriate type */
  1726. if ( v->type != STRING )
  1727. {
  1728. #if PROG_ERRORS
  1729. sprintf ( bwb_ebuf, "in var_findsval(): Variable <%s> is not a string.", v->name );
  1730. bwb_error( bwb_ebuf );
  1731. #else
  1732. bwb_error( err_mismatch );
  1733. #endif
  1734. return NULL;
  1735. }
  1736. /* Check subscripts */
  1737. if ( dim_check( v, pp ) == FALSE )
  1738. {
  1739. return NULL;
  1740. }
  1741. /* Calculate and return the address of the dimensioned array */
  1742. offset = dim_unit( v, pp );
  1743. #if INTENSIVE_DEBUG
  1744. for ( n = 0; n < v->dimensions; ++n )
  1745. {
  1746. sprintf( bwb_ebuf,
  1747. "in var_findsval(): dimensioned variable pos <%d> val <%d>.",
  1748. n, pp[ n ] );
  1749. bwb_debug( bwb_ebuf );
  1750. }
  1751. #endif
  1752. p = v->memstr;
  1753. return (p + offset);
  1754. }
  1755. /***************************************************************
  1756. FUNCTION: dim_check()
  1757. DESCRIPTION: This function checks subscripts of a
  1758. specific variable to be sure that they
  1759. are within the correct range.
  1760. ***************************************************************/
  1761. #if ANSI_C
  1762. static int
  1763. dim_check( struct bwb_variable *v, int *pp )
  1764. #else
  1765. static int
  1766. dim_check( v, pp )
  1767. struct bwb_variable *v;
  1768. int *pp;
  1769. #endif
  1770. {
  1771. register int n;
  1772. /* Check for dimensions */
  1773. if ( v->dimensions < 1 )
  1774. {
  1775. #if PROG_ERRORS
  1776. sprintf( bwb_ebuf, "in dim_check(): var <%s> dimensions <%d>",
  1777. v->name, v->dimensions );
  1778. bwb_error( bwb_ebuf );
  1779. #else
  1780. bwb_error( err_valoorange );
  1781. #endif
  1782. return FALSE;
  1783. }
  1784. /* Check for validly allocated array */
  1785. if (( v->type == NUMBER ) && ( v->memnum == NULL ))
  1786. {
  1787. #if PROG_ERRORS
  1788. sprintf( bwb_ebuf, "in dim_check(): numerical var <%s> memnum not allocated",
  1789. v->name );
  1790. bwb_error( bwb_ebuf );
  1791. #else
  1792. bwb_error( err_valoorange );
  1793. #endif
  1794. return FALSE;
  1795. }
  1796. if (( v->type == STRING ) && ( v->memstr == NULL ))
  1797. {
  1798. #if PROG_ERRORS
  1799. sprintf( bwb_ebuf, "in dim_check(): string var <%s> memstr not allocated",
  1800. v->name );
  1801. bwb_error( bwb_ebuf );
  1802. #else
  1803. bwb_error( err_valoorange );
  1804. #endif
  1805. return FALSE;
  1806. }
  1807. /* Now check subscript values */
  1808. for ( n = 0; n < v->dimensions; ++n )
  1809. {
  1810. if ( ( pp[ n ] < dim_base ) || ( ( pp[ n ] - dim_base )
  1811. > v->array_sizes[ n ] ))
  1812. {
  1813. #if PROG_ERRORS
  1814. sprintf( bwb_ebuf, "in dim_check(): array subscript var <%s> pos <%d> val <%d> out of range <%d>-<%d>.",
  1815. v->name, n, pp[ n ], dim_base, v->array_sizes[ n ] );
  1816. bwb_error( bwb_ebuf );
  1817. #else
  1818. bwb_error( err_valoorange );
  1819. #endif
  1820. return FALSE;
  1821. }
  1822. }
  1823. /* No problems found */
  1824. return TRUE;
  1825. }
  1826. /***************************************************************
  1827. FUNCTION: var_make()
  1828. DESCRIPTION: This function initializes a variable,
  1829. allocating necessary memory for it.
  1830. ***************************************************************/
  1831. #if ANSI_C
  1832. int
  1833. var_make( struct bwb_variable *v, int type )
  1834. #else
  1835. int
  1836. var_make( v, type )
  1837. struct bwb_variable *v;
  1838. int type;
  1839. #endif
  1840. {
  1841. size_t data_size;
  1842. bstring *b;
  1843. bstring *sp; /* JBV */
  1844. register int n; /* JBV */
  1845. #if TEST_BSTRING
  1846. static int tnumber = 0;
  1847. #endif
  1848. switch( type )
  1849. {
  1850. case STRING:
  1851. v->type = STRING;
  1852. data_size = sizeof( bstring );
  1853. break;
  1854. default:
  1855. v->type = NUMBER;
  1856. data_size = sizeof( bnumber );
  1857. break;
  1858. }
  1859. /* get memory for array */
  1860. /* First kleanup the joint (JBV) */
  1861. if (v->memnum != NULL)
  1862. {
  1863. /* Revised to FREE pass-thru call by JBV */
  1864. FREE(v->memnum, "var_make");
  1865. v->memnum = NULL;
  1866. }
  1867. if (v->memstr != NULL)
  1868. {
  1869. /* Remember to deallocate those far-flung branches! (JBV) */
  1870. sp = v->memstr;
  1871. for ( n = 0; n < (int) v->array_units; ++n )
  1872. {
  1873. if ( sp[ n ].sbuffer != NULL )
  1874. {
  1875. /* Revised to FREE pass-thru call by JBV */
  1876. FREE( sp[ n ].sbuffer, "var_make" );
  1877. sp[ n ].sbuffer = NULL;
  1878. }
  1879. sp[ n ].rab = FALSE;
  1880. sp[ n ].length = 0;
  1881. }
  1882. /* Revised to FREE pass-thru call by JBV */
  1883. FREE(v->memstr, "var_make");
  1884. v->memstr = NULL;
  1885. }
  1886. /* Revised to FREE pass-thru calls by JBV */
  1887. if (v->array_sizes != NULL)
  1888. {
  1889. FREE(v->array_sizes, "var_make");
  1890. v->array_sizes = NULL; /* JBV */
  1891. }
  1892. if (v->array_pos != NULL)
  1893. {
  1894. FREE(v->array_pos, "var_make");
  1895. v->array_pos = NULL; /* JBV */
  1896. }
  1897. if ( v->type == NUMBER )
  1898. {
  1899. /* Revised to CALLOC pass-thru call by JBV */
  1900. if ( ( v->memnum = CALLOC( 2, sizeof( bnumber ), "var_make" )) == NULL )
  1901. {
  1902. bwb_error( err_getmem );
  1903. return FALSE;
  1904. }
  1905. }
  1906. else
  1907. {
  1908. /* Revised to CALLOC pass-thru call by JBV */
  1909. if ( ( v->memstr = CALLOC( 2, sizeof( bstring ), "var_make" )) == NULL )
  1910. {
  1911. bwb_error( err_getmem );
  1912. return FALSE;
  1913. }
  1914. }
  1915. /* get memory for array_sizes and array_pos */
  1916. /* Revised to CALLOC pass-thru call by JBV */
  1917. if ( ( v->array_sizes = (int *) CALLOC( 2, sizeof( int ), "var_make" )) == NULL )
  1918. {
  1919. bwb_error( err_getmem );
  1920. return FALSE;
  1921. }
  1922. /* Revised to CALLOC pass-thru call by JBV */
  1923. if ( ( v->array_pos = (int *) CALLOC( 2, sizeof( int ), "var_make" )) == NULL )
  1924. {
  1925. bwb_error( err_getmem );
  1926. return FALSE;
  1927. }
  1928. v->array_pos[ 0 ] = dim_base;
  1929. v->array_sizes[ 0 ] = 1;
  1930. v->dimensions = 1;
  1931. v->common = FALSE;
  1932. v->array_units = 1;
  1933. if ( type == STRING )
  1934. {
  1935. b = var_findsval( v, v->array_pos );
  1936. b->rab = FALSE;
  1937. }
  1938. #if INTENSIVE_DEBUG
  1939. sprintf( bwb_ebuf, "in var_make(): made variable <%s> type <%c> pos[ 0 ] <%d>",
  1940. v->name, v->type, v->array_pos[ 0 ] );
  1941. bwb_debug( bwb_ebuf );
  1942. #endif
  1943. #if TEST_BSTRING
  1944. if ( type == STRING )
  1945. {
  1946. b = var_findsval( v, v->array_pos );
  1947. sprintf( b->name, "bstring# %d", tnumber );
  1948. ++tnumber;
  1949. sprintf( bwb_ebuf, "in var_make(): new string variable <%s>",
  1950. b->name );
  1951. bwb_debug( bwb_ebuf );
  1952. }
  1953. #endif
  1954. return TRUE;
  1955. }
  1956. /***************************************************************
  1957. FUNCTION: var_islocal()
  1958. DESCRIPTION: This function determines whether the string
  1959. pointed to by 'buffer' has the name of
  1960. a local variable at the present EXEC stack
  1961. level.
  1962. ***************************************************************/
  1963. #if ANSI_C
  1964. extern struct bwb_variable *
  1965. var_islocal( char *buffer )
  1966. #else
  1967. struct bwb_variable *
  1968. var_islocal( buffer )
  1969. char *buffer;
  1970. #endif
  1971. {
  1972. struct bwb_variable *v;
  1973. #if INTENSIVE_DEBUG
  1974. sprintf( bwb_ebuf, "in var_islocal(): check for local variable <%s> EXEC level <%d>",
  1975. buffer, CURTASK exsc );
  1976. bwb_debug( bwb_ebuf );
  1977. #endif
  1978. /* run through the local variable list and try to find a match */
  1979. for ( v = CURTASK excs[ CURTASK exsc ].local_variable; v != NULL; v = v->next )
  1980. {
  1981. #if INTENSIVE_DEBUG
  1982. sprintf( bwb_ebuf, "in var_islocal(): checking var <%s> level <%d>...",
  1983. v->name, CURTASK exsc );
  1984. bwb_debug( bwb_ebuf );
  1985. #endif
  1986. if ( strcmp( v->name, buffer ) == 0 )
  1987. {
  1988. #if PROG_ERRORS
  1989. switch( v->type )
  1990. {
  1991. case STRING:
  1992. case NUMBER:
  1993. break;
  1994. default:
  1995. sprintf( bwb_ebuf, "in var_islocal(): inappropriate precision for variable <%s>",
  1996. v->name );
  1997. bwb_error( bwb_ebuf );
  1998. break;
  1999. }
  2000. #endif
  2001. #if INTENSIVE_DEBUG
  2002. sprintf( bwb_ebuf, "in var_islocal(): found local variable <%s>", v->name );
  2003. bwb_debug( bwb_ebuf );
  2004. #endif
  2005. return v;
  2006. }
  2007. }
  2008. /* search failed, return NULL */
  2009. #if INTENSIVE_DEBUG
  2010. sprintf( bwb_ebuf, "in var_islocal(): Failed to find local variable <%s> level <%d>",
  2011. buffer, CURTASK exsc );
  2012. bwb_debug( bwb_ebuf );
  2013. #endif
  2014. return NULL;
  2015. }
  2016. /***************************************************************
  2017. FUNCTION: bwb_vars()
  2018. DESCRIPTION: This function implements the Bywater-
  2019. specific debugging command VARS, which
  2020. gives a list of all variables defined
  2021. in memory.
  2022. ***************************************************************/
  2023. #if PERMANENT_DEBUG
  2024. #if ANSI_C
  2025. struct bwb_line *
  2026. bwb_vars( struct bwb_line *l )
  2027. #else
  2028. struct bwb_line *
  2029. bwb_vars( l )
  2030. struct bwb_line *l;
  2031. #endif
  2032. {
  2033. struct bwb_variable *v;
  2034. char tbuf[ MAXSTRINGSIZE + 1 ];
  2035. /* run through the variable list and print variables */
  2036. for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
  2037. {
  2038. sprintf( bwb_ebuf, "variable <%s>\t", v->name );
  2039. prn_xprintf( stdout, bwb_ebuf );
  2040. switch( v->type )
  2041. {
  2042. case STRING:
  2043. str_btoc( tbuf, var_getsval( v ) );
  2044. sprintf( bwb_ebuf, "STRING\tval: <%s>\n", tbuf );
  2045. prn_xprintf( stdout, bwb_ebuf );
  2046. break;
  2047. case NUMBER:
  2048. #if NUMBER_DOUBLE
  2049. sprintf( bwb_ebuf, "NUMBER\tval: <%lf>\n", var_getnval( v ) );
  2050. prn_xprintf( stdout, bwb_ebuf );
  2051. #else
  2052. sprintf( bwb_ebuf, "NUMBER\tval: <%f>\n", var_getnval( v ) );
  2053. prn_xprintf( stdout, bwb_ebuf );
  2054. #endif
  2055. break;
  2056. default:
  2057. sprintf( bwb_ebuf, "ERROR: type is <%c>", (char) v->type );
  2058. prn_xprintf( stdout, bwb_ebuf );
  2059. break;
  2060. }
  2061. }
  2062. return bwb_zline( l );
  2063. }
  2064. #endif