system.pp 8.0 KB

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