Blob


1 #include "rc.h"
2 #include "exec.h"
3 #include "fns.h"
4 int hash(char *s, int n)
5 {
6 register int h=0, i=1;
7 while(*s) h+=*s++*i++;
8 h%=n;
9 return h<0?h+n:h;
10 }
11 #define NKW 30
12 struct kw{
13 char *name;
14 int type;
15 struct kw *next;
16 }*kw[NKW];
17 void kenter(int type, char *name)
18 {
19 register int h=hash(name, NKW);
20 register struct kw *p=new(struct kw);
21 p->type=type;
22 p->name=name;
23 p->next=kw[h];
24 kw[h]=p;
25 }
26 void kinit(void){
27 kenter(FOR, "for");
28 kenter(IN, "in");
29 kenter(WHILE, "while");
30 kenter(IF, "if");
31 kenter(NOT, "not");
32 kenter(TWIDDLE, "~");
33 kenter(BANG, "!");
34 kenter(SUBSHELL, "@");
35 kenter(SWITCH, "switch");
36 kenter(FN, "fn");
37 }
38 tree *klook(char *name)
39 {
40 struct kw *p;
41 tree *t=token(name, WORD);
42 for(p=kw[hash(name, NKW)];p;p=p->next)
43 if(strcmp(p->name, name)==0){
44 t->type=p->type;
45 t->iskw=1;
46 break;
47 }
48 return t;
49 }
50 var *gvlook(char *name)
51 {
52 int h=hash(name, NVAR);
53 var *v;
54 for(v=gvar[h];v;v=v->next) if(strcmp(v->name, name)==0) return v;
55 return gvar[h]=newvar(strdup(name), gvar[h]);
56 }
57 var *vlook(char *name)
58 {
59 var *v;
60 if(runq)
61 for(v=runq->local;v;v=v->next)
62 if(strcmp(v->name, name)==0) return v;
63 return gvlook(name);
64 }
65 void _setvar(char *name, word *val, int callfn)
66 {
67 register struct var *v=vlook(name);
68 freewords(v->val);
69 v->val=val;
70 v->changed=1;
71 if(callfn && v->changefn)
72 v->changefn(v);
73 }
74 void setvar(char *name, word *val)
75 {
76 _setvar(name, val, 1);
77 }
78 void bigpath(var *v)
79 {
80 /* convert $PATH to $path */
81 char *p, *q;
82 word **l, *w;
84 if(v->val == nil){
85 _setvar("path", nil, 0);
86 return;
87 }
88 p = v->val->word;
89 w = nil;
90 l = &w;
91 /*
92 * Doesn't handle escaped colon nonsense.
93 */
94 if(p[0] == 0)
95 p = nil;
96 while(p){
97 q = strchr(p, ':');
98 if(q)
99 *q = 0;
100 *l = newword(p[0] ? p : ".", nil);
101 l = &(*l)->next;
102 if(q){
103 *q = ':';
104 p = q+1;
105 }else
106 p = nil;
108 _setvar("path", w, 0);
110 void littlepath(var *v)
112 /* convert $path to $PATH */
113 char *p;
114 word *w;
116 p = _list2str(v->val, ':');
117 w = new(word);
118 w->word = p;
119 w->next = nil;
120 _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */
122 void pathinit(void)
124 var *v;
126 v = gvlook("path");
127 v->changefn = littlepath;
128 v = gvlook("PATH");
129 v->changefn = bigpath;
130 bigpath(v);