Re: show subscripts in dump - help and ideas requested - solved

new topic     » goto parent     » topic index » view thread      » older message » newer message

Minor cleanup, same output:

constant MAXLINELEN = 77 
-- Of course the first notion is to print things as and when lines get full, however 
--  consider s = repeat(0,20); s[10] = repeat(0,20): if, as I do, you want to see: 
--  s[1..9] = {0,0,0,0,0,0,0,0,0} 
--  s[10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 
--  s[11..20] = {0,0,0,0,0,0,0,0,0,0,0} 
--  (assuming that 20 was enough to break past MAXLINELEN and force the linebreaks) 
--  then while printing (or splitting) s[10] you've got 9 elements in hand, somewhere 
--  higher up the call stack, that you haven't had reason to print yet, and of course  
--  with longer and more deeply nested structures things can get far worse. Instead, 
--  just append things to a "printstack" along with a key to sort everything into the 
--  right order before printing. The routines below chuck around a fair few partial 
--  results, start and current indexes, and return the same in subtly different ways 
--  depending on what just happened, that I would struggle to explain any better than 
--  the source code itself does. 
sequence printstack -- each element contains 3 items: 
                    --  indicii - for sorting, eg {21,1} 
                    --  name    - eg "symtab[21][1..11]" (matches that {21,1}) 
                    --  text    - the formatted value 
procedure addtostack(sequence idii, integer idxr, string name, string text) 
    idii[$] = idxr 
--  if idii={11} then ?9/0 end if 
    printstack = append(printstack,{idii,name,text}) 
end procedure 
function subscr(string prev, string name, integer prst, integer prdx) 
-- Helper routine for setting subscripts, typically for things  
--  that are just about to be chucked onto the printstack. 
-- Note this is not meant to be called for any [1..$] cases. 
    if prst=prdx then 
        name = sprintf("%s[%d]",{name,prst}) 
        name = sprintf("%s[%d..%d]",{name,prst,prdx}) 
        prev = "{"&prev&"}" 
    end if 
    return {prev,name} 
end function 
function cdi(string name, string prev, integer prst, integer prdx, object o, sequence idii) 
-- Clever display of i'th item. Recursive. 
--  name is eg "symtab", but may get "symtab[1]", "symtab[1][1]", etc. 
--  prev is previously collected stuff to output: concatenate to it, or split the line. 
--  prst is a staring index where (a non-empty) prev began. 
--  prdx is the element index of name that we just got passed in o. 
--  idii is a list of (start) indexes, to be used in the final sort. 
-- Returns extended or purged {prst,prev} 
-- ps: not totally sure I got return "1,2,3" vs return "{1,2,3}" precisely right,  
--      but, touch wood, it seems fine in all the cases I have tested so far... 
string this     -- Scratch var: string representation of o or next element of o. 
                -- In the key recursive call below, "this" gets passed to "prev", 
                -- and grows/shrinks from what that returns rather than directly. 
string namedx   -- Scratch var: name with some or other idx tacked on the end. 
integer newprst,                    -- Scratch/innner version of prst. 
        lo,                         -- length(o) shorthand 
        lp,                         -- length(prev) shorthand 
        lt,                         -- length(name)+4+lp+length(this) shorthand 
        wasstacklen = length(printstack)    -- to check if something got dumped 
    if atom(o) then 
        this = sprintf("%.10g", o) 
        if integer(o) then 
            if o>=#20 and o<=#FF then 
                this &= sprintf("'%s'",o) 
            end if 
        elsif not find('.',this) 
          and not find('e',this)        -- eg 1e308 
          and not find('n',this) then   -- (inf/nan) 
            -- Ensure you can tell 5 and 5.000000000001 apart. 
            -- Note that while you can infer from the presence 
            -- of ".0" it is "not integer", in no way does the 
            -- /absence/ mean anything at all about whether a  
            -- variable was declared integer/atom/object/udt. 
            this &= ".0" 
        end if 
    elsif string(o) then 
        this = '"'&o&'"' 
        if length(idii) then 
            namedx = sprintf("%s[%d]",{name,prdx}) 
            namedx = name 
        end if 
        this = "" 
        newprst = 1 
        for i=1 to length(o) do 
            {newprst,this} = cdi(namedx,this,newprst,i,o[i],idii&i) 
        end for 
        if newprst>1 
        or (length(idii) and 
            wasstacklen<length(printstack)) then 
            -- Something just got printed, so empty prev and  
            -- force linebreaks all the way back up the call  
            -- stack (which is done by returning prdx+1) 
            if length(prev) then 
                {prev,namedx} = subscr(prev,name,prst,prdx-1) 
            end if 
            lo = length(o) 
            if newprst<=lo then 
                if prdx!=-1 then 
                    name = sprintf("%s[%d]",{name,prdx}) 
                end if 
                {this,name} = subscr(this,name,newprst,lo) 
            end if 
            return {prdx+1,""} 
        end if 
        this = "{"&this&"}" 
    end if 
    lp = length(prev) 
    lt = length(name)+4+lp+length(this) -- (+4 is for " = " and a ',') 
    if lp=0 then 
        if not string(o)            -- (any splitting already done) 
        or lt<MAXLINELEN then       -- (or no need to split string) 
            return {prst,this} 
        end if 
    elsif lt<MAXLINELEN then 
        -- note that we are clearly returning a partial result here, 
        -- of say "1,2,3" rather than "{1,2,3}". 
        return {prst,prev&','&this} 
        {prev,namedx} = subscr(prev,name,prst,prdx-1) 
    end if 
    if string(o) then 
        -- One that wouldn't fit, so split if needed and 
        -- force linebreaks all the way back up the call  
        -- stack (which is done by returning prdx+1) 
        if prdx!=-1 then 
            name = sprintf("%s[%d]",{name,prdx}) 
        end if 
        newprst = 1 
        idii &= 1 
        lo = length(o) 
        while lo-newprst+length(name)+13>MAXLINELEN do 
            lp = newprst+MAXLINELEN-14-length(name) 
            this = '"'&o[newprst..lp]&'"' 
            namedx = sprintf("%s[%d..%d]",{name,newprst,lp}) 
            newprst = lp+1 
        end while 
        if newprst!=1 then 
            name = sprintf("%s[%d..%d]",{name,newprst,lo}) 
            this = '"'&o[newprst..lo]&'"' 
        end if 
        return {prdx+1,""} 
    end if 
    return {prdx,this} 
end function 
procedure clever_dump(string name, object o) 
-- Display "name = sprint(o)" but with indexes  
-- as needed, together with smart line splitting. 
integer prst 
string s 
    printstack = {} 
    {prst,s} = cdi(name,"",1,-1,o,{}) 
    if length(s) then 
    end if 
    printstack = sort(printstack) 
    for i=1 to length(printstack) do 
        printf(1,"%s = %s\n",printstack[i][2..3]) 
    end for 
end procedure 
constant symtab = {1,0,3,4,0,0,0,8,0,0,0,12,0,0,15, 
                   {"C:\\Program Files (x86)\\Phix\\builtins\\", 
                    "C:\\Program Files (x86)\\Phix\\", 
                    "C:\\Program Files (x86)\\Phix\\demo\\misc\\eubins-mingw32\\"}, 
                   {{3, "someotherfile.exw"}, {3, "somefile.e"}, 
                    {1, "prtnid2.e"}, {1, "psprint.e"}, {1, "pprntf.e"}}, 
                   {-1,8,1,2304,0,253, "P", 0,0,0,32452560, 
sequence t = repeat(0,10) 
    t[5] = repeat('t',200) 
    t = repeat('t',200) 
if getc(0) then end if 
new topic     » goto parent     » topic index » view thread      » older message » newer message


Quick Links

User menu

Not signed in.

Misc Menu