system.pp 40 KB

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