1 #include <assert.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <limits.h>
7 
8 #include "nmtbl.h"
9 #include "token.h"
10 #include "trnod.h"
11 #include "util.h"
12 
13 static proc_tp* curr_proc = NULL;
14 static char*    struct_path = "";
15 static token*   global_func_decl_level;
16 
17 //-----------------------------------------------------------------------------
18 
force_semicolon()19 void node::force_semicolon()
20 {
21     if (l_tkn->tag == TKN_SEMICOLON) return;
22 
23     token* tkn = l_tkn->next_relevant();
24 
25     if (tkn->tag != TKN_SEMICOLON)  {
26 	l_tkn = l_tkn->append(";");
27 	l_tkn->tag = TKN_SEMICOLON;
28     } else {
29 	l_tkn = tkn;
30 	while ((tkn = tkn->prev)->cat == CAT_WSPC) {
31 	    if (tkn->tag != TKN_CMNT) tkn->disable();
32 	}
33     }
34 }
35 
swallow_semicolon()36 void node::swallow_semicolon()
37 {
38     token* tkn = l_tkn->next_relevant();
39 
40     if (tkn->tag == TKN_SEMICOLON)  {
41 	tkn->disable();
42     }
43 }
44 
45 
attrib(int)46 void node::attrib(int) {}
47 
translate(int)48 void node::translate(int) {}
49 
50 #define CONS1(a) this->a = a
51 #define CONS2(a,b) CONS1(a), this->b = b
52 #define CONS3(a,b,c) CONS2(a,b), this->c = c
53 #define CONS4(a,b,c,d) CONS3(a,b,c), this->d = d
54 #define CONS5(a,b,c,d,e) CONS4(a,b,c,d), this->e = e
55 #define CONS6(a,b,c,d,e,f) CONS5(a,b,c,d,e), this->f = f
56 #define CONS7(a,b,c,d,e,f,g) CONS6(a,b,c,d,e,f), this->g = g
57 #define CONS8(a,b,c,d,e,f,g,i) CONS7(a,b,c,d,e,f,g), this->i = i
58 #define CONS9(a,b,c,d,e,f,g,i,j) CONS8(a,b,c,d,e,f,g,i), this->j = j
59 #define CONS10(a,b,c,d,e,f,g,i,j,k) CONS9(a,b,c,d,e,f,g,i,j), this->k = k
60 #define CONS11(a,b,c,d,e,f,g,i,j,k,l) CONS10(a,b,c,d,e,f,g,i,j,k), this->l = l
61 
62 //=============================================================================
63 // Statements
64 //=============================================================================
65 
import_list_node(token * lpar,token_list * params,token * rpar)66 import_list_node::import_list_node(token* lpar, token_list* params, token* rpar)
67 {
68     CONS3(lpar, params, rpar);
69 }
70 
attrib(int)71 void import_list_node::attrib(int)
72 {
73 }
74 
translate(int)75 void import_list_node::translate(int)
76 {
77     token::remove(lpar, rpar);
78 }
79 
program_node(token * program,token * name,import_list_node * params,token * semi,block_node * block,token * end)80 program_node::program_node(token* program, token* name,
81 			   import_list_node* params,
82 			   token* semi, block_node* block, token* end)
83 {
84     CONS6(program, name, params, semi, block, end);
85 }
86 
attrib(int)87 void program_node::attrib(int)
88 {
89     curr_proc = main = new proc_tp;
90     main->res_type = &integer_type;
91     if (turbo_pascal) {
92 	b_ring::push(main);
93 	main->scope = b_ring::global;
94 	b_ring::top_b_ring = main;
95     }
96     block->attrib(ctx_program);
97 }
98 
translate(int)99 void program_node::translate(int)
100 {
101     if (program != NULL) {
102         token::disable(program, semi);
103     }
104     end->disable();
105     curr_proc = main;
106     global_func_decl_level = block->body->t_begin;
107     block->translate(ctx_program);
108     token* first_stmt = block->body->t_begin->next_relevant();
109 
110     if (1/*pio_init*/) {
111 	block->body->t_begin->prepend("int main(int argc, const char* argv[])\n");
112     } else {
113 	block->body->t_begin->prepend("int main()\n");
114     }
115     block->body->t_end->prepend("return EXIT_SUCCESS;\n")
116 	->set_bind(first_stmt);
117     main->insert_temporaries(first_stmt);
118     if (1/*pio_init*/) {
119 	first_stmt->prepend("pio_initialize(argc, argv);\n");
120     }
121 }
122 
123 bool unit_node::interface_part;
124 char* unit_node::unit_name;
125 
unit_node(token * t_unit,token * t_name,token * t_semi,token * t_interface,decl_node * unit_decl,token * t_implementation,decl_node * unit_def,compound_node * initializer,token * t_end,token * t_dot)126 unit_node::unit_node(token* t_unit, token* t_name, token* t_semi,
127 		     token* t_interface,
128 		     decl_node* unit_decl, token* t_implementation,
129 		     decl_node* unit_def, compound_node* initializer,
130 		     token* t_end, token* t_dot)
131 {
132     CONS10(t_unit, t_name, t_semi, t_interface,
133 	   unit_decl, t_implementation,
134 	   unit_def, initializer, t_end, t_dot);
135 }
136 
attrib(int)137 void unit_node::attrib(int)
138 {
139     decl_node* dcl;
140 
141     unit_tp* type = new unit_tp;
142     b_ring::global_b_ring.add(t_name->name, symbol::s_var, type);
143     b_ring::push(type);
144 
145     type->scope = b_ring::global;
146     b_ring::top_b_ring = type;
147 
148     for (dcl = unit_decl; dcl != NULL; dcl = dcl->next) {
149 	dcl->attrib(ctx_module);
150     }
151     for (dcl = unit_def; dcl != NULL; dcl = dcl->next) {
152 	dcl->attrib(ctx_module);
153     }
154     if (initializer) {
155 	curr_proc = main = new proc_tp;
156 	initializer->attrib(ctx_program);
157     }
158 }
159 
translate(int)160 void unit_node::translate(int)
161 {
162     decl_node* dcl;
163     char* unit_name = "";
164     if (t_name != NULL) {
165 	unit_name = t_name->out_text;
166 	t_unit->set_trans(dprintf("#define __%s_implementation__\n",
167 				  unit_name));
168 	token::disable(t_name, t_semi);
169     }
170     if (t_end) {
171 	t_end->disable();
172     }
173     t_dot->disable();
174     curr_proc = NULL;
175 
176     interface_part = TRUE;
177     for (dcl = unit_decl; dcl != NULL; dcl = dcl->next) {
178 	unit_node::unit_name = unit_name;
179 	dcl->translate(ctx_module);
180     }
181     interface_part = FALSE;
182     for (dcl = unit_def; dcl != NULL; dcl = dcl->next) {
183 	unit_node::unit_name = unit_name;
184 	dcl->translate(ctx_module);
185     }
186 
187     if (initializer) {
188 	curr_proc = main;
189 	global_func_decl_level = initializer->t_begin;
190 	unit_node::unit_name = unit_name;
191 	initializer->translate(ctx_program);
192 	token* first_stmt = initializer->t_begin->next_relevant();
193 
194 	initializer->t_begin->prepend(
195 	    dprintf("class unit_%s_initialize {\n"
196 		    "  public: unit_%s_initialize();\n"
197 		    "};\n"
198 		    "static unit_%s_initialize %s_constructor;\n\n"
199 		    "unit_%s_initialize::unit_%s_initialize() ",
200 		    unit_name, unit_name, unit_name, unit_name,
201 		    unit_name, unit_name));
202 
203         main->insert_temporaries(first_stmt);
204     }
205     t_implementation->cat = CAT_WSPC;
206     t_interface->cat = CAT_WSPC;
207 }
208 
209 
module_node(token * program,token * name,import_list_node * params,token * semi,decl_node * decls,token * t_dot)210 module_node::module_node(token* program, token* name,
211 			 import_list_node* params,
212 			 token* semi, decl_node* decls, token* t_dot)
213 {
214     CONS6(program, name, params, semi, decls, t_dot);
215 }
216 
attrib(int)217 void module_node::attrib(int)
218 {
219     for(decl_node* dcl = decls; dcl != NULL; dcl = dcl->next) {
220 	dcl->attrib(ctx_module);
221     }
222 }
223 
translate(int)224 void module_node::translate(int)
225 {
226     if (program != NULL) {
227         token::disable(program, semi);
228     }
229     if (t_dot != NULL) {
230 	t_dot->disable();
231     }
232     for(decl_node* dcl = decls; dcl != NULL; dcl = dcl->next) {
233 	dcl->translate(ctx_module);
234     }
235 }
236 
237 
238 
239 
block_node(decl_node * decls,compound_node * body)240 block_node::block_node(decl_node* decls, compound_node* body)
241 {
242     CONS2(decls, body);
243 }
244 
attrib(int ctx)245 void block_node::attrib(int ctx)
246 {
247     for (decl_node* dcl = decls; dcl != NULL; dcl = dcl->next) {
248         dcl->attrib(ctx);
249     }
250     body->attrib(ctx);
251 }
252 
253 
translate(int ctx)254 void block_node::translate(int ctx)
255 {
256     for( decl_node* dcl = decls; dcl != NULL; dcl = dcl->next ) {
257         dcl->translate(ctx);
258     }
259     body->translate(ctx);
260     f_tkn = decls ? decls->f_tkn : body->f_tkn;
261     l_tkn = body->l_tkn;
262 }
263 
264 
is_compound()265 bool stmt_node::is_compound() { return FALSE; }
266 
267 
label_node(token * ident,token * colon,stmt_node * stmt)268 label_node::label_node(token* ident, token* colon, stmt_node* stmt)
269 {
270     CONS3(ident, colon, stmt);
271 }
272 
attrib(int ctx)273 void label_node::attrib(int ctx)
274 {
275     stmt->attrib(ctx);
276 }
277 
translate(int ctx)278 void label_node::translate(int ctx)
279 {
280     ident->set_trans(dprintf("L%s", ident->out_text));
281     stmt->translate(ctx);
282     f_tkn = ident;
283     l_tkn = stmt->l_tkn;
284 }
285 
with_node(token * t_with,expr_node * ptrs,token * t_do,stmt_node * body)286 with_node::with_node(token* t_with, expr_node* ptrs, token* t_do, stmt_node* body)
287 {
288     CONS4(t_with, ptrs, t_do, body);
289 }
290 
291 
292 int with_node::nested = 0;
293 
push_with_context(b_ring * block,expr_node * ptr,stmt_node * body)294 static void push_with_context(b_ring* block, expr_node* ptr, stmt_node* body)
295 {
296     record_tp  *type;
297     symbol     *save_with = NULL;
298     b_ring     **bpp = NULL;
299 
300     ptr->attrib(ctx_value);
301     if (ptr->type == NULL) {
302 	body->attrib(ctx_value);
303 	return;
304     }
305     type = (record_tp*)ptr->type->get_typedef();
306 
307     if (type->tag == tp_record || type->tag == tp_object) {
308 	for (bpp = &b_ring::curr_b_ring; *bpp != NULL; bpp = &(*bpp)->outer) {
309 	    if (*bpp == type) {
310 		*bpp = (*bpp)->outer;
311 		break;
312 	    }
313 	}
314 	b_ring::push(type);
315         save_with = type->with;
316 
317 	if (ptr->tag == tn_atom
318 	    && (((atom_expr_node*)ptr)->var == NULL
319 		|| ((atom_expr_node*)ptr)->var->ring->scope != b_ring::record))
320 	{
321 	    // Variable of unnamed type is used as 'with' expression
322 	    // Do not create new variable in this case (since it's type will
323 	    // be incompatible), instead of this substitute original variable
324 	    type->with = ((atom_expr_node*)ptr)->var;
325 	} else {
326 	    nm_entry* with = with_node::nested
327 		? nm_entry::add(dprintf("with%d",with_node::nested),TKN_IDENT)
328 		: nm_entry::add("with", TKN_IDENT);
329 	    type->with = block->add(with, symbol::s_ref, type);
330 	}
331 	with_node::nested += 1;
332     }
333     if (ptr->next) push_with_context(block, ptr->next, body);
334     else body->attrib(ctx_value);
335 
336     if (type->tag == tp_record || type->tag == tp_object) {
337 	type->with = save_with;
338 	with_node::nested -= 1;
339         b_ring::pop();
340 	if (bpp != NULL) {
341 	    type->outer = *bpp;
342 	    *bpp = type;
343 	}
344     }
345 }
346 
attrib(int)347 void with_node::attrib(int)
348 {
349     b_ring *block = new b_ring(b_ring::block);
350 
351     b_ring::push(block);
352     nested_counter = nested;
353     push_with_context(block, ptrs, body);
354     b_ring::pop();
355 }
356 
357 
358 
translate(int ctx)359 void with_node::translate(int ctx)
360 {
361     token* stmt1;
362 
363     body->translate(ctx);
364     t_do->disable();
365 
366     f_tkn = t_with;
367     l_tkn = body->l_tkn;
368 
369     if (ptrs->tag == tn_atom && ptrs->next == NULL
370 	&& (((atom_expr_node*)ptrs)->var == NULL
371 	    || ((atom_expr_node*)ptrs)->var->ring->scope != b_ring::record))
372     {
373 	token::disable(t_with, t_do);
374 	t_do->disappear();
375 	return;
376     }
377     if (body->is_compound())  {
378 	t_with->set_trans("{\n");
379 	body->l_tkn->set_bind(t_with);
380 	body->f_tkn->disable();
381 	stmt1 = body->f_tkn->next_relevant();
382     } else {
383         t_with->set_trans("{");
384 	l_tkn = body->l_tkn->append("}");
385 	stmt1 = body->f_tkn;
386     }
387 
388     for (expr_node *e = ptrs; e != NULL; e = e->next) {
389 	e->translate(language_c ? ctx_access : ctx_value);
390 
391 	if (e->tag == tn_atom
392 	    && (((atom_expr_node*)e)->var == NULL
393 		|| ((atom_expr_node*)e)->var->ring->scope != b_ring::record))
394 	{
395 	    token::disable(e->f_tkn, e->l_tkn);
396 	    token* comma = e->l_tkn->next_relevant();
397 	    if (comma->tag == TKN_COMMA) {
398 		comma->disable();
399 	    }
400 	} else if (e->type != NULL) {
401 	    if (e->type->name == NULL && e->type->tpd != NULL) {
402 		((record_tpd_node*)e->type->tpd)->assign_name();
403 	    }
404 	    e->type->insert_before(e->f_tkn)->set_pos(stmt1);
405 	    if (language_c) {
406 		if (nested_counter == 0)  {
407 		    e->f_tkn->prepend("* with = ");
408 		} else {
409 		    e->f_tkn->prepend(dprintf("* with%d = ", nested_counter));
410 		}
411 		if (e->tag != tn_address) {
412 		    e->f_tkn->prepend("&");
413 		}
414 	    } else {
415 		if (nested_counter == 0)  {
416 		    e->f_tkn->prepend("& with = ");
417 		} else {
418 		    e->f_tkn->prepend(dprintf("& with%d = ", nested_counter));
419 		}
420 	    }
421 	    if (e->l_tkn->next_relevant()->tag == TKN_COMMA) {
422 		e->l_tkn->next_relevant()->set_trans(";\n");
423 	    } else {
424 		e->l_tkn->append(";");
425 	    }
426 	}
427 	nested_counter += 1;
428     }
429     swallow_semicolon();
430 }
431 
pcall_node(expr_node * fcall)432 pcall_node::pcall_node(expr_node* fcall)
433 {
434     CONS1(fcall);
435 }
436 
attrib(int)437 void pcall_node::attrib(int)
438 {
439     fcall->attrib(ctx_statement);
440 }
441 
translate(int)442 void pcall_node::translate(int)
443 {
444     fcall->translate(ctx_statement);
445     f_tkn = fcall->f_tkn;
446     l_tkn = fcall->l_tkn;
447     force_semicolon();
448 }
449 
450 
read_node(token * t_read,expr_group_node * params)451 read_node::read_node(token* t_read, expr_group_node* params)
452 {
453     CONS2(t_read, params);
454 }
455 
attrib(int)456 void read_node::attrib(int)
457 {
458     if( params ) {
459 	params->attrib(ctx_lvalue);
460     }
461 }
462 
463 
translate(int)464 void read_node::translate(int)
465 {
466     f_tkn = l_tkn = t_read;
467 
468     if (language_c) {
469         if (params) {
470             char const* format = "";
471 	    char const* newln = (t_read->tag == TKN_READLN) ? (char *) "\\n" : "";
472 	    expr_node *prm = params->expr;
473 
474 	    l_tkn = params->rpar;
475 
476 	    if (prm->type->tag == tp_file) {
477 		prm->translate(ctx_value);
478 		expr_node* file = prm;
479 		while ((prm = prm->next) != NULL){
480 		    prm->translate(ctx_lvalue);
481 		    if (prm->tag == tn_filevar && language_c) {
482 			prm->f_tkn->prepend("scopy(")->set_pos(t_read);
483 		    } else {
484 			prm->f_tkn->prepend("sread(")->set_pos(t_read);
485 		    }
486 		    prm->f_tkn->copy(file->f_tkn, file->l_tkn);
487 		    prm->f_tkn->prepend(", ");
488 		    prm->l_tkn->append(")");
489 		}
490 		token::disable(t_read, file->l_tkn->next_relevant());
491 		params->rpar->disable();
492 		force_semicolon();
493 		return;
494 	    }
495 	    if (prm->type->tag == tp_text) {
496 		prm->translate(ctx_access);
497 		if (prm->tag != tn_address) {
498 		    prm->f_tkn->prepend("&");
499 		}
500 		prm = prm->next;
501 		t_read->set_trans("tread");
502 	    } else {
503 		t_read->set_trans("cread");
504 	    }
505 	    int n_params = 0;
506 	    while( prm != NULL ) {
507 		char fmt = '?';
508 		prm->translate(ctx_access);
509 		n_params += 1;
510 		switch (prm->type->tag) {
511 		  case tp_dynarray:
512 		  case tp_array:
513 		    fmt = 's';
514 		    ((array_tp*)prm->type->get_typedef())
515 			->insert_dimensions(prm);
516 		    break;
517 		  case tp_real:
518 		    fmt = 'f';
519 		    break;
520 		  case tp_integer:
521 		    fmt = 'i';
522 		    break;
523 		  case tp_char:
524 		    fmt = 'c';
525 		    break;
526 		  case tp_bool:
527 		    fmt = 'b';
528 		    break;
529 		  case tp_range:
530 		    switch(((range_tp*)prm->type->get_typedef())->size) {
531 		      case 1: fmt = 'B'; break;
532 		      case 2: fmt = 'W'; break;
533 		      case 4: fmt = 'i'; break;
534 		      default:
535 			warning(prm->f_tkn, "sizeof range type is %d",
536 				((range_tp*)prm->type->get_typedef())->size);
537 		    }
538 		    break;
539 		  default:
540 		    warning(prm->f_tkn, "invalid parameter for read operator");
541 		}
542 		format = dprintf("%s%%%c", format, fmt);
543 		if (fmt != 's' && prm->tag != tn_address) {
544 		    prm->f_tkn = prm->f_tkn->prepend("&");
545 		}
546 		prm = prm->next;
547 	    }
548 	    if (params->expr->type->tag == tp_text) {
549 		params->expr->l_tkn->append(dprintf(", \"%s%s\"",
550 						    format, newln));
551 	    } else {
552 		params->lpar->append(dprintf(
553 		    n_params ? "\"%s%s\", " : "\"%s%s\"", format, newln));
554 	    }
555 	} else if (t_read->tag == TKN_READLN) {
556 	    t_read->set_trans("cread(\"\\n\")");
557 	} else {
558 	    warning(t_read, "read statement with no effect");
559 	    t_read->disable();
560 	}
561 
562     } else { // C++
563 
564 	if (params) {
565 	    l_tkn = params->rpar;
566 	    params->lpar->disable();
567 	    params->rpar->disable();
568 
569 	    expr_node *prm = params->expr;
570 	    bool newln = (t_read->tag == TKN_READLN);
571 
572 	    if (prm->type->tag == tp_text || prm->type->tag == tp_file) {
573 		prm->translate(ctx_value);
574 		if (prm->next) {
575 		    prm->l_tkn->next_relevant()->set_trans(" >> ");
576 		}
577 		prm->f_tkn->set_pos(t_read);
578 		t_read->disable();
579 		prm = prm->next;
580 	    } else {
581 		t_read->set_trans("input >> ");
582 	    }
583 	    while (prm != NULL) {
584 		prm->translate(ctx_lvalue);
585 		if (prm->next != NULL) {
586 		    prm->l_tkn->next_relevant()->set_trans(" >> ");
587 		}
588 		prm = prm->next;
589 	    }
590 	    if (newln) {
591 		l_tkn = l_tkn->append(" >> NL");
592 	    }
593 	} else if (t_read->tag == TKN_READLN) {
594 	    t_read->set_trans("input >> NL");
595 	} else {
596 	    warning(t_read, "read statement with no effect");
597 	    t_read->disable();
598 	}
599     }
600     force_semicolon();
601 }
602 
603 
write_node(token * t_write,write_list_node * params)604 write_node::write_node(token* t_write, write_list_node* params)
605 {
606     CONS2(t_write, params);
607 }
608 
attrib(int)609 void write_node::attrib(int)
610 {
611     if( params ) {
612 	params->attrib(ctx_value);
613     }
614 }
615 
616 
617 static char* write_format;
618 static int   n_write_params;
619 
translate(int)620 void write_node::translate(int)
621 {
622     f_tkn = l_tkn = t_write;
623 
624     if (language_c) {
625         if (params) {
626 	    write_param_node *prm = params->vals;
627 
628 	    l_tkn = params->rpar;
629 	    char const* newln = (t_write->tag == TKN_WRITELN) ? (char *) "\\n" : "";
630             write_format = NULL;
631 	    if (prm->type->tag == tp_file) {
632 		prm->translate(ctx_value);
633 		expr_node* file = prm;
634 		while ((prm = (write_param_node*)prm->next) != NULL){
635 		    prm->translate(ctx_value);
636 		    prm->f_tkn->prepend("swrite(")->set_pos(t_write);
637 		    prm->f_tkn->copy(file->f_tkn, file->l_tkn);
638 		    prm->f_tkn->prepend(", ");
639 		    prm->l_tkn->append(")");
640 		}
641 		token::disable(t_write, file->l_tkn->next_relevant());
642 		params->rpar->disable();
643 		force_semicolon();
644 		return;
645 	    }
646 	    if (prm->type->tag == tp_text) {
647 		prm->translate(ctx_access);
648 		if (prm->val->tag != tn_address) {
649 		    prm->f_tkn->prepend("&");
650 		}
651 		prm = (write_param_node*)prm->next;
652 		t_write->set_trans("twrite");
653 	    } else {
654 		t_write->set_trans("cwrite");
655 	    }
656 	    write_format = "";
657 	    n_write_params = 0;
658 	    while( prm != NULL ) {
659 		prm->translate(ctx_value);
660 		prm = (write_param_node*)prm->next;
661 	    }
662 	    if (params->vals->type->tag == tp_text) {
663 		params->vals->l_tkn->append(dprintf(", \"%s%s\"",
664 					      write_format, newln));
665 	    } else {
666 		params->lpar->append(dprintf(
667 		    n_write_params ? "\"%s%s\", " : "\"%s%s\"",
668 		    write_format, newln));
669 	    }
670 	} else if (t_write->tag == TKN_WRITELN) {
671 	    t_write->set_trans("cwrite(\"\\n\")");
672 	} else {
673 	    warning(t_write, "write statement with no effect");
674 	    t_write->disable();
675 	}
676 
677     } else { // language C++
678 
679 	if (params) {
680 	    l_tkn = params->rpar;
681 	    if (t_write->tag == TKN_STR) { // Turbo Pascal
682 		write_param_node *prm = params->vals;
683 		while (prm != NULL) {
684 		    prm->translate(ctx_toascii);
685 		    prm = (write_param_node*)prm->next;
686 		}
687 	    } else {
688 		params->lpar->disable();
689 		params->rpar->disable();
690 
691 		write_param_node *prm = params->vals;
692 		bool newln = (t_write->tag == TKN_WRITELN);
693 		if (prm->type->tag == tp_text || prm->type->tag == tp_file) {
694 		    prm->translate(ctx_value);
695 		    if (prm->next) {
696 			prm->l_tkn->next_relevant()->set_trans( " << ");
697 		    }
698 		    prm->f_tkn->set_pos(t_write);
699 		    t_write->disable();
700 		    prm = (write_param_node*)prm->next;
701 		} else {
702 		    t_write->set_trans("output << ");
703 		}
704 		while (prm != NULL) {
705 		    prm->translate(ctx_value);
706 		    if (prm->next != NULL) {
707 			prm->l_tkn->next_relevant()->set_trans(" << ");
708 		    }
709 		    prm = (write_param_node*)prm->next;
710 		}
711 		if (newln) {
712 		    l_tkn = l_tkn->append(" << NL");
713 		}
714 	    }
715 	} else if (t_write->tag == TKN_WRITELN) {
716 	    t_write->set_trans("output << NL");
717 	} else {
718 	    warning(t_write, "write statement with no effect");
719 	    t_write->disable();
720 	}
721     }
722     force_semicolon();
723 }
724 
compound_node(token * t_begin,stmt_node * body,token * t_end)725 compound_node::compound_node(token* t_begin,  stmt_node* body, token* t_end)
726 {
727     CONS3(t_begin, body, t_end);
728 }
729 
attrib(int)730 void compound_node::attrib(int)
731 {
732     for (stmt_node* stmt = body; stmt != NULL; stmt = stmt->next) {
733         stmt->attrib(ctx_statement);
734     }
735 }
736 
translate(int)737 void compound_node::translate(int)
738 {
739     f_tkn = t_begin;
740     l_tkn = t_end;
741     for (stmt_node* stmt = body; stmt != NULL; stmt = stmt->next) {
742         stmt->translate(ctx_statement);
743     }
744     t_begin->set_trans("{");
745     t_end->set_trans("}");
746     swallow_semicolon();
747 }
748 
is_compound()749 bool compound_node::is_compound() { return TRUE; }
750 
751 assign_node* assign_node::stmt;
752 
assign_node(expr_node * lval,token * assign,expr_node * rval)753 assign_node::assign_node(expr_node* lval, token* assign, expr_node* rval)
754 {
755     CONS3(lval, assign, rval);
756 }
757 
attrib(int)758 void assign_node::attrib(int)
759 {
760     lval->attrib(ctx_lvalue);
761     rval->attrib(lval->type && lval->type->tag == tp_proc
762 		 ? ctx_procptr : ctx_rvalue);
763     if (lval->type && lval->type->tag == tp_set) {
764 	rval->type = lval->type->get_typedef();
765     }
766 }
767 
translate(int)768 void assign_node::translate(int)
769 {
770     stmt = this;
771     lval->translate(ctx_lvalue);
772     if (lval->tag == tn_filevar) {
773 	rval->translate(ctx_value);
774 	f_tkn = lval->f_tkn->prepend("store(");
775 	token::disable(lval->l_tkn->next, rval->f_tkn->prev);
776 	lval->l_tkn->append(", ");
777 	l_tkn = rval->l_tkn->append(")");
778 	force_semicolon();
779 	return;
780     }
781     rval->translate(lval->type && lval->type->tag == tp_proc
782 		    ? ctx_procptr : ctx_rvalue);
783 
784     if (language_c && rval->tag == tn_retarr) {
785 	// function return array right in assignment destination
786 	//   lval is moved into function arguments
787 	f_tkn = rval->f_tkn;
788 	l_tkn = rval->l_tkn;
789 	assign->disable();
790 	force_semicolon();
791 	return;
792     }
793     f_tkn = lval->f_tkn;
794     l_tkn = rval->l_tkn;
795     if (lval->type && (lval->type->tag == tp_array || lval->type->tag == tp_varying_string)) {
796 	if (language_c) {
797 	    if (rval->type && rval->type->tag == tp_char) {
798 		f_tkn = lval->f_tkn->prepend("*");
799 		assign->set_trans("=");
800 	    } else {
801 		token::disable(lval->l_tkn->next, rval->f_tkn->prev);
802 		lval->l_tkn->append(", ");
803 		if (lval->is_parameter()) {
804 		    f_tkn = lval->f_tkn->prepend("memcpy(");
805 		    if (lval->type->name != NULL) {
806 			l_tkn = rval->l_tkn->append(dprintf(", sizeof(%s))",
807 							    lval->type->name));
808 		    } else {
809 			l_tkn = rval->l_tkn->append(", ")->append("*sizeof(*");
810 			((array_tp*)lval->type->get_typedef())->
811 			    insert_length(l_tkn);
812 			l_tkn = l_tkn->append("))");
813 			l_tkn->copy(lval->f_tkn, lval->l_tkn);
814 		    }
815 		} else {
816 		    f_tkn = lval->f_tkn->prepend("arrcpy(");
817 		    token::disable(lval->l_tkn->next, rval->f_tkn->prev);
818 		    lval->l_tkn->append(", ");
819 		    l_tkn = rval->l_tkn->append(")");
820 		}
821 	    }
822 	} else { // language C++
823 	    if (no_array_assign_operator && rval->type &&
824 		(rval->type->tag == tp_char || rval->type->tag == tp_string))
825 	    {
826 #if 0
827 		if (rval->type->tag == tp_char) {
828 		    f_tkn = lval->f_tkn->prepend("*");
829 		    assign->set_trans("=");
830 		} else
831 #endif
832 		{
833 		    token::disable(lval->l_tkn->next, rval->f_tkn->prev);
834 		    lval->l_tkn->append(".assign(");
835 		    l_tkn = rval->l_tkn->append(")");
836 		}
837 	    } else {
838 		assign->set_trans("=");
839 	    }
840 	}
841     } else {
842 	if (assign->tag == TKN_LET) {
843 	    assign->set_trans("=");
844 	}
845     }
846     force_semicolon();
847 }
848 
849 
goto_node(token * t_goto,token * t_label)850 goto_node::goto_node(token* t_goto, token* t_label)
851 {
852     CONS2(t_goto, t_label);
853 }
854 
attrib(int)855 void goto_node::attrib(int)
856 {
857 }
858 
translate(int)859 void goto_node::translate(int)
860 {
861     t_label->set_trans(dprintf("L%s", t_label->out_text));
862     f_tkn = t_goto;
863     l_tkn = t_label;
864     force_semicolon();
865 }
866 
867 //--------------------------------------------------------------------
868 
case_node(expr_node * list,token * coln,stmt_node * stmt)869 case_node::case_node(expr_node* list, token* coln, stmt_node* stmt)
870 {
871     CONS3(list, coln, stmt);
872     next = NULL;
873 }
874 
attrib(int ctx)875 void case_node::attrib(int ctx)
876 {
877     for (expr_node* e = list; e != NULL; e = e->next) {
878 	e->attrib(ctx);
879     }
880     stmt->attrib(ctx);
881     if (turbo_pascal) {
882 	for (stmt_node* st = stmt->next; st != NULL; st = st->next) {
883 	    st->attrib(ctx);
884 	}
885     }
886 }
887 
translate(int)888 void case_node::translate(int)
889 {
890     if (list == NULL) {
891 	assert(turbo_pascal ? coln->tag==TKN_ELSE : coln->tag==TKN_OTHERWISE);
892         coln->set_trans("default:");
893 	stmt->translate(ctx_statement);
894 	if (turbo_pascal) {
895 	    for (stmt_node* st = stmt->next; st != NULL; st = st->next) {
896 		st->translate(ctx_statement);
897 	    }
898 	}
899 	f_tkn = coln;
900 	l_tkn = stmt->l_tkn;
901 
902     } else {
903 
904 	for (expr_node* e = list; e != NULL; e = e->next) {
905 	    e->translate(ctx_value);
906 	    e->f_tkn->prepend("case ");
907 	    e->l_tkn->next_relevant()->set_trans(":");  // replace comma
908 	}
909 	stmt->translate(ctx_statement);
910 	f_tkn = list->f_tkn;
911 	if (f_tkn->line != stmt->l_tkn->line) {
912 	    l_tkn = stmt->l_tkn->append("break;");
913             l_tkn->set_bind(stmt->l_tkn->get_first_token());
914 	    stmt->l_tkn->append("\n");
915         } else {
916 	    l_tkn = stmt->l_tkn->append(" break;");
917 	}
918     }
919 }
920 
921 
switch_node(token * t_case,expr_node * expr,token * t_of,case_node * cases,token * t_end)922 switch_node::switch_node(token* t_case, expr_node* expr, token* t_of,
923 		         case_node* cases, token* t_end)
924 {
925     CONS5(t_case, expr, t_of, cases, t_end);
926 }
927 
attrib(int)928 void switch_node::attrib(int)
929 {
930     expr->attrib(ctx_condition);
931     for (case_node *c = cases; c != NULL; c = c->next) {
932 	c->attrib(ctx_statement);
933     }
934 }
935 
translate(int)936 void switch_node::translate(int)
937 {
938     f_tkn = t_case;
939     l_tkn = t_end;
940     expr->translate(ctx_value);
941     t_case->set_trans("switch");
942     if (expr->tag != tn_group) {
943         expr->f_tkn->prepend("(");
944         expr->l_tkn->append(")");
945     }
946     t_of->set_trans("{");
947     for (case_node *c = cases; c != NULL; c = c->next) {
948         c->translate(ctx_statement);
949     }
950     t_end->set_trans("}");
951     swallow_semicolon();
952 }
953 
if_node(token * t_if,expr_node * expr,token * t_then,stmt_node * alt1,token * t_else,stmt_node * alt2)954 if_node::if_node(token* t_if, expr_node* expr, token* t_then,
955 		 stmt_node* alt1, token* t_else, stmt_node* alt2)
956 {
957     CONS6(t_if, expr, t_then, alt1, t_else, alt2);
958 }
959 
attrib(int)960 void if_node::attrib(int)
961 {
962     expr->attrib(ctx_condition);
963     alt1->attrib(ctx_statement);
964     if (alt2) {
965 	alt2->attrib(ctx_statement);
966     }
967 }
968 
translate(int)969 void if_node::translate(int)
970 {
971     expr->translate(ctx_condition);
972     f_tkn = t_if;
973     if (expr->tag != tn_group) {
974         expr->f_tkn->prepend("(");
975         expr->l_tkn->append(")");
976     }
977     t_then->disable();
978     alt1->translate(ctx_statement);
979     l_tkn = alt1->l_tkn;
980     if (alt2) {
981         alt2->translate(ctx_statement);
982 	l_tkn = alt2->l_tkn;
983     }
984 }
985 
for_node(token * t_for,token * t_ident,token * t_asg,expr_node * from,token * t_to,expr_node * till,token * t_do,stmt_node * body)986 for_node::for_node(token* t_for, token* t_ident, token* t_asg,
987 	           expr_node* from, token* t_to, expr_node* till,
988 	           token* t_do, stmt_node* body)
989 {
990     CONS8(t_for, t_ident, t_asg, from, t_to, till, t_do, body);
991 }
992 
attrib(int)993 void for_node::attrib(int)
994 {
995     from->attrib(ctx_value);
996     till->attrib(ctx_value);
997     body->attrib(ctx_statement);
998     var = b_ring::search_cur(t_ident);
999 }
1000 
translate(int ctx)1001 void for_node::translate(int ctx)
1002 {
1003     if (var != NULL) {
1004 	var->translate(t_ident);
1005     }
1006     t_for->append("(");
1007     t_asg->set_trans("=");
1008     from->translate(ctx_value);
1009     from->l_tkn->append(";");
1010     t_to->set_trans(t_ident->out_text);
1011     t_to->append(t_to->name->tag == TKN_TO ? (char *) " <=" : (char *) " >=");
1012     till->translate(ctx_value);
1013     till->l_tkn->append(";");
1014     if (t_to->name->tag == TKN_TO) {
1015 	if (var && var->type->tag == tp_enum && var->type->name != NULL) {
1016 	    t_do->set_trans(dprintf("%s = succ(%s,%s))",
1017 				    t_ident->out_text, var->type->name,
1018 				    t_ident->out_text));
1019 	} else {
1020 	    t_do->set_trans(dprintf("%s ++)", t_ident->out_text));
1021 	}
1022     } else {
1023 	if (var && var->type->tag == tp_enum && var->type->name != NULL) {
1024 	    t_do->set_trans(dprintf("%s = pred(%s,%s))",
1025 				    t_ident->out_text, var->type->name,
1026 				    t_ident->out_text));
1027 	} else {
1028 	    t_do->set_trans(dprintf("%s --)", t_ident->out_text));
1029 	}
1030     }
1031     body->translate(ctx);
1032     f_tkn = t_for;
1033     l_tkn = body->l_tkn;
1034 }
1035 
while_node(token * t_while,expr_node * expr,token * t_do,stmt_node * body)1036 while_node::while_node(token* t_while, expr_node* expr, token* t_do,
1037 	               stmt_node* body)
1038 {
1039     CONS4(t_while, expr, t_do, body);
1040 }
1041 
attrib(int ctx)1042 void while_node::attrib(int ctx)
1043 {
1044     expr->attrib(ctx_condition);
1045     body->attrib(ctx);
1046 }
1047 
translate(int ctx)1048 void while_node::translate(int ctx)
1049 {
1050     expr->translate(ctx_condition);
1051     if (expr->tag != tn_group) {
1052         expr->f_tkn->prepend("(");
1053         expr->l_tkn->append(")");
1054     }
1055     t_do->disable();
1056     body->translate(ctx);
1057     f_tkn = t_while;
1058     l_tkn = body->l_tkn;
1059 }
1060 
repeat_node(token * t_repeat,stmt_node * body,token * t_until,expr_node * expr)1061 repeat_node::repeat_node(token* t_repeat, stmt_node* body, token* t_until,
1062 			 expr_node*expr)
1063 {
1064     CONS4(t_repeat, body, t_until, expr) ;
1065 }
1066 
attrib(int ctx)1067 void repeat_node::attrib(int ctx)
1068 {
1069     for (stmt_node *stmt = body; stmt != NULL; stmt = stmt->next) {
1070         stmt->attrib(ctx);
1071     }
1072     expr->attrib(ctx_condition);
1073 }
1074 
translate(int ctx)1075 void repeat_node::translate(int ctx)
1076 {
1077     bool body_is_block =
1078 	body != NULL && body->is_compound() && body->next == NULL;
1079 
1080     t_repeat->set_trans(body_is_block ? (char *) "do" : (char *) "do {");
1081     for (stmt_node *stmt = body; stmt != NULL; stmt = stmt->next) {
1082         stmt->translate(ctx);
1083     }
1084     t_until->set_trans(body_is_block ? (char *) "while" : (char *) "} while");
1085     expr->translate(ctx_condition);
1086     f_tkn = t_repeat;
1087     l_tkn = expr->l_tkn;
1088     if (expr->tag != tn_group && expr->tag != tn_atom) {
1089         expr->f_tkn->prepend("(!(");
1090         l_tkn = expr->l_tkn->append("))");
1091     } else {
1092         expr->f_tkn->prepend("(!");
1093         l_tkn = expr->l_tkn->append(")");
1094     }
1095     force_semicolon();
1096 }
1097 
return_node(token * t_return)1098 return_node::return_node(token* t_return)
1099 {
1100     CONS1(t_return);
1101 }
1102 
attrib(int)1103 void return_node::attrib(int)
1104 {
1105 }
1106 
translate(int)1107 void return_node::translate(int)
1108 {
1109     l_tkn = f_tkn = t_return;
1110     if (curr_proc->is_function()) {
1111 	if (language_c && curr_proc->res_type->tag == tp_array) {
1112 	    l_tkn = t_return->append(dprintf(" (%s*)%s_result",
1113 					     curr_proc->res_type->name,
1114 					     curr_proc->proc_name));
1115 	} else {
1116 	    if (curr_proc->is_constructor || curr_proc->is_destructor) {
1117 		l_tkn = t_return->append(" this");
1118 	    } else {
1119 		l_tkn = t_return->append(dprintf(" %s_result",
1120 						 curr_proc->proc_name));
1121 	    }
1122 	}
1123     }
1124     force_semicolon();
1125 }
1126 
empty_node(token * last)1127 empty_node::empty_node(token* last)
1128 {
1129     CONS1(last);
1130 }
1131 
attrib(int)1132 void empty_node::attrib(int)
1133 {
1134     f_tkn = l_tkn = last;
1135 }
1136 
translate(int)1137 void empty_node::translate(int)
1138 {
1139     token* last = l_tkn;
1140     token* prev = last->next->prev_relevant();
1141     if (prev->out_text == NULL || strcmp(prev->out_text, "}") != 0) {
1142         force_semicolon();
1143     }
1144     l_tkn->set_pos(last);
1145 }
1146 
1147 //
1148 // Expression level
1149 //
1150 
1151 
is_parameter()1152 bool expr_node::is_parameter()
1153 {
1154     symbol *var = ((atom_expr_node*)this)->var;
1155     return tag == tn_atom
1156 	&& ((var->flags & (symbol::f_val_param|symbol::f_var_param))
1157 	    || (var->ring->scope != b_ring::record
1158 		&& var->ring != curr_proc
1159 		&& var->ring->scope != b_ring::global));
1160 }
1161 
atom_expr_node(token * tkn)1162 atom_expr_node::atom_expr_node(token* tkn) : expr_node(tn_atom)
1163 {
1164     CONS1(tkn);
1165 }
1166 
attrib(int ctx)1167 void atom_expr_node::attrib(int ctx)
1168 {
1169     if (turbo_pascal && tkn->name->tag == TKN_SELF) {
1170 	assert(proc_def_node::self != NULL);
1171 	type = proc_def_node::self;
1172 	with = proc_def_node::self->with;
1173 	tag = tn_self;
1174 	var = NULL;
1175     } else if (turbo_pascal && tkn->name->tag == TKN_EXIT) {
1176 	type = &void_type;
1177     } else if (!turbo_pascal || tkn->name->tag != TKN_ABSTRACT) {
1178 	var = b_ring::search_cur(tkn);
1179 	if (var != NULL) {
1180 	    if (var->type == NULL) {
1181 		warning(tkn, "type of variable '%s' is unknown", tkn->in_text);
1182 		var->type = &void_type;
1183 	    }
1184 
1185 	    type = var->type;
1186 	    with = var->ring->with;
1187 
1188 	    if (var->flags & symbol::f_const) {
1189 		flags |= tn_is_const;
1190 		value = var->value;
1191 	    }
1192 
1193 	    if (type->tag == tp_proc) {
1194 		if (ctx == ctx_lvalue) {
1195 		    if (type == curr_proc) {
1196 			type = curr_proc->res_type;
1197 			if (type == NULL) {
1198 			    error(tkn,"attempt to return value from procedure");
1199 			}
1200 		    }
1201 		} else {
1202 		    if (ctx == ctx_procptr) {
1203 			var->out_name->flags |= nm_entry::recursive;
1204 		    } else if (ctx != ctx_apply) {
1205 			proc_tp* prc = (proc_tp*)type->get_typedef();
1206 			prc->add_caller(curr_proc);
1207 			type = prc->res_type;
1208 			if (language_c && type != NULL && type->tag == tp_array
1209 			    && ctx != ctx_rvalue)
1210 			{
1211 			    temp = curr_proc->add_temp(type);
1212 			}
1213 		    }
1214 		}
1215 	    } else {
1216 		if (var->ring->scope == b_ring::proc && var->ring != curr_proc)
1217 		{
1218 		    if (var->tag == symbol::s_const) {
1219 			if (!(var->flags & symbol::f_static)) {
1220 			    var->flags |= symbol::f_static;
1221 			    var->ring->make_unique(var);
1222 			}
1223 		    } else {
1224 			curr_proc->add_extra_param(var);
1225 		    }
1226 		}
1227 		if (ctx == ctx_lvalarray || ctx == ctx_lvalue) {
1228 		    var->flags |= symbol::f_lvalue;
1229 		}
1230 	    }
1231 	} else {
1232 	    // Let converter work well even with incorrect code
1233 	    warning(tkn, "undefined identifier '%s'", tkn->in_text);
1234 	    type = &void_type;
1235 	    with = NULL;
1236 	}
1237     }
1238 }
1239 
translate(int ctx)1240 void atom_expr_node::translate(int ctx)
1241 {
1242     l_tkn = f_tkn = tkn;
1243 
1244     if (turbo_pascal && tkn->name->tag == TKN_SELF) {
1245 	if (ctx == ctx_access) {
1246 	    tkn->set_trans("this");
1247 	} else {
1248 	    tkn->set_trans("(*this)");
1249 	}
1250 	return;
1251     } else if (turbo_pascal && tkn->name->tag == TKN_EXIT) {
1252 	if (curr_proc && curr_proc->res_type) {
1253 	    if (curr_proc->proc_name != NULL) {
1254 		tkn->set_trans(dprintf("return %s_result",
1255 				       curr_proc->proc_name));
1256 	    } else {
1257 		tkn->set_trans("return 0");
1258 	    }
1259 	} else {
1260 	    tkn->set_trans("return");
1261 	}
1262 	return;
1263     } else if (turbo_pascal && tkn->name->tag == TKN_ABSTRACT) {
1264 	tkn->set_trans("assert(\"abstract method is called\",false)");
1265 	return;
1266     }
1267     if (var != NULL) {
1268 	var->translate(tkn);
1269         if (var->type == curr_proc && ctx == ctx_lvalue) {
1270 
1271 	    tkn->set_trans(dprintf("%s_result", curr_proc->proc_name));
1272 
1273         } else if (var->type->tag == tp_proc) {
1274 	    if (turbo_pascal && tkn->name->tag == TKN_HALT) {
1275 		tkn->set_trans(ctx == ctx_apply ? (char *) "exit" : (char *) "exit(0)");
1276 		return;
1277 	    }
1278 	    proc_tp* prc = (proc_tp*)var->type->get_typedef();
1279             if (ctx != ctx_procptr && ctx != ctx_apply && ctx != ctx_lvalue) {
1280 	        token* lpar = tkn->append("(");
1281 		token* t = lpar;
1282 		bool first = TRUE;
1283 		param_spec* prm;
1284 
1285 		if (language_c) {
1286 		    for (prm = prc->params;
1287 			 prm != NULL;
1288 			 prm = prm->next)
1289 		    {
1290 			if (!first) {
1291 			    t = t->append(", ");
1292 			}
1293 			first = FALSE;
1294 			if (prm->var->type->tag == tp_file
1295 			    || prm->var->type->tag == tp_text)
1296 			{
1297 			    t = t->append(strcmp(var->in_name->text, (char *) "page")
1298 					  ? (char *) "input" : (char *) "output");
1299 			} else {
1300 			    t = t->append("0");
1301 			}
1302 		    }
1303 		}
1304                 for (prm = prc->extra_params;
1305 	             prm != NULL;
1306                      prm = prm->next)
1307                 {
1308 		    if (prm->var->flags & symbol::f_static) continue;
1309 
1310 		    if (!first) {
1311 			t = t->append(", ");
1312 		    }
1313 		    first = FALSE;
1314 
1315 		    if (language_c && prm->var->tag != symbol::s_ref
1316 			&& (prm->var->tag != symbol::s_const
1317 			    || !prm->var->type->is_scalar())
1318 			&& prm->var->ring == curr_proc
1319 			&& !prm->var->type->is_array())
1320 		    {
1321 			t = t->append("&");
1322 		    }
1323 		    t = t->append(prm->var->out_name->text);
1324                 }
1325                 l_tkn = t = t->append(")");
1326 		if (language_c && type != NULL && type->tag == tp_array) {
1327 		    if (!first) {
1328 			t = lpar->append(", ");
1329 		    }
1330 		    if (ctx == ctx_rvalue) {
1331 			f_tkn->set_pos(assign_node::stmt->lval->f_tkn);
1332 			t->move(assign_node::stmt->lval->f_tkn,
1333 				assign_node::stmt->lval->l_tkn);
1334 			tag = tn_retarr;
1335 		    } else {
1336 			t->prepend(temp);
1337 			f_tkn = f_tkn->prepend("*");
1338 		    }
1339 		}
1340             } // endif not function  pointer
1341         } else if (var->ring->scope == b_ring::record) {
1342 
1343             if (with != NULL) {
1344 		f_tkn = tkn->prepend(language_c && with->tag == symbol::s_ref
1345 				     ? (char *) "->" : (char *) ".")
1346 		    ->prepend(with->out_name->text);
1347 	    }
1348 
1349 	} else if (language_c &&
1350 		   (!var->type->is_array()
1351 		    && (var->tag != symbol::s_const || !var->type->is_scalar())
1352 		    && (var->tag == symbol::s_ref
1353 			|| (!(var->flags & symbol::f_static)
1354 			    && var->ring->scope != b_ring::record
1355 			    && var->ring != curr_proc
1356 			    && var->ring->scope != b_ring::global))))
1357 	{
1358 	    if (ctx == ctx_access) {
1359 		tag = tn_address;
1360 	    } else if (ctx == ctx_array || ctx == ctx_lvalarray) {
1361 		f_tkn = tkn->prepend("(*");
1362 		l_tkn = tkn->append(")");
1363 	    } else {
1364 		f_tkn = tkn->prepend("*");
1365 	    }
1366         } else if (ctx == ctx_statement) {
1367 	    l_tkn = tkn->append("()");
1368         }
1369     }
1370 }
1371 
literal_node(token * value_tkn,int tag)1372 literal_node::literal_node(token* value_tkn, int tag)
1373 : expr_node(tag, tn_is_literal)
1374 {
1375     CONS1(value_tkn);
1376 }
1377 
integer_node(token * value_tkn)1378 integer_node::integer_node(token* value_tkn) : literal_node(value_tkn, tn_intnum)
1379 {
1380     flags |= tn_is_const;
1381 }
1382 
btoi(char * s)1383 static long btoi(char* s)
1384 {
1385     long val = 0;
1386     while (*s == '0' || *s == '1') {
1387 	val = (val << 1) | (*s++ - '0');
1388     }
1389     return val;
1390 }
1391 
attrib(int)1392 void integer_node::attrib(int)
1393 {
1394     type = &integer_type;
1395     char* p = value_tkn->in_text;
1396 
1397     if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
1398     {
1399 	sscanf(p + 2, "%x", &value);
1400 	radix = 16;
1401     } else if (turbo_pascal && *p == '$') {
1402 	sscanf(p + 1, "%x", &value);
1403 	radix = 16;
1404     } else if(strncmp(p, "2#", 2) == 0) {
1405 	value = btoi(p + 2);
1406 	radix = 8;
1407     } else if(strncmp(p, "8#", 2) == 0) {
1408 	sscanf(p + 2, "%o", &value);
1409 	radix = 8;
1410     } else if(strncmp(p, "16#", 3) == 0) {
1411 	sscanf(p + 3, "%x", &value);
1412 	radix = 16;
1413     } else if(strncmp(p, "10#", 3) == 0) {
1414 	sscanf(p + 3, "%d", &value);
1415 	radix = 10;
1416     } else {
1417 	int len = strlen(p)-1;
1418 	if (p[len] == 'h' || p[len] == 'H') {
1419 	    sscanf(p, "%x", &value);
1420 	    radix = 16;
1421 	} else if (p[len] == 'b' || p[len] == 'B') {
1422 	    value = btoi(p);
1423 	    radix = 16;
1424 	} else {
1425 	    sscanf(p, "%d", &value);
1426 	    radix = 10;
1427 	}
1428     }
1429 }
1430 
translate(int)1431 void integer_node::translate(int)
1432 {
1433     f_tkn = l_tkn = value_tkn;
1434 
1435     switch(radix) {
1436       case 8:
1437 	value_tkn->set_trans(dprintf("%#o", value));
1438 	break;
1439       case 10:
1440 	value_tkn->set_trans(dprintf("%d", value));
1441 	break;
1442       case 16:
1443 	value_tkn->set_trans(dprintf("%#x", value));
1444 	break;
1445     }
1446 }
1447 
1448 
real_node(token * value_tkn)1449 real_node::real_node(token* value_tkn) : literal_node(value_tkn, tn_realnum) {}
1450 
attrib(int)1451 void real_node::attrib(int)
1452 {
1453     type = &real_type;
1454 }
1455 
translate(int)1456 void real_node::translate(int)
1457 {
1458     f_tkn = l_tkn = value_tkn;
1459 }
1460 
string_node(token * value_tkn)1461 string_node::string_node(token* value_tkn) : literal_node(value_tkn, tn_string) {}
1462 
attrib(int)1463 void string_node::attrib(int)
1464 {
1465     char *s = value_tkn->out_text;
1466 
1467     if ((s[0] == '\'' && s[1] != '\'' && s[2] == '\'' && s[3] == '\0') ||
1468        (s[0] == '\'' && s[1] == '\'' && s[2] == '\'' && s[3] == '\'' && s[4] == '\0') ||
1469 	s[0] == '#' && strchr(s+1, '#') == NULL && strchr(s+1, '\'') == NULL)
1470     {
1471         type = &char_type;
1472     } else {
1473         type = &string_type;
1474     }
1475 }
1476 
translate(int ctx)1477 void string_node::translate(int ctx)
1478 {
1479     char *s = value_tkn->out_text;
1480 
1481     f_tkn = l_tkn = value_tkn;
1482 
1483     if (s[0] == '\'' && s[1] != '\'' && s[2] == '\'' && s[3] == '\0') {
1484         tag = tn_char;
1485 	value = (unsigned char)s[1];
1486 	if (s[1] == '\\') {
1487 	    s[2] = '\\';
1488 	    s[3] = '\'';
1489 	    s[4] = '\0';
1490 	}
1491     } else if (s[0] == '\'' && s[1] == '\'' && s[2] == '\''
1492 	    && s[3] == '\'' && s[4] == '\0')
1493     {
1494         tag = tn_char;
1495 	value = '\'';
1496 	s[1] = '\\';
1497     } else if (s[0] == '#' && strchr(s+1, '#') == NULL
1498 	       && strchr(s+1, '\'') == NULL)
1499     {
1500         tag = tn_char;
1501 	if (s[1] == '$') {
1502 	    sscanf(s+2, "%x\n", &value);
1503 	    value_tkn->set_trans(dprintf("'\\x%x'", value));
1504 	} else {
1505 	    sscanf(s+1, "%d\n", &value);
1506 	    value_tkn->set_trans(dprintf("'\\%o'", value));
1507 	}
1508     } else {
1509 	if (!language_c && ctx == ctx_record) {
1510 	    char *buf = new char[strlen(s)*4];
1511 	    char ch, *d = buf;
1512 	    *d++ = '{';
1513 	    *d++ = '{';
1514 	    bool in_quotes = FALSE;
1515 	    while((ch = *s++) != '\0') {
1516 		switch(ch) {
1517 		  case '\\':
1518 		    *d++ = '\\';
1519 		    *d++ = '\\';
1520 		    continue;
1521 		  case '\'':
1522 		    if (in_quotes) {
1523 			if (*s == '\'') {
1524 			    if (*(d-1) != '{') *d++ = ',';
1525 			    *d++ = '\'';
1526 			    *d++ = '\\';
1527 			    *d++ = '\'';
1528 			    *d++ = '\'';
1529 			    s += 1;
1530 			}
1531 			in_quotes = FALSE;
1532 		    } else {
1533 			in_quotes = TRUE;
1534 		    }
1535 		    continue;
1536 		  case '#':
1537 		    if (!in_quotes) {
1538 			if (*(d-1) != '{') *d++ = ',';
1539 			if (*s == '$') {
1540 			    *d++ = '0';
1541 			    *d++ = 'x';
1542 			    s += 1;
1543 			    while (ch = *++s, isxdigit((unsigned char)ch)) {
1544 				*d++ = ch;
1545 			    }
1546 			} else {
1547 			    while ((ch = *s++) >= '0' && ch <= '9') {
1548 				*d++ = ch;
1549 			    }
1550 			    s -= 1;
1551 			}
1552 			continue;
1553 		    }
1554 		  default:
1555 		    if (*(d-1) != '{') *d++ = ',';
1556 		    *d++ = '\'';
1557 		    *d++ = ch;
1558 		    *d++ = '\'';
1559 		}
1560 	    }
1561 	    *d++ = '}';
1562 	    *d++ = '}';
1563 	    *d++ = '\0';
1564 	    value_tkn->set_trans(buf);
1565 	    return;
1566 	} else {
1567 	    char *buf = new char[strlen(s)*2 + 1];
1568 	    char ch, *d = buf;
1569 	    bool in_quotes = FALSE;
1570 	    *d++ = '"';
1571 	    while((ch = *s++) != '\0') {
1572 		switch(ch) {
1573 		  case '\\':
1574 		    *d++ = '\\';
1575 		    *d++ = '\\';
1576 		    continue;
1577 		  case '"':
1578 		    *d++ = '\\';
1579 		    *d++= '"';
1580 		    continue;
1581 		  case '\'':
1582 		    if (in_quotes) {
1583 			if (*s == '\'') {
1584 			    *d++ = '\'';
1585 			}
1586 			in_quotes = FALSE;
1587 		    } else {
1588 			in_quotes = TRUE;
1589 		    }
1590 		    continue;
1591 		  case '?':
1592 		    if (s[-1] == '?' &&
1593 			(s[1] == '=' || s[1] == '/' ||
1594 			 (s[1] == '\'' && s[2] == '\'') ||
1595 			 s[1] == '(' || s[1] == ')' || s[1] == '!' ||
1596 			 s[1] == '-' || s[1] == '<' || s[1] == '>'))
1597 		    {
1598 			*d++ = '\\';
1599                     }
1600 		    *d++ = ch;
1601 		    continue;
1602 		  case '#':
1603 		    if (!in_quotes) {
1604 			int code = 0;
1605 			if (*s == '$') {
1606 			    *d++ = '\\';
1607 			    *d++ = 'x';
1608 			    while (ch = *++s, isxdigit((unsigned char)ch)) {
1609 				*d++ = ch;
1610 			    }
1611 			    continue;
1612 			} else {
1613 			    while ((ch = *s++) >= '0' && ch <= '9') {
1614 				code = code*10 + ch - '0';
1615 			    }
1616 			    s -= 1;
1617 			}
1618 			switch (code) {
1619 			  case '\n':
1620 			    *d++ = '\\';
1621 			    *d++ = 'n';
1622 			    break;
1623 			  case '\t':
1624 			    *d++ = '\\';
1625 			    *d++ = 'n';
1626 			    break;
1627 			  case '\r':
1628 			    *d++ = '\\';
1629 			    *d++ = 'r';
1630 			    break;
1631 			  case '\f':
1632 			    *d++ = '\\';
1633 			    *d++ = 'f';
1634 			    break;
1635 			  case '\b':
1636 			    *d++ = '\\';
1637 			    *d++ = 'b';
1638 			    break;
1639 			  case '\v':
1640 			    *d++ = '\\';
1641 			    *d++ = 'v';
1642 			    break;
1643 			  default:
1644 			    *d++ = '\\';
1645 			    d += sprintf(d, "%o", code);
1646 			}
1647 			continue;
1648 		    }
1649 		  default:
1650 		    *d++ = ch;
1651 		}
1652 	    }
1653 	    *d++ = '"';
1654 	    *d++ = '\0';
1655 	    value_tkn->set_trans(buf);
1656 	}
1657     }
1658 }
1659 
set_elem_node(expr_node * item)1660 set_elem_node::set_elem_node(expr_node* item)
1661 {
1662     CONS1(item);
1663 }
1664 
attrib(int ctx)1665 void set_elem_node::attrib(int ctx)
1666 {
1667     item->attrib(ctx);
1668     type = item->type;
1669 }
1670 
translate(int ctx)1671 void set_elem_node::translate(int ctx)
1672 {
1673     item->translate(ctx);
1674     f_tkn = item->f_tkn;
1675     l_tkn = item->l_tkn;
1676     if (language_c && short_set && type->tag == tp_enum &&
1677 	((enum_tp*)type->get_typedef())->n_elems <= SHORT_SET_CARD)
1678     {
1679 	token* t = l_tkn->next_relevant();
1680 	if (t->tag == TKN_COMMA) {
1681 	    t->set_trans("|");
1682 	    if (t->next->tag == TKN_SPACE) t->next->disable();
1683 	    if (t->prev->tag == TKN_SPACE) t->prev->disable();
1684 	}
1685 	f_tkn = f_tkn->prepend("ELEM(");
1686 	l_tkn = l_tkn->append(")");
1687     }
1688 }
1689 
set_range_node(expr_node * low,token * dots,expr_node * high)1690 set_range_node::set_range_node(expr_node* low, token* dots, expr_node* high)
1691 {
1692     CONS3(low, dots, high);
1693 }
1694 
attrib(int ctx)1695 void set_range_node::attrib(int ctx)
1696 {
1697     low->attrib(ctx);
1698     high->attrib(ctx);
1699     type = low->type;
1700 }
1701 
translate(int ctx)1702 void set_range_node::translate(int ctx)
1703 {
1704     low->translate(ctx);
1705     high->translate(ctx);
1706     if (language_c && short_set && type->tag == tp_enum &&
1707 	((enum_tp*)type->get_typedef())->n_elems <= SHORT_SET_CARD)
1708     {
1709 	token* t = low->l_tkn->next_relevant();
1710 	if (t->tag == TKN_COMMA) t->set_trans("|");
1711 	f_tkn = low->f_tkn->prepend("RANGE(");
1712     } else {
1713 	f_tkn = low->f_tkn->prepend("range(");
1714     }
1715     l_tkn = high->l_tkn->append(")");
1716     dots->set_trans(",");
1717 }
1718 
set_node(token * t_lbr,set_item_node * items,token * t_rbr)1719 set_node::set_node(token* t_lbr, set_item_node* items, token* t_rbr)
1720 : expr_node(tn_set)
1721 {
1722     CONS3(t_lbr, items, t_rbr);
1723 }
1724 
attrib(int)1725 void set_node::attrib(int)
1726 {
1727     for (set_item_node* item = items; item != NULL; item = item->next) {
1728 	item->attrib(ctx_value);
1729     }
1730     type = new set_tp(items ? items->type : &integer_type);
1731 }
1732 
translate(int)1733 void set_node::translate(int)
1734 {
1735     f_tkn = t_lbr;
1736     l_tkn = t_rbr;
1737     for (set_item_node* item = items; item != NULL; item = item->next) {
1738 	item->translate(ctx_value);
1739     }
1740     if (language_c) {
1741 	if (short_set && ((set_tp*)type)->is_short_set()) {
1742 	    if (items) {
1743 		if (items->next != NULL) {
1744 		    t_lbr->set_trans("(");
1745 		    t_rbr->set_trans(")");
1746 		} else {
1747 		    t_lbr->disable();
1748 		    t_rbr->disable();
1749 		}
1750 	    } else {
1751 		t_lbr->set_trans("0");
1752 		t_rbr->disable();
1753 	    }
1754 	    return;
1755 	} else {
1756 	    t_lbr->set_trans("setof(");
1757 	}
1758     } else {
1759 	if (((set_tp*)type)->elem_type->tag == tp_enum) {
1760 	    assert(((set_tp*)type)->elem_type->name != NULL);
1761 	    t_lbr->set_trans(dprintf("set_of_enum(%s)::of(",
1762 				     ((set_tp*)type)->elem_type->name));
1763 	} else {
1764 	    t_lbr->set_trans("set::of(");
1765 	}
1766     }
1767     t_rbr->set_trans(items ? (char *) ", eos)" : (char *) "eos)");
1768 }
1769 
idx_expr_node(expr_node * arr,token * t_lbr,expr_node * indices,token * t_rbr)1770 idx_expr_node::idx_expr_node(expr_node* arr, token* t_lbr, expr_node* indices,
1771 		             token* t_rbr)
1772 : expr_node(tn_index)
1773 {
1774     CONS4(arr, t_lbr, indices, t_rbr);
1775 }
1776 
attrib(int ctx)1777 void idx_expr_node::attrib(int ctx)
1778 {
1779     arr->attrib(ctx == ctx_lvalue ? ctx_lvalarray : ctx_array);
1780     type = arr->type;
1781 
1782     for(expr_node* e = indices; e != NULL; e = e->next) {
1783         if (type && type->is_array()) {
1784 	    type = ((array_tp*)type->get_typedef())->elem_type;
1785 	}
1786         e->attrib(ctx_value);
1787     }
1788 }
1789 
translate(int ctx)1790 void idx_expr_node::translate(int ctx)
1791 {
1792     arr->translate(ctx == ctx_lvalue ? ctx_lvalarray : ctx_array);
1793     f_tkn = arr->f_tkn;
1794     l_tkn = t_rbr;
1795 
1796     array_tp* arr_type = arr->type ? (array_tp*)arr->type->get_typedef()
1797 	                           : (array_tp*)NULL;
1798 
1799     for (expr_node* e = indices; e != NULL; e = e->next) {
1800         e->translate(ctx_value);
1801 	token *next = e->l_tkn->next_relevant();
1802 
1803 	if (arr_type == NULL || !arr_type->is_array()) {
1804 	    warning(e->f_tkn, "applying index operator to expression of non-array type");
1805 	}
1806 	if (language_c && arr_type && arr_type->is_array()) {
1807 	    if (arr_type->base != 0 && !no_index_decrement) {
1808 		if (arr_type->base != -1 && e->tag == tn_add
1809 		    && ((op_node*)e)->right->is_const_literal())
1810 		{
1811 		    int val = ((op_node*)e)->right->value - arr_type->base;
1812 		    if (val == 0) {
1813 			token::disable(((op_node*)e)->left->l_tkn->next,
1814 				       ((op_node*)e)->right->l_tkn);
1815 		    } else {
1816 			((op_node*)e)->right->f_tkn->set_trans(dprintf("%d", val));
1817 		    }
1818 		}
1819 		else if (arr_type->base != -1 && e->tag == tn_sub
1820 			   && ((op_node*)e)->right->is_const_literal())
1821 		{
1822 		    ((op_node*)e)->right->f_tkn->set_trans(dprintf("%d",
1823 		         ((op_node*)e)->right->value + arr_type->base));
1824 		}
1825 		else if (arr_type->base != -1
1826 			   && (e->tag == tn_add || e->tag == tn_sub)
1827 			   && ((op_node*)e)->left->is_const_literal())
1828 		{
1829 		    ((op_node*)e)->left->f_tkn->set_trans(dprintf("%d",
1830 			((op_node*)e)->left->value - arr_type->base));
1831 		}
1832 		else if (arr_type->base != -1 && e->is_const_literal())
1833 		{
1834 		    e->f_tkn->set_trans(dprintf("%d", e->value - arr_type->base));
1835 		}
1836 		else if (arr_type->low)
1837 		{
1838 		    e->l_tkn->append(dprintf(" - %s", arr_type->low));
1839 		}
1840 		else
1841 		{
1842 		    assert(arr_type->low_expr != NULL);
1843 		    token* next = e->l_tkn->next;
1844 		    next->prepend("-(");
1845 		    next->copy(arr_type->low_expr->f_tkn,
1846 			       arr_type->low_expr->l_tkn);
1847 		    next->prepend(")");
1848 		    e->l_tkn = next->prev;
1849 		}
1850 	    }
1851 	    if (arr_type->elem_type->tag == tp_dynarray) {
1852 		if (arr->tag == tn_index
1853 		    && t_lbr != ((idx_expr_node*)arr)->t_lbr)
1854 		{
1855 		    t_lbr->disable();
1856 		    t_lbr = ((idx_expr_node*)arr)->t_lbr;
1857 		}
1858 		if (t_lbr->next_relevant() != e->l_tkn) {
1859 		    t_lbr->append("(");
1860 		    e->l_tkn->append(")");
1861 		}
1862 		if (e->l_tkn->next != next) {
1863 		    token::disable(e->l_tkn->next, next->prev);
1864 		}
1865 		next->set_trans(dprintf("*(%s-%s+1) + ",
1866 					arr_type->high, arr_type->low));
1867 		arr_type = (array_tp*)arr_type->elem_type->get_typedef();
1868 		continue;
1869 	    } else if (arr_type->tag == tp_dynarray
1870 		       && arr->tag == tn_index
1871 		       && t_lbr != ((idx_expr_node*)arr)->t_lbr)
1872 	    {
1873 		    t_lbr->disable();
1874 		    t_lbr = ((idx_expr_node*)arr)->t_lbr;
1875 	    }
1876 
1877 	} else if (arr_type && arr_type->tag == tp_string) {
1878 	    e->l_tkn->append("-1");
1879 	}
1880 
1881 	if (arr_type && arr_type->is_array() && arr_type->elem_type->is_array()) {
1882 	    arr_type = (array_tp*)arr_type->elem_type->get_typedef();
1883 	}
1884 	if (e->next != NULL) {
1885 	    assert(next->tag == TKN_COMMA);
1886 
1887 	    token::disable(e->l_tkn->next, next->next_relevant()->prev);
1888 	    e->l_tkn->append("][");
1889 	}
1890     }
1891 }
1892 
deref_expr_node(expr_node * ptr,token * op)1893 deref_expr_node::deref_expr_node(expr_node* ptr, token* op)
1894 : expr_node(tn_deref)
1895 {
1896     CONS2(ptr, op);
1897 }
1898 
attrib(int)1899 void deref_expr_node::attrib(int)
1900 {
1901     ptr->attrib(ctx_array);
1902     type = ptr->type;
1903     if (type->is_reference()) {
1904 	type = ((ref_tp*)type->get_typedef())->base_type;
1905     } else {
1906 	warning(op, "dereferencing not pointer type");
1907     }
1908 }
1909 
translate(int ctx)1910 void deref_expr_node::translate(int ctx)
1911 {
1912     ptr->translate(ctx_array);
1913     f_tkn = ptr->f_tkn;
1914     l_tkn = op;
1915     op->disable();
1916     if (ptr->type != NULL && (ptr->type->tag == tp_file || ptr->type->tag == tp_text)) {
1917         tag = tn_filevar;
1918 	if (ctx != ctx_lvalue) {
1919 	    if (language_c) {
1920 		ptr->l_tkn->append(")");
1921 		if (ctx == ctx_access) {
1922 		    f_tkn = f_tkn->prepend("currec(");
1923 		    tag = tn_address;
1924 		} else {
1925 		    if (ctx == ctx_array) {
1926 			f_tkn = f_tkn->prepend("(*currec(");
1927 			ptr->l_tkn->append(")");
1928 		    } else {
1929 			f_tkn = f_tkn->prepend("*currec(");
1930 		    }
1931 		}
1932 	    } else { //language C++
1933 		f_tkn = f_tkn->prepend("*");
1934 		if (ctx == ctx_array || ctx == ctx_access) {
1935 		    f_tkn = f_tkn->prepend("(");
1936 		    ptr->l_tkn->append(")");
1937 		}
1938 	    }
1939 	}
1940     } else {
1941 	if (ctx != ctx_access) {
1942 	    if (type && type->tag != tp_void) { // not Turbo Pascal pointer type
1943 		f_tkn = f_tkn->prepend("*");
1944 		if (ctx == ctx_array || ctx == ctx_lvalarray) {
1945 		    f_tkn = f_tkn->prepend("(");
1946 		    ptr->l_tkn->append(")");
1947 		}
1948 	    }
1949 	} else {
1950 	    tag = tn_address;
1951 	}
1952 	op->disable();
1953     }
1954 }
1955 
1956 
1957 
access_expr_node(expr_node * rec,token * pnt,token * field)1958 access_expr_node::access_expr_node(expr_node* rec, token* pnt, token* field)
1959   : expr_node(tn_access)
1960 {
1961     CONS3(rec, pnt, field);
1962 }
1963 
attrib(int)1964 void access_expr_node::attrib(int)
1965 {
1966     rec->attrib(ctx_access);
1967     if (rec->type != NULL && (rec->type->tag == tp_record || rec->type->tag == tp_object || rec->type->tag == tp_unit)) {
1968         recfld = ((record_tp*)rec->type->get_typedef())->search(field);
1969 	if (recfld == NULL) {
1970 	    warning(field, "component not found");
1971 	}
1972     } else {
1973 	warning(field, "unknown record type");
1974 	recfld = NULL;
1975     }
1976     if (recfld == NULL) {
1977 	type = &void_type;
1978     } else {
1979 	type = recfld->type;
1980     }
1981 }
1982 
translate(int ctx)1983 void access_expr_node::translate(int ctx)
1984 {
1985     rec->translate(ctx_access);
1986     f_tkn = rec->f_tkn;
1987     l_tkn = field;
1988     if (rec->tag == tn_address || rec->tag == tn_self) {
1989        pnt->set_trans("->");
1990     } else if (rec->type != NULL && rec->type->tag == tp_unit) {
1991        pnt->set_trans("::");
1992     }
1993     if (recfld) recfld->translate(field);
1994     if (turbo_pascal
1995 	&& rec->type != NULL
1996 	&& (rec->type->tag == tp_object || rec->type->tag == tp_unit)
1997 	&& type->tag == tp_proc && ctx != ctx_apply)
1998     {
1999 	l_tkn = l_tkn->append("()");
2000     }
2001 }
2002 
2003 //---------------------------------------------------------
2004 
address_node(token * t_adr,expr_node * var)2005 address_node::address_node(token* t_adr, expr_node* var)
2006 : expr_node(tn_ref)
2007 {
2008     CONS2(t_adr, var);
2009 }
2010 
attrib(int)2011 void address_node::attrib(int)
2012 {
2013     var->attrib(ctx_lvalue);
2014     type = new ref_tp(var->type);
2015 }
2016 
translate(int)2017 void address_node::translate(int)
2018 {
2019 	f_tkn = t_adr;
2020     if (turbo_pascal && var->tag == tn_self) {
2021        ((atom_expr_node*)var)->tkn->remove();
2022        l_tkn = f_tkn;
2023 	   f_tkn->set_trans("this");
2024     } else {
2025 	   var->translate(ctx_lvalue);
2026        t_adr->set_trans("&");
2027        l_tkn = var->l_tkn;
2028     }
2029 }
2030 
2031 //---------------------------------------------------------
2032 
attrib(int ctx)2033 void case_range_node::attrib(int ctx)
2034 {
2035     from->attrib(ctx);
2036     to->attrib(ctx);
2037     type = from->type;
2038 }
2039 
translate(int ctx)2040 void case_range_node::translate(int ctx)
2041 {
2042     from->translate(ctx);
2043     to->translate(ctx);
2044     if ((from->tag == tn_char || from->tag == tn_intnum) &&
2045 	(to->tag == tn_char || to->tag == tn_intnum))
2046     {
2047 	int range = to->value - from->value + 1;
2048 	if (range > 1 && (range <= 16 || range == 26 || range == 32))
2049 	{
2050 	    f_tkn = from->f_tkn->prepend(dprintf("RANGE_%d(", range));
2051 	    l_tkn = to->l_tkn->append(")");
2052 	    t_range->set_trans(",");
2053 	    return;
2054 	}
2055     }
2056     warning(t_range,"Conversion of case range item is correct only for GCC\n");
2057     t_range->set_trans(" ... ");
2058     f_tkn = from->f_tkn;
2059     l_tkn = to->l_tkn;
2060 }
2061 
case_range_node(expr_node * from,token * t_range,expr_node * to)2062 case_range_node::case_range_node(expr_node* from, token* t_range, expr_node*to)
2063 : expr_node(tn_case_range)
2064 {
2065     CONS3(from, t_range, to);
2066 }
2067 
2068 //----------------------------------------------------------
2069 
op_node(int tag,expr_node * left,token * op,expr_node * right)2070 op_node::op_node(int tag, expr_node* left, token* op, expr_node* right)
2071 : expr_node(tag)
2072 {
2073     CONS3(left, op, right);
2074 }
2075 
2076 
attrib(int)2077 void op_node::attrib(int)
2078 {
2079     if (left) {
2080 	left->parent_tag = tag;
2081         left->attrib(ctx_value);
2082 	type = left->type;
2083     }
2084     if (right) {
2085 	right->parent_tag = tag;
2086         right->attrib(ctx_value);
2087 	type = right->type;
2088     }
2089     if ((unsigned(tag - tn_add) <= tn_div - tn_add) &&
2090 	((left->type && left->type->get_typedef() == &longint_type)
2091 	 || (right->type && right->type->get_typedef() == &longint_type)))
2092     {
2093 	type = &longint_type;
2094     }
2095     if ((left == NULL || (left->flags & tn_is_const)) &&
2096 	(right == NULL || (right->flags & tn_is_const)))
2097     {
2098 	switch (tag) {
2099 	  case tn_add:
2100 	    value = left->value + right->value;
2101 	    flags |= tn_is_const;
2102 	    break;
2103 	  case tn_sub:
2104 	    value = left->value - right->value;
2105 	    flags |= tn_is_const;
2106 	    break;
2107 	  case tn_plus:
2108 	    value = + right->value;
2109 	    flags |= tn_is_const | (right->flags & tn_is_literal);
2110 	    break;
2111 	  case tn_minus:
2112 	    value = - right->value;
2113 	    flags |= tn_is_const | (right->flags & tn_is_literal);
2114 	    break;
2115 	  case tn_mod:
2116 	    value = left->value % right->value;
2117 	    flags |= tn_is_const;
2118 	    break;
2119 	  case tn_mul:
2120 	    value = left->value * right->value;
2121 	    flags |= tn_is_const;
2122 	    break;
2123 	  case tn_div:
2124 	    value = left->value / right->value;
2125 	    flags |= tn_is_const;
2126 	    break;
2127 	}
2128     }
2129 
2130     if (tag == tn_divr) {
2131         type = &real_type;
2132     } else if (tag >= tn_in && tag <= tn_le) {
2133         type = &bool_type;
2134     } else if (left && right && right->type && right->type->tag == tp_set
2135 	       && left->type && left->type->tag == tp_set)
2136     {
2137 	set_tp* ltype = (set_tp*)left->type->get_typedef();
2138 	set_tp* rtype = (set_tp*)right->type->get_typedef();
2139 	type = (ltype->card() < rtype->card()) ? ltype : rtype;
2140     } else if (left && right && left->type && right->type &&
2141 	       (left->type->tag == tp_real || right->type->tag == tp_real))
2142     {
2143         type = &real_type;
2144     } else if (left && right && left->type && right->type &&
2145 	       (right->type->tag == tp_string || right->type->tag == tp_char))
2146     {
2147         type = &varying_string_type;
2148     }
2149 }
2150 
2151 static char* cmp_op[] = { "==", "!=", ">", ">=", "<", "<=" };
2152 static char* rcmp_op[] = { "==", "!=", "<", "<=", ">", ">=" };
2153 
2154 #define CMP_OP(c) cmp_op[(c)-tn_eq]
2155 #define RCMP_OP(c) rcmp_op[(c)-tn_eq]
2156 
translate(int)2157 void op_node::translate(int)
2158 {
2159     f_tkn = l_tkn = op;
2160 
2161     if (right && left && right->type && left->type && right->type->tag == tp_set) {
2162 	if (left->type->tag == tp_set) {
2163 	    set_tp* ltype = (set_tp*)left->type->get_typedef();
2164 	    set_tp* rtype = (set_tp*)right->type->get_typedef();
2165 	    left->type = right->type =
2166 		(ltype->card() < rtype->card()) ? ltype : rtype;
2167 	} else {
2168 	    right->type = new set_tp(left->type);
2169 	}
2170     }
2171 
2172     if (left) {
2173 	left->translate(ctx_value);
2174 	f_tkn = left->f_tkn;
2175     }
2176     if (right) {
2177         right->translate(ctx_value);
2178 	l_tkn = right->l_tkn;
2179     }
2180     switch(tag) {
2181       case tn_mod:
2182         op->set_trans("%");
2183         break;
2184       case tn_div:
2185         op->set_trans("/");
2186         break;
2187       case tn_divr:
2188         op->set_trans("/");
2189 	if (left->type && left->type->tag != tp_real &&
2190 	    right->type && right->type->tag != tp_real)
2191         {
2192 	    f_tkn = left->f_tkn->prepend("(real)(");
2193 	    left->l_tkn->append(")");
2194 	}
2195         break;
2196       case tn_and:
2197         op->set_trans(((left->type && left->type->tag != tp_bool) ||
2198 	    (right->type && right->type->tag != tp_bool) || nological)
2199 		      ? (char *) "&" : (char *) "&&");
2200 	if (parent_tag != tn_group && parent_tag != tn_and) {
2201 	    f_tkn = left->f_tkn->prepend("(");
2202 	    l_tkn = right->l_tkn->append(")");
2203 	}
2204 	break;
2205       case tn_xor:
2206         op->set_trans("^");
2207 	if (parent_tag != tn_group && parent_tag != tn_xor) {
2208 	    f_tkn = left->f_tkn->prepend("(");
2209 	    l_tkn = right->l_tkn->append(")");
2210 	}
2211 	break;
2212       case tn_let:
2213 	op->set_trans("=");
2214 	break;
2215       case tn_shr:
2216 	if (parent_tag != tn_group) {
2217 	    f_tkn = left->f_tkn->prepend(left->type &&
2218 			left->type->get_typedef() == &longint_type
2219 			    ? (char *) "((unsigned long)" : (char *) "((cardinal)");
2220 	    l_tkn = right->l_tkn->append(")");
2221 	} else {
2222 	    f_tkn = left->f_tkn->prepend(left->type &&
2223 			left->type->get_typedef() == &longint_type
2224 			    ? (char *) "(unsigned long)" : (char *) "(cardinal)");
2225 	}
2226 	op->set_trans(">>");
2227 	break;
2228       case tn_shl:
2229 	if (parent_tag != tn_group) {
2230 	    f_tkn = left->f_tkn->prepend("(");
2231 	    l_tkn = right->l_tkn->append(")");
2232 	}
2233 	op->set_trans("<<");
2234 	break;
2235       case tn_or:
2236 	if (parent_tag != tn_group && parent_tag != tn_or) {
2237 	    f_tkn = left->f_tkn->prepend("(");
2238 	    l_tkn = right->l_tkn->append(")");
2239 	}
2240 	op->set_trans(((left->type && left->type->tag != tp_bool) ||
2241 		       (right->type && right->type->tag != tp_bool) ||
2242 		       nological) ? (char *) "|" : (char *) "||");
2243         break;
2244       case tn_in:
2245         token::disable(left->l_tkn->next, right->f_tkn->prev);
2246 	if (language_c) {
2247             f_tkn = left->f_tkn->prepend(
2248 		        short_set && ((set_tp*)right->type)->is_short_set()
2249                         ? (char *) "INSET(" : (char *) "inset(");
2250 	    left->l_tkn->append(", ");
2251 	    l_tkn = right->l_tkn->append(")");
2252 	} else {
2253 	    left->f_tkn->move(right->f_tkn, right->l_tkn);
2254 	    if (right->tag==tn_add || right->tag==tn_sub || right->tag==tn_mul){
2255 		f_tkn = right->f_tkn->prepend("(");
2256 		right->l_tkn->append(")");
2257 	    } else {
2258 		f_tkn = right->f_tkn;
2259 	    }
2260 	    left->f_tkn->prepend(".has(");
2261 	    l_tkn = left->l_tkn->append(")");
2262 	}
2263         break;
2264       case tn_add:
2265       case tn_sub:
2266       case tn_mul:
2267         if (left->type && left->type->tag == tp_set) {
2268 	    if (language_c) {
2269 		if (short_set && ((set_tp*)type)->is_short_set()) {
2270 		    f_tkn = left->f_tkn->prepend(tag == tn_add
2271 						 ? (char *) "JOIN(" : tag == tn_sub
2272 						 ? (char *) "DIFFERENCE("
2273 						 : (char *) "INTERSECT(");
2274 		} else {
2275 		    f_tkn = left->f_tkn->prepend(tag == tn_add
2276 						 ? (char *) "join(" : tag == tn_sub
2277 						 ? (char *) "difference("
2278 						 : (char *) "intersect(");
2279 		}
2280 		l_tkn = right->l_tkn->append(")");
2281 		token::disable(left->l_tkn->next, right->f_tkn->prev);
2282 		left->l_tkn->append(", ");
2283 	    }
2284 	} else if (!language_c) {
2285 	    if (left->type
2286 		&& (left->type->tag == tp_string || left->type->tag == tp_char))
2287 	    {
2288 		f_tkn = left->f_tkn->prepend("string(");
2289 		left->l_tkn->append(")");
2290 	    }
2291 	}
2292 	break;
2293       case tn_eq:
2294       case tn_ne:
2295       case tn_gt:
2296       case tn_ge:
2297       case tn_lt:
2298       case tn_le:
2299 	if (unsigned_comparison && left->type && right->type &&
2300 	    (left->type->tag == tp_range || right->type->tag == tp_range ||
2301 	     left->type->tag == tp_enum || right->type->tag == tp_enum))
2302         {
2303 	    range_tp* ltype = (range_tp*)left->type->get_typedef();
2304 	    range_tp* rtype = (range_tp*)right->type->get_typedef();
2305 
2306 	    if (((ltype->tag == tp_range && ltype->min_value >= 0) ||
2307 		 ltype->tag == tp_enum) &&
2308 		((rtype->tag == tp_range && rtype->min_value < 0) ||
2309 		 (rtype->tag == tp_integer && !(right->flags & tn_is_const))))
2310 	    {
2311 		if (rtype->tag == tp_integer) {
2312 		    right->f_tkn->prepend("(cardinal)");
2313 		}
2314 		else if (ltype->tag == tp_enum || rtype->size <= ltype->size)
2315 		{
2316 		    right->f_tkn->prepend(rtype->size == 1 ? (char *) "(unsigned char)":
2317 					  rtype->size == 2 ? (char *) "(unsigned short)"
2318 					  : (char *) "(unsigned)");
2319 		}
2320 	    } else if (((rtype->tag == tp_range && rtype->min_value >= 0) ||
2321 			rtype->tag == tp_enum) &&
2322 		       ((ltype->tag == tp_range && ltype->min_value < 0) ||
2323 			(ltype->tag == tp_integer && !(left->flags & tn_is_const))))
2324 	    {
2325 		if (ltype->tag == tp_integer) {
2326 		    f_tkn = left->f_tkn->prepend("(cardinal)");
2327 		}
2328                 else if (rtype->tag == tp_enum || ltype->size <= rtype->size)
2329 		{
2330 		    f_tkn = left->f_tkn->prepend(
2331 					  ltype->size == 1 ? (char *) "(unsigned char)":
2332 					  ltype->size == 2 ? (char *) "(unsigned short)"
2333 					  : (char *) "(unsigned)");
2334 		}
2335 	    }
2336 	}
2337 	if (language_c && left->type && right->type) {
2338 	    switch(left->type->tag) {
2339 	      case tp_string:
2340 	      case tp_record:
2341 	      case tp_array:
2342 	      case tp_dynarray:
2343 		if (right->type->tag == tp_char) {
2344 		    f_tkn = left->f_tkn->prepend("*");
2345 		} else {
2346 		    token::disable(left->l_tkn->next, right->f_tkn->prev);
2347 		    left->l_tkn->append(", ");
2348 		    if (left->is_parameter()) {
2349 			f_tkn = left->f_tkn->prepend("memcmp(");
2350 			if (left->type->tag == tp_record) {
2351 			    left->f_tkn->prepend("&");
2352 			    right->f_tkn->prepend("&");
2353 			}
2354 			if (left->type->name != NULL) {
2355 			    l_tkn = right->l_tkn->append(
2356 					   dprintf(", sizeof(%s)) %s 0",
2357 					       left->type->name, CMP_OP(tag)));
2358 			} else {
2359 			    l_tkn = right->l_tkn->append(", ")
2360 				                ->append("*sizeof(*");
2361 			    ((array_tp*)left->type->get_typedef())->
2362 				insert_length(l_tkn);
2363 			    l_tkn = l_tkn->append(dprintf(")) %s 0",
2364 							  CMP_OP(tag)));
2365 			    l_tkn->copy(left->f_tkn, left->l_tkn);
2366 			}
2367 		    } else if (left->type->tag == tp_string) {
2368 			token::swap(left->f_tkn, left->l_tkn,
2369 				    right->f_tkn, right->l_tkn);
2370 			f_tkn = right->f_tkn->prepend("arrcmp(");
2371 			l_tkn = left->l_tkn->append(dprintf(") %s 0",
2372 							    RCMP_OP(tag)));
2373 		    } else {
2374 			if (left->type->tag == tp_record) {
2375 			    f_tkn = left->f_tkn->prepend("reccmp(");
2376 			} else {
2377 			    f_tkn = left->f_tkn->prepend("arrcmp(");
2378 			}
2379 			l_tkn = right->l_tkn->append(dprintf(") %s 0",
2380 							     CMP_OP(tag)));
2381 		    }
2382 		    return;
2383 		}
2384 	      case tp_char:
2385 		if (right->type && right->type->is_array()) {
2386 		    right->f_tkn->prepend("*");
2387 		}
2388 		break;
2389 	      case tp_set:
2390 		token::disable(left->l_tkn->next, right->f_tkn->prev);
2391 		left->l_tkn->append(", ");
2392 
2393 		if (short_set && left->type && ((set_tp*)left->type)->is_short_set()) {
2394 		    switch (tag) {
2395 		      case tn_eq:
2396 			f_tkn = left->f_tkn->prepend("EQUIVALENT(");
2397 			l_tkn = right->l_tkn->append(")");
2398 			break;
2399 		      case tn_ne:
2400 			f_tkn = left->f_tkn->prepend("!EQUIVALENT(");
2401 			l_tkn = right->l_tkn->append(")");
2402 			break;
2403 		      case tn_le:
2404 			f_tkn = left->f_tkn->prepend("SUBSET(");
2405 			l_tkn = right->l_tkn->append(")");
2406 			break;
2407 		      case tn_ge:
2408 			token::swap(left->f_tkn, left->l_tkn,
2409 				    right->f_tkn, right->l_tkn);
2410 			f_tkn = right->f_tkn->prepend("SUBSET(");
2411 			l_tkn = left->l_tkn->append(")");
2412 			break;
2413 		    }
2414 		} else {
2415 		    switch (tag) {
2416 		      case tn_eq:
2417 			f_tkn = left->f_tkn->prepend("equivalent(");
2418 			l_tkn = right->l_tkn->append(")");
2419 			break;
2420 		      case tn_ne:
2421 			f_tkn = left->f_tkn->prepend("!equivalent(");
2422 			l_tkn = right->l_tkn->append(")");
2423 			break;
2424 		      case tn_le:
2425 			f_tkn = left->f_tkn->prepend("subset(");
2426 			l_tkn = right->l_tkn->append(")");
2427 			break;
2428 		      case tn_ge:
2429 			token::swap(left->f_tkn, left->l_tkn,
2430 				    right->f_tkn, right->l_tkn);
2431 			f_tkn = right->f_tkn->prepend("subset(");
2432 			l_tkn = left->l_tkn->append(")");
2433 			break;
2434 		    }
2435 		}
2436 		return;
2437 	    }
2438 	} else { // language C++
2439 	    if (left->type && right->type
2440 		&& (right->type->tag == tp_array
2441 		 || right->type->tag == tp_varying_string
2442 		 || right->type->tag == tp_dynarray)
2443 		&& (left->type->tag == tp_string
2444 		    || left->type->tag == tp_char))
2445 	    {
2446 		token::swap(left->f_tkn, left->l_tkn,
2447 			    right->f_tkn, right->l_tkn);
2448 		f_tkn = right->f_tkn;
2449 		l_tkn = left->l_tkn;
2450 		op->set_trans(RCMP_OP(tag));
2451 		return;
2452 	    }
2453 	}
2454 	op->set_trans(CMP_OP(tag));
2455         break;
2456       case tn_not:
2457         op->set_trans(right->type && right->type->tag == tp_bool ? (char *) "!" : (char *) "~");
2458         break;
2459     }
2460     if ((unsigned(tag - tn_add) <= tn_div - tn_add) && type && type->tag == tp_longint)
2461     {
2462 	if (left->type && left->type->tag != tp_longint) {
2463 	    f_tkn = f_tkn->prepend("longint(");
2464 	    left->l_tkn->append(")");
2465 	} else if (right->type && right->type->tag != tp_longint) {
2466 	    right->f_tkn->prepend("longint(");
2467 	    l_tkn = l_tkn->append(")");
2468 	}
2469     }
2470 }
2471 
fcall_node(expr_node * fptr,token * lpar,expr_node * args,token * rpar)2472 fcall_node::fcall_node(expr_node* fptr, token* lpar, expr_node* args,
2473 		       token* rpar)
2474 : expr_node(tn_fcall)
2475 {
2476     CONS4(fptr, lpar, args, rpar);
2477 }
2478 
attrib(int ctx)2479 void fcall_node::attrib(int ctx)
2480 {
2481     if (fptr->tag == tn_atom && ((atom_expr_node*)fptr)->tkn->tag != TKN_IDENT)
2482     {
2483 	if (args) {
2484 	    args->attrib(ctx_value);
2485 	}
2486         switch (((atom_expr_node*)fptr)->tkn->tag) {
2487 	  case TKN_NEW:
2488 	    type = new ref_tp(args->type);
2489 	    if (turbo_pascal && args->next != NULL) {
2490 		if (args->type->is_reference()) {
2491 		    tpexpr* bt =
2492 			((ref_tp*)args->type->get_typedef())->base_type;
2493 		    if (bt->tag == tp_object) {
2494 			b_ring::push((object_tp*)bt->get_typedef());
2495 			args->next->attrib(ctx_value);
2496 			b_ring::pop();
2497 		    }
2498 		}
2499 	    }
2500 	    break;
2501 	  case TKN_DISPOSE:
2502 	    if (turbo_pascal && args->next != NULL) {
2503 		if (args->type->is_reference()) {
2504 		    tpexpr* bt =
2505 			((ref_tp*)args->type->get_typedef())->base_type;
2506 		    if (bt->tag == tp_object) {
2507 			b_ring::push((object_tp*)bt->get_typedef());
2508 			args->next->attrib(ctx_value);
2509 			b_ring::pop();
2510 		    }
2511 		}
2512 	    }
2513 	    break;
2514 	  case TKN_REF:
2515 	    type = new ref_tp(args->type);
2516 	    break;
2517 	  case TKN_PRED:
2518 	    type = args->type;
2519 	    if (args->flags & symbol::f_const) {
2520 		flags |= tn_is_const;
2521 		value = args->value - 1;
2522 	    }
2523 	    break;
2524 	  case TKN_SUCC:
2525 	    type = args->type;
2526 	    if (args->flags & symbol::f_const) {
2527 		flags |= tn_is_const;
2528 		value = args->value + 1;
2529 	    }
2530 	    break;
2531 	  case TKN_HALT:
2532 	    if (turbo_pascal) {
2533 		((atom_expr_node*)fptr)->tkn->set_trans("exit");
2534 	    } else {
2535 		goto normal_call;
2536 	    }
2537 	    //nobreak;
2538 	  default:
2539 	    if (args != NULL) {
2540 		for (expr_node* expr=args->next; expr != NULL; expr=expr->next)
2541 		{
2542 		    expr->attrib(ctx_value);
2543 		}
2544 	    }
2545 	}
2546 	return;
2547     }
2548   normal_call:
2549     fptr->attrib(ctx_apply);
2550     if (fptr->type != NULL) {
2551 	if (fptr->type->tag == tp_proc) {
2552 	    proc_tp* prc = (proc_tp*)fptr->type->get_typedef();
2553 	    type = prc->res_type;
2554 	    param_spec* p = prc->params;
2555 	    prc->add_caller(curr_proc);
2556 
2557 	    for (expr_node* e = args; e != NULL; e = e->next) {
2558 		if (p != NULL) {
2559 		    e->attrib(p->var->type->tag == tp_proc
2560 			      ? ctx_procptr : (p->var->flags & symbol::f_var_param)
2561 			      ? ctx_lvalue : ctx_value);
2562 		    if (p->var->type->tag == tp_set) {
2563 			e->type = p->var->type->get_typedef();
2564 		    }
2565 		    p = p->next;
2566 		} else {
2567 		    e->attrib(ctx_value);
2568 		}
2569 	    }
2570 	    if (language_c && type != NULL && type->tag == tp_array
2571 		&& ctx != ctx_rvalue)
2572 	    {
2573 		temp = curr_proc->add_temp(type);
2574 	    }
2575 	} else { // constant array or record constructor
2576 
2577 	    type = fptr->type;
2578 	    int expr_ctx = (type->tag == tp_record || type->tag == tp_object
2579 			    || (type->tag == tp_array
2580 				&& (ctx == ctx_constant || language_c)))
2581 		? ctx_record : ctx_value;
2582 
2583 	    if (type->tag != tp_array && type->tag != tp_record && type->tag != tp_object
2584 		&& !(fptr->tag == tn_atom
2585 		     && ((atom_expr_node*)fptr)->var != NULL
2586 		     && ((atom_expr_node*)fptr)->var->tag == symbol::s_type))
2587 	    {
2588 		warning(lpar, "function not defined");
2589 	    }
2590 	    for (expr_node* e = args; e != NULL; e = e->next) {
2591 		e->attrib(expr_ctx);
2592 	    }
2593 	}
2594     }
2595 }
2596 
translate(int ctx)2597 void fcall_node::translate(int ctx)
2598 {
2599     l_tkn = rpar;
2600 
2601     if (fptr->tag == tn_atom && ((atom_expr_node*)fptr)->tkn->tag != TKN_IDENT)
2602     {
2603 	f_tkn = ((atom_expr_node*)fptr)->tkn;
2604 
2605         switch(((atom_expr_node*)fptr)->tkn->tag) {
2606 	  case TKN_NEW:
2607 	    if (language_c) {
2608 		args->translate(ctx_value);
2609 		args->f_tkn->set_pos(f_tkn);
2610 		f_tkn->disable();
2611 		lpar->disable();
2612 		if (args->next != NULL) {
2613 		    token::remove(args->l_tkn->next, rpar->prev);
2614 		}
2615 		if (args->type->is_reference()) {
2616 		    tpexpr* bt=((ref_tp*)args->type->get_typedef())->base_type;
2617 		    assert(bt->name != NULL);
2618 
2619 		    rpar->set_trans(dprintf(" = (%s*)%s(%s))",
2620 				    bt->name,
2621 				    (bt->get_typedef()->flags & tp_need_init)
2622 				    ? "calloc(1,sizeof" : "malloc(sizeof",
2623 				    bt->name));
2624 		}
2625 	    } else {
2626 		expr_node* expr = args;
2627 		if (expr != NULL && expr->tag == tn_fcall
2628 		    && expr->type != NULL && expr->type->tag == tp_object)
2629 		{
2630 		    (((fcall_node*)expr)->fptr)->translate(ctx_apply);
2631 		    expr = ((fcall_node*)expr)->args;
2632 		}
2633 		while (expr != NULL) {
2634 		    expr->translate(ctx_value);
2635 		    expr = expr->next;
2636 		}
2637 		if (turbo_pascal) {
2638 		    if (args->type->is_reference()) {
2639 			tpexpr* cls = ((ref_tp*)args->type->get_typedef())->base_type;
2640 			char* cls_name;
2641 			if (cls != NULL && cls->name != NULL) {
2642 			    cls_name = cls->name;
2643 			} else {
2644 			    cls_name = args->type->name;
2645 			}
2646 			if (ctx == ctx_rvalue) {
2647 			    if (args->next != NULL) {
2648 				token::remove(lpar, args->next->f_tkn->prev);
2649 				f_tkn->set_trans(dprintf("(new %s)->",
2650 							 cls_name));
2651 				rpar->disable();
2652 			    } else {
2653 				token::remove(lpar, rpar);
2654 				l_tkn = f_tkn;
2655 				f_tkn->set_trans(dprintf("new %s", cls_name));
2656 			    }
2657 			} else {
2658 			    args->f_tkn->set_pos(f_tkn);
2659 			    f_tkn->disable();
2660 			    lpar->disable();
2661 			    if (args->next != NULL) {
2662 				token::disable(args->l_tkn->next,
2663 					       args->next->f_tkn->prev);
2664 				args->l_tkn->append(dprintf(" = (new %s)->",
2665 							    cls_name));
2666 				rpar->disable();
2667 			    } else {
2668 				token::disable(args->l_tkn->next, rpar);
2669 				args->l_tkn->append(dprintf(" = new %s",
2670 							    cls_name));
2671 			    }
2672 			}
2673 		    } else {
2674 			lpar->set_trans(" ");
2675 			rpar->disable();
2676 			warning(f_tkn, "Unknown type for new operator\n");
2677 		    }
2678 		} else {
2679 		    args->f_tkn->set_pos(f_tkn);
2680 		    f_tkn->disable();
2681 		    lpar->disable();
2682 		    if (args->next != NULL) {
2683 			token::remove(args->l_tkn->next, rpar->prev);
2684 		    }
2685 		    rpar->set_trans(" = new ");
2686 		    if (args->type->is_reference()) {
2687 			tpexpr* bt=((ref_tp*)args->type->get_typedef())->base_type;
2688 			assert(bt->name != NULL);
2689 			l_tkn = rpar->append(bt->name);
2690 		    }
2691 		}
2692 	    }
2693 	    break;
2694 	  case TKN_DISPOSE:
2695 	    args->translate(ctx_value);
2696 	    if (language_c) {
2697 		f_tkn->set_trans("free");
2698 	    } else {
2699 		f_tkn->set_trans("delete ");
2700 		lpar->disable();
2701 		rpar->disable();
2702 		if (turbo_pascal) {
2703 		    if (args->next) {
2704 			args->next->translate(ctx_value);
2705 			token::remove(args->l_tkn->next, args->next->f_tkn->prev);
2706 			args->l_tkn->append("->");
2707 		    }
2708 		}
2709 	    }
2710 	    break;
2711 	  case TKN_REF:
2712 	    args->translate(ctx_lvalue);
2713 	    f_tkn->set_trans("&");
2714 	    lpar->disable();
2715 	    rpar->disable();
2716 	    break;
2717 	  case TKN_PRED:
2718 	  case TKN_SUCC:
2719 	    assert(args->type->name != NULL);
2720 	    args->translate(ctx_rvalue);
2721 	    lpar->append(dprintf("%s,", args->type->name));
2722 	    break;
2723 	  case TKN_INC:
2724 	    args->translate(ctx_lvalue);
2725 	    token::disable(f_tkn, lpar);
2726 	    args->f_tkn->set_pos(f_tkn);
2727 	    if (args->next) {
2728 		args->next->translate(ctx_rvalue);
2729 		token::disable(args->l_tkn->next, args->next->f_tkn->prev);
2730 		args = args->next;
2731 		args->f_tkn->prepend(" += ");
2732 	    } else {
2733 		args->l_tkn->append(" += 1");
2734 	    }
2735 	    rpar->disable();
2736 	    break;
2737 	  case TKN_DEC:
2738 	    args->translate(ctx_lvalue);
2739 	    args->f_tkn->set_pos(f_tkn);
2740 	    token::disable(f_tkn, lpar);
2741 	    if (args->next) {
2742 		args->next->translate(ctx_rvalue);
2743 		token::disable(args->l_tkn->next, args->next->f_tkn->prev);
2744 		args = args->next;
2745 		args->f_tkn->prepend(" -= ");
2746 	    } else {
2747 		args->l_tkn->append(" -= 1");
2748 	    }
2749 	    rpar->disable();
2750 	    break;
2751 	}
2752 	return;
2753     }
2754 
2755     fptr->translate(ctx_apply);
2756     f_tkn = fptr->f_tkn;
2757     l_tkn = rpar;
2758 
2759     if (fptr->type && fptr->type->tag == tp_proc) {
2760 	proc_tp* prc = (proc_tp*)fptr->type->get_typedef();
2761         param_spec* p = prc->params;
2762 	tpexpr* prev_param_type = NULL;
2763 
2764         for (expr_node* e = args; e != NULL; e = e->next) {
2765 	    if (p != NULL) {
2766                 e->translate(p->var->type->tag == tp_proc ? ctx_procptr
2767 			     : (language_c && p->var->tag == symbol::s_ref)
2768 			     ? ctx_access : ctx_value);
2769 		if (p->var->type->is_array() && e->type != NULL && e->type->tag == tp_char) {
2770 		    if (e->tag == tn_char) {
2771 			char* s = ((string_node*)e)->value_tkn->out_text;
2772 			if (*s == '\'') {
2773 			    *s = '"';
2774 			    s += strlen(s) - 1;
2775 			    *s = '"';
2776 			}
2777 			e->type = &string_type;
2778 		    } else {
2779 			if (!turbo_pascal) {
2780 			    warning(e->f_tkn, "assignment of charater constant to array");
2781 			}
2782 		    }
2783 		}
2784 		if (p->var->type->tag == tp_string) {
2785 		    if (e->type->tag == tp_array || e->type->tag == tp_dynarray)
2786 		    {
2787 			e->f_tkn->prepend("lpsz(");
2788 			if (language_c) {
2789 			    ((array_tp*)e->type->get_typedef())
2790 				->insert_dimensions(e);
2791 			}
2792 			e->l_tkn->append(")");
2793 		    }
2794 		} else if (p->var->type->tag == tp_array
2795 			   && !language_c && prc->is_extern_c
2796 			   && (e->type->tag == tp_array
2797 			       || e->type->tag == tp_dynarray))
2798 		{
2799 		    e->l_tkn->append(".body()");
2800 		} else {
2801 		    if (language_c) {
2802 			if (p->var->type->tag == tp_dynarray) {
2803 			    if (prev_param_type != p->var->type) {
2804 				if (!e->type->is_array())
2805 				{
2806 				    warning(e->f_tkn, "passing non-aray object"
2807 					    " as conformant array parameter");
2808 				} else {
2809 				    // push on stack bounds of array
2810 				    if (e->type->tag == tp_string) {
2811 					e->f_tkn->prepend("array(");
2812 					e->l_tkn->append(")");
2813 				    } else {
2814 					((array_tp*)e->type->get_typedef())->
2815 					    insert_dimensions(e, (array_tp*)
2816 					        p->var->type->get_typedef());
2817 				    }
2818 				}
2819 				prev_param_type = p->var->type;
2820 			    }
2821 			} else if (p->var->tag == symbol::s_ref
2822 				   && e->tag != tn_address)
2823 			{
2824 			    e->f_tkn->prepend("&");
2825 			}
2826 		    } else { // language C++
2827 			if (!prc->is_extern_c
2828 			    && p->var->type->tag == tp_array
2829 			    && e->type->tag == tp_string)
2830 			{
2831 			    if (p->var->type->name == NULL) {
2832 				e->f_tkn->prepend("as_array(");
2833 				e->l_tkn->append(")");
2834 			    } else {
2835 				e->f_tkn->prepend(dprintf("as(%s,",
2836 							  p->var->type->name));
2837 				e->l_tkn->append(")");
2838 			    }
2839 			} else if (p->var->type->tag == tp_any
2840 				   || (p->var->tag == symbol::s_ref
2841 				       && prc->is_extern_c))
2842                         {
2843 			    e->f_tkn->prepend("&");
2844 			}
2845 		    }
2846 		}
2847 		p = p->next;
2848             } else {
2849                 e->translate(ctx_value);
2850             }
2851         }
2852 	if (language_c) {
2853 	    // push default values of skipped parameters
2854 	    while (p != NULL) {
2855 		rpar->prepend(", 0");
2856 		p = p->next;
2857 	    }
2858 	    if (type != NULL && type->tag == tp_array) {
2859 		if (ctx == ctx_rvalue) {
2860 		    f_tkn->set_pos(assign_node::stmt->lval->f_tkn);
2861 		    lpar->append(", ")->move(assign_node::stmt->lval->f_tkn,
2862 					     assign_node::stmt->lval->l_tkn);
2863 		    tag = tn_retarr;
2864 		} else {
2865 		    lpar->append(dprintf("%s, ", temp));
2866 		    f_tkn = f_tkn->prepend("*");
2867 		}
2868 	    }
2869 	}
2870 
2871         token* rest = rpar->prev_relevant();
2872 
2873         for (param_spec* prm = prc->extra_params;
2874 	     prm != NULL;
2875 	     prm = prm->next)
2876         {
2877 	    if (prm->var->flags & symbol::f_static) continue;
2878 
2879 	    rest = rest->append(", ");
2880 	    if (language_c && prm->var->tag != symbol::s_ref
2881 		&& (prm->var->tag != symbol::s_const
2882 		    || !prm->var->type->is_scalar())
2883 		&& prm->var->ring == curr_proc
2884 		&& !prm->var->type->is_array())
2885 	    {
2886 		rest = rest->append("&");
2887 	    }
2888 	    rest = rest->append(prm->var->out_name->text);
2889         }
2890 
2891     } else if (type != NULL && (type->tag == tp_record || type->tag == tp_object
2892 	       || (type->tag == tp_array
2893 		   && (language_c || ctx == ctx_constant))))
2894     {
2895 	if (hp_pascal) {
2896 	    if (language_c) {
2897 		f_tkn = fptr->f_tkn->prepend("(");
2898 		fptr->l_tkn->append("*)");
2899 	    }
2900 	} else {
2901 	    token::remove(fptr->f_tkn, fptr->l_tkn);
2902 	    f_tkn = lpar;
2903 	    if (language_c || type->tag == tp_record || type->tag == tp_object) {
2904 		lpar->set_trans("{");
2905 		rpar->set_trans("}");
2906 	    } else {
2907 		if (args->tag != tn_string || args->next != NULL) {
2908 		    lpar->set_trans("{{");
2909 		    rpar->set_trans("}}");
2910 		}
2911 	    }
2912 	    for (expr_node* e = args; e != NULL; e = e->next) {
2913 		e->translate(ctx_record);
2914 	    }
2915 	    if (ctx != ctx_constant) {
2916 		assert(type->name != NULL);
2917 
2918 		static int n_const;
2919 		token *t = lpar->prev;
2920 		char* const_name = dprintf("%s_const%d", type->name, ++n_const);
2921 
2922 		assert(global_func_decl_level != NULL);
2923 
2924 		global_func_decl_level->move(lpar, rpar);
2925 		lpar->prepend(dprintf("const %s %s = ", type->name, const_name));
2926 		rpar->append(";\n\n");
2927 
2928 		f_tkn = l_tkn = t->append(const_name);
2929 	    }
2930 	}
2931     } else { // undefined function call
2932 	if (fptr->type && fptr->type->tag >= tp_any &&
2933 	    (fptr->type->tag < tp_proc || fptr->type->tag == tp_ref || fptr->type->tag == tp_fwd_ref))
2934 	{
2935 	    // type conversion
2936 	    f_tkn = fptr->f_tkn->prepend("(");
2937 	    fptr->l_tkn->append(")");
2938 	}
2939 	for (expr_node* e = args; e != NULL; e = e->next) {
2940 	    e->translate(ctx_value);
2941 	}
2942 	if (!language_c && type != NULL && type->tag == tp_array) {
2943 	    fptr->l_tkn->append("::make");
2944 	}
2945     }
2946 }
2947 
2948 
skipped_node(token * comma)2949 skipped_node::skipped_node(token* comma) : expr_node(tn_skip)
2950 {
2951     this->comma = comma;
2952 }
2953 
attrib(int)2954 void skipped_node::attrib(int)
2955 {
2956     type = &void_type;
2957 }
2958 
translate(int)2959 void skipped_node::translate(int)
2960 {
2961     l_tkn = f_tkn = comma->append(" 0");
2962 }
2963 
2964 
loophole_node(token * t_loophole,token * t_lpar,tpd_node * tpd,token * t_comma,expr_node * expr,token * t_rpar)2965 loophole_node::loophole_node(token* t_loophole, token* t_lpar, tpd_node* tpd,
2966 			     token* t_comma, expr_node *expr, token* t_rpar)
2967   : expr_node(tn_loophole)
2968 {
2969     CONS6(t_loophole, t_lpar, tpd, t_comma, expr, t_rpar);
2970 }
2971 
attrib(int ctx)2972 void loophole_node::attrib(int ctx)
2973 {
2974     tpd->attrib(ctx);
2975     expr->attrib(ctx_access);
2976     type = tpd->type;
2977 }
2978 
translate(int ctx)2979 void loophole_node::translate(int ctx)
2980 {
2981     f_tkn = t_lpar;
2982     l_tkn = t_rpar;
2983     tpd->translate(ctx);
2984     expr->translate(ctx_access);
2985     t_loophole->disable();
2986     if (expr->tag == tn_address) {
2987 	tpd->l_tkn->append("*)");
2988 	f_tkn = f_tkn->prepend("*");
2989     }
2990     else if (language_c && tpd->type->tag == tp_integer
2991 	    && expr->type->tag == tp_set
2992 	    && (!short_set || !((set_tp*)expr->type->get_typedef())->is_short_set()))
2993     {
2994 	token::disable(t_lpar, tpd->l_tkn);
2995 	expr->l_tkn->append(".setarray[0]");
2996     }
2997     else
2998     {
2999 	tpd->l_tkn->append(")");
3000     }
3001     t_rpar->disable();
3002     t_comma->disable();
3003 }
3004 
3005 
field_init_node(token * t_field,token * t_coln,expr_node * value)3006 field_init_node::field_init_node(token* t_field,token* t_coln,expr_node* value)
3007 {
3008     CONS3(t_field, t_coln, value);
3009     next = NULL;
3010 }
3011 
attrib(tpexpr * record_type)3012 void field_init_node::attrib(tpexpr* record_type)
3013 {
3014     int ctx = ctx_constant;
3015     if (record_type != NULL && record_type->tag != tp_void) {
3016 	symbol* s = ((record_tp*)record_type)->shallow_search(t_field);
3017 	if (s == NULL) {
3018 	    warning(t_field, "Field '%s' is not found in record %s\n",
3019 		    t_field->in_text,
3020 		    record_type->name ? record_type->name : "");
3021 	} else {
3022 	    value->type = s->type;
3023 	    ctx = s->type->tag == tp_record || s->type->tag == tp_object ? ctx_record
3024 		: s->type->is_array() ? ctx_array : ctx_constant;
3025 	}
3026     }
3027     value->attrib(ctx);
3028 }
3029 
translate(int)3030 void field_init_node::translate(int)
3031 {
3032     value->translate(ctx_constant);
3033     f_tkn = value->f_tkn;
3034     l_tkn = value->l_tkn;
3035     token::disable(t_field, f_tkn->prev);
3036     token* sep = l_tkn->next_relevant();
3037     if (sep->tag == TKN_SEMICOLON) {
3038 	sep->set_trans(",");
3039     }
3040 }
3041 
record_constant_node(token * lpar,field_init_node * flist,token * rpar)3042 record_constant_node::record_constant_node(token* lpar, field_init_node* flist,
3043 					   token* rpar)
3044 : expr_node(tn_record_const)
3045 {
3046     CONS3(lpar, flist, rpar);
3047 }
3048 
attrib(int)3049 void record_constant_node::attrib(int)
3050 {
3051     tpexpr* record_type = type;
3052     if (record_type != NULL && (record_type->tag == tp_record || record_type->tag == tp_object)) {
3053 	record_type = record_type->get_typedef();
3054     }
3055     for (field_init_node* val = flist; val != NULL; val = val->next) {
3056 	val->attrib(record_type);
3057     }
3058 }
3059 
translate(int ctx)3060 void record_constant_node::translate(int ctx)
3061 {
3062     f_tkn = lpar;
3063     l_tkn = rpar;
3064     lpar->set_trans("{");
3065     rpar->set_trans("}");
3066     for (field_init_node* val = flist; val != NULL; val = val->next) {
3067 	val->translate(ctx);
3068     }
3069 }
3070 
3071 
expr_group_node(token * lpar,expr_node * expr,token * rpar)3072 expr_group_node::expr_group_node(token* lpar, expr_node* expr, token* rpar)
3073 : expr_node(tn_group)
3074 {
3075     CONS3(lpar, expr, rpar);
3076 }
3077 
aggregate_constant(expr_node * expr,symbol * component)3078 static expr_node* aggregate_constant(expr_node* expr, symbol* component)
3079 {
3080     if (component != NULL) {
3081 	if (component->next != NULL) {
3082 	    expr = aggregate_constant(expr, component->next);
3083 	}
3084     }
3085     if (expr != NULL) {
3086 	int ctx = ctx_constant;
3087 	if (component != NULL && component->type != NULL) {
3088 	    expr->type = component->type;
3089 	    ctx = component->type->tag == tp_record || component->type->tag == tp_object ? ctx_record
3090 		: component->type->is_array() ? ctx_array : ctx_constant;
3091 	}
3092 	expr->attrib(ctx);
3093 	return expr->next;
3094     }
3095     return NULL;
3096 }
3097 
attrib(int ctx)3098 void expr_group_node::attrib(int ctx)
3099 {
3100     this->ctx = ctx;
3101     if (type != NULL) {
3102 	if (type->tag == tp_record || type->tag == tp_object) {
3103 	    for (expr_node* e = aggregate_constant(expr,
3104 				    ((record_tp*)type->get_typedef())->syms);
3105 		 e != NULL;
3106 		 e = e->next)
3107 	    {
3108 		e->attrib(ctx_constant);
3109 	    }
3110 	    return;
3111 	} else if (type->is_array()) {
3112 	    tpexpr* elem_type = ((array_tp*)type->get_typedef())->elem_type;
3113 	    ctx = (elem_type->tag == tp_record || elem_type->tag == tp_object) ? ctx_record
3114 		: (elem_type->is_array()) ? ctx_array : ctx_constant;
3115 	    for(expr_node* e = expr; e != NULL; e = e->next) {
3116 		e->type = elem_type;
3117 		e->attrib(ctx);
3118 	    }
3119 	    return;
3120 	}
3121     }
3122     for(expr_node* e = expr; e != NULL; e = e->next) {
3123 	e->attrib(ctx);
3124     }
3125     type = expr->type;
3126 }
3127 
3128 
translate(int)3129 void expr_group_node::translate(int)
3130 {
3131     f_tkn = lpar;
3132     l_tkn = rpar;
3133     if (ctx == ctx_record || (language_c && ctx == ctx_array)) {
3134 	// constructor of record
3135         lpar->set_trans("{");
3136         rpar->set_trans("}");
3137     } else if (!language_c && ctx == ctx_array) {
3138         lpar->set_trans("{{");
3139         rpar->set_trans("}}");
3140     }
3141     for (expr_node* e = expr; e != NULL; e = e->next) {
3142         e->translate(ctx_constant);
3143     }
3144 }
3145 
3146 
write_list_node(token * lpar,write_param_node * vals,token * rpar)3147 write_list_node::write_list_node(token* lpar, write_param_node* vals,
3148 				 token* rpar)
3149 {
3150     CONS3(lpar, vals, rpar);
3151 }
3152 
attrib(int)3153 void write_list_node::attrib(int)
3154 {
3155     for(expr_node* prm = vals; prm != NULL; prm = prm->next)
3156     {
3157         prm->attrib(ctx_value);
3158     }
3159 }
3160 
3161 
translate(int)3162 void write_list_node::translate(int)
3163 {
3164     f_tkn = lpar;
3165     l_tkn = rpar;
3166 
3167     for(expr_node* prm = vals; prm != NULL; prm = prm->next)
3168     {
3169         prm->translate(ctx_value);
3170     }
3171 }
3172 
3173 
write_param_node(expr_node * val,token * t_coln1,expr_node * width,token * t_coln2,expr_node * prec)3174 write_param_node::write_param_node(expr_node* val,
3175 		     token* t_coln1, expr_node* width,
3176 		     token* t_coln2, expr_node* prec)
3177 : expr_node(tn_wrp)
3178 {
3179     CONS5(val, t_coln1, width, t_coln2, prec);
3180 }
3181 
attrib(int ctx)3182 void write_param_node::attrib(int ctx)
3183 {
3184 
3185     val->attrib(ctx);
3186     type = val->type;
3187     if (width) {
3188 	width->attrib(ctx_value);
3189 	if (prec) {
3190 	    prec->attrib(ctx_value);
3191         }
3192     }
3193 }
3194 
make_fmt_string(char * src)3195 static char* make_fmt_string(char* src) {
3196     char buf[65536];
3197     char* dst = buf;
3198     if (strcmp(src, "'\"'") == 0) return "\\\"";
3199     src += 1; // skip '"'
3200     while (*src != '\0') {
3201 	if (*src == '%') *dst++ = '%';
3202 	*dst++ = *src++;
3203     }
3204     *--dst = '\0'; // skip '"'
3205     return strdup(buf);
3206 }
3207 
translate(int ctx)3208 void write_param_node::translate(int ctx)
3209 {
3210     val->translate(ctx);
3211     f_tkn = val->f_tkn;
3212     l_tkn = val->l_tkn;
3213 
3214     if (language_c) {
3215 
3216 	if (write_format == NULL) return;
3217 	n_write_params += 1;
3218 
3219 	char fmt = '?';
3220 	switch(val->type->tag) {
3221 	  case tp_string:
3222 	    if (width == NULL && val->tag == tn_string) {
3223 		write_format = dprintf("%s%s", write_format,
3224 		    make_fmt_string(((string_node*)val)->value_tkn->out_text));
3225 		token* prev = f_tkn->prev_relevant();
3226 		if (prev->tag == TKN_COMMA) {
3227 		    prev = prev->prev_relevant();
3228 		    token::disable(prev->next, l_tkn);
3229 		} else {
3230 		    token* next = l_tkn->next_relevant();
3231 		    if (next->tag == TKN_COMMA) {
3232 			next = next->next_relevant();
3233 		    }
3234 		    token::disable(f_tkn, next->prev);
3235 		}
3236 		n_write_params -= 1;
3237 		return;
3238 	    }
3239 #if 1
3240 	    fmt = 'z';
3241 #else
3242 	    fmt = 's';
3243 	    f_tkn = val->f_tkn->prepend("array(");
3244 	    val->l_tkn->append(")");
3245 #endif
3246 	    break;
3247 	  case tp_array:
3248 	    fmt = 's';
3249 	    ((array_tp*)val->type->get_typedef())->insert_dimensions(val);
3250 	    break;
3251 	  case tp_char:
3252 	    if (width == NULL && val->tag == tn_char) {
3253 		write_format = dprintf("%s%s", write_format,
3254 		    make_fmt_string(((string_node*)val)->value_tkn->out_text));
3255 		token* prev = f_tkn->prev_relevant();
3256 		if (prev->tag == TKN_COMMA) {
3257 		    prev = prev->prev_relevant();
3258 		    token::disable(prev->next, l_tkn);
3259 		} else {
3260 		    token* next = l_tkn->next_relevant();
3261 		    if (next->tag == TKN_COMMA) {
3262 			next = next->next_relevant();
3263 		    }
3264 		    token::disable(f_tkn, next->prev);
3265 		}
3266 		n_write_params -= 1;
3267 		return;
3268 	    }
3269 	    fmt = 'c';
3270 	    break;
3271 	  case tp_bool:
3272 	    fmt = 'b';
3273 	    break;
3274 	  case tp_integer:
3275 	  case tp_range:
3276 	    fmt = 'i';
3277 	    break;
3278 	  case tp_real:
3279 	    fmt = 'f';
3280 	    break;
3281 	  default:
3282 	    warning(val->f_tkn, "invalid parameter for write operator");
3283 	}
3284 	if (width) {
3285 	    width->translate(ctx_value);
3286 	    t_coln1->set_trans(",");
3287 	    if (prec) {
3288 		prec->translate(ctx_value);
3289 		if (width->is_const_literal() && prec->is_const_literal()) {
3290 		    write_format = dprintf("%s%%%d.%d%c", write_format,
3291 					   width->value, prec->value, fmt);
3292 		    token::disable(val->l_tkn->next, prec->l_tkn);
3293 		} else {
3294 		    t_coln2->set_trans(",");
3295 		    write_format = dprintf("%s%%*.*%c", write_format, fmt);
3296 		}
3297 	    } else {
3298 		if (width->is_const_literal()) {
3299 		    write_format = dprintf("%s%%%d%c", write_format,
3300 					   width->value, fmt);
3301 		    token::disable(val->l_tkn->next, width->l_tkn);
3302 		} else {
3303 		    write_format = dprintf("%s%%*%c", write_format, fmt);
3304 		}
3305 	    }
3306 	} else {
3307 	    write_format = dprintf("%s%%%c", write_format, fmt);
3308 	}
3309 
3310     } else { // language C++
3311 
3312 	if (ctx == ctx_toascii) {
3313 	    if (width) {
3314 		width->translate(ctx_value);
3315 		t_coln1->set_trans(",");
3316 		l_tkn = width->l_tkn;
3317 		if (prec) {
3318 		    prec->translate(ctx_value);
3319 		    t_coln2->set_trans(",");
3320 		    l_tkn = prec->l_tkn;
3321 		}
3322 	    }
3323 	} else {
3324 	    if (val->type->tag == tp_bool) {
3325 		f_tkn = val->f_tkn->prepend("btos(");
3326 		l_tkn = val->l_tkn->append(")");
3327 	    }
3328 	    if (width) {
3329 		width->translate(ctx_value);
3330 		f_tkn = f_tkn->prepend("format(");
3331 		t_coln1->set_trans(",");
3332 		if (prec) {
3333 		    t_coln2->set_trans(",");
3334 		    prec->translate(ctx_value);
3335 		    l_tkn = prec->l_tkn->append(")");
3336 		} else {
3337 		    l_tkn = width->l_tkn->append(")");
3338 		}
3339 	    }
3340 	}
3341     }
3342 }
3343 
3344 
3345 //
3346 // Declaration
3347 //
3348 
label_decl_part_node(token * t_label,token_list * labels,token * t_semi)3349 label_decl_part_node::label_decl_part_node(token* t_label,
3350 					   token_list* labels,
3351 					   token* t_semi)
3352 {
3353     CONS3(t_label, labels, t_semi);
3354 }
3355 
attrib(int)3356 void label_decl_part_node::attrib(int)
3357 {
3358 }
3359 
translate(int)3360 void label_decl_part_node::translate(int)
3361 {
3362     token::remove(t_label, t_semi);
3363 }
3364 
3365 const_def_node* const_def_node::enumeration;
3366 
const_def_node(token * ident,token * equal,expr_node * constant)3367 const_def_node::const_def_node(token* ident, token* equal,
3368 			       expr_node* constant)
3369 {
3370     CONS3(ident, equal, constant);
3371 }
3372 
attrib(int)3373 void const_def_node::attrib(int)
3374 {
3375     constant->attrib(ctx_constant);
3376     sym = b_ring::add_cur(ident, symbol::s_const, constant->type);
3377     if (constant->flags & tn_is_const) {
3378 	sym->flags |= symbol::f_const;
3379 	sym->value = constant->value;
3380     }
3381     if (language_c && (sym->type->tag == tp_integer
3382 		       || sym->type->tag == tp_char
3383 		       || sym->type->tag == tp_set))
3384     {
3385 	sym->out_name->flags |= nm_entry::macro;
3386     }
3387 }
3388 
translate(int)3389 void const_def_node::translate(int)
3390 {
3391     constant->translate(ctx_constant);
3392     if (curr_proc && curr_proc->make_all_constants_global
3393 	&& !(sym->flags & symbol::f_static))
3394     {
3395 	curr_proc->make_unique(sym);
3396     }
3397     sym->translate(ident);
3398     l_tkn = constant->l_tkn;
3399     token::disable(ident->next, constant->f_tkn->prev);
3400     if (language_c && (sym->type->tag == tp_integer
3401 		       || sym->type->tag == tp_bool
3402 		       || sym->type->tag == tp_char
3403 		       || sym->type->tag == tp_set))
3404     {
3405 	if (!do_not_use_enums && !(sym->flags & symbol::f_static) &&
3406 	    (sym->type->tag == tp_integer ||  sym->type->tag == tp_bool))
3407 	{
3408 	    if (enumeration == NULL || (sym->flags & symbol::f_static)) {
3409 		f_tkn = ident->prepend("enum { ");
3410 		f_tkn->pos = curr_proc == NULL ? 0 : ident->pos;
3411 	    } else {
3412 		enumeration->l_tkn->set_trans(",");
3413 		enumeration->l_tkn->prev_relevant()->disable();
3414 	    }
3415 	    equal->set_trans(" = ");
3416 	    enumeration = this;
3417 	    l_tkn = constant->l_tkn->append("}");
3418 	    force_semicolon();
3419 	} else {
3420 	    enumeration = NULL;
3421 	    token* t;
3422 	    f_tkn = ident->prepend("#define ");
3423 	    f_tkn->pos = 0;
3424 	    equal->set_trans(" ");
3425 	    if (curr_proc) {
3426 		curr_proc->add_define(sym);
3427 	    }
3428 	    for (t = f_tkn->prev;
3429 		 t->cat == CAT_WSPC && t->tag != TKN_LN;
3430 		 t = t->prev);
3431 
3432 	    if (t->tag != TKN_LN) {
3433 		f_tkn = f_tkn->prepend("\n");
3434 		f_tkn->tag = TKN_LN;
3435 	    }
3436 	    t = l_tkn->next_relevant();
3437 	    if (t->tag == TKN_SEMICOLON) {
3438 		t->set_trans("\n");
3439 		t->tag = TKN_LN;
3440 	    }
3441 	}
3442     } else {
3443 	f_tkn = ident->prepend(language_c ? (char *) "static const " : (char *) "const ");
3444 	enumeration = NULL;
3445 	if (constant->type->tag == tp_string) {
3446 	    ident->prepend("char ");
3447 	    ident->append("[]");
3448 	} else {
3449 	    constant->type->insert_before(ident);
3450 	    ident->prepend(" ");
3451         }
3452 	equal->set_trans(" = ");
3453 	force_semicolon();
3454     }
3455     if (sym->flags & symbol::f_static) {
3456 	assert(global_func_decl_level != NULL);
3457 	global_func_decl_level->move_region(f_tkn, l_tkn);
3458 	global_func_decl_level->prepend("\n");
3459 	(new token(NULL, TKN_BEG_SHIFT, f_tkn->line, f_tkn->pos))
3460 	    ->insert_b(f_tkn);
3461 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3462     }
3463 }
3464 
typed_const_def_node(token * ident,token * coln,tpd_node * tpd,token * equal,expr_node * constant)3465 typed_const_def_node::typed_const_def_node(token* ident, token* coln,
3466 					   tpd_node* tpd,
3467 					   token* equal, expr_node* constant)
3468 : const_def_node(ident, equal, constant)
3469 {
3470     CONS2(coln, tpd);
3471 }
3472 
attrib(int)3473 void typed_const_def_node::attrib(int)
3474 {
3475     tpd->attrib(ctx_constant);
3476     constant->type = tpd->type;
3477     constant->attrib(tpd->type->tag == tp_array
3478 		     ? ctx_array : tpd->type->tag == tp_record || tpd->type->tag == tp_object
3479 		     ? ctx_record : ctx_constant);
3480 
3481     sym = b_ring::add_cur(ident, symbol::s_const, constant->type);
3482     if (constant->flags & tn_is_const) {
3483 	sym->flags |= symbol::f_const;
3484 	sym->value = constant->value;
3485     }
3486 }
3487 
translate(int)3488 void typed_const_def_node::translate(int)
3489 {
3490     constant->translate(ctx_constant);
3491     tpd->translate(ctx_constant);
3492     if (curr_proc && curr_proc->make_all_constants_global
3493 	&& !(sym->flags & symbol::f_static))
3494     {
3495 	curr_proc->make_unique(sym);
3496     }
3497     sym->translate(ident);
3498     l_tkn = constant->l_tkn;
3499     f_tkn = ident->prepend(" ")->move(tpd->f_tkn, tpd->l_tkn)->prepend("const ");
3500     token::disable(ident->next, constant->f_tkn->prev);
3501     equal->set_trans(" = ");
3502     force_semicolon();
3503 
3504     if (sym->flags & symbol::f_static) {
3505 	assert(global_func_decl_level != NULL);
3506 	global_func_decl_level->move_region(f_tkn, l_tkn);
3507 	global_func_decl_level->prepend("\n");
3508 	(new token(NULL, TKN_BEG_SHIFT, f_tkn->line, f_tkn->pos))
3509 	    ->insert_b(f_tkn);
3510 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3511     }
3512 }
3513 
const_def_part_node(token * t_const,const_def_node * list)3514 const_def_part_node::const_def_part_node(token* t_const, const_def_node* list)
3515 {
3516     CONS2(t_const, list);
3517 }
3518 
attrib(int ctx)3519 void const_def_part_node::attrib(int ctx)
3520 {
3521     for (decl_node* def = list; def != NULL; def = def->next) {
3522         def->attrib(ctx);
3523     }
3524 }
3525 
translate(int ctx)3526 void const_def_part_node::translate(int ctx)
3527 {
3528     f_tkn = l_tkn = t_const;
3529     const_def_node::enumeration = NULL;
3530     for (decl_node* def = list; def != NULL; def = def->next) {
3531         def->translate(ctx);
3532 	l_tkn = def->l_tkn;
3533     }
3534     t_const->disappear();
3535     if (ctx == ctx_block && curr_proc->make_all_constants_global) {
3536 	// make type definition global
3537         global_func_decl_level->move_region(f_tkn, l_tkn);
3538 	global_func_decl_level->prepend("\n\n");
3539         (new token(NULL, TKN_BEG_SHIFT, f_tkn->line,
3540 		   f_tkn->next_relevant()->pos))->insert_b(f_tkn);
3541 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3542     }
3543     if (ctx == ctx_module || ctx == ctx_program) {
3544         (new token((char*)0, TKN_BEG_SHIFT, f_tkn->line,
3545 		   f_tkn->next_relevant()->pos))->insert_b(f_tkn);
3546         (new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3547     }
3548 }
3549 
type_def_node(token * ident,token * equal,tpd_node * tpd)3550 type_def_node::type_def_node(token* ident, token* equal, tpd_node* tpd)
3551 {
3552     CONS3(ident, equal, tpd);
3553 }
3554 
attrib(int ctx)3555 void type_def_node::attrib(int ctx)
3556 {
3557     tpd->attrib(ctx);
3558     tpexpr* type = new simple_tp(tpd->type);
3559     sym = b_ring::add_cur(ident, symbol::s_type, type);
3560     type->name = sym->out_name->text;
3561 
3562     switch (tpd->tag) {
3563       case tpd_node::tpd_enum:
3564         ((enum_tp*)tpd->type)->set_bounds(sym);
3565         ((enum_tp*)tpd->type)->set_enumeration_name(type);
3566 	break;
3567       case tpd_node::tpd_range:
3568         ((range_tp*)tpd->type)->set_bounds(sym);
3569 	break;
3570       case tpd_node::tpd_object:
3571         ((object_tp*)tpd->type)->class_name = sym;
3572     }
3573 }
3574 
translate(int ctx)3575 void type_def_node::translate(int ctx)
3576 {
3577     tpd->translate(ctx);
3578     sym->translate(ident);
3579     f_tkn = ident;
3580     l_tkn = tpd->l_tkn;
3581     token::disable(ident->next, tpd->f_tkn->prev);
3582 
3583     if (language_c && tpd->tag == tpd_node::tpd_array) {
3584 	tpd_node* eltd = ((array_tpd_node*)tpd)->eltd;
3585         f_tkn = ident->prepend("typedef ");
3586 	ident->move(eltd->f_tkn, eltd->l_tkn);
3587         ident->prepend(" ");
3588     } else if (small_enum && tpd->tag == tpd_node::tpd_enum) {
3589 	int n_elems = ((enum_tp*)tpd->type)->n_elems;
3590 	ident->set_trans(dprintf("typedef %s %s;\n",
3591 			       n_elems < 0x100 ? "unsigned char" :
3592 			       n_elems < 0x10000 ? "unsigned short" :
3593 			       "unsigned", ident->out_text));
3594 	((enum_tpd_node*)tpd)->f_tkn->set_bind(ident);
3595     } else if (!language_c && tpd->tag == tpd_node::tpd_enum) {
3596 	ident->append(" ");
3597 	f_tkn = ident->prepend("enum ");
3598 	((enum_tpd_node*)tpd)->f_tkn->disable();
3599     } else if (tpd->tag == tpd_node::tpd_object) {
3600 	tpd->f_tkn->append(ident->out_text);
3601 	tpd->f_tkn->set_pos(ident);
3602 	ident->disappear();
3603      } else if (tpd->tag == tpd_node::tpd_record) {
3604 	record_tpd_node* rec_tpd = (record_tpd_node*)tpd;
3605 	if (language_c) {
3606 	    rec_tpd->t_record->set_trans(dprintf("typedef %s%s ",
3607 						 rec_tpd->t_record->out_text,
3608 						 ident->out_text));
3609 	    l_tkn = l_tkn->append(" ")->append(ident->out_text);
3610 	} else {
3611 	    rec_tpd->t_record->set_trans(dprintf("%s%s ",
3612 						 rec_tpd->t_record->out_text,
3613 						 ident->out_text));
3614 	}
3615 	rec_tpd->t_record->set_pos(ident);
3616 	ident->disappear();
3617     } else if (tpd->tag == tpd_node::tpd_proc) {
3618 	fptr_tpd_node* fptr = (fptr_tpd_node*)tpd;
3619 	fptr->t_params->prepend(dprintf("(*%s)", ident->out_text));
3620 	ident->set_trans("typedef ");
3621     } else {
3622 	ident->append(" ");
3623         l_tkn = l_tkn->append(" ")->append(ident->out_text);
3624         ident->set_trans("typedef");
3625     }
3626     force_semicolon();
3627 }
3628 
3629 
type_def_part_node(token * t_type,type_def_node * types)3630 type_def_part_node::type_def_part_node(token* t_type, type_def_node* types)
3631 {
3632     CONS2(t_type, types);
3633 }
3634 
attrib(int ctx)3635 void type_def_part_node::attrib(int ctx)
3636 {
3637     for (decl_node* tpd = types; tpd != NULL; tpd = tpd->next) {
3638 	tpd->attrib(ctx);
3639     }
3640     if (ctx == ctx_block && curr_proc) {
3641 	curr_proc->make_all_constants_global = TRUE;
3642     }
3643 }
3644 
translate(int ctx)3645 void type_def_part_node::translate(int ctx)
3646 {
3647     f_tkn = l_tkn = t_type;
3648     t_type->disappear();
3649     for (decl_node* tpd = types; tpd != NULL; tpd = tpd->next) {
3650 	tpd->translate(ctx);
3651 	l_tkn = tpd->l_tkn;
3652     }
3653     if (ctx == ctx_block) {
3654 	// make type definition global
3655         global_func_decl_level->move_region(f_tkn, l_tkn);
3656 	global_func_decl_level->prepend("\n\n");
3657         (new token(NULL, TKN_BEG_SHIFT, f_tkn->line,
3658 		   f_tkn->next_relevant()->pos))->insert_b(f_tkn);
3659 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3660     } else {
3661         (new token((char*)0, TKN_BEG_SHIFT, f_tkn->line,
3662 		   f_tkn->next_relevant()->pos))->insert_b(f_tkn);
3663 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3664     }
3665 }
3666 
unit_spec_node(token * t_unit,token * t_name,token * t_semi,token * t_interface,decl_node * decls)3667 unit_spec_node::unit_spec_node(token* t_unit, token* t_name, token* t_semi,
3668 			       token* t_interface, decl_node* decls)
3669 {
3670     CONS5(t_unit, t_name, t_semi, t_interface, decls);
3671 }
3672 
attrib(int ctx)3673 void unit_spec_node::attrib(int ctx)
3674 {
3675     unit_tp* type = new unit_tp;
3676     b_ring::global_b_ring.add(t_name->name, symbol::s_var, type);
3677     b_ring* outer = b_ring::pop();
3678 
3679     b_ring::push(type);
3680 
3681     for (decl_node* dcl = decls; dcl != NULL; dcl = dcl->next) {
3682 	dcl->attrib(ctx);
3683     }
3684     b_ring::push(outer);
3685 }
3686 
translate(int ctx)3687 void unit_spec_node::translate(int ctx)
3688 {
3689     for (decl_node* dcl = decls; dcl != NULL; dcl = dcl->next) {
3690 	dcl->translate(ctx);
3691 	l_tkn = dcl->l_tkn;
3692     }
3693 }
3694 
3695 
var_decl_node(token_list * vars,token * coln,tpd_node * tpd)3696 var_decl_node::var_decl_node(token_list* vars, token* coln, tpd_node* tpd)
3697 {
3698     CONS3(vars, coln, tpd);
3699     scope = NULL;
3700 }
3701 
attrib(int ctx)3702 void var_decl_node::attrib(int ctx)
3703 {
3704     tpexpr* tp;
3705     if (tpd != NULL) {
3706 	tpd->attrib(ctx);
3707 	tp = tpd->type;
3708 	if (tp == NULL) {
3709 	    warning(coln, "type is unknown");
3710 	    tpd->type = tp = &any_type;
3711 	}
3712     } else {
3713 	tp = &any_type;
3714     }
3715 
3716     for (token_list* tkn = vars; tkn != NULL; tkn = tkn->next) {
3717 	int prm_class = symbol::s_var;
3718 	if (language_c) {
3719 	    if (tp->tag == tp_array || tp->tag == tp_dynarray) {
3720 		if (ctx == ctx_valpar) {
3721 		    prm_class = symbol::s_const;
3722 		}
3723 	    } else {
3724 		if (ctx == ctx_varpar) {
3725 		    prm_class = symbol::s_ref;
3726 		}
3727 	    }
3728 	} else if (ctx == ctx_varpar && tp->tag != tp_array
3729 		   && tp->tag != tp_string && curr_proc->is_extern_c)
3730         {
3731 	    prm_class = symbol::s_ref;
3732 	}
3733 
3734 	tkn->var = b_ring::add_cur(tkn->ident, prm_class, tp);
3735 	if (ctx == ctx_varpar) {
3736 	    tkn->var->flags |= symbol::f_var_param;
3737 	}
3738 	else if (ctx == ctx_valpar) {
3739 	    tkn->var->flags |= symbol::f_val_param;
3740 	}
3741 	if (*struct_path) {
3742 	   tkn->var->path = struct_path;
3743 	}
3744 	if (ctx == ctx_valpar || ctx == ctx_varpar) {
3745 	    curr_proc->add_param(tkn->var);
3746 	}
3747     }
3748 }
3749 
3750 static token* var_decl_coln; // align formal parameters of procedures
3751 
translate(int ctx)3752 void  var_decl_node::translate(int ctx)
3753 {
3754     tpexpr* tp;
3755     if (tpd != NULL) {
3756 	tpd->translate(ctx);
3757 	tp = tpd->type;
3758     } else {
3759 	tp = &any_type;
3760     }
3761     f_tkn = vars->ident;
3762     l_tkn = coln ? coln : f_tkn;
3763 
3764     if (coln != NULL) {
3765 	token::disable(coln->prev_relevant()->next, tpd->f_tkn->prev);
3766     }
3767     if (ctx == ctx_valpar || ctx == ctx_varpar) {
3768 	if (language_c && tp->tag == tp_dynarray) {
3769 	    token *t = vars->ident->prev;
3770 	    ((array_tp*)tp->get_typedef())->
3771 		insert_bound_params(vars->ident);
3772 	    if (var_decl_coln) {
3773 	        t->next->set_bind(var_decl_coln);
3774 	    }
3775 	}
3776         for (token_list* tkn = vars; tkn != NULL; tkn = tkn->next) {
3777 	    token *t;
3778 	    tkn->var->translate(tkn->ident);
3779 	    if (language_c) {
3780 		if (tpd != NULL) {
3781 		    if (tpd->tag == tpd_node::tpd_array) {
3782 			tpd_node* eltd = ((array_tpd_node*)tpd)->eltd;
3783 			t = tkn->ident->copy(eltd->f_tkn, eltd->l_tkn);
3784 			if (tp->tag == tp_dynarray) {
3785 			    tkn->ident->prepend(ctx == ctx_varpar
3786 						? (char *) "* " : (char *) " const* ");
3787 			} else {
3788 			    tkn->ident->prepend(ctx == ctx_varpar
3789 						? (char *) " " : (char *) "  const ");
3790 			    tkn->ident->next->copy(tpd->f_tkn, tpd->l_tkn);
3791 			}
3792 		    } else {
3793 			t = tkn->ident->prepend(ctx == ctx_varpar
3794 						? tp->tag == tp_array || tp->tag == tp_string ? (char *) " " : (char *) "* "
3795 						: tp->tag == tp_array ? (char *) " const " : (char *) " ")->
3796 			    copy(tpd->f_tkn, tpd->l_tkn);
3797 		    }
3798 		} else {
3799 		    t = tkn->ident->prepend("void* ");
3800 		}
3801 	    } else { // C++
3802 		if (tpd == NULL) {
3803 		    t = tkn->ident->prepend("void* ");
3804 		} else {
3805 		    char* modifier = " ";
3806 		    if (ctx == ctx_varpar) {
3807 			if (tp->tag != tp_dynarray && tp->tag != tp_string) {
3808 			    if (curr_proc->is_extern_c) {
3809 				if (tp->tag != tp_array) {
3810 				    modifier = "* ";
3811 				}
3812 			    } else {
3813 				modifier = "& ";
3814 			    }
3815 			}
3816 		    }
3817 		    t = tkn->ident->prepend(modifier);
3818 		    if (curr_proc->is_extern_c && tp->tag == tp_array) {
3819 			char* param_type_name =
3820 			    ((array_tp*)tp->get_typedef())->elem_type->name;
3821 			t->prepend(dprintf("%s* ", param_type_name
3822 					   ? param_type_name : "void"));
3823 		    } else {
3824 			t->copy(tpd->f_tkn, tpd->l_tkn);
3825 		    }
3826 		}
3827 	    }
3828 	    if (var_decl_coln) {
3829 	        t->set_bind(var_decl_coln);
3830 	    } else {
3831 	        t->set_pos(tkn->ident);
3832             }
3833 	    if (tkn == vars) {
3834 		f_tkn = t;
3835             }
3836         }
3837 	if (tpd != NULL) {
3838 	    token::remove(tpd->f_tkn, tpd->l_tkn);
3839 	}
3840 	if (language_c && tpd != NULL && tpd->tag == tpd_node::tpd_array) {
3841 	    tpd_node* eltd = ((array_tpd_node*)tpd)->eltd;
3842 	    token::remove(eltd->f_tkn, eltd->l_tkn);
3843 	}
3844         if (l_tkn->next_relevant()->tag == TKN_SEMICOLON) {
3845             l_tkn->next_relevant()->set_trans(",");
3846         }
3847 
3848     } else {
3849 	bool is_static = FALSE;
3850 	for (token_list* tkn = vars; tkn != NULL; tkn = tkn->next) {
3851 	    if (tkn->var->out_name != tkn->ident->name) {
3852 		tkn->ident->set_trans(tkn->var->out_name->text);
3853 	    }
3854 	    if (language_c && ctx != ctx_record
3855 		&& (tp->get_typedef()->flags & tp_need_init))
3856 	    {
3857 		// initialize file structure
3858 		tkn->ident->append(
3859 		    (tp->tag == tp_file || tp->tag == tp_text)
3860 		    ? (char *) " = VOID_FILE" : (char *) " = {0}");
3861 	    }
3862 	    if (tkn->var->flags & symbol::f_static) {
3863 		is_static = TRUE;
3864 	    }
3865 	}
3866 	if (language_c && tpd->tag == tpd_node::tpd_array) {
3867 	    tpd_node* eltd = ((array_tpd_node*)tpd)->eltd;
3868 	    f_tkn = f_tkn->prepend(" ");
3869 	    f_tkn = f_tkn->move(eltd->f_tkn, eltd->l_tkn);
3870 	    for (token_list* tkn = vars; tkn != NULL; tkn = tkn->next) {
3871 		tkn->ident->next->copy(tpd->f_tkn, tpd->l_tkn);
3872 	    }
3873 	    token::remove(tpd->f_tkn, tpd->l_tkn);
3874 	} else {
3875 	    if (language_c && tpd->tag == tpd_node::tpd_ref) {
3876 		for (token_list* tkn = vars->next; tkn != NULL; tkn=tkn->next){
3877 		    tkn->ident->prepend("*");
3878 		}
3879 	    }
3880 	    f_tkn = f_tkn->prepend(" ");
3881 	    f_tkn = f_tkn->move(tpd->f_tkn, tpd->l_tkn);
3882 	}
3883 	if (ctx != ctx_record  && ctx != ctx_object
3884 	    && (unit_node::interface_part
3885 		|| (extern_vars
3886 		    && coln != NULL
3887 		    && (coln->attr & token::from_include_file))))
3888         {
3889 	    f_tkn = f_tkn->prepend("EXTERN ");
3890 	} else if (scope != NULL) {
3891 	    f_tkn = f_tkn->prepend(scope->tag == TKN_EXTERNAL ? (char *) "extern " :
3892 				   scope->tag == TKN_STATIC ? (char *) "static " : (char *) "");
3893 	}
3894         force_semicolon();
3895 	if (is_static) {
3896 	    assert(global_func_decl_level != NULL);
3897 	    for (token_list* tkn = vars; tkn != NULL; tkn = tkn->next) {
3898 		if (!(tkn->var->flags & symbol::f_static)) {
3899 		    tkn->var->flags |= symbol::f_static;
3900 		    tkn->var->ring->make_unique(tkn->var);
3901 		    tkn->var->translate(tkn->ident);
3902 		}
3903 	    }
3904 	    f_tkn = f_tkn->prepend("static ");
3905 	    global_func_decl_level->move_region(f_tkn, l_tkn);
3906 	    global_func_decl_level->prepend("\n");
3907 	    (new token(NULL, TKN_BEG_SHIFT, f_tkn->line, f_tkn->pos))
3908 		->insert_b(f_tkn);
3909 	    (new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3910 	}
3911     }
3912 }
3913 
var_decl_part_node(token * t_var,var_decl_node * vars)3914 var_decl_part_node::var_decl_part_node(token* t_var, var_decl_node* vars)
3915 {
3916     CONS2(t_var, vars);
3917 }
3918 
attrib(int ctx)3919 void var_decl_part_node::attrib(int ctx)
3920 {
3921     for (decl_node* var = vars; var != NULL; var = var->next) {
3922         var->attrib(ctx == ctx_valpar ? (int)ctx_varpar : ctx);
3923     }
3924 }
3925 
translate(int ctx)3926 void var_decl_part_node::translate(int ctx)
3927 {
3928     f_tkn = l_tkn = t_var;
3929     for (decl_node* var = vars; var != NULL; var = var->next) {
3930         var->translate(ctx == ctx_valpar ? (int)ctx_varpar : ctx);
3931 	l_tkn = var->l_tkn;
3932     }
3933     if (t_var) {
3934 	t_var->disappear();
3935     } else {
3936 	f_tkn = vars->f_tkn;
3937     }
3938     //    token::disable(t_var, t_var->next_relevant()->prev);
3939     if (ctx == ctx_module || ctx == ctx_program) {
3940         (new token((char*)0, TKN_BEG_SHIFT, f_tkn->line,
3941 		   f_tkn->next_relevant()->pos))->insert_b(f_tkn);
3942         (new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3943 	if (unit_node::interface_part) {
3944 	    f_tkn = f_tkn->prepend(dprintf("\n#ifdef __%s_implementation__\n"
3945 					   "#undef EXTERN\n"
3946 					   "#define EXTERN\n"
3947 					   "#endif\n\n",
3948 					   unit_node::unit_name));
3949 	    l_tkn = l_tkn->append("\n#undef EXTERN\n"
3950 				  "#define EXTERN extern\n");
3951 	}
3952     }
3953 }
3954 
3955 
var_origin_decl_node(token * t_ident,token * t_origin,expr_node * addr,token * t_colon,tpd_node * tpd)3956 var_origin_decl_node::var_origin_decl_node(token* t_ident,
3957 					   token* t_origin, expr_node *addr,
3958 					   token* t_colon, tpd_node *tpd)
3959 {
3960     CONS5(t_ident, t_origin, addr, t_colon, tpd);
3961 }
3962 
3963 
attrib(int ctx)3964 void var_origin_decl_node::attrib(int ctx)
3965 {
3966     tpd->attrib(ctx);
3967     type = tpd->type;
3968     sym = b_ring::add_cur(t_ident,
3969 			  language_c ? symbol::s_ref : symbol::s_var, type);
3970     addr->attrib(ctx_value);
3971 }
3972 
translate(int ctx)3973 void var_origin_decl_node::translate(int ctx)
3974 {
3975     tpd->translate(ctx);
3976     sym->translate(t_ident);
3977     addr->translate(ctx_value);
3978     l_tkn = addr->l_tkn;
3979     assert(type->name != NULL);
3980     f_tkn = t_ident->prepend(type->name);
3981     if (language_c) {
3982 	t_ident->prepend("* ");
3983 	t_origin->set_trans(dprintf(" = (%s*)", type->name));
3984     } else {
3985 	t_ident->prepend("& ");
3986 	t_origin->set_trans(dprintf(" = *(%s*)", type->name));
3987     }
3988     token::disable(l_tkn->next, tpd->l_tkn);
3989     force_semicolon();
3990     if (sym->flags & symbol::f_static) {
3991 	assert(global_func_decl_level != NULL);
3992 	f_tkn = f_tkn->prepend("static ");
3993 	global_func_decl_level->move_region(f_tkn, l_tkn);
3994 	global_func_decl_level->prepend("\n\n");
3995 	(new token(NULL, TKN_BEG_SHIFT, f_tkn->line, f_tkn->pos))
3996 	    ->insert_b(f_tkn);
3997 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
3998     } else {
3999 	if (ctx == ctx_module || ctx == ctx_program) {
4000 	    (new token((char*)0, TKN_BEG_SHIFT, f_tkn->line,
4001 		       f_tkn->next_relevant()->pos))->insert_b(f_tkn);
4002 	    (new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
4003 	}
4004     }
4005 }
4006 
4007 
param_list_node(token * lpar,decl_node * params,token * rpar)4008 param_list_node::param_list_node(token* lpar, decl_node* params, token* rpar)
4009 {
4010     CONS3(lpar, params, rpar);
4011 }
4012 
attrib(int)4013 void param_list_node::attrib(int)
4014 {
4015     for (decl_node* dcl = params; dcl != NULL; dcl = dcl->next) {
4016         dcl->attrib(ctx_valpar);
4017     }
4018 }
4019 
translate(int)4020 void param_list_node::translate(int)
4021 {
4022     f_tkn = lpar;
4023     l_tkn = rpar;
4024 
4025     for (decl_node* dcl = params; dcl != NULL; dcl = dcl->next) {
4026         dcl->translate(ctx_valpar);
4027 	if (var_decl_coln == NULL) {
4028 	    var_decl_coln = dcl->f_tkn->prev->next_relevant();
4029         }
4030     }
4031     var_decl_coln = NULL;
4032 }
4033 
4034 
4035 // Class proc_decl_node is used for procedure formal parameter declaration
4036 
proc_decl_node(token * t_proc,token * t_ident,param_list_node * params,token * t_coln,tpd_node * ret_type)4037 proc_decl_node::proc_decl_node(token* t_proc, token* t_ident,
4038 			       param_list_node* params,
4039 			       token* t_coln, tpd_node* ret_type)
4040 {
4041     CONS5(t_proc, t_ident, params, t_coln, ret_type);
4042 }
4043 
attrib(int ctx)4044 void proc_decl_node::attrib(int ctx)
4045 {
4046     if (ret_type) ret_type->attrib(ctx);
4047 
4048     type = new proc_tp(ret_type ? ret_type->type : (tpexpr*)NULL, (tpd_node*)this);
4049     var = b_ring::add_cur(t_ident, symbol::s_var, type);
4050     type->proc_name = var->out_name->text;
4051     curr_proc->add_param(var);
4052     if (params) {
4053         proc_tp* save_proc = curr_proc;
4054 	curr_proc = type;
4055 	b_ring::push(type);
4056 	params->attrib(ctx);
4057 	b_ring::pop();
4058 	curr_proc = save_proc;
4059     }
4060 }
4061 
insert_return_type()4062 void proc_decl_node::insert_return_type() {
4063     if (ret_type) {
4064         ret_type->translate(ctx_block);
4065 	assert(ret_type->type->name != NULL);
4066 	if (language_c && ret_type->type->tag == tp_array) {
4067 	    t_proc->set_trans(dprintf("%s*", ret_type->type->name));
4068 	    var->flags |= symbol::f_var_param;
4069 	} else {
4070 	    t_proc->set_trans(ret_type->type->name);
4071 	}
4072 	token::disable(t_coln->prev_relevant()->next, ret_type->l_tkn);
4073     } else {
4074 	if (type->is_constructor || type->is_destructor) {
4075 	    if (var != NULL) {
4076 		t_proc->set_trans(dprintf("%s*", ((object_tp*)var->ring)->
4077 					  class_name->out_name->text));
4078 	    }
4079 	} else {
4080 	    t_proc->set_trans("void");
4081 	}
4082     }
4083     if (*pascall) {
4084 	t_proc->append(pascall);
4085 	t_proc->append(" ");
4086     }
4087 }
4088 
insert_params()4089 void proc_decl_node::insert_params() {
4090     token* rest = NULL;
4091     bool first = FALSE;
4092     if (params) {
4093         proc_tp* save_proc = curr_proc;
4094 	curr_proc = type;
4095         params->translate(ctx_block);
4096 	curr_proc = save_proc;
4097 	rest = params->rpar;
4098     } else {
4099         rest = t_ident->append("(")->append(")");
4100 	first = TRUE;
4101     }
4102     if (language_c && type->res_type != NULL
4103 	&& type->res_type->tag == tp_array)
4104     {
4105 	if (params) {
4106 	    params->lpar->append(dprintf("%s %s_result, ",
4107 					 type->res_type->name,
4108 					 type->proc_name));
4109 	} else {
4110 	    rest->prepend(dprintf("%s %s_result",
4111 				   type->res_type->name, type->proc_name));
4112 	}
4113 	first = FALSE;
4114     }
4115     for (param_spec* p = type->extra_params; p != NULL; p = p->next) {
4116 
4117 	if (p->var->flags & symbol::f_static) continue;
4118 
4119 	if (!first) {
4120      	    rest->prepend(", ");
4121 	}
4122 	first = FALSE;
4123 	if (language_c) {
4124 	    if (p->var->type->tag == tp_array) {
4125 		array_tpd_node* atp = (array_tpd_node*)p->var->type->tpd;
4126 		rest->copy(atp->eltd->f_tkn, atp->eltd->l_tkn);
4127 		rest->prepend(dprintf(p->var->tag == symbol::s_const
4128 				      ? " const %s" : " %s",
4129 				      p->var->out_name->text));
4130 		rest->copy(atp->f_tkn, atp->l_tkn);
4131 	    } else if (p->var->type->tag == tp_dynarray) {
4132 		array_tpd_node* atp = (array_tpd_node*)p->var->type->tpd;
4133 		rest->copy(atp->eltd->f_tkn, atp->eltd->l_tkn);
4134 		rest->prepend(dprintf(p->var->tag == symbol::s_const
4135 				      ? " const* %s" : "* %s",
4136 				      p->var->out_name->text));
4137 	    } else {
4138 		p->var->type->insert_before(rest);
4139 		if (p->var->tag == symbol::s_const) {
4140 		    if (p->var->type->is_scalar()
4141 			|| p->var->type->tag == tp_string)
4142 		    {
4143 			rest->prepend(dprintf(" const %s",
4144 					      p->var->out_name->text));
4145 		    } else {
4146 			rest->prepend(dprintf(" const* %s",
4147 					      p->var->out_name->text));
4148 		    }
4149 		} else {
4150 		    rest->prepend(dprintf("* %s", p->var->out_name->text));
4151 		}
4152 	    }
4153 	} else {
4154 	    p->var->type->insert_before(rest);
4155 	    if (p->var->tag == symbol::s_const) {
4156 		if (p->var->type->is_scalar()) {
4157 		    rest->prepend(dprintf(" const %s",
4158 					  p->var->out_name->text));
4159 		} else {
4160 		    rest->prepend(dprintf(" const& %s",
4161 					  p->var->out_name->text));
4162 		}
4163 	    } else {
4164 		rest->prepend(dprintf("& %s", p->var->out_name->text));
4165 	    }
4166 	}
4167     }
4168 }
4169 
4170 
translate(int)4171 void proc_decl_node::translate(int)
4172 {
4173     f_tkn = t_proc;
4174 
4175     insert_return_type();
4176     t_ident->set_trans(dprintf("(*%s)", var->out_name->text));
4177     insert_params();
4178     l_tkn = params ? params->l_tkn : t_ident->next->next;
4179 
4180     if (l_tkn->next_relevant()->tag == TKN_SEMICOLON) {
4181         l_tkn->next_relevant()->set_trans(",");
4182     }
4183 }
4184 
proc_fwd_decl_node(token * t_proc,token * t_ident,param_list_node * params,token * t_coln,tpd_node * ret_type,token * t_semi1,token_list * qualifiers,token * t_semi2)4185 proc_fwd_decl_node::proc_fwd_decl_node
4186    (token* t_proc, token* t_ident, param_list_node* params, token* t_coln,
4187     tpd_node* ret_type, token* t_semi1, token_list* qualifiers, token* t_semi2)
4188 : proc_decl_node(t_proc, t_ident, params, t_coln, ret_type)
4189 {
4190     CONS3(t_semi1, qualifiers, t_semi2);
4191 }
4192 
attrib(int ctx)4193 void proc_fwd_decl_node::attrib(int ctx)
4194 {
4195     if (ret_type) {
4196 	ret_type->attrib(ctx);
4197     }
4198     type = new proc_tp(ret_type ? ret_type->type : (tpexpr*)NULL);
4199     type->forward = this;
4200 
4201     if (turbo_pascal) {
4202 	if (t_proc->tag == TKN_CONSTRUCTOR) {
4203 	    type->is_constructor = TRUE;
4204 	} else if (t_proc->tag == TKN_DESTRUCTOR) {
4205 	    type->is_destructor = TRUE;
4206 	}
4207     }
4208     is_external = FALSE;
4209     is_static = FALSE;
4210     is_virtual = FALSE;
4211     for (token_list* t = qualifiers; t != NULL; t = t->next) {
4212 	if (t->ident->tag == TKN_EXTERNAL) {
4213 	    is_external = TRUE;
4214 	} else if (t->ident->tag == TKN_STATIC) {
4215 	    is_static = TRUE;
4216 	} else if (t->ident->tag == TKN_VIRTUAL) {
4217 	    is_virtual = TRUE;
4218 	} else if (t->ident->tag == TKN_C) {
4219 	    type->is_extern_c = TRUE;
4220 	}
4221     }
4222 
4223     if ((var = b_ring::search_cur(t_ident)) == NULL || var->type == NULL
4224 	|| var->type->tag != tp_proc || var->ring != b_ring::curr_b_ring
4225 	|| (var->flags & symbol::f_syslib))
4226     {
4227 	var = b_ring::add_cur(t_ident, symbol::s_proc, type);
4228     } else {
4229 	var->type = type;
4230     }
4231     type->proc_name = var->out_name->text;
4232 
4233     if (params) {
4234         proc_tp* save_proc = curr_proc;
4235 	curr_proc = type;
4236       	b_ring::push(type);
4237 	params->attrib(ctx);
4238 	b_ring::pop();
4239 	curr_proc = save_proc;
4240     }
4241 }
4242 
translate(int)4243 void proc_fwd_decl_node::translate(int)
4244 {
4245     f_tkn = t_proc;
4246     l_tkn = t_semi1;
4247 
4248     insert_return_type();
4249     if (qualifiers) {
4250 	if (is_external) {
4251 	    f_tkn = f_tkn->prepend(type->is_extern_c && !language_c
4252 				   ? (char *) "extern \"C\" " : (char *) "extern ");
4253 	} else if (is_static) {
4254 	    f_tkn = f_tkn->prepend("static ");
4255 	} else if (is_virtual) {
4256 	    f_tkn = f_tkn->prepend("virtual ");
4257 	}
4258     }
4259     var->translate(t_ident);
4260     insert_params();
4261     if (qualifiers) {
4262 	token::remove(qualifiers->ident, t_semi2);
4263     }
4264 }
4265 
4266 
4267 object_tp* proc_def_node::self;
4268 
proc_def_node(token * t_proc,token * t_class,token * t_dot,token * t_ident,param_list_node * params,token * t_coln,tpd_node * ret_type,token * t_semi1,token * t_attrib,token * t_semi2,block_node * block,token * t_semi3)4269 proc_def_node::proc_def_node
4270   (token* t_proc, token* t_class, token* t_dot, token* t_ident, param_list_node* params, token* t_coln,
4271    tpd_node* ret_type, token* t_semi1, token* t_attrib, token* t_semi2,
4272    block_node* block, token* t_semi3)
4273 : proc_decl_node(t_proc, t_ident, params, t_coln, ret_type)
4274 {
4275     CONS7(t_class, t_dot, t_semi1, t_attrib, t_semi2, block, t_semi3);
4276     use_forward = FALSE;
4277     s_self = NULL;
4278     self = NULL;
4279 }
4280 
attrib(int ctx)4281 void proc_def_node::attrib(int ctx)
4282 {
4283     if (ret_type) {
4284 	ret_type->attrib(ctx);
4285     }
4286     type = new proc_tp(ret_type ? ret_type->type : (tpexpr*)NULL);
4287 
4288     if (t_class != NULL) { // class method
4289 	s_self = b_ring::search_cur(t_class);
4290 	if (s_self == NULL) {
4291 	    warning(t_class, "Class %s is not defined\n", t_class->out_text);
4292 	} else {
4293 	    self = (object_tp*)s_self->type->get_typedef();
4294 	    var = self->search(t_ident);
4295 	    if (var == NULL || var->type->tag != tp_proc) {
4296 		warning(t_class, "Method %s not found in class %s\n",
4297 			t_ident->out_text, t_class->out_text);
4298 		var = self->add(t_ident->name, symbol::s_proc, type);
4299 	    } else {
4300 		type = (proc_tp*)var->type;
4301 	    }
4302 	    b_ring::push(self);
4303 	}
4304     } else {
4305 	if ((var = b_ring::search_cur(t_ident)) == NULL || var->type == NULL
4306 	    || var->type->tag != tp_proc || var->ring != b_ring::curr_b_ring
4307 	    || (var->flags & symbol::f_syslib))
4308 	{
4309 	    var = b_ring::add_cur(t_ident, symbol::s_proc, type);
4310 	}
4311 	else
4312 	{
4313 	    if (((proc_tp*)var->type)->forward != NULL
4314 		&& params == NULL && ret_type == NULL)
4315 	    {
4316 		use_forward = TRUE;
4317 		type = (proc_tp*)var->type;
4318 	    } else {
4319 		var->type = type;
4320 	    }
4321 	}
4322     }
4323     if (var != NULL) {
4324 	type->proc_name = var->out_name->text;
4325     }
4326     b_ring::push(type);
4327     proc_tp* save_proc = curr_proc;
4328     curr_proc = type;
4329     if (params) params->attrib(ctx);
4330     block->attrib(ctx_block);
4331     if (save_proc) {
4332 	save_proc->n_subproc += curr_proc->n_subproc + 1;
4333     }
4334     curr_proc = save_proc;
4335 
4336     b_ring::pop();
4337     if (t_class && self) {
4338 	b_ring::pop();
4339 	self = NULL;
4340     }
4341 }
4342 
translate(int ctx)4343 void proc_def_node::translate(int ctx)
4344 {
4345     f_tkn = t_proc;
4346     l_tkn = t_semi3;
4347     int is_recursive = var->out_name->flags & nm_entry::recursive;
4348 
4349     proc_tp* save_proc = curr_proc;
4350     curr_proc = type;
4351 
4352     if (t_attrib != NULL) {
4353 	token::remove(t_attrib, t_semi2);
4354     }
4355 
4356     if (use_forward) {
4357         f_tkn = t_proc->copy(type->forward->f_tkn,
4358 			     type->forward->t_semi1->prev);
4359 	token::remove(t_proc, t_semi1->prev);
4360     } else {
4361 	insert_return_type();
4362         var->translate(t_ident);
4363 	insert_params();
4364     }
4365     t_semi3->disable();
4366     if (s_self) {
4367 	s_self->translate(t_class);
4368     }
4369     if (t_dot) {
4370 	t_dot->set_trans("::");
4371     }
4372     if (ctx != ctx_block) {
4373 	global_func_decl_level = f_tkn;
4374 	if (type->n_subproc > 0 && t_class == NULL) { // make forward declaration
4375 	    f_tkn->copy(f_tkn, t_semi1);
4376 	    f_tkn->prepend("\n");
4377 	}
4378     } else {
4379 	f_tkn = f_tkn->prepend("static ");
4380 	if (type->n_subproc > 0) { // make forward declaration
4381 	    global_func_decl_level->copy(f_tkn, t_semi1);
4382 	    global_func_decl_level->prepend("\n");
4383 	}
4384     }
4385     if (var->ring->scope == b_ring::global && use_call_graph && !is_recursive){
4386 	type->make_vars_static();
4387     }
4388 
4389     block->translate(ctx_block);
4390 
4391     t_semi1->disable();
4392     token* first_stmt = t_semi1->next_relevant();
4393     token* lbr = block->body->t_begin;
4394     if (first_stmt != block->body->t_begin) {
4395 	lbr = first_stmt->prepend("{\n");
4396 	lbr->set_pos(block->body->t_begin);
4397 	block->body->t_begin->disable();
4398     }
4399     block->body->t_end->set_bind(lbr);
4400 
4401 
4402     if (language_c) {
4403 	type->undefine(block->body->t_end->prev_relevant());
4404     }
4405     first_stmt = block->body->t_begin->next_relevant();
4406 
4407     type->insert_temporaries(first_stmt);
4408 
4409     if (!language_c) {
4410 	type->declare_conformant_array_bounds(first_stmt);
4411     }
4412     if (type->res_type != NULL)
4413     {
4414 	if( language_c && type->res_type->tag == tp_array) {
4415 	    block->body->t_end->prepend(dprintf("return (%s*)%s_result;\n",
4416 						type->res_type->name,
4417 						type->proc_name))
4418 		->set_bind(first_stmt);
4419 	} else {
4420 	    first_stmt->prepend(dprintf("%s %s_result;\n",
4421 				     type->res_type->name, type->proc_name));
4422 	    block->body->t_end->prepend(dprintf("return %s_result;\n",
4423 						type->proc_name))
4424 		->set_bind(first_stmt);
4425 	}
4426     } else if (type->is_constructor || type->is_destructor) {
4427 	block->body->t_end->prepend("return this;\n")->set_bind(first_stmt);
4428     }
4429     curr_proc = save_proc;
4430     if (ctx == ctx_block)
4431     {
4432         global_func_decl_level->move_region(f_tkn, l_tkn);
4433 	global_func_decl_level->prepend("\n\n");
4434         (new token((char*)0, TKN_BEG_SHIFT, f_tkn->line, f_tkn->pos))->
4435 	  insert_b(f_tkn);
4436 	(new token((char*)0, TKN_END_SHIFT))->insert_a(l_tkn);
4437     }
4438 }
4439 
4440 //
4441 // Type declaration node
4442 //
4443 
4444 
simple_tpd_node(token * tkn)4445 simple_tpd_node::simple_tpd_node(token* tkn) : tpd_node(tpd_simple)
4446 {
4447     this->tkn = tkn;
4448 }
4449 
attrib(int ctx)4450 void simple_tpd_node::attrib(int ctx)
4451 {
4452     sym = b_ring::search_cur(tkn);
4453     if (sym == NULL) {
4454         if (ctx == ctx_reftyp) {
4455             type = new fwd_ref_tp(tkn);
4456 	} else {
4457  	    warning(tkn, "unknown type");
4458 	    type = &void_type;
4459         }
4460     } else {
4461 	type = sym->type;
4462     }
4463 }
4464 
4465 
translate(int ctx)4466 void simple_tpd_node::translate(int ctx)
4467 {
4468     l_tkn = f_tkn = tkn;
4469     if (sym != NULL) {
4470 	sym->translate(tkn);
4471     } else {
4472 	if (ctx == ctx_reftyp) {
4473 	    f_tkn = tkn->prepend("struct ");
4474         }
4475     }
4476 }
4477 
fptr_tpd_node(token * t_proc,param_list_node * params,token * t_coln,tpd_node * ret_type)4478 fptr_tpd_node::fptr_tpd_node(token* t_proc, param_list_node* params,
4479 			     token* t_coln, tpd_node* ret_type)
4480 : tpd_node(tpd_proc)
4481 {
4482     CONS4(t_proc, params, t_coln, ret_type);
4483 }
4484 
4485 
attrib(int ctx)4486 void fptr_tpd_node::attrib(int ctx)
4487 {
4488     if (ret_type) {
4489         ret_type->attrib(ctx);
4490     }
4491     type = new proc_tp(ret_type ? ret_type->type : (tpexpr*)NULL);
4492     if (params) {
4493         proc_tp* save_proc = curr_proc;
4494 	curr_proc = (proc_tp*)type;
4495 	b_ring::push(curr_proc);
4496 	params->attrib(ctx);
4497 	b_ring::pop();
4498 	curr_proc = save_proc;
4499     }
4500 }
4501 
translate(int)4502 void fptr_tpd_node::translate(int)
4503 {
4504     f_tkn = t_proc;
4505     if (ret_type) {
4506         ret_type->translate(ctx_block);
4507 	assert(ret_type->type->name != NULL);
4508 	t_proc->set_trans(ret_type->type->name);
4509 	token::disable(t_coln->prev_relevant()->next, ret_type->l_tkn);
4510     } else {
4511         t_proc->set_trans("void");
4512     }
4513     if (*pascall) {
4514 	t_proc->append(pascall);
4515 	t_proc->append(" ");
4516     }
4517     if (params) {
4518         proc_tp* save_proc = curr_proc;
4519 	curr_proc = (proc_tp*)type;
4520         params->translate(ctx_block);
4521 	curr_proc = save_proc;
4522 	l_tkn = params->rpar;
4523 	t_params = params->lpar;
4524     } else {
4525         t_params = l_tkn = t_proc->append("()");
4526     }
4527 }
4528 
4529 
enum_tpd_node(token * lpar,token_list * items,token * rpar)4530 enum_tpd_node::enum_tpd_node(token* lpar, token_list* items, token* rpar)
4531 : tpd_node(tpd_enum)
4532 {
4533     CONS3(lpar, items, rpar);
4534 }
4535 
attrib(int)4536 void enum_tpd_node::attrib(int)
4537 {
4538     int n = 0;
4539     type = new enum_tp(this);
4540     for (token_list* t = items; t != NULL; t = t->next) {
4541         ((enum_tp*)type)->last = t->var = b_ring::add_cur(t->ident,
4542 							  symbol::s_const,
4543 							  &integer_type);
4544 	t->var->value = n++;
4545 	t->var->flags |= symbol::f_const;
4546 	if (b_ring::curr_b_ring->scope != b_ring::global) {
4547 	    t->var->flags |= symbol::f_static;
4548 	    t->var->ring->make_unique(t->var);
4549 	}
4550     }
4551     ((enum_tp*)type)->n_elems = n;
4552     ((enum_tp*)type)->first = items->var;
4553 }
4554 
4555 
translate(int)4556 void enum_tpd_node::translate(int)
4557 {
4558     f_tkn = lpar->prepend("enum ");
4559     l_tkn = rpar;
4560     for (token_list* t = items; t != NULL; t = t->next) {
4561         t->var->translate(t->ident);
4562 	t->ident->attr |= token::fix_pos;
4563     }
4564     lpar->set_trans("{");
4565     rpar->set_trans("}");
4566 
4567     if (((enum_tp*)type)->max != NULL) {
4568         rpar->prepend(", ");
4569         rpar->prepend(((enum_tp*)type)->max);
4570     }
4571 }
4572 
range_tpd_node(expr_node * low,token * dots,expr_node * high)4573 range_tpd_node::range_tpd_node(expr_node* low, token* dots, expr_node* high)
4574 : tpd_node(tpd_range)
4575 {
4576     CONS3(low, dots, high);
4577 }
4578 
attrib(int)4579 void range_tpd_node::attrib(int)
4580 {
4581     low->attrib(ctx_value);
4582     high->attrib(ctx_value);
4583     range_tp* rtp = new range_tp(this);
4584     long min_value = INT_MIN, max_value = INT_MAX;
4585 
4586     if (low->flags & tn_is_const) {
4587 	min_value = low->value;
4588     }
4589     if (high->flags & tn_is_const) {
4590 	max_value = high->value;
4591     }
4592     if (!(low->flags & high->flags & tn_is_const)) {
4593 	warning(dots, "unable to calculate bounds for range type");
4594     }
4595     rtp->min_value = min_value;
4596     rtp->max_value = max_value;
4597 
4598     if (min_value >= 0 && max_value <= 255)  {
4599 	rtp->name = "unsigned char";
4600 	rtp->size = 1;
4601     } else if(min_value >= -128 && max_value <= 127) {
4602 	rtp->name = "signed char";
4603 	rtp->size = 1;
4604     } else if(min_value >= 0 && max_value <= USHRT_MAX) {
4605 	rtp->name = "unsigned short";
4606 	rtp->size = 2;
4607     } else if(min_value >= SHRT_MIN && max_value <= SHRT_MAX) {
4608 	rtp->name = "short";
4609 	rtp->size = 2;
4610     } else if(min_value >= 0 && (unsigned long)max_value <= UINT_MAX) {
4611 	rtp->name = "unsigned";
4612 	rtp->size = 4;
4613     } else if(min_value >= INT_MIN && max_value <= INT_MAX) {
4614 	rtp->name = "int";
4615 	rtp->size = 4;
4616     } else {
4617 	rtp->name = "integer";
4618 	rtp->size = 4;
4619     }
4620     type = rtp;
4621 }
4622 
4623 
translate(int)4624 void range_tpd_node::translate(int)
4625 {
4626     low->translate(ctx_value);
4627     high->translate(ctx_value);
4628 
4629     token* first = low->f_tkn->get_first_token();
4630 
4631     f_tkn = l_tkn = low->f_tkn->prepend(type->name);
4632     if (((range_tp*)type)->min != NULL) {
4633 	if (language_c) {
4634 	    low->f_tkn->prepend(dprintf("\n#define %s ",
4635 					((range_tp*)type)->min));
4636 	    dots->disable();
4637 	    high->f_tkn->prepend(dprintf("\n#define %s ",
4638 					((range_tp*)type)->max));
4639 	    token* next = high->l_tkn->next_relevant();
4640 	    if (next->tag == TKN_SEMICOLON) {
4641 		next->set_trans("\n");
4642 	    } else {
4643 		high->l_tkn->append("\n");
4644 	    }
4645 	} else {
4646 	    low->f_tkn->prepend("\n");
4647 	    low->f_tkn->prepend("const int ")->set_pos(first);
4648 	    low->f_tkn->prepend(((range_tp*)type)->min);
4649 	    low->f_tkn->prepend(" = ");
4650 	    low->l_tkn->append(";");
4651 	    dots->disable();
4652 	    high->f_tkn->prepend("\n");
4653 	    high->f_tkn->prepend("const int ")->set_pos(first);
4654 	    high->f_tkn->prepend(((range_tp*)type)->max);
4655 	    high->f_tkn->prepend(" = ");
4656 	    token* next = high->l_tkn->next_relevant();
4657 	    if (next->tag != TKN_SEMICOLON) {
4658 		next = high->l_tkn->append(";");
4659 		next->tag = TKN_SEMICOLON;
4660 	    }
4661 	}
4662     } else {
4663 	token::remove(low->f_tkn, high->l_tkn);
4664     }
4665 }
4666 
4667 
4668 static array_tp* curr_array = NULL;
4669 
type_index_node(tpd_node * tpd)4670 type_index_node::type_index_node(tpd_node* tpd)
4671 {
4672     this->tpd = tpd;
4673 }
4674 
attrib(int ctx)4675 void type_index_node::attrib(int ctx)
4676 {
4677     tpd->attrib(ctx);
4678     assert(tpd->tag == tpd_node::tpd_simple);
4679 }
4680 
translate(int)4681 void type_index_node::translate(int)
4682 {
4683     f_tkn = l_tkn = ((simple_tpd_node*)tpd)->tkn;
4684     tpexpr* type = tpd->type->get_typedef();
4685 
4686     if (language_c) {
4687 	switch(type->tag) {
4688 	  case tp_bool:
4689 	    f_tkn->set_trans("2");
4690 	    curr_array->set_dim("0", "1");
4691 	    break;
4692 	  case tp_range:
4693 	    { range_tp* range = (range_tp*)type->get_typedef();
4694   	      if (no_index_decrement) {
4695 		  f_tkn->set_trans(dprintf("%s+1", range->max));
4696 	      } else {
4697 		  f_tkn->set_trans(dprintf("%s-%s+1", range->max, range->min));
4698 	      }
4699 	      curr_array->set_dim(range->min, range->max);
4700 	    }
4701 	    break;
4702 	  case tp_char:
4703 	    f_tkn->set_trans("256");
4704 	    curr_array->set_dim(" -128", "127");
4705 	    break;
4706 	  case tp_enum:
4707 	    f_tkn->set_trans(((enum_tp*)type->get_typedef())->max);
4708 	    curr_array->set_dim("0", dprintf("%s-1",
4709 				       ((enum_tp*)type->get_typedef())->max));
4710 	    break;
4711 	  default:
4712 	    warning(f_tkn, "Illegal type of index");
4713 	}
4714     } else {
4715 	switch(type->tag) {
4716 	  case tp_bool:
4717 	    f_tkn->set_trans("false,true");
4718 	    break;
4719 	  case tp_char:
4720 	    f_tkn->set_trans("-128,127");
4721 	    break;
4722 	  case tp_range:
4723 	    f_tkn->set_trans(dprintf("%s,%s",
4724 				     ((range_tp*)type->get_typedef())->min,
4725 				     ((range_tp*)type->get_typedef())->max));
4726 	    break;
4727 	  case tp_enum:
4728 	    f_tkn->set_trans(dprintf("0,%s",
4729 				     ((enum_tp*)type->get_typedef())->max));
4730 	    break;
4731 	  default:
4732 	    warning(f_tkn, "Illegal type of index");
4733 	}
4734     }
4735 
4736 }
4737 
range_index_node(expr_node * low,token * dots,expr_node * high)4738 range_index_node::range_index_node(expr_node *low, token* dots,
4739 				   expr_node* high)
4740 {
4741     CONS3(low, dots, high);
4742 }
4743 
attrib(int)4744 void range_index_node::attrib(int)
4745 {
4746     low->attrib(ctx_value);
4747     high->attrib(ctx_value);
4748 }
4749 
translate(int)4750 void range_index_node::translate(int)
4751 {
4752     low->translate(ctx_value);
4753     high->translate(ctx_value);
4754     f_tkn = low->f_tkn;
4755     l_tkn = high->l_tkn;
4756 
4757     if (language_c) {
4758 	curr_array->set_dim(NULL, NULL, low, high);
4759 	if (no_index_decrement) {
4760 	    token::remove(low->f_tkn, high->f_tkn->prev);
4761 	    l_tkn = high->l_tkn->append("+1");
4762 	    return;
4763 	}
4764 	if (low->is_const_literal()) {
4765 	    if (low->value == 1) {
4766 		token::remove(low->f_tkn, high->f_tkn->prev);
4767 		return;
4768 	    }
4769 	    if (high->is_const_literal()) {
4770 		token::remove(low->f_tkn, high->f_tkn->prev);
4771 		high->f_tkn->set_trans(dprintf("%d", high->value - low->value + 1));
4772 		return;
4773 	    }
4774 	}
4775 	token::swap(low->f_tkn, low->l_tkn, high->f_tkn, high->l_tkn);
4776 	dots->set_trans("-");
4777 	f_tkn = high->f_tkn;
4778 	l_tkn = low->l_tkn->append("+1");
4779     } else { // language C++
4780 	dots->set_trans(",");
4781     }
4782 }
4783 
conformant_index_node(token * low,token * dots,token * high,token * coln,tpd_node * tpd)4784 conformant_index_node::conformant_index_node(token *low, token *dots,
4785 				             token *high, token *coln,
4786 		                             tpd_node* tpd)
4787 {
4788     CONS5(low, dots, high, coln, tpd);
4789 }
4790 
attrib(int)4791 void conformant_index_node::attrib(int)
4792 {
4793     symbol *l = b_ring::add_cur(low, symbol::s_const, &integer_type);
4794     symbol *h = b_ring::add_cur(high, symbol::s_const, &integer_type);
4795     l->flags |= symbol::f_val_param;
4796     h->flags |= symbol::f_val_param;
4797     curr_array->set_conformant_dim(l, h);
4798 }
4799 
translate(int)4800 void conformant_index_node::translate(int)
4801 {
4802 
4803     // last and first tokens are not calculated here since it is not possible
4804     // (and not necessary)
4805 }
4806 
array_tpd_node(token * t_packed,token * t_array,token * t_lbr,idx_node * indices,token * t_rbr,token * t_of,tpd_node * eltd)4807 array_tpd_node::array_tpd_node(token *t_packed, token *t_array,
4808                                token* t_lbr, idx_node *indices,
4809  			       token* t_rbr, token* t_of, tpd_node *eltd)
4810 : tpd_node(tpd_array)
4811 {
4812     CONS7(t_packed, t_array, t_lbr, indices, t_rbr, t_of, eltd);
4813 }
4814 
set_indices_attrib(idx_node * idx)4815 void array_tpd_node::set_indices_attrib(idx_node* idx)
4816 {
4817     if (idx->next) {
4818 	set_indices_attrib(idx->next);
4819     }
4820     type = curr_array = new array_tp(type, this);
4821     idx->attrib(ctx_component);
4822 }
4823 
attrib(int)4824 void array_tpd_node::attrib(int)
4825 {
4826     eltd->attrib(ctx_component);
4827     type = eltd->type;
4828     set_indices_attrib(indices);
4829 }
4830 
translate(int ctx)4831 void array_tpd_node::translate(int ctx)
4832 {
4833     f_tkn = t_array;
4834 
4835     if (t_packed) {
4836 	t_packed->disable();
4837     }
4838     eltd->translate(ctx_component);
4839 
4840     if (language_c) {
4841 	token::disable(t_array, t_lbr->prev);
4842 	token::disable(t_rbr->next, eltd->f_tkn->prev);
4843 	f_tkn = t_lbr;
4844 	l_tkn = t_rbr;
4845 	if (eltd->tag == tpd_array) {
4846 	    l_tkn = eltd->l_tkn;
4847 	    eltd = ((array_tpd_node*)eltd)->eltd;
4848 	}
4849 	if (type->tag == tp_dynarray) {
4850 	    token::remove(t_lbr, t_rbr);
4851 	    f_tkn = eltd->f_tkn;
4852 	    l_tkn = eltd->l_tkn;
4853 	} else {
4854 	    curr_array = (array_tp*)type;
4855 
4856 	    for (idx_node* idx = indices; idx != NULL; idx = idx->next) {
4857 		idx->translate(ctx);
4858 		if (idx->next) {
4859 		    token* comma = idx->l_tkn->next_relevant();
4860 		    assert(comma->tag == TKN_COMMA);
4861 		    token::disable(idx->l_tkn->next,
4862 				   comma->next_relevant()->prev);
4863 		    idx->l_tkn->append("][");
4864 		    curr_array = (array_tp*)curr_array->elem_type;
4865 		}
4866 	    }
4867 	}
4868     } else { // C++
4869 	if (type->tag == tp_dynarray) {
4870 
4871 	    if (eltd->type->tag == tp_dynarray) {
4872 		array_tpd_node* atp = (array_tpd_node*)eltd;
4873 		eltd = atp->eltd;
4874 		t_of = atp->t_of;
4875 		t_array->set_trans("conf_matrix");
4876 	    } else {
4877 		t_array->set_trans(indices->next == NULL
4878 				   ? (char *) "conf_array" : (char *) "conf_matrix");
4879 	    }
4880 	    token::disable(t_array->next, eltd->f_tkn->prev);
4881 	    eltd->f_tkn->prepend("<");
4882 	    l_tkn = eltd->l_tkn->append(">");
4883 
4884 	} else {
4885 
4886 	    for (idx_node* idx = indices; idx != NULL; idx = idx->next) {
4887 		idx->translate(ctx_component);
4888 	    }
4889 	    t_lbr->set_trans("<");
4890 	    t_rbr->set_trans(",");
4891 	    if (t_array->next != t_lbr) {
4892 		token::disable(t_array->next, t_lbr->prev);
4893 	    }
4894 	    if (indices->next == NULL && eltd->tag == tpd_array && !((array_tp*)eltd->type)->elem_type->is_array()) {
4895 		token::disable(t_rbr->next, ((array_tpd_node*)eltd)->t_lbr);
4896 		t_array->set_trans("matrix");
4897 		l_tkn = eltd->l_tkn;
4898 	    } else {
4899 		if (indices->next != NULL && indices->next->next == NULL) {
4900 		    t_array->set_trans("matrix");
4901 		}
4902 		token::disable(t_rbr->next, eltd->f_tkn->prev);
4903 		l_tkn = eltd->l_tkn->append(">");
4904 	    }
4905 	}
4906     }
4907 }
4908 
4909 //-------------------------------------------------------------------
4910 
varying_tpd_node(token * t_string,token * t_lbr,expr_node * size,token * t_rbr)4911 varying_tpd_node::varying_tpd_node(token *t_string,
4912 				   token* t_lbr, expr_node *size,
4913 				   token* t_rbr)
4914 : tpd_node(tpd_string)
4915 {
4916     if (language_c) {
4917 	error(t_string,"Varying string are supported only for C++ conversion");
4918     }
4919     CONS4(t_string, t_lbr, size, t_rbr);
4920 }
4921 
attrib(int ctx)4922 void varying_tpd_node::attrib(int ctx)
4923 {
4924     size->attrib(ctx_component);
4925     if (use_c_strings && (ctx == ctx_record || ctx == ctx_component)) {
4926 	type = &string_type;
4927     } else {
4928 	type = &varying_string_type;
4929     }
4930 }
4931 
translate(int)4932 void varying_tpd_node::translate(int)
4933 {
4934     f_tkn = t_string;
4935     l_tkn = t_rbr;
4936     if (type->tag == tp_string) {
4937 	t_string->set_trans("asciiz");
4938 	token::disable(t_lbr, t_rbr);
4939     } else {
4940 	size->translate(ctx_component);
4941 	t_lbr->set_trans("<");
4942 	t_rbr->set_trans(">");
4943 	t_string->set_trans("varying_string");
4944     }
4945 }
4946 //-------------------------------------------------------------------
4947 
string_tpd_node(token * t_string)4948 string_tpd_node::string_tpd_node(token *t_string) : tpd_node(tpd_string)
4949 {
4950     if (language_c) {
4951 	error(t_string,"Varying string are supported only for C++ conversion");
4952     }
4953     CONS1(t_string);
4954 }
4955 
attrib(int ctx)4956 void string_tpd_node::attrib(int ctx)
4957 {
4958     if (use_c_strings && (ctx == ctx_record || ctx == ctx_component)) {
4959 	type = &string_type;
4960     } else {
4961 	type = &varying_string_type;
4962     }
4963 }
4964 
translate(int)4965 void string_tpd_node::translate(int)
4966 {
4967     f_tkn = l_tkn = t_string;
4968     if (type->tag == tp_string) {
4969 	f_tkn->set_trans("asciiz");
4970     }
4971 }
4972 
4973 //----------------------------------------------------------------------
4974 
ptr_tpd_node(token * tkn_ref,tpd_node * tpd)4975 ptr_tpd_node::ptr_tpd_node(token* tkn_ref, tpd_node* tpd)
4976 : tpd_node(tpd_ref)
4977 {
4978     CONS2(tkn_ref, tpd);
4979 }
4980 
attrib(int)4981 void ptr_tpd_node::attrib(int)
4982 {
4983     tpd->attrib(ctx_reftyp);
4984     type = (tpd->type->tag == tp_fwd_ref)
4985 	? tpd->type : new ref_tp(tpd->type, this);
4986 }
4987 
translate(int)4988 void ptr_tpd_node::translate(int)
4989 {
4990     tkn_ref->disable();
4991     tpd->translate(ctx_reftyp);
4992     f_tkn = tpd->f_tkn;
4993     l_tkn = tpd->l_tkn->append("*");
4994 }
4995 
variant_node(expr_node * tag_list,token * t_coln,token * t_lpar,field_list_node * fields,token * t_rpar)4996 variant_node::variant_node(expr_node* tag_list, token* t_coln,
4997 			  token* t_lpar, field_list_node* fields,
4998 			  token* t_rpar)
4999 {
5000     CONS5(tag_list, t_coln, t_lpar, fields, t_rpar);
5001     next = NULL;
5002 }
5003 
5004 int variant_node::number;
5005 
attrib(int ctx)5006 void variant_node::attrib(int ctx)
5007 {
5008     tag_list->attrib(ctx);
5009 
5010     if (fields->is_single()) {
5011 	fields->attrib(ctx);
5012     } else {
5013 	char* save_path = struct_path;
5014 	number += 1;
5015         if (tag_list->tag == tn_atom) {
5016 	    token* tag = ((atom_expr_node*)tag_list)->tkn;
5017 	    struct_name = isdigit(tag->out_text[0])
5018 	        ? dprintf("s%s", tag->out_text)
5019 		: dprintf("s_%s", tag->out_text);
5020 	} else {
5021 	    struct_name = dprintf("s%d", number);
5022         }
5023 	struct_path = dprintf("%s%s.", struct_path, struct_name);
5024 	fields->attrib(ctx);
5025 	struct_path = save_path;
5026     }
5027 }
5028 
translate(int ctx)5029 void variant_node::translate(int ctx)
5030 {
5031     tag_list->translate(ctx);
5032     f_tkn = t_lpar;
5033     l_tkn = t_rpar;
5034     fields->translate(ctx);
5035 
5036     if (fields->is_single()) {
5037 	token* t = t_lpar->next_relevant();
5038 	t_lpar->disable();
5039 	t_rpar->disable();
5040 	if (t->line == tag_list->f_tkn->line) {
5041 	    t->set_pos(tag_list->f_tkn);
5042         }
5043 	swallow_semicolon();
5044     } else {
5045 	t_lpar->set_trans("struct {");
5046 	t_rpar->set_trans(dprintf("} %s", struct_name));
5047 	if (t_lpar->line == tag_list->f_tkn->line) {
5048 	    t_lpar->set_pos(tag_list->f_tkn);
5049 	}
5050 	force_semicolon();
5051     }
5052     if (comment_tags) {
5053 	tag_list->f_tkn->prepend("/*");
5054 	t_lpar->prepend("*/");
5055     } else {
5056 	token::disable(tag_list->f_tkn, t_lpar->prev);
5057     }
5058 }
5059 
5060 
5061 
selector_node(token * tag_field,token * coln,tpd_node * tag_type)5062 selector_node::selector_node(token* tag_field, token* coln,
5063 			     tpd_node* tag_type)
5064 {
5065     CONS3(tag_field, coln, tag_type);
5066     var = NULL;
5067 }
5068 
variant_part_node(token * t_case,selector_node * selector,token * t_of,variant_node * variants)5069 variant_part_node::variant_part_node(token* t_case, selector_node* selector,
5070 				     token* t_of, variant_node* variants)
5071 {
5072     CONS4(t_case, selector, t_of, variants);
5073 }
5074 
attrib(int ctx)5075 void variant_part_node::attrib(int ctx)
5076 {
5077     selector->tag_type->attrib(ctx);
5078     if (selector->tag_field != NULL) {
5079 	selector->var = b_ring::add_cur(selector->tag_field,
5080 					symbol::s_var,
5081 					selector->tag_type->type);
5082 	if (*struct_path) {
5083 	    selector->var->path = struct_path;
5084 	}
5085     }
5086     if (language_c && ctx != ctx_union) {
5087 	char* save_path = struct_path;
5088 	struct_path = dprintf("%su.", struct_path);
5089 	for (variant_node* vp = variants; vp != NULL; vp = vp->next) {
5090 	    vp->attrib(ctx);
5091 	}
5092 	struct_path = save_path;
5093     } else {
5094 	for (variant_node* vp = variants; vp != NULL; vp = vp->next) {
5095 	    vp->attrib(ctx);
5096 	}
5097     }
5098 }
5099 
translate(int ctx)5100 void variant_part_node::translate(int ctx)
5101 {
5102     f_tkn = t_case;
5103     l_tkn = t_of;
5104     for (variant_node* vp = variants; vp != NULL; vp = vp->next) {
5105 	vp->translate(ctx);
5106 	l_tkn = vp->l_tkn;
5107     }
5108 
5109     selector->tag_type->translate(ctx);
5110 
5111     if (selector->tag_field != NULL) {
5112 	assert(selector->tag_type->type->name != NULL);
5113 	t_case->set_trans(selector->tag_type->type->name);
5114 	if (selector->tag_field->next != t_of) {
5115 	    token::disable(selector->tag_field->next, t_of->prev);
5116 	}
5117 	selector->tag_field->append(";\n");
5118 	t_of->set_trans("union {");
5119 	t_of->set_bind(t_case);
5120     } else {
5121 	t_case->set_trans("union ");
5122 	t_case->append("{");
5123 	token::disable(t_case->next->next, t_of);
5124     }
5125     l_tkn = l_tkn->append("\n");
5126     if (language_c && ctx != ctx_union) {
5127 	l_tkn = l_tkn->append("} u");
5128     } else {
5129 	l_tkn = l_tkn->append("}");
5130     }
5131     l_tkn->set_bind(t_case);
5132     if (ctx != ctx_union) {
5133 	force_semicolon();
5134     }
5135 }
5136 
field_list_node(var_decl_node * fix_part,variant_part_node * var_part)5137 field_list_node::field_list_node(var_decl_node* fix_part,
5138 				 variant_part_node* var_part)
5139 {
5140     CONS2(fix_part, var_part);
5141 }
5142 
is_single()5143 int field_list_node::is_single()
5144 {
5145     return (var_part == NULL && (fix_part == NULL ||
5146 	(fix_part->vars->next == NULL && fix_part->next == NULL)));
5147 }
5148 
attrib(int)5149 void field_list_node::attrib(int)
5150 {
5151     ctx = (smart_union && fix_part == NULL && var_part != NULL
5152 	   && var_part->selector->tag_field == NULL)
5153 	? ctx_union : ctx_record;
5154 
5155     for (decl_node *dcl = fix_part; dcl != NULL; dcl = dcl->next) {
5156 	dcl->attrib(ctx);
5157     }
5158     if (var_part) {
5159 	int save_number = variant_node::number;
5160 	variant_node::number = 0;
5161 	var_part->attrib(ctx);
5162 	variant_node::number = save_number;
5163     }
5164 }
5165 
translate(int)5166 void field_list_node::translate(int)
5167 {
5168     f_tkn = l_tkn = NULL;
5169 
5170     for (decl_node *dcl = fix_part; dcl != NULL; dcl = dcl->next) {
5171 	dcl->translate(ctx);
5172 	if (f_tkn == NULL) f_tkn = dcl->f_tkn;
5173 	l_tkn = dcl->l_tkn;
5174     }
5175     if (var_part) {
5176 	var_part->translate(ctx);
5177 	if (f_tkn == NULL) f_tkn = var_part->f_tkn;
5178 	l_tkn = var_part->l_tkn;
5179     }
5180     if (l_tkn != NULL) {
5181 	force_semicolon();
5182     }
5183 }
5184 
object_tpd_node(token * t_object,token * t_lbr,token * t_superclass,token * t_rbr,decl_node * fields,token * t_end)5185 object_tpd_node::object_tpd_node(token* t_object,
5186 				 token* t_lbr, token* t_superclass, token* t_rbr,
5187 				 decl_node* fields, token* t_end)
5188 : tpd_node(tpd_object)
5189 {
5190     CONS6(t_object, t_lbr, t_superclass, t_rbr, fields, t_end);
5191 }
5192 
attrib(int)5193 void object_tpd_node::attrib(int)
5194 {
5195     if (t_superclass != NULL) {
5196 	super = b_ring::search_cur(t_superclass);
5197 	if (super == NULL) {
5198 	    warning("Base class %s not defined\n", t_superclass->out_text);
5199 	    type = new object_tp(this);
5200 	} else {
5201 	    type = new object_tp(this, (object_tp*)super->type->get_typedef());
5202 	}
5203     } else {
5204 	type = new object_tp(this);
5205     }
5206     b_ring::push((object_tp*)type);
5207     for (decl_node* dcl = fields; dcl != NULL; dcl = dcl->next) {
5208 	dcl->attrib(ctx_object);
5209     }
5210     b_ring::pop();
5211 }
5212 
translate(int)5213 void object_tpd_node::translate(int)
5214 {
5215     f_tkn = t_object;
5216     l_tkn = t_end;
5217     if (t_superclass != NULL) {
5218 	if (super) {
5219 	    super->translate(t_superclass);
5220 	}
5221 	t_lbr->set_trans(" : public ");
5222 	t_rbr->set_trans(" {\n");
5223 	t_rbr->append("public:")->set_bind(t_object);
5224     } else {
5225 	t_object->append(" {\n")->append("public:")->set_bind(t_object);
5226     }
5227 
5228     for (decl_node* dcl = fields; dcl != NULL; dcl = dcl->next) {
5229 	dcl->translate(ctx_object);
5230     }
5231     t_object->set_trans("class ");
5232     t_end->set_trans("}");
5233     t_end->set_bind(t_object);
5234 }
5235 
5236 
record_tpd_node(token * t_packed,token * t_record,field_list_node * fields,token * t_end)5237 record_tpd_node::record_tpd_node(token* t_packed, token* t_record,
5238 				 field_list_node* fields, token* t_end)
5239 : tpd_node(tpd_record)
5240 {
5241     CONS4(t_packed, t_record, fields, t_end);
5242 }
5243 
attrib(int ctx)5244 void record_tpd_node::attrib(int ctx)
5245 {
5246     type = new record_tp(this);
5247     static record_tpd_node* cur_outer;
5248     outer = cur_outer;
5249     cur_outer = this;
5250     char* save_path = struct_path;
5251     struct_path = "";
5252     b_ring::push((record_tp*)type);
5253     fields->attrib(ctx);
5254     ((record_tp*)type)->calc_flags();
5255     b_ring::pop();
5256     struct_path = save_path;
5257     cur_outer = outer;
5258 }
5259 
translate(int ctx)5260 void record_tpd_node::translate(int ctx)
5261 {
5262     fields->translate(ctx);
5263     f_tkn = t_record;
5264     l_tkn = t_end;
5265     if (smart_union && fields->fix_part == NULL && fields->var_part != NULL
5266 	&& fields->var_part->selector->tag_field == NULL)
5267     {
5268 	fields->var_part->t_case->set_pos(t_record);
5269         t_record->disappear();
5270 	t_end->disappear();
5271 	swallow_semicolon();
5272 	f_tkn = t_record = fields->var_part->t_case;
5273 	l_tkn = t_end = fields->var_part->l_tkn;
5274     } else {
5275 	t_record->set_trans("struct ");
5276 	t_record->append("{");
5277 	t_end->set_trans("}");
5278 	t_end->set_bind(t_record);
5279     }
5280 
5281     if (t_packed) {
5282       	t_packed->disable();
5283     }
5284 }
5285 
5286 
assign_name()5287 void record_tpd_node::assign_name()
5288 {
5289     static int anonymous_struct_counter = 0;
5290 
5291     assert(tag == tpd_record);
5292 
5293     char* name = dprintf("A%d", ++anonymous_struct_counter);
5294     t_record->append(dprintf("%s ", name));
5295 
5296     if (language_c) {
5297 	type->name = dprintf("%s%s", t_record->out_text, name);
5298     } else {
5299 	if (outer != NULL) {
5300 	    if (outer->type->name == NULL) {
5301 		outer->assign_name();
5302 	    }
5303 	    type->name = dprintf("%s::%s", outer->type->name, name);
5304 	} else {
5305 	    type->name = name;
5306 	}
5307     }
5308 }
5309 
file_tpd_node(token * t_packed,token * t_file,token * t_of,tpd_node * recordtp)5310 file_tpd_node::file_tpd_node(token* t_packed, token* t_file, token* t_of, tpd_node* recordtp)
5311 : tpd_node(tpd_file)
5312 {
5313     CONS4(t_packed, t_file, t_of, recordtp);
5314 }
5315 
attrib(int ctx)5316 void file_tpd_node::attrib(int ctx)
5317 {
5318     recordtp->attrib(ctx);
5319     type = new file_tp(recordtp->type, this);
5320 }
5321 
translate(int ctx)5322 void file_tpd_node::translate(int ctx)
5323 {
5324     recordtp->translate(ctx);
5325     f_tkn = t_file;
5326     token::disable(t_file->next, recordtp->f_tkn->prev);
5327 
5328     if (t_packed) {
5329        	t_packed->disable();
5330     }
5331     if (language_c) {
5332 	recordtp->f_tkn->prepend("(");
5333 	l_tkn = recordtp->l_tkn->append(")");
5334     } else {
5335 	recordtp->f_tkn->prepend("<");
5336 	l_tkn = recordtp->l_tkn->append(">");
5337     }
5338 }
5339 
5340 
set_tpd_node(token * t_packed,token * t_set,token * t_of,tpd_node * elemtp)5341 set_tpd_node::set_tpd_node(token* t_packed, token* t_set, token* t_of,
5342 			   tpd_node* elemtp)
5343 : tpd_node(tpd_set)
5344 {
5345     CONS4(t_packed, t_set, t_of, elemtp);
5346 }
5347 
attrib(int ctx)5348 void set_tpd_node::attrib(int ctx)
5349 {
5350     elemtp->attrib(ctx);
5351     type = new set_tp(elemtp->type);
5352 }
5353 
translate(int ctx)5354 void set_tpd_node::translate(int ctx)
5355 {
5356     elemtp->translate(ctx);
5357     l_tkn = f_tkn = t_set;
5358     if (t_packed) {
5359 	t_packed->disable();
5360     }
5361     if (!language_c  && elemtp->type->tag == tp_enum) {
5362 	t_set->set_trans("set_of_enum(");
5363 	token::disable(t_set->next, elemtp->f_tkn->prev);
5364 	l_tkn = elemtp->l_tkn->append(")");
5365     } else {
5366 	if (language_c && short_set) {
5367 	    int card = ((set_tp*)type)->card();
5368 	    if (card <= 16) t_set->set_trans("set16");
5369 	    else if (card <= 32) t_set->set_trans("set32");
5370 	}
5371 	token::disable(t_set->next, elemtp->l_tkn);
5372     }
5373 }
5374 
5375