home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / calc / part04 < prev    next >
Encoding:
Text File  |  1992-05-09  |  50.0 KB  |  1,523 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  3. Subject: v26i030: CALC - An arbitrary precision C-like calculator, Part04/21
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  8. Posting-Number: Volume 26, Issue 30
  9. Archive-Name: calc/part04
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 4 (of 21)."
  18. # Contents:  addop.c help/file help/overview help/statement
  19. #   lib/lucas_tbl.cal symbol.c
  20. # Wrapped by dbell@elm on Tue Feb 25 15:20:58 1992
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'addop.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'addop.c'\"
  24. else
  25. echo shar: Extracting \"'addop.c'\" \(9489 characters\)
  26. sed "s/^X//" >'addop.c' <<'END_OF_FILE'
  27. X/*
  28. X * Copyright (c) 1992 David I. Bell
  29. X * Permission is granted to use, distribute, or modify this source,
  30. X * provided that this copyright notice remains intact.
  31. X *
  32. X * Add opcodes to a function being compiled.
  33. X */
  34. X
  35. X#include "calc.h"
  36. X#include "opcodes.h"
  37. X#include "string.h"
  38. X#include "func.h"
  39. X#include "token.h"
  40. X#include "label.h"
  41. X#include "symbol.h"
  42. X
  43. X
  44. X#define    FUNCALLOCSIZE    20    /* reallocate size for functions */
  45. X#define    OPCODEALLOCSIZE    100    /* reallocate size for opcodes in functions */
  46. X
  47. X
  48. Xstatic long maxopcodes;        /* number of opcodes available */
  49. Xstatic long newindex;        /* index of new function */
  50. Xstatic long oldop;        /* previous opcode */
  51. Xstatic long debugline;        /* line number of latest debug opcode */
  52. Xstatic long funccount;        /* number of functions */
  53. Xstatic long funcavail;        /* available number of functions */
  54. Xstatic FUNC *functemplate;    /* function definition template */
  55. Xstatic FUNC **functions;    /* table of functions */
  56. Xstatic STRINGHEAD funcnames;    /* function names */
  57. Xstatic int codeflag;
  58. X
  59. XNUMBER *constvalue();
  60. X
  61. X
  62. X/*
  63. X * Initialize the table of user defined functions.
  64. X */
  65. Xvoid
  66. Xinitfunctions()
  67. X{
  68. X    initstr(&funcnames);
  69. X    maxopcodes = OPCODEALLOCSIZE;
  70. X    functemplate = (FUNC *) malloc(funcsize(maxopcodes));
  71. X    if (functemplate == NULL)
  72. X        error("Cannot allocate function template");
  73. X    functions = (FUNC **) malloc(sizeof(FUNC *) * FUNCALLOCSIZE);
  74. X    if (functions == NULL)
  75. X        error("Cannot allocate function table");
  76. X    funccount = 0;
  77. X    funcavail = FUNCALLOCSIZE;
  78. X}
  79. X
  80. X
  81. X/*
  82. X * Show the list of user defined functions.
  83. X */
  84. Xvoid
  85. Xshowfunctions()
  86. X{
  87. X    FUNC **fpp;        /* pointer into function table */
  88. X    FUNC *fp;        /* current function */
  89. X
  90. X    if (funccount == 0) {
  91. X        printf("No user functions defined.\n");
  92. X        return;
  93. X    }
  94. X    printf("Name Arguments\n");
  95. X    printf("---- ---------\n");
  96. X    for (fpp = &functions[funccount - 1]; fpp >= functions; fpp--) {
  97. X        fp = *fpp;
  98. X        if (fp == NULL)
  99. X            continue;
  100. X        printf("%-12s %-2d\n", fp->f_name, fp->f_paramcount);
  101. X    }
  102. X    printf("\n");
  103. X}
  104. X
  105. X
  106. X/*
  107. X * Initialize a function for definition.
  108. X * Newflag is TRUE if we should allocate a new function structure,
  109. X * instead of the usual overwriting of the template function structure.
  110. X * The new structure is returned in the global curfunc variable.
  111. X */
  112. Xvoid
  113. Xbeginfunc(name, newflag)
  114. X    char *name;            /* name of function */
  115. X    BOOL newflag;            /* TRUE if need new structure */
  116. X{
  117. X    register FUNC *fp;        /* current function */
  118. X
  119. X    newindex = adduserfunc(name);
  120. X    maxopcodes = OPCODEALLOCSIZE;
  121. X    fp = functemplate;
  122. X    if (newflag) {
  123. X        fp = (FUNC *) malloc(funcsize(maxopcodes));
  124. X        if (fp == NULL)
  125. X            error("Cannot allocate temporary function");
  126. X    }
  127. X    fp->f_next = NULL;
  128. X    fp->f_localcount = 0;
  129. X    fp->f_opcodecount = 0;
  130. X    fp->f_savedvalue.v_type = V_NULL;
  131. X    fp->f_name = namestr(&funcnames, newindex);
  132. X    curfunc = fp;
  133. X    initlocals();
  134. X    initlabels();
  135. X    oldop = OP_NOP;
  136. X    debugline = 0;
  137. X    errorcount = 0;
  138. X}
  139. X
  140. X
  141. X/*
  142. X * Commit the just defined function for use.
  143. X * This replaces any existing definition for the function.
  144. X * This should only be called for normal user-defined functions.
  145. X */
  146. Xvoid
  147. Xendfunc()
  148. X{
  149. X    register FUNC *fp;        /* function just finished */
  150. X    long size;            /* size of just created function */
  151. X
  152. X    checklabels();
  153. X    if (errorcount) {
  154. X        printf("\"%s\": %ld error%s\n", curfunc->f_name, errorcount,
  155. X            ((errorcount == 1) ? "" : "s"));
  156. X        return;
  157. X    }
  158. X    size = funcsize(curfunc->f_opcodecount);
  159. X    fp = (FUNC *) malloc(size);
  160. X    if (fp == NULL)
  161. X        error("Cannot commit function");
  162. X    memcpy((char *) fp, (char *) curfunc, size);
  163. X    if (curfunc != functemplate)
  164. X        free(curfunc);
  165. X    if (codeflag) {
  166. X        for (size = 0; size < fp->f_opcodecount; ) {
  167. X            printf("%ld: ", (long)size);
  168. X            size += dumpop(&fp->f_opcodes[size]);
  169. X        }
  170. X    }
  171. X    if (functions[newindex])
  172. X        free(functions[newindex]);
  173. X    functions[newindex] = fp;
  174. X    objuncache();
  175. X    if (inputisterminal())
  176. X        printf("\"%s\" defined\n", fp->f_name);
  177. X}
  178. X
  179. X
  180. X/*
  181. X * Find the user function with the specified name, and return its index.
  182. X * If the function does not exist, its name is added to the function table
  183. X * and an error will be generated when it is called if it is still undefined.
  184. X */
  185. Xlong
  186. Xadduserfunc(name)
  187. X    char *name;        /* name of function */
  188. X{
  189. X    long index;        /* index of function */
  190. X
  191. X    index = findstr(&funcnames, name);
  192. X    if (index >= 0)
  193. X        return index;
  194. X    if (funccount >= funcavail) {
  195. X        functions = (FUNC **) realloc(functions,
  196. X            sizeof(FUNC *) * (funcavail + FUNCALLOCSIZE));
  197. X        if (functions == NULL)
  198. X            error("Failed to reallocate function table");
  199. X        funcavail += FUNCALLOCSIZE;
  200. X    }
  201. X    if (addstr(&funcnames, name) == NULL)
  202. X        error("Cannot save function name");
  203. X    index = funccount++;
  204. X    functions[index] = NULL;
  205. X    return index;
  206. X}
  207. X
  208. X
  209. X/*
  210. X * Clear any optimization that may be done for the next opcode.
  211. X * This is used when defining a label.
  212. X */
  213. Xvoid
  214. Xclearopt()
  215. X{
  216. X    oldop = OP_NOP;
  217. X    debugline = 0;
  218. X}
  219. X
  220. X
  221. X/*
  222. X * Find a function structure given its index.
  223. X */
  224. XFUNC *
  225. Xfindfunc(index)
  226. X    long index;
  227. X{
  228. X    if ((unsigned long) index >= funccount)
  229. X        error("Undefined function");
  230. X    return functions[index];
  231. X}
  232. X
  233. X
  234. X/*
  235. X * Return the name of a function given its index.
  236. X */
  237. Xchar *
  238. Xnamefunc(index)
  239. X    long index;
  240. X{
  241. X    return namestr(&funcnames, index);
  242. X}
  243. X
  244. X
  245. X/*
  246. X * Add an opcode to the current function being compiled.
  247. X * Note: This can change the curfunc global variable when the
  248. X * function needs expanding.
  249. X */
  250. Xvoid
  251. Xaddop(op)
  252. X    long op;
  253. X{
  254. X    register FUNC *fp;        /* current function */
  255. X    NUMBER *q;
  256. X
  257. X    fp = curfunc;
  258. X    if ((fp->f_opcodecount + 5) >= maxopcodes) {
  259. X        maxopcodes += OPCODEALLOCSIZE;
  260. X        fp = (FUNC *) malloc(funcsize(maxopcodes));
  261. X        if (fp == NULL)
  262. X            error("cannot reallocate function");
  263. X        memcpy((char *) fp, (char *) curfunc,
  264. X            funcsize(curfunc->f_opcodecount));
  265. X        if (curfunc != functemplate)
  266. X            free(curfunc);
  267. X        curfunc = fp;
  268. X    }
  269. X    /*
  270. X     * Check the current opcode against the previous opcode and try to
  271. X     * slightly optimize the code depending on the various combinations.
  272. X     */
  273. X    if (op == OP_GETVALUE) {
  274. X        switch (oldop) {
  275. X
  276. X        case OP_NUMBER: case OP_ZERO: case OP_ONE: case OP_IMAGINARY:
  277. X        case OP_GETEPSILON: case OP_SETEPSILON: case OP_STRING:
  278. X        case OP_UNDEF: case OP_GETCONFIG: case OP_SETCONFIG:
  279. X            return;
  280. X        case OP_DUPLICATE:
  281. X            fp->f_opcodes[fp->f_opcodecount - 1] = OP_DUPVALUE;
  282. X            oldop = OP_DUPVALUE;
  283. X            return;
  284. X        case OP_INDEXADDR:
  285. X            fp->f_opcodes[fp->f_opcodecount - 2] = OP_INDEXVALUE;
  286. X            oldop = OP_INDEXVALUE;
  287. X            return;
  288. X        case OP_FIADDR:
  289. X            fp->f_opcodes[fp->f_opcodecount - 1] = OP_FIVALUE;
  290. X            oldop = OP_FIVALUE;
  291. X            return;
  292. X        case OP_GLOBALADDR:
  293. X            fp->f_opcodes[fp->f_opcodecount - 2] = OP_GLOBALVALUE;
  294. X            oldop = OP_GLOBALVALUE;
  295. X            return;
  296. X        case OP_LOCALADDR:
  297. X            fp->f_opcodes[fp->f_opcodecount - 2] = OP_LOCALVALUE;
  298. X            oldop = OP_LOCALVALUE;
  299. X            return;
  300. X        case OP_PARAMADDR:
  301. X            fp->f_opcodes[fp->f_opcodecount - 2] = OP_PARAMVALUE;
  302. X            oldop = OP_PARAMVALUE;
  303. X            return;
  304. X        case OP_ELEMADDR:
  305. X            fp->f_opcodes[fp->f_opcodecount - 2] = OP_ELEMVALUE;
  306. X            oldop = OP_ELEMVALUE;
  307. X            return;
  308. X        }
  309. X    }
  310. X    if ((op == OP_NEGATE) && (oldop == OP_NUMBER)) {
  311. X        q = constvalue(fp->f_opcodes[fp->f_opcodecount - 1]);
  312. X        fp->f_opcodes[fp->f_opcodecount - 1] = addqconstant(qneg(q));
  313. X        oldop = OP_NUMBER;
  314. X        return;
  315. X    }
  316. X    if ((op == OP_POWER) && (oldop == OP_NUMBER)) {
  317. X        if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 2L) == 0) {
  318. X            fp->f_opcodecount--;
  319. X            fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE;
  320. X            oldop = OP_SQUARE;
  321. X            return;
  322. X        }
  323. X        if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 4L) == 0) {
  324. X            fp->f_opcodes[fp->f_opcodecount - 2] = OP_SQUARE;
  325. X            fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE;
  326. X            oldop = OP_SQUARE;
  327. X            return;
  328. X        }
  329. X    }
  330. X    if ((op == OP_POP) && (oldop == OP_ASSIGN)) {    /* optimize */
  331. X        fp->f_opcodes[fp->f_opcodecount - 1] = OP_ASSIGNPOP;
  332. X        oldop = OP_ASSIGNPOP;
  333. X        return;
  334. X    }
  335. X    /*
  336. X     * No optimization possible, so store the opcode.
  337. X     */
  338. X    fp->f_opcodes[fp->f_opcodecount] = op;
  339. X    fp->f_opcodecount++;
  340. X    oldop = op;
  341. X}
  342. X
  343. X
  344. X/*
  345. X * Add an opcode and an index to the current function being compiled.
  346. X */
  347. Xvoid
  348. Xaddopindex(op, index)
  349. X    long op;
  350. X    long index;
  351. X{
  352. X    NUMBER *q;
  353. X
  354. X    switch (op) {
  355. X    case OP_NUMBER:
  356. X        q = constvalue(index);
  357. X        if (qiszero(q)) {
  358. X            addop(OP_ZERO);
  359. X            return;
  360. X        }
  361. X        if (qisone(q)) {
  362. X            addop(OP_ONE);
  363. X            return;
  364. X        }
  365. X        break;
  366. X
  367. X    case OP_DEBUG:
  368. X        if ((traceflags & TRACE_NODEBUG) || (index == debugline))
  369. X            return;
  370. X        debugline = index;
  371. X        if (oldop == OP_DEBUG) {
  372. X            curfunc->f_opcodes[curfunc->f_opcodecount - 1] = index;
  373. X            return;
  374. X        }
  375. X        break;
  376. X    }
  377. X    addop(op);
  378. X    curfunc->f_opcodes[curfunc->f_opcodecount] = index;
  379. X    curfunc->f_opcodecount++;
  380. X}
  381. X
  382. X
  383. X/*
  384. X * Add an opcode and a character pointer to the function being compiled.
  385. X */
  386. Xvoid
  387. Xaddopptr(op, ptr)
  388. X    long op;
  389. X    char *ptr;
  390. X{
  391. X    char **ptraddr;
  392. X
  393. X    addop(op);
  394. X    ptraddr = (char **) &curfunc->f_opcodes[curfunc->f_opcodecount];
  395. X    *ptraddr = ptr;
  396. X    curfunc->f_opcodecount += PTR_SIZE;
  397. X}
  398. X
  399. X
  400. X/*
  401. X * Add an opcode and an index and an argument count for a function call.
  402. X */
  403. Xvoid
  404. Xaddopfunction(op, index, count)
  405. X    long op;
  406. X    long index;
  407. X{
  408. X    long newop;
  409. X
  410. X    if ((op == OP_CALL) && ((newop = builtinopcode(index)) != OP_NOP)) {
  411. X        if ((newop == OP_SETCONFIG) && (count == 1))
  412. X            newop = OP_GETCONFIG;
  413. X        if ((newop == OP_SETEPSILON) && (count == 0))
  414. X            newop = OP_GETEPSILON;
  415. X        if ((newop == OP_ABS) && (count == 1))
  416. X            addop(OP_GETEPSILON);
  417. X        addop(newop);
  418. X        return;
  419. X    }
  420. X    addop(op);
  421. X    curfunc->f_opcodes[curfunc->f_opcodecount++] = index;
  422. X    curfunc->f_opcodes[curfunc->f_opcodecount++] = count;
  423. X}
  424. X
  425. X
  426. X/*
  427. X * Add a jump-type opcode and a label to the function being compiled.
  428. X */
  429. Xvoid
  430. Xaddoplabel(op, label)
  431. X    long op;
  432. X    LABEL *label;        /* label to be added */
  433. X{
  434. X    addop(op);
  435. X    uselabel(label);
  436. X}
  437. X
  438. X/* END CODE */
  439. END_OF_FILE
  440. if test 9489 -ne `wc -c <'addop.c'`; then
  441.     echo shar: \"'addop.c'\" unpacked with wrong size!
  442. fi
  443. # end of 'addop.c'
  444. fi
  445. if test -f 'help/file' -a "${1}" != "-c" ; then 
  446.   echo shar: Will not clobber existing file \"'help/file'\"
  447. else
  448. echo shar: Extracting \"'help/file'\" \(7229 characters\)
  449. sed "s/^X//" >'help/file' <<'END_OF_FILE'
  450. XUsing files
  451. X
  452. X    The calculator provides some functions which allow the program to
  453. X    read or write text files.  These functions use stdio internally,
  454. X    and the functions appear similar to some of the stdio functions.
  455. X    Some differences do occur, as will be explained here.
  456. X
  457. X    Names of files are subject to ~ expansion just like the C or
  458. X    Korn shell.  For example, the file name:
  459. X
  460. X        ~/.rc.cal
  461. X    
  462. X    refers to the file '.rc.cal' under your home directory.  The
  463. X    file name:
  464. X
  465. X        ~chongo/.rc.cal
  466. X
  467. X    refers to the a file 'rc.cal' under the home directory of 'chongo'.
  468. X
  469. X    A file can be opened for either reading, writing, or appending.
  470. X    To do this, the 'fopen' function is used, which accepts a filename
  471. X    and an open mode, both as strings.  You use 'r' for reading, 'w'
  472. X    for writing, and 'a' for appending.  For example, to open the file
  473. X    'foo' for reading, the following could be used:
  474. X
  475. X        fd = fopen('foo', 'r');
  476. X
  477. X    If the open is unsuccessful, the numeric value of errno is returned.
  478. X    If the open is successful, a value of type 'file' will be returned.
  479. X    You can use the 'isfile' function to test the return value to see
  480. X    if the open succeeded.  You should assign the return value of fopen
  481. X    to a variable for later use.  File values can be copied to more than
  482. X    one variable, and using any of the variables with the same file value
  483. X    will produce the same results.
  484. X
  485. X    If you overwrite a variable containing a file value or don't save the
  486. X    result of an 'fopen', the opened file still remains open.  Such 'lost'
  487. X    files can be recovered by using the 'files' function.  This function
  488. X    either takes no arguments or else takes one integer argument.  If no
  489. X    arguments are given, then 'files' returns the maximum number of opened
  490. X    files.  If an argument is given, then the 'files' function uses it as
  491. X    an index into an internal table of open files, and returns a value
  492. X    referring to one the open files.  If that entry in the table is not
  493. X    in use, then the null value is returned instead.  Index 0 always
  494. X    refers to standard input, index 1 always refers to standard output,
  495. X    and index 2 always refers to standard error.  These three files are
  496. X    already open by the calculator and cannot be closed.  As an example
  497. X    of using 'files', if you wanted to assign a file value which is
  498. X    equivalent to stdout, you could use:
  499. X
  500. X        stdout = files(1);
  501. X
  502. X    The 'fclose' function is used to close a file which had been opened.
  503. X    When this is done, the file value associated with the file remains
  504. X    a file value, but appears 'closed', and cannot be used in further
  505. X    file-related calls (except fclose) without causing errors.  This same
  506. X    action occurs to all copies of the file value.  You do not need to
  507. X    explicitly close all the copies of a file value.  The 'fclose'
  508. X    function returns the numeric value of errno if there had been an
  509. X    error using the file, or the null value if there was no error.
  510. X
  511. X    File values can be printed.  When this is done, the filename of the
  512. X    opened file is printed inside of quote marks.  If the file value had
  513. X    been closed, then the null string is printed.  If a file value is the
  514. X    result of a top-level expression, then in addition to the filename,
  515. X    the open mode, file position, and possible EOF, error, and closed
  516. X    status is also displayed.
  517. X
  518. X    File values can be used inside of 'if' tests.  When this is done,
  519. X    an opened file is TRUE, and a closed file is FALSE.  As an example
  520. X    of this, the following loop will print the names of all the currently
  521. X    opened non-standard files with their indexes, and then close them:
  522. X
  523. X        for (i = 3; i < files(); i++) {
  524. X            if (files(i)) {
  525. X                print i, files(i);
  526. X                fclose(files(i));
  527. X            }
  528. X        }
  529. X
  530. X    The functions to read from files are 'fgetline' and 'fgetc'.
  531. X    The 'fgetline' function accepts a file value, and returns the next
  532. X    input line from a file.  The line is returned as a string value, and
  533. X    does not contain the end of line character.  Empty lines return the
  534. X    null string.  When the end of file is reached, fgetline returns the
  535. X    null value.  (Note the distinction between a null string and a null
  536. X    value.)  If the line contained a numeric value, then the 'eval'
  537. X    function can then be used to convert the string to a numeric value.
  538. X    Care should be used when doing this, however, since eval will
  539. X    generate an error if the string doesn't represent a valid expression.
  540. X    The 'fgetc' function returns the next character from a file as a
  541. X    single character string.  It returns the null value when end of file
  542. X    is reached.
  543. X
  544. X    The 'printf' and 'fprintf' functions are used to print results to a
  545. X    file (which could be stdout or stderr).  The 'fprintf' function
  546. X    accepts a file variable, whereas the 'printf' function assumes the
  547. X    use of 'files(1)' (stdout).  They both require a format string, which
  548. X    is used in almost the same way as in normal C.  The differences come
  549. X    in the interpretation of values to be printed for various formats.
  550. X    Unlike in C, where an unmatched format type and value will cause
  551. X    problems, in the calculator nothing bad will happen.  This is because
  552. X    the calculator knows the types of all values, and will handle them
  553. X    all reasonably.  What this means is that you can (for example), always
  554. X    use %s or %d in your format strings, even if you are printing a non-
  555. X    string or non-numeric value.  For example, the following is valid:
  556. X
  557. X        printf("Two values are %d and %s\n", "fred", 4567);
  558. X
  559. X    and will print "Two values are fred and 4567".
  560. X
  561. X    Using particular format characters, however, is still useful if
  562. X    you wish to use width or precision arguments in the format, or if
  563. X    you wish to print numbers in a particular format.  The following
  564. X    is a list of the possible numeric formats:
  565. X
  566. X        %d        print in currently defined numeric format
  567. X        %f        print as floating point
  568. X        %e        print as exponential
  569. X        %r        print as decimal fractions
  570. X        %x        print as hex fractions
  571. X        %o        print as octal fractions
  572. X        %b        print as binary fractions
  573. X
  574. X    Note then, that using %d in the format makes the output configurable
  575. X    by using the 'config' function to change the output mode, whereas
  576. X    the other formats override the mode and force the output to be in
  577. X    the specified format.
  578. X
  579. X    Using the precision argument will override the 'config' function
  580. X    to set the number of decimal places printed.  For example:
  581. X
  582. X        printf("The number is %.100f\n", 1/3);
  583. X
  584. X    will print 100 decimal places no matter what the display configuration
  585. X    value is set to.
  586. X
  587. X    The %s and %c formats are identical, and will print out the string
  588. X    representation of the value.  In these cases, the precision argument
  589. X    will truncate the output the same way as in standard C.
  590. X
  591. X    If a matrix or list is printed, then the output mode and precision
  592. X    affects the printing of each individual element.  However, field
  593. X    widths are ignored since these values print using multiple lines.
  594. X    Field widths are also ignored if an object value prints on multiple
  595. X    lines.
  596. X
  597. X    The final file-related functions are 'fflush', 'ferror', and 'feof'.
  598. X    The 'fflush' function forces buffered output to a file.  The 'ferror'
  599. X    function returns nonzero if an error had occurred to a file.  The
  600. X    'feof' function returns nonzero if end of file has been reached
  601. X    while reading a file.
  602. X
  603. X    The 'strprintf' function formats output similarly to 'printf',
  604. X    but the output is returned as a string value instead of being
  605. X    printed.
  606. END_OF_FILE
  607. if test 7229 -ne `wc -c <'help/file'`; then
  608.     echo shar: \"'help/file'\" unpacked with wrong size!
  609. fi
  610. # end of 'help/file'
  611. fi
  612. if test -f 'help/overview' -a "${1}" != "-c" ; then 
  613.   echo shar: Will not clobber existing file \"'help/overview'\"
  614. else
  615. echo shar: Extracting \"'help/overview'\" \(6768 characters\)
  616. sed "s/^X//" >'help/overview' <<'END_OF_FILE'
  617. X            CALC - An arbitrary precision calculator.
  618. X                by David I. Bell
  619. X
  620. X
  621. X    This is a calculator program with arbitrary precision arithmetic.
  622. X    All numbers are represented as fractions with arbitrarily large
  623. X    numerators and denominators which are always reduced to lowest terms.
  624. X    Real or exponential format numbers can be input and are converted
  625. X    to the equivalent fraction.  Hex, binary, or octal numbers can be
  626. X    input by using numbers with leading '0x', '0b' or '0' characters.
  627. X    Complex numbers can be input using a trailing 'i', as in '2+3i'.
  628. X    Strings and characters are input by using single or double quotes.
  629. X
  630. X    Commands are statements in a C-like language, where each input
  631. X    line is treated as the body of a procedure.  Thus the command
  632. X    line can contain variable declarations, expressions, labels,
  633. X    conditional tests, and loops.  Assignments to any variable name
  634. X    will automatically define that name as a global variable.  The
  635. X    other important thing to know is that all non-assignment expressions
  636. X    which are evaluated are automatically printed.  Thus, you can evaluate 
  637. X    an expression's value by simply typing it in.
  638. X
  639. X    Many useful built-in mathematical functions are available.  Use
  640. X    the 'show builtins' command to list them.  You can also define
  641. X    your own functions by using the 'define' keyword, followed by a
  642. X    function declaration very similar to C.  Functions which only
  643. X    need to return a simple expression can be defined using an
  644. X    equals sign, as in the example 'define sc(a,b) = a^3 + b^3'.
  645. X    Variables in functions can be defined as either 'global' or
  646. X    'local'.  Global variables are common to all functions and the
  647. X    command line, whereas local variables are unique to each
  648. X    function level, and are destroyed when the function returns.
  649. X    Variables are not typed at definition time, but dynamically
  650. X    change as they are used.  So you must supply the correct type
  651. X    of variable to those functions and operators which only work
  652. X    for a subset of types.
  653. X
  654. X    By default, arguments to functions are passed by value (even
  655. X    matrices).  For speed, you can put an ampersand before any
  656. X    variable argument in a function call, and that variable will be
  657. X    passed by reference instead.  However, if the function changes
  658. X    its argument, the variable will change.  Arguments to built-in
  659. X    functions and object manipulation functions are always called
  660. X    by reference.  If a user-defined function takes more arguments
  661. X    than are passed, the undefined arguments have the null value.
  662. X    The 'param' function returns function arguments by argument
  663. X    number, and also returns the number of arguments passed.  Thus
  664. X    functions can be written to handle an arbitrary number of
  665. X    arguments.
  666. X
  667. X    The mat statement is used to create a matrix.  It takes a
  668. X    variable name, followed by the bounds of the matrix in square
  669. X    brackets.  The lower bounds are zero by default, but colons can
  670. X    be used to change them.  For example 'mat foo[3, 1:10]' defines
  671. X    a two dimensional matrix, with the first index ranging from 0
  672. X    to 3, and the second index ranging from 1 to 10.  The bounds of
  673. X    a matrix can be an expression calculated at runtime.
  674. X
  675. X    Lists of values are created using the 'list' function, and values can
  676. X    be inserted or removed from either the front or the end of the list.
  677. X    List elements can be indexed directly using double square brackets.
  678. X
  679. X    The obj statement is used to create an object.  Objects are
  680. X    user-defined values for which user-defined routines are
  681. X    implicitly called to perform simple actions such as add,
  682. X    multiply, compare, and print. Objects types are defined as in
  683. X    the example 'obj complex {real, imag}', where 'complex' is the
  684. X    name of the object type, and 'real' and 'imag' are element
  685. X    names used to define the value of the object (very much like
  686. X    structures).  Variables of an object type are created as in the
  687. X    example 'obj complex x,y', where 'x' and 'y' are variables.
  688. X    The elements of an object are referenced using a dot, as in the
  689. X    example 'x.real'. All user-defined routines have names composed
  690. X    of the object type and the action to perform separated by an
  691. X    underscore, as in the example 'complex_add'.  The command 'show
  692. X    objfuncs' lists all the definable routines.  Object routines
  693. X    which accept two arguments should be prepared to handle cases
  694. X    in which either one of the arguments is not of the expected
  695. X    object type.
  696. X
  697. X    These are the differences between the normal C operators and
  698. X    the ones defined by the calculator.  The '/' operator divides
  699. X    fractions, so that '7 / 2' evaluates to 7/2. The '//' operator
  700. X    is an integer divide, so that '7 // 2' evaluates to 3.  The '^'
  701. X    operator is a integral power function, so that 3^4 evaluates to
  702. X    81.  Matrices of any dimension can be treated as a zero based
  703. X    linear array using double square brackets, as in 'foo[[3]]'.
  704. X    Matrices can be indexed by using commas between the indices, as
  705. X    in foo[3,4].  Object and list elements can be referenced by
  706. X    using double square brackets.
  707. X
  708. X    The print statement is used to print values of expressions.
  709. X    Separating values by a comma puts one space between the output
  710. X    values, whereas separating values by a colon concatenates the
  711. X    output values.  A trailing colon suppresses printing of the end
  712. X    of line.  An example of printing is 'print \"The square of\",
  713. X    x, \"is\", x^2\'.
  714. X
  715. X    The 'config' function is used to modify certain parameters that
  716. X    affect calculations or the display of values.  For example, the
  717. X    output display mode can be set using 'config(\"mode\", type)',
  718. X    where 'type' is one of 'frac', 'int', 'real', 'exp', 'hex',
  719. X    'oct', or 'bin'.  The default output mode is real.  For the
  720. X    integer, real, or exponential formats, a leading '~' indicates
  721. X    that the number was truncated to the number of decimal places
  722. X    specified by the default precision.  If the '~' does not
  723. X    appear, then the displayed number is the exact value.
  724. X
  725. X    The number of decimal places printed is set by using
  726. X    'config(\"display\", n)'.  The default precision for
  727. X    real-valued functions can be set by using 'epsilon(x)', where x
  728. X    is the required precision (such as 1e-50).
  729. X
  730. X    There is a command stack feature so that you can easily
  731. X    re-execute previous commands and expressions from the terminal.
  732. X    Each command is labeled with a two digit number. To execute a
  733. X    command again, type '`n', where n is the number for the command
  734. X    to be executed.  Using '`-n' re-execute the command which is
  735. X    the n'th command back.  Using '``' re-executes the previous
  736. X    command, and is a shortcut for typing '`-1'.  The '`h n'
  737. X    command just displays the previous n commands (20 if n is not
  738. X    given).
  739. X
  740. X    Files can be read in by using the 'read filename' command.
  741. X    These can contain both functions to be defined, and expressions
  742. X    to be calculated.  Global variables which are numbers can be
  743. X    saved to a file by using the 'write filename' command.
  744. END_OF_FILE
  745. if test 6768 -ne `wc -c <'help/overview'`; then
  746.     echo shar: \"'help/overview'\" unpacked with wrong size!
  747. fi
  748. # end of 'help/overview'
  749. fi
  750. if test -f 'help/statement' -a "${1}" != "-c" ; then 
  751.   echo shar: Will not clobber existing file \"'help/statement'\"
  752. else
  753. echo shar: Extracting \"'help/statement'\" \(8631 characters\)
  754. sed "s/^X//" >'help/statement' <<'END_OF_FILE'
  755. XStatements
  756. X
  757. X    Statements are very much like C statements.  Most statements act
  758. X    identically to those in C, but there are minor differences and
  759. X    some additions.  The following is a list of the statement types,
  760. X    with explanation of the non-C statements.  In this list, upper
  761. X    case words identify the keywords which are actually in lower case.
  762. X    Statements are generally terminated with semicolons, except if the
  763. X    statement is the compound one formed by matching braces.  Various
  764. X    expressions are optional and may be omitted (as in RETURN).
  765. X
  766. X
  767. X    NOTE: Calc commands are in lower case.   UPPER case is used below
  768. X          for emphasis only, and should be considered in lower case.
  769. X
  770. X
  771. X    IF (expr) statement
  772. X    IF (expr) statement ELSE statement
  773. X    FOR (optionalexpr ; optionalexpr ; optionalexpr) statement
  774. X    WHILE (expr) statement
  775. X    DO statement WHILE (expr)
  776. X    CONTINUE
  777. X    BREAK
  778. X    GOTO label
  779. X        These all work like in normal C.
  780. X
  781. X    RETURN optionalexpr
  782. X        This returns a value from a function.  Functions always
  783. X        have a return value, even if this statement is not used.
  784. X        If no return statement is executed, or if no expression
  785. X        is specified in the return statement, then the return
  786. X        value from the function is the null type.
  787. X
  788. X    SWITCH (expr) { caseclauses }
  789. X        Switch statements work similarly to C, except for the
  790. X        following.  A switch can be done on any type of value,
  791. X        and the case statements can be of any type of values.
  792. X        The case statements can also be expressions calculated
  793. X        at runtime.  The calculator compares the switch value
  794. X        with each case statement in the order specified, and
  795. X        selects the first case which matches.  The default case
  796. X        is the exception, and only matches once all other cases
  797. X        have been tested.
  798. X
  799. X    { statements }
  800. X        This is a normal list of statements, each one ended by
  801. X        a semicolon.  Unlike the C language, no declarations are
  802. X        permitted within an inner-level compound statement.
  803. X        Declarations are only permitted at the beginning of a
  804. X        function definition, or at the beginning of an expression
  805. X        sequence.
  806. X
  807. X    MAT variable [dimension] [dimension] ...
  808. X    MAT variable [dimension, dimension, ...]
  809. X
  810. X        This creates a matrix variable with the specified dimensions.
  811. X        Matrices can have from 1 to 4 dimensions.  When specifying
  812. X        multiple dimensions, you can use either the standard C syntax,
  813. X        or else you can use commas for separating the dimensions.
  814. X        For example, the following two statements are equivalent,
  815. X        and so will create the same two dimensional matrix:
  816. X
  817. X            mat foo[3][6];
  818. X            mat foo[3,6];
  819. X
  820. X        By default, each dimension is indexed starting at zero,
  821. X        as in normal C, and contains the specified number of
  822. X        elements.  However, this can be changed if a colon is
  823. X        used to separate two values.  If this is done, then the
  824. X        two values become the lower and upper bounds for indexing.
  825. X        This is convenient, for example, to create matrices whose
  826. X        first row and column begin at 1.  Examples of matrix
  827. X        definitions are:
  828. X
  829. X            mat x[3]    one dimension, bounds are 0-2
  830. X            mat foo[4][5]    two dimensions, bounds are 0-3 and 0-4
  831. X            mat a[-7:7]    one dimension, bounds are (-7)-7
  832. X            mat s[1:9,1:9]    two dimensions, bounds are 1-9 and 1-9
  833. X
  834. X        Note that the MAT statement is not a declaration, but is
  835. X        executed at runtime.  Within a function, the specified
  836. X        variable must already be defined, and is just converted to
  837. X        a matrix of the specified size, and all elements are set
  838. X        to the value of zero.  For convenience, at the top level
  839. X        command level, the MAT command automatically defines a
  840. X        global variable of the specified name if necessary.
  841. X
  842. X        Since the MAT statement is executed, the bounds on the
  843. X        matrix can be full expressions, and so matrices can be
  844. X        dynamically allocated.  For example:
  845. X
  846. X            size = 20;
  847. X            mat data[size*2];
  848. X
  849. X        allocates a matrix which can be indexed from 0 to 39.
  850. X
  851. X    OBJ type { elementnames } optionalvariables
  852. X    OBJ type variables
  853. X
  854. X        These create a new object type, or create one or more
  855. X        variables of the specified type.  For this calculator,
  856. X        an object is just a structure which is implicitly acted
  857. X        on by user defined routines.  The user defined routines
  858. X        implement common operations for the object, such as plus
  859. X        and minus, multiply and divide, comparison and printing.
  860. X        The calculator will automatically call these routines in
  861. X        order to perform many operations.
  862. X    
  863. X        To create an object type, the data elements used in
  864. X        implementing the object are specified within a pair
  865. X        of braces, separated with commas.  For example, to
  866. X        define an object will will represent points in 3-space,
  867. X        whose elements are the three coordinate values, the
  868. X        following could be used:
  869. X    
  870. X            obj point {x, y, z};
  871. X    
  872. X        This defines an object type called point, whose elements
  873. X        have the names x, y, and z.  The elements are accessed
  874. X        similarly to structure element accesses, by using a period.
  875. X        For example, given a variable 'v' which is a point object,
  876. X        the three coordinates of the point can be referenced by:
  877. X
  878. X            v.x
  879. X            v.y
  880. X            v.z
  881. X
  882. X        A particular object type can only be defined once, and
  883. X        is global throughout all functions.  However, different
  884. X        object types can be used at the same time.
  885. X
  886. X        In order to create variables of an object type, they
  887. X        can either be named after the right brace of the object
  888. X        creation statement, or else can be defined later with
  889. X        another obj statement.  To create two points using the
  890. X        second (and most common) method, the following is used:
  891. X
  892. X            obj point p1, p2;    
  893. X
  894. X        This statement is executed, and is not a declaration.
  895. X        Thus within a function, the variables p1 and p2 must have
  896. X        been previously defined, and are just changed to be the
  897. X        new object type.  For convenience, at the top level command
  898. X        level, object variables are automatically defined as being
  899. X        global when necessary.
  900. X
  901. X    EXIT string
  902. X    QUIT string
  903. X
  904. X        This command is used in two cases.  At the top command
  905. X        line level, quit will exit from the calculator.  This
  906. X        is the normal way to leave the calculator.  In any other
  907. X        use, quit will abort the current calculation as if an
  908. X        error had occurred.  If a string is given, then the string
  909. X        is printed as the reason for quitting, otherwise a general
  910. X        quit message is printed.  The routine name and line number
  911. X        which executed the quit is also printed in either case.
  912. X
  913. X        Quit is useful when a routine detects invalid arguments,
  914. X        in order to stop a calculation cleanly.  For example,
  915. X        for a square root routine, an error can be given if the
  916. X        supplied parameter was a negative number, as in:
  917. X
  918. X            define mysqrt(n)
  919. X            {
  920. X                if (n < 0)
  921. X                    quit "Negative argument";
  922. X                ...
  923. X            }
  924. X
  925. X        Exit is an alias for quit.
  926. X
  927. X
  928. X    PRINT exprs
  929. X
  930. X        For interactive expression evaluation, the values of all
  931. X        typed-in expressions are automatically displayed to the
  932. X        user.  However, within a function or loop, the printing of
  933. X        results must be done explicitly.  This can be done using
  934. X        the 'printf' or 'fprintf' functions, as in standard C, or
  935. X        else by using the built-in 'print' statement.  The advantage
  936. X        of the print statement is that a format string is not needed.
  937. X        Instead, the given values are simply printed with zero or one
  938. X        spaces between each value.
  939. X
  940. X        Print accepts a list of expressions, separated either by
  941. X        commas or colons.  Each expression is evaluated in order
  942. X        and printed, with no other output, except for the following
  943. X        special cases.  The comma which separates expressions prints
  944. X        a single space, and a newline is printed after the last
  945. X        expression unless the statement ends with a colon.  As
  946. X        examples:
  947. X
  948. X            print 3, 4;        prints "3 4" and newline.
  949. X            print 5:;        prints "5" with no newline.
  950. X            print 'a' : 'b' , 'c';    prints "ab c" and newline.
  951. X            print;            prints a newline.
  952. X
  953. X        For numeric values, the format of the number depends on the
  954. X        current "mode" configuration parameter.  The initial mode
  955. X        is to print real numbers, but it can be changed to other
  956. X        modes such as exponential, decimal fractions, or hex.
  957. X
  958. X        If a matrix or list is printed, then the elements contained
  959. X        within the matrix or list will also be printed, up to the
  960. X        maximum number specified by the "maxprint" configuration
  961. X        parameter.  If an element is also a matrix or a list, then
  962. X        their values are not recursively printed.  Objects are printed
  963. X        using their user-defined routine.  Printing a file value
  964. X        prints the name of the file that was opened.
  965. X
  966. X
  967. X    SHOW item
  968. X
  969. X        This command displays some information.
  970. X        The following is a list of the various items:
  971. X
  972. X            builtins    built in functions
  973. X            globals        global variables
  974. X            functions    user-defined functions
  975. X            objfuncs    possible object functions
  976. X            memory        memory usage
  977. X    
  978. X
  979. X    Also see the help topic:
  980. X
  981. X        command         top level commands
  982. END_OF_FILE
  983. if test 8631 -ne `wc -c <'help/statement'`; then
  984.     echo shar: \"'help/statement'\" unpacked with wrong size!
  985. fi
  986. # end of 'help/statement'
  987. fi
  988. if test -f 'lib/lucas_tbl.cal' -a "${1}" != "-c" ; then 
  989.   echo shar: Will not clobber existing file \"'lib/lucas_tbl.cal'\"
  990. else
  991. echo shar: Extracting \"'lib/lucas_tbl.cal'\" \(6758 characters\)
  992. sed "s/^X//" >'lib/lucas_tbl.cal' <<'END_OF_FILE'
  993. X/*
  994. X * Copyright (c) 1992 Landon Curt Noll
  995. X * Permission is granted to use, distribute, or modify this source,
  996. X * provided that this copyright notice remains intact.
  997. X *
  998. X * By: Landon Curt Noll
  999. X *     chongo@toad.com  -or-  ...!{pyramid,sun,uunet}!sun!hoptoad!chongo
  1000. X *
  1001. X *
  1002. X * Lucasian criteria for primality
  1003. X *
  1004. X * The following table is taken from:
  1005. X *
  1006. X *    "Lucasian Criteria for the Primality of N=h*2^n-1", by Hans Riesel,
  1007. X *    Mathematics of Computation, Vol 23 #108, p 872.
  1008. X *
  1009. X * The index of the *_val[] arrays correspond to the v(1) values found
  1010. X * in the table.  That is, for v(1) == x:
  1011. X *
  1012. X *    D == d_val[x]
  1013. X *    a == a_val[x]
  1014. X *    b == b_val[x]
  1015. X *    r == r_val[x]        (r == abs(a^2 - b^2*D))
  1016. X *
  1017. X *
  1018. X * Note that when *_val[i] is not a number, the related v(1) value
  1019. X * is not found in Table 1.
  1020. X */
  1021. X
  1022. Xtrymax = 100;
  1023. Xmat d_val[trymax+1];
  1024. Xmat a_val[trymax+1];
  1025. Xmat b_val[trymax+1];
  1026. Xmat r_val[trymax+1];
  1027. X/* v1= 0        INVALID */
  1028. X/* v1= 1        INVALID */
  1029. X/* v1= 2        INVALID */
  1030. Xd_val[ 3]=   5;  a_val[ 3]= 1;  b_val[ 3]=1;  r_val[ 3]=4;
  1031. Xd_val[ 4]=   3;  a_val[ 4]= 1;  b_val[ 4]=1;  r_val[ 4]=2;
  1032. Xd_val[ 5]=  21;  a_val[ 5]= 3;  b_val[ 5]=1;  r_val[ 5]=12;
  1033. Xd_val[ 6]=   2;  a_val[ 6]= 1;  b_val[ 6]=1;  r_val[ 6]=1;
  1034. X/* v1= 7        INVALID */
  1035. Xd_val[ 8]=  15;  a_val[ 8]= 3;  b_val[ 8]=1;  r_val[ 8]=6;
  1036. Xd_val[ 9]=  77;  a_val[ 9]= 7;  b_val[ 9]=1;  r_val[ 9]=28;
  1037. Xd_val[10]=   6;  a_val[10]= 2;  b_val[10]=1;  r_val[10]=2;
  1038. Xd_val[11]=  13;  a_val[11]= 3;  b_val[11]=1;  r_val[11]=4;
  1039. Xd_val[12]=  35;  a_val[12]= 5;  b_val[12]=1;  r_val[12]=10;
  1040. Xd_val[13]= 165;  a_val[13]=11;  b_val[13]=1;  r_val[13]=44;
  1041. X/* v1=14        INVALID */
  1042. Xd_val[15]= 221;  a_val[15]=13;  b_val[15]=1;  r_val[15]=52;
  1043. Xd_val[16]=   7;  a_val[16]= 3;  b_val[16]=1;  r_val[16]=2;
  1044. Xd_val[17]= 285;  a_val[17]=15;  b_val[17]=1;  r_val[17]=60;
  1045. X/* v1=18        INVALID */
  1046. Xd_val[19]= 357;  a_val[19]=17;  b_val[19]=1;  r_val[19]=68;
  1047. Xd_val[20]=  11;  a_val[20]= 3;  b_val[20]=1;  r_val[20]=2;
  1048. Xd_val[21]= 437;  a_val[21]=19;  b_val[21]=1;  r_val[21]=76;
  1049. Xd_val[22]=  30;  a_val[22]= 5;  b_val[22]=1;  r_val[22]=5;
  1050. X/* v1=23        INVALID */
  1051. Xd_val[24]= 143;  a_val[24]=11;  b_val[24]=1;  r_val[24]=22;
  1052. Xd_val[25]=  69;  a_val[25]= 9;  b_val[25]=1;  r_val[25]=12;
  1053. Xd_val[26]=  42;  a_val[26]= 6;  b_val[26]=1;  r_val[26]=6;
  1054. Xd_val[27]=  29;  a_val[27]= 5;  b_val[27]=1;  r_val[27]=4;
  1055. Xd_val[28]= 195;  a_val[28]=13;  b_val[28]=1;  r_val[28]=26;
  1056. Xd_val[29]=  93;  a_val[29]= 9;  b_val[29]=1;  r_val[29]=12;
  1057. Xd_val[30]=  14;  a_val[30]= 4;  b_val[30]=1;  r_val[30]=2;
  1058. Xd_val[31]= 957;  a_val[31]=29;  b_val[31]=1;  r_val[31]=116;
  1059. Xd_val[32]= 255;  a_val[32]=15;  b_val[32]=1;  r_val[32]=30;
  1060. Xd_val[33]=1085;  a_val[33]=31;  b_val[33]=1;  r_val[33]=124;
  1061. X/* v1=34        INVALID */
  1062. Xd_val[35]=1221;  a_val[35]=33;  b_val[35]=1;  r_val[35]=132;
  1063. Xd_val[36]= 323;  a_val[36]=17;  b_val[36]=1;  r_val[36]=34;
  1064. Xd_val[37]=1365;  a_val[37]=35;  b_val[37]=1;  r_val[37]=140;
  1065. Xd_val[38]=  10;  a_val[38]= 3;  b_val[38]=1;  r_val[38]=1;
  1066. Xd_val[39]=1517;  a_val[39]=37;  b_val[39]=1;  r_val[39]=148;
  1067. Xd_val[40]= 399;  a_val[40]=19;  b_val[40]=1;  r_val[40]=38;
  1068. Xd_val[41]=1677;  a_val[41]=39;  b_val[41]=1;  r_val[41]=156;
  1069. Xd_val[42]= 110;  a_val[42]=10;  b_val[42]=1;  r_val[42]=10;
  1070. Xd_val[43]= 205;  a_val[43]=15;  b_val[43]=1;  r_val[43]=20;
  1071. Xd_val[44]= 483;  a_val[44]=21;  b_val[44]=1;  r_val[44]=42;
  1072. Xd_val[45]=2021;  a_val[45]=43;  b_val[45]=1;  r_val[45]=172;
  1073. Xd_val[46]=  33;  a_val[46]= 6;  b_val[46]=1;  r_val[46]=3;
  1074. X/* v1=47        INVALID */
  1075. Xd_val[48]=  23;  a_val[48]= 5;  b_val[48]=1;  r_val[48]=2;
  1076. Xd_val[49]=2397;  a_val[49]=47;  b_val[49]=1;  r_val[49]=188;
  1077. Xd_val[50]=  39;  a_val[50]= 6;  b_val[50]=1;  r_val[50]=3;
  1078. Xd_val[51]=  53;  a_val[51]= 7;  b_val[51]=1;  r_val[51]=4;
  1079. X/* v1=52        INVALID */
  1080. Xd_val[53]=2805;  a_val[53]=51;  b_val[53]=1;  r_val[53]=204;
  1081. Xd_val[54]= 182;  a_val[54]=13;  b_val[54]=1;  r_val[54]=13;
  1082. Xd_val[55]=3021;  a_val[55]=53;  b_val[55]=1;  r_val[55]=212;
  1083. Xd_val[56]=  87;  a_val[56]= 9;  b_val[56]=1;  r_val[56]=6;
  1084. Xd_val[57]=3245;  a_val[57]=55;  b_val[57]=1;  r_val[57]=220;
  1085. Xd_val[58]= 210;  a_val[58]=14;  b_val[58]=1;  r_val[58]=14;
  1086. Xd_val[59]=3477;  a_val[59]=57;  b_val[59]=1;  r_val[59]=228;
  1087. Xd_val[60]= 899;  a_val[60]=29;  b_val[60]=1;  r_val[60]=58;
  1088. Xd_val[61]= 413;  a_val[61]=21;  b_val[61]=1;  r_val[61]=28;
  1089. X/* v1=62        INVALID */
  1090. Xd_val[63]=3965;  a_val[63]=61;  b_val[63]=1;  r_val[63]=244;
  1091. Xd_val[64]=1023;  a_val[64]=31;  b_val[64]=1;  r_val[64]=62;
  1092. Xd_val[65]= 469;  a_val[65]=21;  b_val[65]=1;  r_val[65]=28;
  1093. Xd_val[66]=  17;  a_val[66]= 4;  b_val[66]=1;  r_val[66]=1;
  1094. Xd_val[67]=4485;  a_val[67]=65;  b_val[67]=1;  r_val[67]=260;
  1095. Xd_val[68]=1155;  a_val[68]=33;  b_val[68]=1;  r_val[68]=66;
  1096. Xd_val[69]=4757;  a_val[69]=67;  b_val[69]=1;  r_val[69]=268;
  1097. Xd_val[70]=  34;  a_val[70]= 6;  b_val[70]=1;  r_val[70]=2;
  1098. Xd_val[71]=5037;  a_val[71]=69;  b_val[71]=1;  r_val[71]=276;
  1099. Xd_val[72]=1295;  a_val[72]=35;  b_val[72]=1;  r_val[72]=70;
  1100. Xd_val[73]= 213;  a_val[73]=15;  b_val[73]=1;  r_val[73]=12;
  1101. Xd_val[74]=  38;  a_val[74]= 6;  b_val[74]=1;  r_val[74]=2;
  1102. Xd_val[75]=5621;  a_val[75]=73;  b_val[75]=1;  r_val[75]=292;
  1103. Xd_val[76]=1443;  a_val[76]=37;  b_val[76]=1;  r_val[76]=74;
  1104. Xd_val[77]= 237;  a_val[77]=15;  b_val[77]=1;  r_val[77]=12;
  1105. Xd_val[78]=  95;  a_val[78]=10;  b_val[78]=1;  r_val[78]=5;
  1106. X/* v1=79        INVALID */
  1107. Xd_val[80]=1599;  a_val[80]=39;  b_val[80]=1;  r_val[80]=78;
  1108. Xd_val[81]=6557;  a_val[81]=79;  b_val[81]=1;  r_val[81]=316;
  1109. Xd_val[82]= 105;  a_val[82]=10;  b_val[82]=1;  r_val[82]=5;
  1110. Xd_val[83]=  85;  a_val[83]= 9;  b_val[83]=1;  r_val[83]=4;
  1111. Xd_val[84]=1763;  a_val[84]=41;  b_val[84]=1;  r_val[84]=82;
  1112. Xd_val[85]=7221;  a_val[85]=83;  b_val[85]=1;  r_val[85]=332;
  1113. Xd_val[86]= 462;  a_val[86]=21;  b_val[86]=1;  r_val[86]=21;
  1114. Xd_val[87]=7565;  a_val[87]=85;  b_val[87]=1;  r_val[87]=340;
  1115. Xd_val[88]= 215;  a_val[88]=15;  b_val[88]=1;  r_val[88]=10;
  1116. Xd_val[89]=7917;  a_val[89]=87;  b_val[89]=1;  r_val[89]=348;
  1117. Xd_val[90]= 506;  a_val[90]=22;  b_val[90]=1;  r_val[90]=22;
  1118. Xd_val[91]=8277;  a_val[91]=89;  b_val[91]=1;  r_val[91]=356;
  1119. Xd_val[92]= 235;  a_val[92]=15;  b_val[92]=1;  r_val[92]=10;
  1120. Xd_val[93]=8645;  a_val[93]=91;  b_val[93]=1;  r_val[93]=364;
  1121. Xd_val[94]= 138;  a_val[94]=12;  b_val[94]=1;  r_val[94]=6;
  1122. Xd_val[95]=9021;  a_val[95]=93;  b_val[95]=1;  r_val[95]=372;
  1123. Xd_val[96]=  47;  a_val[96]= 7;  b_val[96]=1;  r_val[96]=2;
  1124. Xd_val[97]=1045;  a_val[97]=33;  b_val[97]=1;  r_val[97]=44;
  1125. X/* v1=98        INVALID */
  1126. Xd_val[99]=9797;  a_val[99]=97;  b_val[99]=1;  r_val[99]=388;
  1127. Xd_val[100]=  51; a_val[100]= 7; b_val[100]=1; r_val[100]=2;
  1128. X
  1129. Xglobal lib_debug;
  1130. Xif (!isnum(lib_debug) || lib_debug>0) print "d_val[100] defined"
  1131. Xif (!isnum(lib_debug) || lib_debug>0) print "a_val[100] defined"
  1132. Xif (!isnum(lib_debug) || lib_debug>0) print "b_val[100] defined"
  1133. Xif (!isnum(lib_debug) || lib_debug>0) print "r_val[100] defined"
  1134. END_OF_FILE
  1135. if test 6758 -ne `wc -c <'lib/lucas_tbl.cal'`; then
  1136.     echo shar: \"'lib/lucas_tbl.cal'\" unpacked with wrong size!
  1137. fi
  1138. # end of 'lib/lucas_tbl.cal'
  1139. fi
  1140. if test -f 'symbol.c' -a "${1}" != "-c" ; then 
  1141.   echo shar: Will not clobber existing file \"'symbol.c'\"
  1142. else
  1143. echo shar: Extracting \"'symbol.c'\" \(7254 characters\)
  1144. sed "s/^X//" >'symbol.c' <<'END_OF_FILE'
  1145. X/*
  1146. X * Copyright (c) 1992 David I. Bell
  1147. X * Permission is granted to use, distribute, or modify this source,
  1148. X * provided that this copyright notice remains intact.
  1149. X *
  1150. X * Global and local symbol routines.
  1151. X */
  1152. X
  1153. X#include "calc.h"
  1154. X#include "token.h"
  1155. X#include "symbol.h"
  1156. X#include "string.h"
  1157. X#include "opcodes.h"
  1158. X#include "func.h"
  1159. X
  1160. X#define HASHSIZE    37    /* size of hash table */
  1161. X
  1162. X
  1163. Xstatic STRINGHEAD localnames;    /* list of local variable names */
  1164. Xstatic STRINGHEAD globalnames;    /* list of global variable names */
  1165. Xstatic STRINGHEAD paramnames;    /* list of parameter variable names */
  1166. Xstatic GLOBAL *globalhash[HASHSIZE];    /* hash table for globals */
  1167. X
  1168. Xstatic void fitprint();
  1169. X
  1170. X
  1171. X/*
  1172. X * Hash a symbol name so we can find it in the hash table.
  1173. X * Args are the symbol name and the symbol name size.
  1174. X */
  1175. X#define HASH(n, s) ((unsigned)((n)[0]*123 + (n)[s-1]*135 + (s)*157) % HASHSIZE)
  1176. X
  1177. X
  1178. X/*
  1179. X * Initialize the global symbol table.
  1180. X */
  1181. Xvoid
  1182. Xinitglobals()
  1183. X{
  1184. X    int i;        /* index counter */
  1185. X
  1186. X    for (i = 0; i < HASHSIZE; i++)
  1187. X        globalhash[i] = NULL;
  1188. X    initstr(&globalnames);
  1189. X}
  1190. X
  1191. X
  1192. X/*
  1193. X * Define a possibly new global variable.
  1194. X * If it did not already exist, it is created with an undefined value.
  1195. X * The address of the global symbol structure is returned.
  1196. X */
  1197. XGLOBAL *
  1198. Xaddglobal(name)
  1199. X    char *name;        /* name of global variable */
  1200. X{
  1201. X    GLOBAL *sp;        /* current symbol pointer */
  1202. X    GLOBAL **hp;        /* hash table head address */
  1203. X    long len;        /* length of string */
  1204. X
  1205. X    len = strlen(name);
  1206. X    if (len <= 0)
  1207. X        return NULL;
  1208. X    hp = &globalhash[HASH(name, len)];
  1209. X    for (sp = *hp; sp; sp = sp->g_next) {
  1210. X        if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0))
  1211. X            return sp;
  1212. X    }
  1213. X    sp = (GLOBAL *) malloc(sizeof(GLOBAL));
  1214. X    if (sp == NULL)
  1215. X        return sp;
  1216. X    sp->g_name = addstr(&globalnames, name);
  1217. X    sp->g_len = len;
  1218. X    sp->g_value.v_type = V_NULL;
  1219. X    sp->g_next = *hp;
  1220. X    *hp = sp;
  1221. X    return sp;
  1222. X}
  1223. X
  1224. X
  1225. X/*
  1226. X * Look up the name of a global variable and return its address.
  1227. X * Returns NULL if the symbol was not found.
  1228. X */
  1229. XGLOBAL *
  1230. Xfindglobal(name)
  1231. X    char *name;        /* name of global variable */
  1232. X{
  1233. X    GLOBAL *sp;        /* current symbol pointer */
  1234. X    long len;        /* length of string */
  1235. X
  1236. X    len = strlen(name);
  1237. X    sp = globalhash[HASH(name, len)];
  1238. X    while (sp) {
  1239. X        if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0))
  1240. X            return sp;
  1241. X        sp = sp->g_next;
  1242. X    }
  1243. X    return sp;
  1244. X}
  1245. X
  1246. X
  1247. X/*
  1248. X * Return the name of a global variable given its address.
  1249. X */
  1250. Xchar *
  1251. Xglobalname(sp)
  1252. X    GLOBAL *sp;        /* address of global pointer */
  1253. X{
  1254. X    if (sp)
  1255. X        return sp->g_name;
  1256. X    return "";
  1257. X}
  1258. X
  1259. X
  1260. X/*
  1261. X * Show the value of all global variables, typing only the head and
  1262. X * tail of very large numbers.
  1263. X */
  1264. Xvoid
  1265. Xshowglobals()
  1266. X{
  1267. X    GLOBAL **hp;            /* hash table head address */
  1268. X    register GLOBAL *sp;        /* current global symbol pointer */
  1269. X    long count;            /* number of global variables shown */
  1270. X    NUMBER *num, *den;
  1271. X    long digits;
  1272. X
  1273. X    count = 0;
  1274. X    for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
  1275. X        for (sp = *hp; sp; sp = sp->g_next) {
  1276. X            if (sp->g_value.v_type != V_NUM)
  1277. X                continue;
  1278. X            if (count++ == 0) {
  1279. X                printf("\nName    Digits  Value\n");
  1280. X                printf(  "----    ------  -----\n");
  1281. X            }
  1282. X            printf("%-8s ", sp->g_name);
  1283. X            num = qnum(sp->g_value.v_num);
  1284. X            digits = qdigits(num);
  1285. X            printf("%-7ld ", digits);
  1286. X            fitprint(num, digits, 60L);
  1287. X            qfree(num);
  1288. X            if (!qisint(sp->g_value.v_num)) {
  1289. X                den = qden(sp->g_value.v_num);
  1290. X                digits = qdigits(den);
  1291. X                printf("\n    %-6ld /", digits);
  1292. X                fitprint(den, digits, 60L);
  1293. X                qfree(den);
  1294. X            }
  1295. X            printf("\n");
  1296. X        }
  1297. X    }
  1298. X    printf(count ? "\n" : "No global variables defined.\n");
  1299. X}
  1300. X
  1301. X
  1302. X/*
  1303. X * Print an integer which is guaranteed to fit in the specified number
  1304. X * of columns, using imbedded '...' characters if it is too large.
  1305. X */
  1306. Xstatic void
  1307. Xfitprint(num, digits, width)
  1308. X    NUMBER *num;        /* number to print */
  1309. X    long digits, width;
  1310. X{
  1311. X    long show, used;
  1312. X    NUMBER *p, *t, *div, *val;
  1313. X
  1314. X    if (digits <= width) {
  1315. X        qprintf("%r", num);
  1316. X        return;
  1317. X    }
  1318. X    show = (width / 2) - 2;
  1319. X    t = itoq(10L);
  1320. X    p = itoq((long) (digits - show));
  1321. X    div = qpowi(t, p);
  1322. X    val = qquo(num, div);
  1323. X    qprintf("%r...", val);
  1324. X    qfree(p);
  1325. X    qfree(div);
  1326. X    qfree(val);
  1327. X    p = itoq(show);
  1328. X    div = qpowi(t, p);
  1329. X    val = qmod(num, div);
  1330. X    used = qdigits(val);
  1331. X    while (used++ < show) printf("0");
  1332. X    qprintf("%r", val);
  1333. X    qfree(p);
  1334. X    qfree(div);
  1335. X    qfree(val);
  1336. X    qfree(t);
  1337. X}
  1338. X
  1339. X
  1340. X/*
  1341. X * Write all normal global variables to an output file.
  1342. X * Note: Currently only simple types are saved.
  1343. X * Returns nonzero on error.
  1344. X */
  1345. Xwriteglobals(name)
  1346. X    char *name;
  1347. X{
  1348. X    FILE *fp;
  1349. X    GLOBAL **hp;            /* hash table head address */
  1350. X    register GLOBAL *sp;        /* current global symbol pointer */
  1351. X    int savemode;            /* saved output mode */
  1352. X
  1353. X    fp = f_open(name, "w");
  1354. X    if (fp == NULL)
  1355. X        return 1;
  1356. X    setfp(fp);
  1357. X    for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
  1358. X        for (sp = *hp; sp; sp = sp->g_next) {
  1359. X            switch (sp->g_value.v_type) {
  1360. X                case V_NUM:
  1361. X                case V_COM:
  1362. X                case V_STR:
  1363. X                    break;
  1364. X                default:
  1365. X                    continue;
  1366. X            }
  1367. X            math_fmt("%s = ", sp->g_name);
  1368. X            savemode = _outmode_;
  1369. X            _outmode_ = MODE_HEX;
  1370. X            printvalue(&sp->g_value, PRINT_UNAMBIG);
  1371. X            _outmode_ = savemode;
  1372. X            math_str(";\n");
  1373. X        }
  1374. X    }
  1375. X    setfp(stdout);
  1376. X    if (fclose(fp))
  1377. X        return 1;
  1378. X    return 0;
  1379. X}
  1380. X
  1381. X
  1382. X/*
  1383. X * Initialize the local and parameter symbol table information.
  1384. X */
  1385. Xvoid
  1386. Xinitlocals()
  1387. X{
  1388. X    initstr(&localnames);
  1389. X    initstr(¶mnames);
  1390. X    curfunc->f_localcount = 0;
  1391. X    curfunc->f_paramcount = 0;
  1392. X}
  1393. X
  1394. X
  1395. X/*
  1396. X * Add a possibly new local variable definition.
  1397. X * Returns the index of the variable into the local symbol table.
  1398. X * Minus one indicates the symbol could not be added.
  1399. X */
  1400. Xlong
  1401. Xaddlocal(name)
  1402. X    char *name;        /* name of local variable */
  1403. X{
  1404. X    long index;        /* current symbol index */
  1405. X
  1406. X    index = findstr(&localnames, name);
  1407. X    if (index >= 0)
  1408. X        return index;
  1409. X    index = localnames.h_count;
  1410. X    (void) addstr(&localnames, name);
  1411. X    curfunc->f_localcount++;
  1412. X    return index;
  1413. X}
  1414. X
  1415. X
  1416. X/*
  1417. X * Find a local variable name and return its index.
  1418. X * Returns minus one if the variable name is not defined.
  1419. X */
  1420. Xlong
  1421. Xfindlocal(name)
  1422. X    char *name;        /* name of local variable */
  1423. X{
  1424. X    return findstr(&localnames, name);
  1425. X}
  1426. X
  1427. X
  1428. X/*
  1429. X * Return the name of a local variable.
  1430. X */
  1431. Xchar *
  1432. Xlocalname(n)
  1433. X    long n;
  1434. X{
  1435. X    return namestr(&localnames, n);
  1436. X}
  1437. X
  1438. X
  1439. X/*
  1440. X * Add a possibly new parameter variable definition.
  1441. X * Returns the index of the variable into the parameter symbol table.
  1442. X * Minus one indicates the symbol could not be added.
  1443. X */
  1444. Xlong
  1445. Xaddparam(name)
  1446. X    char *name;        /* name of parameter variable */
  1447. X{
  1448. X    long index;        /* current symbol index */
  1449. X
  1450. X    index = findstr(¶mnames, name);
  1451. X    if (index >= 0)
  1452. X        return index;
  1453. X    index = paramnames.h_count;
  1454. X    (void) addstr(¶mnames, name);
  1455. X    curfunc->f_paramcount++;
  1456. X    return index;
  1457. X}
  1458. X
  1459. X
  1460. X/*
  1461. X * Find a parameter variable name and return its index.
  1462. X * Returns minus one if the variable name is not defined.
  1463. X */
  1464. Xlong
  1465. Xfindparam(name)
  1466. X    char *name;        /* name of parameter variable */
  1467. X{
  1468. X    return findstr(¶mnames, name);
  1469. X}
  1470. X
  1471. X
  1472. X/*
  1473. X * Return the name of a parameter variable.
  1474. X */
  1475. Xchar *
  1476. Xparamname(n)
  1477. X    long n;
  1478. X{
  1479. X    return namestr(¶mnames, n);
  1480. X}
  1481. X
  1482. X
  1483. X/*
  1484. X * Return the type of a variable name.
  1485. X * This is either local, parameter, global, or undefined.
  1486. X */
  1487. Xsymboltype(name)
  1488. X    char *name;        /* variable name to find */
  1489. X{
  1490. X    if (findlocal(name) >= 0)
  1491. X        return SYM_LOCAL;
  1492. X    if (findparam(name) >= 0)
  1493. X        return SYM_PARAM;
  1494. X    if (findglobal(name))
  1495. X        return SYM_GLOBAL;
  1496. X    return SYM_UNDEFINED;
  1497. X}
  1498. X
  1499. X/* END CODE */
  1500. END_OF_FILE
  1501. if test 7254 -ne `wc -c <'symbol.c'`; then
  1502.     echo shar: \"'symbol.c'\" unpacked with wrong size!
  1503. fi
  1504. # end of 'symbol.c'
  1505. fi
  1506. echo shar: End of archive 4 \(of 21\).
  1507. cp /dev/null ark4isdone
  1508. MISSING=""
  1509. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  1510.     if test ! -f ark${I}isdone ; then
  1511.     MISSING="${MISSING} ${I}"
  1512.     fi
  1513. done
  1514. if test "${MISSING}" = "" ; then
  1515.     echo You have unpacked all 21 archives.
  1516.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1517. else
  1518.     echo You still need to unpack the following archives:
  1519.     echo "        " ${MISSING}
  1520. fi
  1521. ##  End of shell archive.
  1522. exit 0
  1523.