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.
 
 
 
 
 
 

724 lines
16 KiB

  1. /***************************************************************
  2. bwb_stc.c Commands Related to Structured Programming
  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. /*---------------------------------------------------------------*/
  27. #include "bwbasic.h"
  28. /* prototypes */
  29. static int
  30. fslt_clear(void);
  31. static int
  32. scan_readargs(struct fslte * f,
  33. struct bwb_line * line, int *position);
  34. struct bwb_variable *
  35. bwb_etov(struct bwb_variable * dst, struct exp_ese * src);
  36. int
  37. fslt_addlocalvar(struct fslte * f, struct bwb_variable * v);
  38. /***************************************************************
  39. FUNCTION: bwb_scan()
  40. DESCRIPTION: This function scans all lines of the
  41. program in memory and creates a FUNCTION-
  42. SUB lookup table (fslt) for the program.
  43. ***************************************************************/
  44. int
  45. bwb_scan(void)
  46. {
  47. struct bwb_line *current;
  48. int Indention = 0;
  49. bwx_DEBUG(__FUNCTION__);
  50. /* int position; */
  51. if (CURTASK rescan != TRUE)
  52. {
  53. return FALSE;
  54. }
  55. /* program needs to be scanned again, because a line was added or
  56. * deleted */
  57. /* first run through the FUNCTION - SUB loopkup table and free any
  58. * existing memory */
  59. fslt_clear();
  60. for (current = CURTASK bwb_start.next; current != &CURTASK bwb_end; current = current->next)
  61. {
  62. current->OtherLine = NULL;
  63. }
  64. /* run through the list of lines and identify SUB and FUNCTION
  65. * statements */
  66. for (current = CURTASK bwb_start.next; current != &CURTASK bwb_end; current = current->next)
  67. {
  68. /* position = current->Startpos; */
  69. switch (current->cmdnum)
  70. {
  71. case C_DEF:
  72. case C_FUNCTION:
  73. case C_SUB:
  74. case C_USER_LBL:
  75. fslt_add(current);
  76. case C_DO:
  77. case C_DO_WHILE:
  78. case C_DO_UNTIL:
  79. case C_WHILE:
  80. case C_UNTIL:
  81. case C_FOR:
  82. case C_IF:
  83. case C_SELECT_CASE:
  84. find_BottomLineInCode(current);
  85. break;
  86. }
  87. switch (current->cmdnum)
  88. {
  89. case C_NEXT:
  90. case C_LOOP:
  91. case C_LOOP_UNTIL:
  92. case C_LOOP_WHILE:
  93. case C_UEND:
  94. case C_WEND:
  95. case C_ELSEIF:
  96. case C_ELSE:
  97. case C_END_IF:
  98. case C_CASE:
  99. case C_CASE_IF:
  100. case C_CASE_IS:
  101. case C_CASE_ELSE:
  102. case C_END_SELECT:
  103. case C_END_SUB:
  104. case C_END_FUNCTION:
  105. Indention--;
  106. break;
  107. }
  108. if (Indention < 0)
  109. {
  110. Indention = 0;
  111. }
  112. current->Indention = Indention;
  113. switch (current->cmdnum)
  114. {
  115. case C_FOR:
  116. case C_DO:
  117. case C_DO_UNTIL:
  118. case C_DO_WHILE:
  119. case C_UNTIL:
  120. case C_WHILE:
  121. case C_IF_THEN:
  122. case C_ELSEIF:
  123. case C_ELSE:
  124. case C_SELECT_CASE:
  125. case C_CASE:
  126. case C_CASE_IF:
  127. case C_CASE_IS:
  128. case C_CASE_ELSE:
  129. case C_FUNCTION:
  130. case C_SUB:
  131. Indention++;
  132. break;
  133. }
  134. }
  135. /* return */
  136. CURTASK rescan = FALSE;
  137. return TRUE;
  138. }
  139. /***************************************************************
  140. FUNCTION: fslt_clear()
  141. DESCRIPTION: This C function clears all existing memory
  142. in the FUNCTION-SUB lookup table.
  143. ***************************************************************/
  144. static int
  145. fslt_clear(void)
  146. {
  147. struct fslte *current, *next;
  148. struct bwb_variable *c, *n;
  149. bwx_DEBUG(__FUNCTION__);
  150. /* run through table and clear memory */
  151. next = CURTASK fslt_start.next;
  152. for (current = CURTASK fslt_start.next; current != &CURTASK fslt_end;
  153. current = next)
  154. {
  155. /* check for local variables and free them */
  156. c = current->local_variable;
  157. while (c != NULL)
  158. {
  159. n = c->next;
  160. /* Revised to FREE pass-thru call by JBV */
  161. FREE(c, "fslt_clear");
  162. c = n;
  163. }
  164. next = current->next;
  165. /* Revised to FREE pass-thru calls by JBV */
  166. if (current->name != NULL)
  167. {
  168. FREE(current->name, "fslt_clear"); /* JBV */
  169. current->name = NULL; /* JBV */
  170. }
  171. FREE(current, "fslt_clear");
  172. current = NULL; /* JBV */
  173. }
  174. /* reset linkage */
  175. CURTASK fslt_start.next = &CURTASK fslt_end;
  176. return TRUE;
  177. }
  178. /***************************************************************
  179. FUNCTION: fslt_add()
  180. DESCRIPTION: This C function adds an entry to the
  181. FUNCTION-SUB lookup table.
  182. ***************************************************************/
  183. int
  184. fslt_add(struct bwb_line * line /* , int *position , int code */ )
  185. {
  186. char tbuf[BasicStringLengthMax + 1];
  187. char *name;
  188. struct fslte *f, *n;
  189. int p;
  190. int *position;
  191. position = &p;
  192. p = line->Startpos;
  193. bwx_DEBUG(__FUNCTION__);
  194. /* get the element for name */
  195. if ( /* code == EXEC_LABEL */ line->cmdnum == C_USER_LBL)
  196. {
  197. p = 0;
  198. scan_element(line->buffer, &p, tbuf);
  199. tbuf[strlen(tbuf) - 1] = '\0'; /* remove trailing colon */
  200. }
  201. else
  202. {
  203. adv_ws(line->buffer, position);
  204. exp_getvfname(&(line->buffer[*position]), tbuf);
  205. *position += strlen(tbuf);
  206. }
  207. /* get memory for name buffer */
  208. /* Revised to CALLOC pass-thru call by JBV */
  209. if ((name = CALLOC(1, strlen(tbuf) + 1, "fslt_add")) == NULL)
  210. {
  211. bwb_error("in fslt_add(): failed to get memory for name buffer");
  212. return FALSE;
  213. }
  214. strcpy(name, tbuf);
  215. /* get memory for fslt structure */
  216. if ((f = CALLOC(1, sizeof(struct fslte), "fslt_add")) == NULL)
  217. {
  218. bwb_error("in fslt_add(): failed to get memory for fslt structure");
  219. return FALSE;
  220. }
  221. /* fill in structure */
  222. f->line = line;
  223. f->name = name;
  224. f->local_variable = NULL;
  225. f->ParameterCount = 0; /* 0..32, 255 == VARIAMT */
  226. f->ParameterTypes = 0; /* bit 0 is first parameter */
  227. /* read arguments */
  228. adv_ws(line->buffer, position);
  229. f->startpos = *position;
  230. if (line->buffer[*position] == '(')
  231. {
  232. scan_readargs(f, line, position);
  233. }
  234. /* establish linkages */
  235. n = CURTASK fslt_start.next;
  236. CURTASK fslt_start.next = f;
  237. f->next = n;
  238. fnc_add_deffn(f);
  239. return TRUE;
  240. }
  241. /***************************************************************
  242. FUNCTION: scan_readargs()
  243. DESCRIPTION: This C function reads arguments (variable
  244. names for an entry added to the FUNCTION-
  245. SUB lookup table.
  246. ***************************************************************/
  247. static int
  248. scan_readargs(struct fslte * f, struct bwb_line * line, int *position)
  249. {
  250. int control_loop;
  251. struct bwb_variable *v;
  252. char tbuf[BasicStringLengthMax + 1];
  253. bwx_DEBUG(__FUNCTION__);
  254. f->ParameterCount = 0; /* 0..254, 255 == ... */
  255. f->ParameterTypes = 0; /* bit 0 is first parameter */
  256. /* if we are at begin paren, advance */
  257. if (line->buffer[*position] == '(')
  258. {
  259. ++(*position);
  260. }
  261. /* loop through looking for arguments */
  262. control_loop = TRUE;
  263. adv_ws(line->buffer, position);
  264. if (strncasecmp(&(line->buffer[*position]), "...", 3) == 0)
  265. {
  266. /* FUNCTION FRED( ... ) */
  267. (*position) += 3;
  268. adv_ws(line->buffer, position);
  269. if (line->buffer[*position] == ')')
  270. {
  271. f->ParameterCount = 0xFF; /* VARIANT */
  272. f->ParameterTypes = 0;
  273. ++(*position);
  274. f->startpos = *position;
  275. return TRUE;
  276. }
  277. bwb_error(err_syntax);
  278. return FALSE;
  279. }
  280. while (control_loop == TRUE)
  281. {
  282. if (line->buffer[*position] == '\0' || line->buffer[*position] == OptionCommentChar)
  283. {
  284. /* premature end of line */
  285. control_loop = FALSE;
  286. f->startpos = *position;
  287. bwb_error(err_syntax);
  288. return FALSE;
  289. }
  290. switch (line->buffer[*position])
  291. {
  292. case ')': /* end of argument list */
  293. ++(*position);
  294. control_loop = FALSE;
  295. f->startpos = *position;
  296. return TRUE;
  297. case '=': /* end of NO argument list */
  298. control_loop = FALSE;
  299. f->startpos = *position;
  300. return TRUE;
  301. default: /* presume beginning of argument == variable
  302. * name */
  303. exp_getvfname(&(line->buffer[*position]), tbuf);
  304. *position += strlen(tbuf);
  305. /* initialize the variable and add it to local chain */
  306. v = var_new(tbuf);
  307. fslt_addlocalvar(f, v);
  308. /* advance past the comma */
  309. if (line->buffer[*position] == ',')
  310. {
  311. ++(*position);
  312. }
  313. if (f->ParameterCount > 32)
  314. {
  315. /* should have been declared VARIANT */
  316. bwb_error(err_syntax);
  317. return FALSE;
  318. }
  319. else
  320. {
  321. if (v->type == STRING)
  322. {
  323. f->ParameterTypes |= (1 << f->ParameterCount);
  324. }
  325. f->ParameterCount++; /* 0..32, 255 == VARIANT */
  326. }
  327. break;
  328. }
  329. adv_ws(line->buffer, position);
  330. }
  331. return TRUE;
  332. }
  333. /***************************************************************
  334. FUNCTION: bwb_def()
  335. DESCRIPTION: This C function implements the BASIC
  336. DEF statement. Since DEF and FUNCTION
  337. are equivalent, it simply passes execution
  338. to bwb_function().
  339. SYNTAX: DEF FNname(arg...)] = expression
  340. NOTE: It is not a strict requirement that the
  341. function name should begin with "FN".
  342. ***************************************************************/
  343. struct bwb_line *
  344. bwb_DEF(struct bwb_line * l)
  345. {
  346. bwx_DEBUG(__FUNCTION__);
  347. /* this line will be executed by fnc_deffn() in bwb_fnc.c */
  348. adv_eos(l->buffer, &(l->position));
  349. return bwb_zline(l);
  350. }
  351. /***************************************************************
  352. FUNCTION: bwb_call()
  353. DESCRIPTION: This C function implements the BASIC
  354. CALL subroutine command.
  355. SYNTAX: CALL subroutine-name
  356. ***************************************************************/
  357. struct bwb_line *
  358. bwb_CALL(struct bwb_line * l)
  359. {
  360. bwx_DEBUG(__FUNCTION__);
  361. /* Call the expression interpreter to evaluate the function */
  362. /* prn_xprintf(Buffer); */
  363. bwb_exp(l->buffer, FALSE, &l->position);
  364. if (ERROR_PENDING)
  365. {
  366. /* prn_xprintf("oops"); */
  367. }
  368. adv_eos(l->buffer, &(l->position));
  369. return bwb_zline(l);
  370. #if 0
  371. return bwb_DEF_SUB(l);
  372. #endif
  373. }
  374. /***************************************************************
  375. FUNCTION: find_label()
  376. DESCRIPTION: This C function finds a program line that
  377. begins with the label included in <buffer>.
  378. ***************************************************************/
  379. struct bwb_line *
  380. find_label(char *buffer)
  381. {
  382. bwx_DEBUG(__FUNCTION__);
  383. while (*buffer == ' ')
  384. buffer++;
  385. if (*buffer == 0)
  386. {
  387. bwb_error(err_noln);
  388. }
  389. else
  390. if (isdigit(*buffer))
  391. {
  392. /* LINE NUMBER */
  393. int number;
  394. number = atoi(buffer);
  395. if (number > 0)
  396. {
  397. struct bwb_line *x;
  398. for (x = &CURTASK bwb_start; x != &CURTASK bwb_end; x = x->next)
  399. {
  400. if (x->number == number)
  401. {
  402. return x;
  403. }
  404. }
  405. }
  406. sprintf(bwb_ebuf, "Line number %d not found", number);
  407. bwb_error(bwb_ebuf);
  408. }
  409. else
  410. if (OptionFlags & OPTION_LABELS_ON)
  411. {
  412. /* LABEL */
  413. if (isalpha(*buffer))
  414. {
  415. struct fslte *f;
  416. for (f = CURTASK fslt_start.next; f != &(CURTASK fslt_end); f = f->next)
  417. {
  418. if (strcasecmp(buffer, f->name) == 0)
  419. {
  420. return f->line;
  421. }
  422. }
  423. }
  424. sprintf(bwb_ebuf, "Line label '%s' not found", buffer);
  425. bwb_error(bwb_ebuf);
  426. }
  427. else
  428. {
  429. sprintf(bwb_ebuf, "Line label '%s' is not allowed", buffer);
  430. bwb_error(bwb_ebuf);
  431. }
  432. return NULL;
  433. }
  434. /***************************************************************
  435. FUNCTION: bwb_exit()
  436. DESCRIPTION: This C function implements the BASIC EXIT
  437. statement, calling subroutines for either
  438. EXIT FOR or EXIT DO.
  439. SYNTAX: EXIT FOR|DO
  440. ***************************************************************/
  441. struct bwb_line *
  442. bwb_EXIT(struct bwb_line * l)
  443. {
  444. bwx_DEBUG(__FUNCTION__);
  445. sprintf(bwb_ebuf, "in bwb_exit(): Nonsense or nothing following EXIT");
  446. bwb_error(bwb_ebuf);
  447. return bwb_zline(l);
  448. }
  449. /***************************************************************
  450. FUNCTION: bwb_etov()
  451. DESCRIPTION: This function assigns the value of a
  452. bwBASIC expression stack element (src)
  453. to the value of a bwBASIC variable (dst).
  454. ***************************************************************/
  455. struct bwb_variable *
  456. bwb_etov(struct bwb_variable * dst, struct exp_ese * src)
  457. {
  458. if ((int) src->type != dst->type)
  459. {
  460. sprintf(bwb_ebuf, "in bwb_etov(): mismatch src <%d> dst <%d>",
  461. src->type, dst->type);
  462. bwb_error(bwb_ebuf);
  463. return NULL;
  464. }
  465. if (dst->type == NUMBER)
  466. {
  467. *var_findnval(dst, dst->array_pos) = exp_getnval(src);
  468. }
  469. else
  470. {
  471. str_btob(var_getsval(dst), exp_getsval(src));
  472. }
  473. return dst;
  474. }
  475. /***************************************************************
  476. FUNCTION: fslt_addlocalvar()
  477. DESCRIPTION: This function adds a local variable
  478. to the FUNCTION-SUB lookup table at
  479. a specific level.
  480. ***************************************************************/
  481. int
  482. fslt_addlocalvar(struct fslte * f, struct bwb_variable * v)
  483. {
  484. bwx_DEBUG(__FUNCTION__);
  485. /* find end of local chain */
  486. if (f->local_variable == NULL)
  487. {
  488. f->local_variable = v;
  489. }
  490. else
  491. {
  492. struct bwb_variable *p;
  493. struct bwb_variable *c;
  494. p = f->local_variable;
  495. for (c = f->local_variable->next; c != NULL; c = c->next)
  496. {
  497. p = c;
  498. }
  499. p->next = v;
  500. }
  501. v->next = NULL;
  502. return TRUE;
  503. }
  504. /***************************************************************
  505. FUNCTION: fslt_init()
  506. DESCRIPTION: This function initializes the FUNCTION-SUB
  507. lookup table.
  508. ***************************************************************/
  509. int
  510. fslt_init(int task)
  511. {
  512. bwx_DEBUG(__FUNCTION__);
  513. LOCALTASK fslt_start.next = &(LOCALTASK fslt_end);
  514. return TRUE;
  515. }
  516. struct bwb_line *
  517. bwb_USER_LBL(struct bwb_line * l)
  518. {
  519. bwx_DEBUG(__FUNCTION__);
  520. adv_eos(l->buffer, &(l->position));
  521. return bwb_zline(l);
  522. }
  523. /* EOF */