aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/var.c
blob: d442369ea2c7efa1231b0e0e1cf2fea7fec55b70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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);
}