home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-15 | 116.2 KB | 2,665 lines |
- # Package-Verwaltung für CLISP
- # Bruno Haible 28.1.1995
-
- #include "lispbibl.c"
- #include "arilev0.c" # für Hashcode-Berechnung
-
- # Datenstruktur des Symbols: siehe LISPBIBL.D
- # Datenstruktur der Symboltabelle:
- # ein Vektor mit 3 Slots:
- # size Fixnum >0, <2^16, = Länge der table
- # table Vektor der Länge size,
- # enthält einzelne Symbole (/= NIL) und Symbollisten
- # count Anzahl der Symbole in der Table, Fixnum >=0
- #define Symtab_size(symtab) (TheSvector(symtab)->data[0])
- #define Symtab_table(symtab) (TheSvector(symtab)->data[1])
- #define Symtab_count(symtab) (TheSvector(symtab)->data[2])
- # Konsistenzregel:
- # Zu jedem String gibt es in der Tabelle höchstens ein Symbol mit diesem
- # Printnamen.
-
- # UP: Kreiert eine neue leere Symboltabelle.
- # make_symtab(size)
- # > size: gewünschte Größe der Tabelle (ungerade, >0, <2^16)
- # < ergebnis: neue Symboltabelle dieser Größe
- # kann GC auslösen
- local object make_symtab (uintL size);
- local object make_symtab(size)
- var reg2 uintL size;
- { var reg3 object table = allocate_vector(size); # Vektor mit size NIL-Einträgen
- pushSTACK(table);
- {var reg1 object symtab = allocate_vector(3); # Vektor der Länge 3
- Symtab_table(symtab) = popSTACK(); # table einfüllen
- Symtab_size(symtab) = fixnum(size); # size einfüllen
- Symtab_count(symtab) = Fixnum_0; # count := 0 einfüllen
- return symtab;
- }}
-
- # UP: berechnet den Hashcode eines Strings. Dies ist eine 16-Bit-Zahl.
- # string_hashcode(string)
- # > string: ein String.
- # < ergebnis: der Hashcode des Strings
- local uint16 string_hashcode (object string);
- local uint16 string_hashcode(string)
- var reg5 object string;
- { var uintL len;
- var reg2 uintB* charptr = unpack_string(string,&len);
- # ab charptr kommen len Zeichen
- var reg1 uint32 hashcode = 0; # Hashcode, nur die unteren 16 Bit sind wesentlich
- var reg3 uintC count;
- dotimesC(count, (len>16 ? 16 : len), # min(len,16) mal:
- { # hashcode um 5 Bit nach links rotieren:
- hashcode = hashcode << 5; hashcode = hashcode | high16(hashcode);
- # und nächstes Byte dazuXORen:
- hashcode = hashcode ^ (uint32)(*charptr++);
- });
- return (uint16)hashcode;
- }
-
- # UP: Reorganisiert eine Symboltabelle, nachdem sie gewachsen ist, und
- # versucht dabei Conses zu sparen.
- # rehash_symtab(symtab)
- # > symtab: Symboltabelle
- # < ergebnis: reorganisierte Symboltabelle (EQ zur ersten).
- # nur bei gesetzter BREAK_SEM_2 aufzurufen
- # kann GC auslösen
- local object rehash_symtab (object symtab);
- #
- # Hilfsfunktionen:
- #
- # Entnimmt ein Cons aus free-conses oder liefert ein frisches.
- # new_cons()
- # < ergebnis: neues Cons.
- # Stackaufbau: free-conses, newtable, listr, symbol, entry.
- # kann GC auslösen
- local object new_cons (void);
- local object new_cons()
- { var reg1 object free = STACK_4; # free-conses
- if (!nullp(free))
- { STACK_4 = Cdr(free); # free-conses verkürzen
- return free;
- }
- else
- { return allocate_cons(); } # neues Cons aus der Speicherverwaltung anfordern
- }
- #
- # Fügt ein Symbol zusätzlich in die neue Tabelle ein.
- # newinsert(sym,size);
- # > sym: Symbol
- # Stackaufbau: tab, oldtable, free-conses, newtable, listr.
- # kann GC auslösen
- local void newinsert (object sym, uintWL size);
- local void newinsert(sym,size)
- var reg4 object sym;
- var reg5 uintWL size;
- { var reg2 uintL index = # Index = Hashcode mod size
- (uintL)(string_hashcode(Symbol_name(sym)) % size);
- var reg3 object entry = TheSvector(STACK_1)->data[index]; # entry in der newtable
- if ((!nullp(entry)) || nullp(sym))
- # Ist entry=NIL und sym/=NIL, so ist einfach sym einzutragen.
- # Sonst muß entry durch Consen erweitert werden:
- { pushSTACK(sym); # Symbol retten
- pushSTACK(entry); # entry retten
- if (!listp(entry))
- # Falls entry keine Liste ist, durch (new-cons entry NIL) ersetzen:
- { var reg1 object new_entry = new_cons();
- Cdr(new_entry) = NIL; Car(new_entry) = STACK_0;
- STACK_0 = new_entry;
- }
- # und Symbol davorconsen:
- { var reg1 object new_entry = new_cons();
- Cdr(new_entry) = popSTACK(); # entry bzw. Liste als CDR eintragen
- Car(new_entry) = popSTACK(); # Symbol als CAR eintragen
- sym = new_entry; # und dann new_entry eintragen
- } }
- TheSvector(STACK_1)->data[index] = sym; # neue Entry in newtable eintragen
- }
- #
- local object rehash_symtab(symtab)
- var reg6 object symtab;
- { pushSTACK(symtab); # Symboltabelle retten
- {var reg5 uintL oldsize = posfixnum_to_L(Symtab_size(symtab)); # alte Größe
- var reg6 uintL newsize; # neue Größe
- var reg4 object size; # neue Größe (als Fixnum)
- pushSTACK(Symtab_table(symtab)); # oldtable = alter Tabellenvektor
- pushSTACK(NIL); # free-conses := NIL
- # neue Größe = min(floor(oldsize*1.6),65535)
- { # multipliziere oldsize (>0, <2^16) mit 1.6*2^15, dann durch 2^15 :
- var reg1 uint32 prod = mulu16(oldsize,52429UL);
- newsize = (prod < (1UL<<31) ? prod>>15 : (1UL<<16)-1 );
- } # newsize ist jetzt >= oldsize > 0 und < 2^16
- # newsize durch Abrunden ungerade machen:
- newsize = (newsize - 1) | 1 ;
- # size berechnen:
- size = fixnum(newsize);
- # Bei newsize <= oldsize braucht die Tabelle nicht vergrößert zu werden:
- if (newsize <= oldsize) { skipSTACK(3); return symtab; }
- { var reg1 object newtable = allocate_vector(newsize); # neuer Vektor mit size NILs
- pushSTACK(newtable); # retten
- }
- # Hier könnte man gegen Unterbrechungen schützen.
- # Stackaufbau: tab, oldtable, free-conses, newtable.
- # Symbole von oldtable nach newtable übertragen:
- # Erst die Symbole verarbeiten, die auf Listen sitzen
- # (dabei werden evtl. Conses frei):
- { var reg3 object* offset = 0; # offset = sizeof(object)*index
- var reg2 uintC count;
- dotimespC(count,oldsize,
- { var reg1 object oldentry = # Eintrag mit Nummer index in oldtable
- *(object*)(pointerplus(&TheSvector(STACK_2)->data[0],(aint)offset));
- if (consp(oldentry)) # diesmal nur nichtleere Symbollisten verarbeiten
- do { pushSTACK(Cdr(oldentry)); # Restliste retten
- Cdr(oldentry) = STACK_2; STACK_2 = oldentry; # oldentry vor free-conses consen
- newinsert(Car(oldentry),newsize); # Symbol in die neue Tabelle eintragen
- oldentry = popSTACK(); # Restliste
- }
- while (consp(oldentry));
- offset++;
- });
- }
- # Dann die Symbole verarbeiten, die kollisionsfrei dasitzen:
- { var reg3 object* offset = 0; # offset = sizeof(object)*index
- var reg2 uintC count;
- dotimespC(count,oldsize,
- { var reg1 object oldentry = # Eintrag mit Nummer index in oldtable
- *(object*)(pointerplus(&TheSvector(STACK_2)->data[0],(aint)offset));
- if (!(listp(oldentry))) # diesmal nur Symbole /= NIL verarbeiten
- { pushSTACK(oldentry); # Dummy, damit der Stack stimmt
- newinsert(oldentry,newsize); # in die neue Tabelle eintragen
- skipSTACK(1);
- }
- offset++;
- });
- }
- # Stackaufbau: tab, oldtable, free-conses, newtable.
- # tab aktualisieren:
- { var reg1 object newtable = popSTACK(); # newtable
- skipSTACK(2);
- symtab = popSTACK(); # tab
- Symtab_size(symtab) = size;
- Symtab_table(symtab) = newtable;
- }
- # Hier könnte man Unterbrechungen wieder zulassen.
- return symtab;
- }}
-
- # UP: Sucht ein Symbol gegebenen Printnamens in einer Symboltabelle.
- # symtab_lookup(string,symtab,&sym)
- # > string: String
- # > symtab: Symboltabelle
- # < ergebnis: TRUE falls gefunden, FALSE falls nicht gefunden.
- # falls gefunden:
- # < sym: das Symbol aus der Symboltabelle, das den gegebenen Printnamen hat
- local boolean symtab_lookup (object string, object symtab, object* sym_);
- local boolean symtab_lookup(string,symtab,sym_)
- var reg3 object string;
- var reg4 object symtab;
- var reg5 object* sym_;
- { var reg2 uintL index = # Index = Hashcode mod size
- (uintL)(string_hashcode(string) % (uintW)(posfixnum_to_L(Symtab_size(symtab))));
- var reg1 object entry = TheSvector(Symtab_table(symtab))->data[index]; # entry in der table
- if (!(listp(entry)))
- # entry ist ein einzelnes Symbol
- { # erster String und Printname des gefundenen Symbols gleich ?
- if (string_gleich(string,Symbol_name(entry)))
- { *sym_ = entry; return TRUE; }
- else
- { return FALSE; }
- }
- else
- # entry ist eine Symbolliste
- { while (consp(entry))
- { # erster String und Printname des Symbols gleich ?
- if (string_gleich(string,Symbol_name(Car(entry)))) { goto found; }
- entry = Cdr(entry);
- }
- { return FALSE; } # nicht gefunden
- found: # gefunden als CAR von entry
- { *sym_ = Car(entry); return TRUE; }
- }
- }
-
- # UP: Sucht ein gegebenes Symbol in einer Symboltabelle.
- # symtab_find(sym,symtab)
- # > sym: Symbol
- # > symtab: Symboltabelle
- # < ergebnis: TRUE wenn gefunden
- local boolean symtab_find (object sym, object symtab);
- local boolean symtab_find(sym,symtab)
- var reg3 object sym;
- var reg4 object symtab;
- { var reg2 uintL index = # Index = Hashcode mod size
- (uintL)(string_hashcode(Symbol_name(sym)) % (uintW)(posfixnum_to_L(Symtab_size(symtab))));
- var reg1 object entry = TheSvector(Symtab_table(symtab))->data[index]; # entry in der table
- if (!(listp(entry)))
- # entry ist ein einzelnes Symbol
- { # sym und gefundenes Symbol gleich ?
- if (eq(sym,entry)) { return TRUE; } else { return FALSE; }
- }
- else
- # entry ist eine Symbolliste
- { while (consp(entry))
- { # sym und Symbol aus entry gleich ?
- if (eq(sym,Car(entry))) { goto found; }
- entry = Cdr(entry);
- }
- { return FALSE; } # nicht gefunden
- found: # gefunden als CAR von entry
- { return TRUE; }
- }
- }
-
- # UP: Fügt ein gegebenes Symbol in eine Symboltabelle ein (destruktiv).
- # symtab_insert(sym,symtab)
- # > sym: Symbol
- # > symtab: Symboltabelle
- # < ergebnis: neue Symboltabelle, EQ zur alten
- # nur bei gesetzter BREAK_SEM_2 aufzurufen
- # kann GC auslösen
- local object symtab_insert (object sym, object symtab);
- local object symtab_insert(sym,symtab)
- var reg4 object sym;
- var reg3 object symtab;
- { # erst der Test, ob Reorganisieren nötig ist:
- { var reg1 uintL size = posfixnum_to_L(Symtab_size(symtab));
- var reg2 uintL count = posfixnum_to_L(Symtab_count(symtab));
- # Bei count>=2*size muß die Tabelle reorganisiert werden:
- if (count >= 2*size)
- { pushSTACK(sym); # Symbol retten
- symtab = rehash_symtab(symtab);
- sym = popSTACK();
- }
- }
- # Dann das Symbol einfügen:
- {var reg2 uintL index = # Index = Hashcode mod size
- (uintL)(string_hashcode(Symbol_name(sym)) % (uintW)(posfixnum_to_L(Symtab_size(symtab))));
- var reg1 object entry = TheSvector(Symtab_table(symtab))->data[index]; # entry in der table
- if ((!(nullp(entry))) || (nullp(sym)))
- # Ist entry=NIL und sym/=NIL, so ist einfach sym einzutragen.
- # Sonst muß entry durch Consen erweitert werden:
- { pushSTACK(symtab); # symtab retten
- pushSTACK(sym); # Symbol retten
- pushSTACK(entry); # entry retten
- if (!(listp(entry)))
- # Falls entry keine Liste ist, durch (cons entry NIL) ersetzen:
- { var reg1 object new_entry = allocate_cons();
- Car(new_entry) = STACK_0;
- STACK_0 = new_entry;
- }
- # und Symbol davorconsen:
- { var reg1 object new_entry = allocate_cons();
- Cdr(new_entry) = popSTACK(); # entry bzw. Liste als CDR eintragen
- Car(new_entry) = popSTACK(); # Symbol als CAR eintragen
- sym = new_entry; # und dann new_entry eintragen
- }
- symtab = popSTACK();
- }
- TheSvector(Symtab_table(symtab))->data[index] = sym; # neue Entry eintragen
- Symtab_count(symtab) = fixnum_inc(Symtab_count(symtab),1); # (incf count)
- return symtab;
- }}
-
- # UP: Entfernt aus einer Symboltabelle ein darin vorkommendes Symbol.
- # symtab_delete(sym,symtab)
- # > sym: Symbol
- # > symtab: Symboltabelle
- local void symtab_delete (object sym, object symtab);
- local void symtab_delete(sym,symtab)
- var reg3 object sym;
- var reg4 object symtab;
- { var reg2 uintL index = # Index = Hashcode mod size
- (uintL)(string_hashcode(Symbol_name(sym)) % (uintW)(posfixnum_to_L(Symtab_size(symtab))));
- var reg2 object* entryptr = &TheSvector(Symtab_table(symtab))->data[index];
- var reg1 object entry = *entryptr; # entry in der table
- if (!(listp(entry)))
- # entry ist ein einzelnes Symbol
- { # sym und gefundenes Symbol gleich ?
- if (!eq(sym,entry)) { goto notfound; }
- # entry durch NIL ersetzen:
- *entryptr = NIL;
- }
- else
- # entry ist eine Symbolliste
- { while (consp(entry))
- { # sym und Symbol aus entry gleich ?
- if (eq(sym,Car(entry))) { goto found; }
- entryptr = &Cdr(entry); entry = *entryptr;
- }
- goto notfound; # nicht gefunden
- found: # gefunden als CAR von *entryptr = entry
- # -> ein Listenelement streichen:
- { *entryptr = Cdr(entry); } # entry durch Cdr(entry) ersetzen
- }
- # schließlich noch den Symbolzähler um 1 erniedrigen:
- Symtab_count(symtab) = fixnum_inc(Symtab_count(symtab),-1); # (decf count)
- return;
- # nicht gefunden
- notfound:
- pushSTACK(unbound); # "Wert" für Slot PACKAGE von PACKAGE-ERROR
- pushSTACK(sym);
- //: DEUTSCH "Symbol ~ kann nicht aus der Symboltabelle entfernt werden."
- //: ENGLISH "symbol ~ cannot be deleted from symbol table"
- //: FRANCAIS "Le symbole ~ ne peux pas être retiré de la table des symboles."
- fehler(package_error, GETTEXT("symbol ~ cannot be deleted from symbol table"));
- }
-
- # Datenstruktur der Package siehe LISPBIBL.D.
- # Komponenten:
- # pack_external_symbols Symboltabelle der extern präsenten Symbole
- # pack_internal_symbols Symboltabelle der intern präsenten Symbole
- # pack_shadowing_symbols Liste der Shadowing-Symbole
- # pack_use_list Use-List, eine Liste von Packages
- # pack_used_by_list Used-by-List, eine Liste von Packages
- # pack_name der Name, ein Simple-String
- # pack_nicknames die Nicknames, eine Liste von Simple-Strings
-
- # Konsistenzregeln:
- # 1. Alle Packages sind genau einmal in ALL_PACKAGES aufgeführt.
- # 2. Die Vereinigung über ALL_PACKAGES von {Name} U Nicknames ist disjunkt.
- # 3. Für je zwei Packages p,q gilt:
- # p in use_list(q) <==> q in used_by_list(q)
- # 4. p sei eine Package.
- # accessible(p) = ISymbols(p) U ESymbols(p) U
- # U {ESymbols(q) | q in use_list(p)}
- # 5. Für jede Package p ist
- # shadowing_symbols(p) eine Teilmenge von ISymbols(p) U ESymbols(p)
- # und damit auch eine Teilmenge von accessible(p).
- # 6. s sei ein String, p eine Package.
- # Ist die Menge der Symbole in accessible(p) mit dem Printnamen = s
- # mehr als einelementig,
- # so liegt genau eines dieser Symbole in shadowing_symbols(p).
- # 7. s sei ein String, p eine Package.
- # Es gibt höchstens ein Symbol mit dem Printnamen = s
- # in ISymbols(p) U ESymbols(p) .
- # 8. Ist s ein Symbol mit der Home-Package p /= NIL,
- # so ist s in ISymbols(p) U ESymbols(p) enthalten.
-
- # UP: Erzeugt eine neue Package, ohne auf Namenskonflikte zu testen.
- # make_package(name,nicknames)
- # > name: Name (ein Simple-String)
- # > nicknames: Nicknames (eine Liste von Simple-Strings)
- # < ergebnis: neue Package
- # kann GC auslösen
- local object make_package (object name, object nicknames);
- local object make_package(name,nicknames)
- var reg3 object name;
- var reg4 object nicknames;
- { set_break_sem_2();
- pushSTACK(nicknames); pushSTACK(name); # Nicknames und Namen retten
- # Tabelle für externe Symbole erzeugen:
- { var reg1 object symtab = make_symtab(11); pushSTACK(symtab); }
- # Tabelle für interne Symbole erzeugen:
- { var reg1 object symtab = make_symtab(63); pushSTACK(symtab); }
- # neue Package erzeugen:
- { var reg1 object pack = allocate_package();
- # und füllen:
- ThePackage(pack)->pack_internal_symbols = popSTACK();
- ThePackage(pack)->pack_external_symbols = popSTACK();
- ThePackage(pack)->pack_shadowing_symbols = NIL;
- ThePackage(pack)->pack_use_list = NIL;
- ThePackage(pack)->pack_used_by_list = NIL;
- ThePackage(pack)->pack_name = popSTACK();
- ThePackage(pack)->pack_nicknames = popSTACK();
- # und in ALL_PACKAGES einhängen:
- pushSTACK(pack);
- {var reg2 object new_cons = allocate_cons();
- pack = popSTACK();
- Car(new_cons) = pack; Cdr(new_cons) = O(all_packages);
- O(all_packages) = new_cons;
- # fertig:
- clr_break_sem_2();
- return pack;
- } }}
-
- # UP: Sucht ein Symbol gegebenen Printnamens in der Shadowing-Liste einer
- # Package.
- # shadowing_lookup(string,pack,&sym)
- # > string: String
- # > pack: Package
- # < ergebnis: TRUE, falls gefunden.
- # < sym: das Symbol aus der Shadowing-Liste, das den gegebenen Printnamen hat
- # (falls gefunden)
- local boolean shadowing_lookup (object string, object pack, object* sym_);
- local boolean shadowing_lookup(string,pack,sym_)
- var reg2 object string;
- var reg4 object pack;
- var reg3 object* sym_;
- { var reg1 object list = ThePackage(pack)->pack_shadowing_symbols;
- # Shadowing-Liste durchlaufen:
- while (consp(list))
- { if (string_gleich(string,Symbol_name(Car(list)))) { goto found; }
- list = Cdr(list);
- }
- return FALSE; # nicht gefunden
- found: # gefunden
- *sym_ = Car(list); return TRUE;
- }
-
- # UP: Sucht ein gegebenes Symbol in der Shadowing-Liste einer Package.
- # shadowing_find(sym,pack)
- # > sym: Symbol
- # > pack: Package
- # < ergebnis: TRUE falls gefunden.
- local boolean shadowing_find (object sym, object pack);
- local boolean shadowing_find(sym,pack)
- var reg2 object sym;
- var reg3 object pack;
- { var reg1 object list = ThePackage(pack)->pack_shadowing_symbols;
- # Shadowing-Liste durchlaufen:
- while (consp(list))
- { if (eq(sym,Car(list))) { goto found; }
- list = Cdr(list);
- }
- return FALSE; # nicht gefunden
- found: # gefunden
- return TRUE;
- }
-
- # UP: Fügt ein Symbol zur Shadowing-Liste einer Package, die noch kein
- # Symbol desselben Namens enthält, hinzu.
- # shadowing_insert(&sym,&pack)
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < sym: Symbol, EQ zum alten
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- local void shadowing_insert (object* sym_, object* pack_);
- local void shadowing_insert(sym_,pack_)
- var reg2 object* sym_;
- var reg3 object* pack_;
- { # neues Cons mit Symbol als CAR vor die Shadowing-Symbols einhängen:
- var reg1 object new_cons = allocate_cons();
- var reg2 object pack = *pack_;
- Car(new_cons) = *sym_;
- Cdr(new_cons) = ThePackage(pack)->pack_shadowing_symbols;
- ThePackage(pack)->pack_shadowing_symbols = new_cons;
- }
-
- # UP: Entfernt ein Symbol gegebenen Namens aus der Shadowing-Liste
- # einer Package.
- # shadowing_delete(string,pack)
- # > string: String
- # > pack: Package
- local void shadowing_delete (object string, object pack);
- local void shadowing_delete(string,pack)
- var reg3 object string;
- var reg4 object pack;
- { var reg2 object* listptr = &ThePackage(pack)->pack_shadowing_symbols;
- var reg1 object list = *listptr;
- # list = *listptr durchläuft die Shadowing-Liste
- while (consp(list))
- { if (string_gleich(string,Symbol_name(Car(list)))) { goto found; }
- listptr = &Cdr(list); list = *listptr;
- }
- # kein Symbol dieses Namens gefunden, fertig.
- return;
- found:
- # Gleichheit: entfernen. Danach ist man fertig, da es in der
- # Shadowing-Liste nur ein Symbol desselben Printnamens geben kann.
- *listptr = Cdr(list); # list durch Cdr(list) ersetzen
- return;
- }
-
- # UP: testet, ob ein Symbol in einer Package accessible ist und dabei nicht
- # von einem anderen Symbol desselben Namens verdeckt wird.
- # accessiblep(sym,pack)
- # > sym: Symbol
- # > pack: Package
- # < ergebnis: TRUE falls sym in pack accessible und nicht verdeckt ist,
- # FALSE sonst
- global boolean accessiblep (object sym, object pack);
- global boolean accessiblep(sym,pack)
- var reg2 object sym;
- var reg3 object pack;
- { # Methode:
- # Suche erst ein Symbol gleichen Namens in der Shadowing-Liste;
- # falls nicht gefunden, suche das Symbol unter den präsenten und dann
- # unter den vererbten Symbolen.
- # Andere mögliche Methode (hier nicht realisiert):
- # Ist die Home-Package von sym gleich pack, so ist sym in pack präsent,
- # fertig. Sonst suche ein präsentes Symbol gleichen Namens.
- # sym gefunden -> fertig.
- # Ein anderes gefunden -> sym ist nicht auf der Shadowing-Liste und
- # daher nicht sichtbar.
- # Keins gefunden -> Suche sym unter den vererbten Symbolen.
- var object shadowingsym;
- # Suche erst in der Shadowing-Liste von pack:
- if (shadowing_lookup(Symbol_name(sym),pack,&shadowingsym))
- { # shadowingsym = in der Shadowing-Liste gefundenes Symbol
- return (eq(shadowingsym,sym)); # mit sym vergleichen
- }
- else
- # Kein Symbol gleichen Namens in der Shadowing-Liste
- { # Suche unter den internen Symbolen:
- if (symtab_find(sym,ThePackage(pack)->pack_internal_symbols))
- goto found;
- # Suche unter den externen Symbolen:
- if (symtab_find(sym,ThePackage(pack)->pack_external_symbols))
- goto found;
- # Suche unter den externen Symbolen der Packages aus der Use-List:
- { var reg1 object list = ThePackage(pack)->pack_use_list;
- while (consp(list))
- { if (symtab_find(sym,ThePackage(Car(list))->pack_external_symbols))
- goto found;
- list = Cdr(list);
- }
- return FALSE; # nicht gefunden
- }
- found: # gefunden
- return TRUE;
- } }
-
- # UP: testet, ob ein Symbol in einer Package als externes Symbol accessible
- # ist.
- # externalp(sym,pack)
- # > sym: Symbol
- # > pack: Package
- # < ergebnis:
- # TRUE falls sym in pack als externes Symbol accessible ist,
- # (in diesem Falle ist sym nicht verdeckt, denn ein eventuell sym
- # vedeckendes Symbol müßte in shadowing-symbols(pack) aufgeführt sein,
- # nach den Konsistenzregeln 5 und 7 also mit sym identisch sein),
- # FALSE sonst
- global boolean externalp (object sym, object pack);
- global boolean externalp(sym,pack)
- var reg2 object sym;
- var reg1 object pack;
- { return symtab_find(sym,ThePackage(pack)->pack_external_symbols);
- }
-
- # UP: sucht ein externes Symbol gegebenen Printnamens in einer Package.
- # find_external_symbol(string,pack,&sym)
- # > string: String
- # > pack: Package
- # < ergebnis: TRUE, falls ein externes Symbol dieses Printnamens in pack gefunden.
- # < sym: dieses Symbol, falls gefunden.
- global boolean find_external_symbol (object string, object pack, object* sym_);
- global boolean find_external_symbol(string,pack,sym_)
- var reg2 object string;
- var reg3 object pack;
- var reg1 object* sym_;
- { return symtab_lookup(string,ThePackage(pack)->pack_external_symbols,&(*sym_)); }
-
- # UP: Nachfragefunktion an den Benutzer.
- # query_user(ml)
- # > ml: nichtleere Liste von Möglichkeiten. Jede Möglichkeit ist dabei eine
- # Liste aus einem Kurz-String (den der Benutzer eintippen soll), einem
- # Langstring (der der Erläuterung dient) und weiteren Informationen.
- # < ergebnis: Die vom Benutzer angewählte Möglichkeit.
- # kann GC auslösen
- local object query_user (object ml);
- local object query_user(ml)
- var reg5 object ml;
- { pushSTACK(ml);
- {var object stream = var_stream(S(query_io),strmflags_rd_ch_B|strmflags_wr_ch_B); # Stream *QUERY-IO*
- terpri(&stream); # Neue Zeile
- write_sstring(&stream,OL(query_string1)); # "Wählen Sie bitte aus:"
- # Möglichkeiten ausgeben:
- { var reg2 object mlistr = STACK_0; # restliche Möglichkeiten
- while (consp(mlistr))
- { pushSTACK(mlistr);
- terpri(&stream);
- write_sstring(&stream,O(query_string2)); # " "
- { var reg1 object moeglichkeit = Car(STACK_0); # nächste Möglichkeit
- pushSTACK(Car(Cdr(moeglichkeit))); # Langstring retten
- write_string(&stream,Car(moeglichkeit)); # Kurzstring ausgeben
- write_sstring(&stream,O(query_string3)); # " -- "
- write_string(&stream,popSTACK()); # Langstring ausgeben
- }
- mlistr = popSTACK();
- mlistr = Cdr(mlistr);
- } }
- terpri(&stream);
- terpri(&stream);
- # Benutzer-Antwort einlesen:
- loop
- { write_sstring(&stream,O(query_string7)); # "> "
- pushSTACK(stream); # Stream retten
- pushSTACK(stream); funcall(L(read_line),1); # (READ-LINE stream) aufrufen
- pushSTACK(value1); # Antwort retten
- # Stackaufbau: Möglichkeiten, Stream, Antwort
- # Antwort mit den Kurzstrings vergleichen:
- pushSTACK(STACK_2); # Möglichkeiten durchgehen
- while (mconsp(STACK_0))
- { pushSTACK(Car(Car(STACK_0))); # nächsten Kurzstring
- pushSTACK(STACK_2); # mit Antwort vergleichen:
- funcall(L(string_gleich),2); # (STRING= Kurzstring Antwort)
- if (!nullp(value1)) goto antwort_ok;
- STACK_0 = Cdr(STACK_0); # Möglichkeitenliste verkürzen
- }
- skipSTACK(1);
- # Antwort mit den Kurzstrings vergleichen, diesmal lascher:
- pushSTACK(STACK_2); # Möglichkeiten durchgehen
- while (mconsp(STACK_0))
- { pushSTACK(Car(Car(STACK_0))); # nächsten Kurzstring
- pushSTACK(STACK_2); # mit Antwort vergleichen:
- funcall(L(string_equal),2); # (STRING-EQUAL Kurzstring Antwort)
- if (!nullp(value1)) goto antwort_ok;
- STACK_0 = Cdr(STACK_0); # Möglichkeitenliste verkürzen
- }
- skipSTACK(1);
- skipSTACK(1); # Antwort vergessen
- stream = popSTACK(); # Stream zurück
- # bis jetzt immer noch keine korrekte Antwort
- write_sstring(&stream,OL(query_string4)); # "Wählen Sie bitte eines von "
- # Möglichkeiten ausgeben:
- { var reg2 object mlistr = STACK_0; # restliche Möglichkeiten
- while (consp(mlistr))
- { pushSTACK(mlistr);
- write_string(&stream,Car(Car(mlistr))); # Kurzstring ausgeben
- mlistr = popSTACK();
- mlistr = Cdr(mlistr);
- if (atomp(mlistr)) break;
- pushSTACK(mlistr);
- write_sstring(&stream,O(query_string5)); # ", "
- mlistr = popSTACK();
- } }
- write_sstring(&stream,OL(query_string6)); # " aus."
- terpri(&stream);
- }
- antwort_ok:
- { var reg1 object mlistr = popSTACK(); # letzte Möglichkeitenliste
- skipSTACK(3); # Antwort, Stream und Möglichkeitenliste vergessen
- return Car(mlistr); # angewählte Möglichkeit
- }}}
-
- # UP: sucht eine Package mit gegebenem Namen oder Nickname
- # find_package(string)
- # > string: String
- # < ergebnis: Package mit diesem Namen oder NIL
- global object find_package (object string);
- global object find_package(string)
- var reg2 object string;
- { var reg4 object packlistr = O(all_packages); # Package-Liste durchgehen
- var reg3 object pack;
- while (consp(packlistr))
- { pack = Car(packlistr); # zu testende Package
- # Teste Namen:
- if (string_gleich(string,ThePackage(pack)->pack_name)) goto found;
- # Teste Nicknamen:
- { var reg1 object nicknamelistr = ThePackage(pack)->pack_nicknames; # Nickname-Liste durchgehen
- while (consp(nicknamelistr))
- { if (string_gleich(string,Car(nicknamelistr))) goto found;
- nicknamelistr = Cdr(nicknamelistr);
- } }
- packlistr = Cdr(packlistr); # nächste Package
- }
- # nicht gefunden
- return NIL;
- found: # gefunden
- return pack;
- }
-
- # UP: Sucht ein Symbol gegebenen Printnamens in einer Package.
- # find_symbol(string,pack,&sym)
- # > string: String
- # > pack: Package
- # < sym: Symbol, falls gefunden; sonst NIL
- # < ergebnis: 0, wenn nicht gefunden
- # 1, wenn als externes Symbol vorhanden
- # 2, wenn vererbt über use-list
- # 3, wenn als internes Symbol vorhanden
- # + (-4, wenn in der Shadowing-Liste vorhanden)
- local sintBWL find_symbol (object string, object pack, object* sym_);
- local sintBWL find_symbol(string,pack,sym_)
- var reg4 object string;
- var reg5 object pack;
- var reg3 object* sym_;
- { # Suche erst in der Shadowing-Liste von pack:
- if (shadowing_lookup(string,pack,&(*sym_)))
- # *sym_ = in der Shadowing-Liste gefundenes Symbol
- { # Suche es unter den internen Symbolen:
- if (symtab_find(*sym_,ThePackage(pack)->pack_internal_symbols))
- { return 3-4; } # unter den internen Symbolen gefunden
- # Suche es unter den externen Symbolen:
- if (symtab_find(*sym_,ThePackage(pack)->pack_external_symbols))
- { return 1-4; } # unter den externen Symbolen gefunden
- # Widerspruch zur Konsistenzregel 5.
- pushSTACK(*sym_); pushSTACK(pack);
- //: DEUTSCH "Inkonsistenz in ~ : Symbol ~ ist zwar unter SHADOWING-SYMBOLS vorhanden, aber nicht präsent."
- //: ENGLISH "~ inconsistent: symbol ~ is a shadowing symbol but not present"
- //: FRANCAIS "Inconsistence dans ~ : Le symbole ~ est énuméré parmi les SHADOWING-SYMBOLS mais n'est pas présent."
- fehler(serious_condition, GETTEXT("~ inconsistent: symbol ~ is a shadowing symbol but not present"));
- }
- else
- # Symbol noch nicht gefunden
- { # Suche unter den internen Symbolen:
- if (symtab_lookup(string,ThePackage(pack)->pack_internal_symbols,&(*sym_)))
- { return 3; } # unter den internen Symbolen gefunden
- # Suche unter den externen Symbolen:
- if (symtab_lookup(string,ThePackage(pack)->pack_external_symbols,&(*sym_)))
- { return 1; } # unter den externen Symbolen gefunden
- # Suche unter den externen Packages aus der Use-List:
- { var reg2 object packlistr = ThePackage(pack)->pack_use_list;
- while (consp(packlistr))
- { var reg1 object usedpack = Car(packlistr);
- if (symtab_lookup(string,ThePackage(usedpack)->pack_external_symbols,&(*sym_)))
- { return 2; } # unter den vererbten Symbolen gefunden
- # (nur einmal vererbt, sonst wäre was in der
- # Shadowing-Liste gewesen)
- packlistr = Cdr(packlistr);
- } }
- # nicht gefunden
- *sym_ = NIL; return 0;
- } }
- # Eigentlich bräuchte man in der Shadowing-Liste erst zu suchen, nachdem
- # man die präsenten Symbole abgesucht hat, denn das Symbol in der
- # Shadowing-Liste ist ja präsent (Konsistenzregel 5).
-
- # UP: Fügt ein Symbol in eine Package ein, in der noch kein Symbol desselben
- # Namens existiert. Achtet nicht auf Konflikte.
- # make_present(sym,pack);
- # > sym: Symbol
- # > pack: Package
- # nur bei gesetzter BREAK_SEM_2 aufzurufen
- # kann GC auslösen
- local void make_present (object sym, object pack);
- local void make_present(sym,pack)
- var reg1 object sym;
- var reg2 object pack;
- { if (!eq(pack,O(keyword_package)))
- # Symbol in die internen Symbole einfügen:
- { symtab_insert(sym,ThePackage(pack)->pack_internal_symbols); }
- else
- # Symbol modifizieren und in die externen Symbole einfügen:
- { pushSTACK(sym);
- set_Symbol_value(STACK_0,STACK_0); # sym erhält sich selbst als Wert
- # als konstant und als Keyword markieren:
- TheSymbol(STACK_0)->header_flags |= (bit(constant_bit_hf) | bit(keyword_bit_hf));
- symtab_insert(STACK_0,ThePackage(pack)->pack_external_symbols);
- skipSTACK(1);
- } }
-
- # UP: Interniert ein Symbol gegebenen Printnamens in einer Package.
- # intern(string,pack,&sym)
- # > string: String
- # > pack: Package
- # < sym: Symbol
- # < ergebnis: 0, wenn nicht gefunden, sondern neu erzeugt
- # 1, wenn als externes Symbol vorhanden
- # 2, wenn vererbt über use-list
- # 3, wenn als internes Symbol vorhanden
- # kann GC auslösen
- global uintBWL intern (object string, object pack, object* sym_);
- global uintBWL intern(string,pack,sym_)
- var reg3 object string;
- var reg4 object pack;
- var reg2 object* sym_;
- { { var reg1 sintBWL ergebnis = find_symbol(string,pack,&(*sym_)); # suchen
- if (!(ergebnis==0)) { return ergebnis & 3; } # gefunden -> fertig
- }
- pushSTACK(pack); # Package retten
- string = coerce_imm_ss(string); # String in immutablen Simple-String umwandeln
- {var reg1 object sym = make_symbol(string); # (make-symbol string) ausführen
- pack = popSTACK();
- # dieses neue Symbol in die Package eintragen:
- set_break_sem_2(); # Vor Unterbrechungen schützen
- Symbol_package(sym) = pack; # Home-Package eintragen
- pushSTACK(sym); # Symbol retten
- make_present(sym,pack); # und in diese internieren
- *sym_ = popSTACK();
- clr_break_sem_2(); # Unterbrechungen wieder zulassen
- return 0;
- }}
-
- # UP: Interniert ein Symbol gegebenen Printnamens in der Keyword-Package.
- # intern_keyword(string)
- # > string: String
- # < ergebnis: Symbol, ein Keyword
- # kann GC auslösen
- global object intern_keyword (object string);
- global object intern_keyword(string)
- var reg1 object string;
- { var object sym;
- intern(string,O(keyword_package),&sym);
- return sym;
- }
-
- # UP: Importiert ein Symbol in eine Package und macht es zum Shadowing-Symbol.
- # Eventuell wird dazu ein anderes in dieser Package präsentes Symbol
- # desselben Namens uninterniert.
- # shadowing_import(&sym,&pack);
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < sym: Symbol, EQ zum alten
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- local void shadowing_import (object* sym_, object* pack_);
- local void shadowing_import(sym_,pack_)
- var reg3 object* sym_;
- var reg4 object* pack_;
- { set_break_sem_2(); # Vor Unterbrechungen schützen
- {var reg2 object sym = *sym_;
- var reg1 object pack = *pack_;
- # Suche ein internes oder ein externes Symbol gleichen Namens:
- var object othersym;
- var reg5 boolean i_found;
- var reg6 object string = Symbol_name(sym);
- pushSTACK(string); # String retten
- if ( (i_found = symtab_lookup(string,ThePackage(pack)->pack_internal_symbols,&othersym))
- || (symtab_lookup(string,ThePackage(pack)->pack_external_symbols,&othersym))
- )
- # ein Symbol othersym desselben Namens war schon präsent in der Package
- { if (!eq(othersym,sym)) # war es das zu importierende Symbol selbst?
- { # Nein -> muß othersym aus den internen bzw. aus den externen
- # Symbolen herausnehmen:
- symtab_delete(othersym,
- i_found ? ThePackage(pack)->pack_internal_symbols
- : ThePackage(pack)->pack_external_symbols
- );
- # Wurde dieses Symbol aus seiner Home-Package herausgenommen,
- # so muß seine Home-Package auf NIL gesetzt werden:
- if (eq(Symbol_package(othersym),pack))
- { Symbol_package(othersym) = NIL; }
- # Symbol sym muß in die Package pack neu aufgenommen werden.
- make_present(sym,pack);
- } }
- else
- # Symbol sym muß in die Package pack neu aufgenommen werden.
- make_present(sym,pack);
- }
- # Symbol muß in die Shadowing-Liste der Package aufgenommen werden.
- shadowing_delete(popSTACK(),*pack_); # String aus der Shadowing-Liste herausnehmen
- shadowing_insert(&(*sym_),&(*pack_)); # Symbol dafür in die Shadowing-Liste aufnehmen
- clr_break_sem_2(); # Unterbrechungen wieder zulassen
- }
-
- # UP: Überdeckt in einer Package alle aus anderen Packages accessiblen
- # Symbole gegebenen Namens durch ein in dieser Package präsentes Symbol
- # desselben Namens.
- # shadow(&sym,&pack)
- #ifdef X3J13_161
- # > sym: Symbol oder String (im STACK)
- #else
- # > sym: Symbol (im STACK)
- #endif
- # > pack: Package (im STACK)
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- local void shadow (object* sym_, object* pack_);
- local void shadow(sym_,pack_)
- var reg2 object* sym_;
- var reg3 object* pack_;
- { set_break_sem_2(); # Vor Unterbrechungen schützen
- {# Suche ein internes oder ein externes Symbol gleichen Namens:
- var reg4 object string = # Nur der Name des Symbols interessiert.
- #ifdef X3J13_161
- (msymbolp(*sym_) ? Symbol_name(*sym_) : coerce_imm_ss(*sym_));
- #else
- Symbol_name(*sym_);
- #endif
- var reg1 object pack = *pack_;
- pushSTACK(NIL); # Platz für othersym machen
- pushSTACK(string); # String retten
- if (!(symtab_lookup(string,ThePackage(pack)->pack_internal_symbols,&STACK_1)
- || symtab_lookup(string,ThePackage(pack)->pack_external_symbols,&STACK_1)
- ) )
- # nicht gefunden -> neues Symbol desselben Namens erzeugen:
- { var reg1 object othersym = make_symbol(STACK_0); # neues Symbol
- STACK_1 = othersym;
- make_present(othersym,*pack_); # in die Package eintragen
- Symbol_package(STACK_1) = *pack_; # Home-Package des neuen Symbols sei pack
- } }
- # Stackaufbau: othersym, string
- # In der Package ist nun das Symbol othersym desselben Namens präsent.
- shadowing_delete(popSTACK(),*pack_); # String aus der Shadowing-Liste herausnehmen
- shadowing_insert(&STACK_0,&(*pack_)); # othersym dafür in die Shadowing-Liste aufnehmen
- skipSTACK(1); # othersym vergessen
- clr_break_sem_2(); # Unterbrechungen wieder zulassen
- }
-
- # UP: Entfernt ein Symbol aus der Menge der präsenten Symbole einer Package
- # und sorgt für Konfliktauflösung für den Fall, daß es in der Shadowing-List
- # dieser Package war und deswegen ein Namenskonflikt entsteht.
- # unintern(&sym,&pack)
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < sym: Symbol, EQ zum alten
- # < pack: Package, EQ zur alten
- # < ergebnis: T wenn gefunden und gelöscht, NIL falls nichts getan.
- # kann GC auslösen
- local object unintern (object* sym_, object* pack_);
- local object unintern(sym_,pack_)
- var reg3 object* sym_;
- var reg4 object* pack_;
- { var reg2 object sym = *sym_;
- var reg1 object pack = *pack_;
- var reg5 object symtab;
- # sym unter den internen und den externen Symbolen suchen:
- if (symtab_find(sym,symtab=ThePackage(pack)->pack_internal_symbols)
- || symtab_find(sym,symtab=ThePackage(pack)->pack_external_symbols)
- )
- { # Symbol sym in der Tabelle symtab gefunden
- if (shadowing_find(sym,pack)) # in der Shadowing-Liste suchen
- # möglicher Konflikt -> Auswahlliste aufbauen:
- { pushSTACK(symtab); # Symboltabelle retten
- pushSTACK(NIL); # Möglichkeitenliste anfangen
- pushSTACK(ThePackage(pack)->pack_use_list); # Use-List durchgehen
- # Stackaufbau: Symboltabelle, ML, Use-List-Rest
- while (mconsp(STACK_0))
- { var object othersym;
- pack = Car(STACK_0); # Package aus der Use-List
- STACK_0 = Cdr(STACK_0);
- # vererbtes Symbol gleichen Namens suchen:
- if (symtab_lookup(Symbol_name(*sym_),ThePackage(pack)->pack_external_symbols,&othersym))
- # othersym ist ein Symbol gleichen Namens, aus pack vererbt
- { var reg1 object temp;
- pushSTACK(temp=ThePackage(pack)->pack_name); # Name von pack
- pushSTACK(othersym); # Symbol
- pushSTACK(OL(unint_string1)); # "Symbol "
- pushSTACK(Symbol_name(othersym)); # Symbolname
- pushSTACK(OL(unint_string2)); # " aus #<PACKAGE "
- pushSTACK(temp); # Packagename
- pushSTACK(OL(unint_string3)); # "> wird als Shadowing deklariert"
- temp = string_concat(5); # (STRING-CONCAT "..." Symbolname "..." Packagename "...")
- pushSTACK(temp); # Gesamtstring
- temp = allocate_cons(); Car(temp) = STACK_1;
- STACK_1 = temp; # (list othersym)
- temp = allocate_cons(); Car(temp) = popSTACK(); Cdr(temp) = popSTACK();
- pushSTACK(temp); # (list Gesamtstring othersym)
- temp = allocate_cons(); Cdr(temp) = popSTACK(); Car(temp) = popSTACK();
- # temp = (list Packagename Gesamtstring othersym)
- # STACK stimmt wieder
- # auf die Möglichkeitenliste pushen:
- pushSTACK(temp);
- temp = allocate_cons();
- Car(temp) = popSTACK(); Cdr(temp) = STACK_1;
- STACK_1 = temp;
- } }
- skipSTACK(1);
- # Möglichkeitenliste fertig aufgebaut.
- # Stackaufbau: Symboltabelle, ML
- # Falls (length ML) >= 2, liegt ein Konflikt vor:
- if (mconsp(STACK_0) && mconsp(Cdr(STACK_0)))
- # Continuable Error auslösen:
- { pushSTACK(OL(unint_string4)); # "Sie dürfen auswählen..."
- pushSTACK(OL(unint_string5)); # "Durch Uninternieren von ~S aus ~S ..."
- pushSTACK(*sym_); # Symbol
- pushSTACK(*pack_); # Package
- funcall(S(cerror),4); # (CERROR "..." "..." Symbol Package)
- STACK_0 = query_user(STACK_0); # Auswahl erfragen
- }
- else
- { STACK_0 = NIL; }
- # STACK_0 ist die Auswahl (NIL falls kein Konflikt entsteht)
- # Stackaufbau: Symboltabelle, Auswahl
- set_break_sem_3();
- { var reg1 object sym = *sym_;
- var reg2 object pack = *pack_;
- # Symbol aus der Symboltabelle entfernen:
- symtab_delete(sym,STACK_1);
- # Falls es aus seiner Home-Package entfernt wurde,
- # setze die Home-Package auf NIL:
- if (eq(Symbol_package(sym),pack))
- { Symbol_package(sym) = NIL; }
- # Symbol aus Shadowing-Liste streichen:
- shadowing_delete(Symbol_name(sym),pack);
- }
- { var reg1 object auswahl = popSTACK(); # Auswahl
- if (!nullp(auswahl))
- # im Konfliktfalle: angewähltes Symbol importieren:
- { pushSTACK(Car(Cdr(Cdr(auswahl))));
- shadowing_import(&STACK_0,&(*pack_));
- skipSTACK(1);
- } }
- skipSTACK(1); # Symboltabelle vergessen
- clr_break_sem_3();
- return T; # Das war's
- }
- else
- # kein Konflikt
- { set_break_sem_2();
- symtab_delete(sym,symtab); # Symbol löschen
- if (eq(Symbol_package(sym),pack))
- { Symbol_package(sym) = NIL; } # evtl. Home-Package auf NIL setzen
- clr_break_sem_2();
- return T;
- }
- }
- else
- # nicht gefunden
- { return NIL; }
- }
-
- # UP: Importiert ein Symbol in eine Package und sorgt für Konfliktauflösung
- # für den Fall, daß ein Namenskonflikt entweder mit einem aus einer anderen
- # Package vererbten Symbol oder mit einem bereits in dieser Package präsenten
- # Symbol desselben Namens entsteht.
- # import(&sym,&pack);
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- global void import (object* sym_, object* pack_);
- global void import(sym_,pack_)
- var reg3 object* sym_;
- var reg4 object* pack_;
- { var reg2 object sym = *sym_;
- var reg1 object pack = *pack_;
- var reg3 object string = Symbol_name(sym);
- var object othersym;
- var reg5 object othersymtab;
- # Symbol gleichen Namens unter den internen und den externen Symbolen suchen:
- if (symtab_lookup(string,othersymtab=ThePackage(pack)->pack_internal_symbols,&othersym)
- || symtab_lookup(string,othersymtab=ThePackage(pack)->pack_external_symbols,&othersym)
- )
- # othersym = Symbol desselben Namens, gefunden in othersymtab
- { if (eq(othersym,sym))
- # dasselbe Symbol -> nichts tun
- { return; }
- # nicht dasselbe Symbol war präsent -> muß othersym rauswerfen und
- # dafür das gegebene Symbol sym reinsetzen.
- # Zuvor feststellen, ob zusätzlich noch vererbte Symbole da sind,
- # und dann Continuable Error melden.
- pushSTACK(string);
- pushSTACK(othersym);
- pushSTACK(othersymtab);
- # erst Inherited-Flag berechnen:
- pushSTACK(ThePackage(pack)->pack_use_list); # Use-List wird abgesucht
- while (mconsp(STACK_0))
- { var object otherusedsym;
- var reg1 object usedpack = Car(STACK_0);
- STACK_0 = Cdr(STACK_0);
- # Symbol gleichen Namens in usedpack suchen:
- if (symtab_lookup(string,ThePackage(usedpack)->pack_external_symbols,&otherusedsym))
- { STACK_0 = T; break; } # gefunden -> inherited-Flag := T
- } # sonst ist am Schluß inherited-Flag = STACK_0 = NIL
- # Stackaufbau: Symbol-Name, othersym, othersymtab, inherited-Flag.
- # Continuable Error melden:
- { pushSTACK(OL(import_string1)); # "Sie dürfen über das weitere Vorgehen entscheiden."
- pushSTACK(nullp(STACK_1) # bei inherited=NIL die kurze Meldung
- ? OL(import_string2) # "Durch Importieren von ~S in ~S entsteht ein Namenskonflikt mit ~S."
- : OL(import_string3) # "Durch Importieren von ~S in ~S ... Namenskonflikt mit ~S und weiteren Symbolen."
- );
- pushSTACK(sym); # Symbol
- pushSTACK(pack); # Package
- pushSTACK(STACK_6); # othersym
- # vom Typ package_error??
- funcall(S(cerror),5); # (CERROR String1 String2/3 sym pack othersym)
- }
- # Antwort vom Benutzer erfragen:
- { var reg2 object ml = # Möglichkeitenliste (("I" ... T) ("N" ... NIL))
- (nullp(STACK_0) ? OL(import_list1) : OL(import_list2));
- var reg1 object antwort = query_user(ml);
- if (nullp(Car(Cdr(Cdr(antwort))))) # NIL-Möglichkeit angewählt?
- { skipSTACK(4); return; } # ja -> nicht importieren, fertig
- }
- # Importieren:
- set_break_sem_2();
- pack = *pack_;
- # othersym aus pack entfernen:
- { var reg1 object othersym = STACK_2;
- symtab_delete(othersym,STACK_1); # othersym aus othersymtab entfernen
- if (eq(Symbol_package(othersym),pack))
- { Symbol_package(othersym) = NIL; } # evtl. Home-Package := NIL
- }
- # sym in pack einfügen:
- make_present(*sym_,pack);
- # Symbole gleichen Namens aus der Shadowing-List von pack entfernen:
- shadowing_delete(STACK_3,*pack_);
- # Falls inherited-Flag, sym in pack zum Shadowing-Symbol machen:
- if (!nullp(STACK_0))
- { shadowing_insert(&(*sym_),&(*pack_)); }
- clr_break_sem_2();
- skipSTACK(4); return;
- }
- else
- # Kein Symbol desselben Namens war präsent.
- # Suche ein Symbol desselben Namens, das vererbt ist (es gibt
- # nach den Konsistenzregeln 6 und 5 höchstens ein solches):
- { var object otherusedsym;
- { pushSTACK(ThePackage(pack)->pack_use_list); # Use-List wird abgesucht
- while (mconsp(STACK_0))
- { var reg1 object usedpack = Car(STACK_0);
- STACK_0 = Cdr(STACK_0);
- # Symbol gleichen Namens in usedpack suchen:
- if (symtab_lookup(string,ThePackage(usedpack)->pack_external_symbols,&otherusedsym))
- goto inherited_found;
- }
- skipSTACK(1);
- # Kein Symbol desselben Namens war accessible.
- # sym kann daher gefahrlos importiert werden.
- goto import_sym;
- }
- inherited_found: # gefunden.
- skipSTACK(1);
- # Wurde genau das gegebene Symbol gefunden?
- if (eq(otherusedsym,sym))
- goto import_sym; # ja -> importieren
- # nein -> Continuable Error melden und Benutzer fragen:
- { pushSTACK(OL(import_string1)); # "Sie dürfen über das weitere Vorgehen entscheiden."
- pushSTACK(OL(import_string2)); # "Durch Importieren von ~S in ~S entsteht ein Namenskonflikt mit ~S."
- pushSTACK(sym); # Symbol
- pushSTACK(pack); # Package
- pushSTACK(otherusedsym); # otherusedsym
- funcall(S(cerror),5); # (CERROR String1 String2 sym pack otherusedsym)
- }
- { var reg1 object antwort = query_user(OL(import_list3));
- if (nullp(Car(Cdr(Cdr(antwort))))) # NIL-Möglichkeit angewählt?
- { return; } # ja -> nicht importieren, fertig
- }
- # Importieren:
- set_break_sem_2();
- # sym in pack einfügen:
- make_present(*sym_,*pack_);
- # sym in pack zum Shadowing-Symbol machen:
- shadowing_insert(&(*sym_),&(*pack_));
- clr_break_sem_2(); return;
- import_sym:
- # sym einfach in pack einfügen:
- set_break_sem_2();
- make_present(sym,pack);
- clr_break_sem_2(); return;
- }
- }
-
- # UP: Setzt ein Symbol vom externen auf den internen Status in einer Package
- # zurück.
- # unexport(&sym,&pack);
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- local void unexport (object* sym_, object* pack_);
- local void unexport(sym_,pack_)
- var reg3 object* sym_;
- var reg4 object* pack_;
- { var reg2 object sym = *sym_;
- var reg1 object pack = *pack_;
- var reg3 object symtab;
- if (symtab_find(sym,symtab=ThePackage(pack)->pack_external_symbols))
- # sym ist in pack extern
- { if (eq(pack,O(keyword_package))) # auf Keyword-Package testen
- { pushSTACK(pack); # Wert für Slot PACKAGE von PACKAGE-ERROR
- pushSTACK(pack);
- //: DEUTSCH "UNEXPORT ist in ~ nicht zulässig."
- //: ENGLISH "UNEXPORT in ~ is illegal"
- //: FRANCAIS "UNEXPORT n'est pas permis dans ~."
- fehler(package_error, GETTEXT("UNEXPORT in ~ is illegal"));
- }
- set_break_sem_2();
- symtab_delete(sym,symtab); # sym aus den externen Symbolen entfernen
- symtab_insert(sym,ThePackage(pack)->pack_internal_symbols); # dafür in die internen Symbole einfügen
- clr_break_sem_2();
- }
- else
- # Suchen, ob das Symbol überhaupt accessible ist.
- { # Suche unter den internen Symbolen:
- if (symtab_find(sym,ThePackage(pack)->pack_internal_symbols))
- goto found;
- # Suche unter den externen Symbolen der Packages aus der Use-List:
- { var reg1 object list = ThePackage(pack)->pack_use_list;
- while (consp(list))
- { if (symtab_find(sym,ThePackage(Car(list))->pack_external_symbols))
- goto found;
- list = Cdr(list);
- } }
- # nicht gefunden unter den accessiblen Symbolen
- { pushSTACK(pack); # Wert für Slot PACKAGE von PACKAGE-ERROR
- pushSTACK(pack); pushSTACK(sym);
- //: DEUTSCH "UNEXPORT ist nur auf accessiblen Symbolen möglich, nicht auf Symbol ~ in ~."
- //: ENGLISH "UNEXPORT works only on accessible symbols, not on ~ in ~"
- //: FRANCAIS "UNEXPORT n'est possible que pour des symboles accessibles mais pas pour le symbole ~ dans ~."
- fehler(package_error, GETTEXT("UNEXPORT works only on accessible symbols, not on ~ in ~"));
- }
- found: # gefunden unter den nicht-externen accessiblen Symbolen
- return; # nichts zu tun
- } }
-
- # UP: Setzt ein präsentes Symbol auf externen Status.
- # make_external(sym,pack);
- # > sym: Symbol
- # > pack: Package, in der das Symbol präsent ist
- # kann GC auslösen
- local void make_external (object sym, object pack);
- local void make_external(sym,pack)
- var reg2 object sym;
- var reg1 object pack;
- { if (symtab_find(sym,ThePackage(pack)->pack_external_symbols))
- { return; } # Symbol bereits extern -> nichts zu tun
- set_break_sem_2();
- symtab_delete(sym,ThePackage(pack)->pack_internal_symbols); # sym aus den internen Symbolen entfernen
- symtab_insert(sym,ThePackage(pack)->pack_external_symbols); # dafür in die externen Symbole einfügen
- clr_break_sem_2();
- }
-
- # UP: Exportiert ein Symbol aus einer Package
- # export(&sym,&pack);
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < sym: Symbol, EQ zum alten
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- global void export (object* sym_, object* pack_);
- global void export(sym_,pack_)
- var reg3 object* sym_;
- var reg4 object* pack_;
- { var reg2 object sym = *sym_;
- var reg1 object pack = *pack_;
- # sym unter den externen Symbolen von pack suchen:
- if (symtab_find(sym,ThePackage(pack)->pack_external_symbols))
- { return; } # gefunden -> fertig
- { var reg6 boolean import_it = FALSE;
- # import_it = Flag, ob Symbol erst noch importiert werden muß.
- # sym unter den internen Symbolen von pack suchen:
- if (!(symtab_find(sym,ThePackage(pack)->pack_internal_symbols)))
- # Symbol sym ist nicht präsent in Package pack
- { import_it = TRUE;
- # Suche, ob es wenigstens accessible ist:
- { var reg1 object list = ThePackage(pack)->pack_use_list;
- while (consp(list))
- { if (symtab_find(sym,ThePackage(Car(list))->pack_external_symbols))
- goto found;
- list = Cdr(list);
- } }
- # Symbol sym ist nicht einmal accessible in der Package pack
- # Continuable Error melden:
- { pushSTACK(OL(export_string1)); # "Sie dürfen über das weitere Vorgehen entscheiden."
- pushSTACK(OL(export_string2)); # "Symbol ~S müßte erst in ~S importiert werden, bevor es exportiert werden kann."
- pushSTACK(sym); # Symbol
- pushSTACK(pack); # Package
- # vom Typ package_error??
- funcall(S(cerror),4); # (CERROR "Sie dürfen aussuchen, ..." "..." Symbol Package)
- }
- # beim Benutzer nachfragen:
- { var reg1 object antwort = query_user(OL(export_list1));
- if (nullp(Car(Cdr(Cdr(antwort))))) # NIL-Möglichkeit angewählt?
- { return; } # ja -> nicht exportieren, fertig
- }
- found: ;
- }
- # Nun auf Namensfonflikte testen:
- pushSTACK(NIL); # Conflict-Resolver:=NIL
- # Stackaufbau: Conflict-Resolver (eine Liste von Paaren (sym . pack),
- # auf die shadowing_import angewandt werden muß).
- pushSTACK(ThePackage(*pack_)->pack_used_by_list); # Used-By-List wird abgesucht
- while (mconsp(STACK_0))
- { var reg1 object usingpack = Car(STACK_0); # USEnde Package
- STACK_0 = Cdr(STACK_0);
- {var object othersym;
- if (find_symbol(Symbol_name(*sym_),usingpack,&othersym) > 0)
- # othersym ist ein Symbol desselben Namens in usingpack
- if (!eq(othersym,*sym_))
- # es ist nicht sym selbst -> es liegt ein Konflikt vor
- { pushSTACK(othersym); pushSTACK(usingpack);
- # Stackaufbau: Conflict-Resolver, Used-by-list-Rest,
- # anderes Symbol, USEnde Package.
- # Continuable Error melden:
- { pushSTACK(OL(export_string3)); # "Sie dürfen aussuchen, welches Symbol Vorrang hat."
- pushSTACK(OL(export_string4)); # "Durch Exportieren von ~S aus ~S ... Namenskonflikt mit ~S in ~S."
- pushSTACK(*sym_); # Symbol
- pushSTACK(*pack_); # Package
- pushSTACK(othersym); # anderes Symbol
- pushSTACK(usingpack); # USEnde Package
- funcall(S(cerror),6); # (CERROR "..." "..." sym pack othersym usingpack)
- }
- # Einleitung ausgeben:
- { var object stream = var_stream(S(query_io),strmflags_rd_ch_B|strmflags_wr_ch_B); # Stream *QUERY-IO*
- terpri(&stream); # Neue Zeile
- write_sstring(&stream,OL(export_string5)); # "Welches Symbol soll in "
- prin1(&stream,STACK_0); # usingpack ausgeben
- write_sstring(&stream,OL(export_string6)); # " Vorrang haben?"
- }
- # Möglichkeitenliste konstruieren:
- { var reg1 object temp;
- pushSTACK(O(export_string7)); # "1"
- pushSTACK(OL(export_string9)); # "Das zu exportierende Symbol "
- pushSTACK(*sym_); # Symbol
- funcall(L(prin1_to_string),1); # (prin1-to-string Symbol)
- pushSTACK(value1);
- temp = string_concat(2); # (string-concat "Das zu exportierende Symbol " (prin1-to-string Symbol))
- pushSTACK(temp);
- pushSTACK(T);
- temp = listof(3); # (list "1" (string-concat ...) 'T)
- pushSTACK(temp);
- pushSTACK(O(export_string8)); # "2"
- pushSTACK(OL(export_string10)); # "Das alte Symbol "
- pushSTACK(STACK_4); # anderes Symbol
- funcall(L(prin1_to_string),1); # (prin1-to-string anderesSymbol)
- pushSTACK(value1);
- temp = string_concat(2); # (string-concat "Das alte Symbol " (prin1-to-string anderesSymbol))
- pushSTACK(temp);
- pushSTACK(NIL);
- temp = listof(3); # (list "2" (string-concat ...) 'NIL)
- pushSTACK(temp);
- temp = listof(2); # (list (list "1" ... 'T) (list "2" ... 'NIL))
- # Beim Benutzer nachfragen:
- { var reg2 object antwort = query_user(temp);
- var reg3 object solvingsym =
- (!(nullp(Car(Cdr(Cdr(antwort))))) # NIL-Möglichkeit angewählt?
- ? *sym_ # nein -> sym
- : STACK_1 # ja -> othersym
- );
- pushSTACK(solvingsym); # ausgewähltes Symbol
- }
- # Conflict-Resolver um (solvingsym . usingpack) erweitern:
- temp = allocate_cons();
- Car(temp) = popSTACK(); # solvingsym
- Cdr(temp) = popSTACK(); # usingpack
- # temp = (cons solvingsym usingpack)
- # vor Conflict-Resolver davorconsen:
- STACK_0 = temp;
- temp = allocate_cons();
- Car(temp) = popSTACK(); # (solvingsym . usingpack)
- Cdr(temp) = STACK_1;
- STACK_1 = temp;
- }
- # Stackaufbau: Conflict-Resolver, Used-by-list-Rest.
- }} }
- skipSTACK(1);
- # Stackaufbau: Conflict-Resolver.
- # Nun evtl. Symbol sym importieren:
- if (import_it)
- { # sym in pack importieren:
- import(&(*sym_),&(*pack_));
- # Dieses Importieren kann durch einen CERROR abgebrochen werden.
- # Ein Abbruch an dieser Stelle ist ungefährlich, denn bis jetzt
- # ist das Symbol nur intern in der Package (außer falls es sich
- # um das KEYWORD-Package handelt, das nicht geUSEd werden kann).
- }
- set_break_sem_3(); # gegen Unterbrechungen schützen
- # Nun die Konflikte auflösen:
- while (mconsp(STACK_0))
- { var reg1 object cons_sym_pack = Car(STACK_0);
- STACK_0 = Cdr(STACK_0);
- pushSTACK(Car(cons_sym_pack)); # solvingsym
- pushSTACK(Cdr(cons_sym_pack)); # usingpack
- shadowing_import(&STACK_1,&STACK_0); # importieren und shadowen
- skipSTACK(2);
- }
- skipSTACK(1);
- make_external(*sym_,*pack_); # sym in pack extern machen
- clr_break_sem_3(); # Unterbrechungen wieder freigeben
- } }
-
- # UP: Wendet eine Funktion auf alle Symbole einer Symboltabelle an.
- # (Diese Funktion darf im Extremfall das Symbol mittels symtab_delete
- # aus der Tabelle herausnehmen.)
- # map_symtab(fun,symtab);
- # > fun: Funktion mit einem Argument
- # > symtab: Symboltabelle
- # kann GC auslösen
- local void map_symtab (object fun, object symtab);
- local void map_symtab(fun,symtab)
- var reg5 object fun;
- var reg4 object symtab;
- { pushSTACK(fun); # Funktion
- pushSTACK(Symtab_table(symtab)); # Tabellenvektor
- {var uintL size = posfixnum_to_L(Symtab_size(symtab)); # Anzahl der Einträge
- var reg3 object* offset = 0; # offset = sizeof(object)*index
- var reg2 uintC count;
- dotimespC(count,size,
- { var reg1 object entry = # Eintrag mit Nummer index in table
- *(object*)(pointerplus(&TheSvector(STACK_0)->data[0],(aint)offset));
- if (atomp(entry))
- { if (!(nullp(entry)))
- # entry ist ein Symbol /= NIL
- { pushSTACK(entry); funcall(STACK_2,1); } # Funktion anwenden
- }
- else
- # nichtleere Symbolliste abarbeiten
- { pushSTACK(entry);
- do { var reg1 object listr = STACK_0;
- STACK_0 = Cdr(listr);
- pushSTACK(Car(listr)); funcall(STACK_3,1); # Funktion auf Symbol anwenden
- }
- until (matomp(STACK_0));
- skipSTACK(1);
- }
- offset++;
- });
- skipSTACK(2);
- }}
-
- # UP: Bewirkt, daß alle externen Symbole einer gegebenen Liste von Packages
- # implizit accessible in einer gegebenen Package werden.
- # use_package(packlist,pack);
- # > packlist: Liste von Packages, die zu USEn sind
- # > pack: Package
- # Die Liste packlist wird dabei zerstört!
- # kann GC auslösen
- local void use_package (object packlist, object pack);
- local object* use_package_local; # Pointer auf drei lokale Variablen
- local void use_package(packlist,pack)
- var object packlist;
- var reg5 object pack;
- { # packlist := (delete-duplicates packlist :test #'eq) :
- { var reg4 object packlist1 = packlist;
- while (consp(packlist1))
- { var reg3 object to_delete = Car(packlist1);
- # Entferne to_delete destruktiv aus (cdr packlist1) :
- var reg2 object packlist2 = packlist1; # läuft ab packlist1
- var reg1 object packlist3; # stets = (cdr packlist2)
- while (consp(packlist3=Cdr(packlist2)))
- { if (eq(Car(packlist3),to_delete))
- # streiche (car packlist3) destruktiv aus der Liste:
- { Cdr(packlist2) = Cdr(packlist3); }
- else
- # weiterrücken:
- { packlist2 = packlist3; }
- }
- packlist1 = Cdr(packlist1);
- } }
- # Entferne aus packlist alle die Packages, die gleich pack sind
- # oder bereits in der Use-List von pack vorkommen:
- { var reg4 object* packlistr_ = &packlist;
- var reg3 object packlistr = *packlistr_;
- # packlistr läuft durch packlist, packlistr = *packlistr_
- while (consp(packlistr))
- { # Teste, ob (car packlistr) gestrichen werden muß:
- var reg2 object pack_to_test = Car(packlistr);
- if (eq(pack_to_test,pack))
- goto delete_pack_to_test;
- { var reg1 object usedpacklistr = ThePackage(pack)->pack_use_list;
- while (consp(usedpacklistr))
- { if (eq(pack_to_test,Car(usedpacklistr)))
- goto delete_pack_to_test;
- usedpacklistr = Cdr(usedpacklistr);
- } }
- if (TRUE)
- # nichts streichen, weiterrücken:
- { packlistr_ = &Cdr(packlistr); packlistr = *packlistr_; }
- else
- # streiche (car packlistr) :
- { delete_pack_to_test:
- packlistr = *packlistr_ = Cdr(packlistr);
- }
- } }
- # Konfliktliste aufbauen.
- # Dabei ist ein Konflikt eine mindestens zweielementige Liste
- # von Symbolen gleichen Printnamens, zusammen mit der Package,
- # aus der dieses Symbol genommen wird:
- # ((pack1 . sym1) ...) bedeutet, daß bei Ausführung des USE-PACKAGE
- # die Symbole sym1,... (aus pack1 etc.) sich um die Sichtbarkeit in
- # Package pack streiten würden.
- # Die Konfliktliste ist die Liste aller auftretenden Konflikte.
- { pushSTACK(pack); # Package pack retten
- pushSTACK(packlist); # Liste zu USEnder Packages retten
- pushSTACK(NIL); # (bisher leere) Konfliktliste
- # Stackaufbau: pack, packlist, conflicts.
- use_package_local = &STACK_0; # zeigt auf die drei lokalen Variablen
- # Packageliste durchgehen:
- { pushSTACK(packlist);
- while (mconsp(STACK_0))
- { var reg1 object pack_to_use = Car(STACK_0);
- STACK_0 = Cdr(STACK_0);
- # #'use_package_aux auf alle externen Symbole von pack_to_use anwenden:
- map_symtab(L(use_package_aux),ThePackage(pack_to_use)->pack_external_symbols);
- }
- skipSTACK(1);
- }
- # Konfliktliste umbauen: Jeder Konflikt ((pack1 . sym1) ...) wird
- # umgeformt zu (("1" packname1 . sym1) ...).
- { pushSTACK(STACK_0); # Konfliktliste durchgehen
- while (mconsp(STACK_0))
- { var reg4 object conflict = Car(STACK_0);
- STACK_0 = Cdr(STACK_0);
- pushSTACK(conflict); # Konflikt durchgehen
- { var reg5 object counter = Fixnum_0; # Zähler := 0
- while (mconsp(STACK_0))
- { counter = fixnum_inc(counter,1); # Zähler um 1 erhöhen
- pushSTACK(counter); funcall(L(prin1_to_string),1); # (prin1-to-string Zähler)
- pushSTACK(value1); # Zählerstring retten
- { var reg2 object new_cons = allocate_cons(); # neues Cons
- Car(new_cons) = popSTACK(); # Zählerstring als CAR
- {var reg1 object old_cons = Car(STACK_0); # Cons der Form (pack . sym)
- Car(old_cons) = ThePackage(Car(old_cons))->pack_name; # pack durch seinen Namen ersetzen
- Cdr(new_cons) = old_cons; Car(STACK_0) = new_cons; # Zählerstring-Cons einfügen
- }}
- STACK_0 = Cdr(STACK_0);
- } }
- skipSTACK(1);
- }
- skipSTACK(1);
- }
- # Konflikt-Liste fertig.
- pushSTACK(NIL); # Conflict-Resolver := NIL
- # Stackaufbau: pack, packlist, conflicts, conflict-resolver.
- # Konflikte durch Benutzerfragen behandeln:
- if (!(nullp(STACK_1))) # nur bei conflicts/=NIL nötig
- { # Continuable Error melden:
- { pushSTACK(OL(usepack_string1)); # "Sie dürfen bei jedem Konflikt ..."
- pushSTACK(OL(usepack_string2)); # "~S Namenskonflikte bei USE-PACKAGE von ~S in die Package ~S."
- pushSTACK(fixnum(llength(STACK_3))); # (length conflicts)
- pushSTACK(STACK_5); # packlist
- pushSTACK(STACK_7); # pack
- funcall(S(cerror),5); # (CERROR "..." "..." (length conflicts) usedpacks pack)
- }
- { pushSTACK(STACK_1); # conflicts durchgehen
- while (mconsp(STACK_0))
- { pushSTACK(Car(STACK_0)); # conflict
- {var object stream = var_stream(S(query_io),strmflags_rd_ch_B|strmflags_wr_ch_B); # Stream *QUERY-IO*
- terpri(&stream); # Neue Zeile
- write_sstring(&stream,OL(usepack_string3)); # "Welches Symbol mit dem Namen "
- # (cdr (cdr (car conflict))) = (cdr (cdr '("1" packname1 . sym1))) = sym1
- prin1(&stream,Symbol_name(Cdr(Cdr(Car(STACK_0))))); # Name davon ausgeben
- write_sstring(&stream,OL(usepack_string4)); # " soll in "
- prin1(&stream,STACK_5); # pack ausgeben
- write_sstring(&stream,OL(usepack_string5)); # " Vorrang haben?"
- }
- # Beim Benutzer nachfragen,
- # mit conflict als Möglichkeitenliste:
- {var reg2 object antwort = query_user(popSTACK());
- # Davon das Symbol nehmen und in den conflict-resolver stecken:
- pushSTACK(Cdr(Cdr(antwort))); # sym
- }
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK(); # sym
- Cdr(new_cons) = STACK_1; # conflict-resolver
- STACK_1 = new_cons; # conflict-resolver := (cons sym conflict-resolver)
- }
- STACK_0 = Cdr(STACK_0); # restliche Konfliktliste verkürzen
- }
- skipSTACK(1);
- } }
- # Stackaufbau: pack, packlist, conflicts, conflict-resolver.
- # Konflikte auflösen:
- { set_break_sem_3();
- # conflict-resolver durchgehen:
- while (mconsp(STACK_0))
- { pushSTACK(Car(STACK_0)); # Symbol aus conflict-resolver
- shadowing_import(&STACK_0,&STACK_4); # in pack zum Shadowing-Symbol machen
- skipSTACK(1);
- STACK_0 = Cdr(STACK_0);
- }
- skipSTACK(2); # conflicts und conflict-resolver vergessen
- # Stackaufbau: pack, packlist.
- # packlist durchgehen:
- while (mconsp(STACK_0))
- { pushSTACK(Car(STACK_0)); # pack_to_use
- # pack_to_use auf die Use-List von pack setzen:
- # (push pack_to_use (package-use-list pack))
- { var reg1 object new_cons = allocate_cons();
- var reg2 object pack = STACK_2;
- Car(new_cons) = STACK_0; # pack_to_use
- Cdr(new_cons) = ThePackage(pack)->pack_use_list;
- ThePackage(pack)->pack_use_list = new_cons;
- }
- # pack auf die Used-By-List von pack_to_use setzen:
- # (push pack (package-used-by-list pack_to_use))
- { var reg1 object new_cons = allocate_cons();
- var reg2 object pack_to_use = popSTACK();
- Car(new_cons) = STACK_1; # pack
- Cdr(new_cons) = ThePackage(pack_to_use)->pack_used_by_list;
- ThePackage(pack_to_use)->pack_used_by_list = new_cons;
- }
- STACK_0 = Cdr(STACK_0);
- }
- skipSTACK(2); # pack und packlist vergessen
- clr_break_sem_3();
- } } }
-
- # Hilfsfunktion für use_package:
- # Teste das Argument (ein externes Symbol aus einer der Packages aus
- # packlist), ob es einen Konflikt erzeugt. Wenn ja, erweitere conflicts.
- LISPFUNN(use_package_aux,1)
- { var reg6 object* localptr = use_package_local;
- # Pointer auf lokale Variablen von use_package:
- # *(localptr STACKop 2) = pack,
- # *(localptr STACKop 1) = packlist,
- # *(localptr STACKop 0) = conflicts.
- var reg7 object string = Symbol_name(popSTACK()); # Printname des übergebenen Symbols
- # Gibt es einen Konflikt zwischen den Symbolen mit Printname = string ?
- # Bisherige Konfliktliste (((pack1 . sym1) ...) ...) durchgehen:
- { var reg1 object conflictsr = *(localptr STACKop 0);
- while (consp(conflictsr))
- { # Konflikt schon behandelt?
- # (car conflictsr) = nächster Konflikt,
- # (car (car conflictsr)) = dessen erstes Cons,
- # (cdr (car (car conflictsr))) = darin das Symbol,
- # ist dessen Printname = string ?
- if (string_gleich(Symbol_name(Cdr(Car(Car(conflictsr)))),string))
- goto ok;
- conflictsr = Cdr(conflictsr);
- } }
- pushSTACK(string); # string retten
- # neuen Konflikt aufbauen:
- pushSTACK(NIL); # neuer Konflikt (noch leer)
- # Testen, ob ein gleichnamiges Symbol bereits in pack accessible ist:
- { var object othersym;
- var reg2 sintBWL code = find_symbol(STACK_1,*(localptr STACKop 2),&othersym);
- if (code < 0)
- # Gleichnamiges Symbol in der Shadowing-Liste verhindert Konflikt.
- { skipSTACK(2); goto ok; }
- if (code > 0)
- # accessible, aber nicht shadowing -> Konflikt um (pack . othersym) erweitern:
- { pushSTACK(othersym);
- {var reg1 object temp = allocate_cons();
- Cdr(temp) = popSTACK(); # othersym
- Car(temp) = *(localptr STACKop 2); # pack
- pushSTACK(temp); # (pack . othersym)
- }
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK(); Cdr(new_cons) = STACK_0;
- STACK_0 = new_cons;
- } }}
- # Testen, in welchen Packages aus packlist ein gleichnamiges Symbol
- # extern ist:
- { var reg3 object packlistr = *(localptr STACKop 1); # packlist durchgehen
- while (consp(packlistr))
- { var reg2 object pack_to_use = Car(packlistr);
- packlistr = Cdr(packlistr);
- { var object othersym;
- if (symtab_lookup(STACK_1,ThePackage(pack_to_use)->pack_external_symbols,&othersym))
- # othersym hat den Printnamen = string und ist extern in pack_to_use.
- # (pack_to_use . othersym) auf conflict pushen:
- { pushSTACK(packlistr); # packlistr retten
- pushSTACK(pack_to_use);
- pushSTACK(othersym);
- {var reg1 object new_cons = allocate_cons();
- Cdr(new_cons) = popSTACK(); Car(new_cons) = popSTACK();
- pushSTACK(new_cons); # (cons pack_to_use othersym)
- }
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK();
- packlistr = popSTACK();
- Cdr(new_cons) = STACK_0;
- STACK_0 = new_cons; # conflict := (cons (cons pack_to_use othersym) conflict)
- } } } }}
- { var reg5 object conflict = popSTACK(); # der fertige Konflikt
- # conflict := (delete-duplicates conflict :key #'cdr :test #'eq):
- { var reg4 object conflict1 = conflict;
- while (consp(conflict1))
- { var reg3 object to_delete = Cdr(Car(conflict1));
- # Entferne alle Elemente mit CDR=to_delete
- # destruktiv aus (cdr conflict1) :
- var reg2 object conflict2 = conflict1; # läuft ab conflict1
- var reg1 object conflict3; # stets = (cdr conflict2)
- while (consp(conflict3=Cdr(conflict2)))
- { if (eq(Cdr(Car(conflict3)),to_delete))
- # streiche (car conflict3) destruktiv aus der Liste:
- { Cdr(conflict2) = Cdr(conflict3); }
- else
- # weiterrücken:
- { conflict2 = conflict3; }
- }
- conflict1 = Cdr(conflict1);
- } }
- # Falls conflict eine Länge >=2 hat, wird es zu conflicts geconst:
- if (consp(conflict) && mconsp(Cdr(conflict)))
- { pushSTACK(conflict);
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK(); # conflict
- Cdr(new_cons) = *(localptr STACKop 0); # conflicts
- *(localptr STACKop 0) = new_cons; # conflicts := (cons conflict conflicts)
- }}
- }
- skipSTACK(1); # string vergessen
- ok: value1 = NIL; mv_count=0; # keine Werte
- }
-
- # UP: Bewirkt, daß eine gegebene Package nicht mehr von einer (anderen)
- # gegebenen Package geUSEt wird.
- # unuse_1package(pack,qpack);
- # > pack: Package
- # > qpack: Package
- # Entfernt qpack von der Use-List von pack
- # und pack von der Used-By-List von qpack.
- local void unuse_1package (object pack, object qpack);
- local void unuse_1package(pack,qpack)
- var reg1 object pack;
- var reg2 object qpack;
- { set_break_sem_2();
- # qpack aus der Use-List von pack entfernen:
- ThePackage(pack)->pack_use_list =
- deleteq(ThePackage(pack)->pack_use_list,qpack);
- # pack aus der Used-By-List von qpack entfernen:
- ThePackage(qpack)->pack_used_by_list =
- deleteq(ThePackage(qpack)->pack_used_by_list,pack);
- clr_break_sem_2();
- }
-
- # UP: Bewirkt, daß eine Liste gegebener Packages nicht mehr von einer
- # gegebenen Package geUSEt wird.
- # unuse_package(packlist,pack);
- # > packlist: Liste von Packages
- # > pack: Package
- # Entfernt alle Packages aus packlist von der Use-List von pack
- # und pack von den Used-By-Listen aller Packages aus packlist.
- local void unuse_package (object packlist, object pack);
- local void unuse_package(packlist,pack)
- var reg1 object packlist;
- var reg2 object pack;
- { set_break_sem_3();
- # packlist durchgehen:
- while (consp(packlist))
- { unuse_1package(pack,Car(packlist));
- packlist = Cdr(packlist);
- }
- clr_break_sem_3();
- }
-
- # UP: liefert die aktuelle Package
- # get_current_package()
- # < ergebnis: aktuelle Package
- global object get_current_package (void);
- global object get_current_package()
- { var reg1 object pack = Symbol_value(S(packagestern)); # Wert von *PACKAGE*
- if (packagep(pack) && !pack_deletedp(pack))
- { return pack; }
- else
- { var reg1 object newpack = O(default_package); # *PACKAGE* zurücksetzen
- set_Symbol_value(S(packagestern),newpack);
- pushSTACK(pack); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(package)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(newpack); pushSTACK(pack);
- //: DEUTSCH "Der Wert von *PACKAGE* war keine Package. Alter Wert: ~. Neuer Wert: ~."
- //: ENGLISH "The value of *PACKAGE* was not a package. Old value ~. New value ~."
- //: FRANCAIS "La valeur de *PACKAGE* n'était pas un paquetage. Ancienne valeur : ~. Nouvelle valeur : ~."
- fehler(type_error, GETTEXT("The value of *PACKAGE* was not a package. Old value ~. New value ~."));
- } }
-
- # UP: Überprüft ein Package-Argument.
- # Testet, ob es eine Package oder ein Packagename ist, und liefert es als
- # Package zurück. Sonst Fehlermeldung.
- # test_package_arg(obj)
- # > obj: Argument
- # > subr_self: Aufrufer (ein SUBR)
- # < ergebnis: in eine Package umgewandeltes Argument
- local object test_package_arg (object obj);
- local object test_package_arg(obj)
- var reg1 object obj;
- { if (packagep(obj)) # Package -> meist OK
- { if (!pack_deletedp(obj)) { return obj; }
- pushSTACK(obj); # Wert für Slot PACKAGE von PACKAGE-ERROR
- pushSTACK(obj);
- //: DEUTSCH "Package ~ wurde gelöscht."
- //: ENGLISH "Package ~ has been deleted."
- //: FRANCAIS "Le paquetage ~ a été éliminé."
- fehler(package_error, GETTEXT("Package ~ has been deleted."));
- }
- if (stringp(obj))
- string: # String -> Package mit Namen obj suchen:
- { var reg2 object pack = find_package(obj);
- if (!(nullp(pack))) { return pack; }
- pushSTACK(obj); # Wert für Slot PACKAGE von PACKAGE-ERROR
- pushSTACK(obj);
- //: DEUTSCH "Eine Package mit Namen ~ gibt es nicht."
- //: ENGLISH "There is no package with name ~"
- //: FRANCAIS "Il n'y a pas de paquetage de nom ~."
- fehler(package_error, GETTEXT("There is no package with name ~"));
- }
- if (symbolp(obj)) # Symbol ->
- { obj = Symbol_name(obj); goto string; } # Printnamen verwenden
- pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(O(type_packname)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß eine Package oder ein Packagename sein, nicht ~"
- //: ENGLISH "~: argument should be a package or a package name, not ~"
- //: FRANCAIS "L'argument de ~ doit être un paquetage ou un nom de paquetage et non ~."
- fehler(type_error, GETTEXT("~: argument should be a package or a package name, not ~"));
- }
-
- LISPFUNN(make_symbol,1) # (MAKE-SYMBOL printname), CLTL S. 168
- { var reg1 object arg = popSTACK();
- if (!(stringp(arg)))
- { pushSTACK(arg); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(string)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(arg); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Argument muß ein String sein, nicht ~."
- //: ENGLISH "~: argument should be a string, not ~"
- //: FRANCAIS "~ : L'argument doit être une chaîne et non ~."
- fehler(type_error, GETTEXT("~: argument should be a string, not ~"));
- }
- # Simple-String draus machen und Symbol bauen:
- value1 = make_symbol(coerce_imm_ss(arg)); mv_count=1;
- }
-
- # UP: Überprüft ein String/Symbol-Argument
- # > obj: Argument
- # > subr_self: Aufrufer (ein SUBR)
- # < ergebnis: Argument als String
- local object test_stringsym_arg (object obj);
- local object test_stringsym_arg(obj)
- var reg1 object obj;
- { if (stringp(obj)) return obj; # String: unverändert zurück
- if (symbolp(obj)) return TheSymbol(obj)->pname; # Symbol: Printnamen verwenden
- pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(O(type_stringsym)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Argument muß ein String oder Symbol sein, nicht ~."
- //: ENGLISH "~: argument ~ should be a string or a symbol"
- //: FRANCAIS "~ : L'argument doit être un symbole ou une chaîne et non ~."
- fehler(type_error, GETTEXT("~: argument ~ should be a string or a symbol"));
- }
-
- LISPFUNN(find_package,1) # (FIND-PACKAGE name), CLTL S. 183
- { var reg1 object name = test_stringsym_arg(popSTACK()); # Argument als String
- value1 = find_package(name); # Package suchen
- mv_count=1;
- }
-
- LISPFUNN(pfind_package,1) # (SYSTEM::%FIND-PACKAGE name)
- { value1 = test_package_arg(popSTACK()); # Argument als Package
- mv_count=1;
- }
-
- LISPFUNN(package_name,1) # (PACKAGE-NAME package), CLTL S. 184
- { var reg1 object pack = popSTACK();
- if (packagep(pack) && pack_deletedp(pack))
- { value1 = NIL; }
- else
- { pack = test_package_arg(pack); # Argument als Package
- value1 = ThePackage(pack)->pack_name; # der Name
- }
- mv_count=1;
- }
-
- LISPFUNN(package_nicknames,1) # (PACKAGE-NICKNAMES package), CLTL S. 184
- { var reg1 object pack = popSTACK();
- if (packagep(pack) && pack_deletedp(pack))
- { value1 = NIL; }
- else
- { pack = test_package_arg(pack); # Argument als Package
- value1 = copy_list(ThePackage(pack)->pack_nicknames); # Nicknameliste sicherheitshalber kopieren
- }
- mv_count=1;
- }
-
- # UP: Überprüft name und nicknames - Argumente von RENAME-PACKAGE und MAKE-PACKAGE.
- # Testet, ob STACK_2 ein Name ist, und macht daraus einen Simple-String.
- # Testet, ob STACK_1 ein Name oder eine Liste von Namen ist, und macht
- # daraus eine neue Liste von Simple-Strings.
- # > subr-self: Aufrufer (ein SUBR)
- # kann GC auslösen
- local void test_names_args (void);
- local void test_names_args()
- { # name auf String prüfen und zu einem Simple-String machen:
- STACK_2 = coerce_imm_ss(test_stringsym_arg(STACK_2));
- # Nickname-Argument in eine Liste umwandeln:
- { var reg2 object nicknames = STACK_1;
- if (eq(nicknames,unbound))
- { STACK_1 = NIL; } # keine Nicknames angegeben -> Default NIL
- else
- if (!(listp(nicknames)))
- { # nicknames keine Liste -> eine einelementige Liste daraus machen:
- nicknames = allocate_cons();
- Car(nicknames) = STACK_1;
- STACK_1 = nicknames;
- } }
- # Nickname(s) auf String prüfen, zu Simple-Strings machen
- # und daraus eine neue Nicknameliste machen:
- { pushSTACK(NIL); # neue Nicknameliste := NIL
- while (mconsp(STACK_2))
- {{var reg1 object nickname = Car(STACK_2); # nächster Nickname
- STACK_2 = Cdr(STACK_2);
- nickname = coerce_imm_ss(test_stringsym_arg(nickname)); # als Simple-String
- # vor die neue Nicknameliste consen:
- pushSTACK(nickname);
- }
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK();
- Cdr(new_cons) = STACK_0;
- STACK_0 = new_cons;
- }}
- {var reg1 object nicknames = popSTACK();
- STACK_1 = nicknames; # neue Nicknameliste ersetzt die alte
- }}
- }
-
- LISPFUN(rename_package,2,1,norest,nokey,0,NIL)
- # (RENAME-PACKAGE pack name [nicknames]), CLTL S. 184
- { # Testen, ob pack eine Package ist:
- STACK_2 = test_package_arg(STACK_2);
- # name und nicknames überprüfen:
- pushSTACK(NIL); # Dummy auf den Stack
- test_names_args();
- skipSTACK(1);
- {var reg1 object pack = STACK_2;
- # Teste, ob ein Packagenamenkonflikt entsteht:
- { var reg3 object name = STACK_1;
- var reg2 object nicknamelistr = STACK_0;
- # name durchläuft den Namen und alle Nicknames
- loop
- { var reg1 object found = find_package(name); # Suche Package mit diesem Namen
- if (!(nullp(found) || eq(found,pack)))
- { # gefunden, aber eine andere als die gegebene Package:
- pushSTACK(pack); # Wert für Slot PACKAGE von PACKAGE-ERROR
- pushSTACK(name); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Eine Package mit dem Namen ~ gibt es schon."
- //: ENGLISH "~: there is already a package named ~"
- //: FRANCAIS "~ : Il y a déjà un paquetage de nom ~."
- fehler(package_error, GETTEXT("~: there is already a package named ~"));
- }
- # Keine oder nur die gegebene Package hat den Namen name ->
- # kein Konflikt mit diesem (Nick)name, weiter:
- if (atomp(nicknamelistr)) break;
- name = Car(nicknamelistr); # nächster Nickname
- nicknamelistr = Cdr(nicknamelistr); # restliche Nicknameliste verkürzen
- } }
- # Es gibt keine Konflikte.
- set_break_sem_2();
- ThePackage(pack)->pack_name = STACK_1;
- ThePackage(pack)->pack_nicknames = STACK_0;
- clr_break_sem_2();
- skipSTACK(3);
- value1 = pack; mv_count=1; # pack als Wert
- }}
-
- LISPFUNN(package_use_list,1) # (PACKAGE-USE-LIST package), CLTL S. 184
- { var reg1 object pack = test_package_arg(popSTACK()); # Argument als Package
- value1 = copy_list(ThePackage(pack)->pack_use_list); # Use-List sicherheitshalber kopieren
- mv_count=1;
- }
-
- LISPFUNN(package_used_by_list,1) # (PACKAGE-USED-BY-LIST package), CLTL S. 184
- { var reg1 object pack = test_package_arg(popSTACK()); # Argument als Package
- value1 = copy_list(ThePackage(pack)->pack_used_by_list); # Used-By-List sicherheitshalber kopieren
- mv_count=1;
- }
-
- LISPFUNN(package_shadowing_symbols,1) # (PACKAGE-SHADOWING-SYMBOLS package), CLTL S. 184
- { var reg1 object pack = test_package_arg(popSTACK()); # Argument als Package
- value1 = copy_list(ThePackage(pack)->pack_shadowing_symbols); # Shadowing-Liste sicherheitshalber kopieren
- mv_count=1;
- }
-
- LISPFUNN(list_all_packages,0)
- # (LIST-ALL-PACKAGES) liefert eine Liste aller Packages, CLTL S. 184
- { value1 = reverse(O(all_packages)); # (Kopie der Liste, sicherheitshalber)
- mv_count=1;
- }
-
- # UP: Überprüft das letzte Argument &optional (pack *package*) einer
- # LISP-Funktion.
- # test_optional_package_arg()
- # > STACK_0: letztes Argument
- # > subr_self: Aufrufer (ein SUBR)
- # < STACK_0: in eine Package umgewandeltes Argument
- local void test_optional_package_arg (void);
- local void test_optional_package_arg()
- { var reg1 object pack = STACK_0;
- if (eq(pack,unbound))
- { STACK_0 = get_current_package(); } # Default ist Wert von *PACKAGE*
- else
- { STACK_0 = test_package_arg(pack); }
- }
-
- # UP: Überprüfung der Argumente von INTERN und FIND-SYMBOL.
- # test_intern_args()
- # > subr_self: Aufrufer (ein SUBR)
- local void test_intern_args (void);
- local void test_intern_args()
- { # String überprüfen:
- if (!(stringp(STACK_1)))
- { pushSTACK(STACK_1); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(string)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(STACK_(1+2)); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Argument ~ ist kein String."
- //: ENGLISH "~: argument ~ is not a string"
- //: FRANCAIS "~ : L'argument ~ n'est pas une chaîne."
- fehler(type_error, GETTEXT("~: argument ~ is not a string"));
- }
- # Package überprüfen:
- test_optional_package_arg();
- }
-
- # UP: Wandelt ein INTERN/FIND-SYMBOL - Ergebnis in ein Keyword um.
- # intern_result(code)
- # > code : Flag wie bei intern und find_symbol
- # < ergebnis : entsprechendes Keyword
- local object intern_result (uintBWL code);
- local object intern_result(code)
- var reg1 uintBWL code;
- { switch (code)
- { case 0: return NIL; # 0 -> NIL
- case 1: return S(Kexternal); # 1 -> :EXTERNAL
- case 2: return S(Kinherited); # 2 -> :INHERITED
- case 3: return S(Kinternal); # 3 -> :INTERNAL
- default: NOTREACHED
- } }
-
- LISPFUN(intern,1,1,norest,nokey,0,NIL)
- # (INTERN string [package]), CLTL S. 184
- { test_intern_args(); # Argumente überprüfen
- {var reg2 object pack = popSTACK();
- var reg1 object string = popSTACK();
- #if !defined(VALUE1_EXTRA)
- var reg3 uintBWL code = intern(string,pack,&value1); # Symbol nach value1
- #else
- var object value;
- var reg3 uintBWL code = intern(string,pack,&value); # Symbol nach value
- value1 = value;
- #endif
- value2 = intern_result(code); mv_count=2; # 2 Werte
- }}
-
- LISPFUN(find_symbol,1,1,norest,nokey,0,NIL)
- # (FIND-SYMBOL string [package]), CLTL S. 185
- { test_intern_args(); # Argumente überprüfen
- {var reg2 object pack = popSTACK();
- var reg1 object string = popSTACK();
- #if !defined(VALUE1_EXTRA)
- var reg3 uintBWL code = find_symbol(string,pack,&value1) & 3; # Symbol nach value1
- #else
- var object value;
- var reg3 uintBWL code = find_symbol(string,pack,&value) & 3; # Symbol nach value
- value1 = value;
- #endif
- value2 = intern_result(code); mv_count=2; # 2 Werte
- }}
-
- LISPFUN(unintern,1,1,norest,nokey,0,NIL)
- # (UNINTERN symbol [package]), CLTL S. 185
- { # Symbol überprüfen:
- if (!(msymbolp(STACK_1)))
- { pushSTACK(STACK_1); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(symbol)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(STACK_(1+2)); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Argument ~ ist kein Symbol."
- //: ENGLISH "~: argument ~ is not a symbol"
- //: FRANCAIS "~ : L'argument ~ n'est pas un symbole."
- fehler(type_error, GETTEXT("~: argument ~ is not a symbol"));
- }
- # Package überprüfen:
- test_optional_package_arg();
- # uninternieren:
- value1 = unintern(&STACK_1,&STACK_0); mv_count=1;
- skipSTACK(2);
- }
-
- # Ausführer einer Funktion wie EXPORT, UNEXPORT, IMPORT, SHADOWING-IMPORT
- # oder SHADOW. Überprüft, ob das erste Argument eine Symbolliste ist, ob
- # das zweite Argument (Default: *PACKAGE*) eine Package ist, und wendet das
- # Unterprogramm auf jedes der Symbole an. Rücksprung mit 1 Wert T.
- # apply_symbols(&fun);
- # Spezifikation des Unterprogrammes fun:
- # fun(&sym,&pack);
- # > sym: Symbol (im STACK)
- # > pack: Package (im STACK)
- # < pack: Package, EQ zur alten
- # kann GC auslösen
- # < STACK: aufgeräumt
- # kann GC auslösen
- typedef void sym_pack_function (object* sym_, object* pack_);
- local Values apply_symbols (sym_pack_function* fun);
- local Values apply_symbols(fun)
- var reg2 sym_pack_function* fun;
- { # Überprüfe, ob das erste Argument eine Symbolliste oder ein Symbol ist:
- { var reg1 object symarg = STACK_1;
- # auf Symbol testen:
- if (symbolp(symarg)) goto ok;
- #ifdef X3J13_161
- if ((fun == &shadow) && stringp(symarg)) goto ok;
- #endif
- # auf Symbolliste testen:
- while (consp(symarg)) # symarg durchläuft STACK_1
- { if (!(msymbolp(Car(symarg))
- #ifdef X3J13_161
- || ((fun == &shadow) && mstringp(Car(symarg)))
- #endif
- ) )
- goto not_ok;
- symarg = Cdr(symarg);
- }
- if (!(nullp(symarg))) goto not_ok; # Liste korrekt beendet?
- goto ok; # korrekte Symbolliste
- not_ok:
- pushSTACK(STACK_1); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß ein Symbol oder eine Symbolliste sein, nicht ~"
- //: ENGLISH "~: argument should be a symbol or a list of symbols, not ~"
- //: FRANCAIS "~ : L'argument de ~ doit être un symbole ou une liste de symboles et non ~."
- fehler(error, GETTEXT("~: argument should be a symbol or a list of symbols, not ~"));
- ok: ;
- }
- # Package überprüfen:
- test_optional_package_arg();
- # Stackaufbau: symarg, pack.
- # fun auf alle Symbole anwenden:
- if (matomp(STACK_1))
- # einzelnes Symbol
- { # Stackaufbau: sym, pack.
- (*fun)(&STACK_1,&STACK_0);
- skipSTACK(2);
- }
- else
- # nichtleere Symbolliste
- { pushSTACK(NIL);
- do { var reg1 object symlistr = STACK_2;
- STACK_2 = Cdr(symlistr);
- STACK_0 = Car(symlistr); # Symbol
- # Stackaufbau: symlistr, pack, sym.
- (*fun)(&STACK_0,&STACK_1);
- }
- until (matomp(STACK_2));
- skipSTACK(3);
- }
- # beenden:
- value1 = T; mv_count=1;
- }
-
- LISPFUN(export,1,1,norest,nokey,0,NIL)
- # (EXPORT symbols [package]), CLTL S. 186
- { return_Values apply_symbols(&export); }
-
- LISPFUN(unexport,1,1,norest,nokey,0,NIL)
- # (UNEXPORT symbols [package]), CLTL S. 186
- { return_Values apply_symbols(&unexport); }
-
- LISPFUN(import,1,1,norest,nokey,0,NIL)
- # (IMPORT symbols [package]), CLTL S. 186
- { return_Values apply_symbols(&import); }
-
- LISPFUN(shadowing_import,1,1,norest,nokey,0,NIL)
- # (SHADOWING-IMPORT symbols [package]), CLTL S. 186
- { return_Values apply_symbols(&shadowing_import); }
-
- LISPFUN(shadow,1,1,norest,nokey,0,NIL)
- # (SHADOW symbols [package]), CLTL S. 186
- { return_Values apply_symbols(&shadow); }
-
- # UP: Vorbereitung der Argumente bei USE-PACKAGE und UNUSE-PACKAGE.
- # Das 1. Argument STACK_1 wird zu einer (neu erzeugten) Liste von Packages
- # gemacht, das 2. Argument STACK_0 wird überprüft.
- # > subr_self: Aufrufer (ein SUBR)
- # kann GC auslösen
- local void prepare_use_package (void);
- local void prepare_use_package()
- { # 2. Argument (Package) überprüfen:
- test_optional_package_arg();
- # 1. Argument (Package oder Packageliste) überprüfen:
- { var reg2 object packs_to_use = STACK_1;
- if (!(listp(packs_to_use)))
- # packs_to_use keine Liste -> einelementige Liste draus machen:
- { pushSTACK(test_package_arg(packs_to_use)); # einzelne Package
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK();
- STACK_1 = new_cons;
- }}
- else
- # packs_to_use eine Liste -> neue Packageliste aufbauen:
- { pushSTACK(NIL); # mit NIL anfangen
- while (mconsp(STACK_2))
- { var reg1 object packlistr = STACK_2;
- STACK_2 = Cdr(packlistr);
- pushSTACK(test_package_arg(Car(packlistr))); # nächste Package
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK();
- Cdr(new_cons) = STACK_0;
- STACK_0 = new_cons;
- }}
- {var reg1 object packlist = popSTACK(); # neue Packageliste
- STACK_1 = packlist;
- }}
- } }
-
- LISPFUN(use_package,1,1,norest,nokey,0,NIL)
- # (USE-PACKAGE packs-to-use [package]), CLTL S. 187
- { prepare_use_package();
- {var reg2 object pack = popSTACK();
- var reg1 object packlist = popSTACK();
- use_package(packlist,pack);
- value1 = T; mv_count=1;
- }}
-
- LISPFUN(unuse_package,1,1,norest,nokey,0,NIL)
- # (UNUSE-PACKAGE packs-to-use [package]), CLTL S. 187
- { prepare_use_package();
- {var reg2 object pack = popSTACK();
- var reg1 object packlist = popSTACK();
- unuse_package(packlist,pack);
- value1 = T; mv_count=1;
- }}
-
- # UP: Korrigiert einen Package(nick)name.
- # > name: Gewünschter Packagename (Simple-String)
- # > STACK_1: "Sie dürfen einen neuen (Nick)Name eingeben."
- # > STACK_0: "Bitte neuen Package(nick)name eingeben:"
- # < ergebnis: Noch nicht vorkommender Packagename
- # kann GC auslösen
- local object correct_packname (object name);
- local object correct_packname(name)
- var reg2 object name;
- { while (!(nullp(find_package(name))))
- { # Package mit diesem Namen existiert schon
- { pushSTACK(STACK_1); # "Sie dürfen ... eingeben."
- pushSTACK(OL(makepack_string3)); # "Eine Package mit dem Namen ~S gibt es schon."
- pushSTACK(name);
- funcall(S(cerror),3); # (CERROR "Sie dürfen ..." "Package ~S existiert" name)
- }
- { var object stream = var_stream(S(query_io),strmflags_rd_ch_B|strmflags_wr_ch_B); # Stream *QUERY-IO*
- terpri(&stream); # neue Zeile
- write_sstring(&stream,STACK_0); # "Bitte ... eingeben:"
- pushSTACK(stream); funcall(L(read_line),1); # (READ-LINE stream)
- name = value1;
- } }
- return name;
- }
-
- # UP für MAKE-PACKAGE und IN-PACKAGE:
- # Bildet eine neue Package und liefert sie als Wert.
- # > STACK_2: name-Argument
- # > STACK_1: nicknames-Argument
- # > STACK_0: uselist-Argument
- # > subr_self: Aufrufer (ein SUBR)
- # erhöht STACK um 3
- # kann GC auslösen
- local void in_make_package (void);
- local void in_make_package()
- { # name in Simple-String und nicknames in neue Simple-String-Liste umwandeln:
- test_names_args();
- # name überprüfen und evtl. korrigieren:
- { pushSTACK(OL(makepack_string1)); # "Sie dürfen einen neuen Namen eingeben."
- pushSTACK(OL(makepack_string4)); # "Bitte neuen Packagenamen eingeben:"
- STACK_4 = correct_packname(STACK_4);
- skipSTACK(2);
- }
- # nicknames überprüfen und evtl. korrigieren:
- { pushSTACK(STACK_1); # nicknames durchgehen
- while (mconsp(STACK_0))
- { var reg1 object nickname = Car(STACK_0); # nickname herausgreifen
- pushSTACK(OL(makepack_string2)); # "Sie dürfen einen neuen Nickname eingeben."
- pushSTACK(OL(makepack_string5)); # "Bitte neuen Packagenickname eingeben:"
- nickname = correct_packname(nickname); # korrigieren
- skipSTACK(2);
- Car(STACK_0) = nickname; # und wieder einsetzen
- STACK_0 = Cdr(STACK_0);
- }
- skipSTACK(1);
- }
- # Package erzeugen:
- {var reg1 object pack = make_package(STACK_2,STACK_1);
- STACK_2 = pack; # und retten
- # Stackaufbau: pack, nicknames, uselist-Argument.
- # Defaultwert für Use-Argument verwenden:
- if (eq(STACK_0,unbound)) { STACK_0 = O(use_default); }
- # (USE-PACKAGE UseList neuePackage) ausführen:
- { pushSTACK(STACK_0); # UseList
- pushSTACK(pack); # neue Package
- funcall(L(use_package),2);
- }}
- skipSTACK(2);
- value1 = popSTACK(); mv_count=1; # Package als Wert
- }
-
- LISPFUN(make_package,1,0,norest,key,2, (kw(nicknames),kw(use)) )
- # (MAKE-PACKAGE name [:NICKNAMES nicknames] [:USE uselist]), CLTL S. 183
- { in_make_package(); }
-
- LISPFUN(pin_package,1,0,norest,key,2, (kw(nicknames),kw(use)) )
- # (SYSTEM::%IN-PACKAGE name [:NICKNAMES nicknames] [:USE uselist]) ist
- # wie (IN-PACKAGE name [:NICKNAMES nicknames] [:USE uselist]), CLTL S. 183,
- # nur daß *PACKAGE* nicht modifiziert wird.
- { # name überprüfen und in String umwandeln:
- var reg3 object name = test_stringsym_arg(STACK_2);
- STACK_2 = name;
- # Package mit diesem Namen suchen:
- {var reg2 object pack = find_package(name);
- if (nullp(pack))
- # Package nicht gefunden, muß eine neue erzeugen
- { in_make_package(); }
- else
- # Package gefunden
- { STACK_2 = pack; # pack retten
- # Stackaufbau: pack, nicknames, uselist.
- # Die Nicknames anpassen:
- if (!eq(STACK_1,unbound))
- # Nicknames installieren mit RENAME-PACKAGE:
- { pushSTACK(pack); # pack
- pushSTACK(ThePackage(pack)->pack_name); # (package-name pack)
- pushSTACK(STACK_3); # nicknames
- funcall(L(rename_package),3); # (RENAME-PACKAGE pack (package-name pack) nicknames)
- }
- # Die Use-List anpassen:
- if (!eq(STACK_0,unbound))
- { # Use-List erweitern mit USE-PACKAGE
- # und verkürzen mit UNUSE-PACKAGE:
- pushSTACK(STACK_2); # pack als 2. Argument für USE-PACKAGE
- prepare_use_package(); # Argumente STACK_1, STACK_0 überprüfen
- skipSTACK(1);
- # Stackaufbau: pack, nicknames, neue Use-List.
- # USE-PACKAGE ausführen (mit kopierter Use-List):
- use_package(reverse(STACK_0),STACK_2);
- # Alle Packages, die jetzt noch in der Use-List von pack
- # aufgeführt sind, aber nicht in der in STACK_0 befindlichen
- # uselist vorkommen, werden mit unuse_1package entfernt:
- pack = STACK_2;
- { var reg3 object used_packs = ThePackage(pack)->pack_use_list; # Use-List von pack durchgehen
- while (consp(used_packs))
- { var reg2 object qpack = Car(used_packs);
- # in uselist suchen:
- var reg1 object listr = STACK_0;
- while (consp(listr))
- { if (eq(qpack,Car(listr))) goto unuse_ok; # in uselist gefunden -> OK
- listr = Cdr(listr);
- }
- # nicht in uselist gefunden
- unuse_1package(pack,qpack);
- unuse_ok: ;
- used_packs = Cdr(used_packs);
- } } }
- # Die Use-List ist korrekt angepaßt.
- skipSTACK(2); # uselist und nicknames vergessen
- value1 = popSTACK(); mv_count=1; # pack als Wert
- }
- }}
-
- LISPFUN(in_package,1,0,norest,key,2, (kw(nicknames),kw(use)) )
- # (IN-PACKAGE name [:NICKNAMES nicknames] [:USE uselist]), CLTL S. 183
- { C_pin_package();
- # Ergebnis an *PACKAGE* zuweisen:
- set_Symbol_value(S(packagestern),value1);
- }
-
- local object* delete_package_local; # Pointer auf eine lokale Variable
- LISPFUNN(delete_package,1)
- # (DELETE-PACKAGE package), CLTL2 S. 265-266
- { var reg1 object pack = popSTACK();
- if (packagep(pack))
- { if (pack_deletedp(pack))
- { value1 = NIL; mv_count=1; return; } # schon gelöscht -> 1 Wert NIL
- }
- elif (stringp(pack))
- string: # String -> Package mit diesem Namen suchen:
- { var reg2 object found = find_package(pack);
- if (nullp(found))
- { # Continuable Error auslösen:
- pushSTACK(OL(delpack_string1)); # "Ignorieren."
- pushSTACK(OL(delpack_string2)); # "~S: Eine Package mit Namen ~S gibt es nicht."
- pushSTACK(S(delete_package));
- pushSTACK(pack);
- funcall(S(cerror),4); # (CERROR "..." "..." 'DELETE-PACKAGE pack)
- value1 = NIL; mv_count=1; # 1 Wert NIL
- return;
- }
- pack = found;
- }
- elif (symbolp(pack)) # Symbol ->
- { pack = Symbol_name(pack); goto string; } # Printnamen verwenden
- else
- { pack = test_package_arg(pack); } # Fehler melden
- pushSTACK(pack);
- if (!nullp(ThePackage(pack)->pack_used_by_list))
- { # Continuable Error auslösen:
- pushSTACK(OL(delpack_string3)); # "~*~S wird trotzdem gelöscht."
- pushSTACK(OL(delpack_string4)); # "~S: ~S wird von ~{~S~^, ~} benutzt."
- pushSTACK(S(delete_package));
- pushSTACK(pack);
- pushSTACK(ThePackage(pack)->pack_used_by_list);
- funcall(S(cerror),5); # (CERROR "..." "..." 'DELETE-PACKAGE pack used-by-list)
- }
- pack = STACK_0;
- # (DOLIST (p used-py-list) (UNUSE-PACKAGE pack p)) ausführen:
- set_break_sem_3();
- while (mconsp(ThePackage(pack)->pack_used_by_list))
- { unuse_1package(Car(ThePackage(pack)->pack_used_by_list),pack); }
- clr_break_sem_3();
- # (UNUSE-PACKAGE (package-use-list pack) pack) ausführen:
- unuse_package(ThePackage(pack)->pack_use_list,pack);
- # #'delete-package-aux auf die in pack präsenten Symbole anwenden:
- delete_package_local = &STACK_0;
- map_symtab(L(delete_package_aux),ThePackage(STACK_0)->pack_external_symbols);
- map_symtab(L(delete_package_aux),ThePackage(STACK_0)->pack_internal_symbols);
- pack = popSTACK();
- # pack aus der Liste aller Packages herausnehmen und als gelöscht markieren:
- set_break_sem_2();
- O(all_packages) = deleteq(O(all_packages),pack);
- mark_pack_deleted(pack);
- clr_break_sem_2();
- value1 = T; mv_count=1; # 1 Wert T
- }
-
- # Hilfsfunktion für DELETE-PACKAGE:
- # Entferne das Argument (ein präsentes Symbol) aus pack.
- LISPFUNN(delete_package_aux,1)
- { value1 = unintern(&STACK_0,delete_package_local); mv_count=1; skipSTACK(1); }
-
- LISPFUNN(find_all_symbols,1)
- # (FIND-ALL-SYMBOLS name), CLTL S. 187
- { STACK_0 = test_stringsym_arg(STACK_0); # name als String
- pushSTACK(NIL); # (bisher leere) Symbolliste
- pushSTACK(O(all_packages)); # Liste aller Packages durchgehen
- while (mconsp(STACK_0))
- { var reg2 object pack = Car(STACK_0); # nächste Package
- # in deren internen und externen Symbolen suchen:
- var object sym;
- if (symtab_lookup(STACK_2,ThePackage(pack)->pack_internal_symbols,&sym)
- || symtab_lookup(STACK_2,ThePackage(pack)->pack_external_symbols,&sym)
- )
- # gefunden: Symbol sym ist in Package pack präsent,
- # mit (pushnew sym STACK_1 :test #'eq) auf die Symbolliste consen:
- { # Suche, ob das gefundene Symbol sym in STACK_1 vorkommt:
- {var reg1 object symlistr = STACK_1;
- while (consp(symlistr))
- { if (eq(sym,Car(symlistr))) goto already_found; # gefunden -> nichts weiter zu tun
- symlistr = Cdr(symlistr);
- } }
- # nicht gefunden, muß consen:
- pushSTACK(sym);
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK();
- Cdr(new_cons) = STACK_1;
- STACK_1 = new_cons;
- }
- already_found: ;
- }
- STACK_0 = Cdr(STACK_0);
- }
- skipSTACK(1);
- value1 = popSTACK(); mv_count=1; # Symbolliste als Wert
- skipSTACK(1);
- }
-
- local object* map_symbols_local; # Pointer auf zwei lokale Variablen
- LISPFUNN(map_symbols,2)
- # (SYSTEM::MAP-SYMBOLS fun pack)
- # wendet die Funktion fun auf alle in pack accessiblen Symbole an. Wert NIL.
- { # 2. Argument überprüfen:
- STACK_0 = test_package_arg(STACK_0);
- # fun auf alle internen Symbole loslassen:
- map_symtab(STACK_1,ThePackage(STACK_0)->pack_internal_symbols);
- # fun auf alle externen Symbole loslassen:
- map_symtab(STACK_1,ThePackage(STACK_0)->pack_external_symbols);
- # fun auf alle vererbten Symbole loslassen:
- map_symbols_local = &STACK_0; # zeigt auf die zwei lokalen Variablen
- pushSTACK(ThePackage(STACK_0)->pack_use_list); # Use-List durchgehen
- while (mconsp(STACK_0))
- { var reg1 object usedpack = Car(STACK_0); # nächste Package aus der Use-List
- STACK_0 = Cdr(STACK_0);
- map_symtab(L(map_symbols_aux),ThePackage(usedpack)->pack_external_symbols);
- }
- skipSTACK(3);
- value1 = NIL; mv_count=1; # NIL als Wert
- }
-
- # Hilfsfunktion für map_symbols:
- # Teste, ob das Argument nicht in der gegebenen Package verdeckt ist, und
- # wende dann die gegebene Funktion an.
- LISPFUNN(map_symbols_aux,1)
- { var reg1 object* localptr = map_symbols_local;
- # Pointer auf lokale Variablen von map_symbols:
- # *(localptr STACKop 1) = fun,
- # *(localptr STACKop 0) = pack.
- # Verdeckt ist das Symbol STACK_0 genau dann, wenn sich ein davon
- # verschiedenes Symbol desselben Namens in der Shadowing-Liste von pack
- # befindet.
- var object shadowingsym;
- if (!(shadowing_lookup(Symbol_name(STACK_0),*(localptr STACKop 0),&shadowingsym)
- && !eq(shadowingsym,STACK_0)
- ) )
- { funcall(*(localptr STACKop 1),1); }
- else
- # Symbol ist in pack verdeckt -> Funktion nicht aufrufen
- { skipSTACK(1); }
- map_symbols_local = localptr; # damit MAP-SYMBOLS reentrant ist
- value1 = NIL; mv_count=0; # keine Werte
- }
-
- LISPFUNN(map_external_symbols,2)
- # (SYSTEM::MAP-EXTERNAL-SYMBOLS fun pack)
- # wendet die Funktion fun auf alle in pack externen Symbole an. Wert NIL.
- { # 2. Argument überprüfen:
- var reg1 object pack = test_package_arg(popSTACK());
- # fun auf alle externen Symbole loslassen:
- map_symtab(popSTACK(),ThePackage(pack)->pack_external_symbols);
- value1 = NIL; mv_count=1; # NIL als Wert
- }
-
- LISPFUNN(map_all_symbols,1)
- # (SYSTEM::MAP-ALL-SYMBOLS fun)
- # wendet die Funktion fun auf alle in irgendeiner Package präsenten Symbole an.
- { pushSTACK(O(all_packages)); # Package-Liste durchgehen
- while (mconsp(STACK_0))
- { var reg1 object pack = Car(STACK_0); # nächste Package
- STACK_0 = Cdr(STACK_0);
- pushSTACK(pack); # retten
- # fun auf alle internen Symbole loslassen:
- map_symtab(STACK_2,ThePackage(pack)->pack_internal_symbols);
- pack = popSTACK();
- # fun auf alle externen Symbole loslassen:
- map_symtab(STACK_1,ThePackage(pack)->pack_external_symbols);
- }
- skipSTACK(2);
- value1 = NIL; mv_count=1; # NIL als Wert
- }
-
- # Hilfsfunktionen für WITH-PACKAGE-ITERATOR, CLtL2 S. 275, und LOOP:
- # (SYSTEM::PACKAGE-ITERATOR package flags) liefert einen internen Zustand
- # für das Iterieren durch die Package.
- # (SYSTEM::PACKAGE-ITERATE internal-state) iteriert durch eine Package um
- # eins weiter, verändert dabei internal-state und liefert: 3 Werte
- # T, symbol, accessibility des nächsten Symbols bzw. 1 Wert NIL am Schluß.
-
- LISPFUNN(package_iterator,2)
- { STACK_1 = test_package_arg(STACK_1); # package-Argument überprüfen
- # Ein interner Zustand besteht aus einem Vektor
- # #(entry index symtab inh-packages package flags)
- # wobei flags eine Teilliste von (:INTERNAL :EXTERNAL :INHERITED) ist,
- # package die ursprüngliche Package ist,
- # inh-packages eine Teilliste von (package-use-list package) ist,
- # symtab eine Symboltabelle oder NIL ist,
- # index ein Index in symtab ist,
- # entry der Rest eines Eintrags in symtab ist.
- {var reg1 object state = allocate_vector(6);
- # TheSvector(state)->data[2] = NIL; # unnötig
- TheSvector(state)->data[3] = ThePackage(STACK_1)->pack_use_list;
- TheSvector(state)->data[4] = STACK_1;
- TheSvector(state)->data[5] = STACK_0;
- value1 = state; mv_count=1; skipSTACK(2); # state als Wert
- }}
-
- LISPFUNN(package_iterate,1)
- { var reg1 object state = popSTACK(); # interner Zustand
- if (simple_vector_p(state) && (TheSvector(state)->length == 6)) # hoffentlich ein 6er-Vektor
- { # state = #(entry index symtab inh-packages package flags)
- var reg2 object symtab = TheSvector(state)->data[2];
- if (simple_vector_p(symtab))
- { if (FALSE)
- { search1:
- TheSvector(state)->data[2] = symtab;
- TheSvector(state)->data[1] = Symtab_size(symtab);
- TheSvector(state)->data[0] = NIL;
- }
- search2:
- { var reg3 object entry = TheSvector(state)->data[0];
- search3:
- # Innerhalb von entry weitersuchen:
- if (consp(entry))
- { TheSvector(state)->data[0] = Cdr(entry);
- value2 = Car(entry); goto found;
- }
- elif (!nullp(entry))
- { TheSvector(state)->data[0] = NIL;
- value2 = entry; goto found;
- }
- if (FALSE)
- { found:
- # Ein Symbol value2 gefunden.
- # Stelle sicher, daß es in pack accessible und nicht verdeckt
- # ist. Ansonsten befindet sich ein davon verschiedenes Symbol
- # desselben Namens in der Shadowing-Liste von pack.
- {var object shadowingsym;
- if (!(eq(Car(TheSvector(state)->data[5]),S(Kinherited))
- && shadowing_lookup(Symbol_name(value2),TheSvector(state)->data[4],&shadowingsym)
- && !eq(shadowingsym,value2)
- ) )
- { # Symbol value2 ist wirklich accessible.
- value1 = T; value3 = Car(TheSvector(state)->data[5]);
- mv_count=3; return;
- }
- goto search2;
- }}
- # entry = NIL geworden -> zum nächsten Index
- {var reg4 uintL index = posfixnum_to_L(TheSvector(state)->data[1]);
- if (index > 0)
- { TheSvector(state)->data[1] = fixnum_inc(TheSvector(state)->data[1],-1);
- index--;
- entry = (index < posfixnum_to_L(Symtab_size(symtab)) # index sicherheitshalber überprüfen
- ? TheSvector(Symtab_table(symtab))->data[index]
- : NIL
- );
- goto search3;
- }
- }}
- # index = 0 geworden -> zur nächsten Tabelle
- if (eq(Car(TheSvector(state)->data[5]),S(Kinherited)))
- { search4:
- if (mconsp(TheSvector(state)->data[3]))
- { # zum nächsten Element der Liste inh-packages
- symtab = ThePackage(Car(TheSvector(state)->data[3]))->pack_external_symbols;
- TheSvector(state)->data[3] = Cdr(TheSvector(state)->data[3]);
- goto search1;
- } }
- search5:
- # zum nächsten Element von flags
- TheSvector(state)->data[5] = Cdr(TheSvector(state)->data[5]);
- }
- {var reg4 object flags = TheSvector(state)->data[5];
- if (consp(flags))
- { var reg3 object flag = Car(flags);
- if (eq(flag,S(Kinternal))) # :INTERNAL
- { symtab = ThePackage(TheSvector(state)->data[4])->pack_internal_symbols;
- goto search1;
- }
- elif (eq(flag,S(Kexternal))) # :EXTERNAL
- { symtab = ThePackage(TheSvector(state)->data[4])->pack_external_symbols;
- goto search1;
- }
- elif (eq(flag,S(Kinherited))) # :INHERITED
- goto search4;
- goto search5; # unzulässiges Flag übergehen
- }} }
- value1 = NIL; mv_count=1; return; # 1 Wert NIL
- }
-
- # UP: Initialisiert die Packageverwaltung
- # init_packages();
- global void init_packages (void);
- global void init_packages()
- { pushSTACK(make_imm_array(asciz_to_string("LISP")));
- pushSTACK(make_imm_array(asciz_to_string("USER")));
- pushSTACK(make_imm_array(asciz_to_string("SYSTEM")));
- pushSTACK(make_imm_array(asciz_to_string("SYS")));
- pushSTACK(make_imm_array(asciz_to_string("KEYWORD")));
- pushSTACK(make_imm_array(asciz_to_string("")));
- # Stackaufbau: "LISP", "USER", "SYSTEM", "SYS", "KEYWORD", "".
- O(all_packages) = NIL; # ALL_PACKAGES := NIL
- # #<PACKAGE KEYWORD> einrichten:
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = popSTACK(); # ""
- O(keyword_package) = make_package(popSTACK(),new_cons); # "KEYWORD",("")
- }
- # #<PACKAGE SYSTEM> einrichten:
- {var reg1 object new_cons = allocate_cons();
- Car(new_cons) = STACK_0; # "SYS"
- STACK_0 = make_package(STACK_1,new_cons); # "SYSTEM",("SYS")
- }
- # #<PACKAGE USER> einrichten:
- O(default_package) = # und zur Default-Package machen
- STACK_2 = make_package(STACK_2,NIL); # "USER",()
- # #<PACKAGE LISP> einrichten:
- STACK_3 = STACK_1 = make_package(STACK_3,NIL); # "LISP",()
- # Stackaufbau: #<PACKAGE LISP>, #<PACKAGE USER>, #<PACKAGE LISP>, #<PACKAGE SYSTEM>.
- # (USE-PACKAGE '#<PACKAGE LISP> '#<PACKAGE SYSTEM>) :
- funcall(L(use_package),2);
- # (USE-PACKAGE '#<PACKAGE LISP> '#<PACKAGE USER>) :
- funcall(L(use_package),2);
- # Alle weiteren Packages einrichten, ans Ende der Liste ALL_PACKAGES hängen:
- nreverse(O(all_packages));
- #define LISPPACK LISPPACK_B
- #include "constpack.c"
- #undef LISPPACK
- nreverse(O(all_packages));
- }
-
-