system.pp 44 KB

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