system.pp 48 KB

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