12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313 |
- MODULE Stores;
- (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Stores.odc *)
- (* DO NOT EDIT *)
- IMPORT SYSTEM, Kernel, Dialog, Strings, Files;
- CONST
- (** Alien.cause, Reader.TurnIntoAlien cause - flagged by internalization procs **)
- alienVersion* = 1; alienComponent* = 2;
- (** Alien.cause - internally detected **)
- inconsistentVersion* = -1; inconsistentType* = -2;
- moduleFileNotFound* = -3; invalidModuleFile* = -4;
- inconsModuleVersion* = -5; typeNotFound* = -6;
- dictLineLen = 32; (* length of type & elem dict lines *)
- newBase = 0F0X; (* new base type (level = 0), i.e. not yet in dict *)
- newExt = 0F1X; (* new extension type (level = 1), i.e. not yet in dict *)
- oldType = 0F2X; (* old type, i.e. already in dict *)
- nil = 080X; (* nil store *)
- link = 081X; (* link to another elem in same file *)
- store = 082X; (* general store *)
- elem = 083X; (* elem store *)
- newlink = 084X; (* link to another non-elem store in same file *)
- minVersion = 0; maxStoreVersion = 0;
- elemTName = "Stores.ElemDesc"; (* type of pre-1.3 elems *)
- modelTName = "Models.ModelDesc"; (* the only known family of pre-1.3 elems *)
-
- inited = TRUE; anonymousDomain = FALSE; (* values to be used when calling NewDomain *)
-
- compatible = TRUE;
- TYPE
- TypeName* = ARRAY 64 OF CHAR;
- TypePath* = ARRAY 16 OF TypeName;
- OpName* = ARRAY 32 OF CHAR;
- Domain* = POINTER TO LIMITED RECORD
- sequencer: ANYPTR;
- dlink: Domain;
- initialized, copyDomain: BOOLEAN;
- level, copyera, nextElemId: INTEGER;
- sDict: StoreDict;
- cleaner: TrapCleaner;
- s: Store (* used for CopyOf *)
- END;
- Operation* = POINTER TO ABSTRACT RECORD END;
- Store* = POINTER TO ABSTRACT RECORD
- dlink: Domain;
- era, id: INTEGER; (* externalization era and id *)
- isElem: BOOLEAN (* to preserve file format: is this an elem in the old sense? *)
- END;
- AlienComp* = POINTER TO LIMITED RECORD
- next-: AlienComp
- END;
- AlienPiece* = POINTER TO LIMITED RECORD (AlienComp)
- pos-, len-: INTEGER
- END;
- AlienPart* = POINTER TO LIMITED RECORD (AlienComp)
- store-: Store
- END;
- Alien* = POINTER TO LIMITED RECORD (Store)
- path-: TypePath; (** the type this store would have if it were not an alien **)
- cause-: INTEGER; (** # 0, the cause that turned this store into an alien **)
- file-: Files.File; (** base file holding alien pieces **)
- comps-: AlienComp (** the constituent components of this alien store **)
- END;
- ReaderState = RECORD
- next: INTEGER; (* position of next store in current level *)
- end: INTEGER (* position just after last read store *)
- END;
- WriterState = RECORD
- linkpos: INTEGER (* address of threading link *)
- END;
- TypeDict = POINTER TO RECORD
- next: TypeDict;
- org: INTEGER; (* origin id of this dict line *)
- type: ARRAY dictLineLen OF TypeName; (* type[org] .. type[org + dictLineLen - 1] *)
- baseId: ARRAY dictLineLen OF INTEGER
- END;
- StoreDict = POINTER TO RECORD
- next: StoreDict;
- org: INTEGER; (* origin id of this dict line *)
- elem: ARRAY dictLineLen OF Store (* elem[org] .. elem[org + dictLineLen - 1] *)
- END;
- Reader* = RECORD
- rider-: Files.Reader;
- cancelled-: BOOLEAN; (** current Internalize has been cancelled **)
- readAlien-: BOOLEAN; (** at least one alien read since ConnectTo **)
- cause: INTEGER;
- nextTypeId, nextElemId, nextStoreId: INTEGER; (* next id of non-dict type, "elem", store *)
- tDict, tHead: TypeDict; (* mapping (id <-> type) - self-organizing list *)
- eDict, eHead: StoreDict; (* mapping (id -> elem) - self-organizing list *)
- sDict, sHead: StoreDict; (* mapping (id -> store) - self-organizing list *)
- st: ReaderState;
- noDomain: BOOLEAN;
- store: Store
- END;
- Writer* = RECORD
- rider-: Files.Writer;
- writtenStore-: Store;
- era: INTEGER; (* current externalization era *)
- noDomain: BOOLEAN; (* no domain encountered yet *)
- modelType: Kernel.Type;
- domain: Domain; (* domain of current era *)
- nextTypeId, nextElemId, nextStoreId: INTEGER; (* next id of non-dict type or elem *)
- tDict, tHead: TypeDict; (* mapping (id -> type) - self-organizing list *)
- st: WriterState
- END;
- TrapCleaner = POINTER TO RECORD (Kernel.TrapCleaner)
- d: Domain
- END;
- VAR
- nextEra: INTEGER; (* next externalization era *)
- thisTypeRes: INTEGER; (* side-effect res code of ThisType *)
- logReports: BOOLEAN;
- (** Cleaner **)
- PROCEDURE (c: TrapCleaner) Cleanup;
- BEGIN
- c.d.level := 0;
- c.d.sDict := NIL;
- c.d.s := NIL
- END Cleanup;
- PROCEDURE (d: Domain) SetSequencer* (sequencer: ANYPTR), NEW;
- BEGIN
- ASSERT(d.sequencer = NIL);
- d.sequencer := sequencer
- END SetSequencer;
-
- PROCEDURE (d: Domain) GetSequencer*(): ANYPTR, NEW;
- BEGIN
- RETURN d.sequencer
- END GetSequencer;
- PROCEDURE^ Report* (IN msg, p0, p1, p2: ARRAY OF CHAR);
-
- PROCEDURE^ (VAR rd: Reader) SetPos* (pos: INTEGER), NEW;
- PROCEDURE^ (VAR rd: Reader) ReadVersion* (min, max: INTEGER; OUT version: INTEGER), NEW;
- PROCEDURE^ (VAR rd: Reader) ReadSChar* (OUT x: SHORTCHAR), NEW;
- PROCEDURE^ (VAR rd: Reader) ReadInt* (OUT x: INTEGER), NEW;
- PROCEDURE^ (VAR rd: Reader) ReadXString* (OUT x: ARRAY OF CHAR), NEW;
- PROCEDURE^ (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
-
- PROCEDURE^ (VAR wr: Writer) SetPos* (pos: INTEGER), NEW;
- PROCEDURE^ (VAR wr: Writer) WriteVersion* (version: INTEGER), NEW;
- PROCEDURE^ (VAR wr: Writer) WriteSChar* (x: SHORTCHAR), NEW;
- PROCEDURE^ (VAR wr: Writer) WriteInt* (x: INTEGER), NEW;
- PROCEDURE^ (VAR wr: Writer) WriteXString* (IN x: ARRAY OF CHAR), NEW;
- PROCEDURE^ (VAR wr: Writer) WriteStore* (x: Store), NEW;
-
- PROCEDURE^ Join* (s0, s1: Store);
- (** Operation **)
- PROCEDURE (op: Operation) Do* (), NEW, ABSTRACT;
- (** Store **)
- PROCEDURE NewDomain (initialized: BOOLEAN): Domain;
- VAR d: Domain;
- BEGIN
- NEW(d); d.level := 0; d.sDict := NIL; d.cleaner := NIL;
- d.initialized := initialized; d.copyDomain := FALSE;
- RETURN d
- END NewDomain;
- PROCEDURE DomainOf (s: Store): Domain;
- VAR d, p, q, r: Domain;
- BEGIN
- d := s.dlink;
- IF (d # NIL) & (d.dlink # NIL) THEN
- p := NIL; q := d; r := q.dlink;
- WHILE r # NIL DO q.dlink := p; p := q; q := r; r := q.dlink END;
- d := q;
- WHILE p # NIL DO q := p; p := q.dlink; q.dlink := d END;
- s.dlink := d
- END;
- RETURN d
- END DomainOf;
- PROCEDURE (s: Store) Domain*(): Domain, NEW;
- VAR d: Domain;
- BEGIN
- d := DomainOf(s);
- IF (d # NIL) & ~d.initialized THEN d := NIL END;
- RETURN d
- END Domain;
-
- PROCEDURE (s: Store) CopyFrom- (source: Store), NEW, EMPTY;
- PROCEDURE (s: Store) Internalize- (VAR rd: Reader), NEW, EXTENSIBLE;
- VAR thisVersion: INTEGER;
- BEGIN
- rd.ReadVersion(minVersion, maxStoreVersion, thisVersion);
- IF ~rd.cancelled & s.isElem THEN
- rd.ReadVersion(minVersion, maxStoreVersion, thisVersion)
- (* works since maxStoreVersion = maxElemVersion = 0 in pre-1.3 *)
- END
- END Internalize;
- PROCEDURE (s: Store) ExternalizeAs- (VAR s1: Store), NEW, EMPTY;
- PROCEDURE (s: Store) Externalize- (VAR wr: Writer), NEW, EXTENSIBLE;
- BEGIN
- wr.WriteVersion(maxStoreVersion);
- IF s.isElem THEN wr.WriteVersion(maxStoreVersion) END
- END Externalize;
- (** Alien **)
- PROCEDURE^ CopyOf* (s: Store): Store;
- PROCEDURE (a: Alien) CopyFrom- (source: Store);
- VAR s, c, cp: AlienComp; piece: AlienPiece; part: AlienPart;
- BEGIN
- WITH source: Alien DO
- a.path := source.path;
- a.cause := source.cause;
- a.file := source.file;
- a.comps := NIL;
- s := source.comps; cp := NIL;
- WHILE s # NIL DO
- WITH s: AlienPiece DO
- NEW(piece); c := piece;
- piece.pos := s.pos; piece.len := s.len
- | s: AlienPart DO
- NEW(part); c := part;
- IF s.store # NIL THEN part.store := CopyOf(s.store); Join(part.store, a) END
- END;
- IF cp # NIL THEN cp.next := c ELSE a.comps := c END;
- cp := c;
- s := s.next
- END
- END
- END CopyFrom;
- PROCEDURE (a: Alien) Internalize- (VAR rd: Reader);
- BEGIN
- HALT(100)
- END Internalize;
- PROCEDURE (a: Alien) Externalize- (VAR w: Writer);
- BEGIN
- HALT(100)
- END Externalize;
- (* types *)
- PROCEDURE GetThisTypeName (t: Kernel.Type; VAR type: TypeName);
- VAR i, j: INTEGER; ch: CHAR; name: Kernel.Name;
- BEGIN
- Kernel.GetTypeName(t, name); type := t.mod.name$;
- i := 0; ch := type[0]; WHILE ch # 0X DO INC(i); ch := type[i] END;
- type[i] := "."; INC(i);
- j := 0; REPEAT ch := name[j]; type[i] := ch; INC(i); INC(j) UNTIL ch = 0X;
- IF compatible THEN
- IF type[i-2] = "^" THEN (* for backward compatibility *)
- type[i-2] := "D"; type[i-1] := "e"; type[i] := "s"; type[i+1] := "c"; type[i+2] := 0X
- END
- END
- END GetThisTypeName;
- PROCEDURE ThisType (type: TypeName): Kernel.Type;
- VAR m: Kernel.Module; t: Kernel.Type; i, j: INTEGER; ch: CHAR;
- typ: Kernel.Name; mod: ARRAY 256 OF CHAR; res: INTEGER; str: ARRAY 256 OF CHAR;
- BEGIN
- ASSERT(type # "", 20);
- i := 0; ch := type[0];
- WHILE (ch # ".") & (ch # 0X) DO mod[i] := SHORT(ch); INC(i); ch := type[i] END;
- ASSERT(ch = ".", 21);
- mod[i] := 0X; INC(i);
- m := Kernel.ThisMod(mod);
- IF m # NIL THEN
- j := 0; REPEAT ch := type[i]; typ[j] := SHORT(ch); INC(i); INC(j) UNTIL ch = 0X;
- t := Kernel.ThisType(m, typ);
- IF (t = NIL) & (j >= 5) THEN (* try pointer type *)
- IF (typ[j-5] = "D") & (typ[j-4] = "e") & (typ[j-3] = "s") & (typ[j-2] = "c") THEN
- typ[j-5] := "^"; typ[j-4] := 0X;
- t := Kernel.ThisType(m, typ)
- END
- END;
- IF t = NIL THEN thisTypeRes := typeNotFound END
- ELSE
- t := NIL;
- Kernel.GetLoaderResult(res, str, str, str);
- CASE res OF
- | Kernel.fileNotFound: thisTypeRes := moduleFileNotFound
- | Kernel.syntaxError: thisTypeRes := invalidModuleFile
- | Kernel.objNotFound: thisTypeRes := inconsModuleVersion
- | Kernel.illegalFPrint: thisTypeRes := inconsModuleVersion
- | Kernel.cyclicImport: thisTypeRes := invalidModuleFile (* cyclic import ... *)
- ELSE thisTypeRes := invalidModuleFile
- END
- END;
- RETURN t
- END ThisType;
-
- PROCEDURE SameType (IN x, y: TypeName): BOOLEAN;
- VAR i: INTEGER;
- BEGIN
- IF x = y THEN RETURN TRUE
- ELSE
- i := 0; WHILE x[i] = y[i] DO INC(i) END;
- RETURN
- (x[i] = "^") & (x[i+1] = 0X) & (y[i] = "D") & (y[i+1] = "e") & (y[i+2] = "s") & (y[i+3] = "c") & (y[i+4] = 0X)
- OR (y[i] = "^") & (y[i+1] = 0X) & (x[i] = "D") & (x[i+1] = "e") & (x[i+2] = "s") & (x[i+3] = "c") & (x[i+4] = 0X)
- END
- END SameType;
- PROCEDURE SamePath (t: Kernel.Type; VAR path: TypePath): BOOLEAN;
- (* check whether t coincides with path *)
- VAR tn: TypeName; i, n: INTEGER;
- BEGIN
- i := -1; n := Kernel.LevelOf(t);
- REPEAT
- GetThisTypeName(t.base[n], tn);
- DEC(n); INC(i)
- UNTIL (n < 0) OR ~SameType(tn, path[i]);
- RETURN SameType(tn, path[i])
- END SamePath;
- PROCEDURE NewStore (t: Kernel.Type): Store;
- VAR p: ANYPTR;
- BEGIN
- ASSERT(t # NIL, 20);
- Kernel.NewObj(p, t); ASSERT(p # NIL, 100);
- ASSERT(p IS Store, 21);
- RETURN p(Store)
- END NewStore;
- (* type dictionary *)
- PROCEDURE GetThisType (VAR d: TypeDict; id: INTEGER; VAR type: TypeName);
- (* pre: (id, t) IN dict *)
- VAR h, p: TypeDict; org, k: INTEGER;
- BEGIN
- k := id MOD dictLineLen; org := id - k;
- h := NIL; p := d; WHILE p.org # org DO h := p; p := p.next END;
- IF h # NIL THEN h.next := p.next; p.next := d; d := p END;
- type := p.type[k];
- ASSERT(type # "", 100)
- END GetThisType;
- PROCEDURE ThisId (VAR d: TypeDict; t: TypeName): INTEGER;
- (* pre: t # "" *)
- (* post: res = id if (t, id) in dict, res = -1 else *)
- VAR h, p: TypeDict; k, id: INTEGER;
- BEGIN
- h := NIL; p := d; id := -1;
- WHILE (p # NIL) & (id < 0) DO
- k := 0; WHILE (k < dictLineLen) & (p.type[k, 0] # 0X) & (p.type[k] # t) DO INC(k) END;
- IF (k < dictLineLen) & (p.type[k, 0] # 0X) THEN id := p.org + k
- ELSE h := p; p := p.next
- END
- END;
- IF (id >= 0) & (h # NIL) THEN h.next := p.next; p.next := d; d := p END;
- RETURN id
- END ThisId;
- PROCEDURE ThisBaseId (VAR d: TypeDict; id: INTEGER): INTEGER;
- (* post: res = id if base(t) # NIL, res = -1 if base(t) = NIL; res >= 0 => T(res) = base(t) *)
- VAR h, p: TypeDict; k, org, baseId: INTEGER;
- BEGIN
- k := id MOD dictLineLen; org := id - k;
- h := NIL; p := d; WHILE p.org # org DO h := p; p := p.next END;
- IF h # NIL THEN h.next := p.next; p.next := d; d := p END;
- baseId := p.baseId[k];
- RETURN baseId
- END ThisBaseId;
- PROCEDURE AddType (VAR d, h: TypeDict; id: INTEGER; type: TypeName);
- VAR k: INTEGER;
- BEGIN
- k := id MOD dictLineLen;
- IF (h = NIL) OR ((k = 0) & (h.org # id)) THEN
- NEW(h); h.org := id - k; h.next := d; d := h
- END;
- h.type[k] := type; h.baseId[k] := -1
- END AddType;
- PROCEDURE AddBaseId (h: TypeDict; id, baseId: INTEGER);
- VAR k: INTEGER;
- BEGIN
- k := id MOD dictLineLen;
- h.baseId[k] := baseId
- END AddBaseId;
- PROCEDURE InitTypeDict (VAR d, h: TypeDict; VAR nextID: INTEGER);
- BEGIN
- d := NIL; h := NIL; nextID := 0
- END InitTypeDict;
- (* store dictionary - used to maintain referential sharing *)
- PROCEDURE ThisStore (VAR d: StoreDict; id: INTEGER): Store;
- (* pre: (id, s) IN dict *)
- VAR h, p: StoreDict; s: Store; k, org: INTEGER;
- BEGIN
- k := id MOD dictLineLen; org := id - k;
- h := NIL; p := d; WHILE p.org # org DO h := p; p := p.next END;
- IF h # NIL THEN h.next := p.next; p.next := d; d := p END;
- s := p.elem[k];
- ASSERT(s # NIL, 100);
- RETURN s
- END ThisStore;
- PROCEDURE AddStore (VAR d, h: StoreDict; s: Store);
- VAR k: INTEGER;
- BEGIN
- k := s.id MOD dictLineLen;
- IF (h = NIL) OR ((k = 0) & (h.org # s.id)) THEN
- NEW(h); h.org := s.id - k; h.next := d; d := h
- END;
- h.elem[k] := s
- END AddStore;
- PROCEDURE InitStoreDict (VAR d, h: StoreDict; VAR nextID: INTEGER);
- BEGIN
- d := NIL; h := NIL; nextID := 0
- END InitStoreDict;
- (* support for type mapping *)
- PROCEDURE ReadPath (VAR rd: Reader; VAR path: TypePath);
- VAR h: TypeDict; id, extId: INTEGER; i: INTEGER; kind: SHORTCHAR;
- PROCEDURE AddPathComp (VAR rd: Reader);
- BEGIN
- IF h # NIL THEN AddBaseId(h, extId, rd.nextTypeId) END;
- AddType(rd.tDict, rd.tHead, rd.nextTypeId, path[i]);
- h := rd.tHead; extId := rd.nextTypeId
- END AddPathComp;
- BEGIN
- h := NIL; i := 0; rd.ReadSChar(kind);
- WHILE kind = newExt DO
- rd.ReadXString(path[i]);
- AddPathComp(rd); INC(rd.nextTypeId);
- IF path[i] # elemTName THEN INC(i) END;
- rd.ReadSChar(kind)
- END;
- IF kind = newBase THEN
- rd.ReadXString(path[i]);
- AddPathComp(rd); INC(rd.nextTypeId); INC(i)
- ELSE
- ASSERT(kind = oldType, 100);
- rd.ReadInt(id);
- IF h # NIL THEN AddBaseId(h, extId, id) END;
- REPEAT
- GetThisType(rd.tDict, id, path[i]); id := ThisBaseId(rd.tDict, id);
- IF path[i] # elemTName THEN INC(i) END
- UNTIL id = -1
- END;
- path[i] := ""
- END ReadPath;
- PROCEDURE WritePath (VAR wr: Writer; VAR path: TypePath);
- VAR h: TypeDict; id, extId: INTEGER; i, n: INTEGER;
- BEGIN
- h := NIL;
- n := 0; WHILE path[n] # "" DO INC(n) END;
- i := 0;
- WHILE i < n DO
- id := ThisId(wr.tDict, path[i]);
- IF id >= 0 THEN
- IF h # NIL THEN AddBaseId(h, extId, id) END;
- wr.WriteSChar(oldType); wr.WriteInt(id); n := i
- ELSE
- IF i + 1 < n THEN wr.WriteSChar(newExt) ELSE wr.WriteSChar(newBase) END;
- wr.WriteXString(path[i]);
- IF h # NIL THEN AddBaseId(h, extId, wr.nextTypeId) END;
- AddType(wr.tDict, wr.tHead, wr.nextTypeId, path[i]);
- h := wr.tHead; extId := wr.nextTypeId;
- INC(wr.nextTypeId);
- IF path[i] = modelTName THEN
- id := ThisId(wr.tDict, elemTName); ASSERT(id < 0, 100); ASSERT(i + 2 = n, 101);
- wr.WriteSChar(newExt); wr.WriteXString(elemTName);
- IF h # NIL THEN AddBaseId(h, extId, wr.nextTypeId) END;
- AddType(wr.tDict, wr.tHead, wr.nextTypeId, elemTName);
- h := wr.tHead; extId := wr.nextTypeId;
- INC(wr.nextTypeId)
- END
- END;
- INC(i)
- END
- END WritePath;
- PROCEDURE WriteType (VAR wr: Writer; t: Kernel.Type);
- VAR path: TypePath; n, i: INTEGER;
- BEGIN
- i := 0; n := Kernel.LevelOf(t);
- WHILE n >= 0 DO
- GetThisTypeName(t.base[n], path[i]);
- DEC(n); INC(i)
- END;
- path[i] := "";
- WritePath(wr, path)
- END WriteType;
- (* support for alien mapping *)
- PROCEDURE InternalizeAlien (VAR rd: Reader; VAR comps: AlienComp; down, pos, len: INTEGER);
- VAR h, p: AlienComp; piece: AlienPiece; part: AlienPart; file: Files.File;
- next, end, max: INTEGER;
- BEGIN
- file := rd.rider.Base(); max := file.Length();
- end := pos + len; h := NIL;
- IF down # 0 THEN next := down ELSE next := end END;
- WHILE pos < end DO
- ASSERT(end <= max, 100);
- IF pos < next THEN
- NEW(piece); piece.pos := pos; piece.len := next - pos;
- p := piece; pos := next
- ELSE
- ASSERT(pos = next, 101);
- rd.SetPos(next);
- NEW(part); rd.ReadStore(part.store);
- ASSERT(rd.st.end > next, 102);
- p := part; pos := rd.st.end;
- IF rd.st.next > 0 THEN
- ASSERT(rd.st.next > next, 103); next := rd.st.next
- ELSE next := end
- END
- END;
- IF h = NIL THEN comps := p ELSE h.next := p END;
- h := p
- END;
- ASSERT(pos = end, 104);
- rd.SetPos(end)
- END InternalizeAlien;
- PROCEDURE ExternalizePiece (VAR wr: Writer; file: Files.File; p: AlienPiece);
- VAR r: Files.Reader; w: Files.Writer; b: BYTE; l, len: INTEGER;
- BEGIN
- l := file.Length(); len := p.len;
- ASSERT(0 <= p.pos, 100); ASSERT(p.pos <= l, 101);
- ASSERT(0 <= len, 102); ASSERT(len <= l - p.pos, 103);
- r := file.NewReader(NIL); r.SetPos(p.pos);
- w := wr.rider;
- WHILE len # 0 DO r.ReadByte(b); w.WriteByte(b); DEC(len) END
- END ExternalizePiece;
- PROCEDURE ExternalizeAlien (VAR wr: Writer; file: Files.File; comps: AlienComp);
- VAR p: AlienComp;
- BEGIN
- p := comps;
- WHILE p # NIL DO
- WITH p: AlienPiece DO
- ExternalizePiece(wr, file, p)
- | p: AlienPart DO
- wr.WriteStore(p.store)
- END;
- p := p.next
- END
- END ExternalizeAlien;
- (** Reader **)
- PROCEDURE (VAR rd: Reader) ConnectTo* (f: Files.File), NEW;
- (** pre: rd.rider = NIL OR f = NIL **)
- BEGIN
- IF f = NIL THEN
- rd.rider := NIL
- ELSE
- ASSERT(rd.rider = NIL, 20);
- rd.rider := f.NewReader(rd.rider); rd.SetPos(0);
- InitTypeDict(rd.tDict, rd.tHead, rd.nextTypeId);
- InitStoreDict(rd.eDict, rd.eHead, rd.nextElemId);
- InitStoreDict(rd.sDict, rd.sHead, rd.nextStoreId);
- rd.noDomain := TRUE
- END;
- rd.readAlien := FALSE
- END ConnectTo;
- PROCEDURE (VAR rd: Reader) SetPos* (pos: INTEGER), NEW;
- BEGIN
- rd.rider.SetPos(pos)
- END SetPos;
- PROCEDURE (VAR rd: Reader) Pos* (): INTEGER, NEW;
- BEGIN
- RETURN rd.rider.Pos()
- END Pos;
- PROCEDURE (VAR rd: Reader) ReadBool* (OUT x: BOOLEAN), NEW;
- VAR b: BYTE;
- BEGIN
- rd.rider.ReadByte(b); x := b # 0
- END ReadBool;
- PROCEDURE (VAR rd: Reader) ReadSChar* (OUT x: SHORTCHAR), NEW;
- BEGIN
- rd.rider.ReadByte(SYSTEM.VAL(BYTE, x))
- END ReadSChar;
- PROCEDURE (VAR rd: Reader) ReadXChar* (OUT x: CHAR), NEW;
- VAR c: SHORTCHAR;
- BEGIN
- rd.rider.ReadByte(SYSTEM.VAL(BYTE,c)); x := c
- END ReadXChar;
- PROCEDURE (VAR rd: Reader) ReadChar* (OUT x: CHAR), NEW;
- VAR le: ARRAY 2 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 2);
- x := CHR(le[0] MOD 256 + (le[1] MOD 256) * 256)
- END ReadChar;
- PROCEDURE (VAR rd: Reader) ReadByte* (OUT x: BYTE), NEW;
- BEGIN
- rd.rider.ReadByte(x)
- END ReadByte;
- PROCEDURE (VAR rd: Reader) ReadSInt* (OUT x: SHORTINT), NEW;
- VAR le, be: ARRAY 2 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 2);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(SHORTINT, le)
- ELSE
- be[0] := le[1]; be[1] := le[0];
- x := SYSTEM.VAL(SHORTINT, be)
- END
- END ReadSInt;
- PROCEDURE (VAR rd: Reader) ReadXInt* (OUT x: INTEGER), NEW;
- VAR le, be: ARRAY 2 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 2);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(SHORTINT, le)
- ELSE
- be[0] := le[1]; be[1] := le[0];
- x := SYSTEM.VAL(SHORTINT, be)
- END
- END ReadXInt;
- PROCEDURE (VAR rd: Reader) ReadInt* (OUT x: INTEGER), NEW;
- VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 4);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(INTEGER, le)
- ELSE
- be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
- x := SYSTEM.VAL(INTEGER, be)
- END
- END ReadInt;
- PROCEDURE (VAR rd: Reader) ReadLong* (OUT x: LONGINT), NEW;
- VAR le, be: ARRAY 8 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 8);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(LONGINT, le)
- ELSE
- be[0] := le[7]; be[1] := le[6]; be[2] := le[5]; be[3] := le[4];
- be[4] := le[3]; be[5] := le[2]; be[6] := le[1]; be[7] := le[0];
- x := SYSTEM.VAL(LONGINT, be)
- END
- END ReadLong;
- PROCEDURE (VAR rd: Reader) ReadSReal* (OUT x: SHORTREAL), NEW;
- VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 4);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(SHORTREAL, le)
- ELSE
- be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
- x := SYSTEM.VAL(SHORTREAL, be)
- END
- END ReadSReal;
- PROCEDURE (VAR rd: Reader) ReadXReal* (OUT x: REAL), NEW;
- VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 4);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(SHORTREAL, le)
- ELSE
- be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
- x := SYSTEM.VAL(SHORTREAL, be)
- END
- END ReadXReal;
- PROCEDURE (VAR rd: Reader) ReadReal* (OUT x: REAL), NEW;
- VAR le, be: ARRAY 8 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 8);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(REAL, le)
- ELSE
- be[0] := le[7]; be[1] := le[6]; be[2] := le[5]; be[3] := le[4];
- be[4] := le[3]; be[5] := le[2]; be[6] := le[1]; be[7] := le[0];
- x := SYSTEM.VAL(REAL, be)
- END
- END ReadReal;
- PROCEDURE (VAR rd: Reader) ReadSet* (OUT x: SET), NEW;
- VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
- BEGIN
- rd.rider.ReadBytes(le, 0, 4);
- IF Kernel.littleEndian THEN
- x := SYSTEM.VAL(SET, le)
- ELSE
- be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
- x := SYSTEM.VAL(SET, be)
- END
- END ReadSet;
- PROCEDURE (VAR rd: Reader) ReadSString* (OUT x: ARRAY OF SHORTCHAR), NEW;
- VAR i: INTEGER; ch: SHORTCHAR;
- BEGIN
- i := 0; REPEAT rd.ReadSChar(ch); x[i] := ch; INC(i) UNTIL ch = 0X
- END ReadSString;
- PROCEDURE (VAR rd: Reader) ReadXString* (OUT x: ARRAY OF CHAR), NEW;
- VAR i: INTEGER; ch: CHAR;
- BEGIN
- i := 0; REPEAT rd.ReadXChar(ch); x[i] := ch; INC(i) UNTIL ch = 0X
- END ReadXString;
- PROCEDURE (VAR rd: Reader) ReadString* (OUT x: ARRAY OF CHAR), NEW;
- VAR i: INTEGER; ch: CHAR;
- BEGIN
- i := 0; REPEAT rd.ReadChar(ch); x[i] := ch; INC(i) UNTIL ch = 0X
- END ReadString;
- PROCEDURE AlienReport (cause: INTEGER);
- VAR s, e: ARRAY 32 OF CHAR;
- BEGIN
- CASE cause OF
- | alienVersion: s := "#System:AlienVersion"
- | alienComponent: s := "#System:AlienComponent"
- | inconsistentVersion: s := "#System:InconsistentVersion"
- ELSE s := "#System:UnknownCause"
- END;
- Strings.IntToString(cause, e);
- Report("#System:AlienCause ^0 ^1 ^2", s, e, "")
- END AlienReport;
- PROCEDURE AlienTypeReport (cause: INTEGER; t: ARRAY OF CHAR);
- VAR s: ARRAY 64 OF CHAR;
- BEGIN
- CASE cause OF
- | inconsistentType: s := "#System:InconsistentType ^0"
- | moduleFileNotFound: s := "#System:CodeFileNotFound ^0"
- | invalidModuleFile: s := "#System:InvalidCodeFile ^0"
- | inconsModuleVersion: s := "#System:InconsistentModuleVersion ^0"
- | typeNotFound: s := "#System:TypeNotFound ^0"
- END;
- Report(s, t, "", "")
- END AlienTypeReport;
- PROCEDURE (VAR rd: Reader) TurnIntoAlien* (cause: INTEGER), NEW;
- BEGIN
- ASSERT(cause > 0, 20);
- rd.cancelled := TRUE; rd.readAlien := TRUE; rd.cause := cause;
- AlienReport(cause)
- END TurnIntoAlien;
- PROCEDURE (VAR rd: Reader) ReadVersion* (min, max: INTEGER; OUT version: INTEGER), NEW;
- VAR v: BYTE;
- BEGIN
- rd.ReadByte(v); version := v;
- IF (version < min) OR (version > max) THEN
- rd.TurnIntoAlien(alienVersion)
- END
- END ReadVersion;
- PROCEDURE (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
- VAR a: Alien; t: Kernel.Type;
- len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
- kind: SHORTCHAR; path: TypePath; type: TypeName;
- save: ReaderState;
- BEGIN
- rd.ReadSChar(kind);
- IF kind = nil THEN
- rd.ReadInt(comment); rd.ReadInt(next);
- rd.st.end := rd.Pos();
- IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
- x := NIL
- ELSIF kind = link THEN
- rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
- rd.st.end := rd.Pos();
- IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
- x := ThisStore(rd.eDict, id)
- ELSIF kind = newlink THEN
- rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
- rd.st.end := rd.Pos();
- IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
- x := ThisStore(rd.sDict, id)
- ELSIF (kind = store) OR (kind = elem) THEN
- IF kind = elem THEN
- id := rd.nextElemId; INC(rd.nextElemId)
- ELSE
- id := rd.nextStoreId; INC(rd.nextStoreId)
- END;
- ReadPath(rd, path); type := path[0];
- nextTypeId := rd.nextTypeId; nextElemId := rd.nextElemId; nextStoreId := rd.nextStoreId;
- rd.ReadInt(comment);
- pos1 := rd.Pos();
- rd.ReadInt(next); rd.ReadInt(down); rd.ReadInt(len);
- pos := rd.Pos();
- IF next > 0 THEN rd.st.next := pos1 + next + 4 ELSE rd.st.next := 0 END;
- IF down > 0 THEN downPos := pos1 + down + 8 ELSE downPos := 0 END;
- rd.st.end := pos + len;
- rd.cause := 0;
- ASSERT(len >= 0, 101);
- IF next # 0 THEN
- ASSERT(rd.st.next > pos1, 102);
- IF down # 0 THEN
- ASSERT(downPos < rd.st.next, 103)
- END
- END;
- IF down # 0 THEN
- ASSERT(downPos > pos1, 104);
- ASSERT(downPos < rd.st.end, 105)
- END;
- t := ThisType(type);
- IF t # NIL THEN
- x := NewStore(t); x.isElem := kind = elem
- ELSE
- rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
- x := NIL
- END;
- IF x # NIL THEN
- IF SamePath(t, path) THEN
- IF kind = elem THEN
- x.id := id; AddStore(rd.eDict, rd.eHead, x)
- ELSE
- x.id := id; AddStore(rd.sDict, rd.sHead, x)
- END;
- save := rd.st; rd.cause := 0; rd.cancelled := FALSE;
- x.Internalize(rd);
- rd.st := save;
- IF rd.cause # 0 THEN x := NIL
- ELSIF (rd.Pos() # rd.st.end) OR rd.rider.eof THEN
- rd.cause := inconsistentVersion; AlienReport(rd.cause);
- x := NIL
- END
- ELSE
- rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
- x := NIL
- END
- END;
-
- IF x # NIL THEN
- IF rd.noDomain THEN
- rd.store := x;
- rd.noDomain := FALSE
- ELSE
- Join(rd.store, x)
- END
- ELSE (* x is an alien *)
- rd.SetPos(pos);
- ASSERT(rd.cause # 0, 107);
- NEW(a); a.path := path; a.cause := rd.cause; a.file := rd.rider.Base();
- IF rd.noDomain THEN
- rd.store := a;
- rd.noDomain := FALSE
- ELSE
- Join(rd.store, a)
- END;
- IF kind = elem THEN
- a.id := id; AddStore(rd.eDict, rd.eHead, a)
- ELSE
- a.id := id; AddStore(rd.sDict, rd.sHead, a)
- END;
- save := rd.st;
- rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
- InternalizeAlien(rd, a.comps, downPos, pos, len);
- rd.st := save;
- x := a;
- ASSERT(rd.Pos() = rd.st.end, 108);
- rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE
- END
- ELSE
- pos := rd.Pos();
- HALT(20)
- END
- END ReadStore;
- (** Writer **)
- PROCEDURE (VAR wr: Writer) ConnectTo* (f: Files.File), NEW;
- (** pre: wr.rider = NIL OR f = NIL **)
- BEGIN
- IF f = NIL THEN
- wr.rider := NIL
- ELSE
- ASSERT(wr.rider = NIL, 20);
- wr.rider := f.NewWriter(wr.rider); wr.SetPos(f.Length());
- wr.era := nextEra; INC(nextEra);
- wr.noDomain := TRUE;
- wr.modelType := ThisType(modelTName);
- InitTypeDict(wr.tDict, wr.tHead, wr.nextTypeId);
- wr.nextElemId := 0; wr.nextStoreId := 0;
- wr.st.linkpos := -1
- END;
- wr.writtenStore := NIL
- END ConnectTo;
- PROCEDURE (VAR wr: Writer) SetPos* (pos: INTEGER), NEW;
- BEGIN
- wr.rider.SetPos(pos)
- END SetPos;
- PROCEDURE (VAR wr: Writer) Pos* (): INTEGER, NEW;
- BEGIN
- RETURN wr.rider.Pos()
- END Pos;
- PROCEDURE (VAR wr: Writer) WriteBool* (x: BOOLEAN), NEW;
- BEGIN
- IF x THEN wr.rider.WriteByte(1) ELSE wr.rider.WriteByte(0) END
- END WriteBool;
- PROCEDURE (VAR wr: Writer) WriteSChar* (x: SHORTCHAR), NEW;
- BEGIN
- wr.rider.WriteByte(SYSTEM.VAL(BYTE, x))
- END WriteSChar;
- PROCEDURE (VAR wr: Writer) WriteXChar* (x: CHAR), NEW;
- VAR c: SHORTCHAR;
- BEGIN
- c := SHORT(x); wr.rider.WriteByte(SYSTEM.VAL(BYTE, c))
- END WriteXChar;
- PROCEDURE (VAR wr: Writer) WriteChar* (x: CHAR), NEW;
- TYPE a = ARRAY 2 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[1]; le[1] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 2)
- END WriteChar;
- PROCEDURE (VAR wr: Writer) WriteByte* (x: BYTE), NEW;
- BEGIN
- wr.rider.WriteByte(x)
- END WriteByte;
- PROCEDURE (VAR wr: Writer) WriteSInt* (x: SHORTINT), NEW;
- TYPE a = ARRAY 2 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[1]; le[1] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 2)
- END WriteSInt;
- PROCEDURE (VAR wr: Writer) WriteXInt* (x: INTEGER), NEW;
- TYPE a = ARRAY 2 OF BYTE;
- VAR y: SHORTINT; le, be: a; (* little endian, big endian *)
- BEGIN
- y := SHORT(x);
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, y)
- ELSE
- be := SYSTEM.VAL(a, y);
- le[0] := be[1]; le[1] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 2)
- END WriteXInt;
- PROCEDURE (VAR wr: Writer) WriteInt* (x: INTEGER), NEW;
- TYPE a = ARRAY 4 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 4)
- END WriteInt;
- PROCEDURE (VAR wr: Writer) WriteLong* (x: LONGINT), NEW;
- TYPE a = ARRAY 8 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[7]; le[1] := be[6]; le[2] := be[5]; le[3] := be[4];
- le[4] := be[3]; le[5] := be[2]; le[6] := be[1]; le[7] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 8)
- END WriteLong;
- PROCEDURE (VAR wr: Writer) WriteSReal* (x: SHORTREAL), NEW;
- TYPE a = ARRAY 4 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 4)
- END WriteSReal;
- PROCEDURE (VAR wr: Writer) WriteXReal* (x: REAL), NEW;
- TYPE a = ARRAY 4 OF BYTE;
- VAR y: SHORTREAL; le, be: a; (* little endian, big endian *)
- BEGIN
- y := SHORT(x);
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, y)
- ELSE
- be := SYSTEM.VAL(a, y);
- le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 4)
- END WriteXReal;
- PROCEDURE (VAR wr: Writer) WriteReal* (x: REAL), NEW;
- TYPE a = ARRAY 8 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[7]; le[1] := be[6]; le[2] := be[5]; le[3] := be[4];
- le[4] := be[3]; le[5] := be[2]; le[6] := be[1]; le[7] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 8)
- END WriteReal;
- PROCEDURE (VAR wr: Writer) WriteSet* (x: SET), NEW;
- (* SIZE(SET) = 4 *)
- TYPE a = ARRAY 4 OF BYTE;
- VAR le, be: a; (* little endian, big endian *)
- BEGIN
- IF Kernel.littleEndian THEN
- le := SYSTEM.VAL(a, x)
- ELSE
- be := SYSTEM.VAL(a, x);
- le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
- END;
- wr.rider.WriteBytes(le, 0, 4)
- END WriteSet;
- PROCEDURE (VAR wr: Writer) WriteSString* (IN x: ARRAY OF SHORTCHAR), NEW;
- VAR i: INTEGER; ch: SHORTCHAR;
- BEGIN
- i := 0; ch := x[0]; WHILE ch # 0X DO wr.WriteSChar(ch); INC(i); ch := x[i] END;
- wr.WriteSChar(0X)
- END WriteSString;
- PROCEDURE (VAR wr: Writer) WriteXString* (IN x: ARRAY OF CHAR), NEW;
- VAR i: INTEGER; ch: CHAR;
- BEGIN
- i := 0; ch := x[0]; WHILE ch # 0X DO wr.WriteXChar(ch); INC(i); ch := x[i] END;
- wr.WriteSChar(0X)
- END WriteXString;
- PROCEDURE (VAR wr: Writer) WriteString* (IN x: ARRAY OF CHAR), NEW;
- VAR i: INTEGER; ch: CHAR;
- BEGIN
- i := 0; ch := x[0]; WHILE ch # 0X DO wr.WriteChar(ch); INC(i); ch := x[i] END;
- wr.WriteChar(0X)
- END WriteString;
- PROCEDURE (VAR wr: Writer) WriteVersion* (version: INTEGER), NEW;
- BEGIN
- wr.WriteByte(SHORT(SHORT(version)))
- END WriteVersion;
- PROCEDURE (VAR wr: Writer) WriteStore* (x: Store), NEW;
- VAR t: Kernel.Type; pos1, pos2, pos: INTEGER;
- save: WriterState;
- BEGIN
- ASSERT(wr.rider # NIL, 20);
- IF x # NIL THEN
- IF wr.noDomain THEN
- wr.domain := x.Domain(); wr.noDomain := FALSE
- ELSE ASSERT(x.Domain() = wr.domain, 21)
- END;
- x.ExternalizeAs(x); IF x = NIL THEN wr.writtenStore := NIL; RETURN END
- END;
- IF wr.st.linkpos > 0 THEN (* link to previous block's <next> or up block's <down> *)
- pos := wr.Pos();
- IF pos - wr.st.linkpos = 4 THEN
- (* hack to resolve ambiguity between next = 0 because of end-of-chain, or because of offset = 0.
- above guard holds only if for the latter case.
- ASSUMPTION:
- this can happen only if linkpos points to a next (not a down)
- and there is a comment byte just before
- *)
- wr.SetPos(wr.st.linkpos - 4); wr.WriteInt(1); wr.WriteInt(pos - wr.st.linkpos - 4)
- ELSE
- wr.SetPos(wr.st.linkpos); wr.WriteInt(pos - wr.st.linkpos - 4)
- END;
- wr.SetPos(pos)
- END;
- IF x = NIL THEN
- wr.WriteSChar(nil);
- wr.WriteInt(0); (* <comment> *)
- wr.st.linkpos := wr.Pos();
- wr.WriteInt(0) (* <next> *)
- ELSIF x.era >= wr.era THEN
- ASSERT(x.era = wr.era, 23);
- IF x.isElem THEN wr.WriteSChar(link) ELSE wr.WriteSChar(newlink) END;
- wr.WriteInt(x.id);
- wr.WriteInt(0); (* <comment> *)
- wr.st.linkpos := wr.Pos();
- wr.WriteInt(0) (* <next> *)
- ELSE
- x.era := wr.era;
- WITH x: Alien DO
- IF x.isElem THEN
- wr.WriteSChar(elem); x.id := wr.nextElemId; INC(wr.nextElemId)
- ELSE
- wr.WriteSChar(store); x.id := wr.nextStoreId; INC(wr.nextStoreId)
- END;
- WritePath(wr, x.path)
- ELSE
- t := Kernel.TypeOf(x);
- x.isElem := t.base[1] = wr.modelType;
- IF x.isElem THEN
- wr.WriteSChar(elem); x.id := wr.nextElemId; INC(wr.nextElemId)
- ELSE
- wr.WriteSChar(store); x.id := wr.nextStoreId; INC(wr.nextStoreId)
- END;
- WriteType(wr, t)
- END;
- wr.WriteInt(0); (* <comment> *)
- pos1 := wr.Pos(); wr.WriteInt(0); wr.WriteInt(0); (* <next>, <down> *)
- pos2 := wr.Pos(); wr.WriteInt(0); (* <len> *)
- save := wr.st; (* push current writer state; switch to structured *)
- wr.st.linkpos := pos1 + 4;
- WITH x: Alien DO ExternalizeAlien(wr, x.file, x.comps)
- ELSE
- x.Externalize(wr)
- END;
- wr.st := save; (* pop writer state *)
- wr.st.linkpos := pos1;
- pos := wr.Pos();
- wr.SetPos(pos2); wr.WriteInt(pos - pos2 - 4); (* patch <len> *)
- wr.SetPos(pos)
- END;
- wr.writtenStore := x
- END WriteStore;
- (** miscellaneous **)
- PROCEDURE Report* (IN msg, p0, p1, p2: ARRAY OF CHAR);
- BEGIN
- IF logReports THEN
- Dialog.ShowParamMsg(msg, p0, p1, p2)
- END
- END Report;
- PROCEDURE BeginCloning (d: Domain);
- BEGIN
- ASSERT(d # NIL, 20);
- INC(d.level);
- IF d.level = 1 THEN
- d.copyera := nextEra; INC(nextEra); d.nextElemId := 0;
- IF d.cleaner = NIL THEN NEW(d.cleaner); d.cleaner.d := d END;
- Kernel.PushTrapCleaner(d.cleaner)
- END
- END BeginCloning;
-
- PROCEDURE EndCloning (d: Domain);
- BEGIN
- ASSERT(d # NIL, 20);
- DEC(d.level);
- IF d.level = 0 THEN
- d.sDict := NIL;
- Kernel.PopTrapCleaner(d.cleaner);
- d.s := NIL
- END
- END EndCloning;
- PROCEDURE CopyOf* (s: Store): Store;
- VAR h: Store; c: StoreDict; d: Domain; k, org: INTEGER;
- BEGIN
- ASSERT(s # NIL, 20);
-
- d := DomainOf(s);
- IF d = NIL THEN d := NewDomain(anonymousDomain); s.dlink := d; d.copyDomain := TRUE END;
- BeginCloning(d);
- IF s.era >= d.copyera THEN (* s has already been copied *)
- ASSERT(s.era = d.copyera, 21);
- k := s.id MOD dictLineLen; org := s.id - k;
- c := d.sDict;
- WHILE (c # NIL) & (c.org # org) DO c := c.next END;
- ASSERT((c # NIL) & (c.elem[k] # NIL), 100);
- h := c.elem[k]
- ELSE
- s.era := d.copyera;
- s.id := d.nextElemId; INC(d.nextElemId);
- Kernel.NewObj(h, Kernel.TypeOf(s));
- k := s.id MOD dictLineLen;
- IF k = 0 THEN NEW(c); c.org := s.id; c.next := d.sDict; d.sDict := c
- ELSE c := d.sDict
- END;
- ASSERT((c # NIL) & (c.org = s.id - k) & (c.elem[k] = NIL), 101);
- c.elem[k] := h;
- IF d.s = NIL THEN d.s := h ELSE Join(h, d.s) END;
- h.CopyFrom(s)
- END;
- EndCloning(d);
- RETURN h
- END CopyOf;
-
- PROCEDURE ExternalizeProxy* (s: Store): Store;
- BEGIN
- IF s # NIL THEN s.ExternalizeAs(s) END;
- RETURN s
- END ExternalizeProxy;
-
- PROCEDURE InitDomain* (s: Store);
- VAR d: Domain;
- BEGIN
- ASSERT(s # NIL, 20);
- d := DomainOf(s);
- IF d = NIL THEN d := NewDomain(inited); s.dlink := d
- ELSE d.initialized := TRUE
- END
- END InitDomain;
-
- PROCEDURE Join* (s0, s1: Store);
- VAR d0, d1: Domain;
- BEGIN
- ASSERT(s0 # NIL, 20); ASSERT(s1 # NIL, 21);
- d0 := DomainOf(s0); d1 := DomainOf(s1);
- IF (d0 = NIL) & (d1 = NIL) THEN
- s0.dlink := NewDomain(anonymousDomain); s1.dlink := s0.dlink
- ELSIF d0 = NIL THEN
- s0.dlink := d1; d1.copyDomain := FALSE
- ELSIF d1 = NIL THEN
- s1.dlink := d0; d0.copyDomain := FALSE
- ELSIF d0 # d1 THEN
- ASSERT(~d0.initialized OR ~d1.initialized, 22);
- (* PRE 22 s0.Domain() = NIL OR s1.Domain() = NIL OR s0.Domain() = s1.Domain() *)
- IF ~d0.initialized & (d0.level = 0) THEN d0.dlink := d1; d1.copyDomain := FALSE
- ELSIF ~d1.initialized & (d1.level = 0) THEN d1.dlink := d0; d0.copyDomain := FALSE
- ELSE HALT(100)
- END
- END
- END Join;
-
- PROCEDURE Joined* (s0, s1: Store): BOOLEAN;
- VAR d0, d1: Domain;
- BEGIN
- ASSERT(s0 # NIL, 20); ASSERT(s1 # NIL, 21);
- d0 := DomainOf(s0); d1 := DomainOf(s1);
- RETURN (s0 = s1) OR ((d0 = d1) & (d0 # NIL))
- END Joined;
- PROCEDURE Unattached* (s: Store): BOOLEAN;
- BEGIN
- ASSERT(s # NIL, 20);
- RETURN (s.dlink = NIL) OR s.dlink.copyDomain
- END Unattached;
- BEGIN
- nextEra := 1; logReports := FALSE
- END Stores.
|