system.pas 43 KB

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