system.pp 8.8 KB

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