system.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2020 by Karoly Balogh
  4. System unit for the Sinclair QL
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit System;
  12. interface
  13. {$define FPC_IS_SYSTEM}
  14. {$define FPC_STDOUT_TRUE_ALIAS}
  15. {$define FPC_ANSI_TEXTFILEREC}
  16. {$define FPC_QL_USE_OSHEAP}
  17. {$ifdef FPC_QL_USE_OSHEAP}
  18. {$define HAS_MEMORYMANAGER}
  19. {$endif FPC_QL_USE_OSHEAP}
  20. {$i systemh.inc}
  21. {Platform specific information}
  22. const
  23. LineEnding = #10;
  24. LFNSupport = false;
  25. CtrlZMarksEOF: boolean = false; (* #26 not considered as end of file *)
  26. DirectorySeparator = '\';
  27. DriveSeparator = ':';
  28. ExtensionSeparator = '.';
  29. PathSeparator = ';';
  30. AllowDirectorySeparators : set of char = ['\','/'];
  31. AllowDriveSeparators : set of char = [':'];
  32. FileNameCaseSensitive = false;
  33. FileNameCasePreserving = false;
  34. maxExitCode = 255;
  35. MaxPathLen = 255;
  36. AllFilesMask = '*.*';
  37. sLineBreak = LineEnding;
  38. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  39. const
  40. UnusedHandle = -1;
  41. StdInputHandle: longint = UnusedHandle;
  42. StdOutputHandle: longint = UnusedHandle;
  43. StdErrorHandle: longint = UnusedHandle;
  44. var
  45. QL_ChannelIDNum : word;
  46. QL_ChannelIDs: pdword;
  47. QL_CommandLineLen : word;
  48. QL_CommandLine : pchar;
  49. argv: PPChar;
  50. argc: Longint;
  51. {$if defined(FPUSOFT)}
  52. {$define fpc_softfpu_interface}
  53. {$i softfpu.pp}
  54. {$undef fpc_softfpu_interface}
  55. {$endif defined(FPUSOFT)}
  56. type
  57. QLConHandle = record
  58. inputHandle: longint;
  59. outputHandle: longint;
  60. errorHandle: longint;
  61. userData: pointer;
  62. end;
  63. function SetQLJobName(const s: string): longint;
  64. function GetQLJobName: string;
  65. function GetQLJobNamePtr: pointer;
  66. procedure SetQLDefaultConExitMessage(const msg: PChar);
  67. implementation
  68. {$define FPC_SYSTEM_HAS_STACKTOP}
  69. {$define FPC_SYSTEM_HAS_BACKTRACESTR}
  70. {$if defined(FPUSOFT)}
  71. {$define fpc_softfpu_implementation}
  72. {$define softfpu_compiler_mul32to64}
  73. {$define softfpu_inline}
  74. {$i softfpu.pp}
  75. {$undef fpc_softfpu_implementation}
  76. { we get these functions and types from the softfpu code }
  77. {$define FPC_SYSTEM_HAS_float64}
  78. {$define FPC_SYSTEM_HAS_float32}
  79. {$define FPC_SYSTEM_HAS_flag}
  80. {$define FPC_SYSTEM_HAS_extractFloat64Frac0}
  81. {$define FPC_SYSTEM_HAS_extractFloat64Frac1}
  82. {$define FPC_SYSTEM_HAS_extractFloat64Exp}
  83. {$define FPC_SYSTEM_HAS_extractFloat64Sign}
  84. {$define FPC_SYSTEM_HAS_ExtractFloat32Frac}
  85. {$define FPC_SYSTEM_HAS_extractFloat32Exp}
  86. {$define FPC_SYSTEM_HAS_extractFloat32Sign}
  87. {$endif defined(FPUSOFT)}
  88. {$i system.inc}
  89. {$ifdef FPC_QL_USE_OSHEAP}
  90. {$i osheap.inc}
  91. {$endif FPC_QL_USE_OSHEAP}
  92. function GetProcessID:SizeUInt;
  93. begin
  94. GetProcessID := mt_inf(nil, nil);
  95. end;
  96. {*****************************************************************************
  97. ParamStr
  98. *****************************************************************************}
  99. var
  100. args: PChar;
  101. { number of args }
  102. function ParamCount: LongInt;
  103. begin
  104. ParamCount:=argc;
  105. end;
  106. { argument number l }
  107. function ParamStr(l: LongInt): string;
  108. begin
  109. if (l >= 0) and (l <= argc) then
  110. ParamStr:=argv[l]
  111. else
  112. ParamStr:='';
  113. end;
  114. procedure SysInitParamsAndEnv;
  115. var
  116. i,j : longint;
  117. c : char;
  118. argv_size : longint;
  119. const
  120. word_separators=[' ',#0];
  121. begin
  122. argc:=0;
  123. argv:=nil;
  124. args:=GetMem(QL_CommandLineLen+1);
  125. if not assigned(args) then
  126. exit;
  127. Move(QL_CommandLine^,args^,QL_CommandLineLen);
  128. args[QL_CommandLineLen]:=#0;
  129. i:=0;
  130. c:=' ';
  131. while args[i]<>#0 do
  132. begin
  133. if (c in word_separators) and not (args[i] in word_separators) then
  134. inc(argc);
  135. c:=args[i];
  136. inc(i);
  137. end;
  138. { +2 is because argv[0] should be program name,
  139. and argv[argc+1] is argv array terminator }
  140. argv:=GetMem((argc+2)*sizeof(pointer));
  141. if not assigned(argv) then
  142. begin
  143. argc:=0;
  144. exit;
  145. end;
  146. argv[argc+1]:=nil;
  147. { FIX ME: for now the 0th argument (program name) is just always empty }
  148. argv[0]:=#0;
  149. i:=0;
  150. j:=1;
  151. c:=' ';
  152. while args[i]<>#0 do
  153. begin
  154. if (c in word_separators) and not (args[i] in word_separators) then
  155. begin
  156. argv[j]:=@args[i];
  157. inc(j);
  158. end;
  159. c:=args[i];
  160. if (c in word_separators) then
  161. args[i]:=#0;
  162. inc(i);
  163. end;
  164. end;
  165. procedure randomize;
  166. begin
  167. { Get the current date/time }
  168. randseed:=mt_rclck;
  169. end;
  170. {*****************************************************************************
  171. Platform specific custom calls
  172. *****************************************************************************}
  173. procedure PrintStr(ch: longint; const s: shortstring);
  174. begin
  175. io_sstrg(ch,-1,@s[1],ord(s[0]));
  176. end;
  177. procedure DebugStr(const s: shortstring); public name '_dbgstr';
  178. var
  179. i: longint;
  180. begin
  181. PrintStr(stdOutputHandle,s);
  182. for i:=0 to 10000 do begin end;
  183. end;
  184. var
  185. start_proc: byte; external name '_start';
  186. { WARNING! if you change this value, make sure there's enough
  187. buffer space for the job name in the startup code! }
  188. const
  189. JOB_NAME_MAX_LEN = 48;
  190. function SetQLJobName(const s: string): longint;
  191. var
  192. len: longint;
  193. begin
  194. SetQLJobName:=-1;
  195. if pword(@start_proc)[3] = $4afb then
  196. begin
  197. len:=length(s);
  198. if len > JOB_NAME_MAX_LEN then
  199. len:=JOB_NAME_MAX_LEN;
  200. Move(s[1],pword(@start_proc)[5],len);
  201. pword(@start_proc)[4]:=len;
  202. SetQLJobName:=len;
  203. end;
  204. end;
  205. function GetQLJobName: string;
  206. var
  207. len: longint;
  208. begin
  209. GetQLJobName:='';
  210. if pword(@start_proc)[3] = $4afb then
  211. begin
  212. len:=pword(@start_proc)[4];
  213. if len <= JOB_NAME_MAX_LEN then
  214. begin
  215. SetLength(GetQLJobName,len);
  216. Move(pword(@start_proc)[5],GetQLJobName[1],len);
  217. end;
  218. end;
  219. end;
  220. function GetQLJobNamePtr: pointer;
  221. begin
  222. GetQLJobNamePtr:=nil;
  223. if pword(@start_proc)[3] = $4afb then
  224. begin
  225. GetQLJobNamePtr:=@pword(@start_proc)[4];
  226. end;
  227. end;
  228. const
  229. QLDefaultConExitMessage: PChar = 'Press any key to exit';
  230. procedure SetQLDefaultConExitMessage(const msg: PChar);
  231. begin
  232. QLDefaultConExitMessage:=msg;
  233. end;
  234. function QLOpenCon(var console: QLConHandle): boolean; weakexternal name 'QLOpenCon';
  235. procedure QLCloseCon(var console: QLConHandle); weakexternal name 'QLCloseCon';
  236. function DefaultQLOpenCon(var console: QLConHandle): boolean;
  237. var
  238. r: TQLRect;
  239. begin
  240. DefaultQLOpenCon:=false;
  241. with console do
  242. begin
  243. inputHandle:=io_open('con_',Q_OPEN);
  244. if inputHandle <= 0 then
  245. exit;
  246. outputHandle:=inputHandle;
  247. errorHandle:=inputHandle;
  248. userData:=nil;
  249. r.q_width:=512;
  250. r.q_height:=256;
  251. r.q_x:=0;
  252. r.q_y:=0;
  253. sd_wdef(outputHandle,-1,2,1,@r);
  254. sd_clear(outputHandle,-1);
  255. end;
  256. DefaultQLOpenCon:=true;
  257. end;
  258. procedure DefaultQLCloseCon(var console: QLConHandle);
  259. begin
  260. with console do
  261. begin
  262. if assigned(QLDefaultConExitMessage) and (length(QLDefaultConExitMessage) > 0) then
  263. begin
  264. io_sstrg(outputHandle, -1, QLDefaultConExitMessage, length(QLDefaultConExitMessage));
  265. io_fbyte(inputHandle, -1);
  266. end;
  267. end;
  268. end;
  269. {*****************************************************************************
  270. System Dependent Entry code
  271. *****************************************************************************}
  272. var
  273. jobStackDataPtr: pointer; external name '__stackpointer_on_entry';
  274. program_name: shortstring; external name '__fpc_program_name';
  275. QLCon: QLConHandle;
  276. QLConOpen: boolean;
  277. { QL/QDOS specific startup }
  278. procedure SysInitQDOS;
  279. begin
  280. QL_ChannelIDNum:=pword(jobStackDataPtr)[0];
  281. QL_ChannelIDs:=@pword(jobStackDataPtr)[1];
  282. QL_CommandLineLen:=pword(@QL_ChannelIDs[QL_ChannelIDNum])[0];
  283. QL_CommandLine:=@pword(@QL_ChannelIDs[QL_ChannelIDNum])[1];
  284. SetQLJobName(program_name);
  285. if assigned(@QLOpenCon) then
  286. QLConOpen:=QLOpenCon(QLCon)
  287. else
  288. QLConOpen:=DefaultQLOpenCon(QLCon);
  289. if not QLConOpen then
  290. halt(1);
  291. with QLCon do
  292. begin
  293. stdInputHandle:=inputHandle;
  294. stdOutputHandle:=outputHandle;
  295. stdErrorHandle:=errorHandle;
  296. end;
  297. end;
  298. {*****************************************************************************
  299. System Dependent Exit code
  300. *****************************************************************************}
  301. procedure haltproc(e:longint); external name '_haltproc';
  302. procedure system_exit;
  303. begin
  304. if assigned(args) then
  305. FreeMem(args);
  306. if assigned(argv) then
  307. FreeMem(argv);
  308. if QLConOpen then
  309. begin
  310. if assigned(@QLCloseCon) then
  311. QLCloseCon(QLCon)
  312. else
  313. DefaultQLCloseCon(QLCon);
  314. end;
  315. stdInputHandle:=UnusedHandle;
  316. stdOutputHandle:=UnusedHandle;
  317. stdErrorHandle:=UnusedHandle;
  318. haltproc(exitcode);
  319. end;
  320. {*****************************************************************************
  321. System Unit Initialization
  322. *****************************************************************************}
  323. procedure SysInitStdIO;
  324. begin
  325. OpenStdIO(Input,fmInput,StdInputHandle);
  326. OpenStdIO(Output,fmOutput,StdOutputHandle);
  327. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  328. {$ifndef FPC_STDOUT_TRUE_ALIAS}
  329. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  330. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  331. {$endif FPC_STDOUT_TRUE_ALIAS}
  332. end;
  333. function CheckInitialStkLen (StkLen: SizeUInt): SizeUInt;
  334. begin
  335. CheckInitialStkLen := StkLen;
  336. end;
  337. begin
  338. StackLength := CheckInitialStkLen (InitialStkLen);
  339. StackBottom := StackTop - StackLength;
  340. StackMargin := min(align(StackLength div 20,2),STACK_MARGIN_MAX);
  341. { Initialize ExitProc }
  342. ExitProc:=Nil;
  343. SysInitQDOS;
  344. {$ifndef FPC_QL_USE_OSHEAP}
  345. { Setup heap }
  346. InitHeap;
  347. {$else FPC_QL_USE_OSHEAP}
  348. // InitOSHeap;
  349. {$endif FPC_QL_USE_OSHEAP}
  350. SysInitExceptions;
  351. {$ifdef FPC_HAS_FEATURE_UNICODESTRINGS}
  352. InitUnicodeStringManager;
  353. {$endif FPC_HAS_FEATURE_UNICODESTRINGS}
  354. { Setup stdin, stdout and stderr }
  355. SysInitStdIO;
  356. { Reset IO Error }
  357. InOutRes:=0;
  358. { Setup command line arguments }
  359. SysInitParamsAndEnv;
  360. {$ifdef FPC_HAS_FEATURE_THREADING}
  361. InitSystemThreads;
  362. {$endif FPC_HAS_FEATURE_THREADING}
  363. end.