V10/cmd/spitbol/minpp.spt
-IN80
-TITLE minpp: minimal conditional assenbly preprocessor
*
* This program processes MINIMAL conditional assembly directives.
* Its existence is required because none of the assemblers for
* VAX/UN*X support conditional assembly. The C-preprocessor
* could be used instead. However, the MINIMAL conditional assembly
* commands would have to be translated first and this hinders
* development work at non-UN*X sites.
*
&anchor = 1
&stlimit = 1000000000
*
* Obtain file information.
*
infile = input
input( .in,0,infile )
terminal = 'Input file: ' infile
outfile = input
output( .out,1,outfile )
terminal = 'Output file: ' outfile
*
* XFERVEC is the transfer vector for routing control to handlers
* for conditional assembly directives.
*
xfervec = table( 11,,.badop )
xfervec['.DEF'] = .defop
xfervec['.UNDEF'] = .undefop
xfervec['.IF'] = .ifop
xfervec['.THEN'] = .thenop
xfervec['.ELSE'] = .elseop
xfervec['.FI'] = .fiop
*
* SYMTBL tracks defined conditional symbols. (Undefined symbols
* are assigned null values in SYMTBL.)
*
symtbl = table( 11 )
*
* STATESTK maintains all state information while processing conditional
* statements. LEVEL indexes the top entry. Another variable, TOP,
* has a copy of SAVESTK[LEVEL].
*
statestk = array( 30 )
level = 0
top =
*
* Each STATE entry in STATESTK contains state information about
* the processing for each active .IF. The state is maintained
* as 2 fields:
*
* result the result of the .IF expression evaluation-
* TRUE, FALSE, or BYPASS
*
* mode whether processing THEN or ELSE portion of .IF
*
data( 'state(result,mode)' )
false = 0
true = 1
bypass = 2
else = 0
then = 1
*
* PROCESSREC is indexed by the current RESULT and MODE to determine
* whether or not a statement should be processed and written to the
* output file.
*
processrec = array( false ':' bypass ',' else ':' then,0 )
processrec[true,then] = 1
processrec[false,else] = 1
*
* RIP breaks up conditional assembly directives.
*
sep = ' '
rip = ( break(sep) | rem ) . condcmd
+ ( span(sep) | '' )
+ ( break(sep) | rem ) . condvar
*
* Main loop: read a record and transfer control to appropriate
* conditional assembly directive handler or other statement handler.
*
loop line = in :f(done)
incnt = incnt + 1
leq( substr( line,1,1 ),'.' ) :f(other)
line ? rip :s( $xfervec[condcmd] )
*
* Syntax error handler.
*
synerr terminal = incnt '(syntax error):' line :(loop)
*
* Process define
*
defop ident( condvar ) :s(synerr)
eq( level ) :s(defok)
eq( processrec[result(top),mode(top)] ) :s(loop)
defok symtbl[condvar] = 1 :(loop)
*
* process undefine
*
undefop
ident( condvar ) :s(synerr)
eq( level ) :s(undok)
eq( processrec[result(top),mode(top)] ) :s(loop)
undok symtbl[condvar] = :(loop)
*
* process if
*
ifop ident( condvar ) :s(synerr)
eq( level ) :s(ifok)
*
* Here for .IF encountered during bypass state.
*
ne( processrec[result(top),mode(top)] ) :s(ifok)
level = level + 1
top = statestk[level] = state(bypass,then) :(loop)
*
* Here for .IF to be processed normally.
*
ifok level = level + 1
top = statestk[level] = state(
+ ( differ( symtbl[condvar] ) true,false ),
+ then ) :(loop)
*
* process .then
*
thenop eq(level) :s(synerr)f(loop)
*
* process .else
*
elseop mode(top) = ne( level ) else :s(loop)f(synerr)
*
* process .fi
*
fiop level = ne( level ) level - 1 :f(synerr)
top = ( ne( level ) statestk[level],'' ) :(loop)
*
* process statements other than consitional directives.
*
other eq( level ) :s(outit)
eq( processrec[result(top),mode(top)] ) :s(loop)
outit out = line
outcnt = outcnt + 1 :(loop)
*
* finished - print out statistics.
*
done terminal = lpad( incnt,6 ) ' input records.'
terminal = lpad( outcnt,6 ) ' output records.'
end
spitv35.min
spitv35.ppmin