system.pp 49 KB

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