PageRenderTime 57ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 1ms

/src/package.d

https://github.com/ynd/clisp-branch--ynd-devel
D | 2890 lines | 1945 code | 111 blank | 834 comment | 299 complexity | 1ef9fed67b20bc31fb5be26f15f56aff MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Package Management for CLISP
  3. * Bruno Haible 1990-2005
  4. * Sam Steingold 1999-2008
  5. * German comments translated into English: Stefan Kain 2002-02-20
  6. */
  7. #include "lispbibl.c"
  8. #include "arilev0.c" /* for hashcode calculation */
  9. /* data structure of the symbols: see LISPBIBL.D
  10. data structure of the symbol table:
  11. a vector with 3 Slots:
  12. size Fixnum >0, <2^24, = length of the table
  13. table vector of length size,
  14. contains single symbols (/= NIL) and symbol-lists
  15. count number of symbols in the table, Fixnum >=0 */
  16. #define Symtab_size(symtab) (TheSvector(symtab)->data[0])
  17. #define Symtab_table(symtab) (TheSvector(symtab)->data[1])
  18. #define Symtab_count(symtab) (TheSvector(symtab)->data[2])
  19. /* consistency rule: for each string there is in the table
  20. at most one symbol with this printname. */
  21. /* UP: Creates a new empty symbol-table.
  22. make_symtab(size)
  23. > size: the desired size of the table (odd number, >0, <2^24)
  24. < result: new symbol-table of this size
  25. can trigger GC */
  26. local maygc object make_symtab (uintL size) {
  27. var object table = allocate_vector(size); /* vector with size NIL-entries */
  28. pushSTACK(table);
  29. var object symtab = allocate_vector(3); /* vector of length 3 */
  30. Symtab_table(symtab) = popSTACK(); /* insert table */
  31. Symtab_size(symtab) = fixnum(size); /* insert size */
  32. Symtab_count(symtab) = Fixnum_0; /* insert count := 0 */
  33. return symtab;
  34. }
  35. /* UP: Calculates the hashcode of a string. This is a 24-bit-number.
  36. string_hashcode(string,invert)
  37. > string: a string
  38. > invert: whether to implicitly case-invert the string
  39. < result: the hashcode of the string */
  40. local uint32 string_hashcode (object string, bool invert) {
  41. var uintL len;
  42. var uintL offset;
  43. string = unpack_string_ro(string,&len,&offset);
  44. var uint32 hashcode = 0; /* hashcode, only the lower 24 Bit count */
  45. if (len > 0) {
  46. SstringDispatch(string,X, {
  47. var const cintX* charptr = &((SstringX)TheVarobject(string))->data[offset];
  48. /* there are len characters, starting at charptr */
  49. /* Look at all len characters, not just at the first min(len,16)
  50. characters, as we did earlier, because a bad hash function quasi
  51. turns the hash table into a few long linear lists. */
  52. var uintC count;
  53. dotimesC(count, len, {
  54. /* rotate hashcode by 5 bits to the left: */
  55. hashcode = hashcode << 5; hashcode = hashcode + (hashcode >> 24);
  56. /* 'add' next byte via XOR: */
  57. var cintX c = *charptr++;
  58. hashcode = hashcode ^ (uint32)(invert ? as_cint(invert_case(as_chart(c))) : c);
  59. });
  60. });
  61. }
  62. return hashcode & 0x00FFFFFF;
  63. }
  64. /* UP: Reorganizes a symbol-table, after it has grown, and
  65. tries to save Conses.
  66. rehash_symtab(symtab)
  67. > symtab: symbol-table
  68. < result: reorganized symbol-table (EQ to the first).
  69. call only, if BREAK_SEM_2 is set
  70. can trigger GC */
  71. local maygc object rehash_symtab (object symtab);
  72. /* auxiliary functions: */
  73. /* takes a Cons from free-conses or returns a fresh one.
  74. new_cons()
  75. < result: new Cons.
  76. stack layout: free-conses, newtable, listr, symbol, entry.
  77. can trigger GC */
  78. local maygc object new_cons (void) {
  79. var object free = STACK_4; /* free-conses */
  80. if (!nullp(free)) {
  81. STACK_4 = Cdr(free); /* shorten free-conses */
  82. return free;
  83. } else {
  84. return allocate_cons(); /* request new Cons from memory-management */
  85. }
  86. }
  87. /* inserts an additional symbol into the new table.
  88. newinsert(sym,size);
  89. > sym: symbol
  90. stack layout: tab, oldtable, free-conses, newtable, listr.
  91. can trigger GC */
  92. local maygc void newinsert (object sym, uintL size) {
  93. var uintL index = /* Index = Hashcode mod size */
  94. string_hashcode(Symbol_name(sym),false) % size;
  95. /* entry in the newtable */
  96. var object entry = TheSvector(STACK_1)->data[index];
  97. if ((!nullp(entry)) || nullp(sym)) {
  98. /* if entry=NIL and sym/=NIL, then simply enter sym.
  99. else, entry must be extended by cons-ing: */
  100. pushSTACK(sym); /* save symbol */
  101. pushSTACK(entry); /* save entry */
  102. if (!listp(entry)) {
  103. /* if entry is not a list, replace with (new-cons entry NIL): */
  104. var object new_entry = new_cons();
  105. Cdr(new_entry) = NIL; Car(new_entry) = STACK_0;
  106. STACK_0 = new_entry;
  107. }
  108. /* and cons symbol in front of it: */
  109. var object new_entry = new_cons();
  110. Cdr(new_entry) = popSTACK(); /* enter entry resp. list as CDR */
  111. Car(new_entry) = popSTACK(); /* enter symbol as CAR */
  112. sym = new_entry; /* and then enter new_entry */
  113. }
  114. TheSvector(STACK_1)->data[index] = sym; /* enter new entry in newtable */
  115. }
  116. local object rehash_symtab (object symtab) {
  117. pushSTACK(symtab); /* save symbol-table */
  118. var uintL oldsize = posfixnum_to_V(Symtab_size(symtab)); /* old size */
  119. var uintL newsize; /* new size */
  120. var object size; /* new size (as Fixnum) */
  121. pushSTACK(Symtab_table(symtab)); /* oldtable = old table-vector */
  122. pushSTACK(NIL); /* free-conses := NIL */
  123. #ifdef TYPECODES /* Svector_length is limited to max. 2^32-1 */
  124. /* new size = min(floor(oldsize*1.6),2^32-1) */
  125. { /* multiply oldsize (>0, <2^32) with 1.6*2^31, then divide by 2^31 : */
  126. var uint32 prod_hi;
  127. var uint32 prod_lo;
  128. mulu32(oldsize,3435973888UL, prod_hi=,prod_lo=);
  129. newsize =
  130. (prod_hi < (1UL<<31) ? (prod_hi << 1) | (prod_lo >> 31) : (1UL<<31)-1 );
  131. }
  132. #else /* Svector_length is limited to max. 2^24-1 */
  133. /* new size = min(floor(oldsize*1.6),2^24-1) */
  134. { /* multiply oldsize (>0, <2^24) with 1.6*2^7, then divide by 2^7 : */
  135. var uint32 prod = oldsize * 205UL;
  136. newsize = (prod < (1UL<<31) ? prod>>7 : (1UL<<24)-1 );
  137. } /* newsize is now >= oldsize > 0 and < 2^24 */
  138. #endif
  139. /* make newsize odd by rounding off: */
  140. newsize = (newsize - 1) | 1 ;
  141. /* calculate size: */
  142. size = fixnum(newsize);
  143. /* if newsize <= oldsize , the table does not need to be enlarged: */
  144. if (newsize <= oldsize) {
  145. skipSTACK(3);
  146. return symtab;
  147. }
  148. { /* new vector with size NILs */
  149. var object newtable = allocate_vector(newsize);
  150. pushSTACK(newtable); /* save */
  151. }
  152. /* here we could protect against breaks.
  153. stack layout: tab, oldtable, free-conses, newtable.
  154. transfer symbols from oldtable to newtable:
  155. first process the symbols, that sit in lists
  156. (maybe Conses become free): */
  157. {
  158. var gcv_object_t* offset = 0; /* offset = sizeof(gcv_object_t)*index */
  159. var uintC count;
  160. dotimespC(count,oldsize, {
  161. var object oldentry = /* entry with number index in oldtable */
  162. *(gcv_object_t*)(pointerplus(&TheSvector(STACK_2)->data[0],
  163. (aint)offset));
  164. if (consp(oldentry)) /* this time process only non-empty symbol-lists */
  165. do {
  166. pushSTACK(Cdr(oldentry)); /* save rest-list */
  167. /* cons oldentry in front of free-conses */
  168. Cdr(oldentry) = STACK_2; STACK_2 = oldentry;
  169. /* enter symbol in the new table */
  170. newinsert(Car(oldentry),newsize);
  171. oldentry = popSTACK(); /* rest-list */
  172. } while (consp(oldentry));
  173. offset++;
  174. });
  175. }
  176. { /* then process symbols, that sit there collision-free: */
  177. var gcv_object_t* offset = 0; /* offset = sizeof(gcv_object_t)*index */
  178. var uintC count;
  179. dotimespC(count,oldsize, {
  180. var object oldentry = /* entry with number index in oldtable */
  181. *(gcv_object_t*)(pointerplus(&TheSvector(STACK_2)->data[0],
  182. (aint)offset));
  183. if (!listp(oldentry)) { /* this time process only symbols /= NIL */
  184. pushSTACK(oldentry); /* dummy, so that the stack is fine */
  185. newinsert(oldentry,newsize); /* enter into the new table */
  186. skipSTACK(1);
  187. }
  188. offset++;
  189. });
  190. }
  191. /* stack layout: tab, oldtable, free-conses, newtable. */
  192. { /* update tab: */
  193. var object newtable = popSTACK(); /* newtable */
  194. skipSTACK(2);
  195. symtab = popSTACK(); /* tab */
  196. Symtab_size(symtab) = size;
  197. Symtab_table(symtab) = newtable;
  198. }
  199. /* here, breaks could be allowed again. */
  200. return symtab;
  201. }
  202. /* UP: Searches a symbol with given print-name in the symbol-table.
  203. symtab_lookup(string,invert,symtab,&sym)
  204. > string: string
  205. > invert: whether to implicitly case-invert the string
  206. > symtab: symbol-table
  207. < result: true if found, false if not found.
  208. if found:
  209. < sym: the symbol from the symbol-table, that has the given printname */
  210. local bool symtab_lookup (object string, bool invert, object symtab, object* sym_) {
  211. var uintL index = /* Index = Hashcode mod size */
  212. string_hashcode(string,invert) % (uintL)posfixnum_to_V(Symtab_size(symtab));
  213. /* entry in the table */
  214. var object entry = TheSvector(Symtab_table(symtab))->data[index];
  215. if (!listp(entry)) { /* entry is a single symbol */
  216. /* first string and printname of the found symbol are equal ? */
  217. if ((invert ? string_eq_inverted : string_eq)
  218. (string,Symbol_name(entry))) {
  219. if (sym_) { *sym_ = entry; }
  220. return true;
  221. } else {
  222. return false;
  223. }
  224. } else { /* entry is a symbol-list */
  225. while (consp(entry)) {
  226. /* first string and printname of the symbol are equal ? */
  227. if ((invert ? string_eq_inverted : string_eq)
  228. (string,Symbol_name(Car(entry))))
  229. goto found;
  230. entry = Cdr(entry);
  231. }
  232. return false; /* not found */
  233. found: /* found as CAR of entry */
  234. if (sym_) { *sym_ = Car(entry); }
  235. return true;
  236. }
  237. }
  238. /* UP: Searches a given symbol in the symbol-table.
  239. symtab_find(sym,symtab)
  240. > sym: symbol
  241. > symtab: symbol-table
  242. < result: true, if found */
  243. local bool symtab_find (object sym, object symtab) {
  244. var uintL index = /* Index = Hashcode mod size */
  245. string_hashcode(Symbol_name(sym),false) % (uintL)posfixnum_to_V(Symtab_size(symtab));
  246. /* entry in the table */
  247. var object entry = TheSvector(Symtab_table(symtab))->data[index];
  248. if (!listp(entry)) { /* entry is a single symbol */
  249. /* sym and found symbol are equal ? */
  250. if (eq(sym,entry))
  251. return true;
  252. else
  253. return false;
  254. } else { /* entry is a symbol-list */
  255. if (nullp(memq(sym,entry))) return false; /* not found */
  256. else return true; /* found as CAR from entry */
  257. }
  258. }
  259. /* UP: Inserts a given symbol into the symbol-table (destructively).
  260. symtab_insert(sym,symtab)
  261. > sym: symbol
  262. > symtab: symbol-table
  263. < result: new symbol-table, EQ to the old one
  264. call only, if BREAK_SEM_2 is set
  265. can trigger GC */
  266. local maygc object symtab_insert (object sym, object symtab) {
  267. { /* first test if reorganization is necessary: */
  268. var uintL size = posfixnum_to_V(Symtab_size(symtab));
  269. var uintL count = posfixnum_to_V(Symtab_count(symtab));
  270. /* if count>=2*size , the table must be reorganized: */
  271. if (count >= 2*size) {
  272. pushSTACK(sym); /* save symbol */
  273. symtab = rehash_symtab(symtab);
  274. sym = popSTACK();
  275. }
  276. }
  277. /* then insert the symbol: */
  278. var uintL index = /* Index = Hashcode mod size */
  279. string_hashcode(Symbol_name(sym),false) % (uintL)posfixnum_to_V(Symtab_size(symtab));
  280. /* entry in the table */
  281. var object entry = TheSvector(Symtab_table(symtab))->data[index];
  282. if (!nullp(entry) || nullp(sym)) {
  283. /* if entry=NIL and sym/=NIL, then simply enter sym.
  284. else, entry must be extended by cons-ing: */
  285. pushSTACK(symtab); /* save symtab */
  286. pushSTACK(sym); /* save Symbol */
  287. pushSTACK(entry); /* save entry */
  288. if (!listp(entry)) {
  289. /* if entry is not a list, replace with (cons entry NIL): */
  290. var object new_entry = allocate_cons();
  291. Car(new_entry) = STACK_0;
  292. STACK_0 = new_entry;
  293. }
  294. { /* and cons symbol in front of it: */
  295. var object new_entry = allocate_cons();
  296. Cdr(new_entry) = popSTACK(); /* enter entry resp. list as CDR */
  297. Car(new_entry) = popSTACK(); /* enter symbol as CAR */
  298. sym = new_entry; /* and then enter new_entry */
  299. }
  300. symtab = popSTACK();
  301. }
  302. TheSvector(Symtab_table(symtab))->data[index] = sym; /* enter new entry */
  303. Symtab_count(symtab) = fixnum_inc(Symtab_count(symtab),1); /* (incf count) */
  304. return symtab;
  305. }
  306. /* UP: Removes a symbol from a symbol-table.
  307. symtab_delete(sym,symtab)
  308. > sym: symbol
  309. > symtab: symboltable */
  310. local void symtab_delete (object sym, object symtab) {
  311. var uintL index = /* Index = Hashcode mod size */
  312. string_hashcode(Symbol_name(sym),false) % (uintL)posfixnum_to_V(Symtab_size(symtab));
  313. var gcv_object_t* entryptr = &TheSvector(Symtab_table(symtab))->data[index];
  314. var object entry = *entryptr; /* entry in the table */
  315. if (!listp(entry)) { /* entry is a single symbol */
  316. /* sym and found symbol eq ? */
  317. if (!eq(sym,entry))
  318. goto notfound;
  319. /* replace entry with NIL: */
  320. *entryptr = NIL;
  321. } else { /* entry is a symbol-list */
  322. while (consp(entry)) {
  323. /* sym and symbol from entry eq ? */
  324. if (eq(sym,Car(entry)))
  325. goto found;
  326. entryptr = &Cdr(entry); entry = *entryptr;
  327. }
  328. goto notfound; /* not found */
  329. found: /* found as CAR of *entryptr = entry */
  330. /* -> discard a list-element: */
  331. *entryptr = Cdr(entry); /* replace entry with Cdr(entry) */
  332. }
  333. /* finally decrement the symbol-counter by 1: (decf count) */
  334. { Symtab_count(symtab) = fixnum_inc(Symtab_count(symtab),-1); }
  335. return;
  336. notfound:
  337. pushSTACK(unbound); /* PACKAGE-ERROR slot PACKAGE */
  338. pushSTACK(sym);
  339. error(package_error,
  340. GETTEXT("symbol ~S cannot be deleted from symbol table"));
  341. }
  342. /* lookup the STRING among the EXTernal (resp. INTernal) symbols of PACK */
  343. #define package_lookup_ext(string,invert,pack,res_) \
  344. symtab_lookup(string,invert,ThePackage(pack)->pack_external_symbols,res_)
  345. #define package_lookup_int(string,invert,pack,res_) \
  346. symtab_lookup(string,invert,ThePackage(pack)->pack_internal_symbols,res_)
  347. /* Test whether there is an inherited symbol with the given name.
  348. inherited_lookup(string,invert,pack,&sym)
  349. Return true if string is found in (package-use-list pack).
  350. > string: a Lisp string object
  351. > invert: whether to implicitly case-invert the string
  352. > pack: is a Lisp package object
  353. The symbol found is returned in *SYM_ (if SYM_ is not NULL). */
  354. local bool inherited_lookup (object string, bool invert, object pack, object* sym_) {
  355. var object packlistr = ThePackage(pack)->pack_use_list;
  356. while (consp(packlistr)) {
  357. var object usedpack = Car(packlistr);
  358. if (package_lookup_ext(string,invert,usedpack,sym_))
  359. return true;
  360. packlistr = Cdr(packlistr);
  361. }
  362. return false;
  363. }
  364. /* Check whether the symbol is inherited by the package.
  365. inherited_find(symbol,pack)
  366. SYMBOL is a Lisp symbol object
  367. PACK is a Lisp package object */
  368. local bool inherited_find (object symbol, object pack) {
  369. var object list = ThePackage(pack)->pack_use_list;
  370. while (consp(list)) {
  371. if (symtab_find(symbol,ThePackage(Car(list))->pack_external_symbols))
  372. return true;
  373. list = Cdr(list);
  374. }
  375. return false;
  376. }
  377. /* data structure of package, see LISPBIBL.D.
  378. Components:
  379. pack_external_symbols symbol-table of the externally present symbols
  380. pack_internal_symbols symbol-table of the internally present symbols
  381. pack_shadowing_symbols list of the shadowing-symbols
  382. pack_use_list use-list, a list of packages
  383. pack_used_by_list used-by-list, a list of packages
  384. pack_name the name, an immutable simple-string
  385. pack_nicknames the nicknames, a list of immutable simple-strings
  386. pack_docstring the documentation string or NIL
  387. consistency rules:
  388. 1. All packages are listed in ALL_PACKAGES exactly once.
  389. 2. The union over ALL_PACKAGES of { name } U nicknames is disjoint.
  390. 3. for any two packages p,q:
  391. p in use_list(q) <==> q in used_by_list(q)
  392. 4. p is a Package.
  393. accessible(p) = ISymbols(p) U ESymbols(p) U
  394. U { ESymbols(q) | q in use_list(p) }
  395. 5. For each Package p
  396. shadowing_symbols(p) is a subset of ISymbols(p) U ESymbols(p)
  397. and therefore also a subset of accessible(p).
  398. 6. s is a string, p is a package.
  399. If more than one element of accessible(p) has print name = s, then
  400. exactly one of these symbols is in shadowing_symbols(p).
  401. 7. s is a string, p is a package.
  402. At most one symbol with the print name = s
  403. is in ISymbols(p) U ESymbols(p).
  404. 8. If s is a symbol with the Home Package p /= NIL,
  405. then s is in ISymbols(p) U ESymbols(p). */
  406. /* UP: make sure pack_shortest_name is indeed the shortest */
  407. local void ensure_pack_shortest_name (object pack) {
  408. var object shortest_name = ThePackage(pack)->pack_name;
  409. var uintL shortest_len = Sstring_length(shortest_name);
  410. var object nick_list = ThePackage(pack)->pack_nicknames;
  411. while (consp(nick_list)) {
  412. var object nick = Car(nick_list); nick_list = Cdr(nick_list);
  413. var uintL nick_len = Sstring_length(nick);
  414. if (nick_len < shortest_len) {
  415. shortest_len = nick_len;
  416. shortest_name = nick;
  417. }
  418. }
  419. ThePackage(pack)->pack_shortest_name = shortest_name;
  420. }
  421. /* UP: Creates a new package, without testing for name-conflicts.
  422. make_package(name,nicknames,case_sensitive_p)
  423. > name: name (an immutable simple-string)
  424. > nicknames: nicknames (a list of immutable simple-strings)
  425. > case_sensitive_p: flag, if case-sensitive
  426. > case_inverted_p: flag, if case-inverted
  427. < result: new package
  428. can trigger GC */
  429. local maygc object make_package (object name, object nicknames,
  430. bool case_sensitive_p, bool case_inverted_p) {
  431. set_break_sem_2();
  432. pushSTACK(nicknames); pushSTACK(name); /* save nicknames and names */
  433. /* create table for external symbols: */
  434. { var object symtab = make_symtab(11); pushSTACK(symtab); }
  435. /* create table for internal symbols: */
  436. { var object symtab = make_symtab(63); pushSTACK(symtab); }
  437. /* create new package: */
  438. var object pack = allocate_package();
  439. /* and fill: */
  440. if (case_sensitive_p) { mark_pack_casesensitive(pack); }
  441. if (case_inverted_p) { mark_pack_caseinverted(pack); }
  442. ThePackage(pack)->pack_internal_symbols = popSTACK();
  443. ThePackage(pack)->pack_external_symbols = popSTACK();
  444. ThePackage(pack)->pack_shadowing_symbols = NIL;
  445. ThePackage(pack)->pack_use_list = NIL;
  446. ThePackage(pack)->pack_used_by_list = NIL;
  447. ThePackage(pack)->pack_name = popSTACK();
  448. ThePackage(pack)->pack_nicknames = popSTACK();
  449. ThePackage(pack)->pack_docstring = NIL;
  450. ensure_pack_shortest_name(pack);
  451. /* and insert in ALL_PACKAGES: */
  452. pushSTACK(pack);
  453. var object new_cons = allocate_cons();
  454. pack = popSTACK();
  455. Car(new_cons) = pack; Cdr(new_cons) = O(all_packages);
  456. O(all_packages) = new_cons;
  457. /* finished: */
  458. clr_break_sem_2();
  459. return pack;
  460. }
  461. /* UP: Searches a symbol of given printname in the shadowing-list
  462. of a package.
  463. shadowing_lookup(string,invert,pack,&sym)
  464. > string: string
  465. > invert: whether to implicitly case-invert the string
  466. > pack: package
  467. < result: true, if found.
  468. < sym: the symbol from the shadowing-list, that has the given printname
  469. (if found) */
  470. local bool shadowing_lookup (object string, bool invert, object pack, object* sym_) {
  471. var object list = ThePackage(pack)->pack_shadowing_symbols;
  472. /* traverse shadowing-list: */
  473. while (consp(list)) {
  474. if ((invert ? string_eq_inverted : string_eq)
  475. (string,Symbol_name(Car(list))))
  476. goto found;
  477. list = Cdr(list);
  478. }
  479. return false; /* not found */
  480. found: /* found */
  481. if (sym_) { *sym_ = Car(list); }
  482. return true;
  483. }
  484. /* UP: Searches a given symbol in the shadowing-list of a package.
  485. shadowing_find(sym,pack)
  486. > sym: symbol
  487. > pack: package
  488. < result: true if found. */
  489. #define shadowing_find(s,p) (!nullp(memq(s,ThePackage(p)->pack_shadowing_symbols)))
  490. /* UP: Adds a symbol to the shadowing-list of a package, that does not yet
  491. contain a symbol of the same name.
  492. shadowing_insert(&sym,&pack)
  493. > sym: symbol (in STACK)
  494. > pack: package (in STACK)
  495. < sym: symbol, EQ to the old one
  496. < pack: package, EQ to the old one
  497. can trigger GC */
  498. local maygc void shadowing_insert (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  499. /* insert a new cons with symbol as CAR in front of the shadowing-symbols: */
  500. var object new_cons = allocate_cons();
  501. var object pack = *pack_;
  502. Car(new_cons) = *sym_;
  503. Cdr(new_cons) = ThePackage(pack)->pack_shadowing_symbols;
  504. ThePackage(pack)->pack_shadowing_symbols = new_cons;
  505. }
  506. /* UP: Removes a symbol of given name from the shadowing-list
  507. of a package.
  508. shadowing_delete(string,invert,pack)
  509. > string: string
  510. > invert: whether to implicitly case-invert the string
  511. > pack: package */
  512. local void shadowing_delete (object string, bool invert, object pack) {
  513. var gcv_object_t* listptr = &ThePackage(pack)->pack_shadowing_symbols;
  514. var object list = *listptr;
  515. /* list = *listptr traverses the shadowing-list */
  516. while (consp(list)) {
  517. if ((invert ? string_eq_inverted : string_eq)
  518. (string,Symbol_name(Car(list))))
  519. goto found;
  520. listptr = &Cdr(list); list = *listptr;
  521. }
  522. /* no symbol with this name found, done. */
  523. return;
  524. found:
  525. /* equality: remove. After that we are done, because there can be only
  526. one symbol of the same printname in the shadowing-list. */
  527. *listptr = Cdr(list); /* replace list with Cdr(list) */
  528. return;
  529. }
  530. /* UP: Tests, if a symbol in a package is accessible and is not
  531. shadowed by another symbol of the same name.
  532. accessiblep(sym,pack)
  533. > sym: symbol
  534. > pack: package
  535. < result: true if sym is accessible in pack and is not shadowed,
  536. else false */
  537. global bool accessiblep (object sym, object pack) {
  538. /* method:
  539. First, search a symbol of equal name in the shadowing-list;
  540. if not found, search the symbol among the present ones and
  541. then among the inherited symbols.
  542. Other possible method (not realized here):
  543. If the home-package of sym is equal to pack, sym is present in pack,
  544. done. Else search a present symbol of equal name.
  545. sym found -> finished.
  546. Found another one -> sym is not in the shadowing-list and
  547. thus not visible.
  548. none found -> search sym among the inherited symbols. */
  549. var object shadowingsym;
  550. /* First, search in the shadowing-list of pack: */
  551. if (shadowing_lookup(Symbol_name(sym),false,pack,&shadowingsym)) {
  552. /* shadowingsym = symbol, found in the shadowing-list */
  553. return (eq(shadowingsym,sym)); /* compare with sym */
  554. } else { /* no symbol of equal name in the shadowing-list */
  555. /* Search among the internal symbols: */
  556. if (symtab_find(sym,ThePackage(pack)->pack_internal_symbols))
  557. return true;
  558. /* Search among the external symbols: */
  559. if (symtab_find(sym,ThePackage(pack)->pack_external_symbols))
  560. return true;
  561. /* Search among the external symbols of the packages from the use-list: */
  562. if (inherited_find(sym,pack))
  563. return true;
  564. return false;
  565. }
  566. }
  567. /* UP: tests, if a symbol is accessible in a package as
  568. external symbol.
  569. externalp(sym,pack)
  570. > sym: symbol
  571. > pack: package
  572. < result:
  573. true if sym is accessible in pack as external symbol,
  574. (in this case, sym is not shadowed, because a symbol,
  575. possibly shadowing sym, should be listed in shadowing-symbols(pack),
  576. according to the consistency-rules 5 and 7 identical with sym),
  577. else false */
  578. global bool externalp (object sym, object pack) {
  579. return symtab_find(sym,ThePackage(pack)->pack_external_symbols);
  580. }
  581. /* UP: locates an external symbol with a given printname in a package.
  582. find_external_symbol(string,invert,pack,&sym)
  583. > string: string
  584. > invert: whether to implicitly case-invert the string
  585. > pack: package
  586. < result: true, if an external symbol with that printname has been found in pack.
  587. < sym: this symbol, if found. */
  588. global bool find_external_symbol (object string, bool invert, object pack, object* sym_) {
  589. return package_lookup_ext(string,invert,pack,sym_);
  590. }
  591. /* UP: searches a package of given name or nickname
  592. find_package(string)
  593. > string: string
  594. < result: package of this name or NIL */
  595. global object find_package (object string) {
  596. var object packlistr = O(all_packages); /* traverse package-list */
  597. var object pack;
  598. while (consp(packlistr)) {
  599. pack = Car(packlistr); /* Package to be tested */
  600. /* test name: */
  601. if (string_eq(string,ThePackage(pack)->pack_name))
  602. return pack;
  603. { /* test nickname: */
  604. /* traverse nickname-list */
  605. var object nicknamelistr = ThePackage(pack)->pack_nicknames;
  606. while (consp(nicknamelistr)) {
  607. if (string_eq(string,Car(nicknamelistr)))
  608. return pack;
  609. nicknamelistr = Cdr(nicknamelistr);
  610. }
  611. }
  612. packlistr = Cdr(packlistr); /* next package */
  613. }
  614. /* not found */
  615. return NIL;
  616. }
  617. /* UP: Searches a symbol of given printname in a package.
  618. find_symbol(string,invert,pack,&sym)
  619. > string: string
  620. > invert: whether to implicitly case-invert the string
  621. > pack: package
  622. < sym: symbol, if found; else NIL
  623. < result: 0, if not found
  624. 1, if available as external symbol
  625. 2, if inherited via use-list
  626. 3, if available as internal symbol
  627. + (-4, if available in the shadowing-list) */
  628. local sintBWL find_symbol (object string, bool invert, object pack, object* sym_) {
  629. /* First search in the shadowing-list of pack: */
  630. if (shadowing_lookup(string,invert,pack,sym_)) {
  631. /* *sym_ = symbol, found in the shadowing-list */
  632. /* Search for it among the internal symbols: */
  633. if (symtab_find(*sym_,ThePackage(pack)->pack_internal_symbols))
  634. return 3-4; /* found among the internal symbols */
  635. /* Search it among the external symbols: */
  636. if (symtab_find(*sym_,ThePackage(pack)->pack_external_symbols))
  637. return 1-4; /* found among the external symbols */
  638. /* contradiction to consistency rule 5. */
  639. pushSTACK(*sym_); pushSTACK(pack);
  640. error(serious_condition,GETTEXT("~S inconsistent: symbol ~S is a shadowing symbol but not present"));
  641. } else { /* symbol not yet found */
  642. /* search among the internal symbols: */
  643. if (package_lookup_int(string,invert,pack,sym_))
  644. return 3; /* found among the internal symbols */
  645. /* search among the external symbols: */
  646. if (package_lookup_ext(string,invert,pack,sym_))
  647. return 1; /* found among the external symbols */
  648. /* search among the external packages from the use-list: */
  649. if (inherited_lookup(string,invert,pack,sym_))
  650. return 2; /* found among the inherited symbols */
  651. /* not found */
  652. *sym_ = NIL; return 0;
  653. }
  654. }
  655. /* Actually, one has to search in the shadowing-list only after
  656. one has searched among the present symbols, because the symbol in the
  657. shadowing-list is already present (consistency rule 5). */
  658. /* raise a continuable error when func(obj) was called on a locked package pack
  659. continue means "Ignore the lock and proceed"
  660. can trigger GC */
  661. local maygc void cerror_package_locked (object func, object pack, object obj) {
  662. pushSTACK(NIL); /* 7 continue-format-string */
  663. pushSTACK(S(package_error)); /* 6 error type */
  664. pushSTACK(S(Kpackage)); /* 5 :PACKAGE */
  665. if (consp(pack)) pushSTACK(Car(pack)); /* from check-redefinition */
  666. else pushSTACK(pack); /* 4 PACKAGE-ERROR slot PACKAGE */
  667. pushSTACK(NIL); /* 3 error-format-string */
  668. pushSTACK(func); /* 2 */
  669. pushSTACK(obj); /* 1 */
  670. pushSTACK(pack); /* 0 */
  671. /* CLSTEXT "can trigger GC", so it cannot be called until
  672. all the arguments have been already pushed on the STACK */
  673. STACK_7 = CLSTEXT("Ignore the lock and proceed"); /* continue-format-string */
  674. STACK_3 = CLSTEXT("~A(~S): ~S is locked"); /* error-format-string */
  675. funcall(L(cerror_of_type),8);
  676. }
  677. /* check the package lock */
  678. #define check_pack_lock(func,pack,obj) \
  679. if (pack_locked_p(pack)) cerror_package_locked(func,pack,obj)
  680. #define safe_check_pack_lock(func,pack,obj) \
  681. do { pushSTACK(pack); pushSTACK(obj); /* save */ \
  682. check_pack_lock(func, STACK_1 /*pack*/,STACK_0 /*obj*/); \
  683. obj = popSTACK(); pack = popSTACK(); /* restore */ \
  684. } while(0)
  685. /* UP: Inserts a symbol into a package, that has no symbol of the same name yet.
  686. Does not check for conflicts.
  687. make_present(sym,pack);
  688. > sym: symbol
  689. > pack: package
  690. only call, if BREAK_SEM_2 is set
  691. can trigger GC */
  692. local maygc void make_present (object sym, object pack) {
  693. if (!eq(pack,O(keyword_package))) {
  694. if (nullp(Symbol_package(sym)))
  695. Symbol_package(sym) = pack;
  696. /* Insert symbol into the internal symbols: */
  697. symtab_insert(sym,ThePackage(pack)->pack_internal_symbols);
  698. } else {
  699. if (nullp(Symbol_package(sym))) {
  700. pushSTACK(pack); /* save */
  701. sym = check_symbol_not_symbol_macro(sym);
  702. Symbol_package(sym) = pack = popSTACK();
  703. Symbol_value(sym) = sym; /* sym gets itself as value */
  704. set_const_flag(TheSymbol(sym)); /* mark as constant */
  705. }
  706. /* Insert symbol into the external symbols: */
  707. symtab_insert(sym,ThePackage(pack)->pack_external_symbols);
  708. }
  709. }
  710. /* UP: Interns a symbol with a given printname in a package.
  711. intern(string,invert,pack,&sym)
  712. > string: string
  713. > invert: whether to implicitly case-invert the string
  714. > pack: package
  715. < sym: symbol
  716. < result: 0, if not found, but newly created
  717. 1, if available as external symbol
  718. 2, if inherited via use-list
  719. 3, if available as internal symbol
  720. can trigger GC */
  721. global maygc uintBWL intern (object string, bool invert, object pack, object* sym_) {
  722. {
  723. var sintBWL result = find_symbol(string,invert,pack,sym_); /* search */
  724. if (!(result==0))
  725. return result & 3; /* found -> finished */
  726. }
  727. pushSTACK(pack); /* save package */
  728. if (pack_locked_p(pack)) {
  729. /* when STRING comes from READ, it points to a re-usable buffer
  730. that will be overwritten during the CERROR i/o
  731. therefore we must copy and save it */
  732. pushSTACK(coerce_ss(string));
  733. cerror_package_locked(S(intern),STACK_1/*pack*/,STACK_0/*string*/);
  734. string = popSTACK();
  735. }
  736. if (invert)
  737. string = string_invertcase(string);
  738. string = coerce_imm_ss(string); /* string --> immutable simple-string */
  739. var object sym = make_symbol(string); /* (make-symbol string) */
  740. pack = popSTACK();
  741. /* enter this new symbol into the package: */
  742. set_break_sem_2(); /* protect against breaks */
  743. pushSTACK(sym); /* save symbol */
  744. make_present(sym,pack); /* intern into this package */
  745. *sym_ = popSTACK();
  746. clr_break_sem_2(); /* allow breaks */
  747. return 0;
  748. }
  749. /* UP: Interns a symbol of given printname into the keyword-package.
  750. intern_keyword(string)
  751. > string: string
  752. < result: symbol, a keyword
  753. can trigger GC */
  754. global maygc object intern_keyword (object string) {
  755. var object sym;
  756. intern(string,false,O(keyword_package),&sym);
  757. return sym;
  758. }
  759. /* UP: lookup the string among the internal and, if not found,
  760. external symbols of the package PACK
  761. tab, if supplied, is the assignment that will set the table in which the
  762. STRINNG was found */
  763. #define package_lookup(string,invert,pack,res_,tab) \
  764. (symtab_lookup(string,invert,tab ThePackage(pack)->pack_internal_symbols,res_) || \
  765. symtab_lookup(string,invert,tab ThePackage(pack)->pack_external_symbols,res_))
  766. /* UP: Imports a symbol into a package and turns it into a shadowing-symbol.
  767. Possibly another present symbol in this package
  768. of the same name is uninterned.
  769. shadowing_import(&sym,&pack);
  770. > sym: symbol (in STACK)
  771. > pack: package (in STACK)
  772. < sym: symbol, EQ to the old one
  773. < pack: package, EQ to the old one
  774. can trigger GC */
  775. local maygc void shadowing_import (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  776. check_pack_lock(S(shadowing_import),*pack_,*sym_);
  777. set_break_sem_2(); /* protect against breaks */
  778. {
  779. var object sym = *sym_;
  780. var object pack = *pack_;
  781. /* Searches an internal or external symbol of the same name: */
  782. var object othersym;
  783. var object tab_found;
  784. var object string = Symbol_name(sym);
  785. pushSTACK(string); /* save string */
  786. if (package_lookup(string,false,pack,&othersym,tab_found=)) {
  787. /* a symbol othersym of the same name was
  788. already present in the package */
  789. if (!eq(othersym,sym)) { /* was it the to be imported symbol itself? */
  790. /* no -> have to take othersym away from the internal resp. */
  791. /* from the external symbols: */
  792. symtab_delete(othersym,tab_found);
  793. /* Was this symbol taken away from its home-package,
  794. its home-package must be set to NIL: */
  795. if (eq(Symbol_package(othersym),pack))
  796. Symbol_package(othersym) = NIL;
  797. /* symbol sym must be added to the package pack. */
  798. make_present(sym,pack);
  799. }
  800. } else { /* symbol sym must be added to the package pack. */
  801. make_present(sym,pack);
  802. }
  803. }
  804. /* symbol must be added to the shadowing-list of the package. */
  805. shadowing_delete(popSTACK(),false,*pack_); /* remove string from */
  806. /* the shadowing-list */
  807. shadowing_insert(sym_,pack_); /* add symbol to the shadowing-list */
  808. clr_break_sem_2(); /* allow breaks */
  809. }
  810. /* UP: Shadows in a package all symbols accessible from other packages
  811. of give name by one symbol present in this package
  812. of the same name.
  813. shadow(&sym,invert,&pack)
  814. > sym: symbol or string (in STACK)
  815. > invert: whether to implicitly case-invert the string
  816. > pack: package (in STACK)
  817. < pack: package, EQ to the old
  818. can trigger GC */
  819. local maygc void do_shadow (const gcv_object_t* sym_, bool invert, const gcv_object_t* pack_) {
  820. check_pack_lock(S(shadow),*pack_,*sym_);
  821. set_break_sem_2(); /* protect against breaks */
  822. /* Search an internal or external symbol of the same name: */
  823. var object string = /* only the name of the symbol counts. */
  824. test_stringsymchar_arg(*sym_,invert);
  825. var object pack = *pack_;
  826. pushSTACK(NIL); /* make room for othersym */
  827. pushSTACK(string); /* save string */
  828. var object othersym;
  829. if (package_lookup(string,invert,pack,&othersym,)) {
  830. STACK_1 = othersym;
  831. } else {
  832. /* not found -> create new symbol of the same name: */
  833. if (invert)
  834. string = string_invertcase(string);
  835. string = coerce_imm_ss(string); /* string --> immutable simple-string */
  836. var object othersym = make_symbol(string); /* new symbol */
  837. STACK_1 = othersym;
  838. make_present(othersym,*pack_); /* enter into the package */
  839. /* home-package of the new symbols is pack */
  840. Symbol_package(STACK_1) = *pack_;
  841. }
  842. /* stack-layout: othersym, string
  843. In the package, now symbol othersym of the same name is present.
  844. remove string from the shadowing-list */
  845. shadowing_delete(popSTACK(),invert,*pack_);
  846. /* therefore add othersym to the shadowing-list */
  847. shadowing_insert(&STACK_0,pack_);
  848. skipSTACK(1); /* forget othersym */
  849. clr_break_sem_2(); /* allow breaks */
  850. }
  851. local maygc void shadow (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  852. do_shadow(sym_,false,pack_);
  853. }
  854. local maygc void cs_shadow (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  855. do_shadow(sym_,true,pack_);
  856. }
  857. /* UP: Removes a symbol from the set of present symbols of a package
  858. and does conflict resolution if it was in the shadowing-list
  859. of this package and a name conflict arises.
  860. unintern(&sym,&pack)
  861. > sym: symbol (in STACK)
  862. > pack: package (in STACK)
  863. < sym: symbol, EQ to the old
  864. < pack: package, EQ to the old
  865. < result: T if found and deleted, NIL if nothing has been done.
  866. can trigger GC */
  867. local maygc object unintern (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  868. check_pack_lock(S(unintern),*pack_,*sym_);
  869. var object sym = *sym_;
  870. var object pack = *pack_;
  871. var object symtab;
  872. /* search sym among the internal and the external symbols: */
  873. if (symtab_find(sym,symtab=ThePackage(pack)->pack_internal_symbols)
  874. || symtab_find(sym,symtab=ThePackage(pack)->pack_external_symbols)) {
  875. /* found symbol sym in the table symtab */
  876. if (shadowing_find(sym,pack)) { /* search in the shadowing-list */
  877. /* possible conflict -> build up selection-list: */
  878. pushSTACK(symtab); /* save symboltable */
  879. pushSTACK(NIL); /* start option-list */
  880. pushSTACK(ThePackage(pack)->pack_use_list); /* traverse use-list */
  881. /* stack-layout: symboltable, OL, use-list-rest */
  882. while (mconsp(STACK_0)) {
  883. var object othersym;
  884. pack = Car(STACK_0); /* package from the use-list */
  885. STACK_0 = Cdr(STACK_0);
  886. /* search inherited symbol of the same name: */
  887. if (package_lookup_ext(Symbol_name(*sym_),false,pack,&othersym)) {
  888. /* check that othersym is not in the option-list yet */
  889. var object temp = STACK_1;
  890. while (mconsp(temp)) {
  891. if (eq(Cdr(Cdr(Car(temp))),othersym))
  892. goto next_package;
  893. temp = Cdr(temp);
  894. }
  895. /* othersym is a symbol of the same name, inherited from pack */
  896. pushSTACK(temp=ThePackage(pack)->pack_name); /* name of pack */
  897. pushSTACK(othersym); /* symbol */
  898. pushSTACK(NIL);
  899. pushSTACK(NIL); /* "symbol ~A from ~A will become a shadowing symbol" */
  900. pushSTACK(Symbol_name(othersym)); /* symbolname */
  901. pushSTACK(pack); /* package */
  902. STACK_2 = CLSTEXT("symbol ~A from ~A will become a shadowing symbol");
  903. /* (FORMAT NIL "..." symbolname packagename) */
  904. funcall(S(format),4);
  905. temp = value1;
  906. pushSTACK(temp); /* total-string */
  907. temp = allocate_cons();
  908. Car(temp) = popSTACK();
  909. Cdr(temp) = popSTACK();
  910. pushSTACK(temp); /* (cons total-string othersym) */
  911. temp = allocate_cons();
  912. Cdr(temp) = popSTACK();
  913. Car(temp) = popSTACK();
  914. /* temp = (list packagename total-string othersym) */
  915. /* STACK is correct, again */
  916. /* push to the option-list: */
  917. pushSTACK(temp);
  918. temp = allocate_cons();
  919. Car(temp) = popSTACK(); Cdr(temp) = STACK_1;
  920. STACK_1 = temp;
  921. }
  922. next_package:;
  923. }
  924. skipSTACK(1);
  925. /* option-list build-up finished.
  926. stack-layout: symboltable, OL
  927. if (length OL) >= 2, there's a conflict: */
  928. if (mconsp(STACK_0) && mconsp(Cdr(STACK_0))) {
  929. /* raise a correctable error, options is STACK_0 already */
  930. pushSTACK(*pack_); /* PACKAGE-ERROR slot PACKAGE */
  931. pushSTACK(*pack_); /* package */
  932. pushSTACK(*sym_); /* symbol */
  933. correctable_error(package_error,GETTEXT("Uninterning ~S from ~S uncovers a name conflict.\nYou may choose the symbol in favour of which to resolve the conflict."));
  934. pushSTACK(value1);
  935. } else
  936. STACK_0 = NIL;
  937. /* STACK_0 is the selection (NIL if no conflict arises) */
  938. /* stack-layout: symboltable, selection */
  939. set_break_sem_3();
  940. {
  941. var object sym = *sym_;
  942. var object pack = *pack_;
  943. /* remove symbol from symboltable: */
  944. symtab_delete(sym,STACK_1);
  945. /* if it was removed from its home-package,
  946. set the home-package to NIL: */
  947. if (eq(Symbol_package(sym),pack))
  948. Symbol_package(sym) = NIL;
  949. /* discard symbol from shadowing-list: */
  950. shadowing_delete(Symbol_name(sym),false,pack);
  951. }
  952. if (!nullp(STACK_0))
  953. /* in case of a conflict: import selected symbol: */
  954. shadowing_import(&STACK_0,pack_);
  955. skipSTACK(2); /* forget symboltable & selection */
  956. clr_break_sem_3();
  957. return T; /* that's it */
  958. } else { /* no conflict */
  959. set_break_sem_2();
  960. symtab_delete(sym,symtab); /* delete symbol */
  961. if (eq(Symbol_package(sym),pack))
  962. Symbol_package(sym) = NIL; /* maybe set home-package to NIL */
  963. clr_break_sem_2();
  964. return T;
  965. }
  966. } else /* not found */
  967. return NIL;
  968. }
  969. /* UP: raise a continuable error and query the user about how to proceed
  970. return true when an abort was requested
  971. dialog_type == 0 or 1 or 2
  972. can trigger GC */
  973. local maygc bool query_intern_conflict (object pack, object sym, object other,
  974. int dialog_type) {
  975. pushSTACK(NIL); /* place for OPTIONS */
  976. pushSTACK(pack); /* PACKAGE-ERROR slot PACKAGE */
  977. pushSTACK(other); pushSTACK(pack); pushSTACK(sym);
  978. switch (dialog_type) { /* fill OPTIONS */
  979. case 0: /* conflict */
  980. STACK_4=CLOTEXT("((IMPORT \"import it and unintern the other symbol\" . T)"
  981. " (IGNORE \"do not import it, leave undone\" . NIL))");
  982. break;
  983. case 1: /* conflict & shadowing */
  984. STACK_4=CLOTEXT("((IMPORT \"import it, unintern one other symbol and shadow the other symbols\" . T)"
  985. " (IGNORE \"do not import it, leave undone\" . NIL))");
  986. break;
  987. case 2: /* shadowing */
  988. STACK_4=CLOTEXT("((IMPORT \"import it and shadow the other symbol\" . T)"
  989. " (IGNORE \"do nothing\" . NIL))");
  990. break;
  991. default: NOTREACHED;
  992. }
  993. correctable_error(package_error,(dialog_type == 1
  994. ? GETTEXT("Importing ~S into ~S produces a name conflict with ~S and other symbols.")
  995. : GETTEXT("Importing ~S into ~S produces a name conflict with ~S.")));
  996. return nullp(value1);
  997. }
  998. /* UP: Imports a symbol into a package and does conflict resolution
  999. in case, that a name conflict arises either with a symbol
  1000. inherited from anotherpackage or with an already present symbol
  1001. in this package of the same name.
  1002. import(&sym,&pack);
  1003. > sym: symbol (in STACK)
  1004. > pack: package (in STACK)
  1005. < pack: package, EQ to the old
  1006. can trigger GC */
  1007. global maygc void import (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  1008. var object sym = *sym_;
  1009. var object pack = *pack_;
  1010. var object string = Symbol_name(sym);
  1011. var object othersym;
  1012. var object othersymtab;
  1013. /* search symbol of the same name among the internal
  1014. and the external symbols: */
  1015. if (package_lookup(string,false,pack,&othersym,othersymtab=)) {
  1016. /* othersym = symbol of the same name, found in othersymtab */
  1017. if (eq(othersym,sym)) /* the same symbol -> nothing to do */
  1018. return;
  1019. /* not the same symbol was present -> must throw out othersym and
  1020. insert the given symbol sym for it.
  1021. determine beforehand, if there are additional inherited
  1022. symbols there, and then raise Continuable Error. */
  1023. pushSTACK(string);
  1024. pushSTACK(othersym);
  1025. pushSTACK(othersymtab);
  1026. /* first calculate inherited-flag: */
  1027. var bool inheritedp = inherited_lookup(string,false,pack,NULL);
  1028. /* stack-layout: symbol-name, othersym, othersymtab. */
  1029. /* raise Continuable Error: */
  1030. if (query_intern_conflict(*pack_,*sym_,othersym,inheritedp ? 1 : 0)) {
  1031. skipSTACK(3); return; /* yes -> do not import, finished */
  1032. }
  1033. /* import: */
  1034. set_break_sem_2();
  1035. pack = *pack_;
  1036. { /* remove othersym from pack: */
  1037. var object othersym = STACK_1;
  1038. symtab_delete(othersym,STACK_0); /* remove othersym from othersymtab */
  1039. if (eq(Symbol_package(othersym),pack))
  1040. Symbol_package(othersym) = NIL; /* maybe home-package := NIL */
  1041. }
  1042. /* insert sym in pack: */
  1043. make_present(*sym_,pack);
  1044. /* remove symbols of the same name from the shadowing-list of pack: */
  1045. shadowing_delete(STACK_2,false,*pack_);
  1046. /* if inherited-flag, turn sym in pack into a shadowing-symbol: */
  1047. if (inheritedp)
  1048. shadowing_insert(sym_,pack_);
  1049. clr_break_sem_2();
  1050. skipSTACK(3); return;
  1051. } else {
  1052. /* no symbol of the same name was present.
  1053. Search a symbol of the same name, that is inherited (there is
  1054. at most one, according to the consistency rules 6 and 5): */
  1055. var object otherusedsym;
  1056. if (!inherited_lookup(string,false,pack,&otherusedsym)
  1057. || eq(otherusedsym,sym)) {
  1058. /* insert sym simply in pack: */
  1059. set_break_sem_2();
  1060. make_present(sym,pack);
  1061. clr_break_sem_2();
  1062. } else {
  1063. /* no -> raise Continuable Error and query user: */
  1064. if (query_intern_conflict(pack,sym,otherusedsym,2))
  1065. return; /* yes -> do not import, finished */
  1066. /* import: */
  1067. set_break_sem_2();
  1068. /* insert sym in pack: */
  1069. make_present(*sym_,*pack_);
  1070. /* turn sym in pack into a shadowing-symbol: */
  1071. shadowing_insert(sym_,pack_);
  1072. clr_break_sem_2();
  1073. }
  1074. }
  1075. }
  1076. /* UP: Sets a symbol back from external to internal status in
  1077. einer package.
  1078. unexport(&sym,&pack);
  1079. > sym: symbol (in STACK)
  1080. > pack: package (in STACK)
  1081. < pack: package, EQ to the old
  1082. can trigger GC */
  1083. local maygc void unexport (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  1084. check_pack_lock(S(unexport),*pack_,*sym_);
  1085. var object sym = *sym_;
  1086. var object pack = *pack_;
  1087. var object symtab;
  1088. if (symtab_find(sym,symtab=ThePackage(pack)->pack_external_symbols)) {
  1089. /* sym is external in pack */
  1090. if (eq(pack,O(keyword_package))) { /* test for keyword-package */
  1091. pushSTACK(pack); /* PACKAGE-ERROR slot PACKAGE */
  1092. pushSTACK(pack);
  1093. error(package_error,GETTEXT("UNEXPORT in ~S is illegal"));
  1094. }
  1095. set_break_sem_2();
  1096. symtab_delete(sym,symtab); /* remove sym from the external symbols */
  1097. /* therefor, insert it into the internal symbols */
  1098. symtab_insert(sym,ThePackage(pack)->pack_internal_symbols);
  1099. clr_break_sem_2();
  1100. } else {
  1101. /* Search, if the symbol is accessible at all. */
  1102. /* Search among the internal symbols: */
  1103. if (symtab_find(sym,ThePackage(pack)->pack_internal_symbols))
  1104. return;
  1105. /* Search among the external symbols of the packages from the use-list: */
  1106. if (inherited_find(sym,pack))
  1107. return;
  1108. /* not found among the accessible symbols */
  1109. pushSTACK(pack); /* PACKAGE-ERROR slot PACKAGE */
  1110. pushSTACK(pack); pushSTACK(sym);
  1111. error(package_error,
  1112. GETTEXT("UNEXPORT works only on accessible symbols, not on ~S in ~S"));
  1113. }
  1114. }
  1115. /* UP: Sets a present symbol into external status.
  1116. make_external(sym,pack);
  1117. > sym: symbol
  1118. > pack: package, in which the symbol is present
  1119. can trigger GC */
  1120. local maygc void make_external (object sym, object pack) {
  1121. if (symtab_find(sym,ThePackage(pack)->pack_external_symbols))
  1122. return; /* symbol already external -> nothing to do */
  1123. set_break_sem_2();
  1124. /* remove sym from the internal symbols */
  1125. symtab_delete(sym,ThePackage(pack)->pack_internal_symbols);
  1126. /* therefor, insert it into the external symbols */
  1127. symtab_insert(sym,ThePackage(pack)->pack_external_symbols);
  1128. clr_break_sem_2();
  1129. }
  1130. /* UP: Exports a symbol from a package
  1131. export(&sym,&pack);
  1132. > sym: symbol (in STACK)
  1133. > pack: package (in STACK)
  1134. < sym: symbol, EQ to the old
  1135. < pack: package, EQ to the old
  1136. can trigger GC */
  1137. global maygc void export (const gcv_object_t* sym_, const gcv_object_t* pack_) {
  1138. check_pack_lock(S(export),*pack_,*sym_);
  1139. var object sym = *sym_;
  1140. var object pack = *pack_;
  1141. /* search sym among the external symbols of pack: */
  1142. if (symtab_find(sym,ThePackage(pack)->pack_external_symbols))
  1143. return; /* found -> finished */
  1144. var bool import_it = false;
  1145. /* import_it = flag, if symbol has to be imported first. */
  1146. /* search sym among the internal symbols of pack: */
  1147. if (!(symtab_find(sym,ThePackage(pack)->pack_internal_symbols))) {
  1148. /* symbol sym is not present in package pack */
  1149. import_it = true;
  1150. /* Search, if it is at least accessible: */
  1151. if (!inherited_find(sym,pack)) {
  1152. /* symbol sym is not even accessible in the package pack ==>
  1153. raise correctable error: */
  1154. pushSTACK(NIL); /* place for OPTIONS */
  1155. pushSTACK(pack); /* PACKAGE-ERROR slot PACKAGE */
  1156. /* "symbol ~S has to be imported in ~S before being exported" */
  1157. pushSTACK(pack); pushSTACK(sym); pushSTACK(S(export));
  1158. STACK_4 = CLOTEXT("((IMPORT \"import the symbol first\" . T)"
  1159. " (IGNORE \"do nothing, do not export the symbol\" . NIL))");
  1160. correctable_error(package_error,GETTEXT("~S: Symbol ~S should be imported into ~S before being exported."));
  1161. if (nullp(value1)) /* NIL-option selected? */
  1162. return; /* yes -> do not export, finished */
  1163. }
  1164. }
  1165. /* Test for name-conflict: */
  1166. pushSTACK(NIL); /* conflict-resolver:=NIL */
  1167. /* stack-layout: conflict-resolver (a list of pairs (sym . pack),
  1168. for which shadowing_import has to be applied).
  1169. used-by-list is searched */
  1170. pushSTACK(ThePackage(*pack_)->pack_used_by_list);
  1171. while (mconsp(STACK_0)) {
  1172. var object usingpack = Car(STACK_0); /* USE-ing package */
  1173. STACK_0 = Cdr(STACK_0);
  1174. var object othersym;
  1175. if (find_symbol(Symbol_name(*sym_),false,usingpack,&othersym) > 0)
  1176. /* othersym is a symbol of the same name in usingpack */
  1177. if (!eq(othersym,*sym_)) {
  1178. var gcv_object_t *othersym_, *usingpack_;
  1179. /* it is not sym itself -> there is a conflict */
  1180. pushSTACK(othersym); othersym_ = &STACK_0;
  1181. pushSTACK(usingpack); usingpack_ = &STACK_0;
  1182. /* stack-layout: conflict-resolver, used-by-list-rest,
  1183. other symbol, USE-ing package. */
  1184. pushSTACK(NIL); /* space for OPTIONS */
  1185. pushSTACK(*pack_); /* PACKAGE-ERROR slot PACKAGE */
  1186. pushSTACK(usingpack); /* USE-ing package */
  1187. pushSTACK(usingpack); /* USE-ing package */
  1188. pushSTACK(othersym); /* other symbol */
  1189. pushSTACK(*pack_); /* package */
  1190. pushSTACK(*sym_); /* symbol */
  1191. { /* construct options-list: */
  1192. var object temp;
  1193. pushSTACK(ThePackage(*pack_)->pack_name); /* package name */
  1194. pushSTACK(CLSTEXT("the symbol to export, "));
  1195. pushSTACK(*sym_); /* symbol */
  1196. funcall(L(prin1_to_string),1); /* (prin1-to-string Symbol) */
  1197. pushSTACK(value1);
  1198. /* (string-concat "The new symbol " (prin1-to-string Symbol)) */
  1199. temp = string_concat(2);
  1200. pushSTACK(t

Large files files are truncated, but you can click here to view the full file