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

📄 cawf.c

📁 操作系统源代码
💻 C
字号:
/* *	cawf - a C version of Henry Spencer's awf(1), the Amazingly *	       Workable (text) Formatter * *	V. Abell, Purdue University Computing Center *//* *	Copyright (c) 1991 Purdue University Research Foundation, *	West Lafayette, Indiana 47907.  All rights reserved. * *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue *	University Computing Center.  Not derived from licensed software; *	derived from awf(1) by Henry Spencer of the University of Toronto. * *	Permission is granted to anyone to use this software for any *	purpose on any computer system, and to alter it and redistribute *	it freely, subject to the following restrictions: * *	1. The author is not responsible for any consequences of use of *	   this software, even if they arise from flaws in it. * *	2. The origin of this software must not be misrepresented, either *	   by explicit claim or by omission.  Credits must appear in the *	   documentation. * *	3. Altered versions must be plainly marked as such, and must not *	   be misrepresented as being the original software.  Credits must *	   appear in the documentation. * *	4. This notice may not be removed or altered. */static char Version[] = "4.0";#include "cawf.h"#include <sys/stat.h>#ifndef	UNIX#include <io.h>#include <process.h>#include <string.h>#include <sys\types.h>#include <sys\stat.h>#endifmain(argc, argv)	int     argc;	char    *argv[];{	char *ep;               	/* environment pointer */	int fff = 0;			/* final form feed status */	char **files;			/* file names */	int help = 0;			/* help status */	int i;	               		/* temporary index */	size_t l;                       /* length */	char *lib = CAWFLIB;		/* library path */	int libl;			/* library path length */	int mac = 0;			/* macro specification status */	int nf = 0;             	/* number of files */	char *np;               	/* name pointer */	int pc;                 	/* prolog count */	struct stat sbuf;               /* stat buffer *//* * Save program name. */	if ((Pname = strrchr(argv[0], '\\')) != NULL)		Pname++;	else if ((Pname = strrchr(argv[0], '/')) != NULL)		Pname++;	else		Pname = argv[0];/* * Set error file stream pointer. */	Efs = stderr;/* * Get library name. */	if ((np = getenv("CAWFLIB")) != NULL)		lib = np;	libl = strlen(lib);/* * Get device file name. */	for (ep = getenv("TERM");; ep = NULL) {		if (ep == NULL || *ep == '\0')			ep = "dumb";		l = libl + 1 + strlen(ep) + strlen(".dev") + 1;		if ((np = malloc(l)) == NULL)			Error(FATAL, NOLINE,				" no string space for device file: ", ep);		(void) sprintf(np, "%s/%s.dev", lib, ep);		if (stat(np, &sbuf) == 0)			break;		if (strcmp(ep, "dumb") == 0)			Error(FATAL, NOLINE, " no dumb.dev file in ", lib);		(void) free(np);	}	if ((files = malloc((argc + 2) * sizeof(files[0]))) == NULL)		Error(FATAL, NOLINE, " no space for file list",			NULL);	files[nf++] = np;/* * Get common text file name. */	l = libl + 1 + strlen("common") + 1;	if ((np = malloc(l)) == NULL)		Error(FATAL, NOLINE, " no string space for common file name",			NULL);	(void) sprintf(np, "%s/common", lib);	files[nf++] = np;/* * Process options. */	while ((i = getopt(argc, argv, "c:d:ef:hm:")) != EOF) {		switch (i) {	/*	 * -c<device_configuration_file_path>>	 */		case 'c':			Devconf = optarg;			break;	/*	 * -d<output_device_name> -- define output device name	 *	 * The default output device name is NORMAL -- i.e., a device that	 * does bold face with backspace and overprinting and italic face with	 * underscore.  NORMAL is usually a terminal device.	 *	 * There is a built-in device, named ANSI, that does bold face with	 * the ANSI shadow mode and italic face with the ANSI underscore mode.	 * ANSI is normally a terminal device that supports the ANSI shadow	 * and underscore modes.	 *	 * There is a built-in output device, named NONE, that does nothing	 * at all for the bold or italic faces.  This is usually a terminal	 * device.	 *	 * All other device names must match a stanza in the device	 * configuration file.	 */		case 'd':			Device = optarg;			break;	/*	 * -e -- eject: issue final form feed	 */		case 'e':			fff = 1;			break;	/*	 * -f<output_device_font_name> -- define font name for the output	 *				  device (from device configuration	 *				  file)	 */		case 'f':			Devfont = optarg;			break;	/*	 * -h -- display help (usage)	 */		case 'h':			help = 1;			break;	/*	 * -m<macro_file_name>	 *	 *  Special support is provided for -man, -me and -ms.	 */		case 'm':			if (mac) {				Error(WARN, NOLINE,					"multiple macro file declaration",					NULL);				break;			}			l = libl + 2 + strlen(optarg) + strlen(".mac") + 1;			if ((np = malloc(l)) == NULL)				Error(FATAL, NOLINE, " no string space for ",					argv[1]);			(void) sprintf(np, "%s/m%s.mac", lib, optarg);			files[nf++] = np;			if (strcmp(optarg, "an") == 0)				Marg = MANMACROS;			else if (strcmp(optarg, "s") == 0			     ||  strcmp(optarg, "e") == 0)				Marg = MSMACROS;			mac++;			break;	/*	 * Option not recognized by getopt().	 */		case '?':			Err = 1;		}	}	if (Defdev())		Err++;	if (help || Err) {	  (void) fprintf(stderr,	    "%s %s usage: [-c<c>] [-d<d>] [-e] [-f<f>] [-h] [-m<m>] file...\n",		Pname, Version);	  (void) fprintf(stderr,	    "\t-c<c>     <c> is the device configuration file path\n");	  (void) fprintf(stderr,	    "\t-d<d>     <d> is the output device name\n");	  (void) fprintf(stderr,	    "\t          (default = NORMAL, using \\b for bold and italic)\n");	  (void) fprintf(stderr,	    "\t          (built-ins = ANSI, NONE and NORMAL)\n");	  (void) fprintf(stderr,	    "\t-e        issue eject after last page\n");	  (void) fprintf(stderr,	    "\t-f<f>     <f> is the output device font name\n");	  (void) fprintf(stderr,	    "\t-h        display help (this output)\n");	  (void) fprintf(stderr,	    "\t-m<m>     m<m> is the macro file name\n");	  (void) fprintf(stderr,	    "\tfile ...  source file names\n");	  exit(Err);	}	if (mac == 0) {	    /*	     * No macroes - enable Bold, Italic and Roman fonts.	     */		for (i = 0; Fcode[i].nm; i++) {			switch (Fcode[i].nm) {			case 'B':			case 'I':			case 'R':				Fcode[i].status = '1';			}		}	}/* * Add user-supplied file names. */	pc = nf;	if (optind >= argc) {		files[nf++] = NULL;       /* STDIN */	} else {		while (optind < argc)			files[nf++] = argv[optind++];	}/* * Make sure all input files are accessible. */	for (i = 0; i < nf; i++) {		if (files[i] != NULL) {			if (stat(files[i], &sbuf) != 0)				Error(WARN, NOLINE, " can't find ", files[i]);		}	}	if (Err)		exit(1);/* * Miscellaneous initialization. */	for (i = 0; ; i++) {		if (Pat[i].re == NULL)			break;		if ((Pat[i].pat = regcomp(Pat[i].re)) == NULL)			Error(WARN, NOLINE, Pat[i].re, " regcomp failure");	}	if ((i = Findscale((int)'n', 0.0, 0)) < 0)		Error(WARN, NOLINE, " can't find Scale['n']", NULL);	Scalen = Scale[i].val;	if ((i = Findscale((int)'u', 0.0, 0)) < 0)		Error(WARN, NOLINE, " can't find Scale['u']", NULL);	Scaleu = Scale[i].val;	if ((i = Findscale((int)'v', 0.0, 0)) < 0)		Error(WARN, NOLINE, " can't find Scale['v']", NULL);	Scalev = Scale[i].val;	(void) Findstr((unsigned char *)"CH", (unsigned char *)"= % -", 1);	Cont = Newstr((unsigned char *)" ");	Contlen = 1;	if ((Trtbl = (unsigned char *)malloc(256)) == NULL)		Error(WARN, NOLINE, " can't allocate translate table space",			NULL);	else {		*Trtbl = ' ';		for (i = 1; i < 256; i++)			Trtbl[i] = (unsigned char) i;	}	if (Err)		exit(1);/* * Here begins pass1 of awf - reading input lines and expanding macros. *//* * Output prolog. */	if (Fstr.i) {		for (i = 0; i < Fstr.il; i++) {			Charput((int)Fstr.i[i]);		}	}	Macro((unsigned char *)".^x");	Macro((unsigned char *)".^b");	Macro((unsigned char *)".^# 1 <prolog>");/* * Read input files. */	for (i = 0; i < nf; i++) {		Dowarn = (i >= pc);		if (files[i] == NULL) {			np = "stdin";			Ifs = stdin;		} else {#ifdef	UNIX			if ((Ifs = fopen(files[i], "r")) == NULL)#else			if ((Ifs = fopen(files[i], "rt")) == NULL)#endif				Error(FATAL, NOLINE, " can't open ", files[i]);			np = files[i];		}		if (i >= pc) {			(void) sprintf((char *)Line, ".^# 1 %s", np);			Macro(Line);			NR = 0;		}		Fsp = 0;		do {			while (fgets((char *)Line, MAXLINE, Ifs) != NULL) {				NR++;				if ((np = strrchr((char *)Line, '\n')) != NULL)					*np = '\0';				else					Line[MAXLINE-1] = '\0';				Macro(Line);			}			if (i >= pc)				Macro((unsigned char *)".^e");			if (Ifs != stdin)				(void) fclose(Ifs);			if (Fsp > 0) {				Free(&Inname);				Inname = Inn_stk[Fsp-1];				NR = NR_stk[Fsp-1];				Ifs = Ifs_stk[Fsp-1];			}		} while (Fsp-- > 0);	}	Macro(NULL);	if (fff)		Charput((int)'\f');	exit(Err);}/* * Macro(inp) - process a possible macro statement *		pass non-macros and macros alike to pass 2 */voidMacro(inp)	unsigned char *inp;		/* possible macro statement pointer */{	unsigned char c[2];		/* characters */	int endm;			/* end of macro status */	FILE *fs;			/* temporary file stream */	int i, j, k;                    /* temporary indexes */	int mx;                         /* Macrotab[] index */	int req;			/* request character status */	unsigned char *s1, *s2;		/* temporary string pointers */	if (inp == NULL) {		Pass2(NULL);		return;	}	req = (*inp == '.' || *inp == '\'') ? 1 : 0;/* * Check for file name designator. */	if (req && inp[1] == '^' && inp[2] == '#') {		Free(&Inname);		Inname = Field(3, inp, 1);		F = NULL;		Pass2(inp);		return;	}/* * Check for source command - "^[.']so". */	if (req && inp[1] == 's' && inp[2] == 'o') {		if ((s1 = Field(2, inp, 1)) == NULL) {			Error(WARN, LINE, " no file specified", NULL);			return;		}		if ((fs = fopen((char *)s1, "r")) == NULL) {			Error(WARN, LINE, " can't open", NULL);			return;		}		if (Fsp >= MAXFSTK) {			(void) fclose(fs);			Error(WARN, LINE, " nesting too deep", NULL);			return;		}		Ifs_stk[Fsp] = Ifs;		Ifs = fs;		Inn_stk[Fsp] = Inname;		Inname = F;		F = NULL;		NR_stk[Fsp++] = NR;		NR = 0;		return;	} /*  * Check for ignore.  */	if (req && inp[1] == 'i' && inp[2] == 'g') {		while (fgets((char *)inp, MAXLINE, Ifs) != NULL) {			NR++;			if (inp[0] == '.' && inp[1] == '.') break;		}		return;	} /*  * Check for start of macro definition.  */	if (req && inp[1] == 'd' && inp[2] == 'e') {		if (inp[3] != ' ' || inp[4] == '\0') {			Error(WARN, LINE, " illegal macro definition", NULL);			return;		}		c[0] = inp[4];		c[1] = inp[5];		Curmx = Findmacro(c, 1);		return;	}/* * Check for macro text.  Remove double backslashes. */	if (req && (inp[1] == '\0' || (inp[2] == '\0' && inp[0] == inp[1])))		endm = 1;	else		endm = 0;	if (Curmx >= 0 && !endm) {		if (Mtx >= MAXMTXT)			Error(FATAL, LINE, " out of macro text space", NULL);		if ((s1 = (unsigned char *)strchr((char *)inp, '\\')) == NULL)			Macrotxt[Mtx] = Newstr(inp);		else {			for (s1 = Pass1ln, s2 = inp;; s1++) {				if ((*s1 = *s2++) == '\0')					break;				if (*s1 == '\\' && *s2 == '\\')					s2++;			}			Macrotxt[Mtx] = Newstr(Pass1ln);		}		if (Macrotab[Curmx].bx == -1)			Macrotab[Curmx].bx = Mtx;		Mtx++;		Macrotab[Curmx].ct++;		return;	}/* * Check for end of macro. */	if (Curmx >= 0 && endm) {		Curmx = -1;		(void) sprintf((char *)Pass1ln, ".^# %d %s", NR, Inname);		Pass2(Pass1ln);		return;	} /*  * Check for conditionals and macro expansions.  */	if (req	&&  (((mx = Findmacro(inp+1, 0)) != -1) || regexec(Pat[0].pat, inp))) {		Expand(inp);		return;	}/* * None of the above: forward the line. */	Pass2(inp);}

⌨️ 快捷键说明

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