ARB
aisc_mix.c
Go to the documentation of this file.
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 
13 static 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 
151 int 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 
205 hash::hash(int size_) {
206  size = size_;
207  entries = (hash_entry **)calloc(sizeof(hash_entry *), size);
208 }
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 
222 int 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 
235 const 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 
242 void 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 
258 var_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 
266 const 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 
char * val
hash(int size_)
Definition: aisc_mix.c:205
static Code * aisc_calc_blocks(Code *co, Code *afor, Code *aif, int up)
Definition: aisc_mix.c:13
void write(const char *key, const char *val)
Definition: aisc_mix.c:242
Code * ELSE
Definition: aisc_parser.h:47
Code * IF
Definition: aisc_parser.h:46
char * str
Definition: aisc_parser.h:37
var_ref get_local(const char *key)
Definition: aisc_mix.c:258
hash_entry * next
#define print_error(code_or_loc, err)
Definition: aisc_def.h:47
Code * FOR
Definition: aisc_parser.h:49
char * key
Code * ENDFOR
Definition: aisc_parser.h:51
Code * next
Definition: aisc_parser.h:36
~hash()
Definition: aisc_mix.c:209
CONSTEXPR_INLINE bool is_SPACE_SEP_LF_EOS(char c)
Definition: aisc_inline.h:28
Code * NEXT
Definition: aisc_parser.h:50
const char * read() const
#define NULp
Definition: cxxforward.h:116
const char * read_local(const char *key) const
Definition: aisc_mix.c:266
CommandType command
Definition: aisc_parser.h:41
Code * ENDIF
Definition: aisc_parser.h:48
void SKIP_SPACE_LF(const char *&var)
Definition: aisc_inline.h:32
GB_write_int const char s
Definition: AW_awar.cxx:154