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