system.pp 45 KB

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