system.pp 48 KB

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