system.pas 38 KB

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