system.pp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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. {$I systemh.inc}
  13. {$IFDEF FPC_X86_DATA_NEAR}
  14. {$I locheaph.inc}
  15. {$ELSE FPC_X86_DATA_NEAR}
  16. { todo: implement a working win16 heap manager for the far data models }
  17. {$I tnyheaph.inc}
  18. {$ENDIF FPC_X86_DATA_NEAR}
  19. const
  20. LineEnding = #13#10;
  21. { LFNSupport is a variable here, defined below!!! }
  22. DirectorySeparator = '\';
  23. DriveSeparator = ':';
  24. ExtensionSeparator = '.';
  25. PathSeparator = ';';
  26. AllowDirectorySeparators : set of char = ['\','/'];
  27. AllowDriveSeparators : set of char = [':'];
  28. { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! }
  29. maxExitCode = 255;
  30. MaxPathLen = 256;
  31. const
  32. { Default filehandles }
  33. UnusedHandle = $ffff;{ instead of -1, as it is a word value}
  34. StdInputHandle = 0;
  35. StdOutputHandle = 1;
  36. StdErrorHandle = 2;
  37. FileNameCaseSensitive : boolean = false;
  38. FileNameCasePreserving: boolean = false;
  39. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  40. sLineBreak = LineEnding;
  41. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  42. { Default memory segments (Tp7 compatibility) }
  43. { seg0040: Word = $0040;
  44. segA000: Word = $A000;
  45. segB000: Word = $B000;
  46. segB800: Word = $B800;}
  47. type
  48. LPSTR = ^Char;far;
  49. PFarChar = ^Char;far;
  50. PHugeChar = ^Char;huge;
  51. var
  52. { Mem[] support }
  53. mem : array[0..$7fff-1] of byte absolute $0:$0;
  54. memw : array[0..($7fff div sizeof(word))-1] of word absolute $0:$0;
  55. meml : array[0..($7fff div sizeof(longint))-1] of longint absolute $0:$0;
  56. { C-compatible arguments and environment }
  57. argc:longint; //!! public name 'operatingsystem_parameter_argc';
  58. argv:PPchar; //!! public name 'operatingsystem_parameter_argv';
  59. envp:PPchar; //!! public name 'operatingsystem_parameter_envp';
  60. dos_argv0 : pchar; //!! public name 'dos_argv0';
  61. { The DOS Program Segment Prefix segment (TP7 compatibility) }
  62. PrefixSeg:Word;public name '__fpc_PrefixSeg';
  63. { BP7 compatible windows variables }
  64. { In C, these are the parameters to WinMain }
  65. CmdLine: LPSTR;public name '__fpc_CmdLine';
  66. CmdShow: SmallInt;public name '__fpc_CmdShow';
  67. HInstance: Word{HINST};public name '__fpc_HInstance';
  68. HPrevInst: Word{HINST};public name '__fpc_HPrevInst';
  69. { The value that needs to be added to the segment to move the pointer by
  70. 64K bytes (BP7 compatibility) }
  71. SelectorInc: Word;public name '__fpc_SelectorInc';
  72. { SaveInt00: FarPointer;public name '__SaveInt00';}
  73. AllFilesMask: string [3];
  74. {$ifndef RTLLITE}
  75. { System info }
  76. LFNSupport : boolean;
  77. {$ELSE RTLLITE}
  78. const
  79. LFNSupport = false;
  80. {$endif RTLLITE}
  81. procedure MessageBox(hWnd: word; lpText, lpCaption: LPSTR; uType: word);external 'USER';
  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. {$I system.inc}
  124. {$IFDEF FPC_X86_DATA_NEAR}
  125. {$I locheap.inc}
  126. {$ELSE FPC_X86_DATA_NEAR}
  127. { todo: implement a working win16 heap manager for the far data models }
  128. {$I tinyheap.inc}
  129. {$ENDIF FPC_X86_DATA_NEAR}
  130. {*****************************************************************************
  131. ParamStr/Randomize
  132. *****************************************************************************}
  133. {function GetProgramName: string;
  134. var
  135. dos_env_seg: Word;
  136. ofs: Word;
  137. Ch, Ch2: Char;
  138. begin
  139. if dos_version < $300 then
  140. begin
  141. GetProgramName := '';
  142. exit;
  143. end;
  144. dos_env_seg := PFarWord(Ptr(PrefixSeg, $2C))^;
  145. ofs := 1;
  146. repeat
  147. Ch := PFarChar(Ptr(dos_env_seg,ofs - 1))^;
  148. Ch2 := PFarChar(Ptr(dos_env_seg,ofs))^;
  149. if (Ch = #0) and (Ch2 = #0) then
  150. begin
  151. Inc(ofs, 3);
  152. GetProgramName := '';
  153. repeat
  154. Ch := PFarChar(Ptr(dos_env_seg,ofs))^;
  155. if Ch <> #0 then
  156. GetProgramName := GetProgramName + Ch;
  157. Inc(ofs);
  158. if ofs = 0 then
  159. begin
  160. GetProgramName := '';
  161. exit;
  162. end;
  163. until Ch = #0;
  164. exit;
  165. end;
  166. Inc(ofs);
  167. if ofs = 0 then
  168. begin
  169. GetProgramName := '';
  170. exit;
  171. end;
  172. until false;
  173. end;}
  174. function GetArg(ArgNo: Integer; out ArgResult: string): Integer;
  175. var
  176. I: Integer;
  177. InArg: Boolean;
  178. begin
  179. ArgResult := '';
  180. I := 0;
  181. InArg := False;
  182. GetArg := 0;
  183. while CmdLine[I]<>#0 do
  184. begin
  185. if not InArg and (CmdLine[I] <> ' ') then
  186. begin
  187. InArg := True;
  188. Inc(GetArg);
  189. end;
  190. if InArg and (CmdLine[I] = ' ') then
  191. InArg := False;
  192. if InArg and (GetArg = ArgNo) then
  193. ArgResult := ArgResult + CmdLine[I];
  194. Inc(I);
  195. end;
  196. end;
  197. function paramcount : longint;
  198. var
  199. tmpstr: string;
  200. begin
  201. paramcount := GetArg(-1, tmpstr);
  202. end;
  203. function paramstr(l : longint) : string;
  204. begin
  205. if l = 0 then
  206. paramstr := ''{GetProgramName}
  207. else
  208. GetArg(l, paramstr);
  209. end;
  210. procedure randomize;
  211. {var
  212. hl : longint;
  213. regs : Registers;}
  214. begin
  215. { regs.AH:=$2C;
  216. MsDos(regs);
  217. hl:=regs.DX;
  218. randseed:=hl*$10000+ regs.CX;}
  219. end;
  220. {*****************************************************************************
  221. System Dependent Exit code
  222. *****************************************************************************}
  223. procedure system_exit;
  224. {var
  225. h : byte;}
  226. begin
  227. (* RestoreInterruptHandlers;
  228. for h:=0 to max_files-1 do
  229. if openfiles[h] then
  230. begin
  231. {$ifdef SYSTEMDEBUG}
  232. writeln(stderr,'file ',opennames[h],' not closed at exit');
  233. {$endif SYSTEMDEBUG}
  234. if h>=5 then
  235. do_close(h);
  236. end;
  237. {$ifndef FPC_MM_TINY}
  238. if not CheckNullArea then
  239. writeln(stderr, 'Nil pointer assignment');
  240. {$endif FPC_MM_TINY}*)
  241. asm
  242. mov al, byte [exitcode]
  243. mov ah, 4Ch
  244. int 21h
  245. end;
  246. end;
  247. {*****************************************************************************
  248. SystemUnit Initialization
  249. *****************************************************************************}
  250. procedure InitWin16Heap;
  251. begin
  252. {$ifdef FPC_X86_DATA_NEAR}
  253. SetMemoryManager(LocalHeapMemoryManager);
  254. {$else FPC_X86_DATA_NEAR}
  255. { todo: implement a working win16 heap manager for the far data models }
  256. {$endif FPC_X86_DATA_NEAR}
  257. end;
  258. function CheckLFN:boolean;
  259. var
  260. regs : Registers;
  261. RootName : pchar;
  262. buf : array [0..31] of char;
  263. begin
  264. { Check LFN API on drive c:\ }
  265. RootName:='C:\';
  266. { Call 'Get Volume Information' ($71A0) }
  267. FillChar(regs,SizeOf(regs),0);
  268. regs.AX:=$71a0;
  269. regs.ES:=Seg(buf);
  270. regs.DI:=Ofs(buf);
  271. regs.CX:=32;
  272. regs.DS:=Seg(RootName^);
  273. regs.DX:=Ofs(RootName^);
  274. MsDos_Carry(regs);
  275. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  276. CheckLFN:=(regs.Flags and fCarry=0) and (regs.BX and $4000=$4000);
  277. end;
  278. procedure SysInitStdIO;
  279. begin
  280. OpenStdIO(Input,fmInput,StdInputHandle);
  281. OpenStdIO(Output,fmOutput,StdOutputHandle);
  282. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  283. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  284. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  285. end;
  286. function GetProcessID: SizeUInt;
  287. begin
  288. GetProcessID := PrefixSeg;
  289. end;
  290. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  291. begin
  292. result := stklen;
  293. end;
  294. begin
  295. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  296. with PAutoDataSegHeader(Ptr(DSeg,0))^ do
  297. begin
  298. StackBottom := Ptr(SSeg,pStackTop);
  299. StackLength := pStackBot-pStackTop;
  300. end;
  301. {$else}
  302. with PAutoDataSegHeader(0)^ do
  303. begin
  304. StackBottom := NearPointer(pStackTop);
  305. StackLength := pStackBot-pStackTop;
  306. end;
  307. {$endif}
  308. { To be set if this is a GUI or console application }
  309. IsConsole := FALSE;
  310. { To be set if this is a library and not a program }
  311. IsLibrary := FALSE;
  312. { Setup heap }
  313. InitWin16Heap;
  314. SysInitExceptions;
  315. initunicodestringmanager;
  316. { Use LFNSupport LFN }
  317. LFNSupport:=CheckLFN;
  318. if LFNSupport then
  319. begin
  320. FileNameCasePreserving:=true;
  321. AllFilesMask := '*';
  322. end
  323. else
  324. AllFilesMask := '*.*';
  325. { Reset IO Error }
  326. InOutRes:=0;
  327. end.