system.pp 48 KB

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