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

  1. Newsgroups: comp.sources.misc
  2. From: tcamp@acpub.duke.edu (Ted A. Campbell)
  3. Subject:  v33i040:  bwbasic - Bywater BASIC interpreter version 1.10, Part04/11
  4. Message-ID: <1992Nov5.035311.15712@sparky.imd.sterling.com>
  5. X-Md4-Signature: 69e013f0dbe4e75aeb880d4336b6bdef
  6. Date: Thu, 5 Nov 1992 03:53:11 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 40
  11. Archive-name: bwbasic/part04
  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_dio.c bwb_str.c makefile.qcl
  19. # Wrapped by kent@sparky on Wed Nov  4 21:34:23 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 4 (of 11)."'
  23. if test -f 'bwb_dio.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'bwb_dio.c'\"
  25. else
  26.   echo shar: Extracting \"'bwb_dio.c'\" \(46285 characters\)
  27.   sed "s/^X//" >'bwb_dio.c' <<'END_OF_FILE'
  28. X/***************************************************************
  29. X
  30. X        bwb_dio.c       Device Input/Output Routines
  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 <sys/types.h>
  65. X#include <sys/stat.h>
  66. X
  67. X#include "bwbasic.h"
  68. X#include "bwb_mes.h"
  69. X
  70. X#if INTENSIVE_DEBUG
  71. X#define RANDOM_FILLCHAR        'X'
  72. X#else
  73. X#define RANDOM_FILLCHAR        ' '
  74. X#endif
  75. X
  76. Xstruct dev_element *dev_table;          /* table of devices */
  77. X
  78. Xstatic struct bwb_variable *v;
  79. Xstatic int pos;
  80. Xstatic int req_devnumber;
  81. Xstatic int rlen;
  82. Xstatic int mode;
  83. X
  84. Xstatic struct bwb_line *dio_lrset( struct bwb_line *l, int rset );
  85. Xstatic int dio_flush( int dev_number );
  86. X
  87. X/***************************************************************
  88. X
  89. X        FUNCTION:       bwb_open()
  90. X
  91. X        DESCRIPTION: This function implements the BASIC OPEN
  92. X        command to open a stream for device input/output.
  93. X
  94. X        SYNTAX: 1. OPEN "I"|"O"|"R", [#]n, filename [,rlen]
  95. X                2. OPEN filename [FOR INPUT|OUTPUT|APPEND|] AS [#]n [LEN=n]
  96. X***************************************************************/
  97. X
  98. Xstruct bwb_line *
  99. Xbwb_open( struct bwb_line *l )
  100. X   {
  101. X   FILE *fp;
  102. X   struct exp_ese *e;
  103. X   register int n;
  104. X   int previous_buffer;
  105. X   char atbuf[ MAXSTRINGSIZE + 1 ];
  106. X   char first[ MAXSTRINGSIZE + 1 ];
  107. X   char devname[ MAXSTRINGSIZE + 1 ];
  108. X
  109. X   /* initialize */
  110. X
  111. X   mode = req_devnumber = rlen = -1;
  112. X   previous_buffer = FALSE;
  113. X
  114. X   /* get the first expression element up to comma or whitespace */
  115. X
  116. X   adv_element( l->buffer, &( l->position ), atbuf );
  117. X
  118. X   /* parse the first expression element */
  119. X
  120. X   pos = 0;
  121. X   e = bwb_exp( atbuf, FALSE, &pos );
  122. X   str_btoc( first, exp_getsval( e ) );
  123. X
  124. X   #if INTENSIVE_DEBUG
  125. X   sprintf( bwb_ebuf, "in bwb_open(): first element is <%s>",
  126. X      first );
  127. X   bwb_debug( bwb_ebuf );
  128. X   #endif
  129. X
  130. X   /* test for syntactical form: if a comma follows the first element, 
  131. X      then the syntax is form 1 (the old CP/M BASIC format); otherwise we
  132. X      presume form 2 */
  133. X
  134. X   adv_ws( l->buffer, &( l->position ) );
  135. X
  136. X   /* Parse syntax Form 1 (OPEN "x", #n, devname...) */
  137. X
  138. X   if ( l->buffer[ l->position ] == ',' )
  139. X      {
  140. X
  141. X      /* parse the next element to get the device number */
  142. X
  143. X      ++( l->position );                        /* advance beyond comma */
  144. X      adv_ws( l->buffer, &( l->position ) );
  145. X      if ( l->buffer[ l->position ] == '#' )
  146. X         {
  147. X         ++( l->position );
  148. X         adv_ws( l->buffer, &( l->position ) );
  149. X         }
  150. X
  151. X      adv_element( l->buffer, &( l->position ), atbuf );
  152. X
  153. X      pos = 0;
  154. X      e = bwb_exp( atbuf, FALSE, &pos );
  155. X      if ( e->type == STRING )
  156. X         {
  157. X     #if PROG_ERRORS
  158. X     bwb_error( "String where integer was expected for device number" );
  159. X     #else
  160. X     bwb_error( err_syntax );
  161. X     #endif
  162. X         l->next->position = 0;
  163. X         return l->next;
  164. X         }
  165. X      req_devnumber = exp_getival( e );
  166. X
  167. X      #if INTENSIVE_DEBUG
  168. X      sprintf( bwb_ebuf, "in bwb_open(): syntax 1, req dev number is %d",
  169. X         req_devnumber );
  170. X      bwb_debug( bwb_ebuf );
  171. X      #endif
  172. X
  173. X      /* parse the next element to get the devname */
  174. X
  175. X      adv_ws( l->buffer, &( l->position ) );    /* advance past whitespace */
  176. X      ++( l->position );                        /* advance past comma */
  177. X      adv_element( l->buffer, &( l->position ), atbuf );
  178. X
  179. X      pos = 0;
  180. X      e = bwb_exp( atbuf, FALSE, &pos );
  181. X      if ( e->type != STRING )
  182. X         {
  183. X     #if PROG_ERRORS
  184. X     bwb_error( "in bwb_open(): number where string was expected for devname" );
  185. X     #else
  186. X     bwb_error( err_syntax );
  187. X         #endif
  188. X         l->next->position = 0;
  189. X         return l->next;
  190. X         }
  191. X      str_btoc( devname, exp_getsval( e ) );
  192. X
  193. X      #if INTENSIVE_DEBUG
  194. X      sprintf( bwb_ebuf, "in bwb_open(): syntax 1, devname <%s>",
  195. X         devname  );
  196. X      bwb_debug( bwb_ebuf );
  197. X      #endif
  198. X
  199. X      /* see if there is another element; if so, parse it to get the
  200. X         record length */
  201. X
  202. X      adv_ws( l->buffer, &( l->position ) );
  203. X      if ( l->buffer[ l->position ] == ',' )
  204. X         {
  205. X
  206. X         ++( l->position );                     /* advance beyond comma */
  207. X         adv_element( l->buffer, &( l->position ), atbuf );
  208. X
  209. X         pos = 0;
  210. X         e = bwb_exp( atbuf, FALSE, &pos );
  211. X         if ( e->type == STRING )
  212. X            {
  213. X        #if PROG_ERRORS
  214. X            bwb_error( "String where integer was expected for record length" );
  215. X            #else
  216. X            bwb_error( err_syntax );
  217. X            #endif
  218. X            l->next->position = 0;
  219. X            return l->next;
  220. X            }
  221. X         rlen = exp_getival( e );
  222. X
  223. X         #if INTENSIVE_DEBUG
  224. X         sprintf( bwb_ebuf, "in bwb_open(): syntax 1, record length is %d",
  225. X            rlen );
  226. X         bwb_debug( bwb_ebuf );
  227. X         #endif
  228. X
  229. X         }
  230. X
  231. X      /* the first letter of the first should indicate the
  232. X         type of file opening requested: test this letter,
  233. X         then parse accordingly */
  234. X
  235. X      /* open file for sequential INPUT */
  236. X
  237. X      if ( ( first[ 0 ] == 'i' ) || ( first[ 0 ] == 'I' ))
  238. X         {
  239. X         mode = DEVMODE_INPUT;
  240. X         }
  241. X
  242. X      /* open file for sequential OUTPUT */
  243. X
  244. X      else if ( ( first[ 0 ] == 'o' ) || ( first[ 0 ] == 'O' ))
  245. X         {
  246. X         mode = DEVMODE_OUTPUT;
  247. X         }
  248. X
  249. X      /* open file for RANDOM access input and output */
  250. X
  251. X      else if ( ( first[ 0 ] == 'r' ) || ( first[ 0 ] == 'R' ))
  252. X         {
  253. X         mode = DEVMODE_RANDOM;
  254. X         }
  255. X
  256. X      /* error: none of the appropriate modes found */
  257. X
  258. X      else
  259. X         {
  260. X     #if PROG_ERRORS
  261. X     sprintf( bwb_ebuf, "in bwb_open(): invalid mode" );
  262. X     bwb_error( bwb_ebuf );
  263. X     #else
  264. X     bwb_error( err_syntax );
  265. X     #endif
  266. X         }
  267. X
  268. X      #if INTENSIVE_DEBUG
  269. X      sprintf( bwb_ebuf, "in bwb_open(): syntax 1, mode is %d", mode );
  270. X      bwb_debug( bwb_ebuf );
  271. X      #endif
  272. X
  273. X      }
  274. X
  275. X   /* Parse syntax Form 2 (OPEN devname FOR mode AS #n ... ) */
  276. X
  277. X   else
  278. X      {
  279. X
  280. X      /* save the devname from first */
  281. X
  282. X      strcpy( devname, first );
  283. X
  284. X      #if INTENSIVE_DEBUG
  285. X      sprintf( bwb_ebuf, "in bwb_open(): syntax 2, devname <%s>",
  286. X         devname );
  287. X      bwb_debug( bwb_ebuf );
  288. X      #endif
  289. X
  290. X      /* get the next element */
  291. X
  292. X      adv_element( l->buffer, &( l->position ), atbuf );
  293. X
  294. X      /* check for "FOR mode" statement */
  295. X
  296. X      bwb_strtoupper( atbuf );
  297. X      if ( strcmp( atbuf, "FOR" ) == 0 )
  298. X         {
  299. X         adv_element( l->buffer, &( l->position ), atbuf );
  300. X         bwb_strtoupper( atbuf );
  301. X         if ( strcmp( atbuf, "INPUT" ) == 0 )
  302. X            {
  303. X            mode = DEVMODE_INPUT;
  304. X            }
  305. X         else if ( strcmp( atbuf, "OUTPUT" ) == 0 )
  306. X            {
  307. X            mode = DEVMODE_OUTPUT;
  308. X            }
  309. X         else if ( strcmp( atbuf, "APPEND" ) == 0 )
  310. X            {
  311. X            mode = DEVMODE_RANDOM;
  312. X            }
  313. X         else 
  314. X            {
  315. X        #if PROG_ERRORS
  316. X            bwb_error( "in bwb_open(): Invalid device i/o mode specified" );
  317. X            #else
  318. X            bwb_error( err_syntax );
  319. X            #endif
  320. X            l->next->position = 0;
  321. X            return l->next;
  322. X            }
  323. X
  324. X         /* get the next element */
  325. X
  326. X         adv_element( l->buffer, &( l->position ), atbuf );
  327. X
  328. X         }
  329. X      else
  330. X         {
  331. X         mode = DEVMODE_RANDOM;
  332. X         }
  333. X
  334. X      #if INTENSIVE_DEBUG
  335. X      sprintf( bwb_ebuf, "in bwb_open(): syntax 2, mode is %d", mode );
  336. X      bwb_debug( bwb_ebuf );
  337. X      #endif
  338. X
  339. X      /* This leaves us with the next element in the atbuf: it
  340. X         should read "AS" */
  341. X
  342. X      bwb_strtoupper( atbuf );
  343. X      if ( strcmp( atbuf, "AS" ) != 0 )
  344. X         {
  345. X     #if PROG_ERRORS
  346. X         bwb_error( "in bwb_open(): expected AS statement" );
  347. X         #else
  348. X         bwb_error( err_syntax );
  349. X         #endif
  350. X         l->next->position = 0;
  351. X         return l->next;
  352. X         }
  353. X
  354. X      /* get the next element */
  355. X
  356. X      adv_ws( l->buffer, &( l->position ) );
  357. X
  358. X      if ( l->buffer[ l->position ] == '#' )
  359. X         {
  360. X         ++( l->position );
  361. X         }
  362. X
  363. X      adv_element( l->buffer, &( l->position ), atbuf );
  364. X
  365. X      #if INTENSIVE_DEBUG
  366. X      sprintf( bwb_ebuf, "in bwb_open(): string to parse for req dev number <%s>",
  367. X         atbuf );
  368. X      bwb_debug( bwb_ebuf );
  369. X      #endif
  370. X
  371. X      pos = 0;
  372. X      e = bwb_exp( atbuf, FALSE, &pos );
  373. X      if ( e->type == STRING )
  374. X         {
  375. X     #if PROG_ERRORS
  376. X         bwb_error( "String where integer was expected for record length" );
  377. X         #else
  378. X         bwb_error( err_syntax );
  379. X         #endif
  380. X         l->next->position = 0;
  381. X         return l->next;
  382. X         }
  383. X      req_devnumber = exp_getival( e );
  384. X
  385. X      #if INTENSIVE_DEBUG
  386. X      sprintf( bwb_ebuf, "in bwb_open(): syntax 2, req dev number is %d",
  387. X         req_devnumber );
  388. X      bwb_debug( bwb_ebuf );
  389. X      #endif
  390. X
  391. X      /* Check for LEN = n statement */
  392. X
  393. X      adv_element( l->buffer, &( l->position ), atbuf );
  394. X      bwb_strtoupper( atbuf );
  395. X      if ( strncmp( atbuf, "LEN", (size_t) 3 ) == 0 )
  396. X         {
  397. X
  398. X         pos = l->position - strlen( atbuf );
  399. X         while( ( l->buffer[ pos ] != '=' ) && ( l->buffer[ pos ] != '\0' ))
  400. X            {
  401. X            ++pos;
  402. X            }
  403. X         if ( l->buffer[ pos ] == '\0' )
  404. X            {
  405. X        #if PROG_ERRORS
  406. X            bwb_error( "Failed to find equals sign after LEN element" );
  407. X            #else
  408. X            bwb_error( err_syntax );
  409. X            #endif
  410. X            l->next->position = 0;
  411. X            return l->next;
  412. X            }
  413. X         ++pos;         /* advance past equal sign */
  414. X
  415. X         e = bwb_exp( l->buffer, FALSE, &pos );
  416. X
  417. X         if ( e->type == STRING )
  418. X            {
  419. X        #if PROG_ERRORS
  420. X            bwb_error( "String where integer was expected for record length" );
  421. X            #else
  422. X            bwb_error( err_syntax );
  423. X            #endif
  424. X            l->next->position = 0;
  425. X            return l->next;
  426. X            }
  427. X         rlen = exp_getival( e );
  428. X
  429. X         #if INTENSIVE_DEBUG
  430. X         sprintf( bwb_ebuf, "in bwb_open(): syntax 2, record length is %d",
  431. X            rlen );
  432. X         bwb_debug( bwb_ebuf );
  433. X         #endif
  434. X
  435. X         }
  436. X
  437. X      }                                 /* end of syntax 2 */
  438. X
  439. X   /* check for valid requested device number */
  440. X
  441. X   if ( ( req_devnumber < 0 ) || ( req_devnumber >= DEF_DEVICES ))
  442. X      {
  443. X      #if PROG_ERRORS
  444. X      bwb_error( "in bwb_open(): Requested device number is out of range." );
  445. X      #else
  446. X      bwb_error( err_devnum );
  447. X      #endif
  448. X      l->next->position = 0;
  449. X      return l->next;
  450. X      }
  451. X
  452. X   if ( dev_table[ req_devnumber ].mode == DEVMODE_CLOSED )
  453. X      {
  454. X      #if INTENSIVE_DEBUG
  455. X      sprintf( bwb_ebuf, "in bwb_open(): using previously closed file (and buffer)" );
  456. X      bwb_debug( bwb_ebuf );
  457. X      #endif
  458. X      previous_buffer = TRUE;
  459. X      }
  460. X
  461. X   if ( ( dev_table[ req_devnumber ].mode != DEVMODE_CLOSED ) &&
  462. X      ( dev_table[ req_devnumber ].mode != DEVMODE_AVAILABLE ) )
  463. X      {
  464. X      #if PROG_ERRORS
  465. X      bwb_error( "in bwb_open(): Requested device number is already in use." );
  466. X      #else
  467. X      bwb_error( err_devnum );
  468. X      #endif
  469. X
  470. X      l->next->position = 0;
  471. X      return l->next;
  472. X      }
  473. X
  474. X   #if INTENSIVE_DEBUG
  475. X   sprintf( bwb_ebuf, "in bwb_open(): ready to open device <%s> mode <%d>",
  476. X      devname, mode );
  477. X   bwb_debug( bwb_ebuf );
  478. X   #endif
  479. X
  480. X   /* attempt to open the file */
  481. X
  482. X   switch( mode )
  483. X      {
  484. X      case DEVMODE_OUTPUT:
  485. X         fp = fopen( devname, "w" );
  486. X         break;
  487. X      case DEVMODE_INPUT:
  488. X         fp = fopen( devname, "r" );
  489. X         break;
  490. X      case DEVMODE_APPEND:
  491. X         fp = fopen( devname, "a" );
  492. X         break;
  493. X      case DEVMODE_RANDOM:
  494. X         fp = fopen( devname, "r+" );
  495. X         if ( fp == NULL )
  496. X            {
  497. X            fp = fopen( devname, "w" );
  498. X            fclose( fp );
  499. X            fp = fopen( devname, "r+" );
  500. X            }
  501. X         break;
  502. X      }
  503. X
  504. X   /* check for valid file opening */
  505. X
  506. X   if ( fp == NULL )
  507. X      {
  508. X      #if PROG_ERRORS
  509. X      sprintf( bwb_ebuf, "Failed to open device <%s>", devname );
  510. X      bwb_error( bwb_ebuf );
  511. X      #else
  512. X      bwb_error( err_dev );
  513. X      #endif
  514. X      l->next->position = 0;
  515. X      return l->next;
  516. X      }
  517. X
  518. X   /* assign values to device table */
  519. X
  520. X   dev_table[ req_devnumber ].mode = mode;
  521. X   dev_table[ req_devnumber ].cfp = fp;
  522. X   dev_table[ req_devnumber ].reclen = rlen;
  523. X   dev_table[ req_devnumber ].next_record = 1;
  524. X   dev_table[ req_devnumber ].loc = 0;
  525. X   strcpy( dev_table[ req_devnumber ].filename, devname );
  526. X
  527. X   /* allocate a character buffer for random access */
  528. X
  529. X   if (( mode == DEVMODE_RANDOM ) && ( previous_buffer != TRUE ))
  530. X      {
  531. X      if ( ( dev_table[ req_devnumber ].buffer = calloc( rlen + 1, 1 )) == NULL )
  532. X         {
  533. X         bwb_error( err_getmem );
  534. X         return l;
  535. X         }
  536. X
  537. X      dio_flush( req_devnumber );
  538. X
  539. X      #if INTENSIVE_DEBUG
  540. X      sprintf( bwb_ebuf, "in bwb_open(): allocated new random-access buffer" );
  541. X      bwb_debug( bwb_ebuf );
  542. X      #endif
  543. X
  544. X      }
  545. X
  546. X   #if INTENSIVE_DEBUG
  547. X   sprintf( bwb_ebuf, "in bwb_open(): file is open now; end of function" );
  548. X   bwb_debug( bwb_ebuf );
  549. X   #endif
  550. X
  551. X   /* return next line number in sequence */
  552. X
  553. X   l->next->position = 0;
  554. X   return l->next;
  555. X   }
  556. X
  557. X/***************************************************************
  558. X
  559. X        FUNCTION:       bwb_close()
  560. X
  561. X        DESCRIPTION: This function implements the BASIC CLOSE
  562. X        command to close a stream for device input/output.
  563. X  
  564. X        SYNTAX:         CLOSE [#]n [,[#]n...]
  565. X
  566. X***************************************************************/
  567. X
  568. Xstruct bwb_line *
  569. Xbwb_close( struct bwb_line *l )
  570. X   {
  571. X   struct exp_ese *e;
  572. X   char atbuf[ MAXSTRINGSIZE + 1 ];
  573. X
  574. X   /* loop to get device numbers to close */
  575. X
  576. X   do
  577. X      {
  578. X
  579. X      adv_ws( l->buffer, &( l->position ) );
  580. X      if ( l->buffer[ l->position ] =='#' )
  581. X         {
  582. X         ++( l->position );
  583. X         }
  584. X
  585. X      adv_element( l->buffer, &( l->position ), atbuf );
  586. X
  587. X      pos = 0;
  588. X      e = bwb_exp( atbuf, FALSE, &pos );
  589. X
  590. X      if ( e->type == STRING )
  591. X         {
  592. X     #if PROG_ERRORS
  593. X         bwb_error( "String where integer was expected for device number" );
  594. X         #else
  595. X         bwb_error( err_syntax );
  596. X         #endif
  597. X         l->next->position = 0;
  598. X         return l->next;
  599. X         }
  600. X
  601. X      req_devnumber = exp_getival( e );
  602. X
  603. X      #if INTENSIVE_DEBUG
  604. X      sprintf( bwb_ebuf, "in bwb_close(): requested device number <%d>",
  605. X         req_devnumber );
  606. X      bwb_debug( bwb_ebuf );
  607. X      #endif
  608. X
  609. X      /* check for valid requested device number */
  610. X
  611. X      if ( ( req_devnumber < 0 ) || ( req_devnumber >= DEF_DEVICES ))
  612. X         {
  613. X     #if PROG_ERRORS
  614. X         bwb_error( "in bwb_close(): Requested device number is out if range." );
  615. X         #else
  616. X         bwb_error( err_devnum );
  617. X         #endif
  618. X         l->next->position = 0;
  619. X         return l->next;
  620. X         }
  621. X
  622. X      if (( dev_table[ req_devnumber ].mode == DEVMODE_CLOSED ) ||
  623. X         ( dev_table[ req_devnumber ].mode == DEVMODE_AVAILABLE ) )
  624. X         {
  625. X     #if PROG_ERRORS
  626. X         bwb_error( "in bwb_close(): Requested device number is not in use." );
  627. X         #else
  628. X         bwb_error( err_devnum );
  629. X         #endif
  630. X
  631. X         l->next->position = 0;
  632. X         return l->next;
  633. X         }
  634. X
  635. X      #if INTENSIVE_DEBUG
  636. X      sprintf( bwb_ebuf, "in bwb_close(): closing device # <%d>",
  637. X     req_devnumber );
  638. X      bwb_debug( bwb_ebuf );
  639. X      #endif
  640. X
  641. X      /* attempt to close the file */
  642. X
  643. X      if ( fclose( dev_table[ req_devnumber ].cfp ) != 0 )
  644. X         {
  645. X     #if PROG_ERRORS
  646. X         bwb_error( "in bwb_close(): Failed to close the device" );
  647. X         #else
  648. X         bwb_error( err_dev );
  649. X         #endif
  650. X         l->next->position = 0;
  651. X         return l->next;
  652. X         }
  653. X
  654. X      /* mark the device in the table as unavailable */
  655. X
  656. X      dev_table[ req_devnumber ].mode = DEVMODE_CLOSED;
  657. X
  658. X      /* eat up any remaining whitespace */
  659. X
  660. X      adv_ws( l->buffer, &( l->position ) );
  661. X
  662. X      }
  663. X
  664. X   while ( l->buffer[ l->position ] == ',' );
  665. X
  666. X   /* return next line number in sequence */
  667. X
  668. X   l->next->position = 0;
  669. X   return l->next;
  670. X   }
  671. X
  672. X/***************************************************************
  673. X
  674. X        FUNCTION:       bwb_chdir()
  675. X
  676. X        DESCRIPTION: This function implements the BASIC CHDIR
  677. X        command to switch logged directories.
  678. X
  679. X        SYNTAX: CHDIR pathname$
  680. X***************************************************************/
  681. X
  682. X#if DIRECTORY_CMDS
  683. Xstruct bwb_line *
  684. Xbwb_chdir( struct bwb_line *l )
  685. X   {
  686. X   int r;
  687. X   static int position;
  688. X   struct exp_ese *e;
  689. X   static char *atbuf;
  690. X   static int init = FALSE;
  691. X
  692. X   /* get memory for temporary buffers if necessary */
  693. X
  694. X   if ( init == FALSE )
  695. X      {
  696. X      init = TRUE;
  697. X      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  698. X         {
  699. X         bwb_error( err_getmem );
  700. X         }
  701. X      }
  702. X
  703. X   /* get the next element in atbuf */
  704. X
  705. X   adv_element( l->buffer, &( l->position ), atbuf  );
  706. X
  707. X   #if INTENSIVE_DEBUG
  708. X   sprintf( bwb_ebuf, "in bwb_chdir(): argument is <%s>", atbuf );
  709. X   bwb_debug( bwb_ebuf );
  710. X   #endif
  711. X
  712. X   /* interpret the argument */
  713. X
  714. X   position = 0;
  715. X   e = bwb_exp( atbuf, FALSE, &position );
  716. X
  717. X   if ( e->type != STRING )
  718. X      {
  719. X      bwb_error( err_argstr );
  720. X      l->next->position = 0;
  721. X      return l->next;
  722. X      }
  723. X
  724. X   /* try to chdir to the requested directory */
  725. X
  726. X   str_btoc( atbuf, &( e->sval ) );
  727. X   r = chdir( atbuf );
  728. X
  729. X   /* detect error */
  730. X
  731. X   if ( r == -1 )
  732. X      {
  733. X      bwb_error( err_opsys );
  734. X      l->next->position = 0;
  735. X      return l->next;
  736. X      }
  737. X
  738. X   l->next->position = 0;
  739. X   return l->next;
  740. X
  741. X   }
  742. X
  743. X/***************************************************************
  744. X
  745. X        FUNCTION:       bwb_rmdir()
  746. X
  747. X        DESCRIPTION: This function implements the BASIC CHDIR
  748. X        command to remove a subdirectory.
  749. X
  750. X        SYNTAX: RMDIR pathname$
  751. X***************************************************************/
  752. X
  753. Xstruct bwb_line *
  754. Xbwb_rmdir( struct bwb_line *l )
  755. X   {
  756. X   int r;
  757. X   static int position;
  758. X   struct exp_ese *e;
  759. X   static char *atbuf;
  760. X   static int init = FALSE;
  761. X
  762. X   /* get memory for temporary buffers if necessary */
  763. X
  764. X   if ( init == FALSE )
  765. X      {
  766. X      init = TRUE;
  767. X      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  768. X         {
  769. X         bwb_error( err_getmem );
  770. X         }
  771. X      }
  772. X
  773. X   /* get the next element in atbuf */
  774. X
  775. X   adv_element( l->buffer, &( l->position ), atbuf  );
  776. X
  777. X   #if INTENSIVE_DEBUG
  778. X   sprintf( bwb_ebuf, "in bwb_rmdir(): argument is <%s>", atbuf );
  779. X   bwb_debug( bwb_ebuf );
  780. X   #endif
  781. X
  782. X   /* interpret the argument */
  783. X
  784. X   position = 0;
  785. X   e = bwb_exp( atbuf, FALSE, &position );
  786. X
  787. X   if ( e->type != STRING )
  788. X      {
  789. X      bwb_error( err_argstr );
  790. X      l->next->position = 0;
  791. X      return l->next;
  792. X      }
  793. X
  794. X   /* try to remove the requested directory */
  795. X
  796. X   str_btoc( atbuf, &( e->sval ) );
  797. X   r = rmdir( atbuf );
  798. X
  799. X   /* detect error */
  800. X
  801. X   if ( r == -1 )
  802. X      {
  803. X      bwb_error( err_opsys );
  804. X      }
  805. X
  806. X   l->next->position = 0;
  807. X   return l->next;
  808. X
  809. X   }
  810. X
  811. X/***************************************************************
  812. X
  813. X        FUNCTION:       bwb_mkdir()
  814. X
  815. X        DESCRIPTION: This function implements the BASIC MKDIR
  816. X        command to create a new subdirectory.
  817. X
  818. X        SYNTAX: MKDIR pathname$
  819. X
  820. X***************************************************************/
  821. X
  822. Xstruct bwb_line *
  823. Xbwb_mkdir( struct bwb_line *l )
  824. X   {
  825. X   int r;
  826. X   static int position;
  827. X   struct exp_ese *e;
  828. X   static char *atbuf;
  829. X   static int init = FALSE;
  830. X
  831. X   /* get memory for temporary buffers if necessary */
  832. X
  833. X   if ( init == FALSE )
  834. X      {
  835. X      init = TRUE;
  836. X      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  837. X         {
  838. X         bwb_error( err_getmem );
  839. X         }
  840. X      }
  841. X
  842. X   /* get the next element in atbuf */
  843. X
  844. X   adv_element( l->buffer, &( l->position ), atbuf  );
  845. X
  846. X   #if INTENSIVE_DEBUG
  847. X   sprintf( bwb_ebuf, "in bwb_mkdir(): argument is <%s>", atbuf );
  848. X   bwb_debug( bwb_ebuf );
  849. X   #endif
  850. X
  851. X   /* interpret the argument */
  852. X
  853. X   position = 0;
  854. X   e = bwb_exp( atbuf, FALSE, &position );
  855. X
  856. X   if ( e->type != STRING )
  857. X      {
  858. X      bwb_error( err_argstr );
  859. X      l->next->position = 0;
  860. X      return l->next;
  861. X      }
  862. X
  863. X   /* try to make the requested directory */
  864. X
  865. X   str_btoc( atbuf, &( e->sval ) );
  866. X   r = mkdir( atbuf );
  867. X
  868. X   /* detect error */
  869. X
  870. X   if ( r == -1 )
  871. X      {
  872. X      bwb_error( err_opsys );
  873. X      }
  874. X
  875. X   l->next->position = 0;
  876. X   return l->next;
  877. X
  878. X   }
  879. X
  880. X#endif                /* DIRECTORY_CMDS */
  881. X
  882. X/***************************************************************
  883. X
  884. X        FUNCTION:       bwb_kill()
  885. X
  886. X        DESCRIPTION: This function implements the BASIC KILL
  887. X        command to erase a disk file.
  888. X
  889. X        SYNTAX: KILL btbuf$
  890. X***************************************************************/
  891. X
  892. Xstruct bwb_line *
  893. Xbwb_kill( struct bwb_line *l )
  894. X   {
  895. X   int r;
  896. X   static int position;
  897. X   struct exp_ese *e;
  898. X   static char *atbuf;
  899. X   static int init = FALSE;
  900. X
  901. X   /* get memory for temporary buffers if necessary */
  902. X
  903. X   if ( init == FALSE )
  904. X      {
  905. X      init = TRUE;
  906. X      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  907. X         {
  908. X         bwb_error( err_getmem );
  909. X         }
  910. X      }
  911. X
  912. X   /* get the next element in atbuf */
  913. X
  914. X   adv_element( l->buffer, &( l->position ), atbuf  );
  915. X
  916. X   #if INTENSIVE_DEBUG
  917. X   sprintf( bwb_ebuf, "in bwb_kill(): argument is <%s>", atbuf );
  918. X   bwb_debug( bwb_ebuf );
  919. X   #endif
  920. X
  921. X   /* interpret the argument */
  922. X
  923. X   position = 0;
  924. X  e = bwb_exp( atbuf, FALSE, &position );
  925. X
  926. X   if ( e->type != STRING )
  927. X      {
  928. X      bwb_error( err_argstr );
  929. X      l->next->position = 0;
  930. X      return l->next;
  931. X      }
  932. X
  933. X   /* try to delete the specified file */
  934. X
  935. X   str_btoc( atbuf, &( e->sval ) );
  936. X   r = unlink( atbuf );
  937. X
  938. X   /* detect error */
  939. X
  940. X   if ( r == -1 )
  941. X      {
  942. X      bwb_error( err_opsys );
  943. X      }
  944. X
  945. X   l->next->position = 0;
  946. X   return l->next;
  947. X
  948. X   }
  949. X
  950. X/***************************************************************
  951. X
  952. X        FUNCTION:       bwb_name()
  953. X
  954. X        DESCRIPTION: This function implements the BASIC NAME
  955. X        command to rename a disk file.
  956. X
  957. X        SYNTAX: NAME old_btbuf$ AS new_btbuf$
  958. X***************************************************************/
  959. X
  960. Xstruct bwb_line *
  961. Xbwb_name( struct bwb_line *l )
  962. X   {
  963. X   int r;
  964. X   static int position;
  965. X   struct exp_ese *e;
  966. X   static char *atbuf;
  967. X   static char *btbuf;
  968. X   static int init = FALSE;
  969. X
  970. X   /* get memory for temporary buffers if necessary */
  971. X
  972. X   if ( init == FALSE )
  973. X      {
  974. X      init = TRUE;
  975. X      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  976. X         {
  977. X         bwb_error( err_getmem );
  978. X         }
  979. X      if ( ( btbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
  980. X         {
  981. X         bwb_error( err_getmem );
  982. X         }
  983. X      }
  984. X
  985. X   /* get the first argument in atbuf */
  986. X
  987. X   adv_element( l->buffer, &( l->position ), atbuf  );
  988. X
  989. X   /* interpret the first argument */
  990. X
  991. X   position = 0;
  992. X   e = bwb_exp( atbuf, FALSE, &position );
  993. X
  994. X   if ( e->type != STRING )
  995. X      {
  996. X      bwb_error( err_argstr );
  997. X      l->next->position = 0;
  998. X      return l->next;
  999. X      }
  1000. X
  1001. X   /* this argument must be copied back to atbuf, else the next
  1002. X      call to bwb_exp() will overwrite the structure to which e
  1003. X      refers */
  1004. X
  1005. X   str_btoc( atbuf, &( e->sval ) );
  1006. X
  1007. X   #if INTENSIVE_DEBUG
  1008. X   sprintf( bwb_ebuf, "in bwb_name(): old name is <%s>", atbuf );
  1009. X   bwb_debug( bwb_ebuf );
  1010. X   #endif
  1011. X
  1012. X   /* get the second argument in btbuf */
  1013. X
  1014. X   adv_element( l->buffer, &( l->position ), btbuf  );
  1015. X   bwb_strtoupper( btbuf );
  1016. X
  1017. X   #if INTENSIVE_DEBUG
  1018. X   sprintf( bwb_ebuf, "in bwb_name(): AS string is <%s>", btbuf );
  1019. X   bwb_debug( bwb_ebuf );
  1020. X   #endif
  1021. X
  1022. X   if ( strcmp( btbuf, "AS" ) != 0 )
  1023. X      {
  1024. X      bwb_error( err_syntax );
  1025. X      l->next->position = 0;
  1026. X      return l->next;
  1027. X      }
  1028. X
  1029. X   /* get the third argument in btbuf */
  1030. X
  1031. X   adv_element( l->buffer, &( l->position ), btbuf  );
  1032. X
  1033. X   /* interpret the third argument */
  1034. X
  1035. X   position = 0;
  1036. X   e = bwb_exp( btbuf, FALSE, &position );
  1037. X
  1038. X   if ( e->type != STRING )
  1039. X      {
  1040. X      bwb_error( err_argstr );
  1041. X      l->next->position = 0;
  1042. X      return l->next;
  1043. X      }
  1044. X
  1045. X   str_btoc( btbuf, &( e->sval ) );
  1046. X
  1047. X   #if INTENSIVE_DEBUG
  1048. X   sprintf( bwb_ebuf, "in bwb_name(): new name is <%s>", btbuf );
  1049. X   bwb_debug( bwb_ebuf );
  1050. X   #endif
  1051. X
  1052. X   /* try to rename the file */
  1053. X
  1054. X   r = rename( atbuf, btbuf );
  1055. X
  1056. X   /* detect error */
  1057. X
  1058. X   if ( r != 0 )
  1059. X      {
  1060. X      bwb_error( err_opsys );
  1061. X      }
  1062. X
  1063. X   l->next->position = 0;
  1064. X   return l->next;
  1065. X
  1066. X   }
  1067. X
  1068. X/***************************************************************
  1069. X
  1070. X        FUNCTION:       bwb_field()
  1071. X
  1072. X        DESCRIPTION:    This C function implements the BASIC
  1073. X            FIELD command.
  1074. X
  1075. X***************************************************************/
  1076. X
  1077. Xstruct bwb_line *
  1078. Xbwb_field( struct bwb_line *l )
  1079. X   {
  1080. X   int dev_number;
  1081. X   int length;
  1082. X   struct exp_ese *e;
  1083. X   struct bwb_variable *v;
  1084. X   bstring *b;
  1085. X   int current_pos;
  1086. X   char atbuf[ MAXSTRINGSIZE + 1 ];
  1087. X   char btbuf[ MAXSTRINGSIZE + 1 ];
  1088. X
  1089. X   current_pos = 0;
  1090. X
  1091. X   /* first read device number */
  1092. X
  1093. X   adv_ws( l->buffer, &( l->position ) );
  1094. X   if ( l->buffer[ l->position ] =='#' )
  1095. X      {
  1096. X      ++( l->position );
  1097. X      }
  1098. X
  1099. X   adv_element( l->buffer, &( l->position ), atbuf );
  1100. X
  1101. X   #if INTENSIVE_DEBUG
  1102. X   sprintf( bwb_ebuf, "in bwb_field(): device # buffer <%s>", atbuf );
  1103. X   bwb_debug( bwb_ebuf );
  1104. X   #endif
  1105. X
  1106. X   pos = 0;
  1107. X   e = bwb_exp( atbuf, FALSE, &pos );
  1108. X
  1109. X   if ( e->type != INTEGER )
  1110. X      {
  1111. X      #if PROG_ERRORS
  1112. X      bwb_error( "in bwb_field(): Integer was expected for device number" );
  1113. X      #else
  1114. X      bwb_error( err_syntax );
  1115. X      #endif
  1116. X      return l;
  1117. X      }
  1118. X
  1119. X   dev_number = exp_getival( e );
  1120. X
  1121. X   #if INTENSIVE_DEBUG
  1122. X   sprintf( bwb_ebuf, "in bwb_field(): device <%d>", dev_number );
  1123. X   bwb_debug( bwb_ebuf );
  1124. X   #endif
  1125. X
  1126. X   /* be sure that the requested device is open */
  1127. X
  1128. X   if (( dev_table[ dev_number ].mode == DEVMODE_CLOSED ) ||
  1129. X      ( dev_table[ req_devnumber ].mode == DEVMODE_AVAILABLE ) )
  1130. X      {
  1131. X      #if PROG_ERRORS
  1132. X      bwb_error( "in bwb_field(): Requested device number is not in use." );
  1133. X      #else
  1134. X      bwb_error( err_devnum );
  1135. X      #endif
  1136. X      return l;
  1137. X      }
  1138. X
  1139. X   /* loop to read variables */
  1140. X
  1141. X   do
  1142. X      {
  1143. X
  1144. X      /* read the comma and advance beyond it */
  1145. X
  1146. X      adv_ws( l->buffer, &( l->position ) );
  1147. X      if ( l->buffer[ l->position ] ==',' )
  1148. X         {
  1149. X         ++( l->position );
  1150. X         }
  1151. X
  1152. X      /* first find the size of the field */
  1153. X
  1154. X      adv_element( l->buffer, &( l->position ), atbuf );    /* get element */
  1155. X
  1156. X      pos = 0;
  1157. X      e = bwb_exp( atbuf, FALSE, &pos );
  1158. X
  1159. X      if ( e->type != INTEGER )
  1160. X         {
  1161. X     #if PROG_ERRORS
  1162. X         bwb_error( "in bwb_field(): integer value for field size not found" );
  1163. X         #else
  1164. X         bwb_error( err_syntax );
  1165. X         #endif
  1166. X         return l;
  1167. X         }
  1168. X
  1169. X      length = exp_getival( e );
  1170. X
  1171. X      #if INTENSIVE_DEBUG
  1172. X      sprintf( bwb_ebuf, "in bwb_field(): device <%d> length <%d> buf <%s>",
  1173. X         dev_number, length, &( l->buffer[ l->position ] ) );
  1174. X      bwb_debug( bwb_ebuf );
  1175. X      #endif
  1176. X
  1177. X      /* read the AS */
  1178. X
  1179. X      adv_element( l->buffer, &( l->position ), atbuf );    /* get element */
  1180. X      bwb_strtoupper( atbuf );
  1181. X
  1182. X      #if INTENSIVE_DEBUG
  1183. X      sprintf( bwb_ebuf, "in bwb_field(): AS element <%s>", atbuf );
  1184. X      bwb_debug( bwb_ebuf );
  1185. X      #endif
  1186. X
  1187. X      if ( strncmp( atbuf, "AS", 2 ) != 0 )
  1188. X         {
  1189. X     #if PROG_ERRORS
  1190. X         bwb_error( "in bwb_field(): AS statement not found" );
  1191. X         #else
  1192. X         bwb_error( err_syntax );
  1193. X         #endif
  1194. X         return l;
  1195. X         }
  1196. X
  1197. X      /* read the string variable name */
  1198. X
  1199. X      adv_element( l->buffer, &( l->position ), atbuf );    /* get element */
  1200. X      v = var_find( atbuf );
  1201. X
  1202. X      if ( v->type != STRING )
  1203. X         {
  1204. X     #if PROG_ERRORS
  1205. X         bwb_error( "in bwb_field(): string variable name not found" );
  1206. X         #else
  1207. X         bwb_error( err_syntax );
  1208. X         #endif
  1209. X         return l;
  1210. X         }
  1211. X
  1212. X      #if INTENSIVE_DEBUG
  1213. X      sprintf( bwb_ebuf, "in bwb_field(): device <%d> var <%s> length <%d>",
  1214. X         dev_number, v->name, length );
  1215. X      bwb_debug( bwb_ebuf );
  1216. X      #endif
  1217. X
  1218. X      /* check for overflow of record length */
  1219. X
  1220. X      if ( ( current_pos + length ) > dev_table[ dev_number ].reclen )
  1221. X         {
  1222. X     #if PROG_ERRORS
  1223. X         bwb_error( "in bwb_field(): record length exceeded" );
  1224. X         #else
  1225. X         bwb_error( err_overflow );
  1226. X         #endif
  1227. X         return l;
  1228. X         }
  1229. X
  1230. X      /* set buffer */
  1231. X
  1232. X      b = var_findsval( v, v->array_pos );
  1233. X      if ( b->buffer != NULL )
  1234. X         {
  1235. X         free( b->buffer );
  1236. X         }
  1237. X      b->buffer = dev_table[ dev_number ].buffer + current_pos;
  1238. X      b->length = (unsigned char) length;
  1239. X      b->rab = TRUE;
  1240. X
  1241. X      current_pos += length;
  1242. X
  1243. X      #if INTENSIVE_DEBUG
  1244. X      sprintf( bwb_ebuf, "in bwb_field(): buffer <%lXh> var <%s> buffer <%lXh>",
  1245. X         (long) dev_table[ dev_number ].buffer, v->name, (long) b->buffer );
  1246. X      bwb_debug( bwb_ebuf );
  1247. X      #endif
  1248. X
  1249. X      /* eat up any remaining whitespace */
  1250. X
  1251. X      adv_ws( l->buffer, &( l->position ) );
  1252. X
  1253. X      }
  1254. X
  1255. X   while ( l->buffer[ l->position ] == ',' );
  1256. X
  1257. X   /* return */
  1258. X
  1259. X   return l;
  1260. X
  1261. X   }
  1262. X
  1263. X/***************************************************************
  1264. X
  1265. X        FUNCTION:       bwb_lset()
  1266. X
  1267. X        DESCRIPTION:    This C function implements the BASIC
  1268. X            LSET command.
  1269. X
  1270. X***************************************************************/
  1271. X
  1272. Xstruct bwb_line *
  1273. Xbwb_lset( struct bwb_line *l )
  1274. X   {
  1275. X   return dio_lrset( l, FALSE );
  1276. X   }
  1277. X   
  1278. X/***************************************************************
  1279. X
  1280. X        FUNCTION:       bwb_rset()
  1281. X
  1282. X        DESCRIPTION:    This C function implements the BASIC
  1283. X            RSET command.
  1284. X
  1285. X***************************************************************/
  1286. X
  1287. Xstruct bwb_line *
  1288. Xbwb_rset( struct bwb_line *l )
  1289. X   {
  1290. X   return dio_lrset( l, TRUE );
  1291. X   }
  1292. X
  1293. X/***************************************************************
  1294. X
  1295. X        FUNCTION:       dio_lrset()
  1296. X
  1297. X        DESCRIPTION:    This C function implements the BASIC
  1298. X            RSET and LSET commands.
  1299. X
  1300. X***************************************************************/
  1301. X
  1302. Xstruct bwb_line *
  1303. Xdio_lrset( struct bwb_line *l, int rset )
  1304. X   {
  1305. X   char varname[ MAXVARNAMESIZE + 1 ];
  1306. X   bstring *d, *s;
  1307. X   int *pp;
  1308. X   int n_params;
  1309. X   int p;
  1310. X   register int n, i;
  1311. X   int startpos;
  1312. X   struct exp_ese *e;
  1313. X
  1314. X   /* find the variable name */
  1315. X
  1316. X   bwb_getvarname( l->buffer, varname, &( l->position ));
  1317. X
  1318. X   v = var_find( varname );
  1319. X
  1320. X   if ( v == NULL )
  1321. X      {
  1322. X      #if PROG_ERRORS
  1323. X      sprintf( bwb_ebuf, "in dio_lrset(): failed to find variable" );
  1324. X      bwb_error( bwb_ebuf );
  1325. X      #else
  1326. X      bwb_error( err_syntax );
  1327. X      #endif
  1328. X      }
  1329. X
  1330. X   if ( v->type != STRING )
  1331. X      {
  1332. X      #if PROG_ERRORS
  1333. X      sprintf( bwb_ebuf, "in dio_lrset(): assignment must be to string variable" );
  1334. X      bwb_error( bwb_ebuf );
  1335. X      #else
  1336. X      bwb_error( err_syntax );
  1337. X      #endif
  1338. X      }
  1339. X
  1340. X   /* read subscripts */
  1341. X
  1342. X   pos = 0;
  1343. X   if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
  1344. X      {
  1345. X      #if INTENSIVE_DEBUG
  1346. X      sprintf( bwb_ebuf, "in dio_lrset(): variable <%s> has 1 dimension",
  1347. X         v->name );
  1348. X      bwb_debug( bwb_ebuf );
  1349. X      #endif
  1350. X      n_params = 1;
  1351. X      pp = &p;
  1352. X      pp[ 0 ] = dim_base;
  1353. X      }
  1354. X   else
  1355. X      {
  1356. X      #if INTENSIVE_DEBUG
  1357. X      sprintf( bwb_ebuf, "in dio_lrset(): variable <%s> has > 1 dimensions",
  1358. X         v->name );
  1359. X      bwb_debug( bwb_ebuf );
  1360. X      #endif
  1361. X      dim_getparams( l->buffer, &( l->position ), &n_params, &pp );
  1362. X      }
  1363. X
  1364. X   exp_es[ exp_esc ].pos_adv = pos;
  1365. X   for ( n = 0; n < v->dimensions; ++n )
  1366. X      {
  1367. X      v->array_pos[ n ] = pp[ n ];
  1368. X      }
  1369. X
  1370. X   /* get bstring pointer */
  1371. X
  1372. X   d = var_findsval( v, pp );
  1373. X
  1374. X   /* find equals sign */
  1375. X
  1376. X   adv_ws( l->buffer, &( l->position ));
  1377. X   if ( l->buffer[ l->position ] != '=' )
  1378. X      {
  1379. X      #if PROG_ERRORS
  1380. X      sprintf( bwb_ebuf, "in dio_lrset(): failed to find equal sign" );
  1381. X      bwb_error( bwb_ebuf );
  1382. X      #else
  1383. X      bwb_error( err_syntax );
  1384. X      #endif
  1385. X      }
  1386. X   ++( l->position );
  1387. X   adv_ws( l->buffer, &( l->position ));
  1388. X
  1389. X   /* read remainder of line to get value */
  1390. X
  1391. X   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  1392. X   s = exp_getsval( e );
  1393. X
  1394. X   /* set starting position */
  1395. X
  1396. X   startpos = 0;
  1397. X   if ( rset == TRUE )
  1398. X      {
  1399. X      if ( s->length < d->length )
  1400. X         {
  1401. X         startpos = d->length - s->length;
  1402. X         }
  1403. X      }
  1404. X
  1405. X   #if INTENSIVE_DEBUG
  1406. X   sprintf( bwb_ebuf, "in dio_lrset(): startpos <%d> buffer <%lX>", 
  1407. X      startpos, (long) d->buffer );
  1408. X   bwb_debug( bwb_ebuf );
  1409. X   #endif
  1410. X
  1411. X   /* write characters to new position */
  1412. X
  1413. X   i = 0;
  1414. X   for ( n = startpos; ( i < s->length ) && ( n < d->length ); ++n )
  1415. X      {
  1416. X      d->buffer[ n ] = s->buffer[ i ];
  1417. X      ++i;
  1418. X      }
  1419. X
  1420. X   /* return */
  1421. X
  1422. X   return l;
  1423. X
  1424. X   }
  1425. X
  1426. X/***************************************************************
  1427. X
  1428. X        FUNCTION:       bwb_get()
  1429. X
  1430. X        DESCRIPTION:    This C function implements the BASIC
  1431. X            GET command.
  1432. X
  1433. X***************************************************************/
  1434. X
  1435. Xstruct bwb_line *
  1436. Xbwb_get( struct bwb_line *l )
  1437. X   {
  1438. X   int dev_number;
  1439. X   int rec_number;
  1440. X   register int i;
  1441. X   struct exp_ese *e;
  1442. X   char atbuf[ MAXSTRINGSIZE + 1 ];
  1443. X   char btbuf[ MAXSTRINGSIZE + 1 ];
  1444. X
  1445. X   /* first read device number */
  1446. X
  1447. X   adv_ws( l->buffer, &( l->position ) );
  1448. X   if ( l->buffer[ l->position ] =='#' )
  1449. X      {
  1450. X      ++( l->position );
  1451. X      }
  1452. X
  1453. X   adv_element( l->buffer, &( l->position ), atbuf );
  1454. X
  1455. X   pos = 0;
  1456. X   e = bwb_exp( atbuf, FALSE, &pos );
  1457. X
  1458. X   if ( e->type != INTEGER )
  1459. X      {
  1460. X      #if PROG_ERRORS
  1461. X      bwb_error( "in bwb_get(): Integer was expected for device number" );
  1462. X      #else
  1463. X      bwb_error( err_syntax );
  1464. X      #endif
  1465. X      return l;
  1466. X      }
  1467. X
  1468. X   dev_number = exp_getival( e );
  1469. X
  1470. X   #if INTENSIVE_DEBUG
  1471. X   sprintf( bwb_ebuf, "in bwb_get(): device <%d>", dev_number );
  1472. X   bwb_debug( bwb_ebuf );
  1473. X   #endif
  1474. X
  1475. X   /* be sure that the requested device is open */
  1476. X
  1477. X   if ( ( dev_table[ dev_number ].mode == DEVMODE_CLOSED ) ||
  1478. X      ( dev_table[ req_devnumber ].mode == DEVMODE_AVAILABLE ) )
  1479. X      {
  1480. X      #if PROG_ERRORS
  1481. X      bwb_error( "in bwb_get(): Requested device number is not in use." );
  1482. X      #else
  1483. X      bwb_error( err_devnum );
  1484. X      #endif
  1485. X      return l;
  1486. X      }
  1487. X
  1488. X   /* see if there is a comma (and record number) */
  1489. X
  1490. X   adv_ws( l->buffer, &( l->position ) );
  1491. X   if ( l->buffer[ l->position ] == ',' )    /* yes, there is a comma */
  1492. X      {
  1493. X      ++( l->position );
  1494. X
  1495. X      /* get the record number element */
  1496. X
  1497. X      adv_element( l->buffer, &( l->position ), atbuf );
  1498. X
  1499. X      pos = 0;
  1500. X      e = bwb_exp( atbuf, FALSE, &pos );
  1501. X      rec_number = exp_getival( e );
  1502. X
  1503. X      }
  1504. X
  1505. X   else                /* no record number given */
  1506. X      {
  1507. X      rec_number = dev_table[ dev_number ].next_record;
  1508. X      }
  1509. X
  1510. X   #if INTENSIVE_DEBUG
  1511. X   sprintf( bwb_ebuf, "in bwb_get(): record number <%d>", rec_number );
  1512. X   bwb_debug( bwb_ebuf );
  1513. X   #endif
  1514. X
  1515. X   /* wind the c file up to the proper point */
  1516. X
  1517. X   if ( fseek( dev_table[ dev_number ].cfp,
  1518. X      (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen ), 
  1519. X      SEEK_SET ) != 0 )
  1520. X      {
  1521. X      #if PROG_ERRORS
  1522. X      sprintf( bwb_ebuf, "in bwb_get(): fseek() failed, rec number <%d> offset <%ld>",
  1523. X        rec_number, (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen ) );
  1524. X      bwb_error( bwb_ebuf );
  1525. X      #else
  1526. X      bwb_error( err_dev );
  1527. X      #endif
  1528. X      return l;
  1529. X      }
  1530. X
  1531. X   /* read the requested bytes into the buffer */
  1532. X
  1533. X   for ( i = 0; i < dev_table[ dev_number ].reclen; ++i )
  1534. X      {
  1535. X      dev_table[ dev_number ].buffer[ i ] =
  1536. X         (char) fgetc( dev_table[ dev_number ].cfp );
  1537. X      ++( dev_table[ dev_number ].loc );
  1538. X      }
  1539. X
  1540. X   /* increment (or reset) the current record */
  1541. X
  1542. X   dev_table[ dev_number ].next_record = rec_number + 1;
  1543. X
  1544. X   return l;
  1545. X
  1546. X   }
  1547. X
  1548. X/***************************************************************
  1549. X
  1550. X        FUNCTION:       bwb_put()
  1551. X
  1552. X        DESCRIPTION:    This C function implements the BASIC
  1553. X            PUT command.
  1554. X
  1555. X***************************************************************/
  1556. X
  1557. Xstruct bwb_line *
  1558. Xbwb_put( struct bwb_line *l )
  1559. X   {
  1560. X   int dev_number;
  1561. X   int rec_number;
  1562. X   register int i;
  1563. X   struct exp_ese *e;
  1564. X   struct bwb_variable *v;
  1565. X   char atbuf[ MAXSTRINGSIZE + 1 ];
  1566. X   char btbuf[ MAXSTRINGSIZE + 1 ];
  1567. X
  1568. X   /* first read device number */
  1569. X
  1570. X   adv_ws( l->buffer, &( l->position ) );
  1571. X   if ( l->buffer[ l->position ] =='#' )
  1572. X      {
  1573. X      ++( l->position );
  1574. X      }
  1575. X
  1576. X   adv_element( l->buffer, &( l->position ), atbuf );
  1577. X   dev_number = atoi( atbuf );
  1578. X
  1579. X   #if INTENSIVE_DEBUG
  1580. X   sprintf( bwb_ebuf, "in bwb_put(): device <%d>", dev_number );
  1581. X   bwb_debug( bwb_ebuf );
  1582. X   #endif
  1583. X
  1584. X   /* be sure that the requested device is open */
  1585. X
  1586. X   if ( ( dev_table[ dev_number ].mode == DEVMODE_CLOSED ) ||
  1587. X      ( dev_table[ req_devnumber ].mode == DEVMODE_AVAILABLE ) )
  1588. X      {
  1589. X      #if PROG_ERRORS
  1590. X      bwb_error( "in bwb_put(): Requested device number is not in use." );
  1591. X      #else
  1592. X      bwb_error( err_devnum );
  1593. X      #endif
  1594. X      return l;
  1595. X      }
  1596. X
  1597. X   /* see if there is a comma (and record number) */
  1598. X
  1599. X   adv_ws( l->buffer, &( l->position ) );
  1600. X   if ( l->buffer[ l->position ] == ',' )    /* yes, there is a comma */
  1601. X      {
  1602. X      ++( l->position );
  1603. X
  1604. X      /* get the record number element */
  1605. X
  1606. X      adv_element( l->buffer, &( l->position ), atbuf );
  1607. X
  1608. X      #if INTENSIVE_DEBUG
  1609. X      sprintf( bwb_ebuf, "in bwb_put(): rec no buffer <%s>", atbuf );
  1610. X      bwb_debug( bwb_ebuf );
  1611. X      #endif
  1612. X
  1613. X      pos = 0;
  1614. X      e = bwb_exp( atbuf, FALSE, &pos );
  1615. X
  1616. X      #if INTENSIVE_DEBUG
  1617. X      sprintf( bwb_ebuf, "in bwb_put(): return type <%c>", e->type );
  1618. X      bwb_debug( bwb_ebuf );
  1619. X      #endif
  1620. X
  1621. X      rec_number = exp_getival( e );
  1622. X
  1623. X      }
  1624. X
  1625. X   else                /* no record number given */
  1626. X      {
  1627. X      rec_number = dev_table[ dev_number ].next_record;
  1628. X      }
  1629. X
  1630. X   #if INTENSIVE_DEBUG
  1631. X   sprintf( bwb_ebuf, "in bwb_put(): record number <%d>", rec_number );
  1632. X   bwb_debug( bwb_ebuf );
  1633. X   #endif
  1634. X
  1635. X   /* wind the c file up to the proper point */
  1636. X
  1637. X   if ( fseek( dev_table[ dev_number ].cfp,
  1638. X      (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen ), 
  1639. X      SEEK_SET ) != 0 )
  1640. X      {
  1641. X      #if PROG_ERRORS
  1642. X      sprintf( bwb_ebuf, "in bwb_get(): fseek() failed, rec number <%d> offset <%ld>",
  1643. X        rec_number, (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen ) );
  1644. X      bwb_error( bwb_ebuf );
  1645. X      #else
  1646. X      bwb_error( err_dev );
  1647. X      #endif
  1648. X      return l;
  1649. X      }
  1650. X
  1651. X   #if INTENSIVE_DEBUG
  1652. X   sprintf( bwb_ebuf, "in bwb_put(): ready to write to file, buffer <%lXh>",
  1653. X      (long) dev_table[ dev_number ].buffer );
  1654. X   bwb_debug( bwb_ebuf );
  1655. X   xprintf( stderr, "Buffer: <" );
  1656. X   #endif
  1657. X
  1658. X   /* write the requested bytes to the file */
  1659. X
  1660. X   for ( i = 0; i < dev_table[ dev_number ].reclen; ++i )
  1661. X      {
  1662. X      fputc( dev_table[ dev_number ].buffer[ i ],
  1663. X         dev_table[ dev_number ].cfp );
  1664. X      #if INTENSIVE_DEBUG
  1665. X      xputc( stderr, dev_table[ dev_number ].buffer[ i ] );
  1666. X      #endif
  1667. X      ++( dev_table[ dev_number ].loc );
  1668. X      }
  1669. X
  1670. X   #if INTENSIVE_DEBUG
  1671. X   xprintf( stderr, ">\n" );
  1672. X   sprintf( bwb_ebuf, "in bwb_put(): write to file complete" );
  1673. X   bwb_debug( bwb_ebuf );
  1674. X   #endif
  1675. X
  1676. X   /* flush the buffer */
  1677. X
  1678. X   dio_flush( dev_number );
  1679. X
  1680. X   /* increment (or reset) the current record */
  1681. X
  1682. X   dev_table[ dev_number ].next_record = rec_number + 1;
  1683. X
  1684. X   return l;
  1685. X
  1686. X   }
  1687. X
  1688. X/***************************************************************
  1689. X
  1690. X        FUNCTION:       dio_flush()
  1691. X
  1692. X        DESCRIPTION:    This C function flushes the random-access
  1693. X            buffer associated with file dev_number.
  1694. X
  1695. X***************************************************************/
  1696. X
  1697. Xint
  1698. Xdio_flush( int dev_number )
  1699. X   {
  1700. X   register int n;
  1701. X
  1702. X   if ( dev_table[ dev_number ].mode != DEVMODE_RANDOM )
  1703. X      {
  1704. X      #if PROG_ERRORS
  1705. X      sprintf( bwb_ebuf, "in dio_flush(): only random-access buffers can be flushed" );
  1706. X      bwb_error( bwb_ebuf );
  1707. X      #else
  1708. X      bwb_error( err_dev );
  1709. X      #endif
  1710. X      }
  1711. X
  1712. X   /* fill buffer with blanks (or 'X' for test) */
  1713. X
  1714. X   for ( n = 0; n < dev_table[ req_devnumber ].reclen; ++n )
  1715. X      {
  1716. X      dev_table[ req_devnumber ].buffer[ n ] = RANDOM_FILLCHAR;
  1717. X      }
  1718. X
  1719. X   return TRUE;
  1720. X
  1721. X   }
  1722. X
  1723. X/***************************************************************
  1724. X
  1725. X        FUNCTION:       fnc_loc()
  1726. X
  1727. X        DESCRIPTION:    This C function implements the BASIC
  1728. X            LOC() function. As implemented here,
  1729. X            this only workd for random-acess files.
  1730. X
  1731. X***************************************************************/
  1732. X
  1733. Xstruct bwb_variable *
  1734. Xfnc_loc( int argc, struct bwb_variable *argv )
  1735. X   {
  1736. X   static struct bwb_variable nvar;
  1737. X   static int init = FALSE;
  1738. X   int dev_number;
  1739. X
  1740. X   #if INTENSIVE_DEBUG
  1741. X   sprintf( bwb_ebuf, "in fnc_loc(): received f_arg <%f> ",
  1742. X      var_getdval( &( argv[ 0 ] ) ) );
  1743. X   bwb_debug( bwb_ebuf );
  1744. X   #endif
  1745. X
  1746. X   if ( argc < 1 )
  1747. X      {
  1748. X      #if PROG_ERRORS
  1749. X      sprintf( bwb_ebuf, "Not enough parameters (%d) to function LOC().",
  1750. X         argc );
  1751. X      bwb_error( bwb_ebuf );
  1752. X      #else
  1753. X      bwb_error( err_syntax );
  1754. X      #endif
  1755. X      return NULL;
  1756. X      }
  1757. X   else if ( argc > 1 )
  1758. X      {
  1759. X      #if PROG_ERRORS
  1760. X      sprintf( bwb_ebuf, "Too many parameters (%d) to function LOC().",
  1761. X         argc );
  1762. X      bwb_error( bwb_ebuf );
  1763. X      #else
  1764. X      bwb_error( err_syntax );
  1765. X      #endif
  1766. X      return NULL;
  1767. X      }
  1768. X
  1769. X   dev_number = var_getival( &( argv[ 0 ] ) );
  1770. X
  1771. X   if ( init == FALSE )
  1772. X      {
  1773. X      init = TRUE;
  1774. X      var_make( &nvar, INTEGER );
  1775. X      }
  1776. X
  1777. X   /* note if this is the very beginning of the file */
  1778. X
  1779. X   if ( dev_table[ dev_number ].loc == 0 )
  1780. X      {
  1781. X      * var_findival( &nvar, nvar.array_pos ) = 0;
  1782. X      }
  1783. X   else
  1784. X      {
  1785. X      * var_findival( &nvar, nvar.array_pos ) =
  1786. X         dev_table[ dev_number ].next_record;
  1787. X      }
  1788. X
  1789. X   return &nvar;
  1790. X   }
  1791. X
  1792. X/***************************************************************
  1793. X
  1794. X        FUNCTION:       fnc_lof()
  1795. X
  1796. X        DESCRIPTION:    This C function implements the BASIC
  1797. X            LOF() function. 
  1798. X
  1799. X***************************************************************/
  1800. X
  1801. Xstruct bwb_variable *
  1802. Xfnc_lof( int argc, struct bwb_variable *argv )
  1803. X   {
  1804. X   static struct bwb_variable nvar;
  1805. X   static int init = FALSE;
  1806. X   int dev_number;
  1807. X   int r;
  1808. X   static struct stat statbuf;
  1809. X
  1810. X   #if INTENSIVE_DEBUG
  1811. X   sprintf( bwb_ebuf, "in fnc_lof(): received f_arg <%f> ",
  1812. X      var_getdval( &( argv[ 0 ] ) ) );
  1813. X   bwb_debug( bwb_ebuf );
  1814. X   #endif
  1815. X
  1816. X   if ( argc < 1 )
  1817. X      {
  1818. X      #if PROG_ERRORS
  1819. X      sprintf( bwb_ebuf, "Not enough parameters (%d) to function LOF().",
  1820. X         argc );
  1821. X      bwb_error( bwb_ebuf );
  1822. X      #else
  1823. X      bwb_error( err_syntax );
  1824. X      #endif
  1825. X      return NULL;
  1826. X      }
  1827. X   else if ( argc > 1 )
  1828. X      {
  1829. X      #if PROG_ERRORS
  1830. X      sprintf( bwb_ebuf, "Too many parameters (%d) to function LOF().",
  1831. X         argc );
  1832. X      bwb_error( bwb_ebuf );
  1833. X      #else
  1834. X      bwb_error( err_syntax );
  1835. X      #endif
  1836. X      return NULL;
  1837. X      }
  1838. X
  1839. X   dev_number = var_getival( &( argv[ 0 ] ) );
  1840. X
  1841. X   if ( init == FALSE )
  1842. X      {
  1843. X      init = TRUE;
  1844. X      var_make( &nvar, SINGLE );
  1845. X      }
  1846. X
  1847. X   /* stat the file */
  1848. X
  1849. X   r = stat( dev_table[ dev_number ].filename, &statbuf );
  1850. X
  1851. X   if ( r != 0 )
  1852. X      {
  1853. X      #if PROG_ERRORS
  1854. X      sprintf( bwb_ebuf, "in fnc_lof(): failed to find file <%s>",
  1855. X         dev_table[ dev_number ].filename );
  1856. X      bwb_error( bwb_ebuf );
  1857. X      #else
  1858. X      sprintf( bwb_ebuf, ERR_OPENFILE,
  1859. X         dev_table[ dev_number ].filename );
  1860. X      bwb_error( bwb_ebuf );
  1861. X      #endif
  1862. X      return NULL;
  1863. X      }
  1864. X
  1865. X   * var_findfval( &nvar, nvar.array_pos ) = (float) statbuf.st_size;
  1866. X
  1867. X   return &nvar;
  1868. X   }
  1869. X
  1870. X/***************************************************************
  1871. X
  1872. X        FUNCTION:       fnc_eof()
  1873. X
  1874. X        DESCRIPTION:    This C function implements the BASIC
  1875. X            EOF() function. 
  1876. X
  1877. X***************************************************************/
  1878. X
  1879. Xstruct bwb_variable *
  1880. Xfnc_eof( int argc, struct bwb_variable *argv )
  1881. X   {
  1882. X   static struct bwb_variable nvar;
  1883. X   static int init = FALSE;
  1884. X   int dev_number;
  1885. X
  1886. X   #if INTENSIVE_DEBUG
  1887. X   sprintf( bwb_ebuf, "in fnc_loc(): received f_arg <%f> ",
  1888. X      var_getdval( &( argv[ 0 ] ) ) );
  1889. X   bwb_debug( bwb_ebuf );
  1890. X   #endif
  1891. X
  1892. X   if ( argc < 1 )
  1893. X      {
  1894. X      #if PROG_ERRORS
  1895. X      sprintf( bwb_ebuf, "Not enough parameters (%d) to function EOF().",
  1896. X         argc );
  1897. X      bwb_error( bwb_ebuf );
  1898. X      #else
  1899. X      bwb_error( err_syntax );
  1900. X      #endif
  1901. X      return NULL;
  1902. X      }
  1903. X   else if ( argc > 1 )
  1904. X      {
  1905. X      #if PROG_ERRORS
  1906. X      sprintf( bwb_ebuf, "Too many parameters (%d) to function EOF().",
  1907. X         argc );
  1908. X      bwb_error( bwb_ebuf );
  1909. X      #else
  1910. X      bwb_error( err_syntax );
  1911. X      #endif
  1912. X      return NULL;
  1913. X      }
  1914. X
  1915. X   dev_number = var_getival( &( argv[ 0 ] ) );
  1916. X
  1917. X   if ( init == FALSE )
  1918. X      {
  1919. X      init = TRUE;
  1920. X      var_make( &nvar, INTEGER );
  1921. X      }
  1922. X
  1923. X   /* note if this is the very beginning of the file */
  1924. X
  1925. X   if ( dev_table[ dev_number ].mode == DEVMODE_AVAILABLE )
  1926. X      {
  1927. X      bwb_error( err_devnum );
  1928. X      * var_findival( &nvar, nvar.array_pos ) = TRUE;
  1929. X      }
  1930. X   else if ( dev_table[ dev_number ].mode == DEVMODE_CLOSED )
  1931. X      {
  1932. X      bwb_error( err_devnum );
  1933. X      * var_findival( &nvar, nvar.array_pos ) = TRUE;
  1934. X      }
  1935. X   else if ( feof( dev_table[ dev_number ].cfp ) == 0 )
  1936. X      {
  1937. X      * var_findival( &nvar, nvar.array_pos ) = FALSE;
  1938. X      }
  1939. X   else
  1940. X      {
  1941. X      * var_findival( &nvar, nvar.array_pos ) = TRUE;
  1942. X      }
  1943. X
  1944. X   return &nvar;
  1945. X   }
  1946. X
  1947. X
  1948. END_OF_FILE
  1949.   if test 46285 -ne `wc -c <'bwb_dio.c'`; then
  1950.     echo shar: \"'bwb_dio.c'\" unpacked with wrong size!
  1951.   fi
  1952.   # end of 'bwb_dio.c'
  1953. fi
  1954. if test -f 'bwb_str.c' -a "${1}" != "-c" ; then 
  1955.   echo shar: Will not clobber existing file \"'bwb_str.c'\"
  1956. else
  1957.   echo shar: Extracting \"'bwb_str.c'\" \(7137 characters\)
  1958.   sed "s/^X//" >'bwb_str.c' <<'END_OF_FILE'
  1959. X/***************************************************************
  1960. X
  1961. X        bwb_str.c       String-management routines
  1962. X                        for Bywater BASIC Interpreter
  1963. X
  1964. X                        Copyright (c) 1992, Ted A. Campbell
  1965. X
  1966. X                        Bywater Software
  1967. X                        P. O. Box 4023
  1968. X                        Duke Station
  1969. X                        Durham, NC  27706
  1970. X
  1971. X                        email: tcamp@acpub.duke.edu
  1972. X
  1973. X        Copyright and Permissions Information:
  1974. X
  1975. X        All U.S. and international copyrights are claimed by the
  1976. X        author. The author grants permission to use this code
  1977. X        and software based on it under the following conditions:
  1978. X        (a) in general, the code and software based upon it may be
  1979. X        used by individuals and by non-profit organizations; (b) it
  1980. X        may also be utilized by governmental agencies in any country,
  1981. X        with the exception of military agencies; (c) the code and/or
  1982. X        software based upon it may not be sold for a profit without
  1983. X        an explicit and specific permission from the author, except
  1984. X        that a minimal fee may be charged for media on which it is
  1985. X        copied, and for copying and handling; (d) the code must be
  1986. X        distributed in the form in which it has been released by the
  1987. X        author; and (e) the code and software based upon it may not
  1988. X        be used for illegal activities.
  1989. X
  1990. X***************************************************************/
  1991. X
  1992. X#include <stdio.h>
  1993. X#include <stdlib.h>
  1994. X#include <string.h>
  1995. X
  1996. X#include "bwbasic.h"
  1997. X#include "bwb_mes.h"
  1998. X
  1999. X#define FREE_STRBUFFERS    0    /* works with QuickC but not others */
  2000. X
  2001. X#if INTENSIVE_DEBUG || TEST_BSTRING
  2002. Xstatic char tbuf[ MAXSTRINGSIZE + 1 ];
  2003. X#endif
  2004. X
  2005. X/***************************************************************
  2006. X
  2007. X        FUNCTION:       str_btob()
  2008. X
  2009. X        DESCRIPTION:    This C function assigns a bwBASIC string
  2010. X            structure to another bwBASIC string 
  2011. X            structure.
  2012. X
  2013. X***************************************************************/
  2014. X
  2015. Xint
  2016. Xstr_btob( bstring *d, bstring *s )
  2017. X   {
  2018. X   char *t;
  2019. X   register int i;
  2020. X
  2021. X   #if TEST_BSTRING
  2022. X   sprintf( tbuf, "in str_btob(): entry, source b string name is <%s>", s->name );
  2023. X   bwb_debug( tbuf );
  2024. X   sprintf( tbuf, "in str_btob(): entry, destination b string name is <%s>", d->name );
  2025. X   bwb_debug( tbuf );
  2026. X   #endif
  2027. X
  2028. X   /* get memory for new buffer */
  2029. X
  2030. X   if ( ( t = (char *) calloc( s->length + 1, 1 )) == NULL )
  2031. X      {
  2032. X      bwb_error( err_getmem );
  2033. X      return FALSE;
  2034. X      }
  2035. X
  2036. X   /* write the c string to the b string */
  2037. X
  2038. X   t[ 0 ] = '\0';
  2039. X   for ( i = 0; i < s->length; ++i )
  2040. X      {
  2041. X      t[ i ] = s->buffer[ i ];
  2042. X      #if INTENSIVE_DEBUG
  2043. X      tbuf[ i ] = s->buffer[ i ];
  2044. X      tbuf[ i + 1 ] = '\0';
  2045. X      #endif
  2046. X      }
  2047. X
  2048. X   /* deallocate old memory */
  2049. X
  2050. X   #if INTENSIVE_DEBUG
  2051. X   if ( d->rab == TRUE )
  2052. X      {
  2053. X      sprintf( bwb_ebuf, "in str_btob(): reallocating RAB" );
  2054. X      bwb_debug( bwb_ebuf );
  2055. X      }
  2056. X   #endif
  2057. X   #if FREE_STRBUFFERS
  2058. X   if (( d->rab != TRUE ) && ( d->buffer != NULL ))
  2059. X      {
  2060. X      free( d->buffer );
  2061. X      }
  2062. X   #endif
  2063. X   d->rab = (char) FALSE;
  2064. X
  2065. X   /* reassign buffer */
  2066. X
  2067. X   d->buffer = t;
  2068. X
  2069. X   /* reassign length */
  2070. X
  2071. X   d->length = s->length;
  2072. X
  2073. X   #if INTENSIVE_DEBUG
  2074. X   sprintf( bwb_ebuf, "in str_btob(): exit length <%d> string <%s>",
  2075. X      d->length, tbuf );
  2076. X   bwb_debug( bwb_ebuf );
  2077. X   #endif
  2078. X
  2079. X   /* return */
  2080. X
  2081. X   return TRUE;
  2082. X
  2083. X   }
  2084. X
  2085. X/***************************************************************
  2086. X
  2087. X        FUNCTION:       str_ctob()
  2088. X
  2089. X        DESCRIPTION:    This C function assigns a null-terminated
  2090. X            C string to a bwBASIC string structure.
  2091. X
  2092. X***************************************************************/
  2093. X
  2094. Xint
  2095. Xstr_ctob( bstring *s, char *buffer )
  2096. X   {
  2097. X   char *t;
  2098. X   register int i;
  2099. X
  2100. X   #if INTENSIVE_DEBUG
  2101. X   sprintf( tbuf, "in str_ctob(): entry, c string is <%s>", buffer );
  2102. X   bwb_debug( tbuf );
  2103. X   #endif
  2104. X   #if TEST_BSTRING
  2105. X   sprintf( tbuf, "in str_ctob(): entry, b string name is <%s>", s->name );
  2106. X   bwb_debug( tbuf );
  2107. X   #endif
  2108. X
  2109. X   /* get memory for new buffer */
  2110. X
  2111. X   if ( ( t = (char *) calloc( strlen( buffer ) + 1, 1 )) == NULL )
  2112. X      {
  2113. X      bwb_error( err_getmem );
  2114. X      return FALSE;
  2115. X      }
  2116. X
  2117. X   /* write the c string to the b string */
  2118. X
  2119. X   t[ 0 ] = '\0';
  2120. X   for ( i = 0; i < strlen( buffer ); ++i )
  2121. X      {
  2122. X      t[ i ] = buffer[ i ];
  2123. X      #if INTENSIVE_DEBUG
  2124. X      tbuf[ i ] = buffer[ i ];
  2125. X      tbuf[ i + 1 ] = '\0';
  2126. X      #endif
  2127. X      }
  2128. X
  2129. X   /* deallocate old memory */
  2130. X
  2131. X   #if INTENSIVE_DEBUG
  2132. X   if ( s->rab == TRUE )
  2133. X      {
  2134. X      sprintf( bwb_ebuf, "in str_ctob(): reallocating RAB" );
  2135. X      bwb_debug( bwb_ebuf );
  2136. X      }
  2137. X   #endif
  2138. X   #if FREE_STRBUFFERS
  2139. X   if (( s->rab != TRUE ) && ( s->buffer != NULL ))
  2140. X      {
  2141. X      free( s->buffer );
  2142. X      }
  2143. X   #endif
  2144. X   s->rab = (char) FALSE;
  2145. X
  2146. X   /* reassign buffer */
  2147. X
  2148. X   s->buffer = t;
  2149. X
  2150. X   /* reassign length */
  2151. X
  2152. X   s->length = (unsigned char) strlen( buffer );
  2153. X
  2154. X   #if INTENSIVE_DEBUG
  2155. X   sprintf( bwb_ebuf, "in str_ctob(): exit length <%d> string <%s>",
  2156. X      s->length, tbuf );
  2157. X   bwb_debug( bwb_ebuf );
  2158. X   #endif
  2159. X
  2160. X   /* return */
  2161. X
  2162. X   return TRUE;
  2163. X
  2164. X   }
  2165. X
  2166. X/***************************************************************
  2167. X
  2168. X        FUNCTION:       str_btoc()
  2169. X
  2170. X        DESCRIPTION:    This C function assigns a null-terminated
  2171. X            C string to a bwBASIC string structure.
  2172. X
  2173. X***************************************************************/
  2174. X
  2175. Xint
  2176. Xstr_btoc( char *buffer, bstring *s )
  2177. X   {
  2178. X   register int i;
  2179. X
  2180. X   #if INTENSIVE_DEBUG
  2181. X   sprintf( tbuf, "in str_btoc(): entry, b string length is <%d>", 
  2182. X      s->length );
  2183. X   bwb_debug( tbuf );
  2184. X   #endif
  2185. X   #if TEST_BSTRING
  2186. X   sprintf( tbuf, "in str_btoc(): entry, b string name is <%s>", s->name );
  2187. X   bwb_debug( tbuf );
  2188. X   #endif
  2189. X
  2190. X   /* write the b string to the c string */
  2191. X
  2192. X   buffer[ 0 ] = '\0';
  2193. X   for ( i = 0; i < s->length; ++i )
  2194. X      {
  2195. X      buffer[ i ] = s->buffer[ i ];
  2196. X      buffer[ i + 1 ] = '\0';
  2197. X      if ( i >= MAXSTRINGSIZE )
  2198. X         {
  2199. X         i = s->length + 1;
  2200. X         }
  2201. X      }
  2202. X
  2203. X   #if INTENSIVE_DEBUG
  2204. X   sprintf( tbuf, "in str_btoc(): exit, c string is <%s>", buffer );
  2205. X   bwb_debug( tbuf );
  2206. X   #endif
  2207. X
  2208. X   /* return */
  2209. X
  2210. X   return TRUE;
  2211. X
  2212. X   }
  2213. X
  2214. X/***************************************************************
  2215. X
  2216. X        FUNCTION:       str_cat()
  2217. X
  2218. X        DESCRIPTION:    This C function 
  2219. X
  2220. X***************************************************************/
  2221. X
  2222. Xchar *
  2223. Xstr_cat( bstring *a, bstring *b )
  2224. X   {
  2225. X   char abuf[ MAXSTRINGSIZE + 1 ];
  2226. X   char bbuf[ MAXSTRINGSIZE + 1 ];
  2227. X   char *r;
  2228. X
  2229. X   str_btoc( abuf, a );
  2230. X   str_btoc( bbuf, b );
  2231. X
  2232. X   #if INTENSIVE_DEBUG
  2233. X   sprintf( bwb_ebuf, "in str_cat(): a <%s> b <%s>", abuf, bbuf );
  2234. X   bwb_debug( bwb_ebuf );
  2235. X   #endif
  2236. X
  2237. X   r = strcat( abuf, bbuf );
  2238. X   str_ctob( a, abuf );
  2239. X
  2240. X   return r;
  2241. X   }
  2242. X
  2243. X/***************************************************************
  2244. X
  2245. X        FUNCTION:       str_cmp()
  2246. X
  2247. X        DESCRIPTION:    This C function 
  2248. X
  2249. X***************************************************************/
  2250. X
  2251. Xint
  2252. Xstr_cmp( bstring *a, bstring *b )
  2253. X   {
  2254. X   char abuf[ MAXSTRINGSIZE + 1 ];
  2255. X   char bbuf[ MAXSTRINGSIZE + 1 ];
  2256. X
  2257. X   str_btoc( abuf, a );
  2258. X   str_btoc( bbuf, b );
  2259. X
  2260. X   return strcmp( abuf, bbuf );
  2261. X   }
  2262. X
  2263. X
  2264. END_OF_FILE
  2265.   if test 7137 -ne `wc -c <'bwb_str.c'`; then
  2266.     echo shar: \"'bwb_str.c'\" unpacked with wrong size!
  2267.   fi
  2268.   # end of 'bwb_str.c'
  2269. fi
  2270. if test -f 'makefile.qcl' -a "${1}" != "-c" ; then 
  2271.   echo shar: Will not clobber existing file \"'makefile.qcl'\"
  2272. else
  2273.   echo shar: Extracting \"'makefile.qcl'\" \(1216 characters\)
  2274.   sed "s/^X//" >'makefile.qcl' <<'END_OF_FILE'
  2275. X#               Microsoft QuickC Makefile for Bywater BASIC Interpreter
  2276. X#
  2277. X#        This makefile is for line-oriented QuickC only, not for
  2278. X#        the QuickC integrated environment. To make the program:
  2279. X#        rename this file as "makefile," then type "nmake."
  2280. X#
  2281. XPROJ=           bwbasic
  2282. XCC=             qcl
  2283. X
  2284. X#
  2285. X#        These are the normal flags I used to compile bwBASIC:
  2286. X#
  2287. XCFLAGS=         -O -AL -W3 -Za
  2288. X
  2289. X#
  2290. X#        The following flags can be used for debugging:
  2291. X#
  2292. X#CFLAGS=         -Od -AL -W3 -Za -Zr -Zi
  2293. X
  2294. XLFLAGS=         /NOE /ST:8192
  2295. X
  2296. XOFILES=         bwbasic.obj bwb_int.obj bwb_tbl.obj bwb_cmd.obj bwb_prn.obj\
  2297. X                bwb_exp.obj bwb_var.obj bwb_inp.obj bwb_fnc.obj bwb_cnd.obj\
  2298. X                bwb_ops.obj bwb_dio.obj bwb_str.obj bwb_elx.obj bwb_mth.obj
  2299. X
  2300. XHFILES=         bwbasic.h bwb_mes.h
  2301. X
  2302. Xall:            $(PROJ).exe
  2303. X
  2304. X$(OFILES):      $(HFILES) makefile.qcl
  2305. X
  2306. X$(PROJ).exe:    $(OFILES)
  2307. X        echo >NUL @<<$(PROJ).crf
  2308. Xbwbasic.obj +
  2309. Xbwb_cmd.obj +
  2310. Xbwb_cnd.obj +
  2311. Xbwb_fnc.obj +
  2312. Xbwb_inp.obj +
  2313. Xbwb_int.obj +
  2314. Xbwb_prn.obj +
  2315. Xbwb_tbl.obj +
  2316. Xbwb_var.obj +
  2317. Xbwb_exp.obj +
  2318. Xbwb_ops.obj +
  2319. Xbwb_dio.obj +
  2320. Xbwb_str.obj +
  2321. Xbwb_elx.obj +
  2322. Xbwb_mth.obj +
  2323. X$(OBJS_EXT)
  2324. X$(PROJ).exe
  2325. X
  2326. X$(LIBS_EXT);
  2327. X<<
  2328. X        link $(LFLAGS) @$(PROJ).crf
  2329. X    erase $(PROJ).crf
  2330. X
  2331. END_OF_FILE
  2332.   if test 1216 -ne `wc -c <'makefile.qcl'`; then
  2333.     echo shar: \"'makefile.qcl'\" unpacked with wrong size!
  2334.   fi
  2335.   # end of 'makefile.qcl'
  2336. fi
  2337. echo shar: End of archive 4 \(of 11\).
  2338. cp /dev/null ark4isdone
  2339. MISSING=""
  2340. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2341.     if test ! -f ark${I}isdone ; then
  2342.     MISSING="${MISSING} ${I}"
  2343.     fi
  2344. done
  2345. if test "${MISSING}" = "" ; then
  2346.     echo You have unpacked all 11 archives.
  2347.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2348. else
  2349.     echo You still must unpack the following archives:
  2350.     echo "        " ${MISSING}
  2351. fi
  2352. exit 0
  2353. exit 0 # Just in case...
  2354.