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

  1. Newsgroups: comp.sources.misc
  2. From: tcamp@delphi.com (Ted A. Campbell)
  3. Subject: v40i063:  bwbasic - Bywater BASIC interpreter version 2.10, Part12/15
  4. Message-ID: <1993Oct29.162752.4164@sparky.sterling.com>
  5. X-Md4-Signature: 5055c59eb24c85e7eedc6ce14877dbbf
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Fri, 29 Oct 1993 16:27:52 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: tcamp@delphi.com (Ted A. Campbell)
  12. Posting-number: Volume 40, Issue 63
  13. Archive-name: bwbasic/part12
  14. Environment: UNIX, DOS
  15. Supersedes: bwbasic: Volume 33, Issue 37-47
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  bwbasic-2.10/bwb_exp.c
  22. # Wrapped by kent@sparky on Thu Oct 21 10:47:51 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 12 (of 15)."'
  26. if test -f 'bwbasic-2.10/bwb_exp.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'bwbasic-2.10/bwb_exp.c'\"
  28. else
  29.   echo shar: Extracting \"'bwbasic-2.10/bwb_exp.c'\" \(35984 characters\)
  30.   sed "s/^X//" >'bwbasic-2.10/bwb_exp.c' <<'END_OF_FILE'
  31. X/****************************************************************
  32. X
  33. X        bwb_exp.c       Expression Parser
  34. X                        for Bywater BASIC Interpreter
  35. X
  36. X                        Copyright (c) 1993, Ted A. Campbell
  37. X                        Bywater Software
  38. X
  39. X                        email: tcamp@delphi.com
  40. X
  41. X        Copyright and Permissions Information:
  42. X
  43. X        All U.S. and international rights are claimed by the author,
  44. X        Ted A. Campbell.
  45. X
  46. X    This software is released under the terms of the GNU General
  47. X    Public License (GPL), which is distributed with this software
  48. X    in the file "COPYING".  The GPL specifies the terms under
  49. X    which users may copy and use the software in this distribution.
  50. X
  51. X    A separate license is available for commercial distribution,
  52. X    for information on which you should contact the author.
  53. X
  54. X****************************************************************/
  55. X
  56. X#include <stdio.h>
  57. X#include <ctype.h>
  58. X#include <math.h>
  59. X
  60. X#include "bwbasic.h"
  61. X#include "bwb_mes.h"
  62. X
  63. X/***************************************************************
  64. X
  65. X        FUNCTION:    bwb_exp()
  66. X
  67. X        DESCRIPTION:    This is the function by which the expression
  68. X            parser is called.
  69. X
  70. X***************************************************************/
  71. X
  72. X#if ANSI_C
  73. Xstruct exp_ese *
  74. Xbwb_exp( char *expression, int assignment, int *position )
  75. X#else
  76. Xstruct exp_ese *
  77. Xbwb_exp( expression, assignment, position )
  78. X   char *expression;
  79. X   int assignment;
  80. X   int *position;
  81. X#endif
  82. X   {
  83. X   struct exp_ese *rval;            /* return value */
  84. X   int entry_level, main_loop, err_condition;
  85. X   char *e;                                     /* pointer to current string */
  86. X   int r;                                       /* return value from functions */
  87. X   register int c;                              /* quick counter */
  88. X#if OLD_WAY
  89. X   int adv_loop;
  90. X#endif
  91. X
  92. X#if INTENSIVE_DEBUG
  93. X   sprintf( bwb_ebuf, "entered bwb_exp(): expression <%s> assignment <%d> level <%d>",
  94. X      & ( expression[ *position ] ), assignment, CURTASK expsc );
  95. X   bwb_debug( bwb_ebuf );
  96. X#endif
  97. X
  98. X   /* save the entry level of the expression stack in order to
  99. X      check it at the end of this function */
  100. X
  101. X   entry_level = CURTASK expsc;
  102. X   err_condition = FALSE;
  103. X
  104. X   /* advance past whitespace or beginningg of line segment */
  105. X
  106. X#if MULTISEG_LINES
  107. X   if ( expression[ *position ] == ':' )
  108. X      {
  109. X      ++( *position );
  110. X      }
  111. X#endif
  112. X   adv_ws( expression, position );
  113. X#if MULTISEG_LINES
  114. X   if ( expression[ *position ] == ':' )
  115. X      {
  116. X      ++( *position );
  117. X      adv_ws( expression, position );
  118. X      }
  119. X#endif
  120. X
  121. X   /* increment the expression stack counter to get a new level */
  122. X
  123. X   inc_esc();
  124. X
  125. X   /* check to be sure there is a legitimate expression
  126. X      and set initial parameters for the main loop */
  127. X
  128. X   if ( is_eol( expression, position ) == TRUE )
  129. X      {
  130. X      main_loop = FALSE;    /* break out of loop */
  131. X      }
  132. X   else
  133. X      {
  134. X      main_loop = TRUE;
  135. X      CURTASK exps[ CURTASK expsc ].pos_adv = 0;
  136. X      }
  137. X
  138. X#if OLDWAY
  139. X   adv_loop = TRUE;
  140. X   while( adv_loop == TRUE )
  141. X      {
  142. X      switch( expression[ *position ] )
  143. X         {
  144. X         case ' ':                           /* whitespace */
  145. X         case '\t':
  146. X            ++(*position);
  147. X            break;
  148. X         case '\0':                          /* end of string */
  149. X         case '\r':
  150. X         case '\n':
  151. X            main_loop = adv_loop = FALSE;    /* break out of loop */
  152. X            break;
  153. X         default:
  154. X            adv_loop = FALSE;
  155. X            main_loop = TRUE;
  156. X            CURTASK exps[ CURTASK expsc ].pos_adv = 0;
  157. X            break;
  158. X         }
  159. X      }
  160. X#endif
  161. X
  162. X   /* main parsing loop */
  163. X
  164. X   while ( main_loop == TRUE )
  165. X      {
  166. X
  167. X      /* set variable <e> to the start of the expression */
  168. X
  169. X      e = &( expression[ *position ] );
  170. X
  171. X#if INTENSIVE_DEBUG
  172. X      sprintf( bwb_ebuf, "in bwb_exp(): main loop, level <%d> element <%s> ",
  173. X         CURTASK expsc, e );
  174. X      bwb_debug( bwb_ebuf );
  175. X#endif
  176. X
  177. X      /* detect the operation required at this level */
  178. X
  179. X      CURTASK exps[ CURTASK expsc ].operation = exp_findop( e );
  180. X
  181. X#if INTENSIVE_DEBUG
  182. X      sprintf( bwb_ebuf, "in bwb_exp(): exp_findop() returned <%d>",
  183. X         CURTASK exps[ CURTASK expsc ].operation );
  184. X      bwb_debug( bwb_ebuf );
  185. X#endif
  186. X
  187. X      /* perform actions specific to the operation */
  188. X
  189. X      switch( CURTASK exps[ CURTASK expsc ].operation )
  190. X         {
  191. X         case OP_ERROR:
  192. X            main_loop = FALSE;
  193. X            err_condition = TRUE;
  194. X            break;
  195. X
  196. X     case OP_TERMINATE:                /* terminate at THEN, ELSE, TO */
  197. X#if INTENSIVE_DEBUG
  198. X        bwb_debug( "in bwb_exp(): Found OP_TERMINATE" );
  199. X#endif
  200. X         case OP_STRJOIN:                  /* string join or tab */
  201. X         case OP_STRTAB:
  202. X        main_loop = FALSE;
  203. X        err_condition = FALSE;
  204. X        dec_esc();
  205. X        break;
  206. X
  207. X     case OP_ADD:                      /* in the case of any numerical operation, */
  208. X         case OP_SUBTRACT:
  209. X         case OP_MULTIPLY:
  210. X         case OP_DIVIDE:
  211. X         case OP_MODULUS:
  212. X         case OP_EXPONENT:
  213. X         case OP_INTDIVISION:
  214. X         case OP_GREATERTHAN:
  215. X         case OP_LESSTHAN:
  216. X         case OP_GTEQ:
  217. X         case OP_LTEQ:
  218. X         case OP_NOTEQUAL:
  219. X         case OP_NOT:
  220. X         case OP_AND:
  221. X         case OP_OR:
  222. X         case OP_XOR:
  223. X         case OP_IMPLIES:
  224. X         case OP_EQUIV:
  225. X
  226. X#if INTENSIVE_DEBUG
  227. X            sprintf( bwb_ebuf, "in bwb_exp(): operator detected." );
  228. X            bwb_debug( bwb_ebuf );
  229. X#endif
  230. X
  231. X            CURTASK exps[ CURTASK expsc ].pos_adv = -1;             /* set to strange number */
  232. X
  233. X            /* cycle through operator table to find match */
  234. X
  235. X            for ( c = 0; c < N_OPERATORS; ++c )
  236. X               {
  237. X               if ( exp_ops[ c ].operation == CURTASK exps[ CURTASK expsc ].operation )
  238. X                  {
  239. X                  CURTASK exps[ CURTASK expsc ].pos_adv = strlen( exp_ops[ c ].symbol );
  240. X                  }
  241. X               }
  242. X
  243. X            if ( CURTASK exps[ CURTASK expsc ].pos_adv == -1 )      /* was a match found? */
  244. X               {
  245. X               CURTASK exps[ CURTASK expsc ].pos_adv = 0;           /* no -- set to 0 */
  246. X               }
  247. X            break;                         /* and move on */
  248. X
  249. X         case OP_EQUALS:
  250. X
  251. X#if INTENSIVE_DEBUG
  252. X            sprintf( bwb_ebuf, "in bwb_exp(): equal sign detected." );
  253. X            bwb_debug( bwb_ebuf );
  254. X#endif
  255. X
  256. X            if ( assignment == TRUE )
  257. X               {
  258. X               CURTASK exps[ CURTASK expsc ].operation = OP_ASSIGN;
  259. X               }
  260. X            CURTASK exps[ CURTASK expsc ].pos_adv = 1;
  261. X            break;
  262. X
  263. X         case PARENTHESIS:
  264. X            r = exp_paren( e );
  265. X            break;
  266. X
  267. X     case CONST_STRING:
  268. X            r = exp_strconst( e );
  269. X            break;
  270. X
  271. X     case CONST_NUMERICAL:
  272. X            r = exp_numconst( e );
  273. X#if INTENSIVE_DEBUG
  274. X            sprintf( bwb_ebuf, "in bwb_exp(): return from exp_numconst(), r = <%d>",
  275. X               r );
  276. X            bwb_debug( bwb_ebuf );
  277. X#endif
  278. X            break;
  279. X
  280. X         case FUNCTION:
  281. X
  282. X#if INTENSIVE_DEBUG
  283. X            sprintf( bwb_ebuf, "in bwb_exp(): calling exp_function(), expression <%s>",
  284. X               e );
  285. X            bwb_debug( bwb_ebuf );
  286. X#endif
  287. X
  288. X            r = exp_function( e );
  289. X            break;
  290. X
  291. X         case OP_USERFNC:
  292. X
  293. X#if INTENSIVE_DEBUG
  294. X            sprintf( bwb_ebuf, "in bwb_exp(): calling exp_ufnc(), expression <%s>",
  295. X               e );
  296. X            bwb_debug( bwb_ebuf );
  297. X#endif
  298. X
  299. X        r = exp_ufnc( e );
  300. X
  301. X#if INTENSIVE_DEBUG
  302. X        sprintf( bwb_ebuf, "in bwb_exp(): return from exp_ufnc(), buffer <%s>",
  303. X           &( expression[ *position ] ) );
  304. X        bwb_debug( bwb_ebuf );
  305. X#endif
  306. X
  307. X            break;
  308. X
  309. X         case VARIABLE:
  310. X            r = exp_variable( e );
  311. X            break;
  312. X
  313. X     default:
  314. X            err_condition = TRUE;
  315. X            main_loop = FALSE;
  316. X#if PROG_ERRORS
  317. X            sprintf( bwb_ebuf, "in bwb_exp.c:bwb_exp(): unidentified operation (%d).",
  318. X               CURTASK exps[ CURTASK expsc ].operation );
  319. X            bwb_error( bwb_ebuf );
  320. X#else
  321. X            bwb_error( err_syntax );
  322. X#endif
  323. X            break;
  324. X         }
  325. X
  326. X      /* increment *position counter based on previous actions */
  327. X
  328. X      *position += CURTASK exps[ CURTASK expsc ].pos_adv;
  329. X      CURTASK exps[ CURTASK expsc ].pos_adv = 0;            /* reset advance counter */
  330. X
  331. X#if INTENSIVE_DEBUG
  332. X      sprintf( bwb_ebuf, "in bwb_exp(): advanced position; r <%d> err_c <%d>",
  333. X         r, err_condition );
  334. X      bwb_debug( bwb_ebuf );
  335. X#endif
  336. X
  337. X#if INTENSIVE_DEBUG
  338. X      if ( CURTASK exps[ CURTASK expsc ].operation == OP_EQUALS )
  339. X         {
  340. X         sprintf( bwb_ebuf, "in bwb_exp(): with OP_EQUALS: finished case" );
  341. X         bwb_debug( bwb_ebuf );
  342. X         }
  343. X#endif
  344. X
  345. X      /* check for end of string */
  346. X
  347. X      if ( is_eol( expression, position ) == TRUE )
  348. X         {
  349. X         main_loop = FALSE;    /* break out of loop */         
  350. X         }
  351. X
  352. X#if OLDWAY
  353. X      adv_loop = TRUE;
  354. X      while( adv_loop == TRUE )
  355. X         {
  356. X         switch( expression[ *position ] )
  357. X            {
  358. X            case ' ':                           /* whitespace */
  359. X            case '\t':
  360. X               ++(*position);
  361. X               break;
  362. X            case '\0':                          /* end of string */
  363. X            case '\r':
  364. X            case '\n':
  365. X            case ':':
  366. X               main_loop = adv_loop = FALSE;    /* break out of loop */
  367. X               break;
  368. X            default:
  369. X               adv_loop = FALSE;
  370. X               break;
  371. X            }
  372. X         }
  373. X#endif
  374. X
  375. X      /* get a new stack level before looping */
  376. X
  377. X      if ( main_loop == TRUE )
  378. X         {
  379. X         r = inc_esc();
  380. X#if INTENSIVE_DEBUG
  381. X         sprintf( bwb_ebuf, "in bwb_exp(): increment esc, r <%d>, err_c <%d>",
  382. X            r, err_condition );
  383. X         bwb_debug( bwb_ebuf );
  384. X#endif
  385. X         }
  386. X
  387. X      /* check for error return */
  388. X
  389. X      if ( r == OP_ERROR )
  390. X         {
  391. X#if INTENSIVE_DEBUG
  392. X         sprintf( bwb_ebuf, "in bwb_exp(): found r == OP_ERROR." );
  393. X         bwb_debug( bwb_ebuf );
  394. X#endif
  395. X         main_loop = FALSE;
  396. X         err_condition = TRUE;
  397. X         }
  398. X      else
  399. X         {
  400. X         r = TRUE;
  401. X         }
  402. X
  403. X      }                                 /* end of main parsing loop */
  404. X
  405. X#if INTENSIVE_DEBUG
  406. X   sprintf( bwb_ebuf, "in bwb_exp(): breakout from main parsing loop, r <%d> err_c <%d>",
  407. X      r, err_condition );
  408. X   bwb_debug( bwb_ebuf );
  409. X#endif
  410. X
  411. X   /* check error condition */
  412. X
  413. X   if ( err_condition == TRUE )
  414. X      {
  415. X
  416. X#if INTENSIVE_DEBUG
  417. X      sprintf( bwb_ebuf, "error detected in expression parser" );
  418. X      bwb_debug( bwb_ebuf );
  419. X#endif
  420. X
  421. X      /* decrement the expression stack counter until it matches entry_level */
  422. X
  423. X      while( CURTASK expsc > entry_level )
  424. X         {
  425. X         dec_esc();
  426. X         }
  427. X
  428. X#if PROG_ERRORS
  429. X      bwb_error( "in bwb_exp():  Error detected in parsing expression" );
  430. X#else
  431. X      bwb_error( err_syntax );
  432. X#endif
  433. X      }
  434. X
  435. X   /* no error; normal exit from function */
  436. X
  437. X   else
  438. X      {
  439. X
  440. X      /* are any more operations needed? if we are still at entry level,
  441. X         then they are not */
  442. X
  443. X      /* try operations */
  444. X
  445. X      exp_operation( entry_level );
  446. X
  447. X      /* see what is on top of the stack */
  448. X
  449. X      if ( CURTASK expsc > ( entry_level + 1 ))
  450. X         {
  451. X         switch( CURTASK exps[ CURTASK expsc ].operation )
  452. X            {
  453. X            case OP_STRJOIN:
  454. X               if ( CURTASK expsc != ( entry_level + 2 ))
  455. X                  {
  456. X#if PROG_ERRORS
  457. X                  sprintf( bwb_ebuf, "in bwb_exp(): OP_STRJOIN in wrong position." );
  458. X                  bwb_error( bwb_ebuf );
  459. X#else
  460. X                  bwb_error( err_syntax );
  461. X#endif
  462. X                  }
  463. X               break;
  464. X            default:
  465. X#if PROG_ERRORS
  466. X               sprintf( bwb_ebuf, "in bwb_exp(): incomplete expression." );
  467. X               bwb_error( bwb_ebuf );
  468. X#else
  469. X               bwb_error( err_syntax );
  470. X#endif
  471. X               break;
  472. X            }
  473. X
  474. X         /* decrement the expression stack counter */
  475. X
  476. X#if INTENSIVE_DEBUG
  477. X         sprintf( bwb_ebuf, "in bwb_exp(): before dec_esc type is <%c>",
  478. X            CURTASK exps[ CURTASK expsc ].type );
  479. X         bwb_debug( bwb_ebuf );
  480. X#endif
  481. X
  482. X         dec_esc();
  483. X
  484. X         }
  485. X
  486. X      /* assign rvar to the variable for the current level */
  487. X
  488. X      rval = &( CURTASK exps[ CURTASK expsc ] );
  489. X
  490. X      /* decrement the expression stack counter */
  491. X
  492. X      dec_esc();
  493. X
  494. X      /* check the current level before exit */
  495. X
  496. X      if ( entry_level != CURTASK expsc )
  497. X         {
  498. X#if PROG_ERRORS
  499. X         sprintf( bwb_ebuf, "in bwb_exp(): exit stack level (%d) does not match entry stack level (%d)",
  500. X            CURTASK expsc, entry_level );
  501. X         bwb_error( bwb_ebuf );
  502. X#else
  503. X         bwb_error( err_overflow );
  504. X#endif
  505. X         }
  506. X
  507. X      }
  508. X
  509. X   /* return a pointer to the last stack level */
  510. X
  511. X   return rval;
  512. X
  513. X   }
  514. X
  515. X/***************************************************************
  516. X
  517. X    FUNCTION:       exp_findop()
  518. X
  519. X    DESCRIPTION:    This function reads the expression to find
  520. X            what operation is required at its stack level.
  521. X
  522. X***************************************************************/
  523. X
  524. X#if ANSI_C
  525. Xint
  526. Xexp_findop( char *expression )
  527. X#else
  528. Xint
  529. Xexp_findop( expression )
  530. X   char *expression;
  531. X#endif
  532. X   {
  533. X   register int c;                              /* character counter */
  534. X   int carry_on;                                /* boolean: control while loop */
  535. X   int rval;                                    /* return value */
  536. X   char cbuf[ MAXSTRINGSIZE + 1 ];              /* capitalized expression */
  537. X   char nbuf[ MAXSTRINGSIZE + 1 ];              /* non-capitalized expression */
  538. X   int position;                                /* position in the expression */
  539. X   int adv_loop;                                /* control loop to build expression */
  540. X
  541. X#if INTENSIVE_DEBUG
  542. X   sprintf( bwb_ebuf, "in exp_findop(): received <%s>", expression );
  543. X   bwb_debug( bwb_ebuf );
  544. X#endif
  545. X
  546. X   /* set return value to OP_NULL initially */
  547. X
  548. X   rval = OP_NULL;
  549. X
  550. X   /* assign local pointer to expression to begin reading */
  551. X
  552. X   position = 0;
  553. X
  554. X   /* advance to the first significant character */
  555. X
  556. X   adv_ws( expression, &position );
  557. X
  558. X#if INTENSIVE_DEBUG
  559. X   sprintf( bwb_ebuf, "in exp_findop(): expression after advance <%s>",
  560. X      &( expression[ position ] ) );
  561. X   bwb_debug( bwb_ebuf );
  562. X#endif
  563. X
  564. X   /* we now have the first significant character and can begin parsing */
  565. X
  566. X   /* check the first character for an indication of a parenthetical
  567. X      expression, a string constant, or a numerical constant that begins
  568. X      with a digit (numerical constants beginning with a plus or minus
  569. X      sign or hex/octal/binary constants will have to be detected by
  570. X      exp_isnc() */
  571. X
  572. X   carry_on = TRUE;
  573. X   switch ( expression[ position ] )
  574. X      {
  575. X      case '\"':                /* this should indicate a string constant */
  576. X         rval = CONST_STRING;
  577. X         break;
  578. X      case '(':                 /* this will indicate a simple parenthetical expression */
  579. X         rval = PARENTHESIS;
  580. X         break;
  581. X
  582. X#if MULTISEG_LINES
  583. X      case ':':                 /* terminate processing */
  584. X#endif
  585. X      case ')':            /* end of argument list? */
  586. X         rval = OP_TERMINATE;
  587. X         break;
  588. X
  589. X      case '0':                 /* these will indicate a numerical constant */
  590. X      case '1':
  591. X      case '2':
  592. X      case '3':
  593. X      case '4':
  594. X      case '5':
  595. X      case '6':
  596. X      case '7':
  597. X      case '8':
  598. X      case '9':
  599. X      case '.':
  600. X      case '&':                 /* designator for hex or octal constant */
  601. X         rval = CONST_NUMERICAL;
  602. X         break;
  603. X      }
  604. X
  605. X#if INTENSIVE_DEBUG
  606. X   sprintf( bwb_ebuf, "in exp_findop(): rval pos 1 is <%d>", rval );
  607. X   bwb_debug( bwb_ebuf );
  608. X#endif
  609. X
  610. X   /* String constants, numerical constants, open parentheses, and
  611. X      the plus and minus operators have been checked at this point;
  612. X      but if the return value is still OP_NULL, other possibilities
  613. X      must be checked, namely, other operators, function names, and
  614. X      variable names.  The function adv_element cannot be used here
  615. X      because it will stop, e.g., with certain operators and not
  616. X      include them in the returned element. */
  617. X
  618. X   /* get a character string to be interpreted */
  619. X
  620. X   adv_loop = TRUE;
  621. X   cbuf[ 0 ] = '\0';
  622. X   nbuf[ 0 ] = '\0';
  623. X   c = 0;
  624. X   while ( adv_loop == TRUE )
  625. X      {
  626. X
  627. X#if INTENSIVE_DEBUG
  628. X      sprintf( bwb_ebuf, "in bwb_findop() loop position <%d> char 0x%x",
  629. X     c, expression[ position ] );
  630. X      bwb_debug( bwb_ebuf );
  631. X#endif
  632. X
  633. X      switch( expression[ position ] )
  634. X     {
  635. X     case ' ':              /* whitespace */
  636. X     case '\t':
  637. X     case '\r':             /* end of line */
  638. X     case '\n':
  639. X     case '\0':             /* end of string */
  640. X     case '(':              /* parenthesis terminating function name */
  641. X        adv_loop = FALSE;
  642. X        break;
  643. X     default:
  644. X        nbuf[ c ] = cbuf[ c ] = expression[ position ];
  645. X        ++c;
  646. X        nbuf[ c ] = cbuf[ c ] = '\0';
  647. X        ++position;
  648. X        break;
  649. X     }
  650. X
  651. X      if ( c >= MAXSTRINGSIZE )
  652. X     {
  653. X     adv_loop = FALSE;
  654. X     }
  655. X
  656. X      }
  657. X   bwb_strtoupper( cbuf );
  658. X
  659. X#if INTENSIVE_DEBUG
  660. X   sprintf( bwb_ebuf, "in exp_findop(): cbuf element is <%s>", cbuf );
  661. X   bwb_debug( bwb_ebuf );
  662. X#endif
  663. X
  664. X   /* check for numerical constant */
  665. X
  666. X   if ( rval == OP_NULL )
  667. X      {
  668. X      rval = exp_isnc( cbuf );
  669. X      }
  670. X
  671. X   /* check for other operators */
  672. X
  673. X   if ( rval == OP_NULL )
  674. X      {
  675. X      rval = exp_isop( cbuf );
  676. X      }
  677. X
  678. X   /* check for user-defined function */
  679. X
  680. X   if ( rval == OP_NULL )
  681. X      {
  682. X      rval = exp_isufn( nbuf );
  683. X      }
  684. X
  685. X   /* check for function name */
  686. X
  687. X   if ( rval == OP_NULL )
  688. X      {
  689. X      rval = exp_isfn( nbuf );
  690. X      }
  691. X
  692. X   /* check for a BASIC command, esp. to catch THEN or ELSE */
  693. X
  694. X   if ( rval == OP_NULL )
  695. X      {
  696. X      rval = exp_iscmd( cbuf );
  697. X      }
  698. X
  699. X   /* last: check for variable name, and assign it if there
  700. X      is not already one */
  701. X
  702. X   if ( rval == OP_NULL )
  703. X      {
  704. X      rval = exp_isvn( nbuf );
  705. X      }
  706. X
  707. X   /* return the value assigned (or OP_ERROR if none assigned) */
  708. X
  709. X   if ( rval == OP_NULL )
  710. X      {
  711. X      return OP_ERROR;
  712. X      }
  713. X   else
  714. X      {
  715. X      return rval;
  716. X      }
  717. X
  718. X   }
  719. X
  720. X/***************************************************************
  721. X
  722. X    FUNCTION:       exp_isnc()
  723. X
  724. X    DESCRIPTION:    This function reads the expression to find
  725. X            if a logical or mathematical operation is
  726. X            required at this point.
  727. X
  728. X***************************************************************/
  729. X
  730. X#if ANSI_C
  731. Xint
  732. Xexp_isnc( char *expression )
  733. X#else
  734. Xint
  735. Xexp_isnc( expression )
  736. X   char *expression;
  737. X#endif
  738. X   {
  739. X
  740. X   switch( expression[ 0 ] )
  741. X      {
  742. X      case '0':                 /* these will indicate a numerical constant */
  743. X      case '1':
  744. X      case '2':
  745. X      case '3':
  746. X      case '4':
  747. X      case '5':
  748. X      case '6':
  749. X      case '7':
  750. X      case '8':
  751. X      case '9':
  752. X      case '&':                 /* indicator for hex or octal constant */
  753. X         return CONST_NUMERICAL;
  754. X      case '+':
  755. X      case '-':
  756. X
  757. X         /* if the previous stack level was a numerical value or a string,
  758. X            then this is certainly not one; return OP_NULL here
  759. X            and let the next function call to exp_isop() determine
  760. X            the (plus or minus) operator */
  761. X
  762. X         if (  ( CURTASK exps[ CURTASK expsc - 1 ].operation == NUMBER )
  763. X            || ( CURTASK exps[ CURTASK expsc - 1 ].operation == VARIABLE )
  764. X            || ( CURTASK exps[ CURTASK expsc - 1 ].operation == CONST_STRING ) )
  765. X            {
  766. X
  767. X#if INTENSIVE_DEBUG
  768. X            sprintf( bwb_ebuf, "in exp_isnc(): previous function is a number or string" );
  769. X            bwb_debug( bwb_ebuf );
  770. X#endif
  771. X
  772. X            return OP_NULL;
  773. X            }
  774. X
  775. X         /* similarly, if the previous stack level was a variable
  776. X            with a numerical value (not a string), then this level
  777. X            must be an operator, not a numerical constant */
  778. X
  779. X         if ( ( CURTASK exps[ CURTASK expsc - 1 ].operation == VARIABLE )
  780. X            && ( CURTASK exps[ CURTASK expsc - 1 ].type != STRING ))
  781. X            {
  782. X            return OP_NULL;
  783. X            }
  784. X
  785. X         /* failing these tests, the argument must be a numerical
  786. X            constant preceded by a plus or minus sign */
  787. X
  788. X         return CONST_NUMERICAL;
  789. X
  790. X      default:
  791. X         return OP_NULL;
  792. X      }
  793. X
  794. X   }
  795. X
  796. X/***************************************************************
  797. X
  798. X    FUNCTION:       exp_isop()
  799. X
  800. X    DESCRIPTION:    This function reads the expression to find
  801. X            if a logical or mathematical operation is
  802. X            required at this point.
  803. X
  804. X        This function presupposes that a numerical constant with
  805. X        affixed plus or minus sign has been ruled out.
  806. X
  807. X***************************************************************/
  808. X
  809. X#if ANSI_C
  810. Xint
  811. Xexp_isop( char *expression )
  812. X#else
  813. Xint
  814. Xexp_isop( expression )
  815. X   char *expression;
  816. X#endif
  817. X   {
  818. X   register int c;                              /* counter */
  819. X
  820. X#if INTENSIVE_DEBUG
  821. X   sprintf( bwb_ebuf, "in exp_isop(): expression is <%s>", expression );
  822. X   bwb_debug( bwb_ebuf );
  823. X#endif
  824. X
  825. X   /* compare the initial characters of the string with the table
  826. X      of operators */
  827. X
  828. X   for ( c = 0; c < N_OPERATORS; ++c )
  829. X      {
  830. X      if ( strncmp( expression, exp_ops[ c ].symbol,
  831. X         (size_t) strlen( exp_ops[ c ].symbol ) ) == 0 )
  832. X         {
  833. X
  834. X#if INTENSIVE_DEBUG
  835. X         sprintf( bwb_ebuf, "in exp_isop(): match <%s>, number <%d>.",
  836. X            exp_ops[ c ].symbol, c );
  837. X         bwb_debug( bwb_ebuf );
  838. X#endif
  839. X
  840. X         return exp_ops[ c ].operation;
  841. X         }
  842. X      }
  843. X
  844. X   /* search failed; return OP_NULL */
  845. X
  846. X   return OP_NULL;
  847. X
  848. X   }
  849. X
  850. X/***************************************************************
  851. X
  852. X    FUNCTION:       exp_iscmd()
  853. X
  854. X    DESCRIPTION:    This function reads the expression to find
  855. X            if a BASIC command name is present; if so,
  856. X            it returns OP_TERMINATE to terminate expression
  857. X            parsing.  This is critical, for example, in
  858. X            parsing a conditional following IF where THEN,
  859. X            ELSE, and other BASIC commands may follow.
  860. X
  861. X***************************************************************/
  862. X
  863. X#if ANSI_C
  864. Xint
  865. Xexp_iscmd( char *expression )
  866. X#else
  867. Xint
  868. Xexp_iscmd( expression )
  869. X   char *expression;
  870. X#endif
  871. X   {
  872. X   register int n;
  873. X
  874. X#if INTENSIVE_DEBUG
  875. X   sprintf( bwb_ebuf, "in exp_iscmd(): expression received <%s>",
  876. X      expression );
  877. X   bwb_debug( bwb_ebuf );
  878. X#endif
  879. X
  880. X   /* first check for THEN or ELSE statements */
  881. X
  882. X   if ( strcmp( expression, CMD_THEN ) == 0 )
  883. X      {
  884. X#if INTENSIVE_DEBUG
  885. X      sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  886. X     expression );
  887. X      bwb_debug( bwb_ebuf );
  888. X#endif
  889. X      return OP_TERMINATE;
  890. X      }
  891. X
  892. X#if STRUCT_CMDS
  893. X   if ( strcmp( expression, CMD_TO ) == 0 )
  894. X      {
  895. X#if INTENSIVE_DEBUG
  896. X      sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  897. X     expression );
  898. X      bwb_debug( bwb_ebuf );
  899. X#endif
  900. X      return OP_TERMINATE;
  901. X      }
  902. X#endif
  903. X
  904. X   if ( strcmp( expression, CMD_ELSE ) == 0 )
  905. X      {
  906. X#if INTENSIVE_DEBUG
  907. X      sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  908. X     expression );
  909. X      bwb_debug( bwb_ebuf );
  910. X#endif
  911. X      return OP_TERMINATE;
  912. X      }
  913. X
  914. X   /* run through the command table and search for a match */
  915. X
  916. X   for ( n = 0; n < COMMANDS; ++n )
  917. X      {
  918. X      if ( strcmp( expression, bwb_cmdtable[ n ].name ) == 0 )
  919. X         {
  920. X#if INTENSIVE_DEBUG
  921. X         sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  922. X            expression );
  923. X         bwb_debug( bwb_ebuf );
  924. X#endif
  925. X         return OP_TERMINATE;
  926. X         }
  927. X#if INTENSIVE_DEBUG
  928. X      else
  929. X         {
  930. X         sprintf( bwb_ebuf, "in exp_iscmd(): No match, <%s> and <%s>; returns %d",
  931. X            expression, bwb_cmdtable[ n ].name,
  932. X            strcmp( expression, bwb_cmdtable[ n ].name ) );
  933. X         bwb_debug( bwb_ebuf );
  934. X         }
  935. X#endif
  936. X      }
  937. X
  938. X   /* search failed, return NULL */
  939. X
  940. X   return OP_NULL;
  941. X
  942. X   }
  943. X
  944. X/***************************************************************
  945. X
  946. X        FUNCTION:       exp_isufn()
  947. X
  948. X        DESCRIPTION:      This function reads the expression to find
  949. X                if a user-defined function name is present
  950. X            at this point.
  951. X
  952. X***************************************************************/
  953. X
  954. X#if ANSI_C
  955. Xint
  956. Xexp_isufn( char *expression )
  957. X#else
  958. Xint
  959. Xexp_isufn( expression )
  960. X   char *expression;
  961. X#endif
  962. X   {
  963. X   struct fslte *f;
  964. X   char tbuf[ MAXVARNAMESIZE + 1 ];
  965. X
  966. X   exp_getvfname( expression, tbuf );
  967. X
  968. X   for ( f = CURTASK fslt_start.next; f != &CURTASK fslt_end; f = f->next )
  969. X      {
  970. X      if ( strcmp( f->name, tbuf ) == 0 )
  971. X         {
  972. X#if INTENSIVE_DEBUG
  973. X         sprintf( bwb_ebuf, "in exp_isufn(): found user function <%s>",
  974. X            tbuf );
  975. X         bwb_debug( bwb_ebuf );
  976. X#endif
  977. X
  978. X         /* a user function name was found: but is it the local variable
  979. X            name for the user function? If so, return OP_NULL and the
  980. X            name will be read as a variable */
  981. X
  982. X         if ( var_islocal( tbuf ) != NULL )
  983. X            {
  984. X            return OP_NULL;
  985. X            }
  986. X         else
  987. X            {
  988. X
  989. X#if INTENSIVE_DEBUG
  990. X            sprintf( bwb_ebuf, "in exp_isufn(): found function <%s> not a local variable, EXEC level <%d>",
  991. X               tbuf, CURTASK exsc );
  992. X            bwb_debug( bwb_ebuf );
  993. X            getchar();
  994. X#endif
  995. X
  996. X            return OP_USERFNC;
  997. X            }
  998. X         }
  999. X      }
  1000. X
  1001. X   return OP_NULL;
  1002. X
  1003. X   }
  1004. X
  1005. X/***************************************************************
  1006. X
  1007. X    FUNCTION:       exp_isfn()
  1008. X
  1009. X    DESCRIPTION:    This function reads the expression to find
  1010. X            if a function name is present at this point.
  1011. X
  1012. X***************************************************************/
  1013. X
  1014. X#if ANSI_C
  1015. Xint
  1016. Xexp_isfn( char *expression )
  1017. X#else
  1018. Xint
  1019. Xexp_isfn( expression )
  1020. X   char *expression;
  1021. X#endif
  1022. X   {
  1023. X
  1024. X   /* Block out the call to exp_getvfname() if exp_isvn() is called
  1025. X      after exp_isfn() */
  1026. X
  1027. X   exp_getvfname( expression, CURTASK exps[ CURTASK expsc ].string );
  1028. X
  1029. X#if INTENSIVE_DEBUG
  1030. X   sprintf( bwb_ebuf, "in exp_isfn(): search for function <%s>",
  1031. X      expression );
  1032. X   bwb_debug( bwb_ebuf );
  1033. X#endif
  1034. X
  1035. X   if ( fnc_find( CURTASK exps[ CURTASK expsc ].string ) == NULL )
  1036. X      {
  1037. X#if INTENSIVE_DEBUG
  1038. X      sprintf( bwb_ebuf, "in exp_isfn(): failed to find function <%s>",
  1039. X         expression );
  1040. X      bwb_debug( bwb_ebuf );
  1041. X#endif
  1042. X      return OP_NULL;
  1043. X      }
  1044. X   else
  1045. X      {
  1046. X#if INTENSIVE_DEBUG
  1047. X      sprintf( bwb_ebuf, "in exp_isfn(): found function <%s>",
  1048. X         expression );
  1049. X      bwb_debug( bwb_ebuf );
  1050. X#endif
  1051. X      return FUNCTION;
  1052. X      }
  1053. X
  1054. X   }
  1055. X
  1056. X/***************************************************************
  1057. X
  1058. X    FUNCTION:       exp_isvn()
  1059. X
  1060. X    DESCRIPTION:    This function reads the expression to find
  1061. X            if a variable name at this point.
  1062. X
  1063. X***************************************************************/
  1064. X
  1065. X#if ANSI_C
  1066. Xint
  1067. Xexp_isvn( char *expression )
  1068. X#else
  1069. Xint
  1070. Xexp_isvn( expression )
  1071. X   char *expression;
  1072. X#endif
  1073. X   {
  1074. X
  1075. X   /* Block out the call to exp_getvfname() if exp_isfn() is called
  1076. X      after exp_isvn() */
  1077. X
  1078. X   /* exp_getvfname( expression, CURTASK exps[ CURTASK expsc ].string ); */
  1079. X
  1080. X   /* rule out null name */
  1081. X
  1082. X   if ( strlen( CURTASK exps[ CURTASK expsc ].string ) == 0 )
  1083. X      {
  1084. X      return OP_NULL;
  1085. X      }
  1086. X
  1087. X#if INTENSIVE_DEBUG
  1088. X   sprintf( bwb_ebuf, "in exp_isvn(): search for variable <%s>",
  1089. X      CURTASK exps[ CURTASK expsc ].string );
  1090. X   bwb_debug( bwb_ebuf );
  1091. X#endif
  1092. X
  1093. X   if ( var_find( CURTASK exps[ CURTASK expsc ].string ) == NULL )
  1094. X      {
  1095. X#if INTENSIVE_DEBUG
  1096. X      sprintf( bwb_ebuf, "in exp_isvn(): failed to find variable <%s>",
  1097. X         expression );
  1098. X      bwb_debug( bwb_ebuf );
  1099. X#endif
  1100. X      return OP_NULL;
  1101. X      }
  1102. X   else
  1103. X      {
  1104. X#if INTENSIVE_DEBUG
  1105. X      sprintf( bwb_ebuf, "in exp_isvn(): found variable <%s>",
  1106. X         CURTASK exps[ CURTASK expsc ].string );
  1107. X      bwb_debug( bwb_ebuf );
  1108. X#endif
  1109. X      return VARIABLE;
  1110. X      }
  1111. X
  1112. X   }
  1113. X
  1114. X/***************************************************************
  1115. X
  1116. X    FUNCTION:       exp_getvfname()
  1117. X
  1118. X    DESCRIPTION:    This function reads the expression to find
  1119. X            a variable or function name at this point.
  1120. X
  1121. X***************************************************************/
  1122. X
  1123. X#if ANSI_C
  1124. Xint
  1125. Xexp_getvfname( char *source, char *destination )
  1126. X#else
  1127. Xint
  1128. Xexp_getvfname( source, destination )
  1129. X   char *source;
  1130. X   char *destination;
  1131. X#endif
  1132. X   {
  1133. X   int s_pos, d_pos;                    /* source, destination positions */
  1134. X
  1135. X#if INTENSIVE_DEBUG
  1136. X   sprintf( bwb_ebuf, "in exp_getvfname(): source buffer <%s>", source );
  1137. X   bwb_debug( bwb_ebuf );
  1138. X#endif
  1139. X
  1140. X   s_pos = d_pos = 0;
  1141. X   destination[ 0 ] = '\0';
  1142. X   while( source[ s_pos ] != '\0' )
  1143. X      {
  1144. X
  1145. X      /* all aphabetical characters are acceptable */
  1146. X
  1147. X      if ( isalpha( source[ s_pos ] ) != 0 )
  1148. X
  1149. X         {
  1150. X         destination[ d_pos ] = source[ s_pos ];
  1151. X
  1152. X         ++d_pos;
  1153. X         ++s_pos;
  1154. X         destination[ d_pos ] = '\0';
  1155. X         }
  1156. X
  1157. X      /* numerical characters are acceptable but not in the first position */
  1158. X
  1159. X      else if (( isdigit( source[ s_pos ] ) != 0 ) && ( d_pos != 0 ))
  1160. X         {
  1161. X         destination[ d_pos ] = source[ s_pos ];
  1162. X         ++d_pos;
  1163. X         ++s_pos;
  1164. X         destination[ d_pos ] = '\0';
  1165. X         }
  1166. X
  1167. X      /* other characters will have to be tried on their own merits */
  1168. X
  1169. X      else
  1170. X         {
  1171. X         switch( source[ s_pos ] )
  1172. X            {
  1173. X
  1174. X            case '.':                           /* tolerated non-alphabetical characters */
  1175. X            case '_':
  1176. X               destination[ d_pos ] = source[ s_pos ];
  1177. X               ++d_pos;
  1178. X               ++s_pos;
  1179. X               destination[ d_pos ] = '\0';
  1180. X               break;
  1181. X
  1182. X        case STRING:                        /* terminating characters */
  1183. X        case '#':                           /* Microsoft-type double precision */
  1184. X        case '!':                           /* Microsoft-type single precision */
  1185. X
  1186. X           destination[ d_pos ] = source[ s_pos ];
  1187. X               ++d_pos;
  1188. X               ++s_pos;
  1189. X               destination[ d_pos ] = '\0';
  1190. X
  1191. X               return TRUE;
  1192. X
  1193. X            case '(':                /* begin function/sub name */
  1194. X               return TRUE;
  1195. X
  1196. X            default:                            /* anything else is non-tolerated */
  1197. X               return FALSE;
  1198. X            }
  1199. X         }
  1200. X      }
  1201. X
  1202. X#if INTENSIVE_DEBUG
  1203. X   sprintf( bwb_ebuf, "in exp_getvfname(): found name <%s>", destination );
  1204. X   bwb_debug( bwb_ebuf );
  1205. X#endif
  1206. X
  1207. X   return TRUE;                         /* exit after coming to the end */
  1208. X
  1209. X   }
  1210. X
  1211. X/***************************************************************
  1212. X
  1213. X    FUNCTION:       exp_validarg()
  1214. X
  1215. X    DESCRIPTION:    This function reads the expression to
  1216. X            determine whether it is a valid argument (to be
  1217. X            read recursively by bwb_exp() and passed to a
  1218. X            function.
  1219. X
  1220. X***************************************************************/
  1221. X
  1222. X#if ANSI_C
  1223. Xint
  1224. Xexp_validarg( char *expression )
  1225. X#else
  1226. Xint
  1227. Xexp_validarg( expression )
  1228. X   char *expression;
  1229. X#endif
  1230. X   {
  1231. X   register int c;
  1232. X
  1233. X#if INTENSIVE_DEBUG
  1234. X   sprintf( bwb_ebuf, "in exp_validarg(): expression <%s>.",
  1235. X      expression );
  1236. X   bwb_debug( bwb_ebuf );
  1237. X#endif
  1238. X
  1239. X   c = 0;
  1240. X   while ( TRUE )
  1241. X      {
  1242. X      switch( expression[ c ] )
  1243. X         {
  1244. X         case ' ':
  1245. X         case '\t':
  1246. X            ++c;
  1247. X            break;
  1248. X         case '\0':
  1249. X            return FALSE;
  1250. X         default:
  1251. X            return TRUE;
  1252. X         }
  1253. X      }
  1254. X
  1255. X   }
  1256. X
  1257. X/***************************************************************
  1258. X
  1259. X        FUNCTION:       exp_getnval()
  1260. X
  1261. X    DESCRIPTION:    This function returns the numerical value
  1262. X            contain in the expression-stack element
  1263. X            pointed to by 'e'.
  1264. X
  1265. X***************************************************************/
  1266. X
  1267. X#if ANSI_C
  1268. Xbnumber
  1269. Xexp_getnval( struct exp_ese *e )
  1270. X#else
  1271. Xbnumber
  1272. Xexp_getnval( e )
  1273. X   struct exp_ese *e;
  1274. X#endif
  1275. X   {
  1276. X
  1277. X   /* check for variable */
  1278. X
  1279. X   if ( e->operation == VARIABLE )
  1280. X      {
  1281. X      switch( e->type )
  1282. X         {
  1283. X         case NUMBER:
  1284. X            return (* var_findnval( e->xvar, e->array_pos ));
  1285. X         default:
  1286. X            bwb_error( err_mismatch );
  1287. X            return (bnumber) 0.0;
  1288. X         }
  1289. X      }
  1290. X
  1291. X   /* must be a numerical value */
  1292. X
  1293. X   if ( e->operation != NUMBER )
  1294. X      {
  1295. X#if PROG_ERRORS
  1296. X      sprintf( bwb_ebuf, "in exp_getnval(): operation <%d> is not a number",
  1297. X         e->operation );
  1298. X      bwb_error( bwb_ebuf );
  1299. X#else
  1300. X      bwb_error( err_syntax );
  1301. X#endif
  1302. X      return (bnumber) 0.0;
  1303. X      }
  1304. X
  1305. X   /* return specific values */
  1306. X
  1307. X   switch( e->type )
  1308. X      {
  1309. X      case NUMBER:
  1310. X         return e->nval;
  1311. X      default:
  1312. X#if PROG_ERRORS
  1313. X         sprintf( bwb_ebuf, "in exp_getnval(): type is <%c>",
  1314. X            e->type );
  1315. X         bwb_error( bwb_ebuf );
  1316. X#else
  1317. X         bwb_error( err_syntax );
  1318. X#endif
  1319. X         return (bnumber) 0.0;
  1320. X      }
  1321. X
  1322. X   }
  1323. X
  1324. X/***************************************************************
  1325. X
  1326. X    FUNCTION:       exp_getsval()
  1327. X
  1328. X    DESCRIPTION:    This function returns a pointer to the
  1329. X            BASIC string structure pointed to by
  1330. X            expression-stack element 'e'.
  1331. X
  1332. X***************************************************************/
  1333. X
  1334. X#if ANSI_C
  1335. Xbstring *
  1336. Xexp_getsval( struct exp_ese *e )
  1337. X#else
  1338. Xbstring *
  1339. Xexp_getsval( e )
  1340. X   struct exp_ese *e;
  1341. X#endif
  1342. X   {
  1343. X   static bstring b;
  1344. X#if TEST_BSTRING
  1345. X   static int init = FALSE;
  1346. X
  1347. X   if ( init == FALSE )
  1348. X      {
  1349. X      sprintf( b.name, "<exp_getsval() bstring>" );
  1350. X      }
  1351. X#endif
  1352. X
  1353. X   b.rab = FALSE;
  1354. X
  1355. X   /* return based on operation type */
  1356. X
  1357. X   switch( e->operation )
  1358. X      {
  1359. X      case CONST_STRING:
  1360. X      case OP_STRJOIN:
  1361. X         return &( e->sval );
  1362. X      case VARIABLE:
  1363. X        switch( e->type )
  1364. X            {
  1365. X        case STRING:
  1366. X               return var_findsval( e->xvar, e->array_pos );
  1367. X            case NUMBER:
  1368. X               sprintf( bwb_ebuf, "%lf ", (double) exp_getnval( e ) );
  1369. X               str_ctob( &b, bwb_ebuf );
  1370. X               return &b;
  1371. X            default:
  1372. X#if PROG_ERRORS
  1373. X               sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
  1374. X                  e->type );
  1375. X               bwb_error( bwb_ebuf );
  1376. X#else
  1377. X               bwb_error( err_syntax );
  1378. X#endif
  1379. X               return NULL;
  1380. X            }
  1381. X     break;
  1382. X
  1383. X      case NUMBER:
  1384. X        switch( e->type )
  1385. X            {
  1386. X        case NUMBER:
  1387. X               sprintf( bwb_ebuf, "%lf ", (double) exp_getnval( e ) );
  1388. X               str_ctob( &b, bwb_ebuf );
  1389. X               return &b;
  1390. X            default:
  1391. X#if PROG_ERRORS
  1392. X               sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
  1393. X                  e->type );
  1394. X               bwb_error( bwb_ebuf );
  1395. X#else
  1396. X               bwb_error( err_syntax );
  1397. X#endif
  1398. X               return NULL;
  1399. X            }
  1400. X     break;
  1401. X      default:
  1402. X#if PROG_ERRORS
  1403. X         sprintf( bwb_ebuf, "in exp_getsval(): operation <%d> inappropriate",
  1404. X            e->operation );
  1405. X         bwb_error( bwb_ebuf );
  1406. X#else
  1407. X         bwb_error( err_syntax );
  1408. X#endif
  1409. X         return NULL;
  1410. X      }
  1411. X
  1412. X   /* this point may not be reached */
  1413. X
  1414. X   return NULL;
  1415. X
  1416. X   }
  1417. X
  1418. X/***************************************************************
  1419. X
  1420. X    FUNCTION:       inc_esc()
  1421. X
  1422. X    DESCRIPTION:    This function increments the expression
  1423. X            stack counter.
  1424. X
  1425. X***************************************************************/
  1426. X
  1427. X#if ANSI_C
  1428. Xint
  1429. Xinc_esc( void )
  1430. X#else
  1431. Xint
  1432. Xinc_esc()
  1433. X#endif
  1434. X   {
  1435. X
  1436. X#if INTENSIVE_DEBUG
  1437. X   sprintf( bwb_ebuf, "in inc_esc(): prev level <%d>",
  1438. X      CURTASK expsc );
  1439. X   bwb_debug ( bwb_ebuf );
  1440. X#endif
  1441. X
  1442. X   ++CURTASK expsc;
  1443. X   if ( CURTASK expsc >= ESTACKSIZE )
  1444. X      {
  1445. X      --CURTASK expsc;
  1446. X#if PROG_ERRORS
  1447. X      sprintf( bwb_ebuf, "in inc_esc(): Maximum expression stack exceeded <%d>",
  1448. X         CURTASK expsc );
  1449. X      bwb_error( bwb_ebuf );
  1450. X#else
  1451. X      bwb_error( err_overflow );
  1452. X#endif
  1453. X      return OP_NULL;
  1454. X      }
  1455. X
  1456. X#if INTENSIVE_DEBUG
  1457. X   sprintf( CURTASK exps[ CURTASK expsc ].string, "New Expression Stack Level %d", CURTASK expsc );
  1458. X#endif
  1459. X
  1460. X   CURTASK exps[ CURTASK expsc ].type = NUMBER;
  1461. X   CURTASK exps[ CURTASK expsc ].operation = OP_NULL;
  1462. X   CURTASK exps[ CURTASK expsc ].pos_adv = 0;
  1463. X
  1464. X   return TRUE;
  1465. X   }
  1466. X
  1467. X/***************************************************************
  1468. X
  1469. X    FUNCTION:       dec_esc()
  1470. X
  1471. X    DESCRIPTION:    This function decrements the expression
  1472. X            stack counter.
  1473. X
  1474. X***************************************************************/
  1475. X
  1476. X#if ANSI_C
  1477. Xint
  1478. Xdec_esc( void )
  1479. X#else
  1480. Xint
  1481. Xdec_esc()
  1482. X#endif
  1483. X   {
  1484. X   --CURTASK expsc;
  1485. X   if ( CURTASK expsc < 0 )
  1486. X      {
  1487. X      CURTASK expsc = 0;
  1488. X#if PROG_ERRORS
  1489. X      sprintf( bwb_ebuf, "in dec_esc(): Expression stack counter < 0." );
  1490. X      bwb_error( bwb_ebuf );
  1491. X#else
  1492. X      bwb_error( err_overflow );
  1493. X#endif
  1494. X      return OP_NULL;
  1495. X      }
  1496. X
  1497. X   return TRUE;
  1498. X   }
  1499. X
  1500. END_OF_FILE
  1501.   if test 35984 -ne `wc -c <'bwbasic-2.10/bwb_exp.c'`; then
  1502.     echo shar: \"'bwbasic-2.10/bwb_exp.c'\" unpacked with wrong size!
  1503.   fi
  1504.   # end of 'bwbasic-2.10/bwb_exp.c'
  1505. fi
  1506. echo shar: End of archive 12 \(of 15\).
  1507. cp /dev/null ark12isdone
  1508. MISSING=""
  1509. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1510.     if test ! -f ark${I}isdone ; then
  1511.     MISSING="${MISSING} ${I}"
  1512.     fi
  1513. done
  1514. if test "${MISSING}" = "" ; then
  1515.     echo You have unpacked all 15 archives.
  1516.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1517. else
  1518.     echo You still must unpack the following archives:
  1519.     echo "        " ${MISSING}
  1520. fi
  1521. exit 0
  1522. exit 0 # Just in case...
  1523.