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.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c
new file mode 100644
index 0000000..d442369
--- /dev/null
+++ b/sys/cmd/rc/var.c
@@ -0,0 +1,129 @@
+#include "rc.h"
+
+Var *globals[1021] = { 0 };
+
+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;
+}
+
+// -----------------------------------------------------------------------
+// keywords
+
+static
+void
+putkw(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;
+}
+
+void
+initkw(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");
+}
+
+int
+kwlookup(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;
+}
+
+// -----------------------------------------------------------------------
+// variables
+
+Var *
+newvar(char *name, Var *link)
+{
+ 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;
+}
+
+/* only global lookup */
+
+Var *
+gvlookup(char *name)
+{
+ Var *v;
+ int h = hash(name, arrlen(globals));
+ for (v = globals[h]; v; v = v->link)
+ if (!strcmp(v->name, name))
+ return v;
+
+ return globals[h] = newvar(strdup(name), globals[h]);
+}
+
+/* local + global lookup */
+Var *
+vlookup(char *name)
+{
+ Var *v;
+ if (shell)
+ for (v = shell->local; v; v = v->link)
+ if (!strcmp(v->name, name))
+ return v;
+ return gvlookup(name);
+}
+
+static
+void
+set(char *name, Word *val, int call)
+{
+ Var *v = vlookup(name);
+ freelist(v->val);
+ v->val = val;
+ v->new = 1;
+ if (call && v->update)
+ v->update(v);
+}
+
+void
+setvar(char *name, Word *val)
+{
+ set(name, val, 1);
+}