2
0

system.pp 50 KB

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