system.pas 37 KB

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