PIPS
tp_yacc.y
Go to the documentation of this file.
1 /*
2 
3  $Id: tp_yacc.y 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 /*
25  * Each full syntax looks for ENDOFLINE so as to check that the right
26  * number of arguments is matched.
27  */
28 
29 %token TK_OPEN TK_CREATE TK_CLOSE TK_CHECKPOINT TK_DELETE
30 %token TK_MODULE
31 %token TK_MAKE TK_APPLY TK_CAPPLY TK_DISPLAY
32 %token TK_REMOVE TK_ACTIVATE
33 %token TK_SET_PROPERTY TK_GET_PROPERTY
34 %token TK_SET_ENVIRONMENT TK_GET_ENVIRONMENT TK_UNSET_ENVIRONMENT
35 %token TK_CDIR TK_INFO TK_PWD TK_HELP TK_SHOW TK_SOURCE
36 %token TK_SHELL TK_ECHO TK_UNKNOWN TK_TIMEOUT
37 %token TK_QUIT TK_EXIT
38 %token TK_LINE TK_CHECKACTIVE TK_VERSION TK_TOUCH
39 
40 %token TK_OWNER_NAME
41 %token TK_OWNER_ALL
42 %token TK_OWNER_ALLFUNC
43 %token TK_OWNER_ALLCU
44 %token TK_OWNER_PROGRAM
45 %token TK_OWNER_MAIN
46 %token TK_OWNER_MODULE
47 %token TK_OWNER_CALLERS
48 %token TK_OWNER_CALLEES
49 
50 %token TK_OPENPAREN
51 %token TK_COMMA
52 %token TK_CLOSEPAREN
53 %token TK_EQUAL
54 
55 %token TK_NAME
56 %token TK_A_STRING
57 %token TK_ENDOFLINE
58 %token TK_INT
59 
60 %type <name> TK_NAME TK_A_STRING TK_LINE TK_UNKNOWN
61 %type <ival> TK_INT
62 %type <status> command commands
63 %type <status> i_open i_create i_close i_delete i_module i_make i_pwd i_source
64 %type <status> i_apply i_activate i_display i_get i_setenv i_getenv i_cd i_rm
65 %type <status> i_info i_shell i_echo i_setprop i_quit i_exit i_help i_capply
66 %type <status> i_checkpoint i_show i_unknown i_checkactive i_touch i_unsetenv
67 %type <status> i_timeout i_version
68 %type <name> rulename filename propname phasename resourcename workspace_name
69 %type <array> filename_list
70 %type <rn> resource_id rule_id
71 %type <array> owner list_of_owner_name
72 
73 %{
74 #ifdef HAVE_CONFIG_H
75  #include "pips_config.h"
76 #endif
77 #include <stdlib.h>
78 #include <stdio.h>
79 #include <string.h>
80 #include <sys/param.h>
81 #include <unistd.h>
82 
83 #include "linear.h"
84 #include "genC.h"
85 
86 #include "ri.h"
87 #include "database.h"
88 
89 #include "misc.h"
90 
91 #include "ri-util.h" /* ri needed for statement_mapping in pipsdbm... */
92 #include "pipsdbm.h"
93 #include "resources.h"
94 #include "phases.h"
95 #include "properties.h"
96 #include "pipsmake.h"
97 
98 #include "top-level.h"
99 #include "tpips.h"
100 
101 /********************************************************** static variables */
102 
103 extern const char *soft_revisions, *soft_date, *cc_version;
104 
105 extern bool tpips_execution_mode;
106 extern bool consistency_enforced_p;
107 static bool processing_started_p=false;
108 
109 #define YYERROR_VERBOSE 1 /* MUCH better error messages with bison */
110 
111 extern void tpips_set_line_to_parse(string);
112 extern void tpips_lex_print_pos(FILE *);
113 extern int yylex(void);
114 extern void yyerror(const char *);
115 
116 static void free_owner_content(res_or_rule * pr)
117 {
118  gen_array_full_free(pr->the_owners), pr->the_owners = NULL;
119  free(pr->the_name), pr->the_name = NULL;
120 }
121 
122 static void set_env_log_and_free(string var, string val)
123 {
124  string ival = getenv(var);
125  if (!ival || !same_string_p(val, ival)) {
126  putenv(strdup(concatenate(var, "=", val, NULL)));
127  }
128  user_log("setenv %s \"%s\"\n", var, val);
129  free(var); free(val);
130 }
131 
132 /* forward.
133  */
134 static bool perform(bool (*)(const char*, const char*), res_or_rule *);
135 
136 static void try_to_parse_everything_just_in_case(void)
137 {
138  gen_array_t modules = db_get_module_list();
139  res_or_rule r;
140  r.the_owners = modules;
141  r.the_name = strdup(DBR_CALLEES);
142  perform(safe_make, &r);
143  // r contents freed at the end of perform
144 }
145 
146 /* try hard to open a module.
147  */
148 static bool tp_set_current_module(const char* name)
149 {
150  if (lazy_open_module(name))
151  return true;
152 
153  // This is courageous, but makes debugging harder...
154  try_to_parse_everything_just_in_case();
155  if (lazy_open_module(name))
156  return true;
157 
158  if (!safe_make(DBR_CODE, name))
159  return false;
160 
161  if (lazy_open_module(name))
162  return true;
163 
164  pips_user_error("Cannot open, module not found: %s", name);
165  return false;
166 }
167 
168 /* display a resource using $PAGER if defined and stdout on a tty.
169  */
170 static bool display_a_resource(const char* rname, const char* mname)
171 {
172  string fname;
173  bool ret;
174 
175  if (!tp_set_current_module(mname))
176  {
177  pips_user_error("could not find module %s to display\n", mname);
178  }
179 
180  fname = build_view_file(rname);
181 
182  if (!fname)
183  {
184  pips_user_error("Cannot build view file %s\n", rname);
185  free(fname);
186  return false;
187  }
188 
189  if (jpips_is_running)
190  {
191  /* Should tell about what it is?
192  * What about special formats, such as graphs and all?
193  */
194  jpips_tag2("show", fname);
195  ret = true;
196  }
197  else
198  {
199  ret = safe_display(fname);
200  }
201 
202  free(fname);
203  return ret;
204 }
205 
206 static bool remove_a_resource(const char* rname, const char* mname)
207 {
208  if (db_resource_p(rname, mname))
209  db_delete_resource(rname, mname);
210  else
211  pips_user_warning("no resource %s[%s] to delete.\n", rname, mname);
212  return true;
213 }
214 
215 /* tell pipsdbm that the resource is up to date.
216  * may be useful if some transformations are applied
217  * which do not change the results of some analyses.
218  * under the responsability of the user, obviously...
219  */
220 static bool touch_a_resource(const char* rname, const char* mname)
221 {
222  if (db_resource_p(rname, mname))
223  db_touch_resource(rname, mname);
224  else
225  pips_user_warning("no resource %s[%s] to delete.\n", rname, mname);
226  return true;
227 }
228 
229 static bool just_show(const char* rname, const char* mname)
230 {
231  string file;
232 
233  if (!db_resource_p(rname, mname)) {
234  pips_user_warning("no resource %s[%s].\n", rname, mname);
235  return false;
236  }
237 
238  if (!displayable_file_p(rname)) {
239  pips_user_warning("resource %s cannot be displayed.\n", rname);
240  return false;
241  }
242 
243  /* now returns the name of the file.
244  */
245  file = db_get_memory_resource(rname, mname, true);
246  fprintf(stdout, "resource %s[%s] is file %s\n", rname, mname, file);
247 
248  return true;
249 }
250 
251 /* perform "what" to all resources in "res". res is freed.
252  * Several rules call it: display, apply...
253  */
254 static bool perform(bool (*what)(const char*, const char*), res_or_rule * res)
255 {
256  bool result = true;
257 
258  if (tpips_execution_mode)
259  {
260  string save_current_module_name;
261 
262  if (!db_get_current_workspace_name())
263  pips_user_error("Open or create a workspace first!");
264 
265  // This may be always trapped earlier in the parser by rule "owner".
266  if (gen_array_nitems(res->the_owners)==0) {
267  pips_user_error("Empty action for %s: no argument!", res->the_name);
268  free_owner_content(res);
269  }
270 
271  // push the current module.
272  string current = db_get_current_module_name();
273  save_current_module_name = current? strdup(current): NULL;
274  current = NULL;
275 
276  GEN_ARRAY_FOREACH(string, mod_name, res->the_owners)
277  {
278  if (mod_name != NULL)
279  {
280  if (!what(res->the_name, mod_name)) {
281  result = false;
282  break;
283  }
284  }
285  else
286  pips_user_warning("Select a module first!\n");
287  }
288 
289  // restore the initial current module, if there was one
290  if (save_current_module_name!=NULL)
291  {
292  if (db_get_current_module_name())
293  db_reset_current_module_name();
294  db_set_current_module_name(save_current_module_name);
295  free(save_current_module_name);
296  }
297  }
298 
299  free_owner_content(res);
300  return result;
301 }
302 
303 static void tp_system(const char* s)
304 {
305  int status;
306  user_log("shell%s%s\n", (s[0]==' '|| s[0]=='\t')? "": " ", s);
307  status = system(s);
308  fflush(stdout);
309 
310  if (status)
311  {
312  pips_user_warning("shell returned status (%d.%d)\n",
313  status/256, status%256);
314 
315  /* generate user error if not interactive,
316  * so as to abort quickly in scripts...
317  */
318  if (!tpips_is_interactive)
319  pips_user_error("shell error (%d) in tpips script\n", status);
320  }
321 }
322 
323 static bool tp_close_the_workspace(const char* s)
324 {
325  bool result = true;
326 
327  pips_debug(7, "reduce rule i_close\n");
328 
329  if (tpips_execution_mode)
330  {
331  string current = db_get_current_workspace_name();
332 
333  if (current!=NULL && s!=NULL)
334  {
335  if (same_string_p(s, current))
336  {
337  close_workspace(false);
338  result = true;
339  }
340  else
341  {
342  pips_user_error("must close the current workspace!\n");
343  result = false;
344  }
345  }
346  else {
347  pips_user_error("No workspace to close. Open or create one!\n");
348  result = false;
349  }
350  result = true;
351  }
352 
353  return result;
354 }
355 
356 static void tp_some_info(const char* about)
357 {
358  if (same_string_p(about, "workspace"))
359  {
360  string ws = db_get_current_workspace_name();
361  fprintf(stdout, "%s\n", ws? ws: "");
362  if (jpips_is_running) jpips_tag2("workspace", ws? ws: "<none>");
363  }
364  else if (same_string_p(about, "module"))
365  {
366  string m = db_get_current_module_name();
367  fprintf(stdout, "%s\n", m? m: "");
368  if (jpips_is_running) jpips_tag2("module", m? m: "<none>");
369  }
370  else if (same_string_p(about, "modules") &&
371  db_get_current_workspace_name())
372  {
373  gen_array_t modules = db_get_module_list();
374  int n = gen_array_nitems(modules), i;
375 
376  if (jpips_is_running)
377  {
378  jpips_begin_tag("modules");
379  jpips_add_tag("");
380  }
381 
382  for(i=0; i<n; i++)
383  {
384  string m = gen_array_item(modules, i);
385  if (jpips_is_running) jpips_add_tag(m);
386  else fprintf(stdout, "%s ", m);
387 
388  }
389  if (jpips_is_running) jpips_end_tag();
390 
391  gen_array_full_free(modules);
392  }
393  else if (same_string_p(about, "directory"))
394  {
395  char pathname[MAXPATHLEN];
396  fprintf(stdout, "%s\n", (char*) getcwd(pathname, MAXPATHLEN));
397  if (jpips_is_running)
398  jpips_tag2("directory", (char*) getcwd(pathname, MAXPATHLEN));
399  }
400 
401  fprintf(stdout, "\n");
402 }
403 
404 /* Returns a newgen array with the main inside. If no main is found,
405  * try to build all callees to parse all sources and maybe find it.
406  *
407  * FI: since the preprocessor has already analyzed all source code and
408  * detect main functions, what do you expect by parsing its result?
409  */
410 static gen_array_t get_main(void)
411 {
412  gen_array_t result = gen_array_make(0), modules;
413  int number_of_main = 0;
414  int n = 0;
415  string main_name = get_first_main_module();
416 
417  if (!string_undefined_p(main_name))
418  {
419  gen_array_append(result, main_name);
420  return result;
421  }
422 
423  /* else try something else just in case...
424  * well, it looks rather useless, maybe.
425  */
426  while (number_of_main==0 && n<2)
427  {
428  n++;
429  modules = db_get_module_list();
430 
431  if (n==2)
432  {
433  pips_user_warning("no main directly found, parsing...\n");
434  try_to_parse_everything_just_in_case();
435  }
436 
437  GEN_ARRAY_FOREACH(string, on, modules)
438  {
439  entity mod = local_name_to_top_level_entity(on);
440 
441  if (!entity_undefined_p(mod) && entity_main_module_p(mod))
442  {
443  if (number_of_main)
444  pips_user_error("More than one main\n");
445  number_of_main++;
446  gen_array_dupappend(result, on);
447  }
448  }
449  gen_array_full_free(modules);
450  }
451 
452  return result;
453 }
454 
455 static void process_file_list(const gen_array_t a)
456 {
457  int n = gen_array_nitems(a);
458  volatile int i = 0;
459  bool saved_tpips_is_interactive = tpips_is_interactive;
460  tpips_is_interactive = false;
461  CATCH(user_exception_error)
462  {
463  // cleanup
464  gen_array_full_free(a);
465  tpips_set_line_to_parse(""); // humm...
466  tpips_is_interactive = saved_tpips_is_interactive;
467  RETHROW();
468  }
469  TRY
470  {
471  for(; i<n; i++)
472  {
473  string name = gen_array_item(a, i);
474  FILE * sourced = fopen(name, "r");
475  if (!sourced) {
476  perror("while sourcing");
477  /* just in case, maybe tpips_init is not yet performed. */
478  if (tpips_init_done)
479  /* this performs a throw... */
480  pips_user_error("cannot source file '%s'\n", name);
481  else
482  {
483  fprintf(stderr, "cannot source file '%s'\n", name);
484  break;
485  }
486  }
487  else
488  {
489  tpips_process_a_file(sourced, name, false);
490  fclose(sourced);
491  }
492  }
493  tpips_set_line_to_parse(""); /* humm... */
494  tpips_is_interactive = saved_tpips_is_interactive;
495  UNCATCH(user_exception_error);
496  }
497 }
498 
499 %}
500 
501 %union {
502  int status;
503  int ival;
504  string name;
505  res_or_rule rn;
506  gen_array_t array;
507 }
508 
509 %%
510 
511 commands: commands command { $$ = $1 && $2; }
512  | command
513  ;
514 
515 command: TK_ENDOFLINE { /* may be empty! */ }
516  | i_open { processing_started_p = true; }
517  | i_create { processing_started_p = false; }
518  | i_close { processing_started_p = false; }
519  | i_delete { processing_started_p = false; }
520  | i_checkpoint
521  | i_module
522  | i_make { processing_started_p = true; }
523  | i_apply { processing_started_p = true; }
524  | i_capply { processing_started_p = true; }
525  | i_display { processing_started_p = true; }
526  | i_show
527  | i_rm
528  | i_activate
529  | i_checkactive
530  | i_get
531  | i_getenv
532  | i_setenv
533  | i_unsetenv
534  | i_timeout
535  | i_cd
536  | i_pwd
537  | i_source
538  | i_info
539  | i_echo
540  | i_shell
541  | i_setprop
542  | i_quit
543  | i_version
544  | i_exit
545  | i_help
546  | i_touch
547  | i_unknown
548  | error {$$ = false;}
549  ;
550 
551 i_quit: TK_QUIT TK_ENDOFLINE
552  {
553  tpips_close();
554  pips_stop(info_log, 0, "tpips quit");
555  }
556  ;
557 
558 
559 i_exit: TK_EXIT TK_ENDOFLINE
560  {
561  exit(0); /* rather rough! */
562  }
563  ;
564 
565 i_version: TK_VERSION TK_ENDOFLINE
566  {
567  fprintf(stdout,
568  // "tpips: (%s)\n"
569  "ARCH=" STRINGIFY(SOFT_ARCH) "\n"
570  "REVS=\n"
571  "%s"
572  "DATE=%s\n"
573  "CC_VERSION=%s\n",
574  soft_revisions, soft_date, cc_version);
575  fflush(stdout);
576  }
577  ;
578 
579 i_help: TK_HELP TK_NAME TK_ENDOFLINE
580  {
581  tpips_help($2); free($2);
582  }
583  | TK_HELP TK_ENDOFLINE
584  {
585  tpips_help("");
586  }
587  ;
588 
589 i_setprop: TK_SET_PROPERTY TK_LINE TK_ENDOFLINE
590  {
591  consistency_enforced_p = get_bool_property("CONSISTENCY_ENFORCED_P");
592  if(!consistency_enforced_p || !processing_started_p) {
593  user_log("setproperty %s\n", $2);
594  reset_property_error(); // We start again at tpips
595  // level and should be able to
596  // avoid the fatal loop...
597  parse_properties_string($2, processing_started_p);
598  if(processing_started_p) {
599  pips_user_warning("Properties should not be updated during "
600  "tpips processing."
601  " Move the setproperty statement at the "
602  "beginning of your tpips script.\n");
603  }
604  }
605  else {
606  pips_user_error("Properties should not be updated during tpips "
607  "processing."
608  " Move the setproperty statement at the beginning "
609  "of your tpips script.\n");
610  }
611  fflush(stdout);
612  free($2);
613  }
614  ;
615 
616 i_shell: TK_SHELL TK_ENDOFLINE
617  {
618  tp_system("${SHELL:-sh}");
619  }
620  | TK_SHELL TK_LINE TK_ENDOFLINE
621  {
622  tp_system($2); free($2);
623  }
624  ;
625 
626 i_unknown: TK_UNKNOWN TK_ENDOFLINE
627  {
628  if (tpips_behaves_like_a_shell())
629  {
630  pips_user_warning("implicit shell command assumed!\n");
631  tp_system($1);
632  }
633  else
634  {
635  tpips_lex_print_pos(stderr);
636  if(get_bool_property("ABORT_ON_USER_ERROR") ||
637  get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR")) {
638  // FI: the next call is used to check error management
639  // pips_internal_error("Just a temporary test\n.");
640  extern string tpips_unknown_string;
641  pips_user_error(
642  "\n\n"
643  "\tUnknown command \"%s\" at line %d in file \"%s\".\n"
644  "\tMaybe you intended to execute a direct shell command.\n"
645  "\tThis convenient feature is desactivated by default.\n"
646  "\tTo enable it, you can run tpips with the -s option,\n"
647  "\tor do \"setproperty TPIPS_IS_A_SHELL=TRUE\",\n"
648  "\tor do \"setenv TPIPS_IS_A_SHELL=TRUE\".\n"
649  "\tOtherwise use ! or \"shell\" as a command prefix.\n\n", tpips_unknown_string, tpips_current_line_number(), tpips_current_file_name());
650  }
651  else {
652  extern string tpips_unknown_string; // provided by the lexer
653  pips_user_warning(
654  "\n\n"
655  "\tMaybe you intended to execute a direct shell command.\n"
656  "\tThis convenient feature is desactivated by default.\n"
657  "\tTo enable it, you can run tpips with the -s option,\n"
658  "\tor do \"setproperty TPIPS_IS_A_SHELL=TRUE\",\n"
659  "\tor do \"setenv TPIPS_IS_A_SHELL=TRUE\".\n"
660  "\tOtherwise use ! or \"shell\" as a command prefix.\n\n");
661  }
662  }
663  free($1);
664  }
665  ;
666 
667 i_echo: TK_ECHO TK_LINE TK_ENDOFLINE
668  {
669  string s = $2;
670  user_log("echo %s\n", $2);
671  skip_blanks(s);
672  fprintf(stdout,"%s\n",s);
673  fflush(stdout);
674  free($2);
675  }
676  | TK_ECHO TK_ENDOFLINE /* there may be no text at all. */
677  {
678  user_log("echo\n");
679  fprintf(stdout,"\n");
680  fflush(stdout);
681  }
682  ;
683 
684 i_info: TK_INFO TK_NAME TK_ENDOFLINE
685  {
686  tp_some_info($2);
687  free($2);
688  }
689  ;
690 
691 i_cd: TK_CDIR TK_NAME TK_ENDOFLINE
692  {
693  user_log("cd %s\n", $2);
694  if (chdir($2)) fprintf(stderr, "error while changing directory\n");
695  free($2);
696  }
697  ;
698 
699 i_pwd: TK_PWD TK_ENDOFLINE
700  {
701  char pathname[MAXPATHLEN];
702  fprintf(stdout, "current working directory: %s\n",
703  (char*) getcwd(pathname, MAXPATHLEN));
704  fflush(stdout);
705  }
706  ;
707 
708 i_getenv: TK_GET_ENVIRONMENT TK_NAME TK_ENDOFLINE
709  {
710  string val = getenv($2);
711  user_log("getenv %s\n", $2);
712  if (val) fprintf(stdout, "%s=%s\n", $2, val);
713  else fprintf(stdout, "%s is not defined\n", $2);
714  free($2);
715  }
716  ;
717 
718 // hmmm... not very convincing
719 i_setenv: TK_SET_ENVIRONMENT TK_NAME TK_NAME TK_ENDOFLINE
720  { set_env_log_and_free($2, $3); }
721  | TK_SET_ENVIRONMENT TK_NAME TK_EQUAL TK_NAME TK_ENDOFLINE
722  { set_env_log_and_free($2, $4); }
723  | TK_SET_ENVIRONMENT TK_NAME TK_A_STRING TK_ENDOFLINE
724  { set_env_log_and_free($2, $3); }
725  | TK_SET_ENVIRONMENT TK_NAME TK_EQUAL TK_A_STRING TK_ENDOFLINE
726  { set_env_log_and_free($2, $4); }
727  | TK_SET_ENVIRONMENT TK_NAME filename_list TK_ENDOFLINE
728  { set_env_log_and_free($2, strdup(string_array_join($3, " "))); }
729  | TK_SET_ENVIRONMENT TK_NAME TK_EQUAL filename_list TK_ENDOFLINE
730  { set_env_log_and_free($2, strdup(string_array_join($4, " "))); }
731  | TK_SET_ENVIRONMENT TK_NAME TK_INT TK_ENDOFLINE
732  { char * v; asprintf(&v, "%d", $3); set_env_log_and_free($2, v); }
733  | TK_SET_ENVIRONMENT TK_NAME TK_EQUAL TK_INT TK_ENDOFLINE
734  { char * v; asprintf(&v, "%d", $4); set_env_log_and_free($2, v); }
735  ;
736 
737 i_unsetenv: TK_UNSET_ENVIRONMENT TK_NAME TK_ENDOFLINE
738  { user_log("unsetenv %s\n", $2); unsetenv($2); }
739  ;
740 
741 i_timeout: TK_TIMEOUT TK_INT TK_ENDOFLINE
742  { user_log("timeout %d\n", $2); set_pips_timeout($2); }
743  ;
744 
745 i_checkpoint: TK_CHECKPOINT TK_ENDOFLINE
746  {
747  if (tpips_execution_mode)
748  {
749  if (db_get_current_workspace_name())
750  checkpoint_workspace();
751  else
752  pips_user_error("Cannot checkpoint, no workspace!\n");
753  }
754  }
755  ;
756 
757 i_open: TK_OPEN workspace_name TK_ENDOFLINE
758  {
759  string main_module_name;
760 
761  pips_debug(7,"reduce rule i_open\n");
762 
763  if (tpips_execution_mode) {
764  if (db_get_current_workspace_name() != NULL) {
765  pips_user_warning("Closing workspace %s "
766  "before opening %s!\n",
767  db_get_current_workspace_name(), $2);
768  close_workspace(false);
769  }
770  if (!workspace_exists_p($2))
771  pips_user_error("No workspace %s to open!\n", $2);
772 
773  if (( $$ = open_workspace ($2)))
774  {
775  main_module_name = get_first_main_module();
776 
777  if (!string_undefined_p(main_module_name)) {
778  /* Ok, we got it ! Now we select it: */
779  user_log("Main module PROGRAM \"%s\" selected.\n",
780  main_module_name);
781  lazy_open_module(main_module_name);
782  free(main_module_name);
783  }
784  }
785  }
786  free($2);
787  }
788  ;
789 
790 workspace_name: TK_NAME
791  {
792  if(workspace_name_p($1))
793  $$ = $1;
794  else
795  pips_user_error("workspace name %s contains invalid char(s)\n", $1);
796  }
797 
798 i_create: TK_CREATE workspace_name /* workspace name */
799  filename_list /* source files */ TK_ENDOFLINE
800  {
801  string main_module_name;
802  pips_debug(7,"reduce rule i_create\n");
803 
804  if (tpips_execution_mode)
805  {
806  if (workspace_exists_p($2))
807  pips_user_error("Workspace %s already exists. Delete it!", $2);
808  else if (db_get_current_workspace_name())
809  {
810  pips_user_error("Close current workspace %s before "
811  "creating another!",
812  db_get_current_workspace_name());
813  }
814  else
815  {
816  if (db_create_workspace($2))
817  {
818  volatile bool ws_ok;
819  volatile bool user_exception_raised = false;
820 
821  CATCH(user_exception_error) {
822  ws_ok = false;
823  user_exception_raised = true;
824  }
825  TRY {
826  ws_ok = create_workspace($3);
827  UNCATCH(user_exception_error);
828  }
829 
830  if (!ws_ok)
831  {
832  if (get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR"))
833  {
834  // this is dangerous, it may or may not work...
835  // hmmm... might recurse on user errors?
836  db_close_workspace(false);
837  pips_user_error("Could not create workspace \"%s\"", $2);
838  }
839  else
840  {
841  db_close_workspace(false);
842  // If you need to preserve the workspace
843  // for debugging purposes, use property ABORT_ON_USER_ERROR
844  if (!get_bool_property("ABORT_ON_USER_ERROR"))
845  {
846  user_log("Deleting workspace...\n");
847  delete_workspace($2);
848  }
849  pips_user_error("Could not create workspace \"%s\"\n", $2);
850  }
851  }
852 
853  if (user_exception_raised)
854  THROW(user_exception_error);
855 
856  main_module_name = get_first_main_module();
857 
858  if (!string_undefined_p(main_module_name))
859  {
860  // Ok, we got it ! Now we select it:
861  user_log("Main module PROGRAM \"%s\" selected.", main_module_name);
862  lazy_open_module(main_module_name);
863  free(main_module_name);
864  }
865  $$ = true;
866  }
867  else {
868  pips_user_error("Cannot create directory for workspace, "
869  "check rights!\n");
870  }
871  }
872  }
873  free($2);
874  gen_array_full_free($3);
875  }
876  ;
877 
878 i_close: TK_CLOSE /* assume current workspace */ TK_ENDOFLINE
879  {
880  $$ = tp_close_the_workspace(db_get_current_workspace_name());
881  }
882  | TK_CLOSE TK_NAME /* workspace name */ TK_ENDOFLINE
883  {
884  $$ = tp_close_the_workspace($2);
885  free($2);
886  }
887  ;
888 
889 i_delete: TK_DELETE workspace_name /* workspace name */ TK_ENDOFLINE
890  {
891  pips_debug(7,"reduce rule i_delete\n");
892 
893  if (tpips_execution_mode) {
894  string wname = db_get_current_workspace_name();
895  if ((wname != NULL) && same_string_p(wname, $2)) {
896  pips_user_error("Close before delete: "
897  "Workspace %s is open\n", wname);
898  $$ = false;
899  } else {
900  if(workspace_exists_p($2))
901  {
902  if(delete_workspace ($2)) {
903  /* In case of problem, user_error() has been
904  called, so it is OK now !!*/
905  user_log ("Workspace %s deleted.\n", $2);
906  $$ = true;
907  }
908  else {
909  pips_user_warning(
910  "Could not delete workspace \"%s\"\n", $2);
911  }
912  }
913  else {
914  pips_user_warning("%s: No such workspace\n", $2);
915  }
916  }
917  }
918  free($2);
919  }
920  ;
921 
922 i_module: TK_MODULE TK_NAME /* module name */ TK_ENDOFLINE
923  {
924  pips_debug(7,"reduce rule i_module\n");
925 
926  if (tpips_execution_mode) {
927  if (db_get_current_workspace_name()) {
928  $$ = tp_set_current_module($2 /*strupper($2,$2)*/);
929  free($2);
930  } else {
931  free($2);
932  pips_user_error("No workspace open. Open or create one!\n");
933  $$ = false;
934  }
935  }
936  else free($2);
937  }
938  ;
939 
940 i_make: TK_MAKE resource_id TK_ENDOFLINE
941  {
942  pips_debug(7, "reduce rule i_make\n");
943  $$ = perform(safe_make, &$2);
944  }
945  ;
946 
947 i_apply: TK_APPLY rule_id TK_ENDOFLINE
948  {
949  pips_debug(7,"reduce rule i_apply\n");
950  $$ = perform(safe_apply, &$2);
951  }
952  ;
953 
954 i_capply: TK_CAPPLY rule_id TK_ENDOFLINE
955  {
956  pips_debug(7, "reduce rule i_capply\n");
957  $$ = safe_concurrent_apply($2.the_name, $2.the_owners);
958  }
959  ;
960 
961 i_display: TK_DISPLAY resource_id TK_ENDOFLINE
962  {
963  pips_debug(7,"reduce rule i_display\n");
964  $$ = perform(display_a_resource, &$2);
965  }
966  ;
967 
968 i_touch: TK_TOUCH resource_id TK_ENDOFLINE
969  {
970  pips_debug(7, "reduce rule i_touch\n");
971  $$ = perform(touch_a_resource, &$2);
972  }
973  ;
974 
975 i_show: TK_SHOW resource_id TK_ENDOFLINE
976  {
977  pips_debug(7, "reduce rule i_show\n");
978  $$ = perform(just_show, &$2);
979  }
980  ;
981 
982 i_rm: TK_REMOVE resource_id TK_ENDOFLINE
983  {
984  pips_debug(7,"reduce rule i_rm\n");
985  $$ = perform(remove_a_resource, &$2);
986  }
987  ;
988 
989 i_activate: TK_ACTIVATE rulename TK_ENDOFLINE
990  {
991  pips_debug(7,"reduce rule i_activate\n");
992  if (tpips_execution_mode)
993  {
994  if(!db_get_current_workspace_name())
995  pips_user_error("Open or create a workspace first!\n");
996 
997  user_log("Selecting rule: %s\n", $2);
998  activate($2);
999  $$ = true;
1000  }
1001  free($2);
1002  }
1003  ;
1004 
1005 i_checkactive: TK_CHECKACTIVE resourcename TK_ENDOFLINE
1006  {
1007  string ph = active_phase_for_resource($2);
1008  fprintf(stdout, "resource %s built by phase %s\n", $2, ph);
1009  if (jpips_is_running)
1010  {
1011  jpips_begin_tag("result");
1012  jpips_add_tag(ph);
1013  jpips_end_tag();
1014  }
1015  free($2);
1016  }
1017  ;
1018 
1019 i_get: TK_GET_PROPERTY propname TK_ENDOFLINE
1020  {
1021  pips_debug(7,"reduce rule i_get (%s)\n", $2);
1022 
1023  if (tpips_execution_mode) {
1024  fprint_property(stdout, $2);
1025  if (jpips_is_running)
1026  {
1027  jpips_begin_tag("result");
1028  jpips_add_tag("");
1029  fprint_property_direct(jpips_out_file(), $2);
1030  jpips_end_tag();
1031  }
1032  $$ = true;
1033  }
1034  free($2);
1035  }
1036  ;
1037 
1038 i_source
1039  : TK_SOURCE filename_list TK_ENDOFLINE
1040  {
1041  process_file_list($2);
1042  gen_array_full_free($2);
1043  }
1044 ;
1045 
1046 rulename: phasename
1047 ;
1048 
1049 filename_list: filename_list filename
1050  {
1051  gen_array_append($1, $2);
1052  $$ = $1;
1053  }
1054  | filename
1055  {
1056  $$ = gen_array_make(0);
1057  gen_array_append($$, $1);
1058  }
1059 ;
1060 
1061 filename: TK_NAME
1062 ;
1063 
1064 resource_id: resourcename owner
1065  {
1066  pips_debug(7,"reduce rule resource_id (%s)\n",$<name>2);
1067  $$.the_name = $1;
1068  $$.the_owners = $2;
1069  }
1070  ;
1071 
1072 rule_id: phasename owner
1073  {
1074  pips_debug(7,"reduce rule rule_id (%s)\n",$1);
1075  $$.the_name = $1;
1076  $$.the_owners = $2;
1077  }
1078  ;
1079 
1080 owner: TK_OPENPAREN TK_OWNER_ALL TK_CLOSEPAREN
1081  {
1082  pips_debug(7,"reduce rule owner (ALL)\n");
1083  if (tpips_execution_mode)
1084  {
1085  if (!db_get_current_workspace_name())
1086  pips_user_error("No current workspace! create or open one!\n");
1087  else
1088  $$ = db_get_module_list();
1089  }
1090  }
1091  | TK_OPENPAREN TK_OWNER_ALLFUNC TK_CLOSEPAREN
1092  {
1093  pips_debug(7,"reduce rule owner (ALLFUNC)\n");
1094  if (tpips_execution_mode)
1095  {
1096  if (!db_get_current_workspace_name())
1097  pips_user_error("No current workspace! create or open one!\n");
1098  else
1099  $$ = db_get_function_list();
1100  }
1101  }
1102  | TK_OPENPAREN TK_OWNER_ALLCU TK_CLOSEPAREN
1103  {
1104  pips_debug(7,"reduce rule owner (ALLCU)\n");
1105  if (tpips_execution_mode)
1106  {
1107  if (!db_get_current_workspace_name())
1108  pips_user_error("No current workspace! create or open one!\n");
1109  else
1110  $$ = db_get_compilation_unit_list();
1111  }
1112  }
1113  | TK_OPENPAREN TK_OWNER_PROGRAM TK_CLOSEPAREN
1114  {
1115  pips_debug(7,"reduce rule owner (PROGRAM)\n");
1116  if (tpips_execution_mode)
1117  {
1118  $$ = gen_array_make(0);
1119  gen_array_dupappend($$, "");
1120  }
1121  }
1122  | TK_OPENPAREN TK_OWNER_MAIN TK_CLOSEPAREN
1123  {
1124  pips_debug(7,"reduce rule owner (MAIN)\n");
1125 
1126  if (tpips_execution_mode) {
1127  if (!db_get_current_workspace_name())
1128  pips_user_error("No current workspace! create or open one!\n");
1129  else {
1130  $$ = get_main();
1131  }
1132  }
1133  }
1134  | TK_OPENPAREN TK_OWNER_MODULE TK_CLOSEPAREN
1135  {
1136  pips_debug(7,"reduce rule owner (MODULE)\n");
1137  if (tpips_execution_mode) {
1138  string n = db_get_current_module_name();
1139  $$ = gen_array_make(0);
1140  if (n) gen_array_dupappend($$, n);
1141  }
1142  }
1143  | TK_OPENPAREN TK_OWNER_CALLEES TK_CLOSEPAREN
1144  {
1145  pips_debug(7,"reduce rule owner (CALLEES)\n");
1146 
1147  if (tpips_execution_mode)
1148  {
1149  callees called_modules;
1150 
1151  if (!safe_make(DBR_CALLEES, db_get_current_module_name()))
1152  pips_internal_error("Cannot make callees for %s\n",
1153  db_get_current_module_name());
1154 
1155  called_modules = (callees)
1156  db_get_memory_resource(DBR_CALLEES,
1157  db_get_current_module_name(),true);
1158 
1159  $$ = gen_array_from_list(callees_callees(called_modules));
1160  }
1161  }
1162  | TK_OPENPAREN TK_OWNER_CALLERS TK_CLOSEPAREN
1163  {
1164  pips_debug(7,"reduce rule owner (CALLERS)\n");
1165  if (tpips_execution_mode)
1166  {
1167  $$ = get_callers(db_get_current_module_name());
1168  }
1169  }
1170  | TK_OPENPAREN list_of_owner_name TK_CLOSEPAREN
1171  { $$ = $2; }
1172  | // No explicit argument, take current module if any
1173  {
1174  pips_debug(7,"reduce rule owner (none)\n");
1175  if (tpips_execution_mode)
1176  {
1177  string n = db_get_current_module_name();
1178  $$ = gen_array_make(0);
1179  if (n)
1180  gen_array_dupappend($$, n);
1181  else {
1182  string wsn = db_get_current_workspace_name();
1183  // pips_internal_error("No current module name\n");
1184  if (wsn==NULL)
1185  pips_user_error(
1186  "No current workspace. Open or create one first!");
1187  else
1188  pips_user_error(
1189  "No current module has been defined, explicitly or implictly.\n"
1190  "Please specify a module name as argument or check that"
1191  " the current workspace \"%s\" contains one main module"
1192  " or no more than one module.\n",
1193  wsn);
1194  }
1195  }
1196  }
1197  ;
1198 
1199 list_of_owner_name: TK_NAME
1200  {
1201  $$ = gen_array_make(0); gen_array_append($$, $1);
1202  }
1203  | list_of_owner_name TK_NAME
1204  { gen_array_append($1, $2 /* strupper($2,$2) */); $$ = $1; }
1205  | list_of_owner_name TK_COMMA TK_NAME
1206  { gen_array_append($1, $3 /* strupper($3,$3) */); $$ = $1; }
1207  ;
1208 
1209 propname: TK_NAME
1210  {
1211  if (!property_name_p($1))
1212  yyerror("Expecting a property name.\n");
1213  $$ = $1;
1214  }
1215  ;
1216 
1217 phasename: TK_NAME
1218  {
1219  if (!phase_name_p($1))
1220  yyerror("Expecting a phase name.\n");
1221  $$ = $1;
1222  }
1223  ;
1224 
1225 resourcename: TK_NAME
1226  {
1227  if (!resource_name_p($1))
1228  yyerror("expecting a resource name\n");
1229  $$ = $1;
1230  }
1231  ;
1232 
1233 %%