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.
 
 
 
 
 
 

4636 lines
98 KiB

  1. /***************************************************************f
  2. bwb_int.c Line Interpretation 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. /*---------------------------------------------------------------*/
  29. #include "bwbasic.h"
  30. int
  31. buff_is_eol( char *buffer, int * position )
  32. {
  33. /*
  34. determines whether 'position' is at the NUL (BasicNulChar) in 'buffer'.
  35. if successful then returns TRUE
  36. otherwise returns FALSE.
  37. 'position' is unchanged.
  38. */
  39. int p;
  40. p = *position;
  41. if( buffer[p] == BasicNulChar )
  42. {
  43. return TRUE;
  44. }
  45. return FALSE;
  46. }
  47. int
  48. line_is_eol( LineType * line )
  49. {
  50. return buff_is_eol( line->buffer, &(line->position) );
  51. }
  52. int
  53. buff_skip_eol( char *buffer, int * position )
  54. {
  55. /*
  56. skip to the NUL (BasicNulChar) in 'buffer'.
  57. if successful then 'position' is updated and returns TRUE
  58. otherwise 'position' is unchanged and returns FALSE.
  59. */
  60. int p;
  61. p = *position;
  62. if( buffer[p] != BasicNulChar )
  63. {
  64. while( buffer[p] != BasicNulChar )
  65. {
  66. p++;
  67. }
  68. *position = p;
  69. return TRUE;
  70. }
  71. return FALSE;
  72. }
  73. int
  74. line_skip_eol( LineType * line )
  75. {
  76. return buff_skip_eol( line->buffer, &(line->position) );
  77. }
  78. int
  79. buff_skip_spaces( char *buffer, int * position )
  80. {
  81. /*
  82. skip spaces in 'buffer'.
  83. if successful then 'position' is updated and returns TRUE
  84. otherwise 'position' is unchanged and returns FALSE.
  85. */
  86. int p;
  87. p = *position;
  88. if( buffer[p] == ' ' )
  89. {
  90. while( buffer[p] == ' ' )
  91. {
  92. p++;
  93. }
  94. *position = p;
  95. return TRUE;
  96. }
  97. return FALSE;
  98. }
  99. int
  100. line_skip_spaces( LineType * line )
  101. {
  102. return buff_skip_spaces( line->buffer, &(line->position) );
  103. }
  104. int
  105. buff_peek_char( char *buffer, int * position, char find )
  106. {
  107. /*
  108. determine whether the next non-space character in 'buffer' is 'find'.
  109. if successful then returns TRUE
  110. otherwise returns FALSE.
  111. 'position' is unchanged.
  112. */
  113. int p;
  114. p = *position;
  115. buff_skip_spaces( buffer, &p );
  116. if( bwb_toupper(buffer[p]) == bwb_toupper(find) )
  117. {
  118. return TRUE;
  119. }
  120. return FALSE;
  121. }
  122. int
  123. line_peek_char( LineType * line, char find )
  124. {
  125. return buff_peek_char( line->buffer, &(line->position), find );
  126. }
  127. int
  128. buff_skip_char( char *buffer, int * position, char find )
  129. {
  130. /*
  131. skip the next non-space character in 'buffer' if it is 'find'.
  132. if successful then 'position' is updated past 'find' and returns TRUE
  133. otherwise 'position' is unchanged and returns FALSE.
  134. */
  135. int p;
  136. p = *position;
  137. buff_skip_spaces( buffer, &p );
  138. if( bwb_toupper(buffer[p]) == bwb_toupper(find) )
  139. {
  140. p++;
  141. *position = p;
  142. return TRUE;
  143. }
  144. return FALSE;
  145. }
  146. int
  147. line_skip_char( LineType * line, char find )
  148. {
  149. return buff_skip_char( line->buffer, &(line->position), find );
  150. }
  151. int
  152. buff_skip_comma( char *buffer, int * position )
  153. {
  154. /*
  155. skip the next non-space character in 'buffer' if it is a comma, semicolon, or colon.
  156. if successful then 'position' is updated past the character and returns TRUE
  157. otherwise 'position' is unchanged and returns FALSE.
  158. */
  159. int p;
  160. p = *position;
  161. buff_skip_spaces( buffer, &p );
  162. switch( buffer[p] )
  163. {
  164. case ',': /* COMMA */
  165. case ';': /* SEMICOLON */
  166. case ':': /* COLON */
  167. p++;
  168. buff_skip_spaces( buffer, &p );
  169. *position = p;
  170. return TRUE;
  171. }
  172. return FALSE;
  173. }
  174. int
  175. line_skip_comma( LineType * line )
  176. {
  177. return buff_skip_comma( line->buffer, &(line->position) );
  178. }
  179. static int char_is_varfirst( char C )
  180. {
  181. /*
  182. determine whether the character is allowed to be the first character of a BASIC variable name.
  183. if successful then returns TRUE
  184. otherwise returns FALSE.
  185. */
  186. if( bwb_isalpha( C ) )
  187. {
  188. return TRUE;
  189. }
  190. return FALSE;
  191. }
  192. static int char_is_varnext( char C )
  193. {
  194. /*
  195. determine whether the character is allowed to be the second character of a BASIC variable name.
  196. if successful then returns TRUE
  197. otherwise returns FALSE.
  198. */
  199. if( bwb_isalnum( C ) )
  200. {
  201. return TRUE;
  202. }
  203. switch(C)
  204. {
  205. case '.':
  206. case '_':
  207. if( My->CurrentVersion->OptionFlags & (OPTION_BUGS_ON) /* varnamex: period and underscore are allowed */ )
  208. {
  209. return TRUE;
  210. }
  211. }
  212. return FALSE;
  213. }
  214. int char_is_vartype( char C )
  215. {
  216. /*
  217. determine whether the character is allowed to be the type character of a BASIC variable name.
  218. if successful then returns TRUE
  219. otherwise returns FALSE.
  220. */
  221. switch( C )
  222. {
  223. case BasicStringSuffix:
  224. return TRUE;
  225. case BasicDoubleSuffix:
  226. case BasicSingleSuffix:
  227. case BasicCurrencySuffix:
  228. case BasicLongSuffix:
  229. case BasicIntegerSuffix:
  230. case BasicByteSuffix:
  231. if( My->CurrentVersion->OptionFlags & (OPTION_BUGS_ON) /* varname: numeric type-chars allowed */ )
  232. {
  233. return TRUE;
  234. }
  235. }
  236. return FALSE;
  237. }
  238. static int char_is_varhead( char C )
  239. {
  240. if( char_is_varfirst( C ) )
  241. {
  242. return TRUE;
  243. }
  244. if( char_is_varnext( C ) )
  245. {
  246. return TRUE;
  247. }
  248. return FALSE;
  249. }
  250. int char_is_vartail( char C )
  251. {
  252. if( char_is_varnext( C ) )
  253. {
  254. return TRUE;
  255. }
  256. if( char_is_vartype( C ) )
  257. {
  258. return TRUE;
  259. }
  260. return FALSE;
  261. }
  262. int
  263. buff_peek_word( char *buffer, int * position, char * find )
  264. {
  265. /*
  266. determine whether the next non-space word in 'buffer' is 'find';
  267. the word 'find' is not a sub-string of a bigger word.
  268. if successful then returns TRUE
  269. otherwise returns FALSE.
  270. 'position' is unchanged.
  271. */
  272. int p;
  273. int n;
  274. p = *position;
  275. buff_skip_spaces( buffer, &p );
  276. if( buff_is_eol( buffer, &p ) )
  277. {
  278. return FALSE;
  279. }
  280. n = bwb_strlen(find);
  281. if( bwb_strnicmp( &(buffer[p]), find, n) == 0 )
  282. {
  283. if( p > 0 )
  284. {
  285. if( char_is_varhead( buffer[p-1] ) )
  286. {
  287. /* _TO */
  288. return FALSE;
  289. }
  290. }
  291. if( char_is_vartail( buffer[p+n] ) )
  292. {
  293. /* TO_ */
  294. return FALSE;
  295. }
  296. return TRUE;
  297. }
  298. return FALSE;
  299. }
  300. int
  301. line_peek_word( LineType * line, char * find )
  302. {
  303. return buff_peek_word( line->buffer, &(line->position), find );
  304. }
  305. int
  306. buff_skip_word( char *buffer, int * position, char * find )
  307. {
  308. /*
  309. skip the next non-space word in 'buffer' if it is 'find';
  310. the word 'find' is not a sub-string of a bigger word.
  311. if successful then 'position' is updated past 'find' and returns TRUE
  312. otherwise 'position' is unchanged and returns FALSE.
  313. */
  314. int p;
  315. int n;
  316. p = *position;
  317. buff_skip_spaces( buffer, &p );
  318. if( buff_is_eol( buffer, &p ) )
  319. {
  320. return FALSE;
  321. }
  322. n = bwb_strlen(find);
  323. if( bwb_strnicmp( &(buffer[p]), find, n) == 0 )
  324. {
  325. if( p > 0 )
  326. {
  327. if( char_is_varhead( buffer[p-1] ) )
  328. {
  329. /* _TO */
  330. return FALSE;
  331. }
  332. }
  333. if( char_is_vartail( buffer[p+n] ) )
  334. {
  335. /* TO_ */
  336. return FALSE;
  337. }
  338. p += n;
  339. *position = p;
  340. return TRUE;
  341. }
  342. return FALSE;
  343. }
  344. int
  345. line_skip_word( LineType * line, char * find )
  346. {
  347. return buff_skip_word( line->buffer, &(line->position), find );
  348. }
  349. int
  350. buff_read_varname( char *buffer, int * position, char * varname )
  351. {
  352. /*
  353. read the next non-space word in 'buffer' that conforms to a BASIC variable name into 'varname'.
  354. if successful then 'position' is updated past 'varname' and returns TRUE
  355. otherwise 'position' is unchanged ('varname' is truncated) and returns FALSE.
  356. 'varname' shall be declared "char varname[BasicNameLengthMax + 1]".
  357. */
  358. int p;
  359. p = *position;
  360. buff_skip_spaces( buffer, &p );
  361. if( char_is_varfirst( buffer[p] ) )
  362. {
  363. int i;
  364. i = 0;
  365. if( i > BasicNameLengthMax )
  366. {
  367. i = BasicNameLengthMax;
  368. }
  369. varname[i] = buffer[p];
  370. p++;
  371. i++;
  372. while (char_is_varnext(buffer[p]))
  373. {
  374. if( i > BasicNameLengthMax )
  375. {
  376. i = BasicNameLengthMax;
  377. }
  378. varname[i] = buffer[p];
  379. p++;
  380. i++;
  381. }
  382. if (char_is_vartype(buffer[p]))
  383. {
  384. if( i > BasicNameLengthMax )
  385. {
  386. i = BasicNameLengthMax;
  387. }
  388. varname[i] = buffer[p];
  389. p++;
  390. i++;
  391. }
  392. varname[i] = BasicNulChar;
  393. *position = p;
  394. return TRUE;
  395. }
  396. varname[0] = BasicNulChar;
  397. return FALSE;
  398. }
  399. int
  400. line_read_varname( LineType * line, char * varname )
  401. {
  402. return buff_read_varname( line->buffer, &(line->position), varname );
  403. }
  404. int
  405. buff_read_label( char * buffer, int * position, char * label )
  406. {
  407. /*
  408. read the next non-space word in 'buffer' that conforms to a BASIC label name into 'label'.
  409. if successful then 'position' is updated past 'label' and returns TRUE
  410. otherwise 'position' is unchanged and returns FALSE.
  411. 'label' shall be declared "char label[BasicNameLengthMax + 1]".
  412. */
  413. int p;
  414. p = *position;
  415. buff_skip_spaces( buffer, &p );
  416. if( char_is_varfirst( buffer[p] ) )
  417. {
  418. int i;
  419. i = 0;
  420. if( i > BasicNameLengthMax )
  421. {
  422. i = BasicNameLengthMax;
  423. }
  424. label[i] = buffer[p];
  425. p++;
  426. i++;
  427. while (char_is_varnext(buffer[p]))
  428. {
  429. if( i > BasicNameLengthMax )
  430. {
  431. i = BasicNameLengthMax;
  432. }
  433. label[i] = buffer[p];
  434. p++;
  435. i++;
  436. }
  437. label[i] = BasicNulChar;
  438. *position = p;
  439. return TRUE;
  440. }
  441. return FALSE;
  442. }
  443. int
  444. line_read_label( LineType * line, char * label )
  445. {
  446. return buff_read_label( line->buffer, &(line->position), label );
  447. }
  448. static int buff_read_keyword( char * buffer, int * position, char * keyword )
  449. {
  450. /*
  451. read the next non-space word in 'buffer' that conforms to a BASIC keyword into 'keyword'.
  452. if successful then 'position' is updated past 'keyword' and returns TRUE
  453. otherwise 'position' is unchanged and returns FALSE.
  454. 'label' shall be declared "char keyword[BasicNameLengthMax + 1]".
  455. */
  456. int p;
  457. p = *position;
  458. buff_skip_spaces( buffer, &p );
  459. if( char_is_varfirst( buffer[p] ) )
  460. {
  461. int i;
  462. i = 0;
  463. if( i > BasicNameLengthMax )
  464. {
  465. i = BasicNameLengthMax;
  466. }
  467. keyword[i] = buffer[p];
  468. p++;
  469. i++;
  470. while (char_is_varnext(buffer[p]))
  471. {
  472. if( i > BasicNameLengthMax )
  473. {
  474. i = BasicNameLengthMax;
  475. }
  476. keyword[i] = buffer[p];
  477. p++;
  478. i++;
  479. }
  480. if( buffer[p] == BasicStringSuffix )
  481. {
  482. if( i > BasicNameLengthMax )
  483. {
  484. i = BasicNameLengthMax;
  485. }
  486. keyword[i] = buffer[p];
  487. p++;
  488. i++;
  489. }
  490. keyword[i] = BasicNulChar;
  491. *position = p;
  492. return TRUE;
  493. }
  494. keyword[0] = BasicNulChar;
  495. return FALSE;
  496. }
  497. VariableType *
  498. buff_read_scalar( char *buffer, int * position )
  499. {
  500. /*
  501. read the next non-space word in 'buffer' that conforms to a BASIC variable name,
  502. including both scalar variables and subscripted array variables.
  503. if successful then 'position' is updated
  504. past 'varname' for scalar variables
  505. (past ')' for subscripted array variables).
  506. and returns a pointer to the variable.
  507. otherwise 'position' is unchanged and returns NULL.
  508. */
  509. int p;
  510. VariableType *v;
  511. char varname[BasicNameLengthMax + 1];
  512. p = *position;
  513. /* Read a variable name */
  514. buff_skip_spaces( buffer, &p );
  515. if( buff_read_varname(buffer, &p, varname) == FALSE )
  516. {
  517. WARN_VARIABLE_NOT_DECLARED;
  518. return NULL;
  519. }
  520. if( buff_peek_char( buffer, &p, BasicLeftParenChar ) )
  521. {
  522. /* MUST be a an array */
  523. register int n;
  524. int n_params; /* number of parameters */
  525. int pp[ MAX_DIMS ];
  526. /* get parameters because the variable is dimensioned */
  527. if( buff_read_array_dimensions(buffer, &p, &n_params, pp) == FALSE )
  528. {
  529. WARN_SUBSCRIPT_OUT_OF_RANGE;
  530. return NULL;
  531. }
  532. /* get the array variable */
  533. if( (v = var_find(varname,n_params,TRUE)) == NULL )
  534. {
  535. WARN_VARIABLE_NOT_DECLARED;
  536. return NULL;
  537. }
  538. for (n = 0; n < v->dimensions; n++)
  539. {
  540. v->array_pos[n] = pp[n];
  541. }
  542. }
  543. else
  544. {
  545. /* simple scalar variable */
  546. if( (v = var_find(varname,0,TRUE)) == NULL )
  547. {
  548. WARN_VARIABLE_NOT_DECLARED;
  549. return NULL;
  550. }
  551. }
  552. *position = p;
  553. return v;
  554. }
  555. VariableType *
  556. line_read_scalar( LineType * line )
  557. {
  558. return buff_read_scalar( line->buffer, &(line->position) );
  559. }
  560. VariableType *
  561. buff_read_matrix( char *buffer, int * position )
  562. {
  563. /*
  564. read the next non-space word in 'buffer' that conforms to a BASIC matrix name,
  565. including both simple matrix variables and redimensioned matrix variables.
  566. if successful then 'position' is updated
  567. past 'varname' for matrix variables
  568. (past ')' for redimensioned matrix variables).
  569. and returns a pointer to the variable.
  570. otherwise 'position' is unchanged and returns NULL.
  571. */
  572. int p;
  573. VariableType *v;
  574. char varname[BasicNameLengthMax + 1];
  575. p = *position;
  576. /* Read a variable name */
  577. buff_skip_spaces( buffer, &p );
  578. if( buff_read_varname(buffer, &p, varname) == FALSE )
  579. {
  580. WARN_SYNTAX_ERROR;
  581. return NULL;
  582. }
  583. buff_skip_spaces( buffer, &p );
  584. v = mat_find( varname );
  585. if( v == NULL)
  586. {
  587. WARN_VARIABLE_NOT_DECLARED;
  588. return NULL;
  589. }
  590. if (buff_peek_char(buffer, &p, BasicLeftParenChar))
  591. {
  592. /* get requested matrix size, which is <= original matrix size */
  593. size_t array_units;
  594. int n;
  595. int n_params; /* number of parameters */
  596. int pp[ MAX_DIMS ];
  597. for (n = 0; n < MAX_DIMS; n++)
  598. {
  599. pp[n] = 0;
  600. }
  601. if( buff_read_array_dimensions(buffer, &p, &n_params, pp) == FALSE )
  602. {
  603. WARN_SYNTAX_ERROR;
  604. return NULL;
  605. }
  606. /* update array dimensions */
  607. array_units = 1;
  608. for (n = 0; n < n_params; n++)
  609. {
  610. if( pp[n] < My->CurrentVersion->OptionBaseValue )
  611. {
  612. WARN_SUBSCRIPT_OUT_OF_RANGE;
  613. return NULL;
  614. }
  615. array_units *= pp[n] - My->CurrentVersion->OptionBaseValue + 1;
  616. }
  617. if( array_units > v->array_units )
  618. {
  619. WARN_SUBSCRIPT_OUT_OF_RANGE;
  620. return NULL;
  621. }
  622. v->dimensions = n_params;
  623. for (n = 0; n < v->dimensions; n++)
  624. {
  625. v->LBOUND[n] = My->CurrentVersion->OptionBaseValue;
  626. v->UBOUND[n] = pp[n];
  627. }
  628. }
  629. *position = p;
  630. return v;
  631. }
  632. VariableType *
  633. line_read_matrix( LineType * line )
  634. {
  635. return buff_read_matrix( line->buffer, &(line->position) );
  636. }
  637. int
  638. buff_read_line_number( char * buffer, int * position, int * linenum )
  639. {
  640. /*
  641. read the next non-space word in 'buffer' that conforms to a BASIC line number.
  642. if successful then 'position' is updated past 'linenum' and returns TRUE
  643. otherwise 'position' is unchanged and returns FALSE.
  644. */
  645. int p;
  646. p = *position;
  647. buff_skip_spaces( buffer, &p );
  648. if( bwb_isdigit( buffer[p] ) )
  649. {
  650. int i;
  651. char label[BasicNameLengthMax + 1];
  652. i = 0;
  653. while (bwb_isdigit(buffer[p]))
  654. {
  655. if( i > BasicNameLengthMax )
  656. {
  657. i = BasicNameLengthMax;
  658. }
  659. label[i] = buffer[p];
  660. p++;
  661. i++;
  662. }
  663. label[i] = BasicNulChar;
  664. *linenum = atoi( label );
  665. *position = p;
  666. return TRUE;
  667. }
  668. return FALSE;
  669. }
  670. int
  671. line_read_line_number( LineType * line, int * linenum )
  672. {
  673. return buff_read_line_number( line->buffer, &(line->position), linenum );
  674. }
  675. int
  676. buff_read_line_sequence( char *buffer, int * position, int * head, int * tail )
  677. {
  678. /*
  679. read the next non-space words in 'buffer' that conforms to a BASIC line number sequnence.
  680. if successful then 'position' is updated past the line number sequence and returns TRUE
  681. otherwise 'position' is unchanged and returns FALSE.
  682. */
  683. /*
  684. ### head == tail
  685. ### - head to BMAX
  686. ### - ### head to tail
  687. - ### BMIN to tail
  688. */
  689. int p;
  690. int h;
  691. int t;
  692. p = *position;
  693. buff_skip_spaces( buffer, &p );
  694. if( buff_skip_char( buffer, &p, '-' ) )
  695. {
  696. /* - ... */
  697. if( buff_read_line_number( buffer, &p, &t ) )
  698. {
  699. /* - ### */
  700. *head = BasicLineNumberMin;
  701. *tail = t;
  702. *position = p;
  703. return TRUE;
  704. }
  705. }
  706. else
  707. if( buff_read_line_number( buffer, &p, &h ) )
  708. {
  709. /* ### ... */
  710. if( buff_skip_char( buffer, &p, '-' ) )
  711. {
  712. /* ### - ... */
  713. if( buff_read_line_number( buffer, &p, &t ) )
  714. {
  715. /* ### - ### */
  716. *head = h;
  717. *tail = t;
  718. *position = p;
  719. return TRUE;
  720. }
  721. else
  722. {
  723. /* ### - */
  724. *head = h;
  725. *tail = BasicLineNumberMax;
  726. *position = p;
  727. return TRUE;
  728. }
  729. }
  730. else
  731. {
  732. /* ### */
  733. *head = h;
  734. *tail = h;
  735. *position = p;
  736. return TRUE;
  737. }
  738. }
  739. return FALSE;
  740. }
  741. int
  742. line_read_line_sequence( LineType * line, int * head, int * tail )
  743. {
  744. return buff_read_line_sequence( line->buffer, &(line->position), head, tail );
  745. }
  746. int
  747. buff_read_integer_expression( char * buffer, int * position, int * Value )
  748. {
  749. /*
  750. read the next non-space words in 'buffer' that conforms to a BASIC integer expression into 'Value'.
  751. if successful then 'position' is updated past 'Value' and returns TRUE
  752. otherwise 'position' is unchanged and returns FALSE.
  753. 'Value' shall be declared "int Value".
  754. */
  755. BasicNumberType X;
  756. int p;
  757. bwx_DEBUG(__FUNCTION__);
  758. p = *position;
  759. buff_skip_spaces( buffer, &p );
  760. if( buff_read_numeric_expression( buffer, &p, &X ) )
  761. {
  762. /* we want the rounded value */
  763. X = bwb_rint( X );
  764. if( INT_MIN <= X && X <= INT_MAX )
  765. {
  766. /* OK */
  767. *Value = (int) bwb_rint( X );
  768. *position = p;
  769. return TRUE;
  770. }
  771. }
  772. /* ERROR */
  773. if( My->MaintainerDebugOn )
  774. {
  775. sprintf( My->bwb_ebuf, "%s, BUFFER:%s\n", __FUNCTION__, &( buffer[ p ] ) ); fputs( My->bwb_ebuf, My->SYSPRN->cfp );
  776. }
  777. return FALSE;
  778. }
  779. int
  780. line_read_integer_expression( LineType * line, int * Value )
  781. {
  782. return buff_read_integer_expression( line->buffer, &(line->position), Value );
  783. }
  784. int
  785. buff_read_numeric_expression( char * buffer, int * position, BasicNumberType * Value )
  786. {
  787. /*
  788. read the next non-space words in 'buffer' that conforms to a BASIC numeric expression into 'Value'.
  789. if successful then 'position' is updated past 'Value' and returns TRUE
  790. otherwise 'position' is unchanged and returns FALSE.
  791. 'Value' shall be declared "BasicNumberType Value".
  792. */
  793. int p;
  794. VariantType x;
  795. VariantType * X = &x;
  796. p = *position;
  797. CLEAR_VARIANT( X );
  798. buff_skip_spaces( buffer, &p );
  799. if( buff_read_expression( buffer, &p, X ) == FALSE )
  800. {
  801. return FALSE;
  802. }
  803. if( X->TypeChar != BasicStringSuffix )
  804. {
  805. /* OK */
  806. *Value = X->Number;
  807. *position = p;
  808. return TRUE;
  809. }
  810. RELEASE( X );
  811. return FALSE;
  812. }
  813. int
  814. line_read_numeric_expression( LineType * line, BasicNumberType * Value )
  815. {
  816. return buff_read_numeric_expression( line->buffer, &(line->position), Value );
  817. }
  818. int
  819. buff_read_string_expression( char * buffer, int * position, char ** Value )
  820. {
  821. /*
  822. read the next non-space words in 'buffer' that conforms to a BASIC string expression into 'Value'.
  823. if successful then 'position' is updated past 'Value' and returns TRUE
  824. otherwise 'position' is unchanged and returns FALSE.
  825. 'Value' shall be declared "char * Value = NULL".
  826. */
  827. int p;
  828. VariantType x;
  829. VariantType * X = &x;
  830. p = *position;
  831. CLEAR_VARIANT( X );
  832. buff_skip_spaces( buffer, &p );
  833. if( buff_read_expression( buffer, &p, X ) == FALSE )
  834. {
  835. return FALSE;
  836. }
  837. if( X->TypeChar == BasicStringSuffix )
  838. {
  839. /* OK */
  840. X->Buffer[ X->Length ] = BasicNulChar;
  841. *Value = X->Buffer;
  842. *position = p;
  843. return TRUE;
  844. }
  845. return FALSE;
  846. }
  847. int
  848. line_read_string_expression( LineType * line, char ** Value )
  849. {
  850. return buff_read_string_expression( line->buffer, &(line->position), Value );
  851. }
  852. int
  853. buff_read_index_item( char * buffer, int * position, int Index, int * Value )
  854. {
  855. /*
  856. read the next non-space words in 'buffer' that conforms to a BASIC integer expression list into 'Value',
  857. selecting the item matching 'Index'. The first 'Index' value is one;
  858. if successful then 'position' is updated past 'Value' and returns TRUE
  859. otherwise 'position' is unchanged and returns FALSE.
  860. 'Value' shall be declared "int Value".
  861. */
  862. int p;
  863. int i;
  864. p = *position;
  865. buff_skip_spaces( buffer, &p );
  866. if( buff_is_eol( buffer, &p ) )
  867. {
  868. return FALSE;
  869. }
  870. if( Index < 1 )
  871. {
  872. return FALSE;
  873. }
  874. /* Index >= 1 */
  875. i = 0;
  876. do
  877. {
  878. int v;
  879. if( buff_read_integer_expression( buffer, &p, &v ) )
  880. {
  881. i++;
  882. if( i == Index )
  883. {
  884. *Value = v;
  885. *position = p;
  886. return TRUE;
  887. }
  888. }
  889. else
  890. {
  891. return FALSE;
  892. }
  893. }
  894. while( buff_skip_comma( buffer, &p ) );
  895. return FALSE;
  896. }
  897. int
  898. line_read_index_item( LineType * line, int Index, int * Value )
  899. {
  900. return buff_read_index_item( line->buffer, &(line->position), Index, Value );
  901. }
  902. int
  903. buff_read_element( char * buffer, int * position, char * element )
  904. {
  905. /*
  906. read the next non-space word in 'buffer' that conforms to a BASIC element.
  907. if successful then 'position' is updated past the element and returns TRUE
  908. otherwise 'position' is unchanged and returns FALSE.
  909. 'element' shall be declared "char element[BasicStringLengthMax + 1]".
  910. */
  911. int p;
  912. int i;
  913. p = *position;
  914. i = 0;
  915. buff_skip_spaces( buffer, &p );
  916. if( buff_is_eol( buffer, &p ) )
  917. {
  918. return FALSE;
  919. }
  920. while( TRUE )
  921. {
  922. switch (buffer[p])
  923. {
  924. case BasicNulChar:
  925. case ',': /* COMMA */
  926. case ';': /* SEMICOLON */
  927. case ':': /* COLON */
  928. case '=':
  929. case ' ':
  930. /* element terminators */
  931. element[i] = BasicNulChar;
  932. *position = p;
  933. return TRUE;
  934. /* break; */
  935. case BasicQuoteChar:
  936. /* string constant */
  937. if( i > 0 )
  938. {
  939. /* terminates previous element */
  940. element[i] = BasicNulChar;
  941. *position = p;
  942. return TRUE;
  943. }
  944. /* return the string constant */
  945. if( i > BasicStringLengthMax )
  946. {
  947. i = BasicStringLengthMax;
  948. }
  949. element[i] = buffer[p];
  950. i++;
  951. p++;
  952. while( buffer[p] != BasicNulChar && buffer[p] != BasicQuoteChar )
  953. {
  954. if( i > BasicStringLengthMax )
  955. {
  956. i = BasicStringLengthMax;
  957. }
  958. element[i] = buffer[p];
  959. i++;
  960. p++;
  961. }
  962. if( buffer[p] == BasicQuoteChar )
  963. {
  964. p++;
  965. }
  966. if( i > BasicStringLengthMax )
  967. {
  968. i = BasicStringLengthMax;
  969. }
  970. element[i] = BasicQuoteChar;
  971. i++;
  972. element[i] = BasicNulChar;
  973. *position = p;
  974. return TRUE;
  975. /* break; */
  976. default:
  977. if( i > BasicStringLengthMax )
  978. {
  979. i = BasicStringLengthMax;
  980. }
  981. element[i] = buffer[p];
  982. i++;
  983. p++;
  984. break;
  985. }
  986. }
  987. /* return FALSE; */ /* never reached */
  988. }
  989. int
  990. line_read_element( LineType * line, char * element )
  991. {
  992. return buff_read_element( line->buffer, &(line->position), element );
  993. }
  994. int
  995. buff_read_letter_sequence(char *buffer, int *position, char *start, char *end)
  996. {
  997. /*
  998. read the next non-space alphabetic character in 'buffer' into 'start';
  999. if seperated by a '-' then read the next non-space alphabetic character into 'end'.
  1000. if successful then 'position' is updated past 'start' (or 'end') and returns TRUE
  1001. otherwise 'position' is unchanged and returns FALSE.
  1002. */
  1003. int p;
  1004. char s;
  1005. char e;
  1006. p = *position;
  1007. buff_skip_spaces(buffer, &p);
  1008. if ( ! bwb_isalpha(buffer[p]) )
  1009. {
  1010. /* character at this position must be a letter */
  1011. return FALSE;
  1012. }
  1013. s = buffer[p];
  1014. p++;
  1015. /* check for hyphen, indicating sequence of more than one letter */
  1016. if ( buff_skip_char( buffer, &p, '-') )
  1017. {
  1018. buff_skip_spaces(buffer, &p);
  1019. if ( ! bwb_isalpha(buffer[p]) )
  1020. {
  1021. /* character at this position must be a letter */
  1022. return FALSE;
  1023. }
  1024. e = buffer[p];
  1025. p++;
  1026. }
  1027. else
  1028. {
  1029. e = s;
  1030. }
  1031. *start = s;
  1032. *end = e;
  1033. *position = p;
  1034. return TRUE;
  1035. }
  1036. int
  1037. line_read_letter_sequence( LineType * line, char *start, char *end)
  1038. {
  1039. return buff_read_letter_sequence( line->buffer, &(line->position), start, end );
  1040. }
  1041. int
  1042. buff_read_array_dimensions(char *buffer, int *position, int *n_params , int params[ /* MAX_DIMS */ ] )
  1043. {
  1044. /*
  1045. read the next non-space words in 'buffer' that conform to BASIC array index values;
  1046. if successful then 'position' is updated past the ending ')' and returns TRUE
  1047. otherwise 'position' is unchanged and returns FALSE.
  1048. */
  1049. int p;
  1050. int n;
  1051. p = *position;
  1052. n = 0;
  1053. buff_skip_spaces(buffer, &p);
  1054. if ( buff_skip_char( buffer, &p, BasicLeftParenChar) )
  1055. {
  1056. /* matrix */
  1057. do
  1058. {
  1059. int Value;
  1060. if( n < MAX_DIMS )
  1061. {
  1062. /* OK */
  1063. if( buff_read_integer_expression( buffer, &p, &Value) )
  1064. {
  1065. params[n] = Value;
  1066. n++;
  1067. }
  1068. else
  1069. {
  1070. return FALSE;
  1071. }
  1072. }
  1073. else
  1074. {
  1075. /* ERROR */
  1076. return FALSE;
  1077. }
  1078. }
  1079. while( buff_skip_comma( buffer, &p ) );
  1080. if ( buff_skip_char( buffer, &p, BasicRightParenChar) == FALSE )
  1081. {
  1082. /* ERROR */
  1083. return FALSE;
  1084. }
  1085. }
  1086. else
  1087. {
  1088. /* scalar */
  1089. n = 0;
  1090. }
  1091. *n_params = n;
  1092. *position = p;
  1093. return TRUE;
  1094. }
  1095. int
  1096. line_read_array_dimensions( LineType * line, int *n_params , int params[ /* MAX_DIMS */ ] )
  1097. {
  1098. return buff_read_array_dimensions(line->buffer, &(line->position), n_params , params );
  1099. }
  1100. int
  1101. buff_peek_array_dimensions(char *buffer, int *position, int *n_params )
  1102. {
  1103. /*
  1104. peek the next non-space words in 'buffer' that conform to BASIC array index values;
  1105. if successful then 'n_params' is updated and returns TRUE
  1106. otherwise 'n_params' is unchanged and returns FALSE.
  1107. 'position' is always unchanged.
  1108. */
  1109. int p;
  1110. int ParenLevel = 0;
  1111. int NumDimensions = 1;
  1112. p = *position;
  1113. buff_skip_spaces( buffer, &p );
  1114. while( buffer[p] != BasicNulChar )
  1115. {
  1116. /* check the current character */
  1117. buff_skip_spaces( buffer, &p );
  1118. if ( buff_skip_char( buffer, &p, BasicLeftParenChar) )
  1119. {
  1120. ParenLevel++;
  1121. }
  1122. else
  1123. if ( buff_skip_char( buffer, &p, BasicRightParenChar) )
  1124. {
  1125. ParenLevel--;
  1126. if (ParenLevel < 0)
  1127. {
  1128. return FALSE;
  1129. }
  1130. if (ParenLevel == 0)
  1131. {
  1132. *n_params = NumDimensions;
  1133. return TRUE;
  1134. }
  1135. }
  1136. else
  1137. if ( buff_skip_comma( buffer, &p) )
  1138. {
  1139. if (ParenLevel == 1)
  1140. {
  1141. NumDimensions++;
  1142. }
  1143. }
  1144. else
  1145. if( buffer[p] == BasicQuoteChar )
  1146. {
  1147. /* embedded string constant */
  1148. p++;
  1149. while ((buffer[p] != BasicQuoteChar) && (buffer[p] != BasicNulChar))
  1150. {
  1151. p++;
  1152. }
  1153. if (buffer[p] == BasicQuoteChar)
  1154. {
  1155. p++;
  1156. }
  1157. }
  1158. else
  1159. {
  1160. /* normal character */
  1161. p++;
  1162. }
  1163. }
  1164. return FALSE;
  1165. }
  1166. int
  1167. line_peek_array_dimensions( LineType * line, int *n_params )
  1168. {
  1169. return buff_peek_array_dimensions(line->buffer, &(line->position), n_params );
  1170. }
  1171. char
  1172. buff_read_type_declaration( char *buffer, int * position )
  1173. {
  1174. /*
  1175. skip the next non-space words in 'buffer' if it is a BASIC type declaration.
  1176. if successful then 'position' is updated past the BASIC type declaration and returns the TypeChar
  1177. otherwise 'position' is unchanged and returns BasicNulChar.
  1178. */
  1179. int p;
  1180. char TypeChar;
  1181. p = *position;
  1182. TypeChar = BasicNulChar;
  1183. buff_skip_spaces( buffer, &p );
  1184. if( buff_is_eol( buffer, &p ) )
  1185. {
  1186. return FALSE;
  1187. }
  1188. if( buff_skip_word(buffer, &p, "AS") == TRUE )
  1189. {
  1190. /* AS ... */
  1191. if( buff_skip_word(buffer, &p, "STRING" ) )
  1192. {
  1193. /* AS STRING */
  1194. TypeChar = BasicStringSuffix;
  1195. }
  1196. else
  1197. if( buff_skip_word(buffer, &p, "DOUBLE" ) )
  1198. {
  1199. /* AS DOUBLE */
  1200. TypeChar = BasicDoubleSuffix;
  1201. }
  1202. else
  1203. if( buff_skip_word(buffer, &p, "SINGLE" ) )
  1204. {
  1205. /* AS SINGLE */
  1206. TypeChar = BasicSingleSuffix;
  1207. }
  1208. else
  1209. if( buff_skip_word(buffer, &p, "CURRENCY" ) )
  1210. {
  1211. /* AS CURRENCY */
  1212. TypeChar = BasicCurrencySuffix;
  1213. }
  1214. else
  1215. if( buff_skip_word(buffer, &p, "LONG" ) )
  1216. {
  1217. /* AS LONG */
  1218. TypeChar = BasicLongSuffix;
  1219. }
  1220. else
  1221. if( buff_skip_word(buffer, &p, "INTEGER" ) )
  1222. {
  1223. /* AS INTEGER */
  1224. TypeChar = BasicIntegerSuffix;
  1225. }
  1226. else
  1227. if( buff_skip_word(buffer, &p, "BYTE" ) )
  1228. {
  1229. /* AS BYTE */
  1230. TypeChar = BasicByteSuffix;
  1231. }
  1232. else
  1233. {
  1234. /* invalid type */
  1235. }
  1236. }
  1237. if( TypeChar != BasicNulChar )
  1238. {
  1239. /* success */
  1240. *position = p;
  1241. }
  1242. return TypeChar;
  1243. }
  1244. char
  1245. line_read_type_declaration( LineType * line )
  1246. {
  1247. return buff_read_type_declaration(line->buffer, &(line->position) );
  1248. }
  1249. /***************************************************************
  1250. FUNCTION: line_start()
  1251. DESCRIPTION: This function reads a line buffer in
  1252. <buffer> beginning at the position
  1253. <pos> and attempts to determine (a)
  1254. the position of the line number in the
  1255. buffer (returned in <lnpos>), (b) the
  1256. line number at this position (returned
  1257. in <lnum>), (c) the position of the
  1258. BASIC command in the buffer (returned
  1259. in <cmdpos>), (d) the position of this
  1260. BASIC command in the command table
  1261. (returned in <cmdnum>), and (e) the
  1262. position of the beginning of the rest
  1263. of the line (returned in <Startpos>).
  1264. Although <Startpos> must be returned
  1265. as a positive integer, the other
  1266. searches may fail, in which case FALSE
  1267. will be returned in their positions.
  1268. <pos> is not incremented.
  1269. ***************************************************************/
  1270. int
  1271. line_start(LineType * l)
  1272. {
  1273. int position;
  1274. char tbuf[BasicNameLengthMax + 1];
  1275. bwx_DEBUG(__FUNCTION__);
  1276. /* set initial values */
  1277. l->Startpos = 0;
  1278. l->cmdnum = 0; /* not found */
  1279. position = 0;
  1280. buff_skip_spaces(l->buffer, &position);
  1281. /* handle special cases */
  1282. if (l->buffer[position] == BasicNulChar)
  1283. {
  1284. /* the NUL (0) char must be handled first */
  1285. l->cmdnum = C_REM;
  1286. return TRUE;
  1287. }
  1288. if (l->buffer[position] == My->CurrentVersion->OptionCommentChar)
  1289. {
  1290. l->cmdnum = C_REM;
  1291. buff_skip_eol(l->buffer, &(position));
  1292. l->Startpos = position;
  1293. return TRUE;
  1294. }
  1295. if (l->buffer[position] == My->CurrentVersion->OptionPrintChar)
  1296. {
  1297. l->cmdnum = C_PRINT;
  1298. l->Startpos = position;
  1299. /* skip past '?' */
  1300. l->Startpos++;
  1301. return TRUE;
  1302. }
  1303. if (l->buffer[position] == My->CurrentVersion->OptionImageChar)
  1304. {
  1305. l->cmdnum = C_IMAGE;
  1306. l->Startpos = position;
  1307. /* skip past ':' */
  1308. l->Startpos++;
  1309. return TRUE;
  1310. }
  1311. if (bwb_strnicmp(&l->buffer[position], "REM", 3) == 0)
  1312. {
  1313. l->cmdnum = C_REM;
  1314. buff_skip_eol(l->buffer, &(position));
  1315. l->Startpos = position;
  1316. return TRUE;
  1317. }
  1318. /* not a SPECIAL */
  1319. /* get the first keyword */
  1320. if( buff_read_keyword(l->buffer, &position, tbuf) == FALSE )
  1321. {
  1322. /* ERROR */
  1323. return FALSE;
  1324. }
  1325. buff_skip_spaces(l->buffer, &position);
  1326. /* check for COMMAND */
  1327. if ((l->cmdnum = is_cmd(tbuf)) > 0)
  1328. {
  1329. /* it is a COMMAND */
  1330. /*
  1331. * NOTE: This is NOT a full parser, this exists only to
  1332. * handle STRUCTURED commands. It is true that we also handle
  1333. * some other easy cases, but remember that this only exists
  1334. * to support STRUCTURED commands. Whether any other commands
  1335. * get processed here is simply because it was easy to do so.
  1336. */
  1337. int cmdnum = 0;
  1338. #define MAX_COMMAND_LENGTH 63
  1339. char xbuf[ MAX_COMMAND_LENGTH + 1 /* NUL */ ]; /* ON ERROR RESUME NEXT */
  1340. bwb_strcpy( xbuf, tbuf );
  1341. do
  1342. {
  1343. cmdnum = 0;
  1344. buff_skip_spaces(l->buffer, &position);
  1345. l->Startpos = position;
  1346. if( buff_read_keyword(l->buffer, &position, tbuf) )
  1347. {
  1348. int n;
  1349. n = bwb_strlen( xbuf ) + 1 + bwb_strlen( tbuf );
  1350. if( n < MAX_COMMAND_LENGTH )
  1351. {
  1352. /* not too long */
  1353. bwb_strcat( xbuf, " " );
  1354. bwb_strcat( xbuf, tbuf );
  1355. cmdnum = is_cmd( xbuf );
  1356. if( cmdnum > 0 )
  1357. {
  1358. /* longer command is valid */
  1359. buff_skip_spaces(l->buffer, &position);
  1360. l->cmdnum = cmdnum;
  1361. l->Startpos = position;
  1362. }
  1363. }
  1364. }
  1365. }
  1366. while( cmdnum > 0 );
  1367. /* process special cases here */
  1368. switch (l->cmdnum)
  1369. {
  1370. case C_CLOAD:
  1371. {
  1372. position = l->Startpos;
  1373. if( buff_skip_char(l->buffer, &position, '*' ) )
  1374. {
  1375. /* CLOAD* */
  1376. buff_skip_spaces(l->buffer, &position);
  1377. l->cmdnum = C_CLOAD8;
  1378. l->Startpos = position;
  1379. }
  1380. }
  1381. break;
  1382. case C_CSAVE:
  1383. {
  1384. position = l->Startpos;
  1385. if( buff_skip_char(l->buffer, &position, '*' ) )
  1386. {
  1387. /* CSAVE* */
  1388. buff_skip_spaces(l->buffer, &position);
  1389. l->cmdnum = C_CSAVE8;
  1390. l->Startpos = position;
  1391. }
  1392. }
  1393. break;
  1394. case C_DEF:
  1395. if( bwb_strchr( l->buffer, '=' ) == NULL )
  1396. {
  1397. /* multi-line DEF ... FNEND */
  1398. l->cmdnum = C_FUNCTION;
  1399. }
  1400. fslt_add(l);
  1401. break;
  1402. case C_FEND:
  1403. l->cmdnum = C_END_FUNCTION;
  1404. break;
  1405. case C_FNEND:
  1406. l->cmdnum = C_END_FUNCTION;
  1407. break;
  1408. case C_FUNCTION:
  1409. fslt_add(l);
  1410. break;
  1411. case C_IF:
  1412. if( IsLastKeyword( l, " THEN" ) )
  1413. {
  1414. /* STRUCTURED */
  1415. l->cmdnum = C_IF_THEN;
  1416. }
  1417. break;
  1418. case C_OPEN:
  1419. {
  1420. if( My->CurrentVersion->OptionVersionBitmask & ( I70 | I73 ) )
  1421. {
  1422. /* OPEN filenum, filename$, INPUT | OUTPUT */
  1423. }
  1424. else
  1425. if (GetKeyword(l, NULL, " AS "))
  1426. {
  1427. /* STRUCTURED */
  1428. }
  1429. else
  1430. {
  1431. /* CLASSIC */
  1432. l->cmdnum = C_DEF_SUB;
  1433. l->Startpos = 0;
  1434. }
  1435. }
  1436. break;
  1437. case C_SUB:
  1438. fslt_add(l);
  1439. break;
  1440. case C_SUBEND:
  1441. l->cmdnum = C_END_SUB;
  1442. break;
  1443. case C_USER_LBL:
  1444. fslt_add(l);
  1445. break;
  1446. }
  1447. /* done */
  1448. return TRUE;
  1449. #if FALSE
  1450. if (l->cmdnum == C_CASE)
  1451. {
  1452. position = l->Startpos;
  1453. buff_read_keyword(l->buffer, &position, tbuf);
  1454. buff_skip_spaces(l->buffer, &position);
  1455. if (bwb_stricmp(tbuf, "ELSE") == 0)
  1456. {
  1457. l->cmdnum = C_CASE_ELSE;
  1458. l->Startpos = position;
  1459. }
  1460. else
  1461. {
  1462. /* CASE ... */
  1463. /* CASE IF ... */
  1464. /* CASE IS ... */
  1465. }
  1466. }
  1467. else
  1468. if (l->cmdnum == C_CLOAD)
  1469. {
  1470. position = l->Startpos;
  1471. if( buff_skip_char(l->buffer, &position, '*' ) )
  1472. {
  1473. /* CLOAD* */
  1474. buff_skip_spaces(l->buffer, &position);
  1475. l->cmdnum = C_CLOAD8;
  1476. l->Startpos = position;
  1477. }
  1478. else
  1479. {
  1480. /* CLOAD ... */
  1481. }
  1482. }
  1483. else
  1484. if (l->cmdnum == C_CSAVE)
  1485. {
  1486. position = l->Startpos;
  1487. if( buff_skip_char(l->buffer, &position, '*' ) )
  1488. {
  1489. /* CSAVE* */
  1490. buff_skip_spaces(l->buffer, &position);
  1491. l->cmdnum = C_CSAVE8;
  1492. l->Startpos = position;
  1493. }
  1494. else
  1495. {
  1496. /* CSAVE ... */
  1497. }
  1498. }
  1499. else
  1500. if (l->cmdnum == C_DEF)
  1501. {
  1502. if(bwb_strchr(l->buffer,'=') == NULL)
  1503. {
  1504. /* multi-line DEF ... FNEND */
  1505. l->cmdnum = C_FUNCTION;
  1506. l->Startpos = position;
  1507. }
  1508. else
  1509. {
  1510. /* single line DEF */
  1511. }
  1512. }
  1513. else
  1514. if (l->cmdnum == C_FNEND)
  1515. {
  1516. l->cmdnum = C_END_FUNCTION;
  1517. }
  1518. else
  1519. if (l->cmdnum == C_FEND)
  1520. {
  1521. l->cmdnum = C_END_FUNCTION;
  1522. }
  1523. else
  1524. if (l->cmdnum == C_END)
  1525. {
  1526. position = l->Startpos;
  1527. buff_read_keyword(l->buffer, &position, tbuf);
  1528. buff_skip_spaces(l->buffer, &position);
  1529. if (bwb_stricmp(tbuf, "FUNCTION") == 0)
  1530. {
  1531. l->cmdnum = C_END_FUNCTION;
  1532. l->Startpos = position;
  1533. }
  1534. else
  1535. if (bwb_stricmp(tbuf, "IF") == 0)
  1536. {
  1537. l->cmdnum = C_END_IF;
  1538. l->Startpos = position;
  1539. }
  1540. else
  1541. if (bwb_stricmp(tbuf, "SELECT") == 0)
  1542. {
  1543. l->cmdnum = C_END_SELECT;
  1544. l->Startpos = position;
  1545. }
  1546. else
  1547. if (bwb_stricmp(tbuf, "SUB") == 0)
  1548. {
  1549. l->cmdnum = C_END_SUB;
  1550. l->Startpos = position;
  1551. }
  1552. else
  1553. {
  1554. /* plain END */
  1555. }
  1556. }
  1557. else
  1558. if (l->cmdnum == C_EXIT)
  1559. {
  1560. position = l->Startpos;
  1561. buff_read_keyword(l->buffer, &position, tbuf);
  1562. buff_skip_spaces(l->buffer, &position);
  1563. if (bwb_stricmp(tbuf, "DO") == 0)
  1564. {
  1565. l->cmdnum = C_EXIT_DO;
  1566. l->Startpos = position;
  1567. }
  1568. else
  1569. if (bwb_stricmp(tbuf, "FOR") == 0)
  1570. {
  1571. l->cmdnum = C_EXIT_FOR;
  1572. l->Startpos = position;
  1573. }
  1574. else
  1575. if (bwb_stricmp(tbuf, "FUNCTION") == 0)
  1576. {
  1577. l->cmdnum = C_EXIT_FUNCTION;
  1578. l->Startpos = position;
  1579. }
  1580. else
  1581. if (bwb_stricmp(tbuf, "SUB") == 0)
  1582. {
  1583. l->cmdnum = C_EXIT_SUB;
  1584. l->Startpos = position;
  1585. }
  1586. else
  1587. if (bwb_stricmp(tbuf, "UNTIL") == 0)
  1588. {
  1589. l->cmdnum = C_EXIT_UNTIL;
  1590. l->Startpos = position;
  1591. }
  1592. else
  1593. if (bwb_stricmp(tbuf, "WHILE") == 0)
  1594. {
  1595. l->cmdnum = C_EXIT_WHILE;
  1596. l->Startpos = position;
  1597. }
  1598. else
  1599. {
  1600. /* EXIT line */
  1601. }
  1602. }
  1603. else
  1604. if (l->cmdnum == C_GO)
  1605. {
  1606. position = l->Startpos;
  1607. buff_read_keyword(l->buffer, &position, tbuf);
  1608. buff_skip_spaces(l->buffer, &position);
  1609. if (bwb_stricmp(tbuf, "SUB") == 0)
  1610. {
  1611. l->cmdnum = C_GOSUB;
  1612. l->Startpos = position;
  1613. }
  1614. else
  1615. if (bwb_stricmp(tbuf, "TO") == 0)
  1616. {
  1617. l->cmdnum = C_GOTO;
  1618. l->Startpos = position;
  1619. }
  1620. else
  1621. {
  1622. /* syntax error */
  1623. l->cmdnum = 0;
  1624. }
  1625. }
  1626. else
  1627. if (l->cmdnum == C_IF)
  1628. {
  1629. if (IsLastKeyword(l, " THEN") == TRUE)
  1630. {
  1631. /* STRUCTURED */
  1632. l->cmdnum = C_IF_THEN;
  1633. }
  1634. else
  1635. {
  1636. /* CLASSIC */
  1637. position = l->Startpos;
  1638. buff_read_keyword(l->buffer, &position, tbuf);
  1639. buff_skip_spaces(l->buffer, &position);
  1640. if (bwb_stricmp(tbuf, "END") == 0)
  1641. {
  1642. /* IF END # X THEN ... */
  1643. l->cmdnum = C_IF_END;
  1644. l->Startpos = position;
  1645. }
  1646. else
  1647. if (bwb_stricmp(tbuf, "MORE") == 0)
  1648. {
  1649. /* IF MORE # X THEN ... */
  1650. l->cmdnum = C_IF_MORE;
  1651. l->Startpos = position;
  1652. }
  1653. else
  1654. {
  1655. /* normal */
  1656. }
  1657. }
  1658. }
  1659. else
  1660. if (l->cmdnum == C_MAT)
  1661. {
  1662. position = l->Startpos;
  1663. buff_read_keyword(l->buffer, &position, tbuf);
  1664. buff_skip_spaces(l->buffer, &position);
  1665. if (bwb_stricmp(tbuf, "GET") == 0)
  1666. {
  1667. l->cmdnum = C_MAT_GET;
  1668. l->Startpos = position;
  1669. }
  1670. else
  1671. if (bwb_stricmp(tbuf, "INPUT") == 0)
  1672. {
  1673. l->cmdnum = C_MAT_INPUT;
  1674. l->Startpos = position;
  1675. }
  1676. else
  1677. if (bwb_stricmp(tbuf, "PRINT") == 0)
  1678. {
  1679. l->cmdnum = C_MAT_PRINT;
  1680. l->Startpos = position;
  1681. }
  1682. else
  1683. if (bwb_stricmp(tbuf, "PUT") == 0)
  1684. {
  1685. l->cmdnum = C_MAT_PUT;
  1686. l->Startpos = position;
  1687. }
  1688. else
  1689. if (bwb_stricmp(tbuf, "READ") == 0)
  1690. {
  1691. l->cmdnum = C_MAT_READ;
  1692. l->Startpos = position;
  1693. }
  1694. else
  1695. if (bwb_stricmp(tbuf, "WRITE") == 0)
  1696. {
  1697. l->cmdnum = C_MAT_WRITE;
  1698. l->Startpos = position;
  1699. }
  1700. else
  1701. {
  1702. /* plain MAT */
  1703. }
  1704. }
  1705. else
  1706. if (l->cmdnum == C_ON)
  1707. {
  1708. position = l->Startpos;
  1709. buff_read_keyword(l->buffer, &position, tbuf);
  1710. buff_skip_spaces(l->buffer, &position);
  1711. if (bwb_stricmp(tbuf, "ERROR") == 0)
  1712. {
  1713. buff_read_keyword(l->buffer, &position, tbuf);
  1714. buff_skip_spaces(l->buffer, &position);
  1715. if (bwb_stricmp(tbuf, "GOTO") == 0)
  1716. {
  1717. l->cmdnum = C_ON_ERROR_GOTO;
  1718. l->Startpos = position;
  1719. }
  1720. else
  1721. if (bwb_stricmp(tbuf, "GOSUB") == 0)
  1722. {
  1723. l->cmdnum = C_ON_ERROR_GOSUB;
  1724. l->Startpos = position;
  1725. }
  1726. else
  1727. if (bwb_stricmp(tbuf, "RESUME") == 0)
  1728. {
  1729. buff_read_keyword(l->buffer, &position, tbuf);
  1730. buff_skip_spaces(l->buffer, &position);
  1731. if (bwb_stricmp(tbuf, "NEXT") == 0)
  1732. {
  1733. l->cmdnum = C_ON_ERROR_RESUME_NEXT;
  1734. l->Startpos = position;
  1735. }
  1736. else
  1737. {
  1738. /* syntax error */
  1739. l->cmdnum = 0;
  1740. }
  1741. }
  1742. else
  1743. if (bwb_stricmp(tbuf, "RETURN") == 0)
  1744. {
  1745. buff_read_keyword(l->buffer, &position, tbuf);
  1746. buff_skip_spaces(l->buffer, &position);
  1747. if (bwb_stricmp(tbuf, "NEXT") == 0)
  1748. {
  1749. l->cmdnum = C_ON_ERROR_RETURN_NEXT;
  1750. l->Startpos = position;
  1751. }
  1752. else
  1753. {
  1754. /* syntax error */
  1755. l->cmdnum = 0;
  1756. }
  1757. }
  1758. else
  1759. {
  1760. /* syntax error */
  1761. l->cmdnum = 0;
  1762. }
  1763. }
  1764. else
  1765. if (bwb_stricmp(tbuf, "TIMER") == 0)
  1766. {
  1767. l->cmdnum = C_ON_TIMER;
  1768. l->Startpos = position;
  1769. }
  1770. else
  1771. {
  1772. /* ON ... GO ... */
  1773. }
  1774. }
  1775. else
  1776. if (l->cmdnum == C_OPEN)
  1777. {
  1778. if( My->CurrentVersion->OptionVersionBitmask & ( I70 | I73 ) )
  1779. {
  1780. /* OPEN filenum, filename$, INPUT | OUTPUT */
  1781. }
  1782. else
  1783. if (GetKeyword(l, NULL, " AS "))
  1784. {
  1785. /* STRUCTURED */
  1786. }
  1787. else
  1788. {
  1789. /* CLASSIC */
  1790. l->cmdnum = C_DEF_SUB;
  1791. l->Startpos = 0;
  1792. }
  1793. }
  1794. else
  1795. if (l->cmdnum == C_OPTION)
  1796. {
  1797. position = l->Startpos;
  1798. buff_read_keyword(l->buffer, &position, tbuf);
  1799. buff_skip_spaces(l->buffer, &position);
  1800. if (bwb_stricmp(tbuf, "ANGLE") == 0)
  1801. {
  1802. buff_read_keyword(l->buffer, &position, tbuf);
  1803. buff_skip_spaces(l->buffer, &position);
  1804. if (bwb_stricmp(tbuf, "DEGREES") == 0)
  1805. {
  1806. l->cmdnum = C_OPTION_ANGLE_DEGREES;
  1807. l->Startpos = position;
  1808. }
  1809. else
  1810. if (bwb_stricmp(tbuf, "GRADIANS") == 0)
  1811. {
  1812. l->cmdnum = C_OPTION_ANGLE_GRADIANS;
  1813. l->Startpos = position;
  1814. }
  1815. else
  1816. if (bwb_stricmp(tbuf, "RADIANS") == 0)
  1817. {
  1818. l->cmdnum = C_OPTION_ANGLE_RADIANS;
  1819. l->Startpos = position;
  1820. }
  1821. else
  1822. {
  1823. /* syntax error */
  1824. l->cmdnum = 0;
  1825. }
  1826. }
  1827. else
  1828. if (bwb_stricmp(tbuf, "ARITHMETIC") == 0)
  1829. {
  1830. buff_read_keyword(l->buffer, &position, tbuf);
  1831. buff_skip_spaces(l->buffer, &position);
  1832. if (bwb_stricmp(tbuf, "DECIMAL") == 0)
  1833. {
  1834. l->cmdnum = C_OPTION_ARITHMETIC_DECIMAL;
  1835. l->Startpos = position;
  1836. }
  1837. else
  1838. if (bwb_stricmp(tbuf, "FIXED") == 0)
  1839. {
  1840. l->cmdnum = C_OPTION_ARITHMETIC_FIXED;
  1841. l->Startpos = position;
  1842. }
  1843. else
  1844. if (bwb_stricmp(tbuf, "NATIVE") == 0)
  1845. {
  1846. l->cmdnum = C_OPTION_ARITHMETIC_NATIVE;
  1847. l->Startpos = position;
  1848. }
  1849. else
  1850. {
  1851. /* syntax error */
  1852. l->cmdnum = 0;
  1853. }
  1854. }
  1855. else
  1856. if (bwb_stricmp(tbuf, "BASE") == 0)
  1857. {
  1858. l->cmdnum = C_OPTION_BASE;
  1859. l->Startpos = position;
  1860. }
  1861. else
  1862. if (bwb_stricmp(tbuf, "BUGS") == 0)
  1863. {
  1864. buff_read_keyword(l->buffer, &position, tbuf);
  1865. buff_skip_spaces(l->buffer, &position);
  1866. if (bwb_stricmp(tbuf, "OFF") == 0)
  1867. {
  1868. l->cmdnum = C_OPTION_BUGS_OFF;
  1869. l->Startpos = position;
  1870. }
  1871. else
  1872. if (bwb_stricmp(tbuf, "ON") == 0)
  1873. {
  1874. l->cmdnum = C_OPTION_BUGS_ON;
  1875. l->Startpos = position;
  1876. }
  1877. else
  1878. {
  1879. /* syntax error */
  1880. l->cmdnum = 0;
  1881. }
  1882. }
  1883. else
  1884. if (bwb_stricmp(tbuf, "COMMENT") == 0)
  1885. {
  1886. l->cmdnum = C_OPTION_COMMENT;
  1887. l->Startpos = position;
  1888. }
  1889. else
  1890. if (bwb_stricmp(tbuf, "COMPARE") == 0)
  1891. {
  1892. buff_read_keyword(l->buffer, &position, tbuf);
  1893. buff_skip_spaces(l->buffer, &position);
  1894. if (bwb_stricmp(tbuf, "BINARY") == 0)
  1895. {
  1896. l->cmdnum = C_OPTION_COMPARE_BINARY;
  1897. l->Startpos = position;
  1898. }
  1899. else
  1900. if (bwb_stricmp(tbuf, "DATABASE") == 0)
  1901. {
  1902. l->cmdnum = C_OPTION_COMPARE_DATABASE;
  1903. l->Startpos = position;
  1904. }
  1905. else
  1906. if (bwb_stricmp(tbuf, "TEXT") == 0)
  1907. {
  1908. l->cmdnum = C_OPTION_COMPARE_TEXT;
  1909. l->Startpos = position;
  1910. }
  1911. else
  1912. {
  1913. /* syntax error */
  1914. l->cmdnum = 0;
  1915. }
  1916. }
  1917. else
  1918. if (bwb_stricmp(tbuf, "COVERAGE") == 0)
  1919. {
  1920. buff_read_keyword(l->buffer, &position, tbuf);
  1921. buff_skip_spaces(l->buffer, &position);
  1922. if (bwb_stricmp(tbuf, "OFF") == 0)
  1923. {
  1924. l->cmdnum = C_OPTION_COVERAGE_OFF;
  1925. l->Startpos = position;
  1926. }
  1927. else
  1928. if (bwb_stricmp(tbuf, "ON") == 0)
  1929. {
  1930. l->cmdnum = C_OPTION_COVERAGE_ON;
  1931. l->Startpos = position;
  1932. }
  1933. else
  1934. {
  1935. /* syntax error */
  1936. l->cmdnum = 0;
  1937. }
  1938. }
  1939. else
  1940. if (bwb_stricmp(tbuf, "DATE") == 0)
  1941. {
  1942. l->cmdnum = C_OPTION_DATE;
  1943. l->Startpos = position;
  1944. }
  1945. else
  1946. if (bwb_stricmp(tbuf, "DISABLE") == 0)
  1947. {
  1948. buff_read_keyword(l->buffer, &position, tbuf);
  1949. buff_skip_spaces(l->buffer, &position);
  1950. if (bwb_stricmp(tbuf, "COMMAND") == 0)
  1951. {
  1952. l->cmdnum = C_OPTION_DISABLE_COMMAND;
  1953. l->Startpos = position;
  1954. }
  1955. else
  1956. if (bwb_stricmp(tbuf, "FUNCTION") == 0)
  1957. {
  1958. l->cmdnum = C_OPTION_DISABLE_FUNCTION;
  1959. l->Startpos = position;
  1960. }
  1961. else
  1962. if (bwb_stricmp(tbuf, "OPERATOR") == 0)
  1963. {
  1964. l->cmdnum = C_OPTION_DISABLE_OPERATOR;
  1965. l->Startpos = position;
  1966. }
  1967. else
  1968. {
  1969. /* syntax error */
  1970. l->cmdnum = 0;
  1971. }
  1972. }
  1973. else
  1974. if (bwb_stricmp(tbuf, "ENABLE") == 0)
  1975. {
  1976. buff_read_keyword(l->buffer, &position, tbuf);
  1977. buff_skip_spaces(l->buffer, &position);
  1978. if (bwb_stricmp(tbuf, "COMMAND") == 0)
  1979. {
  1980. l->cmdnum = C_OPTION_ENABLE_COMMAND;
  1981. l->Startpos = position;
  1982. }
  1983. else
  1984. if (bwb_stricmp(tbuf, "FUNCTION") == 0)
  1985. {
  1986. l->cmdnum = C_OPTION_ENABLE_FUNCTION;
  1987. l->Startpos = position;
  1988. }
  1989. else
  1990. if (bwb_stricmp(tbuf, "OPERATOR") == 0)
  1991. {
  1992. l->cmdnum = C_OPTION_ENABLE_OPERATOR;
  1993. l->Startpos = position;
  1994. }
  1995. else
  1996. {
  1997. /* syntax error */
  1998. l->cmdnum = 0;
  1999. }
  2000. }
  2001. else
  2002. if (bwb_stricmp(tbuf, "ERROR") == 0)
  2003. {
  2004. buff_read_keyword(l->buffer, &position, tbuf);
  2005. buff_skip_spaces(l->buffer, &position);
  2006. if (bwb_stricmp(tbuf, "GOSUB") == 0)
  2007. {
  2008. l->cmdnum = C_OPTION_ERROR_GOSUB;
  2009. l->Startpos = position;
  2010. }
  2011. else
  2012. if (bwb_stricmp(tbuf, "GOTO") == 0)
  2013. {
  2014. l->cmdnum = C_OPTION_ERROR_GOTO;
  2015. l->Startpos = position;
  2016. }
  2017. else
  2018. {
  2019. /* syntax error */
  2020. l->cmdnum = 0;
  2021. }
  2022. }
  2023. else
  2024. if (bwb_stricmp(tbuf, "EXPLICIT") == 0)
  2025. {
  2026. l->cmdnum = C_OPTION_EXPLICIT;
  2027. l->Startpos = position;
  2028. }
  2029. else
  2030. if (bwb_stricmp(tbuf, "IMAGE") == 0)
  2031. {
  2032. l->cmdnum = C_OPTION_IMAGE;
  2033. l->Startpos = position;
  2034. }
  2035. else
  2036. if (bwb_stricmp(tbuf, "IMPLICIT") == 0)
  2037. {
  2038. l->cmdnum = C_OPTION_IMPLICIT;
  2039. l->Startpos = position;
  2040. }
  2041. else
  2042. if (bwb_stricmp(tbuf, "INDENT") == 0)
  2043. {
  2044. l->cmdnum = C_OPTION_INDENT;
  2045. l->Startpos = position;
  2046. }
  2047. else
  2048. if (bwb_stricmp(tbuf, "LABELS") == 0)
  2049. {
  2050. buff_read_keyword(l->buffer, &position, tbuf);
  2051. buff_skip_spaces(l->buffer, &position);
  2052. if (bwb_stricmp(tbuf, "OFF") == 0)
  2053. {
  2054. l->cmdnum = C_OPTION_LABELS_OFF;
  2055. l->Startpos = position;
  2056. }
  2057. else
  2058. if (bwb_stricmp(tbuf, "ON") == 0)
  2059. {
  2060. l->cmdnum = C_OPTION_LABELS_ON;
  2061. l->Startpos = position;
  2062. }
  2063. else
  2064. {
  2065. /* syntax error */
  2066. l->cmdnum = 0;
  2067. }
  2068. }
  2069. else
  2070. if (bwb_stricmp(tbuf, "PRINT") == 0)
  2071. {
  2072. l->cmdnum = C_OPTION_PRINT;
  2073. l->Startpos = position;
  2074. }
  2075. else
  2076. if (bwb_stricmp(tbuf, "ROUND") == 0)
  2077. {
  2078. buff_read_keyword(l->buffer, &position, tbuf);
  2079. buff_skip_spaces(l->buffer, &position);
  2080. if (bwb_stricmp(tbuf, "BANK") == 0)
  2081. {
  2082. l->cmdnum = C_OPTION_ROUND_BANK;
  2083. l->Startpos = position;
  2084. }
  2085. else
  2086. if (bwb_stricmp(tbuf, "MATH") == 0)
  2087. {
  2088. l->cmdnum = C_OPTION_ROUND_MATH;
  2089. l->Startpos = position;
  2090. }
  2091. else
  2092. if (bwb_stricmp(tbuf, "TRUNCATE") == 0)
  2093. {
  2094. l->cmdnum = C_OPTION_ROUND_TRUNCATE;
  2095. l->Startpos = position;
  2096. }
  2097. else
  2098. {
  2099. /* syntax error */
  2100. l->cmdnum = 0;
  2101. }
  2102. }
  2103. else
  2104. if (bwb_stricmp(tbuf, "SLEEP") == 0)
  2105. {
  2106. l->cmdnum = C_OPTION_SLEEP;
  2107. l->Startpos = position;
  2108. }
  2109. else
  2110. if (bwb_stricmp(tbuf, "STATEMENT") == 0)
  2111. {
  2112. l->cmdnum = C_OPTION_STATEMENT;
  2113. l->Startpos = position;
  2114. }
  2115. else
  2116. if (bwb_stricmp(tbuf, "STRICT") == 0)
  2117. {
  2118. buff_read_keyword(l->buffer, &position, tbuf);
  2119. buff_skip_spaces(l->buffer, &position);
  2120. if (bwb_stricmp(tbuf, "OFF") == 0)
  2121. {
  2122. l->cmdnum = C_OPTION_STRICT_OFF;
  2123. l->Startpos = position;
  2124. }
  2125. else
  2126. if (bwb_stricmp(tbuf, "ON") == 0)
  2127. {
  2128. l->cmdnum = C_OPTION_STRICT_ON;
  2129. l->Startpos = position;
  2130. }
  2131. else
  2132. {
  2133. /* syntax error */
  2134. l->cmdnum = 0;
  2135. }
  2136. }
  2137. else
  2138. if (bwb_stricmp(tbuf, "TERMINAL") == 0)
  2139. {
  2140. buff_read_keyword(l->buffer, &position, tbuf);
  2141. buff_skip_spaces(l->buffer, &position);
  2142. if (bwb_stricmp(tbuf, "NONE") == 0)
  2143. {
  2144. l->cmdnum = C_OPTION_TERMINAL_NONE;
  2145. l->Startpos = position;
  2146. }
  2147. else
  2148. if (bwb_stricmp(tbuf, "ADM-3A") == 0)
  2149. {
  2150. l->cmdnum = C_OPTION_TERMINAL_ADM;
  2151. l->Startpos = position;
  2152. }
  2153. else
  2154. if (bwb_stricmp(tbuf, "ANSI") == 0)
  2155. {
  2156. l->cmdnum = C_OPTION_TERMINAL_ANSI;
  2157. l->Startpos = position;
  2158. }
  2159. else
  2160. {
  2161. /* syntax error */
  2162. l->cmdnum = 0;
  2163. }
  2164. }
  2165. else
  2166. if (bwb_stricmp(tbuf, "TIME") == 0)
  2167. {
  2168. l->cmdnum = C_OPTION_TIME;
  2169. l->Startpos = position;
  2170. }
  2171. else
  2172. if (bwb_stricmp(tbuf, "TRACE") == 0)
  2173. {
  2174. buff_read_keyword(l->buffer, &position, tbuf);
  2175. buff_skip_spaces(l->buffer, &position);
  2176. if (bwb_stricmp(tbuf, "OFF") == 0)
  2177. {
  2178. l->cmdnum = C_OPTION_TRACE_OFF;
  2179. l->Startpos = position;
  2180. }
  2181. else
  2182. if (bwb_stricmp(tbuf, "ON") == 0)
  2183. {
  2184. l->cmdnum = C_OPTION_TRACE_ON;
  2185. l->Startpos = position;
  2186. }
  2187. else
  2188. {
  2189. /* syntax error */
  2190. l->cmdnum = 0;
  2191. }
  2192. }
  2193. else
  2194. if (bwb_stricmp(tbuf, "VERSION") == 0)
  2195. {
  2196. l->cmdnum = C_OPTION_VERSION;
  2197. l->Startpos = position;
  2198. }
  2199. else
  2200. if (bwb_stricmp(tbuf, "USING") == 0)
  2201. {
  2202. l->cmdnum = C_OPTION_USING;
  2203. l->Startpos = position;
  2204. }
  2205. else
  2206. {
  2207. /* syntax error */
  2208. l->cmdnum = 0;
  2209. }
  2210. }
  2211. else
  2212. if (l->cmdnum == C_SELECT)
  2213. {
  2214. position = l->Startpos;
  2215. buff_read_keyword(l->buffer, &position, tbuf);
  2216. buff_skip_spaces(l->buffer, &position);
  2217. if (bwb_stricmp(tbuf, "CASE") == 0)
  2218. {
  2219. l->cmdnum = C_SELECT_CASE;
  2220. l->Startpos = position;
  2221. }
  2222. else
  2223. {
  2224. /* syntax error */
  2225. l->cmdnum = 0;
  2226. }
  2227. }
  2228. else
  2229. if (l->cmdnum == C_SUBEND)
  2230. {
  2231. l->cmdnum = C_END_SUB;
  2232. }
  2233. else
  2234. if (l->cmdnum == C_TIMER)
  2235. {
  2236. position = l->Startpos;
  2237. buff_read_keyword(l->buffer, &position, tbuf);
  2238. buff_skip_spaces(l->buffer, &position);
  2239. if (bwb_stricmp(tbuf, "OFF") == 0)
  2240. {
  2241. l->cmdnum = C_TIMER_OFF;
  2242. l->Startpos = position;
  2243. }
  2244. else
  2245. if (bwb_stricmp(tbuf, "ON") == 0)
  2246. {
  2247. l->cmdnum = C_TIMER_ON;
  2248. l->Startpos = position;
  2249. }
  2250. else
  2251. if (bwb_stricmp(tbuf, "STOP") == 0)
  2252. {
  2253. l->cmdnum = C_TIMER_STOP;
  2254. l->Startpos = position;
  2255. }
  2256. else
  2257. {
  2258. /* syntax error */
  2259. l->cmdnum = 0;
  2260. }
  2261. }
  2262. else
  2263. if (l->cmdnum == C_TRACE)
  2264. {
  2265. position = l->Startpos;
  2266. buff_read_keyword(l->buffer, &position, tbuf);
  2267. buff_skip_spaces(l->buffer, &position);
  2268. if (bwb_stricmp(tbuf, "OFF") == 0)
  2269. {
  2270. l->cmdnum = C_TRACE_OFF;
  2271. l->Startpos = position;
  2272. }
  2273. else
  2274. if (bwb_stricmp(tbuf, "ON") == 0)
  2275. {
  2276. l->cmdnum = C_TRACE_ON;
  2277. l->Startpos = position;
  2278. }
  2279. else
  2280. {
  2281. /* plain TRACE */
  2282. }
  2283. }
  2284. /* check for a bogus assignment to a command */
  2285. /* 100 PRINT = X */
  2286. if (l->cmdnum == 0)
  2287. {
  2288. /* syntax error */
  2289. return FALSE;
  2290. }
  2291. /* add to the Function-Sub-Label list */
  2292. switch (l->cmdnum)
  2293. {
  2294. case C_DEF:
  2295. case C_FUNCTION:
  2296. case C_SUB:
  2297. case C_USER_LBL:
  2298. fslt_add(l);
  2299. break;
  2300. }
  2301. /* done */
  2302. return TRUE;
  2303. #endif
  2304. }
  2305. /* not a COMMAND */
  2306. /* check for implied LET */
  2307. if (is_let(l->buffer) == TRUE)
  2308. {
  2309. /* this is an implied LET */
  2310. /* 100 A = 123 */
  2311. l->cmdnum = C_LET; /* bwb_LET */
  2312. l->Startpos = 0;
  2313. return TRUE;
  2314. }
  2315. /* not an implied LET */
  2316. /* check for FUNCTION */
  2317. if (fnc_find(tbuf) != NULL)
  2318. {
  2319. /* check for a bogus assignment to a function */
  2320. /* 100 COS = X */
  2321. if( buff_peek_char(l->buffer, &position, '=' ) )
  2322. {
  2323. /* syntax error */
  2324. l->cmdnum = 0;
  2325. return FALSE;
  2326. }
  2327. /* user is executing a function, such as 100 COS X */
  2328. l->cmdnum = C_DEF_SUB; /* bwb_DEF_SUB, in bwb_tbl.c */
  2329. l->Startpos = 0;
  2330. return TRUE;
  2331. }
  2332. /* not a FUNCTION */
  2333. /* check for LABEL */
  2334. if (My->CurrentVersion->OptionFlags & OPTION_LABELS_ON)
  2335. {
  2336. /* labels are enabled */
  2337. if( My->CurrentVersion->OptionStatementChar != BasicNulChar )
  2338. {
  2339. /* a Statement seperator exists */
  2340. if( buff_skip_char(l->buffer, &position, My->CurrentVersion->OptionStatementChar) )
  2341. {
  2342. /* this is a label */
  2343. /* 100 MyLabel: */
  2344. l->cmdnum = C_USER_LBL; /* bwb_USER_LBL */
  2345. buff_skip_spaces(l->buffer, &position);
  2346. l->Startpos = position;
  2347. return TRUE;
  2348. }
  2349. }
  2350. }
  2351. /* not a LABEL */
  2352. /* ERROR */
  2353. return FALSE;
  2354. }
  2355. /***************************************************************
  2356. FUNCTION: is_cmd()
  2357. DESCRIPTION: This function determines whether the
  2358. string in 'buffer' is a BASIC command
  2359. statement, returning 'id' or 0.
  2360. ***************************************************************/
  2361. int
  2362. is_cmd(char *buffer)
  2363. {
  2364. #if THE_PRICE_IS_RIGHT
  2365. char C;
  2366. bwx_DEBUG(__FUNCTION__);
  2367. #if FALSE
  2368. printf( "check [%s]\n", buffer ); /* HWULF */
  2369. #endif
  2370. C = buffer[0];
  2371. if( bwb_isalpha( C ) )
  2372. {
  2373. /* start with the closest command, without going over */
  2374. int n;
  2375. n = My->CommandStart[ VarTypeIndex( C ) ]; /* first command starting with this letter, assigned in SortAllCommands() */
  2376. if( n < 0 )
  2377. {
  2378. /* NOT FOUND */
  2379. return 0;
  2380. }
  2381. for( ; n < NUM_COMMANDS; n++ )
  2382. {
  2383. if (My->CurrentVersion->OptionVersionBitmask & bwb_cmdtable[n].OptionVersionBitmask)
  2384. {
  2385. int result;
  2386. result = bwb_stricmp(bwb_cmdtable[n].name, buffer);
  2387. if( result == 0 )
  2388. {
  2389. /* FOUND */
  2390. #if FALSE
  2391. printf( "found [%s]\n", buffer ); /* HWULF */
  2392. #endif
  2393. return bwb_cmdtable[n].id;
  2394. }
  2395. if( result > 0 /* found > searched */ )
  2396. {
  2397. /* NOT FOUND */
  2398. return 0;
  2399. }
  2400. }
  2401. }
  2402. }
  2403. /* NOT FOUND */
  2404. return 0;
  2405. #else
  2406. register int n;
  2407. bwx_DEBUG(__FUNCTION__);
  2408. /* Go through the command table and search for a match. */
  2409. for (n = 0; n < NUM_COMMANDS; ++n)
  2410. {
  2411. if (My->CurrentVersion->OptionVersionBitmask & bwb_cmdtable[n].OptionVersionBitmask)
  2412. if (bwb_stricmp(bwb_cmdtable[n].name, buffer) == 0)
  2413. {
  2414. return bwb_cmdtable[n].id;
  2415. }
  2416. }
  2417. /* No command name was found */
  2418. return 0;
  2419. #endif
  2420. }
  2421. /***************************************************************
  2422. FUNCTION: is_let()
  2423. DESCRIPTION: This function tries to determine if the
  2424. expression in <buffer> is a LET statement
  2425. without the LET command specified.
  2426. ***************************************************************/
  2427. int
  2428. is_let(char *buffer)
  2429. {
  2430. register int n;
  2431. bwx_DEBUG(__FUNCTION__);
  2432. /* Go through the expression and search for an unquoted assignment operator. */
  2433. for (n = 0; buffer[n] != BasicNulChar; ++n)
  2434. {
  2435. switch (buffer[n])
  2436. {
  2437. case BasicQuoteChar: /* string constant */
  2438. ++n;
  2439. while (buffer[n] != BasicQuoteChar)
  2440. {
  2441. ++n;
  2442. if (buffer[n] == BasicNulChar)
  2443. {
  2444. WARN_SYNTAX_ERROR;
  2445. return FALSE;
  2446. }
  2447. }
  2448. ++n;
  2449. break;
  2450. case '=':
  2451. return TRUE;
  2452. }
  2453. }
  2454. /* No command name was found */
  2455. return FALSE;
  2456. }
  2457. /***************************************************************
  2458. FUNCTION: bwb_stripcr()
  2459. DESCRIPTION: This function strips the carriage return
  2460. or line-feed from the end of a string.
  2461. ***************************************************************/
  2462. int
  2463. bwb_stripcr(char *s)
  2464. {
  2465. char *E;
  2466. bwx_DEBUG(__FUNCTION__);
  2467. E = bwb_strchr(s, '\r');
  2468. if( E != NULL )
  2469. {
  2470. *E = BasicNulChar;
  2471. }
  2472. E = bwb_strchr(s, '\n');
  2473. if( E != NULL )
  2474. {
  2475. *E = BasicNulChar;
  2476. }
  2477. while (*s)
  2478. {
  2479. if ( ! bwb_isprint( *s ) )
  2480. {
  2481. *s = ' ';
  2482. }
  2483. s++;
  2484. }
  2485. return TRUE;
  2486. }
  2487. /***************************************************************
  2488. FUNCTION: is_numconst()
  2489. DESCRIPTION: This function reads the string in <buffer>
  2490. and returns TRUE if it is a numerical
  2491. constant and FALSE if it is not. At
  2492. this point, only decimal (base 10)
  2493. constants are detected.
  2494. ***************************************************************/
  2495. int
  2496. is_numconst(char *buffer)
  2497. {
  2498. char *p;
  2499. bwx_DEBUG(__FUNCTION__);
  2500. /* Return FALSE for empty buffer */
  2501. if (buffer[0] == BasicNulChar)
  2502. {
  2503. return FALSE;
  2504. }
  2505. /* else check digits */
  2506. p = buffer;
  2507. while (*p != BasicNulChar)
  2508. {
  2509. switch (*p)
  2510. {
  2511. case '0':
  2512. case '1':
  2513. case '2':
  2514. case '3':
  2515. case '4':
  2516. case '5':
  2517. case '6':
  2518. case '7':
  2519. case '8':
  2520. case '9':
  2521. break;
  2522. default:
  2523. return FALSE;
  2524. }
  2525. ++p;
  2526. }
  2527. /* only numerical characters detected */
  2528. return TRUE;
  2529. }
  2530. /***************************************************************
  2531. FUNCTION: bwb_freeline()
  2532. DESCRIPTION: This function frees memory associated
  2533. with a program line in memory.
  2534. ***************************************************************/
  2535. int
  2536. bwb_freeline(LineType * l)
  2537. {
  2538. bwx_DEBUG(__FUNCTION__);
  2539. /* free arguments if there are any */
  2540. /* Revised to FREE pass-thru calls by JBV */
  2541. if (l->buffer != NULL)
  2542. {
  2543. FREE(l->buffer, "bwb_freeline");
  2544. l->buffer = NULL; /* JBV */
  2545. }
  2546. FREE(l, "bwb_freeline");
  2547. /* l = NULL; *//* Assignment of function parameter has no effect
  2548. * outside the function. */
  2549. return TRUE;
  2550. }
  2551. #if FALSE
  2552. /***************************************************************
  2553. FUNCTION: is_eol()
  2554. DESCRIPTION: This function determines whether the buffer
  2555. is at the end of a line.
  2556. ***************************************************************/
  2557. int
  2558. is_eol(char *buffer, int *position)
  2559. {
  2560. char c;
  2561. bwx_DEBUG(__FUNCTION__);
  2562. buff_skip_spaces(buffer, position);
  2563. c = buffer[*position];
  2564. if (c == BasicNulChar || c == My->CurrentVersion->OptionCommentChar)
  2565. {
  2566. return TRUE;
  2567. }
  2568. return FALSE;
  2569. }
  2570. char *
  2571. GetRestOfLine(LineType * l, char *OutputBuffer)
  2572. {
  2573. char *S;
  2574. char *C;
  2575. bwx_DEBUG(__FUNCTION__);
  2576. S = l->buffer;
  2577. S += l->position;
  2578. C = S;
  2579. while (*C != BasicNulChar && *C != My->CurrentVersion->OptionCommentChar)
  2580. {
  2581. C++;
  2582. }
  2583. /* FOUND */
  2584. if (OutputBuffer != NULL)
  2585. {
  2586. char c;
  2587. c = *C;
  2588. *C = BasicNulChar;
  2589. l->position += bwb_strlen(S);
  2590. bwb_strcpy(OutputBuffer, S);
  2591. *C = c;
  2592. }
  2593. return C;
  2594. }
  2595. #endif /* FALSE */
  2596. char *
  2597. GetKeyword(LineType * l, char *OutputBuffer, char *Keyword)
  2598. {
  2599. /* if OutputBuffer is NULL then we just want to know if a keyword
  2600. * exists, and if so where to look after the keyword. this is used by
  2601. * line_start() in bwb_int.c to determine various command flavors.
  2602. * else we want to extract the expression before the keyword and
  2603. * update the position to after the keyword. this is used by various
  2604. * bwb_XXX() when executing BASIC commands. end if
  2605. *
  2606. * if FOUND then if OutputBuffer != NULL then copy line's buffer BEFORE
  2607. * keyword into OutputBuffer update line's position to AFTER keyword
  2608. * end if return pointer AFTER keyword else return NULL end if */
  2609. char *S;
  2610. char *C;
  2611. int n;
  2612. bwx_DEBUG(__FUNCTION__);
  2613. S = l->buffer;
  2614. S += l->position;
  2615. C = S;
  2616. n = bwb_strlen(Keyword);
  2617. while (*C != BasicNulChar && *C != My->CurrentVersion->OptionCommentChar)
  2618. {
  2619. if (bwb_strnicmp(C, Keyword, n) == 0)
  2620. {
  2621. /* FOUND */
  2622. char c;
  2623. c = *C;
  2624. *C = BasicNulChar;
  2625. if (OutputBuffer != NULL)
  2626. {
  2627. l->position += bwb_strlen(S);
  2628. l->position += n;
  2629. bwb_strcpy(OutputBuffer, S);
  2630. }
  2631. *C = c;
  2632. C += n;
  2633. return C;
  2634. }
  2635. else
  2636. if (*C == BasicQuoteChar)
  2637. {
  2638. /* skip string constant */
  2639. C++;
  2640. while (*C != BasicNulChar && *C != BasicQuoteChar)
  2641. {
  2642. C++;
  2643. }
  2644. if (*C == BasicQuoteChar)
  2645. {
  2646. C++;
  2647. }
  2648. }
  2649. else
  2650. {
  2651. /* skip normal character */
  2652. C++;
  2653. }
  2654. }
  2655. /* NOT FOUND */
  2656. return NULL;
  2657. }
  2658. int
  2659. IsLastKeyword(LineType * l, char *Keyword)
  2660. {
  2661. /* find the end of the line ( 0 or ' ) */
  2662. /* backup thru spaces */
  2663. int n;
  2664. char *S;
  2665. char *C;
  2666. bwx_DEBUG(__FUNCTION__);
  2667. S = l->buffer;
  2668. S += l->position;
  2669. C = S;
  2670. n = bwb_strlen(Keyword);
  2671. S += n;
  2672. /* IF x THEN0 IF x THEN'0 IF x THEN ' 0 */
  2673. while (*C != BasicNulChar && *C != My->CurrentVersion->OptionCommentChar)
  2674. {
  2675. /* skip string constants */
  2676. if( *C == BasicQuoteChar )
  2677. {
  2678. /* skip leading quote */
  2679. C++;
  2680. while (*C != BasicNulChar && *C != BasicQuoteChar)
  2681. {
  2682. C++;
  2683. }
  2684. /* skip trailing quote */
  2685. if( *C == BasicQuoteChar )
  2686. {
  2687. C++;
  2688. }
  2689. }
  2690. else
  2691. {
  2692. C++;
  2693. }
  2694. }
  2695. if (C > S)
  2696. {
  2697. C--;
  2698. while (C > S && *C == ' ')
  2699. {
  2700. C--;
  2701. }
  2702. C++;
  2703. if (C > S)
  2704. {
  2705. C -= n;
  2706. if (bwb_strnicmp(C, Keyword, n) == 0)
  2707. {
  2708. /* FOUND */
  2709. return TRUE;
  2710. }
  2711. }
  2712. }
  2713. /* NOT FOUND */
  2714. return FALSE;
  2715. }
  2716. int bwb_isalnum( int C )
  2717. {
  2718. /*
  2719. 4.3.1.1 The isalnum function
  2720. Synopsis
  2721. #include <ctype.h>
  2722. int isalnum(int c);
  2723. Description
  2724. The isalnum function tests for any character for which isalpha or
  2725. isdigit is true.
  2726. */
  2727. switch( C )
  2728. {
  2729. case '0':
  2730. case '1':
  2731. case '2':
  2732. case '3':
  2733. case '4':
  2734. case '5':
  2735. case '6':
  2736. case '7':
  2737. case '8':
  2738. case '9':
  2739. case 'A':
  2740. case 'B':
  2741. case 'C':
  2742. case 'D':
  2743. case 'E':
  2744. case 'F':
  2745. case 'G':
  2746. case 'H':
  2747. case 'I':
  2748. case 'J':
  2749. case 'K':
  2750. case 'L':
  2751. case 'M':
  2752. case 'N':
  2753. case 'O':
  2754. case 'P':
  2755. case 'Q':
  2756. case 'R':
  2757. case 'S':
  2758. case 'T':
  2759. case 'U':
  2760. case 'V':
  2761. case 'W':
  2762. case 'X':
  2763. case 'Y':
  2764. case 'Z':
  2765. case 'a':
  2766. case 'b':
  2767. case 'c':
  2768. case 'd':
  2769. case 'e':
  2770. case 'f':
  2771. case 'g':
  2772. case 'h':
  2773. case 'i':
  2774. case 'j':
  2775. case 'k':
  2776. case 'l':
  2777. case 'm':
  2778. case 'n':
  2779. case 'o':
  2780. case 'p':
  2781. case 'q':
  2782. case 'r':
  2783. case 's':
  2784. case 't':
  2785. case 'u':
  2786. case 'v':
  2787. case 'w':
  2788. case 'x':
  2789. case 'y':
  2790. case 'z':
  2791. return TRUE;
  2792. }
  2793. return FALSE;
  2794. }
  2795. int bwb_isalpha( int C )
  2796. {
  2797. /*
  2798. 4.3.1.2 The isalpha function
  2799. Synopsis
  2800. #include <ctype.h>
  2801. int isalpha(int c);
  2802. Description
  2803. The isalpha function tests for any character for which isupper or
  2804. islower is true, or any of an implementation-defined set of characters
  2805. for which none of iscntrl , isdigit , ispunct , or isspace is true.
  2806. In the C locale, isalpha returns true only for the characters for
  2807. which isupper or islower is true.
  2808. */
  2809. switch( C )
  2810. {
  2811. case 'A':
  2812. case 'B':
  2813. case 'C':
  2814. case 'D':
  2815. case 'E':
  2816. case 'F':
  2817. case 'G':
  2818. case 'H':
  2819. case 'I':
  2820. case 'J':
  2821. case 'K':
  2822. case 'L':
  2823. case 'M':
  2824. case 'N':
  2825. case 'O':
  2826. case 'P':
  2827. case 'Q':
  2828. case 'R':
  2829. case 'S':
  2830. case 'T':
  2831. case 'U':
  2832. case 'V':
  2833. case 'W':
  2834. case 'X':
  2835. case 'Y':
  2836. case 'Z':
  2837. case 'a':
  2838. case 'b':
  2839. case 'c':
  2840. case 'd':
  2841. case 'e':
  2842. case 'f':
  2843. case 'g':
  2844. case 'h':
  2845. case 'i':
  2846. case 'j':
  2847. case 'k':
  2848. case 'l':
  2849. case 'm':
  2850. case 'n':
  2851. case 'o':
  2852. case 'p':
  2853. case 'q':
  2854. case 'r':
  2855. case 's':
  2856. case 't':
  2857. case 'u':
  2858. case 'v':
  2859. case 'w':
  2860. case 'x':
  2861. case 'y':
  2862. case 'z':
  2863. return TRUE;
  2864. }
  2865. return FALSE;
  2866. }
  2867. int bwb_iscntrl( int C )
  2868. {
  2869. /*
  2870. 4.3.1.3 The iscntrl function
  2871. Synopsis
  2872. #include <ctype.h>
  2873. int iscntrl(int c);
  2874. Description
  2875. The iscntrl function tests for any control character.
  2876. */
  2877. switch( C )
  2878. {
  2879. case ' ':
  2880. case '!':
  2881. case '"':
  2882. case '#':
  2883. case '$':
  2884. case '%':
  2885. case '&':
  2886. case '\'':
  2887. case '(':
  2888. case ')':
  2889. case '*':
  2890. case '+':
  2891. case ',':
  2892. case '-':
  2893. case '.':
  2894. case '/':
  2895. case '0':
  2896. case '1':
  2897. case '2':
  2898. case '3':
  2899. case '4':
  2900. case '5':
  2901. case '6':
  2902. case '7':
  2903. case '8':
  2904. case '9':
  2905. case ':':
  2906. case ';':
  2907. case '<':
  2908. case '=':
  2909. case '>':
  2910. case '?':
  2911. case '@':
  2912. case 'A':
  2913. case 'B':
  2914. case 'C':
  2915. case 'D':
  2916. case 'E':
  2917. case 'F':
  2918. case 'G':
  2919. case 'H':
  2920. case 'I':
  2921. case 'J':
  2922. case 'K':
  2923. case 'L':
  2924. case 'M':
  2925. case 'N':
  2926. case 'O':
  2927. case 'P':
  2928. case 'Q':
  2929. case 'R':
  2930. case 'S':
  2931. case 'T':
  2932. case 'U':
  2933. case 'V':
  2934. case 'W':
  2935. case 'X':
  2936. case 'Y':
  2937. case 'Z':
  2938. case '[':
  2939. case '\\':
  2940. case ']':
  2941. case '^':
  2942. case '_':
  2943. case '`':
  2944. case 'a':
  2945. case 'b':
  2946. case 'c':
  2947. case 'd':
  2948. case 'e':
  2949. case 'f':
  2950. case 'g':
  2951. case 'h':
  2952. case 'i':
  2953. case 'j':
  2954. case 'k':
  2955. case 'l':
  2956. case 'm':
  2957. case 'n':
  2958. case 'o':
  2959. case 'p':
  2960. case 'q':
  2961. case 'r':
  2962. case 's':
  2963. case 't':
  2964. case 'u':
  2965. case 'v':
  2966. case 'w':
  2967. case 'x':
  2968. case 'y':
  2969. case 'z':
  2970. case '{':
  2971. case '|':
  2972. case '}':
  2973. case '~':
  2974. return FALSE;
  2975. }
  2976. return TRUE;
  2977. }
  2978. int bwb_isdigit( int C )
  2979. {
  2980. /*
  2981. 4.3.1.4 The isdigit function
  2982. Synopsis
  2983. #include <ctype.h>
  2984. int isdigit(int c);
  2985. Description
  2986. The isdigit function tests for any decimal-digit character (as
  2987. defined in $2.2.1).
  2988. */
  2989. switch( C )
  2990. {
  2991. case '0':
  2992. case '1':
  2993. case '2':
  2994. case '3':
  2995. case '4':
  2996. case '5':
  2997. case '6':
  2998. case '7':
  2999. case '8':
  3000. case '9':
  3001. return TRUE;
  3002. }
  3003. return FALSE;
  3004. }
  3005. int bwb_isgraph( int C )
  3006. {
  3007. /*
  3008. 4.3.1.5 The isgraph function
  3009. Synopsis
  3010. #include <ctype.h>
  3011. int isgraph(int c);
  3012. Description
  3013. The isgraph function tests for any printing character except space (' ').
  3014. */
  3015. switch( C )
  3016. {
  3017. case '!':
  3018. case '"':
  3019. case '#':
  3020. case '$':
  3021. case '%':
  3022. case '&':
  3023. case '\'':
  3024. case '(':
  3025. case ')':
  3026. case '*':
  3027. case '+':
  3028. case ',':
  3029. case '-':
  3030. case '.':
  3031. case '/':
  3032. case '0':
  3033. case '1':
  3034. case '2':
  3035. case '3':
  3036. case '4':
  3037. case '5':
  3038. case '6':
  3039. case '7':
  3040. case '8':
  3041. case '9':
  3042. case ':':
  3043. case ';':
  3044. case '<':
  3045. case '=':
  3046. case '>':
  3047. case '?':
  3048. case '@':
  3049. case 'A':
  3050. case 'B':
  3051. case 'C':
  3052. case 'D':
  3053. case 'E':
  3054. case 'F':
  3055. case 'G':
  3056. case 'H':
  3057. case 'I':
  3058. case 'J':
  3059. case 'K':
  3060. case 'L':
  3061. case 'M':
  3062. case 'N':
  3063. case 'O':
  3064. case 'P':
  3065. case 'Q':
  3066. case 'R':
  3067. case 'S':
  3068. case 'T':
  3069. case 'U':
  3070. case 'V':
  3071. case 'W':
  3072. case 'X':
  3073. case 'Y':
  3074. case 'Z':
  3075. case '[':
  3076. case '\\':
  3077. case ']':
  3078. case '^':
  3079. case '_':
  3080. case '`':
  3081. case 'a':
  3082. case 'b':
  3083. case 'c':
  3084. case 'd':
  3085. case 'e':
  3086. case 'f':
  3087. case 'g':
  3088. case 'h':
  3089. case 'i':
  3090. case 'j':
  3091. case 'k':
  3092. case 'l':
  3093. case 'm':
  3094. case 'n':
  3095. case 'o':
  3096. case 'p':
  3097. case 'q':
  3098. case 'r':
  3099. case 's':
  3100. case 't':
  3101. case 'u':
  3102. case 'v':
  3103. case 'w':
  3104. case 'x':
  3105. case 'y':
  3106. case 'z':
  3107. case '{':
  3108. case '|':
  3109. case '}':
  3110. case '~':
  3111. return TRUE;
  3112. }
  3113. return FALSE;
  3114. }
  3115. int bwb_islower( int C )
  3116. {
  3117. /*
  3118. 4.3.1.6 The islower function
  3119. Synopsis
  3120. #include <ctype.h>
  3121. int islower(int c);
  3122. Description
  3123. The islower function tests for any lower-case letter or any of an
  3124. implementation-defined set of characters for which none of iscntrl ,
  3125. isdigit , ispunct , or isspace is true. In the C locale, islower
  3126. returns true only for the characters defined as lower-case letters (as
  3127. defined in $2.2.1).
  3128. */
  3129. switch( C )
  3130. {
  3131. case 'a':
  3132. case 'b':
  3133. case 'c':
  3134. case 'd':
  3135. case 'e':
  3136. case 'f':
  3137. case 'g':
  3138. case 'h':
  3139. case 'i':
  3140. case 'j':
  3141. case 'k':
  3142. case 'l':
  3143. case 'm':
  3144. case 'n':
  3145. case 'o':
  3146. case 'p':
  3147. case 'q':
  3148. case 'r':
  3149. case 's':
  3150. case 't':
  3151. case 'u':
  3152. case 'v':
  3153. case 'w':
  3154. case 'x':
  3155. case 'y':
  3156. case 'z':
  3157. return TRUE;
  3158. }
  3159. return FALSE;
  3160. }
  3161. int bwb_isprint( int C )
  3162. {
  3163. /*
  3164. 4.3.1.7 The isprint function
  3165. Synopsis
  3166. #include <ctype.h>
  3167. int isprint(int c);
  3168. Description
  3169. The isprint function tests for any printing character including
  3170. space (' ').
  3171. */
  3172. switch( C )
  3173. {
  3174. case ' ':
  3175. case '!':
  3176. case '"':
  3177. case '#':
  3178. case '$':
  3179. case '%':
  3180. case '&':
  3181. case '\'':
  3182. case '(':
  3183. case ')':
  3184. case '*':
  3185. case '+':
  3186. case ',':
  3187. case '-':
  3188. case '.':
  3189. case '/':
  3190. case '0':
  3191. case '1':
  3192. case '2':
  3193. case '3':
  3194. case '4':
  3195. case '5':
  3196. case '6':
  3197. case '7':
  3198. case '8':
  3199. case '9':
  3200. case ':':
  3201. case ';':
  3202. case '<':
  3203. case '=':
  3204. case '>':
  3205. case '?':
  3206. case '@':
  3207. case 'A':
  3208. case 'B':
  3209. case 'C':
  3210. case 'D':
  3211. case 'E':
  3212. case 'F':
  3213. case 'G':
  3214. case 'H':
  3215. case 'I':
  3216. case 'J':
  3217. case 'K':
  3218. case 'L':
  3219. case 'M':
  3220. case 'N':
  3221. case 'O':
  3222. case 'P':
  3223. case 'Q':
  3224. case 'R':
  3225. case 'S':
  3226. case 'T':
  3227. case 'U':
  3228. case 'V':
  3229. case 'W':
  3230. case 'X':
  3231. case 'Y':
  3232. case 'Z':
  3233. case '[':
  3234. case '\\':
  3235. case ']':
  3236. case '^':
  3237. case '_':
  3238. case '`':
  3239. case 'a':
  3240. case 'b':
  3241. case 'c':
  3242. case 'd':
  3243. case 'e':
  3244. case 'f':
  3245. case 'g':
  3246. case 'h':
  3247. case 'i':
  3248. case 'j':
  3249. case 'k':
  3250. case 'l':
  3251. case 'm':
  3252. case 'n':
  3253. case 'o':
  3254. case 'p':
  3255. case 'q':
  3256. case 'r':
  3257. case 's':
  3258. case 't':
  3259. case 'u':
  3260. case 'v':
  3261. case 'w':
  3262. case 'x':
  3263. case 'y':
  3264. case 'z':
  3265. case '{':
  3266. case '|':
  3267. case '}':
  3268. case '~':
  3269. return TRUE;
  3270. }
  3271. return FALSE;
  3272. }
  3273. int bwb_ispunct( int C )
  3274. {
  3275. /*
  3276. 4.3.1.8 The ispunct function
  3277. Synopsis
  3278. #include <ctype.h>
  3279. int ispunct(int c);
  3280. Description
  3281. The ispunct function tests for any printing character except space
  3282. (' ') or a character for which isalnum is true.
  3283. */
  3284. switch( C )
  3285. {
  3286. case '!':
  3287. case '"':
  3288. case '#':
  3289. case '$':
  3290. case '%':
  3291. case '&':
  3292. case '\'':
  3293. case '(':
  3294. case ')':
  3295. case '*':
  3296. case '+':
  3297. case ',':
  3298. case '-':
  3299. case '.':
  3300. case '/':
  3301. case ':':
  3302. case ';':
  3303. case '<':
  3304. case '=':
  3305. case '>':
  3306. case '?':
  3307. case '@':
  3308. case '[':
  3309. case '\\':
  3310. case ']':
  3311. case '^':
  3312. case '_':
  3313. case '`':
  3314. case '{':
  3315. case '|':
  3316. case '}':
  3317. case '~':
  3318. return TRUE;
  3319. }
  3320. return FALSE;
  3321. }
  3322. int bwb_isspace( int C )
  3323. {
  3324. /*
  3325. 4.3.1.9 The isspace function
  3326. Synopsis
  3327. #include <ctype.h>
  3328. int isspace(int c);
  3329. Description
  3330. The isspace function tests for the standard white-space characters
  3331. or for any of an implementation-defined set of characters for which
  3332. isalnum is false. The standard white-space characters are the
  3333. following: space (' '), form feed ('\f'), new-line ('\n'), carriage
  3334. return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). In the
  3335. C locale, isspace returns true only for the standard white-space
  3336. characters.
  3337. */
  3338. switch( C )
  3339. {
  3340. case '\f':
  3341. case '\n':
  3342. case '\r':
  3343. case '\t':
  3344. case '\v':
  3345. case ' ':
  3346. return TRUE;
  3347. }
  3348. return FALSE;
  3349. }
  3350. int bwb_isupper( int C )
  3351. {
  3352. /*
  3353. 4.3.1.10 The isupper function
  3354. Synopsis
  3355. #include <ctype.h>
  3356. int isupper(int c);
  3357. Description
  3358. The isupper function tests for any upper-case letter or any of an
  3359. implementation-defined set of characters for which none of iscntrl ,
  3360. isdigit , ispunct , or isspace is true. In the C locale, isupper
  3361. returns true only for the characters defined as upper-case letters (as
  3362. defined in $2.2.1).
  3363. */
  3364. switch( C )
  3365. {
  3366. case 'A':
  3367. case 'B':
  3368. case 'C':
  3369. case 'D':
  3370. case 'E':
  3371. case 'F':
  3372. case 'G':
  3373. case 'H':
  3374. case 'I':
  3375. case 'J':
  3376. case 'K':
  3377. case 'L':
  3378. case 'M':
  3379. case 'N':
  3380. case 'O':
  3381. case 'P':
  3382. case 'Q':
  3383. case 'R':
  3384. case 'S':
  3385. case 'T':
  3386. case 'U':
  3387. case 'V':
  3388. case 'W':
  3389. case 'X':
  3390. case 'Y':
  3391. case 'Z':
  3392. return TRUE;
  3393. }
  3394. return FALSE;
  3395. }
  3396. int bwb_isxdigit( int C )
  3397. {
  3398. /*
  3399. 4.3.1.11 The isxdigit function
  3400. Synopsis
  3401. #include <ctype.h>
  3402. int isxdigit(int c);
  3403. Description
  3404. The isxdigit function tests for any hexadecimal-digit character (as
  3405. defined in $3.1.3.2).
  3406. */
  3407. switch( C )
  3408. {
  3409. case '0':
  3410. case '1':
  3411. case '2':
  3412. case '3':
  3413. case '4':
  3414. case '5':
  3415. case '6':
  3416. case '7':
  3417. case '8':
  3418. case '9':
  3419. case 'A':
  3420. case 'B':
  3421. case 'C':
  3422. case 'D':
  3423. case 'E':
  3424. case 'F':
  3425. case 'a':
  3426. case 'b':
  3427. case 'c':
  3428. case 'd':
  3429. case 'e':
  3430. case 'f':
  3431. return TRUE;
  3432. }
  3433. return FALSE;
  3434. }
  3435. int bwb_tolower( int C )
  3436. {
  3437. /*
  3438. 4.3.2.1 The tolower function
  3439. Synopsis
  3440. #include <ctype.h>
  3441. int tolower(int c);
  3442. Description
  3443. The tolower function converts an upper-case letter to the
  3444. corresponding lower-case letter.
  3445. Returns
  3446. If the argument is an upper-case letter, the tolower function
  3447. returns the corresponding lower-case letter if there is one; otherwise
  3448. the argument is returned unchanged. In the C locale, tolower maps
  3449. only the characters for which isupper is true to the corresponding
  3450. characters for which islower is true.
  3451. */
  3452. switch( C )
  3453. {
  3454. case 'A':
  3455. return 'a';
  3456. case 'B':
  3457. return 'b';
  3458. case 'C':
  3459. return 'c';
  3460. case 'D':
  3461. return 'd';
  3462. case 'E':
  3463. return 'e';
  3464. case 'F':
  3465. return 'f';
  3466. case 'G':
  3467. return 'g';
  3468. case 'H':
  3469. return 'h';
  3470. case 'I':
  3471. return 'i';
  3472. case 'J':
  3473. return 'j';
  3474. case 'K':
  3475. return 'k';
  3476. case 'L':
  3477. return 'l';
  3478. case 'M':
  3479. return 'm';
  3480. case 'N':
  3481. return 'n';
  3482. case 'O':
  3483. return 'o';
  3484. case 'P':
  3485. return 'p';
  3486. case 'Q':
  3487. return 'q';
  3488. case 'R':
  3489. return 'r';
  3490. case 'S':
  3491. return 's';
  3492. case 'T':
  3493. return 't';
  3494. case 'U':
  3495. return 'u';
  3496. case 'V':
  3497. return 'v';
  3498. case 'W':
  3499. return 'w';
  3500. case 'X':
  3501. return 'x';
  3502. case 'Y':
  3503. return 'y';
  3504. case 'Z':
  3505. return 'z';
  3506. }
  3507. return C;
  3508. }
  3509. int bwb_toupper( int C )
  3510. {
  3511. /*
  3512. 4.3.2.2 The toupper function
  3513. Synopsis
  3514. #include <ctype.h>
  3515. int toupper(int c);
  3516. Description
  3517. The toupper function converts a lower-case letter to the corresponding upper-case letter.
  3518. Returns
  3519. If the argument is a lower-case letter, the toupper function
  3520. returns the corresponding upper-case letter if there is one; otherwise
  3521. the argument is returned unchanged. In the C locale, toupper maps
  3522. only the characters for which islower is true to the corresponding
  3523. characters for which isupper is true.
  3524. */
  3525. switch( C )
  3526. {
  3527. case 'a':
  3528. return 'A';
  3529. case 'b':
  3530. return 'B';
  3531. case 'c':
  3532. return 'C';
  3533. case 'd':
  3534. return 'D';
  3535. case 'e':
  3536. return 'E';
  3537. case 'f':
  3538. return 'F';
  3539. case 'g':
  3540. return 'G';
  3541. case 'h':
  3542. return 'H';
  3543. case 'i':
  3544. return 'I';
  3545. case 'j':
  3546. return 'J';
  3547. case 'k':
  3548. return 'K';
  3549. case 'l':
  3550. return 'L';
  3551. case 'm':
  3552. return 'M';
  3553. case 'n':
  3554. return 'N';
  3555. case 'o':
  3556. return 'O';
  3557. case 'p':
  3558. return 'P';
  3559. case 'q':
  3560. return 'Q';
  3561. case 'r':
  3562. return 'R';
  3563. case 's':
  3564. return 'S';
  3565. case 't':
  3566. return 'T';
  3567. case 'u':
  3568. return 'U';
  3569. case 'v':
  3570. return 'V';
  3571. case 'w':
  3572. return 'W';
  3573. case 'x':
  3574. return 'X';
  3575. case 'y':
  3576. return 'Y';
  3577. case 'z':
  3578. return 'Z';
  3579. }
  3580. return C;
  3581. }
  3582. void *
  3583. bwb_memcpy(void *s1, const void *s2, size_t n)
  3584. {
  3585. /*
  3586. 4.11.2.1 The memcpy function
  3587. Synopsis
  3588. #include <string.h>
  3589. void *memcpy(void *s1, const void *s2, size_t n);
  3590. Description
  3591. The memcpy function copies n characters from the object pointed to
  3592. by s2 into the object pointed to by s1 . If copying takes place
  3593. between objects that overlap, the behavior is undefined.
  3594. Returns
  3595. The memcpy function returns the value of s1 .
  3596. */
  3597. if( n > 0 )
  3598. {
  3599. char * Target;
  3600. char * Source;
  3601. int p;
  3602. Target = (char *) s1;
  3603. Source = (char *) s2;
  3604. p = 0;
  3605. while( p < n )
  3606. {
  3607. Target[p] = Source[p];
  3608. p++;
  3609. }
  3610. }
  3611. return s1;
  3612. }
  3613. void *
  3614. bwb_memmove(void *s1, const void *s2, size_t n)
  3615. {
  3616. /*
  3617. 4.11.2.2 The memmove function
  3618. Synopsis
  3619. #include <string.h>
  3620. void *memmove(void *s1, const void *s2, size_t n);
  3621. Description
  3622. The memmove function copies n characters from the object pointed to
  3623. by s2 into the object pointed to by s1 . Copying takes place as if
  3624. the n characters from the object pointed to by s2 are first copied
  3625. into a temporary array of n characters that does not overlap the
  3626. objects pointed to by s1 and s2 , and then the n characters from the
  3627. temporary array are copied into the object pointed to by s1 .
  3628. Returns
  3629. The memmove function returns the value of s1 .
  3630. */
  3631. if( n > 0 )
  3632. {
  3633. char * Target;
  3634. char * Source;
  3635. char * Temp;
  3636. Target = (char *) s1;
  3637. Source = (char *) s2;
  3638. Temp = (char *) malloc(n);
  3639. if( Temp != NULL )
  3640. {
  3641. int p;
  3642. p = 0;
  3643. while( p < n )
  3644. {
  3645. Temp[p] = Source[p];
  3646. p++;
  3647. }
  3648. p = 0;
  3649. while( p < n )
  3650. {
  3651. Target[p] = Temp[p];
  3652. p++;
  3653. }
  3654. free(Temp);
  3655. }
  3656. }
  3657. return s1;
  3658. }
  3659. char *
  3660. bwb_strcpy(char *s1, const char *s2)
  3661. {
  3662. /*
  3663. 4.11.2.3 The strcpy function
  3664. Synopsis
  3665. #include <string.h>
  3666. char *strcpy(char *s1, const char *s2);
  3667. Description
  3668. The strcpy function copies the string pointed to by s2 (including
  3669. the terminating null character) into the array pointed to by s1 . If
  3670. copying takes place between objects that overlap, the behavior is
  3671. undefined.
  3672. Returns
  3673. The strcpy function returns the value of s1 .
  3674. */
  3675. char C;
  3676. int p;
  3677. p = 0;
  3678. do
  3679. {
  3680. C = s2[p];
  3681. s1[p] = C;
  3682. p++;
  3683. }
  3684. while( C != BasicNulChar );
  3685. return s1;
  3686. }
  3687. char *
  3688. bwb_strncpy(char *s1, const char *s2, size_t n)
  3689. {
  3690. /*
  3691. 4.11.2.4 The strncpy function
  3692. Synopsis
  3693. #include <string.h>
  3694. char *strncpy(char *s1, const char *s2, size_t n);
  3695. Description
  3696. The strncpy function copies not more than n characters (characters
  3697. that follow a null character are not copied) from the array pointed to
  3698. by s2 to the array pointed to by s1 ./120/ If copying takes place
  3699. between objects that overlap, the behavior is undefined.
  3700. If the array pointed to by s2 is a string that is shorter than n
  3701. characters, null characters are appended to the copy in the array
  3702. pointed to by s1 , until n characters in all have been written.
  3703. Returns
  3704. The strncpy function returns the value of s1 .
  3705. */
  3706. if( n > 0 )
  3707. {
  3708. char C;
  3709. int p;
  3710. p = 0;
  3711. do
  3712. {
  3713. C = s2[p];
  3714. s1[p] = C;
  3715. p++;
  3716. }
  3717. while( C != BasicNulChar && p < n );
  3718. while( p < n )
  3719. {
  3720. s1[p] = BasicNulChar;
  3721. p++;
  3722. }
  3723. }
  3724. return s1;
  3725. }
  3726. char *
  3727. bwb_strcat(char *s1, const char *s2)
  3728. {
  3729. /*
  3730. 4.11.3.1 The strcat function
  3731. Synopsis
  3732. #include <string.h>
  3733. char *strcat(char *s1, const char *s2);
  3734. Description
  3735. The strcat function appends a copy of the string pointed to by s2
  3736. (including the terminating null character) to the end of the string
  3737. pointed to by s1 . The initial character of s2 overwrites the null
  3738. character at the end of s1 . If copying takes place between objects
  3739. that overlap, the behavior is undefined.
  3740. Returns
  3741. The strcat function returns the value of s1 .
  3742. */
  3743. char * Temp;
  3744. Temp = bwb_strchr( s1, BasicNulChar );
  3745. bwb_strcpy( Temp, s2 );
  3746. return s1;
  3747. }
  3748. char *
  3749. bwb_strncat(char *s1, const char *s2, size_t n)
  3750. {
  3751. /*
  3752. 4.11.3.2 The strncat function
  3753. Synopsis
  3754. #include <string.h>
  3755. char *strncat(char *s1, const char *s2, size_t n);
  3756. Description
  3757. The strncat function appends not more than n characters (a null
  3758. character and characters that follow it are not appended) from the
  3759. array pointed to by s2 to the end of the string pointed to by s1 .
  3760. The initial character of s2 overwrites the null character at the end
  3761. of s1 . A terminating null character is always appended to the
  3762. result./121/ If copying takes place between objects that overlap, the
  3763. behavior is undefined.
  3764. Returns
  3765. The strncat function returns the value of s1 .
  3766. */
  3767. char * Temp;
  3768. Temp = bwb_strchr( s1, BasicNulChar );
  3769. bwb_strncpy( Temp, s2, n );
  3770. return s1;
  3771. }
  3772. int
  3773. bwb_memcmp(const void *s1, const void *s2, size_t n)
  3774. {
  3775. /*
  3776. 4.11.4.1 The memcmp function
  3777. Synopsis
  3778. #include <string.h>
  3779. int memcmp(const void *s1, const void *s2, size_t n);
  3780. Description
  3781. The memcmp function compares the first n characters of the object
  3782. pointed to by s1 to the first n characters of the object pointed to by
  3783. s2 ./122/
  3784. Returns
  3785. The memcmp function returns an integer greater than, equal to, or
  3786. less than zero, according as the object pointed to by s1 is greater
  3787. than, equal to, or less than the object pointed to by s2 .
  3788. */
  3789. if( n > 0 )
  3790. {
  3791. int p;
  3792. char * L;
  3793. char * R;
  3794. p = 0;
  3795. L = (char *) s1;
  3796. R = (char *) s2;
  3797. while( p < n )
  3798. {
  3799. if( L[p] > R[p] )
  3800. {
  3801. return 1;
  3802. }
  3803. if( L[p] < R[p] )
  3804. {
  3805. return -1;
  3806. }
  3807. /* L[p] == R[p] */
  3808. p++;
  3809. }
  3810. }
  3811. return 0;
  3812. }
  3813. int
  3814. bwb_strcmp(const char *s1, const char *s2)
  3815. {
  3816. /*
  3817. 4.11.4.2 The strcmp function
  3818. Synopsis
  3819. #include <string.h>
  3820. int strcmp(const char *s1, const char *s2);
  3821. Description
  3822. The strcmp function compares the string pointed to by s1 to the
  3823. string pointed to by s2 .
  3824. Returns
  3825. The strcmp function returns an integer greater than, equal to, or
  3826. less than zero, according as the string pointed to by s1 is greater
  3827. than, equal to, or less than the string pointed to by s2 .
  3828. */
  3829. char C;
  3830. int p;
  3831. p = 0;
  3832. do
  3833. {
  3834. if( s1[p] > s2[p] )
  3835. {
  3836. return 1;
  3837. }
  3838. if( s1[p] < s2[p] )
  3839. {
  3840. return -1;
  3841. }
  3842. /* s1[p] == s2[p] */
  3843. C = s1[p];
  3844. p++;
  3845. }
  3846. while( C != BasicNulChar );
  3847. return 0;
  3848. }
  3849. int
  3850. bwb_strncmp(const char *s1, const char *s2, size_t n)
  3851. {
  3852. /*
  3853. 4.11.4.4 The strncmp function
  3854. Synopsis
  3855. #include <string.h>
  3856. int strncmp(const char *s1, const char *s2, size_t n);
  3857. Description
  3858. The strncmp function compares not more than n characters
  3859. (characters that follow a null character are not compared) from the
  3860. array pointed to by s1 to the array pointed to by s2 .
  3861. Returns
  3862. The strncmp function returns an integer greater than, equal to, or
  3863. less than zero, according as the possibly null-terminated array
  3864. pointed to by s1 is greater than, equal to, or less than the possibly
  3865. null-terminated array pointed to by s2 .
  3866. */
  3867. if( n > 0 )
  3868. {
  3869. char C;
  3870. int p;
  3871. p = 0;
  3872. do
  3873. {
  3874. if( s1[p] > s2[p] )
  3875. {
  3876. return 1;
  3877. }
  3878. if( s1[p] < s2[p] )
  3879. {
  3880. return -1;
  3881. }
  3882. /* s1[p] == s2[p] */
  3883. C = s1[p];
  3884. p++;
  3885. }
  3886. while( C != BasicNulChar && p < n );
  3887. }
  3888. return 0;
  3889. }
  3890. void *
  3891. bwb_memchr(const void *s, int c, size_t n)
  3892. {
  3893. /*
  3894. 4.11.5.1 The memchr function
  3895. Synopsis
  3896. #include <string.h>
  3897. void *memchr(const void *s, int c, size_t n);
  3898. Description
  3899. The memchr function locates the first occurrence of c (converted to
  3900. an unsigned char ) in the initial n characters (each interpreted as
  3901. unsigned char ) of the object pointed to by s .
  3902. Returns
  3903. The memchr function returns a pointer to the located character, or
  3904. a null pointer if the character does not occur in the object.
  3905. */
  3906. if( n > 0 )
  3907. {
  3908. int p;
  3909. unsigned char *Check;
  3910. unsigned char Find;
  3911. p = 0;
  3912. Check = (unsigned char *)s;
  3913. Find = (unsigned char) c;
  3914. do
  3915. {
  3916. if( Check[p] == Find )
  3917. {
  3918. return (void *) &(Check[p]);
  3919. }
  3920. p++;
  3921. }
  3922. while( p < n );
  3923. }
  3924. return NULL;
  3925. }
  3926. char *
  3927. bwb_strchr(const char *s, int c)
  3928. {
  3929. /*
  3930. 4.11.5.2 The strchr function
  3931. Synopsis
  3932. #include <string.h>
  3933. char *strchr(const char *s, int c);
  3934. Description
  3935. The strchr function locates the first occurrence of c (converted to
  3936. a char ) in the string pointed to by s . The terminating null
  3937. character is considered to be part of the string.
  3938. Returns
  3939. The strchr function returns a pointer to the located character, or
  3940. a null pointer if the character does not occur in the string.
  3941. */
  3942. int p;
  3943. char Find;
  3944. char C;
  3945. p = 0;
  3946. Find = (char) c;
  3947. do
  3948. {
  3949. C = s[p];
  3950. if( C == Find )
  3951. {
  3952. return (char *) &(s[p]);
  3953. }
  3954. p++;
  3955. }
  3956. while( C != BasicNulChar );
  3957. return NULL;
  3958. }
  3959. char *
  3960. bwb_strrchr(const char *s, int c)
  3961. {
  3962. /*
  3963. 4.11.5.5 The strrchr function
  3964. Synopsis
  3965. #include <string.h>
  3966. char *strrchr(const char *s, int c);
  3967. Description
  3968. The strrchr function locates the last occurrence of c (converted to
  3969. a char ) in the string pointed to by s . The terminating null
  3970. character is considered to be part of the string.
  3971. Returns
  3972. The strrchr function returns a pointer to the character, or a null
  3973. pointer if c does not occur in the string.
  3974. */
  3975. int p;
  3976. char Find;
  3977. char * Found;
  3978. char C;
  3979. p = 0;
  3980. Find = (char) c;
  3981. Found = NULL;
  3982. do
  3983. {
  3984. C = s[p];
  3985. if( C == Find )
  3986. {
  3987. Found = (char *) &(s[p]);
  3988. }
  3989. p++;
  3990. }
  3991. while( C != BasicNulChar );
  3992. return Found;
  3993. }
  3994. void *
  3995. bwb_memset(void *s, int c, size_t n)
  3996. {
  3997. /*
  3998. 4.11.6.1 The memset function
  3999. Synopsis
  4000. #include <string.h>
  4001. void *memset(void *s, int c, size_t n);
  4002. Description
  4003. The memset function copies the value of c (converted to an unsigned
  4004. char ) into each of the first n characters of the object pointed to by
  4005. s .
  4006. Returns
  4007. The memset function returns the value of s .
  4008. */
  4009. if( n > 0 )
  4010. {
  4011. int p;
  4012. unsigned char * Target;
  4013. unsigned char Value;
  4014. p = 0;
  4015. Target = (unsigned char *)s;
  4016. Value = (unsigned char) c;
  4017. do
  4018. {
  4019. Target[p] = Value;
  4020. p++;
  4021. }
  4022. while( p < n );
  4023. }
  4024. return s;
  4025. }
  4026. size_t
  4027. bwb_strlen(const char *s)
  4028. {
  4029. /*
  4030. 4.11.6.3 The strlen function
  4031. Synopsis
  4032. #include <string.h>
  4033. size_t strlen(const char *s);
  4034. Description
  4035. The strlen function computes the length of the string pointed to by s .
  4036. Returns
  4037. The strlen function returns the number of characters that precede
  4038. the terminating null character.
  4039. */
  4040. size_t p;
  4041. p = 0;
  4042. while( s[p] != BasicNulChar )
  4043. {
  4044. p++;
  4045. }
  4046. return p;
  4047. }
  4048. #if HAVE_UNIX_GCC
  4049. /* these are intrinsic C functions in my environment using -ansi */
  4050. #else /* ! HAVE_UNIX_GCC */
  4051. unsigned int
  4052. sleep( unsigned int X )
  4053. {
  4054. return X;
  4055. }
  4056. #endif /* ! HAVE_UNIX_GCC */
  4057. double
  4058. bwb_rint(double x)
  4059. {
  4060. /* BASIC dialects have different rounding rules */
  4061. double Result;
  4062. if( x < 0 )
  4063. {
  4064. return - bwb_rint(-x);
  4065. }
  4066. /* x >= 0 */
  4067. switch( My->OptionRoundType )
  4068. {
  4069. case C_OPTION_ROUND_BANK:
  4070. /* normal financial rounding */
  4071. Result = floor(x + 0.5);
  4072. if( x - floor( x ) == 0.5 )
  4073. {
  4074. /* midway */
  4075. double Half;
  4076. Half = Result / 2.0;
  4077. if( Half != floor( Half ) )
  4078. {
  4079. /* odd -> even */
  4080. Result--;
  4081. }
  4082. }
  4083. break;
  4084. case C_OPTION_ROUND_MATH:
  4085. /* normal mathematical rounding */
  4086. Result = floor(x + 0.5);
  4087. break;
  4088. case C_OPTION_ROUND_TRUNCATE:
  4089. /* simple truncation */
  4090. Result = floor(x);
  4091. break;
  4092. }
  4093. return Result;
  4094. }
  4095. int
  4096. bwb_stricmp(const char *s1, const char *s2)
  4097. {
  4098. const unsigned char *p1;
  4099. const unsigned char *p2;
  4100. p1 = (const unsigned char *) s1;
  4101. p2 = (const unsigned char *) s2;
  4102. while (*p1 != BasicNulChar)
  4103. {
  4104. char c1;
  4105. char c2;
  4106. c1 = bwb_toupper(*p1);
  4107. c2 = bwb_toupper(*p2);
  4108. if (c1 < c2)
  4109. {
  4110. return -1;
  4111. }
  4112. if (c1 > c2)
  4113. {
  4114. return 1;
  4115. }
  4116. p1++;
  4117. p2++;
  4118. }
  4119. if (*p2 == BasicNulChar)
  4120. {
  4121. return 0;
  4122. }
  4123. return -1;
  4124. }
  4125. int
  4126. bwb_strnicmp(const char *s1, const char *s2, size_t n)
  4127. {
  4128. const unsigned char *p1;
  4129. const unsigned char *p2;
  4130. size_t x = 0;
  4131. p1 = (const unsigned char *) s1;
  4132. p2 = (const unsigned char *) s2;
  4133. while (x < n)
  4134. {
  4135. char c1;
  4136. char c2;
  4137. c1 = bwb_toupper(p1[x]);
  4138. c2 = bwb_toupper(p2[x]);
  4139. if (c1 < c2)
  4140. {
  4141. return -1;
  4142. }
  4143. if (c1 > c2)
  4144. {
  4145. return 1;
  4146. }
  4147. if (c1 == BasicNulChar)
  4148. {
  4149. return 0;
  4150. }
  4151. x++;
  4152. }
  4153. return 0;
  4154. }
  4155. /* EOF */