Jspice3
variable.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Do variable substitution.
10  */
11 
12 #include "spice.h"
13 #include "misc.h"
14 #include "cpdefs.h"
15 #include "suffix.h"
16 
17 #ifdef __STDC__
18 static wordlist *vareval(char*);
19 static wordlist *var2wl(struct variable*,int,int);
20 static char *eval_range(char*);
21 static char *iv_special(char*);
22 static int vcmp();
23 static struct variable *getlist(wordlist**);
24 #else
25 static wordlist *vareval();
26 static wordlist *var2wl();
27 static char *eval_range();
28 static char *iv_special();
29 static int vcmp();
30 static struct variable *getlist();
31 #endif
32 
33 /* A variable substitution is
34  * indicated by a $, and the variable name is the following string of
35  * non-special characters. All variable values are inserted as a single
36  * word, except for lists, which are a list of words.
37  * A routine cp_usrset must be supplied by the host program to deal
38  * with variables that aren't used by cshpar -- it should be
39  * cp_usrset(var, isset), where var is a variable *, and isset is
40  * true if the variable is being set, false if unset.
41  * Also required is a routine cp_enqvar(name) which returns a struct
42  * variable *, which allows the host program to provide values for
43  * non-cshpar variables.
44  */
45 
46 bool cp_noglob = true; /* This is just a bad thing. */
47 bool cp_nonomatch = false;
48 bool cp_noclobber = false;
49 bool cp_ignoreeof = false;
50 
51 char cp_dol = '$';
52 
53 static void *variables;
54 
55 /* Non-alphanumeric characters that may appear in variable names. < is very
56  * special...
57  */
58 
59 #define VALIDCHARS "_<#?@.()[]&"
60 
61 void
63 
64 wordlist **list;
65 {
66  wordlist *wl, *nwl, *wlist, *twl;
67  char *s, *t, buf[BSIZE_SP], wbuf[BSIZE_SP];
68  int i, lev1, lev2;
69 
70 
71  if (list == NULL)
72  return;
73  wlist = *list;
74  for (wl = wlist; wl; wl = wl->wl_next) {
75  t = wl->wl_word;
76  i = 0;
77  while (s = strchr(t, cp_dol)) {
78  while (t < s)
79  wbuf[i++] = *t++;
80  wbuf[i] = '\0';
81  (void) strcpy(buf, ++s);
82  s = buf;
83  t++;
84  /* Get s and t past the end of the var name. */
85  if (*s &&
86  (isalphanum(*s) || strchr(VALIDCHARS, *s) || *s == cp_dol)) {
87  t++;
88  s++;
89  }
90  lev1 = lev2 = 0;
91  for ( ; *s; t++,s++) {
92  if (isalphanum(*s))
93  continue;
94  if (*s == '[') {
95  lev1++;
96  continue;
97  }
98  if (*s == '(') {
99  lev2++;
100  continue;
101  }
102  if (*s == ']') {
103  if (lev1) {
104  lev1--;
105  continue;
106  }
107  break;
108  }
109  if (*s == ')') {
110  if (lev2) {
111  lev2--;
112  continue;
113  }
114  break;
115  }
116  if (strchr(VALIDCHARS, *s))
117  continue;
118  if (lev1 || lev2)
119  continue;
120  break;
121  }
122  if (!*s && (lev1 || lev2)) {
123  char *str;
124  wordlist *ww;
125 
126  /* split token, concatenate them */
127  if (wl->wl_next) {
128  ww = wl->wl_next;
129  str = tmalloc(
130  strlen(wl->wl_word) + strlen(ww->wl_word) + 1);
131  strcpy(str,wl->wl_word);
132  strcat(str,ww->wl_word);
133  txfree(wl->wl_word);
134  wl->wl_word = str;
135  txfree(ww->wl_word);
136  wl->wl_next = ww->wl_next;
137  wl->wl_next->wl_prev = wl;
138  txfree((char*)ww);
139  t = wl->wl_word;
140  i = 0;
141  continue;
142  }
143  else {
144  fprintf(cp_err,
145  "Error: unbalanced parentheses or brackets\n");
146  wl_print(wlist,cp_err);
147  fprintf(cp_err,"\n");
148  *list = NULL;
149  return;
150  }
151  }
152 
153  *s = '\0';
154  nwl = vareval(buf);
155  if (i) {
156  (void) strcpy(buf, wbuf);
157  if (nwl) {
158  (void) strcat(buf, nwl->wl_word);
159  tfree(nwl->wl_word);
160  }
161  else {
162  nwl = alloc(struct wordlist);
163  }
164  nwl->wl_word = copy(buf);
165  }
166  if (!(twl = wl_splice(wl, nwl))) {
167  wl_free(wlist);
168  *list = NULL;
169  return;
170  }
171  if (wl == wlist)
172  wlist = nwl;
173  wl = twl;
174  (void) strcpy(buf, wl->wl_word);
175  i = strlen(buf);
176  (void) strcat(buf, t);
177  tfree(wl->wl_word);
178  wl->wl_word = copy(buf);
179  t = &wl->wl_word[i];
180  s = wl->wl_word;
181  for (i = 0; s < t; s++)
182  wbuf[i++] = *s;
183  }
184  }
185  *list = wlist;
186  return;
187 }
188 
189 
190 /* Evaluate a variable. */
191 
192 static wordlist *
193 vareval(string)
194 
195 char *string;
196 {
197  struct variable *v, *vv;
198  wordlist *wl;
199  char buf[BSIZE_SP], *s;
200  char *range = NULL;
201  int i, up, low;
202 
203  string = copy(string);
204 
205  cp_wstrip(string);
206  if (s = strchr(string, '[')) {
207  *s = '\0';
208  range = eval_range(s+1);
209  }
210 
211  switch (*string) {
212 
213  case '$':
214  wl = alloc(struct wordlist);
215  (void) sprintf(buf, "%d", getpid());
216  wl->wl_word = copy(buf);
217  goto end;
218 
219  case '<':
220  (void) fflush(cp_out);
221  if (!fgets(buf, BSIZE_SP, cp_in)) {
222  clearerr(cp_in);
223  (void) strcpy(buf, "EOF");
224  }
225  for (s = buf; *s && (*s != '\n'); s++) ;
226  *s = '\0';
227  wl = cp_lexer(buf);
228  /* This is a hack. */
229  if (!wl->wl_word)
230  wl->wl_word = copy("");
231  goto end;
232 
233  case '?':
234  wl = alloc(struct wordlist);
235  s = string + 1;
236  if (htab_get(s,variables))
237  wl->wl_word = copy("1");
238  else {
239  v = cp_enqvar(s);
240  if (v) {
241  wl->wl_word = copy("1");
242  va_free(v);
243  }
244  else
245  wl->wl_word = copy("0");
246  }
247  goto end;
248 
249  case '#':
250  wl = alloc(struct wordlist);
251  s = string + 1;
252  v = (struct variable *)htab_get(s,variables);
253  if (v) {
254  if (v->va_type == VT_LIST)
255  for (v = v->va_vlist, i = 0; v; v = v->va_next,i++);
256  else
257  i = (v->va_type != VT_BOOL);
258  }
259  else {
260  /* cp_enqvar() takes care of range */
261  if (range) {
262  sprintf(buf,"%s[%s",s,range);
263  txfree(string);
264  string = copy(buf);
265  }
266  v = cp_enqvar(string);
267  if (v) {
268  if (v->va_type == VT_LIST)
269  for (v = v->va_vlist, i = 0; v; v = v->va_next,i++);
270  else
271  i = (v->va_type != VT_BOOL);
272  va_free(v);
273  }
274  else {
275  fprintf(cp_err, "Error: %s: no such variable.\n",s);
276  wl = (wordlist *)NULL;
277  goto end;
278  }
279  }
280  (void) sprintf(buf, "%d", i);
281  wl->wl_word = copy(buf);
282  goto end;
283 
284  case '\0':
285  wl = alloc(struct wordlist);
286  wl->wl_word = copy("$");
287  goto end;
288  }
289 
290  /* The notation var[stuff] has two meanings... If this is a real
291  * variable, then the [] denotes range, but if this is a strange
292  * (e.g, device parameter) variable, it could be anything...
293  */
294  v = (struct variable *)htab_get(string,variables);
295  if (!v && isdigit(*string)) {
296  v = (struct variable *)htab_get("arvg",variables);
297  if (range)
298  txfree(range);
299  range = copy(string);
300  }
301 
302  if (!v) {
303  /* cp_enqvar() takes care of range */
304  if (range) {
305  sprintf(buf,"%s[%s",string,range);
306  txfree(string);
307  string = copy(buf);
308  }
309  /* take care of forms like v($something) */
310  if (*string == '&' && strchr("vViI",*(string+1)) &&
311  *(string+2) == '(' && *(string+3) == '$')
312  string = iv_special(string);
313 
314  v = cp_enqvar(string);
315  if (v) {
316  wl = cp_varwl(v);
317  va_free(v);
318  goto end;
319  }
320  }
321  if (!v) {
322  if (s = getenv(string)) {
323  wl = alloc(struct wordlist);
324  wl->wl_word = copy(s);
325  goto end;
326  }
327  }
328  if (!v) {
329  fprintf(cp_err, "Error: %s: no such variable.\n", string);
330  wl = (wordlist *)NULL;
331  goto end;
332  }
333 
334  /* Now parse and deal with 'range' ... */
335  if (range) {
336  s = range;
337  if (!isdigit(*s) && *s != '-')
338  fprintf(cp_err,
339  "Warning: nonparseable range specified, %s[%s\n",string,s);
340 
341  for (low = 0; isdigit(*s); s++)
342  low = low * 10 + *s - '0';
343  if ((*s == '-') && isdigit(s[1]))
344  for (up = 0, s++; isdigit(*s); s++)
345  up = up * 10 + *s - '0';
346  else if (*s == '-') {
347  if (v->va_type != VT_LIST)
348  up = 0;
349  else {
350  for (up = 0, vv = v->va_vlist; vv; vv = vv->va_next,up++) ;
351  if (!up) {
352  wl = (wordlist*)NULL;
353  goto end;
354  }
355  up--;
356  }
357  }
358  else
359  up = low;
360  wl = var2wl(v, low, up);
361  }
362  else
363  wl = cp_varwl(v);
364 
365 end:
366  if (range)
367  txfree(range);
368  txfree(string);
369  return (wl);
370 }
371 
372 
373 static struct wordlist *
374 var2wl(v,lo,hi)
375 
376 struct variable *v;
377 int lo, hi;
378 {
379  struct variable *vx, *tx, *vn, *vlo, *vl0, *vl1;
380  wordlist *wl;
381  int i;
382  bool rev = false;
383 
384  if (v->va_type != VT_LIST) {
385  if (lo != 0 && hi != 0)
386  return (NULL);
387  else
388  return (cp_varwl(v));
389  }
390  if (hi < lo) {
391  i = hi;
392  hi = lo;
393  lo = i;
394  rev = true;
395  }
396 
397  vl0 = v->va_vlist;
398  vx = vl0;
399  for (i = 0; i < lo; i++) {
400  vx = vx->va_next;
401  if (vx == NULL)
402  return (NULL);
403  }
404  vlo = vx;
405  for (i = lo; i < hi; i++) {
406  vx = vx->va_next;
407  if (vx == NULL)
408  break;
409  }
410  if (vx) {
411  vl1 = vx->va_next;
412  vx->va_next = NULL;
413  }
414 
415  if (rev) {
416  tx = NULL;
417  for ( ; vlo; vlo = vn) {
418  vn = vlo->va_next;
419  vlo->va_next = tx;
420  tx = vlo;
421  }
422  vlo = tx;
423  }
424 
425  v->va_vlist = vlo;
426  wl = cp_varwl(v);
427 
428  if (rev) {
429  tx = NULL;
430  for ( ; vlo; vlo = vn) {
431  vn = vlo->va_next;
432  vlo->va_next = tx;
433  tx = vlo;
434  }
435  vlo = tx;
436  }
437 
438  if (vx)
439  vx->va_next = vl1;
440  v->va_vlist = vl0;
441  return (wl);
442 }
443 
444 
445 static char *
446 eval_range(string)
447 
448 /* Parse and evaluate the range specification, replacing any shell
449  * variables by integer equivalents.
450  */
451 char *string;
452 {
453  char *s, *t, *tok1, *tok2, *tokd = NULL, *tokb = NULL;
454  char buf[128];
455  int i, lev1, lev2;
456  wordlist *wl;
457 
458  /* get rid of any white space */
459  t = string;
460  s = tmalloc(strlen(string)+1);
461  string = s;
462  for ( ; *t; t++) {
463  if (isspace(*t))
464  continue;
465  *s++ = *t;
466  }
467  *s = '\0';
468 
469  if (!strchr(string,'$'))
470  return (string);
471 
472  s = tok1 = string;
473  lev1 = lev2 = 0;
474  while (*s) {
475  if (*s == '[')
476  lev1++;
477  else if (*s == '(')
478  lev2++;
479  else if (*s == ']') {
480  if (lev1)
481  lev1--;
482  else if (!lev2)
483  /* [tok1] */
484  break;
485  }
486  else if (*s == ')') {
487  if (lev2)
488  lev2--;
489  }
490  else if (*s == '-' && !lev1 && !lev2) {
491  if (s == tok1)
492  /* [-tok2] */
493  tok1 = NULL;
494  /* [tok1-...] */
495  break;
496  }
497  s++;
498  }
499  if (*s == '-') {
500  tokd = s;
501  *s = '\0';
502  s++;
503  tok2 = s;
504  lev1 = lev2 = 0;
505  while (*s) {
506  if (*s == '[')
507  lev1++;
508  else if (*s == '(')
509  lev2++;
510  else if (*s == ')') {
511  if (lev2)
512  lev2--;
513  }
514  else if (*s == ']') {
515  if (lev1)
516  lev1--;
517  else if (!lev2) {
518  if (tok2 == s) {
519  /* [...-] */
520  tok2 == NULL;
521  break;
522  }
523  /* [...-tok2] */
524  tokb = s;
525  *s = '\0';
526  break;
527  }
528  }
529  s++;
530  }
531  if (!*s && tok2 == s) {
532  /* no last ], not to worry */
533  tok2 = NULL;
534  }
535  }
536  else {
537  if (*s == ']') {
538  tokb = s;
539  *s = '\0';
540  }
541  tok2 = NULL;
542  }
543 
544  *buf = '\0';
545  if (tok1) {
546  if (*tok1 == '$') {
547  tok1++;
548  wl = vareval(tok1);
549  if (wl) {
550  tok1 = wl_flatten(wl);
551  wl_free(wl);
552  i = atof(tok1) + .5;
553  txfree(tok1);
554  }
555  else
556  i = 0;
557  sprintf(buf,"%d",i);
558  }
559  else
560  sprintf(buf,"%s",tok1);
561  }
562  if (tokd)
563  strcat(buf,"-");
564  if (tok2) {
565  if (*tok2 == '$') {
566  tok2++;
567  wl = vareval(tok2);
568  if (wl) {
569  tok2 = wl_flatten(wl);
570  wl_free(wl);
571  i = atof(tok2) + .5;
572  txfree(tok2);
573  }
574  else
575  i = 0;
576  sprintf(buf + strlen(buf),"%d",i);
577  }
578  else
579  sprintf(buf + strlen(buf),"%s",tok2);
580 
581  }
582  strcat(buf,"]");
583  txfree(string);
584  return (copy(buf));
585 }
586 
587 
588 static char *
590 
591 /* this substitutes in forms like v($something) */
592 char *str;
593 {
594  char *s, *t, *u;
595  wordlist *wl;
596  int cnt;
597 
598  cnt = 1;
599  for (s = str+4; *s; s++) {
600  if (*s == '(')
601  cnt++;
602  else if (*s == ')')
603  cnt--;
604  if (!cnt)
605  break;
606  }
607  if (*s != ')')
608  /* no closing paren, error */
609  return (str);
610  *s = '\0';
611  wl = vareval(str+4);
612  *s = ')';
613  t = wl_flatten(wl);
614  wl_free(wl);
615  if (!t)
616  /* some error occurred */
617  return (str);
618  u = tmalloc(strlen(t) + strlen(s) + 4);
619  u[0] = '&';
620  u[1] = str[1];
621  u[2] = '(';
622  strcpy(u+3,t);
623  strcat(u,s);
624  txfree(str);
625  txfree(t);
626  return (u);
627 }
628 
629 
630 /* Print the values of currently defined variables. */
631 
632 struct xxx {
633  struct variable *x_v;
634  char x_char;
635 } ;
636 
637 void
639 {
640  struct variable *v;
641  struct variable *uv1, *uv2;
642  wordlist *wl, *wl0;
643  int i, j;
644  char *s;
645  struct xxx *vars;
646 
647  cp_usrvars(&uv1, &uv2);
648 
649  for (v = uv1, i = 0; v; v = v->va_next)
650  i++;
651  for (v = uv2; v; v = v->va_next)
652  i++;
653  wl0 = (wordlist*)htab_list(variables);
654  i += wl_length(wl0);
655 
656  vars = (struct xxx *) tmalloc(sizeof (struct xxx) * i);
657 
658  for (wl = wl0, i = 0; wl; wl = wl->wl_next, i++) {
659  vars[i].x_v = (struct variable*)((char**)wl->wl_word)[1];
660  vars[i].x_char = ' ';
661  }
662  for (v = uv1; v; v = v->va_next, i++) {
663  vars[i].x_v = v;
664  vars[i].x_char = '*';
665  }
666  for (v = uv2; v; v = v->va_next, i++) {
667  vars[i].x_v = v;
668  vars[i].x_char = '+';
669  }
670 
671  qsort((char *) vars, i, sizeof (struct xxx), vcmp);
672 
673  out_send("\n");
674  for (j = 0; j < i; j++) {
675  if (j && eq(vars[j].x_v->va_name, vars[j - 1].x_v->va_name))
676  continue;
677  v = vars[j].x_v;
678  if (v->va_type == VT_BOOL) {
679  out_printf("%c %-18s\n", vars[j].x_char, v->va_name);
680  }
681  else {
682  out_printf("%c %-18s", vars[j].x_char, v->va_name);
683  wl = vareval(v->va_name);
684  s = wl_flatten(wl);
685  wl_free(wl);
686  if (v->va_type == VT_LIST)
687  out_printf("( %s )\n", s);
688  else
689  out_printf("%s\n", s);
690  txfree(s);
691  }
692  }
693 
694  wl_free(wl0);
695  va_free(uv1);
696  va_free(uv2);
697  txfree((char*)vars);
698  out_send("\n");
699  return;
700 }
701 
702 
703 static int
704 vcmp(v1, v2)
705 
706 struct xxx *v1, *v2;
707 {
708  int i;
709 
710  if (i = strcmp(v1->x_v->va_name, v2->x_v->va_name))
711  return (i);
712  else
713  return (v1->x_char - v2->x_char);
714 }
715 
716 
717 wordlist *
719 
720 struct variable *var;
721 {
722  wordlist *wl = NULL, *w, *wx = NULL;
723  char buf[BSIZE_SP];
724  struct variable *vt;
725 
726  switch(var->va_type) {
727  case VT_BOOL:
728  /* Can't ever be false. */
729  (void) sprintf(buf, "%s", var->va_bool ? "true" : "false");
730  break;
731  case VT_NUM:
732  (void) sprintf(buf, "%d", var->va_num);
733  break;
734  case VT_REAL:
735  /* This is a case where printnum isn't too good... */
736  (void) sprintf(buf, "%g", var->va_real);
737  (void) fixxp2(buf);
738  break;
739  case VT_STRING:
740  if (var->va_string == NULL)
741  (void)strcpy(buf,"(null)");
742  else {
743  char *t = copy(var->va_string);
744  cp_unquote(t);
745  (void) strcpy(buf, t);
746  tfree(t);
747  }
748  break;
749  case VT_LIST: /* The tricky case. */
750  for (vt = var->va_vlist; vt; vt = vt->va_next) {
751  if ((w = cp_varwl(vt)) == NULL)
752  continue;
753  if (wl == NULL) {
754  wl = wx = w;
755  }
756  else {
757  wx->wl_next = w;
758  w->wl_prev = wx;
759  }
760  while (wx->wl_next)
761  wx = wx->wl_next;
762  }
763  return (wl);
764  default:
765  fprintf(cp_err,
766  "cp_varwl: Internal Error: bad variable type %d\n",
767  var->va_type);
768  return (NULL);
769  }
770  wl = alloc(struct wordlist);
771  wl->wl_next = wl->wl_prev = NULL;
772  wl->wl_word = copy(buf);
773  return (wl);
774 }
775 
776 
777 /* Set a variable. */
778 /* This now handles forms like "set var[n] = whatever", where var must be
779  * a previously defined list, and n (index 0) must be in bounds, and
780  * whatever must be of the same type. n must be an explicit integer.
781  */
782 
783 void
784 cp_vset(varname, type, value)
785 
786 char *varname;
787 char type;
788 char *value;
789 {
790  struct variable *v, *vv;
791  int i, rnum;
792  bool alreadythere = false, rangefound = false;
793  char *t, *range;
794  char vname[BSIZE_SP];
795 
796  strcpy(vname,varname);
797  cp_unquote(vname);
798 
799  if (eq(vname,"argv") || eq(vname,"argc"))
800  return;
801 
802  range = strchr(vname,'[');
803  if (range) {
804  rangefound = true;
805  *range = '\0';
806  range++;
807  range = eval_range(range);
808  for (rnum = 0,t = range; isdigit(*t); t++)
809  rnum = rnum * 10 + *t - '0';
810  tfree(range);
811  }
812  if ((v = (struct variable *)htab_get(vname,variables)) == NULL) {
813  if (range) {
814  fprintf(cp_err,
815  "Error: %s is not set, length unknown.\n",vname);
816  return;
817  }
818  v = alloc(struct variable);
819  v->va_name = copy(vname);
820  }
821  else {
822  alreadythere = true;
823  if (range) {
824  if (v->va_type != VT_LIST) {
825  fprintf(cp_err,"Error: %s is not a list.\n",vname);
826  return;
827  }
828  for (vv = v->va_vlist,i = rnum; vv && i; vv = vv->va_next,i--);
829  if (vv == NULL) {
830  fprintf(cp_err,
831  "Error: %d out of range for %s.\n",rnum,vname);
832  return;
833  }
834  if (type != vv->va_type) {
835  fprintf(cp_err,"Error: type mismatch for %s.\n",vname);
836  return;
837  }
838  switch (type) {
839  case VT_BOOL:
840  vv->va_bool = *(int*)value;
841  break;
842  case VT_NUM:
843  vv->va_num = *(int*)value;
844  break;
845  case VT_REAL:
846  vv->va_real = *(double*)value;
847  break;
848  case VT_STRING:
849  txfree(vv->va_string);
850  vv->va_string = copy(value);
851  break;
852  case VT_LIST:
853  va_free(vv->va_vlist);
854  vv->va_vlist = (struct variable*)value;
855  break;
856  default:
857  fprintf(cp_err,
858  "cp_vset: Internal Error: bad variable type %d.\n",
859  type);
860  }
861  return;
862  }
863  if (v->va_type == VT_STRING)
864  txfree(v->va_string);
865  else if (v->va_type == VT_LIST)
866  va_free(v->va_vlist);
867  }
868 
869  switch (type) {
870  case VT_BOOL:
871  if (* ((bool *) value) == false) {
872  cp_remvar(vname);
873  return;
874  }
875  else
876  v->va_bool = true;
877  break;
878 
879  case VT_NUM:
880  v->va_num = * (int *) value;
881  break;
882 
883  case VT_REAL:
884  v->va_real = * (double *) value;
885  break;
886 
887  case VT_STRING:
888  v->va_string = copy(value);
889  break;
890 
891  case VT_LIST:
892  v->va_vlist = (struct variable *) value;
893  break;
894 
895  default:
896  fprintf(cp_err,
897  "cp_vset: Internal Error: bad variable type %d.\n",type);
898  return;
899  }
900  v->va_type = type;
901 
902  i = cp_internalset(v,true);
903 
904  switch (i) {
905 
906  case US_OK:
907  /* Normal case. */
908  if (!alreadythere) {
909  if (!variables)
910  variables = htab_init();
911  htab_add(v->va_name,(void*)v,variables);
912  }
913  break;
914 
915  case US_DONTRECORD:
916  /* Do nothing... */
917  if (alreadythere) {
918  fprintf(cp_err,
919  "cp_vset: Internal Error: %s already there, but 'dont record'\n",
920  v->va_name);
921  }
922  break;
923 
924  case US_READONLY:
925  /* Badness... */
926  fprintf(cp_err, "Error: %s is a read-only variable.\n",
927  v->va_name);
928  if (alreadythere)
929  fprintf(cp_err,
930  "cp_vset: Internal Error: it was already there too!!\n");
931  break;
932 
933  default:
934  fprintf(cp_err, "cp_vset: Internal Error: bad US val %d\n", i);
935  break;
936  }
937  return;
938 }
939 
940 
941 void
942 cp_remvar(varname)
943 
944 char *varname;
945 {
946  struct variable *v;
947  bool found = true;
948  int i;
949 
950  if (eq(varname,"argv") || eq(varname,"argc")) {
951  return;
952  }
953  v = (struct variable *)htab_get(varname,variables);
954  if (!v) {
955  /* Gotta make up a var struct for cp_internalset()... */
956  v = alloc(struct variable);
957  v->va_name = varname;
958  found = false;
959  }
960 
961  i = cp_internalset(v,false);
962 
963  switch (i) {
964 
965  case US_OK:
966  /* Normal case. */
967  if (found) {
968  htab_delete(varname,variables);
969  va_free(v);
970  }
971  break;
972 
973  case US_DONTRECORD:
974  /* Do nothing... */
975  if (found)
976  fprintf(cp_err,
977  "cp_remvar: Internal Error: var %d in list but shouldn't be\n",
978  varname);
979  break;
980 
981  case US_READONLY:
982  /* Badness... */
983  fprintf(cp_err, "Error: %s is a read-only variable.\n",
984  v->va_name);
985  if (found)
986  fprintf(cp_err,
987  "cp_remvar: Internal Error: var %d in list but shouldn't be\n",
988  varname);
989  break;
990 
991  default:
992  fprintf(cp_err, "cp_remvar: Internal Error: bad US val %d\n",i);
993  break;
994  }
995  if (!found)
996  txfree((char*)v);
997  return;
998 }
999 
1000 
1001 /* The set command. Syntax is
1002  * set [opt ...] [opt = val ...]. Val may be a string, an int, a float,
1003  * or a list of the form (elt1 elt2 ...).
1004  */
1005 
1006 void
1008 
1009 wordlist *wl;
1010 {
1011  struct variable *vars, *v0;
1012  char *s;
1013 
1014  if (wl == NULL) {
1015  cp_vprint();
1016  return;
1017  }
1018  v0 = vars = cp_setparse(wl);
1019 
1020  /* This is sort of a hassle... */
1021  while (vars) {
1022  switch (vars->va_type) {
1023  case VT_BOOL:
1024  s = (char *) &vars->va_bool;
1025  break;
1026  case VT_NUM:
1027  s = (char *) &vars->va_num;
1028  break;
1029  case VT_REAL:
1030  s = (char *) &vars->va_real;
1031  break;
1032  case VT_STRING:
1033  s = vars->va_string;
1034  break;
1035  case VT_LIST:
1036  s = (char *) va_copy(vars->va_vlist);
1037  break;
1038  }
1039  cp_vset(vars->va_name, vars->va_type, s);
1040  vars = vars->va_next;
1041  }
1042  va_free(v0);
1043  return;
1044 }
1045 
1046 
1047 struct variable *
1049 
1050 wordlist *wl;
1051 {
1052  char *name, *val, *s, *st;
1053  double *td;
1054  struct variable *vv, *lv;
1055  struct variable *vars = NULL;
1056 
1057  while (wl) {
1058  name = copy(wl->wl_word);
1059  cp_unquote(name);
1060  wl = wl->wl_next;
1061  if (((wl == NULL) || (*wl->wl_word != '=')) &&
1062  strchr(name, '=') == NULL) {
1063  vv = alloc(struct variable);
1064  vv->va_name = name;
1065  vv->va_type = VT_BOOL;
1066  vv->va_bool = true;
1067  vv->va_next = vars;
1068  vars = vv;
1069  continue;
1070  }
1071  if (wl && eq(wl->wl_word, "=")) {
1072  wl = wl->wl_next;
1073  if (wl == NULL || strchr(name,'=') != NULL)
1074  goto bad;
1075  val = wl->wl_word;
1076  wl = wl->wl_next;
1077  }
1078  else if (wl && (*wl->wl_word == '=')) {
1079  if (strchr(name, '=') != NULL)
1080  goto bad;
1081  val = wl->wl_word + 1;
1082  wl = wl->wl_next;
1083  }
1084  else if (s = strchr(name, '=')) {
1085  if (s == name) goto bad;
1086  val = s + 1;
1087  *s = '\0';
1088  if (*val == '\0') {
1089  if (wl == NULL) {
1090  fprintf(cp_err,
1091  "Error: %s equals what?.\n",name);
1092  goto bad;
1093  }
1094  val = wl->wl_word;
1095  wl = wl->wl_next;
1096  }
1097  }
1098  else {
1099  goto bad;
1100  }
1101  val = copy(val);
1102  cp_unquote(val);
1103  if (eq(val, "(")) {
1104  tfree(val);
1105  lv = getlist(&wl);
1106  if (!lv)
1107  goto bad;
1108  vv = alloc(struct variable);
1109  vv->va_name = name;
1110  vv->va_type = VT_LIST;
1111  vv->va_vlist = lv;
1112  vv->va_next = vars;
1113  vars = vv;
1114 
1115  continue;
1116  }
1117 
1118  st = val;
1119  td = ft_numparse(&st, false);
1120  vv = alloc(struct variable);
1121  vv->va_name = name;
1122  vv->va_next = vars;
1123  vars = vv;
1124  if (td && *st == '\0') {
1125  vv->va_type = VT_REAL;
1126  vv->va_real = *td;
1127  tfree(val);
1128  }
1129  else {
1130  vv->va_type = VT_STRING;
1131  vv->va_string = val;
1132  }
1133  }
1134  return (vars);
1135 bad:
1136  fprintf(cp_err, "Error: bad set form.\n");
1137  tfree(name);
1138  if (vars) va_free(vars);
1139  return (NULL);
1140 }
1141 
1142 
1143 static struct variable *
1144 getlist(wlist)
1145 
1146 wordlist **wlist;
1147 {
1148  wordlist *wl = *wlist;
1149  struct variable *listv = NULL, *vv;
1150  char *ss, *st;
1151  double *td;
1152 
1153  while (wl && wl->wl_word) {
1154  if (eq(wl->wl_word, ")")) {
1155  wl = wl->wl_next;
1156  *wlist = wl;
1157  return (listv);
1158  }
1159  if (!listv)
1160  listv = vv = alloc(struct variable);
1161  else {
1162  vv->va_next = alloc(struct variable);
1163  vv = vv->va_next;
1164  }
1165  if (eq(wl->wl_word, "(")) {
1166  wl = wl->wl_next;
1167  vv->va_type = VT_LIST;
1168  vv->va_vlist = getlist(&wl);
1169  if (vv->va_vlist == NULL) {
1170  va_free(listv);
1171  *wlist = wl;
1172  return (NULL);
1173  }
1174  continue;
1175  }
1176  st = ss = copy(wl->wl_word);
1177  cp_unquote(ss);
1178  td = ft_numparse(&ss, false);
1179  if (td && *ss == '\0') {
1180  vv->va_type = VT_REAL;
1181  vv->va_real = *td;
1182  tfree(st);
1183  }
1184  else {
1185  vv->va_type = VT_STRING;
1186  vv->va_string = st;
1187  }
1188  wl = wl->wl_next;
1189  }
1190  *wlist = wl;
1191  va_free(listv);
1192  return (NULL);
1193 }
1194 
1195 
1196 void
1198 
1199 wordlist *wl;
1200 {
1201  char *name;
1202  struct variable *var, *nv;
1203  wordlist *tl, *wl0;
1204 
1205  if (eq(wl->wl_word, "*")) {
1206  wl0 = (wordlist*)htab_wl(variables);
1207  for (tl = wl0; tl; tl = tl->wl_next)
1208  cp_remvar(tl->wl_word);
1209  wl_free(wl0);
1210  return;
1211  }
1212  while (wl != NULL) {
1213  name = wl->wl_word;
1214  cp_remvar(name);
1215  wl = wl->wl_next;
1216  }
1217  return;
1218 }
1219 
1220 
1221 /* Shift a list variable, by default argv, one to the left (or more if a
1222  * second argument is given.
1223  */
1224 
1225 void
1227 
1228 wordlist *wl;
1229 {
1230  struct variable *v, *vv, *lv;
1231  char *n = "argv";
1232  int num = 1;
1233 
1234  if (wl) {
1235  n = wl->wl_word;
1236  wl = wl->wl_next;
1237  }
1238  if (wl)
1239  num = scannum(wl->wl_word);
1240 
1241  v = (struct variable *)htab_get(n,variables);
1242  if (!v) {
1243  fprintf(cp_err, "Error: %s: no such variable\n", n);
1244  return;
1245  }
1246  if (v->va_type != VT_LIST) {
1247  fprintf(cp_err, "Error: %s not of type list\n", n);
1248  return;
1249  }
1250 
1251  lv = NULL;
1252  for (vv = v->va_vlist; vv && (num > 0); num--) {
1253  lv = vv;
1254  vv = vv->va_next;
1255  }
1256 
1257  if (num) {
1258  fprintf(cp_err, "Error: variable %s not long enough\n", n);
1259  return;
1260  }
1261 
1262  if (lv) {
1263  lv->va_next = NULL;
1264  va_free(lv);
1265  }
1266  v->va_vlist = vv;
1267  return;
1268 }
1269 
1270 
1271 /* Determine the value of a variable. Fail if the variable is unset,
1272  * and if the type doesn't match, try and make it work...
1273  */
1274 
1275 bool
1276 cp_getvar(name, type, retval)
1277 
1278 int type;
1279 char *name, *retval;
1280 {
1281  struct variable *v;
1282 
1283  v = (struct variable *)htab_get(name,variables);
1284  if (v == NULL) {
1285  if (type == VT_BOOL)
1286  * (bool *) retval = false;
1287  return (false);
1288  }
1289  if (v->va_type == type) {
1290  switch (type) {
1291  case VT_BOOL:
1292  * (bool *) retval = true;
1293  break;
1294  case VT_NUM: {
1295  int *i;
1296  i = (int *) retval;
1297  *i = v->va_num;
1298  break;
1299  }
1300  case VT_REAL: {
1301  double *d;
1302  d = (double *) retval;
1303  *d = v->va_real;
1304  break;
1305  }
1306  case VT_STRING: { /* Gotta be careful to have room. */
1307  char *s;
1308  s = copy(v->va_string);
1309  cp_unquote(s);
1310  cp_wstrip(s);
1311  (void) strcpy(retval, s);
1312  txfree(s);
1313  break;
1314  }
1315  case VT_LIST: { /* Funny case... */
1316  struct variable **tv;
1317  tv = (struct variable **) retval;
1318  *tv = v->va_vlist;
1319  break;
1320  }
1321  default:
1322  fprintf(cp_err,
1323  "cp_getvar: Internal Error: bad var type %d.\n", type);
1324  break;
1325  }
1326  return (true);
1327  }
1328  else {
1329  /* Try to coerce it.. */
1330  if ((type == VT_NUM) && (v->va_type == VT_REAL)) {
1331  int *i;
1332  i = (int *) retval;
1333  *i = (int) v->va_real;
1334  return (true);
1335  }
1336  else if ((type == VT_REAL) && (v->va_type == VT_NUM)) {
1337  double *d;
1338  d = (double *) retval;
1339  *d = (double) v->va_num;
1340  return (true);
1341  }
1342  else if ((type == VT_STRING) && (v->va_type == VT_NUM)) {
1343  (void) sprintf(retval, "%d", v->va_num);
1344  return (true);
1345  }
1346  else if ((type == VT_STRING) && (v->va_type == VT_REAL)) {
1347  (void) sprintf(retval, "%f", v->va_real);
1348  return (true);
1349  }
1350  return (false);
1351  }
1352 }
1353 
1354 
1355 /* free a variable structure */
1356 void
1358 
1359 struct variable *v;
1360 {
1361  struct variable *vv;
1362 
1363  for ( ; v; v = vv) {
1364  vv = v->va_next;
1365  txfree(v->va_name);
1366  if (v->va_type == VT_STRING)
1367  txfree(v->va_string);
1368  if (v->va_type == VT_LIST)
1369  va_free(v->va_vlist);
1370  txfree((char*)v);
1371  }
1372 }
1373 
1374 
1375 /* copy a variable structure */
1376 struct variable *
1378 
1379 struct variable *v;
1380 {
1381  struct variable *nv, *n0 = NULL;
1382 
1383  while (v) {
1384  if (n0 == NULL)
1385  n0 = nv = alloc(struct variable);
1386  else {
1387  nv->va_next = alloc(struct variable);
1388  nv = nv->va_next;
1389  }
1390  nv->va_name = copy(v->va_name);
1391  nv->va_type = v->va_type;
1392  if (v->va_type == VT_BOOL)
1393  nv->va_bool = v->va_bool;
1394  else if (v->va_type == VT_REAL)
1395  nv->va_real = v->va_real;
1396  else if (v->va_type == VT_NUM)
1397  nv->va_num = v->va_num;
1398  else if (v->va_type == VT_STRING)
1399  nv->va_string = copy(v->va_string);
1400  else if (v->va_type == VT_LIST)
1401  nv->va_vlist = va_copy(v->va_vlist);
1402  v = v->va_next;
1403  }
1404  return (n0);
1405 }
1406 
1407 
1408 /* Implelentation of a stack for argc, argv[] variables.
1409  * These variables are set and cleared through these routines
1410  * only, not through com_set(), com_unset(), cp_remvar().
1411  */
1412 
1413 struct avstack {
1414  int ac;
1415  struct variable *av;
1416 };
1417 
1418 #define DEPTH 100
1419 
1420 static struct avstack av_stack[DEPTH];
1421 static int stackp;
1422 
1423 void
1425 
1426 wordlist *wl;
1427 {
1428  struct variable *listv = NULL, *lv;
1429  struct variable *v, **pv = NULL;
1430  int *pc = NULL;
1431  int n;
1432  char *st, *ss;
1433  double *td;
1434 
1435  if (stackp == 0) {
1436 
1437  v = alloc(struct variable);
1438  v->va_name = copy("argc");
1439  v->va_type = VT_NUM;
1440  pc = &v->va_num;
1441  htab_add("argc",(void*)v,variables);
1442 
1443  v = alloc(struct variable);
1444  v->va_name = copy("argv");
1445  v->va_type = VT_LIST;
1446  pv = &v->va_vlist;
1447  htab_add("argv",(void*)v,variables);
1448  }
1449  else {
1450  v = (struct variable *)htab_get("argv",variables);
1451  if (v)
1452  pv = &v->va_vlist;
1453  v = (struct variable *)htab_get("argc",variables);
1454  if (v)
1455  pc = &v->va_num;
1456  }
1457  if (pv && pc) {
1458  if (stackp) {
1459  av_stack[stackp].av = *pv;
1460  av_stack[stackp].ac = *pc;
1461  }
1462  stackp++;
1463  if (stackp == DEPTH) {
1464  fprintf(cp_err, "Warning: stack overflow\n");
1465  stackp--;
1466  return;
1467  }
1468 
1469  n = 0;
1470  while (wl && wl->wl_word) {
1471  v = alloc(struct variable);
1472  st = ss = copy(wl->wl_word);
1473  cp_unquote(ss);
1474  td = ft_numparse(&ss, false);
1475  if (td && *ss == '\0') {
1476  v->va_type = VT_REAL;
1477  v->va_real = *td;
1478  txfree(st);
1479  }
1480  else {
1481  v->va_type = VT_STRING;
1482  v->va_string = st;
1483  }
1484  if (listv) {
1485  lv->va_next = v;
1486  lv = v;
1487  }
1488  else
1489  listv = lv = v;
1490  n++;
1491  wl = wl->wl_next;
1492  }
1493  *pv = listv;
1494  *pc = n;
1495  }
1496 }
1497 
1498 
1499 void
1501 
1502 {
1503  struct variable *vv, *vc, **pv = NULL;
1504  int *pc = NULL;
1505 
1506  if (stackp == 0)
1507  return;
1508 
1509  vv = (struct variable *)htab_get("argv",variables);
1510  if (vv)
1511  pv = &vv->va_vlist;
1512  vc = (struct variable *)htab_get("argc",variables);
1513  if (vc)
1514  pc = &vc->va_num;
1515 
1516  if (pc && pv) {
1517  stackp--;
1518  if (stackp == 0) {
1519 
1520  htab_delete("argv",variables);
1521  htab_delete("argc",variables);
1522  va_free(vv);
1523  va_free(vc);
1524  }
1525  else {
1526  va_free(*pv);
1527  *pv = av_stack[stackp].av;
1528  *pc = av_stack[stackp].ac;
1529  }
1530  }
1531 }
void com_unset(wordlist *wl)
Definition: variable.c:1197
#define US_OK
Definition: cpdefs.h:49
static char buf[MAXPROMPT]
Definition: arg.c:18
#define US_READONLY
Definition: cpdefs.h:50
#define BSIZE_SP
Definition: misc.h:19
void wl_print()
#define eq(a, b)
Definition: misc.h:29
Definition: variable.c:632
int wl_length()
static wordlist * vareval()
void va_free(struct variable *v)
Definition: variable.c:1357
void out_printf()
char * strcpy()
Definition: cddefs.h:119
void htab_delete()
void cp_remvar(char *varname)
Definition: variable.c:942
void com_set(wordlist *wl)
Definition: variable.c:1007
#define VT_LIST
Definition: cpstd.h:64
double * ft_numparse()
int scannum()
Definition: cddefs.h:169
static wordlist * var2wl()
Definition: library.c:18
int cp_internalset()
#define alloc(type)
Definition: cdmacs.h:21
#define DEPTH
Definition: variable.c:1418
void cp_unquote()
char * copy()
char * getenv(char *c)
Definition: libfuncs.c:106
void * htab_wl()
static char * iv_special()
char va_type
Definition: cpstd.h:42
static int stackp
Definition: variable.c:1421
void wl_free()
FILE * cp_err
Definition: help.c:101
char * tmalloc()
static char * eval_range()
bool cp_getvar(char *name, int type, char *retval)
Definition: variable.c:1276
void * htab_init()
Definition: hash.c:27
struct wordlist * wl_prev
Definition: cpstd.h:24
char * va_name
Definition: cpstd.h:43
Definition: cddefs.h:237
void com_shift(wordlist *wl)
Definition: variable.c:1226
#define tfree(x)
Definition: cdmacs.h:22
struct variable * va_copy(struct variable *v)
Definition: variable.c:1377
void txfree()
#define NULL
Definition: spdefs.h:121
Definition: types.c:18
void cp_vprint()
Definition: variable.c:638
bool cp_nonomatch
Definition: variable.c:47
char cp_dol
Definition: variable.c:51
bool cp_noglob
Definition: variable.c:46
wordlist * wl_splice()
FILE * cp_out
Definition: help.c:101
#define VT_NUM
Definition: cpstd.h:61
wordlist * cp_varwl(struct variable *var)
Definition: variable.c:718
#define VT_STRING
Definition: cpstd.h:63
struct variable * cp_enqvar()
char x_char
Definition: variable.c:634
wordlist * cp_lexer()
static int vcmp()
bool cp_ignoreeof
Definition: variable.c:49
#define VT_BOOL
Definition: cpstd.h:60
int ac
Definition: variable.c:1414
Definition: cpstd.h:21
void cp_usrvars()
qsort()
Definition: string.c:375
struct variable * av
Definition: variable.c:1415
return(True)
static void * variables
Definition: variable.c:53
#define VALIDCHARS
Definition: variable.c:59
int getpid()
Definition: libfuncs.c:137
Definition: netlist.c:477
Definition: dir.c:53
void htab_add()
static struct variable * getlist()
static struct avstack av_stack[DEPTH]
Definition: variable.c:1420
void * htab_get()
void out_send()
struct wordlist * wl_next
Definition: cpstd.h:23
char * fixxp2()
#define VT_REAL
Definition: cpstd.h:62
char * wl_word
Definition: cpstd.h:22
void cp_pusharg(wordlist *wl)
Definition: variable.c:1424
#define isalphanum(c)
Definition: misc.h:30
void cp_variablesubst(wordlist **list)
Definition: variable.c:62
struct mfbpc pc
Definition: mfbopen.c:14
FILE * cp_in
Definition: help.c:101
void clearerr(FILE *fp)
Definition: libfuncs.c:116
char * wl_flatten()
bool cp_noclobber
Definition: variable.c:48
#define US_DONTRECORD
Definition: cpdefs.h:51
Definition: cddefs.h:192
struct variable * va_next
Definition: cpstd.h:51
void cp_wstrip()
struct variable * x_v
Definition: variable.c:633
Definition: cpstd.h:41
void * htab_list()
void cp_poparg()
Definition: variable.c:1500
struct variable * cp_setparse(wordlist *wl)
Definition: variable.c:1048
void cp_vset(char *varname, char type, char *value)
Definition: variable.c:784