load.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /* Copyright (C) 1995,1996,1998,1999,2000,2001 Free Software Foundation, Inc.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. * Boston, MA 02110-1301 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice. */
  41. #include <string.h>
  42. #include "libguile/_scm.h"
  43. #include "libguile/libpath.h"
  44. #include "libguile/fports.h"
  45. #include "libguile/read.h"
  46. #include "libguile/eval.h"
  47. #include "libguile/throw.h"
  48. #include "libguile/alist.h"
  49. #include "libguile/dynwind.h"
  50. #include "libguile/root.h"
  51. #include "libguile/strings.h"
  52. #include "libguile/modules.h"
  53. #include "libguile/validate.h"
  54. #include "libguile/load.h"
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57. #ifdef HAVE_UNISTD_H
  58. #include <unistd.h>
  59. #endif /* HAVE_UNISTD_H */
  60. #ifndef R_OK
  61. #define R_OK 4
  62. #endif
  63. /* Loading a file, given an absolute filename. */
  64. /* Hook to run when we load a file, perhaps to announce the fact somewhere.
  65. Applied to the full name of the file. */
  66. static SCM *scm_loc_load_hook;
  67. static void
  68. swap_port (void *data)
  69. {
  70. SCM *save_port = data, tmp = scm_cur_loadp;
  71. scm_cur_loadp = *save_port;
  72. *save_port = tmp;
  73. }
  74. static SCM
  75. load (void *data)
  76. {
  77. SCM port = SCM_PACK (data);
  78. while (1)
  79. {
  80. SCM form = scm_read (port);
  81. if (SCM_EOF_OBJECT_P (form))
  82. break;
  83. scm_primitive_eval_x (form);
  84. }
  85. return SCM_UNSPECIFIED;
  86. }
  87. SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0,
  88. (SCM filename),
  89. "Load the file named @var{filename} and evaluate its contents in\n"
  90. "the top-level environment. The load paths are not searched;\n"
  91. "@var{filename} must either be a full pathname or be a pathname\n"
  92. "relative to the current directory. If the variable\n"
  93. "@code{%load-hook} is defined, it should be bound to a procedure\n"
  94. "that will be called before any code is loaded. See the\n"
  95. "documentation for @code{%load-hook} later in this section.")
  96. #define FUNC_NAME s_scm_primitive_load
  97. {
  98. SCM hook = *scm_loc_load_hook;
  99. SCM_VALIDATE_STRING (1, filename);
  100. if (!SCM_FALSEP (hook) && !SCM_EQ_P (scm_procedure_p (hook), SCM_BOOL_T))
  101. SCM_MISC_ERROR ("value of %load-hook is neither a procedure nor #f",
  102. SCM_EOL);
  103. if (! SCM_FALSEP (hook))
  104. scm_call_1 (hook, filename);
  105. { /* scope */
  106. SCM port, save_port;
  107. port = scm_open_file (filename, scm_mem2string ("r", sizeof (char)));
  108. save_port = port;
  109. scm_internal_dynamic_wind (swap_port,
  110. load,
  111. swap_port,
  112. (void *) SCM_UNPACK (port),
  113. &save_port);
  114. scm_close_port (port);
  115. }
  116. return SCM_UNSPECIFIED;
  117. }
  118. #undef FUNC_NAME
  119. SCM
  120. scm_c_primitive_load (const char *filename)
  121. {
  122. return scm_primitive_load (scm_makfrom0str (filename));
  123. }
  124. /* Builtin path to scheme library files. */
  125. #ifdef SCM_PKGDATA_DIR
  126. SCM_DEFINE (scm_sys_package_data_dir, "%package-data-dir", 0, 0, 0,
  127. (),
  128. "Return the name of the directory where Scheme packages, modules and\n"
  129. "libraries are kept. On most Unix systems, this will be\n"
  130. "@samp{/usr/local/share/guile}.")
  131. #define FUNC_NAME s_scm_sys_package_data_dir
  132. {
  133. return scm_makfrom0str (SCM_PKGDATA_DIR);
  134. }
  135. #undef FUNC_NAME
  136. #endif /* SCM_PKGDATA_DIR */
  137. #ifdef SCM_LIBRARY_DIR
  138. SCM_DEFINE (scm_sys_library_dir, "%library-dir", 0,0,0,
  139. (),
  140. "Return the directory where the Guile Scheme library files are installed.\n"
  141. "E.g., may return \"/usr/share/guile/1.3.5\".")
  142. #define FUNC_NAME s_scm_sys_library_dir
  143. {
  144. return scm_makfrom0str(SCM_LIBRARY_DIR);
  145. }
  146. #undef FUNC_NAME
  147. #endif /* SCM_LIBRARY_DIR */
  148. #ifdef SCM_SITE_DIR
  149. SCM_DEFINE (scm_sys_site_dir, "%site-dir", 0,0,0,
  150. (),
  151. "Return the directory where the Guile site files are installed.\n"
  152. "E.g., may return \"/usr/share/guile/site\".")
  153. #define FUNC_NAME s_scm_sys_site_dir
  154. {
  155. return scm_makfrom0str(SCM_SITE_DIR);
  156. }
  157. #undef FUNC_NAME
  158. #endif /* SCM_SITE_DIR */
  159. /* Initializing the load path, and searching it. */
  160. /* List of names of directories we search for files to load. */
  161. static SCM *scm_loc_load_path;
  162. /* List of extensions we try adding to the filenames. */
  163. static SCM *scm_loc_load_extensions;
  164. /* Parse the null-terminated string PATH as if it were a standard path
  165. environment variable (i.e. a colon-separated list of strings), and
  166. prepend the elements to TAIL. */
  167. SCM
  168. scm_internal_parse_path (char *path, SCM tail)
  169. {
  170. if (path && path[0] != '\0')
  171. {
  172. char *scan, *elt_end;
  173. /* Scan backwards from the end of the string, to help
  174. construct the list in the right order. */
  175. scan = elt_end = path + strlen (path);
  176. do {
  177. /* Scan back to the beginning of the current element. */
  178. do scan--;
  179. while (scan >= path && *scan != ':');
  180. tail = scm_cons (scm_mem2string (scan + 1, elt_end - (scan + 1)),
  181. tail);
  182. elt_end = scan;
  183. } while (scan >= path);
  184. }
  185. return tail;
  186. }
  187. SCM_DEFINE (scm_parse_path, "parse-path", 1, 1, 0,
  188. (SCM path, SCM tail),
  189. "Parse @var{path}, which is expected to be a colon-separated\n"
  190. "string, into a list and return the resulting list with\n"
  191. "@var{tail} appended. If @var{path} is @code{#f}, @var{tail}\n"
  192. "is returned.")
  193. #define FUNC_NAME s_scm_parse_path
  194. {
  195. SCM_ASSERT (SCM_FALSEP (path) || (SCM_STRINGP (path)),
  196. path,
  197. SCM_ARG1, FUNC_NAME);
  198. if (SCM_UNBNDP (tail))
  199. tail = SCM_EOL;
  200. return (SCM_FALSEP (path)
  201. ? tail
  202. : scm_internal_parse_path (SCM_STRING_CHARS (path), tail));
  203. }
  204. #undef FUNC_NAME
  205. /* Initialize the global variable %load-path, given the value of the
  206. SCM_SITE_DIR and SCM_LIBRARY_DIR preprocessor symbols and the
  207. GUILE_LOAD_PATH environment variable. */
  208. void
  209. scm_init_load_path ()
  210. {
  211. SCM path = SCM_EOL;
  212. #ifdef SCM_LIBRARY_DIR
  213. path = scm_list_3 (scm_makfrom0str (SCM_SITE_DIR),
  214. scm_makfrom0str (SCM_LIBRARY_DIR),
  215. scm_makfrom0str (SCM_PKGDATA_DIR));
  216. #endif /* SCM_LIBRARY_DIR */
  217. path = scm_internal_parse_path (getenv ("GUILE_LOAD_PATH"), path);
  218. *scm_loc_load_path = path;
  219. }
  220. SCM scm_listofnullstr;
  221. /* Search PATH for a directory containing a file named FILENAME.
  222. The file must be readable, and not a directory.
  223. If we find one, return its full filename; otherwise, return #f.
  224. If FILENAME is absolute, return it unchanged.
  225. If given, EXTENSIONS is a list of strings; for each directory
  226. in PATH, we search for FILENAME concatenated with each EXTENSION. */
  227. SCM_DEFINE (scm_search_path, "search-path", 2, 1, 0,
  228. (SCM path, SCM filename, SCM extensions),
  229. "Search @var{path} for a directory containing a file named\n"
  230. "@var{filename}. The file must be readable, and not a directory.\n"
  231. "If we find one, return its full filename; otherwise, return\n"
  232. "@code{#f}. If @var{filename} is absolute, return it unchanged.\n"
  233. "If given, @var{extensions} is a list of strings; for each\n"
  234. "directory in @var{path}, we search for @var{filename}\n"
  235. "concatenated with each @var{extension}.")
  236. #define FUNC_NAME s_scm_search_path
  237. {
  238. char *filename_chars;
  239. int filename_len;
  240. size_t max_path_len; /* maximum length of any PATH element */
  241. size_t max_ext_len; /* maximum length of any EXTENSIONS element */
  242. SCM_VALIDATE_LIST (1,path);
  243. SCM_VALIDATE_STRING (2, filename);
  244. if (SCM_UNBNDP (extensions))
  245. extensions = SCM_EOL;
  246. else
  247. SCM_VALIDATE_LIST (3,extensions);
  248. filename_chars = SCM_STRING_CHARS (filename);
  249. filename_len = SCM_STRING_LENGTH (filename);
  250. /* If FILENAME is absolute, return it unchanged. */
  251. if (filename_len >= 1 && filename_chars[0] == '/')
  252. return filename;
  253. /* Find the length of the longest element of path. */
  254. {
  255. SCM walk;
  256. max_path_len = 0;
  257. for (walk = path; !SCM_NULLP (walk); walk = SCM_CDR (walk))
  258. {
  259. SCM elt = SCM_CAR (walk);
  260. SCM_ASSERT_TYPE (SCM_STRINGP (elt), path, 1, FUNC_NAME,
  261. "list of strings");
  262. if (SCM_STRING_LENGTH (elt) > max_path_len)
  263. max_path_len = SCM_STRING_LENGTH (elt);
  264. }
  265. }
  266. /* If FILENAME has an extension, don't try to add EXTENSIONS to it. */
  267. {
  268. char *endp;
  269. for (endp = filename_chars + filename_len - 1;
  270. endp >= filename_chars;
  271. endp--)
  272. {
  273. if (*endp == '.')
  274. {
  275. /* This filename already has an extension, so cancel the
  276. list of extensions. */
  277. extensions = SCM_EOL;
  278. break;
  279. }
  280. else if (*endp == '/')
  281. /* This filename has no extension, so keep the current list
  282. of extensions. */
  283. break;
  284. }
  285. }
  286. /* Find the length of the longest element of the load extensions
  287. list. */
  288. { /* scope */
  289. SCM walk;
  290. max_ext_len = 0;
  291. for (walk = extensions; !SCM_NULLP (walk); walk = SCM_CDR (walk))
  292. {
  293. SCM elt = SCM_CAR (walk);
  294. SCM_ASSERT_TYPE (SCM_STRINGP (elt), elt, 3, FUNC_NAME,
  295. "list of strings");
  296. if (SCM_STRING_LENGTH (elt) > max_ext_len)
  297. max_ext_len = SCM_STRING_LENGTH (elt);
  298. }
  299. }
  300. SCM_DEFER_INTS;
  301. { /* scope */
  302. SCM result = SCM_BOOL_F;
  303. size_t buf_size = max_path_len + 1 + filename_len + max_ext_len + 1;
  304. char *buf = SCM_MUST_MALLOC (buf_size);
  305. /* This simplifies the loop below a bit. */
  306. if (SCM_NULLP (extensions))
  307. extensions = scm_listofnullstr;
  308. /* Try every path element. At this point, we know the path is a
  309. proper list of strings. */
  310. for (; !SCM_NULLP (path); path = SCM_CDR (path))
  311. {
  312. size_t len;
  313. SCM dir = SCM_CAR (path);
  314. SCM exts;
  315. /* Concatenate the path name and the filename. */
  316. len = SCM_STRING_LENGTH (dir);
  317. memcpy (buf, SCM_STRING_CHARS (dir), len);
  318. if (len >= 1 && buf[len - 1] != '/')
  319. buf[len++] = '/';
  320. memcpy (buf + len, filename_chars, filename_len);
  321. len += filename_len;
  322. /* Try every extension. At this point, we know the extension
  323. list is a proper, nonempty list of strings. */
  324. for (exts = extensions; !SCM_NULLP (exts); exts = SCM_CDR (exts))
  325. {
  326. SCM ext = SCM_CAR (exts);
  327. size_t ext_len = SCM_STRING_LENGTH (ext);
  328. struct stat mode;
  329. /* Concatenate the extension. */
  330. memcpy (buf + len, SCM_STRING_CHARS (ext), ext_len);
  331. buf[len + ext_len] = '\0';
  332. /* If the file exists at all, we should return it. If the
  333. file is inaccessible, then that's an error. */
  334. if (stat (buf, &mode) == 0
  335. && ! (mode.st_mode & S_IFDIR))
  336. {
  337. result = scm_mem2string (buf, len + ext_len);
  338. goto end;
  339. }
  340. }
  341. }
  342. end:
  343. scm_must_free (buf);
  344. scm_done_free (buf_size);
  345. SCM_ALLOW_INTS;
  346. return result;
  347. }
  348. }
  349. #undef FUNC_NAME
  350. /* Search %load-path for a directory containing a file named FILENAME.
  351. The file must be readable, and not a directory.
  352. If we find one, return its full filename; otherwise, return #f.
  353. If FILENAME is absolute, return it unchanged. */
  354. SCM_DEFINE (scm_sys_search_load_path, "%search-load-path", 1, 0, 0,
  355. (SCM filename),
  356. "Search @var{%load-path} for the file named @var{filename},\n"
  357. "which must be readable by the current user. If @var{filename}\n"
  358. "is found in the list of paths to search or is an absolute\n"
  359. "pathname, return its full pathname. Otherwise, return\n"
  360. "@code{#f}. Filenames may have any of the optional extensions\n"
  361. "in the @code{%load-extensions} list; @code{%search-load-path}\n"
  362. "will try each extension automatically.")
  363. #define FUNC_NAME s_scm_sys_search_load_path
  364. {
  365. SCM path = *scm_loc_load_path;
  366. SCM exts = *scm_loc_load_extensions;
  367. SCM_VALIDATE_STRING (1, filename);
  368. if (scm_ilength (path) < 0)
  369. SCM_MISC_ERROR ("%load-path is not a proper list", SCM_EOL);
  370. if (scm_ilength (exts) < 0)
  371. SCM_MISC_ERROR ("%load-extension list is not a proper list", SCM_EOL);
  372. return scm_search_path (path, filename, exts);
  373. }
  374. #undef FUNC_NAME
  375. SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 0, 0,
  376. (SCM filename),
  377. "Search @var{%load-path} for the file named @var{filename} and\n"
  378. "load it into the top-level environment. If @var{filename} is a\n"
  379. "relative pathname and is not found in the list of search paths,\n"
  380. "an error is signalled.")
  381. #define FUNC_NAME s_scm_primitive_load_path
  382. {
  383. SCM full_filename;
  384. SCM_VALIDATE_STRING (1, filename);
  385. full_filename = scm_sys_search_load_path (filename);
  386. if (SCM_FALSEP (full_filename))
  387. {
  388. int absolute = (SCM_STRING_LENGTH (filename) >= 1
  389. && SCM_STRING_CHARS (filename)[0] == '/');
  390. SCM_MISC_ERROR ((absolute
  391. ? "Unable to load file ~S"
  392. : "Unable to find file ~S in load path"),
  393. scm_list_1 (filename));
  394. }
  395. return scm_primitive_load (full_filename);
  396. }
  397. #undef FUNC_NAME
  398. SCM
  399. scm_c_primitive_load_path (const char *filename)
  400. {
  401. return scm_primitive_load_path (scm_makfrom0str (filename));
  402. }
  403. #if SCM_DEBUG_DEPRECATED == 0
  404. /* Eval now copies source properties, so this function is no longer required.
  405. */
  406. SCM_SYMBOL (scm_end_of_file_key, "end-of-file");
  407. SCM_DEFINE (scm_read_and_eval_x, "read-and-eval!", 0, 1, 0,
  408. (SCM port),
  409. "Read a form from @var{port} (standard input by default), and evaluate it\n"
  410. "(memoizing it in the process) in the top-level environment. If no data\n"
  411. "is left to be read from @var{port}, an @code{end-of-file} error is\n"
  412. "signalled.")
  413. #define FUNC_NAME s_scm_read_and_eval_x
  414. {
  415. SCM form = scm_read (port);
  416. if (SCM_EOF_OBJECT_P (form))
  417. scm_ithrow (scm_end_of_file_key, SCM_EOL, 1);
  418. return scm_eval_x (form, scm_current_module ());
  419. }
  420. #undef FUNC_NAME
  421. #endif
  422. /* Information about the build environment. */
  423. /* Initialize the scheme variable %guile-build-info, based on data
  424. provided by the Makefile, via libpath.h. */
  425. static void
  426. init_build_info ()
  427. {
  428. static struct { char *name; char *value; } info[] = SCM_BUILD_INFO;
  429. SCM *loc = SCM_VARIABLE_LOC (scm_c_define ("%guile-build-info", SCM_EOL));
  430. unsigned long i;
  431. for (i = 0; i < (sizeof (info) / sizeof (info[0])); i++)
  432. *loc = scm_acons (scm_str2symbol (info[i].name),
  433. scm_makfrom0str (info[i].value),
  434. *loc);
  435. }
  436. void
  437. scm_init_load ()
  438. {
  439. scm_listofnullstr = scm_permanent_object (scm_list_1 (scm_nullstr));
  440. scm_loc_load_path = SCM_VARIABLE_LOC (scm_c_define ("%load-path", SCM_EOL));
  441. scm_loc_load_extensions
  442. = SCM_VARIABLE_LOC (scm_c_define ("%load-extensions",
  443. scm_list_2 (scm_makfrom0str (".scm"),
  444. scm_nullstr)));
  445. scm_loc_load_hook = SCM_VARIABLE_LOC (scm_c_define ("%load-hook", SCM_BOOL_F));
  446. init_build_info ();
  447. #include "libguile/load.x"
  448. }
  449. /*
  450. Local Variables:
  451. c-file-style: "gnu"
  452. End:
  453. */