PIPS
statement.c
Go to the documentation of this file.
1 /*
2 
3  $Id: statement.c 23260 2016-11-02 07:38:51Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 
34 #include "genC.h"
35 #include "parser_private.h"
36 #include "linear.h"
37 #include "ri.h"
38 #include "ri-util.h"
39 
40 #include "misc.h"
41 #include "properties.h"
42 
43 #include "syntax.h"
44 #include "syn_yacc.h"
45 
46 
47 
48 /* the purpose of the following data structure is to associate labels to
49 instructions. The data structure contains a string (the label's name)
50 and a statement (the statement which the label is attached to). */
51 
52 #define INITIAL_STMTHEAP_BUFFER_SIZE 10
53 
54 typedef struct {
55  string l; /* the name of the label */
56  statement s; /* the statement attached to l */
57 } stmt;
58 
61 static int CurrentStmt = 0;
62 
63 static void
65 {
66  if (StmtHeap_buffer_size!=0) return; /* if needed */
67  pips_debug(9, "allocating StmtHeap buffer\n");
70  pips_assert("malloc ok", StmtHeap_buffer);
71 }
72 
73 static void
75 {
76  pips_debug(9, "resizing StmtHeap buffer\n");
77  pips_assert("buffer initialized", StmtHeap_buffer_size>0);
79  StmtHeap_buffer = (stmt*) realloc(StmtHeap_buffer,
80  sizeof(stmt)*StmtHeap_buffer_size);
81  pips_assert("realloc ok", StmtHeap_buffer);
82 }
83 
84 void
86 {
87  CurrentStmt = 0;
88 }
89 
90 /* this functions looks up in table StmtHeap for the statement s whose
91 label is l. */
92 
93 statement
95 string l;
96 {
97  int i;
98 
99  for (i = 0; i < CurrentStmt; i++)
100  if (strcmp(l, StmtHeap_buffer[i].l) == 0)
101  return(StmtHeap_buffer[i].s);
102 
103  return(statement_undefined);
104 }
105 
106 
107 
108 /* this function looks for undefined labels. a label is undefined if a
109 goto to that label has been encountered and if no statement with this
110 label has been parsed. */
111 
112 void
114 {
115  int i;
116  int MustStop = false;
117 
118  for (i = 0; i < CurrentStmt; i++) {
119  statement s = StmtHeap_buffer[i].s;
121  MustStop = true;
122  user_warning("CheckAndInitializeStmt", "Undefined label \"%s\"\n",
124  }
125  }
126 
127  if (MustStop) {
128  ParserError("CheckAndInitializeStmt", "Undefined label(s)\n");
129  }
130  else {
131  CurrentStmt = 0;
132  }
133 }
134 
135 
136 
137 /* this function stores a new association in table StmtHeap: the label
138 of statement s is e. */
139 
140 void
141 NewStmt(e, s)
142 entity e;
143 statement s;
144 {
146 
147  pips_assert("The empty label is not associated to a statement",
149 
150  pips_assert("Label e is the label of statement s", e==statement_label(s));
151 
153  user_log("NewStmt: duplicate label: %s\n", entity_name(e));
154  ParserError("NewStmt", "duplicate label\n");
155  }
156 
159 
162  CurrentStmt += 1;
163 }
164 
165 
166 
167 /* The purpose of the following data structure is to build the control
168 structure of the procedure being analyzed. each time a control statement
169 (do loop, block if, ...) is analyzed, a new block is created and pushed
170 on the block stack. regular statement (assign, goto, return, ...) are
171 linked to the block that is on the top of the stack. blocks are removed
172 from the stack when the corresponding end statement is encountered
173 (endif, end of loop, ...).
174 
175 The block ending statements are ELSE, ENDIF,...
176 
177 There does not seem to be any limit on the nesting level in Fortran standard.
178 MAXBLOCK is set to "large" value for our users. The IF/THEN/ELSEIF construct is replaced by nested IF/ELSE statements which increases the nesting level observed by the source reader.
179 
180 Fabien Coelho suggests to refactor this part of the code with a Newgen stack automatically reallocated on overflow:
181 
182 stack s = stack_make(statement_domain, 0, 0);
183 stack_push(e, s);
184 e = stack_pop(s);
185 while (!stack_empty_p(s)) { ... }
186 stack_free(s);
187 */
188 
189 #define MAXBLOCK 200
190 
191 typedef struct block {
192  instruction i; /* the instruction that contains this block */
193  string l; /* the expected statement which will end this block */
194  cons * c; /* the list of statements contained in this block */
195  int elsifs ; /* ELSEIF statements are desugared as nested IFs. They
196  must be counted to generate the effect of the proper
197  number of ENDIF */
201 
202 void
204 {
205  CurrentBlock = 0;
206 }
207 
208 bool
210 {
211  return(CurrentBlock == 0);
212 }
213 
214 bool
216 {
217  return(CurrentBlock == MAXBLOCK);
218 }
219 
220 void
222 instruction i;
223 string l;
224 {
225  if (IsBlockStackFull())
226  ParserError("PushBlock", "top of stack reached\n");
227 
228  pips_assert("PushBlock", instruction_block_p(i));
229 
230  BlockStack[CurrentBlock].i = i;
231  BlockStack[CurrentBlock].l = l;
232  BlockStack[CurrentBlock].c = NULL;
233  BlockStack[CurrentBlock].elsifs = 0;
234  CurrentBlock += 1;
235 }
236 
239 {
240  if (IsBlockStackEmpty())
241  ParserError("PopBlock", "bottom of stack reached\n");
242 
243  return(BlockStack[--CurrentBlock].i);
244 }
245 
246 
247 ␌
248 /* This functions creates a label. LABEL_PREFIX is added to its name, for
249  * integer constants and labels not to have the same name space.
250  *
251  * If an empty string is passed, the empty label seems to be returned
252  * since EMPTY_LABEL_NAME is defined as LABEL_PREFIX in ri-util-local.h
253  * (FI, 5 March 1998)
254  */
255 
256 entity
258 const char* s;
259 {
260  entity l;
261  static char *name = NULL ;
262 
263  if( name == NULL ) {
264  name = (char *)malloc( LABEL_SIZE+sizeof(LABEL_PREFIX) ) ;
265  }
266  debug(5, "MakeLabel", "\"%s\"\n", s);
267 
268  strcpy(name, LABEL_PREFIX);
269  strcat(name, s);
270 
271  l = FindOrCreateEntity( (strcmp( name, LABEL_PREFIX )==0) ?
273  CurrentPackage, name);
274 
275  if (entity_type(l) == type_undefined) {
276  debug(5, "MakeLabel", "%s\n", name);
281  }
282  else {
283  debug(5, "MakeLabel", "%s already exists\n", name);
284  }
285  return(l);
286 }
287 
288 statement
290 entity l;
291 instruction i;
292 {
293  statement s;
294 
295  debug(9, "MakeNewLabelledStatement", "begin for label \"%s\" and instruction %s\n",
297 
298  if(instruction_loop_p(i) && get_bool_property("PARSER_SIMPLIFY_LABELLED_LOOPS")) {
301 
302  statement_number(ls) = get_statement_number();//get_next_statement_number();
303  NewStmt(l, c);
305  CONS(STATEMENT, ls, NIL)));
306  }
307  else if(instruction_block_p(i)) {
308  /* Associate label to the first statement in the block because
309  * block cannot be labelled.
310  */
312 
313  statement_label(s1) = l;
314  NewStmt(l, s1);
320  }
321  else {
322  s = make_statement(l,
323  (instruction_goto_p(i))?
324  STATEMENT_NUMBER_UNDEFINED : get_statement_number(),//get_next_statement_number(),
328  NewStmt(l, s);
329  }
330 
331  debug(9, "MakeNewLabelledStatement", "end for label \"%s\"\n",
332  label_local_name(l));
333 
334  return s;
335 }
336 
337 statement
339 statement s;
340 instruction i;
341 {
343 
344  debug(9, "ReuseLabelledStatement", "begin for label \"%s\"\n",
346 
347  pips_assert("Should have no number",
349  pips_assert("The statement instruction should be undefined",
351 
352  if(instruction_loop_p(i) && get_bool_property("PARSER_SIMPLIFY_LABELLED_LOOPS")) {
353  /* Comments probably are lost... */
356 
357  statement_number(ls) = get_statement_number();//get_next_statement_number();
358  statement_instruction(s) = c;
359 
360  new_s = instruction_to_statement(
363  CONS(STATEMENT, ls, NIL)))));
364  }
365  else if(instruction_block_p(i)) {
366  /* Here, you are in trouble because the label cannot be carried
367  * by the block. It should be carried by the first statement of
368  * the block... which has already been allocated.
369  * This only should occur with desugared constructs because they
370  * must bypass the MakeStatement() module to handle statement
371  * numbering properly.
372  *
373  * Reuse s1, the first statement of the block, to contain the
374  * whole block. Reuse s to contain the first instruction of the
375  * block.
376  */
378 
379  pips_assert("The first statement of the block is not a block",
381 
382  /* s only has got a label */
387 
393 
395  CDR(instruction_block(i)));
396 
397  pips_assert("The first statement of block s1 must be s\n",
399  == s);
400 
401  new_s = s1;
402  }
403  else {
404  statement_instruction(s) = i;
405  /*
406  statement_number(s) = (instruction_goto_p(i))?
407  STATEMENT_NUMBER_UNDEFINED : get_next_statement_number();
408  */
409  /* Let's number labelled GOTO because a CONTINUE is derived later from them */
410  statement_number(s) = get_statement_number(); //get_next_statement_number();
411  new_s = s;
412  }
413 
414  debug(9, "ReuseLabelledStatement", "end for label \"%s\"\n",
416 
417  return new_s;
418 }
419 
420 /* This function makes a statement. l is the label and i the
421  * instruction. We make sure that the label is not declared twice.
422  *
423  * Comments are added by LinkInstToCurrentBlock() which calls MakeStatement()
424  * because it links the instruction by linking its statement..
425  *
426  * GO TO statements are numbered like other statements although they
427  * are destroyed by the controlizer. To be changed.
428  */
429 
430 statement
432 entity l;
433 instruction i;
434 {
435  statement s;
436 
437  debug(5, "MakeStatement", "Begin for label %s and instruction %s\n",
439 
440  pips_assert("MakeStatement", type_statement_p(entity_type(l)));
441  pips_assert("MakeStatement", storage_rom_p(entity_storage(l)));
442  pips_assert("MakeStatement", value_constant_p(entity_initial(l)));
443  pips_assert("MakeStatement",
445 
446  if (!entity_empty_label_p(l)) {
447  /* There is an actual label */
448 
449  /* Well, there is no easy solution to handle labels when Fortran
450  * constructs such as alternate returns, computed gotos and
451  * assigned gotos are desugared because they may be part of a
452  * logical IF, unknowingly.
453  */
454  /*
455  if (instruction_block_p(i))
456  ParserError("makeStatement", "a block must have no label\n");
457  */
458 
459  /* FI, PJ: the "rice" phase does not handle labels on DO like 100 in:
460  * 100 DO 200 I = 1, N
461  *
462  * This should be trapped by "rice" when loops are checked to see
463  * if Allen/Kennedy's algorithm is applicable
464  */
465  if (instruction_loop_p(i)) {
466  if(!get_bool_property("PARSER_SIMPLIFY_LABELLED_LOOPS")) {
467  user_warning("MakeStatement",
468  "DO loop reachable by GO TO via label %s "
469  "cannot be parallelized by PIPS\n",
470  entity_local_name(l));
471  }
472  }
473 
474  if ((s = LabelToStmt(entity_name(l))) == statement_undefined) {
475  /* There is not forward reference to the this label. A new statement
476  * can be safely allocated.
477  */
478  s = MakeNewLabelledStatement(l,i);
479  }
480  else {
481  /* A forward reference has been encountered and the corresponding
482  * statement has been allocated and has been referenced by at least
483  * one go to statement.
484  */
485 
487  /* The CONTINUE slot can be re-used. It is likely to
488  be an artificial CONTINUE added to carry a
489  comment. Maybe it would be better to manage lab_I in a
490  more consistent way by resetting it as soon as it is
491  used. But I did not find the reset! */
492  /*
493  if(statement_continue_p(s)) {
494  free_instruction(statement_instruction(s));
495  statement_instruction(s) = instruction_undefined;
496  statement_number(s) = STATEMENT_NUMBER_UNDEFINED;
497  }
498  else {
499  */
500  user_warning("MakeStatement", "Label %s may be used twice\n",
501  entity_local_name(l));
502  ParserError("MakeStatement", "Same label used twice\n");
503  /* } */
504  }
505  s = ReuseLabelledStatement(s, i);
506  }
507  }
508  else {
509  /* No actual label, no problem */
510  s = make_statement(l,
512  STATEMENT_NUMBER_UNDEFINED : get_statement_number(), //get_next_statement_number(),
516  }
517 
518  return(s);
519 }
520 
521 
522 
523 /* this function links the instruction i to the current block of
524 statements. if i is the last instruction of the block (i and the block
525 have the same label), the current block is popped from the stack. in
526 fortran, one instruction migth end more than one block. */
527 
528 void
530 instruction i;
531 bool number_it;
532 {
533  statement s;
534  cons * pc;
535  entity l = MakeLabel(lab_I);
536 
537  pips_debug(8, "Begin for instruction %s with label \"%s\"\n",
539 
540  /* A label cannot be used twice */
542 
543  if (IsBlockStackEmpty())
544  ParserError("LinkInstToCurrentBlock", "no current block\n");
545 
547  /* a CONTINUE instruction must be added to carry the label,
548  because blocks cannot be labelled */
549  /*
550  list ls = instruction_block(i);
551  statement c = MakeStatement(l, make_continue_instruction());
552  */
553  /* The above continue is not a user statement an should not be numbered */
554  /* OK, an argument could be added to MakeStatement()... */
555  /* decrement_statement_number(); */
556 
557  /* instruction_block(i) = CONS (STATEMENT, c, ls); */
558  if(number_it) {
559  /* pips_assert("Why do you want to number a block?!?", false); */
560  /* OK, let's be cool and ignore this request to save the caller a test */
561  /* s = MakeStatement(entity_empty_label(), i); */
562  /* s = instruction_to_statement(i); */
563  ;
564  }
565  else{
566  /* s = instruction_to_statement(i); */
567  ;
568  }
569  s = MakeStatement(l, i);
570  }
571  else {
572  s = MakeStatement(l, i);
573  }
574 
575  if (iPrevComm != 0) {
576  /* Because of labelled loop desugaring, new_i may be different from i */
578  if(instruction_block_p(new_i)) {
579  statement fs = statement_undefined; // first statement of the block
580  statement ss = statement_undefined; // second statement, if it exist
581  statement cs = statement_undefined; // commented statement
582 
583  /* Only desugared constructs such as labelled loop, computed go to or IO with
584  * error handling should produce blocks. Such blocks should be
585  * non-empty and not commented.
586  */
587  pips_assert("The block is non empty", !ENDP(instruction_block(new_i)));
588  /* Sometimes, we generate blocks with only one statement in it. E.g. alternate returns
589  pips_assert("The block has at least two statements", !ENDP(CDR(instruction_block(new_i))));
590  */
591 
592  fs = STATEMENT(CAR(instruction_block(new_i)));
593  /* For keeping pragma attached to a loop attached to it,
594  we have to find the loop instruction within the
595  block */
596  if(!ENDP(CDR(instruction_block(new_i)))) {
597  ss = STATEMENT(CAR(CDR(instruction_block(new_i))));
598 
600  cs = ss;
601  else
602  cs = fs;
603  }
604  else {
605  cs = fs;
606  }
607  /*
608  pips_assert("The first statement has no comments",
609  statement_comments(cs) == empty_comments);
610  */
612  user_log("Current comment of chosen statement: \"%s\"\n",
613  statement_comments(cs));
614  user_log("Block comment to be carried by first statement: \"%s\"\n",
615  PrevComm);
616  pips_internal_error("The first statement of the block should have no comments");
617  }
618 
619  pips_assert("The chosen statement is not a block",
621 
623  }
624  else {
626  }
627  PrevComm[0] = '\0';
628  iPrevComm = 0;
629  }
630 
631  pc = CONS(STATEMENT, s, NULL);
632 
633  if (BlockStack[CurrentBlock-1].c == NULL) {
635  }
636  else {
637  CDR(BlockStack[CurrentBlock-1].c) = pc;
638  }
639  BlockStack[CurrentBlock-1].c = pc;
640 
641  /* while i is the last instruction of the current block ... */
642  while (BlockStack[CurrentBlock-1].l != NULL &&
643  strcmp(label_local_name(l), BlockStack[CurrentBlock-1].l) == 0)
644  PopBlock();
645 
646  pips_debug(8, "End for instruction %s with label \"%s\"\n",
648 }
649 
650 
651 
652 /* this function creates an empty block */
653 
655 {
656  return(make_instruction_block(NIL));
657 }
658 
659 ␌
660 
661 /* this function creates a simple Fortran statement such as RETURN,
662 CONTINUE, ...
663 
664 s is the name of the intrinsic function.
665 
666 e is one optional argument (might be equal to expression_undefined). */
667 
670 char *s;
671 expression e;
672 {
673  cons *l; /* la liste d'arguments */
674 
675  l = (e == expression_undefined) ? NIL : CONS(EXPRESSION, e, NIL);
676 
678  make_call(CreateIntrinsic(s), l)));
679 }
680 
681 ␌
682 
683 /* this function creates a goto instruction. n is the target label. */
684 
687 string n;
688 {
691 
692  l = MakeLabel(n);
693 
694  i = make_goto_instruction(l);
695 
696  return i;
697 }
698 
699 /* In a "go to" instruction, the label does not appear explictly.
700  * It is replaced by the statement to be jumped at.
701  * If the statement carrying the label has been encountered before,
702  * everything is fine. Else the target statement has to be synthesized
703  * blindly ahead of time.
704  */
707 {
710 
711  if (s == statement_undefined) {
712  s = make_statement(l,
716  instruction_undefined, NIL, NULL,
718  NewStmt(l, s);
719  }
720 
722 
723  return g;
724 }
725 
726 
728 {
729  instruction inst = MakeAssignedOrComputedGotoInst(ll, e, false);
730 
731  return inst;
732 }
733 
735 {
736  instruction inst;
738 
740 
741  inst = MakeAssignedOrComputedGotoInst(ll, expr, true);
742 
743  return inst;
744 }
745 
748 {
750  list cs = NIL;
751  int l = 0;
752  list cl = list_undefined;
754  syntax sce = expression_syntax(ce);
756 
757  /* ce might have side effects */
758  if(syntax_reference_p(sce)) {
759  /* ce can be used several times without side effects */
760  e = ce;
761  }
762  else if(syntax_call_p(sce)) {
763  if(call_constant_p(syntax_call(sce))) {
764  e = ce;
765  }
766  else {
767  /* We cannot know yet if ce has side effects */
768  /* expression_intrinsic_operation_p(ce): a user call may be hidden
769  at a lower level and some intrinsics may have side effects and
770  it might be more efficient not to recompute a complex
771  expression several times */
772  /* Prefix starts with I to avoid an explicit declaration and a
773  regeneration of declarations by the prettyprinter. */
776  make_basic(is_basic_int, (void*) 4));
778 
779  e = entity_to_expression(tmp);
780  }
781  }
782  else {
783  pips_internal_error("No range expected", false);
784  }
785 
786 
787  for(l = gen_length(ll), cl = ll; !ENDP(cl); l--, POP(cl)) {
788  string ln = STRING(CAR(cl));
789  instruction g = MakeGotoInst(ln);
790  expression cond =
795  entity_domain),
796  copy_expression(e),
797  int_to_expression(assigned? atoi(ln):l));
798  /* Assigned GO TO: if the current label is not in the list, this is an error
799  * in Fortran 90. ISO/IEC 1539 Section 8.2.4 page 108. Same in Fortran 77
800  * standard, Section 11-2.
801  */
802  statement may_stop = (assigned && (cl==ll)) ?
805  :
807  instruction iif =
809  make_test(cond,
811  may_stop));
813 
814  s = instruction_to_statement(iif);
815 
816  /* Update the statement numbers of all possibly allocated statements */
818  if(stop_statement_p(may_stop))
820 
821  cs = CONS(STATEMENT, s, cs);
822  }
823 
825  cs = CONS(STATEMENT, s_init, cs);
826 
827  /* MakeStatement won't increment the current statement number
828  * because this is a block... so it has to be done here
829  */
830  // (void) get_next_statement_number();
831  ins = make_instruction_block(cs);
832 
833  (void) instruction_consistent_p(ins);
834 
835  /* FatalError("parser", "computed goto statement prohibited\n"); */
836 
837  return ins;
838 }
839 
840 /* this function creates an affectation statement.
841 
842  l is a reference (the left hand side).
843 
844  e is an expression (the right hand side).
845 */
846 
849 {
852 
853  if(syntax_reference_p(l)) {
855  i = make_assign_instruction(lhs, e);
856  }
857  else
858  {
859  if(syntax_call_p(l) &&
862  {
863  list lexpr = CONS(EXPRESSION, e, NIL);
864  list asub = call_arguments(syntax_call(l));
865 
867  free_syntax(l);
868 
871  gen_append(asub, lexpr)));
872  }
873  else
874  {
875  if (syntax_call_p(l) &&
877  {
878  if (get_bool_property("PARSER_EXPAND_STATEMENT_FUNCTIONS"))
879  {
880  /* Let us keep the statement function definition somewhere.
881  */
882  /* Preserve the current comments as well as the information
883  about the macro substitution */
886 
887  pips_debug(5, "considering %s as a macro\n",
889 
891  statement_comments(stmt2) =
892  strdup(concatenate("C$PIPS STATEMENT FUNCTION ",
894  " SUBSTITUTED\n", 0));
896  CONS(STATEMENT, stmt2, NIL)));
897  }
898  else
899  {
900  /* FI: we stumble here when a Fortran macro is used. */
901  user_warning("MakeAssignInst", "%s() appears as lhs\n",
903  ParserError("MakeAssignInst",
904  "bad lhs (function call or undeclared array)"
905  " or PIPS unsupported Fortran macro\n"
906  "you might consider switching the "
907  "PARSER_EXPAND_STATEMENT_FUNCTIONS property,\n"
908  "in the latter, at your own risk...\n");
909  }
910  }
911  else {
912  if(syntax_call_p(l)) {
913  /* FI: we stumble here when a Fortran PARAMETER is used as lhs. */
914  user_warning("MakeAssignInst", "PARAMETER %s appears as lhs\n",
916  ParserError("MakeAssignInst",
917  "Illegal lhs\n");
918  }
919  else {
920  FatalError("MakeAssignInst", "Unexpected syntax tag\n");
921  }
922  }
923  }
924  }
925 
926  return i;
927 }
928 
929 /* Update of the type returned by function f. nt must be a freshly
930  allocated object. It is included in f's data structure */
931 void
933 {
934  type ft = entity_type(f);
935  type rt = type_undefined;
936 
937  //pips_assert("function type is functional", type_functional_p(ft));
938  if(!type_functional_p(ft)) {
939  /* The function is probably a formal parameter, its type is
940  wrong. The return type is either void if it is called by CALL
941  or its current implicit type. */
943  pips_user_warning("Variable \"%s\" is a formal functional parameter\n",
945  ParserError(__FUNCTION__,
946  "Formal functional parameters are not yet supported\n");
947  }
948  else {
949  pips_internal_error("Unexpected case");
950  }
951  }
952  else {
954  }
955 
956  pips_assert("result type is variable or unkown or void or undefined",
957  type_undefined_p(rt)
958  || type_unknown_p(rt)
959  || type_void_p(rt)
960  || type_variable_p(rt));
961 
962  pips_assert("new result type is variable or void",
963  type_void_p(nt)
964  ||type_variable_p(nt));
965 
966  free_type(rt);
968 }
969 
970 void
972 {
973  list pc = list_undefined;
974  list pc2 = list_undefined;
975  type t = type_undefined;
977 
978  pips_assert("update_functional_type_with_actual_arguments", !type_undefined_p(entity_type(e)));
979  t = entity_type(e);
980  pips_assert("update_functional_type_with_actual_arguments", type_functional_p(t));
981  ft = type_functional(t);
982 
983 
984  if( ENDP(functional_parameters(ft))) {
985  /* OK, it is not safe: may be it's a 0-ary function */
986  for (pc = l; pc != NULL; pc = CDR(pc)) {
987  expression ae = EXPRESSION(CAR(pc));
988  type t = type_undefined;
990 
991  if(expression_reference_p(ae)) {
994 
995  if(type_functional_p(tv)) {
996  pips_user_warning("Functional actual argument %s found.\n"
997  "Functional arguments are not yet suported by PIPS\n",
999  }
1000 
1001  t = copy_type(tv);
1002  }
1003  else {
1004  basic b = basic_of_expression(ae);
1005  variable v = make_variable(b, NIL,NIL);
1006  t = make_type(is_type_variable, v);
1007  }
1008 
1009  p = make_parameter(t,
1011  make_dummy_unknown());
1012  functional_parameters(ft) =
1014  CONS(PARAMETER, p, NIL));
1015  }
1016  }
1017  else if(get_bool_property("PARSER_TYPE_CHECK_CALL_SITES")) {
1018  /* The pre-existing typing of e should match the new one */
1019  int i = 0;
1020  bool warning_p = false;
1021 
1022  for (pc = l, pc2 = functional_parameters(ft), i = 1;
1023  !ENDP(pc) && !ENDP(pc2);
1024  POP(pc), i++) {
1025  expression ae = EXPRESSION(CAR(pc));
1026  type at = type_undefined;
1027  type ft = parameter_type(PARAMETER(CAR(pc2)));
1028  type eft = type_varargs_p(ft)? type_varargs(ft) : ft;
1029  /* parameter p = parameter_undefined; */
1030 
1031  if(expression_reference_p(ae)) {
1034 
1035  if(type_functional_p(tv)) {
1036  pips_user_warning("Functional actual argument %s found.\n"
1037  "Functional arguments are not yet suported by PIPS\n",
1039  }
1040 
1041  at = copy_type(tv);
1042  }
1043  else {
1044  basic b = basic_of_expression(ae);
1045  variable v = make_variable(b, NIL,NIL);
1046 
1047  at = make_type(is_type_variable, v);
1048  }
1049 
1050  if((type_variable_p(eft)
1052  || type_equal_p(at, eft)) {
1053  /* OK */
1054  if(!type_varargs_p(ft))
1055  POP(pc2);
1056  }
1057  else {
1058  user_warning("update_functional_type_with_actual_arguments",
1059  "incompatible %d%s actual argument and type in call to %s "
1060  "between lines %d and %d. Current type is not updated\n",
1061  i, nth_suffix(i),
1063  free_type(at);
1064  warning_p = true;
1065  break;
1066  }
1067  free_type(at);
1068  }
1069 
1070  if(!warning_p) {
1071  if(!(ENDP(pc) /* the actual parameter list must be exhausted */
1072  && (ENDP(pc2) /* as well as the type parameter list */
1073  || (ENDP(CDR(pc2)) /* unless the last type in the parameter list is a varargs */
1074  && type_varargs_p(parameter_type(PARAMETER(CAR(pc2)))))))) {
1075  user_warning("update_functional_type_with_actual_arguments",
1076  "inconsistent arg. list lengths for %s:\n"
1077  " %d args according to type and %d actual arguments\n"
1078  "between lines %d and %d. Current type is not updated\n",
1079  module_local_name(e),
1082  }
1083  }
1084  }
1085 }
1086 
1087 /* this function creates a call statement. e is the called function. l
1088 is the argument list, a list of expressions. */
1089 
1090 instruction
1092  entity e, /* callee */
1093  cons * l /* list of actual parameters */
1094 )
1095 {
1097  list ar = get_alternate_returns();
1098  list ap = add_actual_return_code(l);
1099  storage s = entity_storage(e);
1100  bool ffp_p = false;
1101  entity fe = e;
1102 
1103  if(!storage_undefined_p(s)) {
1104  if(storage_formal_p(s)) {
1105  ffp_p = true;
1106  pips_user_warning("entity %s is a formal functional parameter\n",
1107  entity_name(e));
1108  /* ParserError("MakeCallInst",
1109  "Formal functional parameters are not supported "
1110  "by PIPS.\n"); */
1111  /* FI: Before you can proceed to
1112  update_functional_type_result(), you may have to fix
1113  the type of e. Basically, if its type is not
1114  functional, it should be made functional with result
1115  void. I do not fix the problem in the parser because
1116  tons of other problems are going to appear, at least
1117  one for each PIPS analysis, starting with effects,
1118  proper, cumulated, regions, transformers,
1119  preconditions,... No quick fix, but a special effort
1120  made after an explicit decision. */
1121  }
1122  }
1123 
1124  if(!ffp_p) {
1126 
1127  /* The following assertion is no longer true when fucntions are
1128  passed as actual arguments. */
1129  /* pips_assert("e itself is returned",
1130  MakeExternalFunction(e, MakeTypeVoid()) == e); */
1132  }
1133 
1136 
1137  if(!ENDP(ar)) {
1140 
1142  pips_assert("Alternate return substitution required\n", SubstituteAlternateReturnsP());
1144  pips_assert("Must be a sequence", instruction_block_p(i));
1146  s,
1147  instruction_block(i));
1148  }
1149  else {
1151  }
1152 
1153  return i;
1154 }
1155 
1156 
1157 
1158 /* this function creates a do loop statement.
1159 
1160 s is a reference to the do variable.
1161 
1162 r is the range of the do loop.
1163 
1164 l is the label of the last statement of the loop. */
1165 
1166 void
1167 MakeDoInst(s, r, l)
1168 syntax s;
1169 range r;
1170 string l;
1171 {
1172  instruction ido, instblock_do;
1173  statement stmt_do;
1174  entity dovar, dolab;
1175 
1176  if (!syntax_reference_p(s))
1177  FatalError("MakeDoInst", "function call as DO variable\n");
1178 
1179  if (reference_indices(syntax_reference(s)) != NULL)
1180  FatalError("MakeDoInst", "variable reference as DO variable\n");
1181 
1184  /* This free is not nice for the caller! Nor for the debugger. */
1185  free_syntax(s);
1186 
1187  dolab = MakeLabel((strcmp(l, "BLOCKDO") == 0) ? "" : l);
1188 
1189  instblock_do = MakeEmptyInstructionBlock();
1190  stmt_do = instruction_to_statement(instblock_do);
1191 
1192  if(get_bool_property("PARSER_LINEARIZE_LOOP_BOUNDS")) {
1196 
1199  make_loop(dovar, r, stmt_do, dolab,
1201  UU),
1202  NIL));
1203  }
1204  else {
1205  /* Let's build a sequence with loop range assignments */
1207  make_loop(dovar, r, stmt_do, dolab,
1209  UU),
1210  NIL));
1212 
1213  if(!normalized_linear_p(ni)) {
1216  make_basic(is_basic_int, (void*) 4));
1220  }
1221 
1222  if(!normalized_linear_p(nu)) {
1225  make_basic(is_basic_int, (void*) 4));
1229  }
1230 
1231  if(!normalized_linear_p(nl)) {
1234  make_basic(is_basic_int, (void*) 4));
1238  }
1239  ido = make_instruction_block(a);
1240  }
1241  }
1242  else {
1244  make_loop(dovar, r, stmt_do, dolab,
1246  UU),
1247  NIL));
1248  }
1249 
1250  LinkInstToCurrentBlock(ido, true);
1251 
1252  PushBlock(instblock_do, l);
1253 }
1254 
1255 /* This function creates a while do loop statement.
1256  *
1257  * c is the loop condition
1258  * l is the label of the last statement of the loop.
1259  */
1260 
1261 void
1263 {
1264  instruction iwdo, instblock_do;
1265  statement stmt_do;
1266  entity dolab;
1268 
1269  if(!logical_expression_p(c)) {
1270  /* with the f77 compiler, this is equivalent to c.NE.0*/
1272  c, int_to_expression(0));
1273  pips_user_warning("WHILE condition between lines %d and %d is not a logical expression.\n",
1274  line_b_I,line_e_I);
1275  }
1276  else {
1277  cond = c;
1278  }
1279 
1280  dolab = MakeLabel((strcmp(l, "BLOCKDO") == 0) ? "" : l);
1281 
1282  instblock_do = MakeEmptyInstructionBlock();
1283  stmt_do = instruction_to_statement(instblock_do);
1284 
1286  make_whileloop(cond, stmt_do, dolab,make_evaluation_before()));
1287 
1288  LinkInstToCurrentBlock(iwdo, true);
1289 
1290  PushBlock(instblock_do, l);
1291 }
1292 ␌
1294 {
1296 
1297  if(!logical_expression_p(e)) {
1298  /* with the f77 compiler, this is equivalent to e.NE.0 if e is an
1299  integer expression. */
1300  if(integer_expression_p(e)) {
1302  e, int_to_expression(0));
1303  pips_user_warning("IF condition between lines %d and %d is not a logical expression.\n",
1304  line_b_I,line_e_I);
1305  }
1306  else {
1307  ParserError("MakeBlockIfInst", "IF condition is neither logical nor integer.\n");
1308  }
1309  }
1310  else {
1311  cond = e;
1312  }
1313  return cond;
1314 }
1315 
1316 /* this function creates a logical if statement. the true part of the
1317  * test is a block with only one instruction (i), and the false part is an
1318  * empty block.
1319  *
1320  * Modifications:
1321  * - there is no need for a block in the true branch, any statement can do
1322  * - there is no need for a CONTINUE statement in the false branch, an empty block
1323  * is plenty
1324  * - MakeStatement() cannot be used for the true and false branches because it
1325  * disturbs the statement numering
1326  */
1327 
1328 instruction
1330 expression e;
1331 instruction i;
1332 {
1333  /* It is not easy to number bt because Yacc reduction order does not help... */
1336  expression cond = fix_if_condition(e);
1338  make_test(cond, bt, bf));
1339 
1340  if (i == instruction_undefined)
1341  FatalError("MakeLogicalIfInst", "bad instruction\n");
1342 
1343  /* Instruction i should not be a block, unless:
1344  * - an alternate return
1345  * - a computed GO TO
1346  * - an assigned GO TO
1347  * has been desugared.
1348  *
1349  * If the logical IF is labelled, the label has been stolen by the
1350  * first statement in the block. This shows that label should only
1351  * be affected by MakeStatement and not by desugaring routines.
1352  */
1353  if(instruction_block_p(i)) {
1354  list l = instruction_block(i);
1355  /* statement first = STATEMENT(CAR(l)); */
1356  /* Only the alternate return case assert:
1357  pips_assert("Block of two instructions or call with return code checks",
1358  (gen_length(l)==2 && assignment_statement_p(first))
1359  ||
1360  (statement_call_p(first))
1361  );
1362  */
1363  MAP(STATEMENT, s, {
1365  }, l);
1366  }
1367  else {
1369  }
1370 
1371  return ti;
1372 }
1373 
1374 /* this function transforms an arithmetic if statement into a set of
1375 regular tests. long but easy to understand without comments.
1376 
1377 e is the test expression. e is inserted in the instruction returned
1378 (beware of sharing)
1379 
1380 l1, l2, l3 are the three labels of the original if statement.
1381 
1382  IF (E) 10, 20, 30
1383 
1384 becomes
1385 
1386  IF (E .LT. 0) THEN
1387  GOTO 10
1388  ELSE
1389  IF (E .EQ. 0) THEN
1390  GOTO 20
1391  ELSE
1392  GOTO 30
1393  ENDIF
1394  ENDIF
1395 
1396 */
1397 
1398 instruction
1399 MakeArithmIfInst(e, l1, l2, l3)
1400 expression e;
1401 string l1, l2, l3;
1402 {
1403  expression e1, e2;
1404  statement s1, s2, s3, s;
1406 
1407  /* FI: Should be improved by testing equality between l1, l2 and l3
1408  * Cases observed:
1409  * l1 == l2
1410  * l2 == l3
1411  * l1 == l3
1412  * Plus, just in case, l1==l2==l3
1413  */
1414 
1415  if(strcmp(l1,l2)==0) {
1416  if(strcmp(l2,l3)==0) {
1417  /* This must be quite unusual, but the variables in e have to be dereferenced
1418  * to respect the use-def chains, e may have side effects,...
1419  *
1420  * If the optimizer is very good, the absolute value of e
1421  * should be checked positive?
1422  */
1423  e1 = MakeUnaryCall(CreateIntrinsic("ABS"), e);
1424  e2 = MakeBinaryCall(CreateIntrinsic(".GE."),
1425  e1, int_to_expression(0));
1426 
1429 
1431  make_test(e2,s1,s2));
1432  }
1433  else {
1434  e1 = MakeBinaryCall(CreateIntrinsic(".LE."),
1435  e, int_to_expression(0));
1436 
1439 
1441  make_test(e1,s1,s3));
1442  }
1443  }
1444  else if(strcmp(l1,l3)==0) {
1445  e1 = MakeBinaryCall(CreateIntrinsic(".EQ."),
1446  e, int_to_expression(0));
1447 
1450 
1452  make_test(e1,s2,s1));
1453  }
1454  else if(strcmp(l2,l3)==0) {
1455  e1 = MakeBinaryCall(CreateIntrinsic(".LT."),
1456  e, int_to_expression(0));
1457 
1460 
1462  make_test(e1,s1,s2));
1463  }
1464  else {
1465  /* General case */
1466  e1 = MakeBinaryCall(CreateIntrinsic(".LT."),
1467  e, int_to_expression(0));
1468  e2 = MakeBinaryCall(CreateIntrinsic(".EQ."),
1470 
1474 
1476  make_test(e2,s2,s3)));
1478 
1480  }
1481 
1482  return ifarith;
1483 }
1484 
1485 /* this function and the two next ones create a block if statement. the
1486 true and the else part of the test are two empty blocks. e is the test
1487 expression.
1488 
1489 the true block is pushed on the stack. it will contain the next
1490 statements, and will end with a else statement or an endif statement.
1491 
1492 if a else statement is reached, the true block is popped and the false
1493 block is pushed to gather the false part statements. if no else
1494 statement is found, the true block will be popped with the endif
1495 statement and the false block will remain empty. */
1496 
1497 void
1499 expression e;
1500 int elsif;
1501 {
1502  instruction bt, bf, i;
1503  expression cond = fix_if_condition(e);
1504 
1507 
1509  make_test(cond,
1510  MakeStatement(MakeLabel(""), bt),
1511  MakeStatement(MakeLabel(""), bf)));
1512 
1513  LinkInstToCurrentBlock(i, true);
1514 
1515  PushBlock(bt, "ELSE");
1516  BlockStack[CurrentBlock-1].elsifs = elsif ;
1517 }
1518 
1519 /* This function is used to handle either an ELSE or an ELSEIF construct */
1520 
1521 int
1522 MakeElseInst(bool is_else_p)
1523 {
1524  statement if_stmt;
1525  test if_test;
1526  int elsifs;
1527  bool has_comments_p = (iPrevComm != 0);
1528 
1529  if(CurrentBlock==0) {
1530  /* No open block can be closed by this ELSE */
1531  ParserError("MakeElseInst", "unexpected ELSE statement\n");
1532  }
1533 
1534  elsifs = BlockStack[CurrentBlock-1].elsifs ;
1535 
1536  if (strcmp("ELSE", BlockStack[CurrentBlock-1].l))
1537  ParserError("MakeElseInst", "block if statement badly nested\n");
1538 
1539  if (has_comments_p) {
1540  /* Generate a CONTINUE to carry the comments but not the label
1541  because the ELSE is not represented in the IR and cannot carry
1542  comments. The ELSEIF is transformed into an IF which can carry
1543  comments and label but the prettyprint of structured code is
1544  nicer if the comments are carried by a CONTINUE in the previous
1545  block. Of course, this is not good for unstructured code since
1546  comments end up far from their intended target or attached to
1547  a dead CONTINUE if the previous block ends up with a GO TO.
1548 
1549  The current label is temporarily hidden. */
1550  string ln = strdup(get_current_label_string());
1554  free(ln);
1555  }
1556 
1557  (void) PopBlock();
1558 
1559  if_stmt = STATEMENT(CAR(BlockStack[CurrentBlock-1].c));
1560 
1561  if (! instruction_test_p(statement_instruction(if_stmt)))
1562  FatalError("MakeElseInst", "no block if statement\n");
1563 
1564  if_test = instruction_test(statement_instruction(if_stmt));
1565 
1566  PushBlock(statement_instruction(test_false(if_test)), "ENDIF");
1567 
1568  if (is_else_p && !empty_current_label_string_p()) {
1569  /* generate a CONTINUE to carry the label because the ELSE is not
1570  represented in the IR */
1572  }
1573 
1574  return( BlockStack[CurrentBlock-1].elsifs = elsifs ) ;
1575 }
1576 
1577 void
1579 {
1580  int elsifs = -1;
1581 
1582  if(CurrentBlock==0) {
1583  ParserError("MakeEndifInst", "unexpected ENDIF statement\n");
1584  }
1585 
1586  if (iPrevComm != 0) {
1587  /* generate a CONTINUE to carry the comments */
1589  }
1590 
1591  if (BlockStack[CurrentBlock-1].l != NULL &&
1592  strcmp("ELSE", BlockStack[CurrentBlock-1].l) == 0) {
1593  elsifs = MakeElseInst(true);
1595  }
1596  if (BlockStack[CurrentBlock-1].l == NULL ||
1597  strcmp("ENDIF", BlockStack[CurrentBlock-1].l)) {
1598  ParserError("MakeEndifInst", "block if statement badly nested\n");
1599  }
1600  else {
1601  elsifs = BlockStack[CurrentBlock-1].elsifs ;
1602  }
1603  pips_assert( "MakeEndifInst", elsifs >= 0 ) ;
1604 
1605  do {
1606  (void) PopBlock();
1607  } while( elsifs-- != 0 ) ;
1608 }
1609 
1610 void
1612 {
1613  if(CurrentBlock<=1) {
1614  ParserError("MakeEnddoInst", "Unexpected ENDDO statement\n");
1615  }
1616 
1617  if (strcmp("BLOCKDO", BlockStack[CurrentBlock-1].l)
1618  &&strcmp(lab_I, BlockStack[CurrentBlock-1].l))
1619  ParserError("MakeEnddoInst", "block do statement badly nested\n");
1620 
1621  /*LinkInstToCurrentBlock(MakeZeroOrOneArgCallInst("ENDDO",
1622  expression_undefined));*/
1623  /* Although it is not really an instruction, the ENDDO statement may
1624  * carry comments and be labelled when closing a DO label structure.
1625  */
1627 
1628  /* An unlabelled ENDDO can only close one loop. This cannot be
1629  * performed by LinkInstToCurrentBlock().
1630  */
1631  if (strcmp("BLOCKDO", BlockStack[CurrentBlock-1].l)==0)
1632  (void) PopBlock();
1633 }
1634 
1635 string
1637 int token;
1638 {
1639  string name;
1640 
1641  switch (token) {
1642  case TK_BUFFERIN:
1643  name = "BUFFERIN";
1644  break;
1645  case TK_BUFFEROUT:
1646  name = "BUFFEROUT";
1647  break;
1648  case TK_INQUIRE:
1649  name = "INQUIRE";
1650  break;
1651  case TK_OPEN:
1652  name = "OPEN";
1653  break;
1654  case TK_CLOSE:
1655  name = "CLOSE";
1656  break;
1657  case TK_PRINT:
1658  name = "PRINT";
1659  break;
1660  case TK_READ:
1661  name = "READ";
1662  break;
1663  case TK_REWIND:
1664  name = "REWIND";
1665  break;
1666  case TK_WRITE:
1667  name = "WRITE";
1668  break;
1669  case TK_ENDFILE:
1670  name = "ENDFILE";
1671  break;
1672  case TK_BACKSPACE:
1673  name = "BACKSPACE";
1674  break;
1675  default:
1676  FatalError("NameOfToken", "unknown token\n");
1677  name = string_undefined; /* just to avoid a gcc warning */
1678  break;
1679  }
1680 
1681  return(name);
1682 }
1683 
1684 /* Generate a test to jump to l if flag f is TRUE
1685  * Used to implement control effects of IO's due to ERR= and END=.
1686  *
1687  * Should not use MakeStatement() directly or indirectly to avoid
1688  * counting these pseudo-instructions
1689  */
1690 statement
1692 {
1700 
1701  statement_consistent_p(check);
1702 
1703  return check;
1704 }
1705 
1706 /* this function creates an IO statement. keyword indicates which io
1707 statement is to be built (READ, WRITE, ...).
1708 
1709 lci is a list of 'control specifications'. its has the following format:
1710 
1711  ("UNIT=", 6, "FMT=", "*", "RECL=", 80, "ERR=", 20)
1712 
1713 lio is the list of expressions to write or references to read. */
1714 
1715 instruction MakeIoInstA(int keyword, list lci, list lio)
1716 {
1717  cons *l;
1718  /* The composite IO with potential branches for ERR and END */
1720  /* The pure io itself */
1722  /* virtual tests to implement ERR= and END= clauses */
1723  statement io_err = statement_undefined;
1724  statement io_end = statement_undefined;
1726 
1727  for (l = lci; l != NULL; l = CDR(CDR(l))) {
1728  syntax s1;
1729  entity e1;
1730 
1732 
1733  e1 = call_function(syntax_call(s1));
1734 
1735  if (strcmp(entity_local_name(e1), "UNIT=") == 0) {
1736  if( ! expression_undefined_p(unit) )
1738  unit = EXPRESSION(CAR(CDR(l)));
1739  }
1740  }
1741 
1742  /* we scan the list of specifications to detect labels (such as in
1743  ERR=20, END=30, FMT=50, etc.), that were stored as integer constants
1744  (20, 30, 50) and that must be replaced by labels (_20, _30, _50). */
1745  for (l = lci; l != NULL; l = CDR(CDR(l))) {
1746  syntax s1, s2;
1747  entity e1, e2;
1748 
1750  s2 = expression_syntax(EXPRESSION(CAR(CDR(l))));
1751 
1752  pips_assert("syntax is a call", syntax_call_p(s1));
1753  e1 = call_function(syntax_call(s1));
1754  pips_assert("value is constant", value_constant_p(entity_initial(e1)));
1755  pips_assert("constant is not int (thus litteral or call)",
1757 
1758  if (strcmp(entity_local_name(e1), "ERR=") == 0 ||
1759  strcmp(entity_local_name(e1), "END=") == 0 ||
1760  strcmp(entity_local_name(e1), "FMT=") == 0) {
1761  if (syntax_call_p(s2)) {
1762  e2 = call_function(syntax_call(s2));
1763  if (value_constant_p(entity_initial(e2))) {
1765  /* here is a label */
1766  call_function(syntax_call(s2)) =
1768  }
1769  }
1770  e2 = call_function(syntax_call(s2));
1771  if (strcmp(entity_local_name(e1), "FMT=") != 0
1773  /* UNIT is not defined for INQUIRE (et least)
1774  * Let's use LUN 0 by default for END et ERR.
1775  */
1776  unit = int_to_expression(0);
1777  }
1778  if (strcmp(entity_local_name(e1), "ERR=") == 0) {
1780  }
1781  else if (strcmp(entity_local_name(e1), "END=") == 0) {
1783  }
1784  else {
1785  //free_expression(unit);
1786  ;
1787  }
1788  }
1789  }
1790  }
1791 
1792  /*
1793  for (l = lci; CDR(l) != NULL; l = CDR(l)) ;
1794 
1795  CDR(l) = lio;
1796  l = lci;
1797  */
1798 
1799  lci = gen_nconc(lci, lio);
1800 
1803  lci));
1804 
1805  if(statement_undefined_p(io_err) && statement_undefined_p(io_end)) {
1806  io = io_call;
1807  }
1808  else {
1809  list ls = NIL;
1810  if(!statement_undefined_p(io_err)) {
1811  ls = CONS(STATEMENT, io_err, ls);
1812  }
1813  if(!statement_undefined_p(io_end)) {
1814  ls = CONS(STATEMENT, io_end, ls);
1815  }
1816  ls = CONS(STATEMENT, MakeStatement(entity_empty_label(), io_call), ls);
1819  }
1820 
1821  return io;
1822 }
1823 
1824 
1825 
1826 /* this function creates a BUFFER IN or BUFFER OUT io statement. this is
1827 not ansi fortran.
1828 
1829 e1 is the logical unit.
1830 
1831 nobody known the exact meaning of e2
1832 
1833 e3 et e4 are references that indicate which variable elements are to be
1834 buffered in or out. */
1835 
1836 instruction
1837 MakeIoInstB(keyword, e1, e2, e3, e4)
1838 int keyword;
1839 expression e1, e2, e3, e4;
1840 {
1841  cons * l;
1842 
1843  l = CONS(EXPRESSION, e1,
1844  CONS(EXPRESSION, e2,
1845  CONS(EXPRESSION, e3,
1846  CONS(EXPRESSION, e4, NULL))));
1847 
1850  l)));
1851 }
1852 
1853 instruction
1855 {
1857  expression std, format, unite;
1858  cons * lci;
1859 
1860  switch(keyword) {
1861  case TK_READ:
1862  case TK_PRINT:
1865  unite = MakeCharacterConstantExpression("UNIT=");
1866  format = MakeCharacterConstantExpression("FMT=");
1867 
1868  lci = CONS(EXPRESSION, unite,
1869  CONS(EXPRESSION, std,
1870  CONS(EXPRESSION, format,
1871  CONS(EXPRESSION, unit, NULL))));
1872  /* Functionally PRINT is a special case of WRITE */
1873  inst = MakeIoInstA((keyword==TK_PRINT)?TK_WRITE:TK_READ,
1874  lci, NIL);
1875  break;
1876  case TK_WRITE:
1877  case TK_OPEN:
1878  case TK_CLOSE:
1879  case TK_INQUIRE:
1880  ParserError("Syntax",
1881  "Illegal syntax in IO statement, "
1882  "Parentheses and arguments required");
1883  break;
1884  case TK_BACKSPACE:
1885  case TK_REWIND:
1886  case TK_ENDFILE:
1887  unite = MakeCharacterConstantExpression("UNIT=");
1888  lci = CONS(EXPRESSION, unite,
1889  CONS(EXPRESSION, unit, NULL));
1890  inst = MakeIoInstA(keyword, lci, NIL);
1891  break;
1892  default:
1893  ParserError("Syntax","Unexpected token in IO statement");
1894  }
1895  return inst;
1896 }
1897 
1898 instruction
1899 MakeSimpleIoInst2(int keyword, expression f, list io_list)
1900 {
1902  //expression std, format, unite;
1903  //list cil;
1904 
1905  switch(keyword) {
1906  case TK_READ:
1907  inst = make_simple_Fortran_io_instruction(true, f, io_list);
1908  break;
1909  case TK_PRINT:
1910  inst = make_simple_Fortran_io_instruction(false, f, io_list);
1911  break;
1912  case TK_WRITE:
1913  case TK_OPEN:
1914  case TK_CLOSE:
1915  case TK_INQUIRE:
1916  case TK_BACKSPACE:
1917  case TK_REWIND:
1918  case TK_ENDFILE:
1919  ParserError("Syntax",
1920  "Illegal syntax in IO statement, Parentheses are required");
1921  break;
1922  default:
1923  ParserError("Syntax","Unexpected token in IO statement");
1924  }
1925  return inst;
1926 }
1927 
1928 ␌
1929 /* Are we in the declaration or in the executable part?
1930  * Have we seen a FORMAT statement before an executable statement?
1931  * For more explanation, see check_first_statement() below.
1932  */
1933 
1934 static int seen = false;
1935 static int format_seen = false;
1936 static int declaration_lines = -1;
1937 
1938 /* Well, some constant defined in reader.c
1939  * and not deserving a promotion in syntax-local.h
1940  */
1941 #define UNDEF (-2)
1942 
1943 void
1945 {
1946  seen = false;
1947  format_seen = false;
1948  declaration_lines = -1;
1949 }
1950 
1951 void
1953 {
1954  if(!format_seen && !seen) {
1955  format_seen = true;
1956  /* declaration_lines = line_b_I-1; */
1957  debug(8, "set_first_format_statement", "line_b_C=%d, line_b_I=%d\n",
1958  line_b_C, line_b_I);
1960  }
1961 }
1962 
1963 bool
1965 {
1966  return seen;
1967 }
1968 
1969 bool
1971 {
1972  return format_seen;
1973 }
1974 
1975 void
1977 {
1978  if(seen) {
1979  ParserError("Syntax",
1980  "Declaration appears after executable statement");
1981  }
1982  else if(format_seen && !seen) {
1983  /* A FORMAT statement has been found in the middle of the declarations */
1984  if(!get_bool_property("PRETTYPRINT_ALL_DECLARATIONS")) {
1985  pips_user_warning("FORMAT statement within declarations. In order to "
1986  "analyze this code, "
1987  "please set property PRETTYPRINT_ALL_DECLARATIONS "
1988  "or move this FORMAT down in executable code.\n");
1989  ParserError("Syntax", "Source cannot be parsed with current properties");
1990  }
1991  }
1992 }
1993 
1994 /* This function is called each time an executable statement is encountered
1995  * but is effective the first time only.
1996  *
1997  * It mainly copies the declaration text in the symbol table because it is
1998  * impossible (very difficult) to reproduce it in a user-friendly manner.
1999  *
2000  * The declaration text stops at the first executable statement or at the first
2001  * FORMAT statement.
2002  */
2003 void
2005 {
2006  int line_start = true;
2007  int in_comment = false;
2008  int out_of_constant_string = true;
2009  int in_constant_string = false;
2010  int end_of_constant_string = false;
2011  char string_sep = '\000';
2012 
2013  if (! seen)
2014  {
2015  FILE *fd;
2016  int cpt = 0, ibuffer = 0, c;
2017 
2018  /* dynamic local buffer
2019  */
2020  int buffer_size = 1000;
2021  char * buffer = (char*) malloc(buffer_size);
2022  pips_assert("malloc ok", buffer);
2023 
2024  seen = true;
2025 
2026  /* we must read the input file from the begining and up to the
2027  line_b_I-1 th line, and the texte read must be stored in buffer */
2028 
2029  if(!format_seen) {
2030  /* declaration_lines = line_b_I-1; */
2031  debug(8, "check_first_statement", "line_b_C=%d, line_b_I=%d\n",
2032  line_b_C, line_b_I);
2034  }
2035 
2036  fd = safe_fopen(CurrentFN, "r");
2037  while ((c = getc(fd)) != EOF) {
2038  if(line_start == true)
2039  in_comment = strchr(START_COMMENT_LINE,c) != NULL;
2040  /* buffer[ibuffer++] = in_comment? c : toupper(c); */
2041  if(in_comment) {
2042  buffer[ibuffer++] = c;
2043  }
2044  else {
2045  /* Constant strings must be taken care of */
2046  if(out_of_constant_string) {
2047  if(c=='\'' || c == '"') {
2048  string_sep = c;
2049  out_of_constant_string = false;
2050  in_constant_string = true;
2051  buffer[ibuffer++] = c;
2052  }
2053  else {
2054  buffer[ibuffer++] = toupper(c);
2055  }
2056  }
2057  else
2058  if(in_constant_string) {
2059  if(c==string_sep) {
2060  in_constant_string = false;
2061  end_of_constant_string = true;
2062  }
2063  buffer[ibuffer++] = c;
2064  }
2065  else
2066  if(end_of_constant_string) {
2067  if(c==string_sep) {
2068  in_constant_string = true;
2069  end_of_constant_string = false;
2070  buffer[ibuffer++] = c;
2071  }
2072  else {
2073  out_of_constant_string = true;
2074  end_of_constant_string = false;
2075  buffer[ibuffer++] = toupper(c);
2076  }
2077  }
2078  }
2079 
2080  if (ibuffer >= buffer_size-10)
2081  {
2082  pips_assert("buffer initialized", buffer_size>0);
2083  buffer_size*=2;
2084  buffer = (char*) realloc(buffer, buffer_size);
2085  pips_assert("realloc ok", buffer);
2086  }
2087 
2088  if (c == '\n') {
2089  cpt++;
2090  line_start = true;
2091  in_comment = false;
2092  }
2093  else {
2094  line_start = false;
2095  }
2096 
2097  if (cpt == declaration_lines)
2098  break;
2099  }
2100  safe_fclose(fd, CurrentFN);
2101  buffer[ibuffer++] = '\0';
2102  /* Standard version */
2104  buffer = NULL;
2105  /* For Cathare-2, get rid of 100 to 200 MB of declaration text: */
2106  /*
2107  code_decls_text(EntityCode(get_current_module_entity())) = strdup("");
2108  free(buffer);
2109  */
2110  /* strdup(buffer); */
2111  /* free(buffer), buffer=NULL; */
2112 
2113  /* kill the first statement's comment because it's already
2114  included in the declaration text */
2115  /* FI: I'd rather keep them together! */
2116  /*
2117  PrevComm[0] = '\0';
2118  iPrevComm = 0;
2119  */
2120  /*
2121  Comm[0] = '\0';
2122  iComm = 0;
2123  */
2124 
2125  /* clean up the declarations */
2126  /* Common sizes are not yet known because ComputeAddresses() has not been called yet */
2127  /* update_common_sizes(); */
2128 
2129  /* It might seem logical to perform these calls from EndOfProcedure()
2130  * here. But at least ComputeAddresses() is useful for implictly
2131  * declared variables.
2132  * These calls are better located in EndOfProcedure().
2133  */
2134  /*
2135  * UpdateFunctionalType(FormalParameters);
2136  *
2137  * ComputeEquivalences();
2138  * ComputeAddresses();
2139  *
2140  * check_common_layouts(get_current_module_entity());
2141  *
2142  * SaveChains();
2143  */
2144  }
2145 }
void user_log(const char *format,...)
Definition: message.c:234
bool instruction_consistent_p(instruction p)
Definition: ri.c:1124
execution make_execution(enum execution_utype tag, void *val)
Definition: ri.c:838
evaluation make_evaluation_before(void)
Definition: ri.c:786
call make_call(entity a1, list a2)
Definition: ri.c:269
parameter make_parameter(type a1, mode a2, dummy a3)
Definition: ri.c:1495
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
whileloop make_whileloop(expression a1, statement a2, entity a3, evaluation a4)
Definition: ri.c:2937
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
basic make_basic(enum basic_utype tag, void *val)
Definition: ri.c:155
storage make_storage_rom(void)
Definition: ri.c:2285
type copy_type(type p)
TYPE.
Definition: ri.c:2655
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
value make_value(enum value_utype tag, void *val)
Definition: ri.c:2832
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
bool statement_consistent_p(statement p)
Definition: ri.c:2195
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
void free_expression(expression p)
Definition: ri.c:853
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
void free_type(type p)
Definition: ri.c:2658
constant make_constant_litteral(void)
Definition: ri.c:418
void free_syntax(syntax p)
Definition: ri.c:2445
dummy make_dummy_unknown(void)
Definition: ri.c:617
synchronization make_synchronization_none(void)
Definition: ri.c:2424
sequence make_sequence(list a)
Definition: ri.c:2125
type make_type(enum type_utype tag, void *val)
Definition: ri.c:2706
#define LOCAL
Definition: bootstrap.c:84
stack BlockStack
Attention, the null statement in C is represented as the continue statement in Fortran (make_continue...
Definition: statement.c:58
expression MakeCharacterConstantExpression(string s)
END_EOLE.
Definition: constant.c:573
void DeclareVariable(entity e, type t, list d, storage s, value v)
void DeclareVariable(e, t, d, s, v): update entity e description as declaration statements are encoun...
Definition: declaration.c:670
string make_entity_fullname(const char *module_name, const char *local_name)
END_EOLE.
Definition: entity_names.c:230
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define call_constant_p(C)
Definition: flint_check.c:51
#define STRING(x)
Definition: genC.h:87
void * malloc(YYSIZE_T)
void free(void *)
statement make_block_statement(list body)
Make a block statement from a list of statement.
Definition: statement.c:616
statement instruction_to_statement(instruction instr)
Build a statement from a give instruction.
Definition: statement.c:597
statement make_empty_block_statement()
Build an empty statement (block/sequence)
Definition: statement.c:625
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
instruction make_assign_instruction(expression l, expression r)
Definition: instruction.c:87
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_append(list l1, const list l2)
Definition: list.c:471
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
bool statement_loop_p(statement s)
Definition: statement.c:349
statement make_assign_statement(expression l, expression r)
Definition: statement.c:583
bool stop_statement_p(statement s)
Test if a statement is a Fortran STOP.
Definition: statement.c:263
bool continue_statement_p(statement s)
Test if a statement is a CONTINUE, that is the FORTRAN nop, the ";" in C or the "pass" in Python....
Definition: statement.c:203
instruction make_simple_Fortran_io_instruction(bool is_read_p, expression f, list io_list)
Derived from the Fortran parser code.
Definition: statement.c:807
statement make_continue_statement(entity l)
Definition: statement.c:953
string instruction_identification(instruction i)
Return a constant string representing symbolically the instruction type.
Definition: instruction.c:284
static expression s_init
must take care not to substitute in an inserted expression
Definition: macros.c:177
void parser_add_a_macro(call c, expression e)
Definition: macros.c:113
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define user_warning(fn,...)
Definition: misc-local.h:262
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
#define LABEL_PREFIX
Definition: naming-local.h:31
#define LIST_DIRECTED_FORMAT_NAME
Definition: naming-local.h:97
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
string nth_suffix(int)
Definition: string.c:250
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
#define string_undefined
Definition: newgen_types.h:40
int unit
UNIT.
Definition: newgen_types.h:97
#define UU
Definition: newgen_types.h:98
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
entity MakeExternalFunction(entity e, type r)
Definition: procedure.c:2372
void update_called_modules(entity e)
Definition: procedure.c:308
char * PrevComm
Definition: reader.c:152
int get_statement_number()
eturn the line number of the statement being parsed
Definition: reader.c:1392
int iPrevComm
Definition: reader.c:153
#define instruction_block_p(i)
#define IO_EFFECTS_PACKAGE_NAME
Implicit variables to handle IO effetcs.
#define SUBSTRING_FUNCTION_NAME
#define EQUAL_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define statement_block_p(stat)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define IO_EOF_ARRAY_NAME
array of end of file codes
#define IO_ERROR_ARRAY_NAME
array of error codes for LUNs
#define STOP_FUNCTION_NAME
#define LABEL_SIZE
constant sizes
#define instruction_block(i)
#define empty_comments
Empty comments (i.e.
#define ASSIGN_SUBSTRING_FUNCTION_NAME
#define NON_EQUAL_OPERATOR_NAME
#define make_empty_statement
An alias for make_empty_block_statement.
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
entity entity_empty_label(void)
Definition: entity.c:1105
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool entity_empty_label_p(entity e)
Definition: entity.c:666
code EntityCode(entity e)
this function checks that e has an initial value code.
Definition: entity.c:301
entity CreateIntrinsic(string name)
this function does not create an intrinsic function because they must all be created beforehand by th...
Definition: entity.c:1311
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
const char * label_local_name(entity e)
END_EOLE.
Definition: entity.c:604
expression reference_to_expression(reference r)
Definition: expression.c:196
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
bool logical_expression_p(expression e)
Definition: expression.c:610
bool integer_expression_p(expression e)
Definition: expression.c:601
expression MakeNullaryCall(entity f)
Creates a call expression to a function with zero arguments.
Definition: expression.c:331
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
mode MakeModeReference(void)
Definition: type.c:82
type MakeTypeVoid(void)
Definition: type.c:102
bool type_equal_p(type, type)
Definition: type.c:547
type MakeTypeStatement(void)
Definition: type.c:92
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
#define type_functional_p(x)
Definition: ri.h:2950
#define value_undefined
Definition: ri.h:3016
@ is_basic_int
Definition: ri.h:571
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define functional_result(x)
Definition: ri.h:1444
#define storage_formal_p(x)
Definition: ri.h:2522
#define parameter_type(x)
Definition: ri.h:1819
#define value_constant(x)
Definition: ri.h:3073
#define syntax_reference(x)
Definition: ri.h:2730
#define type_unknown_p(x)
Definition: ri.h:2956
#define normalized_linear_p(x)
Definition: ri.h:1779
#define instruction_loop_p(x)
Definition: ri.h:1518
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define range_upper(x)
Definition: ri.h:2290
#define syntax_call_p(x)
Definition: ri.h:2734
#define statement_ordering(x)
Definition: ri.h:2454
#define type_functional(x)
Definition: ri.h:2952
#define parameter_undefined
Definition: ri.h:1794
#define test_false(x)
Definition: ri.h:2837
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define type_statement_p(x)
Definition: ri.h:2941
@ is_value_constant
Definition: ri.h:3033
#define instruction_undefined_p(x)
Definition: ri.h:1455
#define range_increment(x)
Definition: ri.h:2292
#define value_constant_p(x)
Definition: ri.h:3071
#define basic_overloaded_p(x)
Definition: ri.h:623
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define type_undefined_p(x)
Definition: ri.h:2884
#define entity_undefined
Definition: ri.h:2761
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_loop
Definition: ri.h:1471
#define value_symbolic_p(x)
Definition: ri.h:3068
#define type_void_p(x)
Definition: ri.h:2959
#define entity_name(x)
Definition: ri.h:2790
#define type_varargs(x)
Definition: ri.h:2955
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define type_varargs_p(x)
Definition: ri.h:2953
#define range_lower(x)
Definition: ri.h:2288
#define code_decls_text(x)
Definition: ri.h:786
#define statement_instruction(x)
Definition: ri.h:2458
#define constant_litteral_p(x)
Definition: ri.h:857
#define statement_comments(x)
Definition: ri.h:2456
#define type_undefined
Definition: ri.h:2883
#define storage_rom_p(x)
Definition: ri.h:2525
@ is_execution_sequential
Definition: ri.h:1189
#define instruction_test_p(x)
Definition: ri.h:1515
#define call_arguments(x)
Definition: ri.h:711
#define instruction_test(x)
Definition: ri.h:1517
#define statement_undefined_p(x)
Definition: ri.h:2420
@ is_type_void
Definition: ri.h:2904
@ is_type_variable
Definition: ri.h:2900
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define instruction_goto_p(x)
Definition: ri.h:1524
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define storage_undefined_p(x)
Definition: ri.h:2477
#define functional_undefined
Definition: ri.h:1418
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define variable_basic(x)
Definition: ri.h:3120
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define storage_undefined
Definition: ri.h:2476
#define entity_initial(x)
Definition: ri.h:2796
char * strdup()
s1
Definition: set.c:247
static int cpt
Definition: stats.c:41
static size_t buffer_size
Definition: string.c:114
static string buffer
Definition: string.c:113
instruction i
Definition: statement.c:192
string l
the instruction that contains this block
Definition: statement.c:193
cons * c
the expected statement which will end this block
Definition: statement.c:194
int elsifs
the list of statements contained in this block
Definition: statement.c:195
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
statement s
the name of the label
Definition: statement.c:56
string l
Definition: statement.c:55
#define TK_CLOSE
Definition: syn_yacc.c:289
#define TK_ENDFILE
Definition: syn_yacc.c:301
#define TK_BACKSPACE
Definition: syn_yacc.c:282
#define TK_BUFFEROUT
Definition: syn_yacc.c:286
#define TK_BUFFERIN
Definition: syn_yacc.c:285
#define TK_WRITE
Definition: syn_yacc.c:337
#define TK_REWIND
Definition: syn_yacc.c:329
#define TK_OPEN
Definition: syn_yacc.c:320
#define TK_PRINT
Definition: syn_yacc.c:324
#define TK_READ
Definition: syn_yacc.c:326
#define TK_INQUIRE
Definition: syn_yacc.c:315
#define FatalError(f, m)
Definition: syntax-local.h:56
#define START_COMMENT_LINE
Legal characters to start a comment line.
Definition: syntax-local.h:30
void set_current_label_string(string ln)
Definition: parser.c:81
char * CurrentFN
Pre-parser for Fortran syntax idiosyncrasy.
Definition: parser.c:49
int line_e_I
Definition: parser.c:68
int line_b_C
Definition: parser.c:68
int line_b_I
Indicates where the current instruction (in fact statement) starts and ends in the input file and giv...
Definition: parser.c:68
string get_current_label_string()
Definition: parser.c:76
bool empty_current_label_string_p()
Definition: parser.c:87
char lab_I[6]
Definition: parser.c:69
bool ParserError(const char *f, const char *m)
Definition: parser.c:116
void reset_current_label_string()
Definition: parser.c:71
const char * CurrentPackage
the name of the current package, i.e.
Definition: parser.c:58
bool SubstituteAlternateReturnsP()
Definition: return.c:81
list add_actual_return_code(list apl)
Definition: return.c:222
instruction generate_return_code_checks(list labels)
Definition: return.c:337
list get_alternate_returns()
Definition: return.c:258
void check_first_statement()
This function is called each time an executable statement is encountered but is effective the first t...
Definition: statement.c:2004
statement ReuseLabelledStatement(statement s, instruction i)
Definition: statement.c:338
void update_functional_type_with_actual_arguments(entity e, list l)
Definition: statement.c:971
LOCAL int CurrentBlock
Definition: statement.c:200
statement MakeStatement(entity l, instruction i)
This function makes a statement.
Definition: statement.c:431
void PushBlock(instruction i, string l)
Definition: statement.c:221
statement make_check_io_statement(string n, expression u, entity l)
Generate a test to jump to l if flag f is TRUE Used to implement control effects of IO's due to ERR= ...
Definition: statement.c:1691
void set_first_format_statement()
Definition: statement.c:1952
void check_in_declarations()
Definition: statement.c:1976
void ResetBlockStack()
Definition: statement.c:203
instruction MakeZeroOrOneArgCallInst(char *s, expression e)
this function creates a simple Fortran statement such as RETURN, CONTINUE, ...
Definition: statement.c:669
bool IsBlockStackEmpty()
Definition: statement.c:209
entity MakeLabel(char *s) const
This functions creates a label.
Definition: statement.c:257
instruction MakeAssignedOrComputedGotoInst(list ll, expression ce, bool assigned)
Definition: statement.c:747
struct block block
#define INITIAL_STMTHEAP_BUFFER_SIZE
the purpose of the following data structure is to associate labels to instructions.
Definition: statement.c:52
instruction MakeArithmIfInst(expression e, string l1, string l2, string l3)
this function transforms an arithmetic if statement into a set of regular tests.
Definition: statement.c:1399
instruction MakeEmptyInstructionBlock()
this function creates an empty block
Definition: statement.c:654
static void init_StmtHeap_buffer(void)
Definition: statement.c:64
static int StmtHeap_buffer_size
Definition: statement.c:60
bool first_format_statement_seen()
Definition: statement.c:1970
instruction MakeCallInst(entity e, cons *l)
this function creates a call statement.
Definition: statement.c:1091
expression fix_if_condition(expression e)
Definition: statement.c:1293
void update_functional_type_result(entity f, type nt)
Update of the type returned by function f.
Definition: statement.c:932
void CheckAndInitializeStmt(void)
this function looks for undefined labels.
Definition: statement.c:113
void MakeDoInst(syntax s, range r, string l)
this function creates a do loop statement.
Definition: statement.c:1167
instruction MakeComputedGotoInst(list ll, expression e)
Definition: statement.c:727
void parser_reset_StmtHeap_buffer(void)
statement.c
Definition: statement.c:85
instruction MakeGotoInst(string n)
this function creates a goto instruction.
Definition: statement.c:686
instruction MakeIoInstB(int keyword, expression e1, expression e2, expression e3, expression e4)
this function creates a BUFFER IN or BUFFER OUT io statement.
Definition: statement.c:1837
static void resize_StmtHeap_buffer(void)
Definition: statement.c:74
statement LabelToStmt(string l)
this functions looks up in table StmtHeap for the statement s whose label is l.
Definition: statement.c:94
bool first_executable_statement_seen()
Definition: statement.c:1964
instruction MakeSimpleIoInst2(int keyword, expression f, list io_list)
Definition: statement.c:1899
void MakeBlockIfInst(expression e, int elsif)
this function and the two next ones create a block if statement.
Definition: statement.c:1498
string NameOfToken(int token)
Definition: statement.c:1636
instruction MakeAssignedGotoInst(list ll, entity i)
Definition: statement.c:734
#define MAXBLOCK
The purpose of the following data structure is to build the control structure of the procedure being ...
Definition: statement.c:189
static int format_seen
Definition: statement.c:1935
bool IsBlockStackFull()
Definition: statement.c:215
void MakeEndifInst()
Definition: statement.c:1578
void LinkInstToCurrentBlock(instruction i, bool number_it)
this function links the instruction i to the current block of statements.
Definition: statement.c:529
instruction MakeLogicalIfInst(expression e, instruction i)
this function creates a logical if statement.
Definition: statement.c:1329
void MakeWhileDoInst(expression c, string l)
This function creates a while do loop statement.
Definition: statement.c:1262
instruction MakeIoInstA(int keyword, list lci, list lio)
this function creates an IO statement.
Definition: statement.c:1715
static int seen
Are we in the declaration or in the executable part? Have we seen a FORMAT statement before an execut...
Definition: statement.c:1934
void reset_first_statement()
Definition: statement.c:1944
#define UNDEF
Well, some constant defined in reader.c and not deserving a promotion in syntax-local....
Definition: statement.c:1941
statement MakeNewLabelledStatement(entity l, instruction i)
Definition: statement.c:289
void NewStmt(entity e, statement s)
this function stores a new association in table StmtHeap: the label of statement s is e.
Definition: statement.c:141
void MakeEnddoInst()
Definition: statement.c:1611
instruction make_goto_instruction(entity l)
In a "go to" instruction, the label does not appear explictly.
Definition: statement.c:706
static stmt * StmtHeap_buffer
Definition: statement.c:59
instruction MakeAssignInst(syntax l, expression e)
this function creates an affectation statement.
Definition: statement.c:848
static int CurrentStmt
Definition: statement.c:61
instruction MakeSimpleIoInst1(int keyword, expression unit)
Definition: statement.c:1854
instruction PopBlock()
Definition: statement.c:238
static int declaration_lines
Definition: statement.c:1936
int MakeElseInst(bool is_else_p)
This function is used to handle either an ELSE or an ELSEIF construct.
Definition: statement.c:1522