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 + -
显示快捷键?