1 #include <string.h>
2
3 #include "nmtbl.h"
4 #include "token.h"
5 #include "trnod.h"
6 #include "util.h"
7
8 tpexpr void_type(tp_void, NULL, "void");
9 tpexpr any_type(tp_any, NULL, "void*");
10 tpexpr integer_type(tp_integer, NULL, "integer");
11 tpexpr longint_type(tp_longint, NULL, "longint");
12 tpexpr real_type(tp_real, NULL, "real");
13 tpexpr double_type(tp_real, NULL, "double");
14 tpexpr char_type(tp_char, NULL, "char");
15 tpexpr bool_type(tp_bool, NULL, "boolean");
16 ref_tp pointer_type(&void_type);
17 string_tp string_type;
18 varying_string_tp varying_string_type;
19 text_tp text_type;
20
21
22 //---------------------------------------------------------------------
23
insert_before(token * t)24 token *tpexpr::insert_before(token *t)
25 {
26 return (name != NULL)
27 ? t->prepend(name)
28 : t->copy(tpd->f_tkn, tpd->l_tkn);
29 }
30
31
get_typedef()32 tpexpr* tpexpr::get_typedef() { return this; }
33
is_reference()34 bool tpexpr::is_reference() { return FALSE; }
35
is_array()36 bool tpexpr::is_array() { return FALSE; }
37
38 //---------------------------------------------------------------------
39
get_typedef()40 tpexpr* simple_tp::get_typedef() { return alias->get_typedef(); }
41
is_reference()42 bool simple_tp::is_reference() { return alias->is_reference(); }
is_array()43 bool simple_tp::is_array() { return alias->is_array(); }
44
45 //---------------------------------------------------------------------
46
ref_tp(tpexpr * tp,tpd_node * tpd)47 ref_tp::ref_tp(tpexpr* tp, tpd_node* tpd)
48 : tpexpr(tp_ref, tpd), base_type(tp)
49 {
50 if (tp != NULL && tp->name != NULL) {
51 name = dprintf("%s*", tp->name);
52 }
53 }
54
is_reference()55 bool ref_tp::is_reference() { return TRUE; }
56
57 //---------------------------------------------------------------------
58
fwd_ref_tp(token * t)59 fwd_ref_tp::fwd_ref_tp(token* t)
60 {
61 tag = tp_fwd_ref;
62 ident = t;
63 name = dprintf("struct %s*", t->out_text);
64 }
65
66
get_typedef()67 tpexpr* fwd_ref_tp::get_typedef()
68 {
69 if (tag == tp_fwd_ref) {
70 symbol *sym = b_ring::search_cur(ident);
71 if (sym != NULL) {
72 base_type = sym->type;
73 tag = tp_ref;
74 }
75 }
76 return this;
77 }
78
79 //---------------------------------------------------------------------
80
set_bounds(symbol * var)81 void enum_tp::set_bounds(symbol* var)
82 {
83 max = dprintf("last_%s", var->out_name->text);
84 }
85
86
set_enumeration_name(tpexpr * type)87 void enum_tp::set_enumeration_name(tpexpr* type)
88 {
89 symbol* sym = last;
90 do {
91 sym->type = type;
92 if (sym == first) break;
93 sym = sym->next;
94 } while (TRUE);
95 }
96
97
98 //---------------------------------------------------------------------
99
set_bounds(symbol * var)100 void range_tp::set_bounds(symbol* var)
101 {
102 max = dprintf("max_%s", var->out_name->text);
103 min = dprintf("min_%s", var->out_name->text);
104 }
105
106 //---------------------------------------------------------------------
107
array_tp(tpexpr * tp,tpd_node * tpd)108 array_tp::array_tp(tpexpr* tp, tpd_node* tpd)
109 : tpexpr(tp_array, tpd), elem_type(tp)
110 {
111 flags |= tp->get_typedef()->flags & tp_need_init;
112 low = high = NULL;
113 low_expr = high_expr = NULL;
114 base = -1;
115 }
116
is_array()117 bool array_tp::is_array() { return TRUE; }
118
insert_bounds_definition(symbol * array,token * block,int n)119 void array_tp::insert_bounds_definition(symbol* array, token* block, int n)
120 {
121 if (elem_type->tag == tp_dynarray || n > 0) n += 1;
122
123 block->prepend(dprintf("const int %s = %s.%s%.0d;\n",
124 low, array->out_name->text, "low", n));
125 block->prepend(dprintf("const int %s = %s.%s%.0d;\n",
126 high, array->out_name->text, "high", n));
127
128 if (elem_type->tag == tp_dynarray) {
129 ((array_tp*)elem_type->get_typedef())->
130 insert_bounds_definition(array, block, n);
131 }
132 }
133
set_dim(char * low,char * high,expr_node * low_expr,expr_node * high_expr)134 void array_tp::set_dim(char *low, char *high,
135 expr_node *low_expr, expr_node *high_expr)
136 {
137 this->low = low;
138 this->high = high;
139 this->low_expr = low_expr;
140 this->high_expr = high_expr;
141
142 if (low != NULL && strcmp(low, "0") == 0) {
143 base = 0;
144 } else if (low_expr != NULL && low_expr->is_const_literal()) {
145 base = low_expr->value;
146 }
147 }
148
set_conformant_dim(symbol * low_sym,symbol * high_sym)149 void array_tp::set_conformant_dim(symbol* low_sym, symbol* high_sym)
150 {
151 low_var = low_sym;
152 high_var = high_sym;
153 low = low_sym->out_name->text;
154 high = high_sym->out_name->text;
155 low_expr = high_expr = NULL;
156 tag = tp_dynarray;
157 }
158
insert_dimensions(expr_node * e,array_tp * conf_arr,int n)159 void array_tp::insert_dimensions(expr_node* e, array_tp* conf_arr, int n)
160 {
161 token *t = e->f_tkn;
162
163 if (low == NULL) {
164 assert(low_expr != NULL);
165 t->copy(low_expr->f_tkn, low_expr->l_tkn);
166 } else {
167 t->prepend(low);
168 }
169 t->prepend(", ");
170 if (!e->is_parameter() && (base == 0 || base == 1)) {
171 t->prepend(dprintf("items(%.*s", n, "****************"));
172 t->copy(e->f_tkn, e->l_tkn);
173 t->prepend(base == 0 ? (char *) ")-1" : (char *) ")");
174 } else {
175 if (high == NULL) {
176 assert(high_expr != NULL);
177 t->copy(high_expr->f_tkn, high_expr->l_tkn);
178 } else {
179 t->prepend(high);
180 }
181 }
182 t->prepend(", ");
183
184 if (conf_arr && conf_arr->elem_type->tag == tp_dynarray) {
185 if (elem_type->tag != tp_array) {
186 warning(e->f_tkn, "array is incompatible with conformant scheme");
187 } else {
188 ((array_tp*)elem_type->get_typedef())->
189 insert_dimensions(e, (array_tp*)conf_arr->elem_type, n + 1);
190 }
191 if (tag != tp_dynarray) {
192 e->f_tkn->prepend("*");
193 }
194 }
195 }
196
197
insert_length(token * before)198 void array_tp::insert_length(token* before)
199 {
200 if (base == 0 || no_index_decrement) {
201 if (high != NULL) {
202 before->prepend(dprintf("(%s+1)", high));
203 } else {
204 assert(high_expr != NULL);
205 if (high_expr->is_const_literal()) {
206 before->prepend(dprintf("%d", high_expr->value + 1));
207 } else {
208 before->prepend("(");
209 before->copy(high_expr->f_tkn, high_expr->l_tkn);
210 before->prepend("+1)");
211 }
212 }
213 } else if (base == 1) {
214 if (high != NULL) {
215 before->prepend(high);
216 } else {
217 assert(high_expr != NULL);
218 before->copy(high_expr->f_tkn, high_expr->l_tkn);
219 }
220 } else {
221 if (high != NULL && low != NULL) {
222 before->prepend(dprintf("(%s-%s+1)", high, low));
223 } else {
224 assert(high_expr != NULL && low_expr != NULL);
225 before->prepend("((");
226 before->copy(high_expr->f_tkn, high_expr->l_tkn);
227 before->prepend(")-(");
228 before->copy(low_expr->f_tkn, low_expr->l_tkn);
229 before->prepend(")+1)");
230 }
231 }
232 if (elem_type->tag == tp_dynarray) {
233 ((array_tp*)elem_type)->insert_bound_params(before);
234 }
235 }
236
insert_bound_params(token * before)237 void array_tp::insert_bound_params(token* before)
238 {
239 assert(low != NULL && high != NULL);
240 before->prepend(dprintf("const integer %s, const integer %s, ",
241 low, high));
242 if (elem_type->tag == tp_dynarray) {
243 ((array_tp*)elem_type)->insert_bound_params(before);
244 }
245 }
246
add_proc_param(proc_tp * proc)247 void array_tp::add_proc_param(proc_tp* proc)
248 {
249 proc->add_extra_param(low_var);
250 proc->add_extra_param(high_var);
251 if (elem_type->tag == tp_dynarray) {
252 ((array_tp*)elem_type)->add_proc_param(proc);
253 }
254 }
255
256 //---------------------------------------------------------------------
257
text_tp()258 text_tp::text_tp() : file_tp(&char_type) {
259 tag = tp_text;
260 name = "text";
261 }
262
263 //---------------------------------------------------------------------
264
calc_flags()265 void record_tp::calc_flags()
266 {
267 for (symbol *sym = syms; sym != NULL; sym = sym->next) {
268 flags |= sym->type->get_typedef()->flags;
269 }
270 }
271
272 //---------------------------------------------------------------------
273
274
object_tp(tpd_node * tpd,object_tp * super)275 object_tp::object_tp(tpd_node *tpd, object_tp* super) : record_tp(tpd)
276 {
277 tag = tp_object;
278 class_name = NULL;
279 inherite = super;
280 }
281
282
283
284 //---------------------------------------------------------------------
285
string_tp()286 string_tp::string_tp() : array_tp(&char_type)
287 {
288 tag = tp_string;
289 base = 1;
290 low = "1";
291 name = "char*";
292 }
293
insert_dimensions(expr_node * e,array_tp * conf_arr,int n)294 void string_tp::insert_dimensions(expr_node* e, array_tp* conf_arr, int n)
295 {
296 e->f_tkn->prepend("array(");
297 e->l_tkn->append(")");
298 }
299
300 //---------------------------------------------------------------------
301
varying_string_tp()302 varying_string_tp::varying_string_tp() : array_tp(&char_type)
303 {
304 tag = tp_varying_string;
305 base = 1;
306 low = "1";
307 name = "string";
308 }
309
310 //---------------------------------------------------------------------
311
proc_tp(tpexpr * rtype,tpd_node * tpd)312 proc_tp::proc_tp(tpexpr* rtype, tpd_node* tpd)
313 : tpexpr(tp_proc, tpd), b_ring(b_ring::proc)
314 {
315 params = last = NULL;
316 extra_params = NULL;
317 callers = NULL;
318 res_type = rtype;
319 forward = NULL;
320 proc_name = NULL;
321 define_list = NULL;
322 last_temp = temp_list = NULL;
323 n_temp = 0;
324 n_subproc = 0;
325 make_all_constants_global = FALSE;
326 is_extern_c = FALSE;
327 is_constructor = FALSE;
328 is_destructor = FALSE;
329 }
330
add_param(symbol * var)331 void proc_tp::add_param(symbol *var)
332 {
333 if (last == NULL) {
334 params = last = new param_spec(var);
335 } else {
336 last = last->next = new param_spec(var);
337 }
338 }
339
add_extra_param(symbol * var)340 void proc_tp::add_extra_param(symbol *var)
341 {
342 param_spec **pp, *p;
343
344 if (var->ring == this) return;
345
346 if (var->ring->scope == b_ring::proc && var->type
347 && !var->type->is_scalar() && var->type->get_typedef() == var->type)
348 {
349 ((proc_tp*)var->ring)->make_all_constants_global = TRUE;
350 }
351
352 if (language_c && var->type->tag == tp_dynarray) {
353 ((array_tp*)var->type)->add_proc_param(this);
354 }
355 for (pp = &extra_params; (p = *pp) != NULL; pp = &p->next) {
356 if (p->var == var) return;
357 }
358 *pp = new param_spec(var);
359 var->flags |= symbol::f_exported;
360
361 for (caller_spec *f = callers; f != NULL; f = f->next) {
362 f->caller->add_extra_param(var);
363 }
364 }
365
add_caller(proc_tp * f)366 void proc_tp::add_caller(proc_tp* f)
367 {
368 caller_spec *cp, **cpp;
369
370 if (f == this || f == NULL || proc_name == NULL) return;
371
372 for (cpp = &callers; (cp = *cpp) != NULL; cpp = &cp->next) {
373 if (cp->caller == f) return;
374 }
375 *cpp = new caller_spec(f);
376 if (use_call_graph && call_graph_file != NULL && f->proc_name != NULL) {
377 fprintf(call_graph_file, "%s -> %s\n", f->proc_name, proc_name);
378 }
379 for (param_spec *p = extra_params; p != NULL; p = p->next) {
380 f->add_extra_param(p->var);
381 }
382 }
383
384
declare_conformant_array_bounds(token * section)385 void proc_tp::declare_conformant_array_bounds(token* section)
386 {
387 param_spec* prm;
388 tpexpr* prev_type = NULL;
389
390 for (prm = params; prm != NULL; prm = prm->next) {
391 if (prm->var->type->tag == tp_dynarray) {
392 if (prm->var->type != prev_type) {
393 ((array_tp*)prm->var->type)->insert_bounds_definition
394 (prm->var, section);
395 prev_type = prm->var->type;
396 }
397 if ((prm->var->flags & symbol::f_val_param)
398 && (copy_array || (prm->var->flags & symbol::f_lvalue)))
399 {
400 section->prepend(dprintf("copy_conformant_array(%s);\n",
401 prm->var->out_name->text));
402 }
403 }
404 }
405 for (prm = extra_params; prm != NULL; prm = prm->next) {
406 if (prm->var->type->tag == tp_dynarray) {
407 if (prm->var->type != prev_type) {
408 ((array_tp*)prm->var->type)->insert_bounds_definition
409 (prm->var, section);
410 prev_type = prm->var->type;
411 }
412 if ((prm->var->flags & symbol::f_val_param)
413 && (copy_array || (prm->var->flags & symbol::f_lvalue)))
414 {
415 section->prepend(dprintf("copy_conformant_array(%s);\n",
416 prm->var->out_name->text));
417 }
418 }
419 }
420 }
421
add_define(symbol * s)422 void proc_tp::add_define(symbol* s)
423 {
424 define_list = new define_spec(s, define_list);
425 }
426
undefine(token * t)427 void proc_tp::undefine(token* t)
428 {
429 if (define_list != NULL) {
430 t = t->append("\n\n");
431 }
432 for (define_spec* def = define_list; def != NULL; def = def->next) {
433 t = t->append(dprintf("#undef %s\n", def->sym->out_name->text));
434 }
435 }
436
add_temp(tpexpr * type)437 char* proc_tp::add_temp(tpexpr* type)
438 {
439 if (last_temp == NULL) {
440 temp_list = last_temp = new temp_spec(type);
441 } else {
442 last_temp = last_temp->next = new temp_spec(type);
443 }
444 return dprintf("temp%d", ++n_temp);
445 }
446
insert_temporaries(token * t)447 void proc_tp::insert_temporaries(token* t)
448 {
449 int n = 0;
450 for (temp_spec* ts = temp_list; ts != NULL; ts = ts->next) {
451 assert(ts->type->name != NULL);
452 t->prepend(dprintf("%s temp%d;\n", ts->type->name, ++n));
453 }
454 }
455