symbols.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. /* Copyright (C) 1995,1996,1997,1998, 2000, 2002 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., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 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 <stdio.h>
  42. #include "libguile/_scm.h"
  43. #include "libguile/chars.h"
  44. #include "libguile/eval.h"
  45. #include "libguile/variable.h"
  46. #include "libguile/alist.h"
  47. #include "libguile/root.h"
  48. #include "libguile/strings.h"
  49. #include "libguile/vectors.h"
  50. #include "libguile/weaks.h"
  51. #include "libguile/validate.h"
  52. #include "libguile/symbols.h"
  53. #ifdef HAVE_STRING_H
  54. #include <string.h>
  55. #endif
  56. /* NUM_HASH_BUCKETS is the number of symbol scm_hash table buckets.
  57. */
  58. #define NUM_HASH_BUCKETS 137
  59. /* {Symbols}
  60. */
  61. unsigned long
  62. scm_strhash (const unsigned char *str, scm_sizet len, unsigned long n)
  63. {
  64. if (len > 5)
  65. {
  66. scm_sizet i = 5;
  67. unsigned long h = 264 % n;
  68. while (i--)
  69. h = ((h << 8) + ((unsigned) (scm_downcase (str[h % len])))) % n;
  70. return h;
  71. }
  72. else
  73. {
  74. scm_sizet i = len;
  75. unsigned long h = 0;
  76. while (i)
  77. h = ((h << 8) + ((unsigned) (scm_downcase (str[--i])))) % n;
  78. return h;
  79. }
  80. }
  81. int scm_symhash_dim = NUM_HASH_BUCKETS;
  82. /* scm_sym2vcell
  83. * looks up the symbol in the symhash table.
  84. */
  85. SCM
  86. scm_sym2vcell (SCM sym, SCM thunk, SCM definep)
  87. {
  88. if (SCM_NIMP (thunk))
  89. {
  90. SCM var;
  91. if (SCM_TYP7 (thunk) == scm_tc7_cclo
  92. && SCM_TYP7 (SCM_CCLO_SUBR (thunk)) == scm_tc7_subr_3)
  93. /* Bypass evaluator in the standard case. */
  94. var = SCM_SUBRF (SCM_CCLO_SUBR (thunk)) (thunk, sym, definep);
  95. else
  96. var = scm_apply (thunk, sym, scm_cons (definep, scm_listofnull));
  97. if (SCM_FALSEP (var))
  98. return SCM_BOOL_F;
  99. else
  100. {
  101. if (SCM_IMP(var) || !SCM_VARIABLEP (var))
  102. scm_wta (sym, "strangely interned symbol? ", "");
  103. return SCM_VARVCELL (var);
  104. }
  105. }
  106. else
  107. {
  108. SCM lsym;
  109. SCM * lsymp;
  110. SCM z;
  111. scm_sizet scm_hash = scm_strhash (SCM_UCHARS (sym), (scm_sizet) SCM_LENGTH (sym),
  112. (unsigned long) scm_symhash_dim);
  113. SCM_DEFER_INTS;
  114. for (lsym = SCM_VELTS (scm_symhash)[scm_hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
  115. {
  116. z = SCM_CAR (lsym);
  117. if (SCM_EQ_P (SCM_CAR (z), sym))
  118. {
  119. SCM_ALLOW_INTS;
  120. return z;
  121. }
  122. }
  123. for (lsym = *(lsymp = &SCM_VELTS (scm_weak_symhash)[scm_hash]);
  124. SCM_NIMP (lsym);
  125. lsym = *(lsymp = SCM_CDRLOC (lsym)))
  126. {
  127. z = SCM_CAR (lsym);
  128. if (SCM_EQ_P (SCM_CAR (z), sym))
  129. {
  130. if (SCM_NFALSEP (definep))
  131. {
  132. /* Move handle from scm_weak_symhash to scm_symhash. */
  133. *lsymp = SCM_CDR (lsym);
  134. SCM_SETCDR (lsym, SCM_VELTS(scm_symhash)[scm_hash]);
  135. SCM_VELTS(scm_symhash)[scm_hash] = lsym;
  136. }
  137. SCM_ALLOW_INTS;
  138. return z;
  139. }
  140. }
  141. SCM_ALLOW_INTS;
  142. return scm_wta (sym, "uninterned symbol? ", "");
  143. }
  144. }
  145. /* scm_sym2ovcell
  146. * looks up the symbol in an arbitrary obarray.
  147. */
  148. SCM
  149. scm_sym2ovcell_soft (SCM sym, SCM obarray)
  150. {
  151. SCM lsym, z;
  152. scm_sizet scm_hash;
  153. scm_hash = scm_strhash (SCM_UCHARS (sym),
  154. (scm_sizet) SCM_LENGTH (sym),
  155. SCM_LENGTH (obarray));
  156. SCM_REDEFER_INTS;
  157. for (lsym = SCM_VELTS (obarray)[scm_hash];
  158. SCM_NIMP (lsym);
  159. lsym = SCM_CDR (lsym))
  160. {
  161. z = SCM_CAR (lsym);
  162. if (SCM_EQ_P (SCM_CAR (z), sym))
  163. {
  164. SCM_REALLOW_INTS;
  165. return z;
  166. }
  167. }
  168. SCM_REALLOW_INTS;
  169. return SCM_BOOL_F;
  170. }
  171. SCM
  172. scm_sym2ovcell (SCM sym, SCM obarray)
  173. {
  174. SCM answer;
  175. answer = scm_sym2ovcell_soft (sym, obarray);
  176. if (!SCM_FALSEP (answer))
  177. return answer;
  178. scm_wta (sym, "uninterned symbol? ", "");
  179. return SCM_UNSPECIFIED; /* not reached */
  180. }
  181. /* Intern a symbol whose name is the LEN characters at NAME in OBARRAY.
  182. OBARRAY should be a vector of lists, indexed by the name's hash
  183. value, modulo OBARRAY's length. Each list has the form
  184. ((SYMBOL . VALUE) ...), where SYMBOL is a symbol, and VALUE is the
  185. value associated with that symbol (in the current module? in the
  186. system module?)
  187. To "intern" a symbol means: if OBARRAY already contains a symbol by
  188. that name, return its (SYMBOL . VALUE) pair; otherwise, create a
  189. new symbol, add the pair (SYMBOL . SCM_UNDEFINED) to the
  190. appropriate list of the OBARRAY, and return the pair.
  191. If softness is non-zero, don't create a symbol if it isn't already
  192. in OBARRAY; instead, just return #f.
  193. If OBARRAY is SCM_BOOL_F, create a symbol listed in no obarray and
  194. return (SYMBOL . SCM_UNDEFINED).
  195. If OBARRAY is scm_symhash, and that doesn't contain the symbol,
  196. check scm_weak_symhash instead. */
  197. SCM
  198. scm_intern_obarray_soft (const char *name,scm_sizet len,SCM obarray,int softness)
  199. {
  200. SCM lsym;
  201. SCM z;
  202. register scm_sizet i;
  203. register unsigned char *tmp;
  204. scm_sizet scm_hash;
  205. SCM_REDEFER_INTS;
  206. if (SCM_FALSEP (obarray))
  207. {
  208. scm_hash = scm_strhash ((unsigned char *) name, len, 1019);
  209. goto uninterned_symbol;
  210. }
  211. scm_hash = scm_strhash ((unsigned char *) name, len, SCM_LENGTH (obarray));
  212. /* softness == -1 used to mean that it was known that the symbol
  213. wasn't already in the obarray. I don't think there are any
  214. callers that use that case any more, but just in case...
  215. -- JimB, Oct 1996 */
  216. if (softness == -1)
  217. abort ();
  218. retry_new_obarray:
  219. for (lsym = SCM_VELTS (obarray)[scm_hash]; SCM_NIMP (lsym); lsym = SCM_CDR (lsym))
  220. {
  221. z = SCM_CAR (lsym);
  222. z = SCM_CAR (z);
  223. tmp = SCM_UCHARS (z);
  224. if (SCM_LENGTH (z) != len)
  225. goto trynext;
  226. for (i = len; i--;)
  227. if (((unsigned char *) name)[i] != tmp[i])
  228. goto trynext;
  229. {
  230. SCM a;
  231. a = SCM_CAR (lsym);
  232. SCM_REALLOW_INTS;
  233. return a;
  234. }
  235. trynext:;
  236. }
  237. if (SCM_EQ_P (obarray, scm_symhash))
  238. {
  239. obarray = scm_weak_symhash;
  240. goto retry_new_obarray;
  241. }
  242. uninterned_symbol:
  243. if (softness)
  244. {
  245. SCM_REALLOW_INTS;
  246. return SCM_BOOL_F;
  247. }
  248. lsym = scm_makfromstr (name, len, SCM_SYMBOL_SLOTS);
  249. SCM_SETLENGTH (lsym, (long) len, scm_tc7_msymbol);
  250. SCM_SYMBOL_HASH (lsym) = scm_hash;
  251. SCM_SET_SYMBOL_PROPS (lsym, SCM_EOL);
  252. if (SCM_FALSEP (obarray))
  253. {
  254. SCM answer;
  255. SCM_REALLOW_INTS;
  256. SCM_NEWCELL (answer);
  257. SCM_DEFER_INTS;
  258. SCM_SETCAR (answer, lsym);
  259. SCM_SETCDR (answer, SCM_UNDEFINED);
  260. SCM_REALLOW_INTS;
  261. return answer;
  262. }
  263. else
  264. {
  265. SCM a;
  266. SCM b;
  267. SCM_NEWCELL (a);
  268. SCM_NEWCELL (b);
  269. SCM_SETCAR (a, lsym);
  270. SCM_SETCDR (a, SCM_UNDEFINED);
  271. SCM_SETCAR (b, a);
  272. SCM_SETCDR (b, SCM_VELTS(obarray)[scm_hash]);
  273. SCM_VELTS(obarray)[scm_hash] = b;
  274. SCM_REALLOW_INTS;
  275. return SCM_CAR (b);
  276. }
  277. }
  278. SCM
  279. scm_intern_obarray (const char *name,scm_sizet len,SCM obarray)
  280. {
  281. return scm_intern_obarray_soft (name, len, obarray, 0);
  282. }
  283. SCM
  284. scm_intern (const char *name,scm_sizet len)
  285. {
  286. return scm_intern_obarray (name, len, scm_symhash);
  287. }
  288. SCM
  289. scm_intern0 (const char * name)
  290. {
  291. return scm_intern (name, strlen (name));
  292. }
  293. /* Intern the symbol named NAME in scm_symhash, NAME is null-terminated. */
  294. SCM
  295. scm_sysintern0_no_module_lookup (const char *name)
  296. {
  297. SCM easy_answer;
  298. SCM_DEFER_INTS;
  299. easy_answer = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 1);
  300. if (SCM_NIMP (easy_answer))
  301. {
  302. SCM_ALLOW_INTS;
  303. return easy_answer;
  304. }
  305. else
  306. {
  307. SCM lsym;
  308. scm_sizet len = strlen (name);
  309. scm_sizet scm_hash = scm_strhash ((unsigned char *) name,
  310. len,
  311. (unsigned long) scm_symhash_dim);
  312. SCM_NEWCELL (lsym);
  313. SCM_SETLENGTH (lsym, (long) len, scm_tc7_ssymbol);
  314. SCM_SETCHARS (lsym, name);
  315. lsym = scm_cons (lsym, SCM_UNDEFINED);
  316. SCM_VELTS (scm_symhash)[scm_hash] = scm_cons (lsym, SCM_VELTS (scm_symhash)[scm_hash]);
  317. SCM_ALLOW_INTS;
  318. return lsym;
  319. }
  320. }
  321. /* Is it safe to access SCM_TOP_LEVEL_LOOKUP_CLOSURE_VAR?
  322. */
  323. int scm_can_use_top_level_lookup_closure_var;
  324. /* Intern the symbol named NAME in scm_symhash, and give it the value
  325. VAL. NAME is null-terminated. Use the current top_level lookup
  326. closure to give NAME its value.
  327. */
  328. SCM
  329. scm_sysintern (const char *name, SCM val)
  330. {
  331. SCM vcell = scm_sysintern0 (name);
  332. SCM_SETCDR (vcell, val);
  333. return vcell;
  334. }
  335. SCM
  336. scm_sysintern0 (const char *name)
  337. {
  338. SCM lookup_proc;
  339. if (scm_can_use_top_level_lookup_closure_var &&
  340. SCM_NIMP (lookup_proc = SCM_CDR (scm_top_level_lookup_closure_var)))
  341. {
  342. SCM sym = SCM_CAR (scm_intern0 (name));
  343. SCM vcell = scm_sym2vcell (sym, lookup_proc, SCM_BOOL_T);
  344. if (SCM_FALSEP (vcell))
  345. scm_misc_error ("sysintern0", "can't define variable", sym);
  346. return vcell;
  347. }
  348. else
  349. return scm_sysintern0_no_module_lookup (name);
  350. }
  351. /* Lookup the value of the symbol named by the nul-terminated string
  352. NAME in the current module. */
  353. SCM
  354. scm_symbol_value0 (const char *name)
  355. {
  356. /* This looks silly - we look up the symbol twice. But it is in
  357. fact necessary given the current module system because the module
  358. lookup closures are written in scheme which needs real symbols. */
  359. SCM symbol = scm_intern_obarray_soft (name, strlen (name), scm_symhash, 0);
  360. SCM vcell = scm_sym2vcell (SCM_CAR (symbol),
  361. SCM_CDR (scm_top_level_lookup_closure_var),
  362. SCM_BOOL_F);
  363. if (SCM_FALSEP (vcell))
  364. return SCM_UNDEFINED;
  365. return SCM_CDR (vcell);
  366. }
  367. SCM_DEFINE (scm_symbol_p, "symbol?", 1, 0, 0,
  368. (SCM obj),
  369. "Returns @t{#t} if @var{obj} is a symbol, otherwise returns @t{#f}. (r5rs)")
  370. #define FUNC_NAME s_scm_symbol_p
  371. {
  372. if SCM_IMP(obj) return SCM_BOOL_F;
  373. return SCM_BOOL(SCM_SYMBOLP(obj));
  374. }
  375. #undef FUNC_NAME
  376. SCM_DEFINE (scm_symbol_to_string, "symbol->string", 1, 0, 0,
  377. (SCM s),
  378. "Returns the name of @var{symbol} as a string. If the symbol was part of\n"
  379. "an object returned as the value of a literal expression\n"
  380. "(section @pxref{Literal expressions}) or by a call to the @samp{read} procedure,\n"
  381. "and its name contains alphabetic characters, then the string returned\n"
  382. "will contain characters in the implementation's preferred standard\n"
  383. "case---some implementations will prefer upper case, others lower case.\n"
  384. "If the symbol was returned by @samp{string->symbol}, the case of\n"
  385. "characters in the string returned will be the same as the case in the\n"
  386. "string that was passed to @samp{string->symbol}. It is an error\n"
  387. "to apply mutation procedures like @code{string-set!} to strings returned\n"
  388. "by this procedure. (r5rs)\n\n"
  389. "The following examples assume that the implementation's standard case is\n"
  390. "lower case:\n\n"
  391. "@format\n"
  392. "@t{(symbol->string 'flying-fish) \n"
  393. " ==> \"flying-fish\"\n"
  394. "(symbol->string 'Martin) ==> \"martin\"\n"
  395. "(symbol->string\n"
  396. " (string->symbol "Malvina")) \n"
  397. " ==> \"Malvina\"\n"
  398. "}\n"
  399. "@end format")
  400. #define FUNC_NAME s_scm_symbol_to_string
  401. {
  402. SCM_VALIDATE_SYMBOL (1,s);
  403. return scm_makfromstr(SCM_CHARS(s), (scm_sizet)SCM_LENGTH(s), 0);
  404. }
  405. #undef FUNC_NAME
  406. SCM_DEFINE (scm_string_to_symbol, "string->symbol", 1, 0, 0,
  407. (SCM s),
  408. "Returns the symbol whose name is @var{string}. This procedure can\n"
  409. "create symbols with names containing special characters or letters in\n"
  410. "the non-standard case, but it is usually a bad idea to create such\n"
  411. "symbols because in some implementations of Scheme they cannot be read as\n"
  412. "themselves. See @samp{symbol->string}.\n\n"
  413. "The following examples assume that the implementation's standard case is\n"
  414. "lower case:\n\n"
  415. "@format\n"
  416. "@t{(eq? 'mISSISSIppi 'mississippi) \n"
  417. " ==> #t\n"
  418. "(string->symbol \"mISSISSIppi\") \n"
  419. " ==>\n"
  420. " @r{}the symbol with name \"mISSISSIppi\"\n"
  421. "(eq? 'bitBlt (string->symbol \"bitBlt\")) \n"
  422. " ==> #f\n"
  423. "(eq? 'JollyWog\n"
  424. " (string->symbol\n"
  425. " (symbol->string 'JollyWog))) \n"
  426. " ==> #t\n"
  427. "(string=? \"K. Harper, M.D.\"\n"
  428. " (symbol->string\n"
  429. " (string->symbol \"K. Harper, M.D.\"))) \n"
  430. " ==> #t\n"
  431. "}\n"
  432. "@end format")
  433. #define FUNC_NAME s_scm_string_to_symbol
  434. {
  435. SCM vcell;
  436. SCM answer;
  437. SCM_VALIDATE_ROSTRING (1,s);
  438. vcell = scm_intern(SCM_ROCHARS(s), (scm_sizet)SCM_LENGTH(s));
  439. answer = SCM_CAR (vcell);
  440. return answer;
  441. }
  442. #undef FUNC_NAME
  443. SCM_DEFINE (scm_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0,
  444. (SCM o, SCM s, SCM softp),
  445. "Intern a new symbol in @var{obarray}, a symbol table, with name\n"
  446. "@var{string}.\n\n"
  447. "If @var{obarray} is @code{#f}, use the default system symbol table. If\n"
  448. "@var{obarray} is @code{#t}, the symbol should not be interned in any\n"
  449. "symbol table; merely return the pair (@var{symbol}\n"
  450. ". @var{#<undefined>}).\n\n"
  451. "The @var{soft?} argument determines whether new symbol table entries\n"
  452. "should be created when the specified symbol is not already present in\n"
  453. "@var{obarray}. If @var{soft?} is specified and is a true value, then\n"
  454. "new entries should not be added for symbols not already present in the\n"
  455. "table; instead, simply return @code{#f}.")
  456. #define FUNC_NAME s_scm_string_to_obarray_symbol
  457. {
  458. SCM vcell;
  459. SCM answer;
  460. int softness;
  461. SCM_VALIDATE_ROSTRING (2,s);
  462. SCM_ASSERT (SCM_BOOLP (o) || SCM_VECTORP (o), o, SCM_ARG1, FUNC_NAME);
  463. softness = (!SCM_UNBNDP (softp) && !SCM_FALSEP(softp));
  464. /* iron out some screwy calling conventions */
  465. if (SCM_FALSEP (o))
  466. o = scm_symhash;
  467. else if (SCM_EQ_P (o, SCM_BOOL_T))
  468. o = SCM_BOOL_F;
  469. vcell = scm_intern_obarray_soft (SCM_ROCHARS(s),
  470. (scm_sizet)SCM_ROLENGTH(s),
  471. o,
  472. softness);
  473. if (SCM_FALSEP (vcell))
  474. return vcell;
  475. answer = SCM_CAR (vcell);
  476. return answer;
  477. }
  478. #undef FUNC_NAME
  479. SCM_DEFINE (scm_intern_symbol, "intern-symbol", 2, 0, 0,
  480. (SCM o, SCM s),
  481. "Add a new symbol to @var{obarray} with name @var{string}, bound to an\n"
  482. "unspecified initial value. The symbol table is not modified if a symbol\n"
  483. "with this name is already present.")
  484. #define FUNC_NAME s_scm_intern_symbol
  485. {
  486. scm_sizet hval;
  487. SCM_VALIDATE_SYMBOL (2,s);
  488. if (SCM_FALSEP (o))
  489. o = scm_symhash;
  490. SCM_VALIDATE_VECTOR (1,o);
  491. hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
  492. /* If the symbol is already interned, simply return. */
  493. SCM_REDEFER_INTS;
  494. {
  495. SCM lsym;
  496. SCM sym;
  497. for (lsym = SCM_VELTS (o)[hval];
  498. SCM_NIMP (lsym);
  499. lsym = SCM_CDR (lsym))
  500. {
  501. sym = SCM_CAR (lsym);
  502. if (SCM_EQ_P (SCM_CAR (sym), s))
  503. {
  504. SCM_REALLOW_INTS;
  505. return SCM_UNSPECIFIED;
  506. }
  507. }
  508. SCM_VELTS (o)[hval] =
  509. scm_acons (s, SCM_UNDEFINED, SCM_VELTS (o)[hval]);
  510. }
  511. SCM_REALLOW_INTS;
  512. return SCM_UNSPECIFIED;
  513. }
  514. #undef FUNC_NAME
  515. SCM_DEFINE (scm_unintern_symbol, "unintern-symbol", 2, 0, 0,
  516. (SCM o, SCM s),
  517. "Remove the symbol with name @var{string} from @var{obarray}. This\n"
  518. "function returns @code{#t} if the symbol was present and @code{#f}\n"
  519. "otherwise.")
  520. #define FUNC_NAME s_scm_unintern_symbol
  521. {
  522. scm_sizet hval;
  523. SCM_VALIDATE_SYMBOL (2,s);
  524. if (SCM_FALSEP (o))
  525. o = scm_symhash;
  526. SCM_VALIDATE_VECTOR (1,o);
  527. hval = scm_strhash (SCM_UCHARS (s), SCM_LENGTH (s), SCM_LENGTH(o));
  528. SCM_DEFER_INTS;
  529. {
  530. SCM lsym_follow;
  531. SCM lsym;
  532. SCM sym;
  533. for (lsym = SCM_VELTS (o)[hval], lsym_follow = SCM_BOOL_F;
  534. SCM_NIMP (lsym);
  535. lsym_follow = lsym, lsym = SCM_CDR (lsym))
  536. {
  537. sym = SCM_CAR (lsym);
  538. if (SCM_EQ_P (SCM_CAR (sym), s))
  539. {
  540. /* Found the symbol to unintern. */
  541. if (SCM_FALSEP (lsym_follow))
  542. SCM_VELTS(o)[hval] = lsym;
  543. else
  544. SCM_SETCDR (lsym_follow, SCM_CDR(lsym));
  545. SCM_ALLOW_INTS;
  546. return SCM_BOOL_T;
  547. }
  548. }
  549. }
  550. SCM_ALLOW_INTS;
  551. return SCM_BOOL_F;
  552. }
  553. #undef FUNC_NAME
  554. SCM_DEFINE (scm_symbol_binding, "symbol-binding", 2, 0, 0,
  555. (SCM o, SCM s),
  556. "Look up in @var{obarray} the symbol whose name is @var{string}, and\n"
  557. "return the value to which it is bound. If @var{obarray} is @code{#f},\n"
  558. "use the global symbol table. If @var{string} is not interned in\n"
  559. "@var{obarray}, an error is signalled.")
  560. #define FUNC_NAME s_scm_symbol_binding
  561. {
  562. SCM vcell;
  563. SCM_VALIDATE_SYMBOL (2,s);
  564. if (SCM_FALSEP (o))
  565. o = scm_symhash;
  566. SCM_VALIDATE_VECTOR (1,o);
  567. vcell = scm_sym2ovcell (s, o);
  568. return SCM_CDR(vcell);
  569. }
  570. #undef FUNC_NAME
  571. SCM_DEFINE (scm_symbol_interned_p, "symbol-interned?", 2, 0, 0,
  572. (SCM o, SCM s),
  573. "Return @var{#t} if @var{obarray} contains a symbol with name\n"
  574. "@var{string}, and @var{#f} otherwise.")
  575. #define FUNC_NAME s_scm_symbol_interned_p
  576. {
  577. SCM vcell;
  578. SCM_VALIDATE_SYMBOL (2,s);
  579. if (SCM_FALSEP (o))
  580. o = scm_symhash;
  581. SCM_VALIDATE_VECTOR (1,o);
  582. vcell = scm_sym2ovcell_soft (s, o);
  583. if (SCM_IMP (vcell) && SCM_EQ_P (o, scm_symhash))
  584. vcell = scm_sym2ovcell_soft (s, scm_weak_symhash);
  585. return (SCM_NIMP(vcell)
  586. ? SCM_BOOL_T
  587. : SCM_BOOL_F);
  588. }
  589. #undef FUNC_NAME
  590. SCM_DEFINE (scm_symbol_bound_p, "symbol-bound?", 2, 0, 0,
  591. (SCM o, SCM s),
  592. "Return @var{#t} if @var{obarray} contains a symbol with name\n"
  593. "@var{string} bound to a defined value. This differs from\n"
  594. "@var{symbol-bound?} in that the mere mention of a symbol usually causes\n"
  595. "it to be interned; @code{symbol-bound?} determines whether a symbol has\n"
  596. "been given any meaningful value.")
  597. #define FUNC_NAME s_scm_symbol_bound_p
  598. {
  599. SCM vcell;
  600. SCM_VALIDATE_SYMBOL (2,s);
  601. if (SCM_FALSEP (o))
  602. o = scm_symhash;
  603. SCM_VALIDATE_VECTOR (1,o);
  604. vcell = scm_sym2ovcell_soft (s, o);
  605. return SCM_BOOL (SCM_NIMP (vcell) && !SCM_UNBNDP (SCM_CDR (vcell)));
  606. }
  607. #undef FUNC_NAME
  608. SCM_DEFINE (scm_symbol_set_x, "symbol-set!", 3, 0, 0,
  609. (SCM o, SCM s, SCM v),
  610. "Find the symbol in @var{obarray} whose name is @var{string}, and rebind\n"
  611. "it to @var{value}. An error is signalled if @var{string} is not present\n"
  612. "in @var{obarray}.")
  613. #define FUNC_NAME s_scm_symbol_set_x
  614. {
  615. SCM vcell;
  616. SCM_VALIDATE_SYMBOL (2,s);
  617. if (SCM_FALSEP (o))
  618. o = scm_symhash;
  619. SCM_VALIDATE_VECTOR (1,o);
  620. vcell = scm_sym2ovcell (s, o);
  621. SCM_SETCDR (vcell, v);
  622. return SCM_UNSPECIFIED;
  623. }
  624. #undef FUNC_NAME
  625. static void
  626. msymbolize (SCM s)
  627. {
  628. SCM string;
  629. string = scm_makfromstr (SCM_CHARS (s), SCM_LENGTH (s), SCM_SYMBOL_SLOTS);
  630. SCM_SETCHARS (s, SCM_CHARS (string));
  631. SCM_SETLENGTH (s, SCM_LENGTH (s), scm_tc7_msymbol);
  632. SCM_SETCDR (string, SCM_EOL);
  633. SCM_SETCAR (string, SCM_EOL);
  634. SCM_SET_SYMBOL_PROPS (s, SCM_EOL);
  635. /* If it's a tc7_ssymbol, it comes from scm_symhash */
  636. SCM_SYMBOL_HASH (s) = scm_strhash (SCM_UCHARS (s),
  637. (scm_sizet) SCM_LENGTH (s),
  638. SCM_LENGTH (scm_symhash));
  639. }
  640. SCM_DEFINE (scm_symbol_fref, "symbol-fref", 1, 0, 0,
  641. (SCM s),
  642. "Return the contents of @var{symbol}'s @dfn{function slot}.")
  643. #define FUNC_NAME s_scm_symbol_fref
  644. {
  645. SCM_VALIDATE_SYMBOL (1,s);
  646. SCM_DEFER_INTS;
  647. if (SCM_TYP7(s) == scm_tc7_ssymbol)
  648. msymbolize (s);
  649. SCM_ALLOW_INTS;
  650. return SCM_SYMBOL_FUNC (s);
  651. }
  652. #undef FUNC_NAME
  653. SCM_DEFINE (scm_symbol_pref, "symbol-pref", 1, 0, 0,
  654. (SCM s),
  655. "Return the @dfn{property list} currently associated with @var{symbol}.")
  656. #define FUNC_NAME s_scm_symbol_pref
  657. {
  658. SCM_VALIDATE_SYMBOL (1,s);
  659. SCM_DEFER_INTS;
  660. if (SCM_TYP7(s) == scm_tc7_ssymbol)
  661. msymbolize (s);
  662. SCM_ALLOW_INTS;
  663. return SCM_SYMBOL_PROPS (s);
  664. }
  665. #undef FUNC_NAME
  666. SCM_DEFINE (scm_symbol_fset_x, "symbol-fset!", 2, 0, 0,
  667. (SCM s, SCM val),
  668. "Change the binding of @var{symbol}'s function slot.")
  669. #define FUNC_NAME s_scm_symbol_fset_x
  670. {
  671. SCM_VALIDATE_SYMBOL (1,s);
  672. SCM_DEFER_INTS;
  673. if (SCM_TYP7(s) == scm_tc7_ssymbol)
  674. msymbolize (s);
  675. SCM_ALLOW_INTS;
  676. SCM_SET_SYMBOL_FUNC (s, val);
  677. return SCM_UNSPECIFIED;
  678. }
  679. #undef FUNC_NAME
  680. SCM_DEFINE (scm_symbol_pset_x, "symbol-pset!", 2, 0, 0,
  681. (SCM s, SCM val),
  682. "Change the binding of @var{symbol}'s property slot.")
  683. #define FUNC_NAME s_scm_symbol_pset_x
  684. {
  685. SCM_VALIDATE_SYMBOL (1,s);
  686. SCM_DEFER_INTS;
  687. if (SCM_TYP7(s) == scm_tc7_ssymbol)
  688. msymbolize (s);
  689. SCM_SET_SYMBOL_PROPS (s, val);
  690. SCM_ALLOW_INTS;
  691. return SCM_UNSPECIFIED;
  692. }
  693. #undef FUNC_NAME
  694. SCM_DEFINE (scm_symbol_hash, "symbol-hash", 1, 0, 0,
  695. (SCM s),
  696. "Return the hash value derived from @var{symbol}'s name, i.e. the integer\n"
  697. "index into @var{symbol}'s obarray at which it is stored.")
  698. #define FUNC_NAME s_scm_symbol_hash
  699. {
  700. SCM_VALIDATE_SYMBOL (1,s);
  701. if (SCM_TYP7(s) == scm_tc7_ssymbol)
  702. msymbolize (s);
  703. return SCM_MAKINUM (SCM_UNPACK (s) ^ SCM_SYMBOL_HASH (s));
  704. }
  705. #undef FUNC_NAME
  706. static void
  707. copy_and_prune_obarray (SCM from, SCM to)
  708. {
  709. int i;
  710. int length = SCM_LENGTH (from);
  711. for (i = 0; i < length; ++i)
  712. {
  713. SCM head = SCM_VELTS (from)[i]; /* GC protection */
  714. SCM ls = head;
  715. SCM res = SCM_EOL;
  716. SCM *lloc = &res;
  717. while (SCM_NIMP (ls))
  718. {
  719. if (!SCM_UNBNDP (SCM_CDAR (ls)))
  720. {
  721. *lloc = scm_cons (SCM_CAR (ls), SCM_EOL);
  722. lloc = SCM_CDRLOC (*lloc);
  723. }
  724. ls = SCM_CDR (ls);
  725. }
  726. SCM_VELTS (to)[i] = res;
  727. }
  728. }
  729. SCM_DEFINE (scm_builtin_bindings, "builtin-bindings", 0, 0, 0,
  730. (),
  731. "Create and return a copy of the global symbol table, removing all\n"
  732. "unbound symbols.")
  733. #define FUNC_NAME s_scm_builtin_bindings
  734. {
  735. int length = SCM_LENGTH (scm_symhash);
  736. SCM obarray = scm_make_vector (SCM_MAKINUM (length), SCM_EOL);
  737. copy_and_prune_obarray (scm_symhash, obarray);
  738. return obarray;
  739. }
  740. #undef FUNC_NAME
  741. SCM_DEFINE (scm_builtin_weak_bindings, "builtin-weak-bindings", 0, 0, 0,
  742. (),
  743. "")
  744. #define FUNC_NAME s_scm_builtin_weak_bindings
  745. {
  746. int length = SCM_LENGTH (scm_weak_symhash);
  747. SCM obarray = scm_make_doubly_weak_hash_table (SCM_MAKINUM (length));
  748. copy_and_prune_obarray (scm_weak_symhash, obarray);
  749. return obarray;
  750. }
  751. #undef FUNC_NAME
  752. static int gensym_counter;
  753. static SCM gensym_prefix;
  754. /* :FIXME:OPTIMIZE */
  755. SCM_DEFINE (scm_gensym, "gensym", 0, 2, 0,
  756. (SCM name, SCM obarray),
  757. "Create a new, unique symbol in @var{obarray}, using the global symbol\n"
  758. "table by default. If @var{name} is specified, it should be used as a\n"
  759. "prefix for the new symbol's name. The default prefix is @code{%%gensym}.")
  760. #define FUNC_NAME s_scm_gensym
  761. {
  762. SCM new;
  763. if (SCM_UNBNDP (name))
  764. name = gensym_prefix;
  765. else
  766. SCM_VALIDATE_ROSTRING (1,name);
  767. new = name;
  768. if (SCM_UNBNDP (obarray))
  769. {
  770. obarray = SCM_BOOL_F;
  771. goto skip_test;
  772. }
  773. else
  774. SCM_ASSERT ((SCM_VECTORP (obarray) || SCM_WVECTP (obarray)),
  775. obarray,
  776. SCM_ARG2,
  777. FUNC_NAME);
  778. while (!SCM_FALSEP (scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_T)))
  779. skip_test:
  780. new = scm_string_append
  781. (scm_cons2 (name,
  782. scm_number_to_string (SCM_MAKINUM (gensym_counter++),
  783. SCM_UNDEFINED),
  784. SCM_EOL));
  785. return scm_string_to_obarray_symbol (obarray, new, SCM_BOOL_F);
  786. }
  787. #undef FUNC_NAME
  788. void
  789. scm_init_symbols ()
  790. {
  791. gensym_counter = 0;
  792. gensym_prefix = scm_permanent_object (scm_makfrom0str ("%%gensym"));
  793. #include "libguile/symbols.x"
  794. }
  795. /*
  796. Local Variables:
  797. c-file-style: "gnu"
  798. End:
  799. */