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