load.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2004, 2006 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public
  5. * License as published by the Free Software Foundation; either
  6. * version 2.1 of the License, or (at your option) any later version.
  7. *
  8. * This library 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 GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. # include <config.h>
  19. #endif
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include "libguile/_scm.h"
  23. #include "libguile/libpath.h"
  24. #include "libguile/fports.h"
  25. #include "libguile/read.h"
  26. #include "libguile/eval.h"
  27. #include "libguile/throw.h"
  28. #include "libguile/alist.h"
  29. #include "libguile/dynwind.h"
  30. #include "libguile/root.h"
  31. #include "libguile/strings.h"
  32. #include "libguile/modules.h"
  33. #include "libguile/lang.h"
  34. #include "libguile/chars.h"
  35. #include "libguile/srfi-13.h"
  36. #include "libguile/validate.h"
  37. #include "libguile/load.h"
  38. #include "libguile/fluids.h"
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif /* HAVE_UNISTD_H */
  44. #ifndef R_OK
  45. #define R_OK 4
  46. #endif
  47. /* Loading a file, given an absolute filename. */
  48. /* Hook to run when we load a file, perhaps to announce the fact somewhere.
  49. Applied to the full name of the file. */
  50. static SCM *scm_loc_load_hook;
  51. /* The current reader (a fluid). */
  52. static SCM the_reader = SCM_BOOL_F;
  53. static size_t the_reader_fluid_num = 0;
  54. SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0,
  55. (SCM filename),
  56. "Load the file named @var{filename} and evaluate its contents in\n"
  57. "the top-level environment. The load paths are not searched;\n"
  58. "@var{filename} must either be a full pathname or be a pathname\n"
  59. "relative to the current directory. If the variable\n"
  60. "@code{%load-hook} is defined, it should be bound to a procedure\n"
  61. "that will be called before any code is loaded. See the\n"
  62. "documentation for @code{%load-hook} later in this section.")
  63. #define FUNC_NAME s_scm_primitive_load
  64. {
  65. SCM hook = *scm_loc_load_hook;
  66. SCM_VALIDATE_STRING (1, filename);
  67. if (scm_is_true (hook) && scm_is_false (scm_procedure_p (hook)))
  68. SCM_MISC_ERROR ("value of %load-hook is neither a procedure nor #f",
  69. SCM_EOL);
  70. if (!scm_is_false (hook))
  71. scm_call_1 (hook, filename);
  72. { /* scope */
  73. SCM port = scm_open_file (filename, scm_from_locale_string ("r"));
  74. scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
  75. scm_i_dynwind_current_load_port (port);
  76. while (1)
  77. {
  78. SCM reader, form;
  79. /* Lookup and use the current reader to read the next
  80. expression. */
  81. reader = SCM_FAST_FLUID_REF (the_reader_fluid_num);
  82. if (reader == SCM_BOOL_F)
  83. form = scm_read (port);
  84. else
  85. form = scm_call_1 (reader, port);
  86. if (SCM_EOF_OBJECT_P (form))
  87. break;
  88. scm_primitive_eval_x (form);
  89. }
  90. scm_dynwind_end ();
  91. scm_close_port (port);
  92. }
  93. return SCM_UNSPECIFIED;
  94. }
  95. #undef FUNC_NAME
  96. SCM
  97. scm_c_primitive_load (const char *filename)
  98. {
  99. return scm_primitive_load (scm_from_locale_string (filename));
  100. }
  101. /* Builtin path to scheme library files. */
  102. #ifdef SCM_PKGDATA_DIR
  103. SCM_DEFINE (scm_sys_package_data_dir, "%package-data-dir", 0, 0, 0,
  104. (),
  105. "Return the name of the directory where Scheme packages, modules and\n"
  106. "libraries are kept. On most Unix systems, this will be\n"
  107. "@samp{/usr/local/share/guile}.")
  108. #define FUNC_NAME s_scm_sys_package_data_dir
  109. {
  110. return scm_from_locale_string (SCM_PKGDATA_DIR);
  111. }
  112. #undef FUNC_NAME
  113. #endif /* SCM_PKGDATA_DIR */
  114. #ifdef SCM_LIBRARY_DIR
  115. SCM_DEFINE (scm_sys_library_dir, "%library-dir", 0,0,0,
  116. (),
  117. "Return the directory where the Guile Scheme library files are installed.\n"
  118. "E.g., may return \"/usr/share/guile/1.3.5\".")
  119. #define FUNC_NAME s_scm_sys_library_dir
  120. {
  121. return scm_from_locale_string (SCM_LIBRARY_DIR);
  122. }
  123. #undef FUNC_NAME
  124. #endif /* SCM_LIBRARY_DIR */
  125. #ifdef SCM_SITE_DIR
  126. SCM_DEFINE (scm_sys_site_dir, "%site-dir", 0,0,0,
  127. (),
  128. "Return the directory where the Guile site files are installed.\n"
  129. "E.g., may return \"/usr/share/guile/site\".")
  130. #define FUNC_NAME s_scm_sys_site_dir
  131. {
  132. return scm_from_locale_string (SCM_SITE_DIR);
  133. }
  134. #undef FUNC_NAME
  135. #endif /* SCM_SITE_DIR */
  136. /* Initializing the load path, and searching it. */
  137. /* List of names of directories we search for files to load. */
  138. static SCM *scm_loc_load_path;
  139. /* List of extensions we try adding to the filenames. */
  140. static SCM *scm_loc_load_extensions;
  141. SCM_DEFINE (scm_parse_path, "parse-path", 1, 1, 0,
  142. (SCM path, SCM tail),
  143. "Parse @var{path}, which is expected to be a colon-separated\n"
  144. "string, into a list and return the resulting list with\n"
  145. "@var{tail} appended. If @var{path} is @code{#f}, @var{tail}\n"
  146. "is returned.")
  147. #define FUNC_NAME s_scm_parse_path
  148. {
  149. #ifdef __MINGW32__
  150. SCM sep = SCM_MAKE_CHAR (';');
  151. #else
  152. SCM sep = SCM_MAKE_CHAR (':');
  153. #endif
  154. if (SCM_UNBNDP (tail))
  155. tail = SCM_EOL;
  156. return (scm_is_false (path)
  157. ? tail
  158. : scm_append_x (scm_list_2 (scm_string_split (path, sep), tail)));
  159. }
  160. #undef FUNC_NAME
  161. /* Initialize the global variable %load-path, given the value of the
  162. SCM_SITE_DIR and SCM_LIBRARY_DIR preprocessor symbols and the
  163. GUILE_LOAD_PATH environment variable. */
  164. void
  165. scm_init_load_path ()
  166. {
  167. char *env;
  168. SCM path = SCM_EOL;
  169. #ifdef SCM_LIBRARY_DIR
  170. path = scm_list_3 (scm_from_locale_string (SCM_SITE_DIR),
  171. scm_from_locale_string (SCM_LIBRARY_DIR),
  172. scm_from_locale_string (SCM_PKGDATA_DIR));
  173. #endif /* SCM_LIBRARY_DIR */
  174. env = getenv ("GUILE_LOAD_PATH");
  175. if (env)
  176. path = scm_parse_path (scm_from_locale_string (env), path);
  177. *scm_loc_load_path = path;
  178. }
  179. SCM scm_listofnullstr;
  180. /* Utility functions for assembling C strings in a buffer.
  181. */
  182. struct stringbuf {
  183. char *buf, *ptr;
  184. size_t buf_len;
  185. };
  186. static void
  187. stringbuf_free (void *data)
  188. {
  189. struct stringbuf *buf = (struct stringbuf *)data;
  190. free (buf->buf);
  191. }
  192. static void
  193. stringbuf_grow (struct stringbuf *buf)
  194. {
  195. size_t ptroff = buf->ptr - buf->buf;
  196. buf->buf_len *= 2;
  197. buf->buf = scm_realloc (buf->buf, buf->buf_len);
  198. buf->ptr = buf->buf + ptroff;
  199. }
  200. static void
  201. stringbuf_cat_locale_string (struct stringbuf *buf, SCM str)
  202. {
  203. size_t max_len = buf->buf_len - (buf->ptr - buf->buf) - 1;
  204. size_t len = scm_to_locale_stringbuf (str, buf->ptr, max_len);
  205. if (len > max_len)
  206. {
  207. /* buffer is too small, double its size and try again.
  208. */
  209. stringbuf_grow (buf);
  210. stringbuf_cat_locale_string (buf, str);
  211. }
  212. else
  213. {
  214. /* string fits, terminate it and check for embedded '\0'.
  215. */
  216. buf->ptr[len] = '\0';
  217. if (strlen (buf->ptr) != len)
  218. scm_misc_error (NULL,
  219. "string contains #\\nul character: ~S",
  220. scm_list_1 (str));
  221. buf->ptr += len;
  222. }
  223. }
  224. static void
  225. stringbuf_cat (struct stringbuf *buf, char *str)
  226. {
  227. size_t max_len = buf->buf_len - (buf->ptr - buf->buf) - 1;
  228. size_t len = strlen (str);
  229. if (len > max_len)
  230. {
  231. /* buffer is too small, double its size and try again.
  232. */
  233. stringbuf_grow (buf);
  234. stringbuf_cat (buf, str);
  235. }
  236. else
  237. {
  238. /* string fits, copy it into buffer.
  239. */
  240. strcpy (buf->ptr, str);
  241. buf->ptr += len;
  242. }
  243. }
  244. /* Search PATH for a directory containing a file named FILENAME.
  245. The file must be readable, and not a directory.
  246. If we find one, return its full filename; otherwise, return #f.
  247. If FILENAME is absolute, return it unchanged.
  248. If given, EXTENSIONS is a list of strings; for each directory
  249. in PATH, we search for FILENAME concatenated with each EXTENSION. */
  250. SCM_DEFINE (scm_search_path, "search-path", 2, 1, 0,
  251. (SCM path, SCM filename, SCM extensions),
  252. "Search @var{path} for a directory containing a file named\n"
  253. "@var{filename}. The file must be readable, and not a directory.\n"
  254. "If we find one, return its full filename; otherwise, return\n"
  255. "@code{#f}. If @var{filename} is absolute, return it unchanged.\n"
  256. "If given, @var{extensions} is a list of strings; for each\n"
  257. "directory in @var{path}, we search for @var{filename}\n"
  258. "concatenated with each @var{extension}.")
  259. #define FUNC_NAME s_scm_search_path
  260. {
  261. struct stringbuf buf;
  262. char *filename_chars;
  263. size_t filename_len;
  264. SCM result = SCM_BOOL_F;
  265. if (SCM_UNBNDP (extensions))
  266. extensions = SCM_EOL;
  267. scm_dynwind_begin (0);
  268. filename_chars = scm_to_locale_string (filename);
  269. filename_len = strlen (filename_chars);
  270. scm_dynwind_free (filename_chars);
  271. /* If FILENAME is absolute, return it unchanged. */
  272. #ifdef __MINGW32__
  273. if (((filename_len >= 1) &&
  274. (filename_chars[0] == '/' || filename_chars[0] == '\\')) ||
  275. ((filename_len >= 3) && filename_chars[1] == ':' &&
  276. ((filename_chars[0] >= 'a' && filename_chars[0] <= 'z') ||
  277. (filename_chars[0] >= 'A' && filename_chars[0] <= 'Z')) &&
  278. (filename_chars[2] == '/' || filename_chars[2] == '\\')))
  279. #else
  280. if (filename_len >= 1 && filename_chars[0] == '/')
  281. #endif
  282. {
  283. scm_dynwind_end ();
  284. return filename;
  285. }
  286. /* If FILENAME has an extension, don't try to add EXTENSIONS to it. */
  287. {
  288. char *endp;
  289. for (endp = filename_chars + filename_len - 1;
  290. endp >= filename_chars;
  291. endp--)
  292. {
  293. if (*endp == '.')
  294. {
  295. /* This filename already has an extension, so cancel the
  296. list of extensions. */
  297. extensions = SCM_EOL;
  298. break;
  299. }
  300. #ifdef __MINGW32__
  301. else if (*endp == '/' || *endp == '\\')
  302. #else
  303. else if (*endp == '/')
  304. #endif
  305. /* This filename has no extension, so keep the current list
  306. of extensions. */
  307. break;
  308. }
  309. }
  310. /* This simplifies the loop below a bit.
  311. */
  312. if (scm_is_null (extensions))
  313. extensions = scm_listofnullstr;
  314. buf.buf_len = 512;
  315. buf.buf = scm_malloc (buf.buf_len);
  316. scm_dynwind_unwind_handler (stringbuf_free, &buf, SCM_F_WIND_EXPLICITLY);
  317. /* Try every path element.
  318. */
  319. for (; scm_is_pair (path); path = SCM_CDR (path))
  320. {
  321. SCM dir = SCM_CAR (path);
  322. SCM exts;
  323. size_t sans_ext_len;
  324. buf.ptr = buf.buf;
  325. stringbuf_cat_locale_string (&buf, dir);
  326. /* Concatenate the path name and the filename. */
  327. #ifdef __MINGW32__
  328. if ((buf.ptr > buf.buf) && (buf.ptr[-1] != '/') && (buf.ptr[-1] != '\\'))
  329. #else
  330. if ((buf.ptr > buf.buf) && (buf.ptr[-1] != '/'))
  331. #endif
  332. stringbuf_cat (&buf, "/");
  333. stringbuf_cat (&buf, filename_chars);
  334. sans_ext_len = buf.ptr - buf.buf;
  335. /* Try every extension. */
  336. for (exts = extensions; scm_is_pair (exts); exts = SCM_CDR (exts))
  337. {
  338. SCM ext = SCM_CAR (exts);
  339. struct stat mode;
  340. buf.ptr = buf.buf + sans_ext_len;
  341. stringbuf_cat_locale_string (&buf, ext);
  342. /* If the file exists at all, we should return it. If the
  343. file is inaccessible, then that's an error. */
  344. if (stat (buf.buf, &mode) == 0
  345. && ! (mode.st_mode & S_IFDIR))
  346. {
  347. result = scm_from_locale_string (buf.buf);
  348. goto end;
  349. }
  350. }
  351. if (!SCM_NULL_OR_NIL_P (exts))
  352. scm_wrong_type_arg_msg (NULL, 0, extensions, "proper list");
  353. }
  354. if (!SCM_NULL_OR_NIL_P (path))
  355. scm_wrong_type_arg_msg (NULL, 0, path, "proper list");
  356. end:
  357. scm_dynwind_end ();
  358. return result;
  359. }
  360. #undef FUNC_NAME
  361. /* Search %load-path for a directory containing a file named FILENAME.
  362. The file must be readable, and not a directory.
  363. If we find one, return its full filename; otherwise, return #f.
  364. If FILENAME is absolute, return it unchanged. */
  365. SCM_DEFINE (scm_sys_search_load_path, "%search-load-path", 1, 0, 0,
  366. (SCM filename),
  367. "Search @var{%load-path} for the file named @var{filename},\n"
  368. "which must be readable by the current user. If @var{filename}\n"
  369. "is found in the list of paths to search or is an absolute\n"
  370. "pathname, return its full pathname. Otherwise, return\n"
  371. "@code{#f}. Filenames may have any of the optional extensions\n"
  372. "in the @code{%load-extensions} list; @code{%search-load-path}\n"
  373. "will try each extension automatically.")
  374. #define FUNC_NAME s_scm_sys_search_load_path
  375. {
  376. SCM path = *scm_loc_load_path;
  377. SCM exts = *scm_loc_load_extensions;
  378. SCM_VALIDATE_STRING (1, filename);
  379. if (scm_ilength (path) < 0)
  380. SCM_MISC_ERROR ("%load-path is not a proper list", SCM_EOL);
  381. if (scm_ilength (exts) < 0)
  382. SCM_MISC_ERROR ("%load-extension list is not a proper list", SCM_EOL);
  383. return scm_search_path (path, filename, exts);
  384. }
  385. #undef FUNC_NAME
  386. SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 0, 0,
  387. (SCM filename),
  388. "Search @var{%load-path} for the file named @var{filename} and\n"
  389. "load it into the top-level environment. If @var{filename} is a\n"
  390. "relative pathname and is not found in the list of search paths,\n"
  391. "an error is signalled.")
  392. #define FUNC_NAME s_scm_primitive_load_path
  393. {
  394. SCM full_filename;
  395. full_filename = scm_sys_search_load_path (filename);
  396. if (scm_is_false (full_filename))
  397. SCM_MISC_ERROR ("Unable to find file ~S in load path",
  398. scm_list_1 (filename));
  399. return scm_primitive_load (full_filename);
  400. }
  401. #undef FUNC_NAME
  402. SCM
  403. scm_c_primitive_load_path (const char *filename)
  404. {
  405. return scm_primitive_load_path (scm_from_locale_string (filename));
  406. }
  407. /* Information about the build environment. */
  408. /* Initialize the scheme variable %guile-build-info, based on data
  409. provided by the Makefile, via libpath.h. */
  410. static void
  411. init_build_info ()
  412. {
  413. static struct { char *name; char *value; } info[] = SCM_BUILD_INFO;
  414. SCM *loc = SCM_VARIABLE_LOC (scm_c_define ("%guile-build-info", SCM_EOL));
  415. unsigned long i;
  416. for (i = 0; i < (sizeof (info) / sizeof (info[0])); i++)
  417. {
  418. SCM key = scm_from_locale_symbol (info[i].name);
  419. SCM val = scm_from_locale_string (info[i].value);
  420. *loc = scm_acons (key, val, *loc);
  421. }
  422. }
  423. void
  424. scm_init_load ()
  425. {
  426. scm_listofnullstr = scm_permanent_object (scm_list_1 (scm_nullstr));
  427. scm_loc_load_path = SCM_VARIABLE_LOC (scm_c_define ("%load-path", SCM_EOL));
  428. scm_loc_load_extensions
  429. = SCM_VARIABLE_LOC (scm_c_define ("%load-extensions",
  430. scm_list_2 (scm_from_locale_string (".scm"),
  431. scm_nullstr)));
  432. scm_loc_load_hook = SCM_VARIABLE_LOC (scm_c_define ("%load-hook", SCM_BOOL_F));
  433. the_reader = scm_make_fluid ();
  434. the_reader_fluid_num = SCM_FLUID_NUM (the_reader);
  435. SCM_FAST_FLUID_SET_X (the_reader_fluid_num, SCM_BOOL_F);
  436. scm_c_define("current-reader", the_reader);
  437. init_build_info ();
  438. #include "libguile/load.x"
  439. }
  440. /*
  441. Local Variables:
  442. c-file-style: "gnu"
  443. End:
  444. */