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.

bwb_elx.c 35 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. /****************************************************************
  2. bwb_elx.c Parse Elements of Expressions
  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. /***************************************************************
  29. FUNCTION: exp_paren()
  30. DESCRIPTION: This function interprets a parenthetical
  31. expression, calling bwb_exp() (recursively)
  32. to resolve the internal expression.
  33. ***************************************************************/
  34. int
  35. exp_paren(char *expression)
  36. {
  37. struct exp_ese *e;
  38. int s_pos; /* position in build buffer */
  39. int loop;
  40. int paren_level;
  41. bwx_DEBUG(__FUNCTION__);
  42. /* find a string enclosed by parentheses */
  43. CURTASK exps[CURTASK expsc].pos_adv = 1; /* start beyond open
  44. * paren */
  45. s_pos = 0;
  46. loop = TRUE;
  47. paren_level = 1;
  48. CURTASK exps[CURTASK expsc].string[0] = '\0';
  49. while (loop == TRUE)
  50. {
  51. /* check the current character */
  52. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  53. {
  54. case '\0':
  55. bwb_error(err_incomplete);
  56. loop = FALSE;
  57. break;
  58. case '(':
  59. ++paren_level;
  60. CURTASK exps[CURTASK expsc].string[s_pos]
  61. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  62. ++s_pos;
  63. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  64. break;
  65. case ')':
  66. --paren_level;
  67. if (paren_level == 0)
  68. {
  69. loop = FALSE;
  70. }
  71. else
  72. {
  73. CURTASK exps[CURTASK expsc].string[s_pos]
  74. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  75. ++s_pos;
  76. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  77. }
  78. break;
  79. case '\"': /* embedded string constant */
  80. ++CURTASK exps[CURTASK expsc].pos_adv;
  81. while ((expression[CURTASK exps[CURTASK expsc].pos_adv] != '\"')
  82. && (expression[CURTASK exps[CURTASK expsc].pos_adv] != '\0'))
  83. {
  84. CURTASK exps[CURTASK expsc].string[s_pos]
  85. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  86. ++s_pos;
  87. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  88. ++CURTASK exps[CURTASK expsc].pos_adv;
  89. }
  90. break;
  91. default:
  92. CURTASK exps[CURTASK expsc].string[s_pos]
  93. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  94. ++s_pos;
  95. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  96. break;
  97. }
  98. /* advance the counter */
  99. ++CURTASK exps[CURTASK expsc].pos_adv;
  100. }
  101. /* call bwb_exp() recursively to interpret this expression */
  102. CURTASK exps[CURTASK expsc].rec_pos = 0;
  103. e = bwb_exp(CURTASK exps[CURTASK expsc].string, FALSE,
  104. &(CURTASK exps[CURTASK expsc].rec_pos));
  105. /* assign operation and value at this level */
  106. CURTASK exps[CURTASK expsc].type = e->type;
  107. switch (e->type)
  108. {
  109. case STRING:
  110. CURTASK exps[CURTASK expsc].operation = CONST_STRING;
  111. str_btob(exp_getsval(&(CURTASK exps[CURTASK expsc])), exp_getsval(e));
  112. break;
  113. default:
  114. CURTASK exps[CURTASK expsc].operation = NUMBER;
  115. CURTASK exps[CURTASK expsc].nval = exp_getnval(e);
  116. break;
  117. }
  118. return TRUE;
  119. }
  120. /***************************************************************
  121. FUNCTION: exp_strconst()
  122. DESCRIPTION: This function interprets a string
  123. constant.
  124. ***************************************************************/
  125. int
  126. exp_strconst(char *expression)
  127. {
  128. int e_pos, s_pos;
  129. bwx_DEBUG(__FUNCTION__);
  130. /* assign values to structure */
  131. CURTASK exps[CURTASK expsc].type = STRING;
  132. CURTASK exps[CURTASK expsc].operation = CONST_STRING;
  133. /* set counters */
  134. s_pos = 0;
  135. CURTASK exps[CURTASK expsc].pos_adv = e_pos = 1;
  136. CURTASK exps[CURTASK expsc].string[0] = '\0';
  137. /* read the string up until the next quotation mark */
  138. /* While yer at it, check for a null terminator too (JBV, found by
  139. * DD) */
  140. while ((expression[e_pos] != '\"') && (expression[e_pos] != '\0'))
  141. {
  142. CURTASK exps[CURTASK expsc].string[s_pos] = expression[e_pos];
  143. ++e_pos;
  144. ++s_pos;
  145. ++CURTASK exps[CURTASK expsc].pos_adv;
  146. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  147. if (s_pos > BasicStringLengthMax)
  148. {
  149. sprintf(bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
  150. expression, BasicStringLengthMax);
  151. bwb_error(bwb_ebuf);
  152. return OP_NULL;
  153. }
  154. }
  155. /* now write string over to bstring */
  156. str_ctob(&(CURTASK exps[CURTASK expsc].sval), CURTASK exps[CURTASK expsc].string);
  157. /* advance past last quotation mark */
  158. /*-------------------------------------------------------------*/
  159. /* Of course, it doesn't hurt to make sure it's really a quote */
  160. /* (JBV, found by DD) */
  161. /*-------------------------------------------------------------*/
  162. if (expression[e_pos] == '\"')
  163. ++CURTASK exps[CURTASK expsc].pos_adv;
  164. /* return */
  165. return TRUE;
  166. }
  167. /***************************************************************
  168. FUNCTION: exp_numconst()
  169. DESCRIPTION: This function interprets a numerical
  170. constant.
  171. ***************************************************************/
  172. int
  173. exp_numconst(char *expression)
  174. {
  175. int base; /* numerical base for the constant */
  176. static struct bwb_variable mantissa; /* mantissa of floating-point
  177. * number */
  178. static int init = FALSE; /* is mantissa variable initialized? */
  179. int exponent; /* exponent for floating point number */
  180. int man_start; /* starting point of mantissa */
  181. int s_pos; /* position in build string */
  182. int build_loop;
  183. int need_pm;
  184. unsigned int u;
  185. bwx_DEBUG(__FUNCTION__);
  186. /* initialize the variable if necessary */
  187. if (init == FALSE)
  188. {
  189. init = TRUE;
  190. var_make(&mantissa, NUMBER);
  191. }
  192. /* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
  193. * this is necessary because mantissa might be used before dim_base
  194. * is set */
  195. mantissa.array_pos[0] = dim_base;
  196. need_pm = FALSE;
  197. CURTASK exps[CURTASK expsc].nval = 0;
  198. /* check the first character(s) to determine numerical base and
  199. * starting point of the mantissa */
  200. switch (expression[0])
  201. {
  202. case '-':
  203. case '+':
  204. case '0':
  205. case '1':
  206. case '2':
  207. case '3':
  208. case '4':
  209. case '5':
  210. case '6':
  211. case '7':
  212. case '8':
  213. case '9':
  214. case '.':
  215. base = 10; /* decimal constant */
  216. man_start = 0; /* starts at position 0 */
  217. need_pm = FALSE;
  218. break;
  219. case '&': /* hex or octal constant */
  220. if ((expression[1] == 'H') || (expression[1] == 'h'))
  221. {
  222. base = 16; /* hexadecimal constant */
  223. man_start = 2; /* starts at position 2 */
  224. }
  225. else
  226. {
  227. base = 8; /* octal constant */
  228. if ((expression[1] == 'O') || (expression[1] == 'o'))
  229. {
  230. man_start = 2; /* starts at position 2 */
  231. }
  232. else
  233. {
  234. man_start = 1; /* starts at position 1 */
  235. }
  236. }
  237. break;
  238. default:
  239. sprintf(bwb_ebuf, "expression <%s> is not a numerical constant.",
  240. expression);
  241. bwb_error(bwb_ebuf);
  242. return OP_NULL;
  243. }
  244. /* now build the mantissa according to the numerical base */
  245. switch (base)
  246. {
  247. case 10: /* decimal constant */
  248. /* initialize counters */
  249. CURTASK exps[CURTASK expsc].pos_adv = man_start;
  250. CURTASK exps[CURTASK expsc].type = NUMBER;
  251. CURTASK exps[CURTASK expsc].string[0] = '\0';
  252. s_pos = 0;
  253. exponent = OP_NULL;
  254. build_loop = TRUE;
  255. /* loop to build the string */
  256. while (build_loop == TRUE)
  257. {
  258. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  259. {
  260. case '-': /* prefixed plus or minus */
  261. case '+':
  262. /* in the first position, a plus or minus
  263. * sign can be added to the beginning of the
  264. * string to be scanned */
  265. if (CURTASK exps[CURTASK expsc].pos_adv == man_start)
  266. {
  267. CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
  268. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  269. * character */
  270. ++s_pos;
  271. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  272. }
  273. /* but in any other position, the plus or
  274. * minus sign must be taken as an operator
  275. * and thus as terminating the string to be
  276. * scanned */
  277. else
  278. {
  279. build_loop = FALSE;
  280. }
  281. break;
  282. case '.': /* note at least single precision */
  283. case '0': /* or ordinary digit */
  284. case '1':
  285. case '2':
  286. case '3':
  287. case '4':
  288. case '5':
  289. case '6':
  290. case '7':
  291. case '8':
  292. case '9':
  293. CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
  294. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  295. * character */
  296. ++s_pos;
  297. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  298. break;
  299. case BasicDoubleSuffix: /* Microsoft-type
  300. * precision indicator;
  301. * ignored but
  302. * terminates */
  303. case BasicSingleSuffix: /* Microsoft-type
  304. * precision indicator;
  305. * ignored but
  306. * terminates */
  307. case BasicCurrencySuffix: /* Microsoft-type
  308. * precision indicator;
  309. * ignored but
  310. * terminates */
  311. case BasicLongSuffix: /* Microsoft-type precision
  312. * indicator; ignored but
  313. * terminates */
  314. case BasicIntegerSuffix: /* Microsoft-type
  315. * precision indicator;
  316. * ignored but
  317. * terminates */
  318. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  319. * character */
  320. CURTASK exps[CURTASK expsc].type = NUMBER;
  321. exponent = FALSE;
  322. build_loop = FALSE;
  323. break;
  324. case 'E': /* exponential, single precision */
  325. case 'e':
  326. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  327. * character */
  328. CURTASK exps[CURTASK expsc].type = NUMBER;
  329. exponent = TRUE;
  330. build_loop = FALSE;
  331. break;
  332. case 'D': /* exponential, double precision */
  333. case 'd':
  334. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  335. * character */
  336. CURTASK exps[CURTASK expsc].type = NUMBER;
  337. exponent = TRUE;
  338. build_loop = FALSE;
  339. break;
  340. default: /* anything else, terminate */
  341. build_loop = FALSE;
  342. break;
  343. }
  344. }
  345. /* assign the value to the mantissa variable */
  346. sscanf(CURTASK exps[CURTASK expsc].string, BasicNumberScanFormat,
  347. var_findnval(&mantissa, mantissa.array_pos));
  348. /* test if integer bounds have been exceeded */
  349. if (CURTASK exps[CURTASK expsc].type == NUMBER)
  350. {
  351. int i;
  352. BasicNumberType d;
  353. i = (int) var_getnval(&mantissa);
  354. d = (BasicNumberType) i;
  355. if (d != var_getnval(&mantissa))
  356. {
  357. CURTASK exps[CURTASK expsc].type = NUMBER;
  358. }
  359. }
  360. /* read the exponent if there is one */
  361. if (exponent == TRUE)
  362. {
  363. /* allow a plus or minus once at the beginning */
  364. need_pm = TRUE;
  365. /* initialize counters */
  366. CURTASK exps[CURTASK expsc].string[0] = '\0';
  367. s_pos = 0;
  368. build_loop = TRUE;
  369. /* loop to build the string */
  370. while (build_loop == TRUE)
  371. {
  372. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  373. {
  374. case '-': /* prefixed plus or minus */
  375. case '+':
  376. if (need_pm == TRUE) /* only allow once */
  377. {
  378. CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
  379. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  380. * character */
  381. ++s_pos;
  382. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  383. }
  384. else
  385. {
  386. build_loop = FALSE;
  387. }
  388. break;
  389. case '0': /* or ordinary digit */
  390. case '1':
  391. case '2':
  392. case '3':
  393. case '4':
  394. case '5':
  395. case '6':
  396. case '7':
  397. case '8':
  398. case '9':
  399. CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
  400. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  401. * character */
  402. ++s_pos;
  403. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  404. need_pm = FALSE;
  405. break;
  406. default: /* anything else, terminate */
  407. build_loop = FALSE;
  408. break;
  409. }
  410. } /* end of build loop for exponent */
  411. /* assign the value to the user variable */
  412. sscanf(CURTASK exps[CURTASK expsc].string, BasicNumberScanFormat,
  413. &(CURTASK exps[CURTASK expsc].nval));
  414. } /* end of exponent search */
  415. if (CURTASK exps[CURTASK expsc].nval == 0)
  416. {
  417. CURTASK exps[CURTASK expsc].nval = var_getnval(&mantissa);
  418. }
  419. else
  420. {
  421. CURTASK exps[CURTASK expsc].nval = var_getnval(&mantissa)
  422. * pow(10.0, CURTASK exps[CURTASK expsc].nval);
  423. }
  424. break;
  425. case 8: /* octal constant */
  426. /* initialize counters */
  427. CURTASK exps[CURTASK expsc].pos_adv = man_start;
  428. CURTASK exps[CURTASK expsc].type = NUMBER;
  429. CURTASK exps[CURTASK expsc].string[0] = '\0';
  430. s_pos = 0;
  431. exponent = OP_NULL;
  432. build_loop = TRUE;
  433. /* loop to build the string */
  434. while (build_loop == TRUE)
  435. {
  436. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  437. {
  438. case '0': /* or ordinary digit */
  439. case '1':
  440. case '2':
  441. case '3':
  442. case '4':
  443. case '5':
  444. case '6':
  445. case '7':
  446. CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
  447. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  448. * character */
  449. ++s_pos;
  450. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  451. break;
  452. default: /* anything else, terminate */
  453. build_loop = FALSE;
  454. break;
  455. }
  456. }
  457. /* now scan the string to determine the number */
  458. sscanf(CURTASK exps[CURTASK expsc].string, "%o", &u);
  459. CURTASK exps[CURTASK expsc].nval = u;
  460. break;
  461. case 16: /* hexadecimal constant */
  462. /* initialize counters */
  463. CURTASK exps[CURTASK expsc].pos_adv = man_start;
  464. CURTASK exps[CURTASK expsc].type = NUMBER;
  465. CURTASK exps[CURTASK expsc].string[0] = '\0';
  466. s_pos = 0;
  467. exponent = OP_NULL;
  468. build_loop = TRUE;
  469. /* loop to build the string */
  470. while (build_loop == TRUE)
  471. {
  472. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  473. {
  474. case '0': /* or ordinary digit */
  475. case '1':
  476. case '2':
  477. case '3':
  478. case '4':
  479. case '5':
  480. case '6':
  481. case '7':
  482. case '8':
  483. case '9':
  484. case 'A':
  485. case 'a':
  486. case 'B':
  487. case 'b':
  488. case 'C':
  489. case 'c':
  490. case 'D':
  491. case 'd':
  492. case 'E':
  493. case 'e':
  494. case 'F': /* Don't forget these! (JBV) */
  495. case 'f':
  496. CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
  497. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
  498. * character */
  499. ++s_pos;
  500. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  501. break;
  502. default: /* anything else, terminate */
  503. build_loop = FALSE;
  504. break;
  505. }
  506. }
  507. /* now scan the string to determine the number */
  508. sscanf(CURTASK exps[CURTASK expsc].string, "%x", &u);
  509. CURTASK exps[CURTASK expsc].nval = u;
  510. break;
  511. }
  512. /* note that the operation at this level is now a determined NUMBER */
  513. CURTASK exps[CURTASK expsc].operation = NUMBER;
  514. return TRUE;
  515. }
  516. /***************************************************************
  517. FUNCTION: exp_function()
  518. DESCRIPTION: This function interprets a function,
  519. calling bwb_exp() (recursively) to resolve any
  520. parameters to the function.
  521. ***************************************************************/
  522. struct bwb_variable *
  523. var_chain(struct bwb_variable * argv)
  524. {
  525. /* create a variable chain */
  526. struct bwb_variable *argn;
  527. bwx_DEBUG(__FUNCTION__);
  528. if (argv == NULL)
  529. {
  530. /* we are the first variable in the chain */
  531. argn = (struct bwb_variable *) CALLOC(1, sizeof(struct bwb_variable), "exp_function");
  532. }
  533. else
  534. {
  535. /* find the end of the chain */
  536. for (argn = argv; argn->next != NULL; argn = argn->next);
  537. /* add ourself to the end */
  538. argn->next = (struct bwb_variable *) CALLOC(1, sizeof(struct bwb_variable), "exp_function");
  539. argn = argn->next;
  540. }
  541. argn->next = NULL;
  542. /* return pointer to the variable just created */
  543. return argn;
  544. }
  545. int
  546. exp_function(char *expression)
  547. {
  548. struct exp_ese *e;
  549. int s_pos; /* position in build buffer */
  550. int loop;
  551. int paren_level;
  552. int n_args;
  553. /* struct bwb_variable argv[ MAX_FARGS ]; *//* Removed by JBV */
  554. struct bwb_variable *argv; /* Added by JBV */
  555. struct bwb_variable *argn;
  556. bstring *b;
  557. bwx_DEBUG(__FUNCTION__);
  558. argv = var_chain(NULL); /* RETURN variable */
  559. argn = NULL;
  560. /* assign pointers to argument stack */
  561. /* get the function name */
  562. exp_getvfname(expression, CURTASK exps[CURTASK expsc].string);
  563. /* now find the function itself */
  564. CURTASK exps[CURTASK expsc].function = fnc_find(CURTASK exps[CURTASK expsc].string);
  565. /* check to see if it is valid */
  566. if (CURTASK exps[CURTASK expsc].function == NULL)
  567. {
  568. sprintf(bwb_ebuf, "Failed to find function <%s>.",
  569. CURTASK exps[CURTASK expsc].string);
  570. bwb_error(bwb_ebuf);
  571. return OP_ERROR;
  572. }
  573. /* note that this level is a function */
  574. CURTASK exps[CURTASK expsc].operation = FUNCTION;
  575. CURTASK exps[CURTASK expsc].pos_adv = strlen(CURTASK exps[CURTASK expsc].string);
  576. /* check for begin parenthesis */
  577. loop = TRUE;
  578. while (loop == TRUE)
  579. {
  580. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  581. {
  582. case ' ': /* whitespace */
  583. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance */
  584. break;
  585. case '(': /* begin paren */
  586. ++CURTASK exps[CURTASK expsc].pos_adv; /* advance beyond it */
  587. paren_level = 1; /* set paren_level */
  588. loop = FALSE; /* and break out */
  589. break;
  590. default: /* anything else */
  591. loop = FALSE;
  592. paren_level = 0; /* do not look for parameters */
  593. break;
  594. }
  595. }
  596. /* find parameters within parentheses */
  597. /* for each argument, find a string ending with ',' or with end
  598. * parenthesis */
  599. n_args = 0;
  600. s_pos = 0;
  601. CURTASK exps[CURTASK expsc].string[0] = '\0';
  602. while (paren_level > 0)
  603. {
  604. /* check the current character */
  605. switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
  606. {
  607. case ',': /* end of an argument */
  608. if (paren_level == 1) /* ignore ',' within
  609. * parentheses */
  610. {
  611. /* call bwb_exp() recursively to resolve the
  612. * argument */
  613. if (exp_validarg(CURTASK exps[CURTASK expsc].string) == TRUE)
  614. {
  615. CURTASK exps[CURTASK expsc].rec_pos = 0;
  616. e = bwb_exp(CURTASK exps[CURTASK expsc].string, FALSE,
  617. &(CURTASK exps[CURTASK expsc].rec_pos));
  618. /* assign operation and value at this
  619. * level */
  620. argn = var_chain(argv);
  621. /* 'argn' is the vaiable to use */
  622. var_make(argn, e->type);
  623. switch (argn->type)
  624. {
  625. case NUMBER:
  626. *var_findnval(argn, argn->array_pos)
  627. = exp_getnval(e);
  628. break;
  629. case STRING:
  630. str_btob(var_findsval(argn,
  631. argn->array_pos), exp_getsval(e));
  632. break;
  633. }
  634. ++n_args; /* increment number of
  635. * parameters */
  636. }
  637. s_pos = 0; /* reset counter */
  638. CURTASK exps[CURTASK expsc].string[0] = '\0';
  639. }
  640. else
  641. {
  642. CURTASK exps[CURTASK expsc].string[s_pos]
  643. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  644. ++s_pos;
  645. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  646. }
  647. break;
  648. case '(':
  649. ++paren_level;
  650. CURTASK exps[CURTASK expsc].string[s_pos]
  651. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  652. ++s_pos;
  653. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  654. break;
  655. case ')':
  656. --paren_level;
  657. if (paren_level == 0)
  658. {
  659. /* call bwb_exp() recursively to resolve the
  660. * argument */
  661. if (exp_validarg(CURTASK exps[CURTASK expsc].string) == TRUE)
  662. {
  663. CURTASK exps[CURTASK expsc].rec_pos = 0;
  664. e = bwb_exp(CURTASK exps[CURTASK expsc].string, FALSE,
  665. &(CURTASK exps[CURTASK expsc].rec_pos));
  666. /* assign operation and value at this
  667. * level */
  668. argn = var_chain(argv);
  669. /* 'argn' is the vaiable to use */
  670. var_make(argn, e->type);
  671. switch (argn->type)
  672. {
  673. case NUMBER:
  674. *var_findnval(argn, argn->array_pos)
  675. = exp_getnval(e);
  676. break;
  677. case STRING:
  678. str_btob(var_findsval(argn,
  679. argn->array_pos), exp_getsval(e));
  680. break;
  681. }
  682. ++n_args; /* increment number of
  683. * parameters */
  684. }
  685. s_pos = 0; /* reset counter */
  686. CURTASK exps[CURTASK expsc].string[0] = '\0';
  687. }
  688. else
  689. {
  690. CURTASK exps[CURTASK expsc].string[s_pos]
  691. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  692. ++s_pos;
  693. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  694. }
  695. break;
  696. case '\"': /* embedded string constant */
  697. /* add the initial quotation mark */
  698. CURTASK exps[CURTASK expsc].string[s_pos]
  699. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  700. ++s_pos;
  701. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  702. ++CURTASK exps[CURTASK expsc].pos_adv;
  703. /* add intervening characters */
  704. while ((expression[CURTASK exps[CURTASK expsc].pos_adv] != '\"')
  705. && (expression[CURTASK exps[CURTASK expsc].pos_adv] != '\0'))
  706. {
  707. CURTASK exps[CURTASK expsc].string[s_pos]
  708. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  709. ++s_pos;
  710. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  711. ++CURTASK exps[CURTASK expsc].pos_adv;
  712. }
  713. /* add the concluding quotation mark */
  714. CURTASK exps[CURTASK expsc].string[s_pos]
  715. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  716. ++s_pos;
  717. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  718. /* the following bracketed out 14 July 1992; since
  719. * this counter */
  720. /* incremented at the end of the switch statement,
  721. * this may */
  722. /* increment it past the next character needed */
  723. /* ++CURTASK exps[ CURTASK expsc ].pos_adv; */
  724. break;
  725. default:
  726. CURTASK exps[CURTASK expsc].string[s_pos]
  727. = expression[CURTASK exps[CURTASK expsc].pos_adv];
  728. ++s_pos;
  729. CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
  730. break;
  731. }
  732. /* advance the counter */
  733. ++CURTASK exps[CURTASK expsc].pos_adv;
  734. }
  735. /* call the function vector */
  736. if (TRUE)
  737. {
  738. /* Compare the parameter signature of the caller to the
  739. * callee. This allows for function overloading based upon
  740. * different parameter signatures. It also eliminates the
  741. * need for any intrinsic function to check it's parameter
  742. * count or check the type of it's parameters. The function
  743. * will only be callled with the correct type and count of
  744. * parameters. Examples of common intrinsic functions which
  745. * are overloaded based upon the parameter signature are
  746. * INSTR and MID$. INSTR( [Start], In$, Find$ ) -> instr(
  747. * string, string ) -> 2 parameters instr( number,
  748. * string, string ) -> 3 parameters */
  749. struct bwb_function *f;
  750. char *name;
  751. f = CURTASK exps[CURTASK expsc].function;
  752. name = f->Name;
  753. /* There are two choices for USER DEFINE FUNCTIONS: #1 - A
  754. * fixed number of upto 32 parameters, declared as FUNCTION
  755. * FRED( A$, B$, X, Y ) #2 - A variant number of upto MAXINT
  756. * parameters, declared as FUNCTION FRED( ... ) */
  757. /* Determine the caller's parameter signature, using an
  758. * algorithm matching the intrinsic table: First argument is
  759. * bit 0; if it is 1 then STRING else NUMBER. Second argument
  760. * is bit 1, and so on. */
  761. if (TRUE)
  762. {
  763. /* VERIFY */
  764. unsigned char ParameterCount;
  765. unsigned long ParameterTypes;
  766. if (n_args > 32)
  767. {
  768. /* VARIANT */
  769. ParameterCount = 0xFF;
  770. ParameterTypes = 0;
  771. }
  772. else
  773. {
  774. int i;
  775. ParameterCount = n_args; /* <= 32 */
  776. ParameterTypes = 0;
  777. argn = argv;
  778. for (i = 0; i < ParameterCount; i++)
  779. {
  780. argn = argn->next;
  781. if (argn->type == STRING)
  782. {
  783. ParameterTypes |= (1 << i);
  784. }
  785. }
  786. }
  787. /* did we find the correct function above? */
  788. if (f->ParameterCount != ParameterCount || f->ParameterTypes != ParameterTypes)
  789. {
  790. /* oops */
  791. f = fnc_find_exact(name, ParameterCount, ParameterTypes);
  792. if (f == NULL)
  793. {
  794. /* NOT FOUND */
  795. f = fnc_find_exact(name, 0xFF, 0); /* look for VARIANT */
  796. }
  797. if (f == NULL)
  798. {
  799. /* NOT FOUND */
  800. sprintf(bwb_ebuf, "*** Illegal Function Call (%s) ***", name);
  801. bwb_error(bwb_ebuf);
  802. return OP_ERROR;
  803. }
  804. /* FOUND */
  805. CURTASK exps[CURTASK expsc].function = f;
  806. }
  807. }
  808. }
  809. /* defaullt the return value */
  810. #define RESULT_NUMBER *argv->memnum
  811. #define RESULT_BUFFER argv->memstr->sbuffer
  812. #define RESULT_LENGTH argv->memstr->length
  813. /* defaullt the return value */
  814. {
  815. if ((CURTASK exps[CURTASK expsc].function->ReturnType & 0x00FF) == STRING)
  816. {
  817. var_make(argv, STRING);
  818. RESULT_BUFFER = (char *) CALLOC(BasicStringLengthMax + 1, 1, "exp_function");
  819. RESULT_LENGTH = 0;
  820. RESULT_BUFFER[RESULT_LENGTH] = '\0';
  821. }
  822. else
  823. {
  824. var_make(argv, NUMBER);
  825. RESULT_NUMBER = 0;
  826. }
  827. strcpy(argv->name, CURTASK exps[CURTASK expsc].function->Name);
  828. }
  829. if (CURTASK exps[CURTASK expsc].function->ReturnType & 0xFF00 /* UniqueID is a line
  830. number */ )
  831. {
  832. /* for all USER DEFINED FUNCTIONS: f->UniqueID == line number
  833. * of DEF FN... */
  834. unsigned short cmdnum;
  835. cmdnum = (CURTASK exps[CURTASK expsc].function->ReturnType & 0xFF00) >> 8;
  836. switch (cmdnum)
  837. {
  838. case C_DEF: /* execute a user function declared using DEF
  839. * FN...(...) = ... */
  840. case C_FUNCTION: /* execute a user function declared
  841. * using FUNCTION ...(...) */
  842. case C_SUB: /* execute a user subroutine declared using
  843. * SUB ...(...) */
  844. fnc_deffn(n_args, argv, CURTASK exps[CURTASK expsc].function->UniqueID);
  845. break;
  846. case C_USER_LBL: /* IF ERL > label1 AND ERL < label2
  847. * THEN ... */
  848. if (n_args > 0)
  849. {
  850. bwb_error("SYNTAX ERROR");
  851. }
  852. /* return the line number associated with the label */
  853. RESULT_NUMBER = CURTASK exps[CURTASK expsc].function->UniqueID;
  854. break;
  855. default:
  856. sprintf(bwb_ebuf, "INTERNAL ERROR, in exp_function(): unexpected cmdnum %d", cmdnum);
  857. bwb_error(bwb_ebuf);
  858. break;
  859. }
  860. }
  861. else
  862. {
  863. /* for all INTRINSIC FUNCTIONS: f->UniqueID == #define F_... */
  864. fnc_intrinsic(n_args, argv, CURTASK exps[CURTASK expsc].function->UniqueID);
  865. }
  866. CURTASK exps[CURTASK expsc].type = (char) argv->type;
  867. switch (argv->type)
  868. {
  869. case STRING:
  870. CURTASK exps[CURTASK expsc].operation = CONST_STRING;
  871. b = var_findsval(argv, argv->array_pos);
  872. str_btob(exp_getsval(&(CURTASK exps[CURTASK expsc])), b);
  873. break;
  874. default:
  875. CURTASK exps[CURTASK expsc].operation = NUMBER;
  876. CURTASK exps[CURTASK expsc].nval = var_getnval(argv);
  877. break;
  878. }
  879. /*-------------------------------------------------*/
  880. /* Now free the argv memory */
  881. /* (some other less fortunate routine may need it) */
  882. /* JBV, 10/95 */
  883. /*-------------------------------------------------*/
  884. var_free(argv);
  885. /* return */
  886. return TRUE;
  887. }
  888. /***************************************************************
  889. FUNCTION: exp_variable()
  890. DESCRIPTION: This function interprets a variable.
  891. ***************************************************************/
  892. int
  893. exp_variable(char *expression)
  894. {
  895. int pos;
  896. register int n;
  897. struct bwb_variable *v;
  898. bstring *b;
  899. int n_params;
  900. int pp[MAX_DIMS];
  901. bwx_DEBUG(__FUNCTION__);
  902. /* get the variable name */
  903. exp_getvfname(expression, CURTASK exps[CURTASK expsc].string);
  904. /* now find the variable itself */
  905. v = CURTASK exps[CURTASK expsc].xvar = var_find(CURTASK exps[CURTASK expsc].string);
  906. /* note that this level is a variable */
  907. CURTASK exps[CURTASK expsc].operation = VARIABLE;
  908. /* read subscripts */
  909. pos = strlen(CURTASK exps[CURTASK expsc].string);
  910. if ((v->dimensions == 1) && (v->array_sizes[0] == 1))
  911. {
  912. pos = strlen(v->name);
  913. n_params = 1;
  914. pp[0] = dim_base;
  915. }
  916. else
  917. {
  918. v->IsInDim++;
  919. n_params = dim_getparams_FIXED(expression, &pos, pp);
  920. v->IsInDim--;
  921. }
  922. if (n_params != v->dimensions)
  923. {
  924. sprintf(bwb_ebuf, "DIMENSION OUT OF RANGE %s(%d)", v->name, n_params);
  925. bwb_error(bwb_ebuf);
  926. return FALSE;
  927. }
  928. CURTASK exps[CURTASK expsc].pos_adv = pos;
  929. for (n = 0; n < v->dimensions; ++n)
  930. {
  931. /* newvar->array_sizes[ n ] = pp[ n ] + ( 1 - dim_base ); */
  932. if ((pp[n] < dim_base) || ((pp[n] + (1 - dim_base)) > v->array_sizes[n]))
  933. {
  934. sprintf(bwb_ebuf, "SUBSCRIPT OUT OF RANGE %s(%d)", v->name, pp[n]);
  935. bwb_error(bwb_ebuf);
  936. return FALSE;
  937. }
  938. CURTASK exps[CURTASK expsc].array_pos[n] = v->array_pos[n] = pp[n];
  939. }
  940. /* assign the type and value at this level */
  941. CURTASK exps[CURTASK expsc].type = (char) v->type;
  942. switch (v->type)
  943. {
  944. case STRING:
  945. b = var_findsval(v, v->array_pos);
  946. str_btob(&(CURTASK exps[CURTASK expsc].sval), b);
  947. break;
  948. default:
  949. CURTASK exps[CURTASK expsc].nval = var_getnval(v);
  950. break;
  951. }
  952. /* return */
  953. return TRUE;
  954. }
  955. /* EOF */