diff options
Diffstat (limited to 'src/preproc/files.c')
-rw-r--r-- | src/preproc/files.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/src/preproc/files.c b/src/preproc/files.c new file mode 100644 index 0000000..07abf60 --- /dev/null +++ b/src/preproc/files.c @@ -0,0 +1,257 @@ +/* + * This file contains routines for setting up characters sources from + * files. It contains code to handle the search for include files. + */ +#include "../preproc/preproc.h" +#include "../preproc/pproto.h" + +#if CYGWIN + #include <limits.h> + #include <string.h> + #include <sys/cygwin.h> +#endif /* CYGWIN */ + +#define IsRelPath(fname) (fname[0] != '/') + +static void file_src (char *fname, FILE *f); + +static char **incl_search; /* standard locations to search for header files */ + +/* + * file_src - set up the structures for a characters source from a file, + * putting the source on the top of the stack. + */ +static void file_src(fname, f) +char *fname; +FILE *f; + { + union src_ref ref; + + #if CYGWIN + char posix_path[ _POSIX_PATH_MAX + 1 ]; + cygwin_conv_to_posix_path( fname, posix_path ); + fname = strdup( posix_path ); + #endif /* CYGWIN */ + + ref.cs = new_cs(fname, f, CBufSize); + push_src(CharSrc, &ref); + next_char = NULL; + fill_cbuf(); + } + +/* + * source - Open the file named fname or use stdin if fname is "-". fname + * is the first file from which to read input (that is, the outermost file). + */ +void source(fname) +char *fname; + { + FILE *f; + + if (strcmp(fname, "-") == 0) + file_src("<stdin>", stdin); + else { + if ((f = fopen(fname, "r")) == NULL) + err2("cannot open ", fname); + file_src(fname, f); + } + } + +/* + * include - open the file named fname and make it the current input file. + */ +void include(trigger, fname, system) +struct token *trigger; +char *fname; +int system; + { + struct str_buf *sbuf; + char *s; + char *path; + char *end_prfx; + struct src *sp; + struct char_src *cs; + char **prefix; + FILE *f; + + /* + * See if this is an absolute path name. + */ + if (IsRelPath(fname)) { + sbuf = get_sbuf(); + f = NULL; + if (!system) { + /* + * This is not a system include file, so search the locations + * of the "ancestor files". + */ + sp = src_stack; + while (f == NULL && sp != NULL) { + if (sp->flag == CharSrc) { + cs = sp->u.cs; + if (cs->f != NULL) { + /* + * This character source is a file. + */ + end_prfx = NULL; + for (s = cs->fname; *s != '\0'; ++s) + if (*s == '/') + end_prfx = s; + if (end_prfx != NULL) + for (s = cs->fname; s <= end_prfx; ++s) + AppChar(*sbuf, *s); + for (s = fname; *s != '\0'; ++s) + AppChar(*sbuf, *s); + path = str_install(sbuf); + f = fopen(path, "r"); + } + } + sp = sp->next; + } + } + /* + * Search in the locations for the system include files. + */ + prefix = incl_search; + while (f == NULL && *prefix != NULL) { + for (s = *prefix; *s != '\0'; ++s) + AppChar(*sbuf, *s); + if (s > *prefix && s[-1] != '/') + AppChar(*sbuf, '/'); + for (s = fname; *s != '\0'; ++s) + AppChar(*sbuf, *s); + path = str_install(sbuf); + f = fopen(path, "r"); + ++prefix; + } + rel_sbuf(sbuf); + } + else { /* The path is absolute. */ + path = fname; + f = fopen(path, "r"); + } + + if (f == NULL) + errt2(trigger, "cannot open include file ", fname); + file_src(path, f); + } + +/* + * init_files - Initialize this module, setting up the search path for + * system header files. + */ +void init_files(opt_lst, opt_args) +char *opt_lst; +char **opt_args; + { + int n_paths = 0; + int i, j; + char *s, *s1; + + /* + * Determine the number of standard locations to search for + * header files and provide any declarations needed for the code + * that establishes these search locations. + */ + + #if CYGWIN + char *incl_var; + static char *sysdir = "/usr/include"; + static char *windir = "/usr/include/w32api"; + n_paths = 2; + + incl_var = getenv("C_INCLUDE_PATH"); + if (incl_var != NULL) { + /* + * Add one entry for evry non-empty, colon-separated string in incl_var. + */ + char *dir_start, *dir_end; + + dir_start = incl_var; + while( ( dir_end = strchr( dir_start, ':' ) ) != NULL ) { + if (dir_end > dir_start) ++n_paths; + dir_start = dir_end + 1; + } + if ( *dir_start != '\0' ) + ++n_paths; /* One path after the final ':' */ + } + #else /* CYGWIN */ + static char *sysdir = "/usr/include/"; + n_paths = 1; + #endif /* CYGWIN */ + + /* + * Count the number of -I options to the preprocessor. + */ + for (i = 0; opt_lst[i] != '\0'; ++i) + if (opt_lst[i] == 'I') + ++n_paths; + + /* + * Set up the array of standard locations to search for header files. + */ + incl_search = alloc((n_paths + 1) * sizeof(char *)); + j = 0; + + /* + * Get the locations from the -I options to the preprocessor. + */ + for (i = 0; opt_lst[i] != '\0'; ++i) + if (opt_lst[i] == 'I') { + s = opt_args[i]; + s1 = alloc(strlen(s) + 1); + strcpy(s1, s); + + #if CYGWIN + /* + * Run s1 through cygwin_conv_to_posix_path; if the posix path + * differs from s1, reset s1 to a copy of the posix path. + */ + { + char posix_path[ _POSIX_PATH_MAX ]; + cygwin_conv_to_posix_path( s1, posix_path ); + if (strcmp( s1, posix_path ) != 0) { + free( s1 ); + s1 = salloc( posix_path ); + } + } + #endif /* CYGWIN */ + + incl_search[j++] = s1; + } + + /* + * Establish the standard locations to search after the -I options + * on the preprocessor. + */ + #if CYGWIN + if (incl_var != NULL) { + /* + * The C_INCLUDE_PATH components are carved out of a copy of incl_var. + * The colons after non-empty directory names are replaced by null + * chars, and the pointers to the start of these names are stored + * in inc_search. + */ + char *dir_start, *dir_end; + + dir_start = salloc( incl_var ); + while( ( dir_end = strchr( dir_start, ':' ) ) != NULL ) { + if (dir_end > dir_start) { + incl_search[j++] = dir_start; + *dir_end = '\0'; + } + dir_start = dir_end + 1; + } + if ( *dir_start != '\0' ) + incl_search[j++] = dir_start; + } + + /* Finally, add the system dir(s) */ + incl_search[j++] = sysdir; + incl_search[j++] = windir; + #else + incl_search[n_paths - 1] = sysdir; + #endif /* CYGWIN */ + + incl_search[n_paths] = NULL; + } |