2
0

system.pp 10 KB

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