MODULE StdLoader; (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 Std/Mod/Loader.odc *) (* DO NOT EDIT *) IMPORT S := SYSTEM, Kernel, Files; CONST done = Kernel.done; fileNotFound = Kernel.fileNotFound; syntaxError = Kernel.syntaxError; objNotFound = Kernel.objNotFound; illegalFPrint = Kernel.illegalFPrint; cyclicImport = Kernel.cyclicImport; noMem = Kernel.noMem; commNotFound = Kernel.commNotFound; commSyntaxError = Kernel.commSyntaxError; descNotFound = -1; OFdir = "Code"; SYSdir = "System"; initMod = "Init"; OFtag = 6F4F4346H; (* meta interface consts *) mConst = 1; mTyp = 2; mVar = 3; mProc = 4; mField = 5; mBool = 1; mChar = 2; mLChar = 3; mSInt = 4; mInt = 5; mLInt = 6; mReal = 7; mLReal = 8; mSet = 9; mString = 10; mLString = 11; mRecord = 1; mArray = 2; mPointer = 3; mProctyp = 4; mInternal = 1; mReadonly = 2; mPrivate = 3; mExported = 4; (* fixup types *) absolute = 100; relative = 101; copy = 102; table = 103; tableend = 104; deref = 105; halfword = 106; TYPE Name = ARRAY 256 OF CHAR; ModSpec = POINTER TO RECORD next, link, imp: ModSpec; name: Name; file: Files.File; mod: Kernel.Module; hs, ms, ds, cs, vs, mad, dad: INTEGER END; Hook = POINTER TO RECORD (Kernel.LoaderHook) END; VAR res-: INTEGER; importing-, imported-, object-: Name; inp: Files.Reader; m: Kernel.Module; PROCEDURE Error (r: INTEGER; impd, impg: ModSpec); BEGIN res := r; imported := impd.name$; IF impg # NIL THEN importing := impg.name$ END; END Error; PROCEDURE Append (VAR s: ARRAY OF CHAR; t: ARRAY OF CHAR); VAR len, i, j: INTEGER; ch: CHAR; BEGIN len := LEN(s); i := 0; WHILE s[i] # 0X DO INC(i) END; j := 0; REPEAT ch := t[j]; s[i] := ch; INC(j); INC(i) UNTIL (ch = 0X) OR (i = len); s[len - 1] := 0X END Append; PROCEDURE ThisObjFile (VAR name: ARRAY OF CHAR): Files.File; VAR f: Files.File; loc: Files.Locator; dir, fname: Files.Name; BEGIN Kernel.SplitName(name, dir, fname); Kernel.MakeFileName(fname, Kernel.objType); loc := Files.dir.This(dir); loc := loc.This(OFdir); f := Files.dir.Old(loc, fname, TRUE); IF (f = NIL) & (dir = "") THEN loc := Files.dir.This(SYSdir); loc := loc.This(OFdir); f := Files.dir.Old(loc, fname, TRUE) END; RETURN f END ThisObjFile; PROCEDURE RWord (VAR x: INTEGER); VAR b: BYTE; y: INTEGER; BEGIN inp.ReadByte(b); y := b MOD 256; inp.ReadByte(b); y := y + 100H * (b MOD 256); inp.ReadByte(b); y := y + 10000H * (b MOD 256); inp.ReadByte(b); x := y + 1000000H * b END RWord; PROCEDURE RNum (VAR x: INTEGER); VAR b: BYTE; s, y: INTEGER; BEGIN s := 0; y := 0; inp.ReadByte(b); WHILE b < 0 DO INC(y, ASH(b + 128, s)); INC(s, 7); inp.ReadByte(b) END; x := ASH((b + 64) MOD 128 - 64, s) + y END RNum; PROCEDURE RName (VAR name: ARRAY OF CHAR); VAR b: BYTE; i, n: INTEGER; BEGIN i := 0; n := LEN(name) - 1; inp.ReadByte(b); WHILE (i < n) & (b # 0) DO name[i] := CHR(b MOD 256); INC(i); inp.ReadByte(b) END; WHILE b # 0 DO inp.ReadByte(b) END; name[i] := 0X END RName; PROCEDURE Fixup (adr: INTEGER; mod: ModSpec); VAR link, offset, linkadr, t, n, x, low, hi: INTEGER; BEGIN RNum(link); WHILE link # 0 DO RNum(offset); WHILE link # 0 DO IF link > 0 THEN linkadr := mod.mad + mod.ms + link ELSE link := -link; IF link < mod.ms THEN linkadr := mod.mad + link ELSE linkadr := mod.dad + link - mod.ms END END; S.GET(linkadr, x); t := x DIV 1000000H; n := (x + 800000H) MOD 1000000H - 800000H; IF t = absolute THEN x := adr + offset ELSIF t = relative THEN x := adr + offset - linkadr - 4 ELSIF t = copy THEN S.GET(adr + offset, x) ELSIF t = table THEN x := adr + n; n := link + 4 ELSIF t = tableend THEN x := adr + n; n := 0 ELSIF t = deref THEN S.GET(adr+2, x); INC(x, offset); ELSIF t = halfword THEN x := adr + offset; low := (x + 8000H) MOD 10000H - 8000H; hi := (x - low) DIV 10000H; S.GET(linkadr + 4, x); S.PUT(linkadr + 4, x DIV 10000H * 10000H + low MOD 10000H); x := x * 10000H + hi MOD 10000H ELSE Error(syntaxError, mod, NIL) END; S.PUT(linkadr, x); link := n END; RNum(link) END END Fixup; PROCEDURE ReadHeader (mod: ModSpec); VAR n, p: INTEGER; name: Name; imp, last: ModSpec; BEGIN mod.file := ThisObjFile(mod.name); IF (mod.file = NIL) & (mod.link # NIL) THEN (* try closing importing obj file *) mod.link.file.Close; mod.link.file := NIL; mod.file := ThisObjFile(mod.name) END; IF mod.file # NIL THEN inp := mod.file.NewReader(inp); IF inp # NIL THEN inp.SetPos(0); RWord(n); RWord(p); IF (n = OFtag) & (p = Kernel.processor) THEN RWord(mod.hs); RWord(mod.ms); RWord(mod.ds); RWord(mod.cs); RWord(mod.vs); RNum(n); RName(name); IF name = mod.name THEN mod.imp := NIL; last := NIL; WHILE n > 0 DO NEW(imp); RName(imp.name); IF last = NIL THEN mod.imp := imp ELSE last.next := imp END; last := imp; imp.next := NIL; DEC(n) END ELSE Error(fileNotFound, mod, NIL) END ELSE Error(syntaxError, mod, NIL) END ELSE Error(noMem, mod, NIL) END ELSE Error(fileNotFound, mod, NIL) END END ReadHeader; PROCEDURE ReadModule (mod: ModSpec); TYPE BlockPtr = POINTER TO ARRAY [1] 1000000H OF BYTE; VAR imptab, x, fp, ofp, opt, a: INTEGER; name: Name; dp, mp: BlockPtr; imp: ModSpec; obj: Kernel.Object; in, n: Kernel.Name; BEGIN IF mod.file = NIL THEN mod.file := ThisObjFile(mod.name) END; inp := mod.file.NewReader(inp); IF inp # NIL THEN inp.SetPos(mod.hs); Kernel.AllocModMem(mod.ds, mod.ms + mod.cs + mod.vs, mod.dad, mod.mad); IF (mod.dad # 0) & (mod.mad # 0) THEN dp := S.VAL(BlockPtr, mod.dad); mp := S.VAL(BlockPtr, mod.mad); inp.ReadBytes(mp^, 0, mod.ms); inp.ReadBytes(dp^, 0, mod.ds); inp.ReadBytes(mp^, mod.ms, mod.cs); mod.mod := S.VAL(Kernel.Module, mod.dad); Fixup(S.ADR(Kernel.NewRec), mod); Fixup(S.ADR(Kernel.NewArr), mod); Fixup(mod.mad, mod); Fixup(mod.dad, mod); Fixup(mod.mad + mod.ms, mod); Fixup(mod.mad + mod.ms + mod.cs, mod); imp := mod.imp; imptab := S.VAL(INTEGER, mod.mod.imports); WHILE (res = done) & (imp # NIL) DO RNum(x); WHILE (res <= done) & (x # 0) DO RName(name); RNum(fp); opt := 0; IF imp.mod # NIL THEN IF name = "" THEN obj := Kernel.ThisDesc(imp.mod, fp) ELSE n := SHORT(name$); obj := Kernel.ThisObject(imp.mod, n) END; IF (obj # NIL) & (obj.id MOD 16 = x) THEN ofp := obj.fprint; IF x = mTyp THEN RNum(opt); IF ODD(opt) THEN ofp := obj.offs END; IF (opt > 1) & (obj.id DIV 16 MOD 16 # mExported) THEN Error(objNotFound, imp, mod); object := name$ END; Fixup(S.VAL(INTEGER, obj.struct), mod) ELSIF x = mVar THEN Fixup(imp.mod.varBase + obj.offs, mod) ELSIF x = mProc THEN Fixup(imp.mod.procBase + obj.offs, mod) END; IF ofp # fp THEN Error(illegalFPrint, imp, mod); object := name$ END ELSIF name # "" THEN Error(objNotFound, imp, mod); object := name$ ELSE Error(descNotFound, imp, mod); (* proceed to find failing named object *) RNum(opt); Fixup(0, mod) END ELSE (* imp is dll *) IF x IN {mVar, mProc} THEN in := SHORT(imp.name$); n := SHORT(name$); a := Kernel.ThisDllObj(x, fp, in, n); IF a # 0 THEN Fixup(a, mod) ELSE Error(objNotFound, imp, mod); object := name$ END ELSIF x = mTyp THEN RNum(opt); RNum(x); IF x # 0 THEN Error(objNotFound, imp, mod); object := name$ END END END; RNum(x) END; S.PUT(imptab, imp.mod); INC(imptab, 4); imp := imp.next END; IF res # done THEN Kernel.DeallocModMem(mod.ds, mod.ms + mod.cs + mod.vs, mod.dad, mod.mad); mod.mod := NIL END ELSE Error(noMem, mod, NIL) END ELSE Error(noMem, mod, NIL) END; mod.file.Close; mod.file := NIL END ReadModule; PROCEDURE LoadMod (mod: ModSpec); VAR i: ModSpec; ok: BOOLEAN; j: INTEGER; n: Kernel.Name; BEGIN importing := ""; imported := ""; object := ""; i := mod; WHILE (i.link # NIL) & (i.link.name # mod.name) DO i := i.link END; IF i.link = NIL THEN ReadHeader(mod) ELSE Error(cyclicImport, i, i.link) END; i := mod.imp; WHILE (res = done) & (i # NIL) DO (* get imported module *) IF i.name = "$$" THEN i.name := "Kernel" END; IF i.name[0] = "$" THEN (* dll *) j := 1; WHILE i.name[j] # 0X DO i.name[j - 1] := i.name[j]; INC(j) END; i.name[j - 1] := 0X; n := SHORT(i.name$); Kernel.LoadDll(n, ok); IF ~ok THEN Error(fileNotFound, i, NIL) END ELSE n := SHORT(i.name$); i.mod := Kernel.ThisLoadedMod(n); (* loaded module *) IF i.mod = NIL THEN i.link := mod; LoadMod(i) END (* new module *) END; i := i.next END; IF res = done THEN n := SHORT(mod.name$); mod.mod := Kernel.ThisLoadedMod(n); (* guaranties uniqueness *) IF mod.mod = NIL THEN ReadModule(mod); IF res = done THEN Kernel.RegisterMod(mod.mod); res := done END END END; IF res = descNotFound THEN res := objNotFound; object := "" END; IF object # "" THEN Append(imported, "."); Append(imported, object); object := "" END END LoadMod; PROCEDURE (h: Hook) ThisMod (IN name: ARRAY OF SHORTCHAR): Kernel.Module; VAR m: Kernel.Module; ms: ModSpec; BEGIN res := done; m := Kernel.ThisLoadedMod(name); IF m = NIL THEN NEW(ms); ms.link := NIL; ms.name := name$; LoadMod(ms); m := ms.mod; inp := NIL (* free last file *) END; h.res := res; h.importing := importing$; h.imported := imported$; h.object := object$; RETURN m END ThisMod; PROCEDURE Init; VAR h: Hook; BEGIN NEW(h); Kernel.SetLoaderHook(h) END Init; BEGIN Init; m := Kernel.ThisMod("Init"); IF res # 0 THEN CASE res OF | fileNotFound: Append(imported, ": code file not found") | syntaxError: Append(imported, ": corrupted code file") | objNotFound: Append(imported, " not found") | illegalFPrint: Append(imported, ": wrong fingerprint") | cyclicImport: Append(imported, ": cyclic import") | noMem: Append(imported, ": not enough memory") ELSE Append(imported, ": loader error") END; IF res IN {objNotFound, illegalFPrint, cyclicImport} THEN Append(imported, " (imported from "); Append(imported, importing); Append(imported, ")") END; Kernel.FatalError(res, imported) END END StdLoader.