📄 input.c
字号:
/* * Read the next character from the current input source. * End of file closes current input source, and returns EOF character. */intnextchar(){ int ch; /* current input character */ if (depth == 0) /* input finished */ return EOF; if (cip->i_state == IS_REREAD) { /* rereading current char */ ch = cip->i_char; cip->i_state = IS_READ; if (ch == '\n') cip->i_line++; return ch; } if (cip->i_str) { /* from string */ ch = chartoint(*cip->i_str++); if (ch == '\0') ch = EOF; } else if (cip->i_fp) { /* from file */ ch = fgetc(cip->i_fp); } else { /* from terminal */ ch = ttychar(); } if (ch == EOF) { /* fix up end of file */ closeinput(); ch = EOF; } if (depth > 0) cip->i_char = ch; /* save for rereads */ if (ch == '\n') cip->i_line++; return ch;}/* * Read in the next line of input from the current input source. * The line is terminated with a null character, and does not contain * the final newline character. The returned string is only valid * until the next such call, and so must be copied if necessary. * Returns NULL on end of file. */char *nextline(){ char *cp; int ch; int len; cp = linebuf; if (linesize == 0) { cp = (char *)malloc(TTYSIZE + 1); if (cp == NULL) math_error("Cannot allocate line buffer"); linebuf = cp; linesize = TTYSIZE; } len = 0; for (;;) { noprompt = TRUE; ch = nextchar(); noprompt = FALSE; if (ch == EOF) return NULL; if (ch == '\0') continue; if (ch == '\n') break; if (len >= linesize) { cp = (char *)realloc(cp, linesize + TTYSIZE + 1); if (cp == NULL) math_error("Cannot realloc line buffer"); linebuf = cp; linesize += TTYSIZE; } cp[len++] = (char)ch; } cp[len] = '\0'; return linebuf;}/* * Read the next character from the terminal. * The routines in the history module are called so that the user * can use a command history and emacs-like editing of the line. */static intttychar(){ int ch; /* current char */ int len; /* length of current command */ static char charbuf[1000]; /* * If we have more to read from the saved command line, then do that. * When we see a newline character, then clear the pointer so we will * read a new line on the next call. */ if (cip->i_ttystr) { ch = chartoint(*cip->i_ttystr++); if (ch == '\n') cip->i_ttystr = NULL; return ch; } /* * We need another complete line. */ abortlevel = 0; inputwait = TRUE; len = hist_getline(noprompt ? "" : prompt, charbuf, sizeof(charbuf)); if (len == 0) { inputwait = FALSE; return EOF; } inputwait = FALSE; /* * Handle shell escape if present */ if (charbuf[0] == '!') { /* do a shell command */ char *cmd; cmd = charbuf + 1; if (*cmd == '\0' || *cmd == '\n') cmd = shell; system(cmd); return '\n'; } hist_saveline(charbuf, len); /* * Return the first character of the line, and set up to * return the rest of it with later calls. */ ch = chartoint(charbuf[0]); if (ch != '\n') cip->i_ttystr = charbuf + 1; return ch;}/* * Return whether or not the input source is the terminal. */BOOLinputisterminal(){ return ((depth <= 0) || ((cip->i_str == NULL) && (cip->i_fp == NULL)));}/* * Return the name of the current input file. * Returns NULL for terminal or strings. */char *inputname(){ if (depth <= 0) return NULL; return cip->i_name;}/* * Return the current line number. */longlinenumber(){ if (depth > 0) return cip->i_line; return 1;}/* * Restore the next character to be read again on the next nextchar call. */voidreread(){ if ((depth <= 0) || (cip->i_state == IS_REREAD)) return; cip->i_state = IS_REREAD; if (cip->i_char == '\n') cip->i_line--;}/* * Process all startup files found in the $CALCRC path. */voidrunrcfiles(){ char path[PATHSIZE+1]; /* name being searched for */ char *cp; char *newcp; char *p; int i; /* execute each file in the list */ for (cp=calcrc, newcp=(char *)strchr(calcrc, LISTCHAR); cp != NULL && *cp; cp = newcp, newcp=(newcp) ? (char *)strchr(newcp+1, LISTCHAR) : NULL) { /* load file name into the path */ if (newcp == NULL) { strcpy(path, cp); } else { strncpy(path, cp, newcp-cp); path[newcp-cp] = '\0'; } /* find the start of the path */ p = (path[0] == ':') ? path+1 : path; if (p[0] == '\0') { continue; } /* process the current file in the list */ i = openfile(p); if (i < 0) continue; getcommands(FALSE); }}/* * isinoderead - determine if we have read a given dev/inode * * This function returns the index of the readset element that matches * a given device/inode, -1 otherwise. */static intisinoderead(sbuf) struct stat *sbuf; /* stat of the inode in question */{ int i; /* deal with the empty case */ if (readset == NULL || maxreadset <= 0) { /* readset is empty */ return -1; } /* scan the entire readset */ for (i=0; i < maxreadset; ++i) { if (readset[i].active && sbuf->st_dev == readset[i].inode.st_dev && sbuf->st_ino == readset[i].inode.st_ino) { /* found a match */ return i; } } /* no match found */ return -1;}/* * findfreeread - find the next free readset element * * This function will return the index of the next free readset element. * If needed, this function will allocate new readset elements. * * This function returns the index of the next free element, or -1. */static intfindfreeread(){ int i; /* deal with an empty readset case */ if (readset == NULL || maxreadset <= 0) { /* malloc a new readset */ readset = (READSET *)malloc((READSET_ALLOC+1)*sizeof(READSET)); if (readset == NULL) { return -1; } maxreadset = READSET_ALLOC; for (i=0; i < READSET_ALLOC; ++i) { readset[i].active = 0; } /* return first entry */ return 0; } /* try to find a free readset entry */ for (i=0; i < maxreadset; ++i) { if (readset[i].active == 0) { /* found a free readset entry */ return i; } } /* all readset entries are in use, allocate more */ readset = (READSET *)realloc(readset, (maxreadset+READSET_ALLOC) * sizeof(READSET)); if (readset == NULL) { return -1; } for (i=0; i < READSET_ALLOC; ++i) { readset[i+maxreadset].active = 0; } maxreadset += READSET_ALLOC; /* return the furst newly allocated free entry */ return maxreadset-READSET_ALLOC;}/* * addreadset - add a entry to the readset array if it is not already there * * This function attempts to add a file into the readset. If the readset * has an entry with a matching dev/inode, then that entry is updated with * the new name and path. If no such readset entry is found, a new entry * is added. * * This function returns the index of the readset entry, or -1 if error. */static intaddreadset(name, path, sbuf) char *name; /* name given to read or include */ char *path; /* full pathname of file */ struct stat *sbuf; /* stat of the path */{ int ret; /* index to return */ /* find the inode */ ret = isinoderead(sbuf); if (ret < 0) { /* not in readset, find a free node */ ret = findfreeread(); if (ret < 0) { /* cannot find/form a free readset entry */ return -1; } } else { /* found an readset entry, free old readset data */ if (readset[ret].name != NULL) { free(readset[ret].name); } if (readset[ret].path != NULL) { free(readset[ret].path); } } /* load our information into the readset entry */ readset[ret].name = (char *)malloc(strlen(name)+1); if (readset[ret].name == NULL) { return -1; } strcpy(readset[ret].name, name); readset[ret].path = (char *)malloc(strlen(path)+1); if (readset[ret].path == NULL) { return -1; } strcpy(readset[ret].path, path); readset[ret].inode = *sbuf; readset[ret].active = 1; /* return index of the newly added entry */ return ret;}/* END CODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -