system.pp 8.3 KB

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