%option "-low-nons-nowarn-noass-nodiag"
%include "inc:util.imp"
%include "mouse.inc"

%recordformat fe02 object fm -
  (%half flags,extra,%integer type,offset,%string(255)name)
%recordformat fe02 header fm -
  ({%byte type,version) %or}%half tyver,flags,export,import,%integer codesize,
   %half reset,main, %integer ownsize,stack,%half dlim,chlim,spare1,spare2)
%recordformat mar fm -
  (%record(mar fm)%name next, %record(fe02 header fm)%name header,
   %integer gla,%string(255)filename)
%recordformat par fm -
  (%record(par fm)%name next,
   %record(mar fm)%name modules)
%recordformat fe02 indir fm -
  (%integer address %or -
   %half op1, %integer opd1, %half op2, %integer opd2)
%recordformat dyn fm -
  (%record(fe02 object fm)%name object, %record(par fm)%name program)

@372(a5) %record (par fm)%name topprog
        
%constinteger jmp=16_4EF9,jsr=16_4EB9,pea=16_4879,leaa4=16_49F9,rts=16_4e75

%constinteger extbit=16_4000,procmask=16_3000,
              system=16_1000,external=16_2000,dynamic=16_3000

%routine mode(%integer f)
%integer shift=32; shift=0 %if f&extbit#0
  %routine p3(%integer x)
    printsymbol(x>>16&255-shift)
    printsymbol(x>>8&255-shift)
    printsymbol(x&255-shift)
  %end
  f = f&procmask
  p3('dat') %if f=0
  p3('sys') %if f=system
  p3('dyn') %if f=dynamic
  p3('ext') %if f=external
%end

%integerfn codestart(%record(fe02 header fm)%name h)
%integer a
  a = addr(h[1])
  %result = a+h_export+h_import
%end

%record(fe02objectfm)%map nextobject(%record(fe02objectfm)%name o)
  %result == record((addr(o[1])-255+length(o_name)+1)&\1)
%end

%externalroutine explore(%integer n)
%record(parfm)%name par
%record(marfm)%name mar
%record(fe02headerfm)%name hdr
%record(fe02objectfm)%name obj
%record(fe02indirfm)%name ind
%integer p
  par == topprog
  %cycle
    mar == par_modules
    %while mar##nil %cycle
      hdr == mar_header
      printstring("Module "); phex(a5)
      space; phex(addr(par)); space; phex(addr(hdr)); space; phex(mar_gla)
      space; printstring(mar_filename); newline
      obj == record(addr(hdr[1]))
      %if hdr_export#0 %start
        %while obj_flags#0 %cycle
          mode(obj_flags); printstring(" export at ")
          %if obj_flags&procmask=0 %start
            phex(mar_gla+obj_offset)
          %else
            phex(codestart(hdr)+obj_offset)
          %finish
          space; printstring(obj_name); newline
          obj == nextobject(obj)
        %repeat
      %finish
      obj == record(addr(hdr[1])+hdr_export)
      %if hdr_import#0 %start
        %while obj_flags#0 %cycle
          mode(obj_flags); printstring(" import at ")
          p = mar_gla+obj_offset; ind == record(p); phex(p); space
          %if obj_flags&procmask=0 %start
            phex(ind_address)
          %else
            phex4(ind_op1); space; phex(ind_opd1)
            %unless obj_flags&procmask=system %start
              space; phex4(ind_op2); space; phex(ind_opd2)
            %finish
          %finish
          space; printstring(obj_name); newline
          obj == nextobject(obj)
        %repeat
      %finish
      mar == mar_next
    %repeat
    n = n-1; %exitif n<=0
    par == par_next
  %repeatuntil par==nil
%end
