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