(* BSD 2-Clause License Copyright (c) 2018-2023, Anton Krotov All rights reserved. *) MODULE Compiler; IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS, SCAN, TEXTDRV; CONST DEF_WINDOWS = "WINDOWS"; DEF_LINUX = "LINUX"; DEF_KOLIBRIOS = "KOLIBRIOS"; DEF_CPU_X86 = "CPU_X86"; DEF_CPU_X8664 = "CPU_X8664"; PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH); VAR param: PARS.PATH; i, j: INTEGER; _end: BOOLEAN; value: INTEGER; minor, major: INTEGER; checking: SET; PROCEDURE getVal (VAR i: INTEGER; VAR value: INTEGER); VAR param: PARS.PATH; val: INTEGER; BEGIN INC(i); UTILS.GetArg(i, param); IF STRINGS.StrToInt(param, val) THEN value := val END; IF param[0] = "-" THEN DEC(i) END END getVal; BEGIN options.lower := TRUE; out := ""; checking := options.checking; _end := FALSE; i := 3; 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 options.stack := value END; IF param[0] = "-" THEN DEC(i) END ELSIF param = "-out" THEN INC(i); UTILS.GetArg(i, param); IF param[0] = "-" THEN DEC(i) ELSE out := param END ELSIF param = "-tab" THEN getVal(i, options.tab) ELSIF param = "-ram" THEN getVal(i, options.ram) ELSIF param = "-rom" THEN getVal(i, options.rom) ELSIF param = "-nochk" THEN INC(i); UTILS.GetArg(i, param); IF param[0] = "-" THEN DEC(i) ELSE j := 0; WHILE param[j] # 0X DO IF param[j] = "p" THEN EXCL(checking, ST.chkPTR) ELSIF param[j] = "t" THEN EXCL(checking, ST.chkGUARD) ELSIF param[j] = "i" THEN EXCL(checking, ST.chkIDX) ELSIF param[j] = "b" THEN EXCL(checking, ST.chkBYTE) ELSIF param[j] = "c" THEN EXCL(checking, ST.chkCHR) ELSIF param[j] = "w" THEN EXCL(checking, ST.chkWCHR) ELSIF param[j] = "r" THEN EXCL(checking, ST.chkCHR); EXCL(checking, ST.chkWCHR); EXCL(checking, ST.chkBYTE) ELSIF param[j] = "s" THEN EXCL(checking, ST.chkSTK) ELSIF param[j] = "a" THEN checking := {} END; INC(j) END; END ELSIF param = "-ver" THEN INC(i); UTILS.GetArg(i, param); IF STRINGS.StrToVer(param, major, minor) THEN options.version := major * 65536 + minor END; IF param[0] = "-" THEN DEC(i) END ELSIF param = "-lower" THEN options.lower := TRUE ELSIF param = "-upper" THEN options.lower := FALSE ELSIF param = "-pic" THEN options.pic := TRUE ELSIF param = "-uses" THEN options.uses := TRUE ELSIF param = "-def" THEN INC(i); UTILS.GetArg(i, param); SCAN.NewDef(param) ELSIF param = "" THEN _end := TRUE ELSE ERRORS.BadParam(param) END; INC(i) UNTIL _end; options.checking := checking END keys; PROCEDURE OutTargetItem (target: INTEGER; text: ARRAY OF CHAR); VAR width: INTEGER; BEGIN width := 15; width := width - LENGTH(TARGETS.Targets[target].ComLinePar) - 4; C.String(" '"); C.String(TARGETS.Targets[target].ComLinePar); C.String("'"); WHILE width > 0 DO C.String(20X); DEC(width) END; C.StringLn(text) END OutTargetItem; 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; options: PROG.OPTIONS; BEGIN options.stack := 2; options.tab := TEXTDRV.defTabSize; options.version := 65536; options.pic := FALSE; options.lower := FALSE; options.uses := FALSE; options.checking := ST.chkALL; PATHS.GetCurrentDirectory(app_path); UTILS.GetArg(0, temp); PATHS.split(temp, path, modname, ext); IF PATHS.isRelative(path) THEN PATHS.RelPath(app_path, path, temp); path := temp END; lib_path := path; UTILS.GetArg(1, inname); STRINGS.replace(inname, "\", UTILS.slash); STRINGS.replace(inname, "/", UTILS.slash); C.Ln; C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor); C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) " + UTILS.Date); C.StringLn("Copyright (c) 2018-2023, Anton Krotov"); IF inname = "" THEN C.Ln; C.StringLn("Usage: Compiler
[optional settings]"); C.Ln; C.StringLn("target ="); IF UTILS.bit_depth = 64 THEN OutTargetItem(TARGETS.Win64C, "Windows64 Console"); OutTargetItem(TARGETS.Win64GUI, "Windows64 GUI"); OutTargetItem(TARGETS.Win64DLL, "Windows64 DLL"); OutTargetItem(TARGETS.Linux64, "Linux64 Exec"); OutTargetItem(TARGETS.Linux64SO, "Linux64 SO") END; OutTargetItem(TARGETS.Win32C, "Windows32 Console"); OutTargetItem(TARGETS.Win32GUI, "Windows32 GUI"); OutTargetItem(TARGETS.Win32DLL, "Windows32 DLL"); OutTargetItem(TARGETS.Linux32, "Linux32 Exec"); OutTargetItem(TARGETS.Linux32SO, "Linux32 SO"); OutTargetItem(TARGETS.KolibriOS, "KolibriOS Exec"); OutTargetItem(TARGETS.KolibriOSDLL, "KolibriOS DLL"); OutTargetItem(TARGETS.MSP430, "MSP430x{1,2}xx microcontrollers"); OutTargetItem(TARGETS.STM32CM3, "STM32 Cortex-M3 microcontrollers"); C.Ln; C.StringLn("optional settings:"); C.Ln; C.StringLn(" -out output"); C.Ln; C.StringLn(" -stk set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln; C.StringLn(" -nochk <'ptibcwra'> disable runtime checking (pointers, types, indexes,"); C.StringLn(" BYTE, CHR, WCHR)"); C.Ln; C.StringLn(" -lower allow lower case for keywords (default)"); C.Ln; C.StringLn(" -upper only upper case for keywords"); C.Ln; C.StringLn(" -def define conditional compilation symbol"); C.Ln; C.StringLn(" -ver set version of program (KolibriOS DLL)"); C.Ln; C.StringLn(" -ram set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; C.StringLn(" -rom set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; C.StringLn(" -tab set width for tabs"); C.Ln; C.StringLn(" -uses list imported modules"); C.Ln; UTILS.Exit(0) END; C.Dashes; PATHS.split(inname, path, modname, ext); IF ext # UTILS.FILE_EXT THEN ERRORS.Error(207) END; IF PATHS.isRelative(path) THEN PATHS.RelPath(app_path, path, temp); path := temp END; UTILS.GetArg(2, param); IF param = "" THEN ERRORS.Error(205) END; SCAN.NewDef(param); IF TARGETS.Select(param) THEN target := TARGETS.target ELSE ERRORS.Error(206) END; IF TARGETS.CPU = TARGETS.cpuMSP430 THEN options.ram := MSP430.minRAM; options.rom := MSP430.minROM END; IF (TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE) THEN options.ram := THUMB.minRAM; options.rom := THUMB.minROM END; IF UTILS.bit_depth < TARGETS.BitDepth THEN ERRORS.Error(206) END; STRINGS.append(lib_path, "lib"); STRINGS.append(lib_path, UTILS.slash); STRINGS.append(lib_path, TARGETS.LibDir); STRINGS.append(lib_path, UTILS.slash); keys(options, outname); TEXTDRV.setTabSize(options.tab); IF outname = "" THEN outname := path; STRINGS.append(outname, modname); STRINGS.append(outname, TARGETS.FileExt) ELSE IF PATHS.isRelative(outname) THEN PATHS.RelPath(app_path, outname, temp); outname := temp END END; PARS.init(options); CASE TARGETS.OS OF |TARGETS.osNONE: |TARGETS.osWIN32, TARGETS.osWIN64: SCAN.NewDef(DEF_WINDOWS) |TARGETS.osLINUX32, TARGETS.osLINUX64: SCAN.NewDef(DEF_LINUX) |TARGETS.osKOS: SCAN.NewDef(DEF_KOLIBRIOS) END; CASE TARGETS.CPU OF |TARGETS.cpuX86: SCAN.NewDef(DEF_CPU_X86) |TARGETS.cpuAMD64: SCAN.NewDef(DEF_CPU_X8664) |TARGETS.cpuMSP430: |TARGETS.cpuTHUMB: |TARGETS.cpuRVM32I: |TARGETS.cpuRVM64I: END; ST.compile(path, lib_path, modname, outname, target, options); time := UTILS.GetTickCount() - UTILS.time; C.Dashes; C.Int(PARS.lines); C.String(" lines, "); C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, "); C.Int(WRITER.counter); C.StringLn(" bytes"); UTILS.Exit(0) END main; BEGIN main END Compiler.