ORB.Mod.txt 17 KB

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