system.pp 11 KB

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