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

📄 file.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * file - file I/O routines callable by users * * Copyright (C) 1999-2006  David I. Bell and Landon Curt Noll * * Primary author:  David I. Bell * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL.  You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. * * @(#) $Revision: 29.16 $ * @(#) $Id: file.c,v 29.16 2006/08/20 15:01:30 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/file.c,v $ * * Under source code control:	1991/07/20 00:21:56 * File existed as early as:	1991 * * chongo <was here> /\oo/\	http://www.isthe.com/chongo/ * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <stdlib.h>#include "have_unistd.h"#if defined(HAVE_UNISTD_H)# include <unistd.h>#endif /* HAVE_UNISTD_H */#include <ctype.h>#include "calc.h"#include "longbits.h"#include "have_fpos.h"#include "have_fpos_pos.h"#include "fposval.h"#include "file.h"#include "calcerr.h"#if defined(_WIN32)# include <io.h>#endif#define READSIZE	1024	/* buffer size for reading *//* * external STDIO functions */extern void math_setfp(FILE *fp);extern FILE *f_open(char *name, char *mode);/* * Table of opened files. * The first three entries always correspond to stdin, stdout, and stderr, * and cannot be closed.  Their file ids are always 0, 1, and 2. */static FILEIO files[MAXFILES] = {	{FILEID_STDIN,	NULL,  (dev_t)0, (ino_t)0,	 "(stdin)",  TRUE, FALSE, FALSE, FALSE, 'r', "r"},	{FILEID_STDOUT, NULL, (dev_t)0, (ino_t)0,	 "(stdout)", FALSE,  TRUE, FALSE, FALSE, 'w', "w"},	{FILEID_STDERR, NULL, (dev_t)0, (ino_t)0,	 "(stderr)", FALSE,  TRUE, FALSE, FALSE, 'w', "w"}};static int ioindex[MAXFILES] = {0,1,2}; /* Indices for FILEIO table */static FILEID lastid = FILEID_STDERR;	/* Last allocated file id */static int idnum = 3;			/* Number of allocated file ids *//* forward static declarations */static ZVALUE filepos2z(FILEPOS pos);static FILEPOS z2filepos(ZVALUE pos);static int set_open_pos(FILE *fp, ZVALUE zpos);static int get_open_pos(FILE *fp, ZVALUE *res);static ZVALUE off_t2z(off_t siz);static ZVALUE dev2z(dev_t dev);static ZVALUE inode2z(ino_t inode);static void getscanfield(FILE *fp, BOOL skip, unsigned int width,			 int scannum, char *scanptr, char **strptr);static void getscanwhite(FILE *fp, BOOL skip, unsigned int width,			 int scannum, char **strptr);static int fscanfile(FILE *fp, char *fmt, int count, VALUE **vals);static void freadnum(FILE *fp, VALUE *valptr);static void freadsum(FILE *fp, VALUE *valptr);static void freadprod(FILE *fp, VALUE *valptr);static void fskipnum(FILE *fp);/* * file_init - perform needed initilization work * * On some systems, one cannot initialize a pointer to a FILE *. * This routine, called once at startup is a work-a-round for * systems with such bogons. * * We will also probe for any open files beyond stderr and set them up. */voidfile_init(void){    static int done = 0;	/* 1 => routine already called */    struct stat sbuf;		/* file status */    FILEIO *fiop;    FILE *fp;    int i;    if (!done) {	/*	 * setup the default set	 */	files[0].fp = stdin;	files[1].fp = stdout;	files[2].fp = stderr;	for (i = 0; i < 3; ++i) {		if (fstat(i, &sbuf) >= 0) {			files[i].dev = sbuf.st_dev;			files[i].inode = sbuf.st_ino;		}	}	/*	 * note any other files that we can find	 */	fiop = &files[3];	for (i = 3; i < MAXFILES; fiop++, ++i) {		char *tname;		fiop->name = NULL;		files[idnum].reading = TRUE;		files[idnum].writing = TRUE;		files[idnum].action = 0;		/*		 * stat the descriptor to see what we have		 */		if (fstat(i, &sbuf) >= 0) {			fp = (FILE *) fdopen(i,"r+");	/*guess mode*/			if (fp) {				strcpy(files[idnum].mode, "r+");			} else {				fp = (FILE *) fdopen(i, "r");				if (fp) {					strcpy(files[idnum].mode, "r");					files[idnum].writing = FALSE;				} else {					fp = (FILE *) fdopen(i, "w");					if (fp) {						strcpy(files[idnum].mode, "w");						files[idnum].reading = FALSE;					}					else						continue;				}			}			tname = (char *)malloc(sizeof("descriptor[19]"));			if (tname == NULL) {				math_error("Out of memory for init_file");				/*NOTREACHED*/			}			sprintf(tname, "descriptor[%d]", i);			files[idnum].name = tname;			files[idnum].id = idnum;			files[idnum].fp = fp;			files[idnum].dev = sbuf.st_dev;			files[idnum].inode = sbuf.st_ino;			ioindex[idnum] = idnum;			idnum++;			lastid++;		}	}	done = 1;    }}/* * init_fileio - initialize a FILEIO structure * * This function initializes a calc FILEIO structure.  It will optionally * malloc the filename string if given an non-NULL associated filename. * It will canonicalize the file open mode string. * * given: *	fiop	pointer to FILEIO structure to initialize *	name	associated filename (NULL => caller will setup filename) *	mode	open mode (one of {r,w,a}{,b}{,+}) *	sbufp	pointer to stat of open file *	id	calc file ID *	fp	open file stream */static voidinit_fileio(FILEIO *fiop, char *name, char *mode,	    struct stat *sbufp, FILEID id, FILE *fp){	char modestr[sizeof(fiop->mode)];	/* mode [rwa]b?\+? */	size_t namelen;				/* length of name */	/* allocate filename if requested */	if (name != NULL) {		namelen = strlen(name);		fiop->name = (char *)malloc(namelen + 1);		if (fiop->name == NULL) {			math_error("No memory for filename");			/*NOTREACHED*/		}	}	/* initialize FILEIO structure */	if (name != NULL) {		strncpy(fiop->name, name, namelen+1);	}	fiop->id = id;	fiop->fp = fp;	fiop->dev = sbufp->st_dev;	fiop->inode = sbufp->st_ino;	fiop->reading = FALSE;	fiop->writing = FALSE;	fiop->appending = FALSE;	fiop->binary = FALSE;	fiop->action = 0;	fiop->mode[0] = '\0';	/*	 * determine file open mode	 *	 * While a leading 'r' is for reading and a leading 'w' is	 * for writing, the presense of a '+' in the string means	 * both reading and writing.  A leading 'a' means append	 * which is writing.	 */	/* canonicalize read modes */	if (mode[0] == 'r') {		/* note read mode */		strcpy(modestr, "r");		fiop->reading = TRUE;		/* note binary mode even though mode is not used / ignored */		if (strchr(mode, 'b') != NULL) {		    strcat(modestr, "b");		}		/* note if reading and writing */		if (strchr(mode, '+') != NULL) {			fiop->writing = TRUE;			strcat(modestr, "+");		}	/* canonicalize write modes */	} else if (mode[0] == 'w') {		/* note write mode */		strcpy(modestr, "w");		fiop->writing = TRUE;		/* note binary mode even though mode is not used / ignored */		if (strchr(mode, 'b') != NULL) {		    strcat(modestr, "b");		}		/* note if reading and writing */		if (strchr(mode, '+') != NULL) {			fiop->reading = TRUE;			strcat(modestr, "+");		}	/* canonicalize append modes */	} else if (mode[0] == 'a') {		/* note append mode */		strcpy(modestr, "a");		fiop->writing = TRUE;		fiop->appending = TRUE;		/* note binary mode even though mode is not used / ignored */		if (strchr(mode, 'b') != NULL) {		    strcat(modestr, "b");		}		/* note if reading and writing */		if (strchr(mode, '+') != NULL) {			fiop->reading = TRUE;			strcat(modestr, "+");		}	/* canonicalize no I/O modes */	} else {		modestr[0] = '\0';	}	modestr[sizeof(modestr)-1] = '\0';	/* firewall */	/* record canonical open mode string */	strncpy(fiop->mode, modestr, sizeof(fiop->mode));}/* * openid - open the specified file name for reading or writing * * given: *	name		file name *	mode		open mode (one of {r,w,a}{,b}{,+}) * * returns: *	>=3 FILEID which can be used to do I/O to the file *	<0 if the open failed * * NOTE: This function will not return 0, 1 or 2 since they are *	 reserved for stdin, stdout, stderr.  In fact, it must not *	 return 0, 1, or 2 because it will confuse those who call *	 the opensearchfiile() function */FILEIDopenid(char *name, char *mode){	FILEIO *fiop;		/* file structure */	FILEID id;		/* new file id */	FILE *fp;	struct stat sbuf;	/* file status */	int i;	/* find the next open slot in the files array */	if (idnum >= MAXFILES)		return -E_MANYOPEN;	fiop = &files[3];	for (i = 3; i < MAXFILES; fiop++,i++) {		if (fiop->name == NULL)			break;	}	if (i == MAXFILES)		math_error("This should not happen in openid()!!!");	/* open the file */	fp = f_open(name, mode);	if (fp == NULL) {		return FILEID_NONE;	}	if (fstat(fileno(fp), &sbuf) < 0) {		math_error("bad fstat");		/*NOTREACHED*/	}	/* get a new FILEID */	id = ++lastid;	ioindex[idnum++] = i;	/* initialize FILEIO structure */	init_fileio(fiop, name, mode, &sbuf, id, fp);	/* return calc open file ID */	return id;}/* * openpathid - open the specified abse filename, or relative filename along a search path * * given: *	name		file name *	mode		open mode (one of {r,w,a}{,b}{,+}) *	pathlist	list of colon separated paths (or NULL) * * returns: *	>=3 FILEID which can be used to do I/O to the file *	<0 if the open failed * * NOTE: This function will not return 0, 1 or 2 since they are *	 reserved for stdin, stdout, stderr.  In fact, it must not *	 return 0, 1, or 2 because it will confuse those who call *	 the opensearchfiile() function */FILEIDopenpathid(char *name, char *mode, char *pathlist){	FILEIO *fiop;		/* file structure */	FILEID id;		/* new file id */	FILE *fp;	struct stat sbuf;	/* file status */	char *openpath;		/* malloc copy of path that was opened */	int i;	/* find the next open slot in the files array */	if (idnum >= MAXFILES)		return -E_MANYOPEN;	fiop = &files[3];	for (i = 3; i < MAXFILES; fiop++,i++) {		if (fiop->name == NULL)			break;	}	if (i == MAXFILES)		math_error("This should not happen in openpathid()!!!");	/* open a file - searching along a path */	openpath = NULL;	fp = f_pathopen(name, mode, pathlist, &openpath);	if (fp == NULL) {		if (openpath != NULL) {			/* should not happen, but just in case */			free(openpath);		}		return FILEID_NONE;	}	if (fstat(fileno(fp), &sbuf) < 0) {		if (openpath != NULL) {			free(openpath);		}		math_error("bad fstat");		/*NOTREACHED*/	}	if (openpath == NULL) {		fclose(fp);		math_error("bad openpath");		/*NOTREACHED*/	}	/* get a new FILEID */	id = ++lastid;	ioindex[idnum++] = i;	/* initialize FILEIO structure */	init_fileio(fiop, NULL, mode, &sbuf, id, fp);	fiop->name = openpath;	/* already malloced by f_pathopen */	/* return calc open file ID */	return id;}/* * reopenid - reopen a FILEID * * given: *	id	FILEID to reopen *	mode	new mode to open as *	mode	new mode to open as (one of "r", "w", "a", "r+", "w+", "a+") *	name	name of new file * * returns: *	FILEID which can be used to do I/O to the file *	<0 if the open failed */FILEIDreopenid(FILEID id, char *mode, char *name){	FILEIO *fiop;		/* file structure */	FILE *fp;	struct stat sbuf;	int i;	/* firewall */	if ((id == FILEID_STDIN) || (id == FILEID_STDOUT) ||	    (id == FILEID_STDERR)) {		math_error("Cannot freopen stdin, stdout, or stderr");		/*NOTREACHED*/	}	/* reopen the file */	fiop = NULL;	for (i = 3; i < idnum; i++) {		fiop = &files[ioindex[i]];		if (fiop->id == id)			break;	}	if (i == idnum) {		if (name == NULL) {			fprintf(stderr, "File not open, need file name\n");			return FILEID_NONE;		}		if (idnum >= MAXFILES) {			fprintf(stderr, "Too many open files\n");			return FILEID_NONE;		}		for (fiop = &files[3], i = 3; i < MAXFILES; fiop++, i++) {			if (fiop->name == NULL)				break;		}		if (i >= MAXFILES) {			math_error("This should not happen in reopenid");			/*NOTREACHED*/		}		fp = f_open(name, mode);		if (fp == NULL) {			fprintf(stderr, "Cannot open file\n");			return FILEID_NONE;		}		ioindex[idnum++] = i;		fiop->id = id;	} else {		if (name == NULL)			fp = freopen(fiop->name, mode, fiop->fp);		else			fp = freopen(name, mode, fiop->fp);		if (fp == NULL) {			free(fiop->name);			fiop->name = NULL;			idnum--;			for (; i < idnum; i++)				ioindex[i] = ioindex[i + 1];			return FILEID_NONE;		}	}	if (fstat(fileno(fp), &sbuf) < 0) {		math_error("bad fstat");		/*NOTREACHED*/	}	/* initialize FILEIO structure */	if (name == NULL) {		if (fiop->name == NULL) {			math_error("old and new reopen filenames are NULL");		}	} else if (fiop->name != NULL) {		free(fiop->name);		fiop->name = NULL;	}	init_fileio(fiop, name, mode, &sbuf, id, fp);	/* return calc open file ID */	return id;}/* * Find the file I/O structure for the specified file id, and verifies that * it is opened in the required manner (0 for reading or 1 for writing). * If writable is -1, then no open checks are made at all and NULL is then * returned if the id represents a closed file. */FILEIO *findid(FILEID id, int writable){	FILEIO *fiop;		/* file structure */	int i;	fiop = NULL;	if ((id < 0) || (id > lastid))		return NULL;	for (i = 0; i < idnum; i++) {		fiop = &files[ioindex[i]];		if (fiop->id == id)			break;	}	if (i == idnum)		return NULL;	if (writable >= 0) {		if ((writable && !fiop->writing) ||		    (!writable && !fiop->reading)) {			return NULL;		}	}	return fiop;}/* * Return whether or not a file id is valid.  This is used for if tests. */BOOLvalidid(FILEID id){	return (findid(id, -1) != NULL);}/* * Return the file with id = index if this is the id of a file that has been * opened (it may have since been closed).  Otherwise returns FILEID_NONE. */FILEIDindexid(long index){	FILEID id;	id = (FILEID) index;	if ((index < 0) || (id > lastid))		return FILEID_NONE;	return id;}/* * Close the specified file id.	 Returns TRUE if there was an error. * Closing of stdin, stdout, or stderr is illegal, but closing of already * closed files is allowed. */intcloseid(FILEID id){	FILEIO *fiop;		/* file structure */	int i;	int err;	fiop = NULL;	/* firewall */	if ((id == FILEID_STDIN) || (id == FILEID_STDOUT) ||	    (id == FILEID_STDERR)) {		math_error("Cannot close stdin, stdout, or stderr");		/*NOTREACHED*/	}	/* get file structure */	for (i = 3; i < idnum; i++) {		fiop = &files[ioindex[i]];		if (fiop->id == id)			break;	}	if (i == idnum)		return 1;		/* File not open */	idnum--;	for (; i < idnum; i++)		ioindex[i] = ioindex[i + 1];	free(fiop->name);	fiop->name = NULL;	/* close file and note error state */	err = ferror(fiop->fp);	err |= fclose(fiop->fp);	fiop->fp = NULL;	/* return success or failure */	return (err ? EOF : 0);}intcloseall(void){	FILEIO *fiop;	int i;	int err;	err = 0;	for (i = 3; i < idnum; i++) {		fiop = &files[ioindex[i]];		if (fiop->fp) {			free(fiop->name);			fiop->name = NULL;			err |= fclose(fiop->fp);		}	}	idnum = 3;	return err;}/* * Return whether or not an error occurred to a file. */BOOLerrorid(FILEID id){	FILEIO *fiop;		/* file structure */	fiop = findid(id, -1);	if (fiop == NULL)		return EOF;	return (ferror(fiop->fp) != 0);}/* * Return whether or not end of file occurred to a file. */BOOLeofid(FILEID id){	FILEIO *fiop;		/* file structure */	fiop = findid(id, -1);	if (fiop == NULL)		return EOF;	return (feof(fiop->fp) != 0);}/* * Flush output to an opened file. */intflushid(FILEID id){	FILEIO *fiop;		/* file structure */	fiop = findid(id, -1);	if (fiop == NULL)		return 0;

⌨️ 快捷键说明

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