From f5209890646c718a5698ab0e2a2f1de60d988f0f Mon Sep 17 00:00:00 2001 From: tom_at_work Date: Sun, 24 Oct 2010 21:35:16 +0000 Subject: [PATCH] Fixed ordinal to string conversion for enumerations * clean up actual ordinal to string conversion in system unit: try to use records instead of hardcoded offsets * before emitting the enum ordinal to string rtti information for enums, they need to be sorted according to their values first. Otherwise rtti information for sparse enums is broken. git-svn-id: trunk@16218 - --- compiler/ncgrtti.pas | 36 ++++++++++++-- rtl/inc/sstrings.inc | 111 +++++++++++++++++++++++++++++++------------ 2 files changed, 111 insertions(+), 36 deletions(-) diff --git a/compiler/ncgrtti.pas b/compiler/ncgrtti.pas index 7397e8e1c3..67fe31b385 100644 --- a/compiler/ncgrtti.pas +++ b/compiler/ncgrtti.pas @@ -1080,11 +1080,11 @@ implementation procedure enumdef_rtti_extrasyms(def:Tenumdef); var - t:Tenumsym; - syms:Penumsym; - sym_count,sym_alloc:longint; - offsets:^longint; - h,i,p,o,st:longint; + t:Tenumsym; + syms:Penumsym; + sym_count,sym_alloc:sizeuint; + offsets:^longint; + h,i,p,o,st:longint; begin {Random access needed, put in array.} getmem(syms,64*sizeof(Tenumsym)); @@ -1139,6 +1139,32 @@ implementation end; st:=enumdef_rtti_calcstringtablestart(def); enumdef_rtti_string2ordindex(sym_count,offsets,syms,st); + { Sort the syms by enum value } + if sym_count>=2 then + begin + p:=1; + while 2*p0 do + begin + for h:=p to sym_count-1 do + begin + i:=h; + t:=syms[i]; + o:=offsets[i]; + repeat + if syms[i-p].value<=t.value then + break; + syms[i]:=syms[i-p]; + offsets[i]:=offsets[i-p]; + dec(i,p); + until imaxvalue) then - exit; {Invalid ordinal value for this enum.} + exit; + { make the ordinal index for lookup zero-based } dec(ordinal,minvalue); end; - {Get the address of the string.} - p:=Pshortstring((PPpointer(ord2strindex+sizeof(longint))+ordinal)^); - if p=nil then - exit; {Invalid ordinal value for this enum.} - s:=p^; + res:=Penum_ord_to_string_lookup(enum_o2s)^.lookup_data[ordinal]; + if (not assigned(res)) then + exit; + s:=res^; end else begin - {The compiler did generate a sorted array of (ordvalue,Pstring) tuples.} - sorted_array:=pointer(Pcardinal(ord2strindex)+2); - {Use a binary search to get the string.} + { The compiler did generate a sorted array of (ordvalue,Pstring) tuples } + sorted_data:=Penum_ord_to_string_search(enum_o2s)^.search_data; + { Use a binary search to get the string } l:=0; - h:=(Pcardinal(ord2strindex)+1)^-1; + h:=Penum_ord_to_string_search(enum_o2s)^.num_entries-1; repeat m:=(l+h) div 2; - if ordinal>sorted_array[m].o then + if ordinal>sorted_data[m].value then l:=m+1 - else if ordinalh then - exit; {Ordinal value not found? Kaboom.} + exit; { Ordinal value not found? Exit } until false; - s:=sorted_array[m].s^; + s:=sorted_data[m].name^; end; - {Pad the string with spaces if necessary.} - if len>length(s) then + + { Pad the string with spaces if necessary } + if (len>length(s)) then begin spaces:=len-length(s); for i:=1 to spaces do