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.
 
 
 
 
 
 

10216 lines
216 KiB

  1. /***************************************************************
  2. bwb_cmd.c Miscellaneous Commands
  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. /* Version 3.20b by Ken Martin Mainly corrected fprint and */
  31. /* fread and fgets to work in Ubuntu */
  32. /* */
  33. /*---------------------------------------------------------------*/
  34. #include "bwbasic.h"
  35. static void bwb_copy_file (char *Source, char *Target);
  36. static LineType *bwb_delete (LineType * l);
  37. static void bwb_display_file (char *Source);
  38. static LineType *bwb_load (LineType * Line, char *Prompt, int IsNew);
  39. static void bwb_new (void);
  40. static LineType *bwb_run_filename_or_linenumber (LineType * L);
  41. static LineType *bwb_save (LineType * Line, char *Prompt);
  42. static LineType *bwb_system (LineType * l);
  43. static LineType *bwb_xlist (LineType * l, FILE * file);
  44. static LineType *bwx_run (LineType * Line, char *ProgramName);
  45. static void CommandOptionVersion (int n, char *OutputLine);
  46. static void CommandUniqueID (int i, char *UniqueID);
  47. static void CommandVector (int i, char *Vector);
  48. static VariableType *find_variable_by_type (char *name, int dimensions,
  49. char VariableTypeCode);
  50. static void FixUp (char *Name);
  51. static LineType *H14_RENAME (LineType * l);
  52. static int line_read_matrix_redim (LineType * l, VariableType * v);
  53. static void ProcessEscapeChars (const char *Input, char *Output);
  54. static int xl_line (FILE * file, LineType * l);
  55. /*
  56. fprintf( file, "------------------------------------------------------------\n");
  57. 123456789012345678901234567890123456789012345678901234567890
  58. fprintf( file, " SYNTAX: %s\n", IntrinsicCommandTable[n].Syntax);
  59. sprintf( tbuf, "DESCRIPTION: %s\n", IntrinsicCommandTable[n].Description);
  60. fprintf( file, " " );
  61. fprintf( file, " [%c] %s\n", X, bwb_vertable[i].Name);
  62. 1234567890123
  63. */
  64. #define LEFT_LENGTH 13
  65. #define RIGHT_LENGTH 47
  66. #define TOTAL_LENGTH ( LEFT_LENGTH + RIGHT_LENGTH )
  67. /*
  68. --------------------------------------------------------------------------------------------
  69. EDIT, RENUM, RENUMBER
  70. --------------------------------------------------------------------------------------------
  71. */
  72. static LineType *
  73. bwx_run (LineType * Line, char *ProgramName)
  74. {
  75. size_t n;
  76. char *tbuf;
  77. int retn;
  78. assert (Line != NULL);
  79. assert( My != NULL );
  80. if (is_empty_string (ProgramName))
  81. {
  82. WARN_BAD_FILE_NAME;
  83. return (Line);
  84. }
  85. if (is_empty_string (My->ProgramFilename))
  86. {
  87. WARN_BAD_FILE_NAME;
  88. return (Line);
  89. }
  90. n = bwb_strlen (ProgramName) + 1 + bwb_strlen (My->ProgramFilename);
  91. if ((tbuf = (char *) calloc (n + 1 /* NulChar */ , sizeof (char))) == NULL)
  92. {
  93. WARN_OUT_OF_MEMORY;
  94. return (Line);
  95. }
  96. bwb_strcpy (tbuf, ProgramName);
  97. bwb_strcat (tbuf, " ");
  98. bwb_strcat (tbuf, My->ProgramFilename);
  99. retn=system (tbuf);
  100. free (tbuf);
  101. tbuf = NULL;
  102. /* open edited file for read */
  103. bwb_NEW (Line); /* Relocated by JBV (bug found by DD) */
  104. if (bwb_fload (NULL) == FALSE)
  105. {
  106. WARN_BAD_FILE_NAME;
  107. return (Line);
  108. }
  109. return (Line);
  110. }
  111. /***************************************************************
  112. FUNCTION: bwb_edit()
  113. DESCRIPTION: This function implements the BASIC EDIT
  114. program by shelling out to a default editor
  115. specified by the variable BWB.EDITOR$.
  116. SYNTAX: EDIT
  117. ***************************************************************/
  118. LineType *
  119. bwb_EDIT (LineType * Line)
  120. {
  121. /*
  122. SYNTAX: EDIT
  123. */
  124. assert (Line != NULL);
  125. assert( My != NULL );
  126. return bwx_run (Line, My->OptionEditString);
  127. }
  128. /***************************************************************
  129. FUNCTION: bwb_renum()
  130. DESCRIPTION: This function implements the BASIC RENUM
  131. command by shelling out to a default
  132. renumbering program called "renum".
  133. Added by JBV 10/95
  134. SYNTAX: RENUM
  135. ***************************************************************/
  136. LineType *
  137. bwb_RENUM (LineType * Line)
  138. {
  139. /*
  140. SYNTAX: RENUM
  141. */
  142. assert (Line != NULL);
  143. assert( My != NULL );
  144. return bwx_run (Line, My->OptionRenumString);
  145. }
  146. LineType *
  147. bwb_RENUMBER (LineType * Line)
  148. {
  149. /*
  150. SYNTAX: RENUMBER
  151. */
  152. assert (Line != NULL);
  153. assert( My != NULL );
  154. return bwx_run (Line, My->OptionRenumString);
  155. }
  156. /*
  157. --------------------------------------------------------------------------------------------
  158. REM
  159. --------------------------------------------------------------------------------------------
  160. */
  161. LineType *
  162. bwb_REM (LineType * L)
  163. {
  164. /*
  165. SYNTAX: REM comment
  166. */
  167. /*
  168. This line holds BASIC comments.
  169. */
  170. assert (L != NULL);
  171. line_skip_eol (L);
  172. return L;
  173. }
  174. /*
  175. --------------------------------------------------------------------------------------------
  176. IMAGE
  177. --------------------------------------------------------------------------------------------
  178. */
  179. LineType *
  180. bwb_IMAGE (LineType * L)
  181. {
  182. /*
  183. SYNTAX: IMAGE print-using-format
  184. */
  185. assert (L != NULL);
  186. line_skip_eol (L);
  187. return L;
  188. }
  189. /*
  190. --------------------------------------------------------------------------------------------
  191. LET
  192. --------------------------------------------------------------------------------------------
  193. */
  194. LineType *
  195. bwb_LET (LineType * L)
  196. {
  197. /*
  198. SYNTAX: LET variable [,...] = expression
  199. */
  200. VariableType *v;
  201. VariantType x;
  202. VariantType *X;
  203. assert (L != NULL);
  204. X = &x;
  205. CLEAR_VARIANT (X);
  206. /* read the list of variables */
  207. do
  208. {
  209. if ((v = line_read_scalar (L)) == NULL)
  210. {
  211. WARN_VARIABLE_NOT_DECLARED;
  212. goto EXIT;
  213. }
  214. }
  215. while (line_skip_seperator (L));
  216. /* skip the equal sign */
  217. if (line_skip_EqualChar (L))
  218. {
  219. /* OK */
  220. }
  221. else if (line_skip_word (L, "EQ"))
  222. {
  223. /* OK */
  224. }
  225. else if (line_skip_word (L, ".EQ."))
  226. {
  227. /* OK */
  228. }
  229. else
  230. {
  231. WARN_SYNTAX_ERROR;
  232. goto EXIT;
  233. }
  234. /* evaluate the expression */
  235. if (line_read_expression (L, X)) /* bwb_LET */
  236. {
  237. /* save the value */
  238. if (line_is_eol (L) == FALSE)
  239. {
  240. WARN_SYNTAX_ERROR;
  241. goto EXIT;
  242. }
  243. L->position = L->Startpos;
  244. /* for each variable, assign the value */
  245. do
  246. {
  247. /* read a variable */
  248. if ((v = line_read_scalar (L)) == NULL)
  249. {
  250. WARN_VARIABLE_NOT_DECLARED;
  251. goto EXIT;
  252. }
  253. assert (v != NULL);
  254. assert (X != NULL);
  255. if (var_set (v, X) == FALSE)
  256. {
  257. WARN_TYPE_MISMATCH;
  258. goto EXIT;
  259. }
  260. }
  261. while (line_skip_seperator (L));
  262. /* we are now at the equals sign */
  263. line_skip_eol (L);
  264. }
  265. else
  266. {
  267. WARN_SYNTAX_ERROR;
  268. }
  269. EXIT:
  270. RELEASE_VARIANT (X);
  271. return L;
  272. }
  273. LineType *
  274. bwb_CONST (LineType * L)
  275. {
  276. /*
  277. SYNTAX: CONST variable [,...] = expression
  278. */
  279. VariableType *v;
  280. VariantType x;
  281. VariantType *X;
  282. assert (L != NULL);
  283. X = &x;
  284. CLEAR_VARIANT (X);
  285. /* read the list of variables */
  286. do
  287. {
  288. if ((v = line_read_scalar (L)) == NULL)
  289. {
  290. WARN_VARIABLE_NOT_DECLARED;
  291. goto EXIT;
  292. }
  293. }
  294. while (line_skip_seperator (L));
  295. /* we are now at the equals sign */
  296. /* skip the equal sign */
  297. if (line_skip_EqualChar (L))
  298. {
  299. /* OK */
  300. }
  301. else if (line_skip_word (L, "EQ"))
  302. {
  303. /* OK */
  304. }
  305. else if (line_skip_word (L, ".EQ."))
  306. {
  307. /* OK */
  308. }
  309. else
  310. {
  311. WARN_SYNTAX_ERROR;
  312. goto EXIT;
  313. }
  314. /* evaluate the expression */
  315. if (line_read_expression (L, X)) /* bwb_LET */
  316. {
  317. /* save the value */
  318. if (line_is_eol (L) == FALSE)
  319. {
  320. WARN_SYNTAX_ERROR;
  321. goto EXIT;
  322. }
  323. /* for each variable, assign the value */
  324. L->position = L->Startpos;
  325. do
  326. {
  327. /* read a variable */
  328. if ((v = line_read_scalar (L)) == NULL)
  329. {
  330. WARN_VARIABLE_NOT_DECLARED;
  331. goto EXIT;
  332. }
  333. assert (v != NULL);
  334. assert (X != NULL);
  335. if (var_set (v, X) == FALSE)
  336. {
  337. WARN_TYPE_MISMATCH;
  338. goto EXIT;
  339. }
  340. }
  341. while (line_skip_seperator (L));
  342. /* we are now at the equals sign */
  343. /* for each variable, mark as constant */
  344. L->position = L->Startpos;
  345. do
  346. {
  347. /* read a variable */
  348. if ((v = line_read_scalar (L)) == NULL)
  349. {
  350. WARN_VARIABLE_NOT_DECLARED;
  351. goto EXIT;
  352. }
  353. assert (v != NULL);
  354. v->VariableFlags |= VARIABLE_CONSTANT;
  355. }
  356. while (line_skip_seperator (L));
  357. /* we are now at the equals sign */
  358. line_skip_eol (L);
  359. }
  360. else
  361. {
  362. WARN_SYNTAX_ERROR;
  363. }
  364. EXIT:
  365. RELEASE_VARIANT (X);
  366. return L;
  367. }
  368. LineType *
  369. bwb_DEC (LineType * L)
  370. {
  371. /*
  372. SYNTAX: DEC variable [,...]
  373. */
  374. VariableType *v;
  375. VariantType x;
  376. VariantType *X;
  377. assert (L != NULL);
  378. X = &x;
  379. CLEAR_VARIANT (X);
  380. /* read the list of variables */
  381. do
  382. {
  383. if ((v = line_read_scalar (L)) == NULL)
  384. {
  385. WARN_VARIABLE_NOT_DECLARED;
  386. goto EXIT;
  387. }
  388. if (v->VariableTypeCode == StringTypeCode)
  389. {
  390. WARN_TYPE_MISMATCH;
  391. goto EXIT;
  392. }
  393. }
  394. while (line_skip_seperator (L));
  395. /* we are now at the end of the line */
  396. if (line_is_eol (L) == FALSE)
  397. {
  398. WARN_SYNTAX_ERROR;
  399. goto EXIT;
  400. }
  401. L->position = L->Startpos;
  402. /* for each variable, assign the value */
  403. do
  404. {
  405. /* read a variable */
  406. if ((v = line_read_scalar (L)) == NULL)
  407. {
  408. WARN_VARIABLE_NOT_DECLARED;
  409. goto EXIT;
  410. }
  411. assert (v != NULL);
  412. assert (X != NULL);
  413. if (var_get (v, X) == FALSE)
  414. {
  415. WARN_VARIABLE_NOT_DECLARED;
  416. goto EXIT;
  417. }
  418. X->Number--;
  419. if (var_set (v, X) == FALSE)
  420. {
  421. WARN_VARIABLE_NOT_DECLARED;
  422. goto EXIT;
  423. }
  424. }
  425. while (line_skip_seperator (L));
  426. /* we are now at the end of the line */
  427. EXIT:
  428. RELEASE_VARIANT (X);
  429. return L;
  430. }
  431. LineType *
  432. bwb_INC (LineType * L)
  433. {
  434. /*
  435. SYNTAX: INC variable [,...]
  436. */
  437. VariableType *v;
  438. VariantType x;
  439. VariantType *X;
  440. assert (L != NULL);
  441. X = &x;
  442. CLEAR_VARIANT (X);
  443. /* read the list of variables */
  444. do
  445. {
  446. if ((v = line_read_scalar (L)) == NULL)
  447. {
  448. WARN_VARIABLE_NOT_DECLARED;
  449. goto EXIT;
  450. }
  451. if (v->VariableTypeCode == StringTypeCode)
  452. {
  453. WARN_TYPE_MISMATCH;
  454. goto EXIT;
  455. }
  456. }
  457. while (line_skip_seperator (L));
  458. /* we are now at the end of the line */
  459. if (line_is_eol (L) == FALSE)
  460. {
  461. WARN_SYNTAX_ERROR;
  462. goto EXIT;
  463. }
  464. L->position = L->Startpos;
  465. /* for each variable, assign the value */
  466. do
  467. {
  468. /* read a variable */
  469. if ((v = line_read_scalar (L)) == NULL)
  470. {
  471. WARN_VARIABLE_NOT_DECLARED;
  472. goto EXIT;
  473. }
  474. assert (v != NULL);
  475. assert (X != NULL);
  476. if (var_get (v, X) == FALSE)
  477. {
  478. WARN_VARIABLE_NOT_DECLARED;
  479. goto EXIT;
  480. }
  481. X->Number++;
  482. if (var_set (v, X) == FALSE)
  483. {
  484. WARN_VARIABLE_NOT_DECLARED;
  485. goto EXIT;
  486. }
  487. }
  488. while (line_skip_seperator (L));
  489. /* we are now at the end of the line */
  490. EXIT:
  491. RELEASE_VARIANT (X);
  492. return L;
  493. }
  494. /*
  495. --------------------------------------------------------------------------------------------
  496. GO
  497. --------------------------------------------------------------------------------------------
  498. */
  499. LineType *
  500. bwb_GO (LineType * L)
  501. {
  502. assert (L != NULL);
  503. WARN_SYNTAX_ERROR;
  504. return L;
  505. }
  506. LineType *
  507. bwb_THEN (LineType * L)
  508. {
  509. assert (L != NULL);
  510. WARN_SYNTAX_ERROR;
  511. return L;
  512. }
  513. LineType *
  514. bwb_TO (LineType * L)
  515. {
  516. assert (L != NULL);
  517. WARN_SYNTAX_ERROR;
  518. return L;
  519. }
  520. LineType *
  521. bwb_STEP (LineType * L)
  522. {
  523. assert (L != NULL);
  524. WARN_SYNTAX_ERROR;
  525. return L;
  526. }
  527. LineType *
  528. bwb_OF (LineType * L)
  529. {
  530. assert (L != NULL);
  531. WARN_SYNTAX_ERROR;
  532. return L;
  533. }
  534. LineType *
  535. bwb_AS (LineType * L)
  536. {
  537. assert (L != NULL);
  538. WARN_SYNTAX_ERROR;
  539. return L;
  540. }
  541. /*
  542. --------------------------------------------------------------------------------------------
  543. AUTO
  544. --------------------------------------------------------------------------------------------
  545. */
  546. LineType *
  547. bwb_BUILD (LineType * L)
  548. {
  549. /*
  550. SYNTAX: BUILD
  551. SYNTAX: BUILD start
  552. SYNTAX: BUILD start, increment
  553. */
  554. assert (L != NULL);
  555. return bwb_AUTO (L);
  556. }
  557. LineType *
  558. bwb_AUTO (LineType * L)
  559. {
  560. /*
  561. SYNTAX: AUTO
  562. SYNTAX: AUTO start
  563. SYNTAX: AUTO start , increment
  564. */
  565. assert (L != NULL);
  566. assert( My != NULL );
  567. My->AutomaticLineNumber = 0;
  568. My->AutomaticLineIncrement = 0;
  569. if (line_is_eol (L))
  570. {
  571. /* AUTO */
  572. My->AutomaticLineNumber = 10;
  573. My->AutomaticLineIncrement = 10;
  574. return L;
  575. }
  576. if (line_read_line_number (L, &My->AutomaticLineNumber))
  577. {
  578. /* AUTO ### ... */
  579. if (My->AutomaticLineNumber < MINLIN || My->AutomaticLineNumber > MAXLIN)
  580. {
  581. WARN_UNDEFINED_LINE;
  582. return L;
  583. }
  584. if (line_is_eol (L))
  585. {
  586. /* AUTO start */
  587. My->AutomaticLineIncrement = 10;
  588. return L;
  589. }
  590. else if (line_skip_seperator (L))
  591. {
  592. /* AUTO ### , ... */
  593. if (line_read_line_number (L, &My->AutomaticLineIncrement))
  594. {
  595. /* AUTO start , increment */
  596. if (My->AutomaticLineIncrement < MINLIN
  597. || My->AutomaticLineIncrement > MAXLIN)
  598. {
  599. WARN_UNDEFINED_LINE;
  600. return L;
  601. }
  602. return L;
  603. }
  604. }
  605. }
  606. My->AutomaticLineNumber = 0;
  607. My->AutomaticLineIncrement = 0;
  608. WARN_SYNTAX_ERROR;
  609. return L;
  610. }
  611. /*
  612. --------------------------------------------------------------------------------------------
  613. BREAK
  614. --------------------------------------------------------------------------------------------
  615. */
  616. LineType *
  617. bwb_BREAK (LineType * l)
  618. {
  619. /*
  620. SYNTAX: BREAK
  621. SYNTAX: BREAK line [,...]
  622. SYNTAX: BREAK line - line
  623. */
  624. assert (l != NULL);
  625. assert( My != NULL );
  626. assert( My->StartMarker != NULL );
  627. assert( My->EndMarker != NULL );
  628. if (line_is_eol (l))
  629. {
  630. /* BREAK */
  631. /* remove all line breaks */
  632. LineType *x;
  633. for (x = My->StartMarker->next; x != My->EndMarker; x = x->next)
  634. {
  635. x->LineFlags &= ~LINE_BREAK;
  636. }
  637. return (l);
  638. }
  639. else
  640. {
  641. do
  642. {
  643. int head;
  644. int tail;
  645. if (line_read_line_sequence (l, &head, &tail))
  646. {
  647. /* BREAK 's' - 'e' */
  648. LineType *x;
  649. if (head < MINLIN || head > MAXLIN)
  650. {
  651. WARN_UNDEFINED_LINE;
  652. return (l);
  653. }
  654. if (tail < MINLIN || tail > MAXLIN)
  655. {
  656. WARN_UNDEFINED_LINE;
  657. return (l);
  658. }
  659. if (head > tail)
  660. {
  661. WARN_SYNTAX_ERROR;
  662. return (l);
  663. }
  664. /* valid range */
  665. /* now go through and list appropriate lines */
  666. for (x = My->StartMarker->next; x != My->EndMarker; x = x->next)
  667. {
  668. if (head <= x->number && x->number <= tail)
  669. {
  670. if (x->LineFlags & LINE_NUMBERED)
  671. {
  672. x->LineFlags |= LINE_BREAK;
  673. }
  674. }
  675. }
  676. }
  677. else
  678. {
  679. WARN_SYNTAX_ERROR;
  680. return (l);
  681. }
  682. }
  683. while (line_skip_seperator (l));
  684. }
  685. return (l);
  686. }
  687. /*
  688. --------------------------------------------------------------------------------------------
  689. DSP
  690. --------------------------------------------------------------------------------------------
  691. */
  692. LineType *
  693. bwb_DSP (LineType * l)
  694. {
  695. /*
  696. SYNTAX: DSP
  697. SYNTAX: DSP variablename [,...]
  698. */
  699. VariableType *v;
  700. assert (l != NULL);
  701. assert( My != NULL );
  702. if (line_is_eol (l))
  703. {
  704. /* DSP */
  705. /* remove all variable displays */
  706. for (v = My->VariableHead; v != NULL; v = v->next)
  707. {
  708. v->VariableFlags &= ~VARIABLE_DISPLAY; /* bwb_DSP() */
  709. }
  710. return (l);
  711. }
  712. /* DSP variablename [,...] */
  713. do
  714. {
  715. char varname[NameLengthMax + 1];
  716. if (line_read_varname (l, varname))
  717. {
  718. /* mark the variable */
  719. for (v = My->VariableHead; v != NULL; v = v->next)
  720. {
  721. if (bwb_stricmp (v->name, varname) == 0)
  722. {
  723. v->VariableFlags |= VARIABLE_DISPLAY; /* bwb_DSP() */
  724. }
  725. }
  726. }
  727. }
  728. while (line_skip_seperator (l));
  729. return (l);
  730. }
  731. /*
  732. --------------------------------------------------------------------------------------------
  733. GOTO
  734. --------------------------------------------------------------------------------------------
  735. */
  736. LineType *
  737. bwb_GO_TO (LineType * l)
  738. {
  739. assert (l != NULL);
  740. return bwb_GOTO (l);
  741. }
  742. LineType *
  743. bwb_GOTO (LineType * l)
  744. {
  745. /*
  746. SYNTAX: GOTO line ' standard GOTO
  747. SYNTAX: GOTO expression ' calculated GOTO
  748. SYNTAX: GOTO expression OF line,... ' indexed GOTO, same as ON expression GOTO line,...
  749. SYNTAX: GOTO line [,...] ON expression ' indexed GOTO, same as ON expression GOTO line,...
  750. */
  751. int Value;
  752. int LineNumber;
  753. LineType *x;
  754. assert (l != NULL);
  755. assert( My != NULL );
  756. assert( My->CurrentVersion != NULL );
  757. Value = 0;
  758. LineNumber = 0;
  759. if (l->LineFlags & (LINE_USER))
  760. {
  761. WARN_ILLEGAL_DIRECT;
  762. return (l);
  763. }
  764. if (line_is_eol (l))
  765. {
  766. WARN_SYNTAX_ERROR;
  767. return (l);
  768. }
  769. if (line_read_integer_expression (l, &Value) == FALSE)
  770. {
  771. WARN_SYNTAX_ERROR;
  772. return (l);
  773. }
  774. if (line_is_eol (l))
  775. {
  776. /* GOTO linenumber */
  777. /* 'Value' is the line number */
  778. LineNumber = Value;
  779. }
  780. else if (line_skip_word (l, "OF"))
  781. {
  782. /* GOTO expression OF line, ... */
  783. /* 'Value' is an index into a list of line numbers */
  784. if (line_read_index_item (l, Value, &LineNumber))
  785. {
  786. /* found 'LineNumber' */
  787. }
  788. else if (My->CurrentVersion->OptionFlags & (OPTION_BUGS_ON) ) /* GOTO X OF ... */
  789. {
  790. /* silently fall-thru to the following line */
  791. line_skip_eol (l);
  792. return (l);
  793. }
  794. else
  795. {
  796. /* ERROR */
  797. WARN_UNDEFINED_LINE;
  798. return (l);
  799. }
  800. }
  801. else if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  802. {
  803. /* GOTO line [,...] ON expression */
  804. while (line_skip_seperator (l))
  805. {
  806. if (line_read_integer_expression (l, &Value) == FALSE)
  807. {
  808. WARN_SYNTAX_ERROR;
  809. return (l);
  810. }
  811. }
  812. if (line_skip_word (l, "ON") == FALSE)
  813. {
  814. WARN_SYNTAX_ERROR;
  815. return (l);
  816. }
  817. if (line_read_integer_expression (l, &Value) == FALSE)
  818. {
  819. WARN_SYNTAX_ERROR;
  820. return (l);
  821. }
  822. /* 'Value' is an index into a list of line numbers */
  823. l->position = l->Startpos;
  824. if (line_read_index_item (l, Value, &LineNumber))
  825. {
  826. /* found 'LineNumber' */
  827. }
  828. else
  829. {
  830. /* silently fall-thru to the following line */
  831. line_skip_eol (l);
  832. return (l);
  833. }
  834. line_skip_eol (l);
  835. }
  836. else
  837. {
  838. WARN_SYNTAX_ERROR;
  839. return (l);
  840. }
  841. if (LineNumber < MINLIN || LineNumber > MAXLIN)
  842. {
  843. WARN_UNDEFINED_LINE;
  844. return (l);
  845. }
  846. /* valid range */
  847. x = NULL;
  848. #if THE_PRICE_IS_RIGHT
  849. if (l->OtherLine != NULL)
  850. {
  851. /* look in the cache */
  852. if (l->OtherLine->number == LineNumber)
  853. {
  854. x = l->OtherLine; /* found in cache */
  855. }
  856. }
  857. #endif /* THE_PRICE_IS_RIGHT */
  858. if (x == NULL)
  859. {
  860. x = find_line_number (LineNumber); /* not found in the cache */
  861. }
  862. if (x != NULL)
  863. {
  864. /* FOUND */
  865. line_skip_eol (l);
  866. x->position = 0;
  867. #if THE_PRICE_IS_RIGHT
  868. l->OtherLine = x; /* save in cache */
  869. #endif /* THE_PRICE_IS_RIGHT */
  870. return x;
  871. }
  872. /* NOT FOUND */
  873. WARN_UNDEFINED_LINE;
  874. return (l);
  875. }
  876. /*
  877. --------------------------------------------------------------------------------------------
  878. GOSUB
  879. --------------------------------------------------------------------------------------------
  880. */
  881. LineType *
  882. bwb_GO_SUB (LineType * l)
  883. {
  884. assert (l != NULL);
  885. return bwb_GOSUB (l);
  886. }
  887. LineType *
  888. bwb_GOSUB (LineType * l)
  889. {
  890. /*
  891. SYNTAX: GOSUB line ' standard GOSUB
  892. SYNTAX: GOSUB expression ' calculated GOSUB
  893. SYNTAX: GOSUB expression OF line,... ' indexed GOSUB, same as ON expression GOSUB line,...
  894. SYNTAX: GOSUB line [,...] ON expression ' indexed GOSUB, same as ON expression GOSUB line,...
  895. */
  896. int Value;
  897. int LineNumber;
  898. LineType *x;
  899. assert (l != NULL);
  900. assert( My != NULL );
  901. assert( My->CurrentVersion != NULL );
  902. Value = 0;
  903. LineNumber = 0;
  904. x = NULL;
  905. if (l->LineFlags & (LINE_USER))
  906. {
  907. WARN_ILLEGAL_DIRECT;
  908. return (l);
  909. }
  910. if (line_is_eol (l))
  911. {
  912. WARN_SYNTAX_ERROR;
  913. return (l);
  914. }
  915. if (line_read_integer_expression (l, &Value) == FALSE)
  916. {
  917. WARN_SYNTAX_ERROR;
  918. return (l);
  919. }
  920. if (line_is_eol (l))
  921. {
  922. /* GOSUB linenumber */
  923. /* 'Value' is the line number */
  924. LineNumber = Value;
  925. }
  926. else if (line_skip_word (l, "OF"))
  927. {
  928. /* GOSUB linenumber [,...] OF expression */
  929. /* 'Value' is an index into a list of line numbers */
  930. if (line_read_index_item (l, Value, &LineNumber))
  931. {
  932. /* found 'LineNumber' */
  933. }
  934. else if (My->CurrentVersion->OptionFlags & (OPTION_BUGS_ON) ) /* GOSUB X OF ... */
  935. {
  936. /* silently fall-thru to the following line */
  937. line_skip_eol (l);
  938. return (l);
  939. }
  940. else
  941. {
  942. /* ERROR */
  943. WARN_UNDEFINED_LINE;
  944. return (l);
  945. }
  946. }
  947. else if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  948. {
  949. /* GOSUB line [,...] ON expression */
  950. while (line_skip_seperator (l))
  951. {
  952. if (line_read_integer_expression (l, &Value) == FALSE)
  953. {
  954. WARN_SYNTAX_ERROR;
  955. return (l);
  956. }
  957. }
  958. if (line_skip_word (l, "ON") == FALSE)
  959. {
  960. WARN_SYNTAX_ERROR;
  961. return (l);
  962. }
  963. if (line_read_integer_expression (l, &Value) == FALSE)
  964. {
  965. WARN_SYNTAX_ERROR;
  966. return (l);
  967. }
  968. /* 'Value' is an index into a list of line numbers */
  969. l->position = l->Startpos;
  970. if (line_read_index_item (l, Value, &LineNumber))
  971. {
  972. /* found 'LineNumber' */
  973. }
  974. else
  975. {
  976. /* silently fall-thru to the following line */
  977. line_skip_eol (l);
  978. return (l);
  979. }
  980. line_skip_eol (l);
  981. }
  982. else
  983. {
  984. WARN_SYNTAX_ERROR;
  985. return (l);
  986. }
  987. if (LineNumber < MINLIN || LineNumber > MAXLIN)
  988. {
  989. WARN_UNDEFINED_LINE;
  990. return (l);
  991. }
  992. /* valid range */
  993. x = NULL;
  994. #if THE_PRICE_IS_RIGHT
  995. if (l->OtherLine != NULL)
  996. {
  997. /* look in the cache */
  998. if (l->OtherLine->number == LineNumber)
  999. {
  1000. x = l->OtherLine; /* found in cache */
  1001. }
  1002. }
  1003. #endif /* THE_PRICE_IS_RIGHT */
  1004. if (x == NULL)
  1005. {
  1006. x = find_line_number (LineNumber); /* not found in the cache */
  1007. }
  1008. if (x != NULL)
  1009. {
  1010. /* FOUND */
  1011. line_skip_eol (l);
  1012. /* save current stack level */
  1013. My->StackHead->line = l;
  1014. /* increment exec stack */
  1015. if (bwb_incexec ())
  1016. {
  1017. /* set the new position to x and return x */
  1018. x->position = 0;
  1019. My->StackHead->line = x;
  1020. My->StackHead->ExecCode = EXEC_GOSUB;
  1021. #if THE_PRICE_IS_RIGHT
  1022. l->OtherLine = x; /* save in cache */
  1023. #endif /* THE_PRICE_IS_RIGHT */
  1024. return x;
  1025. }
  1026. else
  1027. {
  1028. /* ERROR */
  1029. WARN_OUT_OF_MEMORY;
  1030. return My->EndMarker;
  1031. }
  1032. }
  1033. /* NOT FOUND */
  1034. WARN_UNDEFINED_LINE;
  1035. return (l);
  1036. }
  1037. /*
  1038. --------------------------------------------------------------------------------------------
  1039. RETURN
  1040. --------------------------------------------------------------------------------------------
  1041. */
  1042. LineType *
  1043. bwb_RETURN (LineType * l)
  1044. {
  1045. /*
  1046. SYNTAX: RETURN
  1047. */
  1048. assert (l != NULL);
  1049. assert (My != NULL);
  1050. assert (My->CurrentVersion != NULL);
  1051. assert (My->StackHead != NULL);
  1052. if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  1053. {
  1054. /* RETURN [comment] */
  1055. line_skip_eol (l);
  1056. }
  1057. if (My->CurrentVersion->OptionVersionValue & (C77))
  1058. {
  1059. /* CBASIC-II: RETURN exits the first FUNCTION or GOSUB */
  1060. while (My->StackHead->ExecCode != EXEC_GOSUB
  1061. && My->StackHead->ExecCode != EXEC_FUNCTION)
  1062. {
  1063. bwb_decexec ();
  1064. if (My->StackHead == NULL)
  1065. {
  1066. WARN_RETURN_WITHOUT_GOSUB;
  1067. return (l);
  1068. }
  1069. if (My->StackHead->ExecCode == EXEC_NORM) /* End of the line? */
  1070. {
  1071. WARN_RETURN_WITHOUT_GOSUB;
  1072. return (l);
  1073. }
  1074. }
  1075. }
  1076. else
  1077. {
  1078. /* RETURN exits the first GOSUB */
  1079. while (My->StackHead->ExecCode != EXEC_GOSUB)
  1080. {
  1081. bwb_decexec ();
  1082. if (My->StackHead == NULL)
  1083. {
  1084. WARN_RETURN_WITHOUT_GOSUB;
  1085. return (l);
  1086. }
  1087. if (My->StackHead->ExecCode == EXEC_NORM) /* End of the line? */
  1088. {
  1089. WARN_RETURN_WITHOUT_GOSUB;
  1090. return (l);
  1091. }
  1092. }
  1093. }
  1094. /* decrement the EXEC stack counter */
  1095. bwb_decexec ();
  1096. assert (My->StackHead != NULL);
  1097. return My->StackHead->line;
  1098. }
  1099. /*
  1100. --------------------------------------------------------------------------------------------
  1101. POP
  1102. --------------------------------------------------------------------------------------------
  1103. */
  1104. LineType *
  1105. bwb_POP (LineType * l)
  1106. {
  1107. /*
  1108. SYNTAX: POP
  1109. */
  1110. StackType *StackItem;
  1111. assert (l != NULL);
  1112. assert (My != NULL);
  1113. assert (My->CurrentVersion != NULL);
  1114. assert (My->StackHead != NULL);
  1115. StackItem = My->StackHead;
  1116. while (StackItem->ExecCode != EXEC_GOSUB)
  1117. {
  1118. StackItem = StackItem->next;
  1119. if (StackItem == NULL)
  1120. {
  1121. WARN_RETURN_WITHOUT_GOSUB;
  1122. return (l);
  1123. }
  1124. if (StackItem->ExecCode == EXEC_NORM)
  1125. {
  1126. /* End of the line */
  1127. WARN_RETURN_WITHOUT_GOSUB;
  1128. return (l);
  1129. }
  1130. }
  1131. /* hide the GOSUB */
  1132. StackItem->ExecCode = EXEC_POPPED;
  1133. return (l);
  1134. }
  1135. /*
  1136. --------------------------------------------------------------------------------------------
  1137. ON
  1138. --------------------------------------------------------------------------------------------
  1139. */
  1140. LineType *
  1141. bwb_ON (LineType * l)
  1142. {
  1143. /*
  1144. SYNTAX: ON expression GOTO line,... ' expression evaluates to an index
  1145. SYNTAX: ON expression GOSUB line,... ' expression evaluates to an index
  1146. */
  1147. int Value;
  1148. int command;
  1149. int LineNumber;
  1150. LineType *x;
  1151. assert (l != NULL);
  1152. assert (My != NULL);
  1153. assert (My->CurrentVersion != NULL);
  1154. Value = 0;
  1155. command = 0;
  1156. LineNumber = 0;
  1157. x = NULL;
  1158. if (l->LineFlags & (LINE_USER))
  1159. {
  1160. WARN_ILLEGAL_DIRECT;
  1161. return (l);
  1162. }
  1163. if (line_is_eol (l))
  1164. {
  1165. WARN_SYNTAX_ERROR;
  1166. return (l);
  1167. }
  1168. if (line_read_integer_expression (l, &Value) == FALSE)
  1169. {
  1170. WARN_UNDEFINED_LINE;
  1171. return (l);
  1172. }
  1173. if (line_skip_word (l, "GO"))
  1174. {
  1175. if (line_skip_word (l, "TO"))
  1176. {
  1177. command = C_GOTO;
  1178. }
  1179. else if (line_skip_word (l, "SUB"))
  1180. {
  1181. command = C_GOSUB;
  1182. }
  1183. else
  1184. {
  1185. WARN_SYNTAX_ERROR;
  1186. return (l);
  1187. }
  1188. }
  1189. else if (line_skip_word (l, "GOTO"))
  1190. {
  1191. command = C_GOTO;
  1192. }
  1193. else if (line_skip_word (l, "GOSUB"))
  1194. {
  1195. command = C_GOSUB;
  1196. }
  1197. else
  1198. {
  1199. WARN_SYNTAX_ERROR;
  1200. return (l);
  1201. }
  1202. /* 'Value' is an index into a list of line numbers */
  1203. if (line_read_index_item (l, Value, &LineNumber))
  1204. {
  1205. /* found 'LineNumber' */
  1206. }
  1207. else if (My->CurrentVersion->OptionFlags & (OPTION_BUGS_ON) ) /* ON X GOTO|GOSUB ... */
  1208. {
  1209. /* silently fall-thru to the following line */
  1210. line_skip_eol (l);
  1211. return (l);
  1212. }
  1213. else
  1214. {
  1215. /* ERROR */
  1216. WARN_UNDEFINED_LINE;
  1217. return (l);
  1218. }
  1219. if (LineNumber < MINLIN || LineNumber > MAXLIN)
  1220. {
  1221. WARN_UNDEFINED_LINE;
  1222. return (l);
  1223. }
  1224. /* valid range */
  1225. x = NULL;
  1226. #if THE_PRICE_IS_RIGHT
  1227. if (l->OtherLine != NULL)
  1228. {
  1229. /* look in the cache */
  1230. if (l->OtherLine->number == LineNumber)
  1231. {
  1232. x = l->OtherLine; /* found in cache */
  1233. }
  1234. }
  1235. #endif /* THE_PRICE_IS_RIGHT */
  1236. if (x == NULL)
  1237. {
  1238. x = find_line_number (LineNumber); /* not found in the cache */
  1239. }
  1240. if (x != NULL)
  1241. {
  1242. /* FOUND */
  1243. if (command == C_GOTO)
  1244. {
  1245. /* ON ... GOTO ... */
  1246. line_skip_eol (l);
  1247. x->position = 0;
  1248. #if THE_PRICE_IS_RIGHT
  1249. l->OtherLine = x; /* save in cache */
  1250. #endif /* THE_PRICE_IS_RIGHT */
  1251. return x;
  1252. }
  1253. else if (command == C_GOSUB)
  1254. {
  1255. /* ON ... GOSUB ... */
  1256. line_skip_eol (l);
  1257. /* save current stack level */
  1258. My->StackHead->line = l;
  1259. /* increment exec stack */
  1260. if (bwb_incexec ())
  1261. {
  1262. /* set the new position to x and return x */
  1263. x->position = 0;
  1264. My->StackHead->line = x;
  1265. My->StackHead->ExecCode = EXEC_GOSUB;
  1266. #if THE_PRICE_IS_RIGHT
  1267. l->OtherLine = x; /* save in cache */
  1268. #endif /* THE_PRICE_IS_RIGHT */
  1269. return x;
  1270. }
  1271. else
  1272. {
  1273. /* ERROR */
  1274. WARN_OUT_OF_MEMORY;
  1275. return My->EndMarker;
  1276. }
  1277. }
  1278. else
  1279. {
  1280. /* ERROR */
  1281. WARN_SYNTAX_ERROR;
  1282. return (l);
  1283. }
  1284. }
  1285. /* NOT FOUND */
  1286. WARN_UNDEFINED_LINE;
  1287. return (l);
  1288. }
  1289. /*
  1290. --------------------------------------------------------------------------------------------
  1291. PAUSE
  1292. --------------------------------------------------------------------------------------------
  1293. */
  1294. LineType *
  1295. bwb_PAUSE (LineType * l)
  1296. {
  1297. /*
  1298. SYNTAX: PAUSE
  1299. */
  1300. char *pstring;
  1301. char *tbuf;
  1302. int tlen;
  1303. assert (l != NULL);
  1304. assert (My != NULL);
  1305. assert (My->CurrentVersion != NULL);
  1306. assert (My->ConsoleOutput != NULL);
  1307. assert (My->ConsoleInput != NULL);
  1308. pstring = My->ConsoleOutput;
  1309. tbuf = My->ConsoleInput;
  1310. tlen = MAX_LINE_LENGTH;
  1311. if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  1312. {
  1313. /* PAUSE [comment] */
  1314. line_skip_eol (l);
  1315. }
  1316. sprintf (pstring, "PAUSE AT %d\n", l->number);
  1317. bwx_input (pstring, FALSE, tbuf, tlen);
  1318. return (l);
  1319. }
  1320. /*
  1321. --------------------------------------------------------------------------------------------
  1322. STOP
  1323. --------------------------------------------------------------------------------------------
  1324. */
  1325. LineType *
  1326. bwb_STOP (LineType * l)
  1327. {
  1328. /*
  1329. SYNTAX: STOP
  1330. */
  1331. assert (l != NULL);
  1332. assert (My != NULL);
  1333. assert (My->CurrentVersion != NULL);
  1334. if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  1335. {
  1336. /* STOP [comment] */
  1337. line_skip_eol (l);
  1338. }
  1339. My->ContinueLine = l->next;
  1340. bwx_STOP (TRUE);
  1341. return bwb_END (l);
  1342. }
  1343. /*
  1344. --------------------------------------------------------------------------------------------
  1345. END
  1346. --------------------------------------------------------------------------------------------
  1347. */
  1348. LineType *
  1349. bwb_END (LineType * l)
  1350. {
  1351. /*
  1352. SYNTAX: END
  1353. */
  1354. assert (l != NULL);
  1355. assert (My != NULL);
  1356. assert (My->CurrentVersion != NULL);
  1357. if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  1358. {
  1359. /* END [comment] */
  1360. line_skip_eol (l);
  1361. }
  1362. My->ContinueLine = l->next;
  1363. bwx_STOP (FALSE);
  1364. return My->EndMarker;
  1365. }
  1366. /*
  1367. --------------------------------------------------------------------------------------------
  1368. RUN
  1369. --------------------------------------------------------------------------------------------
  1370. */
  1371. static LineType *
  1372. bwb_run_filename_or_linenumber (LineType * L)
  1373. {
  1374. LineType *current = NULL;
  1375. VariantType x;
  1376. VariantType *X;
  1377. assert (L != NULL);
  1378. assert (My != NULL);
  1379. assert (My->StartMarker != NULL);
  1380. X = &x;
  1381. CLEAR_VARIANT (X);
  1382. if (line_read_expression (L, X) == FALSE) /* bwb_run_filename_or_linenumber */
  1383. {
  1384. WARN_SYNTAX_ERROR;
  1385. return L;
  1386. }
  1387. if (X->VariantTypeCode == StringTypeCode)
  1388. {
  1389. /* RUN "filename" */
  1390. /* RUN A$ */
  1391. if (is_empty_string (X->Buffer))
  1392. {
  1393. WARN_BAD_FILE_NAME;
  1394. return L;
  1395. }
  1396. /* open the file and execute it */
  1397. bwb_new (); /* clear memory */
  1398. if (My->ProgramFilename != NULL)
  1399. {
  1400. free (My->ProgramFilename);
  1401. My->ProgramFilename = NULL;
  1402. }
  1403. My->ProgramFilename = bwb_strdup (X->Buffer);
  1404. if (bwb_fload (NULL) == FALSE)
  1405. {
  1406. WARN_BAD_FILE_NAME;
  1407. return L;
  1408. }
  1409. /*
  1410. **
  1411. ** FORCE SCAN
  1412. **
  1413. */
  1414. if (bwb_scan () == FALSE)
  1415. {
  1416. WARN_CANT_CONTINUE;
  1417. return L;
  1418. }
  1419. current = My->StartMarker->next;
  1420. }
  1421. else
  1422. {
  1423. /* RUN 100 */
  1424. /* RUN N */
  1425. /* execute the line */
  1426. int LineNumber;
  1427. LineNumber = (int) bwb_rint (X->Number);
  1428. /*
  1429. **
  1430. ** FORCE SCAN
  1431. **
  1432. */
  1433. if (bwb_scan () == FALSE)
  1434. {
  1435. WARN_CANT_CONTINUE;
  1436. goto EXIT;
  1437. }
  1438. current = find_line_number (LineNumber); /* RUN 100 */
  1439. if (current == NULL)
  1440. {
  1441. WARN_CANT_CONTINUE;
  1442. return L;
  1443. }
  1444. }
  1445. EXIT:
  1446. RELEASE_VARIANT (X);
  1447. return current;
  1448. }
  1449. LineType *
  1450. bwb_RUNNH (LineType * L)
  1451. {
  1452. assert (L != NULL);
  1453. return bwb_RUN (L);
  1454. }
  1455. LineType *
  1456. bwb_RUN (LineType * L)
  1457. {
  1458. /*
  1459. SYNTAX: RUN
  1460. SYNTAX: RUN filename$
  1461. SYNTAX: RUN linenumber
  1462. */
  1463. LineType *current;
  1464. assert (L != NULL);
  1465. assert (My != NULL);
  1466. assert (My->EndMarker != NULL);
  1467. assert (My->DefaultVariableType != NULL);
  1468. /* clear the STACK */
  1469. bwb_clrexec ();
  1470. if (bwb_incexec ())
  1471. {
  1472. /* OK */
  1473. }
  1474. else
  1475. {
  1476. /* ERROR */
  1477. WARN_OUT_OF_MEMORY;
  1478. return My->EndMarker;
  1479. }
  1480. if (line_is_eol (L))
  1481. {
  1482. /* RUN */
  1483. var_CLEAR ();
  1484. /* if( TRUE ) */
  1485. {
  1486. int n;
  1487. for (n = 0; n < 26; n++)
  1488. {
  1489. My->DefaultVariableType[n] = DoubleTypeCode;
  1490. }
  1491. }
  1492. /*
  1493. **
  1494. ** FORCE SCAN
  1495. **
  1496. */
  1497. if (bwb_scan () == FALSE)
  1498. {
  1499. WARN_CANT_CONTINUE;
  1500. return My->EndMarker;
  1501. }
  1502. current = My->StartMarker->next;
  1503. }
  1504. else
  1505. {
  1506. /* RUN 100 : RUN filename$ */
  1507. current = bwb_run_filename_or_linenumber (L);
  1508. if (current == NULL)
  1509. {
  1510. WARN_UNDEFINED_LINE;
  1511. return My->EndMarker;
  1512. }
  1513. }
  1514. current->position = 0;
  1515. assert (My->StackHead != NULL);
  1516. My->StackHead->line = current;
  1517. My->StackHead->ExecCode = EXEC_NORM;
  1518. /* RUN */
  1519. WARN_CLEAR; /* bwb_RUN */
  1520. My->ContinueLine = NULL;
  1521. SetOnError (0);
  1522. /* if( TRUE ) */
  1523. {
  1524. time_t t;
  1525. struct tm *lt;
  1526. time (&t);
  1527. lt = localtime (&t);
  1528. My->StartTimeInteger = lt->tm_hour;
  1529. My->StartTimeInteger *= 60;
  1530. My->StartTimeInteger += lt->tm_min;
  1531. My->StartTimeInteger *= 60;
  1532. My->StartTimeInteger += lt->tm_sec;
  1533. /* number of seconds since midnight */
  1534. }
  1535. return current;
  1536. }
  1537. /*
  1538. --------------------------------------------------------------------------------------------
  1539. CONT
  1540. --------------------------------------------------------------------------------------------
  1541. */
  1542. LineType *
  1543. bwb_CONTINUE (LineType * l)
  1544. {
  1545. /*
  1546. SYNTAX: CONTINUE
  1547. */
  1548. assert (l != NULL);
  1549. return bwb_CONT (l);
  1550. }
  1551. LineType *
  1552. bwb_CONT (LineType * l)
  1553. {
  1554. /*
  1555. SYNTAX: CONT
  1556. */
  1557. LineType *current;
  1558. assert (l != NULL);
  1559. assert (My != NULL);
  1560. assert (My->EndMarker != NULL);
  1561. assert (My->StartMarker != NULL);
  1562. current = NULL;
  1563. /* see if there is an element */
  1564. if (line_is_eol (l))
  1565. {
  1566. /* CONT */
  1567. current = My->ContinueLine;
  1568. }
  1569. else
  1570. {
  1571. /* CONT 100 */
  1572. int LineNumber;
  1573. LineNumber = 0;
  1574. if (line_read_line_number (l, &LineNumber))
  1575. {
  1576. current = find_line_number (LineNumber); /* CONT 100 */
  1577. }
  1578. }
  1579. if (current == NULL || current == My->EndMarker)
  1580. {
  1581. /* same as RUN */
  1582. current = My->StartMarker->next;
  1583. }
  1584. /*
  1585. **
  1586. ** FORCE SCAN
  1587. **
  1588. */
  1589. if (bwb_scan () == FALSE)
  1590. {
  1591. WARN_CANT_CONTINUE;
  1592. return (l);
  1593. }
  1594. current->position = 0;
  1595. bwb_clrexec ();
  1596. if (bwb_incexec ())
  1597. {
  1598. /* OK */
  1599. My->StackHead->line = current;
  1600. My->StackHead->ExecCode = EXEC_NORM;
  1601. }
  1602. else
  1603. {
  1604. /* ERROR */
  1605. WARN_OUT_OF_MEMORY;
  1606. return My->EndMarker;
  1607. }
  1608. /* CONT */
  1609. My->ContinueLine = NULL;
  1610. return current;
  1611. }
  1612. /*
  1613. --------------------------------------------------------------------------------------------
  1614. NEW
  1615. --------------------------------------------------------------------------------------------
  1616. */
  1617. void
  1618. bwb_xnew (LineType * l)
  1619. {
  1620. LineType *current;
  1621. LineType *previous;
  1622. int wait;
  1623. assert (l != NULL);
  1624. assert (My != NULL);
  1625. assert (My->EndMarker != NULL);
  1626. previous = NULL; /* JBV */
  1627. wait = TRUE;
  1628. for (current = l->next; current != My->EndMarker; current = current->next)
  1629. {
  1630. assert (current != NULL);
  1631. if (wait == FALSE)
  1632. {
  1633. free (previous);
  1634. previous = NULL;
  1635. }
  1636. wait = FALSE;
  1637. previous = current;
  1638. }
  1639. l->next = My->EndMarker;
  1640. }
  1641. static void
  1642. bwb_new ()
  1643. {
  1644. assert (My != NULL);
  1645. assert (My->StartMarker != NULL);
  1646. assert (My->DefaultVariableType != NULL);
  1647. /* clear program in memory */
  1648. bwb_xnew (My->StartMarker);
  1649. /* clear all variables */
  1650. var_CLEAR ();
  1651. /* if( TRUE ) */
  1652. {
  1653. int n;
  1654. for (n = 0; n < 26; n++)
  1655. {
  1656. My->DefaultVariableType[n] = DoubleTypeCode;
  1657. }
  1658. }
  1659. /* NEW */
  1660. WARN_CLEAR; /* bwb_new */
  1661. My->ContinueLine = NULL;
  1662. SetOnError (0);
  1663. }
  1664. LineType *
  1665. bwb_NEW (LineType * l)
  1666. {
  1667. /*
  1668. SYNTAX: NEW
  1669. */
  1670. assert (l != NULL);
  1671. assert (My != NULL);
  1672. assert (My->CurrentVersion != NULL);
  1673. bwb_new ();
  1674. if (My->CurrentVersion->OptionVersionValue & (D64 | G65 | G67 | G74))
  1675. {
  1676. if (line_is_eol (l))
  1677. {
  1678. /* NEW */
  1679. char *tbuf;
  1680. int tlen;
  1681. tbuf = My->ConsoleInput;
  1682. tlen = MAX_LINE_LENGTH;
  1683. /* prompt for the program name */
  1684. bwx_input ("NEW PROBLEM NAME:", FALSE, tbuf, tlen);
  1685. if (is_empty_string (tbuf))
  1686. {
  1687. WARN_BAD_FILE_NAME;
  1688. return l;
  1689. }
  1690. if (My->ProgramFilename != NULL)
  1691. {
  1692. free (My->ProgramFilename);
  1693. My->ProgramFilename = NULL;
  1694. }
  1695. My->ProgramFilename = bwb_strdup (tbuf);
  1696. }
  1697. else
  1698. {
  1699. /* NEW filename$ */
  1700. /* the parameter is the program name */
  1701. char *Value;
  1702. Value = NULL;
  1703. if (line_read_string_expression (l, &Value) == FALSE)
  1704. {
  1705. WARN_SYNTAX_ERROR;
  1706. return (l);
  1707. }
  1708. if (is_empty_string (Value))
  1709. {
  1710. WARN_BAD_FILE_NAME;
  1711. return l;
  1712. }
  1713. if (My->ProgramFilename != NULL)
  1714. {
  1715. free (My->ProgramFilename);
  1716. My->ProgramFilename = NULL;
  1717. }
  1718. My->ProgramFilename = Value;
  1719. }
  1720. }
  1721. else
  1722. {
  1723. /* ignore any parameters */
  1724. line_skip_eol (l);
  1725. }
  1726. return (l);
  1727. }
  1728. /*
  1729. --------------------------------------------------------------------------------------------
  1730. SCRATCH
  1731. --------------------------------------------------------------------------------------------
  1732. */
  1733. LineType *
  1734. bwb_SCRATCH (LineType * l)
  1735. {
  1736. /*
  1737. SYNTAX: SCRATCH -- same as NEW
  1738. SYNTAX: SCRATCH # filenumber -- close file and re-open for output
  1739. */
  1740. assert (l != NULL);
  1741. if (line_is_eol (l))
  1742. {
  1743. /* SCRATCH */
  1744. bwb_new ();
  1745. return (l);
  1746. }
  1747. if (line_skip_FilenumChar (l))
  1748. {
  1749. /* SCRATCH # X */
  1750. int FileNumber;
  1751. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  1752. {
  1753. WARN_BAD_FILE_NUMBER;
  1754. return (l);
  1755. }
  1756. if (FileNumber < 0)
  1757. {
  1758. /* SCRATCH # -1 is silently ignored */
  1759. return (l);
  1760. }
  1761. if (FileNumber == 0)
  1762. {
  1763. /* SCRATCH # 0 is silently ignored */
  1764. return (l);
  1765. }
  1766. My->CurrentFile = find_file_by_number (FileNumber);
  1767. if (My->CurrentFile == NULL)
  1768. {
  1769. WARN_BAD_FILE_NUMBER;
  1770. return (l);
  1771. }
  1772. if (My->CurrentFile->DevMode != DEVMODE_CLOSED)
  1773. {
  1774. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  1775. }
  1776. if (My->CurrentFile->cfp != NULL)
  1777. {
  1778. bwb_fclose (My->CurrentFile->cfp);
  1779. My->CurrentFile->cfp = NULL;
  1780. }
  1781. if (My->CurrentFile->buffer != NULL)
  1782. {
  1783. free (My->CurrentFile->buffer);
  1784. My->CurrentFile->buffer = NULL;
  1785. }
  1786. My->CurrentFile->width = 0;
  1787. My->CurrentFile->col = 1;
  1788. My->CurrentFile->row = 1;
  1789. My->CurrentFile->delimit = ',';
  1790. if (is_empty_string (My->CurrentFile->FileName))
  1791. {
  1792. WARN_BAD_FILE_NAME;
  1793. return (l);
  1794. }
  1795. if (bwb_strcmp (My->CurrentFile->FileName, "*") != 0)
  1796. {
  1797. if ((My->CurrentFile->cfp =
  1798. fopen (My->CurrentFile->FileName, "w")) == NULL)
  1799. {
  1800. WARN_BAD_FILE_NAME;
  1801. return (l);
  1802. }
  1803. My->CurrentFile->DevMode = DEVMODE_OUTPUT;
  1804. }
  1805. /* OK */
  1806. return (l);
  1807. }
  1808. WARN_SYNTAX_ERROR;
  1809. return (l);
  1810. }
  1811. /*
  1812. ============================================================================================
  1813. SYSTEM and so on
  1814. ============================================================================================
  1815. */
  1816. static LineType *
  1817. bwb_system (LineType * l)
  1818. {
  1819. /*
  1820. SYNTAX: SYSTEM
  1821. */
  1822. assert (l != NULL);
  1823. assert (My != NULL);
  1824. assert (My->SYSOUT != NULL);
  1825. assert (My->SYSOUT->cfp != NULL);
  1826. fprintf (My->SYSOUT->cfp, "\n");
  1827. fflush (My->SYSOUT->cfp);
  1828. bwx_terminate ();
  1829. return (l); /* never reached */
  1830. }
  1831. /*
  1832. --------------------------------------------------------------------------------------------
  1833. BYE
  1834. --------------------------------------------------------------------------------------------
  1835. */
  1836. LineType *
  1837. bwb_BYE (LineType * l)
  1838. {
  1839. /*
  1840. SYNTAX: BYE
  1841. */
  1842. assert (l != NULL);
  1843. return bwb_system (l);
  1844. }
  1845. /*
  1846. --------------------------------------------------------------------------------------------
  1847. DOS
  1848. --------------------------------------------------------------------------------------------
  1849. */
  1850. LineType *
  1851. bwb_DOS (LineType * l)
  1852. {
  1853. /*
  1854. SYNTAX: DOS
  1855. */
  1856. assert (l != NULL);
  1857. return bwb_system (l);
  1858. }
  1859. /*
  1860. --------------------------------------------------------------------------------------------
  1861. FLEX
  1862. --------------------------------------------------------------------------------------------
  1863. */
  1864. LineType *
  1865. bwb_FLEX (LineType * l)
  1866. {
  1867. /*
  1868. SYNTAX: FLEX
  1869. */
  1870. assert (l != NULL);
  1871. return bwb_system (l);
  1872. }
  1873. /*
  1874. --------------------------------------------------------------------------------------------
  1875. GOODBYE
  1876. --------------------------------------------------------------------------------------------
  1877. */
  1878. LineType *
  1879. bwb_GOODBYE (LineType * l)
  1880. {
  1881. /*
  1882. SYNTAX: GOODBYE
  1883. */
  1884. assert (l != NULL);
  1885. return bwb_system (l);
  1886. }
  1887. /*
  1888. --------------------------------------------------------------------------------------------
  1889. MON
  1890. --------------------------------------------------------------------------------------------
  1891. */
  1892. LineType *
  1893. bwb_MON (LineType * l)
  1894. {
  1895. /*
  1896. SYNTAX: MON
  1897. */
  1898. assert (l != NULL);
  1899. return bwb_system (l);
  1900. }
  1901. /*
  1902. --------------------------------------------------------------------------------------------
  1903. QUIT
  1904. --------------------------------------------------------------------------------------------
  1905. */
  1906. LineType *
  1907. bwb_QUIT (LineType * l)
  1908. {
  1909. /*
  1910. SYNTAX: QUIT
  1911. */
  1912. assert (l != NULL);
  1913. return bwb_system (l);
  1914. }
  1915. /*
  1916. --------------------------------------------------------------------------------------------
  1917. SYSTEM
  1918. --------------------------------------------------------------------------------------------
  1919. */
  1920. LineType *
  1921. bwb_SYSTEM (LineType * l)
  1922. {
  1923. /*
  1924. SYNTAX: SYSTEM
  1925. */
  1926. assert (l != NULL);
  1927. return bwb_system (l);
  1928. }
  1929. /*
  1930. ============================================================================================
  1931. LOAD and so on
  1932. ============================================================================================
  1933. */
  1934. static LineType *
  1935. bwb_load (LineType * Line, char *Prompt, int IsNew)
  1936. {
  1937. /*
  1938. **
  1939. ** load a BASIC program from a file
  1940. **
  1941. */
  1942. /*
  1943. SYNTAX: ... [filename$]
  1944. */
  1945. assert (Line != NULL);
  1946. assert (Prompt != NULL);
  1947. assert (My != NULL);
  1948. assert (My->CurrentVersion != NULL);
  1949. if (IsNew)
  1950. {
  1951. /* TRUE == LOAD */
  1952. bwb_new ();
  1953. }
  1954. else
  1955. {
  1956. /* FALSE == MERGE */
  1957. if (My->ProgramFilename != NULL)
  1958. {
  1959. free (My->ProgramFilename);
  1960. My->ProgramFilename = NULL;
  1961. }
  1962. }
  1963. if (line_is_eol (Line))
  1964. {
  1965. /* default is the last filename used by LOAD or SAVE */
  1966. /* if( My->CurrentVersion->OptionVersionValue & (D64 | G65 | G67 | G74) ) */
  1967. if (is_empty_string (My->ProgramFilename))
  1968. {
  1969. /* prompt for the program name */
  1970. char *tbuf;
  1971. int tlen;
  1972. tbuf = My->ConsoleInput;
  1973. tlen = MAX_LINE_LENGTH;
  1974. bwx_input (Prompt, FALSE, tbuf, tlen);
  1975. if (is_empty_string (tbuf))
  1976. {
  1977. WARN_BAD_FILE_NAME;
  1978. return (Line);
  1979. }
  1980. if (My->ProgramFilename != NULL)
  1981. {
  1982. free (My->ProgramFilename);
  1983. My->ProgramFilename = NULL;
  1984. }
  1985. My->ProgramFilename = bwb_strdup (tbuf);
  1986. }
  1987. fprintf (My->SYSOUT->cfp, "Loading %s\n", My->ProgramFilename);
  1988. ResetConsoleColumn ();
  1989. }
  1990. else
  1991. {
  1992. /* Get an argument for filename */
  1993. char *Value;
  1994. Value = NULL;
  1995. if (line_read_string_expression (Line, &Value) == FALSE)
  1996. {
  1997. WARN_SYNTAX_ERROR;
  1998. return (Line);
  1999. }
  2000. if (is_empty_string (Value))
  2001. {
  2002. WARN_BAD_FILE_NAME;
  2003. return (Line);
  2004. }
  2005. if (My->ProgramFilename != NULL)
  2006. {
  2007. free (My->ProgramFilename);
  2008. My->ProgramFilename = NULL;
  2009. }
  2010. My->ProgramFilename = Value;
  2011. }
  2012. if (bwb_fload (NULL) == FALSE)
  2013. {
  2014. WARN_BAD_FILE_NAME;
  2015. return (Line);
  2016. }
  2017. if (IsNew)
  2018. {
  2019. /* TRUE == LOAD */
  2020. }
  2021. else
  2022. {
  2023. /* FALSE == MERGE */
  2024. if (My->ProgramFilename != NULL)
  2025. {
  2026. free (My->ProgramFilename);
  2027. My->ProgramFilename = NULL;
  2028. }
  2029. }
  2030. /*
  2031. **
  2032. ** FORCE SCAN
  2033. **
  2034. */
  2035. if (bwb_scan () == FALSE)
  2036. {
  2037. WARN_CANT_CONTINUE;
  2038. }
  2039. return (Line);
  2040. }
  2041. /*
  2042. --------------------------------------------------------------------------------------------
  2043. CLOAD
  2044. --------------------------------------------------------------------------------------------
  2045. */
  2046. LineType *
  2047. bwb_CLOAD (LineType * Line)
  2048. {
  2049. /*
  2050. SYNTAX: CLOAD [filename$]
  2051. */
  2052. assert (Line != NULL);
  2053. return bwb_load (Line, "CLOAD FILE NAME:", TRUE);
  2054. }
  2055. /*
  2056. --------------------------------------------------------------------------------------------
  2057. LOAD
  2058. --------------------------------------------------------------------------------------------
  2059. */
  2060. LineType *
  2061. bwb_LOAD (LineType * Line)
  2062. {
  2063. /*
  2064. SYNTAX: LOAD [filename$]
  2065. */
  2066. assert (Line != NULL);
  2067. return bwb_load (Line, "LOAD FILE NAME:", TRUE);
  2068. }
  2069. /*
  2070. --------------------------------------------------------------------------------------------
  2071. MERGE
  2072. --------------------------------------------------------------------------------------------
  2073. */
  2074. LineType *
  2075. bwb_MERGE (LineType * l)
  2076. {
  2077. /*
  2078. SYNTAX: MERGE [filename$]
  2079. */
  2080. assert (l != NULL);
  2081. return bwb_load (l, "MERGE FILE NAME:", FALSE);
  2082. }
  2083. /*
  2084. --------------------------------------------------------------------------------------------
  2085. OLD
  2086. --------------------------------------------------------------------------------------------
  2087. */
  2088. LineType *
  2089. bwb_OLD (LineType * Line)
  2090. {
  2091. /*
  2092. SYNTAX: OLD [filename$]
  2093. */
  2094. assert (Line != NULL);
  2095. return bwb_load (Line, "OLD PROBLEM NAME:", TRUE);
  2096. }
  2097. /*
  2098. --------------------------------------------------------------------------------------------
  2099. TLOAD
  2100. --------------------------------------------------------------------------------------------
  2101. */
  2102. LineType *
  2103. bwb_TLOAD (LineType * Line)
  2104. {
  2105. /*
  2106. SYNTAX: TLOAD [filename$]
  2107. */
  2108. assert (Line != NULL);
  2109. return bwb_load (Line, "TLOAD FILE NAME:", TRUE);
  2110. }
  2111. /*
  2112. --------------------------------------------------------------------------------------------
  2113. RENAME
  2114. --------------------------------------------------------------------------------------------
  2115. */
  2116. static LineType *
  2117. H14_RENAME (LineType * l)
  2118. {
  2119. /*
  2120. SYNTAX: RENAME from$ TO to$
  2121. */
  2122. char *From;
  2123. char *To;
  2124. assert (l != NULL);
  2125. From = NULL;
  2126. To = NULL;
  2127. if (line_read_string_expression (l, &From) == FALSE)
  2128. {
  2129. WARN_SYNTAX_ERROR;
  2130. return (l);
  2131. }
  2132. if (is_empty_string (From))
  2133. {
  2134. WARN_BAD_FILE_NAME;
  2135. return (l);
  2136. }
  2137. if (line_skip_word (l, "TO") == FALSE)
  2138. {
  2139. WARN_SYNTAX_ERROR;
  2140. return (l);
  2141. }
  2142. if (line_read_string_expression (l, &To) == FALSE)
  2143. {
  2144. WARN_SYNTAX_ERROR;
  2145. return (l);
  2146. }
  2147. if (is_empty_string (To))
  2148. {
  2149. WARN_BAD_FILE_NAME;
  2150. return (l);
  2151. }
  2152. if (rename (From, To))
  2153. {
  2154. WARN_BAD_FILE_NAME;
  2155. return (l);
  2156. }
  2157. return (l);
  2158. }
  2159. LineType *
  2160. bwb_RENAME (LineType * l)
  2161. {
  2162. /*
  2163. SYNTAX: RENAME filename$
  2164. */
  2165. assert (l != NULL);
  2166. assert( My != NULL );
  2167. assert( My->CurrentVersion != NULL );
  2168. assert( My->ConsoleInput != NULL );
  2169. if (My->CurrentVersion->OptionVersionValue & (H14))
  2170. {
  2171. /* RENAME == change an exisiting file's name */
  2172. return H14_RENAME (l);
  2173. }
  2174. /* RENAME == change the BASIC program's name for a later SAVE */
  2175. if (line_is_eol (l))
  2176. {
  2177. /* RENAME */
  2178. if (My->CurrentVersion->OptionVersionValue & (D64 | G65 | G67 | G74))
  2179. {
  2180. /* prompt for the program name */
  2181. char *tbuf;
  2182. int tlen;
  2183. tbuf = My->ConsoleInput;
  2184. tlen = MAX_LINE_LENGTH;
  2185. bwx_input ("RENAME PROBLEM NAME:", FALSE, tbuf, tlen);
  2186. if (is_empty_string (tbuf))
  2187. {
  2188. WARN_BAD_FILE_NAME;
  2189. return (l);
  2190. }
  2191. if (My->ProgramFilename != NULL)
  2192. {
  2193. free (My->ProgramFilename);
  2194. My->ProgramFilename = NULL;
  2195. }
  2196. My->ProgramFilename = bwb_strdup (tbuf);
  2197. }
  2198. else
  2199. {
  2200. WARN_SYNTAX_ERROR;
  2201. return (l);
  2202. }
  2203. }
  2204. else
  2205. {
  2206. /* RENAME value$ */
  2207. char *Value;
  2208. Value = NULL;
  2209. if (line_read_string_expression (l, &Value) == FALSE)
  2210. {
  2211. WARN_SYNTAX_ERROR;
  2212. return (l);
  2213. }
  2214. if (is_empty_string (Value))
  2215. {
  2216. WARN_BAD_FILE_NAME;
  2217. return (l);
  2218. }
  2219. if (My->ProgramFilename != NULL)
  2220. {
  2221. free (My->ProgramFilename);
  2222. My->ProgramFilename = NULL;
  2223. }
  2224. My->ProgramFilename = Value;
  2225. }
  2226. return (l);
  2227. }
  2228. /*
  2229. --------------------------------------------------------------------------------------------
  2230. MAT
  2231. --------------------------------------------------------------------------------------------
  2232. */
  2233. extern void
  2234. Determinant (VariableType * v)
  2235. {
  2236. /* http://easy-learn-c-language.blogspot.com/search/label/Numerical Methods */
  2237. /* Numerical Methods: Determinant of nxn matrix using C */
  2238. DoubleType **matrix;
  2239. DoubleType ratio;
  2240. int i;
  2241. int j;
  2242. int k;
  2243. int n;
  2244. assert (v != NULL);
  2245. assert( My != NULL );
  2246. My->LastDeterminant = 0; /* default */
  2247. n = v->UBOUND[0] - v->LBOUND[0] + 1;
  2248. if ((matrix = (DoubleType **) calloc (n, sizeof (DoubleType *))) == NULL)
  2249. {
  2250. goto EXIT;
  2251. }
  2252. assert( matrix != NULL );
  2253. for (i = 0; i < n; i++)
  2254. {
  2255. if ((matrix[i] = (DoubleType *) calloc (n, sizeof (DoubleType))) == NULL)
  2256. {
  2257. goto EXIT;
  2258. }
  2259. assert( matrix[i] != NULL );
  2260. }
  2261. for (i = 0; i < n; i++)
  2262. {
  2263. for (j = 0; j < n; j++)
  2264. {
  2265. VariantType variant;
  2266. CLEAR_VARIANT (&variant);
  2267. v->VINDEX[0] = v->LBOUND[0] + i;
  2268. v->VINDEX[1] = v->LBOUND[1] + j;
  2269. if (var_get (v, &variant) == FALSE)
  2270. {
  2271. WARN_VARIABLE_NOT_DECLARED;
  2272. goto EXIT;
  2273. }
  2274. if (variant.VariantTypeCode == StringTypeCode)
  2275. {
  2276. WARN_TYPE_MISMATCH;
  2277. goto EXIT;
  2278. }
  2279. matrix[i][j] = variant.Number;
  2280. }
  2281. }
  2282. /* Conversion of matrix to upper triangular */
  2283. for (i = 0; i < n; i++)
  2284. {
  2285. for (j = 0; j < n; j++)
  2286. {
  2287. if (j > i)
  2288. {
  2289. if (matrix[i][i] == 0)
  2290. {
  2291. /* - Evaluation of an expression results in division
  2292. * by zero (nonfatal, the recommended recovery
  2293. * procedure is to supply machine infinity with the
  2294. * sign of the numerator and continue)
  2295. */
  2296. if (WARN_DIVISION_BY_ZERO)
  2297. {
  2298. /* ERROR */
  2299. goto EXIT;
  2300. }
  2301. /* CONTINUE */
  2302. if (matrix[j][i] < 0)
  2303. {
  2304. ratio = MINDBL;
  2305. }
  2306. else
  2307. {
  2308. ratio = MAXDBL;
  2309. }
  2310. }
  2311. else
  2312. {
  2313. ratio = matrix[j][i] / matrix[i][i];
  2314. }
  2315. for (k = 0; k < n; k++)
  2316. {
  2317. matrix[j][k] -= ratio * matrix[i][k];
  2318. }
  2319. }
  2320. }
  2321. }
  2322. My->LastDeterminant = 1; /* storage for determinant */
  2323. for (i = 0; i < n; i++)
  2324. {
  2325. DoubleType Value;
  2326. Value = matrix[i][i];
  2327. My->LastDeterminant *= Value;
  2328. }
  2329. EXIT:
  2330. if( matrix != NULL )
  2331. {
  2332. for (i = 0; i < n; i++)
  2333. {
  2334. if( matrix[i] != NULL )
  2335. {
  2336. free (matrix[i]);
  2337. /* matrix[i] = NULL; */
  2338. }
  2339. }
  2340. free (matrix);
  2341. /* matrix = NULL; */
  2342. }
  2343. }
  2344. int
  2345. InvertMatrix (VariableType * vOut, VariableType * vIn)
  2346. {
  2347. /* http://easy-learn-c-language.blogspot.com/search/label/Numerical Methods */
  2348. /* Numerical Methods: Inverse of nxn matrix using C */
  2349. int Result;
  2350. DoubleType **matrix;
  2351. DoubleType ratio;
  2352. int i;
  2353. int j;
  2354. int k;
  2355. int n;
  2356. assert (vOut != NULL);
  2357. assert (vIn != NULL);
  2358. Result = FALSE;
  2359. n = vIn->UBOUND[0] - vIn->LBOUND[0] + 1;
  2360. if ((matrix = (DoubleType **) calloc (n, sizeof (DoubleType *))) == NULL)
  2361. {
  2362. goto EXIT;
  2363. }
  2364. assert( matrix != NULL );
  2365. for (i = 0; i < n; i++)
  2366. {
  2367. if ((matrix[i] =
  2368. (DoubleType *) calloc (n + n, sizeof (DoubleType))) == NULL)
  2369. {
  2370. goto EXIT;
  2371. }
  2372. assert( matrix[i] != NULL );
  2373. }
  2374. for (i = 0; i < n; i++)
  2375. {
  2376. for (j = 0; j < n; j++)
  2377. {
  2378. VariantType variant;
  2379. CLEAR_VARIANT (&variant);
  2380. vIn->VINDEX[0] = vIn->LBOUND[0] + i;
  2381. vIn->VINDEX[1] = vIn->LBOUND[1] + j;
  2382. if (var_get (vIn, &variant) == FALSE)
  2383. {
  2384. WARN_VARIABLE_NOT_DECLARED;
  2385. goto EXIT;
  2386. }
  2387. if (variant.VariantTypeCode == StringTypeCode)
  2388. {
  2389. WARN_TYPE_MISMATCH;
  2390. goto EXIT;
  2391. }
  2392. matrix[i][j] = variant.Number;
  2393. }
  2394. }
  2395. for (i = 0; i < n; i++)
  2396. {
  2397. for (j = n; j < 2 * n; j++)
  2398. {
  2399. if (i == (j - n))
  2400. {
  2401. matrix[i][j] = 1.0;
  2402. }
  2403. else
  2404. {
  2405. matrix[i][j] = 0.0;
  2406. }
  2407. }
  2408. }
  2409. for (i = 0; i < n; i++)
  2410. {
  2411. for (j = 0; j < n; j++)
  2412. {
  2413. if (i != j)
  2414. {
  2415. if (matrix[i][i] == 0)
  2416. {
  2417. /* - Evaluation of an expression results in division
  2418. * by zero (nonfatal, the recommended recovery
  2419. * procedure is to supply machine infinity with the
  2420. * sign of the numerator and continue)
  2421. */
  2422. if (WARN_DIVISION_BY_ZERO)
  2423. {
  2424. /* ERROR */
  2425. goto EXIT;
  2426. }
  2427. /* CONTINUE */
  2428. if (matrix[j][i] < 0)
  2429. {
  2430. ratio = MINDBL;
  2431. }
  2432. else
  2433. {
  2434. ratio = MAXDBL;
  2435. }
  2436. }
  2437. else
  2438. {
  2439. ratio = matrix[j][i] / matrix[i][i];
  2440. }
  2441. for (k = 0; k < 2 * n; k++)
  2442. {
  2443. matrix[j][k] -= ratio * matrix[i][k];
  2444. }
  2445. }
  2446. }
  2447. }
  2448. for (i = 0; i < n; i++)
  2449. {
  2450. DoubleType a;
  2451. a = matrix[i][i];
  2452. if (a == 0)
  2453. {
  2454. /* - Evaluation of an expression results in division
  2455. * by zero (nonfatal, the recommended recovery
  2456. * procedure is to supply machine infinity with the
  2457. * sign of the numerator and continue)
  2458. */
  2459. if (WARN_DIVISION_BY_ZERO)
  2460. {
  2461. /* ERROR */
  2462. goto EXIT;
  2463. }
  2464. /* CONTINUE */
  2465. for (j = 0; j < 2 * n; j++)
  2466. {
  2467. if (matrix[i][j] < 0)
  2468. {
  2469. matrix[i][j] = MINDBL;
  2470. }
  2471. else
  2472. {
  2473. matrix[i][j] = MAXDBL;
  2474. }
  2475. }
  2476. }
  2477. else
  2478. {
  2479. for (j = 0; j < 2 * n; j++)
  2480. {
  2481. matrix[i][j] /= a;
  2482. }
  2483. }
  2484. }
  2485. for (i = 0; i < n; i++)
  2486. {
  2487. for (j = 0; j < n; j++)
  2488. {
  2489. VariantType variant;
  2490. CLEAR_VARIANT (&variant);
  2491. vOut->VINDEX[0] = vOut->LBOUND[0] + i;
  2492. vOut->VINDEX[1] = vOut->LBOUND[0] + j;
  2493. variant.VariantTypeCode = vOut->VariableTypeCode;
  2494. variant.Number = matrix[i][j + n];
  2495. if (var_set (vOut, &variant) == FALSE)
  2496. {
  2497. WARN_VARIABLE_NOT_DECLARED;
  2498. goto EXIT;
  2499. }
  2500. }
  2501. }
  2502. /*
  2503. **
  2504. ** Everything is OK
  2505. **
  2506. */
  2507. Result = TRUE;
  2508. EXIT:
  2509. if (matrix != NULL)
  2510. {
  2511. for (i = 0; i < n; i++)
  2512. {
  2513. if (matrix[i] != NULL)
  2514. {
  2515. free (matrix[i]);
  2516. /* matrix[i] = NULL; */
  2517. }
  2518. }
  2519. free (matrix);
  2520. /* matrix = NULL; */
  2521. }
  2522. return Result;
  2523. }
  2524. static int
  2525. line_read_matrix_redim (LineType * l, VariableType * v)
  2526. {
  2527. /* get OPTIONAL parameters if the variable is dimensioned */
  2528. assert (l != NULL);
  2529. assert (v != NULL);
  2530. if (line_peek_LparenChar (l))
  2531. {
  2532. /* get requested size, which is <= original array size */
  2533. size_t array_units;
  2534. int n;
  2535. int dimensions;
  2536. int LBOUND[MAX_DIMS];
  2537. int UBOUND[MAX_DIMS];
  2538. if (line_read_array_redim (l, &dimensions, LBOUND, UBOUND) == FALSE)
  2539. {
  2540. WARN_SYNTAX_ERROR;
  2541. return FALSE;
  2542. }
  2543. /* update array dimensions */
  2544. array_units = 1;
  2545. for (n = 0; n < dimensions; n++)
  2546. {
  2547. if (UBOUND[n] < LBOUND[n])
  2548. {
  2549. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2550. return FALSE;
  2551. }
  2552. array_units *= UBOUND[n] - LBOUND[n] + 1;
  2553. }
  2554. if (array_units > v->array_units)
  2555. {
  2556. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2557. return FALSE;
  2558. }
  2559. v->dimensions = dimensions;
  2560. for (n = 0; n < dimensions; n++)
  2561. {
  2562. v->LBOUND[n] = LBOUND[n];
  2563. v->UBOUND[n] = UBOUND[n];
  2564. }
  2565. }
  2566. return TRUE;
  2567. }
  2568. LineType *
  2569. bwb_MAT (LineType * l)
  2570. {
  2571. /*
  2572. SYNTAX: MAT A = CON
  2573. SYNTAX: MAT A = IDN
  2574. SYNTAX: MAT A = ZER
  2575. SYNTAX: MAT A = INV B
  2576. SYNTAX: MAT A = TRN B
  2577. SYNTAX: MAT A = (k) * B
  2578. SYNTAX: MAT A = B
  2579. SYNTAX: MAT A = B + C
  2580. SYNTAX: MAT A = B - C
  2581. SYNTAX: MAT A = B * C
  2582. */
  2583. VariableType *v_A;
  2584. char varname_A[NameLengthMax + 1];
  2585. assert (l != NULL);
  2586. /* just a placeholder for now. this will grow. */
  2587. if (line_read_varname (l, varname_A) == FALSE)
  2588. {
  2589. WARN_SYNTAX_ERROR;
  2590. return (l);
  2591. }
  2592. v_A = mat_find (varname_A);
  2593. if (v_A == NULL)
  2594. {
  2595. WARN_VARIABLE_NOT_DECLARED;
  2596. return (l);
  2597. }
  2598. /* variable MUST be numeric */
  2599. if (VAR_IS_STRING (v_A))
  2600. {
  2601. WARN_SYNTAX_ERROR;
  2602. return (l);
  2603. }
  2604. if (line_read_matrix_redim (l, v_A) == FALSE)
  2605. {
  2606. WARN_SYNTAX_ERROR;
  2607. return (l);
  2608. }
  2609. if (line_skip_EqualChar (l) == FALSE)
  2610. {
  2611. WARN_SYNTAX_ERROR;
  2612. return (l);
  2613. }
  2614. /* MAT A = ... */
  2615. if (line_skip_word (l, "CON"))
  2616. {
  2617. /* MAT A = CON */
  2618. /* MAT A = CON(I) */
  2619. /* MAT A = CON(I,J) */
  2620. /* MAT A = CON(I,J,K) */
  2621. /* OK */
  2622. int i;
  2623. int j;
  2624. int k;
  2625. if (line_read_matrix_redim (l, v_A) == FALSE)
  2626. {
  2627. WARN_SYNTAX_ERROR;
  2628. return (l);
  2629. }
  2630. /* both arrays are of the same size */
  2631. switch (v_A->dimensions)
  2632. {
  2633. case 1:
  2634. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2635. {
  2636. VariantType variant;
  2637. CLEAR_VARIANT (&variant);
  2638. variant.VariantTypeCode = v_A->VariableTypeCode;
  2639. variant.Number = 1;
  2640. v_A->VINDEX[0] = i;
  2641. if (var_set (v_A, &variant) == FALSE)
  2642. {
  2643. WARN_VARIABLE_NOT_DECLARED;
  2644. return (l);
  2645. }
  2646. }
  2647. break;
  2648. case 2:
  2649. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2650. {
  2651. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  2652. {
  2653. VariantType variant;
  2654. CLEAR_VARIANT (&variant);
  2655. variant.VariantTypeCode = v_A->VariableTypeCode;
  2656. variant.Number = 1;
  2657. v_A->VINDEX[0] = i;
  2658. v_A->VINDEX[1] = j;
  2659. if (var_set (v_A, &variant) == FALSE)
  2660. {
  2661. WARN_VARIABLE_NOT_DECLARED;
  2662. return (l);
  2663. }
  2664. }
  2665. }
  2666. break;
  2667. case 3:
  2668. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2669. {
  2670. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  2671. {
  2672. for (k = v_A->LBOUND[2]; k <= v_A->UBOUND[2]; k++)
  2673. {
  2674. VariantType variant;
  2675. CLEAR_VARIANT (&variant);
  2676. variant.VariantTypeCode = v_A->VariableTypeCode;
  2677. variant.Number = 1;
  2678. v_A->VINDEX[0] = i;
  2679. v_A->VINDEX[1] = j;
  2680. v_A->VINDEX[2] = k;
  2681. if (var_set (v_A, &variant) == FALSE)
  2682. {
  2683. WARN_VARIABLE_NOT_DECLARED;
  2684. return (l);
  2685. }
  2686. }
  2687. }
  2688. }
  2689. break;
  2690. default:
  2691. WARN_SYNTAX_ERROR;
  2692. return (l);
  2693. }
  2694. }
  2695. else if (line_skip_word (l, "IDN"))
  2696. {
  2697. /* MAT A = IDN */
  2698. /* MAT A = IDN(I,J) */
  2699. /* OK */
  2700. int i;
  2701. int j;
  2702. if (line_read_matrix_redim (l, v_A) == FALSE)
  2703. {
  2704. WARN_SYNTAX_ERROR;
  2705. return (l);
  2706. }
  2707. if (v_A->dimensions != 2)
  2708. {
  2709. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2710. return (l);
  2711. }
  2712. if (v_A->LBOUND[0] != v_A->LBOUND[1])
  2713. {
  2714. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2715. return (l);
  2716. }
  2717. if (v_A->UBOUND[0] != v_A->UBOUND[1])
  2718. {
  2719. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2720. return (l);
  2721. }
  2722. /* square matrix */
  2723. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2724. {
  2725. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  2726. {
  2727. VariantType variant;
  2728. CLEAR_VARIANT (&variant);
  2729. variant.VariantTypeCode = v_A->VariableTypeCode;
  2730. if (i == j)
  2731. {
  2732. variant.Number = 1;
  2733. }
  2734. else
  2735. {
  2736. variant.Number = 0;
  2737. }
  2738. v_A->VINDEX[0] = i;
  2739. v_A->VINDEX[1] = j;
  2740. if (var_set (v_A, &variant) == FALSE)
  2741. {
  2742. WARN_VARIABLE_NOT_DECLARED;
  2743. return (l);
  2744. }
  2745. }
  2746. }
  2747. }
  2748. else if (line_skip_word (l, "ZER"))
  2749. {
  2750. /* MAT A = ZER */
  2751. /* MAT A = ZER(I) */
  2752. /* MAT A = ZER(I,J) */
  2753. /* MAT A = ZER(I,J,K) */
  2754. /* OK */
  2755. int i;
  2756. int j;
  2757. int k;
  2758. if (line_read_matrix_redim (l, v_A) == FALSE)
  2759. {
  2760. WARN_SYNTAX_ERROR;
  2761. return (l);
  2762. }
  2763. /* both arrays are of the same size */
  2764. switch (v_A->dimensions)
  2765. {
  2766. case 1:
  2767. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2768. {
  2769. VariantType variant;
  2770. CLEAR_VARIANT (&variant);
  2771. variant.VariantTypeCode = v_A->VariableTypeCode;
  2772. variant.Number = 0;
  2773. v_A->VINDEX[0] = i;
  2774. if (var_set (v_A, &variant) == FALSE)
  2775. {
  2776. WARN_VARIABLE_NOT_DECLARED;
  2777. return (l);
  2778. }
  2779. }
  2780. break;
  2781. case 2:
  2782. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2783. {
  2784. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  2785. {
  2786. VariantType variant;
  2787. CLEAR_VARIANT (&variant);
  2788. variant.VariantTypeCode = v_A->VariableTypeCode;
  2789. variant.Number = 0;
  2790. v_A->VINDEX[0] = i;
  2791. v_A->VINDEX[1] = j;
  2792. if (var_set (v_A, &variant) == FALSE)
  2793. {
  2794. WARN_VARIABLE_NOT_DECLARED;
  2795. return (l);
  2796. }
  2797. }
  2798. }
  2799. break;
  2800. case 3:
  2801. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2802. {
  2803. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  2804. {
  2805. for (k = v_A->LBOUND[2]; k <= v_A->UBOUND[2]; k++)
  2806. {
  2807. VariantType variant;
  2808. CLEAR_VARIANT (&variant);
  2809. variant.VariantTypeCode = v_A->VariableTypeCode;
  2810. variant.Number = 0;
  2811. v_A->VINDEX[0] = i;
  2812. v_A->VINDEX[1] = j;
  2813. v_A->VINDEX[2] = k;
  2814. if (var_set (v_A, &variant) == FALSE)
  2815. {
  2816. WARN_VARIABLE_NOT_DECLARED;
  2817. return (l);
  2818. }
  2819. }
  2820. }
  2821. }
  2822. break;
  2823. default:
  2824. WARN_SYNTAX_ERROR;
  2825. return (l);
  2826. }
  2827. }
  2828. else if (line_skip_word (l, "INV"))
  2829. {
  2830. /* MAT A = INV B */
  2831. /* MAT A = INV( B ) */
  2832. /* OK */
  2833. VariableType *v_B;
  2834. char varname_B[NameLengthMax + 1];
  2835. if (v_A->dimensions != 2)
  2836. {
  2837. WARN_SYNTAX_ERROR;
  2838. return (l);
  2839. }
  2840. if (v_A->LBOUND[0] != v_A->LBOUND[1] || v_A->UBOUND[0] != v_A->UBOUND[1])
  2841. {
  2842. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2843. return (l);
  2844. }
  2845. if (line_skip_LparenChar (l))
  2846. {
  2847. /* optional */
  2848. }
  2849. if (line_read_varname (l, varname_B) == FALSE)
  2850. {
  2851. WARN_SYNTAX_ERROR;
  2852. return (l);
  2853. }
  2854. if ((v_B = mat_find (varname_B)) == NULL)
  2855. {
  2856. WARN_VARIABLE_NOT_DECLARED;
  2857. return (l);
  2858. }
  2859. /* variable MUST be numeric */
  2860. if (VAR_IS_STRING (v_B))
  2861. {
  2862. WARN_SYNTAX_ERROR;
  2863. return (l);
  2864. }
  2865. if (line_read_matrix_redim (l, v_B) == FALSE)
  2866. {
  2867. WARN_SYNTAX_ERROR;
  2868. return (l);
  2869. }
  2870. if (line_skip_RparenChar (l))
  2871. {
  2872. /* optional */
  2873. }
  2874. if (v_B->dimensions != 2)
  2875. {
  2876. WARN_SYNTAX_ERROR;
  2877. return (l);
  2878. }
  2879. if (v_B->LBOUND[0] != v_B->LBOUND[1] || v_B->UBOUND[0] != v_B->UBOUND[1])
  2880. {
  2881. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2882. return (l);
  2883. }
  2884. if (v_A->LBOUND[0] != v_B->LBOUND[0] || v_A->UBOUND[0] != v_B->UBOUND[0])
  2885. {
  2886. WARN_SUBSCRIPT_OUT_OF_RANGE;
  2887. return (l);
  2888. }
  2889. /* square matrix */
  2890. Determinant (v_B);
  2891. if (My->LastDeterminant == 0)
  2892. {
  2893. WARN_ILLEGAL_FUNCTION_CALL;
  2894. return (l);
  2895. }
  2896. if (InvertMatrix (v_A, v_B) == FALSE)
  2897. {
  2898. WARN_ILLEGAL_FUNCTION_CALL;
  2899. return (l);
  2900. }
  2901. }
  2902. else if (line_skip_word (l, "TRN"))
  2903. {
  2904. /* MAT A = TRN B */
  2905. /* MAT A = TRN( B ) */
  2906. /* OK */
  2907. int i;
  2908. int j;
  2909. VariableType *v_B;
  2910. char varname_B[NameLengthMax + 1];
  2911. if (v_A->dimensions != 2)
  2912. {
  2913. WARN_SYNTAX_ERROR;
  2914. return (l);
  2915. }
  2916. if (line_skip_LparenChar (l))
  2917. {
  2918. /* optional */
  2919. }
  2920. if (line_read_varname (l, varname_B) == FALSE)
  2921. {
  2922. WARN_SYNTAX_ERROR;
  2923. return (l);
  2924. }
  2925. if ((v_B = mat_find (varname_B)) == NULL)
  2926. {
  2927. WARN_VARIABLE_NOT_DECLARED;
  2928. return (l);
  2929. }
  2930. /* variable MUST be numeric */
  2931. if (VAR_IS_STRING (v_B))
  2932. {
  2933. WARN_SYNTAX_ERROR;
  2934. return (l);
  2935. }
  2936. if (line_read_matrix_redim (l, v_B) == FALSE)
  2937. {
  2938. WARN_SYNTAX_ERROR;
  2939. return (l);
  2940. }
  2941. if (line_skip_RparenChar (l))
  2942. {
  2943. /* optional */
  2944. }
  2945. if (v_B->dimensions != 2)
  2946. {
  2947. WARN_SYNTAX_ERROR;
  2948. return (l);
  2949. }
  2950. /* MxN */
  2951. if (v_A->LBOUND[0] != v_B->LBOUND[1] || v_A->UBOUND[0] != v_B->UBOUND[1])
  2952. {
  2953. WARN_SYNTAX_ERROR;
  2954. return (l);
  2955. }
  2956. if (v_A->LBOUND[1] != v_B->LBOUND[0] || v_A->UBOUND[1] != v_B->UBOUND[0])
  2957. {
  2958. WARN_SYNTAX_ERROR;
  2959. return (l);
  2960. }
  2961. /* transpose matrix */
  2962. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  2963. {
  2964. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  2965. {
  2966. VariantType variant;
  2967. CLEAR_VARIANT (&variant);
  2968. v_B->VINDEX[1] = i;
  2969. v_B->VINDEX[0] = j;
  2970. if (var_get (v_B, &variant) == FALSE)
  2971. {
  2972. WARN_VARIABLE_NOT_DECLARED;
  2973. return (l);
  2974. }
  2975. v_A->VINDEX[0] = i;
  2976. v_A->VINDEX[1] = j;
  2977. if (var_set (v_A, &variant) == FALSE)
  2978. {
  2979. WARN_VARIABLE_NOT_DECLARED;
  2980. return (l);
  2981. }
  2982. }
  2983. }
  2984. }
  2985. else if (line_peek_LparenChar (l))
  2986. {
  2987. /* MAT A = (k) * B */
  2988. DoubleType Multiplier;
  2989. VariableType *v_B;
  2990. int i;
  2991. int j;
  2992. int k;
  2993. char *E;
  2994. int p;
  2995. char varname_B[NameLengthMax + 1];
  2996. char *tbuf;
  2997. tbuf = My->ConsoleInput;
  2998. bwb_strcpy (tbuf, &(l->buffer[l->position]));
  2999. E = bwb_strrchr (tbuf, '*');
  3000. if (E == NULL)
  3001. {
  3002. WARN_SYNTAX_ERROR;
  3003. return (l);
  3004. }
  3005. *E = NulChar;
  3006. p = 0;
  3007. if (buff_read_numeric_expression (tbuf, &p, &Multiplier) == FALSE)
  3008. {
  3009. WARN_SYNTAX_ERROR;
  3010. return (l);
  3011. }
  3012. l->position += p;
  3013. if (line_skip_StarChar (l) == FALSE)
  3014. {
  3015. WARN_SYNTAX_ERROR;
  3016. return (l);
  3017. }
  3018. if (line_read_varname (l, varname_B) == FALSE)
  3019. {
  3020. WARN_SYNTAX_ERROR;
  3021. return (l);
  3022. }
  3023. if ((v_B = mat_find (varname_B)) == NULL)
  3024. {
  3025. WARN_VARIABLE_NOT_DECLARED;
  3026. return (l);
  3027. }
  3028. /* variable MUST be numeric */
  3029. if (VAR_IS_STRING (v_B))
  3030. {
  3031. WARN_SYNTAX_ERROR;
  3032. return (l);
  3033. }
  3034. if (line_read_matrix_redim (l, v_B) == FALSE)
  3035. {
  3036. WARN_SYNTAX_ERROR;
  3037. return (l);
  3038. }
  3039. if (v_A->dimensions != v_B->dimensions)
  3040. {
  3041. WARN_SYNTAX_ERROR;
  3042. return (l);
  3043. }
  3044. /* both arrays are of the same size */
  3045. switch (v_A->dimensions)
  3046. {
  3047. case 1:
  3048. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3049. {
  3050. VariantType variant;
  3051. CLEAR_VARIANT (&variant);
  3052. v_B->VINDEX[0] = i;
  3053. if (var_get (v_B, &variant) == FALSE)
  3054. {
  3055. WARN_VARIABLE_NOT_DECLARED;
  3056. return (l);
  3057. }
  3058. variant.Number *= Multiplier;
  3059. v_A->VINDEX[0] = i;
  3060. if (var_set (v_A, &variant) == FALSE)
  3061. {
  3062. WARN_VARIABLE_NOT_DECLARED;
  3063. return (l);
  3064. }
  3065. }
  3066. break;
  3067. case 2:
  3068. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3069. {
  3070. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3071. {
  3072. VariantType variant;
  3073. CLEAR_VARIANT (&variant);
  3074. v_B->VINDEX[0] = i;
  3075. v_B->VINDEX[1] = j;
  3076. if (var_get (v_B, &variant) == FALSE)
  3077. {
  3078. WARN_VARIABLE_NOT_DECLARED;
  3079. return (l);
  3080. }
  3081. variant.Number *= Multiplier;
  3082. v_A->VINDEX[0] = i;
  3083. v_A->VINDEX[1] = j;
  3084. if (var_set (v_A, &variant) == FALSE)
  3085. {
  3086. WARN_VARIABLE_NOT_DECLARED;
  3087. return (l);
  3088. }
  3089. }
  3090. }
  3091. break;
  3092. case 3:
  3093. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3094. {
  3095. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3096. {
  3097. for (k = v_A->LBOUND[2]; k <= v_A->UBOUND[2]; k++)
  3098. {
  3099. VariantType variant;
  3100. CLEAR_VARIANT (&variant);
  3101. v_B->VINDEX[0] = i;
  3102. v_B->VINDEX[1] = j;
  3103. v_B->VINDEX[2] = k;
  3104. if (var_get (v_B, &variant) == FALSE)
  3105. {
  3106. WARN_VARIABLE_NOT_DECLARED;
  3107. return (l);
  3108. }
  3109. variant.Number *= Multiplier;
  3110. v_A->VINDEX[0] = i;
  3111. v_A->VINDEX[1] = j;
  3112. v_A->VINDEX[2] = k;
  3113. if (var_set (v_A, &variant) == FALSE)
  3114. {
  3115. WARN_VARIABLE_NOT_DECLARED;
  3116. return (l);
  3117. }
  3118. }
  3119. }
  3120. }
  3121. break;
  3122. default:
  3123. WARN_SYNTAX_ERROR;
  3124. return (l);
  3125. }
  3126. }
  3127. else
  3128. {
  3129. /* MAT A = B */
  3130. /* MAT A = B + C */
  3131. /* MAT A = B - C */
  3132. /* MAT A = B * C */
  3133. VariableType *v_B;
  3134. char varname_B[NameLengthMax + 1];
  3135. if (line_read_varname (l, varname_B) == FALSE)
  3136. {
  3137. WARN_SYNTAX_ERROR;
  3138. return (l);
  3139. }
  3140. if ((v_B = mat_find (varname_B)) == NULL)
  3141. {
  3142. WARN_VARIABLE_NOT_DECLARED;
  3143. return (l);
  3144. }
  3145. /* variable MUST be numeric */
  3146. if (VAR_IS_STRING (v_B))
  3147. {
  3148. WARN_SYNTAX_ERROR;
  3149. return (l);
  3150. }
  3151. if (line_read_matrix_redim (l, v_B) == FALSE)
  3152. {
  3153. WARN_SYNTAX_ERROR;
  3154. return (l);
  3155. }
  3156. if (line_is_eol (l))
  3157. {
  3158. /* MAT A = B */
  3159. /* OK */
  3160. int i;
  3161. int j;
  3162. int k;
  3163. if (v_A->dimensions != v_B->dimensions)
  3164. {
  3165. WARN_SYNTAX_ERROR;
  3166. return (l);
  3167. }
  3168. /* both arrays are of the same size */
  3169. switch (v_A->dimensions)
  3170. {
  3171. case 1:
  3172. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3173. {
  3174. VariantType variant;
  3175. CLEAR_VARIANT (&variant);
  3176. v_B->VINDEX[0] = i;
  3177. if (var_get (v_B, &variant) == FALSE)
  3178. {
  3179. WARN_VARIABLE_NOT_DECLARED;
  3180. return (l);
  3181. }
  3182. v_A->VINDEX[0] = i;
  3183. if (var_set (v_A, &variant) == FALSE)
  3184. {
  3185. WARN_VARIABLE_NOT_DECLARED;
  3186. return (l);
  3187. }
  3188. }
  3189. break;
  3190. case 2:
  3191. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3192. {
  3193. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3194. {
  3195. VariantType variant;
  3196. CLEAR_VARIANT (&variant);
  3197. v_B->VINDEX[0] = i;
  3198. v_B->VINDEX[1] = j;
  3199. if (var_get (v_B, &variant) == FALSE)
  3200. {
  3201. WARN_VARIABLE_NOT_DECLARED;
  3202. return (l);
  3203. }
  3204. v_A->VINDEX[0] = i;
  3205. v_A->VINDEX[1] = j;
  3206. if (var_set (v_A, &variant) == FALSE)
  3207. {
  3208. WARN_VARIABLE_NOT_DECLARED;
  3209. return (l);
  3210. }
  3211. }
  3212. }
  3213. break;
  3214. case 3:
  3215. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3216. {
  3217. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3218. {
  3219. for (k = v_A->LBOUND[2]; k <= v_A->UBOUND[2]; k++)
  3220. {
  3221. VariantType variant;
  3222. CLEAR_VARIANT (&variant);
  3223. v_B->VINDEX[0] = i;
  3224. v_B->VINDEX[1] = j;
  3225. v_B->VINDEX[2] = k;
  3226. if (var_get (v_B, &variant) == FALSE)
  3227. {
  3228. WARN_VARIABLE_NOT_DECLARED;
  3229. return (l);
  3230. }
  3231. v_A->VINDEX[0] = i;
  3232. v_A->VINDEX[1] = j;
  3233. v_A->VINDEX[2] = k;
  3234. if (var_set (v_A, &variant) == FALSE)
  3235. {
  3236. WARN_VARIABLE_NOT_DECLARED;
  3237. return (l);
  3238. }
  3239. }
  3240. }
  3241. }
  3242. break;
  3243. default:
  3244. WARN_SYNTAX_ERROR;
  3245. return (l);
  3246. }
  3247. }
  3248. else if (line_skip_PlusChar (l))
  3249. {
  3250. /* MAT A = B + C */
  3251. /* OK */
  3252. int i;
  3253. int j;
  3254. int k;
  3255. VariableType *v_C;
  3256. char varname_C[NameLengthMax + 1];
  3257. if (v_A->dimensions != v_B->dimensions)
  3258. {
  3259. WARN_SYNTAX_ERROR;
  3260. return (l);
  3261. }
  3262. /* both arrays are of the same size */
  3263. if (line_read_varname (l, varname_C) == FALSE)
  3264. {
  3265. WARN_SYNTAX_ERROR;
  3266. return (l);
  3267. }
  3268. if ((v_C = mat_find (varname_C)) == NULL)
  3269. {
  3270. WARN_VARIABLE_NOT_DECLARED;
  3271. return (l);
  3272. }
  3273. /* variable MUST be numeric */
  3274. if (VAR_IS_STRING (v_C))
  3275. {
  3276. WARN_SYNTAX_ERROR;
  3277. return (l);
  3278. }
  3279. if (line_read_matrix_redim (l, v_C) == FALSE)
  3280. {
  3281. WARN_SYNTAX_ERROR;
  3282. return (l);
  3283. }
  3284. if (v_B->dimensions != v_C->dimensions)
  3285. {
  3286. WARN_SYNTAX_ERROR;
  3287. return (l);
  3288. }
  3289. /* both arrays are of the same size */
  3290. switch (v_A->dimensions)
  3291. {
  3292. case 1:
  3293. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3294. {
  3295. VariantType variant_L;
  3296. VariantType variant_R;
  3297. CLEAR_VARIANT (&variant_L);
  3298. CLEAR_VARIANT (&variant_R);
  3299. v_B->VINDEX[0] = i;
  3300. if (var_get (v_B, &variant_L) == FALSE)
  3301. {
  3302. WARN_VARIABLE_NOT_DECLARED;
  3303. return (l);
  3304. }
  3305. v_C->VINDEX[0] = i;
  3306. if (var_get (v_C, &variant_R) == FALSE)
  3307. {
  3308. WARN_VARIABLE_NOT_DECLARED;
  3309. return (l);
  3310. }
  3311. variant_L.Number += variant_R.Number;
  3312. v_A->VINDEX[0] = i;
  3313. if (var_set (v_A, &variant_L) == FALSE)
  3314. {
  3315. WARN_VARIABLE_NOT_DECLARED;
  3316. return (l);
  3317. }
  3318. }
  3319. break;
  3320. case 2:
  3321. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3322. {
  3323. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3324. {
  3325. VariantType variant_L;
  3326. VariantType variant_R;
  3327. CLEAR_VARIANT (&variant_L);
  3328. CLEAR_VARIANT (&variant_R);
  3329. v_B->VINDEX[0] = i;
  3330. v_B->VINDEX[1] = j;
  3331. if (var_get (v_B, &variant_L) == FALSE)
  3332. {
  3333. WARN_VARIABLE_NOT_DECLARED;
  3334. return (l);
  3335. }
  3336. v_C->VINDEX[0] = i;
  3337. v_C->VINDEX[1] = j;
  3338. if (var_get (v_C, &variant_R) == FALSE)
  3339. {
  3340. WARN_VARIABLE_NOT_DECLARED;
  3341. return (l);
  3342. }
  3343. variant_L.Number += variant_R.Number;
  3344. v_A->VINDEX[0] = i;
  3345. v_A->VINDEX[1] = j;
  3346. if (var_set (v_A, &variant_L) == FALSE)
  3347. {
  3348. WARN_VARIABLE_NOT_DECLARED;
  3349. return (l);
  3350. }
  3351. }
  3352. }
  3353. break;
  3354. case 3:
  3355. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3356. {
  3357. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3358. {
  3359. for (k = v_A->LBOUND[2]; k <= v_A->UBOUND[2]; k++)
  3360. {
  3361. VariantType variant_L;
  3362. VariantType variant_R;
  3363. CLEAR_VARIANT (&variant_L);
  3364. CLEAR_VARIANT (&variant_R);
  3365. v_B->VINDEX[0] = i;
  3366. v_B->VINDEX[1] = j;
  3367. v_B->VINDEX[2] = k;
  3368. if (var_get (v_B, &variant_L) == FALSE)
  3369. {
  3370. WARN_VARIABLE_NOT_DECLARED;
  3371. return (l);
  3372. }
  3373. v_C->VINDEX[0] = i;
  3374. v_C->VINDEX[1] = j;
  3375. v_C->VINDEX[2] = k;
  3376. if (var_get (v_C, &variant_R) == FALSE)
  3377. {
  3378. WARN_VARIABLE_NOT_DECLARED;
  3379. return (l);
  3380. }
  3381. variant_L.Number += variant_R.Number;
  3382. v_A->VINDEX[0] = i;
  3383. v_A->VINDEX[1] = j;
  3384. v_A->VINDEX[2] = k;
  3385. if (var_set (v_A, &variant_L) == FALSE)
  3386. {
  3387. WARN_VARIABLE_NOT_DECLARED;
  3388. return (l);
  3389. }
  3390. }
  3391. }
  3392. }
  3393. break;
  3394. default:
  3395. WARN_SYNTAX_ERROR;
  3396. return (l);
  3397. }
  3398. }
  3399. else if (line_skip_MinusChar (l))
  3400. {
  3401. /* MAT A = B - C */
  3402. /* OK */
  3403. int i;
  3404. int j;
  3405. int k;
  3406. VariableType *v_C;
  3407. char varname_C[NameLengthMax + 1];
  3408. if (v_A->dimensions != v_B->dimensions)
  3409. {
  3410. WARN_SYNTAX_ERROR;
  3411. return (l);
  3412. }
  3413. /* both arrays are of the same size */
  3414. if (line_read_varname (l, varname_C) == FALSE)
  3415. {
  3416. WARN_SYNTAX_ERROR;
  3417. return (l);
  3418. }
  3419. if ((v_C = mat_find (varname_C)) == NULL)
  3420. {
  3421. WARN_VARIABLE_NOT_DECLARED;
  3422. return (l);
  3423. }
  3424. /* variable MUST be numeric */
  3425. if (VAR_IS_STRING (v_C))
  3426. {
  3427. WARN_SYNTAX_ERROR;
  3428. return (l);
  3429. }
  3430. if (line_read_matrix_redim (l, v_C) == FALSE)
  3431. {
  3432. WARN_SYNTAX_ERROR;
  3433. return (l);
  3434. }
  3435. if (v_B->dimensions != v_C->dimensions)
  3436. {
  3437. WARN_SYNTAX_ERROR;
  3438. return (l);
  3439. }
  3440. /* both arrays are of the same dimension */
  3441. switch (v_A->dimensions)
  3442. {
  3443. case 1:
  3444. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3445. {
  3446. VariantType variant_L;
  3447. VariantType variant_R;
  3448. CLEAR_VARIANT (&variant_L);
  3449. CLEAR_VARIANT (&variant_R);
  3450. v_B->VINDEX[0] = i;
  3451. if (var_get (v_B, &variant_L) == FALSE)
  3452. {
  3453. WARN_VARIABLE_NOT_DECLARED;
  3454. return (l);
  3455. }
  3456. v_C->VINDEX[0] = i;
  3457. if (var_get (v_C, &variant_R) == FALSE)
  3458. {
  3459. WARN_VARIABLE_NOT_DECLARED;
  3460. return (l);
  3461. }
  3462. variant_L.Number -= variant_R.Number;
  3463. v_A->VINDEX[0] = i;
  3464. if (var_set (v_A, &variant_L) == FALSE)
  3465. {
  3466. WARN_VARIABLE_NOT_DECLARED;
  3467. return (l);
  3468. }
  3469. }
  3470. break;
  3471. case 2:
  3472. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3473. {
  3474. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3475. {
  3476. VariantType variant_L;
  3477. VariantType variant_R;
  3478. CLEAR_VARIANT (&variant_L);
  3479. CLEAR_VARIANT (&variant_R);
  3480. v_B->VINDEX[0] = i;
  3481. v_B->VINDEX[1] = j;
  3482. if (var_get (v_B, &variant_L) == FALSE)
  3483. {
  3484. WARN_VARIABLE_NOT_DECLARED;
  3485. return (l);
  3486. }
  3487. v_C->VINDEX[0] = i;
  3488. v_C->VINDEX[1] = j;
  3489. if (var_get (v_C, &variant_R) == FALSE)
  3490. {
  3491. WARN_VARIABLE_NOT_DECLARED;
  3492. return (l);
  3493. }
  3494. variant_L.Number -= variant_R.Number;
  3495. v_A->VINDEX[0] = i;
  3496. v_A->VINDEX[1] = j;
  3497. if (var_set (v_A, &variant_L) == FALSE)
  3498. {
  3499. WARN_VARIABLE_NOT_DECLARED;
  3500. return (l);
  3501. }
  3502. }
  3503. }
  3504. break;
  3505. case 3:
  3506. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3507. {
  3508. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3509. {
  3510. for (k = v_A->LBOUND[2]; k <= v_A->UBOUND[2]; k++)
  3511. {
  3512. VariantType variant_L;
  3513. VariantType variant_R;
  3514. CLEAR_VARIANT (&variant_L);
  3515. CLEAR_VARIANT (&variant_R);
  3516. v_B->VINDEX[0] = i;
  3517. v_B->VINDEX[1] = j;
  3518. v_B->VINDEX[2] = k;
  3519. if (var_get (v_B, &variant_L) == FALSE)
  3520. {
  3521. WARN_VARIABLE_NOT_DECLARED;
  3522. return (l);
  3523. }
  3524. v_C->VINDEX[0] = i;
  3525. v_C->VINDEX[1] = j;
  3526. v_C->VINDEX[2] = k;
  3527. if (var_get (v_C, &variant_R) == FALSE)
  3528. {
  3529. WARN_VARIABLE_NOT_DECLARED;
  3530. return (l);
  3531. }
  3532. variant_L.Number -= variant_R.Number;
  3533. v_A->VINDEX[0] = i;
  3534. v_A->VINDEX[1] = j;
  3535. v_A->VINDEX[2] = k;
  3536. if (var_set (v_A, &variant_L) == FALSE)
  3537. {
  3538. WARN_VARIABLE_NOT_DECLARED;
  3539. return (l);
  3540. }
  3541. }
  3542. }
  3543. }
  3544. break;
  3545. default:
  3546. WARN_SYNTAX_ERROR;
  3547. return (l);
  3548. }
  3549. }
  3550. else if (line_skip_StarChar (l))
  3551. {
  3552. /* MAT A = B * C */
  3553. int i;
  3554. int j;
  3555. int k;
  3556. VariableType *v_C;
  3557. char varname_C[NameLengthMax + 1];
  3558. if (v_A->dimensions != 2)
  3559. {
  3560. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3561. return (l);
  3562. }
  3563. if (v_B->dimensions != 2)
  3564. {
  3565. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3566. return (l);
  3567. }
  3568. if (line_read_varname (l, varname_C) == FALSE)
  3569. {
  3570. WARN_SYNTAX_ERROR;
  3571. return (l);
  3572. }
  3573. if ((v_C = mat_find (varname_C)) == NULL)
  3574. {
  3575. WARN_VARIABLE_NOT_DECLARED;
  3576. return (l);
  3577. }
  3578. /* variable MUST be numeric */
  3579. if (VAR_IS_STRING (v_C))
  3580. {
  3581. WARN_TYPE_MISMATCH;
  3582. return (l);
  3583. }
  3584. if (line_read_matrix_redim (l, v_C) == FALSE)
  3585. {
  3586. WARN_SYNTAX_ERROR;
  3587. return (l);
  3588. }
  3589. if (v_C->dimensions != 2)
  3590. {
  3591. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3592. return (l);
  3593. }
  3594. if (v_A->LBOUND[0] != v_B->LBOUND[0])
  3595. {
  3596. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3597. return (l);
  3598. }
  3599. if (v_A->UBOUND[0] != v_B->UBOUND[0])
  3600. {
  3601. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3602. return (l);
  3603. }
  3604. if (v_A->LBOUND[1] != v_C->LBOUND[1])
  3605. {
  3606. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3607. return (l);
  3608. }
  3609. if (v_A->UBOUND[1] != v_C->UBOUND[1])
  3610. {
  3611. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3612. return (l);
  3613. }
  3614. if (v_B->LBOUND[1] != v_C->LBOUND[0])
  3615. {
  3616. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3617. return (l);
  3618. }
  3619. if (v_B->UBOUND[1] != v_C->UBOUND[0])
  3620. {
  3621. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3622. return (l);
  3623. }
  3624. for (i = v_A->LBOUND[0]; i <= v_A->UBOUND[0]; i++)
  3625. {
  3626. for (j = v_A->LBOUND[1]; j <= v_A->UBOUND[1]; j++)
  3627. {
  3628. VariantType variant_A;
  3629. CLEAR_VARIANT (&variant_A);
  3630. variant_A.VariantTypeCode = v_A->VariableTypeCode;
  3631. variant_A.Number = 0;
  3632. v_A->VINDEX[0] = i;
  3633. v_A->VINDEX[1] = j;
  3634. if (var_set (v_A, &variant_A) == FALSE)
  3635. {
  3636. WARN_VARIABLE_NOT_DECLARED;
  3637. return (l);
  3638. }
  3639. for (k = v_C->LBOUND[0]; k <= v_C->UBOUND[0]; k++)
  3640. {
  3641. VariantType variant_B;
  3642. VariantType variant_C;
  3643. CLEAR_VARIANT (&variant_B);
  3644. CLEAR_VARIANT (&variant_C);
  3645. v_A->VINDEX[0] = i;
  3646. v_A->VINDEX[1] = j;
  3647. if (var_get (v_A, &variant_A) == FALSE)
  3648. {
  3649. WARN_VARIABLE_NOT_DECLARED;
  3650. return (l);
  3651. }
  3652. v_B->VINDEX[0] = i;
  3653. v_B->VINDEX[1] = k;
  3654. if (var_get (v_B, &variant_B) == FALSE)
  3655. {
  3656. WARN_VARIABLE_NOT_DECLARED;
  3657. return (l);
  3658. }
  3659. v_C->VINDEX[0] = k;
  3660. v_C->VINDEX[1] = j;
  3661. if (var_get (v_C, &variant_C) == FALSE)
  3662. {
  3663. WARN_VARIABLE_NOT_DECLARED;
  3664. return (l);
  3665. }
  3666. variant_A.Number += variant_B.Number * variant_C.Number;
  3667. v_A->VINDEX[0] = i;
  3668. v_A->VINDEX[1] = j;
  3669. if (var_set (v_A, &variant_A) == FALSE)
  3670. {
  3671. WARN_VARIABLE_NOT_DECLARED;
  3672. return (l);
  3673. }
  3674. }
  3675. }
  3676. }
  3677. }
  3678. else
  3679. {
  3680. WARN_SYNTAX_ERROR;
  3681. return (l);
  3682. }
  3683. }
  3684. return (l);
  3685. }
  3686. /*
  3687. --------------------------------------------------------------------------------------------
  3688. STORE
  3689. --------------------------------------------------------------------------------------------
  3690. */
  3691. LineType *
  3692. bwb_STORE (LineType * l)
  3693. {
  3694. /*
  3695. SYNTAX: STORE NumericArrayName
  3696. */
  3697. assert (l != NULL);
  3698. return bwb_CSAVE8 (l);
  3699. }
  3700. /*
  3701. --------------------------------------------------------------------------------------------
  3702. CSAVE*
  3703. --------------------------------------------------------------------------------------------
  3704. */
  3705. #define CSAVE_VERSION_1 0x20150218L
  3706. LineType *
  3707. bwb_CSAVE8 (LineType * l)
  3708. {
  3709. /*
  3710. SYNTAX: CSAVE* NumericArrayName
  3711. */
  3712. VariableType *v = NULL;
  3713. FILE *f;
  3714. unsigned long n;
  3715. size_t t;
  3716. char varname[NameLengthMax + 1];
  3717. assert (l != NULL);
  3718. if (line_read_varname (l, varname) == FALSE)
  3719. {
  3720. WARN_SYNTAX_ERROR;
  3721. return (l);
  3722. }
  3723. v = mat_find (varname);
  3724. if (v == NULL)
  3725. {
  3726. WARN_VARIABLE_NOT_DECLARED;
  3727. return (l);
  3728. }
  3729. /* variable MUST be numeric */
  3730. if (VAR_IS_STRING (v))
  3731. {
  3732. WARN_SYNTAX_ERROR;
  3733. return (l);
  3734. }
  3735. /* variable MUST be an array */
  3736. if (v->dimensions == 0)
  3737. {
  3738. WARN_SYNTAX_ERROR;
  3739. return (l);
  3740. }
  3741. if (line_read_matrix_redim (l, v) == FALSE)
  3742. {
  3743. WARN_SYNTAX_ERROR;
  3744. return (l);
  3745. }
  3746. /* variable storage is a mess, we bypass that tradition here. */
  3747. t = v->array_units;
  3748. if (t <= 1)
  3749. {
  3750. WARN_SYNTAX_ERROR;
  3751. return (l);
  3752. }
  3753. /* open file */
  3754. f = fopen (v->name, "w");
  3755. if (f == NULL)
  3756. {
  3757. WARN_SYNTAX_ERROR;
  3758. return (l);
  3759. }
  3760. /* write version number */
  3761. n = CSAVE_VERSION_1;
  3762. fwrite (&n, sizeof (long), 1, f);
  3763. /* write total number of elements */
  3764. fwrite (&t, sizeof (long), 1, f);
  3765. /* write data */
  3766. fwrite (v->Value.Number, sizeof (DoubleType), t, f);
  3767. /* OK */
  3768. bwb_fclose (f);
  3769. return (l);
  3770. }
  3771. /*
  3772. --------------------------------------------------------------------------------------------
  3773. RECALL
  3774. --------------------------------------------------------------------------------------------
  3775. */
  3776. LineType *
  3777. bwb_RECALL (LineType * l)
  3778. {
  3779. /*
  3780. SYNTAX: RECALL NumericArrayName
  3781. */
  3782. assert (l != NULL);
  3783. return bwb_CLOAD8 (l);
  3784. }
  3785. /*
  3786. --------------------------------------------------------------------------------------------
  3787. CLOAD*
  3788. --------------------------------------------------------------------------------------------
  3789. */
  3790. LineType *
  3791. bwb_CLOAD8 (LineType * l)
  3792. {
  3793. /*
  3794. SYNTAX: CLOAD* NumericArrayName
  3795. */
  3796. VariableType *v = NULL;
  3797. FILE *f;
  3798. unsigned long n;
  3799. size_t t;
  3800. char varname[NameLengthMax + 1];
  3801. int myfget;
  3802. assert (l != NULL);
  3803. if (line_read_varname (l, varname) == FALSE)
  3804. {
  3805. WARN_SYNTAX_ERROR;
  3806. return (l);
  3807. }
  3808. v = mat_find (varname);
  3809. if (v == NULL)
  3810. {
  3811. WARN_VARIABLE_NOT_DECLARED;
  3812. return (l);
  3813. }
  3814. /* variable MUST be numeric */
  3815. if (VAR_IS_STRING (v))
  3816. {
  3817. WARN_SYNTAX_ERROR;
  3818. return (l);
  3819. }
  3820. /* variable MUST be an array */
  3821. if (v->dimensions == 0)
  3822. {
  3823. WARN_SYNTAX_ERROR;
  3824. return (l);
  3825. }
  3826. if (line_read_matrix_redim (l, v) == FALSE)
  3827. {
  3828. WARN_SYNTAX_ERROR;
  3829. return (l);
  3830. }
  3831. /* variable storage is a mess, we bypass that tradition here. */
  3832. t = v->array_units;
  3833. if (t <= 1)
  3834. {
  3835. WARN_SYNTAX_ERROR;
  3836. return (l);
  3837. }
  3838. /* open file */
  3839. f = fopen (v->name, "r");
  3840. if (f == NULL)
  3841. {
  3842. WARN_BAD_FILE_NAME;
  3843. return (l);
  3844. }
  3845. /* read version number */
  3846. n = 0;
  3847. myfget=fread (&n, sizeof (long), 1, f);
  3848. if (n != CSAVE_VERSION_1)
  3849. {
  3850. bwb_fclose (f);
  3851. WARN_BAD_FILE_NAME;
  3852. return (l);
  3853. }
  3854. /* read total number of elements */
  3855. n = 0;
  3856. myfget=fread (&n, sizeof (long), 1, f);
  3857. if (n != t)
  3858. {
  3859. bwb_fclose (f);
  3860. WARN_BAD_FILE_NAME;
  3861. return (l);
  3862. }
  3863. /* read data */
  3864. myfget=fread (v->Value.Number, sizeof (DoubleType), t, f);
  3865. /* OK */
  3866. bwb_fclose (f);
  3867. return (l);
  3868. }
  3869. /*
  3870. ============================================================================================
  3871. SAVE and so on
  3872. ============================================================================================
  3873. */
  3874. static LineType *
  3875. bwb_save (LineType * Line, char *Prompt)
  3876. {
  3877. /*
  3878. SYNTAX: SAVE [filename$]
  3879. */
  3880. FILE *outfile;
  3881. assert (Line != NULL);
  3882. assert (Prompt != NULL);
  3883. assert( My != NULL );
  3884. assert( My->ConsoleInput != NULL );
  3885. assert( My->SYSOUT != NULL );
  3886. assert( My->SYSOUT->cfp != NULL );
  3887. /* Get an argument for filename */
  3888. if (line_is_eol (Line))
  3889. {
  3890. /* default is the last filename used by LOAD or SAVE */
  3891. if (is_empty_string (My->ProgramFilename) && Prompt != NULL)
  3892. {
  3893. /* prompt for the program name */
  3894. char *tbuf;
  3895. int tlen;
  3896. tbuf = My->ConsoleInput;
  3897. tlen = MAX_LINE_LENGTH;
  3898. bwx_input (Prompt, FALSE, tbuf, tlen);
  3899. if (is_empty_string (tbuf))
  3900. {
  3901. WARN_BAD_FILE_NAME;
  3902. return (Line);
  3903. }
  3904. if (My->ProgramFilename != NULL)
  3905. {
  3906. free (My->ProgramFilename);
  3907. My->ProgramFilename = NULL;
  3908. }
  3909. My->ProgramFilename = bwb_strdup (tbuf);
  3910. }
  3911. assert( My->ProgramFilename != NULL );
  3912. fprintf (My->SYSOUT->cfp, "Saving %s\n", My->ProgramFilename);
  3913. ResetConsoleColumn ();
  3914. }
  3915. else
  3916. {
  3917. char *Value;
  3918. Value = NULL;
  3919. if (line_read_string_expression (Line, &Value) == FALSE)
  3920. {
  3921. WARN_SYNTAX_ERROR;
  3922. return (Line);
  3923. }
  3924. if (is_empty_string (Value))
  3925. {
  3926. WARN_BAD_FILE_NAME;
  3927. return (Line);
  3928. }
  3929. if (My->ProgramFilename != NULL)
  3930. {
  3931. free (My->ProgramFilename);
  3932. }
  3933. My->ProgramFilename = Value;
  3934. }
  3935. assert( My->ProgramFilename != NULL );
  3936. if ((outfile = fopen (My->ProgramFilename, "w")) == NULL)
  3937. {
  3938. WARN_BAD_FILE_NAME;
  3939. return (Line);
  3940. }
  3941. bwb_xlist (Line, outfile);
  3942. bwb_fclose (outfile);
  3943. return (Line);
  3944. }
  3945. /*
  3946. --------------------------------------------------------------------------------------------
  3947. CSAVE
  3948. --------------------------------------------------------------------------------------------
  3949. */
  3950. LineType *
  3951. bwb_CSAVE (LineType * Line)
  3952. {
  3953. /*
  3954. SYNTAX: CSAVE [filename$]
  3955. */
  3956. assert (Line != NULL);
  3957. return bwb_save (Line, "CSAVE FILE NAME:");
  3958. }
  3959. /*
  3960. --------------------------------------------------------------------------------------------
  3961. REPLACE
  3962. --------------------------------------------------------------------------------------------
  3963. */
  3964. LineType *
  3965. bwb_REPLACE (LineType * Line)
  3966. {
  3967. /*
  3968. SYNTAX: REPLACE [filename$]
  3969. */
  3970. assert (Line != NULL);
  3971. return bwb_save (Line, "REPLACE FILE NAME:");
  3972. }
  3973. /*
  3974. --------------------------------------------------------------------------------------------
  3975. SAVE
  3976. --------------------------------------------------------------------------------------------
  3977. */
  3978. LineType *
  3979. bwb_SAVE (LineType * l)
  3980. {
  3981. /*
  3982. SYNTAX: SAVE [filename$]
  3983. */
  3984. assert (l != NULL);
  3985. return bwb_save (l, "SAVE FILE NAME:");
  3986. }
  3987. /*
  3988. --------------------------------------------------------------------------------------------
  3989. TSAVE
  3990. --------------------------------------------------------------------------------------------
  3991. */
  3992. LineType *
  3993. bwb_TSAVE (LineType * Line)
  3994. {
  3995. /*
  3996. SYNTAX: TSAVE [filename$]
  3997. */
  3998. assert (Line != NULL);
  3999. return bwb_save (Line, "TSAVE FILE NAME:");
  4000. }
  4001. /*
  4002. ============================================================================================
  4003. LIST and so on
  4004. ============================================================================================
  4005. */
  4006. static int
  4007. xl_line (FILE * file, LineType * l)
  4008. {
  4009. char LineExecuted;
  4010. char *C; /* start of comment text */
  4011. char *buffer; /* 0...99999 */
  4012. assert (file != NULL);
  4013. assert (l != NULL);
  4014. assert( My != NULL );
  4015. assert( My->NumLenBuffer != NULL );
  4016. assert( My->CurrentVersion != NULL );
  4017. assert( My->SYSOUT != NULL );
  4018. assert( My->SYSOUT->cfp != NULL );
  4019. assert( My->SYSPRN != NULL );
  4020. assert( My->SYSPRN->cfp != NULL );
  4021. /*
  4022. ** The only difference between LIST, LLIST and SAVE is:
  4023. ** LIST and LLIST display an '*'
  4024. ** when a line has been executed
  4025. ** and OPTION COVERAGE ON is enabled.
  4026. */
  4027. buffer = My->NumLenBuffer;
  4028. LineExecuted = ' ';
  4029. if (My->CurrentVersion->OptionFlags & (OPTION_COVERAGE_ON))
  4030. {
  4031. if (l->LineFlags & LINE_EXECUTED)
  4032. {
  4033. if (file == My->SYSOUT->cfp || file == My->SYSPRN->cfp)
  4034. {
  4035. /* LIST */
  4036. /* LLIST */
  4037. LineExecuted = '*';
  4038. }
  4039. else
  4040. {
  4041. /* SAVE */
  4042. /* EDIT implies SAVE */
  4043. }
  4044. }
  4045. }
  4046. C = l->buffer;
  4047. if (l->LineFlags & LINE_NUMBERED)
  4048. {
  4049. /* explicitly numbered */
  4050. sprintf (buffer, "%*d", LineNumberDigits, l->number);
  4051. /* ##### xxx */
  4052. }
  4053. else
  4054. {
  4055. /* implicitly numbered */
  4056. if (My->LastLineNumber == l->number)
  4057. {
  4058. /* multi-statement line */
  4059. if (l->cmdnum == C_REM
  4060. && IS_CHAR (l->buffer[0], My->CurrentVersion->OptionCommentChar))
  4061. {
  4062. /* trailing comment */
  4063. sprintf (buffer, "%*s%c", LineNumberDigits - 1, "",
  4064. My->CurrentVersion->OptionCommentChar);
  4065. C++; /* skip comment char */
  4066. while (*C == ' ')
  4067. {
  4068. /* skip spaces */
  4069. C++;
  4070. }
  4071. /* ____' xxx */
  4072. }
  4073. else if (My->CurrentVersion->OptionStatementChar)
  4074. {
  4075. /* all other commands, add a colon */
  4076. sprintf (buffer, "%*s%c", LineNumberDigits - 1, "",
  4077. My->CurrentVersion->OptionStatementChar);
  4078. /* ____: xxx */
  4079. }
  4080. else
  4081. {
  4082. /*
  4083. The user is trying to list a multi-line statement
  4084. in a dialect that does NOT support multi-line statements.
  4085. This could occur when LOADing in one dialect and then SAVEing as another dialect, such as:
  4086. OPTION VERSION BASIC-80
  4087. LOAD "TEST1.BAS"
  4088. 100 REM TEST
  4089. 110 PRINT:PRINT:PRINT
  4090. OPTION VERSION MARK-I
  4091. EDIT
  4092. 100 REM TEST
  4093. 110 PRINT
  4094. PRINT
  4095. PRINT
  4096. The only thing we can reasonably do is put spaces for the line number,
  4097. since the user will have to edit the results manually anyways.
  4098. */
  4099. sprintf (buffer, "%*s", LineNumberDigits, "");
  4100. /* _____ xxx */
  4101. }
  4102. }
  4103. else
  4104. {
  4105. /* single-statement line */
  4106. sprintf (buffer, "%*s", LineNumberDigits, "");
  4107. /* _____ xxx */
  4108. }
  4109. }
  4110. fprintf (file, "%s", buffer);
  4111. fprintf (file, "%c", LineExecuted);
  4112. /* if( TRUE ) */
  4113. {
  4114. /* %INCLUDE */
  4115. int i;
  4116. for (i = 0; i < l->IncludeLevel; i++)
  4117. {
  4118. fputc (' ', file);
  4119. }
  4120. }
  4121. if (My->OptionIndentInteger > 0)
  4122. {
  4123. int i;
  4124. for (i = 0; i < l->Indention; i++)
  4125. {
  4126. int j;
  4127. for (j = 0; j < My->OptionIndentInteger; j++)
  4128. {
  4129. fputc (' ', file);
  4130. }
  4131. }
  4132. }
  4133. fprintf (file, "%s\n", C);
  4134. My->LastLineNumber = l->number;
  4135. return TRUE;
  4136. }
  4137. static LineType *
  4138. bwb_xlist (LineType * l, FILE * file)
  4139. {
  4140. assert (l != NULL);
  4141. assert (file != NULL);
  4142. assert( My != NULL );
  4143. assert( My->StartMarker != NULL );
  4144. assert( My->EndMarker != NULL );
  4145. /*
  4146. **
  4147. ** FORCE SCAN
  4148. **
  4149. */
  4150. if (bwb_scan () == FALSE)
  4151. {
  4152. /*
  4153. **
  4154. ** we are used by bwb_SAVE and bwb_EDIT
  4155. **
  4156. WARN_CANT_CONTINUE;
  4157. return (l);
  4158. */
  4159. }
  4160. if (line_is_eol (l))
  4161. {
  4162. /* LIST */
  4163. LineType *x;
  4164. /* now go through and list appropriate lines */
  4165. My->LastLineNumber = -1;
  4166. for (x = My->StartMarker->next; x != My->EndMarker; x = x->next)
  4167. {
  4168. xl_line (file, x);
  4169. }
  4170. fprintf (file, "\n");
  4171. }
  4172. else
  4173. {
  4174. do
  4175. {
  4176. int head;
  4177. int tail;
  4178. if (line_read_line_sequence (l, &head, &tail))
  4179. {
  4180. /* LIST 's' - 'e' */
  4181. LineType *x;
  4182. if (head < MINLIN || head > MAXLIN)
  4183. {
  4184. WARN_UNDEFINED_LINE;
  4185. return (l);
  4186. }
  4187. if (tail < MINLIN || tail > MAXLIN)
  4188. {
  4189. WARN_UNDEFINED_LINE;
  4190. return (l);
  4191. }
  4192. if (head > tail)
  4193. {
  4194. WARN_UNDEFINED_LINE;
  4195. return (l);
  4196. }
  4197. /* valid range */
  4198. /* now go through and list appropriate lines */
  4199. My->LastLineNumber = -1;
  4200. for (x = My->StartMarker->next; x != My->EndMarker; x = x->next)
  4201. {
  4202. if (head <= x->number && x->number <= tail)
  4203. {
  4204. xl_line (file, x);
  4205. }
  4206. }
  4207. fprintf (file, "\n");
  4208. }
  4209. else
  4210. {
  4211. WARN_SYNTAX_ERROR;
  4212. return (l);
  4213. }
  4214. }
  4215. while (line_skip_seperator (l));
  4216. }
  4217. if (file == My->SYSOUT->cfp)
  4218. {
  4219. ResetConsoleColumn ();
  4220. }
  4221. return (l);
  4222. }
  4223. /*
  4224. --------------------------------------------------------------------------------------------
  4225. LIST
  4226. --------------------------------------------------------------------------------------------
  4227. */
  4228. LineType *
  4229. bwb_LIST (LineType * l)
  4230. {
  4231. /*
  4232. SYNTAX: LIST
  4233. SYNTAX: LIST line [,...]
  4234. SYNTAX: LIST line - line
  4235. */
  4236. assert (l != NULL);
  4237. return bwb_xlist (l, My->SYSOUT->cfp);
  4238. }
  4239. /*
  4240. --------------------------------------------------------------------------------------------
  4241. LISTNH
  4242. --------------------------------------------------------------------------------------------
  4243. */
  4244. LineType *
  4245. bwb_LISTNH (LineType * l)
  4246. {
  4247. /*
  4248. SYNTAX: LISTNH
  4249. SYNTAX: LISTNH line [,...]
  4250. SYNTAX: LISTNH line - line
  4251. */
  4252. assert (l != NULL);
  4253. return bwb_xlist (l, My->SYSOUT->cfp);
  4254. }
  4255. /*
  4256. --------------------------------------------------------------------------------------------
  4257. LLIST
  4258. --------------------------------------------------------------------------------------------
  4259. */
  4260. LineType *
  4261. bwb_LLIST (LineType * l)
  4262. {
  4263. /*
  4264. SYNTAX: LLIST
  4265. SYNTAX: LLIST line [,...]
  4266. SYNTAX: LLIST line - line
  4267. */
  4268. assert (l != NULL);
  4269. return bwb_xlist (l, My->SYSPRN->cfp);
  4270. }
  4271. /*
  4272. ============================================================================================
  4273. DELETE and so on
  4274. ============================================================================================
  4275. */
  4276. static LineType *
  4277. bwb_delete (LineType * l)
  4278. {
  4279. assert (l != NULL);
  4280. assert( My != NULL );
  4281. assert( My->CurrentVersion != NULL );
  4282. assert( My->StartMarker != NULL );
  4283. assert( My->EndMarker != NULL );
  4284. if (line_is_eol (l))
  4285. {
  4286. /* DELETE */
  4287. WARN_SYNTAX_ERROR;
  4288. return (l);
  4289. }
  4290. else if (My->CurrentVersion->OptionVersionValue & (C77))
  4291. {
  4292. /*
  4293. SYNTAX: DELETE filenum [,...]
  4294. */
  4295. do
  4296. {
  4297. int FileNumber;
  4298. FileNumber = 0;
  4299. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  4300. {
  4301. WARN_BAD_FILE_NUMBER;
  4302. return (l);
  4303. }
  4304. if (FileNumber <= 0)
  4305. {
  4306. WARN_BAD_FILE_NUMBER;
  4307. return (l);
  4308. }
  4309. My->CurrentFile = find_file_by_number (FileNumber);
  4310. if (My->CurrentFile == NULL)
  4311. {
  4312. WARN_BAD_FILE_NUMBER;
  4313. return (l);
  4314. }
  4315. if (My->CurrentFile->DevMode == DEVMODE_CLOSED)
  4316. {
  4317. WARN_BAD_FILE_NUMBER;
  4318. return (l);
  4319. }
  4320. if (My->CurrentFile->cfp != NULL)
  4321. {
  4322. bwb_fclose (My->CurrentFile->cfp);
  4323. My->CurrentFile->cfp = NULL;
  4324. }
  4325. if (My->CurrentFile->buffer != NULL)
  4326. {
  4327. free (My->CurrentFile->buffer);
  4328. My->CurrentFile->buffer = NULL;
  4329. }
  4330. My->CurrentFile->width = 0;
  4331. My->CurrentFile->col = 1;
  4332. My->CurrentFile->row = 1;
  4333. My->CurrentFile->delimit = ',';
  4334. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  4335. if (My->CurrentFile->FileName == NULL)
  4336. {
  4337. WARN_BAD_FILE_NAME;
  4338. return (l);
  4339. }
  4340. remove (My->CurrentFile->FileName);
  4341. free (My->CurrentFile->FileName);
  4342. My->CurrentFile->FileName = NULL;
  4343. }
  4344. while (line_skip_seperator (l));
  4345. /* OK */
  4346. return (l);
  4347. }
  4348. else
  4349. {
  4350. /*
  4351. SYNTAX: DELETE line [,...]
  4352. SYNTAX: DELETE line - line
  4353. */
  4354. do
  4355. {
  4356. int head;
  4357. int tail;
  4358. if (line_read_line_sequence (l, &head, &tail))
  4359. {
  4360. /* DELETE 's' - 'e' */
  4361. LineType *x;
  4362. LineType *previous;
  4363. if (head < MINLIN || head > MAXLIN)
  4364. {
  4365. WARN_UNDEFINED_LINE;
  4366. return (l);
  4367. }
  4368. if (tail < MINLIN || tail > MAXLIN)
  4369. {
  4370. WARN_UNDEFINED_LINE;
  4371. return (l);
  4372. }
  4373. if (head > tail)
  4374. {
  4375. WARN_UNDEFINED_LINE;
  4376. return (l);
  4377. }
  4378. /* valid range */
  4379. /* avoid deleting ourself */
  4380. if (l->LineFlags & (LINE_USER))
  4381. {
  4382. /* console line (immediate mode) */
  4383. }
  4384. else if (head <= l->number && l->number <= tail)
  4385. {
  4386. /* 100 DELETE 100 */
  4387. WARN_CANT_CONTINUE;
  4388. return (l);
  4389. }
  4390. /* now go through and list appropriate lines */
  4391. previous = My->StartMarker;
  4392. for (x = My->StartMarker->next; x != My->EndMarker;)
  4393. {
  4394. LineType *next;
  4395. next = x->next;
  4396. if (x->number < head)
  4397. {
  4398. previous = x;
  4399. }
  4400. else if (head <= x->number && x->number <= tail)
  4401. {
  4402. if (x == l)
  4403. {
  4404. /* 100 DELETE 100 */
  4405. WARN_CANT_CONTINUE;
  4406. return (l);
  4407. }
  4408. bwb_freeline (x);
  4409. previous->next = next;
  4410. }
  4411. x = next;
  4412. }
  4413. }
  4414. else
  4415. {
  4416. WARN_SYNTAX_ERROR;
  4417. return (l);
  4418. }
  4419. }
  4420. while (line_skip_seperator (l));
  4421. /*
  4422. **
  4423. ** FORCE SCAN
  4424. **
  4425. */
  4426. if (bwb_scan () == FALSE)
  4427. {
  4428. WARN_CANT_CONTINUE;
  4429. return (l);
  4430. }
  4431. }
  4432. return (l);
  4433. }
  4434. /*
  4435. --------------------------------------------------------------------------------------------
  4436. DELETE
  4437. --------------------------------------------------------------------------------------------
  4438. */
  4439. LineType *
  4440. bwb_DELETE (LineType * l)
  4441. {
  4442. assert (l != NULL);
  4443. return bwb_delete (l);
  4444. }
  4445. /*
  4446. --------------------------------------------------------------------------------------------
  4447. PDEL
  4448. --------------------------------------------------------------------------------------------
  4449. */
  4450. LineType *
  4451. bwb_PDEL (LineType * l)
  4452. {
  4453. assert (l != NULL);
  4454. return bwb_delete (l);
  4455. }
  4456. #if FALSE /* keep the source to DONUM and DOUNNUM */
  4457. /*
  4458. --------------------------------------------------------------------------------------------
  4459. DONUM
  4460. --------------------------------------------------------------------------------------------
  4461. */
  4462. LineType *
  4463. bwb_donum (LineType * l)
  4464. {
  4465. /*
  4466. SYNTAX: DONUM
  4467. */
  4468. LineType *current;
  4469. int lnumber;
  4470. assert (l != NULL);
  4471. assert( My != NULL );
  4472. assert( My->StartMarker != NULL );
  4473. assert( My->EndMarker != NULL );
  4474. lnumber = 10;
  4475. for (current = My->StartMarker->next; current != My->EndMarker;
  4476. current = current->next)
  4477. {
  4478. current->number = lnumber;
  4479. lnumber += 10;
  4480. if (lnumber > MAXLIN)
  4481. {
  4482. return (l);
  4483. }
  4484. }
  4485. return (l);
  4486. }
  4487. /*
  4488. --------------------------------------------------------------------------------------------
  4489. DOUNUM
  4490. --------------------------------------------------------------------------------------------
  4491. */
  4492. LineType *
  4493. bwb_dounnum (LineType * l)
  4494. {
  4495. /*
  4496. SYNTAX: DOUNNUM
  4497. */
  4498. LineType *current;
  4499. assert (l != NULL);
  4500. assert( My != NULL );
  4501. assert( My->StartMarker != NULL );
  4502. assert( My->EndMarker != NULL );
  4503. for (current = My->StartMarker->next; current != My->EndMarker;
  4504. current = current->next)
  4505. {
  4506. current->number = 0;
  4507. }
  4508. return (l);
  4509. }
  4510. #endif /* FALSE */
  4511. /*
  4512. --------------------------------------------------------------------------------------------
  4513. FILES
  4514. --------------------------------------------------------------------------------------------
  4515. */
  4516. LineType *
  4517. bwb_FILES (LineType * l)
  4518. {
  4519. /*
  4520. SYNTAX: FILES A$ [, ...]
  4521. */
  4522. /* open a list of files in READ mode */
  4523. assert (l != NULL);
  4524. assert( My != NULL );
  4525. do
  4526. {
  4527. int FileNumber;
  4528. FileNumber = My->LastFileNumber;
  4529. FileNumber++;
  4530. if (FileNumber < 0)
  4531. {
  4532. WARN_BAD_FILE_NUMBER;
  4533. return (l);
  4534. }
  4535. if (FileNumber == 0)
  4536. {
  4537. WARN_BAD_FILE_NUMBER;
  4538. return (l);
  4539. }
  4540. My->CurrentFile = find_file_by_number (FileNumber);
  4541. if (My->CurrentFile == NULL)
  4542. {
  4543. My->CurrentFile = file_new ();
  4544. My->CurrentFile->FileNumber = FileNumber;
  4545. }
  4546. {
  4547. char *Value;
  4548. Value = NULL;
  4549. if (line_read_string_expression (l, &Value) == FALSE)
  4550. {
  4551. WARN_SYNTAX_ERROR;
  4552. return (l);
  4553. }
  4554. if (Value == NULL)
  4555. {
  4556. WARN_SYNTAX_ERROR;
  4557. return (l);
  4558. }
  4559. if (My->CurrentFile->FileName != NULL)
  4560. {
  4561. free (My->CurrentFile->FileName);
  4562. My->CurrentFile->FileName = NULL;
  4563. }
  4564. My->CurrentFile->FileName = Value;
  4565. Value = NULL;
  4566. }
  4567. if (My->CurrentFile->DevMode != DEVMODE_CLOSED)
  4568. {
  4569. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  4570. }
  4571. if (My->CurrentFile->cfp != NULL)
  4572. {
  4573. bwb_fclose (My->CurrentFile->cfp);
  4574. My->CurrentFile->cfp = NULL;
  4575. }
  4576. if (My->CurrentFile->buffer != NULL)
  4577. {
  4578. free (My->CurrentFile->buffer);
  4579. My->CurrentFile->buffer = NULL;
  4580. }
  4581. My->CurrentFile->width = 0;
  4582. My->CurrentFile->col = 1;
  4583. My->CurrentFile->row = 1;
  4584. My->CurrentFile->delimit = ',';
  4585. if (is_empty_string (My->CurrentFile->FileName))
  4586. {
  4587. WARN_BAD_FILE_NAME;
  4588. return (l);
  4589. }
  4590. if (bwb_strcmp (My->CurrentFile->FileName, "*") != 0)
  4591. {
  4592. if ((My->CurrentFile->cfp =
  4593. fopen (My->CurrentFile->FileName, "r")) == NULL)
  4594. {
  4595. WARN_BAD_FILE_NAME;
  4596. return (l);
  4597. }
  4598. My->CurrentFile->DevMode = DEVMODE_INPUT;
  4599. }
  4600. My->LastFileNumber = FileNumber;
  4601. /* OK */
  4602. }
  4603. while (line_skip_seperator (l));
  4604. return (l);
  4605. }
  4606. /*
  4607. --------------------------------------------------------------------------------------------
  4608. FILE
  4609. --------------------------------------------------------------------------------------------
  4610. */
  4611. LineType *
  4612. bwb_FILE (LineType * l)
  4613. {
  4614. assert (l != NULL);
  4615. assert( My != NULL );
  4616. assert( My->CurrentVersion != NULL );
  4617. if (My->CurrentVersion->OptionVersionValue & (C77))
  4618. {
  4619. /*
  4620. CBASIC-II:
  4621. FILE file_name$ ' filename$ must be a simple string scalar (no arrays)
  4622. FILE file_name$ ( record_length% ) ' filename$ must be a simple string scalar (no arrays)
  4623. -- if the file exists,
  4624. then it is used,
  4625. else it is created.
  4626. -- Does not trigger IF END #
  4627. */
  4628. do
  4629. {
  4630. int FileNumber;
  4631. VariableType *v;
  4632. char varname[NameLengthMax + 1];
  4633. if (line_read_varname (l, varname) == FALSE)
  4634. {
  4635. WARN_BAD_FILE_NAME;
  4636. return (l);
  4637. }
  4638. if (is_empty_string (varname))
  4639. {
  4640. WARN_BAD_FILE_NAME;
  4641. return (l);
  4642. }
  4643. v = find_variable_by_type (varname, 0, StringTypeCode);
  4644. if (v == NULL)
  4645. {
  4646. WARN_VARIABLE_NOT_DECLARED;
  4647. return (l);
  4648. }
  4649. if (VAR_IS_STRING (v))
  4650. {
  4651. /* OK */
  4652. }
  4653. else
  4654. {
  4655. WARN_TYPE_MISMATCH;
  4656. return (l);
  4657. }
  4658. FileNumber = My->LastFileNumber;
  4659. FileNumber++;
  4660. if (FileNumber < 0)
  4661. {
  4662. WARN_BAD_FILE_NUMBER;
  4663. return (l);
  4664. }
  4665. if (FileNumber == 0)
  4666. {
  4667. WARN_BAD_FILE_NUMBER;
  4668. return (l);
  4669. }
  4670. My->CurrentFile = find_file_by_number (FileNumber);
  4671. if (My->CurrentFile == NULL)
  4672. {
  4673. My->CurrentFile = file_new ();
  4674. My->CurrentFile->FileNumber = FileNumber;
  4675. }
  4676. if (My->CurrentFile->DevMode != DEVMODE_CLOSED)
  4677. {
  4678. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  4679. }
  4680. if (My->CurrentFile->cfp != NULL)
  4681. {
  4682. bwb_fclose (My->CurrentFile->cfp);
  4683. My->CurrentFile->cfp = NULL;
  4684. }
  4685. if (My->CurrentFile->buffer != NULL)
  4686. {
  4687. free (My->CurrentFile->buffer);
  4688. My->CurrentFile->buffer = NULL;
  4689. }
  4690. My->CurrentFile->width = 0;
  4691. My->CurrentFile->col = 1;
  4692. My->CurrentFile->row = 1;
  4693. My->CurrentFile->delimit = ',';
  4694. /* OK */
  4695. if (line_skip_LparenChar (l))
  4696. {
  4697. /* RANDOM file */
  4698. int RecLen;
  4699. if (line_read_integer_expression (l, &RecLen) == FALSE)
  4700. {
  4701. WARN_FIELD_OVERFLOW;
  4702. return (l);
  4703. }
  4704. if (RecLen <= 0)
  4705. {
  4706. WARN_FIELD_OVERFLOW;
  4707. return (l);
  4708. }
  4709. if (line_skip_RparenChar (l) == FALSE)
  4710. {
  4711. WARN_SYNTAX_ERROR;
  4712. return (l);
  4713. }
  4714. if ((My->CurrentFile->buffer =
  4715. (char *) calloc (RecLen + 1 /* NulChar */ ,
  4716. sizeof (char))) == NULL)
  4717. {
  4718. WARN_OUT_OF_MEMORY;
  4719. return (l);
  4720. }
  4721. My->CurrentFile->width = RecLen;
  4722. }
  4723. /* if( TRUE ) */
  4724. {
  4725. VariantType variant;
  4726. CLEAR_VARIANT (&variant);
  4727. if (var_get (v, &variant) == FALSE)
  4728. {
  4729. WARN_VARIABLE_NOT_DECLARED;
  4730. return (l);
  4731. }
  4732. if (variant.VariantTypeCode == StringTypeCode)
  4733. {
  4734. if (My->CurrentFile->FileName != NULL)
  4735. {
  4736. free (My->CurrentFile->FileName);
  4737. My->CurrentFile->FileName = NULL;
  4738. }
  4739. My->CurrentFile->FileName = variant.Buffer;
  4740. variant.Buffer = NULL;
  4741. }
  4742. else
  4743. {
  4744. WARN_TYPE_MISMATCH;
  4745. return (l);
  4746. }
  4747. }
  4748. if (is_empty_string (My->CurrentFile->FileName))
  4749. {
  4750. WARN_BAD_FILE_NAME;
  4751. return (l);
  4752. }
  4753. My->CurrentFile->cfp = fopen (My->CurrentFile->FileName, "r+");
  4754. if (My->CurrentFile->cfp == NULL)
  4755. {
  4756. My->CurrentFile->cfp = fopen (My->CurrentFile->FileName, "w");
  4757. if (My->CurrentFile->cfp != NULL)
  4758. {
  4759. bwb_fclose (My->CurrentFile->cfp);
  4760. My->CurrentFile->cfp = fopen (My->CurrentFile->FileName, "r+");
  4761. }
  4762. }
  4763. if (My->CurrentFile->cfp == NULL)
  4764. {
  4765. WARN_BAD_FILE_NAME;
  4766. return (l);
  4767. }
  4768. if (My->CurrentFile->width > 0)
  4769. {
  4770. /* RANDOM file */
  4771. My->CurrentFile->DevMode = DEVMODE_RANDOM;
  4772. }
  4773. else
  4774. {
  4775. /* SERIAL file */
  4776. My->CurrentFile->DevMode = DEVMODE_INPUT | DEVMODE_OUTPUT;
  4777. }
  4778. /* OK */
  4779. My->LastFileNumber = FileNumber;
  4780. }
  4781. while (line_skip_seperator (l));
  4782. /* OK */
  4783. return (l);
  4784. }
  4785. if (line_skip_FilenumChar (l))
  4786. {
  4787. /*
  4788. SYNTAX: FILE # X, A$
  4789. */
  4790. int FileNumber;
  4791. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  4792. {
  4793. WARN_BAD_FILE_NUMBER;
  4794. return (l);
  4795. }
  4796. if (line_skip_seperator (l))
  4797. {
  4798. /* OK */
  4799. }
  4800. else
  4801. {
  4802. WARN_SYNTAX_ERROR;
  4803. return (l);
  4804. }
  4805. if (FileNumber < 0)
  4806. {
  4807. /* "FILE # -1" is an ERROR */
  4808. WARN_BAD_FILE_NUMBER;
  4809. return (l);
  4810. }
  4811. if (FileNumber == 0)
  4812. {
  4813. /* "FILE # 0" is an ERROR */
  4814. WARN_BAD_FILE_NUMBER;
  4815. return (l);
  4816. }
  4817. My->CurrentFile = find_file_by_number (FileNumber);
  4818. if (My->CurrentFile == NULL)
  4819. {
  4820. My->CurrentFile = file_new ();
  4821. My->CurrentFile->FileNumber = FileNumber;
  4822. }
  4823. {
  4824. char *Value;
  4825. Value = NULL;
  4826. if (line_read_string_expression (l, &Value) == FALSE)
  4827. {
  4828. WARN_SYNTAX_ERROR;
  4829. return (l);
  4830. }
  4831. if (Value == NULL)
  4832. {
  4833. WARN_SYNTAX_ERROR;
  4834. return (l);
  4835. }
  4836. if (My->CurrentFile->FileName != NULL)
  4837. {
  4838. free (My->CurrentFile->FileName);
  4839. My->CurrentFile->FileName = NULL;
  4840. }
  4841. My->CurrentFile->FileName = Value;
  4842. Value = NULL;
  4843. }
  4844. if (My->CurrentFile->DevMode != DEVMODE_CLOSED)
  4845. {
  4846. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  4847. }
  4848. if (My->CurrentFile->cfp != NULL)
  4849. {
  4850. bwb_fclose (My->CurrentFile->cfp);
  4851. My->CurrentFile->cfp = NULL;
  4852. }
  4853. if (My->CurrentFile->buffer != NULL)
  4854. {
  4855. free (My->CurrentFile->buffer);
  4856. My->CurrentFile->buffer = NULL;
  4857. }
  4858. My->CurrentFile->width = 0;
  4859. My->CurrentFile->col = 1;
  4860. My->CurrentFile->row = 1;
  4861. My->CurrentFile->delimit = ',';
  4862. if (is_empty_string (My->CurrentFile->FileName))
  4863. {
  4864. WARN_BAD_FILE_NAME;
  4865. return (l);
  4866. }
  4867. if (bwb_strcmp (My->CurrentFile->FileName, "*") != 0)
  4868. {
  4869. if ((My->CurrentFile->cfp =
  4870. fopen (My->CurrentFile->FileName, "r")) == NULL)
  4871. {
  4872. WARN_BAD_FILE_NAME;
  4873. return (l);
  4874. }
  4875. My->CurrentFile->DevMode = DEVMODE_INPUT;
  4876. }
  4877. /* OK */
  4878. return (l);
  4879. }
  4880. WARN_SYNTAX_ERROR;
  4881. return (l);
  4882. }
  4883. /*
  4884. --------------------------------------------------------------------------------------------
  4885. DELIMIT
  4886. --------------------------------------------------------------------------------------------
  4887. */
  4888. LineType *
  4889. bwb_DELIMIT (LineType * l)
  4890. {
  4891. /*
  4892. SYNTAX: DELIMIT # X, A$
  4893. */
  4894. assert (l != NULL);
  4895. assert( My != NULL );
  4896. assert( My->SYSIN != NULL );
  4897. if (line_skip_FilenumChar (l))
  4898. {
  4899. /* DELIMIT # */
  4900. int FileNumber;
  4901. char delimit;
  4902. My->CurrentFile = My->SYSIN;
  4903. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  4904. {
  4905. WARN_BAD_FILE_NUMBER;
  4906. return (l);
  4907. }
  4908. if (line_skip_seperator (l))
  4909. {
  4910. /* OK */
  4911. }
  4912. else
  4913. {
  4914. WARN_SYNTAX_ERROR;
  4915. return (l);
  4916. }
  4917. {
  4918. char *Value;
  4919. Value = NULL;
  4920. if (line_read_string_expression (l, &Value) == FALSE)
  4921. {
  4922. WARN_SYNTAX_ERROR;
  4923. return (l);
  4924. }
  4925. if (Value == NULL)
  4926. {
  4927. WARN_SYNTAX_ERROR;
  4928. return (l);
  4929. }
  4930. delimit = Value[0];
  4931. free (Value);
  4932. Value = NULL;
  4933. if (bwb_ispunct (delimit))
  4934. {
  4935. /* OK */
  4936. }
  4937. else
  4938. {
  4939. WARN_ILLEGAL_FUNCTION_CALL;
  4940. return (l);
  4941. }
  4942. }
  4943. if (FileNumber < 0)
  4944. {
  4945. /* "DELIMIT # -1" is SYSPRN */
  4946. My->SYSPRN->delimit = delimit;
  4947. return (l);
  4948. }
  4949. if (FileNumber == 0)
  4950. {
  4951. /* "DELIMIT # 0" is SYSOUT */
  4952. My->SYSOUT->delimit = delimit;
  4953. return (l);
  4954. }
  4955. /* normal file */
  4956. My->CurrentFile = find_file_by_number (FileNumber);
  4957. if (My->CurrentFile == NULL)
  4958. {
  4959. WARN_BAD_FILE_NUMBER;
  4960. return (l);
  4961. }
  4962. My->CurrentFile->delimit = delimit;
  4963. /* OK */
  4964. return (l);
  4965. }
  4966. WARN_SYNTAX_ERROR;
  4967. return (l);
  4968. }
  4969. /*
  4970. --------------------------------------------------------------------------------------------
  4971. MARGIN
  4972. --------------------------------------------------------------------------------------------
  4973. */
  4974. LineType *
  4975. bwb_MARGIN (LineType * l)
  4976. {
  4977. /*
  4978. SYNTAX: MARGIN # X, Y
  4979. */
  4980. /* set width for OUTPUT */
  4981. int FileNumber;
  4982. int Value;
  4983. assert (l != NULL);
  4984. assert( My != NULL );
  4985. assert( My->SYSIN != NULL );
  4986. if (line_skip_FilenumChar (l))
  4987. {
  4988. /* MARGIN # */
  4989. My->CurrentFile = My->SYSIN;
  4990. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  4991. {
  4992. WARN_BAD_FILE_NUMBER;
  4993. return (l);
  4994. }
  4995. if (line_skip_seperator (l))
  4996. {
  4997. /* OK */
  4998. }
  4999. else
  5000. {
  5001. WARN_SYNTAX_ERROR;
  5002. return (l);
  5003. }
  5004. if (line_read_integer_expression (l, &Value) == FALSE)
  5005. {
  5006. WARN_SYNTAX_ERROR;
  5007. return (l);
  5008. }
  5009. if (Value < 0)
  5010. {
  5011. WARN_ILLEGAL_FUNCTION_CALL;
  5012. return (l);
  5013. }
  5014. if (FileNumber < 0)
  5015. {
  5016. /* "MARGIN # -1" is SYSPRN */
  5017. My->SYSPRN->width = Value;
  5018. return (l);
  5019. }
  5020. if (FileNumber == 0)
  5021. {
  5022. /* "MARGIN # 0" is SYSOUT */
  5023. My->SYSOUT->width = Value;
  5024. return (l);
  5025. }
  5026. /* normal file */
  5027. My->CurrentFile = find_file_by_number (FileNumber);
  5028. if (My->CurrentFile == NULL)
  5029. {
  5030. WARN_BAD_FILE_NUMBER;
  5031. return (l);
  5032. }
  5033. if ((My->CurrentFile->DevMode & DEVMODE_WRITE) == 0)
  5034. {
  5035. WARN_BAD_FILE_NUMBER;
  5036. return (l);
  5037. }
  5038. My->CurrentFile->width = Value;
  5039. /* OK */
  5040. return (l);
  5041. }
  5042. WARN_SYNTAX_ERROR;
  5043. return (l);
  5044. }
  5045. /*
  5046. --------------------------------------------------------------------------------------------
  5047. USE
  5048. --------------------------------------------------------------------------------------------
  5049. */
  5050. LineType *
  5051. bwb_USE (LineType * l)
  5052. {
  5053. /*
  5054. SYNTAX: USE parameter$ ' CALL/360, System/360, System/370
  5055. */
  5056. VariableType *v;
  5057. assert (l != NULL);
  5058. assert( My != NULL );
  5059. if ((v = line_read_scalar (l)) == NULL)
  5060. {
  5061. WARN_SYNTAX_ERROR;
  5062. return (l);
  5063. }
  5064. if (v->VariableTypeCode != StringTypeCode)
  5065. {
  5066. WARN_SYNTAX_ERROR;
  5067. return (l);
  5068. }
  5069. /* OK */
  5070. if (My->UseParameterString)
  5071. {
  5072. VariantType variant;
  5073. CLEAR_VARIANT (&variant);
  5074. variant.VariantTypeCode = StringTypeCode;
  5075. variant.Buffer = My->UseParameterString;
  5076. variant.Length = bwb_strlen (My->UseParameterString);
  5077. var_set (v, &variant);
  5078. }
  5079. return (l);
  5080. }
  5081. /*
  5082. --------------------------------------------------------------------------------------------
  5083. CHAIN
  5084. --------------------------------------------------------------------------------------------
  5085. */
  5086. LineType *
  5087. bwb_CHAIN (LineType * l)
  5088. {
  5089. /*
  5090. SYNTAX: CHAIN file-name$ [, linenumber] ' most dialects
  5091. SYNTAX: CHAIN file-name$ [, parameter$] ' CALL/360, System/360, System/370
  5092. */
  5093. /* originally based upon bwb_load() */
  5094. int LineNumber;
  5095. LineType *x;
  5096. assert (l != NULL);
  5097. assert( My != NULL );
  5098. assert( My->CurrentVersion != NULL );
  5099. assert( My->StartMarker != NULL );
  5100. assert( My->EndMarker != NULL );
  5101. /* Get an argument for filename */
  5102. if (line_is_eol (l))
  5103. {
  5104. WARN_BAD_FILE_NAME;
  5105. return (l);
  5106. }
  5107. else
  5108. {
  5109. char *Value;
  5110. Value = NULL;
  5111. if (line_read_string_expression (l, &Value) == FALSE)
  5112. {
  5113. WARN_SYNTAX_ERROR;
  5114. return (l);
  5115. }
  5116. if (is_empty_string (Value))
  5117. {
  5118. WARN_BAD_FILE_NAME;
  5119. return (l);
  5120. }
  5121. if (My->ProgramFilename != NULL)
  5122. {
  5123. free (My->ProgramFilename);
  5124. My->ProgramFilename = NULL;
  5125. }
  5126. My->ProgramFilename = Value;
  5127. }
  5128. /* optional linenumber */
  5129. LineNumber = 0;
  5130. if (line_skip_seperator (l))
  5131. {
  5132. if (My->CurrentVersion->OptionVersionValue & (S70 | I70 | I73))
  5133. {
  5134. /* CHAIN filename$, parameter$ */
  5135. {
  5136. char *Value;
  5137. Value = NULL;
  5138. if (line_read_string_expression (l, &Value) == FALSE)
  5139. {
  5140. WARN_SYNTAX_ERROR;
  5141. return (l);
  5142. }
  5143. if (Value == NULL)
  5144. {
  5145. WARN_SYNTAX_ERROR;
  5146. return (l);
  5147. }
  5148. if (My->UseParameterString)
  5149. {
  5150. free (My->UseParameterString);
  5151. My->UseParameterString = NULL;
  5152. }
  5153. My->UseParameterString = Value;
  5154. }
  5155. }
  5156. else
  5157. {
  5158. /* CHAIN filename$, linenumber */
  5159. if (line_read_integer_expression (l, &LineNumber) == FALSE)
  5160. {
  5161. WARN_SYNTAX_ERROR;
  5162. return (l);
  5163. }
  5164. if (LineNumber < MINLIN || LineNumber > MAXLIN)
  5165. {
  5166. WARN_UNDEFINED_LINE;
  5167. return (l);
  5168. }
  5169. }
  5170. }
  5171. /* deallocate all variables except common ones */
  5172. var_delcvars ();
  5173. /* remove old program from memory */
  5174. bwb_xnew (My->StartMarker);
  5175. /* load new program in memory */
  5176. if (bwb_fload (NULL) == FALSE)
  5177. {
  5178. WARN_BAD_FILE_NAME;
  5179. return (l);
  5180. }
  5181. /* FIXME */
  5182. x = My->StartMarker;
  5183. if (MINLIN <= LineNumber && LineNumber <= MAXLIN)
  5184. {
  5185. /* search for a matching line number */
  5186. while (x->number != LineNumber && x != My->EndMarker)
  5187. {
  5188. x = x->next;
  5189. }
  5190. if (x == My->EndMarker)
  5191. {
  5192. /* NOT FOUND */
  5193. x = My->StartMarker;
  5194. }
  5195. }
  5196. x->position = 0;
  5197. /*
  5198. **
  5199. ** FORCE SCAN
  5200. **
  5201. */
  5202. if (bwb_scan () == FALSE)
  5203. {
  5204. WARN_CANT_CONTINUE;
  5205. return (l);
  5206. }
  5207. /* reset all stack counters */
  5208. bwb_clrexec ();
  5209. if (bwb_incexec ())
  5210. {
  5211. /* OK */
  5212. My->StackHead->line = x;
  5213. My->StackHead->ExecCode = EXEC_NORM;
  5214. }
  5215. else
  5216. {
  5217. /* ERROR */
  5218. WARN_OUT_OF_MEMORY;
  5219. return My->EndMarker;
  5220. }
  5221. /* run the program */
  5222. /* CHAIN */
  5223. WARN_CLEAR; /* bwb_CHAIN */
  5224. My->ContinueLine = NULL;
  5225. SetOnError (0);
  5226. return x;
  5227. }
  5228. /*
  5229. --------------------------------------------------------------------------------------------
  5230. APPEND
  5231. --------------------------------------------------------------------------------------------
  5232. */
  5233. LineType *
  5234. bwb_APPEND (LineType * l)
  5235. {
  5236. /*
  5237. SYNTAX: APPEND # filenumber ' Dartmouth, Mark-I, Mark-II, GCOS
  5238. SYNTAX: APPEND [filename$] ' all others
  5239. */
  5240. assert (l != NULL);
  5241. assert( My != NULL );
  5242. assert( My->CurrentVersion != NULL );
  5243. if (My->CurrentVersion->OptionVersionValue & (D64 | G65 | G67 | G74))
  5244. {
  5245. if (line_skip_FilenumChar (l))
  5246. {
  5247. /* APPEND # filenumber */
  5248. int FileNumber;
  5249. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  5250. {
  5251. WARN_SYNTAX_ERROR;
  5252. return (l);
  5253. }
  5254. if (FileNumber < 0)
  5255. {
  5256. /* "APPEND # -1" is silently ignored */
  5257. return (l);
  5258. }
  5259. if (FileNumber == 0)
  5260. {
  5261. /* "APPEND # 0" is silently ignored */
  5262. return (l);
  5263. }
  5264. My->CurrentFile = find_file_by_number (FileNumber);
  5265. if (My->CurrentFile == NULL)
  5266. {
  5267. WARN_BAD_FILE_NUMBER;
  5268. return (l);
  5269. }
  5270. /* normal file */
  5271. fseek (My->CurrentFile->cfp, 0, SEEK_END);
  5272. My->CurrentFile->DevMode = DEVMODE_APPEND;
  5273. /* OK */
  5274. return (l);
  5275. }
  5276. }
  5277. /* APPEND filename$ */
  5278. return bwb_load (l, "APPEND FILE NAME:", FALSE);
  5279. }
  5280. /*
  5281. --------------------------------------------------------------------------------------------
  5282. ON ERROR and so on
  5283. --------------------------------------------------------------------------------------------
  5284. */
  5285. extern void
  5286. SetOnError (int LineNumber)
  5287. {
  5288. /* scan the stack looking for a FUNCTION/SUB */
  5289. StackType *StackItem;
  5290. assert( My != NULL );
  5291. if (My->StackHead == NULL)
  5292. {
  5293. return;
  5294. }
  5295. for (StackItem = My->StackHead; StackItem->next != NULL;
  5296. StackItem = StackItem->next)
  5297. {
  5298. LineType *current;
  5299. current = StackItem->LoopTopLine;
  5300. if (current != NULL)
  5301. {
  5302. switch (current->cmdnum)
  5303. {
  5304. case C_FUNCTION:
  5305. case C_SUB:
  5306. /* FOUND */
  5307. /* we are in a FUNCTION/SUB, so this is LOCAL */
  5308. StackItem->OnErrorGoto = LineNumber;
  5309. return;
  5310. /* break; */
  5311. }
  5312. }
  5313. }
  5314. /* StackItem->next == NULL */
  5315. /* NOT FOUND */
  5316. /* we are NOT in a FUNCTION/SUB */
  5317. assert (StackItem != NULL);
  5318. StackItem->OnErrorGoto = LineNumber;
  5319. }
  5320. extern int
  5321. GetOnError (void)
  5322. {
  5323. /* scan the stack looking for an active "ON ERROR GOTO linenumber" */
  5324. StackType *StackItem;
  5325. assert( My != NULL );
  5326. for (StackItem = My->StackHead; StackItem != NULL;
  5327. StackItem = StackItem->next)
  5328. {
  5329. if (StackItem->OnErrorGoto != 0)
  5330. {
  5331. /* FOUND */
  5332. return StackItem->OnErrorGoto;
  5333. }
  5334. }
  5335. /* NOT FOUND */
  5336. return 0;
  5337. }
  5338. /*
  5339. --------------------------------------------------------------------------------------------
  5340. ON ERROR
  5341. --------------------------------------------------------------------------------------------
  5342. */
  5343. LineType *
  5344. bwb_ON_ERROR (LineType * l)
  5345. {
  5346. assert (l != NULL);
  5347. WARN_SYNTAX_ERROR;
  5348. return (l);
  5349. }
  5350. /*
  5351. --------------------------------------------------------------------------------------------
  5352. ON ERROR GOTO
  5353. --------------------------------------------------------------------------------------------
  5354. */
  5355. LineType *
  5356. bwb_ON_ERROR_GOTO (LineType * l)
  5357. {
  5358. /* ON ERROR GOTO line */
  5359. int LineNumber;
  5360. assert (l != NULL);
  5361. WARN_CLEAR; /* bwb_ON_ERROR_GOTO */
  5362. /* get the line number */
  5363. LineNumber = 0;
  5364. if (line_is_eol (l))
  5365. {
  5366. /* ON ERROR GOTO */
  5367. SetOnError (0);
  5368. return (l);
  5369. }
  5370. if (line_read_integer_expression (l, &LineNumber) == FALSE)
  5371. {
  5372. WARN_SYNTAX_ERROR;
  5373. return (l);
  5374. }
  5375. /* ON ERORR GOTO linenumber */
  5376. if (LineNumber == 0)
  5377. {
  5378. /* ON ERROR GOTO 0 */
  5379. SetOnError (0);
  5380. return (l);
  5381. }
  5382. if (LineNumber < MINLIN || LineNumber > MAXLIN)
  5383. {
  5384. /* ERROR */
  5385. WARN_UNDEFINED_LINE;
  5386. return (l);
  5387. }
  5388. /* OK */
  5389. SetOnError (LineNumber);
  5390. return (l);
  5391. }
  5392. /*
  5393. --------------------------------------------------------------------------------------------
  5394. ON ERROR GOSUB
  5395. --------------------------------------------------------------------------------------------
  5396. */
  5397. LineType *
  5398. bwb_ON_ERROR_GOSUB (LineType * l)
  5399. {
  5400. /* ON ERROR GOSUB line */
  5401. assert (l != NULL);
  5402. return bwb_ON_ERROR_GOTO (l);
  5403. }
  5404. /*
  5405. --------------------------------------------------------------------------------------------
  5406. ON ERROR RESUME
  5407. --------------------------------------------------------------------------------------------
  5408. */
  5409. LineType *
  5410. bwb_ON_ERROR_RESUME (LineType * l)
  5411. {
  5412. assert (l != NULL);
  5413. WARN_SYNTAX_ERROR;
  5414. return (l);
  5415. }
  5416. /*
  5417. --------------------------------------------------------------------------------------------
  5418. ON ERROR RESUME NEXT
  5419. --------------------------------------------------------------------------------------------
  5420. */
  5421. LineType *
  5422. bwb_ON_ERROR_RESUME_NEXT (LineType * l)
  5423. {
  5424. assert (l != NULL);
  5425. WARN_CLEAR; /* bwb_ON_ERROR_RESUME_NEXT */
  5426. SetOnError (-1);
  5427. return (l);
  5428. }
  5429. /*
  5430. --------------------------------------------------------------------------------------------
  5431. ON ERROR RETURN
  5432. --------------------------------------------------------------------------------------------
  5433. */
  5434. LineType *
  5435. bwb_ON_ERROR_RETURN (LineType * l)
  5436. {
  5437. assert (l != NULL);
  5438. WARN_SYNTAX_ERROR;
  5439. return (l);
  5440. }
  5441. /*
  5442. --------------------------------------------------------------------------------------------
  5443. ON ERROR RETURN NEXT
  5444. --------------------------------------------------------------------------------------------
  5445. */
  5446. LineType *
  5447. bwb_ON_ERROR_RETURN_NEXT (LineType * l)
  5448. {
  5449. assert (l != NULL);
  5450. return bwb_ON_ERROR_RESUME_NEXT (l);
  5451. }
  5452. /*
  5453. --------------------------------------------------------------------------------------------
  5454. ON TIMER
  5455. --------------------------------------------------------------------------------------------
  5456. */
  5457. LineType *
  5458. bwb_ON_TIMER (LineType * l)
  5459. {
  5460. /* ON TIMER(...) GOSUB ... */
  5461. DoubleType v;
  5462. DoubleType minv;
  5463. int LineNumber;
  5464. assert (l != NULL);
  5465. assert( My != NULL );
  5466. My->IsTimerOn = FALSE; /* bwb_ON_TIMER */
  5467. My->OnTimerLineNumber = 0;
  5468. My->OnTimerCount = 0;
  5469. /* get the SECOMDS parameter */
  5470. if (line_read_numeric_expression (l, &v) == FALSE)
  5471. {
  5472. WARN_SYNTAX_ERROR;
  5473. return (l);
  5474. }
  5475. minv = 1;
  5476. assert (CLOCKS_PER_SEC > 0);
  5477. minv /= CLOCKS_PER_SEC;
  5478. if (v < minv)
  5479. {
  5480. /* ERROR */
  5481. WARN_ILLEGAL_FUNCTION_CALL;
  5482. return (l);
  5483. }
  5484. /* get the GOSUB keyword */
  5485. if (line_skip_word (l, "GOSUB") == FALSE)
  5486. {
  5487. WARN_SYNTAX_ERROR;
  5488. return (l);
  5489. }
  5490. /* ON TIMER(X) GOSUB line */
  5491. if (line_read_integer_expression (l, &LineNumber) == FALSE)
  5492. {
  5493. WARN_SYNTAX_ERROR;
  5494. return (l);
  5495. }
  5496. if (LineNumber < MINLIN || LineNumber > MAXLIN)
  5497. {
  5498. /* ERROR */
  5499. WARN_UNDEFINED_LINE;
  5500. return (l);
  5501. }
  5502. /* OK */
  5503. My->OnTimerLineNumber = LineNumber;
  5504. My->OnTimerCount = v;
  5505. return (l);
  5506. }
  5507. /*
  5508. --------------------------------------------------------------------------------------------
  5509. TIMER
  5510. --------------------------------------------------------------------------------------------
  5511. */
  5512. LineType *
  5513. bwb_TIMER (LineType * l)
  5514. {
  5515. assert (l != NULL);
  5516. assert( My != NULL );
  5517. My->IsTimerOn = FALSE; /* bwb_TIMER */
  5518. WARN_SYNTAX_ERROR;
  5519. return (l);
  5520. }
  5521. /*
  5522. --------------------------------------------------------------------------------------------
  5523. TIMER OFF
  5524. --------------------------------------------------------------------------------------------
  5525. */
  5526. LineType *
  5527. bwb_TIMER_OFF (LineType * l)
  5528. {
  5529. assert (l != NULL);
  5530. assert( My != NULL );
  5531. /* TIMER OFF */
  5532. My->IsTimerOn = FALSE; /* bwb_TIMER_OFF */
  5533. My->OnTimerLineNumber = 0;
  5534. My->OnTimerCount = 0;
  5535. return (l);
  5536. }
  5537. /*
  5538. --------------------------------------------------------------------------------------------
  5539. TIMER ON
  5540. --------------------------------------------------------------------------------------------
  5541. */
  5542. LineType *
  5543. bwb_TIMER_ON (LineType * l)
  5544. {
  5545. assert (l != NULL);
  5546. assert( My != NULL );
  5547. My->IsTimerOn = FALSE; /* bwb_TIMER_ON */
  5548. /* TIMER ON */
  5549. if (My->OnTimerCount > 0 && My->OnTimerLineNumber > 0)
  5550. {
  5551. My->OnTimerExpires = bwx_TIMER (My->OnTimerCount);
  5552. My->IsTimerOn = TRUE; /* bwb_TIMER_ON */
  5553. }
  5554. return (l);
  5555. }
  5556. /*
  5557. --------------------------------------------------------------------------------------------
  5558. TIMER STOP
  5559. --------------------------------------------------------------------------------------------
  5560. */
  5561. LineType *
  5562. bwb_TIMER_STOP (LineType * l)
  5563. {
  5564. assert (l != NULL);
  5565. assert( My != NULL );
  5566. My->IsTimerOn = FALSE; /* bwb_TIMER_STOP */
  5567. return (l);
  5568. }
  5569. /*
  5570. --------------------------------------------------------------------------------------------
  5571. RESUME
  5572. --------------------------------------------------------------------------------------------
  5573. */
  5574. LineType *
  5575. bwb_RESUME (LineType * l)
  5576. {
  5577. int LineNumber;
  5578. LineType *x;
  5579. assert (l != NULL);
  5580. assert( My != NULL );
  5581. LineNumber = 0;
  5582. x = My->ERL; /* bwb_RESUME */
  5583. WARN_CLEAR; /* bwb_RESUME */
  5584. if (l->LineFlags & (LINE_USER))
  5585. {
  5586. WARN_ILLEGAL_DIRECT;
  5587. return (l);
  5588. }
  5589. if (x == NULL)
  5590. {
  5591. WARN_RESUME_WITHOUT_ERROR;
  5592. return (l);
  5593. }
  5594. /* Get optional argument for RESUME */
  5595. if (line_is_eol (l))
  5596. {
  5597. /* RESUME */
  5598. /*
  5599. Execution resumes at the statement which caused the error
  5600. For structured commands, this is the top line of the structure.
  5601. */
  5602. x->position = 0;
  5603. return x;
  5604. }
  5605. if (line_skip_word (l, "NEXT"))
  5606. {
  5607. /* RESUME NEXT */
  5608. /*
  5609. Execution resumes at the statement immediately following the one which caused the error.
  5610. For structured commands, this is the bottom line of the structure.
  5611. */
  5612. switch (x->cmdnum)
  5613. {
  5614. case C_IF8THEN:
  5615. /* skip to END_IF */
  5616. assert (x->OtherLine != NULL);
  5617. for (x = x->OtherLine; x->cmdnum != C_END_IF; x = x->OtherLine);
  5618. break;
  5619. case C_SELECT_CASE:
  5620. /* skip to END_SELECT */
  5621. assert (x->OtherLine != NULL);
  5622. for (x = x->OtherLine; x->cmdnum != C_END_SELECT; x = x->OtherLine);
  5623. break;
  5624. default:
  5625. x = x->next;
  5626. }
  5627. x->position = 0;
  5628. return x;
  5629. }
  5630. /* RESUME ### */
  5631. if (line_read_integer_expression (l, &LineNumber) == FALSE)
  5632. {
  5633. WARN_SYNTAX_ERROR;
  5634. return (l);
  5635. }
  5636. if (LineNumber == 0)
  5637. {
  5638. /* SPECIAL CASE */
  5639. /* RESUME 0 */
  5640. /* Execution resumes at the statement which caused the error */
  5641. x->position = 0;
  5642. return x;
  5643. }
  5644. /* VERIFY LINE EXISTS */
  5645. x = find_line_number (LineNumber); /* RESUME 100 */
  5646. if (x != NULL)
  5647. {
  5648. /* FOUND */
  5649. x->position = 0;
  5650. return x;
  5651. }
  5652. /* NOT FOUND */
  5653. WARN_UNDEFINED_LINE;
  5654. return (l);
  5655. }
  5656. /*
  5657. --------------------------------------------------------------------------------------------
  5658. CMDS
  5659. --------------------------------------------------------------------------------------------
  5660. */
  5661. LineType *
  5662. bwb_CMDS (LineType * l)
  5663. {
  5664. int n;
  5665. int lmtch;
  5666. int lcnt;
  5667. assert (l != NULL);
  5668. assert( My != NULL );
  5669. assert( My->SYSOUT != NULL );
  5670. assert( My->SYSOUT->cfp != NULL );
  5671. My->CurrentFile = My->SYSOUT;
  5672. fprintf (My->SYSOUT->cfp, "\nBWBASIC COMMANDS AVAILABLE:\n\n");
  5673. /* run through the command table and print command names */
  5674. lcnt = 0;
  5675. for (n = 0; n < NUM_COMMANDS; n++) /* Loop through table Ken 4-2020 */
  5676. {
  5677. lmtch = strcmp(IntrinsicCommandTable[n].name,IntrinsicCommandTable[n+1].name);
  5678. if (lmtch != 0) { /* If duplicate don't print */
  5679. fprintf (My->SYSOUT->cfp, "%s\n", IntrinsicCommandTable[n].name);
  5680. lcnt = lcnt + 1;
  5681. }
  5682. }
  5683. fprintf (My->SYSOUT->cfp, "\nTotal Commands %d\n\n",lcnt);
  5684. ResetConsoleColumn ();
  5685. return (l);
  5686. }
  5687. static void
  5688. FixUp (char *Name)
  5689. {
  5690. char *C;
  5691. assert (Name != NULL);
  5692. C = Name;
  5693. while (*C)
  5694. {
  5695. if (bwb_isalnum (*C))
  5696. {
  5697. /* OK */
  5698. }
  5699. else
  5700. {
  5701. /* FIX */
  5702. switch (*C)
  5703. {
  5704. case '!':
  5705. *C = '1';
  5706. break;
  5707. case '@':
  5708. *C = '2';
  5709. break;
  5710. case '#':
  5711. *C = '3';
  5712. break;
  5713. case '$':
  5714. *C = '4';
  5715. break;
  5716. case '%':
  5717. *C = '5';
  5718. break;
  5719. case '^':
  5720. *C = '6';
  5721. break;
  5722. case '&':
  5723. *C = '7';
  5724. break;
  5725. case '*':
  5726. *C = '8';
  5727. break;
  5728. case '(':
  5729. *C = '9';
  5730. break;
  5731. case ')':
  5732. *C = '0';
  5733. break;
  5734. default:
  5735. *C = '_';
  5736. }
  5737. }
  5738. C++;
  5739. }
  5740. }
  5741. static void
  5742. CommandUniqueID (int i, char *UniqueID)
  5743. {
  5744. assert (UniqueID != NULL);
  5745. bwb_strcpy (UniqueID, "C_");
  5746. bwb_strcat (UniqueID, IntrinsicCommandTable[i].name);
  5747. FixUp (UniqueID);
  5748. }
  5749. static void
  5750. CommandVector (int i, char *Vector)
  5751. {
  5752. assert (Vector != NULL);
  5753. bwb_strcpy (Vector, "bwb_");
  5754. bwb_strcat (Vector, IntrinsicCommandTable[i].name);
  5755. FixUp (Vector);
  5756. }
  5757. static void
  5758. CommandOptionVersion (int n, char *OutputLine)
  5759. {
  5760. int i;
  5761. int j;
  5762. assert (OutputLine != NULL);
  5763. bwb_strcpy (OutputLine, "");
  5764. j = 0;
  5765. for (i = 0; i < NUM_VERSIONS; i++)
  5766. {
  5767. if (IntrinsicCommandTable[n].OptionVersionBitmask & bwb_vertable[i].
  5768. OptionVersionValue)
  5769. {
  5770. if (j > 0)
  5771. {
  5772. bwb_strcat (OutputLine, " | ");
  5773. }
  5774. bwb_strcat (OutputLine, bwb_vertable[i].ID);
  5775. j++;
  5776. }
  5777. }
  5778. }
  5779. void
  5780. SortAllCommands (void)
  5781. {
  5782. /* sort by name */
  5783. int i;
  5784. assert( My != NULL );
  5785. for (i = 0; i < NUM_COMMANDS - 1; i++)
  5786. {
  5787. int j;
  5788. int k;
  5789. k = i;
  5790. for (j = i + 1; j < NUM_COMMANDS; j++)
  5791. {
  5792. if (bwb_stricmp
  5793. (IntrinsicCommandTable[j].name, IntrinsicCommandTable[k].name) < 0)
  5794. {
  5795. k = j;
  5796. }
  5797. }
  5798. if (k > i)
  5799. {
  5800. CommandType t;
  5801. bwb_memcpy (&t, &(IntrinsicCommandTable[i]), sizeof (CommandType));
  5802. bwb_memcpy (&(IntrinsicCommandTable[i]), &(IntrinsicCommandTable[k]),
  5803. sizeof (CommandType));
  5804. bwb_memcpy (&(IntrinsicCommandTable[k]), &t, sizeof (CommandType));
  5805. }
  5806. }
  5807. #if THE_PRICE_IS_RIGHT
  5808. for (i = 0; i < 26; i++)
  5809. {
  5810. My->CommandStart[i] = -1;
  5811. }
  5812. for (i = 0; i < NUM_COMMANDS; i++)
  5813. {
  5814. int j;
  5815. j = VarTypeIndex (IntrinsicCommandTable[i].name[0]);
  5816. if (j < 0)
  5817. {
  5818. /* non-alpha */
  5819. }
  5820. else if (My->CommandStart[j] < 0)
  5821. {
  5822. /* this is the first command starting with this letter */
  5823. My->CommandStart[j] = i;
  5824. }
  5825. }
  5826. #endif /* THE_PRICE_IS_RIGHT */
  5827. }
  5828. void
  5829. SortAllFunctions (void)
  5830. {
  5831. /* sort by name then number of parameters */
  5832. int i;
  5833. assert( My != NULL );
  5834. for (i = 0; i < NUM_FUNCTIONS - 1; i++)
  5835. {
  5836. int j;
  5837. int k;
  5838. k = i;
  5839. for (j = i + 1; j < NUM_FUNCTIONS; j++)
  5840. {
  5841. int n;
  5842. n =
  5843. bwb_stricmp (IntrinsicFunctionTable[j].Name,
  5844. IntrinsicFunctionTable[k].Name);
  5845. if (n < 0)
  5846. {
  5847. k = j;
  5848. }
  5849. else if (n == 0)
  5850. {
  5851. if (IntrinsicFunctionTable[j].ParameterCount <
  5852. IntrinsicFunctionTable[k].ParameterCount)
  5853. {
  5854. k = j;
  5855. }
  5856. }
  5857. }
  5858. if (k > i)
  5859. {
  5860. IntrinsicFunctionType t;
  5861. bwb_memcpy (&t, &(IntrinsicFunctionTable[i]),
  5862. sizeof (IntrinsicFunctionType));
  5863. bwb_memcpy (&(IntrinsicFunctionTable[i]), &(IntrinsicFunctionTable[k]),
  5864. sizeof (IntrinsicFunctionType));
  5865. bwb_memcpy (&(IntrinsicFunctionTable[k]), &t,
  5866. sizeof (IntrinsicFunctionType));
  5867. }
  5868. }
  5869. #if THE_PRICE_IS_RIGHT
  5870. for (i = 0; i < 26; i++)
  5871. {
  5872. My->IntrinsicFunctionStart[i] = -1;
  5873. }
  5874. for (i = 0; i < NUM_FUNCTIONS; i++)
  5875. {
  5876. int j;
  5877. j = VarTypeIndex (IntrinsicFunctionTable[i].Name[0]);
  5878. if (j < 0)
  5879. {
  5880. /* non-alpha */
  5881. }
  5882. else if (My->IntrinsicFunctionStart[j] < 0)
  5883. {
  5884. /* this is the first command starting with this letter */
  5885. My->IntrinsicFunctionStart[j] = i;
  5886. }
  5887. }
  5888. #endif /* THE_PRICE_IS_RIGHT */
  5889. }
  5890. void
  5891. DumpAllCommandUniqueID (FILE * file)
  5892. {
  5893. int i;
  5894. int j;
  5895. char LastUniqueID[NameLengthMax + 1];
  5896. assert (file != NULL);
  5897. j = 0;
  5898. LastUniqueID[0] = NulChar;
  5899. fprintf (file, "/* COMMANDS */\n");
  5900. /* run through the command table and print comand #define */
  5901. for (i = 0; i < NUM_COMMANDS; i++)
  5902. {
  5903. char UniqueID[NameLengthMax + 1];
  5904. CommandUniqueID (i, UniqueID);
  5905. if (bwb_stricmp (LastUniqueID, UniqueID) != 0)
  5906. {
  5907. /* not a duplicate */
  5908. bwb_strcpy (LastUniqueID, UniqueID);
  5909. j = j + 1;
  5910. fprintf (file, "#define %-30s %3d /* %-30s */\n", UniqueID, j,
  5911. IntrinsicCommandTable[i].name);
  5912. }
  5913. }
  5914. fprintf (file, "#define NUM_COMMANDS %d\n", j);
  5915. fflush (file);
  5916. }
  5917. static void
  5918. ProcessEscapeChars (const char *Input, char *Output)
  5919. {
  5920. int n;
  5921. assert (Input != NULL);
  5922. assert (Output != NULL);
  5923. n = 0;
  5924. while (*Input)
  5925. {
  5926. /* \a \b \f \n \r \t \v \" \\ */
  5927. switch (*Input)
  5928. {
  5929. case '\a':
  5930. *Output = '\\';
  5931. Output++;
  5932. *Output = 'a';
  5933. Output++;
  5934. break;
  5935. case '\b':
  5936. *Output = '\\';
  5937. Output++;
  5938. *Output = 'b';
  5939. Output++;
  5940. break;
  5941. case '\f':
  5942. *Output = '\\';
  5943. Output++;
  5944. *Output = 'f';
  5945. Output++;
  5946. break;
  5947. case '\n':
  5948. *Output = '\\';
  5949. Output++;
  5950. *Output = 'n';
  5951. Output++;
  5952. break;
  5953. case '\r':
  5954. *Output = '\\';
  5955. Output++;
  5956. *Output = 'r';
  5957. Output++;
  5958. break;
  5959. case '\t':
  5960. *Output = '\\';
  5961. Output++;
  5962. *Output = 't';
  5963. Output++;
  5964. break;
  5965. case '\v':
  5966. *Output = '\\';
  5967. Output++;
  5968. *Output = 'n';
  5969. Output++;
  5970. break;
  5971. case '\"':
  5972. *Output = '\\';
  5973. Output++;
  5974. *Output = '"';
  5975. Output++;
  5976. break;
  5977. case '\\':
  5978. *Output = '\\';
  5979. Output++;
  5980. *Output = '\\';
  5981. Output++;
  5982. break;
  5983. default:
  5984. *Output = *Input;
  5985. Output++;
  5986. break;
  5987. }
  5988. *Output = NulChar;
  5989. n++;
  5990. if (n > 60 && *Input == ' ')
  5991. {
  5992. *Output = '\"';
  5993. Output++;
  5994. *Output = '\n';
  5995. Output++;
  5996. *Output = ' ';
  5997. Output++;
  5998. *Output = ' ';
  5999. Output++;
  6000. *Output = '\"';
  6001. Output++;
  6002. *Output = NulChar;
  6003. n = 0;
  6004. }
  6005. Input++;
  6006. }
  6007. }
  6008. void
  6009. DumpAllCommandTableDefinitions (FILE * file)
  6010. {
  6011. /* generate bwd_cmd.c */
  6012. int i;
  6013. assert (file != NULL);
  6014. fprintf (file, "/* COMMAND TABLE */\n\n");
  6015. fprintf (file, "#include \"bwbasic.h\"\n\n");
  6016. fprintf (file,
  6017. "CommandType IntrinsicCommandTable[ /* NUM_COMMANDS */ ] =\n");
  6018. fprintf (file, "{\n");
  6019. /* run through the command table and print comand #define */
  6020. for (i = 0; i < NUM_COMMANDS; i++)
  6021. {
  6022. char tbuf[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpAllCommandTableDefinitions */
  6023. fprintf (file, "{\n");
  6024. fprintf (file, " ");
  6025. CommandUniqueID (i, tbuf);
  6026. fprintf (file, "%s", tbuf);
  6027. fprintf (file, ", /* UniqueID */\n");
  6028. fprintf (file, " ");
  6029. fprintf (file, "\"");
  6030. ProcessEscapeChars (IntrinsicCommandTable[i].Syntax, tbuf);
  6031. fprintf (file, "%s", tbuf);
  6032. fprintf (file, "\"");
  6033. fprintf (file, ", /* Syntax */\n");
  6034. fprintf (file, " ");
  6035. fprintf (file, "\"");
  6036. ProcessEscapeChars (IntrinsicCommandTable[i].Description, tbuf);
  6037. fprintf (file, "%s", tbuf);
  6038. fprintf (file, "\"");
  6039. fprintf (file, ", /* Description */\n");
  6040. fprintf (file, " ");
  6041. fprintf (file, "\"");
  6042. fprintf (file, "%s", IntrinsicCommandTable[i].name);
  6043. fprintf (file, "\"");
  6044. fprintf (file, ", /* Name */\n");
  6045. fprintf (file, " ");
  6046. CommandOptionVersion (i, tbuf);
  6047. fprintf (file, "%s", tbuf);
  6048. fprintf (file, " /* OptionVersionBitmask */\n");
  6049. fprintf (file, "},\n");
  6050. }
  6051. fprintf (file, "};\n");
  6052. fprintf (file, "\n");
  6053. fprintf (file,
  6054. "const size_t NUM_COMMANDS = sizeof( IntrinsicCommandTable ) / sizeof( CommandType );\n");
  6055. fprintf (file, "\n");
  6056. fflush (file);
  6057. }
  6058. void
  6059. DumpAllCommandSwitchStatement (FILE * file)
  6060. {
  6061. int i;
  6062. char LastUniqueID[NameLengthMax + 1];
  6063. assert (file != NULL);
  6064. LastUniqueID[0] = NulChar;
  6065. /* run through the command table and print comand #define */
  6066. fprintf (file, "/* SWITCH */\n");
  6067. fprintf (file, "LineType *bwb_vector( LineType *l )\n");
  6068. fprintf (file, "{\n");
  6069. fprintf (file, " ");
  6070. fprintf (file, "LineType *r;\n");
  6071. fprintf (file, " ");
  6072. fprintf (file, "switch( l->cmdnum )\n");
  6073. fprintf (file, " ");
  6074. fprintf (file, "{\n");
  6075. for (i = 0; i < NUM_COMMANDS; i++)
  6076. {
  6077. char tbuf[NameLengthMax + 1];
  6078. CommandUniqueID (i, tbuf);
  6079. if (bwb_stricmp (LastUniqueID, tbuf) != 0)
  6080. {
  6081. /* not a duplicate */
  6082. bwb_strcpy (LastUniqueID, tbuf);
  6083. fprintf (file, " ");
  6084. fprintf (file, "case ");
  6085. CommandUniqueID (i, tbuf);
  6086. fprintf (file, "%s", tbuf);
  6087. fprintf (file, ":\n");
  6088. fprintf (file, " ");
  6089. fprintf (file, " ");
  6090. fprintf (file, "r = ");
  6091. CommandVector (i, tbuf);
  6092. fprintf (file, "%s", tbuf);
  6093. fprintf (file, "( l );\n");
  6094. fprintf (file, " ");
  6095. fprintf (file, " ");
  6096. fprintf (file, "break;\n");
  6097. }
  6098. }
  6099. fprintf (file, " ");
  6100. fprintf (file, "default:\n");
  6101. fprintf (file, " ");
  6102. fprintf (file, " ");
  6103. fprintf (file, "WARN_INTERNAL_ERROR;\n");
  6104. fprintf (file, " ");
  6105. fprintf (file, " ");
  6106. fprintf (file, "r = l;\n");
  6107. fprintf (file, " ");
  6108. fprintf (file, " ");
  6109. fprintf (file, "break;\n");
  6110. fprintf (file, " ");
  6111. fprintf (file, "}\n");
  6112. fprintf (file, " ");
  6113. fprintf (file, "return r;\n");
  6114. fprintf (file, "}\n");
  6115. fflush (file);
  6116. }
  6117. void
  6118. FixDescription (FILE * file, const char *left, const char *right)
  6119. {
  6120. char buffer[MAINTAINER_BUFFER_LENGTH + 1]; /* FixDescription */
  6121. int l; /* length of left side */
  6122. int p; /* current position */
  6123. int n; /* position of the last space character, zero means none yet seen */
  6124. int i; /* number of characters since last '\n' */
  6125. assert (left != NULL);
  6126. assert (right != NULL);
  6127. l = bwb_strlen (left);
  6128. p = 0;
  6129. n = 0;
  6130. i = 0;
  6131. bwb_strcpy (buffer, right);
  6132. while (buffer[p])
  6133. {
  6134. if (buffer[p] == '\n')
  6135. {
  6136. n = p;
  6137. i = 0;
  6138. }
  6139. if (buffer[p] == ' ')
  6140. {
  6141. n = p;
  6142. }
  6143. if (i > 45 && n > 0)
  6144. {
  6145. buffer[n] = '\n';
  6146. i = p - n;
  6147. }
  6148. p++;
  6149. i++;
  6150. }
  6151. fputs (left, file);
  6152. p = 0;
  6153. while (buffer[p])
  6154. {
  6155. if (buffer[p] == '\n')
  6156. {
  6157. fputc (buffer[p], file);
  6158. p++;
  6159. while (buffer[p] == ' ')
  6160. {
  6161. p++;
  6162. }
  6163. for (i = 0; i < l; i++)
  6164. {
  6165. fputc (' ', file);
  6166. }
  6167. }
  6168. else
  6169. {
  6170. fputc (buffer[p], file);
  6171. p++;
  6172. }
  6173. }
  6174. fputc ('\n', file);
  6175. }
  6176. void
  6177. DumpOneCommandSyntax (FILE * file, int IsXref, int n)
  6178. {
  6179. assert (file != NULL);
  6180. if (n < 0 || n >= NUM_COMMANDS)
  6181. {
  6182. return;
  6183. }
  6184. /* NAME */
  6185. {
  6186. FixDescription (file, " SYNTAX: ", IntrinsicCommandTable[n].Syntax);
  6187. }
  6188. /* DESCRIPTION */
  6189. {
  6190. FixDescription (file, "DESCRIPTION: ",
  6191. IntrinsicCommandTable[n].Description);
  6192. }
  6193. /* COMPATIBILITY */
  6194. if (IsXref)
  6195. {
  6196. int i;
  6197. fprintf (file, " VERSIONS:\n");
  6198. for (i = 0; i < NUM_VERSIONS; i++)
  6199. {
  6200. char X;
  6201. if (IntrinsicCommandTable[n].OptionVersionBitmask & bwb_vertable[i].
  6202. OptionVersionValue)
  6203. {
  6204. /* SUPPORTED */
  6205. X = 'X';
  6206. }
  6207. else
  6208. {
  6209. /* NOT SUPPORTED */
  6210. X = '_';
  6211. }
  6212. fprintf (file, " [%c] %s\n", X, bwb_vertable[i].Name);
  6213. }
  6214. }
  6215. fflush (file);
  6216. }
  6217. void
  6218. DumpAllCommandSyntax (FILE * file, int IsXref,
  6219. OptionVersionType OptionVersionValue)
  6220. {
  6221. /* for the C maintainer */
  6222. int i;
  6223. assert (file != NULL);
  6224. fprintf (file,
  6225. "============================================================\n");
  6226. fprintf (file,
  6227. " COMMANDS \n");
  6228. fprintf (file,
  6229. "============================================================\n");
  6230. fprintf (file, "\n");
  6231. fprintf (file, "\n");
  6232. for (i = 0; i < NUM_COMMANDS; i++)
  6233. {
  6234. if (IntrinsicCommandTable[i].OptionVersionBitmask & OptionVersionValue)
  6235. {
  6236. fprintf (file,
  6237. "------------------------------------------------------------\n");
  6238. DumpOneCommandSyntax (file, IsXref, i);
  6239. }
  6240. }
  6241. fprintf (file,
  6242. "------------------------------------------------------------\n");
  6243. fprintf (file, "\n");
  6244. fprintf (file, "\n");
  6245. fflush (file);
  6246. }
  6247. void
  6248. DumpAllCommandHtmlTable (FILE * file)
  6249. {
  6250. /* generate bwd_cmd.htm */
  6251. int i;
  6252. int j;
  6253. assert (file != NULL);
  6254. /* LEGEND */
  6255. fprintf (file, "<html><head><title>CMDS</title></head><body>\n");
  6256. fprintf (file, "<h1>LEGEND</h1><br>\n");
  6257. fprintf (file, "<table>\n");
  6258. fprintf (file, "<tr>");
  6259. fprintf (file, "<td>");
  6260. fprintf (file, "<b>");
  6261. fprintf (file, "ID");
  6262. fprintf (file, "</b>");
  6263. fprintf (file, "</td>");
  6264. fprintf (file, "<td>");
  6265. fprintf (file, "<b>");
  6266. fprintf (file, "NAME");
  6267. fprintf (file, "</b>");
  6268. fprintf (file, "</td>");
  6269. fprintf (file, "<td>");
  6270. fprintf (file, "<b>");
  6271. fprintf (file, "DESCRIPTION");
  6272. fprintf (file, "</b>");
  6273. fprintf (file, "</td>");
  6274. fprintf (file, "</tr>\n");
  6275. for (j = 0; j < NUM_VERSIONS; j++)
  6276. {
  6277. fprintf (file, "<tr>");
  6278. fprintf (file, "<td>");
  6279. fprintf (file, "%s", bwb_vertable[j].ID);
  6280. fprintf (file, "</td>");
  6281. fprintf (file, "<td>");
  6282. fprintf (file, "%s", bwb_vertable[j].Name);
  6283. fprintf (file, "</td>");
  6284. fprintf (file, "<td>");
  6285. fprintf (file, "%s", bwb_vertable[j].Description);
  6286. fprintf (file, "</td>");
  6287. fprintf (file, "</tr>\n");
  6288. }
  6289. fprintf (file, "</table>\n");
  6290. fprintf (file, "<hr>\n");
  6291. /* DETAILS */
  6292. fprintf (file, "<h1>DETAILS</h1><br>\n");
  6293. fprintf (file, "<table>\n");
  6294. fprintf (file, "<tr>");
  6295. fprintf (file, "<td>");
  6296. fprintf (file, "<b>");
  6297. fprintf (file, "COMMAND");
  6298. fprintf (file, "</b>");
  6299. fprintf (file, "</td>");
  6300. for (j = 0; j < NUM_VERSIONS; j++)
  6301. {
  6302. fprintf (file, "<td>");
  6303. fprintf (file, "<b>");
  6304. fprintf (file, "%s", bwb_vertable[j].ID);
  6305. fprintf (file, "</b>");
  6306. fprintf (file, "</td>");
  6307. }
  6308. fprintf (file, "</tr>\n");
  6309. /* run through the command table and print comand -vs- OPTION VERSION */
  6310. for (i = 0; i < NUM_COMMANDS; i++)
  6311. {
  6312. fprintf (file, "<tr>");
  6313. fprintf (file, "<td>");
  6314. fprintf (file, "%s", (char *) IntrinsicCommandTable[i].Syntax);
  6315. fprintf (file, "</td>");
  6316. for (j = 0; j < NUM_VERSIONS; j++)
  6317. {
  6318. fprintf (file, "<td>");
  6319. if (IntrinsicCommandTable[i].OptionVersionBitmask & bwb_vertable[j].
  6320. OptionVersionValue)
  6321. {
  6322. fprintf (file, "X");
  6323. }
  6324. else
  6325. {
  6326. fprintf (file, " ");
  6327. }
  6328. fprintf (file, "</td>");
  6329. }
  6330. fprintf (file, "</tr>\n");
  6331. }
  6332. fprintf (file, "</table>\n");
  6333. fprintf (file, "</body></html>\n");
  6334. fprintf (file, "\n");
  6335. fflush (file);
  6336. }
  6337. /*
  6338. --------------------------------------------------------------------------------------------
  6339. HELP
  6340. --------------------------------------------------------------------------------------------
  6341. */
  6342. LineType *
  6343. bwb_HELP (LineType * l)
  6344. {
  6345. /* HELP ... */
  6346. int n;
  6347. int Found;
  6348. char *C;
  6349. char *tbuf;
  6350. assert (l != NULL);
  6351. assert( My != NULL );
  6352. assert( My->ConsoleInput != NULL );
  6353. assert( My->SYSOUT != NULL );
  6354. assert( My->SYSOUT->cfp != NULL );
  6355. tbuf = My->ConsoleInput;
  6356. Found = FALSE;
  6357. C = l->buffer;
  6358. C += l->position;
  6359. bwb_strcpy (tbuf, C);
  6360. /* RTRIM$ */
  6361. C = tbuf;
  6362. if (*C != 0)
  6363. {
  6364. /* not an empty line, so remove one (or more) trailing spaces */
  6365. char *E;
  6366. E = bwb_strchr (tbuf, 0);
  6367. E--;
  6368. while (E >= tbuf && *E == ' ')
  6369. {
  6370. *E = 0;
  6371. E--;
  6372. }
  6373. }
  6374. /* EXACT match */
  6375. for (n = 0; n < NUM_COMMANDS; n++)
  6376. {
  6377. if (bwb_stricmp (IntrinsicCommandTable[n].name, tbuf) == 0)
  6378. {
  6379. fprintf (My->SYSOUT->cfp,
  6380. "------------------------------------------------------------\n");
  6381. DumpOneCommandSyntax (My->SYSOUT->cfp, FALSE, n);
  6382. Found = TRUE;
  6383. }
  6384. }
  6385. for (n = 0; n < NUM_FUNCTIONS; n++)
  6386. {
  6387. if (bwb_stricmp (IntrinsicFunctionTable[n].Name, tbuf) == 0)
  6388. {
  6389. fprintf (My->SYSOUT->cfp,
  6390. "------------------------------------------------------------\n");
  6391. DumpOneFunctionSyntax (My->SYSOUT->cfp, FALSE, n);
  6392. Found = TRUE;
  6393. }
  6394. }
  6395. if (Found == FALSE)
  6396. {
  6397. /* PARTIAL match */
  6398. int Length;
  6399. Length = bwb_strlen (tbuf);
  6400. for (n = 0; n < NUM_COMMANDS; n++)
  6401. {
  6402. if (bwb_strnicmp (IntrinsicCommandTable[n].name, tbuf, Length) == 0)
  6403. {
  6404. if (Found == FALSE)
  6405. {
  6406. fprintf (My->SYSOUT->cfp,
  6407. "The following topics are a partial match:\n");
  6408. }
  6409. fprintf (My->SYSOUT->cfp, "%s", IntrinsicCommandTable[n].name);
  6410. fprintf (My->SYSOUT->cfp, "\t");
  6411. Found = TRUE;
  6412. }
  6413. }
  6414. for (n = 0; n < NUM_FUNCTIONS; n++)
  6415. {
  6416. if (bwb_strnicmp (IntrinsicFunctionTable[n].Name, tbuf, Length) == 0)
  6417. {
  6418. if (Found == FALSE)
  6419. {
  6420. fprintf (My->SYSOUT->cfp,
  6421. "The following topics are a partial match:\n");
  6422. }
  6423. fprintf (My->SYSOUT->cfp, "%s", IntrinsicFunctionTable[n].Name);
  6424. fprintf (My->SYSOUT->cfp, "\t");
  6425. Found = TRUE;
  6426. }
  6427. }
  6428. if (Found == TRUE)
  6429. {
  6430. /* match */
  6431. fprintf (My->SYSOUT->cfp, "\n");
  6432. }
  6433. }
  6434. if (Found == FALSE)
  6435. {
  6436. /* NO match */
  6437. fprintf (My->SYSOUT->cfp, "No help found.\n");
  6438. }
  6439. ResetConsoleColumn ();
  6440. line_skip_eol (l);
  6441. return (l);
  6442. }
  6443. int
  6444. NumberValueCheck (ParamTestType ParameterTests, DoubleType X)
  6445. {
  6446. DoubleType XR; /* rounded value */
  6447. unsigned char TestNibble;
  6448. /* VerifyNumeric */
  6449. if (isnan (X))
  6450. {
  6451. /* INTERNAL ERROR */
  6452. return -1;
  6453. }
  6454. if (isinf (X))
  6455. {
  6456. /* - Evaluation of an expression results in an overflow
  6457. * (nonfatal, the recommended recovery procedure is to supply
  6458. * machine in- finity with the algebraically correct sign and
  6459. * continue). */
  6460. if (X < 0)
  6461. {
  6462. X = MINDBL;
  6463. }
  6464. else
  6465. {
  6466. X = MAXDBL;
  6467. }
  6468. if (WARN_OVERFLOW)
  6469. {
  6470. /* ERROR */
  6471. return -1;
  6472. }
  6473. /* CONTINUE */
  6474. }
  6475. /* OK */
  6476. /* VALID NUMERIC VALUE */
  6477. XR = bwb_rint (X);
  6478. ParameterTests &= 0x0000000F;
  6479. TestNibble = (unsigned char) ParameterTests;
  6480. switch (TestNibble)
  6481. {
  6482. case P1ERR:
  6483. /* INTERNAL ERROR */
  6484. return -1;
  6485. /* break; */
  6486. case P1ANY:
  6487. if (X < MINDBL || X > MAXDBL)
  6488. {
  6489. /* ERROR */
  6490. return -1;
  6491. }
  6492. /* OK */
  6493. return 0;
  6494. /* break; */
  6495. case P1BYT:
  6496. if (XR < MINBYT || XR > MAXBYT)
  6497. {
  6498. /* ERROR */
  6499. return -1;
  6500. }
  6501. /* OK */
  6502. return 0;
  6503. /* break; */
  6504. case P1INT:
  6505. if (XR < MININT || XR > MAXINT)
  6506. {
  6507. /* ERROR */
  6508. return -1;
  6509. }
  6510. /* OK */
  6511. return 0;
  6512. /* break; */
  6513. case P1LNG:
  6514. if (XR < MINLNG || XR > MAXLNG)
  6515. {
  6516. /* ERROR */
  6517. return -1;
  6518. }
  6519. /* OK */
  6520. return 0;
  6521. /* break; */
  6522. case P1CUR:
  6523. if (XR < MINCUR || XR > MAXCUR)
  6524. {
  6525. /* ERROR */
  6526. return -1;
  6527. }
  6528. /* OK */
  6529. return 0;
  6530. /* break; */
  6531. case P1FLT:
  6532. if (X < MINSNG || X > MAXSNG)
  6533. {
  6534. /* ERROR */
  6535. return -1;
  6536. }
  6537. /* OK */
  6538. return 0;
  6539. /* break; */
  6540. case P1DBL:
  6541. if (X < MINDBL || X > MAXDBL)
  6542. {
  6543. /* ERROR */
  6544. return -1;
  6545. }
  6546. /* OK */
  6547. return 0;
  6548. /* break; */
  6549. case P1DEV:
  6550. /* ERROR */
  6551. return -1;
  6552. /* break; */
  6553. case P1LEN:
  6554. if (XR < MINLEN || XR > MAXLEN)
  6555. {
  6556. /* ERROR */
  6557. return -1;
  6558. }
  6559. /* OK */
  6560. return 0;
  6561. /* break; */
  6562. case P1POS:
  6563. if (XR < 1 || XR > MAXLEN)
  6564. {
  6565. /* ERROR */
  6566. return -1;
  6567. }
  6568. /* OK */
  6569. return 0;
  6570. /* break; */
  6571. case P1COM:
  6572. /* ERROR */
  6573. return -1;
  6574. /* break; */
  6575. case P1LPT:
  6576. /* ERROR */
  6577. return -1;
  6578. /* break; */
  6579. case P1GTZ:
  6580. if (X > 0)
  6581. {
  6582. /* OK */
  6583. return 0;
  6584. }
  6585. break;
  6586. case P1GEZ:
  6587. if (X >= 0)
  6588. {
  6589. /* OK */
  6590. return 0;
  6591. }
  6592. break;
  6593. case P1NEZ:
  6594. if (X != 0)
  6595. {
  6596. /* OK */
  6597. return 0;
  6598. }
  6599. break;
  6600. }
  6601. /* ERROR */
  6602. return -1;
  6603. }
  6604. int
  6605. StringLengthCheck (ParamTestType ParameterTests, int s)
  6606. {
  6607. unsigned char TestNibble;
  6608. /* check for invalid string length */
  6609. if (s < 0 || s > MAXLEN)
  6610. {
  6611. /* INTERNAL ERROR */
  6612. return -1;
  6613. }
  6614. /* VALID STRING LENGTH */
  6615. ParameterTests &= 0x0000000F;
  6616. TestNibble = (unsigned char) ParameterTests;
  6617. switch (TestNibble)
  6618. {
  6619. case P1ERR:
  6620. /* INTERNAL ERROR */
  6621. return -1;
  6622. /* break; */
  6623. case P1ANY:
  6624. /* OK */
  6625. return 0;
  6626. /* break; */
  6627. case P1BYT:
  6628. if (s >= sizeof (ByteType))
  6629. {
  6630. /* OK */
  6631. return 0;
  6632. }
  6633. break;
  6634. case P1INT:
  6635. if (s >= sizeof (IntegerType))
  6636. {
  6637. /* OK */
  6638. return 0;
  6639. }
  6640. break;
  6641. case P1LNG:
  6642. if (s >= sizeof (LongType))
  6643. {
  6644. /* OK */
  6645. return 0;
  6646. }
  6647. break;
  6648. case P1CUR:
  6649. if (s >= sizeof (CurrencyType))
  6650. {
  6651. /* OK */
  6652. return 0;
  6653. }
  6654. break;
  6655. case P1FLT:
  6656. if (s >= sizeof (SingleType))
  6657. {
  6658. /* OK */
  6659. return 0;
  6660. }
  6661. break;
  6662. case P1DBL:
  6663. if (s >= sizeof (DoubleType))
  6664. {
  6665. /* OK */
  6666. return 0;
  6667. }
  6668. break;
  6669. case P1DEV:
  6670. /* ERROR */
  6671. return -1;
  6672. /* break; */
  6673. case P1LEN:
  6674. /* ERROR */
  6675. return -1;
  6676. /* break; */
  6677. case P1POS:
  6678. /* ERROR */
  6679. return -1;
  6680. /* break; */
  6681. case P1GEZ:
  6682. /* ERROR */
  6683. return -1;
  6684. /* break; */
  6685. case P1GTZ:
  6686. /* ERROR */
  6687. return -1;
  6688. /* break; */
  6689. case P1NEZ:
  6690. /* ERROR */
  6691. return -1;
  6692. /* break; */
  6693. }
  6694. /* ERROR */
  6695. return -1;
  6696. }
  6697. void
  6698. IntrinsicFunctionDefinitionCheck (IntrinsicFunctionType * f)
  6699. {
  6700. /* function definition check -- look for obvious errors */
  6701. assert (f != NULL);
  6702. assert( My != NULL );
  6703. assert( My->SYSOUT != NULL );
  6704. assert( My->SYSOUT->cfp != NULL );
  6705. /* sanity check */
  6706. if (f->ParameterCount == PNONE || f->ParameterCount == 0xFF)
  6707. {
  6708. /* function has NO explicit parameters */
  6709. if (f->ParameterTypes == PNONE)
  6710. {
  6711. /* OK */
  6712. }
  6713. else
  6714. {
  6715. /* oops */
  6716. fprintf (My->SYSOUT->cfp, "invalid ParameterTypes <%s>\n", f->Name);
  6717. }
  6718. if (f->ParameterTests == PNONE)
  6719. {
  6720. /* OK */
  6721. }
  6722. else
  6723. {
  6724. /* oops */
  6725. fprintf (My->SYSOUT->cfp, "invalid ParameterTests <%s>\n", f->Name);
  6726. }
  6727. }
  6728. else
  6729. {
  6730. /* function HAS an explicit number of parameters */
  6731. int i;
  6732. ParamTestType ParameterTests;
  6733. ParameterTests = f->ParameterTests;
  6734. for (i = 0; i < f->ParameterCount; i++)
  6735. {
  6736. /* sanity check this parameter */
  6737. ParamTestType thischeck;
  6738. thischeck = ParameterTests & 0x0000000F;
  6739. /* verify parameter check */
  6740. if (f->ParameterTypes & (1 << i))
  6741. {
  6742. /* STRING */
  6743. if (thischeck >= P1ANY && thischeck <= P1DBL)
  6744. {
  6745. /* OK */
  6746. }
  6747. else
  6748. {
  6749. /* oops */
  6750. fprintf (My->SYSOUT->cfp,
  6751. "invalid ParameterTests <%s> parameter %d\n", f->Name,
  6752. i + 1);
  6753. }
  6754. }
  6755. else
  6756. {
  6757. /* NUMBER */
  6758. if (thischeck >= P1ANY && thischeck <= P1NEZ)
  6759. {
  6760. /* OK */
  6761. }
  6762. else
  6763. {
  6764. /* oops */
  6765. fprintf (My->SYSOUT->cfp,
  6766. "invalid ParameterTests <%s> parameter %d\n", f->Name,
  6767. i + 1);
  6768. }
  6769. }
  6770. ParameterTests = ParameterTests >> 4;
  6771. }
  6772. if (ParameterTests != 0)
  6773. {
  6774. /* oops */
  6775. fprintf (My->SYSOUT->cfp, "invalid ParameterTests <%s> parameter %d\n",
  6776. f->Name, i + 1);
  6777. }
  6778. }
  6779. }
  6780. void
  6781. IntrinsicFunctionUniqueID (IntrinsicFunctionType * f, char *UniqueID)
  6782. {
  6783. /* generate the function's UniqueID */
  6784. /* manual fixup required for duplicates */
  6785. char NumVar;
  6786. char StrVar;
  6787. assert (f != NULL);
  6788. assert (UniqueID != NULL);
  6789. NumVar = 'X';
  6790. StrVar = 'A';
  6791. /* F_ */
  6792. bwb_strcpy (UniqueID, "F_");
  6793. /* NAME */
  6794. bwb_strcat (UniqueID, f->Name);
  6795. /* PARAMETERS */
  6796. if (f->ParameterCount == PNONE || f->ParameterCount == 0xFF)
  6797. {
  6798. /* function has NO explicit parameters */
  6799. }
  6800. else
  6801. {
  6802. /* function HAS explicit parameters */
  6803. int i;
  6804. ParamBitsType ParameterTypes;
  6805. ParameterTypes = f->ParameterTypes;
  6806. for (i = 0; i < f->ParameterCount; i++)
  6807. {
  6808. char VarName[NameLengthMax + 1];
  6809. if (ParameterTypes & 1)
  6810. {
  6811. /* STRING */
  6812. sprintf (VarName, "_%c", StrVar);
  6813. StrVar++;
  6814. }
  6815. else
  6816. {
  6817. /* NUMBER */
  6818. sprintf (VarName, "_%c", NumVar);
  6819. NumVar++;
  6820. }
  6821. bwb_strcat (UniqueID, VarName);
  6822. ParameterTypes = ParameterTypes >> 1;
  6823. }
  6824. }
  6825. /* RETURN TYPE */
  6826. if (f->ReturnTypeCode == StringTypeCode)
  6827. {
  6828. bwb_strcat (UniqueID, "_S");
  6829. }
  6830. else
  6831. {
  6832. bwb_strcat (UniqueID, "_N");
  6833. }
  6834. /* fixup illegal characters, "DEF FN" "BLOAD:", "CLOAD*" */
  6835. FixUp (UniqueID);
  6836. }
  6837. void
  6838. IntrinsicFunctionSyntax (IntrinsicFunctionType * f, char *Syntax)
  6839. {
  6840. /* generate the function's Syntax */
  6841. char NumVar;
  6842. char StrVar;
  6843. assert (f != NULL);
  6844. assert (Syntax != NULL);
  6845. NumVar = 'X';
  6846. StrVar = 'A';
  6847. /* RETURN TYPE */
  6848. if (f->ReturnTypeCode == StringTypeCode)
  6849. {
  6850. bwb_strcpy (Syntax, "S$ = ");
  6851. }
  6852. else
  6853. {
  6854. bwb_strcpy (Syntax, "N = ");
  6855. }
  6856. /* NAME */
  6857. bwb_strcat (Syntax, f->Name);
  6858. /* PARAMETERS */
  6859. if (f->ParameterCount == PNONE)
  6860. {
  6861. /* function has NO explicit parameters */
  6862. }
  6863. else if (f->ParameterCount == 0xFF)
  6864. {
  6865. /* function has a variable number of parameters */
  6866. bwb_strcat (Syntax, "( ... )");
  6867. }
  6868. else
  6869. {
  6870. /* function HAS explicit parameters */
  6871. int i;
  6872. ParamBitsType ParameterTypes;
  6873. ParameterTypes = f->ParameterTypes;
  6874. if (f->ReturnTypeCode == StringTypeCode)
  6875. {
  6876. bwb_strcat (Syntax, "( ");
  6877. }
  6878. else
  6879. {
  6880. bwb_strcat (Syntax, "( ");
  6881. }
  6882. for (i = 0; i < f->ParameterCount; i++)
  6883. {
  6884. char VarName[NameLengthMax + 1];
  6885. if (i > 0)
  6886. {
  6887. bwb_strcat (Syntax, ", ");
  6888. }
  6889. /* verify parameter check */
  6890. if (ParameterTypes & 1)
  6891. {
  6892. /* STRING */
  6893. sprintf (VarName, "%c$", StrVar);
  6894. StrVar++;
  6895. }
  6896. else
  6897. {
  6898. /* NUMBER */
  6899. sprintf (VarName, "%c", NumVar);
  6900. NumVar++;
  6901. }
  6902. bwb_strcat (Syntax, VarName);
  6903. ParameterTypes = ParameterTypes >> 1;
  6904. }
  6905. if (f->ReturnTypeCode == StringTypeCode)
  6906. {
  6907. bwb_strcat (Syntax, " )");
  6908. }
  6909. else
  6910. {
  6911. bwb_strcat (Syntax, " )");
  6912. }
  6913. }
  6914. }
  6915. void
  6916. DumpAllFunctionUniqueID (FILE * file)
  6917. {
  6918. /* for the C maintainer */
  6919. int i;
  6920. int j;
  6921. char LastUniqueID[NameLengthMax + 1];
  6922. assert (file != NULL);
  6923. j = 0;
  6924. LastUniqueID[0] = NulChar;
  6925. fprintf (file, "/* FUNCTIONS */\n");
  6926. for (i = 0; i < NUM_FUNCTIONS; i++)
  6927. {
  6928. char UniqueID[NameLengthMax + 1];
  6929. IntrinsicFunctionUniqueID (&(IntrinsicFunctionTable[i]), UniqueID);
  6930. if (bwb_stricmp (LastUniqueID, UniqueID) != 0)
  6931. {
  6932. /* not a duplicate */
  6933. char Syntax[NameLengthMax + 1];
  6934. bwb_strcpy (LastUniqueID, UniqueID);
  6935. j = j + 1;
  6936. IntrinsicFunctionSyntax (&(IntrinsicFunctionTable[i]), Syntax);
  6937. fprintf (file, "#define %-30s %3d /* %-30s */\n", UniqueID, j, Syntax);
  6938. }
  6939. }
  6940. fprintf (file, "#define NUM_FUNCTIONS %d\n", j);
  6941. fflush (file);
  6942. }
  6943. void
  6944. DumpAllFunctionSwitch (FILE * file)
  6945. {
  6946. /* for the C maintainer */
  6947. int i;
  6948. assert (file != NULL);
  6949. fprintf (file, "/* SWITCH */\n");
  6950. fprintf (file, "switch( UniqueID )\n");
  6951. fprintf (file, "{\n");
  6952. for (i = 0; i < NUM_FUNCTIONS; i++)
  6953. {
  6954. char tbuf[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpAllFunctionSwitch */
  6955. fprintf (file, "case ");
  6956. IntrinsicFunctionUniqueID (&(IntrinsicFunctionTable[i]), tbuf);
  6957. fprintf (file, "%s", tbuf);
  6958. fprintf (file, ":\n");
  6959. fprintf (file, " break;\n");
  6960. }
  6961. fprintf (file, "}\n");
  6962. fflush (file);
  6963. }
  6964. static const char *ParameterRangeID[16] = {
  6965. "P%dERR",
  6966. "P%dANY",
  6967. "P%dBYT",
  6968. "P%dINT",
  6969. "P%dLNG",
  6970. "P%dCUR",
  6971. "P%dFLT",
  6972. "P%dDBL",
  6973. "P%dDEV",
  6974. "P%dLEN",
  6975. "P%dPOS",
  6976. "P%dCOM",
  6977. "P%dLPT",
  6978. "P%dGTZ",
  6979. "P%dGEZ",
  6980. "P%dNEZ",
  6981. };
  6982. static const char *NumberVariableRange[16] = {
  6983. /* P1ERR */ " PARAMETER: %c is a number, INTERNAL ERROR",
  6984. /* P1ANY */ " PARAMETER: %c is a number",
  6985. /* P1BYT */ " PARAMETER: %c is a number, [0,255]",
  6986. /* P1INT */ " PARAMETER: %c is a number, [MININT,MAXINT]",
  6987. /* P1LNG */ " PARAMETER: %c is a number, [MINLNG,MAXLNG]",
  6988. /* P1CUR */ " PARAMETER: %c is a number, [MINCUR,MAXCUR]",
  6989. /* P1FLT */ " PARAMETER: %c is a number, [MINFLT,MAXFLT]",
  6990. /* P1DBL */ " PARAMETER: %c is a number, [MINDBL,MAXDBL]",
  6991. /* P1DEV */ " PARAMETER: %c is a number, RESERVED",
  6992. /* P1LEN */ " PARAMETER: %c is a number, [0,MAXLEN]",
  6993. /* P1POS */ " PARAMETER: %c is a number, [1,MAXLEN]",
  6994. /* P1COM */ " PARAMETER: %c is a number, RESERVED",
  6995. /* P1LPT */ " PARAMETER: %c is a number, RESERVED",
  6996. /* P1GTZ */ " PARAMETER: %c is a number, > 0",
  6997. /* P1GEZ */ " PARAMETER: %c is a number, >= 0",
  6998. /* P1NEZ */ " PARAMETER: %c is a number, <> 0",
  6999. };
  7000. static const char *StringVariableRange[16] = {
  7001. /* P1ERR */ " PARAMETER: %c$ is a string, INTERNAL ERROR",
  7002. /* P1ANY */ " PARAMETER: %c$ is a string, LEN >= 0",
  7003. /* P1BYT */ " PARAMETER: %c$ is a string, LEN >= 1",
  7004. /* P1INT */ " PARAMETER: %c$ is a string, LEN >= sizeof(INT)",
  7005. /* P1LNG */ " PARAMETER: %c$ is a string, LEN >= sizeof(LNG)",
  7006. /* P1CUR */ " PARAMETER: %c$ is a string, LEN >= sizeof(CUR)",
  7007. /* P1FLT */ " PARAMETER: %c$ is a string, LEN >= sizeof(FLT)",
  7008. /* P1DBL */ " PARAMETER: %c$ is a string, LEN >= sizeof(DBL)",
  7009. /* P1DEV */ " PARAMETER: %c$ is a string, RESERVED",
  7010. /* P1LEN */ " PARAMETER: %c$ is a string, RESERVED",
  7011. /* P1POS */ " PARAMETER: %c$ is a string, RESERVED",
  7012. /* P1COM */ " PARAMETER: %c$ is a string, RESERVED",
  7013. /* P1LPT */ " PARAMETER: %c$ is a string, RESERVED",
  7014. /* P1GTZ */ " PARAMETER: %c$ is a string, RESERVED",
  7015. /* P1GEZ */ " PARAMETER: %c$ is a string, RESERVED",
  7016. /* P1NEZ */ " PARAMETER: %c$ is a string, RESERVED",
  7017. };
  7018. void
  7019. DumpAllFuctionTableDefinitions (FILE * file)
  7020. {
  7021. /* generate bwd_fun.c */
  7022. int n;
  7023. assert (file != NULL);
  7024. fprintf (file, "/* FUNCTION TABLE */\n");
  7025. fprintf (file, "\n");
  7026. fprintf (file, "#include \"bwbasic.h\"\n");
  7027. fprintf (file, "\n");
  7028. fprintf (file,
  7029. "IntrinsicFunctionType IntrinsicFunctionTable[ /* NUM_FUNCTIONS */ ] =\n");
  7030. fprintf (file, "{\n");
  7031. for (n = 0; n < NUM_FUNCTIONS; n++)
  7032. {
  7033. int i;
  7034. int j;
  7035. char tbuf[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpAllFuctionTableDefinitions */
  7036. char UniqueID[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpAllFuctionTableDefinitions */
  7037. char Syntax[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpAllFuctionTableDefinitions */
  7038. IntrinsicFunctionType *f;
  7039. f = &(IntrinsicFunctionTable[n]);
  7040. IntrinsicFunctionUniqueID (f, UniqueID);
  7041. IntrinsicFunctionSyntax (f, Syntax);
  7042. fprintf (file, "{\n");
  7043. fprintf (file, " %s, /* UniqueID */\n", UniqueID);
  7044. fprintf (file, " \"%s\", /* Syntax */\n", Syntax);
  7045. fprintf (file, " ");
  7046. fprintf (file, "\"");
  7047. ProcessEscapeChars (f->Description, tbuf);
  7048. fprintf (file, "%s", tbuf);
  7049. fprintf (file, "\"");
  7050. fprintf (file, ", /* Description */\n");
  7051. fprintf (file, " \"%s\", /* Name */\n", f->Name);
  7052. switch (f->ReturnTypeCode)
  7053. {
  7054. case ByteTypeCode:
  7055. fprintf (file, " %s, /* ReturnTypeCode */\n", "ByteTypeCode");
  7056. break;
  7057. case IntegerTypeCode:
  7058. fprintf (file, " %s, /* ReturnTypeCode */\n", "IntegerTypeCode");
  7059. break;
  7060. case LongTypeCode:
  7061. fprintf (file, " %s, /* ReturnTypeCode */\n", "LongTypeCode");
  7062. break;
  7063. case CurrencyTypeCode:
  7064. fprintf (file, " %s, /* ReturnTypeCode */\n", "CurrencyTypeCode");
  7065. break;
  7066. case SingleTypeCode:
  7067. fprintf (file, " %s, /* ReturnTypeCode */\n", "SingleTypeCode");
  7068. break;
  7069. case DoubleTypeCode:
  7070. fprintf (file, " %s, /* ReturnTypeCode */\n", "DoubleTypeCode");
  7071. break;
  7072. case StringTypeCode:
  7073. fprintf (file, " %s, /* ReturnTypeCode */\n", "StringTypeCode");
  7074. break;
  7075. default:
  7076. fprintf (file, " %s, /* ReturnTypeCode */\n", "INTERNAL ERROR");
  7077. break;
  7078. }
  7079. fprintf (file, " %d, /* ParameterCount */\n", f->ParameterCount);
  7080. if (f->ParameterCount == 0 || f->ParameterCount == 0xFF)
  7081. {
  7082. /* function has NO explicit parameters */
  7083. fprintf (file, " %s, /* ParameterTypes */\n", "PNONE");
  7084. fprintf (file, " %s, /* ParameterTests */\n", "PNONE");
  7085. }
  7086. else
  7087. {
  7088. /* function has explicit parameters */
  7089. bwb_strcpy (tbuf, " ");
  7090. for (i = 0; i < f->ParameterCount; i++)
  7091. {
  7092. ParamBitsType ParameterTypes;
  7093. ParameterTypes = f->ParameterTypes >> i;
  7094. ParameterTypes &= 0x1;
  7095. if (i > 0)
  7096. {
  7097. bwb_strcat (tbuf, " | ");
  7098. }
  7099. if (ParameterTypes)
  7100. {
  7101. sprintf (bwb_strchr (tbuf, NulChar), "P%dSTR", i + 1);
  7102. }
  7103. else
  7104. {
  7105. sprintf (bwb_strchr (tbuf, NulChar), "P%dNUM", i + 1);
  7106. }
  7107. }
  7108. bwb_strcat (tbuf, ", /* ParameterTypes */\n");
  7109. fprintf (file, "%s", tbuf);
  7110. bwb_strcpy (tbuf, " ");
  7111. for (i = 0; i < f->ParameterCount; i++)
  7112. {
  7113. ParamTestType ParameterTests;
  7114. ParameterTests = f->ParameterTests >> (i * 4);
  7115. ParameterTests &= 0xF;
  7116. if (i > 0)
  7117. {
  7118. bwb_strcat (tbuf, " | ");
  7119. }
  7120. sprintf (bwb_strchr (tbuf, 0), ParameterRangeID[ParameterTests],
  7121. i + 1);
  7122. /* Conversion may lose significant digits */
  7123. }
  7124. bwb_strcat (tbuf, ", /* ParameterTests */\n");
  7125. fprintf (file, "%s", tbuf);
  7126. }
  7127. bwb_strcpy (tbuf, " ");
  7128. j = 0;
  7129. for (i = 0; i < NUM_VERSIONS; i++)
  7130. {
  7131. if (f->OptionVersionBitmask & bwb_vertable[i].OptionVersionValue)
  7132. {
  7133. if (j > 0)
  7134. {
  7135. bwb_strcat (tbuf, " | ");
  7136. }
  7137. bwb_strcat (tbuf, bwb_vertable[i].ID);
  7138. j++;
  7139. }
  7140. }
  7141. bwb_strcat (tbuf, " /* OptionVersionBitmask */\n");
  7142. fprintf (file, "%s", tbuf);
  7143. fprintf (file, "},\n");
  7144. }
  7145. fprintf (file, "};\n");
  7146. fprintf (file, "\n");
  7147. fprintf (file,
  7148. "const size_t NUM_FUNCTIONS = sizeof( IntrinsicFunctionTable ) / sizeof( IntrinsicFunctionType );\n");
  7149. fprintf (file, "\n");
  7150. fflush (file);
  7151. }
  7152. void
  7153. DumpOneFunctionSyntax (FILE * file, int IsXref, int n)
  7154. {
  7155. IntrinsicFunctionType *f;
  7156. assert (file != NULL);
  7157. if (n < 0 || n >= NUM_FUNCTIONS)
  7158. {
  7159. return;
  7160. }
  7161. f = &(IntrinsicFunctionTable[n]);
  7162. /* NAME */
  7163. {
  7164. char UniqueID[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpOneFunctionSyntax */
  7165. char Syntax[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpOneFunctionSyntax */
  7166. IntrinsicFunctionUniqueID (f, UniqueID);
  7167. IntrinsicFunctionSyntax (f, Syntax);
  7168. fprintf (file, " SYNTAX: %s\n", Syntax);
  7169. }
  7170. /* PARAMETERS */
  7171. if (f->ParameterCount == PNONE || f->ParameterCount == 0xFF)
  7172. {
  7173. /* function has NO explicit parameters */
  7174. }
  7175. else
  7176. {
  7177. /* function HAS explicit parameters */
  7178. int i;
  7179. ParamBitsType ParameterTypes;
  7180. ParamTestType ParameterTests;
  7181. char NumVar;
  7182. char StrVar;
  7183. ParameterTypes = f->ParameterTypes;
  7184. ParameterTests = f->ParameterTests;
  7185. NumVar = 'X';
  7186. StrVar = 'A';
  7187. for (i = 0; i < f->ParameterCount; i++)
  7188. {
  7189. /* sanity check this parameter */
  7190. unsigned long thischeck;
  7191. char tbuf[MAINTAINER_BUFFER_LENGTH + 1]; /* DumpOneFunctionSyntax */
  7192. thischeck = ParameterTests & 0x0000000F;
  7193. /* verify parameter check */
  7194. if (ParameterTypes & 1)
  7195. {
  7196. /* STRING */
  7197. sprintf (tbuf, StringVariableRange[thischeck], StrVar);
  7198. /* Conversion may lose significant digits */
  7199. StrVar++;
  7200. }
  7201. else
  7202. {
  7203. /* NUMBER */
  7204. sprintf (tbuf, NumberVariableRange[thischeck], NumVar);
  7205. /* Conversion may lose significant digits */
  7206. NumVar++;
  7207. }
  7208. fprintf (file, "%s", tbuf);
  7209. fprintf (file, "\n");
  7210. ParameterTypes = ParameterTypes >> 1;
  7211. ParameterTests = ParameterTests >> 4;
  7212. }
  7213. }
  7214. /* DESCRIPTION */
  7215. {
  7216. FixDescription (file, "DESCRIPTION: ", f->Description);
  7217. }
  7218. /* COMPATIBILITY */
  7219. if (IsXref)
  7220. {
  7221. int i;
  7222. fprintf (file, " VERSIONS:\n");
  7223. for (i = 0; i < NUM_VERSIONS; i++)
  7224. {
  7225. char X;
  7226. if (f->OptionVersionBitmask & bwb_vertable[i].OptionVersionValue)
  7227. {
  7228. /* SUPPORTED */
  7229. X = 'X';
  7230. }
  7231. else
  7232. {
  7233. /* NOT SUPPORTED */
  7234. X = '_';
  7235. }
  7236. fprintf (file, " [%c] %s\n", X, bwb_vertable[i].Name);
  7237. }
  7238. }
  7239. fflush (file);
  7240. }
  7241. void
  7242. DumpAllFunctionSyntax (FILE * file, int IsXref,
  7243. OptionVersionType OptionVersionValue)
  7244. {
  7245. /* for the C maintainer */
  7246. int i;
  7247. assert (file != NULL);
  7248. fprintf (file,
  7249. "============================================================\n");
  7250. fprintf (file,
  7251. " FUNCTIONS \n");
  7252. fprintf (file,
  7253. "============================================================\n");
  7254. fprintf (file, "\n");
  7255. fprintf (file, "\n");
  7256. for (i = 0; i < NUM_FUNCTIONS; i++)
  7257. {
  7258. if (IntrinsicFunctionTable[i].OptionVersionBitmask & OptionVersionValue)
  7259. {
  7260. fprintf (file,
  7261. "------------------------------------------------------------\n");
  7262. DumpOneFunctionSyntax (file, IsXref, i);
  7263. }
  7264. }
  7265. fprintf (file,
  7266. "------------------------------------------------------------\n");
  7267. fprintf (file, "\n");
  7268. fprintf (file, "\n");
  7269. fflush (file);
  7270. }
  7271. void
  7272. DumpAllFunctionHtmlTable (FILE * file)
  7273. {
  7274. /* generate bwd_cmd.htm */
  7275. int i;
  7276. int j;
  7277. assert (file != NULL);
  7278. /* LEGEND */
  7279. fprintf (file, "<html><head><title>FNCS</title></head><body>\n");
  7280. fprintf (file, "<h1>LEGEND</h1><br>\n");
  7281. fprintf (file, "<table>\n");
  7282. fprintf (file, "<tr>");
  7283. fprintf (file, "<td>");
  7284. fprintf (file, "<b>");
  7285. fprintf (file, "ID");
  7286. fprintf (file, "</b>");
  7287. fprintf (file, "</td>");
  7288. fprintf (file, "<td>");
  7289. fprintf (file, "<b>");
  7290. fprintf (file, "NAME");
  7291. fprintf (file, "</b>");
  7292. fprintf (file, "</td>");
  7293. fprintf (file, "<td>");
  7294. fprintf (file, "<b>");
  7295. fprintf (file, "DESCRIPTION");
  7296. fprintf (file, "</b>");
  7297. fprintf (file, "</td>");
  7298. fprintf (file, "</tr>\n");
  7299. for (j = 0; j < NUM_VERSIONS; j++)
  7300. {
  7301. fprintf (file, "<tr>");
  7302. fprintf (file, "<td>");
  7303. fprintf (file, "%s", bwb_vertable[j].ID);
  7304. fprintf (file, "</td>");
  7305. fprintf (file, "<td>");
  7306. fprintf (file, "%s", bwb_vertable[j].Name);
  7307. fprintf (file, "</td>");
  7308. fprintf (file, "<td>");
  7309. fprintf (file, "%s", bwb_vertable[j].Description);
  7310. fprintf (file, "</td>");
  7311. fprintf (file, "</tr>\n");
  7312. }
  7313. fprintf (file, "</table>\n");
  7314. fprintf (file, "<hr>\n");
  7315. /* DETAILS */
  7316. fprintf (file, "<h1>DETAILS</h1><br>\n");
  7317. fprintf (file, "<table>\n");
  7318. fprintf (file, "<tr>");
  7319. fprintf (file, "<td>");
  7320. fprintf (file, "<b>");
  7321. fprintf (file, "FUNCTION");
  7322. fprintf (file, "</b>");
  7323. fprintf (file, "</td>");
  7324. for (j = 0; j < NUM_VERSIONS; j++)
  7325. {
  7326. fprintf (file, "<td>");
  7327. fprintf (file, "<b>");
  7328. fprintf (file, "%s", bwb_vertable[j].ID);
  7329. fprintf (file, "</b>");
  7330. fprintf (file, "</td>");
  7331. }
  7332. fprintf (file, "</tr>\n");
  7333. /* run through the command table and print comand -vs- OPTION VERSION */
  7334. for (i = 0; i < NUM_FUNCTIONS; i++)
  7335. {
  7336. fprintf (file, "<tr>");
  7337. fprintf (file, "<td>");
  7338. fprintf (file, "%s", (char *) IntrinsicFunctionTable[i].Syntax);
  7339. fprintf (file, "</td>");
  7340. for (j = 0; j < NUM_VERSIONS; j++)
  7341. {
  7342. fprintf (file, "<td>");
  7343. if (IntrinsicFunctionTable[i].OptionVersionBitmask & bwb_vertable[j].
  7344. OptionVersionValue)
  7345. {
  7346. fprintf (file, "X");
  7347. }
  7348. else
  7349. {
  7350. fprintf (file, " ");
  7351. }
  7352. fprintf (file, "</td>");
  7353. }
  7354. fprintf (file, "</tr>\n");
  7355. }
  7356. fprintf (file, "</table>\n");
  7357. fprintf (file, "</body></html>\n");
  7358. fprintf (file, "\n");
  7359. fflush (file);
  7360. }
  7361. /*
  7362. --------------------------------------------------------------------------------------------
  7363. FNCS
  7364. --------------------------------------------------------------------------------------------
  7365. */
  7366. LineType *
  7367. bwb_FNCS (LineType * l)
  7368. {
  7369. int n;
  7370. int t;
  7371. assert (l != NULL);
  7372. assert( My != NULL );
  7373. assert( My->SYSOUT != NULL );
  7374. assert( My->SYSOUT->cfp != NULL );
  7375. My->CurrentFile = My->SYSOUT;
  7376. fprintf (My->SYSOUT->cfp, "BWBASIC FUNCTIONS AVAILABLE:\n");
  7377. /* run through the command table and print comand names */
  7378. t = 0;
  7379. for (n = 0; n < NUM_FUNCTIONS; n++)
  7380. {
  7381. fprintf (My->SYSOUT->cfp, "%s", IntrinsicFunctionTable[n].Name);
  7382. if (t < 4)
  7383. {
  7384. fprintf (My->SYSOUT->cfp, "\t");
  7385. t++;
  7386. }
  7387. else
  7388. {
  7389. fprintf (My->SYSOUT->cfp, "\n");
  7390. t = 0;
  7391. }
  7392. }
  7393. if (t > 0)
  7394. {
  7395. fprintf (My->SYSOUT->cfp, "\n");
  7396. }
  7397. ResetConsoleColumn ();
  7398. return (l);
  7399. }
  7400. /*
  7401. --------------------------------------------------------------------------------------------
  7402. MAINTAINER
  7403. --------------------------------------------------------------------------------------------
  7404. */
  7405. LineType *
  7406. bwb_MAINTAINER (LineType * l)
  7407. {
  7408. assert (l != NULL);
  7409. WARN_SYNTAX_ERROR;
  7410. return (l);
  7411. }
  7412. LineType *
  7413. bwb_MAINTAINER_CMDS (LineType * l)
  7414. {
  7415. assert (l != NULL);
  7416. WARN_SYNTAX_ERROR;
  7417. return (l);
  7418. }
  7419. LineType *
  7420. bwb_MAINTAINER_CMDS_HTML (LineType * l)
  7421. {
  7422. assert (l != NULL);
  7423. assert(My != NULL);
  7424. assert(My->SYSPRN != NULL);
  7425. assert(My->SYSPRN->cfp != NULL);
  7426. DumpAllCommandHtmlTable (My->SYSPRN->cfp);
  7427. return (l);
  7428. }
  7429. LineType *
  7430. bwb_MAINTAINER_CMDS_ID (LineType * l)
  7431. {
  7432. assert (l != NULL);
  7433. assert(My != NULL);
  7434. assert(My->SYSPRN != NULL);
  7435. assert(My->SYSPRN->cfp != NULL);
  7436. DumpAllCommandUniqueID (My->SYSPRN->cfp);
  7437. return (l);
  7438. }
  7439. LineType *
  7440. bwb_MAINTAINER_CMDS_MANUAL (LineType * l)
  7441. {
  7442. assert (l != NULL);
  7443. assert(My != NULL);
  7444. assert(My->SYSPRN != NULL);
  7445. assert(My->SYSPRN->cfp != NULL);
  7446. DumpAllCommandSyntax (My->SYSPRN->cfp, TRUE, (OptionVersionType)(-1));
  7447. return (l);
  7448. }
  7449. LineType *
  7450. bwb_MAINTAINER_CMDS_SWITCH (LineType * l)
  7451. {
  7452. assert (l != NULL);
  7453. assert(My != NULL);
  7454. assert(My->SYSPRN != NULL);
  7455. assert(My->SYSPRN->cfp != NULL);
  7456. DumpAllCommandSwitchStatement (My->SYSPRN->cfp);
  7457. return (l);
  7458. }
  7459. LineType *
  7460. bwb_MAINTAINER_CMDS_TABLE (LineType * l)
  7461. {
  7462. assert (l != NULL);
  7463. assert(My != NULL);
  7464. assert(My->SYSPRN != NULL);
  7465. assert(My->SYSPRN->cfp != NULL);
  7466. DumpAllCommandTableDefinitions (My->SYSPRN->cfp);
  7467. return (l);
  7468. }
  7469. LineType *
  7470. bwb_MAINTAINER_DEBUG (LineType * l)
  7471. {
  7472. assert (l != NULL);
  7473. WARN_SYNTAX_ERROR;
  7474. return (l);
  7475. }
  7476. LineType *
  7477. bwb_MAINTAINER_DEBUG_ON (LineType * l)
  7478. {
  7479. assert (l != NULL);
  7480. return (l);
  7481. }
  7482. LineType *
  7483. bwb_MAINTAINER_DEBUG_OFF (LineType * l)
  7484. {
  7485. assert (l != NULL);
  7486. return (l);
  7487. }
  7488. LineType *
  7489. bwb_MAINTAINER_FNCS (LineType * l)
  7490. {
  7491. assert (l != NULL);
  7492. WARN_SYNTAX_ERROR;
  7493. return (l);
  7494. }
  7495. LineType *
  7496. bwb_MAINTAINER_FNCS_HTML (LineType * l)
  7497. {
  7498. assert (l != NULL);
  7499. assert(My != NULL);
  7500. assert(My->SYSPRN != NULL);
  7501. assert(My->SYSPRN->cfp != NULL);
  7502. DumpAllFunctionHtmlTable (My->SYSPRN->cfp);
  7503. return (l);
  7504. }
  7505. LineType *
  7506. bwb_MAINTAINER_FNCS_ID (LineType * l)
  7507. {
  7508. assert (l != NULL);
  7509. assert(My != NULL);
  7510. assert(My->SYSPRN != NULL);
  7511. assert(My->SYSPRN->cfp != NULL);
  7512. DumpAllFunctionUniqueID (My->SYSPRN->cfp);
  7513. return (l);
  7514. }
  7515. LineType *
  7516. bwb_MAINTAINER_FNCS_MANUAL (LineType * l)
  7517. {
  7518. assert (l != NULL);
  7519. assert(My != NULL);
  7520. assert(My->SYSPRN != NULL);
  7521. assert(My->SYSPRN->cfp != NULL);
  7522. DumpAllFunctionSyntax (My->SYSPRN->cfp, TRUE, (OptionVersionType)(-1));
  7523. DumpAllOperatorSyntax (My->SYSPRN->cfp, TRUE, (OptionVersionType)(-1));
  7524. return (l);
  7525. }
  7526. LineType *
  7527. bwb_MAINTAINER_FNCS_SWITCH (LineType * l)
  7528. {
  7529. assert (l != NULL);
  7530. assert(My != NULL);
  7531. assert(My->SYSPRN != NULL);
  7532. assert(My->SYSPRN->cfp != NULL);
  7533. DumpAllFunctionSwitch (My->SYSPRN->cfp);
  7534. return (l);
  7535. }
  7536. LineType *
  7537. bwb_MAINTAINER_FNCS_TABLE (LineType * l)
  7538. {
  7539. assert (l != NULL);
  7540. assert(My != NULL);
  7541. assert(My->SYSPRN != NULL);
  7542. assert(My->SYSPRN->cfp != NULL);
  7543. DumpAllFuctionTableDefinitions (My->SYSPRN->cfp);
  7544. return (l);
  7545. }
  7546. void
  7547. DumpHeader (FILE * file)
  7548. {
  7549. char c;
  7550. assert (file != NULL);
  7551. assert(My != NULL);
  7552. assert(My->CurrentVersion != NULL);
  7553. fprintf (file,
  7554. "============================================================\n");
  7555. fprintf (file,
  7556. " GENERAL \n");
  7557. fprintf (file,
  7558. "============================================================\n");
  7559. fprintf (file, "\n");
  7560. fprintf (file, "\n");
  7561. fprintf (file, "OPTION VERSION \"%s\"\n", My->CurrentVersion->Name);
  7562. fprintf (file, "REM INTERNAL ID: %s\n", My->CurrentVersion->ID);
  7563. fprintf (file, "REM DESCRIPTION: %s\n", My->CurrentVersion->Description);
  7564. fprintf (file, "REM REFERENCE: %s\n", My->CurrentVersion->ReferenceTitle);
  7565. fprintf (file, "REM %s\n",
  7566. My->CurrentVersion->ReferenceAuthor);
  7567. fprintf (file, "REM %s\n",
  7568. My->CurrentVersion->ReferenceCopyright);
  7569. fprintf (file, "REM %s\n", My->CurrentVersion->ReferenceURL1);
  7570. fprintf (file, "REM %s\n", My->CurrentVersion->ReferenceURL2);
  7571. fprintf (file, "REM\n");
  7572. if (My->CurrentVersion->OptionFlags & (OPTION_STRICT_ON))
  7573. {
  7574. fprintf (file, "OPTION STRICT ON\n");
  7575. }
  7576. else
  7577. {
  7578. fprintf (file, "OPTION STRICT OFF\n");
  7579. }
  7580. if (My->CurrentVersion->OptionFlags & (OPTION_ANGLE_DEGREES))
  7581. {
  7582. fprintf (file, "OPTION ANGLE DEGREES\n");
  7583. }
  7584. else if (My->CurrentVersion->OptionFlags & (OPTION_ANGLE_GRADIANS))
  7585. {
  7586. fprintf (file, "OPTION ANGLE GRADIANS\n");
  7587. }
  7588. else
  7589. {
  7590. fprintf (file, "OPTION ANGLE RADIANS\n");
  7591. }
  7592. if (My->CurrentVersion->OptionFlags & (OPTION_BUGS_ON))
  7593. {
  7594. fprintf (file, "OPTION BUGS ON\n");
  7595. }
  7596. else
  7597. {
  7598. fprintf (file, "OPTION BUGS OFF\n");
  7599. }
  7600. if (My->CurrentVersion->OptionFlags & (OPTION_LABELS_ON))
  7601. {
  7602. fprintf (file, "OPTION LABELS ON\n");
  7603. }
  7604. else
  7605. {
  7606. fprintf (file, "OPTION LABELS OFF\n");
  7607. }
  7608. if (My->CurrentVersion->OptionFlags & (OPTION_COMPARE_TEXT))
  7609. {
  7610. fprintf (file, "OPTION COMPARE TEXT\n");
  7611. }
  7612. else
  7613. {
  7614. fprintf (file, "OPTION COMPARE BINARY\n");
  7615. }
  7616. if (My->CurrentVersion->OptionFlags & (OPTION_COVERAGE_ON))
  7617. {
  7618. fprintf (file, "OPTION COVERAGE ON\n");
  7619. }
  7620. else
  7621. {
  7622. fprintf (file, "OPTION COVERAGE OFF\n");
  7623. }
  7624. if (My->CurrentVersion->OptionFlags & (OPTION_TRACE_ON))
  7625. {
  7626. fprintf (file, "OPTION TRACE ON\n");
  7627. }
  7628. else
  7629. {
  7630. fprintf (file, "OPTION TRACE OFF\n");
  7631. }
  7632. if (My->CurrentVersion->OptionFlags & (OPTION_ERROR_GOSUB))
  7633. {
  7634. fprintf (file, "OPTION ERROR GOSUB\n");
  7635. }
  7636. else
  7637. {
  7638. fprintf (file, "OPTION ERROR GOTO\n");
  7639. }
  7640. if (My->CurrentVersion->OptionFlags & (OPTION_EXPLICIT_ON))
  7641. {
  7642. fprintf (file, "OPTION EXPLICIT\n");
  7643. }
  7644. else
  7645. {
  7646. fprintf (file, "OPTION IMPLICIT\n");
  7647. }
  7648. fprintf (file, "OPTION BASE %d\n",
  7649. My->CurrentVersion->OptionBaseInteger);
  7650. fprintf (file, "OPTION RECLEN %d\n",
  7651. My->CurrentVersion->OptionReclenInteger);
  7652. fprintf (file, "OPTION DATE \"%s\"\n",
  7653. My->CurrentVersion->OptionDateFormat);
  7654. fprintf (file, "OPTION TIME \"%s\"\n",
  7655. My->CurrentVersion->OptionTimeFormat);
  7656. c = My->CurrentVersion->OptionStringChar;
  7657. if (!bwb_isgraph (c))
  7658. {
  7659. c = ' ';
  7660. };
  7661. fprintf (file, "OPTION PUNCT STRING \"%c\"\n", c);
  7662. c = My->CurrentVersion->OptionDoubleChar;
  7663. if (!bwb_isgraph (c))
  7664. {
  7665. c = ' ';
  7666. };
  7667. fprintf (file, "OPTION PUNCT DOUBLE \"%c\"\n", c);
  7668. c = My->CurrentVersion->OptionSingleChar;
  7669. if (!bwb_isgraph (c))
  7670. {
  7671. c = ' ';
  7672. };
  7673. fprintf (file, "OPTION PUNCT SINGLE \"%c\"\n", c);
  7674. c = My->CurrentVersion->OptionCurrencyChar;
  7675. if (!bwb_isgraph (c))
  7676. {
  7677. c = ' ';
  7678. };
  7679. fprintf (file, "OPTION PUNCT CURRENCY \"%c\"\n", c);
  7680. c = My->CurrentVersion->OptionLongChar;
  7681. if (!bwb_isgraph (c))
  7682. {
  7683. c = ' ';
  7684. };
  7685. fprintf (file, "OPTION PUNCT LONG \"%c\"\n", c);
  7686. c = My->CurrentVersion->OptionIntegerChar;
  7687. if (!bwb_isgraph (c))
  7688. {
  7689. c = ' ';
  7690. };
  7691. fprintf (file, "OPTION PUNCT INTEGER \"%c\"\n", c);
  7692. c = My->CurrentVersion->OptionByteChar;
  7693. if (!bwb_isgraph (c))
  7694. {
  7695. c = ' ';
  7696. };
  7697. fprintf (file, "OPTION PUNCT BYTE \"%c\"\n", c);
  7698. c = My->CurrentVersion->OptionQuoteChar;
  7699. if (!bwb_isgraph (c))
  7700. {
  7701. c = ' ';
  7702. };
  7703. fprintf (file, "OPTION PUNCT QUOTE \"%c\"\n", c);
  7704. c = My->CurrentVersion->OptionCommentChar;
  7705. if (!bwb_isgraph (c))
  7706. {
  7707. c = ' ';
  7708. };
  7709. fprintf (file, "OPTION PUNCT COMMENT \"%c\"\n", c);
  7710. c = My->CurrentVersion->OptionStatementChar;
  7711. if (!bwb_isgraph (c))
  7712. {
  7713. c = ' ';
  7714. };
  7715. fprintf (file, "OPTION PUNCT STATEMENT \"%c\"\n", c);
  7716. c = My->CurrentVersion->OptionPrintChar;
  7717. if (!bwb_isgraph (c))
  7718. {
  7719. c = ' ';
  7720. };
  7721. fprintf (file, "OPTION PUNCT PRINT \"%c\"\n", c);
  7722. c = My->CurrentVersion->OptionInputChar;
  7723. if (!bwb_isgraph (c))
  7724. {
  7725. c = ' ';
  7726. };
  7727. fprintf (file, "OPTION PUNCT INPUT \"%c\"\n", c);
  7728. c = My->CurrentVersion->OptionImageChar;
  7729. if (!bwb_isgraph (c))
  7730. {
  7731. c = ' ';
  7732. };
  7733. fprintf (file, "OPTION PUNCT IMAGE \"%c\"\n", c);
  7734. c = My->CurrentVersion->OptionLparenChar;
  7735. if (!bwb_isgraph (c))
  7736. {
  7737. c = ' ';
  7738. };
  7739. fprintf (file, "OPTION PUNCT LPAREN \"%c\"\n", c);
  7740. c = My->CurrentVersion->OptionRparenChar;
  7741. if (!bwb_isgraph (c))
  7742. {
  7743. c = ' ';
  7744. };
  7745. fprintf (file, "OPTION PUNCT RPAREN \"%c\"\n", c);
  7746. c = My->CurrentVersion->OptionFilenumChar;
  7747. if (!bwb_isgraph (c))
  7748. {
  7749. c = ' ';
  7750. };
  7751. fprintf (file, "OPTION PUNCT FILENUM \"%c\"\n", c);
  7752. c = My->CurrentVersion->OptionAtChar;
  7753. if (!bwb_isgraph (c))
  7754. {
  7755. c = ' ';
  7756. };
  7757. fprintf (file, "OPTION PUNCT AT \"%c\"\n", c);
  7758. c = My->CurrentVersion->OptionUsingDigit;
  7759. if (!bwb_isgraph (c))
  7760. {
  7761. c = ' ';
  7762. };
  7763. fprintf (file, "OPTION USING DIGIT \"%c\"\n", c);
  7764. c = My->CurrentVersion->OptionUsingComma;
  7765. if (!bwb_isgraph (c))
  7766. {
  7767. c = ' ';
  7768. };
  7769. fprintf (file, "OPTION USING COMMA \"%c\"\n", c);
  7770. c = My->CurrentVersion->OptionUsingPeriod;
  7771. if (!bwb_isgraph (c))
  7772. {
  7773. c = ' ';
  7774. };
  7775. fprintf (file, "OPTION USING PERIOD \"%c\"\n", c);
  7776. c = My->CurrentVersion->OptionUsingPlus;
  7777. if (!bwb_isgraph (c))
  7778. {
  7779. c = ' ';
  7780. };
  7781. fprintf (file, "OPTION USING PLUS \"%c\"\n", c);
  7782. c = My->CurrentVersion->OptionUsingMinus;
  7783. if (!bwb_isgraph (c))
  7784. {
  7785. c = ' ';
  7786. };
  7787. fprintf (file, "OPTION USING MINUS \"%c\"\n", c);
  7788. c = My->CurrentVersion->OptionUsingExrad;
  7789. if (!bwb_isgraph (c))
  7790. {
  7791. c = ' ';
  7792. };
  7793. fprintf (file, "OPTION USING EXRAD \"%c\"\n", c);
  7794. c = My->CurrentVersion->OptionUsingDollar;
  7795. if (!bwb_isgraph (c))
  7796. {
  7797. c = ' ';
  7798. };
  7799. fprintf (file, "OPTION USING DOLLAR \"%c\"\n", c);
  7800. c = My->CurrentVersion->OptionUsingFiller;
  7801. if (!bwb_isgraph (c))
  7802. {
  7803. c = ' ';
  7804. };
  7805. fprintf (file, "OPTION USING FILLER \"%c\"\n", c);
  7806. c = My->CurrentVersion->OptionUsingLiteral;
  7807. if (!bwb_isgraph (c))
  7808. {
  7809. c = ' ';
  7810. };
  7811. fprintf (file, "OPTION USING LITERAL \"%c\"\n", c);
  7812. c = My->CurrentVersion->OptionUsingFirst;
  7813. if (!bwb_isgraph (c))
  7814. {
  7815. c = ' ';
  7816. };
  7817. fprintf (file, "OPTION USING FIRST \"%c\"\n", c);
  7818. c = My->CurrentVersion->OptionUsingAll;
  7819. if (!bwb_isgraph (c))
  7820. {
  7821. c = ' ';
  7822. };
  7823. fprintf (file, "OPTION USING ALL \"%c\"\n", c);
  7824. c = My->CurrentVersion->OptionUsingLength;
  7825. if (!bwb_isgraph (c))
  7826. {
  7827. c = ' ';
  7828. };
  7829. fprintf (file, "OPTION USING LENGTH \"%c\"\n", c);
  7830. fprintf (file, "\n");
  7831. fprintf (file, "\n");
  7832. fflush (file);
  7833. }
  7834. LineType *
  7835. bwb_MAINTAINER_MANUAL (LineType * l)
  7836. {
  7837. assert (l != NULL);
  7838. DumpHeader (My->SYSPRN->cfp);
  7839. DumpAllCommandSyntax (My->SYSPRN->cfp, FALSE,
  7840. My->CurrentVersion->OptionVersionValue);
  7841. DumpAllFunctionSyntax (My->SYSPRN->cfp, FALSE,
  7842. My->CurrentVersion->OptionVersionValue);
  7843. DumpAllOperatorSyntax (My->SYSPRN->cfp, FALSE,
  7844. My->CurrentVersion->OptionVersionValue);
  7845. return (l);
  7846. }
  7847. LineType *
  7848. bwb_MAINTAINER_STACK (LineType * l)
  7849. {
  7850. /*
  7851. dump the current execution stack,
  7852. Leftmost is the top,
  7853. Rigthmost is the bottom.
  7854. */
  7855. StackType *StackItem;
  7856. assert (l != NULL);
  7857. for (StackItem = My->StackHead; StackItem != NULL;
  7858. StackItem = StackItem->next)
  7859. {
  7860. LineType *l;
  7861. l = StackItem->line;
  7862. if (l != NULL)
  7863. {
  7864. fprintf (My->SYSOUT->cfp, "%d:", l->number);
  7865. }
  7866. }
  7867. fprintf (My->SYSOUT->cfp, "\n");
  7868. ResetConsoleColumn ();
  7869. return (l);
  7870. }
  7871. /***************************************************************
  7872. FUNCTION: IntrinsicFunction_init()
  7873. DESCRIPTION: This command initializes the function
  7874. linked list, placing all predefined functions
  7875. in the list.
  7876. ***************************************************************/
  7877. int
  7878. IntrinsicFunction_init (void)
  7879. {
  7880. int n;
  7881. for (n = 0; n < NUM_FUNCTIONS; n++)
  7882. {
  7883. IntrinsicFunctionDefinitionCheck (&(IntrinsicFunctionTable[n]));
  7884. }
  7885. return TRUE;
  7886. }
  7887. VariableType *
  7888. IntrinsicFunction_deffn (int argc, VariableType * argv, UserFunctionType * f)
  7889. {
  7890. /*
  7891. The generic handler for user defined functions.
  7892. When called by exp_function(), f->id will be set to the line number of a specific DEF USR.
  7893. */
  7894. VariableType *v;
  7895. VariableType *argn;
  7896. int i;
  7897. LineType *call_line;
  7898. StackType *save_elevel;
  7899. assert (argc >= 0);
  7900. assert (argv != NULL);
  7901. assert (f != NULL);
  7902. assert(My != NULL);
  7903. /* initialize the variable if necessary */
  7904. /* these errors should not occur */
  7905. if (f == NULL)
  7906. {
  7907. WARN_INTERNAL_ERROR;
  7908. return NULL;
  7909. }
  7910. if (f->line == NULL)
  7911. {
  7912. WARN_INTERNAL_ERROR;
  7913. return NULL;
  7914. }
  7915. if (argv == NULL)
  7916. {
  7917. WARN_INTERNAL_ERROR;
  7918. return NULL;
  7919. }
  7920. if (f->ParameterCount == 0xFF)
  7921. {
  7922. /* VARIANT */
  7923. }
  7924. else if (argc != f->ParameterCount)
  7925. {
  7926. WARN_INTERNAL_ERROR;
  7927. return NULL;
  7928. }
  7929. if (f->ParameterCount == 0xFF)
  7930. {
  7931. /* VARIANT */
  7932. f->local_variable = argv;
  7933. }
  7934. else if (argc > 0)
  7935. {
  7936. v = f->local_variable;
  7937. argn = argv;
  7938. for (i = 0; i < argc; i++)
  7939. {
  7940. argn = argn->next;
  7941. if (v == NULL)
  7942. {
  7943. WARN_INTERNAL_ERROR;
  7944. return NULL;
  7945. }
  7946. if (argn == NULL)
  7947. {
  7948. WARN_INTERNAL_ERROR;
  7949. return NULL;
  7950. }
  7951. if (VAR_IS_STRING (v) != VAR_IS_STRING (argn))
  7952. {
  7953. WARN_INTERNAL_ERROR;
  7954. return NULL;
  7955. }
  7956. if (is_empty_string (v->name) == FALSE)
  7957. {
  7958. int IsError;
  7959. IsError = 0;
  7960. switch (v->VariableTypeCode)
  7961. {
  7962. case ByteTypeCode:
  7963. IsError = NumberValueCheck (P1BYT, PARAM_NUMBER);
  7964. break;
  7965. case IntegerTypeCode:
  7966. IsError = NumberValueCheck (P1INT, PARAM_NUMBER);
  7967. break;
  7968. case LongTypeCode:
  7969. IsError = NumberValueCheck (P1LNG, PARAM_NUMBER);
  7970. break;
  7971. case CurrencyTypeCode:
  7972. IsError = NumberValueCheck (P1CUR, PARAM_NUMBER);
  7973. break;
  7974. case SingleTypeCode:
  7975. IsError = NumberValueCheck (P1FLT, PARAM_NUMBER);
  7976. break;
  7977. case DoubleTypeCode:
  7978. IsError = NumberValueCheck (P1DBL, PARAM_NUMBER);
  7979. break;
  7980. case StringTypeCode:
  7981. IsError = StringLengthCheck (P1ANY, PARAM_LENGTH);
  7982. break;
  7983. default:
  7984. WARN_TYPE_MISMATCH;
  7985. return NULL;
  7986. }
  7987. if (IsError != 0)
  7988. {
  7989. WARN_ILLEGAL_FUNCTION_CALL;
  7990. return argv;
  7991. }
  7992. }
  7993. v = v->next;
  7994. }
  7995. }
  7996. /* OK */
  7997. call_line = f->line; /* line to call for function */
  7998. call_line->position = f->startpos;
  7999. if (call_line->cmdnum == C_DEF)
  8000. {
  8001. if (line_skip_EqualChar (call_line) == FALSE)
  8002. {
  8003. WARN_INTERNAL_ERROR;
  8004. return NULL;
  8005. }
  8006. }
  8007. /* PUSH STACK */
  8008. save_elevel = My->StackHead;
  8009. if (bwb_incexec ())
  8010. {
  8011. /* OK */
  8012. My->StackHead->line = call_line;
  8013. My->StackHead->ExecCode = EXEC_FUNCTION;
  8014. }
  8015. else
  8016. {
  8017. /* ERROR */
  8018. WARN_OUT_OF_MEMORY;
  8019. return NULL;
  8020. }
  8021. /* create variable chain */
  8022. if (f->ParameterCount == 0xFF)
  8023. {
  8024. /* VARIANT */
  8025. }
  8026. else if (argc > 0)
  8027. {
  8028. VariableType *source = NULL; /* source variable */
  8029. source = f->local_variable;
  8030. argn = argv;
  8031. for (i = 0; i < argc; i++)
  8032. {
  8033. argn = argn->next;
  8034. /* copy the name */
  8035. bwb_strcpy (argn->name, source->name);
  8036. if (VAR_IS_STRING (source))
  8037. {
  8038. }
  8039. else
  8040. {
  8041. int IsError;
  8042. double Value;
  8043. VariantType variant;
  8044. CLEAR_VARIANT (&variant);
  8045. if (var_get (argn, &variant) == FALSE)
  8046. {
  8047. WARN_VARIABLE_NOT_DECLARED;
  8048. return NULL;
  8049. }
  8050. if (variant.VariantTypeCode == StringTypeCode)
  8051. {
  8052. WARN_TYPE_MISMATCH;
  8053. return NULL;
  8054. }
  8055. Value = variant.Number;
  8056. IsError = 0;
  8057. switch (source->VariableTypeCode)
  8058. {
  8059. case ByteTypeCode:
  8060. IsError = NumberValueCheck (P1BYT, Value);
  8061. Value = bwb_rint (Value);
  8062. break;
  8063. case IntegerTypeCode:
  8064. IsError = NumberValueCheck (P1INT, Value);
  8065. Value = bwb_rint (Value);
  8066. break;
  8067. case LongTypeCode:
  8068. IsError = NumberValueCheck (P1LNG, Value);
  8069. Value = bwb_rint (Value);
  8070. break;
  8071. case CurrencyTypeCode:
  8072. IsError = NumberValueCheck (P1CUR, Value);
  8073. Value = bwb_rint (Value);
  8074. break;
  8075. case SingleTypeCode:
  8076. IsError = NumberValueCheck (P1FLT, Value);
  8077. break;
  8078. case DoubleTypeCode:
  8079. IsError = NumberValueCheck (P1DBL, Value);
  8080. break;
  8081. case StringTypeCode:
  8082. WARN_TYPE_MISMATCH;
  8083. return NULL;
  8084. /* break; */
  8085. default:
  8086. WARN_TYPE_MISMATCH;
  8087. return NULL;
  8088. }
  8089. if (IsError != 0)
  8090. {
  8091. WARN_ILLEGAL_FUNCTION_CALL;
  8092. return argv;
  8093. }
  8094. variant.Number = Value;
  8095. if (var_set (argn, &variant) == FALSE)
  8096. {
  8097. WARN_VARIABLE_NOT_DECLARED;
  8098. return NULL;
  8099. }
  8100. }
  8101. source = source->next;
  8102. }
  8103. }
  8104. if (call_line->cmdnum == C_DEF)
  8105. {
  8106. VariantType x;
  8107. VariantType *X;
  8108. X = &x;
  8109. CLEAR_VARIANT (X);
  8110. /* the function return variable is hidden */
  8111. My->StackHead->local_variable = argv->next;
  8112. /* var_islocal() uses the LoopTopLine to find local variables */
  8113. My->StackHead->LoopTopLine = call_line; /* FUNCTION, SUB */
  8114. /* evaluate the expression */
  8115. if (line_read_expression (call_line, X) == FALSE) /* IntrinsicFunction_deffn */
  8116. {
  8117. WARN_SYNTAX_ERROR;
  8118. goto EXIT;
  8119. }
  8120. /* save the value */
  8121. switch (X->VariantTypeCode)
  8122. {
  8123. case ByteTypeCode:
  8124. case IntegerTypeCode:
  8125. case LongTypeCode:
  8126. case CurrencyTypeCode:
  8127. case SingleTypeCode:
  8128. case DoubleTypeCode:
  8129. if (argv->VariableTypeCode == StringTypeCode)
  8130. {
  8131. WARN_TYPE_MISMATCH;
  8132. goto EXIT;
  8133. }
  8134. /* OK */
  8135. {
  8136. int IsError;
  8137. double Value;
  8138. IsError = 0;
  8139. Value = X->Number;
  8140. /* VerifyNumeric */
  8141. if (isnan (Value))
  8142. {
  8143. /*** FATAL - INTERNAL ERROR - SHOULD NEVER HAPPEN ***/
  8144. WARN_INTERNAL_ERROR;
  8145. return FALSE;
  8146. }
  8147. if (isinf (Value))
  8148. {
  8149. /* - Evaluation of an expression results in an overflow
  8150. * (nonfatal, the recommended recovery procedure is to supply
  8151. * machine in- finity with the algebraically correct sign and
  8152. * continue). */
  8153. if (Value < 0)
  8154. {
  8155. Value = MINDBL;
  8156. }
  8157. else
  8158. {
  8159. Value = MAXDBL;
  8160. }
  8161. if (WARN_OVERFLOW)
  8162. {
  8163. /* ERROR */
  8164. goto EXIT;
  8165. }
  8166. /* CONTINUE */
  8167. }
  8168. /* OK */
  8169. switch (argv->VariableTypeCode)
  8170. {
  8171. case ByteTypeCode:
  8172. IsError = NumberValueCheck (P1BYT, Value);
  8173. Value = bwb_rint (Value);
  8174. break;
  8175. case IntegerTypeCode:
  8176. IsError = NumberValueCheck (P1INT, Value);
  8177. Value = bwb_rint (Value);
  8178. break;
  8179. case LongTypeCode:
  8180. IsError = NumberValueCheck (P1LNG, Value);
  8181. Value = bwb_rint (Value);
  8182. break;
  8183. case CurrencyTypeCode:
  8184. IsError = NumberValueCheck (P1CUR, Value);
  8185. Value = bwb_rint (Value);
  8186. break;
  8187. case SingleTypeCode:
  8188. IsError = NumberValueCheck (P1FLT, Value);
  8189. break;
  8190. case DoubleTypeCode:
  8191. IsError = NumberValueCheck (P1DBL, Value);
  8192. break;
  8193. default:
  8194. WARN_TYPE_MISMATCH;
  8195. goto EXIT;
  8196. /* break; */
  8197. }
  8198. if (IsError != 0)
  8199. {
  8200. if (WARN_OVERFLOW)
  8201. {
  8202. /* ERROR */
  8203. goto EXIT;
  8204. }
  8205. /* CONTINUE */
  8206. }
  8207. /* assign Value */
  8208. RESULT_NUMBER = Value;
  8209. }
  8210. break;
  8211. case StringTypeCode:
  8212. if (argv->VariableTypeCode != StringTypeCode)
  8213. {
  8214. WARN_TYPE_MISMATCH;
  8215. goto EXIT;
  8216. }
  8217. /* OK */
  8218. if (RESULT_BUFFER != My->MaxLenBuffer)
  8219. {
  8220. WARN_INTERNAL_ERROR;
  8221. goto EXIT;
  8222. }
  8223. if (X->Length > MAXLEN)
  8224. {
  8225. WARN_STRING_TOO_LONG; /* IntrinsicFunction_deffn */
  8226. X->Length = MAXLEN;
  8227. }
  8228. bwb_memcpy (RESULT_BUFFER, X->Buffer, X->Length);
  8229. RESULT_LENGTH = X->Length;
  8230. break;
  8231. default:
  8232. WARN_TYPE_MISMATCH;
  8233. goto EXIT;
  8234. /* break; */
  8235. }
  8236. EXIT:
  8237. RELEASE_VARIANT (X);
  8238. /* break variable chain */
  8239. My->StackHead->local_variable = NULL;
  8240. /* POP STACK */
  8241. bwb_decexec ();
  8242. }
  8243. else
  8244. {
  8245. /* the function return variable is visible */
  8246. My->StackHead->local_variable = argv;
  8247. /* var_islocal() uses the LoopTopLine to find local variables */
  8248. My->StackHead->LoopTopLine = call_line; /* FUNCTION, SUB */
  8249. /* execute until function returns */
  8250. while (My->StackHead != save_elevel)
  8251. {
  8252. bwb_execline ();
  8253. }
  8254. }
  8255. if (f->ParameterCount == 0xFF)
  8256. {
  8257. /* VARIANT */
  8258. f->local_variable = NULL;
  8259. }
  8260. if (is_empty_string (argv->name) == FALSE)
  8261. {
  8262. int IsError;
  8263. IsError = 0;
  8264. switch (argv->VariableTypeCode)
  8265. {
  8266. case ByteTypeCode:
  8267. IsError = NumberValueCheck (P1BYT, RESULT_NUMBER);
  8268. break;
  8269. case IntegerTypeCode:
  8270. IsError = NumberValueCheck (P1INT, RESULT_NUMBER);
  8271. break;
  8272. case LongTypeCode:
  8273. IsError = NumberValueCheck (P1LNG, RESULT_NUMBER);
  8274. break;
  8275. case CurrencyTypeCode:
  8276. IsError = NumberValueCheck (P1CUR, RESULT_NUMBER);
  8277. break;
  8278. case SingleTypeCode:
  8279. IsError = NumberValueCheck (P1FLT, RESULT_NUMBER);
  8280. break;
  8281. case DoubleTypeCode:
  8282. IsError = NumberValueCheck (P1DBL, RESULT_NUMBER);
  8283. break;
  8284. case StringTypeCode:
  8285. IsError = StringLengthCheck (P1ANY, RESULT_LENGTH);
  8286. break;
  8287. default:
  8288. /* no check */
  8289. break;
  8290. }
  8291. if (IsError != 0)
  8292. {
  8293. if (WARN_OVERFLOW)
  8294. {
  8295. /* ERROR */
  8296. }
  8297. /* CONTINUE */
  8298. }
  8299. }
  8300. return argv;
  8301. }
  8302. /***************************************************************
  8303. FUNCTION: IntrinsicFunction_find()
  8304. DESCRIPTION: This C function attempts to locate
  8305. a BASIC function with the specified name.
  8306. If successful, it returns a pointer to
  8307. the C structure for the BASIC function,
  8308. if not successful, it returns NULL.
  8309. ***************************************************************/
  8310. extern int
  8311. IntrinsicFunction_name (char *name)
  8312. {
  8313. /* search INTRINSIC functions */
  8314. IntrinsicFunctionType *f;
  8315. int i;
  8316. assert (name != NULL);
  8317. assert(My != NULL);
  8318. assert(My->CurrentVersion != NULL);
  8319. #if THE_PRICE_IS_RIGHT
  8320. /* start with the closest function, without going over */
  8321. i = VarTypeIndex (name[0]);
  8322. if (i < 0)
  8323. {
  8324. /* non-alpha */
  8325. return FALSE;
  8326. }
  8327. i = My->IntrinsicFunctionStart[i]; /* first function starting with this letter */
  8328. if (i < 0)
  8329. {
  8330. /* NOT FOUND */
  8331. return FALSE;
  8332. }
  8333. #else /* THE_PRICE_IS_RIGHT */
  8334. i = 0;
  8335. #endif /* THE_PRICE_IS_RIGHT */
  8336. for (; i < NUM_FUNCTIONS; i++)
  8337. {
  8338. f = &IntrinsicFunctionTable[i];
  8339. if (My->CurrentVersion->OptionVersionValue & f->OptionVersionBitmask)
  8340. {
  8341. int result;
  8342. result = bwb_stricmp (f->Name, name);
  8343. if (result == 0)
  8344. {
  8345. /* FOUND */
  8346. return TRUE;
  8347. }
  8348. if (result > 0 /* found > searched */ )
  8349. {
  8350. /* NOT FOUND */
  8351. return FALSE;
  8352. }
  8353. }
  8354. }
  8355. /* NOT FOUND */
  8356. return FALSE;
  8357. }
  8358. IntrinsicFunctionType *
  8359. IntrinsicFunction_find_exact (char *name, int ParameterCount,
  8360. ParamBitsType ParameterTypes)
  8361. {
  8362. IntrinsicFunctionType *f;
  8363. int i;
  8364. assert (name != NULL);
  8365. assert(My != NULL);
  8366. assert(My->CurrentVersion != NULL);
  8367. /* search INTRINSIC functions */
  8368. #if THE_PRICE_IS_RIGHT
  8369. /* start with the closest function, without going over */
  8370. i = VarTypeIndex (name[0]);
  8371. if (i < 0)
  8372. {
  8373. /* non-alpha */
  8374. return NULL;
  8375. }
  8376. i = My->IntrinsicFunctionStart[i]; /* first function starting with this letter */
  8377. if (i < 0)
  8378. {
  8379. /* NOT FOUND */
  8380. return NULL;
  8381. }
  8382. #else /* THE_PRICE_IS_RIGHT */
  8383. i = 0;
  8384. #endif /* THE_PRICE_IS_RIGHT */
  8385. for (; i < NUM_FUNCTIONS; i++)
  8386. {
  8387. f = &IntrinsicFunctionTable[i];
  8388. if (My->CurrentVersion->OptionVersionValue & f->OptionVersionBitmask)
  8389. {
  8390. if (f->ParameterCount == ParameterCount)
  8391. {
  8392. if (f->ParameterTypes == ParameterTypes)
  8393. {
  8394. int result;
  8395. result = bwb_stricmp (f->Name, name);
  8396. if (result == 0)
  8397. {
  8398. /* FOUND */
  8399. return f;
  8400. }
  8401. if (result > 0 /* found > searched */ )
  8402. {
  8403. /* NOT FOUND */
  8404. return NULL;
  8405. }
  8406. }
  8407. }
  8408. }
  8409. }
  8410. /* NOT FOUND */
  8411. return NULL;
  8412. }
  8413. static VariableType *
  8414. find_variable_by_type (char *name, int dimensions, char VariableTypeCode)
  8415. {
  8416. VariableType *v = NULL;
  8417. assert (name != NULL);
  8418. v = var_find (name, dimensions, FALSE);
  8419. if (v)
  8420. {
  8421. if (VAR_IS_STRING (v))
  8422. {
  8423. if (VariableTypeCode == StringTypeCode)
  8424. {
  8425. /* found */
  8426. return v;
  8427. }
  8428. }
  8429. else
  8430. {
  8431. if (VariableTypeCode != StringTypeCode)
  8432. {
  8433. /* found */
  8434. return v;
  8435. }
  8436. }
  8437. }
  8438. /* not found */
  8439. return NULL;
  8440. }
  8441. /*
  8442. --------------------------------------------------------------------------------------------
  8443. CHANGE
  8444. --------------------------------------------------------------------------------------------
  8445. */
  8446. LineType *
  8447. bwb_CHANGE (LineType * l)
  8448. {
  8449. /* SYNTAX: CHANGE A$ TO X */
  8450. /* SYNTAX: CHANGE X TO A$ */
  8451. char varname[NameLengthMax + 1];
  8452. VariableType *v;
  8453. VariableType *A;
  8454. VariableType *X;
  8455. int IsStringToArray;
  8456. assert (l != NULL);
  8457. v = NULL;
  8458. A = NULL;
  8459. X = NULL;
  8460. IsStringToArray = FALSE;
  8461. /* get 1st variable */
  8462. if (line_read_varname (l, varname) == FALSE)
  8463. {
  8464. WARN_SYNTAX_ERROR;
  8465. return (l);
  8466. }
  8467. v = find_variable_by_type (varname, 0, StringTypeCode);
  8468. if (v)
  8469. {
  8470. /* STRING to ARRAY */
  8471. A = v;
  8472. IsStringToArray = TRUE;
  8473. }
  8474. else
  8475. {
  8476. /* ARRAY to STRING */
  8477. v = find_variable_by_type (varname, 1, DoubleTypeCode);
  8478. if (v)
  8479. {
  8480. X = v;
  8481. IsStringToArray = FALSE;
  8482. }
  8483. }
  8484. if (v == NULL)
  8485. {
  8486. WARN_VARIABLE_NOT_DECLARED;
  8487. return (l);
  8488. }
  8489. /* get "TO" */
  8490. if (line_skip_word (l, "TO") == FALSE)
  8491. {
  8492. WARN_SYNTAX_ERROR;
  8493. return (l);
  8494. }
  8495. /* get 2nd variable */
  8496. if (line_read_varname (l, varname) == FALSE)
  8497. {
  8498. WARN_SYNTAX_ERROR;
  8499. return (l);
  8500. }
  8501. if (IsStringToArray)
  8502. {
  8503. /* STRING to ARRAY */
  8504. v = find_variable_by_type (varname, 1, DoubleTypeCode);
  8505. if (v == NULL)
  8506. {
  8507. v = var_find (varname, 1, TRUE);
  8508. }
  8509. if (v)
  8510. {
  8511. X = v;
  8512. }
  8513. }
  8514. else
  8515. {
  8516. /* ARRAY to STRING */
  8517. v = find_variable_by_type (varname, 0, StringTypeCode);
  8518. if (v == NULL)
  8519. {
  8520. v = var_find (varname, 0, TRUE);
  8521. }
  8522. if (v)
  8523. {
  8524. A = v;
  8525. }
  8526. }
  8527. if (v == NULL)
  8528. {
  8529. WARN_VARIABLE_NOT_DECLARED;
  8530. return (l);
  8531. }
  8532. assert(A != NULL);
  8533. assert(X != NULL);
  8534. if (IsStringToArray)
  8535. {
  8536. /* CHANGE A$ TO X */
  8537. int i;
  8538. int n;
  8539. char *a;
  8540. DoubleType *x;
  8541. unsigned long t;
  8542. if (A->Value.String == NULL)
  8543. {
  8544. WARN_INTERNAL_ERROR;
  8545. return (l);
  8546. }
  8547. if (A->Value.String->sbuffer == NULL)
  8548. {
  8549. WARN_INTERNAL_ERROR;
  8550. return (l);
  8551. }
  8552. /* variable storage is a mess, we bypass that tradition here. */
  8553. t = 1;
  8554. for (n = 0; n < X->dimensions; n++)
  8555. {
  8556. t *= X->UBOUND[n] - X->LBOUND[n] + 1;
  8557. }
  8558. if (t <= A->Value.String->length)
  8559. {
  8560. WARN_SUBSCRIPT_OUT_OF_RANGE;
  8561. return (l);
  8562. }
  8563. n = A->Value.String->length;
  8564. a = A->Value.String->sbuffer;
  8565. x = X->Value.Number;
  8566. *x = n;
  8567. x++;
  8568. for (i = 0; i < n; i++)
  8569. {
  8570. char C;
  8571. DoubleType V;
  8572. C = *a;
  8573. V = C;
  8574. *x = V;
  8575. x++;
  8576. a++;
  8577. }
  8578. }
  8579. else
  8580. {
  8581. /* CHANGE X TO A$ */
  8582. int i;
  8583. int n;
  8584. char *a;
  8585. DoubleType *x;
  8586. unsigned long t;
  8587. /* variable storage is a mess, we bypass that tradition here. */
  8588. t = 1;
  8589. for (n = 0; n < X->dimensions; n++)
  8590. {
  8591. t *= X->UBOUND[n] - X->LBOUND[n] + 1;
  8592. }
  8593. if (t <= 1)
  8594. {
  8595. WARN_SUBSCRIPT_OUT_OF_RANGE;
  8596. return (l);
  8597. }
  8598. if (t > MAXLEN)
  8599. {
  8600. WARN_STRING_TOO_LONG; /* bwb_CHANGE */
  8601. t = MAXLEN;
  8602. }
  8603. if (A->Value.String == NULL)
  8604. {
  8605. if ((A->Value.String =
  8606. (StringType *) calloc (1, sizeof (StringType))) == NULL)
  8607. {
  8608. WARN_OUT_OF_MEMORY;
  8609. return (l);
  8610. }
  8611. A->Value.String->sbuffer = NULL;
  8612. A->Value.String->length = 0;
  8613. }
  8614. if (A->Value.String->sbuffer != NULL)
  8615. {
  8616. free (A->Value.String->sbuffer);
  8617. A->Value.String->sbuffer = NULL;
  8618. A->Value.String->length = 0;
  8619. }
  8620. if (A->Value.String->sbuffer == NULL)
  8621. {
  8622. A->Value.String->length = 0;
  8623. if ((A->Value.String->sbuffer =
  8624. (char *) calloc (t + 1 /* NulChar */ , sizeof (char))) == NULL)
  8625. {
  8626. WARN_OUT_OF_MEMORY;
  8627. return (l);
  8628. }
  8629. }
  8630. a = A->Value.String->sbuffer;
  8631. x = X->Value.Number;
  8632. n = (int) bwb_rint (*x);
  8633. if (n > MAXLEN)
  8634. {
  8635. WARN_STRING_TOO_LONG; /* bwb_CHANGE */
  8636. n = MAXLEN;
  8637. }
  8638. A->Value.String->length = n;
  8639. x++;
  8640. for (i = 0; i < n; i++)
  8641. {
  8642. char C;
  8643. DoubleType V;
  8644. V = *x;
  8645. C = V;
  8646. *a = C;
  8647. x++;
  8648. a++;
  8649. }
  8650. }
  8651. return (l);
  8652. }
  8653. /*
  8654. --------------------------------------------------------------------------------------------
  8655. CONSOLE
  8656. --------------------------------------------------------------------------------------------
  8657. */
  8658. LineType *
  8659. bwb_CONSOLE (LineType * l)
  8660. {
  8661. /* SYNTAX: CONSOLE */
  8662. /* SYNTAX: CONSOLE WIDTH width */
  8663. assert (l != NULL);
  8664. assert(My != NULL);
  8665. assert(My->SYSPRN != NULL);
  8666. assert(My->SYSPRN->cfp != NULL);
  8667. assert(My->SYSOUT != NULL);
  8668. assert(My->SYSOUT->cfp != NULL);
  8669. if (My->IsPrinter == TRUE)
  8670. {
  8671. /* reset printer column */
  8672. if (My->SYSPRN->col != 1)
  8673. {
  8674. fputc ('\n', My->SYSPRN->cfp);
  8675. My->SYSPRN->col = 1;
  8676. }
  8677. My->IsPrinter = FALSE;
  8678. }
  8679. if (line_skip_word (l, "WIDTH"))
  8680. {
  8681. int width;
  8682. width = 0;
  8683. if (line_read_integer_expression (l, &width) == FALSE)
  8684. {
  8685. WARN_ILLEGAL_FUNCTION_CALL;
  8686. return (l);
  8687. }
  8688. if (width < 0)
  8689. {
  8690. WARN_ILLEGAL_FUNCTION_CALL;
  8691. return (l);
  8692. }
  8693. My->SYSOUT->width = width;
  8694. }
  8695. return (l);
  8696. }
  8697. /*
  8698. --------------------------------------------------------------------------------------------
  8699. LPRINTER
  8700. --------------------------------------------------------------------------------------------
  8701. */
  8702. LineType *
  8703. bwb_LPRINTER (LineType * l)
  8704. {
  8705. /* SYNTAX: LPRINTER */
  8706. /* SYNTAX: LPRINTER WIDTH width */
  8707. assert (l != NULL);
  8708. assert(My != NULL);
  8709. assert(My->SYSPRN != NULL);
  8710. assert(My->SYSPRN->cfp != NULL);
  8711. assert(My->SYSOUT != NULL);
  8712. assert(My->SYSOUT->cfp != NULL);
  8713. if (My->IsPrinter == FALSE)
  8714. {
  8715. /* reset console column */
  8716. if (My->SYSOUT->col != 1)
  8717. {
  8718. fputc ('\n', My->SYSOUT->cfp);
  8719. My->SYSOUT->col = 1;
  8720. }
  8721. My->IsPrinter = TRUE;
  8722. }
  8723. if (line_skip_word (l, "WIDTH"))
  8724. {
  8725. int width;
  8726. width = 0;
  8727. if (line_read_integer_expression (l, &width) == FALSE)
  8728. {
  8729. WARN_ILLEGAL_FUNCTION_CALL;
  8730. return (l);
  8731. }
  8732. if (width < 0)
  8733. {
  8734. WARN_ILLEGAL_FUNCTION_CALL;
  8735. return (l);
  8736. }
  8737. My->SYSPRN->width = width;
  8738. }
  8739. return (l);
  8740. }
  8741. extern void
  8742. bwb_fclose (FILE * file)
  8743. {
  8744. if (file == NULL)
  8745. {
  8746. /* don't close */
  8747. }
  8748. else if (file == stdin)
  8749. {
  8750. /* don't close */
  8751. }
  8752. else if (file == stdout)
  8753. {
  8754. /* don't close */
  8755. }
  8756. else if (file == stderr)
  8757. {
  8758. /* don't close */
  8759. }
  8760. else
  8761. {
  8762. fclose (file);
  8763. }
  8764. }
  8765. LineType *
  8766. bwb_LPT (LineType * l)
  8767. {
  8768. /* SYNTAX: LPT */
  8769. /* SYNTAX: LPT filename$ */
  8770. FILE *file;
  8771. char *filename;
  8772. assert (l != NULL);
  8773. assert(My != NULL);
  8774. assert(My->SYSOUT != NULL);
  8775. assert(My->SYSOUT->cfp != NULL);
  8776. file = NULL;
  8777. filename = NULL;
  8778. if (line_is_eol (l))
  8779. {
  8780. /* OK */
  8781. file = stderr;
  8782. }
  8783. else if (line_read_string_expression (l, &filename))
  8784. {
  8785. /* OK */
  8786. if (is_empty_string (filename))
  8787. {
  8788. WARN_BAD_FILE_NAME;
  8789. return (l);
  8790. }
  8791. file = fopen (filename, "w");
  8792. free (filename);
  8793. }
  8794. else
  8795. {
  8796. WARN_SYNTAX_ERROR;
  8797. return (l);
  8798. }
  8799. if (file == NULL)
  8800. {
  8801. WARN_BAD_FILE_NAME;
  8802. return (l);
  8803. }
  8804. bwb_fclose (My->SYSOUT->cfp);
  8805. My->SYSOUT->cfp = file;
  8806. return (l);
  8807. }
  8808. LineType *
  8809. bwb_PTP (LineType * l)
  8810. {
  8811. /* SYNTAX: PTP */
  8812. /* SYNTAX: PTP filename$ */
  8813. FILE *file;
  8814. char *filename;
  8815. assert (l != NULL);
  8816. assert(My != NULL);
  8817. assert(My->SYSOUT != NULL);
  8818. assert(My->SYSOUT->cfp != NULL);
  8819. file = NULL;
  8820. filename = NULL;
  8821. if (line_is_eol (l))
  8822. {
  8823. /* OK */
  8824. file = fopen ("PTP", "w");
  8825. }
  8826. else if (line_read_string_expression (l, &filename))
  8827. {
  8828. /* OK */
  8829. if (is_empty_string (filename))
  8830. {
  8831. WARN_BAD_FILE_NAME;
  8832. return (l);
  8833. }
  8834. file = fopen (filename, "w");
  8835. free (filename);
  8836. }
  8837. else
  8838. {
  8839. WARN_SYNTAX_ERROR;
  8840. return (l);
  8841. }
  8842. if (file == NULL)
  8843. {
  8844. WARN_BAD_FILE_NAME;
  8845. return (l);
  8846. }
  8847. bwb_fclose (My->SYSOUT->cfp);
  8848. My->SYSOUT->cfp = file;
  8849. return (l);
  8850. }
  8851. LineType *
  8852. bwb_PTR (LineType * l)
  8853. {
  8854. /* SYNTAX: PTR */
  8855. /* SYNTAX: PTR filename$ */
  8856. FILE *file;
  8857. char *filename;
  8858. assert (l != NULL);
  8859. assert(My != NULL);
  8860. assert(My->SYSIN != NULL);
  8861. assert(My->SYSIN->cfp != NULL);
  8862. file = NULL;
  8863. filename = NULL;
  8864. if (line_is_eol (l))
  8865. {
  8866. /* OK */
  8867. file = fopen ("PTR", "r");
  8868. }
  8869. else if (line_read_string_expression (l, &filename))
  8870. {
  8871. /* OK */
  8872. if (is_empty_string (filename))
  8873. {
  8874. WARN_BAD_FILE_NAME;
  8875. return (l);
  8876. }
  8877. file = fopen (filename, "r");
  8878. free (filename);
  8879. }
  8880. else
  8881. {
  8882. WARN_SYNTAX_ERROR;
  8883. return (l);
  8884. }
  8885. if (file == NULL)
  8886. {
  8887. WARN_BAD_FILE_NAME;
  8888. return (l);
  8889. }
  8890. bwb_fclose (My->SYSIN->cfp);
  8891. My->SYSIN->cfp = file;
  8892. return (l);
  8893. }
  8894. LineType *
  8895. bwb_TTY (LineType * l)
  8896. {
  8897. /* SYNTAX: TTY */
  8898. assert (l != NULL);
  8899. bwb_TTY_IN (l);
  8900. bwb_TTY_OUT (l);
  8901. return (l);
  8902. }
  8903. LineType *
  8904. bwb_TTY_IN (LineType * l)
  8905. {
  8906. /* SYNTAX: TTY IN */
  8907. assert (l != NULL);
  8908. assert(My != NULL);
  8909. assert(My->SYSIN != NULL);
  8910. assert(My->SYSIN->cfp != NULL);
  8911. bwb_fclose (My->SYSIN->cfp);
  8912. My->SYSIN->cfp = stdin;
  8913. return (l);
  8914. }
  8915. LineType *
  8916. bwb_TTY_OUT (LineType * l)
  8917. {
  8918. /* SYNTAX: TTY OUT */
  8919. assert (l != NULL);
  8920. assert(My != NULL);
  8921. assert(My->SYSOUT != NULL);
  8922. assert(My->SYSOUT->cfp != NULL);
  8923. bwb_fclose (My->SYSOUT->cfp);
  8924. My->SYSOUT->cfp = stdout;
  8925. return (l);
  8926. }
  8927. /*
  8928. --------------------------------------------------------------------------------------------
  8929. CREATE
  8930. --------------------------------------------------------------------------------------------
  8931. */
  8932. LineType *
  8933. bwb_CREATE (LineType * l)
  8934. {
  8935. /* SYNTAX: CREATE filename$ [ RECL reclen ] AS filenum [ BUFF number ] [ RECS size ] */
  8936. int FileNumber;
  8937. int width;
  8938. int buffnum;
  8939. int recsnum;
  8940. char *filename;
  8941. assert (l != NULL);
  8942. assert(My != NULL);
  8943. FileNumber = 0;
  8944. width = 0;
  8945. buffnum = 0;
  8946. recsnum = 0;
  8947. filename = NULL;
  8948. if (line_read_string_expression (l, &filename) == FALSE)
  8949. {
  8950. WARN_SYNTAX_ERROR;
  8951. return (l);
  8952. }
  8953. if (is_empty_string (filename))
  8954. {
  8955. WARN_BAD_FILE_NAME;
  8956. return (l);
  8957. }
  8958. if (line_skip_word (l, "RECL"))
  8959. {
  8960. if (line_read_integer_expression (l, &width) == FALSE)
  8961. {
  8962. WARN_FIELD_OVERFLOW;
  8963. return (l);
  8964. }
  8965. if (width <= 0)
  8966. {
  8967. WARN_FIELD_OVERFLOW;
  8968. return (l);
  8969. }
  8970. }
  8971. if (line_skip_word (l, "AS") == FALSE)
  8972. {
  8973. WARN_SYNTAX_ERROR;
  8974. return (l);
  8975. }
  8976. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  8977. {
  8978. WARN_BAD_FILE_NUMBER;
  8979. return (l);
  8980. }
  8981. if (FileNumber <= 0)
  8982. {
  8983. WARN_BAD_FILE_NUMBER;
  8984. return (l);
  8985. }
  8986. if (line_skip_word (l, "BUFF"))
  8987. {
  8988. if (line_read_integer_expression (l, &buffnum) == FALSE)
  8989. {
  8990. WARN_FIELD_OVERFLOW;
  8991. return (l);
  8992. }
  8993. if (buffnum <= 0)
  8994. {
  8995. WARN_FIELD_OVERFLOW;
  8996. return (l);
  8997. }
  8998. }
  8999. if (line_skip_word (l, "RECS"))
  9000. {
  9001. if (line_read_integer_expression (l, &recsnum) == FALSE)
  9002. {
  9003. WARN_FIELD_OVERFLOW;
  9004. return (l);
  9005. }
  9006. if (recsnum <= 0)
  9007. {
  9008. WARN_FIELD_OVERFLOW;
  9009. return (l);
  9010. }
  9011. }
  9012. /* now, we are ready to create the file */
  9013. My->CurrentFile = find_file_by_number (FileNumber);
  9014. if (My->CurrentFile == NULL)
  9015. {
  9016. My->CurrentFile = file_new ();
  9017. My->CurrentFile->FileNumber = FileNumber;
  9018. }
  9019. if (My->CurrentFile->FileName != NULL)
  9020. {
  9021. free (My->CurrentFile->FileName);
  9022. My->CurrentFile->FileName = NULL;
  9023. }
  9024. My->CurrentFile->FileName = filename;
  9025. filename = NULL;
  9026. if (My->CurrentFile->DevMode != DEVMODE_CLOSED)
  9027. {
  9028. My->CurrentFile->DevMode = DEVMODE_CLOSED;
  9029. }
  9030. if (My->CurrentFile->cfp != NULL)
  9031. {
  9032. bwb_fclose (My->CurrentFile->cfp);
  9033. My->CurrentFile->cfp = NULL;
  9034. }
  9035. if (My->CurrentFile->buffer != NULL)
  9036. {
  9037. free (My->CurrentFile->buffer);
  9038. My->CurrentFile->buffer = NULL;
  9039. }
  9040. My->CurrentFile->width = 0;
  9041. My->CurrentFile->col = 1;
  9042. My->CurrentFile->row = 1;
  9043. My->CurrentFile->delimit = ',';
  9044. /* truncate to zero length or create text file for update (reading and writing) */
  9045. if (is_empty_string (My->CurrentFile->FileName))
  9046. {
  9047. WARN_BAD_FILE_NAME;
  9048. return (l);
  9049. }
  9050. if ((My->CurrentFile->cfp =
  9051. fopen (My->CurrentFile->FileName, "w+")) == NULL)
  9052. {
  9053. WARN_BAD_FILE_NAME;
  9054. return (l);
  9055. }
  9056. if (width > 0)
  9057. {
  9058. My->CurrentFile->width = width;
  9059. My->CurrentFile->DevMode = DEVMODE_RANDOM;
  9060. }
  9061. else
  9062. {
  9063. My->CurrentFile->DevMode = DEVMODE_INPUT | DEVMODE_OUTPUT;
  9064. }
  9065. return (l);
  9066. }
  9067. /*
  9068. --------------------------------------------------------------------------------------------
  9069. COPY
  9070. --------------------------------------------------------------------------------------------
  9071. */
  9072. static void
  9073. bwb_copy_file (char *Source, char *Target)
  9074. {
  9075. FILE *source;
  9076. FILE *target;
  9077. source = NULL;
  9078. target = NULL;
  9079. if (is_empty_string (Source))
  9080. {
  9081. WARN_BAD_FILE_NAME;
  9082. goto EXIT;
  9083. }
  9084. if (is_empty_string (Target))
  9085. {
  9086. WARN_BAD_FILE_NAME;
  9087. goto EXIT;
  9088. }
  9089. source = fopen (Source, "rb");
  9090. if (source == NULL)
  9091. {
  9092. WARN_BAD_FILE_NAME;
  9093. goto EXIT;
  9094. }
  9095. target = fopen (Target, "wb");
  9096. if (target == NULL)
  9097. {
  9098. WARN_BAD_FILE_NAME;
  9099. goto EXIT;
  9100. }
  9101. /* OK */
  9102. while (TRUE)
  9103. {
  9104. int C;
  9105. C = fgetc (source);
  9106. if (C < 0 /* EOF */ || feof (source) || ferror (source))
  9107. {
  9108. break;
  9109. }
  9110. fputc (C, target);
  9111. if (ferror (target))
  9112. {
  9113. break;
  9114. }
  9115. }
  9116. /* DONE */
  9117. EXIT:
  9118. if (source)
  9119. {
  9120. fclose (source);
  9121. }
  9122. if (target)
  9123. {
  9124. fclose (target);
  9125. }
  9126. }
  9127. LineType *
  9128. bwb_COPY (LineType * Line)
  9129. {
  9130. /* SYNTAX: COPY source$ TO target$ */
  9131. char *Source;
  9132. char *Target;
  9133. assert (Line != NULL);
  9134. Source = NULL;
  9135. Target = NULL;
  9136. if (line_read_string_expression (Line, &Source) == FALSE)
  9137. {
  9138. WARN_SYNTAX_ERROR;
  9139. goto EXIT;
  9140. }
  9141. if (line_skip_word (Line, "TO") == FALSE)
  9142. {
  9143. WARN_SYNTAX_ERROR;
  9144. goto EXIT;
  9145. }
  9146. if (line_read_string_expression (Line, &Target) == FALSE)
  9147. {
  9148. WARN_SYNTAX_ERROR;
  9149. goto EXIT;
  9150. }
  9151. bwb_copy_file (Source, Target);
  9152. EXIT:
  9153. if (Source)
  9154. {
  9155. free (Source);
  9156. }
  9157. if (Target)
  9158. {
  9159. free (Target);
  9160. }
  9161. return (Line);
  9162. }
  9163. /*
  9164. --------------------------------------------------------------------------------------------
  9165. DISPLAY
  9166. --------------------------------------------------------------------------------------------
  9167. */
  9168. static void
  9169. bwb_display_file (char *Source)
  9170. {
  9171. FILE *source;
  9172. assert (My->SYSOUT != NULL);
  9173. assert (My->SYSOUT->cfp != NULL);
  9174. source = NULL;
  9175. if (is_empty_string (Source))
  9176. {
  9177. WARN_BAD_FILE_NAME;
  9178. goto EXIT;
  9179. }
  9180. source = fopen (Source, "rb");
  9181. if (source == NULL)
  9182. {
  9183. WARN_BAD_FILE_NAME;
  9184. goto EXIT;
  9185. }
  9186. /* OK */
  9187. while (TRUE)
  9188. {
  9189. int C;
  9190. C = fgetc (source);
  9191. if (C < 0 /* EOF */ || feof (source) || ferror (source))
  9192. {
  9193. break;
  9194. }
  9195. fputc (C, My->SYSOUT->cfp);
  9196. }
  9197. /* DONE */
  9198. EXIT:
  9199. if (source)
  9200. {
  9201. fclose (source);
  9202. }
  9203. }
  9204. LineType *
  9205. bwb_DISPLAY (LineType * Line)
  9206. {
  9207. /* SYNTAX: DISPLAY source$ */
  9208. char *Source;
  9209. assert (Line != NULL);
  9210. Source = NULL;
  9211. if (line_read_string_expression (Line, &Source) == FALSE)
  9212. {
  9213. WARN_SYNTAX_ERROR;
  9214. goto EXIT;
  9215. }
  9216. bwb_display_file (Source);
  9217. EXIT:
  9218. if (Source)
  9219. {
  9220. free (Source);
  9221. }
  9222. return (Line);
  9223. }
  9224. /*
  9225. --------------------------------------------------------------------------------------------
  9226. EOF
  9227. --------------------------------------------------------------------------------------------
  9228. */
  9229. /* EOF */