sh.glob.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 846 行 · 第 1/2 页

C
846
字号
		case 0:			return (scc == 0);		default:			if ((c & TRIM) != scc)				return (0);			continue;		case '?':			if (scc == 0)				return (0);			continue;		case '/':			if (scc)				return (0);slash:			s = entp;			sgpathp = gpathp;			while (*s)				addpath(*s++);			addpath('/');			if (stat(gpath, &stb) == 0 && isdir(stb))				if (*p == 0) {					Gcat(gpath, "");					globcnt++;				} else					expand(p);			gpathp = sgpathp;			*gpathp = 0;			return (0);		}	}}Gmatch(s, p)	register char *s, *p;{	register int scc;	int ok, lc;	int c, cc;	for (;;) {		if ((scc = (*s++ & TRIM)) == QUOTECHAR)			scc = *s++;		if ((c = (*p++ & TRIM)) == QUOTECHAR)			c = (*p++ & TRIM) | QUOTE;		switch (c) {		case '[':			ok = 0;			lc = 077777;			while (cc = *p++) {				if (cc == ']') {					if (ok)						break;					return (0);				}				if (cc == '-') {					if (lc <= scc && scc <= *p++)						ok++;				} else					if (scc == (lc = cc))						ok++;			}			if (cc == 0)				bferr("Missing ]");			continue;		case '*':			if (!*p)				return (1);			for (s--; *s; s++)				if (Gmatch(s, p))					return (1);			return (0);		case 0:			return (scc == 0);		default:			if ((c & TRIM) != scc)				return (0);			continue;		case '?':			if (scc == 0)				return (0);			continue;		}	}}Gcat(s1, s2)	char *s1, *s2;{	register char *p, *q;	int n;	for (p = s1; *p++;)		;	for (q = s2; *q++;)		;	gnleft -= (n = (p - s1) + (q - s2) - 1);	if (gnleft <= 0 || ++gargc >= GAVSIZ)		error("Arguments too long");	gargv[gargc] = 0;	p = gargv[gargc - 1] = xalloc((unsigned)n);	for (q = s1; *p++ = *q++;)		;	for (p--, q = s2; *p++ = *q++;)		;}addpath(c)	char c;{	if (gpathp >= lastgpathp)		error("Pathname too long");	*gpathp++ = c & TRIM;	*gpathp = 0;}rscan(t, f)	register char **t;	int (*f)();{	register char *p;	register CHTYPE c;	while (p = *t++) {		while (c = *p++) {			if ((c & TRIM) == QUOTECHAR)				c = (*p++ & TRIM) | QUOTE;			(*f)(c);		}	}}trim(t)	register char **t;{	register char *p;	while (p = *t++)		strip (p);}/* * tests for file expansion characters */tglob(t)	register char **t;{	register char *p;	register CHTYPE c;#ifdef TGLOBDEBUG	printf ("TGLOB: entered; *t = %s\n", *t);#endif	while (p = *t++) {		if (*p == '~')			gflag |= 2;		else if (*p == '{' && (p[1] == '\0' || p[1] == '}' && p[2] == '\0'))			continue;		while (c = (unsigned char) *p++) {			if ((c & TRIM) == QUOTECHAR)				c = (*p++ & TRIM) | QUOTE;			else if (any(c, globchars))				gflag |= c == '{' ? 2 : 1;		}	}#ifdef TGLOBDEBUG	printf ("TGLOB: exiting; *t = %s\n", *t);#endif}char *globone(str)	register char *str;{	char *gv[2];	register char **gvp;	register char *cp;	gv[0] = str;	gv[1] = 0;	gflag = 0;	tglob(gv);	if (gflag) {		gvp = glob(gv);		if (gvp == 0) {			setname(str);			bferr("No match");		}		cp = *gvp++;		if (cp == 0)			cp = "";		else if (*gvp) {			setname(str);			bferr("Ambiguous");		} else			cp = strip(cp);/*		if (cp == 0 || *gvp) {			setname(str);			bferr(cp ? "Ambiguous" : "No output");		}*/		xfree((char *)gargv); gargv = 0;	} else {		trim(gv);		cp = savestr(gv[0]);	}	return (cp);}/* * Command substitute cp.  If literal, then this is * a substitution from a << redirection, and so we should * not crunch blanks and tabs, separating words only at newlines. */char **dobackp(cp, literal)	char *cp;	bool literal;{	register char *lp, *rp;	char *ep;	char word[BUFSIZ];	char *apargv[GAVSIZ + 2];	if (pargv) {		blkfree(pargv);	}	pargv = apargv;	pargv[0] = NOSTR;	pargcp = pargs = word;	pargc = 0;	pnleft = BUFSIZ - 4;	for (;;) {		for (lp = cp; *lp != '`' || (*(lp-1)&TRIM) == QUOTECHAR; lp++) {	/* 005 - GAG */			if (*lp == 0) {				if (pargcp != pargs)					pword();#ifdef GDEBUG				printf("leaving dobackp\n");#endif				return (pargv = copyblk(pargv));			}			psave(*lp & TRIM);		}		lp++;		for (rp = lp; *rp && *rp != '`' || (*(rp-1)&TRIM) == QUOTECHAR; rp++)	/* 005 - GAG */			if (*rp == '\\') {				rp++;				if (!*rp)					goto oops;			}		if (!*rp)oops:			error("Unmatched `");		ep = savestr(lp);		ep[rp - lp] = 0;		backeval(ep, literal);#ifdef GDEBUG		printf("back from backeval\n");#endif		cp = rp + 1;	}}backeval(cp, literal)	char *cp;	bool literal;{	int pvec[2];	int quoted = (literal || ((cp[0] & TRIM) == QUOTECHAR)) ? QUOTE : 0;	char ibuf[BUFSIZ];	register int icnt = 0, c;	register char *ip;	bool hadnl = 0;	char *fakecom[2];	struct command faket;	faket.t_dtyp = TCOM;	faket.t_dflg = 0;	faket.t_dlef = 0;	faket.t_drit = 0;	faket.t_dspr = 0;	faket.t_dcom = fakecom;	fakecom[0] = "` ... `";	fakecom[1] = 0;	/*	 * We do the psave job to temporarily change the current job	 * so that the following fork is considered a separate job.	 * This is so that when backquotes are used in a	 * builtin function that calls glob the "current job" is not corrupted.	 * We only need one level of pushed jobs as long as we are sure to	 * fork here.	 */	psavejob();	/*	 * It would be nicer if we could integrate this redirection more	 * with the routines in sh.sem.c by doing a fake execute on a builtin	 * function that was piped out.	 */	mypipe(pvec);	if (pfork(&faket, -1) == 0) {		struct wordent paraml;		struct command *t;		(void) close(pvec[0]);		(void) dmove(pvec[1], 1);		(void) dmove(SHDIAG, 2);		initdesc();		arginp = cp;		strip(cp);#ifdef CSHEDIT		(void) lex(&paraml, 0);#else		(void) lex(&paraml);#endif		if (err)			error(err);		alias(&paraml);		t = syntax(paraml.next, &paraml, 0);		if (err)			error(err);		if (t)			t->t_dflg |= FPAR;		(void) signal(SIGTSTP, SIG_IGN);		(void) signal(SIGTTIN, SIG_IGN);		(void) signal(SIGTTOU, SIG_IGN);		execute(t, -1);		exitstat();	}	xfree(cp);	(void) close(pvec[1]);	do {		int cnt = 0;		for (;;) {			if (icnt == 0) {				ip = ibuf;				icnt = read(pvec[0], ip, BUFSIZ);				if (icnt <= 0) {					c = -1;					break;				}			}			if (hadnl)				break;			--icnt;			c = (*ip++ & TRIM);			if (c == 0)				break;			if (c == '\n') {				/*				 * Continue around the loop one				 * more time, so that we can eat				 * the last newline without terminating				 * this word.				 */				hadnl = 1;				continue;			}			if (!quoted && (c == ' ' || c == '\t'))				break;			cnt++;			psave(c | quoted);		}		/*		 * Unless at end-of-file, we will form a new word		 * here if there were characters in the word, or in		 * any case when we take text literally.  If		 * we didn't make empty words here when literal was		 * set then we would lose blank lines.		 */		if (c != -1 && (cnt || literal))			pword();		hadnl = 0;	} while (c >= 0);#ifdef GDEBUG	printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]);	printf("also c = %c <%o>\n", c, c);#endif	(void) close(pvec[0]);	pwait();	prestjob();}psave(c)	int c;{	if (--pnleft <= 0)		error("Word too long");	if (c & QUOTE) { 			/* 004 - GAG */		*pargcp++ = QUOTECHAR;		if (--pnleft <= 0)			error("Word too long");	}	*pargcp++ = c & TRIM;}pword(){	psave(0);	if (pargc == GAVSIZ)		error("Too many words from ``");	pargv[pargc++] = savestr(pargs);	pargv[pargc] = NOSTR;#ifdef GDEBUG	printf("got word %s\n", pargv[pargc-1]);#endif	pargcp = pargs;	pnleft = BUFSIZ - 4;}

⌨️ 快捷键说明

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