system.pp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. unit system;
  2. interface
  3. {$DEFINE FPC_NO_DEFAULT_HEAP}
  4. {$DEFINE FPC_INCLUDE_SOFTWARE_MUL}
  5. {$DEFINE FPC_INCLUDE_SOFTWARE_MOD_DIV}
  6. {$DEFINE FPC_USE_SMALL_DEFAULTSTACKSIZE}
  7. { To avoid warnings in thread.inc code,
  8. but value must be really given after
  9. systemh.inc is included otherwise the
  10. $mode switch is not effective }
  11. {$I systemh.inc}
  12. const
  13. LineEnding = #13#10;
  14. { LFNSupport is a variable here, defined below!!! }
  15. DirectorySeparator = '\';
  16. DriveSeparator = ':';
  17. ExtensionSeparator = '.';
  18. PathSeparator = ';';
  19. AllowDirectorySeparators : set of char = ['\','/'];
  20. AllowDriveSeparators : set of char = [':'];
  21. { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! }
  22. maxExitCode = 255;
  23. MaxPathLen = 256;
  24. const
  25. { Default filehandles }
  26. UnusedHandle = $ffff;{ instead of -1, as it is a word value}
  27. StdInputHandle = 0;
  28. StdOutputHandle = 1;
  29. StdErrorHandle = 2;
  30. FileNameCaseSensitive : boolean = false;
  31. FileNameCasePreserving: boolean = false;
  32. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  33. sLineBreak = LineEnding;
  34. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  35. { Default memory segments (Tp7 compatibility) }
  36. seg0040: Word = $0040;
  37. segA000: Word = $A000;
  38. segB000: Word = $B000;
  39. segB800: Word = $B800;
  40. var
  41. { Mem[] support }
  42. mem : array[0..$7fff-1] of byte absolute $0:$0;
  43. memw : array[0..($7fff div sizeof(word))-1] of word absolute $0:$0;
  44. meml : array[0..($7fff div sizeof(longint))-1] of longint absolute $0:$0;
  45. { C-compatible arguments and environment }
  46. argc:longint; //!! public name 'operatingsystem_parameter_argc';
  47. argv:PPchar; //!! public name 'operatingsystem_parameter_argv';
  48. envp:PPchar; //!! public name 'operatingsystem_parameter_envp';
  49. dos_argv0 : pchar; //!! public name 'dos_argv0';
  50. dos_psp:Word;public name 'dos_psp';
  51. SaveInt00: FarPointer;public name '__SaveInt00';
  52. AllFilesMask: string [3];
  53. {$ifndef RTLLITE}
  54. { System info }
  55. LFNSupport : boolean;
  56. {$ELSE RTLLITE}
  57. const
  58. LFNSupport = false;
  59. {$endif RTLLITE}
  60. implementation
  61. procedure DebugWrite(const S: string); forward;
  62. procedure DebugWriteLn(const S: string); forward;
  63. const
  64. fCarry = 1;
  65. { used for an offset fixup for accessing the proc parameters in asm routines
  66. that use nostackframe. We can't use the parameter name directly, because
  67. i8086 doesn't support sp relative addressing. }
  68. {$ifdef FPC_X86_CODE_FAR}
  69. extra_param_offset = 2;
  70. {$else FPC_X86_CODE_FAR}
  71. extra_param_offset = 0;
  72. {$endif FPC_X86_CODE_FAR}
  73. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  74. extra_data_offset = 2;
  75. {$else}
  76. extra_data_offset = 0;
  77. {$endif}
  78. type
  79. PFarByte = ^Byte;far;
  80. PFarChar = ^Char;far;
  81. PFarWord = ^Word;far;
  82. var
  83. __stktop : pointer;public name '__stktop';
  84. __stkbottom : pointer;public name '__stkbottom';
  85. __nearheap_start: pointer;public name '__nearheap_start';
  86. __nearheap_end: pointer;public name '__nearheap_end';
  87. dos_version:Word;public name 'dos_version';
  88. {$I registers.inc}
  89. procedure Intr(IntNo: Byte; var Regs: Registers); external name 'FPC_INTR';
  90. procedure MsDos(var Regs: Registers); external name 'FPC_MSDOS';
  91. { invokes int 21h with the carry flag set on entry; used for the LFN functions
  92. to ensure that the carry flag is set on exit on older DOS versions which don't
  93. support them }
  94. procedure MsDos_Carry(var Regs: Registers); external name 'FPC_MSDOS_CARRY';
  95. procedure InstallInterruptHandlers; external name 'FPC_INSTALL_INTERRUPT_HANDLERS';
  96. procedure RestoreInterruptHandlers; external name 'FPC_RESTORE_INTERRUPT_HANDLERS';
  97. function CheckNullArea: Boolean; external name 'FPC_CHECK_NULLAREA';
  98. {$I system.inc}
  99. {$I tinyheap.inc}
  100. procedure DebugWrite(const S: string);
  101. begin
  102. asm
  103. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  104. push ds
  105. lds si, S
  106. {$else}
  107. mov si, S
  108. {$endif}
  109. {$ifdef FPC_ENABLED_CLD}
  110. cld
  111. {$endif FPC_ENABLED_CLD}
  112. lodsb
  113. mov cl, al
  114. xor ch, ch
  115. jcxz @@zero_length
  116. mov ah, 2
  117. @@1:
  118. lodsb
  119. mov dl, al
  120. int 21h
  121. loop @@1
  122. @@zero_length:
  123. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  124. pop ds
  125. {$endif}
  126. end ['ax','bx','cx','dx','si','di'];
  127. end;
  128. procedure DebugWriteLn(const S: string);
  129. begin
  130. DebugWrite(S);
  131. DebugWrite(#13#10);
  132. end;
  133. {*****************************************************************************
  134. ParamStr/Randomize
  135. *****************************************************************************}
  136. function GetProgramName: string;
  137. var
  138. dos_env_seg: Word;
  139. ofs: Word;
  140. Ch, Ch2: Char;
  141. begin
  142. if dos_version < $300 then
  143. begin
  144. GetProgramName := '';
  145. exit;
  146. end;
  147. dos_env_seg := PFarWord(Ptr(dos_psp, $2C))^;
  148. ofs := 1;
  149. repeat
  150. Ch := PFarChar(Ptr(dos_env_seg,ofs - 1))^;
  151. Ch2 := PFarChar(Ptr(dos_env_seg,ofs))^;
  152. if (Ch = #0) and (Ch2 = #0) then
  153. begin
  154. Inc(ofs, 3);
  155. GetProgramName := '';
  156. repeat
  157. Ch := PFarChar(Ptr(dos_env_seg,ofs))^;
  158. if Ch <> #0 then
  159. GetProgramName := GetProgramName + Ch;
  160. Inc(ofs);
  161. if ofs = 0 then
  162. begin
  163. GetProgramName := '';
  164. exit;
  165. end;
  166. until Ch = #0;
  167. exit;
  168. end;
  169. Inc(ofs);
  170. if ofs = 0 then
  171. begin
  172. GetProgramName := '';
  173. exit;
  174. end;
  175. until false;
  176. end;
  177. function GetCommandLine: string;
  178. var
  179. len, I: Integer;
  180. begin
  181. len := PFarByte(Ptr(dos_psp, $80))^;
  182. SetLength(GetCommandLine, len);
  183. for I := 1 to len do
  184. GetCommandLine[I] := PFarChar(Ptr(dos_psp, $80 + I))^;
  185. end;
  186. function GetArg(ArgNo: Integer; out ArgResult: string): Integer;
  187. var
  188. cmdln: string;
  189. I: Integer;
  190. InArg: Boolean;
  191. begin
  192. cmdln := GetCommandLine;
  193. ArgResult := '';
  194. I := 1;
  195. InArg := False;
  196. GetArg := 0;
  197. for I := 1 to Length(cmdln) do
  198. begin
  199. if not InArg and (cmdln[I] <> ' ') then
  200. begin
  201. InArg := True;
  202. Inc(GetArg);
  203. end;
  204. if InArg and (cmdln[I] = ' ') then
  205. InArg := False;
  206. if InArg and (GetArg = ArgNo) then
  207. ArgResult := ArgResult + cmdln[I];
  208. end;
  209. end;
  210. function paramcount : longint;
  211. var
  212. tmpstr: string;
  213. begin
  214. paramcount := GetArg(-1, tmpstr);
  215. end;
  216. function paramstr(l : longint) : string;
  217. begin
  218. if l = 0 then
  219. paramstr := GetProgramName
  220. else
  221. GetArg(l, paramstr);
  222. end;
  223. procedure randomize;
  224. var
  225. hl : longint;
  226. regs : Registers;
  227. begin
  228. regs.AH:=$2C;
  229. MsDos(regs);
  230. hl:=regs.DX;
  231. randseed:=hl*$10000+ regs.CX;
  232. end;
  233. {*****************************************************************************
  234. System Dependent Exit code
  235. *****************************************************************************}
  236. procedure system_exit;
  237. var
  238. h : byte;
  239. begin
  240. RestoreInterruptHandlers;
  241. for h:=0 to max_files-1 do
  242. if openfiles[h] then
  243. begin
  244. {$ifdef SYSTEMDEBUG}
  245. writeln(stderr,'file ',opennames[h],' not closed at exit');
  246. {$endif SYSTEMDEBUG}
  247. if h>=5 then
  248. do_close(h);
  249. end;
  250. if not CheckNullArea then
  251. writeln(stderr, 'Nil pointer assignment');
  252. asm
  253. mov al, byte [exitcode]
  254. mov ah, 4Ch
  255. int 21h
  256. end;
  257. end;
  258. {*****************************************************************************
  259. SystemUnit Initialization
  260. *****************************************************************************}
  261. procedure InitNearHeap;
  262. begin
  263. SetMemoryManager(TinyHeapMemoryManager);
  264. RegisterTinyHeapBlock(__nearheap_start, ptruint(__nearheap_end) - ptruint(__nearheap_start));
  265. end;
  266. function CheckLFN:boolean;
  267. var
  268. regs : Registers;
  269. RootName : pchar;
  270. buf : array [0..31] of char;
  271. begin
  272. { Check LFN API on drive c:\ }
  273. RootName:='C:\';
  274. { Call 'Get Volume Information' ($71A0) }
  275. regs.AX:=$71a0;
  276. regs.ES:=Seg(buf);
  277. regs.DI:=Ofs(buf);
  278. regs.CX:=32;
  279. regs.DS:=Seg(RootName^);
  280. regs.DX:=Ofs(RootName^);
  281. MsDos_Carry(regs);
  282. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  283. CheckLFN:=(regs.Flags and fCarry=0) and (regs.BX and $4000=$4000);
  284. end;
  285. procedure SysInitStdIO;
  286. begin
  287. OpenStdIO(Input,fmInput,StdInputHandle);
  288. OpenStdIO(Output,fmOutput,StdOutputHandle);
  289. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  290. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  291. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  292. end;
  293. function GetProcessID: SizeUInt;
  294. begin
  295. GetProcessID := dos_psp;
  296. end;
  297. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  298. begin
  299. result := stklen;
  300. end;
  301. begin
  302. StackBottom := __stkbottom;
  303. StackLength := __stktop - __stkbottom;
  304. InstallInterruptHandlers;
  305. DetectFPU;
  306. if Test8087>0 then
  307. SysInitFPU;
  308. { To be set if this is a GUI or console application }
  309. IsConsole := TRUE;
  310. { To be set if this is a library and not a program }
  311. IsLibrary := FALSE;
  312. { Setup heap }
  313. InitNearHeap;
  314. SysInitExceptions;
  315. initunicodestringmanager;
  316. { Setup stdin, stdout and stderr }
  317. SysInitStdIO;
  318. { Use LFNSupport LFN }
  319. LFNSupport:=CheckLFN;
  320. if LFNSupport then
  321. begin
  322. FileNameCasePreserving:=true;
  323. AllFilesMask := '*';
  324. end
  325. else
  326. AllFilesMask := '*.*';
  327. { Reset IO Error }
  328. InOutRes:=0;
  329. initvariantmanager;
  330. end.