system.pp 44 KB

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