PIPS
source_file.c
Go to the documentation of this file.
1 /*
2 
3  $Id: source_file.c 23476 2018-07-13 08:53:55Z ancourt $
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  * procedures used in both PIPS top-level, wpips and tpips.
29  *
30  * problems to use those procedures with wpips: show_message() and
31  * update_props() .
32  */
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include <dirent.h>
39 
40 #include <sys/stat.h>
41 #include <ctype.h>
42 #include <unistd.h>
43 #include <errno.h>
44 
45 #include "genC.h"
46 #include "linear.h"
47 #include "ri.h"
48 #include "database.h"
49 
50 #include "misc.h"
51 #include "properties.h"
52 
53 #include "ri-util.h"
54 #include "pipsdbm.h"
55 
56 #include "constants.h"
57 #include "resources.h"
58 #include "phases.h"
59 
60 #include "property.h"
61 /* #include "pipsmake.h" */
62 #include "pipsdbm.h"
63 
64 #include "preprocessor.h"
65 
66 #define skip_line_p(s) \
67  ((*(s))=='\0' || (*(s))=='!' || (*(s))=='*' || (*(s))=='c' || (*(s))=='C')
68 
69 
70 
71 
72 /* Return a sorted arg list of workspace names. (For each name, there
73  is a name.database directory in the current directory): */
75 {
76  int i, n;
77  // Find all directories with name ending with ".database":
78  list_files_in_directory(array, ".", "^.*\\.database$", directory_exists_p);
80  // Remove the ".database":
81  for (i = 0; i < n; i++) {
82  *strchr(gen_array_item(array, i), '.') = '\0';
83  }
84 }
85 
86 
87 /* Select the true file with names ending in ".[fF]" and return a sorted
88  arg list: */
90 {
91  list_files_in_directory(array, ".", "^.*\\.[fF]$", file_exists_p);
92 }
93 
94 
95 /* Return the path of an HPFC file name relative to the current PIPS
96  directory. Can be freed by the caller. */
98 {
99  string dir_name = db_get_current_workspace_directory(),
100  name = strdup(concatenate(
101  dir_name, "/", HPFC_COMPILED_FILE_DIR, "/", file_name, NULL));
102  free(dir_name);
103  return name;
104 }
105 
107  char ** hpfc_directory_name)
108 {
109  // some static but dynamic buffer.
110  static int hpfc_bsz = 0;
111  static char * hpfc_dir = NULL;
112 
113  int return_code, len;
115 
116  len = strlen(dir) + strlen(HPFC_COMPILED_FILE_DIR) + 5;
117 
118  if (hpfc_bsz<len) {
119  if (hpfc_dir) free(hpfc_dir), hpfc_dir=NULL;
120  hpfc_bsz = len;
121  hpfc_dir = (char*) malloc(hpfc_bsz);
122  message_assert("malloc succeeded", hpfc_dir);
123  }
124 
125  // Get the HPFC file name list:
126  sprintf(hpfc_dir, "%s/%s", dir, HPFC_COMPILED_FILE_DIR);
127 
128  return_code = safe_list_files_in_directory(
129  file_names,
130  hpfc_dir, /* Where is the output of HPFC: */
131  "^[A-Z].*\\.[fh]$", /* generated files start with upercases */
132  file_exists_p /* Plain files only: */);
133  *hpfc_directory_name = hpfc_dir;
134 
135  return return_code;
136 }
137 
138 
139 /* Change to the given directory if it exists and return a canonical name.
140  Return NULL if it does not exist, or fails
141 */
142 string pips_change_directory(const char *dir)
143 {
144  if (directory_exists_p(dir))
145  {
146  int status = chdir(dir);
147  if (status==-1)
148  {
149  perror("chdir");
150  return NULL;
151  }
152  // should check status...
153  return get_cwd();
154  }
155  return NULL;
156 }
157 
158 /********************************************************* PIPS SOURCE PATH */
159 
160 /* Set the PIPS source path
161 
162  @param path is used to set the search path or to unset if path is NULL
163 
164  Strangely this environment variable is set many times in PIPS to pass
165  some information...
166 */
167 void pips_srcpath_set(string path)
168 {
169  if (path)
170  setenv(SRCPATH, path, true);
171  else
172  unsetenv(SRCPATH);
173 }
174 
175 
176 /* returns an allocated pointer to the old value */
177 string pips_srcpath_append(string pathtoadd)
178 {
179  string old_path, new_path;
180  old_path = getenv(SRCPATH);
181  if (old_path)
182  /* Strdup the string since it is returned and use later in many other
183  places */
184  old_path = strdup(old_path);
185  new_path = concatenate(old_path? old_path: "", old_path? ":": "",
186  pathtoadd, NULL);
187  pips_srcpath_set(new_path);
188  return old_path;
189 }
190 
191 
192 /*************************** MODULE PROCESSING (INCLUDES and IMPLICIT NONE) */
193 
194 static string user_file_directory = NULL;
195 
196 #ifdef NO_RX_LIBRARY
197 
198 static bool pips_process_file(string file_name)
199 {
201  ("trap 'exit 123' 2; pips-process-module ", file_name, NULL));
202 
203  if(err==123) {
204  pips_user_warning("pips-process-module interrupted by control-C\n");
205  return false;
206  }
207  else if(err!=0)
209  ("Unexpected return code from pips-process-module: %d\n", err);
210 
211  return true;
212 }
213 
214 #else
215 
216 #include <regex.h>
217 
218 #define IMPLICIT_NONE_RX "^[ \t]*implicit[ \t]*none"
219 #define INCLUDE_FILE_RX "^[ \t]*include[ \t]*['\"]\\([^'\"]*\\)['\"]"
220 
221 /* not recognized: print *, "i = ", (0.,1.)
222  * to avoid modifying a character constant...
223  * this stuff should be done by hand in split...
224  * also the generated lines may be too long...
225  *
226  * Well, the regex can be improved if necessary.
227  *
228  * In particular, it does first columned tabbed lines.
229  */
230 #define CMPLX_RX \
231 "^[^\t!*Cc].....[^\"']*[^a-zA-Z0-9_ \t][ \t]*\\((\\)[-+0-9eE\\. \t]*,[-+0-9eE\\. \t]*)"
232 
233 #define CMPLX2_RX \
234 "^[^\t!*Cc].....[ \t]*\\((\\)[-+0-9eE\\. \t]*,[-+0-9eE\\. \t]*)"
235 
236 #define DCMPLX_RX \
237  "^[^\t!*Cc].....[^\"']*[^a-zA-Z0-9_ \t][ \t]*" \
238  "\\((\\)[-+0-9dDeE\\. \t]*,[-+0-9dDeE\\. \t]*)"
239 
240 #define DCMPLX2_RX \
241  "^[^\t!*Cc].....[ \t]*\\((\\)[-+0-9dDeE\\. \t]*,[-+0-9dDeE\\. \t]*)"
242 
243 #define GOTO_RX "g[ \t]*o[ \t]*t[ \t]*o[ \t]*"
244 
245 static regex_t
253 
254 /* tries several path for a file to include...
255  * first rely on $PIPS_SRCPATH, then other directories.
256  */
257 static string find_file(string name)
258 {
259  string srcpath = getenv(SRCPATH), result;
260  string path = strdup(concatenate(
261  srcpath? srcpath: "", ":",
263  NULL));
264  result = find_file_in_directories(name, path);
265  free(path);
266  return result;
267 }
268 
269 /* cache of preprocessed includes
270  */
273 {
274  // Since these functions are called in different context, the
275  // conventional pips_debug() is not well suitable, so revert to plain
276  // old fprintf for debug...
277  //fprintf(stderr, "[init_processed_include_cache] Entering\n");
280 }
281 
282 
284 {
285  //fprintf(stderr, "[close_processed_include_cache] Entering\n");
287  {
288  /* pips may call this without a prior call to
289  * init_processed_include_cache under some error conditions,
290  * such as a file not found in the initializer, or a failed cpp.
291  */
292  /*
293  Do not warn the user about PIPS internal architecture issues... :-/
294  pips_user_warning("no 'processed include cache' to close, "
295  "skipping...\n");
296  */
297  return;
298  }
300  HASH_MAP(k, v, { unlink(v); free(v); }, processed_cache);
303 }
304 
305 /* Returns the processed cached file name, or null if none.
306  */
307 static string get_cached(string s)
308 {
309  string res;
310  pips_assert("cache initialized", !hash_table_undefined_p(processed_cache));
311  res = hash_get(processed_cache, s);
312  //fprintf(stderr, "[close_processed_include_cache] Looking for %s : %s\n", s,
313  //res == HASH_UNDEFINED_VALUE ? "NULL" : res);
314 
315  return res == HASH_UNDEFINED_VALUE ? NULL : res;
316 }
317 
318 
319 /* return an allocated unique cache file name.
320  */
321 static string get_new_tmp_file_name(void)
322 {
323  static int unique = 0;
324  string dir_name, file_name;
325  unsigned int len;
327  len = strlen(dir_name)+20;
328  file_name = (char*) malloc(sizeof(char)*len);
329  if (!file_name) pips_internal_error("malloc failed");
330  sprintf(file_name, "%s/cached.%d", dir_name, unique++);
331  pips_assert("not too long", strlen(file_name)<len);
332  free(dir_name);
333  return file_name;
334 }
335 
336 /* double recursion (handle_file/handle_file_name)
337  * => forwarded declaration.
338  */
339 static bool handle_file(FILE*, FILE*);
340 
341 static bool handle_file_name(FILE * out, char * file_name, bool included)
342 {
343  FILE * f;
344  string found = find_file(file_name);
345  bool ok = false;
346 
347  if (!found)
348  {
349  /* Do not raise a user_error exception,
350  because you are not in the right directory
351  maybe this is not true anymore? FC 01/04/1998
352  */
353  pips_user_warning("include file %s not found\n", file_name);
354  fprintf(out,
355  "!! ERROR - include \"%s\" was not found\n"
356  " include \"%s\"\n", file_name, file_name);
357  return false;
358  }
359 
360  pips_debug(2, "including file \"%s\"\n", found);
361  if (included) fprintf(out, "! include \"%s\"\n", file_name);
362 
363  f=safe_fopen(found, "r");
364  ok = handle_file(out, f);
365  safe_fclose(f, found);
366 
367  if (included) fprintf(out, "! end include \"%s\"\n", file_name);
368  free(found);
369  return ok;
370 }
371 
372 static bool handle_include_file(FILE * out, char * file_name)
373 {
374  FILE * in;
375  bool ok = true;
376  string cached = get_cached(file_name);
377  char * error = NULL;
378 
379  if (!cached)
380  {
381  FILE * tmp_out;
382 
383  cached = get_new_tmp_file_name();
384  tmp_out = safe_fopen(cached, "w");
385  ok = handle_file_name(tmp_out, file_name, true);
386  safe_fclose(tmp_out, cached);
387 
388  /* handle bang comments and hollerith with an additionnal
389  * processing...
390  */
391  if (ok)
392  {
393  string filtered;
394  FILE * tmp_hbc, * tmp_in;
395 
396  filtered = get_new_tmp_file_name();
397  tmp_hbc = safe_fopen(filtered, "w");
398  tmp_in = safe_fopen(cached, "r");
399 
400  error = process_bang_comments_and_hollerith(tmp_in, tmp_hbc);
401  if (error) ok = false;
402 
403  safe_fclose(tmp_in, cached);
404  safe_fclose(tmp_hbc, filtered);
405 
406  safe_unlink(cached);
407  free(cached);
408  cached = filtered;
409  }
410 
411  /* if ok put in the cache, otherwise drop it. */
412  if (ok) {
413  //fprintf(stderr, "[handle_include_file] Adding in the cache %s for file %s\n",
414  //cached, file_name);
416  }
417  else {
418  safe_unlink(cached);
419  free(cached), cached = NULL;
420  }
421  }
422 
423  if (ok)
424  {
425  in = safe_fopen(cached, "r");
426  safe_cat(out, in);
427  safe_fclose(in, cached);
428  }
429 
430  if (error) pips_user_error("preprocessing error: %s\n", error);
431 
432  return ok;
433 }
434 
435 /* process f for includes and nones
436  */
437 static bool handle_file(FILE * out, FILE * f)
438 {
439  string line;
440  regmatch_t matches[2]; /* matched strings */
441 
442  while ((line = safe_readline(f)))
443  {
444  if (!skip_line_p(line))
445  {
446  if (!regexec(&include_file_rx, line, 2, matches, 0))
447  {
448  char c = line[matches[1].rm_eo];
449  line[matches[1].rm_eo]='\0';
450 
451  if (!handle_include_file(out, &line[matches[1].rm_so]))
452  return false; /* error? */
453 
454  line[matches[1].rm_eo]=c;
455  fprintf(out, "! ");
456  }
457  else if (!regexec(&implicit_none_rx, line, 0, matches, 0))
458  fprintf(out,
459  "! MIL-STD-1753 Fortran extension not in PIPS\n! ");
460  else {
461  /* FI: test for parser */
462  /* handle_complex_constants(&line); */
463  ;
464  }
465  }
466  fprintf(out, "%s\n", line);
467  free(line);
468  }
469  return true;
470 }
471 
472 static void init_rx(void)
473 {
474  static bool done=false;
475  if (done) return;
476  done=true;
477  if (regcomp(&some_goto_rx, GOTO_RX, REG_ICASE) ||
478  regcomp(&implicit_none_rx, IMPLICIT_NONE_RX, REG_ICASE) ||
479  regcomp(&include_file_rx, INCLUDE_FILE_RX, REG_ICASE) ||
480  regcomp(&complex_cst_rx, CMPLX_RX, REG_ICASE) ||
481  regcomp(&complex_cst2_rx, CMPLX2_RX, REG_ICASE) ||
482  regcomp(&dcomplex_cst_rx, DCMPLX_RX, REG_ICASE) ||
483  regcomp(&dcomplex_cst2_rx, DCMPLX2_RX, REG_ICASE))
484  pips_internal_error("invalid regular expression");
485 }
486 
487 static bool pips_process_file(string file_name, string new_name)
488 {
489  bool ok = false;
490  FILE * out;
491  pips_debug(2, "processing file %s\n", file_name);
492  init_rx();
493  out = safe_fopen(new_name, "w");
494  ok = handle_file_name(out, file_name, false);
495  safe_fclose(out, new_name);
496  return ok;
497 }
498 
499 #endif
500 
501 bool filter_file(string mod_name)
502 {
503  string name, new_name, dir_name, abs_name, abs_new_name;
504  name = db_get_memory_resource(DBR_INITIAL_FILE, mod_name, true);
505 
506  /* directory is set for finding includes. */
508  pips_dirname(db_get_memory_resource(DBR_USER_FILE, mod_name, true));
509  new_name = db_build_file_resource_name
510  (DBR_SOURCE_FILE, mod_name, FORTRAN_FILE_SUFFIX);
511 
513  abs_name = strdup(concatenate(dir_name, "/", name, NULL));
514  abs_new_name = strdup(concatenate(dir_name, "/", new_name, NULL));
515  free(dir_name);
516 
517  if (!pips_process_file(abs_name, abs_new_name))
518  {
519  pips_user_warning("initial file filtering of %s failed\n", mod_name);
520  safe_unlink(abs_new_name);
521  free(abs_new_name); free(abs_name);
522  return false;
523  }
524  free(abs_new_name); free(abs_name);
526 
527  DB_PUT_NEW_FILE_RESOURCE(DBR_SOURCE_FILE, mod_name, new_name);
528  return true;
529 }
530 
531 
532 /******************************************************************** SPLIT */
533 
534 /* is the file name of the form .../zzz???.f */
535 static bool zzz_file_p(string s)
536 {
537  int len = strlen(s)-1;
538  return len>=8 && s[len-8]=='/' && s[len-7]=='#' && s[len-6]=='#' &&
539  s[len-5]=='#' && s[len-1]=='.' && s[len]=='f';
540 }
541 
542 static void clean_file(string name)
543 {
544  FILE *f;
545  string line;
546  int i=0, size = 20;
547  char ** lines = (char**) malloc(sizeof(char*)*size);
548  pips_assert("malloc ok", lines);
549 
550  f=safe_fopen(name, "r");
551  while ((line=safe_readline(f)))
552  {
553  if (!zzz_file_p(line)) /* drop zzz* files */
554  {
555  if (i==size) { /* resize lines[] */
556  size*=2;
557  lines = (char**) realloc(lines, sizeof(char*)*size);
558  pips_assert("realloc ok", lines);
559  }
560  lines[i++]=line;
561  }
562  else
563  {
564  unlink(line);
565  free(line);
566  }
567  }
568  safe_fclose(f, name);
569 
570  /* keep order for unsplit. */
571  /* qsort(lines, i, sizeof(char*), cmp); */
572 
573  f=safe_fopen(name, "w");
574  while (i>0) {
575  fprintf(f, "%s\n", lines[--i]);
576  free(lines[i]);
577  }
578  free(lines);
579  safe_fclose(f, name);
580 }
581 
582 
583 /* Split a C or Fortran file into as many files as modules. */
585 
586 static bool pips_split_file(string name, string tempfile)
587 {
588  char * err = NULL;
589  FILE * out = safe_fopen(tempfile, "w");
590  string dir = db_get_current_workspace_directory();
592 
593  if ( dot_c_file_p( name ) )
594  err = csplit( dir, name, out );
595  else if ( dot_f_file_p( name ) || dot_F_file_p( name ) )
596  err = fsplit( dir, name, out );
597  else if ( dot_f90_file_p( name ) || dot_f95_file_p( name ) )
598  err = f95split( dir, name, &out );
599  else
600  pips_user_error("unexpected file name for splitting: %s", name);
601 
602  free(dir);
604  safe_fclose(out, tempfile);
605  clean_file(tempfile);
606  if (err) {
607  fprintf(stderr, "split error while extracting %s from %s: %s\n",
608  tempfile, name, err);
609  }
610  return err != NULL;
611 }
612 
613 /***************************************** MANAGING .F AND .c FILES WITH CPP */
614 
615 /* Allocate a new string containing the user file name, before
616  preprocessing. */
617 string preprocessed_to_user_file(string preprocessed_user_file)
618 {
619  string user_file = strdup(preprocessed_user_file);
620  string suffix = string_undefined;
621 
622  if ((suffix = find_suffix(user_file, PP_FORTRAN_ED)) != NULL) {
623  strcpy(suffix, FORTRAN_FILE_SUFFIX);
624  }
625  else if((suffix = find_suffix(user_file, PP_C_ED)) != NULL) {
626  strcpy(suffix, C_FILE_SUFFIX);
627  }
628  else {
629  /* No preprocessing has occured */
630  ;
631  }
632  return user_file;
633 }
634 
635 
636 /* Test if a name ends with .F */
637 bool dot_F_file_p(string name) {
638  return !!find_suffix(name, RATFOR_FILE_SUFFIX);
639 }
640 
641 
642 /* Test if a name ends with .f */
643 bool dot_f_file_p(string name) {
644  return !!find_suffix(name, FORTRAN_FILE_SUFFIX);
645 }
646 
647 
648 /* Test if a name ends with .f90 */
649 bool dot_f90_file_p( string name ) {
650  return !!find_suffix( name, FORTRAN90_FILE_SUFFIX );
651 }
652 
653 
654 /* Test if a name ends with .f95 */
655 bool dot_f95_file_p( string name ) {
656  return !!find_suffix( name, FORTRAN95_FILE_SUFFIX );
657 }
658 
659 
660 /* Test if a name ends with .c */
661 bool dot_c_file_p(string name) {
662  return !!find_suffix(name, C_FILE_SUFFIX);
663 }
664 
665 /* Choose a language if all filenames in "files" have the same C or
666  Fortran extensions. */
668 {
669  int i, argc = gen_array_nitems(files);
671  int n_fortran = 0;
672  int n_fortran95 = 0;
673  int n_c = 0;
674 
675  for (i = 0; i < argc; i++) {
676  string fn = gen_array_item(files, i);
677  if(dot_F_file_p(fn) || dot_f_file_p(fn))
678  n_fortran++;
679  else if(dot_c_file_p(fn))
680  n_c++;
681  else if(dot_f90_file_p(fn) || dot_f95_file_p(fn)){
682  n_fortran95++;
683  } else {
684  ;
685  }
686  }
687 
688  if(n_fortran>0 && n_fortran95==0 && n_c==0) {
689  l = make_language_fortran();
690  } else if(n_fortran==0 && n_fortran95>0 && n_c==0) {
692  } else if(n_fortran==0 && n_fortran95==0 && n_c>0) {
693  l = make_language_c();
694  } else {
695  l = make_language_unknown();
696  }
697 
698  return l;
699 }
700 
701 /* Returns the newly allocated name if preprocessing succeeds.
702  * Returns NULL if preprocessing fails.
703  */
704 
705 #if 0
706 /* The structure of the string is not checked. Funny results to be expected for strings starting or ending with ':' and containing lots of SPACES*/
707 static int colon_number(string s)
708 {
709  int number = s? 1: 0;
710  string new_s = s;
711  char c;
712 
713  while((c=*new_s++))
714  if(c==':' && new_s!=s+1 && *new_s!='\000')
715  number++;
716 
717  return number;
718 }
719 #endif
720 
721 int find_eol_coding(string name)
722 {
723  FILE * f = safe_fopen(name, "r");
724  int state =0;
725  int eol_code = -1;
726  int c;
727 
728  while((c=getc(f))!=EOF) {
729  if(c=='\n') {
730  if(state==1)
731  eol_code = 1; // DOS
732  else
733  eol_code = 0; // UNIX
734  break;
735  }
736  else if(c=='\r')
737  state = 1;
738  else {
739  if(state==1) {
740  eol_code = 2; // ISO22
741  break;
742  }
743  }
744  }
745 
746  safe_fclose(f, name);
747 
748  return eol_code;
749 }
750 ␌
751 static string include_path_to_include_flags(string include_path)
752 {
753  /* At least include files from the current directory: */
754  string includes = strdup("");
755 
756  /* Transform the include path p1:p2:... into -Ip1 -Ip2...*/
757  for(int i = 0;; i++) {
758  // Get the path i:
759  string p = nth_path(include_path, i);
760  if (p == NULL)
761  // No more directory
762  break;
763  string old_includes = includes;
764  includes = strdup(concatenate(includes, " -I", p, NULL));
765  free(p);
766  free(old_includes);
767  }
768  return includes;
769 }
770 
771 /* Process a file name.c through the C preprocessor to generate a
772  name.cpp_processed.c file
773 
774  @param name is the name of the file to process
775 
776  @return the name of the produced file
777 */
778 static string process_thru_C_pp(string name) {
779  string dir_name, new_name, simpler, cpp_options, cpp, cpp_err;
780  int status = 0;
781  string include_path = getenv(SRCPATH);
782  // To manage file encoding
783  int eol_code = -1;
784 
786  // FI: generates conflicts when several source files have the same name
787  //simpler = pips_basename(name, C_FILE_SUFFIX);
788  simpler = pips_initial_filename(name, C_FILE_SUFFIX);
789  new_name = strdup(concatenate(dir_name, "/", simpler, PP_C_ED, NULL));
790  cpp_err = strescape(concatenate(new_name, PP_ERR, NULL));
791  free(dir_name);
792  free(simpler);
793 
794  cpp = getenv(CPP_PIPS_ENV);
795  cpp_options = getenv(CPP_PIPS_OPTIONS_ENV);
796 
797  string includes = include_path_to_include_flags(include_path);
798 
799  pips_debug(1, "PIPS_SRCPATH=\"%s\"\n", include_path);
800  pips_debug(1, "INCLUDE=\"%s\"\n", includes);
801 
802  eol_code = find_eol_coding(name);
803  eol_code = 0;
804 
805  if (eol_code>0)
807  "EOL encoding for file \"%s\" is \"%s\" and not supported\n",
808  name, eol_code==1? "dos" : "iso22");
809 
811  (concatenate(cpp? cpp: CPP_CPP,
812  CPP_CPPFLAGS, cpp_options? cpp_options: "",
813  includes, " '",
814  name, "' > '", new_name, "' 2> ", cpp_err, NULL));
815 
816  free(includes);
817 
818  if(status) {
819  (void) safe_system_no_abort(concatenate("cat ", cpp_err, NULL));
820 
821  /* check "test" could be performed before "cat" but not after, and
822  the error file may be useful for the user. Why should we remove
823  it so soon?
824 
825  " && test ! -s ", cpp_err,
826  " && rm -f ", cpp_err, NULL)); */
827  free(new_name);
828  new_name = NULL;
829  }
830 /* Sed command to replace the second occurence of the formal parameter __x of the functions
831  used twice on the same line by __y.
832  Examples from math.h:
833  extern long double fabsl (long double __x) ; extern long double __fabsl (long double __x);
834  will be replace by
835  extern long double fabsl (long double __x) ; extern long double __fabsl (long double __y);
836  */
837  if (status==0) {
839  (concatenate("sed -i -e \"s/(long double __x) ;/(long double __y);/2g\" '",
840  new_name, "' 2> ", cpp_err, NULL));
841 
842  if(status) {
843  (void) safe_system_no_abort(concatenate("cat ", cpp_err, NULL));
844 
845  /* check "test" could be performed before "cat" but not after, and
846  the error file may be useful for the user. Why should we remove
847  it so soon?
848 
849  " && test ! -s ", cpp_err,
850  " && rm -f ", cpp_err, NULL)); */
851  free(new_name);
852  new_name = NULL;
853  }
854  }
855  free(cpp_err);
856 
857  return new_name;
858 }
859 
860 
861 /* Process a ratfor file name.F through the C preprocessor to generate a
862  name.fpp_processed.f file */
863 static string process_thru_fortran_pp(string name)
864 {
865  string dir_name, new_name, simpler, fpp_options, fpp, fpp_err;
866  int status;
867 
869  simpler = pips_basename(name, RATFOR_FILE_SUFFIX);
870  new_name = strdup(concatenate(dir_name, "/", simpler, PP_FORTRAN_ED, NULL));
871  fpp_err = strdup(concatenate(new_name, PP_ERR, NULL));
872  free(dir_name);
873  free(simpler);
874 
875  fpp = getenv(FPP_PIPS_ENV);
876  fpp_options = getenv(FPP_PIPS_OPTIONS_ENV);
877 
878  /* Note: the preprocessor used **must** know somehow about Fortran and
879  * its lexical and comment conventions. This is ok with gcc when g77
880  * or gfortran is included. Otherwise, "'" appearing in Fortran
881  * comments results in errors to be reported. Well, the return code
882  * could be ignored maybe, but I prefer not to.
883  */
884 
885  /* FI->FC: it should be a safe_system_no_abort(). Errors are
886  supposedly displayed... but their display is skipped because of the
887  return code of the first process and pips_internal_error is
888  executed!. PIPS_SRCPATH is not used to find the include files. A
889  pips_user_error is not caught at the process_user_file level.
890 
891  See preprocessor/Validation/csplit09.tpips */
892 
894  FPP_CPPFLAGS, fpp_options? fpp_options: "",
895  " ", name, " > ", new_name, " 2> ", fpp_err,
896  " && cat ", fpp_err,
897  " && test ! -s ", fpp_err,
898  " && rm -f ", fpp_err, NULL));
899 
900  /* fpp was wrong... */
901  if (status)
902  {
903  /* show errors */
904  (void) safe_system_no_abort(concatenate("cat ", fpp_err, NULL));
905  free(new_name);
906  new_name = NULL;
907  }
908 
909  free(fpp_err);
910  return new_name;
911 }
912 
913 
914 /* Process a file through a C or Fortran preprocessor according to its
915  type. */
916 static string process_thru_cpp(string name)
917 {
918  /* Not much to share between .F and .c? */
919  string new_name = string_undefined;
920 
921  if(dot_F_file_p(name))
922  new_name = process_thru_fortran_pp(name);
923  else
924  new_name = process_thru_C_pp(name);
925 
926  return new_name;
927 }
928 ␌
929 /*************************************************** MANAGING A USER FILE */
930 
931 /* Why return an int rather than a bool? */
932 static bool pips_check_syntax(string env, string prop)
933 {
934  // environment has the priority
935  string v = getenv(env);
936 
937  if (v && (*v=='o' || *v=='y' || *v=='t' || *v=='v' || *v=='1' ||
938  *v=='O' || *v=='Y' || *v=='T' || *v=='V'))
939  return true;
940 
941  if (v && (*v=='n' || *v=='f' || *v=='0' || *v=='N' || *v=='F' ))
942  return false;
943 
944  // else look for the property
945  return get_bool_property(prop);
946 }
947 
948 
949 /* A Fortran compiler must be run or not before launching the PIPS
950  * Fortran parser, according to the environment variable
951  * PIPS_CHECK_FORTRAN firstly, and then according to property
952  * CHECK_FORTRAN_SYNTAX_BEFORE_RUNNING_PIPS. So the environment overrides the
953  * property.
954  */
955 static bool pips_check_fortran(void)
956 {
957  string env = "PIPS_CHECK_FORTRAN";
958  string prop = "CHECK_FORTRAN_SYNTAX_BEFORE_RUNNING_PIPS";
959  return pips_check_syntax(env, prop);
960 }
961 
962 /* A C compiler must be run or not before launching the PIPS C parser,
963  * according to the environment variable PIPS_CHECK_C firstly,
964  * and then according to property
965  * CHECK_C_SYNTAX_BEFORE_RUNNING_PIPS. So the environment overrides
966  * the property.
967  */
968 static bool pips_check_c(void)
969 {
970  string env = "PIPS_CHECK_C";
971  string prop = "CHECK_C_SYNTAX_BEFORE_RUNNING_PIPS";
972  return pips_check_syntax(env, prop);
973 }
974 
975 /* Verify that the syntax of a program is correct by running a real
976  * compiler on it.
977  *
978  * string compiler may/must contain the necessary options, e.g. PIPS_CC_FLAGS
979  */
980 static bool
982  string file_name, string compiler, string options, string language)
983 {
984  bool syntax_ok_p = true;
985  // SRCPATH has already been used to locate the file and generate a
986  // full file name, file_name
987  string include_path = getenv(SRCPATH);
988  string includes = include_path_to_include_flags(include_path);
989 
990  user_log("Checking %s syntax of file \"%s\"\n", language, file_name);
991 
992  // SG: do not forget to protect file_name
993  char *pfile_name= strescape(file_name);
995  (concatenate(compiler, " ", options, includes, " ", pfile_name, " ",
996  // DO NOT USE A POSSIBLY SHARED FILE NAME!
997  // the same "file_name.o" can be used by several creates
998  // performed in parallel, for instance by the validation...
999  " -c -o /dev/null", NULL)))
1000  {
1001  // Note that TAB is avoided in warning to simplify validation.
1002  /* pips_user_warning("\n\n %s syntax errors in file \"%s\"!\007\n\n", */
1003  /* language, file_name); */
1004  /* Hopefully, this new warning is more informative and easier to
1005  * retrieve as last line in the Warnings file.
1006  */
1007  pips_user_warning("\n\%s syntax errors in source file \"%s\". "
1008  "Check source file and/or compilation and preprocessing flags.\n",
1009  language, file_name);
1010  syntax_ok_p = false;
1011  }
1012  free(pfile_name);
1013  free(includes);
1014  return syntax_ok_p;
1015 }
1016 
1017 /* Verify that the Fortran syntax of a source file is correct by
1018  compiling it.
1019 */
1021 {
1022  // get compiler & flags...
1023  string fortran = getenv("PIPS_FLINT");
1024  if (!fortran) fortran = getenv("PIPS_F77");
1025  if (!fortran) fortran = DEFAULT_PIPS_FLINT;
1026  // yes, cpp
1027  string flags = getenv("PIPS_CPP_FLAGS");
1028  flags = flags? flags: "";
1029  return check_input_file_syntax(file_name, fortran, flags, "Fortran");
1030 }
1031 
1032 /* Verify that the C syntax of a source file is correct by
1033  compiling it. */
1034 static bool check_c_file_syntax(string file_name)
1035 {
1036  string comp = getenv("PIPS_CC");
1037  string flags = getenv("PIPS_CPP_FLAGS");
1038  bool syntax_ok_p = true;
1039 
1040  comp = comp? comp: DEFAULT_PIPS_CC;
1041  flags = flags? flags: DEFAULT_PIPS_CC_FLAGS;
1042 
1043  syntax_ok_p = check_input_file_syntax(file_name, comp, flags, "C");
1044 
1045  return syntax_ok_p;
1046 }
1047 
1048 /* "foo bla fun ./e.database/foo.f" -> "./e.database/foo.f"
1049  */
1050 static char* extract_last_name(char *line)
1051 {
1052 #if 1
1053  /* look for the two past directory separators */
1054  char * iter = line + strlen(line);
1055  for(int i =2;i&&iter!=line;--iter) {
1056  if(*iter=='/') --i;
1057  }
1058  /* then look for whitespace separated module names */
1059  if(iter==line) {
1060  iter= strrchr(line,' ');
1061  if(iter) {
1062  iter[0]=0;
1063  iter=iter+1;
1064  }
1065  }
1066  else
1067  iter[-1]=0;
1068  if(!iter)
1069  iter=line;
1070 
1071  return iter;
1072 #else
1073  int l = strlen(line);
1074  do {
1075  while (l>=0 && line[l]!=' ') l--;
1076  if (l>=0 && line[l]==' ') line[l]='\0';
1077  } while (l>=0 && strlen(line+l+1)==0);
1078  return l>=-1? line+l+1: NULL;
1079 #endif
1080 
1081 }
1082 
1083 ␌
1084 /* The digestion of a user file by PIPS begins here.
1085 
1086  The file is searched in the SRCPATH directories. */
1087 
1089 
1090 bool process_user_file(string file)
1091 {
1092  bool success_p = false, cpp_processed_p;
1093  string dir_name = db_get_current_workspace_directory();
1094 
1095  // FC: hmmm this function is not very strict,
1096  // and sometime we need clean user errors...
1097  bool generate_user_error =
1098  get_bool_property("ABORT_ON_USER_ERROR") ||
1099  get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR");
1100 
1101  static int number_of_files = 0;
1102  static int number_of_modules = 0;
1103  static int resource_name_conflicts = 0;
1104 
1105  number_of_files++;
1106  pips_debug(1, "file %s (number %d)\n", file, number_of_files);
1107 
1108  /* The file is looked for in the pips source path.
1109  */
1110  string nfile = find_file_in_directories(file, getenv(SRCPATH));
1111 
1112  if (!nfile)
1113  {
1114  pips_user_error("Cannot open file: \"%s\"", file);
1115  return false;
1116  }
1117 
1118  string initial_file = nfile;
1120 
1121  // The new file is registered (well, not really...) in the database.
1122  user_log("Registering file %s\n", file);
1123 
1124  bool syntax_ok_p = true;
1125  if ((dot_F_file_p(nfile) || dot_f_file_p(nfile)) && pips_check_fortran())
1126  {
1127  // Note: a Fortran compiler is required on the machine.
1128  syntax_ok_p = check_fortran_syntax_before_pips(nfile);
1129  }
1130  else if (dot_c_file_p(nfile) && pips_check_c()) {
1131  // Note: a C compiler is required on the machine. Run it.
1132  syntax_ok_p = check_c_file_syntax(nfile);
1133  }
1134  else
1135  {
1136  /* Do not check the syntax in the input file: quite dangerous in
1137  case it is wrong because PIPS is not designed to work on
1138  damaged source codes. But this may be useful is the input file
1139  is a validation file or if the input file has already been
1140  checked. */
1141  pips_debug(1, "No syntactic check on file \"%s\"\n", nfile);
1142  }
1143 
1144  if (!syntax_ok_p)
1145  {
1146  if (generate_user_error)
1147  pips_user_error("Syntax check failed on \"%s\"", nfile);
1148  // It is up to the caller to decide if the syntax must be checked
1149  // for other files as well
1150  return false;
1151  }
1152 
1153  // CPP if file extension is .F or .c
1154  // (assumes string_equal_p(nfile, initial_file))
1155  cpp_processed_p = dot_F_file_p(nfile) || dot_c_file_p(nfile);
1156 
1157  if (cpp_processed_p)
1158  {
1159  user_log("Preprocessing file %s\n", initial_file);
1160  nfile = process_thru_cpp(initial_file);
1161  if (nfile==NULL)
1162  {
1163  if (generate_user_error)
1164  pips_user_error("Cannot preprocess file \"%s\"", initial_file);
1165  else
1166  pips_user_warning("Cannot preprocess file: %s\n", initial_file);
1167  return false;
1168  }
1169  }
1170  else if ( !dot_f_file_p( nfile ) && !dot_f90_file_p( nfile )
1171  && !dot_f95_file_p( nfile ) ) {
1172  pips_user_error("Unexpected file extension\n");
1173  }
1174 
1175  /* If two modules have the same name, the first splitted wins
1176  * and the other one is hidden by the call since fsplit gives
1177  * it a zzz00n.f name
1178  * Let's hope no user module is called ###???.f
1179  */
1180  string file_list =
1181  strdup(concatenate(dir_name,
1182  dot_c_file_p(nfile)?
1183  "/.csplit_file_list" : "/.fsplit_file_list", NULL));
1184  unlink(file_list);
1185 
1186  user_log("Splitting file %s\n", nfile);
1187  if (pips_split_file(nfile, file_list))
1188  {
1189  if (generate_user_error)
1190  pips_user_error("error while splitting file \"%s\"", nfile);
1191  return false;
1192  }
1193 
1194  /* The newly created module files are registered in the database
1195  * The file_list allows split to communicate with this function.
1196  */
1197  FILE * fd = safe_fopen(file_list, "r");
1198  string a_line;
1199  while ((a_line = safe_readline(fd)) && resource_name_conflicts == 0)
1200  {
1201  string mod_name = NULL, res_name = NULL;
1202  list modules = NIL;
1203  bool renamed=false;
1204 
1205  /* a_line: "MODULE1 ... MODULEn file_name"
1206  *
1207  * The list modules comes from entries that might be included
1208  * in the subroutine.
1209  */
1210  string file_name = extract_last_name(a_line);
1211  success_p = true;
1212  number_of_modules++;
1213  pips_debug(2, "module %s (number %d)\n", file_name, number_of_modules);
1214 
1215  while (mod_name!=a_line && (mod_name = extract_last_name(a_line)))
1216  modules = CONS(STRING, mod_name, modules);
1217 
1218  /* For each Fortran module in the line, put the initial_file and
1219  user_file resource. In C, line should have only one entry and a C
1220  source file and a user file resources are created. */
1221  FOREACH(STRING, mod_name, modules)
1222  {
1223  user_log(" Module %s\n", mod_name);
1224 
1225  if (!renamed)
1226  {
1227  FILE * rf = NULL;
1228 
1229  if (dot_c_file_p(nfile)) {
1230  res_name = db_build_file_resource_name
1231  (DBR_C_SOURCE_FILE, mod_name, C_FILE_SUFFIX);
1232  }
1233  else {
1234  res_name = db_build_file_resource_name
1235  (DBR_INITIAL_FILE, mod_name, FORTRAN_INITIAL_FILE_SUFFIX);
1236  }
1237 
1238  string abs_res = strdup(concatenate(dir_name, "/", res_name, NULL));
1239 
1240  if ((rf = fopen(abs_res, "r"))!=NULL)
1241  { // Resource name conflict
1242  string ofile =
1243  db_get_memory_resource(DBR_USER_FILE, mod_name, true);
1244 
1245  fclose(rf);
1246  pips_user_warning("Duplicate module name \"%s\""
1247  " from files \"%s\" and \"%s\".\n",
1248  res_name, ofile, nfile);
1249  resource_name_conflicts++;
1250  break;
1251  }
1252 
1253  if (rename(file_name, abs_res))
1254  pips_internal_error("mv %s %s failed", file_name, res_name);
1255  renamed = true;
1256  free(abs_res);
1257  }
1258 
1259  if(dot_c_file_p(nfile)) {
1260  DB_PUT_NEW_FILE_RESOURCE(DBR_C_SOURCE_FILE, mod_name,
1261  strdup(res_name));
1262  DB_PUT_NEW_FILE_RESOURCE(DBR_INPUT_FILE_NAME, mod_name,
1263  strdup(initial_file));
1264  }
1265  else {
1266  DB_PUT_NEW_FILE_RESOURCE(DBR_INITIAL_FILE, mod_name,
1267  strdup(res_name));
1268  }
1269  // from which file the initial source was derived.
1270  // absolute path to the file so that db moves should be ok?
1271  DB_PUT_NEW_FILE_RESOURCE(DBR_USER_FILE, mod_name, strdup(nfile));
1272 
1273  if ( dot_f90_file_p( nfile ) || dot_f95_file_p( nfile ) )
1274  {
1275  char *parsedcode_filename =
1276  get_resource_file_name(DBR_PARSED_CODE, mod_name);
1277  FILE *parsedcode_file = safe_fopen( parsedcode_filename, "r" );
1278  DB_PUT_NEW_FILE_RESOURCE(DBR_PARSED_CODE, mod_name,
1279  gen_read( parsedcode_file ));
1280  safe_fclose( parsedcode_file, parsedcode_filename );
1281  char *callees_filename =
1282  get_resource_file_name( DBR_CALLEES, mod_name );
1283  FILE *callees_file = safe_fopen( callees_filename, "r" );
1284  DB_PUT_NEW_FILE_RESOURCE(DBR_CALLEES, mod_name,
1285  gen_read( callees_file ) );
1286  safe_fclose( callees_file, callees_filename );
1287  string source_file_name =
1288  strdup(concatenate(dir_name, "/", mod_name, "/", mod_name, ".f90",
1289  NULL));
1290  DB_PUT_NEW_FILE_RESOURCE( DBR_SOURCE_FILE, mod_name, source_file_name );
1291  }
1292  }
1293 
1294  gen_free_list(modules), modules=NIL;
1295 
1296  if (res_name) free(res_name), res_name = NULL;
1297  free(a_line);
1298  }
1299 
1300  safe_fclose(fd, file_list);
1301  unlink(file_list);
1302  free(file_list);
1303  free(dir_name);
1304 
1305  if (cpp_processed_p) {
1306  free(initial_file); /* hey, that's cleaning! */
1308  }
1309 
1310  if (!success_p)
1311  {
1312  // empty file... ???
1313  pips_user_warning("No module was found when splitting file %s.\n", nfile);
1314  }
1315 
1316  if (cpp_processed_p) {
1317  // nfile is not the initial file
1318  pips_debug(1, "Remove output of preprocessing: %s\n", nfile);
1319  /* Seems to be recorded as a resource, causes problems later when
1320  closing the workspace... */
1321  /* unlink(nfile); */
1322  }
1323  free(nfile);
1324 
1325  // well, returns ok whether modules were found or not,
1326  // but do not accept name conflicts.
1327  return resource_name_conflicts==0;
1328 }
1329 
1330 
1331 /*
1332  * Flag a function as a stub
1333  */
1334 bool flag_as_stub(const string module_name) {
1335  if (!db_resource_p(DBR_STUBS, ""))
1336  pips_internal_error("stubs not initialized");
1337  callees stubs=(callees)db_get_memory_resource(DBR_STUBS,"",true);
1339  DB_PUT_MEMORY_RESOURCE(DBR_STUBS,"",stubs);
1340  return true;
1341 
1342 }
1343 
1344 bool bootstrap_stubs(const string module_name)
1345 {
1346  if (db_resource_p(DBR_STUBS, ""))
1347  pips_internal_error("kernels already initialized for %s", module_name);
1348  callees stubs=make_callees(NIL);
1349  DB_PUT_MEMORY_RESOURCE(DBR_STUBS,"",stubs);
1350  return true;
1351 }
void user_log(const char *format,...)
Definition: message.c:234
language make_language_fortran95(void)
Definition: ri.c:1256
language make_language_fortran(void)
Definition: ri.c:1250
language make_language_unknown(void)
Definition: ri.c:1259
language make_language_c(void)
Definition: ri.c:1253
callees make_callees(list a)
Definition: ri.c:227
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
#define error(fun, msg)
NewGen interface with C3 type Psysteme for PIPS project.
Definition: Psc.c:78
static FILE * out
Definition: alias_check.c:128
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
string csplit(char *dir_name, char *file_name, FILE *out)
Definition: csplit_file.c:641
struct _newgen_struct_status_ * status
Definition: database.h:31
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * f95split(char *dir_name, char *file_name, FILE **out)
f95split_file.c
Definition: f95split_file.c:56
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
bool file_exists_p(const char *name)
Definition: file.c:321
char * pips_initial_filename(char *fullpath, char *suffix)
The source file name access path is shortened or not depending on the property.
Definition: file.c:829
string nth_path(const char *path_list, int n)
Returns the allocated nth path from colon-separated path string.
Definition: file.c:362
char * find_file_in_directories(const char *file_name, const char *dir_path)
returns an allocated string pointing to the file, possibly with an additional path taken from colon-s...
Definition: file.c:399
char * get_cwd(void)
returns the current working directory name.
Definition: file.c:486
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
void list_files_in_directory(gen_array_t files, string dir, string re, bool(*file_name_predicate)(const char *))
The same as the previous safe_list_files_in_directory() but with no return code and a call to user er...
Definition: file.c:299
bool directory_exists_p(const char *name)
Definition: file.c:314
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
some path to file suffix some path to *char * pips_dirname(char *fullpath)
Definition: file.c:837
char * safe_readline(FILE *file)
returns the allocated line read, whatever its length.
Definition: file.c:497
int safe_list_files_in_directory(gen_array_t files, string dir, string re, bool(*file_name_predicate)(const char *))
returns a sorted arg list of files matching regular expression re in directory 'dir' and with file_na...
Definition: file.c:250
char * pips_basename(char *fullpath, char *suffix)
Definition: file.c:822
void safe_unlink(const char *file_name)
Delete the given file.
Definition: file.c:852
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void safe_cat(FILE *out, FILE *in)
Definition: file.c:669
#define STRING(x)
Definition: genC.h:87
static FILE * user_file
These functions implements the writing of objects.
Definition: genClib.c:1485
gen_chunk * gen_read(FILE *file)
GEN_READ reads any object from the FILE stream.
Definition: genClib.c:2323
static jmp_buf env
Definition: genClib.c:2473
void * malloc(YYSIZE_T)
void free(void *)
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#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
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
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
#define DB_PUT_NEW_FILE_RESOURCE(res_name, own_name, res_val)
Put a new file resource into the current workspace database.
static GtkWidget * lines[HELP_LINES]
Definition: gtk_help.c:47
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
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
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
string get_resource_file_name(const char *rname, const char *oname)
allocate a full file name for the given resource.
Definition: lowlevel.c:187
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_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_error
Definition: misc-local.h:147
int safe_system_no_abort(string)
the command to be executed
Definition: system.c:47
#define message_assert(msg, ex)
Definition: newgen_assert.h:47
string find_suffix(const string, const string)
Find if a string s end with a suffix.
Definition: string.c:273
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ 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 string_undefined
Definition: newgen_types.h:40
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define build_pgmwd
#define WORKSPACE_TMP_SPACE
Definition: pipsdbm-local.h:31
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
string db_get_current_workspace_name(void)
the function is used to check that there is some current workspace...
Definition: workspace.c:82
#define FPP_CPPFLAGS
The default preprocessor flags to use with Fortran files.
#define FPP_CPP
The preprocessor to use for Fortran files.
#define FPP_PIPS_OPTIONS_ENV
#define SRCPATH
Preprocessing and splitting of Fortran and C files.
#define DEFAULT_PIPS_CC_FLAGS
#define FPP_PIPS_ENV
#define CPP_CPP
default preprocessor and basic options -C: do not discard comments...
#define CPP_PIPS_ENV
pre-processor and added options from environment
#define CPP_PIPS_OPTIONS_ENV
#define CPP_CPPFLAGS
#define CPP_CPPFLAGS " -P -D__PIPS__ -D__HPFC__ "
#define DEFAULT_PIPS_FLINT
#define DEFAULT_PIPS_CC
See necessary definitions in pipsmake-rc.tex.
char * fsplit(char *, char *, FILE *)
Definition: split_file.c:474
char * process_bang_comments_and_hollerith(FILE *, FILE *)
processing extracted for includes...
Definition: split_file.c:836
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_callees(x)
Definition: ri.h:675
#define language_undefined
Definition: ri.h:1551
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
static int line
FLEX_SCANNER.
Definition: scanner.c:852
static hash_table matches
Definition: simdizer.c:60
static void init_rx(void)
Definition: source_file.c:472
static string process_thru_cpp(string name)
Process a file through a C or Fortran preprocessor according to its type.
Definition: source_file.c:916
static void clean_file(string name)
Definition: source_file.c:542
static regex_t implicit_none_rx
Definition: source_file.c:247
#define GOTO_RX
Definition: source_file.c:243
void pips_get_fortran_list(gen_array_t array)
Select the true file with names ending in ".[fF]" and return a sorted arg list:
Definition: source_file.c:89
static bool pips_check_syntax(string env, string prop)
Why return an int rather than a bool?
Definition: source_file.c:932
string preprocessed_to_user_file(string preprocessed_user_file)
Allocate a new string containing the user file name, before preprocessing.
Definition: source_file.c:617
#define CMPLX2_RX
Definition: source_file.c:233
bool dot_c_file_p(string name)
Test if a name ends with .c.
Definition: source_file.c:661
bool filter_file(string mod_name)
Definition: source_file.c:501
#define CMPLX_RX
not recognized: print *, "i = ", (0.,1.) to avoid modifying a character constant.....
Definition: source_file.c:230
static string process_thru_C_pp(string name)
Process a file name.c through the C preprocessor to generate a name.cpp_processed....
Definition: source_file.c:778
static bool check_c_file_syntax(string file_name)
Verify that the C syntax of a source file is correct by compiling it.
Definition: source_file.c:1034
bool dot_f_file_p(string name)
Test if a name ends with .f.
Definition: source_file.c:643
static string include_path_to_include_flags(string include_path)
Definition: source_file.c:751
static bool handle_file(FILE *, FILE *)
double recursion (handle_file/handle_file_name) => forwarded declaration.
Definition: source_file.c:437
static regex_t some_goto_rx
Definition: source_file.c:246
static bool handle_file_name(FILE *out, char *file_name, bool included)
Definition: source_file.c:341
static char * extract_last_name(char *line)
"foo bla fun ./e.database/foo.f" -> "./e.database/foo.f"
Definition: source_file.c:1050
static bool check_fortran_syntax_before_pips(string file_name)
Verify that the Fortran syntax of a source file is correct by compiling it.
Definition: source_file.c:1020
string preprocessor_current_split_file_name
Split a C or Fortran file into as many files as modules.
Definition: source_file.c:584
static regex_t dcomplex_cst_rx
Definition: source_file.c:251
language workspace_language(gen_array_t files)
Choose a language if all filenames in "files" have the same C or Fortran extensions.
Definition: source_file.c:667
static string get_new_tmp_file_name(void)
return an allocated unique cache file name.
Definition: source_file.c:321
bool dot_f90_file_p(string name)
Test if a name ends with .f90.
Definition: source_file.c:649
bool flag_as_stub(const string module_name)
Definition: source_file.c:1334
void pips_get_workspace_list(gen_array_t array)
Return a sorted arg list of workspace names.
Definition: source_file.c:74
#define INCLUDE_FILE_RX
Definition: source_file.c:219
static bool pips_process_file(string file_name, string new_name)
Definition: source_file.c:487
static regex_t complex_cst2_rx
Definition: source_file.c:250
string preprocessor_current_initial_file_name
The digestion of a user file by PIPS begins here.
Definition: source_file.c:1088
void init_processed_include_cache(void)
Definition: source_file.c:272
#define DCMPLX2_RX
Definition: source_file.c:240
static bool pips_check_fortran(void)
A Fortran compiler must be run or not before launching the PIPS Fortran parser, according to the envi...
Definition: source_file.c:955
#define DCMPLX_RX
Definition: source_file.c:236
static bool zzz_file_p(string s)
is the file name of the form .../zzz???.f
Definition: source_file.c:535
#define skip_line_p(s)
include "pipsmake.h"
Definition: source_file.c:66
#define IMPLICIT_NONE_RX
Definition: source_file.c:218
int find_eol_coding(string name)
Returns the newly allocated name if preprocessing succeeds.
Definition: source_file.c:721
static bool check_input_file_syntax(string file_name, string compiler, string options, string language)
Verify that the syntax of a program is correct by running a real compiler on it.
Definition: source_file.c:981
static string find_file(string name)
tries several path for a file to include...
Definition: source_file.c:257
string pips_change_directory(const char *dir)
Change to the given directory if it exists and return a canonical name.
Definition: source_file.c:142
string hpfc_generate_path_name_of_file_name(const char *file_name)
Return the path of an HPFC file name relative to the current PIPS directory.
Definition: source_file.c:97
static string get_cached(string s)
Returns the processed cached file name, or null if none.
Definition: source_file.c:307
bool bootstrap_stubs(const string module_name)
Definition: source_file.c:1344
bool dot_f95_file_p(string name)
Test if a name ends with .f95.
Definition: source_file.c:655
void close_processed_include_cache(void)
Definition: source_file.c:283
static bool handle_include_file(FILE *out, char *file_name)
Definition: source_file.c:372
static regex_t dcomplex_cst2_rx
Definition: source_file.c:252
static bool pips_split_file(string name, string tempfile)
Definition: source_file.c:586
static string process_thru_fortran_pp(string name)
Process a ratfor file name.F through the C preprocessor to generate a name.fpp_processed....
Definition: source_file.c:863
static bool pips_check_c(void)
A C compiler must be run or not before launching the PIPS C parser, according to the environment vari...
Definition: source_file.c:968
static hash_table processed_cache
cache of preprocessed includes
Definition: source_file.c:271
string pips_srcpath_append(string pathtoadd)
returns an allocated pointer to the old value
Definition: source_file.c:177
bool dot_F_file_p(string name)
Test if a name ends with .F.
Definition: source_file.c:637
static regex_t include_file_rx
Definition: source_file.c:248
void pips_srcpath_set(string path)
Set the PIPS source path.
Definition: source_file.c:167
bool process_user_file(string file)
Definition: source_file.c:1090
int hpfc_get_file_list(gen_array_t file_names, char **hpfc_directory_name)
Definition: source_file.c:106
static string user_file_directory
Definition: source_file.c:194
static regex_t complex_cst_rx
Definition: source_file.c:249
static bool ok
static entity array
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
static string file_name