PIPS
lowlevel.c
Go to the documentation of this file.
1 /*
2 
3  $Id: lowlevel.c 23490 2018-10-22 09:49: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  * Load, Save, Free a resource, with available methods.
29  * DBLL = Data Base Low Level
30  */
31 
32 #include "genC.h"
33 #include "linear.h"
34 #include "ri.h"
35 #include "private.h"
36 
37 /**************************************************** METHODS FOR RESOURCES */
38 
39 /* the current module is expected by some load/save functions...
40  */
41 const char* dbll_current_module = (const char*) NULL;
42 
43 typedef char * (* READER)(FILE *);
44 typedef void (* WRITER)(FILE *, void *);
45 typedef void (* FREER) (void *);
46 typedef bool (* CHECKER)(void *);
47 
48 typedef struct {
49  string name;
54 } methods;
55 
56 // default do-nothing methods.
57 #define no_read (READER) abort
58 #define no_write (WRITER) abort
59 static void no_free(void * p) { pips_debug(2, "memory leak (%p)\n", p); }
60 static void writeln_string(FILE * f, void * p) {fprintf(f, "%s\n", (char*)p);}
61 static void unexpected(void)
62 { pips_internal_error("unexpected pipsdbm method");}
63 
64 // from external.c
70 
71 // all methods are stored in this separate file. as an array.
72 /* sigh... */
73 #if defined(__GNUC__) && __GNUC__ >= 8
74 #pragma GCC diagnostic push
75 #pragma GCC diagnostic ignored "-Wcast-function-type"
76 #endif /* gcc version */
77 
78 static methods all_methods[] = {
79 #include "methods.h"
80 };
81 
82 #if defined(__GNUC__) && __GNUC__ >= 8
83 #pragma GCC diagnostic pop
84 #endif /* gcc version */
85 
86 /* return the methods for resource name
87  */
88 static methods * get_methods(const char* name)
89 {
90  /* we use a local cache for fast retrieval.
91  */
92  static hash_table cache = hash_table_undefined;
93  methods * m;
94 
95  if (hash_table_undefined_p(cache)) { /* initialize at first call. */
97  for (m = all_methods; m->name; m++)
98  hash_put(cache, m->name, (void *) m);
99  }
100 
101  /* get the methods! */
102  m = (methods*) hash_get(cache, name);
103  if (m==(methods*)HASH_UNDEFINED_VALUE)
104  m = &all_methods[dbll_number_of_resources()]; /* last is unexpected */
105  return m;
106 }
107 
109 { /* I'm not sure sizeof(all_methods) is ANSI C. FC */
110  return sizeof(all_methods)/sizeof(methods) - 1;
111 }
112 
114 {
115  pips_assert("valid resource number", i>=0 && i<dbll_number_of_resources());
116  return all_methods[i].name;
117 }
118 
119 bool dbll_very_special_resource_p(const char* rname, const char* oname)
120 {
121  return same_string_p(rname, DBR_ENTITIES) && same_string_p(oname, "");
122 }
123 
124 /********************************************************************** FILE */
125 
126 static char* current_builder = NULL;
127 
128 void db_set_current_builder_name(const char* name)
129 {
130  pips_assert("no current builder", !current_builder);
131  current_builder = strdup(name);
132 }
133 
135 {
136  pips_assert("some current builder", current_builder);
138 }
139 
141 {
142  pips_assert("some current builder", current_builder);
143  return current_builder;
144 }
145 
146 #define DEFAULT_OWNER_NAME WORKSPACE_PROGRAM_SPACE
147 
148 /* returns the allocated and mkdir'ed directory for module name
149  */
150 string db_get_directory_name_for_module(const char* name)
151 {
152  string dir_name, ws_dir_name;
153  pips_assert("some valid name", name && !same_string_p(name, ""));
154  ws_dir_name = db_get_current_workspace_directory();
155  dir_name = strdup(concatenate(ws_dir_name, "/", name, NULL));
156  free(ws_dir_name);
157  if (!directory_exists_p(dir_name))
158  if (!create_directory(dir_name)) /* MKDIR */
160  ("cannot create directory %s\n", dir_name);
161  return dir_name;
162 }
163 
164 /* returns an allocated file name for a file resource.
165  * may depend on the current builder, someday.
166  * this function is to be used by all phases that generate files.
167  * it does not include the directory for movability
168  */
169 string db_build_file_resource_name(const char* rname, const char* oname, const char* suffix)
170 {
171  string result;
172  if (same_string_p(oname, "")) oname = DEFAULT_OWNER_NAME;
173  free(db_get_directory_name_for_module(oname));/* mkdir as a side effect. */
174  /* the next name must be compatible with the Display script...
175  * it may depend on the builder function maybe (if pipsmake tells)
176  * may include the resource name? as lower letters?
177  */
178  result = strdup(concatenate(oname, "/", oname, suffix, NULL));
179 
180  pips_debug(8, "file name for %s[%s] with suffix '%s' is '%s'\n",
181  rname, oname, suffix, result);
182  return result;
183 }
184 
185 /* allocate a full file name for the given resource.
186  */
187 string get_resource_file_name(const char* rname, const char* oname)
188 {
189  string dir_name, file_name;
190  if (same_string_p(oname, "")) oname = DEFAULT_OWNER_NAME;
191  dir_name = db_get_directory_name_for_module(oname);
192  file_name = strdup(concatenate(dir_name, "/", rname, NULL));
193  free(dir_name);
194  return file_name;
195 }
196 
197 static FILE * open_resource_file(const char* rname, const char* oname, const char* what)
198 {
199  FILE * file;
200  string file_name = get_resource_file_name(rname, oname);
201  file = safe_fopen(file_name, what);
202  free(file_name);
203  return file;
204 }
205 
206 static void close_resource_file(FILE * file, const char* rname, const char* oname)
207 {
208  string file_name = get_resource_file_name(rname, oname);
209  safe_fclose(file, file_name);
210  free(file_name);
211 }
212 
213 
214 /*********************************************************** BASIC INTERFACE */
215 
216 #include <sys/stat.h>
217 #include <unistd.h>
218 
219 void dbll_unlink_resource_file(const char* rname, const char* oname, bool erroriffailed)
220 {
221  string full_name = get_resource_file_name(rname, oname);
222  if (unlink(full_name) && erroriffailed) {
223  perror(full_name);
224  pips_internal_error("cannot unlink resource %s of %s", rname, oname);
225  }
226  free(full_name);
227 }
228 
229 /* returns 0 on errors (say no file).
230  * otherwise returns the modification time.
231  */
232 static int dbll_stat_file(const char* file_name, bool okifnotthere)
233 {
234  struct stat buf;
235  int time = 0, error = stat(file_name, &buf);
236  if (error<0) { /* some error */
237  if (!okifnotthere || get_bool_property("WARNING_ON_STAT_ERROR")) {
238  perror(file_name);
239  pips_user_warning("error in stat for %s\n", file_name);
240  }
241  if (!okifnotthere) {
242  pips_internal_error("stat error not permitted here");
243  }
244  } else time = (int) buf.st_mtime; /* humm... unsigned... */
245  return time;
246 }
247 
248 /* It is impportant that the workspace directory does not appear in the
249  * file name so as to allow workspaces to be moveable.
250  */
251 int dbll_stat_local_file(const char* file_name, bool okifnotthere)
252 {
253  string full_name;
254  int time;
255  if (file_name[0]!='/' && file_name[0]!='.') {
256  string dir_name = db_get_current_workspace_directory();
257  full_name = strdup(concatenate(dir_name, "/", file_name, NULL));
258  free(dir_name);
259  } else full_name = strdup(file_name);
260  time = dbll_stat_file(full_name, okifnotthere);
261  free(full_name);
262  return time;
263 }
264 
265 int dbll_stat_resource_file(const char* rname, const char* oname, bool okifnotthere)
266 {
267  string file_name = get_resource_file_name(rname, oname);
268  int time = dbll_stat_file(file_name, okifnotthere);
269  free(file_name);
270  return time;
271 }
272 
273 /* save rname of oname p. get the method, then apply it.
274  */
275 void dbll_save_resource(const char* rname, const char* oname, void * p)
276 {
277  methods * m;
278  FILE * f;
279  pips_debug(7, "saving resource %s[%s] (0x%p)\n", rname, oname, p);
280 
281  dbll_current_module = oname;
282  m = get_methods(rname);
283  if (m->write_function==no_write) {
284  pips_user_warning("resource %s of %s lost, no unload function\n",
285  rname, oname);
286  } else {
287  f = open_resource_file(rname, oname, "w");
288  m->write_function(f, p);
289  close_resource_file(f, rname, oname);
290  }
291  dbll_current_module = (string) NULL;
292 }
293 
294 void * dbll_load_resource(const char* rname, const char* oname)
295 {
296  methods * m;
297  FILE * f;
298  void * p = NULL;
299  pips_debug(7, "loading resource %s[%s]\n", rname, oname);
300 
301  dbll_current_module = oname;
302  m = get_methods(rname);
303  if (m->read_function==no_read)
304  pips_internal_error("cannot load %s of %s, no load function",
305  rname, oname);
306  f = open_resource_file(rname, oname, "r");
307  p = m->read_function(f);
308  close_resource_file(f, rname, oname);
309  dbll_current_module = (string) NULL;
310  return p;
311 }
312 
313 void dbll_free_resource(const char* rname, const char* oname, void * p)
314 {
315  methods * m;
316  pips_debug(7, "freeing resource %s[%s] (%p)\n", rname, oname, p);
317  m = get_methods(rname);
318  m->free_function(p);
319 }
320 
321 /* Internal consistency of the resource, not the global consistency
322  wrt other resources and pipsmake rules which is managed by the
323  pipsmake library at a higher level. */
324 bool dbll_check_resource(const char* rname, const char* oname, void * p)
325 {
326  methods * m;
327  /* Know right away which resource is Newgen inconsistent */
328  pips_debug(9, "checking Newgen resource consistency %s[%s] (0x%p)\n",
329  rname, oname, p);
330  m = get_methods(rname);
331  bool b = m->check_function(p);
332  /* FI: I find this message I have added myself pretty useless in
333  general as a core dump occurs in case some inconsistency is
334  found. */
335  pips_debug(9, "checking Newgen resource consistency %s[%s] (0x%p): %s\n",
336  rname, oname, p,
337  bool_to_string(b));
338  return b;
339 }
340 
341 bool dbll_storable_p(const char* rname)
342 {
343  methods * m = get_methods(rname);
344  return m->write_function!=no_write;
345 }
346 
347 
348 /****************************************************** LESS BASIC INTERFACE */
349 
350 void dbll_save_and_free_resource(const char* rname, const char* oname,
351  void * p, bool do_free)
352 {
353  dbll_save_resource(rname, oname, p);
354  if (do_free) dbll_free_resource(rname, oname, p);
355 }
356 
357 /* rather approximated.
358  * beware that this function is used to check whether a resource is a file,
359  * and also to check its current time on pipsmake dependencies.
360  */
361 bool displayable_file_p(const char* name)
362 {
363  methods * m = get_methods(name);
364  return
365  // the resource itself is a string
367  // and the resource names ends with "_FILE"
368  find_suffix((string) name, "_FILE");
369 }
370 
371 /* returns whether the file is managed within the database.
372  * that is it is not a SOURCE_FILE.
373  * basically SOURCE_FILEs are given relative names with leading . or /,
374  * while within the database a leading "*.database/" is always appended.
375  */
376 bool dbll_database_managed_file_p(const char* name)
377 {
378  return name[0]!='.' && name[0]!='/';
379 }
#define error(fun, msg)
NewGen interface with C3 type Psysteme for PIPS project.
Definition: Psc.c:78
void const char const char const int
bool create_directory(char *name)
Definition: file.c:435
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
bool directory_exists_p(const char *name)
Definition: file.c:314
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void free(void *)
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
#define full_name(dir, name)
Definition: compile.c:414
bool dbll_database_managed_file_p(const char *name)
returns whether the file is managed within the database.
Definition: lowlevel.c:376
bool dbll_very_special_resource_p(const char *rname, const char *oname)
Definition: lowlevel.c:119
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
int dbll_stat_local_file(const char *file_name, bool okifnotthere)
It is impportant that the workspace directory does not appear in the file name so as to allow workspa...
Definition: lowlevel.c:251
static void close_resource_file(FILE *file, const char *rname, const char *oname)
Definition: lowlevel.c:206
static char * current_builder
Definition: lowlevel.c:126
static void writeln_string(FILE *f, void *p)
Definition: lowlevel.c:60
void pipsdbm_write_statement_mapping(FILE *, statement_mapping)
Write a statement mapping.
Definition: externals.c:115
void(* WRITER)(FILE *, void *)
Definition: lowlevel.c:44
static methods * get_methods(const char *name)
gcc version
Definition: lowlevel.c:88
void free_static_control_mapping(statement_mapping)
Modification Dec 11 1995: ne pas utiliser free_static_control car il libere des champs qui appartienn...
Definition: externals.c:318
bool displayable_file_p(const char *name)
rather approximated.
Definition: lowlevel.c:361
void(* FREER)(void *)
Definition: lowlevel.c:45
string db_get_current_builder_name(void)
Definition: lowlevel.c:140
#define DEFAULT_OWNER_NAME
Definition: lowlevel.c:146
void pipsdbm_free_statement_mapping(statement_mapping)
Definition: externals.c:190
void dbll_free_resource(const char *rname, const char *oname, void *p)
Definition: lowlevel.c:313
char *(* READER)(FILE *)
Definition: lowlevel.c:43
int dbll_number_of_resources(void)
Definition: lowlevel.c:108
hash_table pipsdbm_read_statement_mapping(FILE *)
Read a statement mapping.
Definition: externals.c:147
void db_reset_current_builder_name(void)
Definition: lowlevel.c:134
static FILE * open_resource_file(const char *rname, const char *oname, const char *what)
Definition: lowlevel.c:197
int dbll_stat_resource_file(const char *rname, const char *oname, bool okifnotthere)
Definition: lowlevel.c:265
#define no_read
Definition: lowlevel.c:57
void dbll_save_resource(const char *rname, const char *oname, void *p)
save rname of oname p.
Definition: lowlevel.c:275
void dbll_unlink_resource_file(const char *rname, const char *oname, bool erroriffailed)
Definition: lowlevel.c:219
string get_resource_file_name(const char *rname, const char *oname)
allocate a full file name for the given resource.
Definition: lowlevel.c:187
#define no_write
Definition: lowlevel.c:58
static methods all_methods[]
sigh...
Definition: lowlevel.c:78
void db_set_current_builder_name(const char *name)
Definition: lowlevel.c:128
bool dbll_check_resource(const char *rname, const char *oname, void *p)
Internal consistency of the resource, not the global consistency wrt other resources and pipsmake rul...
Definition: lowlevel.c:324
bool dbll_storable_p(const char *rname)
Definition: lowlevel.c:341
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
static void unexpected(void)
Definition: lowlevel.c:61
string dbll_get_ith_resource_name(int i)
Definition: lowlevel.c:113
static int dbll_stat_file(const char *file_name, bool okifnotthere)
returns 0 on errors (say no file).
Definition: lowlevel.c:232
void * dbll_load_resource(const char *rname, const char *oname)
Definition: lowlevel.c:294
bool pipsdbm_check_statement_mapping(statement_mapping)
a little bit partial, because domain are not checked.
Definition: externals.c:178
static void no_free(void *p)
Definition: lowlevel.c:59
void dbll_save_and_free_resource(const char *rname, const char *oname, void *p, bool do_free)
Definition: lowlevel.c:350
const char * dbll_current_module
the current module is expected by some load/save functions...
Definition: lowlevel.c:41
bool(* CHECKER)(void *)
Definition: lowlevel.c:46
#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 pips_internal_error
Definition: misc-local.h:149
#define pips_user_irrecoverable_error
Definition: misc-local.h:148
string find_suffix(const string, const string)
Find if a string s end with a suffix.
Definition: string.c:273
string bool_to_string(bool)
Definition: string.c:243
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ hash_string
Definition: newgen_hash.h:32
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define hash_table_undefined_p(h)
Definition: newgen_hash.h:50
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
#define same_string_p(s1, s2)
int bool
we cannot use an enum or stdbool because we need to be compatible with newgen, thus boolean need to h...
Definition: newgen_types.h:78
char * string
STRING.
Definition: newgen_types.h:39
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
static char buf[BSZ]
Definition: split_file.c:157
string name
Definition: lowlevel.c:49
FREER free_function
Definition: lowlevel.c:52
WRITER write_function
Definition: lowlevel.c:51
CHECKER check_function
Definition: lowlevel.c:53
READER read_function
Definition: lowlevel.c:50
static string file_name