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

  1. Newsgroups: comp.sources.misc
  2. From: tcamp@acpub.duke.edu (Ted A. Campbell)
  3. Subject:  v33i043:  bwbasic - Bywater BASIC interpreter version 1.10, Part07/11
  4. Message-ID: <1992Nov5.040351.18938@sparky.imd.sterling.com>
  5. X-Md4-Signature: 382408de53db5a1d20d2b7385154a602
  6. Date: Thu, 5 Nov 1992 04:03:51 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 43
  11. Archive-name: bwbasic/part07
  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_elx.c bwb_int.c
  19. # Wrapped by kent@sparky on Wed Nov  4 21:34:26 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 7 (of 11)."'
  23. if test -f 'bwb_elx.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'bwb_elx.c'\"
  25. else
  26.   echo shar: Extracting \"'bwb_elx.c'\" \(36646 characters\)
  27.   sed "s/^X//" >'bwb_elx.c' <<'END_OF_FILE'
  28. X/****************************************************************
  29. X
  30. X        bwb_elx.c       Parse Elements of Expressions
  31. X                        for Bywater BASIC Interpreter
  32. X
  33. X                        Copyright (c) 1992, Ted A. Campbell
  34. X
  35. X                        Bywater Software
  36. X                        P. O. Box 4023
  37. X                        Duke Station
  38. X                        Durham, NC  27706
  39. X
  40. X                        email: tcamp@acpub.duke.edu
  41. X
  42. X        Copyright and Permissions Information:
  43. X
  44. X        All U.S. and international copyrights are claimed by the
  45. X        author. The author grants permission to use this code
  46. X        and software based on it under the following conditions:
  47. X        (a) in general, the code and software based upon it may be
  48. X        used by individuals and by non-profit organizations; (b) it
  49. X        may also be utilized by governmental agencies in any country,
  50. X        with the exception of military agencies; (c) the code and/or
  51. X        software based upon it may not be sold for a profit without
  52. X        an explicit and specific permission from the author, except
  53. X        that a minimal fee may be charged for media on which it is
  54. X        copied, and for copying and handling; (d) the code must be
  55. X        distributed in the form in which it has been released by the
  56. X        author; and (e) the code and software based upon it may not
  57. X        be used for illegal activities.
  58. X
  59. X****************************************************************/
  60. X
  61. X#include <stdio.h>
  62. X#include <stdlib.h>
  63. X#include <string.h>
  64. X#include <ctype.h>
  65. X#include <math.h>
  66. X
  67. X#include "bwbasic.h"
  68. X#include "bwb_mes.h"
  69. X
  70. X/***************************************************************
  71. X
  72. X        FUNCTION:   exp_paren()
  73. X
  74. X        DESCRIPTION:  This function interprets a parenthetical
  75. X        expression, calling bwb_exp() (recursively) to resolve
  76. X        the internal expression.
  77. X
  78. X***************************************************************/
  79. X
  80. Xint
  81. Xexp_paren( char *expression )
  82. X   {
  83. X   struct exp_ese *e;
  84. X   register int c;
  85. X   int s_pos;                           /* position in build buffer */
  86. X   int loop;
  87. X   int paren_level;
  88. X
  89. X   /* find a string enclosed by parentheses */
  90. X
  91. X   exp_es[ exp_esc ].pos_adv = 1;       /* start beyond open paren */
  92. X   s_pos = 0;
  93. X   loop = TRUE;
  94. X   paren_level = 1;
  95. X   exp_es[ exp_esc ].string[ 0 ] = '\0';
  96. X
  97. X   while( loop == TRUE )
  98. X      {
  99. X
  100. X      /* check the current character */
  101. X
  102. X      switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  103. X         {
  104. X
  105. X         case '(':
  106. X            ++paren_level;
  107. X            exp_es[ exp_esc ].string[ s_pos ]
  108. X               = expression[ exp_es[ exp_esc ].pos_adv ];
  109. X            ++s_pos;
  110. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  111. X            break;
  112. X
  113. X         case ')':
  114. X
  115. X            --paren_level;
  116. X            if ( paren_level == 0 )
  117. X               {
  118. X               loop = FALSE;
  119. X               }
  120. X            else
  121. X               {
  122. X               exp_es[ exp_esc ].string[ s_pos ]
  123. X                  = expression[ exp_es[ exp_esc ].pos_adv ];
  124. X               ++s_pos;
  125. X               exp_es[ exp_esc ].string[ s_pos ] = '\0';
  126. X               }
  127. X            break;
  128. X
  129. X         case '\"':                             /* embedded string constant */
  130. X            ++exp_es[ exp_esc ].pos_adv;
  131. X            while ( ( expression[ exp_es[ exp_esc ].pos_adv ] != '\"' )
  132. X               && ( expression[ exp_es[ exp_esc ].pos_adv ] != '\0' ) )
  133. X               {
  134. X               exp_es[ exp_esc ].string[ s_pos ]
  135. X                  = expression[ exp_es[ exp_esc ].pos_adv ];
  136. X               ++s_pos;
  137. X               exp_es[ exp_esc ].string[ s_pos ] = '\0';
  138. X               ++exp_es[ exp_esc ].pos_adv;
  139. X               }
  140. X            break;
  141. X
  142. X         default:
  143. X            exp_es[ exp_esc ].string[ s_pos ]
  144. X               = expression[ exp_es[ exp_esc ].pos_adv ];
  145. X            ++s_pos;
  146. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  147. X            break;
  148. X         }
  149. X
  150. X      /* advance the counter */
  151. X
  152. X      ++exp_es[ exp_esc ].pos_adv;
  153. X
  154. X      }
  155. X
  156. X   #if INTENSIVE_DEBUG
  157. X   sprintf( bwb_ebuf, "in exp_paren() found internal string <%s>",
  158. X      exp_es[ exp_esc ].string );
  159. X   bwb_debug( bwb_ebuf );
  160. X   #endif
  161. X
  162. X   /* call bwb_exp() recursively to interpret this expression */
  163. X
  164. X   exp_es[ exp_esc ].rec_pos = 0;
  165. X   e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
  166. X          &( exp_es[ exp_esc ].rec_pos ) );
  167. X
  168. X   /* assign operation and value at this level */
  169. X
  170. X   exp_es[ exp_esc ].type = e->type;
  171. X
  172. X   switch ( e->type )
  173. X      {
  174. X      case STRING:
  175. X         exp_es[ exp_esc ].operation = CONST_STRING;
  176. X         str_btob( exp_getsval( &( exp_es[ exp_esc ] )), exp_getsval( e ) );
  177. X         break;
  178. X      case INTEGER:
  179. X         exp_es[ exp_esc ].operation = NUMBER;
  180. X         exp_es[ exp_esc ].ival = exp_getival( e );
  181. X         break;
  182. X      case DOUBLE:
  183. X         exp_es[ exp_esc ].operation = NUMBER;
  184. X         exp_es[ exp_esc ].dval = exp_getdval( e );
  185. X         break;
  186. X      default:
  187. X         exp_es[ exp_esc ].operation = NUMBER;
  188. X         exp_es[ exp_esc ].fval = exp_getfval( e );
  189. X         break;
  190. X      }
  191. X
  192. X   return TRUE;
  193. X
  194. X   }
  195. X
  196. X/***************************************************************
  197. X
  198. X        FUNCTION:   exp_strconst()
  199. X
  200. X        DESCRIPTION:  This function interprets a string
  201. X        constant.
  202. X
  203. X***************************************************************/
  204. X
  205. Xint
  206. Xexp_strconst( char *expression )
  207. X   {
  208. X   int e_pos, s_pos;
  209. X
  210. X   /* assign values to structure */
  211. X
  212. X   exp_es[ exp_esc ].type = STRING;
  213. X   exp_es[ exp_esc ].operation = CONST_STRING;
  214. X
  215. X   /* set counters */
  216. X
  217. X   s_pos = 0;
  218. X   exp_es[ exp_esc ].pos_adv = e_pos = 1;
  219. X   exp_es[ exp_esc ].string[ 0 ] = '\0';
  220. X
  221. X   /* read the string up until the next double quotation mark */
  222. X
  223. X   while( expression[ e_pos ] != '\"' )
  224. X      {
  225. X      exp_es[ exp_esc ].string[ s_pos ] = expression[ e_pos ];
  226. X      ++e_pos;
  227. X      ++s_pos;
  228. X      ++exp_es[ exp_esc ].pos_adv;
  229. X      exp_es[ exp_esc ].string[ s_pos ] = '\0';
  230. X      if ( s_pos >= ( MAXSTRINGSIZE - 1 ) )
  231. X         {
  232. X         #if PROG_ERRORS
  233. X         sprintf( bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
  234. X            expression, MAXSTRINGSIZE );
  235. X         bwb_error( bwb_ebuf );
  236. X         #else
  237. X         bwb_error( err_overflow );
  238. X         #endif
  239. X         return OP_NULL;
  240. X         }
  241. X      }
  242. X
  243. X   /* now write string over to bstring */
  244. X
  245. X   str_ctob( &( exp_es[ exp_esc ].sval ), exp_es[ exp_esc ].string );
  246. X
  247. X   /* advance past last double quotation mark */
  248. X
  249. X   ++exp_es[ exp_esc ].pos_adv;
  250. X
  251. X   /* return */
  252. X
  253. X   return TRUE;
  254. X
  255. X   }
  256. X
  257. X/***************************************************************
  258. X
  259. X        FUNCTION:   exp_numconst()
  260. X
  261. X        DESCRIPTION:  This function interprets a numerical
  262. X        constant.
  263. X
  264. X***************************************************************/
  265. X
  266. Xint
  267. Xexp_numconst( char *expression )
  268. X   {
  269. X   int base;                            /* numerical base for the constant */
  270. X   static struct bwb_variable mantissa; /* mantissa of floating-point number */
  271. X   static int init = FALSE;        /* is mantissa variable initialized? */
  272. X   int exponent;                        /* exponent for floating point number */
  273. X   int man_start;                       /* starting point of mantissa */
  274. X   int s_pos;                           /* position in build string */
  275. X   int build_loop;
  276. X   int need_pm;
  277. X   int i;
  278. X   double d;
  279. X   #if CHECK_RECURSION
  280. X   static int in_use = FALSE;                   /* boolean: is function in use? */
  281. X
  282. X   /* check recursion status */
  283. X
  284. X   if ( in_use == TRUE )
  285. X      {
  286. X      sprintf( bwb_ebuf, "Recursion error in bwb_exp.c:exp_findop(): recursion violation." );
  287. X      bwb_error( bwb_ebuf );
  288. X      }
  289. X
  290. X   /* reset recursion status indicator */
  291. X
  292. X   else
  293. X      {
  294. X      in_use = TRUE;
  295. X      }
  296. X   #endif
  297. X
  298. X   /* initialize the variable if necessary */
  299. X
  300. X   #if INTENSIVE_DEBUG
  301. X   strcpy( mantissa.name, "(mantissa)" );
  302. X   #endif
  303. X
  304. X   if ( init == FALSE )
  305. X      {
  306. X      init = TRUE;
  307. X      var_make( &mantissa, DOUBLE );
  308. X      }
  309. X
  310. X   /* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
  311. X      this is necessary because mantissa might be used before dim_base
  312. X      is set */
  313. X
  314. X   mantissa.array_pos[ 0 ] = dim_base;
  315. X
  316. X   #if INTENSIVE_DEBUG
  317. X   sprintf( bwb_ebuf, "in exp_numconst(): received <%s>, eval <%c>",
  318. X      expression, expression[ 0 ] );
  319. X   bwb_debug( bwb_ebuf );
  320. X   #endif
  321. X
  322. X   need_pm = FALSE;
  323. X   exp_es[ exp_esc ].ival = 0;
  324. X
  325. X   /* check the first character(s) to determine numerical base
  326. X      and starting point of the mantissa */
  327. X
  328. X   switch( expression[ 0 ] )
  329. X      {
  330. X      case '-':
  331. X      case '+':
  332. X      case '0':
  333. X      case '1':
  334. X      case '2':
  335. X      case '3':
  336. X      case '4':
  337. X      case '5':
  338. X      case '6':
  339. X      case '7':
  340. X      case '8':
  341. X      case '9':
  342. X      case '.':
  343. X         base = 10;                     /* decimal constant */
  344. X     man_start = 0;                 /* starts at position 0 */
  345. X     need_pm = FALSE;
  346. X         break;
  347. X      case '&':                         /* hex or octal constant */
  348. X         if ( ( expression[ 1 ] == 'H' ) || ( expression[ 1 ] == 'h' ))
  349. X            {
  350. X            base = 16;                  /* hexadecimal constant */
  351. X            man_start = 2;              /* starts at position 2 */
  352. X            }
  353. X         else
  354. X            {
  355. X            base = 8;                   /* octal constant */
  356. X            if ( ( expression[ 1 ] == 'O' ) || ( expression[ 1 ] == 'o' ))
  357. X               {
  358. X               man_start = 2;           /* starts at position 2 */
  359. X               }
  360. X            else
  361. X               {
  362. X               man_start = 1;           /* starts at position 1 */
  363. X               }
  364. X            }
  365. X         break;
  366. X      default:
  367. X
  368. X         #if PROG_ERRORS
  369. X         sprintf( bwb_ebuf, "expression <%s> is not a numerical constant.",
  370. X            expression );
  371. X         bwb_error( bwb_ebuf );
  372. X         #else
  373. X         bwb_error( err_syntax );
  374. X         #endif
  375. X         return OP_NULL;
  376. X      }
  377. X
  378. X   /* now build the mantissa according to the numerical base */
  379. X
  380. X   switch( base )
  381. X      {
  382. X
  383. X      case 10:                          /* decimal constant */
  384. X
  385. X         /* initialize counters */
  386. X
  387. X         exp_es[ exp_esc ].pos_adv = man_start;
  388. X         exp_es[ exp_esc ].type = INTEGER;
  389. X         exp_es[ exp_esc ].string[ 0 ] = '\0';
  390. X         s_pos = 0;
  391. X         exponent = OP_NULL;
  392. X         build_loop = TRUE;
  393. X
  394. X         /* loop to build the string */
  395. X
  396. X         while ( build_loop == TRUE )
  397. X            {
  398. X            switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  399. X               {
  400. X               case '-':                        /* prefixed plus or minus */
  401. X               case '+':
  402. X
  403. X                  /* in the first position, a plus or minus sign can
  404. X                     be added to the beginning of the string to be
  405. X                     scanned */
  406. X
  407. X                  if ( exp_es[ exp_esc ].pos_adv == man_start )
  408. X                     {
  409. X                     exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  410. X                     ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  411. X                     ++s_pos;
  412. X                     exp_es[ exp_esc ].string[ s_pos ] = '\0';
  413. X                     }
  414. X
  415. X                  /* but in any other position, the plus or minus sign
  416. X                     must be taken as an operator and thus as terminating
  417. X                     the string to be scanned */
  418. X
  419. X                  else
  420. X                     {
  421. X                     build_loop = FALSE;
  422. X                     }
  423. X                  break;
  424. X               case '.':                        /* note at least single precision */
  425. X                  if ( exp_es[ exp_esc ].type == INTEGER )
  426. X                     {
  427. X                     exp_es[ exp_esc ].type = SINGLE;
  428. X                     }                          /* fall through (no break) */
  429. X               case '0':                        /* or ordinary digit */
  430. X               case '1':
  431. X               case '2':
  432. X               case '3':
  433. X               case '4':
  434. X               case '5':
  435. X               case '6':
  436. X               case '7':
  437. X               case '8':
  438. X               case '9':
  439. X                  exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  440. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  441. X                  ++s_pos;
  442. X                  exp_es[ exp_esc ].string[ s_pos ] = '\0';
  443. X                  break;
  444. X
  445. X               case 'E':                        /* exponential, single precision */
  446. X               case 'e':
  447. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  448. X                  exp_es[ exp_esc ].type = SINGLE;
  449. X          exponent = TRUE;
  450. X                  build_loop = FALSE;
  451. X                  break;
  452. X
  453. X
  454. X               case 'D':                        /* exponential, double precision */
  455. X               case 'd':
  456. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  457. X                  exp_es[ exp_esc ].type = DOUBLE;
  458. X          exponent = TRUE;
  459. X                  build_loop = FALSE;
  460. X                  break;
  461. X
  462. X               case SINGLE:                     /* single precision termination */
  463. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  464. X                  exp_es[ exp_esc ].type = SINGLE;
  465. X                  build_loop = FALSE;
  466. X                  break;
  467. X
  468. X               case DOUBLE:                     /* double precision termination */
  469. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  470. X                  exp_es[ exp_esc ].type = DOUBLE;
  471. X                  build_loop = FALSE;
  472. X                  break;
  473. X
  474. X               case INTEGER:                    /* integer precision termination */
  475. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  476. X                  exp_es[ exp_esc ].type = INTEGER;
  477. X                  build_loop = FALSE;
  478. X                  break;
  479. X
  480. X               default:                         /* anything else, terminate */
  481. X                  build_loop = FALSE;
  482. X                  break;
  483. X               }
  484. X
  485. X            }
  486. X
  487. X         /* assign the value to the mantissa variable */
  488. X         
  489. X         sscanf( exp_es[ exp_esc ].string, "%lf", 
  490. X           var_finddval( &mantissa, mantissa.array_pos ));
  491. X
  492. X         #if INTENSIVE_DEBUG
  493. X         sprintf( bwb_ebuf, "in exp_numconst(): read mantissa, string <%s> val <%lf>",
  494. X            exp_es[ exp_esc ].string, var_getdval( &mantissa ) );
  495. X         bwb_debug( bwb_ebuf );
  496. X         #endif
  497. X
  498. X         /* test if integer bounds have been exceeded */
  499. X
  500. X         if ( exp_es[ exp_esc ].type == INTEGER )
  501. X            {
  502. X            i = (int) var_getdval( &mantissa );
  503. X            d = (double) i;
  504. X            if ( d != var_getdval( &mantissa ))
  505. X               {
  506. X               exp_es[ exp_esc ].type = DOUBLE;
  507. X               #if INTENSIVE_DEBUG
  508. X               sprintf( bwb_ebuf, "in exp_numconst(): integer bounds violated, promote to DOUBLE" );
  509. X               bwb_debug( bwb_ebuf );
  510. X               #endif               
  511. X               }
  512. X            }
  513. X
  514. X         /* read the exponent if there is one */
  515. X
  516. X         if ( exponent == TRUE )
  517. X            {
  518. X
  519. X        /* allow a plus or minus once at the beginning */
  520. X
  521. X        need_pm = TRUE;
  522. X
  523. X        /* initialize counters */
  524. X
  525. X            exp_es[ exp_esc ].string[ 0 ] = '\0';
  526. X            s_pos = 0;
  527. X            build_loop = TRUE;
  528. X
  529. X            /* loop to build the string */
  530. X
  531. X            while ( build_loop == TRUE )
  532. X               {
  533. X               switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  534. X                  {
  535. X          case '-':                        /* prefixed plus or minus */
  536. X                  case '+':
  537. X
  538. X             if ( need_pm == TRUE )        /* only allow once */
  539. X            {
  540. X            exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  541. X            ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  542. X            ++s_pos;
  543. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  544. X            }
  545. X             else
  546. X            {
  547. X            build_loop = FALSE;
  548. X            }
  549. X             break;
  550. X
  551. X          case '0':                        /* or ordinary digit */
  552. X                  case '1':
  553. X                  case '2':
  554. X                  case '3':
  555. X                  case '4':
  556. X                  case '5':
  557. X                  case '6':
  558. X                  case '7':
  559. X                  case '8':
  560. X                  case '9':
  561. X
  562. X                     exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  563. X                     ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  564. X                     ++s_pos;
  565. X             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  566. X             need_pm = FALSE;
  567. X                     break;
  568. X
  569. X                  default:                         /* anything else, terminate */
  570. X                     build_loop = FALSE;
  571. X                     break;
  572. X                  }
  573. X
  574. X               }                                /* end of build loop for exponent */
  575. X
  576. X            /* assign the value to the user variable */
  577. X
  578. X            sscanf( exp_es[ exp_esc ].string, "%d",
  579. X               &( exp_es[ exp_esc ].ival ) );
  580. X
  581. X        #if INTENSIVE_DEBUG
  582. X        sprintf( bwb_ebuf, "in exp_numconst(): exponent is <%d>",
  583. X               exp_es[ exp_esc ].ival );
  584. X            bwb_debug( bwb_ebuf );
  585. X            #endif
  586. X
  587. X            }                           /* end of exponent search */
  588. X
  589. X         if ( exp_es[ exp_esc ].ival == 0 )
  590. X            {
  591. X            exp_es[ exp_esc ].dval = var_getdval( &mantissa );
  592. X            }
  593. X         else
  594. X            {
  595. X            exp_es[ exp_esc ].dval = var_getdval( &mantissa )
  596. X               * pow( (double) 10.0, (double) exp_es[ exp_esc ].ival );
  597. X            }
  598. X
  599. X         exp_es[ exp_esc ].fval = (float) exp_es[ exp_esc ].dval;
  600. X         exp_es[ exp_esc ].ival = (int) exp_es[ exp_esc ].dval;
  601. X
  602. X         #if INTENSIVE_DEBUG
  603. X         sprintf( bwb_ebuf, "in exp_numconst(): val double <%lf> single <%f> int <%d>",
  604. X            exp_es[ exp_esc ].dval, exp_es[ exp_esc ].fval, exp_es[ exp_esc ].ival );
  605. X         bwb_debug( bwb_ebuf );
  606. X         #endif
  607. X
  608. X         break;
  609. X
  610. X      case 8:                           /* octal constant */
  611. X
  612. X         /* initialize counters */
  613. X
  614. X         exp_es[ exp_esc ].pos_adv = man_start;
  615. X         exp_es[ exp_esc ].type = INTEGER;
  616. X         exp_es[ exp_esc ].string[ 0 ] = '\0';
  617. X         s_pos = 0;
  618. X         exponent = OP_NULL;
  619. X         build_loop = TRUE;
  620. X
  621. X         /* loop to build the string */
  622. X
  623. X         while ( build_loop == TRUE )
  624. X            {
  625. X            switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  626. X               {
  627. X               case '0':                        /* or ordinary digit */
  628. X               case '1':
  629. X               case '2':
  630. X               case '3':
  631. X               case '4':
  632. X               case '5':
  633. X               case '6':
  634. X               case '7':
  635. X                  exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  636. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  637. X                  ++s_pos;
  638. X                  exp_es[ exp_esc ].string[ s_pos ] = '\0';
  639. X                  break;
  640. X
  641. X               default:                         /* anything else, terminate */
  642. X                  build_loop = FALSE;
  643. X                  break;
  644. X               }
  645. X
  646. X            }
  647. X
  648. X         /* now scan the string to determine the number */
  649. X
  650. X         sscanf( exp_es[ exp_esc ].string, "%o",
  651. X            &( exp_es[ exp_esc ].ival ));
  652. X
  653. X         break;
  654. X
  655. X      case 16:                          /* hexadecimal constant */
  656. X
  657. X         /* initialize counters */
  658. X
  659. X         exp_es[ exp_esc ].pos_adv = man_start;
  660. X         exp_es[ exp_esc ].type = INTEGER;
  661. X         exp_es[ exp_esc ].string[ 0 ] = '\0';
  662. X         s_pos = 0;
  663. X         exponent = OP_NULL;
  664. X         build_loop = TRUE;
  665. X
  666. X         /* loop to build the string */
  667. X
  668. X         while ( build_loop == TRUE )
  669. X            {
  670. X            switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  671. X               {
  672. X               case '0':                        /* or ordinary digit */
  673. X               case '1':
  674. X               case '2':
  675. X               case '3':
  676. X               case '4':
  677. X               case '5':
  678. X               case '6':
  679. X               case '7':
  680. X               case '8':
  681. X               case '9':
  682. X               case 'A':
  683. X               case 'a':
  684. X               case 'B':
  685. X               case 'b':
  686. X               case 'C':
  687. X               case 'c':
  688. X               case 'D':
  689. X               case 'd':
  690. X               case 'E':
  691. X               case 'e':
  692. X                  exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  693. X
  694. X                  ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  695. X                  ++s_pos;
  696. X                  exp_es[ exp_esc ].string[ s_pos ] = '\0';
  697. X                  break;
  698. X
  699. X               default:                         /* anything else, terminate */
  700. X                  build_loop = FALSE;
  701. X                  break;
  702. X               }
  703. X
  704. X            }
  705. X
  706. X         /* now scan the string to determine the number */
  707. X
  708. X         sscanf( exp_es[ exp_esc ].string, "%x",
  709. X            &( exp_es[ exp_esc ].ival ));
  710. X
  711. X         break;
  712. X      }
  713. X
  714. X   /* note that the operation at this level is now a determined NUMBER */
  715. X
  716. X   exp_es[ exp_esc ].operation = NUMBER;
  717. X
  718. X   #if INTENSIVE_DEBUG
  719. X   sprintf( bwb_ebuf, "in exp_numconst(): exit level <%d> precision <%c> value <%lf>",
  720. X      exp_esc, exp_es[ exp_esc ].type, exp_getdval( &( exp_es[ exp_esc ] ) ) );
  721. X   bwb_debug( bwb_ebuf );
  722. X   #endif
  723. X
  724. X   #if CHECK_RECURSION
  725. X   in_use = FALSE;
  726. X   #endif
  727. X
  728. X   return TRUE;
  729. X
  730. X   }
  731. X
  732. X/***************************************************************
  733. X
  734. X        FUNCTION:   exp_function()
  735. X
  736. X        DESCRIPTION:  This function interprets a function,
  737. X        calling bwb_exp() (recursively) to resolve any
  738. X        arguments to the function.
  739. X
  740. X***************************************************************/
  741. X
  742. Xint
  743. Xexp_function( char *expression )
  744. X   {
  745. X   struct exp_ese *e;
  746. X   register int c;
  747. X   int s_pos;                           /* position in build buffer */
  748. X   int loop;
  749. X   int paren_level;
  750. X   int n_args;
  751. X   struct bwb_variable *v;
  752. X   struct bwb_variable argv[ MAX_FARGS ];
  753. X   bstring *b;
  754. X   #if INTENSIVE_DEBUG
  755. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  756. X
  757. X   sprintf( bwb_ebuf, "in exp_function(): entered function, expression <%s>",
  758. X      expression );
  759. X   bwb_debug( bwb_ebuf );
  760. X   #endif
  761. X
  762. X   /* assign pointers to argument stack */
  763. X
  764. X   /* get the function name */
  765. X
  766. X   exp_getvfname( expression, exp_es[ exp_esc ].string );
  767. X
  768. X   #if INTENSIVE_DEBUG
  769. X   sprintf( bwb_ebuf, "in exp_function(): name is <%s>.",
  770. X      exp_es[ exp_esc ].string );
  771. X   bwb_debug( bwb_ebuf );
  772. X   #endif
  773. X
  774. X   /* now find the function itself */
  775. X
  776. X   exp_es[ exp_esc ].function = fnc_find( exp_es[ exp_esc ].string );
  777. X
  778. X   /* check to see if it is valid */
  779. X
  780. X   if ( exp_es[ exp_esc ].function == NULL )
  781. X      {
  782. X      #if PROG_ERRORS
  783. X      sprintf( bwb_ebuf, "Failed to find function <%s>.",
  784. X         exp_es[ exp_esc ].string );
  785. X      bwb_error( bwb_ebuf );
  786. X      #else
  787. X      bwb_error( err_uf  );
  788. X      #endif
  789. X      return OP_ERROR;
  790. X      }
  791. X
  792. X   /* note that this level is a function */
  793. X
  794. X   exp_es[ exp_esc ].operation = FUNCTION;
  795. X   exp_es[ exp_esc ].pos_adv = strlen( exp_es[ exp_esc ].string );
  796. X
  797. X   /* check for begin parenthesis */
  798. X
  799. X   loop = TRUE;
  800. X   while( loop == TRUE )
  801. X      {
  802. X      switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  803. X         {
  804. X
  805. X         case ' ':                              /* whitespace */
  806. X         case '\t':
  807. X            ++exp_es[ exp_esc ].pos_adv;        /* advance */
  808. X            break;
  809. X
  810. X         case '(':                              /* begin paren */
  811. X
  812. X            #if INTENSIVE_DEBUG
  813. X            sprintf( bwb_ebuf, "in exp_function(): found begin parenthesis." );
  814. X            bwb_debug( bwb_ebuf );
  815. X            #endif
  816. X
  817. X            ++exp_es[ exp_esc ].pos_adv;        /* advance beyond it */
  818. X            paren_level = 1;                    /* set paren_level */
  819. X            loop = FALSE;                       /* and break out */
  820. X            break;
  821. X
  822. X         default:                               /* anything else */
  823. X            loop = FALSE;
  824. X            paren_level = 0;                    /* do not look for arguments */
  825. X            break;
  826. X         }
  827. X      }
  828. X
  829. X   /* find arguments within parentheses */
  830. X   /* for each argument, find a string ending with ',' or with end parenthesis */
  831. X
  832. X   n_args = 0;
  833. X   s_pos = 0;
  834. X   exp_es[ exp_esc ].string[ 0 ] = '\0';
  835. X
  836. X   while( paren_level > 0 )
  837. X      {
  838. X
  839. X      /* check the current character */
  840. X
  841. X      switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  842. X         {
  843. X
  844. X         case ',':                      /* end of an argument */
  845. X
  846. X            if ( paren_level == 1 )     /* ignore ',' within parentheses */
  847. X               {
  848. X
  849. X               /* call bwb_exp() recursively to resolve the argument */
  850. X
  851. X               if ( exp_validarg( exp_es[ exp_esc ].string ) == TRUE )
  852. X                  {
  853. X          #if INTENSIVE_DEBUG
  854. X          sprintf( bwb_ebuf,
  855. X             "in exp_function(): valid argument (not last)." );
  856. X                  bwb_debug( bwb_ebuf );
  857. X                  #endif
  858. X
  859. X                  exp_es[ exp_esc ].rec_pos = 0;
  860. X                  e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
  861. X                     &( exp_es[ exp_esc ].rec_pos ) );
  862. X
  863. X                  /* assign operation and value at this level */
  864. X
  865. X                  var_make( &( argv[ n_args ] ), e->type );
  866. X
  867. X                  switch( argv[ n_args ].type )
  868. X                     {
  869. X                     case DOUBLE:
  870. X                        * var_finddval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  871. X                            = exp_getdval( e );
  872. X                        break;
  873. X                     case SINGLE:
  874. X                        * var_findfval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  875. X                            = exp_getfval( e );
  876. X                        break;
  877. X                     case INTEGER:
  878. X                        * var_findival( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  879. X                            = exp_getival( e );
  880. X                        break;
  881. X                     case STRING:
  882. X                        str_btob( var_findsval( &( argv[ n_args ] ),
  883. X                           argv[ n_args ].array_pos ), exp_getsval( e ) );
  884. X                        break;
  885. X                     }
  886. X
  887. X                  ++n_args;                /* increment number of arguments */
  888. X
  889. X                  }
  890. X
  891. X               s_pos = 0;               /* reset counter */
  892. X               exp_es[ exp_esc ].string[ 0 ] = '\0';
  893. X               }
  894. X
  895. X            else
  896. X               {
  897. X               exp_es[ exp_esc ].string[ s_pos ]
  898. X                  = expression[ exp_es[ exp_esc ].pos_adv ];
  899. X               ++s_pos;
  900. X               exp_es[ exp_esc ].string[ s_pos ] = '\0';
  901. X               }
  902. X            break;
  903. X
  904. X         case '(':
  905. X            ++paren_level;
  906. X            exp_es[ exp_esc ].string[ s_pos ]
  907. X               = expression[ exp_es[ exp_esc ].pos_adv ];
  908. X            ++s_pos;
  909. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  910. X            break;
  911. X
  912. X         case ')':
  913. X            --paren_level;
  914. X
  915. X            #if INTENSIVE_DEBUG
  916. X            sprintf( bwb_ebuf,
  917. X               "in exp_function(): hit close parenthesis." );
  918. X            bwb_debug( bwb_ebuf );
  919. X            #endif
  920. X
  921. X            if ( paren_level == 0 )
  922. X               {
  923. X
  924. X               #if INTENSIVE_DEBUG
  925. X               sprintf( bwb_ebuf,
  926. X                  "in exp_function(): paren level 0." );
  927. X               bwb_debug( bwb_ebuf );
  928. X               #endif
  929. X
  930. X               /* call bwb_exp() recursively to resolve the argument */
  931. X
  932. X               if ( exp_validarg( exp_es[ exp_esc ].string ) == TRUE )
  933. X                  {
  934. X          #if INTENSIVE_DEBUG
  935. X          sprintf( bwb_ebuf,
  936. X             "in exp_function(): valid argument (last)." );
  937. X          bwb_debug( bwb_ebuf );
  938. X          #endif
  939. X
  940. X                  exp_es[ exp_esc ].rec_pos = 0;
  941. X                  e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
  942. X                     &( exp_es[ exp_esc ].rec_pos ) );
  943. X
  944. X          #if INTENSIVE_DEBUG
  945. X          sprintf( bwb_ebuf,
  946. X             "in exp_function(): return from bwb_exp(), last arg, type <%c> op <%d>",
  947. X             e->type, e->operation );
  948. X          bwb_debug( bwb_ebuf );
  949. X          #endif
  950. X
  951. X                  /* assign operation and value at this level */
  952. X
  953. X                  var_make( &( argv[ n_args ] ), e->type );
  954. X
  955. X                  switch( argv[ n_args ].type )
  956. X                     {
  957. X                     case DOUBLE:
  958. X                        * var_finddval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  959. X                            = exp_getdval( e );
  960. X                        break;
  961. X                     case SINGLE:
  962. X                        * var_findfval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  963. X                            = exp_getfval( e );
  964. X                        break;
  965. X                     case INTEGER:
  966. X                        * var_findival( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  967. X                            = exp_getival( e );
  968. X                        break;
  969. X                     case STRING:
  970. X                        str_btob( var_findsval( &( argv[ n_args ] ),
  971. X                           argv[ n_args ].array_pos ), exp_getsval( e ) );
  972. X                        break;
  973. X                     }
  974. X
  975. X                  ++n_args;                /* increment number of arguments */
  976. X
  977. X                  }
  978. X
  979. X               s_pos = 0;               /* reset counter */
  980. X               exp_es[ exp_esc ].string[ 0 ] = '\0';
  981. X               }
  982. X
  983. X            else
  984. X               {
  985. X               exp_es[ exp_esc ].string[ s_pos ]
  986. X                  = expression[ exp_es[ exp_esc ].pos_adv ];
  987. X               ++s_pos;
  988. X               exp_es[ exp_esc ].string[ s_pos ] = '\0';
  989. X               }
  990. X            break;
  991. X
  992. X         case '\"':                             /* embedded string constant */
  993. X
  994. X            /* add the initial quotation mark */
  995. X
  996. X            exp_es[ exp_esc ].string[ s_pos ]
  997. X               = expression[ exp_es[ exp_esc ].pos_adv ];
  998. X            ++s_pos;
  999. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  1000. X            ++exp_es[ exp_esc ].pos_adv;
  1001. X
  1002. X            /* add intervening characters */
  1003. X
  1004. X            while ( ( expression[ exp_es[ exp_esc ].pos_adv ] != '\"' )
  1005. X               && ( expression[ exp_es[ exp_esc ].pos_adv ] != '\0' ) )
  1006. X               {
  1007. X               exp_es[ exp_esc ].string[ s_pos ]
  1008. X                  = expression[ exp_es[ exp_esc ].pos_adv ];
  1009. X               ++s_pos;
  1010. X               exp_es[ exp_esc ].string[ s_pos ] = '\0';
  1011. X               ++exp_es[ exp_esc ].pos_adv;
  1012. X               }
  1013. X
  1014. X            /* add the concluding quotation mark */
  1015. X
  1016. X            exp_es[ exp_esc ].string[ s_pos ]
  1017. X               = expression[ exp_es[ exp_esc ].pos_adv ];
  1018. X            ++s_pos;
  1019. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  1020. X            /* the following bracketed out 14 July 1992; since this counter */
  1021. X            /* incremented at the end of the switch statement, this may */
  1022. X            /* increment it past the next character needed */
  1023. X            /* ++exp_es[ exp_esc ].pos_adv; */
  1024. X            break;
  1025. X
  1026. X         default:
  1027. X            exp_es[ exp_esc ].string[ s_pos ]
  1028. X               = expression[ exp_es[ exp_esc ].pos_adv ];
  1029. X            ++s_pos;
  1030. X            exp_es[ exp_esc ].string[ s_pos ] = '\0';
  1031. X            #if INTENSIVE_DEBUG
  1032. X            sprintf( bwb_ebuf, "in exp_function(): new char <%d>=<%c>",
  1033. X               expression[ exp_es[ exp_esc ].pos_adv ],
  1034. X               expression[ exp_es[ exp_esc ].pos_adv ] );
  1035. X            bwb_debug( bwb_ebuf );
  1036. X            sprintf( bwb_ebuf, "in exp_function(): building <%s>.",
  1037. X               exp_es[ exp_esc ].string );
  1038. X            bwb_debug( bwb_ebuf );
  1039. X            #endif
  1040. X            break;
  1041. X         }
  1042. X
  1043. X      /* advance the counter */
  1044. X
  1045. X      ++exp_es[ exp_esc ].pos_adv;
  1046. X
  1047. X      }
  1048. X
  1049. X   #if INTENSIVE_DEBUG
  1050. X   sprintf( bwb_ebuf, "in exp_function(): ready to call function vector" );
  1051. X   bwb_debug( bwb_ebuf );
  1052. X   #endif
  1053. X
  1054. X   /* call the function vector */
  1055. X
  1056. X   if ( exp_es[ exp_esc ].function->ufnc != NULL )
  1057. X      {
  1058. X      #if INTENSIVE_DEBUG
  1059. X      sprintf( bwb_ebuf, "in exp_function(): calling fnc_intufnc()" );
  1060. X      bwb_debug( bwb_ebuf );
  1061. X      #endif
  1062. X      v = fnc_intufnc( n_args, &( argv[ 0 ] ), exp_es[ exp_esc ].function );
  1063. X      }
  1064. X   else
  1065. X      {
  1066. X      #if INTENSIVE_DEBUG
  1067. X      sprintf( bwb_ebuf, "in exp_function(): calling preset function" );
  1068. X      bwb_debug( bwb_ebuf );
  1069. X      #endif
  1070. X      v = exp_es[ exp_esc ].function->vector ( n_args, &( argv[ 0 ] ) );
  1071. X      }
  1072. X
  1073. X   #if INTENSIVE_DEBUG
  1074. X   sprintf( bwb_ebuf, "in exp_function(): return from function vector, type <%c>",
  1075. X      v->type );
  1076. X   bwb_debug( bwb_ebuf );
  1077. X   #endif
  1078. X
  1079. X   /* assign the value at this level */
  1080. X
  1081. X   exp_es[ exp_esc ].type = (char) v->type;
  1082. X   
  1083. X   switch( v->type )
  1084. X      {
  1085. X      case STRING:
  1086. X         exp_es[ exp_esc ].operation = CONST_STRING;
  1087. X
  1088. X         #if INTENSIVE_DEBUG
  1089. X         sprintf( bwb_ebuf, "in exp_function(): ready to assign STRING" );
  1090. X         bwb_debug( bwb_ebuf );
  1091. X         #endif
  1092. X
  1093. X         b = var_findsval( v, v->array_pos );
  1094. X         str_btob( exp_getsval( &( exp_es[ exp_esc ] )), b );
  1095. X
  1096. X         #if INTENSIVE_DEBUG
  1097. X         str_btoc( tbuf, b );
  1098. X         sprintf( bwb_ebuf, "in exp_function(): string assigned <%s>", tbuf );
  1099. X         bwb_debug( bwb_ebuf );
  1100. X         #endif
  1101. X
  1102. X         break;
  1103. X
  1104. X      case DOUBLE:
  1105. X         exp_es[ exp_esc ].operation = NUMBER;
  1106. X         exp_es[ exp_esc ].dval = var_getdval( v );
  1107. X         break;
  1108. X      case INTEGER:
  1109. X         exp_es[ exp_esc ].operation = NUMBER;
  1110. X         exp_es[ exp_esc ].ival = var_getival( v );
  1111. X         break;
  1112. X      default:
  1113. X         exp_es[ exp_esc ].operation = NUMBER;
  1114. X         exp_es[ exp_esc ].fval = var_getfval( v );
  1115. X         break;
  1116. X      }
  1117. X
  1118. X   #if INTENSIVE_DEBUG
  1119. X   sprintf( bwb_ebuf, "in exp_function(): end of function" );
  1120. X   bwb_debug( bwb_ebuf );
  1121. X   #endif
  1122. X
  1123. X   /* return */
  1124. X
  1125. X   return TRUE;
  1126. X
  1127. X   }
  1128. X
  1129. X/***************************************************************
  1130. X
  1131. X        FUNCTION:   exp_variable()
  1132. X
  1133. X        DESCRIPTION:  This function interprets a variable.
  1134. X
  1135. X***************************************************************/
  1136. X
  1137. Xint
  1138. Xexp_variable( char *expression )
  1139. X   {
  1140. X   int pos;
  1141. X   int *pp;
  1142. X   int n_params;
  1143. X   register int n;
  1144. X   struct bwb_variable *v;
  1145. X   bstring *b;
  1146. X   int p;
  1147. X
  1148. X   #if INTENSIVE_DEBUG
  1149. X   sprintf( bwb_ebuf, "in exp_variable(): entered function." );
  1150. X   bwb_debug( bwb_ebuf );
  1151. X   #endif
  1152. X
  1153. X   /* get the variable name */
  1154. X
  1155. X   exp_getvfname( expression, exp_es[ exp_esc ].string );
  1156. X
  1157. X   /* now find the variable itself */
  1158. X
  1159. X   v = exp_es[ exp_esc ].xvar = var_find( exp_es[ exp_esc ].string );
  1160. X
  1161. X   #if INTENSIVE_DEBUG
  1162. X   sprintf( bwb_ebuf, "in exp_variable(): level <%d>, found variable name <%s>",
  1163. X      exp_esc, exp_es[ exp_esc ].xvar->name );
  1164. X   bwb_debug( bwb_ebuf );
  1165. X   #endif
  1166. X
  1167. X   /* note that this level is a variable */
  1168. X
  1169. X   exp_es[ exp_esc ].operation = VARIABLE;
  1170. X
  1171. X   /* read subscripts */
  1172. X
  1173. X   pos = strlen( exp_es[ exp_esc ].string );
  1174. X   if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
  1175. X      {
  1176. X      #if INTENSIVE_DEBUG
  1177. X      sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has 1 dimension",
  1178. X         exp_es[ exp_esc ].xvar->name );
  1179. X      bwb_debug( bwb_ebuf );
  1180. X      #endif
  1181. X      pos = strlen( v->name );
  1182. X      n_params = 1;
  1183. X      pp = &p;
  1184. X      pp[ 0 ] = dim_base;
  1185. X      }
  1186. X   else
  1187. X      {
  1188. X      #if INTENSIVE_DEBUG
  1189. X      sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has > 1 dimensions",
  1190. X         exp_es[ exp_esc ].xvar->name );
  1191. X      bwb_debug( bwb_ebuf );
  1192. X      #endif
  1193. X      dim_getparams( expression, &pos, &n_params, &pp );
  1194. X      }
  1195. X
  1196. X   exp_es[ exp_esc ].pos_adv = pos;
  1197. X   for ( n = 0; n < v->dimensions; ++n )
  1198. X      {
  1199. X      exp_es[ exp_esc ].array_pos[ n ] = v->array_pos[ n ] = pp[ n ];
  1200. X      }
  1201. X
  1202. X   #if INTENSIVE_DEBUG
  1203. X   for ( n = 0; n < v->dimensions; ++ n )
  1204. X      {
  1205. X      sprintf( bwb_ebuf, "in exp_variable(): var <%s> array_pos element <%d> is <%d>.",
  1206. X         v->name, n, v->array_pos[ n ] );
  1207. X      bwb_debug( bwb_ebuf );
  1208. X      }
  1209. X   #endif
  1210. X
  1211. X   /* assign the type and value at this level */
  1212. X
  1213. X   exp_es[ exp_esc ].type = (char) v->type;
  1214. X   
  1215. X   switch( v->type )
  1216. X      {
  1217. X      case STRING:
  1218. X         b = var_findsval( v, v->array_pos );
  1219. X         #if TEST_BSTRING
  1220. X         sprintf( bwb_ebuf, "in exp_variable(): b string name is <%s>",
  1221. X            b->name );
  1222. X         bwb_debug( bwb_ebuf );
  1223. X         #endif
  1224. X         exp_es[ exp_esc ].sval.length = b->length;
  1225. X         exp_es[ exp_esc ].sval.buffer = b->buffer;
  1226. X         break;
  1227. X      case DOUBLE:
  1228. X         exp_es[ exp_esc ].dval = var_getdval( v );
  1229. X         break;
  1230. X      case INTEGER:
  1231. X         exp_es[ exp_esc ].ival = var_getival( v );
  1232. X         break;
  1233. X      default:
  1234. X         exp_es[ exp_esc ].fval = var_getfval( v );
  1235. X         break;
  1236. X      }
  1237. X
  1238. X   #if INTENSIVE_DEBUG
  1239. X   sprintf( bwb_ebuf, "in exp_variable(): exit, name <%s>, level <%d>, op <%d>",
  1240. X      v->name, exp_esc, exp_es[ exp_esc ].operation  );
  1241. X   bwb_debug( bwb_ebuf );
  1242. X   #endif
  1243. X
  1244. X   /* return */
  1245. X
  1246. X   return TRUE;
  1247. X
  1248. X   }
  1249. X
  1250. X
  1251. END_OF_FILE
  1252.   if test 36646 -ne `wc -c <'bwb_elx.c'`; then
  1253.     echo shar: \"'bwb_elx.c'\" unpacked with wrong size!
  1254.   fi
  1255.   # end of 'bwb_elx.c'
  1256. fi
  1257. if test -f 'bwb_int.c' -a "${1}" != "-c" ; then 
  1258.   echo shar: Will not clobber existing file \"'bwb_int.c'\"
  1259. else
  1260.   echo shar: Extracting \"'bwb_int.c'\" \(17458 characters\)
  1261.   sed "s/^X//" >'bwb_int.c' <<'END_OF_FILE'
  1262. X/***************************************************************f
  1263. X
  1264. X        bwb_int.c       Line Interpretation Routines
  1265. X                        for Bywater BASIC Interpreter
  1266. X
  1267. X                        Copyright (c) 1992, Ted A. Campbell
  1268. X
  1269. X                        Bywater Software
  1270. X                        P. O. Box 4023
  1271. X                        Duke Station
  1272. X                        Durham, NC  27706
  1273. X
  1274. X                        email: tcamp@acpub.duke.edu
  1275. X
  1276. X        Copyright and Permissions Information:
  1277. X
  1278. X        All U.S. and international copyrights are claimed by the
  1279. X        author. The author grants permission to use this code
  1280. X        and software based on it under the following conditions:
  1281. X        (a) in general, the code and software based upon it may be
  1282. X        used by individuals and by non-profit organizations; (b) it
  1283. X        may also be utilized by governmental agencies in any country,
  1284. X        with the exception of military agencies; (c) the code and/or
  1285. X        software based upon it may not be sold for a profit without
  1286. X        an explicit and specific permission from the author, except
  1287. X        that a minimal fee may be charged for media on which it is
  1288. X        copied, and for copying and handling; (d) the code must be
  1289. X        distributed in the form in which it has been released by the
  1290. X        author; and (e) the code and software based upon it may not
  1291. X        be used for illegal activities.
  1292. X
  1293. X***************************************************************/
  1294. X
  1295. X#include <stdio.h>
  1296. X#include <stdlib.h>
  1297. X#include <ctype.h>
  1298. X#include <string.h>
  1299. X
  1300. X#include "bwbasic.h"
  1301. X#include "bwb_mes.h"
  1302. X
  1303. X/***************************************************************
  1304. X
  1305. X        FUNCTION:       adv_element()
  1306. X
  1307. X        DESCRIPTION:    This function reads characters in <buffer>
  1308. X                        beginning at <pos> and advances past a
  1309. X                        line element, incrementing <pos> appropri-
  1310. X                        ately and returning the line element in
  1311. X                        <element>.
  1312. X
  1313. X***************************************************************/
  1314. X
  1315. Xint
  1316. Xadv_element( char *buffer, int *pos, char *element )
  1317. X   {
  1318. X   int loop;                                    /* control loop */
  1319. X   int e_pos;                                   /* position in element buffer */
  1320. X   int str_const;                               /* boolean: building a string constant */
  1321. X
  1322. X   /* advance beyond any initial whitespace */
  1323. X
  1324. X   adv_ws( buffer, pos );
  1325. X
  1326. X   #if INTENSIVE_DEBUG
  1327. X   sprintf( bwb_ebuf, "in adv_element(): receieved <%s>.", &( buffer[ *pos ] ));
  1328. X   bwb_debug( bwb_ebuf );
  1329. X   #endif
  1330. X
  1331. X   /* now loop while building an element and looking for an
  1332. X      element terminator */
  1333. X
  1334. X   loop = TRUE;
  1335. X   e_pos = 0;
  1336. X   element[ e_pos ] = '\0';
  1337. X   str_const = FALSE;
  1338. X
  1339. X   while ( loop == TRUE )
  1340. X      {
  1341. X      switch( buffer[ *pos ] )
  1342. X         {
  1343. X         case ',':                      /* element terminators */
  1344. X         case ';':
  1345. X         case ':':
  1346. X         case '=':
  1347. X         case ' ':
  1348. X         case '\t':
  1349. X         case '\0':
  1350. X         case '\n':
  1351. X         case '\r':
  1352. X            if ( str_const == TRUE )
  1353. X               {
  1354. X               element[ e_pos ] = buffer[ *pos ];
  1355. X               ++e_pos;
  1356. X               ++( *pos );
  1357. X               element[ e_pos ] = '\0';
  1358. X               }
  1359. X            else
  1360. X               {
  1361. X               return TRUE;
  1362. X               }
  1363. X            break;
  1364. X
  1365. X         case '\"':                     /* string constant */
  1366. X            element[ e_pos ] = buffer[ *pos ];
  1367. X            ++e_pos;
  1368. X            ++( *pos );
  1369. X            element[ e_pos ] = '\0';
  1370. X            if ( str_const == TRUE )    /* termination of string constant */
  1371. X               {
  1372. X               return TRUE;
  1373. X               }
  1374. X            else                        /* beginning of string constant */
  1375. X               {
  1376. X               str_const = TRUE;
  1377. X               }
  1378. X            break;
  1379. X
  1380. X         default:
  1381. X            element[ e_pos ] = buffer[ *pos ];
  1382. X            ++e_pos;
  1383. X            ++( *pos );
  1384. X            element[ e_pos ] = '\0';
  1385. X            break;
  1386. X         }
  1387. X      }
  1388. X
  1389. X   /* This should not happen */
  1390. X
  1391. X   return FALSE;
  1392. X
  1393. X   }
  1394. X
  1395. X/***************************************************************
  1396. X
  1397. X        FUNCTION:       adv_ws()
  1398. X
  1399. X        DESCRIPTION:    This function reads characters in <buffer>
  1400. X                        beginning at <pos> and advances past any
  1401. X                        whitespace, incrementing <pos> appropri-
  1402. X                        ately.
  1403. X
  1404. X***************************************************************/
  1405. X
  1406. Xint
  1407. Xadv_ws( char *buffer, int *pos )
  1408. X   {
  1409. X   int loop;
  1410. X
  1411. X   loop = TRUE;
  1412. X   while ( loop == TRUE )
  1413. X      {
  1414. X      switch( buffer[ *pos ] )
  1415. X         {
  1416. X         case ' ':
  1417. X         case '\t':
  1418. X            ++( *pos );
  1419. X            break;
  1420. X         default:
  1421. X            return TRUE;
  1422. X         }
  1423. X      }
  1424. X
  1425. X   /* This should not happen */
  1426. X
  1427. X   return FALSE;
  1428. X
  1429. X   }
  1430. X
  1431. X/***************************************************************
  1432. X
  1433. X        FUNCTION:       bwb_strtoupper()
  1434. X
  1435. X        DESCRIPTION:    This function converts the string in
  1436. X                        <buffer> to upper-case characters.
  1437. X
  1438. X***************************************************************/
  1439. X
  1440. Xint
  1441. Xbwb_strtoupper( char *buffer )
  1442. X   {
  1443. X   char *p;
  1444. X
  1445. X   p = buffer;
  1446. X   while ( *p != '\0' )
  1447. X      {
  1448. X      if ( islower( *p ) != FALSE )
  1449. X         {
  1450. X         *p = toupper( *p );
  1451. X         }
  1452. X      ++p;
  1453. X      }
  1454. X
  1455. X   return TRUE;
  1456. X
  1457. X   }
  1458. X
  1459. X/***************************************************************
  1460. X
  1461. X        FUNCTION:       line_start()
  1462. X
  1463. X        DESCRIPTION:    This function reads a line buffer in
  1464. X                        <buffer> beginning at the position
  1465. X                        <pos> and attempts to determine (a)
  1466. X                        the position of the line number in the
  1467. X                        buffer (returned in <lnpos>), (b) the
  1468. X                        line number at this position (returned
  1469. X                        in <lnum>), (c) the position of the
  1470. X                        BASIC command in the buffer (returned
  1471. X                        in <cmdpos>), (d) the position of this
  1472. X                        BASIC command in the command table
  1473. X                        (returned in <cmdnum>), and (e) the
  1474. X                        position of the beginning of the rest
  1475. X                        of the line (returned in <startpos>).
  1476. X                        Although <startpos> must be returned
  1477. X                        as a positive integer, the other
  1478. X                        searches may fail, in which case FALSE
  1479. X                        will be returned in their positions.
  1480. X                        <pos> is not incremented.
  1481. X
  1482. X***************************************************************/
  1483. X
  1484. Xint
  1485. Xline_start( char *buffer, int *pos, int *lnpos, int *lnum, int *cmdpos,
  1486. X   int *cmdnum, int *startpos )
  1487. X   {
  1488. X   static int position;
  1489. X   register int n;
  1490. X   static char *tbuf;
  1491. X   static int init = FALSE;
  1492. X
  1493. X   /* get memory for temporary buffer if necessary */
  1494. X
  1495. X   if ( init == FALSE )
  1496. X      {
  1497. X      init = TRUE;
  1498. X      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  1499. X         {
  1500. X         bwb_error( err_getmem );
  1501. X         }
  1502. X      }
  1503. X
  1504. X   #if INTENSIVE_DEBUG
  1505. X   sprintf( bwb_ebuf, "in line_start(): pos <%d> buffer <%s>", *pos,
  1506. X      buffer );
  1507. X   bwb_debug( bwb_ebuf );
  1508. X   #endif
  1509. X
  1510. X   /* set initial values */
  1511. X
  1512. X   *startpos = position = *pos;
  1513. X   *cmdpos = *lnpos = *pos;
  1514. X   *cmdnum = *lnum = -1;
  1515. X
  1516. X   /* check for null line */
  1517. X
  1518. X   adv_ws( buffer, &position );
  1519. X   if ( buffer[ position ] == '\0' )
  1520. X      {
  1521. X      #if INTENSIVE_DEBUG
  1522. X      bwb_debug( "in line_start(): found NULL line" );
  1523. X      #endif
  1524. X      *cmdnum = getcmdnum( "REM" );
  1525. X      return TRUE;
  1526. X      }
  1527. X
  1528. X   /* advance beyond the first element */
  1529. X
  1530. X   *lnpos = position;
  1531. X   adv_element( buffer, &position, tbuf );
  1532. X   adv_ws( buffer, &position );
  1533. X
  1534. X   /* test for a line number in the first element */
  1535. X
  1536. X   if ( is_numconst( tbuf ) == TRUE )               /* a line number */
  1537. X      {
  1538. X
  1539. X      *lnum = atoi( tbuf );
  1540. X      *startpos = position;                             /* temp */
  1541. X      *cmdpos = position;
  1542. X
  1543. X      adv_element( buffer, &position, tbuf );       /* advance past next element */
  1544. X
  1545. X      #if INTENSIVE_DEBUG
  1546. X      sprintf( bwb_ebuf, "in line_start(): new element is <%s>", tbuf );
  1547. X      bwb_debug( bwb_ebuf );
  1548. X      #endif
  1549. X
  1550. X      if ( is_cmd( tbuf, cmdnum ) == TRUE )
  1551. X         {
  1552. X         adv_ws( buffer, &position );
  1553. X         *startpos = position;
  1554. X         }
  1555. X      else if ( is_let( &( buffer[ *cmdpos ] ), cmdnum ) == TRUE )
  1556. X         {
  1557. X         *cmdpos = -1;
  1558. X         }
  1559. X      else
  1560. X         {
  1561. X         *cmdpos = *cmdnum = -1;
  1562. X         }
  1563. X      }
  1564. X
  1565. X   /* not a line number */
  1566. X
  1567. X   else
  1568. X      {
  1569. X      *lnum = -1;
  1570. X      *lnpos = -1;
  1571. X
  1572. X      #if INTENSIVE_DEBUG
  1573. X      sprintf( bwb_ebuf, "in line_start(): no line number, element <%s>.",
  1574. X         tbuf );
  1575. X      bwb_debug( bwb_ebuf );
  1576. X      #endif
  1577. X
  1578. X      if ( is_cmd( tbuf, cmdnum ) == TRUE )
  1579. X         {
  1580. X         adv_ws( buffer, &position );
  1581. X         *startpos = position;
  1582. X         }
  1583. X      else if ( is_let( &( buffer[ position ] ), cmdnum ) == TRUE )
  1584. X         {
  1585. X         adv_ws( buffer, &position );
  1586. X         *cmdpos = -1;
  1587. X         }
  1588. X      else
  1589. X         {
  1590. X         *cmdpos = *cmdnum = -1;
  1591. X         }
  1592. X      }
  1593. X
  1594. X   #if INTENSIVE_DEBUG
  1595. X   sprintf( bwb_ebuf, "in line_start(): lnpos <%d> lnum <%d>",
  1596. X      *lnpos, *lnum );
  1597. X   bwb_debug( bwb_ebuf );
  1598. X   sprintf( bwb_ebuf, "in line_start(): cmdpos <%d> cmdnum <%d> startpos <%d>",
  1599. X      *cmdpos, *cmdnum, *startpos );
  1600. X   bwb_debug( bwb_ebuf );
  1601. X   #endif
  1602. X
  1603. X   /* return */
  1604. X
  1605. X   return TRUE;
  1606. X
  1607. X   }
  1608. X
  1609. X/***************************************************************
  1610. X
  1611. X        FUNCTION:       is_cmd()
  1612. X
  1613. X        DESCRIPTION:
  1614. X
  1615. X***************************************************************/
  1616. X
  1617. Xint
  1618. Xis_cmd( char *buffer, int *cmdnum )
  1619. X   {
  1620. X   register int n;
  1621. X
  1622. X   /* Convert the command name to upper case */
  1623. X
  1624. X   bwb_strtoupper( buffer );
  1625. X
  1626. X   /* Go through the command table and search for a match. */
  1627. X
  1628. X   for ( n = 0; n < COMMANDS; ++n )
  1629. X      {
  1630. X      if ( strncmp( bwb_cmdtable[ n ].name, buffer,
  1631. X         strlen( bwb_cmdtable[ n ].name )) == 0 )
  1632. X         {
  1633. X         *cmdnum = n;
  1634. X         return TRUE;
  1635. X         }
  1636. X      }
  1637. X
  1638. X   /* No command name was found */
  1639. X
  1640. X   *cmdnum = -1;
  1641. X   return FALSE;
  1642. X
  1643. X   }
  1644. X
  1645. X/***************************************************************
  1646. X
  1647. X        FUNCTION:       is_let()
  1648. X
  1649. X        DESCRIPTION:    This function tries to determine if the
  1650. X                        expression in <buffer> is a LET statement
  1651. X                        without the LET command specified.
  1652. X
  1653. X***************************************************************/
  1654. X
  1655. Xint
  1656. Xis_let( char *buffer, int *cmdnum )
  1657. X   {
  1658. X   register int n, i;
  1659. X
  1660. X   #if INTENSIVE_DEBUG
  1661. X   sprintf( bwb_ebuf, "in is_let(): buffer <%s>", buffer );
  1662. X   bwb_debug( bwb_ebuf );
  1663. X   #endif
  1664. X
  1665. X   /* Go through the expression and search for an assignment operator. */
  1666. X
  1667. X   for ( n = 0; buffer[ n ] != '\0'; ++n )
  1668. X      {
  1669. X      switch( buffer[ n ] )
  1670. X         {
  1671. X         case '\"':                     /* string constant */
  1672. X            ++n;
  1673. X            while( buffer[ n ] != '\"' )
  1674. X               {
  1675. X               ++n;
  1676. X               if ( buffer[ n ] == '\0' )
  1677. X                  {
  1678. X                  #if PROG_ERRORS
  1679. X                  sprintf( bwb_ebuf, "Incomplete string constant" );
  1680. X                  bwb_error( bwb_ebuf );
  1681. X                  #else
  1682. X                  bwb_error( err_syntax );
  1683. X                  #endif
  1684. X                  *cmdnum = -1;
  1685. X                  return FALSE;
  1686. X                  }
  1687. X               }
  1688. X            ++n;
  1689. X            break;
  1690. X         case '=':
  1691. X
  1692. X            #if INTENSIVE_DEBUG
  1693. X            sprintf( bwb_ebuf, "in is_let(): implied LET found." );
  1694. X            bwb_debug( bwb_ebuf );
  1695. X            #endif
  1696. X
  1697. X            for ( i = 0; i < COMMANDS; ++i )
  1698. X               {
  1699. X               if ( strncmp( bwb_cmdtable[ i ].name, "LET", (size_t) 3 ) == 0 )
  1700. X                  {
  1701. X                  *cmdnum = i;
  1702. X                  }
  1703. X               }
  1704. X            return TRUE;
  1705. X         }
  1706. X      }
  1707. X
  1708. X   /* No command name was found */
  1709. X
  1710. X   *cmdnum = -1;
  1711. X   return FALSE;
  1712. X
  1713. X   }
  1714. X
  1715. X/***************************************************************
  1716. X
  1717. X        FUNCTION:       bwb_stripcr()
  1718. X
  1719. X        DESCRIPTION:
  1720. X
  1721. X
  1722. X***************************************************************/
  1723. X
  1724. Xint
  1725. Xbwb_stripcr( char *s )
  1726. X   {
  1727. X   char *p;
  1728. X
  1729. X   p = s;
  1730. X   while ( *p != 0 )
  1731. X      {
  1732. X      switch( *p )
  1733. X         {
  1734. X
  1735. X
  1736. X         case 0x0d:
  1737. X         case 0x0a:
  1738. X            *p = 0;
  1739. X            return TRUE;
  1740. X         }
  1741. X      ++p;
  1742. X      }
  1743. X   *p = 0;
  1744. X   return TRUE;
  1745. X   }
  1746. X
  1747. X/***************************************************************
  1748. X
  1749. X        FUNCTION:       is_numconst()
  1750. X
  1751. X        DESCRIPTION:    This function reads the string in <buffer>
  1752. X                        and returns TRUE if it is a numerical
  1753. X                        constant and FALSE if it is not. At
  1754. X                        this point, only decimal (base 10)
  1755. X                        constants are detected.
  1756. X
  1757. X***************************************************************/
  1758. X
  1759. Xint
  1760. Xis_numconst( char *buffer )
  1761. X   {
  1762. X   char *p;
  1763. X
  1764. X   #if INTENSIVE_DEBUG
  1765. X   sprintf( bwb_ebuf, "in is_numconst(): received string <%s>.", buffer );
  1766. X   bwb_debug( bwb_ebuf );
  1767. X   #endif
  1768. X
  1769. X   /* Return FALSE for empty buffer */
  1770. X
  1771. X   if ( buffer[ 0 ] == '\0' )
  1772. X      {
  1773. X      return FALSE;
  1774. X      }
  1775. X
  1776. X   /* else check digits */
  1777. X
  1778. X   p = buffer;
  1779. X   while( *p != '\0' )
  1780. X      {
  1781. X      switch( *p )
  1782. X         {
  1783. X         case '0':
  1784. X         case '1':
  1785. X         case '2':
  1786. X         case '3':
  1787. X         case '4':
  1788. X         case '5':
  1789. X         case '6':
  1790. X         case '7':
  1791. X         case '8':
  1792. X         case '9':
  1793. X            break;
  1794. X         default:
  1795. X            return FALSE;
  1796. X         }
  1797. X      ++p;
  1798. X      }
  1799. X
  1800. X   /* only numerical characters detected */
  1801. X
  1802. X   return TRUE;
  1803. X
  1804. X   }
  1805. X
  1806. X/***************************************************************
  1807. X
  1808. X        FUNCTION:       bwb_numseq()
  1809. X
  1810. X        DESCRIPTION:
  1811. X
  1812. X***************************************************************/
  1813. X
  1814. Xint
  1815. Xbwb_numseq( char *buffer, int *start, int *end )
  1816. X   {
  1817. X   register int b, n;
  1818. X   int numbers;
  1819. X   static char *tbuf;
  1820. X   static int init = FALSE;
  1821. X
  1822. X   /* get memory for temporary buffer if necessary */
  1823. X
  1824. X   if ( init == FALSE )
  1825. X      {
  1826. X      init = TRUE;
  1827. X      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  1828. X         {
  1829. X         bwb_error( err_getmem );
  1830. X         }
  1831. X      }
  1832. X
  1833. X   if ( buffer[ 0 ] == 0 )
  1834. X      {
  1835. X      *start = *end = 0;
  1836. X      return FALSE;
  1837. X      }
  1838. X
  1839. X   numbers = n = b = 0;
  1840. X   tbuf[ 0 ] = 0;
  1841. X   while( TRUE )
  1842. X      {
  1843. X      switch( buffer[ b ] )
  1844. X         {
  1845. X         case 0:                           /* end of string */
  1846. X         case '\n':
  1847. X         case '\r':
  1848. X            if ( n > 0 )
  1849. X               {
  1850. X               if ( numbers == 0 )
  1851. X                  {
  1852. X                  *end = 0;
  1853. X                  *start = atoi( tbuf );
  1854. X                  ++numbers;
  1855. X                  }
  1856. X               else
  1857. X                  {
  1858. X
  1859. X                  *end = atoi( tbuf );
  1860. X                  return TRUE;
  1861. X                  }
  1862. X               }
  1863. X            else
  1864. X               {
  1865. X               if ( numbers == 0 )
  1866. X                  {
  1867. X                  *start = *end = 0;
  1868. X                  }
  1869. X               else if ( numbers == 1 )
  1870. X                  {
  1871. X                  *end = 0;
  1872. X                  }
  1873. X               else if ( ( numbers == 2 ) && ( tbuf[ 0 ] == 0 ))
  1874. X                  {
  1875. X                  *end = 0;
  1876. X                  }
  1877. X               }
  1878. X            return TRUE;
  1879. X
  1880. X         #ifdef ALLOWWHITESPACE
  1881. X         case ' ':                         /* whitespace */
  1882. X         case '\t':
  1883. X         #endif
  1884. X
  1885. X         case '-':                         /* or skip to next number */
  1886. X            if ( n > 0 )
  1887. X               {
  1888. X               if ( numbers == 0 )
  1889. X                  {
  1890. X                  *start = atoi( tbuf );
  1891. X                  ++numbers;
  1892. X                  }
  1893. X               else
  1894. X                  {
  1895. X                  *end = atoi( tbuf );
  1896. X                  return TRUE;
  1897. X                  }
  1898. X               }
  1899. X            ++b;
  1900. X            n = 0;
  1901. X            break;
  1902. X         case '0':
  1903. X         case '1':
  1904. X         case '2':
  1905. X         case '3':
  1906. X         case '4':
  1907. X         case '5':
  1908. X         case '6':
  1909. X         case '7':
  1910. X         case '8':
  1911. X         case '9':
  1912. X            tbuf[ n ] = buffer[ b ];
  1913. X            ++n;
  1914. X            tbuf[ n ] = 0;
  1915. X            ++b;
  1916. X            break;
  1917. X         default:
  1918. X            #if PROG_ERRORS
  1919. X            sprintf( bwb_ebuf,
  1920. X               "ERROR: character <%c> unexpected in numerical sequence",
  1921. X               buffer[ b ] );
  1922. X            ++b;
  1923. X            bwb_error( bwb_ebuf );
  1924. X            #else
  1925. X            bwb_error( err_syntax );
  1926. X            #endif
  1927. X            break;
  1928. X         }
  1929. X      }
  1930. X
  1931. X   }
  1932. X
  1933. X/***************************************************************
  1934. X
  1935. X        FUNCTION:       bwb_freeline()
  1936. X
  1937. X        DESCRIPTION:
  1938. X
  1939. X***************************************************************/
  1940. X
  1941. Xint
  1942. Xbwb_freeline( struct bwb_line *l )
  1943. X   {
  1944. X   register int n;
  1945. X
  1946. X   /* free arguments if there are any */
  1947. X   
  1948. X   free( l );
  1949. X
  1950. X   return TRUE;
  1951. X   }
  1952. X   
  1953. X/***************************************************************
  1954. X
  1955. X        FUNCTION:       int_qmdstr()
  1956. X
  1957. X        DESCRIPTION:    This function .
  1958. X
  1959. X***************************************************************/
  1960. X
  1961. Xint
  1962. Xint_qmdstr( char *buffer_a, char *buffer_b )
  1963. X   {
  1964. X   char *a, *b;
  1965. X   
  1966. X   a = buffer_a;
  1967. X   ++a;                         /* advance beyond quotation mark */
  1968. X   b = buffer_b;
  1969. X
  1970. X   while( *a != '\"' )
  1971. X      {
  1972. X      *b = *a;
  1973. X      ++a;
  1974. X      ++b;
  1975. X      *b = '\0';
  1976. X      }
  1977. X
  1978. X   return TRUE;
  1979. X
  1980. X   }
  1981. X
  1982. X
  1983. X
  1984. X
  1985. X
  1986. X
  1987. X
  1988. END_OF_FILE
  1989.   if test 17458 -ne `wc -c <'bwb_int.c'`; then
  1990.     echo shar: \"'bwb_int.c'\" unpacked with wrong size!
  1991.   fi
  1992.   # end of 'bwb_int.c'
  1993. fi
  1994. echo shar: End of archive 7 \(of 11\).
  1995. cp /dev/null ark7isdone
  1996. MISSING=""
  1997. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  1998.     if test ! -f ark${I}isdone ; then
  1999.     MISSING="${MISSING} ${I}"
  2000.     fi
  2001. done
  2002. if test "${MISSING}" = "" ; then
  2003.     echo You have unpacked all 11 archives.
  2004.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2005. else
  2006.     echo You still must unpack the following archives:
  2007.     echo "        " ${MISSING}
  2008. fi
  2009. exit 0
  2010. exit 0 # Just in case...
  2011.