system.pp 45 KB

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