ORB.Mod.txt 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. MODULE ORB; (*NW 25.6.2014 / 1.3.2019 in Oberon-07*)
  2. IMPORT Files, ORS;
  3. (*Definition of data types Object and Type, which together form the data structure
  4. called "symbol table". Contains procedures for creation of Objects, and for search:
  5. NewObj, this, thisimport, thisfield (and OpenScope, CloseScope).
  6. Handling of import and export, i.e. reading and writing of "symbol files" is done by procedures
  7. Import and Export. This module contains the list of standard identifiers, with which
  8. the symbol table (universe), and that of the pseudo-module SYSTEM are initialized. *)
  9. CONST versionkey* = 1; maxTypTab = 64;
  10. (* class values*) Head* = 0;
  11. Const* = 1; Var* = 2; Par* = 3; Fld* = 4; Typ* = 5;
  12. SProc* = 6; SFunc* = 7; Mod* = 8;
  13. (* form values*)
  14. Byte* = 1; Bool* = 2; Char* = 3; Int* = 4; Real* = 5; Set* = 6;
  15. Pointer* = 7; NilTyp* = 8; NoTyp* = 9; Proc* = 10;
  16. String* = 11; Array* = 12; Record* = 13;
  17. TYPE Object* = POINTER TO ObjDesc;
  18. Module* = POINTER TO ModDesc;
  19. Type* = POINTER TO TypeDesc;
  20. ObjDesc*= RECORD
  21. class*, exno*: BYTE;
  22. expo*, rdo*: BOOLEAN; (*exported / read-only*)
  23. lev*: INTEGER;
  24. next*, dsc*: Object;
  25. type*: Type;
  26. name*: ORS.Ident;
  27. val*: LONGINT
  28. END ;
  29. ModDesc* = RECORD (ObjDesc) orgname*: ORS.Ident END ;
  30. TypeDesc* = RECORD
  31. form*, ref*, mno*: INTEGER; (*ref is only used for import/export*)
  32. nofpar*: INTEGER; (*for procedures, extension level for records*)
  33. len*: LONGINT; (*for arrays, len < 0 => open array; for records: adr of descriptor*)
  34. dsc*, typobj*: Object;
  35. base*: Type; (*for arrays, records, pointers*)
  36. size*: LONGINT; (*in bytes; always multiple of 4, except for Byte, Bool and Char*)
  37. END ;
  38. (* Object classes and the meaning of "val":
  39. class val
  40. ----------
  41. Var address
  42. Par address
  43. Const value
  44. Fld offset
  45. Typ type descriptor (TD) address
  46. SProc inline code number
  47. SFunc inline code number
  48. Mod key
  49. Type forms and the meaning of "dsc" and "base":
  50. form dsc base
  51. ------------------------
  52. Pointer - type of dereferenced object
  53. Proc params result type
  54. Array - type of elements
  55. Record fields extension *)
  56. VAR topScope*, universe, system*: Object;
  57. byteType*, boolType*, charType*: Type;
  58. intType*, realType*, setType*, nilType*, noType*, strType*: Type;
  59. nofmod, Ref: INTEGER;
  60. typtab: ARRAY maxTypTab OF Type;
  61. PROCEDURE NewObj*(VAR obj: Object; id: ORS.Ident; class: INTEGER); (*insert new Object with name id*)
  62. VAR new, x: Object;
  63. BEGIN x := topScope;
  64. WHILE (x.next # NIL) & (x.next.name # id) DO x := x.next END ;
  65. IF x.next = NIL THEN
  66. NEW(new); new.name := id; new.class := class; new.next := NIL; new.rdo := FALSE; new.dsc := NIL;
  67. x.next := new; obj := new
  68. ELSE obj := x.next; ORS.Mark("mult def")
  69. END
  70. END NewObj;
  71. PROCEDURE thisObj*(): Object;
  72. VAR s, x: Object;
  73. BEGIN s := topScope;
  74. REPEAT x := s.next;
  75. WHILE (x # NIL) & (x.name # ORS.id) DO x := x.next END ;
  76. s := s.dsc
  77. UNTIL (x # NIL) OR (s = NIL);
  78. RETURN x
  79. END thisObj;
  80. PROCEDURE thisimport*(mod: Object): Object;
  81. VAR obj: Object;
  82. BEGIN
  83. IF mod.rdo THEN
  84. IF mod.name[0] # 0X THEN
  85. obj := mod.dsc;
  86. WHILE (obj # NIL) & (obj.name # ORS.id) DO obj := obj.next END
  87. ELSE obj := NIL
  88. END
  89. ELSE obj := NIL
  90. END ;
  91. RETURN obj
  92. END thisimport;
  93. PROCEDURE thisfield*(rec: Type): Object;
  94. VAR fld: Object;
  95. BEGIN fld := rec.dsc;
  96. WHILE (fld # NIL) & (fld.name # ORS.id) DO fld := fld.next END ;
  97. RETURN fld
  98. END thisfield;
  99. PROCEDURE OpenScope*;
  100. VAR s: Object;
  101. BEGIN NEW(s); s.class := Head; s.dsc := topScope; s.next := NIL; topScope := s
  102. END OpenScope;
  103. PROCEDURE CloseScope*;
  104. BEGIN topScope := topScope.dsc
  105. END CloseScope;
  106. (*------------------------------- Import ---------------------------------*)
  107. PROCEDURE MakeFileName*(VAR FName: ORS.Ident; name, ext: ARRAY OF CHAR);
  108. VAR i, j: INTEGER;
  109. BEGIN i := 0; j := 0; (*assume name suffix less than 4 characters*)
  110. WHILE (i < ORS.IdLen-5) & (name[i] > 0X) DO FName[i] := name[i]; INC(i) END ;
  111. REPEAT FName[i]:= ext[j]; INC(i); INC(j) UNTIL ext[j] = 0X;
  112. FName[i] := 0X
  113. END MakeFileName;
  114. PROCEDURE ThisModule(name, orgname: ORS.Ident; non: BOOLEAN; key: LONGINT): Object;
  115. VAR mod: Module; obj, obj1: Object;
  116. BEGIN obj1 := topScope; obj := obj1.next; (*search for module*)
  117. WHILE (obj # NIL) & (obj.name # name) DO obj1 := obj; obj := obj1.next END ;
  118. IF obj = NIL THEN (*insert new module*)
  119. NEW(mod); mod.class := Mod; mod.rdo := FALSE;
  120. mod.name := name; mod.orgname := orgname; mod.val := key;
  121. mod.lev := nofmod; INC(nofmod); mod.type := noType; mod.dsc := NIL; mod.next := NIL;
  122. obj1.next := mod; obj := mod
  123. ELSE (*module already present*)
  124. IF non THEN ORS.Mark("invalid import order") END
  125. END ;
  126. RETURN obj
  127. END ThisModule;
  128. PROCEDURE Read(VAR R: Files.Rider; VAR x: INTEGER);
  129. VAR b: BYTE;
  130. BEGIN Files.ReadByte(R, b);
  131. IF b < 80H THEN x := b ELSE x := b - 100H END
  132. END Read;
  133. PROCEDURE InType(VAR R: Files.Rider; thismod: Object; VAR T: Type);
  134. VAR key: LONGINT;
  135. ref, class, form, np, readonly: INTEGER;
  136. fld, par, obj, mod, last: Object;
  137. t: Type;
  138. name, modname: ORS.Ident;
  139. BEGIN Read(R, ref);
  140. IF ref < 0 THEN T := typtab[-ref] (*already read*)
  141. ELSE NEW(t); T := t; typtab[ref] := t; t.mno := thismod.lev;
  142. Read(R, form); t.form := form;
  143. IF form = Pointer THEN InType(R, thismod, t.base); t.size := 4
  144. ELSIF form = Array THEN
  145. InType(R, thismod, t.base); Files.ReadNum(R, t.len); Files.ReadNum(R, t.size)
  146. ELSIF form = Record THEN
  147. InType(R, thismod, t.base);
  148. IF t.base.form = NoTyp THEN t.base := NIL; obj := NIL ELSE obj := t.base.dsc END ;
  149. Files.ReadNum(R, t.len); (*TD adr/exno*)
  150. Files.ReadNum(R, t.nofpar); (*ext level*)
  151. Files.ReadNum(R, t.size);
  152. Read(R, class); last := NIL;
  153. WHILE class # 0 DO (*fields*)
  154. NEW(fld); fld.class := class; Files.ReadString(R, fld.name);
  155. IF last = NIL THEN t.dsc := fld ELSE last.next := fld END ;
  156. last := fld;
  157. IF fld.name[0] # 0X THEN fld.expo := TRUE; InType(R, thismod, fld.type) ELSE fld.expo := FALSE; fld.type := nilType END ;
  158. Files.ReadNum(R, fld.val); Read(R, class)
  159. END ;
  160. IF last = NIL THEN t.dsc := obj ELSE last.next := obj END
  161. ELSIF form = Proc THEN
  162. InType(R, thismod, t.base);
  163. obj := NIL; np := 0; Read(R, class);
  164. WHILE class # 0 DO (*parameters*)
  165. NEW(par); par.class := class; Read(R, readonly); par.rdo := readonly = 1;
  166. InType(R, thismod, par.type); par.next := obj; obj := par; INC(np); Read(R, class)
  167. END ;
  168. t.dsc := obj; t.nofpar := np; t.size := 4
  169. END ;
  170. Files.ReadString(R, modname);
  171. IF modname[0] # 0X THEN (*re-import*)
  172. Files.ReadInt(R, key); Files.ReadString(R, name);
  173. mod := ThisModule(modname, modname, FALSE, key);
  174. obj := mod.dsc; (*search type*)
  175. WHILE (obj # NIL) & (obj.name # name) DO obj := obj.next END ;
  176. IF obj # NIL THEN T := obj.type (*type object found in object list of mod*)
  177. ELSE (*insert new type object in object list of mod*)
  178. NEW(obj); obj.name := name; obj.class := Typ; obj.next := mod.dsc; mod.dsc := obj; obj.type := t;
  179. t.mno := mod.lev; t.typobj := obj; T := t
  180. END ;
  181. typtab[ref] := T
  182. END
  183. END
  184. END InType;
  185. PROCEDURE Import*(VAR modid, modid1: ORS.Ident);
  186. VAR key: LONGINT; class, k: INTEGER;
  187. obj: Object; t: Type;
  188. thismod: Object;
  189. modname, fname: ORS.Ident;
  190. F: Files.File; R: Files.Rider;
  191. BEGIN
  192. IF modid1 = "SYSTEM" THEN
  193. thismod := ThisModule(modid, modid1, TRUE, key); DEC(nofmod);
  194. thismod.lev := 0; thismod.dsc := system; thismod.rdo := TRUE
  195. ELSE MakeFileName(fname, modid1, ".smb"); F := Files.Old(fname);
  196. IF F # NIL THEN
  197. Files.Set(R, F, 0); Files.ReadInt(R, key); Files.ReadInt(R, key); Files.ReadString(R, modname);
  198. thismod := ThisModule(modid, modid1, TRUE, key); thismod.rdo := TRUE;
  199. Read(R, class); (*version key*)
  200. IF class # versionkey THEN ORS.Mark("wrong version") END ;
  201. Read(R, class);
  202. WHILE class # 0 DO
  203. NEW(obj); obj.class := class; Files.ReadString(R, obj.name);
  204. InType(R, thismod, obj.type); obj.lev := -thismod.lev;
  205. IF class = Typ THEN
  206. t := obj.type; t.typobj := obj; Read(R, k); (*fixup bases of previously declared pointer types*)
  207. WHILE k # 0 DO typtab[k].base := t; Read(R, k) END
  208. ELSE
  209. IF class = Const THEN
  210. IF obj.type.form = Real THEN Files.ReadInt(R, obj.val) ELSE Files.ReadNum(R, obj.val) END
  211. ELSIF class = Var THEN Files.ReadNum(R, obj.val); obj.rdo := TRUE
  212. END
  213. END ;
  214. obj.next := thismod.dsc; thismod.dsc := obj; Read(R, class)
  215. END ;
  216. ELSE ORS.Mark("import not available")
  217. END
  218. END
  219. END Import;
  220. (*-------------------------------- Export ---------------------------------*)
  221. PROCEDURE Write(VAR R: Files.Rider; x: INTEGER);
  222. BEGIN Files.WriteByte(R, x)
  223. END Write;
  224. PROCEDURE OutType(VAR R: Files.Rider; t: Type);
  225. VAR obj, mod, fld, bot: Object;
  226. PROCEDURE OutPar(VAR R: Files.Rider; par: Object; n: INTEGER);
  227. VAR cl: INTEGER;
  228. BEGIN
  229. IF n > 0 THEN
  230. OutPar(R, par.next, n-1); cl := par.class;
  231. Write(R, cl);
  232. IF par.rdo THEN Write(R, 1) ELSE Write(R, 0) END ;
  233. OutType(R, par.type)
  234. END
  235. END OutPar;
  236. PROCEDURE FindHiddenPointers(VAR R: Files.Rider; typ: Type; offset: LONGINT);
  237. VAR fld: Object; i, n: LONGINT;
  238. BEGIN
  239. IF (typ.form = Pointer) OR (typ.form = NilTyp) THEN Write(R, Fld); Write(R, 0); Files.WriteNum(R, offset)
  240. ELSIF typ.form = Record THEN fld := typ.dsc;
  241. WHILE fld # NIL DO FindHiddenPointers(R, fld.type, fld.val + offset); fld := fld.next END
  242. ELSIF typ.form = Array THEN i := 0; n := typ.len;
  243. WHILE i < n DO FindHiddenPointers(R, typ.base, typ.base.size * i + offset); INC(i) END
  244. END
  245. END FindHiddenPointers;
  246. BEGIN
  247. IF t.ref > 0 THEN (*type was already output*) Write(R, -t.ref)
  248. ELSE obj := t.typobj;
  249. IF obj # NIL THEN Write(R, Ref); t.ref := Ref; INC(Ref) ELSE (*anonymous*) Write(R, 0) END ;
  250. Write(R, t.form);
  251. IF t.form = Pointer THEN OutType(R, t.base)
  252. ELSIF t.form = Array THEN OutType(R, t.base); Files.WriteNum(R, t.len); Files.WriteNum(R, t.size)
  253. ELSIF t.form = Record THEN
  254. IF t.base # NIL THEN OutType(R, t.base); bot := t.base.dsc ELSE OutType(R, noType); bot := NIL END ;
  255. IF obj # NIL THEN Files.WriteNum(R, obj.exno) ELSE Write(R, 0) END ;
  256. Files.WriteNum(R, t.nofpar); Files.WriteNum(R, t.size);
  257. fld := t.dsc;
  258. WHILE fld # bot DO (*fields*)
  259. IF fld.expo THEN
  260. Write(R, Fld); Files.WriteString(R, fld.name); OutType(R, fld.type); Files.WriteNum(R, fld.val) (*offset*)
  261. ELSE FindHiddenPointers(R, fld.type, fld.val)
  262. END ;
  263. fld := fld.next
  264. END ;
  265. Write(R, 0)
  266. ELSIF t.form = Proc THEN OutType(R, t.base); OutPar(R, t.dsc, t.nofpar); Write(R, 0)
  267. END ;
  268. IF (t.mno > 0) & (obj # NIL) THEN (*re-export, output name*)
  269. mod := topScope.next;
  270. WHILE (mod # NIL) & (mod.lev # t.mno) DO mod := mod.next END ;
  271. IF mod # NIL THEN Files.WriteString(R, mod(Module).orgname); Files.WriteInt(R, mod.val); Files.WriteString(R, obj.name)
  272. ELSE ORS.Mark("re-export not found"); Write(R, 0)
  273. END
  274. ELSE Write(R, 0)
  275. END
  276. END
  277. END OutType;
  278. PROCEDURE Export*(VAR modid: ORS.Ident; VAR newSF: BOOLEAN; VAR key: LONGINT);
  279. VAR x, sum, oldkey: LONGINT;
  280. obj, obj0: Object;
  281. filename: ORS.Ident;
  282. F, F1: Files.File; R, R1: Files.Rider;
  283. BEGIN Ref := Record + 1; MakeFileName(filename, modid, ".smb");
  284. F := Files.New(filename); Files.Set(R, F, 0);
  285. Files.WriteInt(R, 0); (*placeholder*)
  286. Files.WriteInt(R, 0); (*placeholder for key to be inserted at the end*)
  287. Files.WriteString(R, modid); Write(R, versionkey);
  288. obj := topScope.next;
  289. WHILE obj # NIL DO
  290. IF obj.expo THEN
  291. Write(R, obj.class); Files.WriteString(R, obj.name);
  292. OutType(R, obj.type);
  293. IF obj.class = Typ THEN
  294. IF obj.type.form = Record THEN
  295. obj0 := topScope.next; (*check whether this is base of previously declared pointer types*)
  296. WHILE obj0 # obj DO
  297. IF (obj0.type.form = Pointer) & (obj0.type.base = obj.type) & (obj0.type.ref > 0) THEN Write(R, obj0.type.ref) END ;
  298. obj0 := obj0.next
  299. END
  300. END ;
  301. Write(R, 0)
  302. ELSIF obj.class = Const THEN
  303. IF obj.type.form = Proc THEN Files.WriteNum(R, obj.exno)
  304. ELSIF obj.type.form = Real THEN Files.WriteInt(R, obj.val)
  305. ELSE Files.WriteNum(R, obj.val)
  306. END
  307. ELSIF obj.class = Var THEN Files.WriteNum(R, obj.exno)
  308. END
  309. END ;
  310. obj := obj.next
  311. END ;
  312. REPEAT Write(R, 0) UNTIL Files.Length(F) MOD 4 = 0;
  313. FOR Ref := Record+1 TO maxTypTab-1 DO typtab[Ref] := NIL END ;
  314. Files.Set(R, F, 0); sum := 0; Files.ReadInt(R, x); (* compute key (checksum) *)
  315. WHILE ~R.eof DO sum := sum + x; Files.ReadInt(R, x) END ;
  316. F1 := Files.Old(filename); (*sum is new key*)
  317. IF F1 # NIL THEN Files.Set(R1, F1, 4); Files.ReadInt(R1, oldkey) ELSE oldkey := sum+1 END ;
  318. IF sum # oldkey THEN
  319. IF newSF OR (F1 = NIL) THEN
  320. key := sum; newSF := TRUE; Files.Set(R, F, 4); Files.WriteInt(R, sum); Files.Register(F) (*insert checksum*)
  321. ELSE ORS.Mark("new symbol file inhibited")
  322. END
  323. ELSE newSF := FALSE; key := sum
  324. END
  325. END Export;
  326. PROCEDURE Init*;
  327. BEGIN topScope := universe; nofmod := 1
  328. END Init;
  329. PROCEDURE type(ref, form: INTEGER; size: LONGINT): Type;
  330. VAR tp: Type;
  331. BEGIN NEW(tp); tp.form := form; tp.size := size; tp.ref := ref; tp.base := NIL;
  332. typtab[ref] := tp; RETURN tp
  333. END type;
  334. PROCEDURE enter(name: ARRAY OF CHAR; cl: INTEGER; type: Type; n: LONGINT);
  335. VAR obj: Object;
  336. BEGIN NEW(obj); obj.name := name; obj.class := cl; obj.type := type; obj.val := n; obj.dsc := NIL;
  337. IF cl = Typ THEN type.typobj := obj END ;
  338. obj.next := system; system := obj
  339. END enter;
  340. BEGIN
  341. byteType := type(Byte, Int, 1);
  342. boolType := type(Bool, Bool, 1);
  343. charType := type(Char, Char,1);
  344. intType := type(Int, Int, 4);
  345. realType := type(Real, Real, 4);
  346. setType := type(Set, Set,4);
  347. nilType := type(NilTyp, NilTyp, 4);
  348. noType := type(NoTyp, NoTyp, 4);
  349. strType := type(String, String, 8);
  350. (*initialize universe with data types and in-line procedures;
  351. LONGINT is synonym to INTEGER, LONGREAL to REAL.
  352. LED, ADC, SBC; LDPSR, LDREG, REG, COND are not in language definition*)
  353. system := NIL; (*n = procno*10 + nofpar*)
  354. enter("UML", SFunc, intType, 132); (*functions*)
  355. enter("SBC", SFunc, intType, 122);
  356. enter("ADC", SFunc, intType, 112);
  357. enter("ROR", SFunc, intType, 92);
  358. enter("ASR", SFunc, intType, 82);
  359. enter("LSL", SFunc, intType, 72);
  360. enter("LEN", SFunc, intType, 61);
  361. enter("CHR", SFunc, charType, 51);
  362. enter("ORD", SFunc, intType, 41);
  363. enter("FLT", SFunc, realType, 31);
  364. enter("FLOOR", SFunc, intType, 21);
  365. enter("ODD", SFunc, boolType, 11);
  366. enter("ABS", SFunc, intType, 1);
  367. enter("LED", SProc, noType, 81); (*procedures*)
  368. enter("UNPK", SProc, noType, 72);
  369. enter("PACK", SProc, noType, 62);
  370. enter("NEW", SProc, noType, 51);
  371. enter("ASSERT", SProc, noType, 41);
  372. enter("EXCL", SProc, noType, 32);
  373. enter("INCL", SProc, noType, 22);
  374. enter("DEC", SProc, noType, 11);
  375. enter("INC", SProc, noType, 1);
  376. enter("SET", Typ, setType, 0); (*types*)
  377. enter("BOOLEAN", Typ, boolType, 0);
  378. enter("BYTE", Typ, byteType, 0);
  379. enter("CHAR", Typ, charType, 0);
  380. enter("LONGREAL", Typ, realType, 0);
  381. enter("REAL", Typ, realType, 0);
  382. enter("LONGINT", Typ, intType, 0);
  383. enter("INTEGER", Typ, intType, 0);
  384. topScope := NIL; OpenScope; topScope.next := system; universe := topScope;
  385. system := NIL; (* initialize "unsafe" pseudo-module SYSTEM*)
  386. enter("H", SFunc, intType, 201); (*functions*)
  387. enter("COND", SFunc, boolType, 191);
  388. enter("SIZE", SFunc, intType, 181);
  389. enter("ADR", SFunc, intType, 171);
  390. enter("VAL", SFunc, intType, 162);
  391. enter("REG", SFunc, intType, 151);
  392. enter("BIT", SFunc, boolType, 142);
  393. enter("LDREG", SProc, noType, 142); (*procedures*)
  394. enter("LDPSR", SProc, noType, 131);
  395. enter("COPY", SProc, noType, 123);
  396. enter("PUT", SProc, noType, 112);
  397. enter("GET", SProc, noType, 102);
  398. END ORB.