system.pp 42 KB

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