system.pp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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. {$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. asm
  240. mov al, byte [exitcode]
  241. mov ah, 4Ch
  242. int 21h
  243. end;
  244. end;
  245. {*****************************************************************************
  246. SystemUnit Initialization
  247. *****************************************************************************}
  248. procedure InitNearHeap;
  249. begin
  250. SetMemoryManager(TinyHeapMemoryManager);
  251. RegisterTinyHeapBlock(__nearheap_start, ptruint(__nearheap_end) - ptruint(__nearheap_start));
  252. end;
  253. function CheckLFN:boolean;
  254. var
  255. regs : Registers;
  256. RootName : pchar;
  257. buf : array [0..31] of char;
  258. begin
  259. { Check LFN API on drive c:\ }
  260. RootName:='C:\';
  261. { Call 'Get Volume Information' ($71A0) }
  262. regs.AX:=$71a0;
  263. regs.ES:=Seg(buf);
  264. regs.DI:=Ofs(buf);
  265. regs.CX:=32;
  266. regs.DS:=Seg(RootName^);
  267. regs.DX:=Ofs(RootName^);
  268. MsDos_Carry(regs);
  269. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  270. CheckLFN:=(regs.Flags and fCarry=0) and (regs.BX and $4000=$4000);
  271. end;
  272. procedure SysInitStdIO;
  273. begin
  274. OpenStdIO(Input,fmInput,StdInputHandle);
  275. OpenStdIO(Output,fmOutput,StdOutputHandle);
  276. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  277. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  278. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  279. end;
  280. function GetProcessID: SizeUInt;
  281. begin
  282. GetProcessID := dos_psp;
  283. end;
  284. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  285. begin
  286. result := stklen;
  287. end;
  288. begin
  289. StackTop := __stktop;
  290. StackBottom := __stkbottom;
  291. StackLength := __stktop - __stkbottom;
  292. InstallInterruptHandlers;
  293. if DetectFPU then
  294. SysInitFPU;
  295. { To be set if this is a GUI or console application }
  296. IsConsole := TRUE;
  297. { To be set if this is a library and not a program }
  298. IsLibrary := FALSE;
  299. { Setup heap }
  300. InitNearHeap;
  301. SysInitExceptions;
  302. initunicodestringmanager;
  303. { Setup stdin, stdout and stderr }
  304. SysInitStdIO;
  305. { Use LFNSupport LFN }
  306. LFNSupport:=CheckLFN;
  307. if LFNSupport then
  308. begin
  309. FileNameCasePreserving:=true;
  310. AllFilesMask := '*';
  311. end
  312. else
  313. AllFilesMask := '*.*';
  314. { Reset IO Error }
  315. InOutRes:=0;
  316. initvariantmanager;
  317. end.