system.pp 48 KB

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