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.
 
 
 
 
 
 

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