PIPS
cprettyprinter.c
Go to the documentation of this file.
1 /*
2 
3  $Id: cprettyprinter.c 23270 2016-11-02 09:18:27Z 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 
29  Try to prettyprint a Fortran internal representation (RI) in C.
30  Very basic at the time.
31  Functionnal.
32  All arguments are assumed newly allocated.
33  It might be really slow, but it should be safe.
34  I should use some kind of string accumulator (array/list...)
35 
36  print_crough > MODULE.crough
37  < PROGRAM.entities
38  < MODULE.code
39 
40  print_c_code > MODULE.c_printed_file
41  < MODULE.crough
42  */
43 
44 #include <stdio.h>
45 #include <ctype.h>
46 
47 #include "genC.h"
48 #include "linear.h"
49 
50 #include "properties.h"
51 #include "misc.h"
52 #include "pipsdbm.h"
53 
54 #include "ri.h"
55 #include "effects.h"
56 #include "ri-util.h"
57 #include "prettyprint.h"
58 #include "effects-util.h"
59 
60 #include "text-util.h"
61 
62 #define EMPTY ""
63 #define NL "\n"
64 #define SEMICOLON ";" NL
65 #define SPACE " "
66 
67 #define OPENBRACKET "["
68 #define CLOSEBRACKET "]"
69 
70 #define OPENPAREN "("
71 #define CLOSEPAREN ")"
72 
73 #define OPENBRACE "{"
74 #define CLOSEBRACE "}"
75 
76 #define SHARPDEF "#define"
77 #define COMMENT "//" SPACE
78 
79 // extension relative to pipsmake
80 #define INDENT "indent"
81 #define CROUGH ".crough"
82 #define CPRETTY ".c"
83 #define INTERFACE "_interface.f08"
84 
85 // define an extension to append to scalar name in function signature
86 #define SCALAR_IN_SIG_EXT "_p4a_copy"
87 
88 // define some C macro to support some fortran intrinsics
89 #define MAX_FCT "crough_max"
90 #define MIN_FCT "crough_min"
91 #define MAX_DEF "#define " MAX_FCT "(a,b) (((a)>(b))?(a):(b))\n"
92 #define MIN_DEF "#define " MIN_FCT "(a,b) (((a)<(b))?(a):(b))\n"
93 #define POW_PRE "crough_"
94 #define POW_DEF "#define " POW_PRE "powi(a,b) ((a)^(b))\n"
95 #define CMPLX_FCT "init_complex"
96 #define CMPLX_DEF "#define " CMPLX_FCT "(a,b) (a + b*I)\n"
97 
98 /* forward declaration. */
99 static string c_expression(expression,bool);
100 
101 // Create some list to keep track of scalar variable that are arguments of the
102 // function. They need to be renamed in the function signature, copy at
103 // function entrance and updated at fonction output if they have been written.
104 static list l_type = NIL;
105 static list l_name = NIL;
106 static list l_rename = NIL;
107 static list l_entity = NIL;
108 static list l_written = NIL;
109 
110 /**************************************************************** MISC UTILS */
111 
112 #define current_module_is_a_function() \
113  (entity_function_p(get_current_module_entity()))
114 
115 
116 #define RESULT_NAME "result"
117 
118 /**
119  * @brief test if the string looks like a REAL*8 (double in C) declaration
120  * i.e something like 987987D54654 : a bunch of digit with a letter in the
121  * middle. if yes convert it to C (i.e replace D by E) and return true
122  */
123 static bool convert_double_value(char**str) {
124  bool result = true;
125  int match = 0;
126  int i = 0;
127  pips_debug (5, "test if str : %s is a double value. %c 0 = \n", *str, '0');
128  for (i = 0; ((*str)[i] != '\0') && (result == true); i++) {
129  bool cond = ((*str)[i] == 'D') && (match == 0);
130  if (cond == true) {
131  match = i;
132  continue;
133  }
134  result &= (((*str)[i] >= '0') && ((*str)[i] <= '9')) || ((*str)[i] == '.') || (cond);
135  }
136  pips_debug (5, "end with i = %d, match = %d result = %s\n",
137  i, match, (result)?"true":"false");
138  result &= ((*str)[i] == '\0') && (match + 1 != i) && (match != 0);
139  if (result == true) {
140  *str = strdup (*str);
141  (*str)[match] = 'E';
142  }
143  return result;
144 }
145 
146 /*
147  * convert some fortran constant to their equivalent in C
148  */
149 static void const_wrapper(char** s)
150 {
151  static char * const_to_c[][2] = { { ".true." , "1" } , { ".false." , "0" }};
152  static const int const_to_c_sz = sizeof(const_to_c)/sizeof(*const_to_c);
153  int i;
154  pips_debug (5, "constant to convert : %s\n", *s);
155  if (convert_double_value (s) == false) {
156  /* search fortran constant */
157  char *name = strlower(strdup(*s),*s);
158  for(i=0;i<const_to_c_sz;i++)
159  {
160  if(strcmp(name,const_to_c[i][0]) == 0 )
161  {
162  free(*s);
163  *s = strdup(const_to_c[i][1]);
164  break;
165  }
166  }
167  free(name);
168  }
169  pips_debug (5, "constant converted : %s\n", *s);
170 }
171 
172 /*
173  * warning : return allocated string, otherwise it leads to modification (through strlower)
174  * of critical entities
175  */
176 static char* c_entity_local_name(entity var)
177 {
178  const char* name;
179 
181  var != get_current_module_entity() &&
183  )
184  name = RESULT_NAME;
185  else
186  {
187  name = entity_local_name(var);
188 
189  /* Delete all the prefixes */
190 
191  if (strstr(name,STRUCT_PREFIX) != NULL)
192  name = strstr(name,STRUCT_PREFIX) + 1;
193  if (strstr(name,UNION_PREFIX) != NULL)
194  name = strstr(name,UNION_PREFIX) + 1;
195  if (strstr(name,ENUM_PREFIX) != NULL)
196  name = strstr(name,ENUM_PREFIX) + 1;
197  if (strstr(name,TYPEDEF_PREFIX) != NULL)
198  name = strstr(name,TYPEDEF_PREFIX) + 1;
199  if (strstr(name,MEMBER_SEP_STRING) != NULL)
200  name = strstr(name,MEMBER_SEP_STRING) + 1;
201 
202  /* switch to lower cases... */
203 
204  }
205  char *rname=strlower(strdup(name),name);
206  pips_debug (5, "local name %s found\n", rname);
207  return rname;
208 }
209 
210 // build the list of written entity
211 static void build_written_list (list l) {
212  list l_effects = l;
213  FOREACH (EFFECT, eff, l_effects) {
214  if (effect_write_p (eff)) {
215  entity e = effect_any_entity (eff);
217  pips_debug (5, "entity %s (%p) is written\n", entity_local_name (e), e);
218  } else {
219  entity e = effect_any_entity (eff);
220  pips_debug (5, "entity %s (%p) is not written\n", entity_local_name (e), e);
221  }
222  }
223 }
224 
225 //@return true if the entity is in the writen list
226 static bool written_p (entity e) {
227  return gen_in_list_p (e, l_written);
228 }
229 /**************************************************** Function Pre and Postlude */
230 
231 static string scalar_prelude () {
232  string result = NULL;
233  string previous = NULL;
234  list t = l_type;
235  list n = l_name;
236  list r = l_rename;
237  for (; n != NIL && r!= NIL && t!= NIL; n = n->cdr, r = r->cdr, t = t->cdr) {
238  result = strdup (concatenate ((char*) gen_car (t), SPACE,
239  (string) gen_car (n), " = ", "*",
240  (string) gen_car (r), ";\n", previous,
241  NULL));
242  if (previous != NULL) free (previous);
243  previous = result;
244  }
245  return (result == NULL) ? strdup("") : result;
246 }
247 
248 static string scalar_postlude () {
249  string result = NULL;
250  string previous = NULL;
251  list n = l_name;
252  list r = l_rename;
253  list e = l_entity;
254 
255  for (; n != NIL && r != NIL && e != NIL; n = n->cdr, r = r->cdr, e = e->cdr) {
256  if (written_p (gen_car (e))) {
257  result = strdup (concatenate ("*", (string) gen_car (r), " = ",
258  (string) gen_car (n), ";\n", previous, NULL));
259  if (previous != NULL) free (previous);
260  previous = result;
261  pips_debug (5, "entity %s (%p) restored\n",
263  gen_car (e));
264  } else {
265  pips_debug (5, "entity %s (%p) not restored\n",
267  gen_car (e));
268  }
269  }
270  return (result == NULL) ? strdup("") : result;
271 }
272 
273 /// @brief we want to decide if a scalar variable need to be
274 /// passed by pointer or by value to a C function.
275 /// Fortran77 assumes that all scalars are
276 /// passed by pointer. Starting With Fotran95,
277 /// the arguments can be passed by value by using interfaces.
278 /// @return true if the variable has to be passed by pointer
279 /// @param var, the variable to be test as an entity
280 static bool scalar_by_pointer (entity var) {
281  // init result to false
282  bool result = false;
283  if ((get_bool_property ("CROUGH_FORTRAN_USES_INTERFACE") == false)) {
284  // no interface, var is a scalar
285  result = true;
286  }
287  else if ((get_bool_property ("CROUGH_FORTRAN_USES_INTERFACE") == true) &&
288  (get_bool_property ("CROUGH_SCALAR_BY_VALUE_IN_FCT_DECL") == false) &&
289  (written_p (var) == true)) {
290  // interface exists but var is written (and user doesn't use the property
291  // to force the passing of scalar by value)
292  result = true;
293  }
294 
295  return result;
296 }
297 
298 /************************************************************** DECLARATIONS */
299 
300 /*
301  integer a(n,m) -> int a[m][n];
302  parameter (n=4) -> #define n 4
303  */
304 
305 static string c_basic_string(basic b);
306 
307 static string c_type_string(type t)
308 {
309  string result = "UNKNOWN_TYPE" SPACE;
310  switch (type_tag(t))
311  {
312  case is_type_variable:
313  {
315  result = c_basic_string(b);
316  break;
317  }
318  case is_type_void:
319  {
320  result = "void" SPACE;
321  break;
322  }
323  case is_type_struct:
324  {
325  result = "struct" SPACE;
326  break;
327  }
328  case is_type_union:
329  {
330  result = "union" SPACE;
331  break;
332  }
333  case is_type_enum:
334  {
335  result = "enum" SPACE;
336  break;
337  }
338  default:
339  pips_user_warning("case not handled yet \n");
340  }
341  return strdup(result);
342 }
343 
344 // Convert the fortran type to its c string value
345 static string c_basic_string(basic b)
346 {
347  const char* result = "UNKNOWN_BASIC" SPACE;
348  char * aresult=NULL;
349  bool user_type = get_bool_property ("CROUGH_USER_DEFINED_TYPE");
350  switch (basic_tag(b)) {
351  case is_basic_int: {
352  pips_debug(2,"Basic int\n");
353  if (user_type == false) {
354  switch (basic_int(b)) {
355  case 1: result = "char" SPACE;
356  break;
357  case 2: result = "short" SPACE;
358  break;
359  case 4: result = "int" SPACE;
360  break;
361  case 6: result = "long" SPACE;
362  break;
363  case 8: result = "long long" SPACE;
364  break;
365  case 11: result = "unsigned char" SPACE;
366  break;
367  case 12: result = "unsigned short" SPACE;
368  break;
369  case 14: result = "unsigned int" SPACE;
370  break;
371  case 16: result = "unsigned long" SPACE;
372  break;
373  case 18: result = "unsigned long long" SPACE;
374  break;
375  case 21: result = "signed char" SPACE;
376  break;
377  case 22: result = "signed short" SPACE;
378  break;
379  case 24: result = "signed int" SPACE;
380  break;
381  case 26: result = "signed long" SPACE;
382  break;
383  case 28: result = "signed long long" SPACE;
384  break;
385  }
386  } else {
387  result = get_string_property ("CROUGH_INTEGER_TYPE");
388  }
389  break;
390  }
391  case is_basic_float: {
392  if (user_type == false) {
393  switch (basic_float(b)){
394  case 4: result = "float" SPACE;
395  break;
396  case 8: result = "double" SPACE;
397  break;
398  }
399  } else {
400  result = get_string_property ("CROUGH_REAL_TYPE");
401  }
402  break;
403  }
404  case is_basic_logical:
405  result = "int" SPACE;
406  break;
407  case is_basic_string:
408  result = "char" SPACE;
409  break;
410  case is_basic_bit:
411  {
412  /* An expression indeed... To be fixed... */
413  _int i = (_int) basic_bit(b);
414  pips_debug(2,"Bit field basic: %td\n", i);
415  result = "int" SPACE; /* ignore if it is signed or unsigned */
416  break;
417  }
418  case is_basic_pointer:
419  {
420  type t = basic_pointer(b);
421  pips_debug(2,"Basic pointer\n");
422  result = concatenate(c_type_string(t),"* ",NULL);
423  break;
424  }
425  case is_basic_derived:
426  {
427  entity ent = basic_derived(b);
428  type t = entity_type(ent);
429  char* name = c_entity_local_name(ent);
430  result = concatenate(c_type_string(t),name,NULL);
431  free(name);
432  break;
433  }
434  case is_basic_typedef:
435  {
436  entity ent = basic_typedef(b);
437  aresult = c_entity_local_name(ent);
438  break;
439  }
440  case is_basic_complex:
441  result = "complex" SPACE; /* c99 style with include of complex.h*/
442  break;
443  default:
444  pips_internal_error("unhandled case");
445  }
446  return aresult ? aresult : strdup(result);
447 }
448 
449 /// @return a newly allocated string of the dimensions in C
450 /// @param ldim the variable dimension
451 /// @param fct_sig, set to true if the variable is part of a function signature
452 static string c_dim_string(list ldim, bool fct_sig)
453 {
454  string result = "";
455  if (ldim != NIL )
456  {
457  FOREACH(DIMENSION, dim,ldim)
458  {
459  expression elow = dimension_lower(dim);
460  expression eup = dimension_upper(dim);
461  intptr_t low;
462  intptr_t up;
463  string slow;
464  string sup;
465 
466  /* In fact, the lower bound of array in C is always equal to 0,
467  we only need to print (upper dimension + 1)
468  but in order to handle Fortran code, we check all other possibilities
469  and print (upper - lower + 1). Problem : the order of dimensions is reversed !!!! */
470 #if 1
471  if (expression_integer_value(elow, &low))
472  {
473  if (low == 0)
474  {
475  if (expression_integer_value(eup, &up))
476  result = strdup(concatenate(OPENBRACKET,int2a(up+1),CLOSEBRACKET,result,NULL));
477  else
478  /* to be refined here to make more beautiful expression */
479  result = strdup(concatenate(OPENBRACKET,
481  eup,int_to_expression(1))
482  ),
483  CLOSEBRACKET,result,NULL));
484  }
485  else
486  {
487  if (expression_integer_value(eup, &up)) {
488  result = strdup(concatenate(OPENBRACKET,int2a(up-low+1),CLOSEBRACKET,result,NULL));
489  } else {
490  sup = expression_to_string(eup);
491  if (fct_sig == true) {
492  string tmp = NULL;
493  if (get_bool_property ("CROUGH_FORTRAN_USES_INTERFACE") == false) {
494  tmp = strdup (concatenate ("(*",sup, SCALAR_IN_SIG_EXT, ")", NULL));
495  free (sup);
496  sup = tmp;
497  }
498  }
499  result = strdup(concatenate(OPENBRACKET,sup,"-",int2a(low-1),CLOSEBRACKET,result,NULL));
500  free(sup);
501  }
502  }
503  }
504  else
505 #endif
506  {
507  slow = c_expression(elow,false);
508  sup = c_expression(eup,false);
509  result = strdup(concatenate(OPENBRACKET,sup,"-",slow,"+ 1",CLOSEBRACKET,result,NULL));
510  free(slow);
511  free(sup);
512  }
513  }
514  }
515  /* otherwise the list is empty, no dimension to declare */
516  return strlower (strdup (result), result);
517 }
518 
519 static string c_qualifier_string(list l)
520 {
521  string result="";
522  FOREACH(QUALIFIER,q,l)
523  {
524  switch (qualifier_tag(q)) {
526  result = concatenate(result,"register ",NULL);
527  break;
528  case is_qualifier_thread:
529  result = concatenate(result,"__thread ",NULL);
530  break;
531  case is_qualifier_const:
532  result = concatenate(result,"const ",NULL);
533  break;
535  result = concatenate(result,"restrict ",NULL);
536  break;
538  result = concatenate(result,"volatile ",NULL);
539  break;
540  case is_qualifier_auto:
541  result = concatenate(result,"auto ",NULL);
542  break;
543  case is_qualifier_asm:
544  result = concatenate(result,"__asm(",qualifier_asm(q),") ", NULL);
545  break;
547  result = concatenate(result,"static ",NULL);
548  break;
549  default:
550  pips_internal_error("Unknown qualifier tag %d.\n", qualifier_tag(q));
551  }
552  }
553  return strdup(result);
554 }
555 
557 {
558  string result = "{";
560 
561  bool first = true;
562  FOREACH (EXPRESSION,e,args)
563  {
564  if (brace_expression_p(e))
565  result = strdup(concatenate(result,first?"":",",
566  c_brace_expression_string(e),NULL));
567  else
568  result = strdup(concatenate(result,first?"":",",
569  expression_to_string(e),NULL));
570  first = false;
571  }
572  result = strdup(concatenate(result,"}",NULL));
573  return result;
574 }
575 
576 /// @param var, the variable to get the c declaration
577 /// @param fct_sig, set to true if the variable is part of a function signature
578 static string this_entity_cdeclaration(entity var, bool fct_sig)
579 {
580  string result = NULL;
581  //string name = entity_local_name(var);
582  type t = entity_type(var);
583  storage s = entity_storage(var);
584  pips_debug(2,"Entity name : %s\n",entity_name(var));
585  /* Many possible combinations */
586 
587  /* This is a typedef name, what about typedef int myint[5] ??? */
588  if (typedef_entity_p(var))
589  {
590  string tmp = NULL;
591  tmp=c_entity_local_name(var);
592  result = strdup(concatenate("typedef ", c_type_string(t),SPACE,tmp,NULL));
593  free(tmp);
594  return result;
595  }
596 
597  switch (storage_tag(s)) {
598  case is_storage_rom:
599  {
600  value va = entity_initial(var);
601  if (!value_undefined_p(va))
602  {
603  constant c = NULL;
604  if (value_constant_p(va))
605  c = value_constant(va);
606  else if (value_symbolic_p(va))
608  if (c)
609  {
610  if (constant_int_p(c))
611  {
612  string sval = int2a(constant_int(c));
613  string svar = c_entity_local_name(var);
616  string sbasic = basic_to_string(entity_basic(var));
618  asprintf(&result,"static const %s %s = %s\n",sbasic,svar,sval);
619  free(sval);
620  free(svar);
621  free(sbasic);
622  return result;
623  }
624  /*What about real, double, string, ... ?*/
625  }
626  }
627  break;
628  }
629  case is_storage_ram:
630  {
631  /* ram r = storage_ram(s);
632  entity sec = ram_section(r);
633  if ((sec == CurrentSourceFileStaticArea) || (sec == CurrentStaticArea))
634  result = "static ";*/
635  break;
636  }
637  default:
638  break;
639  }
640 
641  switch (type_tag(t)) {
642  case is_type_variable:
643  {
644  variable v = type_variable(t);
645  string sptr, st, sd, svar, sq, ext;
646  value val = entity_initial(var);
648  sd = c_dim_string(variable_dimensions(v), fct_sig);
650  svar = c_entity_local_name(var);
651 
652  // In the case of a signature check if the scalars need to
653  // be passed by pointers. If the check return true
654  // a "*" must be added
655  if ((fct_sig == true) && (variable_dimensions(v) == NIL) &&
656  (scalar_by_pointer (var) == true)) {
657  ext = SCALAR_IN_SIG_EXT;
658  sptr = "*";
659  l_type = gen_string_cons(strdup(concatenate(sq, st, NULL)),
660  l_type);
661  l_name = gen_string_cons(strdup(concatenate(svar, NULL)),
662  l_name);
663  l_rename = gen_string_cons(strdup(concatenate(svar,ext,NULL)),
664  l_rename);
666  }
667  // In case of a signature check if the arrays need to
668  // be passed by pointers. If the check return true
669  // a "*" must be added and the dim must be remove
670  else if ((fct_sig == true) && (variable_dimensions(v) != NIL) &&
671  (get_bool_property("CROUGH_ARRAY_PARAMETER_AS_POINTER") == true)) {
672  ext = "";
673  sptr = "*";
674  free (sd);
675  sd = strdup ("");
676  }
677  else {
678  ext = "";
679  sptr = "";
680  }
681 
682 
683  /* problems with order !*/
684  result = strdup(concatenate(sq, st, sptr, SPACE, svar, ext,
685  sd, NULL));
686  free(svar);
687  if (!value_undefined_p(val))
688  {
689  if (value_expression_p(val))
690  {
692  if (brace_expression_p(exp))
693  result = strdup(concatenate(result,"=",
695  else
696  result = strdup(concatenate(result,"=",
698  NULL));
699  }
700  }
701  if (basic_bit_p(variable_basic(v)))
702  {
703  /* It is an expression... */
704  _int i = (_int) basic_bit(variable_basic(v));
705  pips_debug(2,"Basic bit %td",i);
706  result = strdup(concatenate(result,":",int2a(i),NULL));
707  user_error("this_entity_cdeclaration",
708  "Bitfield to be finished...");
709  }
710  free(st);
711  free(sd);
712  break;
713  }
714  case is_type_struct:
715  {
716  list l = type_struct(t);
717  string tmp =NULL;
718  tmp = c_entity_local_name(var);
719  result = strdup(concatenate("struct ",tmp, "{", NL,NULL));
720  free(tmp);
721  MAP(ENTITY,ent,
722  {
723  string s = this_entity_cdeclaration(ent, fct_sig);
724  result = strdup(concatenate(result, s, SEMICOLON, NULL));
725  free(s);
726  },l);
727  result = strdup(concatenate(result,"}", NULL));
728  break;
729  }
730  case is_type_union:
731  {
732  list l = type_union(t);
733  string tmp =NULL;
734  tmp = c_entity_local_name(var);
735  result = strdup(concatenate("union ",tmp, "{", NL,NULL));
736  free(tmp);
737  MAP(ENTITY,ent,
738  {
739  string s = this_entity_cdeclaration(ent, fct_sig);
740  result = strdup(concatenate(result, s, SEMICOLON, NULL));
741  free(s);
742  },l);
743  result = strdup(concatenate(result,"}", NULL));
744  break;
745  }
746  case is_type_enum:
747  {
748  list l = type_enum(t);
749  bool first = true;
750  string tmp = NULL;
751  tmp = c_entity_local_name(var);
752  result = strdup(concatenate("enum ", tmp, " {",NULL));
753  free(tmp);
754  MAP(ENTITY,ent,
755  {
756  tmp = c_entity_local_name(ent);
757  result = strdup(concatenate(result,first?"":",",tmp,NULL));
758  free(tmp);
759  first = false;
760  },l);
761  result = strdup(concatenate(result,"}", NULL));
762  break;
763  }
764  default:
765  break;
766  }
767 
768  return result? result: strdup("");
769 }
770 
771 static bool parameter_p(entity e)
772 {
773  /* Constant variables */
774  return storage_rom_p(entity_storage(e)) &&
777 }
778 
779 static bool variable_p(entity e)
780 {
781  storage s = entity_storage(e);
782  return type_variable_p(entity_type(e)) &&
783  (storage_ram_p(s) || storage_return_p(s));
784 }
785 
787 {
788  return parameter_p(e) || variable_p(e);
789 }
790 
791 /// @return true if the entity is an argument
792 static bool argument_p(entity e)
793 {
794  /* Formal variables */
795  return type_variable_p(entity_type(e)) &&
797 }
798 
799 /// @return the string representation of the given declarations.
800 /// @param module, the module to get the declaration.
801 /// @param consider_this_entity, the function test pointer.
802 /// @param separator, the separatot to be used between vars.
803 /// @param lastsep, set to true if a final separator is needed.
804 /// @param fct_sig, set to true if in a function signature.
805 static string c_declarations(
806  entity module,
807  bool (*consider_this_entity)(entity),
808  string separator,
809  bool lastsep,
810  bool fct_sig
811  )
812 {
813  string result = strdup("");
814  code c;
815  bool first = true;
816 
817  pips_assert("it is a code", value_code_p(entity_initial(module)));
818 
821  {
822  string tmp = NULL;
823  tmp = c_entity_local_name(var);
824  pips_debug(2, "Prettyprinter declaration for variable :%s\n",tmp);
825  free(tmp);
826  if (consider_this_entity(var))
827  {
828  string old = result;
829  string svar = this_entity_cdeclaration(var, fct_sig);
830  pips_debug(6, "svar = %s\n", svar);
831  result = strdup(concatenate(old, !first ? separator: "",
832  svar, NULL));
833  pips_debug(6, "result = %s\n", result);
834  free(svar);
835  free(old);
836  first = false;
837  }
838  }
839  // insert the last separtor if required and if at least one declaration
840  // has been inserted.
841  if (lastsep && !first)
842  result = strdup(concatenate(result, separator, NULL));
843  return result;
844 }
845 /******************************************************************* INCLUDE */
846 static string c_include (void) {
847  string result = NULL;
848 
849  // add some c include files in order to support fortran intrinsic
850  result = strdup (concatenate ("//needed include to compile the C output\n"
851  "#include \"math.h\"\n", // fabs
852  "#include \"stdlib.h\"\n", // abs
853  "#include \"complex.h\"\n", // abs
854  "\n",
855  NULL));
856 
857  // take care of include file required by the user
858  const char* user_req = get_string_property ("CROUGH_INCLUDE_FILE_LIST");
859  pips_debug (5, "including the user file list %s\n", user_req);
860  string match = NULL;
861  string tmp = strdup(user_req);
862  match = strtok (tmp, " ,");
863  while (match != NULL) {
864  string old = result;
865  pips_debug (7, "including the file %s\n", match);
866  result = strdup (concatenate (result, "#include \"", match, "\"\n", NULL));
867  match = strtok (NULL, " ,");
868  free (old);
869  }
870  free (match);free(tmp);
871 
872  // user might use its own type that are define in a specific file
873  bool user_type = get_bool_property ("CROUGH_USER_DEFINED_TYPE");
874  pips_debug (5, "includind the user define type file %s\n", user_req);
875  if (user_type == true) {
876  string old = result;
877  const char* f_name = get_string_property ("CROUGH_INCLUDE_FILE");
878  pips_debug (7, "including the file %s\n", f_name);
879  result = strdup (concatenate (result, "#include \"", f_name, "\"\n",
880  NULL));
881  free (old);
882  }
883  pips_debug (5, "include string : %s\n", result);
884  return result;
885 }
886 
887 /********************************************************************* MACRO */
888 static string c_macro (void) {
889  string result = NULL;
890  // add some macro to support fortran intrinsics
891  result = strdup (concatenate ("// The macros to support some fortran intrinsics\n",
892  "// and complex declaration\n"
893  MAX_DEF, MIN_DEF, POW_DEF, CMPLX_DEF, "\n",
894  NULL));
895  return result;
896 }
897 
898 /********************************************************************** HEAD */
899 
900 /* returns the head of the function/subroutine/program.
901  declarations look ANSI C.
902  */
903 #define MAIN_DECLARATION "int main(int argc, char *argv[])" NL
904 
905 static string c_head(entity module)
906 {
907  string result;
908 
909  pips_assert("it is a function", type_functional_p(entity_type(module)));
910 
912  /* another kind : "int main(void)" ?*/
913  result = strdup(MAIN_DECLARATION);
914  }
915  else {
916  string head, args, svar;
918 
919  /* define type head. */
920  if (get_bool_property ("DO_RETURN_TYPE_AS_TYPEDEF") == true) {
921  head = strdup (get_string_property ("SET_RETURN_TYPE_AS_TYPEDEF_NEW_TYPE"));
922  }
923  else if (entity_subroutine_p(module)) {
924  head = strdup("void");
925  }
926  else {
927  variable v;
928  pips_assert("type of result is a variable",
931  head = c_basic_string(variable_basic(v));
932  }
933 
934  /* define args. */
936  {
937  args = c_declarations(module, argument_p, ", ", false, true);
938  }
939  else
940  {
941  args = strdup("void");
942  }
943 
944  svar = c_entity_local_name(module);
945  if (get_bool_property("PRETTYPRINT_C_FUNCTION_NAME_WITH_UNDERSCORE"))
946 
947  result = strdup(concatenate(head, SPACE, svar, "_",
948  OPENPAREN, args, CLOSEPAREN, NL, NULL));
949 
950  else
951  result = strdup(concatenate(head, SPACE, svar,
952  OPENPAREN, args, CLOSEPAREN, NL, NULL));
953 
954  free(svar);
955  free(head);
956  free(args);
957  }
958 
959  return result;
960 }
961 
962 /*************************************************************** EXPRESSIONS */
963 
964 /* generate a basic c expression.
965  no operator priority is assumed...
966  */
967 typedef string (*prettyprinter)(const char*, list);
968 
969 struct s_ppt
970 {
971  char * intrinsic;
972  char * c;
974 };
975 
976 // Define a struct to easily find the function full name according to its
977 // base_name. Basically some letters are prepend or append according to the
978 // size ant type of the opperand. For example abs can become absl or fabsf.
979 typedef struct
980 {
981  char * c_base_name;
982  enum basic_utype type;
984  char* prefix;
985  char* suffix;
986 } c_full_name;
987 
989 
990 static string ppt_binary(const char* in_c, list le)
991 {
992  string result;
993  expression e1, e2;
994  string s1, s2;
995  bool p1, p2;
996 
997  pips_assert("2 arguments to binary call", gen_length(le)==2);
998 
999  e1 = EXPRESSION(CAR(le));
1001  s1 = c_expression(e1,false);
1002 
1003  e2 = EXPRESSION(CAR(CDR(le)));
1005  s2 = c_expression(e2,false);
1006 
1007  result = strdup(concatenate(p1? OPENPAREN: EMPTY, s1, p1? CLOSEPAREN: EMPTY,
1008  SPACE, in_c, SPACE,
1009  p2? OPENPAREN: EMPTY, s2, p2? CLOSEPAREN: EMPTY,
1010  NULL));
1011 
1012  free(s1);
1013  //free(s2);
1014 
1015  return result;
1016 }
1017 
1018 static string ppt_unary(const char* in_c, list le)
1019 {
1020  string e, result;
1021  pips_assert("one arg to unary call", gen_length(le)==1);
1022  e = c_expression(EXPRESSION(CAR(le)),false);
1023  result = strdup(concatenate(in_c, SPACE, e, NULL));
1024  free(e);
1025  return result;
1026 }
1027 
1028 static string ppt_unary_post(const char* in_c, list le)
1029 {
1030  string e, result;
1031  pips_assert("one arg to unary call", gen_length(le)==1);
1032  e = c_expression(EXPRESSION(CAR(le)),false);
1033  result = strdup(concatenate(e, SPACE, in_c, NULL));
1034  free(e);
1035  return result;
1036 }
1037 
1038 /* SG: PBM spotted HERE */
1039 static string ppt_call(const char* in_c, list le)
1040 {
1041  string scall, old;
1042  bool pointer = !get_bool_property ("CROUGH_SCALAR_BY_VALUE_IN_FCT_CALL");
1043  if (le == NIL)
1044  {
1045  scall = strdup(concatenate(in_c, "()", NULL));
1046  }
1047  else
1048  {
1049  bool first = true;
1050  scall = strdup(concatenate(in_c, OPENPAREN, NULL));
1051 
1052  /* Attention: not like this for io statements*/
1053  FOREACH (EXPRESSION, e, le)
1054  {
1055  string arg = c_expression(e,false);
1056  old = scall;
1057  scall = strdup(concatenate(old, first? "" : ", ",
1058  expression_scalar_p(e) && pointer ? "&" : "",
1059  arg, NULL));
1060  free(arg);
1061  free(old);
1062  first = false;
1063  }
1064 
1065  old = scall;
1066  scall = strdup(concatenate(old, CLOSEPAREN, NULL));
1067  free(old);
1068  }
1069  return scall;
1070 }
1071 
1073  {"abs" , is_basic_int , 1 , "" , "" }, //char
1074  {"abs" , is_basic_int , 2 , "" , "" }, //short
1075  {"abs" , is_basic_int , 4 , "" , "" }, //int
1076  {"abs" , is_basic_int , 6 , "l" , "" }, //long
1077  {"abs" , is_basic_int , 8 , "ll" , "" }, //long long
1078  {"abs" , is_basic_float , 4 , "f" , "f"}, //float
1079  {"abs" , is_basic_float , 8 , "f" , "" }, //double
1080  {"abs" , is_basic_complex , 8 , "c" , "f"}, //float complex
1081  {"abs" , is_basic_complex , 16 , "c" , "" }, //double complex
1082  {"pow" , is_basic_int , 1 , POW_PRE, "i"}, //char
1083  {"pow" , is_basic_int , 2 , POW_PRE, "i"}, //short
1084  {"pow" , is_basic_int , 4 , POW_PRE, "i"}, //int
1085  {"pow" , is_basic_int , 6 , POW_PRE, "i"}, //long
1086  {"pow" , is_basic_int , 8 , POW_PRE, "i"}, //long long
1087  {"pow" , is_basic_float , 4 , "" , "f"}, //float
1088  {"pow" , is_basic_float , 8 , "" , "" }, //double
1089  {"pow" , is_basic_complex , 8 , "c" , "f"}, //float complex
1090  {"pow" , is_basic_complex , 16 , "c" , "" }, //double complex
1091  {NULL , is_basic_int , 0 , "" , "" }
1092 };
1093 
1094 /// @brief fill the c_base_name to get the c full name accorgind to its basic
1095 static void get_c_full_name (string* base_in_c, basic b) {
1096  pips_debug (7, "find the C function for \"%s\" according to the basic\n",
1097  *base_in_c);
1098  pips_assert ("cant deal with basic undefined", b != basic_undefined);
1099  // initialize some varaibles
1101  enum basic_utype type = basic_tag (b);
1102  intptr_t size = basic_type_size (b);
1103 
1104  // find the correct row
1105  while ((table->c_base_name != NULL) &&
1106  !(same_string_p(*base_in_c, table->c_base_name) &&
1107  (table->type == type) &&
1108  (table->size == size)))
1109  table++;
1110  if (table->c_base_name == NULL) {
1111  pips_internal_error("can not determin the c function to call");
1112  }
1113  str_append (base_in_c, table->suffix);
1114  str_prepend (base_in_c, table->prefix);
1115  return;
1116 }
1117 
1118 // fortran intrinsic accepts different types but c function only
1119 // accept one type. This type of intrinsic is handle by this ppt_math
1120 // function, it calls the right c function according to its input types.
1121 static string ppt_math(const char* in_c, list le)
1122 {
1123  basic res_basic = basic_undefined;
1124  pips_assert ("need at least one argument", 0 != gen_length (le));
1125  FOREACH (EXPRESSION, exp, le) {
1126  pips_debug (7, "let's analyse the expression to find the involved types\n");
1127  type tmp = expression_to_type (exp);
1128  pips_assert ("type must be a variable", type_variable_p (tmp) == true);
1129  basic cur_b = variable_basic (type_variable (tmp));
1130  pips_assert ("expression_to_type returns a basic undefined",
1131  cur_b != basic_undefined);
1132  if (res_basic == basic_undefined) {
1133  res_basic = copy_basic (cur_b);
1134  }
1135  else {
1136  basic old = res_basic;
1137  res_basic = basic_maximum (old, cur_b);
1138  free_basic (old);
1139  pips_assert ("expression_to_type returns a basic undefined",
1140  !basic_overloaded_p (res_basic));
1141  }
1142  free_type (tmp);
1143  }
1144  string str_copy = strdup (in_c);
1145  get_c_full_name (&str_copy, res_basic);
1146  string result = ppt_call (str_copy, le);
1147  if (res_basic != basic_undefined)
1148  free_basic (res_basic);
1149  free (str_copy);
1150  return result;
1151 }
1152 
1153 // fortran min and max intrinsic accept from 2 to n elements. This can be done
1154 // in c using an ellipse or using a simple macro. The second possibility is
1155 // chosen
1156 static string ppt_min_max (const char* in_c, list le)
1157 {
1158  bool flag = false;
1159  bool pointer = !get_bool_property ("CROUGH_SCALAR_BY_VALUE_IN_FCT_CALL");
1160  expression exp = EXPRESSION (CAR (le));
1161  string arg = c_expression (exp, false);
1162  string result = strdup(concatenate ((expression_scalar_p(exp) &&
1163  pointer)? "&" : "", arg, NULL));
1164  POP (le);
1165  free (arg);
1166 
1167  FOREACH (EXPRESSION, e, le){
1168  arg = c_expression(e,false);
1169  string old = result;
1170  result = strdup(concatenate(in_c , OPENPAREN, old, ", ",
1171  expression_scalar_p(e) && pointer ? "&" : "",
1172  arg, CLOSEPAREN, NULL));
1173  free(arg);
1174  free(old);
1175  flag = true;
1176  }
1177 
1178  pips_assert ("min and max should have at least 2 arguments", flag == true);
1179  return result;
1180 }
1181 
1182 // @brief Generate a pips_user_error for intrinsic that can not be handle
1183 // right now according to the property defined by the user
1184 ///@param in_f, the instrinsic in fortran
1185 static string ppt_unknown(const char* in_f, list le)
1186 {
1187  if (get_bool_property ("CROUGH_PRINT_UNKNOWN_INTRINSIC") == false)
1188  pips_user_error ("This intrinsic can not be tranbslated in c: %s\n", in_f);
1189  string result = ppt_call (in_f, le);
1190  return result;
1191 }
1192 
1193 // @brief Generate a pips_user_error for intrinsic that must not be fined in a
1194 // fortran code
1195 ///@param in_f, the instrinsic in fortran
1196 static string ppt_must_error(const char* in_f, _UNUSED_ list le)
1197 {
1198  string result = strdup ("");
1199  pips_user_error("This intrinsic should not be found in a fortran code: %s\n",
1200  in_f);
1201  return result;
1202 }
1203 
1204 static struct s_ppt intrinsic_to_c[] = {
1205  { "+" , "+" , ppt_binary },
1206  { "-" , "-" , ppt_binary },
1207  { "/" , "/" , ppt_binary },
1208  { "*" , "*" , ppt_binary },
1209  { "--" , "-" , ppt_unary },
1210  { "=" , "=" , ppt_binary },
1211  { ".OR." , "||" , ppt_binary },
1212  { ".AND." , "&&" , ppt_binary },
1213  { ".NOT." , "!" , ppt_unary },
1214  { ".LT." , "<" , ppt_binary },
1215  { ".GT." , ">" , ppt_binary },
1216  { ".LE." , "<=" , ppt_binary },
1217  { ".GE." , ">=" , ppt_binary },
1218  { ".EQ." , "==" , ppt_binary },
1219  { ".EQV." , "==" , ppt_binary },
1220  { ".NE." , "!=" , ppt_binary },
1221  { "." , "." , ppt_binary },
1222  { "->" , "->" , ppt_binary },
1223  { "post++" , "++" , ppt_unary_post},
1224  {"post--" , "--" , ppt_unary_post},
1225  {"++pre" , "++" , ppt_unary },
1226  {"--pre" , "--" , ppt_unary },
1227  {"&" , "&" , ppt_unary },
1228  {"*indirection" , "*" , ppt_unary },
1229  {"+unary" , "+" , ppt_unary },
1230  {"-unary" , "-" , ppt_unary },
1231  {"~" , "~" , ppt_unary },
1232  {"!" , "!" , ppt_unary },
1235  {"<<" , "<<" , ppt_binary },
1236  {">>" , ">>" , ppt_binary },
1237  {"<" , "<" , ppt_binary },
1238  {">" , ">" , ppt_binary },
1239  {"<=" , "<=" , ppt_binary },
1240  {">=" , ">=" , ppt_binary },
1241  {"==" , "==" , ppt_binary },
1242  {"!=" , "!=" , ppt_binary },
1243  {"&bitand" , "&" , ppt_binary },
1244  {"^" , "^" , ppt_binary },
1245  {"|" , "|" , ppt_binary },
1246  {"&&" , "&&" , ppt_binary },
1248  {"*=" , "*=" , ppt_binary },
1249  {"/=" , "/=" , ppt_binary },
1250  {"%=" , "%=" , ppt_binary },
1251  {"+=" , "+=" , ppt_binary },
1252  {"-=" , "-=" , ppt_binary },
1253  {"<<=" , "<<=" , ppt_binary },
1254  {">>=" , ">>=" , ppt_binary },
1255  {"&=" , "&=" , ppt_binary },
1256  {"^=" , "^=" , ppt_binary },
1257  {"|=" , "|=" , ppt_binary },
1258  {POWER_OPERATOR_NAME , "pow" , ppt_math },
1259  {MODULO_OPERATOR_NAME , "%" , ppt_binary },
1260  {ABS_OPERATOR_NAME , "abs" , ppt_math },
1261  {IABS_OPERATOR_NAME , "abs" , ppt_call },
1262  {DABS_OPERATOR_NAME , "fabs" , ppt_call },
1263  {CABS_OPERATOR_NAME , "cabsf" , ppt_call },
1264  {CDABS_OPERATOR_NAME , "cabs" , ppt_call },
1279  {MIN1_OPERATOR_NAME , MIN_FCT , ppt_min_max }, // implicit cast
1280  {AMIN0_OPERATOR_NAME , MIN_FCT , ppt_min_max }, // implicit cast
1284  {MAX0_OPERATOR_NAME , MAX_FCT , ppt_min_max }, // implicit cast
1285  {AMAX0_OPERATOR_NAME , MAX_FCT , ppt_min_max }, // implicit cast
1367  {NULL , NULL , ppt_call }
1368 };
1369 
1370 /* return the prettyprinter structure for c.*/
1371 
1372 static struct s_ppt * get_ppt(entity f)
1373 {
1374  const char* called = entity_local_name(f);
1375  struct s_ppt * table = intrinsic_to_c;
1376  while (table->intrinsic && !same_string_p(called, table->intrinsic))
1377  table++;
1378  return table;
1379 }
1380 
1382 {
1383  syntax s = expression_syntax(e);
1384  switch (syntax_tag(s))
1385  {
1386  case is_syntax_call:
1387  {
1388  struct s_ppt * p = get_ppt(call_function(syntax_call(s)));
1389  return p->ppt==ppt_binary;
1390  }
1391  case is_syntax_reference:
1392  case is_syntax_range:
1393  default:
1394  return false;
1395  }
1396 }
1397 
1398 #define RET "return"
1399 #define CONT "continue"
1400 
1401 static string c_call(call c,bool breakable)
1402 {
1403  entity called = call_function(c);
1404  struct s_ppt * ppt = get_ppt(called);
1405  char* local_name = strdup(entity_local_name(called));
1406  string result = NULL;
1407 
1408  /* special case... */
1409  if (same_string_p(local_name, "RETURN")) {
1410  string copy_out = scalar_postlude ();
1412  result = RET " 0";
1413  else if (current_module_is_a_function())
1414  result = RET SPACE RESULT_NAME;
1415  else
1416  result = RET;
1417  result = strdup(concatenate (copy_out, result, NULL));
1418  free (copy_out);
1419  }
1420  else if (same_string_p(local_name, "CONTINUE") )
1421  {
1422  result = breakable?strdup(CONT):strdup("");
1423  }
1424  else if (call_constant_p(c))
1425  {
1427  result = strlower(strdup(local_name),local_name);
1428  }
1429  else
1430  {
1431  result = ppt->ppt(ppt->c? ppt->c: local_name, call_arguments(c));
1432  string tmp = result;
1433  result=strlower(strdup(result),result);
1434  free(tmp);
1435  }
1436  //free(local_name);
1437 
1438  return result;
1439 }
1440 
1441 /* Attention with Fortran: the indexes are reversed.
1442  And array dimensions in C always rank from 0. BC.
1443 */
1444 static string c_reference(reference r)
1445 {
1446  string result = strdup(EMPTY), old, svar;
1447 
1449 
1451  expression e_tmp;
1452  expression e_lower = dimension_lower(DIMENSION(CAR(l_dim)));
1453  string s;
1454  intptr_t itmp;
1455 
1456  if( !expression_equal_integer_p(e_lower, 0))
1457  e_tmp =
1459  copy_expression(e),
1460  copy_expression(e_lower));
1461  else
1462  e_tmp = copy_expression(e);
1463 
1464  if(expression_integer_value(e_tmp, &itmp))
1465  s = int2a(itmp);
1466  else
1467  s = c_expression( e_tmp,false);
1468 
1469  old = result;
1470  result = strdup(concatenate(OPENBRACKET, s, CLOSEBRACKET,old, NULL));
1471  //free(old);
1472  //free(s);
1473  free_expression(e_tmp);
1474  POP(l_dim);
1475  }
1476 
1477 
1478  old = result;
1480  result = strdup(concatenate(svar, old, NULL));
1481  free(old);
1482  free(svar);
1483  return result;
1484 }
1485 
1486 static string c_expression(expression e,bool breakable)
1487 {
1488  string result = NULL;
1489  syntax s = expression_syntax(e);
1490  switch (syntax_tag(s))
1491  {
1492  case is_syntax_call:
1493  result = c_call(syntax_call(s),breakable);
1494  break;
1495  case is_syntax_range:
1496  result = strdup("range not implemented");
1497  break;
1498  case is_syntax_reference:
1499  result = c_reference(syntax_reference(s));
1500  break;
1501  /* add cast, sizeof here */
1502  default:
1503  pips_internal_error("unexpected syntax tag");
1504  }
1505  return result;
1506 }
1507 
1508 static string c_statement(statement s, bool breakable);
1509 
1510 static string c_unstructured(unstructured u,bool breakable)
1511 {
1512  string result = "";
1513  /* build an arbitrary reverse trail of control nodes */
1514  list trail = unstructured_to_trail(u);
1515  list cc = NIL;
1516  trail = gen_nreverse(trail);
1517  ifdebug(3)
1518  {
1519  printf("Print trail: \n");
1520  dump_trail(trail);
1521  }
1522  /* Copy from text_trail ...*/
1523  for(cc=trail; !ENDP(cc); POP(cc))
1524  {
1525  control c = CONTROL(CAR(cc));
1526  const char* l;
1527  int nsucc = gen_length(control_successors(c));
1529  ifdebug(3)
1530  {
1531  printf("Processing statement:\n");
1532  print_statement(st);
1533  }
1534  switch(nsucc)
1535  {
1536  case 0:
1537  {
1538  printf("nsucc = 0 \n");
1539  result = strdup(concatenate(result,c_statement(st,false),NULL));
1540  break;
1541  }
1542  case 1:
1543  {
1545  printf("nsucc = 1 \n");
1547  !get_bool_property("PRETTYPRINT_CHECK_IO_STATEMENTS"))
1548  {
1549  succ = CONTROL(CAR(CDR(control_successors(succ))));
1551  !get_bool_property("PRETTYPRINT_CHECK_IO_STATEMENTS"))
1552  {
1553 
1554  succ = CONTROL(CAR(CDR(control_successors(succ))));
1555  }
1556  pips_assert("The successor is not a check io statement",
1558  }
1559 
1560  result = strdup(concatenate(result,c_statement(st,false),NULL));
1561  if(statement_does_return(st))
1562  {
1563  if(!ENDP(CDR(cc)))
1564  {
1565  control tsucc = CONTROL(CAR(CDR(cc)));
1566  if(tsucc==succ)
1567  {
1568  break;
1569  }
1570  }
1571  /* A GOTO must be generated to reach the control successor */
1572 
1574  pips_assert("Must be labelled", l!= string_undefined);
1575  result = strdup(concatenate(result,"goto ",l,SEMICOLON,NULL));
1576  }
1577  break;
1578  }
1579  case 2:
1580  {
1581  control succ1 = CONTROL(CAR(control_successors(c)));
1582  control succ2 = CONTROL(CAR(CDR(control_successors(c))));
1584  test t = instruction_test(i);
1585  bool no_endif = false;
1586  string str = NULL;
1587  printf("nsucc = 2 \n");
1588  pips_assert("must be a test", instruction_test_p(i));
1589 
1590  result = strdup(concatenate(result,"if (",c_expression(test_condition(t),breakable), ") {", NL, NULL));
1591  printf("Result = %s\n",result);
1592 
1593  /* Is there a textual successor? */
1594  if(!ENDP(CDR(cc)))
1595  {
1596  control tsucc = CONTROL(CAR(CDR(cc)));
1597  if(tsucc==succ1)
1598  {
1599  if(tsucc==succ2)
1600  {
1601  /* This may happen after restructuring */
1602  printf("This may happen after restructuring\n");
1603  ;
1604  }
1605  else
1606  {
1607  /* succ2 must be reached by GOTO */
1608  printf("succ2 must be reached by GOTO\n");
1610  pips_assert("Must be labelled", l!= string_undefined);
1611  str = strdup(concatenate("}",NL, "else {",NL,"goto ", l, SEMICOLON,"}",NL,NULL));
1612  printf("str = %s\n",str);
1613  }
1614  }
1615  else
1616  {
1617  if(tsucc==succ2)
1618  {
1619  /* succ1 must be reached by GOTO */
1620  printf("succ1 must be reached by GOTO\n");
1622  pips_assert("Must be labelled", l!= string_undefined);
1623  no_endif = true;
1624  }
1625  else
1626  {
1627  /* Both successors must be labelled */
1628  printf("Both successors must be labelled\n");
1630  pips_assert("Must be labelled", l!= string_undefined);
1631  str = strdup(concatenate("goto ", l, SEMICOLON, "}", NL,"else {",NL,NULL));
1633  pips_assert("Must be labelled", l!= string_undefined);
1634  str = strdup(concatenate(str,"goto ", l, SEMICOLON, NULL));
1635  printf("str = %s\n",str);
1636  }
1637  }
1638  }
1639  else
1640  {
1641  /* Both successors must be textual predecessors */
1642  printf("Both successors must be textual predecessors \n");
1644  pips_assert("Must be labelled", l!= string_undefined);
1645  str = strdup(concatenate("goto ", l, SEMICOLON, "}",NL,"else {",NL,NULL));
1647  pips_assert("Must be labelled", l!= string_undefined);
1648  str = strdup(concatenate(str,"goto ", l, SEMICOLON, "}",NL, NULL));
1649  printf("str = %s\n",str);
1650  }
1651 
1652  if(no_endif)
1653  {
1654  printf("No endif\n");
1655  result = strdup(concatenate(result," goto ", l, SEMICOLON, "}",NL,NULL));
1656  printf("Result = %s\n",result);
1657  }
1658  printf("Result before = %s\n",result);
1659  if (str != NULL)
1660  {
1661  printf("str before = %s\n",str);
1662  result = strdup(concatenate(result,str,NULL));
1663  }
1664  printf("Result after = %s\n",result);
1665  break;
1666  }
1667  default:
1668  pips_internal_error("Too many successors for a control node");
1669  }
1670  }
1671 
1672  gen_free_list(trail);
1673  return result;
1674 }
1675 
1676 static string c_test(test t,bool breakable)
1677 {
1678  string result;
1679  bool no_false;
1680  string cond, strue, sfalse;
1681  cond = c_expression(test_condition(t),breakable);
1682  strue = c_statement(test_true(t),breakable);
1683  no_false = empty_statement_p(test_false(t));
1684 
1685  sfalse = no_false? NULL: c_statement(test_false(t),false);
1686 
1687  result = strdup(concatenate("if (", cond, ") {" NL,
1688  strue,
1689  no_false? "}" NL: "} else {" NL,
1690  sfalse, "}" NL, NULL));
1691  free(cond);
1692  free(strue);
1693  if (sfalse) free(sfalse);
1694  return result;
1695 }
1696 
1697 static string c_sequence(sequence seq, bool breakable)
1698 {
1699  string result = strdup(EMPTY);
1701  {
1702  string oldresult = result;
1703  string current = c_statement(s,breakable);
1704  result = strdup(concatenate(oldresult, current, NULL));
1705  free(current);
1706  free(oldresult);
1707  }
1708  return result;
1709 }
1710 
1711 static string c_loop(loop l)
1712 {
1713  /* partial implementation...
1714  However, there is not this kind of loop in C */
1715  string result;
1716  string body = c_statement(loop_body(l),true);
1717  string index = c_entity_local_name(loop_index(l));
1718  range r = loop_range(l);
1719  string low = c_expression(range_lower(r),true);
1720  string up = c_expression(range_upper(r),true);
1721  string theincr = c_expression(range_increment(r),true);
1722  string incr = 0;
1723  if( strcmp(theincr,"1")==0 )
1724  incr = strdup("++");
1725  else
1726  incr = strdup(concatenate( "+=", theincr , NULL ));
1727  free(theincr);
1728  /* what about step*/
1729  result = strdup(concatenate("for (", index, "=", low, "; ",
1730  index, "<=", up, "; ",
1731  index, incr, ")", SPACE, OPENBRACE, NL,
1732  body, CLOSEBRACE, NL, NULL));
1733  free(body);
1734  free(index);
1735  free(incr);
1736  // TODO: There are some allocation bugs in c_expression()
1737  //free(low);
1738  //free(up);
1739  return result;
1740 }
1741 
1742 
1743 static string c_whileloop(whileloop w)
1744 {
1745  /* partial implementation... */
1746  string result;
1747  string body = c_statement(whileloop_body(w),true);
1748  string cond = c_expression(whileloop_condition(w),true);
1750  /*do while and while do loops */
1752  result = strdup(concatenate("while (", cond, ") {" NL,
1753  body, "}" NL, NULL));
1754  else
1755  result = strdup(concatenate("do " NL, "{" NL,
1756  body, "}" NL,"while (", cond, ");" NL, NULL));
1757  free(cond);
1758  free(body);
1759  return result;
1760 }
1761 
1762 static string c_forloop(forloop f)
1763 {
1764  /* partial implementation... */
1765  string result;
1766  string body = c_statement(forloop_body(f),true);
1767  string init = c_expression(forloop_initialization(f),true);
1768  string cond = c_expression(forloop_condition(f),true);
1769  string inc = c_expression(forloop_increment(f),true);
1770  result = strdup(concatenate("for (", init, ";",cond,";",inc,") {" NL,
1771  body, "}" NL, NULL));
1772 
1773  free(inc);
1774  free(cond);
1775  free(init);
1776  free(body);
1777  return result;
1778 }
1779 /**************************************************************** STATEMENTS */
1780 
1781 static string c_statement(statement s, bool breakable)
1782 {
1783  string result;
1786  /*printf("\nCurrent statement : \n");
1787  print_statement(s);*/
1788  switch (instruction_tag(i))
1789  {
1790  case is_instruction_test:
1791  {
1792  test t = instruction_test(i);
1793  result = c_test(t,breakable);
1794  break;
1795  }
1797  {
1798  sequence seq = instruction_sequence(i);
1799  result = c_sequence(seq,breakable);
1800  break;
1801  }
1802  case is_instruction_loop:
1803  {
1804  loop l = instruction_loop(i);
1805  result = c_loop(l);
1806  break;
1807  }
1809  {
1811  result = c_whileloop(w);
1812  break;
1813  }
1815  {
1817  result = c_forloop(f);
1818  break;
1819  }
1820  case is_instruction_call:
1821  {
1822  string scall = c_call(instruction_call(i),breakable);
1823  result = strdup(concatenate(scall, SEMICOLON, NULL));
1824  break;
1825  }
1827  {
1829  result = c_unstructured(u,breakable);
1830  break;
1831  }
1832  case is_instruction_goto:
1833  {
1834  statement g = instruction_goto(i);
1835  entity el = statement_label(g);
1836  const char* l = entity_local_name(el) + sizeof(LABEL_PREFIX) -1;
1837  result = strdup(concatenate("goto ",l, SEMICOLON, NULL));
1838  break;
1839  }
1840  /* add switch, forloop break, continue, return instructions here*/
1841  default:
1842  result = strdup(concatenate(COMMENT, " Instruction not implemented" NL, NULL));
1843  break;
1844  }
1845 
1846  if (!ENDP(l))
1847  {
1848  string decl = "";
1849  MAP(ENTITY, var,
1850  {
1851  string svar;
1852  string tmp = c_entity_local_name(var);
1853  debug(2, "\n In block declaration for variable :", tmp);
1854  free(tmp);
1855  svar = this_entity_cdeclaration(var, false);
1856  decl = strdup(concatenate(decl, svar, SEMICOLON, NULL));
1857  free(svar);
1858  },l);
1859  result = strdup(concatenate(decl,result,NULL));
1860  }
1861 
1862  return result;
1863 }
1864 
1865 /*******************************************************PRINT INTERFACE FCTS */
1866 static string interface_type_string (type t, bool value);
1867 
1868 /// @brief Convert the fortran basic to its interface string value
1869 /// @param b, the basic to be converted to string
1870 /// @param value, set to true if the var has to be passed by value
1871 static string interface_basic_string(basic b, bool value)
1872 {
1873  const char* result = "UNKNOWN_BASIC" SPACE;
1874  char * aresult=NULL;
1875  bool user_type = get_bool_property ("CROUGH_USER_DEFINED_TYPE");
1876  switch (basic_tag(b)) {
1877  case is_basic_int: {
1878  pips_debug(2,"Basic int\n");
1879  if (user_type == false) {
1880  switch (basic_int(b)) {
1881  /* case 1: result = "char"; */
1882  /* break; */
1883  /* case 2: result = "short"; */
1884  /* break; */
1885  case 4:
1886  result = "integer (c_int)";
1887  break;
1888  /* case 6: result = "long"; */
1889  /* break; */
1890  case 8:
1891  result = "integer (c_size_t)";
1892  break;
1893  /* case 11: result = "unsigned char"; */
1894  /* break; */
1895  /* case 12: result = "unsigned short"; */
1896  /* break; */
1897  /* case 14: result = "unsigned int"; */
1898  /* break; */
1899  /* case 16: result = "unsigned long"; */
1900  /* break; */
1901  /* case 18: result = "unsigned long long"; */
1902  /* break; */
1903  /* case 21: result = "signed char"; */
1904  /* break; */
1905  /* case 22: result = "signed short"; */
1906  /* break; */
1907  /* case 24: result = "signed int"; */
1908  /* break; */
1909  /* case 26: result = "signed long"; */
1910  /* break; */
1911  /* case 28: result = "signed long long"; */
1912  /* break; */
1913  default:
1914  pips_assert ("not handle case", false);
1915  break;
1916  }
1917  } else {
1918  result = get_string_property ("CROUGH_INTEGER_TYPE");
1919  }
1920  break;
1921  }
1922  case is_basic_float: {
1923  if (user_type == false) {
1924  switch (basic_float(b)){
1925  case 4: result = "real (c_float)";
1926  break;
1927  case 8: result = "real (c_double)";
1928  break;
1929  }
1930  } else {
1931  result = get_string_property ("CROUGH_REAL_TYPE");
1932  }
1933  break;
1934  }
1935  case is_basic_logical:
1936  result = "integer (c_int)";
1937  break;
1938  case is_basic_string:
1939  result = "character (c_char)";
1940  break;
1941  case is_basic_bit:
1942  pips_internal_error("unhandled case");
1943  break;
1944  case is_basic_pointer:
1945  {
1946  if (value == true) {
1947  type t = basic_pointer(b);
1948  pips_debug(2,"Basic pointer\n");
1949  aresult = interface_type_string (t, false);
1950  if (!type_void_p (t))
1951  return aresult;
1952  }
1953  else {
1954  result = "type (c_ptr)";
1955  }
1956  break;
1957  }
1958  case is_basic_derived:
1959  pips_internal_error("unhandled case");
1960  break;
1961  case is_basic_typedef:
1962  pips_internal_error("unhandled case");
1963  default:
1964  pips_internal_error("unhandled case");
1965  }
1966  if (value == true) {
1967  if(!aresult)aresult=strdup(result);
1968  char * tmp =aresult;
1969  aresult = strdup(concatenate (aresult, ", value", NULL));
1970  free(tmp);
1971  return aresult;
1972  }
1973  return strdup(result) ;
1974 }
1975 
1976 /// @param t, the type to be converted to its string representation
1977 /// @param value, set to true if the associated argument is passed by value
1978 /// (i.e. not by pointer)
1979 static string interface_type_string (type t, bool value)
1980 {
1981  string result ;
1982  switch (type_tag(t)) {
1983  case is_type_variable: {
1985  result = interface_basic_string(b, value);
1986  break;
1987  }
1988  case is_type_void: {
1989  result = strdup ("type (c_ptr)");
1990  break;
1991  }
1992  default:
1993  pips_user_error("case not handled yet \n");
1994  // dead code to avoid compiler warnings.
1995  result = NULL;
1996  }
1997  return result;
1998 }
1999 
2000 /// @brief return a string representation of the type to be used
2001 /// for a variable decalaration in an interface module in order to ensure
2002 /// that the C function can be called from fotran codes
2004  pips_assert("this function is deicated to arguments", argument_p(var));
2005  string result = NULL;
2006  type t = entity_type(var);
2007  variable v = type_variable(t);
2008  if (variable_dimensions (v) != NULL) {
2009  result = strdup ("type (c_ptr), value");
2010  } else {
2011  result = interface_type_string(t, true);
2012  }
2013  return result;
2014 }
2015 
2016 /// @return the string representation of the arguments of the given modules
2017 /// to be used as a variable declaration in an interface.
2018 /// @param module, the module to get the declaration.
2019 /// @param separator, the separatot to be used between vars.
2020 /// @param lastsep, set to true if a final separator is needed.
2021 static string interface_argument_declaration (entity module, string separator,
2022  string indent) {
2023  code c;
2024  string tmp = NULL;
2025  string args = strdup ("");
2026  string result = NULL;
2027 
2028  pips_assert("it is a code", value_code_p(entity_initial(module)));
2029 
2032  if (argument_p(var) == true) {
2033  tmp = args;
2034  args = strdup (concatenate (args, indent,
2036  " :: ",
2037  c_entity_local_name (var),
2038  separator,
2039  NULL));
2040  free(tmp);
2041  }
2042  }
2043  result = strdup (args);
2044  free (args);
2045  return result;
2046 }
2047 
2048 /// @brief return the interface signature for a module, i.e. the list of the
2049 /// variable names that are comma serparated.
2051 {
2052  code c = code_undefined;
2053  bool first = true;
2054  string tmp = NULL;
2055  string args = strdup ("(");
2056  string result = NULL;
2057 
2058  pips_assert("it is a function", type_functional_p(entity_type(module)));
2059  pips_assert("it is a code", value_code_p(entity_initial(module)));
2060 
2062 
2064  if (argument_p (var) == true) {
2065  tmp = args;
2066  args = strdup (concatenate (args, first == true ? "" : ", ",
2067  c_entity_local_name (var), NULL));
2068  free(tmp);
2069  first = false;
2070  }
2071  }
2072 
2073  result = strdup (concatenate (args, ")", NULL));
2074  free (args);
2075  return result;
2076 }
2077 
2079 {
2080  string name = NULL;
2081  string decls = NULL;
2082  string result = NULL;
2083  string signature = NULL;
2084 
2085  pips_assert("only available for subroutines, to be implemented for functions",
2087 
2088  name = c_entity_local_name (module);
2089  signature = interface_signature (module);
2090  decls = interface_argument_declaration (module, "\n", "\t\t\t");
2091 
2092  result = strdup(concatenate ("module ", name, "_interface\n",
2093  "\tinterface\n",
2094  "\t\tsubroutine ", name, signature,
2095  " bind(C, name = \"", name, "\")\n",
2096  "\t\t\tuse iso_c_binding\n", decls,
2097  "\t\tend subroutine ", name,
2098  "\n\tend interface\n",
2099  "end module ", name, "_interface\n",
2100  NULL));
2101  free (name);
2102  free (decls);
2103  free (signature);
2104 
2105  return result;
2106 }
2107 
2108 static string c_code_string(entity module, statement stat)
2109 {
2110  string head, decls, body, result, copy_in, include, macro;
2111 
2112  /* What about declarations that are external a module scope ?
2113  Consider a source file as a module entity, put all declarations in it
2114  (external static + TOP-LEVEL) */
2115 
2116  /* before_head only generates the constant declarations, such as #define*/
2117  ifdebug(2)
2118  {
2119  printf("Module statement: \n");
2120  print_statement(stat);
2121  printf("and declarations: \n");
2123  }
2124 
2125  // get the needed includes
2126  include = c_include ();
2127  // get the needed macro
2128  macro = c_macro ();
2129  // function declaration
2130  head = c_head(module);
2131  // What about declarations associated to statements
2133  false);
2134  body = c_statement(stat, false);
2135  copy_in = scalar_prelude ();
2136 
2137  // concatenate everything to get the code
2138  result = concatenate(include, macro, head, OPENBRACE, NL, decls,
2139  copy_in, NL, body, CLOSEBRACE, NL, NULL);
2140 
2141  free (include);
2142  free(head);
2143  free(decls);
2144  free(body);
2145  free(copy_in);
2146  return strdup(result);
2147 }
2148 
2149 /******************************************************** PIPSMAKE INTERFACE */
2150 
2151 bool print_interface (const char* module_name)
2152 {
2153  FILE * out;
2154  string interface_code, interface, dir, filename;
2155  entity module;
2156  statement stat;
2157 
2158  // get what is needed from PIPS DBM
2159  interface = db_build_file_resource_name(DBR_INTERFACE, module_name, INTERFACE);
2162  filename = strdup(concatenate(dir, "/", interface, NULL));
2163  stat = (statement) db_get_memory_resource(DBR_CODE, module_name, true);
2164 
2167 
2168  debug_on("INTERFACE_DEBUG_LEVEL");
2169  pips_debug(1, "Begin print_interface for %s\n", entity_name(module));
2170 
2171  // get the inteface code as a string
2172  interface_code = interface_code_string(module, stat);
2173  pips_debug(1, "end\n");
2174  debug_off();
2175 
2176  /* save to file */
2177  out = safe_fopen(filename, "w");
2178  fprintf(out, "! Fortran interface module for %s. \n", module_name);
2179  fprintf(out, "%s", interface_code);
2180  safe_fclose(out, filename);
2181 
2182  DB_PUT_FILE_RESOURCE(DBR_INTERFACE, module_name, INTERFACE);
2183 
2186 
2187  free (interface_code);
2188  free (dir);
2189  free (filename);
2190 
2191  return true;
2192 }
2193 
2194 bool print_crough(const char* module_name)
2195 {
2196  FILE * out;
2197  string ppt, crough, dir, filename;
2198  entity module;
2199  statement stat;
2200  list l_effect = NULL;
2201 
2202  // get what is needed from PIPS DBM
2203  crough = db_build_file_resource_name(DBR_CROUGH, module_name, CROUGH);
2206  filename = strdup(concatenate(dir, "/", crough, NULL));
2207  stat = (statement) db_get_memory_resource(DBR_CODE, module_name, true);
2208  l_effect = effects_to_list((effects)
2209  db_get_memory_resource(DBR_SUMMARY_EFFECTS,
2210  module_name, true));
2213 
2214  debug_on("CPRETTYPRINTER_DEBUG_LEVEL");
2215  pips_debug(1, "Begin C prettyprrinter for %s\n", entity_name(module));
2216 
2217  // init the list needed for the function pre and postlude
2218  l_type = NIL;
2219  l_name = NIL;
2220  l_rename = NIL;
2221  l_entity = NIL;
2222  l_written = NIL;
2223  // build the list of written entity
2224  build_written_list (l_effect);
2225 
2226  // get the c code as a string
2227  ppt = c_code_string(module, stat);
2228  pips_debug(1, "end\n");
2229  debug_off();
2230 
2231  /* save to file */
2232  out = safe_fopen(filename, "w");
2233  fprintf(out, "/* C pretty print for module %s. */\n", module_name);
2234  fprintf(out, "%s", ppt);
2235  safe_fclose(out, filename);
2236 
2237  // free and reset strin lists
2243  l_type = NIL;
2244  l_name = NIL;
2245  l_rename = NIL;
2246  l_entity = NIL;
2247  l_written = NIL;
2248  free(ppt);
2249  free(dir);
2250  free(filename);
2251 
2252  DB_PUT_FILE_RESOURCE(DBR_CROUGH, module_name, crough);
2253 
2256 
2257  return true;
2258 }
2259 
2260 /* C indentation thru indent.
2261 */
2262 bool print_c_code(const char* module_name)
2263 {
2264  string crough, cpretty, dir, cmd;
2265 
2266  crough = db_get_memory_resource(DBR_CROUGH, module_name, true);
2267  cpretty = db_build_file_resource_name(DBR_C_PRINTED_FILE, module_name, CPRETTY);
2269 
2270  cmd = strdup(concatenate(INDENT, " ",
2271  dir, "/", crough, " -st > ",
2272  dir, "/", cpretty, NULL));
2273 
2274  safe_system(cmd);
2275 
2276  DB_PUT_FILE_RESOURCE(DBR_C_PRINTED_FILE, module_name, cpretty);
2277  free(cmd);
2278  free(dir);
2279 
2280  return true;
2281 }
list gen_entity_cons(entity p, list l)
Definition: ri.c:2537
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_expression(expression p)
Definition: ri.c:853
void free_type(type p)
Definition: ri.c:2658
void free_basic(basic p)
Definition: ri.c:107
static FILE * out
Definition: alias_check.c:128
struct _newgen_struct_type_ * type
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static bool variable_p(entity e)
#define MIN_DEF
static struct s_ppt * get_ppt(entity f)
return the prettyprinter structure for c.
static string scalar_prelude()
static bool argument_p(entity e)
#define COMMENT
static string c_call(call c, bool breakable)
#define CLOSEBRACKET
static string c_type_string(type t)
static string interface_type_string(type t, bool value)
static string ppt_unary(const char *in_c, list le)
static void build_written_list(list l)
static string c_whileloop(whileloop w)
#define OPENBRACE
#define CROUGH
static string this_entity_cdeclaration(entity var, bool fct_sig)
static string interface_basic_string(basic b, bool value)
Convert the fortran basic to its interface string value.
static string ppt_unknown(const char *in_f, list le)
static string ppt_must_error(const char *in_f, _UNUSED_ list le)
#define EMPTY
#define CPRETTY
static void const_wrapper(char **s)
static string c_declarations(entity module, bool(*consider_this_entity)(entity), string separator, bool lastsep, bool fct_sig)
static string c_unstructured(unstructured u, bool breakable)
static string c_statement(statement s, bool breakable)
static string c_sequence(sequence seq, bool breakable)
static c_full_name c_base_name_to_c_full_name[]
static string c_include(void)
static string c_head(entity module)
static string c_expression(expression, bool)
forward declaration.
#define NL
#define INDENT
static string c_qualifier_string(list l)
static string c_macro(void)
static string ppt_binary(const char *in_c, list le)
static bool expression_needs_parenthesis_p(expression)
static char * c_entity_local_name(entity var)
#define SPACE
#define CONT
#define OPENBRACKET
static list l_type
bool print_interface(const char *module_name)
cprettyprinter.c
static void get_c_full_name(string *base_in_c, basic b)
fill the c_base_name to get the c full name accorgind to its basic
#define SCALAR_IN_SIG_EXT
bool print_c_code(const char *module_name)
C indentation thru indent.
static bool scalar_by_pointer(entity var)
we want to decide if a scalar variable need to be passed by pointer or by value to a C function.
static string ppt_unary_post(const char *in_c, list le)
#define POW_DEF
static string interface_code_string(entity module, _UNUSED_ statement stat)
#define CLOSEPAREN
static bool parameter_or_variable_p(entity e)
#define CMPLX_DEF
static string scalar_postlude()
#define MAX_FCT
#define CLOSEBRACE
#define MAX_DEF
static struct s_ppt intrinsic_to_c[]
#define current_module_is_a_function()
static string interface_argument_type_string(entity var)
return a string representation of the type to be used for a variable decalaration in an interface mod...
static string interface_signature(entity module)
return the interface signature for a module, i.e.
bool print_crough(const char *module_name)
static string ppt_min_max(const char *in_c, list le)
#define RESULT_NAME
static string c_code_string(entity module, statement stat)
static string ppt_math(const char *in_c, list le)
static string c_reference(reference r)
Attention with Fortran: the indexes are reversed.
#define MIN_FCT
static list l_written
static string c_loop(loop l)
#define OPENPAREN
static list l_rename
static list l_entity
#define POW_PRE
#define RET
static string c_basic_string(basic b)
static bool parameter_p(entity e)
#define CMPLX_FCT
static string ppt_call(const char *in_c, list le)
SG: PBM spotted HERE.
#define MAIN_DECLARATION
returns the head of the function/subroutine/program.
static string c_test(test t, bool breakable)
static string c_forloop(forloop f)
static bool written_p(entity e)
static string interface_argument_declaration(entity module, string separator, string indent)
#define SEMICOLON
static list l_name
#define INTERFACE
static string c_brace_expression_string(expression exp)
static bool convert_double_value(char **str)
test if the string looks like a REAL*8 (double in C) declaration i.e something like 987987D54654 : a ...
string(* prettyprinter)(const char *, list)
generate a basic c expression.
static string c_dim_string(list ldim, bool fct_sig)
static text include(const char *file)
if the common is declared similarly in all routines, generate "include 'COMMON.h'",...
Definition: declarations2.c:92
#define effect_write_p(eff)
#define effect_any_entity(e)
some useful SHORTHANDS for EFFECT:
list effects_to_list(effects)
Definition: effects.c:209
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
const char * local_name(const char *s)
Does not take care of block scopes and returns a pointer.
Definition: entity_names.c:221
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
char * get_string_property(const char *)
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
void free(void *)
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#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
void gen_free_string_list(list ls)
Definition: list.c:564
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_string_cons(string s, const list l)
Definition: list.c:919
#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
void * gen_car(list l)
Definition: list.c:364
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_FILE_RESOURCE
Put a file resource into the current workspace database.
Definition: pipsdbm-local.h:85
bool check_io_statement_p(statement)
Definition: statement.c:528
bool empty_statement_p(statement)
Test if a statement is empty.
Definition: statement.c:391
bool statement_does_return(statement)
Returns false is no syntactic control path exits s (i.e.
Definition: statement.c:2195
static Value eval(Pvecteur pv, Value val, Variable var)
enum language_utype get_prettyprint_language_tag()
Definition: language.c:67
void set_prettyprint_language_tag(enum language_utype lang)
set the prettyprint language from a language_utype argument
Definition: language.c:143
string db_build_file_resource_name(const char *rname, const char *oname, const char *suffix)
returns an allocated file name for a file resource.
Definition: lowlevel.c:169
#define debug_on(env)
Definition: misc-local.h:157
#define _UNUSED_
Definition: misc-local.h:232
#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 asprintf
Definition: misc-local.h:225
#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 debug_off()
Definition: misc-local.h:160
#define user_error(fn,...)
Definition: misc-local.h:265
#define pips_user_error
Definition: misc-local.h:147
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
void safe_system(string)
system.c
Definition: system.c:38
#define LABEL_PREFIX
Definition: naming-local.h:31
#define TYPEDEF_PREFIX
Definition: naming-local.h:62
#define UNION_PREFIX
Definition: naming-local.h:58
#define ENUM_PREFIX
Definition: naming-local.h:60
#define MEMBER_SEP_STRING
Definition: naming-local.h:53
#define STRUCT_PREFIX
Definition: naming-local.h:56
void str_append(string *, string)
Append the suffix to the string.
Definition: string.c:356
string strlower(string, const char *)
Definition: string.c:228
void str_prepend(string *, string)
Prepend the prefix to the string.
Definition: string.c:342
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define same_string_p(s1, s2)
#define string_undefined
Definition: newgen_types.h:40
char * string
STRING.
Definition: newgen_types.h:39
intptr_t _int
_INT
Definition: newgen_types.h:53
struct cons * list
Definition: newgen_types.h:106
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static char * module
Definition: pips.c:74
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
string expression_to_string(expression e)
Definition: expression.c:77
string basic_to_string(basic)
Definition: type.c:87
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
void dump_trail(list)
Definition: unstructured.c:263
list unstructured_to_trail(unstructured)
Definition: unstructured.c:240
#define NINT_CONVERSION_NAME
#define ATAN2_OPERATOR_NAME
#define DREAL_GENERIC_CONVERSION_NAME
#define MAX_OPERATOR_NAME
#define POWER_OPERATOR_NAME
#define LLE_OPERATOR_NAME
#define CABS_OPERATOR_NAME
#define CEXP_OPERATOR_NAME
#define PRINT_FUNCTION_NAME
#define IDNINT_CONVERSION_NAME
#define FLOAT_GENERIC_CONVERSION_NAME
#define TANH_OPERATOR_NAME
#define COS_OPERATOR_NAME
#define CDABS_OPERATOR_NAME
#define DSIGN_OPERATOR_NAME
#define READ_FUNCTION_NAME
#define ENDFILE_FUNCTION_NAME
#define SIGN_OPERATOR_NAME
#define DMIN1_OPERATOR_NAME
#define ABS_OPERATOR_NAME
#define DBLE_GENERIC_CONVERSION_NAME
#define DACOS_OPERATOR_NAME
#define COSH_OPERATOR_NAME
#define BUFFERIN_FUNCTION_NAME
#define DSQRT_OPERATOR_NAME
#define MINUS_OPERATOR_NAME
#define IDIM_OPERATOR_NAME
#define AINT_CONVERSION_NAME
#define DCMPLX_GENERIC_CONVERSION_NAME
#define DNINT_CONVERSION_NAME
#define CLOG_OPERATOR_NAME
#define DINT_CONVERSION_NAME
#define IABS_OPERATOR_NAME
#define LOG10_OPERATOR_NAME
#define LENGTH_OPERATOR_NAME
#define DCOSH_OPERATOR_NAME
#define DIM_OPERATOR_NAME
#define DIMAG_CONVERSION_NAME
#define SIN_OPERATOR_NAME
#define DLOG10_OPERATOR_NAME
#define DCONJG_OPERATOR_NAME
#define MAX0_OPERATOR_NAME
#define AMIN0_OPERATOR_NAME
#define BACKSPACE_FUNCTION_NAME
#define MIN0_OPERATOR_NAME
#define MAX1_OPERATOR_NAME
#define CONJG_OPERATOR_NAME
#define AMAX0_OPERATOR_NAME
#define expression_scalar_p(e)
#define REWIND_FUNCTION_NAME
#define DMAX1_OPERATOR_NAME
#define CDSQRT_OPERATOR_NAME
#define IFIX_GENERIC_CONVERSION_NAME
#define ACOS_OPERATOR_NAME
#define OPEN_FUNCTION_NAME
#define CDCOS_OPERATOR_NAME
#define CDLOG_OPERATOR_NAME
#define ALOG10_OPERATOR_NAME
#define LLT_OPERATOR_NAME
#define BUFFEROUT_FUNCTION_NAME
#define CCOS_OPERATOR_NAME
#define DPROD_OPERATOR_NAME
#define CDSIN_OPERATOR_NAME
#define ANINT_CONVERSION_NAME
#define INT_TO_CHAR_CONVERSION_NAME
#define CMPLX_GENERIC_CONVERSION_NAME
#define CHAR_TO_INT_CONVERSION_NAME
#define SQRT_OPERATOR_NAME
#define ATAN_OPERATOR_NAME
#define ISIGN_OPERATOR_NAME
#define INT_GENERIC_CONVERSION_NAME
generic conversion names.
#define LGE_OPERATOR_NAME
#define IMPLIED_DCOMPLEX_NAME
Definition: ri-util-local.h:89
#define WRITE_FUNCTION_NAME
#define DABS_OPERATOR_NAME
#define CLOSE_FUNCTION_NAME
#define AMIN1_OPERATOR_NAME
#define DCOS_OPERATOR_NAME
#define EXP_OPERATOR_NAME
#define LOG_OPERATOR_NAME
#define DSIN_OPERATOR_NAME
#define CSQRT_OPERATOR_NAME
#define TAN_OPERATOR_NAME
#define DSINH_OPERATOR_NAME
#define AIMAG_CONVERSION_NAME
#define INDEX_OPERATOR_NAME
#define CDEXP_OPERATOR_NAME
#define FORMAT_FUNCTION_NAME
#define DATAN2_OPERATOR_NAME
#define DDIM_OPERATOR_NAME
#define SINH_OPERATOR_NAME
#define REAL_GENERIC_CONVERSION_NAME
#define MINUS_C_OPERATOR_NAME
#define DEXP_OPERATOR_NAME
#define DLOG_OPERATOR_NAME
#define C_OR_OPERATOR_NAME
#define CSIN_OPERATOR_NAME
#define SNGL_GENERIC_CONVERSION_NAME
#define DTANH_OPERATOR_NAME
#define DFLOAT_GENERIC_CONVERSION_NAME
#define ASIN_OPERATOR_NAME
#define AMAX1_OPERATOR_NAME
#define DASIN_OPERATOR_NAME
#define INQUIRE_FUNCTION_NAME
#define IDINT_GENERIC_CONVERSION_NAME
#define IMPLIED_COMPLEX_NAME
Definition: ri-util-local.h:88
#define LGT_OPERATOR_NAME
#define MIN1_OPERATOR_NAME
#define DATAN_OPERATOR_NAME
#define DTAN_OPERATOR_NAME
#define MODULO_OPERATOR_NAME
#define PLUS_C_OPERATOR_NAME
#define ALOG_OPERATOR_NAME
#define MIN_OPERATOR_NAME
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
bool entity_subroutine_p(entity e)
Definition: entity.c:737
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_main_module_p(entity e)
Definition: entity.c:700
bool typedef_entity_p(entity e)
Definition: entity.c:1902
basic entity_basic(entity e)
return the basic associated to entity e if it's a function/variable/constant basic_undefined otherwis...
Definition: entity.c:1380
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
void print_entities(list l)
Definition: entity.c:167
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
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
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 brace_expression_p(expression e)
Return bool indicating if expression e is a brace expression.
Definition: expression.c:3384
bool expression_equal_integer_p(expression exp, int i)
================================================================
Definition: expression.c:1977
type ultimate_type(type)
Definition: type.c:3466
int basic_type_size(basic)
See also SizeOfElements()
Definition: type.c:1074
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
basic basic_maximum(basic, basic)
Definition: type.c:1816
#define type_functional_p(x)
Definition: ri.h:2950
#define value_undefined_p(x)
Definition: ri.h:3017
#define loop_body(x)
Definition: ri.h:1644
basic_utype
Definition: ri.h:570
@ is_basic_derived
Definition: ri.h:579
@ is_basic_string
Definition: ri.h:576
@ is_basic_float
Definition: ri.h:572
@ is_basic_bit
Definition: ri.h:577
@ is_basic_pointer
Definition: ri.h:578
@ is_basic_int
Definition: ri.h:571
@ is_basic_logical
Definition: ri.h:573
@ is_basic_typedef
Definition: ri.h:580
@ is_basic_complex
Definition: ri.h:575
#define type_struct(x)
Definition: ri.h:2964
#define value_code_p(x)
Definition: ri.h:3065
#define basic_pointer(x)
Definition: ri.h:637
#define qualifier_tag(x)
Definition: ri.h:2175
#define functional_result(x)
Definition: ri.h:1444
#define code_undefined
Definition: ri.h:757
#define storage_formal_p(x)
Definition: ri.h:2522
#define value_constant(x)
Definition: ri.h:3073
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define forloop_initialization(x)
Definition: ri.h:1366
#define call_function(x)
Definition: ri.h:709
#define QUALIFIER(x)
QUALIFIER.
Definition: ri.h:2106
#define reference_variable(x)
Definition: ri.h:2326
#define basic_derived(x)
Definition: ri.h:640
#define basic_int(x)
Definition: ri.h:616
#define range_upper(x)
Definition: ri.h:2290
#define storage_tag(x)
Definition: ri.h:2515
#define type_tag(x)
Definition: ri.h:2940
#define forloop_increment(x)
Definition: ri.h:1370
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define symbolic_constant(x)
Definition: ri.h:2599
#define constant_int(x)
Definition: ri.h:850
#define instruction_loop(x)
Definition: ri.h:1520
#define type_functional(x)
Definition: ri.h:2952
#define instruction_goto(x)
Definition: ri.h:1526
#define test_false(x)
Definition: ri.h:2837
#define dimension_lower(x)
Definition: ri.h:980
#define basic_tag(x)
Definition: ri.h:613
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define code_declarations(x)
Definition: ri.h:784
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#define range_increment(x)
Definition: ri.h:2292
#define storage_ram_p(x)
Definition: ri.h:2519
#define value_constant_p(x)
Definition: ri.h:3071
#define basic_overloaded_p(x)
Definition: ri.h:623
#define value_symbolic(x)
Definition: ri.h:3070
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define basic_typedef(x)
Definition: ri.h:643
#define statement_label(x)
Definition: ri.h:2450
@ is_storage_rom
Definition: ri.h:2494
@ is_storage_ram
Definition: ri.h:2492
#define basic_undefined
Definition: ri.h:556
#define type_enum(x)
Definition: ri.h:2970
#define constant_int_p(x)
Definition: ri.h:848
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ 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_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#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 functional_parameters(x)
Definition: ri.h:1442
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define value_code(x)
Definition: ri.h:3067
#define qualifier_asm(x)
Definition: ri.h:2196
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define syntax_call(x)
Definition: ri.h:2736
#define control_successors(x)
Definition: ri.h:945
#define variable_qualifiers(x)
Definition: ri.h:3124
#define basic_float(x)
Definition: ri.h:619
#define basic_bit(x)
Definition: ri.h:634
#define test_condition(x)
Definition: ri.h:2833
#define instruction_whileloop(x)
Definition: ri.h:1523
#define range_lower(x)
Definition: ri.h:2288
#define variable_dimensions(x)
Definition: ri.h:3122
#define whileloop_body(x)
Definition: ri.h:3162
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
#define storage_rom_p(x)
Definition: ri.h:2525
#define forloop_condition(x)
Definition: ri.h:1368
#define instruction_test_p(x)
Definition: ri.h:1515
#define call_arguments(x)
Definition: ri.h:711
#define control_statement(x)
Definition: ri.h:941
@ is_qualifier_volatile
Definition: ri.h:2129
@ is_qualifier_register
Definition: ri.h:2130
@ is_qualifier_restrict
Definition: ri.h:2128
@ is_qualifier_thread
Definition: ri.h:2132
@ is_qualifier_const
Definition: ri.h:2127
@ is_qualifier_static_dimension
Definition: ri.h:2134
@ is_qualifier_auto
Definition: ri.h:2131
@ is_qualifier_asm
Definition: ri.h:2133
#define instruction_test(x)
Definition: ri.h:1517
@ is_type_void
Definition: ri.h:2904
@ is_type_enum
Definition: ri.h:2907
@ is_type_variable
Definition: ri.h:2900
@ is_type_union
Definition: ri.h:2906
@ is_type_struct
Definition: ri.h:2905
#define whileloop_condition(x)
Definition: ri.h:3160
#define entity_type(x)
Definition: ri.h:2792
#define value_expression_p(x)
Definition: ri.h:3080
#define expression_syntax(x)
Definition: ri.h:1247
#define storage_return_p(x)
Definition: ri.h:2516
#define evaluation_before_p(x)
Definition: ri.h:1159
#define type_variable_p(x)
Definition: ri.h:2947
#define basic_bit_p(x)
Definition: ri.h:632
#define forloop_body(x)
Definition: ri.h:1372
#define value_expression(x)
Definition: ri.h:3082
#define instruction_unstructured(x)
Definition: ri.h:1532
language_utype
Definition: ri.h:1565
@ is_language_c
Definition: ri.h:1567
#define loop_index(x)
Definition: ri.h:1640
#define type_union(x)
Definition: ri.h:2967
#define variable_basic(x)
Definition: ri.h:3120
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
struct _newgen_struct_match_ * match
Definition: sac_private.h:74
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
int printf()
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
#define intptr_t
Definition: stdint.in.h:294
static size_t current
Definition: string.c:115
char * c_base_name
enum basic_utype type
intptr_t size
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
struct cons * cdr
The pointer to the next element.
Definition: newgen_list.h:43
char * intrinsic
prettyprinter ppt
char * int2a(int)
util.c
Definition: util.c:42
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207