diff options
Diffstat (limited to 'rtl/inc')
-rw-r--r-- | rtl/inc/astrings.inc | 24 | ||||
-rw-r--r-- | rtl/inc/charset.pp | 37 | ||||
-rw-r--r-- | rtl/inc/compproc.inc | 6 | ||||
-rw-r--r-- | rtl/inc/dynarr.inc | 84 | ||||
-rw-r--r-- | rtl/inc/dynarrh.inc | 8 | ||||
-rw-r--r-- | rtl/inc/exeinfo.pp | 2 | ||||
-rw-r--r-- | rtl/inc/fexpand.inc | 9 | ||||
-rw-r--r-- | rtl/inc/file.inc | 8 | ||||
-rw-r--r-- | rtl/inc/generic.inc | 111 | ||||
-rw-r--r-- | rtl/inc/genmath.inc | 321 | ||||
-rw-r--r-- | rtl/inc/innr.inc | 2 | ||||
-rw-r--r-- | rtl/inc/int64.inc | 13 | ||||
-rw-r--r-- | rtl/inc/mathh.inc | 80 | ||||
-rw-r--r-- | rtl/inc/objpash.inc | 20 | ||||
-rw-r--r-- | rtl/inc/rtti.inc | 16 | ||||
-rw-r--r-- | rtl/inc/rttih.inc | 18 | ||||
-rw-r--r-- | rtl/inc/softfpu.pp | 219 | ||||
-rw-r--r-- | rtl/inc/sstrings.inc | 2 | ||||
-rw-r--r-- | rtl/inc/system.fpd | 2 | ||||
-rw-r--r-- | rtl/inc/system.inc | 27 | ||||
-rw-r--r-- | rtl/inc/systemh.inc | 21 | ||||
-rw-r--r-- | rtl/inc/text.inc | 39 | ||||
-rw-r--r-- | rtl/inc/tinyheap.inc | 544 | ||||
-rw-r--r-- | rtl/inc/tnyheaph.inc | 32 | ||||
-rw-r--r-- | rtl/inc/ustringh.inc | 4 | ||||
-rw-r--r-- | rtl/inc/ustrings.inc | 46 | ||||
-rw-r--r-- | rtl/inc/variant.inc | 5 | ||||
-rw-r--r-- | rtl/inc/varianth.inc | 2 | ||||
-rw-r--r-- | rtl/inc/wstringh.inc | 4 | ||||
-rw-r--r-- | rtl/inc/wstrings.inc | 38 |
30 files changed, 1296 insertions, 448 deletions
diff --git a/rtl/inc/astrings.inc b/rtl/inc/astrings.inc index e9fda39988..772d4d7e60 100644 --- a/rtl/inc/astrings.inc +++ b/rtl/inc/astrings.inc @@ -1404,20 +1404,36 @@ end; {$endif FPC_HAS_ANSISTR_OF_CHAR} -Procedure SetString(Out S : AnsiString; Buf : PAnsiChar; Len : SizeInt); inline; +{$ifdef FPC_HAS_CPSTRING} +Procedure fpc_setstring_ansistr_pansichar(out S : RawByteString; Buf : PAnsiChar; Len : SizeInt; cp: TSystemCodePage); rtlproc; compilerproc; +{$else} +Procedure SetString(out S : AnsiString; Buf : PAnsiChar; Len : SizeInt); +{$endif} begin SetLength(S,Len); +{$ifdef FPC_HAS_CPSTRING} + SetCodePage(S,cp,false); +{$endif} If (Buf<>Nil) then fpc_pchar_ansistr_intern_charmove(Buf,0,S,0,Len); end; -Procedure SetString(Out S : AnsiString; Buf : PWideChar; Len : SizeInt); +{$ifdef FPC_HAS_CPSTRING} +Procedure fpc_setstring_ansistr_pwidechar(out S : RawByteString; Buf : PWideChar; Len : SizeInt; cp: TSystemCodePage); rtlproc; compilerproc; +{$else} +Procedure SetString(out S : AnsiString; Buf : PWideChar; Len : SizeInt); +{$endif} begin if (Buf<>nil) and (Len>0) then - widestringmanager.Wide2AnsiMoveProc(Buf,RawByteString(S),DefaultSystemCodePage,Len) + widestringmanager.Wide2AnsiMoveProc(Buf,S,{$ifdef FPC_HAS_CPSTRING}cp{$else}DefaultSystemCodePage{$endif},Len) else - SetLength(S, Len); + begin + SetLength(S, Len); +{$ifdef FPC_HAS_CPSTRING} + SetCodePage(S,cp,false); +{$endif} + end; end; diff --git a/rtl/inc/charset.pp b/rtl/inc/charset.pp index b50b313cfc..b3bc902131 100644 --- a/rtl/inc/charset.pp +++ b/rtl/inc/charset.pp @@ -73,15 +73,15 @@ unit charset; ) : punicodemap;overload; procedure registermapping(p : punicodemap); function registerbinarymapping(const directory,cpname : string):Boolean; - function getmap(const s : string) : punicodemap; - function getmap(cp : word) : punicodemap; + function getmap(const s : string) : punicodemap; + function getmap(cp : word) : punicodemap; function mappingavailable(const s : string) : boolean;inline; function mappingavailable(cp :word) : boolean;inline; function getunicode(c : char;p : punicodemap) : tunicodechar;inline; function getunicode( AAnsiStr : pansichar; AAnsiLen : LongInt; - AMap : punicodemap; + AMap : punicodemap; ADest : tunicodestring ) : LongInt; function getascii(c : tunicodechar;p : punicodemap) : string; @@ -421,10 +421,7 @@ unit charset; Assign(f,filename); Reset(f); if (IOResult<>0) then - begin - Close(f); - exit; - end; + exit; locSize:=FileSize(f); if (locSize<SizeOf(TSerializedMapHeader)) then begin @@ -624,7 +621,7 @@ unit charset; function getunicode( AAnsiStr : pansichar; AAnsiLen : LongInt; - AMap : punicodemap; + AMap : punicodemap; ADest : tunicodestring ) : LongInt; @@ -632,11 +629,11 @@ unit charset; i, c, k, destLen : longint; ps : pansichar; pd : ^tunicodechar; - + begin if (AAnsiStr=nil) or (AAnsiLen<=0) then exit(0); - ps:=AAnsiStr; + ps:=AAnsiStr; if (ADest=nil) then begin c:=AAnsiLen-1; @@ -651,12 +648,12 @@ unit charset; Inc(ps); i:=i+1; end; - end; - i:=i+1; + end; + i:=i+1; Inc(ps); destLen:=destLen+1; - end; - exit(destLen); + end; + exit(destLen); end; pd:=ADest; @@ -668,7 +665,7 @@ unit charset; begin if (AMap^.map[ord(ps^)].flag=umf_leadbyte) then begin - if (i<c) then + if (i<c) then begin k:=(Ord(ps^)*256); Inc(ps); @@ -681,16 +678,16 @@ unit charset; end else pd^:=UNKNOW_CHAR_W; - end - else + end + else pd^:=AMap^.map[ord(ps^)].unicode - end + end else pd^:=UNKNOW_CHAR_W; - i:=i+1; + i:=i+1; Inc(ps); Inc(pd); - end; + end; result:=((PtrUInt(pd)-PtrUInt(ADest)) div SizeOf(tunicodechar)); end; diff --git a/rtl/inc/compproc.inc b/rtl/inc/compproc.inc index a2f8db1aa6..5c37f2079b 100644 --- a/rtl/inc/compproc.inc +++ b/rtl/inc/compproc.inc @@ -507,7 +507,7 @@ function fpc_variant_to_idispatch(const v : variant) : idispatch;compilerproc; function fpc_idispatch_to_variant(const i : idispatch) : variant;compilerproc; procedure fpc_vararray_get(var d : variant;const s : variant;indices : plongint;len : sizeint);compilerproc; procedure fpc_vararray_put(var d : variant;const s : variant;indices : plongint;len : sizeint);compilerproc; -procedure fpc_dispinvoke_variant(dest : pvardata;const source : tvardata; calldesc : pcalldesc;params : pointer);compilerproc; +procedure fpc_dispinvoke_variant(dest : pvardata;var source : tvardata; calldesc : pcalldesc;params : pointer);compilerproc; {$endif FPC_HAS_FEATURE_VARIANTS} {$ifdef FPC_HAS_FEATURE_TEXTIO} @@ -747,7 +747,7 @@ function fpc_longword_to_double(i: longword): double; compilerproc; function fpc_setjmp(var s : jmp_buf) : {$ifdef CPU16}smallint{$else}longint{$endif}; compilerproc; procedure fpc_longjmp(var s : jmp_buf; value : {$ifdef CPU16}smallint{$else}longint{$endif}); compilerproc; -{$ifdef i8086} +{$ifdef cpui8086} { i8086 huge pointer helpers } function fpc_hugeptr_add_longint(p: HugePointer; n: LongInt): HugePointer; compilerproc; function fpc_hugeptr_add_longint_normalized(p: HugePointer; n: LongInt): HugePointer; compilerproc; @@ -765,4 +765,4 @@ function fpc_hugeptr_cmp_normalized_b(p1, p2: HugePointer): Boolean; compilerpro function fpc_hugeptr_cmp_normalized_be(p1, p2: HugePointer): Boolean; compilerproc; function fpc_hugeptr_cmp_normalized_a(p1, p2: HugePointer): Boolean; compilerproc; function fpc_hugeptr_cmp_normalized_ae(p1, p2: HugePointer): Boolean; compilerproc; -{$endif i8086} +{$endif cpui8086} diff --git a/rtl/inc/dynarr.inc b/rtl/inc/dynarr.inc index 76771c15d1..214fd3b5b8 100644 --- a/rtl/inc/dynarr.inc +++ b/rtl/inc/dynarr.inc @@ -30,7 +30,7 @@ type packed {$endif FPC_REQUIRES_PROPER_ALIGNMENT} record - elSize : PtrUInt; + elSize : SizeUInt; elType2 : Pointer; varType : Longint; end; @@ -303,6 +303,88 @@ function fpc_dynarray_copy(psrc : pointer;ti : pointer; procedure DynArraySetLength(var a: Pointer; typeInfo: Pointer; dimCnt: SizeInt; lengthVec: PSizeInt); external name 'FPC_DYNARR_SETLENGTH'; +function DynArraySize(a : pointer): tdynarrayindex; + external name 'FPC_DYNARRAY_LENGTH'; + +procedure DynArrayClear(var a: Pointer; typeInfo: Pointer); + external name 'FPC_DYNARRAY_CLEAR'; + +function DynArrayDim(typeInfo: Pointer): Integer; + begin + result:=0; + while (typeInfo <> nil) and (pdynarraytypeinfo(typeInfo)^.kind = tkDynArray) do + begin + { skip kind and name } + typeInfo:=aligntoptr(typeInfo+2+PByte(typeInfo)[1]); + + { element type info} + typeInfo:=pdynarraytypedata(typeInfo)^.elType2; + + Inc(result); + end; + end; + +function DynArrayBounds(a: Pointer; typeInfo: Pointer): TBoundArray; + var + i,dim: sizeint; + begin + dim:=DynArrayDim(typeInfo); + SetLength(result, dim); + + for i:=0 to pred(dim) do + if a = nil then + exit + else + begin + result[i]:=DynArraySize(a)-1; + a:=PPointerArray(a)^[0]; + end; + end; + +function IsDynArrayRectangular(a: Pointer; typeInfo: Pointer): Boolean; + var + i,j: sizeint; + dim,count: sizeint; + begin + dim:=DynArrayDim(typeInfo); + for i:=1 to pred(dim) do + begin + count:=DynArraySize(PPointerArray(a)^[0]); + + for j:=1 to Pred(DynArraySize(a)) do + if count<>DynArraySize(PPointerArray(a)^[j]) then + exit(false); + + a:=PPointerArray(a)^[0]; + end; + result:=true; + end; + +function DynArrayIndex(a: Pointer; const indices: array of SizeInt; typeInfo: Pointer): Pointer; + var + i,h: sizeint; + begin + h:=High(indices); + for i:=0 to h do + begin + if i<h then + a := PPointerArray(a)^[indices[i]]; + + { skip kind and name } + typeInfo:=(typeInfo+2+PByte(typeInfo)[1]); + { element type info} + typeInfo:=pdynarraytypedata(typeInfo)^.elType2; + + if typeInfo=nil then + exit(nil); + end; + + { skip kind and name } + typeInfo:=(typeInfo+2+PByte(typeInfo)[1]); + + result:=@(PByte(a)[indices[h]*pdynarraytypedata(typeInfo)^.elSize]); + end; + { obsolete but needed for bootstrapping } procedure fpc_dynarray_decr_ref(var p : pointer;ti : pointer); [Public,Alias:'FPC_DYNARRAY_DECR_REF']; compilerproc; begin diff --git a/rtl/inc/dynarrh.inc b/rtl/inc/dynarrh.inc index c355227d4c..515dd3c3fd 100644 --- a/rtl/inc/dynarrh.inc +++ b/rtl/inc/dynarrh.inc @@ -30,4 +30,12 @@ type end; procedure DynArraySetLength(var a: Pointer; typeInfo: Pointer; dimCnt: SizeInt; lengthVec: PSizeInt); +function DynArraySize(a : pointer): tdynarrayindex; +procedure DynArrayClear(var a: Pointer; typeInfo: Pointer); +function DynArrayDim(typeInfo: Pointer): Integer; +function DynArrayBounds(a: Pointer; typeInfo: Pointer): TBoundArray; + +function IsDynArrayRectangular(a: Pointer; typeInfo: Pointer): Boolean; +function DynArrayIndex(a: Pointer; const indices: array of SizeInt; typeInfo: Pointer): Pointer; + procedure fpc_dynarray_rangecheck(p : pointer;i : tdynarrayindex); compilerproc; diff --git a/rtl/inc/exeinfo.pp b/rtl/inc/exeinfo.pp index 198f3265bf..1dc9b70108 100644 --- a/rtl/inc/exeinfo.pp +++ b/rtl/inc/exeinfo.pp @@ -109,7 +109,7 @@ uses Executable Loaders ****************************************************************************} -{$if defined(freebsd) or defined(netbsd) or defined (openbsd) or defined(linux) or defined(sunos) or defined(android)} +{$if defined(freebsd) or defined(netbsd) or defined (openbsd) or defined(linux) or defined(sunos) or defined(android) or defined(dragonfly)} {$ifdef cpu64} {$define ELF64} {$else} diff --git a/rtl/inc/fexpand.inc b/rtl/inc/fexpand.inc index 599e47536a..411283d160 100644 --- a/rtl/inc/fexpand.inc +++ b/rtl/inc/fexpand.inc @@ -79,6 +79,10 @@ begin OldInOutRes := InOutRes; InOutRes := 0; GetDir (DriveNr, Dir); +{$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)} + { set the same codepage as used for the strings in fexpand itself } + SetCodePage(Dir,DefaultFileSystemCodePage); +{$ENDIF FPC_FEXPAND_SYSUTILS and not SYSUTILSUNICODE} InOutRes := OldInOutRes; end; @@ -599,7 +603,10 @@ begin then Delete (PA,length(PA),1); {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR} - +{$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)} + { return result in expected code page } + SetCodePage(Pa,DefaultRTLFileSystemCodePage); +{$ENDIF FPC_FEXPAND_SYSUTILS and not SYSUTILSUNICODE} FExpand := Pa; end; diff --git a/rtl/inc/file.inc b/rtl/inc/file.inc index 8b986df03f..464fcd7f36 100644 --- a/rtl/inc/file.inc +++ b/rtl/inc/file.inc @@ -441,6 +441,7 @@ Begin End; +{$ifdef FPC_HAS_FEATURE_WIDESTRINGS} Procedure Rename(var f : File; const S : UnicodeString);[IOCheck]; {$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API} var @@ -471,8 +472,10 @@ Begin {$endif FPC_ANSI_TEXTFILEREC} {$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API} End; +{$endif FPC_HAS_FEATURE_WIDESTRINGS} +{$ifdef FPC_HAS_FEATURE_ANSISTRINGS} Procedure Rename(var f : File;const s : RawByteString);[IOCheck]; var {$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API} @@ -517,6 +520,7 @@ Begin FileRec(f).Name:=fs {$endif FPC_ANSI_TEXTFILEREC and not FPCRTL_FILESYSTEM_SINGLE_BYTE_API} End; +{$endif FPC_HAS_FEATURE_ANSISTRINGS} Procedure Rename(var f : File;const s : ShortString);[IOCheck]; @@ -542,7 +546,7 @@ Begin End; {$else FPC_HAS_FEATURE_ANSISTRINGS} var - len: SizeInt + len: SizeInt; Begin if InOutRes<>0 then exit; @@ -551,7 +555,7 @@ Begin InOutRes:=102; exit; end; - Do_Rename(PFileTextRecChar(@FileRec(f).Name),p,false); + Do_Rename(PFileTextRecChar(@FileRec(f).Name),p,false,false); { check error code of do_rename } if InOutRes=0 then begin diff --git a/rtl/inc/generic.inc b/rtl/inc/generic.inc index b146f57404..4774d639e4 100644 --- a/rtl/inc/generic.inc +++ b/rtl/inc/generic.inc @@ -1854,45 +1854,35 @@ function SwapEndian(const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endi function SwapEndian(const AValue: LongInt): LongInt; begin - Result := (AValue shl 24) - or ((AValue and $0000FF00) shl 8) - or ((AValue and $00FF0000) shr 8) - or (AValue shr 24); + Result := ((AValue shl 8) and $FF00FF00) or ((AValue shr 8) and $00FF00FF); + Result := (Result shl 16) or (Result shr 16); end; {$ifndef cpujvm} function SwapEndian(const AValue: DWord): DWord; begin - Result := (AValue shl 24) - or ((AValue and $0000FF00) shl 8) - or ((AValue and $00FF0000) shr 8) - or (AValue shr 24); + Result := ((AValue shl 8) and $FF00FF00) or ((AValue shr 8) and $00FF00FF); + Result := (Result shl 16) or (Result shr 16); end; {$endif} function SwapEndian(const AValue: Int64): Int64; begin - Result := (AValue shl 56) - or ((AValue and $000000000000FF00) shl 40) - or ((AValue and $0000000000FF0000) shl 24) - or ((AValue and $00000000FF000000) shl 8) - or ((AValue and $000000FF00000000) shr 8) - or ((AValue and $0000FF0000000000) shr 24) - or ((AValue and $00FF000000000000) shr 40) - or (AValue shr 56); + Result := ((AValue shl 8) and $FF00FF00FF00FF00) or + ((AValue shr 8) and $00FF00FF00FF00FF); + Result := ((Result shl 16) and $FFFF0000FFFF0000) or + ((Result shr 16) and $0000FFFF0000FFFF); + Result := (Result shl 32) or ((Result shr 32)); end; {$ifndef cpujvm} function SwapEndian(const AValue: QWord): QWord; begin - Result := (AValue shl 56) - or ((AValue and $000000000000FF00) shl 40) - or ((AValue and $0000000000FF0000) shl 24) - or ((AValue and $00000000FF000000) shl 8) - or ((AValue and $000000FF00000000) shr 8) - or ((AValue and $0000FF0000000000) shr 24) - or ((AValue and $00FF000000000000) shr 40) - or (AValue shr 56); + Result := ((AValue shl 8) and $FF00FF00FF00FF00) or + ((AValue shr 8) and $00FF00FF00FF00FF); + Result := ((Result shl 16) and $FFFF0000FFFF0000) or + ((Result shr 16) and $0000FFFF0000FFFF); + Result := (Result shl 32) or ((Result shr 32)); end; {$endif} {$endif FPC_SYSTEM_HAS_SWAPENDIAN} @@ -2376,11 +2366,8 @@ function BsrByte(Const AValue: Byte): Byte; {$ifndef FPC_HAS_INTERNAL_BSF_WORD} function BsfWord(Const AValue: Word): {$ifdef CPU16}byte{$else}cardinal{$endif}; begin - result:=$ff; - if lo(AValue)<>0 then - result:=BsfByte(lo(AValue)) - else if hi(AValue) <> 0 then - result:=BsfByte(hi(AValue))+8 + result:=ord(lo(AValue)=0)*8; + result:=result or BsfByte(byte(AValue shr result)); end; {$endif} {$endif} @@ -2389,10 +2376,8 @@ function BsfWord(Const AValue: Word): {$ifdef CPU16}byte{$else}cardinal{$endif}; {$ifndef FPC_HAS_INTERNAL_BSR_WORD} function BsrWord(Const AValue: Word): {$ifdef CPU16}byte{$else}cardinal{$endif}; begin - if hi(AValue)<>0 then - result:=BsrByte(hi(AValue))+8 - else - result:=BsrByte(lo(AValue)) + result:=ord(AValue>255)*8; + result:=result or BsrByte(byte(AValue shr result)); end; {$endif} {$endif} @@ -2400,37 +2385,47 @@ function BsrWord(Const AValue: Word): {$ifdef CPU16}byte{$else}cardinal{$endif}; {$ifndef FPC_HAS_INTERNAL_BSF_DWORD} {$ifndef FPC_SYSTEM_HAS_BSF_DWORD} function BsfDWord(Const AValue : DWord): {$ifdef CPU16}byte{$else}cardinal{$endif}; -begin - result:=$ff; - if lo(AValue)<>0 then - result:=BsfWord(lo(AValue)) - else if hi(AValue) <> 0 then - result:=BsfWord(hi(AValue))+16 -end; + var + tmp: DWord; + begin + result:=ord(lo(AValue)=0)*16; + tmp:=AValue shr result; + result:=result or (ord((tmp and $FF)=0)*8); + tmp:=tmp shr (result and 8); + result:=result or BsfByte(byte(tmp)); + end; {$endif} {$endif} {$ifndef FPC_HAS_INTERNAL_BSR_DWORD} {$ifndef FPC_SYSTEM_HAS_BSR_DWORD} function BsrDWord(Const AValue : DWord): {$ifdef CPU16}byte{$else}cardinal{$endif}; -begin - if hi(AValue)<>0 then - result:=BsrWord(hi(AValue))+16 - else - result:=BsrWord(lo(AValue)) -end; + var + tmp: DWord; + begin + result:=ord(AValue>$FFFF)*16; + tmp:=AValue shr result; + result:=result or (ord(tmp>$FF)*8); + tmp:=tmp shr (result and 8); + result:=result or BsrByte(byte(tmp)); + end; {$endif} {$endif} {$ifndef FPC_HAS_INTERNAL_BSF_QWORD} {$ifndef FPC_SYSTEM_HAS_BSF_QWORD} function BsfQWord(Const AValue : QWord): {$ifdef CPU16}byte{$else}cardinal{$endif}; + var + tmp: DWord; begin - result:=$ff; - if lo(AValue) <> 0 then - result:=BsfDWord(lo(AValue)) - else if hi(AValue) <> 0 then - result:=BsfDWord(hi(AValue)) + 32; + result:=0; + tmp:=lo(AValue); + if (tmp=0) then + begin + tmp:=hi(AValue); + result:=32; + end; + result:=result or BsfDword(tmp); end; {$endif} {$endif} @@ -2438,11 +2433,17 @@ function BsfQWord(Const AValue : QWord): {$ifdef CPU16}byte{$else}cardinal{$endi {$ifndef FPC_HAS_INTERNAL_BSR_QWORD} {$ifndef FPC_SYSTEM_HAS_BSR_QWORD} function BsrQWord(Const AValue : QWord): {$ifdef CPU16}byte{$else}cardinal{$endif}; + var + tmp: DWord; begin - if hi(AValue) <> 0 then - result:=BsrDWord(hi(AValue)) + 32 - else - result:=BsrDWord(lo(AValue)) + result:=32; + tmp:=hi(AValue); + if (tmp=0) then + begin + tmp:=lo(AValue); + result:=0; + end; + result:=result or BsrDword(tmp); end; {$endif} {$endif} diff --git a/rtl/inc/genmath.inc b/rtl/inc/genmath.inc index 6eac64fd77..88c86bf195 100644 --- a/rtl/inc/genmath.inc +++ b/rtl/inc/genmath.inc @@ -90,7 +90,9 @@ const lossth = 1.073741824e9; MAXLOG = 8.8029691931113054295988E1; { log(2**127) } MINLOG = -8.872283911167299960540E1; { log(2**-128) } - + H2_54: double = 18014398509481984.0; {2^54} + huge: double = 1e300; + one: double = 1.0; zero: double = 0; {$if not defined(FPC_SYSTEM_HAS_SIN) or not defined(FPC_SYSTEM_HAS_COS)} @@ -397,9 +399,6 @@ type {* ldexp() multiplies x by 2**n. *} var i: integer; - const - H2_54: double = 18014398509481984.0; {2^54} - huge: double = 1e300; begin i := (float64high(x) and $7ff00000) shr 20; {if +-INF, NaN, 0 or if e=0 return d} @@ -1128,9 +1127,7 @@ type } function fpc_exp_real(d: ValReal):ValReal;compilerproc; const - one: double = 1.0; halF : array[0..1] of double = (0.5,-0.5); - huge: double = 1.0e+300; twom1000: double = 9.33263618503218878990e-302; { 2**-1000=0x01700000,0} o_threshold: double = 7.09782712893383973096e+02; { 0x40862E42, 0xFEFA39EF } u_threshold: double = -7.45133219101941108420e+02; { 0xc0874910, 0xD52D3051 } @@ -1466,7 +1463,7 @@ type k := 0; if (hx < $00100000) then { x < 2**-1022 } begin - if (((hx and $7fffffff) or lx)=0) then + if (((hx and $7fffffff) or longint(lx))=0) then exit(-two54/zero); { log(+-0)=-inf } if (hx<0) then exit((d-d)/zero); { log(-#) = NaN } @@ -1702,9 +1699,6 @@ type 1.62858201153657823623e-02 { 0x3F90AD3A, 0xE322DA11 } ); - one: double = 1.0; - huge: double = 1.0e300; - var w,s1,s2,z: double; ix,hx,id: longint; @@ -1927,3 +1921,310 @@ function FPower10(val: Extended; Power: Longint): Extended; end; end; {$endif SUPPORT_EXTENDED} + +{$ifdef SUPPORT_EXTENDED} +function TExtended80Rec.Mantissa : QWord; + begin + Result:=Frac and $7fffffffffffffff; + end; + + +function TExtended80Rec.Fraction : Extended; + begin + Result:=system.frac(Value); + end; + + +function TExtended80Rec.Exponent : Longint; + begin + Result:=Exp-16383; + end; + + +function TExtended80Rec.GetExp : QWord; + begin + Result:=_Exp and $7fff; + end; + + +procedure TExtended80Rec.SetExp(e : QWord); + begin + _Exp:=(_Exp and $8000) or (e and $7fff); + end; + + +function TExtended80Rec.GetSign : Boolean; + begin + Result:=(_Exp and $8000)<>0; + end; + + +procedure TExtended80Rec.SetSign(s : Boolean); + begin + _Exp:=(_Exp and $7ffff) or (ord(s) shl 15); + end; + +{ + Based on information taken from http://en.wikipedia.org/wiki/Extended_precision#x86_Extended_Precision_Format +} +function TExtended80Rec.SpecialType : TFloatSpecial; + const + Denormal : array[boolean] of TFloatSpecial = (fsDenormal,fsNDenormal); + begin + case Exp of + 0: + begin + if Mantissa=0 then + begin + if Sign then + Result:=fsNZero + else + Result:=fsZero + end + else + Result:=Denormal[Sign]; + end; + $7fff: + case (Frac shr 62) and 3 of + 0,1: + Result:=fsInvalidOp; + 2: + begin + if (Frac and $3fffffffffffffff)=0 then + begin + if Sign then + Result:=fsNInf + else + Result:=fsInf; + end + else + Result:=fsNaN; + end; + 3: + Result:=fsNaN; + end + else + begin + if (Frac and $8000000000000000)=0 then + Result:=fsInvalidOp + else + begin + if Sign then + Result:=fsNegative + else + Result:=fsPositive; + end; + end; + end; + end; + +{ +procedure TExtended80Rec.BuildUp(const _Sign : Boolean; const _Mantissa : QWord; const Exponent : Longint); + begin + end; +} +{$endif SUPPORT_EXTENDED} + + +{$ifdef SUPPORT_DOUBLE} +function TDoubleRec.Mantissa : QWord; + begin + Result:=Data and $fffffffffffff; + end; + + +function TDoubleRec.Fraction : ValReal; + begin + Result:=system.frac(Value); + end; + + +function TDoubleRec.Exponent : Longint; + begin + Result:=Exp-1023; + end; + + +function TDoubleRec.GetExp : QWord; + begin + Result:=(Data and $7ff0000000000000) shr 52; + end; + + +procedure TDoubleRec.SetExp(e : QWord); + begin + Data:=(Data and $800fffffffffffff) or ((e and $7ff) shl 52); + end; + + +function TDoubleRec.GetSign : Boolean; + begin + Result:=(Data and $8000000000000000)<>0; + end; + + +procedure TDoubleRec.SetSign(s : Boolean); + begin + Data:=(Data and $7fffffffffffffff) or (QWord(ord(s)) shl 63); + end; + + +function TDoubleRec.GetFrac : QWord; + begin + Result:=$10000000000000 or Mantissa; + end; + + +procedure TDoubleRec.SetFrac(e : QWord); + begin + Data:=(Data and $7ff0000000000000) or (e and $fffffffffffff); + end; + +{ + Based on information taken from http://en.wikipedia.org/wiki/Double_precision#x86_Extended_Precision_Format +} +function TDoubleRec.SpecialType : TFloatSpecial; + const + Denormal : array[boolean] of TFloatSpecial = (fsDenormal,fsNDenormal); + begin + case Exp of + 0: + begin + if Mantissa=0 then + begin + if Sign then + Result:=fsNZero + else + Result:=fsZero + end + else + Result:=Denormal[Sign]; + end; + $7ff: + if Mantissa=0 then + begin + if Sign then + Result:=fsNInf + else + Result:=fsInf; + end + else + Result:=fsNaN; + else + begin + if Sign then + Result:=fsNegative + else + Result:=fsPositive; + end; + end; + end; + +{ +procedure TDoubleRec.BuildUp(const _Sign : Boolean; const _Mantissa : QWord; const Exponent : Longint); + begin + end; +} +{$endif SUPPORT_DOUBLE} + + +{$ifdef SUPPORT_SINGLE} +function TSingleRec.Mantissa : QWord; + begin + Result:=Data and $7fffff; + end; + + +function TSingleRec.Fraction : ValReal; + begin + Result:=system.frac(Value); + end; + + +function TSingleRec.Exponent : Longint; + begin + Result:=Exp-127; + end; + + +function TSingleRec.GetExp : QWord; + begin + Result:=(Data and $7f800000) shr 23; + end; + + +procedure TSingleRec.SetExp(e : QWord); + begin + Data:=(Data and $807fffff) or ((e and $ff) shl 23); + end; + + +function TSingleRec.GetSign : Boolean; + begin + Result:=(Data and $80000000)<>0; + end; + + +procedure TSingleRec.SetSign(s : Boolean); + begin + Data:=(Data and $7fffffff) or (DWord(ord(s)) shl 31); + end; + + +function TSingleRec.GetFrac : QWord; + begin + Result:=$8000000 or Mantissa; + end; + + +procedure TSingleRec.SetFrac(e : QWord); + begin + Data:=(Data and $ff800000) or (e and $7fffff); + end; + +{ + Based on information taken from http://en.wikipedia.org/wiki/Single_precision#x86_Extended_Precision_Format +} +function TSingleRec.SpecialType : TFloatSpecial; + const + Denormal : array[boolean] of TFloatSpecial = (fsDenormal,fsNDenormal); + begin + case Exp of + 0: + begin + if Mantissa=0 then + begin + if Sign then + Result:=fsNZero + else + Result:=fsZero + end + else + Result:=Denormal[Sign]; + end; + $ff: + if Mantissa=0 then + begin + if Sign then + Result:=fsNInf + else + Result:=fsInf; + end + else + Result:=fsNaN; + else + begin + if Sign then + Result:=fsNegative + else + Result:=fsPositive; + end; + end; + end; + +{ +procedure TSingleRec.BuildUp(const _Sign : Boolean; const _Mantissa : QWord; const Exponent : Longint); + begin + end; +} +{$endif SUPPORT_SINGLE} diff --git a/rtl/inc/innr.inc b/rtl/inc/innr.inc index aec400c1b3..83d6fbeffd 100644 --- a/rtl/inc/innr.inc +++ b/rtl/inc/innr.inc @@ -88,6 +88,8 @@ const fpc_in_box_x = 77; { managed platforms: wrap in class instance } fpc_in_unbox_x_y = 78; { manage platforms: extract from class instance } fpc_in_popcnt_x = 79; + fpc_in_aligned_x = 80; + fpc_in_setstring_x_y_z = 81; { Internal constant functions } fpc_in_const_sqr = 100; diff --git a/rtl/inc/int64.inc b/rtl/inc/int64.inc index 5abd5b4e04..70096ca9ab 100644 --- a/rtl/inc/int64.inc +++ b/rtl/inc/int64.inc @@ -122,6 +122,12 @@ shift,lzz,lzn : longint; begin + { Use the usually faster 32-bit division if possible } + if (hi(z) = 0) and (hi(n) = 0) then + begin + fpc_div_qword := Dword(z) div Dword(n); + exit; + end; fpc_div_qword:=0; if n=0 then HandleErrorAddrFrameInd(200,get_pc_addr,get_frame); @@ -134,6 +140,7 @@ { then d is greater than the n } if lzn>lzz then exit; + shift:=lzz-lzn; n:=n shl shift; for shift:=shift downto 0 do @@ -156,6 +163,12 @@ shift,lzz,lzn : longint; begin + { Use the usually faster 32-bit mod if possible } + if (hi(z) = 0) and (hi(n) = 0) then + begin + fpc_mod_qword := Dword(z) mod Dword(n); + exit; + end; fpc_mod_qword:=0; if n=0 then HandleErrorAddrFrameInd(200,get_pc_addr,get_frame); diff --git a/rtl/inc/mathh.inc b/rtl/inc/mathh.inc index bb079d9982..88f9a20242 100644 --- a/rtl/inc/mathh.inc +++ b/rtl/inc/mathh.inc @@ -115,6 +115,86 @@ procedure float_raise(i: TFPUExceptionMask); operator := (b:real48) e:extended; {$endif SUPPORT_EXTENDED} + type + TFloatSpecial = (fsZero,fsNZero,fsDenormal,fsNDenormal,fsPositive,fsNegative, + fsInf,fsNInf,fsNaN,fsInvalidOp); + +{$ifdef SUPPORT_EXTENDED} + TExtended80Rec = packed record + private + function GetExp : QWord; + procedure SetExp(e : QWord); + function GetSign : Boolean; + procedure SetSign(s : Boolean); + public + function Mantissa : QWord; + function Fraction : Extended; + function Exponent : Longint; + property Sign : Boolean read GetSign write SetSign; + property Exp : QWord read GetExp write SetExp; + function SpecialType : TFloatSpecial; + // procedure BuildUp(const _Sign : Boolean; const _Mantissa : QWord; const Exponent : Longint); + case byte of + 0: (Bytes : array[0..9] of Byte); + 1: (Words : array[0..4] of Word); +{$ifdef ENDIAN_LITTLE} + 2: (Frac : QWord; _Exp: Word); +{$else ENDIAN_LITTLE} + 2: (_Exp: Word; Frac : QWord); +{$endif ENDIAN_LITTLE} + 3: (Value: Extended); + end; +{$endif SUPPORT_EXTENDED} + +{$ifdef SUPPORT_DOUBLE} + TDoubleRec = packed record + private + function GetExp : QWord; + procedure SetExp(e : QWord); + function GetSign : Boolean; + procedure SetSign(s : Boolean); + function GetFrac : QWord; + procedure SetFrac(e : QWord); + public + function Mantissa : QWord; + function Fraction : ValReal; + function Exponent : Longint; + property Sign : Boolean read GetSign write SetSign; + property Exp : QWord read GetExp write SetExp; + property Frac : QWord read Getfrac write SetFrac; + function SpecialType : TFloatSpecial; + case byte of + 0: (Bytes : array[0..7] of Byte); + 1: (Words : array[0..3] of Word); + 2: (Data : QWord); + 3: (Value: Double); + end; +{$endif SUPPORT_DOUBLE} + +{$ifdef SUPPORT_SINGLE} + TSingleRec = packed record + private + function GetExp : QWord; + procedure SetExp(e : QWord); + function GetSign : Boolean; + procedure SetSign(s : Boolean); + function GetFrac : QWord; + procedure SetFrac(e : QWord); + public + function Mantissa : QWord; + function Fraction : ValReal; + function Exponent : Longint; + property Sign : Boolean read GetSign write SetSign; + property Exp : QWord read GetExp write SetExp; + property Frac : QWord read Getfrac write SetFrac; + function SpecialType : TFloatSpecial; + case byte of + 0: (Bytes : array[0..3] of Byte); + 1: (Words : array[0..1] of Word); + 2: (Data : DWord); + 3: (Value: Single); + end; +{$endif SUPPORT_SINGLE} function FMASingle(s1,s2,s3 : single) : single;[internproc:fpc_in_fma_single]; {$ifdef SUPPORT_DOUBLE} diff --git a/rtl/inc/objpash.inc b/rtl/inc/objpash.inc index 9eb394404e..4af69c8c49 100644 --- a/rtl/inc/objpash.inc +++ b/rtl/inc/objpash.inc @@ -154,10 +154,10 @@ tinterfaceentrytype = (etStandard, etVirtualMethodResult, etStaticMethodResult, - etFieldValue, + etFieldValue, etVirtualMethodClass, etStaticMethodClass, - etFieldValueClass + etFieldValueClass ); pinterfaceentry = ^tinterfaceentry; @@ -376,9 +376,9 @@ vtInteger = 0; vtBoolean = 1; vtChar = 2; -{$ifndef FPUNONE} +{$ifndef FPUNONE} vtExtended = 3; -{$endif} +{$endif} vtString = 4; vtPointer = 5; vtPChar = 6; @@ -399,23 +399,23 @@ PVarRec = ^TVarRec; TVarRec = record case VType : sizeint of -{$ifdef ENDIAN_BIG} +{$ifdef ENDIAN_BIG} vtInteger : ({$IFDEF CPU64}integerdummy1 : Longint;{$ENDIF CPU64}VInteger: Longint); vtBoolean : ({$IFDEF CPU64}booldummy : Longint;{$ENDIF CPU64}booldummy1,booldummy2,booldummy3: byte; VBoolean: Boolean); vtChar : ({$IFDEF CPU64}chardummy : Longint;{$ENDIF CPU64}chardummy1,chardummy2,chardummy3: byte; VChar: Char); vtWideChar : ({$IFDEF CPU64}widechardummy : Longint;{$ENDIF CPU64}wchardummy1,VWideChar: WideChar); -{$else ENDIAN_BIG} +{$else ENDIAN_BIG} vtInteger : (VInteger: Longint); vtBoolean : (VBoolean: Boolean); vtChar : (VChar: Char); vtWideChar : (VWideChar: WideChar); -{$endif ENDIAN_BIG} -{$ifndef FPUNONE} +{$endif ENDIAN_BIG} +{$ifndef FPUNONE} vtExtended : (VExtended: PExtended); -{$endif} +{$endif} vtString : (VString: PShortString); vtPointer : (VPointer: Pointer); - vtPChar : (VPChar: PChar); + vtPChar : (VPChar: PAnsiChar); vtObject : (VObject: TObject); vtClass : (VClass: TClass); vtPWideChar : (VPWideChar: PWideChar); diff --git a/rtl/inc/rtti.inc b/rtl/inc/rtti.inc index fdf3954759..6991b573f2 100644 --- a/rtl/inc/rtti.inc +++ b/rtl/inc/rtti.inc @@ -392,3 +392,19 @@ procedure fpc_decref_array(data,typeinfo: pointer; count: SizeInt); [public,alia int_finalizeArray(data,typeinfo,count); end; +procedure InitializeArray(p, typeInfo: Pointer; count: SizeInt); + external name 'FPC_INITIALIZE_ARRAY'; + +procedure FinalizeArray(p, typeInfo: Pointer; count: SizeInt); + external name 'FPC_FINALIZE_ARRAY'; + +procedure CopyArray(dest, source, typeInfo: Pointer; count: SizeInt); + var + i, size: SizeInt; + begin + size:=RTTISize(typeInfo); + if size>0 then + for i:=0 to count-1 do + fpc_Copy_internal(source+size*i, dest+size*i, typeInfo); + end; + diff --git a/rtl/inc/rttih.inc b/rtl/inc/rttih.inc new file mode 100644 index 0000000000..d092088fc6 --- /dev/null +++ b/rtl/inc/rttih.inc @@ -0,0 +1,18 @@ +{ + This file is part of the Free Pascal run time library. + Copyright (c) 1999-2014 by Maciej Izak + + 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. + + **********************************************************************} + +procedure InitializeArray(p, typeInfo: Pointer; count: SizeInt); +procedure FinalizeArray(p, typeInfo: Pointer; count: SizeInt); +procedure CopyArray(dest, source, typeInfo: Pointer; count: SizeInt); + + diff --git a/rtl/inc/softfpu.pp b/rtl/inc/softfpu.pp index 3ad877dd9d..d9f23c16c5 100644 --- a/rtl/inc/softfpu.pp +++ b/rtl/inc/softfpu.pp @@ -132,15 +132,6 @@ TYPE 2: (dummy : double); end; - int64rec = record - case byte of - 1: (low,high : bits32); - // force the record to be aligned like a double - // else *_to_double will fail for cpus like sparc - // and avoid expensive unpacking/packing operations - 2: (dummy : int64); - end; - floatx80 = record case byte of 1: (low : qword;high : word); @@ -167,15 +158,6 @@ TYPE 2: (dummy : double); end; - int64rec = record - case byte of - 1: (high,low : bits32); - // force the record to be aligned like a double - // else *_to_double will fail for cpus like sparc - // and avoid expensive unpacking/packing operations - 2: (dummy : int64); -end; - floatx80 = record case byte of 1: (high : word;low : qword); @@ -604,14 +586,14 @@ end; function roundAndPackInt32( zSign: flag; absZ : bits64): int32; var roundingMode: TFPURoundingMode; - roundNearestEven: flag; + roundNearestEven: boolean; roundIncrement, roundBits: int8; z: int32; begin roundingMode := softfloat_rounding_mode; - roundNearestEven := ord( roundingMode = float_round_nearest_even ); + roundNearestEven := (roundingMode = float_round_nearest_even); roundIncrement := $40; - if ( roundNearestEven=0 ) then + if not roundNearestEven then begin if ( roundingMode = float_round_to_zero ) then begin @@ -630,13 +612,13 @@ begin end; end; end; - roundBits := absZ and $7F; + roundBits := lo(absZ) and $7F; absZ := ( absZ + roundIncrement ) shr 7; - absZ := absZ and not( ord( ( roundBits xor $40 ) = 0 ) and roundNearestEven ); + absZ := absZ and not( bits64( ord( ( roundBits xor $40 ) = 0 ) and ord(roundNearestEven) )); z := absZ; if ( zSign<>0 ) then z := - z; - if ( ( absZ shr 32 ) or ( z and ( ord( z < 0 ) xor zSign ) ) )<>0 then + if ( longint(hi( absZ )) or ( z and ( ord( z < 0 ) xor zSign ) ) )<>0 then begin float_raise( float_flag_invalid ); if zSign<>0 then @@ -1341,9 +1323,9 @@ Var aHigh, aLow, bHigh, bLow: bits16; z0, zMiddleA, zMiddleB, z1: bits32; Begin - aLow := a and $ffff; + aLow := bits16(a); aHigh := a shr 16; - bLow := b and $ffff; + bLow := bits16(b); bHigh := b shr 16; z1 := ( bits32( aLow) ) * bLow; zMiddleA := ( bits32 (aLow) ) * bHigh; @@ -1620,7 +1602,7 @@ Begin z := ( z shl 15 ); if ( z <= a ) then Begin - estimateSqrt32 := bits32 ( ( sbits32 (a )) shr 1 ); + estimateSqrt32 := bits32 ( SarLongint( sbits32 (a)) ); exit; End; End; @@ -2335,7 +2317,7 @@ var Returns the fraction bits of the single-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function ExtractFloat32Frac(a : Float32) : Bits32; +Function ExtractFloat32Frac(a : Float32) : Bits32; inline; Begin ExtractFloat32Frac := A AND $007FFFFF; End; @@ -2345,7 +2327,7 @@ Function ExtractFloat32Frac(a : Float32) : Bits32; Returns the exponent bits of the single-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function extractFloat32Exp( a: float32 ): Int16; +Function extractFloat32Exp( a: float32 ): Int16; inline; Begin extractFloat32Exp := (a shr 23) AND $FF; End; @@ -2355,7 +2337,7 @@ Function extractFloat32Exp( a: float32 ): Int16; Returns the sign bit of the single-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function extractFloat32Sign( a: float32 ): Flag; +Function extractFloat32Sign( a: float32 ): Flag; inline; Begin extractFloat32Sign := a shr 31; End; @@ -2390,7 +2372,7 @@ than the desired result exponent whenever `zSig' is a complete, normalized significand. ------------------------------------------------------------------------------- *} -Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32; +Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32; inline; Begin packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 ) @@ -2423,19 +2405,14 @@ Binary Floating-Point Arithmetic. Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32; Var roundingMode : TFPURoundingMode; - roundNearestEven : Flag; + roundNearestEven : boolean; roundIncrement, roundBits : BYTE; - IsTiny : Flag; + IsTiny : boolean; Begin roundingMode := softfloat_rounding_mode; - if (roundingMode = float_round_nearest_even) then - Begin - roundNearestEven := Flag(TRUE); - end - else - roundNearestEven := Flag(FALSE); + roundNearestEven := (roundingMode = float_round_nearest_even); roundIncrement := $40; - if ( Boolean(roundNearestEven) = FALSE) then + if not roundNearestEven then Begin if ( roundingMode = float_round_to_zero ) Then Begin @@ -2466,23 +2443,22 @@ Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : floa if ( zExp < 0 ) then Begin isTiny := - flag(( softfloat_detect_tininess = float_tininess_before_rounding ) + ( softfloat_detect_tininess = float_tininess_before_rounding ) OR ( zExp < -1 ) - OR ( (zSig + roundIncrement) < $80000000 )); + OR ( (zSig + roundIncrement) < $80000000 ); shift32RightJamming( zSig, - zExp, zSig ); zExp := 0; roundBits := zSig AND $7F; - if ( (isTiny = flag(TRUE)) and (roundBits<>0) ) then + if ( isTiny and (roundBits<>0) ) then float_raise( float_flag_underflow ); End; End; if ( roundBits )<> 0 then set_inexact_flag; zSig := ( zSig + roundIncrement ) shr 7; - zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and roundNearestEven ); + zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and ord(roundNearestEven) ); if ( zSig = 0 ) then zExp := 0; roundAndPackFloat32 := packFloat32( zSign, zExp, zSig ); - exit; End; {* @@ -2509,7 +2485,7 @@ Returns the most-significant 20 fraction bits of the double-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function extractFloat64Frac0(a: float64): bits32; +Function extractFloat64Frac0(a: float64): bits32; inline; Begin extractFloat64Frac0 := a.high and $000FFFFF; End; @@ -2520,14 +2496,14 @@ Returns the least-significant 32 fraction bits of the double-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function extractFloat64Frac1(a: float64): bits32; +Function extractFloat64Frac1(a: float64): bits32; inline; Begin extractFloat64Frac1 := a.low; End; {$define FPC_SYSTEM_HAS_extractFloat64Frac} -Function extractFloat64Frac(a: float64): bits64; +Function extractFloat64Frac(a: float64): bits64; inline; Begin extractFloat64Frac := bits64(a) and $000FFFFFFFFFFFFF; End; @@ -2537,7 +2513,7 @@ Function extractFloat64Frac(a: float64): bits64; Returns the exponent bits of the double-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function extractFloat64Exp(a: float64): int16; +Function extractFloat64Exp(a: float64): int16; inline; Begin extractFloat64Exp:= ( a.high shr 20 ) AND $7FF; End; @@ -2547,7 +2523,7 @@ Function extractFloat64Exp(a: float64): int16; Returns the sign bit of the double-precision floating-point value `a'. ------------------------------------------------------------------------------- *} -Function extractFloat64Sign(a: float64) : flag; +Function extractFloat64Sign(a: float64) : flag; inline; Begin extractFloat64Sign := a.high shr 31; End; @@ -2885,6 +2861,25 @@ Procedure End; {* +---------------------------------------------------------------------------- +Takes an abstract floating-point value having sign `zSign', exponent `zExp', +and significand `zSig', and returns the proper double-precision floating- +point value corresponding to the abstract input. This routine is just like +`roundAndPackFloat64' except that `zSig' does not have to be normalized. +Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +floating-point exponent. +---------------------------------------------------------------------------- +*} + +function normalizeRoundAndPackFloat64(zSign: flag; zExp: int16; zSig: bits64): float64; + var + shiftCount: int8; + begin + shiftCount := countLeadingZeros64( zSig ) - 1; + result := roundAndPackFloat64( zSign, zExp - shiftCount, zSig shl shiftCount); + end; + +{* ------------------------------------------------------------------------------- Returns the result of converting the 32-bit two's complement integer `a' to the single-precision floating-point format. The conversion is performed @@ -3756,7 +3751,7 @@ Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc; float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 ); exit; End; - if ( ( bExp OR bSig ) = 0 ) then + if ( ( bits32(bExp) OR bSig ) = 0 ) then Begin float_raise( float_flag_invalid ); float32_mul.float32 := float32_default_nan; @@ -3772,7 +3767,7 @@ Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc; float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 ); exit; End; - if ( ( aExp OR aSig ) = 0 ) then + if ( ( bits32(aExp) OR aSig ) = 0 ) then Begin float_raise( float_flag_invalid ); float32_mul.float32 := float32_default_nan; @@ -3867,7 +3862,7 @@ Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc; Begin if ( bSig = 0 ) Then Begin - if ( ( aExp OR aSig ) = 0 ) then + if ( ( bits32(aExp) OR aSig ) = 0 ) then Begin float_raise( float_flag_invalid ); float32_div.float32 := float32_default_nan; @@ -4065,7 +4060,7 @@ Begin End; if ( aSign <> 0) then Begin - if ( ( aExp OR aSig ) = 0 ) then + if ( ( bits32(aExp) OR aSig ) = 0 ) then Begin float32_sqrt := a; exit; @@ -4423,7 +4418,7 @@ Var Begin if ( aExp < $3FF ) then Begin - if ( aExp OR aSig0 OR aSig1 )<>0 then + if ( bits32(aExp) OR aSig0 OR aSig1 )<>0 then Begin set_inexact_flag; End; @@ -5071,7 +5066,7 @@ Begin propagateFloat64NaN( a, b, result ); exit; End; - if ( ( bExp OR bSig0 OR bSig1 ) = 0 ) then goto invalid; + if ( ( bits32(bExp) OR bSig0 OR bSig1 ) = 0 ) then goto invalid; packFloat64( zSign, $7FF, 0, 0, result ); exit; End; @@ -5186,7 +5181,7 @@ Begin Begin if ( ( bSig0 OR bSig1 ) = 0 ) then Begin - if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then + if ( ( bits32(aExp) OR aSig0 OR aSig1 ) = 0 ) then Begin invalid: float_raise( float_flag_invalid ); @@ -5418,7 +5413,7 @@ Begin End; if ( aSign <> 0 ) then Begin - if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then + if ( ( bits32(aExp) OR aSig0 OR aSig1 ) = 0 ) then Begin result := a; exit; @@ -5761,7 +5756,6 @@ var zSign : flag; absA : uint64; shiftCount: int8; - intval : int64rec; Begin if ( a = 0 ) then begin @@ -5785,14 +5779,7 @@ Begin begin shiftCount := shiftCount + 7; if ( shiftCount < 0 ) then - begin - intval.low := int64rec(AbsA).low; - intval.high := int64rec(AbsA).high; - shift64RightJamming( intval.high, intval.low, - shiftCount, - intval.high, intval.low); - int64rec(absA).low := intval.low; - int64rec(absA).high := intval.high; - end + shift64RightJamming( absA, - shiftCount, absA ) else absA := absA shl shiftCount; int64_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA ); @@ -5807,38 +5794,28 @@ End; *----------------------------------------------------------------------------*} function qword_to_float32( a: qword ): float32rec; compilerproc; var - zSign : flag; absA : uint64; shiftCount: int8; - intval : int64rec; Begin if ( a = 0 ) then begin qword_to_float32.float32 := 0; exit; end; - zSign := flag(FALSE); absA := a; shiftCount := countLeadingZeros64( absA ) - 40; if ( 0 <= shiftCount ) then begin - qword_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount ); + qword_to_float32.float32:= packFloat32( 0, $95 - shiftCount, absA shl shiftCount ); end else begin shiftCount := shiftCount + 7; if ( shiftCount < 0 ) then - begin - intval.low := int64rec(AbsA).low; - intval.high := int64rec(AbsA).high; - shift64RightJamming( intval.high, intval.low, - shiftCount, - intval.high, intval.low); - int64rec(absA).low := intval.low; - int64rec(absA).high := intval.high; - end + shift64RightJamming( absA, - shiftCount, absA ) else absA := absA shl shiftCount; - qword_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA ); + qword_to_float32.float32:=roundAndPackFloat32( 0, $9C - shiftCount, absA ); end; End; @@ -5851,33 +5828,25 @@ End; function qword_to_float64( a: qword ): float64; {$ifdef fpc}[public,Alias:'QWORD_TO_FLOAT64'];compilerproc;{$endif} var - zSign : flag; - float_result : float64; - AbsA : bits64; - shiftcount : int8; - zSig0, zSig1 : bits32; + shiftCount: int8; Begin - if ( a = 0 ) then - Begin - packFloat64( 0, 0, 0, 0, result ); - exit; - end; - zSign := flag(FALSE); - AbsA := a; - shiftCount := countLeadingZeros64( absA ) - 11; - if ( 0 <= shiftCount ) then - Begin - absA := absA shl shiftcount; - zSig0:=int64rec(absA).high; - zSig1:=int64rec(absA).low; - End - else - Begin - shift64Right( int64rec(absA).high, int64rec(absA).low, - - shiftCount, zSig0, zSig1 ); - End; - packFloat64( zSign, $432 - shiftCount, zSig0, zSig1, float_result ); - qword_to_float64:= float_result; + if ( a = 0 ) then + result := packFloat64( 0, 0, 0 ) + else + begin + shiftCount := countLeadingZeros64(a) - 1; + { numbers with <= 53 significant bits are converted exactly } + if (shiftCount > 9) then + result := packFloat64(0, $43c - shiftCount, a shl (shiftCount-10)) + else if (shiftCount>=0) then + result := roundAndPackFloat64( 0, $43c - shiftCount, a shl shiftCount) + else + begin + { the only possible negative value is -1, in case bit 63 of 'a' is set } + shift64RightJamming(a, 1, a); + result := roundAndPackFloat64(0, $43d, a); + end; + end; End; @@ -5889,37 +5858,15 @@ End; *----------------------------------------------------------------------------*} function int64_to_float64( a: int64 ): float64; {$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];compilerproc;{$endif} -var - zSign : flag; - float_result : float64; - AbsA : bits64; - shiftcount : int8; - zSig0, zSig1 : bits32; Begin - if ( a = 0 ) then - Begin - packFloat64( 0, 0, 0, 0, result ); - exit; - end; - zSign := flag( a < 0 ); - if ZSign<>0 then - AbsA := -a - else - AbsA := a; - shiftCount := countLeadingZeros64( absA ) - 11; - if ( 0 <= shiftCount ) then - Begin - absA := absA shl shiftcount; - zSig0:=int64rec(absA).high; - zSig1:=int64rec(absA).low; - End - else - Begin - shift64Right( int64rec(absA).high, int64rec(absA).low, - - shiftCount, zSig0, zSig1 ); - End; - packFloat64( zSign, $432 - shiftCount, zSig0, zSig1, float_result ); - int64_to_float64:= float_result; + if ( a = 0 ) then + result := packFloat64( 0, 0, 0 ) + else if (a = int64($8000000000000000)) then + result := packFloat64( 1, $43e, 0 ) + else if (a < 0) then + result := normalizeRoundAndPackFloat64( 1, $43c, -a ) + else + result := normalizeRoundAndPackFloat64( 0, $43c, a ); End; diff --git a/rtl/inc/sstrings.inc b/rtl/inc/sstrings.inc index 23dad25481..f16f2c910f 100644 --- a/rtl/inc/sstrings.inc +++ b/rtl/inc/sstrings.inc @@ -2080,7 +2080,7 @@ end; {$ifndef FPC_HAS_SETSTRING_SHORTSTR} {$define FPC_HAS_SETSTRING_SHORTSTR} -Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_shortstr{$else}SetString{$endif}(Out S : Shortstring; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} begin If Len > High(S) then Len := High(S); diff --git a/rtl/inc/system.fpd b/rtl/inc/system.fpd index 7bd5fc3859..dfd8504aeb 100644 --- a/rtl/inc/system.fpd +++ b/rtl/inc/system.fpd @@ -19,6 +19,8 @@ Type Char = #0..#255; Longint = -2147483648..2147483647; Longword= 0..4294967295; + Int64 = =-9223372036854775808.. 9223372036854775807; + QWord = 0..18446744073709551615; Shortint= -128 .. 127; Smallint= -32768 .. 32767; Word = 0 .. 65535; diff --git a/rtl/inc/system.inc b/rtl/inc/system.inc index 8f64474bc3..ea7a80d7c0 100644 --- a/rtl/inc/system.inc +++ b/rtl/inc/system.inc @@ -352,22 +352,22 @@ End; Function Swap (X : Longint) : Longint;{$ifdef SYSTEMINLINE}inline;{$endif} Begin - Swap:=(X and $ffff) shl 16 + (X shr 16) + Swap:=(X shl 16) + (X shr 16); End; Function Swap (X : Cardinal) : Cardinal;{$ifdef SYSTEMINLINE}inline;{$endif} Begin - Swap:=(X and $ffff) shl 16 + (X shr 16) + Swap:=(X shl 16) + (X shr 16); End; Function Swap (X : QWord) : QWord;{$ifdef SYSTEMINLINE}inline;{$endif} Begin - Swap:=(X and $ffffffff) shl 32 + (X shr 32); + Swap:=(X shl 32) + (X shr 32); End; -Function swap (X : Int64) : Int64;{$ifdef SYSTEMINLINE}inline;{$endif} +Function Swap (X : Int64) : Int64;{$ifdef SYSTEMINLINE}inline;{$endif} Begin - Swap:=(X and $ffffffff) shl 32 + (X shr 32); + Swap:=(X shl 32) + (X shr 32); End; {$ifdef SUPPORT_DOUBLE} @@ -1519,6 +1519,7 @@ begin end; +{$ifdef FPC_HAS_FEATURE_ANSISTRINGS} procedure DoDirSeparators(var ps:RawByteString); var i : longint; @@ -1538,7 +1539,10 @@ begin p[i-1]:=DirectorySeparator; end; end; +{$endif FPC_HAS_FEATURE_ANSISTRINGS} + +{$ifdef FPC_HAS_FEATURE_UNICODESTRINGS} procedure DoDirSeparators(var ps:UnicodeString); var i : longint; @@ -1558,6 +1562,7 @@ begin p[i-1]:=DirectorySeparator; end; end; +{$endif FPC_HAS_FEATURE_UNICODESTRINGS} {$endif FPC_HAS_FEATURE_FILEIO} @@ -1642,8 +1647,20 @@ end; {$endif FPC_HAS_FEATURE_FILEIO} +{ helper for targets supporting no ansistrings, it is used + by non-ansistring code } +function min(v1,v2 : SizeInt) : SizeInt; + begin + if v1<v2 then + result:=v1 + else + result:=v2; + end; + +{$ifdef FPC_HAS_FEATURE_TEXTIO} { Text file } {$i text.inc} +{$endif FPC_HAS_FEATURE_TEXTIO} {$ifdef FPC_HAS_FEATURE_FILEIO} { Untyped file } diff --git a/rtl/inc/systemh.inc b/rtl/inc/systemh.inc index 9cd447fa8c..69b489ad9f 100644 --- a/rtl/inc/systemh.inc +++ b/rtl/inc/systemh.inc @@ -20,6 +20,7 @@ {$I-,Q-,H-,R-,V-} {$mode objfpc} +{$modeswitch advancedrecords} { At least 2.4.0 is required } {$if defined(VER1) or defined(VER2_0) or defined(VER2_2) } @@ -412,6 +413,7 @@ Type AnsiChar = Char; PAnsiChar = PChar; PPAnsiChar = PPChar; + PPPAnsiChar = PPPChar; UCS4Char = type 0..$10ffff; PUCS4Char = ^UCS4Char; @@ -524,7 +526,8 @@ Type { the size of textrec/filerec is hardcoded in the 2.6 compiler binary } {$define FPC_ANSI_TEXTFILEREC} {$endif} - TFileTextRecChar = {$ifdef FPC_ANSI_TEXTFILEREC}AnsiChar{$else}UnicodeChar{$endif}; + + TFileTextRecChar = {$if defined(FPC_ANSI_TEXTFILEREC) or not(defined(FPC_HAS_FEATURE_WIDESTRINGS))}AnsiChar{$else}UnicodeChar{$endif}; PFileTextRecChar = ^TFileTextRecChar; TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR); @@ -1070,10 +1073,16 @@ Function Pos(const substr:shortstring;const s:shortstring):SizeInt; Function Pos(C:Char;const s:shortstring):SizeInt; {$ifdef FPC_HAS_FEATURE_ANSISTRINGS} Function Pos(const Substr : ShortString; const Source : RawByteString) : SizeInt; + +{$ifdef FPC_HAS_CPSTRING} +Procedure fpc_setstring_ansistr_pansichar(out S : RawByteString; Buf : PAnsiChar; Len : SizeInt; cp: TSystemCodePage); rtlproc; compilerproc; +Procedure fpc_setstring_ansistr_pwidechar(out S : RawByteString; Buf : PWideChar; Len : SizeInt; cp: TSystemCodePage); rtlproc; compilerproc; +{$else} Procedure SetString(out S : AnsiString; Buf : PAnsiChar; Len : SizeInt); Procedure SetString(out S : AnsiString; Buf : PWideChar; Len : SizeInt); +{$endif} {$endif FPC_HAS_FEATURE_ANSISTRINGS} -Procedure SetString (out S : Shortstring; Buf : PChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_shortstr{$else}SetString{$endif}(out S : Shortstring; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} function ShortCompareText(const S1, S2: shortstring): SizeInt; Function upCase(const s:shortstring):shortstring; Function lowerCase(const s:shortstring):shortstring; overload; @@ -1469,6 +1478,14 @@ const {$endif FPC_HAS_FEATURE_VARIANTS} {***************************************************************************** + RTTI support +*****************************************************************************} + +{$ifdef FPC_HAS_FEATURE_RTTI} +{$i rttih.inc} +{$endif FPC_HAS_FEATURE_RTTI} + +{***************************************************************************** Internal helper routines support *****************************************************************************} diff --git a/rtl/inc/text.inc b/rtl/inc/text.inc index 75379c70da..fa89f8672c 100644 --- a/rtl/inc/text.inc +++ b/rtl/inc/text.inc @@ -200,10 +200,15 @@ Begin TextRec(t).mode:=mode; TextRec(t).bufpos:=0; TextRec(t).bufend:=0; - {$ifdef FPC_HAS_CPSTRING} + +{$ifdef FPC_HAS_CPSTRING} +{$ifdef FPC_HAS_FEATURE_ANSISTRINGS} { if no codepage is yet assigned then assign default ansi codepage } TextRec(t).CodePage:=TranslatePlaceholderCP(TextRec(t).CodePage); - {$endif} +{$else FPC_HAS_FEATURE_ANSISTRINGS} + TextRec(t).CodePage:=0; +{$endif FPC_HAS_FEATURE_ANSISTRINGS} +{$endif FPC_HAS_CPSTRING} FileFunc(TextRec(t).OpenFunc)(TextRec(t)); { reset the mode to closed when an error has occured } if InOutRes<>0 then @@ -266,6 +271,7 @@ Begin End; +{$ifdef FPC_HAS_FEATURE_WIDESTRINGS} Procedure Rename(var t : Text;const s : unicodestring);[IOCheck]; {$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API} var @@ -296,8 +302,11 @@ Begin {$endif FPC_ANSI_TEXTFILEREC} {$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API} End; +{$endif FPC_HAS_FEATURE_WIDESTRINGS} + +{$ifdef FPC_HAS_FEATURE_ANSISTRINGS} Procedure Rename(var t : Text;const s : rawbytestring);[IOCheck]; var {$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API} @@ -342,6 +351,7 @@ Begin TextRec(t).Name:=fs {$endif FPC_ANSI_TEXTTextRec and not FPCRTL_FILESYSTEM_SINGLE_BYTE_API} End; +{$endif FPC_HAS_FEATURE_ANSISTRINGS} Procedure Rename(var t : Text;const s : ShortString);[IOCheck]; @@ -366,16 +376,16 @@ Begin End; {$else FPC_HAS_FEATURE_ANSISTRINGS} var - len: SizeInt + len: SizeInt; Begin if InOutRes<>0 then exit; - if TextRec(f).mode<>fmClosed then + if TextRec(t).mode<>fmClosed then begin InOutRes:=102; exit; end; - Do_Rename(PFileTextRecChar(@TextRec(t).Name),p,false); + Do_Rename(PFileTextRecChar(@TextRec(t).Name),p,false,false); { check error code of do_rename } if InOutRes=0 then begin @@ -602,16 +612,17 @@ End; function GetTextCodePage(var T: Text): TSystemCodePage; begin -{$ifdef FPC_HAS_CPSTRING} +{$if defined(FPC_HAS_CPSTRING) and defined(FPC_HAS_FEATURE_ANSISTRINGS)} GetTextCodePage:=TextRec(T).CodePage; {$else} GetTextCodePage:=0; {$endif} end; + procedure SetTextCodePage(var T: Text; CodePage: TSystemCodePage); begin -{$ifdef FPC_HAS_CPSTRING} +{$if defined(FPC_HAS_CPSTRING) and defined(FPC_HAS_FEATURE_ANSISTRINGS)} TextRec(T).CodePage:=TranslatePlaceholderCP(CodePage); {$endif} end; @@ -631,7 +642,15 @@ end; Procedure fpc_textinit_iso(var t : Text;nr : DWord);compilerproc; begin +{$ifdef FPC_HAS_FEATURE_COMMANDARGS} assign(t,paramstr(nr)); +{$else FPC_HAS_FEATURE_COMMANDARGS} + { primitive workaround for targets supporting no command line arguments, + invent some file name, this will be fixed later on anways because + the current way of handling iso program parameters is apparently + wrong } + assign(t,chr((nr mod 16)+65)); +{$endif FPC_HAS_FEATURE_COMMANDARGS} reset(t); end; @@ -2450,9 +2469,9 @@ begin t.mode:=fmOutput; t.OpenFunc:=nil; t.CloseFunc:=nil; - {$ifdef FPC_HAS_CPSTRING} +{$if defined(FPC_HAS_CPSTRING) and defined(FPC_HAS_FEATURE_ANSISTRINGS)} t.CodePage:=TranslatePlaceholderCP(cp); - {$endif} +{$endif} end; @@ -2561,7 +2580,7 @@ begin t.mode:=fmInput; t.OpenFunc:=nil; t.CloseFunc:=nil; - {$ifdef FPC_HAS_CPSTRING} +{$if defined(FPC_HAS_CPSTRING) and defined(FPC_HAS_FEATURE_ANSISTRINGS)} t.CodePage:=TranslatePlaceholderCP(cp); {$endif} PSizeInt(@t.userdata[BytesReadIndex])^:=0; diff --git a/rtl/inc/tinyheap.inc b/rtl/inc/tinyheap.inc index 38fa5421b2..155417b67c 100644 --- a/rtl/inc/tinyheap.inc +++ b/rtl/inc/tinyheap.inc @@ -13,74 +13,149 @@ **********************************************************************} - const - TinyHeapMinBlock = 4*sizeof(pointer); +{ The heap, implemented here is TP7-compatible in the i8086 far data memory + models. It's basically a linked list of free blocks, which are kept ordered by + start address. The FreeList variable points to the start of the list. Each + free block, except the last one, contains a TTinyHeapBlock structure, which + holds the block size and a pointer to the next free block. The HeapPtr + variable points to the last free block, indicating the end of the list. The + last block is special in that it doesn't contain a TTinyHeapBlock structure. + Instead its size is determined by the pointer difference (HeapEnd-HeapPtr). + It *can* become zero sized, when all the memory inside of it is allocated, in + which case, HeapPtr will become equal to HeapEnd. } + +{$ifdef FPC_TINYHEAP_HUGE} + {$HugePointerArithmeticNormalization On} + {$HugePointerComparisonNormalization On} +{$endif FPC_TINYHEAP_HUGE} type + { TTinyHeapMemBlockSize holds the size of an *allocated* memory block, + and is written at position: + memblockstart-sizeof(TTinyHeapMemBlockSize) } + PTinyHeapMemBlockSize = ^TTinyHeapMemBlockSize; {$ifdef FPC_TINYHEAP_HUGE}huge;{$endif} + TTinyHeapMemBlockSize = PtrUInt; + + { TTinyHeapFreeBlockSize holds the size of a *free* memory block, as a + part of the TTinyHeapBlock structure } +{$ifdef FPC_TINYHEAP_HUGE} + TTinyHeapFreeBlockSize = record + OfsSize: Word; + SegSize: Word; + end; +{$else FPC_TINYHEAP_HUGE} + TTinyHeapFreeBlockSize = PtrUInt; +{$endif FPC_TINYHEAP_HUGE} + + TTinyHeapPointerArithmeticType = ^Byte; {$ifdef FPC_TINYHEAP_HUGE}huge;{$endif} + PTinyHeapBlock = ^TTinyHeapBlock; TTinyHeapBlock = record - Size: ptruint; Next: PTinyHeapBlock; - EndAddr: pointer; + Size: TTinyHeapFreeBlockSize; end; - var - TinyHeapBlocks: PTinyHeapBlock = nil; + const + TinyHeapMinBlock = sizeof(TTinyHeapBlock); - procedure InternalTinyFreeMem(Addr: Pointer; Size: ptruint); forward; + TinyHeapAllocGranularity = sizeof(TTinyHeapBlock); - function FindSize(p: pointer): ptruint; + function EncodeTinyHeapFreeBlockSize(Size: PtrUInt): TTinyHeapFreeBlockSize; inline; begin - FindSize := PPtrUInt(p)[-1]; +{$ifdef FPC_TINYHEAP_HUGE} + EncodeTinyHeapFreeBlockSize.OfsSize := Size and 15; + EncodeTinyHeapFreeBlockSize.SegSize := Size shr 4; +{$else FPC_TINYHEAP_HUGE} + EncodeTinyHeapFreeBlockSize := Size; +{$endif FPC_TINYHEAP_HUGE} + end; + + function DecodeTinyHeapFreeBlockSize(Size: TTinyHeapFreeBlockSize): PtrUInt; inline; + begin +{$ifdef FPC_TINYHEAP_HUGE} + DecodeTinyHeapFreeBlockSize := (PtrUInt(Size.SegSize) shl 4) + Size.OfsSize; +{$else FPC_TINYHEAP_HUGE} + DecodeTinyHeapFreeBlockSize := Size; +{$endif FPC_TINYHEAP_HUGE} + end; + + procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt); forward; + + function FindSize(p: pointer): TTinyHeapMemBlockSize; + begin + FindSize := PTinyHeapMemBlockSize(p)[-1]; end; function SysTinyGetMem(Size: ptruint): pointer; var - p, prev: PTinyHeapBlock; + p, prev, p2: PTinyHeapBlock; AllocSize, RestSize: ptruint; begin {$ifdef DEBUG_TINY_HEAP} Write('SysTinyGetMem(', Size, ')='); {$endif DEBUG_TINY_HEAP} - AllocSize := align(size+sizeof(ptruint), sizeof(pointer)); + AllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity); - p := TinyHeapBlocks; + p := FreeList; prev := nil; - while assigned(p) and (p^.Size < AllocSize) do + while (p<>HeapPtr) and (DecodeTinyHeapFreeBlockSize(p^.Size) < AllocSize) do begin prev := p; p := p^.Next; end; - if assigned(p) then + if p<>HeapPtr then begin - result := @pptruint(p)[1]; + result := @PTinyHeapMemBlockSize(p)[1]; - if p^.Size-AllocSize >= TinyHeapMinBlock then - RestSize := p^.Size-AllocSize + if DecodeTinyHeapFreeBlockSize(p^.Size)-AllocSize >= TinyHeapMinBlock then + RestSize := DecodeTinyHeapFreeBlockSize(p^.Size)-AllocSize else begin - AllocSize := p^.Size; + AllocSize := DecodeTinyHeapFreeBlockSize(p^.Size); RestSize := 0; end; - if prev = nil then - TinyHeapBlocks := p^.Next + if RestSize > 0 then + begin + p2 := pointer(TTinyHeapPointerArithmeticType(p)+AllocSize); + p2^.Next := p^.Next; + p2^.Size := EncodeTinyHeapFreeBlockSize(RestSize); + if prev = nil then + FreeList := p2 + else + prev^.next := p2; + end else - prev^.next := p^.next; - - pptruint(p)^ := size; + begin + if prev = nil then + FreeList := p^.Next + else + prev^.next := p^.next; + end; - if RestSize > 0 then - InternalTinyFreeMem(pointer(ptruint(p)+AllocSize), RestSize); + PTinyHeapMemBlockSize(p)^ := size; end else - if ReturnNilIfGrowHeapFails then - Result := nil - else - HandleError(203); + begin + { p=HeapPtr } + if PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))<AllocSize then + if ReturnNilIfGrowHeapFails then + Result := nil + else + HandleError(203); + + result := @PTinyHeapMemBlockSize(HeapPtr)[1]; + PTinyHeapMemBlockSize(HeapPtr)^ := size; + + HeapPtr := pointer(TTinyHeapPointerArithmeticType(HeapPtr)+AllocSize); + if prev = nil then + FreeList := HeapPtr + else + prev^.next := HeapPtr; + end; {$ifdef DEBUG_TINY_HEAP} - Writeln(ptruint(Result)); + Writeln(HexStr(Result)); {$endif DEBUG_TINY_HEAP} end; @@ -95,80 +170,52 @@ begin mem := GetMem(Size+Alignment-1); memp := align(ptruint(mem), Alignment); - InternalTinyFreeMem(mem, ptruint(memp)-ptruint(mem)); + InternalTinyFreeMem(mem, TTinyHeapPointerArithmeticType(memp)-TTinyHeapPointerArithmeticType(mem)); result := pointer(memp); end; end; - procedure InternalTinyFreeMem(Addr: Pointer; Size: ptruint); - var - b, p, prev: PTinyHeapBlock; - concatenated: boolean; + procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt); + var + p, prev: PTinyHeapBlock; begin - repeat - concatenated := false; - b := addr; + p := FreeList; + prev := nil; - b^.Next := TinyHeapBlocks; - b^.Size := Size; - b^.EndAddr := pointer(ptruint(addr)+size); + while (p<>HeapPtr) and (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(Addr)) do + begin + prev := p; + p := p^.Next; + end; - if TinyHeapBlocks = nil then - TinyHeapBlocks := b + { join with previous block? } + if assigned(prev) and ((TTinyHeapPointerArithmeticType(prev)+DecodeTinyHeapFreeBlockSize(prev^.Size)) = TTinyHeapPointerArithmeticType(Addr)) then + begin + Addr:=prev; + Size:=DecodeTinyHeapFreeBlockSize(prev^.size)+Size; + end + else + if assigned(prev) then + prev^.Next := Addr else - begin - p := TinyHeapBlocks; - prev := nil; - - while assigned(p) do - begin - if p^.EndAddr = addr then - begin - addr:=p; - size:=p^.size+size; - if prev = nil then - TinyHeapBlocks:=p^.next - else - prev^.next:=p^.next; - concatenated:=true; - break; - end - else if p = b^.EndAddr then - begin - size:=p^.size+size; - if prev = nil then - TinyHeapBlocks:=p^.next - else - prev^.next:=p^.next; - concatenated:=true; - break; - end; - - prev := p; - p := p^.next; - end; - - if not concatenated then - begin - p := TinyHeapBlocks; - prev := nil; - - while assigned(p) and (p^.Size < size) do - begin - prev := p; - p := p^.Next; - end; - - if assigned(prev) then - begin - b^.Next := p; - prev^.Next := b; - end - else - TinyHeapBlocks := b; - end; - end; - until not concatenated; + FreeList := Addr; + + { join with next block? } + if TTinyHeapPointerArithmeticType(p)=(TTinyHeapPointerArithmeticType(Addr)+Size) then + begin + if p=HeapPtr then + HeapPtr:=Addr + else + begin + PTinyHeapBlock(Addr)^.Next:=p^.Next; + PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size+DecodeTinyHeapFreeBlockSize(p^.Size)); + end; + end + else + begin + PTinyHeapBlock(Addr)^.Next:=p; + PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size); + end; end; function SysTinyFreeMem(Addr: Pointer): ptruint; @@ -176,16 +223,19 @@ sz: ptruint; begin {$ifdef DEBUG_TINY_HEAP} - Writeln('SysTinyFreeMem(', ptruint(Addr), ')'); + Writeln('SysTinyFreeMem(', HexStr(Addr), ')'); {$endif DEBUG_TINY_HEAP} if addr=nil then begin result:=0; exit; end; - sz := Align(FindSize(addr)+SizeOf(ptruint), sizeof(pointer)); + if (TTinyHeapPointerArithmeticType(addr) < TTinyHeapPointerArithmeticType(HeapOrg)) or + (TTinyHeapPointerArithmeticType(addr) >= TTinyHeapPointerArithmeticType(HeapPtr)) then + HandleError(204); + sz := Align(FindSize(addr)+SizeOf(TTinyHeapMemBlockSize), TinyHeapAllocGranularity); - InternalTinyFreeMem(@pptruint(addr)[-1], sz); + InternalTinyFreeMem(@PTinyHeapMemBlockSize(addr)[-1], sz); result := sz; end; @@ -209,46 +259,300 @@ function SysTinyReAllocMem(var p: pointer; size: ptruint):pointer; var - sz: ptruint; + oldsize, OldAllocSize, NewAllocSize: ptruint; + after_block, before_block, before_before_block: PTinyHeapBlock; + after_block_size, before_block_size: PtrUInt; + new_after_block: PTinyHeapBlock; begin {$ifdef DEBUG_TINY_HEAP} - Write('SysTinyReAllocMem(', ptruint(p), ',', size, ')='); + Write('SysTinyReAllocMem(', HexStr(p), ',', size, ')='); {$endif DEBUG_TINY_HEAP} if size=0 then - result := nil + begin + SysTinyFreeMem(p); + result := nil; + p := nil; + end + else if p=nil then + begin + result := AllocMem(size); + p := result; + end else - result := AllocMem(size); - if result <> nil then begin - if p <> nil then + if (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(HeapOrg)) or + (TTinyHeapPointerArithmeticType(p) >= TTinyHeapPointerArithmeticType(HeapPtr)) then + HandleError(204); + oldsize := FindSize(p); + OldAllocSize := align(oldsize+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity); + NewAllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity); + if OldAllocSize = NewAllocSize then + begin + { old and new size are the same after alignment, so the memory block is already allocated } + { we just need to update the size } + PTinyHeapMemBlockSize(p)[-1] := size; + if size > oldsize then + FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0); + end + else if OldAllocSize > NewAllocSize then begin - sz := FindSize(p); - if sz > size then - sz := size; - move(pbyte(p)^, pbyte(result)^, sz); + { we're decreasing the memory block size, so we can just free the remaining memory at the end } + PTinyHeapMemBlockSize(p)[-1] := size; + InternalTinyFreeMem(Pointer(TTinyHeapPointerArithmeticType(p)+(NewAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))), OldAllocSize-NewAllocSize); + end + else + begin + { we're increasing the memory block size. First, find if there are free memory blocks immediately + before and after our memory block. } + after_block := FreeList; + before_block := nil; + before_before_block := nil; + while (after_block<>HeapPtr) and (TTinyHeapPointerArithmeticType(after_block) < TTinyHeapPointerArithmeticType(p)) do + begin + before_before_block := before_block; + before_block := after_block; + after_block := after_block^.Next; + end; + { is after_block immediately after our block? } + if after_block=Pointer(TTinyHeapPointerArithmeticType(p)+(OldAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))) then + begin + if after_block = HeapPtr then + after_block_size := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr)) + else + after_block_size := DecodeTinyHeapFreeBlockSize(after_block^.size); + end + else + after_block_size := 0; + { is there enough room after the block? } + if (OldAllocSize+after_block_size)>=NewAllocSize then + begin + if after_block = HeapPtr then + begin + HeapPtr:=Pointer(TTinyHeapPointerArithmeticType(HeapPtr)+(NewAllocSize-OldAllocSize)); + if assigned(before_block) then + before_block^.Next := HeapPtr + else + FreeList := HeapPtr; + end + else + begin + if (NewAllocSize-OldAllocSize)=after_block_size then + begin + if assigned(before_block) then + before_block^.Next := after_block^.Next + else + FreeList := after_block^.Next; + end + else + begin + new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(after_block)+(NewAllocSize-OldAllocSize)); + new_after_block^.Next:=after_block^.Next; + new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(after_block_size-(NewAllocSize-OldAllocSize)); + if assigned(before_block) then + before_block^.Next := new_after_block + else + FreeList := new_after_block; + end; + end; + PTinyHeapMemBlockSize(p)[-1] := size; + FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0); + end + else + begin + { is before_block immediately before our block? } + if assigned(before_block) and (Pointer(TTinyHeapPointerArithmeticType(before_block)+DecodeTinyHeapFreeBlockSize(before_block^.Size))=Pointer(TTinyHeapPointerArithmeticType(p)-SizeOf(TTinyHeapMemBlockSize))) then + before_block_size := DecodeTinyHeapFreeBlockSize(before_block^.Size) + else + before_block_size := 0; + + { if there's enough space, we can slide our current block back and reclaim before_block } + if (before_block_size<NewAllocSize) and ((before_block_size+OldAllocSize+after_block_size)>=NewAllocSize) and + { todo: implement this also for after_block_size>0 } + (after_block_size>0) then + begin + if (before_block_size+OldAllocSize+after_block_size)=NewAllocSize then + begin + if after_block=HeapPtr then + begin + HeapPtr := HeapEnd; + if assigned(before_before_block) then + before_before_block^.Next := HeapPtr + else + FreeList := HeapPtr; + end + else + if assigned(before_before_block) then + before_before_block^.Next := after_block^.Next + else + FreeList := after_block^.Next; + end; + Result := Pointer(TTinyHeapPointerArithmeticType(before_block)+SizeOf(TTinyHeapMemBlockSize)); + Move(p^, Result^, oldsize); + PTinyHeapMemBlockSize(before_block)^ := size; + if (before_block_size+OldAllocSize+after_block_size)>NewAllocSize then + begin + new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(before_block)+NewAllocSize); + new_after_block^.Next:=after_block^.Next; + new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(before_block_size+after_block_size-(NewAllocSize-OldAllocSize)); + if assigned(before_before_block) then + before_before_block^.Next := new_after_block + else + FreeList := new_after_block; + end; + FillChar((TTinyHeapPointerArithmeticType(Result)+oldsize)^, size-oldsize, 0); + p := Result; + end + else + begin + result := AllocMem(size); + if result <> nil then + begin + if oldsize > size then + oldsize := size; + move(pbyte(p)^, pbyte(result)^, oldsize); + end; + SysTinyFreeMem(p); + p := result; + end; + end; end; end; - SysTinyFreeMem(p); - p := result; {$ifdef DEBUG_TINY_HEAP} - Writeln(ptruint(result)); + Writeln(HexStr(result)); +{$endif DEBUG_TINY_HEAP} + end; + + function MemAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif}; + var + p: PTinyHeapBlock; + begin + MemAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr)); + if MemAvail > 0 then + Dec(MemAvail, SizeOf(TTinyHeapMemBlockSize)); + + p := FreeList; + while p <> HeapPtr do + begin + Inc(MemAvail, DecodeTinyHeapFreeBlockSize(p^.Size)-SizeOf(TTinyHeapMemBlockSize)); + p := p^.Next; + end; + end; + + function MaxAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif}; + var + p: PTinyHeapBlock; + begin + MaxAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr)); + + p := FreeList; + while p <> HeapPtr do + begin + if DecodeTinyHeapFreeBlockSize(p^.Size) > MaxAvail then + MaxAvail := DecodeTinyHeapFreeBlockSize(p^.Size); + p := p^.Next; + end; + + if MaxAvail > 0 then + Dec(MaxAvail, SizeOf(TTinyHeapMemBlockSize)); + end; + + procedure Mark(var p: Pointer); + begin + p := HeapPtr; + end; + + procedure Release(var p: Pointer); + begin + HeapPtr := p; + FreeList := p; + end; + + procedure InternalTinyAlign(var AAddress: Pointer; ASize: PtrUInt); + var + alignment_inc: smallint; + begin + alignment_inc := TTinyHeapPointerArithmeticType(align(AAddress,TinyHeapAllocGranularity))-TTinyHeapPointerArithmeticType(AAddress); + Inc(AAddress,alignment_inc); + Dec(ASize,alignment_inc); + Dec(ASize,ASize mod TinyHeapAllocGranularity); + end; + + { Strongly simplified version of RegisterTinyHeapBlock, which can be used when + the heap is only a single contiguous memory block. If you want to add + multiple blocks to the heap, you should use RegisterTinyHeapBlock instead. } + procedure RegisterTinyHeapBlock_Simple(AAddress: Pointer; ASize: PtrUInt); + begin +{$ifdef DEBUG_TINY_HEAP} + Writeln('RegisterTinyHeapBlock_Simple(', HexStr(AAddress), ',', ASize, ')'); +{$endif DEBUG_TINY_HEAP} + InternalTinyAlign(AAddress, ASize); + HeapOrg:=AAddress; + HeapPtr:=AAddress; + FreeList:=AAddress; + HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize); + end; + + { Strongly simplified version of RegisterTinyHeapBlock, which can be used when + the heap is only a single contiguous memory block and the address and size + are already aligned on a TinyHeapAllocGranularity boundary. } + procedure RegisterTinyHeapBlock_Simple_Prealigned(AAddress: Pointer; ASize: PtrUInt); + begin +{$ifdef DEBUG_TINY_HEAP} + Writeln('RegisterTinyHeapBlock_Simple_Prealigned(', HexStr(AAddress), ',', ASize, ')'); {$endif DEBUG_TINY_HEAP} + HeapOrg:=AAddress; + HeapPtr:=AAddress; + FreeList:=AAddress; + HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize); end; procedure RegisterTinyHeapBlock(AAddress: pointer; ASize: ptruint); + var + alignment_inc: smallint; + p: PTinyHeapBlock; begin {$ifdef DEBUG_TINY_HEAP} - Writeln('RegisterTinyHeapBlock(', ptruint(AAddress), ',', ASize, ')'); + Writeln('RegisterTinyHeapBlock(', HexStr(AAddress), ',', ASize, ')'); {$endif DEBUG_TINY_HEAP} - if (ptruint(AAddress) and 1) <> 0 then + InternalTinyAlign(AAddress, ASize); + if HeapOrg=nil then + begin + HeapOrg:=AAddress; + HeapPtr:=AAddress; + FreeList:=AAddress; + HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize); + end + else begin - Inc(AAddress); - Dec(ASize); + if (TTinyHeapPointerArithmeticType(HeapOrg) > TTinyHeapPointerArithmeticType(AAddress)) then + HeapOrg:=AAddress; + if TTinyHeapPointerArithmeticType(AAddress) > TTinyHeapPointerArithmeticType(HeapEnd) then + begin + if TTinyHeapPointerArithmeticType(HeapPtr) = TTinyHeapPointerArithmeticType(HeapEnd) then + begin + if FreeList=HeapPtr then + FreeList:=AAddress + else + begin + p:=FreeList; + while p^.Next<>HeapPtr do + p:=p^.Next; + PTinyHeapBlock(HeapPtr)^.Next:=AAddress; + end; + end + else + begin + PTinyHeapBlock(HeapPtr)^.Size:=EncodeTinyHeapFreeBlockSize(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr)); + PTinyHeapBlock(HeapPtr)^.Next:=AAddress; + end; + HeapPtr:=AAddress; + HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize); + end + else if TTinyHeapPointerArithmeticType(AAddress) = TTinyHeapPointerArithmeticType(HeapEnd) then + HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize) + else + InternalTinyFreeMem(AAddress, ASize); end; - if (ASize and 1) <> 0 then - Dec(ASize); - pptruint(AAddress)^ := ASize - SizeOf(ptruint); - FreeMem(pptruint(AAddress) + 1, ASize - SizeOf(ptruint)); end; const diff --git a/rtl/inc/tnyheaph.inc b/rtl/inc/tnyheaph.inc new file mode 100644 index 0000000000..a7f1a37f8a --- /dev/null +++ b/rtl/inc/tnyheaph.inc @@ -0,0 +1,32 @@ +{ + This file is part of the Free Pascal run time library. + Copyright (c) 2014 by the Free Pascal development team. + + Tiny heap manager for the i8086 near heap, embedded targets, etc. + + 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. + + **********************************************************************} + +{$ifdef cpui8086} + {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)} + {$define FPC_TINYHEAP_HUGE} + {$endif} +{$endif cpui8086} + + var + { these vars are TP7-compatible } + HeapOrg: Pointer = nil; { start of heap } + HeapEnd: Pointer = nil; { end of heap } + FreeList: Pointer = nil; { pointer to the first free block } + HeapPtr: Pointer = nil; { pointer to the last free block } + + function MemAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif}; + function MaxAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif}; + procedure Mark(var p: Pointer); + procedure Release(var p: Pointer); diff --git a/rtl/inc/ustringh.inc b/rtl/inc/ustringh.inc index 5fdf8a4380..c856cd0078 100644 --- a/rtl/inc/ustringh.inc +++ b/rtl/inc/ustringh.inc @@ -30,8 +30,8 @@ Function LowerCase(c:UnicodeChar):UnicodeChar; Procedure Insert (Const Source : UnicodeString; Var S : UnicodeString; Index : SizeInt); Procedure Delete (Var S : UnicodeString; Index,Size: SizeInt); -Procedure SetString (Out S : UnicodeString; Buf : PUnicodeChar; Len : SizeInt); -Procedure SetString (Out S : UnicodeString; Buf : PChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_unicodestr_pwidechar{$else}SetString{$endif}(Out S : UnicodeString; Buf : PUnicodeChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_unicodestr_pansichar{$else}SetString{$endif}(Out S : UnicodeString; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} function WideCharToString(S : PWideChar) : UnicodeString; function StringToWideChar(const Src : RawByteString;Dest : PWideChar;DestSize : SizeInt) : PWideChar; diff --git a/rtl/inc/ustrings.inc b/rtl/inc/ustrings.inc index c5c52b2f4d..09ea7dd0df 100644 --- a/rtl/inc/ustrings.inc +++ b/rtl/inc/ustrings.inc @@ -817,7 +817,7 @@ begin len := length(src); { make sure we don't dereference src if it can be nil (JM) } if len > 0 then - widestringmanager.ansi2widemoveproc(pchar(@src[1]),StringCodePage(src),temp,len); + widestringmanager.ansi2widemoveproc(pchar(@src[1]),TranslatePlaceholderCP(StringCodePage(src)),temp,len); len := length(temp); if len > length(res) then len := length(res); @@ -1351,7 +1351,7 @@ end; {$ifndef FPC_HAS_SETSTRING_UNICODESTR_PUNICODECHAR} {$define FPC_HAS_SETSTRING_UNICODESTR_PUNICODECHAR} -Procedure SetString (Out S : UnicodeString; Buf : PUnicodeChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_unicodestr_pwidechar{$else}SetString{$endif}(Out S : UnicodeString; Buf : PUnicodeChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} begin SetLength(S,Len); If (Buf<>Nil) and (Len>0) then @@ -1362,7 +1362,7 @@ end; {$ifndef FPC_HAS_SETSTRING_UNICODESTR_PCHAR} {$define FPC_HAS_SETSTRING_UNICODESTR_PCHAR} -Procedure SetString (Out S : UnicodeString; Buf : PChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_unicodestr_pansichar{$else}SetString{$endif}(Out S : UnicodeString; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} begin If (Buf<>Nil) and (Len>0) then widestringmanager.Ansi2UnicodeMoveProc(Buf,DefaultSystemCodePage,S,Len) @@ -2286,19 +2286,22 @@ function StringCodePage(const S: UnicodeString): TSystemCodePage; overload; {$warnings off} -function GenericUnicodeCase(const s : UnicodeString) : UnicodeString; +function StubUnicodeCase(const s : UnicodeString) : UnicodeString; begin unimplementedunicodestring; end; - -function CompareUnicodeString(const s1, s2 : UnicodeString) : PtrInt; +function StubCompareUnicodeString(const s1, s2 : UnicodeString) : PtrInt; begin unimplementedunicodestring; end; +function StubWideCase(const s: WideString): WideString; + begin + unimplementedunicodestring; + end; -function CompareTextUnicodeString(const s1, s2 : UnicodeString): PtrInt; +function StubCompareWideString(const s1, s2 : WideString) : PtrInt; begin unimplementedunicodestring; end; @@ -2307,24 +2310,23 @@ function CompareTextUnicodeString(const s1, s2 : UnicodeString): PtrInt; procedure initunicodestringmanager; begin {$ifndef HAS_WIDESTRINGMANAGER} - widestringmanager.Unicode2AnsiMoveProc:=@DefaultUnicode2AnsiMove; - widestringmanager.Ansi2UnicodeMoveProc:=@DefaultAnsi2UnicodeMove; - widestringmanager.UpperUnicodeStringProc:=@GenericUnicodeCase; - widestringmanager.LowerUnicodeStringProc:=@GenericUnicodeCase; -{$endif HAS_WIDESTRINGMANAGER} - widestringmanager.CompareUnicodeStringProc:=@CompareUnicodeString; - widestringmanager.CompareTextUnicodeStringProc:=@CompareTextUnicodeString; - {$ifdef FPC_WIDESTRING_EQUAL_UNICODESTRING} -{$ifndef HAS_WIDESTRINGMANAGER} - widestringmanager.Wide2AnsiMoveProc:=@defaultUnicode2AnsiMove; widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2UnicodeMove; - widestringmanager.UpperWideStringProc:=@GenericUnicodeCase; - widestringmanager.LowerWideStringProc:=@GenericUnicodeCase; -{$endif HAS_WIDESTRINGMANAGER} - widestringmanager.CompareWideStringProc:=@CompareUnicodeString; - widestringmanager.CompareTextWideStringProc:=@CompareTextUnicodeString; +{$else FPC_WIDESTRING_EQUAL_UNICODESTRING} + widestringmanager.Ansi2WideMoveProc:=@DefaultAnsi2WideMove; {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING} + widestringmanager.Wide2AnsiMoveProc:=@DefaultUnicode2AnsiMove; + widestringmanager.UpperWideStringProc:=@StubWideCase; + widestringmanager.LowerWideStringProc:=@StubWideCase; + widestringmanager.Unicode2AnsiMoveProc:=@DefaultUnicode2AnsiMove; + widestringmanager.Ansi2UnicodeMoveProc:=@DefaultAnsi2UnicodeMove; + widestringmanager.UpperUnicodeStringProc:=@StubUnicodeCase; + widestringmanager.LowerUnicodeStringProc:=@StubUnicodeCase; +{$endif HAS_WIDESTRINGMANAGER} + widestringmanager.CompareWideStringProc:=@StubCompareWideString; + widestringmanager.CompareTextWideStringProc:=@StubCompareWideString; + widestringmanager.CompareUnicodeStringProc:=@StubCompareUnicodeString; + widestringmanager.CompareTextUnicodeStringProc:=@StubCompareUnicodeString; widestringmanager.CharLengthPCharProc:=@DefaultCharLengthPChar; widestringmanager.CodePointLengthProc:=@DefaultCodePointLength; widestringmanager.GetStandardCodePageProc:=@DefaultGetStandardCodePage; diff --git a/rtl/inc/variant.inc b/rtl/inc/variant.inc index 440fe80bc5..d39eaf1437 100644 --- a/rtl/inc/variant.inc +++ b/rtl/inc/variant.inc @@ -142,7 +142,7 @@ function fpc_idispatch_to_variant(const i : idispatch) : variant;compilerproc; end; -procedure fpc_dispinvoke_variant(dest : pvardata;const source : tvardata; +procedure fpc_dispinvoke_variant(dest : pvardata;var source : tvardata; calldesc : pcalldesc;params : pointer); compilerproc; begin variantmanager.dispinvoke(dest,source,calldesc,params); @@ -1093,9 +1093,6 @@ begin VariantManager:=VarMgr; end; -procedure initvariantmanager; - begin - end; Function Pos (c : Char; Const v : Variant) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif} begin diff --git a/rtl/inc/varianth.inc b/rtl/inc/varianth.inc index 4eda494522..336a6ee149 100644 --- a/rtl/inc/varianth.inc +++ b/rtl/inc/varianth.inc @@ -204,7 +204,7 @@ type varcast : procedure(var dest : variant;const source : variant;vartype : longint); varcastole : procedure(var dest : variant; const source : variant;vartype : longint); - dispinvoke: procedure(dest : pvardata;const source : tvardata; + dispinvoke: procedure(dest : pvardata;var source : tvardata; calldesc : pcalldesc;params : pointer);cdecl; vararrayredim : procedure(var a : variant;highbound : SizeInt); diff --git a/rtl/inc/wstringh.inc b/rtl/inc/wstringh.inc index 57ca32a987..fde3bf756a 100644 --- a/rtl/inc/wstringh.inc +++ b/rtl/inc/wstringh.inc @@ -28,8 +28,8 @@ Function UpCase(const s : WideString) : WideString; Procedure Insert (Const Source : WideString; Var S : WideString; Index : SizeInt); Procedure Delete (Var S : WideString; Index,Size: SizeInt); -Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt); -Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_widestr_pwidechar{$else}SetString{$endif}(Out S : WideString; Buf : PWideChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_widestr_pansichar{$else}SetString{$endif}(Out S : WideString; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} procedure DefaultAnsi2WideMove(source:pchar;cp : TSystemCodePage;var dest:widestring;len:SizeInt); diff --git a/rtl/inc/wstrings.inc b/rtl/inc/wstrings.inc index 403b8c9552..1a366db4cd 100644 --- a/rtl/inc/wstrings.inc +++ b/rtl/inc/wstrings.inc @@ -723,7 +723,7 @@ begin end; -Procedure SetString (Out S : WideString; Buf : PWideChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_widestr_pwidechar{$else}SetString{$endif}(Out S : WideString; Buf : PWideChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} begin SetLength(S,Len); If (Buf<>Nil) and (Len>0) then @@ -731,7 +731,7 @@ begin end; -Procedure SetString (Out S : WideString; Buf : PChar; Len : SizeInt); +Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_widestr_pansichar{$else}SetString{$endif}(Out S : WideString; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING} begin If (Buf<>Nil) and (Len>0) then widestringmanager.Ansi2WideMoveProc(Buf,DefaultSystemCodePage,S,Len) @@ -942,38 +942,4 @@ function UTF8Encode(const s : WideString) : RawByteString; end; end; -procedure unimplementedunicodestring; forward; -{$warnings off} -function GenericWideCase(const s : WideString) : WideString; - begin - unimplementedunicodestring; - end; - - -function CompareWideString(const s1, s2 : WideString) : PtrInt; - begin - unimplementedunicodestring; - end; - - -function CompareTextWideString(const s1, s2 : WideString): PtrInt; - begin - unimplementedunicodestring; - end; - -{$warnings on} - - -procedure initwidestringmanager; - begin - fillchar(widestringmanager,sizeof(widestringmanager),0); -{$ifndef HAS_WIDESTRINGMANAGER} - widestringmanager.Wide2AnsiMoveProc:=@DefaultUnicode2AnsiMove; - widestringmanager.Ansi2WideMoveProc:=@DefaultAnsi2WideMove; - widestringmanager.UpperWideStringProc:=@GenericWideCase; - widestringmanager.LowerWideStringProc:=@GenericWideCase; -{$endif HAS_WIDESTRINGMANAGER} - widestringmanager.CompareWideStringProc:=@CompareWideString; - widestringmanager.CompareTextWideStringProc:=@CompareTextWideString; - end; |