system.pas 38 KB

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