lcalc.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. /* calc.c */
  2. /* Keyboard command interpreter */
  3. /* by Stephen L. Moshier */
  4. /* Include functions for IEEE special values */
  5. #define NANS 1
  6. /* length of command line: */
  7. #define LINLEN 128
  8. #define XON 0x11
  9. #define XOFF 0x13
  10. #define SALONE 1
  11. #define DECPDP 0
  12. #define INTLOGIN 0
  13. #define INTHELP 1
  14. #ifndef TRUE
  15. #define TRUE 1
  16. #endif
  17. /* Initialize squirrel printf: */
  18. #define INIPRINTF 0
  19. #if DECPDP
  20. #define TRUE 1
  21. #endif
  22. #include <stdio.h>
  23. #include <string.h>
  24. static char idterp[] = {
  25. "\n\nSteve Moshier's command interpreter V1.3\n"};
  26. #define ISLOWER(c) ((c >= 'a') && (c <= 'z'))
  27. #define ISUPPER(c) ((c >= 'A') && (c <= 'Z'))
  28. #define ISALPHA(c) (ISLOWER(c) || ISUPPER(c))
  29. #define ISDIGIT(c) ((c >= '0') && (c <= '9'))
  30. #define ISATF(c) (((c >= 'a')&&(c <= 'f')) || ((c >= 'A')&&(c <= 'F')))
  31. #define ISXDIGIT(c) (ISDIGIT(c) || ISATF(c))
  32. #define ISOCTAL(c) ((c >= '0') && (c < '8'))
  33. #define ISALNUM(c) (ISALPHA(c) || (ISDIGIT(c))
  34. FILE *fopen();
  35. #include "lcalc.h"
  36. #include "ehead.h"
  37. /* space for working precision numbers */
  38. static long double vs[22];
  39. /* the symbol table of temporary variables: */
  40. #define NTEMP 4
  41. struct varent temp[NTEMP] = {
  42. {"T", OPR | TEMP, &vs[14]},
  43. {"T", OPR | TEMP, &vs[15]},
  44. {"T", OPR | TEMP, &vs[16]},
  45. {"\0", OPR | TEMP, &vs[17]}
  46. };
  47. /* the symbol table of operators */
  48. /* EOL is interpreted on null, newline, or ; */
  49. struct symbol oprtbl[] = {
  50. {"BOL", OPR | BOL, 0},
  51. {"EOL", OPR | EOL, 0},
  52. {"-", OPR | UMINUS, 8},
  53. /*"~", OPR | COMP, 8,*/
  54. {",", OPR | EOE, 1},
  55. {"=", OPR | EQU, 2},
  56. /*"|", OPR | LOR, 3,*/
  57. /*"^", OPR | LXOR, 4,*/
  58. /*"&", OPR | LAND, 5,*/
  59. {"+", OPR | PLUS, 6},
  60. {"-", OPR | MINUS, 6},
  61. {"*", OPR | MULT, 7},
  62. {"/", OPR | DIV, 7},
  63. /*"%", OPR | MOD, 7,*/
  64. {"(", OPR | LPAREN, 11},
  65. {")", OPR | RPAREN, 11},
  66. {"\0", ILLEG, 0}
  67. };
  68. #define NOPR 8
  69. /* the symbol table of indirect variables: */
  70. extern long double PIL;
  71. struct varent indtbl[] = {
  72. {"t", VAR | IND, &vs[21]},
  73. {"u", VAR | IND, &vs[20]},
  74. {"v", VAR | IND, &vs[19]},
  75. {"w", VAR | IND, &vs[18]},
  76. {"x", VAR | IND, &vs[10]},
  77. {"y", VAR | IND, &vs[11]},
  78. {"z", VAR | IND, &vs[12]},
  79. {"pi", VAR | IND, &PIL},
  80. {"\0", ILLEG, 0}
  81. };
  82. /* the symbol table of constants: */
  83. #define NCONST 10
  84. struct varent contbl[NCONST] = {
  85. {"C",CONST,&vs[0]},
  86. {"C",CONST,&vs[1]},
  87. {"C",CONST,&vs[2]},
  88. {"C",CONST,&vs[3]},
  89. {"C",CONST,&vs[4]},
  90. {"C",CONST,&vs[5]},
  91. {"C",CONST,&vs[6]},
  92. {"C",CONST,&vs[7]},
  93. {"C",CONST,&vs[8]},
  94. {"\0",CONST,&vs[9]}
  95. };
  96. /* the symbol table of string variables: */
  97. static char strngs[160] = {0};
  98. #define NSTRNG 5
  99. struct strent strtbl[NSTRNG] = {
  100. {0, VAR | STRING, 0},
  101. {0, VAR | STRING, 0},
  102. {0, VAR | STRING, 0},
  103. {0, VAR | STRING, 0},
  104. {"\0",ILLEG,0},
  105. };
  106. /* Help messages */
  107. #if INTHELP
  108. static char *intmsg[] = {
  109. "?",
  110. "Unkown symbol",
  111. "Expression ends in illegal operator",
  112. "Precede ( by operator",
  113. ")( is illegal",
  114. "Unmatched )",
  115. "Missing )",
  116. "Illegal left hand side",
  117. "Missing symbol",
  118. "Must assign to a variable",
  119. "Divide by zero",
  120. "Missing symbol",
  121. "Missing operator",
  122. "Precede quantity by operator",
  123. "Quantity preceded by )",
  124. "Function syntax",
  125. "Too many function args",
  126. "No more temps",
  127. "Arg list"
  128. };
  129. #endif
  130. /* the symbol table of functions: */
  131. #if SALONE
  132. long double hex(), cmdh(), cmdhlp();
  133. long double cmddm(), cmdtm(), cmdem();
  134. long double take(), mxit(), exit(), bits(), csys();
  135. long double cmddig(), prhlst(), abmac();
  136. long double ifrac(), xcmpl();
  137. long double floorl(), logl(), powl(), sqrtl(), tanhl(), expl();
  138. long double ellpel(), ellpkl(), incbetl(), incbil();
  139. long double stdtrl(), stdtril(), zstdtrl(), zstdtril();
  140. long double sinl(), cosl(), tanl(), asinl(), acosl(), atanl(), atan2l();
  141. long double tanhl(), atanhl();
  142. #ifdef NANS
  143. int isnanl(), isfinitel(), signbitl();
  144. long double zisnan(), zisfinite(), zsignbit();
  145. #endif
  146. struct funent funtbl[] = {
  147. {"h", OPR | FUNC, cmdh},
  148. {"help", OPR | FUNC, cmdhlp},
  149. {"hex", OPR | FUNC, hex},
  150. /*"view", OPR | FUNC, view,*/
  151. {"exp", OPR | FUNC, expl},
  152. {"floor", OPR | FUNC, floorl},
  153. {"log", OPR | FUNC, logl},
  154. {"pow", OPR | FUNC, powl},
  155. {"sqrt", OPR | FUNC, sqrtl},
  156. {"tanh", OPR | FUNC, tanhl},
  157. {"sin", OPR | FUNC, sinl},
  158. {"cos", OPR | FUNC, cosl},
  159. {"tan", OPR | FUNC, tanl},
  160. {"asin", OPR | FUNC, asinl},
  161. {"acos", OPR | FUNC, acosl},
  162. {"atan", OPR | FUNC, atanl},
  163. {"atantwo", OPR | FUNC, atan2l},
  164. {"tanh", OPR | FUNC, tanhl},
  165. {"atanh", OPR | FUNC, atanhl},
  166. {"ellpe", OPR | FUNC, ellpel},
  167. {"ellpk", OPR | FUNC, ellpkl},
  168. {"incbet", OPR | FUNC, incbetl},
  169. {"incbi", OPR | FUNC, incbil},
  170. {"stdtr", OPR | FUNC, zstdtrl},
  171. {"stdtri", OPR | FUNC, zstdtril},
  172. {"ifrac", OPR | FUNC, ifrac},
  173. {"cmp", OPR | FUNC, xcmpl},
  174. #ifdef NANS
  175. {"isnan", OPR | FUNC, zisnan},
  176. {"isfinite", OPR | FUNC, zisfinite},
  177. {"signbit", OPR | FUNC, zsignbit},
  178. #endif
  179. {"bits", OPR | FUNC, bits},
  180. {"digits", OPR | FUNC, cmddig},
  181. {"dm", OPR | FUNC, cmddm},
  182. {"tm", OPR | FUNC, cmdtm},
  183. {"em", OPR | FUNC, cmdem},
  184. {"take", OPR | FUNC | COMMAN, take},
  185. {"system", OPR | FUNC | COMMAN, csys},
  186. {"exit", OPR | FUNC, mxit},
  187. /*
  188. "remain", OPR | FUNC, eremain,
  189. */
  190. {"\0", OPR | FUNC, 0}
  191. };
  192. /* the symbol table of key words */
  193. struct funent keytbl[] = {
  194. {"\0", ILLEG, 0}
  195. };
  196. #endif
  197. void zgets(), init();
  198. /* Number of decimals to display */
  199. #define DEFDIS 70
  200. static int ndigits = DEFDIS;
  201. /* Menu stack */
  202. struct funent *menstk[5] = {&funtbl[0], NULL, NULL, NULL, NULL};
  203. int menptr = 0;
  204. /* Take file stack */
  205. FILE *takstk[10] = {0};
  206. int takptr = -1;
  207. /* size of the expression scan list: */
  208. #define NSCAN 20
  209. /* previous token, saved for syntax checking: */
  210. struct symbol *lastok = 0;
  211. /* variables used by parser: */
  212. static char str[128] = {0};
  213. int uposs = 0; /* possible unary operator */
  214. static long double qnc;
  215. char lc[40] = { '\n' }; /* ASCII string of token symbol */
  216. static char line[LINLEN] = { '\n','\0' }; /* input command line */
  217. static char maclin[LINLEN] = { '\n','\0' }; /* macro command */
  218. char *interl = line; /* pointer into line */
  219. extern char *interl;
  220. static int maccnt = 0; /* number of times to execute macro command */
  221. static int comptr = 0; /* comma stack pointer */
  222. static long double comstk[5]; /* comma argument stack */
  223. static int narptr = 0; /* pointer to number of args */
  224. static int narstk[5] = {0}; /* stack of number of function args */
  225. /* main() */
  226. /* Entire program starts here */
  227. int main()
  228. {
  229. /* the scan table: */
  230. /* array of pointers to symbols which have been parsed: */
  231. struct symbol *ascsym[NSCAN];
  232. /* current place in ascsym: */
  233. register struct symbol **as;
  234. /* array of attributes of operators parsed: */
  235. int ascopr[NSCAN];
  236. /* current place in ascopr: */
  237. register int *ao;
  238. #if LARGEMEM
  239. /* array of precedence levels of operators: */
  240. long asclev[NSCAN];
  241. /* current place in asclev: */
  242. long *al;
  243. long symval; /* value of symbol just parsed */
  244. #else
  245. int asclev[NSCAN];
  246. int *al;
  247. int symval;
  248. #endif
  249. long double acc; /* the accumulator, for arithmetic */
  250. int accflg; /* flags accumulator in use */
  251. long double val; /* value to be combined into accumulator */
  252. register struct symbol *psym; /* pointer to symbol just parsed */
  253. struct varent *pvar; /* pointer to an indirect variable symbol */
  254. struct funent *pfun; /* pointer to a function symbol */
  255. struct strent *pstr; /* pointer to a string symbol */
  256. int att; /* attributes of symbol just parsed */
  257. int i; /* counter */
  258. int offset; /* parenthesis level */
  259. int lhsflg; /* kluge to detect illegal assignments */
  260. struct symbol *parser(); /* parser returns pointer to symbol */
  261. int errcod; /* for syntax error printout */
  262. /* Perform general initialization */
  263. init();
  264. menstk[0] = &funtbl[0];
  265. menptr = 0;
  266. cmdhlp(); /* print out list of symbols */
  267. /* Return here to get next command line to execute */
  268. getcmd:
  269. /* initialize registers and mutable symbols */
  270. accflg = 0; /* Accumulator not in use */
  271. acc = 0.0L; /* Clear the accumulator */
  272. offset = 0; /* Parenthesis level zero */
  273. comptr = 0; /* Start of comma stack */
  274. narptr = -1; /* Start of function arg counter stack */
  275. psym = (struct symbol *)&contbl[0];
  276. for( i=0; i<NCONST; i++ )
  277. {
  278. psym->attrib = CONST; /* clearing the busy bit */
  279. ++psym;
  280. }
  281. psym = (struct symbol *)&temp[0];
  282. for( i=0; i<NTEMP; i++ )
  283. {
  284. psym->attrib = VAR | TEMP; /* clearing the busy bit */
  285. ++psym;
  286. }
  287. pstr = &strtbl[0];
  288. for( i=0; i<NSTRNG; i++ )
  289. {
  290. pstr->spel = &strngs[ 40*i ];
  291. pstr->attrib = STRING | VAR;
  292. pstr->string = &strngs[ 40*i ];
  293. ++pstr;
  294. }
  295. /* List of scanned symbols is empty: */
  296. as = &ascsym[0];
  297. *as = 0;
  298. --as;
  299. /* First item in scan list is Beginning of Line operator */
  300. ao = &ascopr[0];
  301. *ao = oprtbl[0].attrib & 0xf; /* BOL */
  302. /* value of first item: */
  303. al = &asclev[0];
  304. *al = oprtbl[0].sym;
  305. lhsflg = 0; /* illegal left hand side flag */
  306. psym = &oprtbl[0]; /* pointer to current token */
  307. /* get next token from input string */
  308. gettok:
  309. lastok = psym; /* last token = current token */
  310. psym = parser(); /* get a new current token */
  311. /*printf( "%s attrib %7o value %7o\n", psym->spel, psym->attrib & 0xffff,
  312. psym->sym );*/
  313. /* Examine attributes of the symbol returned by the parser */
  314. att = psym->attrib;
  315. if( att == ILLEG )
  316. {
  317. errcod = 1;
  318. goto synerr;
  319. }
  320. /* Push functions onto scan list without analyzing further */
  321. if( att & FUNC )
  322. {
  323. /* A command is a function whose argument is
  324. * a pointer to the rest of the input line.
  325. * A second argument is also passed: the address
  326. * of the last token parsed.
  327. */
  328. if( att & COMMAN )
  329. {
  330. pfun = (struct funent *)psym;
  331. ( *(pfun->fun))( interl, lastok );
  332. abmac(); /* scrub the input line */
  333. goto getcmd; /* and ask for more input */
  334. }
  335. ++narptr; /* offset to number of args */
  336. narstk[narptr] = 0;
  337. i = lastok->attrib & 0xffff; /* attrib=short, i=int */
  338. if( ((i & OPR) == 0)
  339. || (i == (OPR | RPAREN))
  340. || (i == (OPR | FUNC)) )
  341. {
  342. errcod = 15;
  343. goto synerr;
  344. }
  345. ++lhsflg;
  346. ++as;
  347. *as = psym;
  348. ++ao;
  349. *ao = FUNC;
  350. ++al;
  351. *al = offset + UMINUS;
  352. goto gettok;
  353. }
  354. /* deal with operators */
  355. if( att & OPR )
  356. {
  357. att &= 0xf;
  358. /* expression cannot end with an operator other than
  359. * (, ), BOL, or a function
  360. */
  361. if( (att == RPAREN) || (att == EOL) || (att == EOE))
  362. {
  363. i = lastok->attrib & 0xffff; /* attrib=short, i=int */
  364. if( (i & OPR)
  365. && (i != (OPR | RPAREN))
  366. && (i != (OPR | LPAREN))
  367. && (i != (OPR | FUNC))
  368. && (i != (OPR | BOL)) )
  369. {
  370. errcod = 2;
  371. goto synerr;
  372. }
  373. }
  374. ++lhsflg; /* any operator but ( and = is not a legal lhs */
  375. /* operator processing, continued */
  376. switch( att )
  377. {
  378. case EOE:
  379. lhsflg = 0;
  380. break;
  381. case LPAREN:
  382. /* ( must be preceded by an operator of some sort. */
  383. if( ((lastok->attrib & OPR) == 0) )
  384. {
  385. errcod = 3;
  386. goto synerr;
  387. }
  388. /* also, a preceding ) is illegal */
  389. if( (unsigned short )lastok->attrib == (OPR|RPAREN))
  390. {
  391. errcod = 4;
  392. goto synerr;
  393. }
  394. /* Begin looking for illegal left hand sides: */
  395. lhsflg = 0;
  396. offset += RPAREN; /* new parenthesis level */
  397. goto gettok;
  398. case RPAREN:
  399. offset -= RPAREN; /* parenthesis level */
  400. if( offset < 0 )
  401. {
  402. errcod = 5; /* parenthesis error */
  403. goto synerr;
  404. }
  405. goto gettok;
  406. case EOL:
  407. if( offset != 0 )
  408. {
  409. errcod = 6; /* parenthesis error */
  410. goto synerr;
  411. }
  412. break;
  413. case EQU:
  414. if( --lhsflg ) /* was incremented before switch{} */
  415. {
  416. errcod = 7;
  417. goto synerr;
  418. }
  419. case UMINUS:
  420. case COMP:
  421. goto pshopr; /* evaluate right to left */
  422. default: ;
  423. }
  424. /* evaluate expression whenever precedence is not increasing */
  425. symval = psym->sym + offset;
  426. while( symval <= *al )
  427. {
  428. /* if just starting, must fill accumulator with last
  429. * thing on the line
  430. */
  431. if( (accflg == 0) && (as >= ascsym) && (((*as)->attrib & FUNC) == 0 ))
  432. {
  433. pvar = (struct varent *)*as;
  434. /*
  435. if( pvar->attrib & STRING )
  436. strcpy( (char *)&acc, (char *)pvar->value );
  437. else
  438. */
  439. acc = *pvar->value;
  440. --as;
  441. accflg = 1;
  442. }
  443. /* handle beginning of line type cases, where the symbol
  444. * list ascsym[] may be empty.
  445. */
  446. switch( *ao )
  447. {
  448. case BOL:
  449. /* printf( "%.16e\n", (double )acc ); */
  450. #if NE == 6
  451. e64toasc( &acc, str, 100 );
  452. #else
  453. e113toasc( &acc, str, 100 );
  454. #endif
  455. printf( "%s\n", str );
  456. goto getcmd; /* all finished */
  457. case UMINUS:
  458. acc = -acc;
  459. goto nochg;
  460. /*
  461. case COMP:
  462. acc = ~acc;
  463. goto nochg;
  464. */
  465. default: ;
  466. }
  467. /* Now it is illegal for symbol list to be empty,
  468. * because we are going to need a symbol below.
  469. */
  470. if( as < &ascsym[0] )
  471. {
  472. errcod = 8;
  473. goto synerr;
  474. }
  475. /* get attributes and value of current symbol */
  476. att = (*as)->attrib;
  477. pvar = (struct varent *)*as;
  478. if( att & FUNC )
  479. val = 0.0L;
  480. else
  481. {
  482. /*
  483. if( att & STRING )
  484. strcpy( (char *)&val, (char *)pvar->value );
  485. else
  486. */
  487. val = *pvar->value;
  488. }
  489. /* Expression evaluation, continued. */
  490. switch( *ao )
  491. {
  492. case FUNC:
  493. pfun = (struct funent *)*as;
  494. /* Call the function with appropriate number of args */
  495. i = narstk[ narptr ];
  496. --narptr;
  497. switch(i)
  498. {
  499. case 0:
  500. acc = ( *(pfun->fun) )(acc);
  501. break;
  502. case 1:
  503. acc = ( *(pfun->fun) )(acc, comstk[comptr-1]);
  504. break;
  505. case 2:
  506. acc = ( *(pfun->fun) )(acc, comstk[comptr-2],
  507. comstk[comptr-1]);
  508. break;
  509. case 3:
  510. acc = ( *(pfun->fun) )(acc, comstk[comptr-3],
  511. comstk[comptr-2], comstk[comptr-1]);
  512. break;
  513. default:
  514. errcod = 16;
  515. goto synerr;
  516. }
  517. comptr -= i;
  518. accflg = 1; /* in case at end of line */
  519. break;
  520. case EQU:
  521. if( ( att & TEMP) || ((att & VAR) == 0) || (att & STRING) )
  522. {
  523. errcod = 9;
  524. goto synerr; /* can only assign to a variable */
  525. }
  526. pvar = (struct varent *)*as;
  527. *pvar->value = acc;
  528. break;
  529. case PLUS:
  530. acc = acc + val; break;
  531. case MINUS:
  532. acc = val - acc; break;
  533. case MULT:
  534. acc = acc * val; break;
  535. case DIV:
  536. if( acc == 0.0L )
  537. {
  538. /*
  539. divzer:
  540. */
  541. errcod = 10;
  542. goto synerr;
  543. }
  544. acc = val / acc; break;
  545. /*
  546. case MOD:
  547. if( acc == 0 )
  548. goto divzer;
  549. acc = val % acc; break;
  550. case LOR:
  551. acc |= val; break;
  552. case LXOR:
  553. acc ^= val; break;
  554. case LAND:
  555. acc &= val; break;
  556. */
  557. case EOE:
  558. if( narptr < 0 )
  559. {
  560. errcod = 18;
  561. goto synerr;
  562. }
  563. narstk[narptr] += 1;
  564. comstk[comptr++] = acc;
  565. /* printf( "\ncomptr: %d narptr: %d %d\n", comptr, narptr, acc );*/
  566. acc = val;
  567. break;
  568. }
  569. /* expression evaluation, continued */
  570. /* Pop evaluated tokens from scan list: */
  571. /* make temporary variable not busy */
  572. if( att & TEMP )
  573. (*as)->attrib &= ~BUSY;
  574. if( as < &ascsym[0] ) /* can this happen? */
  575. {
  576. errcod = 11;
  577. goto synerr;
  578. }
  579. --as;
  580. nochg:
  581. --ao;
  582. --al;
  583. if( ao < &ascopr[0] ) /* can this happen? */
  584. {
  585. errcod = 12;
  586. goto synerr;
  587. }
  588. /* If precedence level will now increase, then */
  589. /* save accumulator in a temporary location */
  590. if( symval > *al )
  591. {
  592. /* find a free temp location */
  593. pvar = &temp[0];
  594. for( i=0; i<NTEMP; i++ )
  595. {
  596. if( (pvar->attrib & BUSY) == 0)
  597. goto temfnd;
  598. ++pvar;
  599. }
  600. errcod = 17;
  601. printf( "no more temps\n" );
  602. pvar = &temp[0];
  603. goto synerr;
  604. temfnd:
  605. pvar->attrib |= BUSY;
  606. *pvar->value = acc;
  607. /*printf( "temp %d\n", acc );*/
  608. accflg = 0;
  609. ++as; /* push the temp onto the scan list */
  610. *as = (struct symbol *)pvar;
  611. }
  612. } /* End of evaluation loop */
  613. /* Push operator onto scan list when precedence increases */
  614. pshopr:
  615. ++ao;
  616. *ao = psym->attrib & 0xf;
  617. ++al;
  618. *al = psym->sym + offset;
  619. goto gettok;
  620. } /* end of OPR processing */
  621. /* Token was not an operator. Push symbol onto scan list. */
  622. if( (lastok->attrib & OPR) == 0 )
  623. {
  624. errcod = 13;
  625. goto synerr; /* quantities must be preceded by an operator */
  626. }
  627. if( (unsigned short )lastok->attrib == (OPR | RPAREN) ) /* ...but not by ) */
  628. {
  629. errcod = 14;
  630. goto synerr;
  631. }
  632. ++as;
  633. *as = psym;
  634. goto gettok;
  635. synerr:
  636. #if INTHELP
  637. printf( "%s ", intmsg[errcod] );
  638. #endif
  639. printf( " error %d\n", errcod );
  640. abmac(); /* flush the command line */
  641. goto getcmd;
  642. } /* end of program */
  643. /* parser() */
  644. /* Get token from input string and identify it. */
  645. static char number[128];
  646. struct symbol *parser( )
  647. {
  648. register struct symbol *psym;
  649. register char *pline;
  650. struct varent *pvar;
  651. struct strent *pstr;
  652. char *cp, *plc, *pn;
  653. long lnc;
  654. int i;
  655. long double tem;
  656. /* reference for old Whitesmiths compiler: */
  657. /*
  658. *extern FILE *stdout;
  659. */
  660. pline = interl; /* get current location in command string */
  661. /* If at beginning of string, must ask for more input */
  662. if( pline == line )
  663. {
  664. if( maccnt > 0 )
  665. {
  666. --maccnt;
  667. cp = maclin;
  668. plc = pline;
  669. while( (*plc++ = *cp++) != 0 )
  670. ;
  671. goto mstart;
  672. }
  673. if( takptr < 0 )
  674. { /* no take file active: prompt keyboard input */
  675. printf("* ");
  676. }
  677. /* Various ways of typing in a command line. */
  678. /*
  679. * Old Whitesmiths call to print "*" immediately
  680. * use RT11 .GTLIN to get command string
  681. * from command file or terminal
  682. */
  683. /*
  684. * fflush(stdout);
  685. * gtlin(line);
  686. */
  687. zgets( line, TRUE ); /* keyboard input for other systems: */
  688. mstart:
  689. uposs = 1; /* unary operators possible at start of line */
  690. }
  691. ignore:
  692. /* Skip over spaces */
  693. while( *pline == ' ' )
  694. ++pline;
  695. /* unary minus after operator */
  696. if( uposs && (*pline == '-') )
  697. {
  698. psym = &oprtbl[2]; /* UMINUS */
  699. ++pline;
  700. goto pdon3;
  701. }
  702. /* COMP */
  703. /*
  704. if( uposs && (*pline == '~') )
  705. {
  706. psym = &oprtbl[3];
  707. ++pline;
  708. goto pdon3;
  709. }
  710. */
  711. if( uposs && (*pline == '+') ) /* ignore leading plus sign */
  712. {
  713. ++pline;
  714. goto ignore;
  715. }
  716. /* end of null terminated input */
  717. if( (*pline == '\n') || (*pline == '\0') || (*pline == '\r') )
  718. {
  719. pline = line;
  720. goto endlin;
  721. }
  722. if( *pline == ';' )
  723. {
  724. ++pline;
  725. endlin:
  726. psym = &oprtbl[1]; /* EOL */
  727. goto pdon2;
  728. }
  729. /* parser() */
  730. /* Test for numeric input */
  731. if( (ISDIGIT(*pline)) || (*pline == '.') )
  732. {
  733. lnc = 0; /* initialize numeric input to zero */
  734. qnc = 0.0L;
  735. if( *pline == '0' )
  736. { /* leading "0" may mean octal or hex radix */
  737. ++pline;
  738. if( *pline == '.' )
  739. goto decimal; /* 0.ddd */
  740. /* leading "0x" means hexadecimal radix */
  741. if( (*pline == 'x') || (*pline == 'X') )
  742. {
  743. ++pline;
  744. while( ISXDIGIT(*pline) )
  745. {
  746. i = *pline++ & 0xff;
  747. if( i >= 'a' )
  748. i -= 047;
  749. if( i >= 'A' )
  750. i -= 07;
  751. i -= 060;
  752. lnc = (lnc << 4) + i;
  753. qnc = lnc;
  754. }
  755. goto numdon;
  756. }
  757. else
  758. {
  759. while( ISOCTAL( *pline ) )
  760. {
  761. i = ((*pline++) & 0xff) - 060;
  762. lnc = (lnc << 3) + i;
  763. qnc = lnc;
  764. }
  765. goto numdon;
  766. }
  767. }
  768. else
  769. {
  770. /* no leading "0" means decimal radix */
  771. /******/
  772. decimal:
  773. pn = number;
  774. while( (ISDIGIT(*pline)) || (*pline == '.') )
  775. *pn++ = *pline++;
  776. /* get possible exponent field */
  777. if( (*pline == 'e') || (*pline == 'E') )
  778. *pn++ = *pline++;
  779. else
  780. goto numcvt;
  781. if( (*pline == '-') || (*pline == '+') )
  782. *pn++ = *pline++;
  783. while( ISDIGIT(*pline) )
  784. *pn++ = *pline++;
  785. numcvt:
  786. *pn++ = ' ';
  787. *pn++ = 0;
  788. #if NE == 6
  789. asctoe64( number, &qnc );
  790. #else
  791. asctoe113( number, &qnc );
  792. #endif
  793. /* sscanf( number, "%le", &nc ); */
  794. }
  795. /* output the number */
  796. numdon:
  797. /* search the symbol table of constants */
  798. pvar = &contbl[0];
  799. for( i=0; i<NCONST; i++ )
  800. {
  801. if( (pvar->attrib & BUSY) == 0 )
  802. goto confnd;
  803. tem = *pvar->value;
  804. if( tem == qnc )
  805. {
  806. psym = (struct symbol *)pvar;
  807. goto pdon2;
  808. }
  809. ++pvar;
  810. }
  811. printf( "no room for constant\n" );
  812. psym = (struct symbol *)&contbl[0];
  813. goto pdon2;
  814. confnd:
  815. pvar->spel= contbl[0].spel;
  816. pvar->attrib = CONST | BUSY;
  817. *pvar->value = qnc;
  818. psym = (struct symbol *)pvar;
  819. goto pdon2;
  820. }
  821. /* check for operators */
  822. psym = &oprtbl[3];
  823. for( i=0; i<NOPR; i++ )
  824. {
  825. if( *pline == *(psym->spel) )
  826. goto pdon1;
  827. ++psym;
  828. }
  829. /* if quoted, it is a string variable */
  830. if( *pline == '"' )
  831. {
  832. /* find an empty slot for the string */
  833. pstr = strtbl; /* string table */
  834. for( i=0; i<NSTRNG-1; i++ )
  835. {
  836. if( (pstr->attrib & BUSY) == 0 )
  837. goto fndstr;
  838. ++pstr;
  839. }
  840. printf( "No room for string\n" );
  841. pstr->attrib |= ILLEG;
  842. psym = (struct symbol *)pstr;
  843. goto pdon0;
  844. fndstr:
  845. pstr->attrib |= BUSY;
  846. plc = pstr->string;
  847. ++pline;
  848. for( i=0; i<39; i++ )
  849. {
  850. *plc++ = *pline;
  851. if( (*pline == '\n') || (*pline == '\0') || (*pline == '\r') )
  852. {
  853. illstr:
  854. pstr = &strtbl[NSTRNG-1];
  855. pstr->attrib |= ILLEG;
  856. printf( "Missing string terminator\n" );
  857. psym = (struct symbol *)pstr;
  858. goto pdon0;
  859. }
  860. if( *pline++ == '"' )
  861. goto finstr;
  862. }
  863. goto illstr; /* no terminator found */
  864. finstr:
  865. --plc;
  866. *plc = '\0';
  867. psym = (struct symbol *)pstr;
  868. goto pdon2;
  869. }
  870. /* If none of the above, search function and symbol tables: */
  871. /* copy character string to array lc[] */
  872. plc = &lc[0];
  873. while( ISALPHA(*pline) )
  874. {
  875. /* convert to lower case characters */
  876. if( ISUPPER( *pline ) )
  877. *pline += 040;
  878. *plc++ = *pline++;
  879. }
  880. *plc = 0; /* Null terminate the output string */
  881. /* parser() */
  882. psym = (struct symbol *)menstk[menptr]; /* function table */
  883. plc = &lc[0];
  884. cp = psym->spel;
  885. do
  886. {
  887. if( strcmp( plc, cp ) == 0 )
  888. goto pdon3; /* following unary minus is possible */
  889. ++psym;
  890. cp = psym->spel;
  891. }
  892. while( *cp != '\0' );
  893. psym = (struct symbol *)&indtbl[0]; /* indirect symbol table */
  894. plc = &lc[0];
  895. cp = psym->spel;
  896. do
  897. {
  898. if( strcmp( plc, cp ) == 0 )
  899. goto pdon2;
  900. ++psym;
  901. cp = psym->spel;
  902. }
  903. while( *cp != '\0' );
  904. pdon0:
  905. pline = line; /* scrub line if illegal symbol */
  906. goto pdon2;
  907. pdon1:
  908. ++pline;
  909. if( (psym->attrib & 0xf) == RPAREN )
  910. pdon2: uposs = 0;
  911. else
  912. pdon3: uposs = 1;
  913. interl = pline;
  914. return( psym );
  915. } /* end of parser */
  916. /* exit from current menu */
  917. long double cmdex()
  918. {
  919. if( menptr == 0 )
  920. {
  921. printf( "Main menu is active.\n" );
  922. }
  923. else
  924. --menptr;
  925. cmdh();
  926. return(0.0L);
  927. }
  928. /* gets() */
  929. void zgets( gline, echo )
  930. char *gline;
  931. int echo;
  932. {
  933. register char *pline;
  934. register int i;
  935. scrub:
  936. pline = gline;
  937. getsl:
  938. if( (pline - gline) >= LINLEN )
  939. {
  940. printf( "\nLine too long\n *" );
  941. goto scrub;
  942. }
  943. if( takptr < 0 )
  944. { /* get character from keyboard */
  945. /*
  946. if DECPDP
  947. gtlin( gline );
  948. return(0);
  949. else
  950. */
  951. *pline = getchar();
  952. /*endif*/
  953. }
  954. else
  955. { /* get a character from take file */
  956. i = fgetc( takstk[takptr] );
  957. if( i == -1 )
  958. { /* end of take file */
  959. if( takptr >= 0 )
  960. { /* close file and bump take stack */
  961. fclose( takstk[takptr] );
  962. takptr -= 1;
  963. }
  964. if( takptr < 0 ) /* no more take files: */
  965. printf( "*" ); /* prompt keyboard input */
  966. goto scrub; /* start a new input line */
  967. }
  968. *pline = i;
  969. }
  970. *pline &= 0x7f;
  971. /* xon or xoff characters need filtering out. */
  972. if ( *pline == XON || *pline == XOFF )
  973. goto getsl;
  974. /* control U or control C */
  975. if( (*pline == 025) || (*pline == 03) )
  976. {
  977. printf( "\n" );
  978. goto scrub;
  979. }
  980. /* Backspace or rubout */
  981. if( (*pline == 010) || (*pline == 0177) )
  982. {
  983. pline -= 1;
  984. if( pline >= gline )
  985. {
  986. if ( echo )
  987. printf( "\010\040\010" );
  988. goto getsl;
  989. }
  990. else
  991. goto scrub;
  992. }
  993. if ( echo )
  994. printf( "%c", *pline );
  995. if( (*pline != '\n') && (*pline != '\r') )
  996. {
  997. ++pline;
  998. goto getsl;
  999. }
  1000. *pline = 0;
  1001. if ( echo )
  1002. printf( "%c", '\n' ); /* \r already echoed */
  1003. }
  1004. /* help function */
  1005. long double cmdhlp()
  1006. {
  1007. printf( "%s", idterp );
  1008. printf( "\nFunctions:\n" );
  1009. prhlst( &funtbl[0] );
  1010. printf( "\nVariables:\n" );
  1011. prhlst( &indtbl[0] );
  1012. printf( "\nOperators:\n" );
  1013. prhlst( &oprtbl[2] );
  1014. printf("\n");
  1015. return(0.0L);
  1016. }
  1017. long double cmdh()
  1018. {
  1019. prhlst( menstk[menptr] );
  1020. printf( "\n" );
  1021. return(0.0L);
  1022. }
  1023. /* print keyword spellings */
  1024. long double prhlst(ps)
  1025. register struct symbol *ps;
  1026. {
  1027. register int j, k;
  1028. int m;
  1029. j = 0;
  1030. while( *(ps->spel) != '\0' )
  1031. {
  1032. k = strlen( ps->spel ) - 1;
  1033. /* size of a tab field is 2**3 chars */
  1034. m = ((k >> 3) + 1) << 3;
  1035. j += m;
  1036. if( j > 72 )
  1037. {
  1038. printf( "\n" );
  1039. j = m;
  1040. }
  1041. printf( "%s\t", ps->spel );
  1042. ++ps;
  1043. }
  1044. return(0.0L);
  1045. }
  1046. #if SALONE
  1047. void init(){}
  1048. #endif
  1049. /* macro commands */
  1050. /* define macro */
  1051. long double cmddm()
  1052. {
  1053. zgets( maclin, TRUE );
  1054. return(0.0L);
  1055. }
  1056. /* type (i.e., display) macro */
  1057. long double cmdtm()
  1058. {
  1059. printf( "%s\n", maclin );
  1060. return(0.0L);
  1061. }
  1062. /* execute macro # times */
  1063. long double cmdem( arg )
  1064. long double arg;
  1065. {
  1066. long double f;
  1067. long n;
  1068. long double floorl();
  1069. f = floorl(arg);
  1070. n = f;
  1071. if( n <= 0 )
  1072. n = 1;
  1073. maccnt = n;
  1074. return(0.0L);
  1075. }
  1076. /* open a take file */
  1077. long double take( fname )
  1078. char *fname;
  1079. {
  1080. FILE *f;
  1081. while( *fname == ' ' )
  1082. fname += 1;
  1083. f = fopen( fname, "r" );
  1084. if( f == 0 )
  1085. {
  1086. printf( "Can't open take file %s\n", fname );
  1087. takptr = -1; /* terminate all take file input */
  1088. return(0.0L);
  1089. }
  1090. takptr += 1;
  1091. takstk[ takptr ] = f;
  1092. printf( "Running %s\n", fname );
  1093. return(0.0L);
  1094. }
  1095. /* abort macro execution */
  1096. long double abmac()
  1097. {
  1098. maccnt = 0;
  1099. interl = line;
  1100. return(0.0L);
  1101. }
  1102. /* display integer part in hex, octal, and decimal
  1103. */
  1104. long double hex(qx)
  1105. long double qx;
  1106. {
  1107. long double f;
  1108. long z;
  1109. long double floorl();
  1110. f = floorl(qx);
  1111. z = f;
  1112. printf( "0%lo 0x%lx %ld.\n", z, z, z );
  1113. return(qx);
  1114. }
  1115. #define NASC 16
  1116. long double bits( x )
  1117. long double x;
  1118. {
  1119. int i, j;
  1120. unsigned short dd[4], ee[10];
  1121. char strx[40];
  1122. unsigned short *p;
  1123. p = (unsigned short *) &x;
  1124. for( i=0; i<NE; i++ )
  1125. ee[i] = *p++;
  1126. j = 0;
  1127. for( i=0; i<NE; i++ )
  1128. {
  1129. printf( "0x%04x,", ee[i] & 0xffff );
  1130. if( ++j > 7 )
  1131. {
  1132. j = 0;
  1133. printf( "\n" );
  1134. }
  1135. }
  1136. printf( "\n" );
  1137. /* double conversions
  1138. */
  1139. *((double *)dd) = x;
  1140. printf( "double: " );
  1141. for( i=0; i<4; i++ )
  1142. printf( "0x%04x,", dd[i] & 0xffff );
  1143. printf( "\n" );
  1144. #if 1
  1145. printf( "double -> long double: " );
  1146. *(long double *)ee = *(double *)dd;
  1147. for( i=0; i<6; i++ )
  1148. printf( "0x%04x,", ee[i] & 0xffff );
  1149. printf( "\n" );
  1150. e53toasc( dd, strx, NASC );
  1151. printf( "e53toasc: %s\n", strx );
  1152. printf( "Native printf: %.17e\n", *(double *)dd );
  1153. /* float conversions
  1154. */
  1155. *((float *)dd) = x;
  1156. printf( "float: " );
  1157. for( i=0; i<2; i++ )
  1158. printf( "0x%04x,", dd[i] & 0xffff );
  1159. printf( "\n" );
  1160. e24toe( dd, ee );
  1161. printf( "e24toe: " );
  1162. for( i=0; i<NE; i++ )
  1163. printf( "0x%04x,", ee[i] & 0xffff );
  1164. printf( "\n" );
  1165. e24toasc( dd, strx, NASC );
  1166. printf( "e24toasc: %s\n", strx );
  1167. /* printf( "Native printf: %.16e\n", (double) *(float *)dd ); */
  1168. #ifdef DEC
  1169. printf( "etodec: " );
  1170. etodec( x, dd );
  1171. for( i=0; i<4; i++ )
  1172. printf( "0x%04x,", dd[i] & 0xffff );
  1173. printf( "\n" );
  1174. printf( "dectoe: " );
  1175. dectoe( dd, ee );
  1176. for( i=0; i<NE; i++ )
  1177. printf( "0x%04x,", ee[i] & 0xffff );
  1178. printf( "\n" );
  1179. printf( "DEC printf: %.16e\n", *(double *)dd );
  1180. #endif
  1181. #endif /* 0 */
  1182. return(x);
  1183. }
  1184. /* Exit to monitor. */
  1185. long double mxit()
  1186. {
  1187. exit(0);
  1188. return(0.0L);
  1189. }
  1190. long double cmddig( x )
  1191. long double x;
  1192. {
  1193. long double f;
  1194. long lx;
  1195. f = floorl(x);
  1196. lx = f;
  1197. ndigits = lx;
  1198. if( ndigits <= 0 )
  1199. ndigits = DEFDIS;
  1200. return(f);
  1201. }
  1202. long double csys(x)
  1203. char *x;
  1204. {
  1205. void system();
  1206. system( x+1 );
  1207. cmdh();
  1208. return(0.0L);
  1209. }
  1210. long double ifrac(x)
  1211. long double x;
  1212. {
  1213. unsigned long lx;
  1214. long double y, z;
  1215. z = floorl(x);
  1216. lx = z;
  1217. y = x - z;
  1218. printf( " int = %lx\n", lx );
  1219. return(y);
  1220. }
  1221. long double xcmpl(x,y)
  1222. long double x,y;
  1223. {
  1224. long double ans;
  1225. char str[40];
  1226. #if NE == 6
  1227. e64toasc( &x, str, 100 );
  1228. printf( "x = %s\n", str );
  1229. e64toasc( &y, str, 100 );
  1230. printf( "y = %s\n", str );
  1231. #else
  1232. e113toasc( &x, str, 100 );
  1233. printf( "x = %s\n", str );
  1234. e113toasc( &y, str, 100 );
  1235. printf( "y = %s\n", str );
  1236. #endif
  1237. ans = -2.0;
  1238. if( x == y )
  1239. {
  1240. printf( "x == y " );
  1241. ans = 0.0;
  1242. }
  1243. if( x < y )
  1244. {
  1245. printf( "x < y" );
  1246. ans = -1.0;
  1247. }
  1248. if( x > y )
  1249. {
  1250. printf( "x > y" );
  1251. ans = 1.0;
  1252. }
  1253. return( ans );
  1254. }
  1255. long double zstdtrl(k,t)
  1256. long double k, t;
  1257. {
  1258. int ki;
  1259. long double y;
  1260. ki = k;
  1261. y = stdtrl(ki,t);
  1262. return(y);
  1263. }
  1264. long double zstdtril(k,t)
  1265. long double k, t;
  1266. {
  1267. int ki;
  1268. long double y;
  1269. ki = k;
  1270. y = stdtril(ki,t);
  1271. return(y);
  1272. }
  1273. #ifdef NANS
  1274. long double zisnan(x)
  1275. long double x;
  1276. {
  1277. long double y;
  1278. int k;
  1279. k = isnanl(x);
  1280. y = k;
  1281. return(y);
  1282. }
  1283. long double zisfinite(x)
  1284. long double x;
  1285. {
  1286. long double y;
  1287. int k;
  1288. k = isfinitel(x);
  1289. y = k;
  1290. return(y);
  1291. }
  1292. long double zsignbit(x)
  1293. long double x;
  1294. {
  1295. long double y;
  1296. int k;
  1297. k = signbitl(x);
  1298. y = k;
  1299. return(y);
  1300. }
  1301. #endif