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.
 
 
 
 
 
 

4170 lines
104 KiB

  1. /****************************************************************
  2. bwb_fnc.c Interpretation Routines
  3. for Predefined Functions
  4. for Bywater BASIC Interpreter
  5. Copyright (c) 1993, Ted A. Campbell
  6. Bywater Software
  7. email: tcamp@delphi.com
  8. Copyright and Permissions Information:
  9. All U.S. and international rights are claimed by the author,
  10. Ted A. Campbell.
  11. This software is released under the terms of the GNU General
  12. Public License (GPL), which is distributed with this software
  13. in the file "COPYING". The GPL specifies the terms under
  14. which users may copy and use the software in this distribution.
  15. A separate license is available for commercial distribution,
  16. for information on which you should contact the author.
  17. ***************************************************************/
  18. /*---------------------------------------------------------------*/
  19. /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
  20. /* 11/1995 (eidetics@cerf.net). */
  21. /* */
  22. /* Those additionally marked with "DD" were at the suggestion of */
  23. /* Dale DePriest (daled@cadence.com). */
  24. /* */
  25. /* Version 3.00 by Howard Wulf, AF5NE */
  26. /* */
  27. /* Version 3.10 by Howard Wulf, AF5NE */
  28. /* */
  29. /*---------------------------------------------------------------*/
  30. #include "bwbasic.h"
  31. #ifndef RAND_MAX
  32. #define RAND_MAX 32767
  33. #endif /* RAND_MAX */
  34. #ifndef PI
  35. #define PI 3.14159265358979323846
  36. #endif /* PI */
  37. #define FromDegreesToRadians( X ) ( X * PI / 180.0 )
  38. #define FromRadiansToDegrees( X ) ( X * 180.0 / PI )
  39. #define FromGradiansToRadians( X ) ( X * PI / 200.0 )
  40. #define FromRadiansToGradians( X ) ( X * 200.0 / PI )
  41. static time_t t;
  42. static struct tm *lt;
  43. /* ORD() Table 1 */
  44. /* ACRONYM */
  45. typedef struct
  46. {
  47. const int Value;
  48. const char *Name;
  49. } Acronym;
  50. #define NUM_ACRONYMS (34)
  51. Acronym AcronymTable[NUM_ACRONYMS] =
  52. {
  53. {0, "NUL"},
  54. {1, "SOH"},
  55. {2, "STX"},
  56. {3, "ETX"},
  57. {4, "EOT"},
  58. {5, "ENQ"},
  59. {6, "ACK"},
  60. {7, "BEL"},
  61. {8, "BS"},
  62. {9, "HT"},
  63. {10, "LF"},
  64. {11, "VT"},
  65. {12, "FF"},
  66. {13, "CR"},
  67. {14, "SO"},
  68. {15, "SI"},
  69. {16, "DLE"},
  70. {17, "DC1"},
  71. {18, "DC2"},
  72. {19, "DC3"},
  73. {20, "DC4"},
  74. {21, "NAK"},
  75. {22, "SYN"},
  76. {23, "ETB"},
  77. {24, "CAN"},
  78. {25, "EM"},
  79. {26, "SUB"},
  80. {27, "ESC"},
  81. {28, "FS"},
  82. {29, "GS"},
  83. {30, "RS"},
  84. {31, "US"},
  85. {32, "SP"},
  86. {127, "DEL"}
  87. };
  88. /* ... ORD() */
  89. VariableType *
  90. fnc_intrinsic(int argc, VariableType * argv, int unique_id)
  91. {
  92. /* this is the generic handler for all intrinsic BASIC functions */
  93. /* BasicStringLengthMax must be <= INT_MAX */
  94. FunctionType *f;
  95. VariableType *argn;
  96. unsigned char IsError;/* for ERROR messages */
  97. /* Follow the BASIC naming conventions, so the code is easier to
  98. * maintain */
  99. char *S; /* S$ - STRING functions */
  100. BasicStringLengthType s;/* LEN( S$ ) */
  101. BasicNumberType N; /* N - NUMBER functions */
  102. char *A; /* A$ - 1st STRING parameter */
  103. BasicStringLengthType a;/* LEN( A$ ) */
  104. char *B; /* B$ - 2nd STRING parameter */
  105. BasicStringLengthType b;/* LEN( B$ ) */
  106. #if FALSE /* keep third parameter */
  107. char *C; /* C$ - 3rd STRING parameter */
  108. BasicStringLengthType c;/* LEN( C$ ) */
  109. #endif
  110. BasicNumberType X; /* X - 1st NUMBER parameter */
  111. BasicIntegerType x; /* INT( X ) */
  112. BasicNumberType Y; /* Y - 2nd NUMBER parameter */
  113. BasicIntegerType y; /* INT( Y ) */
  114. #if FALSE /* keep third parameter */
  115. BasicNumberType Z; /* Z - 3rd NUMBER parameter */
  116. BasicIntegerType z; /* INT( Z ) */
  117. #endif
  118. bwx_DEBUG(__FUNCTION__);
  119. /* so the following code is easier to read and maintain */
  120. #define PARAM_NUMBER *argn->memnum
  121. #define PARAM_LENGTH argn->memstr->length
  122. #define PARAM_BUFFER argn->memstr->sbuffer
  123. #define RESULT_NUMBER *argv->memnum
  124. #define RESULT_BUFFER argv->memstr->sbuffer
  125. #define RESULT_LENGTH argv->memstr->length
  126. /* no errors have occurred (yet) */
  127. IsError = 0;
  128. /* look up the intrinsic function, so we can get the details */
  129. {
  130. f = fnc_find_by_id(unique_id);
  131. if (f == NULL)
  132. {
  133. /* bwb_prefuncs[] in bwb_tbl.c is wrong -- this is really bad */
  134. WARN_INTERNAL_ERROR;
  135. return NULL;
  136. }
  137. }
  138. /* the RETURN variable is the first variable in the 'argv' vaariable chain */
  139. if (argv == NULL)
  140. {
  141. WARN_INTERNAL_ERROR;
  142. return NULL;
  143. }
  144. if ( VAR_IS_STRING( argv ) )
  145. {
  146. if (argv->memstr == NULL)
  147. {
  148. WARN_INTERNAL_ERROR;
  149. return NULL;
  150. }
  151. RESULT_LENGTH = 0;
  152. RESULT_BUFFER[RESULT_LENGTH] = BasicNulChar;
  153. }
  154. else
  155. {
  156. if (argv->memnum == NULL)
  157. {
  158. WARN_INTERNAL_ERROR;
  159. return NULL;
  160. }
  161. RESULT_NUMBER = 0;
  162. }
  163. argn = argv;
  164. /* don't make a bad situation worse */
  165. if( bwb_Warning_Pending() /* Keep This */ )
  166. {
  167. /* An unrecognized NON-FATAL ERROR is pending. Just return a sane value. */
  168. /* LET N = LOG(SQR(X)) ' X = -1 */
  169. return argv;
  170. }
  171. /* Follow the BASIC naming conventions, so the code is easier to read and maintain */
  172. {
  173. int i;
  174. int StrCount = 0; /* count of STRING parameters - NEVER > 3 */
  175. int NumCount = 0; /* count of NUMBER parameters - NEVER > 3 */
  176. unsigned long ParameterTests;
  177. ParameterTests = f->ParameterTests;
  178. /* assign reasonable default values */
  179. S = NULL; /* S$ - return value is a STRING */
  180. s = 0; /* LEN( S$ ) */
  181. N = 0; /* N - return value is a NUMBER */
  182. A = NULL; /* A$ - 1st STRING parameter */
  183. a = 0; /* LEN( A$ ) */
  184. B = NULL; /* B$ - 2nd STRING parameter */
  185. b = 0; /* LEN( B$ ) */
  186. #if FALSE /* keep third parameter */
  187. C = NULL; /* C$ - 3rd STRING parameter */
  188. c = 0; /* LEN( C$ ) */
  189. #endif
  190. X = 0; /* X - 1st NUMBER parameter */
  191. x = 0; /* INT( X ) */
  192. Y = 0; /* Y - 2nd NUMBER parameter */
  193. y = 0; /* INT( Y ) */
  194. #if FALSE /* keep third parameter */
  195. Z = 0; /* Z - 3rd NUMBER parameter */
  196. z = 0; /* INT( Z ) */
  197. #endif
  198. /* assign actual values */
  199. if (f->ReturnType == BasicStringSuffix)
  200. {
  201. S = RESULT_BUFFER;
  202. s = RESULT_LENGTH;
  203. }
  204. else
  205. {
  206. N = RESULT_NUMBER;
  207. }
  208. for (i = 0; i < argc && IsError == 0; i++)
  209. {
  210. argn = argn->next;
  211. if (argn == NULL)
  212. {
  213. WARN_INTERNAL_ERROR;
  214. return NULL;
  215. }
  216. if ( VAR_IS_STRING( argn ) )
  217. {
  218. if (argn->memstr == NULL)
  219. {
  220. WARN_INTERNAL_ERROR;
  221. return NULL;
  222. }
  223. StrCount++;
  224. switch (StrCount)
  225. {
  226. case 1:
  227. /* 1st STRING parameter = A$ */
  228. A = PARAM_BUFFER;
  229. a = PARAM_LENGTH;
  230. if (StringLengthCheck(ParameterTests, a))
  231. {
  232. IsError = 'A';
  233. }
  234. else
  235. {
  236. A[a] = 0;
  237. }
  238. break;
  239. case 2:
  240. /* 2nd STRING parameter = B$ */
  241. B = PARAM_BUFFER;
  242. b = PARAM_LENGTH;
  243. if (StringLengthCheck(ParameterTests, b))
  244. {
  245. IsError = 'B';
  246. }
  247. else
  248. {
  249. B[b] = 0;
  250. }
  251. break;
  252. #if FALSE /* keep third parameter */
  253. case 3:
  254. /* 3rd STRING parameter = C$ */
  255. /* not currently used */
  256. C = PARAM_BUFFER;
  257. c = PARAM_LENGTH;
  258. if (StringLengthCheck(ParameterTests, c))
  259. {
  260. IsError = 'C';
  261. }
  262. else
  263. {
  264. C[c] = 0;
  265. }
  266. break;
  267. #endif
  268. default:
  269. /* Nth STRING parameter = ERROR */
  270. IsError = i + 1;
  271. break;
  272. }
  273. }
  274. else
  275. {
  276. if (argn->memnum == NULL)
  277. {
  278. WARN_INTERNAL_ERROR;
  279. return NULL;
  280. }
  281. NumCount++;
  282. switch (NumCount)
  283. {
  284. case 1:
  285. /* 1st NUMBER parameter = X */
  286. X = PARAM_NUMBER;
  287. if (NumberValueCheck(ParameterTests, X))
  288. {
  289. IsError = 'X';
  290. }
  291. else
  292. {
  293. BasicNumberType R;
  294. R = bwb_rint(X);
  295. if (R < INT_MIN || R > INT_MAX)
  296. {
  297. /* certainly not a
  298. * classic BASIC
  299. * integer */
  300. }
  301. else
  302. {
  303. /* Many classic BASIC
  304. * intrinsic
  305. * functions use the
  306. * rounded integer
  307. * value. */
  308. x = (int) R;
  309. }
  310. }
  311. break;
  312. case 2:
  313. /* 2nd NUMBER parameter = Y */
  314. Y = PARAM_NUMBER;
  315. if (NumberValueCheck(ParameterTests, Y))
  316. {
  317. IsError = 'Y';
  318. }
  319. else
  320. {
  321. BasicNumberType R;
  322. R = bwb_rint(Y);
  323. if (R < INT_MIN || R > INT_MAX)
  324. {
  325. /* certainly not a
  326. * classic BASIC
  327. * integer */
  328. }
  329. else
  330. {
  331. /* Many classic BASIC
  332. * intrinsic
  333. * functions use the
  334. * rounded integer
  335. * value. */
  336. y = (int) R;
  337. }
  338. }
  339. break;
  340. #if FALSE /* keep third parameter */
  341. case 3:
  342. /* 3rd NUMBER parameter = Z */
  343. /* not currently used */
  344. Z = PARAM_NUMBER;
  345. if (NumberValueCheck(ParameterTests, Z))
  346. {
  347. IsError = 'Z';
  348. }
  349. else
  350. {
  351. BasicNumberType R;
  352. R = bwb_rint(Z);
  353. if (R < INT_MIN || R > INT_MAX)
  354. {
  355. /* certainly not a
  356. * classic BASIC
  357. * integer */
  358. }
  359. else
  360. {
  361. /* Many classic BASIC
  362. * intrinsic
  363. * functions use the
  364. * rounded integer
  365. * value. */
  366. z = (int) R;
  367. }
  368. }
  369. break;
  370. #endif
  371. default:
  372. /* Nth NUMBER parameter = ERROR */
  373. IsError = i + 1;
  374. break;
  375. }
  376. }
  377. ParameterTests = ParameterTests >> 4;
  378. }
  379. }
  380. /* execute the intrinsic function */
  381. /* WARNING -- do NOT execute a BASIC intrinsic function with bogus parameters */
  382. if (IsError == 0 )
  383. {
  384. switch (unique_id)
  385. {
  386. /* ALL paramters have been checked for TYPE MISMATCH
  387. * and INVALID RANGE */
  388. /* ONLY A HANDFUL OF ERRORS CAN OCCUR */
  389. case 0:
  390. {
  391. /* INTERNAL ERROR */
  392. IsError = 1;
  393. }
  394. break;
  395. case F_DEF_FN_N:
  396. {
  397. /* INTERNAL ERROR */
  398. IsError = 1;
  399. }
  400. break;
  401. case F_ARGC_N:
  402. /* N = ARGC */
  403. {
  404. /* determine number of parameters to the current USER DEFINED FUNCTION */
  405. int n;
  406. n = 0;
  407. if ( My->stack_head != NULL )
  408. {
  409. int Loop;
  410. StackType * stack_item;
  411. Loop = TRUE;
  412. for (stack_item = My->stack_head; stack_item != NULL && Loop == TRUE; stack_item = stack_item->next)
  413. {
  414. if (stack_item->LoopTopLine != NULL)
  415. {
  416. switch (stack_item->LoopTopLine->cmdnum)
  417. {
  418. case C_FUNCTION:
  419. case C_SUB:
  420. /* we have checked all the way to a FUNCTION or SUB boundary */
  421. /* FOUND */
  422. {
  423. VariableType *v;
  424. for (v = stack_item->local_variable; v != NULL && Loop == TRUE; v = v->next)
  425. {
  426. n++;
  427. }
  428. }
  429. Loop = FALSE;
  430. break;
  431. }
  432. }
  433. }
  434. }
  435. n--; /* FUNCTION or SUB name */
  436. N = n;
  437. }
  438. break;
  439. case F_ARGT4_X_S:
  440. /* S$ = ARGT$( X ) */
  441. {
  442. /* determine parameter type to the current USER DEFINED FUNCTION */
  443. int Found;
  444. int n;
  445. Found = FALSE;
  446. n = 0;
  447. s = 0;
  448. if (x < 1)
  449. {
  450. /* bad param number */
  451. }
  452. else
  453. if ( My->stack_head != NULL )
  454. {
  455. int Loop;
  456. StackType * stack_item;
  457. Loop = TRUE;
  458. for (stack_item = My->stack_head; stack_item != NULL && Loop == TRUE; stack_item = stack_item->next)
  459. {
  460. if (stack_item->LoopTopLine != NULL)
  461. {
  462. switch (stack_item->LoopTopLine->cmdnum)
  463. {
  464. case C_FUNCTION:
  465. case C_SUB:
  466. /* we have checked all the way to a FUNCTION or SUB boundary */
  467. /* FOUND */
  468. {
  469. VariableType *v;
  470. for (v = stack_item->local_variable; v != NULL && Loop == TRUE; v = v->next)
  471. {
  472. if (n == x)
  473. {
  474. if ( VAR_IS_STRING( v ) )
  475. {
  476. S[0] = BasicStringSuffix;
  477. s = 1;
  478. Found = TRUE;
  479. }
  480. else
  481. {
  482. S[0] = BasicDoubleSuffix;
  483. s = 1;
  484. Found = TRUE;
  485. }
  486. Loop = FALSE;
  487. }
  488. n++;
  489. }
  490. }
  491. Loop = FALSE;
  492. break;
  493. }
  494. }
  495. }
  496. }
  497. if (Found == FALSE)
  498. {
  499. IsError = 'X';
  500. }
  501. }
  502. break;
  503. case F_ARGV4_X_S:
  504. /* S$ = ARGV$( X ) */
  505. {
  506. /* determine parameter value to the current
  507. * USER DEFINED FUNCTION */
  508. int Found;
  509. int n;
  510. Found = FALSE;
  511. n = 0;
  512. if (x < 1)
  513. {
  514. /* bad param number */
  515. }
  516. else
  517. if ( My->stack_head != NULL )
  518. {
  519. int Loop;
  520. StackType * stack_item;
  521. Loop = TRUE;
  522. for (stack_item = My->stack_head; stack_item != NULL && Loop == TRUE; stack_item = stack_item->next)
  523. {
  524. if (stack_item->LoopTopLine != NULL)
  525. {
  526. switch (stack_item->LoopTopLine->cmdnum)
  527. {
  528. case C_FUNCTION:
  529. case C_SUB:
  530. /* we have checked all the way to a FUNCTION or SUB boundary */
  531. /* FOUND */
  532. {
  533. VariableType *v;
  534. for (v = stack_item->local_variable; v != NULL && Loop == TRUE; v = v->next)
  535. {
  536. if (n == x)
  537. {
  538. if ( VAR_IS_STRING( v ) )
  539. {
  540. s = v->memstr->length;
  541. bwb_memcpy(S, v->memstr->sbuffer, s);
  542. Found = TRUE;
  543. }
  544. else
  545. {
  546. }
  547. Loop = FALSE;
  548. }
  549. n++;
  550. }
  551. }
  552. Loop = FALSE;
  553. break;
  554. }
  555. }
  556. }
  557. }
  558. if (Found == FALSE)
  559. {
  560. IsError = 'X';
  561. }
  562. }
  563. break;
  564. case F_ARGV_X_N:
  565. /* S$ = ARGV( X ) */
  566. {
  567. /* determine parameter value to the current USER DEFINED FUNCTION */
  568. int Found;
  569. int n;
  570. Found = FALSE;
  571. n = 0;
  572. if (x < 1)
  573. {
  574. /* bad param number */
  575. }
  576. else
  577. if ( My->stack_head != NULL )
  578. {
  579. int Loop;
  580. StackType * stack_item;
  581. Loop = TRUE;
  582. for (stack_item = My->stack_head; stack_item != NULL && Loop == TRUE; stack_item = stack_item->next)
  583. {
  584. if (stack_item->LoopTopLine != NULL)
  585. {
  586. switch (stack_item->LoopTopLine->cmdnum)
  587. {
  588. case C_FUNCTION:
  589. case C_SUB:
  590. /* we have checked all the way to a FUNCTION or SUB boundary */
  591. /* FOUND */
  592. {
  593. VariableType *v;
  594. for (v = stack_item->local_variable; v != NULL && Loop == TRUE; v = v->next)
  595. {
  596. if (n == x)
  597. {
  598. if ( VAR_IS_STRING( v ) )
  599. {
  600. }
  601. else
  602. {
  603. N = *v->memnum;
  604. Found = TRUE;
  605. }
  606. Loop = FALSE;
  607. }
  608. n++;
  609. }
  610. }
  611. Loop = FALSE;
  612. break;
  613. }
  614. }
  615. }
  616. }
  617. if (Found == FALSE)
  618. {
  619. IsError = 'X';
  620. }
  621. }
  622. break;
  623. case F_BASE_N:
  624. /* N = BASE */
  625. {
  626. /* PNONE */
  627. N = My->CurrentVersion->OptionBaseValue;
  628. }
  629. break;
  630. case F_ASC_A_N:
  631. case F_ASCII_A_N:
  632. case F_CODE_A_N:
  633. /* N = ASC( A$ ) */
  634. /* N = ASCII( A$ ) */
  635. /* N = CODE( A$ ) */
  636. {
  637. /* P1BYT */
  638. N = A[0];
  639. }
  640. break;
  641. case F_ASC_A_X_N:
  642. /* N = ASC( A$, X ) */
  643. {
  644. /* P1BYT|P2POS */
  645. x--; /* BASIC -> C */
  646. if( x < a )
  647. {
  648. N = A[x];
  649. }
  650. else
  651. {
  652. IsError = 'X';
  653. }
  654. }
  655. break;
  656. case F_CDBL_X_N:
  657. /* N = CDBL( X ) */
  658. {
  659. /* P1DBL */
  660. N = X;
  661. /* argv->VariableType = BasicDoubleSuffix; */
  662. }
  663. break;
  664. case F_CSNG_X_N:
  665. /* N = CSNG( X ) */
  666. {
  667. /* P1FLT */
  668. N = X;
  669. /* argv->VariableType = BasicSingleSuffix; */
  670. }
  671. break;
  672. case F_CCUR_X_N:
  673. /* N = CCUR( X ) */
  674. {
  675. /* P1CUR */
  676. N = bwb_rint(X);
  677. /* argv->VariableType = BasicCurrencySuffix; */
  678. }
  679. break;
  680. case F_CLNG_X_N:
  681. /* N = CLNG( X ) */
  682. {
  683. /* P1LNG */
  684. N = bwb_rint(X);
  685. /* argv->VariableType = BasicLongSuffix; */
  686. }
  687. break;
  688. case F_CINT_X_N:
  689. /* N = CINT( X ) */
  690. {
  691. /* P1INT */
  692. N = bwb_rint(X);
  693. /* argv->VariableType = BasicIntegerSuffix; */
  694. }
  695. break;
  696. case F_MKD4_X_S:
  697. /* S$ = MKD$( X ) */
  698. {
  699. /* P1DBL */
  700. BasicDoubleType x;
  701. x = (BasicDoubleType) X;
  702. s = sizeof(BasicDoubleType);
  703. bwb_memcpy(S, &x, s);
  704. }
  705. break;
  706. case F_MKS4_X_S:
  707. /* S$ = MKS$( X ) */
  708. {
  709. /* P1FLT */
  710. BasicSingleType x;
  711. x = (BasicSingleType) X;
  712. s = sizeof(BasicSingleType);
  713. bwb_memcpy(S, &x, s);
  714. }
  715. break;
  716. case F_MKI4_X_S:
  717. /* S$ = MKI$( X ) */
  718. {
  719. /* P1INT */
  720. BasicIntegerType x;
  721. x = (BasicIntegerType) bwb_rint(X);
  722. s = sizeof(BasicIntegerType);
  723. bwb_memcpy(S, &x, s);
  724. }
  725. break;
  726. case F_MKL4_X_S:
  727. /* S$ = MKL$( X ) */
  728. {
  729. /* P1LNG */
  730. BasicLongType x;
  731. x = (BasicLongType) bwb_rint(X);
  732. s = sizeof(BasicLongType);
  733. bwb_memcpy(S, &x, s);
  734. }
  735. break;
  736. case F_MKC4_X_S:
  737. /* S$ = MKC$( X ) */
  738. {
  739. /* P1CUR */
  740. BasicCurrencyType x;
  741. x = (BasicCurrencyType) bwb_rint(X);
  742. s = sizeof(BasicCurrencyType);
  743. bwb_memcpy(S, &x, s);
  744. }
  745. break;
  746. case F_CVD_A_N:
  747. /* N = CVD( A$ ) */
  748. {
  749. /* P1DBL */
  750. BasicDoubleType n;
  751. a = sizeof(BasicDoubleType);
  752. bwb_memcpy(&n, A, a);
  753. N = n;
  754. }
  755. break;
  756. case F_CVS_A_N:
  757. /* N = CVS( X$ ) */
  758. {
  759. /* P1FLT */
  760. BasicSingleType n;
  761. a = sizeof(BasicSingleType);
  762. bwb_memcpy(&n, A, a);
  763. N = n;
  764. }
  765. break;
  766. case F_CVI_A_N:
  767. /* N = CVI( X$ ) */
  768. {
  769. /* P1INT */
  770. BasicIntegerType n;
  771. a = sizeof(BasicIntegerType);
  772. bwb_memcpy(&n, A, a);
  773. N = n;
  774. }
  775. break;
  776. case F_CVL_A_N:
  777. /* N = CVL( X$ ) */
  778. {
  779. /* P1LNG */
  780. BasicLongType n;
  781. a = sizeof(BasicLongType);
  782. bwb_memcpy(&n, A, a);
  783. N = n;
  784. }
  785. break;
  786. case F_CVC_A_N:
  787. /* N = CVC( X$ ) */
  788. {
  789. /* P1CUR */
  790. BasicCurrencyType n;
  791. a = sizeof(BasicCurrencyType);
  792. bwb_memcpy(&n, A, a);
  793. N = n;
  794. }
  795. break;
  796. case F_ENVIRON4_A_S:
  797. /* S$ = ENVIRON$( A$ ) */
  798. {
  799. /* P1BYT */
  800. char *CharPointer;
  801. CharPointer = getenv(A);
  802. if (CharPointer == NULL)
  803. {
  804. /* empty string */
  805. }
  806. else
  807. {
  808. s = bwb_strlen(CharPointer);
  809. s = MIN(s, BasicStringLengthMax);
  810. if (s == 0)
  811. {
  812. /* empty string */
  813. }
  814. else
  815. {
  816. bwb_memcpy(S, CharPointer, s);
  817. }
  818. }
  819. }
  820. break;
  821. case F_ENVIRON_A_N:
  822. /* ENVIRON A$ */
  823. {
  824. /* P1BYT */
  825. char *CharPointer;
  826. CharPointer = bwb_strchr(A, '=');
  827. if (CharPointer == NULL)
  828. {
  829. /* missing required '=' */
  830. IsError = 'A';
  831. }
  832. else
  833. {
  834. if (putenv(A) == -1)
  835. {
  836. IsError = 'A';
  837. }
  838. else
  839. {
  840. /* OK */
  841. N = 0;
  842. }
  843. }
  844. }
  845. break;
  846. case F_OPEN_A_X_B_Y_N:
  847. /* OPEN "I"|"O"|"R"|"A", [#]n, filename [,rlen] */
  848. {
  849. /* P1STR|P2NUM|P3STR|P4NUM */
  850. /* P1BYT|P2DEV|P3BYT|P4INT */
  851. while (*A == ' ')
  852. {
  853. A++; /* LTRIM$ */
  854. }
  855. IsError = bwb_file_open( *A, x, B, y );
  856. }
  857. break;
  858. case F_OPEN_A_X_B_N:
  859. /* default LEN is 128 for RANDOM, 0 for all others */
  860. /* OPEN "I"|"O"|"R"|"A", [#]n, filename [,rlen] */
  861. {
  862. /* P1STR|P2NUM|P3STR|P4NUM */
  863. /* P1BYT|P2DEV|P3BYT|P4INT */
  864. int y = 0;
  865. while (*A == ' ')
  866. {
  867. A++; /* LTRIM$ */
  868. }
  869. if( bwb_toupper(*A) == 'R' )
  870. {
  871. /* default RANDOM record size */
  872. y = 128;
  873. }
  874. IsError = bwb_file_open( *A, x, B, y );
  875. }
  876. break;
  877. case F_LOC_X_N:
  878. /* N = LOC( X ) */
  879. {
  880. /* P1DEV */
  881. if( x <= 0 )
  882. {
  883. N = 0;
  884. }
  885. else
  886. {
  887. FileType * F;
  888. F = find_file_by_number( x );
  889. if( F == NULL )
  890. {
  891. IsError = 'X';
  892. }
  893. else
  894. if( F == My->SYSIN )
  895. {
  896. N = 0;
  897. }
  898. else
  899. if( F == My->SYSOUT )
  900. {
  901. N = 0;
  902. }
  903. else
  904. if( F == My->SYSPRN )
  905. {
  906. N = 0;
  907. }
  908. else
  909. {
  910. FILE *fp;
  911. fp = F->cfp;
  912. N = ftell(fp);
  913. if( My->CurrentVersion->OptionVersionBitmask & (G65 | G67) )
  914. {
  915. /* byte position, regardless of 'mode' */
  916. }
  917. else
  918. if (F->mode == DEVMODE_RANDOM)
  919. {
  920. /* record number */
  921. if( F->width == 0 )
  922. {
  923. /* byte position */
  924. }
  925. else
  926. {
  927. N /= F->width;
  928. }
  929. }
  930. else
  931. if (F->mode == DEVMODE_BINARY)
  932. {
  933. /* byte position */
  934. }
  935. else
  936. {
  937. /* byte positiion / 128 */
  938. N /= 128;
  939. }
  940. N = floor(N);
  941. N++; /* C to BASIC */
  942. }
  943. }
  944. }
  945. break;
  946. case F_SEEK_X_N:
  947. /* N = SEEK( X ) */
  948. {
  949. /* P1DEV */
  950. if( x <= 0 )
  951. {
  952. N = 0;
  953. }
  954. else
  955. {
  956. FileType * F;
  957. F = find_file_by_number( x );
  958. if( F == NULL )
  959. {
  960. IsError = 'X';
  961. }
  962. else
  963. if( F == My->SYSIN )
  964. {
  965. N = 0;
  966. }
  967. else
  968. if( F == My->SYSOUT )
  969. {
  970. N = 0;
  971. }
  972. else
  973. if( F == My->SYSPRN )
  974. {
  975. N = 0;
  976. }
  977. else
  978. {
  979. FILE *fp;
  980. fp = F->cfp;
  981. N = ftell(fp);
  982. if (F->mode == DEVMODE_RANDOM)
  983. {
  984. /* record number */
  985. if( F->width > 0 )
  986. {
  987. N /= F->width;
  988. }
  989. }
  990. else
  991. {
  992. /* byte positiion */
  993. }
  994. N = floor(N);
  995. N++; /* C to BASIC */
  996. }
  997. }
  998. }
  999. break;
  1000. case F_SEEK_X_Y_N:
  1001. /* SEEK X, Y */
  1002. {
  1003. /* P1DEV|P2INT */
  1004. if( x <= 0 )
  1005. {
  1006. IsError = 'X';
  1007. }
  1008. else
  1009. {
  1010. FileType * F;
  1011. F = find_file_by_number( x );
  1012. if( F == NULL )
  1013. {
  1014. IsError = 'X';
  1015. }
  1016. else
  1017. if( F == My->SYSIN )
  1018. {
  1019. IsError = 'X';
  1020. }
  1021. else
  1022. if( F == My->SYSOUT )
  1023. {
  1024. IsError = 'X';
  1025. }
  1026. else
  1027. if( F == My->SYSPRN )
  1028. {
  1029. IsError = 'X';
  1030. }
  1031. else
  1032. if (y < 1)
  1033. {
  1034. IsError = 'Y';
  1035. }
  1036. else
  1037. {
  1038. long offset;
  1039. offset = y;
  1040. offset--; /* BASIC to C */
  1041. if (F->mode == DEVMODE_RANDOM)
  1042. {
  1043. if( F->width > 0 )
  1044. {
  1045. offset *= F->width;
  1046. }
  1047. }
  1048. if (fseek(F->cfp, offset, SEEK_SET) != 0)
  1049. {
  1050. IsError = 'Y';
  1051. }
  1052. else
  1053. {
  1054. /* OK */
  1055. N = 0;
  1056. }
  1057. }
  1058. }
  1059. }
  1060. break;
  1061. case F_LOF_X_N:
  1062. /* N = LOF( X ) */
  1063. {
  1064. /* P1DEV */
  1065. if( x <= 0 )
  1066. {
  1067. N = 0;
  1068. }
  1069. else
  1070. {
  1071. FileType * F;
  1072. F = find_file_by_number( x );
  1073. if( F == NULL )
  1074. {
  1075. IsError = 'X';
  1076. }
  1077. else
  1078. if( F == My->SYSIN )
  1079. {
  1080. N = 0;
  1081. }
  1082. else
  1083. if( F == My->SYSOUT )
  1084. {
  1085. N = 0;
  1086. }
  1087. else
  1088. if( F == My->SYSPRN )
  1089. {
  1090. N = 0;
  1091. }
  1092. else
  1093. {
  1094. /* file size in bytes */
  1095. FILE *fp;
  1096. long current;
  1097. long total;
  1098. fp = F->cfp;
  1099. current = ftell(fp);
  1100. fseek(fp, 0, SEEK_END);
  1101. total = ftell(fp);
  1102. if (total == current)
  1103. {
  1104. /* EOF */
  1105. }
  1106. else
  1107. {
  1108. fseek(fp, current, SEEK_SET);
  1109. }
  1110. N = total;
  1111. }
  1112. }
  1113. }
  1114. break;
  1115. case F_EOF_X_N:
  1116. /* N = EOF( X ) */
  1117. {
  1118. /* P1DEV */
  1119. if( x <= 0 )
  1120. {
  1121. N = 0;
  1122. }
  1123. else
  1124. {
  1125. FileType * F;
  1126. F = find_file_by_number( x );
  1127. if( F == NULL )
  1128. {
  1129. IsError = 'X';
  1130. }
  1131. else
  1132. if( F == My->SYSIN )
  1133. {
  1134. N = 0;
  1135. }
  1136. else
  1137. if( F == My->SYSOUT )
  1138. {
  1139. N = 0;
  1140. }
  1141. else
  1142. if( F == My->SYSPRN )
  1143. {
  1144. N = 0;
  1145. }
  1146. else
  1147. {
  1148. /* are we at the end? */
  1149. N = bwb_is_eof( F->cfp );
  1150. }
  1151. }
  1152. }
  1153. break;
  1154. case F_FILEATTR_X_Y_N:
  1155. /* N = FILEATTR( X, Y ) */
  1156. {
  1157. /* P1DEV|P2INT */
  1158. if( x <= 0 )
  1159. {
  1160. /* Printer and Console */
  1161. IsError = 'X';
  1162. }
  1163. else
  1164. if( y == 1 )
  1165. {
  1166. FileType * F;
  1167. F = find_file_by_number( x );
  1168. if( F == NULL )
  1169. {
  1170. /* normal CLOSED file */
  1171. N = 0;
  1172. }
  1173. else
  1174. {
  1175. /* normal OPEN file */
  1176. N = F->mode;
  1177. }
  1178. }
  1179. else
  1180. if( y == 2 )
  1181. {
  1182. N = 0;
  1183. }
  1184. else
  1185. {
  1186. IsError = 'Y';
  1187. }
  1188. }
  1189. break;
  1190. case F_CLOSE_X_N:
  1191. /* CLOSE X */
  1192. {
  1193. /* P1DEV */
  1194. if( x <= 0 )
  1195. {
  1196. /* Printer and Console */
  1197. IsError = 'X';
  1198. }
  1199. else
  1200. {
  1201. FileType * F;
  1202. F = find_file_by_number( x );
  1203. if( F == NULL )
  1204. {
  1205. IsError = 'X';
  1206. }
  1207. else
  1208. if( F == My->SYSIN )
  1209. {
  1210. IsError = 'X';
  1211. }
  1212. else
  1213. if( F == My->SYSOUT )
  1214. {
  1215. IsError = 'X';
  1216. }
  1217. else
  1218. if( F == My->SYSPRN )
  1219. {
  1220. IsError = 'X';
  1221. }
  1222. else
  1223. {
  1224. field_close_file( F );
  1225. file_clear( F );
  1226. N = 0;
  1227. }
  1228. }
  1229. }
  1230. break;
  1231. case F_RESET_N:
  1232. case F_CLOSE_N:
  1233. /* RESET */
  1234. /* CLOSE */
  1235. {
  1236. /* PNONE */
  1237. FileType * F;
  1238. for (F = My->file_head; F != NULL; F = F->next)
  1239. {
  1240. field_close_file( F );
  1241. file_clear( F );
  1242. }
  1243. N = 0;
  1244. }
  1245. break;
  1246. case F_FREEFILE_N:
  1247. /* N = FREEFILE */
  1248. {
  1249. /* PNONE */
  1250. int x;
  1251. FileType * F;
  1252. x = 0;
  1253. for (F = My->file_head; F != NULL; F = F->next)
  1254. {
  1255. if (F->mode != DEVMODE_CLOSED)
  1256. {
  1257. if( F->FileNumber > x )
  1258. {
  1259. x = F->FileNumber;
  1260. }
  1261. }
  1262. }
  1263. /* 'x' is the highest FileNumber that is currently open */
  1264. x++;
  1265. if( x > BasicFileNumberMax )
  1266. {
  1267. x = 0;
  1268. }
  1269. N = x;
  1270. }
  1271. break;
  1272. case F_GET_X_Y_N:
  1273. /* GET X, Y */
  1274. {
  1275. /* P1DEV|P2INT */
  1276. if( x <= 0 )
  1277. {
  1278. /* Printer and Console */
  1279. IsError = 'X';
  1280. }
  1281. else
  1282. {
  1283. FileType * F;
  1284. F = find_file_by_number( x );
  1285. if( F == NULL )
  1286. {
  1287. IsError = 'X';
  1288. }
  1289. else
  1290. if( F == My->SYSIN )
  1291. {
  1292. IsError = 'X';
  1293. }
  1294. else
  1295. if( F == My->SYSOUT )
  1296. {
  1297. IsError = 'X';
  1298. }
  1299. else
  1300. if( F == My->SYSPRN )
  1301. {
  1302. IsError = 'X';
  1303. }
  1304. else
  1305. if (F->mode != DEVMODE_RANDOM)
  1306. {
  1307. IsError = 'X';
  1308. }
  1309. else
  1310. if (y < 1)
  1311. {
  1312. IsError = 'Y';
  1313. }
  1314. else
  1315. {
  1316. long offset;
  1317. offset = y;
  1318. offset--; /* BASIC to C */
  1319. if (F->mode == DEVMODE_RANDOM)
  1320. {
  1321. if( F->width > 0 )
  1322. {
  1323. offset *= F->width;
  1324. }
  1325. }
  1326. if (fseek(F->cfp, offset, SEEK_SET) != 0)
  1327. {
  1328. IsError = 'Y';
  1329. }
  1330. else
  1331. {
  1332. int i;
  1333. for (i = 0; i < F->width; i++)
  1334. {
  1335. F->buffer[i] = fgetc(F->cfp);
  1336. }
  1337. field_get( F );
  1338. N = 0;
  1339. }
  1340. }
  1341. }
  1342. }
  1343. break;
  1344. case F_GET_X_N:
  1345. /* GET X */
  1346. {
  1347. /* PDEV1 */
  1348. if( x <= 0 )
  1349. {
  1350. /* Printer and Console */
  1351. IsError = 'X';
  1352. }
  1353. else
  1354. {
  1355. FileType * F;
  1356. F = find_file_by_number( x );
  1357. if( F == NULL )
  1358. {
  1359. IsError = 'X';
  1360. }
  1361. else
  1362. if( F == My->SYSIN )
  1363. {
  1364. IsError = 'X';
  1365. }
  1366. else
  1367. if( F == My->SYSOUT )
  1368. {
  1369. IsError = 'X';
  1370. }
  1371. else
  1372. if( F == My->SYSPRN )
  1373. {
  1374. IsError = 'X';
  1375. }
  1376. else
  1377. if (F->mode != DEVMODE_RANDOM)
  1378. {
  1379. IsError = 'X';
  1380. }
  1381. else
  1382. {
  1383. {
  1384. int i;
  1385. for (i = 0; i < F->width; i++)
  1386. {
  1387. F->buffer[i] = fgetc(F->cfp);
  1388. }
  1389. field_get( F );
  1390. N = 0;
  1391. }
  1392. }
  1393. }
  1394. }
  1395. break;
  1396. case F_PUT_X_Y_N:
  1397. /* PUT X, Y */
  1398. {
  1399. /* P1DEV|P2INT */
  1400. if( x <= 0 )
  1401. {
  1402. /* Printer and Console */
  1403. IsError = 'X';
  1404. }
  1405. else
  1406. {
  1407. FileType * F;
  1408. F = find_file_by_number( x );
  1409. if( F == NULL )
  1410. {
  1411. IsError = 'X';
  1412. }
  1413. else
  1414. if( F == My->SYSIN )
  1415. {
  1416. IsError = 'X';
  1417. }
  1418. else
  1419. if( F == My->SYSOUT )
  1420. {
  1421. IsError = 'X';
  1422. }
  1423. else
  1424. if( F == My->SYSPRN )
  1425. {
  1426. IsError = 'X';
  1427. }
  1428. else
  1429. if (F->mode != DEVMODE_RANDOM)
  1430. {
  1431. IsError = 'X';
  1432. }
  1433. else
  1434. if (y < 1)
  1435. {
  1436. IsError = 'Y';
  1437. }
  1438. else
  1439. {
  1440. long offset;
  1441. offset = y;
  1442. offset--; /* BASIC to C */
  1443. if (F->mode == DEVMODE_RANDOM)
  1444. {
  1445. if( F->width > 0 )
  1446. {
  1447. offset *= F->width;
  1448. }
  1449. }
  1450. if (fseek(F->cfp, offset, SEEK_SET) != 0)
  1451. {
  1452. IsError = 'Y';
  1453. }
  1454. else
  1455. {
  1456. int i;
  1457. field_put( F );
  1458. for (i = 0; i < F->width; i++)
  1459. {
  1460. fputc(F->buffer[i], F->cfp);
  1461. F->buffer[i] = ' '; /* flush */
  1462. }
  1463. N = 0;
  1464. }
  1465. }
  1466. }
  1467. }
  1468. break;
  1469. case F_PUT_X_N:
  1470. /* PUT X */
  1471. {
  1472. /* P1DEV */
  1473. if( x <= 0 )
  1474. {
  1475. /* Printer and Console */
  1476. IsError = 'X';
  1477. }
  1478. else
  1479. {
  1480. FileType * F;
  1481. F = find_file_by_number( x );
  1482. if( F == NULL )
  1483. {
  1484. IsError = 'X';
  1485. }
  1486. else
  1487. if( F == My->SYSIN )
  1488. {
  1489. IsError = 'X';
  1490. }
  1491. else
  1492. if( F == My->SYSOUT )
  1493. {
  1494. IsError = 'X';
  1495. }
  1496. else
  1497. if( F == My->SYSPRN )
  1498. {
  1499. IsError = 'X';
  1500. }
  1501. else
  1502. if (F->mode != DEVMODE_RANDOM)
  1503. {
  1504. IsError = 'X';
  1505. }
  1506. else
  1507. {
  1508. {
  1509. int i;
  1510. field_put( F );
  1511. for (i = 0; i < F->width; i++)
  1512. {
  1513. fputc(F->buffer[i], F->cfp);
  1514. F->buffer[i] = ' '; /* flush */
  1515. }
  1516. N = 0;
  1517. }
  1518. }
  1519. }
  1520. }
  1521. break;
  1522. case F_WIDTH_X_N:
  1523. /* WIDTH X */
  1524. {
  1525. /* P1BYT */
  1526. /* console is #0 */
  1527. My->SYSIN->width = x;
  1528. My->SYSIN->col = 1;
  1529. My->SYSOUT->width = x;
  1530. My->SYSOUT->col = 1;
  1531. N = 0;
  1532. }
  1533. break;
  1534. case F_WIDTH_X_Y_N:
  1535. /* WIDTH X, Y */
  1536. {
  1537. /* WIDTH #file, cols */
  1538. /* P1BYT|PB2YT */
  1539. if( x == 0 )
  1540. {
  1541. My->SYSIN->width = y;
  1542. My->SYSOUT->width = y;
  1543. N = 0;
  1544. }
  1545. else
  1546. if( x < 0 )
  1547. {
  1548. My->SYSPRN->width = y;
  1549. N = 0;
  1550. }
  1551. else
  1552. {
  1553. FileType * F;
  1554. F = find_file_by_number( x );
  1555. if( F == NULL )
  1556. {
  1557. /* WIDTH rows, cols */
  1558. My->SCREEN_ROWS = x;
  1559. My->SYSIN->width = y;
  1560. My->SYSIN->col = 1;
  1561. My->SYSOUT->width = y;
  1562. My->SYSOUT->col = 1;
  1563. N = 0;
  1564. }
  1565. else
  1566. if (F->mode == DEVMODE_RANDOM)
  1567. {
  1568. IsError = 'X';
  1569. }
  1570. else
  1571. {
  1572. /* WIDTH # file, cols */
  1573. F->width = y;
  1574. F->col = 1;
  1575. N = 0;
  1576. }
  1577. }
  1578. }
  1579. break;
  1580. case F_INSTR_X_A_B_N:
  1581. /* N = INSTR( X, A$, B$ ) */
  1582. {
  1583. /* P1POS */
  1584. if (a == 0)
  1585. {
  1586. /* empty searched */
  1587. }
  1588. else
  1589. if (b == 0)
  1590. {
  1591. /* empty pattern */
  1592. }
  1593. else
  1594. if (b > a)
  1595. {
  1596. /* pattern is longer than searched */
  1597. }
  1598. else
  1599. {
  1600. /* search */
  1601. int i;
  1602. int n;
  1603. n = a - b; /* last valid search position */
  1604. n++;
  1605. x--; /* BASIC to C */
  1606. A += x; /* advance to the start
  1607. * position */
  1608. for (i = x; i < n; i++)
  1609. {
  1610. if (bwb_memcmp(A, B, b) == 0)
  1611. {
  1612. /* FOU ND */
  1613. i++; /* C to BASIC */
  1614. N = i;
  1615. i = n; /* exit for */
  1616. }
  1617. A++;
  1618. }
  1619. }
  1620. }
  1621. break;
  1622. case F_INSTR_A_B_N:
  1623. case F_INDEX_A_B_N:
  1624. /* N = INSTR( A$, B$ ) */
  1625. /* N = INDEX( A$, B$ ) */
  1626. {
  1627. if (a == 0)
  1628. {
  1629. /* empty searched */
  1630. }
  1631. else
  1632. if (b == 0)
  1633. {
  1634. /* empty pattern */
  1635. }
  1636. else
  1637. if (b > a)
  1638. {
  1639. /* pattern is longer than searched */
  1640. }
  1641. else
  1642. {
  1643. /* search */
  1644. int i;
  1645. int n;
  1646. n = a - b; /* last valid search
  1647. * position */
  1648. n++;
  1649. /* search */
  1650. for (i = 0; i < n; i++)
  1651. {
  1652. if (bwb_memcmp(A, B, b) == 0)
  1653. {
  1654. /* FOU ND */
  1655. i++; /* C to BASIC */
  1656. N = i;
  1657. i = n; /* exit for */
  1658. }
  1659. A++;
  1660. }
  1661. }
  1662. }
  1663. break;
  1664. case F_SPACE4_X_S:
  1665. case F_SPACE_X_S:
  1666. case F_SPA_X_S:
  1667. /* S$ = SPACE$( X ) */
  1668. /* S$ = SPACE( X ) */
  1669. /* S$ = SPA( X ) */
  1670. {
  1671. /* P1LEN */
  1672. if (x == 0)
  1673. {
  1674. /* no copies */
  1675. }
  1676. else
  1677. {
  1678. bwb_memset(S, (char) ' ', x);
  1679. s = x;
  1680. }
  1681. }
  1682. break;
  1683. case F_STRING4_X_Y_S:
  1684. case F_STRING_X_Y_S:
  1685. case F_STR_X_Y_S:
  1686. /* S$ = STRING$( X, Y ) */
  1687. /* S$ = STRING( X, Y ) */
  1688. /* S$ = STR( X, Y ) */
  1689. {
  1690. /* P1LEN|P2BYT */
  1691. if (x == 0)
  1692. {
  1693. /* no copies */
  1694. }
  1695. else
  1696. {
  1697. bwb_memset(S, (char) y, x);
  1698. s = x;
  1699. }
  1700. }
  1701. break;
  1702. case F_STRING4_X_A_S:
  1703. /* S$ = STRING$( X, A$ ) */
  1704. {
  1705. /* P1LEN|P2BYT */
  1706. if (x == 0)
  1707. {
  1708. /* no copies */
  1709. }
  1710. else
  1711. {
  1712. bwb_memset(S, (char) A[0], x);
  1713. s = x;
  1714. }
  1715. }
  1716. break;
  1717. case F_LIN_X_S:
  1718. /* S$ = LIN( X ) */
  1719. {
  1720. /* P1LEN */
  1721. if (x == 0)
  1722. {
  1723. /* no copies */
  1724. }
  1725. else
  1726. {
  1727. bwb_memset(S, (char) '\n', x);
  1728. s = x;
  1729. }
  1730. }
  1731. break;
  1732. case F_MID4_A_X_S:
  1733. case F_MID_A_X_S:
  1734. /* S$ = MID$( A$, X ) */
  1735. /* S$ = MID( A$, X ) */
  1736. {
  1737. /* P1ANY|P2POS */
  1738. if (a == 0)
  1739. {
  1740. /* empty string */
  1741. }
  1742. else
  1743. if (x > a)
  1744. {
  1745. /* start beyond length */
  1746. }
  1747. else
  1748. {
  1749. x--; /* BASIC to C */
  1750. a -= x; /* nummber of characters to
  1751. * copy */
  1752. A += x; /* pointer to first character
  1753. * to copy */
  1754. bwb_memcpy(S, A, a);
  1755. s = a;
  1756. }
  1757. }
  1758. break;
  1759. case F_MID4_A_X_Y_S:
  1760. case F_MID_A_X_Y_S:
  1761. case F_SEG4_A_X_Y_S:
  1762. case F_SEG_A_X_Y_S:
  1763. /* S$ = MID$( A$, X, Y ) */
  1764. /* S$ = MID( A$, X, Y ) */
  1765. /* S$ = SEG$( A$, X, Y ) */
  1766. /* S$ = SEG( A$, X, Y ) */
  1767. {
  1768. /* P1ANY|P2POS|P3LEN */
  1769. if (a == 0)
  1770. {
  1771. /* empty string */
  1772. }
  1773. else
  1774. if (x > a)
  1775. {
  1776. /* start beyond length */
  1777. }
  1778. else
  1779. if (y == 0)
  1780. {
  1781. /* empty string */
  1782. }
  1783. else
  1784. {
  1785. x--; /* BASIC to C */
  1786. a -= x;
  1787. /* maximum nummber of characters to
  1788. * copy */
  1789. a = MIN(a, y);
  1790. A += x;
  1791. /* pointer to first character to copy */
  1792. bwb_memcpy(S, A, a);
  1793. s = a;
  1794. }
  1795. }
  1796. break;
  1797. case F_LEFT4_A_X_S:
  1798. case F_LEFT_A_X_S:
  1799. /* S$ = LEFT$( A$, X ) */
  1800. /* S$ = LEFT( A$, X ) */
  1801. {
  1802. /* P1ANY|P2LEN */
  1803. if (a == 0)
  1804. {
  1805. /* empty string */
  1806. }
  1807. else
  1808. if (x == 0)
  1809. {
  1810. /* empty string */
  1811. }
  1812. else
  1813. {
  1814. a = MIN(a, x);
  1815. bwb_memcpy(S, A, a);
  1816. s = a;
  1817. }
  1818. }
  1819. break;
  1820. case F_RIGHT4_A_X_S:
  1821. case F_RIGHT_A_X_S:
  1822. /* S$ = RIGHT$( A$, X ) */
  1823. /* S$ = RIGHT( A$, X ) */
  1824. {
  1825. /* P1ANY|P2LEN */
  1826. if (a == 0)
  1827. {
  1828. /* empty string */
  1829. }
  1830. else
  1831. if (x == 0)
  1832. {
  1833. /* empty string */
  1834. }
  1835. else
  1836. {
  1837. x = MIN(a, x);
  1838. A += a;
  1839. A -= x;
  1840. bwb_memcpy(S, A, x);
  1841. s = x;
  1842. }
  1843. }
  1844. break;
  1845. case F_HEX4_X_S:
  1846. /* S$ = HEX$( X ) */
  1847. {
  1848. sprintf(S, "%X", x);
  1849. s = bwb_strlen(S);
  1850. }
  1851. break;
  1852. case F_OCT4_X_S:
  1853. /* S$ = OCT$( X ) */
  1854. {
  1855. sprintf(S, "%o", x);
  1856. s = bwb_strlen(S);
  1857. }
  1858. break;
  1859. case F_CHR_X_S:
  1860. case F_CHR4_X_S:
  1861. case F_CHAR4_X_S:
  1862. /* S$ = CHR( X ) */
  1863. /* S$ = CHR$( X ) */
  1864. /* S$ = CHAR$( X ) */
  1865. /* P1ANY */
  1866. if( My->CurrentVersion->OptionVersionBitmask & ( I70 | I73 ) )
  1867. {
  1868. /* IBM System/360 & System/370 BASIC dialects: the opposite of N = NUM( A$ ) */
  1869. BasicNumerc(X, S);
  1870. s = bwb_strlen(S);
  1871. }
  1872. else
  1873. {
  1874. if( x < 0 || x > 255 )
  1875. {
  1876. IsError = 'X';
  1877. }
  1878. else
  1879. {
  1880. S[0] = (char) x;
  1881. s = 1;
  1882. }
  1883. }
  1884. break;
  1885. case F_CHAR_X_Y_S:
  1886. /* S$ = CHAR( X, Y ) ' same as STRING$(Y,X) */
  1887. {
  1888. /* P1BYT|P2LEN */
  1889. if (y == 0)
  1890. {
  1891. /* no copies */
  1892. }
  1893. else
  1894. {
  1895. bwb_memset(S, (char) x, y);
  1896. s = y;
  1897. }
  1898. }
  1899. break;
  1900. case F_LEN_A_N:
  1901. /* N = LEN( A$ ) */
  1902. {
  1903. N = a;
  1904. }
  1905. break;
  1906. case F_POS_A_B_N:
  1907. /* N = POS( A$, B$ ) */
  1908. {
  1909. if (b == 0)
  1910. {
  1911. /* empty pattern */
  1912. N = 1;
  1913. }
  1914. else
  1915. if (a == 0)
  1916. {
  1917. /* empty searched */
  1918. }
  1919. else
  1920. if (b > a)
  1921. {
  1922. /* pattern is longer than searched */
  1923. }
  1924. else
  1925. {
  1926. /* search */
  1927. int i;
  1928. int n;
  1929. n = a - b; /* last valid search
  1930. * position */
  1931. n++;
  1932. /* search */
  1933. for (i = 0; i < n; i++)
  1934. {
  1935. if (bwb_memcmp(A, B, b) == 0)
  1936. {
  1937. /* FOU ND */
  1938. i++; /* C to BASIC */
  1939. N = i;
  1940. i = n; /* exit for */
  1941. }
  1942. A++;
  1943. }
  1944. }
  1945. }
  1946. break;
  1947. case F_MATCH_A_B_X_N:
  1948. /* N = POS( A$, B$, X ) */
  1949. {
  1950. N = str_match( A, a, B, b, x );
  1951. }
  1952. break;
  1953. case F_POS_A_B_X_N:
  1954. /* N = POS( A$, B$, X ) */
  1955. {
  1956. if (b == 0)
  1957. {
  1958. /* empty pattern */
  1959. N = 1;
  1960. }
  1961. else
  1962. if (a == 0)
  1963. {
  1964. /* empty searched */
  1965. }
  1966. else
  1967. if (b > a)
  1968. {
  1969. /* pattern is longer than searched */
  1970. }
  1971. else
  1972. {
  1973. /* search */
  1974. int i;
  1975. int n;
  1976. n = a - b; /* last valid search position */
  1977. n++;
  1978. /* search */
  1979. x--; /* BASIC to C */
  1980. A += x; /* advance to the start
  1981. * position */
  1982. for (i = x; i < n; i++)
  1983. {
  1984. if (bwb_memcmp(A, B, b) == 0)
  1985. {
  1986. /* FOU ND */
  1987. N = i + 1; /* C to BASIC */
  1988. i = n; /* exit for */
  1989. }
  1990. A++;
  1991. }
  1992. }
  1993. }
  1994. break;
  1995. case F_VAL_A_N:
  1996. case F_NUM_A_N:
  1997. /* N = VAL( A$ ) */
  1998. /* N = NUM( A$ ) */
  1999. {
  2000. /* P1ANY */
  2001. int ScanResult;
  2002. BasicNumberType Value;
  2003. ScanResult = sscanf(A, BasicNumberScanFormat, &Value);
  2004. if (ScanResult != 1)
  2005. {
  2006. /* not a number */
  2007. if (My->CurrentVersion->OptionFlags & OPTION_BUGS_ON /* VAL("X") = 0 */ )
  2008. {
  2009. /* IGNORE */
  2010. N = 0;
  2011. }
  2012. else
  2013. {
  2014. /* ERROR */
  2015. IsError = 'A';
  2016. }
  2017. }
  2018. else
  2019. {
  2020. /* OK */
  2021. N = Value;
  2022. }
  2023. }
  2024. break;
  2025. case F_STR4_X_S:
  2026. case F_NUM4_X_S:
  2027. /* S$ = STR$( X ) */
  2028. /* S$ = NUM$( X ) */
  2029. {
  2030. /* P1ANY */
  2031. BasicNumerc(X, S);
  2032. s = bwb_strlen(S);
  2033. }
  2034. break;
  2035. case F_DATE_N:
  2036. /* N = DATE ' YYYYDDD */
  2037. {
  2038. /* PNONE */
  2039. /* ECMA-116 */
  2040. time(&t);
  2041. lt = localtime(&t);
  2042. N = lt->tm_year;
  2043. N *= 1000;
  2044. N += lt->tm_yday;
  2045. N += 1;
  2046. }
  2047. break;
  2048. case F_DATE4_X_S:
  2049. case F_DATE4_S:
  2050. case F_DAT4_S:
  2051. /* S$ = DATE$( X ) ' value of X is ignored */
  2052. /* S$ = DATE$ */
  2053. /* S$ = DAT$ */
  2054. {
  2055. /* PNONE */
  2056. time(&t);
  2057. lt = localtime(&t);
  2058. s = strftime(S, BasicStringLengthMax, My->CurrentVersion->OptionDateFormat, lt);
  2059. }
  2060. break;
  2061. case F_CLK_X_S:
  2062. case F_CLK4_S:
  2063. case F_TI4_S:
  2064. case F_TIME4_S:
  2065. case F_TIME4_X_S:
  2066. /* S$ = CLK(X) ' the value of paameter X is ignored */
  2067. /* S$ = CLK$ */
  2068. /* S$ = TI$ */
  2069. /* S$ = TIME$ */
  2070. /* S$ = TIME$(X) ' the value of paameter X is ignored */
  2071. {
  2072. /* PNONE */
  2073. time(&t);
  2074. lt = localtime(&t);
  2075. s = strftime(S, BasicStringLengthMax, My->CurrentVersion->OptionTimeFormat, lt);
  2076. }
  2077. break;
  2078. case F_TI_N:
  2079. case F_TIM_N:
  2080. case F_TIME_N:
  2081. case F_TIME_X_N:
  2082. case F_TIMER_N:
  2083. /* N = TI */
  2084. /* N = TIM */
  2085. /* N = TIME */
  2086. /* N = TIME( X ) ' value of X is ignored */
  2087. /* N = TIMER */
  2088. /* N = CPU */
  2089. {
  2090. /* PNONE */
  2091. time(&t);
  2092. lt = localtime(&t);
  2093. if( My->CurrentVersion->OptionVersionBitmask & ( G67 ) )
  2094. {
  2095. N = lt->tm_hour;
  2096. N *= 60;
  2097. N += lt->tm_min;
  2098. N *= 60;
  2099. N += lt->tm_sec;
  2100. /* number of seconds since midnight */
  2101. N -= My->StartTime;
  2102. /* elapsed run time */
  2103. }
  2104. else
  2105. {
  2106. N = lt->tm_hour;
  2107. N *= 60;
  2108. N += lt->tm_min;
  2109. N *= 60;
  2110. N += lt->tm_sec;
  2111. /* number of seconds since midnight */
  2112. }
  2113. }
  2114. break;
  2115. case F_CLK_X_N:
  2116. /* N = CLK( X ) ' value of X is ignored */
  2117. {
  2118. /* PNONE */
  2119. time(&t);
  2120. lt = localtime(&t);
  2121. N = lt->tm_hour;
  2122. N *= 60;
  2123. N += lt->tm_min;
  2124. N *= 60;
  2125. N += lt->tm_sec;
  2126. N /= 3600;
  2127. /* decimal hours: 3:30 PM = 15.50 */
  2128. }
  2129. break;
  2130. case F_TIM_X_N:
  2131. /* N = TIM( X ) */
  2132. {
  2133. /* P1BYT */
  2134. time(&t);
  2135. lt = localtime(&t);
  2136. if( My->CurrentVersion->OptionVersionBitmask & (G65 | G67) )
  2137. {
  2138. /* value of 'X' is ignored */
  2139. N = lt->tm_hour;
  2140. N *= 60;
  2141. N += lt->tm_min;
  2142. N *= 60;
  2143. N += lt->tm_sec;
  2144. /* number of seconds since midnight */
  2145. N -= My->StartTime;
  2146. /* elapsed run time */
  2147. }
  2148. else
  2149. {
  2150. switch( x )
  2151. {
  2152. case 0:
  2153. /* TIM(0) == minute (0..59) */
  2154. N += lt->tm_min;
  2155. break;
  2156. case 1:
  2157. /* TIM(1) == hour (0..23) */
  2158. N = lt->tm_hour;
  2159. break;
  2160. case 2:
  2161. /* TIM(2) == day of year (1..366) */
  2162. N = 1 + lt->tm_yday;
  2163. break;
  2164. case 3:
  2165. /* TIM(3) == year since 1900 (0..) */
  2166. N = lt->tm_year;
  2167. break;
  2168. default:
  2169. IsError = 'X';
  2170. }
  2171. }
  2172. }
  2173. break;
  2174. case F_COMMAND4_X_S:
  2175. /* S$ = COMMAND$(X) */
  2176. if( x < 0 || x > 9 )
  2177. {
  2178. IsError = 'X';
  2179. }
  2180. else
  2181. {
  2182. if( My->COMMAND5[x] == NULL )
  2183. {
  2184. s = 0;
  2185. }
  2186. else
  2187. {
  2188. bwb_strcpy( S, My->COMMAND5[x] );
  2189. s = bwb_strlen( My->COMMAND5[x] );
  2190. }
  2191. }
  2192. break;
  2193. case F_COSH_X_N:
  2194. case F_CSH_X_N:
  2195. case F_HCS_X_N:
  2196. /* N = COSH( X ) */
  2197. /* N = CSH( X ) */
  2198. /* N = HCS( X ) */
  2199. {
  2200. /* P1ANY */
  2201. N = cosh(X);
  2202. }
  2203. break;
  2204. case F_SINH_X_N:
  2205. case F_SNH_X_N:
  2206. case F_HSN_X_N:
  2207. /* N = SINH( X ) */
  2208. /* N = SNH( X ) */
  2209. /* N = HSN( X ) */
  2210. {
  2211. /* P1ANY */
  2212. N = sinh(X);
  2213. }
  2214. break;
  2215. case F_TANH_X_N:
  2216. case F_HTN_X_N:
  2217. /* N = TANH( X ) */
  2218. /* N = HTN( X ) */
  2219. {
  2220. /* P1ANY */
  2221. N = tanh(X);
  2222. }
  2223. break;
  2224. case F_CLG_X_N:
  2225. case F_CLOG_X_N:
  2226. case F_LOG10_X_N:
  2227. case F_LGT_X_N:
  2228. /* N = CLG( X ) */
  2229. /* N = CLOG( X ) */
  2230. /* N = LOG10( X ) */
  2231. /* N = LGT( X ) */
  2232. {
  2233. /* P1GTZ */
  2234. N = log10(X);
  2235. }
  2236. break;
  2237. case F_SLEEP_X_N:
  2238. case F_WAIT_X_N:
  2239. case F_PAUSE_X_N:
  2240. /* N = SLEEP( X ) */
  2241. /* N = WAIT( X ) */
  2242. /* N = PAUSE( X ) */
  2243. {
  2244. /* P1ANY */
  2245. X = X * My->OptionSleepValue;
  2246. if( X <= 0 || X > SHRT_MAX)
  2247. {
  2248. /* do nothing */
  2249. }
  2250. else
  2251. {
  2252. x = (int) bwb_rint( X );
  2253. sleep(x);
  2254. }
  2255. }
  2256. break;
  2257. case F_LOG2_X_N:
  2258. case F_LTW_X_N:
  2259. /* N = LOG2( X ) */
  2260. /* N = LTW( X ) */
  2261. {
  2262. /* P1GTZ */
  2263. N = log(X) / log((BasicNumberType) 2);
  2264. }
  2265. break;
  2266. case F_ACOS_X_N:
  2267. case F_ACS_X_N:
  2268. /* N = ACOS( X ) */
  2269. /* N = ACS( X ) */
  2270. {
  2271. /* P1ANY */
  2272. if (X < -1 || X > 1)
  2273. {
  2274. IsError = 'X';
  2275. }
  2276. else
  2277. {
  2278. N = acos(X);
  2279. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  2280. {
  2281. N = FromRadiansToDegrees( N );
  2282. }
  2283. else
  2284. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  2285. {
  2286. N = FromRadiansToGradians( N );
  2287. }
  2288. }
  2289. }
  2290. break;
  2291. case F_ACSD_X_N:
  2292. /* N = ACSD( X ) */
  2293. {
  2294. /* P1ANY */
  2295. if (X < -1 || X > 1)
  2296. {
  2297. IsError = 'X';
  2298. }
  2299. else
  2300. {
  2301. N = acos(X);
  2302. /* result is always in DEGREES, regardless of OPTION ANGLE setting */
  2303. N = FromRadiansToDegrees( N );
  2304. }
  2305. }
  2306. break;
  2307. case F_ACSG_X_N:
  2308. /* N = ACSG( X ) */
  2309. {
  2310. /* P1ANY */
  2311. if (X < -1 || X > 1)
  2312. {
  2313. IsError = 'X';
  2314. }
  2315. else
  2316. {
  2317. N = acos(X);
  2318. /* result is always in GRADIANS, regardless of OPTION ANGLE setting */
  2319. N = FromRadiansToGradians( N );
  2320. }
  2321. }
  2322. break;
  2323. case F_ASIN_X_N:
  2324. case F_ASN_X_N:
  2325. case F_ARCSIN_X_N:
  2326. /* N = ASIN( X ) */
  2327. /* N = ASN( X ) */
  2328. /* N = ARCSIN( X ) */
  2329. {
  2330. /* P1ANY */
  2331. if (X < -1 || X > 1)
  2332. {
  2333. IsError = 'X';
  2334. }
  2335. else
  2336. {
  2337. N = asin(X);
  2338. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  2339. {
  2340. N = FromRadiansToDegrees( N );
  2341. }
  2342. else
  2343. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  2344. {
  2345. N = FromRadiansToGradians( N );
  2346. }
  2347. }
  2348. }
  2349. break;
  2350. case F_ASND_X_N:
  2351. /* N = ASND( X ) */
  2352. {
  2353. /* P1ANY */
  2354. if (X < -1 || X > 1)
  2355. {
  2356. IsError = 'X';
  2357. }
  2358. else
  2359. {
  2360. N = asin(X);
  2361. /* result is always in DEGREES, regardless of OPTION ANGLE setting */
  2362. N = FromRadiansToDegrees( N );
  2363. }
  2364. }
  2365. break;
  2366. case F_ASNG_X_N:
  2367. /* N = ASNG( X ) */
  2368. {
  2369. /* P1ANY */
  2370. if (X < -1 || X > 1)
  2371. {
  2372. IsError = 'X';
  2373. }
  2374. else
  2375. {
  2376. N = asin(X);
  2377. /* result is always in GRADIANS, regardless of OPTION ANGLE setting */
  2378. N = FromRadiansToGradians( N );
  2379. }
  2380. }
  2381. break;
  2382. case F_COT_X_N:
  2383. /* N = COT( X ) ' = 1 / TAN( X ) */
  2384. {
  2385. /* P1ANY */
  2386. BasicNumberType T;
  2387. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  2388. {
  2389. X = FromDegreesToRadians( X );
  2390. }
  2391. else
  2392. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  2393. {
  2394. X = FromGradiansToRadians( X );
  2395. }
  2396. T = tan(X);
  2397. if (T == 0)
  2398. {
  2399. IsError = 'X';
  2400. }
  2401. else
  2402. {
  2403. N = 1.0 / T;
  2404. }
  2405. }
  2406. break;
  2407. case F_CSC_X_N:
  2408. /* N = CSC( X ) ' = 1 / SIN( X ) */
  2409. {
  2410. /* P1ANY */
  2411. BasicNumberType T;
  2412. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  2413. {
  2414. X = FromDegreesToRadians( X );
  2415. }
  2416. else
  2417. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  2418. {
  2419. X = FromGradiansToRadians( X );
  2420. }
  2421. T = sin(X);
  2422. if (T == 0)
  2423. {
  2424. IsError = 'X';
  2425. }
  2426. else
  2427. {
  2428. N = 1.0 / T;
  2429. }
  2430. }
  2431. break;
  2432. case F_SEC_X_N:
  2433. /* N = SEC( X ) ' = 1 / COS( X ) */
  2434. {
  2435. /* P1ANY */
  2436. BasicNumberType T;
  2437. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  2438. {
  2439. X = FromDegreesToRadians( X );
  2440. }
  2441. else
  2442. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  2443. {
  2444. X = FromGradiansToRadians( X );
  2445. }
  2446. T = cos(X);
  2447. if (T == 0)
  2448. {
  2449. IsError = 'X';
  2450. }
  2451. else
  2452. {
  2453. N = 1.0 / T;
  2454. }
  2455. }
  2456. break;
  2457. case F_UCASE4_A_S:
  2458. /* S$ = UCASE$( A$ ) */
  2459. {
  2460. /* P1ANY */
  2461. if (a == 0)
  2462. {
  2463. /* empty string */
  2464. }
  2465. else
  2466. {
  2467. int i;
  2468. bwb_memcpy(S, A, a);
  2469. s = a;
  2470. /* BASIC allows embedded NULL
  2471. * characters */
  2472. for (i = 0; i < a; i++)
  2473. {
  2474. S[i] = bwb_toupper(S[i]);
  2475. }
  2476. }
  2477. }
  2478. break;
  2479. case F_LCASE4_A_S:
  2480. /* S$ = LCASE$( A$ ) */
  2481. {
  2482. /* P1ANY */
  2483. if (a == 0)
  2484. {
  2485. /* empty string */
  2486. }
  2487. else
  2488. {
  2489. int i;
  2490. bwb_memcpy(S, A, a);
  2491. s = a;
  2492. /* BASIC allows embedded NULL
  2493. * characters */
  2494. for (i = 0; i < a; i++)
  2495. {
  2496. S[i] = bwb_tolower(S[i]);
  2497. }
  2498. }
  2499. }
  2500. break;
  2501. case F_ANGLE_X_Y_N:
  2502. /* N = ANGLE( X, Y ) */
  2503. {
  2504. /* P1ANY|P2ANY */
  2505. if (X == 0 && Y == 0)
  2506. {
  2507. IsError = 'X';
  2508. }
  2509. else
  2510. {
  2511. N = atan2(Y, X);
  2512. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  2513. {
  2514. N = FromRadiansToDegrees( N );
  2515. }
  2516. else
  2517. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  2518. {
  2519. N = FromRadiansToGradians( N );
  2520. }
  2521. }
  2522. }
  2523. break;
  2524. case F_CEIL_X_N:
  2525. /* N = CEIL( X ) */
  2526. {
  2527. /* P1ANY */
  2528. N = ceil(X);
  2529. }
  2530. break;
  2531. case F_DET_N:
  2532. /* N = DET */
  2533. {
  2534. /* PNONE */
  2535. N = My->LastDeterminant;
  2536. }
  2537. break;
  2538. case F_NUM_N:
  2539. /* N = NUM */
  2540. {
  2541. /* PNONE */
  2542. N = My->LastInputCount;
  2543. }
  2544. break;
  2545. case F_DEG_N:
  2546. case F_DEGREE_N:
  2547. /* N = DEG */
  2548. /* N = DEGREE */
  2549. {
  2550. /* PNONE */
  2551. My->CurrentVersion->OptionFlags |= OPTION_ANGLE_DEGREES;
  2552. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_GRADIANS;
  2553. N = 0;
  2554. }
  2555. break;
  2556. case F_RAD_N:
  2557. case F_RADIAN_N:
  2558. /* N = RAD */
  2559. /* N = RADIAN */
  2560. {
  2561. /* PNONE */
  2562. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_DEGREES;
  2563. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_GRADIANS;
  2564. N = 0;
  2565. }
  2566. break;
  2567. case F_GRAD_N:
  2568. case F_GRADIAN_N:
  2569. /* N = GRAD */
  2570. /* N = GRADIAN */
  2571. {
  2572. /* PNONE */
  2573. My->CurrentVersion->OptionFlags &= ~OPTION_ANGLE_DEGREES;
  2574. My->CurrentVersion->OptionFlags |= OPTION_ANGLE_GRADIANS;
  2575. N = 0;
  2576. }
  2577. break;
  2578. case F_DEG_X_N:
  2579. case F_DEGREE_X_N:
  2580. /* N = DEG( X ) */
  2581. /* N = DEGREE( X ) */
  2582. {
  2583. /* P1ANY */
  2584. N = FromRadiansToDegrees( X );
  2585. }
  2586. break;
  2587. case F_RAD_X_N:
  2588. /* N = RAD( X ) */
  2589. {
  2590. /* P1ANY */
  2591. N = FromDegreesToRadians( X );
  2592. }
  2593. break;
  2594. case F_PI_N:
  2595. /* N = PI */
  2596. {
  2597. /* PNONE */
  2598. N = PI;
  2599. }
  2600. break;
  2601. case F_PI_X_N:
  2602. /* N = PI(X) */
  2603. {
  2604. /* P1ANY */
  2605. N = PI * X;
  2606. }
  2607. break;
  2608. case F_LTRIM4_A_S:
  2609. /* S$ = LTRIM$( A$ ) */
  2610. {
  2611. /* P1ANY */
  2612. if (a == 0)
  2613. {
  2614. /* empty string */
  2615. }
  2616. else
  2617. {
  2618. int i;
  2619. /* BASIC allows embedded NULL
  2620. * characters */
  2621. for (i = 0; i < a && A[i] == ' '; i++)
  2622. {
  2623. /* skip spaces */
  2624. }
  2625. /* 'A[ i ]' is first non-space
  2626. * character */
  2627. if (i >= a)
  2628. {
  2629. /* empty string */
  2630. }
  2631. else
  2632. {
  2633. A += i;
  2634. a -= i;
  2635. bwb_memcpy(S, A, a);
  2636. s = a;
  2637. }
  2638. }
  2639. }
  2640. break;
  2641. case F_RTRIM4_A_S:
  2642. /* S$ = RTRIM$( A$ ) */
  2643. {
  2644. /* P1ANY */
  2645. if (a == 0)
  2646. {
  2647. /* empty string */
  2648. }
  2649. else
  2650. {
  2651. int i;
  2652. /* BASIC allows embedded NULL
  2653. * characters */
  2654. for (i = a - 1; i >= 0 && A[i] == ' '; i--)
  2655. {
  2656. /* skip spaces */
  2657. }
  2658. /* 'A[ i ]' is last non-space
  2659. * character */
  2660. if (i < 0)
  2661. {
  2662. /* empty string */
  2663. }
  2664. else
  2665. {
  2666. a = i + 1;
  2667. bwb_memcpy(S, A, a);
  2668. s = a;
  2669. }
  2670. }
  2671. }
  2672. break;
  2673. case F_TRIM4_A_S:
  2674. /* S$ = TRIM$( A$ ) */
  2675. {
  2676. /* P1ANY */
  2677. if (a == 0)
  2678. {
  2679. /* empty string */
  2680. }
  2681. else
  2682. {
  2683. /* LTRIM */
  2684. int i;
  2685. /* BASIC allows embedded NULL
  2686. * characters */
  2687. for (i = 0; i < a && A[i] == ' '; i++)
  2688. {
  2689. /* skip spaces */
  2690. }
  2691. /* 'A[ i ]' is first non-space
  2692. * character */
  2693. if (i >= a)
  2694. {
  2695. /* empty string */
  2696. }
  2697. else
  2698. {
  2699. A += i;
  2700. a -= i;
  2701. bwb_memcpy(S, A, a);
  2702. s = a;
  2703. /* RTRIM */
  2704. A = S;
  2705. a = s;
  2706. if (a == 0)
  2707. {
  2708. /* empty string */
  2709. }
  2710. else
  2711. {
  2712. int i;
  2713. /* BASIC allows
  2714. * embedded NULL
  2715. * characters */
  2716. for (i = a - 1; i >= 0 && A[i] == ' '; i--)
  2717. {
  2718. /* skip
  2719. * spaces */
  2720. }
  2721. /* 'A[ i ]' is last
  2722. * non-space
  2723. * character */
  2724. if (i < 0)
  2725. {
  2726. /* empty
  2727. * string */
  2728. }
  2729. else
  2730. {
  2731. a = i + 1;
  2732. /* bwb_memcpy( S,
  2733. * A, a ); */
  2734. s = a;
  2735. }
  2736. }
  2737. }
  2738. }
  2739. }
  2740. break;
  2741. case F_MAX_X_Y_N:
  2742. /* N = MAX( X, Y ) */
  2743. {
  2744. N = MAX(X, Y);
  2745. }
  2746. break;
  2747. case F_MAX_A_B_S:
  2748. /* S$ = MAX( A$, B$ ) */
  2749. {
  2750. StringType L;
  2751. StringType R;
  2752. L.length = a;
  2753. R.length = b;
  2754. L.sbuffer = A;
  2755. R.sbuffer = B;
  2756. if( str_cmp( &L, &R ) >= 0 )
  2757. {
  2758. /* A >= B */
  2759. bwb_memcpy( S, A, a );
  2760. s = a;
  2761. }
  2762. else
  2763. {
  2764. /* A < B */
  2765. bwb_memcpy( S, B, b );
  2766. s = b;
  2767. }
  2768. }
  2769. break;
  2770. case F_MIN_X_Y_N:
  2771. /* N = MIN( X, Y ) */
  2772. {
  2773. N = MIN(X, Y);
  2774. }
  2775. break;
  2776. case F_MIN_A_B_S:
  2777. /* S$ = MIN( A$, B$ ) */
  2778. {
  2779. StringType L;
  2780. StringType R;
  2781. L.length = a;
  2782. R.length = b;
  2783. L.sbuffer = A;
  2784. R.sbuffer = B;
  2785. if( str_cmp( &L, &R ) <= 0 )
  2786. {
  2787. /* A <= B */
  2788. bwb_memcpy( S, A, a );
  2789. s = a;
  2790. }
  2791. else
  2792. {
  2793. /* A > B */
  2794. bwb_memcpy( S, B, b );
  2795. s = b;
  2796. }
  2797. }
  2798. break;
  2799. case F_FP_X_N:
  2800. case F_FRAC_X_N:
  2801. /* N = FP( X ) */
  2802. /* N = FRAC( X ) */
  2803. {
  2804. BasicNumberType FP;
  2805. BasicNumberType IP;
  2806. FP = modf(X, &IP);
  2807. N = FP;
  2808. }
  2809. break;
  2810. case F_IP_X_N:
  2811. /* N = IP( X ) */
  2812. {
  2813. BasicNumberType IP;
  2814. modf(X, &IP);
  2815. N = IP;
  2816. }
  2817. break;
  2818. case F_EPS_X_N:
  2819. /* N = EPS( Number ) */
  2820. {
  2821. N = DBL_MIN;
  2822. }
  2823. break;
  2824. case F_MAXLVL_N:
  2825. /* N = MAXLVL */
  2826. {
  2827. N = EXECLEVELS;
  2828. }
  2829. break;
  2830. case F_MAXNUM_N:
  2831. /* N = MAXNUM */
  2832. {
  2833. N = DBL_MAX;
  2834. }
  2835. break;
  2836. case F_MINNUM_N:
  2837. /* N = MINNUM */
  2838. {
  2839. N = -DBL_MAX;
  2840. }
  2841. break;
  2842. case F_MAXDBL_N:
  2843. /* N = MAXDBL */
  2844. {
  2845. N = DBL_MAX;
  2846. }
  2847. break;
  2848. case F_MINDBL_N:
  2849. /* N = MINDBL */
  2850. {
  2851. N = -DBL_MAX;
  2852. }
  2853. break;
  2854. case F_MAXSNG_N:
  2855. /* N = MAXSNG */
  2856. {
  2857. N = FLT_MAX;
  2858. }
  2859. break;
  2860. case F_MINSNG_N:
  2861. /* N = MINSNG */
  2862. {
  2863. N = -FLT_MAX;
  2864. }
  2865. break;
  2866. case F_MAXCUR_N:
  2867. /* N = MAXCUR */
  2868. {
  2869. N = LONG_MAX;
  2870. }
  2871. break;
  2872. case F_MINCUR_N:
  2873. /* N = MINCUR */
  2874. {
  2875. N = LONG_MIN;
  2876. }
  2877. break;
  2878. case F_MAXLNG_N:
  2879. /* N = MAXLNG */
  2880. {
  2881. N = LONG_MAX;
  2882. }
  2883. break;
  2884. case F_MINLNG_N:
  2885. /* N = MINLNG */
  2886. {
  2887. N = LONG_MIN;
  2888. }
  2889. break;
  2890. case F_MAXINT_N:
  2891. /* N = MAXINT */
  2892. {
  2893. N = SHRT_MAX;
  2894. }
  2895. break;
  2896. case F_MININT_N:
  2897. /* N = MININT */
  2898. {
  2899. N = SHRT_MIN;
  2900. }
  2901. break;
  2902. case F_MAXBYT_N:
  2903. /* N = MAXBYT */
  2904. {
  2905. N = UCHAR_MAX;
  2906. }
  2907. break;
  2908. case F_MINBYT_N:
  2909. /* N = MINBYT */
  2910. {
  2911. N = 0;
  2912. }
  2913. break;
  2914. case F_MAXDEV_N:
  2915. /* N = MAXDEV */
  2916. {
  2917. N = BasicFileNumberMax;
  2918. }
  2919. break;
  2920. case F_MINDEV_N:
  2921. /* N = MINDEV */
  2922. {
  2923. N = 0;
  2924. }
  2925. break;
  2926. case F_MOD_X_Y_N:
  2927. /* N = MOD( X, Y ) */
  2928. {
  2929. /* P1ANY|P2NEZ */
  2930. BasicNumberType IP;
  2931. IP = floor(X / Y);
  2932. N = X - (Y * IP);
  2933. }
  2934. break;
  2935. case F_REMAINDER_X_Y_N:
  2936. /* REMAINDER( X, Y ) */
  2937. {
  2938. /* P1ANY|P2NEZ */
  2939. BasicNumberType Value;
  2940. BasicNumberType IP;
  2941. Value = X / Y;
  2942. modf(Value, &IP);
  2943. N = X - (Y * IP);
  2944. }
  2945. break;
  2946. case F_ROUND_X_Y_N:
  2947. /* N = ROUND( X, Y ) == INT(X*10^Y+.5)/10^Y */
  2948. {
  2949. /* P1ANY | P2INT */
  2950. if (y < -32 || y > 32)
  2951. {
  2952. IsError = 'Y';
  2953. }
  2954. else
  2955. {
  2956. BasicNumberType T; /* 10^Y */
  2957. T = pow(10.0, Y);
  2958. if (T == 0)
  2959. {
  2960. IsError = 'Y';
  2961. }
  2962. else
  2963. {
  2964. N = floor(X * T + 0.5) / T;
  2965. }
  2966. }
  2967. }
  2968. break;
  2969. case F_TRUNCATE_X_Y_N:
  2970. /* N = TRUNCATE( X, Y ) == INT(X*10^Y)/10^Y */
  2971. {
  2972. /* P1ANY | P2INT */
  2973. if (y < -32 || y > 32)
  2974. {
  2975. IsError = 'Y';
  2976. }
  2977. else
  2978. {
  2979. BasicNumberType T; /* 10^Y */
  2980. T = pow(10.0, Y);
  2981. if (T == 0)
  2982. {
  2983. IsError = 'Y';
  2984. }
  2985. else
  2986. {
  2987. N = floor(X * T) / T;
  2988. }
  2989. }
  2990. }
  2991. break;
  2992. case F_MAXLEN_A_N:
  2993. /* N = MAXLEN( A$ ) */
  2994. {
  2995. N = BasicStringLengthMax;
  2996. }
  2997. break;
  2998. case F_ORD_A_N:
  2999. /* N = ORD( A$ ) */
  3000. {
  3001. /* P1BYT */
  3002. if (a == 1)
  3003. {
  3004. /* same as ASC(A$) */
  3005. N = A[0];
  3006. }
  3007. else
  3008. {
  3009. /* lookup Acronym */
  3010. int c;
  3011. N = -1; /* not found */
  3012. for (c = 0; c < NUM_ACRONYMS; c++)
  3013. {
  3014. if (bwb_stricmp(AcronymTable[c].Name, A) == 0)
  3015. {
  3016. /* found */
  3017. N = AcronymTable[c].Value;
  3018. c = NUM_ACRONYMS; /* exit for */
  3019. }
  3020. }
  3021. if (N < 0)
  3022. {
  3023. /* not found */
  3024. IsError = 'A';
  3025. }
  3026. }
  3027. }
  3028. break;
  3029. case F_RENAME_A_B_N:
  3030. /* N = RENAME( A$, B$ ) */
  3031. {
  3032. /* P1BYT | P2BYT */
  3033. if( My->CurrentVersion->OptionVersionBitmask & ( C77 ) )
  3034. {
  3035. strupper( A ); /* CBASIC-II: file names are always upper case */
  3036. strupper( B ); /* CBASIC-II: file names are always upper case */
  3037. }
  3038. if( rename( A, B ) )
  3039. {
  3040. /* ERROR -- return FALSE */
  3041. N = 0;
  3042. }
  3043. else
  3044. {
  3045. /* OK -- return TRUE */
  3046. N = -1;
  3047. }
  3048. }
  3049. break;
  3050. case F_SIZE_A_N:
  3051. /* N = SIZE( A$ ) */
  3052. {
  3053. /* P1BYT */
  3054. FILE * F;
  3055. if( My->CurrentVersion->OptionVersionBitmask & ( C77 ) )
  3056. {
  3057. strupper( A ); /* CBASIC-II: file names are always upper case */
  3058. }
  3059. F = fopen( A, "rb" );
  3060. if( F != NULL )
  3061. {
  3062. long n;
  3063. fseek( F, 0, SEEK_END );
  3064. n = ftell( F );
  3065. fclose( F );
  3066. if( n > 0 )
  3067. {
  3068. /* round up filesize to next whole kilobyte */
  3069. n += 1023;
  3070. n /= 1024;
  3071. }
  3072. else
  3073. {
  3074. /* a zero-length file returns 0 */
  3075. n = 0;
  3076. }
  3077. N = n;
  3078. }
  3079. /* a non-existing file returns 0 */
  3080. }
  3081. break;
  3082. case F_REPEAT4_X_Y_S:
  3083. /* S$ = REPEAT$( X, Y ) ' X is count, Y is code */
  3084. {
  3085. /* P1LEN | P2BYT */
  3086. if (x == 0)
  3087. {
  3088. /* empty string */
  3089. }
  3090. else
  3091. {
  3092. bwb_memset(S, (char) y, x);
  3093. s = x;
  3094. }
  3095. }
  3096. break;
  3097. case F_REPEAT4_X_A_S:
  3098. /* S$ = REPEAT$( X, A$ ) ' X is count, A$ is code */
  3099. {
  3100. /* P1LEN | P2BYT */
  3101. if (x == 0)
  3102. {
  3103. /* empty string */
  3104. }
  3105. else
  3106. {
  3107. bwb_memset(S, (char) A[0], x);
  3108. s = x;
  3109. }
  3110. }
  3111. break;
  3112. case F_FIX_X_N:
  3113. /* N = FIX( X ) */
  3114. {
  3115. /* N = bwb_rint(X); */
  3116. if( X < 0 )
  3117. {
  3118. N = -floor(-X);
  3119. }
  3120. else
  3121. {
  3122. N = floor(X);
  3123. }
  3124. }
  3125. break;
  3126. case F_ABS_X_N:
  3127. /* N = ABS( X ) */
  3128. {
  3129. N = fabs(X);
  3130. }
  3131. break;
  3132. case F_ATN_X_N:
  3133. case F_ATAN_X_N:
  3134. case F_ARCTAN_X_N:
  3135. /* N = ATN( X ) */
  3136. /* N = ATAN( X ) */
  3137. /* N = ARCTAN( X ) */
  3138. {
  3139. N = atan(X);
  3140. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  3141. {
  3142. N = FromRadiansToDegrees( N );
  3143. }
  3144. else
  3145. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  3146. {
  3147. N = FromRadiansToGradians( N );
  3148. }
  3149. }
  3150. break;
  3151. case F_ATND_X_N:
  3152. /* N = ATND( X ) */
  3153. {
  3154. N = atan(X);
  3155. N = FromRadiansToDegrees( N );
  3156. }
  3157. break;
  3158. case F_ATNG_X_N:
  3159. /* N = ATNG( X ) */
  3160. {
  3161. N = atan(X);
  3162. N = FromRadiansToGradians( N );
  3163. }
  3164. break;
  3165. case F_COS_X_N:
  3166. /* N = COS( X ) */
  3167. {
  3168. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  3169. {
  3170. X = FromDegreesToRadians( X );
  3171. }
  3172. else
  3173. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  3174. {
  3175. X = FromGradiansToRadians( X );
  3176. }
  3177. N = cos(X);
  3178. }
  3179. break;
  3180. case F_COSD_X_N:
  3181. /* N = COSD( X ) */
  3182. {
  3183. X = FromDegreesToRadians( X );
  3184. N = cos(X);
  3185. }
  3186. break;
  3187. case F_COSG_X_N:
  3188. /* N = COSG( X ) */
  3189. {
  3190. X = FromGradiansToRadians( X );
  3191. N = cos(X);
  3192. }
  3193. break;
  3194. case F_EXP_X_N:
  3195. /* N = EXP( X ) */
  3196. {
  3197. N = exp(X);
  3198. }
  3199. break;
  3200. case F_INT_X_N:
  3201. /* N = INT( X ) */
  3202. {
  3203. N = floor(X);
  3204. }
  3205. break;
  3206. case F_FLOAT_X_N:
  3207. case F_INT5_X_N:
  3208. /* N = FLOAT( X ) */
  3209. /* N = INT%( X ) */
  3210. {
  3211. N = bwb_rint(X);
  3212. }
  3213. break;
  3214. case F_INITIALIZE_N:
  3215. /* INITIALIZE */
  3216. {
  3217. N = 0;
  3218. }
  3219. break;
  3220. case F_LOG_X_N:
  3221. case F_LN_X_N:
  3222. case F_LOGE_X_N:
  3223. /* N = LOG( X ) */
  3224. /* N = LN( X ) */
  3225. /* N = LOGE( X ) */
  3226. {
  3227. /* P1GTZ */
  3228. N = log(X);
  3229. }
  3230. break;
  3231. case F_RND_N:
  3232. /* N = RND */
  3233. {
  3234. N = rand();
  3235. N /= RAND_MAX;
  3236. }
  3237. break;
  3238. case F_RND_X_N:
  3239. /* N = RND( X ) */
  3240. {
  3241. N = rand();
  3242. N /= RAND_MAX;
  3243. }
  3244. break;
  3245. case F_SGN_X_N:
  3246. /* N = SGN( X ) */
  3247. {
  3248. if (X > 0)
  3249. {
  3250. N = 1;
  3251. }
  3252. else
  3253. if (X < 0)
  3254. {
  3255. N = -1;
  3256. }
  3257. else
  3258. {
  3259. N = 0;
  3260. }
  3261. }
  3262. break;
  3263. case F_SIN_X_N:
  3264. /* N = SIN( X ) */
  3265. {
  3266. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  3267. {
  3268. X = FromDegreesToRadians( X );
  3269. }
  3270. else
  3271. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  3272. {
  3273. X = FromGradiansToRadians( X );
  3274. }
  3275. N = sin(X);
  3276. }
  3277. break;
  3278. case F_SIND_X_N:
  3279. /* N = SIND( X ) */
  3280. {
  3281. X = FromDegreesToRadians( X );
  3282. N = sin(X);
  3283. }
  3284. break;
  3285. case F_SING_X_N:
  3286. /* N = SING( X ) */
  3287. {
  3288. X = FromGradiansToRadians( X );
  3289. N = sin(X);
  3290. }
  3291. break;
  3292. case F_SQR_X_N:
  3293. case F_SQRT_X_N:
  3294. /* N = SQR( X ) */
  3295. /* N = SQRT( X ) */
  3296. {
  3297. /* P1GEZ */
  3298. N = sqrt(X);
  3299. }
  3300. break;
  3301. case F_TAN_X_N:
  3302. /* N = TAN( X ) */
  3303. {
  3304. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_DEGREES)
  3305. {
  3306. X = FromDegreesToRadians( X );
  3307. }
  3308. else
  3309. if (My->CurrentVersion->OptionFlags & OPTION_ANGLE_GRADIANS)
  3310. {
  3311. X = FromGradiansToRadians( X );
  3312. }
  3313. N = tan(X);
  3314. }
  3315. break;
  3316. case F_TAND_X_N:
  3317. /* N = TAND( X ) */
  3318. {
  3319. X = FromDegreesToRadians( X );
  3320. N = tan(X);
  3321. }
  3322. break;
  3323. case F_TANG_X_N:
  3324. /* N = TANG( X ) */
  3325. {
  3326. X = FromGradiansToRadians( X );
  3327. N = tan(X);
  3328. }
  3329. break;
  3330. case F_SPC_X_S:
  3331. /* S$ = SPC( X ) */
  3332. {
  3333. /* P1ANY */
  3334. /* SPECIAL RULES APPLY. PART OF PRINT COMMAND. WIDTH > 0 */
  3335. X = bwb_rint(X);
  3336. if (X < 1 || X > 255)
  3337. {
  3338. if( bwb_Warning_Overflow("*** WARNING: INVALID SPC() ***") )
  3339. {
  3340. /* ERROR */
  3341. }
  3342. /* CONTINUE */
  3343. X = 1;
  3344. }
  3345. x = (int) X;
  3346. S[0] = PRN_SPC;
  3347. S[1] = (char) x;
  3348. s = 2;
  3349. }
  3350. break;
  3351. case F_TAB_X_S:
  3352. /* S$ = TAB( X ) */
  3353. {
  3354. /* P1ANY */
  3355. /* SPECIAL RULES APPLY. PART OF PRINT COMMAND. WIDTH > 0 */
  3356. X = bwb_rint(X);
  3357. if (X < 1 || X > 255)
  3358. {
  3359. if( bwb_Warning_Overflow("*** WARNING: INVALID TAB() ***") )
  3360. {
  3361. /* ERROR */
  3362. }
  3363. /* CONTINUE */
  3364. X = 1;
  3365. }
  3366. x = (int) X;
  3367. S[0] = PRN_TAB;
  3368. S[1] = (char) x;
  3369. s = 2;
  3370. }
  3371. break;
  3372. case F_POS_N:
  3373. /* N = POS */
  3374. {
  3375. /* PNONE */
  3376. N = My->SYSOUT->col;
  3377. }
  3378. break;
  3379. case F_COUNT_N:
  3380. /* N = COUNT */
  3381. /* COUNT = POS - 1 */
  3382. {
  3383. /* PNONE */
  3384. N = My->SYSOUT->col;
  3385. N--;
  3386. }
  3387. break;
  3388. case F_POS_X_N:
  3389. /* N = POS( X ) */
  3390. {
  3391. /* P1DEV */
  3392. if( x == 0 )
  3393. {
  3394. N = My->SYSOUT->col;
  3395. }
  3396. else
  3397. if( x < 0 )
  3398. {
  3399. N = My->SYSPRN->col;
  3400. }
  3401. else
  3402. {
  3403. FileType * F;
  3404. F = find_file_by_number( x );
  3405. if( F == NULL )
  3406. {
  3407. IsError = 'X';
  3408. }
  3409. else
  3410. {
  3411. N = F->col;
  3412. }
  3413. }
  3414. }
  3415. break;
  3416. case F_INPUT4_X_Y_S:
  3417. /* S$ = INPUT$( X, Y ) */
  3418. {
  3419. /* P1LEN|P2DEV */
  3420. if( y <= 0 )
  3421. {
  3422. IsError = 'Y';
  3423. }
  3424. else
  3425. {
  3426. FileType * F;
  3427. F = find_file_by_number( y );
  3428. if( F == NULL )
  3429. {
  3430. IsError = 'Y';
  3431. }
  3432. else
  3433. {
  3434. if ((F->mode & DEVMODE_READ) == 0)
  3435. {
  3436. IsError = 'Y';
  3437. }
  3438. else
  3439. if (x == 0)
  3440. {
  3441. /* empty string */
  3442. }
  3443. else
  3444. {
  3445. FILE *fp;
  3446. fp = F->cfp;
  3447. if (fp == NULL)
  3448. {
  3449. IsError = 'Y';
  3450. }
  3451. else
  3452. {
  3453. s = fread(S, 1, x, fp);
  3454. s = MAX(s, 0); /* if( s < 0 ) s = 0; */
  3455. }
  3456. }
  3457. }
  3458. }
  3459. }
  3460. break;
  3461. case F_ERROR_X_N:
  3462. /* ERROR X */
  3463. {
  3464. /* P1BYT */
  3465. bwb_Warning(x, "");
  3466. N = 0;
  3467. }
  3468. break;
  3469. case F_ERROR_X_A_N:
  3470. /* ERROR X, A$ */
  3471. {
  3472. /* P1BYT */
  3473. bwb_Warning(x, A);
  3474. N = 0;
  3475. }
  3476. break;
  3477. case F_ERR_N:
  3478. case F_ERRN_N:
  3479. /* N = ERR */
  3480. /* N = ERRN */
  3481. {
  3482. /* PNONE */
  3483. N = My->err_number;
  3484. }
  3485. break;
  3486. case F_ERL_N:
  3487. case F_ERRL_N:
  3488. /* N = ERL */
  3489. /* N = ERRL */
  3490. {
  3491. /* PNONE */
  3492. if( My->err_line != NULL )
  3493. {
  3494. N = My->err_line->number;
  3495. }
  3496. }
  3497. break;
  3498. case F_ERR4_S:
  3499. case F_ERROR4_S:
  3500. /* S = ERR$ */
  3501. /* S = ERROR$ */
  3502. {
  3503. /* PNONE */
  3504. s = bwb_strlen(My->ErrMsg);
  3505. if (s > 0)
  3506. {
  3507. bwb_strcpy(S, My->ErrMsg);
  3508. }
  3509. }
  3510. break;
  3511. /********************************************************************************************
  3512. ** Keep the platform specific functions together.
  3513. *********************************************************************************************/
  3514. case F_INP_X_N:
  3515. case F_PIN_X_N:
  3516. /* N = INP( X ) */
  3517. /* N = PIN( X ) */
  3518. {
  3519. /* P1BYT */
  3520. IsError = 0xFF;
  3521. }
  3522. break;
  3523. case F_PDL_X_N:
  3524. /* N = PDL( X ) */
  3525. {
  3526. /* P1BYT */
  3527. IsError = 0xFF;
  3528. }
  3529. break;
  3530. case F_WAIT_X_Y_N:
  3531. /* WAIT X, Y */
  3532. {
  3533. /* P1NUM|P2NUM */
  3534. /* P1INT|P2BYT */
  3535. IsError = 0xFF;
  3536. }
  3537. break;
  3538. case F_WAIT_X_Y_Z_N:
  3539. /* WAIT X, Y, Z */
  3540. {
  3541. /* P1NUM|P2NUM|P3NUM */
  3542. /* P1INT|P2BYT|P3BYT */
  3543. IsError = 0xFF;
  3544. }
  3545. break;
  3546. case F_OUT_X_Y_N:
  3547. /* OUT X, Y */
  3548. {
  3549. /* P1NUM|P2NUM */
  3550. /* P1INT|P2BYT */
  3551. IsError = 0xFF;
  3552. }
  3553. break;
  3554. case F_PEEK_X_N:
  3555. case F_EXAM_X_N:
  3556. case F_FETCH_X_N:
  3557. /* N = PEEK( X ) */
  3558. /* N = EXAM( X ) */
  3559. /* N = FETCH( X ) */
  3560. {
  3561. /* P1INT */
  3562. IsError = 0xFF;
  3563. }
  3564. break;
  3565. case F_POKE_X_Y_N:
  3566. case F_FILL_X_Y_N:
  3567. case F_STUFF_X_Y_N:
  3568. /* POKE X, Y */
  3569. /* FILL X, Y */
  3570. /* STUFF X, Y */
  3571. {
  3572. /* P1NUM|P2NUM */
  3573. /* P1INT|P2BYT */
  3574. IsError = 0xFF;
  3575. }
  3576. break;
  3577. case F_CLS_N:
  3578. case F_HOME_N:
  3579. /* CLS */
  3580. /* HOME */
  3581. {
  3582. /* PNONE */
  3583. switch (My->OptionTerminalType)
  3584. {
  3585. case C_OPTION_TERMINAL_NONE:
  3586. break;
  3587. case C_OPTION_TERMINAL_ADM:
  3588. fprintf(My->SYSOUT->cfp, "%c", 26);
  3589. break;
  3590. case C_OPTION_TERMINAL_ANSI:
  3591. fprintf(My->SYSOUT->cfp, "%c[2J", 27);
  3592. fprintf(My->SYSOUT->cfp, "%c[%d;%dH", 27, 1, 1);
  3593. break;
  3594. default:
  3595. IsError = 0xFF;
  3596. break;
  3597. }
  3598. fflush(My->SYSOUT->cfp);
  3599. }
  3600. break;
  3601. case F_LOCATE_X_Y_N:
  3602. /* LOCATE X, Y */
  3603. {
  3604. /* P1NUM|P2NUM */
  3605. /* P1BYT|P2BYT */
  3606. /* X is 1 based */
  3607. /* Y is 1 based */
  3608. switch (My->OptionTerminalType)
  3609. {
  3610. case C_OPTION_TERMINAL_NONE:
  3611. break;
  3612. case C_OPTION_TERMINAL_ADM:
  3613. fprintf(My->SYSOUT->cfp, "%c=%c%c", 27, x + 32, y + 32);
  3614. break;
  3615. case C_OPTION_TERMINAL_ANSI:
  3616. fprintf(My->SYSOUT->cfp, "%c[%d;%dH", 27, x, y);
  3617. break;
  3618. default:
  3619. IsError = 0xFF;
  3620. break;
  3621. }
  3622. fflush(My->SYSOUT->cfp);
  3623. }
  3624. break;
  3625. case F_CUR_X_Y_S:
  3626. /* CUR X, Y */
  3627. {
  3628. /* P1NUM|P2NUM */
  3629. /* P1BYT|P2BYT */
  3630. x++; /* X is 0 based */
  3631. y++; /* Y is 0 based */
  3632. switch (My->OptionTerminalType)
  3633. {
  3634. case C_OPTION_TERMINAL_NONE:
  3635. break;
  3636. case C_OPTION_TERMINAL_ADM:
  3637. fprintf(My->SYSOUT->cfp, "%c=%c%c", 27, x + 32, y + 32);
  3638. break;
  3639. case C_OPTION_TERMINAL_ANSI:
  3640. fprintf(My->SYSOUT->cfp, "%c[%d;%dH", 27, x, y);
  3641. break;
  3642. default:
  3643. IsError = 0xFF;
  3644. break;
  3645. }
  3646. fflush(My->SYSOUT->cfp);
  3647. s = 0;
  3648. }
  3649. break;
  3650. case F_VTAB_X_N:
  3651. /* VTAB X */
  3652. {
  3653. /* P1BYT */
  3654. switch (My->OptionTerminalType)
  3655. {
  3656. case C_OPTION_TERMINAL_NONE:
  3657. break;
  3658. case C_OPTION_TERMINAL_ADM:
  3659. fprintf(My->SYSOUT->cfp, "%c=%c%c", 27, x + 32, 1 + 32);
  3660. break;
  3661. case C_OPTION_TERMINAL_ANSI:
  3662. fprintf(My->SYSOUT->cfp, "%c[%d;%dH", 27, x, 1);
  3663. break;
  3664. default:
  3665. IsError = 0xFF;
  3666. break;
  3667. }
  3668. fflush(My->SYSOUT->cfp);
  3669. }
  3670. break;
  3671. case F_COLOR_X_Y_N:
  3672. /* COLOR X, Y */
  3673. {
  3674. /* P1NUM|P2NUM */
  3675. /* P1BYT|P2BYT */
  3676. switch (My->OptionTerminalType)
  3677. {
  3678. case C_OPTION_TERMINAL_NONE:
  3679. break;
  3680. case C_OPTION_TERMINAL_ADM:
  3681. break;
  3682. case C_OPTION_TERMINAL_ANSI:
  3683. fprintf(My->SYSOUT->cfp, "%c[%d;%dm", 27, 30 + x, 40 + y);
  3684. break;
  3685. default:
  3686. IsError = 0xFF;
  3687. break;
  3688. }
  3689. fflush(My->SYSOUT->cfp);
  3690. }
  3691. break;
  3692. case F_FILES_N:
  3693. case F_CATALOG_N:
  3694. /* FILES */
  3695. /* CATALOG */
  3696. {
  3697. /* PNONE */
  3698. VariableType *v;
  3699. char Buffer[BasicStringLengthMax + 1];
  3700. if( (v = var_find(DEFVNAME_FILES,0,FALSE)) == NULL )
  3701. {
  3702. bwb_strcpy(Buffer, DEF_FILES);
  3703. }
  3704. else
  3705. {
  3706. VariantType variant;
  3707. if( var_get( v, &variant ) == FALSE )
  3708. {
  3709. bwb_strcpy( Buffer, DEF_FILES );
  3710. }
  3711. else
  3712. {
  3713. if( variant.TypeChar == '$' )
  3714. {
  3715. bwb_strcpy( Buffer, variant.Buffer );
  3716. RELEASE( (&variant) );
  3717. }
  3718. else
  3719. {
  3720. bwb_strcpy( Buffer, DEF_FILES );
  3721. }
  3722. }
  3723. }
  3724. N = system( Buffer );
  3725. }
  3726. break;
  3727. case F_FILES_A_N:
  3728. case F_CATALOG_A_N:
  3729. /* FILES A$ */
  3730. /* CATALOG A$ */
  3731. {
  3732. /* P1BYT */
  3733. VariableType *v;
  3734. char Buffer[BasicStringLengthMax + 1];
  3735. if( (v = var_find(DEFVNAME_FILES,0,FALSE)) == NULL )
  3736. {
  3737. bwb_strcpy(Buffer, DEF_FILES);
  3738. }
  3739. else
  3740. {
  3741. VariantType variant;
  3742. if( var_get( v, &variant ) == FALSE )
  3743. {
  3744. bwb_strcpy( Buffer, DEF_FILES );
  3745. }
  3746. else
  3747. {
  3748. if( variant.TypeChar == '$' )
  3749. {
  3750. bwb_strcpy( Buffer, variant.Buffer );
  3751. RELEASE( (&variant) );
  3752. }
  3753. else
  3754. {
  3755. bwb_strcpy( Buffer, DEF_FILES );
  3756. }
  3757. }
  3758. }
  3759. bwb_strcat(Buffer, " ");
  3760. bwb_strcat(Buffer, A);
  3761. N = system(Buffer);
  3762. }
  3763. break;
  3764. case F_FRE_N:
  3765. case F_FRE_X_N:
  3766. case F_FRE_A_N:
  3767. case F_FREE_N:
  3768. case F_FREE_X_N:
  3769. case F_FREE_A_N:
  3770. case F_MEM_N:
  3771. case F_TOP_N:
  3772. /* N = FRE( ) */
  3773. /* N = FRE( X ) */
  3774. /* N = FRE( X$ ) */
  3775. /* N = FREE( ) */
  3776. /* N = FREE( X ) */
  3777. /* N = FREE( X$ ) */
  3778. /* N = MEM( ) */
  3779. /* N = TOP( ) */
  3780. {
  3781. N = 32000; /* reasonable value */
  3782. }
  3783. break;
  3784. case F_SHELL_A_N:
  3785. /* N = SHELL( A$ ) */
  3786. {
  3787. /* P1BYT */
  3788. N = system(A);
  3789. }
  3790. break;
  3791. case F_CHDIR_A_N:
  3792. /* CHDIR A$ */
  3793. {
  3794. /* P1BYT */
  3795. #if DIRECTORY_CMDS
  3796. N = chdir(A);
  3797. #else
  3798. IsError = 0xFF;
  3799. #endif
  3800. }
  3801. break;
  3802. case F_MKDIR_A_N:
  3803. /* MKDIR A$ */
  3804. {
  3805. /* P1BYT */
  3806. #if DIRECTORY_CMDS
  3807. #if MKDIR_ONE_ARG
  3808. N = mkdir(A);
  3809. #else
  3810. N = mkdir(A, PERMISSIONS);
  3811. #endif
  3812. #else
  3813. IsError = 0xFF;
  3814. #endif
  3815. }
  3816. break;
  3817. case F_RMDIR_A_N:
  3818. /* RMDIR A$ */
  3819. {
  3820. /* P1BYT */
  3821. #if DIRECTORY_CMDS
  3822. N = rmdir(A);
  3823. #else
  3824. IsError = 0xFF;
  3825. #endif
  3826. }
  3827. break;
  3828. case F_KILL_A_N:
  3829. case F_UNSAVE_A_N:
  3830. /* KILL A$ */
  3831. /* UNSAVE A$ */
  3832. {
  3833. /* P1BYT */
  3834. N = remove(A);
  3835. }
  3836. break;
  3837. case F_NAME_A_B_N:
  3838. /* NAME A$ AS B$ */
  3839. /* N = NAME( A$, B$ ) */
  3840. {
  3841. /* P1BYT|P2BYT */
  3842. N = rename(A, B);
  3843. }
  3844. break;
  3845. case F_INPUT4_X_S:
  3846. /* S$ = INPUT$( X ) */
  3847. {
  3848. /* P1LEN */
  3849. if (x == 0)
  3850. {
  3851. /* empty string */
  3852. }
  3853. else
  3854. {
  3855. for (s = 0; s < x; s++)
  3856. {
  3857. int c;
  3858. c = fgetc( My->SYSIN->cfp );
  3859. if ((c == EOF) || (c == '\n') || (c == '\r'))
  3860. {
  3861. break;
  3862. }
  3863. S[s] = c;
  3864. }
  3865. S[s] = 0;
  3866. }
  3867. }
  3868. break;
  3869. case F_INKEY4_S:
  3870. case F_KEY4_S:
  3871. case F_KEY_S:
  3872. /* S$ = INKEY$ */
  3873. /* S$ = KEY$ */
  3874. /* S$ = KEY */
  3875. {
  3876. /* PNONE */
  3877. int c;
  3878. c = fgetc( My->SYSIN->cfp );
  3879. if (c < 0 || c > 255)
  3880. {
  3881. /* EOF */
  3882. }
  3883. else
  3884. {
  3885. S[s] = c;
  3886. s++;
  3887. }
  3888. S[s] = 0;
  3889. }
  3890. break;
  3891. case F_NULL_X_N:
  3892. /* NULL X */
  3893. {
  3894. /* P1NUM */
  3895. /* P1BYT */
  3896. My->LPRINT_NULLS = x;
  3897. N = 0;
  3898. }
  3899. break;
  3900. case F_LWIDTH_X_N:
  3901. /* LWIDTH X */
  3902. {
  3903. /* P1NUM */
  3904. /* P1BYT */
  3905. My->SYSPRN->width = x;
  3906. My->SYSPRN->col = 1;
  3907. N = 0;
  3908. }
  3909. break;
  3910. case F_LPOS_N:
  3911. /* N = LPOS */
  3912. {
  3913. /* PNONE */
  3914. /* PNONE */
  3915. N = My->SYSPRN->col;
  3916. }
  3917. break;
  3918. case F_TRON_N:
  3919. case F_TRACE_N:
  3920. case F_FLOW_N:
  3921. /* TRON */
  3922. /* TRACE */
  3923. /* FLOW */
  3924. {
  3925. /* PNONE */
  3926. prn_xprintf("Trace is ON\n");
  3927. My->bwb_trace = TRUE;
  3928. N = 0;
  3929. }
  3930. break;
  3931. case F_TROFF_N:
  3932. case F_NOTRACE_N:
  3933. case F_NOFLOW_N:
  3934. /* TROFF */
  3935. /* NOTRACE */
  3936. /* NOFLOW */
  3937. {
  3938. /* PNONE */
  3939. prn_xprintf("Trace is OFF\n");
  3940. My->bwb_trace = FALSE;
  3941. N = 0;
  3942. }
  3943. break;
  3944. case F_RANDOMIZE_N:
  3945. case F_RAN_N:
  3946. case F_RANDOM_N:
  3947. /* RANDOMIZE */
  3948. /* RAN */
  3949. /* RANDOM */
  3950. {
  3951. /* PNONE */
  3952. /* USE THE CURRENT TIME AS THE SEED */
  3953. time(&t);
  3954. lt = localtime(&t);
  3955. x = lt->tm_hour * 3600 + lt->tm_min * 60 + lt->tm_sec;
  3956. srand(x);
  3957. N = 0;
  3958. }
  3959. break;
  3960. case F_RANDOMIZE_X_N:
  3961. case F_RAN_X_N:
  3962. case F_RANDOM_X_N:
  3963. /* RANDOMIZE X */
  3964. /* RAN X */
  3965. /* RANDOM X */
  3966. {
  3967. /* P1NUM */
  3968. /* P1ANY */
  3969. x = (int) bwb_rint( X );
  3970. srand(x);
  3971. N = 0;
  3972. }
  3973. break;
  3974. default:
  3975. {
  3976. /* NOT IMPLEMENTED ON THIS PLATFORM */
  3977. IsError = 0xFF;
  3978. }
  3979. }
  3980. }
  3981. /* sanity check */
  3982. if (IsError == 0)
  3983. {
  3984. if (f->ReturnType == BasicStringSuffix)
  3985. {
  3986. /* STRING */
  3987. if ( /* s < 0 || */ s > BasicStringLengthMax)
  3988. {
  3989. /* ERROR */
  3990. WARN_INTERNAL_ERROR;
  3991. return NULL;
  3992. }
  3993. else
  3994. if (S != RESULT_BUFFER)
  3995. {
  3996. /* ERROR */
  3997. WARN_INTERNAL_ERROR;
  3998. return NULL;
  3999. }
  4000. else
  4001. {
  4002. RESULT_LENGTH = s;
  4003. RESULT_BUFFER[RESULT_LENGTH] = BasicNulChar;
  4004. }
  4005. }
  4006. else
  4007. {
  4008. /* NUMBER */
  4009. if (isnan(N))
  4010. {
  4011. /* ERROR */
  4012. /* this means the parameters were not properly checked */
  4013. WARN_INTERNAL_ERROR;
  4014. return NULL;
  4015. }
  4016. else
  4017. if (isinf(N))
  4018. {
  4019. /* Evaluation of an expression results in an
  4020. * overflow (nonfatal, the recommended
  4021. * recovery procedure is to supply machine
  4022. * in- finity with the algebraically correct
  4023. * sign and continue). */
  4024. if (N < 0)
  4025. {
  4026. N = -DBL_MAX;
  4027. }
  4028. else
  4029. {
  4030. N = DBL_MAX;
  4031. }
  4032. if( bwb_Warning_Overflow("*** Arithmetic Overflow ***") )
  4033. {
  4034. /* ERROR */
  4035. }
  4036. /* CONTINUE */
  4037. }
  4038. RESULT_NUMBER = N;
  4039. }
  4040. }
  4041. /* process errors */
  4042. if (IsError == 0xFF)
  4043. {
  4044. /* NOT IMPLEMENTED ON THIS PLATFORM */
  4045. sprintf(My->bwb_ebuf, "%s IS NOT IMPLEMENTED ON THIS PLATFORM", f->Name);
  4046. bwb_Warning(73, My->bwb_ebuf); /* WARN_ADVANCED_FEATURE */
  4047. }
  4048. else
  4049. if (IsError != 0)
  4050. {
  4051. /* ERROR */
  4052. char Buffer[80];
  4053. switch (IsError)
  4054. {
  4055. case 'A':
  4056. case 'B':
  4057. case 'C':
  4058. /* STRING parameter's value is invalid */
  4059. sprintf(Buffer, "%s(%c$)", f->Name, IsError);
  4060. break;
  4061. case 'X':
  4062. case 'Y':
  4063. case 'Z':
  4064. /* NUMBER parameter's value is invalid */
  4065. sprintf(Buffer, "%s(%c)", f->Name, IsError);
  4066. break;
  4067. default:
  4068. /* All other errors */
  4069. sprintf(Buffer, "%s() #%d", f->Name, IsError);
  4070. break;
  4071. }
  4072. sprintf(My->bwb_ebuf, "ILLEGAL FUUNCTION CALL: %s", Buffer);
  4073. bwb_Warning(5, My->bwb_ebuf); /* WARN_ILLEGAL_FUNCTION_CALL */
  4074. }
  4075. return argv; /* released by exp_function() in bwb_elx.c */
  4076. }
  4077. /* EOF */