Stores.txt 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. MODULE Stores;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Stores.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM, Kernel, Dialog, Strings, Files;
  5. CONST
  6. (** Alien.cause, Reader.TurnIntoAlien cause - flagged by internalization procs **)
  7. alienVersion* = 1; alienComponent* = 2;
  8. (** Alien.cause - internally detected **)
  9. inconsistentVersion* = -1; inconsistentType* = -2;
  10. moduleFileNotFound* = -3; invalidModuleFile* = -4;
  11. inconsModuleVersion* = -5; typeNotFound* = -6;
  12. dictLineLen = 32; (* length of type & elem dict lines *)
  13. newBase = 0F0X; (* new base type (level = 0), i.e. not yet in dict *)
  14. newExt = 0F1X; (* new extension type (level = 1), i.e. not yet in dict *)
  15. oldType = 0F2X; (* old type, i.e. already in dict *)
  16. nil = 080X; (* nil store *)
  17. link = 081X; (* link to another elem in same file *)
  18. store = 082X; (* general store *)
  19. elem = 083X; (* elem store *)
  20. newlink = 084X; (* link to another non-elem store in same file *)
  21. minVersion = 0; maxStoreVersion = 0;
  22. elemTName = "Stores.ElemDesc"; (* type of pre-1.3 elems *)
  23. modelTName = "Models.ModelDesc"; (* the only known family of pre-1.3 elems *)
  24. inited = TRUE; anonymousDomain = FALSE; (* values to be used when calling NewDomain *)
  25. compatible = TRUE;
  26. TYPE
  27. TypeName* = ARRAY 64 OF CHAR;
  28. TypePath* = ARRAY 16 OF TypeName;
  29. OpName* = ARRAY 32 OF CHAR;
  30. Domain* = POINTER TO LIMITED RECORD
  31. sequencer: ANYPTR;
  32. dlink: Domain;
  33. initialized, copyDomain: BOOLEAN;
  34. level, copyera, nextElemId: INTEGER;
  35. sDict: StoreDict;
  36. cleaner: TrapCleaner;
  37. s: Store (* used for CopyOf *)
  38. END;
  39. Operation* = POINTER TO ABSTRACT RECORD END;
  40. Store* = POINTER TO ABSTRACT RECORD
  41. dlink: Domain;
  42. era, id: INTEGER; (* externalization era and id *)
  43. isElem: BOOLEAN (* to preserve file format: is this an elem in the old sense? *)
  44. END;
  45. AlienComp* = POINTER TO LIMITED RECORD
  46. next-: AlienComp
  47. END;
  48. AlienPiece* = POINTER TO LIMITED RECORD (AlienComp)
  49. pos-, len-: INTEGER
  50. END;
  51. AlienPart* = POINTER TO LIMITED RECORD (AlienComp)
  52. store-: Store
  53. END;
  54. Alien* = POINTER TO LIMITED RECORD (Store)
  55. path-: TypePath; (** the type this store would have if it were not an alien **)
  56. cause-: INTEGER; (** # 0, the cause that turned this store into an alien **)
  57. file-: Files.File; (** base file holding alien pieces **)
  58. comps-: AlienComp (** the constituent components of this alien store **)
  59. END;
  60. ReaderState = RECORD
  61. next: INTEGER; (* position of next store in current level *)
  62. end: INTEGER (* position just after last read store *)
  63. END;
  64. WriterState = RECORD
  65. linkpos: INTEGER (* address of threading link *)
  66. END;
  67. TypeDict = POINTER TO RECORD
  68. next: TypeDict;
  69. org: INTEGER; (* origin id of this dict line *)
  70. type: ARRAY dictLineLen OF TypeName; (* type[org] .. type[org + dictLineLen - 1] *)
  71. baseId: ARRAY dictLineLen OF INTEGER
  72. END;
  73. StoreDict = POINTER TO RECORD
  74. next: StoreDict;
  75. org: INTEGER; (* origin id of this dict line *)
  76. elem: ARRAY dictLineLen OF Store (* elem[org] .. elem[org + dictLineLen - 1] *)
  77. END;
  78. Reader* = RECORD
  79. rider-: Files.Reader;
  80. cancelled-: BOOLEAN; (** current Internalize has been cancelled **)
  81. readAlien-: BOOLEAN; (** at least one alien read since ConnectTo **)
  82. cause: INTEGER;
  83. nextTypeId, nextElemId, nextStoreId: INTEGER; (* next id of non-dict type, "elem", store *)
  84. tDict, tHead: TypeDict; (* mapping (id <-> type) - self-organizing list *)
  85. eDict, eHead: StoreDict; (* mapping (id -> elem) - self-organizing list *)
  86. sDict, sHead: StoreDict; (* mapping (id -> store) - self-organizing list *)
  87. st: ReaderState;
  88. noDomain: BOOLEAN;
  89. store: Store
  90. END;
  91. Writer* = RECORD
  92. rider-: Files.Writer;
  93. writtenStore-: Store;
  94. era: INTEGER; (* current externalization era *)
  95. noDomain: BOOLEAN; (* no domain encountered yet *)
  96. modelType: Kernel.Type;
  97. domain: Domain; (* domain of current era *)
  98. nextTypeId, nextElemId, nextStoreId: INTEGER; (* next id of non-dict type or elem *)
  99. tDict, tHead: TypeDict; (* mapping (id -> type) - self-organizing list *)
  100. st: WriterState
  101. END;
  102. TrapCleaner = POINTER TO RECORD (Kernel.TrapCleaner)
  103. d: Domain
  104. END;
  105. VAR
  106. nextEra: INTEGER; (* next externalization era *)
  107. thisTypeRes: INTEGER; (* side-effect res code of ThisType *)
  108. logReports: BOOLEAN;
  109. (** Cleaner **)
  110. PROCEDURE (c: TrapCleaner) Cleanup;
  111. BEGIN
  112. c.d.level := 0;
  113. c.d.sDict := NIL;
  114. c.d.s := NIL
  115. END Cleanup;
  116. PROCEDURE (d: Domain) SetSequencer* (sequencer: ANYPTR), NEW;
  117. BEGIN
  118. ASSERT(d.sequencer = NIL);
  119. d.sequencer := sequencer
  120. END SetSequencer;
  121. PROCEDURE (d: Domain) GetSequencer*(): ANYPTR, NEW;
  122. BEGIN
  123. RETURN d.sequencer
  124. END GetSequencer;
  125. PROCEDURE^ Report* (IN msg, p0, p1, p2: ARRAY OF CHAR);
  126. PROCEDURE^ (VAR rd: Reader) SetPos* (pos: INTEGER), NEW;
  127. PROCEDURE^ (VAR rd: Reader) ReadVersion* (min, max: INTEGER; OUT version: INTEGER), NEW;
  128. PROCEDURE^ (VAR rd: Reader) ReadSChar* (OUT x: SHORTCHAR), NEW;
  129. PROCEDURE^ (VAR rd: Reader) ReadInt* (OUT x: INTEGER), NEW;
  130. PROCEDURE^ (VAR rd: Reader) ReadXString* (OUT x: ARRAY OF CHAR), NEW;
  131. PROCEDURE^ (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
  132. PROCEDURE^ (VAR wr: Writer) SetPos* (pos: INTEGER), NEW;
  133. PROCEDURE^ (VAR wr: Writer) WriteVersion* (version: INTEGER), NEW;
  134. PROCEDURE^ (VAR wr: Writer) WriteSChar* (x: SHORTCHAR), NEW;
  135. PROCEDURE^ (VAR wr: Writer) WriteInt* (x: INTEGER), NEW;
  136. PROCEDURE^ (VAR wr: Writer) WriteXString* (IN x: ARRAY OF CHAR), NEW;
  137. PROCEDURE^ (VAR wr: Writer) WriteStore* (x: Store), NEW;
  138. PROCEDURE^ Join* (s0, s1: Store);
  139. (** Operation **)
  140. PROCEDURE (op: Operation) Do* (), NEW, ABSTRACT;
  141. (** Store **)
  142. PROCEDURE NewDomain (initialized: BOOLEAN): Domain;
  143. VAR d: Domain;
  144. BEGIN
  145. NEW(d); d.level := 0; d.sDict := NIL; d.cleaner := NIL;
  146. d.initialized := initialized; d.copyDomain := FALSE;
  147. RETURN d
  148. END NewDomain;
  149. PROCEDURE DomainOf (s: Store): Domain;
  150. VAR d, p, q, r: Domain;
  151. BEGIN
  152. d := s.dlink;
  153. IF (d # NIL) & (d.dlink # NIL) THEN
  154. p := NIL; q := d; r := q.dlink;
  155. WHILE r # NIL DO q.dlink := p; p := q; q := r; r := q.dlink END;
  156. d := q;
  157. WHILE p # NIL DO q := p; p := q.dlink; q.dlink := d END;
  158. s.dlink := d
  159. END;
  160. RETURN d
  161. END DomainOf;
  162. PROCEDURE (s: Store) Domain*(): Domain, NEW;
  163. VAR d: Domain;
  164. BEGIN
  165. d := DomainOf(s);
  166. IF (d # NIL) & ~d.initialized THEN d := NIL END;
  167. RETURN d
  168. END Domain;
  169. PROCEDURE (s: Store) CopyFrom- (source: Store), NEW, EMPTY;
  170. PROCEDURE (s: Store) Internalize- (VAR rd: Reader), NEW, EXTENSIBLE;
  171. VAR thisVersion: INTEGER;
  172. BEGIN
  173. rd.ReadVersion(minVersion, maxStoreVersion, thisVersion);
  174. IF ~rd.cancelled & s.isElem THEN
  175. rd.ReadVersion(minVersion, maxStoreVersion, thisVersion)
  176. (* works since maxStoreVersion = maxElemVersion = 0 in pre-1.3 *)
  177. END
  178. END Internalize;
  179. PROCEDURE (s: Store) ExternalizeAs- (VAR s1: Store), NEW, EMPTY;
  180. PROCEDURE (s: Store) Externalize- (VAR wr: Writer), NEW, EXTENSIBLE;
  181. BEGIN
  182. wr.WriteVersion(maxStoreVersion);
  183. IF s.isElem THEN wr.WriteVersion(maxStoreVersion) END
  184. END Externalize;
  185. (** Alien **)
  186. PROCEDURE^ CopyOf* (s: Store): Store;
  187. PROCEDURE (a: Alien) CopyFrom- (source: Store);
  188. VAR s, c, cp: AlienComp; piece: AlienPiece; part: AlienPart;
  189. BEGIN
  190. WITH source: Alien DO
  191. a.path := source.path;
  192. a.cause := source.cause;
  193. a.file := source.file;
  194. a.comps := NIL;
  195. s := source.comps; cp := NIL;
  196. WHILE s # NIL DO
  197. WITH s: AlienPiece DO
  198. NEW(piece); c := piece;
  199. piece.pos := s.pos; piece.len := s.len
  200. | s: AlienPart DO
  201. NEW(part); c := part;
  202. IF s.store # NIL THEN part.store := CopyOf(s.store); Join(part.store, a) END
  203. END;
  204. IF cp # NIL THEN cp.next := c ELSE a.comps := c END;
  205. cp := c;
  206. s := s.next
  207. END
  208. END
  209. END CopyFrom;
  210. PROCEDURE (a: Alien) Internalize- (VAR rd: Reader);
  211. BEGIN
  212. HALT(100)
  213. END Internalize;
  214. PROCEDURE (a: Alien) Externalize- (VAR w: Writer);
  215. BEGIN
  216. HALT(100)
  217. END Externalize;
  218. (* types *)
  219. PROCEDURE GetThisTypeName (t: Kernel.Type; VAR type: TypeName);
  220. VAR i, j: INTEGER; ch: CHAR; name: Kernel.Name;
  221. BEGIN
  222. Kernel.GetTypeName(t, name); type := t.mod.name$;
  223. i := 0; ch := type[0]; WHILE ch # 0X DO INC(i); ch := type[i] END;
  224. type[i] := "."; INC(i);
  225. j := 0; REPEAT ch := name[j]; type[i] := ch; INC(i); INC(j) UNTIL ch = 0X;
  226. IF compatible THEN
  227. IF type[i-2] = "^" THEN (* for backward compatibility *)
  228. type[i-2] := "D"; type[i-1] := "e"; type[i] := "s"; type[i+1] := "c"; type[i+2] := 0X
  229. END
  230. END
  231. END GetThisTypeName;
  232. PROCEDURE ThisType (type: TypeName): Kernel.Type;
  233. VAR m: Kernel.Module; t: Kernel.Type; i, j: INTEGER; ch: CHAR;
  234. typ: Kernel.Name; mod: ARRAY 256 OF CHAR; res: INTEGER; str: ARRAY 256 OF CHAR;
  235. BEGIN
  236. ASSERT(type # "", 20);
  237. i := 0; ch := type[0];
  238. WHILE (ch # ".") & (ch # 0X) DO mod[i] := SHORT(ch); INC(i); ch := type[i] END;
  239. ASSERT(ch = ".", 21);
  240. mod[i] := 0X; INC(i);
  241. m := Kernel.ThisMod(mod);
  242. IF m # NIL THEN
  243. j := 0; REPEAT ch := type[i]; typ[j] := SHORT(ch); INC(i); INC(j) UNTIL ch = 0X;
  244. t := Kernel.ThisType(m, typ);
  245. IF (t = NIL) & (j >= 5) THEN (* try pointer type *)
  246. IF (typ[j-5] = "D") & (typ[j-4] = "e") & (typ[j-3] = "s") & (typ[j-2] = "c") THEN
  247. typ[j-5] := "^"; typ[j-4] := 0X;
  248. t := Kernel.ThisType(m, typ)
  249. END
  250. END;
  251. IF t = NIL THEN thisTypeRes := typeNotFound END
  252. ELSE
  253. t := NIL;
  254. Kernel.GetLoaderResult(res, str, str, str);
  255. CASE res OF
  256. | Kernel.fileNotFound: thisTypeRes := moduleFileNotFound
  257. | Kernel.syntaxError: thisTypeRes := invalidModuleFile
  258. | Kernel.objNotFound: thisTypeRes := inconsModuleVersion
  259. | Kernel.illegalFPrint: thisTypeRes := inconsModuleVersion
  260. | Kernel.cyclicImport: thisTypeRes := invalidModuleFile (* cyclic import ... *)
  261. ELSE thisTypeRes := invalidModuleFile
  262. END
  263. END;
  264. RETURN t
  265. END ThisType;
  266. PROCEDURE SameType (IN x, y: TypeName): BOOLEAN;
  267. VAR i: INTEGER;
  268. BEGIN
  269. IF x = y THEN RETURN TRUE
  270. ELSE
  271. i := 0; WHILE x[i] = y[i] DO INC(i) END;
  272. RETURN
  273. (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)
  274. 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)
  275. END
  276. END SameType;
  277. PROCEDURE SamePath (t: Kernel.Type; VAR path: TypePath): BOOLEAN;
  278. (* check whether t coincides with path *)
  279. VAR tn: TypeName; i, n: INTEGER;
  280. BEGIN
  281. i := -1; n := Kernel.LevelOf(t);
  282. REPEAT
  283. GetThisTypeName(t.base[n], tn);
  284. DEC(n); INC(i)
  285. UNTIL (n < 0) OR ~SameType(tn, path[i]);
  286. RETURN SameType(tn, path[i])
  287. END SamePath;
  288. PROCEDURE NewStore (t: Kernel.Type): Store;
  289. VAR p: ANYPTR;
  290. BEGIN
  291. ASSERT(t # NIL, 20);
  292. Kernel.NewObj(p, t); ASSERT(p # NIL, 100);
  293. ASSERT(p IS Store, 21);
  294. RETURN p(Store)
  295. END NewStore;
  296. (* type dictionary *)
  297. PROCEDURE GetThisType (VAR d: TypeDict; id: INTEGER; VAR type: TypeName);
  298. (* pre: (id, t) IN dict *)
  299. VAR h, p: TypeDict; org, k: INTEGER;
  300. BEGIN
  301. k := id MOD dictLineLen; org := id - k;
  302. h := NIL; p := d; WHILE p.org # org DO h := p; p := p.next END;
  303. IF h # NIL THEN h.next := p.next; p.next := d; d := p END;
  304. type := p.type[k];
  305. ASSERT(type # "", 100)
  306. END GetThisType;
  307. PROCEDURE ThisId (VAR d: TypeDict; t: TypeName): INTEGER;
  308. (* pre: t # "" *)
  309. (* post: res = id if (t, id) in dict, res = -1 else *)
  310. VAR h, p: TypeDict; k, id: INTEGER;
  311. BEGIN
  312. h := NIL; p := d; id := -1;
  313. WHILE (p # NIL) & (id < 0) DO
  314. k := 0; WHILE (k < dictLineLen) & (p.type[k, 0] # 0X) & (p.type[k] # t) DO INC(k) END;
  315. IF (k < dictLineLen) & (p.type[k, 0] # 0X) THEN id := p.org + k
  316. ELSE h := p; p := p.next
  317. END
  318. END;
  319. IF (id >= 0) & (h # NIL) THEN h.next := p.next; p.next := d; d := p END;
  320. RETURN id
  321. END ThisId;
  322. PROCEDURE ThisBaseId (VAR d: TypeDict; id: INTEGER): INTEGER;
  323. (* post: res = id if base(t) # NIL, res = -1 if base(t) = NIL; res >= 0 => T(res) = base(t) *)
  324. VAR h, p: TypeDict; k, org, baseId: INTEGER;
  325. BEGIN
  326. k := id MOD dictLineLen; org := id - k;
  327. h := NIL; p := d; WHILE p.org # org DO h := p; p := p.next END;
  328. IF h # NIL THEN h.next := p.next; p.next := d; d := p END;
  329. baseId := p.baseId[k];
  330. RETURN baseId
  331. END ThisBaseId;
  332. PROCEDURE AddType (VAR d, h: TypeDict; id: INTEGER; type: TypeName);
  333. VAR k: INTEGER;
  334. BEGIN
  335. k := id MOD dictLineLen;
  336. IF (h = NIL) OR ((k = 0) & (h.org # id)) THEN
  337. NEW(h); h.org := id - k; h.next := d; d := h
  338. END;
  339. h.type[k] := type; h.baseId[k] := -1
  340. END AddType;
  341. PROCEDURE AddBaseId (h: TypeDict; id, baseId: INTEGER);
  342. VAR k: INTEGER;
  343. BEGIN
  344. k := id MOD dictLineLen;
  345. h.baseId[k] := baseId
  346. END AddBaseId;
  347. PROCEDURE InitTypeDict (VAR d, h: TypeDict; VAR nextID: INTEGER);
  348. BEGIN
  349. d := NIL; h := NIL; nextID := 0
  350. END InitTypeDict;
  351. (* store dictionary - used to maintain referential sharing *)
  352. PROCEDURE ThisStore (VAR d: StoreDict; id: INTEGER): Store;
  353. (* pre: (id, s) IN dict *)
  354. VAR h, p: StoreDict; s: Store; k, org: INTEGER;
  355. BEGIN
  356. k := id MOD dictLineLen; org := id - k;
  357. h := NIL; p := d; WHILE p.org # org DO h := p; p := p.next END;
  358. IF h # NIL THEN h.next := p.next; p.next := d; d := p END;
  359. s := p.elem[k];
  360. ASSERT(s # NIL, 100);
  361. RETURN s
  362. END ThisStore;
  363. PROCEDURE AddStore (VAR d, h: StoreDict; s: Store);
  364. VAR k: INTEGER;
  365. BEGIN
  366. k := s.id MOD dictLineLen;
  367. IF (h = NIL) OR ((k = 0) & (h.org # s.id)) THEN
  368. NEW(h); h.org := s.id - k; h.next := d; d := h
  369. END;
  370. h.elem[k] := s
  371. END AddStore;
  372. PROCEDURE InitStoreDict (VAR d, h: StoreDict; VAR nextID: INTEGER);
  373. BEGIN
  374. d := NIL; h := NIL; nextID := 0
  375. END InitStoreDict;
  376. (* support for type mapping *)
  377. PROCEDURE ReadPath (VAR rd: Reader; VAR path: TypePath);
  378. VAR h: TypeDict; id, extId: INTEGER; i: INTEGER; kind: SHORTCHAR;
  379. PROCEDURE AddPathComp (VAR rd: Reader);
  380. BEGIN
  381. IF h # NIL THEN AddBaseId(h, extId, rd.nextTypeId) END;
  382. AddType(rd.tDict, rd.tHead, rd.nextTypeId, path[i]);
  383. h := rd.tHead; extId := rd.nextTypeId
  384. END AddPathComp;
  385. BEGIN
  386. h := NIL; i := 0; rd.ReadSChar(kind);
  387. WHILE kind = newExt DO
  388. rd.ReadXString(path[i]);
  389. AddPathComp(rd); INC(rd.nextTypeId);
  390. IF path[i] # elemTName THEN INC(i) END;
  391. rd.ReadSChar(kind)
  392. END;
  393. IF kind = newBase THEN
  394. rd.ReadXString(path[i]);
  395. AddPathComp(rd); INC(rd.nextTypeId); INC(i)
  396. ELSE
  397. ASSERT(kind = oldType, 100);
  398. rd.ReadInt(id);
  399. IF h # NIL THEN AddBaseId(h, extId, id) END;
  400. REPEAT
  401. GetThisType(rd.tDict, id, path[i]); id := ThisBaseId(rd.tDict, id);
  402. IF path[i] # elemTName THEN INC(i) END
  403. UNTIL id = -1
  404. END;
  405. path[i] := ""
  406. END ReadPath;
  407. PROCEDURE WritePath (VAR wr: Writer; VAR path: TypePath);
  408. VAR h: TypeDict; id, extId: INTEGER; i, n: INTEGER;
  409. BEGIN
  410. h := NIL;
  411. n := 0; WHILE path[n] # "" DO INC(n) END;
  412. i := 0;
  413. WHILE i < n DO
  414. id := ThisId(wr.tDict, path[i]);
  415. IF id >= 0 THEN
  416. IF h # NIL THEN AddBaseId(h, extId, id) END;
  417. wr.WriteSChar(oldType); wr.WriteInt(id); n := i
  418. ELSE
  419. IF i + 1 < n THEN wr.WriteSChar(newExt) ELSE wr.WriteSChar(newBase) END;
  420. wr.WriteXString(path[i]);
  421. IF h # NIL THEN AddBaseId(h, extId, wr.nextTypeId) END;
  422. AddType(wr.tDict, wr.tHead, wr.nextTypeId, path[i]);
  423. h := wr.tHead; extId := wr.nextTypeId;
  424. INC(wr.nextTypeId);
  425. IF path[i] = modelTName THEN
  426. id := ThisId(wr.tDict, elemTName); ASSERT(id < 0, 100); ASSERT(i + 2 = n, 101);
  427. wr.WriteSChar(newExt); wr.WriteXString(elemTName);
  428. IF h # NIL THEN AddBaseId(h, extId, wr.nextTypeId) END;
  429. AddType(wr.tDict, wr.tHead, wr.nextTypeId, elemTName);
  430. h := wr.tHead; extId := wr.nextTypeId;
  431. INC(wr.nextTypeId)
  432. END
  433. END;
  434. INC(i)
  435. END
  436. END WritePath;
  437. PROCEDURE WriteType (VAR wr: Writer; t: Kernel.Type);
  438. VAR path: TypePath; n, i: INTEGER;
  439. BEGIN
  440. i := 0; n := Kernel.LevelOf(t);
  441. WHILE n >= 0 DO
  442. GetThisTypeName(t.base[n], path[i]);
  443. DEC(n); INC(i)
  444. END;
  445. path[i] := "";
  446. WritePath(wr, path)
  447. END WriteType;
  448. (* support for alien mapping *)
  449. PROCEDURE InternalizeAlien (VAR rd: Reader; VAR comps: AlienComp; down, pos, len: INTEGER);
  450. VAR h, p: AlienComp; piece: AlienPiece; part: AlienPart; file: Files.File;
  451. next, end, max: INTEGER;
  452. BEGIN
  453. file := rd.rider.Base(); max := file.Length();
  454. end := pos + len; h := NIL;
  455. IF down # 0 THEN next := down ELSE next := end END;
  456. WHILE pos < end DO
  457. ASSERT(end <= max, 100);
  458. IF pos < next THEN
  459. NEW(piece); piece.pos := pos; piece.len := next - pos;
  460. p := piece; pos := next
  461. ELSE
  462. ASSERT(pos = next, 101);
  463. rd.SetPos(next);
  464. NEW(part); rd.ReadStore(part.store);
  465. ASSERT(rd.st.end > next, 102);
  466. p := part; pos := rd.st.end;
  467. IF rd.st.next > 0 THEN
  468. ASSERT(rd.st.next > next, 103); next := rd.st.next
  469. ELSE next := end
  470. END
  471. END;
  472. IF h = NIL THEN comps := p ELSE h.next := p END;
  473. h := p
  474. END;
  475. ASSERT(pos = end, 104);
  476. rd.SetPos(end)
  477. END InternalizeAlien;
  478. PROCEDURE ExternalizePiece (VAR wr: Writer; file: Files.File; p: AlienPiece);
  479. VAR r: Files.Reader; w: Files.Writer; b: BYTE; l, len: INTEGER;
  480. BEGIN
  481. l := file.Length(); len := p.len;
  482. ASSERT(0 <= p.pos, 100); ASSERT(p.pos <= l, 101);
  483. ASSERT(0 <= len, 102); ASSERT(len <= l - p.pos, 103);
  484. r := file.NewReader(NIL); r.SetPos(p.pos);
  485. w := wr.rider;
  486. WHILE len # 0 DO r.ReadByte(b); w.WriteByte(b); DEC(len) END
  487. END ExternalizePiece;
  488. PROCEDURE ExternalizeAlien (VAR wr: Writer; file: Files.File; comps: AlienComp);
  489. VAR p: AlienComp;
  490. BEGIN
  491. p := comps;
  492. WHILE p # NIL DO
  493. WITH p: AlienPiece DO
  494. ExternalizePiece(wr, file, p)
  495. | p: AlienPart DO
  496. wr.WriteStore(p.store)
  497. END;
  498. p := p.next
  499. END
  500. END ExternalizeAlien;
  501. (** Reader **)
  502. PROCEDURE (VAR rd: Reader) ConnectTo* (f: Files.File), NEW;
  503. (** pre: rd.rider = NIL OR f = NIL **)
  504. BEGIN
  505. IF f = NIL THEN
  506. rd.rider := NIL
  507. ELSE
  508. ASSERT(rd.rider = NIL, 20);
  509. rd.rider := f.NewReader(rd.rider); rd.SetPos(0);
  510. InitTypeDict(rd.tDict, rd.tHead, rd.nextTypeId);
  511. InitStoreDict(rd.eDict, rd.eHead, rd.nextElemId);
  512. InitStoreDict(rd.sDict, rd.sHead, rd.nextStoreId);
  513. rd.noDomain := TRUE
  514. END;
  515. rd.readAlien := FALSE
  516. END ConnectTo;
  517. PROCEDURE (VAR rd: Reader) SetPos* (pos: INTEGER), NEW;
  518. BEGIN
  519. rd.rider.SetPos(pos)
  520. END SetPos;
  521. PROCEDURE (VAR rd: Reader) Pos* (): INTEGER, NEW;
  522. BEGIN
  523. RETURN rd.rider.Pos()
  524. END Pos;
  525. PROCEDURE (VAR rd: Reader) ReadBool* (OUT x: BOOLEAN), NEW;
  526. VAR b: BYTE;
  527. BEGIN
  528. rd.rider.ReadByte(b); x := b # 0
  529. END ReadBool;
  530. PROCEDURE (VAR rd: Reader) ReadSChar* (OUT x: SHORTCHAR), NEW;
  531. BEGIN
  532. rd.rider.ReadByte(SYSTEM.VAL(BYTE, x))
  533. END ReadSChar;
  534. PROCEDURE (VAR rd: Reader) ReadXChar* (OUT x: CHAR), NEW;
  535. VAR c: SHORTCHAR;
  536. BEGIN
  537. rd.rider.ReadByte(SYSTEM.VAL(BYTE,c)); x := c
  538. END ReadXChar;
  539. PROCEDURE (VAR rd: Reader) ReadChar* (OUT x: CHAR), NEW;
  540. VAR le: ARRAY 2 OF BYTE; (* little endian, big endian *)
  541. BEGIN
  542. rd.rider.ReadBytes(le, 0, 2);
  543. x := CHR(le[0] MOD 256 + (le[1] MOD 256) * 256)
  544. END ReadChar;
  545. PROCEDURE (VAR rd: Reader) ReadByte* (OUT x: BYTE), NEW;
  546. BEGIN
  547. rd.rider.ReadByte(x)
  548. END ReadByte;
  549. PROCEDURE (VAR rd: Reader) ReadSInt* (OUT x: SHORTINT), NEW;
  550. VAR le, be: ARRAY 2 OF BYTE; (* little endian, big endian *)
  551. BEGIN
  552. rd.rider.ReadBytes(le, 0, 2);
  553. IF Kernel.littleEndian THEN
  554. x := SYSTEM.VAL(SHORTINT, le)
  555. ELSE
  556. be[0] := le[1]; be[1] := le[0];
  557. x := SYSTEM.VAL(SHORTINT, be)
  558. END
  559. END ReadSInt;
  560. PROCEDURE (VAR rd: Reader) ReadXInt* (OUT x: INTEGER), NEW;
  561. VAR le, be: ARRAY 2 OF BYTE; (* little endian, big endian *)
  562. BEGIN
  563. rd.rider.ReadBytes(le, 0, 2);
  564. IF Kernel.littleEndian THEN
  565. x := SYSTEM.VAL(SHORTINT, le)
  566. ELSE
  567. be[0] := le[1]; be[1] := le[0];
  568. x := SYSTEM.VAL(SHORTINT, be)
  569. END
  570. END ReadXInt;
  571. PROCEDURE (VAR rd: Reader) ReadInt* (OUT x: INTEGER), NEW;
  572. VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
  573. BEGIN
  574. rd.rider.ReadBytes(le, 0, 4);
  575. IF Kernel.littleEndian THEN
  576. x := SYSTEM.VAL(INTEGER, le)
  577. ELSE
  578. be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
  579. x := SYSTEM.VAL(INTEGER, be)
  580. END
  581. END ReadInt;
  582. PROCEDURE (VAR rd: Reader) ReadLong* (OUT x: LONGINT), NEW;
  583. VAR le, be: ARRAY 8 OF BYTE; (* little endian, big endian *)
  584. BEGIN
  585. rd.rider.ReadBytes(le, 0, 8);
  586. IF Kernel.littleEndian THEN
  587. x := SYSTEM.VAL(LONGINT, le)
  588. ELSE
  589. be[0] := le[7]; be[1] := le[6]; be[2] := le[5]; be[3] := le[4];
  590. be[4] := le[3]; be[5] := le[2]; be[6] := le[1]; be[7] := le[0];
  591. x := SYSTEM.VAL(LONGINT, be)
  592. END
  593. END ReadLong;
  594. PROCEDURE (VAR rd: Reader) ReadSReal* (OUT x: SHORTREAL), NEW;
  595. VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
  596. BEGIN
  597. rd.rider.ReadBytes(le, 0, 4);
  598. IF Kernel.littleEndian THEN
  599. x := SYSTEM.VAL(SHORTREAL, le)
  600. ELSE
  601. be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
  602. x := SYSTEM.VAL(SHORTREAL, be)
  603. END
  604. END ReadSReal;
  605. PROCEDURE (VAR rd: Reader) ReadXReal* (OUT x: REAL), NEW;
  606. VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
  607. BEGIN
  608. rd.rider.ReadBytes(le, 0, 4);
  609. IF Kernel.littleEndian THEN
  610. x := SYSTEM.VAL(SHORTREAL, le)
  611. ELSE
  612. be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
  613. x := SYSTEM.VAL(SHORTREAL, be)
  614. END
  615. END ReadXReal;
  616. PROCEDURE (VAR rd: Reader) ReadReal* (OUT x: REAL), NEW;
  617. VAR le, be: ARRAY 8 OF BYTE; (* little endian, big endian *)
  618. BEGIN
  619. rd.rider.ReadBytes(le, 0, 8);
  620. IF Kernel.littleEndian THEN
  621. x := SYSTEM.VAL(REAL, le)
  622. ELSE
  623. be[0] := le[7]; be[1] := le[6]; be[2] := le[5]; be[3] := le[4];
  624. be[4] := le[3]; be[5] := le[2]; be[6] := le[1]; be[7] := le[0];
  625. x := SYSTEM.VAL(REAL, be)
  626. END
  627. END ReadReal;
  628. PROCEDURE (VAR rd: Reader) ReadSet* (OUT x: SET), NEW;
  629. VAR le, be: ARRAY 4 OF BYTE; (* little endian, big endian *)
  630. BEGIN
  631. rd.rider.ReadBytes(le, 0, 4);
  632. IF Kernel.littleEndian THEN
  633. x := SYSTEM.VAL(SET, le)
  634. ELSE
  635. be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
  636. x := SYSTEM.VAL(SET, be)
  637. END
  638. END ReadSet;
  639. PROCEDURE (VAR rd: Reader) ReadSString* (OUT x: ARRAY OF SHORTCHAR), NEW;
  640. VAR i: INTEGER; ch: SHORTCHAR;
  641. BEGIN
  642. i := 0; REPEAT rd.ReadSChar(ch); x[i] := ch; INC(i) UNTIL ch = 0X
  643. END ReadSString;
  644. PROCEDURE (VAR rd: Reader) ReadXString* (OUT x: ARRAY OF CHAR), NEW;
  645. VAR i: INTEGER; ch: CHAR;
  646. BEGIN
  647. i := 0; REPEAT rd.ReadXChar(ch); x[i] := ch; INC(i) UNTIL ch = 0X
  648. END ReadXString;
  649. PROCEDURE (VAR rd: Reader) ReadString* (OUT x: ARRAY OF CHAR), NEW;
  650. VAR i: INTEGER; ch: CHAR;
  651. BEGIN
  652. i := 0; REPEAT rd.ReadChar(ch); x[i] := ch; INC(i) UNTIL ch = 0X
  653. END ReadString;
  654. PROCEDURE AlienReport (cause: INTEGER);
  655. VAR s, e: ARRAY 32 OF CHAR;
  656. BEGIN
  657. CASE cause OF
  658. | alienVersion: s := "#System:AlienVersion"
  659. | alienComponent: s := "#System:AlienComponent"
  660. | inconsistentVersion: s := "#System:InconsistentVersion"
  661. ELSE s := "#System:UnknownCause"
  662. END;
  663. Strings.IntToString(cause, e);
  664. Report("#System:AlienCause ^0 ^1 ^2", s, e, "")
  665. END AlienReport;
  666. PROCEDURE AlienTypeReport (cause: INTEGER; t: ARRAY OF CHAR);
  667. VAR s: ARRAY 64 OF CHAR;
  668. BEGIN
  669. CASE cause OF
  670. | inconsistentType: s := "#System:InconsistentType ^0"
  671. | moduleFileNotFound: s := "#System:CodeFileNotFound ^0"
  672. | invalidModuleFile: s := "#System:InvalidCodeFile ^0"
  673. | inconsModuleVersion: s := "#System:InconsistentModuleVersion ^0"
  674. | typeNotFound: s := "#System:TypeNotFound ^0"
  675. END;
  676. Report(s, t, "", "")
  677. END AlienTypeReport;
  678. PROCEDURE (VAR rd: Reader) TurnIntoAlien* (cause: INTEGER), NEW;
  679. BEGIN
  680. ASSERT(cause > 0, 20);
  681. rd.cancelled := TRUE; rd.readAlien := TRUE; rd.cause := cause;
  682. AlienReport(cause)
  683. END TurnIntoAlien;
  684. PROCEDURE (VAR rd: Reader) ReadVersion* (min, max: INTEGER; OUT version: INTEGER), NEW;
  685. VAR v: BYTE;
  686. BEGIN
  687. rd.ReadByte(v); version := v;
  688. IF (version < min) OR (version > max) THEN
  689. rd.TurnIntoAlien(alienVersion)
  690. END
  691. END ReadVersion;
  692. PROCEDURE (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
  693. VAR a: Alien; t: Kernel.Type;
  694. len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
  695. kind: SHORTCHAR; path: TypePath; type: TypeName;
  696. save: ReaderState;
  697. BEGIN
  698. rd.ReadSChar(kind);
  699. IF kind = nil THEN
  700. rd.ReadInt(comment); rd.ReadInt(next);
  701. rd.st.end := rd.Pos();
  702. IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
  703. x := NIL
  704. ELSIF kind = link THEN
  705. rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
  706. rd.st.end := rd.Pos();
  707. IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
  708. x := ThisStore(rd.eDict, id)
  709. ELSIF kind = newlink THEN
  710. rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
  711. rd.st.end := rd.Pos();
  712. IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
  713. x := ThisStore(rd.sDict, id)
  714. ELSIF (kind = store) OR (kind = elem) THEN
  715. IF kind = elem THEN
  716. id := rd.nextElemId; INC(rd.nextElemId)
  717. ELSE
  718. id := rd.nextStoreId; INC(rd.nextStoreId)
  719. END;
  720. ReadPath(rd, path); type := path[0];
  721. nextTypeId := rd.nextTypeId; nextElemId := rd.nextElemId; nextStoreId := rd.nextStoreId;
  722. rd.ReadInt(comment);
  723. pos1 := rd.Pos();
  724. rd.ReadInt(next); rd.ReadInt(down); rd.ReadInt(len);
  725. pos := rd.Pos();
  726. IF next > 0 THEN rd.st.next := pos1 + next + 4 ELSE rd.st.next := 0 END;
  727. IF down > 0 THEN downPos := pos1 + down + 8 ELSE downPos := 0 END;
  728. rd.st.end := pos + len;
  729. rd.cause := 0;
  730. ASSERT(len >= 0, 101);
  731. IF next # 0 THEN
  732. ASSERT(rd.st.next > pos1, 102);
  733. IF down # 0 THEN
  734. ASSERT(downPos < rd.st.next, 103)
  735. END
  736. END;
  737. IF down # 0 THEN
  738. ASSERT(downPos > pos1, 104);
  739. ASSERT(downPos < rd.st.end, 105)
  740. END;
  741. t := ThisType(type);
  742. IF t # NIL THEN
  743. x := NewStore(t); x.isElem := kind = elem
  744. ELSE
  745. rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
  746. x := NIL
  747. END;
  748. IF x # NIL THEN
  749. IF SamePath(t, path) THEN
  750. IF kind = elem THEN
  751. x.id := id; AddStore(rd.eDict, rd.eHead, x)
  752. ELSE
  753. x.id := id; AddStore(rd.sDict, rd.sHead, x)
  754. END;
  755. save := rd.st; rd.cause := 0; rd.cancelled := FALSE;
  756. x.Internalize(rd);
  757. rd.st := save;
  758. IF rd.cause # 0 THEN x := NIL
  759. ELSIF (rd.Pos() # rd.st.end) OR rd.rider.eof THEN
  760. rd.cause := inconsistentVersion; AlienReport(rd.cause);
  761. x := NIL
  762. END
  763. ELSE
  764. rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
  765. x := NIL
  766. END
  767. END;
  768. IF x # NIL THEN
  769. IF rd.noDomain THEN
  770. rd.store := x;
  771. rd.noDomain := FALSE
  772. ELSE
  773. Join(rd.store, x)
  774. END
  775. ELSE (* x is an alien *)
  776. rd.SetPos(pos);
  777. ASSERT(rd.cause # 0, 107);
  778. NEW(a); a.path := path; a.cause := rd.cause; a.file := rd.rider.Base();
  779. IF rd.noDomain THEN
  780. rd.store := a;
  781. rd.noDomain := FALSE
  782. ELSE
  783. Join(rd.store, a)
  784. END;
  785. IF kind = elem THEN
  786. a.id := id; AddStore(rd.eDict, rd.eHead, a)
  787. ELSE
  788. a.id := id; AddStore(rd.sDict, rd.sHead, a)
  789. END;
  790. save := rd.st;
  791. rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
  792. InternalizeAlien(rd, a.comps, downPos, pos, len);
  793. rd.st := save;
  794. x := a;
  795. ASSERT(rd.Pos() = rd.st.end, 108);
  796. rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE
  797. END
  798. ELSE
  799. pos := rd.Pos();
  800. HALT(20)
  801. END
  802. END ReadStore;
  803. (** Writer **)
  804. PROCEDURE (VAR wr: Writer) ConnectTo* (f: Files.File), NEW;
  805. (** pre: wr.rider = NIL OR f = NIL **)
  806. BEGIN
  807. IF f = NIL THEN
  808. wr.rider := NIL
  809. ELSE
  810. ASSERT(wr.rider = NIL, 20);
  811. wr.rider := f.NewWriter(wr.rider); wr.SetPos(f.Length());
  812. wr.era := nextEra; INC(nextEra);
  813. wr.noDomain := TRUE;
  814. wr.modelType := ThisType(modelTName);
  815. InitTypeDict(wr.tDict, wr.tHead, wr.nextTypeId);
  816. wr.nextElemId := 0; wr.nextStoreId := 0;
  817. wr.st.linkpos := -1
  818. END;
  819. wr.writtenStore := NIL
  820. END ConnectTo;
  821. PROCEDURE (VAR wr: Writer) SetPos* (pos: INTEGER), NEW;
  822. BEGIN
  823. wr.rider.SetPos(pos)
  824. END SetPos;
  825. PROCEDURE (VAR wr: Writer) Pos* (): INTEGER, NEW;
  826. BEGIN
  827. RETURN wr.rider.Pos()
  828. END Pos;
  829. PROCEDURE (VAR wr: Writer) WriteBool* (x: BOOLEAN), NEW;
  830. BEGIN
  831. IF x THEN wr.rider.WriteByte(1) ELSE wr.rider.WriteByte(0) END
  832. END WriteBool;
  833. PROCEDURE (VAR wr: Writer) WriteSChar* (x: SHORTCHAR), NEW;
  834. BEGIN
  835. wr.rider.WriteByte(SYSTEM.VAL(BYTE, x))
  836. END WriteSChar;
  837. PROCEDURE (VAR wr: Writer) WriteXChar* (x: CHAR), NEW;
  838. VAR c: SHORTCHAR;
  839. BEGIN
  840. c := SHORT(x); wr.rider.WriteByte(SYSTEM.VAL(BYTE, c))
  841. END WriteXChar;
  842. PROCEDURE (VAR wr: Writer) WriteChar* (x: CHAR), NEW;
  843. TYPE a = ARRAY 2 OF BYTE;
  844. VAR le, be: a; (* little endian, big endian *)
  845. BEGIN
  846. IF Kernel.littleEndian THEN
  847. le := SYSTEM.VAL(a, x)
  848. ELSE
  849. be := SYSTEM.VAL(a, x);
  850. le[0] := be[1]; le[1] := be[0]
  851. END;
  852. wr.rider.WriteBytes(le, 0, 2)
  853. END WriteChar;
  854. PROCEDURE (VAR wr: Writer) WriteByte* (x: BYTE), NEW;
  855. BEGIN
  856. wr.rider.WriteByte(x)
  857. END WriteByte;
  858. PROCEDURE (VAR wr: Writer) WriteSInt* (x: SHORTINT), NEW;
  859. TYPE a = ARRAY 2 OF BYTE;
  860. VAR le, be: a; (* little endian, big endian *)
  861. BEGIN
  862. IF Kernel.littleEndian THEN
  863. le := SYSTEM.VAL(a, x)
  864. ELSE
  865. be := SYSTEM.VAL(a, x);
  866. le[0] := be[1]; le[1] := be[0]
  867. END;
  868. wr.rider.WriteBytes(le, 0, 2)
  869. END WriteSInt;
  870. PROCEDURE (VAR wr: Writer) WriteXInt* (x: INTEGER), NEW;
  871. TYPE a = ARRAY 2 OF BYTE;
  872. VAR y: SHORTINT; le, be: a; (* little endian, big endian *)
  873. BEGIN
  874. y := SHORT(x);
  875. IF Kernel.littleEndian THEN
  876. le := SYSTEM.VAL(a, y)
  877. ELSE
  878. be := SYSTEM.VAL(a, y);
  879. le[0] := be[1]; le[1] := be[0]
  880. END;
  881. wr.rider.WriteBytes(le, 0, 2)
  882. END WriteXInt;
  883. PROCEDURE (VAR wr: Writer) WriteInt* (x: INTEGER), NEW;
  884. TYPE a = ARRAY 4 OF BYTE;
  885. VAR le, be: a; (* little endian, big endian *)
  886. BEGIN
  887. IF Kernel.littleEndian THEN
  888. le := SYSTEM.VAL(a, x)
  889. ELSE
  890. be := SYSTEM.VAL(a, x);
  891. le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
  892. END;
  893. wr.rider.WriteBytes(le, 0, 4)
  894. END WriteInt;
  895. PROCEDURE (VAR wr: Writer) WriteLong* (x: LONGINT), NEW;
  896. TYPE a = ARRAY 8 OF BYTE;
  897. VAR le, be: a; (* little endian, big endian *)
  898. BEGIN
  899. IF Kernel.littleEndian THEN
  900. le := SYSTEM.VAL(a, x)
  901. ELSE
  902. be := SYSTEM.VAL(a, x);
  903. le[0] := be[7]; le[1] := be[6]; le[2] := be[5]; le[3] := be[4];
  904. le[4] := be[3]; le[5] := be[2]; le[6] := be[1]; le[7] := be[0]
  905. END;
  906. wr.rider.WriteBytes(le, 0, 8)
  907. END WriteLong;
  908. PROCEDURE (VAR wr: Writer) WriteSReal* (x: SHORTREAL), NEW;
  909. TYPE a = ARRAY 4 OF BYTE;
  910. VAR le, be: a; (* little endian, big endian *)
  911. BEGIN
  912. IF Kernel.littleEndian THEN
  913. le := SYSTEM.VAL(a, x)
  914. ELSE
  915. be := SYSTEM.VAL(a, x);
  916. le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
  917. END;
  918. wr.rider.WriteBytes(le, 0, 4)
  919. END WriteSReal;
  920. PROCEDURE (VAR wr: Writer) WriteXReal* (x: REAL), NEW;
  921. TYPE a = ARRAY 4 OF BYTE;
  922. VAR y: SHORTREAL; le, be: a; (* little endian, big endian *)
  923. BEGIN
  924. y := SHORT(x);
  925. IF Kernel.littleEndian THEN
  926. le := SYSTEM.VAL(a, y)
  927. ELSE
  928. be := SYSTEM.VAL(a, y);
  929. le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
  930. END;
  931. wr.rider.WriteBytes(le, 0, 4)
  932. END WriteXReal;
  933. PROCEDURE (VAR wr: Writer) WriteReal* (x: REAL), NEW;
  934. TYPE a = ARRAY 8 OF BYTE;
  935. VAR le, be: a; (* little endian, big endian *)
  936. BEGIN
  937. IF Kernel.littleEndian THEN
  938. le := SYSTEM.VAL(a, x)
  939. ELSE
  940. be := SYSTEM.VAL(a, x);
  941. le[0] := be[7]; le[1] := be[6]; le[2] := be[5]; le[3] := be[4];
  942. le[4] := be[3]; le[5] := be[2]; le[6] := be[1]; le[7] := be[0]
  943. END;
  944. wr.rider.WriteBytes(le, 0, 8)
  945. END WriteReal;
  946. PROCEDURE (VAR wr: Writer) WriteSet* (x: SET), NEW;
  947. (* SIZE(SET) = 4 *)
  948. TYPE a = ARRAY 4 OF BYTE;
  949. VAR le, be: a; (* little endian, big endian *)
  950. BEGIN
  951. IF Kernel.littleEndian THEN
  952. le := SYSTEM.VAL(a, x)
  953. ELSE
  954. be := SYSTEM.VAL(a, x);
  955. le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
  956. END;
  957. wr.rider.WriteBytes(le, 0, 4)
  958. END WriteSet;
  959. PROCEDURE (VAR wr: Writer) WriteSString* (IN x: ARRAY OF SHORTCHAR), NEW;
  960. VAR i: INTEGER; ch: SHORTCHAR;
  961. BEGIN
  962. i := 0; ch := x[0]; WHILE ch # 0X DO wr.WriteSChar(ch); INC(i); ch := x[i] END;
  963. wr.WriteSChar(0X)
  964. END WriteSString;
  965. PROCEDURE (VAR wr: Writer) WriteXString* (IN x: ARRAY OF CHAR), NEW;
  966. VAR i: INTEGER; ch: CHAR;
  967. BEGIN
  968. i := 0; ch := x[0]; WHILE ch # 0X DO wr.WriteXChar(ch); INC(i); ch := x[i] END;
  969. wr.WriteSChar(0X)
  970. END WriteXString;
  971. PROCEDURE (VAR wr: Writer) WriteString* (IN x: ARRAY OF CHAR), NEW;
  972. VAR i: INTEGER; ch: CHAR;
  973. BEGIN
  974. i := 0; ch := x[0]; WHILE ch # 0X DO wr.WriteChar(ch); INC(i); ch := x[i] END;
  975. wr.WriteChar(0X)
  976. END WriteString;
  977. PROCEDURE (VAR wr: Writer) WriteVersion* (version: INTEGER), NEW;
  978. BEGIN
  979. wr.WriteByte(SHORT(SHORT(version)))
  980. END WriteVersion;
  981. PROCEDURE (VAR wr: Writer) WriteStore* (x: Store), NEW;
  982. VAR t: Kernel.Type; pos1, pos2, pos: INTEGER;
  983. save: WriterState;
  984. BEGIN
  985. ASSERT(wr.rider # NIL, 20);
  986. IF x # NIL THEN
  987. IF wr.noDomain THEN
  988. wr.domain := x.Domain(); wr.noDomain := FALSE
  989. ELSE ASSERT(x.Domain() = wr.domain, 21)
  990. END;
  991. x.ExternalizeAs(x); IF x = NIL THEN wr.writtenStore := NIL; RETURN END
  992. END;
  993. IF wr.st.linkpos > 0 THEN (* link to previous block's <next> or up block's <down> *)
  994. pos := wr.Pos();
  995. IF pos - wr.st.linkpos = 4 THEN
  996. (* hack to resolve ambiguity between next = 0 because of end-of-chain, or because of offset = 0.
  997. above guard holds only if for the latter case.
  998. ASSUMPTION:
  999. this can happen only if linkpos points to a next (not a down)
  1000. and there is a comment byte just before
  1001. *)
  1002. wr.SetPos(wr.st.linkpos - 4); wr.WriteInt(1); wr.WriteInt(pos - wr.st.linkpos - 4)
  1003. ELSE
  1004. wr.SetPos(wr.st.linkpos); wr.WriteInt(pos - wr.st.linkpos - 4)
  1005. END;
  1006. wr.SetPos(pos)
  1007. END;
  1008. IF x = NIL THEN
  1009. wr.WriteSChar(nil);
  1010. wr.WriteInt(0); (* <comment> *)
  1011. wr.st.linkpos := wr.Pos();
  1012. wr.WriteInt(0) (* <next> *)
  1013. ELSIF x.era >= wr.era THEN
  1014. ASSERT(x.era = wr.era, 23);
  1015. IF x.isElem THEN wr.WriteSChar(link) ELSE wr.WriteSChar(newlink) END;
  1016. wr.WriteInt(x.id);
  1017. wr.WriteInt(0); (* <comment> *)
  1018. wr.st.linkpos := wr.Pos();
  1019. wr.WriteInt(0) (* <next> *)
  1020. ELSE
  1021. x.era := wr.era;
  1022. WITH x: Alien DO
  1023. IF x.isElem THEN
  1024. wr.WriteSChar(elem); x.id := wr.nextElemId; INC(wr.nextElemId)
  1025. ELSE
  1026. wr.WriteSChar(store); x.id := wr.nextStoreId; INC(wr.nextStoreId)
  1027. END;
  1028. WritePath(wr, x.path)
  1029. ELSE
  1030. t := Kernel.TypeOf(x);
  1031. x.isElem := t.base[1] = wr.modelType;
  1032. IF x.isElem THEN
  1033. wr.WriteSChar(elem); x.id := wr.nextElemId; INC(wr.nextElemId)
  1034. ELSE
  1035. wr.WriteSChar(store); x.id := wr.nextStoreId; INC(wr.nextStoreId)
  1036. END;
  1037. WriteType(wr, t)
  1038. END;
  1039. wr.WriteInt(0); (* <comment> *)
  1040. pos1 := wr.Pos(); wr.WriteInt(0); wr.WriteInt(0); (* <next>, <down> *)
  1041. pos2 := wr.Pos(); wr.WriteInt(0); (* <len> *)
  1042. save := wr.st; (* push current writer state; switch to structured *)
  1043. wr.st.linkpos := pos1 + 4;
  1044. WITH x: Alien DO ExternalizeAlien(wr, x.file, x.comps)
  1045. ELSE
  1046. x.Externalize(wr)
  1047. END;
  1048. wr.st := save; (* pop writer state *)
  1049. wr.st.linkpos := pos1;
  1050. pos := wr.Pos();
  1051. wr.SetPos(pos2); wr.WriteInt(pos - pos2 - 4); (* patch <len> *)
  1052. wr.SetPos(pos)
  1053. END;
  1054. wr.writtenStore := x
  1055. END WriteStore;
  1056. (** miscellaneous **)
  1057. PROCEDURE Report* (IN msg, p0, p1, p2: ARRAY OF CHAR);
  1058. BEGIN
  1059. IF logReports THEN
  1060. Dialog.ShowParamMsg(msg, p0, p1, p2)
  1061. END
  1062. END Report;
  1063. PROCEDURE BeginCloning (d: Domain);
  1064. BEGIN
  1065. ASSERT(d # NIL, 20);
  1066. INC(d.level);
  1067. IF d.level = 1 THEN
  1068. d.copyera := nextEra; INC(nextEra); d.nextElemId := 0;
  1069. IF d.cleaner = NIL THEN NEW(d.cleaner); d.cleaner.d := d END;
  1070. Kernel.PushTrapCleaner(d.cleaner)
  1071. END
  1072. END BeginCloning;
  1073. PROCEDURE EndCloning (d: Domain);
  1074. BEGIN
  1075. ASSERT(d # NIL, 20);
  1076. DEC(d.level);
  1077. IF d.level = 0 THEN
  1078. d.sDict := NIL;
  1079. Kernel.PopTrapCleaner(d.cleaner);
  1080. d.s := NIL
  1081. END
  1082. END EndCloning;
  1083. PROCEDURE CopyOf* (s: Store): Store;
  1084. VAR h: Store; c: StoreDict; d: Domain; k, org: INTEGER;
  1085. BEGIN
  1086. ASSERT(s # NIL, 20);
  1087. d := DomainOf(s);
  1088. IF d = NIL THEN d := NewDomain(anonymousDomain); s.dlink := d; d.copyDomain := TRUE END;
  1089. BeginCloning(d);
  1090. IF s.era >= d.copyera THEN (* s has already been copied *)
  1091. ASSERT(s.era = d.copyera, 21);
  1092. k := s.id MOD dictLineLen; org := s.id - k;
  1093. c := d.sDict;
  1094. WHILE (c # NIL) & (c.org # org) DO c := c.next END;
  1095. ASSERT((c # NIL) & (c.elem[k] # NIL), 100);
  1096. h := c.elem[k]
  1097. ELSE
  1098. s.era := d.copyera;
  1099. s.id := d.nextElemId; INC(d.nextElemId);
  1100. Kernel.NewObj(h, Kernel.TypeOf(s));
  1101. k := s.id MOD dictLineLen;
  1102. IF k = 0 THEN NEW(c); c.org := s.id; c.next := d.sDict; d.sDict := c
  1103. ELSE c := d.sDict
  1104. END;
  1105. ASSERT((c # NIL) & (c.org = s.id - k) & (c.elem[k] = NIL), 101);
  1106. c.elem[k] := h;
  1107. IF d.s = NIL THEN d.s := h ELSE Join(h, d.s) END;
  1108. h.CopyFrom(s)
  1109. END;
  1110. EndCloning(d);
  1111. RETURN h
  1112. END CopyOf;
  1113. PROCEDURE ExternalizeProxy* (s: Store): Store;
  1114. BEGIN
  1115. IF s # NIL THEN s.ExternalizeAs(s) END;
  1116. RETURN s
  1117. END ExternalizeProxy;
  1118. PROCEDURE InitDomain* (s: Store);
  1119. VAR d: Domain;
  1120. BEGIN
  1121. ASSERT(s # NIL, 20);
  1122. d := DomainOf(s);
  1123. IF d = NIL THEN d := NewDomain(inited); s.dlink := d
  1124. ELSE d.initialized := TRUE
  1125. END
  1126. END InitDomain;
  1127. PROCEDURE Join* (s0, s1: Store);
  1128. VAR d0, d1: Domain;
  1129. BEGIN
  1130. ASSERT(s0 # NIL, 20); ASSERT(s1 # NIL, 21);
  1131. d0 := DomainOf(s0); d1 := DomainOf(s1);
  1132. IF (d0 = NIL) & (d1 = NIL) THEN
  1133. s0.dlink := NewDomain(anonymousDomain); s1.dlink := s0.dlink
  1134. ELSIF d0 = NIL THEN
  1135. s0.dlink := d1; d1.copyDomain := FALSE
  1136. ELSIF d1 = NIL THEN
  1137. s1.dlink := d0; d0.copyDomain := FALSE
  1138. ELSIF d0 # d1 THEN
  1139. ASSERT(~d0.initialized OR ~d1.initialized, 22);
  1140. (* PRE 22 s0.Domain() = NIL OR s1.Domain() = NIL OR s0.Domain() = s1.Domain() *)
  1141. IF ~d0.initialized & (d0.level = 0) THEN d0.dlink := d1; d1.copyDomain := FALSE
  1142. ELSIF ~d1.initialized & (d1.level = 0) THEN d1.dlink := d0; d0.copyDomain := FALSE
  1143. ELSE HALT(100)
  1144. END
  1145. END
  1146. END Join;
  1147. PROCEDURE Joined* (s0, s1: Store): BOOLEAN;
  1148. VAR d0, d1: Domain;
  1149. BEGIN
  1150. ASSERT(s0 # NIL, 20); ASSERT(s1 # NIL, 21);
  1151. d0 := DomainOf(s0); d1 := DomainOf(s1);
  1152. RETURN (s0 = s1) OR ((d0 = d1) & (d0 # NIL))
  1153. END Joined;
  1154. PROCEDURE Unattached* (s: Store): BOOLEAN;
  1155. BEGIN
  1156. ASSERT(s # NIL, 20);
  1157. RETURN (s.dlink = NIL) OR s.dlink.copyDomain
  1158. END Unattached;
  1159. BEGIN
  1160. nextEra := 1; logReports := FALSE
  1161. END Stores.