ORB.Mod.txt 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. MODULE ORB; (*NW 25.6.2014 / 26.1.2020 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
  119. obj1 := topScope; obj := obj1.next;
  120. WHILE (obj # NIL) & (obj IS Module) & (obj(Module).orgname # orgname) DO
  121. obj1 := obj; obj := obj1.next
  122. END
  123. END ;
  124. IF obj = NIL THEN (*insert new module*)
  125. NEW(mod); mod.class := Mod; mod.rdo := FALSE;
  126. mod.name := name; mod.orgname := orgname; mod.val := key;
  127. mod.lev := nofmod; INC(nofmod); mod.type := noType; mod.dsc := NIL; mod.next := NIL;
  128. obj1.next := mod; obj := mod
  129. ELSE (*module already present*)
  130. IF non THEN ORS.Mark("invalid import order") END
  131. END ;
  132. RETURN obj
  133. END ThisModule;
  134. PROCEDURE Read(VAR R: Files.Rider; VAR x: INTEGER);
  135. VAR b: BYTE;
  136. BEGIN Files.ReadByte(R, b);
  137. IF b < 80H THEN x := b ELSE x := b - 100H END
  138. END Read;
  139. PROCEDURE InType(VAR R: Files.Rider; thismod: Object; VAR T: Type);
  140. VAR key: LONGINT;
  141. ref, class, form, np, readonly: INTEGER;
  142. fld, par, obj, mod, last: Object;
  143. t: Type;
  144. name, modname: ORS.Ident;
  145. BEGIN Read(R, ref);
  146. IF ref < 0 THEN T := typtab[-ref] (*already read*)
  147. ELSE NEW(t); T := t; typtab[ref] := t; t.mno := thismod.lev;
  148. Read(R, form); t.form := form;
  149. IF form = Pointer THEN InType(R, thismod, t.base); t.size := 4
  150. ELSIF form = Array THEN
  151. InType(R, thismod, t.base); Files.ReadNum(R, t.len); Files.ReadNum(R, t.size)
  152. ELSIF form = Record THEN
  153. InType(R, thismod, t.base);
  154. IF t.base.form = NoTyp THEN t.base := NIL; obj := NIL ELSE obj := t.base.dsc END ;
  155. Files.ReadNum(R, t.len); (*TD adr/exno*)
  156. Files.ReadNum(R, t.nofpar); (*ext level*)
  157. Files.ReadNum(R, t.size);
  158. Read(R, class); last := NIL;
  159. WHILE class # 0 DO (*fields*)
  160. NEW(fld); fld.class := class; Files.ReadString(R, fld.name);
  161. IF last = NIL THEN t.dsc := fld ELSE last.next := fld END ;
  162. last := fld;
  163. IF fld.name[0] # 0X THEN fld.expo := TRUE; InType(R, thismod, fld.type) ELSE fld.expo := FALSE; fld.type := nilType END ;
  164. Files.ReadNum(R, fld.val); Read(R, class)
  165. END ;
  166. IF last = NIL THEN t.dsc := obj ELSE last.next := obj END
  167. ELSIF form = Proc THEN
  168. InType(R, thismod, t.base);
  169. obj := NIL; np := 0; Read(R, class);
  170. WHILE class # 0 DO (*parameters*)
  171. NEW(par); par.class := class; Read(R, readonly); par.rdo := readonly = 1;
  172. InType(R, thismod, par.type); par.next := obj; obj := par; INC(np); Read(R, class)
  173. END ;
  174. t.dsc := obj; t.nofpar := np; t.size := 4
  175. END ;
  176. Files.ReadString(R, modname);
  177. IF modname[0] # 0X THEN (*re-import*)
  178. Files.ReadInt(R, key); Files.ReadString(R, name);
  179. mod := ThisModule(modname, modname, FALSE, key);
  180. obj := mod.dsc; (*search type*)
  181. WHILE (obj # NIL) & (obj.name # name) DO obj := obj.next END ;
  182. IF obj # NIL THEN T := obj.type (*type object found in object list of mod*)
  183. ELSE (*insert new type object in object list of mod*)
  184. NEW(obj); obj.name := name; obj.class := Typ; obj.next := mod.dsc; mod.dsc := obj; obj.type := t;
  185. t.mno := mod.lev; t.typobj := obj; T := t
  186. END ;
  187. typtab[ref] := T
  188. END
  189. END
  190. END InType;
  191. PROCEDURE Import*(VAR modid, modid1: ORS.Ident);
  192. VAR key: LONGINT; class, k: INTEGER;
  193. obj, thismod: Object;
  194. modname, fname: ORS.Ident;
  195. F: Files.File; R: Files.Rider;
  196. BEGIN
  197. IF modid1 = "SYSTEM" THEN
  198. thismod := ThisModule(modid, modid1, TRUE, key); DEC(nofmod);
  199. thismod.lev := 0; thismod.dsc := system; thismod.rdo := TRUE
  200. ELSE MakeFileName(fname, modid1, ".smb"); F := Files.Old(fname);
  201. IF F # NIL THEN
  202. Files.Set(R, F, 0); Files.ReadInt(R, key); Files.ReadInt(R, key); Files.ReadString(R, modname);
  203. thismod := ThisModule(modid, modid1, TRUE, key); thismod.rdo := TRUE;
  204. Read(R, class); (*version key*)
  205. IF class # versionkey THEN ORS.Mark("wrong version") END ;
  206. Read(R, class);
  207. WHILE class # 0 DO
  208. NEW(obj); obj.class := class; Files.ReadString(R, obj.name);
  209. InType(R, thismod, obj.type); obj.lev := -thismod.lev;
  210. IF class = Typ THEN obj.type.typobj := obj; Read(R, k)
  211. ELSIF class = Const THEN
  212. IF obj.type.form = Real THEN Files.ReadInt(R, obj.val) ELSE Files.ReadNum(R, obj.val) END
  213. ELSIF class = Var THEN Files.ReadNum(R, obj.val); obj.rdo := TRUE
  214. END ;
  215. obj.next := thismod.dsc; thismod.dsc := obj; Read(R, class)
  216. END ;
  217. ELSE ORS.Mark("import not available")
  218. END
  219. END
  220. END Import;
  221. (*-------------------------------- Export ---------------------------------*)
  222. PROCEDURE Write(VAR R: Files.Rider; x: INTEGER);
  223. BEGIN Files.WriteByte(R, x)
  224. END Write;
  225. PROCEDURE OutType(VAR R: Files.Rider; t: Type);
  226. VAR obj, mod, fld, bot: Object;
  227. PROCEDURE OutPar(VAR R: Files.Rider; par: Object; n: INTEGER);
  228. VAR cl: INTEGER;
  229. BEGIN
  230. IF n > 0 THEN
  231. OutPar(R, par.next, n-1); cl := par.class;
  232. Write(R, cl);
  233. IF par.rdo THEN Write(R, 1) ELSE Write(R, 0) END ;
  234. OutType(R, par.type)
  235. END
  236. END OutPar;
  237. PROCEDURE FindHiddenPointers(VAR R: Files.Rider; typ: Type; offset: LONGINT);
  238. VAR fld: Object; i, n: LONGINT;
  239. BEGIN
  240. IF (typ.form = Pointer) OR (typ.form = NilTyp) THEN Write(R, Fld); Write(R, 0); Files.WriteNum(R, offset)
  241. ELSIF typ.form = Record THEN fld := typ.dsc;
  242. WHILE fld # NIL DO FindHiddenPointers(R, fld.type, fld.val + offset); fld := fld.next END
  243. ELSIF typ.form = Array THEN i := 0; n := typ.len;
  244. WHILE i < n DO FindHiddenPointers(R, typ.base, typ.base.size * i + offset); INC(i) END
  245. END
  246. END FindHiddenPointers;
  247. BEGIN
  248. IF t.ref > 0 THEN (*type was already output*) Write(R, -t.ref)
  249. ELSE obj := t.typobj;
  250. IF obj # NIL THEN Write(R, Ref); t.ref := Ref; INC(Ref) ELSE (*anonymous*) Write(R, 0) END ;
  251. Write(R, t.form);
  252. IF t.form = Pointer THEN OutType(R, t.base)
  253. ELSIF t.form = Array THEN OutType(R, t.base); Files.WriteNum(R, t.len); Files.WriteNum(R, t.size)
  254. ELSIF t.form = Record THEN
  255. IF t.base # NIL THEN OutType(R, t.base); bot := t.base.dsc ELSE OutType(R, noType); bot := NIL END ;
  256. IF obj # NIL THEN
  257. IF t.mno > 0 THEN Files.WriteNum(R, t.len) ELSE Files.WriteNum(R, obj.exno) END
  258. ELSE Write(R, 0)
  259. END ;
  260. Files.WriteNum(R, t.nofpar); Files.WriteNum(R, t.size);
  261. fld := t.dsc;
  262. WHILE fld # bot DO (*fields*)
  263. IF fld.expo THEN
  264. Write(R, Fld); Files.WriteString(R, fld.name); OutType(R, fld.type); Files.WriteNum(R, fld.val) (*offset*)
  265. ELSE FindHiddenPointers(R, fld.type, fld.val)
  266. END ;
  267. fld := fld.next
  268. END ;
  269. Write(R, 0)
  270. ELSIF t.form = Proc THEN OutType(R, t.base); OutPar(R, t.dsc, t.nofpar); Write(R, 0)
  271. END ;
  272. IF (t.mno > 0) & (obj # NIL) THEN (*re-export, output name*)
  273. mod := topScope.next;
  274. WHILE (mod # NIL) & (mod.lev # t.mno) DO mod := mod.next END ;
  275. IF mod # NIL THEN Files.WriteString(R, mod(Module).orgname); Files.WriteInt(R, mod.val); Files.WriteString(R, obj.name)
  276. ELSE ORS.Mark("re-export not found"); Write(R, 0)
  277. END
  278. ELSE Write(R, 0)
  279. END
  280. END
  281. END OutType;
  282. PROCEDURE Export*(VAR modid: ORS.Ident; VAR newSF: BOOLEAN; VAR key: LONGINT);
  283. VAR x, sum, oldkey: LONGINT;
  284. obj: Object;
  285. filename: ORS.Ident;
  286. F, F1: Files.File; R, R1: Files.Rider;
  287. BEGIN Ref := Record + 1; MakeFileName(filename, modid, ".smb");
  288. F := Files.New(filename); Files.Set(R, F, 0);
  289. Files.WriteInt(R, 0); (*placeholder*)
  290. Files.WriteInt(R, 0); (*placeholder for key to be inserted at the end*)
  291. Files.WriteString(R, modid); Write(R, versionkey);
  292. obj := topScope.next;
  293. WHILE obj # NIL DO
  294. IF obj.expo THEN
  295. Write(R, obj.class); Files.WriteString(R, obj.name);
  296. OutType(R, obj.type);
  297. IF obj.class = Typ THEN Write(R, 0)
  298. ELSIF obj.class = Const THEN
  299. IF obj.type.form = Proc THEN Files.WriteNum(R, obj.exno)
  300. ELSIF obj.type.form = Real THEN Files.WriteInt(R, obj.val)
  301. ELSE Files.WriteNum(R, obj.val)
  302. END
  303. ELSIF obj.class = Var THEN Files.WriteNum(R, obj.exno)
  304. END
  305. END ;
  306. obj := obj.next
  307. END ;
  308. REPEAT Write(R, 0) UNTIL Files.Length(F) MOD 4 = 0;
  309. FOR Ref := Record+1 TO maxTypTab-1 DO typtab[Ref] := NIL END ;
  310. Files.Set(R, F, 0); sum := 0; Files.ReadInt(R, x); (* compute key (checksum) *)
  311. WHILE ~R.eof DO sum := sum + x; Files.ReadInt(R, x) END ;
  312. F1 := Files.Old(filename); (*sum is new key*)
  313. IF F1 # NIL THEN Files.Set(R1, F1, 4); Files.ReadInt(R1, oldkey) ELSE oldkey := sum+1 END ;
  314. IF sum # oldkey THEN
  315. IF newSF OR (F1 = NIL) THEN
  316. key := sum; newSF := TRUE; Files.Set(R, F, 4); Files.WriteInt(R, sum); Files.Register(F) (*insert checksum*)
  317. ELSE ORS.Mark("new symbol file inhibited")
  318. END
  319. ELSE newSF := FALSE; key := sum
  320. END
  321. END Export;
  322. PROCEDURE Init*;
  323. BEGIN topScope := universe; nofmod := 1
  324. END Init;
  325. PROCEDURE type(ref, form: INTEGER; size: LONGINT): Type;
  326. VAR tp: Type;
  327. BEGIN NEW(tp); tp.form := form; tp.size := size; tp.ref := ref; tp.base := NIL;
  328. typtab[ref] := tp; RETURN tp
  329. END type;
  330. PROCEDURE enter(name: ARRAY OF CHAR; cl: INTEGER; type: Type; n: LONGINT);
  331. VAR obj: Object;
  332. BEGIN NEW(obj); obj.name := name; obj.class := cl; obj.type := type; obj.val := n; obj.dsc := NIL;
  333. IF cl = Typ THEN type.typobj := obj END ;
  334. obj.next := system; system := obj
  335. END enter;
  336. BEGIN
  337. byteType := type(Byte, Int, 1);
  338. boolType := type(Bool, Bool, 1);
  339. charType := type(Char, Char,1);
  340. intType := type(Int, Int, 4);
  341. realType := type(Real, Real, 4);
  342. setType := type(Set, Set,4);
  343. nilType := type(NilTyp, NilTyp, 4);
  344. noType := type(NoTyp, NoTyp, 4);
  345. strType := type(String, String, 8);
  346. (*initialize universe with data types and in-line procedures;
  347. LONGINT is synonym to INTEGER, LONGREAL to REAL.
  348. LED, ADC, SBC; LDPSR, LDREG, REG, COND are not in language definition*)
  349. system := NIL; (*n = procno*10 + nofpar*)
  350. enter("UML", SFunc, intType, 132); (*functions*)
  351. enter("SBC", SFunc, intType, 122);
  352. enter("ADC", SFunc, intType, 112);
  353. enter("ROR", SFunc, intType, 92);
  354. enter("ASR", SFunc, intType, 82);
  355. enter("LSL", SFunc, intType, 72);
  356. enter("LEN", SFunc, intType, 61);
  357. enter("CHR", SFunc, charType, 51);
  358. enter("ORD", SFunc, intType, 41);
  359. enter("FLT", SFunc, realType, 31);
  360. enter("FLOOR", SFunc, intType, 21);
  361. enter("ODD", SFunc, boolType, 11);
  362. enter("ABS", SFunc, intType, 1);
  363. enter("LED", SProc, noType, 81); (*procedures*)
  364. enter("UNPK", SProc, noType, 72);
  365. enter("PACK", SProc, noType, 62);
  366. enter("NEW", SProc, noType, 51);
  367. enter("ASSERT", SProc, noType, 41);
  368. enter("EXCL", SProc, noType, 32);
  369. enter("INCL", SProc, noType, 22);
  370. enter("DEC", SProc, noType, 11);
  371. enter("INC", SProc, noType, 1);
  372. enter("SET", Typ, setType, 0); (*types*)
  373. enter("BOOLEAN", Typ, boolType, 0);
  374. enter("BYTE", Typ, byteType, 0);
  375. enter("CHAR", Typ, charType, 0);
  376. enter("LONGREAL", Typ, realType, 0);
  377. enter("REAL", Typ, realType, 0);
  378. enter("LONGINT", Typ, intType, 0);
  379. enter("INTEGER", Typ, intType, 0);
  380. topScope := NIL; OpenScope; topScope.next := system; universe := topScope;
  381. system := NIL; (* initialize "unsafe" pseudo-module SYSTEM*)
  382. enter("H", SFunc, intType, 201); (*functions*)
  383. enter("COND", SFunc, boolType, 191);
  384. enter("SIZE", SFunc, intType, 181);
  385. enter("ADR", SFunc, intType, 171);
  386. enter("VAL", SFunc, intType, 162);
  387. enter("REG", SFunc, intType, 151);
  388. enter("BIT", SFunc, boolType, 142);
  389. enter("LDREG", SProc, noType, 142); (*procedures*)
  390. enter("LDPSR", SProc, noType, 131);
  391. enter("COPY", SProc, noType, 123);
  392. enter("PUT", SProc, noType, 112);
  393. enter("GET", SProc, noType, 102);
  394. END ORB.