
'--------------------------------------------
function upgradelen(a as sys,b as sys) as sys
'============================================
if (a and 31)<(b and 31) then
  function=(a and &hffffffe0)or(b and 31)
else
  function=a
end if
end function


'-----------------------------------------
sub roundupc(byref v as sys,byval n as sys)
'=========================================
  dim as sys c
  if (v=0)or(n<=1) then exit sub
  c=v mod n
  if c then v+=n-c
end sub

'-----------------------------------------
sub roundup(byref v as sys,byval n as sys)
'=========================================
  dim as sys c
  '
  'IF LARGER THAN 4 BYTES (OR 8 BYTES) THEN ROUND UP TO NEXT
  '
  if n=3 then n=4 '1 2 4 alignment
  '
  if n>cpuw then
    c=-cpuw
    c and= n
    if c<n then n=c+cpuw
  end if
  '
  'ROUND UP TO NEXT ALIGNMENT
  '
  c=-n
  c and= v
  if c<v then v=c+n
end sub


'-----------------------------------------------------------
function arraysize(byref s as string, byref i as sys) as sys
'===========================================================
  '
  dim as sys a,b,v,lb,rb
  dim as string wr
  b=i
  lb=asc(s,i) : if lb=91 then rb=93 else rb=rbr
  v=1
  i+=1 'SKIP FIRST LEFT BRACKET
  wr=mword(s,i) 'supports macros
  if ascn<>rb then ers="Unexpected symbol after array index" : ert=404
  i+=1 : skiplspace(s,i) 'OTHERWISE NEXT DIMENSION
  a=wval(wr) : if a>0 then v*=a
  return v
  '
end function


sub appendsig(wt as string, pt as sys)
'=====================================
  sigs+="#"+wt
  sigd+=chr(pt+48)
end sub


'------------------------------------------------------------
function buildsig(byref s as string,byref k as sys) as string
'============================================================
  '
  dim as sys a,b,dfv,pt=bref,f,j,opf,ta,ct,xcap,m
  dim as string w1,wr,wn,wt
  sigs=""
  sigd=""
  a=k
  b=swd
  do
    wr=tword(s,k)
    if wr="..." then
      if (coco=0)or(coco=8) then coco=1          'POSSIBLE CDECL
      sigd+="."                  : continue do   'ELLIPSIS
    end if
    if wr="byval" then pt=0      : continue do   'BASIC BYVAL
    if wr="byref" then pt=1      : continue do   'BASIC BYREF
    if wr="optional" then opf=17 : continue do   'OPTIONAL PARAMS
    '
    if isc(ascw) then endline(s,k) : continue do 'SKIP COMMENTS
    if (ascw=44)or(ascw=rbr) then                'END OF PARAM STATEMENT
      if xcap=0 then
        if opf then
          sigv+=wn+"=null,"
        else
          sigv+=wn+".=.,"
        end if
      end if
      xcap=0
      if ascw=rbr then exit do 'END OF PARAMS
      continue do
    end if
    '
    'CHECK FOR DEFAULT VALUES
    '
    if ascn=61 then
      k+=1
      sigv+=wr+"="+captsx(s,k)+","
      xcap=1
      dfv=1
      if ct=0 then continue do
    end if
    '
    if wr="as" then f=2 : ct=0   'BASIC TYPE FOLLOWS
    if ascn=97 then
      if wordahead(s,k)="as" then
        k=nwd : f=2 : ct=0       'BASIC TYPE FOLLOWS
        wn=wr
      end if
    end if
    '
    if f=2 then
      wt=tword(s,k) : ta=identype(wt) 'AS TYPE
    end if
    '
    'C STYLE
    '=======
    '
    if f=0 then
      '
      'TYPE RECOGNITION
      '----------------
      '
      k=swd : wr=mword(s,k)
      if wr="optional" then
        opf=17 : continue do
      end if
      a=identype(wr)
      '
      if a then
        pt=0 : ct=1 'identified as C style typing so set indirection to 0
      else
        if len(wt) then
          wn=wr
          wr=wt : a=ta 'default type
          if ct then pt=0 else pt=bref 'default indirection
        end if
      end if
      '
      if a then
        ta=a : f=1 : wt=wr
        do
          if ascw=42 then pt+=1 'COLLECT POINTERS
          if (ascn<>44)and(ascn<>rbr) then
            if ascn=lbr then
              if pt=0 then pt=1 ' void(...)(...)
              capture(s,m,k,0) 'void*(...) IGNORE CASTS & INNER PROTOTYPES
              skiplspace(s,k)
              if ascn=lbr then
                capture(s,m,k,0)
                skiplspace(s,k)
              end if
              exit do
            end if
            '
            wn=tword(s,k)
            '
            'CHECK FOR DEFAULT ASSIGNMENTS
            '
            if ascn=61 then
              sigv+=wn+"=" : k+=1
              sigv+=captsx(s,k)+","
              xcap=1
              dfv=1
            end if
          else
            exit do  'SWALLOW NAMES
          end if
        loop
      end if
      '
    end if
    '
    'COLLECT POINTERS
    '================
    '
    pt+=isptr(s,k)
    '
    '
    'ADD SIG FRAGMENT
    '================
    '
    if f=0 then wr="sys" : wt=wr 'DEFAULT TYPE
    '
    f=0
    '
    if pt=0 then
      if wr="void" then
        if ct then pt=0 else pt=bref
        continue do 'no parameter
      end if
    end if
    if coco=16 then
      pt=0 : wt="sys"
    elseif coco=17 then
      pt=0 : wt="fpu"
    end if
    appendsig(wt,pt+opf)
    if ct then
      pt=0
    else
      pt=bref  'set ptr to the default level
    end if
  loop
  '
  swd=b
  sigs+="@"+sigd
   if dfv=0 then sigv=""
  if len(sigv) then sigv=" (,"+sigv+")"   'DEFAULT VALUES
  return sigs
  '
end function


'================
'ELEMENT ENCODING
'INTERNAL FORMAT:
'================
'
'FIELDS:
'
' 0 TAB
' 1 ELEMENT NAME
' 2 SIZE
' 3 OFFSET
' 4 PROCLIST POSITION
' 5 VARF
'     1 PROPERTY
'     3 PROPERTY BYREF
'     8 CALL
'     9 METHOD
'     10+ INHERITED METHOD WITH OBJECT OFFSET
' 6 CALLING CONVENTION (code + ascii 65)
'     A stdcall
'     B cdecl
'     C ms64
'     I pascal
'     Q cpu
'     R fpu
' 7 VIRTUAL MODALITY
'     A
'     B
'     C
' 8 PROTOTYPE SIGNATURE OR ','
' 9 RETURN TYPE
'10 DEFAULT VALUES?
'     (,A=1,B=32,C=12.5,) etc
'

'-------------------------------------------------------------------------------------------------------------------------------------------
function encodele(byref wm as string, byref k as sys, ty as string, byval n as sys, byval vtl as sys, byval vtp as sys, byref ws as string ) as string
'===========================================================================================================================================
  '
  'PARAMS
  '
  'wm  source string
  'k   source string index
  'ty  type name
  'n   type code
  'vtl virtual pointer flag
  'vtp virtuality code
  '
  '
  ' tt as sys
  ' amphibian frog(100)
  ' tt aa! (as sys) as sys

  dim as sys a,b,m,indi=indt
  dim as string w1,w2,w3,w4,w5
  '
  'DEFAULT ELEMENT
  '---------------
  '
  ws="" 'signature
  '
  '
  'SUBS / FUNCTIONS / METHODS '8' +
  '
  if n=&h11f then
    if vtl>1 then m=9 else m=8 'method / procedure
    w5=" 0       "
  else
    if (n>=htyp)or(indt>0) then m=3 else m=1 'pointer / direct
    w5=" 0 "
  end if
  '
  '
  '
  skiplspace(wm,k) : b=ascn
  '
  'CALLING SIGNATURE / ARRAY SIGNATURE SIG
  '---------------------------------------
  '
  w2=","
  '
  sigv="" 'DEFAULT PARAM VALUES
  'sigu="" 'DEFAULT MEMBER VALUE
  if ascn=lbr then
    k+=1 
    ws=buildsig(wm,k)
    if m<8 then ws=splitsi(ws,w3) 'REMOVE INDIRECTION COMPONENT
    if len(ws) then w2=ws 'SIGNATURE
  else
    if ascn=61 then
      if identype(wordahead(wm,k+1))=0 then 'NOT A UNION =
        k+=1 : capts(wm,k)
      end if
    end if
  end if
  '
  '
  'RETURN SIGNATURE SOG
  '--------------------
  '
  '
  'n = 0x01.. 0xff primitive / 0x11f procedure / 0x200.. higher type
  '
  if n>=htyp then
    w3=str(n) 'higher types (location+htyp)
  elseif len(ty) then
    w3=ty
  else
    w3="," 'error?
  end if
  '
  if indi then
    'return pointers
    if w3="void" then
      w3="sys"
    else
      if m>=8 then w3+=string(indi,"*")
    end if
  end if
  '
  '
  'VARF CALLCONV SIG SOG
  '=====================
  '
  if aml>1 then w4=" ["+str(aml)+"]" 'MEMBER FIXED ARRAY
  '  LISTPOS  VARF       CALLINGCONV  VIRTUAL        SIG   SOG ARRAY DEFAULT VALS
  return w5+str(m)+" "+chr(coco+65)+chr(vtp+65)+" "+w2+" "+w3+w4+sigv
  '
end function


'----------------------------------------------------------
function cloneit(byref wr as string, byval b as sys) as sys
'==========================================================
  '
  'CLONE AN EXISTING ENTITY
  '
  dim as sys i
  dim as string s
  for i=0 to 6
    maco(me,i)=maco(b,i)
  next
  macsi(wr,me,0)
  for i=1 to 3
    s=macso(b,i) : macsi(s,me,i)
  next
  addm() : function=me : addme()
end function

'--------------------------------------------------------------------------------
function callingconv(byref s as string,byref i as sys, byref wr as string) as sys
'================================================================================
dim as sys a
a=dic(callco,wr)
if a=0 then exit function
coco=a and &hff
mid(s,swd)=space(i-swd) 'BLANKOUT
if nisxn then
  wr=tword(s,i)
else
  wr=""
end if
function=0
end function


'--------------------------
function readin() as string
'==========================
dim as sys b
dim as string w1,w2
  '
  w2=string(&h1000,chr(0)) : b=1
  do
    read w1 : if w1="!end!" then exit do
    mid(w2,b)=w1+cr : b+=len(w1)+len(cr)
  loop
  function=left(w2,b-1)
end function




' ##          ##
' ####        ##
' ## ##       ##
' ##  ##      ##
' ##   ##     ##
' ##    ##    ##
' ##     ##   ##
' ##      ##  ##
' ##       ## ##
' ##        ####
' ##          ##


'------------------------------------------
sub enums(byref s as string,byref i as sys)
'==========================================
  dim as sys a,b,c,d,e,k,m
  dim as string wr,wn,w1
  '
  if wordahead(s,i)="bit" then
    k=-3 : i=nwd
  else
    k=-2
  end if
  '
  nextinstruct(s,i)
  wn=tword(s,i) 'NAME PROVIDED?
  '
  if ascw=123 then
    i=swd
    ascn=ascw
    wn="typedefenum"
  end if
  '
  captureb(s,i,m,b,"enum")

  e=m+b
  d=1 : c=0
  '
  'start with value of 0
  'or 1 for bitwise
  '
  'if tranpass=1 then exit sub
  do
    if m>=e then exit do
    wr=tword(s,m)
    if ise(ascw) then
      endline(s,m) : continue do
    end if
    if ascn=61 then
      m+=1
      nextinstruct(s,m) 'SKIP `=`
    end if
    '
    'numbers including &h .. &o coded
    '
    if (isn(ascn)<>0)or(ascn=38) then
      wordval(s,m,m) : d=dv : c=dv
    else
      if (ascn<>44)and(nisxn<>0) then
        w1=tword(s,m)
        w1=mword(w1,1)
       'wordval(w1,1,1)
        c=dv
        d=dv
        skiplspace(s,m)
      end if
    end if
    macoin me
    macsi(wr,me,0)
    addm()
    if k=-3 then c=d : d+=d 'BITWISE ENUM
    macsi(str(c),me,1)
    maco(me,0)=-18 'EQUATE
    addme
    if k=-2 then c+=1       'NORMAL ENUM
    if ascn=44 then m+=1    'SKIP COMMA
    nextinstruct(s,m)
  loop
  macoin me
  macsi(wn,me,0)
  maco(me,0)=-33 'ENUMERATION METATYPE
  maco(me,1)=4   'ASSUMED LENGTH
  maco(me,5)=4   'ASSUMED INT TYPE
  addm()
  addme
  '
  skiplspace(s,i)
end sub


'=====================================
'             VARIABLES
'=====================================
'
'
'  ###         ###   ###   #########
'   ##         ##   #####   ##      ##
'    ##  VAR  ##   ##   ##   ##      ##
'     ##     ##   ##    ##    #######
'      ##   ##   ### DIM ##    ##    ##
'       #####   ##        ##    ##    ##
'        ###   ##          ##    ##    ##
'
'=========================================
'             DIM ----> VAR
'=========================================



'--------------------------
sub vars(s as string)
'==========================
    dim as sys a,b,c,i,k,m,n,v,w,it,poff,arv,tind,indl,cv
    dim as string w1,w2,w3,wd,wr,wm,ws,wt,sigs
    '
    ' create variable and optionally associate with structure
    ' macs 0 name
    ' macs 1 macro (no structure spec)
    ' macs 2 dimension data
    ' macs 3 name of initial type
    '------------------------------
    ' maco 0 0 for primitive or higher-type
    ' maco 1 size
    ' maco 2 offset
    ' maco 3 indirection level of variable
    ' maco 4 type indirection level
    ' maco 5 type code >=htyp = user defined
    '------------------------------
    '
    i=1
    '
    '=====
    varss:
    '=====
    '
    skiplspace(s,i)
    ind=0
    k=0
    '
    'GET TYPE NAME
    '-------------
    '
    wm=aword(s,i)

    if lenw=0 then
      exit sub
    end if
    '
    if ascw<=57 then
      it=wval(wm)
      w=it and 31
    else
      '
      'IDENTIFY TYPE
      '
      it=identype(wm)
      if it=0 then
        ers="type not located: "+wm : ert=14 : exit sub
      end if
      tind=indt 'TYPE INDIRECTION
      '
      '
      '=========
      nidentify:
      '=========
      '
      w=lent
      '
      if it>=htyp then
        k=it  'CLASS OR UDT
      end if
    end if
    ws=""
    '
    '
    'CHECK FOR FUNCTION POINTERS (*foo[n])(..)
    '===========================
    '
    '
    if asc(ary)=40 then
      b=2
      w1=tword(ary,b)
      if ascw=42 then
        w1=tword(ary,b) 'SWALLOW FUNCTION NAME
        w2="" : a=b
        do
          skiplspace(ary,b)
          if ascn=91 then
            a=b
            b=instr(b,ary,"]") : if b=0 then exit do
            b+=1 : w2+=mid(ary,a,b-a)
          else
            exit do
          end if
        loop
        b=a : skiplspace(ary,b)
        if ascn=rbr then skiplspace(ary,b)
        '
        'CAPTURE SIGNATURE
        '
        if ascn=lbr then
          capturi(ary,m,b,a)
          m+=1
          coco=ccx 'default calling convention
          if coco=0 then
            if cpuw=8 then coco=2 'MS64
          end if
          sigv=""
          sigs=buildsig(ary,m)
          wm+=" "+sigs+sigv 'function pointer with signature and defaults
        end if
        ary=w2 : k=&h11f : it=k : w=cpuw 'FUNCTION PTR 32 OR 64 BITS
      end if
    end if
    '
    '
    '
    'EACH VARIABLE
    '=============
    '
    do ' each variable on line
      '
      wt=wm
      arv=len(ary)
      '
      '
      'INDIRECTION
      '===========
      '
      skiplspace(s,i)
      '
      do
        if iss(ascn) then
          w3=""
          exit do
        end if
        c=isptr(s,i) ' *varname
        w3=tword(s,i)
        if ascw=44 then continue do
        cv+=1
        exit do
      loop
      '
      if c then
        arv=0
      end if
      '
      c+=tind 'INCLUDE TYPE INDIRECTION
      '
      '
      if w3="" then exit do
      wd=""
      b=it
      '
      '
      'STRING / BSTRING PARAMS
      '=======================
      '
      if isostr(it) then
        if (lclv>0)and(asce=1) then ' bstr params
          if c then
            c-=1 'TREAT AS DIRECT STRING
          else
            b-=32 'TREAT AS BSTRING
          end if
        end if
      end if
      '
      '
      'VOID TYPES
      '==========
      '
      if b<0 then
        if c then
          'b=0
          if tind then tind-=1 'LPVOID TYPE
          wt="sys" : c-=1 : b=cpuw : w=cpuw : lent=cpuw
          'treat void* as direct system type
        else
          ers="direct void type not usable: "+wm+": "+w3 : ert=13 : exit sub
        end if
      end if
      '
      ind=c
      '
      newrecord(w3)
      macsi(wt,me,3)         'NAME OF TYPE (BUT NOT UNDERLYING TYPEDEF)
      maco(me,0)=k           '0 OR UNDERLYING TYPE OR TYPEDEF
      maco(me,1)=w           'ELEMENT LENGTH (ignoring indrection)
      maco(me,3)=c           'OVERALL LEVEL OF INDIRECTION
      maco(me,5)=b           'TYPE CODE (UNDERLYING TYPE) (VOID*==SYS)
      v=w                    'UNIT SIZE OF PRIMITIVE OR STRUCTURE
      if c then v=cpuw       'SIZE OF POINTER
      '
      '
      '---------
      'CONSTANTS
      '=========
      '
      if cnst then
        if ascn=61 then i+=1 : nextinstruct(s,i) 'skip assign
        if isstr(it) then
          a=&hc1 '&hc0+( it and 31 )
          if a<>it then
            'FORCE WIDE STRING TYPE TO BYTE BSTRING TYPE
            it=a
            macsi(typename(it),me,3)
            maco(me,5)=it
          end if
        end if
        dv=metaval(s,i,w1,it)
        a=asc(w1)
        if isstr(it) and(isq(a)=0) then
          w1=qu+w1+qu
        end if
        if dv=0 then
          if asc(w1)=iq4 then
            if it<&h80 then
              w1=noquotes(w1)
              w1=str(wval(w1))
            end if
          end if
        end if
        macsi("="+w1,me,1)
        w1=""
        goto addvrec
      end if
      '
      poff=aoff
      '
      '
      '
      '#######  #############
      'ARRAYS   #  #  #  #  #
      '#######  #############
      '         #  #  #  #  #
      '         #############
      '         #  #  #  #  #
      '         #############
      '
      '
      '
      'CHECK FOR ARRAY TYPE
      '
      if arv then
        inserts(s,ary,i) 'itr array of arrays not supported
      end if
      '
      if tind then v=cpuw 'var of indirect type
      v=w 'SIZE OF ELEMENT
      '
      skiplspace(s,i)
      '
      '
      'ARRAYS
      '======
      '
      while (ascn=lbr)or(ascn=91)
        '
        i+=1 : skiplspace(s,i)
        '
        if (ascn=rbr)or(ascn=93) then
          i+=1 : skiplspace(s,i) : m=1 : exit do 'EMPTY ARRAY
        end if
        '
        m=metaval(s,i,w1,0)-ixb+1
        wd+=str(m)+" "
        v*=m
        '
        if (ascn=44) then
          ert=704 : ers="single dimension only" : exit sub
        elseif (ascn=rbr)or(ascn=93) then
          i+=1 'skip right bracket
        end if
        skiplspace(s,i)
      wend
      if len(wd) then wd=str(v/w)+" "+wd 'insert overall span
      macsi(wd,me,2) 'number of elements specified
      '
      narray:
      '======
      '
      if c>tind then
        v=cpuw 'one pointer to variable or array
               'otherwise a direct array or direct array of pointers
      end if
      '
      'ALIGN SIZE TO 4 OR 8 BYTES
      roundupc(v,cpuw)
      '
      'STEP UP OR DOWN
      '---------------
      '
      'itr SIMD 128bit alignments
      '
      if vstp then v=vstp 'FORCE STEP SIZE
      '
      if asce=1 then
        aoff+=v : a=poff
      else
        aoff-=v : a=aoff
        'ASSUME ALL DESCENDING VARIABLES ARE LOCAL
        mlcl+=v 'atr coupled variables, no space allocation will be required
      end if
      '
      maco(me,2)=a     'OFFSET
      macsi(memreg(regs,a),me,1) 'ENCODE OPERAND: [ebx+1234]
      '
      'REGISTERS / VAR LINKAGE
      '=======================
      '
      '
      if ascn=97 then
        if wordahead(s,i)="at" then
          '
          'AT
          '===
          '
          i=nwd
          skiplspace(s,i)
          b=maco(me,3)+1
          v=0
          '
          'indirection level
          '
          do
            if ascn=35 then
              wr=tword(s,i)
              wr="["+wr+"]" 'HOST VAR ADDRESS #VAR
              b-=1
              ascw=91
              exit do '#HostVar address
            end if
            wr=mword(s,i)
            if ascn=126 then 'BIND' IMPORTED VARIABLE BYREF
              i+=1
              wpfx="mov "+qedi+cm+wr+cr
              wr=mword(s,i)
              b-=1
              exit do
            end if
            if (ascw=38)or(ascw=64) then
              b-=1 : continue do
            elseif ascw=42 then
              b+=1 : continue do 'indirection
            end if
            exit do
          loop
          '
          '
          'REGISTERS -10
          '
          if mc=-10 then
            if b>0 then
              wr="["+wr+"]"
              b-=1
              ascw=91
            else
              typ=cpuw
            end if
          else
            a=typ
            if b=0 then
              a=cpuw 'ALLOW ADDRESS COUPLING
              if mp then v=maco(mp,2) 'TRANSFER OFFSET VALUE
            end if
            if (ascw<>91)or(isfloat(a)<>0) then
              ers="Must use simple sys variable" : wr=ow : ert=122 : exit sub
            end if
          end if
          '
          macsi(wpfx+wr,me,1)
          aoff=poff ' no change to offset
          maco(me,2)=v
          maco(me,3)=b
        end if 'AT linkage
      end if
      maco(me,4)=tind 'TYPE INDIRECTION LEVEL (needed for arrays)
      addvrec:
      '=======
      dim as string ss
      ss=macso(me,1)
      replace(ss,cr,":")
      appendt(enc("va "+macso(me,0)+" as "+macso(me,3)+" == "+ss))
      addme
    loop
    nextinstruct(s,i)
    if ise(ascn)=0 then
      mc=0 : goto varss 'FURTHER VAR STATEMENTS

    end if
    if lclv=0 then aoffs=aoff
end sub



'------------------------------------------------------------
sub declvars(s as string, byval n as sys, byref wa as string)
'============================================================
  dim as sys a,b
  if s="" then exit sub
  '
  if n=1 then
    localvars()
    lcl=1
  elseif (n=3)or(n=4) then
    staticvars()
  end if
  '
  if cnst then 'CONSTANT
    if len(wa) then
      vars(wword(s,1)+" "+wa) 'CREATE CONSTANT WITH VALUE
      wa=""
    end if
    exit sub
  end if
  '
  vars(s) 'CREATE VARIABLE
  '
end sub



'----------------------
sub varsal(s as string)
'======================
dim as sys n=1 'default local space
if (funi=0)and(dep=0) then n=3 'use static space
declvars(s,n,"")
end sub


'-----------------------------------------
function NewTmpVar(ty as string) as string
'=========================================
dim as sys a
dim as string va
tmpi+=1
va=NewTmpName()
vars(ty+" "+va)
if funi then
  if lclv then
    lcl=1
    if isstr(typ) then lcls=1
  end if
end if
return va
end function


'-----------------------------------------
function tmptypvar(ty as string) as string
'=========================================
varsal(ty+" "+newTmpName())
return macso(me-1,1) 'RETURN OPERAND [ebp-xxxx]
end function


'--------------------------
function tmpvar() as string
'==========================
return tmptypvar("8") 'GENERIC OPERAND [ebp-xxxx]
end function


'-----------------------------------
sub vtlcheckmark(byref wr as string)
'===================================
  dim as sys a
  a=instr(wr,"/\")
  if a then
    a+=2
    if asc(wr,a)<>13 then
      wr=left(wr,a-1)+cr+mid(wr,a)
    end if
  end if
end sub

#if 0

'---------------------------------------------------------------------
function Members(mlist as string,w1 as string, w6 as string) as string
'=====================================================================
  'mlist: list of member objects etc.
  'w1:    dot method to invoke
  'w6:    parameters
  '
  dim as sys a,b,n
  dim as string w2,w3,w4,w5
  a=1
  do
    w3=yword(mlist,a)
    if isn(ascn) then
      w5=yword(mlist,a)
      n=wval(w5)
    else
      n=1
    end if
    if lenw=0 then exit do
    mp=maco(ths,0)-htyp
    b=-1
    w4=w3+w1
    findmemb(w4,"",b,0)
    if b then
      if n>1 then
        w2+="for i=1 to "+w5+cr+w3+"[i]"+w1+" "+w6+cr+"next"+cr 'ARRAY OF MEMBERS
      else
        w2+=w4+" "+w6+cr 'INDIVIDUAL MEMBER
      end if
    end if
  loop
  if len(w2) then
    return "("+cr+"indexbase 1"+cr+"sys i"+cr+w2+")"+cr
  end if
end function


''----------------------------------------------------
'function membervals(a as sys, wd as string) as string
''====================================================
'  dim as string w1,w2
'  dim as sys i
'  w1=macso(a,2)
'  i=instr(w1,chr(127))
'  if i<=1 then return ""
'  if asc(wd)>64 then w2=wd+"." else return left(w1,i-1)
'  w1=cr+left(w1,i-3)
'  replace(w1,cr,cr+w2)
'  return mid(w1,3,len(w1)-2)+cr
'end function

#endif


'#                 #
'###################
'###    TYPES    ###
'###################
'##     #####     ##
'       #####
'       #####
'       #####     ##    ##     ######       #####
'       #####     ##    ##     ##    ##   ##     #
'       #####     ##    ##     ##    ##   ########
'       #####      #######     ######     ##
'       #####           ##     ##         ##     #
'       #####           ##     ##          ######
'      #######     #####

' aml   array size multiplier
' buil  table builder string
' wih   inherited elements to pre-append 
' wmx   max structure length for unions
' vtl   virtual data flag
' pof   offset value building def
' pk    k holder
' vof    next offset value building def
' vp    hold offset for inherited strucs

'---------------------------------------------------------------------
sub types(unip as sys, vtp as sys, byref ttc as sys, byref tuc as sys)
'=====================================================================

  'macso:
  '=====================================
  '0 name
  '1 structure
  '2 default values list
  '3 virtual table maker script
  '=====================================
  'maco:
  '=====================================
  '0 metatype (-3)
  '1 object length
  '2 index of methods table, if present
  '3 flag to indicate virtual table field present
  '4 number of virtual table entries
  '5 max primitive size
  '=====================================



  dim as sys   a,b,c,d,e,f,g,k,m,n,v,w

  dim as sys ctbl,vof,vtl,sih,pk,pof,pv,na,wmx,uni,bb,cmo,indi,sni,clas,tv,x,vtlf,mps,nentry

  dim as string w1,w2,w3,w4,w5,wd,wm,wn,wr,ws,wt,buil,wih,tbls,wpr,nesn,ty,mlist,vlist

    maco(me,0)=-3 ' is a type

    wm=" "+macso(me,1)+" " : k=1
    'w     ' offset accumulator
    'wmx   ' max offset accumulator (unions)
    'pof : vof : ctbl
    '
    '
    '
    ttc=0 : tuc=0
    vtl=instr(wm,"/\"+cr) : vtlf=vtl
    '
    if vtl then
      a=maco(me,2) and 2
      if a=0 then ctbl=1 'VIRTUAL TABLE IS PRESENT
    end if
    '
    cmo=unip and 8   'C MODE FLAG
    clas=unip and 16 'class flag
    '
    'CHECK FOR UNION (1) OR TYPE (0)
    '-------------------------------
    '
    a=unip and 1
    unif(uni)=a
    unim(uni)=a
    '
    addme()
    'priv=&h39
    'pp=priv
    '
    '=======================
    do 'FOR EACH MAIN MEMBER
    '=======================
      '
      maindec:
      '
      pk=k
      '
      'SKIP COMMAS
      'SKIP 'HAS' etc
      '
      'READ QUALIFIER WORDS
      '--------------------
      '
      do
        wr=tword(wm,k)
        if lenw=0 then exit do
        if ascw=59 then mid(wm,swd)=" " : continue do
        if wr="virtual" then mid(wm,swd)=space(7) :continue do 'IGNORE
        '
        'SUPPORT MACROS INSIDE TYPES
        '
        a=lookupm(wr)
        if a then
          m=maco(a,0)
          if (m=-18)or(m=-20) then
            if ascn=97 then
              if wordahead(wm,k)="as" then goto nmacrow 'exclude 'varname as type'
            end if
            w1=left(wm,swd-1) 'protect from destructive parse: inserts()
            k=swd
            wr=mword(wm,k)
            wm=w1+wr+" "+mid(wm,k) 'rebuild wm after macro expansion
            k=len(w1)+lenw+1
          end if
        end if
        '
        nmacrow:
        '
        if ascw=35 then
          '
          'EXTRACT ANY #DEFINES
          '--------------------
          '
          if instrword(" #if #ifdef #ifndef #else #endif ",wr) then
            md=maco(a,5)
            b=k
            k=swd
            w1=left(wm,swd-1)
            metaco(wm,b)
            wm=w1+mid(wm,b)
            if ert then exit sub
            continue do
          end if
          if wr="#define" then
            do
              m=swd
              endline(wm,k)
              w1=rtrim(mid(wm,m,k-m))
              k+=2 : wm=left(wm,m-1)+mid(wm,k) : k=m
              defbuf+=w1+cr
              if asc(w1,len(w1))<>92 then exit do 'checking for line continuation '\'
            loop
          end if
          continue do 'main loop
        end if
        '
        b=dic(" has 1, of 2, from 2, extends 2, align 3, dim 4, as 4, const 4, public 4, protected 4, private 4, ",wr)
        select case b
        case 0
          exit do
        case 1
          sih=0
        case 2
          sih=1
        case 3 
          b=swd : wr=tword(wm,k) : v=-wval(wr) : a=w and v 
          if a<w then w=a-v
        case 4
          'ignore
        end select
        mid(wm,swd)=space(lenw)
      loop
      '
      a=ascw
      '
      'OVERRIDE PREVIOUS ELEMENTS OF SAME NAME
      '---------------------------------------
      '
      'override methods by appending new methods
  
      '---------------------
      'CHECK FOR END OF BODY
      '=====================
      '
      if wr="" then exit do 'END OF STRUCTURE
      '
      '------------------------
      'CHECK FOR METASTATEMENTS
      '========================
      '
      if a=35 then
        c=swd : wr=mword(wr,1) : swd=c
        if mc=-13 then
          md=maco(mp,3)
          if md>=100 then
            metaco(wm,k)
            continue do
          end if
        end if
      end if
      '
      '--------------------------
      'END OF VIRTUAL FUNCTIONS /
      '==========================
      '
      if a=47 then
        '
        if vtl=0 then continue do 'IGNORE ALL BUT THE FIRST '/' ENCOUNTERED
        '
        k+=1 : skiplspace(wm,k) ' /\
        '
        maco(me-1,4)=w/cpuw 'NUMBER OF TABLE ENTRIES
        w=0 : wmx=0 : pof=0 : vof=0 : vtl=0 'CLEAR OFFSETS ETC
        '
        if ascn=0 then wm+=cr 'ensure ending with cr for proper line ending
        k+=2                  'skip cr following
        '
        'IS A VIRTUAL TABLE POINTER NEEDED?
        '----------------------------------
        '                   
        if (vtp>0) then
          '
          'INSERT BASE VTP PLACE
          '
          wm=left(wm,k-1)+htb+"___ 0 0 0 0 9AA , sys"+cr+mid(wm,k) : k+=24
          w=cpuw : pof=w : vof=w
          '
        end if
        '
        pk=k
        '
        'INHERITED BODY LIST
        '-------------------
        '
        'insert the accumulated subelements
        '
        if len(wih) then 'PASS 2 TO PROCESS INHERITED BODIES
          ws=wih : wih="" : wd=","
          '
          'SPLIT THE STRUCTURE STRING
          '
          wt=" "+mid(wm,pk) : wm=left(wm,pk-1)
          '
          goto insert_subelements
          '
        else
          continue do
        end if
        '
      end if 'end of virtual functions /


      '
      '---------------------------
      'UNIONS AND INNER STRUCTURES
      '===========================
      '
      if unif(uni) then
        '
        'CHECK WITHIN UNION
        '------------------
        '
        if unim(uni) then
          if w>wmx then wmx=w ' MAX VAR OFFSET+SIZE
          w=unio(uni)         'RESTORE OFFSET
        end if
        '
        '
        'CHECK END OF UNION/STRUCT
        '-------------------------
        '
        b=swd
        if unif(uni)=1 then
          if wr="end" then
            if instrword(" union struct ",wordahead(wm,k)) then
              k=nwd : unif(uni)=a
            end if
          end if
        end if
        '
        ' ) } OR END OF UNION/STRUCT
        '---------------------------
        '
        if a=unif(uni) then
          '
          if unim(uni) then
            if w<wmx then w=wmx 'MAX VAR OFFSET+SIZE  IN UNION
          end if
          '
          'WORDS FOLLOWING STRUC/UNION
          '
          w1=""
          do
            if ascn=59 then k+=1 : skiplspace(wm,k) : exit do';
            if ise(ascn) then exit do else w1=tword(wm,k)
          loop
          '
          uni-=1
          mid(wm,b)=space(k-b) 'WIPE ENDING
          continue do
        end if
        '
      end if
      '
      'CHECK FOR START OF NESTED UNION / STRUCT
      '----------------------------------------
      '
      d=dic(" struct 1, union 2, type 1,",wr)
      '
      if d then
        m=swd
        c=lenw
        uni+=1        ' stack index
        unio(uni)=w   ' base offset
        unif(uni)=1   ' flag
        unim(uni)=d-1 ' type or union
       'unin(uni)     ' name
        b=swd
        '
        if isxn then
          a=k : nextinstruct(wm,k)
          if (ascn<>lbr)and(ascn<>123) then
            k=a : skiplspace(wm,k) : goto nuname 'brackets not used here
          end if
        end if
        if (ascn=lbr)or(ascn=123) then
          'ANONYMOUS
        else
          wr=tword(wm,k)
          'IS THIS STRUCT ALREADY DEFINED?
          if (ascn<>lbr)and(ascn<>123) then
            a=identype(wr)
            if a then
              mid(wm,m)=space(c) 'blank "struct"
              k=m+c
              uni-=1
              continue do
            end if
          end if
          unin(uni)=wr+"."
          nextinstruct(wm,k) 'NAME GIVEN
        end if
        '
        '------
        nuname:
        '------
        '
        d=1
        c=k
        '
        if ascn=lbr then d=rbr : k+=1 '(
        if ascn=123 then d=125 : k+=1 '{
        unif(uni)=d
        '
        'CHECK FOR ASSOCIATED STRUC NAME
        '
        if d>1 then
          capture(wm,m,c,0) : skiplspace(wm,c)
        end if
        mid(wm,b)=space(k-b) 'WIPE STRUCT NAME
        if ise(ascn)=0 then
          if ascn=42 then
            k+=1
            mid(wm,b)="sys "+tword(wm,k)
            mid(wm,c)=space(k-c)
            ' allocate space for pointer only
            k=b
            uni-=1
          else
            unin(uni)=tword(wm,c)+"." 'capture 1st associated name
          end if
        end if
        '
        continue do
        '
      elseif a=61 then '=' DEMARKATE UNION GROUPS
        '
        'UNION START MARKER '='
        '
        if w>wmx then wmx=w 'SET UNION MAX SIZE
        w=0 'RESET OFFSET
        mid(wm,swd)=" " 'WIPE NAME
        continue do
        '
      end if 'UNIONS AND INNER STRUCTURES
      '
      '============
      nstructunion:
      '============
      '
      '
      '================================
      'TRANSFORM BASIC SYNTAX TO OXYGEN
      'REARRANGE ELEMENT DECLARATION:
      '==============================
      '
      'OVERVIEW:
      '=========
      '
      'C STYLE
      '
      '---------------------------------------------------------------
      ' TYPE/RETURN | NAME | ARRAY OR METHOD/FUNCTION/SUB | (PARAMS) | 
      '===============================================================
      '
      '
      'BASIC
      '
      '-------------------------------------------------------------------
      ' NAME AS | TYPE OR METHOD/FUNCTION/SUB | (PARAMS) | AS RETURN_TYPE |
      '===================================================================
      '
      'TO:
      '===
      '
      '----------------------------------------------------------
      ' TYPE | NAME | METHOD_FLAG: ! | (PARAMS) | AS RETURN_TYPE |
      '==========================================================
      '
      '
      b=swd : n=0 : ascw=0 : indi=0
      a=k
      w1=tword(wm,k)
      k=a
      w2=""
      w3=""
      a=asc(w1)
      '
      'NESTED VARIABLES (NAME DOT)
      '
      if a=123 then
        w2=htb+nesn+wr+" "+str(w)+" 0 0 0 0 0AA"+cr
        nesn+=wr+"."
        wm=left(wm,swd-1)+w2+mid(wm,nwd)
        k=swd+len(w2)
        continue do
      end if
      '
      if asc(wr)=125 then
        a=len(nesn)-1
        do
          a-=1 : if a<=1 then nesn="" : exit do
          if asc(nesn,a)=46 then nesn=left(nesn,a) : exit do
        loop
        mid(wm,swd)=" " : continue do
      end if
      '
      'SUB FUNCTION METHOD name ..
      '===========================
      '
      coco=ccx
      if coco=0 then
        if cpuw=8 then coco=2 'MS64
       end if
      cco=coco
      if (coco=2)and(vtp=0) then coco=3
      mth=dic(" ! 03, sub 01, function 02, method 03, ",wr)
      '
      if mth then
        a=len(w1)
        k+=a
        mid(wm,swd)=space(a) 'BLANK
        w2=w1 'POSSIBLE NAME
        n=&h11f
        wr="sys"
        a=k 'HOLDING POSITION FOR LOOKAHEAD
        w1=tword(wm,k)
        callingconv(wm,k,w1)
        '
        if ascw=lbr then k=a : goto pparams else w3="" ' no '()'
        '
        'CHECK FOR RETURN TYPE
        '---------------------
        '
        if w1="as" then
          a=1 : goto astype
        else
          k=a 'backtrack
          ascw=0 : skiplspace(wm,k) : goto reagg 'NO RETURN TYPE
        end if
        '
      end if 'PROCEDURES
      '
      w2=wr 'POSSIBLE NAME
      '
      'DECLARE name AS TYPE
      '--------------------
      '
      if w1="as" then
        k=nwd : n=1 : a=1 : goto astype
      end if
      '
      '
      a=0
      if nisxn then
        m=instrword(" signed unsigned short long ",wr) 'TYPE MODIFIERS
        if m then
          ctype(wm,k,wr) : a=typ
        else
          a=identype(wr)
        end if
        '
        'COMPOUND OR CUSTOM TYPE
        '
        if a>=htyp then
          m=maco(a-htyp,0)
          '
          'FUNCTION TYPES
          '
          if m=-5 then
            if nisxn then wr=tword(wm,k)
            bb=pk
            'itr overload matching
            nextproc(macso(a-htyp,1),1,"",0)
            if (sig="#@")or(sig="") then sig=","
            'if priv=0 then priv=&h39
            '
            'ENCODE PROCEDURE
            '
            wpr=htb+wr+" "+str(cpuw)+" "+str(w)+" 0       8 "+chr(cco+65)+chr(vtp+65)+" "+sig+" "+sog
            w+=cpuw
            goto recompor
          end if
        end if
      end if 'nisxn
      '
      '
      '=========
      typebfna: 'TYPE BEFORE NAME (C STYLE)
      '=========
      '
      if (a<>0)and(a<&h100)or(a>=htyp) then
        typ=a
        m=isptr(wm,k)
        if ascn<>lbr then
          w2=tword(wm,k) 'NAME
          callingconv(wm,k,w2) 'CHECK CALLING CONVENTION
        else
          k+=1           'SKIP LEFT BRACKET
          ascw=lbr
        end if
        if ascw=lbr then 'NAME IN BRACKETS
          isptr(wm,k)    'SKIP *
          w2=tword(wm,k) 'NAME
          k+=1           'SKIP RIGHT BRACKET
          skiplspace(wm,k)
        end if
        if ascn=lbr then
          if clas then
            mth=3 'METH
          else
            mth=2 'FUN
          end if
          n=&h11f
        end if
        a=1
        if m then
          'w2=string(m,"*")+w2 'INDIRECTION
          indi+=m : m=0
          if typ=-1 then
            typ=cpuw : indi=0 'void *
          end if
          n or=1
        end if
        if ascn=91 then
          a=1 : n or=2       'ARRAY
        end if
        '
        'check ahead for opening parameter bracket
        '
        if a then w1=wordahead(wm,k) else w1=""
        skiplspace(wm,k)
      end if 'type before name tbfna
        '
      '
      pparams:   '(..) [] ARRAY OR PROCEDURE PARAMS
      '============================================
      '
      a=asc(w1)
      if (a=40)or(a=91) then
        capture(wm,m,k,a)
        skiplspace(wm,k)
        w3=mid(wm,m,k-m)
        w1=wordahead(wm,k)
        n or=1
        if w1="as" then
          k=nwd
        elseif ascn=61 then
          'SYNTAX: virtual void f()=0
          if a=40 then
            endline(wm,k) 'skip
          end if
        else
          if n<2 then wr="sys"
        end if
      end if
      '
      astype:  'AS dim type or fun type
      '================================
      '
      if w1="as" then a=1 else a=0
      '
      if a then
        wr=tword(wm,k)
        '
        'PB format: AS ASCIIZ*80
        '
        a=identype(wr)
        if iszstr(a) then
          if ascn=42 then
            a=k
            k+=1
            w1=tword(wm,k)
            w1=mword(w1,1)
            if nmb then
             'wordval(wm,a+1,k)
              w2+="["+str(dv)+"]"
            else
              k=a
              skiplspace(wm,k)
            end if
          end if  
        end if
        indi+=isptr(wm,k)
        if ascn=44 then k+=1 'skip comma
      end if 'AS
      '
      '
      '----------------------------------------
      reagg: 'PUT THE DECLARATION BACK TOGETHER
      '========================================
      '
      'wr primary type: method or vartype
      'w2 name
      'w3 parameters (..)
      '
      'INSERT TYPE NAME AS TYPE 
      '
      if n then
        '               TYPE   NAME   PARAMS
        wm=left(wm,b-1)+wr+" "+w2+" "+w3+mid(wm,k)
      end if
      swd=b
      k=b+len(wr)
      bb=b-1 ' LOCATION OF TRIMBACK POINT
      '
      '
      'IS IT THE DEFAULT TYPE OR
      'IS THE TYPE SPECIFIED BY SIZE?
      '------------------------------
      '
      a=0
      if mth>0 then
        v=cpuw
      else
        v=wval(wr)
        if v=0 then
          a=asc(wr)
        end if
      end if
      '
      lent=v and 31
      '
      'OTHERWISE TRY TO IDENTIFY THE TYPE
      '    
      if (v=0)and(a<>48) then
        '
        n=identype(wr)
        '
        if (n<0)or(n=&h20) then
          '
          'LOOKS LIKE A C TYPE EXPRESSION
          '------------------------------
          '
          ctype(wm,k,wr)
          if wr="void" then typ=cpuw : lent=0 'IN THIS CONTEXT
          v=lent : n=typ ': mid(wm,b)=space(k-b)
          '
        elseif n<htyp then
          '
          'A PRIMITIVE TYPE OR PART OF MULTIELEMENT
          '----------------------------------------
          '
          if n=0 then
            '
            'LOOKAHEAD FOR MULTI-ELEMENT 'AS'
            '
            c=swd
            a=k
            endline(wm,a)
            b=instr(k,wm," as ")
            if (b>0)and(b<a) then
              w1=tword(wm,b+4)
              n=identype(w1)
              mid(wm,b)=space(a-b) 'blank
              if n then wr=w1 : k=c
            end if
            '
            'ASSUME UNIDENTIFIED TYPE TO BE SYSTEM TYPE
            '
            if n=0 then
              ert=121 : ers="Unidentified element type" : ow=wr : exit sub
            end if
          end if 
          v=lent
          '
        else 'n>=htyp
          '
          'CHECK IF POINTER TO ANOTHER STRUCTURE
          '-------------------------------------
          '
          if len(w2) then a=asc(w2) else a=ascn
          if (a<>42)and(indi=0) then
            if wr=macso(me-1,0) then
              ers="class must not be a member of itself"
              ow=wr : ert=999 : exit sub
            end if
          end if
          '
          if maco(n-htyp,0)=-33 then
            n=4 : v=4 'ENUMERATIONS ASSUME LONG TYPE
          end if
          '
          '
        end if 'n, htyp
        '
        m=1
        do
          if asc(w2,m)=42 then
            indt+=1 : k+=1 : m+=1 'indt initially set by identype
          else
            exit do
          end if
        loop
        if indt then v=cpuw
      end if 'v=0
      indt+=indi 'indi is ptr flag
      '
      sni=n 'type
      ty=wr 'type or class by name
      tv=v
      '
      '
      '
      '============
      multielement:  'LOOP POINT FOR MULTIPLE MEMBERS
      '============
      '
      '
      ' ELEMENTS,POINTERS AND PROCEDURES
      '---------------------------------
      '
      aml=1 'DEFAULT AS 1 ARRAY ELEMENT
      v=tv  'PRIMITIVE SIZE
      '
      'POINTER TO ANOTHER STRUCT
      '
      if sni>=htyp then
        'itr auto single-level indirect in encodE ele()
        v=0
        if ascn=42 then
          v=cpuw
          k+=1 : skiplspace(wm,k)
        end if
      end if
      if indt then
        v=cpuw
      end if
      '
      if v or (sni<htyp) then
        '
        '
        'AUTO-ADJUST BOUNDARY ALIGNMENT (PADDING)
        '----------------------------------------
        '
        if pakd=0 then
          roundupc(w,v)
          if mps<v then
            mps=v
          end if
        end if
        '
        a=swd : wn=nesn+unin(uni)+tword(wm,k)
        '
        c=ascn
        '
        '
        'ALLOCATE SPACE FOR FIXED ARRAY
        '------------------------------
        '
        if mth=0 then
          if (ascn=lbr)or(ascn=91) then
            a=k : aml=arraysize(wm,k)
          end if
        end if
        '
        '
        'DEFAULT VALUES
        '--------------
        '
        if ascn=61 then
          a=k : capts(wm,k)
          mlist+=wn+mid(wm,a,k-a)+cm
          mid(wm,a)=space(k-a) 'blank
        end if
        '
        '
        'COMPOSE ELEMENT RECORD
        '----------------------
        '
        c=bref
        '
        if cmo then bref=0 'NO AUTO BYREF IN C MODE
        '
        wpr+=htb+wn+" "+str(v)+" "+str(w)+encodele(wm,k,ty,sni,vtl,vtp,ws)+cr
        skipspace(wm,k)
        '
        bref=c
        '
        'ADD INSTRUCTION TO VIRTUAL TABLE BUILDER
        '----------------------------------------
        '
        if ctbl then
          if (vtl>0)and(mth>0) then
            ws=splitsi(ws,"")
            'tranpass=2 check against proclist
            buil+=enc("te "+wn+ws+" "+hexci(w)) 'VTEntry(w,wn+ws)+cr
            ttc+=1
          end if
        end if
        '
        '
        'CAPTURE DEFAULT MEMBER VALUES
        '
        'ADD OFFSET FOR NEXT ELEMENT
        '---------------------------
        '
        w+=v*aml
        '
        '
        'MULTI ELEMENT / PROPERTY
        '------------------------
        '
        'MEMBERS DEFINED TOGETHER EG: SYS A,B,C(10),D
        'this syntax should not be used for methods.
        '
        '
        if ascn=58 then
          a=k
          k+=1 'SEPARATOR OR BIT FIELD
          skiplspace(wm,k)
          if isn(ascn) then
            'BIT FIELD:   : 4
            wr=wrd(wm,k)
            mid(wm,a)=space(k-a) 'BLANK OUT
          end if
        end if
        if ascn=44 then
          k+=1 : nextinstruct(wm,k)
          '
          'SUPPORT INDIRECTION
          '
          if ascn=42 then
            a=1 : k+=1 : skiplspace(wm,k)
          else 
            a=0
          end if
          'swd=k : ascn=0
          if identype(wordahead(wm,k))=0 then
            if ascn<>61 then indt=a : goto multielement 'REPEAT FOR NEXT ELEMENT
          end if
        end if
        '
        '
        'OTHERWISE NO FURTHER ELEMENTS IN THIS (COMMA CHAINED) LIST
        '
        'TRIM OFF PROCESSED SCRIPT AND RECOMPOSE BLOCK
        '---------------------------------------------
        '
        recompor:
        '
        w2=rtrim(left(wm,bb))+wpr : wpr=""
        wm=w2+mid(wm,k) ' reconstruct
        k=len(w2)+1   'SOURCE READER OFFSET
        ' itr space allocated for fixed arrays
        ' but multidimens not specified (ubound inferred from offs)
        '
        'PROCESS NEXT ELEMENT
        '--------------------
        '
        continue do
        '
      end if 'PRIMITIVES (V>0)
      '
      '#########
      'INHERITED
      '#########
      '  #####
      '  #####
      '  #####
      '  #####
      '  #####
      '  #####
      '  #####
      '  #####
      '  #####
      '  #####
      '#########
      '#########
      '#########
      '
      '
      'GET ELEMENT NAME (OR COMMA FOR INHERITED ELEMENTS)
      '
      '
      skiplspace(wm,k)
      if ise(ascn) then
        wd=","
      else
        wd=tword(wm,k)
        'mlist+=wd+" "
      end if
      '
      '
      'CHECK FOR ARRAY DEFINITION
      '--------------------------
      '
      'LOOK FOR ROUND OR SQUARE BRACKETS
      '
      if (ascn=lbr)or(ascn=91) then
        aml=arraysize(wm,k) : 'ARRAY SIZE
        'mlist+=str(aml)+" "
      end if
      '
      if ascn=97 then
        if wordahead(wm,k)="as" then
          k=nwd : w1=wrd(wm,k) ' swallow as ..
        end if
      end if
      '
      a=sni-htyp 'STRUCTURE INDEX
      '
      if a>0 then e=1 else e=0
      if e=0 then ers="Undefined "+ty : ert=10 : exit sub
      '
      ws=macso(a,1)
      '
      m=instr(ws,"/\"+cr)
      '
      if vtl=0 then
        '
        if m then
          ws=mid(ws,m+2) 'OMIT VIRTUAL SECTION IF PARENT IS NOT A CLASS
          m=0
        end if
        '
      else 'vtl<>0
        '
        if m=0 then
          '
          ws="/\"+cr+ws 'NO VIRTUAL SECTION DEFINED
          m=1
        else 'm<>0
          if maco(a,4) then 'TABLE ENTRIES PRESENT
            if ctbl then
              tbls+="|ue "+_
              hexci(maco(a,2))+" "+_            'vft table index
              hexci(a)+" "+_                    'structure index       
              hexci(aoff+w)+_                   'target offset
              " "+ty+cr 'enc
              tuc+=1
              if lclv=0 then aoffs=aoff
            end if
          end if
        end if
        '
      end if
      '
      '
      '--------------------------
      'SPLIT THE STRUCTURE STRING
      '==========================
      '
      wt=" "+mid(wm,k)
      wm=left(wm,pk-1)
      '
      'INCORPORATE INHERITED BODY ELEMENT
      '
      c=0
      if vtl+m=0 then
        d=maco(a,5) : if mps<d then mps=d
        roundupc(w,d)
        c=1 : w4=" 0 5 "
        d=maco(a,1)
      else
        'if vtl then c=2 : w4=" 0 6 "
        'd=maco(a,4)*cpuw 'VIRTUAL TABLE ENTRIES
      end if
      '
      '
      if c then
        if wd<>"," then
          wm+=htb+nesn+wd+" "+str(d)+" "+str(w)+w4+"AA , "+ty+cr
        end if
      end if
      '
      'CALC OFFSET FOR NEXT INHERITED COMPONENT. (ARRAY SPACE INCLUDED)
      '
      'calculated in advance
      '
      c=0
      if vtl then
        if m then
          c=4 'VIRTUAL PART OF MEMBER INTO MAIN VIRTUAL
        end if
      else 'vtl=0 'MAIN BODY
        if m=0 then
          c=1 'BODY OF MEMBER INTO MAIN BODY
        end if
      end if
      '
      select case c
      case 0 : na=1   : pof=w
      case 1 : na=aml : pof=w+maco(a,1)*aml  'body part (arrays supported)
      case 4 : na=1   : pof=w+maco(a,4)*cpuw 'virtual part (no arrays supported)
      end select
      '
      '
      '
      '==================
      insert_subelements:
      '==================
      '
      '---------------------------
      'PROCESS INHERITED ELEMENTS
      '--------------------------
      '
      b=1
      '
      '
      do 'FOR EACH OF THE INHERITED ELEMENTS
        '
        wn=tword(ws,b) 'THE NAME OF THE SUB ELEMENT
        if lenw=0 then exit do
        m=ascw
        '
        '
        '---------------------------------
        'CAPTURE BODY OF INHERITED ELEMENT
        '=================================
        '
        if m=47 then 
          '
          'end of member vt section and start of member body
          '
          '
          if vtl>0 then
            '
            'CAPTURE BODY OF INHERITED COMPONENT
            '-----------------------------------
            '
            c=maco(a,5)
            if mps<c then mps=c
            roundupc(vof,c)
            vof+=maco(a,1)*aml  'accum size of objects
            '
            'CHECK FIRST IF THERE ARE ANY ELEMENTS IN THE BODY
            '-------------------------------------------------
            '
            b+=1 : nextinstruct(ws,b) '/\
            '
            if len(ws)>=b then
              wih+=" ?"+str(a)+" "+ty+" "+str(aml)+" "+wd+" "+mid(ws,b)
            end if
            '
          end if
          '
          ws=""
          exit do ' END OF PASS 1 WITH CAPTURED BODY
          '
          'previously held over for the body section
          'It is assumed that we are in in the parental body section.
          '
          '
        elseif m=63 then
          '
          '
          'INSERT BODY OF INHERITED SUBELEMENTS INTO MAIN BODY ('?' MARKER)
          '----------------------------------------------------------------
          '
          a=wval(tword(ws,b))   'index to type
          ty=tword(ws,b)        'type
          aml=wval(tword(ws,b)) 'array / single scale
          wd=tword(ws,b)        'type/inherited structure
          wn=tword(ws,b)        'name
          d=0
          if vtp>0 then
            if (pof=cpuw)and(ascw=95) then
              if (wd=",")and(wn="___") then
                d=1 : pof=0
              end if
             end if
          end if
          '
          'BODY OFFSET (allowing for arrays)
          '
          c=maco(a,5)
          if mps<c then mps=c
          roundupc(pof,c)
          w=pof : pof+=maco(a,1)*aml
          if d then
            endline(ws,b) : continue do 'OMIT FIRST VTP (COMPAT WITH SIH)
          end if
          '
          '
          'INCORPORATE INHERITED STRUCTURE NAME
          '
          '
          'A HEADER IS ADDED DESCRIBING THE WHOLE INHERITED STRUCTURE
          '
          if wd<>"," then
            '
            'another of these may be present in the virtual section.
            wm+=htb+nesn+wd+" "+str(maco(a,1))+" "+str(w)+" 0 5 "+ "AA , "+ty+cr
          end if
          '
        end if 'm=63 '?'
        '
        'READ ATTRIBUTES OF EACH INHERITED ELEMENT
        'Recalculate offsets make other adjustments.
        'This applies to both virtual and body sections.
        '
        pv=v
        x=wval(yword(ws,b))  'SIZE
        v=wval(yword(ws,b))  'OFFSET
        w3=yword(ws,b)       'PROCLIST POSITION (PLP)
        w4=yword(ws,b)       'VAR/FUNCTION CODE (VARF)
        c=b : endline(ws,b)  'itr multiline default values
        w5=mid(ws,c,b-c)     'REMAINING ATTRIBUTES
        '
        '
        'CHECK MAX PRIMITIVE SIZE
        '
        n=wval(w4) 'varf
        '
        '
        'ADJUST VAR/FUNCTION CODE VARF
        '-----------------------------
        '
        if vtl then 
          m=n
          '
          if sih=0 then
            if n=9 then n=10 '9 SIGNIFIES INHERITED METHOD
            if n>=10 then
              n+=vof
            end if
          end if
          '
          if n<>m then w4=str(n) 'CONVERT BACK TO STRING
          '
        end if
        '
        'PREFIX NAME DOT TO GIVE THE LOCAL NAME
        '
        if wd<>"," then
          wn=wd+"."+wn 'IF WD IS A COMMA THEN USE THE ORIGINAL NAME
        end if
        '
        '
        'APPEND RECOMPOSED DESCRIPTOR
        '-----------------------------
        '
        'start with tab
        'add element with adjusted offset
        c=w+v 'oop total offset
        w3=" "+str(x)+" "+str(c)+" "+w3+" "+w4+" "+w5+cr
        '
        wm+=htb+unin(uni)+nesn+wn+w3
        '
      loop ' FOR EACH INHERITED SUB ELEMENT
      '
      'pass 1: class virtual table members (early exit)
      'pass 2: object members
      '
      '
      if vtlf+maco(a,4)=0 then
        w=w+maco(a,1)*na 'ELEMENT SIZE
      else
        w=pof 'UPDATE OFFSET FOR VFT OR BODY
      end if
      '
      k=len(wm)+2 'NEXT LINE TO PROCESS
      pk=k
      '
      wm+=wt 'REASSEMBLE RECORD
      sih=0
      '
      'MORE NAMES TO FOLLOW?
      '---------------------
      '
      nextinstruct(wm,k)
      '
      'check for comma (or semicolons in C style structures)
      '
      if ascn=58 then
        k+=1
      elseif ascn=44 then
        k+=1
        wr=wordahead(wm,k)
        a=asc(wm,nwd)
        if isx(a) then
          goto multielement 'loop back to process similar members
        end if
        'otherwise assume a new type
      end if
      '
    '===================================
    loop 'EACH ELEMENT IN MAIN STRUCTURE
    '===================================
    '
    '
    'STORE COMPLETED DATA STRUCTURE
    '==============================
    '
    '
    b=me-1
    macsi(wm,b,1)         'CLASS STRUCTURE RECORD
    macsi(mlist,b,2)      'DEFAULT VALUES LIST
    '
    if wmx>w then w=wmx   'MAX SIZE FOR UNIONS
    roundupc(w,mps)       'ROUND UP TO NEAREST MAX PRIMITIVE SIZE
    maco(b,1)=w           'LENGTH OF STRUCTURE
    if ctbl then
      maco(b,2)=me        'INTERNAL VIRTUAL TABLE INDEX
    end if
    maco(b,3)=vtp         'VIRTUAL TABLE FLAGS (atx)
    maco(b,5)=mps         'MAX PRIMITIVE SIZE
    '
    'mps=0 when the structure is marked as packed
    '
    'SOURCE LISTING
    '
    if vew>0 then
      appendt(cr+"skip"+sp+"TYPE: "+macso(b,0)+cr+cr+macso(b,1)+cr+"END TYPE"+ep)
    end if
    '
    'VIRTUAL TABLE BUILDER
    '=====================
    '
    if ctbl then
      '
      'INFER BASE ADDRESS OF VFT
      '
      c=maco(b,4)
      a=lclv
      '
      'STATIC VFT BUILDER TO GO AT BOTTOM OF METHODS BLOCK
      '
      if a then staticvars()
      '
      if len(buil) then
        buil="lea "+qecx+cm+memreg(regs,aoff)+cr+buil+cr
      end if
      '
      wm=""
      macsi("._mt_"+cr+tbls+buil,b,3)
      '
      'DECLARE THE VACANT VIRTUAL FUNCTION TABLE IMMEDIATELY AFTER CLASS
      '
      w1="sys "+macso(b,0)+"_table("+str(c)+")"
      vars(w1)
      '
      if a then localvars()
      '
    end if
    '
    'INITIAL ASSIGNMENT OF MEMBER VALUES
    '===================================
    '
    'hiex+="def "+macso(b,0)+"_init"+cr+vlist+"end def"+cr
    'rps=1
    '
end sub




'-------------------------------------------------
sub CaptProcHead(byref s as string,byref i as sys)
'=================================================
  dim as sys a,c
  dim as string w1
  do
    skiplspace(s,i)
    if ise(ascn) then
      c=i : nextinstruct(s,i)
      if ascn<>lbr then
        i=c : exit do
      end if
    end if
    if (ascn=123)or(ascn=61)or(ascn=sr1) then
      exit do 'FUNCTION .. {}   FUNCTION .. =
    elseif (ascn=lbr) then
      if a then
        exit do 'assume start of body
      end if
      capturi(s,1,1,i)
      a=1 'flag prototype capture
      continue do
    else
      w1=tword(s,i) 'EAT WORD
    end if
  loop
end sub


'--------------------------------------------------------------------------
sub CaptProcBody(w1 as string,byref s as string , i as sys, byref d as sys)
'==========================================================================
  dim as string w2
  dim as sys nl
  '
  d=0
  '
  'LOOKAHEAD FOR BODY CONTAINED BY {..}
  '------------------------------------
  '
  nextinstruct(s,i)
  '
  if ascn=123 then
    capturi(s,1,1,i)
    endline(s,i) : d=i+2
    exit sub
  elseif ascn=61 then
    endline(s,i) : d=i+2
    exit sub
  end if
  '
  'SPECIAL BLOCK CAPTURE
  '---------------------
  '
  do
    w2=tword(s,i)
    '
    if w2="" then
      exit do
    elseif w2=w1 then 'INNER BLOCKS OF SAME CONSTRUCT
      if (ascn>96)and(ascn<123)and(instrword(" and or xor ",wordahead(s,i))=0) then
        if w2="method" then
          exit do 'NEW METHOD FOUND SO ASSUME THIS ONE IS ONLY A HEADER
        end if
        'OTHERWISE:
        'SUB/FUNCTION INSIDE A SUB/FUNCTION ETC
        if w1="sub" then
          if issub(s,i)=0 then endline(s,i) : continue do
        end if
        'RECURSE
        do
          if (isb(ascn)<>0)or(iss(ascn)<>0) then exit do else w2=tword(s,i)
        loop
        if ascn=lbr then captprochead(s,i)
        captprocbody(w1,s,i,d)
        if d then i=d
        d=0
      end if
    elseif w2="exit" then
      w2=wword(s,i) 'SKIP
    elseif (w2="end")and(isxn=0) then
      w2=tword(s,i)
      if w2="" then exit do 'UNEXPECTED END OF PROGRAM
      if w1=w2 then
        endline(s,i) : if ascn=13 then i+=2
        d=i : exit do 'CONFIRMED BODY NOT JUST HEADER
      end if
    elseif ascw=35 then 
      if left(w2,3)="#if" then metaskip(s,i,2) 'METABLOCK
    elseif (ascw=lbr)or(ascw=123) then
      i=swd : capturi(s,1,1,i) 'SKIP (..) {..}
    elseif isc(ascw) then
      endline(s,i)
    end if
  loop
  '
end sub
 


'------------------------------------------------------------------------------------------
sub makeheaders(byref s as string, byref w4 as string, byref w3 as string, byval mo as sys)
'==========================================================================================
  '
  '  mo=1: #LOOKAHEAD TO BUILD FORWARD DECLARATIONS
  '  mo=2: SCAN THROUGH COMBI CLASS BLOCK TO BUILD CLASS AND METHODS BLOCKS 
  '
  '  s  returns main body section
  '  w4 returns virtual / static body section
  '  w3 returns defined function / method code
  '
  dim as sys a,b,c,d,e,f,i,m,idt,vt
  dim as string w1,w2,w5,w6,wm,lns
  i=1 : wm=s : w3="" : w4="" : e=i
  '
  'replacecolonscrs(s) ' : ' with crs
  do
    if mo=1 then nextinstruct(s,i) else skiplspace(s,i)
    a=0
    if ascn<=13 then
      a=1
    elseif ascn=58 then
      a=1
      i+=1
    end if
    w1=tword(s,i)
    if lenw=0 then exit do
    if a then e=swd
    if ascw=rbr then exit do 'INSIDE A SCOPE
    '
    '
    'COMMENTS
    '
    if isc(ascw) then
      d=swd : e=swd : endline(s,i)
      if ascn=lnm then
        lns=mid(s,d,i-d+2) 'prior line number
      end if
      '
      i+=2
      if mo=2 then mid(s,d)=space(i-d) : e=i 'blank out
      continue do
    end if
    '
    '
    'SKIP QUALIFIER WORDS
    '
    if mo=1 then
      if instrword(" leaf ",w1) then
        w1=tword(s,i)
      end if
    end if
    '
    if w1="virtual" then
      mid(s,swd)=space(7) : vt=1
      continue do
    end if


    idt=0
    mp=lookupm(w1)
    if mp then
      if (maco(mp,0)=-18)or(maco(mp,0)=-20) then
        expandm(s,i,mp) : wm=s : continue do
      end if
      idt=identype(w1)
    end if
    '
    if mo=2 then
      '
      if ascw=47 then
        if ascn=92 then '/\
           s=wm : w3="" : w4="" : exit do  'RESTORE ORIGINAL : (SEPARATE METHODS BLOCK OR EXTERNAL)
        end if
      end if
      '
      if ascn=61 then goto classign
      '
      '
      'INHERIT OR MACRO EXPANSION
      '--------------------------
      '
      a=0
      if idt>=htyp then
        if ascn<>42 then a=1
      'elseif instrword(" static of from has incl ",w1) then 
      elseif instrword(" of from has incl ",w1) then 'members removed
        if expandm(s,i,0) then wm=s : continue do
        a=1
      end if
      '
      if a then
        '
        'CAPTURE IN TOP SECTION (FOR LATER SPLITTING INTO VIRTUAL AND BODY)
        '
        endline(s,i) : i+=2
        w4+=mid(s,e,i-e)
        mid(s,e)=space(i-e) 'blankout
        e=i
        continue do
      end if
      '
      '
      a=ascn
      '
      if ise(a) then
        m=i
        nextinstruct(s,m) : a=asc(s,m)
        if a=123 then i=m
        skiplspace(s,i)
      end if
      '
      'NESTED TYPE
      '
      if a=123 then
        c=swd : capture(s,i,i,m) : skiplspace(s,i)
        e=i : continue do
      end if
    end if 'mo=2
    '
    '
    'BODY ELEMENTS?
    '
    '
    'EXCISE #IF etc
    '--------------
    '
    if ascw=35 then
      md=0 : if mc=-13 then md=maco(mp,3)
      if md>=100 then
        metaco(s,i) : if ert then exit do else continue do
      end if
    end if
    '
    if w1="#byref" then bref=1
    if w1="#byval" then bref=0
    '
    'EXCISE FLAGS
    '------------
    '
    if w1="packed" then
      w3+=mid(s,e,i-e) : w1=tword(s,i) ' follow on for type typdef class
    end if
    '
    'EXCISE BODY BLOCKS
    '------------------
    '
    'except UNION
    '
    if instrword(" ( { def type typedef struct enum ",w1) then
      capturedefs(s,i,m,a,w1)
      if mo=2 then
        w3+=mid(s,e,i-e) : mid(s,e)=space(i-e)
      end if
      e=i : continue do
    end if
    '
    'EXCISE DECLARATIVES ETC
    '-----------------------
    '
    '
    a=0
    'dim' removed
    if instrword(" % ! static declare #def #define ### #view #endv var #byref #byval indexbase #indexbase ",w1) then a=1
    if mo=1 then
      if a=1 then
        endline(s,i) : e=i+2 : continue do
      end if
    end if
    '
    '
    '========
    classign:
    '========
    '
    if ascn=61 then a=1 'ASSIGNMENTS itr array assignments
    '
    if a then
      endcontline(s,i) : endline(s,i) : i+=2 'SKIP LINES ENDING IN  , _ \
      if mo=2 then w3+=mid(s,e,i-e) : mid(s,e)=space(i-e)
      e=i
      continue do
    end if
    '
    'LOOKAHEAD FOR METHOD/FUNCTION/SUB BODY
    '--------------------------------------
    '
    a=0
    '
    if idt then
      f=swd
      isptr(s,i)
      w1=tword(s,i)
      if isc(ascw) then
        endline(s,i) : mid(s,swd)=space(i-swd) 'blank out comment
      elseif ascn=lbr then
        if mo=2 then
          a=3 'TREAT AS C STYLE METHOD
        else 'mo=1
          a=10 'TREAT AS C STYLE FUNCTION
        end if
        swd=f
        i=swd
      else
        endline(s,i) 'NOT DECLARATION OF PROCEDURE
      end if
    elseif ascn=lbr then
      'NOT A PROTOTYPE
      capture(s,i,i,m)
      skiplspace(s,i)
    else
      a=dic(" function 1, sub 2, method 3, macro 4, ",w1)
      if a=2 then
        if issub(s,i)=0 then a=0 'EXCLUDE ASM SUB
      end if
    end if
    '
    if a then
      '
      c=swd : d=0 : f=i
      if mo=1 then e=c
      CaptProcHead(s,i)
      '
      'B NOW INDEXES BOUNDARY OF PROTOTYPE
      '
      if a<>5 then CaptProcBody(w1,s,i,d)
      '
      w1=mid(s,e,i-e) 'PROTOTYPE
      '
      if mo=1 then 'BUILDING FORWARD DECLARATIONS
        if (a<=2) then
          w4+="! "+w1+cr 'BASIC DECLARATION

        elseif a=10 then
          w4+=w1+cr      'C DECLARATION
        end if
        if d then i=d
      end if
      '
      if mo=2 then
        if a<=3 then
          w4+=w1+cr
        end if
        if d=0 then
          if a=3 then
            mid(s,e)=space(i-e) 'OMIT METHOD HEADER FROM BODY
            if vt then
              w3+=lns+w1+"{}"
            end if
          end if
        else 'd>0 body present
          w3+=lns+mid(s,c,d-c)  'CAPTURE WHOLE PROCEDURE EXCLUDING QUALIFIERS
          mid(s,e)=space(d-e)   'OMIT WHOLE METHOD/FUNCTION/SUB AND QUALIFIERS
          i=d
        end if 'd
      end if 'mo=2
      '
      vt=0
      e=i 'UPDATE POSITION FOR NEXT ITEMS
      '
    end if
  loop
  '
  if mo<>2 then exit sub
  '
  'STRIP LEADING SPACES AND EMPTY LINES
  linesltrim(s)
  linesltrim(w3)
  linesltrim(w4)
  '
  '
end sub




