system.pp 8.8 KB

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