|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.