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

1200 lines
35 KiB

  1. /****************************************************************
  2. bwb_elx.c Parse Elements of Expressions
  3. for Bywater BASIC Interpreter
  4. Copyright (c) 1993, Ted A. Campbell
  5. Bywater Software
  6. email: tcamp@delphi.com
  7. Copyright and Permissions Information:
  8. All U.S. and international rights are claimed by the author,
  9. Ted A. Campbell.
  10. This software is released under the terms of the GNU General
  11. Public License (GPL), which is distributed with this software
  12. in the file "COPYING". The GPL specifies the terms under
  13. which users may copy and use the software in this distribution.
  14. A separate license is available for commercial distribution,
  15. for information on which you should contact the author.
  16. ****************************************************************/
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <math.h>
  20. #include "bwbasic.h"
  21. #include "bwb_mes.h"
  22. /***************************************************************
  23. FUNCTION: exp_paren()
  24. DESCRIPTION: This function interprets a parenthetical
  25. expression, calling bwb_exp() (recursively)
  26. to resolve the internal expression.
  27. ***************************************************************/
  28. #if ANSI_C
  29. int
  30. exp_paren( char *expression )
  31. #else
  32. int
  33. exp_paren( expression )
  34. char *expression;
  35. #endif
  36. {
  37. struct exp_ese *e;
  38. int s_pos; /* position in build buffer */
  39. int loop;
  40. int paren_level;
  41. /* find a string enclosed by parentheses */
  42. CURTASK exps[ CURTASK expsc ].pos_adv = 1; /* start beyond open paren */
  43. s_pos = 0;
  44. loop = TRUE;
  45. paren_level = 1;
  46. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  47. while( loop == TRUE )
  48. {
  49. /* check the current character */
  50. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  51. {
  52. case '\r': /* these tests added v1.11 */
  53. case '\n':
  54. case '\0':
  55. bwb_error( err_incomplete );
  56. loop = FALSE;
  57. break;
  58. case '(':
  59. ++paren_level;
  60. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  61. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  62. ++s_pos;
  63. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  64. break;
  65. case ')':
  66. --paren_level;
  67. if ( paren_level == 0 )
  68. {
  69. loop = FALSE;
  70. }
  71. else
  72. {
  73. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  74. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  75. ++s_pos;
  76. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  77. }
  78. break;
  79. case '\"': /* embedded string constant */
  80. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  81. while ( ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '\"' )
  82. && ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '\0' ) )
  83. {
  84. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  85. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  86. ++s_pos;
  87. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  88. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  89. }
  90. break;
  91. default:
  92. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  93. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  94. ++s_pos;
  95. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  96. break;
  97. }
  98. /* advance the counter */
  99. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  100. }
  101. #if INTENSIVE_DEBUG
  102. sprintf( bwb_ebuf, "in exp_paren() found internal string <%s>",
  103. CURTASK exps[ CURTASK expsc ].string );
  104. bwb_debug( bwb_ebuf );
  105. #endif
  106. /* call bwb_exp() recursively to interpret this expression */
  107. CURTASK exps[ CURTASK expsc ].rec_pos = 0;
  108. e = bwb_exp( CURTASK exps[ CURTASK expsc ].string, FALSE,
  109. &( CURTASK exps[ CURTASK expsc ].rec_pos ) );
  110. /* assign operation and value at this level */
  111. CURTASK exps[ CURTASK expsc ].type = e->type;
  112. switch ( e->type )
  113. {
  114. case STRING:
  115. CURTASK exps[ CURTASK expsc ].operation = CONST_STRING;
  116. str_btob( exp_getsval( &( CURTASK exps[ CURTASK expsc ] )), exp_getsval( e ) );
  117. break;
  118. default:
  119. CURTASK exps[ CURTASK expsc ].operation = NUMBER;
  120. CURTASK exps[ CURTASK expsc ].nval = exp_getnval( e );
  121. break;
  122. }
  123. return TRUE;
  124. }
  125. /***************************************************************
  126. FUNCTION: exp_strconst()
  127. DESCRIPTION: This function interprets a string
  128. constant.
  129. ***************************************************************/
  130. #if ANSI_C
  131. int
  132. exp_strconst( char *expression )
  133. #else
  134. int
  135. exp_strconst( expression )
  136. char *expression;
  137. #endif
  138. {
  139. int e_pos, s_pos;
  140. /* assign values to structure */
  141. CURTASK exps[ CURTASK expsc ].type = STRING;
  142. CURTASK exps[ CURTASK expsc ].operation = CONST_STRING;
  143. /* set counters */
  144. s_pos = 0;
  145. CURTASK exps[ CURTASK expsc ].pos_adv = e_pos = 1;
  146. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  147. /* read the string up until the next double quotation mark */
  148. while( expression[ e_pos ] != '\"' )
  149. {
  150. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ e_pos ];
  151. ++e_pos;
  152. ++s_pos;
  153. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  154. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  155. if ( s_pos >= ( MAXSTRINGSIZE - 1 ) )
  156. {
  157. #if PROG_ERRORS
  158. sprintf( bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
  159. expression, MAXSTRINGSIZE );
  160. bwb_error( bwb_ebuf );
  161. #else
  162. bwb_error( err_overflow );
  163. #endif
  164. return OP_NULL;
  165. }
  166. }
  167. /* now write string over to bstring */
  168. str_ctob( &( CURTASK exps[ CURTASK expsc ].sval ), CURTASK exps[ CURTASK expsc ].string );
  169. /* advance past last double quotation mark */
  170. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  171. /* return */
  172. return TRUE;
  173. }
  174. /***************************************************************
  175. FUNCTION: exp_numconst()
  176. DESCRIPTION: This function interprets a numerical
  177. constant.
  178. ***************************************************************/
  179. #if ANSI_C
  180. int
  181. exp_numconst( char *expression )
  182. #else
  183. int
  184. exp_numconst( expression )
  185. char *expression;
  186. #endif
  187. {
  188. int base; /* numerical base for the constant */
  189. static struct bwb_variable mantissa; /* mantissa of floating-point number */
  190. static int init = FALSE; /* is mantissa variable initialized? */
  191. int exponent; /* exponent for floating point number */
  192. int man_start; /* starting point of mantissa */
  193. int s_pos; /* position in build string */
  194. int build_loop;
  195. int need_pm;
  196. int i;
  197. bnumber d;
  198. #if CHECK_RECURSION
  199. static int in_use = FALSE; /* boolean: is function in use? */
  200. /* check recursion status */
  201. if ( in_use == TRUE )
  202. {
  203. sprintf( bwb_ebuf, "Recursion error in bwb_exp.c:exp_findop(): recursion violation." );
  204. bwb_error( bwb_ebuf );
  205. }
  206. /* reset recursion status indicator */
  207. else
  208. {
  209. in_use = TRUE;
  210. }
  211. #endif
  212. /* initialize the variable if necessary */
  213. #if INTENSIVE_DEBUG
  214. strcpy( mantissa.name, "(mantissa)" );
  215. #endif
  216. if ( init == FALSE )
  217. {
  218. init = TRUE;
  219. var_make( &mantissa, NUMBER );
  220. }
  221. /* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
  222. this is necessary because mantissa might be used before dim_base
  223. is set */
  224. mantissa.array_pos[ 0 ] = dim_base;
  225. #if INTENSIVE_DEBUG
  226. sprintf( bwb_ebuf, "in exp_numconst(): received <%s>, eval <%c>",
  227. expression, expression[ 0 ] );
  228. bwb_debug( bwb_ebuf );
  229. #endif
  230. need_pm = FALSE;
  231. CURTASK exps[ CURTASK expsc ].nval = (bnumber) 0;
  232. /* check the first character(s) to determine numerical base
  233. and starting point of the mantissa */
  234. switch( expression[ 0 ] )
  235. {
  236. case '-':
  237. case '+':
  238. case '0':
  239. case '1':
  240. case '2':
  241. case '3':
  242. case '4':
  243. case '5':
  244. case '6':
  245. case '7':
  246. case '8':
  247. case '9':
  248. case '.':
  249. base = 10; /* decimal constant */
  250. man_start = 0; /* starts at position 0 */
  251. need_pm = FALSE;
  252. break;
  253. case '&': /* hex or octal constant */
  254. if ( ( expression[ 1 ] == 'H' ) || ( expression[ 1 ] == 'h' ))
  255. {
  256. base = 16; /* hexadecimal constant */
  257. man_start = 2; /* starts at position 2 */
  258. }
  259. else
  260. {
  261. base = 8; /* octal constant */
  262. if ( ( expression[ 1 ] == 'O' ) || ( expression[ 1 ] == 'o' ))
  263. {
  264. man_start = 2; /* starts at position 2 */
  265. }
  266. else
  267. {
  268. man_start = 1; /* starts at position 1 */
  269. }
  270. }
  271. break;
  272. default:
  273. #if PROG_ERRORS
  274. sprintf( bwb_ebuf, "expression <%s> is not a numerical constant.",
  275. expression );
  276. bwb_error( bwb_ebuf );
  277. #else
  278. bwb_error( err_syntax );
  279. #endif
  280. return OP_NULL;
  281. }
  282. /* now build the mantissa according to the numerical base */
  283. switch( base )
  284. {
  285. case 10: /* decimal constant */
  286. /* initialize counters */
  287. CURTASK exps[ CURTASK expsc ].pos_adv = man_start;
  288. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  289. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  290. s_pos = 0;
  291. exponent = OP_NULL;
  292. build_loop = TRUE;
  293. /* loop to build the string */
  294. while ( build_loop == TRUE )
  295. {
  296. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  297. {
  298. case '-': /* prefixed plus or minus */
  299. case '+':
  300. /* in the first position, a plus or minus sign can
  301. be added to the beginning of the string to be
  302. scanned */
  303. if ( CURTASK exps[ CURTASK expsc ].pos_adv == man_start )
  304. {
  305. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  306. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  307. ++s_pos;
  308. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  309. }
  310. /* but in any other position, the plus or minus sign
  311. must be taken as an operator and thus as terminating
  312. the string to be scanned */
  313. else
  314. {
  315. build_loop = FALSE;
  316. }
  317. break;
  318. case '.': /* note at least single precision */
  319. case '0': /* or ordinary digit */
  320. case '1':
  321. case '2':
  322. case '3':
  323. case '4':
  324. case '5':
  325. case '6':
  326. case '7':
  327. case '8':
  328. case '9':
  329. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  330. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  331. ++s_pos;
  332. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  333. break;
  334. case '#': /* Microsoft-type precision indicator; ignored but terminates */
  335. case '!': /* Microsoft-type precision indicator; ignored but terminates */
  336. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  337. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  338. exponent = FALSE;
  339. build_loop = FALSE;
  340. break;
  341. case 'E': /* exponential, single precision */
  342. case 'e':
  343. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  344. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  345. exponent = TRUE;
  346. build_loop = FALSE;
  347. break;
  348. case 'D': /* exponential, double precision */
  349. case 'd':
  350. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  351. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  352. exponent = TRUE;
  353. build_loop = FALSE;
  354. break;
  355. default: /* anything else, terminate */
  356. build_loop = FALSE;
  357. break;
  358. }
  359. }
  360. /* assign the value to the mantissa variable */
  361. #if NUMBER_DOUBLE
  362. sscanf( CURTASK exps[ CURTASK expsc ].string, "%lf",
  363. var_findnval( &mantissa, mantissa.array_pos ));
  364. #else
  365. sscanf( CURTASK exps[ CURTASK expsc ].string, "%f",
  366. var_findnval( &mantissa, mantissa.array_pos ));
  367. #endif
  368. #if INTENSIVE_DEBUG
  369. sprintf( bwb_ebuf, "in exp_numconst(): read mantissa, string <%s> val <%lf>",
  370. CURTASK exps[ CURTASK expsc ].string, var_getnval( &mantissa ) );
  371. bwb_debug( bwb_ebuf );
  372. #endif
  373. /* test if integer bounds have been exceeded */
  374. if ( CURTASK exps[ CURTASK expsc ].type == NUMBER )
  375. {
  376. i = (int) var_getnval( &mantissa );
  377. d = (bnumber) i;
  378. if ( d != var_getnval( &mantissa ))
  379. {
  380. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  381. #if INTENSIVE_DEBUG
  382. sprintf( bwb_ebuf, "in exp_numconst(): integer bounds violated, promote to NUMBER" );
  383. bwb_debug( bwb_ebuf );
  384. #endif
  385. }
  386. }
  387. /* read the exponent if there is one */
  388. if ( exponent == TRUE )
  389. {
  390. /* allow a plus or minus once at the beginning */
  391. need_pm = TRUE;
  392. /* initialize counters */
  393. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  394. s_pos = 0;
  395. build_loop = TRUE;
  396. /* loop to build the string */
  397. while ( build_loop == TRUE )
  398. {
  399. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  400. {
  401. case '-': /* prefixed plus or minus */
  402. case '+':
  403. if ( need_pm == TRUE ) /* only allow once */
  404. {
  405. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  406. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  407. ++s_pos;
  408. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  409. }
  410. else
  411. {
  412. build_loop = FALSE;
  413. }
  414. break;
  415. case '0': /* or ordinary digit */
  416. case '1':
  417. case '2':
  418. case '3':
  419. case '4':
  420. case '5':
  421. case '6':
  422. case '7':
  423. case '8':
  424. case '9':
  425. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  426. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  427. ++s_pos;
  428. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  429. need_pm = FALSE;
  430. break;
  431. default: /* anything else, terminate */
  432. build_loop = FALSE;
  433. break;
  434. }
  435. } /* end of build loop for exponent */
  436. /* assign the value to the user variable */
  437. #if NUMBER_DOUBLE
  438. sscanf( CURTASK exps[ CURTASK expsc ].string, "%lf",
  439. &( CURTASK exps[ CURTASK expsc ].nval ) );
  440. #else
  441. sscanf( CURTASK exps[ CURTASK expsc ].string, "%f",
  442. &( CURTASK exps[ CURTASK expsc ].nval ) );
  443. #endif
  444. #if INTENSIVE_DEBUG
  445. sprintf( bwb_ebuf, "in exp_numconst(): exponent is <%d>",
  446. (int) CURTASK exps[ CURTASK expsc ].nval );
  447. bwb_debug( bwb_ebuf );
  448. #endif
  449. } /* end of exponent search */
  450. if ( CURTASK exps[ CURTASK expsc ].nval == (bnumber) 0 )
  451. {
  452. CURTASK exps[ CURTASK expsc ].nval = var_getnval( &mantissa );
  453. }
  454. else
  455. {
  456. CURTASK exps[ CURTASK expsc ].nval = var_getnval( &mantissa )
  457. * pow( (bnumber) 10.0, (bnumber) CURTASK exps[ CURTASK expsc ].nval );
  458. }
  459. break;
  460. case 8: /* octal constant */
  461. /* initialize counters */
  462. CURTASK exps[ CURTASK expsc ].pos_adv = man_start;
  463. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  464. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  465. s_pos = 0;
  466. exponent = OP_NULL;
  467. build_loop = TRUE;
  468. /* loop to build the string */
  469. while ( build_loop == TRUE )
  470. {
  471. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  472. {
  473. case '0': /* or ordinary digit */
  474. case '1':
  475. case '2':
  476. case '3':
  477. case '4':
  478. case '5':
  479. case '6':
  480. case '7':
  481. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  482. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  483. ++s_pos;
  484. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  485. break;
  486. default: /* anything else, terminate */
  487. build_loop = FALSE;
  488. break;
  489. }
  490. }
  491. /* now scan the string to determine the number */
  492. sscanf( CURTASK exps[ CURTASK expsc ].string, "%o", &i );
  493. CURTASK exps[ CURTASK expsc ].nval = (bnumber) i;
  494. break;
  495. case 16: /* hexadecimal constant */
  496. /* initialize counters */
  497. CURTASK exps[ CURTASK expsc ].pos_adv = man_start;
  498. CURTASK exps[ CURTASK expsc ].type = NUMBER;
  499. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  500. s_pos = 0;
  501. exponent = OP_NULL;
  502. build_loop = TRUE;
  503. /* loop to build the string */
  504. while ( build_loop == TRUE )
  505. {
  506. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  507. {
  508. case '0': /* or ordinary digit */
  509. case '1':
  510. case '2':
  511. case '3':
  512. case '4':
  513. case '5':
  514. case '6':
  515. case '7':
  516. case '8':
  517. case '9':
  518. case 'A':
  519. case 'a':
  520. case 'B':
  521. case 'b':
  522. case 'C':
  523. case 'c':
  524. case 'D':
  525. case 'd':
  526. case 'E':
  527. case 'e':
  528. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  529. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance to next character */
  530. ++s_pos;
  531. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  532. break;
  533. default: /* anything else, terminate */
  534. build_loop = FALSE;
  535. break;
  536. }
  537. }
  538. /* now scan the string to determine the number */
  539. sscanf( CURTASK exps[ CURTASK expsc ].string, "%x", &i );
  540. CURTASK exps[ CURTASK expsc ].nval = (bnumber) i;
  541. break;
  542. }
  543. /* note that the operation at this level is now a determined NUMBER */
  544. CURTASK exps[ CURTASK expsc ].operation = NUMBER;
  545. #if INTENSIVE_DEBUG
  546. sprintf( bwb_ebuf, "in exp_numconst(): exit level <%d> precision <%c> value <%lf>",
  547. CURTASK expsc, CURTASK exps[ CURTASK expsc ].type, exp_getnval( &( CURTASK exps[ CURTASK expsc ] ) ) );
  548. bwb_debug( bwb_ebuf );
  549. #endif
  550. #if CHECK_RECURSION
  551. in_use = FALSE;
  552. #endif
  553. return TRUE;
  554. }
  555. /***************************************************************
  556. FUNCTION: exp_function()
  557. DESCRIPTION: This function interprets a function,
  558. calling bwb_exp() (recursively) to resolve any
  559. arguments to the function.
  560. ***************************************************************/
  561. #if ANSI_C
  562. int
  563. exp_function( char *expression )
  564. #else
  565. int
  566. exp_function( expression )
  567. char *expression;
  568. #endif
  569. {
  570. struct exp_ese *e;
  571. int s_pos; /* position in build buffer */
  572. int loop;
  573. int paren_level;
  574. int n_args;
  575. struct bwb_variable *v;
  576. struct bwb_variable argv[ MAX_FARGS ];
  577. bstring *b;
  578. #if INTENSIVE_DEBUG
  579. char tbuf[ MAXSTRINGSIZE + 1 ];
  580. sprintf( bwb_ebuf, "in exp_function(): entered function, expression <%s>",
  581. expression );
  582. bwb_debug( bwb_ebuf );
  583. #endif
  584. /* assign pointers to argument stack */
  585. /* get the function name */
  586. exp_getvfname( expression, CURTASK exps[ CURTASK expsc ].string );
  587. #if INTENSIVE_DEBUG
  588. sprintf( bwb_ebuf, "in exp_function(): name is <%s>.",
  589. CURTASK exps[ CURTASK expsc ].string );
  590. bwb_debug( bwb_ebuf );
  591. #endif
  592. /* now find the function itself */
  593. CURTASK exps[ CURTASK expsc ].function = fnc_find( CURTASK exps[ CURTASK expsc ].string );
  594. /* check to see if it is valid */
  595. if ( CURTASK exps[ CURTASK expsc ].function == NULL )
  596. {
  597. #if PROG_ERRORS
  598. sprintf( bwb_ebuf, "Failed to find function <%s>.",
  599. CURTASK exps[ CURTASK expsc ].string );
  600. bwb_error( bwb_ebuf );
  601. #else
  602. bwb_error( err_uf );
  603. #endif
  604. return OP_ERROR;
  605. }
  606. /* note that this level is a function */
  607. CURTASK exps[ CURTASK expsc ].operation = FUNCTION;
  608. CURTASK exps[ CURTASK expsc ].pos_adv = strlen( CURTASK exps[ CURTASK expsc ].string );
  609. /* check for begin parenthesis */
  610. loop = TRUE;
  611. while( loop == TRUE )
  612. {
  613. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  614. {
  615. case ' ': /* whitespace */
  616. case '\t':
  617. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance */
  618. break;
  619. case '(': /* begin paren */
  620. #if INTENSIVE_DEBUG
  621. sprintf( bwb_ebuf, "in exp_function(): found begin parenthesis." );
  622. bwb_debug( bwb_ebuf );
  623. #endif
  624. ++CURTASK exps[ CURTASK expsc ].pos_adv; /* advance beyond it */
  625. paren_level = 1; /* set paren_level */
  626. loop = FALSE; /* and break out */
  627. break;
  628. default: /* anything else */
  629. loop = FALSE;
  630. paren_level = 0; /* do not look for arguments */
  631. break;
  632. }
  633. }
  634. /* find arguments within parentheses */
  635. /* for each argument, find a string ending with ',' or with end parenthesis */
  636. n_args = 0;
  637. s_pos = 0;
  638. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  639. while( paren_level > 0 )
  640. {
  641. /* check the current character */
  642. switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  643. {
  644. case ',': /* end of an argument */
  645. if ( paren_level == 1 ) /* ignore ',' within parentheses */
  646. {
  647. /* call bwb_exp() recursively to resolve the argument */
  648. if ( exp_validarg( CURTASK exps[ CURTASK expsc ].string ) == TRUE )
  649. {
  650. #if INTENSIVE_DEBUG
  651. sprintf( bwb_ebuf,
  652. "in exp_function(): valid argument (not last)." );
  653. bwb_debug( bwb_ebuf );
  654. #endif
  655. CURTASK exps[ CURTASK expsc ].rec_pos = 0;
  656. e = bwb_exp( CURTASK exps[ CURTASK expsc ].string, FALSE,
  657. &( CURTASK exps[ CURTASK expsc ].rec_pos ) );
  658. /* assign operation and value at this level */
  659. var_make( &( argv[ n_args ] ), e->type );
  660. switch( argv[ n_args ].type )
  661. {
  662. case NUMBER:
  663. * var_findnval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  664. = exp_getnval( e );
  665. break;
  666. case STRING:
  667. str_btob( var_findsval( &( argv[ n_args ] ),
  668. argv[ n_args ].array_pos ), exp_getsval( e ) );
  669. break;
  670. }
  671. ++n_args; /* increment number of arguments */
  672. }
  673. s_pos = 0; /* reset counter */
  674. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  675. }
  676. else
  677. {
  678. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  679. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  680. ++s_pos;
  681. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  682. }
  683. break;
  684. case '(':
  685. ++paren_level;
  686. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  687. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  688. ++s_pos;
  689. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  690. break;
  691. case ')':
  692. --paren_level;
  693. #if INTENSIVE_DEBUG
  694. sprintf( bwb_ebuf,
  695. "in exp_function(): hit close parenthesis." );
  696. bwb_debug( bwb_ebuf );
  697. #endif
  698. if ( paren_level == 0 )
  699. {
  700. #if INTENSIVE_DEBUG
  701. sprintf( bwb_ebuf,
  702. "in exp_function(): paren level 0." );
  703. bwb_debug( bwb_ebuf );
  704. #endif
  705. /* call bwb_exp() recursively to resolve the argument */
  706. if ( exp_validarg( CURTASK exps[ CURTASK expsc ].string ) == TRUE )
  707. {
  708. #if INTENSIVE_DEBUG
  709. sprintf( bwb_ebuf,
  710. "in exp_function(): valid argument (last)." );
  711. bwb_debug( bwb_ebuf );
  712. #endif
  713. CURTASK exps[ CURTASK expsc ].rec_pos = 0;
  714. e = bwb_exp( CURTASK exps[ CURTASK expsc ].string, FALSE,
  715. &( CURTASK exps[ CURTASK expsc ].rec_pos ) );
  716. #if INTENSIVE_DEBUG
  717. sprintf( bwb_ebuf,
  718. "in exp_function(): return from bwb_exp(), last arg, type <%c> op <%d>",
  719. e->type, e->operation );
  720. bwb_debug( bwb_ebuf );
  721. #endif
  722. /* assign operation and value at this level */
  723. var_make( &( argv[ n_args ] ), e->type );
  724. switch( argv[ n_args ].type )
  725. {
  726. case NUMBER:
  727. * var_findnval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  728. = exp_getnval( e );
  729. break;
  730. case STRING:
  731. str_btob( var_findsval( &( argv[ n_args ] ),
  732. argv[ n_args ].array_pos ), exp_getsval( e ) );
  733. break;
  734. }
  735. ++n_args; /* increment number of arguments */
  736. }
  737. s_pos = 0; /* reset counter */
  738. CURTASK exps[ CURTASK expsc ].string[ 0 ] = '\0';
  739. }
  740. else
  741. {
  742. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  743. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  744. ++s_pos;
  745. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  746. }
  747. break;
  748. case '\"': /* embedded string constant */
  749. /* add the initial quotation mark */
  750. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  751. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  752. ++s_pos;
  753. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  754. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  755. /* add intervening characters */
  756. while ( ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '\"' )
  757. && ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '\0' ) )
  758. {
  759. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  760. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  761. ++s_pos;
  762. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  763. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  764. }
  765. /* add the concluding quotation mark */
  766. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  767. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  768. ++s_pos;
  769. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  770. /* the following bracketed out 14 July 1992; since this counter */
  771. /* incremented at the end of the switch statement, this may */
  772. /* increment it past the next character needed */
  773. /* ++CURTASK exps[ CURTASK expsc ].pos_adv; */
  774. break;
  775. default:
  776. CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  777. = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  778. ++s_pos;
  779. CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '\0';
  780. #if INTENSIVE_DEBUG
  781. sprintf( bwb_ebuf, "in exp_function(): new char <%d>=<%c>",
  782. expression[ CURTASK exps[ CURTASK expsc ].pos_adv ],
  783. expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] );
  784. bwb_debug( bwb_ebuf );
  785. sprintf( bwb_ebuf, "in exp_function(): building <%s>.",
  786. CURTASK exps[ CURTASK expsc ].string );
  787. bwb_debug( bwb_ebuf );
  788. #endif
  789. break;
  790. }
  791. /* advance the counter */
  792. ++CURTASK exps[ CURTASK expsc ].pos_adv;
  793. }
  794. #if INTENSIVE_DEBUG
  795. sprintf( bwb_ebuf, "in exp_function(): ready to call function vector" );
  796. bwb_debug( bwb_ebuf );
  797. #endif
  798. /* call the function vector */
  799. #if INTENSIVE_DEBUG
  800. sprintf( bwb_ebuf, "in exp_function(): calling preset function" );
  801. bwb_debug( bwb_ebuf );
  802. #endif
  803. v = CURTASK exps[ CURTASK expsc ].function->vector ( n_args, &( argv[ 0 ] ),
  804. CURTASK exps[ CURTASK expsc ].function->id );
  805. #if INTENSIVE_DEBUG
  806. sprintf( bwb_ebuf, "in exp_function(): return from function vector, type <%c>",
  807. v->type );
  808. bwb_debug( bwb_ebuf );
  809. #endif
  810. /* assign the value at this level */
  811. CURTASK exps[ CURTASK expsc ].type = (char) v->type;
  812. switch( v->type )
  813. {
  814. case STRING:
  815. CURTASK exps[ CURTASK expsc ].operation = CONST_STRING;
  816. #if INTENSIVE_DEBUG
  817. sprintf( bwb_ebuf, "in exp_function(): ready to assign STRING" );
  818. bwb_debug( bwb_ebuf );
  819. #endif
  820. b = var_findsval( v, v->array_pos );
  821. str_btob( exp_getsval( &( CURTASK exps[ CURTASK expsc ] )), b );
  822. #if INTENSIVE_DEBUG
  823. str_btoc( tbuf, b );
  824. sprintf( bwb_ebuf, "in exp_function(): string assigned <%s>", tbuf );
  825. bwb_debug( bwb_ebuf );
  826. #endif
  827. break;
  828. default:
  829. CURTASK exps[ CURTASK expsc ].operation = NUMBER;
  830. CURTASK exps[ CURTASK expsc ].nval = var_getnval( v );
  831. break;
  832. }
  833. #if INTENSIVE_DEBUG
  834. sprintf( bwb_ebuf, "in exp_function(): end of function" );
  835. bwb_debug( bwb_ebuf );
  836. #endif
  837. /* return */
  838. return TRUE;
  839. }
  840. /***************************************************************
  841. FUNCTION: exp_variable()
  842. DESCRIPTION: This function interprets a variable.
  843. ***************************************************************/
  844. #if ANSI_C
  845. int
  846. exp_variable( char *expression )
  847. #else
  848. int
  849. exp_variable( expression )
  850. char *expression;
  851. #endif
  852. {
  853. int pos;
  854. int *pp;
  855. int n_params;
  856. register int n;
  857. struct bwb_variable *v;
  858. bstring *b;
  859. int p;
  860. #if INTENSIVE_DEBUG
  861. sprintf( bwb_ebuf, "in exp_variable(): entered function." );
  862. bwb_debug( bwb_ebuf );
  863. #endif
  864. /* get the variable name */
  865. exp_getvfname( expression, CURTASK exps[ CURTASK expsc ].string );
  866. /* now find the variable itself */
  867. v = CURTASK exps[ CURTASK expsc ].xvar = var_find( CURTASK exps[ CURTASK expsc ].string );
  868. #if INTENSIVE_DEBUG
  869. sprintf( bwb_ebuf, "in exp_variable(): level <%d>, found variable name <%s>",
  870. CURTASK expsc, CURTASK exps[ CURTASK expsc ].xvar->name );
  871. bwb_debug( bwb_ebuf );
  872. #endif
  873. /* note that this level is a variable */
  874. CURTASK exps[ CURTASK expsc ].operation = VARIABLE;
  875. /* read subscripts */
  876. pos = strlen( CURTASK exps[ CURTASK expsc ].string );
  877. if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
  878. {
  879. #if INTENSIVE_DEBUG
  880. sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has 1 dimension",
  881. CURTASK exps[ CURTASK expsc ].xvar->name );
  882. bwb_debug( bwb_ebuf );
  883. #endif
  884. pos = strlen( v->name );
  885. n_params = 1;
  886. pp = &p;
  887. pp[ 0 ] = dim_base;
  888. }
  889. else
  890. {
  891. #if INTENSIVE_DEBUG
  892. sprintf( bwb_ebuf, "in exp_variable(): level <%d> variable <%s> has <%d> dimensions",
  893. CURTASK expsc,
  894. v->name,
  895. v->dimensions );
  896. bwb_debug( bwb_ebuf );
  897. #endif
  898. dim_getparams( expression, &pos, &n_params, &pp );
  899. }
  900. CURTASK exps[ CURTASK expsc ].pos_adv = pos;
  901. for ( n = 0; n < v->dimensions; ++n )
  902. {
  903. CURTASK exps[ CURTASK expsc ].array_pos[ n ] = v->array_pos[ n ] = pp[ n ];
  904. }
  905. #if INTENSIVE_DEBUG
  906. if ( v->dimensions > 1 )
  907. {
  908. sprintf( bwb_ebuf, "in exp_variable(): exec stack level <%d>",
  909. CURTASK exsc );
  910. bwb_debug( bwb_ebuf );
  911. for ( n = 0; n < v->dimensions; ++n )
  912. {
  913. sprintf( bwb_ebuf, " variable <%s> array_pos element <%d> is <%d>.",
  914. v->name, n, v->array_pos[ n ] );
  915. bwb_debug( bwb_ebuf );
  916. }
  917. }
  918. #endif
  919. /* assign the type and value at this level */
  920. CURTASK exps[ CURTASK expsc ].type = (char) v->type;
  921. CURTASK exps[ CURTASK expsc ].xvar = v;
  922. switch( v->type )
  923. {
  924. case STRING:
  925. b = var_findsval( v, v->array_pos );
  926. #if TEST_BSTRING
  927. sprintf( bwb_ebuf, "in exp_variable(): b string name is <%s>",
  928. b->name );
  929. bwb_debug( bwb_ebuf );
  930. #endif
  931. #if OLDWAY
  932. CURTASK exps[ CURTASK expsc ].sval.length = b->length;
  933. CURTASK exps[ CURTASK expsc ].sval.sbuffer = b->sbuffer;
  934. #endif
  935. str_btob( &( CURTASK exps[ CURTASK expsc ].sval ), b );
  936. break;
  937. default:
  938. CURTASK exps[ CURTASK expsc ].nval = var_getnval( v );
  939. break;
  940. }
  941. #if INTENSIVE_DEBUG
  942. sprintf( bwb_ebuf, "in exp_variable(): exit, name <%s>, level <%d>, op <%d>",
  943. v->name, CURTASK expsc, CURTASK exps[ CURTASK expsc ].operation );
  944. bwb_debug( bwb_ebuf );
  945. #endif
  946. /* return */
  947. return TRUE;
  948. }