⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1994 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Nested input source file reader. * For terminal input, this also provides a simple command stack. */#include <ctype.h>#include <pwd.h>#include "calc.h"#include "config.h"#include "hist.h"#define TTYSIZE		100	/* reallocation size for terminal buffers */#define DEPTH		10	/* maximum depth of input */#define IS_READ		1	/* reading normally */#define IS_REREAD	2	/* reread current character */#define chartoint(ch)	((ch) & 0xff)	/* make sure char is not negative */#define READSET_ALLOC	8	/* readset to allocate chunk size */typedef struct {	int i_state;		/* state (read, reread) */	int i_char;		/* currently read char */	long i_line;		/* line number */	char *i_str;		/* current string for input (if not NULL) */	char *i_origstr;	/* original string so it can be freed */	char *i_ttystr;		/* current character of tty line (or NULL) */	FILE *i_fp;		/* current file for input (if not NULL) */	char *i_name;		/* file name if known */} INPUT;/* files that calc has read or included */typedef struct {	int active;		/* != 0 => active entry, 0 => unused entry */	char *name;		/* name used to read file */	char *path;		/* real path used to open file */	struct stat inode;	/* inode information for file */} READSET;static READSET *readset = NULL;		/* array of files read */static int maxreadset = 0;		/* length of readset */static int linesize;		/* current max size of input line */static char *linebuf;		/* current input line buffer */static char *prompt;		/* current prompt for terminal */static BOOL noprompt;		/* TRUE if should not print prompt */static int depth;		/* current input depth */static INPUT *cip;		/* current input source */static INPUT inputs[DEPTH];	/* input sources */static int openfile MATH_PROTO((char *name));static int ttychar MATH_PROTO((void));static void closeinput MATH_PROTO((void));static int isinoderead MATH_PROTO((struct stat *sbuf));static int findfreeread MATH_PROTO((void));static int addreadset MATH_PROTO((char *name, char *path, struct stat *sbuf));/* * Open an input file by possibly searching through a path list * and also possibly applying the specified extension.  For example: * opensearchfile("barf", ".:/tmp", ".c") searches in order for the * files "./barf", "./barf.c", "/tmp/barf", and "/tmp/barf.c". * * Returns -1 if we could not open a file or error.   * Returns 1 if file was opened and added to/updated in the readset.    * Returns 0 if file was already in the readset and reopen was 0. */intopensearchfile(name, pathlist, extension, rd_once)	char *name;		/* file name to be read */	char *pathlist;		/* list of colon separated paths (or NULL) */	char *extension;	/* extra extension to try (or NULL) */	int rd_once;		/* TRUE => do not reread a file */{	int i;	char *cp;	char path[PATHSIZE+1];	/* name being searched for */	struct stat statbuf;	/* stat of the path */	/*	 * Don't try the extension if the filename already contains it.	 */	if (extension) {		i = strlen(name) - strlen(extension);		if ((i >= 0) && (strcmp(&name[i], extension) == 0))			extension = NULL;	}	/*	 * If the name is absolute, or if there is no path list, then	 * make one which just searches for the name straight.  Then	 * search through the path list for the file, without and with	 * the specified extension.	 */	if (name[0] == PATHCHAR || 	    name[0] == HOMECHAR || 	    (name[0] == DOTCHAR && name[1] == PATHCHAR) || 	    pathlist == NULL) {		pathlist = "";	}	pathlist--;	do {		pathlist++;		cp = path;		while (*pathlist && (*pathlist != LISTCHAR))			*cp++ = *pathlist++;		if (cp != path)			*cp++ = PATHCHAR;		strcpy(cp, name);		i = openfile(path);		if ((i < 0) && extension) {			strcat(path, extension);			i = openfile(path);		}	} while ((i < 0) && *pathlist);	/* examine what our search produced */	if (i < 0 || cip->i_fp == NULL) {		/* cannot find a file to open */		return -1;	}	if (fstat(fileno(cip->i_fp), &statbuf) < 0) {		/* unable to fstat the open file */		return -1;	}	/* note if we will reopen a file and if that is allowed */	if (rd_once == TRUE && isinoderead(&statbuf) >= 0) {		/* file is in readset and reopen is false */		closeinput();		return 1;	}	/* add this name to the readset */	if (addreadset(name, path, &statbuf) < 0) {		/* cannot add to readset */		closeinput();		return -1;	}	/* file was added to/updated in readset */	return 0;}/* * Given a filename with a leading ~, expand it into a home directory for  * that user.  This function will malloc the space for the expanded path. * * If the path is just ~, or begins with ~/, expand it to the home * directory of the current user.  If the environment variable $HOME * is known, it will be used, otherwise the password file will be * consulted. * * If the path is just ~username, or ~username/, expand it to the home * directory of that user by looking it up in the password file. * * If the password file must be consulted and the username is not found * a NULL pointer is returned. */static char *homeexpand(name)	char *name;		/* a filename with a leading ~ */{	struct passwd *ent;	/* password entry */	char *home2;		/* fullpath of the home directory */	char *fullpath;		/* the malloced expanded path */	char *after;		/* after the ~user or ~ */	char username[PATHSIZE+1];	/* extratced username */	/* firewall */	if (name[0] != HOMECHAR)		return NULL;	/*	 * obtain the home directory component	 */	switch (name[1]) {	case PATHCHAR:		/* ~/... */	case '\0':		/* ~ */		home2 = home;		after = name+1;		break;	default:		/* ~username or ~username/... */		/* extract the username after the ~ */		after = (char *)strchr(name+2, PATHCHAR);		if (after == NULL) {			/* path is just ~username */			ent = (struct passwd *)getpwnam(name+1);			if (ent == NULL) {				/* unknown user */				return NULL;			}			/* just malloc the home directory and return it */			fullpath = (char *)malloc(strlen(ent->pw_dir)+1);			strcpy(fullpath, ent->pw_dir);			return fullpath;		}		if (after-name > PATHSIZE+1) {			/* username is too big */			return NULL;		}		strncpy(username, name+1, after-name-1);		username[after-name-1] = '\0';		/* get that user's home directory */		ent = (struct passwd *)getpwnam(username);		if (ent == NULL) {			/* unknown user */			return NULL;		}		home2 = ent->pw_dir;		break;	}	/*	 * build the fullpath given the home directory	 */	fullpath = (char *)malloc(strlen(home2)+strlen(after)+1);	sprintf(fullpath, "%s%s", home2, after);	return fullpath;}/* * f_open - ~-expand a filename and fopen() it */FILE *f_open(name, mode)	char *name;		/* the filename to open */	char *mode;		/* the fopen mode to use */{	FILE *fp;		/* open file descriptor */	char *fullname;		/* file name with HOMECHAR expansion */	/*	 * expand ~ if needed	 */	if (name[0] == HOMECHAR) {		fullname = homeexpand(name);		if (fullname == NULL)			return NULL;		fp = fopen(fullname, mode);		free(fullname);	} else {		fp = fopen(name, mode);	}	return fp;}/* * Setup for reading from a input file. * Returns -1 if file could not be opened. */static intopenfile(name)	char *name;		/* file name to be read */{	FILE *fp;		/* open file descriptor */	if (depth >= DEPTH)		 return -1;	fp = f_open(name, "r");	if (fp == NULL)		 return -1;	cip++;	cip->i_state = IS_READ;	cip->i_char = '\0';	cip->i_str = NULL;	cip->i_origstr = NULL;	cip->i_ttystr = NULL;	cip->i_fp = fp;	cip->i_line = 1;	cip->i_name = (char *)malloc(strlen(name) + 1);	strcpy(cip->i_name, name);	depth++;	return 0;}/* * Open a string for scanning. String is ended by a null character. * String is copied into local memory so it can be trashed afterwards. * Returns -1 if cannot open string. */intopenstring(str)	char *str;		/* string to be opened */{	char *cp;		/* copied string */	if ((depth >= DEPTH) || (str == NULL))		 return -1;	cp = (char *)malloc(strlen(str) + 1);	if (cp == NULL)		 return -1;	strcpy(cp, str);	cip++;	cip->i_state = IS_READ;	cip->i_char = '\0';	cip->i_str = cp;	cip->i_origstr = cp;	cip->i_fp = NULL;	cip->i_name = NULL;	cip->i_ttystr = NULL;	cip->i_line = 1;	depth++;	return 0;}/* * Set to read input from the terminal. * Returns -1 if there is no more depth for input. */intopenterminal(){	if (depth >= DEPTH)		 return -1;	cip++;	cip->i_state = IS_READ;	cip->i_char = '\0';	cip->i_str = NULL;	cip->i_origstr = NULL;	cip->i_ttystr = NULL;	cip->i_fp = NULL;	cip->i_name = NULL;	cip->i_line = 1;	depth++;	return 0;}/* * Close the current input source. */static voidcloseinput(){	if (depth <= 0)		return;	if (cip->i_origstr)		free(cip->i_origstr);	if (cip->i_fp)		fclose(cip->i_fp);	if (cip->i_name)		free(cip->i_name);	cip--;	depth--;}/* * Reset the input sources back to the initial state. */voidresetinput(){	while (depth > 0)		closeinput();	cip = inputs;	noprompt = FALSE;}/* * Set the prompt for terminal input. */voidsetprompt(str)	char *str;{	prompt = str;	noprompt = FALSE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -