Annotation of researchv10no/cmd/spitbol/mintok.spt, revision 1.1.1.1

1.1       root        1: -IN80
                      2: -TITLE MINTOK: PHASE 1 TRANSLATION FROM MINIMAL TO TOKENS
                      3: -STITL INTRODUCTIONS
                      4: *
                      5: *       This program takes MINIMAL statements and busts them up into
                      6: *       individual pieces.
                      7: *
                      8: -STITL Initialization
                      9: *
                     10: *       Keyword initialization
                     11: *
                     12:        &ANCHOR = 1;    &STLIMIT = -1;  &TRIM   = 1
                     13: *
                     14: *       Useful constants
                     15: *
                     16:         MINLETS = 'ABCDEFGHIJKLMNOPQRSTUVWXY$'
                     17:         NOS     = '0123456789'
                     18:        TAB     = SUBSTR( &ALPHABET,10,1 )
                     19:         REGNAME = ('X' ANY('LSTR')) | ('W' ANY('ABC')) | 'IA' | 'RA' | 'CP'
                     20: *
                     21: *       Zero the counts
                     22: *
                     23:         LABCNT = NOUTLINES = NLINES = NSTMTS = NTARGET = NERRORS = 0
                     24: *
                     25: *       Get file name
                     26: *
                     27:         FILENAMI = INPUT
                     28:        TERMINAL = 'Input MINIMAL file: ' FILENAMI
                     29:         TERMINAL =
                     30:         FILENAMO = INPUT
                     31:        TERMINAL = 'Output TOKEN file: ' FILENAMO
                     32:         TERMINAL =
                     33:         FLCFLAG  = REPLACE( INPUT,'y','Y' )
                     34:        TERMINAL = 'Full line comments passed to TOKEN file? ' FLCFLAG
                     35: *
                     36: *       No page ejects without full line comments
                     37: *
                     38:         TERMINAL = DIFFER(FLCFLAG,'N')
                     39:         EJCFLAG  = REPLACE( (DIFFER(FLCFLAG,'N') INPUT, 'N'),'y','Y' )
                     40:        TERMINAL = 'EJCs passed to TOKEN file? ' EJCFLAG
                     41: -STITL XFER FUNCTIONS
                     42: *       CRACK parses STMT into a STMT data plex and returns it.
                     43: *       It fails if there is a syntax error.
                     44: *
                     45:         DEFINE('CRACK(LINE)LABEL,OPCODE,OPERANDS,COMMENT,OPERAND,CHAR')
                     46: *
                     47: *       STMT is the common data plex used to hold the components of
                     48: *       a statement (either Minimal or VAX) during processing.
                     49: *
                     50:         DATA('STMT(LABEL,OPCODE,OP1,OP2,OP3,COMMENT)')
                     51: *
                     52: *       MINLABEL is a pattern matching a valid Minimal Source Label.
                     53: *
                     54:         MINLABEL = ANY(MINLETS) ANY(MINLETS) ANY(MINLETS NOS)
                     55: +                  ANY(MINLETS NOS) ANY(MINLETS NOS)
                     56: *
                     57: *       CSPARSE parses out the components of the input line in STMT,
                     58: *       and puts them into the locals: LABEL, OPCODE, OPERANDS, COMMENT
                     59: *
                     60:         CSPARSE = (((MINLABEL . LABEL) | ('     '  '' . LABEL)) '  '
                     61: +                  LEN(3) . OPCODE
                     62: +                  (('  ' (BREAK(' ') | RTAB(0)) . OPERANDS
                     63: +                   (SPAN(' ') | '') RTAB(0) . COMMENT)  |
                     64: +                   (RPOS(0) . OPERANDS . COMMENT)))  |
                     65: +                 ('.'  '' . LABEL  MINCOND . OPCODE
                     66: +                  ((TAB(7)  '.'  LEN(4) . OPERANDS) | (RPOS(0) . OPERANDS))
                     67: +                  '' . COMMENT)
                     68: *
                     69: *       CSOPERAND breaks out the next operand in the OPERANDS string.
                     70: *
                     71:         CSOPERAND = (BREAK(',') . OPERAND  ',')  |  ((LEN(1) RTAB(0)) . OPERAND)
                     72: *
                     73: *       CSDTC is a pattern that handles the special case of the Minimal DTC op
                     74: *
                     75:         CSDTC   = ((MINLABEL . LABEL)  |  ('     '  '' . LABEL))
                     76: +                 LEN(7) (LEN(1) $ CHAR  BREAK(*CHAR)  LEN(1)) . OPERAND
                     77: +                 (SPAN(' ') | '')  RTAB(0) . COMMENT
                     78: *
                     79: *      equ.rip is a pattern that parses out the components of an EQU
                     80: *      expression.
                     81: *
                     82:        equ.rip  = ( span(nos) . num1 | minlabel . sym1 )
                     83: +                 ( any('+-') . oprtr | '' )
                     84: +                 ( span(nos) . num2 | minlabel . sym2 | '' )
                     85: +                 rpos(0)
                     86: -EJECT
                     87: *       DOSTMT is the driver routine that causes processing of the
                     88: *       statement plex in THISSTMT.
                     89: *
                     90:         DEFINE('DOSTMT()LABEL,OPCODE,OP1,OP2,OP3,COMMENT,T')
                     91: -SPACE 3
                     92: *
                     93:         DEFINE('TINIT(STR)POS,CNT,INDEX,VAL,LASTVAL')
                     94:         H_EQU.DEFS = TINIT(
                     95: +               'CFP$A[256]CFP$B[4]CFP$C[4]CFP$F[8]'
                     96: +               'CFP$I[1]CFP$M[^X7FFFFFFF]CFP$N[32]'
                     97: +               'NSTMX[10]CFP$R[1]CFP$S[6]CFP$X[2]'
                     98: +              'CFP$U[128]'
                     99: +               'E$SRS[50]E$STS[512]E$CBS[512]E$HNB[253]'
                    100: +               'E$HNW[3]E$FSP[20]'
                    101: +               'CH$LA[065]CH$LB[066]CH$LC[067]CH$LD[068]'
                    102: +               'CH$LE[069]CH$LF[070]CH$LG[071]CH$LH[072]'
                    103: +               'CH$LI[073]CH$LJ[074]CH$LK[075]CH$LL[076]'
                    104: +               'CH$LM[077]CH$LN[078]CH$LO[079]CH$LP[080]'
                    105: +               'CH$LQ[081]CH$LR[082]CH$LS[083]CH$LT[084]'
                    106: +               'CH$LU[085]CH$LV[086]CH$LW[087]CH$LX[088]'
                    107: +               'CH$LY[089]CH$L$[090]'
                    108: +               'CH$D0[048]CH$D1[049]CH$D2[050]CH$D3[051]'
                    109: +               'CH$D4[052]CH$D5[053]CH$D6[054]CH$D7[055]'
                    110: +               'CH$D8[056]CH$D9[057]'
                    111: +               'CH$$A[097]CH$$B[098]CH$$C[099]CH$$D[100]'
                    112: +               'CH$$E[101]CH$$F[102]CH$$G[103]CH$$H[104]'
                    113: +               'CH$$I[105]CH$$J[106]CH$$K[107]CH$$L[108]'
                    114: +               'CH$$M[109]CH$$N[110]CH$$O[111]CH$$P[112]'
                    115: +               'CH$$Q[113]CH$$R[114]CH$$S[115]CH$$T[116]'
                    116: +               'CH$$U[117]CH$$V[118]CH$$W[119]CH$$X[120]'
                    117: +               'CH$$Y[121]CH$$$[122]'
                    118: +               'CH$AM[038]CH$AS[042]CH$AT[064]CH$BB[060]'
                    119: +               'CH$BL[032]CH$BR[124]CH$CL[058]CH$CM[044]'
                    120: +               'CH$DL[036]CH$DT[046]CH$DQ[034]CH$EQ[061]'
                    121: +               'CH$EX[033]CH$MN[045]CH$NM[035]CH$NT[126]'
                    122: +               'CH$PC[037]CH$PL[043]CH$PP[040]CH$RB[062]'
                    123: +               'CH$RP[041]CH$QU[063]CH$SL[047]CH$SM[059]'
                    124: +               'CH$SQ[039]CH$UN[095]CH$OB[091]CH$CB[093]'
                    125: +               'CH$HT[009]CH$VT[012]IODEL[000]')
                    126: *
                    127: *       EQUATES is used by H_EQU and XOP.  It contains a directory of
                    128: *       all labels that were defined by EQU instructions.  This allows
                    129: *       XOP to properly translate operands of the DLBL(X) category.
                    130: *
                    131:         EQUATES = TABLE(257)
                    132: -space 3
                    133: *      BSW is a flag that indicates whether or not a BSW...ESW range
                    134: *      is being processed.
                    135: *
                    136:        bsw     = 0
                    137: -EJECT
                    138: *       Error is used to report an error for THISSTMT
                    139: *
                    140:         DEFINE('ERROR(TEXT)')
                    141: -SPACE 3
                    142: *       OUTSTMT is used to send a target statement to the target code
                    143: *       output file (OUTFILE <=> LU2)
                    144: *
                    145:         DEFINE('OUTSTMT(LABEL,OPCODE,OP1,OP2,OP3,COMMENT)T,STMTOUT')
                    146: *
                    147: *       Associate output file
                    148: *
                    149:         OUTPUT(.OUTFILE,2,(IDENT(FILENAMO) '', FILENAMO))
                    150: *       READLINE is called to return the next non-comment line from
                    151: *       the Minimal input file (INFILE <=> LU1).   Note that it will
                    152: *       not fail on EOF, but it will return a Minimal END statement
                    153: *
                    154:         DEFINE('READLINE()')
                    155: *
                    156: *       Associate input file to LU1
                    157: *
                    158:         INPUT(.INFILE,1,(IDENT(FILENAMI) '', FILENAMI))
                    159: -EJECT
                    160: *       XOP is called to translate a Minimal Operand to a VAX Macro Operand.
                    161: *
                    162:         DEFINE('XOP(XOP)VAL,PREFIX')
                    163: *
                    164: *       XOP.REGS is a pattern to match out register names for translation.
                    165: *
                    166:         XOP.REGS = (*REGNAME . VAL  RPOS(0) . PREFIX)  |
                    167: +                  (BREAK('(') LEN(1)) . PREFIX   LEN(2) . VAL
                    168: *
                    169: *       XOP.XREGS is a table with register translations
                    170: *
                    171:         XOP.XREGS = TINIT('IA[R5]RA[R2]CP[R3]WA[R6]WB[R7]WC[R8]XR[R9]'
                    172: +                   'XL[R10]XT[R10]XS[SP]')
                    173: *
                    174: *       XPINTX is a pattern that will match the INT(X) type operand
                    175: *
                    176:         XPINTX  = SPAN(NOS) . VAL  '('
                    177: *
                    178: *       XPDLBLX is a pattern that will match the DLBL(X) type operand
                    179: *
                    180:         XPDLBLX = MINLABEL . VAL  '('
                    181: -STITL MAIN PROGRAM
                    182: *       Here follows the driver code for the "main" program.
                    183: -SPACE 3
                    184: *
                    185: *       Loop until program exits via H_END
                    186: *
                    187: MN03    DOSTMT()                                        :(MN03)
                    188: -STITL CRACK(LINE)
                    189: *       CRACK is called to create a STMT plex containing the various
                    190: *       entrails of the Minimal Source statement in LINE.  For
                    191: *       conditional assembly ops, the opcode is the op, and OP1
                    192: *       is the symbol.  Note that DTC is handled as a special case to
                    193: *       assure that the decomposition is correct.
                    194: *
                    195: *       CRACK will print an error and fail if a syntax error occurs.
                    196: *
                    197: CRACK   NSTMTS  = NSTMTS + 1
                    198:         LINE    CSPARSE                                 :F(CS03)
                    199:         CRACK   = STMT(LABEL,OPCODE,,,,COMMENT)
                    200:         IDENT(OPCODE,'DTC')                             :S(CS02)
                    201: *
                    202: *      Now pick out operands until none left
                    203: *
                    204:        OPERANDS  CSOPERAND =                           :F(CS01)
                    205:        OP1(CRACK) = XOP(OPERAND)
                    206:        OPERANDS  CSOPERAND =                           :F(CS01)
                    207:        OP2(CRACK) = XOP(OPERAND)
                    208:        OPERANDS  CSOPERAND                             :F(CS01)
                    209:        OP3(CRACK) = XOP(OPERAND)
                    210: *
                    211: *      Operands all parsed out.  That's all folks.
                    212: *
                    213: CS01   :(RETURN)
                    214: *
                    215: *      DTC - Special case
                    216: *
                    217: CS02   LINE    CSDTC                                   :F(CS03)
                    218:        OP1(CRACK) = OPERAND
                    219:        COMMENT(CRACK) = COMMENT                        :(CS01)
                    220: *
                    221: *      Here on syntax error
                    222: *
                    223: CS03   ERROR('SOURCE LINE SYNTAX ERROR')               :(FRETURN)
                    224: -STITL DOSTMT()
                    225: *       DOSTMT is invoked to initiate processing of the next line from
                    226: *       READLINE.  For efficient access
                    227: *       DOSTMT puts name values corresponding to the components in
                    228: *       variables with the same names (LABEL, OPCODE, OP1,OP2,OP3 and
                    229: *       COMMENT) which allows the various handlers to $var to store/fetch
                    230: *       the values of the statment.
                    231: *
                    232: *       After doing this, DOSTMT branches to the handler routine indicated
                    233: *       for this opcode in the HANDLER table (there must be an entry or
                    234: *       an error results).  The handlers all have entry points beginning
                    235: *       with "H_", and can be considered a logical extension of the
                    236: *       DOSTMT routine.  The handlers have the choice of branching back
                    237: *       to DSGEN to cause the THISSTMT plex to be sent to OUTSTMT, or
                    238: *       of RETURNing themselves, in which case the handler must output
                    239: *       all needed code itself.
                    240: *
                    241: *       The handlers are listed in a separate section below.
                    242: *
                    243: DOSTMT  THISLINE = READLINE()
                    244:         THISSTMT = CRACK(THISLINE)              :F(DOSTMT)
                    245:         LABEL   = .LABEL(THISSTMT)
                    246:         OPCODE  = .OPCODE(THISSTMT)
                    247:         OP1     = .OP1(THISSTMT)
                    248:         OP2     = .OP2(THISSTMT)
                    249:         OP3     = .OP3(THISSTMT)
                    250:         COMMENT = .COMMENT(THISSTMT)
                    251: *
                    252: *      ONLY NEED TO PROCESS 5 INSTRUCTIONS:
                    253: *
                    254: *      BSW,END,EQU,ESW,IFF
                    255: *
                    256:         LEQ( $OPCODE,'EQU' )                    :s(h_equ)
                    257:        leq( $opcode,'IFF' )                    :s(h_iff)
                    258:        leq( $opcode,'BSW' )                    :s(h_bsw)
                    259:        leq( $opcode,'ESW' )                    :s(h_esw)
                    260:        leq( $opcode,'END' )                    :s(h_end)
                    261: *
                    262: *       GENERATE TOKENS.
                    263: *
                    264: DSGEN   OUTSTMT($LABEL,$OPCODE,$OP1,$OP2,$OP3,$COMMENT) :(RETURN)
                    265: -STITL ERROR(TEXT)
                    266: *       This module handles reporting of errors with the offending
                    267: *       statement text in THISLINE.  Comments explaining
                    268: *       the error are written to the listing (including error chain), and
                    269: *       the appropriate counts are updated.
                    270: *
                    271: ERROR   OUTFILE = '* *???* ' THISLINE
                    272:         OUTFILE = '*       ' TEXT
                    273: +                 (IDENT(LASTERROR),'. LAST ERROR WAS LINE ' LASTERROR)
                    274:         LASTERROR = NOUTLINES
                    275:         NOUTLINES = NOUTLINES + 2
                    276:         NERRORS = NERRORS + 1
                    277: +                       :(RETURN)
                    278: -STITL OUTSTMT(LABEL,OPCODE,OP1,OP2,OP3,COMMENT)
                    279: *       This module writes the components of the VAX MACRO statement
                    280: *       passed in the argument list to the formatted .MAR file
                    281: *
                    282: OUTSTMT
                    283: *
                    284: *       Send text to OUTFILE
                    285: *
                    286:         OUTFILE = '{' LABEL '{' OPCODE '{' OP1 '{' OP2 '{' OP3 '{' COMMENT
                    287:         NTARGET = NTARGET + 1
                    288:         NOUTLINES = NOUTLINES + 1
                    289: +                       :(RETURN)
                    290: -STITL READLINE()
                    291: *       This routine returns the next statement line in the input file
                    292: *       to the caller.  It never fails.  If there is no more input,
                    293: *       then a Minimal END statement is returned.
                    294: *       Comments are passed through to the output file directly.
                    295: *
                    296: *
                    297: READLINE READLINE = INFILE                      :F(RL02)
                    298:         NLINES  = NLINES + 1
                    299:        ident( readline )                       :s(readline)
                    300:         LEQ( SUBSTR( READLINE,1,1 ),'*' )       :F(RL01)
                    301: *
                    302: *       Only print comment if requested.
                    303: *
                    304:         OUTFILE = IDENT(FLCFLAG,'Y') READLINE   :F(READLINE)
                    305:         NOUTLINES = NOUTLINES + 1               :(READLINE)
                    306: *
                    307: *       Here if not a comment line
                    308: *
                    309: RL01    :(RETURN)
                    310: *
                    311: *       Here on EOF
                    312: *
                    313: RL02    READLINE = '       END'
                    314:                         :(RL01)
                    315: -STITL TINIT(STR)
                    316: *       This routine is called to initialize a table from a string of
                    317: *       index/value pairs.
                    318: *
                    319: TINIT   POS     = 0
                    320: *
                    321: *       Count the number of "[" symbols to get an assessment of the table
                    322: *       size we need.
                    323: *
                    324: TIN01   STR     (TAB(*POS) '[' BREAK(']') *?(CNT = CNT + 1) @POS)
                    325: +                                       :S(TIN01)
                    326: *
                    327: *       Allocate the table, and then fill it. Note that a small memory
                    328: *       optimisation is attempted here by trying to re-use the previous
                    329: *       value string if it is the same as the present one.
                    330: *
                    331:         TINIT   = TABLE(CNT)
                    332: TIN02   STR     (BREAK('[') $ INDEX LEN(1) BREAK(']') $ VAL LEN(1)) =
                    333: +                                       :F(RETURN)
                    334:         VAL     = CONVERT( VAL,'INTEGER' )
                    335:         VAL     = IDENT(VAL,LASTVAL) LASTVAL
                    336:         LASTVAL = VAL
                    337:         TINIT[INDEX] = VAL              :(TIN02)
                    338: -STITL XOP(OPERAND)
                    339: *       XOP is called to Translate a Minimal Source Operand into
                    340: *       a semantically equivalent VAX/Macro Operand.  Most of the
                    341: *       Minimal Operands are basically OK,  the following transformations
                    342: *       must be applied:
                    343: *
                    344: *               - All operands beginning with "=" have the "=" changed
                    345: *                 to a VAX immediate mode beginning with "#"
                    346: *               - Byte immediate "*..." is changed to "#4*..."
                    347: *               - INT(X) is changed to "4*INT(X)"
                    348: *               - DLBL(X) is changed to "4*DLBL(X)"
                    349: *               - CLBL(X) and WLBL(X) are changed to L^XLBL(X)
                    350: *
                    351: *
                    352: *       Check for immediate mode
                    353: *
                    354: XOP     XOP  '='        = '#'                   :S(XP01)
                    355: *
                    356: *       Else check for byte immediate
                    357: *
                    358:         XOP  ('*'  LEN(1) . VAL)  =  '#4*' VAL  :S(XP01)
                    359: *
                    360: *       Else check for INT(X)
                    361: *
                    362:         XOP  XPINTX  =  (IDENT(VAL,'0'), '4*' VAL) '('  :S(XP01)
                    363: *
                    364: *       Else check for DLBL(X), CLBL(X) or WLBL(X)
                    365: *
                    366:         XOP  XPDLBLX  =  (DIFFER(EQUATES[VAL]) '4*', 'L^') VAL '('
                    367: *
                    368: *       Merge here with XOP containing syntax fixes.  Now map registers
                    369: *
                    370: XP01    XOP     XOP.REGS        = PREFIX XOP.XREGS[VAL]         :(RETURN)
                    371: -stitl Handle instructions
                    372: *
                    373: *      BSW processing begins by building an array that can hold all
                    374: *      IFF operands and comments.
                    375: *
                    376: h_bsw  ub = ( integer( $op2 ) $op2, equates[$op2] )
                    377:        iffar = integer( ub )
                    378: +              array( '0:' ub - 1,'{{' )               :f(error)
                    379:        dplbl = $op3
                    380:        bsw   = 1                                       :(dsgen)
                    381: -space 3
                    382: *
                    383: *      IFF processing sets the iffar[] element to the current
                    384: *      value, plbl, and comment.
                    385: *
                    386: h_iff  eq( bsw )                                       :s(error)
                    387:        iffval = ( integer( $op1 ) $op1, equates[$op1] )
                    388:        iffar[iffval] = integer( iffval ) 
                    389: +              $op1 '{' $op2 '{' $comment              :f(error)s(return)
                    390: *
                    391: *      In order to support translation of MINIMAL operands and
                    392: *      BSW/IFF/ESW preprocessing, all EQU expressions must be
                    393: *      evaluated and kept in a symbol table.
                    394: *
                    395: h_equ  equates[$label] = ident($op1,'*')
                    396: +                      h_equ.defs[$label]              :s(dsgen)
                    397: *
                    398:        num1 = num2 = sym1 = sym2 = oprtr = 
                    399:        $op1 equ.rip                                    :f(error)
                    400:        num1    = differ(sym1) equates[sym1]
                    401:        num2    = differ(sym2) equates[sym2]
                    402:        val     = eval( num1 ' ' oprtr ' ' num2 )               :f(error)
                    403:        equates[$label] = val                           :(dsgen)
                    404: -space 3
                    405: *
                    406: *      ESW processing generates an IFF for every value in the
                    407: *      BSW range.
                    408: *
                    409: h_esw  eq( bsw)                                        :s(error)
                    410:        iffindx = 0
                    411: h_esw1 iffar[iffindx] break('{') $ val len(1)
                    412: +              break( '{' ) $ plbl len(1)
                    413: +              rem $ cmnt
                    414: +                                                      :f(h_esw2)
                    415:        val = ident( val ) 'DUMMY'
                    416:        plbl = ident( plbl ) dplbl
                    417:        outstmt(,'IFF',val,plbl,,cmnt)
                    418:        iffindx = iffindx + 1                           :(h_esw1)
                    419: h_esw2  iffar =                                                :(dsgen)
                    420: -SPACE 3
                    421: *       END prints statistics on terminal then exits program
                    422: *
                    423: H_END   OUTSTMT(,'END',,,,$COMMENT)
                    424:         TERMINAL = '*** TRANSLATION COMPLETE ***'
                    425:         TERMINAL = NLINES ' LINES READ.'
                    426:         TERMINAL = NSTMTS ' STATEMENTS PROCESSED.'
                    427:         TERMINAL = NTARGET ' TARGET CODE LINES PRODUCED.'
                    428:         TERMINAL = NERRORS ' ERRORS OCCURRED.'
                    429:         TERMINAL = DIFFER(LASTERROR) 'THE LAST ERROR WAS IN LINE ' LASTERROR
                    430:         &CODE   = NE(NERRORS) 2001
                    431:        terminal = collect() ' free words'
                    432:         :(END)
                    433: *
                    434: END
                    435: spitv35.ppmin
                    436: spitv35.tok
                    437: y
                    438: y

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.