PROCEDURE ,010000 ;+ ; Abstract: RNSYM ; ; This module has support for the RUNOFF symbol table, ; including variable creation, lookup, table initialisation, ; and variable modification. Variable names may have up to ; 6 characters and may take on numeric or character ; quantities. A variable which is of CHARACTER type may ; not take on a numeric quantity and vice-versa. ; ; Calling sequence: ; ; MOV #VARIABLE_NAME_BUFFER,R1 ; MOV #VARIABLE_VALUE,R0 ; CALL SETINT ; Add or modify existing integer ; ; MOV #VARIABLE_NAME_BUFFER,R1 ; MOV #VARIABLE_VALUE_BUFFER,R0 ; CALL SETCHA ; Add or modify existing character ; ; MOV #VARIABLE_NAME_BUFFER,R1 ; CALL RETCHA ; Retrieve a character representation ; ; of a character or integer variable ; ; MOV #VARIABLE_NAME_BUFFER,R1 ; CALL RETINT ; Retrieve a numeric representation ; ; of an integer variable. Result is ; ; in R0, and CC-C is set if the ; ; variable does not exist or is of ; ; the wrong type. ; ; MOV #VARIABLE_NAME_BUFFER,R1 ; CALL DELSYM ; Delete existing symbol ; ; CALL INISYM ; Initialise symbol table ; ; *** note *** ; ; Variable deletion (DELSYM), and the various character ; functions (including character variables) are not yet ; implemented in their entirity because no syntactic ; method has yet been devised for their use !!! ; ; Written: 12-Apr-80, -1.0.0-, Bruce C. Wright ; Modified: ; Verified: ;- ; ; Format of symbol table list ; SYMNXT = 0 ; Pointer to next symbol in list. SYMNAM = 2 ; Beginning of symbol name (6 bytes) SYMTYP = 10 ; Symbol type INTSYM= 0 ; Integer type CHASYM= 1 ; Character type ; ; Portion for Integer symbols only ; INTVAL = 12 ; Value for integer symbols INTLEN = 14 ; Total size of entry for Integer variable ; ; Portion for Character symbols only ; CHASIZ = 12 ; Size of character symbol CHAHDR = 14 ; Length of header (total size variable) ; DATA RNSYMD,LCL ; ; The list header ; ; SYMHDR: .WORD 0 ; Header of list of table entries CHABUF: .ASCII " " ; Buffer for character conversion. ; ; External subroutine to initialise the symbol table listhead. ; CODE RNSYM INISYM:: CLR SYMHDR ; Clear out the symbol table. RETURN ; And return to the caller. ; ; External subroutine to set an integer variable. It will ; return with CC-C set if the variable specified is not an ; integer. ; SETINT:: MOV R1,-(SP) ; Save the buffer address. CALL LOCSYM ; Lookup the symbol. BCC 10$ ; Skip if no error. MOV R0,-(SP) ; Save R0 MOV #INTLEN,R0 ; Get the symbol size. CALL CRESYM ; And create the symbol. MOV (SP)+,R0 ; Recover R0 MOV #INTSYM,SYMTYP(R1) ; Set symbol type. 10$: CMP #INTSYM,SYMTYP(R1) ; Is it an integer? BNE 20$ ; No -- error. MOV R0,INTVAL(R1) ; Save the value into the table. BR 30$ ; And return. 20$: DIAG INVSYM ; Invalid use of symbol 30$: MOV (SP)+,R1 ; Recover R1 RETURN ; And return to the caller. ; ; External subroutine to retrieve an integer representation of ; a variable. It will return with CC-C set if the variable does ; not exist or is not an integer. ; RETINT:: MOV R1,-(SP) ; Save the buffer address CLR R0 ; Clear R0 in case no symbol. CALL LOCSYM ; Lookup the symbol BCS 10$ ; Skip if error occurred. MOV INTVAL(R1),R0 ; Return the value of the symbol. BR 20$ ; And return. 10$: DIAG UNDSYM ; Undefined symbol 20$: MOV (SP)+,R1 ; Recover R1 RETURN ; And return to the caller. ; ; External subroutine to return a character representation. ; If the variable is a character variable, the character buffer ; is simply returned. If the variable is an integer, the integer ; is first transformed into a character string and then returned. ; .REPT 0 ; Comment out for now. RETCHA:: MOV R1,-(SP) ; Save the name buffer address. CALL LOCSYM ; Lookup the symbol. BCS 99$ ; Skip if error occurred. CMP SYMTYP(R1),#SYMINT ; Is it an integer? BNE 99$ ; No - for now, only integers allowed. MOV R0,-(SP) ; Save some registers. MOV R2,-(SP) ; ... MOV INTVAL(R1),R0 ; Get the value of the integer. MOV #CHABUF,R2 ; Get buffer to place it in. CALL DECIML ; Convert to decimal. CLRB (R2)+ ; End it with a MOV (SP)+,R2 ; Recover registers. MOV (SP)+,R0 ; ... MOV #CHABUF,R1 ; Point to the buffer. CLC ; Show success. 99$: MOV (SP)+,R1 ; Recover R1 RETURN ; And return to the caller. .ENDR ; ; Internal subroutine to create a symbol and place it on the ; symbol table list. It requires two parameters, the new ; symbol name buffer in R1 and the size of the entry in R0 ; CRESYM: MOV R1,-(SP) ; Save R1 MOV R0,R1 ; Put length to create into R1 CALL ALLOC ; Allocate the length to create. MOV (SP)+,R0 ; Remember address of name. MOV R2,-(SP) ; Save some registers. MOV R3,-(SP) ; ... MOV #6.,R3 ; Set maximum size of symbols. MOV R1,R2 ; Point to beginning of block. ADD #SYMNAM,R2 ; Increment up to name. 10$: MOVB (R0)+,(R2)+ ; Move in until a 0 is moved. BEQ 20$ ; ... SOB R3,10$ ; or until count is exhausted. BR 40$ ; Skip if the count was exhausted first. 20$: DEC R2 ; Point to the 0 just moved. 30$: CLRB (R2)+ ; Output blanks until end of name. SOB R3,30$ ; ... 40$: MOV SYMHDR,(R1) ; Link into the chain. MOV R1,SYMHDR ; ... MOV (SP)+,R3 ; Recover registers. MOV (SP)+,R2 ; ... RETURN ; And return to the caller. ; ; Internal subroutine to locate a symbol table entry. It ; requires only one input, R1 pointing to the symbol name ; and returns with R1 pointing to the symbol table entry ; or with CC-C set if no such symbol was found. ; LOCSYM: MOV R0,-(SP) ; Save some registers. MOV R2,-(SP) ; ... MOV R3,-(SP) ; ... MOV R4,-(SP) ; ... MOV R5,-(SP) ; ... MOV SYMHDR,R2 ; Point to the symbol table. BEQ 45$ ; Skip if nothing there. 10$: MOV R2,R3 ; Point to beginning of entry. ADD #SYMNAM,R3 ; Point to beginning of name. MOV R1,R4 ; Point to beginning of lookup name. MOV #6,R5 ; Get maximum size of entry. 20$: MOVB (R4)+,R0 ; Get lookup character. BEQ 30$ ; Got it -- ensure at end of lookup. CMPB R0,(R3)+ ; Does it match the entry? BNE 40$ ; No -- next entry. SOB R5,20$ ; And loop over whole string. BR 50$ ; At end of string. 30$: TSTB (R3)+ ; at the end of the other string? BEQ 50$ ; Yes -- match. 40$: MOV (R2),R2 ; Get to next symbol table entry. BNE 10$ ; Loop if still more in table. 45$: SEC ; Show error. BR 99$ ; And return. 50$: MOV R2,R1 ; Return the pointer. CLC ; Show success. 99$: MOV (SP)+,R5 ; Recover registers. MOV (SP)+,R4 ; ... MOV (SP)+,R3 ; ... MOV (SP)+,R2 ; ... MOV (SP)+,R0 ; ... RETURN ; And return to the caller. ; ; Internal subroutine to convert to decimal for output. ; .REPT 0 ; Comment out for now DECIML: .IF NDF R$$EIS ; If not an EIS machine ... MOV #10.,R1 ; Get 10. to divide by CALL $DIV ; Do the division the hard way. .IFF ; Otherwise, if an EIS machine ... MOV R0,R1 ; Get quantity into low order. CLR R0 ; Clear out high order. DIV #10.,R0 ; Divide by 10. .ENDC ;R$$EIS ; End of conditional EIS code. MOV R1,-(SP) ; Save remainder. TST R0 ; Anything left? BEQ 10$ ; No -- just return it CALL DECIML ; Yes -- call ourselves recursively. 10$: MOV (SP)+,R1 ; Recover remainder. ADD #'0,R1 ; Make it into a printable digit. MOVB R1,(R2)+ ; And output it. RETURN ; And return to the caller. .ENDR .END