system.pas 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. {
  2. ****************************************************************************
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2005 by Free Pascal development team
  5. Free Pascal - OS/2 runtime library
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. ****************************************************************************}
  12. unit System;
  13. interface
  14. {$ifdef SYSTEMDEBUG}
  15. {$define SYSTEMEXCEPTIONDEBUG}
  16. {.$define IODEBUG}
  17. {.$define DEBUGENVIRONMENT}
  18. {.$define DEBUGARGUMENTS}
  19. {$endif SYSTEMDEBUG}
  20. {$DEFINE OS2EXCEPTIONS}
  21. {$DEFINE OS2UNICODE}
  22. {$define DISABLE_NO_THREAD_MANAGER}
  23. {$DEFINE HAS_GETCPUCOUNT}
  24. {$I systemh.inc}
  25. const
  26. LineEnding = #13#10;
  27. { LFNSupport is defined separately below!!! }
  28. DirectorySeparator = '\';
  29. DriveSeparator = ':';
  30. ExtensionSeparator = '.';
  31. PathSeparator = ';';
  32. AllowDirectorySeparators : set of char = ['\','/'];
  33. AllowDriveSeparators : set of char = [':'];
  34. { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! }
  35. MaxExitCode = 65535;
  36. MaxPathLen = 260;
  37. (* MaxPathLen is referenced as constant from unit SysUtils *)
  38. (* - changing to variable or typed constant is not possible. *)
  39. AllFilesMask = '*';
  40. RealMaxPathLen: word = MaxPathLen;
  41. (* Default value only - real value queried from the system on startup. *)
  42. type
  43. TOS = (osDOS, osOS2, osDPMI); (* For compatibility with target EMX *)
  44. TUConvObject = pointer;
  45. TLocaleObject = pointer;
  46. const
  47. OS_Mode: TOS = osOS2; (* For compatibility with target EMX *)
  48. First_Meg: pointer = nil; (* For compatibility with target EMX *)
  49. UnusedHandle=-1;
  50. StdInputHandle=0;
  51. StdOutputHandle=1;
  52. StdErrorHandle=2;
  53. LFNSupport: boolean = true;
  54. FileNameCaseSensitive: boolean = false;
  55. FileNameCasePreserving: boolean = true;
  56. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  57. RTLUsesWinCP: boolean = true; (* UnicodeString manager shall treat *)
  58. (* codepage numbers passed to RTL functions as those used under MS Windows *)
  59. (* and translates them to their OS/2 equivalents if necessary. *)
  60. sLineBreak = LineEnding;
  61. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  62. var
  63. { C-compatible arguments and environment }
  64. argc : longint;
  65. argv : ppchar;
  66. envp : ppchar;
  67. EnvC: cardinal;
  68. (* Pointer to the block of environment variables - used e.g. in unit Dos. *)
  69. Environment: PChar;
  70. var
  71. (* Type / run mode of the current process: *)
  72. (* 0 .. full screen OS/2 session *)
  73. (* 1 .. DOS session *)
  74. (* 2 .. VIO windowable OS/2 session *)
  75. (* 3 .. Presentation Manager OS/2 session *)
  76. (* 4 .. detached (background) OS/2 process *)
  77. ApplicationType: cardinal;
  78. const
  79. HeapAllocFlags: cardinal = $53; (* Compatible to VP/2 *)
  80. (* mfPag_Commit or mfObj_Tile or mfPag_Write or mfPag_Read *)
  81. function ReadUseHighMem: boolean;
  82. procedure WriteUseHighMem (B: boolean);
  83. (* Is allocation of memory above 512 MB address limit allowed? Even if use *)
  84. (* of high memory is supported by the underlying OS/2 version, just a subset *)
  85. (* of OS/2 API functions can work with memory buffers located in high *)
  86. (* memory. Since FPC RTL allocates heap using memory pools received from *)
  87. (* the operating system and thus memory allocation from the operating system *)
  88. (* may happen at a different time than allocation of memory from FPC heap, *)
  89. (* use of high memory shall be enabled only if the given program is ensured *)
  90. (* not to use any OS/2 API function beyond the limited set supporting it any *)
  91. (* time between enabling this feature and program termination. *)
  92. property
  93. UseHighMem: boolean read ReadUseHighMem write WriteUseHighMem;
  94. (* UseHighMem is provided for compatibility with 2.0.x. *)
  95. {$IFDEF OS2UNICODE}
  96. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte;
  97. var UConvObj: TUConvObject): TSystemCodepage;
  98. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte;
  99. var UConvObj: TUConvObject): cardinal;
  100. function OS2CPtoRtlCP (CP: cardinal; ReqFlags: byte): TSystemCodepage;
  101. function RtlCPtoOS2CP (RtlCP: TSystemCodepage; ReqFlags: byte): cardinal;
  102. (* function RtlChangeCP (CP: TSystemCodePage; const stdcp: TStandardCodePageEnum): longint; *)
  103. {$ENDIF OS2UNICODE}
  104. const
  105. (* Are file sizes > 2 GB (64-bit) supported on the current system? *)
  106. FSApi64: boolean = false;
  107. UniAPI: boolean = false;
  108. (* Support for tracking I/O errors returned by OS/2 API calls - emulation *)
  109. (* of GetLastError / fpGetError functionality used e.g. in Sysutils. *)
  110. type
  111. TOSErrorWatch = procedure (Error: cardinal);
  112. procedure NoErrorTracking (Error: cardinal);
  113. (* This shall be invoked whenever a non-zero error is returned by OS/2 APIs *)
  114. (* used in the RTL. Direct OS/2 API calls in user programs are not covered! *)
  115. const
  116. OSErrorWatch: TOSErrorWatch = @NoErrorTracking;
  117. function SetOSErrorTracking (P: pointer): pointer;
  118. procedure SetDefaultOS2FileType (FType: ShortString);
  119. procedure SetDefaultOS2Creator (Creator: ShortString);
  120. type
  121. TDosOpenL = function (FileName: PChar; var Handle: THandle;
  122. var Action: cardinal; InitSize: int64;
  123. Attrib, OpenFlags, FileMode: cardinal;
  124. EA: pointer): cardinal; cdecl;
  125. TDosSetFilePtrL = function (Handle: THandle; Pos: int64; Method: cardinal;
  126. var PosActual: int64): cardinal; cdecl;
  127. TDosSetFileSizeL = function (Handle: THandle; Size: int64): cardinal; cdecl;
  128. TUniCreateUConvObject = function (const CpName: PWideChar;
  129. var UConv_Object: TUConvObject): longint; cdecl;
  130. TUniFreeUConvObject = function (UConv_Object: TUConvObject): longint; cdecl;
  131. TUniMapCpToUcsCp = function (const Codepage: cardinal;
  132. CodepageName: PWideChar; const N: cardinal): longint; cdecl;
  133. TUniUConvFromUcs = function (UConv_Object: TUConvObject;
  134. var UcsBuf: PWideChar; var UniCharsLeft: longint; var OutBuf: PChar;
  135. var OutBytesLeft: longint; var NonIdentical: longint): longint; cdecl;
  136. TUniUConvToUcs = function (UConv_Object: TUConvObject; var InBuf: PChar;
  137. var InBytesLeft: longint; var UcsBuf: PWideChar; var UniCharsLeft: longint;
  138. var NonIdentical: longint): longint; cdecl;
  139. TUniToLower = function (UniCharIn: WideChar): WideChar; cdecl;
  140. TUniToUpper = function (UniCharIn: WideChar): WideChar; cdecl;
  141. TUniStrColl = function (Locale_Object: TLocaleObject;
  142. const UCS1, UCS2: PWideChar): longint; cdecl;
  143. TUniCreateLocaleObject = function (LocaleSpecType: longint;
  144. const LocaleSpec: pointer;
  145. var Locale_Object: TLocaleObject): longint; cdecl;
  146. TUniFreeLocaleObject = function (Locale_Object: TLocaleObject): longint;
  147. cdecl;
  148. TUniMapCtryToLocale = function (CountryCode: cardinal; LocaleName: PWideChar;
  149. BufSize: longint): longint; cdecl;
  150. const
  151. DosCallsHandle: THandle = THandle (-1);
  152. {$IFDEF OS2UNICODE}
  153. UConvHandle: THandle = THandle (-1);
  154. LibUniHandle: THandle = THandle (-1);
  155. {$ENDIF OS2UNICODE}
  156. var
  157. Sys_DosOpenL: TDosOpenL;
  158. Sys_DosSetFilePtrL: TDosSetFilePtrL;
  159. Sys_DosSetFileSizeL: TDosSetFileSizeL;
  160. {$IFDEF OS2UNICODE}
  161. Sys_UniCreateUConvObject: TUniCreateUConvObject;
  162. Sys_UniFreeUConvObject: TUniFreeUConvObject;
  163. Sys_UniMapCpToUcsCp: TUniMapCpToUcsCp;
  164. Sys_UniUConvFromUcs: TUniUConvFromUcs;
  165. Sys_UniUConvToUcs: TUniUConvToUcs;
  166. Sys_UniToLower: TUniToLower;
  167. Sys_UniToUpper: TUniToUpper;
  168. Sys_UniStrColl: TUniStrColl;
  169. Sys_UniCreateLocaleObject: TUniCreateLocaleObject;
  170. Sys_UniFreeLocaleObject: TUniFreeLocaleObject;
  171. Sys_UniMapCtryToLocale: TUniMapCtryToLocale;
  172. {$ENDIF OS2UNICODE}
  173. implementation
  174. {*****************************************************************************
  175. System unit initialization.
  176. ****************************************************************************}
  177. {$I system.inc}
  178. {*****************************************************************************
  179. Exception handling.
  180. ****************************************************************************}
  181. {$IFDEF OS2EXCEPTIONS}
  182. var
  183. { value of the stack segment
  184. to check if the call stack can be written on exceptions }
  185. _SS : Cardinal;
  186. function Is_Prefetch (P: pointer): boolean;
  187. var
  188. A: array [0..15] of byte;
  189. DoAgain: boolean;
  190. InstrLo, InstrHi, OpCode: byte;
  191. I: longint;
  192. MemSize, MemAttrs: cardinal;
  193. RC: cardinal;
  194. begin
  195. Is_Prefetch := false;
  196. MemSize := SizeOf (A);
  197. RC := DosQueryMem (P, MemSize, MemAttrs);
  198. if RC <> 0 then
  199. OSErrorWatch (RC)
  200. else if (MemAttrs and (mfPag_Free or mfPag_Commit) <> 0)
  201. and (MemSize >= SizeOf (A)) then
  202. Move (P^, A [0], SizeOf (A))
  203. else
  204. Exit;
  205. I := 0;
  206. DoAgain := true;
  207. while DoAgain and (I < 15) do
  208. begin
  209. OpCode := A [I];
  210. InstrLo := OpCode and $f;
  211. InstrHi := OpCode and $f0;
  212. case InstrHi of
  213. { prefix? }
  214. $20, $30:
  215. DoAgain := (InstrLo and 7) = 6;
  216. $60:
  217. DoAgain := (InstrLo and $c) = 4;
  218. $f0:
  219. DoAgain := InstrLo in [0, 2, 3];
  220. $0:
  221. begin
  222. Is_Prefetch := (InstrLo = $f) and (A [I + 1] in [$D, $18]);
  223. Exit;
  224. end;
  225. else
  226. DoAgain := false;
  227. end;
  228. Inc (I);
  229. end;
  230. end;
  231. const
  232. MaxExceptionLevel = 16;
  233. ExceptLevel: byte = 0;
  234. var
  235. ExceptEIP: array [0..MaxExceptionLevel - 1] of longint;
  236. ExceptError: array [0..MaxExceptionLevel - 1] of byte;
  237. ResetFPU: array [0..MaxExceptionLevel - 1] of boolean;
  238. {$ifdef SYSTEMEXCEPTIONDEBUG}
  239. procedure DebugHandleErrorAddrFrame (Error: longint; Addr, Frame: pointer);
  240. begin
  241. if IsConsole then
  242. begin
  243. Write (StdErr, ' HandleErrorAddrFrame (error = ', Error);
  244. Write (StdErr, ', addr = ', hexstr (PtrUInt (Addr), 8));
  245. WriteLn (StdErr, ', frame = ', hexstr (PtrUInt (Frame), 8), ')');
  246. end;
  247. HandleErrorAddrFrame (Error, Addr, Frame);
  248. end;
  249. {$endif SYSTEMEXCEPTIONDEBUG}
  250. procedure JumpToHandleErrorFrame;
  251. var
  252. EIP, EBP, Error: longint;
  253. begin
  254. (* save ebp *)
  255. asm
  256. movl (%ebp),%eax
  257. movl %eax,ebp
  258. end;
  259. if (ExceptLevel > 0) then
  260. Dec (ExceptLevel);
  261. EIP := ExceptEIP [ExceptLevel];
  262. Error := ExceptError [ExceptLevel];
  263. {$ifdef SYSTEMEXCEPTIONDEBUG}
  264. if IsConsole then
  265. WriteLn (StdErr, 'In JumpToHandleErrorFrame error = ', Error);
  266. {$endif SYSTEMEXCEPTIONDEBUG}
  267. if ResetFPU [ExceptLevel] then
  268. SysResetFPU;
  269. { build a fake stack }
  270. asm
  271. {$ifdef REGCALL}
  272. movl ebp,%ecx
  273. movl eip,%edx
  274. movl error,%eax
  275. pushl eip
  276. movl ebp,%ebp // Change frame pointer
  277. {$else}
  278. movl ebp,%eax
  279. pushl %eax
  280. movl eip,%eax
  281. pushl %eax
  282. movl error,%eax
  283. pushl %eax
  284. movl eip,%eax
  285. pushl %eax
  286. movl ebp,%ebp // Change frame pointer
  287. {$endif}
  288. {$ifdef SYSTEMEXCEPTIONDEBUG}
  289. jmpl DebugHandleErrorAddrFrame
  290. {$else not SYSTEMEXCEPTIONDEBUG}
  291. jmpl HandleErrorAddrFrame
  292. {$endif SYSTEMEXCEPTIONDEBUG}
  293. end;
  294. end;
  295. function System_Exception_Handler (Report: PExceptionReportRecord;
  296. RegRec: PExceptionRegistrationRecord;
  297. Context: PContextRecord;
  298. DispContext: pointer): cardinal; cdecl;
  299. var
  300. Res: cardinal;
  301. Err: byte;
  302. Must_Reset_FPU: boolean;
  303. RC: cardinal;
  304. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  305. CurSS: cardinal;
  306. B: byte;
  307. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  308. begin
  309. {$ifdef SYSTEMEXCEPTIONDEBUG}
  310. if IsConsole then
  311. begin
  312. asm
  313. xorl %eax,%eax
  314. movw %ss,%ax
  315. movl %eax,CurSS
  316. end;
  317. WriteLn (StdErr, 'In System_Exception_Handler, error = ',
  318. HexStr (Report^.Exception_Num, 8));
  319. WriteLn (StdErr, 'Context SS = ', HexStr (Context^.Reg_SS, 8),
  320. ', current SS = ', HexStr (CurSS, 8));
  321. end;
  322. {$endif SYSTEMEXCEPTIONDEBUG}
  323. Res := Xcpt_Continue_Search;
  324. if Context^.Reg_SS = _SS then
  325. begin
  326. Err := 0;
  327. Must_Reset_FPU := true;
  328. {$ifdef SYSTEMEXCEPTIONDEBUG}
  329. if IsConsole then
  330. Writeln (StdErr, 'Exception ', HexStr (Report^.Exception_Num, 8));
  331. {$endif SYSTEMEXCEPTIONDEBUG}
  332. case Report^.Exception_Num of
  333. Xcpt_Integer_Divide_By_Zero,
  334. Xcpt_Float_Divide_By_Zero:
  335. Err := 200;
  336. Xcpt_Array_Bounds_Exceeded:
  337. begin
  338. Err := 201;
  339. Must_Reset_FPU := false;
  340. end;
  341. Xcpt_Unable_To_Grow_Stack:
  342. begin
  343. Err := 202;
  344. Must_Reset_FPU := false;
  345. end;
  346. Xcpt_Float_Overflow:
  347. Err := 205;
  348. Xcpt_Float_Denormal_Operand,
  349. Xcpt_Float_Underflow:
  350. Err := 206;
  351. {Context^.FloatSave.StatusWord := Context^.FloatSave.StatusWord and $ffffff00;}
  352. Xcpt_Float_Inexact_Result,
  353. Xcpt_Float_Invalid_Operation,
  354. Xcpt_Float_Stack_Check:
  355. Err := 207;
  356. Xcpt_Integer_Overflow:
  357. begin
  358. Err := 215;
  359. Must_Reset_FPU := false;
  360. end;
  361. Xcpt_Illegal_Instruction:
  362. { if we're testing sse support, simply set the flag and continue }
  363. if SSE_Check then
  364. begin
  365. OS_Supports_SSE := false;
  366. { skip the offending movaps %xmm7, %xmm6 instruction }
  367. Inc (Context^.Reg_EIP, 3);
  368. Report^.Exception_Num := 0;
  369. Res := Xcpt_Continue_Execution;
  370. end
  371. else
  372. Err := 216;
  373. Xcpt_Access_Violation:
  374. { Athlon prefetch bug? }
  375. if Is_Prefetch (pointer (Context^.Reg_EIP)) then
  376. begin
  377. { if yes, then retry }
  378. Report^.Exception_Num := 0;
  379. Res := Xcpt_Continue_Execution;
  380. end
  381. else
  382. Err := 216;
  383. Xcpt_Signal:
  384. case Report^.Parameters [0] of
  385. Xcpt_Signal_KillProc:
  386. Err := 217;
  387. Xcpt_Signal_Break,
  388. Xcpt_Signal_Intr:
  389. if Assigned (CtrlBreakHandler) then
  390. if CtrlBreakHandler (Report^.Parameters [0] = Xcpt_Signal_Break) then
  391. begin
  392. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  393. WriteLn (StdErr, 'CtrlBreakHandler returned true');
  394. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  395. Report^.Exception_Num := 0;
  396. Res := Xcpt_Continue_Execution;
  397. RC := DosAcknowledgeSignalException (Report^.Parameters [0]);
  398. if RC <> 0 then
  399. OSErrorWatch (RC);
  400. end
  401. else
  402. Err := 217;
  403. end;
  404. Xcpt_Privileged_Instruction:
  405. begin
  406. Err := 218;
  407. Must_Reset_FPU := false;
  408. end;
  409. else
  410. begin
  411. if ((Report^.Exception_Num and Xcpt_Severity_Code)
  412. = Xcpt_Fatal_Exception) then
  413. Err := 217
  414. else
  415. Err := 255;
  416. end;
  417. end;
  418. if (Err <> 0) and (ExceptLevel < MaxExceptionLevel)
  419. (* TH: The following line is necessary to avoid an endless loop *)
  420. and (Report^.Exception_Num < Xcpt_Process_Terminate)
  421. then
  422. begin
  423. ExceptEIP [ExceptLevel] := Context^.Reg_EIP;
  424. ExceptError [ExceptLevel] := Err;
  425. ResetFPU [ExceptLevel] := Must_Reset_FPU;
  426. Inc (ExceptLevel);
  427. Context^.Reg_EIP := cardinal (@JumpToHandleErrorFrame);
  428. Report^.Exception_Num := 0;
  429. Res := Xcpt_Continue_Execution;
  430. {$ifdef SYSTEMEXCEPTIONDEBUG}
  431. if IsConsole then
  432. begin
  433. WriteLn (StdErr, 'Exception Continue Exception set at ',
  434. HexStr (ExceptEIP [ExceptLevel], 8));
  435. WriteLn (StdErr, 'EIP changed to ',
  436. HexStr (longint (@JumpToHandleErrorFrame), 8), ', error = ', Err);
  437. end;
  438. {$endif SYSTEMEXCEPTIONDEBUG}
  439. end;
  440. end
  441. else
  442. if (Report^.Exception_Num = Xcpt_Signal) and
  443. (Report^.Parameters [0] and (Xcpt_Signal_Intr or Xcpt_Signal_Break) <> 0)
  444. and Assigned (CtrlBreakHandler) then
  445. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  446. begin
  447. WriteLn (StdErr, 'XCPT_SIGNAL caught, CtrlBreakHandler assigned, Param = ',
  448. Report^.Parameters [0]);
  449. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  450. if CtrlBreakHandler (Report^.Parameters [0] = Xcpt_Signal_Break) then
  451. begin
  452. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  453. WriteLn (StdErr, 'CtrlBreakHandler returned true');
  454. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  455. Report^.Exception_Num := 0;
  456. Res := Xcpt_Continue_Execution;
  457. RC := DosAcknowledgeSignalException (Report^.Parameters [0]);
  458. if RC <> 0 then
  459. OSErrorWatch (RC);
  460. end
  461. else
  462. Err := 217;
  463. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  464. end
  465. else
  466. if IsConsole then
  467. begin
  468. WriteLn (StdErr, 'Ctx flags = ', HexStr (Context^.ContextFlags, 8));
  469. if Context^.ContextFlags and Context_Floating_Point <> 0 then
  470. begin
  471. for B := 1 to 6 do
  472. Write (StdErr, 'Ctx Env [', B, '] = ', HexStr (Context^.Env [B], 8),
  473. ', ');
  474. WriteLn (StdErr, 'Ctx Env [7] = ', HexStr (Context^.Env [7], 8));
  475. for B := 0 to 6 do
  476. Write (StdErr, 'FPU stack [', B, '] = ', Context^.FPUStack [B], ', ');
  477. WriteLn (StdErr, 'FPU stack [7] = ', Context^.FPUStack [7]);
  478. end;
  479. if Context^.ContextFlags and Context_Segments <> 0 then
  480. WriteLn (StdErr, 'GS = ', HexStr (Context^.Reg_GS, 8),
  481. ', FS = ', HexStr (Context^.Reg_FS, 8),
  482. ', ES = ', HexStr (Context^.Reg_ES, 8),
  483. ', DS = ', HexStr (Context^.Reg_DS, 8));
  484. if Context^.ContextFlags and Context_Integer <> 0 then
  485. begin
  486. WriteLn (StdErr, 'EDI = ', HexStr (Context^.Reg_EDI, 8),
  487. ', ESI = ', HexStr (Context^.Reg_ESI, 8));
  488. WriteLn (StdErr, 'EAX = ', HexStr (Context^.Reg_EAX, 8),
  489. ', EBX = ', HexStr (Context^.Reg_EBX, 8),
  490. ', ECX = ', HexStr (Context^.Reg_ECX, 8),
  491. ', EDX = ', HexStr (Context^.Reg_EDX, 8));
  492. end;
  493. if Context^.ContextFlags and Context_Control <> 0 then
  494. begin
  495. WriteLn (StdErr, 'EBP = ', HexStr (Context^.Reg_EBP, 8),
  496. ', SS = ', HexStr (Context^.Reg_SS, 8),
  497. ', ESP = ', HexStr (Context^.Reg_ESP, 8));
  498. WriteLn (StdErr, 'CS = ', HexStr (Context^.Reg_CS, 8),
  499. ', EIP = ', HexStr (Context^.Reg_EIP, 8),
  500. ', EFlags = ', HexStr (Context^.Flags, 8));
  501. end;
  502. end;
  503. {$endif SYSTEMEXCEPTIONDEBUG}
  504. System_Exception_Handler := Res;
  505. end;
  506. var
  507. ExcptReg: PExceptionRegistrationRecord; public name '_excptregptr';
  508. {$ifdef SYSTEMEXCEPTIONDEBUG}
  509. var
  510. OldExceptAddr,
  511. NewExceptAddr: PtrUInt;
  512. {$endif SYSTEMEXCEPTIONDEBUG}
  513. procedure Install_Exception_Handler;
  514. var
  515. T: cardinal;
  516. RC: cardinal;
  517. begin
  518. {$ifdef SYSTEMEXCEPTIONDEBUG}
  519. (* ThreadInfoBlock is located at FS:[0], the first *)
  520. (* entry is pointer to head of exception handler chain. *)
  521. asm
  522. movl $0,%eax
  523. movl %fs:(%eax),%eax
  524. movl %eax, OldExceptAddr
  525. end;
  526. {$endif SYSTEMEXCEPTIONDEBUG}
  527. with ExcptReg^ do
  528. begin
  529. Prev_Structure := nil;
  530. ExceptionHandler := TExceptionHandler (@System_Exception_Handler);
  531. end;
  532. (* Disable pop-up windows for errors and exceptions *)
  533. DosError (deDisableExceptions);
  534. DosSetExceptionHandler (ExcptReg^);
  535. if IsConsole then
  536. begin
  537. RC := DosSetSignalExceptionFocus (1, T);
  538. if RC <> 0 then
  539. OSErrorWatch (RC);
  540. RC := DosAcknowledgeSignalException (Xcpt_Signal_Intr);
  541. if RC <> 0 then
  542. OSErrorWatch (RC);
  543. RC := DosAcknowledgeSignalException (Xcpt_Signal_Break);
  544. if RC <> 0 then
  545. OSErrorWatch (RC);
  546. end;
  547. {$ifdef SYSTEMEXCEPTIONDEBUG}
  548. asm
  549. movl $0,%eax
  550. movl %fs:(%eax),%eax
  551. movl %eax, NewExceptAddr
  552. end;
  553. {$endif SYSTEMEXCEPTIONDEBUG}
  554. end;
  555. procedure Remove_Exception_Handlers;
  556. var
  557. RC: cardinal;
  558. begin
  559. RC := DosUnsetExceptionHandler (ExcptReg^);
  560. OSErrorWatch (RC);
  561. end;
  562. {$ENDIF OS2EXCEPTIONS}
  563. procedure system_exit;
  564. begin
  565. (* if IsLibrary then
  566. ExitDLL(ExitCode);
  567. *)
  568. (*
  569. if not IsConsole then
  570. begin
  571. Close(stderr);
  572. Close(stdout);
  573. Close(erroutput);
  574. Close(Input);
  575. Close(Output);
  576. end;
  577. *)
  578. {$IFDEF OS2EXCEPTIONS}
  579. Remove_Exception_Handlers;
  580. {$ENDIF OS2EXCEPTIONS}
  581. DosExit (1{process}, exitcode);
  582. end;
  583. {$ASMMODE ATT}
  584. {****************************************************************************
  585. Miscellaneous related routines.
  586. ****************************************************************************}
  587. function paramcount:longint;assembler;
  588. asm
  589. movl argc,%eax
  590. decl %eax
  591. end {['EAX']};
  592. function paramstr(l:longint):string;
  593. var p:^Pchar;
  594. begin
  595. if (l>=0) and (l<=paramcount) then
  596. begin
  597. p:=argv;
  598. paramstr:=strpas(p[l]);
  599. end
  600. else paramstr:='';
  601. end;
  602. procedure randomize;
  603. var
  604. dt: TSysDateTime;
  605. begin
  606. // Hmm... Lets use timer
  607. DosGetDateTime(dt);
  608. randseed:=dt.hour+(dt.minute shl 8)+(dt.second shl 16)+(dt.sec100 shl 32);
  609. end;
  610. {****************************************************************************
  611. Error Message writing using messageboxes
  612. ****************************************************************************}
  613. const
  614. WinInitialize: TWinInitialize = nil;
  615. WinCreateMsgQueue: TWinCreateMsgQueue = nil;
  616. WinMessageBox: TWinMessageBox = nil;
  617. EnvSize: cardinal = 0;
  618. var
  619. ErrorBuf: array [0..ErrorBufferLength] of char;
  620. ErrorLen: longint;
  621. PMWinHandle: cardinal;
  622. function ErrorWrite (var F: TextRec): integer;
  623. {
  624. An error message should always end with #13#10#13#10
  625. }
  626. var
  627. P: PChar;
  628. I: longint;
  629. begin
  630. if F.BufPos > 0 then
  631. begin
  632. if F.BufPos + ErrorLen > ErrorBufferLength then
  633. I := ErrorBufferLength - ErrorLen
  634. else
  635. I := F.BufPos;
  636. Move (F.BufPtr^, ErrorBuf [ErrorLen], I);
  637. Inc (ErrorLen, I);
  638. ErrorBuf [ErrorLen] := #0;
  639. end;
  640. if ErrorLen > 3 then
  641. begin
  642. P := @ErrorBuf [ErrorLen];
  643. for I := 1 to 4 do
  644. begin
  645. Dec (P);
  646. if not (P^ in [#10, #13]) then
  647. break;
  648. end;
  649. end;
  650. if ErrorLen = ErrorBufferLength then
  651. I := 4;
  652. if (I = 4) then
  653. begin
  654. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  655. ErrorLen := 0;
  656. end;
  657. F.BufPos := 0;
  658. ErrorWrite := 0;
  659. end;
  660. function ErrorClose (var F: TextRec): integer;
  661. begin
  662. if ErrorLen > 0 then
  663. begin
  664. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  665. ErrorLen := 0;
  666. end;
  667. ErrorLen := 0;
  668. ErrorClose := 0;
  669. end;
  670. function ErrorOpen (var F: TextRec): integer;
  671. begin
  672. TextRec(F).InOutFunc := @ErrorWrite;
  673. TextRec(F).FlushFunc := @ErrorWrite;
  674. TextRec(F).CloseFunc := @ErrorClose;
  675. ErrorOpen := 0;
  676. end;
  677. procedure AssignError (var T: Text);
  678. begin
  679. Assign (T, '');
  680. TextRec (T).OpenFunc := @ErrorOpen;
  681. Rewrite (T);
  682. end;
  683. procedure SysInitStdIO;
  684. (*
  685. var
  686. RC: cardinal;
  687. *)
  688. begin
  689. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  690. displayed in a messagebox }
  691. (*
  692. StdInputHandle := longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  693. StdOutputHandle := longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  694. StdErrorHandle := longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  695. if not IsConsole then
  696. begin
  697. RC := DosLoadModule (nil, 0, 'PMWIN', PMWinHandle);
  698. if RC <> 0 then
  699. OSErrorWatch (RC)
  700. else
  701. begin
  702. RC := DosQueryProcAddr (PMWinHandle, 789, nil, pointer (WinMessageBox));
  703. if RC <> 0 then
  704. OSErrorWatch (RC)
  705. else
  706. begin
  707. RC := DosQueryProcAddr (PMWinHandle, 763, nil, pointer (WinInitialize));
  708. if RC <> 0 then
  709. OSErrorWatch (RC)
  710. else
  711. begin
  712. RC := DosQueryProcAddr (PMWinHandle, 716, nil, pointer (WinCreateMsgQueue));
  713. if RC <> 0 then
  714. OSErrorWatch (RC)
  715. else
  716. begin
  717. WinInitialize (0);
  718. WinCreateMsgQueue (0, 0);
  719. end
  720. end
  721. end
  722. end;
  723. if RC <> 0 then
  724. HandleError (2);
  725. AssignError (StdErr);
  726. AssignError (StdOut);
  727. Assign (Output, '');
  728. Assign (Input, '');
  729. end
  730. else
  731. begin
  732. *)
  733. OpenStdIO (Input, fmInput, StdInputHandle);
  734. OpenStdIO (Output, fmOutput, StdOutputHandle);
  735. OpenStdIO (ErrOutput, fmOutput, StdErrorHandle);
  736. OpenStdIO (StdOut, fmOutput, StdOutputHandle);
  737. OpenStdIO (StdErr, fmOutput, StdErrorHandle);
  738. (*
  739. end;
  740. *)
  741. end;
  742. function strcopy(dest,source : pchar) : pchar;assembler;
  743. var
  744. saveeax,saveesi,saveedi : longint;
  745. asm
  746. movl %edi,saveedi
  747. movl %esi,saveesi
  748. {$ifdef REGCALL}
  749. movl %eax,saveeax
  750. movl %edx,%edi
  751. {$else}
  752. movl source,%edi
  753. {$endif}
  754. testl %edi,%edi
  755. jz .LStrCopyDone
  756. leal 3(%edi),%ecx
  757. andl $-4,%ecx
  758. movl %edi,%esi
  759. subl %edi,%ecx
  760. {$ifdef REGCALL}
  761. movl %eax,%edi
  762. {$else}
  763. movl dest,%edi
  764. {$endif}
  765. jz .LStrCopyAligned
  766. .LStrCopyAlignLoop:
  767. movb (%esi),%al
  768. incl %edi
  769. incl %esi
  770. testb %al,%al
  771. movb %al,-1(%edi)
  772. jz .LStrCopyDone
  773. decl %ecx
  774. jnz .LStrCopyAlignLoop
  775. .balign 16
  776. .LStrCopyAligned:
  777. movl (%esi),%eax
  778. movl %eax,%edx
  779. leal 0x0fefefeff(%eax),%ecx
  780. notl %edx
  781. addl $4,%esi
  782. andl %edx,%ecx
  783. andl $0x080808080,%ecx
  784. jnz .LStrCopyEndFound
  785. movl %eax,(%edi)
  786. addl $4,%edi
  787. jmp .LStrCopyAligned
  788. .LStrCopyEndFound:
  789. testl $0x0ff,%eax
  790. jz .LStrCopyByte
  791. testl $0x0ff00,%eax
  792. jz .LStrCopyWord
  793. testl $0x0ff0000,%eax
  794. jz .LStrCopy3Bytes
  795. movl %eax,(%edi)
  796. jmp .LStrCopyDone
  797. .LStrCopy3Bytes:
  798. xorb %dl,%dl
  799. movw %ax,(%edi)
  800. movb %dl,2(%edi)
  801. jmp .LStrCopyDone
  802. .LStrCopyWord:
  803. movw %ax,(%edi)
  804. jmp .LStrCopyDone
  805. .LStrCopyByte:
  806. movb %al,(%edi)
  807. .LStrCopyDone:
  808. {$ifdef REGCALL}
  809. movl saveeax,%eax
  810. {$else}
  811. movl dest,%eax
  812. {$endif}
  813. movl saveedi,%edi
  814. movl saveesi,%esi
  815. end;
  816. threadvar
  817. DefaultCreator: ShortString;
  818. DefaultFileType: ShortString;
  819. procedure SetDefaultOS2FileType (FType: ShortString);
  820. begin
  821. {$WARNING Not implemented yet!}
  822. DefaultFileType := FType;
  823. end;
  824. procedure SetDefaultOS2Creator (Creator: ShortString);
  825. begin
  826. {$WARNING Not implemented yet!}
  827. DefaultCreator := Creator;
  828. end;
  829. (* The default handler does not store the OS/2 API error codes. *)
  830. procedure NoErrorTracking (Error: cardinal);
  831. begin
  832. end;
  833. function SetOSErrorTracking (P: pointer): pointer;
  834. begin
  835. SetOSErrorTracking := OSErrorWatch;
  836. if P = nil then
  837. OSErrorWatch := @NoErrorTracking
  838. else
  839. OSErrorWatch := TOSErrorWatch (P);
  840. end;
  841. procedure InitEnvironment;
  842. var env_count : longint;
  843. cp : pchar;
  844. begin
  845. env_count:=0;
  846. cp:=environment;
  847. while cp ^ <> #0 do
  848. begin
  849. inc(env_count);
  850. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  851. inc(longint(cp)); { skip to next character }
  852. end;
  853. envp := sysgetmem((env_count+1) * sizeof(pchar));
  854. envc := env_count;
  855. if (envp = nil) then exit;
  856. cp:=environment;
  857. env_count:=0;
  858. while cp^ <> #0 do
  859. begin
  860. envp[env_count] := sysgetmem(strlen(cp)+1);
  861. strcopy(envp[env_count], cp);
  862. {$IfDef DEBUGENVIRONMENT}
  863. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  864. {$EndIf}
  865. inc(env_count);
  866. while (cp^ <> #0) do
  867. inc(longint(cp)); { skip to NUL }
  868. inc(longint(cp)); { skip to next character }
  869. end;
  870. envp[env_count]:=nil;
  871. end;
  872. var
  873. (* Initialized by system unit initialization *)
  874. PIB: PProcessInfoBlock;
  875. procedure InitArguments;
  876. var
  877. arglen,
  878. count : PtrInt;
  879. argstart,
  880. pc,arg : pchar;
  881. quote : char;
  882. argvlen : PtrInt;
  883. RC: cardinal;
  884. procedure allocarg(idx,len: PtrInt);
  885. { var
  886. oldargvlen : PtrInt;}
  887. begin
  888. if idx>=argvlen then
  889. begin
  890. { oldargvlen:=argvlen;}
  891. argvlen:=(idx+8) and (not 7);
  892. sysreallocmem(argv,argvlen*sizeof(pointer));
  893. { fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);}
  894. end;
  895. { use realloc to reuse already existing memory }
  896. { always allocate, even if length is zero, since }
  897. { the arg. is still present! }
  898. ArgV [Idx] := SysAllocMem (Succ (Len));
  899. end;
  900. begin
  901. CmdLine := SysAllocMem (MaxPathLen);
  902. ArgV := SysAllocMem (8 * SizeOf (pointer));
  903. ArgLen := StrLen (PChar (PIB^.Cmd));
  904. Inc (ArgLen);
  905. RC := DosQueryModuleName (PIB^.Handle, MaxPathLen, CmdLine);
  906. if RC = 0 then
  907. ArgVLen := Succ (StrLen (CmdLine))
  908. else
  909. (* Error occurred - use program name from command line as fallback. *)
  910. begin
  911. Move (PIB^.Cmd^, CmdLine, ArgLen);
  912. ArgVLen := ArgLen;
  913. end;
  914. { Get ArgV [0] }
  915. ArgV [0] := SysAllocMem (ArgVLen);
  916. Move (CmdLine^, ArgV [0]^, ArgVLen);
  917. Count := 1;
  918. (* PC points to leading space after program name on command line *)
  919. PC := PChar (PIB^.Cmd) + ArgLen;
  920. (* ArgLen contains size of command line arguments including leading space. *)
  921. ArgLen := Succ (StrLen (PC));
  922. SysReallocMem (CmdLine, ArgVLen + Succ (ArgLen));
  923. Move (PC^, CmdLine [ArgVLen], Succ (ArgLen));
  924. (* ArgV has space for 8 parameters from the first allocation. *)
  925. ArgVLen := 8;
  926. { process arguments }
  927. while pc^<>#0 do
  928. begin
  929. { skip leading spaces }
  930. while pc^ in [#1..#32] do
  931. inc(pc);
  932. if pc^=#0 then
  933. break;
  934. { calc argument length }
  935. quote:=' ';
  936. argstart:=pc;
  937. arglen:=0;
  938. while (pc^<>#0) do
  939. begin
  940. case pc^ of
  941. #1..#32 :
  942. begin
  943. if quote<>' ' then
  944. inc(arglen)
  945. else
  946. break;
  947. end;
  948. '"' :
  949. begin
  950. if quote<>'''' then
  951. begin
  952. if pchar(pc+1)^<>'"' then
  953. begin
  954. if quote='"' then
  955. quote:=' '
  956. else
  957. quote:='"';
  958. end
  959. else
  960. inc(pc);
  961. end
  962. else
  963. inc(arglen);
  964. end;
  965. '''' :
  966. begin
  967. if quote<>'"' then
  968. begin
  969. if pchar(pc+1)^<>'''' then
  970. begin
  971. if quote='''' then
  972. quote:=' '
  973. else
  974. quote:='''';
  975. end
  976. else
  977. inc(pc);
  978. end
  979. else
  980. inc(arglen);
  981. end;
  982. else
  983. inc(arglen);
  984. end;
  985. inc(pc);
  986. end;
  987. { copy argument }
  988. { Don't copy the first one, it is already there.}
  989. If Count<>0 then
  990. begin
  991. allocarg(count,arglen);
  992. quote:=' ';
  993. pc:=argstart;
  994. arg:=argv[count];
  995. while (pc^<>#0) do
  996. begin
  997. case pc^ of
  998. #1..#32 :
  999. begin
  1000. if quote<>' ' then
  1001. begin
  1002. arg^:=pc^;
  1003. inc(arg);
  1004. end
  1005. else
  1006. break;
  1007. end;
  1008. '"' :
  1009. begin
  1010. if quote<>'''' then
  1011. begin
  1012. if pchar(pc+1)^<>'"' then
  1013. begin
  1014. if quote='"' then
  1015. quote:=' '
  1016. else
  1017. quote:='"';
  1018. end
  1019. else
  1020. inc(pc);
  1021. end
  1022. else
  1023. begin
  1024. arg^:=pc^;
  1025. inc(arg);
  1026. end;
  1027. end;
  1028. '''' :
  1029. begin
  1030. if quote<>'"' then
  1031. begin
  1032. if pchar(pc+1)^<>'''' then
  1033. begin
  1034. if quote='''' then
  1035. quote:=' '
  1036. else
  1037. quote:='''';
  1038. end
  1039. else
  1040. inc(pc);
  1041. end
  1042. else
  1043. begin
  1044. arg^:=pc^;
  1045. inc(arg);
  1046. end;
  1047. end;
  1048. else
  1049. begin
  1050. arg^:=pc^;
  1051. inc(arg);
  1052. end;
  1053. end;
  1054. inc(pc);
  1055. end;
  1056. arg^:=#0;
  1057. end;
  1058. {$IfDef DEBUGARGUMENTS}
  1059. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  1060. {$EndIf}
  1061. inc(count);
  1062. end;
  1063. { get argc and create an nil entry }
  1064. argc:=count;
  1065. allocarg(argc,0);
  1066. { free unused memory }
  1067. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  1068. end;
  1069. function GetFileHandleCount: longint;
  1070. var L1: longint;
  1071. L2: cardinal;
  1072. RC: cardinal;
  1073. begin
  1074. L1 := 0; (* Don't change the amount, just check. *)
  1075. RC := DosSetRelMaxFH (L1, L2);
  1076. if RC <> 0 then
  1077. begin
  1078. GetFileHandleCount := 50;
  1079. OSErrorWatch (RC);
  1080. end
  1081. else
  1082. GetFileHandleCount := L2;
  1083. end;
  1084. function CheckInitialStkLen (StkLen: SizeUInt): SizeUInt;
  1085. begin
  1086. CheckInitialStkLen := StkLen;
  1087. end;
  1088. var
  1089. TIB: PThreadInfoBlock;
  1090. RC: cardinal;
  1091. P: pointer;
  1092. DW: cardinal;
  1093. const
  1094. DosCallsName: array [0..8] of char = 'DOSCALLS'#0;
  1095. {$IFDEF OS2UNICODE}
  1096. {$I sysucode.inc}
  1097. {$ENDIF OS2UNICODE}
  1098. begin
  1099. {$IFDEF OS2EXCEPTIONS}
  1100. asm
  1101. xorl %eax,%eax
  1102. movw %ss,%ax
  1103. movl %eax,_SS
  1104. end;
  1105. {$ENDIF OS2EXCEPTIONS}
  1106. DosGetInfoBlocks (@TIB, @PIB);
  1107. StackLength := CheckInitialStkLen (InitialStkLen);
  1108. { OS/2 has top of stack in TIB^.StackLimit - unlike Windows where it is in TIB^.Stack }
  1109. StackBottom := TIB^.StackLimit - StackLength;
  1110. {Set type of application}
  1111. ApplicationType := PIB^.ProcType;
  1112. ProcessID := PIB^.PID;
  1113. ThreadID := TIB^.TIB2^.TID;
  1114. IsConsole := ApplicationType <> 3;
  1115. {Query maximum path length (QSV_MAX_PATH_LEN = 1)}
  1116. if DosQuerySysInfo (1, 1, DW, SizeOf (DW)) = 0 then
  1117. RealMaxPathLen := DW;
  1118. ExitProc := nil;
  1119. {$IFDEF OS2EXCEPTIONS}
  1120. Install_Exception_Handler;
  1121. {$ENDIF OS2EXCEPTIONS}
  1122. (* Initialize the amount of file handles *)
  1123. FileHandleCount := GetFileHandleCount;
  1124. {Initialize the heap.}
  1125. (* Logic is following:
  1126. The heap is initially restricted to low address space (< 512 MB).
  1127. If underlying OS/2 version allows using more than 512 MB per process
  1128. (OS/2 WarpServer for e-Business, eComStation, possibly OS/2 Warp 4.0
  1129. with FP13 and above as well), use of this high memory is allowed for
  1130. future memory allocations at the end of System unit initialization.
  1131. The consequences are that the compiled application can allocate more
  1132. memory, but it must make sure to use direct DosAllocMem calls if it
  1133. needs a memory block for some system API not supporting high memory.
  1134. This is probably no problem for direct calls to these APIs, but
  1135. there might be situations when a memory block needs to be passed
  1136. to a 3rd party DLL which in turn calls such an API call. In case
  1137. of problems usage of high memory can be turned off by setting
  1138. UseHighMem to false - the program should change the setting at its
  1139. very beginning (e.g. in initialization section of the first unit
  1140. listed in the "uses" section) to avoid having preallocated memory
  1141. from the high memory region before changing value of this variable. *)
  1142. InitHeap;
  1143. Sys_DosOpenL := @DummyDosOpenL;
  1144. Sys_DosSetFilePtrL := @DummyDosSetFilePtrL;
  1145. Sys_DosSetFileSizeL := @DummyDosSetFileSizeL;
  1146. RC := DosQueryModuleHandle (@DosCallsName [0], DosCallsHandle);
  1147. if RC = 0 then
  1148. begin
  1149. RC := DosQueryProcAddr (DosCallsHandle, OrdDosOpenL, nil, P);
  1150. if RC = 0 then
  1151. begin
  1152. Sys_DosOpenL := TDosOpenL (P);
  1153. RC := DosQueryProcAddr (DosCallsHandle, OrdDosSetFilePtrL, nil, P);
  1154. if RC = 0 then
  1155. begin
  1156. Sys_DosSetFilePtrL := TDosSetFilePtrL (P);
  1157. RC := DosQueryProcAddr (DosCallsHandle, OrdDosSetFileSizeL, nil, P);
  1158. if RC = 0 then
  1159. begin
  1160. Sys_DosSetFileSizeL := TDosSetFileSizeL (P);
  1161. FSApi64 := true;
  1162. end;
  1163. end;
  1164. end;
  1165. if RC <> 0 then
  1166. OSErrorWatch (RC);
  1167. RC := DosQueryProcAddr (DosCallsHandle, OrdDosAllocThreadLocalMemory,
  1168. nil, P);
  1169. if RC = 0 then
  1170. begin
  1171. DosAllocThreadLocalMemory := TDosAllocThreadLocalMemory (P);
  1172. RC := DosQueryProcAddr (DosCallsHandle, OrdDosAllocThreadLocalMemory,
  1173. nil, P);
  1174. if RC = 0 then
  1175. begin
  1176. DosFreeThreadLocalMemory := TDosFreeThreadLocalMemory (P);
  1177. TLSAPISupported := true;
  1178. end
  1179. else
  1180. OSErrorWatch (RC);
  1181. end
  1182. else
  1183. OSErrorWatch (RC);
  1184. end
  1185. else
  1186. OSErrorWatch (RC);
  1187. { ... and exceptions }
  1188. SysInitExceptions;
  1189. fpc_cpucodeinit;
  1190. InitUnicodeStringManager;
  1191. {$IFDEF OS2UNICODE}
  1192. InitOS2WideStringManager;
  1193. InitDefaultCP;
  1194. {$ELSE OS2UNICODE}
  1195. (* Otherwise called within InitDefaultCP... *)
  1196. RC := DosQueryCP (SizeOf (CPArr), @CPArr, ReturnedSize);
  1197. if (RC <> 0) and (RC <> 473) then
  1198. begin
  1199. OSErrorWatch (RC);
  1200. CPArr [0] := 850;
  1201. end
  1202. else if (ReturnedSize < 4) then
  1203. CPArr [0] := 850;
  1204. DefaultFileSystemCodePage := CPArr [0];
  1205. {$ENDIF OS2UNICODE}
  1206. DefaultSystemCodePage := DefaultFileSystemCodePage;
  1207. DefaultRTLFileSystemCodePage := DefaultFileSystemCodePage;
  1208. DefaultUnicodeCodePage := CP_UTF16;
  1209. { ... and I/O }
  1210. SysInitStdIO;
  1211. { no I/O-Error }
  1212. InOutRes:=0;
  1213. {Initialize environment (must be after InitHeap because allocates memory)}
  1214. Environment := pointer (PIB^.Env);
  1215. InitEnvironment;
  1216. InitArguments;
  1217. DefaultCreator := '';
  1218. DefaultFileType := '';
  1219. InitSystemThreads;
  1220. {$IFDEF EXTDUMPGROW}
  1221. { Int_HeapSize := high (cardinal);}
  1222. {$ENDIF EXTDUMPGROW}
  1223. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1224. if IsConsole then
  1225. WriteLn (StdErr, 'Old exception ', HexStr (OldExceptAddr, 8),
  1226. ', new exception ', HexStr (NewExceptAddr, 8), ', _SS = ', HexStr (_SS, 8));
  1227. {$endif SYSTEMEXCEPTIONDEBUG}
  1228. end.