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.
 
 
 
 
 
 

5078 lines
103 KiB

  1. /***************************************************************
  2. bwb_var.c Variable-Handling Routines
  3. for Bywater BASIC Interpreter
  4. Copyright (c) 1993, Ted A. Campbell
  5. Bywater Software
  6. email: tcamp@delphi.com
  7. Copyright and Permissions Information:
  8. All U.S. and international rights are claimed by the author,
  9. Ted A. Campbell.
  10. This software is released under the terms of the GNU General
  11. Public License (GPL), which is distributed with this software
  12. in the file "COPYING". The GPL specifies the terms under
  13. which users may copy and use the software in this distribution.
  14. A separate license is available for commercial distribution,
  15. for information on which you should contact the author.
  16. ***************************************************************/
  17. /*---------------------------------------------------------------*/
  18. /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
  19. /* 11/1995 (eidetics@cerf.net). */
  20. /* */
  21. /* Those additionally marked with "DD" were at the suggestion of */
  22. /* Dale DePriest (daled@cadence.com). */
  23. /* */
  24. /* Version 3.00 by Howard Wulf, AF5NE */
  25. /* */
  26. /* Version 3.10 by Howard Wulf, AF5NE */
  27. /* */
  28. /* Version 3.20 by Howard Wulf, AF5NE */
  29. /* */
  30. /*---------------------------------------------------------------*/
  31. #include "bwbasic.h"
  32. /* Prototypes for functions visible to this file only */
  33. static void clear_virtual (VirtualType * Z);
  34. static void clear_virtual_by_variable (VariableType * Variable);
  35. static int dim_check (VariableType * variable);
  36. static size_t dim_unit (VariableType * v, int *pp);
  37. static LineType *dio_lrset (LineType * l, int rset);
  38. static void field_clear (FieldType * Field);
  39. static FieldType *field_new (void);
  40. static VirtualType *find_virtual_by_variable (VariableType * Variable);
  41. static LineType *internal_swap (LineType * l);
  42. static VariableType *mat_islocal (char *buffer);
  43. static VirtualType *new_virtual (void);
  44. static int var_defx (LineType * l, int TypeCode);
  45. static VariableType *var_islocal (char *buffer, int dimensions);
  46. static void var_link_new_variable (VariableType * v);
  47. extern int
  48. var_init (void)
  49. {
  50. assert( My != NULL );
  51. My->VariableHead = NULL;
  52. return TRUE;
  53. }
  54. extern LineType *
  55. bwb_COMMON (LineType * l)
  56. {
  57. /*
  58. SYNTAX: COMMON scalar
  59. SYNTAX: COMMON matrix( dimnesions ) ' COMMON A(1), B(2), C(3)
  60. SYNTAX: COMMON matrix( [, [,]] ) ' COMMON A(), B(,), C(,,)
  61. */
  62. assert (l != NULL);
  63. do
  64. {
  65. int dimensions;
  66. VariableType *variable;
  67. char varname[NameLengthMax + 1];
  68. dimensions = 0;
  69. /* get variable name and find variable */
  70. if (line_read_varname (l, varname) == FALSE)
  71. {
  72. WARN_SYNTAX_ERROR;
  73. return (l);
  74. }
  75. if (line_skip_LparenChar (l))
  76. {
  77. line_skip_spaces (l); /* keep this */
  78. if (bwb_isdigit (l->buffer[l->position]))
  79. {
  80. /* COMMON A(3) : DIM A( 5, 10, 20 ) */
  81. if (line_read_integer_expression (l, &dimensions) == FALSE)
  82. {
  83. WARN_SYNTAX_ERROR;
  84. return (l);
  85. }
  86. }
  87. else
  88. {
  89. /* COMMON A(,,) : DIM A( 5, 10, 20 ) */
  90. dimensions++;
  91. while (line_skip_seperator (l))
  92. {
  93. dimensions++;
  94. }
  95. }
  96. if (line_skip_RparenChar (l) == FALSE)
  97. {
  98. WARN_SYNTAX_ERROR;
  99. return (l);
  100. }
  101. }
  102. if ((variable = var_find (varname, dimensions, TRUE)) == NULL)
  103. {
  104. WARN_VARIABLE_NOT_DECLARED;
  105. return (l);
  106. }
  107. /* mark as COMMON */
  108. variable->VariableFlags |= VARIABLE_COMMON;
  109. }
  110. while (line_skip_seperator (l));
  111. return (l);
  112. }
  113. extern LineType *
  114. bwb_ERASE (LineType * l)
  115. {
  116. /*
  117. SYNTAX: ERASE variable [, ...] ' ERASE A, B, C
  118. */
  119. assert (l != NULL);
  120. assert( My != NULL );
  121. do
  122. {
  123. char varname[NameLengthMax + 1];
  124. /* get variable name and find variable */
  125. if (line_read_varname (l, varname))
  126. {
  127. /* erase all matching SCALAR and ARRAY variables */
  128. int dimensions;
  129. for (dimensions = 0; dimensions < MAX_DIMS; dimensions++)
  130. {
  131. VariableType *variable;
  132. variable = var_find (varname, dimensions, FALSE);
  133. if (variable != NULL)
  134. {
  135. /* found a variable */
  136. VariableType *p; /* previous variable in linked list */
  137. /* find then previous variable in chain */
  138. if (variable == My->VariableHead)
  139. {
  140. /* free head */
  141. My->VariableHead = variable->next;
  142. variable->next = NULL;
  143. var_free (variable);
  144. }
  145. else
  146. {
  147. /* free tail */
  148. for (p = My->VariableHead; p != NULL && p->next != variable;
  149. p = p->next)
  150. {
  151. ;
  152. }
  153. if (p == NULL)
  154. {
  155. /* this should never happen */
  156. WARN_INTERNAL_ERROR;
  157. return NULL;
  158. }
  159. if (p->next != variable)
  160. {
  161. /* this should never happen */
  162. WARN_INTERNAL_ERROR;
  163. return NULL;
  164. }
  165. /* reassign linkage */
  166. p->next = variable->next;
  167. variable->next = NULL;
  168. var_free (variable);
  169. }
  170. }
  171. }
  172. }
  173. }
  174. while (line_skip_seperator (l));
  175. return (l);
  176. }
  177. static LineType *
  178. internal_swap (LineType * l)
  179. {
  180. VariableType *lhs;
  181. VariableType *rhs;
  182. assert (l != NULL);
  183. if (line_skip_LparenChar (l))
  184. {
  185. /* optional */
  186. }
  187. /* get left variable */
  188. if ((lhs = line_read_scalar (l)) == NULL)
  189. {
  190. WARN_SYNTAX_ERROR;
  191. return (l);
  192. }
  193. /* get required comma */
  194. if (line_skip_seperator (l) == FALSE)
  195. {
  196. WARN_SYNTAX_ERROR;
  197. return (l);
  198. }
  199. /* get right variable */
  200. if ((rhs = line_read_scalar (l)) == NULL)
  201. {
  202. WARN_SYNTAX_ERROR;
  203. return (l);
  204. }
  205. if (line_skip_RparenChar (l))
  206. {
  207. /* optional */
  208. }
  209. /* check to be sure that both variables are compatible */
  210. if (VAR_IS_STRING (rhs) != VAR_IS_STRING (lhs))
  211. {
  212. WARN_TYPE_MISMATCH;
  213. return (l);
  214. }
  215. /* swap the values */
  216. {
  217. VariantType L;
  218. VariantType R;
  219. CLEAR_VARIANT (&L);
  220. CLEAR_VARIANT (&R);
  221. if (var_get (lhs, &L) == FALSE)
  222. {
  223. WARN_SYNTAX_ERROR;
  224. return (l);
  225. }
  226. if (var_get (rhs, &R) == FALSE)
  227. {
  228. WARN_SYNTAX_ERROR;
  229. return (l);
  230. }
  231. if (var_set (lhs, &R) == FALSE)
  232. {
  233. WARN_SYNTAX_ERROR;
  234. return (l);
  235. }
  236. if (var_set (rhs, &L) == FALSE)
  237. {
  238. WARN_SYNTAX_ERROR;
  239. return (l);
  240. }
  241. }
  242. /* return */
  243. return (l);
  244. }
  245. extern LineType *
  246. bwb_EXCHANGE (LineType * l)
  247. {
  248. /*
  249. SYNTAX: EXCHANGE variable, variable
  250. SYNTAX: EXCHANGE ( variable, variable )
  251. */
  252. assert (l != NULL);
  253. return internal_swap (l);
  254. }
  255. extern LineType *
  256. bwb_SWAP (LineType * l)
  257. {
  258. /*
  259. SYNTAX: SWAP variable, variable
  260. SYNTAX: SWAP ( variable, variable )
  261. */
  262. assert (l != NULL);
  263. return internal_swap (l);
  264. }
  265. extern VariableType *
  266. var_free (VariableType * variable)
  267. {
  268. /*
  269. Release all the memory associated with a specific variable.
  270. This function returns NULL, so you can use it like this:
  271. variable = var_new(...);
  272. ...
  273. variable = var_free( variable );
  274. */
  275. if (variable != NULL)
  276. {
  277. if (variable->next != NULL)
  278. {
  279. /* This allows variable chains to be easily released. */
  280. variable->next = var_free (variable->next);
  281. }
  282. /* cleanup this variable */
  283. field_free_variable (variable);
  284. clear_virtual_by_variable (variable);
  285. if (VAR_IS_STRING (variable))
  286. {
  287. if (variable->Value.String != NULL)
  288. {
  289. int j;
  290. for (j = 0; j < variable->array_units; j++)
  291. {
  292. if (variable->Value.String[j].sbuffer != NULL)
  293. {
  294. free (variable->Value.String[j].sbuffer);
  295. }
  296. variable->Value.String[j].length = 0;
  297. }
  298. free (variable->Value.String);
  299. variable->Value.String = NULL;
  300. }
  301. }
  302. else
  303. {
  304. if (variable->Value.Number != NULL)
  305. {
  306. free (variable->Value.Number);
  307. variable->Value.Number = NULL;
  308. }
  309. }
  310. free (variable);
  311. }
  312. return NULL;
  313. }
  314. extern void
  315. var_CLEAR (void)
  316. {
  317. /*
  318. Close all open file (variables)
  319. */
  320. /* jaf-20211010 files should be closed when variables are cleared. */
  321. bwb_close_all();
  322. /*
  323. free all variables except PRESET
  324. */
  325. VariableType *variable;
  326. assert( My != NULL );
  327. for (variable = My->VariableHead; variable != NULL;)
  328. {
  329. if (variable->VariableFlags & VARIABLE_PRESET)
  330. {
  331. /* keep */
  332. variable = variable->next;
  333. }
  334. else if (variable == My->VariableHead)
  335. {
  336. /* free head */
  337. My->VariableHead = variable->next;
  338. variable->next = NULL;
  339. var_free (variable);
  340. variable = My->VariableHead;
  341. }
  342. else
  343. {
  344. /* free tail */
  345. VariableType *z;
  346. z = variable->next;
  347. variable->next = NULL;
  348. var_free (variable);
  349. variable = z;
  350. }
  351. }
  352. }
  353. extern LineType *
  354. bwb_CLEAR (LineType * l)
  355. {
  356. /*
  357. SYNTAX: CLEAR
  358. */
  359. assert (l != NULL);
  360. var_CLEAR ();
  361. line_skip_eol (l);
  362. return (l);
  363. }
  364. LineType *
  365. bwb_CLR (LineType * l)
  366. {
  367. assert (l != NULL);
  368. return bwb_CLEAR (l);
  369. }
  370. /***********************************************************
  371. FUNCTION: var_delcvars()
  372. DESCRIPTION: This function deletes all variables
  373. in memory except those previously marked
  374. as common.
  375. ***********************************************************/
  376. int
  377. var_delcvars (void)
  378. {
  379. VariableType *v;
  380. assert( My != NULL );
  381. for (v = My->VariableHead; v != NULL;)
  382. {
  383. if (v->VariableFlags & VARIABLE_PRESET)
  384. {
  385. /* keep */
  386. v = v->next;
  387. }
  388. else if (v->VariableFlags & VARIABLE_COMMON)
  389. {
  390. /* keep */
  391. v = v->next;
  392. }
  393. else if (v == My->VariableHead)
  394. {
  395. /* free head */
  396. My->VariableHead = v->next;
  397. v->next = NULL;
  398. var_free (v);
  399. v = My->VariableHead;
  400. }
  401. else
  402. {
  403. /* free tail */
  404. VariableType *z; /* next variable */
  405. z = v->next;
  406. v->next = NULL;
  407. var_free (v);
  408. v = z;
  409. }
  410. }
  411. return TRUE;
  412. }
  413. /***********************************************************
  414. FUNCTION: bwb_mid()
  415. DESCRIPTION: This function implements the BASIC
  416. MID$ command.
  417. Same as MID$ function, except it will set
  418. the desired substring and not return its
  419. value. Added by JBV 10/95
  420. SYNTAX: MID$( string-variable$, start-position-in-string
  421. [, number-of-spaces ] ) = expression
  422. ***********************************************************/
  423. LineType *
  424. bwb_MID4 (LineType * l)
  425. {
  426. /* MID$( target$, start% [ , length% ] ) = source$ */
  427. VariableType *variable;
  428. VariantType target;
  429. int start;
  430. int length;
  431. VariantType source;
  432. int maxlen;
  433. assert (l != NULL);
  434. CLEAR_VARIANT (&source);
  435. CLEAR_VARIANT (&target);
  436. start = 0;
  437. length = 0;
  438. maxlen = 0;
  439. if (line_skip_LparenChar (l) == FALSE)
  440. {
  441. WARN_SYNTAX_ERROR;
  442. return (l);
  443. }
  444. if ((variable = line_read_scalar (l)) == NULL)
  445. {
  446. WARN_SYNTAX_ERROR;
  447. return (l);
  448. }
  449. if (VAR_IS_STRING (variable))
  450. {
  451. /* OK */
  452. }
  453. else
  454. {
  455. /* ERROR */
  456. WARN_TYPE_MISMATCH;
  457. return (l);
  458. }
  459. if (var_get (variable, &target) == FALSE)
  460. {
  461. WARN_SYNTAX_ERROR;
  462. return (l);
  463. }
  464. if (target.VariantTypeCode != StringTypeCode)
  465. {
  466. WARN_TYPE_MISMATCH;
  467. return (l);
  468. }
  469. if (line_skip_seperator (l) == FALSE)
  470. {
  471. WARN_SYNTAX_ERROR;
  472. return (l);
  473. }
  474. if (line_read_integer_expression (l, &start) == FALSE)
  475. {
  476. WARN_SYNTAX_ERROR;
  477. return (l);
  478. }
  479. if (start < 1)
  480. {
  481. WARN_ILLEGAL_FUNCTION_CALL;
  482. return (l);
  483. }
  484. if (start > target.Length)
  485. {
  486. WARN_ILLEGAL_FUNCTION_CALL;
  487. return (l);
  488. }
  489. maxlen = 1 + target.Length - start;
  490. if (line_skip_seperator (l))
  491. {
  492. if (line_read_integer_expression (l, &length) == FALSE)
  493. {
  494. WARN_SYNTAX_ERROR;
  495. return (l);
  496. }
  497. if (length < 0)
  498. {
  499. WARN_ILLEGAL_FUNCTION_CALL;
  500. return (l);
  501. }
  502. }
  503. else
  504. {
  505. length = -1; /* MAGIC */
  506. }
  507. if (line_skip_RparenChar (l) == FALSE)
  508. {
  509. WARN_SYNTAX_ERROR;
  510. return (l);
  511. }
  512. /* skip the equal sign */
  513. if (line_skip_EqualChar (l) == FALSE)
  514. {
  515. WARN_SYNTAX_ERROR;
  516. return (l);
  517. }
  518. if (line_read_expression (l, &source) == FALSE) /* bwb_MID4 */
  519. {
  520. WARN_SYNTAX_ERROR;
  521. return (l);
  522. }
  523. if (source.VariantTypeCode != StringTypeCode)
  524. {
  525. WARN_TYPE_MISMATCH;
  526. return (l);
  527. }
  528. if (length == -1 /* MAGIC */ )
  529. {
  530. length = source.Length;
  531. }
  532. length = MIN (length, maxlen);
  533. length = MIN (length, source.Length);
  534. if (length < 0)
  535. {
  536. WARN_INTERNAL_ERROR;
  537. return (l);
  538. }
  539. if (length > 0)
  540. {
  541. int i;
  542. start--; /* BASIC to C */
  543. for (i = 0; i < length; i++)
  544. {
  545. target.Buffer[start + i] = source.Buffer[i];
  546. }
  547. target.Buffer[target.Length] = NulChar;
  548. if (var_set (variable, &target) == FALSE)
  549. {
  550. WARN_SYNTAX_ERROR;
  551. return (l);
  552. }
  553. }
  554. RELEASE_VARIANT (&source);
  555. RELEASE_VARIANT (&target);
  556. return (l);
  557. }
  558. /***********************************************************
  559. FUNCTION: bwb_ddbl()
  560. DESCRIPTION: This function implements the BASIC
  561. DEFDBL command.
  562. SYNTAX: DEFDBL letter[-letter](, letter[-letter])...
  563. ***********************************************************/
  564. LineType *
  565. bwb_DEFBYT (LineType * l)
  566. {
  567. /*
  568. DEFBYT letter[-letter](, letter[-letter])...
  569. */
  570. assert (l != NULL);
  571. var_defx (l, ByteTypeCode);
  572. return (l);
  573. }
  574. LineType *
  575. bwb_DEFCUR (LineType * l)
  576. {
  577. /*
  578. DEFCUR letter[-letter](, letter[-letter])...
  579. */
  580. assert (l != NULL);
  581. var_defx (l, CurrencyTypeCode);
  582. return (l);
  583. }
  584. LineType *
  585. bwb_DEFDBL (LineType * l)
  586. {
  587. /*
  588. DEFDBL letter[-letter](, letter[-letter])...
  589. */
  590. assert (l != NULL);
  591. var_defx (l, DoubleTypeCode);
  592. return (l);
  593. }
  594. /***********************************************************
  595. FUNCTION: bwb_dint()
  596. DESCRIPTION: This function implements the BASIC
  597. DEFINT command.
  598. SYNTAX: DEFINT letter[-letter](, letter[-letter])...
  599. ***********************************************************/
  600. LineType *
  601. bwb_DEFINT (LineType * l)
  602. {
  603. /*
  604. DEFINT letter[-letter](, letter[-letter])...
  605. */
  606. assert (l != NULL);
  607. var_defx (l, IntegerTypeCode);
  608. return (l);
  609. }
  610. LineType *
  611. bwb_DEFLNG (LineType * l)
  612. {
  613. /*
  614. DEFLNG letter[-letter](, letter[-letter])...
  615. */
  616. assert (l != NULL);
  617. var_defx (l, LongTypeCode);
  618. return (l);
  619. }
  620. /***********************************************************
  621. FUNCTION: bwb_dsng()
  622. DESCRIPTION: This function implements the BASIC
  623. DEFSNG command.
  624. SYNTAX: DEFSNG letter[-letter](, letter[-letter])...
  625. ***********************************************************/
  626. LineType *
  627. bwb_DEFSNG (LineType * l)
  628. {
  629. /*
  630. DEFSNG letter[-letter](, letter[-letter])...
  631. */
  632. assert (l != NULL);
  633. var_defx (l, SingleTypeCode);
  634. return (l);
  635. }
  636. /***********************************************************
  637. FUNCTION: bwb_dstr()
  638. DESCRIPTION: This function implements the BASIC
  639. DEFSTR command.
  640. SYNTAX: DEFSTR letter[-letter](, letter[-letter])...
  641. ***********************************************************/
  642. LineType *
  643. bwb_DEFSTR (LineType * l)
  644. {
  645. /*
  646. DEFSTR letter[-letter](, letter[-letter])...
  647. */
  648. assert (l != NULL);
  649. var_defx (l, StringTypeCode);
  650. return (l);
  651. }
  652. LineType *
  653. bwb_TEXT (LineType * l)
  654. {
  655. /*
  656. TEXT letter[-letter](, letter[-letter])...
  657. */
  658. assert (l != NULL);
  659. var_defx (l, StringTypeCode);
  660. return (l);
  661. }
  662. LineType *
  663. bwb_TRACE (LineType * l)
  664. {
  665. assert (l != NULL);
  666. return bwb_TRACE_ON(l);
  667. }
  668. LineType *
  669. bwb_TRACE_ON (LineType * l)
  670. {
  671. assert (l != NULL);
  672. assert( My != NULL );
  673. assert( My->SYSOUT != NULL );
  674. assert( My->SYSOUT->cfp != NULL );
  675. fprintf (My->SYSOUT->cfp, "Trace is ON\n");
  676. ResetConsoleColumn ();
  677. My->IsTraceOn = TRUE;
  678. return (l);
  679. }
  680. LineType *
  681. bwb_TRACE_OFF (LineType * l)
  682. {
  683. assert (l != NULL);
  684. assert( My != NULL );
  685. assert( My->SYSOUT != NULL );
  686. assert( My->SYSOUT->cfp != NULL );
  687. fprintf (My->SYSOUT->cfp, "Trace is OFF\n");
  688. ResetConsoleColumn ();
  689. My->IsTraceOn = FALSE;
  690. return (l);
  691. }
  692. int
  693. VarTypeIndex (char C)
  694. {
  695. switch (C)
  696. {
  697. case 'A':
  698. return 0;
  699. case 'B':
  700. return 1;
  701. case 'C':
  702. return 2;
  703. case 'D':
  704. return 3;
  705. case 'E':
  706. return 4;
  707. case 'F':
  708. return 5;
  709. case 'G':
  710. return 6;
  711. case 'H':
  712. return 7;
  713. case 'I':
  714. return 8;
  715. case 'J':
  716. return 9;
  717. case 'K':
  718. return 10;
  719. case 'L':
  720. return 11;
  721. case 'M':
  722. return 12;
  723. case 'N':
  724. return 13;
  725. case 'O':
  726. return 14;
  727. case 'P':
  728. return 15;
  729. case 'Q':
  730. return 16;
  731. case 'R':
  732. return 17;
  733. case 'S':
  734. return 18;
  735. case 'T':
  736. return 19;
  737. case 'U':
  738. return 20;
  739. case 'V':
  740. return 21;
  741. case 'W':
  742. return 22;
  743. case 'X':
  744. return 23;
  745. case 'Y':
  746. return 24;
  747. case 'Z':
  748. return 25;
  749. case 'a':
  750. return 0;
  751. case 'b':
  752. return 1;
  753. case 'c':
  754. return 2;
  755. case 'd':
  756. return 3;
  757. case 'e':
  758. return 4;
  759. case 'f':
  760. return 5;
  761. case 'g':
  762. return 6;
  763. case 'h':
  764. return 7;
  765. case 'i':
  766. return 8;
  767. case 'j':
  768. return 9;
  769. case 'k':
  770. return 10;
  771. case 'l':
  772. return 11;
  773. case 'm':
  774. return 12;
  775. case 'n':
  776. return 13;
  777. case 'o':
  778. return 14;
  779. case 'p':
  780. return 15;
  781. case 'q':
  782. return 16;
  783. case 'r':
  784. return 17;
  785. case 's':
  786. return 18;
  787. case 't':
  788. return 19;
  789. case 'u':
  790. return 20;
  791. case 'v':
  792. return 21;
  793. case 'w':
  794. return 22;
  795. case 'x':
  796. return 23;
  797. case 'y':
  798. return 24;
  799. case 'z':
  800. return 25;
  801. }
  802. return -1;
  803. }
  804. /***********************************************************
  805. Function: var_defx()
  806. DESCRIPTION: This function is a generalized DEFxxx handler.
  807. ***********************************************************/
  808. static int
  809. var_defx (LineType * l, int TypeCode)
  810. {
  811. /*
  812. DEFxxx letter[-letter](, letter[-letter])...
  813. */
  814. assert (l != NULL);
  815. assert( My != NULL );
  816. assert( My->DefaultVariableType != NULL );
  817. do
  818. {
  819. char firstc;
  820. char lastc;
  821. int first;
  822. int last;
  823. int c;
  824. /* find a sequence of letters for variables */
  825. if (line_read_letter_sequence (l, &firstc, &lastc) == FALSE)
  826. {
  827. /* DEFINT 0-9 */
  828. WARN_SYNTAX_ERROR;
  829. return FALSE;
  830. }
  831. first = VarTypeIndex (firstc);
  832. if (first < 0)
  833. {
  834. /* DEFINT 0-Z */
  835. WARN_SYNTAX_ERROR;
  836. return FALSE;
  837. }
  838. last = VarTypeIndex (lastc);
  839. if (last < 0)
  840. {
  841. /* DEFINT A-9 */
  842. WARN_SYNTAX_ERROR;
  843. return FALSE;
  844. }
  845. if (first > last)
  846. {
  847. /* DEFINT Z-A */
  848. WARN_SYNTAX_ERROR;
  849. return FALSE;
  850. }
  851. for (c = first; c <= last; c++)
  852. {
  853. My->DefaultVariableType[c] = TypeCode; /* var_defx */
  854. }
  855. }
  856. while (line_skip_seperator (l));
  857. return TRUE;
  858. }
  859. /***************************************************************
  860. FUNCTION: var_find()
  861. DESCRIPTION: This C function attempts to find a variable
  862. name matching the argument in buffer. If
  863. it fails to find a matching name, it
  864. sets up a new variable with that name.
  865. ***************************************************************/
  866. VariableType *
  867. mat_find (char *name)
  868. {
  869. /*
  870. similar to var_find, but returns the first matrix found
  871. */
  872. VariableType *v;
  873. assert( My != NULL );
  874. /* check for NULL variable name */
  875. if (name == NULL)
  876. {
  877. WARN_INTERNAL_ERROR;
  878. return NULL;
  879. }
  880. if (is_empty_string (name))
  881. {
  882. WARN_SYNTAX_ERROR;
  883. return NULL;
  884. }
  885. /* check for a local variable at this EXEC level */
  886. v = mat_islocal (name);
  887. if (v != NULL)
  888. {
  889. return v;
  890. }
  891. /* now run through the global variable list and try to find a match */
  892. for (v = My->VariableHead; v != NULL; v = v->next)
  893. {
  894. assert( v != NULL );
  895. if (v->dimensions > 0)
  896. {
  897. if (bwb_stricmp (v->name, name) == 0)
  898. {
  899. return v;
  900. }
  901. }
  902. }
  903. return NULL;
  904. }
  905. VariableType *
  906. var_find (char *name, int dimensions, int IsImplicit)
  907. {
  908. VariableType *v;
  909. int n;
  910. assert( My != NULL );
  911. assert( My->CurrentVersion != NULL );
  912. assert( My->DefaultVariableType != NULL );
  913. /* check for NULL variable name */
  914. if (name == NULL)
  915. {
  916. WARN_INTERNAL_ERROR;
  917. return NULL;
  918. }
  919. if (is_empty_string (name))
  920. {
  921. WARN_SYNTAX_ERROR;
  922. return NULL;
  923. }
  924. if (dimensions < 0)
  925. {
  926. WARN_INTERNAL_ERROR;
  927. return NULL;
  928. }
  929. /* check for a local variable at this EXEC level */
  930. v = var_islocal (name, dimensions);
  931. if (v != NULL)
  932. {
  933. return v;
  934. }
  935. /* now run through the global variable list and try to find a match */
  936. for (v = My->VariableHead; v != NULL; v = v->next)
  937. {
  938. assert( v != NULL );
  939. if (v->dimensions == dimensions)
  940. {
  941. if (bwb_stricmp (v->name, name) == 0)
  942. {
  943. return v;
  944. }
  945. }
  946. }
  947. if (IsImplicit == FALSE)
  948. {
  949. return NULL;
  950. }
  951. if (My->CurrentVersion->OptionFlags & OPTION_EXPLICIT_ON)
  952. {
  953. /* NO implicit creation - all variables must be created via DIM */
  954. WARN_VARIABLE_NOT_DECLARED;
  955. return NULL;
  956. }
  957. if (My->CurrentVersion->OptionFlags & OPTION_STRICT_ON)
  958. {
  959. if (dimensions > 0)
  960. {
  961. /* Implicit ARRAY is not allowed */
  962. WARN_VARIABLE_NOT_DECLARED;
  963. return NULL;
  964. }
  965. }
  966. /* this is a IMPLICIT variable, so initialize it... */
  967. /* initialize new variable */
  968. if ((v = (VariableType *) calloc (1, sizeof (VariableType))) == NULL)
  969. {
  970. WARN_OUT_OF_MEMORY;
  971. return NULL;
  972. }
  973. /* copy the name into the appropriate structure */
  974. assert( v != NULL );
  975. bwb_strcpy (v->name, name);
  976. /* determine variable TypeCode */
  977. v->VariableTypeCode = var_nametype (name);
  978. if (v->VariableTypeCode == NulChar)
  979. {
  980. /* variable name has no declared TypeCode */
  981. n = VarTypeIndex (name[0]);
  982. if (n < 0)
  983. {
  984. v->VariableTypeCode = DoubleTypeCode; /* default */
  985. }
  986. else
  987. {
  988. v->VariableTypeCode = My->DefaultVariableType[n];
  989. }
  990. }
  991. v->VariableFlags = 0;
  992. v->dimensions = dimensions;
  993. v->array_units = 1;
  994. for (n = 0; n < v->dimensions; n++)
  995. {
  996. v->LBOUND[n] = My->CurrentVersion->OptionBaseInteger; /* implicit lower bound */
  997. v->UBOUND[n] = 10; /* implicit upper bound */
  998. if (v->UBOUND[n] < v->LBOUND[n])
  999. {
  1000. WARN_SUBSCRIPT_OUT_OF_RANGE;
  1001. return NULL;
  1002. }
  1003. v->VINDEX[n] = v->LBOUND[n];
  1004. v->array_units *= v->UBOUND[n] - v->LBOUND[n] + 1;
  1005. }
  1006. /* assign array memory */
  1007. if (VAR_IS_STRING (v))
  1008. {
  1009. if ((v->Value.String =
  1010. (StringType *) calloc (v->array_units, sizeof (StringType))) == NULL)
  1011. {
  1012. WARN_OUT_OF_MEMORY;
  1013. return NULL;
  1014. }
  1015. }
  1016. else
  1017. {
  1018. if ((v->Value.Number =
  1019. (DoubleType *) calloc (v->array_units, sizeof (DoubleType))) == NULL)
  1020. {
  1021. WARN_OUT_OF_MEMORY;
  1022. return NULL;
  1023. }
  1024. }
  1025. /* insert variable at the beginning of the variable chain */
  1026. v->next = My->VariableHead;
  1027. My->VariableHead = v;
  1028. return v;
  1029. }
  1030. /***************************************************************
  1031. FUNCTION: var_new()
  1032. DESCRIPTION: This function assigns memory for a new variable.
  1033. ***************************************************************/
  1034. VariableType *
  1035. var_new (char *name, char TypeCode)
  1036. {
  1037. VariableType *v;
  1038. /* get memory for new variable */
  1039. if (name == NULL)
  1040. {
  1041. WARN_INTERNAL_ERROR;
  1042. return NULL;
  1043. }
  1044. if (is_empty_string (name))
  1045. {
  1046. WARN_SYNTAX_ERROR;
  1047. return NULL;
  1048. }
  1049. if ((v = (VariableType *) calloc (1, sizeof (VariableType))) == NULL)
  1050. {
  1051. WARN_OUT_OF_MEMORY;
  1052. return NULL;
  1053. }
  1054. /* copy the name into the appropriate structure */
  1055. assert( v != NULL );
  1056. bwb_strcpy (v->name, name);
  1057. /* set memory in the new variable */
  1058. var_make (v, TypeCode);
  1059. /* and return */
  1060. return v;
  1061. }
  1062. /***************************************************************
  1063. FUNCTION: bwb_dim()
  1064. DESCRIPTION: This function implements the BASIC DIM
  1065. statement, allocating memory for a
  1066. dimensioned array of variables.
  1067. SYNTAX: DIM variable(elements...)[,variable(elements...)]
  1068. ***************************************************************/
  1069. static void
  1070. var_link_new_variable (VariableType * v)
  1071. {
  1072. /*
  1073. We are called by DIM, so this is an explicitly created variable.
  1074. There are only two possibilities:
  1075. 1. We are a LOCAL variable of a SUB or FUNCTION.
  1076. 2. We are a GLOBAL variable.
  1077. */
  1078. assert (v != NULL);
  1079. assert( My != NULL );
  1080. if (My->StackHead != NULL)
  1081. {
  1082. StackType *StackItem;
  1083. for (StackItem = My->StackHead; StackItem != NULL;
  1084. StackItem = StackItem->next)
  1085. {
  1086. if (StackItem->LoopTopLine != NULL)
  1087. {
  1088. switch (StackItem->LoopTopLine->cmdnum)
  1089. {
  1090. case C_FUNCTION:
  1091. case C_SUB:
  1092. /* we have found a FUNCTION or SUB boundary, must be LOCAL */
  1093. v->next = StackItem->local_variable;
  1094. StackItem->local_variable = v;
  1095. return;
  1096. /* break; */
  1097. }
  1098. }
  1099. }
  1100. }
  1101. /* no FUNCTION or SUB on the stack, must be GLOBAL */
  1102. v->next = My->VariableHead;
  1103. My->VariableHead = v;
  1104. }
  1105. static VirtualType *
  1106. new_virtual (void)
  1107. {
  1108. VirtualType *Z;
  1109. assert( My != NULL );
  1110. /* look for an empty slot */
  1111. for (Z = My->VirtualHead; Z != NULL; Z = Z->next)
  1112. {
  1113. if (Z->Variable == NULL)
  1114. {
  1115. /* FOUND */
  1116. return Z;
  1117. }
  1118. }
  1119. /* NOT FOUND */
  1120. if ((Z = (VirtualType *) calloc (1, sizeof (VirtualType))) == NULL)
  1121. {
  1122. WARN_OUT_OF_MEMORY;
  1123. return NULL;
  1124. }
  1125. Z->next = My->VirtualHead;
  1126. My->VirtualHead = Z;
  1127. return Z;
  1128. }
  1129. static void
  1130. clear_virtual (VirtualType * Z)
  1131. {
  1132. assert (Z != NULL);
  1133. Z->Variable = NULL;
  1134. Z->FileNumber = 0;
  1135. Z->FileOffset = 0;
  1136. Z->FileLength = 0;
  1137. }
  1138. static void
  1139. clear_virtual_by_variable (VariableType * Variable)
  1140. {
  1141. VirtualType *Z;
  1142. assert (Variable != NULL);
  1143. assert( My != NULL );
  1144. for (Z = My->VirtualHead; Z != NULL; Z = Z->next)
  1145. {
  1146. if (Z->Variable == Variable)
  1147. {
  1148. /* FOUND */
  1149. clear_virtual (Z);
  1150. }
  1151. }
  1152. }
  1153. extern void
  1154. clear_virtual_by_file (int FileNumber)
  1155. {
  1156. /* called by file_clear() */
  1157. VirtualType *Z;
  1158. assert( My != NULL );
  1159. for (Z = My->VirtualHead; Z != NULL; Z = Z->next)
  1160. {
  1161. if (Z->FileNumber == FileNumber)
  1162. {
  1163. /* FOUND */
  1164. clear_virtual (Z);
  1165. }
  1166. }
  1167. }
  1168. static VirtualType *
  1169. find_virtual_by_variable (VariableType * Variable)
  1170. {
  1171. VirtualType *Z;
  1172. assert (Variable != NULL);
  1173. assert( My != NULL );
  1174. for (Z = My->VirtualHead; Z != NULL; Z = Z->next)
  1175. {
  1176. if (Z->Variable == Variable)
  1177. {
  1178. /* FOUND */
  1179. return Z;
  1180. }
  1181. }
  1182. /* NOT FOUND */
  1183. return NULL;
  1184. }
  1185. LineType *
  1186. bwb_LOCAL (LineType * l)
  1187. {
  1188. /* only supported inside a FUNCTION or SUB */
  1189. assert (l != NULL);
  1190. return bwb_DIM (l);
  1191. }
  1192. LineType *
  1193. bwb_DIM (LineType * l)
  1194. {
  1195. int FileNumber; /* the file might not be OPEN when the variable is declared */
  1196. size_t FileOffset; /* from beginning of file */
  1197. int FileLength; /* sizeof( DoubleType ) or Fixed String Length */
  1198. assert (l != NULL);
  1199. assert( My != NULL );
  1200. assert( My->DefaultVariableType != NULL );
  1201. FileNumber = 0;
  1202. FileOffset = 0;
  1203. FileLength = 0;
  1204. if (line_skip_FilenumChar (l))
  1205. {
  1206. /* DIM # filenum , ... */
  1207. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  1208. {
  1209. WARN_BAD_FILE_NUMBER;
  1210. return (l);
  1211. }
  1212. if (FileNumber <= 0)
  1213. {
  1214. WARN_BAD_FILE_NUMBER;
  1215. return (l);
  1216. }
  1217. if (line_skip_seperator (l) == FALSE)
  1218. {
  1219. WARN_BAD_FILE_NUMBER;
  1220. return (l);
  1221. }
  1222. FileOffset = 0;
  1223. FileLength = 0;
  1224. }
  1225. do
  1226. {
  1227. VariableType *v;
  1228. int n;
  1229. int dimensions;
  1230. int LBOUND[MAX_DIMS];
  1231. int UBOUND[MAX_DIMS];
  1232. char TypeCode;
  1233. char varname[NameLengthMax + 1];
  1234. /* Get variable name */
  1235. if (line_read_varname (l, varname) == FALSE)
  1236. {
  1237. WARN_SYNTAX_ERROR;
  1238. return (l);
  1239. }
  1240. /* read parameters */
  1241. dimensions = 0;
  1242. if (line_peek_LparenChar (l))
  1243. {
  1244. if (line_read_array_redim (l, &dimensions, LBOUND, UBOUND) == FALSE)
  1245. {
  1246. WARN_SYNTAX_ERROR;
  1247. return (l);
  1248. }
  1249. /* check array dimensions */
  1250. for (n = 0; n < dimensions; n++)
  1251. {
  1252. if (UBOUND[n] < LBOUND[n])
  1253. {
  1254. WARN_SUBSCRIPT_OUT_OF_RANGE;
  1255. return (l);
  1256. }
  1257. }
  1258. }
  1259. /* determine variable TypeCode */
  1260. TypeCode = var_nametype (varname);
  1261. if (TypeCode == NulChar)
  1262. {
  1263. /* variable has no explicit TypeCode char */
  1264. TypeCode = line_read_type_declaration (l); /* AS DOUBLE and so on */
  1265. if (TypeCode == NulChar)
  1266. {
  1267. /* variable has no declared TypeCode */
  1268. int i;
  1269. i = VarTypeIndex (varname[0]);
  1270. if (i < 0)
  1271. {
  1272. TypeCode = DoubleTypeCode; /* default */
  1273. }
  1274. else
  1275. {
  1276. TypeCode = My->DefaultVariableType[i];
  1277. }
  1278. }
  1279. }
  1280. switch (TypeCode)
  1281. {
  1282. case ByteTypeCode:
  1283. /* DIM # file_num , var_name AS BYTE */
  1284. FileLength = sizeof (ByteType);
  1285. break;
  1286. case IntegerTypeCode:
  1287. /* DIM # file_num , var_name AS INTEGER */
  1288. FileLength = sizeof (IntegerType);
  1289. break;
  1290. case LongTypeCode:
  1291. /* DIM # file_num , var_name AS LONG */
  1292. FileLength = sizeof (LongType);
  1293. break;
  1294. case CurrencyTypeCode:
  1295. /* DIM # file_num , var_name AS CURRENCY */
  1296. FileLength = sizeof (CurrencyType);
  1297. break;
  1298. case SingleTypeCode:
  1299. /* DIM # file_num , var_name AS SINGLE */
  1300. FileLength = sizeof (SingleType);
  1301. break;
  1302. case DoubleTypeCode:
  1303. /* DIM # file_num , var_name AS DOUBLE */
  1304. FileLength = sizeof (DoubleType);
  1305. break;
  1306. case StringTypeCode:
  1307. /* DIM # file_num , var_name AS STRING * fixed_length */
  1308. FileLength = 16; /* default */
  1309. if (line_skip_StarChar (l) || line_skip_EqualChar (l))
  1310. {
  1311. /* optional fixed length */
  1312. if (line_read_integer_expression (l, &FileLength) == FALSE)
  1313. {
  1314. WARN_SYNTAX_ERROR;
  1315. return (l);
  1316. }
  1317. if (FileLength <= 0)
  1318. {
  1319. WARN_SYNTAX_ERROR;
  1320. return (l);
  1321. }
  1322. if (FileLength > MAXLEN)
  1323. {
  1324. WARN_STRING_TOO_LONG; /* bwb_DIM */
  1325. FileLength = MAXLEN;
  1326. }
  1327. }
  1328. break;
  1329. default:
  1330. {
  1331. WARN_INTERNAL_ERROR;
  1332. return (l);
  1333. }
  1334. }
  1335. v = var_find (varname, dimensions, FALSE);
  1336. if (v == NULL)
  1337. {
  1338. /* a new variable */
  1339. if ((v = (VariableType *) calloc (1, sizeof (VariableType))) == NULL)
  1340. {
  1341. WARN_OUT_OF_MEMORY;
  1342. return (l);
  1343. }
  1344. bwb_strcpy (v->name, varname);
  1345. v->VariableTypeCode = TypeCode;
  1346. /* assign array dimensions */
  1347. v->dimensions = dimensions;
  1348. for (n = 0; n < dimensions; n++)
  1349. {
  1350. v->LBOUND[n] = LBOUND[n];
  1351. v->UBOUND[n] = UBOUND[n];
  1352. }
  1353. /* assign initial array position */
  1354. for (n = 0; n < dimensions; n++)
  1355. {
  1356. v->VINDEX[n] = v->LBOUND[n];
  1357. }
  1358. /* calculate the array size */
  1359. v->array_units = 1;
  1360. for (n = 0; n < dimensions; n++)
  1361. {
  1362. v->array_units *= v->UBOUND[n] - v->LBOUND[n] + 1;
  1363. }
  1364. /* assign array memory */
  1365. if (FileNumber > 0)
  1366. {
  1367. /* the new variable is VIRTUAL */
  1368. v->VariableFlags = VARIABLE_VIRTUAL;
  1369. /* if( TRUE ) */
  1370. {
  1371. /* OK */
  1372. VirtualType *Z;
  1373. Z = find_virtual_by_variable (v);
  1374. if (Z == NULL)
  1375. {
  1376. Z = new_virtual ();
  1377. if (Z == NULL)
  1378. {
  1379. WARN_OUT_OF_MEMORY;
  1380. return (l);
  1381. }
  1382. Z->Variable = v;
  1383. }
  1384. /* update file information */
  1385. Z->FileNumber = FileNumber;
  1386. Z->FileOffset = FileOffset;
  1387. Z->FileLength = FileLength;
  1388. FileOffset += FileLength * v->array_units;
  1389. }
  1390. }
  1391. else if (VAR_IS_STRING (v))
  1392. {
  1393. if ((v->Value.String =
  1394. (StringType *) calloc (v->array_units,
  1395. sizeof (StringType))) == NULL)
  1396. {
  1397. WARN_OUT_OF_MEMORY;
  1398. return (l);
  1399. }
  1400. }
  1401. else
  1402. {
  1403. if ((v->Value.Number =
  1404. (DoubleType *) calloc (v->array_units,
  1405. sizeof (DoubleType))) == NULL)
  1406. {
  1407. WARN_OUT_OF_MEMORY;
  1408. return (l);
  1409. }
  1410. }
  1411. /* set place at beginning of variable chain */
  1412. var_link_new_variable (v);
  1413. /* end of conditional for new variable */
  1414. }
  1415. else
  1416. {
  1417. /* old variable */
  1418. if (v->VariableTypeCode != TypeCode)
  1419. {
  1420. WARN_TYPE_MISMATCH;
  1421. return (l);
  1422. }
  1423. /* check to be sure the number of dimensions is the same */
  1424. if (v->dimensions != dimensions)
  1425. {
  1426. WARN_REDIMENSION_ARRAY;
  1427. return (l);
  1428. }
  1429. /* check to be sure sizes for each dimension are the same */
  1430. for (n = 0; n < dimensions; n++)
  1431. {
  1432. if (v->LBOUND[n] != LBOUND[n])
  1433. {
  1434. WARN_REDIMENSION_ARRAY;
  1435. return (l);
  1436. }
  1437. if (v->UBOUND[n] != UBOUND[n])
  1438. {
  1439. WARN_REDIMENSION_ARRAY;
  1440. return (l);
  1441. }
  1442. }
  1443. if (FileNumber > 0)
  1444. {
  1445. /* the existing variable MUST be Virtual */
  1446. if (v->VariableFlags & VARIABLE_VIRTUAL)
  1447. {
  1448. /* OK */
  1449. VirtualType *Z;
  1450. Z = find_virtual_by_variable (v);
  1451. if (Z == NULL)
  1452. {
  1453. Z = new_virtual ();
  1454. if (Z == NULL)
  1455. {
  1456. WARN_OUT_OF_MEMORY;
  1457. return (l);
  1458. }
  1459. Z->Variable = v;
  1460. }
  1461. /* update file information */
  1462. Z->FileNumber = FileNumber;
  1463. Z->FileOffset = FileOffset;
  1464. Z->FileLength = FileLength;
  1465. FileOffset += FileLength * v->array_units;
  1466. }
  1467. else
  1468. {
  1469. /* the existing variable is NOT virtual */
  1470. WARN_TYPE_MISMATCH;
  1471. return (l);
  1472. }
  1473. }
  1474. else
  1475. {
  1476. /* the existing variable CANNOT be Virtual */
  1477. if (v->VariableFlags & VARIABLE_VIRTUAL)
  1478. {
  1479. /* the existing variable IS virtual */
  1480. WARN_TYPE_MISMATCH;
  1481. return (l);
  1482. }
  1483. else
  1484. {
  1485. /* OK */
  1486. }
  1487. }
  1488. /* end of conditional for old variable */
  1489. }
  1490. }
  1491. while (line_skip_seperator (l));
  1492. /* return */
  1493. return (l);
  1494. }
  1495. /***************************************************************
  1496. FUNCTION: dim_unit()
  1497. DESCRIPTION: This function calculates the unit
  1498. position for an array.
  1499. ***************************************************************/
  1500. static size_t
  1501. dim_unit (VariableType * v, int *pp)
  1502. {
  1503. size_t r;
  1504. size_t b;
  1505. int n;
  1506. assert (v != NULL);
  1507. assert (pp != NULL);
  1508. /* Calculate and return the address of the dimensioned array */
  1509. /* Check EACH dimension for out-of-bounds, AND check correct number
  1510. * of dimensions. NBS_P076_0250 errors correctly. */
  1511. /*
  1512. Ux = Upper bound of dimension
  1513. Lx = Lower bound of dimension
  1514. Ix = Selected idex in dimension
  1515. dimensions b
  1516. 0 1
  1517. 1 b0 * ( U0 - L0 + 1 )
  1518. 2 b1 * ( U1 - L1 + 1 )
  1519. 3 b2 * ( U2 - L2 + 1 )
  1520. dimensions r
  1521. 0 0
  1522. 1 r0 + ( I0 - L0 ) * b0
  1523. 2 r1 + ( I1 - L1 ) * b1
  1524. 3 r2 + ( I2 - L2 ) * b2
  1525. */
  1526. r = 0;
  1527. b = 1;
  1528. for (n = 0; n < v->dimensions; n++)
  1529. {
  1530. if (pp[n] < v->LBOUND[n] || pp[n] > v->UBOUND[n])
  1531. {
  1532. WARN_SUBSCRIPT_OUT_OF_RANGE;
  1533. return 0;
  1534. }
  1535. r += b * (pp[n] - v->LBOUND[n]);
  1536. b *= v->UBOUND[n] - v->LBOUND[n] + 1;
  1537. }
  1538. if (r > v->array_units)
  1539. {
  1540. WARN_SUBSCRIPT_OUT_OF_RANGE;
  1541. return 0;
  1542. }
  1543. return r;
  1544. }
  1545. /***************************************************************
  1546. FUNCTION: bwb_option()
  1547. DESCRIPTION: This function implements the BASIC OPTION
  1548. BASE statement, designating the base (1 or
  1549. 0) for addressing DIM arrays.
  1550. SYNTAX: OPTION BASE number
  1551. ***************************************************************/
  1552. void
  1553. OptionVersionSet (int i)
  1554. {
  1555. assert( i >= 0 && i < NUM_VERSIONS );
  1556. assert( My != NULL );
  1557. My->CurrentVersion = &bwb_vertable[i];
  1558. }
  1559. LineType *
  1560. bwb_OPTION (LineType * l)
  1561. {
  1562. assert (l != NULL);
  1563. WARN_SYNTAX_ERROR;
  1564. return (l);
  1565. }
  1566. LineType *
  1567. bwb_OPTION_ANGLE (LineType * l)
  1568. {
  1569. assert (l != NULL);
  1570. WARN_SYNTAX_ERROR;
  1571. return (l);
  1572. }
  1573. LineType *
  1574. bwb_OPTION_ANGLE_DEGREES (LineType * l)
  1575. {
  1576. assert (l != NULL);
  1577. assert( My != NULL );
  1578. assert( My->CurrentVersion != NULL );
  1579. /* OPTION ANGLE DEGREES */
  1580. My->CurrentVersion->OptionFlags |= OPTION_ANGLE_DEGREES;
  1581. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_GRADIANS;
  1582. return (l);
  1583. }
  1584. LineType *
  1585. bwb_OPTION_ANGLE_GRADIANS (LineType * l)
  1586. {
  1587. assert (l != NULL);
  1588. assert( My != NULL );
  1589. assert( My->CurrentVersion != NULL );
  1590. /* OPTION ANGLE GRADIANS */
  1591. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_DEGREES;
  1592. My->CurrentVersion->OptionFlags |= OPTION_ANGLE_GRADIANS;
  1593. return (l);
  1594. }
  1595. LineType *
  1596. bwb_OPTION_ANGLE_RADIANS (LineType * l)
  1597. {
  1598. assert (l != NULL);
  1599. assert( My != NULL );
  1600. assert( My->CurrentVersion != NULL );
  1601. /* OPTION ANGLE RADIANS */
  1602. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_DEGREES;
  1603. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_GRADIANS;
  1604. return (l);
  1605. }
  1606. LineType *
  1607. bwb_OPTION_ARITHMETIC (LineType * l)
  1608. {
  1609. assert (l != NULL);
  1610. WARN_SYNTAX_ERROR;
  1611. return (l);
  1612. }
  1613. LineType *
  1614. bwb_OPTION_ARITHMETIC_DECIMAL (LineType * l)
  1615. {
  1616. /* OPTION ARITHMETIC DECIMAL */
  1617. assert (l != NULL);
  1618. return (l);
  1619. }
  1620. LineType *
  1621. bwb_OPTION_ARITHMETIC_FIXED (LineType * l)
  1622. {
  1623. /* OPTION ARITHMETIC FIXED */
  1624. assert (l != NULL);
  1625. return (l);
  1626. }
  1627. LineType *
  1628. bwb_OPTION_ARITHMETIC_NATIVE (LineType * l)
  1629. {
  1630. /* OPTION ARITHMETIC NATIVE */
  1631. assert (l != NULL);
  1632. return (l);
  1633. }
  1634. LineType *
  1635. bwb_OPTION_BASE (LineType * l)
  1636. {
  1637. /* OPTION BASE integer */
  1638. assert (l != NULL);
  1639. assert( My != NULL );
  1640. assert( My->CurrentVersion != NULL );
  1641. return bwb_option_range_integer (l,
  1642. &(My->CurrentVersion->OptionBaseInteger),
  1643. MININT, MAXINT);
  1644. }
  1645. LineType *
  1646. bwb_OPTION_BUGS (LineType * l)
  1647. {
  1648. assert (l != NULL);
  1649. WARN_SYNTAX_ERROR;
  1650. return (l);
  1651. }
  1652. LineType *
  1653. bwb_OPTION_BUGS_BOOLEAN (LineType * l)
  1654. {
  1655. assert (l != NULL);
  1656. assert( My != NULL );
  1657. assert( My->CurrentVersion != NULL );
  1658. /* OPTION BUGS BOOLEAN */
  1659. My->CurrentVersion->OptionFlags |= OPTION_BUGS_BOOLEAN;
  1660. return (l);
  1661. }
  1662. LineType *
  1663. bwb_OPTION_BUGS_ON (LineType * l)
  1664. {
  1665. assert (l != NULL);
  1666. assert( My != NULL );
  1667. assert( My->CurrentVersion != NULL );
  1668. /* OPTION BUGS ON */
  1669. My->CurrentVersion->OptionFlags |= OPTION_BUGS_ON;
  1670. return (l);
  1671. }
  1672. LineType *
  1673. bwb_OPTION_BUGS_OFF (LineType * l)
  1674. {
  1675. assert (l != NULL);
  1676. assert( My != NULL );
  1677. assert( My->CurrentVersion != NULL );
  1678. /* OPTION BUGS OFF */
  1679. My->CurrentVersion->OptionFlags &= ~OPTION_BUGS_ON;
  1680. My->CurrentVersion->OptionFlags &= ~OPTION_BUGS_BOOLEAN;
  1681. return (l);
  1682. }
  1683. LineType *
  1684. bwb_option_punct_char (LineType * l, char *c)
  1685. {
  1686. /* OPTION ... char$ */
  1687. assert (l != NULL);
  1688. assert (c != NULL);
  1689. {
  1690. char *Value;
  1691. char C;
  1692. Value = NULL;
  1693. if (line_read_string_expression (l, &Value) == FALSE)
  1694. {
  1695. WARN_SYNTAX_ERROR;
  1696. return (l);
  1697. }
  1698. if (Value == NULL)
  1699. {
  1700. WARN_SYNTAX_ERROR;
  1701. return (l);
  1702. }
  1703. C = Value[0];
  1704. free (Value);
  1705. /* OK */
  1706. if (bwb_ispunct (C))
  1707. {
  1708. /* enable */
  1709. *c = C;
  1710. }
  1711. else
  1712. {
  1713. /* disable */
  1714. *c = NulChar;
  1715. }
  1716. }
  1717. return (l);
  1718. }
  1719. LineType *
  1720. bwb_option_range_integer (LineType * l, int *Integer, int MinVal, int MaxVal)
  1721. {
  1722. /* OPTION ... integer */
  1723. assert (l != NULL);
  1724. assert (Integer != NULL);
  1725. assert (MinVal < MaxVal);
  1726. {
  1727. int Value;
  1728. Value = 0;
  1729. if (line_read_integer_expression (l, &Value) == FALSE)
  1730. {
  1731. WARN_SYNTAX_ERROR;
  1732. return (l);
  1733. }
  1734. if (Value < MinVal || Value > MaxVal)
  1735. {
  1736. WARN_ILLEGAL_FUNCTION_CALL;
  1737. return (l);
  1738. }
  1739. *Integer = Value;
  1740. }
  1741. return (l);
  1742. }
  1743. LineType *
  1744. bwb_OPTION_PUNCT_COMMENT (LineType * l)
  1745. {
  1746. /* OPTION PUNCT COMMENT char$ */
  1747. assert (l != NULL);
  1748. assert( My != NULL );
  1749. assert( My->CurrentVersion != NULL );
  1750. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionCommentChar));
  1751. }
  1752. LineType *
  1753. bwb_OPTION_COMPARE (LineType * l)
  1754. {
  1755. assert (l != NULL);
  1756. WARN_SYNTAX_ERROR;
  1757. return (l);
  1758. }
  1759. LineType *
  1760. bwb_OPTION_COMPARE_BINARY (LineType * l)
  1761. {
  1762. assert (l != NULL);
  1763. assert( My != NULL );
  1764. assert( My->CurrentVersion != NULL );
  1765. /* OPTION COMPARE BINARY */
  1766. My->CurrentVersion->OptionFlags &= ~OPTION_COMPARE_TEXT;
  1767. return (l);
  1768. }
  1769. LineType *
  1770. bwb_OPTION_COMPARE_DATABASE (LineType * l)
  1771. {
  1772. assert (l != NULL);
  1773. assert( My != NULL );
  1774. assert( My->CurrentVersion != NULL );
  1775. /* OPTION COMPARE DATABASE */
  1776. My->CurrentVersion->OptionFlags |= OPTION_COMPARE_TEXT;
  1777. return (l);
  1778. }
  1779. LineType *
  1780. bwb_OPTION_COMPARE_TEXT (LineType * l)
  1781. {
  1782. assert (l != NULL);
  1783. assert( My != NULL );
  1784. assert( My->CurrentVersion != NULL );
  1785. /* OPTION COMPARE TEXT */
  1786. My->CurrentVersion->OptionFlags |= OPTION_COMPARE_TEXT;
  1787. return (l);
  1788. }
  1789. LineType *
  1790. bwb_OPTION_COVERAGE (LineType * l)
  1791. {
  1792. assert (l != NULL);
  1793. WARN_SYNTAX_ERROR;
  1794. return (l);
  1795. }
  1796. LineType *
  1797. bwb_OPTION_COVERAGE_ON (LineType * l)
  1798. {
  1799. assert (l != NULL);
  1800. assert( My != NULL );
  1801. assert( My->CurrentVersion != NULL );
  1802. /* OPTION COVERAGE ON */
  1803. My->CurrentVersion->OptionFlags |= OPTION_COVERAGE_ON;
  1804. return (l);
  1805. }
  1806. LineType *
  1807. bwb_OPTION_COVERAGE_OFF (LineType * l)
  1808. {
  1809. assert (l != NULL);
  1810. assert( My != NULL );
  1811. assert( My->CurrentVersion != NULL );
  1812. /* OPTION COVERAGE OFF */
  1813. My->CurrentVersion->OptionFlags &= ~OPTION_COVERAGE_ON;
  1814. return (l);
  1815. }
  1816. LineType *
  1817. bwb_OPTION_DATE (LineType * l)
  1818. {
  1819. /* OPTION DATE format$ */
  1820. char *Value;
  1821. assert (l != NULL);
  1822. assert( My != NULL );
  1823. assert( My->CurrentVersion != NULL );
  1824. Value = NULL;
  1825. if (line_read_string_expression (l, &Value) == FALSE)
  1826. {
  1827. WARN_SYNTAX_ERROR;
  1828. return (l);
  1829. }
  1830. if (Value == NULL)
  1831. {
  1832. WARN_SYNTAX_ERROR;
  1833. return (l);
  1834. }
  1835. /* OK */
  1836. My->CurrentVersion->OptionDateFormat = Value;
  1837. #if FALSE /* keep this ... */
  1838. /*
  1839. ** Yes, this can theoretically cause a memory leak.
  1840. ** No, we are not going to fix it.
  1841. ** This command is only supported in the profile.
  1842. ** This will only execute at most once,
  1843. ** so there is no actual memory leak.
  1844. **
  1845. */
  1846. free (Value);
  1847. #endif
  1848. return (l);
  1849. }
  1850. LineType *
  1851. bwb_OPTION_DIGITS (LineType * l)
  1852. {
  1853. int Value;
  1854. assert (l != NULL);
  1855. assert( My != NULL );
  1856. /* OPTION DIGITS integer */
  1857. Value = 0;
  1858. if (line_read_integer_expression (l, &Value))
  1859. {
  1860. /* OK */
  1861. if (Value == 0)
  1862. {
  1863. /* default */
  1864. Value = SIGNIFICANT_DIGITS;
  1865. }
  1866. if (Value < MINIMUM_DIGITS || Value > MAXIMUM_DIGITS)
  1867. {
  1868. WARN_ILLEGAL_FUNCTION_CALL;
  1869. return (l);
  1870. }
  1871. My->OptionDigitsInteger = Value;
  1872. }
  1873. return (l);
  1874. }
  1875. LineType *
  1876. bwb_OPTION_DISABLE (LineType * l)
  1877. {
  1878. assert (l != NULL);
  1879. WARN_SYNTAX_ERROR;
  1880. return (l);
  1881. }
  1882. LineType *
  1883. bwb_OPTION_DISABLE_COMMAND (LineType * l)
  1884. {
  1885. /* OPTION DISABLE COMMAND name$ */
  1886. int IsFound;
  1887. char *Value;
  1888. assert (l != NULL);
  1889. assert( My != NULL );
  1890. assert( My->CurrentVersion != NULL );
  1891. IsFound = FALSE;
  1892. Value = NULL;
  1893. /* Get COMMAND */
  1894. if (line_read_string_expression (l, &Value) == FALSE)
  1895. {
  1896. WARN_SYNTAX_ERROR;
  1897. return (l);
  1898. }
  1899. if (Value == NULL)
  1900. {
  1901. WARN_SYNTAX_ERROR;
  1902. return (l);
  1903. }
  1904. /* OK */
  1905. {
  1906. /* Name */
  1907. int i;
  1908. for (i = 0; i < NUM_COMMANDS; i++)
  1909. {
  1910. if (bwb_stricmp (Value, IntrinsicCommandTable[i].name) == 0)
  1911. {
  1912. /* FOUND */
  1913. /* DISABLE COMMAND */
  1914. IntrinsicCommandTable[i].OptionVersionBitmask &=
  1915. ~My->CurrentVersion->OptionVersionValue;
  1916. IsFound = TRUE;
  1917. }
  1918. }
  1919. }
  1920. free (Value);
  1921. if (IsFound == FALSE)
  1922. {
  1923. /* display warning message */
  1924. fprintf (My->SYSOUT->cfp, "IGNORED: %s\n", l->buffer);
  1925. ResetConsoleColumn ();
  1926. }
  1927. return (l);
  1928. }
  1929. LineType *
  1930. bwb_OPTION_DISABLE_FUNCTION (LineType * l)
  1931. {
  1932. /* OPTION DISABLE FUNCTION name$ */
  1933. int IsFound;
  1934. assert (l != NULL);
  1935. assert( My != NULL );
  1936. assert( My->CurrentVersion != NULL );
  1937. IsFound = FALSE;
  1938. /* Get FUNCTION */
  1939. {
  1940. char *Value;
  1941. Value = NULL;
  1942. if (line_read_string_expression (l, &Value) == FALSE)
  1943. {
  1944. WARN_SYNTAX_ERROR;
  1945. return (l);
  1946. }
  1947. if (Value == NULL)
  1948. {
  1949. WARN_SYNTAX_ERROR;
  1950. return (l);
  1951. }
  1952. /* OK */
  1953. {
  1954. /* Name */
  1955. int i;
  1956. for (i = 0; i < NUM_FUNCTIONS; i++)
  1957. {
  1958. if (bwb_stricmp (Value, IntrinsicFunctionTable[i].Name) == 0)
  1959. {
  1960. /* FOUND */
  1961. /* DISABLE FUNCTION */
  1962. IntrinsicFunctionTable[i].OptionVersionBitmask &=
  1963. ~My->CurrentVersion->OptionVersionValue;
  1964. IsFound = TRUE;
  1965. }
  1966. }
  1967. }
  1968. free (Value);
  1969. }
  1970. if (IsFound == FALSE)
  1971. {
  1972. /* display warning message */
  1973. fprintf (My->SYSOUT->cfp, "IGNORED: %s\n", l->buffer);
  1974. ResetConsoleColumn ();
  1975. }
  1976. return (l);
  1977. }
  1978. LineType *
  1979. bwb_OPTION_EDIT (LineType * l)
  1980. {
  1981. /* OPTION EDIT string$ */
  1982. char *Value;
  1983. assert (l != NULL);
  1984. assert( My != NULL );
  1985. Value = NULL;
  1986. if (line_read_string_expression (l, &Value) == FALSE)
  1987. {
  1988. WARN_SYNTAX_ERROR;
  1989. return (l);
  1990. }
  1991. if (Value == NULL)
  1992. {
  1993. WARN_SYNTAX_ERROR;
  1994. return (l);
  1995. }
  1996. /* OK */
  1997. My->OptionEditString = Value;
  1998. #if FALSE /* keep this ... */
  1999. /*
  2000. ** Yes, this can theoretically cause a memory leak.
  2001. ** No, we are not going to fix it.
  2002. ** This command is only supported in the profile.
  2003. ** This will only execute at most once,
  2004. ** so there is no actual memory leak.
  2005. **
  2006. */
  2007. free (Value);
  2008. #endif
  2009. return (l);
  2010. }
  2011. LineType *
  2012. bwb_OPTION_EXTENSION (LineType * l)
  2013. {
  2014. /* OPTION EXTENSION ext$ */
  2015. char *Value;
  2016. assert (l != NULL);
  2017. assert( My != NULL );
  2018. Value = NULL;
  2019. if (line_read_string_expression (l, &Value) == FALSE)
  2020. {
  2021. WARN_SYNTAX_ERROR;
  2022. return (l);
  2023. }
  2024. if (Value == NULL)
  2025. {
  2026. WARN_SYNTAX_ERROR;
  2027. return (l);
  2028. }
  2029. /* OK */
  2030. My->OptionExtensionString = Value;
  2031. #if FALSE /* keep this ... */
  2032. /*
  2033. ** Yes, this can theoretically cause a memory leak.
  2034. ** No, we are not going to fix it.
  2035. ** This command is only supported in the profile.
  2036. ** This command will only execute at most once,
  2037. ** so there is no actual memory leak.
  2038. **
  2039. */
  2040. free (Value);
  2041. #endif
  2042. return (l);
  2043. }
  2044. LineType *
  2045. bwb_OPTION_FILES (LineType * l)
  2046. {
  2047. /* OPTION FILES name$ */
  2048. char *Value;
  2049. assert (l != NULL);
  2050. assert( My != NULL );
  2051. Value = NULL;
  2052. if (line_read_string_expression (l, &Value) == FALSE)
  2053. {
  2054. WARN_SYNTAX_ERROR;
  2055. return (l);
  2056. }
  2057. if (Value == NULL)
  2058. {
  2059. WARN_SYNTAX_ERROR;
  2060. return (l);
  2061. }
  2062. /* OK */
  2063. My->OptionFilesString = Value;
  2064. #if FALSE /* keep this ... */
  2065. /*
  2066. ** Yes, this can theoretically cause a memory leak.
  2067. ** No, we are not going to fix it.
  2068. ** This command is only supported in the profile.
  2069. ** This will only execute at most once,
  2070. ** so there is no actual memory leak.
  2071. **
  2072. */
  2073. free (Value);
  2074. #endif
  2075. return (l);
  2076. }
  2077. LineType *
  2078. bwb_OPTION_PROMPT (LineType * l)
  2079. {
  2080. /* OPTION PROMPT prompt$ */
  2081. char *Value;
  2082. assert (l != NULL);
  2083. assert( My != NULL );
  2084. Value = NULL;
  2085. if (line_read_string_expression (l, &Value) == FALSE)
  2086. {
  2087. WARN_SYNTAX_ERROR;
  2088. return (l);
  2089. }
  2090. if (Value == NULL)
  2091. {
  2092. WARN_SYNTAX_ERROR;
  2093. return (l);
  2094. }
  2095. /* OK */
  2096. My->OptionPromptString = Value;
  2097. #if FALSE /* keep this ... */
  2098. /*
  2099. ** Yes, this can theoretically cause a memory leak.
  2100. ** No, we are not going to fix it.
  2101. ** This command is only supported in the profile.
  2102. ** This will only execute at most once,
  2103. ** so there is no actual memory leak.
  2104. **
  2105. */
  2106. free (Value);
  2107. #endif
  2108. return (l);
  2109. }
  2110. LineType *
  2111. bwb_OPTION_RENUM (LineType * l)
  2112. {
  2113. /* OPTION RENUM name$ */
  2114. char *Value;
  2115. assert (l != NULL);
  2116. assert( My != NULL );
  2117. Value = NULL;
  2118. if (line_read_string_expression (l, &Value) == FALSE)
  2119. {
  2120. WARN_SYNTAX_ERROR;
  2121. return (l);
  2122. }
  2123. if (Value == NULL)
  2124. {
  2125. WARN_SYNTAX_ERROR;
  2126. return (l);
  2127. }
  2128. /* OK */
  2129. My->OptionRenumString = Value;
  2130. #if FALSE /* keep this ... */
  2131. /*
  2132. ** Yes, this can theoretically cause a memory leak.
  2133. ** No, we are not going to fix it.
  2134. ** This command is only supported in the profile.
  2135. ** This will only execute at most once,
  2136. ** so there is no actual memory leak.
  2137. **
  2138. */
  2139. free (Value);
  2140. #endif
  2141. return (l);
  2142. }
  2143. LineType *
  2144. bwb_OPTION_ENABLE (LineType * l)
  2145. {
  2146. assert (l != NULL);
  2147. WARN_SYNTAX_ERROR;
  2148. return (l);
  2149. }
  2150. LineType *
  2151. bwb_OPTION_ENABLE_COMMAND (LineType * l)
  2152. {
  2153. /* OPTION ENABLE COMMAND name$ */
  2154. int IsFound;
  2155. assert (l != NULL);
  2156. assert( My != NULL );
  2157. assert( My->CurrentVersion != NULL );
  2158. IsFound = FALSE;
  2159. /* Get COMMAND */
  2160. {
  2161. char *Value;
  2162. Value = NULL;
  2163. if (line_read_string_expression (l, &Value) == FALSE)
  2164. {
  2165. WARN_SYNTAX_ERROR;
  2166. return (l);
  2167. }
  2168. if (Value == NULL)
  2169. {
  2170. WARN_SYNTAX_ERROR;
  2171. return (l);
  2172. }
  2173. /* OK */
  2174. {
  2175. /* Name */
  2176. int i;
  2177. for (i = 0; i < NUM_COMMANDS; i++)
  2178. {
  2179. if (bwb_stricmp (Value, IntrinsicCommandTable[i].name) == 0)
  2180. {
  2181. /* FOUND */
  2182. /* ENABLE COMMAND */
  2183. IntrinsicCommandTable[i].OptionVersionBitmask |=
  2184. My->CurrentVersion->OptionVersionValue;
  2185. IsFound = TRUE;
  2186. }
  2187. }
  2188. }
  2189. free (Value);
  2190. }
  2191. if (IsFound == FALSE)
  2192. {
  2193. /* display warning message */
  2194. fprintf (My->SYSOUT->cfp, "IGNORED: %s\n", l->buffer);
  2195. ResetConsoleColumn ();
  2196. }
  2197. return (l);
  2198. }
  2199. LineType *
  2200. bwb_OPTION_ENABLE_FUNCTION (LineType * l)
  2201. {
  2202. /* OPTION ENABLE FUNCTION name$ */
  2203. int IsFound;
  2204. assert (l != NULL);
  2205. assert( My != NULL );
  2206. assert( My->CurrentVersion != NULL );
  2207. IsFound = FALSE;
  2208. /* Get FUNCTION */
  2209. {
  2210. char *Value;
  2211. Value = NULL;
  2212. if (line_read_string_expression (l, &Value) == FALSE)
  2213. {
  2214. WARN_SYNTAX_ERROR;
  2215. return (l);
  2216. }
  2217. if (Value == NULL)
  2218. {
  2219. WARN_SYNTAX_ERROR;
  2220. return (l);
  2221. }
  2222. /* OK */
  2223. {
  2224. /* Name */
  2225. int i;
  2226. for (i = 0; i < NUM_FUNCTIONS; i++)
  2227. {
  2228. if (bwb_stricmp (Value, IntrinsicFunctionTable[i].Name) == 0)
  2229. {
  2230. /* FOUND */
  2231. /* ENABLE FUNCTION */
  2232. IntrinsicFunctionTable[i].OptionVersionBitmask |=
  2233. My->CurrentVersion->OptionVersionValue;
  2234. IsFound = TRUE;
  2235. }
  2236. }
  2237. }
  2238. free (Value);
  2239. }
  2240. if (IsFound == FALSE)
  2241. {
  2242. /* display warning message */
  2243. fprintf (My->SYSOUT->cfp, "IGNORED: %s\n", l->buffer);
  2244. ResetConsoleColumn ();
  2245. }
  2246. return (l);
  2247. }
  2248. LineType *
  2249. bwb_OPTION_ERROR (LineType * l)
  2250. {
  2251. assert (l != NULL);
  2252. WARN_SYNTAX_ERROR;
  2253. return (l);
  2254. }
  2255. LineType *
  2256. bwb_OPTION_ERROR_GOSUB (LineType * l)
  2257. {
  2258. /* OPTION ERROR GOSUB */
  2259. assert (l != NULL);
  2260. assert( My != NULL );
  2261. assert( My->CurrentVersion != NULL );
  2262. My->CurrentVersion->OptionFlags |= OPTION_ERROR_GOSUB;
  2263. return (l);
  2264. }
  2265. LineType *
  2266. bwb_OPTION_ERROR_GOTO (LineType * l)
  2267. {
  2268. /* OPTION ERROR GOTO */
  2269. assert (l != NULL);
  2270. assert( My != NULL );
  2271. assert( My->CurrentVersion != NULL );
  2272. My->CurrentVersion->OptionFlags &= ~OPTION_ERROR_GOSUB;
  2273. return (l);
  2274. }
  2275. LineType *
  2276. bwb_OPTION_EXPLICIT (LineType * l)
  2277. {
  2278. /* OPTION EXPLICIT */
  2279. assert (l != NULL);
  2280. assert( My != NULL );
  2281. assert( My->CurrentVersion != NULL );
  2282. My->CurrentVersion->OptionFlags |= OPTION_EXPLICIT_ON;
  2283. return (l);
  2284. }
  2285. LineType *
  2286. bwb_OPTION_PUNCT_IMAGE (LineType * l)
  2287. {
  2288. /* OPTION PUNCT IMAGE char$ */
  2289. assert (l != NULL);
  2290. assert( My != NULL );
  2291. assert( My->CurrentVersion != NULL );
  2292. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionImageChar));
  2293. }
  2294. LineType *
  2295. bwb_OPTION_IMPLICIT (LineType * l)
  2296. {
  2297. /* OPTION IMPLICIT */
  2298. assert (l != NULL);
  2299. assert( My != NULL );
  2300. assert( My->CurrentVersion != NULL );
  2301. My->CurrentVersion->OptionFlags &= ~OPTION_EXPLICIT_ON;
  2302. return (l);
  2303. }
  2304. LineType *
  2305. bwb_OPTION_INDENT (LineType * l)
  2306. {
  2307. /* OPTION INDENT integer */
  2308. assert (l != NULL);
  2309. assert( My != NULL );
  2310. return bwb_option_range_integer (l, &(My->OptionIndentInteger), 0, 7);
  2311. }
  2312. LineType *
  2313. bwb_OPTION_PUNCT_INPUT (LineType * l)
  2314. {
  2315. /* OPTION PUNCT INPUT char$ */
  2316. assert (l != NULL);
  2317. assert( My != NULL );
  2318. assert( My->CurrentVersion != NULL );
  2319. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionInputChar));
  2320. }
  2321. LineType *
  2322. bwb_OPTION_LABELS (LineType * l)
  2323. {
  2324. assert (l != NULL);
  2325. WARN_SYNTAX_ERROR;
  2326. return (l);
  2327. }
  2328. LineType *
  2329. bwb_OPTION_LABELS_ON (LineType * l)
  2330. {
  2331. assert (l != NULL);
  2332. assert( My != NULL );
  2333. assert( My->CurrentVersion != NULL );
  2334. /* OPTION LABELS ON */
  2335. My->CurrentVersion->OptionFlags |= OPTION_LABELS_ON;
  2336. return (l);
  2337. }
  2338. LineType *
  2339. bwb_OPTION_LABELS_OFF (LineType * l)
  2340. {
  2341. assert (l != NULL);
  2342. assert( My != NULL );
  2343. assert( My->CurrentVersion != NULL );
  2344. /* OPTION LABELS OFF */
  2345. My->CurrentVersion->OptionFlags &= ~OPTION_LABELS_ON;
  2346. return (l);
  2347. }
  2348. LineType *
  2349. bwb_OPTION_PUNCT_PRINT (LineType * l)
  2350. {
  2351. /* OPTION PUNCT PRINT char$ */
  2352. assert (l != NULL);
  2353. assert( My != NULL );
  2354. assert( My->CurrentVersion != NULL );
  2355. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionPrintChar));
  2356. }
  2357. LineType *
  2358. bwb_OPTION_PUNCT_QUOTE (LineType * l)
  2359. {
  2360. /* OPTION PUNCT QUOTE char$ */
  2361. assert (l != NULL);
  2362. assert( My != NULL );
  2363. assert( My->CurrentVersion != NULL );
  2364. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionQuoteChar));
  2365. }
  2366. LineType *
  2367. bwb_OPTION_ROUND (LineType * l)
  2368. {
  2369. assert (l != NULL);
  2370. WARN_SYNTAX_ERROR;
  2371. return (l);
  2372. }
  2373. LineType *
  2374. bwb_OPTION_ROUND_BANK (LineType * l)
  2375. {
  2376. /* OPTION ROUND BANK */
  2377. assert (l != NULL);
  2378. assert( My != NULL );
  2379. My->OptionRoundType = C_OPTION_ROUND_BANK;
  2380. return (l);
  2381. }
  2382. LineType *
  2383. bwb_OPTION_ROUND_MATH (LineType * l)
  2384. {
  2385. /* OPTION ROUND MATH */
  2386. assert (l != NULL);
  2387. assert( My != NULL );
  2388. My->OptionRoundType = C_OPTION_ROUND_MATH;
  2389. return (l);
  2390. }
  2391. LineType *
  2392. bwb_OPTION_ROUND_TRUNCATE (LineType * l)
  2393. {
  2394. /* OPTION ROUND TRUNCATE */
  2395. assert (l != NULL);
  2396. assert( My != NULL );
  2397. My->OptionRoundType = C_OPTION_ROUND_TRUNCATE;
  2398. return (l);
  2399. }
  2400. LineType *
  2401. bwb_OPTION_SCALE (LineType * l)
  2402. {
  2403. /* OPTION SCALE integer */
  2404. assert (l != NULL);
  2405. assert( My != NULL );
  2406. return bwb_option_range_integer (l, &(My->OptionScaleInteger),
  2407. MINIMUM_SCALE, MAXIMUM_SCALE);
  2408. }
  2409. LineType *
  2410. bwb_OPTION_SLEEP (LineType * l)
  2411. {
  2412. /* OPTION SLEEP number */
  2413. assert (l != NULL);
  2414. assert( My != NULL );
  2415. if (line_read_numeric_expression (l, &My->OptionSleepDouble) == FALSE)
  2416. {
  2417. WARN_SYNTAX_ERROR;
  2418. return (l);
  2419. }
  2420. return (l);
  2421. }
  2422. LineType *
  2423. bwb_OPTION_STDERR (LineType * l)
  2424. {
  2425. /* OPTION STDERR filename$ */
  2426. assert (l != NULL);
  2427. assert( My != NULL );
  2428. assert( My->SYSPRN != NULL );
  2429. assert( My->SYSPRN->cfp != NULL );
  2430. if (line_is_eol (l))
  2431. {
  2432. bwb_fclose (My->SYSPRN->cfp);
  2433. My->SYSPRN->cfp = stderr;
  2434. }
  2435. else
  2436. {
  2437. char *Value;
  2438. Value = NULL;
  2439. if (line_read_string_expression (l, &Value) == FALSE)
  2440. {
  2441. WARN_SYNTAX_ERROR;
  2442. return (l);
  2443. }
  2444. if (Value == NULL)
  2445. {
  2446. WARN_SYNTAX_ERROR;
  2447. return (l);
  2448. }
  2449. /* OK */
  2450. if (is_empty_string (Value))
  2451. {
  2452. bwb_fclose (My->SYSPRN->cfp);
  2453. My->SYSPRN->cfp = stderr;
  2454. }
  2455. else
  2456. {
  2457. bwb_fclose (My->SYSPRN->cfp);
  2458. My->SYSPRN->cfp = fopen (Value, "w+");
  2459. if (My->SYSPRN->cfp == NULL)
  2460. {
  2461. /* sane default */
  2462. My->SYSPRN->cfp = stderr;
  2463. WARN_BAD_FILE_NAME;
  2464. }
  2465. }
  2466. free (Value);
  2467. }
  2468. return (l);
  2469. }
  2470. LineType *
  2471. bwb_OPTION_STDIN (LineType * l)
  2472. {
  2473. /* OPTION STDIN filename$ */
  2474. assert (l != NULL);
  2475. assert( My != NULL );
  2476. assert( My->SYSIN != NULL );
  2477. assert( My->SYSIN->cfp != NULL );
  2478. if (line_is_eol (l))
  2479. {
  2480. bwb_fclose (My->SYSIN->cfp);
  2481. My->SYSIN->cfp = stdin;
  2482. }
  2483. else
  2484. {
  2485. char *Value;
  2486. Value = NULL;
  2487. if (line_read_string_expression (l, &Value) == FALSE)
  2488. {
  2489. WARN_SYNTAX_ERROR;
  2490. return (l);
  2491. }
  2492. if (Value == NULL)
  2493. {
  2494. WARN_SYNTAX_ERROR;
  2495. return (l);
  2496. }
  2497. /* OK */
  2498. if (is_empty_string (Value))
  2499. {
  2500. bwb_fclose (My->SYSIN->cfp);
  2501. My->SYSIN->cfp = stdin;
  2502. }
  2503. else
  2504. {
  2505. bwb_fclose (My->SYSIN->cfp);
  2506. My->SYSIN->cfp = fopen (Value, "r");
  2507. if (My->SYSIN->cfp == NULL)
  2508. {
  2509. /* sane default */
  2510. My->SYSIN->cfp = stdin;
  2511. WARN_BAD_FILE_NAME;
  2512. }
  2513. }
  2514. free (Value);
  2515. }
  2516. return (l);
  2517. }
  2518. LineType *
  2519. bwb_OPTION_STDOUT (LineType * l)
  2520. {
  2521. /* OPTION STDOUT filename$ */
  2522. assert (l != NULL);
  2523. assert( My != NULL );
  2524. assert( My->SYSOUT != NULL );
  2525. assert( My->SYSOUT->cfp != NULL );
  2526. if (line_is_eol (l))
  2527. {
  2528. bwb_fclose (My->SYSOUT->cfp);
  2529. My->SYSOUT->cfp = stdout;
  2530. }
  2531. else
  2532. {
  2533. char *Value;
  2534. Value = NULL;
  2535. if (line_read_string_expression (l, &Value) == FALSE)
  2536. {
  2537. WARN_SYNTAX_ERROR;
  2538. return (l);
  2539. }
  2540. if (Value == NULL)
  2541. {
  2542. WARN_SYNTAX_ERROR;
  2543. return (l);
  2544. }
  2545. /* OK */
  2546. if (is_empty_string (Value))
  2547. {
  2548. bwb_fclose (My->SYSOUT->cfp);
  2549. My->SYSOUT->cfp = stdout;
  2550. }
  2551. else
  2552. {
  2553. bwb_fclose (My->SYSOUT->cfp);
  2554. My->SYSOUT->cfp = fopen (Value, "w+");
  2555. if (My->SYSOUT->cfp == NULL)
  2556. {
  2557. /* sane default */
  2558. My->SYSOUT->cfp = stdout;
  2559. WARN_BAD_FILE_NAME;
  2560. }
  2561. }
  2562. free (Value);
  2563. }
  2564. return (l);
  2565. }
  2566. LineType *
  2567. bwb_OPTION_PUNCT_STATEMENT (LineType * l)
  2568. {
  2569. /* OPTION PUNCT STATEMENT char$ */
  2570. assert (l != NULL);
  2571. assert( My != NULL );
  2572. assert( My->CurrentVersion != NULL );
  2573. return bwb_option_punct_char (l,
  2574. &(My->CurrentVersion->OptionStatementChar));
  2575. }
  2576. LineType *
  2577. bwb_OPTION_STRICT (LineType * l)
  2578. {
  2579. assert (l != NULL);
  2580. WARN_SYNTAX_ERROR;
  2581. return (l);
  2582. }
  2583. LineType *
  2584. bwb_OPTION_STRICT_ON (LineType * l)
  2585. {
  2586. assert (l != NULL);
  2587. assert( My != NULL );
  2588. assert( My->CurrentVersion != NULL );
  2589. /* OPTION STRICT ON */
  2590. My->CurrentVersion->OptionFlags |= OPTION_STRICT_ON;
  2591. return (l);
  2592. }
  2593. LineType *
  2594. bwb_OPTION_STRICT_OFF (LineType * l)
  2595. {
  2596. assert (l != NULL);
  2597. assert( My != NULL );
  2598. assert( My->CurrentVersion != NULL );
  2599. /* OPTION STRICT OFF */
  2600. My->CurrentVersion->OptionFlags &= ~OPTION_STRICT_ON;
  2601. return (l);
  2602. }
  2603. LineType *
  2604. bwb_OPTION_PUNCT (LineType * l)
  2605. {
  2606. assert (l != NULL);
  2607. WARN_SYNTAX_ERROR;
  2608. return (l);
  2609. }
  2610. LineType *
  2611. bwb_OPTION_PUNCT_STRING (LineType * l)
  2612. {
  2613. /* OPTION PUNCT STRING char$ */
  2614. assert (l != NULL);
  2615. assert( My != NULL );
  2616. assert( My->CurrentVersion != NULL );
  2617. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionStringChar));
  2618. }
  2619. LineType *
  2620. bwb_OPTION_PUNCT_DOUBLE (LineType * l)
  2621. {
  2622. /* OPTION PUNCT DOUBLE char$ */
  2623. assert (l != NULL);
  2624. assert( My != NULL );
  2625. assert( My->CurrentVersion != NULL );
  2626. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionDoubleChar));
  2627. }
  2628. LineType *
  2629. bwb_OPTION_PUNCT_SINGLE (LineType * l)
  2630. {
  2631. /* OPTION PUNCT SINGLE char$ */
  2632. assert (l != NULL);
  2633. assert( My != NULL );
  2634. assert( My->CurrentVersion != NULL );
  2635. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionSingleChar));
  2636. }
  2637. LineType *
  2638. bwb_OPTION_PUNCT_CURRENCY (LineType * l)
  2639. {
  2640. /* OPTION PUNCT CURRENCY char$ */
  2641. assert (l != NULL);
  2642. assert( My != NULL );
  2643. assert( My->CurrentVersion != NULL );
  2644. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionCurrencyChar));
  2645. }
  2646. LineType *
  2647. bwb_OPTION_PUNCT_LONG (LineType * l)
  2648. {
  2649. /* OPTION PUNCT LONG char$ */
  2650. assert (l != NULL);
  2651. assert( My != NULL );
  2652. assert( My->CurrentVersion != NULL );
  2653. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionLongChar));
  2654. }
  2655. LineType *
  2656. bwb_OPTION_PUNCT_INTEGER (LineType * l)
  2657. {
  2658. /* OPTION PUNCT INTEGER char$ */
  2659. assert (l != NULL);
  2660. assert( My != NULL );
  2661. assert( My->CurrentVersion != NULL );
  2662. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionIntegerChar));
  2663. }
  2664. LineType *
  2665. bwb_OPTION_PUNCT_BYTE (LineType * l)
  2666. {
  2667. /* OPTION PUNCT BYTE char$ */
  2668. assert (l != NULL);
  2669. assert( My != NULL );
  2670. assert( My->CurrentVersion != NULL );
  2671. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionByteChar));
  2672. }
  2673. LineType *
  2674. bwb_OPTION_PUNCT_LPAREN (LineType * l)
  2675. {
  2676. /* OPTION PUNCT LPAREN char$ */
  2677. assert (l != NULL);
  2678. assert( My != NULL );
  2679. assert( My->CurrentVersion != NULL );
  2680. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionLparenChar));
  2681. }
  2682. LineType *
  2683. bwb_OPTION_PUNCT_RPAREN (LineType * l)
  2684. {
  2685. /* OPTION PUNCT RPAREN char$ */
  2686. assert (l != NULL);
  2687. assert( My != NULL );
  2688. assert( My->CurrentVersion != NULL );
  2689. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionRparenChar));
  2690. }
  2691. LineType *
  2692. bwb_OPTION_PUNCT_FILENUM (LineType * l)
  2693. {
  2694. /* OPTION PUNCT FILENUM char$ */
  2695. assert (l != NULL);
  2696. assert( My != NULL );
  2697. assert( My->CurrentVersion != NULL );
  2698. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionFilenumChar));
  2699. }
  2700. LineType *
  2701. bwb_OPTION_PUNCT_AT (LineType * l)
  2702. {
  2703. /* OPTION PUNCT AT char$ */
  2704. assert (l != NULL);
  2705. assert( My != NULL );
  2706. assert( My->CurrentVersion != NULL );
  2707. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionAtChar));
  2708. }
  2709. LineType *
  2710. bwb_OPTION_RECLEN (LineType * l)
  2711. {
  2712. /* OPTION RECLEN integer */
  2713. assert (l != NULL);
  2714. assert( My != NULL );
  2715. assert( My->CurrentVersion != NULL );
  2716. return bwb_option_range_integer (l,
  2717. &(My->CurrentVersion->OptionReclenInteger),
  2718. 0, MAXINT);
  2719. }
  2720. LineType *
  2721. bwb_OPTION_TERMINAL (LineType * l)
  2722. {
  2723. assert (l != NULL);
  2724. WARN_SYNTAX_ERROR;
  2725. return (l);
  2726. }
  2727. LineType *
  2728. bwb_OPTION_TERMINAL_NONE (LineType * l)
  2729. {
  2730. /* OPTION TERMINAL NONE */
  2731. assert (l != NULL);
  2732. assert( My != NULL );
  2733. My->OptionTerminalType = C_OPTION_TERMINAL_NONE;
  2734. return (l);
  2735. }
  2736. LineType *
  2737. bwb_OPTION_TERMINAL_ADM (LineType * l)
  2738. {
  2739. /* OPTION TERMINAL ADM-3A */
  2740. assert (l != NULL);
  2741. assert( My != NULL );
  2742. My->OptionTerminalType = C_OPTION_TERMINAL_ADM;
  2743. return (l);
  2744. }
  2745. LineType *
  2746. bwb_OPTION_TERMINAL_ANSI (LineType * l)
  2747. {
  2748. /* OPTION TERMINAL ANSI */
  2749. assert (l != NULL);
  2750. assert( My != NULL );
  2751. My->OptionTerminalType = C_OPTION_TERMINAL_ANSI;
  2752. return (l);
  2753. }
  2754. LineType *
  2755. bwb_OPTION_TIME (LineType * l)
  2756. {
  2757. /* OPTION TIME format$ */
  2758. char *Value;
  2759. assert (l != NULL);
  2760. assert( My != NULL );
  2761. assert( My->CurrentVersion != NULL );
  2762. Value = NULL;
  2763. if (line_read_string_expression (l, &Value) == FALSE)
  2764. {
  2765. WARN_SYNTAX_ERROR;
  2766. return (l);
  2767. }
  2768. if (Value == NULL)
  2769. {
  2770. WARN_SYNTAX_ERROR;
  2771. return (l);
  2772. }
  2773. /* OK */
  2774. My->CurrentVersion->OptionTimeFormat = Value;
  2775. #if FALSE /* keep this ... */
  2776. /*
  2777. ** Yes, this can theoretically cause a memory leak.
  2778. ** No, we are not going to fix it.
  2779. ** This command is only supported in the profile.
  2780. ** This will only execute at most once,
  2781. ** so there is no actual memory leak.
  2782. **
  2783. */
  2784. free (Value);
  2785. #endif
  2786. return (l);
  2787. }
  2788. LineType *
  2789. bwb_OPTION_TRACE (LineType * l)
  2790. {
  2791. assert (l != NULL);
  2792. WARN_SYNTAX_ERROR;
  2793. return (l);
  2794. }
  2795. LineType *
  2796. bwb_OPTION_TRACE_ON (LineType * l)
  2797. {
  2798. /* OPTION TRACE ON */
  2799. assert (l != NULL);
  2800. assert( My != NULL );
  2801. assert( My->CurrentVersion != NULL );
  2802. My->CurrentVersion->OptionFlags |= OPTION_TRACE_ON;
  2803. return (l);
  2804. }
  2805. LineType *
  2806. bwb_OPTION_TRACE_OFF (LineType * l)
  2807. {
  2808. /* OPTION TRACE OFF */
  2809. assert (l != NULL);
  2810. assert( My != NULL );
  2811. assert( My->CurrentVersion != NULL );
  2812. My->CurrentVersion->OptionFlags &= ~OPTION_TRACE_ON;
  2813. return (l);
  2814. }
  2815. LineType *
  2816. bwb_OPTION_USING (LineType * l)
  2817. {
  2818. assert (l != NULL);
  2819. WARN_SYNTAX_ERROR;
  2820. return (l);
  2821. }
  2822. LineType *
  2823. bwb_OPTION_USING_DIGIT (LineType * l)
  2824. {
  2825. /* OPTION USING DIGIT char$ */
  2826. assert (l != NULL);
  2827. assert( My != NULL );
  2828. assert( My->CurrentVersion != NULL );
  2829. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingDigit));
  2830. }
  2831. LineType *
  2832. bwb_OPTION_USING_COMMA (LineType * l)
  2833. {
  2834. /* OPTION USING COMMA char$ */
  2835. assert (l != NULL);
  2836. assert( My != NULL );
  2837. assert( My->CurrentVersion != NULL );
  2838. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingComma));
  2839. }
  2840. LineType *
  2841. bwb_OPTION_USING_PERIOD (LineType * l)
  2842. {
  2843. /* OPTION USING PERIOD char$ */
  2844. assert (l != NULL);
  2845. assert( My != NULL );
  2846. assert( My->CurrentVersion != NULL );
  2847. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingPeriod));
  2848. }
  2849. LineType *
  2850. bwb_OPTION_USING_PLUS (LineType * l)
  2851. {
  2852. /* OPTION USING PLUS char$ */
  2853. assert (l != NULL);
  2854. assert( My != NULL );
  2855. assert( My->CurrentVersion != NULL );
  2856. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingPlus));
  2857. }
  2858. LineType *
  2859. bwb_OPTION_USING_MINUS (LineType * l)
  2860. {
  2861. /* OPTION USING MINUS char$ */
  2862. assert (l != NULL);
  2863. assert( My != NULL );
  2864. assert( My->CurrentVersion != NULL );
  2865. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingMinus));
  2866. }
  2867. LineType *
  2868. bwb_OPTION_USING_EXRAD (LineType * l)
  2869. {
  2870. /* OPTION USING EXRAD char$ */
  2871. assert (l != NULL);
  2872. assert( My != NULL );
  2873. assert( My->CurrentVersion != NULL );
  2874. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingExrad));
  2875. }
  2876. LineType *
  2877. bwb_OPTION_USING_DOLLAR (LineType * l)
  2878. {
  2879. /* OPTION USING DOLLAR char$ */
  2880. assert (l != NULL);
  2881. assert( My != NULL );
  2882. assert( My->CurrentVersion != NULL );
  2883. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingDollar));
  2884. }
  2885. LineType *
  2886. bwb_OPTION_USING_FILLER (LineType * l)
  2887. {
  2888. /* OPTION USING FILLER char$ */
  2889. assert (l != NULL);
  2890. assert( My != NULL );
  2891. assert( My->CurrentVersion != NULL );
  2892. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingFiller));
  2893. }
  2894. LineType *
  2895. bwb_OPTION_USING_LITERAL (LineType * l)
  2896. {
  2897. /* OPTION USING LITERAL char$ */
  2898. assert (l != NULL);
  2899. assert( My != NULL );
  2900. assert( My->CurrentVersion != NULL );
  2901. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingLiteral));
  2902. }
  2903. LineType *
  2904. bwb_OPTION_USING_FIRST (LineType * l)
  2905. {
  2906. /* OPTION USING FIRST char$ */
  2907. assert (l != NULL);
  2908. assert( My != NULL );
  2909. assert( My->CurrentVersion != NULL );
  2910. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingFirst));
  2911. }
  2912. LineType *
  2913. bwb_OPTION_USING_ALL (LineType * l)
  2914. {
  2915. /* OPTION USING ALL char$ */
  2916. assert (l != NULL);
  2917. assert( My != NULL );
  2918. assert( My->CurrentVersion != NULL );
  2919. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingAll));
  2920. }
  2921. LineType *
  2922. bwb_OPTION_USING_LENGTH (LineType * l)
  2923. {
  2924. /* OPTION USING LENGTH char$ */
  2925. assert (l != NULL);
  2926. assert( My != NULL );
  2927. assert( My->CurrentVersion != NULL );
  2928. return bwb_option_punct_char (l, &(My->CurrentVersion->OptionUsingLength));
  2929. }
  2930. extern LineType *
  2931. bwb_OPTION_VERSION (LineType * l)
  2932. {
  2933. /* OPTION VERSION [version$] */
  2934. char *Name;
  2935. int i;
  2936. assert (l != NULL);
  2937. assert( My != NULL );
  2938. assert( My->SYSOUT != NULL );
  2939. assert( My->SYSOUT->cfp != NULL );
  2940. Name = NULL;
  2941. if (line_is_eol (l))
  2942. {
  2943. /* OPTIONAL */
  2944. }
  2945. else if (line_read_string_expression (l, &Name))
  2946. {
  2947. if (is_empty_string (Name) == FALSE)
  2948. {
  2949. /* a version was specified */
  2950. for (i = 0; i < NUM_VERSIONS; i++)
  2951. {
  2952. if (bwb_stricmp (Name, bwb_vertable[i].Name) == 0)
  2953. {
  2954. /* FOUND */
  2955. OptionVersionSet (i);
  2956. return (l);
  2957. }
  2958. }
  2959. /* NOT FOUND */
  2960. fprintf (My->SYSOUT->cfp, "OPTION VERSION \"%s\" IS INVALID\n", Name);
  2961. }
  2962. }
  2963. fprintf (My->SYSOUT->cfp, "VALID CHOICES ARE:\n");
  2964. for (i = 0; i < NUM_VERSIONS; i++)
  2965. {
  2966. char *tbuf;
  2967. tbuf = My->ConsoleOutput;
  2968. bwb_strcpy (tbuf, "\"");
  2969. bwb_strcat (tbuf, bwb_vertable[i].Name);
  2970. bwb_strcat (tbuf, "\"");
  2971. fprintf (My->SYSOUT->cfp, "OPTION VERSION %-16s ' %s\n", tbuf,
  2972. bwb_vertable[i].Description);
  2973. }
  2974. ResetConsoleColumn ();
  2975. line_skip_eol (l);
  2976. return (l);
  2977. }
  2978. LineType *
  2979. bwb_OPTION_ZONE (LineType * l)
  2980. {
  2981. /* OPTION ZONE integer */
  2982. int Value;
  2983. assert (l != NULL);
  2984. assert( My != NULL );
  2985. Value = 0;
  2986. if (line_read_integer_expression (l, &Value))
  2987. {
  2988. /* OK */
  2989. if (Value == 0)
  2990. {
  2991. /* default */
  2992. Value = ZONE_WIDTH;
  2993. }
  2994. if (Value < MINIMUM_ZONE || Value > MAXIMUM_ZONE)
  2995. {
  2996. WARN_ILLEGAL_FUNCTION_CALL;
  2997. return (l);
  2998. }
  2999. My->OptionZoneInteger = Value;
  3000. }
  3001. return (l);
  3002. }
  3003. int
  3004. var_get (VariableType * variable, VariantType * variant)
  3005. {
  3006. size_t offset;
  3007. /* check sanity */
  3008. if (variable == NULL)
  3009. {
  3010. WARN_INTERNAL_ERROR;
  3011. return FALSE;
  3012. }
  3013. if (variant == NULL)
  3014. {
  3015. WARN_INTERNAL_ERROR;
  3016. return FALSE;
  3017. }
  3018. /* Check subscripts */
  3019. if (dim_check (variable) == FALSE)
  3020. {
  3021. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3022. return FALSE;
  3023. }
  3024. /* Determine offset from array base ( for scalars the offset is always zero ) */
  3025. offset = dim_unit (variable, variable->VINDEX);
  3026. CLEAR_VARIANT (variant);
  3027. /* Force compatibility */
  3028. variant->VariantTypeCode = variable->VariableTypeCode;
  3029. if (variable->VariableTypeCode == StringTypeCode)
  3030. {
  3031. /* Variable is a STRING */
  3032. StringType Value;
  3033. Value.sbuffer = NULL;
  3034. Value.length = 0;
  3035. /* both STRING */
  3036. if (variable->VariableFlags & VARIABLE_VIRTUAL) /* var_get() */
  3037. {
  3038. /* get file information */
  3039. VirtualType *Z;
  3040. FileType *F;
  3041. Z = find_virtual_by_variable (variable);
  3042. if (Z == NULL)
  3043. {
  3044. WARN_INTERNAL_ERROR;
  3045. return FALSE;
  3046. }
  3047. offset *= Z->FileLength; /* Byte offset */
  3048. offset += Z->FileOffset; /* Beginning of this data */
  3049. /* update file information */
  3050. F = find_file_by_number (Z->FileNumber);
  3051. if (F == NULL)
  3052. {
  3053. WARN_BAD_FILE_MODE;
  3054. return FALSE;
  3055. }
  3056. if (F->DevMode != DEVMODE_VIRTUAL)
  3057. {
  3058. WARN_BAD_FILE_MODE;
  3059. return FALSE;
  3060. }
  3061. if (F->cfp == NULL)
  3062. {
  3063. WARN_BAD_FILE_MODE;
  3064. return FALSE;
  3065. }
  3066. if (fseek (F->cfp, offset, SEEK_SET) != 0)
  3067. {
  3068. WARN_BAD_FILE_MODE;
  3069. return FALSE;
  3070. }
  3071. Value.length = Z->FileLength;
  3072. if ((Value.sbuffer =
  3073. (char *) calloc (Value.length + 1 /* NulChar */ ,
  3074. sizeof (char))) == NULL)
  3075. {
  3076. WARN_OUT_OF_MEMORY;
  3077. return FALSE;
  3078. }
  3079. if (fread (Value.sbuffer, Value.length, 1, F->cfp) != 1)
  3080. {
  3081. WARN_DISK_IO_ERROR;
  3082. return FALSE;
  3083. }
  3084. }
  3085. else
  3086. {
  3087. StringType *string;
  3088. string = variable->Value.String;
  3089. if (string == NULL)
  3090. {
  3091. WARN_INTERNAL_ERROR;
  3092. return FALSE;
  3093. }
  3094. string += offset;
  3095. if (str_btob (&Value, string) == FALSE)
  3096. {
  3097. WARN_INTERNAL_ERROR;
  3098. return FALSE;
  3099. }
  3100. }
  3101. variant->Buffer = Value.sbuffer;
  3102. variant->Length = Value.length;
  3103. }
  3104. else
  3105. {
  3106. /* Variable is a NUMBER */
  3107. DoubleType Value;
  3108. /* both NUMBER */
  3109. if (variable->VariableFlags & VARIABLE_VIRTUAL) /* var_get() */
  3110. {
  3111. /* get file information */
  3112. VirtualType *Z;
  3113. FileType *F;
  3114. Z = find_virtual_by_variable (variable);
  3115. if (Z == NULL)
  3116. {
  3117. WARN_INTERNAL_ERROR;
  3118. return FALSE;
  3119. }
  3120. offset *= Z->FileLength; /* Byte offset */
  3121. offset += Z->FileOffset; /* Beginning of this data */
  3122. /* update file information */
  3123. F = find_file_by_number (Z->FileNumber);
  3124. if (F == NULL)
  3125. {
  3126. WARN_BAD_FILE_MODE;
  3127. return FALSE;
  3128. }
  3129. if (F->DevMode != DEVMODE_VIRTUAL)
  3130. {
  3131. WARN_BAD_FILE_MODE;
  3132. return FALSE;
  3133. }
  3134. if (F->cfp == NULL)
  3135. {
  3136. WARN_BAD_FILE_MODE;
  3137. return FALSE;
  3138. }
  3139. if (fseek (F->cfp, offset, SEEK_SET) != 0)
  3140. {
  3141. WARN_BAD_FILE_MODE;
  3142. return FALSE;
  3143. }
  3144. switch (variable->VariableTypeCode)
  3145. {
  3146. case ByteTypeCode:
  3147. {
  3148. ByteType X;
  3149. if (fread (&X, sizeof (X), 1, F->cfp) != 1)
  3150. {
  3151. WARN_DISK_IO_ERROR;
  3152. return FALSE;
  3153. }
  3154. Value = X;
  3155. }
  3156. break;
  3157. case IntegerTypeCode:
  3158. {
  3159. IntegerType X;
  3160. if (fread (&X, sizeof (X), 1, F->cfp) != 1)
  3161. {
  3162. WARN_DISK_IO_ERROR;
  3163. return FALSE;
  3164. }
  3165. Value = X;
  3166. }
  3167. break;
  3168. case LongTypeCode:
  3169. {
  3170. LongType X;
  3171. if (fread (&X, sizeof (X), 1, F->cfp) != 1)
  3172. {
  3173. WARN_DISK_IO_ERROR;
  3174. return FALSE;
  3175. }
  3176. Value = X;
  3177. }
  3178. break;
  3179. case CurrencyTypeCode:
  3180. {
  3181. CurrencyType X;
  3182. if (fread (&X, sizeof (X), 1, F->cfp) != 1)
  3183. {
  3184. WARN_DISK_IO_ERROR;
  3185. return FALSE;
  3186. }
  3187. Value = X;
  3188. }
  3189. break;
  3190. case SingleTypeCode:
  3191. {
  3192. SingleType X;
  3193. if (fread (&X, sizeof (X), 1, F->cfp) != 1)
  3194. {
  3195. WARN_DISK_IO_ERROR;
  3196. return FALSE;
  3197. }
  3198. Value = X;
  3199. }
  3200. break;
  3201. case DoubleTypeCode:
  3202. {
  3203. DoubleType X;
  3204. if (fread (&X, sizeof (X), 1, F->cfp) != 1)
  3205. {
  3206. WARN_DISK_IO_ERROR;
  3207. return FALSE;
  3208. }
  3209. Value = X;
  3210. }
  3211. break;
  3212. case StringTypeCode:
  3213. {
  3214. WARN_INTERNAL_ERROR;
  3215. return FALSE;
  3216. }
  3217. /* break; */
  3218. default:
  3219. {
  3220. WARN_INTERNAL_ERROR;
  3221. return FALSE;
  3222. }
  3223. }
  3224. }
  3225. else
  3226. {
  3227. DoubleType *number;
  3228. number = variable->Value.Number;
  3229. if (number == NULL)
  3230. {
  3231. WARN_INTERNAL_ERROR;
  3232. return FALSE;
  3233. }
  3234. number += offset;
  3235. /* copy value */
  3236. Value = *number;
  3237. }
  3238. /* VerifyNumeric */
  3239. if (isnan (Value))
  3240. {
  3241. /*** FATAL - INTERNAL ERROR - SHOULD NEVER HAPPEN ***/
  3242. WARN_INTERNAL_ERROR;
  3243. return FALSE;
  3244. }
  3245. if (isinf (Value))
  3246. {
  3247. /* - Evaluation of an expression results in an overflow
  3248. * (nonfatal, the recommended recovery procedure is to supply
  3249. * machine in- finity with the algebraically correct sign and
  3250. * continue). */
  3251. if (Value < 0)
  3252. {
  3253. Value = MINDBL;
  3254. }
  3255. else
  3256. {
  3257. Value = MAXDBL;
  3258. }
  3259. if (WARN_OVERFLOW)
  3260. {
  3261. /* ERROR */
  3262. return FALSE;
  3263. }
  3264. /* CONTINUE */
  3265. }
  3266. /* OK */
  3267. switch (variable->VariableTypeCode)
  3268. {
  3269. case ByteTypeCode:
  3270. case IntegerTypeCode:
  3271. case LongTypeCode:
  3272. case CurrencyTypeCode:
  3273. /* integer values */
  3274. Value = bwb_rint (Value);
  3275. break;
  3276. case SingleTypeCode:
  3277. case DoubleTypeCode:
  3278. /* float values */
  3279. break;
  3280. default:
  3281. /* ERROR */
  3282. WARN_INTERNAL_ERROR;
  3283. return FALSE;
  3284. /* break; */
  3285. }
  3286. variant->Number = Value;
  3287. }
  3288. return TRUE;
  3289. }
  3290. int
  3291. var_set (VariableType * variable, VariantType * variant)
  3292. {
  3293. size_t offset;
  3294. assert( My != NULL );
  3295. assert( My->SYSOUT != NULL );
  3296. assert( My->SYSOUT->cfp != NULL );
  3297. /* check sanity */
  3298. if (variable == NULL)
  3299. {
  3300. WARN_INTERNAL_ERROR;
  3301. return FALSE;
  3302. }
  3303. if (variant == NULL)
  3304. {
  3305. WARN_INTERNAL_ERROR;
  3306. return FALSE;
  3307. }
  3308. /* check CONST */
  3309. if (variable->VariableFlags & (VARIABLE_CONSTANT))
  3310. {
  3311. /* attempting to assign to a constant */
  3312. WARN_VARIABLE_NOT_DECLARED;
  3313. return FALSE;
  3314. }
  3315. /* Check subscripts */
  3316. if (dim_check (variable) == FALSE)
  3317. {
  3318. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3319. return FALSE;
  3320. }
  3321. /* Determine offset from array base ( for scalars the offset is always zero ) */
  3322. offset = dim_unit (variable, variable->VINDEX);
  3323. /* Verify compatibility */
  3324. if (variable->VariableTypeCode == StringTypeCode)
  3325. {
  3326. /* Variable is a STRING */
  3327. StringType Value;
  3328. /* Verify value is a STRING */
  3329. if (variant->VariantTypeCode != StringTypeCode)
  3330. {
  3331. WARN_TYPE_MISMATCH;
  3332. return FALSE;
  3333. }
  3334. Value.sbuffer = variant->Buffer;
  3335. Value.length = variant->Length;
  3336. /* both STRING */
  3337. if (variable->VariableFlags & VARIABLE_VIRTUAL) /* var_set() */
  3338. {
  3339. /* get file information */
  3340. VirtualType *Z;
  3341. FileType *F;
  3342. int count;
  3343. Z = find_virtual_by_variable (variable);
  3344. if (Z == NULL)
  3345. {
  3346. WARN_INTERNAL_ERROR;
  3347. return FALSE;
  3348. }
  3349. offset *= Z->FileLength; /* Byte offset */
  3350. offset += Z->FileOffset; /* Beginning of this data */
  3351. /* update file information */
  3352. F = find_file_by_number (Z->FileNumber);
  3353. if (F == NULL)
  3354. {
  3355. WARN_BAD_FILE_MODE;
  3356. return FALSE;
  3357. }
  3358. if (F->DevMode != DEVMODE_VIRTUAL)
  3359. {
  3360. WARN_BAD_FILE_MODE;
  3361. return FALSE;
  3362. }
  3363. if (F->cfp == NULL)
  3364. {
  3365. WARN_BAD_FILE_MODE;
  3366. return FALSE;
  3367. }
  3368. if (fseek (F->cfp, offset, SEEK_SET) != 0)
  3369. {
  3370. WARN_BAD_FILE_MODE;
  3371. return FALSE;
  3372. }
  3373. count = MIN (Value.length, Z->FileLength);
  3374. if (fwrite (Value.sbuffer, sizeof (char), count, F->cfp) != count)
  3375. {
  3376. WARN_DISK_IO_ERROR;
  3377. return FALSE;
  3378. }
  3379. /* PADR */
  3380. while (count < Z->FileLength)
  3381. {
  3382. if (fputc (' ', F->cfp) == EOF)
  3383. {
  3384. WARN_BAD_FILE_MODE;
  3385. return FALSE;
  3386. }
  3387. count++;
  3388. }
  3389. }
  3390. else
  3391. {
  3392. StringType *string;
  3393. string = variable->Value.String;
  3394. if (string == NULL)
  3395. {
  3396. WARN_INTERNAL_ERROR;
  3397. return FALSE;
  3398. }
  3399. string += offset;
  3400. if (str_btob (string, &Value) == FALSE)
  3401. {
  3402. WARN_INTERNAL_ERROR;
  3403. return FALSE;
  3404. }
  3405. }
  3406. if (variable->VariableFlags & VARIABLE_DISPLAY) /* var_set() */
  3407. {
  3408. if (My->ThisLine) /* var_set() */
  3409. {
  3410. if (My->ThisLine->LineFlags & (LINE_USER)) /* var_set() */
  3411. {
  3412. /* immediate mode */
  3413. }
  3414. else
  3415. {
  3416. fprintf (My->SYSOUT->cfp, "#%d %s=%s\n", My->ThisLine->number, variable->name, variant->Buffer); /* var_set() */
  3417. ResetConsoleColumn ();
  3418. }
  3419. }
  3420. }
  3421. }
  3422. else
  3423. {
  3424. /* Variable is a NUMBER */
  3425. DoubleType Value;
  3426. /* Verify value is a NUMBER */
  3427. if (variant->VariantTypeCode == StringTypeCode)
  3428. {
  3429. WARN_TYPE_MISMATCH;
  3430. return FALSE;
  3431. }
  3432. /* both NUMBER */
  3433. /* VerifyNumeric */
  3434. if (isnan (variant->Number))
  3435. {
  3436. /*** FATAL - INTERNAL ERROR - SHOULD NEVER HAPPEN ***/
  3437. WARN_INTERNAL_ERROR;
  3438. return FALSE;
  3439. }
  3440. if (isinf (variant->Number))
  3441. {
  3442. /* - Evaluation of an expression results in an overflow
  3443. * (nonfatal, the recommended recovery procedure is to supply
  3444. * machine in- finity with the algebraically correct sign and
  3445. * continue). */
  3446. if (variant->Number < 0)
  3447. {
  3448. variant->Number = MINDBL;
  3449. }
  3450. else
  3451. {
  3452. variant->Number = MAXDBL;
  3453. }
  3454. if (WARN_OVERFLOW)
  3455. {
  3456. /* ERROR */
  3457. return FALSE;
  3458. }
  3459. /* CONTINUE */
  3460. }
  3461. /* OK */
  3462. switch (variable->VariableTypeCode)
  3463. {
  3464. case ByteTypeCode:
  3465. variant->Number = bwb_rint (variant->Number);
  3466. if (variant->Number < MINBYT)
  3467. {
  3468. if (WARN_OVERFLOW)
  3469. {
  3470. return FALSE;
  3471. }
  3472. variant->Number = MINBYT;
  3473. }
  3474. else if (variant->Number > MAXBYT)
  3475. {
  3476. if (WARN_OVERFLOW)
  3477. {
  3478. return FALSE;
  3479. }
  3480. variant->Number = MAXBYT;
  3481. }
  3482. break;
  3483. case IntegerTypeCode:
  3484. variant->Number = bwb_rint (variant->Number);
  3485. if (variant->Number < MININT)
  3486. {
  3487. if (WARN_OVERFLOW)
  3488. {
  3489. return FALSE;
  3490. }
  3491. variant->Number = MININT;
  3492. }
  3493. else if (variant->Number > MAXINT)
  3494. {
  3495. if (WARN_OVERFLOW)
  3496. {
  3497. return FALSE;
  3498. }
  3499. variant->Number = MAXINT;
  3500. }
  3501. break;
  3502. case LongTypeCode:
  3503. variant->Number = bwb_rint (variant->Number);
  3504. if (variant->Number < MINLNG)
  3505. {
  3506. if (WARN_OVERFLOW)
  3507. {
  3508. return FALSE;
  3509. }
  3510. variant->Number = MINLNG;
  3511. }
  3512. else if (variant->Number > MAXLNG)
  3513. {
  3514. if (WARN_OVERFLOW)
  3515. {
  3516. return FALSE;
  3517. }
  3518. variant->Number = MAXLNG;
  3519. }
  3520. break;
  3521. case CurrencyTypeCode:
  3522. variant->Number = bwb_rint (variant->Number);
  3523. if (variant->Number < MINCUR)
  3524. {
  3525. if (WARN_OVERFLOW)
  3526. {
  3527. return FALSE;
  3528. }
  3529. variant->Number = MINCUR;
  3530. }
  3531. else if (variant->Number > MAXCUR)
  3532. {
  3533. if (WARN_OVERFLOW)
  3534. {
  3535. return FALSE;
  3536. }
  3537. variant->Number = MAXCUR;
  3538. }
  3539. break;
  3540. case SingleTypeCode:
  3541. if (variant->Number < MINSNG)
  3542. {
  3543. if (WARN_OVERFLOW)
  3544. {
  3545. return FALSE;
  3546. }
  3547. variant->Number = MINSNG;
  3548. }
  3549. else if (variant->Number > MAXSNG)
  3550. {
  3551. if (WARN_OVERFLOW)
  3552. {
  3553. return FALSE;
  3554. }
  3555. variant->Number = MAXSNG;
  3556. }
  3557. break;
  3558. case DoubleTypeCode:
  3559. if (variant->Number < MINDBL)
  3560. {
  3561. if (WARN_OVERFLOW)
  3562. {
  3563. return FALSE;
  3564. }
  3565. variant->Number = MINDBL;
  3566. }
  3567. else if (variant->Number > MAXDBL)
  3568. {
  3569. if (WARN_OVERFLOW)
  3570. {
  3571. return FALSE;
  3572. }
  3573. variant->Number = MAXDBL;
  3574. }
  3575. break;
  3576. default:
  3577. WARN_INTERNAL_ERROR;
  3578. return FALSE;
  3579. /* break; */
  3580. }
  3581. Value = variant->Number;
  3582. if (variable->VariableFlags & VARIABLE_VIRTUAL) /* var_set() */
  3583. {
  3584. /* get file information */
  3585. VirtualType *Z;
  3586. FileType *F;
  3587. Z = find_virtual_by_variable (variable);
  3588. if (Z == NULL)
  3589. {
  3590. WARN_INTERNAL_ERROR;
  3591. return FALSE;
  3592. }
  3593. offset *= Z->FileLength; /* Byte offset */
  3594. offset += Z->FileOffset; /* Beginning of this data */
  3595. /* update file information */
  3596. F = find_file_by_number (Z->FileNumber);
  3597. if (F == NULL)
  3598. {
  3599. WARN_BAD_FILE_MODE;
  3600. return FALSE;
  3601. }
  3602. if (F->DevMode != DEVMODE_VIRTUAL)
  3603. {
  3604. WARN_BAD_FILE_MODE;
  3605. return FALSE;
  3606. }
  3607. if (F->cfp == NULL)
  3608. {
  3609. WARN_BAD_FILE_MODE;
  3610. return FALSE;
  3611. }
  3612. if (fseek (F->cfp, offset, SEEK_SET) != 0)
  3613. {
  3614. WARN_BAD_FILE_MODE;
  3615. return FALSE;
  3616. }
  3617. switch (variable->VariableTypeCode)
  3618. {
  3619. case ByteTypeCode:
  3620. {
  3621. ByteType X;
  3622. X = Value;
  3623. if (fwrite (&X, sizeof (X), 1, F->cfp) != 1)
  3624. {
  3625. WARN_DISK_IO_ERROR;
  3626. return FALSE;
  3627. }
  3628. }
  3629. break;
  3630. case IntegerTypeCode:
  3631. {
  3632. IntegerType X;
  3633. X = Value;
  3634. if (fwrite (&X, sizeof (X), 1, F->cfp) != 1)
  3635. {
  3636. WARN_DISK_IO_ERROR;
  3637. return FALSE;
  3638. }
  3639. }
  3640. break;
  3641. case LongTypeCode:
  3642. {
  3643. LongType X;
  3644. X = Value;
  3645. if (fwrite (&X, sizeof (X), 1, F->cfp) != 1)
  3646. {
  3647. WARN_DISK_IO_ERROR;
  3648. return FALSE;
  3649. }
  3650. }
  3651. break;
  3652. case CurrencyTypeCode:
  3653. {
  3654. CurrencyType X;
  3655. X = Value;
  3656. if (fwrite (&X, sizeof (X), 1, F->cfp) != 1)
  3657. {
  3658. WARN_DISK_IO_ERROR;
  3659. return FALSE;
  3660. }
  3661. }
  3662. break;
  3663. case SingleTypeCode:
  3664. {
  3665. SingleType X;
  3666. X = Value;
  3667. if (fwrite (&X, sizeof (X), 1, F->cfp) != 1)
  3668. {
  3669. WARN_DISK_IO_ERROR;
  3670. return FALSE;
  3671. }
  3672. }
  3673. break;
  3674. case DoubleTypeCode:
  3675. {
  3676. DoubleType X;
  3677. X = Value;
  3678. if (fwrite (&X, sizeof (X), 1, F->cfp) != 1)
  3679. {
  3680. WARN_DISK_IO_ERROR;
  3681. return FALSE;
  3682. }
  3683. }
  3684. break;
  3685. case StringTypeCode:
  3686. {
  3687. WARN_INTERNAL_ERROR;
  3688. return FALSE;
  3689. }
  3690. /* break; */
  3691. default:
  3692. {
  3693. WARN_INTERNAL_ERROR;
  3694. return FALSE;
  3695. }
  3696. }
  3697. }
  3698. else
  3699. {
  3700. DoubleType *number;
  3701. number = variable->Value.Number;
  3702. if (number == NULL)
  3703. {
  3704. WARN_INTERNAL_ERROR;
  3705. return FALSE;
  3706. }
  3707. number += offset;
  3708. *number = Value;
  3709. }
  3710. if (variable->VariableFlags & VARIABLE_DISPLAY) /* var_set() */
  3711. {
  3712. if (My->ThisLine) /* var_set() */
  3713. {
  3714. if (My->ThisLine->LineFlags & (LINE_USER)) /* var_set() */
  3715. {
  3716. /* immediate mode */
  3717. }
  3718. else
  3719. {
  3720. FormatBasicNumber (Value, My->NumLenBuffer);
  3721. fprintf (My->SYSOUT->cfp, "#%d %s=%s\n", My->ThisLine->number, variable->name, My->NumLenBuffer); /* var_set() */
  3722. ResetConsoleColumn ();
  3723. }
  3724. }
  3725. }
  3726. }
  3727. return TRUE;
  3728. }
  3729. /***************************************************************
  3730. FUNCTION: dim_check()
  3731. DESCRIPTION: This function checks subscripts of a
  3732. specific variable to be sure that they
  3733. are within the correct range.
  3734. ***************************************************************/
  3735. static int
  3736. dim_check (VariableType * variable)
  3737. {
  3738. /* Check for validly allocated array */
  3739. int n;
  3740. assert (variable != NULL);
  3741. if (variable->VariableFlags & VARIABLE_VIRTUAL) /* var_set() */
  3742. {
  3743. if (variable->Value.String != NULL)
  3744. {
  3745. WARN_INTERNAL_ERROR;
  3746. return FALSE;
  3747. }
  3748. if (variable->Value.Number != NULL)
  3749. {
  3750. WARN_INTERNAL_ERROR;
  3751. return FALSE;
  3752. }
  3753. }
  3754. else if (VAR_IS_STRING (variable))
  3755. {
  3756. if (variable->Value.String == NULL)
  3757. {
  3758. WARN_INTERNAL_ERROR;
  3759. return FALSE;
  3760. }
  3761. }
  3762. else
  3763. {
  3764. if (variable->Value.Number == NULL)
  3765. {
  3766. WARN_INTERNAL_ERROR;
  3767. return FALSE;
  3768. }
  3769. }
  3770. /* Now check subscript values */
  3771. for (n = 0; n < variable->dimensions; n++)
  3772. {
  3773. if (variable->VINDEX[n] < variable->LBOUND[n]
  3774. || variable->VINDEX[n] > variable->UBOUND[n])
  3775. {
  3776. WARN_SUBSCRIPT_OUT_OF_RANGE;
  3777. return FALSE;
  3778. }
  3779. }
  3780. /* No problems found */
  3781. return TRUE;
  3782. }
  3783. /***************************************************************
  3784. FUNCTION: var_make()
  3785. DESCRIPTION: This function initializes a variable,
  3786. allocating necessary memory for it.
  3787. ***************************************************************/
  3788. int
  3789. var_make (VariableType * variable, char TypeCode)
  3790. {
  3791. /* ALL variables are created here */
  3792. assert (variable != NULL);
  3793. switch (TypeCode)
  3794. {
  3795. case ByteTypeCode:
  3796. case IntegerTypeCode:
  3797. case LongTypeCode:
  3798. case CurrencyTypeCode:
  3799. case SingleTypeCode:
  3800. case DoubleTypeCode:
  3801. case StringTypeCode:
  3802. /* OK */
  3803. break;
  3804. default:
  3805. /* ERROR */
  3806. WARN_TYPE_MISMATCH;
  3807. return FALSE;
  3808. }
  3809. variable->VariableTypeCode = TypeCode;
  3810. /* get memory for array */
  3811. /* First cleanup the joint (JBV) */
  3812. if (variable->Value.Number != NULL)
  3813. {
  3814. free (variable->Value.Number);
  3815. variable->Value.Number = NULL;
  3816. }
  3817. if (variable->Value.String != NULL)
  3818. {
  3819. /* Remember to deallocate those far-flung branches! (JBV) */
  3820. StringType *sp; /* JBV */
  3821. int n; /* JBV */
  3822. sp = variable->Value.String;
  3823. for (n = 0; n < (int) variable->array_units; n++)
  3824. {
  3825. if (sp[n].sbuffer != NULL)
  3826. {
  3827. free (sp[n].sbuffer);
  3828. sp[n].sbuffer = NULL;
  3829. }
  3830. sp[n].length = 0;
  3831. }
  3832. free (variable->Value.String);
  3833. variable->Value.String = NULL;
  3834. }
  3835. variable->dimensions = 0;
  3836. variable->array_units = 1;
  3837. if (VAR_IS_STRING (variable))
  3838. {
  3839. if ((variable->Value.String =
  3840. calloc (variable->array_units, sizeof (StringType))) == NULL)
  3841. {
  3842. WARN_OUT_OF_MEMORY;
  3843. return FALSE;
  3844. }
  3845. }
  3846. else
  3847. {
  3848. if ((variable->Value.Number =
  3849. calloc (variable->array_units, sizeof (DoubleType))) == NULL)
  3850. {
  3851. WARN_OUT_OF_MEMORY;
  3852. return FALSE;
  3853. }
  3854. }
  3855. return TRUE;
  3856. }
  3857. /***************************************************************
  3858. FUNCTION: var_islocal()
  3859. DESCRIPTION: This function determines whether the string
  3860. pointed to by 'buffer' has the name of
  3861. a local variable at the present EXEC stack
  3862. level.
  3863. ***************************************************************/
  3864. static VariableType *
  3865. mat_islocal (char *buffer)
  3866. {
  3867. /*
  3868. similar to var_islocal, but returns first matrix found.
  3869. */
  3870. assert (buffer != NULL);
  3871. assert( My != NULL );
  3872. if (My->StackHead != NULL)
  3873. {
  3874. StackType *StackItem;
  3875. for (StackItem = My->StackHead; StackItem != NULL;
  3876. StackItem = StackItem->next)
  3877. {
  3878. if (StackItem->LoopTopLine != NULL)
  3879. {
  3880. switch (StackItem->LoopTopLine->cmdnum)
  3881. {
  3882. case C_DEF:
  3883. case C_FUNCTION:
  3884. case C_SUB:
  3885. /* we have found a FUNCTION or SUB boundary */
  3886. {
  3887. VariableType *variable;
  3888. for (variable = StackItem->local_variable; variable != NULL;
  3889. variable = variable->next)
  3890. {
  3891. if (variable->dimensions > 0)
  3892. {
  3893. if (bwb_stricmp (variable->name, buffer) == 0)
  3894. {
  3895. /* FOUND */
  3896. return variable;
  3897. }
  3898. }
  3899. }
  3900. }
  3901. /* we have checked all the way to a FUNCTION or SUB boundary */
  3902. /* NOT FOUND */
  3903. return NULL;
  3904. /* break; */
  3905. }
  3906. }
  3907. }
  3908. }
  3909. /* NOT FOUND */
  3910. return NULL;
  3911. }
  3912. static VariableType *
  3913. var_islocal (char *buffer, int dimensions)
  3914. {
  3915. assert (buffer != NULL);
  3916. assert( My != NULL );
  3917. if (My->StackHead != NULL)
  3918. {
  3919. StackType *StackItem;
  3920. for (StackItem = My->StackHead; StackItem != NULL;
  3921. StackItem = StackItem->next)
  3922. {
  3923. if (StackItem->LoopTopLine != NULL)
  3924. {
  3925. switch (StackItem->LoopTopLine->cmdnum)
  3926. {
  3927. case C_DEF:
  3928. case C_FUNCTION:
  3929. case C_SUB:
  3930. /* we have found a FUNCTION or SUB boundary */
  3931. {
  3932. VariableType *variable;
  3933. for (variable = StackItem->local_variable; variable != NULL;
  3934. variable = variable->next)
  3935. {
  3936. if (variable->dimensions == dimensions)
  3937. {
  3938. if (bwb_stricmp (variable->name, buffer) == 0)
  3939. {
  3940. /* FOUND */
  3941. return variable;
  3942. }
  3943. }
  3944. }
  3945. }
  3946. /* we have checked all the way to a FUNCTION or SUB boundary */
  3947. /* NOT FOUND */
  3948. return NULL;
  3949. /* break; */
  3950. }
  3951. }
  3952. }
  3953. }
  3954. /* NOT FOUND */
  3955. return NULL;
  3956. }
  3957. /***************************************************************
  3958. FUNCTION: bwb_vars()
  3959. DESCRIPTION: This function implements the Bywater-
  3960. specific debugging command VARS, which
  3961. gives a list of all variables defined
  3962. in memory.
  3963. ***************************************************************/
  3964. LineType *
  3965. bwb_VARS (LineType * l)
  3966. {
  3967. VariableType *variable;
  3968. assert (l != NULL);
  3969. assert( My != NULL );
  3970. assert( My->SYSOUT != NULL );
  3971. assert( My->SYSOUT->cfp != NULL );
  3972. /* run through the variable list and print variables */
  3973. fprintf (My->SYSOUT->cfp, "%-*s %-6s %-4s %s\n", NameLengthMax, "Name",
  3974. "Type", "Dims", "Value");
  3975. for (variable = My->VariableHead; variable != NULL;
  3976. variable = variable->next)
  3977. {
  3978. VariantType variant;
  3979. CLEAR_VARIANT (&variant);
  3980. if (var_get (variable, &variant) == FALSE)
  3981. {
  3982. WARN_VARIABLE_NOT_DECLARED;
  3983. return (l);
  3984. }
  3985. if (variant.VariantTypeCode == StringTypeCode)
  3986. {
  3987. fprintf (My->SYSOUT->cfp, "%-*s %-6s %-4d %s\n", NameLengthMax,
  3988. variable->name, "STRING", variable->dimensions,
  3989. variant.Buffer);
  3990. }
  3991. else
  3992. {
  3993. FormatBasicNumber (variant.Number, My->NumLenBuffer);
  3994. fprintf (My->SYSOUT->cfp, "%-*s %-6s %-4d %s\n", NameLengthMax,
  3995. variable->name, "NUMBER", variable->dimensions,
  3996. My->NumLenBuffer);
  3997. }
  3998. RELEASE_VARIANT (&variant);
  3999. }
  4000. ResetConsoleColumn ();
  4001. return (l);
  4002. }
  4003. /***************************************************************
  4004. FUNCTION: bwb_field()
  4005. DESCRIPTION: This C function implements the BASIC
  4006. FIELD command.
  4007. ***************************************************************/
  4008. static void
  4009. field_clear (FieldType * Field)
  4010. {
  4011. int i;
  4012. assert (Field != NULL);
  4013. Field->File = NULL;
  4014. Field->FieldOffset = 0;
  4015. Field->FieldLength = 0;
  4016. Field->Var = NULL;
  4017. for (i = 0; i < MAX_DIMS; i++)
  4018. {
  4019. Field->VINDEX[i] = 0;
  4020. }
  4021. }
  4022. static FieldType *
  4023. field_new (void)
  4024. {
  4025. /* search for an empty slot */
  4026. FieldType *Field;
  4027. assert( My != NULL );
  4028. for (Field = My->FieldHead; Field != NULL; Field = Field->next)
  4029. {
  4030. if (Field->File == NULL || Field->Var == NULL)
  4031. {
  4032. field_clear (Field);
  4033. return Field;
  4034. }
  4035. }
  4036. /* not found */
  4037. if ((Field = calloc (1, sizeof (FieldType))) == NULL)
  4038. {
  4039. WARN_OUT_OF_MEMORY;
  4040. return NULL;
  4041. }
  4042. Field->next = My->FieldHead;
  4043. My->FieldHead = Field;
  4044. return Field;
  4045. }
  4046. void
  4047. field_close_file (FileType * File)
  4048. {
  4049. /* a CLOSE of a file is in progress, release associated fields */
  4050. FieldType *Field;
  4051. assert (File != NULL);
  4052. assert( My != NULL );
  4053. for (Field = My->FieldHead; Field != NULL; Field = Field->next)
  4054. {
  4055. if (Field->File == File)
  4056. {
  4057. Field->File = NULL;
  4058. Field->Var = NULL;
  4059. }
  4060. }
  4061. }
  4062. void
  4063. field_free_variable (VariableType * Var)
  4064. {
  4065. /* an ERASE of a variable is in progress, release associated fields */
  4066. FieldType *Field;
  4067. assert (Var != NULL);
  4068. assert( My != NULL );
  4069. for (Field = My->FieldHead; Field != NULL; Field = Field->next)
  4070. {
  4071. if (Field->Var == Var)
  4072. {
  4073. Field->File = NULL;
  4074. Field->Var = NULL;
  4075. }
  4076. }
  4077. }
  4078. void
  4079. field_get (FileType * File)
  4080. {
  4081. /* a GET of the RANDOM file is in progress, update variables from FILE buffer */
  4082. FieldType *Field;
  4083. assert( My != NULL );
  4084. if (File == NULL)
  4085. {
  4086. WARN_BAD_FILE_NUMBER;
  4087. return;
  4088. }
  4089. if (File->buffer == NULL)
  4090. {
  4091. WARN_BAD_FILE_MODE;
  4092. return;
  4093. }
  4094. for (Field = My->FieldHead; Field != NULL; Field = Field->next)
  4095. {
  4096. if (Field->File == File && Field->Var != NULL)
  4097. {
  4098. /* from file to variable */
  4099. VariantType variant;
  4100. CLEAR_VARIANT (&variant);
  4101. if (Field->FieldOffset < 0)
  4102. {
  4103. WARN_FIELD_OVERFLOW;
  4104. return;
  4105. }
  4106. if (Field->FieldLength <= 0)
  4107. {
  4108. WARN_FIELD_OVERFLOW;
  4109. return;
  4110. }
  4111. if ((Field->FieldOffset + Field->FieldLength) > File->width)
  4112. {
  4113. WARN_FIELD_OVERFLOW;
  4114. return;
  4115. }
  4116. variant.VariantTypeCode = StringTypeCode;
  4117. variant.Length = Field->FieldLength;
  4118. if ((variant.Buffer =
  4119. (char *) calloc (variant.Length + 1 /* NulChar */ ,
  4120. sizeof (char))) == NULL)
  4121. {
  4122. WARN_OUT_OF_MEMORY;
  4123. return;
  4124. }
  4125. /* if( TRUE ) */
  4126. {
  4127. int i;
  4128. for (i = 0; i < Field->Var->dimensions; i++)
  4129. {
  4130. Field->Var->VINDEX[i] = Field->VINDEX[i];
  4131. }
  4132. }
  4133. /* if( TRUE ) */
  4134. {
  4135. int i;
  4136. char *Buffer;
  4137. Buffer = File->buffer;
  4138. Buffer += Field->FieldOffset;
  4139. for (i = 0; i < variant.Length; i++)
  4140. {
  4141. variant.Buffer[i] = Buffer[i];
  4142. }
  4143. variant.Buffer[variant.Length] = NulChar;
  4144. }
  4145. if (var_set (Field->Var, &variant) == FALSE)
  4146. {
  4147. WARN_VARIABLE_NOT_DECLARED;
  4148. return;
  4149. }
  4150. RELEASE_VARIANT (&variant);
  4151. }
  4152. }
  4153. }
  4154. void
  4155. field_put (FileType * File)
  4156. {
  4157. /* a PUT of the RANDOM file is in progress, update FILE buffer from variables */
  4158. FieldType *Field;
  4159. assert( My != NULL );
  4160. if (File == NULL)
  4161. {
  4162. WARN_BAD_FILE_NUMBER;
  4163. return;
  4164. }
  4165. if (File->buffer == NULL)
  4166. {
  4167. WARN_BAD_FILE_MODE;
  4168. return;
  4169. }
  4170. for (Field = My->FieldHead; Field != NULL; Field = Field->next)
  4171. {
  4172. if (Field->File == File && Field->Var != NULL)
  4173. {
  4174. /* from variable to file */
  4175. VariantType variant;
  4176. CLEAR_VARIANT (&variant);
  4177. if (Field->FieldOffset < 0)
  4178. {
  4179. WARN_FIELD_OVERFLOW;
  4180. return;
  4181. }
  4182. if (Field->FieldLength <= 0)
  4183. {
  4184. WARN_FIELD_OVERFLOW;
  4185. return;
  4186. }
  4187. if ((Field->FieldOffset + Field->FieldLength) > File->width)
  4188. {
  4189. WARN_FIELD_OVERFLOW;
  4190. return;
  4191. }
  4192. /* if( TRUE ) */
  4193. {
  4194. int i;
  4195. for (i = 0; i < Field->Var->dimensions; i++)
  4196. {
  4197. Field->Var->VINDEX[i] = Field->VINDEX[i];
  4198. }
  4199. }
  4200. if (var_get (Field->Var, &variant) == FALSE)
  4201. {
  4202. WARN_VARIABLE_NOT_DECLARED;
  4203. return;
  4204. }
  4205. if (variant.VariantTypeCode != StringTypeCode)
  4206. {
  4207. WARN_TYPE_MISMATCH;
  4208. return;
  4209. }
  4210. /* if( TRUE ) */
  4211. {
  4212. int i;
  4213. int n;
  4214. char *Buffer;
  4215. i = 0;
  4216. n = 0;
  4217. Buffer = File->buffer;
  4218. Buffer += Field->FieldOffset;
  4219. if (variant.Buffer != NULL)
  4220. {
  4221. n = MIN (variant.Length, Field->FieldLength);
  4222. }
  4223. for (i = 0; i < n; i++)
  4224. {
  4225. Buffer[i] = variant.Buffer[i];
  4226. }
  4227. for (i = n; i < Field->FieldLength; i++)
  4228. {
  4229. /* Pad on the right with spaces */
  4230. Buffer[i] = ' ';
  4231. }
  4232. }
  4233. RELEASE_VARIANT (&variant);
  4234. }
  4235. }
  4236. }
  4237. LineType *
  4238. bwb_FIELD (LineType * l)
  4239. {
  4240. FileType *File;
  4241. int FileNumber;
  4242. int FieldOffset;
  4243. assert (l != NULL);
  4244. FileNumber = 0;
  4245. FieldOffset = 0;
  4246. /* first read device number */
  4247. if (line_skip_FilenumChar (l))
  4248. {
  4249. /* optional */
  4250. }
  4251. if (line_read_integer_expression (l, &FileNumber) == FALSE)
  4252. {
  4253. WARN_SYNTAX_ERROR;
  4254. return (l);
  4255. }
  4256. if (FileNumber <= 0)
  4257. {
  4258. /* FIELD # 0 is an error */
  4259. WARN_BAD_FILE_NUMBER;
  4260. return (l);
  4261. }
  4262. File = find_file_by_number (FileNumber);
  4263. if (File == NULL)
  4264. {
  4265. WARN_BAD_FILE_NUMBER;
  4266. return (l);
  4267. }
  4268. if (File->DevMode != DEVMODE_RANDOM)
  4269. {
  4270. WARN_BAD_FILE_MODE;
  4271. return (l);
  4272. }
  4273. /* loop to read variables */
  4274. /* read the comma and advance beyond it */
  4275. while (line_skip_seperator (l))
  4276. {
  4277. int FieldLength;
  4278. VariableType *variable;
  4279. VariantType variant;
  4280. CLEAR_VARIANT (&variant);
  4281. /* first find the size of the field */
  4282. FieldLength = 0;
  4283. if (line_read_integer_expression (l, &FieldLength) == FALSE)
  4284. {
  4285. WARN_SYNTAX_ERROR;
  4286. return (l);
  4287. }
  4288. if (FieldLength <= 0)
  4289. {
  4290. WARN_SYNTAX_ERROR;
  4291. return (l);
  4292. }
  4293. /* read the AS */
  4294. if (line_skip_word (l, "AS") == FALSE)
  4295. {
  4296. WARN_SYNTAX_ERROR;
  4297. return (l);
  4298. }
  4299. /* read the string variable name */
  4300. if ((variable = line_read_scalar (l)) == NULL)
  4301. {
  4302. WARN_VARIABLE_NOT_DECLARED;
  4303. return (l);
  4304. }
  4305. if (VAR_IS_STRING (variable))
  4306. {
  4307. /* OK */
  4308. }
  4309. else
  4310. {
  4311. WARN_TYPE_MISMATCH;
  4312. return (l);
  4313. }
  4314. /* check for overflow of record length */
  4315. if ((FieldOffset + FieldLength) > File->width)
  4316. {
  4317. WARN_FIELD_OVERFLOW;
  4318. return (l);
  4319. }
  4320. /* set buffer */
  4321. variant.VariantTypeCode = StringTypeCode;
  4322. /* if( TRUE ) */
  4323. {
  4324. FieldType *Field;
  4325. int i;
  4326. Field = field_new ();
  4327. if (Field == NULL)
  4328. {
  4329. WARN_OUT_OF_MEMORY;
  4330. return (l);
  4331. }
  4332. Field->File = File;
  4333. Field->FieldOffset = FieldOffset;
  4334. Field->FieldLength = FieldLength;
  4335. Field->Var = variable;
  4336. for (i = 0; i < variable->dimensions; i++)
  4337. {
  4338. Field->VINDEX[i] = variable->VINDEX[i];
  4339. }
  4340. variant.Length = FieldLength;
  4341. if ((variant.Buffer =
  4342. (char *) calloc (variant.Length + 1 /* NulChar */ ,
  4343. sizeof (char))) == NULL)
  4344. {
  4345. WARN_OUT_OF_MEMORY;
  4346. return (l);
  4347. }
  4348. bwb_memset (variant.Buffer, ' ', variant.Length);
  4349. variant.Buffer[variant.Length] = NulChar;
  4350. }
  4351. if (var_set (variable, &variant) == FALSE)
  4352. {
  4353. WARN_VARIABLE_NOT_DECLARED;
  4354. return (l);
  4355. }
  4356. RELEASE_VARIANT (&variant);
  4357. FieldOffset += FieldLength;
  4358. }
  4359. /* return */
  4360. return (l);
  4361. }
  4362. /***************************************************************
  4363. FUNCTION: bwb_lset()
  4364. DESCRIPTION: This C function implements the BASIC
  4365. LSET command.
  4366. SYNTAX: LSET string-variable$ = expression
  4367. ***************************************************************/
  4368. LineType *
  4369. bwb_LSET (LineType * l)
  4370. {
  4371. assert (l != NULL);
  4372. return dio_lrset (l, FALSE);
  4373. }
  4374. /***************************************************************
  4375. FUNCTION: bwb_rset()
  4376. DESCRIPTION: This C function implements the BASIC
  4377. RSET command.
  4378. SYNTAX: RSET string-variable$ = expression
  4379. ***************************************************************/
  4380. LineType *
  4381. bwb_RSET (LineType * l)
  4382. {
  4383. assert (l != NULL);
  4384. return dio_lrset (l, TRUE);
  4385. }
  4386. /***************************************************************
  4387. FUNCTION: dio_lrset()
  4388. DESCRIPTION: This C function implements the BASIC
  4389. RSET and LSET commands.
  4390. ***************************************************************/
  4391. static LineType *
  4392. dio_lrset (LineType * l, int rset)
  4393. {
  4394. /* LSET and RSET */
  4395. VariantType variant;
  4396. int n;
  4397. int i;
  4398. int startpos;
  4399. VariableType *v;
  4400. VariantType t;
  4401. VariantType *T;
  4402. assert (l != NULL);
  4403. T = &t;
  4404. CLEAR_VARIANT (T);
  4405. CLEAR_VARIANT (&variant);
  4406. /* get the variable */
  4407. if ((v = line_read_scalar (l)) == NULL)
  4408. {
  4409. WARN_VARIABLE_NOT_DECLARED;
  4410. return (l);
  4411. }
  4412. if (VAR_IS_STRING (v) == FALSE)
  4413. {
  4414. WARN_TYPE_MISMATCH;
  4415. return (l);
  4416. }
  4417. /* skip the equals sign */
  4418. if (line_skip_EqualChar (l) == FALSE)
  4419. {
  4420. WARN_SYNTAX_ERROR;
  4421. return (l);
  4422. }
  4423. /* get the value */
  4424. if (line_read_expression (l, T) == FALSE) /* dio_lrset */
  4425. {
  4426. WARN_SYNTAX_ERROR;
  4427. return (l);
  4428. }
  4429. if (T->VariantTypeCode != StringTypeCode)
  4430. {
  4431. WARN_TYPE_MISMATCH;
  4432. return (l);
  4433. }
  4434. if (var_get (v, &variant) == FALSE)
  4435. {
  4436. WARN_VARIABLE_NOT_DECLARED;
  4437. return (l);
  4438. }
  4439. /* determine starting position */
  4440. startpos = 0;
  4441. if (rset == TRUE && T->Length < variant.Length)
  4442. {
  4443. /*
  4444. LET A$ = "123_456" ' variant.Length = 7
  4445. LET B$ = "789" ' T->Length = 3
  4446. RSET A$ = B$ ' startpos = 4
  4447. PRINT "[";A$;"]" ' [123_789]
  4448. */
  4449. startpos = variant.Length - T->Length;
  4450. for(n=0; n<startpos; n++) variant.Buffer[n]=' ';
  4451. }
  4452. /* write characters to new position */
  4453. for (n = startpos, i = 0;
  4454. (n < (int) variant.Length) && (i < (int) T->Length); n++, i++)
  4455. {
  4456. variant.Buffer[n] = T->Buffer[i];
  4457. }
  4458. if(rset == FALSE) while(n<variant.Length) variant.Buffer[n++]=' ';
  4459. if (var_set (v, &variant) == FALSE)
  4460. {
  4461. WARN_VARIABLE_NOT_DECLARED;
  4462. return (l);
  4463. }
  4464. /* OK */
  4465. RELEASE_VARIANT (T);
  4466. RELEASE_VARIANT (&variant);
  4467. return (l);
  4468. }
  4469. /* EOF */