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

📄 compile.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1992 Diomidis Spinellis. * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Diomidis Spinellis of Imperial College, University of London. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)compile.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include <sys/types.h>#include <sys/stat.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <regex.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "defs.h"#include "extern.h"#define LHSZ	128#define	LHMASK	(LHSZ - 1)static struct labhash {	struct	labhash *lh_next;	u_int	lh_hash;	struct	s_command *lh_cmd;	int	lh_ref;} *labels[LHSZ];static char	 *compile_addr __P((char *, struct s_addr *));static char	 *compile_delimited __P((char *, char *));static char	 *compile_flags __P((char *, struct s_subst *));static char	 *compile_re __P((char *, regex_t **));static char	 *compile_subst __P((char *, struct s_subst *));static char	 *compile_text __P((void));static char	 *compile_tr __P((char *, char **));static struct s_command		**compile_stream __P((char *, struct s_command **, char *));static char	 *duptoeol __P((char *, char *));static void	  enterlabel __P((struct s_command *));static struct s_command		 *findlabel __P((char *));static void	  fixuplabel __P((struct s_command *, struct s_command *));static void	  uselabel __P((void));/* * Command specification.  This is used to drive the command parser. */struct s_format {	char code;				/* Command code */	int naddr;				/* Number of address args */	enum e_args args;			/* Argument type */};static struct s_format cmd_fmts[] = {	{'{', 2, GROUP},	{'a', 1, TEXT},	{'b', 2, BRANCH},	{'c', 2, TEXT},	{'d', 2, EMPTY},	{'D', 2, EMPTY},	{'g', 2, EMPTY},	{'G', 2, EMPTY},	{'h', 2, EMPTY},	{'H', 2, EMPTY},	{'i', 1, TEXT},	{'l', 2, EMPTY},	{'n', 2, EMPTY},	{'N', 2, EMPTY},	{'p', 2, EMPTY},	{'P', 2, EMPTY},	{'q', 1, EMPTY},	{'r', 1, RFILE},	{'s', 2, SUBST},	{'t', 2, BRANCH},	{'w', 2, WFILE},	{'x', 2, EMPTY},	{'y', 2, TR},	{'!', 2, NONSEL},	{':', 0, LABEL},	{'#', 0, COMMENT},	{'=', 1, EMPTY},	{'\0', 0, COMMENT},};/* The compiled program. */struct s_command *prog;/* * Compile the program into prog. * Initialise appends. */voidcompile(){	*compile_stream(NULL, &prog, NULL) = NULL;	fixuplabel(prog, NULL);	uselabel();	appends = xmalloc(sizeof(struct s_appends) * appendnum);	match = xmalloc((maxnsub + 1) * sizeof(regmatch_t));}#define EATSPACE() do {							\	if (p)								\		while (*p && isascii(*p) && isspace(*p))		\			p++;						\	} while (0)static struct s_command **compile_stream(terminator, link, p)	char *terminator;	struct s_command **link;	register char *p;{	static char lbuf[_POSIX2_LINE_MAX + 1];	/* To save stack */	struct s_command *cmd, *cmd2;	struct s_format *fp;	int naddr;				/* Number of addresses */	if (p != NULL)		goto semicolon;	for (;;) {		if ((p = cu_fgets(lbuf, sizeof(lbuf))) == NULL) {			if (terminator != NULL)				err(COMPILE, "unexpected EOF (pending }'s)");			return (link);		}semicolon:	EATSPACE();		if (p && (*p == '#' || *p == '\0'))			continue;		if (*p == '}') {			if (terminator == NULL)				err(COMPILE, "unexpected }");			return (link);		}		*link = cmd = xmalloc(sizeof(struct s_command));		link = &cmd->next;		cmd->nonsel = cmd->inrange = 0;		/* First parse the addresses */		naddr = 0;		cmd->a1 = cmd->a2 = NULL;/* Valid characters to start an address */#define	addrchar(c)	(strchr("0123456789/\\$", (c)))		if (addrchar(*p)) {			naddr++;			cmd->a1 = xmalloc(sizeof(struct s_addr));			p = compile_addr(p, cmd->a1);			EATSPACE();				/* EXTENSION */			if (*p == ',') {				naddr++;				p++;				EATSPACE();			/* EXTENSION */				cmd->a2 = xmalloc(sizeof(struct s_addr));				p = compile_addr(p, cmd->a2);			}		}nonsel:		/* Now parse the command */		EATSPACE();		if (!*p)			err(COMPILE, "command expected");		cmd->code = *p;		for (fp = cmd_fmts; fp->code; fp++)			if (fp->code == *p)				break;		if (!fp->code)			err(COMPILE, "invalid command code %c", *p);		if (naddr > fp->naddr)			err(COMPILE,"command %c expects up to %d address(es), found %d", *p, fp->naddr, naddr);		switch (fp->args) {		case NONSEL:			/* ! */			cmd->nonsel = ! cmd->nonsel;			p++;			goto nonsel;		case GROUP:			/* { */			p++;			EATSPACE();			if (!*p)				p = NULL;			cmd2 = xmalloc(sizeof(struct s_command));			cmd2->code = '}';			*compile_stream("}", &cmd->u.c, p) = cmd2;			cmd->next = cmd2;			link = &cmd2->next;			break;		case EMPTY:		/* d D g G h H l n N p P q x = \0 */			p++;			EATSPACE();			if (*p == ';') {				p++;				link = &cmd->next;				goto semicolon;			}			if (*p)				err(COMPILE,"extra characters at the end of %c command", cmd->code);			break;		case TEXT:			/* a c i */			p++;			EATSPACE();			if (*p != '\\')				err(COMPILE,"command %c expects \\ followed by text", cmd->code);			p++;			EATSPACE();			if (*p)				err(COMPILE,"extra characters after \\ at the end of %c command", cmd->code);			cmd->t = compile_text();			break;		case COMMENT:			/* \0 # */			break;		case WFILE:			/* w */			p++;			EATSPACE();			if (*p == '\0')				err(COMPILE, "filename expected");			cmd->t = duptoeol(p, "w command");			if (aflag)				cmd->u.fd = -1;			else if ((cmd->u.fd = open(p, 			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,			    DEFFILEMODE)) == -1)				err(FATAL, "%s: %s\n", p, strerror(errno));			break;		case RFILE:			/* r */			p++;			EATSPACE();			if (*p == '\0')				err(COMPILE, "filename expected");			else				cmd->t = duptoeol(p, "read command");			break;		case BRANCH:			/* b t */			p++;			EATSPACE();			if (*p == '\0')				cmd->t = NULL;			else				cmd->t = duptoeol(p, "branch");			break;		case LABEL:			/* : */			p++;			EATSPACE();			cmd->t = duptoeol(p, "label");			if (strlen(p) == 0)				err(COMPILE, "empty label");			enterlabel(cmd);			break;		case SUBST:			/* s */			p++;			if (*p == '\0' || *p == '\\')				err(COMPILE,"substitute pattern can not be delimited by newline or backslash");			cmd->u.s = xmalloc(sizeof(struct s_subst));			p = compile_re(p, &cmd->u.s->re);			if (p == NULL)				err(COMPILE, "unterminated substitute pattern");			--p;			p = compile_subst(p, cmd->u.s);			p = compile_flags(p, cmd->u.s);			EATSPACE();			if (*p == ';') {				p++;				link = &cmd->next;				goto semicolon;			}			break;		case TR:			/* y */			p++;			p = compile_tr(p, (char **)&cmd->u.y);			EATSPACE();			if (*p == ';') {				p++;				link = &cmd->next;				goto semicolon;			}			if (*p)				err(COMPILE,"extra text at the end of a transform command");			break;		}	}}/* * Get a delimited string.  P points to the delimeter of the string; d points * to a buffer area.  Newline and delimiter escapes are processed; other * escapes are ignored. * * Returns a pointer to the first character after the final delimiter or NULL * in the case of a non-terminated string.  The character array d is filled * with the processed string. */static char *compile_delimited(p, d)	char *p, *d;{	char c;	c = *p++;	if (c == '\0')		return (NULL);	else if (c == '\\')		err(COMPILE, "\\ can not be used as a string delimiter");	else if (c == '\n')		err(COMPILE, "newline can not be used as a string delimiter");	while (*p) {		if (*p == '\\' && p[1] == c)			p++;		else if (*p == '\\' && p[1] == 'n') {			*d++ = '\n';			p += 2;			continue;		} else if (*p == '\\' && p[1] == '\\')			*d++ = *p++;		else if (*p == c) {			*d = '\0';			return (p + 1);		}		*d++ = *p++;	}	return (NULL);}/* * Get a regular expression.  P points to the delimiter of the regular * expression; repp points to the address of a regexp pointer.  Newline * and delimiter escapes are processed; other escapes are ignored. * Returns a pointer to the first character after the final delimiter * or NULL in the case of a non terminated regular expression.  The regexp * pointer is set to the compiled regular expression. * Cflags are passed to regcomp. */static char *compile_re(p, repp)	char *p;	regex_t **repp;{	int eval;	char re[_POSIX2_LINE_MAX + 1];	p = compile_delimited(p, re);	if (p && strlen(re) == 0) {		*repp = NULL;		return (p);	}

⌨️ 快捷键说明

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