system.pp 9.1 KB

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