system.pp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. function SetQLJobName(const s: string): longint;
  57. function GetQLJobName: string;
  58. function GetQLJobNamePtr: pointer;
  59. implementation
  60. {$define FPC_SYSTEM_HAS_STACKTOP}
  61. {$define FPC_SYSTEM_HAS_BACKTRACESTR}
  62. {$if defined(FPUSOFT)}
  63. {$define fpc_softfpu_implementation}
  64. {$define softfpu_compiler_mul32to64}
  65. {$define softfpu_inline}
  66. {$i softfpu.pp}
  67. {$undef fpc_softfpu_implementation}
  68. { we get these functions and types from the softfpu code }
  69. {$define FPC_SYSTEM_HAS_float64}
  70. {$define FPC_SYSTEM_HAS_float32}
  71. {$define FPC_SYSTEM_HAS_flag}
  72. {$define FPC_SYSTEM_HAS_extractFloat64Frac0}
  73. {$define FPC_SYSTEM_HAS_extractFloat64Frac1}
  74. {$define FPC_SYSTEM_HAS_extractFloat64Exp}
  75. {$define FPC_SYSTEM_HAS_extractFloat64Sign}
  76. {$define FPC_SYSTEM_HAS_ExtractFloat32Frac}
  77. {$define FPC_SYSTEM_HAS_extractFloat32Exp}
  78. {$define FPC_SYSTEM_HAS_extractFloat32Sign}
  79. {$endif defined(FPUSOFT)}
  80. {$i system.inc}
  81. {$ifdef FPC_QL_USE_OSHEAP}
  82. {$i osheap.inc}
  83. {$endif FPC_QL_USE_OSHEAP}
  84. function GetProcessID:SizeUInt;
  85. begin
  86. GetProcessID := mt_inf(nil, nil);
  87. end;
  88. {*****************************************************************************
  89. ParamStr
  90. *****************************************************************************}
  91. var
  92. args: PChar;
  93. { number of args }
  94. function ParamCount: LongInt;
  95. begin
  96. ParamCount:=argc;
  97. end;
  98. { argument number l }
  99. function ParamStr(l: LongInt): string;
  100. begin
  101. if (l >= 0) and (l <= argc) then
  102. ParamStr:=argv[l]
  103. else
  104. ParamStr:='';
  105. end;
  106. procedure SysInitParamsAndEnv;
  107. var
  108. i,j : longint;
  109. c : char;
  110. argv_size : longint;
  111. const
  112. word_separators=[' ',#0];
  113. begin
  114. argc:=0;
  115. argv:=nil;
  116. args:=GetMem(QL_CommandLineLen+1);
  117. if not assigned(args) then
  118. exit;
  119. Move(QL_CommandLine^,args^,QL_CommandLineLen);
  120. args[QL_CommandLineLen]:=#0;
  121. i:=0;
  122. c:=' ';
  123. while args[i]<>#0 do
  124. begin
  125. if (c in word_separators) and not (args[i] in word_separators) then
  126. inc(argc);
  127. c:=args[i];
  128. inc(i);
  129. end;
  130. { +2 is because argv[0] should be program name,
  131. and argv[argc+1] is argv array terminator }
  132. argv:=GetMem((argc+2)*sizeof(pointer));
  133. if not assigned(argv) then
  134. begin
  135. argc:=0;
  136. exit;
  137. end;
  138. argv[argc+1]:=nil;
  139. { FIX ME: for now the 0th argument (program name) is just always empty }
  140. argv[0]:=#0;
  141. i:=0;
  142. j:=1;
  143. c:=' ';
  144. while args[i]<>#0 do
  145. begin
  146. if (c in word_separators) and not (args[i] in word_separators) then
  147. begin
  148. argv[j]:=@args[i];
  149. inc(j);
  150. end;
  151. c:=args[i];
  152. if (c in word_separators) then
  153. args[i]:=#0;
  154. inc(i);
  155. end;
  156. end;
  157. procedure randomize;
  158. begin
  159. { Get the current date/time }
  160. randseed:=mt_rclck;
  161. end;
  162. {*****************************************************************************
  163. Platform specific custom calls
  164. *****************************************************************************}
  165. procedure PrintStr(ch: longint; const s: shortstring);
  166. begin
  167. io_sstrg(ch,-1,@s[1],ord(s[0]));
  168. end;
  169. procedure DebugStr(const s: shortstring); public name '_dbgstr';
  170. var
  171. i: longint;
  172. begin
  173. PrintStr(stdOutputHandle,s);
  174. for i:=0 to 10000 do begin end;
  175. end;
  176. var
  177. start_proc: byte; external name '_start';
  178. { WARNING! if you change this value, make sure there's enough
  179. buffer space for the job name in the startup code! }
  180. const
  181. JOB_NAME_MAX_LEN = 48;
  182. function SetQLJobName(const s: string): longint;
  183. var
  184. len: longint;
  185. begin
  186. SetQLJobName:=-1;
  187. if pword(@start_proc)[3] = $4afb then
  188. begin
  189. len:=length(s);
  190. if len > JOB_NAME_MAX_LEN then
  191. len:=JOB_NAME_MAX_LEN;
  192. Move(s[1],pword(@start_proc)[5],len);
  193. pword(@start_proc)[4]:=len;
  194. SetQLJobName:=len;
  195. end;
  196. end;
  197. function GetQLJobName: string;
  198. var
  199. len: longint;
  200. begin
  201. GetQLJobName:='';
  202. if pword(@start_proc)[3] = $4afb then
  203. begin
  204. len:=pword(@start_proc)[4];
  205. if len <= JOB_NAME_MAX_LEN then
  206. begin
  207. SetLength(GetQLJobName,len);
  208. Move(pword(@start_proc)[5],GetQLJobName[1],len);
  209. end;
  210. end;
  211. end;
  212. function GetQLJobNamePtr: pointer;
  213. begin
  214. GetQLJobNamePtr:=nil;
  215. if pword(@start_proc)[3] = $4afb then
  216. begin
  217. GetQLJobNamePtr:=@pword(@start_proc)[4];
  218. end;
  219. end;
  220. {*****************************************************************************
  221. System Dependent Entry code
  222. *****************************************************************************}
  223. var
  224. jobStackDataPtr: pointer; external name '__stackpointer_on_entry';
  225. program_name: shortstring; external name '__fpc_program_name';
  226. { QL/QDOS specific startup }
  227. procedure SysInitQDOS;
  228. var
  229. r: TQLRect;
  230. begin
  231. QL_ChannelIDNum:=pword(jobStackDataPtr)[0];
  232. QL_ChannelIDs:=@pword(jobStackDataPtr)[1];
  233. QL_CommandLineLen:=pword(@QL_ChannelIDs[QL_ChannelIDNum])[0];
  234. QL_CommandLine:=@pword(@QL_ChannelIDs[QL_ChannelIDNum])[1];
  235. SetQLJobName(program_name);
  236. stdInputHandle:=io_open('con_',Q_OPEN);
  237. stdOutputHandle:=stdInputHandle;
  238. stdErrorHandle:=stdInputHandle;
  239. r.q_width:=512;
  240. r.q_height:=256;
  241. r.q_x:=0;
  242. r.q_y:=0;
  243. sd_wdef(stdInputHandle,-1,2,1,@r);
  244. sd_clear(stdInputHandle,-1);
  245. end;
  246. {*****************************************************************************
  247. System Dependent Exit code
  248. *****************************************************************************}
  249. procedure haltproc(e:longint); external name '_haltproc';
  250. procedure system_exit;
  251. const
  252. anyKey: pchar = 'Press any key to exit';
  253. begin
  254. if assigned(args) then
  255. FreeMem(args);
  256. if assigned(argv) then
  257. FreeMem(argv);
  258. io_sstrg(stdOutputHandle, -1, anyKey, length(anykey));
  259. io_fbyte(stdInputHandle, -1);
  260. stdInputHandle:=UnusedHandle;
  261. stdOutputHandle:=UnusedHandle;
  262. stdErrorHandle:=UnusedHandle;
  263. haltproc(exitcode);
  264. end;
  265. {*****************************************************************************
  266. System Unit Initialization
  267. *****************************************************************************}
  268. procedure SysInitStdIO;
  269. begin
  270. OpenStdIO(Input,fmInput,StdInputHandle);
  271. OpenStdIO(Output,fmOutput,StdOutputHandle);
  272. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  273. {$ifndef FPC_STDOUT_TRUE_ALIAS}
  274. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  275. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  276. {$endif FPC_STDOUT_TRUE_ALIAS}
  277. end;
  278. function CheckInitialStkLen (StkLen: SizeUInt): SizeUInt;
  279. begin
  280. CheckInitialStkLen := StkLen;
  281. end;
  282. begin
  283. StackLength := CheckInitialStkLen (InitialStkLen);
  284. StackBottom := StackTop - StackLength;
  285. StackMargin := min(align(StackLength div 20,2),STACK_MARGIN_MAX);
  286. { Initialize ExitProc }
  287. ExitProc:=Nil;
  288. SysInitQDOS;
  289. {$ifndef FPC_QL_USE_OSHEAP}
  290. { Setup heap }
  291. InitHeap;
  292. {$else FPC_QL_USE_OSHEAP}
  293. // InitOSHeap;
  294. {$endif FPC_QL_USE_OSHEAP}
  295. SysInitExceptions;
  296. {$ifdef FPC_HAS_FEATURE_UNICODESTRINGS}
  297. InitUnicodeStringManager;
  298. {$endif FPC_HAS_FEATURE_UNICODESTRINGS}
  299. { Setup stdin, stdout and stderr }
  300. SysInitStdIO;
  301. { Reset IO Error }
  302. InOutRes:=0;
  303. { Setup command line arguments }
  304. SysInitParamsAndEnv;
  305. {$ifdef FPC_HAS_FEATURE_THREADING}
  306. InitSystemThreads;
  307. {$endif FPC_HAS_FEATURE_THREADING}
  308. end.