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

📄 expand.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 3 页
字号:
	case VSTRIMLEFT:		for (loc = startp; loc < str; loc++) {			c = *loc;			*loc = '\0';			if (patmatch(str, startp, varflags & VSQUOTE))				goto recordleft;			*loc = c;			if ((varflags & VSQUOTE) && *loc == CTLESC)			        loc++;		}		return 0;	case VSTRIMLEFTMAX:		for (loc = str - 1; loc >= startp;) {			c = *loc;			*loc = '\0';			if (patmatch(str, startp, varflags & VSQUOTE))				goto recordleft;			*loc = c;			loc--;			if ((varflags & VSQUOTE) && loc > startp &&			    *(loc - 1) == CTLESC) {				for (q = startp; q < loc; q++)					if (*q == CTLESC)						q++;				if (q > loc)					loc--;			}		}		return 0;	case VSTRIMRIGHT:	        for (loc = str - 1; loc >= startp;) {			if (patmatch(str, loc, varflags & VSQUOTE))				goto recordright;			loc--;			if ((varflags & VSQUOTE) && loc > startp &&			    *(loc - 1) == CTLESC) { 				for (q = startp; q < loc; q++)					if (*q == CTLESC)						q++;				if (q > loc)					loc--;			}		}		return 0;	case VSTRIMRIGHTMAX:		for (loc = startp; loc < str - 1; loc++) {			if (patmatch(str, loc, varflags & VSQUOTE))				goto recordright;			if ((varflags & VSQUOTE) && *loc == CTLESC)			        loc++;		}		return 0;	default:		abort();	}recordleft:	*loc = c;	amount = ((str - 1) - (loc - startp)) - expdest;	STADJUST(amount, expdest);	while (loc != str - 1)		*startp++ = *loc++;	return 1;recordright:	amount = loc - expdest;	STADJUST(amount, expdest);	STPUTC('\0', expdest);	STADJUST(-1, expdest);	return 1;}/* * Expand a variable, and return a pointer to the next character in the * input string. */STATIC char *evalvar(char *p, int flag){	int subtype;	int varflags;	char *var;	char *val;	int patloc;	int c;	int set;	int special;	int startloc;	int varlen;	int apply_ifs;	int quotes = flag & (EXP_FULL | EXP_CASE);	varflags = (unsigned char)*p++;	subtype = varflags & VSTYPE;	var = p;	special = !is_name(*p);	p = strchr(p, '=') + 1;again: /* jump here after setting a variable with ${var=text} */	if (special) {		set = varisset(var, varflags & VSNUL);		val = NULL;	} else {		val = lookupvar(var);		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {			val = NULL;			set = 0;		} else			set = 1;	}	varlen = 0;	startloc = expdest - stackblock();	if (!set && uflag) {		switch (subtype) {		case VSNORMAL:		case VSTRIMLEFT:		case VSTRIMLEFTMAX:		case VSTRIMRIGHT:		case VSTRIMRIGHTMAX:		case VSLENGTH:			error("%.*s: parameter not set", p - var - 1, var);			/* NOTREACHED */		}	}	if (set && subtype != VSPLUS) {		/* insert the value of the variable */		if (special) {			varvalue(var, varflags & VSQUOTE, subtype, flag);			if (subtype == VSLENGTH) {				varlen = expdest - stackblock() - startloc;				STADJUST(-varlen, expdest);			}		} else {			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX								  : BASESYNTAX;			if (subtype == VSLENGTH) {				for (;*val; val++)					varlen++;			} else {				while (*val) {					if (quotes && syntax[(int)*val] == CCTL)						STPUTC(CTLESC, expdest);					STPUTC(*val++, expdest);				}			}		}	}	apply_ifs = ((varflags & VSQUOTE) == 0 ||		(*var == '@' && shellparam.nparam != 1));	switch (subtype) {	case VSLENGTH:		expdest = cvtnum(varlen, expdest);		break;	case VSNORMAL:		break;	case VSPLUS:		set = !set;		/* FALLTHROUGH */	case VSMINUS:		if (!set) {		        argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));			/*			 * ${x-a b c} doesn't get split, but removing the			 * 'apply_ifs = 0' apparantly breaks ${1+"$@"}..			 * ${x-'a b' c} should generate 2 args.			 */			/* We should have marked stuff already */			apply_ifs = 0;		}		break;	case VSTRIMLEFT:	case VSTRIMLEFTMAX:	case VSTRIMRIGHT:	case VSTRIMRIGHTMAX:		if (!set)			break;		/*		 * Terminate the string and start recording the pattern		 * right after it		 */		STPUTC('\0', expdest);		patloc = expdest - stackblock();		if (subevalvar(p, NULL, patloc, subtype,			       startloc, varflags) == 0) {			int amount = (expdest - stackblock() - patloc) + 1;			STADJUST(-amount, expdest);		}		/* Remove any recorded regions beyond start of variable */		removerecordregions(startloc);		apply_ifs = 1;		break;	case VSASSIGN:	case VSQUESTION:		if (set)			break;		if (subevalvar(p, var, 0, subtype, startloc, varflags)) {			varflags &= ~VSNUL;			/* 			 * Remove any recorded regions beyond 			 * start of variable 			 */			removerecordregions(startloc);			goto again;		}		apply_ifs = 0;		break;	default:		abort();	}	if (apply_ifs)		recordregion(startloc, expdest - stackblock(),			     varflags & VSQUOTE);	if (subtype != VSNORMAL) {	/* skip to end of alternative */		int nesting = 1;		for (;;) {			if ((c = *p++) == CTLESC)				p++;			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {				if (set)					argbackq = argbackq->next;			} else if (c == CTLVAR) {				if ((*p++ & VSTYPE) != VSNORMAL)					nesting++;			} else if (c == CTLENDVAR) {				if (--nesting == 0)					break;			}		}	}	return p;}/* * Test whether a specialized variable is set. */STATIC intvarisset(char *name, int nulok){	if (*name == '!')		return backgndpid != -1;	else if (*name == '@' || *name == '*') {		if (*shellparam.p == NULL)			return 0;		if (nulok) {			char **av;			for (av = shellparam.p; *av; av++)				if (**av != '\0')					return 1;			return 0;		}	} else if (is_digit(*name)) {		char *ap;		int num = atoi(name);		if (num > shellparam.nparam)			return 0;		if (num == 0)			ap = arg0;		else			ap = shellparam.p[num - 1];		if (nulok && (ap == NULL || *ap == '\0'))			return 0;	}	return 1;}/* * Add the value of a specialized variable to the stack string. */STATIC voidvarvalue(char *name, int quoted, int subtype, int flag){	int num;	char *p;	int i;	char sep;	char **ap;	char const *syntax;#define STRTODEST(p) \	do {\	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \		syntax = quoted? DQSYNTAX : BASESYNTAX; \		while (*p) { \			if (syntax[(int)*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:		expdest = cvtnum(num, expdest);		break;	case '-':		for (i = 0; optlist[i].name; i++) {			if (optlist[i].val)				STPUTC(optlist[i].letter, expdest);		}		break;	case '@':		if (flag & EXP_FULL && quoted) {			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {				STRTODEST(p);				if (*ap)					STPUTC('\0', expdest);			}			break;		}		/* fall through */	case '*':		if (ifsset() != 0)			sep = ifsval()[0];		else			sep = ' ';		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {			STRTODEST(p);			if (*ap && sep)				STPUTC(sep, expdest);		}		break;	case '0':		p = arg0;		STRTODEST(p);		break;	default:		if (is_digit(*name)) {			num = atoi(name);			if (num > 0 && num <= shellparam.nparam) {				p = shellparam.p[num - 1];				STRTODEST(p);			}		}		break;	}}/* * Record the fact that we have to scan this region of the * string for IFS characters. */STATIC voidrecordregion(int start, int end, int inquotes){	struct ifsregion *ifsp;	if (ifslastp == NULL) {		ifsp = &ifsfirst;	} else {		if (ifslastp->endoff == start		    && ifslastp->inquotes == inquotes) {			/* extend previous area */			ifslastp->endoff = end;			return;		}		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));		ifslastp->next = ifsp;	}	ifslastp = ifsp;	ifslastp->next = NULL;	ifslastp->begoff = start;	ifslastp->endoff = end;	ifslastp->inquotes = inquotes;}/* * 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(char *string, struct arglist *arglist){	struct ifsregion *ifsp;	struct strlist *sp;	char *start;	char *p;	char *q;	const char *ifs;	const char *ifsspc;	int inquotes;	start = string;	ifsspc = NULL;	inquotes = 0;	if (ifslastp == NULL) {		/* Return entire argument, IFS doesn't apply to any of it */		sp = (struct strlist *)stalloc(sizeof *sp);		sp->text = start;		*arglist->lastp = sp;		arglist->lastp = &sp->next;		return;	}	ifs = ifsset() ? ifsval() : " \t\n";	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {		p = string + ifsp->begoff;		inquotes = ifsp->inquotes;		ifsspc = NULL;		while (p < string + ifsp->endoff) {			q = p;			if (*p == CTLESC)				p++;			if (inquotes) {				/* Only NULs (probably from "$@") end args */				if (*p != 0) {					p++;					continue;				}			} else {				if (!strchr(ifs, *p)) {					p++;					continue;				}				ifsspc = strchr(" \t\n", *p);				/* Ignore IFS whitespace at start */				if (q == start && ifsspc != NULL) {					p++;					start = p;					continue;				}			}			/* Save this argument... */			*q = '\0';			sp = (struct strlist *)stalloc(sizeof *sp);			sp->text = start;			*arglist->lastp = sp;			arglist->lastp = &sp->next;			p++;			if (ifsspc != NULL) {				/* Ignore further trailing IFS whitespace */				for (; p < string + ifsp->endoff; p++) {					q = p;					if (*p == CTLESC)						p++;					if (strchr(ifs, *p) == NULL) {						p = q;						break;					}					if (strchr(" \t\n", *p) == NULL) {						p++;						break;					}				}			}			start = p;		}	}	/*	 * Save anything left as an argument.	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as	 * generating 2 arguments, the second of which is empty.	 * Some recent clarification of the Posix spec say that it	 * should only generate one....	 */	if (*start /* || (!ifsspc && start > string) */) {		sp = (struct strlist *)stalloc(sizeof *sp);		sp->text = start;		*arglist->lastp = sp;		arglist->lastp = &sp->next;	}}

⌨️ 快捷键说明

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