system.pp 46 KB

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