2
0

system.pas 43 KB

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