123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2005 by Florian Klaempfl and Pavel Ozerski
- and Yury Sidorov member of the Free Pascal development team.
- FPC Pascal system unit for the WinCE.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit System;
- interface
- {$define FPC_IS_SYSTEM}
- {$ifdef SYSTEMDEBUG}
- {$define SYSTEMEXCEPTIONDEBUG}
- {$endif SYSTEMDEBUG}
- {$define WINCE_EXCEPTION_HANDLING}
- {$define DISABLE_NO_THREAD_MANAGER}
- {$define HAS_CMDLINE}
- {$define HAS_MEMORYMANAGER} // comment this line to switch from wincemm to fpcmm
- {$define HAS_WIDESTRINGMANAGER}
- {$define DISABLE_NO_DYNLIBS_MANAGER}
- {$define FPC_SYSTEM_HAS_SYSDLH}
- { include system-independent routine headers }
- {$I systemh.inc}
- const
- LineEnding = #13#10;
- LFNSupport = true;
- DirectorySeparator = '\';
- DriveSeparator = ':';
- ExtensionSeparator = '.';
- PathSeparator = ';';
- AllowDirectorySeparators : set of char = ['\','/'];
- AllowDriveSeparators : set of char = [':'];
- { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! }
- maxExitCode = 65535;
- MaxPathLen = 260;
- AllFilesMask = '*';
- const
- { Default filehandles }
- UnusedHandle : THandle = THandle(-1);
- StdInputHandle : THandle = 0;
- StdOutputHandle : THandle = 0;
- StdErrorHandle : THandle = 0;
- FileNameCaseSensitive : boolean = false;
- FileNameCasePreserving: boolean = true;
- CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
- sLineBreak = LineEnding;
- DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
- var
- { WinCE Info }
- hprevinst,
- MainInstance,
- DLLreason,DLLparam:DWord;
- type
- TDLL_Entry_Hook = procedure (dllparam : longint);
- const
- Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
- Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
- Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
- { ANSI <-> Wide }
- function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
- function WideToAnsiBuf(WideBuf: PWideChar; WideCharsLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
- function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
- function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
- { Wrappers for some WinAPI calls }
- function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
- function ResetEvent(h: THandle): LONGBOOL;
- function SetEvent(h: THandle): LONGBOOL;
- function GetCurrentProcessId:DWORD;
- function Win32GetCurrentThreadId:DWORD;
- function TlsAlloc : DWord;
- function TlsFree(dwTlsIndex : DWord) : LongBool;
- function GetFileAttributesW(p : pwidechar) : dword;
- cdecl; external KernelDLL name 'GetFileAttributesW';
- function DeleteFileW(p : pwidechar) : longint;
- cdecl; external KernelDLL name 'DeleteFileW';
- function MoveFileW(old,_new : pwidechar) : longint;
- cdecl; external KernelDLL name 'MoveFileW';
- function CreateFileW(lpFileName:pwidechar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
- lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
- dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
- cdecl; external KernelDLL name 'CreateFileW';
- {$ifdef CPUARM}
- function addd(d1,d2 : double) : double; compilerproc;
- cdecl;external 'coredll' name '__addd';
- function subd(d1,d2 : double) : double; compilerproc;
- cdecl;external 'coredll' name '__subd';
- function muld(d1,d2 : double) : double; compilerproc;
- cdecl;external 'coredll' name '__muld';
- function divd(d1,d2 : double) : double; compilerproc;
- cdecl;external 'coredll' name '__divd';
- function eqd(d1,d2 : double) : boolean; compilerproc;
- cdecl;external 'coredll' name '__eqd';
- function ned(d1,d2 : double) : boolean; compilerproc;
- cdecl;external 'coredll' name '__ned';
- function ltd(d1,d2 : double) : boolean; compilerproc;
- cdecl;external 'coredll' name '__ltd';
- function gtd(d1,d2 : double) : boolean; compilerproc;
- cdecl;external 'coredll' name '__gtd';
- function ged(d1,d2 : double) : boolean; compilerproc;
- cdecl;external 'coredll' name '__ged';
- function led(d1,d2 : double) : boolean; compilerproc;
- cdecl;external 'coredll' name '__led';
- { ***************** single ******************** }
- function eqs(d1,d2 : single) : boolean; compilerproc;
- cdecl;external 'coredll' name '__eqs';
- function nes(d1,d2 : single) : boolean; compilerproc;
- cdecl;external 'coredll' name '__nes';
- function lts(d1,d2 : single) : boolean; compilerproc;
- cdecl;external 'coredll' name '__lts';
- function gts(d1,d2 : single) : boolean; compilerproc;
- cdecl;external 'coredll' name '__gts';
- function ges(d1,d2 : single) : boolean; compilerproc;
- cdecl;external 'coredll' name '__ges';
- function les(d1,d2 : single) : boolean; compilerproc;
- cdecl;external 'coredll' name '__les';
- function dtos(d : double) : single; compilerproc;
- cdecl;external 'coredll' name '__dtos';
- function stod(d : single) : double; compilerproc;
- cdecl;external 'coredll' name '__stod';
- function negs(d : single) : single; compilerproc;
- cdecl;external 'coredll' name '__negs';
- function negd(d : double) : double; compilerproc;
- cdecl;external 'coredll' name '__negd';
- function utod(i : dword) : double; compilerproc;
- cdecl;external 'coredll' name '__utod';
- function itod(i : longint) : double; compilerproc;
- cdecl;external 'coredll' name '__itod';
- function ui64tod(i : qword) : double; compilerproc;
- cdecl;external 'coredll' name '__u64tod';
- function i64tod(i : int64) : double; compilerproc;
- cdecl;external 'coredll' name '__i64tod';
- function utos(i : dword) : single; compilerproc;
- cdecl;external 'coredll' name '__utos';
- function itos(i : longint) : single; compilerproc;
- cdecl;external 'coredll' name '__itos';
- function ui64tos(i : qword) : single; compilerproc;
- cdecl;external 'coredll' name '__u64tos';
- function i64tos(i : int64) : single; compilerproc;
- cdecl;external 'coredll' name '__i64tos';
- function adds(s1,s2 : single) : single; compilerproc;
- function subs(s1,s2 : single) : single; compilerproc;
- function muls(s1,s2 : single) : single; compilerproc;
- function divs(s1,s2 : single) : single; compilerproc;
- {$endif CPUARM}
- function CmdLine: PChar;
- { C compatible arguments }
- function argc: longint;
- function argv: ppchar;
- implementation
- var
- SysInstance : Longint;public name '_FPC_SysInstance';
- function MessageBox(w1:longint;l1,l2:PWideChar;w2:longint):longint;
- cdecl; external 'coredll' name 'MessageBoxW';
- function CreateDirectoryW(name : pwidechar;sec : pointer) : longbool;
- cdecl; external KernelDLL name 'CreateDirectoryW';
- function RemoveDirectoryW(name:pwidechar):longbool;
- cdecl; external KernelDLL name 'RemoveDirectoryW';
- {*****************************************************************************}
- {$define FPC_SYSTEM_HAS_MOVE}
- procedure memmove(dest, src: pointer; count: longint);
- cdecl; external 'coredll' name 'memmove';
- procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];
- begin
- if count > 0 then
- memmove(@dest, @source, count);
- end;
- {$define FPC_SYSTEM_HAS_COMPAREBYTE}
- function memcmp(buf1, buf2: pointer; count: longint): longint;
- cdecl; external 'coredll' name 'memcmp';
- function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt;
- begin
- CompareByte := memcmp(@buf1, @buf2, len);
- end;
- {$ifdef CPUARM}
- {$define FPC_SYSTEM_HAS_INT}
- function floor(d : double) : double;
- cdecl;external 'coredll' name 'floor';
- function ceil(d : double) : double;
- cdecl;external 'coredll' name 'ceil';
- function fpc_int_real(d: ValReal): ValReal;compilerproc;
- begin
- if d > 0 then
- fpc_int_real:=floor(d)
- else
- fpc_int_real:=ceil(d);
- end;
- {$define FPC_SYSTEM_HAS_TRUNC}
- function __dtoi64(d: double) : int64; cdecl; external 'coredll';
- function fpc_trunc_real(d : ValReal) : int64; assembler; nostackframe; compilerproc;
- asm
- b __dtoi64
- end;
- {$define FPC_SYSTEM_HAS_ABS}
- function fabs(d: double): double; cdecl; external 'coredll';
- function fpc_abs_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
- asm
- b fabs
- end;
- {$define FPC_SYSTEM_HAS_SQRT}
- function coresqrt(d: double): double; cdecl; external 'coredll' name 'sqrt';
- function fpc_sqrt_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
- asm
- b coresqrt
- end;
- function adds(s1,s2 : single) : single;
- begin
- adds := double(s1) + double(s2);
- end;
- function subs(s1,s2 : single) : single;
- begin
- subs := double(s1) - double(s2);
- end;
- function muls(s1,s2 : single) : single;
- begin
- muls := double(s1) * double(s2);
- end;
- function divs(s1,s2 : single) : single;
- begin
- divs := double(s1) / double(s2);
- end;
- {$endif CPUARM}
- {*****************************************************************************}
- { include system independent routines }
- {$I system.inc}
- {*****************************************************************************
- ANSI <-> Wide
- *****************************************************************************}
- const
- { MultiByteToWideChar }
- MB_PRECOMPOSED = 1;
- MB_COMPOSITE = 2;
- MB_ERR_INVALID_CHARS = 8;
- MB_USEGLYPHCHARS = 4;
- function MultiByteToWideChar(CodePage:UINT; dwFlags:DWORD; lpMultiByteStr:PChar; cchMultiByte:longint; lpWideCharStr:PWideChar;cchWideChar:longint):longint;
- cdecl; external 'coredll' name 'MultiByteToWideChar';
- function WideCharToMultiByte(CodePage:UINT; dwFlags:DWORD; lpWideCharStr:PWideChar; cchWideChar:longint; lpMultiByteStr:PChar;cchMultiByte:longint; lpDefaultChar:PChar; lpUsedDefaultChar:pointer):longint;
- cdecl; external 'coredll' name 'WideCharToMultiByte';
- function GetACP:UINT; cdecl; external 'coredll' name 'GetACP';
- { Returns number of characters stored to WideBuf, including null-terminator. }
- function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
- begin
- Result := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, AnsiBuf, AnsiBufLen, WideBuf, WideBufLen div SizeOf(WideChar));
- if ((AnsiBufLen <> -1) or (Result = 0)) and (WideBuf <> nil) then
- begin
- if (Result + 1)*SizeOf(WideChar) > WideBufLen then
- begin
- Result := 0;
- if WideBufLen < SizeOf(WideChar) then
- exit;
- end;
- WideBuf[Result] := #0;
- end;
- if (AnsiBufLen <> -1) and ((Result <> 0) or (AnsiBufLen = 0)) then
- Inc(Result);
- end;
- { Returns number of characters stored to AnsiBuf, including null-terminator. }
- function WideToAnsiBuf(WideBuf: PWideChar; WideCharsLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
- begin
- Result := WideCharToMultiByte(CP_ACP, 0, WideBuf, WideCharsLen, AnsiBuf, AnsiBufLen, nil, nil);
- if ((WideCharsLen <> -1) or (Result = 0)) and (AnsiBuf <> nil) then
- begin
- if Result + 1 > AnsiBufLen then
- begin
- Result := 0;
- if AnsiBufLen < 1 then
- exit;
- end;
- AnsiBuf[Result] := #0;
- end;
- if (WideCharsLen <> -1) and ((Result <> 0) or (WideCharsLen = 0)) then
- Inc(Result);
- end;
- { Returns dynamic memory block, which contains wide string. This memory should be freed using FreeMem. }
- { outlen will contain number of wide characters stored to result buffer, including null-terminator. }
- function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
- var
- len: longint;
- begin
- while True do begin
- if strlen <> -1 then
- len:=strlen + 1
- else
- len:=AnsiToWideBuf(str, -1, nil, 0);
- if len > 0 then
- begin
- len:=len*SizeOf(WideChar);
- GetMem(Result, len);
- len:=AnsiToWideBuf(str, strlen, Result, len);
- if (len = 0) and (strlen <> -1) then
- begin
- FreeMem(Result);
- strlen:=-1;
- continue;
- end;
- end
- else begin
- GetMem(Result, SizeOf(WideChar));
- len:=1;
- Result^:=#0;
- end;
- break;
- end;
- if outlen <> nil then
- outlen^:=len;
- end;
- { Returns dynamic memory block, which contains wide string. This memory should be freed using FreeMem. }
- { outlen will contain number of wide characters stored to result buffer, including null-terminator. }
- function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
- var
- len, wlen: longint;
- begin
- len:=Length(s);
- wlen:=(len + 1)*SizeOf(WideChar);
- GetMem(Result, wlen);
- wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen)*SizeOf(WideChar);
- if wlen = 0 then
- begin
- wlen:=AnsiToWideBuf(PChar(s), len, nil, 0)*SizeOf(WideChar);
- if wlen > 0 then
- begin
- ReAllocMem(Result, wlen);
- wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen)*SizeOf(WideChar);
- end
- else
- begin
- Result^:=#0;
- wlen:=SizeOf(WideChar);
- end;
- end;
- if outlen <> nil then
- outlen^:=wlen div SizeOf(WideChar);
- end;
- {*****************************************************************************
- WinAPI wrappers implementation
- *****************************************************************************}
- const
- {$ifdef CPUARM}
- UserKData = $FFFFC800;
- {$else CPUARM}
- UserKData = $00005800;
- {$endif CPUARM}
- SYSHANDLE_OFFSET = $004;
- SYS_HANDLE_BASE = 64;
- SH_CURTHREAD = 1;
- SH_CURPROC = 2;
- type
- PHandle = ^THandle;
- const
- EVENT_PULSE = 1;
- EVENT_RESET = 2;
- EVENT_SET = 3;
- function CreateEventW(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:PWideChar): THandle;
- cdecl; external KernelDLL name 'CreateEventW';
- function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
- var
- buf: array[0..MaxPathLen] of WideChar;
- begin
- if lpName=nil then
- CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, nil)
- else begin
- AnsiToWideBuf(lpName, -1, buf, SizeOf(buf));
- CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, buf);
- end;
- end;
- function EventModify(h: THandle; func: DWORD): LONGBOOL;
- cdecl; external KernelDLL name 'EventModify';
- function TlsCall(p1, p2: DWORD): DWORD;
- cdecl; external KernelDLL name 'TlsCall';
- function ResetEvent(h: THandle): LONGBOOL;
- begin
- ResetEvent := EventModify(h,EVENT_RESET);
- end;
- function SetEvent(h: THandle): LONGBOOL;
- begin
- SetEvent := EventModify(h,EVENT_SET);
- end;
- function GetCurrentProcessId:DWORD;
- var
- p: PHandle;
- begin
- p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURPROC*SizeOf(THandle));
- GetCurrentProcessId := p^;
- end;
- function Win32GetCurrentThreadId:DWORD;
- var
- p: PHandle;
- begin
- p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURTHREAD*SizeOf(THandle));
- Win32GetCurrentThreadId := p^;
- end;
- const
- TLS_FUNCALLOC = 0;
- TLS_FUNCFREE = 1;
- function TlsAlloc : DWord;
- begin
- TlsAlloc := TlsCall(TLS_FUNCALLOC, 0);
- end;
- function TlsFree(dwTlsIndex : DWord) : LongBool;
- begin
- TlsFree := LongBool(TlsCall(TLS_FUNCFREE, dwTlsIndex));
- end;
- {*****************************************************************************
- Parameter Handling
- *****************************************************************************}
- function GetCommandLine : pwidechar;
- cdecl; external KernelDLL name 'GetCommandLineW';
- var
- ModuleName : array[0..255] of char;
- function GetCommandFile:pchar;
- var
- buf: array[0..MaxPathLen] of WideChar;
- begin
- if ModuleName[0] = #0 then begin
- GetModuleFileName(0, @buf, SizeOf(buf));
- WideToAnsiBuf(buf, -1, @ModuleName, SizeOf(ModuleName));
- end;
- GetCommandFile:=@ModuleName;
- end;
- var
- Fargc: longint;
- Fargv: ppchar;
- FCmdLine: PChar;
- procedure setup_arguments;
- var
- arglen,
- count : longint;
- argstart,
- pc,arg : pchar;
- quote : char;
- argvlen : longint;
- procedure allocarg(idx,len:longint);
- var
- oldargvlen : longint;
- begin
- if idx>=argvlen then
- begin
- oldargvlen:=argvlen;
- argvlen:=(idx+8) and (not 7);
- sysreallocmem(Fargv,argvlen*sizeof(pointer));
- fillchar(Fargv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
- end;
- { use realloc to reuse already existing memory }
- { always allocate, even if length is zero, since }
- { the arg. is still present! }
- sysreallocmem(Fargv[idx],len+1);
- end;
- begin
- { create commandline, it starts with the executed filename which is argv[0] }
- { WinCE passes the command NOT via the args, but via getmodulefilename}
- if FCmdLine <> nil then exit;
- argvlen:=0;
- pc:=getcommandfile;
- Arglen:=0;
- while pc[Arglen] <> #0 do
- Inc(Arglen);
- allocarg(0,arglen);
- move(pc^,Fargv[0]^,arglen+1);
- { Setup FCmdLine variable }
- arg:=PChar(GetCommandLine);
- count:=WideToAnsiBuf(PWideChar(arg), -1, nil, 0);
- FCmdLine:=SysGetMem(arglen + count + 3);
- FCmdLine^:='"';
- move(pc^, (FCmdLine + 1)^, arglen);
- (FCmdLine + arglen + 1)^:='"';
- (FCmdLine + arglen + 2)^:=' ';
- WideToAnsiBuf(PWideChar(arg), -1, FCmdLine + arglen + 3, count);
- { process arguments }
- count:=0;
- pc:=FCmdLine;
- {$IfDef SYSTEM_DEBUG_STARTUP}
- Writeln(stderr,'WinCE GetCommandLine is #',pc,'#');
- {$EndIf }
- while pc^<>#0 do
- begin
- { skip leading spaces }
- while pc^ in [#1..#32] do
- inc(pc);
- if pc^=#0 then
- break;
- { calc argument length }
- quote:=' ';
- argstart:=pc;
- arglen:=0;
- while (pc^<>#0) do
- begin
- case pc^ of
- #1..#32 :
- begin
- if quote<>' ' then
- inc(arglen)
- else
- break;
- end;
- '"' :
- begin
- if quote<>'''' then
- begin
- if pchar(pc+1)^<>'"' then
- begin
- if quote='"' then
- quote:=' '
- else
- quote:='"';
- end
- else
- inc(pc);
- end
- else
- inc(arglen);
- end;
- '''' :
- begin
- if quote<>'"' then
- begin
- if pchar(pc+1)^<>'''' then
- begin
- if quote='''' then
- quote:=' '
- else
- quote:='''';
- end
- else
- inc(pc);
- end
- else
- inc(arglen);
- end;
- else
- inc(arglen);
- end;
- inc(pc);
- end;
- { copy argument }
- { Don't copy the first one, it is already there.}
- If Count<>0 then
- begin
- allocarg(count,arglen);
- quote:=' ';
- pc:=argstart;
- arg:=Fargv[count];
- while (pc^<>#0) do
- begin
- case pc^ of
- #1..#32 :
- begin
- if quote<>' ' then
- begin
- arg^:=pc^;
- inc(arg);
- end
- else
- break;
- end;
- '"' :
- begin
- if quote<>'''' then
- begin
- if pchar(pc+1)^<>'"' then
- begin
- if quote='"' then
- quote:=' '
- else
- quote:='"';
- end
- else
- inc(pc);
- end
- else
- begin
- arg^:=pc^;
- inc(arg);
- end;
- end;
- '''' :
- begin
- if quote<>'"' then
- begin
- if pchar(pc+1)^<>'''' then
- begin
- if quote='''' then
- quote:=' '
- else
- quote:='''';
- end
- else
- inc(pc);
- end
- else
- begin
- arg^:=pc^;
- inc(arg);
- end;
- end;
- else
- begin
- arg^:=pc^;
- inc(arg);
- end;
- end;
- inc(pc);
- end;
- arg^:=#0;
- end;
- {$IfDef SYSTEM_DEBUG_STARTUP}
- Writeln(stderr,'dos arg ',count,' #',arglen,'#',Fargv[count],'#');
- {$EndIf SYSTEM_DEBUG_STARTUP}
- inc(count);
- end;
- { get argc and create an nil entry }
- Fargc:=count;
- allocarg(argc,0);
- { free unused memory }
- sysreallocmem(Fargv,(argc+1)*sizeof(pointer));
- end;
- function CmdLine: PChar;
- begin
- setup_arguments;
- Result:=FCmdLine;
- end;
- function argc: longint;
- begin
- setup_arguments;
- Result:=Fargc;
- end;
- function argv: ppchar;
- begin
- setup_arguments;
- Result:=Fargv;
- end;
- function paramcount : longint;
- begin
- paramcount := argc - 1;
- end;
- function paramstr(l : longint) : string;
- begin
- setup_arguments;
- if (l>=0) and (l<Fargc) then
- paramstr:=strpas(Fargv[l])
- else
- paramstr:='';
- end;
- procedure randomize;
- begin
- randseed:=GetTickCount;
- end;
- {*****************************************************************************
- System Dependent Exit code
- *****************************************************************************}
- procedure PascalMain;external name 'PASCALMAIN';
- procedure ExitThread(Exitcode : longint); cdecl; external 'coredll';
- Procedure system_exit;
- begin
- if IsLibrary then
- exit;
- if not IsConsole then
- begin
- Close(stderr);
- Close(stdout);
- Close(erroutput);
- Close(Input);
- Close(Output);
- end;
- ExitThread(exitcode);
- end;
- {$ifdef cpu386}
- var
- { value of the stack segment
- to check if the call stack can be written on exceptions }
- _SS : Cardinal;
- {$endif cpu386}
- function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
- begin
- IsLibrary:=true;
- Dll_entry:=false;
- case DLLreason of
- DLL_PROCESS_ATTACH :
- begin
- PASCALMAIN;
- Dll_entry:=true;
- end;
- DLL_THREAD_ATTACH :
- begin
- { Allocate Threadvars ?!}
- if assigned(Dll_Thread_Attach_Hook) then
- Dll_Thread_Attach_Hook(DllParam);
- end;
- DLL_THREAD_DETACH :
- begin
- if assigned(Dll_Thread_Detach_Hook) then
- Dll_Thread_Detach_Hook(DllParam);
- { Release Threadvars ?!}
- end;
- DLL_PROCESS_DETACH :
- begin
- Lib_Exit;
- if assigned(Dll_Process_Detach_Hook) then
- Dll_Process_Detach_Hook(DllParam);
- end;
- end;
- end;
- {$ifdef WINCE_EXCEPTION_HANDLING}
- //
- // Hardware exception handling
- //
- {
- Error code definitions for the WinCE API functions
- Values are 32 bit values layed out as follows:
- 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
- 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
- +---+-+-+-----------------------+-------------------------------+
- |Sev|C|R| Facility | Code |
- +---+-+-+-----------------------+-------------------------------+
- where
- Sev - is the severity code
- 00 - Success
- 01 - Informational
- 10 - Warning
- 11 - Error
- C - is the Customer code flag
- R - is a reserved bit
- Facility - is the facility code
- Code - is the facility's status code
- }
- const
- SEVERITY_SUCCESS = $00000000;
- SEVERITY_INFORMATIONAL = $40000000;
- SEVERITY_WARNING = $80000000;
- SEVERITY_ERROR = $C0000000;
- const
- STATUS_SEGMENT_NOTIFICATION = $40000005;
- DBG_TERMINATE_THREAD = $40010003;
- DBG_TERMINATE_PROCESS = $40010004;
- DBG_CONTROL_C = $40010005;
- DBG_CONTROL_BREAK = $40010008;
- STATUS_GUARD_PAGE_VIOLATION = $80000001;
- STATUS_DATATYPE_MISALIGNMENT = $80000002;
- STATUS_BREAKPOINT = $80000003;
- STATUS_SINGLE_STEP = $80000004;
- DBG_EXCEPTION_NOT_HANDLED = $80010001;
- STATUS_ACCESS_VIOLATION = $C0000005;
- STATUS_IN_PAGE_ERROR = $C0000006;
- STATUS_INVALID_HANDLE = $C0000008;
- STATUS_NO_MEMORY = $C0000017;
- STATUS_ILLEGAL_INSTRUCTION = $C000001D;
- STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
- STATUS_INVALID_DISPOSITION = $C0000026;
- STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
- STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
- STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
- STATUS_FLOAT_INEXACT_RESULT = $C000008F;
- STATUS_FLOAT_INVALID_OPERATION = $C0000090;
- STATUS_FLOAT_OVERFLOW = $C0000091;
- STATUS_FLOAT_STACK_CHECK = $C0000092;
- STATUS_FLOAT_UNDERFLOW = $C0000093;
- STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
- STATUS_INTEGER_OVERFLOW = $C0000095;
- STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
- STATUS_STACK_OVERFLOW = $C00000FD;
- STATUS_CONTROL_C_EXIT = $C000013A;
- STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
- STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
- STATUS_REG_NAT_CONSUMPTION = $C00002C9;
- const
- ExceptionContinueExecution = 0;
- ExceptionContinueSearch = 1;
- ExceptionNestedException = 2;
- ExceptionCollidedUnwind = 3;
- ExceptionExecuteHandler = 4;
- MaxExceptionLevel = 16;
- exceptLevel : Byte = 0;
- {$ifdef CPUARM}
- const
- CONTEXT_ARM = $0000040;
- CONTEXT_CONTROL = CONTEXT_ARM or $00000001;
- CONTEXT_INTEGER = CONTEXT_ARM or $00000002;
- CONTEXT_SEGMENTS = CONTEXT_ARM or $00000004;
- CONTEXT_FLOATING_POINT = CONTEXT_ARM or $00000008;
- CONTEXT_DEBUG_REGISTERS = CONTEXT_ARM or $00000010;
- CONTEXT_EXTENDED_REGISTERS = CONTEXT_ARM or $00000020;
- CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
- NUM_VFP_REGS = 32;
- NUM_EXTRA_CONTROL_REGS = 8;
- type
- PContext = ^TContext;
- TContext = record
- ContextFlags : LongWord;
- // This section is specified/returned if the ContextFlags word contains
- // the flag CONTEXT_INTEGER.
- R0 : LongWord;
- R1 : LongWord;
- R2 : LongWord;
- R3 : LongWord;
- R4 : LongWord;
- R5 : LongWord;
- R6 : LongWord;
- R7 : LongWord;
- R8 : LongWord;
- R9 : LongWord;
- R10 : LongWord;
- R11 : LongWord;
- R12 : LongWord;
- // This section is specified/returned if the ContextFlags word contains
- // the flag CONTEXT_CONTROL.
- Sp : LongWord;
- Lr : LongWord;
- Pc : LongWord;
- Psr : LongWord;
- Fpscr : LongWord;
- FpExc : LongWord;
- // Floating point registers
- S : array[0..(NUM_VFP_REGS + 1)-1] of LongWord;
- FpExtra : array[0..(NUM_EXTRA_CONTROL_REGS)-1] of LongWord;
- end;
- {$endif CPUARM}
- {$ifdef CPUI386}
- const
- CONTEXT_X86 = $00010000;
- CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
- CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
- CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
- CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
- CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
- CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
- MAXIMUM_SUPPORTED_EXTENSION = 512;
- type
- PFloatingSaveArea = ^TFloatingSaveArea;
- TFloatingSaveArea = packed record
- ControlWord : Cardinal;
- StatusWord : Cardinal;
- TagWord : Cardinal;
- ErrorOffset : Cardinal;
- ErrorSelector : Cardinal;
- DataOffset : Cardinal;
- DataSelector : Cardinal;
- RegisterArea : array[0..79] of Byte;
- Cr0NpxState : Cardinal;
- end;
- PContext = ^TContext;
- TContext = packed record
- //
- // The flags values within this flag control the contents of
- // a CONTEXT record.
- //
- ContextFlags : Cardinal;
- //
- // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
- // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
- // included in CONTEXT_FULL.
- //
- Dr0, Dr1, Dr2,
- Dr3, Dr6, Dr7 : Cardinal;
- //
- // This section is specified/returned if the
- // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
- //
- FloatSave : TFloatingSaveArea;
- //
- // This section is specified/returned if the
- // ContextFlags word contains the flag CONTEXT_SEGMENTS.
- //
- SegGs, SegFs,
- SegEs, SegDs : Cardinal;
- //
- // This section is specified/returned if the
- // ContextFlags word contains the flag CONTEXT_INTEGER.
- //
- Edi, Esi, Ebx,
- Edx, Ecx, Eax : Cardinal;
- //
- // This section is specified/returned if the
- // ContextFlags word contains the flag CONTEXT_CONTROL.
- //
- Ebp : Cardinal;
- Eip : Cardinal;
- SegCs : Cardinal;
- EFlags, Esp, SegSs : Cardinal;
- //
- // This section is specified/returned if the ContextFlags word
- // contains the flag CONTEXT_EXTENDED_REGISTERS.
- // The format and contexts are processor specific
- //
- ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
- end;
- {$endif CPUI386}
- type
- PExceptionPointers = ^TExceptionPointers;
- TExceptionPointers = packed record
- ExceptionRecord : PExceptionRecord;
- ContextRecord : PContext;
- end;
- {$ifdef CPUI386}
- {**************************** i386 Exception handling *****************************************}
- function GetCurrentProcess:DWORD;
- begin
- GetCurrentProcess := SH_CURPROC+SYS_HANDLE_BASE;
- end;
- function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
- cdecl; external 'coredll' name 'ReadProcessMemory';
- function is_prefetch(p : pointer) : boolean;
- var
- a : array[0..15] of byte;
- doagain : boolean;
- instrlo,instrhi,opcode : byte;
- i : longint;
- begin
- result:=false;
- { read memory savely without causing another exeception }
- if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
- exit;
- i:=0;
- doagain:=true;
- while doagain and (i<15) do
- begin
- opcode:=a[i];
- instrlo:=opcode and $f;
- instrhi:=opcode and $f0;
- case instrhi of
- { prefix? }
- $20,$30:
- doagain:=(instrlo and 7)=6;
- $60:
- doagain:=(instrlo and $c)=4;
- $f0:
- doagain:=instrlo in [0,2,3];
- $0:
- begin
- result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
- exit;
- end;
- else
- doagain:=false;
- end;
- inc(i);
- end;
- end;
- var
- exceptEip : array[0..MaxExceptionLevel-1] of Longint;
- exceptError : array[0..MaxExceptionLevel-1] of Byte;
- resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
- {$ifdef SYSTEMEXCEPTIONDEBUG}
- procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
- begin
- if IsConsole then
- begin
- write(stderr,'HandleErrorAddrFrame(error=',error);
- write(stderr,',addr=',hexstr(addr,8));
- writeln(stderr,',frame=',hexstr(frame,8),')');
- end;
- HandleErrorAddrFrame(error,addr,frame);
- end;
- {$endif SYSTEMEXCEPTIONDEBUG}
- procedure JumpToHandleErrorFrame;
- var
- eip, ebp, error : Longint;
- begin
- // save ebp
- asm
- movl (%ebp),%eax
- movl %eax,ebp
- end;
- if (exceptLevel > 0) then
- dec(exceptLevel);
- eip:=exceptEip[exceptLevel];
- error:=exceptError[exceptLevel];
- {$ifdef SYSTEMEXCEPTIONDEBUG}
- if IsConsole then
- writeln(stderr,'In JumpToHandleErrorFrame error=',error);
- {$endif SYSTEMEXCEPTIONDEBUG}
- if resetFPU[exceptLevel] then
- SysResetFPU;
- { build a fake stack }
- asm
- {$ifdef REGCALL}
- movl ebp,%ecx
- movl eip,%edx
- movl error,%eax
- pushl eip
- movl ebp,%ebp // Change frame pointer
- {$else}
- movl ebp,%eax
- pushl %eax
- movl eip,%eax
- pushl %eax
- movl error,%eax
- pushl %eax
- movl eip,%eax
- pushl %eax
- movl ebp,%ebp // Change frame pointer
- {$endif}
- {$ifdef SYSTEMEXCEPTIONDEBUG}
- jmpl DebugHandleErrorAddrFrame
- {$else not SYSTEMEXCEPTIONDEBUG}
- jmpl HandleErrorAddrFrame
- {$endif SYSTEMEXCEPTIONDEBUG}
- end;
- end;
- function i386_exception_handler(ExceptionRecord: PExceptionRecord;
- EstablisherFrame: pointer; ContextRecord: PContext;
- DispatcherContext: pointer): longint; cdecl;
- var
- res: longint;
- must_reset_fpu: boolean;
- begin
- res := ExceptionContinueSearch;
- if ContextRecord^.SegSs=_SS then begin
- must_reset_fpu := true;
- {$ifdef SYSTEMEXCEPTIONDEBUG}
- if IsConsole then Writeln(stderr,'Exception ',
- hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
- {$endif SYSTEMEXCEPTIONDEBUG}
- case cardinal(ExceptionRecord^.ExceptionCode) of
- STATUS_INTEGER_DIVIDE_BY_ZERO,
- STATUS_FLOAT_DIVIDE_BY_ZERO :
- res := 200;
- STATUS_ARRAY_BOUNDS_EXCEEDED :
- begin
- res := 201;
- must_reset_fpu := false;
- end;
- STATUS_STACK_OVERFLOW :
- begin
- res := 202;
- must_reset_fpu := false;
- end;
- STATUS_FLOAT_OVERFLOW :
- res := 205;
- STATUS_FLOAT_DENORMAL_OPERAND,
- STATUS_FLOAT_UNDERFLOW :
- res := 206;
- {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
- STATUS_FLOAT_INEXACT_RESULT,
- STATUS_FLOAT_INVALID_OPERATION,
- STATUS_FLOAT_STACK_CHECK :
- res := 207;
- STATUS_INTEGER_OVERFLOW :
- begin
- res := 215;
- must_reset_fpu := false;
- end;
- STATUS_ILLEGAL_INSTRUCTION:
- res := 216;
- STATUS_ACCESS_VIOLATION:
- { Athlon prefetch bug? }
- if is_prefetch(pointer(ContextRecord^.Eip)) then
- begin
- { if yes, then retry }
- ExceptionRecord^.ExceptionCode := 0;
- res:=ExceptionContinueExecution;
- end
- else
- res := 216;
- STATUS_CONTROL_C_EXIT:
- res := 217;
- STATUS_PRIVILEGED_INSTRUCTION:
- begin
- res := 218;
- must_reset_fpu := false;
- end;
- else
- begin
- if ((ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
- res := 217
- else
- res := 255;
- end;
- end;
- if (res >= 200) and (exceptLevel < MaxExceptionLevel) then begin
- exceptEip[exceptLevel] := ContextRecord^.Eip;
- exceptError[exceptLevel] := res;
- resetFPU[exceptLevel] := must_reset_fpu;
- inc(exceptLevel);
- ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
- ExceptionRecord^.ExceptionCode := 0;
- res := ExceptionContinueExecution;
- {$ifdef SYSTEMEXCEPTIONDEBUG}
- if IsConsole then begin
- writeln(stderr,'Exception Continue Exception set at ',
- hexstr(exceptEip[exceptLevel],8));
- writeln(stderr,'Eip changed to ',
- hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
- end;
- {$endif SYSTEMEXCEPTIONDEBUG}
- end;
- end;
- i386_exception_handler := res;
- end;
- {$endif CPUI386}
- {$ifdef CPUARM}
- {**************************** ARM Exception handling *****************************************}
- var
- exceptPC : array[0..MaxExceptionLevel-1] of Longint;
- exceptError : array[0..MaxExceptionLevel-1] of Byte;
- procedure JumpToHandleErrorFrame;
- var
- _pc, _fp, _error : Longint;
- begin
- // get original fp
- asm
- ldr r0,[r11,#-12]
- str r0,_fp
- end;
- if (exceptLevel > 0) then
- dec(exceptLevel);
- _pc:=exceptPC[exceptLevel];
- _error:=exceptError[exceptLevel];
- asm
- ldr r0,_error
- ldr r1,_pc
- ldr r2,_fp
- mov r11,r2 // Change frame pointer
- b HandleErrorAddrFrame
- end;
- end;
- function ARM_ExceptionHandler(ExceptionRecord: PExceptionRecord;
- EstablisherFrame: pointer; ContextRecord: PContext;
- DispatcherContext: pointer): longint; [public, alias : '_ARM_ExceptionHandler'];
- var
- res: longint;
- begin
- res := ExceptionContinueSearch;
- case cardinal(ExceptionRecord^.ExceptionCode) of
- STATUS_INTEGER_DIVIDE_BY_ZERO,
- STATUS_FLOAT_DIVIDE_BY_ZERO :
- res := 200;
- STATUS_ARRAY_BOUNDS_EXCEEDED :
- res := 201;
- STATUS_STACK_OVERFLOW :
- res := 202;
- STATUS_FLOAT_OVERFLOW :
- res := 205;
- STATUS_FLOAT_DENORMAL_OPERAND,
- STATUS_FLOAT_UNDERFLOW :
- res := 206;
- STATUS_FLOAT_INEXACT_RESULT,
- STATUS_FLOAT_INVALID_OPERATION,
- STATUS_FLOAT_STACK_CHECK :
- res := 207;
- STATUS_INTEGER_OVERFLOW :
- res := 215;
- STATUS_ILLEGAL_INSTRUCTION:
- res := 216;
- STATUS_ACCESS_VIOLATION:
- res := 216;
- STATUS_DATATYPE_MISALIGNMENT:
- res := 214;
- STATUS_CONTROL_C_EXIT:
- res := 217;
- STATUS_PRIVILEGED_INSTRUCTION:
- res := 218;
- else
- begin
- if ((cardinal(ExceptionRecord^.ExceptionCode) and SEVERITY_ERROR) = SEVERITY_ERROR) then
- res := 217
- else
- res := 255;
- end;
- end;
- if (res <> ExceptionContinueSearch) and (exceptLevel < MaxExceptionLevel) then begin
- exceptPC[exceptLevel] := ContextRecord^.PC;
- exceptError[exceptLevel] := res;
- inc(exceptLevel);
- ContextRecord^.PC := Longint(@JumpToHandleErrorFrame);
- ExceptionRecord^.ExceptionCode := 0;
- res := ExceptionContinueExecution;
- {$ifdef SYSTEMEXCEPTIONDEBUG}
- if IsConsole then begin
- writeln(stderr,'Exception Continue Exception set at ',
- hexstr(exceptEip[exceptLevel],8));
- writeln(stderr,'Eip changed to ',
- hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
- end;
- {$endif SYSTEMEXCEPTIONDEBUG}
- end;
- ARM_ExceptionHandler := res;
- end;
- {$endif CPUARM}
- {$endif WINCE_EXCEPTION_HANDLING}
- procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
- begin
- IsLibrary:=false;
- {$ifdef CPUARM}
- asm
- mov fp,#0
- bl PASCALMAIN;
- end;
- {$endif CPUARM}
- {$ifdef CPUI386}
- asm
- {$ifdef WINCE_EXCEPTION_HANDLING}
- pushl i386_exception_handler
- pushl %fs:(0)
- mov %esp,%fs:(0)
- {$endif WINCE_EXCEPTION_HANDLING}
- pushl %ebp
- xorl %eax,%eax
- movw %ss,%ax
- movl %eax,_SS
- xorl %ebp,%ebp
- call PASCALMAIN
- popl %ebp
- {$ifdef WINCE_EXCEPTION_HANDLING}
- popl %fs:(0)
- addl $4, %esp
- {$endif WINCE_EXCEPTION_HANDLING}
- end;
- {$endif CPUI386}
- end;
- procedure _FPC_mainCRTStartup;public name '_mainCRTStartup';
- begin
- IsConsole:=True;
- Exe_entry;
- end;
- procedure _FPC_WinMainCRTStartup;public name '_WinMainCRTStartup';
- begin
- IsConsole:=False;
- Exe_entry;
- end;
- procedure _FPC_DLLMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLMainCRTStartup';
- begin
- IsConsole:=true;
- sysinstance:=_hinstance;
- dllreason:=_dllreason;
- dllparam:=_dllparam;
- DLL_Entry;
- end;
- procedure _FPC_DLLWinMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLWinMainCRTStartup';
- begin
- IsConsole:=false;
- sysinstance:=_hinstance;
- dllreason:=_dllreason;
- dllparam:=_dllparam;
- DLL_Entry;
- end;
- {****************************************************************************
- OS dependend widestrings
- ****************************************************************************}
- function CharUpperBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharUpperBuffW';
- function CharLowerBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharLowerBuffW';
- procedure WinCEWide2AnsiMove(source:pwidechar;var dest:RawByteString;cp:TSystemCodePage;len:SizeInt);
- var
- destlen: SizeInt;
- begin
- // retrieve length including trailing #0
- // not anymore, because this must also be usable for single characters
- destlen:=WideCharToMultiByte(cp, 0, source, len, nil, 0, nil, nil);
- // this will null-terminate
- setlength(dest, destlen);
- if destlen>0 then
- begin
- WideCharToMultiByte(cp, 0, source, len, @dest[1], destlen, nil, nil);
- PAnsiRec(pointer(dest)-AnsiFirstOff)^.CodePage:=cp;
- end;
- end;
- procedure WinCEAnsi2WideMove(source:pchar;cp:TSystemCodePage;var dest:widestring;len:SizeInt);
- var
- destlen: SizeInt;
- dwFlags: DWORD;
- begin
- if cp=CP_UTF8 then
- dwFlags:=0
- else
- dwFlags:=MB_PRECOMPOSED;
- destlen:=MultiByteToWideChar(cp, dwFlags, source, len, nil, 0);
- // this will null-terminate
- setlength(dest, destlen);
- if destlen>0 then
- MultiByteToWideChar(cp, dwFlags, source, len, @dest[1], destlen);
- end;
- function WinCEWideUpper(const s : WideString) : WideString;
- begin
- result:=s;
- UniqueString(result);
- if length(result)>0 then
- CharUpperBuff(LPWSTR(result),length(result));
- end;
- function WinCEWideLower(const s : WideString) : WideString;
- begin
- result:=s;
- UniqueString(result);
- if length(result)>0 then
- CharLowerBuff(LPWSTR(result),length(result));
- end;
- procedure WinCEUnicode2AnsiMove(source:punicodechar;var dest:RawByteString;cp:TSystemCodePage;len:SizeInt);
- var
- destlen: SizeInt;
- begin
- // retrieve length including trailing #0
- // not anymore, because this must also be usable for single characters
- destlen:=WideCharToMultiByte(cp, 0, source, len, nil, 0, nil, nil);
- // this will null-terminate
- setlength(dest, destlen);
- if destlen>0 then
- begin
- WideCharToMultiByte(cp, 0, source, len, @dest[1], destlen, nil, nil);
- PAnsiRec(pointer(dest)-AnsiFirstOff)^.CodePage:=cp;
- end;
- end;
- procedure WinCEAnsi2UnicodeMove(source:pchar;cp : TSystemCodePage;var dest:UnicodeString;len:SizeInt);
- var
- destlen: SizeInt;
- dwflags: DWORD;
- begin
- if cp=CP_UTF8 then
- dwFlags:=0
- else
- dwFlags:=MB_PRECOMPOSED;
- destlen:=MultiByteToWideChar(cp, dwFlags, source, len, nil, 0);
- // this will null-terminate
- setlength(dest, destlen);
- if destlen>0 then
- begin
- MultiByteToWideChar(cp, dwFlags, source, len, @dest[1], destlen);
- PUnicodeRec(pointer(dest)-UnicodeFirstOff)^.CodePage:=CP_UTF16;
- end;
- end;
- function WinCEUnicodeUpper(const s : UnicodeString) : UnicodeString;
- begin
- Result:=WinCEWideUpper(s);
- end;
- function WinCEUnicodeLower(const s : UnicodeString) : UnicodeString;
- begin
- Result:=WinCEWideLower(s);
- end;
- function WinCEGetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
- begin
- case stdcp of
- scpAnsi: Result := GetACP;
- scpConsoleInput: Result := GetACP;
- scpConsoleOutput: Result := GetACP;
- { all of WinCE's file APIs are based on UTF8 -> prevent data loss when using
- single byte strings }
- scpFileSystemSingleByte: Result := CP_UTF8;
- end;
- end;
- { there is a similiar procedure in sysutils which inits the fields which
- are only relevant for the sysutils units }
- procedure InitWinCEWidestrings;
- begin
- widestringmanager.Wide2AnsiMoveProc:=@WinCEWide2AnsiMove;
- widestringmanager.Ansi2WideMoveProc:=@WinCEAnsi2WideMove;
- widestringmanager.UpperWideStringProc:=@WinCEWideUpper;
- widestringmanager.LowerWideStringProc:=@WinCEWideLower;
- { Unicode }
- widestringmanager.Unicode2AnsiMoveProc:=@WinCEUnicode2AnsiMove;
- widestringmanager.Ansi2UnicodeMoveProc:=@WinCEAnsi2UnicodeMove;
- widestringmanager.UpperUnicodeStringProc:=@WinCEUnicodeUpper;
- widestringmanager.LowerUnicodeStringProc:=@WinCEUnicodeLower;
- { Codepage }
- widestringmanager.GetStandardCodePageProc:=@WinCEGetStandardCodePage;
- DefaultSystemCodePage:=GetACP;
- DefaultFileSystemCodePage:=WinCEGetStandardCodePage(scpFileSystemSingleByte);
- DefaultRTLFileSystemCodePage:=DefaultFileSystemCodePage;
- DefaultUnicodeCodePage:=CP_UTF16;
- end;
- {$IFDEF HAS_MEMORYMANAGER}
- {****************************************************************************
- Memory manager
- ****************************************************************************}
- function malloc(Size : ptruint) : Pointer; cdecl; external 'coredll';
- procedure free(P : pointer); cdecl; external 'coredll';
- function realloc(P : Pointer; Size : ptruint) : pointer; cdecl; external 'coredll';
- function _msize(P : pointer): ptruint; cdecl; external 'coredll';
- function SysGetMem (Size : ptruint) : Pointer;
- begin
- Result:=malloc(Size);
- end;
- Function SysFreeMem (P : pointer) : ptruint;
- begin
- free(P);
- Result:=0;
- end;
- Function SysFreeMemSize(p:pointer;Size:ptruint):ptruint;
- begin
- Result:=0;
- if (size > 0) and (p <> nil) then
- Result:=SysFreeMem(P);
- end;
- Function SysAllocMem(Size : ptruint) : Pointer;
- begin
- Result:=SysGetMem(Size);
- if Result <> nil then
- FillChar(Result^, Size, 0);
- end;
- Function SysReAllocMem (var p:pointer;Size:ptruint):Pointer;
- begin
- Result:=realloc(p, Size);
- p:=Result;
- end;
- function SysTryResizeMem(var p:pointer;size : ptruint):boolean;
- var
- res: pointer;
- begin
- res:=realloc(p, Size);
- Result:=(res <> nil) or (Size = 0);
- if Result then
- p:=res;
- end;
- function SysMemSize(P : pointer): ptruint;
- begin
- Result:=_msize(P);
- end;
- function SysGetHeapStatus:THeapStatus;
- begin
- fillchar(Result,sizeof(Result),0);
- end;
- function SysGetFPCHeapStatus:TFPCHeapStatus;
- begin
- fillchar(Result,sizeof(Result),0);
- end;
- {$ENDIF HAS_MEMORYMANAGER}
- {****************************************************************************
- Error Message writing using messageboxes
- ****************************************************************************}
- const
- ErrorBufferLength = 1024;
- var
- ErrorBuf : array[0..ErrorBufferLength] of char;
- ErrorBufW : array[0..ErrorBufferLength] of widechar;
- ErrorLen : longint;
- procedure ErrorWrite(Var F: TextRec);
- {
- An error message should always end with #13#10#13#10
- }
- var
- i : longint;
- Begin
- while F.BufPos>0 do
- begin
- begin
- if F.BufPos+ErrorLen>ErrorBufferLength then
- i:=ErrorBufferLength-ErrorLen
- else
- i:=F.BufPos;
- Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
- inc(ErrorLen,i);
- ErrorBuf[ErrorLen]:=#0;
- end;
- if ErrorLen=ErrorBufferLength then
- begin
- AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
- MessageBox(0,@ErrorBufW,'Error',$10010); { MB_SETFOREGROUND or ICON_ERROR }
- ErrorLen:=0;
- end;
- Dec(F.BufPos,i);
- end;
- End;
- procedure ErrorClose(Var F: TextRec);
- begin
- if ErrorLen>0 then
- begin
- AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
- MessageBox(0,@ErrorBufW,'Error',$10010); { MB_SETFOREGROUND or ICON_ERROR }
- ErrorLen:=0;
- end;
- ErrorLen:=0;
- end;
- procedure ErrorOpen(Var F: TextRec);
- Begin
- TextRec(F).InOutFunc:=@ErrorWrite;
- TextRec(F).FlushFunc:=@ErrorWrite;
- TextRec(F).CloseFunc:=@ErrorClose;
- ErrorLen:=0;
- End;
- procedure AssignError(Var T: Text);
- begin
- Assign(T,'');
- TextRec(T).OpenFunc:=@ErrorOpen;
- Rewrite(T);
- end;
- function _getstdfilex(fd: integer): pointer; cdecl; external 'coredll';
- function _fileno(fd: pointer): THandle; cdecl; external 'coredll';
- procedure SysInitStdIO;
- begin
- { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
- displayed in and messagebox }
- if not IsConsole then
- begin
- AssignError(stderr);
- AssignError(stdout);
- Assign(Output,'');
- Assign(Input,'');
- Assign(ErrOutput,'');
- end
- else
- begin
- StdInputHandle:=_fileno(_getstdfilex(0));
- StdOutputHandle:=_fileno(_getstdfilex(1));
- StdErrorHandle:=_fileno(_getstdfilex(2));
- OpenStdIO(Input,fmInput,StdInputHandle);
- OpenStdIO(Output,fmOutput,StdOutputHandle);
- OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
- OpenStdIO(StdOut,fmOutput,StdOutputHandle);
- OpenStdIO(StdErr,fmOutput,StdErrorHandle);
- end;
- end;
- (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
- var
- ProcessID: SizeUInt;
- function GetProcessID: SizeUInt;
- begin
- GetProcessID := ProcessID;
- end;
- function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
- begin
- result := stklen;
- end;
- procedure SysCleanup;
- var
- i: integer;
- begin
- if FCmdLine = nil then
- exit;
- SysFreeMem(FCmdLine);
- for i:=0 to Fargc do
- sysfreemem(Fargv[i]);
- sysfreemem(Fargv);
- end;
- initialization
- SysResetFPU;
- if not(IsLibrary) then
- SysInitFPU;
- StackLength := CheckInitialStkLen(InitialStkLen);
- StackBottom := Sptr - StackLength;
- { some misc stuff }
- hprevinst:=0;
- if not IsLibrary then
- SysInstance:=GetModuleHandle(nil);
- MainInstance:=SysInstance;
- {$IFNDEF HAS_MEMORYMANAGER}
- { Setup Heap }
- InitHeap;
- {$ENDIF HAS_MEMORYMANAGER}
- SysInitExceptions;
- initunicodestringmanager;
- InitWinCEWidestrings;
- if not IsLibrary then
- begin
- SysInitStdIO;
- end;
- { Reset IO Error }
- InOutRes:=0;
- ProcessID := GetCurrentProcessID;
- { threading }
- InitSystemThreads;
- InitSystemDynLibs;
- DispCallByIDProc:=@DoDispCallByIDError;
- finalization
- SysCleanup;
- end.
|