HOST.ob07 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2022, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE HOST;
  7. IMPORT SYSTEM, K := KOSAPI, API;
  8. CONST
  9. slash* = "/";
  10. eol* = 0DX + 0AX;
  11. bit_depth* = API.BIT_DEPTH;
  12. maxint* = ROR(-2, 1);
  13. minint* = ROR(1, 1);
  14. MAX_PARAM = 1024;
  15. TYPE
  16. DAYS = ARRAY 12, 31, 2 OF INTEGER;
  17. FNAME = ARRAY 520 OF CHAR;
  18. FS = POINTER TO rFS;
  19. rFS = RECORD
  20. subfunc, pos, hpos, bytes, buffer: INTEGER;
  21. name: FNAME
  22. END;
  23. FD = POINTER TO rFD;
  24. rFD = RECORD
  25. attr: INTEGER;
  26. ntyp: CHAR;
  27. reserved: ARRAY 3 OF CHAR;
  28. time_create, date_create,
  29. time_access, date_access,
  30. time_modif, date_modif,
  31. size, hsize: INTEGER;
  32. name: FNAME
  33. END;
  34. VAR
  35. Console: BOOLEAN;
  36. days: DAYS;
  37. Params: ARRAY MAX_PARAM, 2 OF INTEGER;
  38. argc*: INTEGER;
  39. maxreal*, inf*: REAL;
  40. PROCEDURE [stdcall, "Console.obj", "con_init"] con_init (wnd_width, wnd_height, scr_width, scr_height, title: INTEGER);
  41. PROCEDURE [stdcall, "Console.obj", "con_exit"] con_exit (bCloseWindow: BOOLEAN);
  42. PROCEDURE [stdcall, "Console.obj", "con_write_string"] con_write_string (string, length: INTEGER);
  43. PROCEDURE ExitProcess* (p1: INTEGER);
  44. BEGIN
  45. IF Console THEN
  46. con_exit(FALSE)
  47. END;
  48. K.sysfunc1(-1)
  49. END ExitProcess;
  50. PROCEDURE OutChar* (c: CHAR);
  51. BEGIN
  52. IF Console THEN
  53. con_write_string(SYSTEM.ADR(c), 1)
  54. ELSE
  55. K.sysfunc3(63, 1, ORD(c))
  56. END
  57. END OutChar;
  58. PROCEDURE GetFileInfo (FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN;
  59. VAR
  60. res2: INTEGER;
  61. fs: rFS;
  62. BEGIN
  63. fs.subfunc := 5;
  64. fs.pos := 0;
  65. fs.hpos := 0;
  66. fs.bytes := 0;
  67. fs.buffer := SYSTEM.ADR(Info);
  68. COPY(FName, fs.name)
  69. RETURN K.sysfunc22(70, SYSTEM.ADR(fs), res2) = 0
  70. END GetFileInfo;
  71. PROCEDURE Exists (FName: ARRAY OF CHAR): BOOLEAN;
  72. VAR
  73. fd: rFD;
  74. BEGIN
  75. RETURN GetFileInfo(FName, fd) & ~(4 IN BITS(fd.attr))
  76. END Exists;
  77. PROCEDURE Close (VAR F: FS);
  78. BEGIN
  79. IF F # NIL THEN
  80. DISPOSE(F)
  81. END
  82. END Close;
  83. PROCEDURE Open (FName: ARRAY OF CHAR): FS;
  84. VAR
  85. F: FS;
  86. BEGIN
  87. IF Exists(FName) THEN
  88. NEW(F);
  89. IF F # NIL THEN
  90. F.subfunc := 0;
  91. F.pos := 0;
  92. F.hpos := 0;
  93. F.bytes := 0;
  94. F.buffer := 0;
  95. COPY(FName, F.name)
  96. END
  97. ELSE
  98. F := NIL
  99. END
  100. RETURN F
  101. END Open;
  102. PROCEDURE Read (F: FS; Buffer, Count: INTEGER): INTEGER;
  103. VAR
  104. res, res2: INTEGER;
  105. BEGIN
  106. IF F # NIL THEN
  107. F.subfunc := 0;
  108. F.bytes := Count;
  109. F.buffer := Buffer;
  110. res := K.sysfunc22(70, SYSTEM.ADR(F^), res2);
  111. IF res2 > 0 THEN
  112. F.pos := F.pos + res2
  113. END
  114. ELSE
  115. res2 := 0
  116. END
  117. RETURN res2
  118. END Read;
  119. PROCEDURE Write (F: FS; Buffer, Count: INTEGER): INTEGER;
  120. VAR
  121. res, res2: INTEGER;
  122. BEGIN
  123. IF F # NIL THEN
  124. F.subfunc := 3;
  125. F.bytes := Count;
  126. F.buffer := Buffer;
  127. res := K.sysfunc22(70, SYSTEM.ADR(F^), res2);
  128. IF res2 > 0 THEN
  129. F.pos := F.pos + res2
  130. END
  131. ELSE
  132. res2 := 0
  133. END
  134. RETURN res2
  135. END Write;
  136. PROCEDURE Create (FName: ARRAY OF CHAR): FS;
  137. VAR
  138. F: FS;
  139. res2: INTEGER;
  140. BEGIN
  141. NEW(F);
  142. IF F # NIL THEN
  143. F.subfunc := 2;
  144. F.pos := 0;
  145. F.hpos := 0;
  146. F.bytes := 0;
  147. F.buffer := 0;
  148. COPY(FName, F.name);
  149. IF K.sysfunc22(70, SYSTEM.ADR(F^), res2) # 0 THEN
  150. DISPOSE(F)
  151. END
  152. END
  153. RETURN F
  154. END Create;
  155. PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER;
  156. VAR
  157. n: INTEGER;
  158. fs: FS;
  159. BEGIN
  160. SYSTEM.GET(SYSTEM.ADR(F), fs);
  161. n := Read(fs, SYSTEM.ADR(Buffer[0]), bytes);
  162. IF n = 0 THEN
  163. n := -1
  164. END
  165. RETURN n
  166. END FileRead;
  167. PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER;
  168. VAR
  169. n: INTEGER;
  170. fs: FS;
  171. BEGIN
  172. SYSTEM.GET(SYSTEM.ADR(F), fs);
  173. n := Write(fs, SYSTEM.ADR(Buffer[0]), bytes);
  174. IF n = 0 THEN
  175. n := -1
  176. END
  177. RETURN n
  178. END FileWrite;
  179. PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER;
  180. VAR
  181. fs: FS;
  182. res: INTEGER;
  183. BEGIN
  184. fs := Create(FName);
  185. SYSTEM.GET(SYSTEM.ADR(fs), res)
  186. RETURN res
  187. END FileCreate;
  188. PROCEDURE FileClose* (F: INTEGER);
  189. VAR
  190. fs: FS;
  191. BEGIN
  192. SYSTEM.GET(SYSTEM.ADR(F), fs);
  193. Close(fs)
  194. END FileClose;
  195. PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER;
  196. VAR
  197. fs: FS;
  198. res: INTEGER;
  199. BEGIN
  200. fs := Open(FName);
  201. SYSTEM.GET(SYSTEM.ADR(fs), res)
  202. RETURN res
  203. END FileOpen;
  204. PROCEDURE chmod* (FName: ARRAY OF CHAR);
  205. END chmod;
  206. PROCEDURE GetTickCount* (): INTEGER;
  207. RETURN K.sysfunc2(26, 9)
  208. END GetTickCount;
  209. PROCEDURE AppAdr (): INTEGER;
  210. VAR
  211. buf: ARRAY 1024 OF CHAR;
  212. a: INTEGER;
  213. BEGIN
  214. a := K.sysfunc3(9, SYSTEM.ADR(buf), -1);
  215. SYSTEM.GET(SYSTEM.ADR(buf) + 22, a)
  216. RETURN a
  217. END AppAdr;
  218. PROCEDURE GetCommandLine (): INTEGER;
  219. VAR
  220. param: INTEGER;
  221. BEGIN
  222. SYSTEM.GET(28 + AppAdr(), param)
  223. RETURN param
  224. END GetCommandLine;
  225. PROCEDURE GetName (): INTEGER;
  226. VAR
  227. name: INTEGER;
  228. BEGIN
  229. SYSTEM.GET(32 + AppAdr(), name)
  230. RETURN name
  231. END GetName;
  232. PROCEDURE GetChar (adr: INTEGER): CHAR;
  233. VAR
  234. res: CHAR;
  235. BEGIN
  236. SYSTEM.GET(adr, res)
  237. RETURN res
  238. END GetChar;
  239. PROCEDURE ParamParse;
  240. VAR
  241. p, count, name, cond: INTEGER;
  242. c: CHAR;
  243. PROCEDURE ChangeCond (A, B, C: INTEGER; c: CHAR; VAR cond: INTEGER);
  244. BEGIN
  245. IF (c <= 20X) & (c # 0X) THEN
  246. cond := A
  247. ELSIF c = 22X THEN
  248. cond := B
  249. ELSIF c = 0X THEN
  250. cond := 6
  251. ELSE
  252. cond := C
  253. END
  254. END ChangeCond;
  255. BEGIN
  256. p := GetCommandLine();
  257. name := GetName();
  258. Params[0, 0] := name;
  259. WHILE GetChar(name) # 0X DO
  260. INC(name)
  261. END;
  262. Params[0, 1] := name - 1;
  263. cond := 0;
  264. count := 1;
  265. WHILE (argc < MAX_PARAM) & (cond # 6) DO
  266. c := GetChar(p);
  267. CASE cond OF
  268. |0: ChangeCond(0, 4, 1, c, cond); IF cond = 1 THEN Params[count, 0] := p END
  269. |1: ChangeCond(0, 3, 1, c, cond); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END
  270. |3: ChangeCond(3, 1, 3, c, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END
  271. |4: ChangeCond(5, 0, 5, c, cond); IF cond = 5 THEN Params[count, 0] := p END
  272. |5: ChangeCond(5, 1, 5, c, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END
  273. |6:
  274. END;
  275. INC(p)
  276. END;
  277. argc := count
  278. END ParamParse;
  279. PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR);
  280. VAR
  281. i, j, len: INTEGER;
  282. c: CHAR;
  283. BEGIN
  284. j := 0;
  285. IF n < argc THEN
  286. len := LEN(s) - 1;
  287. i := Params[n, 0];
  288. WHILE (j < len) & (i <= Params[n, 1]) DO
  289. c := GetChar(i);
  290. IF c # 22X THEN
  291. s[j] := c;
  292. INC(j)
  293. END;
  294. INC(i)
  295. END
  296. END;
  297. s[j] := 0X
  298. END GetArg;
  299. PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR);
  300. VAR
  301. n: INTEGER;
  302. BEGIN
  303. n := K.sysfunc4(30, 2, SYSTEM.ADR(path[0]), LEN(path) - 2);
  304. path[n - 1] := slash;
  305. path[n] := 0X
  306. END GetCurrentDirectory;
  307. PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN;
  308. RETURN path[0] # slash
  309. END isRelative;
  310. PROCEDURE UnixTime* (): INTEGER;
  311. VAR
  312. date, time, year, month, day, hour, min, sec: INTEGER;
  313. BEGIN
  314. date := K.sysfunc1(29);
  315. time := K.sysfunc1(3);
  316. year := date MOD 16;
  317. date := date DIV 16;
  318. year := (date MOD 16) * 10 + year;
  319. date := date DIV 16;
  320. month := date MOD 16;
  321. date := date DIV 16;
  322. month := (date MOD 16) * 10 + month;
  323. date := date DIV 16;
  324. day := date MOD 16;
  325. date := date DIV 16;
  326. day := (date MOD 16) * 10 + day;
  327. date := date DIV 16;
  328. hour := time MOD 16;
  329. time := time DIV 16;
  330. hour := (time MOD 16) * 10 + hour;
  331. time := time DIV 16;
  332. min := time MOD 16;
  333. time := time DIV 16;
  334. min := (time MOD 16) * 10 + min;
  335. time := time DIV 16;
  336. sec := time MOD 16;
  337. time := time DIV 16;
  338. sec := (time MOD 16) * 10 + sec;
  339. time := time DIV 16;
  340. INC(year, 2000)
  341. RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec
  342. END UnixTime;
  343. PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER;
  344. BEGIN
  345. SYSTEM.GET32(SYSTEM.ADR(x), a);
  346. SYSTEM.GET32(SYSTEM.ADR(x) + 4, b)
  347. RETURN a
  348. END splitf;
  349. PROCEDURE d2s* (x: REAL): INTEGER;
  350. VAR
  351. h, l, s, e: INTEGER;
  352. BEGIN
  353. e := splitf(x, l, h);
  354. s := ASR(h, 31) MOD 2;
  355. e := (h DIV 100000H) MOD 2048;
  356. IF e <= 896 THEN
  357. h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H;
  358. REPEAT
  359. h := h DIV 2;
  360. INC(e)
  361. UNTIL e = 897;
  362. e := 896;
  363. l := (h MOD 8) * 20000000H;
  364. h := h DIV 8
  365. ELSIF (1151 <= e) & (e < 2047) THEN
  366. e := 1151;
  367. h := 0;
  368. l := 0
  369. ELSIF e = 2047 THEN
  370. e := 1151;
  371. IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN
  372. h := 80000H;
  373. l := 0
  374. END
  375. END;
  376. DEC(e, 896)
  377. RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8
  378. END d2s;
  379. PROCEDURE init (VAR days: DAYS);
  380. VAR
  381. i, j, n0, n1: INTEGER;
  382. BEGIN
  383. FOR i := 0 TO 11 DO
  384. FOR j := 0 TO 30 DO
  385. days[i, j, 0] := 0;
  386. days[i, j, 1] := 0;
  387. END
  388. END;
  389. days[ 1, 28, 0] := -1;
  390. FOR i := 0 TO 1 DO
  391. days[ 1, 29, i] := -1;
  392. days[ 1, 30, i] := -1;
  393. days[ 3, 30, i] := -1;
  394. days[ 5, 30, i] := -1;
  395. days[ 8, 30, i] := -1;
  396. days[10, 30, i] := -1;
  397. END;
  398. n0 := 0;
  399. n1 := 0;
  400. FOR i := 0 TO 11 DO
  401. FOR j := 0 TO 30 DO
  402. IF days[i, j, 0] = 0 THEN
  403. days[i, j, 0] := n0;
  404. INC(n0)
  405. END;
  406. IF days[i, j, 1] = 0 THEN
  407. days[i, j, 1] := n1;
  408. INC(n1)
  409. END
  410. END
  411. END;
  412. inf := SYSTEM.INF();
  413. maxreal := 1.9;
  414. PACK(maxreal, 1023);
  415. Console := TRUE;
  416. IF Console THEN
  417. con_init(-1, -1, -1, -1, SYSTEM.SADR("Oberon-07 for KolibriOS"))
  418. END;
  419. ParamParse
  420. END init;
  421. BEGIN
  422. init(days)
  423. END HOST.