system.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. unit system;
  2. interface
  3. {$DEFINE FPC_NO_DEFAULT_HEAP}
  4. {$DEFINE FPC_INCLUDE_SOFTWARE_MUL}
  5. {$DEFINE FPC_INCLUDE_SOFTWARE_MOD_DIV}
  6. {$DEFINE FPC_USE_SMALL_DEFAULTSTACKSIZE}
  7. { To avoid warnings in thread.inc code,
  8. but value must be really given after
  9. systemh.inc is included otherwise the
  10. $mode switch is not effective }
  11. {$DEFINE HAS_CMDLINE}
  12. {$DEFINE DISABLE_NO_DYNLIBS_MANAGER}
  13. {$DEFINE FPC_SYSTEM_HAS_SYSDLH}
  14. {$I systemh.inc}
  15. {$IFDEF FPC_X86_DATA_NEAR}
  16. {$I locheaph.inc}
  17. {$ELSE FPC_X86_DATA_NEAR}
  18. {$I glbheaph.inc}
  19. {$ENDIF FPC_X86_DATA_NEAR}
  20. const
  21. LineEnding = #13#10;
  22. { LFNSupport is a variable here, defined below!!! }
  23. DirectorySeparator = '\';
  24. DriveSeparator = ':';
  25. ExtensionSeparator = '.';
  26. PathSeparator = ';';
  27. AllowDirectorySeparators : set of char = ['\','/'];
  28. AllowDriveSeparators : set of char = [':'];
  29. { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! }
  30. maxExitCode = 255;
  31. MaxPathLen = 256;
  32. const
  33. { Default filehandles }
  34. UnusedHandle = $ffff;{ instead of -1, as it is a word value}
  35. StdInputHandle = 0;
  36. StdOutputHandle = 1;
  37. StdErrorHandle = 2;
  38. FileNameCaseSensitive : boolean = false;
  39. FileNameCasePreserving: boolean = false;
  40. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  41. sLineBreak = LineEnding;
  42. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  43. { Default memory segments (Tp7 compatibility) }
  44. { seg0040: Word = $0040;
  45. segA000: Word = $A000;
  46. segB000: Word = $B000;
  47. segB800: Word = $B800;}
  48. type
  49. LPSTR = ^Char;far;
  50. PFarChar = ^Char;far;
  51. PHugeChar = ^Char;huge;
  52. var
  53. { Mem[] support }
  54. mem : array[0..$7fff-1] of byte absolute $0:$0;
  55. memw : array[0..($7fff div sizeof(word))-1] of word absolute $0:$0;
  56. meml : array[0..($7fff div sizeof(longint))-1] of longint absolute $0:$0;
  57. { C-compatible arguments and environment }
  58. argc:longint; //!! public name 'operatingsystem_parameter_argc';
  59. argv:PPchar; //!! public name 'operatingsystem_parameter_argv';
  60. envp:PPchar; //!! public name 'operatingsystem_parameter_envp';
  61. dos_argv0 : pchar; //!! public name 'dos_argv0';
  62. { The DOS Program Segment Prefix segment (TP7 compatibility) }
  63. PrefixSeg:Word;public name '__fpc_PrefixSeg';
  64. { BP7 compatible windows variables }
  65. { In C, these are the parameters to WinMain }
  66. CmdLine: LPSTR;public name '__fpc_CmdLine';
  67. CmdShow: SmallInt;public name '__fpc_CmdShow';
  68. HInstance: Word{HINST};public name '__fpc_HInstance';
  69. HPrevInst: Word{HINST};public name '__fpc_HPrevInst';
  70. { The value that needs to be added to the segment to move the pointer by
  71. 64K bytes (BP7 compatibility) }
  72. SelectorInc: Word;public name '__fpc_SelectorInc';
  73. { SaveInt00: FarPointer;public name '__SaveInt00';}
  74. AllFilesMask: string [3];
  75. {$ifndef RTLLITE}
  76. { System info }
  77. LFNSupport : boolean;
  78. {$ELSE RTLLITE}
  79. const
  80. LFNSupport = false;
  81. {$endif RTLLITE}
  82. implementation
  83. const
  84. fCarry = 1;
  85. { used for an offset fixup for accessing the proc parameters in asm routines
  86. that use nostackframe. We can't use the parameter name directly, because
  87. i8086 doesn't support sp relative addressing. }
  88. {$ifdef FPC_X86_CODE_FAR}
  89. extra_param_offset = 2;
  90. {$else FPC_X86_CODE_FAR}
  91. extra_param_offset = 0;
  92. {$endif FPC_X86_CODE_FAR}
  93. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  94. extra_data_offset = 2;
  95. {$else}
  96. extra_data_offset = 0;
  97. {$endif}
  98. type
  99. PFarByte = ^Byte;far;
  100. PFarWord = ^Word;far;
  101. { structure, located at DS:0, initialized by InitTask }
  102. PAutoDataSegHeader = ^TAutoDataSegHeader;
  103. TAutoDataSegHeader = record
  104. null: Word;
  105. oOldSP: Word;
  106. hOldSS: Word;
  107. pLocalHeap: Word;
  108. pAtomTable: Word;
  109. pStackTop: Word;
  110. pStackMin: Word;
  111. pStackBot: Word;
  112. end;
  113. {$I registers.inc}
  114. procedure MsDos(var Regs: Registers); external name 'FPC_MSDOS';
  115. { invokes int 21h with the carry flag set on entry; used for the LFN functions
  116. to ensure that the carry flag is set on exit on older DOS versions which don't
  117. support them }
  118. procedure MsDos_Carry(var Regs: Registers); external name 'FPC_MSDOS_CARRY';
  119. {$define SYSTEMUNIT}
  120. {$I wintypes.inc}
  121. {$I winprocsh.inc}
  122. {$I winprocs.inc}
  123. { in protected mode, loading invalid values into segment registers causes an
  124. exception, so we use this function to initialize our Registers structure }
  125. procedure ZeroSegRegs(var regs: Registers); inline;
  126. begin
  127. regs.DS:=0;
  128. regs.ES:=0;
  129. end;
  130. {$I system.inc}
  131. {$IFDEF FPC_X86_DATA_NEAR}
  132. {$I locheap.inc}
  133. {$ELSE FPC_X86_DATA_NEAR}
  134. {$I glbheap.inc}
  135. {$ENDIF FPC_X86_DATA_NEAR}
  136. {*****************************************************************************
  137. ParamStr/Randomize
  138. *****************************************************************************}
  139. {function GetProgramName: string;
  140. var
  141. dos_env_seg: Word;
  142. ofs: Word;
  143. Ch, Ch2: Char;
  144. begin
  145. if dos_version < $300 then
  146. begin
  147. GetProgramName := '';
  148. exit;
  149. end;
  150. dos_env_seg := PFarWord(Ptr(PrefixSeg, $2C))^;
  151. ofs := 1;
  152. repeat
  153. Ch := PFarChar(Ptr(dos_env_seg,ofs - 1))^;
  154. Ch2 := PFarChar(Ptr(dos_env_seg,ofs))^;
  155. if (Ch = #0) and (Ch2 = #0) then
  156. begin
  157. Inc(ofs, 3);
  158. GetProgramName := '';
  159. repeat
  160. Ch := PFarChar(Ptr(dos_env_seg,ofs))^;
  161. if Ch <> #0 then
  162. GetProgramName := GetProgramName + Ch;
  163. Inc(ofs);
  164. if ofs = 0 then
  165. begin
  166. GetProgramName := '';
  167. exit;
  168. end;
  169. until Ch = #0;
  170. exit;
  171. end;
  172. Inc(ofs);
  173. if ofs = 0 then
  174. begin
  175. GetProgramName := '';
  176. exit;
  177. end;
  178. until false;
  179. end;}
  180. function GetArg(ArgNo: Integer; out ArgResult: string): Integer;
  181. var
  182. I: Integer;
  183. InArg: Boolean;
  184. begin
  185. ArgResult := '';
  186. I := 0;
  187. InArg := False;
  188. GetArg := 0;
  189. while CmdLine[I]<>#0 do
  190. begin
  191. if not InArg and (CmdLine[I] <> ' ') then
  192. begin
  193. InArg := True;
  194. Inc(GetArg);
  195. end;
  196. if InArg and (CmdLine[I] = ' ') then
  197. InArg := False;
  198. if InArg and (GetArg = ArgNo) then
  199. ArgResult := ArgResult + CmdLine[I];
  200. Inc(I);
  201. end;
  202. end;
  203. function paramcount : longint;
  204. var
  205. tmpstr: string;
  206. begin
  207. paramcount := GetArg(-1, tmpstr);
  208. end;
  209. function paramstr(l : longint) : string;
  210. begin
  211. if l = 0 then
  212. paramstr := ''{GetProgramName}
  213. else
  214. GetArg(l, paramstr);
  215. end;
  216. procedure randomize;
  217. begin
  218. randseed:=GetTickCount;
  219. end;
  220. {****************************************************************************
  221. Error Message writing using messageboxes
  222. ****************************************************************************}
  223. const
  224. ErrorBufferLength = 1024;
  225. ErrorMessageBoxFlags = MB_OK or MB_ICONHAND or MB_TASKMODAL;
  226. var
  227. ErrorBuf : array[0..ErrorBufferLength] of char;
  228. ErrorLen : SizeInt;
  229. procedure ErrorWrite(Var F: TextRec);
  230. {
  231. An error message should always end with #13#10#13#10
  232. }
  233. var
  234. i : SizeInt;
  235. Begin
  236. while F.BufPos>0 do
  237. begin
  238. begin
  239. if F.BufPos+ErrorLen>ErrorBufferLength then
  240. i:=ErrorBufferLength-ErrorLen
  241. else
  242. i:=F.BufPos;
  243. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  244. inc(ErrorLen,i);
  245. ErrorBuf[ErrorLen]:=#0;
  246. end;
  247. if ErrorLen=ErrorBufferLength then
  248. begin
  249. if not NoErrMsg then
  250. {$IFDEF FPC_X86_DATA_NEAR}
  251. MessageBox(0,Ptr(Seg(ErrorBuf),Ofs(ErrorBuf)),nil,ErrorMessageBoxFlags);
  252. {$ELSE FPC_X86_DATA_NEAR}
  253. MessageBox(0,@ErrorBuf,nil,ErrorMessageBoxFlags);
  254. {$ENDIF FPC_X86_DATA_NEAR}
  255. ErrorLen:=0;
  256. end;
  257. Dec(F.BufPos,i);
  258. end;
  259. End;
  260. procedure ShowErrMsg;
  261. begin
  262. if ErrorLen>0 then
  263. begin
  264. {$IFDEF FPC_X86_DATA_NEAR}
  265. MessageBox(0,Ptr(Seg(ErrorBuf),Ofs(ErrorBuf)),nil,ErrorMessageBoxFlags);
  266. {$ELSE FPC_X86_DATA_NEAR}
  267. MessageBox(0,@ErrorBuf,nil,ErrorMessageBoxFlags);
  268. {$ENDIF FPC_X86_DATA_NEAR}
  269. ErrorLen:=0;
  270. end;
  271. end;
  272. procedure ErrorClose(Var F: TextRec);
  273. begin
  274. ShowErrMsg;
  275. end;
  276. procedure ErrorOpen(Var F: TextRec);
  277. Begin
  278. TextRec(F).Handle:=StdErrorHandle;
  279. TextRec(F).Mode:=fmOutput;
  280. TextRec(F).InOutFunc:=@ErrorWrite;
  281. TextRec(F).FlushFunc:=@ErrorWrite;
  282. TextRec(F).CloseFunc:=@ErrorClose;
  283. ErrorLen:=0;
  284. End;
  285. procedure AssignError(Var T: Text);
  286. begin
  287. Assign(T,'');
  288. TextRec(T).OpenFunc:=@ErrorOpen;
  289. Rewrite(T);
  290. end;
  291. {*****************************************************************************
  292. System Dependent Exit code
  293. *****************************************************************************}
  294. procedure system_exit;
  295. {var
  296. h : byte;}
  297. begin
  298. (* RestoreInterruptHandlers;
  299. for h:=0 to max_files-1 do
  300. if openfiles[h] then
  301. begin
  302. {$ifdef SYSTEMDEBUG}
  303. writeln(stderr,'file ',opennames[h],' not closed at exit');
  304. {$endif SYSTEMDEBUG}
  305. if h>=5 then
  306. do_close(h);
  307. end;
  308. {$ifndef FPC_MM_TINY}
  309. if not CheckNullArea then
  310. writeln(stderr, 'Nil pointer assignment');
  311. {$endif FPC_MM_TINY}*)
  312. Close(stderr);
  313. Close(stdout);
  314. Close(erroutput);
  315. Close(Input);
  316. Close(Output);
  317. ShowErrMsg;
  318. asm
  319. mov al, byte [exitcode]
  320. mov ah, 4Ch
  321. int 21h
  322. end;
  323. end;
  324. {*****************************************************************************
  325. SystemUnit Initialization
  326. *****************************************************************************}
  327. procedure InitWin16Heap;
  328. begin
  329. {$ifdef FPC_X86_DATA_NEAR}
  330. SetMemoryManager(LocalHeapMemoryManager);
  331. {$else FPC_X86_DATA_NEAR}
  332. SetMemoryManager(GlobalHeapMemoryManager);
  333. {$endif FPC_X86_DATA_NEAR}
  334. end;
  335. function CheckLFN:boolean;
  336. var
  337. regs : Registers;
  338. RootName : pchar;
  339. buf : array [0..31] of char;
  340. begin
  341. { Check LFN API on drive c:\ }
  342. RootName:='C:\';
  343. { Call 'Get Volume Information' ($71A0) }
  344. { no need to ZeroSegRegs(regs), because we initialize both DS and ES }
  345. regs.AX:=$71a0;
  346. regs.ES:=Seg(buf);
  347. regs.DI:=Ofs(buf);
  348. regs.CX:=32;
  349. regs.DS:=Seg(RootName^);
  350. regs.DX:=Ofs(RootName^);
  351. MsDos_Carry(regs);
  352. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  353. CheckLFN:=(regs.Flags and fCarry=0) and (regs.BX and $4000=$4000);
  354. end;
  355. procedure SysInitStdIO;
  356. begin
  357. AssignError(stderr);
  358. AssignError(StdOut);
  359. Assign(Output,'');
  360. Assign(Input,'');
  361. Assign(ErrOutput,'');
  362. end;
  363. function GetProcessID: SizeUInt;
  364. begin
  365. GetProcessID := PrefixSeg;
  366. end;
  367. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  368. begin
  369. result := stklen;
  370. end;
  371. begin
  372. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  373. with PAutoDataSegHeader(Ptr(DSeg,0))^ do
  374. begin
  375. StackBottom := Ptr(SSeg,pStackTop);
  376. StackLength := pStackBot-pStackTop;
  377. end;
  378. {$else}
  379. with PAutoDataSegHeader(0)^ do
  380. begin
  381. StackBottom := NearPointer(pStackTop);
  382. StackLength := pStackBot-pStackTop;
  383. end;
  384. {$endif}
  385. { To be set if this is a GUI or console application }
  386. IsConsole := FALSE;
  387. { To be set if this is a library and not a program }
  388. IsLibrary := FALSE;
  389. { Setup heap }
  390. InitWin16Heap;
  391. SysInitExceptions;
  392. initunicodestringmanager;
  393. { Setup stdin, stdout and stderr }
  394. SysInitStdIO;
  395. { Use LFNSupport LFN }
  396. LFNSupport:=CheckLFN;
  397. if LFNSupport then
  398. begin
  399. FileNameCasePreserving:=true;
  400. AllFilesMask := '*';
  401. end
  402. else
  403. AllFilesMask := '*.*';
  404. { Reset IO Error }
  405. InOutRes:=0;
  406. end.