system.pas 38 KB

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