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

1282 lines
26 KiB

  1. /***************************************************************
  2. bwb_dio.c Device Input/Output Routines
  3. for Bywater BASIC Interpreter
  4. Copyright (c) 1993, Ted A. Campbell
  5. Bywater Software
  6. email: tcamp@delphi.com
  7. Copyright and Permissions Information:
  8. All U.S. and international rights are claimed by the author,
  9. Ted A. Campbell.
  10. This software is released under the terms of the GNU General
  11. Public License (GPL), which is distributed with this software
  12. in the file "COPYING". The GPL specifies the terms under
  13. which users may copy and use the software in this distribution.
  14. A separate license is available for commercial distribution,
  15. for information on which you should contact the author.
  16. ***************************************************************/
  17. /*---------------------------------------------------------------*/
  18. /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
  19. /* 11/1995 (eidetics@cerf.net). */
  20. /* */
  21. /* Those additionally marked with "DD" were at the suggestion of */
  22. /* Dale DePriest (daled@cadence.com). */
  23. /* */
  24. /* Version 3.00 by Howard Wulf, AF5NE */
  25. /* */
  26. /* Version 3.10 by Howard Wulf, AF5NE */
  27. /* */
  28. /* Version 3.20 by Howard Wulf, AF5NE */
  29. /* */
  30. /*---------------------------------------------------------------*/
  31. #include "bwbasic.h"
  32. static LineType *C77_OPEN (LineType * l);
  33. static LineType *D71_OPEN (LineType * l);
  34. static LineType *H80_OPEN (LineType * l);
  35. static LineType *M80_OPEN (LineType * l);
  36. static LineType *S70_OPEN (LineType * l);
  37. static LineType *T79_OPEN (LineType * l);
  38. /***************************************************************
  39. FUNCTION: bwb_open()
  40. DESCRIPTION: This function implements the BASIC OPEN
  41. command to open a stream for device input/output.
  42. SYNTAX: 1. OPEN "I"|"O"|"R"|"A", [#]n, filename [,rlen]
  43. 2. OPEN filename [FOR INPUT|OUTPUT|APPEND|RANDOM|BINARY] AS [#]n [LEN=n]
  44. ***************************************************************/
  45. extern void
  46. bwb_file_open (char A, int x, char *B, int y)
  47. {
  48. /* OPEN "I"|"O"|"R"|"A", [#] filenum, filename [,reclen] */
  49. /* P1STR|P2NUM|P3STR|P4NUM */
  50. /* P1BYT|P2DEV|P3BYT|P4INT */
  51. int mode;
  52. FileType *F;
  53. FILE *fp;
  54. char *buffer;
  55. assert (B != NULL);
  56. assert(My != NULL);
  57. assert(My->CurrentVersion != NULL);
  58. assert(My->SYSIN != NULL);
  59. assert(My->SYSOUT != NULL);
  60. assert(My->SYSPRN != NULL);
  61. mode = 0;
  62. F = NULL;
  63. fp = NULL;
  64. buffer = NULL;
  65. if (y < 0)
  66. {
  67. WARN_FIELD_OVERFLOW;
  68. return;
  69. }
  70. mode = bwb_toupper (A);
  71. switch (mode)
  72. {
  73. case 'I':
  74. case 'O':
  75. case 'A':
  76. case 'B':
  77. case 'V':
  78. case 'R':
  79. /* valid mode */
  80. break;
  81. default:
  82. WARN_BAD_FILE_MODE;
  83. return;
  84. }
  85. /* valid mode */
  86. F = find_file_by_number (x);
  87. if (F == NULL)
  88. {
  89. F = file_new ();
  90. if (F == NULL)
  91. {
  92. WARN_OUT_OF_MEMORY;
  93. return;
  94. }
  95. }
  96. if (F == My->SYSIN)
  97. {
  98. WARN_BAD_FILE_NUMBER;
  99. return;
  100. }
  101. if (F == My->SYSOUT)
  102. {
  103. WARN_BAD_FILE_NUMBER;
  104. return;
  105. }
  106. if (F == My->SYSPRN)
  107. {
  108. WARN_BAD_FILE_NUMBER;
  109. return;
  110. }
  111. if (F->DevMode != DEVMODE_CLOSED)
  112. {
  113. WARN_BAD_FILE_NUMBER;
  114. return;
  115. }
  116. /* valid filenumber */
  117. switch (mode)
  118. {
  119. case 'I':
  120. mode = DEVMODE_INPUT;
  121. fp = fopen (B, "r");
  122. if (fp == NULL)
  123. {
  124. WARN_BAD_FILE_NAME;
  125. return;
  126. }
  127. if (y > 0)
  128. {
  129. /* RECLEN == INPUT BUFFER SIZE */
  130. if ((buffer =
  131. (char *) calloc (y + 1 /* NulChar */ , sizeof (char))) == NULL)
  132. {
  133. WARN_OUT_OF_MEMORY;
  134. return;
  135. }
  136. bwb_memset (buffer, ' ', y); /* flush */
  137. buffer[y] = NulChar;
  138. }
  139. break;
  140. case 'O':
  141. mode = DEVMODE_OUTPUT;
  142. fp = fopen (B, "w");
  143. if (fp == NULL)
  144. {
  145. WARN_BAD_FILE_NAME;
  146. return;
  147. }
  148. if (y > 0)
  149. {
  150. /* RECLEN == OUTPUT WRAP WIDTH */
  151. }
  152. break;
  153. case 'A':
  154. mode = DEVMODE_APPEND;
  155. fp = fopen (B, "a");
  156. if (fp == NULL)
  157. {
  158. WARN_BAD_FILE_NAME;
  159. return;
  160. }
  161. fseek (fp, 0, SEEK_END);
  162. if (y > 0)
  163. {
  164. /* RECLEN == OUTPUT WRAP WIDTH */
  165. }
  166. break;
  167. case 'B':
  168. mode = DEVMODE_BINARY;
  169. fp = fopen (B, "r+");
  170. if (fp == NULL)
  171. {
  172. fp = fopen (B, "w");
  173. if (fp != NULL)
  174. {
  175. bwb_fclose (fp);
  176. fp = fopen (B, "r+");
  177. }
  178. }
  179. if (fp == NULL)
  180. {
  181. WARN_BAD_FILE_NAME;
  182. return;
  183. }
  184. if (y > 0)
  185. {
  186. /* RECLEN == SILENTLY IGNORED */
  187. }
  188. break;
  189. case 'V':
  190. mode = DEVMODE_VIRTUAL;
  191. fp = fopen (B, "r+");
  192. if (fp == NULL)
  193. {
  194. fp = fopen (B, "w");
  195. if (fp != NULL)
  196. {
  197. bwb_fclose (fp);
  198. fp = fopen (B, "r+");
  199. }
  200. }
  201. if (fp == NULL)
  202. {
  203. WARN_BAD_FILE_NAME;
  204. return;
  205. }
  206. if (y > 0)
  207. {
  208. /* RECLEN == SILENTLY IGNORED */
  209. }
  210. break;
  211. case 'R':
  212. if (y == 0)
  213. {
  214. /* dialect-specific default record length */
  215. y = My->CurrentVersion->OptionReclenInteger;
  216. if (y == 0)
  217. {
  218. /* there is no default record length */
  219. WARN_FIELD_OVERFLOW;
  220. return;
  221. }
  222. }
  223. mode = DEVMODE_RANDOM;
  224. fp = fopen (B, "r+");
  225. if (fp == NULL)
  226. {
  227. fp = fopen (B, "w");
  228. if (fp != NULL)
  229. {
  230. bwb_fclose (fp);
  231. fp = fopen (B, "r+");
  232. }
  233. }
  234. if (fp == NULL)
  235. {
  236. WARN_BAD_FILE_NAME;
  237. return;
  238. }
  239. if (y > 0)
  240. {
  241. /* RECLEN == RANDOM BUFFER SIZE */
  242. if ((buffer = (char *) calloc (y, sizeof (char))) == NULL)
  243. {
  244. WARN_OUT_OF_MEMORY;
  245. return;
  246. }
  247. bwb_memset (buffer, ' ', y); /* flush */
  248. }
  249. break;
  250. default:
  251. /* should not happen */
  252. WARN_BAD_FILE_MODE;
  253. return;
  254. }
  255. /* OK */
  256. F->FileNumber = x;
  257. F->DevMode = mode;
  258. F->cfp = fp;
  259. F->width = y; /* WIDTH == RECLEN */
  260. F->col = 1;
  261. F->row = 1;
  262. F->delimit = ',';
  263. if (F->buffer != NULL)
  264. {
  265. free (F->buffer);
  266. F->buffer = NULL;
  267. }
  268. F->buffer = buffer;
  269. if (F->FileName != NULL)
  270. {
  271. free (F->FileName);
  272. F->FileName = NULL;
  273. }
  274. F->FileName = bwb_strdup (B); /* 'B' is free'd by caller */
  275. return;
  276. }
  277. static LineType *
  278. C77_OPEN (LineType * l)
  279. {
  280. int FileNumber;
  281. int RecordLength;
  282. char *FileName;
  283. assert (l != NULL);
  284. assert(My != NULL);
  285. FileNumber = 0;
  286. RecordLength = 0;
  287. FileName = NULL;
  288. /*
  289. SYNTAX: OPEN filename$ [ RECL reclen ] AS filenumber [ BUFF ignored ] [ RECS ignored ]
  290. */
  291. /*
  292. ---------------------------------------------
  293. FILE NAME
  294. ---------------------------------------------
  295. */
  296. if (line_read_string_expression (l, &FileName) == FALSE)
  297. {
  298. WARN_BAD_FILE_NAME;
  299. return (l);
  300. }
  301. if (FileName == NULL)
  302. {
  303. WARN_BAD_FILE_NAME;
  304. return (l);
  305. }
  306. if (is_empty_string (FileName))
  307. {
  308. WARN_BAD_FILE_NAME;
  309. return (l);
  310. }
  311. /*
  312. ---------------------------------------------
  313. RECORD LENGTH
  314. ---------------------------------------------
  315. */
  316. if (line_skip_word (l, "RECL"))
  317. {
  318. if (line_read_integer_expression (l, &RecordLength) == FALSE)
  319. {
  320. WARN_FIELD_OVERFLOW;
  321. return (l);
  322. }
  323. if (RecordLength <= 0)
  324. {
  325. WARN_FIELD_OVERFLOW;
  326. return (l);
  327. }
  328. }
  329. /*
  330. ---------------------------------------------
  331. FILE NUMBER
  332. ---------------------------------------------
  333. */
  334. if (line_skip_word (l, "AS") == FALSE)
  335. {
  336. WARN_SYNTAX_ERROR;
  337. return (l);
  338. }
  339. if (line_skip_FilenumChar (l))
  340. {
  341. /* OPTIONAL */
  342. }
  343. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  344. {
  345. WARN_BAD_FILE_NUMBER;
  346. return (l);
  347. }
  348. if (FileNumber <= 0)
  349. {
  350. WARN_BAD_FILE_NUMBER;
  351. return (l);
  352. }
  353. /*
  354. ---------------------------------------------
  355. IGNORED
  356. ---------------------------------------------
  357. */
  358. /* if( TRUE ) */
  359. {
  360. int Ignored;
  361. Ignored = 0;
  362. /*
  363. these are all parsed but ignored
  364. */
  365. if (line_skip_word (l, "BUFF"))
  366. {
  367. if (line_read_integer_expression (l, &Ignored) == FALSE)
  368. {
  369. WARN_ILLEGAL_FUNCTION_CALL;
  370. return (l);
  371. }
  372. if (Ignored <= 0)
  373. {
  374. WARN_ILLEGAL_FUNCTION_CALL;
  375. return (l);
  376. }
  377. }
  378. if (line_skip_word (l, "RECS"))
  379. {
  380. if (line_read_integer_expression (l, &Ignored) == FALSE)
  381. {
  382. WARN_ILLEGAL_FUNCTION_CALL;
  383. return (l);
  384. }
  385. if (Ignored <= 0)
  386. {
  387. WARN_ILLEGAL_FUNCTION_CALL;
  388. return (l);
  389. }
  390. }
  391. }
  392. /*
  393. ---------------------------------------------
  394. FILE MODE
  395. ---------------------------------------------
  396. */
  397. /*
  398. ---------------------------------------------
  399. DO IT
  400. ---------------------------------------------
  401. */
  402. My->CurrentFile = find_file_by_number (FileNumber);
  403. if (My->CurrentFile == NULL)
  404. {
  405. My->CurrentFile = file_new ();
  406. My->CurrentFile->FileNumber = FileNumber;
  407. }
  408. if (My->CurrentFile->FileName != NULL)
  409. {
  410. free (My->CurrentFile->FileName);
  411. My->CurrentFile->FileName = NULL;
  412. }
  413. My->CurrentFile->FileName = FileName;
  414. FileName = NULL;
  415. if (My->CurrentFile->DevMode != DEVMODE_CLOSED)
  416. {
  417. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  418. }
  419. if (My->CurrentFile->cfp != NULL)
  420. {
  421. bwb_fclose (My->CurrentFile->cfp);
  422. My->CurrentFile->cfp = NULL;
  423. }
  424. if (My->CurrentFile->buffer != NULL)
  425. {
  426. free (My->CurrentFile->buffer);
  427. My->CurrentFile->buffer = NULL;
  428. }
  429. My->CurrentFile->width = 0;
  430. My->CurrentFile->col = 1;
  431. My->CurrentFile->row = 1;
  432. My->CurrentFile->delimit = ',';
  433. /* open EXISTING text file for update (reading and writing) */
  434. if (is_empty_string (My->CurrentFile->FileName))
  435. {
  436. WARN_BAD_FILE_NAME;
  437. return (l);
  438. }
  439. if ((My->CurrentFile->cfp =
  440. fopen (My->CurrentFile->FileName, "r+")) == NULL)
  441. {
  442. /* IF END # file_number THEN line_number */
  443. if (My->CurrentFile->EOF_LineNumber > 0)
  444. {
  445. LineType *x;
  446. x = find_line_number (My->CurrentFile->EOF_LineNumber); /* not found in the cache */
  447. if (x != NULL)
  448. {
  449. /* FOUND */
  450. line_skip_eol (l);
  451. x->position = 0;
  452. free (FileName);
  453. FileName = NULL;
  454. return x;
  455. }
  456. /* NOT FOUND */
  457. WARN_UNDEFINED_LINE;
  458. return (l);
  459. }
  460. WARN_BAD_FILE_NAME;
  461. return (l);
  462. }
  463. if (RecordLength > 0)
  464. {
  465. My->CurrentFile->width = RecordLength; /* includes the terminating '\n' */
  466. My->CurrentFile->DevMode = DEVMODE_RANDOM;
  467. if ((My->CurrentFile->buffer =
  468. (char *) calloc (RecordLength, sizeof (char))) == NULL)
  469. {
  470. WARN_OUT_OF_MEMORY;
  471. return (l);
  472. }
  473. bwb_memset (My->CurrentFile->buffer, ' ', RecordLength); /* flush */
  474. }
  475. else
  476. {
  477. My->CurrentFile->DevMode = DEVMODE_INPUT | DEVMODE_OUTPUT;
  478. }
  479. /* OK */
  480. free (FileName);
  481. FileName = NULL;
  482. return (l);
  483. }
  484. static LineType *
  485. S70_OPEN (LineType * l)
  486. {
  487. int FileNumber;
  488. char FileMode;
  489. int RecordLength;
  490. char *FileName;
  491. assert (l != NULL);
  492. FileNumber = 0;
  493. FileMode = 'R';
  494. RecordLength = 0;
  495. FileName = NULL;
  496. /*
  497. SYNTAX: OPEN filenumber, filename$, INPUT | OUTPUT | APPEND | VIRTUAL
  498. */
  499. /*
  500. ---------------------------------------------
  501. FILE NUMBER
  502. ---------------------------------------------
  503. */
  504. if (line_skip_FilenumChar (l))
  505. {
  506. /* OPTIONAL */
  507. }
  508. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  509. {
  510. WARN_BAD_FILE_NUMBER;
  511. return (l);
  512. }
  513. if (FileNumber <= 0)
  514. {
  515. WARN_BAD_FILE_NUMBER;
  516. return (l);
  517. }
  518. if (line_skip_seperator (l) == FALSE)
  519. {
  520. WARN_SYNTAX_ERROR;
  521. return (l);
  522. }
  523. /*
  524. ---------------------------------------------
  525. FILE NAME
  526. ---------------------------------------------
  527. */
  528. if (line_read_string_expression (l, &FileName) == FALSE)
  529. {
  530. WARN_BAD_FILE_NAME;
  531. return (l);
  532. }
  533. if (FileName == NULL)
  534. {
  535. WARN_BAD_FILE_NAME;
  536. return (l);
  537. }
  538. if (is_empty_string (FileName))
  539. {
  540. WARN_BAD_FILE_NAME;
  541. return (l);
  542. }
  543. if (line_skip_seperator (l) == FALSE)
  544. {
  545. WARN_SYNTAX_ERROR;
  546. return (l);
  547. }
  548. /*
  549. ---------------------------------------------
  550. FILE MODE
  551. ---------------------------------------------
  552. */
  553. /* if( TRUE ) */
  554. {
  555. if (line_skip_word (l, "INPUT"))
  556. {
  557. FileMode = 'I';
  558. }
  559. else if (line_skip_word (l, "OUTPUT"))
  560. {
  561. FileMode = 'O';
  562. }
  563. else if (line_skip_word (l, "APPEND"))
  564. {
  565. FileMode = 'A';
  566. }
  567. else if (line_skip_word (l, "VIRTUAL"))
  568. {
  569. FileMode = 'V';
  570. }
  571. else
  572. {
  573. WARN_BAD_FILE_MODE;
  574. return (l);
  575. }
  576. }
  577. /*
  578. ---------------------------------------------
  579. RECORD LENGTH
  580. ---------------------------------------------
  581. */
  582. RecordLength = 0;
  583. /*
  584. ---------------------------------------------
  585. DO IT
  586. ---------------------------------------------
  587. */
  588. bwb_file_open (FileMode, FileNumber, FileName, RecordLength);
  589. free (FileName);
  590. FileName = NULL;
  591. return (l);
  592. }
  593. static LineType *
  594. D71_OPEN (LineType * l)
  595. {
  596. int FileNumber;
  597. char FileMode;
  598. int RecordLength;
  599. char *FileName;
  600. assert (l != NULL);
  601. FileNumber = 0;
  602. FileMode = 'R';
  603. RecordLength = 0;
  604. FileName = NULL;
  605. /*
  606. SYNTAX: OPEN filename$ [FOR mode] AS FILE filenumber [ ,RECORDSIZE ignored ] [ ,CLUSTERSIZE ignored ] [ ,MODE ignored ]
  607. */
  608. /*
  609. ---------------------------------------------
  610. FILE NAME
  611. ---------------------------------------------
  612. */
  613. if (line_read_string_expression (l, &FileName) == FALSE)
  614. {
  615. WARN_BAD_FILE_NAME;
  616. return (l);
  617. }
  618. if (FileName == NULL)
  619. {
  620. WARN_BAD_FILE_NAME;
  621. return (l);
  622. }
  623. if (is_empty_string (FileName))
  624. {
  625. WARN_BAD_FILE_NAME;
  626. return (l);
  627. }
  628. /*
  629. ---------------------------------------------
  630. FILE MODE
  631. ---------------------------------------------
  632. */
  633. if (line_skip_word (l, "FOR"))
  634. {
  635. if (line_skip_word (l, "INPUT"))
  636. {
  637. FileMode = 'I';
  638. }
  639. else if (line_skip_word (l, "OUTPUT"))
  640. {
  641. FileMode = 'O';
  642. }
  643. else if (line_skip_word (l, "APPEND"))
  644. {
  645. FileMode = 'A';
  646. }
  647. else if (line_skip_word (l, "RANDOM"))
  648. {
  649. FileMode = 'R';
  650. }
  651. else if (line_skip_word (l, "BINARY"))
  652. {
  653. FileMode = 'B';
  654. }
  655. else if (line_skip_word (l, "VIRTUAL"))
  656. {
  657. FileMode = 'V';
  658. }
  659. else
  660. {
  661. WARN_BAD_FILE_MODE;
  662. return (l);
  663. }
  664. }
  665. /*
  666. ---------------------------------------------
  667. FILE NUMBER
  668. ---------------------------------------------
  669. */
  670. if (line_skip_word (l, "AS") == FALSE)
  671. {
  672. WARN_SYNTAX_ERROR;
  673. return (l);
  674. }
  675. if (line_skip_word (l, "FILE") == FALSE)
  676. {
  677. WARN_SYNTAX_ERROR;
  678. return (l);
  679. }
  680. if (line_skip_FilenumChar (l))
  681. {
  682. /* OPTIONAL */
  683. }
  684. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  685. {
  686. WARN_BAD_FILE_NUMBER;
  687. return (l);
  688. }
  689. if (FileNumber <= 0)
  690. {
  691. WARN_BAD_FILE_NUMBER;
  692. return (l);
  693. }
  694. /*
  695. ---------------------------------------------
  696. RECORD LENGTH
  697. ---------------------------------------------
  698. */
  699. RecordLength = 0;
  700. while (line_is_eol (l) == FALSE)
  701. {
  702. int Ignored;
  703. Ignored = 0;
  704. /*
  705. these are all parsed but ignored
  706. */
  707. if (line_skip_seperator (l))
  708. {
  709. /* OK */
  710. }
  711. else if (line_skip_word (l, "RECORDSIZE"))
  712. {
  713. if (line_read_integer_expression (l, &Ignored) == FALSE)
  714. {
  715. WARN_SYNTAX_ERROR;
  716. return (l);
  717. }
  718. }
  719. else if (line_skip_word (l, "CLUSTERSIZE"))
  720. {
  721. if (line_read_integer_expression (l, &Ignored) == FALSE)
  722. {
  723. WARN_SYNTAX_ERROR;
  724. return (l);
  725. }
  726. }
  727. else if (line_skip_word (l, "FILESIZE"))
  728. {
  729. if (line_read_integer_expression (l, &Ignored) == FALSE)
  730. {
  731. WARN_SYNTAX_ERROR;
  732. return (l);
  733. }
  734. }
  735. else if (line_skip_word (l, "MODE"))
  736. {
  737. if (line_read_integer_expression (l, &Ignored) == FALSE)
  738. {
  739. WARN_SYNTAX_ERROR;
  740. return (l);
  741. }
  742. }
  743. else
  744. {
  745. WARN_SYNTAX_ERROR;
  746. return (l);
  747. }
  748. }
  749. /*
  750. ---------------------------------------------
  751. DO IT
  752. ---------------------------------------------
  753. */
  754. bwb_file_open (FileMode, FileNumber, FileName, RecordLength);
  755. free (FileName);
  756. FileName = NULL;
  757. return (l);
  758. }
  759. static LineType *
  760. H80_OPEN (LineType * l)
  761. {
  762. int FileNumber;
  763. char FileMode;
  764. int RecordLength;
  765. char *FileName;
  766. assert (l != NULL);
  767. FileNumber = 0;
  768. FileMode = 'R';
  769. RecordLength = 0;
  770. FileName = NULL;
  771. /*
  772. SYNTAX: OPEN filename$ FOR mode AS FILE filenumber
  773. */
  774. /*
  775. ---------------------------------------------
  776. FILE NAME
  777. ---------------------------------------------
  778. */
  779. if (line_read_string_expression (l, &FileName) == FALSE)
  780. {
  781. WARN_BAD_FILE_NAME;
  782. return (l);
  783. }
  784. if (FileName == NULL)
  785. {
  786. WARN_BAD_FILE_NAME;
  787. return (l);
  788. }
  789. if (is_empty_string (FileName))
  790. {
  791. WARN_BAD_FILE_NAME;
  792. return (l);
  793. }
  794. /*
  795. ---------------------------------------------
  796. FILE MODE
  797. ---------------------------------------------
  798. */
  799. if (line_skip_word (l, "FOR") == FALSE)
  800. {
  801. WARN_SYNTAX_ERROR;
  802. return (l);
  803. }
  804. if (line_skip_word (l, "READ"))
  805. {
  806. FileMode = 'I';
  807. }
  808. else if (line_skip_word (l, "WRITE"))
  809. {
  810. FileMode = 'O';
  811. }
  812. else if (line_skip_word (l, "VIRTUAL"))
  813. {
  814. FileMode = 'V';
  815. }
  816. else
  817. {
  818. WARN_BAD_FILE_MODE;
  819. return (l);
  820. }
  821. /*
  822. ---------------------------------------------
  823. FILE NUMBER
  824. ---------------------------------------------
  825. */
  826. if (line_skip_word (l, "AS") == FALSE)
  827. {
  828. WARN_SYNTAX_ERROR;
  829. return (l);
  830. }
  831. if (line_skip_word (l, "FILE") == FALSE)
  832. {
  833. WARN_SYNTAX_ERROR;
  834. return (l);
  835. }
  836. if (line_skip_FilenumChar (l))
  837. {
  838. /* OPTIONAL */
  839. }
  840. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  841. {
  842. WARN_BAD_FILE_NUMBER;
  843. return (l);
  844. }
  845. if (FileNumber <= 0)
  846. {
  847. WARN_BAD_FILE_NUMBER;
  848. return (l);
  849. }
  850. /*
  851. ---------------------------------------------
  852. RECORD LENGTH
  853. ---------------------------------------------
  854. */
  855. RecordLength = 0;
  856. /*
  857. ---------------------------------------------
  858. DO IT
  859. ---------------------------------------------
  860. */
  861. bwb_file_open (FileMode, FileNumber, FileName, RecordLength);
  862. free (FileName);
  863. FileName = NULL;
  864. return (l);
  865. }
  866. static LineType *
  867. M80_OPEN (LineType * l)
  868. {
  869. int FileNumber;
  870. char FileMode;
  871. int RecordLength;
  872. char *FileName;
  873. assert (l != NULL);
  874. assert(My != NULL);
  875. assert(My->CurrentVersion != NULL);
  876. FileNumber = 0;
  877. FileMode = 'R';
  878. RecordLength = 0;
  879. FileName = NULL;
  880. /*
  881. SYNTAX: OPEN filename$ [FOR mode] AS filenumber [LEN reclen]
  882. */
  883. /*
  884. ---------------------------------------------
  885. FILE NAME
  886. ---------------------------------------------
  887. */
  888. if (line_read_string_expression (l, &FileName) == FALSE)
  889. {
  890. WARN_BAD_FILE_NAME;
  891. return (l);
  892. }
  893. if (FileName == NULL)
  894. {
  895. WARN_BAD_FILE_NAME;
  896. return (l);
  897. }
  898. if (is_empty_string (FileName))
  899. {
  900. WARN_BAD_FILE_NAME;
  901. return (l);
  902. }
  903. /*
  904. ---------------------------------------------
  905. FILE MODE
  906. ---------------------------------------------
  907. */
  908. if (line_skip_word (l, "FOR"))
  909. {
  910. if (line_skip_word (l, "INPUT"))
  911. {
  912. FileMode = 'I';
  913. }
  914. else if (line_skip_word (l, "OUTPUT"))
  915. {
  916. FileMode = 'O';
  917. }
  918. else if (line_skip_word (l, "APPEND"))
  919. {
  920. FileMode = 'A';
  921. }
  922. else if (line_skip_word (l, "RANDOM"))
  923. {
  924. FileMode = 'R';
  925. }
  926. else if (line_skip_word (l, "BINARY"))
  927. {
  928. FileMode = 'B';
  929. }
  930. else if (line_skip_word (l, "VIRTUAL"))
  931. {
  932. FileMode = 'V';
  933. }
  934. else
  935. {
  936. WARN_BAD_FILE_MODE;
  937. return (l);
  938. }
  939. }
  940. if (My->CurrentVersion->OptionVersionValue & (H14))
  941. {
  942. /*
  943. **
  944. ** these are parsed but ignored
  945. **
  946. */
  947. if (line_skip_word (l, "ACCESS"))
  948. {
  949. /* ACCESS */
  950. if (line_skip_word (l, "READ"))
  951. {
  952. /* ACCESS READ */
  953. if (line_skip_word (l, "WRITE"))
  954. {
  955. /* ACCESS READ WRITE */
  956. }
  957. }
  958. else if (line_skip_word (l, "WRITE"))
  959. {
  960. /* ACCESS WRITE */
  961. }
  962. }
  963. if (line_skip_word (l, "SHARED"))
  964. {
  965. /* SHARED */
  966. }
  967. else if (line_skip_word (l, "LOCK"))
  968. {
  969. /* LOCK */
  970. if (line_skip_word (l, "READ"))
  971. {
  972. /* LOCK READ */
  973. }
  974. else if (line_skip_word (l, "WRITE"))
  975. {
  976. /* LOCK WRITE */
  977. }
  978. }
  979. }
  980. /*
  981. ---------------------------------------------
  982. FILE NUMBER
  983. ---------------------------------------------
  984. */
  985. if (line_skip_word (l, "AS") == FALSE)
  986. {
  987. WARN_SYNTAX_ERROR;
  988. return (l);
  989. }
  990. if (My->CurrentVersion->OptionVersionValue & (H14))
  991. {
  992. if (line_skip_word (l, "FILE"))
  993. {
  994. /* OPTIONAL */
  995. }
  996. }
  997. if (line_skip_FilenumChar (l))
  998. {
  999. /* OPTIONAL */
  1000. }
  1001. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  1002. {
  1003. WARN_BAD_FILE_NUMBER;
  1004. return (l);
  1005. }
  1006. if (FileNumber <= 0)
  1007. {
  1008. WARN_BAD_FILE_NUMBER;
  1009. return (l);
  1010. }
  1011. /*
  1012. ---------------------------------------------
  1013. RECORD LENGTH
  1014. ---------------------------------------------
  1015. */
  1016. RecordLength = 0;
  1017. if (line_skip_word (l, "LEN"))
  1018. {
  1019. if (line_skip_EqualChar (l))
  1020. {
  1021. /* OPTIONAL */
  1022. }
  1023. if (line_read_integer_expression (l, &RecordLength) == FALSE)
  1024. {
  1025. WARN_FIELD_OVERFLOW;
  1026. return (l);
  1027. }
  1028. if (RecordLength <= 0)
  1029. {
  1030. WARN_FIELD_OVERFLOW;
  1031. return (l);
  1032. }
  1033. }
  1034. /*
  1035. ---------------------------------------------
  1036. DO IT
  1037. ---------------------------------------------
  1038. */
  1039. bwb_file_open (FileMode, FileNumber, FileName, RecordLength);
  1040. free (FileName);
  1041. FileName = NULL;
  1042. return (l);
  1043. }
  1044. static LineType *
  1045. T79_OPEN (LineType * l)
  1046. {
  1047. int FileNumber;
  1048. char FileMode;
  1049. int RecordLength;
  1050. char *FileName;
  1051. assert (l != NULL);
  1052. FileNumber = 0;
  1053. FileMode = 'R';
  1054. RecordLength = 0;
  1055. FileName = NULL;
  1056. /*
  1057. SYNTAX: OPEN [NEW | OLD] filename$ AS filenumber
  1058. */
  1059. /*
  1060. ---------------------------------------------
  1061. FILE MODE
  1062. ---------------------------------------------
  1063. */
  1064. if (line_skip_word (l, "NEW"))
  1065. {
  1066. FileMode = 'O';
  1067. }
  1068. else if (line_skip_word (l, "OLD"))
  1069. {
  1070. FileMode = 'I';
  1071. }
  1072. else if (line_skip_word (l, "VIRTUAL"))
  1073. {
  1074. FileMode = 'V';
  1075. }
  1076. /*
  1077. ---------------------------------------------
  1078. FILE NAME
  1079. ---------------------------------------------
  1080. */
  1081. if (line_read_string_expression (l, &FileName) == FALSE)
  1082. {
  1083. WARN_BAD_FILE_NAME;
  1084. return (l);
  1085. }
  1086. if (FileName == NULL)
  1087. {
  1088. WARN_BAD_FILE_NAME;
  1089. return (l);
  1090. }
  1091. if (is_empty_string (FileName))
  1092. {
  1093. WARN_BAD_FILE_NAME;
  1094. return (l);
  1095. }
  1096. /*
  1097. ---------------------------------------------
  1098. FILE NUMBER
  1099. ---------------------------------------------
  1100. */
  1101. if (line_skip_word (l, "AS") == FALSE)
  1102. {
  1103. WARN_SYNTAX_ERROR;
  1104. return (l);
  1105. }
  1106. if (line_skip_FilenumChar (l))
  1107. {
  1108. /* OPTIONAL */
  1109. }
  1110. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  1111. {
  1112. WARN_BAD_FILE_NUMBER;
  1113. return (l);
  1114. }
  1115. if (FileNumber <= 0)
  1116. {
  1117. WARN_BAD_FILE_NUMBER;
  1118. return (l);
  1119. }
  1120. /*
  1121. ---------------------------------------------
  1122. RECORD LENGTH
  1123. ---------------------------------------------
  1124. */
  1125. RecordLength = 0;
  1126. /*
  1127. ---------------------------------------------
  1128. DO IT
  1129. ---------------------------------------------
  1130. */
  1131. bwb_file_open (FileMode, FileNumber, FileName, RecordLength);
  1132. free (FileName);
  1133. FileName = NULL;
  1134. return (l);
  1135. }
  1136. LineType *
  1137. bwb_OPEN (LineType * l)
  1138. {
  1139. assert (l != NULL);
  1140. assert(My != NULL);
  1141. assert(My->CurrentVersion != NULL);
  1142. if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  1143. {
  1144. return S70_OPEN (l);
  1145. }
  1146. if (My->CurrentVersion->OptionVersionValue & (D71))
  1147. {
  1148. return D71_OPEN (l);
  1149. }
  1150. if (My->CurrentVersion->OptionVersionValue & (C77))
  1151. {
  1152. return C77_OPEN (l);
  1153. }
  1154. if (My->CurrentVersion->OptionVersionValue & (H80))
  1155. {
  1156. return H80_OPEN (l);
  1157. }
  1158. if (My->CurrentVersion->OptionVersionValue & (T79 | R86))
  1159. {
  1160. return T79_OPEN (l);
  1161. }
  1162. /* default */
  1163. return M80_OPEN (l);
  1164. }
  1165. /***************************************************************
  1166. FUNCTION: bwb_name()
  1167. DESCRIPTION: This function implements the BASIC NAME
  1168. command to rename a disk file.
  1169. SYNTAX: NAME old_filename AS new_filename
  1170. ***************************************************************/
  1171. LineType *
  1172. bwb_NAME (LineType * l)
  1173. {
  1174. char *OldName;
  1175. char *NewName;
  1176. assert (l != NULL);
  1177. OldName = NULL;
  1178. NewName = NULL;
  1179. if (line_read_string_expression (l, &OldName) == FALSE)
  1180. {
  1181. WARN_SYNTAX_ERROR;
  1182. return (l);
  1183. }
  1184. if (is_empty_string (OldName))
  1185. {
  1186. WARN_BAD_FILE_NAME;
  1187. return (l);
  1188. }
  1189. if (line_skip_word (l, "AS") == FALSE)
  1190. {
  1191. WARN_SYNTAX_ERROR;
  1192. return (l);
  1193. }
  1194. if (line_read_string_expression (l, &NewName) == FALSE)
  1195. {
  1196. WARN_SYNTAX_ERROR;
  1197. return (l);
  1198. }
  1199. if (is_empty_string (NewName))
  1200. {
  1201. WARN_BAD_FILE_NAME;
  1202. return (l);
  1203. }
  1204. /* try to rename the file */
  1205. if (rename (OldName, NewName) != 0)
  1206. {
  1207. WARN_BAD_FILE_NAME;
  1208. }
  1209. free (OldName);
  1210. OldName = NULL;
  1211. free (NewName);
  1212. NewName = NULL;
  1213. return (l);
  1214. }
  1215. /* EOF */