PIPS
dbm.c
Go to the documentation of this file.
1 /*
2 
3  $Id: dbm.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 
28 #include <stdio.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 
32 #include "linear.h"
33 #include "genC.h"
34 
35 #include "properties.h"
36 #include "misc.h"
37 #include "pipsdbm.h"
38 
39 #include "ri-util.h"
40 #include "bootstrap.h" // bootstrap
41 #include "preprocessor.h" //pips_srcpath_set, dot_f90_file_p, dot_f95_file_p, process_user_file, init_processed_include_cache, close_processed_include_cache
42 #include "pipsmake.h" // parse_makefile & al.
43 
44 #include "top-level.h"
45 
47 
48 /* default assignment of pips_update_props_handler is
49  * default_update_props. Some top-level (eg. wpips) may need a
50  * special update_props proceedure; they should let
51  * pips_update_props_handler point toward it.
52  */
54 
55 /* PIPS SRCPATH before opening the workspace, for restauration.
56  * also works if the path was not set.
57  */
58 static string saved_pips_src_path = NULL;
59 static bool some_saved_path = false;
60 
61 static void push_path(void)
62 {
63  string dir;
64  pips_assert("not set", !some_saved_path);
66  //saved_pips_src_path = strdup(pips_srcpath_append(dir));
67  some_saved_path = true;
68  free(dir);
69 }
70 
71 static void pop_path(void)
72 {
76  saved_pips_src_path = NULL;
77  some_saved_path = false;
78 }
79 
80 /* In case an error has been detected, both create_workspace and close_workspace may attempt to clean up various static data structures. */
81 static void safe_pop_path(void)
82 {
83  if(some_saved_path) {
86  saved_pips_src_path = NULL;
87  some_saved_path = false;
88  }
89 }
90 
91 /* tpips used to convert lower cases into upper cases for all module
92  names, but this is no longer possible with C functions. To make it
93  easier for the user and for the validation, an upper case version of
94  name is open if name cannot be open. */
95 bool open_module(const char* name)
96 {
97  bool success = false;
98  char* upper_case_name = strupper(strdup(name), name);
99  char* module_name ;
100 
102  pips_user_error("No current workspace, open or create one first!\n");
103 
104  if (db_module_exists_p(name))
105  module_name = strdup(name);
106  else if(db_module_exists_p(upper_case_name)) {
107  module_name = upper_case_name;
108  pips_user_warning("Module \"%s\" selected instead of \"%s\""
109  " which was not found\n",
110  module_name, name);
111  }
112  else
113  module_name = NULL;
114 
115  if(module_name) {
116  if (db_get_current_module_name()) /* reset if needed */
118 
120  }
121 
122  if (success) {
124  user_log("Module %s selected\n", module_name);
125  }
126  else {
127  if(strcmp(name, upper_case_name)==0)
128  pips_user_warning("Could not open module %s\n", name);
129  else
130  pips_user_warning("Could not open module %s (nor %s)\n",
131  name, upper_case_name);
132  }
133 
134  if (upper_case_name != module_name)
135  free(upper_case_name);
136  return success;
137 }
138 
139 /* Open the module of a workspace if there is only one.
140 
141  @return true if all was OK or if nothing has been done (there is no
142  single module).
143 */
145 {
146  // Be optimistic:-)
147  bool success = true;
148  gen_array_t a;
149 
150  pips_assert("some current workspace", db_get_current_workspace_name());
151 
152  // First parse the makefile to avoid writing an empty one.
153  (void) parse_makefile();
154 
155  // this function returns various stuff that need to be filtered!
156  a = db_get_module_list();
157 
158  if (gen_array_nitems(a)==1) {
159  string mn = gen_array_item(a, 0);
160  if (!compilation_unit_p(mn))
161  success = open_module(mn);
162  }
163  else if (gen_array_nitems(a)==2) {
164  // In C, you cannot have fewer than two modules
165  // because of compilation units
166  string mn1 = gen_array_item(a, 0), mn2 = gen_array_item(a, 1);
167  bool mod1 = !compilation_unit_p(mn1), mod2 = !compilation_unit_p(mn2);
168  if (mod1 ^ mod2)
169  success = open_module(mod1? mn1: mod2? mn2: NULL);
170  }
172 
173  return success;
174 }
175 
176 /* FI: should be called "initialize_workspace()"; a previous call to
177  * db_create_workspace() is useful to create the log file between
178  * the two calls says RK
179  */
181 {
182  int i, argc = gen_array_nitems(files);
183  string name, dir = db_get_current_workspace_directory();
184  bool success = true;
185 
186  // since db_create_workspace() must have been called before...
187  pips_assert("some current workspace", db_get_current_workspace_name());
188 
189  open_log_file(dir);
190  open_warning_file(dir);
191  free(dir);
192 
193  // although CREATE_WORKSPACE is not a pass, to avoid unknown[unknown]"
194  set_pips_current_computation("CREATE_WORKSPACE","Program");
197 
198  // pop_path() is too strict,
199  // let's push anyway since user errors are not caught below!
200  push_path();
201 
202  // Flag that check if there is F90 file
203  bool fortran_90_p = false;
204 
205  // Precompile F95/F90 files, necessary because of module
206  for ( i = 0; i < argc; i++ ) {
207  string filename = gen_array_item( files, i );
208  if ( dot_f90_file_p( filename ) || dot_f95_file_p( filename ) ) {
209  fortran_90_p = true;
210  compile_f90_module( filename );
211  }
212  }
213 
214  if (fortran_90_p) {
215  // Load entities (fortran95 need it)
216  bootstrap( NULL );
217  }
218 
219  for (i = 0; success && i < argc; i++)
220  {
222  {
223  success = false;
224  // cleanup???
225  if (!get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR"))
226  {
227  // DB: free the hash_table, otherwise core dump during the next
228  // call to create_workspace.
232  close_log_file();
234  pop_path();
235  }
236  RETHROW();
237  }
238  TRY
239  {
242  }
243  }
244 
245  if (success)
246  {
247  (* pips_update_props_handler)();
249  user_log("Workspace %s created and opened.\n", name);
250 
251  // If there is only one function, make it the current module
253 
254  if (success)
256 
257  // set active phases
259  }
260 
261  if (success) {
262  // Try to select the source language
264 
265  l = workspace_language(files);
267  free_language(l);
268  }
269 
270  if (!success)
271  {
272  if (!get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR"))
273  {
274  // DB: free the hash_table, otherwise core dump during the next
275  // call to create_workspace.
278  close_log_file();
280  pop_path();
281  }
282  }
283 
285  return success;
286 }
287 
288 /* Do not open a module already opened : */
289 bool lazy_open_module(const char* name)
290 {
291  bool success = true;
292 
293  pips_assert("lazy_open_module", db_get_current_workspace_name());
294  pips_assert("cannot lazy_open no module", name != NULL);
295 
298  if (strcmp(current_name, name) != 0)
299  success = open_module(name);
300  else
301  user_log ("Module %s already active.\n", name);
302  } else
303  success = open_module(name);
304 
305  return success;
306 }
307 
308 /* should be: success (cf wpips.h) */
309 bool open_workspace(const char* name)
310 {
311  bool success;
312 
314  pips_user_error("Some current workspace, close it first!\n");
315 
316  if (!workspace_exists_p(name))
317  pips_user_error("Workspace %s does not exist!\n", name);
318 
319  if (!workspace_ok_p(name))
320  pips_user_error("Workspace %s not readable!\n", name);
321 
322  if (make_open_workspace(name) == NULL) {
323  /* should be show_message */
324  /* FI: what happens since log_file is not open? */
325  user_log("Cannot open workspace %s.\n", name);
326  success = false;
327  }
328  else {
329  string dir = db_get_current_workspace_directory();
330 
331  (* pips_update_props_handler)();
332 
333  open_log_file(dir);
334  open_warning_file(dir);
335  free(dir);
338  user_log("Workspace %s opened.\n", name);
341  push_path();
342  }
343  return success;
344 }
345 
346 bool close_workspace(bool is_quit)
347 {
348  bool success;
349 
351  pips_user_error("No workspace to close!\n");
352 
353  /* It is useless to save on disk some non up to date resources:
354  */
356  success = make_close_workspace(is_quit);
357  close_log_file();
363  safe_pop_path();
364  return success;
365  /*clear_props();*/
366 }
367 
368 bool delete_workspace(const char * wname)
369 {
370  int success = check_delete_workspace(wname,true);
371 
372  return success;
373 }
374 
375 bool check_delete_workspace(const char* wname, bool check)
376 {
377  int failure;
379 
380  /* Yes but at least close the LOGFILE if we delete the current
381  workspace since it will fail on NFS because of the open file
382  descriptor (creation of .nfs files). RK */
383 
384  if (check)
385  {
386  if (current && same_string_p(wname, current))
387  pips_user_error("Cannot delete current workspace, close it first!\n");
388  }
389  else
390  {
391  string name = strdup(current);
392  (void) close_makefile(name);
393  free(name);
394  close_log_file();
396  /* reset_entity_to_size(); */
398  }
399 
400  char *escaped_wname = strescape(wname);
401  if ((failure=safe_system_no_abort(concatenate("Delete ", escaped_wname, NULL))))
402  pips_user_warning("exit code for Delete is %d\n", failure);
403  free(escaped_wname);
404 
405  return !failure;
406 }
407 ␌
408 
409 
410 void compile_f90_module( string filename ) {
411  string dir = db_get_current_workspace_directory( );
412 
413  // Create precompiled directory
414  char *compiled_dir_name = strdup( concatenate( dir, "/Precompiled", NULL ) );
415  mkdir( compiled_dir_name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
416 
417  char *gfc_command = concatenate( "gfortran -fsyntax-only",
418  " -fcray-pointer -ffree-form",
419  " -x f95-cpp-input"
420  " -J ",
421  compiled_dir_name,
422  " ",
423  filename,
424  NULL );
425  if( 0 != system( gfc_command ) ) {
426  pips_user_warning("Precompilation failed : %s", gfc_command);
427  }
428 
429 }
430 
431 /* Get all stubs. The returned value is allocated dynamically
432  and needs to be freed by the caller of this function */
434 {
435  list stubs = NIL;
436 
437  // flag_as_stub pass specific
438 #ifdef DBR_STUBS
439  if (db_resource_p(DBR_STUBS, "")) {
440  callees r_stubs = (callees) db_get_memory_resource(DBR_STUBS, "", true);
441  stubs = callees_callees(r_stubs);
442  }
443 #endif // DBR_STUBS
444 
445  return gen_array_from_list(stubs);
446 }
void open_warning_file(const char *dir)
Definition: message.c:286
void close_log_file(void)
Definition: message.c:162
void user_log(const char *format,...)
Definition: message.c:234
void open_log_file(const string dir)
Definition: message.c:171
void close_warning_file(void)
Definition: message.c:293
void set_pips_current_computation(const char *rname, const char *oname)
message.c
Definition: message.c:65
void reset_pips_current_computation(void)
Definition: message.c:87
void free_language(language p)
Definition: ri.c:1205
void db_reset_current_module_name(void)
Definition: database.c:1064
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
string db_get_current_module_name(void)
Also used to check whether set...
Definition: database.c:1059
bool db_set_current_module_name(const char *name)
Definition: database.c:1045
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
#define CATCH(what)
@ user_exception_error
#define UNCATCH(what)
#define RETHROW()
#define TRY
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void gen_array_full_free(gen_array_t a)
Definition: array.c:77
gen_array_t gen_array_from_list(list ls)
Definition: array.c:170
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
bool bootstrap(string workspace)
Definition: bootstrap.c:5619
bool open_module(const char *name)
tpips used to convert lower cases into upper cases for all module names, but this is no longer possib...
Definition: dbm.c:95
void default_update_props()
Warning! Do not modify this file that is automatically generated!
Definition: dbm.c:46
bool open_module_if_unique(void)
Open the module of a workspace if there is only one.
Definition: dbm.c:144
static void safe_pop_path(void)
In case an error has been detected, both create_workspace and close_workspace may attempt to clean up...
Definition: dbm.c:81
void compile_f90_module(string filename)
Definition: dbm.c:410
bool delete_workspace(const char *wname)
Definition: dbm.c:368
bool create_workspace(gen_array_t files)
FI: should be called "initialize_workspace()"; a previous call to db_create_workspace() is useful to ...
Definition: dbm.c:180
void(* pips_update_props_handler)()=default_update_props
default assignment of pips_update_props_handler is default_update_props.
Definition: dbm.c:53
static void pop_path(void)
Definition: dbm.c:71
bool close_workspace(bool is_quit)
Definition: dbm.c:346
gen_array_t get_stubs()
Get all stubs.
Definition: dbm.c:433
bool lazy_open_module(const char *name)
Do not open a module already opened :
Definition: dbm.c:289
bool check_delete_workspace(const char *wname, bool check)
Definition: dbm.c:375
static void push_path(void)
Definition: dbm.c:61
static bool some_saved_path
Definition: dbm.c:59
bool open_workspace(const char *name)
should be: success (cf wpips.h)
Definition: dbm.c:309
static string saved_pips_src_path
PIPS SRCPATH before opening the workspace, for restauration.
Definition: dbm.c:58
bool compilation_unit_p(const char *module_name)
The names of PIPS entities carry information about their nature.
Definition: entity_names.c:56
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * strescape(const char *source)
protect a string, for example for use in a system call list of non escaped characters in the macro ab...
Definition: file.c:334
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void free(void *)
bool success
Definition: gpips-local.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
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
gen_array_t db_get_module_list(void)
Get an array of all the modules (functions, procedures and compilation units) of a workspace.
Definition: database.c:1266
bool db_module_exists_p(const char *name)
Return whether name is a "valid" module.
Definition: database.c:1129
static int failure(Pproblem XX, Pproblem UU, Pproblem VV, struct rproblem *RR)
Definition: isolve.c:1964
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_user_error
Definition: misc-local.h:147
int safe_system_no_abort(string)
the command to be executed
Definition: system.c:47
string strupper(string, const char *)
Definition: string.c:213
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define same_string_p(s1, s2)
bool make_close_workspace(bool is_quit)
FI->GO: could be in top-level, no?
Definition: openclose.c:102
string make_open_workspace(const char *name)
Definition: openclose.c:72
#define WORKSPACE_SRC_SPACE
Definition: pipsdbm-local.h:32
bool workspace_exists_p(const char *)
Definition: workspace.c:266
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
bool workspace_ok_p(const char *)
Definition: workspace.c:274
string db_get_current_workspace_name(void)
the function is used to check that there is some current workspace...
Definition: workspace.c:82
bool close_makefile(const char *)
makefile parse_makefile(void)
void delete_some_resources(void)
this is quite ugly, but I wanted to put the enumeration down to pipsdbm.
Definition: pipsmake.c:1446
void pips_srcpath_set(string)
Set the PIPS source path.
Definition: source_file.c:167
bool dot_f95_file_p(string)
Test if a name ends with .f95.
Definition: source_file.c:655
void init_processed_include_cache(void)
Definition: source_file.c:272
bool process_user_file(string)
Definition: source_file.c:1090
void close_processed_include_cache(void)
Definition: source_file.c:283
bool dot_f90_file_p(string)
Test if a name ends with .f90.
Definition: source_file.c:649
language workspace_language(gen_array_t)
Choose a language if all filenames in "files" have the same C or Fortran extensions.
Definition: source_file.c:667
void reset_static_entities()
Definition: entity.c:146
void reset_label_counter()
Definition: entity.c:322
void safe_reset_entity_to_size(void)
In case of error handling, PIPS may try to reset this table twice.
Definition: size.c:647
void reset_unique_variable_numbers(void)
Definition: variable.c:421
void set_entity_to_size(void)
Definition: size.c:625
void reset_entity_to_size(void)
Definition: size.c:635
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_callees(x)
Definition: ri.h:675
#define language_undefined
Definition: ri.h:1551
char * strdup()
static size_t current
Definition: string.c:115
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
static string current_name
Definition: tpips.c:73