Trailing-Edge
-
PDP-10 Archives
-
ALGOL-20_29Jan82
-
algol-sources/algcon.mac
There are 8 other files named algcon.mac in the archive. Click here to see a list.
;
;
;COPYRIGHT (C) 1975,1981,1982 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
;
;
; WRITTEN BY K. NIST, C.M.U./ EDITED BY R. M. DE MORGAN
SEARCH ALGPRM ; MAIN PARAMETER FILE
SALL
%TITLE(ALGCON,ALGOL COMPILER CONTROL MODULE)
TWOSEG
LOC .JBVER ;[171]
VERNO ;[171]
RELOC 400000
MLON
; THIS MODULE CONTAINS THE FOLLOWING ROUTINES:
;
;
; .RINIT ".RINIT" WILL INITIALIZE THE READ MODULE AND WRITE MODULE.
; ".RINIT" WILL SCAN THE COMMAND STRING AND OPEN FILES,
; INITIALIZE VARIABLES, AND ACQUIRE AND ALLOCATE SPACE
; FOR TABLES.
;
; .PINIT ".PINIT" IS CALLED BEFORE EACH ENTRY PROCEDURE TO
; REINITIALIZE VARIABLES AND REALLOCATE TABLES. ".PINIT"
; IS AUTOMATICALLY DONE AS PART OF ".RINIT".
;
; .RUND ".RUND" PERFORM LEXICAL SCANNING. ".RUND" WILL "READ UNTIL
; NEXT DELIMITER" AND THEN SHIFT THE WINDOW. ".RUND" WILL
; COMPUTE "LEXEX" AND "COMPNAME".
;
; .SEARCH ".SEARCH" WILL SEARCH THE SYMBOL TABLE FOR AN IDENTIFIER
; AND, OPTIONALLY, IF NOT FOUND WILL ENTER THE IDENTIFIER
; INTO THE TABLE.
;
; .STADD ".STADD" WILL ADD TO THE SYMBOL TABLE AN ENTRY FOR AN
; IDENTIFIER WHOSE NAME DUPLICATES THE NAME OF AN EXISTING
; IDENTIFIER.
;
; .XTNDLB ".XTNDLB" WILL MAKE THE LAST ENTRY IN THE SYMBOL TABLE AN
; EXTENDED ENTRY.
;
; .TOFIX ".TOFIX" WILL ENTER A TYPE-15 FIXUP INTO THE FIXUP TABLE.
;
; .CON1 ".CON1" WILL ENTER A 1-WORD CONSTANT INTO THE CONSTANTS
; TABLE.
;
; .CON2 ".CON2" WILL ENTER A 2-WORD CONSTANT INTO THE CONSTANTS
; TABLE.
;
; .FAILED ".FAILED" WILL ENTER AN ERROR MESSAGE INTO THE MESSAGE TABLE
; TO BE INCLUDED IN THE LISTING.
; .BLK1 ".BLK1" IS CALLED AT THE BEGINNING OF A BLOCK TO ENTER INTO
; THE LISTING THE MESSAGE "START OF BLOCK N".
;
; .BLK2 ".BLK2" IS CALLED AT THE END OF A BLOCK TO ENTER INTO THE
; LISTING THE MESSAGE "END BLOCK N, CONT M".
;
; .SCRUND ".SCRUND" WILL COMPUTE "LEXEX" AND "COMPNAME".
;
; GETCS "GETCS" WILL READ AND INTERPRET A COMMAND STRING.
;
; LMSGZ "LMSGZ" IS CALLED AT THE END OF A COMPILATION TO PRINT
; THE REMAINING CONTENTS OF THE MESSAGE TABLE.
;
; .STOVER ".STOVER" WILL HANDLE STACK OVERFLOWS.
;
; INS "INS" AND "TCHECK" ARE USED TO INSERT MESSAGES INTO
; TCHECK THE LISTING.
;
; GETSPC "GETSPC" IS USED TO ACQUIRE SPACE IN THE SYMBOL TABLE.
;
; HAL "HAL" WILL COMPUTE THE HASH VALUE AND NAME LENGTH FOR A
; SYMBOL TABLE ENTRY.
; TABLE ALLOCATION:
;
; TEMP SYMBOL FIXUP CONSTANTS STACK
; CODE TABLE TABLE TABLE
;! ! ! ! !
;! \ ! \ / ! \ ! \ !
;!---> !------------> <------!------> !------------------> !
;! / ! / \ ! / ! / !
;! ! ! ! !
; T ST N N FC N CS C
; C YC A A IO A OT O
; B MM S F XN C NA R
; A BA T T UT T EC E
; S OX E E PA E NK N
; E L B DB D
;
;
;
;
; TEMPCODE IS A BUFFER THAT RECEIVES PARTIALLY GENERATED CODE FOR
; EXPRESSIONS. TEMPCODE CAN OVERFLOW IF THE COMPILER ENCOUNTERS
; A SUPER-LARGE EXPRESSION. WHEN THIS HAPPENS THE COMPILATION
; ABORTS. THE DEFAULT LENGTH OF TEMPCODE IS "TEMPL". THE ALGOL
; USER CAN OVER-RIDE THIS WITH THE /T SWITCH.
;
IFNDEF TEMPL,<
TEMPL==400>
;
;
; THE SYMBOL TABLE HAS ENTRIES FOR ALL IDENTIFIERS ACTIVE IN THE
; USER'S PROGRAM. THE FIXUP TABLE CONTAINS THE ACCUMULATED TYPE-15
; LOADER BLOCK FIX-UPS. THE SYMBOL TABLE AND FIXUP TABLE GROW
; TOWARD EACH OTHER. IF THEY SHOULD MEET, CORE WILL BE EXPANDED
; BY AN AMOUNT "DELTA", THE FIXUP TABLE, CONSTANTS TABLE, AND STACK
; WILL BE MOVED UPWARD IN CORE BY AN AMOUNT "DELTA", AND THE COMPILATION
; WILL CONTINUE. THE COMBINED INITIAL LENGTH OF THE SYMBOL TABLE
; AND FIXUP TABLE IS "TABLES".
;
IFNDEF TABLES,<
TABLES==400>
; THE CONSTANTS TABLE CONTAINS WHATEVER SINGLE AND DOUBLE PRECISION
; FIXED AND FLOATING POINT CONSTANTS THAT CANNOT BE EXPRESSED AS
; IMMEDIATES, AND ALSO STRINGS. IF THE CONSTANTS TABLE SHOULD
; OVERFLOW, CORE WILL BE EXPANDED BY AN AMOUNT "DELTA", THE STACK
; WILL BE MOVED UPWARD IN CORE BY AN AMOUNT "DELTA", AND THE
; COMPILATION WILL CONTINUE. THE INITIAL LENGTH OF THE CONSTANTS
; TABLE IS "CONL".
;
IFNDEF CONL,<
CONL==30>
;
;
;
; THE STACK CONTAINS "PUSH" AND "PUSHJ" DATA, AND OTHER BLOCKS OF
; DATA. WHEN THE STACK OVERFLOWS, CORE IS EXPANDED BY AN AMOUNT
; "DELTA". THE INITIAL LENGTH OF THE STACK IS "STACKL".
;
IFNDEF STACKL,<
STACKL==100>
;
;
;
; THE UPPER BOUND OF THE STACK IS "COREND". PLEASE NOTE THAT NOTHING
; CAN GO INTO THE LOW SEGMENT ABOVE "COREND".
;
;
IFNDEF DELTA,<
DELTA==100>
;
;
;
; ALL BUFFER RINGS ARE COMPOSED OF BUFFERS OF STANDARD SIZE
; FOR THE PARTICULAR DEVICE. THE ALGOL USER CAN SELECT THE NUMBER
; OF BUFFERS IN EACH RING WITH THE /B SWITCH. THE DEFAULT NUMBER
; OF BUFFERS IN EACH BUFFER RING IS:
;
IFNDEF SBUF,< ; SOURCE
SBUF==2>
IFNDEF LBUF,< ; LISTING
LBUF==2>
IFNDEF OBUF,< ; OBJECT CODE
OBUF==2>
; REGISTER ASSIGNMENTS:
FL==A0 ; FLAGS REGISTER
; A10-A13 ; SAFE OVER READ MODDULE
A14==14 ; SAFE OVER READ MODULE
DEL==15
SYM==16
SP==17 ; STACK POINTER (SAFE OVER READ MODULE)
STOPS==A7
DBASE==A10
; READ MODULE FLAGS -- BIT ASSIGNMENTS (RFLAGS)
EXISTS==400000 ; LISTING FILE EXISTS
LTTY==200000 ; LISTING DEVICE IS A TTY
CSDONE==100000 ; COMMAND STRING SCANNED, COMPILATION STARTED
SPAREN==40000 ; PARENTHETICAL COMMAND STRING SWITCH
TTY==20000 ; SOURCE DEVICE IS A TTY
ESWIT==10000 ; LINE NUMBERS IN COLS 73-80
NSWIT==4000 ; NO ERROR PRINTOUTS ON TTY
COMPLETE==2000 ; 1 = LISTING COMPLETE AND CLOSED
TMG==1000 ; TERMINATION MESSAGE GIVEN
ELINE==400 ; EDITORS LINE NUMBER SCANNED
BLANKL==200 ; BLANK LINE BEING SCANNED
WITHIN==100 ; WITHIN NEWLINE ROUTINE
ONECHS==40 ; 1 CHARACTER SWITCH SCANNED
STATS==20 ; STATS REQUESTED.
; ACCUMULATOR ZERO -- BIT ASSIGNMENTS
; **************************************************
; * *
; * W A R N I N G ! ! ! ! ! ! ! ! ! ! ! *
; * *
; * THIS M U S T AGREE WITH GB DEFINITIONS *
; * IN FILE ALGMAC !!! *
; * *
; **************************************************
TRLOFF==20000 ; DON'T PLANT TRACE INFO ( IMPLIES TRPOFF)
TRPOFF==10000 ; DON'T MAKE SYMBOL BLOCKS
CREF==4000 ; /CREF - PRODUCE O/P FOR CROSS-REF PROGRAM
ACOFF==2000 ; /CHECKOFF - FORCE NO ARRAY-BOUND CHECKS
ACON==1000 ; /CHECKON - FORCE ARRAY-BOUND CHECKS
OBOO==400 ; OBJECT CODE LISTING ON/OFF FLAG
NOENTR==200 ; 1 => MAKE NO NEW ENTRIES IN SYMBOL TABLE
ACOO==100 ; ARRAY-BOUND CHECKING IN FORCE
LNOO==40 ; LINE-NUMBERS ON/OFF FLAG
LISTOO==20 ; LISTON/LISTOFF SWITCH
DECLAR==10 ; DECLARATION MODE
BPAIR==4 ; SCANNING A BOUND PAIR
ERRF==2 ; FATAL ERROR FOUND. NO CODE GENERATED
ERRL==1 ; SCANNING IN ERROR-LABEL
; OTHER RANDOM BITS
USE==400000 ; BUFFER USE BIT
EXACT==400000 ; USE EXACT POINTER FOR ERROR MSG UP-ARROW
DEVTTY==10 ; DEVCHR TTY BIT
RWTRT==-1
RWTLNK==0
RWTLEN==0
RWTLEX==1
RWTNAM==2
SYMBLK==0
SYMLNK==0
SYMTYP==1
SYMNAM==2
.FAILE=FAILED
INTERN .PINIT
INTERN .BLK1
INTERN .BLK2
INTERN .FAILE
.LSCAN=LSCAN
INTERN .LSCAN
.RINIT=RINIT
INTERN .RINIT
.SEARCH=SEARCH
INTERN .SEARCH
.STADD=STADD
INTERN .STADD
.GETSPC=GETSPC
INTERN .GETSPC
.RUND=RUND
INTERN .RUND
.XTNDL=XTNDLB
INTERN .XTNDL
.HAL=HAL
INTERN .HAL
.CON1=CON1
INTERN .CON1
.CON2=CON2
INTERN .CON2
INTERN .SCRUND
INTERN .TOFIX
INTERN .STOVE
INTERN COREB
INTERN CSBLK
INTERN CHKSUM
INTERN CCLSW
INTERN PRNAME
INTERN OFILE
EXTERN .JBERR
EXTERN .HELPR
EXTERN .JBREL
EXTERN .FAIL
EXTERN .JBAPR
EXTERN .JBTPC
EXTERN .JBFF
EXTERN .JBDDT
BLKLEV=BLOCKL
..HARD==60
..SOFT==0
..FRIED==1040
..IUO==1140
..FATAL==200
..FVARY==400
..SYM==10
..DEL==4
..NSYM==2
..NDEL==1
..IMM==20000
..IUO2==100
SUSPCO==40
RELOC 0
DEFINE FAIL(NNN,ARG1,ARG2,TEXT)
<
PUSHJ SP,FAILX
XWD <<..'ARG1+..'ARG2>&<777777>>,^D'NNN
>
FAILX: BLOCK 5 ; INITIALISED FROM HISEG AT START1.
; PUSH SP,A1 ; SAVE A1
; PUSH SP,A2 ; SAVE A2
; MOVE A1,@-2(SP) ; GET PARAM
; MOVEM A1,FAILX1 ; SAVE IT
; PUSHJ SP,.FAIL ; CALL FAIL ROUTINE
FAILX1: BLOCK 5
; XWD 0,0 ; PARAM WILL BE PUT HERE
; POP SP,A2 ; RESTORE A2
; POP SP,A1 ; RESTORE A1
; AOS (SP) ; SKIP RETURN
; POPJ SP, ; EXIT FAILX
RELOC
$IMM==1 ; CONSTANT, SIMPLE
$CT==3 ; CONSTANT, REGULAR
$ST==7 ; VARIABLE, SIMPLE
$SYMB==4 ; THIS BIT ON IMPLIES A SIMPLE VARIABLE
; FORMAT OF A RESERVED WORD TABLE ENTRY
;
; EACH ENTRY IN THIS TABLE IS LINKED INTO ONE OF 26 SUB-LISTS (ONE
; FOR EACH LETTER OF THE ALPHABET) WHOSE HEADS CAN BE FOUND USING
; THE "RESERVED WORD HASH TABLE". WHICH SUB-LIST THAT AN ENTRY IS LOCATED
; ON DEPENDS UPON THE FIRST LETTER OF THE NAME OF THE DELIMITER WORD.
;
; ALL ENTRIES IN THE TABLE THAT ARE LOCATED BEFORE THE ADDRESS "FRW"
; ARE CONSIDERED FLAGGED, AND THE WORD PRECEDING THESE ENTRIES MUST
; CONTAIN THE ADDRESS OF A ROUTINE THAT WILL PERFORM THE SPECIAL
; PROCESSING FOR THAT DELIMITER WORD. OTHER THAN THIS, NEITHER THE
; POSITION OF A DELIMITER WORD IN THE TABLE NOR ITS POSITION ON A
; DELIMITERS ON A SUB-LIST SHOULD BE ARRANGED IN ORDER OF FREQUENCY
; OF USAGE.
;
; THE RIGHT HALF OF THE FIRST WORD OF AN ENTRY CONTAINS THE SUB-LIST
; LINK. THE LEFT HALF CONTAINS EITHER A 0 OR A -1, DEPENDING ON WHETHER
; THE DELIMITER NAME WILL TAKE UP 1 WORD OR 2, RESPECTIVELY. THE SECOND
; WORD OF THE ENTRY CONTAINS THE COMPLETE LEXEME FOR THE DELIMITER.
; THE THIRD AND FOURTH WORDS OF THE ENTRY CONTAIN THE NAME OF THE
; DELIMITER. THERE IS NO FOURTH WORD IF THE NAME IS ONLY 1 WORD LONG
; (5 CHARACTERS OR LESS).
DEFINE N1(NAM,LN)
<
<373737373737>&<LN-1+SIXBIT/NAM/>
>
DEFINE N2(NAM)
<
<373737373737>&<SIXBIT/NAM/>
>
DEFINE LEX(ROOT)
<
INTERN Z'ROOT
EXTERN L$'ROOT,R$'ROOT
Z'ROOT: XWD L$'ROOT,R$'ROOT>
; *** RESERVED WORD TABLE ***
FBEGIN
FB: FB1 ; BEGIN
LEX(BEGIN)
N1(NIGEB,5)
FEND
FE: FE1 ; END
LEX(END)
N1(DNE,3)
FFALSE
FF1: FF2 ; FALSE
0
N1(ESLAF,5)
FGO
FG1: 0 ; GO
LEX(GOTO)
N1(OG,2)
COMNT2
FC: XWD -1,FC1 ; COMMENT
0
N1(EMMOC,7)
N2(TN)
FTRUE
FT1: 0 ; TRUE
0
N1(EURT,4)
FRW: ; ALL PRECEDING RESERVED WORDS ARE FLAGGED.
FA:
.+3 ; ARRAY
LEX(ARRAY)
N1(YARRA,5)
0 ; AND
LEX(AND)
N1(DNA,3)
FB1:
XWD -1,0 ; BOOLEAN
LEX(BOOLEAN)
N1(ELOOB,7)
N2(NA)
FC1:
XWD -1,.+4 ; COMPLEX
LEX(COMPLEX)
N1(LPMOC,7)
N2(XE)
XWD -1,.+4 ; CHECKON
LEX(CON)
N1(KCEHC,7)
N2(NO)
XWD -1,0 ; CHECKOFF
LEX(COFF)
N1(KCEHC,8)
N2(FFO)
FD:
.+3 ; DO
LEX(DO)
N1(OD,2)
0 ; DIV
LEX(DIV)
N1(VID,3)
FE1:
.+3 ; ELSE
LEX(ELSE)
N1(ESLE,4)
XWD -1,.+4 ; EXTERNAL
LEX(EXTERNAL)
N1(RETXE,8)
N2(LAN)
0 ; EQV
LEX(EQV)
N1(VQE,3)
FF:
FF1 ; FOR
LEX(FOR)
N1(ROF,3)
FF2:
XWD -1,0 ; FORWARD
LEX(FORWARD)
N1(AWROF,7)
N2(DR)
FG:
FG1 ; GOTO
XWD L$GOTO,R$GOTO
N1(OTOG,4)
FI:
.+3 ; IF
LEX(IF)
N1(FI,2)
XWD -1,.+4 ; INTEGER
LEX(INTEGER)
N1(GETNI,7)
N2(RE)
0 ; IMP
LEX(IMP)
N1(PMI,3)
FLL:
.+3 ; LABEL
LEX(LABEL)
N1(LEBAL,5)
.+3 ; LONG
LEX(LONG)
N1(GNOL,4)
XWD -1,.+4 ; LISTON
LEX(LON)
N1(OTSIL,6)
N2(N)
XWD -1,.+4 ; LISTOFF
LEX(LOFF)
N1(OTSIL,7)
N2(FF)
0 ; LINE
LEX(LINE)
N1(ENIL,4)
FN:
0 ; NOT
LEX(NOT)
N1(TON,3)
FO:
.+3 ; OWN
LEX(OWN)
N1(NWO,3)
0 ; OR
LEX(OR)
N1(RO,2)
FP:
XWD -1,0 ; PROCEDURE
LEX(PROCEDURE)
N1(ECORP,9)
N2(ERUD)
FR:
.+3 ; REAL
LEX(REAL)
N1(LAER,4)
0 ; REM
LEX(REM)
N1(MER,3)
FS:
.+3 ; STEP
LEX(STEP)
N1(PETS,4)
XWD -1,.+4 ; STRING
LEX(STRING)
N1(NIRTS,6)
N2(G)
XWD -1,0 ; SWITCH
LEX(SWITCH)
N1(CTIWS,6)
N2(H)
FT:
FT1 ; THEN
LEX(THEN)
N1(NEHT,4)
FU:
0 ; UNTIL
LEX(UNTIL)
N1(LITNU,5)
FV:
0 ; VALUE
LEX(VALUE)
N1(EULAV,5)
FW:
0 ; WHILE
LEX(WHILE)
N1(ELIHW,5)
; ** RESERVED WORD HASH TABLE **
RESWRD: FA
FB
FC
FD
FE
FF
FG
0
FI
0
0
FLL
0
FN
FO
FP
0
FR
FS
FT
FU
FV
FW
0
0
0
; SPECIAL CHARACTERS
.TAB==11
.LF==12
.VT==13
.FF==14
.CR==15
.CZ==32
.ALT1==33
.CLEFT==37
.SPACE==" "
.EXCL=="!"
.DQUOT==""""
.$=="$"
.%=="%"
.AMPER=="&"
.LPAREN=="("
.RPAREN==")"
.STAR=="*"
.PLUS=="+"
.COMMA==","
.MINUS=="-"
.DOT=="."
.SLASH=="/"
.N0=="0"
.N7=="7"
.N9=="9"
.COLON==":"
.SEMI==";"
.EQUAL=="="
.QUESTION=="?"
.AAAAA=="@"
.A=="A"
.B=="B"
.E=="E"
.I=="I"
.O=="O"
.T=="T"
.Z=="Z"
.LBRAC=="["
.RBRAC=="]"
.UP=="^"
.LEFT=="_"
.ALT2==175
.ALT3==176
.CRF==SIXBIT/ CRF/
.LST==SIXBIT/ LST/
.REL==SIXBIT/ REL/
.ALG==SIXBIT/ ALG/
.DSK==SIXBIT/ DSK/
.TMP==SIXBIT/ TMP/
SUBTTL ** RINIT **
; READ MODULE INITIALIZATION ROUTINE
RINIT: MOVEM A1,LINK ; SAVE RETURN LINK
CLOSE 3,0 ; CLOSE SOURCE FILE, IF OPEN
CLOSE 5,0 ; CLOSE COMMAND STRING FILE, IF OPEN
MOVE SP,[ ; LOAD A STACK POINTER
XWD -46,TMPBUF] ; TEMPORARILY USE TMPBUF AS A STACK
; IF THIS IS NOT THE 1ST CALL TO ".RINIT" THEN THE LISTING FROM
; THE PREVIOUS COMPILATION MIGHT NOT YET BE COMPLETE, AND ALSO
; THE REL-FILE MIGHT NOT YET BE CLOSED NOR DELETED IF IT IS TO
; BE DELETED.
MOVE A7,RFLAGS ; GET OLD READ MODULE FLAGS
MOVE A4,COREB ; GET OLD VALUE OF CORE
XORI A4,RANDOM ; CODE IT
CAME A4,CHKSUM ; IF VALUE OF CORE NOT VALID
JRST START1 ; THEN SKIP THIS PART
SKIPL WFLAG ; UNLESS REL-FILE IS TO BE DELETED
JRST START0 ; SKIP OVER THIS PART
; DELETE REL-FILE
SKIPE OFILE ; IF THERE IS NO REL FILE
CLOSE 1,40 ; DON'T SUPERSEDE
SETZM WFLAG ; CLEAR THE WRITE MODULE FLAG
; COMPLETE THE LISTING
START0:; TLNE A7,COMPLETE ; IF PREVIOUS RUN'S LISTING IS COMPLETE
; JRST START ; THEN SKIP THIS PART
PUSHJ SP,CREFNL ; CLOSE OFF ANY CREF INFO
MOVEI A1,NLCHRS ; PUT A BLANK LINE IN LISTING
PUSHJ SP,INSERT
SKIPN A1,.JBERR ; IF THERE ARE NO ERRORS
SKIPA A1,[[ASCIZ/No/]]; THEN SAY SO
PUSHJ SP,LPRINT ; CONVERT TO DECIMAL ASCII
PUSHJ SP,DONE1 ; INCLUDE IT IN LISTING
MOVE A1,.JBERR
CAIN A1,1 ; DON'T USE SOJG - DONE1 NEEDS .JBERR
SKIPA A1,[[ASCIZ/ error
/]]
MOVEI A1,ERRORM ; " ERRORS"
PUSHJ SP,DONE1 ; INCLUDE IN LISTING
SKIPN A1,WRNCNT ;[171] IF THERE ARE NO WARNINGS,
SKIPA A1,[[ASCIZ /No/]] ;[171] THEN SAY SO
PUSHJ SP,LPRINT ;[171] OR ELSE CONVERT NUMBER TO DECIMAL ASCII
PUSHJ SP,DONE1 ;[171] AND INCLUDE IT IN LISTING
MOVE A1,WRNCNT ;[171] GET WARNING COUNT
CAIN A1,1 ;[171] IF IT IS 1, USE THE SINGULAR
SKIPA A1,[[ASCIZ / warning
/]] ;[171] ...
MOVEI A1,[ASCIZ / warnings
/] ;[171] IF NOT, USE THE PLURAL
PUSHJ SP,DONE1 ;[171] AND INCLUDE IT IN LISTING
IFN FTSTATS,<
TLNN A7,STATS ; STATS ?
JRST START3 ; NO
MOVEI A1,[ASCIZ/
Number of identifiers = /] ;
PUSHJ SP,DONE2 ;
MOVE A1,DEFCNT ;
PUSHJ SP,LPRINT ;
PUSHJ SP,DONE2 ;
MOVEI A1,[ASCIZ/
Average characters in each = /] ;
PUSHJ SP,DONE2 ;
MOVE A1,IDCHRS ;
IDIV A1,DEFCNT ;
ADDI A1,1 ;
PUSHJ SP,LPRINT ;
PUSHJ SP,DONE2 ;
MOVEI A1,[ASCIZ/
Number of identifier references = /] ;
PUSHJ SP,DONE2 ;
MOVE A1,REFCNT ;
PUSHJ SP,LPRINT ;
PUSHJ SP,DONE2 ;
MOVEI A1,NLCHRS ;
PUSHJ SP,DONE2 ;
START3: >
MOVEI A1,LINES3 ; PUT 3 BLANK LINES
PUSHJ SP,INSERT ; IN LISTING
TLNE A7,EXISTS ; IF LISTING EXISTS,
PUSHJ SP,WRITEL ; WRITE OUT THIS BUFFER
START: CLOSE 1,0 ; CLOSE REL-FILE
CLOSE 2,0 ; CLOSE LISTING
JRST START1+1 ; SKIP NEXT INSTRUCTION
START1: SETOM CSCOMP ; MARK COMMAND STRING TO BE READ
SKIPN .JBDDT ; UNLESS DDT IS LOADED...
RESET ; RESET IO
MOVE A4,.JBFF ; ADD ADDRESS OF FREE CORE
XORI A4,RANDOM ; HASH IT
MOVEM A4,CHKSUM ; SET CHECK SUM
HRRZ A5,.JBFF ; GET START OF FREE CORE
MOVEM A5,COREB ; SET BASE OF CORE
; *** BEGIN THE CURRENT COMPILATION ***
IFE FTSYM,<
MOVEI FL,TRPOFF ; DEFAULT TO NO SYMBOLS (TYPE 1044 BLOCKS)
>
IFN FTSYM,<
SETZ FL, ; CLEAR FLAG REGISTER>
MOVE A7,IFLAGS ; GET A NEW SET OF FLAGS
SETZB A5,DYNOWN ; CLEAR OUR PROCESSOR TO KA, AND INITIAL HEAP SIZE
MOVEI A4,TEMPL ; DEFAULT LENGTH OF TEMPCODE
MOVEM A4,LTCODE ; SET LENGTH OF TEMPCODE
MOVEI A1,RLIST ; READ MODULE INIT LIST
PUSHJ SP,BMOVE ; INITIALIZE READ MODULE FROM HIGH SEG
MOVEI A4,600000 ; SET PROCESSOR TO TRAP ON
APRENB A4, ; A PUSHDOWN OVERFLOW
SKIPA A4,.+1 ; SET THE RESERVED WORD TABLE POINTER
XWD A1,RESWRD-.A ; TO THE ACTUAL RESERVED WORD TABLE
MOVEM A4,RWS ; SET IT
SKIPE .JBDDT ; SPECIAL MESSAGE IF
SKIPE CCLSW ; NOT CCL-MODE AND
JRST START2
OUTSTR DDTMSG ; DDT HAS BEEN LOADED
; PROCESS COMMAND STRING
START2: MOVEI A4,OBUF ; DEFAULT NUMBER OF OBJECT BUFFERS
MOVEM A4,OLIST+7 ; SET IT
MOVEI A4,LBUF ; DEFAULT NUMBER OF LISTING BUFFERS
MOVEM A4,LLIST+7 ; SET IT
MOVEI A4,SBUF ; DEFAULT NUMBER OF SOURCE BUFFERS
MOVEM A4,SLIST+7 ; SET IT
SKIPN CSCOMP ; IF PREVIOUS COMMAND STRING NOT EMPTY
JRST .+4 ; THEN DONT READ ANOTHER
SKIPGE CCLSW ; IF CCLSW = -1
JRST QUIT ; THEN NOTHING MORE TO COMPILE
PUSHJ SP,GETCS ; READ IN THE COMMAND STRING
; SCAN OBJECT CODE FILE NAME
MOVEI A4,.REL ; EXTENSION NAME DEFAULT
MOVSM A4,OFILE+1 ; SET DEFAULT
MOVEI A1,OLIST ; OBJECT CODE PARAM LIST
PUSHJ SP,SCAN2 ; SCAN NAME
; SCAN LISTING FILE NAME
MOVEI A4,.DSK ; LISTING DEVICE DEFAULT
MOVSM A4,LLIST+1 ; SET IT
EDIT(042); DONT USE OLD LISTING FILE NAME AGAIN
SETZM LFILE ; [E042] CLEAR LISTING FILE NAME
CAIE A6,.LEFT ; _?
CAIN A6,.EQUAL ; OR =?
JRST CS1 ; -YES, NEXT SCAN SOURCE FILES
CAIE A6,.COMMA ; IF TERMINATING CHAR NOT A COMMA
JRST CSER ; THEN COMMAND STRING ERROR
MOVEI A4,777777 ; EXTENSION NAME DEFAULT - GARBAGE
MOVSM A4,LFILE+1 ; SET DEFAULT VALUE
MOVEI A1,LLIST ; LISTING PARAM LIST
PUSHJ SP,SCAN2 ; SCAN NAME
CAIN A6,.LEFT ; _?
JRST CS1 ; YES
CAIE A6,.EQUAL ; =?
JRST CSER ; NO - COMMAND STRING ERROR
; SCAN SOURCE FILE NAME
CS1: TRO FL,LISTOO ; TURN LISTING ON
PUSHJ SP,SCAN3 ; SCAN 1ST SOURCE FILE AND OPEN IT
JRST CS5 ; CONTINUE
; SCAN SOURCE FILE NAME AND OPEN IT. DEV:FILE.EXT[123,456]/A/B
SCAN3: MOVEI A4,.ALG ; EXTENSION NAME DEFAULT
MOVSM A4,SFILE+1 ; SET DEFAULT
MOVEI A1,SLIST ; SOURCE PARAM LIST
PUSHJ SP,SCAN2 ; SCAN NAME
CAIE A6,.COMMA ; IF THE LAST CHAR IS NOT A COMMA
JRST CS12 ; THEN SKIP THIS PART
AOS CSCOMP ; MARK: LINE NOT COMPLETELY SCANNED
JRST CS14 ; CONTINUE
CS12: CAIE A6,.CR ; IF IT IS NOT A CR
JRST CS13 ; THEN SKIP THIS PART
PUSHJ SP,SCANCH ; STEP OVER THE LINE FEED
PUSHJ SP,SCANCH ; READ THE NEXT CHAR
JRST CS12 ; TRY AGAIN
CS13: CAIG A6,0 ; IF IT IS A NULL OR OTHER TERMINATOR
SETOM CSCOMP ; THEN MARK: END OF COMMAND STRING
HRLZI A4,070000 ; BYTE POINTER BACK-UP CONSTANT
ADDM A4,CSP ; BACK UP THE COMMAND STRING POINTER
CS14: TLZ A7,TTY ; CLEAR TTY FLAG
MOVE A5,SLIST+1 ; GET SOURCE DEVICE NAME
DEVCHR A5, ; WHAT IS DEVICE?
TLNE A5,DEVTTY ; IS IT A TTY?
TLO A7,TTY ; YES - SET FLAG BIT
; OPEN SOURCE DEVICE
OPEN 3,SLIST ; OPEN SOURCE DEVICE
JRST DSERR1 ; -SOMETHING WRONG
TLNE A7,CSDONE ; UNLESS THIS IS THE 1ST SOURCE FILE IN
JRST CS11 ; THE COMMAND STRING, SKIP THIS PART
; ESTABLISH SOURCE BUFFER RING
MOVE A5,SLIST+7 ; GET NUMBER OF BUFFERS
MOVEI A1,(A5) ; COPY TO A1
IMULI A1,204 ; EACH BUFFER TAKES UP 204 WORDS
PUSHJ SP,ALLOCATE ; GET SPACE FOR THESE BUFFERS
ADD A1,[ ; SET REGISTER A1 TO LOOK LIKE
XWD 202,1] ; A BUFFER LINK WORD
HRRZM A1,OLDSBR ; SAVE ADDRESS OF SOURCE BUFFER RING
JRST .+3 ; JUMP INTO LOOP
MOVEM A1,204(A1) ; SET NEXT BUFFER TO POINT TO THIS BUFFER
ADDI A1,204 ; STEP TO NEXT BUFFER
SOJG A5,.-2 ; LOOP
MOVEM A1,@OLDSBR ; SET LINK WORD OF 1ST BUFFER
CS11: MOVE A4,OLDSBR ; GET OLD SOURCE BUFFER RING
HRLI A4,400000 ; TURN ON USE BIT
MOVEM A4,BHEAD3 ; USE FOR THE CURRENT FILE ALSO
HRLI A4,000700 ; S-P BITS
MOVEM A4,BHEAD3+1 ; SET UP BYTE POINTER
; FIND SOURCE FILE
CS9: LOOKUP 3,SFILE ; SELECT SOURCE FILE
JRST DSERR2 ; FILE DOESNT EXIST
POPJ SP, ; EXIT SCAN3
SUBTTL ** COMMAND STRING ROUTINES **
; SCAN A FILE NAME ELEMENT (DEV, FILE, OR EXT)
SCAN1: SETZ A3,0 ; CLEAR A3
SKIPA A2,.+1
POINT 6,A3 ; SET UP OUTPUT POINTER
CS8: PUSHJ SP,SCANCH ; GET NEXT CHAR
SKIPL CTABLE(A6) ; IF NOT LETTER OR DIGIT
POPJ SP, ; THEN EXIT
SUBI A6,40 ; ELSE CONVERT TO SIXBIT
TLNE A2,770000 ; MORE THAN SIX CHARS?
IDPB A6,A2 ; DEPOSIT CHAR
JRST CS8 ; YES - IGNORE
; SCAN A FILE NAME OF THE FORM DEV:FILE.EXT[123,456]/A/B
SCAN2: MOVEI A4,.DSK ; "DSK"
MOVSM A4,1(A1) ; SET DEFAULT VALUE
SETZM 5(A1) ; CLEAR TIME/DATE
SETZM 6(A1) ; CLEAR PPN
PUSHJ SP,SCAN1 ; SCAN 1ST STRING
CAIE A6,.COLON ; ENDS IN COLON?
JRST CS2 ; -NO, MUST BE A FILE NAME
MOVEM A3,1(A1) ; SET DEVICE NAME
PUSHJ SP,SCAN1 ; SCAN NEXT STRING
CS2: MOVEM A3,3(A1) ; SET FILENAME
CAIE A6,.DOT ; ENDS IN DOT?
JRST CS10 ; -NO
PUSHJ SP,SCAN1 ; -YES, SCAN EXTENSION NAME
HLLZM A3,4(A1) ; SAVE EXTENSION NAME
CS10: CAIN A6,.EXCL ; IF EXCLAMATION MARK FOUND
JRST RUNUUO ; THEN TRANSFER TO NEXT CUSP
CAIE A6,.LBRAC ; IF IT IS NOT A "["
JRST SWITCH ; EXIT VIA SWITCH
; SCAN PROJECT/PROGRAMMER NUMBERS
PUSHJ SP,SCAN4 ; SCAN 1ST NUMBER
CAIE A6,.COMMA ; IT IS AN ERROR IF THIS
JRST CSER ; CHAR IS NOT A COMMA
HRLZM A5,6(A1) ; SAVE PROJECT NUMBER
PUSHJ SP,SCAN4 ; SCAN 2ND NUMBER
CAIE A6,.RBRAC ; IF IT'S A ]
CAIN A6,.CR ;
SKIPA ;
JRST CSER ;
HRRM A5,6(A1) ; SAVE PROGRAMMER NUMBER
EDIT(022); MAKE SWITCHES AFTER PPN'S WORK.
PUSHJ SP,SCANCH ; [E022] READ NEXT CHAR.
JRST SWITCH ; [E022] PROCESS SWITCHES, EXIT SCAN2.
; SUBROUTINE TO SCAN PROJECT NUMBER OR PROGRAMMER NUMBER
SCAN4: MOVEI A5,0 ; CLEAR A5
PUSHJ SP,SCANCH ; GET NEXT CHAR
CAIL A6,.N0 ; IF IT IS BELOW "0"
CAILE A6,.N7 ; OR ABOVE "7"
POPJ SP, ; THEN EXIT SCAN4
LSH A5,3 ; MULTIPLY BY 8
ADDI A5,-.N0(A6) ; AND ADD IN CURRENT DIGIT
JRST SCAN4+1 ; LOOP
; CHECK FOR, AND PROCESS, A COMMAND SWITCH
SWITCH: CAIN A6,.SLASH ; SWITCH ?
JRST SW13 ; YES
CAIE A6,.LPAREN ; START OF COMPIL SWITCH-STRING ?
POPJ SP, ; NO.
TLO A7,SPAREN ; YES - REMEMBER
SW13: MOVEI A4,6
SETZM SWIT
SKIPA A5,.+1 ;
POINT 6,SWIT ;
SW1: PUSHJ SP,SCANCH ; GET A CHARACTER
SKIPL CTABLE(A6) ; LETTER ?
JRST SW2 ; NO
ADDI A6,40 ; YES - TO SIXBIT
IDPB A6,A5
SOJG A4,SW1 ; GET UP TO 6
MOVE A5,SWIT ; GET SWITCH
CAMN A5,[SIXBIT/CHECKO/] ; /CHECKON OR /CHECKOFF !
JRST SW3 ; YES
PUSHJ SP,SCANCH
SKIPGE CTABLE(A6) ; SKIP REMAINING
JRST .-2 ; LETTERS
SW2: MOVEM A6,SWDEL ; SAVE DELIMITER CHARACTER
CAIN A4,6
JRST SE1 ; ERROR - NOTHING THERE !
CAIN A4,5 ; 1 CHAR SW ?
TLOA A7,ONECHS ; YES - REMEMBER
TLZ A7,ONECHS ; ELSE REMEMBER NOT
IMULI A4,6
SETO A6,
LSH A6,-^D36(A4) ; MAKE MASK
MOVEM A6,SWMASK
HRLZI A6,-SWTABN
SETZ A4,
SW4: MOVE A5,SWTAB(A6) ; GET AN ENTRY FROM SWITCH-TABLE
ANDCM A5,SWMASK ; MASK IT
CAMN A5,SWIT ; WHAT HE TYPED ?
JRST SW5 ; YES
SW9: AOBJN A6,SW4 ; NO - GET NEXT ENTRY
JUMPE A4,SE2 ; RECOGNIZED - ERROR IF NOT
SW11: SETZ A5,
MOVE A6,SWDEL ; RESTORE DELIMITER
TLNE A4,SWNYET ; "NOT IMPLEMENTED YET" ?
JRST NOTIMP ; YES - TELL HIM
TLNN A4,VALSW ; VALUE WANTED ?
JRST SW12 ; NO
CAIN A6,.COLON ; YES - DELIMITER = COLON ?
JRST SW14 ; YES - OK
TLNN A4,SWVOPT-VALSW ; NO - OPTIONAL ?
JRST SE3 ; NO - COMPLAIN
JRST SW6 ; YES - OK (VALUE = 0)
SW14: JFCL 17,.+1 ; CLEAR OVERFLOW FLAG
SW7: PUSHJ SP,SCANCH ; GET DIGIT
CAIL A6,.N0 ; IS
CAILE A6,.N9 ; IT ?
JRST SW6A ; NO - END OF VALUE
IMULI A5,^D10 ; YES - ADD IT IN
ADDI A5,-.N0(A6)
JOV SE4 ; TOO BIG !
JRST SW7
SW12: CAIN A6,.COLON ; NO VALUE WANTED - DID HE GIVE ONE ?
JRST SE6 ; YES - COMPLAIN
JRST SW6 ; NO - GOOD.
SW6A: CAIN A6,"K" ; nK OR
IMULI A5,^D1024
CAIN A6,"P" ; nP ?
IMULI A5,^D512
JOV SE4 ; TOO BIG.
CAIE A6,"K"
CAIN A6,"P" ; & GET NEXT CHAR
PUSHJ SP,SCANCH
SW6: ; HERE, A5 = VALUE, OR 0
; A6 = DELIMITER (OF SWITCH OR VALUE)
; A4 = DISPATCH TABLE ENTRY
TLNN A4,SETVAL ; SET VALUE TYPE ?
JRST SW10 ; NO
MOVEM A5,@A4 ; YES - SET IT !!MUST BE @, NOT ()!!
JRST SWEND ; GET NEXT SWITCH
SW10: TLNE A4,XCTSW ; EXCECUTE INSTRUCTION TYPE ?
XCT @A4 ; YES - DO IT
TLNN A4,XCTSW ; ELSE
PUSHJ SP,@A4 ; JUMP TO ROUTINE
JRST SWEND ; DONE - GET NEXT SWITCH
SW3: ; CHECKO SCANNED - IS IT -N OR -FF ?
PUSHJ SP,SCANCH ; GET 7TH CHARACTER
CAIN A6,"N" ; CHECKON ?
TRO FL,ACON!ACOO ; YES - REMEMBER
CAIN A6,"F" ; CHECKOFF ?
TRO FL,ACOFF
TRNN FL,ACON!ACOFF ; IF NEITHER FLAG WAS SET
JRST SE2 ; IT'S UNRECOGNIZED
PUSHJ SP,SCANCH ; GOBBLE
SKIPGE CTABLE(A6) ; REMAINING
JRST .-2 ; LETTERS
JRST SWEND ; DO NEXT SWITCH
SW5: SKIPGE SWDTAB(A6) ; 1 CHAR FLAG ?
TLNN A7,ONECHS ; YES - ONLY 1 CHAR TYPED ?
JRST SW8 ; NO
MOVE A4,SWDTAB(A6) ; YES - GET ENTRY
JRST SW11 ; AND DISPATCH
SW8: JUMPN A4,SE5 ; UNIQUE ? - ERROR IF NOT
MOVE A4,SWDTAB(A6) ; YES - GET ENTRY
JRST SW9 ; AND GO ON LOOKING
SE1: OUTSTR [ASCIZ/
? Non-alpha switch
/]
JRST CSER+1
SE2: OUTSTR [ASCIZ/
? Unrecognized/]
JRST SE9
SE3: OUTSTR [ASCIZ/
? No value for/]
JRST SE9
SE4: OUTSTR [ASCIZ/
? Value too large for/]
JRST SE9
SE5: OUTSTR [ASCIZ/
? Non-unique/]
JRST SE9
SE6: OUTSTR [ASCIZ/
? No value allowed for/]
JRST SE9
NOTIMP: OUTSTR [ASCIZ/
? Unimplemented/]
SE9: SKIPA A5,.+1 ;
POINT 6,SWIT ;
SKIPA A6,.+1 ;
POINT 7,SWERR+2 ;
ILDB A4,A5 ; MOVE SWITCH TO TYPE-BUFFER
JUMPE A4,.+4 ; NULL - END ?
ADDI A4,40 ; TO ASCII
IDPB A4,A6
JRST .-4 ; GO ON
IDPB A4,A6 ; DEPOSIT THE NULL (AS ASCIZ TERMINATOR)
OUTSTR SWERR
OUTSTR [ASCIZ/
/]
SETZM SWERR+2 ; CLEAR BUFFER
SETZM SWERR+3
JRST CSER+1
SWEND: TLNN A7,SPAREN ; IN A COMPIL SWITCH-STRING ?
JRST SWITCH ; NO
CAIN A6,.RPAREN ; CORRECT TERMINATOR ?
PUSHJ SP,SCANCH ; YES - GOBBLE IT
JRST SWITCH
; SWITCH TABLES
;
; EACH SWITCH HAS A V-MACRO IN THE DEFINITION OF THE SWS-MACRO.
;
; FORMAT OF THE V-MACRO ENTRY:
;
; V NAME,*,ACTIONS,ADDRESS-OR-INSTRUCTION
;
; WHERE:
;
; NAME IS THE SWITCH-NAME (ALPHA) - ONLY
; THE FIRST 6 ARE USED.
;
; * MEANS THIS SWITCH WILL BE RECOGNIZED IN PREFERENCE TO OTHERS
; BEGINNING WITH THE SAME LETTER, IF ONLY 1 CHARACTER IS
; TYPED (E.G. /H MEANS /HELP, NOT /HEAP)
;
; ACTIONS IS A BIT-MASK, AS FOLLOWS:
;
; VALSW A VALUE (/SW:VALUE) IS EXPECTED
; SETVAL A VALUE IS TO BE SET INTO THE ADDRESS SPECIFIED BY
; THE FOURTH PARAMETER (0 IF NOT VALSW)
; XCTSW AN INSTRUCTION, SUPPLIED AS THE FOURTH PARAMETER, IS
; TO BE OBEYED.
; SWVOPT THE VALUE IS OPTIONAL (IMPLIES VALSW)
; SWNYET NOT-YET-IMPLEMENTED: TYPE MESSAGE & GO TO ERROR
;
; ADDRESS-OR-INSTRUCTION
; IS THE ADDRESS OF THE ROUTINE TO OBEY, OR
; IS THE ADDRESS TO SET A VALUE TO (SETVAL), OR
; IS THE INSTRUCTION TO OBEY (XCTSW).
;
;
DEFINE SWS,<
;; V NAME,*,ACTIONS,ADDRESS
V SYMBOLS,,XCTSW,<TRZ FL,TRPOFF> ; PRODUCE DEBUGGER SYMBOLS (TYPE 1044 BLOCKS)
V NOSYMBOLS,,XCTSW,<TRO FL,TRPOFF>; NO SYMBOL BLOCKS
V NOERRORS,,XCTSW,<TLO A7,NSWIT> ; SUPPRESS ERRORS ON TTY
V NOLIST,,XCTSW,<TRZ FL,LISTOO!CREF> ; TURN OFF LISTING
IFN FTSTATS,<
V STATS,,XCTSW,<TLO A7,STATS> ; STATISTICS
>
IFE FTSTATS,<
V STATS,,SWNYET
>
V LIST,*,XCTSW,<TRO FL,LISTOO> ; TURN ON LISTING
V QUOTED,*,SETVAL,RWS ; QUOTED STROP-WORDS
V NOQUOTES,,,SWNOQT ; UNQUOTED STROP-WORDS
V HEAP,,SETVAL!VALSW,DYNOWN ; CHANGE INITIAL HEAP-SIZE
V HELP,*,XCTSW,<JRST HELPER> ; TELL HIM WHAT TO DO
V TEMPCODE,,SETVAL!VALSW,LTCODE ; TEMPCODE BUFFER SIZE
V NUMBERS,,XCTSW,<TLO A7,ESWIT> ; SEQUENCE NUMBERS
V NONUMBERS,,XCTSW,<TLZ A7,ESWIT> ; NO SEQUENCE NUMBERS
V BUFFERS,,SETVAL!VALSW,<7(A1)> ; # I/O BUFFERS
V TRACE,*,SWVOPT,SWTRAC ; TRACE-BUFFER LENGTH
V PRODUCTION,*,XCTSW,<TRO FL,TRLOFF!TRPOFF>
; SUPPRESS DIAGNOSTIC INFO
V CREF,,XCTSW,<TRO FL,CREF!LISTOO> ; CROSS-REFERENCE LISTING
V NOCREF,,XCTSW,<TRZ FL,CREF> ; NO CREF LISTING
>
SETVAL==200000
VALSW==100000
XCTSW==40000
SWNYET==20000
SWVOPT==10000!VALSW
DEFINE V(A,B,C,D),<
<SIXBIT/A/>>
SWTAB: SWS ; GENERATE SWITCH NAME TABLE
SWTABN==.-SWTAB ; GET # SWITCHES
DEFINE V(A,B,C,D),<
.ZZZ==0
IFIDN <B><*>,<
.ZZZ==400000>
IFNB <C>,<
.ZZZ==.ZZZ!C>
IFN .ZZZ&XCTSW,< ;; GENERATE INSTR, & POINTER
.ZZZ,,[D]>
IFE .ZZZ&XCTSW,< ;; ELSE JUST ENTER VALUE GIVEN
<.ZZZ_^D18>+<D>> >
SWDTAB: SWS ; GENERATE SWITCH DISPATCH TABLE
PURGE SWS
PURGE .ZZZ
PURGE V
XALL
SWNOQT: SKIPA A4,.+1 ;
XWD A1,RESWRD-.A ; SET UP RESERVED-WORD-TABLE
MOVEM A4,RWS ; POINTER
POPJ SP,
SWTRAC: SKIPN A5 ; VALUE GIVEN ?
MOVEI A5,^D100 ; NO - GIVE DEFAULT
MOVEM A5,TRACLN
TRZ FL,TRLOFF!TRPOFF ; & ENSURE TRACING ON
POPJ SP,
HELPER: MOVE A1,[SIXBIT/ALGOL/]
PUSHJ SP,.HELPR
JRST CSER+1 ; TREAT AS SWITCH-ERROR (GET NEXT LINE)
;
; SWITCH SCANNER DATA
;
RELOC
SWIT: BLOCK 2 ; BUFFER FOR SWITCH
SWDEL: BLOCK 1 ; SWITCH DELIMITER SAVE
SWMASK: BLOCK 1 ; SAVE FOR UNIQUENESS-TEST MASK
SWERR: BLOCK 3 ; INITIALISED FROM HISEG.
; ASCIZ/ switch: / ; END OF ERROR-MESSAGE
RELOC
; INPUT THE COMMAND STRING
GETCS: SETZM CSFILE ; CLEAR COMMAND STRING FILE NAME
SETZM CSFILE+1 ; CLEAR COMMAND STRING EXTENSION NAME
SETZM CSFILE+3 ; CLEAR PROJECT/PROGRAMMER NUMBER
SKIPN CCLSW ; IF ENTRY WAS NOT FROM CCL
JRST GETCS2 ; THEN SKIP THIS PART
; READ CCL COMMAND STRING WITH TMPCOR UUO
SETOM CCLSW ; MARK: CCL COMMAND STRING HAS BEEN READ
SKIPA A4,.+1 ; GET TMPCOR PARAMETER
XWD 2,TEMPC1 ; READ JUST FOR LENGTH OF FILE
TMPCOR A4, ; READ TEMPORARY CORE FILE
SKIPA A3,[440600,,A1] ; READ ERROR, SEE IF THERE IS A DISK FILE
JRST GETCS3 ; CONTINUE
; READ CCL COMMAND STRING FROM DISK
PJOB A4, ; GET JOB NUMBER
IDIVI A4,^D100 ; GET 1ST DIGIT
ADDI A4,20 ; CONVERT TO SIXBIT
IDPB A4,A3 ; PUT IN A1
IDIVI A5,^D10 ; GET 2ND AND 3RD DIGITS
ADDI A5,20 ; CONVERT 2ND DIGIT TO SIXBIT
IDPB A5,A3 ; PUT IN A1
ADDI A6,20 ; CONVERT THIRD DIGIT TO SIXBIT
IDPB A6,A3 ; PUT IT IN A1
HRRI A1,.ALG ; A1 NOW CONTAINS XXXALG
MOVEM A1,CSFILE ; SET FILE NAME
MOVEI A1,.TMP ; THE EXTENSION NAME IS TMP
MOVSM A1,CSFILE+1 ; SET EXTENSION NAME
MOVEI A1,.DSK ; DEVICE IS DSK
MOVSM A1,CSLIST+1 ; SET DEVICE NAME
; OPEN COMMAND STRING FILE, WRITE A "*"
GETCS2: OPEN 5,CSLIST ; OPEN COM STRING DEVICE
JRST TERMIN ; CANT OPEN, QUIT
LOOKUP 5,CSFILE ; FIND THE FILE IF THERE IS ONE
JRST TERMIN ; FILE CANNOT BE READ
SKIPE CCLSW ; IF CALLED FROM CCL
JRST GETCS4 ; THEN DONT PRINT COMMAND STRING STAR
OUTBUF 5,1 ; GET A BUFFER RING
OUTPUT 5,0 ; GET AN OUTPUT BUFFER
MOVEI A4,.STAR ; "*"
IDPB A4,STHEAD+1 ; PUT IN OUTPUT BUFFER
OUTPUT 5,0 ; WRITE IT TO THE TTY
; READ IN COMMAND STRING
GETCS4: INBUF 5,1 ; GET AN INPUT BUFFER RING
AOS A4,CSBLK ; POINT AT DESIRED BLOCK OF CMD STRING
USETI 5,(A4) ; AND TELL MONITOR TO READ IT
INPUT 5,0 ; READ THE COMMAND STRING
STATO 5,20000 ; DID WE REACH END OF THE COMMAND FILE ?
JRST GETCS5 ; NOT YET
SETZM CSBLK ; YES, MARK END-OF-COMMAND-FILE REACHED
SETZM CSTRIN ; AND ENSURE NULL TERMINATOR IN C.S.
JRST GETCS3 ; NOW PROCEED TO FETCH THE NULL TERMINATOR
GETCS5: MOVE A4,CSHEAD ; BUFFER ADDRESS
HRLZI A4,2(A4) ; WHERE COMMAND STRING SITS NOW
HRRI A4,CSTRIN ; WHERE TO MOVE IT TO
MOVE A5,CSHEAD+2 ; GET LENGTH OF BUFFER
IDIVI A5,5 ; IN WORDS
BLT A4,CSTRIN-1(A5) ; AND SAVE THE COMMAND STRING
SETZM CSTRIN(A5) ; CLOBBER OLD GARBAGE
EDIT(117); CORRECT COMMAND SCANNER TO IGNORE LEADING SPACES
GETCS3: MOVE A5,[POINT 7,CSTRIN]; [E117] GET BYTE POINTER TO A5
MOVEM A5,CSP ; [E117] SAVE IT
SKIPL CSCOMP ; IF CURRENT CMD FILE NOT FINISHED
POPJ SP, ; THEN RETURN NOW
ILDB A6,A5 ; [E117] GET NEXT CHAR
CAIE A6,.SPACE ; [E117] IF CHAR IS SPACE
CAIN A6,.TAB ; [E117] OR TAB,
JRST .-3 ; [E117] SKIP OVER IT
CAIN A6,.CR ; IF THE 1ST CHARACTER IS A CR
JRST GETCS ; THEN READ ANOTHER COMMAND STRING
CAIN A6,.CZ ; CONTROL-Z ?
EXIT ; YES - ALL DONE
JUMPL A6,GETCS ; DITTO FOR OTHER TERMINATOR
SETZM CSCOMP ; MARK: COMMAND STRING YET TO BE SCANNED
POPJ SP, ; RETURN
SCANCH: ILDB A6,CSP ; FETCH NEXT CHAR
CAIG A6,172 ; LOWER CASE ?
CAIGE A6,141
JRST SCANC1
SUBI A6,40 ; CONVERT IT TO UPPER CASE
POPJ SP,
SCANC1: CAIE A6,.SPACE ; IGNORE SPACES AND TABS
CAIN A6,.TAB
JRST SCANCH
CAIE A6,.LF
CAIN A6,.VT
JRST SCANC2
CAIE A6,.FF
CAIN A6,.ALT1
JRST SCANC2
CAIE A6,.ALT2
CAIN A6,.ALT3
SCANC2: MOVNI A6,1
CAIE A6,0
POPJ SP,
SKIPE CSFILE ; ARE WE READING A DISK CMD FILE ?
SKIPN CSBLK ; YES, ANY MORE TO COME ?
POPJ SP, ; NO, RETURN NULL TERMINATOR NOW
SETZM CSFILE+3 ; CLEAR CMD FILE PPN
MOVEI A6,.DSK ; DEVICE MUST BE RESET TO DSK
MOVSM A6,CSLIST+1 ; AFTER CALL TO BMOVE AT START1+14
PUSH SP,A4 ; SAVE A4 AND A5 OVER
PUSH SP,A5 ; CALL TO GETCS2
PUSHJ SP,GETCS2 ; TO READ NEXT CMD FILE BLOCK
POP SP,A5 ; RESTORE A5,A4
POP SP,A4
JRST SCANCH
RELOC
;----------------------------------------------------------
OLIST: BLOCK 3 ; "B" DATA MODE (14)
; SIXBIT DEVICE
; XWD BHEAD1,0 ; BUFFER HEADER
OFILE: BLOCK 1 ; SIXBIT FILENAME
BLOCK 1 ; SIXBIT EXTENSION
BLOCK 1 ; TIME/DATE
BLOCK 1 ; PROJECT/PROGRAMMER
BLOCK 1 ; NUMBER OF RING BUFFERS
BHEAD1: BLOCK 1 ; OBJECT BUFFER HEADER BLOCK
BLOCK 1 ; WRITE POINTER
BLOCK 1 ; COUNT
;----------------------------------------------------------
LLIST: BLOCK 1 ; "A" DATA MODE
BLOCK 2 ; SIXBIT DEVICE
; XWD BHEAD2,0 ; BUFFER HEADER
LFILE: BLOCK 1 ; SIXBIT FILENAME
BLOCK 1 ; SIXBIT EXTENSION
BLOCK 1 ; TIME/DATE
BLOCK 1 ; PROJECT/PROGRAMMER
BLOCK 1 ; NUMBER OF BUFFERS
BHEAD2: BLOCK 1 ; LISTING BUFFER HEADER BLOCK
W: BLOCK 1 ; LISTING POINTER
BLOCK 1 ; COUNT
;----------------------------------------------------------
SLIST: BLOCK 1 ; "A" DATA MODE
BLOCK 2 ; SIXBIT DEVICE
; XWD 0,BHEAD3 ; BUFFER HEADER
SFILE: BLOCK 1 ; SIXBIT FILENAME
BLOCK 1 ; SIXBIT EXTENSION
BLOCK 1 ; TIME/DATE
BLOCK 1 ; PROJECT/PROGRAMMER
BLOCK 1 ; NUMBER OF BUFFERS
BHEAD3: BLOCK 1 ; SOURCE BUFFER HEADER BLOCK
P: BLOCK 1 ; READ POINTER
BLOCK 1 ; COUNT
;----------------------------------------------------------
CSLIST: BLOCK 3
; 1 ; "AL" DATA MODE
; SIXBIT /TTY/ ; DEVICE
; XWD STHEAD,CSHEAD ; BUFFER HEADS
CSFILE: BLOCK 1 ; SIXBIT FILE NAME
BLOCK 1 ; SIXBIT EXTENSION
BLOCK 1 ; TIME/DATE
BLOCK 1 ; PROJECT/PROGRAMMER NUMBER
CSHEAD: BLOCK 1 ; BUFFER
CSP: BLOCK 1 ; POINTER
BLOCK 1 ; COUNT
;--------------------------------------------------------
STHEAD: BLOCK 3 ; BUFFER HEADER FOR COMMAND STRING STAR
CSLEN==201 ; LENGTH OF COMMAND STRING BUFFER
CSTRIN: BLOCK CSLEN ; COMMAND STRING BUFFER
CCLSW: BLOCK 1 ; CCL SWITCH. 1=ENTERED FROM CCL
RFLAGS: BLOCK 1 ; READ-MODULE FLAGS
BLOCK1: BLOCK 1 ; BEGINNING OF SYMBOL TABLE BLOCK 1
STACKB: BLOCK 1 ; BEGINNING OF STACK
COREB: BLOCK 1 ; BEGINNING OF CORE ACQUIRED WITH CORE UUO
COREND: BLOCK 1 ; END OF LOW SEGMENT
LTCODE: BLOCK 1 ; LENGTH OF TEMPCODE
CSCOMP: BLOCK 1 ; -1 = COMMAND STRING COMPLETELY SCANNED
; 0 = COMMAND STRING CONTAINS YET ANOTHER COMP.
; 1 = CURRENT LINE OF COM.STRING NOT COMPLETELY SCAND.
CSBLK: BLOCK 1 ; POINTER TO WHICH CMD FILE BLK WE'RE AT
CHKSUM: BLOCK 1 ; CHECK SUM
PNBUF: BLOCK 2 ; PREPARED NAME BUFFER
RELOC
TEMPC1: XWD .ALG,0 ; TMPCOR READ BLOCK
IOWD CSLEN,CSTRIN
SUBTTL ** A RANDOM COLLECTION OF RANDOM ROUTINES **
; TERMINATE COMPILATION DUE TO ABNORMAL CONDITION
TERMIN: OUTSTR TERMSG ; WRITE TERMINATE MSG
EDIT(001); DON'T DELETE OLD .REL-FILE IF DISASTERS STRIKE.
QUIT: CLOSE 1,40 ; [E001] CLOSE OBJECT FILE
CLOSE 2,0 ; CLOSE LISTING FILE
CLOSE 3,0 ; CLOSE SOURCE FILE
SKIPN CSFILE ; HAVE WE A DSK CMD FILE ?
JRST QUIT1 ; NO SO NO NEED TO DELETE IT !
PUSHJ SP,GETCS ; YES, OPEN IT
SETZM CSFILE ; CLEAR ITS NAME
RENAME 5,CSFILE ; AND DELETE IT
JFCL ; IGNORE ERRORS
CLOSE 5,0 ; CLOSE THE DEVICE
SETZM CSBLK ; MARK IT ABSENT
QUIT1: MOVE A4,COREB ; GET ORIGINAL VALUE OF JOBFF
HRRZM A4,.JBFF ; RETURN CORE USED DURING COMPILATION
SETZM COREB ; MARK: RETURNED
EXIT ; RETURN TO MONITOR
; COMMAND STRING ERROR
CSER: OUTSTR CSERM ; WRITE MSG
SETOM CSCOMP ; MARK: COMMAND STRING FULLY SCANNED
SKIPN CCLSW ; TERMINATE IF CALLED FROM CCL
TLNE A7,CSDONE ; IF COMMAND STRING ONLY PART SCANNED
JRST TERMIN ; THEN TERMINATE
JRST START2 ; ELSE GET ANOTHER COMMAND STRING
; WRITE TO LISTING, GET NEXT OUTPUT BUFFER
WRITEL: HLLZ A3,W ; GET S-P BITS
ROT A3,4 ; PUT 1ST 4 BITS IN RIGHT HALF
SETCM A3,MSKTBL(A3) ; GET A MASK FROM TABLE
ANDM A3,@W ; DELETE TRAILING EXTRA CHARS
OUT 2,0 ; GET NEXT OUTPUT BUFFER
JRST .+3 ; -OK, SKIP
OUTSTR LISTER ; -OUTPUT ERROR
JRST TERMIN ; TERMINATE COMP
; WRITTEN OK, MARK END OF NEW BUFFER
MOVE A6,BHEAD2 ; ADDR OF CURRENT BUFFER
HLRZ A3,(A6) ; LENGTH OF BUFFER
TLZ A6,USE ; ZERO USE BIT
ADDI A6,(A3) ; ADD LENGTH TO ADDRESS
MOVEM A6,OBEND ; SAVE ADDR OF END OF BUFFER DATA
POPJ SP, ; EXIT
; ALLOCATE BUFFER SPACE
ALLOCATE:
PUSH SP,.JBFF ; SAVE ADDRESS OF BUFFER
ADDB A1,.JBFF ; SET NEW VALUE OF FREE SPACE POINTER
CAMGE A1,.JBREL ; IF NOT BEYOND END OF LOW SEGMENT
JRST .+3 ; THEN SKIP THIS
CORE A1, ; MOVE UP THE TOP OF THE LOW SEG
JRST TERMIN ; -CANNOT ACQUIRE MORE CORE
POP SP,A1 ; GET ADDRESS OF BUFFER
POPJ SP, ; EXIT ALLOCATE
; CANNOT OPEN SOURCE DEVICE
DSERR1: SKIPA A1,[ ; INCLUDE DEVICE IN MSG
POINT 6,SLIST+1] ; POINTER TO DEVICE NAME
; CANNOT OPEN LISTING FILE
DSERR3: MOVE A4,[POINT 6,LLIST+1] ; LOAD POINTER TO LISTING DEVICE NAME
DSERR0: MOVEI A6,6 ; 6 CHARS LONG
PUSHJ SP,PRENAM ; WRITE TO TTY
OUTSTR ILLDEV ; WRITE REST OF MSG
JRST CSER+1 ; TERMINATE COMP
; WRITE DEVICE NAME ON TTY
PRENAM: MOVE A5,[ ; POINTER TO WHERE
POINT 7,PNBUF] ; PREPARED NAME WILL GO
MOVEI A3,.QUESTION
IDPB A3,A5 ; OUTPUT A "?"
PNL: ILDB A3,A4 ; GET A CHAR
MOVEI A3,40(A3) ; CONV TO ASCII
IDPB A3,A5 ; PUT IN BUFFER
SOJG A6,PNL ; LOOP
IDPB A6,A5 ; END BUFFER WITH A NULL
OUTSTR PNBUF ; WRITE BUFFER TO TTY
POPJ SP, ; EXIT
; CANNOT READ FROM INDICATED SOURCE FILE
DSERR2: HLRZ A4,SFILE+1 ; IF EXTENSION NAME IS NULL
JUMPE A4,.+3 ; THEN THE ERROR IS REAL
SETZM SFILE+1 ; OTHERWISE CHANGE FROM .ALG TO .
JRST CS9 ; AND TRY AGAIN
MOVE A4,[ ; PUT FILENAME IN MSG
POINT 6,SFILE] ; POINTER TO FILENAME
MOVEI A6,6 ; 6 CHARS LONG
PUSHJ SP,PRENAM ; WRITE FILENAME TO TTY
OUTSTR ..DOT ; WRITE DOT TO TTY
MOVEI A6,3 ; 3 CHAR EXTENSION LENGTH
MOVE A5,[POINT 7,PNBUF]
PUSHJ SP,PNL ; WRITE FILENAME EXT TO TTY
MOVE A6,SFILE+1
ANDI A6,7 ; GET LOOKUP RETURN CODE
CAIN A6,2 ; IF RC=2,
JRST READPR ; THEN FILE READ PROTECTED
OUTSTR NOFILE ; ELSE FILE DOESNT EXIST
JRST CSER+1 ; TERMINATE COMP
READPR: OUTSTR READPM ; WRITE MSG
JRST CSER+1 ; TERMINATE COMP
..DOT: ASCIZ /./ ; DOT
IFLAGS: XWD <WITHIN+COMPLETE>&777777,NORMAL ; INITIAL READ MODULE FLAGS
; UNABLE TO CREATE LISTING FILE
DSERR4: OUTSTR UNLIST ; UNABLE TO CREATE LISTING
JRST CSER+1 ; TERMINATE COMP
; PUT 2-DIGIT DECIMAL NUMBER IN LISTING
DEC2: IDIVI A4,^D10 ; A4=TENS, A5=ONES
MOVEI A4,.N0(A4) ; CONV TO ASCII
IDPB A4,A3 ; MOVE TO LISTING
MOVEI A5,.N0(A5) ; CONV TO ASCII
IDPB A5,A3 ; MOVE TO LISTING
IDPB A14,A3 ; MOVE : OR - TO LISTING
POPJ SP, ; EXIT
; RUN THE NEXT CUSP
RUNUUO: SKIPE .JBERR ; IF THERE WERE ERRORS
JRST QUIT ; THEN ABORT LOADING
MOVSI A3,(SIXBIT /SYS/)
MOVEM A3,LB ; SEARCH DEVICE
MOVE A3,OFILE ; GET NAME OF PROGRAM TO BE CALLED
MOVEM A3,LB+1 ; PUT IN PARAMETER BLOCK
SETZM LB+2
SETZM LB+3
SETZM LB+4
SETZM LB+5 ; CLEAR OUT THE REST
HRLZI A4,1 ; ENTER IT AT ITS CCL ENTRY POINT
HRRI A4,LB ; ADDRESS OF PARAMETER BLOCK
RUN A4, ; LOAD AND RUN NEXT CUSP
JRST TERMIN ; CUSP NOT FOUND, STOP
; PUT CURRENT DATE AND TIME IN LISTING
DATIME: MOVE A3,LBP ; GET BUFFER POINTER
DATE A4, ; GET DATE
IDIVI A4,^D372 ; DIVIDE BY 372 DAYS/YEAR
IDIVI A5,^D31 ; DIVIDE BY 31 DAYS PER MONTH
MOVE A1,A5 ; SAVE ACC A5
MOVE A2,A4 ; SAVE ACC A4
MOVEI A14,.MINUS ; -
MOVEI A4,1(A6) ; DAY
PUSHJ SP,DEC2 ; WRITE 2 DIGITS
ROT A1,-1
MOVEI A4,[SIXBIT /JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC/](A1)
JUMPGE A1,.+2
TLOA A4,(POINT 6,0,17)
TLO A4,(POINT 6,0,) ; GET MONTH
MOVEI A5,3
ILDB A6,A4
ADDI A6,40
IDPB A6,A3
SOJG A5,.-3 ; AND WRITE IT
IDPB A14,A3
MOVEI A4,100(A2) ; YEAR
PUSHJ SP,DEC2 ; WRITE 2 DIGITS
MOVEI A1,.SPACE ; BLANK
DPB A1,A3 ; INCLUDE
MOVEI A5,3 ; FOUR
IDPB A1,A3 ; BLANKS.
SOJG A5,.-1 ; PUT A BLANK IN LISTING
MSTIME A4, ; GET TIME OF DAY
IDIVI A4,^D1000 ; CONVERT TO SECONDS
IDIVI A4,^D3600 ; DIVIDE BY 3600 SEC/HOUR
IDIVI A5,^D60 ; DIVIDE BY 60 SEC/MIN
MOVE A2,A5 ; SAVE ACC A5
MOVEI A14,.COLON ; :
PUSHJ SP,DEC2 ; WRITE HOUR AS 2 DIGITS
MOVE A4,A2 ; MINUTE
PUSHJ SP,DEC2 ; WRITE 2 DIGITS
MOVE A4,A6 ; SECOND
PUSHJ SP,DEC2 ; WRITE 2 DIGITS
MOVEI A1,0 ; ASCII NULL
DPB A1,A3 ; PUT NULL AT END OF MESSAGE
MOVEI A1,LB ; ADDR OF BUFFER
PUSHJ SP,INSERT ; INSERT LINE IN LISTING
TLNE A7,LTTY ; IF LISTING IS TO TTY:
JRST DATIM1 ; THEN DON'T DO IT
MOVEI A1,COMSTR
PUSHJ SP,INSERT
MOVEI A1,CSTRIN
PUSHJ SP,INSERT
DATIM1: MOVEI A1,LINES3 ; 3 BLANK LINES
PUSHJ SP,INSERT ; INSERT IN LISTING
JRST ICHECK ; ALIGN TO A FULLWORD, EXIT DATIME
RELOC
LINK: BLOCK 1 ; RETURN LINK
LINK1: BLOCK 1 ; RETURN LINK .PINIT
OLDSBR: BLOCK 1 ; OLD SOURCE BUFFER RING
RELOC
; "DEC" WILL CONVERT THE NUMBER IN A4 TO DECIMAL ASCII CHARACTERS,
; AND PLACE THE RESULT DIRECTLY INTO THE LISTING. "DEC" WILL PRINT
; THE NUMBER RIGHT-JUSTIFIED IN A FIELD WHOSE SIZE IS SPECIFIED IN
; A3. "DEC" WILL PRECEDE THE FIRST PRINTABLE CHARACTER OF THE NUMBER
; WITH THE CHARACTER THAT IS SPECIFIED IN RH A2.
; "CRFDEC" WILL FILL THE FIELD WITH THE CHARACTER IN LH A2,
; INSTEAD OF BLANKS
DEC: HRLI A2," " ; BLANK-FILL
CRFDEC: MOVE A1,A3 ; COPY NUMBER OF CHARS
IDIVI A4,^D10 ; DIVIDE BY 10
LSHC A5,-4 ; MOVE REMAINDER TO ACC A3
SOJG A1,.-2 ; LOOP TILL END OF NUMBER
HLRZ A1,A2 ; PUT FILLER IN ACC A1
DEC1: LSHC A5,4 ; GET NEXT CHAR FROM A6
JUMPN A5,DEC3 ; JUMP IF NON ZERO
EDIT (203); ;[203]
CAIN A3,1 ;[203] LAST CHARACTER AND STILL A ZERO?
JRST DEC3 ;[203] GO PRINT IT THEN
IDPB A1,W ; INCLUDE A LEADING BLANK
SOJG A3,DEC1 ; LOOP TILL END OF NUMBER
DEC3: DPB A2,W ; INCLUDE SPECIAL CHARACTER
MOVEI A5,.N0(A5) ; CONVERT TO ASCII
IDPB A5,W ; PUT NUMBER IN LISTING
MOVEI A5,0 ; CLEAR A5
LSHC A5,4 ; GET NEXT CHAR FROM A6
SOJG A3,DEC3+1 ; LOOP TILL END OF NUMBER
POPJ SP, ; EXIT DEC - A3=0 IS RELIED ON!
; DETERMINE WHETHER NL CHAR IS FOR END OF LINE OR END OF BUFFER
NCHECK: MOVE A1,P ; GET READ POINTER
CAMN A1,IBEND ; IF AT END OF BUFFER
JRST INEND1 ; THEN GET ANOTHER BUFFER
JRST SKRET ; EXIT NCHECK
; COMPUTE LENGTH OF TAB
TAB: MOVE A2,CC ; GET CHAR COUNT
SUB A2,LP1 ; COMPUTE POSITION ON CURRENT LINE
ADDI A2,^D8 ; TAB TO THE NEW POSITION
ANDCMI A2,7 ; BACK UP TO 8-CHAR MULTIPLE
SUBI A2,1 ; BACK UP 1 MORE CHAR
ADD A2,LP1 ; COMPUTE NEW CHARACTER COUNT
MOVEM A2,CC ; SE IT
MOVE A2,CTABLE(A1) ; RELOAD THE TABLE ENTRY VALUE
POPJ SP, ; EXIT TAB
CSERM: ASCIZ /?INVALID COMMAND STRING
/
TERMSG: ASCIZ /?COMPILATION TERMINATED
/
LISTER: ASCIZ /?OUTPUT ERROR ON LISTING
/
ILLDEV: ASCIZ / DEVICE NOT AVAILABLE
/
NOFILE: ASCIZ / FILE DOES NOT EXIST
/
DDTMSG: ASCIZ / DDT is loaded
/
HEADIN: ASCIZ /DECSYSTEM-20 ALGOL-60, Version / ; [274]
READPM: ASCIZ / FILE READ PROTECTED
/
UNLIST: ASCIZ /?CANNOT CREATE LISTING FILE
/
LINES3: ASCIZ /
/
FORM: XWD 060000,0
ERRORM: ASCIZ / errors
/
QUERY: ASCIZ /?/
ALGOL: ASCIZ /ALGOL: / ;[251]
ALGDDT: ASCIZ/ALGDDT: /
COMSTR: ASCIZ/
Command string: /
SUBTTL ** RINIT **
; CREATE OBJECT FILE
CS5: SKIPE OFILE ; IF FILE NAME NOT NULL
JRST NOOBJ-1 ; THEN CREATE THE OBJECT FILE
MOVS A5,OLIST+1 ; GET DEVICE NAME
CAIE A5,.DSK ; UNLESS DEVICE NAME IS DSK
PUSHJ SP,WRITE1 ; CREATE OBJECT FILE
; WRITE "ALGOL: NAME "
NOOBJ: PUSHJ SP,WRITE0 ; ELSE CALL WRITE0
TLO A7,CSDONE ; 1ST PART OF CS DONE
SKIPN CCLSW ; IF THIS IS NOT A CCL RUN
JRST LST1 ; THEN SKIP THIS
SKIPN .JBDDT ; IF NO DDT ..
OUTSTR ALGOL ; WRITE "ALGOL: "
SKIPE .JBDDT ; ELSE..
OUTSTR ALGDDT ; ..WRITE "ALGDDT: "
MOVEI A4,6 ; WRITE 6 CHARACTERS OF FILE NAME
MOVE A5,[ ; LOAD A POINTER TO
XWD 440600,SFILE] ; THE NAME OF THE SOURCE FILE
ILDB A6,A5 ; GET NEXT SIXBIT CHARACTER
ADDI A6,40 ; CONVERT IT TO ASCII
TTCALL 1,A6 ; WRITE IT TO TERMINAL
SOJG A4,.-3 ; LOOP
OUTSTR NLCHRS ; WRITE A CR/LF
; CREATE LISTING
LST1: SETZM W ; ZERO W
SKIPE LFILE ; IS THERE A LISTING?
JRST LST ; -YES
MOVS A5,LLIST+1 ; -MAYBE, CHECK DEVICE
CAIN A5,.DSK ; DSK?
JRST NOLST ; -YES, NO LISTING
LST: MOVE A5,LLIST+1 ; GET DEVICE NAME
DEVCHR A5, ; GET DEVICE CHARACTERISTICS WITH DEVCHR
TLNE A5,DEVTTY ; IF LISTING DEVICE IS A TTY
TLO A7,LTTY!NSWIT ; THEN SET INDICATOR
TLNE A5,DEVTTY ; AND
TRZ FL,CREF ; TURN OFF CREF'ING.
OPEN 2,LLIST ; OPEN LISTING
JRST DSERR3 ; -SOMETHING WRONG
OUTBUF 2,@LLIST+7 ; GET A BUFFER RING
HLRZ A3,LFILE+1 ; GET EXT
CAIE A3,777777 ; STILL GARBAGE ?
JRST LST2 ; NO - USE HIS
MOVEI A3,.LST ; YES USE .LST
TRNE FL,CREF ; UNLESS WE'RE CREF'ING
MOVEI A3,.CRF ; IN WHICH CASE USE .CRF
MOVSM A3,LFILE+1
LST2: ENTER 2,LFILE ; CREATE FILE
JRST DSERR4 ; -CANNOT CREATE
TLO A7,EXISTS ; SET FLAG: FILE EXISTS
SETZM FIVEC ; INIT FIVE CHAR COUNT
; PUT HEADING IN LISTING
PUSHJ SP,WRITEL ; GET THE 1ST LISTING BUFFER
MOVEI A1,FORM ; ADDRESS OF A FORM FEED
TLNE A7,LTTY ; IF LISTING IS SENT TO TTY
PUSHJ SP,INSERT ; THEN SEND A FORM-FEED THERE
MOVEI A1,HEADIN ; ADDR OF HEADING
PUSHJ SP,INSERT ; PUT IN LISTING
MOVE A6,LBP ; PREPARE TO PRINT VERSION NUMBER
LDB A1,[POINT 9,.JBVER,11]
EDIT(111); INSERT VERSION NUMBER IN OCTAL
PUSHJ SP,LST4 ; [E111] INSERT OCTAL VALUE
LDB A1,[POINT 6,.JBVER,17]
JUMPE A1,LST3
IDIVI A1,^D26
JUMPE A1,.+3 ; FIRST LETTER OF..
ADDI A1,.A-1
IDPB A1,A6 ; ..MINOR VERSION NUMBER
ADDI A2,.A-1
IDPB A2,A6 ; ..AND ITS SECOND LETTER
LST3: MOVEI A1,.LPAREN
IDPB A1,A6
HRRZ A1,.JBVER ; [E111] GET EDIT NUMBER
PUSHJ SP,LST4 ; [E111] INSERT IT IN OCTAL
MOVEI A1,.RPAREN
IDPB A1,A6
MOVEI A1,.SPACE
MOVEI A4,3
IDPB A1,A6 ; INSERT THREE SPACES
SOJG A4,.-1
MOVEI A1,0
IDPB A1,A6
MOVEI A1,LB
PUSHJ SP,INSERT
PUSHJ SP,DATIME ; PUT DATE, TIME AND COMMAND-STRING IN LISTING
TLNE A7,LTTY ; IF LISTING IS TO TTY
PUSHJ SP,WRITEL ; THEN CLEAR THE BUFFER
JRST NOLST1 ; CONTINUE
LST4: IDIVI A1,10 ; [E111] SPLIT OFF OCTAL DIGIT
JUMPE A1,LST5 ; [E111] JUMP IF ALL DONE
HRLM A2,(SP) ; [E111] OTHERWISE SAVE DIGIT
PUSHJ SP,LST4 ; [E111] AND INSERT EARLIER
HLRZ A2,(SP) ; [E111] DIGITS FIRST.
LST5: ADDI A2,.N0 ; [E111] CONVERT TO ASCII
IDPB A2,A6 ; [E111] INSERT IN TEXT
POPJ SP, ; [E111] AND RETURN
NOLST: HRRI A7,NLIST1 ; SET FLAGS ADDR
; INITIALIZE VARIABLES AND TABLES
NOLST1: SETZM CC ; INIT CHARACTER COUNT
IFN FTSTATS,<
SETZM DEFCNT ; INIT
SETZM IDCHRS ; STATS
SETZM REFCNT ; COUNTERS.
>
SETZM OLDNO ; INIT OLD LINE NUMBER
SETZM LINE5 ; INIT 5-CHAR LINE NUMBER
SETZM LSBUFP ; INIT NAME BUF LIST POINTER
SETZM BNUM ; INIT BEGIN NUMBER
SETZM LBNUM ; INIT LAST BEGIN NUMBER
SETZM ENUM ; INIT END NUMBER
SETZM LENUM ; INIT LAST END NUMBER
SETZM NSYM ; INIT NSYM
SETZM PLIST+4 ; INIT PLIST+4
SETZM NDEL ; INIT NDEL
SETZM DUBBLE ; INIT DUBBLE
SETZM BLEX ; INIT BUFFERED LEXEME
SETZM .JBERR ; INIT ERROR COUNT
SETZM WRNCNT ;[171] INIT WARNING COUNT
SETZM TBLEN ; INIT TMPBUF DATA LENGTH WORD
SETZM SSTART ; INIT SEGMENT START
SETZM LINENO ; INIT LINENO
SETZM NXTSLN ; CLEAR NEXT STATEMENT NUMBER FOR SYM
SETZM NXTDLN ; AND DEL (WILL BE COPIED BY RUND)
SETOM LSTSLN ; MAKE LAST AN IMPOSSIBLE VALUE
SETOM LASTRA ; MAKE SURE FIRST STN IS SENT
SETZM SENDSN ; MARK NOT SET UP YET
SETZM STCFL ; INIT STRING CHARACTERS FLAG
MOVEI A4,50 ; SET THE BEGIN TABLE INDEX
MOVEM A4,BTI ; TO 50
MOVEI A4,MTABLE ; ADDRESS OF MTABLE
MOVEM A4,NAMTE ; INIT MESSAGE TABLE POINTER
MOVEI A4,PLIST+3 ; ADDR OF POINTER TABLE
MOVEM A4,PLIST ; INIT UP-ARROW LIST
MOVEM A7,RFLAGS ; SAVE THE FLAGS
HRRZ A4,.JBFF ; GET ADDRESS OF FREE SPACE
MOVEM A4,TCBASE ; USE AS BASE FOR ALLOCATION
JSP A1,.PINIT ; ALLOCATE TABLES
MOVEM A7,A7SAV ; SAVE A7
MOVE A7,RFLAGS ; GET FLAGS AGAIN
PUSHJ SP,READ ; READ IN FIRST LINE OF SOURCE
EMPTY: TLZ A7,WITHIN ; MARK: WITHIN NEWLINE
MOVE A2,P ; GET READ POINTER
MOVEM A2,LSTART ; SAVE POINTER TO LINE START
PUSHJ SP,NL11 ; CHECK FOR LINE NUMBERS, ETC
HALT . ; CANT POSSIBLY RETURN HERE
EMPTY1: SETOM NDEL ; MAKE IT LOOK LIKE SOMTHING IS IN NDEL
PUSHJ SP,RUND ; DO AN INITIAL RUND
AOJA DEL,@LINK ; CLEAR DEL AND EXIT
SUBTTL ** PINIT **
.PINIT: MOVEM A1,LINK1 ; SAVE RETURN LINK
; INITIALIZE VARIABLES
SETZM TOFIXI ; INIT FIXUP TABLE HALFWORD INDEX
SETZM RA ; INIT PROGRAM COUNTER
SETZM FNLEVEL ; INIT FUNCTION LEVEL
SETZM BLOCKL ; INIT BLOCK LEVEL
SETZM LEXBLOCK ; INIT LEXICAL BLOCK LEVEL
SETZM CURBLOCK ; INIT CURRENT BLOCK LEVEL
SETZM THUNK ; INIT THUNK
SETOM CAX ; INIT CAX
SETOM PROSKIP ; INIT PROCEDURE SKIP
HRLZI DBASE,400000 ; INIT DISPLAY POINTER
HRLZI DBASE+1,400000 ; INIT DISPLAY POINTER
MOVEI A4,A13+1 ; INIT
MOVEM A4,LAC ; LAC
HRLZI STOPS,160000 ; INIT STOPS
; ACQUIRE SPACE FOR TABLES
MOVE A5,TCBASE ; BASE OF AVAILABLE CORE
ADD A5,LTCODE ; THE LENGTH OF TEMPCODE
ADDI A5,TABLES+CONL+STACKL+1
; PLUS THE LENGTH OF SYMBOL AND FIXUP TABLES
; PLUS LENGTH OF CONSTANT TABLE
; PLUS LENGTH OF STACK
MOVEM A5,COREND ; SAVE THE CALLI PARAMETER
HRRZM A5,.JBFF ; SET NEW VALUE OF JOBFF
CORE A5, ; GET CORE FOR ALL OF THAT
JRST TERMIN ; CORE NOT AVAILABLE, TERMINATE
; ALLOCATE TABLES
MOVE SP,TCBASE ; BASE OF TEMPCODE
MOVEM SP,INDEX ; SET THE TEMPCODE INDEX
ADD SP,LTCODE ; ADD LENGTH OF TEMPCODE
MOVEM SP,TCMAX ; SET END OF TEMPCODE
ADDI SP,1 ; LEAVE 1 WORD BETWEEN SYMBOL TABLE AND TEMPCODE
MOVEM SP,BLOCK1 ; WHICH IS ALSO THE START OF THE SYMBOL TABLE
MOVEM SP,STBB ; START OF CURRENT BLOCK IN SYMBOL TABLE
MOVEM SP,NASTE ; 1ST AVAILABLE ENTRY IN SYMBOL TABLE
ADDI SP,TABLES ; ADD LENGTH OF TABLES
MOVEM SP,CONTAB ; SET BASE OF CONSTANT TABLE
MOVEM SP,FIXUP ; WHICH IS ALSO THE BASE OF THE FIXUP TABLE
MOVEM SP,LASTST ; END OF STRING CHAIN
MOVEI A5,1(SP) ; STEP OVER 1ST WORD OF CONSTANTS TABLE
MOVEM A5,NACTE ; SET NEXT AVAILABLE CONSTANT TABLE ENTRY
MOVEI A5,-1(SP) ; BACK UP 1
MOVEM A5,NAFTE ; SET NEXT AVAILABLE FIX-UP TABLE ENTRY
MOVEM A5,LASTC1 ; SET CONSTANT TABLE POINTER
MOVEI A5,-2(SP) ; BACK UP 1 MORE
MOVEM A5,LASTC2 ; SET CONSTANT TABLE POINTER
ADDI SP,CONL ; ADD LENGTH OF CONSTANT TABLE
MOVEM SP,CONEND ; SET END OF CONSTANT TABLE
MOVEM SP,STACKB ; SAVE BEGINNING ADDR OF STACK
HRLI SP,-STACKL ; SET UP STACK POINTER
MOVE A4,INDEX ; TEMPCODE POINTER
HRLI A4,770000 ; INIT
MOVEM A4,HANDLE ; HANDLE
HRREI A4,-1 ; THE 1ST ENTRY IN THE CONSTANTS TABLE MUST
PUSHJ SP,CON1 ; BE A CONSTANT OF -1
MOVEI A1,B0LIST## ; INIT LIST
PUSHJ SP,BMOVE ; INITIALIZE BLOCK-0 FROM HIGH SEGMENT
JRST @LINK1 ; EXIT .PINIT
SUBTTL ** TABLE OVERFLOW ROUTINES **
; SYMBOL TABLE OR FIXUP TABLE OVERFLOW
OVFL1: PUSHJ SP,OVFLS ; SAVE SOME REGISTERS
MOVE A4,NAFTE ; BASE OF CORE TO MOVE
PUSHJ SP,OVFL ; MOVE IT
ADDM A4,CONTAB ; UPDATE BASE OF CONSTANT TABLE
ADDM A4,FIXUP ; UPDATE BASE OF FIXUP TABLE
ADDM A4,LASTST ; UPDATE STRING CHAIN
ADDM A4,NACTE ; UPDATE CONSTANT TABLE POINTER
ADDM A4,NAFTE ; UPDATE FIXUP TABLE POINTER
ADDM A4,LASTC1 ; UPDATE 1-WORD CONSTANT CHAIN
ADDM A4,LASTC2 ; UPDATE 2-WORD CONSTANT CHAIN
OVFL3: ADDM A4,CONEND ; UPDATE POINTER TO END OF CONSTANT TABLE
ADDM A4,STACKB ; UPDATE BASE OF STACK
MOVE A4,OVA ; RESTORE A4
MOVE A5,OVB ; RESTORE A5
MOVE A6,OVC ; RESTORE A6
MOVE A3,OVD ; RESTORE A3
POPJ SP, ; EXIT OVFL1 OR OVFL2
; CONSTANTS TABLE OVERFLOW
OVFL2: PUSHJ SP,OVFLS ; SAVE SOME REGISTERS
MOVE A4,CONEND ; BASE OF CORE TO MOVE
PUSHJ SP,OVFL ; MOVE IT
JRST OVFL3 ; CONTINUE
OVFL: MOVEI A5,DELTA ; LENGTH OF CORE TO ACQUIRE
ADDB A5,COREND ; NEW END OF LOW SEGMENT
HRRZM A5,.JBFF ; SET JOBFF
CORE A5, ; GET SOME MORE CORE
JRST OVFLX ; -CANT GET IT
MOVE A5,COREND ; GET NEW END OF CORE
ADDI A5,1-DELTA ; BLT "TO" ADDRESS
HRLI A5,-DELTA(A5) ; BLT "FROM" ADDRESS
JRST OVFLL1 ; JUMP INTO MOVE LOOP
OVFLL: MOVE A3,A5 ; COPY BLT PARAM TO A3
BLT A3,DELTA-1(A5) ; MOVE A DELTA OF CORE
SUB A5,[ ; COMPUTE THE NEXT BLT CONSTANT
XWD DELTA,DELTA] ; BACK UP TO NEXT DELTA
OVFLL1: HLRZ A6,A5 ; GET THE "FROM" ADDRESS
CAILE A6,(A4) ; IF ABOVE THE BASE OF CORE TO MOVE
JRST OVFLL ; THEN CONTINUE LOOPING
HRL A4,A4 ; FORM A NEW BLT POINTER FOR
ADDI A4,DELTA ; CORE OF SIZE LESS THAN DELTA
MOVE A3,A4 ; COPY BLT CONSTANT TO A3
BLT A3,DELTA-1(A5) ; MOVE THE LESS THAN DELTA CORE
MOVE A4,[ ; CORRECTION FACTOR FOR DISPLAY POINTERS
XWD DELTA,DELTA] ; VALUE
MOVEI A5,DBASE ; HEAD OF CHAIN
ADDM A4,(A5) ; UPDATE THE POINTER
HLRE A5,(A5) ; LOCATE NEXT DISPLAY POINTER IN CHAIN
JUMPG A5,.-2 ; LOOP UNLESS END OF LIST
MOVEI A5,DBASE+1 ; HEAD OF CHAIN
ADDM A4,(A5) ; UPDATE THE POINTER
HLRE A5,(A5) ; LOCATE NEXT DISPLAY POINTER IN CHAIN
JUMPG A5,.-2 ; LOOP UNLESS END OF LIST
MOVEI A4,DELTA ; UPDATE FACTOR
ADD SP,A4 ; SET POINTER TO NEW LOCATION OF STACK
POPJ SP, ; EXIT OVFL
OVFLX: OUTSTR OVFLXM ; SEND MSG TO TTY
JRST TERMIN ; TERMINATE COMPILATION
OVFLXM: ASCIZ /?MORE CORE REQUIRED
/
OVFLS: MOVEM A4,OVA ; SAVE A4
MOVEM A5,OVB ; SAVE A5
MOVEM A6,OVC ; SAVE A6
MOVEM A3,OVD ; SAVE A3
POPJ SP, ; EXIT OVFLS
; STACK OVERFLOW ALLOCATING STACK LOCALS
OVFL5: MOVEM A4,OVA ; SAVE ACC A4
MOVE A4,.STOVE ; GET RETURN LINK
MOVEM A4,.JBTPC ; SAVE IN JOBTPC
JRST .+2 ; SKIP
; STACK OVERFLOW BY PUSH OR PUSHJ
OVFL4: MOVEM A4,OVA ; SAVE IN ACC A4
MOVEI A4,DELTA ; CORE INCREMENT
ADDB A4,COREND ; NEW END OF LOW SEGMENT
HRRZM A4,.JBFF ; SET JOBFF
CORE A4, ; GET MORE CORE
JRST OVFLX ; -NOT AVAILABLE, TERMINATE
HRLZI A4,-DELTA ; CORRECTION CONSTANT
ADD SP,A4 ; FIX UP STACK POINTER
MOVE A4,OVA ; RESTORE ACC A4
JRST 2,@.JBTPC ; RETURN TO COMPILATION
RELOC
OVA: BLOCK 1
OVB: BLOCK 1
OVC: BLOCK 1
OVD: BLOCK 1
.STOVE: BLOCK 2 ; RETURN LINK
; JRST OVFL5 ; JUMP INTO HIGH SEGMENT
RELOC
SUBTTL ** NEW-LINE **
; *** NEW-LINE ROUTINE ***
;
; THIS ROUTINE IS CALLED WHENEVER A CARRIAGE-RETURN, LINE-FEED,
; OR OTHER SUCH CHARACTER IS SCANNED. NEWLINE PERFORMS ALL I/O
; PROCESSING ASSOCIATED WITH THE SOURCE AND LISTING FILES.
; NEWLINE RETURNS IN REGISTER A1 THE 1ST CHAR OF THE NEXT
; LINE. REGISTERS A1 - A6 ARE NOT SAFE OVER NEWLINE.
;
;
; THROUGHOUT THE COMPILER, CHARACTERS ARE SCANNED WHERE THEY SIT
; IN THE SOURCE BUFFER RING. CHARACTERS ARE READ WITH AN "ILDB".
; THE LISTING IS FORMED BY TRANSFERING CHARACTERS FROM THE SOURCE
; BUFFER RING TO THE LISTING BUFFER RING WITH A "BLT" INSTRUCTION.
; A "BLT" IS 20 TIMES FASTER PER CHARACTER THAN AN "IDPB", ALTHOUGH
; THERE IS A GREATER OVERHEAD INVOLVED AT THE BEGINNING OF EACH LINE.
;
; THE FOLLOWING ARE SOME OF THE CHARACTERISTICS OF THE "NEWLINE" ROUTINE:
;
; 1.) THE POSITIONS OF THE CHARACTERS IN THE WORDS MUST BE THE SAME
; IN THE SOURCE AND LISTING BUFFERS. THEREFORE, ANYTHING ELSE THAT APPEARS
; IN THE LISTING MUST BE ARRANGED IN STRINGS THAT ARE A MULTIPLE OF
; 5 CHARACTERS AND WHICH ARE MOVED TO THE LISTING WITH IDPB'S.
; THIS INCLUDES THE LINE PREFIX (ON THE FRONT OF EACH LINE OF ALGOL
; TEXT IN THE LISTING), WHICH ALSO MUST BE A MULTIPLE OF 8 PRINTABLE
; CHARACTERS SO THAT TABS ALIGN CORRECTLY.
;
; 2.) THE LINE IS MOVED FROM THE SOURCE BUFFER RING TO THE LISTING BUFFER
; RING AFTER THE LINE HAS BEEN SCANNED, SINCE UNTIL THEN THE EXTENT
; OF THE LINE IS NOT KNOWN. WHENEVER A NEW SOURCE BUFFER IS OBTAINED
; FROM THE SOURCE DEVICE, A WORD CONTAINING A CR/LF IS INSERTED AFTER
; THE DATA IN THE BUFFER TO MARK ITS END. THUS, WHENEVER A CR IS SCANNED
; A CHECK MUST BE MADE TO SEE IF IT IS THE END OF THE BUFFER.
; 3.) A CONSIDERABLE AMOUNT OF CODE IS DEDICATED TO HANDLING THE
; FOLLOWING EXCEPTIONAL CASES: WHEN THE LINE WONT FIT IN WHAT IS LEFT
; OF THE OUTPUT BUFFER ("SHOB1" AND "SHOB2"), AND WHEN THE SOURCE
; LINE IS SPLIT OVER TWO INPUT BUFFERS ("INEND" AND "SHIB").
; WHEN THE INPUT LINE IS SPLIT OVER TWO INPUT BUFFERS, THE 1ST PART
; MUST BE SAVED (IN "TMPBUF") WHILE THE 2ND PART IS BEING SCANNED,
; SINCE ONCE THE NEW INPUT BUFFER IS OBTAINED, THE OLD INPUT BUFFER IS
; NO LONGER RELIABLE.
; THE RIGHT HALF OF RFLAGS CONTAINS
; THE ADDRESS OF ONE OF THE FOLLOWING:
; NORMAL:
; NOLIST:
; NLIST1:
; ENDPRG:
NEWLINE: MOVEM A7,A7SAV ; SAVE A7
MOVE A7,RFLAGS ; GET READ MODULE FLAGS
JRST (A7) ; GO TO APPROPRIATE ROUTINE
; LISTING EXISTS AND WAS ON
NORMAL: SETCM A2,A7 ; IF SOURCE
TLNN A2,TTY!LTTY ; AND LISTING ARE TTY
JRST NLIST1 ; THEN SUPRESS LISTING
TRNN FL,LISTOO ; DID HE TURN LISTING OFF?
JRST TURNOF ; -YES
; LISTING EXISTS AND IS ON
TURNON: MOVE A2,P ; PUT READ POINTER IN A2
TLNE A7,ESWIT ; IF LINE NUMBERS IN 73-80
MOVE A2,LINEND ; THEN GET TRUE READ POINTER
MOVEM A2,P ; SAVE TRUE READ POINTER
CAMN A2,IBEND ; AT END OF INPUT BUFFER?
JRST INEND ; -YES, GET ANOTHER
TLO A7,WITHIN ; WE ARE WITHIN THE NEWLINE ROUTINE
; PRINT THE 1ST BATCH OF MESSAGES
MOVEI A5,MTABLE ; ADDR OF MESSAGE TABLE
CAML A5,NAMTE ; IF END OF TABLE
JRST NL2 ; THEN NO MESSAGES TO PRINT
SETZM LMSGS ; SET LMSG SWITCH TO "1ST PASS"
PUSHJ SP,LMSG ; PRINT 1ST GROUP OF MESSAGES
NL2: SKIPLE FFCNT2 ; IF THERE ARE FORM-FEEDS THAT HAVE NOT
PUSHJ SP,INSFF ; YET BEEN PUT IN LISTING, PUT THEM THERE
PUSHJ SP,CREFNL ; IF CREF, DO CREF STUFF
; MAKE SURE THAT THERE IS ROOM IN OUTPUT BUFFER FOR 1ST PART OF LINE
MOVEI A1,.SPACE ; PUT A BLANK IN ACC A1
MOVE A4,W ; GET WRITE POINTER
TLNE A7,LTTY ; IF THE LISTING IS TO THE TTY
JRST NL15 ; THEN PRODUCE A DIFFERENT LISTING
MOVEI A4,5(A4) ; GO AHEAD 5 WORDS
CAML A4,OBEND ; AT END OF BUFFER?
PUSHJ SP,SHOB1 ; -YES, GET ANOTHER
; PRINT PROGRAM COUNTER
SETZM (A4) ; CLEAR 1ST CHARS OF TEXT
MOVEI A5,6 ; PRINT 6 CHARS
TLNE A7,TMG ; IF NO REL FILE
JRST NL18 ; THEN DONT PRINT PC
MOVE A4,[ ; LOAD A POINTER TO
POINT 3,RA,17] ; PROGRAM COUNTER
NL1: ILDB A6,A4 ; GET 3 BITS
MOVEI A6,.N0(A6) ; CONV TO ASCII
IDPB A6,W ; PUT IN LISTING
SOJG A5,NL1 ; LOOP
NL19: IDPB A5,W ; INCLUDE A NULL
; PRINT BEGIN NUMBER
MOVE A4,BNUM ; LOAD BEGIN NUMBER
CAMN A4,LBNUM ; COMPARE TO LAST BEGIN NUMBER
JSP A3,NL3 ; -SAME, PRINT SOME BLANKS
MOVEM A4,LBNUM ; SAVE AS LAST BEGIN NUMBER
MOVEI A2,.B ; WRITE A "B"
MOVEI A3,5 ; WRITE 5 CHARS
PUSHJ SP,DEC ; WRITE IT
; PRINT END NUMBER
MOVE A4,ENUM ; LOAD END NUMBER
CAMN A4,LENUM ; COMPARE TO LST END NUMBER
JSP A3,NL3 ; -SAME, PRINT SOME BLANKS
MOVEM A4,LENUM ; SAVE AS LAST END NUMBER
MOVEI A2,.E ; WRITE AN "E"
MOVEI A3,5 ; WRITE 5 CHARS
PUSHJ SP,DEC ; CONVERT TO DECIMAL
JRST NL6 ; CONTINUE
; SUBROUTINE FOR PUTTING 5 BLANKS IN LISTING INSTEAD OF BEGIN/END NUMBER
NL3: MOVEI A5,5 ; WRITE 5 BLANKS
IDPB A1,W ; INCLUDE A BLANK
SOJG A5,.-1 ; LOOP
JRST 4(A3) ; EXIT
; PUT 6 BLANKS IN LISTING INSTEAD OF PC
NL18: IDPB A1,W ; PUT BLANK IN LISTING
SOJG A5,NL18 ; LOOP 5 MORE TIMES
JRST NL19 ; CONTINUE
; PUT LINE NUMBER IN LISTING
NL6: TLZN A7,ELINE ; IF TEXT HAS A LINE NUMBER
TLNE A7,ESWIT ; OR NUMBERS IN 73-80
JRST NL5 ; THEN DONT GENERATE A LINE NUMBER
MOVE A4,LINENO ; GET LINE NUMBER
MOVEI A2,.SPACE ; ACC A2 = BLANK
MOVEI A3,7 ; PRINT 7 CHARS LONG
PUSHJ SP,DEC ; CONVERT TO DECIMAL
JRST NL7 ; CONTINUE
NL5: MOVEI A3,0
IDPB A3,W ; INSERT A NULL
IDPB A1,W ; INCLUDE ANOTHER SPACE
TLNN A7,ESWIT ; IF NOT NUMBERS IN 73-80
JRST NL7 ; THEN SKIP THIS PART
MOVE A2,CHAR ; GET THE SAVED CHARACTER
DPB A2,CHARP ; REINSERT IT INTO ITS PLACE IN THE LINE
; READ THE LF THAT FOLLOWS THE CR
NL7: IDPB A1,W ; PUT BLANK IN LISTING
MOVE A2,P ; LOAD READ POINTER
PUSHJ SP,GETNL ; READ NEXT CHAR
MOVE A3,CTABLE(A1) ; GET TABLE ENTRY
CAIN A3,4 ; IF IT IS A LF
MOVEM A1,CHAR2 ; THEN SAVE THIS CHAR
CAIE A3,4 ; IS IT A LF?
ADD A2,[ ; BACK UP POINTER
XWD 070000,0] ; POINTER DECREMENT CONSTANT
; PUT 1ST WORD OF LINE TEXT IN OUTPUT BUFFER
MOVE A6,LSTART ; POINTER TO BEGINNING OF LAST LINE
MOVEM A2,LSTART ; SET NEXT LINE START
HLLZ A4,W ; GET WRITE POINTER S-P BITS
ROT A4,4 ; PUT 1ST 4 BITS IN RIGHT HALF
MOVE A4,MSKTBL(A4) ; GET A MASK
AND A4,@A6 ; MASK OFF EXTRANEOUS CHARS
IORM A4,@W ; PUT REMAINING CHARS IN LISTING
; MOVE REMAINDER OF ALGOL TEXT TO OUTPUT BUFFER WITH A BLT
AOS A5,W ; STEP WRITE POINTER AND LOAD IT
HRLI A5,1(A6) ; STEP OLD READ POINTER
SKIPE TBLEN ; IS INPUT LINE SPLIT OVER 2 BUFFERS?
JRST SHIB ; -YES, TREAT SEPARATELY
MOVEI A4,(A2) ; CURRENT READ POINTER ADDRESS
SUBI A4,1(A6) ; CURRENT LINE LENGTH
ADDI A4,@W ; END OF LINE IN WRITE BUFFER
;
; Edit(1005) Deal with very long source lines correctly
;
NL14: CAMGE A4,OBEND ; [E1005] WILL LINE OVERFLOW OUTPUT BUFFER?
JRST .+3 ; [E1005] - NO, SO OK
PUSHJ SP,SHOB2 ; [E1005] - YES, HANDLE WITH CARE
JRST NL14 ; [E1005] TRY AGAIN
CAIL A4,(A5) ; NEGATIVE LENGTH?
NL13: BLT A5,(A4) ; MOVE THE LINE
HLL A4,A2 ; FORM NEW WRITE POINTER
MOVEM A4,W ; SAVE IT
; PRINT 2ND BATCH OF MESSAGES
NL10: PUSHJ SP,GETNL ; STEP TO NEXT CHAR
MOVEI A5,MTABLE ; ADDR OF MESSAGE TABLE
CAML A5,NAMTE ; IF NO MESSAGES IN TABLE
JRST NL9 ; THEN SKIP THIS PART
SETOM LMSGS ; SET LMSG SWITCH TO 2ND PASS
PUSHJ SP,LMSG ; PRINT REST OF MSGS
MOVEI A1,MTABLE ; START OF MESSAGE TABLE
MOVEM A1,NAMTE ; SET POINTER TO START OF TABLE
; PROCESS ANY FORM FEEDS
NL9: LDB A1,A2 ; GET THE NEXT CHAR
JUMPN A1,.+3 ; SKIP THIS IF NOT A NULL
PUSHJ SP,GETNL ; READ THE NEXT CHAR
JUMPE A1,.-1 ; READ ANOTHER IF IT IS A NULL
TLZ A7,WITHIN ; WE ARE ABOUT TO EXIT THE NEWLINE ROUTINE
CAIE A1,.FF ; IF IT IS NOT A FORM-FEED
JRST NL11+1 ; THEN SKIP THIS PART
PUSHJ SP,FFOUND ; PROCESS THE FORM-FEED
JRST NL9+2 ; LOOK FOR ANOTHER FORM-FEED
; SKIP OVER ANY NULLS AT BEGINNING OF NEXT LINE
NL11: PUSHJ SP,GETNL ; READ NEXT CHAR
JUMPE A1,NL11 ; READ AGAIN IF A NULL
; PROCESS LINE NUMBER IF ANY
TLNE A7,ESWIT ; IF NUMBERS IN 73-80
JRST COL73 ; THEN SCAN THE LINE NUMBER
MOVE A4,LINENO ; GET OLD LINE NUMBER
MOVE A5,(A2) ; PICK UP FIRST WORD
TRNN A5,1 ; IS IT A LINE NUMBER?
AOJA A4,NL8 ; -NO, INCREMENT LINE NO. AND SKIP
CAIN A1,.SPACE ; IF LINE NUMBER IS BLANK
JRST BLN ; THEN JUMP
MOVEI A5,4 ; SCAN NEXT 4 CHARS
MOVEI A4,-.N0(A1) ; CONVERT 1ST CHAR TO DECIMAL
PUSHJ SP,GETNL ; GET NEXT CHAR
IMULI A4,^D10 ; MULTIPLY PREVIOUS RESULT BY 10
ADDI A4,-.N0(A1) ; ADD IN CURRENT CHAR
SOJG A5,.-3 ; LOOP
PUSHJ SP,GETNL ; SKIP OVER TAB
SOS CC ; DONT COUNT THIS AS A POSITION
CAIN A1,.FF ; IF IT IS A FORM-FEED
PUSHJ SP,FFOUND ; THEN PROCESS IT
CAIE A1,.TAB ; IF IT IS NOT A TAB
JRST NOTAB ; THEN TREAT SEPARATELY
NL16: PUSHJ SP,GETNL ; GET NEXT CHAR
CAIE A1,.FF ; IF IT IS NOT A FORM-FEED
JRST .+3 ; THEN SKIP THIS PART
PUSHJ SP,FFOUND ; PROCESS IT
JRST NL16 ; READ ANOTHER CHAR
TLO A7,ELINE ; MARK: EDITOR LINE NUMBER SCANNED
; SAVE ALL LINE POINTERS
NL8: MOVE A5,CC ; GET POSITION COUNT
EXCH A4,LINENO ; SET NEW LINE NUMBER
EXCH A5,LP1 ; SET START OF CURRENT LINE
TLZE A7,BLANKL ; IF THIS WAS A BLANK LINE
JRST .+3 ; THEN SKIP
MOVEM A4,OLDNO ; SET OLD LINE NUMBER
MOVEM A5,LP2 ; SET START OF PRECEDING LINE
; CHECK FOR A BLANK LINE
MOVE A5,CTABLE(A1) ; GET CHARS TABLE ENTRY
CAIN A5,4 ; IF IT IS A NEW LINE CHAR
TLO A7,BLANKL ; THEN MARK THIS A BLANK LINE
; EXIT FROM NEWLINE
MOVEM A2,P ; SAVE READ POINTER
PUSHJ SP,CREFST ; O/P CREF START DATA, IF WE'RE CREF'ING
MOVEM A7,RFLAGS ; STORE READ-MODULE FLAGS
MOVE A7,A7SAV ; RESTORE A7
JRST SKRET ; EXIT NEWLINE
SUBTTL ** SUBROUTINES OF NEWLINE **
; ROUTINES FOR CROSS-REFERENCING.
CREFIT: ; ENTER WITH LEXEME OF IDENTIFIER IN A1. CALLED FROM SEARCH.
MOVE A2,SYMNAM(A1) ; GET FIRST WORD OF NAME
ANDI A2,77 ; GET # CHARS - 1
ADDI A2,1
DPB A2,[POINT 7,CREFRF,13] ; PUT INTO CREF DATA
ADDI A2,3 ; ALLOW FOR ^A^? AND POSSIBLE ^B
ADDM A2,CRFCNT ; UPDATE CHAR-COUNTER
PUSHJ SP,NAME ; GET NAME IN ASCIZ
MOVEI A1,CREFRF
EXCH A7,RFLAGS ; GET READ-MODULE FLAGS
PUSHJ SP,INSERT ; OUTPUT (<DEL> B) ^A^?
MOVEI A1,LB ; WHERE NAME ROUTINE LEFT IT
PUSHJ SP,INSERT ; SYMBOL NAME
MOVEI A1,CREFDF ; DEFINITION FLAG
HRRZ A2,NDEL ; GET TERMINATING DELIMITER,
CAIN A2,15 ; AND IF IT IS A COLON THEN
JRST CREFLB ; THIS IS A LABEL DEFINITION
TRNN FL,DECLAR ; DECLARATION ?
SOSA CRFCNT ; NO - DON'T ALLOW FOR ^B IN COUNT OF CHARS
CREFLB: PUSHJ SP,INSERT ; YES - TELL CREF
EXCH A7,RFLAGS ; PUT READ-MODULE FLAGS AWAY.
POPJ SP, ; BACK TO SEARCH
CREFNL: ; CALLED BY NEWLINE JUST BEFORE PRINTING SOURCE-LINE
MOVEI A1,CREFND ; END CREF DATA
JRST CRFNL3
CRFNL2: MOVEI A1,[BYTE(7)177,"D"] ; <DEL>D - END CREF DATA - NO LINE #
CRFNL3: SKIPE CRFCNT ; ANY CREF'ING DONE ON THIS LINE ?
TRNN FL,CREF ; ANY CREF'ING AT ALL ?
POPJ SP, ; NO
PUSHJ SP,INSERT ; <DEL> A
AOS CRFCNT ; ALLOW FOR <DEL>A
AOS A1,CRFCNT ; # OF CHARACTERS OUTPUT BY CREF
IDIVI A1,5 ;
JUMPE A2,CRFNL1 ; WHOLE # OF WORDS ?
SUBI A2,5
MOVEM A2,CRFCNT ; NO - MUST MAKE IT SO
PUSHJ SP,INSNUL ; BY PUTTING IN NULLS
AOSE CRFCNT ; ENOUGH ?
JRST .-2 ; NO
CRFNL1: SETZM CRFCNT ; CLEAR COUNT
POPJ SP,
CREFST: ; OUTPUT START-OF-CREF DATA, IF REQUIRED.
SKIPN CRFCNT ; NOT ALREADY STARTED, AND...
TRNN FL,CREF ; CREF ?
POPJ SP, ; NO
PUSH SP,A1 ; YES - SAVE A1 (USED IN NEWLINE)
MOVEI A1,[BYTE(7)177,"B"] ;<DEL>B - START CREF DATA
PUSHJ SP,INSERT ; OUTPUT IT
MOVEI A1,2 ; UPDATE
ADDM A1,CRFCNT ; CREF COUNTER
POP SP,A1
POPJ SP,
CREFDF: BYTE(7)2,0,0,0,0 ; ^B (DEFINITION FLAG)
CREFND: BYTE(7)177,"A",0,0,0 ; <DEL> A (END OF CREF DATA)
RELOC
CREFRF: BLOCK 1
; BYTE(7)1,0,0,0,0 ; ^A (SYMBOL REF. 2ND BYTE PLUGGED WITH LENGTH)
CRFCNT: BLOCK 1 ; # OF CHARS O/P BY CREF
RELOC
; BRIEF FORM OF LISTING FOR WHEN SENT TO TTY
NL15: TLNN A7,ELINE ; IF THERE IS AN EDITOR'S LINE NUMBER
TLNE A7,ESWIT ; OR NUMBERS IN 73 - 80
JRST NL7+1 ; THEN DONT GENERATE ANOTHER ONE
MOVEI A4,2(A4) ; END OF WHERE LINE PREFIX WILL GO
CAML A4,OBEND ; IF PAST END OF BUFFER
PUSHJ SP,SHOB1 ; THEN GET ANOTHER OUTPUT BUFFER
MOVE A4,LINENO ; GET THE CURRENT LINE NUMBER
MOVEI A2,.SPACE ; PRECEDE WITH A SPACE
MOVEI A3,7 ; FIELD IS 7 CHARS WIDE
PUSHJ SP,DEC ; PUT LINE NUMBER IN LISTING
IDPB A3,W ; PUT AN ASCII NULL IN LISTING
IDPB A3,W ; PUT IN ANOTHER ONE
JRST NL7 ; CONTINUE
; LISTING EXISTS BUT WAS OFF
NOLIST: TRNN FL,LISTOO ; IF SO, IS IT CURRENTLY ON?
JRST NLIST1 ; -NO, CONTINUE WITH NO LISTING
HRRI A7,NORMAL ; TIME TO TURN LISTING BACK ON
;[223] LSTART AND W MUST BE THE SAME BYTE OFFSET WHEN THE LISTING RESUMES.
HLRZ A1,LSTART ;[223] GET THE SOURCE'S OFFSET
SETZ A4, ;[223] CREATE A NULL BYTE
NLIST3: HLRZ A2,W ;[223] GET W'S OFFSET (LISTING'S OFFSET)
CAMN A2,A1 ;[223] ARE THEY THE SAME?
JRST TURNON ;[223] YES, EVERYTHING IS OK
IDPB A4,W ;[223] NO, WRITE A NULL BYTE
JRST NLIST3 ;[223] AND LOOP
; TURN LISTING OFF
TURNOF: HRRI A7,NOLIST ; TURN LISTING OFF
; LISTING IS OFF
NLIST1: MOVE A2,P ; LOAD READ POINTER
TLNE A7,ESWIT ; IF NUMBERS IN 73-80
MOVE A2,LINEND ; GET TRUE READ POINTER
MOVEM A2,P ; SAVE TRUE VALUE
CAMN A2,IBEND ; AT END OF INPUT BUFFER?
JRST INEND ; -YES, GET A NEW INPUT BUFFER
TLO A7,WITHIN ; WE ARE WITHIN THE NEWLINE ROUTINE
MOVEM A2,LSTART ; SAVE POINTER FOR LATER
SETZM SSTART ; CLEAR SEGMENT START MARKER
SETZM TBLEN ; EMPTY OUT TMPBUF
; PRINT 1ST BATCH OF MESSAGES
MOVEI A5,MTABLE ; ADDR OF MESSAGE TABLE
CAML A5,NAMTE ; IF NO MESSAGES IN TABLE
JRST NLIST2 ; THEN SKIP THIS PART
SETZM LMSGS ; SET LMSG SWITCH TO 1ST PASS
PUSHJ SP,LMSG ; PRINT MESSAGES
; READ THE LF THAT FOLLOWS THE CR
NLIST2: PUSHJ SP,GETNL ; GET NEXT CHAR
MOVE A4,CTABLE(A1) ; GET TABLE ENTRY
CAIE A4,4 ; IT IS NORMALLY A LF
JRST NL10+1 ; -NO, CONTINUE WITHOUT STEPPING READ POINTER
MOVEM A2,LSTART ; SAVE READ POINTER
MOVEM A1,CHAR2 ; SAVE THIS CHAR
JRST NL10 ; CONTINUE
; "GETNL" WILL READ THE NEXT CHARACTER OF THE SOURCE TEXT. "GETNL"
; MUST BE USED WHENEVER A CHARACTER IS TO BE READ WITHIN "NEWLINE".
; "GETNL" WILL CALL "INEND" IF AN END OF BUFFER OCCURRS.
GETNL: ILDB A1,A2 ; GET NEXT CHAR
AOS CC ; STEP POSITION COUNT
CAME A2,IBEND ; UNLESS AT END OF INPUT BUFFER
POPJ SP, ; EXIT GETNL
MOVEM A2,P ; INEND WANTS POINTER SET
PUSHJ SP,INEND ; READ NEXT INPUT BUFFER
MOVE A7,RFLAGS ; RELOAD READ MODULE FLAGS
MOVE A2,P ; RELOAD READ POINTER
JRST GETNL+2 ; TEST AGAIN
; "INEND" IS CALLED WHENEVER THE END OF AN INPUT BUFFER IS REACHED.
; "INEND" WILL MOVE THE 1ST PART OF THE SPLIT INPUT LINE TO "TMPBUF"
; AND THEN CALL "READ" TO OBTAIN THE NEXT INPUT BUFFER.
INEND1: MOVEM A2,NLR+4 ; SAVE A2
MOVE A2,A1 ; MOVE READ POINTER TO A2
MOVEM A7,A7SAV ; SAVE A7
MOVE A7,RFLAGS ; GET READ MODULE FLAGS
INEND: MOVEM A4,NLR ; SAVE A4
MOVEM A5,NLR+1 ; SAVE A5
MOVEM A6,NLR+2 ; SAVE A6
MOVEM A3,NLR+3 ; SAVE A3
HRRZ A6,A2 ; GET READ POINTER
SKIPN A5,SSTART ; UNLESS LINE ALREADY BROKEN ONCE
MOVE A5,LSTART ; GET START OF LINE SEGMENT
SUBI A6,(A5) ; LENGTH OF DATA TO MOVE
MOVEI A4,TMPBUF-1(A6) ; END OF LINE IN TEMPBUF
HRLZI A5,(A5) ; MOVE SEGMENT FROM RING BUFFER
HRRI A5,TMPBUF ; TO TEMP BUFFER
HRRM A5,LSTART ; SET NEW VALUE FOR LSTART
ADD A4,TBLEN ; ADD TO WHAT IS IN TMPBUF
EDIT(025); BE MORE INFORMATIVE IF WE ARE GIVING UP
CAIGE A4,BUF0 ; [E025] WILL IT ALL FIT IN TMPBUF ?
JRST INEND2 ; [E025] YES - CARRY ON
OUTSTR [ASCIZ /
? SOURCE STATEMENT TOO LONG /] ; [E025] NO - TELL USER
JRST TERMIN ; THEN GIVE UP
INEND2: ADD A5,TBLEN ; [E025] ADD TO WHAT IS IN TMPBUF
ADDM A6,TBLEN ; ADDITIONAL LENGTH OF TMPBUF
BLT A5,(A4) ; MOVE LINE
PUSHJ SP,READ ; READ NEXT BUFFER
INEND5: MOVE A5,P ; GET NEW POINTER
MOVEI A5,1(A5) ; ADD 1
MOVEM A5,SSTART ; SAVE THIS ADDR
ILDB A1,P ; READ 1ST CHAR
CAIN A1,.CZ ; IF THIS IS A CONTROL-Z
JRST INEND4 ; THEN READ AGAIN
MOVEM A7,RFLAGS ; SAVE READ-MODULE FLAGS
MOVE A7,A7SAV ; RESTORE A7
MOVE A4,NLR ; RESTORE A4
MOVE A5,NLR+1 ; RESTORE A5
MOVE A6,NLR+2 ; RESTORE A6
MOVE A3,NLR+3 ; RESTORE A3
MOVE A2,NLR+4 ; RESTORE A2
POPJ SP, ; EXIT NEWLINE
INEND4: PUSHJ SP,READ1 ; CALL INEND BUT DONT PRINT A LINE NUMBER ON TTY
JRST INEND5 ; CONTINUE
; IF THE SOURCE DEVICE IS A TTY, "READ" WILL SEND THE NEXT LINE NUMBER
; TO THE TTY. THEN "READ" WILL OBTAIN THE NEXT BUFFER FROM THE SOURCE
; DEVICE, AND MARK THE END OF DATA IN IT WITH A WORD CONTAINING A
; CR/LF.
READ: TLNN A7,TTY ; IS SOURCE DEVICE A TTY?
JRST READ1 ; -NO, SKIP WRITING A LINE NUMBER
TLNN A7,WITHIN ; IF WITHIN THE NEWLINE ROUTINE
JRST READ1 ; THEN PRINT NUMBER ELSE SKIP THIS PART
PUSH SP,W ; SAVE W
MOVEI A5,BUF0
HRLI A5,440700
MOVEM A5,W ; SET UP BYTE POINTER
MOVE A4,LINENO ; GET CURRENT LINE NUMBER
ADDI A4,1 ; INCREMENT IT
MOVEI A2,.SPACE
MOVEI A3,7
PUSHJ SP,DEC ; PRINT LINE NO.
MOVEI A4,.SPACE ; LOAD A BLANK
IDPB A4,W ; PUT THE BLANK IN BUFFER
MOVEI A4,0
IDPB A4,W ; AND FINISH WITH A NULL
POP SP,W ; RESTORE W
OUTSTR BUF0 ; OUTPUT LINE NUMBER
READ1: IN 3,0 ; INPUT NEXT BUFFER
JRST INOKA ; -SUCCESSFUL READ
STATO 3,710000 ; WAS IT A READ ERROR?
JRST EOF ; -NO, JUST END OF FILE
OUTSTR INERRM ; WRITE ERROR MSG
JRST TERMIN ; TERMINATE COMP
INERRM: ASCIZ /?INPUT ERROR
/
; INPUT BUFFER READ SUCCESSFULLY
INOKA: MOVE A6,BHEAD3 ; ADDR OF CURRENT BUFFER
HRRZ A5,1(A6) ; LENGTH OF BUFFER IN WORDS
JUMPE A5,READ ; IF EMPTY GET ANOTHER BUFFER
ADD A5,P ; ADDR OF END OF BUFFER
SKIPN (A5) ; BACKUP OVER NULLS
SOJA A5,.-1
MOVE A4,NLCHRS ; LOAD A CR/LF
MOVEM A4,1(A5) ; PUT IT AT END OF BUFFER
ADD A5,[ ; HOW POINTER WILL LOOK AT
XWD 350000,1] ; END OF BUFFER
MOVEM A5,IBEND ; STORE FOR LATER COMPARISON
POPJ SP, ; EXIT INEND
; END-OF-FILE ENCOUNTERED
EOF: MOVE A4,BHEAD3 ; LOCATE CURRENT BUFFER RING
MOVEM A4,OLDSBR ; SAVE ITS ADDRESS
CLOSE 3,0 ; CLOSE SOURCE FILE
SKIPG CSCOMP ; IF NO MORE SOURCE FILES
JRST ENDPRG ; THEN RETURN EOF LEXEME
TLZ A7,ESWIT ; TURN OFF 73-80 INDICATOR
SETZM CSCOMP ; CLEAR SWITCH
PUSHJ SP,SCAN3 ; SCAN NEXT SOURCE FILE AND OPEN IT
JRST READ ; READ 1ST BUFFER
; END OF SOURCE DATA (NO MORE SOURCE FILES)
ENDPRG: HRRI A7,ENDPRG ; LSCAN WILL READ NO MORE
MOVEM A7,RFLAGS ; SAVE READ-MODULE FLAGS
MOVE A7,A7SAV ; RESTORE A7
MOVE A2,[ ; SET UP A POINTER TO
POINT 7,NLCHRS] ; A NEW-LINE CHAR
MOVEM A2,P ; PUT IN READ POINTER
MOVE A3,ZEOF ; OUTPUT END-OF-FILE LEXEME
; RETURN TO CALLER OF LSCAN
EOF5: POP SP,A4 ; GET RETURN LINK
MOVEI A4,(A4) ; CLEAR LEFT HALF
CAIN A4,EMPTY
JRST EMPTY1 ; NULL FILE
CAIE A4,RUND0
CAIN A4,RUND5 ; IF IT IS ONE OF THESE
JRST (A4) ; THEN GO THERE
JRST EOF5 ; ELSE ASCEND ANOTHER LEVEL
NLCHRS: ASCIZ /
/
; NO ROOM IN OUTPUT BUFFER FOR LINE PREFIX
SHOB1: HLRZ A5,W ; GET OLD S-P BITS
PUSHJ SP,WRITEL ; GET NEXT BUFFER
AOS A4,W ; STEP WRITE POINTER, LOAD IT
SETZM (A4) ; ZERO 1ST WORD OF LINE IN BUFFER
SETZM 5(A4) ; ZERO 6TH WORD OF LINE IN BUFFER
HRLM A5,W ; SET NEW WRITE POINTER
POPJ SP, ; CONTINUE
; NO ROOM IN OUTPUT BUFFER FOR THE ALGOL TEXT
SHOB2: SOS A6,OBEND ; LAST WORD IN BUFFER
CAIGE A6,(A5) ; IF FULL UP
JRST SHOB3 ; THEN SKIP THIS
MOVE A3,A5 ; SAVE A5
BLT A5,(A6) ; AND FILL UP BUFFER
MOVE A5,A3 ; RESTORE A5
SHOB3: HRLI A6,010700
MOVEM A6,W ; SET UP W
SUBI A4,(A6) ; REMAINDER
SUBI A6,-1(A5) ; AMOUNT TRANSFERRED
HRLZI A6,(A6)
ADD A5,A6 ; MOVE UP INPUT POINTER
PUSHJ SP,WRITEL ; GET NEW OUTPUT BUFFER
ADDI A4,@W ; STOP ADDRESS FOR BLT
AOS W ; STEP WRITE POINTER
HRR A5,W ; SET UP OUTPUT POINTER
POPJ SP, ; [E1005] AND TRY AGAIN
; INPUT LINE WAS SPLIT OVER 2 INPUT BUFFERS
SHIB: SOS A4,TBLEN ; A4=LENGTH OF FIRST PART
ADDI A4,@W ; STOP ADDR FOR BLT
CAMGE A4,OBEND ; WILL THIS OVERFLOW BUFFER?
JRST SHIB1 ; -NO, SKIP
; 1ST PART OF INPUT LINE WILL NOT FIT IN OUTPUT BUFFER
PUSH SP,A6 ; [E1005] SAVE A6
PUSHJ SP,SHOB2 ; [E1005] SEND WHAT WE CAN
POP SP,A6 ; [E1005] RESTORE A6
JRST SHIB+2 ; [E1005] AND TRY AGAIN
SHIB1: CAIG A4,(A5) ; SKIP BLT IF LENGTH NEGATIVE
JRST .+3 ; -YES, SKIP
MOVE A3,A5 ; MOVE TO ACC A3
BLT A3,-1(A4) ; MOVE 1ST PART OF LINE
MOVEM A4,W ; SET W JUST IN CASE SHOB2 IS CALLED
MOVEI A5,(A4) ; WHERE 2ND PART WILL START
HRL A5,SSTART ; WHERE 2ND PART NOW SITS
ADDI A4,(A2) ; ADD CURRENT POINTER ADDR
SUB A4,SSTART ; STOP ADDR FOR BLT
SETZM TBLEN ; ZERO TBLEN
SETZM SSTART ; CLEAR SSTART
JRST NL14 ; CONTINUE
FFOUND: MOVEI A1,0 ; ASCII NULL
DPB A1,A2 ; DELETE FORM FEED FROM INPUT BUFFER
AOS FFCNT ; STEP FORM FEED COUNNT
AOS FFCNT2 ; STEP OTHER FORM FEED COUNT
POPJ SP, ; EXIT FFOUND
; PUT FORM-FEED IN FRONT OF LINE
;
Edit(165); If CREFing include FF characters in cref count
;
INSFF: PUSH SP,FFCNT2 ; [E162] Save number of FFs sent
MOVEI A1,[BYTE(7)177,"F",14] ; PUT IN "END-OF-CREF",F.F
TRNN FL,CREF ; IF CREF, OTHERWISE
INSFF1: MOVEI A1,FORM ; ADDRESS OF A FORM-FEED
PUSHJ SP,INSERT ; PUT IT IN LISTING
SOSLE FFCNT2 ; IF MORE FORM-FEEDS TO INSERT, THEN
JRST INSFF1 ; LOOP
POP SP,A1 ; [E165] Get saved FF count
TRNN FL,CREF ; IF NOT CREF
JRST [ ; [E165]
PUSHJ SP,IC2 ; [E165] then tidy up
POPJ SP,] ; [E165] and exit
IMULI A1,3 ; [E165] Get actual count of chars sent
ADDI A1,2 ; [E162] and include end of cref chars
ADDM A1,CRFCNT ;
MOVEI A1,[BYTE(7)177,"B"] ; ELSE START CREF DATA FOR NEW LINE
JRST INSERT ; EXIT VIA INSERT
; LINE NUMBER NOT FOLLOWED BY A TAB
NOTAB: CAIN A1,.CR ; IF IT IS A CARRIAGE RETURN
JRST .+4 ; THEN SKIP THIS PART
MOVEI A1,.TAB ; AN ASCII TAB CHARACTER
DPB A1,A2 ; REPLACE THE CHARACTER WITH A TAB
JRST NL16 ; CONTINUE
PUSHJ SP,GETNL ; READ THE NEXT CHARACTER
CAIN A1,.CR ; IF IT IS A CARRIAGE RETURN
JRST NL8-1 ; THEN IT IS PROBABLY THE SEQUENCE: CR CR LF
MOVEI A1,.LF ; LINE-FEED
PUSHJ SP,FFOUND+1 ; REPLACE CR BY LF ETC.
JRST NL8-1 ; CONTINUE
; BLANK LINE NUMBER ENCOUNTERED
BLN: MOVEI A5,7 ; SKIP OVER 7 CHARACTERS
MOVEI A6,0 ; ASCII NULL
DPB A6,A2 ; REPLACE CHARACTER WITH A NULL
PUSHJ SP,GETNL ; READ A CHARACTER
SOJG A5,.-2 ; LOOP
PUSHJ SP,FFOUND ; NULL OUT THE FORM-FEED
JRST NL11 ; CONTINUE
RELOC
IBEND: BLOCK 1 ; END OF INPUT BUFFER
OBEND: BLOCK 1 ; END OF OUTPUT BUFFER
BNUM: BLOCK 1 ; BEGIN NUMBER
LBNUM: BLOCK 1 ; LAST BEGIN NUMBER
ENUM: BLOCK 1 ; END NUMBER
LENUM: BLOCK 1 ; LAST END NUMBER
LINEND: BLOCK 1 ; READ POINTER AT END OF CURRENT LINE
LINE5: BLOCK 1 ; 5 -CHAR DATASET LINE NUMBER
LSTART: BLOCK 1 ; START OF CURRENT LINE
SSTART: BLOCK 1 ; START OF CURRENT LINE SEGMENT
CHAR: BLOCK 1 ; SAVE CHAR FROM 80-COLUMN LINE
CHARP: BLOCK 1 ; SAVED CHARACTER'S RESTORATION POINTER
TBLEN: BLOCK 1 ; LENGTH OF DATA IN TMPBUF
A7SAV: BLOCK 1 ; SAVE AREA FOR A7
NLR: BLOCK 5 ; SAVE AREA FOR REGISTERS OVER NEWLINE
EDIT(025); INCREASE SIZE OF TMPBUF
TMPBUF: BLOCK 200 ; SAVED 1ST PART OF SPLIT SOURCE LINE
BUF0: BLOCK 5
RELOC
; THE "COL73" ROUTINE WAS CONTRIVED AFTER THE REST OF "NEWLINE" WAS
; WRITTEN. "NEWLINE" HAS THE CONVENTION THAT THE LINE NUMBER MUST BE
; KNOWN BEFORE THE LINE IS SCANNED. "COL73" WILL CAUSE THE WHOLE
; LINE TO BE "UNOFFICIALLY" MOVED INTO "TMPBUF" BEFORE SCANNING ANY OF
; IT SO THAT THE LINE NUMBER CAN FIRST BE SCANNED. HOWEVER, IF PART
; OF THE LINE WAS MOVED THERE BY "INEND", ONLY THE LAST PART OF THE LINE
; IS "UNOFFICIAL". BY "UNOFFICIAL" IT IS MEANT THAT THE TEXT IS
; NOT REALLY THERE (NOT INCLUDED IN "TBLEN", WHICH IS THE COUNT
; OF DATA WORDS IN "TMPBUF"), AND THE LISTING WILL BE TAKEN FROM
; TEXT IN THE SOURCE BUFFER RATHER THAN FROM "TMPBUF". HOWEVER
; THE SOURCE BYTE POINTER WILL POINT INTO "TMPBUF". THE 1ST CHARACTER
; OF THE LINE NUMBER IS EXTRACTED AND REPLACED WITH A CR SO THAT
; THE SCANNER WILL NOT RUN INTO THE LINE NUMBER.
; FORM READ POINTER TO TMPBUF
COL73: MOVE A3,A2 ; COPY READ POINTER
HRRI A3,TMPBUF ; POINT IT TO TMPBUF
ADD A3,TBLEN ; IN CASE SOMETHING ALREADY IN TMPBUF
MOVEI A5,^D16 ; PUT NEXT 17 WORDS IN TMPBUF
COL73A: ADDI A5,(A2) ; END OF SOURCE IN RING BUFFER
MOVE A6,IBEND ; END OF RING BUFFER
CAIGE A5,(A6) ; IF THE LINE IS ENTIRELY WITHIN RING BUFFER
JRST COL73B ; THEN SKIP THIS PART
; USE INEND TO PUT PART OF LINE IN TMPBUF
MOVE A2,LSTART ; GET LINE START
SKIPN SSTART ; SKIP IF TMPBUF NOT EMPTY
TLNE A2,760000 ; IF BYTE POINTER NOT AT END OF WORD
JRST .+2 ; THEN SKIP THIS PART
ADDI A3,1 ; THEN IGNORE 1ST WORD OF TMPBUF
SUBI A5,(A6) ; EXCESS LENGTH - 1
MOVEM A6,P ; SET P
MOVE A2,A6 ; COPY TO A2
PUSHJ SP,INEND ; GET NEXT INPUT BUFFER
MOVE A7,RFLAGS ; RE-FETCH READ MODULE FLAGS
MOVE A2,P ; RELOAD POINTER
JRST COL73A ; MOVE REMAINDER TO TMPBUF
; MOVE REMAINDER OF LINE TO TMPBUF "UNOFFICIALLY"
COL73B: MOVEM A5,LINEND ; SAVE END OF TEXT IN RING BUFFER
HRLZ A6,A2 ; "FROM" ADDRESS
HRRI A6,TMPBUF ; "TO" ADDRESS
ADD A6,TBLEN ; IN CASE TMPBUF NOT EMPTY
SUBI A5,(A2) ; LENGTH OF MOVE - 1
JUMPL A5,.+3 ; SKIP IF NOTHING TO MOVE
ADDI A5,(A6) ; "STOP" ADDRESS
BLT A6,(A5) ; MOVE TEXT TO TMPBUF
; REPLACE 1ST DIGIT OF LINE NUMBER WITH A CR
MOVE A2,A3 ; A2 = NEW READ POINTER
IBP A3 ; STEP TO COLUMN 2
IBP A3 ; STEP TO COLUMN 3
ADDI A3,^D14 ; STEP TO COLUMN 73
LDB A4,A3 ; GET THE CHARACTER THAT IS THERE
MOVEM A4,CHAR ; SAVE IT FOR LATER
MOVEI A6,.CR ; ASCII CARRIAGE RETURN CHARACTER
DPB A6,A3 ; PUT IN PLACE OF OTHER CHARACTER
MOVEM A3,CHARP ; SAVE POINTER TO THIS CHARACTER
SUBI A4,.N0 ; CONVERT FROM ASCII TO BINARY
MOVEI A6,7 ; READ 7 MORE CHARACTERS
; SCAN LINE NUMBER
COL73C: ILDB A5,A3 ; READ NEXT CHAR
CAIN A5,.SPACE ; IF IT IS A BLANK
JRST .+3 ; THEN IGNORE IT
IMULI A4,^D10 ; MULT PREVIOUS RESULT BY 10
ADDI A4,-.N0(A5) ; ADD IN CURRENT DIGIT
SOJG A6,COL73C ; LOOP
; FROM TRUE LINE POINTER TO SOURCE BUFFER RING
HRR A3,LINEND ; GET POINTER TO TEXT IN RING BUFFER
TLNN A3,760000 ; STEP POINTER, BUT NOT TO NEXT WORD
SUBI A3,1 ; TRUE POINTER
IBP A3 ; THE NEXT CHARACTER TO BE READ FROM THE RING BUFFER
MOVEM A3,LINEND ; SAVE THIS POINTER
LDB A1,A2 ; READ THE NEXT CHARACTER
JRST NL8 ; CONTINUE
SUBTTL ** ERROR HANDLING ROUTINES **
; ERROR MESSAGES
;
; ERROR MESSAGES ARE NOT PRINTED IMMEDIATELY AS THE ERRORS ARE
; DETECTED. IF THEY WERE THEN, SINCE THE ALGOL TEXT IS NOT MOVED TO
; THE LISTING UNTIL AFTER THE LINE HAS BEEN SCANNED (FOR EFFICIENCY)
; USUALLY THE ERROR CODE WOULD APPEAR BELOW THE ERROR MESSAGE, AND
; OTHER TIMES THE ERROR CODE WOULD APPEAR ABOVE THE ERROR MESSAGE
; BECAUSE THE SCANNER IS USUALLY PROCESSING AHEAD OF THE SYNTAX
; ANALYZERS. TO COMBAT THIS, MESSAGES ARE BUFFERED IN A MESSAGE TABLE.
; THEN, WHEN THE SCANNER REACHES THE END OF A LINE, "NEWLINE" WILL
; 1.) PRINT ALL MESSAGES THAT PERTAIN TO THE PRECEDING LINE OF
; TEXT, 2.) PRINT THE CURRENT LINE OF TEXT, AND 3.) PRINT ALL MESSAGES
; THAT PERTAIN TO THE CURRENT LINE OF TEXT.
;
; EACH TIME THE SCANNER READ A CHARACTER WITH AN "ILDB" IT STEPS
; "CC" WITH AN "AOS". FOR EACH ITEM SCANNED "RUND" WILL STORE "CC"
; IN THE CORRECT WORD OF "PLIST". "PLIST" HAS 4 WORDS, ONE FOR EACH
; PORT OF THE WINDOW. "LP1" AND "LP2" CONTAIN THE CHARACTER NUMBERS
; THAT BEGAN THE CURRENT AND PREVIOUS LINES OF TEXT, RESPECTIVELY.
; USING ALL OF THE ABOVE, THE MESSAGE ROUTINE CAN TELL EXACTLY
; WHERE TO PRINT THE UP-ARROW.
;
; THE MESSAGE ROUTINE USUALLY PRINTS THE UP ARROW 1 POSITION
; TO THE LEFT OF WHERE IT HAS CALCULATED THAT THE UP-ARROW SHOULD GO.
; (THIS IS USUALLY A MORE CORRECT PLACE TO PUT IT.) BUT THIS CAN
; BE PREVENTED BY STORING THE CHARACTER COUNT WORD WITH BIT ZERO
; SET TO ONE.
; ".FAILED" IS CALLED BY THE ".FAIL" ROUTINE WITH A1 CONTAINING
; THE FOLLOWING PARAMETER:
;
;
;
; +----------------------------------------------------------------+
; ! ! ! ! ! !
; ! !F! ! FLAGS ! MESSAGE NUMBER !
; ! ! ! ! ! !
; +----------------------------------------------------------------+
; 4 8 17 18 35
;
; BIT 4: UP-ARROW GOES UNDER READ BYTE POINTER, DONT SHIFT LEFT 1
; BITS 8-9: (OF NO CONCERN TO THIS MODULE)
; BIT 10: FATAL ERROR. HALT IMMEDIATELY
; BIT 11: "ILLEGAL USE OF" TYPE MESSAGE
; BIT 12: DELETE REL-FILE
; BIT 13: (OF NO CONCERN TO THIS MODULE)
; BIT 14: UP-ARROW GOES UNDER SYM
; BIT 15: UP-ARROW GOES UNDER DEL
; BIT 16: UP-ARROW GOES UNDER NSYM
; BIT 17: UP-ARROW GOES UNDER NDEL
; BITS 18-35: MESSAGE NUMBER
; FROM THE ABOVE PARAMETER ".FAILED" WILL COMPUTE A MESSAGE TABLE
; ENTRY AND INSERT IT INTO THE MESSAGE TABLE. THE FORMAT OF A MESSAGE
; TABLE ENTRY IS:
;
;
;
; +-----------------------------------------------------------------+
; ! ! ! ! !
; ! BYTE COUNT !FLAGS !KIND/TYPE! MESSAGE NUMBER !
; ! ! ! ! !
; +-----------------------------------------------------------------+
; 0 7 8 11 12 17 18 35
;
; BITS 0-7: POSITION OF ARROW ON PRINT PAGE
; BIT 8: ERROR ON THE PRECEDING LINE
; BIT 9: ERROR ON SOME PREVIOUS LINE
; BIT 10: "ILLEGAL USE OF" TYPE MESSAGE
; BIT 11: DELETE REL-FILE
; BITS 12-17: KIND AND TYPE EXTRACTED FROM LEXEME IN SYM
; BITS 18-35: MESSAGE NUMBER
; THE MESSAGES "START OF BLOCK N" AND "END BLOCK N, CONT M" ARE
; ALSO BUFFERED IN THE MESSAGE TABLE. ENTRIES FOR THESE HAVE THE
; FOLLOWING FORMAT, WHICH IS DISTINGUISHED FROM THE OTHERS BY HAVING
; A POSITION COUNT OF 377.
;
;
;
; +-----------------------------------------------------------------+
; ! ! ! ! !
; ! 377 ! ! VALUE 1 ! VALUE 2 !
; ! ! ! ! !
; +-----------------------------------------------------------------+
; 0 7 8 9 10 22 23 35
;
;
; BITS 0-7: 377
; BIT 8: MESSAGE ON THE PRECEDING OR SOME PREVIOUS LINE
; BIT 9: MUST BE ZERO
; BITS 10-22: VALUE 1
; BITS 23-35: VALUE 2
;
; IF VALUE2 = 0 THEN PRINT "START OF BLOCK (VALUE1)"
; ELSE PRINT "END BLOCK (VALUE2), CONT (VALUE1)";
..PREC==1000 ; ERROR ON PRECEDING LINE
..PREV==400 ; ERROR ON SOME PREVIOUS LINE
..IUO1==200 ; "ILLEGAL USE OF" FORM
..TERM==100 ; "REL FILE DELETED"
; ".FAIL", ".BLK1", AND ".BLK2" PUT ENTRIES IN THE MESSAGE TABLE,
; "LMSG" TAKES THEM OUT AND PRINTS THEM.
; LMSGS = 0 FOR PASS1, -1 FOR PASS2
; EDIT (1002) Include bad identifiers in error messages.
;
Edit(166); Correct Edit 1002 for errors at block level 1
;
LMSG1: MOVE A1,(A5) ; [E166] Get message entry.
TLC A1,776000 ; [E166] Is this a block begin or end ?
TLCN A1,776000 ; [E166] ...
AOJA A5,LMSG5 ; [E166] Yes - step to next entry
TLNE A1,..IUO1 ; [E166] If IUO or undeclared identifier
JRST LMSG6 ; [E166] ...
HRRZ A1,A1 ; [E166] ...
CAIE A1,1 ; [E166] ...
CAIN A1,^D62 ; [266] CHECK FOR SPECIFIC ERROR MESSAGE #
SKIPA ; [266] MESSAGE HAS MORE TO TYPE, SKIP
AOJA A5,LMSG5 ; [E166] ...
LMSG6: PUSHJ SP,IUOLN ; [E166] then get entry length in A1
ADDM A1,A5 ; [E166] and step extra length.
AOJA A5,LMSG5 ; STEP TO NEXT TABLE ENTRY
LMSG: PUSH SP,A2 ; SAVE A2
LMSG5: CAML A5,NAMTE ; [E166] END OF MESSAGES?
JRST LMSGE ; -YES, DONE
MOVE A2,(A5) ; GET ENTRY CONTENTS
MOVE A4,LMSGS ; LOAD THE SWITCH
TLNN A2,..PREC+..PREV; IF EITHER BIT IS SET
SETCM A4,A4 ; THEN THIS MESSAGE SHOULD BE PRINTED
JUMPN A4,LMSG1 ; ONLY ON THE 1ST PASS THROUGH LMSG
; CHECK FOR "START BLOCK" AND "END BLOCK" ENTRIES
LSH A2,-^D28 ; COLUMN POINTER
CAIN A2,377 ; IF BYTES=255 THEN IT IS
JRST BLK1A ; A BLOCK BEGIN OR END LINE
PUSHJ SP,CRFNL2 ; TERMINATE CREF DATA, IF ANY.
; WRITE: "****** ^"
MOVEI A1,STAR3 ; "*******"
PUSHJ SP,INSERT ; SEND TO LISTING
MOVE A2,(A5) ; GET MESSAGE TABLE ENTRY
TLNE A2,..PREV ; IF ERROR OCCURRED ON A PREVIOUS LINE
JRST LMSG3 ; THEN HANDLE SEPARATELY
LSH A2,-^D28 ; GET ARROW POSITION
JUMPE A2,LMSG2 ; NO ^ IF ZERO
TLNN A7,LTTY ; UNLESS THE LISTING IS GOING TO THE TTY
ADDI A2,^D16 ; PUT 16 MORE BLANKS AT START OF LINE
TLNN A7,EXISTS ; [E134] ARE WE LISTING
JRST LMSG2 ; [E134] NO - DON'T BOTHER
MOVEI A1,(A2) ; [E134] GET THE COUNT
MOVEI A2,.SPACE ; [E134] SPACE CHARACTER
PUSHJ SP,INS7 ; [E134] PUT CHAR IN BUFFER
SOJG A1,.-1 ; [E134]
MOVEI A2,.UP ; [E134]
PUSHJ SP,INS7 ; [E134] OUTPUT ^
SETZ A2, ; [E134]
PUSHJ SP,INS7 ; [E134] AND A NULL
JRST LMSG2 ; [E134]
LMSG4: PUSHJ SP,INSERT ; INSERT LINE IN LISTING
LMSG2: PUSHJ SP,ICHECK ; INCLUDE CR/LF
PUSHJ SP,NPRINT ; PUT ERROR LINE NUMBER IN LISTING
; WRITE ERROR MESSAGE TO LISTING
JSP A6,LMSG0 ; GET ERROR MESSAGE
HLL A1,(A5) ; GET FLAGS
TRNN A1,777777 ; IF NO ENTRY THEN
MOVEI A1,[ ; USE A
ASCIZ //] ; LITERAL NULL STRING
TLNE A1,..IUO1 ; IF "ILLEGAL USE OF"
PUSHJ SP,IUO ; THEN HANDLE SEPARATELY
PUSHJ SP,INSE ; PUT MESSAGE IN LISTING
HRRZ A1,(A5) ; [E1002] If undeclared identifier
CAIE A1,^D62 ; [266] IF MISSING FORWARD, LIST LABEL NAME
CAIN A1,1 ; [E1002] ...
PUSHJ SP,OUTSYM ; [E1002] then list spelling.
PUSHJ SP,KCHECK ; PUT CR/LF IN MESSAGE
; CHECK FOR FATAL ERROR
MOVE A4,(A5) ; GET MESSAGE TABLE ENTRY
TLNN A4,..TERM ; IF OBJECT CODE NOT TERMINATED
JRST [AOS WRNCNT ;[171] THEN INCREMENT WARNING COUNT
JRST LMSG1] ;[171] AND LOOP
AOS .JBERR ; ELSE INCREMENT ERROR COUNT
TLOE A7,TMG ; IF TERM MSG PREV GIVEN
JRST LMSG1 ; THEN LOOP
SETOM WFLAG ; MARK REL FILE TO BE ERASED
EDIT (247) ; [247] FIX COMPILER LOOPING WITH BAD PROG.
MOVEI A1,TERMC ; ADDR OF TERMINATION MESSAGE
PUSHJ SP,INS ; "REL-FILE DELETED"
PUSHJ SP,TCHECK ; CR/LF
JRST LMSG1 ; LOOP
TERMC: ASCIZ /?ALGNRF No .REL file created/
STAR3: ASCIZ /*******/
SPACE2: ASCIZ / /
; "NPRINT" WILL PRINT THE LINE NUMBER OF THE ERROR
NPRINT: MOVEI A1,[ASCIZ/%/] ; [300] DEFAULT TO WARNING
MOVE A4,(A5) ; [300] GET MESSAGE TABLE ENTRY
TLNE A4,..TERM ; [300] IF THIS WAS A FATAL ERROR
MOVEI A1,[ASCIZ/?/] ; [300] THEN USE A QUESTION MARK
PUSHJ SP,INSE ; [300] PUT CORRECT ONE IN LISTING
SKIPN LMSGS ; IF MESSAGE FOR PREVIOUS LINE
SKIPA A1,OLDNO ; THEN GET OLD LINE NUMBER
MOVE A1,LINENO ; ELSE GET LINE NUMBER
PUSHJ SP,LPRINT ; CONVERT IT TO ASCII
PUSHJ SP,INSE ; WRITE LINE NUMBER TO LISTING AND TTY
MOVEI A1,SPACE2 ; WRITE 2 SPACES
JRST INSE ; SEND TO LISTING AND TTY, EXIT NPRINT
; ERROR IS NEITHER ON CURRENT NOR PRECEDING LINE
LMSG3: MOVEI A1,Y19 ; "ERROR ON A PREVIOUS LINE"
JRST LMSG4 ; CONTINUE
; EXIT LMSG
LMSGE: PUSHJ SP,CREFST ; OUTPUT CREF START DATA, IF REQUIRED.
POP SP,A2 ; RESTORE A2
POPJ SP, ; EXIT LMSG
; AN "IUO" MESSAGE IS A MESSAGE OF THE FORM "XXX YYY FOUND WHERE A
; ZZZ WAS EXPECTED". THE ERROR MESSAGE NUMBER SPECIFIES ONLY THE
; TEXT OF ZZZ. XXX AND YYY ARE THE TYPE AND KIND OF WHAT WAS
; FOUND, AND THE TEXT OF THESE MUST BE DETERMINED BY DECODING THE
; LEXEME IN SYM.
IUO: LDB A1,[ ; GET "TYPE" OF ITEM
POINT 3,(A5),14] ; POINTER TO TYPE FIELD IN ENTRY
CAIN A1,4 ; IF IT IS A LABEL
JRST IUOLAB ; THEN HANDLE SEPARATELY
MOVE A1,IUOMT1(A1) ; GET NAME
PUSHJ SP,INS ; PUT IN LISTING
LDB A1,[ ; GET "KIND" OF ITEM
POINT 3,(A5),17] ; POINTER TO KIND FIELD IN ENTRY
MOVE A1,IUOMT2(A1) ; GET NAME
IUO1: PUSHJ SP,INS ; PUT IN LISTING
PUSHJ SP,OUTSYM ; [E1002] Put spelling in listing.
MOVEI A1,Y2 ; " WHERE A "
PUSHJ SP,INS ; PUT IN LISTING
JSP A6,LMSG0 ; GET MESSAGE
PUSHJ SP,INS ; PUT IN LISTING
MOVEI A1,Y3 ; " WAS EXPECTED"
POPJ SP, ; EXIT IUO
IUOLAB: LDB A1,[ ; GET "KIND" OF ITEM
POINT 3,(A5),17] ; POINTER TO KIND FIELD
MOVE A1,IUOMT3(A1) ; GET PROPER NAME
JRST IUO1 ; CONTINUE
LMSG0: HRRZ A1,(A5) ; GET MESSAGE #
ROT A1,-1
JUMPL A1,.+3
HLRZ A1,TTABLE(A1)
JRST (A6)
HRRZ A1,TTABLE(A1)
JRST (A6)
; BLOCK START OR END
BLK1A: TLNE A7,LTTY ; IF LISTING IS ON TTY
JRST LMSG1 ; THEN DONT WRITE BLOCK BEGIN OR END MSG
MOVE A4,(A5) ; RELOAD PARAM WORD
TRNE A4,017777 ; IF RIGHT-MOST 13 BITS NOT ZERO
JRST BLK2A ; THEN THIS IS AN END MESSAGE
; "START OF BLOCK N"
TRNN FL,CREF ; CREF ?
JRST BLK2B ; NO
PUSH SP,A5 ; DEC CLOBBERS THIS
PUSHJ SP,CREFST ; OUTPUT CREF START-DATA, IF NEEDED.
MOVEI A1,BLK2M3 ; START-BLOCK
PUSHJ SP,INSERT
MOVEI A3,5 ; FOR DEC
MOVE A2,["-",,"-"] ; FILLER-CHAR,,RIGHT-MOST FILLER
LDB A4,[POINT 13,(A5),22] ; BLOCK-NUMBER
PUSHJ SP,CRFDEC ; TO DECIMAL TO LISTING
MOVEI A5,^D8 ; UPDATE
ADDM A5,CRFCNT ; CHARACTER-COUNT
POP SP,A5
JRST LMSG1 ; DON'T PRINT 'START OF BLOCK'
BLK2B: MOVEI A1,BLK1M ; "START OF BLOCK "
BLKC: PUSHJ SP,INSERT ; PUT IN LISTING
LDB A1,[ ; GET THE NUMBER STORED IN
POINT 13,(A5),22] ; BITS 10-22
PUSHJ SP,LPRINT ; CONVERT TO DECIMAL ASCII
PUSHJ SP,INSERT ; PUT NUMBER IN LISTING
PUSHJ SP,ICHECK ; CR/LF
JRST LMSG1 ; LOOP
; "END OF BLOCK N, CONT M"
BLK2A: TRNN FL,CREF ; CREF ?
JRST BLK2C ; NO
PUSH SP,A5
PUSHJ SP,CREFST ; OUTPUT CREF START DATA, IF NEEDED.
MOVEI A1,BLK2M4 ; END BLOCK
PUSHJ SP,INSERT
MOVEI A3,5
MOVE A2,["-",,"-"] ; FILLER-CHAR,,RIGHT-MOST-FILLER
LDB A4,[POINT 13,(A5),35] ; BLOCK-NUMBER
PUSHJ SP,CRFDEC ; TO LISTING IN DECIMAL
MOVEI A5,^D8 ; UPDATE
ADDM A5,CRFCNT ; CHAR-COUNT
POP SP,A5
JRST LMSG1 ; DON'T PRINT 'END OF BLOCK'
BLK2C: MOVEI A1,BLK2M1 ; "END BLOCK "
PUSHJ SP,INSERT ; PUT IN LISTING
LDB A1,[ ; GET THE NUMBER STORED IN
POINT 13,(A5),35] ; BITS 23-35
PUSHJ SP,LPRINT ; CONVERT TO DECIMAL ASCII
PUSHJ SP,INSERT ; PUT NUMBER IN LISTING
MOVEI A1,BLK2M2 ; ", CONT "
JRST BLKC ; CONTINUE
BLK1M: ASCIZ /START OF BLOCK /
BLK2M1: ASCIZ /END BLOCK /
BLK2M2: ASCIZ /, CONT /
BLK2M3: BYTE(7)015,6,"B",0 ; CREF START-BLOCK: T15 6CH B
BLK2M4: BYTE(7)016,6,"E",0 ; CREF END BLOCK: T16 6CH E
; "LMSGZ" IS CALLED AT THE END OF THE COMPILATION BY ".ZZEND". "LMSGZ"
; WILL PRINT ALL MESSAGES THAT REMAIN IN THE MESSAGE TABLE THAT
; HAVE NOT YET BEEN PRINTED.
LMSGZ: MOVEM A7,A7SAV ; SAVE A7
MOVE A7,RFLAGS ; FETCH THE READ MODULE FLAGS
MOVEI A5,MTABLE ; ADDR OF MESSAGE TABLE
CAML A5,NAMTE ; IF NO MESSAGES IN MESSAGE TABLE
POPJ SP, ; THEN EXIT LMSGZ
SKIPE LMSGS ; [273] DUMP 1ST GROUP OF MESSAGES, UNLESS DONE
JRST LMSGZ2
PUSHJ SP,LMSG ; PRINT MESSAGES
LMSGZ2: MOVEI A5,MTABLE ; ADDR OF MESSAGE TABLE
SETOM LMSGS ; DUMP 2ND GROUP OF MESSSAGES
PUSHJ SP,LMSG ; PUT THEM IN LISTING
PUSHJ SP,CRFNL2 ; OUTPUT CREF END, & ANY NECESSARY NULLS
MOVEI A1,LINES3 ; PUT 3 BLANK LINES
PUSHJ SP,INSERT ; IN LISTING
JRST ICHECK ; INSERT A CR/LF, EXIT LMSGZ
LBP: POINT 7,LB ; [273] LISTING BUFFER POINTER
RELOC
MTABLE: BLOCK 50 ; MESSAGE TABLE
NAMTE: BLOCK 1
; MTABLE ; NEXT AVAIL MESSAGE TABLE ENTRY
LMSGS: BLOCK 1 ; LMSG SWITCH: 0 FOR PASS1, -1 FOR PASS2
LB: BLOCK 40 ; LISTING BUFFER FOR MESSAGES
OLDNO: BLOCK 1 ; OLD LINE NUMBER
WRNCNT: BLOCK 1 ;[171] WARNING COUNT
RELOC
Y2: ASCIZ / FOUND WHERE A/
Y3: ASCIZ / WAS EXPECTED/
Y4: ASCIZ /STRING/
Y5: ASCIZ /COMPLEX/
Y6: ASCIZ /TYPELESS/
Y7: ASCIZ /BOOLEAN/
Y8: ASCIZ /LONG REAL/
Y9: ASCIZ /REAL/
Y10: ASCIZ /INTEGER/
Y11: ASCIZ / VARIABLE/
Y12: ASCIZ / EXPRESSION/
Y13: ASCIZ / ARRAY IDENTIFIER/
Y14: ASCIZ / PROCEDURE/
Y15: ASCIZ / CONSTANT/
Y16: ASCIZ /LABEL/
Y17: ASCIZ /DESIGNATIONAL EXPRESSION/
Y18: ASCIZ /SWITCH/
IUOMT1: Y4
Y5
Y6
Y7
0
Y8
Y9
Y10
IUOMT2: Y11
Y12
Y13
Y14
Y15
IUOMT3: Y16
Y17
0
Y18
Y19 ;[252] MAKE ENTRY FOR Y19 TOO
Y19: ASCIZ / ERROR ON A PREVIOUS LINE:/
; THE INSERT ROUTINES ("INSERT", "INS", AND "INSE") ARE USED TO INSERT
; MESSAGES INTO THE LISTING. THE CHECK ROUTINES ("ICHECK", "TCHECK",
; AND "KCHECK") WILL INSERT A CR/LF INTO THE LISTING, AND THEN
; INSERT NULLS INTO THE LISTING SO THAT THE TOTAL NUMBER OF CHARACTERS
; INSERTED SINCE THE LAST CHECK ROUTINE WAS CALLED IS A MULTIPLE OF 5.
; WHENEVER AN INSERT ROUTINE IS USED, A CHECK ROUTINE MUST BE CALLED
; BEFORE THE NEXT CALL TO NEWLINE.
;
; "INSERT" AND "ICHECK" WRITE MESSAGES IN THE LISTING. "INS" AND
; "TCHECK" ALSO WRITE THE MESSAGE TO THE TTY. "INSE" AND "KCHECK"
; ARE USED TO WRITE MESSAGES WHEN MESSAGE 98 MIGHT BE ENCOUNTERED.
INSE: HRRZ A3,(A5) ; GET MESSAGE NUMBER
CAIN A3,^D98 ; IF THIS IS MESSAGE 98
JRST INSERT ; THEN DONT WRITE TO TTY
; INSERT LINE IN LISTING, AND ALSO WRITE IT TO TTY
INS: TLNN A7,NSWIT ; IF NO N-SWITCH
OUTSTR (A1) ; THEN WRITE IT TO TTY
JRST INSERT ; INSERT LINE IN LISTING
; PUT DECIMAL NUMBER IN LISTING
LPRINT: MOVE A6,LBP ; GET BUFFER BYTE POINTER
PUSHJ SP,LPR1 ; CONVERT IT TO CHARACTERS
MOVEI A1,0 ; ASCII NULL
IDPB A1,A6 ; END STRING WITH AN ASCII NULL
MOVEI A1,LB ; OUTPUT ADDRESS OF BUFFER
POPJ SP, ; EXIT LPRINT
; CONVERT IT TO DECIMAL
LPR1: IDIVI A1,12 ; DIVIDE BY TEN
PUSH SP,A2 ; PUT DIGIT ON STACK
SKIPE A1 ; SKIP IF END OF NUMBER
PUSHJ SP,LPR1 ; RECURSIVE CALL TO LPR1
POP SP,A1 ; FETCH DIGIT FROM STACK
ADDI A1,.N0 ; CONV TO ASCII
IDPB A1,A6 ; PUT IN BUFFER
POPJ SP, ; ASCEND FROM LPR1
; Write msg to listing, and to TTY if CCL and there were errors,
; or if not CCL (DONE1).
; DONE2 writes msg to listing, and to TTY if not CCL.
; Both used at end, called from START0, to do N Errors, stats, etc.
DONE1: SKIPE WRNCNT ; [300] ANY WARNINGS?
JRST INS ; [300] YES, SEND TO TTY
SKIPN .JBERR
DONE2: SKIPN CCLSW
JRST INS ; TO TTY AS WELL, IF REQUD.
; Insert a message in listing. The address of the message in ASCIZ
; format should be in A1
INSERT: TROA A2,777777 ; SET SWITCH TO SAY INSERT, NOT INSNUL
INSNUL: SETZ A2, ; INSERT ONE NULL
TLNN A7,EXISTS ; IF LISTING DOES NOT EXIST
INS2: POPJ SP, ; THEN DONT SEND MESSAGE THERE
JUMPE A2,INS7 ; IF NOT NULL...
HRLI A1,440700 ; SET UP BYTE POINTER
; CHARACTER TRANSFER LOOP
INS6: ILDB A2,A1 ; GET A CHAR
JUMPE A2,INS2 ; IF NULL, THE END
PUSHJ SP,INS7 ; [E134] OUTPUT THE CHARACTER
JRST INS6 ; [E134] AND LOOP UNTIL DONE
INS7: SOSGE FIVEC ; DECR NO OF REMAINING CHARS
JRST INS3 ; -END OF 5-CHAR GROUP
INS1: IDPB A2,W ; PUT CHAR IN LISTING
POPJ SP, ; DONE
; AT END OF WORD, CHECK FOR END OF LISTING BUFFER
INS3: HRRZ A6,W ; GET LISTING POINTER
ADDI A6,2 ; STEP TO NEXT WORD
CAML A6,OBEND ; IF IT IS NOT WITHIN BUFFER
JRST INS5 ; THEN GET A NEW BUFFER
INS4: MOVEI A6,4 ; 4 CHARS LEFT AFTER THIS ONE
MOVEM A6,FIVEC ; SET 5-CHAR GROUP COUNT
JRST INS1 ; CONTINUE
; END OF BUFFER, GET ANOTHER
INS5: HLRZ A4,W ; SAVE S-P BITS OF LISTING POINTER
PUSHJ SP,WRITEL ; GET A NEW BUFFER
AOS A6,W ; STEP LISTING POINTER
SETZM (A6) ; ZERO 1ST WORD OF BUFFER
HRLM A4,W ; SET S-P BITS
JRST INS4 ; CONTINUE
KCHECK: HRRZ A3,(A5) ; GET MESSAGE NUMBER
CAIN A3,^D98 ; IF IT IS MESSAGE 98
JRST ICHECK ; THEN DONT WRITE CR/LF TO TTY
; WRITE CR/LF TO TTY, THEN CALL "ICHECK"
TCHECK: MOVEI A1,NLCHRS ; PUT A CR/LF
PUSHJ SP,INS ; INTO LISTING
JRST IC2 ; CONTINUE
; "ICHECK MUST BE CALLED AFTER USING "INSERT" TO WRITE THE CR/LF TO
; THE LISTING, AND TO MAKE SURE THAT THE TOTAL INSERTED MESSAGE
; IS A MULTIPLE OF 5 CHARACTERS LONG.
ICHECK: MOVEI A1,NLCHRS ; PUT A CR/LF
PUSHJ SP,INSERT ; INTO LISTING
IC2: TLNN A7,EXISTS ; IF LISTING DOESNT EXIST
POPJ SP, ; THEN SKIP THIS
MOVEI A1,0 ; NULL CHARACTER
IC1: SOSGE FIVEC ; DECR NO OF REMAINING CHARS
POPJ SP, ; EXIT ICHECK IF NONE LEFT
IDPB A1,W ; PUT NULL INTO LISTTIG
JRST IC1 ; LOOP
RELOC
FIVEC: BLOCK 1 ; FIVE CHARACTER COUNT
RELOC
; PUT ENTRY IN MESSAGE TABLE
FAILED: MOVEM A6,REG3+5 ; SAVE A6
MOVE A6,[ ; LOAD BLT WORD
XWD A1,REG3] ; BLT WORD
BLT A6,REG3+4 ; SAVE REGS
; FIND THE BYTE POINTER TO THE ERROR
SETOM BYTES ; ZERO ^ POSITION
SETZB A4,FAILF ; CLEAR FLAGS
TLNN A1,..IMM+17 ; IF THERE IS TO BE NO ^
JRST FAILA ; THEN SKIP THIS PART
TLNN A1,..IMM ; IF NOT ^ WHERE POINTER IS NOW
JRST .+3 ; THEN SKIP
AOS BYTES ; USE EXACT POINTER
MOVE A4,CC ; THEN USE CURRENT READ POINTER
MOVE A5,PLIST ; GET POINTER LIST POINTER
XORI A5,2 ; FLIP IT
TLNE A1,..SYM ; IF ^ UNDER SYM
MOVE A4,(A5) ; THEN GET SYM POINTER
TLNE A1,..DEL ; IF ^ UNDER DEL
MOVE A4,1(A5) ; THEN GET DEL POINTER
XORI A5,2 ; FLIP POINTER SWITCH
TLNE A1,..NSYM ; IF ^ UNDER NSYM
MOVE A4,(A5) ; THEN GET NSYM POINTER
TLNE A1,..NDEL ; IF ^ UNDER NDEL
MOVE A4,1(A5) ; THEN GET NDEL POINTER
JUMPE A4,FAILB ; IF POINTER ZERO, ERROR ON A PREVIOUS LINE
TLZE A4,EXACT ; IF FLAG BIT IS ON
AOS BYTES ; THEN USE EXACT POINTER
; DETERMINE WHAT LINE THE ERROR IS ON
CAMGE A4,LP1 ; IF ERROR NOT ON CURRENT LINE
JRST FAILC ; THEN CHECK PRECEDING LINE
SUB A4,LP1 ; COMPUTE POSITION ON LINE
ADDM A4,BYTES ; SAVE IT
JRST FAILA ; CONTINUE
FAILC: CAMGE A4,LP2 ; IF ERROR NOT ON PRECEDING LINE
JRST FAILB ; THEN DONT PRINT AN ^
SUB A4,LP2 ; COMPUTE POSITION ON LINE
ADDM A4,BYTES ; SAVE IT
AOSA FAILF ; SET FLAG +
FAILB: SETOM FAILF ; SET FLAG -
; CREATE MESSAGE TABLE ENTRY
FAILA: AOS A4,BYTES ; GET UP ARROW POSITION
LDB A5,[ ; GET TYPE FIELD OF SYM
POINT 6,SYM,8] ; POINTER TO TYPE FIELD
CAIN A5,<$L>B44 ; IF TYPE = LABEL
MOVEI A5,4 ; THEN CHANGE TO 04
ANDI A5,7 ; USE ONLY 3 BITS OF TYPE FIELD
LSH A4,7 ; SHIFT 7
ADD A4,A5 ; INCLUDE TYPE FIELD
LSH A4,3 ; SHIFT 3
LDB A5,[ ; GET KIND FIELD OF SYM
POINT 2,SYM,2] ; POINTER TO KIND FIELD
TLNN SYM,$SYMB ; IF SYM IS A CONSTANT
MOVEI A5,4 ; THEN USE AN 04
ADD A4,A5 ; INCLUDE KIND
MOVS A4,A4 ; MOVE IMFO TO FINAL POSITION
MOVE A5,REG3 ; GET PARAMETER TO "FAILED"
HRR A4,A5 ; INCLUDE MESSAGE NUMBER
SKIPLE A6,FAILF ; IF ERROR ON PRECEDING LINE
TLO A4,..PREC ; THEN SET FLAG
SKIPGE A6 ; IF ERROR ON SOME PREVIOUS LINE
TLO A4,..PREV ; THEN SET FLAG
TLNE A5,SUSPCO ; IF TERMINATION BIT ON
TLO A4,..TERM ; THEN TURN ON CORRESPONDING BIT
BLK0: MOVE A6,NAMTE ; NEXT AVAILABLE MSG TABLE ENTRY SPACE
CAIL A6,MTABLE+50 ; IF PAST END OF TABLE
JRST BLK2 ; [E1002] then don't put in table
HRRZ A3,A5 ; [E1002] If undeclared identifier
CAIE A3,^D62 ; [266] CHECK FOR MISSING FORWARD LABEL TOO
CAIN A3,1 ; [E1002] ...
JRST .+4 ; [E1002] ...
TLNN A5,..IUO2 ; [E1002] or IUO
JRST BLK1 ; [E1002] ...
TLO A4,..IUO1 ; [E1002] then enter symbol spelling.
HRRZ A3,SYM ; [E1002] Address of symbol in A3
CAIL A3,MTABLE ; [E1002] In symbol table (best to make sure)?
CAML A3,NASTE ; [E1002] ...
JRST BLK3 ; [E1002] No - enter a null.
HLRZ A1,A4 ; [E1002] Get lexeme kind in A1
ANDI A1,7 ; [E1002] ...
CAIE A1,1 ; [E1002] If kind = expression or constant
CAIN A1,4 ; [E1002] ...
JRST BLK3 ; [E1002] then make a null entry.
MOVEI A3,SYMNAM(A3) ; [E1002] Start of spelling in ST.
HRRZ A1,@A3 ; [E1002] ...
PUSHJ SP,IUOLN1 ; [E1002] Get entry length in A1.
JRST BLK4
BLK3: MOVEI A1,1 ; [E1002] Null entry of length 1.
MOVEI A3,[EXP 0] ; [E1002] and zero value.
BLK4: ADDM A1,A6 ; [E1002] Room for spelling in table ?
CAIL A6,MTABLE+50 ; [E1002] ...
JRST BLK2 ; [E1002] No - don't enter it.
MOVE A6,NAMTE ; [E1002] Save current next entry free.
ADDM A1,NAMTE ; [E1002] Add in spelling entry length.
HRL A2,A3 ; [E1002] Set up BLT word.
HRR A2,A6 ; [E1002] ...
AOJ A2, ; [E1002] ...
BLT A2,@NAMTE ; [E1002] Move spelling into message table.
BLK1: MOVEM A4,(A6) ; [E1002] Put entry into table.
AOS NAMTE ; [E1002] Step table index.
BLK2: TLNE A5,..FATAL ; [E1002] If termination bit is on
JRST FAILT ; THEN STOP COMPILATION
MOVS A6,[ ; GET POINTERS FOR
XWD A1,REG3] ; BLT
BLT A6,A6 ; RESTORE REGISTERS
POPJ SP, ; EXIT FAILED
; FATAL ERROR. STOP COMPILATION IMMEDIATELY.
ILDB A1,P ; READ NEXT CHAR
FAILT: LDB A1,P ; RESD CHAR (FIRST TIME)
MOVE A2,CTABLE(A1) ; GET ITS ENTRY
CAIN A2,4 ; IF IT A NEW-LINE CHAR
PUSHJ SP,NEWLINE ; THEN PRINT LINE AND MESSAGES
JRST FAILT-1 ; ELSE READ ANOTHER CHAR
MOVEI A1,TERMSG ; TERMINATION MESSAGE
PUSHJ SP,INS ; INSERT IT IN LISTING
PUSHJ SP,TCHECK ; CR/LF
JRST RINIT+1 ; GET ANOTHER COMMAND STRING
RELOC
REG3: BLOCK 6 ; REGISTER SAVE AREA
BYTES: BLOCK 1 ; BYTE COUNT FOR ^
FAILF: BLOCK 1 ; FLAG USED BY FAILED
LP1: BLOCK 1 ; POINTER TO START OF CURRENT LINE
LP2: BLOCK 1 ; POINTER TO START OF PRECEDING LINE
BLKF: BLOCK 1 ; .BLK1 .BLK2 FLAG
RELOC
; [E1002] IUOLN - Finds the word length of a spelling in the ST.
IUOLN: HRRZ A1,1(A5) ; [E1002] Get entry length in A1.
IUOLN1: ANDI A1,77 ; [E1002] ...
ADDI A1,2 ; [E1002] ...
IDIVI A1,6 ; [E1002] ...
SKIPE ,A2 ; [E1002] ...
AOJ A1, ; [E1002] ...
POPJ SP, ; [E1002] Return.
; [E1002] OUTSYM - Inserts a spelling from the message table
; into the listing.
OUTSYM: MOVE A1,A5 ; [E1002] Adress of spelling - 1.
SKIPN ,1(A5) ; [E1002] If null entry
POPJ SP, ; [E1002] then don't bother.
PUSH SP,A5 ; [E1002] Convert to ASCIZ in LB.
SOJ A1, ; [E1002] ...
PUSHJ SP,NAME ; [E1002] ...
POP SP,A5 ; [E1002] ...
MOVEI A1,[ASCIZ/ </] ; [E1002] List a '<'.
PUSHJ SP,INS ; [E1002] ...
MOVEI A1,LB ; [E1002] List spelling.
PUSHJ SP,INS ; [E1002] ...
MOVEI A1,[ASCIZ/>/] ; [E1002] List a '>'.
PUSHJ SP,INS ; [E1002] ...
POPJ SP, ; [E1002] Return.
; START OF BLOCK
.BLK1: SETZM BLKF ; ZERO THE FLAG
JRST .+2 ; SKIP
; END OF BLOCK
.BLK2: SETOM BLKF ; SET FLAG NON-ZERO
MOVEM A6,REG3+5 ; SAVE WORD
MOVE A6,[ ; LOAD BLT WORD
XWD A1,REG3] ; BLT WORD
BLT A6,REG3+4 ; SAVE ALL 6 REGS
MOVE A2,CURBLOCK ; GET CURRENT BLOCK NUMBER
SKIPN BLKF ; IF .BLK1 THEN
LSHC A1,^D36 ; MOVE TO A1, CLEAR 2ND PARAM
LSH A2,^D23 ; COMBINE THE PARAM IN A1
LSHC A1,-^D23 ; WITH THE PARAM IN A2
MOVE A5,PLIST ; POINTER BUFFER
XORI A5,2 ; FLIP IT TO SYM AND DEL
MOVE A4,1(A5) ; GET POINTER TO DEL
SKIPN BLKF ; IF .BLK1 THEN
MOVE A4,(A5) ; USE POINTER TO SYM INSTEAD
TLZE A4,EXACT ; IF FLAG BIT IS ON
ADDI A4,1 ; THEN USE EXACT POINTER
CAMG A4,LP1 ; DETERMINE WHICH LINE IT IS ON
TLO A2,..PREC ; MARK: ON PRECEDING LINE
TLO A2,776000 ; SET BYTES=255
MOVE A4,A2 ; MOVE TO A4
MOVEI A5,0 ; CLEAR A5
JRST BLK0 ; CONTINUE
SCDLT=.-43
LEX(NE) ; "#"
BLOCK 4
LEX(LPAR) ; "("
LEX(RPAR) ; ")"
LEX(TIMES) ; "*"
LEX(PLUS) ; "+"
LEX(COM) ; ","
LEX(MINUS) ; "-"
LEX(DOT) ; "."
LEX(SLASH) ; "/"
TCDLT: XWD L$ASS,R$ASS ; ":="
0
LEX(LEQ) ; "<="
0
LEX(GTE) ; ">="
0
LEX(UPLUS)
LEX(UMINUS)
LEX(PHID)
0
LEX(COLON) ; ":"
LEX(SC) ; ";"
LEX(LSS) ; "<"
LEX(EQ) ; "="
LEX(GTR) ; ">"
BLOCK ^D28
LEX(LBRA) ; "["
LEX(EOF) ; END-OF-FILE
LEX(RBRA) ; "]"
LEX(POW) ; "^"
LEX(ASS) ; "_"
SUBTTL ** LSCAN **
; ***** L S C A N *****
;
; "LSCAN" READS ALGOL TEXT FROM A FILE AND
; CONVERTS IT TO AN INTERNAL CODE. EACH CALL TO
; LSCAN PRODUCES THE NEXT ITEM FROM THE ALGOL
; PROGRAM. ITEMS ARE OF THREE TYPES:
;
; 1. IF THE ITEM IS A DELIMITER (EITHER
; SINGLE CHARACTER OR RESERVED WORD) LSCAN SETS
; A3 EQUAL TO THE LEXEME OF THAT DELIMITER.
;
; 2. IF THE ITEM IS A LITERAL CONSTANT
; LSCAN SETS A3 EQUAL THE LEXEME FOR THAT
; CONSTANT (PUTTING THE CONSTANT IN THE OBJECT
; MODULE'S CONSTANT TABLE IF NECESSARY), AND
; SKIP-RETURNS.
;
; 3. IF THE ITEM IS AN IDENTIFIER NAME
; LSCAN PLACES IN A3 A POSITIVE NUMBER (A
; BUFFER ADDRESS), AND SKIP-RETURNS. THIS NUMBER
; IS THE INPUT PARAMETER TO THE ROUTINE "SEARCH"
; WHICH IS USED TO PRODUCE THE LEXEME FOR THE
; IDENTIFIER.
LSCAN: SKIPE A3,BLEX ; IF THERE IS A BUFFERED LEXEME
JRST BLEXR ; THEN TREAT SEPARATELY
LDB A1,P ; PICK UP 1ST CHAR
SKIPE A2,CTABLE(A1) ; LOAD TABLE ENTRY, SKIP IF DELIM
JRST @TABLE1(A2) ; JUMP TO APPROPRIATE ROUTINE
JRST DELIM
DIGITS ; NUMBERS
LETTER ; LETTERS
TABLE1: DELIM ; DELIMITERS
FLAGD ; DELIMITERS (FLAGGED)
SPACE ; IGNORABLES
SPACE ; SPACE & TAB
NEW1 ; NEW-LINE
LOWER ; LOWER CASE
OTHER ; OTHER CHARS
SQUOTE ; SINGLE QUOTE
; SPACE OR TAB
SPACE: CAIN A1,.TAB ; IF IT IS A TAB
PUSHJ SP,TAB ; COMPUTE ITS LENGTH
ILDB A1,P ; GET ANOTHER CHAR
AOSA CC ; STEP POSITION COUNT
; END OF LINE - WATCH THE SPACING HERE !
NEW1: PUSHJ SP,NEWLINE ; PROCESS LISTING, GET NEXT CHAR
JFCL ; NO-OP
NEW3: MOVE A2,CTABLE(A1) ; LOAD TABLE ENTRY
JRST @TABLE1(A2) ; JUMP TO APPROPRIATE ROUTINE
; FLAGGED CHAR: : < > !
FLAGD: CAIN A1,.EXCL ; IF CHAR IS A "!"
JRST COMNT0 ; THEN PROCESS COMMENT
MOVE A4,A1 ; COPY CHARACTER TO A4
JSP A6,IGST ; READ THE NEXT CHARACTER
CAIN A1,.EQUAL ; IS IT AN "=" ??
JRST FLAGD1 ; -YES, ITS A 2-CHAR DELIM
MOVE A3,SCDLT(A4) ; PICK UP LEXEME FOR DELIM
POPJ SP, ; EXIT LSCAN
; :=, <=, OR >=
FLAGD1: MOVE A3,TCDLT-.COLON(A4); GET DELIMETER LEXEME
JRST SQOK2 ; EXIT LSCAN
; A SPECIAL CHARACTER WAS SCANNED
OTHER: HLRZ A2,CTABLE(A1) ; GET LEFT HALF OF CHARS TABLE ENTRY
JRST @TABLE3(A2) ; JUMP THROUGH TABLE 3
TABLE3: ILLEGAL ; ILLEGAL CHARACTER
POWER ; @ &
SCON ; " $ %
DOT ; .
; SPECIAL CONSTANT
SCON: CAIN A1,.% ; A "%" INDICATES
JRST OCTAL ; AN OCTAL CONSTANT
CAIN A1,.$ ; A "$" INDICATES
JRST DOLLAR ; A SYMBOL CONSTANT
JRST STRING ; OTHERWISE, MUST BE A STRING
; A CONSTANTLESS EXPONENT
POWER: SETZB A4,MARKER ; MARK: NO DECIMAL POINT
MOVEI A5,1 ; SET DOUBLE-LENGTH CONSTANT = 1
SETZM FORMAT ; [E044] ASSUME SINGLE PRECISION
JRST C22 ; [E044] AND JUMP INTO DIGITS
; A DOT HAS BEEN SCANNED
DOT: JSP A6,IGST ; GET THE NEXT CHAR
MOVE A3,CTABLE(A1)
AOJGE A3,DOT1 ; IF NOT DIGIT, DELIMITER
MOVEI A3,^D9 ; SET LOOP INDEX
MOVEM A3,MARKER ; SET DECIMAL POINT MARKER
SETZB A4,FORMAT ; [E044] CLEAR HI WORD OF DOUBLE
MOVEI A5,-.N0(A1) ; CONVERT 1ST CHAR TO BINARY
SOJA A3,LLOOP1 ; JUMP INTO "NUMBER"
; THE DOT IS A DELIMITER
DOT1: SKIPA A3,ZDOT ; LOAD ITS LEXEME
BLEXR: SETZM BLEX ; CLEAR INDICATOR
POPJ SP, ; EXIT LSCAN
; AN ILLEGAL CHAR HAS BEEN SCANNED
ILLEGAL: FAIL (93,SOFT,IMM,ILLEGAL CHARACTER)
ILL1: ILDB A1,P ; GET NEXT CHAR
AOS CC ; STEP POSITION COUNT
MOVE A2,CTABLE(A1) ; GET ITS TABLE ENTRY
CAIN A2,6 ; IF IT TOO IS AN ILLEGAL CHARACTER
JRST ILL1 ; THEN LOOP WITHOUT PRINTING ANOTHER MSG
JRST @TABLE1(A2) ; OTHERWISE JUMP THROUGH TABLE 1
; **** CHARACTER TABLE ****
;
; THIS TABLE IS USED TO CLASSIFY EACH OF
; THE ASCII CHARACTERS ACCORDING TO THE
; FOLLOWING TYPES:
;
; -2 DIGIT
; -1 LETTER
; 0 SINGLE-CHARACTER DELIMITERS
; 1 FLAGGED DELIMITERS
; 2 SHOULD BE IGNORED ON INPUT
; 3 SPACE CHARS (SPACE & TAB)
; 4 NEW-LINE CHARS (CR, LF, )
; 5 LOWER CASE LETTERS
; 6 OTHER CHARS.
; LEFT HALF:
; 0 ILLEGAL CHAR
; 1 @ &
; 2 " $ %
; 3 .
; 7 SINGLE QUOTE
0 ; -1 PSEUDO ALTMODE (SCANCH)
CTABLE: 2 ; 0 NULL
6 ; 1 ^A
6 ; 2 ^B
6 ; 3 ^C
6 ; 4 ^D (EOT)
6 ; 5 ^E (WRU)
6 ; 6 ^F
6 ; 7 ^G (BELL)
6 ; 10 ^H (BACKSPACE)
3 ; 11 ^I (TAB)
4 ; 12 ^J (LINE FEED)
6 ; 13 ^K (VERT TAB)
3 ; 14 ^L (FORM)
4 ; 15 ^M (RETURN)
6 ; 16 ^N
6 ; 17 ^O
6 ; 20 ^P
2 ; 21 ^Q (XON)
2 ; 22 ^R (TAPE)
2 ; 23 ^S (XOFF)
2 ; 24 ^T (NOTAPE)
6 ; 25 ^U
6 ; 26 ^V
6 ; 27 ^W
6 ; 30 ^X
6 ; 31 ^Y
4 ; 32 ^Z
6 ; 33 ^LBRAC (ESC)
6 ; 34 ^\
6 ; 35 ^RBRAC
6 ; 36 ^^
6 ; 37 ^_
3 ; 40 SPACE
XWD 1,1 ; 41 !
XWD 2,6 ; 42 "
0 ; 43 #
XWD 2,6 ; 44 $
XWD 2,6 ; 45 %
XWD 1,6 ; 46 &
7 ; 47 '
0 ; 50 (
0 ; 51 )
0 ; 52 *
0 ; 53 +
0 ; 54 ,
0 ; 55 -
XWD 3,6 ; 56 .
0 ; 57 /
-2 ; 60 0
-2 ; 61 1
-2 ; 62 2
-2 ; 63 3
-2 ; 64 4
-2 ; 65 5
-2 ; 66 6
-2 ; 67 7
-2 ; 70 8
-2 ; 71 9
1 ; 72 :
0 ; 73 ;
1 ; 74 LESS THAN
0 ; 75 =
1 ; 76 GRTR THAN
6 ; 77 ?
XWD 1,6 ; 100 @
-1 ; 101 A
-1 ; 102 B
-1 ; 103 C
-1 ; 104 D
-1 ; 105 E
-1 ; 106 F
-1 ; 107 G
-1 ; 110 H
-1 ; 111 I
-1 ; 112 J
-1 ; 113 K
-1 ; 114 L
-1 ; 115 M
-1 ; 116 N
-1 ; 117 O
-1 ; 120 P
-1 ; 121 Q
-1 ; 122 R
-1 ; 123 S
-1 ; 124 T
-1 ; 125 U
-1 ; 126 V
-1 ; 127 W
-1 ; 130 X
-1 ; 131 Y
-1 ; 132 Z
0 ; 133 LBRAC
6 ; 134 \
0 ; 135 RBRAC
0 ; 136 ^
0 ; 137 _
6 ; 140 LEFT SINGLE QUOTE
5 ; 141 LA
5 ; 142 LB
5 ; 143 LC
5 ; 144 LD
5 ; 145 LE
5 ; 146 LF
5 ; 147 LG
5 ; 150 LH
5 ; 151 LI
5 ; 152 LJ
5 ; 153 LK
5 ; 154 LL
5 ; 155 LM
5 ; 156 LN
5 ; 157 LO
5 ; 160 LP
5 ; 161 LQ
5 ; 162 LR
5 ; 163 LS
5 ; 164 LT
5 ; 165 LU
5 ; 166 LV
5 ; 167 LW
5 ; 170 LX
5 ; 171 LY
5 ; 172 LZ
6 ; 173 LEFT BRACE
6 ; 174 VERTICAL BAR
3 ; 175 RIGHT BRACE (ALTMODE)
6 ; 176 NOT
2 ; 177 DELETE
; ***** L E T T E R *****
;
; "LETTER" SCANS IDENTIFIER NAMES AND RESERVED WORDS,
; UNLESS RESERVED WORDS ARE QUOTED. "LETTER" WILL OUTPUT
; THE LEXEME OF A RESERVED WORD OR THE BUFFER ADDRESS OF AN
; IDENTIFIER.
;
; "LETTER" READS CHARACTERS 6 AT A TIME. THE 7-BIT
; CHARACTERS ARE READ INTO REGISTER A1 WITH AN ILDB AND
; THEN 6 OF THESE BITS ARE SHIFTED INTO REGISTER A2 WITH
; A "LSHC A1,-6" . WHEN REGISTER A2 IS FULL IT IS DUMPED
; INTO THE NEXT WORD OF A NAME BUFFER. THUS THE NAME IS
; STORED IN A NAME BUFFER, 6 CHARACTERS PER WORD (NOT
; THE SAME AS "SIXBIT" CHARACTERS), WITH THE CHARACTERS IN
; REVERSE ORDER, AND WITH BLANKS ON THE RIGHT. THE RIGHT-MOST
; 6 BITS OF THE 1ST WORD OF THE NAME IN THE NAME BUFFER
; CONTAIN THE LENGTH OF THE NAME IN CHARACTERS MINUS 1.
; THE WORD IMMEDIATELY PRECEDING THE NAME BUFFER CONTAINS
; THE LENGTH OF THE NAME IN WORDS MINUS 1.
;
; UNLESS RESERVED WORDS ARE QUOTED, THE NAME IS THEN LOOKED
; UP IN THE RESERVED WORD TABLE TO FIND OUT IF IT IS A RESERVED
; WORD. IF IT IS FOUND, THE LEXEME IS OUTPUT, AND THE NAME
; BUFFER WILL BE USED AGAIN AT THE NEXT CALL TO "LETTER".
; IF IT IS NOT FOUND, THE NAME BUFFER ADDRESS IS OUTPUT.
; THIS ADDRESS IS USED BY "SEARCH" TO LOCATE THE IDENTIFIER
; IN THE SYMBOL TABLE. THE NEXT CALL TO "LETTER" WILL NOT
; USE THE SAME NAME BUFFER, THUS "SEARCH" DOES NOT HAVE TO
; BE CALLED IMMEDIATELY. "LETTER" CURRENTLY ROTATES AMONGST
; THREE NAME BUFFERS.
;
LOWER: MOVEI A1,-40(A1) ; CONVERT TO UPPER CASE
LETTER: SKIPE A5,RWS ; IF RESERVED MODE
MOVE A5,@A5 ; LOCATE RESERVED WORD SUBLIST
MOVEM A5,RWSL ; SAVE IT FOR LATER
AOSA A3,LSBUFP ; GET LIST INDEX AND SKIP
SETZM LSBUFP ; ZERO INDEX
SKIPN A3,LSBUFT(A3) ; LOCATE A NAME BUFFER
JRST .-2 ; -RECYCLE
SETZ A2, ; CLEAR A2
HRLZI A5,-5 ; SCAN 1ST 5 CHARS
HRLZI A6,-13 ; BUT NO MORE THAN 65 CHARS
; CHARACTER-READING LOOP
LET1: LSHC A1,-6 ; MOVE CHAR TO ACC A1
ILDB A1,P ; GET NEXT CHAR
AOS CC ; STEP POSITION COUNT
SKIPL A4,CTABLE(A1) ; CHECK IF LETTER OR NUMBER
JRST @TABLE2(A4) ; -NO, GOTO A ROUTINE
LET2: AOBJN A5,LET1 ; LOOP
; END OF 6-CHAR GROUP
MOVEM A2,@A3 ; SAVE CHARS IN NAME BUFFER
SETZ A2, ; CLEAR A2
HRLI A5,-6 ; READ NEXT 6 CHARS
AOBJN A6,LET1 ; BUT NOT PAST 65 CHARS
; LINE EXCEEDS 64 CHARS
LET3: MOVEI A6,-1(A6) ; BACK UP COUNTER
FAIL (91,SOFT,IMM,NAME EXCEEDS 64 CHARACTERS)
PUSHJ SP,ATNAC ; ADVANCE TO NEXT ALPHAMERIC CHARACTER
MOVEI A5,77 ; MAKE NAME 63 CHARACTERS LONG
MOVEI A6,12 ; MAKE NAME 11 WORDS LONG
JRST LET4+3 ; CONTINUE
TABLE2: LET4 ; DELIMITERS
LET4 ; DELIMITERS (FLAGGED)
LET1+1 ; IGNORABLES
LET12 ; SPACE & TAB
LET13 ; NEW-LINE
LET11 ; LOWER CASE
LET14 ; OTHER
LET4 ; SINGLE QUOTE
LET12: SKIPN RWS ; RESERVED WORD MODE?
JRST LET1+1 ; NO - IGNORE
; END OF NAME, CHECK IF RESERVED WORD
LET4: MOVEM A2,@A3 ; SAVE LAST GROUP OF CHARS
TRNE A5,100 ; IF NAME IS 65 CHARACTERS LONG
JRST LET3 ; THEN GIVE ERROR
HRRZM A6,-1(A3) ; PUT LENGTH-IN-WORDS IN BUFFER
MOVEI A6,(A5) ; PUT LENGTH-IN-CHARS IN A6
IORB A6,(A3) ; PUT LENGTH IN BUFFER, PICK UP 1ST WORD
SQ3: SKIPN A5,RWSL ; IS THERE A SUBLIST?
JRST LET9 ; -NO, SKIP EVERY THING
LET7: CAME A6,RWTNAM(A5) ; DO 1ST WORDS MATCH?
JRST LET8 ; -NO, CONTINUE SEARCH
LET5: SKIPL A4,RWTLEN(A5) ; IS NAME 1 WORD LONG?
JRST LET6 ; -NO, 2 WORDS LONG
LET10: MOVE A4,1(A3) ; GET 2ND WORD OF NAME BUFFER
CAME A4,RWTNAM+1(A5) ; DO 2ND WORDS MATCH
JRST LET8 ; -NO, CONTINUE
; NAME FOUND IN RESERVED-WORD TABLE
LET6: MOVE A3,RWTLEX(A5) ; LOAD LEXEME
SKIPE RWS ; IF RESERVED WORD MODE
SOS LSBUFP ; RELEASE BUFFER
CAIGE A5,FRW ; IS RESERVED WORD FLAGGED?
JRST @RWTRT(A5) ; -YES, GOTO ROUTINE
POPJ SP, ; -NO, LSCAN
LET8: HRRZ A5,RWTLNK(A5) ; LOCATE ENTRY ON SUBLIST
JUMPN A5,LET7 ; LOOP UNLESS LINK=0
;;; GENERAL SKIP RETURN POINT
; NAME IS NOT A RESERVED WORD - IS AN IDENTIFIER
LET9: POP SP,A4 ; GET RETURN LINK
JRST 1(A4) ; SKIP RETURN
; LOWER-CASE LETTER SCANNED
LET11: MOVEI A1,-40(A1) ; CONVERT TO UPPER CASE
JRST LET2 ; CONTINUE
LET13: PUSHJ SP,NCHECK ; INPUT NEXT LINE
JRST LET1+3 ; -END OF BUFFER IN MID LINE, CONTINUE
JRST LET4 ; END OF NAME
LET14: CAIE A1,.DOT ; IF THIS IS A DOT
JRST LET4 ; ELSE END OF NAME
PUSH SP,A6 ; SAVE A6
PUSH SP,A2 ; SAVE A2
JSP A6,GETCHR ; READ NEXT CHARACTER
POP SP,A2 ; RESTORE A2
POP SP,A6 ; RESTORE A6
SKIPGE CTABLE(A1) ; IF IT IS A LETTER OR A NUMBER
JRST LET2 ; THEN CONTINUE WITH IDENTIFIER NAME
MOVE A4,ZDOT ; ELSE BUFFER THE LEXEME FOR
MOVEM A4,BLEX ; THE DELIMITER "DOT"
JRST LET4 ; END OF IDENTIFIER NAME
; THE FOLLOWING ROUTINES PROCESS THE FLAGGED RESERVED WORDS
FBEGIN: SOSGE A5,BTI ; DECREMENT BEGIN TABLE INDEX
POPJ SP, ; EXIT LSCAN IF TABLE IS FULL
AOS A4,BNUM ; ADD 1 TO BEGIN NUMBER
MOVEM A4,BTAB(A5) ; STORE NUMBER IN TABLE
POPJ SP, ; EXIT LSCAN
FEND: AOSG A4,BTI ; STEP BEGIN TABLE INDEX
POPJ SP, ; EXIT LSCAN IF TABLE STILL FULL
SKIPE A4,BTAB-1(A4) ; LOAD BEGIN NUMBER (DON'T PRINT E0)
MOVEM A4,ENUM ; SAVE FOR PRINTING
POPJ SP, ; EXIT LSCAN
; A "GO" HAS BEEN SCANNED, NOW SEARCH FOR THE "TO"
FGO: LDB A1,P ; GET LAST CHAR
MOVE A2,CTABLE(A1) ; GET ITS TABLE ENTRY
FGO1: CAIE A2,3 ; IF IT IS NOT A SPACE OR A TAB
JRST GOERR2 ; THEN HE BLEW IT
JSP A6,GETCHR ; GET ANOTHER CHAR
CAIE A1,.T ; IF IT IS NOT A "T"
JRST FGO1 ; THEN SEARCH NEXT CHAR
JSP A6,GETCHR ; GET ANOTHER CHAR
CAIE A1,.O ; IF IT IS NOT A "O"
JRST GOERR1 ; THEN IT IS WRONG
JSP A6,GETCHR ; GET ANOTHER CHAR
CAIE A2,-1 ; THIS CHARACTER MUST NOT BE AN UPPER
CAIN A2,5 ; OR LOWER CASE LETTER
JRST GOERR1 ; OR IT IS AN ERROR
FGO2: MOVE A3,ZGOTO ; LOAD LEXEME
POPJ SP, ; EXIT LSCAN
GOERR1: PUSHJ SP,ATNAC ; ADVANCE TO NON-ALPHAMERIC CHAR
GOERR2: FAIL (99,SOFT,IMM,DID NOT FIND 'TO' IN 'GOTO' STATEMENT) ; [273]
JRST FGO2
COMNT2: SKIPN RWS ; 'COMMENT': IF QUOTED MODE
JRST [POP SP,A1 ; [273] THEN LOSE LINK FROM SQUOTE
JRST COMNT1] ; [273] AND PARSE COMMENT
TDZA A1,A1 ; AND CLEAR A1
COMNT0: MOVEI A1,-1 ; "!": FLAG A1
CAME DEL,ZEND ; IF DEL#END
EDIT(104); Allow comment to go over newlines without error.
JRST COMNT4 ; [E104] THEN PROCEED
;
Edit(161); Accept COMMENT after END without error.
;
SKIPE A1 ; [E161] ELSE if "!" then
JSP A6,GETCHR ; [E161] get next character
JRST LSCAN ; [E161] and let SBEGIN process comment.
COMNT4: PUSHJ SP,COMNT3(A1) ; [E104] DISPATCH TO IGNORE COMMENT
IBP P ; [E104] THEN STEP BYTE POINTER
AOS CC ; [E104] AND CHARACTER COUNT
JRST LSCAN ; [E104] TO IGNORE SEMICOLON
NEW2: PUSHJ SP,NEWLINE ; CALL NEWLINE (SKIP RETURN!)
COMNT1: JSP A6,GETCHR ; GET NEXT CHAR
COMNT3: LDB A1,P ; GET THE CHARACTER
MOVE A2,CTABLE(A1) ; GET ITS TABLE ENTRY
CAIN A2,4 ; IF IT IS A NEW-LINE CHAR
JRST NEW2 ; THEN HANDLE SPECIALLY
CAIN A1,.SEMI ; [273] IF IT'S A SEMI-COLON
POPJ SP, ; [273][E104] THEN RETURN
SKIPE RWS ; [273] ELSE, RESERVED WORD MODE?
JRST COMNT1 ; [273] NO, JUST LOOP UNTIL SEMICOLON FOUND
CAIE A2,7 ; [273] YES, IS CHR. A SINGLE-QUOTE?
JRST COMNT1 ; [273] NO, CONTINUE LOOPING
FAIL (92,SOFT,IMM,RESERVED WORD DELIMITER NOT ALLOWED HERE) ; [273]
JRST COMNT1 ; [273] YES, ERROR AND CONTINUE SCANNING COMMENT
44; ***** D I G I T S *****
;
; "DIGITS" IS USED TO SCAN DECIMAL CONSTANTS. "DIGITS"
; WILL COMPUTE THE VALUE, PUT IT INTO THE CONSTANTS TABLE
; IF NECESSARY, AND PRODUCE THE LEXEME.
;
; "DIGITS" WORKS BY READING THE 1ST 10 DIGITS WITH A
; QUICK 7-INSTRUCTION LOOP (LLOOP1) THAT ALWAYS PRODUCES AN INTEGER.
; IF A DECIMAL POINT IS ENCOUNTERED, THE LOOP INDEX IS SAVED
; IN "MARKER" AND USED LATER TO DETERMINE THE POWER OF TEN,
; THEN CONTROL RETURNS TO THE LOOP. IF THERE ARE MORE THAN
; TEN DIGITS, CONTROL PASSES TO A SECOND LOOP (LLOOP2) THAT
; READS DIGITS INTO THE DOUBLE AC 4-5 ABSORBING A DECIMAL
; POINT IF NECESSARY. FINALLY
; THE CONSTANT IS CONVERTED TO THE INDICATED TYPE.
; SINGLE-PRECISION FLOATING POINT IS FIRST CONVERTED TO
; DOUBLE-PRECISION FLOATING POINT, THEN THE POWER OF TEN
; IS INCLUDED. THIS IS DONE SO THAT ALL 27 BITS OF THE
; FRACTION ARE ACCURATE.
; ROUNDING TO SINGLE-PRECISION IS DONE LATER, IF NECESSARY, BY
; CONVERT.
;
DIGITS:
; SET UP FOR READING DIGITS
MOVEI A3,^D9 ; READ 1ST 9 DIGITS OF NUMBER
SETZB A4,MARKER ; CLEAR DECIMAL POINT MARKER
SETZM EXTRA ; AND EXTRA DIGIT COUNT
EDIT(044); Dont force constants to D.P. unnecessarily
SETZM FORMAT ; [E044] ASSUME IT WILL BE SINGLE PRECISION
MOVEI A5,-.N0(A1) ; CONVERT 1ST CHAR TO BINARY
; MAIN LOOP FOR SCANNING NUMBER
LLOOP1: ILDB A1,P ; READ NEXT CHAR
AOS CC ; STEP POSITION COUNT
C1: MOVE A2,CTABLE(A1) ; GET CHAR'S TABLE ENTRY
JRST @TABLE4(A2) ; JUMP THROUGH TABLE 4
C2: IMULI A5,^D10 ; MULT PREVIOUS RESULT BY TEN
ADDI A5,-.N0(A1) ; ADD IN NEW DIGIT
SOJG A3,LLOOP1 ; LOOP
; NUMBER IS LONGER THAN 10 CHARS
MOVEI A3,30000 ; SET A NEW INDEX
SKIPE MARKER ; IF A DECIMAL POINT HAS OCCURRED
ADDM A3,MARKER ; THEN ADD NEW INDEX TO MARKER
; LOOP THAT READS UNTIL OVERFLOW
LLOOP2: JSP A6,IGST ; READ NEXT CHAR
CAIN A1,.DOT ; IF IT IS A DOT
JRST C3 ; THEN EXIT THIS LOOP
MOVE A2,CTABLE(A1) ; IF CHAR IS NOT NUMERIC
AOJGE A2,@TABLE4(A2) ; GO ELSEWHERE
EXCH A4,A5 ; SWAP TO LONG MULTIPLY
MULI A4,^D10 ; MULTIPLY SUM SO FAR
ADDI A5,-.N0(A1) ; AND ADD THE NUMBER
TLZE A5,(1B0) ; [E044] OVERFLOW INTO TOP BIT ?
AOJA A4,C6D ; [E044] YES - ADD IT IN TO A4
JUMPN A4,C6D ; IF A4 NON-ZERO SUM V. LARGE
SOJA A3,LLOOP2 ; KEEP GOING
C3: MOVEM A3,MARKER ; STORE DECIMAL POINT MARKER
; MAIN LOOP FOR SCANNING LONG NUMBERS
LLOOP3: ILDB A1,P ; GET NEXT CHAR
AOS CC ; STEP POSITION COUNT
C5: MOVE A2,CTABLE(A1) ; GET(TABLE ENTRY
JRST @TABLE5(A2) ; AND USE TABLE5
C6: MOVEM A5,COPY ; LONG INTEGER MULTIPLY
MULI A4,^D10 ; MULTIPLY HIGH-ORDER WORD
JUMPN A4,C6A ; TOO BIG IF NON-ZERO
MOVE A4,COPY ; NOW THE LOW-ORDER
MOVEM A5,COPY ; INTO THE CORRECT HALF
MULI A4,^D10 ; MULTIPLY LOW-ORDER WORD
ADDI A5,-.N0(A1) ; ADD IN THE NEW NUMBER
ADD A4,COPY ; ADD BACK THE HIGH ORDER WORD
TLZE A5,(1B0) ; [E044] CARRY INTO TOP BIT OF LOW WORD ?
ADDI A4,1 ; [E044] YES - ADD IN TO HIGH WORD
C6D: SOJA A3,LLOOP3 ; AND KEEP GOING
C6A: DIVI A4,^D10 ; RESTORE THE ORIGINAL NUMBER
MOVE A5,COPY ; RESTORE LOW-ORDER WORD
SKIPE MARKER ; IF DECIMAL POINT EVER SCANNED
JRST C6C ; DON'T WORRY
;
; OTHERWISE NUMBER IS TOO LARGE - SAY SO
;
CAIL A1,"5" ;
ADDI A5,1 ; ROUND IN IGNORED DIGIT
MOVE A1,[..IMM,,^D98]
PUSHJ SP,.FAILED
AOS EXTRA ; ALLOW FOR DIGIT JUST IGNORED
C6C: AOS CC
ILDB A1,P ; NEXT CHAR
MOVE A2,CTABLE(A1) ; GET ITS TABLE ENTRY
AOJGE A2,@TABLE5(A2)
SKIPN MARKER ; IF NO DECIMAL POINT SEEN,
AOS EXTRA ; COUNT IGNORED DIGITS
JRST C6C ; AND KEEP IGNORING
C2 ; NUMBER
C8 ; LETTER
TABLE4: C8 ; DELIMITER
C8 ; DELIMITER (FLAGGED)
LLOOP1 ; IGNORABLE CHARACTER
LLOOP1 ; SPACE & TAB
C8B ; NEW-LINE
C8 ; LOWER CASE LETTER
C10 ; OTHER (E.G. PERIOD, &, @)
C8 ; SINGLE QUOTE
C8B: PUSHJ SP,NCHECK ; INPUT NEXT LINE
JRST C1 ; -END OF BUFFER IN MID LINE, CONTINUE
; NORMAL END OF NUMBER
C8: SKIPE MARKER ; IF A DECIMAL POINT WAS EVER SCANNED
JRST C18 ; THEN THE NUMBER IS DOUBLE-FLOATING
C8A: TLNE A5,777777 ; IF LEFT HALF OF VALUE IS NON ZERO
JRST C9 ; THEN NUMBER IS NOT INTEGER-IMMEDIATE
; THE CONSTANT IS AN INTEGER-IMMEDIATE
MOVE A3,A5 ; MOVE CONSTANT TO A3 FOR OUTPUT
HRLI A3,$EXP+$I+$SIM+$DEC+$IMM; LEXEME TYPE FIELDS
JRST LET9 ; EXIT LSCAN
; THE CONSTANT IS AN INTEGER FULLWORD
C9: PUSHJ SP,CON1Z ; SEARCH CONSTANTS TABLE
HRLI A3,$EXP+$I+$SIM+$DEC+$CT; LEXEME LEFT HALF
JRST LET9 ; EXIT LSCAN
; A SPECIAL CHARACTER WAS SCANNED
C10: HLRZ A2,CTABLE(A1) ; GET LEFT HALF OF CHAR'S TABLE ENTRY
JRST @TABLE6(A2) ; JUMP THROUGH TABLE 6
TABLE6: C19 ; ILLEGAL CHARACTER
C22 ; [E044] @ &
C20 ; " $ %
C16 ; .
; A DOT WAS SCANNED
C16: SKIPE MARKER ; IF MARKER NOT ZERO THEN THERE ARE
JRST C17 ; TWO DECIMAL POINTS IN THIS CONSTANT
MOVEM A3,MARKER ; SET DECIMAL POINT MARKER
JRST LLOOP1 ; RETURN TO LOOP
; CONSTANT CONTAINS TWO DECIMAL POINTS
C17: PUSHJ SP,BADNAC ; PRINT ERROR MSG, USE ATNAC
; CONVERT CONSTANT TO DOUBLE-FLOATING
C18: SUB A3,MARKER ; FIX SCALING CONSTANT
JRST C13 ; HALVES AND CONTINUE
; AN ILLEGAL CHARACTER WAS SCANNED
C19: PUSHJ SP,BADNAC ; PRINT ERROR MESSAGE, USE ATNAC
JRST C8 ; CONTINUE
C20: PUSHJ SP,BADCON ; PRINT ERROR MSG
JRST C8 ; CONTINUE
C6 ; NUMBER
C30 ; LETTER
TABLE5: C28 ; DELIMITER
C28 ; DELIMITER (FLAGGED)
LLOOP3 ; IGNORABLE
EDIT (215); CHANGE AT TABLE5 + 3 CLRH 17-JULY-79
LLOOP3 ;[215] SPACE AND TAB
;[215] C28 ; SPACE & TAB
C36 ; NEW-LINE
C30 ; LOWER CASE LETTER
C21 ; OTHER
C28 ; SINGLE QUOTE
; A SPECIAL CHAR WAS SCANNED
C21: HLRZ A2,CTABLE(A1) ; GET LEFT HALF OF CHAR'S TABLE ENTRY
JRST @TABLE7(A2) ; JUMP THROUGH TABLE 7
TABLE7: C27 ; ILLEGAL CHARACTER
C22 ; @ &
C30 ; " $ %
C25 ; .
; A @ OR & WAS SCANNED
C22: JSP A6,IGST ; GET NEXT CHAR
CAIE A1,.AAAAA ; IF IT IS A @
CAIN A1,.AMPER ; OR A &
AOSA FORMAT ; [E044] THEN REMEMBER IT WAS
JRST C24 ; [E044] ELSE CARRY ON
JSP A6,IGST ;[215] IGNORE IT
;[215] JSP A6,GETCHR ; [E044] IGNORE IT
;**** JRST C24 ; [E044] FALL THROUGH TO GET EXPONENT
; PRODUCE LEXEME FOR DOUBLE PRECISION CONSTANT
C24: PUSHJ SP,EXPONT ; SCAN THE EXPONENT
C13: PUSHJ SP,FCMML ; INCLUDE CORRECT POWER OF TEN
SKIPE FORMAT ; [E044] IS THIS EXPLICIT DOUBLE PRECISION ?
JRST C13A ; [E044] YES - MUST MAKE DOUBLE-WORD CONSTANT
JUMPE A5,C13B ; [E044] NO - CAN WE USE A SINGLE WORD ?
TLO A5,(1B0) ; [E044] NO - SET SIGN BIT OF SECOND WORD TO 1
C13A: PUSHJ SP,CON2 ; PUT CONSTANT IN CONSTANT TABLE
HRLI A3,$EXP+$LR+$SIM+$DEC+$CT; LEXEME LEFT HALF
JRST LET9 ; EXIT LSCAN
C13B: TRNN A4,-1 ; [E044] CAN THIS BE AN IMMEDIATE CONSTANT ?
JRST C13C ; [E044] YES - GO FORM THE LEXEME
PUSHJ SP,CON1 ; [E044] NO - ENTER IT IN THE TABLE
HRLI A3,$EXP+$R+$SIM+$DEC+$CT; [E044] FORM LEXEME
JRST LET9 ; [E044] EXIT FROM LSCAN
C13C: HLRZ A3,A4 ; [E044] IMMEDIATE REAL CONSTANT - GET VALUE
HRLI A3,$EXP+$R+$SIM+$DEC+$IMM; [E044] SET LEXEME BITS IN L.H.
JRST LET9 ; [E044] AND EXIT FROM LSCAN
; A DOT WAS SCANNED
C25: SKIPE MARKER ; IF MARKER NOT ZERO THEN THERE ARE
JRST C26 ; TWO DECIMAL POINTS IN THIS CONSTANT
MOVEM A3,MARKER ; SET DECIMAL POINT MARKER
JRST LLOOP3 ; RETURN TO LOOP
; EITHER A LETTER OR TWO DECIMAL POINTS APPEARED IN CONSTANT
C26: PUSHJ SP,BADNAC ; PRINT ERROR MSG, USE ATNAC
JSP A6,IGST ; GET NEXT CHAR
CAME A1,.AAAAA ; IF IT IS A @
CAMN A1,.AMPER ; OR A &
JRST C22 ; THEN CONTINUE AS DOUBLE-PRECISION
JRST C28 ; ELSE CONVERT TO SINGLE-PRECISION
; A STRANGE CHAR APPEARED IN CONSTANT
C27: PUSHJ SP,BADNAC ; PRINT ERROR MSG, USE ATNAC
JRST C28 ; CONTINUE
C30: PUSHJ SP,BADCON ; PRINT ERROR MESSAGE
C28: SKIPE MARKER ; IF A DECIMAL POINT WAS EVER SCANNED
JRST C29 ; THEN JUMP OVER THIS PART
; INTEGER TOO LARGE FOR INTEGER
MOVE A1,[ ; LOAD PARAMETER FOR MESSAGE
XWD ..IMM,^D98] ; MSG 98
PUSHJ SP,.FAILED ; "INTEGER CONST CONVERTED TO TYPE REAL"
TDZA A3,A3 ; EXPONENT OF ZERO
C29: SUB A3,MARKER ; FIX SCALING
ADD A3,EXTRA ; ALLOW FOR SKIPPED DIGITS
JRST C13 ; CONTINUE AS DOUBLE PRECISION
BADCON: FAIL (90,FRIED,IMM,INVALID CONSTANT)
POPJ SP, ; EXIT BADCON
; SUBROUTINE TO SCAN POWER OF TEN
EXPONT: SKIPE MARKER ; IF A DECIMAL POINT HAS OCCURRED
SUBM A3,MARKER ; THEN SET CORRECT POWER OF TEN
SETZB A3,SIGN ; CLEAR EXPONENT AND SIGN
CAIN A1,.MINUS ; IF IT IS A MINUS SIGN
JRST C34 ; THEN SET INDICATOR
CAIN A1,.PLUS ; IF IT IS A PLUS SIGN
JRST C35 ; THEN READ NEXT CHAR
LLOOP4: HRRZ A2,CTABLE(A1) ; GET CHAR'S TABLE ENTRY
CAIE A2,-2 ; IF IT IS NOT A DIGIT
JRST C31 ; THEN JUMP OUT OF LOOP
IMULI A3,^D10 ; MULT PREVIOUS RESULT BY TEN
ADDI A3,-.N0(A1) ; ADD IN CURRENT DIGIT
CAILE A3,^D300 ; IF NUMBER IS EXCEEDINGLY LARGE
JRST C33 ; THEN STOP THIS NONSENSE
JSP A6,IGST ; GET NEXT CHAR
JRST LLOOP4 ; LOOP
C31: CAIN A2,6 ; IF IT IS AN ILLEGAL CHAR
JRST C33 ; THEN PRINT ERROR
SKIPE SIGN ; IF SIGN IS NEGATIVE
MOVN A3,A3 ; THEN NEGATE EXPONENT
ADD A3,EXTRA ; ALLOW FOR ANY IGNORED DIGITS
SETZM EXTRA ;
ADD A3,MARKER ; ADD IN DECIMAL POINT CORRECTION
POPJ SP, ; EXIT EXPONT
C33: PUSHJ SP,BADNAC ; PRINT MSG, USE ATNAC
C4: SETZ A3, ; USE A ZERO EXPONENT
POPJ SP, ; EXIT EXPONT
C34: SETOM SIGN ; SET SIGN MINUS
C35: JSP A6,IGST ; GET NEXT CHAR
JRST LLOOP4 ; RETURN TO LOOP
C36: PUSHJ SP,NCHECK ; INPUT NEXT LINE
JRST C5 ; -END OF BUFFER IN MID LINE, CONTINUE
JRST C28 ; TRUE END OF LINE
; UNDERFLOW HANDLERS
FPU1: TLNN A2,000100 ; IF NOT UNDERFLOW
JRST (A2) ; THEN RETURN
TLZ A2,440100 ; CLEAR FLAGS
MOVEM A2,OVA
LDB A2,[POINT 4,-2(A2),12] ; GET RELEVANT ACC. NUMBER
SETZM (A2) ; AND ZERO IT
JRST 2,@OVA ; AND RETURN
FPU2: TLNN A2,000100 ; IF NOT UNDERFLOW
JRST (A2) ; THEN RETURN
TLZ A2,440100 ; CLEAR FLAGS
MOVEM A2,OVA
LDB A2,[POINT 4,-2(A2),12] ; GET RELEVANT ACC. NUMBER
SETZM (A2) ; AND ZERO IT
SETZM 1(A2) ; ALSO ZERO NEXT ACC.
JRST 2,@OVA ; AND RETURN
FPUS: TLNN A2,000100 ; IF NOT UNDERFLOW
JRST (A2) ; THEN RETURN
TLZ A2,440100 ; CLEAR FLAGS
MOVEM A2,OVA
LDB A2,[POINT 4,-2(A2),12] ; GET RELEVANT ACC. NUMBER
MOVEM A2,OVB ; AND SAVE IT
MOVEM A3,OVC ; AND A3
MOVE A2,(A2) ; GET VALUE OF ACC.
HLRE A3,A2 ; GET EXPONENT, EXTENDING SIGN
ASH A3,-11
TSCE A3,A3 ; IF NEGATIVE, COMPLEMENT EXPONENT
TLOA A2,777000 ; NEGATIVE - SET ALL ONES
TLZ A2,777000 ; POSITIVE - SET ALL ZEROS
CAMGE A3,[346,,346] ; WILL ALL OF MANTISSA DISAPPEAR?
TDZA A2,A2 ; YES - SAVE LONG SHIFT
ASH A2,400000(A3) ; DENORMALIZE MANTISSA TO SUIT EXPONENT
MOVEM A2,@OVB ; RESTORE RELEVANT ACC.
MOVE A3,OVC ; RESTORE A3
JRST 2,@OVA ; AND RETURN
RELOC
LSBUFP: BLOCK 2 ; NAME BUFFER POINTER
LSBUF1: BLOCK 14 ; NAME BUFFER
LSBUF2: BLOCK 14 ; NAME BUFFER
LSBUF3: BLOCK 14 ; NAME BUFFER
RWSL: BLOCK 1 ; ADDR OF RESERVED WORD TABLE SUBLIST
BLEX: BLOCK 1 ; BUFFERED LEXEME
CC: BLOCK 1 ; POSITION COUNT
BTI: BLOCK 1 ; BEGIN-TABLE INDEX
BTAB: BLOCK 50 ; BEGIN-TABLE
EXPSAV: BLOCK 1 ; TO SAVE THE EXPONENT
DECEXP: BLOCK 1 ; TO STORE THE DECIMAL EXPONENT
RELOC
LSBUFT: XWD A6,LSBUF1 ; NAME BUFFER LIST
XWD A6,LSBUF2
XWD A6,LSBUF3
0
MSKTBL: 000000000000
000000000000
000000000377
000000077777
000000000000
000017777777
000000000000
003777777777
SUBTTL POWERS OF TEN TABLE
;
;POWER OF TEN TABLE IN DOUBLE PRECISION INTEGER FORMAT,
; EACH WITH 35 BITS OF FRACTION (SIGNS ARE EXLCLUDED), THE
; BINARY POINT IS BETWEEN BITS 0 AND 1 OF THE HIGH ORDER
; WORD, THE EXPONENT (EXCESS 200) FOR THE 70 BIT FRACTION
; IS STORED IN THE SHORT TABLE "EXPTEN"
;
DEFINE .TAB. (A)<
REPEAT 0,<
NUMBER 732,357347511265,056017357445
NUMBER 736,225520615661,074611525567
NUMBER 741,273044761235,213754053125
NUMBER 744,351656155504,356747065752
NUMBER 750,222114704413,025260341562
NUMBER 753,266540065515,332534432117
NUMBER 756,344270103041,121263540543
NUMBER 762,216563051724,322660234335
NUMBER 765,262317664312,007434303425
NUMBER 770,337003641374,211343364332
NUMBER 774,213302304735,325716130610
NUMBER 777,256162766125,113301556752
>
NUMBER 002,331617563552,236162112545
NUMBER 006,210071650242,242707256537
NUMBER 011,252110222313,113471132267
NUMBER 014,324532266776,036407360745
NUMBER 020,204730362276,323044526457
NUMBER 023,246116456756,207655654173
NUMBER 026,317542172552,051631227231
NUMBER 032,201635314542,132077636440
NUMBER 035,242204577672,360517606150
NUMBER 040,312645737651,254643547602
NUMBER 043,375417327624,030014501542
NUMBER 047,236351506674,217007711035
NUMBER 052,306044030453,262611673245
NUMBER 055,367455036566,237354252116
NUMBER 061,232574123152,043523552261
NUMBER 064,301333150004,254450504735
NUMBER 067,361622002005,327562626124
NUMBER 073,227073201203,246647575664
NUMBER 076,274712041444,220421535242
NUMBER 101,354074451755,264526064512
NUMBER 105,223445672164,220725640716
NUMBER 110,270357250621,265113211102
NUMBER 113,346453122766,042336053323
NUMBER 117,220072763671,325412633103
NUMBER 122,264111560650,112715401724
NUMBER 125,341134115022,135500702312
NUMBER 131,214571460113,172410431376
NUMBER 134,257727774136,131112537675
NUMBER 137,333715773165,357335267655
NUMBER 143,211340575011,265512262714
NUMBER 146,253630734214,043034737477
NUMBER 151,326577123257,053644127417
NUMBER 155,206157364055,173306466551
NUMBER 160,247613261070,332170204303
NUMBER 163,321556135307,020626245364
NUMBER 167,203044672274,152375747331
NUMBER 172,243656050753,205075341217
NUMBER 175,314631463146,146314631463
A:
NUMBER 201,200000000000,0
NUMBER 204,240000000000,0
NUMBER 207,310000000000,0
NUMBER 212,372000000000,0
NUMBER 216,234200000000,0
NUMBER 221,303240000000,0
NUMBER 224,364110000000,0
NUMBER 230,230455000000,0
NUMBER 233,276570200000,0
NUMBER 236,356326240000,0
NUMBER 242,225005744000,0
NUMBER 245,272207335000,0
NUMBER 250,350651224200,0
NUMBER 254,221411634520,0
NUMBER 257,265714203644,0
NUMBER 262,343277244615,0
NUMBER 266,216067446770,040000000000
NUMBER 271,261505360566,050000000000
NUMBER 274,336026654723,262000000000
NUMBER 300,212616214044,117200000000
NUMBER 303,255361657055,143040000000
NUMBER 306,330656232670,273650000000
NUMBER 312,207414740623,165311000000
NUMBER 315,251320130770,122573200000
NUMBER 320,323604157166,147332040000
NUMBER 324,204262505412,000510224000
NUMBER 327,245337226714,200632271000
NUMBER 332,316627074477,241000747200
NUMBER 336,201176345707,304500460420
NUMBER 341,241436037271,265620574524
NUMBER 344,311745447150,043164733651
NUMBER 347,374336761002,054022122623
NUMBER 353,235613266501,133413263573
NUMBER 356,305156144221,262316140531
NUMBER 361,366411575266,037001570657
NUMBER 365,232046056261,323301053415
NUMBER 370,300457471736,110161266320
NUMBER 373,360573410325,332215544004
NUMBER 377,226355145205,250330436402
REPEAT 0,<
NUMBER 402,274050376447,022416546102
NUMBER 405,353062476160,327122277522
NUMBER 411,222737506706,206363367623
NUMBER 414,267527430470,050060265567
NUMBER 417,345455336606,062074343124
NUMBER 423,217374313163,337245615764
NUMBER 426,263273376020,327117161361
NUMBER 431,340152275425,014743015655
NUMBER 435,214102366355,050055710514
NUMBER 440,257123064050,162071272637
NUMBER 443,332747701062,216507551406
NUMBER 447,210660730537,231114641743
NUMBER 452,253035116667,177340012333
>
>
DEFINE NUMBER(A,B,C)
<EXP B,C>
TENTAB: .TAB. TENS
XX==<TENS-TENTAB>/2 ; CALCULATE THE NUMBER OF TABLE ENTRIES BEFORE "TENS"
XX==XX-XX/4*4 ; CALC XX=XX MOD 4
BINR1==<BINR2==<BINR3==0>> ; INIT THE BINARY
DEFINE NUMBER (A,B,C)<
IFE XX-1,< BYTE (9) BINR1,BINR2,BINR3,<A>
BINR1==<BINR2==<BINR3==0>> >
IFE XX-2,<BINR3==A>
IFE XX-3,<BINR2==A>
IFE XX,<BINR1==A
XX==4>
XX==XX-1>
POINT ^D9,EXPTEN-1(A6),^D17
POINT ^D9,EXPTEN-1(A6),^D26
POINT ^D9,EXPTEN-1(A6),^D35
BYTAB: POINT ^D9,EXPTEN(A6),^D8
POINT ^D9,EXPTEN(A6),^D17
POINT ^D9,EXPTEN(A6),^D26
POINT ^D9,EXPTEN(A6),^D35
.TAB. EXPTEN
IFN BINR1!BINR2!BINR3,< BYTE (9) BINR1,BINR2,BINR3,0>
SUBTTL FLOATING CONSTANT MAKER
;
; BASED ON FORTRAN ROUTINE FCMML
; TO CONVERT A DOUBLE-LENGTH INTEGER CONSTANT TO A
; DOUBLE PRECISION CONSTANT FOR KA OR KI PROCESSORS
;
FCMML: PUSH SP,A7 ; SAVE A7
MOVEM A3,DECEXP ; HIGH ORDER WORD
MOVE A6,A5 ; LOW ORDER WORD
JFFO A4,FCMML0 ; DOES HIGH WORD HAVE ONES ?
EXCH A4,A6 ; NO, SWAP HIGH AND LOW
MOVEI A2,243 ; SET BIN POINT BETWEEN HALVES
JFFO A4,FCMML0+1 ; ANY ONES NOW ?
JRST FCFML ; NUMBER IS ZERO
FCMML0: MOVEI A2,306 ; MAXIMUM EXPONENT
EXCH A5,A6 ; SWAP LOW WORD AND SHIFT COUNT
ASHC A4,-1(A6) ; LEFT NORMALISE
SUBI A2,-1(A6) ; ADJUST EXPONENT ACCORDINGLY
FCMML2: MOVM A1,A3 ; GET MAGNITUDE OF DECIMAL EXP
CAILE A1,^D100 ; TOO BIG ?
JRST FCMOVR ; YES, OVERFLOW ERROR
JUMPE A1,FCMML6 ; EXP=0
FCMML3: SETZM EXPSAV
CAIG A1,^D38 ; EXPONENT GT 38
JRST FCMML4 ; NO
SUBI A1,^D38 ; REDUCE IT BY 38
MOVEM A1,EXPSAV ; SAVE THE DIFFERENCE
MOVEI A1,^D38 ; SET FOR FIRST * OR /
FCMML4: LSH A1,1 ;
SKIPGE DECEXP ; IS EXPONENT -VE ?
MOVNS A1 ; ADJUST TABLE INDEX
;
; START LONG PRECISION INTEGER MULTIPLY
;
MUL A5,TENS(A1) ; A5 := (A5*H)*H
MOVE A3,A5 ; SAVE RESULT
MOVE A5,A4 ; GET HIGH FRACTION
MUL A5,TENS+1(A1) ; AND MULTIPLY BY LOW TEN
ADD A3,A5 ; ADD HIGH PARTS OF CROSS PRODUCTS
MUL A4,TENS(A1) ; FORM PRODUCT OF THE HIGH PARTS
TLZE A3,(1B0) ; PROPAGATE A CARRY IF REQ'D
ADDI A4,1 ;
ADD A5,A3
TLZE A5,(1B0)
ADDI A4,1
TLNE A4,(1B1) ; IS RESULT NORMALISED ?
JRST .+3 ; YES
ASHC A4,1 ; NO - LEFT SHIFT ONE
SUBI A2,1 ; AND ADJUST EXPONENT
FCMML5: MOVE A6,A1 ; MOVE DECIMAL EXPONENT TO DOUBLE AC
ASH A6,-1 ; RESTORE SIGNED EXPONENT
IDIVI A6,4 ; BYTAB PACKED 4 ENTRIES PER WORD
LDB A6,BYTAB(A7) ; GET BINARY EXPONENT POWER 10
ADD A2,A6 ; ADD IT INTO FINAL BINARY EXPONENT
SUBI A2,200 ; GET RID OF EXCESS 200
SKIPE A1,EXPSAV ;
JRST FCMML3
; We get here with (A4,A5) holding a double precision
; binary fraction (normalized to bit 1 of A4), and A2
; holding the binary exponent.
FCMML6: ADDI A5,200 ; [E056] ROUND LOW ORDER WORD
TLZE A5,(1B0) ; [E056] IF NO CARRY NEEDED
AOSL A4 ; [E056] OR A4 WAS NOT 377777,,777777
JRST FCMML7 ; [E056] THEN CARRY ON
; Adding in a half (to the lowest bit position) caused carry. This can
; only happen if all bits were one, in which case all significant bits
; are now zero.
ADDI A2,1 ; [E056] INCREASE EXPONENT BY ONE, AND SET
MOVSI A4,(1B1) ; [E056] (A4,A5) TO 200000000000000000....
FCMML7: TRNE A2,777400 ; [E056] IS EXPONENT IN RANGE 000-377 ?
JRST FCMOV1 ; [E056] NO - OVERFLOW. SET TO MIN/MAX
ASHC A4,-^D8 ; [E056] YES - MAKE ROOM FOR EXPONENT
DPB A2,[POINT ^D9,A4,^D8] ; [E056] AND INSERT IT
FCFML: POP SP,A7 ; RESTORE A7
POPJ SP,
FCMOVR: MOVE A2,DECEXP
FCMOV1: SKIPGE A2
TDZA A4,A4 ; YES, ZERO ON UNDERFLOW
HRLOI A4,377777 ; NO MAX NUMBER ON OVERFLOW
MOVE A5,A4 ; SAVE PATCHED RESULT AS ANSWER
JRST FCFML
SUBTTL CONSTANT TABLE HANDLING
; CONSTANTS TABLE
;
; THE SIZE OF THE CONSTANTS TABLE ALWAYS INCREASES DURING A COMPILATION.
; NEW ENTRIES ARE PLACED AT THE END, AND ARE ALSO LINKED INTO ONE OF
; THREE CHAINS ACCORDING TO WHETHER IT IS FOR A 1-WORD CONSTANT,
; A 2-WORD CONSTANT, OR A STRING. THEREFORE EACH ENTRY HAS A LINK.
; THIS LINK IS ALWAYS IN THE RIGHT HALF OF THE 1ST WORD OF THE ENTRY.
; THE VALUE OF THE LINK IS EQUAL TO A NUMBER WHICH IF SUBTRACTED
; FROM THE ADDRESS OF THE ENTRY WILL YIELD THE ADDRESS OF THE NEXT
; ENTRY OF THE CHAIN. EACH CHAIN TERMINATES IN A FAKE ENTRY WHOSE
; 1ST DATA WORD IS THE 1ST WORD OF THE CONSTANTS TABLE. BECAUSE
; OF THIS, THE CONSTANTS TABLE CAN BE SEARCHED IN A 3-INSTRUCTION LOOP.
; THE FORMATS OF THE DIFFERENT TYPES OF ENTRIES ARE:
;
;
;
; 1-WORD CONSTANTS 2-WORD CONSTANTS STRINGS
;
; !--------------------! !--------------------! !--------------------!
; ! ! ! ! ! !
; WORD-0 ! LEFT: BACKCHAIN ! ! LEFT: BACKCHAIN 1 ! ! LEFT: BACKCHAIN 1 !
; ! RIGHT: LINK ! ! RIGHT: LINK ! ! RIGHT: LINK !
; ! ! ! ! ! !
; !--------------------! !--------------------! !--------------------!
; ! ! ! ! ! !
; WORD-1 ! VALUE ! ! LEFT: (NOT USED) ! ! LEFT: (NOT USED) !
; ! ! ! RIGHT: BACKCHAIN 2 ! ! RIGHT: BACKCHAIN 2 !
; ! ! ! ! ! !
; !--------------------! !--------------------! !--------------------!
; ! ! ! !
; WORD-2 ! 1ST WORD OF VALUE ! ! LEFT: (NOT USED) !
; ! ! ! RIGHT: # OF BYTES !
; ! ! ! !
; !--------------------! !--------------------!
; ! ! ! !
; WORD-3 ! 2ND WORD OF VALUE ! ! 1ST WORD OF STRING !
; ! ! ! !
; ! ! ! !
; !--------------------! !--------------------!
; ! !
;
; ! !
; !--------------------!
; ! !
; WORD-N+2 ! NTH WORD OF STRING !
; ! !
; ! !
; !--------------------!
; ENTER 1-WORD CONSTANT IN CONSTANTS TABLE
CON1Z: MOVE A4,A5 ; LOAD INTO A4, MOSTLY FOR DIGITS
CON1: MOVEM A4,@CONTAB ; SAVE VALUE IN BEGINNING OF CONSTANTS TABLE
SKIPA A3,LASTC1 ; LOAD LAST 1-WORD CONSTANT, AND SKIP
CON1A: SUB A3,(A3) ; STEP BACK TO PREVIOUS ENTRY
CAME A4,1(A3) ; DO VALUES MATCH?
JRST CON1A ; -NO, LOOP
MOVEI A6,1(A3) ; ADDR OF NEXT WORD
CAME A6,CONTAB ; WAS WORD REALLY IN CONSTANTS TABLE?
JRST CON1B ; YES, STOP SEARCH
MOVEI A6,2 ; NEW ENTRY IS 2 WORDS LONG
PUSHJ SP,GETCTS ; GET SOME SPACE IN CONSTANTS TABLE
MOVEI A6,(A3) ; COPY ADDR OF NEW ENTRY TO A6
SUB A6,LASTC1 ; SUBTRACT FROM LAST 1-WORD ENTRY ADDR
MOVEM A6,(A3) ; SAVE IN NEW ENTRY AS A LINK
MOVEM A4,1(A3) ; PUT VALUE IN ENTRY
MOVEM A3,LASTC1 ; SET NEW LASTC1
CON1B: SUB A3,CONTAB ; CONV FROM ABS TO REL ADDRESS
POPJ SP, ; EXIT CON1
; GET SPACE IN CONSTANTS TABLE
GETCTS: HRRZ A3,NACTE ; ADDR OF NEW ENTRY
ADDB A6,NACTE ; ADD LENGTH OF NEW ENTRY
CAML A6,CONEND ; DOES IT OVERFLOW THE TABLE?
JRST OVFL2 ; -YES, MOVE THE TABLES, EXIT GETCTS
POPJ SP, ; EXIT GETCTS
; ENTER 2-WORD CONSTANT IN CONSTANTS TABLE
CON2: MOVEM A4,@CONTAB ; SAVE VALUE IN BEGINNING OF CONSTANT TABLE
SKIPA A3,LASTC2 ; LOAD ADDR OF LAST 2-WORD CONSTANT AND SKIP
CON2A: SUB A3,(A3) ; STEP BACK TO PREVIOUS ENTRY
CAME A4,2(A3) ; DO VALUES MATCH?
JRST CON2A ; -NO, LOOP
MOVEI A6,2(A3) ; STEP TO NEXT WORD
CAMN A6,CONTAB ; WAS WORD REALLY IN CONSTANTS TABLE?
JRST CON2B ; -NO, ENTER IT
CAME A5,3(A3) ; DO 2ND WORDS MATCH?
JRST CON2A ; -NO, LOOP
JRST CON1B ; EXIT CON2
CON2B: MOVEI A6,4 ; NEW ENTRY IS 4 WORDS LONG
PUSHJ SP,GETCTS ; GET SPACE FOR IT
MOVEI A6,(A3) ; COPY ADDR TO A6
SUB A6,LASTC2 ; SUBTRACT FROM LAST 2-WORD ENTRY ADDR
MOVEM A6,(A3) ; SAVE IN NEW ENTRY AS A LINK
MOVEM A4,2(A3) ; PUT 1ST WORD IN ENTRY
MOVEM A5,3(A3) ; PUT 2ND WORD IN ENTRY
SETZM 1(A3) ; CLEAR BACK-CHAINS
MOVEM A3,LASTC2 ; SET NEW LASTC2
JRST CON1B
RELOC
MARKER: BLOCK 1 ; DECIMAL POINT MARKER
COPY: BLOCK 1 ; TEMPORARY COPY OF VALUE OF CONSTANT
EXTRA: BLOCK 1 ; NUMBER OF DIGITS IGNORED
SIGN: BLOCK 1 ; SIGN OF THE EXPONENT
FORMAT: BLOCK 1 ; [E044] SINGLE/DOUBLE PRECISION FLAG
LASTC1: BLOCK 1 ; LAST 1-WORD CONSTANT IN CONSTANT TABLE
LASTC2: BLOCK 1 ; LAST 2-WORD CONSTANT IN CONSTANT TABLE
CONEND: BLOCK 1 ; END OF CONSTANT TABLE
RELOC
; ***** A T N A C *****
;
; ADVANCE TO NEXT NON-ALPHAMERIC CHARACTER
;
BADNAC: PUSHJ SP,BADCON ; BADCON/ATNAC
JRST ATNAC
ATNAC2: CAIE A1,.DOT ; IF IT IS NOT A DOT
POPJ SP, ; THEN EXIT ATNAC
ATNAC: ILDB A1,P ; LOAD THE NEXT CHAR
AOS CC ; STEP POSITION COUNT
MOVE A2,CTABLE(A1) ; GET ITS TABLE ENTRY
JRST @TABLE9(A2) ; JUMP THROUGH TABLE 9
ATNAC ; NUMBER
ATNAC ; LETTER
TABLE9: ATNAC1 ; DELIMITER
ATNAC1 ; DELIMITER (FLAGGED)
ATNAC ; IGNORABLE CHAR
ATNAC1 ; SPACE & TAB
ATNAC3 ; NEW-LINE CHAR
ATNAC ; LOWER-CASE
ATNAC2 ; OTHER CHAR @ % $ " & . ILLEGALS
ATNAC ; SINGLE QUOTE
ATNAC3: PUSHJ SP,NCHECK ; INPUT NEXT LINE
JRST ATNAC+2 ; -END OF BUFFER IN MID LINE, CONTINUE
ATNAC1: POPJ SP, ; EXIT ATNAC
; ***** OCTAL CONSTANTS *****
OCTAL: SETZB A4,A5 ; CLEAR A4,A5
; CHARACTER READING LOOP
OCTALL: ILDB A1,P ; GET A CHAR
AOS CC ; STEP POSITION COUNT
CAIL A1,.N0 ; IF IT IS BELOW 0
CAILE A1,.N7 ; OR ABOVE 7
JRST OCTALD ; THEN CONSTANT IS FINISHED
LSHC A4,3 ; MULTIPLY BY 8
JUMPN A4,OCTILL ; TEST FOR OVERFLOW
IORI A5,-.N0(A1) ; ADD IN CURRENT DIGIT
JRST OCTALL ; LOOP
OCTALD: MOVE A2,CTABLE(A1) ; GET CHARS TABLE ENTRY
JRST @TABLE8(A2) ; JUMP THROUGH TABLE 8
OCTILL ; NUMBER
OCTOUT ; LETTER
TABLE8: OCTOUT ; DELIM
OCTOUT ; DELIM (FLAGGED)
OCTALL ; IGNORABLE
OCTALL ; SPACE & TAB
OCTNL ; NEW-LINE
OCTOUT ; LOWER CASE
OCTIL1 ; OTHER
OCTOUT ; SINGLE QUOTE
; NEW-LINE CHARACTER SCANNED
OCTNL: PUSHJ SP,NCHECK ; INPUT NEXT LINE
JRST OCTALL+2 ; -END OF BUFFER IN MID LINE, CONTINUE
; END OF OCTAL CONSTANT
OCTOUT: TLNE A5,777777 ; IF LEFT HALF NON-ZERO
JRST OCTFUL ; THEN THE CONSTANT IS A FULLWORD
SKIPA A3,A5 ; MOVE THE CONSTANT TO A3
FFALSE: MOVEI A3,0 ; 'FALSE'
; CONSTANT IS A HALFWORD
FALSE1: HRLI A3,$EXP+$B+$SIM+$DEC+$IMM; LEXEME
JRST LET9 ; EXIT LSCAN
; "TRUE" SCANNED
FTRUE: HRREI A5,-1 ; "TRUE" IS A WORD OF ALL ONES
; CONSTANT IS A FULL WORD
OCTFUL: PUSHJ SP,CON1Z ; PUT IN CONSTANT TABLE
HRLI A3,$EXP+$B+$REG+$DEC+$CT; LEXEME
JRST LET9 ; EXIT LSCAN
; INVALID FORMAT FOR OCTAL CONSTANT
OCTILL: PUSHJ SP,BADNAC ; PRINT ERROR MSG, USE ATNAC
JRST OCTOUT ; CONTINUE
OCTIL1: PUSHJ SP,BADCON ; PRINT ERROR MESSAGE
JRST OCTOUT ; CONTINUE
; ***** SYMBOL CONSTANTS *****
;
;
;
DOLLAR: JSP A6,STCHAR ; GET NEXT CHAR
MOVE A3,A1 ; THIS WILL BE THE TERMINATING CHAR
MOVEI A5,0
MOVEI A4,6 ; READ 6 CHARS
SCLOOP: JSP A6,STCHAR ; READ ANOTHER CHAR
CAIN A1,(A3) ; IF IT IS THE END CHAR
JRST SCDONE ; THEN THE CONSTANT IS DONE
LSH A5,7 ; SHIFT THE CONSTANT OVER 7
IORI A5,(A1) ; INCLUDE THE CURRENT CHAR
SOJG A4,SCLOOP ; LOOP
PUSHJ SP,BADNAC ; PRINT ERROR MSG, USE ATNAC
JRST C8A ; CONTINUE AS IF AN INTEGER
SCDONE: IBP P ; STEP TO NEXT CHAR
AOS CC
JRST C8A ; CONTINUE AS AN INTEGER
; ***** STRINGS *****
;
;
;
; SET UP
STRING: MOVEI A6,3 ; GET 3 WORDS FROM
PUSHJ SP,GETCTS ; THE CONSTANTS TABLE
MOVE A6,A3 ; COPY 1ST WORD ADDRESS TO A6
PUSH SP,LASTST ; SAVE ADDRESS OF STRING CHAIN
SUB A6,LASTST ; COMPUTE DISTANCE BACK TO LAST STRING
MOVEM A3,LASTST ; SET NEW POINTER TO LAST STRING
HRRZM A6,(A3) ; USE AS THE LINK
SETZM 1(A3) ; CLEAR THE BACK CHAIN POINTERS
ADDI A3,2 ; STEP FORWARD 2 WORDS
HRRZM A3,CCOUNT ; SET POINTER TO CHAR COUNT WORD
HRLI A3,000700 ; FORM BUFFER BYTE POINTER
MOVEM A3,STRPNT ; SET POINTER
SETZB A5,BCOUNT ; CLEAR CHARACTER AND BRACKET COUNTS
JRST STR6 ; CONTINUE
; CHARACTER READING LOOP
STR1: JSP A6,STCHAR ; READ A CHARACTER
CAIE A1,.DQUOT ; IF IT IS A "
CAIN A1,.SEMI ; IF IT IS A SEMI-COLON
JRST SPECIAL ; THEN IT IS ILLEGAL
CAIN A1,.CLEFT ; IF IT IS A ^_
JRST CLEFT ; THEN SCAN FOR A LINE-FEED
STR2: IDPB A1,STRPNT ; PUT THE CHAR IN THE CONSTANTS TABLE
ADDI A5,1 ; STEP THE CHARACTER COUNT
SOJG A4,STR1 ; LOOP
; END OF 20-CHARACTER GROUP
STR6: MOVEI A6,4 ; GET 4 MORE WORDS FROM THE
PUSHJ SP,GETCTS ; CONSTANTS TABLE
SUB A3,[ ; SET UP FOR LOOP
XWD 4,4] ; THE 4 WORDS THAT WERE JUST ACQUIRED
SETZM 4(A3) ; MUST BE CLEARED TO ZERO
AOBJN A3,.-1 ; ZERO THE NEXT WORD
MOVEI A4,^D20 ; READ THE NEXT 20 CHARACTERS
JRST STR1 ; LOOP
; A " OR ; WAS SCANNED
SPECIAL:
MOVE A3,A1 ; SAVE THE CHAR
JSP A6,GETCHR ; GET THE NEXT CHARACTER
CAIE A1,(A3) ; IF IT IS NOT A "
JRST STEND ; THEN IT WAS THE END OF THE STRING
JRST STR2 ; AND CONTINUE
; A ^_ WAS ENCOUNTERED
CLEFT: MOVEI A1,.LEFT ; "_"
DPB A1,P ; PUT A _ IN LISTING
JSP A6,STCHAR ; GET THE NEXT CHARACTER
CAIG A1,.FF
CAIGE A1,.LF ; IF LF,FF OR VT
JRST STCHAR ; THEN READ THE NEXT CHAR FOR REAL
JRST STR1 ; OTHERWISE LOOP
; END OF STRING FOUND
STEND: CAIN A3,.SEMI ; IF CHAR IS A SEMICOLON THEN
JRST STERR ; IT IS AN ERROR
HRRZ A4,STRPNT ; GET THE BUFFER STRING POINTER
ADDI A4,1 ; STEP TO NEXT AVAILABLE WORD
MOVEM A4,NACTE ; SAVE IT
MOVEI A4,0 ; LOAD A ZERO
MOVEI A3,4 ; SET COUNT
IDPB A4,STRPNT ; INCLUDE FOUR NULLS
SOJG A3,.-1
MOVE A3,CCOUNT ; GET THE CHARACTER COUNT WORD POINTER
MOVEM A5,@A3 ; SAVE THE CHARACTER COUNT
; SEARCH FOR A DUPLICATE STRING IN CONSTANTS TABLE
SUBI A3,2 ; STEP BACK TO START OF ENTRY
EDIT(040); CALCULATE LENGTH OF NULL STRINGS CORRECTLY
SOSL A5 ; [E040] MAKE DIVISION COME OUT RIGHT
IDIVI A5,5 ; COMPUTE THE NUMBER OF WORDS
MOVN A5,A5 ; NEGATIVE OF LENGTH
HRLZI A5,-2(A5) ; NEGATIVE LENGTH+1 TO LEFT HALF
HRRI A5,2 ; INDEX TO BYTES WORD
HRLI A3,A2 ; LEFT HALF = A2
MOVE A1,A3 ; COPY A3 TO A1
JRST STR4 ; JUMP INTO LOOP
; COMPARE THE 2 STRING ENTRIES
STR3: HRLI A1,A2 ; LEFT HALF = A2
MOVE A2,A5 ; SET COUNT REGISTER
MOVE A4,@A3 ; GET WORD OF ENTRY
CAME A4,@A1 ; IF MISMATCH
JRST STR4 ; THEN QUIT THIS ENTRY
AOBJN A2,.-3 ; LOOP FOR ALL OF STRING
; DUPLICATE FOUND, USE IT INSTEAD
HRRZM A3,NACTE ; RETURN THE NEW ENTRY TO AVAILABLE SPACE
POP SP,LASTST ; RESTORE THE OLD VALUE OF LASTST
MOVE A3,A1 ; -MATCH FOUND, USE IT
JRST STR5 ; CONTINUE
; LOCATE NEXT STRING IN CONSTANTS TABLE
STR4: SUB A1,(A1) ; LOCATE NEXT ENTRY ON CHAIN
MOVEI A1,(A1) ; ZERO LEFT HALF
CAMLE A1,CONTAB ; IF NOT END OF CHAIN
JRST STR3 ; THEN COMPARE THESE ENTRIES
POP SP,A1 ; DISCARD SAVED VALUE OF LASTST
; FORM LEXEME
STR5: SUB A3,CONTAB ; CONVERT TO RELATIVE ADDRESS
HRLI A3,$EXP+$S+$REG+$DEC+$CT; LEXEME
JRST LET9 ; EXIT LSCAN
; INVALID FORMAT FOR STRING CONSTANT
STERR: PUSHJ SP,BADNAC ; PRINT "INVALID CONSTANT" MESSAGE, USE ATNAC
JRST STEND+2 ; COMPLETE CONSTANT AND CONTINUE
RELOC
LASTST: BLOCK 1 ; LAST STRING IN CONSTANTS TABLE
CCOUNT: BLOCK 1 ; CHARACTER COUNT WORD POINTER
BCOUNT: BLOCK 1 ; BRACKET COUNT
STRPNT: BLOCK 1 ; BYTE POINTER INTO BUFFER
RELOC
; THERE ARE THREE ROUTINES THAT WILL READ THE NEXT CHARACTER FROM
; THE SOURCE STREAM. HOWEVER MOST OF THE TIME THE COMPILER DOES NOT
; USE ANY OF THEM BUT INSTEAD HAS THE NECESSARY CODE IN-LINE.
; THESE ROUTINES ARE DESCRIBED:
;
; "GETCHR" IS THE MOST OFTEN USED. "GETCHR" WILL PROCESS IGNORABLE
; CHARACTERS, LOWER CASE LETTERS, TABS, AND CHARACTERS THAT SIGNIFY
; THE END OF THE INPUT BUFFER. "GETCHR" WILL PRESENT ALL OTHER CHARACTERS
; UNCHANGED.
;
; "STCHAR" IS USED TO READ CHARACTERS FOR STRINGS. THE NEWLINE AND
; TAB FUNCTIONS ARE PERFORMED, BUT NEWLINE CHARACTERS ARE ALSO PRESENTED
; AS OUTPUT. IGNORABLE CHARACTERS ARE NOT PRESENTED. LOWER CASE
; LETTERS ARE NOT CONVERTED TO UPPER CASE.
;
; "GETNL" MUST BE USED TO READ CHARACTERS FROM WITHIN THE NEWLINE
; ROUTINE. "GETNL" WILL CHECK FOR END OF INPUT BUFFER, AND READ
; ANOTHER BUFFER IF THIS OCCURRS.
; ** GETCHR **
IGST: MOVEM A6,A6SAV ; SAVE THE LINK
JSP A6,GETCHR ; AND CALL GETCHR
CAIN A2,3 ; IF IT IS A SPACE OR TAB
JRST GETCHR ; THEN TRY AGAIN
JRST @A6SAV ; ELSE EXIT
GETCHR: ILDB A1,P ; GET THE NEXT CHARACTER
AOS CC ; STEP CHARACTER COUNT
MOVE A2,CTABLE(A1) ; GET THE CHARS TABLE ENTRY
XCT TABL11(A2) ; ANALYZE CHARACTER
JRST (A6) ; CHAR OK, EXIT GETCHR
EDIT(073); If chars were split across a buffer, GETCHR did not convert LC
GET.NL: PUSHJ SP,NCHECK ; [E073] DO WE NEED TO CALL NEWLINE ?
JRST GETCHR+2 ; [E073] NO - JUST TEST CHAR FOR LC, ETC.
JSP A2,SAVE ; SAVE SOME REGISTERS
PUSHJ SP,NEWLINE ; CALL NEWLINE
JFCL ; WONT RETURN HERE
JSP A2,REST ; RESTORE THE REGISTERS
JRST GETCHR+2 ; CONTINUE WITH NEW CHARACTER
GETTAB: CAIN A1,.TAB ; IF IT IS A TAB
PUSHJ SP,TAB ; THEN TAKE CARE OF IT
JRST (A6) ; NUMBER
JRST (A6) ; LETTER
TABL11: JRST (A6) ; DELIMITER
JRST (A6) ; FLAGGED DELIMITER
JRST GETCHR ; IGNORABLE CHARACTER
JRST GETTAB ; SPACE & TAB
JRST GET.NL ; [E073] ACTION FOR NEWLINE
SUBI A1,40 ; LOWER CASE
JRST (A6) ; OTHER CHARACTERS
JRST (A6) ; SINGLE QUOTE
; ** STCHAR **
STCHAR: SKIPE A2,STCFL ; IF THERE ARE ANY BUFFERED CHARACTERS
JRST STCNL1 ; THEN USE THEM
; READ THE NEXT CHARACTER
STCHR1: ILDB A1,P ; GET NEXT CHAR
AOS CC ; STEP POSITION COUNT
MOVE A2,CTABLE(A1) ; GET ITS TABLE ENTRY
JRST @TABL10(A2) ; JUMP THROUGH TABLE
STCOK ; NUMBER
STCOK ; LETTER
TABL10: STCOK ; DELIMITER
STCOK ; DELIMITER (FLAGGED)
STCHR1 ; IGNORABLE
STCTAB ; SPACE & TAB
STCNL ; NEW-LINE CHARACTER
STCOK ; LOWER CASE LETTER
STCOK ; OTHER
STCOK ; SINGLE QUOTE
; CHECK FOR A TAB
STCTAB: CAIN A1,.TAB ; IF IT IS A TAB
PUSHJ SP,TAB ; THEN FIND ITS LENGTH
; NOT A SPECIAL CHARACTER
STCOK: SETZM STCFL ; CLEAR THE FLAG
JRST (A6) ; EXIT STCHAR
; A NEW-LINE CHARACTER HAS BEEN SCANNED
STCNL: MOVEM A1,CHAR1 ; SAVE THIS CHARACTER
PUSHJ SP,NCHECK ; IF THIS IS ONLY THE END OF BUFFER
JRST STCHR1+2 ; THEN GET ANOTHER BUFFER AND CONTINUE
AOS STCFL ; SET THE FLAG +
SETZM CHAR2 ; CLEAR 2ND CHAR
SETZM FFCNT ; ZERO FORM-FEED COUNT
JSP A2,SAVE ; SAVE THE REGISTERS
PUSHJ SP,NEWLINE ; PRINT THE LAST LINE
JFCL ; CANT RETURN HERE
JSP A2,REST ; RESTORE THE REGISTERS
EXCH A1,CHAR1 ; GET THE 1ST CHAR
JRST (A6) ; EXIT STCHAR
; 1ST CALL AFTER A NL CHAR: PRESENT 2ND BUFFERED CHAR
STCNL1: JUMPL A2,STCNL2 ; JUMP IF FLAG NEGATIVE
SETOM STCFL ; SET FLAG NEGATIVE
SKIPN A1,CHAR2 ; GET THE 2ND CHAR
JRST STCHR1 ; IF NONE, READ NEXT CHAR
JRST (A6) ; EXIT STCHAR
; 2ND CALL AFTER A NL CHAR: PRESENT ANY FORM-FEEDS
STCNL2: SOSGE FFCNT ; DECREMENT FORM-FEED COUNT
JRST STCNL3 ; JUMP IF NEG (NO MORE FORM FEEDS)
MOVEI A1,.FF ; FORM FEED
JRST (A6) ; EXIT STCHAR
; A SUBSEQUENT CALL: PRESENT 3RD BUFFERED CHAR
STCNL3: SETZM STCFL ; ZERO FLAG
MOVE A1,CHAR1 ; GET THE 3RD CHARACTER
JRST STCHR1+2 ; READ NEXT CHAR
; SAVE A4, A5, A6, AND A3 ON STACK
SAVE: PUSH SP,A4 ; SAVE A4
PUSH SP,A5 ; SAVE A5
PUSH SP,A6 ; SAVE A6
PUSH SP,A3 ; SAVE A3
JRST (A2) ; EXIT SAVE
; RESTORE THEM
REST: POP SP,A3 ; RESTORE A3
POP SP,A6 ; RESTORE A6
POP SP,A5 ; RESTORE A5
POP SP,A4 ; RESTORE A4
JRST (A2) ; EXIT REST
RELOC
CHAR1: BLOCK 1 ; 1ST NL CHAR
CHAR2: BLOCK 1 ; 2ND NL CHAR
FFCNT: BLOCK 1 ; FORM-FEED COUNT
FFCNT2: BLOCK 1 ; FLAG -- NUMBER OF NL CHARS
STCFL: BLOCK 1 ; FLAG -- NUMBER OF NL CHARS
RELOC
; ********* QUOTED DELIMITER WORDS *********
; SET UP
SQUOTE: SKIPE RWS ; IF NO QUOTED RESERVED WORDS
JRST SQ4 ; THEN THIS IS AN ERROR, PROBABLY
JSP A6,IGST ; READ A CHARACTER
MOVE A2,CTABLE(A1) ; GET THE CHARS TABLE ENTRY
AOJN A2,SQILL ; ONLY A LETTER ALLOWED
MOVE A5,RESWRD-.A(A1); GET THE RESERVED WORD TABLE SUBLIST
MOVEM A5,RWSL ; SAVE IT FOR LATER
SETZB A2,SAVED ; ZERO A2 AND SAVED 1ST WORD OF NAME
HRLZI A5,-5 ; READ 5 CHARS
; CHARACTER-READING LOOP
SQ1: LSHC A1,-6 ; SHIFT CHAR INTO A2
ILDB A1,P ; READ NEXT CHAR
AOS CC ; STEP CHAR COUNT
SKIPL A4,CTABLE(A1) ; GET THE CHARS TABLE ENTRY
JRST @TABLE0(A4) ; GOTO ROUTINE IF NOT A LETTER
SQ2: AOBJN A5,SQ1 ; LOOP
; NAME LONGER THAN 1 WORD
SKIPLE SAVED ; IF 2ND TIME HERE THEN
JRST SQILL ; THIS IS AN ERROR
MOVEM A2,SAVED ; SAVE THE 1ST 5 CHARS OF THE NAME
SETZ A2, ; CLEAR F
HRLI A5,-6 ; READ 6 MORE CHARS
JRST SQ1 ; RETURN TO THE LOOP
TABLE0: SQILL ; DELIMITERS
SQILL ; FLAGGED DELIMITERS
SQ1+1 ; IGNORABLE CHARS
SQ1+1 ; SPACE & TAB
SQNL ; NEW-LINE
SQLOW ; LOWER CASE LETTER
SQILL ; OTHER
SQOK ; SINGLE QUOTE
SQ4: SKIPE FNLEVEL ; BEGINNING OF THE WORLD ?
JRST ILLEGAL ; NO - ERROR
SETZM RWS ; YES - PRETEND WE'VE HAD /QUOTE
JRST SQUOTE ; AND TRY AGAIN.
; LOWER CASE LETTER SCANNED
SQLOW: MOVEI A1,-40(A1) ; CONVERT TO UPPER CASE
JRST SQ2 ; RETURN TO LOOP
; A NEW-LINE CHARACTER WAS SCANNED
SQNL: PUSHJ SP,NCHECK ; CHECK IF END OF BUFFER
JRST SQ1+2 ; END OF BUFFER, CONTINUE AS IF NOTHING
SQILL: JSP A6,GETCHR ; READ THE NEXT CHAR
FAIL (130,HARD,IMM,IMPROPER WORD DELIMITER) ; [273]
JRST C4 ; RETURN THE NULL DELIMITER
; MATCHING QUOTE FOUND, LOOK IT UP IN RESERVED WORD TABLE
SQOK: SKIPE A1,SAVED ; FETCH 1ST WORD, SKIP IF NONE
EXCH A1,A2 ; A1=2ND WORD, A2=1ST WORD
MOVE A6,A2 ; MOVE 1ST WORD TO A6
IORI A6,(A5) ; INCLUDE THE CHAR COUNT
MOVEI A3,A1-1 ; LET A3 POINT TO THE 2ND WORD
PUSHJ SP,SQ3 ; SEARCH THE RESERVED WORD TABLE
JRST SQOK2 ; DELIMITER
; PROBABLY "TRUE" OR "FALSE" SCANNED
TLNN A3,40 ; UNLESS IT IS 'TRUE' OR 'FALSE'
JRST SQILL ; IT IS AN ERROR
;
; Edit(1006) Fix compiler crash on multiple 'true' or 'false'.
;
AOSA (SP) ; PREPARE FOR SKIP RETURN
; EXTENSION FROM LSCAN
DELIM: MOVE A3,SCDLT(A1) ; GET THE LEXEME
SQOK2: IBP P ; READ THE NEXT CHAR
AOS CC ; STEP THE CHARACTER COUNT
POPJ SP, ; EXIT
RELOC
SAVED: BLOCK 1 ; SAVED 1ST 5 CHARS OF NAME
RWS: BLOCK 1 ; RESERVED WORD TABLE POINTER
RELOC
SUBTTL ** SEARCH **
; SYMBOL TABLE ENTRY:
;
; !-----------------! WORD 1 BIT 0: DYNAMIC
; ! ! ! BITS 1-2: KIND
; WORD-0 ! BL/PL ! LINK ! BITS 3-8: TYPE
; ! ! ! BITS 9-11: STATUS
; !--------!--------! BIT 12: 1=DECLARED
; ! ! ! BITS 13-17: NUMBER OF ACTUALS
; WORD-1 ! LEXEME ! VALUE !
; ! ! !
; !-----------------! WORD 0 BIT 0: 1=EXTENDED ENTRY
; ! ! BIT 1: 1=MESSAGE GIVEN
; WORD-2 ! NAME ! BIT 2: (NOT USED)
; BITS 3-11: BLOCK LEVEL
; ! ! BITS 12-17: PROCEDURE LEVEL
; ! !
; !-----------------!
; ! !
; ! EXTENSION WORD1 !
; ! !
; !-----------------! NOTE: THE EXTENSION WORDS ARE OPTIONAL
; ! !
; ! EXTENSION WORD2 !
; ! !
; !-----------------!
;
;
;
;
;
; ***** S E A R C H *****
;
; "SEARCH" IS USED TO LOOK UP AN IDENTIFIER IN THE SYMBOL
; TABLE. "SEARCH" USES AS INPUT THE BUFFER ADDRESS CONTAINED
; IN NSYM AND OUTPUTS THE IDENTIFIER'S LEXEME INTO SYM.
;
; IF THE IDENTIFIER IS NOT FOUND IN THE SYMBOL TABLE, "SEARCH"
; WILL AUTOMATICALLY PUT IT INTO THE TABLE UNLESS THE GLOBAL
; BOOLEAN "NOENTRY" IS SET TO 1.
;
; IF THE GLOBAL BOOLEAN "DECLAR" IS SET TO 1 THEN "SEARCH"
; WILL SEARCH ONLY THE CURRENT BLOCK LEVEL PORTION OF THE
; SYMBOL TABLE. "DECLAR" INDICATES DECLARATION MODE.
SEARCH: MOVE A3,NSYM ; GET NSYM
MOVE A2,(A3) ; GET 1ST WORD OF NAME
MOVE A4,A2 ; COPY TO A4
MULI A4,RANDOM ; RANDOMIZE
ANDI A4,177 ; USE 7 BITS FOR HASH INDEX
SKIPN A1,SYMHT##(A4) ; LOCATE 1ST ENTRY IN SUBLIST
JRST NEWSYM ; -NONE, MUST BE A NEW SYMBOL
SERCH1: TRNN FL,DECLAR ; ARE WE IN DECLARATION MODE?
JRST LOOP3+1 ; -NO, GOTO 3-INST LOOP
SKIPA A5,STBB ; LOAD BLOCK POINTER, SKIP
; 4-INST LOOP FOR DECLARATION MODE
LOOP4: HRRZ A1,SYMLNK(A1) ; LOCATE NEXT SUBLIST ENTRY
CAILE A5,(A1) ; WITHIN CURRENT BLOCK?
JRST NEWSYM ; -NO, MUST BE NEW
CAME A2,SYMNAM(A1) ; 1ST WORDS SAME?
JRST LOOP4 ; -NO, LOOP
JRST SERCH2 ; -YES, CHECK REMAINDER
; 3-INST LOOP FOR NORMAL MODE
LOOP3: HRRZ A1,SYMLNK(A1) ; LOCATE NEXT SUBLIST ENTRY
CAME A2,SYMNAM(A1) ; 1ST WORDS MATCH?
JRST LOOP3 ; -NO, LOOP
TRNN A1,777777 ; LINK TO ZERO?
JRST NEWSYM ; -YES, MATCH NOT REALLY FOUND
; MATCH FOUND ON 1ST WORDS
SERCH2: SKIPN A6,-1(A3) ; GET LENGTH OF NAME
JRST SERCH3 ; -IS 1 WORD LONG, DONE
ADD A1,[ ; SET UP REGISTER FOR
XWD A6,SYMNAM] ; INDIRECT ADDRESSING
MOVE A5,@A3 ; GET A WORD FROM BUFFER
CAME A5,@A1 ; COMPARE TO WORD IN ENTRY
JRST SERCH4 ; -MISMATCH
SOJG A6,.-3 ; -MATCH. LOOP
MOVEI A1,-SYMNAM(A1) ; CORRECT ADDRESS
; -END OF NAME, SEARCH COMPLETE
; END OF NAME, SYMBOL FOUND
SERCH3: IFN FTSTATS,<
AOS REFCNT ; INCREMENT STATS COUNTER
>
HLL A1,SYMTYP(A1) ; LOAD LEXEME
MOVE SYM,A1 ; MOVE LEXEME TO SYM
TRNE FL,CREF ; ARE WE CREF'ING ?
PUSHJ SP,CREFIT ; YES - DO IT (CLOBBER AC1-6)
MOVE A1,SYM ; THE RECOVERY ROUTINES IN UTL EXPECT IT!
TLZ SYM,37 ; ZERO THE 5 BITS
TLO SYM,$ST ; MARK LEXEME A VARIABLE, SIMPLE
TRNN FL,BPAIR ; IF NOT SCANNING A BOUND PAIR, THEN
POPJ SP, ; EXIT SEARCH
LDB A4,[ ; GET THE ENTRY'S BLOCK LEVEL
POINT 9,SYMBLK(SYM),11] ; POINTER TO BLOCK LEVEL FIELD
CAME A4,BLOCKL ; IF NOT THE SAME AS CURRENT BLOCK LEVEL
POPJ SP, ; THEN OK, EXIT SEARCH
FAIL (84,HARD,NSYM,VARIABLE CANT BE USED HERE)
POPJ SP, ; EXIT SEARCH
; SYMBOL NOT IN SYMBOL TABLE
NEWSYM: TRNE FL,NOENTR ; SHOULD AN ENTRY BE MADE?
JRST NONEW ; -NO, SKIP
IFN FTSTATS,<
AOS DEFCNT ; INCREMENT STATS COUNTER.
MOVE A1,(A3) ;
ANDI A1,77 ; GET # CHARS -1
ADDM A1,IDCHRS ; ACCUMULATE FOR AVERAGE.
>
MOVE A6,-1(A3) ; GET NAME LENGTH
PUSHJ SP,GETSYM ; GET SOME SPACE IN SYMBOL TABLE
PUSHJ SP,LINKUP ; FILL THE ENTRY AND LINK IT UP
HRLI A1,$ST ; MARK LEXEME A VARIABLE, SIMPLE
MOVE SYM,A1 ; MOVE LEXEME TO SYM
TRNE FL,CREF ; ARE WE CREF'ING ?
PUSHJ SP,CREFIT ; YES - DO IT (& CLOBBER AC1-6)
SKIPA A1,SYM ; THE RECOVERY ROUTINES IN UTL EXPECT IT!
NONEW: MOVEI SYM,0 ; RETURN A NULL SYMBOL
POPJ SP, ; EXIT SEARCH
SERCH4: HRRZ A1,SYMLNK-SYMNAM(A1); LOCATE NEXT ENTRY ON SUBLIST
JRST SERCH1 ; RETURN TO LOOP
GETSYM: MOVEI A5,SYMNAM+1(A6) ; TOTAL LENGTH OF NEW ENTRY
; ACQUIRE SOME SPACE IN SYMBOL TABLE
GETSPC: HRRZ A1,NASTE ; LOCATE NEXT AVAIL ENTRY
ADDB A5,NASTE ; COMPUTE NEW NEXT ENTRY
CAMLE A5,NAFTE ; CHECK FOR TABLE OVERFLOW
JRST OVFL1 ; -OVERFLOW, MOVE THE TABLES, EXIT
POPJ SP, ; EXIT
; COMPUTE AN ENTRY'S HASH VALUE AND NAME LENGTH IN WORDS-1
HAL: MOVE A4,SYMNAM(A3) ; GET 1ST WORD OF NAME
MULI A4,RANDOM ; RANDOMIZE
ANDI A4,177 ; SAVE 7 BITS FOR HASH
MOVE A5,SYMNAM(A3) ; GET 1ST WORD OF NAME
MOVEI A5,1(A5) ; ADD 1
ANDI A5,77 ; SAVE ONLY LENGTH BYTE
IDIVI A5,6 ; DIVIDE BY 6 CHARS/WORD
MOVEI A6,(A5) ; COPY IN A6
POPJ SP, ; EXIT
; LINK NEW ENTRY INTO SYMBOL TABLE
LINKUP: MOVE A5,SYMHT##(A4) ; PUT NEW ENTRY ON TOP OF
MOVEM A1,SYMHT##(A4) ; HASH TABLE SUBLIST
MOVE A2,BLKLEV ; GET BLOCK LEVEL
LSH A2,6 ; SHIFT IT 6
IOR A2,FNLEVE ; INCLUDE FUNCTION LEVEL
HRL A5,A2 ; PUT WITH NEW LINK
MOVEM A5,SYMLNK(A1) ; SET LINK FIELD
SETZM SYMTYP(A1) ; CLEAR TYPE & VALUE
MOVEI A5,SYMNAM(A1) ; SET UP FOR
HRLI A5,A6 ; INDIRECT ADDRESSING
LNKUP1: MOVE A2,@A3 ; GET WORD FROM SOURCE
MOVEM A2,@A5 ; PUT IN SYMBOL TABLE ENTRY
SOJGE A6,LNKUP1 ; LOOP TILL DONE
POPJ SP, ; DONE
IFN FTSTATS,<
RELOC ;
IDCHRS:BLOCK 1 ; # CHARS IN IDENTIFIERS (FOR STATS)
DEFCNT:BLOCK 1 ; # OF IDENTIFIERS DEFINED.
REFCNT: BLOCK 1 ; # OF REFERENCES TO IDENTIFIERS.
RELOC ;
>
SUBTTL ** STADD & XTNDLB & TOFIX **
; ***** S T A D D *****
;
; "STADD" WILL MAKE A NEW ENTRY IN THE SYMBOL TABLE FOR A NEW
; IDENTIFIER WHOSE NAME IS THE SAME AS THE IDENTIFIER NAMED
; IN SYM. SINCE "STADD" IS USED ONLY FOR LABELS, "STADD"
; WILL AUTOMATICALLY EXTEND THIS ENTRY. THE LEXEME FOR THIS
; NEW ENTRY REPLACES THAT WHICH IS IN SYM. THE VALUE FIELD OF THE
; NEW ENTRY WILL POINT TO THE OLD ENTRY.
;
;
STADD: MOVEI A3,(SYM) ; GET ADDR OF OLD ENTRY
PUSHJ SP,HAL ; GET HASH AND LENGTH OF ENTRY
PUSHJ SP,GETSYM ; GET SOME SPACE IN SYMBOL TABLE
MOVEI A3,SYMNAM(A3) ; ADDRES OF NAME FIELD
HRLI A3,A6 ; SET UP FOR INDIRECT ADDRESSING
PUSHJ SP,LINKUP ; LINK UP THE NEW ENTRY
HRRM SYM,1(A1) ; CHAIN NEW ENTRY TO OLD ENTRY
HRRZI SYM,(A1) ; MOVE ADDR TO SYM
; ***** E X T E N D *****
;
; THE ENTRY NAMED IN SYM IS EXTENDED BY 2 WORDS.
;
;
XTNDLB: MOVEI A5,2 ; GET TWO MORE WORDS FROM
PUSHJ SP,GETSPC ; THE SYMBOL TABLE
EDIT (177); DO NOT CLOBBER SYMBOL TABLE IN ERROR CASES
HRRZ A5,SYM ;[177] IN THIS LEVEL?
CAMGE A5,STBB ;[177]
JRST XTNDL1 ;[177] NO! MUST BE ERRONEOUS PROGRAM
EDIT (207); DO NOT CLOBBER SYMBOL TABLE IN ERROR CASES
PUSH SP,A3+1 ;[207] SAVE SOME REGISTERS
PUSH SP,A3 ;[207]
LDB A3,[POINT 6,2(SYM),35] ;[207]
ADDI A3,2+5 ;[207] GET CC FIELD, ADD TWO CHARACTERS
IDIVI A3,6 ;[207] CONVERT TO WORDS
ADD A5,A3 ;[207] GET END ADDRESS
POP SP,A3 ;[207] RESTORE
POP SP,A3+1 ;[207]
CAIE A1,2(A5) ;[207] AT END?
JRST XTNDL1 ;[207] NO, SOME KIND OF AN ERROR
SETZM (A1) ; ZERO 1ST WORD OF EXTENSION
SETZM 1(A1) ; ZERO 2ND WORD OF EXTENSION
HRLZI A5,400000 ; SET EXTEND BIT ON
IORM A5,(SYM) ; PUT IN ENTRY
POPJ SP, ; EXIT EXTEND
; CONTROL ONLY GETS HERE IF WE ARE TRYING TO EXTEND THE SYMBOL TABLE
; ENTRY FOR SOMETHING GLOBAL TO US (YCCH). THIS ONLY HAPPENS IN ERRONEOUS
; PROGRAMS, SINCE ALL FORWARD DECLARATIONS MAKE EXTENDED ENTRIES. WE
; CAN GET HERE, FOR EXAMPLE, IF A PARAMETER TO A PROCEDURE IS NOT DECLARED
; AND TURNS OUT TO BE A LABEL (SOME INNER ROUTINE DOES A GOTO TO IT).
; THIS ROUTINE INVOLVES A LOT OF OVERHEAD TO MOVE THE SYMBOL TABLE UP FOR THE
; EXTENSION, BUT WILL ONLY BE INVOKED FOR PROGRAMS WHICH ALREADY HAVE A FATAL
; ERROR (NO OBJECT CODE BEING PRODUCED) ANYWAYS.
;
; THE ALTERNATIVE WOULD BE TO ALWAYS CREATE EXTENDED SYMBOL TABLE ENTRIES
; IN ALL CASES, BUT THIS MIGHT CAUSE PROGRAMS TO RUN OUT OF CORE WHICH NOW
; COMPILE CORRECTLY.
;
; STEP 1: MOVE THE SYMBOL TABLE UP AND ZERO THE EXTENSION WORDS
;
XTNDL1: PUSH SP,A2 ;[177] SAVE REGISTERS
PUSH SP,A3 ;[177]
PUSH SP,A4 ;[177]
HRLZI A5,400000 ;[177] GET EXTEND BIT
IORM A5,(SYM) ;[177] MARK AS EXTENDED
MOVEI A2,2(SYM) ;[177] GET ADDRESS, PLUS TWO OVERHEAD WORDS
LDB A5,[POINT 6,2(SYM),35] ;[177] GET CC FIELD
ADDI A5,2+5 ;[177] ADD TWO CHARACTERS (ONE IS CC FIELD)
PUSH SP,A5+1 ;[177]
IDIVI A5,6 ;[177] CONVERT TO WORDS, ROUNDING UP
POP SP,A5+1 ;[177]
ADD A2,A5 ;[177] ADD IN, A2 IS FIRST WORD WHICH WILL MOVE
MOVE A5,NASTE ;[177] A5 IS LAST WORD WHICH WILL MOVE
SUBI A5,3 ;[177] MOVE DOWN TO LAST USED WORD
;
; REVERSE BLT SYMBOL TABLE UP
; WE CAN'T DO A REAL BLT, SINCE IT WILL OVERLAP
;
XTNDL2: MOVE A1,(A5) ;[177] GET A WORD
MOVEM A1,2(A5) ;[177] STORE IT UP TWO WORDS
SOJ A5, ;[177] MOVE DOWN A WORD
CAML A5,A2 ;[177] COMPARE WITH LOWEST WORD TO MOVE
JRST XTNDL2 ;[177] LOOP DOWN TO REVERSE BLT
;
; CLEAR EXTENSION WORDS OF SYM
;
SETZM (A2) ;[177]
SETZM 1(A2) ;[177]
;
; FIX BLOCK LEVEL POINTERS IN SYMBOL TABLE
; A2: FIRST WORD (LOWEST ADDRESS) WHICH HAS MOVED
; A5: ADDRESS OF CURRENT BLOCK POINTER (STARTS AT STBB)
; A1: WORDS TO MOVE CONTENTS IN
;
MOVE A5,STBB ;[177] INITIALIZE POINTER TO CURRENT BLOCK
CAMGE A5,A2 ;[207] SHOULD STBB MOVE?
JRST XTNDL3 ;[207] NO
ADDI A5,2 ;[177] RELOCATE IT BY TWO WORDS
MOVEM A5,STBB ;[177] AND REPLACE
;
XTNDL3: MOVE A1,-1(A5) ;[177] GET POINTER
CAMGE A1,A2 ;[177] IF LESS THAN A2 (OR ZERO), DONE
JRST XTNDL4 ;[177]
ADDI A1,2 ;[177] ELSE, RELOCATE BY TWO WORDS
MOVEM A1,-1(A5) ;[177] AND REPLACE
MOVE A5,A1 ;[177] LOOP DOWN BLOCKS
JRST XTNDL3 ;[177]
;
; FIX HASH TABLE POINTERS INTO SYMBOL TABLE
; A5: AOBJN POINTER
; A2: LOWEST ADDRESS WORD WHICH MOVED
;
XTNDL4: HRRI A5,SYMHT ;[177] GET START ADDRESS OF HASH TABLE
HRLI A5,-200 ;[177] GET NEGATIVE WORD COUNT
;
XTNDL5: MOVE A1,(A5) ;[177] GET A HASH POINTER TO SYMBOL TABLE
CAMGE A1,A2 ;[177] NEED TO RELOCATE IT?
JRST XTNDL6 ;[177] NOT IF LESS THAN LOWEST WORD MOVED (OR ZERO)
ADDI A1,2 ;[177] YES, RELOCATE BY TWO WORDS
MOVEM A1,(A5) ;[177] AND REPLACE
;
; FIX LINKS IN SYMBOL TABLE FROM THIS HASH POINTER CHAIN HEAD
;
MOVE A3,A1 ;[177] ADDRESS OF LINK
;
XTNDL7: HRRZ A4,(A3) ;[177] GET LINK
CAMGE A4,A2 ;[177] NEED TO RELOCATE IT?
JRST XTNDL6 ;[177] NO
ADDI A4,2 ;[177] YES, RELOCATE IT BY TWO WORDS
HRRM A4,(A3) ;[177] AND REPLACE IT
MOVE A3,A4 ;[177] ON TO THE NEXT (PREVIOUS IN CHAIN)
JRST XTNDL7 ;[177] LOOP ENDS WHEN HIT ZERO OR BELOW MOVED AREA
;
XTNDL6: AOBJN A5,XTNDL5 ;[177] LOOP THROUGH HASH TABLE
;
POP SP,A4 ;[177] RESTORE REGISTERS
POP SP,A3 ;[177]
POP SP,A2 ;[177]
POPJ SP, ;[177] AND RETURN (WHEW!)
; ***** T O F I X *****
;
; PUT HALFWORD INTO FIX-UP TABLE
;
;
.TOFIX: MOVEI A4,1 ; LOAD A 1
XORB A4,TOFIXI ; DECIDE WHICH HALF
SOJE A4,TOFIX1 ; IF RIGHT HALF, GET ANOTHER WORD
MOVE A4,NAFTE ; LOCATE WORD -1
HRLM A2,1(A4) ; PUT HALFWORD INTO TABLE
POPJ SP, ; EXIT TOFIX
TOFIX1: SOS A4,NAFTE ; STEP TO NEXT AVAIL WORD IN FIX-UP TABLE
CAML A4,NASTE ; IF SUFFICIENT SPACE IN FIXUP TABLE
JRST .+3 ; THEN SKIP THIS PART
PUSHJ SP,OVFL1 ; THEN MOVE THE TABLES
ADDI A4,DELTA ; USE CORRECT POINTER
HRRZM A2,1(A4) ; PUT HALFWORD INTO TABLE
POPJ SP, ; EXIT TOFIX
RELOC
TOFIXI: BLOCK 1 ; "TOFIX" HALFWORD POINTER
RELOC
SUBTTL ** RUND **
; ***** R U N D *****
;
; "RUND" ADVANCES THE WINDOW BY PUTTING NSYM INTO SYM, NDEL
; INTO DEL, AND CALLING "LSCAN" TO OBTAIN NEW LEXEMES FOR
; NSYM AND NDEL. IF NSYM CONTAINED AN IDENTIFIER BUFFER
; ADDRESS, THE LEXEME IS OBTAINED BY CALLING "SEARCH".
; "RUND" WILL INSERT NULL-SYMBOLS BETWEEN CONSECUTIVE
; DELIMITERS, AND WILL INSERT NULL DELIMITERS BETWEEN CONSECUTIVE
; SYMBOLS. "RUND" WILL COMPUTE "LEXEX" AND "COMPNAME", AND
; WILL CORRECTLY BUFFER THE CHARACTER COUNTERS SO THAT THEY CAN
; BE FOUND BY THE ROUTINES THAT PRINT THE UP-ARROWS IN
; ERROR MESSAGES.
;
;
RUND:
; SHIFT WINDOW
MOVE A4,NXTSLN ; GET NSYM LINE NO
MOVEM A4,CURSLN ; AND SAVE AS CURRENT LINE NO
MOVE A4,NXTDLN ; SIMILARLY UPDATE DEL
MOVEM A4,CURDLN ; FROM NDEL LINE NO
MOVE SYM,NSYM ; MOVE NSYM TO SYM
TLNE SYM,$SYMB ; UNLESS THIS IS A CONSTANT
PUSHJ SP,SEARCH ; GET LEXEME, PUT IN SYM
MOVE DEL,NDEL ; THE LEFT
JUMPE DEL,RUND2 ; -RUND PREVIOUSLY SCANNED 2 SYMS IN A ROW
; SCAN NEXT ITEM
PUSHJ SP,LSCAN ; SCAN NEXT ITEM
RUND0: JRST RUND3 ; -A DELIM WAS SCANNED (2ND IN A ROW)
MOVE A2,CC ; LOAD POINTER FOR ERR MSG UP-ARROW
RUND1: MOVE A4,LINENO ; A SYMBOL HAS BEEN SCANNED
MOVEM A4,NXTSLN ; SO REMEMBER WHAT LINE IT WAS ON
MOVEI A4,2
XORB A4,PLIST ; ALTERNATE BETWEEN TWO POINTER BUFFERS
MOVEM A2,(A4) ; SAVE READ POINTER
MOVEM A3,NSYM ; PUT LEXEME IN NSYM
; SCAN ANOTHER ITEM
PUSHJ SP,LSCAN ; SCAN ANOTHER ITEM
RUND5: JRST RUND4 ; -A DELIM WAS SCANNED
; SCANNED 2 NON-DELIMITERS IN A ROW
MOVEM A3,DUBBLE ; -ANOTHER SYM SCANNED, SAVE FOR NEXT RUND
MOVE A2,CC ; LOAD POINTER FOR ERR MSG UP-ARROW
MOVEM A2,DOUBLP ; SAVE THE POINTER FOR LATER TOO
MOVE A4,PLIST ; POINTER BUFFER
MOVE A2,(A4) ; GET POINTER TO SYM
TLO A2,EXACT ; USE EXACT POINTER
SETZM NDEL ; PUT NULL-DELIM INTO NDEL
JRST RUND8+1 ; CONTINUE
; FETCH THE SAVED 2ND SYMBOL
RUND2: MOVE A3,DUBBLE ; RETRIEVE OLD DOUBLE SYM
MOVE A2,DOUBLP ; RETRIEVE ITS POINTER TOO
JRST RUND1 ; CONTINUE ON
; DELIMITER ONLY, NO SYMBOL
; Edit (1003) Make ALGDDT NEXT command work in this case.
RUND3: MOVE A4,LINENO ; [E1003] UPDATE NXTSLN TO BE THE
MOVEM A4,NXTSLN ; [E1003] CURRENT LINE NUMBER
MOVEM A3,NDEL ; [E1003] PUT LEXEME IN NDEL
SETZM NSYM ; PUT NULL SYMBOL IN NSYM
MOVE A4,PLIST ; POINTER BUFFER
MOVE A2,1(A4) ; GET POINTER TO SYM
TLO A2,EXACT ; USE EXACT POINTER
MOVEI A4,2 ; HERE IT IS AGAIN
XORB A4,PLIST ; ALTERNATE BETWEEN TWO POINTER BUFFERS
MOVEM A2,(A4) ; SAVE NULL-SYMBOL POINTER
JRST RUND8
; SCANNED A SYMBOL FOLLOWED BY A DELIMITER
RUND4: MOVEM A3,NDEL ; PUT LEXEME IN NDEL
MOVE A4,PLIST ; RELOAD ADDR OF CURRENT POINTER BUFFER
RUND8: MOVE A2,CC ; LOAD POINTER FOR ERR MSG UP-ARROW
MOVEM A2,1(A4) ; SAVE READ POINTER
MOVE A4,LINENO ; GET LINE NUMBER FOR NDEL
MOVEM A4,NXTDLN ; AND SAVE IT
; COMPUTE LEXEX AND COMPNAME
RUND7: TLNN SYM,$SYMB ; IF CONSTANT OR NULL SYMBOL
JRST RUND6 ; THEN SKIP THIS
LDB A4,[ ; PICK UP THE BLOCK LEVEL
POINT 9,SYMBLK(SYM),11] ; POINTER TO BLOCK LEVEL FIELD
SETCM A5,SYM ; COMPLEMENT THE LEXEME
TLNN A5,$FON ; IF FORMAL-BY-NAME
JRST IRREG ; THEN ONES COMP BL
TLNE A5,$PRO ; IF IT IS NOT A PROCEDURE
JRST REGUL ; THEN POSITIVE BL
HRRZ A5,SYM ; GET SYMBOL TABLE ADDRESS ALONE
CAIGE A5,B0END## ; IF A LIBRARY PROCEDURE
JRST REGUL ; THEN POSITIVE BL
; IF FORMAL BY NAME OR NON-LIBRARY PROCEDURE, LEXEX=-BL-1
IRREG: ADDI A4,1 ; PLUS 1
LSH A4,^D27 ; SHIFT BL+1 TO POSITION
MOVNM A4,LEXEX ; NEGATE AND MOVE TO LEXEME EXTENSION
JRST RUND6+1
; FOR ALL OTHERS, LEXEX=BL, COMPNAME=A RANDOM BIT ON
REGUL: LSH A4,^D27 ; SHIFT BL INTO POSITION
MOVEM A4,LEXEX ; STORE IN LEXEME EXTENSION
MOVE A4,SYM ; GET SYMBOL TABLE ADDRESS
ANDI A4,37 ; SAVE FIVE BITS
MOVEI A5,1 ; PUT A 1 IN ACCUMULATOR
LSH A5,(A4) ; SHIFT IT RANDOMLY
MOVEM A5,COMPNAME ; STORE IT IN COMPNAME
POPJ SP, ; EXIT RUND
; DONT COMPUTE LEXEX OR COMPNAME FOR A CONSTANT OR NULL SYMBOL
RUND6: SETZM LEXEX ; CLEAR LEXEME EXTENSION
SETZM COMPNAME ; CLEAR COMPOSIT NAME
POPJ SP, ; EXIT RUND
.SCRUND:
MOVE A4,PLIST ; ADDRESS OF SAVED POINTER
MOVE A4,(A4) ; TO NSYM. GET IT
MOVEI A5,2 ; ADDRESS OF POINTER BUFFER FOR
XOR A5,PLIST ; SYM
MOVEM A4,(A5) ; SET SYM POINTER
MOVEM A4,1(A5) ; SET DEL POINTER
JRST RUND7
RELOC
DUBBLE: BLOCK 1 ; SAVE AREA FOR CASE OF DOUBLE-SYMBOL
DOUBLP: BLOCK 1 ; SAVE AREA FOR ITS POINTER
RELOC
SUBTTL ** ERROR MESSAGE TEXT TABLE **
TTABLE:
[ASCIZ /SEMICOLON OMITTED/],,
[ASCIZ /UNDECLARED IDENTIFIER/] ; 1
[ASCIZ /INCORRECT STATEMENT/],,
[ASCIZ /INCORRECT EXPRESSION/] ; 3
[ASCIZ /PROBABLY OPERATOR OMITTED/],,
[ASCIZ /IDENTIFIER OR CONSTANT MISSING/] ; 5
[ASCIZ /INCORRECT DESIGNATIONAL EXPRESSION/],,
[ASCIZ /INCORRECT OR UNPARENTHESIZED ASSIGNMENT/] ; 7
[ASCIZ /SYMBOL NOT PERMITTED HERE/],,
[ASCIZ /AMBIGUOUS USE OF COLON/] ; 9
[ASCIZ /SEMICOLON PROBABLY SUPERFLUOUS/],,
[ASCIZ /ONLY LETTER STRING ALLOWED/] ; 11
[ASCIZ /THIS DELIMITER IS NOT PERMITTED BEFORE 'DO'/],,
[ASCIZ /'WHILE' STATEMENT IS NOT ALLOWED BETWEEN 'THEN' AND 'ELSE'/]
; 13
[ASCIZ /'THEN' MUST NOT BE FOLLOWED BY 'IF'/],,
[ASCIZ /'THEN' STATEMENT NOT FOUND/] ; 15
[ASCIZ /DECLARATIONS MUST BE TERMINATED BY SEMICOLON/],,
[ASCIZ /THIS IS NOT ALLOWED AFTER END/] ; 17
[ASCIZ /CANNOT BE USED AS ARGUMENT/],,
[ASCIZ /ARGUMENT TOO LARGE/] ; 19
[ASCIZ /PROBABLY 'END' OMITTED/],,
[ASCIZ /COMPLEX ARITHMETIC NOT IMPLEMENTED/] ; 21
[ASCIZ /DECLARATOR 'LONG' MUST BE FOLLOWED BY 'REAL'/],,
[ASCIZ /NOT PERMITTED AS DECLARATOR/] ; 23
[ASCIZ /NOT PERMITTED AS SPECIFIER/],,
[ASCIZ /INCORRECT DECLARATION OR SPECIFICATION/] ; 25
[ASCIZ /NO DECLARATION SHOULD FOLLOW PROCEDURE OR SWITCH DECLARATION/],,
[ASCIZ /IMPROPER ARRAY DELARATION OR SPECIFICATION/] ; 27
[ASCIZ /DELIMITER MUST NOT BE DECLARED OR SPECIFIED/],,
[ASCIZ /PROBABLY LIST ELEMENT MISSING/] ; 29
[ASCIZ /IMPROPER DECLARATION/],,
[ASCIZ /VALUE WAS ALREADY SPECIFIED/] ; 31
[ASCIZ /IMPROPER TYPE OF FORMAL IN VALUELIST/],,
[ASCIZ /NON-FORMALS MUST NOT BE SPECIFIED/] ; 33
[ASCIZ /BOUND PAIR NOT FOUND/],,
[ASCIZ /INCORRECT BOUND PAIR/] ; 35
[ASCIZ /PROBABLY RIGHT BRACKET OMITTED/],,
[ASCIZ /TYPE DOES NOT MATCH FORWARD DECLARATION/] ; 37
[ASCIZ /:= MISSING IN SWITCH DECLARATION/],,
[ASCIZ /PROCEDURE NESTING TOO DEEP/] ; 39
[ASCIZ /NOT A SIMPLE IDENTIFIER IN FORMAL LIST/],,
[ASCIZ /FORMAL LIST NOT PROPERLY TERMINATED/] ; 41
[ASCIZ /PROBABLY SEMICOLON MISSING IN PROCEDURE HEADING/],,
[ASCIZ /NOT ALL FORMALS HAVE BEEN SPECIFIED/] ; 43
[ASCIZ /INCORRECTLY STRUCTURED FORMAL LIST/],,
[ASCIZ /'UNTIL' EXPRESSION NOT FOUND/] ; 45
[ASCIZ /BYTE NOT PERMITTED AS CONTROL VARIABLE/],,
[ASCIZ /ASSIGNMENT DELIMITER NOT FOUND/] ; 47
[ASCIZ /DELIMITER 'DO' NOT FOUND/],,
[ASCIZ /ASSIGNMENT HAS NON-MATCHING TYPES/] ; 49
[ASCIZ /DELIMITER OMITTED/],,
[ASCIZ /CANNOT BE USED AS UNARY OPERATOR/] ; 51
[ASCIZ /CANNOT BE USED AS BINARY OPERATOR/],,
[ASCIZ /'THEN' EXPRESSION NOT FOUND/] ; 53
[ASCIZ /CONDITIONAL EXPRESSION MUST HAVE 'ELSE' PART/],,
[ASCIZ /CONDITIONAL EXPRESSION MUST BE PARENTHESIZED/] ; 55
[ASCIZ /IMPROPER SEQUENCE OF DELIMITERS/],,
[ASCIZ /WRONG NUMBER OF DIMENSIONS/] ; 57
[ASCIZ /TOO MANY PARAMETERS FOR STANDARD FUNCTION/],,
[ASCIZ /NON-TYPE PROCEDURE IN EXPRESSION/] ; 59
[ASCIZ /MATCHING CLOSE PARENTHESIS NOT FOUND/],,
[ASCIZ /INCORRECT NUMBER OF ACTUAL PARAMETERS/] ; 61
[ASCIZ /NO DECLARATION IN THIS BLOCK FOR FORWARD/],,
[ASCIZ //] ; [266] 63
[ASCIZ /FORWARD DECLARATION WAS REQUIRED/],,
[ASCIZ /TYPES DO NOT MATCH/] ; 65
[ASCIZ /STACK ADDRESS OVERFLOW/],,
[ASCIZ /NON-INTEGER OPERAND FOR OPERATOR 'DIV' OR 'REM'/] ; 67
[ASCIZ /COMPLEX ARITHMETIC NOT IMPLEMENTED/],,
[ASCIZ /NON-ARITHMETIC OPERAND FOR ARITHMETIC OPERATOR/] ; 69
[ASCIZ /NON-ARITHMETIC OPERAND FOR RELATIONAL OPERATOR/],,
[ASCIZ /NON-BOOLEAN OPERAND FOR BOOLEAN OPERATOR/] ; 71
[ASCIZ /DELIMITER 'NOT' REQUIRES BOOLEAN OPERAND/],,
[ASCIZ /UNARY + AND - REQUIRE ARITHMETIC OPERAND/] ; 73
[ASCIZ /OVERFLOW WHILE COMBINING CONSTANTS/],,
[ASCIZ /OVERFLOW IN LONG REAL OPERATION ON CONSTANTS/] ; 75
[ASCIZ /OVERFLOW OR UNDEFINED RESULT FOR "CONSTANT ^ CONSTANT"/],,
[ASCIZ /PARAMETER FOR STANDARD FUNCTION MUST BE ARITHMETIC/] ; 77
[ASCIZ /STANDARD FUNCTION "INT" REQUIRES BOOLEAN PARAMETER/],,
[ASCIZ /STANDARD FUNCTION "BOOL" REQUIRES INTEGER OPERAND/] ; 79
[ASCIZ /PARAMETER MUST BE OF ARITHMETIC TYPE/],,
[ASCIZ /FOR STATEMENT NOT ALLOWED BETWEEN 'THEN' AND 'ELSE'/] ; 81
[ASCIZ /SWITCH IDENTIFIER NOT ALLOWED HERE/],,
[ASCIZ /EXPRESSION TOO LONG/] ; 83
[ASCIZ /IDENTIFIER DECLARED IN THIS BLOCK NOT PERMITTED HERE/],,
[ASCIZ /INCORRECT FILE OR BLOCK STRUCTURE/] ; 85
[ASCIZ /INCORRECT BLOCK STRUCTURE: TOO MANY ENDS/],,
[ASCIZ /PROCEDURE INCORRECTLY TERMINATED/] ; 87
[ASCIZ /INCORRECT FILE STRUCTURE/],,
[ASCIZ /EMPTY SOURCE FILE/] ; 89
[ASCIZ /INVALID CONSTANT/],,
[ASCIZ /IDENTIFIER EXCEEDS 64 CHARACTERS/] ; 91
[ASCIZ /RESERVED WORD DELIMITER NOT ALLOWED HERE/],,
[ASCIZ /CHARACTER NOT LEGAL IN ALGOL/] ; [273] 93
[ASCIZ /EXPONENT TOO SMALL/],,
[ASCIZ /EXPONENT TOO LARGE/] ; 95
[ASCIZ /DECLARATION FOLLOWS STATEMENT/],,
[ASCIZ /IMPROPER USE OF "."/] ; 97
[ASCIZ /INTEGER CONSTANT TOO BIG: CONVERTED TO TYPE REAL/],,
[ASCIZ /DID NOT FIND 'TO' IN 'GOTO' STATEMENT/] ; [273] 99
[ASCIZ /N EXPRESSION/],,
[ASCIZ / STATEMENT/] ; 101
[ASCIZ / BOOLEAN EXPRESSION/],,
[ASCIZ / DESIGNATIONAL EXPRESSION/] ; 103
[ASCIZ / LABEL IDENTIFIER/],,
[ASCIZ / LABEL IDENTIFIER/] ; 105
[ASCIZ /N UNDECLARED (UNSPECIFIED) IDENTIFIER/],,
[ASCIZ /N ARITHMETIC EXPRESSION/] ; 107
[ASCIZ / NEW IDENTIFIER/],,
[ASCIZ /N ARITHMETIC EXPRESSION/] ; 109
[ASCIZ /N ARITHMETIC EXPRESSION/],,
[ASCIZ /N ARITHMETIC EXPRESSION/] ; 111
[ASCIZ /N ARITHMETIC VARIABLE/],,
[ASCIZ / VARIABLE/] ; 113
[ASCIZ / STRING EXPRESSION/],,
[ASCIZ / BOOLEAN OR ARITHMETIC EXPRESSION/] ; 115
[ASCIZ / BOOLEAN OR ARITHMETIC EXPRESSION/],,
[ASCIZ /N ARRAY IDENTIFIER/] ; 117
[ASCIZ /N ARITHMETIC EXPRESSION/],,
[ASCIZ / SWITCH IDENTIFIER/] ; 119
[ASCIZ /N ACTUAL PARAMETER/],,
[ASCIZ / PROCEDURE IDENTIFIER/] ; 121
[ASCIZ /N ARITHMETIC EXPRESSION/],,
[ASCIZ /N ARITHMETIC EXPRESSION/] ; 123
[ASCIZ / STRING VARIABLE/],,
[ASCIZ / BOOLEAN OR ARITHMETIC EXPRESSION/] ; 125
[ASCIZ /NO VALUE ASSIGNED TO TYPED PROCEDURE, OR PROCEDURE NAME CONFLICTS WITH ANOTHER DEFINITION/],,
[ASCIZ/ ASSIGNMENT TO PROCEDURE OUTSIDE ITS BODY/] ; [306] 127
[ASCIZ /INTEGER TOO LARGE - 34 359 738 367 SUPPLIED/],,
[ASCIZ /ILLEGAL USE OF RESERVED WORD/] ; 129
[ASCIZ /IMPROPER WORD DELIMITER/],,
[0] ; [273] 131
; "BMOVE" WITH "RLIST" AS ITS PARAMETER IS USED TO INITIALIZE
; THE READ MODULE'S LOW-SEGMENT FROM THE HIGH-SEGMENT.
RLIST:
XWD FAILX,12
PUSH SP,A1
PUSH SP,A2
MOVE A1,@-2(SP)
MOVEM A1,FAILX1
PUSHJ SP,.FAIL
0
POP SP,A2
POP SP,A1
; GENERAL SKIP RETURN
SKRET: AOS (SP)
POPJ SP,
XWD .STOVE+1,1
JRST OVFL5
XWD .JBAPR,1
JRST OVFL4
XWD OLIST,3
14
0
XWD BHEAD1,0
XWD LLIST,3
0
0
XWD BHEAD2,0
XWD SLIST,3
0
0
XWD 0,BHEAD3
XWD CSLIST,3
1
SIXBIT /TTY/
XWD STHEAD,CSHEAD
XWD SWERR,4
ASCIZ/ switch: /
XWD CREFRF,2
BYTE(7)1,0,0,0,0
0
XWD TRACLN,2
DEC 100
EXP DELTA1
0 ; TERMINATE LIST
SUBTTL OUTPUT MODULE
; THIS MODULE CONTAINS THE FOLLOWING ROUTINES
;
;
; .MABS (MOVE ABSOLUTE) WRITE OUT 1 WORD
; A1=VALUE
; NO RELOCATION
;
; .MREL (MOVE RELOCATED) WRITE OUT 1 WORD
; A1=VALUE
; RELOCATE RIGHT HALF
;
; .RAFIX (REL ADDRESS FIXUP) WRITE OUT 1 TYPE-10 FIXUP
; A1=CHAIN
; PROGRAM COUNTER=VALUE
; RELOCATE BOTH HALVES
;
; .ADRFIX (ADDRESS FIXUP) WRITE OUT 1 TYPE-10 FIXUP
; A1=CHAIN
; A2=VALUE
; RELOCATE BOTH HALVES
;
; .ABSFIX (ABSOLUTE FIXUP) WRITE OUT 1 TYPE-10 FIXUP
; A1=CHAIN
; A2=VALUE
; RELOCATE LEFT HALF (CHAIN)
;
; .FIX50 (RADIX50 FIXUP) WRITE OUT 1 TYPE-2 FIXUP
; A1=LOCATION
; A2=RADIX50 NAME
; RELOCATE LOCATION
;
; .EXTFIX (EXTERNAL FIXUP) WRITE OUT ALL TYPE-2 FIXUPS FOR 1 EXTERNAL
; PROCEDURE
; A5=ADDRESS OF SYMBOL TABLE ENTRY
;
; .ADDFIX (ADDITIVE FIXUP) WRITE OUT 1 TYPE-2 ADDITIVE FIXUP
; A1=LOCATION (RELOCATE)
; RADIX50 NAME IS ALWAYS %ALGDR
;
; .TYPE0 (BLOCK TYPE-0 ENTRY) WRITE OUT 1 TYPE-0 IDENTIFIER ENTRY
; WRITE1 OPEN REL-FILE
;
; WRITE0 CALLED IN PLACE OF WRITE1 WHEN THERE IS NO REL-FILE
;
; .PROGD PREPARE TO COMPILE A MAIN PROGRAM
;
; .PROCD PREPARE TO COMPILE AN EXTERNAL PROCEDURE
;
; BMOVE MOVE BLOCKS OF DATA ACCORDING TO A LIST
; A1=LIST
;
; .ZZEND MOVE CONSTANTS TABLE TO REL-FILE,
; MOVE FIXUP TABLE TO REL-FILE,
; MOVE LIBRARY FIXUPS TO REL-FILE,
; PUT AN END BLOCK IN REL-FILE,
; CLOSE REL-FILE.
;
; DUMP REL-FILE DUMP PROGRAM
;
; NAME EXTRACT FROM SYMBOL TABLE ENTRY THE IDENTIFIER NAME
; IN ASCIZ FORMAT
INTERN .PROGD
INTERN .PROCD
INTERN .RAFIX ; RELOCATABLE FIX-UP ROUTINE
INTERN .ADRFIX ; ADDRESS FIX-UP ROUTINE
INTERN .ABSFIX ; ABSOLUTE FIX-UP ROUTINE
INTERN .ADDFIX ; ADDITIVE FIX-UP ROUTINE
INTERN .EXTFIX ; EXTERNAL NAME FIX-UP ROUTINE
INTERN .FIX50 ; EXTERNAL NAME FIX-UP ROUTINE (RADIX50 INPUT)
INTERN .MREL ; MOVE RELOCATABLE
INTERN .MABS ; MOVE ABSOLUTE
INTERN .ZZEND ; WRITE MODULE PROGRAM END ROUTINE
EXTEN==400000 ; EXTENDED ENTRY FLAG BIT
EXISTS==400000 ; 1 = LISTING FILE EXISTS
COMPLETE==002000 ; 1 = LISTING FILE COMPLETE AND CLOSED
IND==0
ADR==1
PTR==2
BLK==3
EN==4
TYP==5
LEN==6 ;
; INITIALIZE WRITE MODULE, CREATE REL-FILE, PREPARE TO RECEIVE OUTPUT.
WRITE1: OPEN 1,OLIST ; OPEN THE OBJECT FILE
JRST DSERR5 ; CANNOT OPEN DEVICE
OUTBUF 1,@OLIST+7 ; GET A BUFFER RING
ENTER 1,OFILE ; ENTER THE NEW FILE
JRST DSERR6 ; -CANNOT CREATE NEW FILE
PUSHJ SP,WRITE ; INITIALIZE BUFFERS
OUT 1,0 ; GET 1ST OUTPUT BUFFER
JRST .+2 ; -OK
JRST DSERR7 ; ERROR
MOVEI A1,1 ; A 1 MEANS TO OUTPUT OBJECT CODE
MOVEM A1,WFLAG ; SET WRITE MODULE FLAG
JRST SKRET ; EXIT WRITE1
; INITIALIZE WRITE MODULE, DON'T CREATE REL-FILE, PREPARE TO
; RECEIVE OUTPUT.
WRITE0: MOVEI A1,203 ; ALLOCATE A DUMMY BUFFER WHOSE LENGTH
PUSHJ SP,ALLOCATE ; IS 203
ADDI A1,1 ; STEP TO LINK WORD
HRRZM A1,BHEAD1 ; SET BUFFER HEADER
HRLI A1,202 ; BUFFER LENGTH
MOVEM A1,(A1) ; PUT BUFFER RING LINK IN BUFFER
PUSHJ SP,WRITE ; INITIALIZE BUFFERS
SETZM WFLAG ; MARK: NO REL FILE
POPJ SP, ; EXIT WRITE0
; "WRITE" IS CALLED BY "WRITE0" AND "WRITE1". "WRITE" ALLOCATES
; SPACE FOR THE ISOLATED BUFFERS, AND SETS UP ALL OF THE STATUS BLOCKS.
; SET STATUS BLOCKS FROM HIGH SEGMENT
WRITE: HRLZI A1,A3 ; ADDRESS OF A3
MOVEM A1,T0ADR ; INIT T0ADR
MOVEM A1,T1ADR ; INIT T1ADR
MOVEM A1,T2ADR ; INIT T2ADR
MOVEM A1,T10ADR ; INIT T10ADR
HRLZI A1,440200 ; LEFT HALF OF BYTE POINTERS
MOVEM A1,T1PTR ; INIT T1PTR
MOVEM A1,T10PTR ; INIT T10PTR
HRLZI A1,440400 ; LEFT HALF OF TYPE-2 BYTE POINTER
MOVEM A1,T2PTR ; INIT T2PTR
MOVEI A1,2 ; 2
MOVEM A1,T2TYP ; INIT T2TYP
MOVEI A1,1 ; 1
MOVEM A1,T1TYP ; INIT T1TYP
MOVEI A1,NEWT0 ;
MOVEM A1,T0TYP ;
MOVE A2,BHEAD1 ; GET BUFFER ADDRESS
HLRZ A2,(A2) ; GET LENGTH OF BUFFER
SUBI A2,1 ; TRUE USABLE LENGTH
MOVEM A2,BUFLEN ; SAVE THE OUTPUT BUFFER LENGTH
; ACQUIRE SPACE FOR TYPE-2 BUFFER, INITIALIZE ITS STATUS BLOCK
MOVEI A1,600 ; BUFFERS MIGHT USE UP TO #600 WORDS
PUSHJ SP,ALLOCATE ; GET SPACE FOR BUFFERS
EXCH A1,A2 ; SWAP REGS, IE A1=BASE ADDR, A2=LENGTH
MOVEI A3,(A2) ; BUFFER FOR TYPE-2 BLOCKS
ADDI A2,-1(A1) ; STEP POINTER
MOVEM A2,T2END ; MARK END OF TYPE-2 BUFFER
MOVEI A4,TYPE2 ; PARAM FOR INITB
MOVEI A5,^D19 ; LENGTH OF MOST SUB-BLOCKS
MOVEM A5,T2LEN ;
PUSHJ SP,INITB ; INITIALIZE TYPE-2 STATUS BLOCK
; ACQUIRE SPACE FOR TYPE-10 BUFFER, INITIALIZE ITS STATUS BLOCK
MOVEI A3,1(A2) ; BUFFER FOR TYPE-10 BLOCKS
ADD A2,A1 ; STEP POINTER
MOVEM A2,T10END ; MARK END OF TYPE-10 BUFFER
MOVEI A4,TYPE10 ; PARAM FOR INITB
MOVEM A5,T10LEN ;
PUSHJ SP,INITB ; INITIALIZE TYPE-10 STATUS BLOCK
; ACQUIRE SPACE FOR TYPE-0 BUFFER, INITIALIZE ITS STATUS BLOCK
MOVEI A3,1(A2) ; BUFFER FOR TYPE-0 BLOCKS
ADD A2,A1 ; STEP POINTER
MOVEM A2,T0END ; MARK END OF TYPE-0 BUFFER
MOVEI A4,TYPE0 ; PARAM FOR INITB
MOVEI A6,^D127 ; LONG 'SUB'-BLOCK FOR PSEUDO-TYPE0
MOVEM A6,T0LEN ;
PUSHJ SP,INITB ; INITIALIZE TYPE-0 STATUS BLOCK
ADDI A2,1 ; NEW BEGINNING OF FREE SPACE
HRRM A2,.JBFF ; SET JOBFF
; INITIALIZE TYPE-1 STATUS BLOCK
HRRZ A3,BHEAD1 ; GET ADDRESS OF PRIME BUFFER
ADDI A3,1 ; STEP TO NEXT WORD
HRRM A3,T1ADR ; SET T1ADR
ADD A3,A1 ; STEP TO END OF BUFFER
MOVEM A3,T1END ; SET END OF BUFFER
MOVEM A5,T1LEN ;
POPJ SP, ; EXIT WRITE
; CANT OPEN OBJECT FILE DEVICE
DSERR5: MOVE A1,[ ; LOAD A POINTER TO
POINT 6,OLIST+1] ; THE FILE NAME
JRST DSERR0 ; PRINT THE MESSAGE, TERMINATE
; CANNOT CREATE REL-FILE
DSERR6: OUTSTR UNOBJ ; PRINT MSG
JRST TERMIN ; TERMINATE COMPILATION
UNOBJ: ASCIZ /?CANNOT CREATE OBJECT FILE
/
; ERROR ON "OUT" UUO
DSERR7: OUTSTR UNEXP ; PRINT ERROR MSG
JRST TERMIN ; TERMINATE
UNEXP: ASCIZ /OUTPUT ERROR
/
; "BMOVE" WILL MOVE BLOCKS OF DATA AROUND IN CORE ACCORDING TO A
; CONTROL LIST WHOSE ADDRESS IS IN A1. THE FIRST WORD OF THE CONTROL
; LIST IS A CONTROL WORD WHOSE LEFT HALF CONTAINS THE LOCATION
; WHERE THE DATA WILL GO, AND WHOSE RIGHT HALF CONTAINS THE LENGTH OF
; THE BLOCK OF DATA IN WORDS. THE CONTROL WORD IS FOLLOWED IMMEDIATELY
; BY THE BLOCK OF DATA THAT IS TO BE MOVED. THE BLOCK OF DATA IS
; FOLLOWED IMMEDIATELY BY ANOTHER CONTROL WORD AND ANOTHER BLOCK TO
; BE MOVED, ETC. THE CONTROL LIST IS TERMINATED BY AN ALL ZERO
; CONTROL WORD.
BMOVE: SKIPN A2,(A1) ; IF NO MORE BLOCKS THEN
POPJ SP, ; EXIT BMOVE
MOVS A3,A2 ; "TO" ADDRESS TO A3
HRLI A3,1(A1) ; "FROM" ADDRESS
MOVS A4,A2 ; "TO" ADDRESS PLUS
ADD A4,(A1) ; LENGTH OF BLOCK
ADDI A1,1(A2) ; "END" ADDRESS PLUS 1
BLT A3,-1(A4) ; MOVE THE DATA
JRST BMOVE ; PROCESS ANOTHER BLOCK
;
; These are the patterns for the LINK blocks
; output at the beginning of the program. They are
; BLT'd to the low segment before data is written
; in them.
;
XWD LB,WRITE4-WRITE3+1
WRITE3: XWD 0,WRITE4-WRITE3-1
XWD 4,0 ; TYPE-4 BLOCK OF LENGTH 0
XWD 0,0 ; RELOCATION BITS
XWD 6,2 ; TYPE-6 BLOCK OF LENGTH 2
XWD 0,0 ; RELOCATION BITS
PRNAME: RADIX50 0,ALGOBJ ; PROGRAM NAME
XWD 3,1 ; ALGOL, 1 FLAGS MAIN PROGRAM
EDIT(140); Use compiler Version number as program version number
XWD 1,2 ; [E140] Type-1 block of length 2
XWD 0,0 ; [E140] No relocation bits
PRGVER: EXP .JBVER ; [E140] Version word (in JOBDAT)
EXP 0 ; [E140] Fill value in later
XWD 2,20 ; TYPE-2 BLOCK OF LENGTH 16
XWD 040000,0 ; RELOCATION BITS
RADIX50 04,%BEGIN ; PROGRAM ENTRY POINT
XWD 0,0 ; VALUE
RADIX50 60,%ALGDA ; %ALGDA
XWD 0,0 ; NO VALUE
DIR: RADIX50 60,%ALGDR ; %ALGDR
XWD 0,0 ; NO USAGE
HEAP: RADIX50 04,%HEAP ; %HEAP DEFINITION
XWD 0,0 ; VALUE
FLAGS: RADIX50 04,%FLAGS
XWD 0,0 ; RUN-TIME FLAGS
TRACE: RADIX50 04,%TRACE ;
XWD 0,0
VERLHS: RADIX50 04,%JBVER
EXP 0 ; LEFT HALF OF VERSION #
VERRHS: RADIX50 04,%JBEDT
EXP 0 ;
WRITE4: 0
0
MODHDR==SIXBIT/MOD/
WRITE7: XWD LB+WRITE4-WRITE3,14
MODBL: XWD NEWT0,12 ;
EXP MODHDR+12 ; ACTUAL BLOCK HEADER
BLOCK 11
0
0
; ".PROGD" MOVES THE TYPE-4,-6, -2 AND TYPE0 BLOCKS
; THAT START EACH ALGOL MAIN PROGRAM
; TO THE PRIME BUFFER.
.PROGD: MOVEI A1,WRITE3-1 ; PARAM FOR INIT
PUSHJ SP,BMOVE ; MOVE CODE TO BUFFER
TRNE FL,TRPOFF ; UNLESS PRODUCTION
JRST PD1
MOVEI A1,WRITE7 ; TYPE-0 MODULE HEADER
PUSHJ SP,BMOVE ; TO LOW SEGMENT
MOVEI A1,13 ; EXTRA LENGTH
ADDM A1,LB
PD1: HRLZI A1,<<2B23>+3> ; KI-10 ALGOL INDICATOR
HLLM A1,<LB+PRNAME+1-WRITE3>
HRRZ A1,T1ADR ; BEGINNING OF AVAILABLE SPACE IN BUFFER
ADDI A1,1 ; TRUE BEGINNING
MOVEI A5,(A1) ; SAVE FOR LATER IN A5
HRLM A1,LB ; SET DESTINATION PART OF CONTROL WORD
ADDI A1,WRITE4-WRITE3-2
; END OF WHERE THIS BLOCK WILL BE
TRNN FL,TRPOFF ; ADJUST IF NOT PRODUCTION [54]
ADDI A1,13 ; TO INCLUDE MODULE HEADER [54]
CAMG A1,T1END ; IF ENOUGH SPACE IN BUFFER
JRST .+3 ; THEN USE THIS BUFFER
PUSHJ SP,GETBUF ; ELSE GET ANOTHER OUTPUT BUFFER
JRST PD1 ; AND TRY AGAIN
HRRM A1,T1ADR ; SET NEW T1ADR
MOVEI A1,LB ; ADDRESS OF NEW BMOVE LIST
PUSHJ SP,BMOVE ; MOVE INTO FINAL POSITION
MOVE A2,TRACLN ; LENGTH OF TRACE-BUFFER (/T SW)
MOVEM A2,TRACE-WRITE3(A5) ;
MOVE A2,DYNOWN ; LENGTH OF HEAP (/HEAP SWITCH)
CAIGE A2,DELTA1 ; ENSURE IT'S AT LEAST...
MOVEI A2,DELTA1 ; ...THE MINIMUM
MOVEM A2,HEAP-WRITE3(A5)
SETZM A2,FLAGS-WRITE3(A5)
SKIPN A1,OFILE ; GET OBJECT FILE NAME
SKIPA A2,PRNAME ; NONE - USE DEFAULT
PUSHJ SP,RADX50 ; CONVERT TO RADIX50
MOVEM A2,PRNAME-WRITE3-1(A5) ; PUT IN BUFFER
MOVE A1,.JBVER ; LINK-PLANTED VERSION NUMBER
MOVEM A1,PRGVER-WRITE3(A5) ; Save as program version number
HLRZM A1,VERLHS-WRITE3(A5)
HRRZM A1,VERRHS-WRITE3(A5)
TRNE FL,TRPOFF ; ONLY IF REQUIRED
JRST WRITE2
TLZ A2,740000 ; CLEAR CODE BITS
IDIVI A2,50 ; RIGHT-
JUMPE A3,.-1 ; JUSTIFY
IMULI A2,50 ; RADIX-50
ADDI A2,(A3) ; NAME.
MOVEM A2,MODBL-1-WRITE3(A5) ; PUT MODULE TITLE IN BLOCK
MOVE A2,SLIST+1 ; SOURCE DEVICE
MOVEM A2,MODBL+2-WRITE3(A5) ;
MOVE A2,LINENO ; CURRENT LINE NUMBER
MOVEM A2,MODBL-2-WRITE3(A5) ;
HRLI A5,SFILE ; FILE INFO
MOVEI A1,MODBL-WRITE3+6(A5) ; END OF FILE INFO
ADDI A5,MODBL+3-WRITE3
BLT A5,(A1) ; ALL TO TYPE0-BLOCK
JRST WRITE2 ; CONTINUE
;------------------------------------------------
XWD LB,WRITE6-WRITE5+1
WRITE5: XWD 0,WRITE6-WRITE5-1
XWD 4,1 ; TYPE-4 BLOCK OF LENGTH 1
XWD 0,0 ; RELOCATION BITS
PNAME1: XWD 0,0 ; PROCEDURE NAME
XWD 6,2 ; TYPE-6 BLOCK OF LENGTH 2
XWD 0,0 ; RELOCATION BITS
PNAME2: XWD 0,0 ; PROCEDURE NAME
XWD 3,0 ; ALGOL
XWD 2,2 ; TYPE-2 BLOCK OF LENGTH 2
XWD 040000,0 ; RELOCATION BITS
PNAME3: XWD 0,0 ; PROCEDURE ENTRY POINT NAME
PVALUE: XWD 0,0 ; VALUE
WRITE6: 0
0
WRITE8: XWD LB+WRITE6-WRITE5,14
EMODBL: XWD NEWT0,12 ; SUBSEQUENT MODULES
EXP MODHDR+12 ;
BLOCK 11 ;
0
0
; ".PROCD" MOVES TO THE PRIME BUFFER THE TYPE-4,-6, AND -2 BLOCKS
; THAT START EACH ALGOL EXTERNAL PROCEDURE.
.PROCD: MOVEI A1,WRITE5-1 ; PARAM FOR INIT
PUSHJ SP,BMOVE ; MOVE CODE TO BUFFER
TRNE FL,TRPOFF ; UNLESS PRODUCTION
JRST PD2
MOVEI A1,WRITE8 ; LENGTH/DESTN FOR BMOVE
PUSHJ SP,BMOVE
MOVEI A1,13 ; EXTRA LENGTH
ADDM A1,LB
PD2: HRLZI A1,<<2B23>+3> ; KI-10 ALGOL INDICATOR
MOVEM A1,<LB+PNAME2+1-WRITE5>
HRRZ A1,T1ADR ; BEGINNING OF AVAILABLE SPACE IN BUFFER
ADDI A1,1 ; TRUE BEGINNING
PUSH SP,A1 ; SAVE ON STACK FOR LATER
HRLM A1,LB ; SET DESTINATION PART OF CONTROL WORD
ADDI A1,WRITE6-WRITE5-2 ; END OF WHERE THIS BLOCK WILL BE
TRNN FL,TRPOFF ; IF NOT PRODUCTION...
ADDI A1,13 ; ...INCLUDE EXTRA PIECE.
CAMG A1,T1END ; IF THERE IS ENOUGH SPACE IN BUFFER
JRST .+4 ; THEN USE THIS BUFFER
POP SP,A1 ; ELSE LOSE STACKED A1
PUSHJ SP,GETBUF ; AND GET ANOTHER OUTPUT BUFFER
JRST PD2 ; AND TRY AGAIN
HRRM A1,T1ADR ; SET NEW T1ADR
MOVEI A1,LB ; ADDRESS OF NEW BMOVE LIST
PUSHJ SP,BMOVE ; MOVE INTO FINAL POSITION
HRRZ A5,NSYM ; GET ADDR OF BUFFER CONTAINING PROCEDURE NAME
SUBI A5,2 ; MAKE LOOK LIKE SYMBOL TABLE ENTRY
PUSHJ SP,PULL50 ; CONVERT NAME IN ENTRY TO RADIX50
POP SP,A3 ; ADDRESS OF MOVED BLOCK
MOVEM A2,PNAME1-WRITE5-1(A3) ; PUT NAME IN BUFFER
MOVEM A2,PNAME2-WRITE5-1(A3) ; PUT NAME IN BUFFER
TLO A2,040000 ; CODE 04
MOVEM A2,PNAME3-WRITE5-1(A3) ; PUT NAME IN BUFFER
TRNE FL,TRLOFF ; /PRODUCTION ?
JRST WRITE2 ; YES - IMPLIES /NOSYMBOLS
PUSH SP,A2 ; NO - REMEMBER A2
MOVE A1,NSYM ; GET SYMBOL BUFFER ADDRESS
MOVE A1,(A1) ; GET FIRST WORD
ANDI A1,77 ; GET LENGTH IN CHARS - 1
ADDI A1,6+6+2+5 ; LENGTH+1 + ROUNDING + PROFILE & SIZE
IDIVI A1,6 ; GET NUMBER OF SIXBITZ WORDS
MOVEM A1,PVALUE-WRITE5-1(A3) ; SET VALUE WORD
POP SP,A2 ; RESTORE NAME
TRNE FL,TRPOFF ;
JRST WRITE2
TLZ A2,740000 ; CLEAR CODE BITS
MOVEM A2,EMODBL-1-WRITE5(A3) ; PUT MODULE TITLE IN.
MOVE A2,SLIST+1 ; SOURCE DEVICE
MOVEM A2,EMODBL+2-WRITE5(A3) ;
MOVE A2,LINENO ;
MOVEM A2,EMODBL-2-WRITE5(A3) ;
ADDI A3,EMODBL+3-WRITE5
HRLI A3,SFILE ; SOURCE FILE INFO
MOVEI A1,3(A3) ;
BLT A3,(A1) ;
; "WRITE2" IS CALLED BY ".PROGD" AND ".PROCD". "WRITE2" WILL PUT
; THE PROGRAM COUNTER (RA) INTO THE 1ST DATA WORD OF A NEW TYPE-1
; LOADER BLOCK.
WRITE2: PUSHJ SP,FIN1 ; INITIALIZE PRIME BUFFER
MOVEI A4,TYPE1 ; INITIALISE TYPE-1 BLOCK
PUSHJ SP,INITB
AOS A3,T1IND ; GET INDEX
SETZM @T1ADR ; SET START ADDRESS
MOVEI A3,1 ; RELOCATE RIGHT HALF
IDPB A3,T1PTR ; SET RELOCATION BITS
MOVEI A4,10 ; THIS BUFFER IS FOR
MOVEM A4,T10TYP ; TYPE-10 BLOCKS
POPJ SP, ; EXIT .PROGD OR .PROCD
; "PULL50" WILL EXTRACT THE RADIX50 NAME OF AN IDENTIFIER FROM THE
; SYMBOL TABLE ENTRY. A5 SHOULD CONTAIN THE ADDRESS OF THE SYMBOL TABLE
; ENTRY. THE OUTPUT IS IN A2, RIGHT-JUSTIFIED.
PULL50: MOVEI A1,0 ; CLEAR A1
MOVE A2,2(A5) ; GET 1ST WORD OF NAME
MOVEI A3,(A2)
ANDI A3,77 ; #CHARS.-1
MOVEI A4,(A3)
IMULI A4,6 ; COPY*6
CAIGE A3,5 ; IF THERE ARE LESS THAN 6 CHARS
JRST IDL ; THEN SKIP THIS PART
MOVE A1,3(A5) ; PICK UP 2ND WORD
CAIGE A3,^D10 ; IF THERE ARE LESS THAN 11 CHARS
ROT A1,-^D24(A4) ; SHIFT AROUND 6TH CHAR.
ANDI A1,77
XORI A1,40 ; CONVERT TO PROPER SIXBIT
MOVEI A3,4 ; RESET CHAR COUNT
MOVEI A4,^D30 ; SET UP FINAL SHIFT
IDL: ROT A1,-^D12 ; MOVE LAST CHAR TO LEFT SIDE OF A1
LSHC A1,6 ; MOVE NEXT CHAR INTO A1
XORI A1,40 ; CONVERT TO PROPER SIXBIT
SOJGE A3,IDL ; LOOP TILL DONE
ROT A1,(A4) ; RESULT
; "RADX50" WILL CONVERT THE SIXBIT NAME IN A1 TO RADIX50, AND
; OUTPUT THE RESULT IN A2, LEFT-JUSTIFIED.
RADX50: MOVEI A2,0 ; CLEAR A2
MOVEI A3,6 ; SCAN 6 CHARS
MOVE A6,[ ; LOAD A POINTER TO
POINT 6,A1] ; A1
RADIXL: IMULI A2,50 ; MULTIPLY CHAR BY 50
ILDB A4,A6 ; GET NEXT CHAR
JUMPE A4,.+5 ; SKIP IF A NULL CHAR
CAILE A4,40 ; IF THIS IS A LETTER
SUBI A4,7 ; THEN SUB 7
SUBI A4,17 ; CONVERT TO SPECIAL SIXBIT
ADDI A2,(A4) ; ADD INTO PREVIOUS RESULT
SOJG A3,RADIXL ; LOOP
POPJ SP, ; EXIT RADX50
RELOC
WFLAG: BLOCK 1 ; WRITE MODULE FLAG
A1SAV: BLOCK 1 ; SAVE AREA FOR .TYPE0 ACS
A2SAV: BLOCK 1 ; SAVE AREA FOR A2
A4SAV: BLOCK 1 ; SAVE AREA FOR A4
A5SAV: BLOCK 1 ; SAVE AREA FOR A5
A6SAV: BLOCK 1 ; SAVE AREA FOR A6
BUFLEN: BLOCK 1 ; OUTPUT BUFFER LENGTH
WINDEX: BLOCK 1 ; WORD INDEX
TRACLN: BLOCK 1
; ^D100 ; TRACE BUFFER LENGTH (/T SW)
DYNOWN: BLOCK 1 ; LENGTH OF HEAP (/HEAP SWITCH)
;
; TERMINOLOGY
;
;
; LOADER SUB-BLOCK: A WORD OF RELOCATION BITS FOLLOWED BY UP
; TO 18 DATA WORDS.
;
;
; LOADER BLOCK: A DESCRIPTOR WORD FOLLOWED BY ANY NUMBER
; OF LOADER SUB-BLOCKS. ONLY THE LAST SUB-BLOCK
; MAY CONTAIN LESS THAN 18 DATA WORDS.
;
;
; DESCRIPTOR WORD: LEFT HALF CONTAINS LOADER BLOCK TYPE.
; RIGHT HALF CONTAINS THE NUMBER OF DATA WORDS
; IN THE LOADER BLOCK. NOTE THAT THIS NUMBER
; DOES NOT INCLUDE THE DESCRIPTOR WORD OR ANY
; RELOCATION BITS WORDS.
;
;
; BUFFER: A BLOCK OF 200 (OCTAL) WORDS THAT CAN RECIEVE
; OUTPUT.
;
;
; RING BUFFER: A BUFFER, AS DEFINED ABOVE, THAT IS INCLUDED
; IN AN OUTPUT BUFFER-RING ACCEPTABLE TO THE
; OPERATING SYSTEM.
;
;
; BUFFER-RING: A RING OF RING BUFFERS.
;
;
; ISOLATED BUFFER: A BUFFER THAT IS NOT A RING BUFFER. ANY OUTPUT
; DATA THAT IS PLACED IN AN ISOLATED BUFFER
; MUST EVENTUALLY BE MOVED TO A RING BUFFER.
;
;
; PRIME BUFFER: THROUGHOUT MOST OF THE COMPILATION, TYPE-1, TYPE-2,
; TYPE-10, AND TYPE-0 DATA IS PRODUCED SIMULTANEOUSLY.
; BUT DUE TO THE INGENIOUS DESIGN OF THE BUFFER-RING
; CONCEPT IT IS ONLY POSSIBLE TO FILL ONE RING BUFFER
; AT A TIME. THEREFORE TYPE-1 DATA IS PLACED IN THE
; AVAILABLE RING BUFFER, AND THE TYPE-2, TYPE-10, AND TYPE-0
; DATA ARE PLACED IN THREE ISOLATED BUFFERS. WE SHALL
; CALL THE AVAILABLE RING BUFFER THE "PRIME BUFFER".
; STATUS BLOCK THIS MODULE CONTAINS GENERALIZED ROUTINES
; THAT CAN OPERATE ON ANY BUFFER. THE INPUT
; PARAMETER TO THESE ROUTINES IS THE ADDRESS
; OF A "STATUS BLOCK". A STATUS BLOCK IS A BLOCK
; OF WORDS THAT DESCRIBES THE CURRENT STATUS OF THE
; BUFFER. A STATUS BLOCK HAS THE FOLLOWING FORMAT:
;
;
; STATUS BLOCK FORMAT:
;
; WORD 0 (T#IND) LOADER SUB-BLOCK INDEX. THIS WORD NORMALLY
; INDEX WORD CYCLES FROM -18 TO 0. WHEN IT BECOMES +1
; IT IS TIME TO CALL THE ROUTINE "GET" WHICH
; SETS UP THE BUFFER FOR ANOTHER SUB-BLOCK.
; IF, FOR EXAMPLE, "GET" FINDS THAT THERE ARE
; ONLY 7 UNUSED WORDS AT THE END OF THE BUFFER,
; THEN IT WILL SET UP THIS WORD TO CYCLE FROM
; -7 TO 0.
;
;
; WORD 1 (T#ADR) BUFFER POINTER. THE RIGHT HALF OF THIS WORD
; ADDRESS WORD POINTS TO THE EVENTUAL LAST WORD OF THE SUB-BLOCK
; THAT IS BEING FILLED. THE LEFT HALF ALWAYS
; CONTAINS A3. THEN A DATA WORD IS MOVED INTO
; A SUB-BLOCK BY THE FOLLOWING SEQUENCE:
;
; AOSLE A3,T#IND ; STEP AND FETCH THE INDEX
; PUSHJ SP,T#GET ; -NO ROOM IN SUB-BLOCK, CALL GET
; MOVEM A1,@T#ADR ; MOVE DATA WORD INTO SUB-BLOCK
;
;
; WORD 2 (T#PTR) RELOCATION BITS BYTE POINTER. THE RELOCATION
; POINTER WORD BITS ARE INSERTED INTO THE RELOCATION WORD
; USING AN IDPB WITH THIS BYTE POINTER.
;
;
; WORD 3 (T#BLK) THIS WORD POINTS TO THE DESCRIPTOR WORD OF
; BLOCK START OF THE LOADER BLOCK IN THE BUFFER. AFTER
; THE BUFFER IS FILLED THE DESCRIPTOR WORD IS
; SET BY THE SEQUENCE:
;
; (USED LENGTH OF BUFFER) := T#ADR+T#IND-T#BLK ;
; @T#BLK := (USED LENGTH OF BUFFER)-(USED LENGTH OF BUFFER)/19 ;
;
;
; WORD 4 (T#END) THIS WORD POINTS TO THE LAST USABLE WORD
; BUFFER END OF THE BUFFER.
;
;
; WORD 5 (T#TYP) THIS WORD CONTAINS THE LOADER BLOCK TYPE FOR
; BLOCK TYPE WHICH THIS BUFFER IS BEING USED.
; IF AT ANY TIME "GET" DETECTS THAT ANY OF THESE BUFFERS IS FULL,
; "GET" WILL CALL "FIN". "FIN" WILL USE "MOVBLK" TO MOVE THE TYPE-2, TYPE-0
; AND TYPE-10 LOADER BLOCKS FROM THE ISOLATED BUFFERS TO THE PRIME
; BUFFER (AND IN THE PROCESS DO OUT UUO'S WHENEVER THE PRIME BUFFER
; BECOMES FULL). "FIN" WILL THEN USE "INITB" TO INITIALIZE EACH OF
; THE BUFFERS FOR MORE OUTPUT.
; ********* STATUS BLOCKS *********
TYPE1:
T1IND: BLOCK 1 ; INDEX
T1ADR: BLOCK 1 ; (A3) ADDRESS POINTER
T1PTR: BLOCK 1
; XWD 440200,0 ; POINTER TO RELOCATION BITS
T1BLK: BLOCK 1 ; LOCATION OF LOADER BLOCK
T1END: BLOCK 1 ; END OF THAT BUFFER
T1TYP: BLOCK 1 ; TYPE 1
T1LEN: BLOCK 1 ; LENGTH
TYPE2:
T2IND: BLOCK 1 ; -^D18 ; INDEX
T2ADR: BLOCK 1 ; (A3) ; ADDRESS POINTER
T2PTR: BLOCK 1
; XWD 440400,0 ; POINTER TO RELOCATION BITS
T2BLK: BLOCK 1 ; LOCATION OF LOADER BLOCK
T2END: BLOCK 1 ; END OF THAT BUFFER
T2TYP: BLOCK 1 ; TYPE 2
T2LEN: BLOCK 1 ; LENGTH
TYPE10:
T10IND: BLOCK 1 ; -^D18 ; INDEX
T10ADR: BLOCK 1 ; (A3) ; ADDRESS POINTER
T10PTR: BLOCK 1
; XWD 440200,0 ; POINTER TO RELOCATION BITS
T10BLK: BLOCK 1 ; LOCATION OF LOADER BLOCK
T10END: BLOCK 1 ; END OF THAT BUFFER
T10TYP: BLOCK 1 ; TYPE 10
T10LEN: BLOCK 1 ; LENGTH
T1000S:
; *** All headers for new block-types (type .GE. 1000) must follow this label.
TYPE0:
T0IND: BLOCK 1 ; -^D126. ; INDEX
T0ADR: BLOCK 1 ; (A3) ; ADDRESS POINTER
T0PTR: BLOCK 1 ; POINTER TO RELOCATION BITS (UNUSED)
T0BLK: BLOCK 1 ; LOCATION OF LOADER BLOCK
T0END: BLOCK 1 ; END OF THAT BUFFER
T0TYP: BLOCK 1 ; TYPE 0
T0LEN: BLOCK 1 ; LENGTH
TYPE15=TYPE10
T15IND=T10IND
T15ADR=T10ADR
T15PTR=T10PTR
T15BLK=T10BLK
T15END=T10END
T15TYP=15
NEWT0==1044 ; BLOCK TYPE FOR ALGOL SYMBOLS
RELOC
; ********* OUTPUT ROUTINES *********
;--------------------------------------------------------------
.MABS: AOSLE A3,T1IND ; FETCH THE INDEX AND STEP IT
PUSHJ SP,T1GET ; -AT END OF 18-WORD BLOCK
MOVEM A1,@T1ADR ; STORE THE WORD IN THE BUFFER
IBP T1PTR ; RELOCATION BITS ARE ZERO
MABS1: AOS RA ; STEP PROGRAM COUNTER
POPJ SP, ; EXIT .MABS
;--------------------------------------------------------------
.MREL: TRNN A1,777777 ; IF RIGHT HALF OF T IS ZERO
JRST .MABS ; THEN DO A MABS
.MREL0::AOSLE A3,T1IND ; STEP AND FETCH WORD INDEX
PUSHJ SP,T1GET ; -END OF SUB-BLOCK
MOVEM A1,@T1ADR ; STORE THE WORD IN THE BUFFER
MOVEI A3,1 ; RELOCATE RIGHT HALF
IDPB A3,T1PTR ; SET RELOCATION BITS
JRST MABS1 ; EXIT .MREL
;--------------------------------------------------------------
.RAFIX: TRNN A1,777777 ; IF RIGHT HALF ZERO
POPJ SP, ; THEN DO NOTHING
AOSLE A3,T10IND ; STEP AND FETCH WORD INDEX
PUSHJ SP,T10GET ; -END OF SUB-BLOCK
HRL A1,RA ; THE VALUE IS THE CURRENT PROGRAM COUNTER
RAFIX1: MOVSM A1,@T10ADR ; STORE THE WORD IN THE BUFFER
MOVEI A3,3 ; RELOCATE BOTH HALVES
IDPB A3,T10PTR ; SET THE RELOCATION BITS
POPJ SP, ; EXIT .RAFIX
;--------------------------------------------------------------
.ADRFIX:
TRNN A1,777777 ; IF RIGHT HALF ZERO
POPJ SP, ; THEN DO NOTHING
AOSLE A3,T10IND ; STEP AND FETCH WORD INDEX
PUSHJ SP,T10GET ; -END OF SUB-BLOCK
HRL A1,A2 ; PUT VALUE WITH BACK-CHAIN POINTER
JRST RAFIX1 ; EXIT .ADRFIX
;--------------------------------------------------------------
.ABSFIX:
TRNN A1,777777 ; IF RIGHT HALF ZERO
POPJ SP, ; THEN DO NOTHING
AOSLE A3,T10IND ; STEP AND FETCH WORD INDEX
PUSHJ SP,T10GET ; -END OF SUB-BLOCK
HRL A2,A1 ; PUT VALUE WITH BACK-CHAIN POINTER
MOVEM A2,@T10ADR ; PUT WORD INTO BUFFER
MOVEI A3,2 ; RELOCATE THE LEFT HALF
IDPB A3,T10PTR ; SET RELOCATION BITS
POPJ SP, ; EXIT .ABSFIX
;--------------------------------------------------------------
.FIX50: TRNN A1,777777 ; IF RIGHT HALF ZERO
POPJ SP, ; THEN DO NOTHING
MOVEM A5,A5SAV ; SAVE A5
AOSLE A3,T2IND ; STEP AND FETCH WORD INDEX
PUSHJ SP,T2GET ; -END OF SUB-BLOCK
TLO A2,600000 ; INCLUDE THE CODE 60 INDICATOR
MOVEM A2,@T2ADR ; STORE THE WORD IN THE BUFFER
AOSLE A3,T2IND ; STEP AND FETCH THE WORD INDEX
PUSHJ SP,T2GET ; -END OF SUB-BLOCK
HRRZM A1,@T2ADR ; STORE THE WORD IN THE BUFFER
MOVE A5,A5SAV ; RESTORE A5
JRST .ADDF1 ; EXIT VIA ADDFIX
;--------------------------------------------------------------
.EXTFIX:
MOVEM A5,A5SAV ; SAVE A5 BECAUSE PULL50 WILL CLOBBER IT
PUSHJ SP,PULL50 ; EXTRACT NAME AND CONVERT TO RADIX50
MOVE A5,A5SAV ; RESTORE A5
MOVE A1,1(A5) ; LOAD VALUE FIELD OF ENTRY
PUSHJ SP,.FIX50 ; WRITE OUT THIS BACK-CHAIN POINTER
MOVE A3,(A5) ; GET 1ST WORD OF ENTRY
TLNN A3,EXTEN ; IF THIS IS NOT AN EXTENDED ENTRY
POPJ SP, ; THEN EXIT .EXTFIX
MOVE A3,2(A5) ; GET NAME WORD
ADDI A3,1 ; ADD 1 TO BYTE COUNT
ANDI A3,77 ; SAVE ONLY LENGTH BYTE
IDIVI A3,6 ; CONVERT TO A WORD COUNT
ADDI A3,3(A5) ; STEP TO EXTENSION
MOVE A1,(A3) ; GET 1ST WORD OF EXTENSION
JRST .FIX50 ; WRITE OUT THIS BACK-CHAIN POINTER, EXIT .EXTFIX
;--------------------------------------------------------------
.ADDFIX:
AOSLE A3,T2IND ; STEP AND FETCH WORD INDEX
PUSHJ SP,T2GET ; -END OF SUB-BLOCK
MOVE A2,DIR ; ADDITIVE FIX UP TO %ALGDR
MOVEM A2,@T2ADR ; STORE THE WORD IN THE BUFFER
AOSLE A3,T2IND ; STEP AND FETCH THE WORD INDEX
PUSHJ SP,T2GET ; -END OF SUB-BLOCK
HRLI A1,400000 ; INDICATE AN ADDITIVE FIX-UP
MOVEM A1,@T2ADR ; STORE THE WORD IN THE BUFFER
.ADDF1: MOVEI A3,1 ; RELOCATE RIGHT HALF OF SECOND WORD
IDPB A3,T2PTR ; SET THE RELOCATION BITS
POPJ SP, ; EXIT .ADDFIX
;--------------------------------------------------------------
.TYPE0::LDB A2,[POINT 6,2(A1),35] ; LENGTH IN CHARS
IDIVI A2,5 ; THEN WORDS
AOS A2 ; ADJUST
MOVNM A2,A1SAV ; SAVE IT FOR LOOP
ADDI A2,2 ; ADD EXTRA LENGTH
HRLI A2,'SYM' ; AND SET CODE
PUSHJ SP,MOVE0 ; ENTER IT
MOVE A2,1(A1) ; LEXEME,,VALUE
MOVE A4,FNLEVEL ;
SOJG A4,TYPE0A ; IF AT PL = 0
TLC A2,$EXT ; AND STATUS
TLZE A2,$STATUS ; .NE. EXTERNAL,
TLOA A2,$OWN ; FORCE $OWN
TLO A2,$EXT ; LEAVE $EXT ALONE !
TYPE0A: PUSHJ SP,MOVE0
PUSHJ SP,NAME ; CONVERT TO ASCII
HRL A1,A1SAV ; -VE LHS COUNT
HRRI A1,LB ; BEGINNING OF NAME
MOVE A2,(A1)
PUSHJ SP,MOVE0 ; TO BLOCK
AOBJN A1,.-2 ; REST OF NAME TOO
POPJ SP,
.PRSYM::LDB A2,[POINT 6,2(A1),35] ; GET LENGTH IN CHARS
IDIVI A2,5 ; THEN WORDS
AOS A2 ; AND ALLOW FOR EXTRA
MOVNM A2,A1SAV ; SAVE IT FOR LOOP
ADDI A2,2 ; ADD EXTRA LENGTH
HRLI A2,'SYM' ; SET CODE
PUSHJ SP,MOVE0 ; WRITE IT TO THE FILE
MOVE A2,A1 ; GET NEW LEXEME
TLZ A2,$PRO-$VAR ; CHANGE TYPE TO VARIABLE
TLZ A2,$STATUS ; AND STATUS TO SIMPLE
HRR A2,FNLEVEL ; RESULT IS AT FNLEVEL+1(DL)
AOJA A2,TYPE0A ; SO GO INSERT IN BUFFER
.BHDR:: PUSHJ SP,SNDSTN ; MAKE SURE STN ITEM IS SENT
MOVE A2,BHDR ; ALGOL BLOCK SYMBOL HEADER
PUSHJ SP,MOVE0
MOVE A2,BLOCKLEVEL
HRL A2,CURBLOCK ;
PUSHJ SP,MOVE0
MOVE A2,FNLEVEL
HRL A2,CURDLN
JRST MOVE0 ; EXIT VIA MOVE0
.SBHDR::PUSHJ SP,SNDSTN ; MAKE SURE STN ITEM IS SENT
MOVE A2,SBHDR ; BLOCK BEGIN ITEM
JRST MOVE0 ; EXIT VIA MOVE0
BLKH==SIXBIT/BLK/
BHDR: EXP BLKH+3
SBLKH==SIXBIT/BKS/
SBHDR: EXP SBLKH+1
.ESBLK::MOVE A2,CURDLN ; "END" STATEMENT - LINE NO IS DEL
MOVEM A2,CURSLN ; LINE NUMBER (END IS A DELIMITER)
.SNBLK::MOVE A2,RA ; GET ADDRESS.
CAME A2,LASTRA ; IS IT A NEW ADDRESS ?
PUSHJ SP,SNDSTN ; YES - OUTPUT OLD STN BLOCK
MOVE A2,RA ; THEN GET ADDRESS AGAIN
MOVEM A2,LASTRA ; REMEMBER FOR NEXT TIME
MOVE A2,CURSLN ; GET LINE NUMBER
MOVEM A2,SENDLN ; REMEMBER THIS ALSO
SETOM SENDSN ; SAY WE HAVE A BLOCK
POPJ SP, ; AND RETURN
SNDSTN: SKIPN SENDSN ; DO WE NEED TO SEND ONE ?
POPJ SP, ; NO - RETURN
SETZM SENDSN ; YES - SAY WE HAVE DONE SO
MOVE A2,SNHDR ; STATEMENT NUMBER BLOCK.
PUSHJ SP,MOVE0
MOVE A2,LASTRA ; PROGRAM COUNTER
PUSHJ SP,MOVE0
MOVE A2,SENDLN ; GET LINE NUMBER OF STATEMENT
CAMN A2,LSTSLN ; IF SAME AS LAST TIME, THEN
AOSA STMTNO ; INCREMENT STATEMENT WITHIN LINE
SETZM STMTNO ; OTHERWISE RESET TO 0
MOVEM A2,LSTSLN ; REMEMBER LINE NUMBER FOR NEXT TIME
HRL A2,STMTNO ; STATEMENT-WITHIN-LINE-#,,LINE-#
JRST MOVE0 ; TO .REL FILE & POPJ.
STMNTB==SIXBIT/STN/
SNHDR: EXP STMNTB+3
.MRK.0::PUSHJ SP,MRK.XX
.MRK.1::PUSHJ SP,MRK.XX
.MRK.2::PUSHJ SP,MRK.XX
.MRK.3::PUSHJ SP,MRK.XX
.MRK.4::PUSHJ SP,MRK.XX
.MRK.5::PUSHJ SP,MRK.XX
.MRK.6::PUSHJ SP,MRK.XX
.MRK.7::PUSHJ SP,MRK.XX
.MRK.8::PUSHJ SP,MRK.XX
.MRK.9::PUSHJ SP,MRK.XX
MRK.XX: TRNE FL,TRPOFF ; ARE WE SENDING SYMBOLS ?
JRST [
SUB SP,[1,,1] ; NO - CLEAR JUNK FROM STACK
POPJ SP,] ; AND RETURN
PUSHJ SP,SNDSTN ;YES - MAKE SURE STN HAS BEEN SENT
MOVE A2,[XWD 'MRK',2];GET MARKER TYPE CODE
PUSHJ SP,MOVE0 ; AND SEND IT OUT
POP SP,A2 ; THEN GET LINK
SUBI A2,.MRK.1 ; CONVERT TO TYPE CODE
HRL A2,RA ; GET ADDRESS INTO LEFT HALF
; **** JRST MOVE0 ;**** FALL INTO MOVE0 ****
MOVE0: AOSLE A3,T0IND ; GET INDEX
PUSHJ SP,T0GET ; -END OF SUB-BLOCK
MOVEM A2,@T0ADR ; STORE THE WORD IN THE BUFFER
POPJ SP, ; EXIT MOVE0
RELOC
LASTRA: BLOCK 1 ; ADDRESS OF STN BLOCK.
SENDSN: BLOCK 1 ; FLAG TO SAY SEND STN ITEM
SENDLN: BLOCK 1 ; LINE NUMBER FOR STN ITEM
RELOC
;--------------------------------------------------------------
T1GET: MOVEI A4,TYPE1 ; ADDR OF STATUS BLOCK DESCRIBES TYPE-1 BLOCK
JRST GET ; CONTINUE
T2GET: MOVEI A4,TYPE2 ; ADDR OF STATUS BLOCK DESCRIBES TYPE-2 BLOCK
JRST GET ; CONTINUE
T10GET: MOVEI A4,TYPE10 ; ADDR OF STATUS BLOCK DESCRIBES TYPE-10 BLOCK
JRST GET ; CONTINUE
T0GET: MOVEI A4,TYPE0 ; [247] LOAD ADDR OF T0 STATUS BLOCK
; [247] AND FALL THROUGH TO "GET"
;
; "GET" IS CALLED WHEN A SUB-BLOCK IS FULL. "GET" WILL SET UP THE
; STATUS BLOCK FOR THE NEXT SUB-BLOCK. IF THERE IS ROOM LEFT
; IN THE BUFFER FOR MORE THAN 18 DATA WORDS, "GET" WILL SET THE INDEX
; WORD TO CYCLE FROM -18 TO 0. IF THERE IS BETWEEN 3 AND 18 WORDS
; OF SPACE LEFT IN THE BUFFER, "GET" WILL SET THE INDEX WORD SO THAT
; IT BECOMES ZERO WHEN THE BUFFER IS FULL.
;
; IF THERE ARE LESS THAN 3 AVAILABLE WORDS LEFT IN THE BUFFER,
; "GET" WILL NOT START ANOTHER SUB-BLOCK IN THAT BUFFER. INSTEAD,
; "GET" WILL CALL "FIN" TO MOVE THE LOADER BLOCKS TO THE PRIME BUFFER.
; THEN "GET" WILL PUT THE PROGRAM COUNTER (RA) INTO THE 1ST DATA WORD
; OF THE NEW TYPE-1 LOADER BLOCK.
;
GET: MOVE A5,EN(A4) ; COMPUTE THE AMOUNT OF SPACE LEFT
SUB A5,ADR(A4) ; IN THE BUFFER.
MOVEI A5,(A5) ; CLEAR LEFT HALF OF A5
CAIGE A5,3 ; IF LESS THAN 3 WORDS REMAIN
JRST GET1 ; THEN DON'T START ANOTHER SUB-BLOCK.
CAMLE A5,LEN(A4) ; IF MORE THAN LEN WORDS REMAIN
MOVE A5,LEN(A4) ; USE EXACTLY LEN WORDS FOR THIS SUB-BLOCK
MOVE A3,ADR(A4) ; GET OLD ADDRESS POINTER
ADDI A3,1 ; THE NEXT WORD IS THE NEW RELOCATION BITS WORD
HRRM A3,PTR(A4) ; SET POINTER'S ADDRESS FIELD
SETZM (A3) ; CLEAR THE RELOCATION BITS
MOVEI A3,44 ; REINITIALIZE THE P-FIELD OF
DPB A3,[POINT 6,PTR(A4),5] ; THE BYTE POINTER TO THE FIRST BYTE
ADDM A5,ADR(A4) ; LENGTH OF NEW SUB-BLOCK TO OLD ADDR POINTER
MOVN A3,A5 ; NEGATE LENGTH OF NEW SUB-BLOCK
ADDI A3,2 ; BUT DONT COUNT THE RELOCATION WORD
HRREM A3,IND(A4) ; THIS WILL BE THE NEW INDEX WORD
POPJ SP, ; EXIT GET
GET1: MOVEM A2,A2SAV ; SAVE A2
MOVEM A4,A4SAV ; SAVE A4
SOS IND(A4) ; CORRECT END OF DATA
PUSHJ SP,FIN ; FINISH
MOVEI A4,TYPE1
PUSHJ SP,INITB ; INITIALIZE NEW TYPE1
AOS A3,T1IND ; STEP AND FETCH THE INDEX
MOVE A2,RA ; GET PROGRAM COUNTER
TLZE A2,400000 ; IF RA WAS DECREMENTED
ADDI A2,1 ; THEN COMPENSATE
HRRZM A2,@T1ADR ; PUT PROGRAM COUNTER INTO SUB-BLOCK
MOVEI A3,1 ; 2ND HALF IS RELOCATABLE
IDPB A3,T1PTR ; OUTPUT RELOCATION BITS
MOVE A4,A4SAV ; RESTORE A4
MOVE A2,A2SAV ; RESTORE A2
AOSGE A3,IND(A4) ; STEP INDEX
POPJ SP, ; EXIT T1GET, T2GET, OR T10GET
JRST GET1 ; TRY AGAIN IF BLOCK TOO SHORT.
; "COMPL" COMPUTES THE NUMBER OF DATA WORDS IN A LOADER BLOCK.
; "COMPL" EXPECTS A4 TO CONTAIN THE ADDRESS OF THE STATUS BLOCK,
; AND THAT THE STATUS BLOCK ADDRESS WORD (T#ADR) POINT TO THE
; LAST ACTUAL DATA WORD OF THE LOADER BLOCK. "COMPL" WILL INSERT
; THIS NUMBER INTO THE LOADER BLOCK'S DESCRIPTOR WORD.
COMPL: HRRZ A5,ADR(A4) ; GET END OF LOADER BLOCK
SUB A5,BLK(A4) ; LENGTH OF USED BUFFER SPACE
HRL A5,TYP(A4) ; GET TYPE BITS
TLNE A5,1700 ; NO ADJUSTMENT FOR TYPES
JRST COMPL1 ; 1000-1077
MOVEI A2,-1(A5) ; COPY LENGTH-1 TO A2
IDIVI A2,^D19 ; COMPUTE NUMBER OF RELOCATION WORDS
SUBI A5,1(A2) ; ELSE SUB FOR # DATA WORDS
COMPL1: MOVEM A5,@BLK(A4) ; PUT TYPE AND LENGTH AT BEGINNING OF BLOCK
POPJ SP, ; EXIT COMPL
; "GETBUF" WILL GET A NEW PRIME BUFFER, AND THEN UPDATE THE PRIME
; BUFFER STATUS BLOCK TO REFLECT THIS CHANGE.
GETBUF: MOVE A2,T1ADR ; END OF DATA IN BUFFER
HRRM A2,BHEAD1+1 ; MARK IN HEADER
SKIPLE WFLAG ; IF THERE IS AN OBJECT MODULE
OUT 1,0 ; GET ANOTHER BUFFER
JRST .+2 ; -OK
JRST DSERR7 ; -OUTPUT ERROR
HRRZ A2,BHEAD1 ; ADDRESS OF NEW BUFFER
ADDI A2,1 ; STEP OVER 1ST WORD
HRRM A2,T1BLK ; MARK BLOCK BEGINNING
HRRM A2,T1ADR ; SET T1ADR
ADD A2,BUFLEN ; COMPUTE END OF BUFFER
HRRZM A2,T1END ; SAVE THIS ADDRESS
POPJ SP, ; EXIT CHECK3
; "FIN" WILL ADD THE INDEX WORD, T1IND, TO THE ADDRESS WORD, T1ADR,
; AND EXPECT THE SUM TO POINT TO THE LAST DATA WORD IN THE PRIME BUFFER.
; THEN "FIN" WILL COMPUTE THE NUMBER OF DATA WORDS IN THE LOADER BLOCK
; THAT IS BEING FILLED IN THE PRIME BUFFER, AND INSERT THIS NUMBER
; INTO THE LOADER BLOCK'S DESCRIPTOR WORD. THEN "FIN" WILL USE "MOVBLK"
; TO MOVE LOADER BLOCKS FROM THE ISOLATED BUFFERS TO THE PRIME BUFFER.
; FINALLY, "FIN" WILL INITIALIZE THE PRIME BUFFER TO RECEIVE SUB-BLOCKS
; OF A NEW LOADER BLOCK.
FIN: HRRE A4,T1IND ; GET INDEX
ADDM A4,T1ADR ; COMPUTE END OF DATA IN PRIME BUFFER
MOVEI A4,TYPE1 ; PARAM FOR COMPL
PUSHJ SP,COMPL ; LENGTH OF CODE IN BUFFER, PUT IN BUFFER
FIN4: MOVEI A4,TYPE2 ; [302] PARAM FOR MOVBLK
PUSHJ SP,MOVBLK ; MOVE TYPE-2 LOADER BLOCK TO PRIME BUFFER
MOVEI A4,TYPE10 ; PARAM FOR MOVBLK
PUSHJ SP,MOVBLK ; MOVE TYPE-10 LOADER BLOCK TO PRIME BUFFER
MOVEI A4,TYPE0 ; PARAM FOR MOVBLK
TRNN FL,TRPOFF ; UNLESS PRODUCTION SWITCH SET
PUSHJ SP,MOVBLK ; MOVE TYPE-0 LOADER BLOCK TO PRIME BUFFER
FIN1: MOVE A3,T1END ; END OF BUFFER
SUB A3,T1ADR ; COMPUTE REMAINING LENGTH OF BUFFER
MOVEI A3,(A3) ; ZERO LEFT HALF
CAIGE A3,3 ; IF THERE ARE LESS THAN 3 WORDS LEFT
PUSHJ SP,GETBUF ; THEN GET ANOTHER BUFFER
AOS A3,T1ADR ; NEXT AVAILABLE WORD IN PRIME BUFFER
POPJ SP,
; "INITB" INITIALIZES A BUFFER SO THAT IT CAN RECEIVE THE 1ST SUB-BLOCK
; OF A NEW LOADER BLOCK. "INITB" EXPECTS A3 TO CONTAIN THE ADDRESS
; OF THE NEW LOADER BLOCK (ADDRESS OF THE DESCRIPTOR WORD), AND THAT
; A4 CONTAIN THE ADDRESS OF THE STATUS BLOCK.
INITB: HRRZM A3,BLK(A4) ; SET POINTER TO DESCRIPTOR WORD
HRRZS A3 ; CLEAR LHS
ADD A3,LEN(A4) ; STEP TO END OF SUB-BLOCK
CAMLE A3,EN(A4) ; IF PAST END OF BUFFER
MOVE A3,EN(A4) ; THEN BUFFER END BECOMES SUB-BLOCK END
HRRM A3,ADR(A4) ; SET ADDRESS POINTER
SUB A3,BLK(A4) ; COMPUTE LENGTH OF SUB-BLOCK
MOVNM A3,IND(A4) ; SET INDEX WORD
CAIL A4,T1000S ; All this not requ'd for 1000 up,
POPJ SP, ; So skip it
AOS IND(A4) ; Step past relocation word
MOVE A3,BLK(A4) ; Beginning of block
MOVEI A3,1(A3) ; Relocation word
SETZM (A3) ; To zero
HRRM A3,PTR(A4) ; SET ADDR FIELD OF RELOCATION BITS POINTER
MOVEI A3,44 ; BYTE 1
DPB A3,[ ; SET P-FIELD OF RELOCATION
POINT 6,PTR(A4),5] ; BITS BYTE POINTER
POPJ SP, ; EXIT INITB
; "MOVBLK" WILL MOVE A LOADER BLOCK FROM AN ISOLATED BUFFER TO THE
; PRIME BUFFER. "MOVBLK" EXPECTS A4 TO CONTAIN THE ADDRESS OF THE
; STATUS BLOCK, AND THAT T1ADR POINT TO THE LAST ACTUAL DATA WORD
; IN THE PRIME BUFFER. UPON COMPLETION, "MOVBLK" WILL SET T1ADR TO
; POINT TO THE NEW LAST DATA WORD IN THE PRIME BUFFER.
;
; IF THE LOADER BLOCK TO BE MOVED WILL NOT FIT IN THE AVAILABLE SPACE
; IN THE PRIME BUFFER, "MOVBLK" WILL MOVE AS MUCH AS WILL FIT, AND
; THEN PERFORM AN OUT UUO TO GET A NEW PRIME BUFFER, THEN MOVE THE
; REMAINDER OF THE LOADER BLOCK TO THE NEW PRIME BUFFER.
MOVBLK: HRRE A5,IND(A4) ; GET INDEX
ADDM A5,ADR(A4) ; COMPUTE END OF LOADER BLOCK
PUSHJ SP,COMPL ; COMPUTE LENGTH OF BLOCK, PUT IN BLOCK
; COMPUTE LENGTH OF LOADER BLOCK TO MOVE
HRRZ A5,ADR(A4) ; GET END OF USED SPACE
SUB A5,BLK(A4) ; SUBTRACT BEGINNING OF LOADER BLOCK
EDIT(070); Allow only one data word in new block-types
SOJL A5,MBLK2 ; [E070] Exit if no data words
MOVE A3,TYP(A4) ; [E070] Else get Block-Type
TRNN A3,1700 ; [E070] And if not a new block
JUMPE A5,MBLK2 ; [E070] Exit if only one word
ADDI A5,2 ; TRUE LENGTH OF BLOCK TO MOVE
; COMPUTE REMAINING SPACE IN CURRENT OUTPUT BUFFER
MOVE A3,T1END ; END OF OUTPUT BUFFER
SUB A3,T1ADR ; SUBTRACT POINTER
MOVEI A3,(A3) ; ZERO LEFT HALF OF A3
; A5=LENGTH OF LOADER BLOCK TO MOVE
; A3=LENGTH OF AVAIL SPACE IN PRIME BUFFER
JUMPE A3,MBLK3 ; JUMP IF NO SPACE LEFT
CAIGE A3,(A5) ; IF THERE IS NOT ENOUGH SPACE THEN
JRST MBLK4 ; CONTINUE
; MOVE REMAINDER OF LOADER BLOCK TO OUTPUT BUFFER
HRLZ A3,BLK(A4) ; "FROM" ADDRESS
MOVE A2,T1ADR ; END OF DATA IN PRIME BUFFER
MBLK1: HRRI A3,1(A2) ; "TO" ADDRESS
ADDI A2,(A5) ; "END" ADDRESS IN PRIME BUFFER
HRRM A2,T1ADR ; SAVE AS NEW ADDRESS POINER
HRRM A2,T1BLK
AOS T1BLK
BLT A3,(A2) ; MOVE IT
MBLK2: MOVE A3,BLK(A4) ; LOCATE BEGINNING OF LOADER BLOCK
JRST INITB ; INITIALIZE IT, EXIT MOVBLK
; NO SPACE IN PRIME BUFFER
MBLK3: HRL A3,BLK(A4) ; "FROM" ADDRESS
JRST MBLK5 ; CONTINUE
; INSUFFICIENT SPACE IN PRIME BUFFER
MBLK4: SUB A5,A3 ; COMPUTE LENGTH OF 2ND PART
ADD A3,BLK(A4) ; COMPUTE "FROM" ADDRESS FOR 2ND PART
HRLZI A3,(A3) ; SAVE FOR LATER
AOS A2,T1ADR ; "TO" ADDRESS
HRL A2,BLK(A4) ; "FROM" ADDRESS
BLT A2,@T1END ; MOVE 1ST PART OF LOADER BLOCK
MBLK5: MOVE A2,T1END ; END OF PRIME BUFFER
HRRM A2,T1ADR ; SET T1ADR TO IT
PUSHJ SP,GETBUF ; GET ANOTHER PRIME BUFFER
HRRZ A2,T1ADR ; ADDR OF BEGINNING OF NEW BUFFER
JRST MBLK1 ; CONTINUE
.ZZEND: MOVEM A6,A6SAV ; SAVE A6
PUSHJ SP,LMSGZ ; PRINT ANY ERROR MESSAGES LEFT IN TABLE
;--------------------------------------------------------
; SEARCH SYMBOL TABLE FOR UNDEFINED LABELS.
;--------------------------------------------------------
ZLAB: MOVE A1,STBB ; WHERE AN UNDEFINED LABEL ENTRY MIGHT BE
CAML A1,NASTE ; IF NO UNDEFINED LABEL
JRST ZC0 ; THEN SKIP THIS PART
PUSHJ SP,NAME ; EXTRACT FROM SYMBOL TABLE ENTRY THE ASCIZ NAME
MOVE A2,(A1) ; GET 1ST WORD OF ENTRY
TLNE A2,EXTEN ; IF IT IS AN EXTENDED ENTRY
ADDI A6,2 ; THEN ADD 2 TO POINTER
MOVEM A6,STBB ; SAVE FOR LATER
HRRZ A1,-2(A6) ; GET THE CHAIN HEAD
MOVEI A2,777777 ; FIX IT UP TO JUMP TO -1
PUSHJ SP,.ABSFIX ; WRITE OUT THE FIX-UP
MOVEI A1,UNDLAB ; "UNDEFINED LABEL "
PUSHJ SP,INS ; SEND TO LISTING AND TO TTY
MOVEI A1,LB ; ADDRESS OF NAME OF LABEL
PUSHJ SP,INS ; SEND TO LISTING AND TO TTY
MOVEI A1,[ASCIZ/>/] ; END NAME OF LABEL
PUSHJ SP,INS ; ...WITH A ">"
PUSHJ SP,TCHECK ; CR/LF
AOS .JBERR ; ADD 1 TO ACCUMULATED ERROR COUNT
MOVE A1,RFLAGS ; IF TERMINATION MESSAGE GIVEN
TLOE A1,TMG ; ...
JRST ZLAB ; THEN LOOK FOR ANOTHER UNDEFINED LABEL
MOVEM A1,RFLAGS ; ELSE TERMINATE REL FILE
SETOM WFLAG ; MARK .REL FILE TO BE DELETED
MOVEI A1,TERMC ; ADDRESS OF TERMINATION MESSAGE.
PUSHJ SP,INS ; "REL FILE DELETED"
PUSHJ SP,TCHECK ; CR/LF
JRST ZLAB ; LOOK FOR ANOTHER UNDEFINED LABEL
UNDLAB: ASCIZ /?UNDEFINED LABEL </ ;[304]
;--------------------------------------------------------
; MOVE 1-WORD CONSTANTS TO REL-FILE
;--------------------------------------------------------
ZC1: HLRZ A1,(A2) ; IF BACK-CHAIN IS ZERO
JUMPE A1,.+4 ; THEN DONT OUTPUT THIS CONSTANT
MOVE A1,1(A2) ; GET CONSTANTS VALUE
HLRZ A6,(A2) ; GET THE BACK CHAIN
PUSHJ SP,ZZZ ; OUTPUT THE WORD AND THE BACK CHAIN
SUB A2,(A2) ; LOCATE NEXT ENTRY ON CHAIN
TLZA A2,777777 ; ZERO LEFT HALF
ZC0: MOVE A2,LASTC1 ; START OF 1-WORD-CONSTANTS CHAIN
ZC2: CAMLE A2,CONTAB ; UNLESS END OF CHAIN
JRST ZC1 ; LOOP
;--------------------------------------------------------
; MOVE 2-WORD CONSTANTS TO REL-FILE
;--------------------------------------------------------
MOVE A2,LASTC2 ; START OF 2-WORD-CONSTANTS CHAIN
JRST ZC4 ; JUMP INTO LOOP
ZC3: MOVE A1,2(A2) ; GET 1ST WORD OF VALUE
HLRZ A6,(A2) ; GET THE BACK CHAIN
JUMPE A6,ZC4-2 ; IF NO BACK-CHAIN THEN SKIP THIS CONSTANT
PUSHJ SP,ZZZ ; OUTPUT THE WORD AND ITS FIXUP
MOVE A1,3(A2) ; GET 2ND WORD OF VALUE
HRRZ A6,1(A2) ; GET THE BACK CHAIN
PUSHJ SP,ZZZ ; OUTPUT THE WORD AND ITS FIXUP
SUB A2,(A2) ; LOCATE NEXT ENTRY ON CHAIN
MOVEI A2,(A2) ; ZERO LEFT HALF
ZC4: CAMLE A2,CONTAB ; UNLESS END OF CHAIN,
JRST ZC3 ; LOOP
;--------------------------------------------------------
; MOVE ANY ASCII STRINGS FROM CONSTANTS TABLE TO REL-FILE
;--------------------------------------------------------
MOVE A2,LASTST ; ADDR OF LAST STRING
JRST ZC8 ; JUMP INTO LOOP
ZC5: HLLZ A1,(A2) ; GET 1ST BACK-CHAIN
IOR A1,1(A2) ; OR WITH OTHER BACK-CHAINS
JUMPE A1,ZC8-2 ; IF ALL 3 ZERO THEN SKIP THIS STRING
HRRZ A1,RA ; GET ADDRESS OF EVENTUAL
ADDI A1,2 ; STRING ADDRESS
HRLI A1,440700 ; SET POSITION BITS
PUSHJ SP,.MREL ; WRITE 1ST WORD OF STRING HEADER
HLRZ A6,(A2) ; GET THE BACK CHAIN
PUSHJ SP,ZZZ+1 ; WRITE OUT THE FIXUP
MOVE A1,2(A2) ; GET BYTE COUNT
HRRZ A6,1(A2) ; GET THE 2ND BACK CHAIN
PUSHJ SP,ZZZ ; WRITE OUT THE WORD AND ITS FIXUP
SKIPN 2(A2) ; IF STRING IS 0 CHARS LONG
JRST ZC7 ; THEN SKIP THIS PART
PUSH SP,A1 ; SAVE VALUE OF RA FOR LATER
MOVEI A1,2(A2) ; START OF STRING -1
MOVEM A1,TEMP ; PUT IN TEMP
ZC6: AOS A1,TEMP ; GET ADDR OF NEXT WORD OF STRING
MOVE A1,(A1) ; GET NEXT WORD OF STRING
PUSHJ SP,.MABS ; WRITE IT OUT
HRREI A1,-5 ; DECREMENT CHARACTER COUNT
ADDB A1,2(A2) ; BY 5
JUMPG A1,ZC6 ; LOOP IF STILL SOME LEFT
POP SP,A1 ; RETRIEVE OLD VALUE OF RA
ZC7: PUSH SP,RA ; SAVE CURRENT VALUE OF RA
MOVEM A1,RA ; SET RA TO OLD VALUE
HLRZ A1,1(A2) ; GET 3RD BACK-CHAIN POINTER
PUSHJ SP,.RAFIX ; WRITE IT OUT
POP SP,RA ; RESTORE CORRECT VALUE OF RA
SUB A2,(A2) ; STEP TO NEXT STRING
MOVEI A2,(A2) ; ZERO LEFT HALF
ZC8: CAMLE A2,CONTAB ; IF THERE IS ANOTHER STRING
JRST ZC5 ; THEN LOOP
;--------------------------------------------------------
; MOVE CONTENTS OF FIXUP TABLE TO REL-FILE
;--------------------------------------------------------
;
;
; TYPE-15 BLOCKS (NOT MORE THAN 1 PER PROGRAM)
; ARE CREATED AS FOLLOWS -
; THE BLOCK HEADER WORD IS WRITTEN DIRECTLY INTO THE
; CURRENT PRIME BUFFER, SINCE ITS TOTAL LENGTH IS
; KNOWN, THEN ITS CONSTITUENT SUB-BLOCKS ARE BUILT IN
; THE TYPE-10 BUFFER AND MOVED OUT ONE BY ONE INTO THE
; PRIME BUFFER, SO AS TO PRESENT ONE CONTINUOUS STREAM
; TO THE LOADER.
;
;
PUSHJ SP,FIN ; CLEAR OUT ALL OTHER BUFFERS
MOVE A2,FIXUP ; COMPUTE TOTAL LENGTH
SUB A2,NAFTE ; OF THE BLOCK
LSH A2,1 ; SINCE TABLE WAS PACKED
SOJL A2,ZEXIT3-2 ; MAYBE NOTHING
HRLI A2,15 ; BLOCK HEADER
MOVEI A3,0 ; CLEAR A3 'cos T1ADR uses it
MOVEM A2,@T1ADR
SOS A3,T15BLK ; INITIALIZE FIRST S-B
MOVEI A4,TYPE15
PUSHJ SP,INITB ;
AOS T15BLK ; To please future calls
HRL A2,RA
SETZM PTR15
PUSHJ SP,MOV15A ; WRITE OUT RELOC ETC
MOVE A1,FIXUP
ZEXIT1: SUBI A1,1 ; STEP TO NEXT WORD (TABLE GROWS DOWNWARD)
CAMG A1,NAFTE ; IF AT END OF TABLE
JRST ZEXIT2 ; THEN FINISHED PROCESSING TABLE
MOVE A3,(A1) ; GET RIGHT HALF
PUSHJ SP,MOV15 ; PUT INTO TYPE-15 BLOCK
HLRZ A3,(A1) ; GET LEFT HALF
PUSHJ SP,MOV15 ; PUT INTO TYPE-15 BLOCK
JRST ZEXIT1 ; LOOP
;--------------------------------------------------------
; SUBROUTINE FOR MOVING TYPE-15 FIXUPS
;--------------------------------------------------------
MOV15: AOS A2,PTR15 ; GET A VALUE FOR IT
HRL A2,A3 ; PUT VALUE WITH BACK CHAIN POINTER
MOV15A: AOSLE A3,T15IND ; GET INDEX
PUSHJ SP,T15GET ; -END OF SUB-BLOCK
MOVEM A2,@T15ADR ; PUT FIX-UP INTO BUFFER
MOVEI A3,2 ; BACK POINTER IS RELOCATABLE
TLNN A2,777777 ; IF THERE IS NO BACK-CHAIN
MOVEI A3,0 ; THEN BACK POINTER IS NOT RELOCATABLE
IDPB A3,T15PTR ; OUTPUT RELOCATION BITS
POPJ SP, ; EXIT MOV15
;--------------------------------------------------------------
; THIS SECTION OUTPUTS A TYPE15 SUB-BLOCK TO PRIME BUFFER
;----------------------------------------------------------------
T15GET: AOS A5,T1ADR ; UPDATE NEXT LOCN
MOVEI A4,(A5) ; [302] DESTINATION
ADDI A4,^D17(A3) ; PLUS LENGTH OF THIS S-B
HRL A5,T15BLK ; BLOCK BEGINNING
CAMG A4,T1END ; ANY ROOM ?
JRST T15GT1 ; IF SO, JUMP ON
;
; THIS SECTION OUTPUTS AS MUCH OF A SUB-BLOCK AS WILL
; FIT TO THE PRIME BUFFER, PUSHES OUT THE BUFFER
; VIA GETBLK, AND LEAVES THE REMAINDER OF THE SUB-BLOCK
; TO T15GET.
;
BLT A5,@T1END ; SHIFT AS MANY AS POSS.
SUB A4,T1END ; #WORDS STILL TO MOVE
ADDI A3,^D18 ; TOTAL WORDS TO MOVE
SUBI A3,(A4) ; WORDS MOVED
ADDM A3,T1ADR ; UPDATE LAST WORD USED
HRRZ A5,T15BLK ; SET A5 UP FOR LATER
ADDI A5,(A3)
MOVEM A2,A2SAV ; GETBUF DESTROYS IT
PUSHJ SP,GETBUF ; OUTPUT
MOVE A2,A2SAV ; RESTORE A2
HRLI A5,(A5) ; ORIGIN ON LEFT
HRR A5,T1ADR
ADDI A4,(A5)
ADDI A5,1
T15GT1: BLT A5,(A4)
HRRM A4,T1ADR ; UPDATE T1ADR
HRRZ A3,T1ADR ; [302] GET CURRENT POSITION OF T1ADR
SUB A3,T1BLK ; [302] CALCULATE HOW MUCH ROOM IS LEFT NOW
MOVNS A3 ; [302] NEGATE ANSWER
CAMLE A3,T1IND ; [302] IS OUR RESULT LARGER THAN WHAT'S THERE?
MOVEM A3,T1IND ; [302] NO, SET INDEX ACCORDINGLY
SOS A3,T15BLK ;
MOVEI A4,TYPE15
PUSHJ SP,INITB ;
AOS T15BLK ;
AOS A3,T15IND ; FOR MOV15
POPJ SP, ; OR MAYBE ONLY EXIT
; SUBROUTINE FOR MOVING CONSTANTS TO REL-FILE
ZZZ: PUSHJ SP,.MABS ; WRITE OUT THE WORD
SOS A1,RA ; GET AND DECREMENT RA
TLO A1,400000 ; TAG IT
MOVEM A1,RA
MOVE A1,A6 ; MOVE THE CHAIN TO A1
PUSHJ SP,.RAFIX ; WRITE OUT THE FIXUP
AOS A1,RA
HRRZM A1,RA ; INCREMENT RA AND CLEAR FLAG
POPJ SP,
;--------------------------------------------------------
; MOVE TO REL-FILE THE TYPE-2 ENTRIES FOR THE LIBRARY PROCEDURES
;--------------------------------------------------------
ZEXIT2: MOVNI A1,^D18 ; CHECK FOR NULL S-BLK
AOS A3,T15IND
CAME A1,T15IND
PUSHJ SP,T15GET
SETOM ECOUNT ; INITIALIZE ALIAS COUNT
MOVEI A5,BLOCK0## ; 1ST ENTRY IN BLOCK 0
ZEXIT3: AOS A2,ECOUNT ; STEP ALIAS INDEX
MOVE A2,ATABLE##(A2) ; GET ALIAS NAME IN RADIX50
IMULI A2,50 ; APPEND PROCESSOR CHARACTER
ADDI A2,26 ; IE "L" IN RAD 50
MOVE A1,1(A5) ; VALUE FIELD CONTAINS BACK CHAIN
PUSHJ SP,.FIX50 ; WRITE OUT FIX-UP
MOVE A1,(A5) ; GET 1ST WORD OF ENTRY
MOVE A3,2(A5) ; 1ST WORD OF NAME
ADDI A3,1 ; ADD 1 TO CHARACTER COUNT
ANDI A3,77 ; SAVE ONLY CHAR COUNT
IDIVI A3,6 ; CONVERT TO WORD COUNT MINUS 1
ADDI A5,3(A3) ; STEP TO PAST NAME
TLNN A1,EXTEN ; IF THIS IS NOT AN EXTENDED ENTRY
JRST ZEXIT4 ; THEN SKIP THIS PART
MOVE A1,(A5) ; LOAD 1ST WORD OF EXTENSION
MOVE A2,ECOUNT ; GET THE ENTRY COUNT
MOVE A2,AT2##(A2) ; GET 2ND ALIAS NAME IN RADIX50
IMULI A2,50 ; AND ADD PROCESSOR CHARACTER
ADDI A2,26
PUSHJ SP,.FIX50 ; WRITE OUT FIX-UP
ADDI A5,2 ; SET PAST EXTENSION TO NEXT ENTRY
ZEXIT4: CAIGE A5,B0END## ; IF STILL WITHIN BLOCK 0
JRST ZEXIT3 ; THEN LOOP
;--------------------------------------------------------
; WRITE OUT THE TYPE-5 END BLOCK
;--------------------------------------------------------
PUSHJ SP,FIN4 ; [302] FINISH
HRRZ A1,T1ADR ; GET NEXT FREE LOCATION
MOVE A2,[5,,1] ; THIS IS A TYPE-5 BLOCK
MOVEM A2,(A1) ; PUT INTO BUFFER
HRLZI A2,200000 ; RELOCATION BITS
MOVEM A2,1(A1) ; PUT INTO BUFFER
MOVE A2,RA ; GET END OF PROGRAM PLUS 1
HRRZM A2,2(A1) ; PUT INTO BUFFER
ADDI A1,2 ; END OF DATA
HRRM A1,T1ADR ; SET NEW T1ADR
HRRM A1,BHEAD1+1 ; SET END OF DATA
MOVE A6,A6SAV ; RESTORE A6
TLNE A7,EXISTS ; IF THE LISTING EXISTS
TLZ A7,COMPLETE ; THEN MARK IT COMPLETE
MOVEM A7,RFLAGS ; SAVE READ MODULE FLAGS
MOVE A7,A7SAV ; RESTORE A7
POPJ SP, ; EXIT .ZZEND
RELOC
TEMP: BLOCK 1 ; TEMP
PTR15: BLOCK 1 ; STATIC OWN AREA POINTER
ECOUNT: BLOCK 1 ; ENTRY COUNT
RELOC
; "NAME" WILL EXTRACT FROM A SYMBOL TABLE ENTRY THE NAME OF THE
; IDENTIFIER IN ASCIZ FORMAT. A1 SHOULD CONTAIN THE ADDRESS OF
; THE SYMBOL TABLE ENTRY. THE OUTPUT IS IN A BUFFER CALLED "LB"
NAME: MOVE A5,[LB,,LB+1] ; [301] LOAD BLT POINTER
SETZM LB ; CLEAR ENOUGH OF LB
BLT A5,LB+^D14 ; FOR A 64-CHAR NAME.
MOVE A5,LBP ; BYTE POINTER TO OUTPUT BUFFER
MOVEI A6,2(A1) ; STEP TO 1ST NAME WORD OF ENTRY
MOVE A3,(A6) ; LOAD 1ST NAME WORD
LSHC A3,-6 ; PEEL OFF LENGTH COUNT
LSH A4,-36 ; CHAR COUNT -1
MOVEI A2,1(A4) ; A2 = CHAR COUNT
NAMEL: JUMPE A3,EDT301 ; [301] DON'T LOOP FOREVER IF NAME IS NULL
LSHC A3,-6 ; GET NEXT CHAR
LSH A4,-36 ; MOVE TO RIGHT OF REG
JUMPE A4,NAMEL ; IF A NULL THEN GET ANOTHER CHAR
TRNN A4,40 ; IF IT IS A LETTER
IORI A4,100 ; THEN CONVERT IT TO ASCII
IDPB A4,A5 ; PUT IN BUFFER
JUMPN A3,.+3 ; SKIP IF STILL MORE CHARS IN A3
EDT301: ADDI A6,1 ; [301] STEP WORD INDEX
MOVE A3,(A6) ; PICK UP NEXT WORD OF NAME
SOJG A2,NAMEL ; LOOP ONCE FOR EACH CHAR
POPJ SP, ; EXIT NAME
SUBTTL DATA MODULE
DEFINE MOD(N,ALOC)
<INTERN B.'N
INTERN Q.'N;
Q.'N==ALOC
B.'N: BLOCK ALOC
>
;..STORAGE ALLOCATION FOR MODULES
RELOC
MOD(MDEC,0);
MOD(MSTM,0);
MOD(MEXP,0);
MOD(MFOR,12);
MOD(MUTL,2);
MOD(MSER,16);
MOD(MCOD,3);
MOD(MFUN,1);
SUBTTL GLOBAL VARIABLES (FULL WORDS)
DEFINE GLOB(G)
<INTERN G
G: BLOCK 1
>
GLOB NSYM; ;NEXT SYMBOL
GLOB NDEL; ;NEXT DELIMITER
GLOB BLOCKLEVEL; ;CURRENT BLOCKLEVEL
GLOB FNLEVEL; ;CURRENT FUNCTION LEVEL
GLOB STBB; ;SYMBOL TABLE BASE FOR THIS BLOCK
GLOB NASTE; ;NEXT AVAIL. SYMBOL TABLE ENTRY
GLOB NACTE; ;NEXT AVAIL. CONSTANTS TABOL ENTRY
GLOB NAFTE; ;NEXT AVAILABLE FIXUP TABLE ENTRY;
GLOB FIXUP; ;BASE OF FIXUP TABLE;
GLOB CONTAB; ;CONSTANT TABLE BASE;
GLOB CAX; ;PROCEDURE LEVEL OF LAST ACCESSED NON-LOCAL
GLOB RA; ;RELATIVE ADDRESS OF NEXT INSTRUCTION PLACED IN
;OBCODE
GLOB LEXBLOCK; ;MONOTONICALLY INCREASING COUNT OF BLOCKS
GLOB CURBLOCK; ;LEXBLOCK OF CURRENT BLOCK
GLOB ARDEC; ;ARRAY DECLARED IN BLOCK => TRUE; ELSE FALSE
GLOB PROSKIP; ;PROCEDURE FOUND SWITCH (-1 NONE FOUND) OR ADDR
;OF FIRST ONE
GLOB LSTSLN; ; LINE NUMBER OF LAST STN BLOCK
GLOB CURSLN; ; LINE NUMBER FOR SYM
GLOB NXTSLN; ; LINE NUMBER OF NSYM
GLOB CURDLN; ; LINE NUMBER FOR DEL
GLOB NXTDLN; ; LINE NUMBER OF NDEL
GLOB STMTNO; ; STATEMENT # WITHIN A LINE.
GLOB LINENO; ;LINE NUMBER SPECIFIED BY LINE PSEUDO-STATEMENT
GLOB INDEX; ;FIRST AVAILABLE FREE WORD IN TEMPCODE
GLOB HANDLE; ;PORTION POINTER FOR CURRENTLY OPEN PORTION
GLOB LEXEX; ;BLOCKLEVEL & HANDLE FOR SYM * THESE
GLOB COMPNAME; ;COMPOSIT NAME FOR SYM * MUST
GLOB LLEXEX; ;BLOCKLEVEL & HANDLE FOR LEFT OP* APPEAR
GLOB LCOMPNAME; ;COMPOSIT NAME FOR LEFT OP * TOGETHER
GLOB LAC; ;LAST ALLOCATED ACCUMULATOR
GLOB TCBASE; ;THE FIRST LOCATION OF TEMPCODE BUFFER.
GLOB TCMAX; ;THE LAST LOCATION OF TEMPCODE BUFFER.
GLOB THUNK; ;ADDRESS OF JRST OVER THUNKS (0 IF NONE YET.);
GLOB OP; ;CONTAINS THE OPERATOR DURING CODE GENERATION;
GLOB KA; ;COMMUNICATIONS CELL FOR GLOAD AND LOAD;
GLOB FBSYMSAVE; ;SAVED STEP ELEMENT LEXEME
GLOB FBLEXSAVE;
GLOB FBCOMPSAVE;
GLOB PREFACC; ;PREFERED REGISTER FOR CGINCR
;THIS IS LEXICAL SCANNER'S TABLE OF LINE POINTERS.
GLOB PLIST;
BLOCK 6;
RELOC
END