system.pp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 by Florian Klaempfl and Pavel Ozerski
  4. and Yury Sidorov member of the Free Pascal development team.
  5. FPC Pascal system unit for the WinCE.
  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. {$endif SYSTEMDEBUG}
  17. {$define WINCE_EXCEPTION_HANDLING}
  18. {$define DISABLE_NO_THREAD_MANAGER}
  19. {$define HAS_CMDLINE}
  20. {$define HAS_MEMORYMANAGER} // comment this line to switch from wincemm to fpcmm
  21. {$define HAS_WIDESTRINGMANAGER}
  22. { include system-independent routine headers }
  23. {$I systemh.inc}
  24. const
  25. LineEnding = #13#10;
  26. LFNSupport = true;
  27. DirectorySeparator = '\';
  28. DriveSeparator = ':';
  29. ExtensionSeparator = '.';
  30. PathSeparator = ';';
  31. AllowDirectorySeparators : set of char = ['\','/'];
  32. AllowDriveSeparators : set of char = [':'];
  33. { FileNameCaseSensitive is defined separately below!!! }
  34. maxExitCode = 65535;
  35. MaxPathLen = 260;
  36. AllFilesMask = '*';
  37. const
  38. { Default filehandles }
  39. UnusedHandle : THandle = THandle(-1);
  40. StdInputHandle : THandle = 0;
  41. StdOutputHandle : THandle = 0;
  42. StdErrorHandle : THandle = 0;
  43. FileNameCaseSensitive : boolean = true;
  44. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  45. sLineBreak = LineEnding;
  46. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  47. var
  48. { WinCE Info }
  49. hprevinst,
  50. MainInstance,
  51. DLLreason,DLLparam:DWord;
  52. type
  53. TDLL_Entry_Hook = procedure (dllparam : longint);
  54. const
  55. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  56. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  57. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  58. { ANSI <-> Wide }
  59. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  60. function WideToAnsiBuf(WideBuf: PWideChar; WideCharsLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  61. function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
  62. function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
  63. { Wrappers for some WinAPI calls }
  64. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
  65. function ResetEvent(h: THandle): LONGBOOL;
  66. function SetEvent(h: THandle): LONGBOOL;
  67. function GetCurrentProcessId:DWORD;
  68. function Win32GetCurrentThreadId:DWORD;
  69. function TlsAlloc : DWord;
  70. function TlsFree(dwTlsIndex : DWord) : LongBool;
  71. function GetFileAttributes(p : pchar) : dword;
  72. function DeleteFile(p : pchar) : longint;
  73. function MoveFile(old,_new : pchar) : longint;
  74. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  75. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  76. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  77. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  78. function RemoveDirectory(name:pointer):longbool;
  79. {$ifdef CPUARM}
  80. { the external directive isn't really necessary here because it is overridden by external (FK) }
  81. function addd(d1,d2 : double) : double; compilerproc;
  82. cdecl;external 'coredll' name '__addd';
  83. function subd(d1,d2 : double) : double; compilerproc;
  84. cdecl;external 'coredll' name '__subd';
  85. function muld(d1,d2 : double) : double; compilerproc;
  86. cdecl;external 'coredll' name '__muld';
  87. function divd(d1,d2 : double) : double; compilerproc;
  88. cdecl;external 'coredll' name '__divd';
  89. function eqd(d1,d2 : double) : boolean; compilerproc;
  90. cdecl;external 'coredll' name '__eqd';
  91. function ned(d1,d2 : double) : boolean; compilerproc;
  92. cdecl;external 'coredll' name '__ned';
  93. function ltd(d1,d2 : double) : boolean; compilerproc;
  94. cdecl;external 'coredll' name '__ltd';
  95. function gtd(d1,d2 : double) : boolean; compilerproc;
  96. cdecl;external 'coredll' name '__gtd';
  97. function ged(d1,d2 : double) : boolean; compilerproc;
  98. cdecl;external 'coredll' name '__ged';
  99. function led(d1,d2 : double) : boolean; compilerproc;
  100. cdecl;external 'coredll' name '__led';
  101. { ***************** single ******************** }
  102. function eqs(d1,d2 : single) : boolean; compilerproc;
  103. cdecl;external 'coredll' name '__eqs';
  104. function nes(d1,d2 : single) : boolean; compilerproc;
  105. cdecl;external 'coredll' name '__nes';
  106. function lts(d1,d2 : single) : boolean; compilerproc;
  107. cdecl;external 'coredll' name '__lts';
  108. function gts(d1,d2 : single) : boolean; compilerproc;
  109. cdecl;external 'coredll' name '__gts';
  110. function ges(d1,d2 : single) : boolean; compilerproc;
  111. cdecl;external 'coredll' name '__ges';
  112. function les(d1,d2 : single) : boolean; compilerproc;
  113. cdecl;external 'coredll' name '__les';
  114. function dtos(d : double) : single; compilerproc;
  115. cdecl;external 'coredll' name '__dtos';
  116. function stod(d : single) : double; compilerproc;
  117. cdecl;external 'coredll' name '__stod';
  118. function negs(d : single) : single; compilerproc;
  119. cdecl;external 'coredll' name '__negs';
  120. function negd(d : double) : double; compilerproc;
  121. cdecl;external 'coredll' name '__negd';
  122. function utod(i : dword) : double; compilerproc;
  123. cdecl;external 'coredll' name '__utod';
  124. function itod(i : longint) : double; compilerproc;
  125. cdecl;external 'coredll' name '__itod';
  126. function ui64tod(i : qword) : double; compilerproc;
  127. cdecl;external 'coredll' name '__u64tod';
  128. function i64tod(i : int64) : double; compilerproc;
  129. cdecl;external 'coredll' name '__i64tod';
  130. function utos(i : dword) : single; compilerproc;
  131. cdecl;external 'coredll' name '__utos';
  132. function itos(i : longint) : single; compilerproc;
  133. cdecl;external 'coredll' name '__itos';
  134. function ui64tos(i : qword) : single; compilerproc;
  135. cdecl;external 'coredll' name '__u64tos';
  136. function i64tos(i : int64) : single; compilerproc;
  137. cdecl;external 'coredll' name '__i64tos';
  138. function adds(s1,s2 : single) : single; compilerproc;
  139. function subs(s1,s2 : single) : single; compilerproc;
  140. function muls(s1,s2 : single) : single; compilerproc;
  141. function divs(s1,s2 : single) : single; compilerproc;
  142. {$endif CPUARM}
  143. function CmdLine: PChar;
  144. { C compatible arguments }
  145. function argc: longint;
  146. function argv: ppchar;
  147. implementation
  148. var
  149. SysInstance : Longint;public name '_FPC_SysInstance';
  150. function MessageBox(w1:longint;l1,l2:PWideChar;w2:longint):longint;
  151. cdecl; external 'coredll' name 'MessageBoxW';
  152. {*****************************************************************************}
  153. {$define FPC_SYSTEM_HAS_MOVE}
  154. procedure memmove(dest, src: pointer; count: longint);
  155. cdecl; external 'coredll' name 'memmove';
  156. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];
  157. begin
  158. if count > 0 then
  159. memmove(@dest, @source, count);
  160. end;
  161. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  162. function memcmp(buf1, buf2: pointer; count: longint): longint;
  163. cdecl; external 'coredll' name 'memcmp';
  164. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt;
  165. begin
  166. CompareByte := memcmp(@buf1, @buf2, len);
  167. end;
  168. {$ifdef CPUARM}
  169. {$define FPC_SYSTEM_HAS_INT}
  170. function floor(d : double) : double;
  171. cdecl;external 'coredll' name 'floor';
  172. function ceil(d : double) : double;
  173. cdecl;external 'coredll' name 'ceil';
  174. function fpc_int_real(d: ValReal): ValReal;compilerproc;
  175. begin
  176. if d > 0 then
  177. fpc_int_real:=floor(d)
  178. else
  179. fpc_int_real:=ceil(d);
  180. end;
  181. {$define FPC_SYSTEM_HAS_TRUNC}
  182. function __dtoi64(d: double) : int64; cdecl; external 'coredll';
  183. function fpc_trunc_real(d : ValReal) : int64; assembler; nostackframe; compilerproc;
  184. asm
  185. b __dtoi64
  186. end;
  187. {$define FPC_SYSTEM_HAS_ABS}
  188. function fabs(d: double): double; cdecl; external 'coredll';
  189. function fpc_abs_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
  190. asm
  191. b fabs
  192. end;
  193. {$define FPC_SYSTEM_HAS_SQRT}
  194. function coresqrt(d: double): double; cdecl; external 'coredll' name 'sqrt';
  195. function fpc_sqrt_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
  196. asm
  197. b coresqrt
  198. end;
  199. function adds(s1,s2 : single) : single;
  200. begin
  201. adds := addd(s1, s2);
  202. end;
  203. function subs(s1,s2 : single) : single;
  204. begin
  205. subs := subd(s1, s2);
  206. end;
  207. function muls(s1,s2 : single) : single;
  208. begin
  209. muls := muld(s1, s2);
  210. end;
  211. function divs(s1,s2 : single) : single;
  212. begin
  213. divs := divd(s1, s2);
  214. end;
  215. {$endif CPUARM}
  216. {*****************************************************************************}
  217. { include system independent routines }
  218. {$I system.inc}
  219. {*****************************************************************************
  220. ANSI <-> Wide
  221. *****************************************************************************}
  222. const
  223. { MultiByteToWideChar }
  224. MB_PRECOMPOSED = 1;
  225. MB_COMPOSITE = 2;
  226. MB_ERR_INVALID_CHARS = 8;
  227. MB_USEGLYPHCHARS = 4;
  228. CP_OEMCP = 1;
  229. function MultiByteToWideChar(CodePage:UINT; dwFlags:DWORD; lpMultiByteStr:PChar; cchMultiByte:longint; lpWideCharStr:PWideChar;cchWideChar:longint):longint;
  230. cdecl; external 'coredll' name 'MultiByteToWideChar';
  231. function WideCharToMultiByte(CodePage:UINT; dwFlags:DWORD; lpWideCharStr:PWideChar; cchWideChar:longint; lpMultiByteStr:PChar;cchMultiByte:longint; lpDefaultChar:PChar; lpUsedDefaultChar:pointer):longint;
  232. cdecl; external 'coredll' name 'WideCharToMultiByte';
  233. function GetACP:UINT; cdecl; external 'coredll' name 'GetACP';
  234. function GetConsoleCP:UINT; cdecl; external 'coredll' name 'GetConsoleCP';
  235. function GetConsoleOutputCP:UINT; cdecl; external 'coredll' name 'GetConsoleOutputCP';
  236. { Returns number of characters stored to WideBuf, including null-terminator. }
  237. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  238. begin
  239. Result := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, AnsiBuf, AnsiBufLen, WideBuf, WideBufLen div SizeOf(WideChar));
  240. if ((AnsiBufLen <> -1) or (Result = 0)) and (WideBuf <> nil) then
  241. begin
  242. if (Result + 1)*SizeOf(WideChar) > WideBufLen then
  243. begin
  244. Result := 0;
  245. if WideBufLen < SizeOf(WideChar) then
  246. exit;
  247. end;
  248. WideBuf[Result] := #0;
  249. end;
  250. if (AnsiBufLen <> -1) and ((Result <> 0) or (AnsiBufLen = 0)) then
  251. Inc(Result);
  252. end;
  253. { Returns number of characters stored to AnsiBuf, including null-terminator. }
  254. function WideToAnsiBuf(WideBuf: PWideChar; WideCharsLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  255. begin
  256. Result := WideCharToMultiByte(CP_ACP, 0, WideBuf, WideCharsLen, AnsiBuf, AnsiBufLen, nil, nil);
  257. if ((WideCharsLen <> -1) or (Result = 0)) and (AnsiBuf <> nil) then
  258. begin
  259. if Result + 1 > AnsiBufLen then
  260. begin
  261. Result := 0;
  262. if AnsiBufLen < 1 then
  263. exit;
  264. end;
  265. AnsiBuf[Result] := #0;
  266. end;
  267. if (WideCharsLen <> -1) and ((Result <> 0) or (WideCharsLen = 0)) then
  268. Inc(Result);
  269. end;
  270. { Returns dynamic memory block, which contains wide string. This memory should be freed using FreeMem. }
  271. { outlen will contain number of wide characters stored to result buffer, including null-terminator. }
  272. function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
  273. var
  274. len: longint;
  275. begin
  276. while True do begin
  277. if strlen <> -1 then
  278. len:=strlen + 1
  279. else
  280. len:=AnsiToWideBuf(str, -1, nil, 0);
  281. if len > 0 then
  282. begin
  283. len:=len*SizeOf(WideChar);
  284. GetMem(Result, len);
  285. len:=AnsiToWideBuf(str, strlen, Result, len);
  286. if (len = 0) and (strlen <> -1) then
  287. begin
  288. FreeMem(Result);
  289. strlen:=-1;
  290. continue;
  291. end;
  292. end
  293. else begin
  294. GetMem(Result, SizeOf(WideChar));
  295. len:=1;
  296. Result^:=#0;
  297. end;
  298. break;
  299. end;
  300. if outlen <> nil then
  301. outlen^:=len;
  302. end;
  303. { Returns dynamic memory block, which contains wide string. This memory should be freed using FreeMem. }
  304. { outlen will contain number of wide characters stored to result buffer, including null-terminator. }
  305. function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
  306. var
  307. len, wlen: longint;
  308. begin
  309. len:=Length(s);
  310. wlen:=(len + 1)*SizeOf(WideChar);
  311. GetMem(Result, wlen);
  312. wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen)*SizeOf(WideChar);
  313. if wlen = 0 then
  314. begin
  315. wlen:=AnsiToWideBuf(PChar(s), len, nil, 0)*SizeOf(WideChar);
  316. if wlen > 0 then
  317. begin
  318. ReAllocMem(Result, wlen);
  319. wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen)*SizeOf(WideChar);
  320. end
  321. else
  322. begin
  323. Result^:=#0;
  324. wlen:=SizeOf(WideChar);
  325. end;
  326. end;
  327. if outlen <> nil then
  328. outlen^:=wlen div SizeOf(WideChar);
  329. end;
  330. {*****************************************************************************
  331. WinAPI wrappers implementation
  332. *****************************************************************************}
  333. function GetFileAttributesW(p : pwidechar) : dword;
  334. cdecl; external KernelDLL name 'GetFileAttributesW';
  335. function DeleteFileW(p : pwidechar) : longint;
  336. cdecl; external KernelDLL name 'DeleteFileW';
  337. function MoveFileW(old,_new : pwidechar) : longint;
  338. cdecl; external KernelDLL name 'MoveFileW';
  339. function CreateFileW(lpFileName:pwidechar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  340. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  341. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  342. cdecl; external KernelDLL name 'CreateFileW';
  343. function CreateDirectoryW(name : pwidechar;sec : pointer) : longbool;
  344. cdecl; external KernelDLL name 'CreateDirectoryW';
  345. function RemoveDirectoryW(name:pwidechar):longbool;
  346. cdecl; external KernelDLL name 'RemoveDirectoryW';
  347. function GetFileAttributes(p : pchar) : dword;
  348. var
  349. buf: array[0..MaxPathLen] of WideChar;
  350. begin
  351. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  352. GetFileAttributes := GetFileAttributesW(buf);
  353. end;
  354. function DeleteFile(p : pchar) : longint;
  355. var
  356. buf: array[0..MaxPathLen] of WideChar;
  357. begin
  358. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  359. DeleteFile := DeleteFileW(buf);
  360. end;
  361. function MoveFile(old,_new : pchar) : longint;
  362. var
  363. buf_old, buf_new: array[0..MaxPathLen] of WideChar;
  364. begin
  365. AnsiToWideBuf(old, -1, buf_old, SizeOf(buf_old));
  366. AnsiToWideBuf(_new, -1, buf_new, SizeOf(buf_new));
  367. MoveFile := MoveFileW(buf_old, buf_new);
  368. end;
  369. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  370. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  371. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  372. var
  373. buf: array[0..MaxPathLen] of WideChar;
  374. begin
  375. AnsiToWideBuf(lpFileName, -1, buf, SizeOf(buf));
  376. CreateFile := CreateFileW(buf, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  377. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  378. end;
  379. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  380. var
  381. buf: array[0..MaxPathLen] of WideChar;
  382. begin
  383. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  384. CreateDirectory := CreateDirectoryW(buf, sec);
  385. end;
  386. function RemoveDirectory(name:pointer):longbool;
  387. var
  388. buf: array[0..MaxPathLen] of WideChar;
  389. begin
  390. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  391. RemoveDirectory := RemoveDirectoryW(buf);
  392. end;
  393. const
  394. {$ifdef CPUARM}
  395. UserKData = $FFFFC800;
  396. {$else CPUARM}
  397. UserKData = $00005800;
  398. {$endif CPUARM}
  399. SYSHANDLE_OFFSET = $004;
  400. SYS_HANDLE_BASE = 64;
  401. SH_CURTHREAD = 1;
  402. SH_CURPROC = 2;
  403. type
  404. PHandle = ^THandle;
  405. const
  406. EVENT_PULSE = 1;
  407. EVENT_RESET = 2;
  408. EVENT_SET = 3;
  409. function CreateEventW(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:PWideChar): THandle;
  410. cdecl; external KernelDLL name 'CreateEventW';
  411. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
  412. var
  413. buf: array[0..MaxPathLen] of WideChar;
  414. begin
  415. if lpName=nil then
  416. CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, nil)
  417. else begin
  418. AnsiToWideBuf(lpName, -1, buf, SizeOf(buf));
  419. CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, buf);
  420. end;
  421. end;
  422. function EventModify(h: THandle; func: DWORD): LONGBOOL;
  423. cdecl; external KernelDLL name 'EventModify';
  424. function TlsCall(p1, p2: DWORD): DWORD;
  425. cdecl; external KernelDLL name 'TlsCall';
  426. function ResetEvent(h: THandle): LONGBOOL;
  427. begin
  428. ResetEvent := EventModify(h,EVENT_RESET);
  429. end;
  430. function SetEvent(h: THandle): LONGBOOL;
  431. begin
  432. SetEvent := EventModify(h,EVENT_SET);
  433. end;
  434. function GetCurrentProcessId:DWORD;
  435. var
  436. p: PHandle;
  437. begin
  438. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURPROC*SizeOf(THandle));
  439. GetCurrentProcessId := p^;
  440. end;
  441. function Win32GetCurrentThreadId:DWORD;
  442. var
  443. p: PHandle;
  444. begin
  445. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURTHREAD*SizeOf(THandle));
  446. Win32GetCurrentThreadId := p^;
  447. end;
  448. const
  449. TLS_FUNCALLOC = 0;
  450. TLS_FUNCFREE = 1;
  451. function TlsAlloc : DWord;
  452. begin
  453. TlsAlloc := TlsCall(TLS_FUNCALLOC, 0);
  454. end;
  455. function TlsFree(dwTlsIndex : DWord) : LongBool;
  456. begin
  457. TlsFree := LongBool(TlsCall(TLS_FUNCFREE, dwTlsIndex));
  458. end;
  459. {*****************************************************************************
  460. Parameter Handling
  461. *****************************************************************************}
  462. function GetCommandLine : pwidechar;
  463. cdecl; external KernelDLL name 'GetCommandLineW';
  464. var
  465. ModuleName : array[0..255] of char;
  466. function GetCommandFile:pchar;
  467. var
  468. buf: array[0..MaxPathLen] of WideChar;
  469. begin
  470. if ModuleName[0] = #0 then begin
  471. GetModuleFileName(0, @buf, SizeOf(buf));
  472. WideToAnsiBuf(buf, -1, @ModuleName, SizeOf(ModuleName));
  473. end;
  474. GetCommandFile:=@ModuleName;
  475. end;
  476. var
  477. Fargc: longint;
  478. Fargv: ppchar;
  479. FCmdLine: PChar;
  480. procedure setup_arguments;
  481. var
  482. arglen,
  483. count : longint;
  484. argstart,
  485. pc,arg : pchar;
  486. quote : char;
  487. argvlen : longint;
  488. procedure allocarg(idx,len:longint);
  489. var
  490. oldargvlen : longint;
  491. begin
  492. if idx>=argvlen then
  493. begin
  494. oldargvlen:=argvlen;
  495. argvlen:=(idx+8) and (not 7);
  496. sysreallocmem(Fargv,argvlen*sizeof(pointer));
  497. fillchar(Fargv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  498. end;
  499. { use realloc to reuse already existing memory }
  500. { always allocate, even if length is zero, since }
  501. { the arg. is still present! }
  502. sysreallocmem(Fargv[idx],len+1);
  503. end;
  504. begin
  505. { create commandline, it starts with the executed filename which is argv[0] }
  506. { WinCE passes the command NOT via the args, but via getmodulefilename}
  507. if FCmdLine <> nil then exit;
  508. argvlen:=0;
  509. pc:=getcommandfile;
  510. Arglen:=0;
  511. while pc[Arglen] <> #0 do
  512. Inc(Arglen);
  513. allocarg(0,arglen);
  514. move(pc^,Fargv[0]^,arglen+1);
  515. { Setup FCmdLine variable }
  516. arg:=PChar(GetCommandLine);
  517. count:=WideToAnsiBuf(PWideChar(arg), -1, nil, 0);
  518. FCmdLine:=SysGetMem(arglen + count + 3);
  519. FCmdLine^:='"';
  520. move(pc^, (FCmdLine + 1)^, arglen);
  521. (FCmdLine + arglen + 1)^:='"';
  522. (FCmdLine + arglen + 2)^:=' ';
  523. WideToAnsiBuf(PWideChar(arg), -1, FCmdLine + arglen + 3, count);
  524. { process arguments }
  525. count:=0;
  526. pc:=FCmdLine;
  527. {$IfDef SYSTEM_DEBUG_STARTUP}
  528. Writeln(stderr,'WinCE GetCommandLine is #',pc,'#');
  529. {$EndIf }
  530. while pc^<>#0 do
  531. begin
  532. { skip leading spaces }
  533. while pc^ in [#1..#32] do
  534. inc(pc);
  535. if pc^=#0 then
  536. break;
  537. { calc argument length }
  538. quote:=' ';
  539. argstart:=pc;
  540. arglen:=0;
  541. while (pc^<>#0) do
  542. begin
  543. case pc^ of
  544. #1..#32 :
  545. begin
  546. if quote<>' ' then
  547. inc(arglen)
  548. else
  549. break;
  550. end;
  551. '"' :
  552. begin
  553. if quote<>'''' then
  554. begin
  555. if pchar(pc+1)^<>'"' then
  556. begin
  557. if quote='"' then
  558. quote:=' '
  559. else
  560. quote:='"';
  561. end
  562. else
  563. inc(pc);
  564. end
  565. else
  566. inc(arglen);
  567. end;
  568. '''' :
  569. begin
  570. if quote<>'"' then
  571. begin
  572. if pchar(pc+1)^<>'''' then
  573. begin
  574. if quote='''' then
  575. quote:=' '
  576. else
  577. quote:='''';
  578. end
  579. else
  580. inc(pc);
  581. end
  582. else
  583. inc(arglen);
  584. end;
  585. else
  586. inc(arglen);
  587. end;
  588. inc(pc);
  589. end;
  590. { copy argument }
  591. { Don't copy the first one, it is already there.}
  592. If Count<>0 then
  593. begin
  594. allocarg(count,arglen);
  595. quote:=' ';
  596. pc:=argstart;
  597. arg:=Fargv[count];
  598. while (pc^<>#0) do
  599. begin
  600. case pc^ of
  601. #1..#32 :
  602. begin
  603. if quote<>' ' then
  604. begin
  605. arg^:=pc^;
  606. inc(arg);
  607. end
  608. else
  609. break;
  610. end;
  611. '"' :
  612. begin
  613. if quote<>'''' then
  614. begin
  615. if pchar(pc+1)^<>'"' then
  616. begin
  617. if quote='"' then
  618. quote:=' '
  619. else
  620. quote:='"';
  621. end
  622. else
  623. inc(pc);
  624. end
  625. else
  626. begin
  627. arg^:=pc^;
  628. inc(arg);
  629. end;
  630. end;
  631. '''' :
  632. begin
  633. if quote<>'"' then
  634. begin
  635. if pchar(pc+1)^<>'''' then
  636. begin
  637. if quote='''' then
  638. quote:=' '
  639. else
  640. quote:='''';
  641. end
  642. else
  643. inc(pc);
  644. end
  645. else
  646. begin
  647. arg^:=pc^;
  648. inc(arg);
  649. end;
  650. end;
  651. else
  652. begin
  653. arg^:=pc^;
  654. inc(arg);
  655. end;
  656. end;
  657. inc(pc);
  658. end;
  659. arg^:=#0;
  660. end;
  661. {$IfDef SYSTEM_DEBUG_STARTUP}
  662. Writeln(stderr,'dos arg ',count,' #',arglen,'#',Fargv[count],'#');
  663. {$EndIf SYSTEM_DEBUG_STARTUP}
  664. inc(count);
  665. end;
  666. { get argc and create an nil entry }
  667. Fargc:=count;
  668. allocarg(argc,0);
  669. { free unused memory }
  670. sysreallocmem(Fargv,(argc+1)*sizeof(pointer));
  671. end;
  672. function CmdLine: PChar;
  673. begin
  674. setup_arguments;
  675. Result:=FCmdLine;
  676. end;
  677. function argc: longint;
  678. begin
  679. setup_arguments;
  680. Result:=Fargc;
  681. end;
  682. function argv: ppchar;
  683. begin
  684. setup_arguments;
  685. Result:=Fargv;
  686. end;
  687. function paramcount : longint;
  688. begin
  689. paramcount := argc - 1;
  690. end;
  691. function paramstr(l : longint) : string;
  692. begin
  693. setup_arguments;
  694. if (l>=0) and (l<Fargc) then
  695. paramstr:=strpas(Fargv[l])
  696. else
  697. paramstr:='';
  698. end;
  699. procedure randomize;
  700. begin
  701. randseed:=GetTickCount;
  702. end;
  703. {*****************************************************************************
  704. System Dependent Exit code
  705. *****************************************************************************}
  706. procedure PascalMain;external name 'PASCALMAIN';
  707. procedure ExitThread(Exitcode : longint); cdecl; external 'coredll';
  708. Procedure system_exit;
  709. begin
  710. if IsLibrary then
  711. exit;
  712. if not IsConsole then
  713. begin
  714. Close(stderr);
  715. Close(stdout);
  716. Close(erroutput);
  717. Close(Input);
  718. Close(Output);
  719. end;
  720. ExitThread(exitcode);
  721. end;
  722. {$ifdef cpu386}
  723. var
  724. { value of the stack segment
  725. to check if the call stack can be written on exceptions }
  726. _SS : Cardinal;
  727. {$endif cpu386}
  728. Const
  729. { DllEntryPoint }
  730. DLL_PROCESS_ATTACH = 1;
  731. DLL_THREAD_ATTACH = 2;
  732. DLL_PROCESS_DETACH = 0;
  733. DLL_THREAD_DETACH = 3;
  734. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  735. begin
  736. IsLibrary:=true;
  737. Dll_entry:=false;
  738. case DLLreason of
  739. DLL_PROCESS_ATTACH :
  740. begin
  741. PASCALMAIN;
  742. Dll_entry:=true;
  743. end;
  744. DLL_THREAD_ATTACH :
  745. begin
  746. { Allocate Threadvars ?!}
  747. if assigned(Dll_Thread_Attach_Hook) then
  748. Dll_Thread_Attach_Hook(DllParam);
  749. end;
  750. DLL_THREAD_DETACH :
  751. begin
  752. if assigned(Dll_Thread_Detach_Hook) then
  753. Dll_Thread_Detach_Hook(DllParam);
  754. { Release Threadvars ?!}
  755. end;
  756. DLL_PROCESS_DETACH :
  757. begin
  758. Lib_Exit;
  759. if assigned(Dll_Process_Detach_Hook) then
  760. Dll_Process_Detach_Hook(DllParam);
  761. end;
  762. end;
  763. end;
  764. {$ifdef WINCE_EXCEPTION_HANDLING}
  765. //
  766. // Hardware exception handling
  767. //
  768. {
  769. Error code definitions for the WinCE API functions
  770. Values are 32 bit values layed out as follows:
  771. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  772. 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  773. +---+-+-+-----------------------+-------------------------------+
  774. |Sev|C|R| Facility | Code |
  775. +---+-+-+-----------------------+-------------------------------+
  776. where
  777. Sev - is the severity code
  778. 00 - Success
  779. 01 - Informational
  780. 10 - Warning
  781. 11 - Error
  782. C - is the Customer code flag
  783. R - is a reserved bit
  784. Facility - is the facility code
  785. Code - is the facility's status code
  786. }
  787. const
  788. SEVERITY_SUCCESS = $00000000;
  789. SEVERITY_INFORMATIONAL = $40000000;
  790. SEVERITY_WARNING = $80000000;
  791. SEVERITY_ERROR = $C0000000;
  792. const
  793. STATUS_SEGMENT_NOTIFICATION = $40000005;
  794. DBG_TERMINATE_THREAD = $40010003;
  795. DBG_TERMINATE_PROCESS = $40010004;
  796. DBG_CONTROL_C = $40010005;
  797. DBG_CONTROL_BREAK = $40010008;
  798. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  799. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  800. STATUS_BREAKPOINT = $80000003;
  801. STATUS_SINGLE_STEP = $80000004;
  802. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  803. STATUS_ACCESS_VIOLATION = $C0000005;
  804. STATUS_IN_PAGE_ERROR = $C0000006;
  805. STATUS_INVALID_HANDLE = $C0000008;
  806. STATUS_NO_MEMORY = $C0000017;
  807. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  808. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  809. STATUS_INVALID_DISPOSITION = $C0000026;
  810. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  811. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  812. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  813. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  814. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  815. STATUS_FLOAT_OVERFLOW = $C0000091;
  816. STATUS_FLOAT_STACK_CHECK = $C0000092;
  817. STATUS_FLOAT_UNDERFLOW = $C0000093;
  818. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  819. STATUS_INTEGER_OVERFLOW = $C0000095;
  820. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  821. STATUS_STACK_OVERFLOW = $C00000FD;
  822. STATUS_CONTROL_C_EXIT = $C000013A;
  823. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  824. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  825. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  826. const
  827. ExceptionContinueExecution = 0;
  828. ExceptionContinueSearch = 1;
  829. ExceptionNestedException = 2;
  830. ExceptionCollidedUnwind = 3;
  831. ExceptionExecuteHandler = 4;
  832. MaxExceptionLevel = 16;
  833. exceptLevel : Byte = 0;
  834. {$ifdef CPUARM}
  835. const
  836. CONTEXT_ARM = $0000040;
  837. CONTEXT_CONTROL = CONTEXT_ARM or $00000001;
  838. CONTEXT_INTEGER = CONTEXT_ARM or $00000002;
  839. CONTEXT_SEGMENTS = CONTEXT_ARM or $00000004;
  840. CONTEXT_FLOATING_POINT = CONTEXT_ARM or $00000008;
  841. CONTEXT_DEBUG_REGISTERS = CONTEXT_ARM or $00000010;
  842. CONTEXT_EXTENDED_REGISTERS = CONTEXT_ARM or $00000020;
  843. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  844. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  845. NUM_VFP_REGS = 32;
  846. NUM_EXTRA_CONTROL_REGS = 8;
  847. type
  848. PContext = ^TContext;
  849. TContext = record
  850. ContextFlags : LongWord;
  851. // This section is specified/returned if the ContextFlags word contains
  852. // the flag CONTEXT_INTEGER.
  853. R0 : LongWord;
  854. R1 : LongWord;
  855. R2 : LongWord;
  856. R3 : LongWord;
  857. R4 : LongWord;
  858. R5 : LongWord;
  859. R6 : LongWord;
  860. R7 : LongWord;
  861. R8 : LongWord;
  862. R9 : LongWord;
  863. R10 : LongWord;
  864. R11 : LongWord;
  865. R12 : LongWord;
  866. // This section is specified/returned if the ContextFlags word contains
  867. // the flag CONTEXT_CONTROL.
  868. Sp : LongWord;
  869. Lr : LongWord;
  870. Pc : LongWord;
  871. Psr : LongWord;
  872. Fpscr : LongWord;
  873. FpExc : LongWord;
  874. // Floating point registers
  875. S : array[0..(NUM_VFP_REGS + 1)-1] of LongWord;
  876. FpExtra : array[0..(NUM_EXTRA_CONTROL_REGS)-1] of LongWord;
  877. end;
  878. {$endif CPUARM}
  879. {$ifdef CPUI386}
  880. const
  881. CONTEXT_X86 = $00010000;
  882. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  883. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  884. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  885. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  886. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  887. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  888. MAXIMUM_SUPPORTED_EXTENSION = 512;
  889. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  890. type
  891. PFloatingSaveArea = ^TFloatingSaveArea;
  892. TFloatingSaveArea = packed record
  893. ControlWord : Cardinal;
  894. StatusWord : Cardinal;
  895. TagWord : Cardinal;
  896. ErrorOffset : Cardinal;
  897. ErrorSelector : Cardinal;
  898. DataOffset : Cardinal;
  899. DataSelector : Cardinal;
  900. RegisterArea : array[0..79] of Byte;
  901. Cr0NpxState : Cardinal;
  902. end;
  903. PContext = ^TContext;
  904. TContext = packed record
  905. //
  906. // The flags values within this flag control the contents of
  907. // a CONTEXT record.
  908. //
  909. ContextFlags : Cardinal;
  910. //
  911. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  912. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  913. // included in CONTEXT_FULL.
  914. //
  915. Dr0, Dr1, Dr2,
  916. Dr3, Dr6, Dr7 : Cardinal;
  917. //
  918. // This section is specified/returned if the
  919. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  920. //
  921. FloatSave : TFloatingSaveArea;
  922. //
  923. // This section is specified/returned if the
  924. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  925. //
  926. SegGs, SegFs,
  927. SegEs, SegDs : Cardinal;
  928. //
  929. // This section is specified/returned if the
  930. // ContextFlags word contains the flag CONTEXT_INTEGER.
  931. //
  932. Edi, Esi, Ebx,
  933. Edx, Ecx, Eax : Cardinal;
  934. //
  935. // This section is specified/returned if the
  936. // ContextFlags word contains the flag CONTEXT_CONTROL.
  937. //
  938. Ebp : Cardinal;
  939. Eip : Cardinal;
  940. SegCs : Cardinal;
  941. EFlags, Esp, SegSs : Cardinal;
  942. //
  943. // This section is specified/returned if the ContextFlags word
  944. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  945. // The format and contexts are processor specific
  946. //
  947. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  948. end;
  949. {$endif CPUI386}
  950. type
  951. PExceptionRecord = ^TExceptionRecord;
  952. TExceptionRecord = packed record
  953. ExceptionCode : Longint;
  954. ExceptionFlags : Longint;
  955. ExceptionRecord : PExceptionRecord;
  956. ExceptionAddress : Pointer;
  957. NumberParameters : Longint;
  958. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  959. end;
  960. PExceptionPointers = ^TExceptionPointers;
  961. TExceptionPointers = packed record
  962. ExceptionRecord : PExceptionRecord;
  963. ContextRecord : PContext;
  964. end;
  965. {$ifdef CPUI386}
  966. {**************************** i386 Exception handling *****************************************}
  967. function GetCurrentProcess:DWORD;
  968. begin
  969. GetCurrentProcess := SH_CURPROC+SYS_HANDLE_BASE;
  970. end;
  971. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  972. cdecl; external 'coredll' name 'ReadProcessMemory';
  973. function is_prefetch(p : pointer) : boolean;
  974. var
  975. a : array[0..15] of byte;
  976. doagain : boolean;
  977. instrlo,instrhi,opcode : byte;
  978. i : longint;
  979. begin
  980. result:=false;
  981. { read memory savely without causing another exeception }
  982. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  983. exit;
  984. i:=0;
  985. doagain:=true;
  986. while doagain and (i<15) do
  987. begin
  988. opcode:=a[i];
  989. instrlo:=opcode and $f;
  990. instrhi:=opcode and $f0;
  991. case instrhi of
  992. { prefix? }
  993. $20,$30:
  994. doagain:=(instrlo and 7)=6;
  995. $60:
  996. doagain:=(instrlo and $c)=4;
  997. $f0:
  998. doagain:=instrlo in [0,2,3];
  999. $0:
  1000. begin
  1001. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  1002. exit;
  1003. end;
  1004. else
  1005. doagain:=false;
  1006. end;
  1007. inc(i);
  1008. end;
  1009. end;
  1010. var
  1011. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1012. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1013. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1014. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1015. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1016. begin
  1017. if IsConsole then
  1018. begin
  1019. write(stderr,'HandleErrorAddrFrame(error=',error);
  1020. write(stderr,',addr=',hexstr(addr,8));
  1021. writeln(stderr,',frame=',hexstr(frame,8),')');
  1022. end;
  1023. HandleErrorAddrFrame(error,addr,frame);
  1024. end;
  1025. {$endif SYSTEMEXCEPTIONDEBUG}
  1026. procedure JumpToHandleErrorFrame;
  1027. var
  1028. eip, ebp, error : Longint;
  1029. begin
  1030. // save ebp
  1031. asm
  1032. movl (%ebp),%eax
  1033. movl %eax,ebp
  1034. end;
  1035. if (exceptLevel > 0) then
  1036. dec(exceptLevel);
  1037. eip:=exceptEip[exceptLevel];
  1038. error:=exceptError[exceptLevel];
  1039. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1040. if IsConsole then
  1041. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1042. {$endif SYSTEMEXCEPTIONDEBUG}
  1043. if resetFPU[exceptLevel] then
  1044. SysResetFPU;
  1045. { build a fake stack }
  1046. asm
  1047. {$ifdef REGCALL}
  1048. movl ebp,%ecx
  1049. movl eip,%edx
  1050. movl error,%eax
  1051. pushl eip
  1052. movl ebp,%ebp // Change frame pointer
  1053. {$else}
  1054. movl ebp,%eax
  1055. pushl %eax
  1056. movl eip,%eax
  1057. pushl %eax
  1058. movl error,%eax
  1059. pushl %eax
  1060. movl eip,%eax
  1061. pushl %eax
  1062. movl ebp,%ebp // Change frame pointer
  1063. {$endif}
  1064. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1065. jmpl DebugHandleErrorAddrFrame
  1066. {$else not SYSTEMEXCEPTIONDEBUG}
  1067. jmpl HandleErrorAddrFrame
  1068. {$endif SYSTEMEXCEPTIONDEBUG}
  1069. end;
  1070. end;
  1071. function i386_exception_handler(ExceptionRecord: PExceptionRecord;
  1072. EstablisherFrame: pointer; ContextRecord: PContext;
  1073. DispatcherContext: pointer): longint; cdecl;
  1074. var
  1075. res: longint;
  1076. must_reset_fpu: boolean;
  1077. begin
  1078. res := ExceptionContinueSearch;
  1079. if ContextRecord^.SegSs=_SS then begin
  1080. must_reset_fpu := true;
  1081. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1082. if IsConsole then Writeln(stderr,'Exception ',
  1083. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1084. {$endif SYSTEMEXCEPTIONDEBUG}
  1085. case cardinal(ExceptionRecord^.ExceptionCode) of
  1086. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1087. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1088. res := 200;
  1089. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1090. begin
  1091. res := 201;
  1092. must_reset_fpu := false;
  1093. end;
  1094. STATUS_STACK_OVERFLOW :
  1095. begin
  1096. res := 202;
  1097. must_reset_fpu := false;
  1098. end;
  1099. STATUS_FLOAT_OVERFLOW :
  1100. res := 205;
  1101. STATUS_FLOAT_DENORMAL_OPERAND,
  1102. STATUS_FLOAT_UNDERFLOW :
  1103. res := 206;
  1104. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1105. STATUS_FLOAT_INEXACT_RESULT,
  1106. STATUS_FLOAT_INVALID_OPERATION,
  1107. STATUS_FLOAT_STACK_CHECK :
  1108. res := 207;
  1109. STATUS_INTEGER_OVERFLOW :
  1110. begin
  1111. res := 215;
  1112. must_reset_fpu := false;
  1113. end;
  1114. STATUS_ILLEGAL_INSTRUCTION:
  1115. res := 216;
  1116. STATUS_ACCESS_VIOLATION:
  1117. { Athlon prefetch bug? }
  1118. if is_prefetch(pointer(ContextRecord^.Eip)) then
  1119. begin
  1120. { if yes, then retry }
  1121. ExceptionRecord^.ExceptionCode := 0;
  1122. res:=ExceptionContinueExecution;
  1123. end
  1124. else
  1125. res := 216;
  1126. STATUS_CONTROL_C_EXIT:
  1127. res := 217;
  1128. STATUS_PRIVILEGED_INSTRUCTION:
  1129. begin
  1130. res := 218;
  1131. must_reset_fpu := false;
  1132. end;
  1133. else
  1134. begin
  1135. if ((ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1136. res := 217
  1137. else
  1138. res := 255;
  1139. end;
  1140. end;
  1141. if (res >= 200) and (exceptLevel < MaxExceptionLevel) then begin
  1142. exceptEip[exceptLevel] := ContextRecord^.Eip;
  1143. exceptError[exceptLevel] := res;
  1144. resetFPU[exceptLevel] := must_reset_fpu;
  1145. inc(exceptLevel);
  1146. ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1147. ExceptionRecord^.ExceptionCode := 0;
  1148. res := ExceptionContinueExecution;
  1149. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1150. if IsConsole then begin
  1151. writeln(stderr,'Exception Continue Exception set at ',
  1152. hexstr(exceptEip[exceptLevel],8));
  1153. writeln(stderr,'Eip changed to ',
  1154. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1155. end;
  1156. {$endif SYSTEMEXCEPTIONDEBUG}
  1157. end;
  1158. end;
  1159. i386_exception_handler := res;
  1160. end;
  1161. {$endif CPUI386}
  1162. {$ifdef CPUARM}
  1163. {**************************** ARM Exception handling *****************************************}
  1164. var
  1165. exceptPC : array[0..MaxExceptionLevel-1] of Longint;
  1166. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1167. procedure JumpToHandleErrorFrame;
  1168. var
  1169. _pc, _fp, _error : Longint;
  1170. begin
  1171. // get original fp
  1172. asm
  1173. ldr r0,[r11,#-12]
  1174. str r0,_fp
  1175. end;
  1176. if (exceptLevel > 0) then
  1177. dec(exceptLevel);
  1178. _pc:=exceptPC[exceptLevel];
  1179. _error:=exceptError[exceptLevel];
  1180. asm
  1181. ldr r0,_error
  1182. ldr r1,_pc
  1183. ldr r2,_fp
  1184. mov r11,r2 // Change frame pointer
  1185. b HandleErrorAddrFrame
  1186. end;
  1187. end;
  1188. function ARM_ExceptionHandler(ExceptionRecord: PExceptionRecord;
  1189. EstablisherFrame: pointer; ContextRecord: PContext;
  1190. DispatcherContext: pointer): longint; [public, alias : '_ARM_ExceptionHandler'];
  1191. var
  1192. res: longint;
  1193. begin
  1194. res := ExceptionContinueSearch;
  1195. case cardinal(ExceptionRecord^.ExceptionCode) of
  1196. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1197. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1198. res := 200;
  1199. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1200. res := 201;
  1201. STATUS_STACK_OVERFLOW :
  1202. res := 202;
  1203. STATUS_FLOAT_OVERFLOW :
  1204. res := 205;
  1205. STATUS_FLOAT_DENORMAL_OPERAND,
  1206. STATUS_FLOAT_UNDERFLOW :
  1207. res := 206;
  1208. STATUS_FLOAT_INEXACT_RESULT,
  1209. STATUS_FLOAT_INVALID_OPERATION,
  1210. STATUS_FLOAT_STACK_CHECK :
  1211. res := 207;
  1212. STATUS_INTEGER_OVERFLOW :
  1213. res := 215;
  1214. STATUS_ILLEGAL_INSTRUCTION:
  1215. res := 216;
  1216. STATUS_ACCESS_VIOLATION:
  1217. res := 216;
  1218. STATUS_DATATYPE_MISALIGNMENT:
  1219. res := 214;
  1220. STATUS_CONTROL_C_EXIT:
  1221. res := 217;
  1222. STATUS_PRIVILEGED_INSTRUCTION:
  1223. res := 218;
  1224. else
  1225. begin
  1226. if ((cardinal(ExceptionRecord^.ExceptionCode) and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1227. res := 217
  1228. else
  1229. res := 255;
  1230. end;
  1231. end;
  1232. if (res <> ExceptionContinueSearch) and (exceptLevel < MaxExceptionLevel) then begin
  1233. exceptPC[exceptLevel] := ContextRecord^.PC;
  1234. exceptError[exceptLevel] := res;
  1235. inc(exceptLevel);
  1236. ContextRecord^.PC := Longint(@JumpToHandleErrorFrame);
  1237. ExceptionRecord^.ExceptionCode := 0;
  1238. res := ExceptionContinueExecution;
  1239. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1240. if IsConsole then begin
  1241. writeln(stderr,'Exception Continue Exception set at ',
  1242. hexstr(exceptEip[exceptLevel],8));
  1243. writeln(stderr,'Eip changed to ',
  1244. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1245. end;
  1246. {$endif SYSTEMEXCEPTIONDEBUG}
  1247. end;
  1248. ARM_ExceptionHandler := res;
  1249. end;
  1250. {$endif CPUARM}
  1251. {$endif WINCE_EXCEPTION_HANDLING}
  1252. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  1253. var
  1254. st: pointer;
  1255. begin
  1256. IsLibrary:=false;
  1257. {$ifdef CPUARM}
  1258. asm
  1259. str sp,st
  1260. end;
  1261. StackTop:=st;
  1262. asm
  1263. mov fp,#0
  1264. bl PASCALMAIN;
  1265. end;
  1266. {$endif CPUARM}
  1267. {$ifdef CPUI386}
  1268. asm
  1269. {$ifdef WINCE_EXCEPTION_HANDLING}
  1270. pushl i386_exception_handler
  1271. pushl %fs:(0)
  1272. mov %esp,%fs:(0)
  1273. {$endif WINCE_EXCEPTION_HANDLING}
  1274. pushl %ebp
  1275. movl %esp,%eax
  1276. movl %eax,st
  1277. end;
  1278. StackTop:=st;
  1279. asm
  1280. xorl %eax,%eax
  1281. movw %ss,%ax
  1282. movl %eax,_SS
  1283. xorl %ebp,%ebp
  1284. call PASCALMAIN
  1285. popl %ebp
  1286. {$ifdef WINCE_EXCEPTION_HANDLING}
  1287. popl %fs:(0)
  1288. addl $4, %esp
  1289. {$endif WINCE_EXCEPTION_HANDLING}
  1290. end;
  1291. {$endif CPUI386}
  1292. end;
  1293. procedure _FPC_mainCRTStartup;public name '_mainCRTStartup';
  1294. begin
  1295. IsConsole:=True;
  1296. Exe_entry;
  1297. end;
  1298. procedure _FPC_WinMainCRTStartup;public name '_WinMainCRTStartup';
  1299. begin
  1300. IsConsole:=False;
  1301. Exe_entry;
  1302. end;
  1303. procedure _FPC_DLLMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLMainCRTStartup';
  1304. begin
  1305. IsConsole:=true;
  1306. sysinstance:=_hinstance;
  1307. dllreason:=_dllreason;
  1308. dllparam:=_dllparam;
  1309. DLL_Entry;
  1310. end;
  1311. procedure _FPC_DLLWinMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLWinMainCRTStartup';
  1312. begin
  1313. IsConsole:=false;
  1314. sysinstance:=_hinstance;
  1315. dllreason:=_dllreason;
  1316. dllparam:=_dllparam;
  1317. DLL_Entry;
  1318. end;
  1319. {****************************************************************************
  1320. OS dependend widestrings
  1321. ****************************************************************************}
  1322. function CharUpperBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharUpperBuffW';
  1323. function CharLowerBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharLowerBuffW';
  1324. procedure WinCEWide2AnsiMove(source:pwidechar;var dest:RawByteString;cp:TSystemCodePage;len:SizeInt);
  1325. var
  1326. destlen: SizeInt;
  1327. begin
  1328. // retrieve length including trailing #0
  1329. // not anymore, because this must also be usable for single characters
  1330. destlen:=WideCharToMultiByte(cp, 0, source, len, nil, 0, nil, nil);
  1331. // this will null-terminate
  1332. setlength(dest, destlen);
  1333. if destlen>0 then
  1334. begin
  1335. WideCharToMultiByte(cp, 0, source, len, @dest[1], destlen, nil, nil);
  1336. PAnsiRec(pointer(dest)-AnsiFirstOff)^.CodePage:=cp;
  1337. end;
  1338. end;
  1339. procedure WinCEAnsi2WideMove(source:pchar;cp:TSystemCodePage;var dest:widestring;len:SizeInt);
  1340. var
  1341. destlen: SizeInt;
  1342. dwFlags: DWORD;
  1343. begin
  1344. if cp=CP_UTF8 then
  1345. dwFlags:=0
  1346. else
  1347. dwFlags:=MB_PRECOMPOSED;
  1348. destlen:=MultiByteToWideChar(cp, dwFlags, source, len, nil, 0);
  1349. // this will null-terminate
  1350. setlength(dest, destlen);
  1351. if destlen>0 then
  1352. MultiByteToWideChar(cp, dwFlags, source, len, @dest[1], destlen);
  1353. end;
  1354. function WinCEWideUpper(const s : WideString) : WideString;
  1355. begin
  1356. result:=s;
  1357. UniqueString(result);
  1358. if length(result)>0 then
  1359. CharUpperBuff(LPWSTR(result),length(result));
  1360. end;
  1361. function WinCEWideLower(const s : WideString) : WideString;
  1362. begin
  1363. result:=s;
  1364. UniqueString(result);
  1365. if length(result)>0 then
  1366. CharLowerBuff(LPWSTR(result),length(result));
  1367. end;
  1368. procedure WinCEUnicode2AnsiMove(source:punicodechar;var dest:RawByteString;cp:TSystemCodePage;len:SizeInt);
  1369. var
  1370. destlen: SizeInt;
  1371. begin
  1372. // retrieve length including trailing #0
  1373. // not anymore, because this must also be usable for single characters
  1374. destlen:=WideCharToMultiByte(cp, 0, source, len, nil, 0, nil, nil);
  1375. // this will null-terminate
  1376. setlength(dest, destlen);
  1377. if destlen>0 then
  1378. begin
  1379. WideCharToMultiByte(cp, 0, source, len, @dest[1], destlen, nil, nil);
  1380. PAnsiRec(pointer(dest)-AnsiFirstOff)^.CodePage:=cp;
  1381. end;
  1382. end;
  1383. procedure WinCEAnsi2UnicodeMove(source:pchar;cp : TSystemCodePage;var dest:UnicodeString;len:SizeInt);
  1384. var
  1385. destlen: SizeInt;
  1386. dwflags: DWORD;
  1387. begin
  1388. if cp=CP_UTF8 then
  1389. dwFlags:=0
  1390. else
  1391. dwFlags:=MB_PRECOMPOSED;
  1392. destlen:=MultiByteToWideChar(cp, dwFlags, source, len, nil, 0);
  1393. // this will null-terminate
  1394. setlength(dest, destlen);
  1395. if destlen>0 then
  1396. begin
  1397. MultiByteToWideChar(cp, dwFlags, source, len, @dest[1], destlen);
  1398. PUnicodeRec(pointer(dest)-UnicodeFirstOff)^.CodePage:=CP_UTF16;
  1399. end;
  1400. end;
  1401. function WinCEUnicodeUpper(const s : UnicodeString) : UnicodeString;
  1402. begin
  1403. Result:=WinCEWideUpper(s);
  1404. end;
  1405. function WinCEUnicodeLower(const s : UnicodeString) : UnicodeString;
  1406. begin
  1407. Result:=WinCEWideLower(s);
  1408. end;
  1409. function WinCEGetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
  1410. begin
  1411. case stdcp of
  1412. scpAnsi: Result := GetACP;
  1413. scpConsoleInput: Result := GetConsoleCP;
  1414. scpConsoleOutput: Result := GetConsoleOutputCP;
  1415. end;
  1416. end;
  1417. { there is a similiar procedure in sysutils which inits the fields which
  1418. are only relevant for the sysutils units }
  1419. procedure InitWinCEWidestrings;
  1420. begin
  1421. widestringmanager.Wide2AnsiMoveProc:=@WinCEWide2AnsiMove;
  1422. widestringmanager.Ansi2WideMoveProc:=@WinCEAnsi2WideMove;
  1423. widestringmanager.UpperWideStringProc:=@WinCEWideUpper;
  1424. widestringmanager.LowerWideStringProc:=@WinCEWideLower;
  1425. { Unicode }
  1426. widestringmanager.Unicode2AnsiMoveProc:=@WinCEUnicode2AnsiMove;
  1427. widestringmanager.Ansi2UnicodeMoveProc:=@WinCEAnsi2UnicodeMove;
  1428. widestringmanager.UpperUnicodeStringProc:=@WinCEUnicodeUpper;
  1429. widestringmanager.LowerUnicodeStringProc:=@WinCEUnicodeLower;
  1430. { Codepage }
  1431. widestringmanager.GetStandardCodePageProc:=@WinCEGetStandardCodePage;
  1432. DefaultSystemCodePage:=GetACP;
  1433. DefaultUnicodeCodePage:=CP_UTF16;
  1434. end;
  1435. {$IFDEF HAS_MEMORYMANAGER}
  1436. {****************************************************************************
  1437. Memory manager
  1438. ****************************************************************************}
  1439. function malloc(Size : ptruint) : Pointer; cdecl; external 'coredll';
  1440. procedure free(P : pointer); cdecl; external 'coredll';
  1441. function realloc(P : Pointer; Size : ptruint) : pointer; cdecl; external 'coredll';
  1442. function _msize(P : pointer): ptruint; cdecl; external 'coredll';
  1443. function SysGetMem (Size : ptruint) : Pointer;
  1444. begin
  1445. Result:=malloc(Size);
  1446. end;
  1447. Function SysFreeMem (P : pointer) : ptruint;
  1448. begin
  1449. free(P);
  1450. Result:=0;
  1451. end;
  1452. Function SysFreeMemSize(p:pointer;Size:ptruint):ptruint;
  1453. begin
  1454. Result:=0;
  1455. if (size > 0) and (p <> nil) then
  1456. Result:=SysFreeMem(P);
  1457. end;
  1458. Function SysAllocMem(Size : ptruint) : Pointer;
  1459. begin
  1460. Result:=SysGetMem(Size);
  1461. if Result <> nil then
  1462. FillChar(Result^, Size, 0);
  1463. end;
  1464. Function SysReAllocMem (var p:pointer;Size:ptruint):Pointer;
  1465. begin
  1466. Result:=realloc(p, Size);
  1467. p:=Result;
  1468. end;
  1469. function SysTryResizeMem(var p:pointer;size : ptruint):boolean;
  1470. var
  1471. res: pointer;
  1472. begin
  1473. res:=realloc(p, Size);
  1474. Result:=(res <> nil) or (Size = 0);
  1475. if Result then
  1476. p:=res;
  1477. end;
  1478. function SysMemSize(P : pointer): ptruint;
  1479. begin
  1480. Result:=_msize(P);
  1481. end;
  1482. function SysGetHeapStatus:THeapStatus;
  1483. begin
  1484. fillchar(Result,sizeof(Result),0);
  1485. end;
  1486. function SysGetFPCHeapStatus:TFPCHeapStatus;
  1487. begin
  1488. fillchar(Result,sizeof(Result),0);
  1489. end;
  1490. {$ENDIF HAS_MEMORYMANAGER}
  1491. {****************************************************************************
  1492. Error Message writing using messageboxes
  1493. ****************************************************************************}
  1494. const
  1495. ErrorBufferLength = 1024;
  1496. var
  1497. ErrorBuf : array[0..ErrorBufferLength] of char;
  1498. ErrorBufW : array[0..ErrorBufferLength] of widechar;
  1499. ErrorLen : longint;
  1500. Function ErrorWrite(Var F: TextRec): Integer;
  1501. {
  1502. An error message should always end with #13#10#13#10
  1503. }
  1504. var
  1505. i : longint;
  1506. Begin
  1507. while F.BufPos>0 do
  1508. begin
  1509. begin
  1510. if F.BufPos+ErrorLen>ErrorBufferLength then
  1511. i:=ErrorBufferLength-ErrorLen
  1512. else
  1513. i:=F.BufPos;
  1514. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1515. inc(ErrorLen,i);
  1516. ErrorBuf[ErrorLen]:=#0;
  1517. end;
  1518. if ErrorLen=ErrorBufferLength then
  1519. begin
  1520. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1521. MessageBox(0,@ErrorBufW,'Error',$10010); { MB_SETFOREGROUND or ICON_ERROR }
  1522. ErrorLen:=0;
  1523. end;
  1524. Dec(F.BufPos,i);
  1525. end;
  1526. ErrorWrite:=0;
  1527. End;
  1528. Function ErrorClose(Var F: TextRec): Integer;
  1529. begin
  1530. if ErrorLen>0 then
  1531. begin
  1532. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1533. MessageBox(0,@ErrorBufW,'Error',$10010); { MB_SETFOREGROUND or ICON_ERROR }
  1534. ErrorLen:=0;
  1535. end;
  1536. ErrorLen:=0;
  1537. ErrorClose:=0;
  1538. end;
  1539. Function ErrorOpen(Var F: TextRec): Integer;
  1540. Begin
  1541. TextRec(F).InOutFunc:=@ErrorWrite;
  1542. TextRec(F).FlushFunc:=@ErrorWrite;
  1543. TextRec(F).CloseFunc:=@ErrorClose;
  1544. ErrorLen:=0;
  1545. ErrorOpen:=0;
  1546. End;
  1547. procedure AssignError(Var T: Text);
  1548. begin
  1549. Assign(T,'');
  1550. TextRec(T).OpenFunc:=@ErrorOpen;
  1551. Rewrite(T);
  1552. end;
  1553. function _getstdfilex(fd: integer): pointer; cdecl; external 'coredll';
  1554. function _fileno(fd: pointer): THandle; cdecl; external 'coredll';
  1555. procedure SysInitStdIO;
  1556. begin
  1557. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1558. displayed in and messagebox }
  1559. if not IsConsole then
  1560. begin
  1561. AssignError(stderr);
  1562. AssignError(stdout);
  1563. Assign(Output,'');
  1564. Assign(Input,'');
  1565. Assign(ErrOutput,'');
  1566. end
  1567. else
  1568. begin
  1569. StdInputHandle:=_fileno(_getstdfilex(0));
  1570. StdOutputHandle:=_fileno(_getstdfilex(1));
  1571. StdErrorHandle:=_fileno(_getstdfilex(2));
  1572. OpenStdIO(Input,fmInput,StdInputHandle);
  1573. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1574. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  1575. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1576. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1577. end;
  1578. end;
  1579. (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
  1580. var
  1581. ProcessID: SizeUInt;
  1582. function GetProcessID: SizeUInt;
  1583. begin
  1584. GetProcessID := ProcessID;
  1585. end;
  1586. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  1587. begin
  1588. result := stklen;
  1589. end;
  1590. procedure SysCleanup;
  1591. var
  1592. i: integer;
  1593. begin
  1594. if FCmdLine = nil then
  1595. exit;
  1596. SysFreeMem(FCmdLine);
  1597. for i:=0 to Fargc do
  1598. sysfreemem(Fargv[i]);
  1599. sysfreemem(Fargv);
  1600. end;
  1601. initialization
  1602. SysResetFPU;
  1603. if not(IsLibrary) then
  1604. SysInitFPU;
  1605. StackLength := CheckInitialStkLen(InitialStkLen);
  1606. StackBottom := StackTop - StackLength;
  1607. { some misc stuff }
  1608. hprevinst:=0;
  1609. if not IsLibrary then
  1610. SysInstance:=GetModuleHandle(nil);
  1611. MainInstance:=SysInstance;
  1612. {$IFNDEF HAS_MEMORYMANAGER}
  1613. { Setup Heap }
  1614. InitHeap;
  1615. {$ENDIF HAS_MEMORYMANAGER}
  1616. SysInitExceptions;
  1617. initunicodestringmanager;
  1618. InitWinCEWidestrings;
  1619. if not IsLibrary then
  1620. begin
  1621. SysInitStdIO;
  1622. end;
  1623. { Reset IO Error }
  1624. InOutRes:=0;
  1625. ProcessID := GetCurrentProcessID;
  1626. { threading }
  1627. InitSystemThreads;
  1628. { Reset internal error variable }
  1629. errno:=0;
  1630. initvariantmanager;
  1631. DispCallByIDProc:=@DoDispCallByIDError;
  1632. finalization
  1633. SysCleanup;
  1634. end.