123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- 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 := "<TypeDesc>" 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.
|