PIPS
readmakefile.y
Go to the documentation of this file.
1 /*
2 
3  $Id: readmakefile.y 23128 2016-07-01 11:58:21Z 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 
25 /* Some modifications are made to save the current makefile (s.a. files
26  * pipsmake/readmakefile.y pipsmake.h )
27  *
28  * They only occure between following tags:
29  *
30  * Bruno Baron
31  */
32 
33 %token PROGRAM
34 %token MODULE
35 %token MAIN
36 %token COMMON
37 %token TK_CALLEES
38 %token CALLERS
39 %token ALL
40 %token SELECT
41 %token COMPILATION_UNIT
42 %token REQUIRED
43 %token PRODUCED
44 %token MODIFIED
45 %token PRESERVED
46 %token PRE_TRANSFORMATION
47 %token POST_TRANSFORMATION
48 %token DOT
49 %token <name> NAME
50 
51 %type <name> phase
52 %type <name> resource
53 %type <owner> owner
54 %type <virtual> virtual
55 %type <list> virtuals
56 %type <rule> deps
57 %type <rule> rule
58 %type <tag> dir
59 
60 %{
61 #ifdef HAVE_CONFIG_H
62  #include "pips_config.h"
63 #endif
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include "linear.h"
68 
69 #include "genC.h"
70 #include "ri.h"
71 #include "database.h"
72 #include "makefile.h"
73 
74 #include "misc.h"
75 
76 #include "properties.h"
77 #include "top-level.h"
78 #include "pipsmake.h"
79 
80 #include "stdlib.h"
81 
82 static makefile pipsmakefile = makefile_undefined;
83 static hash_table activated = NULL;
84 %}
85 
86 %union {
87  string name;
88  owner owner;
89  virtual_resource virtual;
90  cons *list;
91  rule rule;
92  int tag;
93 }
94 
95 %%
96 rules: rules rule
97  { add_rule($2); }
98  |
99  {
100  pipsmakefile = make_makefile(NIL, NIL);
101  if (activated)
102  hash_table_free(activated), activated=NULL;
103  activated = hash_table_make(hash_string, 0);
104  }
105  ;
106 
107 rule: phase deps
108  { rule_phase($2) = $1; $$ = $2; }
109  ;
110 
111 deps: deps dir virtuals
112  {
113  if ($2 == REQUIRED) {
114  rule_required($1) =
115  gen_nconc(rule_required($1), $3);
116  }
117  else if ($2 == PRODUCED) {
118  rule_produced($1) =
119  gen_nconc(rule_produced($1), $3);
120  }
121  else if ($2 == PRESERVED) {
122  rule_preserved($1) =
123  gen_nconc(rule_preserved($1), $3);
124  }
125  else if ($2 == MODIFIED) {
126  rule_modified($1) =
127  gen_nconc(rule_modified($1), $3);
128  }
129  else if ($2 == PRE_TRANSFORMATION) {
130  rule_pre_transformation($1) =
131  gen_nconc(rule_pre_transformation($1), $3);
132  }
133  else if ($2 == POST_TRANSFORMATION) {
134  rule_post_transformation($1) =
135  gen_nconc(rule_post_transformation($1), $3);
136  }
137  else {
138  pips_internal_error("unknown dir: %d", $2);
139  }
140  $$ = $1;
141  }
142  | // empty rule
143  { $$ = make_rule(string_undefined, NIL, NIL, NIL, NIL, NIL,NIL); }
144  ;
145 
146 dir: REQUIRED
147  { $$ = REQUIRED; }
148  | PRODUCED
149  { $$ = PRODUCED; }
150  | MODIFIED
151  { $$ = MODIFIED; }
152  | PRESERVED
153  { $$ = PRESERVED; }
154  | PRE_TRANSFORMATION
155  { $$ = PRE_TRANSFORMATION; }
156  | POST_TRANSFORMATION
157  { $$ = POST_TRANSFORMATION; }
158  ;
159 
160 virtuals: virtuals virtual
161  { $$ = gen_nconc($1, CONS(VIRTUAL_RESOURCE, $2, NIL)); }
162  |
163  { $$ = NIL; }
164  ;
165 
166 virtual: owner DOT resource
167  { $$ = make_virtual_resource($3, $1); }
168  ;
169 
170 owner: PROGRAM
171  { $$ = make_owner(is_owner_program, UU); }
172  | MODULE
173  { $$ = make_owner(is_owner_module, UU); }
174  | MAIN
175  { $$ = make_owner(is_owner_main, UU); }
176  | COMMON
177  {
178  /*$$ = make_owner(is_owner_common, UU);*/
179  YYERROR;
180  }
181  | TK_CALLEES
182  { $$ = make_owner(is_owner_callees, UU); }
183  | CALLERS
184  { $$ = make_owner(is_owner_callers, UU); }
185  | ALL
186  { $$ = make_owner(is_owner_all, UU); }
187  | SELECT
188  { $$ = make_owner(is_owner_select, UU); }
189  | COMPILATION_UNIT
190  { $$ = make_owner(is_owner_compilation_unit, UU); }
191  ;
192 
193 phase: NAME
194  { $$ = strupper($1, $1); }
195  ;
196 
197 resource: NAME
198  { $$ = strupper($1, $1); }
199  ;
200 %%
201 
202 void yyerror_lex_part(const char *);
203 void yyerror(const char * s)
204 {
205  int c;
206  yyerror_lex_part(s);
207  fprintf(stderr, "[readmakefile] unparsed text:\n");
208  while ((c = getc(pipsmake_in)) != EOF) putc(c, stderr);
209  pips_internal_error("reading pips makefile failed");
210 }
211 
212 void
213 fprint_virtual_resources(FILE *fd, const char* dir, list lrv)
214 {
215  FOREACH(VIRTUAL_RESOURCE, vr, lrv)
216  {
217  owner o = virtual_resource_owner(vr);
218  string n = virtual_resource_name(vr);
219 
220  switch (owner_tag(o)) {
221  case is_owner_program:
222  fprintf(fd, " %s program.%s\n", dir, n);
223  break;
224  case is_owner_module:
225  fprintf(fd, " %s module.%s\n", dir, n);
226  break;
227  case is_owner_main:
228  fprintf(fd, " %s main.%s\n", dir, n);
229  break;
230  case is_owner_callees:
231  fprintf(fd, " %s callees.%s\n", dir, n);
232  break;
233  case is_owner_callers:
234  fprintf(fd, " %s callers.%s\n", dir, n);
235  break;
236  case is_owner_all:
237  fprintf(fd, " %s all.%s\n", dir, n);
238  break;
239  case is_owner_select:
240  fprintf(fd, " %s select.%s\n", dir, n);
241  break;
242  case is_owner_compilation_unit:
243  fprintf(fd, " %s compilation_unit.%s\n", dir, n);
244  break;
245  default:
246  pips_internal_error("bad owner tag (%d)\n", owner_tag(o));
247  }
248  }
249 }
250 
251 void fprint_makefile(FILE *fd, makefile m)
252 {
253  FOREACH(RULE, r, makefile_rules(m))
254  {
255  fprintf(fd, "%s\n", rule_phase(r));
256  fprint_virtual_resources(fd, "\t!", rule_pre_transformation(r));
257  fprint_virtual_resources(fd, "\t<", rule_required(r));
258  fprint_virtual_resources(fd, "\t>", rule_produced(r));
259  fprint_virtual_resources(fd, "\t=", rule_preserved(r));
260  fprint_virtual_resources(fd, "\t#", rule_modified(r));
261  }
262 }
263 
264 makefile
265 parse_makefile(void)
266 {
267  // do it only once
268  if (pipsmakefile == makefile_undefined)
269  {
270  debug_on("PIPSMAKE_DEBUG_LEVEL");
271 
272  pipsmake_in = fopen_config(PIPSMAKE_RC, NULL, "PIPS_PIPSMAKERC");
273 
274  init_lex();
275  yyparse();
276  safe_fclose(pipsmake_in, "PIPS_PIPSMAKERC");
277 
278  ifdebug(8) fprint_makefile(stderr, pipsmakefile);
279 
280  debug_off();
281  }
282 
283  return pipsmakefile;
284 }
285 
286 
287 /* this function returns the rule that defines builder pname */
288 rule find_rule_by_phase(const char* pname)
289 {
290  rule fr = rule_undefined;
291  makefile m = parse_makefile();
292 
293  pips_debug(9, "searching rule for phase %s\n", pname);
294 
295  /* walking thru rules */
296  FOREACH(RULE, r, makefile_rules(m)) {
297  if (same_string_p(rule_phase(r), pname)) {
298  fr = r;
299  break;
300  }
301  }
302 
303  return fr;
304 }
305 
306 void add_rule(rule r)
307 {
308  string pn = rule_phase(r);
309  bool active_phase = false;
310 
311  // Check resources produced by this rule
312  FOREACH(VIRTUAL_RESOURCE, vr, rule_produced(r)) {
313  string vrn = virtual_resource_name(vr);
314  string phase;
315 
316  // We activated this rule to produce this resource only if
317  // this resource is not already produced
318  if ((phase = hash_get(activated, vrn)) == HASH_UNDEFINED_VALUE) {
319  pips_debug(1, "Default function for %s is %s\n", vrn, pn);
320 
321  active_phase = true;
322  hash_put(activated, vrn, pn);
323 
324  makefile_active_phases(pipsmakefile) =
325  CONS(STRING, strdup(pn), makefile_active_phases(pipsmakefile));
326  }
327  else pips_debug(1, "Function %s not activated\n", pn);
328  }
329 
330  // Check resources required for this rule if it is an active one
331  if (active_phase) {
332  FOREACH(VIRTUAL_RESOURCE, vr, rule_required(r)) {
333  string vrn = virtual_resource_name(vr);
334  owner vro = virtual_resource_owner(vr);
335  string phase;
336 
337  // We must use a resource already defined
338  if ( owner_callers_p(vro) || owner_callees_p(vro) ) {}
339  else {
340  phase = hash_get(activated, vrn);
341  if (phase == HASH_UNDEFINED_VALUE)
342  {
343  if (get_bool_property("PIPSMAKE_WARNINGS"))
344  pips_user_warning(
345  "%s: phase %s requires an undefined resource %s\n",
346  PIPSMAKE_RC, pn, vrn);
347  }
348  // If we use a resource, another function should have produced it
349  else if (strcmp(phase, pn) == 0) {
350  pips_internal_error(
351  "%s: phase %s cannot be active for the %s resource\n",
352  PIPSMAKE_RC, phase, vrn);
353  }
354  else
355  pips_debug(1, "Required resource %s is checked OK for Function %s\n",
356  vrn, pn);
357  }
358  }
359  }
360 
361  // FI: no check of rule name unicity; e.g. double declaration of sesamify
362  rule or = find_rule_by_phase(rule_phase(r));
363  if(rule_undefined_p(or))
364  makefile_rules(pipsmakefile) = gen_nconc(makefile_rules(pipsmakefile),
365  CONS(RULE, r, NIL));
366  else
367  pips_internal_error("Double declaration of phase \"%s\"\n"
368  "Check pipsmake-rc.tex or pipsmake.rc\n",
369  rule_phase(r));
370 }
371 
372 makefile open_makefile(const char* name)
373 {
374  FILE * fd;
375  char * mkf_name;
376 
377  mkf_name = build_pgm_makefile(name);
378  fd = fopen(mkf_name, "r");
379 
380  if (!makefile_undefined_p(pipsmakefile))
381  {
382  free_makefile(pipsmakefile);
383  pipsmakefile = makefile_undefined;
384  pips_debug(1, "current makefile erased\n");
385  }
386 
387  if (fd)
388  {
389  pipsmakefile = read_makefile(fd);
390  safe_fclose(fd, mkf_name);
391  }
392  else
393  {
394  pips_user_warning("pipsmake file not found in database...\n");
395  pipsmakefile = parse_makefile();
396  }
397 
398  free(mkf_name);
399  return pipsmakefile;
400 }
401 
402 void
403 save_makefile(const char* name)
404 {
405  char * mkf_name = build_pgm_makefile(name);
406  FILE * fd = safe_fopen(mkf_name, "w");
407  write_makefile(fd, pipsmakefile);
408  safe_fclose(fd, mkf_name);
409  pips_debug(1, "makefile written on %s\n", mkf_name);
410  free(mkf_name);
411 }
412 
413 bool
414 close_makefile(const char* name)
415 {
416  save_makefile(name);
417  free_makefile(pipsmakefile), pipsmakefile = makefile_undefined;
418  return true;
419 }