Files
oberon-07-compiler/source/Compiler.ob07
T

213 lines
5.5 KiB
Plaintext

(*
BSD 2-Clause License
Copyright (c) 2018, Anton Krotov
All rights reserved.
*)
MODULE Compiler;
IMPORT STATEMENTS, TARGETS, PARS, UTILS, PATHS, CONSOLE, ERRORS, STRINGS, VER, WRITER;
CONST
EXT = ".ob07";
PROCEDURE Target (s: ARRAY OF CHAR): INTEGER;
VAR
res: INTEGER;
BEGIN
IF s = "con" THEN
res := TARGETS.CON
ELSIF s = "gui" THEN
res := TARGETS.GUI
ELSIF s = "dll" THEN
res := TARGETS.DLL
ELSIF s = "kos" THEN
res := TARGETS.KOS
ELSIF s = "obj" THEN
res := TARGETS.OBJ
ELSE
res := 0
END
RETURN res
END Target;
PROCEDURE keys (VAR StackSize, BaseAddress, Version: INTEGER; VAR pic, reloc: BOOLEAN);
VAR
param: PARS.PATH;
i: INTEGER;
end: BOOLEAN;
value: INTEGER;
minor,
major: INTEGER;
BEGIN
end := FALSE;
i := 4;
REPEAT
UTILS.GetArg(i, param);
IF param = "-stk" THEN
INC(i);
UTILS.GetArg(i, param);
IF STRINGS.StrToInt(param, value) & (1 <= value) & (value <= 32) THEN
StackSize := value
END;
IF param[0] = "-" THEN
DEC(i)
END;
ELSIF param = "-base" THEN
INC(i);
UTILS.GetArg(i, param);
IF STRINGS.StrToInt(param, value) THEN
BaseAddress := ((value DIV 64) * 64) * 1024
END;
IF param[0] = "-" THEN
DEC(i)
END;
ELSIF param = "-ver" THEN
INC(i);
UTILS.GetArg(i, param);
IF STRINGS.StrToVer(param, major, minor) THEN
Version := major * 65536 + minor
END;
IF param[0] = "-" THEN
DEC(i)
END;
ELSIF param = "-pic" THEN
pic := TRUE
ELSIF param = "-reloc" THEN
reloc := TRUE
ELSIF param = "" THEN
end := TRUE
ELSE
ERRORS.error3("bad parameter: ", param, "")
END;
INC(i)
UNTIL end
END keys;
PROCEDURE main;
VAR
path: PARS.PATH;
inname: PARS.PATH;
ext: PARS.PATH;
app_path: PARS.PATH;
lib_path: PARS.PATH;
modname: PARS.PATH;
outname: PARS.PATH;
param: PARS.PATH;
temp: PARS.PATH;
target: INTEGER;
time: INTEGER;
StackSize,
Version,
BaseAdr: INTEGER;
pic, reloc: BOOLEAN;
BEGIN
StackSize := 1;
Version := 65536;
pic := FALSE;
reloc := FALSE;
PATHS.GetCurrentDirectory(app_path);
lib_path := app_path;
UTILS.GetArg(1, inname);
IF inname = "" THEN
CONSOLE.String("Akron Oberon-07/16 Compiler v"); CONSOLE.Int(VER.Major); CONSOLE.String("."); CONSOLE.Int2(VER.Minor); CONSOLE.Ln;
CONSOLE.String("Usage: Compiler <main module> <output> <target> [optional settings]"); CONSOLE.Ln; CONSOLE.Ln;
CONSOLE.String("target = 'con' | 'gui' | 'dll' | 'kos' | 'obj'"); CONSOLE.Ln; CONSOLE.Ln;
CONSOLE.String("optional settings:"); CONSOLE.Ln;
CONSOLE.String(" -stk <size> set size of stack in megabytes"); CONSOLE.Ln;
CONSOLE.String(" -base <address> set base address of image in kilobytes"); CONSOLE.Ln;
CONSOLE.String(" -pic generate position-independent code"); CONSOLE.Ln;
CONSOLE.String(" -reloc make relocation table"); CONSOLE.Ln;
CONSOLE.String(" -ver <major.minor> set version of program ('obj' only)"); CONSOLE.Ln;
UTILS.Exit(0)
END;
PATHS.split(inname, path, modname, ext);
IF ext # EXT THEN
ERRORS.error3("inputfile name extension must be '", EXT, "'")
END;
IF PATHS.isRelative(path) THEN
PATHS.RelPath(app_path, path, temp);
path := temp
END;
UTILS.GetArg(2, outname);
IF outname = "" THEN
ERRORS.error1("not enough parameters")
END;
IF PATHS.isRelative(outname) THEN
PATHS.RelPath(app_path, outname, temp);
outname := temp
END;
UTILS.GetArg(3, param);
IF param = "" THEN
ERRORS.error1("not enough parameters")
END;
target := Target(param);
IF target = 0 THEN
ERRORS.error1("bad parameter <target>")
END;
PARS.program.dll := target IN {TARGETS.DLL, TARGETS.OBJ};
PARS.program.obj := target = TARGETS.OBJ;
STRINGS.append(lib_path, "lib");
STRINGS.append(lib_path, UTILS.slash);
IF target IN {TARGETS.CON, TARGETS.GUI, TARGETS.DLL} THEN
IF target = TARGETS.DLL THEN
BaseAdr := 10000000H
ELSE
BaseAdr := 400000H
END;
STRINGS.append(lib_path, "Windows32");
STRINGS.append(lib_path, UTILS.slash)
ELSIF target IN {TARGETS.KOS, TARGETS.OBJ} THEN
STRINGS.append(lib_path, "KolibriOS");
STRINGS.append(lib_path, UTILS.slash)
END;
keys(StackSize, BaseAdr, Version, pic, reloc);
STATEMENTS.do(path, lib_path, modname, outname, EXT, target, Version, StackSize, BaseAdr, pic, reloc);
time := UTILS.GetTickCount() - UTILS.time;
CONSOLE.Int(time DIV 100); CONSOLE.String("."); CONSOLE.Int2(time MOD 100); CONSOLE.String(" sec, ");
CONSOLE.Int(WRITER.counter); CONSOLE.String(" bytes"); CONSOLE.Ln;
UTILS.Exit(0)
END main;
BEGIN
main
END Compiler.