📄 variable.c
字号:
/* RCS Info: $Revision: 1.1 $ on $Date: 91/04/02 12:04:31 $ * $Source: //pepper/atesse_spice/spice3/CP/RCS/variable.c,v $ * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group * * Do variable substitution. */#include "prefix.h"#include "CPdefs.h"#include "suffix.h"static wordlist *vareval();static int vcmp();/* A variable substitution is * indicated by a $, and the variable name is the following string of * non-special characters. All variable values are inserted as a single * word, except for lists, which are a list of words. * A routine cp_usrset must be supplied by the host program to deal * with variables that aren't used by cshpar -- it should be * cp_usrset(var, isset), where var is a variable *, and isset is * true if the variable is being set, false if unset. * Also required is a routine cp_enqvar(name) which returns a struct * variable *, which allows the host program to provide values for * non-cshpar variables. */bool cp_noglob = true; /* This is just a bad thing. */bool cp_nonomatch = false;bool cp_noclobber = false;bool cp_ignoreeof = false;char cp_dol = '$';static struct variable *variables = NULL;/* Non-alphanumeric characters that may appear in variable names. < is very * special... */#define VALIDCHARS "$-_<#?@.()[]&"wordlist *cp_variablesubst(wlist) wordlist *wlist;{ wordlist *wl, *nwl; char *s, *t, buf[BSIZE], wbuf[BSIZE]; int i; for (wl = wlist; wl; wl = wl->wl_next) { t = wl->wl_word; i = 0; while(s = index(t, cp_dol)) { while (t < s) wbuf[i++] = *t++; wbuf[i] = '\0'; (void) strcpy(buf, ++s); s = buf; t++; while (*s && (isalphanum(*s) || index(VALIDCHARS, *s))) { /* Get s and t past the end of the var name. */ t++; s++; } *s = '\0'; nwl = vareval(buf); if (i) { (void) strcpy(buf, wbuf); if (nwl) { (void) strcat(buf, nwl->wl_word); tfree(nwl->wl_word); } else { nwl = alloc(wordlist); } nwl->wl_word = copy(buf); } if (!(wl = wl_splice(wl, nwl))) return (NULL); /* This is bad... */ for (wlist = wl; wlist->wl_prev; wlist = wlist->wl_prev) ; (void) strcpy(buf, wl->wl_word); i = strlen(buf); (void) strcat(buf, t); tfree(wl->wl_word); wl->wl_word = copy(buf); t = &wl->wl_word[i]; s = wl->wl_word; for (i = 0; s < t; s++) wbuf[i++] = *s; } } return (wlist);}/* Evaluate a variable. */static wordlist *vareval(string) char *string;{ struct variable *v; wordlist *wl; char buf[BSIZE], *s; char *oldstring = copy(string); char *range = NULL; int i, up, low; cp_wstrip(string); if (s = index(string, '[')) { *s = '\0'; range = s + 1; } switch (*string) { case '$': wl = alloc(wordlist);#ifdef UNIX (void) sprintf(buf, "%d", getpid());#else (void) strcpy(buf, "Sorry, this isn't UNIX...\n");#endif wl->wl_word = copy(buf); return (wl); case '<': (void) fflush(cp_out); if (!fgets(buf, BSIZE, cp_in)) { clearerr(cp_in); (void) strcpy(buf, "EOF"); } for (s = buf; *s && (*s != '\n'); s++) ; *s = '\0'; wl = cp_lexer(buf); /* This is a hack. */ if (!wl->wl_word) wl->wl_word = copy(""); return (wl); case '?': wl = alloc(wordlist); string++; for (v = variables; v; v = v->va_next) if (eq(v->va_name, string)) break; if (!v) v = cp_enqvar(string); wl->wl_word = copy(v ? "1" : "0"); return (wl); case '#': wl = alloc(wordlist); string++; for (v = variables; v; v = v->va_next) if (eq(v->va_name, string)) break; if (!v) v = cp_enqvar(string); if (!v) { fprintf(cp_err, "Error: %s: no such variable.\n", string); return (NULL); } if (v->va_type == VT_LIST) for (v = v->va_vlist, i = 0; v; v = v->va_next) i++; else i = (v->va_type != VT_BOOL); (void) sprintf(buf, "%d", i); wl->wl_word = copy(buf); return (wl); case '\0': wl = alloc(wordlist); wl->wl_word = copy("$"); return (wl); } /* The notation var[stuff] has two meanings... If this is a real * variable, then the [] denotes range, but if this is a strange * (e.g, device parameter) variable, it could be anything... */ for (v = variables; v; v = v->va_next) if (eq(v->va_name, string)) break; if (!v && isdigit(*string)) { for (v = variables; v; v = v->va_next) if (eq(v->va_name, "argv")) break; range = string; } if (!v) { range = NULL; string = oldstring; v = cp_enqvar(string); } if (!v && (s = getenv(string))) { wl = alloc(wordlist); wl->wl_word = copy(s); return (wl); } if (!v) { fprintf(cp_err, "Error: %s: no such variable.\n", string); return (NULL); } wl = cp_varwl(v); /* Now parse and deal with 'range' ... */ if (range) { for (low = 0; isdigit(*range); range++) low = low * 10 + *range - '0'; if ((*range == '-') && isdigit(range[1])) for (up = 0, range++; isdigit(*range); range++) up = up * 10 + *range - '0'; else if (*range == '-') up = wl_length(wl); else up = low; up--, low--; wl = wl_range(wl, low, up); } return (wl);}/* Print the values of currently defined variables. */struct xxx { struct variable *x_v; char x_char;} ;voidcp_vprint(){ struct variable *v; struct variable *uv1, *uv2; wordlist *wl; int i, j; char *s; struct xxx *vars; cp_usrvars(&uv1, &uv2); for (v = uv1, i = 0; v; v = v->va_next) i++; for (v = uv2; v; v = v->va_next) i++; for (v = variables; v; v = v->va_next) i++; vars = (struct xxx *) tmalloc(sizeof (struct xxx) * i); out_init(); for (v = variables, i = 0; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = ' '; } for (v = uv1; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = '*'; } for (v = uv2; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = '+'; } qsort((char *) vars, i, sizeof (struct xxx), vcmp); for (j = 0; j < i; j++) { if (j && eq(vars[j].x_v->va_name, vars[j - 1].x_v->va_name)) continue; v = vars[j].x_v; if (v->va_type == VT_BOOL) {/* out_printf("%c %s\n", vars[j].x_char, v->va_name); */ sprintf(out_pbuf, "%c %s\n", vars[j].x_char, v->va_name); out_send(out_pbuf); } else { out_printf("%c %s\t", vars[j].x_char, v->va_name); wl = vareval(v->va_name); s = wl_flatten(wl); if (v->va_type == VT_LIST) { out_printf("( %s )\n", s); } else out_printf("%s\n", s); } } return;}static intvcmp(v1, v2) struct xxx *v1, *v2;{ int i; if (i = strcmp(v1->x_v->va_name, v2->x_v->va_name)) return (i); else return (v1->x_char - v2->x_char);}wordlist *cp_varwl(var) struct variable *var;{ wordlist *wl = NULL, *w, *wx = NULL; char buf[BSIZE]; struct variable *vt; switch(var->va_type) { case VT_BOOL: /* Can't ever be false. */ (void) sprintf(buf, "%s", var->va_bool ? "true" : "false"); break; case VT_NUM: (void) sprintf(buf, "%d", var->va_num); break; case VT_REAL: /* This is a case where printnum isn't too good... */ (void) sprintf(buf, "%G", var->va_real); break; case VT_STRING: (void) strcpy(buf, cp_unquote(var->va_string)); break; case VT_LIST: /* The tricky case. */ for (vt = var->va_vlist; vt; vt = vt->va_next) { w = cp_varwl(vt); if (wl == NULL) wl = wx = w; else { wx->wl_next = w; w->wl_prev = wx; wx = w; } } return (wl); default: fprintf(cp_err, "cp_varwl: Internal Error: bad variable type %d\n", var->va_type); return (NULL); } wl = alloc(wordlist); wl->wl_next = wl->wl_prev = NULL; wl->wl_word = copy(buf); return (wl);}/* Set a variable. */voidcp_vset(varname, type, value) char *varname; char type; char *value;{ struct variable *v; int i; bool alreadythere = false;/* for (v = variables; v; v = v->va_next) ; printf("ok while setting %s\n", varname);*/ varname = cp_unquote(varname); for (v = variables; v; v = v->va_next) if (eq(varname, v->va_name)) { alreadythere = true; break; } if (!v) { v = alloc(variable); v->va_name = copy(varname); } switch (type) { case VT_BOOL: if (* ((bool *) value) == false) { cp_remvar(varname); return; } else v->va_bool = true; break; case VT_NUM: v->va_num = * (int *) value; break; case VT_REAL: v->va_real = * (double *) value; break; case VT_STRING: v->va_string = copy(value); break; case VT_LIST: v->va_vlist = (struct variable *) value; break; default: fprintf(cp_err, "cp_vset: Internal Error: bad variable type %d.\n", type); return; } v->va_type = type; /* Now, see if there is anything interesting going on. We recognise * these special variables: noglob, nonomatch, history, echo, * noclobber, prompt, and verbose. cp_remvar looks for these variables * too. The host program will get any others. */ if (eq(varname, "noglob")) cp_noglob = true; else if (eq(varname, "nonomatch")) cp_nonomatch = true; else if (eq(varname, "history") && (type == VT_NUM)) cp_maxhistlength = v->va_num; else if (eq(varname, "history") && (type == VT_REAL)) cp_maxhistlength = v->va_real; else if (eq(varname, "noclobber")) cp_noclobber = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -