home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Utilities / Calc / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-12  |  17.7 KB  |  824 lines  |  [TEXT/????]

  1. /*
  2.  * Copyright (c) 1992 David I. Bell
  3.  * Permission is granted to use, distribute, or modify this source,
  4.  * provided that this copyright notice remains intact.
  5.  *
  6.  * Nested input source file reader.
  7.  * For terminal input, this also provides a simple command stack.
  8.  */
  9.  
  10. #include <ctype.h>
  11. #ifndef MACINTOSH
  12. #include <pwd.h>
  13. #endif
  14. #include "calc.h"
  15. #include "config.h"
  16.  
  17. #define MAXSAVE        255    /* number of saved terminal lines */
  18. #define DEFHIST        20    /* default history length display */
  19. #define TTYSIZE        100    /* reallocation size for terminal buffers */
  20. #define DEPTH        10    /* maximum depth of input */
  21. #define IS_READ        1    /* reading normally */
  22. #define IS_REREAD    2    /* reread current character */
  23. #define chartoint(ch)    ((ch) & 0xff)    /* make sure char is not negative */
  24.  
  25.  
  26. typedef struct {
  27.     short i_state;        /* state (read, reread) */
  28.     short i_char;        /* currently read char */
  29.     long i_line;        /* line number */
  30.     char *i_str;        /* current string for input (if not NULL) */
  31.     char *i_origstr;    /* original string so it can be freed */
  32.     char *i_ttystr;        /* current character of tty line (or NULL) */
  33.     FILE *i_fp;        /* current file for input (if not NULL) */
  34.     char *i_name;        /* file name if known */
  35. } INPUT;
  36.  
  37.  
  38. static int stacksize;        /* number of elements in command stack */
  39. static int stackindex;        /* current index into command stack */
  40. static int cmdsize;        /* current max size of terminal buffer */
  41. static int editsize;        /* current max size of edit buffer */
  42. static int linesize;        /* current max size of input line */
  43. static char *linebuf;        /* current input line buffer */
  44. static char *cmdbuf;        /* current command line buffer */
  45. static char *editbuf;        /* edit buffer */
  46. static char **cmdstack;        /* command stack */
  47. static char *prompt;        /* current prompt for terminal */
  48. static BOOL noprompt;        /* TRUE if should not print prompt */
  49.  
  50. static int depth;        /* current input depth */
  51. static INPUT *cip;        /* current input source */
  52. static INPUT inputs[DEPTH];    /* input sources */
  53.  
  54.  
  55. static char *findhistory(), *edithistory();
  56. static int openfile();
  57. static int ttychar();
  58.  
  59. #ifndef MACINTOSH
  60. extern struct passwd *getpwnam();
  61. #endif
  62.  
  63. /*
  64.  * Open an input file by possibly searching through a path list
  65.  * and also possibly applying the specified extension.  For example:
  66.  * opensearchfile("barf", ".:/tmp", ".c") searches in order for the
  67.  * files "./barf", "./barf.c", "/tmp/barf", and "/tmp/barf.c".
  68.  *
  69.  * Returns -1 if all specified files cannot be opened.
  70.  */
  71. opensearchfile(name, pathlist, extension)
  72.     char *name;        /* file name to be read */
  73.     char *pathlist;        /* list of colon separated paths (or NULL) */
  74.     char *extension;    /* extra extension to try (or NULL) */
  75. {
  76.     int i;
  77.     char *cp;
  78.     char path[PATHSIZE+1];    /* name being searched for */
  79.  
  80.     /*
  81.      * Don't try the extension if the filename already contains it.
  82.      */
  83.     if (extension) {
  84.         i = strlen(name) - strlen(extension);
  85.         if ((i >= 0) && (strcmp(&name[i], extension) == 0))
  86.             extension = NULL;
  87.     }
  88.     /*
  89.      * If the name is absolute, or if there is no path list, then
  90.      * make one which just searches for the name straight.  Then
  91.      * search through the path list for the file, without and with
  92.      * the specified extension.
  93.      */
  94.     if (name[0] == PATHCHAR || 
  95.         name[0] == HOMECHAR || 
  96.         (name[0] == DOTCHAR && name[1] == PATHCHAR) || 
  97.         pathlist == NULL) {
  98.         pathlist = "";
  99.     }
  100.     pathlist--;
  101.     do {
  102.         pathlist++;
  103.         cp = path;
  104.         while (*pathlist && (*pathlist != LISTCHAR))
  105.             *cp++ = *pathlist++;
  106.         if (cp != path)
  107.             *cp++ = PATHCHAR;
  108.         strcpy(cp, name);
  109.         i = openfile(path);
  110.         if ((i < 0) && extension) {
  111.             strcat(path, extension);
  112.             i = openfile(path);
  113.         }
  114.     } while ((i < 0) && *pathlist);
  115.     return i;
  116. }
  117.  
  118.  
  119. /*
  120.  * Given a filename with a leading ~, expand it into a home directory for 
  121.  * that user.  This function will malloc the space for the expanded path.
  122.  *
  123.  * If the path is just ~, or begins with ~/, expand it to the home
  124.  * directory of the current user.  If the environment variable $HOME
  125.  * is known, it will be used, otherwise the password file will be
  126.  * consulted.
  127.  *
  128.  * If the path is just ~username, or ~username/, expand it to the home
  129.  * directory of that user by looking it up in the password file.
  130.  *
  131.  * If the password file must be consulted and the username is not found
  132.  * a NULL pointer is returned.
  133.  */
  134. static char *
  135. homeexpand(name)
  136.     char *name;        /* a filename with a leading ~ */
  137. {
  138.     struct passwd *ent;    /* password entry */
  139.     char *home2;        /* fullpath of the home directory */
  140.     char *fullpath;        /* the malloced expanded path */
  141.     char *after;        /* after the ~user or ~ */
  142.     char username[PATHSIZE+1];    /* extratced username */
  143.  
  144.     /* firewall */
  145.     if (name[0] != HOMECHAR)
  146.         return NULL;
  147.  
  148.     /*
  149.      * obtain the home directory component
  150.      */
  151.     switch (name[1]) {
  152.     case PATHCHAR:        /* ~/... */
  153.     case '\0':        /* ~ */
  154.         home2 = home;
  155.         after = name+1;
  156.         break;
  157.     default:        /* ~username or ~username/... */
  158.  
  159.         /* extract the username after the ~ */
  160.         after = (char *)strchr(name+2, PATHCHAR);
  161.         if (after == NULL) {
  162.             /* path is just ~username */
  163. #ifndef MACINTOSH            
  164.             ent = getpwnam(name+1);
  165. #else
  166.             ent = NULL;
  167. #endif            
  168.             if (ent == NULL) {
  169.                 /* unknown user */
  170.                 return NULL;
  171.             }
  172.             /* just malloc the home directory and return it */
  173. #ifdef MACINTOSH
  174.             fullpath = ":";    
  175. #else            
  176.             fullpath = (char *)malloc(strlen(ent->pw_dir)+1);
  177.             strcpy(fullpath, ent->pw_dir);
  178. #endif
  179.             return fullpath;
  180.         }
  181.         if (after-name > PATHSIZE+1) {
  182.             /* username is too big */
  183.             return NULL;
  184.         }
  185.         strncpy(username, name+1, after-name-1);
  186.         username[after-name-1] = '\0';
  187.  
  188.         /* get that user's home directory */
  189. #ifndef MACINTOSH        
  190.         ent = getpwnam(username);
  191. #else
  192.         ent = NULL;
  193. #endif        
  194.         if (ent == NULL) {
  195.             /* unknown user */
  196.             return NULL;
  197.         }
  198. #ifndef MACINTOSH        
  199.         home2 = ent->pw_dir;
  200. #else
  201.         home2 = ":";
  202. #endif        
  203.         break;
  204.     }
  205.  
  206.     /*
  207.      * build the fullpath given the home directory
  208.      */
  209.     fullpath = (char *)malloc(strlen(home2)+strlen(after)+1);
  210.     sprintf(fullpath, "%s%s", home2, after);
  211.     return fullpath;
  212. }
  213.  
  214.  
  215. /*
  216.  * f_open - ~-expand a filename and fopen() it
  217.  */
  218. FILE *
  219. f_open(name, mode)
  220.     char *name;        /* the filename to open */
  221.     char *mode;        /* the fopen mode to use */
  222. {
  223.     FILE *fp;        /* open file descriptor */
  224.     char *fullname;        /* file name with HOMECHAR expansion */
  225.  
  226.     /*
  227.      * expand ~ if needed
  228.      */
  229.     if (name[0] == HOMECHAR) {
  230.         fullname = homeexpand(name);
  231.         if (fullname == NULL)
  232.             return NULL;
  233.         fp = fopen(fullname, mode);
  234.         free(fullname);
  235.     } else {
  236.         fp = fopen(name, mode);
  237.     }
  238.     return fp;
  239. }
  240.  
  241.  
  242. /*
  243.  * Setup for reading from a input file.
  244.  * Returns -1 if file could not be opened.
  245.  */
  246. static
  247. openfile(name)
  248.     char *name;        /* file name to be read */
  249. {
  250.     FILE *fp;        /* open file descriptor */
  251.  
  252.     if (depth >= DEPTH)
  253.          return -1;
  254.     fp = f_open(name, "r");
  255.     if (fp == NULL)
  256.          return -1;
  257.     cip++;
  258.     cip->i_state = IS_READ;
  259.     cip->i_char = '\0';
  260.     cip->i_str = NULL;
  261.     cip->i_origstr = NULL;
  262.     cip->i_ttystr = NULL;
  263.     cip->i_fp = fp;
  264.     cip->i_line = 1;
  265.     cip->i_name = (char *)malloc(strlen(name) + 1);
  266.     strcpy(cip->i_name, name);
  267.     depth++;
  268.     return 0;
  269. }
  270.  
  271.  
  272. /*
  273.  * Open a string for scanning. String is ended by a null character.
  274.  * String is copied into local memory so it can be trashed afterwards.
  275.  * Returns -1 if cannot open string.
  276.  */
  277. openstring(str)
  278.     char *str;        /* string to be opened */
  279. {
  280.     char *cp;        /* copied string */
  281.  
  282.     if ((depth >= DEPTH) || (str == NULL))
  283.          return -1;
  284.     cp = (char *)malloc(strlen(str) + 1);
  285.     if (cp == NULL)
  286.          return -1;
  287.     strcpy(cp, str);
  288.     cip++;
  289.     cip->i_state = IS_READ;
  290.     cip->i_char = '\0';
  291.     cip->i_str = cp;
  292.     cip->i_origstr = cp;
  293.     cip->i_fp = NULL;
  294.     cip->i_name = NULL;
  295.     cip->i_ttystr = NULL;
  296.     cip->i_line = 1;
  297.     depth++;
  298.     return 0;
  299. }
  300.  
  301.  
  302. /*
  303.  * Set to read input from the terminal.
  304.  * Returns -1 if there is no more depth for input.
  305.  */
  306. openterminal()
  307. {
  308.     if (depth >= DEPTH)
  309.          return -1;
  310.     if (cmdsize == 0) {
  311.         cmdbuf = (char *)malloc(TTYSIZE + 1);
  312.         if (cmdbuf == NULL)
  313.             return -1;
  314.         cmdsize = TTYSIZE;
  315.     }
  316.     if (editsize == 0) {
  317.         editbuf = (char *)malloc(TTYSIZE + 1);
  318.         if (editbuf == NULL)
  319.             return -1;
  320.         editsize = TTYSIZE;
  321.     }
  322.     if (stacksize == 0) {
  323.         cmdstack = (char **) malloc(MAXSAVE * sizeof(char *));
  324.         if (cmdstack == NULL)
  325.             return -1;
  326.         stacksize = MAXSAVE;
  327.         for (stackindex = 0; stackindex < MAXSAVE; stackindex++)
  328.             cmdstack[stackindex] = NULL;
  329.         stackindex = 0;
  330.     }
  331.     cip++;
  332.     cip->i_state = IS_READ;
  333.     cip->i_char = '\0';
  334.     cip->i_str = NULL;
  335.     cip->i_origstr = NULL;
  336.     cip->i_ttystr = NULL;
  337.     cip->i_fp = NULL;
  338.     cip->i_name = NULL;
  339.     cip->i_line = 1;
  340.     depth++;
  341.     return 0;
  342. }
  343.  
  344.  
  345. /*
  346.  * Close the current input source.
  347.  */
  348. static void
  349. closeinput()
  350. {
  351.     if (depth <= 0)
  352.         return;
  353.     if (cip->i_origstr)
  354.         free(cip->i_origstr);
  355.     if (cip->i_fp)
  356.         fclose(cip->i_fp);
  357.     if (cip->i_name)
  358.         free(cip->i_name);
  359.     cip--;
  360.     depth--;
  361. }
  362.  
  363.  
  364. /*
  365.  * Reset the input sources back to the initial state.
  366.  */
  367. void
  368. resetinput()
  369. {
  370.     while (depth > 0)
  371.         closeinput();
  372.     cip = inputs;
  373.     noprompt = FALSE;
  374. }
  375.  
  376.  
  377. /*
  378.  * Set the prompt for terminal input.
  379.  */
  380. void
  381. setprompt(str)
  382.     char *str;
  383. {
  384.     prompt = str;
  385.     noprompt = FALSE;
  386. }
  387.  
  388.  
  389. /*
  390.  * Read the next character from the current input source.
  391.  * End of file returns newline character and closes current input source,
  392.  * except for the last input source, which returns EOF.
  393.  */
  394. int
  395. nextchar()
  396. {
  397.     int ch;            /* current input character */
  398.  
  399.     if (depth == 0)        /* input finished */
  400.          return EOF;
  401.     if (cip->i_state == IS_REREAD) {    /* rereading current char */
  402.          ch = cip->i_char;
  403.          cip->i_state = IS_READ;
  404.          if (ch == '\n')
  405.             cip->i_line++;
  406.          return ch;
  407.     }
  408.     if (cip->i_str) {        /* from string */
  409.         ch = chartoint(*cip->i_str++);
  410.         if (ch == '\0')
  411.             ch = EOF;
  412.     } else if (cip->i_fp) {        /* from file */
  413.         ch = fgetc(cip->i_fp);
  414.     } else {            /* from terminal */
  415.         ch = ttychar();
  416.     }
  417.     if (ch == EOF) {        /* fix up end of file */
  418.         closeinput();
  419.         ch = '\n';
  420.         if (depth <= 0)
  421.             ch = EOF;
  422.     }
  423.     if (depth > 0)
  424.         cip->i_char = (char)ch;    /* save for rereads */
  425.     if (ch == '\n')
  426.         cip->i_line++;
  427.     return ch;
  428. }
  429.  
  430.  
  431. /*
  432.  * Read in the next line of input from the current input source.
  433.  * The line is terminated with a null character, and does not contain
  434.  * the final newline character.  The returned string is only valid
  435.  * until the next such call, and so must be copied if necessary.
  436.  * Returns NULL on end of file.
  437.  */
  438. char *
  439. nextline()
  440. {
  441.     char *cp;
  442.     int ch;
  443.     int len;
  444.  
  445.     cp = linebuf;
  446.     if (linesize == 0) {
  447.         cp = (char *)malloc(TTYSIZE + 1);
  448.         if (cp == NULL)
  449.             error("Cannot allocate line buffer");
  450.         linebuf = cp;
  451.         linesize = TTYSIZE;
  452.     }
  453.     len = 0;
  454.     for (;;) {
  455.         noprompt = TRUE;
  456.         ch = nextchar();
  457.         noprompt = FALSE;
  458.         if (ch == EOF)
  459.             return NULL;
  460.         if (ch == '\0')
  461.             continue;
  462.         if (ch == '\n')
  463.             break;
  464.         if (len >= linesize) {
  465.             cp = (char *)realloc(cp, linesize + TTYSIZE + 1);
  466.             if (cp == NULL)
  467.                 error("Cannot realloc line buffer");
  468.             linebuf = cp;
  469.             linesize += TTYSIZE;
  470.         }
  471.         cp[len++] = (char)ch;
  472.     }
  473.     cp[len] = '\0';
  474.     return linebuf;
  475. }
  476.  
  477.  
  478. /*
  479.  * Read the next character from the terminal.
  480.  * This works by reading in a complete line from the terminal at once,
  481.  * and then returns the characters one by one as required.  If the line
  482.  * begins with the special command stack history character, then it is
  483.  * replaced by some previous command line.  The saved line is then put on
  484.  * the command stack for future reference.
  485.  */
  486. static int
  487. ttychar()
  488. {
  489.     int ch;            /* current char */
  490.     int len;        /* length of current command */
  491.     char *newbuf;        /* new buffer */
  492.  
  493.     /*
  494.      * If we have more to read from the saved command line, then do that.
  495.      * When we see a newline character, then clear the pointer so we will
  496.      * read a new line on the next call.
  497.      */
  498.     if (cip->i_ttystr) {
  499.         ch = chartoint(*cip->i_ttystr++);
  500.         if (ch == '\n')
  501.             cip->i_ttystr = NULL;
  502.         return ch;
  503.     }
  504.     /*
  505.      * We need another complete line.  Print the prompt string, then read
  506.      * in a new command line, expanding the command buffer as necessary.
  507.      */
  508.     if (!noprompt) {
  509.         printf("%02d%s", stackindex + 1, prompt);
  510.         fflush(stdout);
  511.     }
  512.     abortlevel = 0;
  513.     len = 0;
  514.     do {
  515.         if (len >= cmdsize) {
  516.             newbuf = (char *)realloc(cmdbuf, cmdsize + TTYSIZE + 1);
  517.             if (newbuf == NULL) {
  518.                 perror("Cannot reallocate terminal buffer");
  519.                 return EOF;
  520.             }
  521.             cmdbuf = newbuf;
  522.             cmdsize += TTYSIZE;
  523.         }
  524.         inputwait = TRUE;
  525.         ch = getchar();
  526.         inputwait = FALSE;
  527.         if (ch == EOF)
  528.             return EOF;
  529.         ch = chartoint(ch);
  530.         if (ch)
  531.             cmdbuf[len++] = (char)ch;
  532.     } while (ch != '\n');
  533.     cmdbuf[len] = '\0';
  534.     /*
  535.      * If the line was blank, then just return the line feed and do not
  536.      * put the line on the command stack.
  537.      */
  538.     if (len == 1)
  539.         return '\n';
  540.     /*
  541.      * Handle shell escape if present
  542.      */
  543.     if (cmdbuf[0] == '!') {        /* do a shell command */
  544.         char *cmd;
  545.  
  546.         cmd = cmdbuf + 1;
  547.         if (*cmd == '\0' || *cmd == '\n')
  548.             cmd = shell;
  549.         system(cmd);
  550.         return '\n';
  551.     /*
  552.      * Handle history command if present.
  553.      */
  554.     } else if (cmdbuf[0] == '`') {
  555.         cmdbuf[len-1] = '\0';
  556.         newbuf = findhistory(cmdbuf + 1);
  557.         if (newbuf == NULL)
  558.             return '\n';
  559.         strcpy(cmdbuf, newbuf);
  560.     }
  561.     /*
  562.      * Save the line in the command stack.
  563.      */
  564.     newbuf = (char *)malloc(strlen(cmdbuf) + 1);
  565.     if (newbuf == NULL) {
  566.         perror("Cannot save history line");
  567.         return EOF;
  568.     }
  569.     strcpy(newbuf, cmdbuf);
  570.     if (cmdstack[stackindex])
  571.         free(cmdstack[stackindex]);
  572.     cmdstack[stackindex] = newbuf;
  573.     stackindex = (stackindex + 1) % MAXSAVE;
  574.     /*
  575.      * Return the first character of the line, and set up to
  576.      * return the rest of it with later calls.
  577.      */
  578.     cip->i_ttystr = cmdbuf + 1;
  579.     return chartoint(cmdbuf[0]);
  580. }
  581.  
  582. #ifdef __STDC__
  583. int isascii(char ch)
  584. {
  585.     if ((int) ch >= 0 && (int) ch <= 0x7F)
  586.        return 1;
  587.     else
  588.        return 0;
  589. }
  590. #endif
  591.  
  592. /*
  593.  * Parse a history command line, and return the selected command.
  594.  * NULL is returned if the history command is invalid. Legal formats:
  595.  *    ``    The previous command.
  596.  *    `n    Command number n.
  597.  *    `-n    The nth command back.
  598.  *    `h n    List last n history elements.
  599.  *    `e n    Edit command n (last if not given).
  600.  */
  601. static char *
  602. findhistory(cmd)
  603.     char *cmd;        /* history command */
  604. {
  605.     int num;        /* command number */
  606.     int action;        /* action character */
  607.     int back;        /* how much to search backwards */
  608.     char *str;        /* returned string */
  609.  
  610.     num = 0;
  611.     if ((*cmd == '`') && (cmd[1] == '\0')) {
  612.         num = stackindex - 1;
  613.         if (num < 0)
  614.             num += MAXSAVE;
  615.         str = cmdstack[num];
  616.         if (str == NULL)
  617.             fprintf(stderr, "No previous command\n");
  618.         return str;
  619.     }
  620.     action = '\0';
  621.     if (isascii(*cmd) && islower(*cmd))
  622.         action = *cmd++;
  623.     else if (isascii(*cmd) && isupper(*cmd))
  624.         action = tolower(*cmd++);
  625.     while (isascii(*cmd) && isspace(*cmd))
  626.         cmd++;
  627.     back = FALSE;
  628.     if (*cmd == '-') {
  629.         back = TRUE;
  630.         cmd++;
  631.     }
  632.     num = 0;
  633.     while ((*cmd >= '0') && (*cmd <= '9'))
  634.         num = num * 10 + (*cmd++ - '0');
  635.     if (*cmd != '\0' && *cmd != '\n') {
  636.         fprintf(stderr, "Invalid history command format\n");
  637.         return NULL;
  638.     }
  639.     if ((num == 0) && (action == 'h'))
  640.         num = DEFHIST;
  641.     if ((num == 0) && (action == 'e'))
  642.         num = stackindex;
  643.     if ((num <= 0) || (num > MAXSAVE)) {
  644.         fprintf(stderr, "Invalid history command number\n");
  645.         return NULL;
  646.     }
  647.     if (back)
  648.         num = stackindex - num;
  649.     else
  650.         num--;
  651.     if (num < 0)
  652.         num += MAXSAVE;
  653.     switch (action) {
  654.         case '\0':
  655.             str = cmdstack[num];
  656.             if (str == NULL)
  657.                 fprintf(stderr, "History stack element %d is undefined\n", num + 1);
  658.             return str;
  659.  
  660.         case 'e':
  661.             return edithistory(cmdstack[num]);
  662.  
  663.         case 'h':
  664.             num++;
  665.             back = stackindex - num;
  666.             if (back < 0)
  667.                 back += MAXSAVE;
  668.             printf("\n");
  669.             while (num-- > 0) {
  670.                 if (cmdstack[back])
  671.                 printf("%02d: %s", back + 1, cmdstack[back]);
  672.                 back = (back + 1) % MAXSAVE;
  673.             }
  674.             printf("\n");
  675.             return NULL;
  676.  
  677.         default:
  678.             fprintf(stderr, "Invalid history action character");
  679.             return NULL;
  680.     }
  681. }
  682.  
  683.  
  684. /*
  685.  * Edit the specified command string and return the new version of it.
  686.  * The string is safe to reference until the next call to this routine.
  687.  * Returns NULL if the user gives the command to abort the edit.
  688.  */
  689. /*ARGSUSED*/
  690. static char *
  691. edithistory(str)
  692.     char *str;        /* original string */
  693. {
  694. #if 0
  695.     char *tmp;        /* temporary string */
  696.     int len;        /* current length of string */
  697.     int cmd;        /* edit command */
  698. #endif
  699.  
  700.     printf("Editing not implemented\n");
  701.     return NULL;
  702. #if 0
  703.     len = strlen(str);
  704.     if (len >= editsize) {
  705.         tmp = realloc(editbuf, len + TTYSIZE + 1);
  706.         if (tmp == NULL) {
  707.             perror("Cannot grow edit line");
  708.             return NULL;
  709.         }
  710.         free(editbuf);
  711.         editbuf = tmp;
  712.         editsize = len + TTYSIZE;
  713.     }
  714.     strcpy(editbuf, str);
  715.     for (;;) {
  716.         printf(" %s*", editbuf);
  717.         fflush(stdout);
  718.         cmd = getchar();
  719.         switch (cmd) {
  720.             case EOF:
  721.                 return NULL;
  722.             case '\n':
  723.                 return editbuf;
  724.             default:
  725.                 while (getchar() != '\n') ;
  726.                 printf("Bad edit command\n");
  727.         }
  728.     }
  729. #endif
  730. }
  731.  
  732.  
  733. /*
  734.  * Return whether or not the input source is the terminal.
  735.  */
  736. BOOL
  737. inputisterminal()
  738. {
  739.     return ((depth <= 0) || ((cip->i_str == NULL) && (cip->i_fp == NULL)));
  740. }
  741.  
  742.  
  743. /*
  744.  * Return the name of the current input file.
  745.  * Returns NULL for terminal or strings.
  746.  */
  747. char *
  748. inputname()
  749. {
  750.     if (depth <= 0)
  751.         return NULL;
  752.     return cip->i_name;
  753. }
  754.  
  755.  
  756. /*
  757.  * Return the current line number.
  758.  */
  759. long
  760. linenumber()
  761. {
  762.     if (depth > 0)
  763.         return cip->i_line;
  764.     return 1;
  765. }
  766.  
  767.  
  768. /*
  769.  * Restore the next character to be read again on the next nextchar call.
  770.  */
  771. void
  772. reread()
  773. {
  774.     if ((depth <= 0) || (cip->i_state == IS_REREAD))
  775.         return;
  776.     cip->i_state = IS_REREAD;
  777.     if (cip->i_char == '\n')
  778.         cip->i_line--;
  779. }
  780.  
  781.  
  782. /*
  783.  * Process all startup files found in the $CALCRC path.
  784.  */
  785. void
  786. runrcfiles()
  787. {
  788.     char path[PATHSIZE+1];    /* name being searched for */
  789.     char *cp;
  790.     char *newcp;
  791.     char *p;
  792.     int i;
  793.  
  794.     /* execute each file in the list */
  795.     for (cp=calcrc, newcp=(char *)strchr(calcrc, LISTCHAR);
  796.          cp != NULL && *cp;
  797.          cp = newcp, 
  798.          newcp=(newcp) ? (char *)strchr(newcp+1, LISTCHAR) : NULL) {
  799.  
  800.         /* load file name into the path */
  801.         if (newcp == NULL) {
  802.             strcpy(path, cp);
  803.         } else {
  804.             strncpy(path, cp, newcp-cp);
  805.             path[newcp-cp] = '\0';
  806.         }
  807.  
  808.         /* find the start of the path */
  809.         p = (path[0] == ':') ? path+1 : path;
  810.         if (p[0] == '\0') {
  811.             continue;
  812.         }
  813.  
  814.         /* process the current file in the list */
  815.         i = openfile(p);
  816.         if (i < 0)
  817.             continue;
  818.         getcommands();
  819.     }
  820. }
  821.  
  822.  
  823. /* END CODE */
  824.