system.pp 49 KB

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