Compiler.ob07 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2023, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE Compiler;
  7. IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE,
  8. ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS, SCAN, TEXTDRV;
  9. CONST
  10. DEF_WINDOWS = "WINDOWS";
  11. DEF_LINUX = "LINUX";
  12. DEF_KOLIBRIOS = "KOLIBRIOS";
  13. DEF_CPU_X86 = "CPU_X86";
  14. DEF_CPU_X8664 = "CPU_X8664";
  15. PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH);
  16. VAR
  17. param: PARS.PATH;
  18. i, j: INTEGER;
  19. _end: BOOLEAN;
  20. value: INTEGER;
  21. minor,
  22. major: INTEGER;
  23. checking: SET;
  24. PROCEDURE getVal (VAR i: INTEGER; VAR value: INTEGER);
  25. VAR
  26. param: PARS.PATH;
  27. val: INTEGER;
  28. BEGIN
  29. INC(i);
  30. UTILS.GetArg(i, param);
  31. IF STRINGS.StrToInt(param, val) THEN
  32. value := val
  33. END;
  34. IF param[0] = "-" THEN
  35. DEC(i)
  36. END
  37. END getVal;
  38. BEGIN
  39. options.lower := TRUE;
  40. out := "";
  41. checking := options.checking;
  42. _end := FALSE;
  43. i := 3;
  44. REPEAT
  45. UTILS.GetArg(i, param);
  46. IF param = "-stk" THEN
  47. INC(i);
  48. UTILS.GetArg(i, param);
  49. IF STRINGS.StrToInt(param, value) & (1 <= value) & (value <= 32) THEN
  50. options.stack := value
  51. END;
  52. IF param[0] = "-" THEN
  53. DEC(i)
  54. END
  55. ELSIF param = "-fa" THEN
  56. getVal(i, options.PE32FileAlignment)
  57. ELSIF param = "-out" THEN
  58. INC(i);
  59. UTILS.GetArg(i, param);
  60. IF param[0] = "-" THEN
  61. DEC(i)
  62. ELSE
  63. out := param
  64. END
  65. ELSIF param = "-tab" THEN
  66. getVal(i, options.tab)
  67. ELSIF param = "-ram" THEN
  68. getVal(i, options.ram)
  69. ELSIF param = "-rom" THEN
  70. getVal(i, options.rom)
  71. ELSIF param = "-nochk" THEN
  72. INC(i);
  73. UTILS.GetArg(i, param);
  74. IF param[0] = "-" THEN
  75. DEC(i)
  76. ELSE
  77. j := 0;
  78. WHILE param[j] # 0X DO
  79. IF param[j] = "p" THEN
  80. EXCL(checking, ST.chkPTR)
  81. ELSIF param[j] = "t" THEN
  82. EXCL(checking, ST.chkGUARD)
  83. ELSIF param[j] = "i" THEN
  84. EXCL(checking, ST.chkIDX)
  85. ELSIF param[j] = "b" THEN
  86. EXCL(checking, ST.chkBYTE)
  87. ELSIF param[j] = "c" THEN
  88. EXCL(checking, ST.chkCHR)
  89. ELSIF param[j] = "w" THEN
  90. EXCL(checking, ST.chkWCHR)
  91. ELSIF param[j] = "r" THEN
  92. EXCL(checking, ST.chkCHR);
  93. EXCL(checking, ST.chkWCHR);
  94. EXCL(checking, ST.chkBYTE)
  95. ELSIF param[j] = "s" THEN
  96. EXCL(checking, ST.chkSTK)
  97. ELSIF param[j] = "a" THEN
  98. checking := {}
  99. END;
  100. INC(j)
  101. END;
  102. END
  103. ELSIF param = "-ver" THEN
  104. INC(i);
  105. UTILS.GetArg(i, param);
  106. IF STRINGS.StrToVer(param, major, minor) THEN
  107. options.version := major * 65536 + minor
  108. END;
  109. IF param[0] = "-" THEN
  110. DEC(i)
  111. END
  112. ELSIF param = "-lower" THEN
  113. options.lower := TRUE
  114. ELSIF param = "-upper" THEN
  115. options.lower := FALSE
  116. ELSIF param = "-pic" THEN
  117. options.pic := TRUE
  118. ELSIF param = "-uses" THEN
  119. options.uses := TRUE
  120. ELSIF param = "-def" THEN
  121. INC(i);
  122. UTILS.GetArg(i, param);
  123. SCAN.NewDef(param)
  124. ELSIF param = "" THEN
  125. _end := TRUE
  126. ELSE
  127. ERRORS.BadParam(param)
  128. END;
  129. INC(i)
  130. UNTIL _end;
  131. options.checking := checking
  132. END keys;
  133. PROCEDURE OutTargetItem (target: INTEGER; text: ARRAY OF CHAR);
  134. VAR
  135. width: INTEGER;
  136. BEGIN
  137. width := 15;
  138. width := width - LENGTH(TARGETS.Targets[target].ComLinePar) - 4;
  139. C.String(" '"); C.String(TARGETS.Targets[target].ComLinePar); C.String("'");
  140. WHILE width > 0 DO
  141. C.String(20X);
  142. DEC(width)
  143. END;
  144. C.StringLn(text)
  145. END OutTargetItem;
  146. PROCEDURE main;
  147. VAR
  148. path: PARS.PATH;
  149. inname: PARS.PATH;
  150. ext: PARS.PATH;
  151. app_path: PARS.PATH;
  152. lib_path: PARS.PATH;
  153. modname: PARS.PATH;
  154. outname: PARS.PATH;
  155. param: PARS.PATH;
  156. temp: PARS.PATH;
  157. target: INTEGER;
  158. time: INTEGER;
  159. options: PROG.OPTIONS;
  160. BEGIN
  161. options.stack := 2;
  162. options.tab := TEXTDRV.defTabSize;
  163. options.version := 65536;
  164. options.pic := FALSE;
  165. options.lower := FALSE;
  166. options.uses := FALSE;
  167. options.checking := ST.chkALL;
  168. PATHS.GetCurrentDirectory(app_path);
  169. UTILS.GetArg(0, temp);
  170. PATHS.split(temp, path, modname, ext);
  171. IF PATHS.isRelative(path) THEN
  172. PATHS.RelPath(app_path, path, temp);
  173. path := temp
  174. END;
  175. lib_path := path;
  176. UTILS.GetArg(1, inname);
  177. STRINGS.replace(inname, "\", UTILS.slash);
  178. STRINGS.replace(inname, "/", UTILS.slash);
  179. C.Ln;
  180. C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor);
  181. C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) " + UTILS.Date);
  182. C.StringLn("Copyright (c) 2018-2023, Anton Krotov");
  183. IF inname = "" THEN
  184. C.Ln;
  185. C.StringLn("Usage: Compiler <main module> <target> [optional settings]"); C.Ln;
  186. C.StringLn("target =");
  187. IF UTILS.bit_depth = 64 THEN
  188. OutTargetItem(TARGETS.Win64C, "Windows64 Console");
  189. OutTargetItem(TARGETS.Win64GUI, "Windows64 GUI");
  190. OutTargetItem(TARGETS.Win64DLL, "Windows64 DLL");
  191. OutTargetItem(TARGETS.Linux64, "Linux64 Exec");
  192. OutTargetItem(TARGETS.Linux64SO, "Linux64 SO")
  193. END;
  194. OutTargetItem(TARGETS.Win32C, "Windows32 Console");
  195. OutTargetItem(TARGETS.Win32GUI, "Windows32 GUI");
  196. OutTargetItem(TARGETS.Win32DLL, "Windows32 DLL");
  197. OutTargetItem(TARGETS.Linux32, "Linux32 Exec");
  198. OutTargetItem(TARGETS.Linux32SO, "Linux32 SO");
  199. OutTargetItem(TARGETS.KolibriOS, "KolibriOS Exec");
  200. OutTargetItem(TARGETS.KolibriOSDLL, "KolibriOS DLL");
  201. OutTargetItem(TARGETS.MSP430, "MSP430x{1,2}xx microcontrollers");
  202. OutTargetItem(TARGETS.STM32CM3, "STM32 Cortex-M3 microcontrollers");
  203. C.Ln;
  204. C.StringLn("optional settings:"); C.Ln;
  205. C.StringLn(" -out <file name> output"); C.Ln;
  206. C.StringLn(" -stk <size> set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln;
  207. C.StringLn(" -nochk <'ptibcwra'> disable runtime checking (pointers, types, indexes,");
  208. C.StringLn(" BYTE, CHR, WCHR)"); C.Ln;
  209. C.StringLn(" -lower allow lower case for keywords (default)"); C.Ln;
  210. C.StringLn(" -upper only upper case for keywords"); C.Ln;
  211. C.StringLn(" -def <identifier> define conditional compilation symbol"); C.Ln;
  212. C.StringLn(" -ver <major.minor> set version of program (KolibriOS DLL)"); C.Ln;
  213. C.StringLn(" -ram <size> set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln;
  214. C.StringLn(" -rom <size> set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln;
  215. C.StringLn(" -tab <width> set width for tabs"); C.Ln;
  216. C.StringLn(" -uses list imported modules"); C.Ln;
  217. C.StringLn(" -fa <size> set PE32 file alignment {512 (def.), 1024, 2048, 4096}"); C.Ln;
  218. UTILS.Exit(0)
  219. END;
  220. C.Dashes;
  221. PATHS.split(inname, path, modname, ext);
  222. IF ext # UTILS.FILE_EXT THEN
  223. ERRORS.Error(207)
  224. END;
  225. IF PATHS.isRelative(path) THEN
  226. PATHS.RelPath(app_path, path, temp);
  227. path := temp
  228. END;
  229. UTILS.GetArg(2, param);
  230. IF param = "" THEN
  231. ERRORS.Error(205)
  232. END;
  233. SCAN.NewDef(param);
  234. IF TARGETS.Select(param) THEN
  235. target := TARGETS.target
  236. ELSE
  237. ERRORS.Error(206)
  238. END;
  239. IF TARGETS.CPU = TARGETS.cpuMSP430 THEN
  240. options.ram := MSP430.minRAM;
  241. options.rom := MSP430.minROM
  242. END;
  243. IF (TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE) THEN
  244. options.ram := THUMB.minRAM;
  245. options.rom := THUMB.minROM
  246. END;
  247. IF UTILS.bit_depth < TARGETS.BitDepth THEN
  248. ERRORS.Error(206)
  249. END;
  250. STRINGS.append(lib_path, "lib");
  251. STRINGS.append(lib_path, UTILS.slash);
  252. STRINGS.append(lib_path, TARGETS.LibDir);
  253. STRINGS.append(lib_path, UTILS.slash);
  254. keys(options, outname);
  255. TEXTDRV.setTabSize(options.tab);
  256. IF outname = "" THEN
  257. outname := path;
  258. STRINGS.append(outname, modname);
  259. STRINGS.append(outname, TARGETS.FileExt)
  260. ELSE
  261. IF PATHS.isRelative(outname) THEN
  262. PATHS.RelPath(app_path, outname, temp);
  263. outname := temp
  264. END
  265. END;
  266. PARS.init(options);
  267. CASE TARGETS.OS OF
  268. |TARGETS.osNONE:
  269. |TARGETS.osWIN32,
  270. TARGETS.osWIN64: SCAN.NewDef(DEF_WINDOWS)
  271. |TARGETS.osLINUX32,
  272. TARGETS.osLINUX64: SCAN.NewDef(DEF_LINUX)
  273. |TARGETS.osKOS: SCAN.NewDef(DEF_KOLIBRIOS)
  274. END;
  275. CASE TARGETS.CPU OF
  276. |TARGETS.cpuX86: SCAN.NewDef(DEF_CPU_X86)
  277. |TARGETS.cpuAMD64: SCAN.NewDef(DEF_CPU_X8664)
  278. |TARGETS.cpuMSP430:
  279. |TARGETS.cpuTHUMB:
  280. |TARGETS.cpuRVM32I:
  281. |TARGETS.cpuRVM64I:
  282. END;
  283. ST.compile(path, lib_path, modname, outname, target, options);
  284. time := UTILS.GetTickCount() - UTILS.time;
  285. C.Dashes;
  286. C.Int(PARS.lines); C.String(" lines, ");
  287. C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, ");
  288. C.Int(WRITER.counter); C.StringLn(" bytes");
  289. UTILS.Exit(0)
  290. END main;
  291. BEGIN
  292. main
  293. END Compiler.