PIPS
activate.c
Go to the documentation of this file.
1 /*
2 
3  $Id: activate.c 23412 2017-08-09 15:07:09Z irigoin $
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 <sys/types.h>
33 
34 #include "genC.h"
35 #include "database.h"
36 #include "linear.h"
37 #include "ri.h"
38 #include "properties.h"
39 #include "ri-util.h"
40 #include "pipsdbm.h"
41 #include "pipsmake.h"
42 
43 #include "misc.h"
44 
46 
48 
50 {
51  makefile current_makefile = parse_makefile();
52 
53  if (saved_active_phases == NIL)
56 }
57 
59 {
60  makefile current_makefile = parse_makefile();
61 
62  ifdebug(9) {
63  puts("----- BEFORE RETRIEVING -----");
64  fprint_activated(stdout);
65  }
66 
67  if (saved_active_phases != NIL)
68  {
70  makefile_active_phases(current_makefile) = saved_active_phases;
72 
73  ifdebug(9) {
74  puts("----- AFTER RETREIVING -----");
75  fprint_activated(stdout);
76  }
77  }
78 }
79 
80 bool active_phase_p(const char * phase)
81 {
82  makefile current_makefile = parse_makefile();
83  list apl = makefile_active_phases(current_makefile);
84 
85  FOREACH(STRING, s, apl)
86  if (same_string_p(s, phase))
87  return true; // new line for breakpoints
88 
89  return false;
90 }
91 
92 /* Debugging function */
93 bool saved_active_phase_p(const char * phase)
94 {
96 
97  if(ENDP(sapl)) {
98  fprintf(stderr, "Active phases have not been saved\n");
99  }
100  else {
101  FOREACH(STRING, s, sapl)
102  if (same_string_p(s, phase))
103  return true; // new line for breakpoints
104  }
105 
106  return false;
107 }
108 
109 
110 void fprint_activated(FILE *fd)
111 {
112  makefile m = parse_makefile();
114  fprintf(fd, "%s\n", s);
115 }
116 
117 /* return the phase which would be used to build a given resource.
118  */
119 string active_phase_for_resource(string res)
120 {
121  return rule_phase(find_rule_by_resource(res));
122 }
123 
124 const char * activate_phase(const char * phase)
125 {
126  makefile current_makefile = parse_makefile();
127  bool rule_cyclic_p = true;
128  const char * status = phase;
129 
130  debug_on("PIPSMAKE_DEBUG_LEVEL");
131  pips_debug(1, "%s - requested\n", phase);
132 
133  pips_assert("a current workspace is defined",
135 
136  /* find rule that describes phase */
137  rule r = find_rule_by_phase(phase);
138 
139  if (r == rule_undefined) {
140  if (get_bool_property("PIPSMAKE_WARNINGS"))
141  pips_user_warning("Rule `%s' undefined.\n"
142  "Check spelling and/or ACTIVE_PHASE property.\n",
143  phase);
144  status = NULL;
145  }
146  else if (active_phase_p(phase)) {
147  if (get_bool_property("PIPSMAKE_WARNINGS"))
148  pips_user_warning ("Rule `%s' already active\n", phase);
149  }
150  else if (!gen_length(rule_produced(r))) {
151  // if (get_bool_property("PIPSMAKE_WARNINGS"))
152  pips_user_warning("Phase %s produces no resource\n", phase);
153  status = NULL;
154  }
155  else {
156  // GO: for many produced resources we loop over them
157  // with the same 'old' code
158  // find resource res that is produced by phase
160  bool require_produced_rule_p = false;
161  string vrn = virtual_resource_name(res);
162 
164  string vrn2 = virtual_resource_name(vr);
165  owner vro = virtual_resource_owner(vr);
166 
167  // We do not check callers and callees
168  // I dropped select also, just in case... FC
169  if (!(owner_callers_p(vro) || owner_callees_p(vro) ||
170  owner_select_p(vro)) && same_string_p(vrn, vrn2))
171  require_produced_rule_p = true;
172  }
173 
174  // If the current produced resource is not required by the new rule
175  if (!require_produced_rule_p) {
176  rule_cyclic_p = false;
177  // find current active phase old_phase that produces res
178  string old_phase = rule_phase(find_rule_by_resource(vrn));
179 
180  // replace old_phase by phase in active phase list
181  if (old_phase != NULL) {
182  pips_debug(5, "replacing %s by %s for %s\n", old_phase, phase, vrn);
183  MAPL(pa, {
184  string s = STRING(CAR(pa));
185 
186  if (strcmp(s, old_phase) == 0) {
187  free(STRING(CAR(pa)));
188  STRING(CAR(pa)) = strdup(phase);
189  }
190  }, makefile_active_phases(current_makefile));
191  }
192 
193  // this generates many warnings when called from select...
194  if (get_bool_property("ACTIVATE_DEL_DERIVED_RES"))
196  else
198  // remove resources with the same name as res
199  // to maintain consistency in the database
200  db_unput_resources(vrn);
201  }
202  }
203  }
204 
205  if (rule_cyclic_p == true) {
206  pips_user_warning("Phase %s is cyclic\n", phase);
207  status = NULL;
208  }
209  }
210  debug_off();
211  return status;
212 }
213 
214 const char* activate(const char* phase)
215 {
216  const char* r = activate_phase(phase);
217  if(!r)
218  pips_user_error("Phase activation error: check the phase names\n");
219  return r;
220 }
221 
222 /* Use property ACTIVE_PHASES to active the phases required by the
223  user. */
224 bool activate_phases(void)
225 {
226  string d = " ,\t\n";
227  // strtok breaks its first argument string
228  string ap = strdup(get_string_property("ACTIVE_PHASES"));
229  string cap = strtok(ap, d);
230  bool pips_special =
231  !same_string_p("full", get_string_property("PIPS_VERSION"));
232  bool result = true;
233 
234  while (cap!=NULL) {
235  pips_debug(1, "Phase to activate: %s\n", cap);
236  if (!active_phase_p(cap)) {
237  const char* r = activate_phase(cap);
238  result = r!=NULL;
239  }
240  cap = strtok(NULL, d);
241  }
242  free(ap);
243 
244  // for a specialized pips, accept invalid phase names
245  return pips_special? true: result;
246 }
247 
248 /* Choose the right combination of activate and setproperty for a
249  given language.
250 
251  This is not really compatible with the litterate programming of
252  pipsmake-rc.tex, where this information should be encoded.
253  */
255 {
256  if(language_fortran_p(l)) {
257  /* Usual properties for Fortran */
258  set_bool_property("PRETTYPRINT_STATEMENT_NUMBER", true);
259  set_bool_property("FOR_TO_WHILE_LOOP_IN_CONTROLIZER", false);
260  set_bool_property("FOR_TO_DO_LOOP_IN_CONTROLIZER", false);
261 
262  if(!active_phase_p("PARSER"))
263  activate("PARSER");
264  } else if(language_fortran95_p(l)) {
265  /* Usual properties for Fortran 90/95 */
266  set_bool_property("PRETTYPRINT_STATEMENT_NUMBER", false);
267  set_bool_property("FOR_TO_WHILE_LOOP_IN_CONTROLIZER", false);
268  set_bool_property("FOR_TO_DO_LOOP_IN_CONTROLIZER", false);
269 
270  // Temporary fix for autogenerated file
271  if(!active_phase_p("PARSER"))
272  activate("PARSER");
273  } else if(language_c_p(l)) {
274  /* Usual properties for C */
275  set_bool_property("PRETTYPRINT_STATEMENT_NUMBER", false);
276  set_bool_property("FOR_TO_WHILE_LOOP_IN_CONTROLIZER", true);
277  set_bool_property("FOR_TO_DO_LOOP_IN_CONTROLIZER", true);
278 
279  if(!active_phase_p("C_PARSER"))
280  activate("C_PARSER");
281  // No longer useful
282  //if(!active_phase_p("C_SYMBOL_TABLE"))
283  // activate("C_SYMBOL_TABLE");
284  }
285  else {
286  /* The language is unknown*/
287  pips_user_warning("Unknown language initialization\n");
288  }
289 }
290 
291 /*
292  * get the set of resources being derived from a given one
293  */
294 static void get_more_derived_resources (vrn, set_of_res)
295 string vrn;
296 set set_of_res;
297 {
298  makefile m = parse_makefile();
299  rule r;
300 
301  /* If the given resource is not in the set */
302  if (set_belong_p (set_of_res, (char *) vrn))
303  return;
304 
305  /* put it into the set */
306  set_add_element (set_of_res, set_of_res, (char *) vrn);
307 
308  pips_debug(8, "got %s\n", vrn);
309 
310  /* For all active phases*/
311  MAPL(pa, {
312 
313  r = find_rule_by_phase(STRING(CAR(pa)));
314 
315  if (rule_use_resource_produced(r) == true)
316  debug(9, "get_more_derived_resources",
317  "Don't scan cycling phase %s\n",STRING(CAR(pa)));
318  else
319  {
320  debug(9, "get_more_derived_resources",
321  "Scan phase %s\n",STRING(CAR(pa)));
322 
323  /* Search in the required rules */
324  MAPL(pvr, {
326  string vrn2 = virtual_resource_name(res2);
327 
328  /* If the resource names are equal */
329  if (same_string_p(vrn, vrn2)) {
330 
331  debug(9, "get_more_derived_resources",
332  "Resource %s is required by phase %s\n",
333  vrn, STRING(CAR(pa)));
334 
335  /* make a recursion for all the produced rules */
336  MAPL(pvr3, {
337  virtual_resource res3 = VIRTUAL_RESOURCE(CAR(pvr3));
338  string vrn3 = virtual_resource_name(res3);
339  /* Here, there is no infinite loop problem
340  with rule producing a ressource they require,
341  because the resource has already been had
342  to the set */
343  get_more_derived_resources(vrn3, set_of_res);
344  }, (list) rule_produced ( r ) );
345  break;
346  }
347  }, (list) rule_required( r ) );
348  }
349  }, makefile_active_phases(m));
350 }
351 ␌
352 /* Test if a rule uses a resource it produces */
354 rule r;
355 {
356  MAPL(pvrp, {
357  /* find resource res that is produced by phase */
359  string vrn = virtual_resource_name(res);
360 
361  MAPL(pvr, {
363  string vrn2 = virtual_resource_name(vr);
364  /* owner vro = virtual_resource_owner(vr); */
365 
366  /* We DO check callers and callees (DB,08/96) */
367  /* if ( owner_callers_p(vro) || owner_callees_p(vro) ) {}
368  else
369  */
370  if (same_string_p(vrn, vrn2))
371  return true;
372  }, (list) rule_required( r ) );
373 
374  }, (list) rule_produced( r ) );
375 
376  return false;
377 }
378 
379 /*
380  * Delete the resources derived from a given one
381  */
383 {
384  set s = set_make (set_pointer);
385  string vrn = virtual_resource_name(res);
386  /* Get the set of virtual resource to destroy */
388  SET_MAP(se, delete_named_resources((string) se), s);
389  set_free(s);
390 }
391 
392 
393 
394 
395 
396 
int db_unput_resources(const char *rname)
Delete all the resources of a given type "rname".
Definition: database.c:915
static void get_more_derived_resources(string vrn, set set_of_res)
Definition: activate.c:294
bool active_phase_p(const char *phase)
Definition: activate.c:80
const char * activate(const char *phase)
Definition: activate.c:214
bool saved_active_phase_p(const char *phase)
Debugging function.
Definition: activate.c:93
static list saved_active_phases
Definition: activate.c:47
void save_active_phases(void)
activate.c
Definition: activate.c:49
bool activate_phases(void)
Use property ACTIVE_PHASES to active the phases required by the user.
Definition: activate.c:224
void activate_language(language l)
Choose the right combination of activate and setproperty for a given language.
Definition: activate.c:254
void fprint_activated(FILE *fd)
Definition: activate.c:110
void retrieve_active_phases(void)
Definition: activate.c:58
string active_phase_for_resource(string res)
return the phase which would be used to build a given resource.
Definition: activate.c:119
static void delete_derived_resources()
const char * activate_phase(const char *phase)
Definition: activate.c:124
bool rule_use_resource_produced(rule r)
Test if a rule uses a resource it produces.
Definition: activate.c:353
struct _newgen_struct_status_ * status
Definition: database.h:31
char * get_string_property(const char *)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define STRING(x)
Definition: genC.h:87
void free(void *)
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
#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 MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
list gen_copy_string_list(list ls)
of string
Definition: list.c:556
#define rule_phase(x)
Definition: makefile.h:244
#define virtual_resource_owner(x)
Definition: makefile.h:292
#define rule_required(x)
Definition: makefile.h:246
#define owner_callers_p(x)
Definition: makefile.h:158
#define rule_undefined
Definition: makefile.h:215
#define virtual_resource_name(x)
Definition: makefile.h:290
#define makefile_active_phases(x)
Definition: makefile.h:84
#define rule_produced(x)
Definition: makefile.h:248
#define owner_callees_p(x)
Definition: makefile.h:155
#define VIRTUAL_RESOURCE(x)
VIRTUAL_RESOURCE.
Definition: makefile.h:260
#define owner_select_p(x)
Definition: makefile.h:164
#define debug_on(env)
Definition: misc-local.h:157
#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 debug_off()
Definition: misc-local.h:160
#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
#define same_string_p(s1, s2)
#define SET_MAP(element, code, the_set)
Definition: newgen_set.h:54
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
struct cons * list
Definition: newgen_types.h:106
string db_get_current_workspace_name(void)
the function is used to check that there is some current workspace...
Definition: workspace.c:82
rule find_rule_by_phase(const char *)
this function returns the rule that defines builder pname
makefile parse_makefile(void)
rule find_rule_by_resource(const char *rname)
This function returns the active rule to produce resource rname.
Definition: pipsmake.c:694
void delete_named_resources(const char *rn)
Delete from up_to_date_resources make cache all the resources with a given resource name.
Definition: pipsmake.c:1482
void set_bool_property(const char *, bool)
#define language_fortran95_p(x)
Definition: ri.h:1597
#define language_c_p(x)
Definition: ri.h:1594
#define language_fortran_p(x)
Definition: ri.h:1591
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41