source: branches/stable/AISC/aisc_mix.c

Last change on this file was 16763, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1// ================================================================
2/*                                                                  */
3//   File      : aisc_mix.c
4//   Purpose   :
5/*                                                                  */
6//   Institute of Microbiology (Technical University Munich)
7//   http://www.arb-home.de/
8/*                                                                  */
9// ================================================================
10
11#include "aisc_interpreter.h"
12
13static Code *aisc_calc_blocks(Code * co, Code * afor, Code * aif, int up) {
14    Code *oif;
15    Code *ofor;
16    Code *aelse;
17    Code *anext;
18
19    while (co) {
20        while (co && (!co->command)) {
21            co->IF = aif;
22            co->FOR = afor;
23            co = co->next;
24        }
25        if (!co) return NULp;
26        co->IF = aif;
27        co->FOR = afor;
28        switch (co->command) {
29            case CT_NEXT:
30                if (!co->FOR) print_error(co, "NEXT without FOR");
31                return co;
32            case CT_ENDFOR:
33                if (!co->FOR) print_error(co, "ENDFOR without FOR");
34                return co;
35            case CT_ELSE:
36                if (!co->IF) print_error(co, "ELSE without IF");
37                return co;
38            case CT_ELSEIF:
39                if (!co->IF) print_error(co, "ELSEIF without IF");
40                return co;
41            case CT_ENDIF:
42                if (!co->IF) print_error(co, "ENDIF without IF");
43                return co;
44
45            case CT_IF:
46                oif = aif;
47                aif = co;
48                co  = aisc_calc_blocks(co->next, afor, aif, 0);
49                if (!co) {
50                    print_error(aif, "IF without ELSE or ENDIF");
51                    return NULp;
52                }
53                if (co->command == CT_ELSE) {
54                    aif->ELSE=co;
55                    aelse = co;
56                    co = aisc_calc_blocks(co->next, afor, aif, 0);
57                    if (!co) {
58                        print_error(aif, "ELSE without ENDIF");
59                        return NULp;
60                    }
61                    if  (co->command!=CT_ENDIF) {
62                        print_error(aif, "ELSE without ENDIF");
63                        print_error(co, "<detected here>");
64                        return NULp;
65                    }
66                    aif->ENDIF=co;
67                    aelse->ENDIF=co;
68                    if (up) return co;
69                }
70                else if (co->command == CT_ELSEIF) {
71                    Code *co_if    = new Code(*co);
72                    co_if->command = CT_IF;   // when jumped to (from prev failed IF, act like IF)
73                    co->command    = CT_ELSE; // when running into, act like else
74                    co ->next      = co_if;
75                    freenull(co->str);
76                    aif->ELSE = co;
77                    aelse     = co;
78                    co        = aisc_calc_blocks(co_if, afor, aif, 1);
79                    if (!co) {
80                        print_error(aif->ELSE, "ELSEIF without ENDIF or ELSE");
81                        return NULp;
82                    }
83                    if  (co->command!=CT_ENDIF) {
84                        print_error(aif->ELSE, "ELSEIF without ENDIF");
85                        print_error(co, "<detected here>");
86                        return NULp;
87                    }
88                    aif->ENDIF   = co;
89                    co_if->ENDIF = co;
90                    aelse->ENDIF = co;
91                    if (up) return co;
92                }
93                else if (co->command == CT_ENDIF) {
94                    aif->ELSE  = co;
95                    aif->ENDIF = co;
96                    if (up) return co;
97                }
98                else {
99                    print_error(aif, "IF without ELSE or ENDIF");
100                    print_error(co, "<detected here>");
101                    return NULp;
102                }
103                aif = oif;
104                break;
105            case CT_FOR:
106                ofor = afor;
107                afor = co;
108                co = aisc_calc_blocks(co->next, afor, aif, 0);
109                if (!co) {
110                    print_error(afor, "FOR without NEXT or ENDFOR");
111                    return NULp;
112                }
113                if (co->command == CT_NEXT) {
114                    afor->NEXT=co;
115                    anext = co;
116                    co = aisc_calc_blocks(co->next, afor, aif, 0);
117                    if (!co) {
118                        print_error(afor->NEXT, "NEXT without ENDFOR");
119                        return NULp;
120                    }
121                    if  (co->command!=CT_ENDFOR) {
122                        print_error(afor->NEXT, "NEXT without ENDFOR");
123                        print_error(co, "<detected here>");
124                        return NULp;
125                    }
126                    afor->ENDFOR  = co;
127                    anext->ENDFOR = co;
128
129                }
130                else if (co->command == CT_ENDFOR) {
131                    afor->ENDFOR = co;
132                    afor->NEXT   = co;
133                    co->command  = CT_NEXT;
134                }
135                else {
136                    print_error(afor, "FOR without NEXT or ENDFOR");
137                    print_error(co, "<detected here>");
138                    return NULp;
139                }
140                afor = ofor;
141                break;
142            default:
143                break;
144
145        }
146        co = co->next;
147    }
148    return NULp;
149}
150
151int Interpreter::compile_program() {
152    for (Code *co=prg; co; co=co->next) {
153        if (!strncmp(co->str, "IF", 2))     { co->set_command(CT_IF, co->str+2); continue; }
154        if (!strncmp(co->str, "ELSEIF", 6)) { co->set_command(CT_ELSEIF, co->str+6); continue; }
155        if (!strncmp(co->str, "ELSE", 4))   { co->set_command(CT_ELSE, co->str+4); continue; }
156        if (!strncmp(co->str, "ENDIF", 5))  { co->set_command(CT_ENDIF, co->str+5); continue; }
157        if (!strncmp(co->str, "FOR", 3))    { co->set_command(CT_FOR, co->str+3); continue; }
158        if (!strncmp(co->str, "ENDFOR", 6)) { co->set_command(CT_ENDFOR, co->str+6); continue; }
159        if (!strncmp(co->str, "NEXT", 4))   { co->set_command(CT_NEXT, co->str+4); continue; }
160       
161        if (!strncmp(co->str, "LABEL", 5)) {
162            co->set_command(CT_LABEL, co->str+5);
163            define_fun(co->str, co);
164            continue;
165        }
166        if (!strncmp(co->str, "FUNCTION", 8)) {
167            char *buf1, *buf2;
168            char *s, *s2;
169            buf1 = co->str+8;
170            co->command = CT_FUNCTION;
171            SKIP_SPACE_LF(buf1);
172            for (s=buf1; !is_SPACE_SEP_LF_EOS(*s); s++) ;
173            if (*s) {
174                *s = 0;
175                s++;
176                SKIP_SPACE_LF(s);
177                s2 = strdup(s);
178            }
179            else {
180                s2 = strdup("");
181            }
182            buf2    = strdup(buf1);
183            free(co->str);
184            co->str = s2;
185            define_fun(buf2, co);
186            free(buf2);
187            continue;
188        }
189
190        co->command = CT_OTHER_CMD;
191        co->cmd     = find_command(co);
192    }
193
194    Code *co = aisc_calc_blocks(prg, NULp, NULp, 0);
195    if (co) {
196        print_error(co, "program is not well formed");
197    }
198
199    return 0;
200}
201
202// -------------
203//      hash
204
205hash::hash(int size_) {
206    size = size_;
207    entries = (hash_entry **)calloc(sizeof(hash_entry *), size);
208}
209hash::~hash() {
210    for (int i = 0; i<size; ++i) {
211        hash_entry *enext;
212        for (hash_entry *e=entries[i]; e; e=enext) {
213            if (e->val) free(e->val);
214            free(e->key);
215            enext = e->next;
216            free(e);
217        }
218    }
219    free(entries);
220}
221
222int hash::Index(const char *key) const {
223    const char *p = key;
224    int         x = 1;
225    char        c;
226
227    while ((c=*(p++))) {
228        x = (((x & 0x7fff)<<1) | ((x & 0x8000)>>15)) ^ c;
229    }
230    x %= size;
231    if (x<0) x += size;
232    return x;
233}
234
235const hash_entry *hash::find_entry(const char *key, int idx) const {
236    for (hash_entry *e = entries[idx]; e; e=e->next) {
237        if (!strcmp(e->key, key)) return e;
238    }
239    return NULp;
240}
241
242void hash::write(const char *key, const char *val) {
243    int         idx = Index(key);
244    hash_entry *e   = find_entry(key, idx);
245    if (e) {
246        freeset(e->val, nulldup(val));
247    }
248    else {
249        e       = (hash_entry *)calloc(sizeof(hash_entry), 1);
250        e->next = entries[idx];
251        e->key  = strdup(key);
252        e->val  = val ? strdup(val) : NULp;
253       
254        entries[idx] = e;
255    }
256}
257
258var_ref Interpreter::get_local(const char *key) {
259    var_ref ref;
260    for (Stack *s = stack; s && !ref; s = s->next) {
261        ref = s->hs->ref(key);
262    }
263    return ref;
264}
265
266const char *Interpreter::read_local(const char *key) const {
267    const var_ref local = const_cast<Interpreter*>(this)->get_local(key);
268    return local.read();
269}
270
Note: See TracBrowser for help on using the repository browser.