2
0

Loader.txt 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. MODULE StdLoader;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 Std/Mod/Loader.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT S := SYSTEM, Kernel, Files;
  5. CONST
  6. done = Kernel.done;
  7. fileNotFound = Kernel.fileNotFound;
  8. syntaxError = Kernel.syntaxError;
  9. objNotFound = Kernel.objNotFound;
  10. illegalFPrint = Kernel.illegalFPrint;
  11. cyclicImport = Kernel.cyclicImport;
  12. noMem = Kernel.noMem;
  13. commNotFound = Kernel.commNotFound;
  14. commSyntaxError = Kernel.commSyntaxError;
  15. descNotFound = -1;
  16. OFdir = "Code";
  17. SYSdir = "System";
  18. initMod = "Init";
  19. OFtag = 6F4F4346H;
  20. (* meta interface consts *)
  21. mConst = 1; mTyp = 2; mVar = 3; mProc = 4; mField = 5;
  22. mBool = 1; mChar = 2; mLChar = 3; mSInt = 4; mInt = 5; mLInt = 6;
  23. mReal = 7; mLReal = 8; mSet = 9; mString = 10; mLString = 11;
  24. mRecord = 1; mArray = 2; mPointer = 3; mProctyp = 4;
  25. mInternal = 1; mReadonly = 2; mPrivate = 3; mExported = 4;
  26. (* fixup types *)
  27. absolute = 100; relative = 101; copy = 102; table = 103; tableend = 104; deref = 105; halfword = 106;
  28. TYPE
  29. Name = ARRAY 256 OF CHAR;
  30. ModSpec = POINTER TO RECORD
  31. next, link, imp: ModSpec;
  32. name: Name;
  33. file: Files.File;
  34. mod: Kernel.Module;
  35. hs, ms, ds, cs, vs, mad, dad: INTEGER
  36. END;
  37. Hook = POINTER TO RECORD (Kernel.LoaderHook) END;
  38. VAR
  39. res-: INTEGER;
  40. importing-, imported-, object-: Name;
  41. inp: Files.Reader;
  42. m: Kernel.Module;
  43. PROCEDURE Error (r: INTEGER; impd, impg: ModSpec);
  44. BEGIN
  45. res := r; imported := impd.name$;
  46. IF impg # NIL THEN importing := impg.name$ END;
  47. END Error;
  48. PROCEDURE Append (VAR s: ARRAY OF CHAR; t: ARRAY OF CHAR);
  49. VAR len, i, j: INTEGER; ch: CHAR;
  50. BEGIN
  51. len := LEN(s);
  52. i := 0; WHILE s[i] # 0X DO INC(i) END;
  53. j := 0; REPEAT ch := t[j]; s[i] := ch; INC(j); INC(i) UNTIL (ch = 0X) OR (i = len);
  54. s[len - 1] := 0X
  55. END Append;
  56. PROCEDURE ThisObjFile (VAR name: ARRAY OF CHAR): Files.File;
  57. VAR f: Files.File; loc: Files.Locator; dir, fname: Files.Name;
  58. BEGIN
  59. Kernel.SplitName(name, dir, fname);
  60. Kernel.MakeFileName(fname, Kernel.objType);
  61. loc := Files.dir.This(dir); loc := loc.This(OFdir);
  62. f := Files.dir.Old(loc, fname, TRUE);
  63. IF (f = NIL) & (dir = "") THEN
  64. loc := Files.dir.This(SYSdir); loc := loc.This(OFdir);
  65. f := Files.dir.Old(loc, fname, TRUE)
  66. END;
  67. RETURN f
  68. END ThisObjFile;
  69. PROCEDURE RWord (VAR x: INTEGER);
  70. VAR b: BYTE; y: INTEGER;
  71. BEGIN
  72. inp.ReadByte(b); y := b MOD 256;
  73. inp.ReadByte(b); y := y + 100H * (b MOD 256);
  74. inp.ReadByte(b); y := y + 10000H * (b MOD 256);
  75. inp.ReadByte(b); x := y + 1000000H * b
  76. END RWord;
  77. PROCEDURE RNum (VAR x: INTEGER);
  78. VAR b: BYTE; s, y: INTEGER;
  79. BEGIN
  80. s := 0; y := 0; inp.ReadByte(b);
  81. WHILE b < 0 DO INC(y, ASH(b + 128, s)); INC(s, 7); inp.ReadByte(b) END;
  82. x := ASH((b + 64) MOD 128 - 64, s) + y
  83. END RNum;
  84. PROCEDURE RName (VAR name: ARRAY OF CHAR);
  85. VAR b: BYTE; i, n: INTEGER;
  86. BEGIN
  87. i := 0; n := LEN(name) - 1; inp.ReadByte(b);
  88. WHILE (i < n) & (b # 0) DO name[i] := CHR(b MOD 256); INC(i); inp.ReadByte(b) END;
  89. WHILE b # 0 DO inp.ReadByte(b) END;
  90. name[i] := 0X
  91. END RName;
  92. PROCEDURE Fixup (adr: INTEGER; mod: ModSpec);
  93. VAR link, offset, linkadr, t, n, x, low, hi: INTEGER;
  94. BEGIN
  95. RNum(link);
  96. WHILE link # 0 DO
  97. RNum(offset);
  98. WHILE link # 0 DO
  99. IF link > 0 THEN linkadr := mod.mad + mod.ms + link
  100. ELSE link := -link;
  101. IF link < mod.ms THEN linkadr := mod.mad + link
  102. ELSE linkadr := mod.dad + link - mod.ms
  103. END
  104. END;
  105. S.GET(linkadr, x); t := x DIV 1000000H;
  106. n := (x + 800000H) MOD 1000000H - 800000H;
  107. IF t = absolute THEN x := adr + offset
  108. ELSIF t = relative THEN x := adr + offset - linkadr - 4
  109. ELSIF t = copy THEN S.GET(adr + offset, x)
  110. ELSIF t = table THEN x := adr + n; n := link + 4
  111. ELSIF t = tableend THEN x := adr + n; n := 0
  112. ELSIF t = deref THEN S.GET(adr+2, x); INC(x, offset);
  113. ELSIF t = halfword THEN
  114. x := adr + offset;
  115. low := (x + 8000H) MOD 10000H - 8000H;
  116. hi := (x - low) DIV 10000H;
  117. S.GET(linkadr + 4, x);
  118. S.PUT(linkadr + 4, x DIV 10000H * 10000H + low MOD 10000H);
  119. x := x * 10000H + hi MOD 10000H
  120. ELSE Error(syntaxError, mod, NIL)
  121. END;
  122. S.PUT(linkadr, x); link := n
  123. END;
  124. RNum(link)
  125. END
  126. END Fixup;
  127. PROCEDURE ReadHeader (mod: ModSpec);
  128. VAR n, p: INTEGER; name: Name; imp, last: ModSpec;
  129. BEGIN
  130. mod.file := ThisObjFile(mod.name);
  131. IF (mod.file = NIL) & (mod.link # NIL) THEN (* try closing importing obj file *)
  132. mod.link.file.Close; mod.link.file := NIL;
  133. mod.file := ThisObjFile(mod.name)
  134. END;
  135. IF mod.file # NIL THEN
  136. inp := mod.file.NewReader(inp);
  137. IF inp # NIL THEN
  138. inp.SetPos(0); RWord(n); RWord(p);
  139. IF (n = OFtag) & (p = Kernel.processor) THEN
  140. RWord(mod.hs); RWord(mod.ms); RWord(mod.ds); RWord(mod.cs); RWord(mod.vs);
  141. RNum(n); RName(name);
  142. IF name = mod.name THEN
  143. mod.imp := NIL; last := NIL;
  144. WHILE n > 0 DO
  145. NEW(imp); RName(imp.name);
  146. IF last = NIL THEN mod.imp := imp ELSE last.next := imp END;
  147. last := imp; imp.next := NIL; DEC(n)
  148. END
  149. ELSE Error(fileNotFound, mod, NIL)
  150. END
  151. ELSE Error(syntaxError, mod, NIL)
  152. END
  153. ELSE Error(noMem, mod, NIL)
  154. END
  155. ELSE Error(fileNotFound, mod, NIL)
  156. END
  157. END ReadHeader;
  158. PROCEDURE ReadModule (mod: ModSpec);
  159. TYPE BlockPtr = POINTER TO ARRAY [1] 1000000H OF BYTE;
  160. VAR imptab, x, fp, ofp, opt, a: INTEGER;
  161. name: Name; dp, mp: BlockPtr; imp: ModSpec; obj: Kernel.Object; in, n: Kernel.Name;
  162. BEGIN
  163. IF mod.file = NIL THEN mod.file := ThisObjFile(mod.name) END;
  164. inp := mod.file.NewReader(inp);
  165. IF inp # NIL THEN
  166. inp.SetPos(mod.hs);
  167. Kernel.AllocModMem(mod.ds, mod.ms + mod.cs + mod.vs, mod.dad, mod.mad);
  168. IF (mod.dad # 0) & (mod.mad # 0) THEN
  169. dp := S.VAL(BlockPtr, mod.dad); mp := S.VAL(BlockPtr, mod.mad);
  170. inp.ReadBytes(mp^, 0, mod.ms);
  171. inp.ReadBytes(dp^, 0, mod.ds);
  172. inp.ReadBytes(mp^, mod.ms, mod.cs);
  173. mod.mod := S.VAL(Kernel.Module, mod.dad);
  174. Fixup(S.ADR(Kernel.NewRec), mod);
  175. Fixup(S.ADR(Kernel.NewArr), mod);
  176. Fixup(mod.mad, mod);
  177. Fixup(mod.dad, mod);
  178. Fixup(mod.mad + mod.ms, mod);
  179. Fixup(mod.mad + mod.ms + mod.cs, mod);
  180. imp := mod.imp; imptab := S.VAL(INTEGER, mod.mod.imports);
  181. WHILE (res = done) & (imp # NIL) DO
  182. RNum(x);
  183. WHILE (res <= done) & (x # 0) DO
  184. RName(name); RNum(fp); opt := 0;
  185. IF imp.mod # NIL THEN
  186. IF name = "" THEN obj := Kernel.ThisDesc(imp.mod, fp)
  187. ELSE n := SHORT(name$); obj := Kernel.ThisObject(imp.mod, n)
  188. END;
  189. IF (obj # NIL) & (obj.id MOD 16 = x) THEN
  190. ofp := obj.fprint;
  191. IF x = mTyp THEN
  192. RNum(opt);
  193. IF ODD(opt) THEN ofp := obj.offs END;
  194. IF (opt > 1) & (obj.id DIV 16 MOD 16 # mExported) THEN
  195. Error(objNotFound, imp, mod); object := name$
  196. END;
  197. Fixup(S.VAL(INTEGER, obj.struct), mod)
  198. ELSIF x = mVar THEN
  199. Fixup(imp.mod.varBase + obj.offs, mod)
  200. ELSIF x = mProc THEN
  201. Fixup(imp.mod.procBase + obj.offs, mod)
  202. END;
  203. IF ofp # fp THEN Error(illegalFPrint, imp, mod); object := name$ END
  204. ELSIF name # "" THEN
  205. Error(objNotFound, imp, mod); object := name$
  206. ELSE
  207. Error(descNotFound, imp, mod); (* proceed to find failing named object *)
  208. RNum(opt); Fixup(0, mod)
  209. END
  210. ELSE (* imp is dll *)
  211. IF x IN {mVar, mProc} THEN
  212. in := SHORT(imp.name$); n := SHORT(name$);
  213. a := Kernel.ThisDllObj(x, fp, in, n);
  214. IF a # 0 THEN Fixup(a, mod)
  215. ELSE Error(objNotFound, imp, mod); object := name$
  216. END
  217. ELSIF x = mTyp THEN
  218. RNum(opt); RNum(x);
  219. IF x # 0 THEN Error(objNotFound, imp, mod); object := name$ END
  220. END
  221. END;
  222. RNum(x)
  223. END;
  224. S.PUT(imptab, imp.mod); INC(imptab, 4); imp := imp.next
  225. END;
  226. IF res # done THEN
  227. Kernel.DeallocModMem(mod.ds, mod.ms + mod.cs + mod.vs, mod.dad, mod.mad); mod.mod := NIL
  228. END
  229. ELSE Error(noMem, mod, NIL)
  230. END
  231. ELSE Error(noMem, mod, NIL)
  232. END;
  233. mod.file.Close; mod.file := NIL
  234. END ReadModule;
  235. PROCEDURE LoadMod (mod: ModSpec);
  236. VAR i: ModSpec; ok: BOOLEAN; j: INTEGER; n: Kernel.Name;
  237. BEGIN
  238. importing := ""; imported := ""; object := ""; i := mod;
  239. WHILE (i.link # NIL) & (i.link.name # mod.name) DO i := i.link END;
  240. IF i.link = NIL THEN ReadHeader(mod)
  241. ELSE Error(cyclicImport, i, i.link)
  242. END;
  243. i := mod.imp;
  244. WHILE (res = done) & (i # NIL) DO (* get imported module *)
  245. IF i.name = "$$" THEN i.name := "Kernel" END;
  246. IF i.name[0] = "$" THEN (* dll *)
  247. j := 1;
  248. WHILE i.name[j] # 0X DO i.name[j - 1] := i.name[j]; INC(j) END;
  249. i.name[j - 1] := 0X; n := SHORT(i.name$);
  250. Kernel.LoadDll(n, ok);
  251. IF ~ok THEN Error(fileNotFound, i, NIL) END
  252. ELSE
  253. n := SHORT(i.name$);
  254. i.mod := Kernel.ThisLoadedMod(n); (* loaded module *)
  255. IF i.mod = NIL THEN i.link := mod; LoadMod(i) END (* new module *)
  256. END;
  257. i := i.next
  258. END;
  259. IF res = done THEN
  260. n := SHORT(mod.name$);
  261. mod.mod := Kernel.ThisLoadedMod(n); (* guaranties uniqueness *)
  262. IF mod.mod = NIL THEN
  263. ReadModule(mod);
  264. IF res = done THEN
  265. Kernel.RegisterMod(mod.mod);
  266. res := done
  267. END
  268. END
  269. END;
  270. IF res = descNotFound THEN res := objNotFound; object := "<TypeDesc>" END;
  271. IF object # "" THEN Append(imported, "."); Append(imported, object); object := "" END
  272. END LoadMod;
  273. PROCEDURE (h: Hook) ThisMod (IN name: ARRAY OF SHORTCHAR): Kernel.Module;
  274. VAR m: Kernel.Module; ms: ModSpec;
  275. BEGIN
  276. res := done;
  277. m := Kernel.ThisLoadedMod(name);
  278. IF m = NIL THEN
  279. NEW(ms); ms.link := NIL; ms.name := name$;
  280. LoadMod(ms);
  281. m := ms.mod;
  282. inp := NIL (* free last file *)
  283. END;
  284. h.res := res;
  285. h.importing := importing$;
  286. h.imported := imported$;
  287. h.object := object$;
  288. RETURN m
  289. END ThisMod;
  290. PROCEDURE Init;
  291. VAR h: Hook;
  292. BEGIN
  293. NEW(h); Kernel.SetLoaderHook(h)
  294. END Init;
  295. BEGIN
  296. Init;
  297. m := Kernel.ThisMod("Init");
  298. IF res # 0 THEN
  299. CASE res OF
  300. | fileNotFound: Append(imported, ": code file not found")
  301. | syntaxError: Append(imported, ": corrupted code file")
  302. | objNotFound: Append(imported, " not found")
  303. | illegalFPrint: Append(imported, ": wrong fingerprint")
  304. | cyclicImport: Append(imported, ": cyclic import")
  305. | noMem: Append(imported, ": not enough memory")
  306. ELSE Append(imported, ": loader error")
  307. END;
  308. IF res IN {objNotFound, illegalFPrint, cyclicImport} THEN
  309. Append(imported, " (imported from "); Append(imported, importing); Append(imported, ")")
  310. END;
  311. Kernel.FatalError(res, imported)
  312. END
  313. END StdLoader.