MODULE DswLinker486Main; IMPORT Kernel, HostFiles, Files, Console, Strings, LB := Dev2LnkBase, Load := Dev2LnkLoad, WrPe := Dev2LnkWritePe, WrElf := Dev2LnkWriteElf, WrElfS := Dev2LnkWriteElfStatic; CONST tgtElfStatic = 0; tgtElfExe = 1; tgtElfDll = 2; tgtPeExe = 3; tgtPeDll = 4; version = "0.3"; TYPE Elem = POINTER TO RECORD name: ARRAY 256 OF CHAR; next: Elem END; VAR u: Elem; inobj: LB.Directory; outdir, outname: Files.Name; os, interp, main, kernel: ARRAY 256 OF CHAR; static, dll, sinit: BOOLEAN; PROCEDURE GetPath (IN path: ARRAY OF CHAR; OUT dir, name: Files.Name); VAR i, j, len: INTEGER; BEGIN len := LEN(path$); i := len - 1; WHILE (i >= 0) & (path[i] # '/') DO DEC(i) END; IF i >= 0 THEN FOR i := 0 TO i - 1 DO dir[i] := path[i] END; dir[i] := 0X ELSE dir := "" END; j := i + 1; i := 0; WHILE path[j] # 0X DO name[i] := path[j]; INC(i); INC(j) END; name[i] := 0X END GetPath; PROCEDURE InitOptions; VAR i: INTEGER; h, t: Elem; obj: LB.Directory; p: ARRAY 256 OF CHAR; PROCEDURE Check; BEGIN IF i >= Kernel.argc THEN Console.WriteStr("required more parameters for "); Console.WriteStr(p); Console.WriteLn; Kernel.Quit(1) END END Check; BEGIN i := 1; WHILE i < Kernel.argc DO IF Kernel.argv[i, 0] = "-" THEN p := Kernel.argv[i]$; INC(i); IF p = "-os" THEN Check; Strings.ToLower(Kernel.argv[i]$, os); INC(i) ELSIF p = "-interp" THEN Check; interp := Kernel.argv[i]$; INC(i) ELSIF p = "-o" THEN Check; GetPath(Kernel.argv[i]$, outdir, outname); INC(i) ELSIF p = "-static" THEN static := TRUE ELSIF p = "-dll" THEN dll := TRUE ELSIF p = "-sinit" THEN sinit := TRUE ELSIF (p = "-m") OR (p = "-main") THEN Check; main := Kernel.argv[i]$; INC(i) ELSIF (p = "-k") OR (p = "-kernel") THEN Check; kernel := Kernel.argv[i]$; INC(i) ELSIF p = "-codedir" THEN Check; obj := inobj; NEW(inobj); inobj.path := Kernel.argv[i]$; inobj.legacy := FALSE; inobj.next := obj; INC(i) ELSIF p = "-legacycodedir" THEN Check; obj := inobj; NEW(inobj); inobj.path := Kernel.argv[i]$; inobj.legacy := TRUE; inobj.next := obj; INC(i) ELSIF p = "-trap" THEN LB.trap := TRUE; Kernel.intTrap := TRUE ELSIF p = "-version" THEN Console.WriteStr(version); Console.WriteLn; Kernel.Quit(0) ELSE Console.WriteStr("unknown option "); Console.WriteStr(p); Console.WriteLn; Kernel.Quit(1) END ELSE IF h = NIL THEN NEW(h); t := h ELSE NEW(t.next); t := t.next END; t.name := Kernel.argv[i]$; INC(i) END END; u := h END InitOptions; PROCEDURE CheckOptions; BEGIN IF (os = "linux") OR (os = "freebsd") OR (os = "openbsd") THEN IF dll THEN LB.Init(tgtElfDll) ELSIF static THEN LB.Init(tgtElfStatic) ELSE LB.Init(tgtElfExe) END; LB.dynaInit := ~sinit; IF os = "linux" THEN LB.opt.OSABI := WrElf.ELFOSABI_NONE; IF interp = "" THEN LB.opt.elfInterpreter := WrElf.linuxInterpreter ELSE LB.opt.elfInterpreter := SHORT(interp$) END ELSIF os = "freebsd" THEN LB.opt.OSABI := WrElf.ELFOSABI_FREEBSD; IF interp = "" THEN LB.opt.elfInterpreter := WrElf.freeBSDInterpreter ELSE LB.opt.elfInterpreter := SHORT(interp$) END ELSIF os = "openbsd" THEN LB.opt.OSABI := WrElf.ELFOSABI_NONE; IF interp = "" THEN LB.opt.elfInterpreter := WrElf.openBSDInterpreter ELSE LB.opt.elfInterpreter := SHORT(interp$) END ELSE HALT(100) END; IF outname = "" THEN Files.dir.GetFileName("a", "out", outname) END ELSIF os = "win32" THEN IF dll THEN LB.Init(tgtPeDll) ELSE LB.Init(tgtPeExe) END; LB.dynaInit := ~sinit; IF outname = "" THEN Files.dir.GetFileName("a", "exe", outname) END; IF static THEN Console.WriteStr("-static not supported for win32"); Console.WriteLn; Kernel.Quit(1) END; IF interp # "" THEN Console.WriteStr("-interp not supported for win32"); Console.WriteLn; Kernel.Quit(1) END ELSIF os = "" THEN Console.WriteStr("os not specified"); Console.WriteLn; Kernel.Quit(1) ELSE Console.WriteStr("unknown os "); Console.WriteStr(os); Console.WriteLn; Kernel.Quit(1) END; IF main = "" THEN Console.WriteStr("main module not specified"); Console.WriteLn; Kernel.Quit(1) END; IF outname = "" THEN Console.WriteStr("required path to output file"); Console.WriteLn; Kernel.Quit(1) END; IF inobj = NIL THEN Console.WriteStr("required path to input objects"); Console.WriteLn; Kernel.Quit(1) END; LB.objList := inobj; LB.outputPath := outdir; LB.outputName := SHORT(outname$); LB.KernelName := SHORT(kernel$); LB.mainName := SHORT(main$); IF u = NIL THEN Console.WriteStr("no input specified"); Console.WriteLn; Kernel.Quit(1) END; END CheckOptions; PROCEDURE LinkAll; VAR m: Elem; codeBase, dataBase, varsBase: INTEGER; BEGIN m := u; WHILE m # NIL DO CASE LB.target OF | tgtElfStatic, tgtElfExe, tgtPeExe: Load.AddModule(m.name) | tgtElfDll, tgtPeDll: Load.ExportModule(m.name) END; m := m.next END; CASE LB.target OF | tgtElfStatic, tgtElfDll, tgtPeDll: (* ok *) | tgtElfExe: IF os = "freebsd" THEN Load.ExportVariable(LB.KernelName$, "__progname"); Load.ExportVariable(LB.KernelName$, "environ") END; Load.ExportAll | tgtPeExe: Load.ExportAll END; codeBase := 0; dataBase := 0; varsBase := 0; LB.BeginLinking; IF LB.outPe THEN WrPe.Init; WrPe.GetBases(codeBase, dataBase, varsBase); LB.SetAddr(codeBase, dataBase, varsBase); LB.DoFixups; WrPe.WriteOut ELSIF LB.outElf & LB.opt.elfStatic THEN WrElfS.Init; WrElfS.GetBases(codeBase, dataBase, varsBase); LB.SetAddr(codeBase, dataBase, varsBase); LB.DoFixups; WrElfS.WriteOut ELSIF LB.outElf THEN WrElf.Init; WrElf.GetBases(codeBase, dataBase, varsBase); LB.SetAddr(codeBase, dataBase, varsBase); LB.DoFixups; WrElf.WriteOut END; IF LB.error THEN Console.WriteStr("link failed"); Console.WriteLn; Kernel.Quit(1) END END LinkAll; PROCEDURE Init; BEGIN IF Kernel.trapCount # 0 THEN Kernel.Quit(1) END; HostFiles.SetRootDir("."); InitOptions; CheckOptions; LinkAll; Kernel.Quit(0) END Init; BEGIN Kernel.intTrap := FALSE; Kernel.Start(Init) END DswLinker486Main.