var.c

来自「Android 一些工具」· C语言 代码 · 共 826 行 · 第 1/2 页

C
826
字号
/* * Called when a shell procedure is invoked to clear out nonexported * variables.  It is also necessary to reallocate variables of with * VSTACK set since these are currently allocated on the stack. */#ifdef mkinitvoid shprocvar(void);SHELLPROC {	shprocvar();}#endifvoidshprocvar(void){	struct var **vpp;	struct var *vp, **prev;	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {		for (prev = vpp ; (vp = *prev) != NULL ; ) {			if ((vp->flags & VEXPORT) == 0) {				*prev = vp->next;				if ((vp->flags & VTEXTFIXED) == 0)					ckfree(vp->text);				if ((vp->flags & VSTRFIXED) == 0)					ckfree(vp);			} else {				if (vp->flags & VSTACK) {					vp->text = savestr(vp->text);					vp->flags &=~ VSTACK;				}				prev = &vp->next;			}		}	}	initvar();}/* * Command to list all variables which are set.  Currently this command * is invoked from the set command when the set command is called without * any variables. */voidprint_quoted(const char *p){	const char *q;	if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {		out1fmt("%s", p);		return;	}	while (*p) {		if (*p == '\'') {			out1fmt("\\'");			p++;			continue;		}		q = index(p, '\'');		if (!q) {			out1fmt("'%s'", p );			return;		}		out1fmt("'%.*s'", (int)(q - p), p );		p = q;	}}static intsort_var(const void *v_v1, const void *v_v2){	const struct var * const *v1 = v_v1;	const struct var * const *v2 = v_v2;	/* XXX Will anyone notice we include the '=' of the shorter name? */	return strcmp((*v1)->text, (*v2)->text);}/* * POSIX requires that 'set' (but not export or readonly) output the * variables in lexicographic order - by the locale's collating order (sigh). * Maybe we could keep them in an ordered balanced binary tree * instead of hashed lists. * For now just roll 'em through qsort for printing... */intshowvars(const char *name, int flag, int show_value){	struct var **vpp;	struct var *vp;	const char *p;	static struct var **list;	/* static in case we are interrupted */	static int list_len;	int count = 0;	if (!list) {		list_len = 32;		list = ckmalloc(list_len * sizeof *list);	}	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {		for (vp = *vpp ; vp ; vp = vp->next) {			if (flag && !(vp->flags & flag))				continue;			if (vp->flags & VUNSET && !(show_value & 2))				continue;			if (count >= list_len) {				list = ckrealloc(list,					(list_len << 1) * sizeof *list);				list_len <<= 1;			}			list[count++] = vp;		}	}	qsort(list, count, sizeof *list, sort_var);	for (vpp = list; count--; vpp++) {		vp = *vpp;		if (name)			out1fmt("%s ", name);		for (p = vp->text ; *p != '=' ; p++)			out1c(*p);		if (!(vp->flags & VUNSET) && show_value) {			out1fmt("=");			print_quoted(++p);		}		out1c('\n');	}	return 0;}/* * The export and readonly commands. */intexportcmd(int argc, char **argv){	struct var *vp;	char *name;	const char *p;	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;	int pflag;	pflag = nextopt("p") == 'p' ? 3 : 0;	if (argc <= 1 || pflag) {		showvars( pflag ? argv[0] : 0, flag, pflag );		return 0;	}	while ((name = *argptr++) != NULL) {		if ((p = strchr(name, '=')) != NULL) {			p++;		} else {			vp = find_var(name, NULL, NULL);			if (vp != NULL) {				vp->flags |= flag;				continue;			}		}		setvar(name, p, flag);	}	return 0;}/* * The "local" command. */intlocalcmd(int argc, char **argv){	char *name;	if (! in_function())		error("Not in a function");	while ((name = *argptr++) != NULL) {		mklocal(name, 0);	}	return 0;}/* * Make a variable a local variable.  When a variable is made local, it's * value and flags are saved in a localvar structure.  The saved values * will be restored when the shell function returns.  We handle the name * "-" as a special case. */voidmklocal(const char *name, int flags){	struct localvar *lvp;	struct var **vpp;	struct var *vp;	INTOFF;	lvp = ckmalloc(sizeof (struct localvar));	if (name[0] == '-' && name[1] == '\0') {		char *p;		p = ckmalloc(sizeof_optlist);		lvp->text = memcpy(p, optlist, sizeof_optlist);		vp = NULL;	} else {		vp = find_var(name, &vpp, NULL);		if (vp == NULL) {			if (strchr(name, '='))				setvareq(savestr(name), VSTRFIXED|flags);			else				setvar(name, NULL, VSTRFIXED|flags);			vp = *vpp;	/* the new variable */			lvp->text = NULL;			lvp->flags = VUNSET;		} else {			lvp->text = vp->text;			lvp->flags = vp->flags;			vp->flags |= VSTRFIXED|VTEXTFIXED;			if (name[vp->name_len] == '=')				setvareq(savestr(name), flags);		}	}	lvp->vp = vp;	lvp->next = localvars;	localvars = lvp;	INTON;}/* * Called after a function returns. */voidpoplocalvars(void){	struct localvar *lvp;	struct var *vp;	while ((lvp = localvars) != NULL) {		localvars = lvp->next;		vp = lvp->vp;		TRACE(("poplocalvar %s", vp ? vp->text : "-"));		if (vp == NULL) {	/* $- saved */			memcpy(optlist, lvp->text, sizeof_optlist);			ckfree(lvp->text);		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {			(void)unsetvar(vp->text, 0);		} else {			if (vp->func && (vp->flags & VNOFUNC) == 0)				(*vp->func)(lvp->text + vp->name_len + 1);			if ((vp->flags & VTEXTFIXED) == 0)				ckfree(vp->text);			vp->flags = lvp->flags;			vp->text = lvp->text;		}		ckfree(lvp);	}}intsetvarcmd(int argc, char **argv){	if (argc <= 2)		return unsetcmd(argc, argv);	else if (argc == 3)		setvar(argv[1], argv[2], 0);	else		error("List assignment not implemented");	return 0;}/* * The unset builtin command.  We unset the function before we unset the * variable to allow a function to be unset when there is a readonly variable * with the same name. */intunsetcmd(int argc, char **argv){	char **ap;	int i;	int flg_func = 0;	int flg_var = 0;	int ret = 0;	while ((i = nextopt("evf")) != '\0') {		if (i == 'f')			flg_func = 1;		else			flg_var = i;	}	if (flg_func == 0 && flg_var == 0)		flg_var = 1;	for (ap = argptr; *ap ; ap++) {		if (flg_func)			ret |= unsetfunc(*ap);		if (flg_var)			ret |= unsetvar(*ap, flg_var == 'e');	}	return ret;}/* * Unset the specified variable. */intunsetvar(const char *s, int unexport){	struct var **vpp;	struct var *vp;	vp = find_var(s, &vpp, NULL);	if (vp == NULL)		return 1;	if (vp->flags & VREADONLY)		return (1);	INTOFF;	if (unexport) {		vp->flags &= ~VEXPORT;	} else {		if (vp->text[vp->name_len + 1] != '\0')			setvar(s, nullstr, 0);		vp->flags &= ~VEXPORT;		vp->flags |= VUNSET;		if ((vp->flags & VSTRFIXED) == 0) {			if ((vp->flags & VTEXTFIXED) == 0)				ckfree(vp->text);			*vpp = vp->next;			ckfree(vp);		}	}	INTON;	return 0;}/* * Returns true if the two strings specify the same varable.  The first * variable name is terminated by '='; the second may be terminated by * either '=' or '\0'. */STATIC intstrequal(const char *p, const char *q){	while (*p == *q++) {		if (*p++ == '=')			return 1;	}	if (*p == '=' && *(q - 1) == '\0')		return 1;	return 0;}/* * Search for a variable. * 'name' may be terminated by '=' or a NUL. * vppp is set to the pointer to vp, or the list head if vp isn't found * lenp is set to the number of charactets in 'name' */STATIC struct var *find_var(const char *name, struct var ***vppp, int *lenp){	unsigned int hashval;	int len;	struct var *vp, **vpp;	const char *p = name;	hashval = 0;	while (*p && *p != '=')		hashval = 2 * hashval + (unsigned char)*p++;	len = p - name;	if (lenp)		*lenp = len;	vpp = &vartab[hashval % VTABSIZE];	if (vppp)		*vppp = vpp;	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {		if (vp->name_len != len)			continue;		if (memcmp(vp->text, name, len) != 0)			continue;		if (vppp)			*vppp = vpp;		return vp;	}	return NULL;}

⌨️ 快捷键说明

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