1 /********************************************************************/
2 /* */
3 /* s7 Seed7 interpreter */
4 /* Copyright (C) 1990 - 2013 Thomas Mertes */
5 /* */
6 /* This program is free software; you can redistribute it and/or */
7 /* modify it under the terms of the GNU General Public License as */
8 /* published by the Free Software Foundation; either version 2 of */
9 /* the License, or (at your option) any later version. */
10 /* */
11 /* This program is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public */
17 /* License along with this program; if not, write to the */
18 /* Free Software Foundation, Inc., 51 Franklin Street, */
19 /* Fifth Floor, Boston, MA 02110-1301, USA. */
20 /* */
21 /* Module: Analyzer - Libraries */
22 /* File: seed7/src/libpath.c */
23 /* Changes: 1990 - 1994, 2013 Thomas Mertes */
24 /* Content: Procedures to manage the include library search path. */
25 /* */
26 /********************************************************************/
27
28 #define LOG_FUNCTIONS 0
29 #define VERBOSE_EXCEPTIONS 0
30
31 #include "version.h"
32
33 #include "stdlib.h"
34 #include "stdio.h"
35 #include "string.h"
36
37 #include "common.h"
38 #include "data.h"
39 #include "data_rtl.h"
40 #include "os_decls.h"
41 #include "heaputl.h"
42 #include "striutl.h"
43 #include "infile.h"
44 #include "hsh_rtl.h"
45 #include "str_rtl.h"
46 #include "cmd_rtl.h"
47 #include "cmd_drv.h"
48
49 #undef EXTERN
50 #define EXTERN
51 #include "libpath.h"
52
53
54 static rtlArrayType lib_path;
55
56 intType strCmpGeneric (const genericType value1, const genericType value2);
57 genericType strCreateGeneric (const genericType source);
58 void strDestrGeneric (const genericType old_value);
59
60
61
initIncludeFileHash(void)62 rtlHashType initIncludeFileHash (void)
63
64 {
65 rtlHashType includeFileHash;
66
67 /* initIncludeFileHash */
68 logFunction(printf("initIncludeFileHash()\n"););
69 includeFileHash = hshEmpty();
70 logFunction(printf("initIncludeFileHash --> " FMT_U_MEM "\n",
71 (memSizeType) includeFileHash););
72 return includeFileHash;
73 } /* initIncludeFileHash */
74
75
76
shutIncludeFileHash(const const_rtlHashType includeFileHash)77 void shutIncludeFileHash (const const_rtlHashType includeFileHash)
78
79 { /* shutIncludeFileHash */
80 logFunction(printf("shutIncludeFileHash(" FMT_U_MEM ")\n",
81 (memSizeType) includeFileHash););
82 hshDestr(includeFileHash, &strDestrGeneric, &genericDestr);
83 logFunction(printf("shutIncludeFileHash -->\n"););
84 } /* shutIncludeFileHash */
85
86
87
openIncludeFile(const rtlHashType includeFileHash,const_striType includeFileName,errInfoType * err_info)88 static includeResultType openIncludeFile (const rtlHashType includeFileHash,
89 const_striType includeFileName, errInfoType *err_info)
90
91 {
92 striType absolutePath;
93 includeResultType includeResult = INCLUDE_FAILED;
94
95 /* openIncludeFile */
96 logFunction(printf("openIncludeFile(" FMT_U_MEM ", \"%s\", %d)\n",
97 (memSizeType) includeFileHash,
98 striAsUnquotedCStri(includeFileName),
99 *err_info););
100 absolutePath = getAbsolutePath(includeFileName);
101 if (unlikely(absolutePath == NULL)) {
102 *err_info = MEMORY_ERROR;
103 } else {
104 if (hshContains(includeFileHash, (genericType) absolutePath,
105 strHashCode(absolutePath), &strCmpGeneric)) {
106 /* already included */
107 logMessage(printf("already included: \"%s\"\n",
108 striAsUnquotedCStri(absolutePath)););
109 includeResult = INCLUDE_ALREADY;
110 } else if (openInfile(includeFileName, in_file.write_library_names,
111 in_file.write_line_numbers, err_info)) {
112 /* add to list of include files */
113 hshIncl(includeFileHash, (genericType) absolutePath,
114 (genericType) 1, strHashCode(absolutePath),
115 &strCmpGeneric, &strCreateGeneric,
116 &genericCreate, &genericCpy);
117 includeResult = INCLUDE_SUCCESS;
118 } /* if */
119 FREE_STRI(absolutePath, absolutePath->size);
120 } /* if */
121 logFunction(printf("openIncludeFile --> %d (err_info=%d)\n",
122 includeResult, *err_info););
123 return includeResult;
124 } /* openIncludeFile */
125
126
127
128 /**
129 * Search for an include library and open it, if it was found.
130 * A library with an absolute path is opened directly.
131 * For a library with a relative path the directories of the
132 * include library search path are checked for the library.
133 * The directories of the search path are checked one after
134 * another for the requested include library file. As soon as
135 * the include library is found the search is stopped and the
136 * include library is opened.
137 */
findIncludeFile(const rtlHashType includeFileHash,const_striType includeFileName,errInfoType * err_info)138 includeResultType findIncludeFile (const rtlHashType includeFileHash,
139 const_striType includeFileName, errInfoType *err_info)
140
141 {
142 memSizeType lib_path_size;
143 memSizeType position;
144 striType curr_path;
145 memSizeType length;
146 striType stri;
147 includeResultType includeResult = INCLUDE_FAILED;
148
149 /* findIncludeFile */
150 logFunction(printf("findIncludeFile(" FMT_U_MEM ", \"%s\", %d)\n",
151 (memSizeType) includeFileHash,
152 striAsUnquotedCStri(includeFileName),
153 *err_info););
154 if (*err_info == OKAY_NO_ERROR) {
155 if (includeFileName->size >= 1 && includeFileName->mem[0] == '/') {
156 includeResult = openIncludeFile(includeFileHash, includeFileName, err_info);
157 } else if (unlikely(lib_path == NULL)) {
158 /* This is a compile-time function and it is called at run-time. */
159 *err_info = ACTION_ERROR;
160 } else {
161 lib_path_size = arraySize(lib_path);
162 for (position = 0;
163 includeResult == INCLUDE_FAILED && position < lib_path_size;
164 position++) {
165 curr_path = lib_path->arr[position].value.striValue;
166 if (curr_path->size == 0) {
167 includeResult = openIncludeFile(includeFileHash, includeFileName, err_info);
168 } else {
169 if (curr_path->size > MAX_STRI_LEN - includeFileName->size) {
170 *err_info = MEMORY_ERROR;
171 } else {
172 length = curr_path->size + includeFileName->size;
173 if (!ALLOC_STRI_SIZE_OK(stri, length)) {
174 *err_info = MEMORY_ERROR;
175 } else {
176 stri->size = length;
177 memcpy(stri->mem, curr_path->mem,
178 (size_t) curr_path->size * sizeof(strElemType));
179 memcpy(&stri->mem[curr_path->size], includeFileName->mem,
180 (size_t) includeFileName->size * sizeof(strElemType));
181 includeResult = openIncludeFile(includeFileHash, stri, err_info);
182 FREE_STRI(stri, length);
183 } /* if */
184 } /* if */
185 } /* if */
186 } /* for */
187 if (includeResult == INCLUDE_FAILED && *err_info == OKAY_NO_ERROR) {
188 *err_info = FILE_ERROR;
189 } /* if */
190 } /* if */
191 } /* if */
192 logFunction(printf("findIncludeFile --> %d (err_info=%d)\n",
193 includeResult, *err_info););
194 return includeResult;
195 } /* findIncludeFile */
196
197
198
199 #ifdef OUT_OF_ORDER
print_lib_path(void)200 static void print_lib_path (void)
201
202 {
203 memSizeType length;
204 memSizeType position;
205 striType stri;
206
207 /* print_lib_path */
208 length = arraySize(lib_path);
209 for (position = 0; position < length; position++) {
210 stri = lib_path->arr[position].value.striValue;
211 prot_stri(stri);
212 prot_nl();
213 } /* for */
214 } /* print_lib_path */
215 #endif
216
217
218
219 /**
220 * Add the given directory path to the include library search path.
221 * The function makes sure that all paths in the include library
222 * search path end with '/'.
223 */
appendToLibPath(const_striType path,errInfoType * err_info)224 void appendToLibPath (const_striType path, errInfoType *err_info)
225
226 {
227 memSizeType stri_len;
228 striType stri;
229 rtlArrayType resized_lib_path;
230 memSizeType position;
231
232 /* appendToLibPath */
233 logFunction(printf("appendToLibPath(\"%s\")\n",
234 striAsUnquotedCStri(path)););
235 stri_len = path->size;
236 if (stri_len >= 1 && path->mem[stri_len - 1] != '/') {
237 stri_len++;
238 } /* if */
239 if (!ALLOC_STRI_CHECK_SIZE(stri, stri_len)) {
240 *err_info = MEMORY_ERROR;
241 } else {
242 resized_lib_path = REALLOC_RTL_ARRAY(lib_path,
243 (memSizeType) lib_path->max_position,
244 (memSizeType) (lib_path->max_position + 1));
245 if (resized_lib_path == NULL) {
246 FREE_STRI(stri, stri_len);
247 *err_info = MEMORY_ERROR;
248 } else {
249 lib_path = resized_lib_path;
250 COUNT3_RTL_ARRAY((memSizeType) lib_path->max_position,
251 (memSizeType) (lib_path->max_position + 1));
252 stri->size = stri_len;
253 for (position = 0; position < path->size; position++) {
254 if (path->mem[position] == '\\') {
255 stri->mem[position] = '/';
256 } else {
257 stri->mem[position] = path->mem[position];
258 } /* if */
259 } /* for */
260 if (stri_len != path->size) {
261 stri->mem[stri_len - 1] = '/';
262 } /* if */
263 lib_path->arr[lib_path->max_position].value.striValue = stri;
264 lib_path->max_position++;
265 } /* if */
266 } /* if */
267 logFunction(printf("appendToLibPath --> (err_info=%d)\n", *err_info););
268 } /* appendToLibPath */
269
270
271
272 /**
273 * Initialize the include library search path.
274 * The initial search path consists of the following directories:
275 * 1. The directory of the program source file.
276 * 2. Directories from the commandline option -l.
277 * 3. The directory containing the predefined Seed7 include libraries.
278 * 4. The directory specified with the SEED7_LIBRARY environment variable.
279 */
initLibPath(const_striType sourceFileName,const const_rtlArrayType seed7_libraries,errInfoType * err_info)280 void initLibPath (const_striType sourceFileName,
281 const const_rtlArrayType seed7_libraries, errInfoType *err_info)
282
283 {
284 striType path;
285 memSizeType position;
286 memSizeType dir_path_size;
287 static const os_charType seed7_library[] =
288 {'S', 'E', 'E', 'D', '7', '_', 'L', 'I', 'B', 'R', 'A', 'R', 'Y', 0};
289 os_striType library_environment_variable;
290 intType idx;
291
292 /* initLibPath */
293 logFunction(printf("initLibPath\n"););
294 if (!ALLOC_RTL_ARRAY(lib_path, 0)) {
295 *err_info = MEMORY_ERROR;
296 } else {
297 lib_path->min_position = 1;
298 lib_path->max_position = 0;
299
300 /* Add directory of the source file to the lib_path. */
301 dir_path_size = 0;
302 for (position = 0; position < sourceFileName->size; position++) {
303 if (sourceFileName->mem[position] == '/') {
304 dir_path_size = position + 1;
305 } /* if */
306 } /* for */
307 if (!ALLOC_STRI_SIZE_OK(path, dir_path_size)) {
308 *err_info = MEMORY_ERROR;
309 } else {
310 path->size = dir_path_size;
311 memcpy(path->mem, sourceFileName->mem, dir_path_size * sizeof(strElemType));
312 appendToLibPath(path, err_info);
313 FREE_STRI(path, path->size);
314 } /* if */
315
316 /* Add the libraries from the commandline to the lib_path */
317 if (seed7_libraries != NULL) {
318 for (idx = 0;
319 idx <= seed7_libraries->max_position - seed7_libraries->min_position;
320 idx++) {
321 appendToLibPath(seed7_libraries->arr[idx].value.striValue, err_info);
322 } /* for */
323 } /* if */
324
325 /* Add the hardcoded library of the interpreter to the lib_path. */
326 path = cstri8_or_cstri_to_stri(SEED7_LIBRARY);
327 if (path == NULL) {
328 *err_info = MEMORY_ERROR;
329 } else {
330 appendToLibPath(path, err_info);
331 FREE_STRI(path, path->size);
332 } /* if */
333
334 /* Add the SEED7_LIBRARY environment variable to the lib_path */
335 library_environment_variable = os_getenv(seed7_library);
336 if (library_environment_variable != NULL) {
337 path = cp_from_os_path(library_environment_variable, err_info);
338 os_getenv_string_free(library_environment_variable);
339 if (path != NULL) {
340 appendToLibPath(path, err_info);
341 FREE_STRI(path, path->size);
342 } /* if */
343 } /* if */
344
345 /* print_lib_path(); */
346 } /* if */
347 logFunction(printf("initLibPath -->\n"););
348 } /* initLibPath */
349
350
351
freeLibPath(void)352 void freeLibPath (void)
353
354 {
355 memSizeType length;
356 memSizeType position;
357 striType stri;
358
359 /* freeLibPath */
360 logFunction(printf("freeLibPath\n"););
361 length = arraySize(lib_path);
362 for (position = 0; position < length; position++) {
363 stri = lib_path->arr[position].value.striValue;
364 FREE_STRI(stri, stri->size);
365 } /* for */
366 FREE_RTL_ARRAY(lib_path, length);
367 lib_path = NULL;
368 logFunction(printf("freeLibPath -->\n"););
369 } /* freeLibPath */
370