system.pp 9.3 KB

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