home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / bwbasic / part03 < prev    next >
Encoding:
Text File  |  1992-11-03  |  60.1 KB  |  2,299 lines

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