dcalc.c 27 KB

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