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

  1. Newsgroups: comp.sources.misc
  2. From: tcamp@delphi.com (Ted A. Campbell)
  3. Subject: v40i065:  bwbasic - Bywater BASIC interpreter version 2.10, Part14/15
  4. Message-ID: <1993Oct29.162825.4322@sparky.sterling.com>
  5. X-Md4-Signature: de848aeadf0f0b70d206017bdc16290d
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Fri, 29 Oct 1993 16:28:25 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: tcamp@delphi.com (Ted A. Campbell)
  12. Posting-number: Volume 40, Issue 65
  13. Archive-name: bwbasic/part14
  14. Environment: UNIX, DOS
  15. Supersedes: bwbasic: Volume 33, Issue 37-47
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  bwbasic-2.10/bwb_inp.c
  22. # Wrapped by kent@sparky on Thu Oct 21 10:47:52 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 14 (of 15)."'
  26. if test -f 'bwbasic-2.10/bwb_inp.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'bwbasic-2.10/bwb_inp.c'\"
  28. else
  29.   echo shar: Extracting \"'bwbasic-2.10/bwb_inp.c'\" \(34854 characters\)
  30.   sed "s/^X//" >'bwbasic-2.10/bwb_inp.c' <<'END_OF_FILE'
  31. X/***************************************************************
  32. X
  33. X        bwb_inp.c       Input Routines
  34. X                        for Bywater BASIC Interpreter
  35. X
  36. X                        Commands:       DATA
  37. X                                        READ
  38. X                                        RESTORE
  39. X                                        INPUT
  40. X                                        LINE INPUT
  41. X
  42. X                        Copyright (c) 1993, Ted A. Campbell
  43. X                        Bywater Software
  44. X
  45. X                        email: tcamp@delphi.com
  46. X
  47. X        Copyright and Permissions Information:
  48. X
  49. X        All U.S. and international rights are claimed by the author,
  50. X        Ted A. Campbell.
  51. X
  52. X    This software is released under the terms of the GNU General
  53. X    Public License (GPL), which is distributed with this software
  54. X    in the file "COPYING".  The GPL specifies the terms under
  55. X    which users may copy and use the software in this distribution.
  56. X
  57. X    A separate license is available for commercial distribution,
  58. X    for information on which you should contact the author.
  59. X
  60. X***************************************************************/
  61. X
  62. X#include <stdio.h>
  63. X#include <ctype.h>
  64. X#include <math.h>
  65. X
  66. X#include "bwbasic.h"
  67. X#include "bwb_mes.h"
  68. X
  69. X/* Declarations of functions visible to this file only */
  70. X
  71. X#if ANSI_C
  72. Xstatic struct bwb_line *bwb_xinp( struct bwb_line *l, FILE *f );
  73. Xstatic struct bwb_line *inp_str( struct bwb_line *l, char *buffer,
  74. X   char *var_list, int *position );
  75. Xstatic int inp_const( char *m_buffer, char *s_buffer, int *position );
  76. Xstatic int inp_assign( char *b, struct bwb_variable *v );
  77. Xstatic int inp_advws( FILE *f );
  78. Xstatic int inp_xgetc( FILE *f, int is_string );
  79. Xstatic int inp_eatcomma( FILE *f );
  80. X#else
  81. Xstatic struct bwb_line *bwb_xinp();
  82. Xstatic struct bwb_line *inp_str();
  83. Xstatic int inp_const();
  84. Xstatic int inp_assign();
  85. Xstatic int inp_advws();
  86. Xstatic int inp_xgetc();
  87. Xstatic int inp_eatcomma();
  88. X#endif
  89. X
  90. Xstatic char_saved = FALSE;
  91. Xstatic cs;
  92. X
  93. X/***************************************************************
  94. X
  95. X        FUNCTION:       bwb_read()
  96. X
  97. X        DESCRIPTION:    This function implements the BASIC READ
  98. X                        statement.
  99. X
  100. X        SYNTAX:         READ variable[, variable...]
  101. X
  102. X***************************************************************/
  103. X
  104. X#if ANSI_C
  105. Xstruct bwb_line *
  106. Xbwb_read( struct bwb_line *l )
  107. X#else
  108. Xstruct bwb_line *
  109. Xbwb_read( l )
  110. X   struct bwb_line *l;
  111. X#endif
  112. X   {
  113. X   int pos;
  114. X   register int n;
  115. X   int main_loop, adv_loop;
  116. X   struct bwb_variable *v;
  117. X   int n_params;                         /* number of parameters */
  118. X   int *pp;                              /* pointer to parameter values */
  119. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  120. X
  121. X#if INTENSIVE_DEBUG
  122. X   sprintf( bwb_ebuf, "in bwb_read(): buffer <%s>",
  123. X      &( l->buffer[ l->position ]));
  124. X   bwb_debug( bwb_ebuf );
  125. X#endif
  126. X
  127. X   /* Process each variable read from the READ statement */
  128. X
  129. X   main_loop = TRUE;
  130. X   while ( main_loop == TRUE )
  131. X      {
  132. X
  133. X      /* first check position in l->buffer and advance beyond whitespace */
  134. X
  135. X      adv_loop = TRUE;
  136. X      while( adv_loop == TRUE )
  137. X         {
  138. X
  139. X#if INTENSIVE_DEBUG
  140. X         sprintf( bwb_ebuf, "in bwb_read() adv_loop char <%d> = <%c>",
  141. X            l->buffer[ l->position ], l->buffer[ l->position ] );
  142. X         bwb_debug( bwb_ebuf );
  143. X#endif
  144. X
  145. X         switch ( l->buffer[ l->position ] )
  146. X            {
  147. X            case ',':                   /* comma delimiter */
  148. X            case ' ':                   /* whitespace */
  149. X            case '\t':
  150. X               ++l->position;
  151. X               break;
  152. X            case ':':                   /* end of line segment */
  153. X        case '\n':                  /* end of line */
  154. X            case '\r':
  155. X            case '\0':
  156. X               adv_loop = FALSE;        /* break out of advance loop */
  157. X               main_loop = FALSE;       /* break out of main loop */
  158. X               break;
  159. X            default:                    /* anything else */
  160. X               adv_loop = FALSE;        /* break out of advance loop */
  161. X               break;
  162. X            }
  163. X         }
  164. X
  165. X#if INTENSIVE_DEBUG
  166. X      sprintf( bwb_ebuf, "in bwb_read(): end of adv_loop <%d> main_loop <%d>",
  167. X         adv_loop, main_loop );
  168. X      bwb_debug( bwb_ebuf );
  169. X#endif
  170. X
  171. X      /* be sure main_loop id still valid after checking the line */
  172. X
  173. X      if ( main_loop == TRUE )
  174. X         {
  175. X
  176. X         /* Read a variable name */
  177. X
  178. X         bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  179. X         inp_adv( l->buffer, &( l->position ) );
  180. X         v = var_find( tbuf );
  181. X
  182. X#if INTENSIVE_DEBUG
  183. X     sprintf( bwb_ebuf, "in bwb_read(): line <%d> variable <%s>",
  184. X        l->number, v->name );
  185. X     bwb_debug( bwb_ebuf );
  186. X     sprintf( bwb_ebuf, "in bwb_read(): remaining line <%s>",
  187. X        &( l->buffer[ l->position ] ) );
  188. X     bwb_debug( bwb_ebuf );
  189. X#endif
  190. X
  191. X         /* advance beyond whitespace or comma in data buffer */
  192. X
  193. X         inp_adv( CURTASK data_line->buffer, &CURTASK data_pos );
  194. X
  195. X         /* Advance to next line if end of buffer */
  196. X
  197. X         switch( CURTASK data_line->buffer[ CURTASK data_pos ] )
  198. X            {
  199. X            case '\0':                     /* end of buffer */
  200. X            case '\n':
  201. X            case '\r':
  202. X
  203. X               CURTASK data_line = CURTASK data_line->next;
  204. X
  205. X               /* advance farther to line with DATA statement if necessary */
  206. X
  207. X               pos = 0;
  208. X               line_start( CURTASK data_line->buffer, &pos,
  209. X                  &( CURTASK data_line->lnpos ),
  210. X                  &( CURTASK data_line->lnum ),
  211. X                  &( CURTASK data_line->cmdpos ),
  212. X                  &( CURTASK data_line->cmdnum ),
  213. X                  &( CURTASK data_line->startpos ) );
  214. X               CURTASK data_pos = CURTASK data_line->startpos;
  215. X
  216. X#if INTENSIVE_DEBUG
  217. X               sprintf( bwb_ebuf, "in bwb_read(): current data line: <%s>",
  218. X                  CURTASK data_line->buffer );
  219. X               bwb_debug( bwb_ebuf );
  220. X#endif
  221. X
  222. X               break;
  223. X            }
  224. X
  225. X         while ( bwb_cmdtable[ CURTASK data_line->cmdnum ].vector != bwb_data )
  226. X            {
  227. X
  228. X            if ( CURTASK data_line == &CURTASK bwb_end )
  229. X               {
  230. X               CURTASK data_line = CURTASK bwb_start.next;
  231. X               }
  232. X
  233. X            else
  234. X               {
  235. X               CURTASK data_line = CURTASK data_line->next;
  236. X               }
  237. X
  238. X            pos = 0;
  239. X            line_start( CURTASK data_line->buffer, &pos,
  240. X               &( CURTASK data_line->lnpos ),
  241. X               &( CURTASK data_line->lnum ),
  242. X               &( CURTASK data_line->cmdpos ),
  243. X               &( CURTASK data_line->cmdnum ),
  244. X               &( CURTASK data_line->startpos ) );
  245. X            CURTASK data_pos = CURTASK data_line->startpos;
  246. X
  247. X#if INTENSIVE_DEBUG
  248. X            sprintf( bwb_ebuf, "in bwb_read(): advance to data line: <%s>",
  249. X               CURTASK data_line->buffer );
  250. X            bwb_debug( bwb_ebuf );
  251. X#endif
  252. X
  253. X            }
  254. X
  255. X         /* advance beyond whitespace in data buffer */
  256. X
  257. X         adv_loop = TRUE;
  258. X         while ( adv_loop == TRUE )
  259. X            {
  260. X            switch( CURTASK data_line->buffer[ CURTASK data_pos ] )
  261. X               {
  262. X               case '\0':                       /* end of buffer */
  263. X               case '\n':
  264. X               case '\r':
  265. X                  bwb_error( err_od );
  266. X                  return bwb_zline( l );
  267. X               case ' ':                        /* whitespace */
  268. X               case '\t':
  269. X                  ++CURTASK data_pos;
  270. X                  break;
  271. X               default:
  272. X                  adv_loop = FALSE;             /* carry on */
  273. X                  break;
  274. X               }
  275. X            }
  276. X
  277. X         /* now at last we have a variable in v that needs to be
  278. X            assigned data from the data_buffer at position CURTASK data_pos.
  279. X            What remains to be done is to get one single bit of data,
  280. X            a string constant or numerical constant, into the small
  281. X            buffer */
  282. X
  283. X         inp_const( CURTASK data_line->buffer, tbuf, &CURTASK data_pos );
  284. X
  285. X#if INTENSIVE_DEBUG
  286. X     sprintf( bwb_ebuf, "in bwb_read(): data constant is <%s>", tbuf );
  287. X     bwb_debug( bwb_ebuf );
  288. X#endif
  289. X
  290. X         /* get parameters if the variable is dimensioned */
  291. X
  292. X     adv_ws( l->buffer, &( l->position ) );
  293. X     if ( l->buffer[ l->position ] == '(' )
  294. X        {
  295. X#if INTENSIVE_DEBUG
  296. X        sprintf( bwb_ebuf, "in bwb_read(): variable <%s> is dimensioned",
  297. X           v->name );
  298. X        bwb_debug( bwb_ebuf );
  299. X#endif
  300. X            dim_getparams( l->buffer, &( l->position ), &n_params, &pp );
  301. X            for ( n = 0; n < v->dimensions; ++n )
  302. X               {
  303. X               v->array_pos[ n ] = pp[ n ];
  304. X               }
  305. X        }
  306. X#if INTENSIVE_DEBUG
  307. X     else
  308. X        {
  309. X        sprintf( bwb_ebuf, "in bwb_read(): variable <%s> is NOT dimensioned",
  310. X           v->name );
  311. X        bwb_debug( bwb_ebuf );
  312. X        sprintf( bwb_ebuf, "in bwb_read(): remaining line <%s>",
  313. X           &( l->buffer[ l->position ] ) );
  314. X        bwb_debug( bwb_ebuf );
  315. X        }
  316. X#endif
  317. X
  318. X         /* finally assign the data to the variable */
  319. X
  320. X         inp_assign( tbuf, v );
  321. X
  322. X         }                              /* end of remainder of main loop */
  323. X
  324. X      }                                 /* end of main_loop */
  325. X
  326. X#if INTENSIVE_DEBUG
  327. X   sprintf( bwb_ebuf, "in bwb_read(): exiting function, line <%s> ",
  328. X      &( l->buffer[ l->position ] ) );
  329. X   bwb_debug( bwb_ebuf );
  330. X#endif
  331. X
  332. X   return bwb_zline( l );
  333. X
  334. X   }
  335. X
  336. X/***************************************************************
  337. X
  338. X        FUNCTION:       bwb_data()
  339. X
  340. X        DESCRIPTION:    This function implements the BASIC DATA
  341. X                        statement, although at the point at which
  342. X                        DATA statements are encountered, no
  343. X                        processing is done.  All actual processing
  344. X                        of DATA statements is accomplished by READ
  345. X                        (bwb_read()).
  346. X
  347. X        SYNTAX:         DATA constant[, constant]...
  348. X
  349. X***************************************************************/
  350. X
  351. X#if ANSI_C
  352. Xstruct bwb_line *
  353. Xbwb_data( struct bwb_line *l )
  354. X#else
  355. Xstruct bwb_line *
  356. Xbwb_data( l )
  357. X   struct bwb_line *l;
  358. X#endif
  359. X   {
  360. X
  361. X#if MULTISEG_LINES
  362. X   adv_eos( l->buffer, &( l->position ));
  363. X#endif
  364. X
  365. X   return bwb_zline( l );
  366. X   }
  367. X
  368. X/***************************************************************
  369. X
  370. X        FUNCTION:       bwb_restore()
  371. X
  372. X        DESCRIPTION:    This function implements the BASIC RESTORE
  373. X                        statement.
  374. X
  375. X        SYNTAX:         RESTORE [line number]
  376. X
  377. X***************************************************************/
  378. X
  379. X#if ANSI_C
  380. Xstruct bwb_line *
  381. Xbwb_restore( struct bwb_line *l )
  382. X#else
  383. Xstruct bwb_line *
  384. Xbwb_restore( l )
  385. X   struct bwb_line *l;
  386. X#endif
  387. X   {
  388. X   struct bwb_line *r;
  389. X   struct bwb_line *r_line;
  390. X   int n;
  391. X   int pos;
  392. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  393. X
  394. X   /* get the first element beyond the starting position */
  395. X
  396. X   adv_element( l->buffer, &( l->position ), tbuf );
  397. X
  398. X   /* if the line is not a numerical constant, then there is no
  399. X      argument; set the current line to the first in the program */
  400. X
  401. X   if ( is_numconst( tbuf ) != TRUE )
  402. X      {
  403. X      CURTASK data_line = &CURTASK bwb_start;
  404. X      CURTASK data_pos = 0;
  405. X#if INTENSIVE_DEBUG
  406. X      sprintf( bwb_ebuf, "in bwb_restore(): RESTORE w/ no argument " );
  407. X      bwb_debug( bwb_ebuf );
  408. X#endif
  409. X      return bwb_zline( l );
  410. X      }
  411. X
  412. X   /* find the line */
  413. X
  414. X   n = atoi( tbuf );
  415. X
  416. X#if INTENSIVE_DEBUG
  417. X   sprintf( bwb_ebuf, "in bwb_restore(): line for restore is <%d>", n );
  418. X   bwb_debug( bwb_ebuf );
  419. X#endif
  420. X
  421. X   r_line = NULL;
  422. X   for ( r = CURTASK bwb_start.next; r != &CURTASK bwb_end; r = r->next )
  423. X      {
  424. X
  425. X      if ( r->number == n )
  426. X         {
  427. X         r_line = r;
  428. X         }
  429. X      }
  430. X
  431. X   if ( r_line == NULL )
  432. X      {
  433. X#if PROG_ERRORS
  434. X      sprintf( bwb_ebuf, "at line %d: Can't find line number for RESTORE.",
  435. X         l->number );
  436. X      bwb_error( bwb_ebuf );
  437. X#else
  438. X      sprintf( bwb_ebuf, err_lnnotfound, n );
  439. X      bwb_error( bwb_ebuf );
  440. X#endif
  441. X      return bwb_zline( l );
  442. X      }
  443. X
  444. X   /* initialize variables for the line */
  445. X
  446. X   pos = 0;
  447. X   line_start( r_line->buffer, &pos,
  448. X      &( r_line->lnpos ),
  449. X      &( r_line->lnum ),
  450. X      &( r_line->cmdpos ),
  451. X      &( r_line->cmdnum ),
  452. X      &( r_line->startpos ) );
  453. X
  454. X   /* verify that line is a data statement */
  455. X
  456. X   if ( bwb_cmdtable[ r_line->cmdnum ].vector != bwb_data )
  457. X      {
  458. X#if PROG_ERRORS
  459. X      sprintf( bwb_ebuf, "at line %d: Line %d is not a DATA statement.",
  460. X         l->number, r_line->number );
  461. X      bwb_error( bwb_ebuf );
  462. X#else
  463. X      bwb_error( err_syntax );
  464. X#endif
  465. X      return bwb_zline( l );
  466. X      }
  467. X
  468. X   /* reassign CURTASK data_line */
  469. X
  470. X   CURTASK data_line = r_line;
  471. X   CURTASK data_pos = CURTASK data_line->startpos;
  472. X
  473. X   return bwb_zline( l );
  474. X   }
  475. X
  476. X/***************************************************************
  477. X
  478. X        FUNCTION:       bwb_input()
  479. X
  480. X        DESCRIPTION:    This function implements the BASIC INPUT
  481. X                        statement.
  482. X
  483. X        SYNTAX:         INPUT [;][prompt$;]variable[$,variable]...
  484. X                        INPUT#n variable[$,variable]...
  485. X
  486. X***************************************************************/
  487. X
  488. X#if ANSI_C
  489. Xstruct bwb_line *
  490. Xbwb_input( struct bwb_line *l )
  491. X#else
  492. Xstruct bwb_line *
  493. Xbwb_input( l )
  494. X   struct bwb_line *l;
  495. X#endif
  496. X   {
  497. X   FILE *fp;
  498. X   int pos;
  499. X   int req_devnumber;
  500. X   struct exp_ese *v;
  501. X   int is_prompt;
  502. X   int suppress_qm;
  503. X   static char tbuf[ MAXSTRINGSIZE + 1 ];
  504. X   static char pstring[ MAXSTRINGSIZE + 1 ];
  505. X
  506. X#if INTENSIVE_DEBUG
  507. X   sprintf( bwb_ebuf, "in bwb_input(): enter function" );
  508. X   bwb_debug( bwb_ebuf );
  509. X#endif
  510. X
  511. X   pstring[ 0 ] = '\0';
  512. X
  513. X#if COMMON_CMDS
  514. X
  515. X   /* advance beyond whitespace and check for the '#' sign */
  516. X
  517. X   adv_ws( l->buffer, &( l->position ) );
  518. X
  519. X   if ( l->buffer[ l->position ] == '#' )
  520. X      {
  521. X      ++( l->position );
  522. X      adv_element( l->buffer, &( l->position ), tbuf );
  523. X      pos = 0;
  524. X      v = bwb_exp( tbuf, FALSE, &pos );
  525. X      adv_ws( l->buffer, &( l->position ) );
  526. X      if ( l->buffer[ l->position ] == ',' )
  527. X         {
  528. X         ++( l->position );
  529. X         }
  530. X      else
  531. X         {
  532. X#if PROG_ERRORS
  533. X         bwb_error( "in bwb_input(): no comma after#n" );
  534. X#else
  535. X         bwb_error( err_syntax );
  536. X#endif
  537. X         return bwb_zline( l );
  538. X         }
  539. X
  540. X      req_devnumber = (int) exp_getnval( v );
  541. X
  542. X#if INTENSIVE_DEBUG
  543. X      sprintf( bwb_ebuf, "in bwb_input(): requested device number <%d>",
  544. X         req_devnumber );
  545. X      bwb_debug( bwb_ebuf );
  546. X#endif
  547. X
  548. X      /* check the requested device number */
  549. X
  550. X      if ( ( req_devnumber < 0 ) || ( req_devnumber >= DEF_DEVICES ))
  551. X         {
  552. X#if PROG_ERRORS
  553. X         bwb_error( "in bwb_input(): Requested device number is out if range." );
  554. X#else
  555. X         bwb_error( err_devnum );
  556. X#endif
  557. X         return bwb_zline( l );
  558. X         }
  559. X
  560. X      if ( ( dev_table[ req_devnumber ].mode == DEVMODE_CLOSED ) ||
  561. X         ( dev_table[ req_devnumber ].mode == DEVMODE_AVAILABLE ) )
  562. X         {
  563. X#if PROG_ERRORS
  564. X         bwb_error( "in bwb_input(): Requested device number is not open." );
  565. X#else
  566. X         bwb_error( err_devnum );
  567. X#endif
  568. X
  569. X         return bwb_zline( l );
  570. X         }
  571. X
  572. X      if ( dev_table[ req_devnumber ].mode != DEVMODE_INPUT )
  573. X         {
  574. X#if PROG_ERRORS
  575. X         bwb_error( "in bwb_input(): Requested device is not open for INPUT." );
  576. X#else
  577. X         bwb_error( err_devnum );
  578. X#endif
  579. X
  580. X         return bwb_zline( l );
  581. X         }
  582. X
  583. X      /* look up the requested device in the device table */
  584. X
  585. X      fp = dev_table[ req_devnumber ].cfp;
  586. X
  587. X      }
  588. X   else
  589. X      {
  590. X      fp = stdin;
  591. X      }
  592. X
  593. X#else
  594. X   fp = stdin;
  595. X#endif                /* COMMON_CMDS */
  596. X
  597. X   /* if input is not from stdin, then branch to bwb_xinp() */
  598. X
  599. X   if ( fp != stdin )
  600. X      {
  601. X      return bwb_xinp( l, fp );
  602. X      }
  603. X
  604. X   /* from this point we presume that input is from stdin */
  605. X
  606. X   /* check for a semicolon or a quotation mark, not in
  607. X      first position: this should indicate a prompt string */
  608. X
  609. X   suppress_qm = is_prompt = FALSE;
  610. X
  611. X   adv_ws( l->buffer, &( l->position ) );
  612. X
  613. X   switch( l->buffer[ l->position ] )
  614. X      {
  615. X      case '\"':
  616. X         is_prompt = TRUE;
  617. X         break;
  618. X
  619. X      case ';':
  620. X
  621. X         /* AGENDA: add code to suppress newline if a
  622. X            semicolon is used here; this may not be possible
  623. X            using ANSI C alone, since it has not functions for
  624. X            unechoed console input. */
  625. X
  626. X         is_prompt = TRUE;
  627. X         ++l->position;
  628. X         break;
  629. X
  630. X      case ',':
  631. X
  632. X         /* QUERY: why is this code here? the question mark should
  633. X            be suppressed if a comma <follows> the prompt string. */
  634. X
  635. X#if INTENSIVE_DEBUG
  636. X         bwb_debug( "in bwb_input(): found initial comma" );
  637. X#endif
  638. X         suppress_qm = TRUE;
  639. X         ++l->position;
  640. X         break;
  641. X      }
  642. X
  643. X   /* get prompt string and print it */
  644. X
  645. X   if ( is_prompt == TRUE )
  646. X      {
  647. X
  648. X      /* get string element */
  649. X
  650. X      inp_const( l->buffer, tbuf, &( l->position ) );
  651. X
  652. X      /* advance past semicolon to beginning of variable */
  653. X
  654. X      suppress_qm = inp_adv( l->buffer, &( l->position ) );
  655. X
  656. X      /* print the prompt string */
  657. X
  658. X      strncpy( pstring, tbuf, MAXSTRINGSIZE );
  659. X      }                                      /* end condition: prompt string */
  660. X
  661. X   /* print out the question mark delimiter unless it has been
  662. X      suppressed */
  663. X
  664. X   if ( suppress_qm != TRUE )
  665. X      {
  666. X      strncat( pstring, "? ", MAXSTRINGSIZE );
  667. X      }
  668. X
  669. X#if INTENSIVE_DEBUG
  670. X   sprintf( bwb_ebuf, "in bwb_input(): ready to get input line" );
  671. X   bwb_debug( bwb_ebuf );
  672. X#endif
  673. X
  674. X   /* read a line into the input buffer */
  675. X
  676. X   bwx_input( pstring, tbuf );
  677. X   bwb_stripcr( tbuf );
  678. X
  679. X#if INTENSIVE_DEBUG
  680. X   sprintf( bwb_ebuf, "in bwb_input(): received line <%s>", tbuf );
  681. X   bwb_debug( bwb_ebuf );
  682. X   bwb_debug( "Press RETURN: " );
  683. X   getchar();
  684. X#endif
  685. X
  686. X   /* reset print column to account for LF at end of fgets() */
  687. X
  688. X   * prn_getcol( stdout ) = 1;
  689. X
  690. X   return inp_str( l, tbuf, l->buffer, &( l->position ) );
  691. X
  692. X   }
  693. X
  694. X/***************************************************************
  695. X
  696. X        FUNCTION:       bwb_xinp()
  697. X
  698. X        DESCRIPTION:    This function does the bulk of processing
  699. X                        for INPUT#, and so is file independent.
  700. X
  701. X***************************************************************/
  702. X
  703. X#if ANSI_C
  704. Xstatic struct bwb_line *
  705. Xbwb_xinp( struct bwb_line *l, FILE *f )
  706. X#else
  707. Xstatic struct bwb_line *
  708. Xbwb_xinp( l, f )
  709. X   struct bwb_line *l;
  710. X   FILE *f;
  711. X#endif
  712. X   {
  713. X   int loop;
  714. X   struct bwb_variable *v;
  715. X   char c;
  716. X   register int n;
  717. X   int *pp;
  718. X   int n_params;
  719. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  720. X
  721. X#if INTENSIVE_DEBUG
  722. X   sprintf( bwb_ebuf, "in bwb_xinp(): buffer <%s>",
  723. X      &( l->buffer[ l->position ] ) );
  724. X   bwb_debug( bwb_ebuf );
  725. X#endif
  726. X
  727. X   /* loop through elements required */
  728. X
  729. X   loop = TRUE;
  730. X   while ( loop == TRUE )
  731. X      {
  732. X      
  733. X      /* read a variable from the list */
  734. X
  735. X      bwb_getvarname( l->buffer, tbuf, &( l->position ) );
  736. X      v = var_find( tbuf );
  737. X
  738. X#if INTENSIVE_DEBUG
  739. X      sprintf( bwb_ebuf, "in bwb_xinp(): found variable name <%s>",
  740. X         v->name );
  741. X      bwb_debug( bwb_ebuf );
  742. X#endif
  743. X
  744. X      /* read subscripts */
  745. X
  746. X      adv_ws( l->buffer, &( l->position ) );
  747. X      if ( l->buffer[ l->position ] == '(' )
  748. X         {
  749. X#if INTENSIVE_DEBUG
  750. X         sprintf( bwb_ebuf, "in bwb_xinp(): variable <%s> has dimensions",
  751. X            v->name );
  752. X         bwb_debug( bwb_ebuf );
  753. X#endif
  754. X         dim_getparams( l->buffer, &( l->position ), &n_params, &pp );
  755. X         for ( n = 0; n < v->dimensions; ++n )
  756. X            {
  757. X            v->array_pos[ n ] = pp[ n ];
  758. X            }
  759. X         }
  760. X
  761. X      inp_advws( f );
  762. X
  763. X      /* perform type-specific input */
  764. X
  765. X      switch( v->type )
  766. X         {
  767. X         case STRING:
  768. X            if ( inp_xgetc( f, TRUE ) != '\"' )
  769. X               {
  770. X#if PROG_ERRORS
  771. X               sprintf( bwb_ebuf, "in bwb_xinp(): expected quotation mark" );
  772. X               bwb_error( bwb_ebuf );
  773. X#else
  774. X               bwb_error( err_mismatch );
  775. X#endif
  776. X               }
  777. X            n = 0;
  778. X            while ( ( c = (char) inp_xgetc( f, TRUE )) != '\"' )
  779. X               {
  780. X               tbuf[ n ] = c;
  781. X               ++n;
  782. X               tbuf[ n ] = '\0';
  783. X               }
  784. X            str_ctob( var_findsval( v, v->array_pos ), tbuf );
  785. X#if INTENSIVE_DEBUG
  786. X            sprintf( bwb_ebuf, "in bwb_xinp(): read STRING <%s>",
  787. X               tbuf );
  788. X            bwb_debug( bwb_ebuf );
  789. X#endif
  790. X            inp_eatcomma( f );
  791. X            break;
  792. X         default:
  793. X            n = 0;
  794. X            while ( ( c = (char) inp_xgetc( f, FALSE )) != ',' )
  795. X               {
  796. X               tbuf[ n ] = c;
  797. X               ++n;
  798. X               tbuf[ n ] = '\0';
  799. X               }
  800. X#if INTENSIVE_DEBUG
  801. X            sprintf( bwb_ebuf, "in bwb_xinp(): read NUMBER <%s>",
  802. X               tbuf );
  803. X            bwb_debug( bwb_ebuf );
  804. X#endif
  805. X            * var_findnval( v, v->array_pos ) = (bnumber) atof( tbuf );
  806. X            break;
  807. X         }                /* end of switch for type-specific input */
  808. X
  809. X      /* check for comma */
  810. X
  811. X      adv_ws( l->buffer, &( l->position ) );
  812. X      if ( l->buffer[ l->position ] == ',' )
  813. X         {
  814. X         ++( l->position );
  815. X         }
  816. X      else
  817. X         {
  818. X         loop = FALSE;
  819. X         }
  820. X
  821. X      }
  822. X
  823. X   /* return */
  824. X
  825. X   return bwb_zline( l );
  826. X
  827. X   }
  828. X
  829. X/***************************************************************
  830. X
  831. X        FUNCTION:       inp_advws()
  832. X
  833. X    DESCRIPTION:    This C function advances past whitespace
  834. X            inoput from a particular file or device.
  835. X
  836. X***************************************************************/
  837. X
  838. X#if ANSI_C
  839. Xstatic int
  840. Xinp_advws( FILE *f )
  841. X#else
  842. Xstatic int
  843. Xinp_advws( f )
  844. X   FILE *f;
  845. X#endif
  846. X   {
  847. X   register int c;
  848. X   int loop;
  849. X
  850. X   loop = TRUE;
  851. X   while ( loop == TRUE )
  852. X      {
  853. X      c = (char) inp_xgetc( f, TRUE );
  854. X
  855. X      switch( c )
  856. X         {
  857. X         case '\n':
  858. X         case '\r':
  859. X         case ' ':
  860. X         case '\t':
  861. X            break;
  862. X         default:
  863. X            char_saved = TRUE;
  864. X            cs = c;
  865. X            loop = FALSE;
  866. X            break;
  867. X         }
  868. X      }   
  869. X
  870. X   return TRUE;
  871. X   }
  872. X
  873. X/***************************************************************
  874. X
  875. X        FUNCTION:       inp_xgetc()
  876. X
  877. X    DESCRIPTION:    This C function reads in a character from
  878. X            a specified file or device.
  879. X
  880. X***************************************************************/
  881. X
  882. X#if ANSI_C
  883. Xstatic int
  884. Xinp_xgetc( FILE *f, int is_string )
  885. X#else
  886. Xstatic int
  887. Xinp_xgetc( f, is_string )
  888. X   FILE *f;
  889. X   int is_string;
  890. X#endif
  891. X   {
  892. X   register int c;
  893. X   static int prev_eof = FALSE;
  894. X
  895. X   if ( char_saved == TRUE )
  896. X      {
  897. X      char_saved = FALSE;
  898. X      return cs;
  899. X      }
  900. X
  901. X   if ( feof( f ) != 0 )
  902. X      {
  903. X      if ( prev_eof == TRUE )
  904. X         {
  905. X         bwb_error( err_od );
  906. X         }
  907. X      else
  908. X         {
  909. X     prev_eof = TRUE;
  910. X     return (int) ',';
  911. X     }
  912. X      }
  913. X
  914. X   prev_eof = FALSE;
  915. X
  916. X   c = fgetc( f );
  917. X
  918. X   if ( is_string == TRUE )
  919. X      {
  920. X      return c;
  921. X      }
  922. X      
  923. X   switch( c )
  924. X      {
  925. X      case ' ':
  926. X      case '\n':
  927. X      case ',':
  928. X      case '\r':
  929. X         return ',';
  930. X      }
  931. X
  932. X   return c;
  933. X
  934. X   }
  935. X
  936. X/***************************************************************
  937. X
  938. X        FUNCTION:       inp_eatcomma()
  939. X
  940. X    DESCRIPTION:    This C function advances beyond a comma
  941. X            input from a specified file or device.
  942. X
  943. X***************************************************************/
  944. X
  945. X#if ANSI_C
  946. Xstatic int
  947. Xinp_eatcomma( FILE *f )
  948. X#else
  949. Xstatic int
  950. Xinp_eatcomma( f )
  951. X   FILE *f;
  952. X#endif
  953. X   {
  954. X   char c;
  955. X
  956. X   while ( ( c = (char) inp_xgetc( f, TRUE ) ) == ',' )
  957. X      {
  958. X      }
  959. X      
  960. X   char_saved = TRUE;
  961. X   cs = c;
  962. X      
  963. X   return TRUE;
  964. X   }
  965. X
  966. X/***************************************************************
  967. X
  968. X        FUNCTION:       inp_str()
  969. X
  970. X        DESCRIPTION:    This function does INPUT processing
  971. X                        from a determined string of input
  972. X                        data and a determined variable list
  973. X                        (both in memory).  This presupposes
  974. X            that input has been taken from stdin,
  975. X            not from a disk file or device.
  976. X
  977. X***************************************************************/
  978. X
  979. X#if ANSI_C
  980. Xstatic struct bwb_line *
  981. Xinp_str( struct bwb_line *l, char *input_buffer, char *var_list, int *vl_position )
  982. X#else
  983. Xstatic struct bwb_line *
  984. Xinp_str( l, input_buffer, var_list, vl_position )
  985. X   struct bwb_line *l;
  986. X   char *input_buffer;
  987. X   char *var_list;
  988. X   int *vl_position;
  989. X#endif
  990. X   {
  991. X   int i;
  992. X   register int n;
  993. X   struct bwb_variable *v;
  994. X   int loop;
  995. X   int *pp;
  996. X   int n_params;
  997. X   char ttbuf[ MAXSTRINGSIZE + 1 ];        /* build element */
  998. X   char varname[ MAXSTRINGSIZE + 1 ];        /* build element */
  999. X
  1000. X#if INTENSIVE_DEBUG
  1001. X   sprintf( bwb_ebuf, "in inp_str(): received line <%s>",
  1002. X      l->buffer );
  1003. X   bwb_debug( bwb_ebuf );
  1004. X   sprintf( bwb_ebuf, "in inp_str(): received variable list <%s>.",
  1005. X      &( var_list[ *vl_position ] ) );
  1006. X   bwb_debug( bwb_ebuf );
  1007. X   sprintf( bwb_ebuf, "in inp_str(): received input buffer  <%s>.",
  1008. X      input_buffer );
  1009. X   bwb_debug( bwb_ebuf );
  1010. X#endif
  1011. X
  1012. X   /* Read elements, and assign them to variables */
  1013. X
  1014. X   i = 0;
  1015. X   loop = TRUE;
  1016. X   while ( loop == TRUE )
  1017. X      {
  1018. X
  1019. X      /* get a variable name from the list */
  1020. X
  1021. X      bwb_getvarname( var_list, varname, vl_position );    /* get name */
  1022. X      v = var_find( varname );
  1023. X
  1024. X#if INTENSIVE_DEBUG
  1025. X      sprintf( bwb_ebuf, "in inp_str(): found variable buffer <%s> name <%s>",
  1026. X         varname, v->name );
  1027. X      bwb_debug( bwb_ebuf );
  1028. X#endif
  1029. X
  1030. X      /* read subscripts if appropriate */
  1031. X
  1032. X      adv_ws( var_list, vl_position );
  1033. X      if ( var_list[ *vl_position ] == '(' )
  1034. X         {
  1035. X#if INTENSIVE_DEBUG
  1036. X     sprintf( bwb_ebuf, "in inp_str(): variable <%s> has dimensions",
  1037. X        v->name );
  1038. X     bwb_debug( bwb_ebuf );
  1039. X#endif
  1040. X         dim_getparams( var_list, vl_position, &n_params, &pp );
  1041. X         for ( n = 0; n < v->dimensions; ++n )
  1042. X            {
  1043. X            v->array_pos[ n ] = pp[ n ];
  1044. X            }
  1045. X         }
  1046. X
  1047. X      /* build string from input buffer in ttbuf */
  1048. X
  1049. X      n = 0;
  1050. X      ttbuf[ 0 ] = '\0';
  1051. X      while ( ( input_buffer[ i ] != ',' )
  1052. X         &&   ( input_buffer[ i ] != '\0' ))
  1053. X         {
  1054. X         ttbuf[ n ] = input_buffer[ i ];
  1055. X         ++n;
  1056. X         ++i;
  1057. X         ttbuf[ n ] = '\0';
  1058. X         }
  1059. X
  1060. X#if INTENSIVE_DEBUG
  1061. X      sprintf( bwb_ebuf, "in inp_str(): string for input <%s>",
  1062. X         ttbuf );
  1063. X      bwb_debug( bwb_ebuf );
  1064. X#endif
  1065. X
  1066. X      /* perform type-specific input */
  1067. X
  1068. X      inp_assign( ttbuf, v );
  1069. X
  1070. X      /* check for commas in variable list and input list and advance */
  1071. X
  1072. X      adv_ws( var_list, vl_position );
  1073. X      switch( var_list[ *vl_position ] )
  1074. X     {
  1075. X     case '\n':
  1076. X     case '\r':
  1077. X     case '\0':
  1078. X     case ':':
  1079. X        loop = FALSE;
  1080. X        break;
  1081. X     case ',':
  1082. X        ++( *vl_position );
  1083. X        break;
  1084. X         }
  1085. X      adv_ws( var_list, vl_position );
  1086. X
  1087. X      adv_ws( input_buffer, &i );
  1088. X      switch ( input_buffer[ i ] )
  1089. X     {
  1090. X     case '\n':
  1091. X     case '\r':
  1092. X     case '\0':
  1093. X     case ':':
  1094. X        loop = FALSE;
  1095. X        break;
  1096. X     case ',':
  1097. X        ++i;
  1098. X        break;
  1099. X     }
  1100. X      adv_ws( input_buffer, &i );
  1101. X
  1102. X      }
  1103. X
  1104. X#if INTENSIVE_DEBUG
  1105. X   sprintf( bwb_ebuf, "in inp_str(): exit, line buffer <%s>",
  1106. X      &( l->buffer[ l->position ] ) );
  1107. X   bwb_debug( bwb_ebuf );
  1108. X#endif
  1109. X
  1110. X   /* return */
  1111. X
  1112. X   return bwb_zline( l );
  1113. X
  1114. X   }
  1115. X
  1116. X/***************************************************************
  1117. X
  1118. X        FUNCTION:       inp_assign()
  1119. X
  1120. X        DESCRIPTION:    This function assigns the value of a
  1121. X                        numerical or string constant to a
  1122. X                        variable.
  1123. X
  1124. X
  1125. X***************************************************************/
  1126. X
  1127. X#if ANSI_C
  1128. Xstatic int
  1129. Xinp_assign( char *b, struct bwb_variable *v )
  1130. X#else
  1131. Xstatic int
  1132. Xinp_assign( b, v )
  1133. X   char *b;
  1134. X   struct bwb_variable *v;
  1135. X#endif
  1136. X   {
  1137. X
  1138. X   switch( v->type )
  1139. X      {
  1140. X      case STRING:
  1141. X         str_ctob( var_findsval( v, v->array_pos ), b );
  1142. X         break;
  1143. X
  1144. X      case NUMBER:
  1145. X         if ( strlen( b ) == 0 )
  1146. X            {
  1147. X            *( var_findnval( v, v->array_pos )) = (bnumber) 0.0;
  1148. X            }
  1149. X         else
  1150. X            {
  1151. X            *( var_findnval( v, v->array_pos )) = (bnumber) atof( b );
  1152. X            }
  1153. X         break;
  1154. X
  1155. X      default:
  1156. X#if PROG_ERRORS
  1157. X         sprintf( bwb_ebuf, "in inp_assign(): variable <%s> of unknown type",
  1158. X            v->name );
  1159. X         bwb_error( bwb_ebuf );
  1160. X#else
  1161. X         bwb_error( err_mismatch );
  1162. X#endif
  1163. X         return FALSE;
  1164. X
  1165. X      }
  1166. X
  1167. X   return FALSE;
  1168. X
  1169. X   }
  1170. X
  1171. X/***************************************************************
  1172. X
  1173. X        FUNCTION:       inp_adv()
  1174. X
  1175. X        DESCRIPTION:    This function advances the string pointer
  1176. X                        past whitespace and the item delimiter
  1177. X                        (comma).
  1178. X
  1179. X***************************************************************/
  1180. X
  1181. X#if ANSI_C
  1182. Xint
  1183. Xinp_adv( char *b, int *c )
  1184. X#else
  1185. Xint
  1186. Xinp_adv( b, c )
  1187. X   char *b;
  1188. X   int *c;
  1189. X#endif
  1190. X   {
  1191. X   int rval;
  1192. X
  1193. X   rval = FALSE;
  1194. X
  1195. X   while( TRUE )
  1196. X      {
  1197. X      switch( b[ *c ] )
  1198. X         {
  1199. X         case ' ':              /* whitespace */
  1200. X         case '\t':
  1201. X         case ';':              /* semicolon, end of prompt string */
  1202. X            ++*c;
  1203. X            break;
  1204. X         case ',':              /* comma, variable delimiter */
  1205. X            rval = TRUE;
  1206. X            ++*c;
  1207. X            break;
  1208. X         case '\0':        /* end of line */
  1209. X         case ':':         /* end of line segment */
  1210. X            rval = TRUE;
  1211. X            return rval;
  1212. X         default:
  1213. X            return rval;
  1214. X         }
  1215. X      }
  1216. X   }
  1217. X
  1218. X/***************************************************************
  1219. X
  1220. X        FUNCTION:       inp_const()
  1221. X
  1222. X        DESCRIPTION:    This function reads a numerical or string
  1223. X                        constant from <m_buffer> into <s_buffer>,
  1224. X                        incrementing <position> appropriately.
  1225. X
  1226. X***************************************************************/
  1227. X
  1228. X#if ANSI_C
  1229. Xstatic int
  1230. Xinp_const( char *m_buffer, char *s_buffer, int *position )
  1231. X#else
  1232. Xstatic int
  1233. Xinp_const( m_buffer, s_buffer, position )
  1234. X   char *m_buffer;
  1235. X   char *s_buffer;
  1236. X   int *position;
  1237. X#endif
  1238. X   {
  1239. X   int string;
  1240. X   int s_pos;
  1241. X   int loop;
  1242. X
  1243. X#if INTENSIVE_DEBUG
  1244. X   sprintf( bwb_ebuf, "in inp_const(): received argument <%s>.",
  1245. X      &( m_buffer[ *position ] ) );
  1246. X   bwb_debug( bwb_ebuf );
  1247. X#endif
  1248. X
  1249. X   string = FALSE;
  1250. X
  1251. X   /* first detect string constant */
  1252. X
  1253. X   if ( m_buffer[ *position ] == '\"' )
  1254. X      {
  1255. X      string = TRUE;
  1256. X      ++( *position );
  1257. X      }
  1258. X   else
  1259. X      {
  1260. X      string = FALSE;
  1261. X      }
  1262. X
  1263. X   /* build the constant string */
  1264. X
  1265. X   s_buffer[ 0 ] = '\0';
  1266. X   s_pos = 0;
  1267. X   loop = TRUE;
  1268. X
  1269. X   while ( loop == TRUE )
  1270. X      {
  1271. X
  1272. X      switch ( m_buffer[ *position ] )
  1273. X         {
  1274. X         case '\0':                     /* end of string */
  1275. X         case '\n':
  1276. X         case '\r':
  1277. X            return TRUE;
  1278. X         case ' ':                      /* whitespace */
  1279. X         case '\t':
  1280. X         case ',':                      /* or end of argument */
  1281. X            if ( string == FALSE )
  1282. X               {
  1283. X               return TRUE;
  1284. X               }
  1285. X            else
  1286. X               {
  1287. X               s_buffer[ s_pos ] = m_buffer[ *position ];
  1288. X               ++( *position );
  1289. X               ++s_buffer;
  1290. X               s_buffer[ s_pos ] = '\0';
  1291. X               }
  1292. X            break;
  1293. X         case '\"':
  1294. X            if ( string == TRUE )
  1295. X               {
  1296. X               ++( *position );                 /* advance beyond quotation mark */
  1297. X               inp_adv( m_buffer, position );
  1298. X               return TRUE;
  1299. X               }
  1300. X            else
  1301. X               {
  1302. X#if PROG_ERRORS
  1303. X               sprintf( bwb_ebuf, "Unexpected character in numerical constant." );
  1304. X               bwb_error( bwb_ebuf );
  1305. X#else
  1306. X               bwb_error( err_syntax );
  1307. X#endif
  1308. X               return FALSE;
  1309. X               }
  1310. X         default:
  1311. X            s_buffer[ s_pos ] = m_buffer[ *position ];
  1312. X            ++( *position );
  1313. X            ++s_buffer;
  1314. X            s_buffer[ s_pos ] = '\0';
  1315. X            break;
  1316. X         }
  1317. X
  1318. X      }
  1319. X
  1320. X   return FALSE;
  1321. X
  1322. X   }
  1323. X
  1324. X#if COMMON_CMDS
  1325. X
  1326. X/***************************************************************
  1327. X
  1328. X        FUNCTION:       bwb_line()
  1329. X
  1330. X        DESCRIPTION:    This function implements the BASIC LINE
  1331. X                        INPUT statement.
  1332. X
  1333. X    SYNTAX:         LINE INPUT [[#] device-number,]["prompt string";] string-variable$
  1334. X
  1335. X***************************************************************/
  1336. X
  1337. X#if ANSI_C
  1338. Xstruct bwb_line *
  1339. Xbwb_line( struct bwb_line *l )
  1340. X#else
  1341. Xstruct bwb_line *
  1342. Xbwb_line( l )
  1343. X   struct bwb_line *l;
  1344. X#endif
  1345. X   {
  1346. X   int dev_no;
  1347. X   struct bwb_variable *v;
  1348. X   FILE *inp_device;
  1349. X   char tbuf[ MAXSTRINGSIZE + 1 ];
  1350. X   char pstring[ MAXSTRINGSIZE + 1 ];
  1351. X
  1352. X   /* assign default values */
  1353. X
  1354. X   inp_device = stdin;
  1355. X
  1356. X   pstring[ 0 ] = '\0';
  1357. X
  1358. X   /* advance to first element (INPUT statement) */
  1359. X
  1360. X   adv_element( l->buffer, &( l->position ), tbuf );
  1361. X   bwb_strtoupper( tbuf );
  1362. X   if ( strcmp( tbuf, "INPUT" ) != 0 )
  1363. X      {
  1364. X      bwb_error( err_syntax );
  1365. X      return bwb_zline( l );
  1366. X      }
  1367. X   adv_ws( l->buffer, &( l->position ) );
  1368. X
  1369. X   /* check for semicolon in first position */
  1370. X
  1371. X   if ( l->buffer[ l->position ] == ';' )
  1372. X      {
  1373. X      ++l->position;
  1374. X      adv_ws( l->buffer, &( l->position ) );
  1375. X      }
  1376. X
  1377. X   /* else check for# for file number in first position */
  1378. X
  1379. X   else if ( l->buffer[ l->position ] == '#' )
  1380. X      {
  1381. X      ++l->position;
  1382. X      adv_element( l->buffer, &( l->position ), tbuf );
  1383. X      adv_ws( l->buffer, &( l->position ));
  1384. X      dev_no = atoi( tbuf );
  1385. X
  1386. X#if INTENSIVE_DEBUG
  1387. X      sprintf( bwb_ebuf, "in bwb_line(): file number requested <%d>", dev_no );
  1388. X      bwb_debug( bwb_ebuf );
  1389. X#endif
  1390. X
  1391. X      if ( dev_table[ dev_no ].cfp == NULL )
  1392. X         {
  1393. X         bwb_error( err_dev );
  1394. X         return bwb_zline( l );
  1395. X         }
  1396. X      else
  1397. X         {
  1398. X         inp_device = dev_table[ dev_no ].cfp;
  1399. X         }
  1400. X      }
  1401. X
  1402. X   /* check for comma */
  1403. X
  1404. X   if ( l->buffer[ l->position ] == ',' )
  1405. X      {
  1406. X      ++( l->position );
  1407. X      adv_ws( l->buffer, &( l->position ));
  1408. X      }
  1409. X
  1410. X   /* check for quotation mark indicating prompt */
  1411. X
  1412. X   if ( l->buffer[ l->position ] == '\"' )
  1413. X      {
  1414. X      inp_const( l->buffer, pstring, &( l->position ) );
  1415. X      }
  1416. X
  1417. X   /* read the variable for assignment */
  1418. X
  1419. X#if INTENSIVE_DEBUG
  1420. X   sprintf( bwb_ebuf, "in bwb_line(): tbuf <%s>", 
  1421. X      tbuf );
  1422. X   bwb_debug( bwb_ebuf );
  1423. X   sprintf( bwb_ebuf, "in bwb_line(): line buffer <%s>", 
  1424. X      &( l->buffer[ l->position ] ) );
  1425. X   bwb_debug( bwb_ebuf );
  1426. X#endif
  1427. X
  1428. X   adv_element( l->buffer, &( l->position ), tbuf );
  1429. X
  1430. X#if INTENSIVE_DEBUG
  1431. X   sprintf( bwb_ebuf, "in bwb_line(): variable buffer <%s>", tbuf );
  1432. X   bwb_debug( bwb_ebuf );
  1433. X#endif
  1434. X   v = var_find( tbuf );
  1435. X   if ( v->type != STRING )
  1436. X      {
  1437. X#if PROG_ERRORS
  1438. X      bwb_error( "in bwb_line(): String variable required" );
  1439. X#else
  1440. X      bwb_error( err_syntax );
  1441. X#endif
  1442. X      return bwb_zline( l );
  1443. X      }
  1444. X
  1445. X#if INTENSIVE_DEBUG
  1446. X   sprintf( bwb_ebuf, "in bwb_line(): variable for assignment <%s>", v->name );
  1447. X   bwb_debug( bwb_ebuf );
  1448. X#endif
  1449. X
  1450. X   /* read a line of text into the bufffer */
  1451. X
  1452. X   if ( inp_device == stdin )
  1453. X      {
  1454. X      bwx_input( pstring, tbuf );
  1455. X      }
  1456. X   else
  1457. X      {
  1458. X      fgets( tbuf, MAXSTRINGSIZE, inp_device );
  1459. X      }
  1460. X   bwb_stripcr( tbuf );
  1461. X   str_ctob( var_findsval( v, v->array_pos ), tbuf );
  1462. X
  1463. X   /* end: return next line */
  1464. X
  1465. X   return bwb_zline( l );
  1466. X   }
  1467. X
  1468. X#endif                /* COMMON_CMDS */
  1469. X
  1470. END_OF_FILE
  1471.   if test 34854 -ne `wc -c <'bwbasic-2.10/bwb_inp.c'`; then
  1472.     echo shar: \"'bwbasic-2.10/bwb_inp.c'\" unpacked with wrong size!
  1473.   fi
  1474.   # end of 'bwbasic-2.10/bwb_inp.c'
  1475. fi
  1476. echo shar: End of archive 14 \(of 15\).
  1477. cp /dev/null ark14isdone
  1478. MISSING=""
  1479. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1480.     if test ! -f ark${I}isdone ; then
  1481.     MISSING="${MISSING} ${I}"
  1482.     fi
  1483. done
  1484. if test "${MISSING}" = "" ; then
  1485.     echo You have unpacked all 15 archives.
  1486.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1487. else
  1488.     echo You still must unpack the following archives:
  1489.     echo "        " ${MISSING}
  1490. fi
  1491. exit 0
  1492. exit 0 # Just in case...
  1493.