aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/var.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/var.c')
-rw-r--r--sys/cmd/rc/var.c230
1 files changed, 138 insertions, 92 deletions
diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c
index d442369..d48dc66 100644
--- a/sys/cmd/rc/var.c
+++ b/sys/cmd/rc/var.c
@@ -1,129 +1,175 @@
#include "rc.h"
+#include "exec.h"
+#include "fns.h"
-Var *globals[1021] = { 0 };
+var *gvar[NVAR] = { 0 }; /* hash for globals */
-struct Keyword {
- ushort type;
- char *name;
- struct Keyword *link;
-} *keywords[41];
-
-// -----------------------------------------------------------------------
-// utility
-
-static
int
hash(char *s, int n)
{
- int i = 1, h = 0;
- while (*s)
- h += *s++*i++;
- h %= n;
- return (h<0)?h+n:h;
+ int h = 0, i = 1;
+ while(*s) h+=*s++*i++;
+ h%=n;
+ return h<0?h+n:h;
}
+#define NKW 30
+struct kw{
+ char *name;
+ int type;
+ struct kw *next;
+}*kw[NKW];
-// -----------------------------------------------------------------------
-// keywords
-
-static
void
-putkw(int type, char *name)
+kenter(int type, char *name)
{
- struct Keyword *kw;
- int h = hash(name, arrlen(keywords));
-
- alloc(kw);
- kw->type = type;
- kw->name = name;
- kw->link = keywords[h];
-
- keywords[h] = kw;
+ int h = hash(name, NKW);
+ struct kw *p = new(struct kw);
+ p->type = type;
+ p->name = name;
+ p->next = kw[h];
+ kw[h] = p;
}
void
-initkw(void)
+kinit(void)
{
- putkw(Tfor, "for");
- putkw(Tin, "in");
- putkw(Twhile, "while");
- putkw(Tif, "if");
- putkw(Telse, "else");
- putkw(Tswitch, "switch");
- putkw(Tcase, "case");
- putkw(Tfunc, "func");
+ kenter(FOR, "for");
+ kenter(IN, "in");
+ kenter(WHILE, "while");
+ kenter(IF, "if");
+ kenter(NOT, "not");
+ kenter(TWIDDLE, "~");
+ kenter(BANG, "!");
+ kenter(SUBSHELL, "@");
+ kenter(SWITCH, "switch");
+ kenter(FN, "fn");
}
-int
-kwlookup(char *name)
+tree*
+klook(char *name)
{
- int t;
- struct Keyword *it;
- for(t=-1,it = keywords[hash(name, arrlen(keywords))];it;it = it->link)
- if(!strcmp(it->name, name))
- t = it->type;
- return t;
+ struct kw *p;
+ tree *t = token(name, WORD);
+ for(p = kw[hash(name, NKW)];p;p = p->next)
+ if(strcmp(p->name, name)==0){
+ t->type = p->type;
+ t->iskw = 1;
+ break;
+ }
+ return t;
}
-// -----------------------------------------------------------------------
-// variables
-
-Var *
-newvar(char *name, Var *link)
+var*
+gvlook(char *name)
{
- Var *v;
-
- alloc(v);
- v->name = name;
- v->val = 0;
- v->func = nil;
- v->funcnew = 0;
- v->new = 0;
- v->update = nil;
- v->link = link;
-
- return v;
+ int h = hash(name, NVAR);
+ var *v;
+ for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
+ return gvar[h] = newvar(strdup(name), gvar[h]);
}
-/* only global lookup */
+var*
+vlook(char *name)
+{
+ var *v;
+ if(runq)
+ for(v = runq->local;v;v = v->next)
+ if(strcmp(v->name, name)==0) return v;
+ return gvlook(name);
+}
-Var *
-gvlookup(char *name)
+void
+_setvar(char *name, word *val, int callfn)
{
- Var *v;
- int h = hash(name, arrlen(globals));
- for (v = globals[h]; v; v = v->link)
- if (!strcmp(v->name, name))
- return v;
+ struct var *v = vlook(name);
+ freewords(v->val);
+ v->val=val;
+ v->changed=1;
+ if(callfn && v->changefn)
+ v->changefn(v);
+}
- return globals[h] = newvar(strdup(name), globals[h]);
+void
+setvar(char *name, word *val)
+{
+ _setvar(name, val, 1);
}
-/* local + global lookup */
-Var *
-vlookup(char *name)
+void
+bigpath(var *v)
{
- Var *v;
- if (shell)
- for (v = shell->local; v; v = v->link)
- if (!strcmp(v->name, name))
- return v;
- return gvlookup(name);
+ /* convert $PATH to $path */
+ char *p, *q;
+ word **l, *w;
+
+ if(v->val == nil){
+ _setvar("path", nil, 0);
+ return;
+ }
+ p = v->val->word;
+ w = nil;
+ l = &w;
+ /*
+ * Doesn't handle escaped colon nonsense.
+ */
+ if(p[0] == 0)
+ p = nil;
+ while(p){
+ q = strchr(p, ':');
+ if(q)
+ *q = 0;
+ *l = newword(p[0] ? p : ".", nil);
+ l = &(*l)->next;
+ if(q){
+ *q = ':';
+ p = q+1;
+ }else
+ p = nil;
+ }
+ _setvar("path", w, 0);
}
-static
+char*
+list2strcolon(word *words)
+{
+ char *value, *s, *t;
+ int len = 0;
+ word *ap;
+ for(ap = words;ap;ap = ap->next)
+ len+=1+strlen(ap->word);
+ value = emalloc(len+1);
+ s = value;
+ for(ap = words;ap;ap = ap->next){
+ for(t = ap->word;*t;) *s++=*t++;
+ *s++=':';
+ }
+ if(s==value)
+ *s='\0';
+ else s[-1]='\0';
+ return value;
+}
void
-set(char *name, Word *val, int call)
+littlepath(var *v)
{
- Var *v = vlookup(name);
- freelist(v->val);
- v->val = val;
- v->new = 1;
- if (call && v->update)
- v->update(v);
+ /* convert $path to $PATH */
+ char *p;
+ word *w;
+
+ p = list2strcolon(v->val);
+ w = new(word);
+ w->word = p;
+ w->next = nil;
+ _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */
}
void
-setvar(char *name, Word *val)
+pathinit(void)
{
- set(name, val, 1);
+ var *v;
+
+ v = gvlook("path");
+ v->changefn = littlepath;
+ v = gvlook("PATH");
+ v->changefn = bigpath;
+ bigpath(v);
}