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

  1. Newsgroups: comp.sources.unix
  2. From: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  3. Subject: v26i034: CALC - An arbitrary precision C-like calculator, Part08/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 34
  9. Archive-Name: calc/part08
  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 8 (of 21)."
  18. # Contents:  input.c lib/regress.cal
  19. # Wrapped by dbell@elm on Tue Feb 25 15:21:03 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'input.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'input.c'\"
  23. else
  24. echo shar: Extracting \"'input.c'\" \(17693 characters\)
  25. sed "s/^X//" >'input.c' <<'END_OF_FILE'
  26. X/*
  27. X * Copyright (c) 1992 David I. Bell
  28. X * Permission is granted to use, distribute, or modify this source,
  29. X * provided that this copyright notice remains intact.
  30. X *
  31. X * Nested input source file reader.
  32. X * For terminal input, this also provides a simple command stack.
  33. X */
  34. X
  35. X#include <ctype.h>
  36. X#include <pwd.h>
  37. X#include "calc.h"
  38. X#include "config.h"
  39. X
  40. X#define MAXSAVE        255    /* number of saved terminal lines */
  41. X#define DEFHIST        20    /* default history length display */
  42. X#define TTYSIZE        100    /* reallocation size for terminal buffers */
  43. X#define DEPTH        10    /* maximum depth of input */
  44. X#define IS_READ        1    /* reading normally */
  45. X#define IS_REREAD    2    /* reread current character */
  46. X#define chartoint(ch)    ((ch) & 0xff)    /* make sure char is not negative */
  47. X
  48. X
  49. Xtypedef struct {
  50. X    short i_state;        /* state (read, reread) */
  51. X    short i_char;        /* currently read char */
  52. X    long i_line;        /* line number */
  53. X    char *i_str;        /* current string for input (if not NULL) */
  54. X    char *i_origstr;    /* original string so it can be freed */
  55. X    char *i_ttystr;        /* current character of tty line (or NULL) */
  56. X    FILE *i_fp;        /* current file for input (if not NULL) */
  57. X    char *i_name;        /* file name if known */
  58. X} INPUT;
  59. X
  60. X
  61. Xstatic int stacksize;        /* number of elements in command stack */
  62. Xstatic int stackindex;        /* current index into command stack */
  63. Xstatic int cmdsize;        /* current max size of terminal buffer */
  64. Xstatic int editsize;        /* current max size of edit buffer */
  65. Xstatic int linesize;        /* current max size of input line */
  66. Xstatic char *linebuf;        /* current input line buffer */
  67. Xstatic char *cmdbuf;        /* current command line buffer */
  68. Xstatic char *editbuf;        /* edit buffer */
  69. Xstatic char **cmdstack;        /* command stack */
  70. Xstatic char *prompt;        /* current prompt for terminal */
  71. Xstatic BOOL noprompt;        /* TRUE if should not print prompt */
  72. X
  73. Xstatic int depth;        /* current input depth */
  74. Xstatic INPUT *cip;        /* current input source */
  75. Xstatic INPUT inputs[DEPTH];    /* input sources */
  76. X
  77. X
  78. Xstatic char *findhistory(), *edithistory();
  79. Xstatic int openfile();
  80. Xstatic int ttychar();
  81. X
  82. Xextern struct passwd *getpwnam();
  83. X
  84. X
  85. X/*
  86. X * Open an input file by possibly searching through a path list
  87. X * and also possibly applying the specified extension.  For example:
  88. X * opensearchfile("barf", ".:/tmp", ".c") searches in order for the
  89. X * files "./barf", "./barf.c", "/tmp/barf", and "/tmp/barf.c".
  90. X *
  91. X * Returns -1 if all specified files cannot be opened.
  92. X */
  93. Xopensearchfile(name, pathlist, extension)
  94. X    char *name;        /* file name to be read */
  95. X    char *pathlist;        /* list of colon separated paths (or NULL) */
  96. X    char *extension;    /* extra extension to try (or NULL) */
  97. X{
  98. X    int i;
  99. X    char *cp;
  100. X    char path[PATHSIZE+1];    /* name being searched for */
  101. X
  102. X    /*
  103. X     * Don't try the extension if the filename already contains it.
  104. X     */
  105. X    if (extension) {
  106. X        i = strlen(name) - strlen(extension);
  107. X        if ((i >= 0) && (strcmp(&name[i], extension) == 0))
  108. X            extension = NULL;
  109. X    }
  110. X    /*
  111. X     * If the name is absolute, or if there is no path list, then
  112. X     * make one which just searches for the name straight.  Then
  113. X     * search through the path list for the file, without and with
  114. X     * the specified extension.
  115. X     */
  116. X    if (name[0] == PATHCHAR || 
  117. X        name[0] == HOMECHAR || 
  118. X        (name[0] == DOTCHAR && name[1] == PATHCHAR) || 
  119. X        pathlist == NULL) {
  120. X        pathlist = "";
  121. X    }
  122. X    pathlist--;
  123. X    do {
  124. X        pathlist++;
  125. X        cp = path;
  126. X        while (*pathlist && (*pathlist != LISTCHAR))
  127. X            *cp++ = *pathlist++;
  128. X        if (cp != path)
  129. X            *cp++ = PATHCHAR;
  130. X        strcpy(cp, name);
  131. X        i = openfile(path);
  132. X        if ((i < 0) && extension) {
  133. X            strcat(path, extension);
  134. X            i = openfile(path);
  135. X        }
  136. X    } while ((i < 0) && *pathlist);
  137. X    return i;
  138. X}
  139. X
  140. X
  141. X/*
  142. X * Given a filename with a leading ~, expand it into a home directory for 
  143. X * that user.  This function will malloc the space for the expanded path.
  144. X *
  145. X * If the path is just ~, or begins with ~/, expand it to the home
  146. X * directory of the current user.  If the environment variable $HOME
  147. X * is known, it will be used, otherwise the password file will be
  148. X * consulted.
  149. X *
  150. X * If the path is just ~username, or ~username/, expand it to the home
  151. X * directory of that user by looking it up in the password file.
  152. X *
  153. X * If the password file must be consulted and the username is not found
  154. X * a NULL pointer is returned.
  155. X */
  156. Xstatic char *
  157. Xhomeexpand(name)
  158. X    char *name;        /* a filename with a leading ~ */
  159. X{
  160. X    struct passwd *ent;    /* password entry */
  161. X    char *home2;        /* fullpath of the home directory */
  162. X    char *fullpath;        /* the malloced expanded path */
  163. X    char *after;        /* after the ~user or ~ */
  164. X    char username[PATHSIZE+1];    /* extratced username */
  165. X
  166. X    /* firewall */
  167. X    if (name[0] != HOMECHAR)
  168. X        return NULL;
  169. X
  170. X    /*
  171. X     * obtain the home directory component
  172. X     */
  173. X    switch (name[1]) {
  174. X    case PATHCHAR:        /* ~/... */
  175. X    case '\0':        /* ~ */
  176. X        home2 = home;
  177. X        after = name+1;
  178. X        break;
  179. X    default:        /* ~username or ~username/... */
  180. X
  181. X        /* extract the username after the ~ */
  182. X        after = (char *)strchr(name+2, PATHCHAR);
  183. X        if (after == NULL) {
  184. X            /* path is just ~username */
  185. X            ent = getpwnam(name+1);
  186. X            if (ent == NULL) {
  187. X                /* unknown user */
  188. X                return NULL;
  189. X            }
  190. X            /* just malloc the home directory and return it */
  191. X            fullpath = (char *)malloc(strlen(ent->pw_dir)+1);
  192. X            strcpy(fullpath, ent->pw_dir);
  193. X            return fullpath;
  194. X        }
  195. X        if (after-name > PATHSIZE+1) {
  196. X            /* username is too big */
  197. X            return NULL;
  198. X        }
  199. X        strncpy(username, name+1, after-name-1);
  200. X        username[after-name-1] = '\0';
  201. X
  202. X        /* get that user's home directory */
  203. X        ent = getpwnam(username);
  204. X        if (ent == NULL) {
  205. X            /* unknown user */
  206. X            return NULL;
  207. X        }
  208. X        home2 = ent->pw_dir;
  209. X        break;
  210. X    }
  211. X
  212. X    /*
  213. X     * build the fullpath given the home directory
  214. X     */
  215. X    fullpath = (char *)malloc(strlen(home2)+strlen(after)+1);
  216. X    sprintf(fullpath, "%s%s", home2, after);
  217. X    return fullpath;
  218. X}
  219. X
  220. X
  221. X/*
  222. X * f_open - ~-expand a filename and fopen() it
  223. X */
  224. XFILE *
  225. Xf_open(name, mode)
  226. X    char *name;        /* the filename to open */
  227. X    char *mode;        /* the fopen mode to use */
  228. X{
  229. X    FILE *fp;        /* open file descriptor */
  230. X    char *fullname;        /* file name with HOMECHAR expansion */
  231. X
  232. X    /*
  233. X     * expand ~ if needed
  234. X     */
  235. X    if (name[0] == HOMECHAR) {
  236. X        fullname = homeexpand(name);
  237. X        if (fullname == NULL)
  238. X            return NULL;
  239. X        fp = fopen(fullname, mode);
  240. X        free(fullname);
  241. X    } else {
  242. X        fp = fopen(name, mode);
  243. X    }
  244. X    return fp;
  245. X}
  246. X
  247. X
  248. X/*
  249. X * Setup for reading from a input file.
  250. X * Returns -1 if file could not be opened.
  251. X */
  252. Xstatic
  253. Xopenfile(name)
  254. X    char *name;        /* file name to be read */
  255. X{
  256. X    FILE *fp;        /* open file descriptor */
  257. X
  258. X    if (depth >= DEPTH)
  259. X         return -1;
  260. X    fp = f_open(name, "r");
  261. X    if (fp == NULL)
  262. X         return -1;
  263. X    cip++;
  264. X    cip->i_state = IS_READ;
  265. X    cip->i_char = '\0';
  266. X    cip->i_str = NULL;
  267. X    cip->i_origstr = NULL;
  268. X    cip->i_ttystr = NULL;
  269. X    cip->i_fp = fp;
  270. X    cip->i_line = 1;
  271. X    cip->i_name = (char *)malloc(strlen(name) + 1);
  272. X    strcpy(cip->i_name, name);
  273. X    depth++;
  274. X    return 0;
  275. X}
  276. X
  277. X
  278. X/*
  279. X * Open a string for scanning. String is ended by a null character.
  280. X * String is copied into local memory so it can be trashed afterwards.
  281. X * Returns -1 if cannot open string.
  282. X */
  283. Xopenstring(str)
  284. X    char *str;        /* string to be opened */
  285. X{
  286. X    char *cp;        /* copied string */
  287. X
  288. X    if ((depth >= DEPTH) || (str == NULL))
  289. X         return -1;
  290. X    cp = (char *)malloc(strlen(str) + 1);
  291. X    if (cp == NULL)
  292. X         return -1;
  293. X    strcpy(cp, str);
  294. X    cip++;
  295. X    cip->i_state = IS_READ;
  296. X    cip->i_char = '\0';
  297. X    cip->i_str = cp;
  298. X    cip->i_origstr = cp;
  299. X    cip->i_fp = NULL;
  300. X    cip->i_name = NULL;
  301. X    cip->i_ttystr = NULL;
  302. X    cip->i_line = 1;
  303. X    depth++;
  304. X    return 0;
  305. X}
  306. X
  307. X
  308. X/*
  309. X * Set to read input from the terminal.
  310. X * Returns -1 if there is no more depth for input.
  311. X */
  312. Xopenterminal()
  313. X{
  314. X    if (depth >= DEPTH)
  315. X         return -1;
  316. X    if (cmdsize == 0) {
  317. X        cmdbuf = (char *)malloc(TTYSIZE + 1);
  318. X        if (cmdbuf == NULL)
  319. X            return -1;
  320. X        cmdsize = TTYSIZE;
  321. X    }
  322. X    if (editsize == 0) {
  323. X        editbuf = (char *)malloc(TTYSIZE + 1);
  324. X        if (editbuf == NULL)
  325. X            return -1;
  326. X        editsize = TTYSIZE;
  327. X    }
  328. X    if (stacksize == 0) {
  329. X        cmdstack = (char **) malloc(MAXSAVE * sizeof(char *));
  330. X        if (cmdstack == NULL)
  331. X            return -1;
  332. X        stacksize = MAXSAVE;
  333. X        for (stackindex = 0; stackindex < MAXSAVE; stackindex++)
  334. X            cmdstack[stackindex] = NULL;
  335. X        stackindex = 0;
  336. X    }
  337. X    cip++;
  338. X    cip->i_state = IS_READ;
  339. X    cip->i_char = '\0';
  340. X    cip->i_str = NULL;
  341. X    cip->i_origstr = NULL;
  342. X    cip->i_ttystr = NULL;
  343. X    cip->i_fp = NULL;
  344. X    cip->i_name = NULL;
  345. X    cip->i_line = 1;
  346. X    depth++;
  347. X    return 0;
  348. X}
  349. X
  350. X
  351. X/*
  352. X * Close the current input source.
  353. X */
  354. Xstatic void
  355. Xcloseinput()
  356. X{
  357. X    if (depth <= 0)
  358. X        return;
  359. X    if (cip->i_origstr)
  360. X        free(cip->i_origstr);
  361. X    if (cip->i_fp)
  362. X        fclose(cip->i_fp);
  363. X    if (cip->i_name)
  364. X        free(cip->i_name);
  365. X    cip--;
  366. X    depth--;
  367. X}
  368. X
  369. X
  370. X/*
  371. X * Reset the input sources back to the initial state.
  372. X */
  373. Xvoid
  374. Xresetinput()
  375. X{
  376. X    while (depth > 0)
  377. X        closeinput();
  378. X    cip = inputs;
  379. X    noprompt = FALSE;
  380. X}
  381. X
  382. X
  383. X/*
  384. X * Set the prompt for terminal input.
  385. X */
  386. Xvoid
  387. Xsetprompt(str)
  388. X    char *str;
  389. X{
  390. X    prompt = str;
  391. X    noprompt = FALSE;
  392. X}
  393. X
  394. X
  395. X/*
  396. X * Read the next character from the current input source.
  397. X * End of file returns newline character and closes current input source,
  398. X * except for the last input source, which returns EOF.
  399. X */
  400. Xint
  401. Xnextchar()
  402. X{
  403. X    int ch;            /* current input character */
  404. X
  405. X    if (depth == 0)        /* input finished */
  406. X         return EOF;
  407. X    if (cip->i_state == IS_REREAD) {    /* rereading current char */
  408. X         ch = cip->i_char;
  409. X         cip->i_state = IS_READ;
  410. X         if (ch == '\n')
  411. X            cip->i_line++;
  412. X         return ch;
  413. X    }
  414. X    if (cip->i_str) {        /* from string */
  415. X        ch = chartoint(*cip->i_str++);
  416. X        if (ch == '\0')
  417. X            ch = EOF;
  418. X    } else if (cip->i_fp) {        /* from file */
  419. X        ch = fgetc(cip->i_fp);
  420. X    } else {            /* from terminal */
  421. X        ch = ttychar();
  422. X    }
  423. X    if (ch == EOF) {        /* fix up end of file */
  424. X        closeinput();
  425. X        ch = '\n';
  426. X        if (depth <= 0)
  427. X            ch = EOF;
  428. X    }
  429. X    if (depth > 0)
  430. X        cip->i_char = (char)ch;    /* save for rereads */
  431. X    if (ch == '\n')
  432. X        cip->i_line++;
  433. X    return ch;
  434. X}
  435. X
  436. X
  437. X/*
  438. X * Read in the next line of input from the current input source.
  439. X * The line is terminated with a null character, and does not contain
  440. X * the final newline character.  The returned string is only valid
  441. X * until the next such call, and so must be copied if necessary.
  442. X * Returns NULL on end of file.
  443. X */
  444. Xchar *
  445. Xnextline()
  446. X{
  447. X    char *cp;
  448. X    int ch;
  449. X    int len;
  450. X
  451. X    cp = linebuf;
  452. X    if (linesize == 0) {
  453. X        cp = (char *)malloc(TTYSIZE + 1);
  454. X        if (cp == NULL)
  455. X            error("Cannot allocate line buffer");
  456. X        linebuf = cp;
  457. X        linesize = TTYSIZE;
  458. X    }
  459. X    len = 0;
  460. X    for (;;) {
  461. X        noprompt = TRUE;
  462. X        ch = nextchar();
  463. X        noprompt = FALSE;
  464. X        if (ch == EOF)
  465. X            return NULL;
  466. X        if (ch == '\0')
  467. X            continue;
  468. X        if (ch == '\n')
  469. X            break;
  470. X        if (len >= linesize) {
  471. X            cp = (char *)realloc(cp, linesize + TTYSIZE + 1);
  472. X            if (cp == NULL)
  473. X                error("Cannot realloc line buffer");
  474. X            linebuf = cp;
  475. X            linesize += TTYSIZE;
  476. X        }
  477. X        cp[len++] = (char)ch;
  478. X    }
  479. X    cp[len] = '\0';
  480. X    return linebuf;
  481. X}
  482. X
  483. X
  484. X/*
  485. X * Read the next character from the terminal.
  486. X * This works by reading in a complete line from the terminal at once,
  487. X * and then returns the characters one by one as required.  If the line
  488. X * begins with the special command stack history character, then it is
  489. X * replaced by some previous command line.  The saved line is then put on
  490. X * the command stack for future reference.
  491. X */
  492. Xstatic int
  493. Xttychar()
  494. X{
  495. X    int ch;            /* current char */
  496. X    int len;        /* length of current command */
  497. X    char *newbuf;        /* new buffer */
  498. X
  499. X    /*
  500. X     * If we have more to read from the saved command line, then do that.
  501. X     * When we see a newline character, then clear the pointer so we will
  502. X     * read a new line on the next call.
  503. X     */
  504. X    if (cip->i_ttystr) {
  505. X        ch = chartoint(*cip->i_ttystr++);
  506. X        if (ch == '\n')
  507. X            cip->i_ttystr = NULL;
  508. X        return ch;
  509. X    }
  510. X    /*
  511. X     * We need another complete line.  Print the prompt string, then read
  512. X     * in a new command line, expanding the command buffer as necessary.
  513. X     */
  514. X    if (!noprompt) {
  515. X        printf("%02d%s", stackindex + 1, prompt);
  516. X        fflush(stdout);
  517. X    }
  518. X    abortlevel = 0;
  519. X    len = 0;
  520. X    do {
  521. X        if (len >= cmdsize) {
  522. X            newbuf = (char *)realloc(cmdbuf, cmdsize + TTYSIZE + 1);
  523. X            if (newbuf == NULL) {
  524. X                perror("Cannot reallocate terminal buffer");
  525. X                return EOF;
  526. X            }
  527. X            cmdbuf = newbuf;
  528. X            cmdsize += TTYSIZE;
  529. X        }
  530. X        inputwait = TRUE;
  531. X        ch = getchar();
  532. X        inputwait = FALSE;
  533. X        if (ch == EOF)
  534. X            return EOF;
  535. X        ch = chartoint(ch);
  536. X        if (ch)
  537. X            cmdbuf[len++] = (char)ch;
  538. X    } while (ch != '\n');
  539. X    cmdbuf[len] = '\0';
  540. X    /*
  541. X     * If the line was blank, then just return the line feed and do not
  542. X     * put the line on the command stack.
  543. X     */
  544. X    if (len == 1)
  545. X        return '\n';
  546. X    /*
  547. X     * Handle shell escape if present
  548. X     */
  549. X    if (cmdbuf[0] == '!') {        /* do a shell command */
  550. X        char *cmd;
  551. X
  552. X        cmd = cmdbuf + 1;
  553. X        if (*cmd == '\0' || *cmd == '\n')
  554. X            cmd = shell;
  555. X        system(cmd);
  556. X        return '\n';
  557. X    /*
  558. X     * Handle history command if present.
  559. X     */
  560. X    } else if (cmdbuf[0] == '`') {
  561. X        cmdbuf[len-1] = '\0';
  562. X        newbuf = findhistory(cmdbuf + 1);
  563. X        if (newbuf == NULL)
  564. X            return '\n';
  565. X        strcpy(cmdbuf, newbuf);
  566. X    }
  567. X    /*
  568. X     * Save the line in the command stack.
  569. X     */
  570. X    newbuf = (char *)malloc(strlen(cmdbuf) + 1);
  571. X    if (newbuf == NULL) {
  572. X        perror("Cannot save history line");
  573. X        return EOF;
  574. X    }
  575. X    strcpy(newbuf, cmdbuf);
  576. X    if (cmdstack[stackindex])
  577. X        free(cmdstack[stackindex]);
  578. X    cmdstack[stackindex] = newbuf;
  579. X    stackindex = (stackindex + 1) % MAXSAVE;
  580. X    /*
  581. X     * Return the first character of the line, and set up to
  582. X     * return the rest of it with later calls.
  583. X     */
  584. X    cip->i_ttystr = cmdbuf + 1;
  585. X    return chartoint(cmdbuf[0]);
  586. X}
  587. X
  588. X
  589. X/*
  590. X * Parse a history command line, and return the selected command.
  591. X * NULL is returned if the history command is invalid. Legal formats:
  592. X *    ``    The previous command.
  593. X *    `n    Command number n.
  594. X *    `-n    The nth command back.
  595. X *    `h n    List last n history elements.
  596. X *    `e n    Edit command n (last if not given).
  597. X */
  598. Xstatic char *
  599. Xfindhistory(cmd)
  600. X    char *cmd;        /* history command */
  601. X{
  602. X    int num;        /* command number */
  603. X    int action;        /* action character */
  604. X    int back;        /* how much to search backwards */
  605. X    char *str;        /* returned string */
  606. X
  607. X    num = 0;
  608. X    if ((*cmd == '`') && (cmd[1] == '\0')) {
  609. X        num = stackindex - 1;
  610. X        if (num < 0)
  611. X            num += MAXSAVE;
  612. X        str = cmdstack[num];
  613. X        if (str == NULL)
  614. X            fprintf(stderr, "No previous command\n");
  615. X        return str;
  616. X    }
  617. X    action = '\0';
  618. X    if (isascii(*cmd) && islower(*cmd))
  619. X        action = *cmd++;
  620. X    else if (isascii(*cmd) && isupper(*cmd))
  621. X        action = tolower(*cmd++);
  622. X    while (isascii(*cmd) && isspace(*cmd))
  623. X        cmd++;
  624. X    back = FALSE;
  625. X    if (*cmd == '-') {
  626. X        back = TRUE;
  627. X        cmd++;
  628. X    }
  629. X    num = 0;
  630. X    while ((*cmd >= '0') && (*cmd <= '9'))
  631. X        num = num * 10 + (*cmd++ - '0');
  632. X    if (*cmd != '\0' && *cmd != '\n') {
  633. X        fprintf(stderr, "Invalid history command format\n");
  634. X        return NULL;
  635. X    }
  636. X    if ((num == 0) && (action == 'h'))
  637. X        num = DEFHIST;
  638. X    if ((num == 0) && (action == 'e'))
  639. X        num = stackindex;
  640. X    if ((num <= 0) || (num > MAXSAVE)) {
  641. X        fprintf(stderr, "Invalid history command number\n");
  642. X        return NULL;
  643. X    }
  644. X    if (back)
  645. X        num = stackindex - num;
  646. X    else
  647. X        num--;
  648. X    if (num < 0)
  649. X        num += MAXSAVE;
  650. X    switch (action) {
  651. X        case '\0':
  652. X            str = cmdstack[num];
  653. X            if (str == NULL)
  654. X                fprintf(stderr, "History stack element %d is undefined\n", num + 1);
  655. X            return str;
  656. X
  657. X        case 'e':
  658. X            return edithistory(cmdstack[num]);
  659. X
  660. X        case 'h':
  661. X            num++;
  662. X            back = stackindex - num;
  663. X            if (back < 0)
  664. X                back += MAXSAVE;
  665. X            printf("\n");
  666. X            while (num-- > 0) {
  667. X                if (cmdstack[back])
  668. X                printf("%02d: %s", back + 1, cmdstack[back]);
  669. X                back = (back + 1) % MAXSAVE;
  670. X            }
  671. X            printf("\n");
  672. X            return NULL;
  673. X
  674. X        default:
  675. X            fprintf(stderr, "Invalid history action character");
  676. X            return NULL;
  677. X    }
  678. X}
  679. X
  680. X
  681. X/*
  682. X * Edit the specified command string and return the new version of it.
  683. X * The string is safe to reference until the next call to this routine.
  684. X * Returns NULL if the user gives the command to abort the edit.
  685. X */
  686. X/*ARGSUSED*/
  687. Xstatic char *
  688. Xedithistory(str)
  689. X    char *str;        /* original string */
  690. X{
  691. X#if 0
  692. X    char *tmp;        /* temporary string */
  693. X    int len;        /* current length of string */
  694. X    int cmd;        /* edit command */
  695. X#endif
  696. X
  697. X    printf("Editing not implemented\n");
  698. X    return NULL;
  699. X#if 0
  700. X    len = strlen(str);
  701. X    if (len >= editsize) {
  702. X        tmp = realloc(editbuf, len + TTYSIZE + 1);
  703. X        if (tmp == NULL) {
  704. X            perror("Cannot grow edit line");
  705. X            return NULL;
  706. X        }
  707. X        free(editbuf);
  708. X        editbuf = tmp;
  709. X        editsize = len + TTYSIZE;
  710. X    }
  711. X    strcpy(editbuf, str);
  712. X    for (;;) {
  713. X        printf(" %s*", editbuf);
  714. X        fflush(stdout);
  715. X        cmd = getchar();
  716. X        switch (cmd) {
  717. X            case EOF:
  718. X                return NULL;
  719. X            case '\n':
  720. X                return editbuf;
  721. X            default:
  722. X                while (getchar() != '\n') ;
  723. X                printf("Bad edit command\n");
  724. X        }
  725. X    }
  726. X#endif
  727. X}
  728. X
  729. X
  730. X/*
  731. X * Return whether or not the input source is the terminal.
  732. X */
  733. XBOOL
  734. Xinputisterminal()
  735. X{
  736. X    return ((depth <= 0) || ((cip->i_str == NULL) && (cip->i_fp == NULL)));
  737. X}
  738. X
  739. X
  740. X/*
  741. X * Return the name of the current input file.
  742. X * Returns NULL for terminal or strings.
  743. X */
  744. Xchar *
  745. Xinputname()
  746. X{
  747. X    if (depth <= 0)
  748. X        return NULL;
  749. X    return cip->i_name;
  750. X}
  751. X
  752. X
  753. X/*
  754. X * Return the current line number.
  755. X */
  756. Xlong
  757. Xlinenumber()
  758. X{
  759. X    if (depth > 0)
  760. X        return cip->i_line;
  761. X    return 1;
  762. X}
  763. X
  764. X
  765. X/*
  766. X * Restore the next character to be read again on the next nextchar call.
  767. X */
  768. Xvoid
  769. Xreread()
  770. X{
  771. X    if ((depth <= 0) || (cip->i_state == IS_REREAD))
  772. X        return;
  773. X    cip->i_state = IS_REREAD;
  774. X    if (cip->i_char == '\n')
  775. X        cip->i_line--;
  776. X}
  777. X
  778. X
  779. X/*
  780. X * Process all startup files found in the $CALCRC path.
  781. X */
  782. Xvoid
  783. Xrunrcfiles()
  784. X{
  785. X    char path[PATHSIZE+1];    /* name being searched for */
  786. X    char *cp;
  787. X    char *newcp;
  788. X    char *p;
  789. X    int i;
  790. X
  791. X    /* execute each file in the list */
  792. X    for (cp=calcrc, newcp=(char *)strchr(calcrc, LISTCHAR);
  793. X         cp != NULL && *cp;
  794. X         cp = newcp, 
  795. X         newcp=(newcp) ? (char *)strchr(newcp+1, LISTCHAR) : NULL) {
  796. X
  797. X        /* load file name into the path */
  798. X        if (newcp == NULL) {
  799. X            strcpy(path, cp);
  800. X        } else {
  801. X            strncpy(path, cp, newcp-cp);
  802. X            path[newcp-cp] = '\0';
  803. X        }
  804. X
  805. X        /* find the start of the path */
  806. X        p = (path[0] == ':') ? path+1 : path;
  807. X        if (p[0] == '\0') {
  808. X            continue;
  809. X        }
  810. X
  811. X        /* process the current file in the list */
  812. X        i = openfile(p);
  813. X        if (i < 0)
  814. X            continue;
  815. X        getcommands();
  816. X    }
  817. X}
  818. X
  819. X
  820. X/* END CODE */
  821. END_OF_FILE
  822. if test 17693 -ne `wc -c <'input.c'`; then
  823.     echo shar: \"'input.c'\" unpacked with wrong size!
  824. fi
  825. # end of 'input.c'
  826. fi
  827. if test -f 'lib/regress.cal' -a "${1}" != "-c" ; then 
  828.   echo shar: Will not clobber existing file \"'lib/regress.cal'\"
  829. else
  830. echo shar: Extracting \"'lib/regress.cal'\" \(19555 characters\)
  831. sed "s/^X//" >'lib/regress.cal' <<'END_OF_FILE'
  832. X/*
  833. X * Copyright (c) 1992 David I. Bell
  834. X * Permission is granted to use, distribute, or modify this source,
  835. X * provided that this copyright notice remains intact.
  836. X *
  837. X * Test the correct execution of the calculator by reading this library file.
  838. X * Errors are reported with '****' messages, or worse.  :-)
  839. X *
  840. X * NOTE: Unlike most calc lib files, this one performs its work when
  841. X *       it is read.  Normally one would just define functions and
  842. X *     values for later use.  In the case of the regression test,
  843. X *     we do not want to do this.
  844. X */
  845. X
  846. Xdefine verify(test, str)
  847. X{
  848. X    if (test != 1) {
  849. X        print '**** Non-true result (' : test : '): ' : str;
  850. X        return;
  851. X    }
  852. X    print str;
  853. X}
  854. X
  855. X
  856. Xdefine error(str)
  857. X{
  858. X    print '****' , str;
  859. X}
  860. X
  861. X
  862. Xdefine getglobalvar()
  863. X{
  864. X    global    globalvar;
  865. X
  866. X    return globalvar;
  867. X}
  868. X
  869. X
  870. X/*
  871. X * Test boolean operations and IF tests.
  872. X */
  873. Xdefine test_booleans()
  874. X{
  875. X    local    x;
  876. X    local    y;
  877. X    local    t1, t2, t3;
  878. X
  879. X    print '100: Beginning test_booleans';
  880. X
  881. X    if (0)
  882. X        print '**** if (0)';
  883. X
  884. X    if (1)
  885. X        print '101: if (1)';
  886. X
  887. X    if (2)
  888. X        print '102: if (2)';
  889. X
  890. X    if (1)
  891. X        print '103: if (1) else';
  892. X    else
  893. X        print '**** if (1) else';
  894. X
  895. X    if (0)
  896. X        print '**** if (0) else';
  897. X    else
  898. X        print '104: if (0) else';
  899. X
  900. X    if (1 == 1)
  901. X        print '105: if 1 == 1';
  902. X    else
  903. X        print '**** if 1 == 1';
  904. X
  905. X    if (1 != 2)
  906. X        print '106: if 1 != 2';
  907. X    else
  908. X        print '**** if 1 != 2';
  909. X
  910. X    verify(1,      '107: verify 1');
  911. X    verify(2 == 2, '108: verify 2 == 2');
  912. X    verify(2 != 3, '109: verify 2 != 3');
  913. X    verify(2 <  3, '110: verify 2 <  3');
  914. X    verify(2 <= 2, '111: verify 2 <= 2');
  915. X    verify(2 <= 3, '112: verify 2 <= 3');
  916. X    verify(3 >  2, '113: verify 3 >  2');
  917. X    verify(2 >= 2, '114: verify 2 >= 2');
  918. X    verify(3 >= 2, '115: verify 3 >= 2');
  919. X    verify(!0,     '116: verify !0');
  920. X    verify(!1 == 0,'117: verify !1 == 0');
  921. X    print '118: Ending test_booleans';
  922. X}
  923. X
  924. X
  925. X/*
  926. X * Test variables and simple assignments.
  927. X */
  928. Xdefine test_variables()
  929. X{
  930. X    local    x1, x2, x3;
  931. X    global    g1, g2;
  932. X    local    t;
  933. X    global    globalvar;
  934. X
  935. X    print '200: Beginning test_variables';
  936. X    x1 = 5;
  937. X    x3 = 7 * 2;
  938. X    x2 = 9 + 1;
  939. X    globalvar = 22;
  940. X    g1 = 19 - 3;
  941. X    g2 = 79;
  942. X    verify(x1 == 5,  '201: x1 == 5');
  943. X    verify(x2 == 10, '202: x2 == 10');
  944. X    verify(x3 == 14, '203: x3 == 14');
  945. X    verify(g1 == 16, '204: g1 == 16');
  946. X    verify(g2 == 79, '205: g2 == 79');
  947. X    verify(globalvar == 22, '204: globalvar == 22');
  948. X    verify(getglobalvar() == 22, '205: getglobalvar() == 22');
  949. X    x1 = x2 + x3 + g1;
  950. X    verify(x1 == 40, '206: x1 == 40');
  951. X    g1 = x3 + g2;
  952. X    verify(g1 == 93, '207: g1 == 207');
  953. X    x1 = 5;
  954. X    verify(x1++ == 5, '208: x1++ == 5');
  955. X    verify(x1 == 6, '209: x1 == 6');
  956. X    verify(++x1 == 7, '210: ++x1 == 7');
  957. X    x1 += 3;
  958. X    verify(x1 == 10, '211: x1 == 10');
  959. X    x1 -= 6;
  960. X    verify(x1 == 4, '212: x1 == 4');
  961. X    x1 *= 3;
  962. X    verify(x1 == 12, '213: x1 == 12');
  963. X    x1 /= 4;
  964. X    verify(x1 == 3, '214: x1 == 3');
  965. X    x1 = x2 = x3;
  966. X    verify(x2 == 14, '215: x2 == 14');
  967. X    verify(x1 == 14, '216: x1 == 14');
  968. X    print '217: Ending test_variables';
  969. X}
  970. X
  971. X
  972. X/*
  973. X * Test logical AND and OR operators and short-circuit evaluation.
  974. X */
  975. Xdefine test_logicals()
  976. X{
  977. X    local    x;
  978. X
  979. X    print '300: Beginning test_logicals';
  980. X
  981. X    if (2 && 3)
  982. X        print '301: if (2 && 3)';
  983. X    else
  984. X        print '**** if (2 && 3)';
  985. X
  986. X    if (2 && 0)
  987. X        print '**** if (2 && 0)';
  988. X    else
  989. X        print '302: if (2 && 0)';
  990. X
  991. X    if (0 && 2)
  992. X        print '**** if (0 && 2)';
  993. X    else
  994. X        print '303: if (0 && 2)';
  995. X
  996. X    if (0 && 0)
  997. X        print '**** if (0 && 0)';
  998. X    else
  999. X        print '304: if (0 && 0)';
  1000. X
  1001. X    if (2 || 0)
  1002. X        print '305: if (2 || 0)';
  1003. X    else
  1004. X        print '**** if (2 || 0)';
  1005. X
  1006. X    if (0 || 2)
  1007. X        print '306: if (0 || 2)';
  1008. X    else
  1009. X        print '**** if (0 || 2)';
  1010. X
  1011. X    if (0 || 0)
  1012. X        print '**** if (0 || 0)';
  1013. X    else
  1014. X        print '307: if (0 || 0)';
  1015. X
  1016. X    x = 2 || 3; verify(x == 2, '308: (2 || 3) == 2');
  1017. X    x = 2 || 0; verify(x == 2, '309: (2 || 0) == 2');
  1018. X    x = 0 || 3; verify(x == 3, '310: (0 || 3) == 3');
  1019. X    x = 0 || 0; verify(x == 0, '311: (0 || 0) == 0');
  1020. X    x = 2 && 3; verify(x == 3, '312: (2 && 3) == 3');
  1021. X    x = 2 && 0; verify(x == 0, '313: (2 && 0) == 0');
  1022. X    x = 0 && 3; verify(x == 0, '314: (0 && 3) == 0');
  1023. X    x = 2 || error('2 || error()');
  1024. X    x = 0 && error('0 && error()');
  1025. X    print '315: Ending test_logicals';
  1026. X}
  1027. X
  1028. X
  1029. X/*
  1030. X * Test simple arithmetic operations and expressions.
  1031. X */
  1032. Xdefine test_arithmetic()
  1033. X{
  1034. X    print '400: Beginning test_arithmetic';
  1035. X    verify(3+4==7, '401: 3 + 4 == 7');
  1036. X    verify(4-1==3, '402: 4 - 1 == 3');
  1037. X    verify(2*3==6, '403: 2 * 3 == 6');
  1038. X    verify(8/4==2, '404: 8 / 4 == 2');
  1039. X    verify(2^3==8, '405: 2 ^ 3 == 8');
  1040. X    verify(9-4-2==3, '406: 9-4-2 == 3');
  1041. X    verify(9-4+2==7, '407: 9-4+2 == 6');
  1042. X    verify(-5+2==-3,  '408: -5+2 == -3');
  1043. X    verify(2*3+1==7, '409: 2*3+1 == 7');
  1044. X    verify(1+2*3==7, '410: 1+2*3 == 7');
  1045. X    verify((1+2)*3==9, '411: (1+2)*3 == 9');
  1046. X    verify(2*(3+1)==8, '412: 2*(3+1) == 8');
  1047. X    verify(9-(2+3)==4, '413: 9-(2+3) == 4');
  1048. X    verify(9+(2-3)==8, '414: 9+(2-3) == 8');
  1049. X    verify((2+3)*(4+5)==45, '415: (2+3)*(4+5) == 45');
  1050. X    verify(10/(2+3)==2, '416: 10/(2+3) == 2');
  1051. X    verify(12/3+4==8, '417: 12/3+4 == 8');
  1052. X    verify(6+12/3==10, '418: 6+12/3 == 10');
  1053. X    verify(2+3==1+4, '419: 2+3 == 1+4');
  1054. X    verify(-(2+3)==-5, '420: -(2+3) == -5');
  1055. X    verify(7&18==2,    '421: 7&18 == 2');
  1056. X    verify(3|17==19,   '422: 3|17 == 19');
  1057. X    verify(2&3|1==3,   '423: 2&3|1 == 3');
  1058. X    verify(2&(3|1)==2, '424: 2&(3|1) == 2');
  1059. X    verify(3<<4==48,   '425: 3<<4 == 48');
  1060. X    verify(5>>1==2,    '426: 5>>1 == 2');
  1061. X    verify(3<<-1==1,   '427: 3<<-1 == 1');
  1062. X    verify(5>>-2==20,  '428: 5>>-2 == 20');
  1063. X    verify(1<<2<<3==65536, '429: 1<<2<<3 == 65536');
  1064. X    verify((1<<2)<<3==32, '430: (1<<2)<<3 == 32');
  1065. X    verify(2^3^2==512, '431: 2^3^2 == 512');
  1066. X    verify((2^3)^2==64,'432: (2^3)^2 == 64');
  1067. X    print '433: Ending test_arithmetic';
  1068. X}
  1069. X
  1070. X
  1071. X/*
  1072. X * Test string constants and comparisons
  1073. X */
  1074. Xdefine test_strings()
  1075. X{
  1076. X    local x, y, z;
  1077. X
  1078. X    print '500: Beginning test_strings';
  1079. X    x = 'string';
  1080. X    y = "string";
  1081. X    z = x;
  1082. X    verify(z == "string", '501: z == "string"');
  1083. X    verify(z != "foo", '502: z != "foo"');
  1084. X    verify(z != 3, '503: z != 3');
  1085. X    verify('' == "", '504: \'\' == ""');
  1086. X    verify("a" == "a", '505: "a" == "a"');
  1087. X    verify("c" != "d", '506: "c" != "d"');
  1088. X    verify("" != "a", '507: "" != "a"');
  1089. X    verify("rs" < "rt", '508: "rs" < "rt"');
  1090. X    verify("rs" < "ss", '509: "rs < "ss"');
  1091. X    verify("rs" <= "rs", '510: "rs" <= "rs"');
  1092. X    verify("rs" <= "tu", '511: "rs" <= "tu"');
  1093. X    verify("rs" > "cd", '512: "rs" > "cd"');
  1094. X    verify("rs" >= "rs", '513: "rs" >= "rs"');
  1095. X    verify("rs" >= "cd", '514: "rs" >= "cd"'); 
  1096. X    verify("abc" > "ab", '515: "abc" > "ab"');
  1097. X    print '516: Ending test_strings';
  1098. X}
  1099. X
  1100. X
  1101. X/*
  1102. X * Do multiplication and division on three numbers in various ways
  1103. X * and verify the results agree.
  1104. X */
  1105. Xdefine muldivcheck(a, b, c, str)
  1106. X{
  1107. X    local    abc, acb, bac, bca, cab, cba;
  1108. X
  1109. X    abc = (a * b) * c;
  1110. X    acb = (a * c) * b;
  1111. X    bac = (b * a) * c;
  1112. X    bca = (b * c) * a;
  1113. X    cab = (c * a) * b;
  1114. X    cba = (c * b) * a;
  1115. X
  1116. X    if (abc != acb) print '**** abc != acb:', str;
  1117. X    if (acb != bac) print '**** acb != bac:', str;
  1118. X    if (bac != bca) print '**** bac != bca:', str;
  1119. X    if (bca != cab) print '**** bca != cab:', str;
  1120. X    if (cab != cba) print '**** cab != cba:', str;
  1121. X    if (abc/a != b*c) print '**** abc/a != bc:', str;
  1122. X    if (abc/b != a*c) print '**** abc/b != ac:', str;
  1123. X    if (abc/c != a*b) print '**** abc/c != ab:', str;
  1124. X    print str;
  1125. X}
  1126. X
  1127. X
  1128. X/*
  1129. X * Use the identity for squaring the sum of two squares to check
  1130. X * multiplication and squaring.
  1131. X */
  1132. Xdefine squarecheck(a, b, str)
  1133. X{
  1134. X    local    a2, b2, tab, apb, apb2, t;
  1135. X
  1136. X    a2 = a^2;
  1137. X    b2 = b^2;
  1138. X    tab = a * b * 2;
  1139. X    apb = a + b;
  1140. X    apb2 = apb^2;
  1141. X    if (a2 != a*a) print '**** a^2 != a*a:', str;
  1142. X    if (b2 != b*b) print '**** b^2 != b*b:', str;
  1143. X    if (apb2 != apb*apb) print '**** (a+b)^2 != (a+b)*(a+b):', str;
  1144. X    if (a2+tab+b2 != apb2) print '**** (a+b)^2 != a^2 + 2ab + b^2:', str;
  1145. X    if (a2/a != a) print '**** a^2/a != a:', str;
  1146. X    if (b2/b != b) print '**** b^2/b != b:', str;
  1147. X    if (apb2/apb != apb) print '**** (a+b)^2/(a+b) != a+b:', str;
  1148. X    if (a2*b2 != (a*b)^2) print '**** a^2*b^2 != (ab)^2:', str;
  1149. X    print str;
  1150. X}
  1151. X
  1152. X
  1153. X/*
  1154. X * Use the raising of numbers to large powers to check multiplication
  1155. X * and exponentiation.
  1156. X */
  1157. Xdefine powercheck(a, p1, p2, str)
  1158. X{
  1159. X    local    a1, a2, a3;
  1160. X
  1161. X    a1 = (a^p1)^p2;
  1162. X    a2 = (a^p2)^p1;
  1163. X    a3 = a^(p1*p2);
  1164. X    if (a1 != a2) print '**** (a^p1)^p2 != (a^p2)^p1:', str;
  1165. X    if (a1 != a3) print '**** (a^p1)^p2 != a^(p1*p2):', str;
  1166. X    print str;
  1167. X}
  1168. X
  1169. X
  1170. X/*
  1171. X * Test fraction reductions.
  1172. X * Arguments MUST be relatively prime.
  1173. X */
  1174. Xdefine fraccheck(a, b, c, str)
  1175. X{
  1176. X    local    ab, bc, ca, aoc, boc, aob;
  1177. X
  1178. X    ab = a * b;
  1179. X    bc = b * c;
  1180. X    ca = c * a;
  1181. X    aoc = ab / bc;
  1182. X    if (num(aoc) != a) print '**** num(aoc) != a:', str;
  1183. X    if (den(aoc) != c) print '**** den(aoc) != c:', str;
  1184. X    boc = ab / ca;
  1185. X    if (num(boc) != b) print '**** num(boc) != b:', str;
  1186. X    if (den(boc) != c) print '**** den(boc) != c:', str;
  1187. X    aob = ca / bc;
  1188. X    if (num(aob) != a) print '**** num(aob) != a:', str;
  1189. X    if (den(aob) != b) print '**** den(aob) != b:', str;
  1190. X    if (aob*boc != aoc) print '**** aob*boc != aoc;', str;
  1191. X    print str;
  1192. X}
  1193. X
  1194. X
  1195. X/*
  1196. X * Test multiplication and squaring algorithms.
  1197. X */
  1198. Xdefine algcheck(a, b, str)
  1199. X{
  1200. X    local    ss, ms, t1, t2, t3, t4, t5, t6, t7;
  1201. X    local    a1, a2, a3, a4, a5, a6, a7;
  1202. X    local    oldmul2, oldsq2;
  1203. X
  1204. X    oldmul2 = config("mul2", 2);
  1205. X    oldsq2 = config("sq2", 2);
  1206. X    a1 = a * b;
  1207. X    a2 = a * a;
  1208. X    a3 = b * b;
  1209. X    a4 = a^2;
  1210. X    a5 = b^2;
  1211. X    a6 = a2^2;
  1212. X    a7 = pmod(3,a-1,a);
  1213. X    for (ms = 2; ms < 20; ms++) {
  1214. X        for (ss = 2; ss < 20; ss++) {
  1215. X            config("mul2", ms);
  1216. X            config("sq2", ss);
  1217. X            t1 = a * b;
  1218. X            t2 = a * a;
  1219. X            t3 = b * b;
  1220. X            t4 = a^2;
  1221. X            t5 = b^2;
  1222. X            t6 = t2^2;
  1223. X            if (((ms + ss) % 37) == 4)
  1224. X                t7 = pmod(3,a-1,a);
  1225. X            if (t1 != a1) print '**** t1 != a1:', str;
  1226. X            if (t2 != a2) print '**** t2 != a2:', str;
  1227. X            if (t3 != a3) print '**** t3 != a3:', str;
  1228. X            if (t4 != a4) print '**** t4 != a4:', str;
  1229. X            if (t5 != a5) print '**** t5 != a5:', str;
  1230. X            if (t6 != a6) print '**** t6 != a6:', str;
  1231. X            if (t7 != a7) print '**** t7 != a7:', str;
  1232. X        }
  1233. X    }
  1234. X    config("mul2", oldmul2);
  1235. X    config("sq2", oldsq2);
  1236. X    print str;
  1237. X}
  1238. X
  1239. X
  1240. X/*
  1241. X * Test big numbers using some identities.
  1242. X */
  1243. Xdefine test_bignums()
  1244. X{
  1245. X    local    a, b, c, d;
  1246. X
  1247. X    print '600: Beginning test_bignums';
  1248. X    a = 64357824568234938591;
  1249. X    b = 12764632632458756817;
  1250. X    c = 43578234973856347982;
  1251. X    muldivcheck(a, b, c, '601: muldivcheck 1');
  1252. X    a = 3^100;
  1253. X    b = 5^97;
  1254. X    c = 7^88;
  1255. X    muldivcheck(a, b, c, '602: muldivcheck 2');
  1256. X    a = 2^160 - 1;
  1257. X    b = 2^161 - 1;
  1258. X    c = 2^162 - 1;
  1259. X    muldivcheck(a, b, c, '603: muldivcheck 3');
  1260. X    a = 3^35 / 5^35;
  1261. X    b = 7^35 / 11^35;
  1262. X    c = 13^35 / 17^35;
  1263. X    muldivcheck(a, b, c, '604: muldivcheck 4');
  1264. X    a = (10^97-1) / 9;
  1265. X    b = (10^53-1) / 9;
  1266. X    c = (10^37-1) / 9;
  1267. X    muldivcheck(a, b, c, '605: muldivcheck 5');
  1268. X    a = 17^50;
  1269. X    b = 19^47;
  1270. X    squarecheck(a, b, '606: squarecheck 1');
  1271. X    a = 2^111-1;
  1272. X    b = 2^17;
  1273. X    squarecheck(a, b, '607: squarecheck 2');
  1274. X    a = 23^43 / 29^43;
  1275. X    b = 31^42 / 37^29;
  1276. X    squarecheck(a, b, '608: squarecheck 3');
  1277. X    a = 4657892345743659834657238947854639;
  1278. X    b = 43784356784365893467659347867689;
  1279. X    squarecheck(a, b, '609: squarecheck 4');
  1280. X    a = (10^80-1) / 9;
  1281. X    b = (10^50-1) / 9;
  1282. X    squarecheck(a, b, '610: squarecheck 5');
  1283. X    a = 101^99;
  1284. X    b = -a;
  1285. X    squarecheck(a, b, '611: squarecheck 6');
  1286. X    a = (10^19-1) / 9;
  1287. X    verify(ptest(a, 20), '612: primetest R19');
  1288. X    a = (10^23-1) / 9;
  1289. X    verify(ptest(a, 20), '613: primetest R23');
  1290. X    a = 2^127 - 1;
  1291. X    verify(ptest(a, 1), '614: primetest M127');
  1292. X    a = 2^521 - 1;
  1293. X    verify(ptest(a, 1), '615: primetest M521');
  1294. X    powercheck(17, 127, 30, '616: powercheck 1');
  1295. X    powercheck(111, 899, 6, '617: powercheck 2');
  1296. X    powercheck(3, 87, 89, '618: powercheck 3');
  1297. X    fraccheck(3^200, 5^173, 7^138, '619: fraccheck 1');
  1298. X    fraccheck(11^100, 12^98, 13^121, '620: fraccheck 2');
  1299. X    fraccheck(101^270, 103^111, 105^200, '621: fraccheck 3');
  1300. X    a = 0xffff0000ffffffff00000000ffff0000000000000000ffff;
  1301. X    b = 0x555544440000000000000000000000000000000011112222333344440000;
  1302. X    c = 0x999911113333000011111111000022220000000000000000333300000000ffff;
  1303. X    d = 0x3333ffffffff0000000000000000ffffffffffffffff000000000000;
  1304. X    algcheck(a, a, '622: algcheck 1');
  1305. X    algcheck(a, b, '623: algcheck 2');
  1306. X    algcheck(a, c, '624: algcheck 3');
  1307. X    algcheck(a, d, '625: algcheck 4');
  1308. X    algcheck(b, b, '626: algcheck 5');
  1309. X    algcheck(b, c, '627: algcheck 6');
  1310. X    algcheck(b, d, '628: algcheck 7');
  1311. X    algcheck(c, c, '629: algcheck 8');
  1312. X    algcheck(c, d, '630: algcheck 9');
  1313. X    algcheck(d, d, '631: algcheck 10');
  1314. X    print '632: Ending test_bignums';
  1315. X}
  1316. X
  1317. X
  1318. X/*
  1319. X * Test many of the built-in functions.
  1320. X */
  1321. Xdefine test_functions()
  1322. X{
  1323. X    print '700: Beginning test_functions';
  1324. X    verify(abs(3) == 3,    '701: abs(3) == 3');
  1325. X    verify(abs(-4) == 4,   '702: abs(-4) == 4');
  1326. X    verify(avg(7) == 7,    '703: avg(7) == 7');
  1327. X    verify(avg(3,5) == 4,  '704: avg(3,5) == 4');
  1328. X    verify(cmp(2,3) == -1, '705: cmp(2,3) == -1');
  1329. X    verify(cmp(6,6) == 0,  '706: cmp(6,6) == 0');
  1330. X    verify(cmp(7,4) == 1,  '707: cmp(7,4) == 1');
  1331. X    verify(comb(9,9) == 1, '708: comb(9,9) == 1');
  1332. X    verify(comb(5,2) == 10,'709: comb(5,2) == 10');
  1333. X    verify(conj(4) == 4,   '710: conj(4) == 4');
  1334. X    verify(conj(2-3i) == 2+3i, '711: conj(2-3i) == 2+3i');
  1335. X    verify(den(17) == 1,   '712: den(17) == 1');
  1336. X    verify(den(3/7) == 7,  '713: den(3/7) == 7');
  1337. X    verify(den(-2/3) == 3, '714: den(-2/3) == 3');
  1338. X    verify(digits(0) == 1, '715: digits(0) == 1');
  1339. X    verify(digits(9) == 1, '716: digits(9) == 1');
  1340. X    verify(digits(10) == 2,'717: digits(10) == 2');
  1341. X    verify(digits(-691) == 3, '718: digits(-691) == 3');
  1342. X    verify(eval('2+3') == 5, "719: eval('2+3') == 5");
  1343. X    verify(fcnt(11,3) == 0,'720: fcnt(11,3) == 0');
  1344. X    verify(fcnt(18,3) == 2,'721: fcnt(18,3) == 2');
  1345. X    verify(fib(0) == 0,    '722: fib(0) == 0');
  1346. X    verify(fib(1) == 1,    '723: fib(1) == 1');
  1347. X    verify(fib(9) == 34,   '724: fib(9) == 34');
  1348. X    verify(frem(12,5) == 12, '725: frem(12,5) == 12');
  1349. X    verify(frem(45,3) == 5, '726: frem(45,3) == 5');
  1350. X    verify(fact(0) == 1,   '727: fact(0) == 1');
  1351. X    verify(fact(1) == 1,   '728: fact(1) == 1');
  1352. X    verify(fact(5) == 120, '729: fact(5) == 120');
  1353. X    verify(frac(3) == 0,   '730: frac(3) == 0');
  1354. X    verify(frac(2/3) == 2/3, '731: frac(2/3) == 2/3');
  1355. X    verify(frac(17/3) == 2/3, '732: frac(17/3) == 2/3');
  1356. X    verify(gcd(0,3) == 3,  '733: gcd(0,3) == 3');
  1357. X    verify(gcd(1,12) == 1, '734: gcd(1,12) == 1');
  1358. X    verify(gcd(11,7) == 1, '735: gcd(11,7) == 1');
  1359. X    verify(gcd(20,65) == 5, '736: gcd(20,65) == 5');
  1360. X    verify(gcdrem(20,3) == 20, '737: gcdrem(20,3) == 20');
  1361. X    verify(gcdrem(100,6) == 25, '738: gcdrem(100,6) == 25');
  1362. X    verify(highbit(1) == 0, '739: highbit(1) == 0');
  1363. X    verify(highbit(15) == 3, '740: highbit(15) == 3');
  1364. X    verify(hypot(3,4) == 5, '741: hypot(3,4) == 5');
  1365. X    verify(ilog(90,3) == 4, '742: ilog(90,3) == 4');
  1366. X    verify(ilog10(123) == 2, '743: ilog10(123) == 2');
  1367. X    verify(ilog2(17) == 4, '744: ilog2(17) == 4');
  1368. X    verify(im(3) == 0,     '745: im(3) == 0');
  1369. X    verify(im(2+3i) == 3,  '746: im(2+3i) == 3');
  1370. X    verify(int(5) == 5,    '757: int(5) == 5');
  1371. X    verify(int(19/3) == 6, '758: int(19/3) == 6');
  1372. X    verify(inverse(3/2) == 2/3, '759: inverse(3/2) == 2/3');
  1373. X    verify(iroot(18,2) == 4, '760: iroot(18,2) == 4');
  1374. X    verify(iroot(100,3) == 4, '761: iroot(100,3) == 4');
  1375. X    verify(iseven(10) == 1, '762: iseven(10) == 1');
  1376. X    verify(iseven(13) == 0, '763: iseven(13) == 0');
  1377. X    verify(iseven('a') == 0, "764: iseven('a') == 0");
  1378. X    verify(isint(7) == 1,  '765: isint(7) == 1');
  1379. X    verify(isint(19/2) == 0, '766: isint(19/2) == 0');
  1380. X    verify(isint('a') == 0, "767: isint('a') == 0");
  1381. X    verify(islist(3) == 0, '768: islist(3) == 0');
  1382. X    verify(islist(list(2,3)) == 1, '769: islist(list(2,3)) == 1');
  1383. X    verify(ismat(3) == 0, '770: ismat(3) == 0');
  1384. X    verify(ismult(7,3) == 0, '771: ismult(7,3) == 0');
  1385. X    verify(ismult(15,5) == 1, '772: ismult(15,5) == 1');
  1386. X    verify(isnull(3) == 0, '773: isnull(3) == 0');
  1387. X    verify(isnull(null()) == 1, '774: isnull(null()) == 1');
  1388. X    verify(isnum(2/3) == 1, '775: isnum(2/3) == 1');
  1389. X    verify(isnum('xx') == 0, "776: isnum('xx') == 0");
  1390. X    verify(isobj(3) == 0, '777: isobj(3) == 0');
  1391. X    verify(isodd(7) == 1, '778: isodd(7) == 1');
  1392. X    verify(isodd(8) == 0, '779: isodd(8) == 0');
  1393. X    verify(isodd('x') == 0, "780: isodd('a') == 0");
  1394. X    verify(isqrt(27) == 5, '781: isqrt(27) == 5');
  1395. X    verify(isreal(3) == 1, '782: isreal(3) == 1');
  1396. X    verify(isreal('x') == 0, "783: isreal('x') == 0");
  1397. X    verify(isreal(2+3i) == 0, '784: isreal(2+3i) == 0');
  1398. X    verify(isstr(5) == 0,  '785: isstr(5) == 0');
  1399. X    verify(isstr('foo') == 1, "786: isstr('foo') == 1");
  1400. X    verify(isrel(10,14) == 0, '787: isrel(10,14) == 0');
  1401. X    verify(isrel(15,22) == 1, '788: isrel(15,22) == 1');
  1402. X    verify(issimple(6) == 1, '789: issimple(6) == 1');
  1403. X    verify(issimple(3-2i) == 1, '790: issimple(3-2i) == 1');
  1404. X    verify(issimple(list(5)) == 0, '791: issimple(list(5)) == 0');
  1405. X    verify(issq(26) == 0, '792: issq(26) == 0');
  1406. X    verify(issq(9/4) == 1, '793: issq(9/4) == 1');
  1407. X    verify(istype(9,4) == 1, '795: istype(9,4) == 1');
  1408. X    verify(istype(3,'xx') == 0, "796: istype(3,'xx') == 0");
  1409. X    verify(jacobi(5,11) == 1, '797: jacobi(2,7) == 1');
  1410. X    verify(jacobi(6,13) == -1, '798: jacobi(6,13) == 0');
  1411. X    verify(lcm(3,4,5,6) == 60, '799: lcm(3,4,5,6) == 60');
  1412. X    verify(lcmfact(8) == 840, '800: lcmfact(8) == 840');
  1413. X    verify(lfactor(21,5) == 3, '801: lfactor(21,5) == 3');
  1414. X    verify(lfactor(97,20) == 1, '802: lfactor(97,20) == 1');
  1415. X    verify(lowbit(12) == 2, '803: lowbit(12) == 2');
  1416. X    verify(lowbit(17) == 0, '804: lowbit(17) == 0');
  1417. X    verify(ltol(1) == 0, '805: ltol(1) == 0');
  1418. X    verify(max(3,-9,7,4) == 7, '806: max(3,-9,7,4) == 7');
  1419. X    verify(meq(13,33,10) == 1, '807: meq(13,33,10) == 1');
  1420. X    verify(meq(7,19,11) == 0, '808: meq(7,19,11) == 0');
  1421. X    verify(min(9,5,12) == 5, '809: min(9,5,12) == 5');
  1422. X    verify(minv(13,97) == 15, '810: minv(13,97) == 15');
  1423. X    verify(mne(16,37,10) == 1, '811: mne(16,37,10) == 1');
  1424. X    verify(mne(46,79,11) == 0, '812: mne(46,79,11) == 0');
  1425. X    verify(norm(4) == 16,   '813: norm(4) == 16');
  1426. X    verify(norm(2-3i) == 13, '814: norm(2-3i) == 13');
  1427. X    verify(num(7) == 7,     '815: num(7) == 7');
  1428. X    verify(num(11/4) == 11, '816: num(11/4) == 11');
  1429. X    verify(num(-9/5) == -9, '817: num(-9/5) == -9');
  1430. X    verify(char(ord('a')+2) == 'c', "818: char(ord('a')+2) == 'c'");
  1431. X    verify(perm(7,3) == 210, '819: perm(7,3) == 210');
  1432. X    verify(pfact(10) == 210, '820: pfact(10) == 210');
  1433. X    verify(places(3/7) == -1, '821: places(3/7) == -1');
  1434. X    verify(places(.347) == 3, '822: places(.347) == 3');
  1435. X    verify(places(17) == 0, '823: places(17) == 0');
  1436. X    verify(pmod(3,36,37) == 1, '824: pmod(3,36,37) == 1');
  1437. X    verify(poly(2,3,5,2) == 19, '825; poly(2,3,5,2) == 19');
  1438. X    verify(ptest(101,10) == 1, '826: ptest(101,10) == 1');
  1439. X    verify(ptest(221,30) == 0, '827: ptest(221,30) == 0');
  1440. X    verify(re(9) == 9,       '828: re(9) == 9');
  1441. X    verify(re(-7+3i) == -7,  '829: re(-7+3i) == -7');
  1442. X    verify(scale(3,4) == 48, '830: scale(3,4) == 48');
  1443. X    verify(sgn(-4) == -1,    '831: sgn(-4) == -1');
  1444. X    verify(sgn(0) == 0,      '832: sgn(0) == 0');
  1445. X    verify(sgn(3) == 1,      '833: sgn(3) == 1');
  1446. X    verify(size(7) == 1,     '834: size(7) == 1');
  1447. X    verify(sqrt(121) == 11,  '835: sqrt(121) == 11');
  1448. X    verify(ssq(2,3,4) == 29, '836: ssq(2,3,4) == 29');
  1449. X    verify(str(45) == '45',  "837; str(45) == '45'");
  1450. X    verify(strcat('a','bc','def')=='abcdef',"838; strcat('a','bc','def')=='abcdef'");
  1451. X    verify(strlen('') == 0,  "839: strlen('') == 0");
  1452. X    verify(strlen('abcd') == 4, "840: strlen('abcd') == 4");
  1453. X    verify(substr('abcd',2,1) == 'b', "841: substr('abcd',2,1) == 'b'");
  1454. X    verify(substr('abcd',3,4) == 'cd', "842: substr('abcd',3,4) == 'cd'");
  1455. X    verify(substr('abcd',1,3) == 'abc', "843: substr('abcd',1,3) == 'abc'");
  1456. X    verify(xor(17,17) == 0,  '844: xor(17,17) == 0');
  1457. X    verify(xor(12,5) == 9,   '845: xor(12,5) == 9');
  1458. X    verify(mmin(3,7) == 3, '846: mmin(3,7) == 3');
  1459. X    verify(mmin(4,7) == -3, '847: mmin(4,7) == -3');
  1460. X    verify(digit(123,2) == 1, '848: digit(123,2) == 1');
  1461. X    print '849: Ending test_functions';
  1462. X}
  1463. X
  1464. X
  1465. Xprint '001: Beginning regression tests';
  1466. Xprint '002: Within each section, output should be numbered sequentially';
  1467. Xprint;
  1468. Xreturn test_booleans();
  1469. Xprint;
  1470. Xreturn test_variables();
  1471. Xprint;
  1472. Xreturn test_logicals();
  1473. Xprint;
  1474. Xreturn test_arithmetic();
  1475. Xprint;
  1476. Xreturn test_strings();
  1477. Xprint;
  1478. Xreturn test_bignums();
  1479. Xprint;
  1480. Xreturn test_functions();
  1481. END_OF_FILE
  1482. if test 19555 -ne `wc -c <'lib/regress.cal'`; then
  1483.     echo shar: \"'lib/regress.cal'\" unpacked with wrong size!
  1484. fi
  1485. # end of 'lib/regress.cal'
  1486. fi
  1487. echo shar: End of archive 8 \(of 21\).
  1488. cp /dev/null ark8isdone
  1489. MISSING=""
  1490. 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
  1491.     if test ! -f ark${I}isdone ; then
  1492.     MISSING="${MISSING} ${I}"
  1493.     fi
  1494. done
  1495. if test "${MISSING}" = "" ; then
  1496.     echo You have unpacked all 21 archives.
  1497.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1498. else
  1499.     echo You still need to unpack the following archives:
  1500.     echo "        " ${MISSING}
  1501. fi
  1502. ##  End of shell archive.
  1503. exit 0
  1504.