1 /* GNU m4 -- A simple macro processor
3 Copyright (C) 1989-1993, 2004, 2006-2014, 2016-2017, 2020-2021 Free
4 Software Foundation, Inc.
6 This file is part of GNU M4.
8 GNU M4 is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU M4 is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>.
22 /* Handling of path search of included files via the builtins "include"
29 struct includes *next; /* next directory to search */
30 const char *dir; /* directory */
34 typedef struct includes includes;
36 static includes *dir_list; /* the list of path directories */
37 static includes *dir_list_end; /* the end of same */
38 static int dir_max_length; /* length of longest directory name */
50 include_env_init (void)
56 if (no_gnu_extensions)
59 env_path = getenv ("M4PATH");
63 env_path = xstrdup (env_path);
68 path_end = strchr (path, ':');
71 add_include_directory (path);
79 add_include_directory (const char *dir)
83 if (no_gnu_extensions)
89 incl = (includes *) xmalloc (sizeof (struct includes));
91 incl->len = strlen (dir);
92 incl->dir = xstrdup (dir);
94 if (incl->len > dir_max_length) /* remember len of longest directory */
95 dir_max_length = incl->len;
97 if (dir_list_end == NULL)
100 dir_list_end->next = incl;
104 xfprintf (stderr, "add_include_directory (%s);\n", dir);
108 /* Attempt to open FILE; if it opens, verify that it is not a
109 directory, and ensure it does not leak across execs. */
111 m4_fopen (const char *file)
113 FILE *fp = fopen (file, "re");
117 int fd = fileno (fp);
118 if (fstat (fd, &st) == 0 && S_ISDIR (st.st_mode))
128 /* Search for FILE, first in `.', then according to -I options. If
129 successful, return the open file, and if RESULT is not NULL, set
130 *RESULT to a malloc'd string that represents the file found with
131 respect to the current working directory. */
134 m4_path_search (const char *file, char **result)
138 char *name; /* buffer for constructed name */
144 /* Reject empty file. */
151 /* Look in current working directory first. */
152 fp = m4_fopen (file);
156 *result = xstrdup (file);
160 /* If file not found, and filename absolute, fail. */
161 if (IS_ABSOLUTE_FILE_NAME (file) || no_gnu_extensions)
165 for (incl = dir_list; incl != NULL; incl = incl->next)
167 name = file_name_concat (incl->dir, file, NULL);
170 xfprintf (stderr, "m4_path_search (%s) -- trying %s\n", file, name);
173 fp = m4_fopen (name);
176 if (debug_level & DEBUG_TRACE_PATH)
177 DEBUG_MESSAGE2 ("path search for `%s' found `%s'", file, name);
192 static void MAYBE_UNUSED
197 xfprintf (stderr, "include_dump:\n");
198 for (incl = dir_list; incl != NULL; incl = incl->next)
199 xfprintf (stderr, "\t%s\n", incl->dir);
202 #endif /* DEBUG_INCL */