system.pp 8.4 KB

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