


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


'---------------------------------------------------------------------
function multiassign(s as string, byref i as sys, tp as sys) as string
'=====================================================================
  dim as sys a
  dim as string w1,w2,w3
  if ascn<>123 then
    i+=1 '<= =>
  end if
  if vew>0 then
    w1="'MULTIASSIGN =>"+cr
  end if
  if len(epfx) then 'ARRAY INDEXING
    a=instrevn(-1,epfx,"mov ")
    psg=left(epfx,a-1)+medi+qesi+cr 'BYPASS TEMP VAR
    epfx=""
  else
    psg	+=leaedi(wsg)
  end if
  if cpuw=8 then w1+="sub rsp,8"+cr 'MAINTAIN STACK ALIGNMENT
  w1+=psg+operi(4,cpuw,qedi)
  asgm=1
  asgo=0 
  asgi=maco(mp,1)
  asgj=0
  asgk=0
  asgl=0
  '
  if tp>=htyp then
    asgs=macso(tp-htyp,1)
  elseif tp>&h100 then
    '
  elseif tp>=&he0 then
    w2=mid(macso(tp-htyp,1),3,3)
    if w2="bp-" then asgl=1 'LOCAL(ELSE GLOBAL) ARRAY
  end if
  '
  nextinstruct(s,i)
  '
  if (tp>=htyp)and(ascn=123) then
    w2=macso(tp-htyp,2) 'TYPE DEFAULT EXPRESSIONS
    if len(w2) then
      i+=1 : skiplspace(s,i)
      a=subsas(s,i,"{,"+w2+"}","",1)
      skiplspace(s,i)
    end if
  end if
  '
  'skip left bracket
  asgb=0
  if (ascn=lbr)or(ascn=123) then
    if ascn=lbr then asgb=rbr else asgb=125
    i+=1
    nextinstruct(s,i)
  end if
  '
  'READ IN DATA SERIES
  '
  'itr pz linkage by zstring ptr array?
  '
  w2=express(s,i,tp)
  if cpuw=4 then w3="add esp,4" else w3="add rsp,16" 'STACK RELEASE
  if len(w2) then return w1+w2+w3+cr
  '
end function


'--------------------------------------------------------
sub dataset(byref s as string, byref i as sys, tp as sys)
'========================================================
  dim as sys a,b,n
  dim as string w2,w3,w4,w5
  w2=typename(tp)
  w3=newTmpName()
  if wordahead(s,i+1)="}" then
    i=nwd
    vars(w2+" "+w3)
    goto ndataset
  end if
  a=i : elct=0 : capts(s,i)
  staticvars()
  vars(w2+" "+w3+"["+str(elct+ixb)+"]")
  i=a : skiplspace(s,i)
  w4=wsg : w5=psg : b=mp
  mp=me-1 : wsg=macso(mp,1) : psg=""
  n=nst
  nst=0
  epfx+=multiassign(s,i,tp)
  nst=n
  wsg=w4 : psg=w5 : mp=b
  '
  ndataset:
  inserts(s,w3,i)
  typ=tp
  skiplspace(s,i)
end sub


'--------------------------------------------------------
function isexpr(byref s as string, byval i as sys) as sys
'========================================================
'DETECT OPERATORS
dim as sys b,p,n
dim as string wr
skiplspace(s,i)
do
  select case ascn
  case 9       :         'TAB
  case 0 to 13 : exit do 'END OF LINE
  case 44      : exit do ','
  case 40      : n+=1    '('
  case 91      : n+=1    '['
  case 123     : return -2 '{...'
  case 41      : n-=1 : if n<0 then exit do ')'
  case 93      : n-=1 : if n<0 then exit do ']'
  case sr1     : exit do ' STATEMENT SEPARATORS
  case sr2     : exit do
  case ct1     : exit do 'COMMENT MARKS
  case ct2     : exit do
  end select
  wr=aword(s,i)
  b=swd+1
  p=identop(s,swd,b)
  if p then return -1
loop
end function

'

'--------------------------------------------------------------------------
function expandexpr(byref s as string, byref i as sys, typa1 as sys) as sys
'==========================================================================
'
dim as sys a,b,p,m,n,bg,ndo
dim as string wr,wt,w1,w2,w3,w4,w5
static as sys st(15)
skiplspace(s,i)
st(n)=i
bg=i
do
  select case ascn
  case 9    :         'TAB
  case 0    : exit do 'END OF STRING
  case 10   : if n=0 then exit do 'END OF LINE
  case 13   : if n=0 then exit do 'END OF LINE
  case 44   : if n=0 then exit do ','
  case 40   : n+=1 : st(n)=i '('
  case 91   : n+=1    '['
  case 123  : n+=1    '{'
  'PF IS SET TO 1 FOR CAPTURING WHOLE FUNCTION CALL
  case 41   : n-=1 : if n<0 then exit do ')'
  case 93   : n-=1 : if n<0 then exit do ']'
  case 125  : n-=1 : if n<0 then exit do '}'
  case 58   : if n=0 then exit do        ':'
  case sr1  : exit do ' STATEMENT SEPARATORS
  case sr2  : exit do
  case ct1  : exit do 'COMMENT MARKS
  case ct2  : exit do
  case else :
    wr=aword(s,i)
    if ascn=63 then 'TEST FOR IIF EXPRESSION
      ndo=st(n)
      if ndo>bg then w1=mid(s,bg,ndo-bg)
      w2=mid(s,ndo+1,i-ndo-1)
      i+=1 : w3=captsx(s,i)
      if ascn=58 then
        i+=1 : w4=captsx(s,i)
      end if
      if ndo then i+=1 'SKIP ')'
      a=typa1
      if a<=0 then 'DETERMINE TYPE FROM EXPRESSION
        wt=w3
        nsto=1 : wt=express(wt,1,0) : jn=0 : epfx="" : nsto=0
        if isbstr(typg) then typg+=32 'auto dynamic string
        a=typg
      end if
      w5=NewTmpVar(typename(a)) 'VARIABLE TO HOLD ASSIGNMENT
      hiex+="if "+w2+" then"+cr+w5+"="+w3+cr
      if len(w4) then hiex+="else"+cr+w5+"="+w4+cr
      hiex+="end if"+cr
      inserts(s,w1+w5,i)
      bg=i
      skiplspace(s,i)
      rps=2
      continue do
    end if 'ASCN=63
    if isx(ascn) then exit do
    if instrword(" _ + - * / \ & | < = > ! ^ ~ and or xor not ",wr) then
      nextinstruct(s,i) : continue do
    elseif instrword(" as at then else elseif end to step ",wr) then
      i=swd : skiplspace(s,i) : exit do
    end if
    continue do
  end select
  i+=1 : skiplspace(s,i)
loop
i=bg : skiplspace(s,i)
return asc(s,i)
end function


'----------------------------------------------------------------------------------
function precedence(byref s as string, byref i as sys, byval bsn as sys ) as string
'==================================================================================
  '
  static as sys ppl(31),pk(31)
  dim as string uu,u,wr,wk,w1
  dim as sys a,b,c,d,e,f,k,nl,pp,twd,alb,ma,ido,le,ngs,qp,oqq
  '
  skiplspace(s,i) : if isxn then exit function
  nl=bsn
  '
  do
    c=i : skipspace(s,i)
    '
    '
    wr=tword(s,i)
    '
    oqq=oq
    '
    if ngs then
      ngs=0
      if isn(ascw) then
        u+="-"
      else
        a=swd
        if (isb(ascw))or(isb(ascn)) then
          if ascw=40 then i=swd 'NESTED EXPRESSION 
          captarray(s,i)
          wr=mid(s,a,i-a) 'NESTED EXPRESSION / ARRAY / FUNCTION
          skiplspace(s,i)
        end if
        if ido then
          inserts(s,"("+wr+" _neg ) ",i)
        else
          inserts(s,wr+" _neg ",i)
        end if
        continue do
      end if
    end if 'ngs
    '
    'if lenw=0 then exit do
    '
    'PRE ++ --
    '
    if ascw=ascn then
      if (ascw=43)or(ascw=45) then
        u+=string(2,chr(ascn)) : i+=1 : continue do
      end if
    end if
    '
    '
    'TERMINATOR WORDS AND SYMBOLS
    'ASSEMBLER OPERANDS
    '
    if lenw>1 then
      if instrword(" then else to ",wr) then
        i=c : exit do
      end if
    else
      a=(k=0)or(ido)
      select case ascw
      case 0 to 31 : i=c : exit do
      case 38  : if qp<>1 then u+="& " : continue do '&' address
      case 42  : if a then u+="*" : continue do '*' pointer
      case 43  : if a then          continue do '+' positive (ignore)
      case 45  : if a then ngs=1  : continue do '-' negative num/var/function
      case ct1 : i=c : exit do
      case ct2 : i=c : exit do
      case sr1 : i=c : exit do
      case sr2 : i=c : exit do
      case 123 : i=c : exit do
      case 125 : i=c : exit do
      case 91
        '
        'ASSEMBLER OPERANDS/ARRAY INDEX SKIP
        '
        a=instr(i,s,"]")
        if a then i=a+1 : skiplspace(s,i)
        '
      end select
    end if
    '
    ido=0
    '
    '
    qp=1
    twd=len(u)+1        'NEXT BUFFER POSITION
    a=i-c               'NUMBER OF SPACES
    u+=mid(s,c,a)       'APPEND SPACE BEFORE NEXT WORD
    k=twd+a             'INCLUDE SPACING IN BUFFER POSITION
    '
    select case ascw

    case 44 
      a=nl-bsn 'number of closing brackets
      uu+=string(alb,"(")+left(u,twd-1)+string(a,")")+"," 'CLOSE ALL BRACKETS BEFORE COMMA AND RESET PP & DD
      k=0 : u="" : nl=bsn : pp=0 : alb=0
      continue do
    case 40 '( 
      if ascn<>rbr then
        u+=precedence(s,i,nl+1) 'RECURSE INSIDE BRACKETS
      else
        u+=tword(s,i) 'EMPTY BRACKET PAIR
      end if
      '
      if iss(ascn) then
        exit do
      else
        continue do
      end if
    case 41 ')
      exit do  'TERMINATE INCLUDING BRACKET
    end select
    '
    'IDENTIFY OPERATOR
    '
    b=i : a=0
    '
    if ascw<>91 then
      a=identop(s,swd,i)
      skiplspace(s,i)
      if a then
        if asc(s,i)=61 then exit  do ' assignments combo operator += -= *= /= and=
        qp=a
      end if
    end if
    '
    if ascw=61 then
      if a<=2 then exit do '= is an assignment
    end if
    '
    'IS AN OPERATOR (prl=precedence level)
    '
    if a>2 then
      '
      ido=a 'hold operator code
      '
      le=i-b
      if le>0 then
        u+=mid(s,b,le)
        k+=le'extra char operators
      end if
      '
      'AUTO LINE CONTINUATION
      '
      if ise(ascn) then
        nextinstruct(s,i) : u+=" "
      end if
      do
      '
      if nprec then
        b=prl     'no precedence evaluation
      else
        b=ppl(nl) 'precedence level
      end if
      '
      if prl>b then
        '
        'HIGHER PRECEDENCE: INSERT '(' AFTER PREVIOUS OPERATOR
        '-----------------------------------------------------
        '
        if pp then
          u=left(u,pk(nl)-1)+"("+mid(u,pk(nl))
          k+=1  'char buffer position
          nl+=1 'next stack position
        end if
        '
      elseif prl<b then
        '
        'LOWER PRECEDENCE: INSERT ')' BRACKET BEFORE OPERATOR
        '----------------------------------------------------
        '
        if (nl>bsn)or(pp<>0) then
          u=left(u,twd-1)+")"+mid(u,twd)
          k+=1   'CHAR BUFFER POSITION
          twd+=1 'eg: if (a=b)or..
        end if
        '
        if nl>bsn then
          nl-=1              'previous stack position (release current)
          continue do        'for possible multiple ')' closures
        else
          if pp then alb+=1  'add to starting left bracket count
        end if
        '
      end if 'precedence bracket inserts
      '
      'itr imperfect solution for mixed bool exprs and exprs containing div
      if (nl=0)or(cnd=0) then 'implied prl=b 'no nesting
        if ido=47 then divi=1
      end if
      'if ido=47 then divi=1 'always use float division for '/'
      '
      exit do
      loop
      '
      ppl(nl)=prl  'stack record precedence level
      pk(nl)=k     'stack record position following operator
      pp=a         'flag 1 or more operators processed
      '
    else 'NOT AN OPERATOR
      '
      if iss(ascn)  then
        exit do 'END OF STATEMENT
      elseif ascn=asc(s,i+1) then
        if (ascn=43)or(ascn=45) then
          u+=string(2,chr(ascn))+" " : i+=2  'POST ++ --
        end if
      end if
      ' 
    end if
  loop
  '
  'CLOSE REMAINING BRACKETS AND RETURN TO PREVIOUS LEVEL
  '
  '
  'itr check for unbalance brackets?
  '
  function=uu+string(alb,"(")+u+string(nl-bsn,")")
  '
end function


'-----------------------------------------------------------------------------
function GetTerm(byref s as string, byref i as sys, byref mi as sys) as string
'=============================================================================
'
'GET WORD PLUS ANY BRACKETED PARAMS
'
dim as string wt
dim as sys a,c,m
skiplspace(s,i)
c=i
wt=aword(s,i)
mi=0
a=ascn
if isb(ascn) then
  if ascn=123 then
    mi=c-i-1 'USE NEG SIGN TO LOCATE '{..}
  end if
  do 'CAPTURE MULTIPLE: a().b[].c 
    if isb(ascn) then
      if ascn=40 then mi=i-c+1 'LOCATION OF LAST '(..)
      capture (s,m,i,0)
      if asc(s,i)=46 then
        wt=aword(s,i)
        continue do
      end if
    end if
    exit do
  loop
  wt=mid(s,c,i-c)
  skiplspace(s,i)
end if
return wt
end function

'--------------------------------------------------------------------
function findop(byval ht as sys, wn as string, byref b as sys) as sys
'====================================================================
dim as sys a,u
dim as string wr,ts
u=ht-htyp
b=0
ts=macso(u,0) 'TYPE NAME
a=lookupm(ts+"_op") 'OPERATIONS GROUP NAME
if a then
  wr=macso(a,1)
  b=instr(wr,"."+qu+wn+qu) 'LOCATE OPERATOR / FUNCTION MACROMEMBER
  if b=0 then a=0
end if
if a=0 then
  a=lookupm(wn+"_op")
  if a then
    if maco(a,0)=-20 then b=-1 else a=0 'HIGHER MACRO
  end if
end if
return a
end function


'----------------------------------------------------------------------------------------------
function TypeHigherExpr(byref s as string, byval i as sys, wn as string, byref r as sys) as sys
'==============================================================================================
'CHECK TYPE OF FIRST OPERAND
'BYPASS OUTER BRACKETS
dim as sys a,l,j,m,n,t,u,w
dim as string wr,wt
r=0
l=lenw
n=ascn
w=ascw
'SKIP LEFT BRACKETS
do
  skiplspace(s,i)
  if ascn=lbr then i+=1 else exit do
loop
wr=aword(s,i)
if (ascn=40)or(ascn=91) then
  j=i
  capture(s,0,j,0)
  if asc(s,j)=46 then
    'assume primitive member?
    'itr check for dot macro invocation
    goto nthe
  end if
end if
if isa(ascw)=0 then goto nthe
t=lookupm(wr)
if t then
  t=maco(t,0) 'itr derived types
  if t>htyp then
    if len(wn)=0 then function=t : goto nthe 'NO PROC/MACRO NAME GIVEN
    u=findop(t,wn,a) 'CHECK FOR OPERATIONS GROUP MACRO
    if a then
      if a<0 then
        r=identype(macso(u,2)) '109
        function=t : goto nthe
      end if
      a+=len(wn)+3
      wr=macso(u,1)
      macromembertype(wr,a,r) 'THE TYPE RETURNED BY THE MACROMEMBER, IF SPECIFIED
      function=t : goto nthe 'T IS THE MAIN TYPE
    end if
  end if
end if
'
nthe:
lenw=l
ascn=n
ascw=w
end function


declare function HigherExpr(byref s as string, byref i as sys, ht as sys, byref hx as string) as string


'-----------------------------------------------------------------------------------------
sub ParamHigherExpr(byref wn as string, byref wm as string, mi as sys, byref hx as string)
'=========================================================================================
  dim as sys a,b,r,t
  dim as string wa,wt
  hx=""
  wm=aword(wn,1) 
  if dtf then wm=mid(wm,dtf+1)
  a=mi+1 'PARAMS FOLLOWING BRACKET
  b=mi
  'SUPPORT MULTIPLE PARAM EXPRESSIONS
  do
    'SUPPORT MIXED PRIMITIVES AND HIGHER TYPES
    t=TypeHigherExpr(wn,b,"",r)
    if t then
      wa=HigherExpr(wn,a,t,wt) 'BUT PRIMITIVES ARE PASSED OVER
      if len(wa) then
        hx+=wt
        wn=left(wn,b)+wa+mid(wn,a) 'REPLACE EXPRESSION WITH TEMP VAR
        a=b+len(wa)+1 'NEW POSITION OF DELIMITER
      end if
    else
      capts(wn,a)
    end if
    if asc(wn,a)=44 then
      b=a : a+=1
      continue do 'MORE PARAMS
    end if
    exit do
  loop
end sub

'-----------------------------------------------------------------------------------------------
sub MixHigherExpr(byref s as string, byref i as sys , byref wt as string , tp as sys, tq as sys)
'===============================================================================================
dim as sys a,b,m,p
dim as string wn,wv,hx,owb
rps=1
p=op
owb=owa
wn=higherexpr(s,i,tp,hx) 'RETURNS VAR NAME, AND HX CONTAINS EXPRESSION SOURCE
a=ascn
b=op
wv=mword(wn,1) 'GET TRANSLATED OPERAND
op=b
if (a=rbr)and(nst>0) then
  if b>1 then m=mp else m=-mp
  st(nst-1).g=m : hix=1
end if
if (tq<>0)and(tq<htyp) then
  wt+=operi(op,tq,wv)
  typ=tq
end if
hiex+=hx
if len(wt) then hiex+=storecode(wt)+cr :  'STORES WT CODE FOR LATE INSERTION AND CLEARS WT
skiplspace(s,i)
op=p
owa=owb
end sub


'----------------------------------------------------------------------------------------------
function HigherExpr(byref s as string, byref i as sys, ht as sys, byref hx as string) as string
'==============================================================================================
'OPERATING ON DECOMPOSED EXPRESSIONS: A=B+C  A=F(...)
dim as sys    a,b,e,m,r,t
dim as sys    le,pp,mi,mc,mh,mt,ml,ng,sav
dim as string hz,wa,wc,wm,wn,wo,wr,wt,wh,ts,tt,ms
hx=""
'PRIMITIVES PASS THRU
if ht<htyp then
  wa=NewTmpVar(typename(ht))
  hx+=captsx(s,i) 'REST OF STATEMENT
  goto nhexpr
end if
'
ts=macso(ht-htyp,0) 'TYPE NAME
ms=ts+"_op."
if findop(ht,"register",0) then sav=1
'
skiplspace(s,i)

if ascn=45 then
  ng=1 : i+=1 : skiplspace(s,i) 'CAPTURE NEGATIVE
else
  ng=0
end if
'
do
  wn=""
  skiplspace(s,i)
  e=(ascn=41)or(ascn=44)
  if (e<>0)and(sav=0) then 'PARAMS , )
    wa=wc 'RETURN ACCUM
    goto nhexpr 'LEAVE
  end if
  if (e<>0)or(isendofexpress(s,i)) then
    if cnd then wa=wc : goto nhexpr 'CONDITIONAL 
    if (instr("!==<><=>=",wo)>0) then ts="bool"
    if(sav<>0)and(e<>0)then wa=newtmpvar(ts) else wa=osg
    hz+=ms+qu+"save"+qu+"("+wa+cm+wc+")"+cr 'SAVE or COND
    goto nhexpr 'LEAVE
  end if
  'OTHERWISE CHECK FOR OPERATOR
  b=i : i+=1
  pp=identop(s,b,i)
  if pp then
    wo=mid(s,b,i-b)
    skiplspace(s,i)
  else
    i=b 'STEP BACK IF NOT AN OPERATOR
   if ng then wo="neg" else wo="load"
   wc=newtmpvar(ts)
  end if
  ng=0
  'CHECK FOR NESTED EXPRESSIONS
  if ascn=lbr then '+(V*W)
    i+=1 'SKIP OPENING BRACKET '('
    wn=wa
    wa=HigherExpr(s,i,ht,wt) 'RECURSE
    i+=1 'SKIP CLOSING BRACKET ')'
    hx+=wt
    mi=0
  else
    wn=getterm(s,i,mi)
    if mi=0 then wa=wn
  end if
  '
  'MULTIASSIGN OR MACRO FUNCTION
  if mi then
    wm=aword(wn,1)
    if mi<0 then
      wa=NewTmpVar(wm)
      hx+=wa+"="+mid(wn,-mi)+cr 'MULTIASSIGN {..} INSERT RETURN NAME
    else 'mi>0 MACRO FUNCTION
      t=TypeHigherExpr(wn,mi,wm,r) 'TERM, INSERTPOINT I TYPE
      if r=0 then r=ht 'USE MAIN TYPE
      ParamHigherExpr(wn,wm,mi,wt) 'TERM, WORD, INSERTPOINT PARAMS
      hx+=wt 'RESOLVED PARAMS
      if (r<>ht) then
        wa=NewTmpVar(typename(r))
      else
        wa=NewTmpVar(ts)
      end if
      findop(ht,wm,b)
      if b>=0 then
        tt=ms+qu+wm+qu
      else
        tt=wm+"_op" 'MAIN NAME
      end if
      hx+=tt+"(/"+wa+cm+mid(wn,mi+1)+cr 'INVOKE FUNCTION
      if r<htyp then
        goto nhexpr 'HIGHER EXPRESSION WITH PRIMITIVE OUTPUT VARIABLE
      end if
    end if 'mi>0
  end if 'mi
  '
  'WO: OPERATOR
  'WA: ROPERAND
  hz+=ms+qu+wo+qu+"("+wc+cm+wa+")"+cr 'INVOKE OPERATOR
  ng=0
loop
'
nhexpr:
op=pp 'EXPOSE OPERATOR
hx+=hz
if (pp<=1)and(ng=0)and(mi=0) then typ=ht else typ=maco(me-1,5)
return wa
end function


'-------------------------------------------------------------
sub metaskip(byref s as string, byref i as sys,byval f as sys)
'=============================================================
  '
  'destructive # skip
  '
  dim as sys a,b,c,d
  dim as string wr
  b=i
  wr=tword(s,i) 'ALWAYS SKIP FIRST WORD
  do
    if ascn=0 then exit do 'PREMATURE END OF STRING TREATED AS TERMINATOR
    '
    wr=tword(s,i) : if isc(ascw) then endline(s,i) : continue do
    '
    if ascw=35 then
      '
      '------------------
      'SAME NESTING DEPTH
      '------------------
      '
      if d<=0 then 
        '
        'f=0: BLANK OUT TILL THE NEXT #ELSE / #ELSEIF / #ENDIF
        'f=1: BLANK OUT TILL #ENDIF
        'f>1: NO BLANKING (SKIP TO #ENDIF ONLY)
        '
        if f=0 then
          if (wr="#else")or(wr="#elseif") then
            '
            'BLANK OUT THE PRIOR CODE WHICH FAILED THE CONDITION
            '
            mid(s,b)=space(i-b)
            '
            if wr<>"#else" then
              '
              'REPLACE (#IF #ELSEIF) WITH #IF
              '
              i-=4 : mid(s,i)="#if " 'PATCHED BACK INTO CODE STREAM
              '
            end if
            '
            exit sub 'DONE
            '
          end if '#ELSE ETC
          '
        end if 'D=0
        '
        if wr="#endif" then exit do
        '
      end if
      '
      'ADJUST DEPTH
      '------------
      '
      if left(wr,3)="#if" then d+=1 'INCREASING NESTING DEPTH
      '
      if wr="#endif" then d-=1 'DECREASING NESTING DEPTH
      '
    end if
  loop
  '
  if f<=1 then mid(s,b)=space(i-b) 'BLANK ALL
  '
  skiplspace(s,i)
  '
end sub


'----------------------------------------------------------
function cword(byref s as string, byref i as sys) as string
'==========================================================
  dim as string wr
  wr=tword(s,i)
  if (ascw=37)or(ascw=36) then
    mid(s,swd)=" " : wr=tword(s,i) ' IGNORE % $ PREFIX
  end if
  function=wr
end function


'----------------------------------------------------------
function sword(byref s as string, byref i as sys) as string
'==========================================================
  dim as sys a
  a=instr(i,s,sq)
  if a then function=mid(s,i,a-i) : i=a+1
end function



'---------------------------------------------------------
function sval(byref s as string, byref i as sys) as double
'=========================================================
  dim as sys a
  a=instr(i,s,sq)
  if a then function=wval(mid(s,i,a-i)) : i=a+1
end function



'------------------------------------------------------------------------------------------------
function metaval(byref s as string, byref i as sys,byref wa as string, byval tp as sys) as double
'================================================================================================
  '
  dim as sys    a,k,n,t,o,r,igb,rcr,wtal,wtaf,opr
  dim as double b,v,w
  dim as string w1,w2,wr,wp,ws
  dim as sys    m=i,j=instr(i,s,cr)
  '
  if j=0 then j=len(s)+1
  '
  'INSERT BRACKETS TO ESTABLISH OPERATOR PRECEDENCE
  '
  'if ascn=lbr then
  '  i+=1 : igb=1  'IGNORE OUTER BRACKETS
  'end if
  '
  if nprec=0 then
    met=1 : w1=precedence(s,i,0) : met=0
    inserts(s,w1,i)
  end if
  '
  wa=""
  opr=1 'PRELOAD OPERATOR
  ascw=0
  skiplspace(s,i)
  '
  if (ascn=45)or(ascn=43) then
    opr=0
  end if
  '
  do
    '
    'OPERATIONS
    '==========
    '
    w=0
    '
    ' -(v)
    if ascn=95 then 'neg expression 
      if wordahead(s,i)="_neg" then
        i=nwd : v=-v : skiplspace(s,i)
        continue do
      end if
    end if
    '
    if opr=1 then
      wr="" 'LOAD OPERAND
    else
      wr=tword(s,i) 'GET OPERATOR
      opr=identop(s,swd,i)
      if opr=0 then
        if ascw=61 then
          opr=101 'COMPARE '='
        elseif ascw=lbr then '((.. MULTIPLE BRACKETS
          opr=1
          i=swd : skiplspace(s,i)
        end if        
      end if
    end if
    '
    if (opr<>0)or(ascw=rbr) then
      '
      'UNSTACK OR GET NEXT OPERAND
      '---------------------------
      '
      k=1
      if ascw=rbr then
        w=v
        n=sval(ws,k)
        v=sval(ws,k)
        opr=asc(ws,k)
        k+=2
        ws=mid(ws,k)
        if n then w=not w
        goto metoperate
      end if
      '
      '========================================
      operands: 'recursion expansion loop point
      '========================================
      '
      rmwops:
      '
      wp=cword(s,i)
      '
      if ascw=92 then
        continue do '\' C style line continuation
      end if
      '
      if isq(ascw) then
        wa+=noquotes(wp)  ' ACCUMULATE STRINGS
        wtal+=1
      end if
      '
      b=0 : n=0
      '
      'EXAMPLES:
      '---------
      '
      ' IF NOT (...)
      ' IF NOT ISDEF ( X )
      ' OR ISNDEF ( X )
      ' AND NOT (...)
      '
      'NOT ISDEF ISNDEF
      '----------------
      '
      if (wp="not")or(wp="!") then
        n=not n
        wp=cword(s,i)
      end if
      '
      if ascw=lbr then 'METASTACK
        ws=str(n)+sq+str(v)+sq+chr(opr)+sq+ws
        v=0
        n=0
        skiplspace(s,i)
        if (ascn=45)or(ascn=43) then
          opr=0 'PICKUP OPERATOR
        else
          opr=1 'LOAD OPERAND
        end if
        continue do
      end if
      b=dic(" def 1, isdef 1, defined 1, ndef 2, isndef 2, undefined 2, match 3, leftmatch 4, ",wp)
      if b then
        if b=2 then n=not(n) 'OPPOSITE LOGIC
      elseif wp="#str" then
        wtaf=1 : continue do
      elseif wp="#hex" then
        wtaf=2 : continue do
      elseif wp="null" then
        wp="0"
      end if
      '
      if b then
        w=0
        if ascn=lbr then
          i+=1 : r=1 'IGNORE (
          skiplspace(s,i)
        end if
        if nisxn then
          if b>2 then 'MATCH STRING
            w1=noquotes(mword(s,i))
            if ascn=44 then i+=1
            w2=noquotes(mword(s,i))
            if b=4 then w2=left(w2,len(w1)) 'LEFTMATCH
            clcase(w1) : clcase(w2) 'APPLY CASE CONVERSION
            if w1=w2 then w=not w 'TRUE
            goto nvaldone
          end if
          wp=cword(s,i)
          if isa(ascn) then
            mp=lookupm(wp)
            if mp=0 then
              wp=mword(wp,1) : skiplspace(s,i) 'MEMBERS
              if ert then mp=0 : ert=0 : ers="" 'SUPRESS ERRORS
            end if
          else 'symbol number quote
            mp=-1
          end if
          if mp then w=not w 'TRUE
        end if 'nisxn
        '
        nvaldone:
        '          
        if ascn=rbr then
          if r then i+=1'IGNORE )
        end if
        r=0
        if n then w=not w 'INVERT LOGIC
        wp=""
      end if 'b operators
      '
      '
      'CHECK IF LITERAL NUMBER
      '-----------------------
      '
      a=asc(wp)
      if isn(a)or(a=38) then
        wordval(s,swd,i)
        w=dv
        goto metoperate
      elseif isq(a) then
        goto metoperate
      end if
      '
      '
      'CHECK IF SYMBOL
      '---------------
      '
      if len(wp) then
        '
        a=lookupm(wp)
        '
        if a=0 then
          w=0
          if asc(wp)=35 then
            w=getvarptr(wp)
            if w=0 then ert=502 : ers="Can't find Symbol: "+wp : exit do
          else
            if asc(wp)=91 then
              ert=503  : ers="cannot use variable as constant"
            else
              ert=504 : ers="Undefined Symbol: "+wp
            end if
            exit do
          end if
          '
        else
          '
          'ACCEPT $ % DEF #DEFINE MACRO metatypes
          '--------------------------------------
          '
          inserts(s,wp+" ",i)
          a=nl : nl=0
          wp=mword(s,i)
          inserts(s,wp+" ",i)
          nl=a
          rcr+=1 
          if rcr>100 then ert=505 : ers="Recursion suspected in macro expression" : exit do
          goto rmwops
        end if
      end if
      '
      '----------
      metoperate:
      '----------
      '
      wp=""
      b=v
      '
      '-------------------------
      ' V ACCUM   W OPERAND
      '=========================
      '

      select case opr
      case 1  : v=w
      case 33 : v and=w
      case 34 : v or=w
      case 37 : v or=w
      case 35 : v xor=w
      case 74 : v=v shl w
      case 75 : v=v shr w
      case 43 : v+=w
      case 45 : v-=w
      case 42 : v*=w
      case 47 : v/=w
      case 92 : v\=w
      '
      'booleans and/or/xor
      '
      case 71 : v=0 : if (b<>0)and(w<>0) then v=-1
      case 72 : v=0 : if (b<>0)or(w<>0) then v=-1
      case 73 : v=0 : if b<>w then v=-1
      end select
      '
      'comparators
      '
      if (opr>=20)and(opr<32) then
      v=0
      select case opr

      case 20  : if b=w  then v=-1
      case 28  : if b<w  then v=-1
      case 30  : if b<=w then v=-1
      case 21  : if b<>w then v=-1
      case 31  : if b>w  then v=-1
      case 29  : if b>=w then v=-1
      end select
      end if
      opr=0
      '
    end if ' OPERATORS
    '
    '
    '======================================
    checkendost: 'CHECK IF END OF STATEMENT
    '======================================
    '
    skiplspace(s,i)
    '
    if ascn=rbr then
      if ws="" then
        'if igb then
        '  i+=1 : skiplspace(s,i) 'skip outer right bracket
        'end if
        exit do
      end if
    end if
    '
    if (ascn<=32)or(ascn=93)or(ascn=44)or(ascn=sr1) then exit do ' end of [...] , :
    '
    'NEXT OPERATOR OR BRACKET
    '------------------------
    '
    '
  loop ' # EXPRESSION LOOP
  '
  if wtal+wtaf=0 then
    wa=str(v)
  else
    if wtaf then
      if wtaf=1 then
        wa+=str(v)
      elseif wtaf=2 then
        wa+=hex(v)
      end if
    end if
    wa=qu+wa+qu
  end if
  ascw=asc(wa)
  function=v
end function


'---------------------------------------------
sub caseval(byref s as string, byref i as sys)
'=============================================
  dim as sys a
  dim as string w1
  w1=mid(s,swd,5)
  a=instr(2,w1,"'")
  if (a>0)and(a<=4) then
    lenw=a
    i=swd+lenw
    a=asc(w1,2)
    if a=92 then
      a=asc(w1,3)
      select case a
      case &h62 : a=8  '\b back
      case &h6e : a=10 '\n linefeed
      case &h72 : a=13 '\r return
      case &h74 : a=9  '\t tab
      end select
    end if
    w1=str(a) 'translate into byte value
    mid(s,swd)=w1+space(lenw-len(w1))
    ascw=asc(w1)
  else
    endline(s,i) : ascn=13
  end if
end sub


'--------------------------------------------
sub metaco(byref s as string, byref i as sys)
'============================================

  dim as sys a,b,c,d,m,mb
  dim as double v
  dim as string wr,w1,w2,w3,w4,w5,w6,wt

  mb=swd ' START OF BLOCK
  '
  c=md
  '
  '-------------------------
  'HIGH LEVEL '#DEFINE MACRO
  '=========================
  '
  if (md=104)or(md=109) then
    '
    w1=wword(s,i)
    ' 
    'CHECK FOR PARAMS IN BRACKETS
    '----------------------------
    '
    a=0
    '
    if md=109 then 'MACRO
      if ascn<>lbr then
        if nisxn then
          wt=tword(s,i) 'RETURN TYPE
          a=instr(i,s,"(")
          if a then wt+=mid(s,i,a-i) : i=a : ascn=lbr
        end if
      end if
    end if
    if ascn=lbr then
      if md=104 then '#DEFINE ...
        '
        'MUST BE NO SPACE BETWEEN IDENTIFIER AND BRACKET EG: M(A, B, C)
        '
        if i=swd+len(w1) then a=1
        '
      else 'md=109 'MACRO ...
        '
        'OXYGEN MACRO WILL ACCEPT EMPTY BRACKETS ()
        '
        a=1
      end if
    end if
    '
    'IF PARAMETERS WERE DETECTED...
    '
    if a then
      c=i
      capturi(s,m,b,i)
      w3=mid(s,m,b)
      striplineno(w3)
      clcasewds(w3)
      w4="" : b=1
      'FORMAT FOR DEFAULT PARAMS: ,WORD=
      d=instr(w3,"=")
      if d then
        do
          w5=tword(w3,b)
          if lenw=0 then exit do
          if ascn=61 then
            b+=1 : w5+="="
            w5+=captsx(w3,b)
          end if
          if ascn=44 then
            if b<d then w5+="="
            b+=1 : w5+=cm
          end if
          w4+=w5
        loop
        w3=w4
      end if
    else
      w3=""
    end if
    '
    '-------
    nmparam:
    '-------
    '
    skiplspace(s,i)
    '
    '-------
    '#DEFINE
    '=======
    '
    'CHECK FOR C TYPE QUOTE ' ' AND MULTILINE \ ASCII 92
    '
    if md=104 then
      dim as sys cct1,cct2,ciq3
      m=i
      do
        do
          if (ascn=13)or(ascn=10)or(ascn=0) then ascw=0 : exit do
          w2=wrd(s,i)
          if ascw=39 then
            caseval(s,i) 'A'
          elseif ascw=92 then
            exit do '\'
          end if
        loop 'EACH WORD IN LINE
        '
        if ascw<>92 then exit do
        mid(s,swd)=" " : ascn=32 'BLANK OUT `\`
        endline(s,i) : i+=2
        skiplspace(s,i)
      loop 'EACH LINE
      b=i-m
      w2=mid(s,m,b)
      striplineno(w2)
    end if
    '
    'OTHERWISE CAPTURE BLOCK
    '
    '-----
    'MACRO
    '=====
    '
    if md=109 then
      '
      if ise(ascn) then
        a=i
        nextinstruct(s,i)
        if ascn=lbr then
          c=i
          i+=1
          skiplspace(s,i)
          if ise(ascn)=0 then 'DETECT BRACKETED EXPRESSION
            i=c : ascn=lbr
            capturend(s,m,b,i,"macro") 'NOT USING LBR RBR BLOCK
            goto macapture
          end if
        end if
        i=a : ascn=asc(s,i) 'BACKTRACK TO AVOID SINGLE LINE CAPTURE
      end if
      '
      captureb(s,i,m,b,"macro")
      skiplspace(s,i)
      if ise(ascn)=0 then
        endline(s,i) : b=i-m ' (...) ...
        if asc(s,m-1)=lbr then m-=1 : b+=1 'INCLUDE LEFT BRACKET
      end if
      '
      macapture:
      '=========
      '
      w2=mid(s,m,b)
      striplineno(w2)
      nocomments(w2)
      skiplspace(s,i)
    end if
    '
    if b>0 then
      clcasewds(w2)
      nofinalcr(w2)
    else 'empty macro
      w2=""
    end if
    '
    '
    newrecord(w1)
    macsi(w2,me,1) 'BODY
    macsi(wt,me,2) 'RETURNTYPE
    macsi(w3,me,3) 'PROTOTYPE
    maco(me,0)=-20 'METATYPE HIGH LEVEL MACROS
    maco(me,5)=md '104 for '#define'  109 for 'macro'
    addme : if ert then exit sub
    exit sub
    '
  elseif md=107 then '#UNDEF
    wr=tword(s,i) : mp=lookupm(wr)
    if mp then
      macsi("",mp,0) 'knockout name
    end if
    exit sub
  '
  '
  elseif md=108 then 'ALIAS TYPE AS OTHERNAME (thinBasic)
    w1=tword(s,i) : nextspace(s,i) : wr=tword(s,i)
    newrecord(wr)
    macsi(w1,me,1)
    maco(me,0)=-18
    addme
    exit sub
  '
  '
  elseif (c=100)or(c=110) then '#IF #PRINT
    v=metaval(s,i,wr,0)
    if c=110 then
      qq noquotes(wr),c 'display result
      exit sub
    end if
  '  
  '
  'AFTER ACCEPTING VALID BLOCK:
  'DELETE REMAINDER
  elseif (c=101)or(c=102) then '#ELSE #ELSEIF
    i=mb : metaskip(s,i,1) 'BLANK OUT ALL INCLUDING THE TERMINATING #ENDIF
    goto xmetaco
  '
  elseif c=103 then '#ENDIF
   v=-1
  '
  elseif (c=105)or(c=106) then '#IFDEF '#IFNDEF
    '
    if nisxn then
      wr=tword(s,i)
      v=-1
      if isa(ascw) then
        mp=lookupm(wr)
        if mp=0 then
          wr=mword(wr,1) : skiplspace(s,i) 'MEMBERS
          if ert then mp=0 : ert=0 : ers="" 'SUPPRESS ANY ERRORS
        end if
      else
        mp=-1
      end if
      if c=106 then
        if mp<>0 then v=0
      else
        if mp=0  then v=0
      end if
    else 'isxn
      if c=105 then v=0 else v=-1 'NO OTHER WORD ON THE LINE
    end if
    '
  elseif c=113 then '#EVAL
    v=metaval(s,i,wr,0)
    inserts(s,wr,i)
    exit sub
  end if
  '
  '-----------
  'META ACTION
  '===========
  '
  if v=0 then
    '
    'BLANK OUT THIS INVALID BLOCK INCLUDING THE META EXPRESSION
    'BUT STOP WHEN #ELSE #ELSEIF ALTERNATIVE IS ENCOUNTERED
    '
    i=mb : metaskip(s,i,0)
  else
    '
    'THE BLOCK IS VALID THEREFORE
    'BLANK OUT THE TESTING META EXPRESSION ONLY
    '
    'endline(s,i)
    mid(s,mb)=space(i-mb)
  end if
  '
  xmetaco: 'DONE
  '
end sub


'--------------------------------------------------
sub EncodeEquate(byref s as string, byref i as sys)
'==================================================
dim as sys a,b
dim as string wr
b=asc(s,swd+1)
if b=ascw then  '%% $$
  i+=1
  swd+=1
  a=1
  b=asc(s,swd+1)
end if
if (b=61)or(b=42) then '%= $= $*
  i+=1
end if
wr=tword(s,i)
if isa(ascw)=0 then
  endline(s,i) : exit sub 'MUST USE ALPHABETIC OR UNDERSCORE 
end if
if a then
  if lookupm(wr) then
    endline(s,i)
    exit sub 'ALREADY DEFINED
  end if
end if
if ascn=61 then
  i+=1 : skiplspace(s,i)
end if
if b=61 then
  swd=i
  md=113 'EVALUATE
  metaco(s,i)
end if
newrecord(wr)
if ert then exit sub
a=i
endline(s,i)
wr=mid(s,a,i-a) 'single line only
nocomments(wr)
wr=ltrim(wr)
macsi(wr,me,1)
maco(me,0)=-18
maco(me,2)=b
addme
end sub


'-------------------------------------------------
sub includefile(byref s as string, byref i as sys)
'=================================================
  '
  'CHECK FOR FILES ALREADY INCLUDED
  '--------------------------------
  '
  '
  '  #################
  '  # INCLUDE FILES #
  '  #################
  '  ###
  '  ###
  '  ###
  '  ##############
  '  ##############
  '  ###
  '  ###
  '  ###
  '  ###
  '  ###
  '  ####
  '
  
  dim as sys a,b,c,d,e,f,p
  dim as string wd,w1
  dim as zstring ptr pch
  do
    wd=tword(s,i)
    if wd="once" then a=1 : continue do
    i=swd : wd=lexiword(s,i)
    if ascw=60 then
      f=instr(2,wd,">")
      if f then
        wd=mid(wd,2,lenw-2) : p=1
      end if
    end if
    exit do
  loop
  w1=filename(wd)
  if instr(w1,".")=0 then wd+=".inc" : w1+=".inc"
  if a then
    b=1
    do
      if b>=fql then exit do
      if w1=ssn(b) then
        c=1 : d=ssh(b) : exit do
      end if
      b+=1
    loop
  end if
  '
  ssn(fql)=w1 'NAME LOG (WITH HASH)
  '
  if len(wd) then
    if fq>63   then ers="Too many nested 'include' files "+wd : ert=40 : exit sub
    if fql>999 then ers="Too many 'include' files "+wd : ert=40 : exit sub
  else
    exit sub
  end if
  '
  '
  'RESOLVE FILE PATH
  '
  if len(ipath) then
    wd=ipath+wd
    p=2
  elseif p then
    wd="$\inc\"+wd 'ASSUME FILE IS IN THE INC FOLDER
  end if
  '
  if asc(wd)=36 then wd=rootpath(wd) else p=-1
  '
  if pPathCall then
    pch=inclpath(wd)
    a=lenzs(pch)
     wd=ps_to_str(pch,a)
  end if
  '
  sst(fq)=mid(s,i)  'SAVE REMAINING PARENTAL SOURCE CODE
  i=1
  '
  '
  getfile(wd,s)  'GET THE INCLUDE
  '
  '
  'CHECK FOR EMPTY OR NON-EXISTENT FILE
  '
  if len(s)=0 then
    w1=wd
    if p=-1 then
      wd=rootpath("$\inc\"+wd) 'LOOK IN THE INC FOLDER
      ert=0 'CANCEL ERROR
      getfile(wd,s) 'TRY AGAIN
    end if
  end if
  '
  if len(s)=0 then
    exit sub 'ERROR GENERATED
  end if
  '
  ssf(fq)=wd 'REMEMBER NAME
  '
  '
  'CHECK IF PRIOR FILE SEEMS IDENTICAL
  '
  e=hashid(s)
  '
  if c then
    if d=e then
      s=sst(fq) 'ALREADY SEEN SO REVERT TO PARENT
      exit sub
    end if
  end if
  '
  ssh(fql)=e   'FILE CONTENT HASH
  stb(fq)=s    'NEW SOURCE CODE (redundant?)
  sti(fq)=fql  'INDEX TO NAME & HASH LOG
  fq+=1        'INCR FILE STACK INDEX
  fql+=1       'INCR FILE LOG INDEX
  '
  LineMark(s)
  cfile=wd
  appendt("'_"+qu+wd+qu+cr) 'EMBED FILENAME
  '
end sub


sub SetNameSpace(byref s as string, byref i as sys)
'==================================================
  dim as string wr,w1
  dim as sys a
  if nisxn then
    wr=tword(s,i)
    w1=wr+"::"
    a=lookupm(w1)
    if a then
      nsi=a
    else
      macoin me
      macsi(w1,me,0)
      maco(me,0)=-12
      nsi=0
      addmin()
      nsi=me
      addme
    end if
  else
    nsi=0
    wr=""
  end if
  appendt ("namespace "+wr+cr) 'PASS ON
end sub


'--------------------------------
sub intrinsic(byref w1 as string)
'================================
  '
  'ACCEPTS METATYPES -4 -9 -10 -11 -13 -14 -15 -16 -17 -18 -19 -20
  '
  dim as sys a,b,c,d
  dim as string wr
  c=1 : wr=yword(w1,c)
  macsi(wr,me,0) 'NAME
  a=-wval(yword(w1,c))
  if a=-20 then
    md=109 'HIGH LEVEL MACRO
    metaco(w1,c)
    exit sub
  end if
  addm()
  maco(me,0)=a 'METATYPE
  w1=mid(w1,c)
  c=1
  d=wval(w1)
  if a=-4  then
    w1="## sys "+memreg(qebx,d)+" 0 EA 0.       "+cr
  elseif a=-10 then
    d=asc(w1,1)-48
    if d>9 then d-=7
    if d=15 then d=16
    maco(me,1)=d 'SIZE
    maco(me,5)=d
    macsi(revdic(idtype,d),me,3) 'REGISTER TYPE NAME
  elseif a=-11 then
    maco(me,4)=d : nextspace(w1,c) : d=wval(yword(w1,c)) : w1=""
  elseif a=-16 then
    c=1
    nextspace(w1,c)
    wr=yword(w1,c)
    d=identype(wr)
  elseif a=-17 then
    d=&h6a 'type for extended floating point
  end if
  if (a<=-11)and(a>=-17) then
    maco(me,5)=d 'RETURN-TYPE / KEYWORD ENCODING
    if a=-15 then maco(me,1)=d and 31 'LENGTH FOR CTYPE KEYWORD
  end if
  if len(w1) then macsi(w1,me,1) 'BODY
  me+=1
end sub


'---------------
sub intrinsics()
'===============
  dim as sys a,b,c
  dim as string w1
  do
    read w1
    if w1="" then exit do
    intrinsic(w1)
  loop
end sub


#if 0
'EARLY FLAT MACRO RESOLUTION

'--------------------------------
sub preprocess(byref s as string)
'================================
dim as sys a,c,h,i,k,le,n,nl,lnb,lne,lct,en,ppf
dim as string wd,wr,ww,wk
GlobalClear()
InitDefTables()
restore kernel_funs : Intrinsics()
j=1 'CLEAR OUTPUT BUFFER T
le=len(s)
i=1
ascn=13 'CAUSE NL=1
while i<len(s)
  lct+=1
  if (ascn=13)or(ascn=10) then nl=1 else nl=0
  ww=wrd(s,i)
  wr=ww
  clcase(wr)
  ascw=asc(wr)
  '
  if ascw=35 then
    if wr="#preprocess" then
      yesno(s,i,preproc)
      if nisxn then
        if wordahead(s,i)="scoped" then
          preproc=2 : i=nwd
          skiplspace(s,i)
        end if
      end if
      if preproc then
        ppf=preproc
      else
        endline(s,i) : appendt(mid(s,i))
        exit while
      end if
      continue while
    end if
  end if
  '
  if preproc=0 then
    if ascw then
      'itr includefiles
      endlineq(s,i) : i+=2
      appendt(mid(s,swd,i-swd))
      if ppf=0 then
        if lct>100 then j=1 : exit sub 'ASSUME NO #PREPROCESS 
      end if
      continue while
    else
      j=1 : exit sub
    end if
  end if
  '
  'FILE SOURCES
  if ascw=0 then
    if fq then
      fq-=1 'resume previous source string
      i=1 : s=sst(fq) : skiplspace(s,i)
      if fq then wd=ssf(fq-1) else wd="main source"
      cfile=wd
      appendt("'_"+qu+wd+qu+cr) 'EMBED CURRENT FILENAME
      continue while
    end if
    exit while
  end if
  '
  'ACTIVE PREPROCESSING
  '
  'REMOVE BASIC COMMENTS EXCEPT FOR LINE MARKERS
  if ascw=39 then
    endline(s,i)
    if asc(s,swd+1)=lnm then
      lnb=swd+2
      lne=i
      k=i+2 : skiplspace(s,k) 'LOOK ON NEXT LINE
      if (ascn=37)or(ascn=35) then
        'OMIT LINEMARKER
      else
        appendt(mid(s,swd,i-swd)+cr) 'CAPTURE LINE MARKER
      end if
      skiplspace(s,i)
      continue while
    end if
    appendt(cr) 'LEAVE BLANK LINE INSTEAD OF COMMENT
    continue while
  elseif ascw=47 then
    a=swd
    if ccomment(s,a) then
      i=a
      if (ascn=13)or(ascn=10) then appendt(cr) else appendt(" ")
      continue while
    end if
  end if
  '
  'MACRO EXPANSION
  if isa(ascw) then
    en=0
    if preproc=2 then
      if ascw=&h65 then
        'SCOPE SUPPORT
        if wr="end" then
          if nisxn then
            a=swd
            appendt ww+" "
            ww=wrd(s,i) : wr=ww : clcase(wr) : ascw=asc(wr)
            swd=a
            en=1
          end if
        end if
      end if
    end if
    mp=lookupm(wr)
    mc=0
    a=0
    if mp then
      mc=maco(mp,0)
      select case mc
      case -18 : wk=macres(mp,s,i) : a=1 'LO-LEVEL MACRO: % $
      case -20 : wk=himac(mp,s,i)  : a=2 'HI-LEVEL MACRO: #define
      case -14 to -13 : 'SCOPE SUPPORT
      if preproc=2 then
        a=instrword(" function sub method methods class scope block ",wr)
        if a then
          if en=0 then
            if wr="sub" then a=issub(s,i)
          end if
          if a then
            if en then unnest() else nest()
          end if
          a=0
        end if          
      end if
      end select
      '
      if a then 'POSSIBLE RECURSIVE MACRO EXPANSION
        if i>le*50 then
          ers="Suspect unlimited recursion in macro"
          ert=99
        end if
        if ert then exit while
        inserts(s,wk+" ",i)
        skiplspace(s,i)
        if nl=1 then ascn=13 'TREAT AS NEW LINE
        continue while
      end if
    end if
  end if
  '
  if nl=0 then goto outputww
  md=0
  '
  'CHECK FIRST WORDS ON EACH LINE
  '
  'ITR NEED TO RUN FULL LINE CHECKS FOR SCOPING ({})
  'if (ascw=40) or (ascw=123) then
  '  if isxn then nest()
  'elseif (ascw=41) or (ascw=125) then
  '  if isxn then unnest()
  if ascw=35 then
    '
    if wr="#define" then
      md=104
    elseif wr="#include" then
      includefile(s,i)
      le=len(s)
      if ert then exit while
      continue while
    elseif wr="#includepath" then
      paths(s,i,ipath)
      continue while
    elseif wr="#ifdef" then
      md=105
    elseif wr="#ifndef" then
      md=106
    elseif wr="#undef" then
      md=107
    elseif wr="#if" then
      md=100
    elseif wr="#else" then
      md=101
    elseif wr="#elseif" then
      md=102
    elseif wr="#endif" then
      md=103
    elseif wr="#eval" then
      md=113
    elseif wr="#case" then
      'nested #case is now obsolete
      if nisxn then
        wr=lcase(tword(s,i))
        casf=dic(" insensitive 1, sensitive 2, capital 3, capitalsensitive 3, ",wr)
        appendt("#case "+wr+cr)
        ascn=13
        continue while
      end if
    end if
  elseif ascw=&h69 then 'i
    if wr="include" then
      includefile(s,i)
      le=len(s)
      if ert then exit while
      ascn=13 : continue while
    elseif wr="includepath" then
      paths(s,i,ipath)
      ascn=13 : continue while
    end if
    '
  elseif (ascw=36)or(ascw=37) then '$ %
    a=asc(s,i+1)
    if a>64 then
      EncodeEquate(s,i)
      if ert then exit while
      ascn=13 : continue while
    end if
    
  elseif (ascw=&h6e) then 'n
    if wr="namespace" then
      SetNameSpace(s,i) : continue while
      ascn=13
    end if
  elseif (ascw=&h74) then 't
    if wr="type" then
      wd=tword(s,i)
      wk=captureblock(s,i,wr)
      ww=wr+" "+wd+cr+wk+"end type"
      ascn=13
    end if
  end if
  '
  if md>=100 then
    metaco(s,i)
    if ert then exit while
    ascn=13 : continue while
  end if
  '
  outputww: 'OUTPUT EXPANDED SOURCE CODE
  '
  appendt(ww)
  if ert then exit while
  if (ascn=13)or(ascn=10) then
    appendt(cr)
    ascn=13
  else
    n=i-swd-lenw
    if n>0 then appendt(space(n))
  end if
wend
SetNameSpace("",1)
'
'EXTRACT PROCESSED SCRIPT FROM T BUFFER
s=left(t,j-1)
if ert then
  ers="PREPROCESSOR"+cr+"ERROR: "+htb+ers+cr+_
  "WORD: "+htb+ww+cr+_
  "LINE: "+htb+mid(s,lnb,lne-lnb)+cr
  if fq then
    ers+="FILE: "+htb+ssf(fq-1)+cr
  end if
  if vew>=2 then
    appendt(ers)
  end if
end if
'open "t.txt" for output as 3 : print #3,s : close(3) 'examine
j=1 'CLEAR T BUFFER
end sub
#endif
