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

📄 expand.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (syntax[*p] == CCTL) \				STPUTC(CTLESC, expdest); \			STPUTC(*p++, expdest); \		} \	} else \		while (*p) \			STPUTC(*p++, expdest); \	} while (0)	switch (name) {	case '$':		num = rootpid;		goto numvar;	case '?':		num = exitstatus;		goto numvar;	case '#':		num = shellparam.nparam;		goto numvar;	case '!':		num = backgndpid;numvar:		p = temp + 31;		temp[31] = '\0';		do {			*--p = num % 10 + '0';		} while ((num /= 10) != 0);		while (*p)			STPUTC(*p++, expdest);		break;	case '-':		for (i = 0 ; i < NOPTS ; i++) {			if (optlist[i].val)				STPUTC(optlist[i].letter, expdest);		}		break;	case '@':		if (allow_split) {			sep = '\0';			goto allargs;		}		/* fall through */				case '*':		sep = ' ';allargs:		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {			STRTODEST(p);			if (*ap)				STPUTC(sep, expdest);		}		break;	case '0':		p = arg0;		STRTODEST(p);		break;	default:		if ((unsigned)(name -= '1') <= '9' - '1') {			p = shellparam.p[name];			STRTODEST(p);		}		break;	}}/* * Record the the fact that we have to scan this region of the * string for IFS characters. */STATIC voidrecordregion(start, end, nulonly) {	register struct ifsregion *ifsp;	if (ifslastp == NULL) {		ifsp = &ifsfirst;	} else {		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));		ifslastp->next = ifsp;	}	ifslastp = ifsp;	ifslastp->next = NULL;	ifslastp->begoff = start;	ifslastp->endoff = end;	ifslastp->nulonly = nulonly;}/* * Break the argument string into pieces based upon IFS and add the * strings to the argument list.  The regions of the string to be * searched for IFS characters have been stored by recordregion. */STATIC voidifsbreakup(string, arglist)	char *string;	struct arglist *arglist;	{	struct ifsregion *ifsp;	struct strlist *sp;	char *start;	register char *p;	char *q;	char *ifs;	start = string;	if (ifslastp != NULL) {		ifsp = &ifsfirst;		do {			p = string + ifsp->begoff;			ifs = ifsp->nulonly? nullstr : ifsval();			while (p < string + ifsp->endoff) {				q = p;				if (*p == CTLESC)					p++;				if (strchr(ifs, *p++)) {					if (q > start || *ifs != ' ') {						*q = '\0';						sp = (struct strlist *)stalloc(sizeof *sp);						sp->text = start;						*arglist->lastp = sp;						arglist->lastp = &sp->next;					}					if (*ifs == ' ') {						for (;;) {							if (p >= string + ifsp->endoff)								break;							q = p;							if (*p == CTLESC)								p++;							if (strchr(ifs, *p++) == NULL) {								p = q;								break;							}						}					}					start = p;				}			}		} while ((ifsp = ifsp->next) != NULL);		if (*start || (*ifs != ' ' && start > string)) {			sp = (struct strlist *)stalloc(sizeof *sp);			sp->text = start;			*arglist->lastp = sp;			arglist->lastp = &sp->next;		}	} else {		sp = (struct strlist *)stalloc(sizeof *sp);		sp->text = start;		*arglist->lastp = sp;		arglist->lastp = &sp->next;	}}/* * Expand shell metacharacters.  At this point, the only control characters * should be escapes.  The results are stored in the list exparg. */char *expdir;STATIC voidexpandmeta(str, flag)	struct strlist *str;	{	char *p;	struct strlist **savelastp;	struct strlist *sp;	char c;	/* TODO - EXP_REDIR */	while (str) {		if (fflag)			goto nometa;		p = str->text;		for (;;) {			/* fast check for meta chars */			if ((c = *p++) == '\0')				goto nometa;			if (c == '*' || c == '?' || c == '[' || c == '!')				break;		}		savelastp = exparg.lastp;		INTOFF;		if (expdir == NULL) {			int i = strlen(str->text);			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */		}		expmeta(expdir, str->text);		ckfree(expdir);		expdir = NULL;		INTON;		if (exparg.lastp == savelastp) {			/* 			 * no matches 			 */nometa:			*exparg.lastp = str;			rmescapes(str->text);			exparg.lastp = &str->next;		} else {			*exparg.lastp = NULL;			*savelastp = sp = expsort(*savelastp);			while (sp->next != NULL)				sp = sp->next;			exparg.lastp = &sp->next;		}		str = str->next;	}}/* * Do metacharacter (i.e. *, ?, [...]) expansion. */STATIC voidexpmeta(enddir, name)	char *enddir;	char *name;	{	register char *p;	char *q;	char *start;	char *endname;	int metaflag;	struct stat statb;	DIR *dirp;	struct dirent *dp;	int atend;	int matchdot;	metaflag = 0;	start = name;	for (p = name ; ; p++) {		if (*p == '*' || *p == '?')			metaflag = 1;		else if (*p == '[') {			q = p + 1;			if (*q == '!')				q++;			for (;;) {				if (*q == CTLESC)					q++;				if (*q == '/' || *q == '\0')					break;				if (*++q == ']') {					metaflag = 1;					break;				}			}		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {			metaflag = 1;		} else if (*p == '\0')			break;		else if (*p == CTLESC)			p++;		if (*p == '/') {			if (metaflag)				break;			start = p + 1;		}	}	if (metaflag == 0) {	/* we've reached the end of the file name */		if (enddir != expdir)			metaflag++;		for (p = name ; ; p++) {			if (*p == CTLESC)				p++;			*enddir++ = *p;			if (*p == '\0')				break;		}		if (metaflag == 0 || stat(expdir, &statb) >= 0)			addfname(expdir);		return;	}	endname = p;	if (start != name) {		p = name;		while (p < start) {			if (*p == CTLESC)				p++;			*enddir++ = *p++;		}	}	if (enddir == expdir) {		p = ".";	} else if (enddir == expdir + 1 && *expdir == '/') {		p = "/";	} else {		p = expdir;		enddir[-1] = '\0';	}	if ((dirp = opendir(p)) == NULL)		return;	if (enddir != expdir)		enddir[-1] = '/';	if (*endname == 0) {		atend = 1;	} else {		atend = 0;		*endname++ = '\0';	}	matchdot = 0;	if (start[0] == '.' || start[0] == CTLESC && start[1] == '.')		matchdot++;	while (! int_pending() && (dp = readdir(dirp)) != NULL) {		if (dp->d_name[0] == '.' && ! matchdot)			continue;		if (patmatch(start, dp->d_name)) {			if (atend) {				scopy(dp->d_name, enddir);				addfname(expdir);			} else {				char *q;				for (p = enddir, q = dp->d_name ; *p++ = *q++ ;);				p[-1] = '/';				expmeta(p, endname);			}		}	}	closedir(dirp);	if (! atend)		endname[-1] = '/';}/* * Add a file name to the list. */STATIC voidaddfname(name)	char *name;	{	char *p;	struct strlist *sp;	p = stalloc(strlen(name) + 1);	scopy(name, p);	sp = (struct strlist *)stalloc(sizeof *sp);	sp->text = p;	*exparg.lastp = sp;	exparg.lastp = &sp->next;}/* * Sort the results of file name expansion.  It calculates the number of * strings to sort and then calls msort (short for merge sort) to do the * work. */STATIC struct strlist *expsort(str)	struct strlist *str;	{	int len;	struct strlist *sp;	len = 0;	for (sp = str ; sp ; sp = sp->next)		len++;	return msort(str, len);}STATIC struct strlist *msort(list, len)	struct strlist *list;	{	struct strlist *p, *q;	struct strlist **lpp;	int half;	int n;	if (len <= 1)		return list;	half = len >> 1;      	p = list;	for (n = half ; --n >= 0 ; ) {		q = p;		p = p->next;	}	q->next = NULL;			/* terminate first half of list */	q = msort(list, half);		/* sort first half of list */	p = msort(p, len - half);		/* sort second half */	lpp = &list;	for (;;) {		if (strcmp(p->text, q->text) < 0) {			*lpp = p;			lpp = &p->next;			if ((p = *lpp) == NULL) {				*lpp = q;				break;			}		} else {			*lpp = q;			lpp = &q->next;			if ((q = *lpp) == NULL) {				*lpp = p;				break;			}		}	}	return list;}/* * Returns true if the pattern matches the string. */intpatmatch(pattern, string)	char *pattern;	char *string;	{#ifdef notdef	if (pattern[0] == '!' && pattern[1] == '!')		return 1 - pmatch(pattern + 2, string);	else#endif		return pmatch(pattern, string);}STATIC intpmatch(pattern, string)	char *pattern;	char *string;	{	register char *p, *q;	register char c;	p = pattern;	q = string;	for (;;) {		switch (c = *p++) {		case '\0':			goto breakloop;		case CTLESC:			if (*q++ != *p++)				return 0;			break;		case '?':			if (*q++ == '\0')				return 0;			break;		case '*':			c = *p;			if (c != CTLESC && c != '?' && c != '*' && c != '[') {				while (*q != c) {					if (*q == '\0')						return 0;					q++;				}			}			do {				if (pmatch(p, q))					return 1;			} while (*q++ != '\0');			return 0;		case '[': {			char *endp;			int invert, found;			char chr;			endp = p;			if (*endp == '!')				endp++;			for (;;) {				if (*endp == '\0')					goto dft;		/* no matching ] */				if (*endp == CTLESC)					endp++;				if (*++endp == ']')					break;			}			invert = 0;			if (*p == '!') {				invert++;				p++;			}			found = 0;			chr = *q++;			c = *p++;			do {				if (c == CTLESC)					c = *p++;				if (*p == '-' && p[1] != ']') {					p++;					if (*p == CTLESC)						p++;					if (chr >= c && chr <= *p)						found = 1;					p++;				} else {					if (chr == c)						found = 1;				}			} while ((c = *p++) != ']');			if (found == invert)				return 0;			break;		}dft:	        default:			if (*q++ != c)				return 0;			break;		}	}breakloop:	if (*q != '\0')		return 0;	return 1;}/* * Remove any CTLESC characters from a string. */voidrmescapes(str)	char *str;	{	register char *p, *q;	p = str;	while (*p != CTLESC) {		if (*p++ == '\0')			return;	}	q = p;	while (*p) {		if (*p == CTLESC)			p++;		*q++ = *p++;	}	*q = '\0';}/* * See if a pattern matches in a case statement. */intcasematch(pattern, val)	union node *pattern;	char *val;	{	struct stackmark smark;	int result;	char *p;	setstackmark(&smark);	argbackq = pattern->narg.backquote;	STARTSTACKSTR(expdest);	ifslastp = NULL;	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);	STPUTC('\0', expdest);	p = grabstackstr(expdest);	result = patmatch(p, val);	popstackmark(&smark);	return result;}

⌨️ 快捷键说明

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