.TITLE TECO TECO-11 .NLIST TTM .LIST TOC,MEB,BEX .DSABL REG,GBL,LC .SBTTL TECO-11 ; PDP-11 TECO ; ; PDP-11 TECO STARTED OUT AS A BRUTE FORCE TRANSLATION OF OS/8 ; TECO BY HANK MAURER AND BOB HARTMAN AT FORD OF COLOGNE, ; WEST GERMANY. OS/8 TECO CAME FROM A PROGRAM ORIGINALLY ; WRITTEN BY RUSSELL HAMM, WAY BACK WHEN... IT WAS MODIFIED ; FOR OS/8 BY THE O.M.S.I. CREW, SPEEDED UP, SHORTENED, AND ; MAKE PDP-10 COMPATIBLE BY RICHARD LARY OF DEC WITH ASSISTANCE ; FROM MARIO DENOBLI OF THE P?S. THE BRUTE FORCE TRANSLATION ; WAS FURTHER MUNGED AND ALTERED BY MARK BRAMHALL OF DEC TO ; BRING IT INTO MORE STANDARD PDP-11 CODE AND MAKE A HIGH/LOW ; SEGMENT SPLIT. MEMORY SIZE EXPANSION WAS ADDED. FURTHER PDP-10 ; COMPATIBILITY WAS DONE BY ANTON CHERNOFF. VARIOUS NEW COMMANDS ; AND FEATURES WERE ADDED AGAIN. FINALLY HERE WE ARE... TECO-11! ; LAST EDIT ON 31-DEC-84 BY BILL SCONCE .IDENT /V40.00/ VERSON = 40. ;VERSION NUMBER .SBTTL INTERNAL GLOBALS ; MAIN ENTRY POINT AND GLOBAL EQUATES .GLOBL VERSON ;TECO'S VERSION NUMBER (SEE FIRST LISTING PAGE) .GLOBL TECO ;"DEAD START" ENTRY POINT ; NOTE: ENTER TECO HERE WITH THE READ/WRITE AREA ALL SET UP AND ; POINTED TO BY R5. TECO WILL SET (RESET) THE SP STACK ITSELF. .GLOBL TECOCR ;"START" ENTRY POINT WITH CR/LF OUTPUT ; NOTE: ENTER TECO HERE WITH THE READ/WRITE AREA ALL SET UP AND ; POINTED TO BY R5. THE SP STACK MUST BE VALID, BUT TECO WILL ; SET (RESET) THE SP STACK SOON. A CARRIAGE RETURN/LINE FEED ; PAIR IS OUTPUT BEFORE (RE-)STARTING TECO. .GLOBL CMDQRG ;Q-REG NUMBER OF THE COMMAND Q-REGISTER .GLOBL RWSIZE ;SIZE OF TECO'S READ/WRITE AREA IN BYTES .GLOBL TECOCH ;LOCATION OF THE DEFAULT COMMAND JUMP DISPATCH TABLE ; NOTE: THIS IS THE DEFAULT COMMAND JUMP DISPATCH TABLE FOR TECO ; COMMANDS. IT IS 314(8) BYTES IN LENGTH CORRESPONDING TO A ; WORD ENTRY FOR EVERY ASCII CODE BETWEEN 000(8) AND 140(8) ; INCLUSIVE AND A WORD ENTRY FOR EVERY ASCII CODE BETWEEN ; 173(8) AND 177(8) INCLUSIVE. THE ADDRESS "TECOCH" IS THE NORMAL ; ADDRESS STORED IN "TECOJP(R5)" FOR USE AS THE COMMAND JUMP ; DISPATCH TABLE. .GLOBL ERROR ;LOCATION OF THE GENERAL "ILLEGAL COMMAND" ERROR ; NOTE: PATCHING THE JUMP DISPATCH TABLE (WHICH STARTS AT @TECOJP(R5), ; INDEXED BY ASCII CHARACTER CODE IN RANGE 0 TO 140 TIMES 2 ; OR BY ASCII CHARACTER CODE IN RANGE 173 TO 177 MINUS 32 TIMES 2 ; FOR WORD ADDRESSING) TO POINT TO THIS LOCATION WILL DISABLE ; THE CORRESPONDING COMMAND IN TECO. FOR EXAMPLE, PATCHING ; OFFSET 262(8), WHICH IS 131(8) TIMES 2, WHICH IS THE ASCII CODE ; FOR 'Y', TO POINT TO THE LOCATION "ERROR" WILL DISABLE THE ; YANK COMMAND. .GLOBL CNV8BT ;LOCATION OF THE 8-BIT CHARACTER CONVERSION TABLE ; NOTE: THIS TABLE HAS A WORD ENTRY FOR EVERY CHARACTER CODE BETWEEN 200(8) ; AND 377(8) INCLUSIVE. FOR LEGAL DEC MULTI-NATIONAL CHARACTER CODES, ; THE ENTRY IS THE TWO CHARACTER COMPOSE SEQUENCE IN ASCII (AND BIT ; <15> IS CLEAR). FOR UNUSED AND/OR ILLEGAL CHARACTER CODES, THE ; ENTRY IS THE TWO CHARACTER HEXIDECIMAL REPRESENTATION OF THE CODE ; AND HAS BIT <15> SET. ; SPECIAL ACCESS TO TECO'S COMMAND INTERPRETER LOOP .GLOBL CMDDNE ;COMMAND DONE LOCATION IN INTERPRETER LOOP ; OUT: R0, R1, R2, R3, R4 CAN BE CLOBBERED ; ; NOTE: WHEN A COMMAND COMPLETES IT RETURNS TO THIS LOCATION. THE ; NORMAL CONTENTS OF THIS LOCATION IS "TST NFLG(R5)". YOU CAN ; OVERLAY THESE TWO (2) WORDS WITH A "JSR PC,@#XXX" TO CALL ; SOME SPECIAL COMMAND COMPLETION SUBROUTINE; JUST BE SURE TO ; END YOUR ROUTINE WITH "TST NFLG(R5)" IMMEDIATELY BEFORE THE ; "RTS PC". ; SPECIAL ACCESS TO SOME OF TECO'S ROUTINES ; NOTE THAT, ALL ROUTINES REQUIRE R5 TO BE POINTING TO TECO'S READ/WRITE ; AREA AND RETURN R5 UNMODIFIED. .GLOBL CRLF ;JSR PC,CRLF ; OUT: R0 IS CLOBBERED ; ; NOTE: THIS ROUTINE WILL PRINT / ON THE TERMINAL. .GLOBL CRLFNO ;JSR PC,CRLFNO ; OUT: R0 IS CLOBBERED ; ; NOTE: THIS ROUTINE WILL CANCEL ANY CONTROL/O AND ; THEN PRINT / ON THE TERMINAL. .GLOBL DIVD ;JSR PC,DIVD ; IN: R0 = DIVIDEND (UNSIGNED) ; R2 = DIVISOR (UNSIGNED) ; ; OUT: R0 = ANSWER (UNSIGNED) ; R1 = REMAINDER (UNSIGNED) ; R3 IS CLOBBERED .GLOBL IOERR ;JMP IOERR ; IN: R0 = RAD50 OF AN ERROR CODE (3 ALPHANUMERICS) ; R2 -> AN ASCIZ STRING EXPLAINING THE ERROR ; = 0 IF NO EXPLANATION STRING ; ; NOTE: THIS IS AN ERROR CALL AND NO RETURN TO THE CALLER IS MADE. .GLOBL IOERRS ;JMP IOERRS ; IN: R0 = RAD50 OF AN ERROR CODE (3 ALPHANUMERICS) ; R2 -> AN ASCIZ STRING EXPLAINING THE ERROR ; = 0 IF NO EXPLANATION STRING ; R4 = 0 AS A SIGNAL TO ALSO PRINT THE FILENAME BUFFER ; ; NOTE: THIS IS AN ERROR CALL AND NO RETURN TO THE CALLER IS MADE. .GLOBL PRTLIN ;JSR PC,PRTLIN ; OUT: R0, R1, R3, R4 ARE CLOBBERED ; ; NOTE: THIS ROUTINE WILL (RE-)PRINT THE MOST RECENT TECO COMMAND ; LINE USING THE 'TECOIO' ROUTINES "TYPE" AND "PRINT". .GLOBL SIZEQR ;JSR PC,SIZEQR ; IN: R1 = DESIRED SIZE IN BYTES OF THE Q-REGISTER AREA (0<=R1<=077777) ; ; OUT: IF CALL SUCCEEDED THEN THE CARRY IS SET. .GLOBL UPPERC ;JSR PC,UPPERC ; IN: R0 = CHARACTER TO CONVERT TO UPPER CASE IF IT'S LOWER CASE ; ; OUT: R0 = CHARACTER CONVERTED TO UPPER CASE IF IT WAS LOWER CASE ; ; NOTE: THIS ROUTINE IS SIMPLY AN "UPCASE" ROUTINE. .GLOBL ZEROD ;JSR R3,ZEROD ; IN: N(R5) = NUMBER TO CONVERT TO ASCII ; NMRBAS(R5) = 0 FOR DECIMAL CONVERSION (WITH OPTIONAL MINUS SIGN) ; > 0 FOR OCTAL CONVERSION (NO MINUS SIGN EVER) ; < 0 FOR HEXIDECIMAL CONVERSION (NO MINUS SIGN EVER) ; ; OUT: R0, R1, R2, R3, R4 ARE CLOBBERED ; ; NOTE: THE FORMAT OF THIS CALL IS: ; ; JSR R3,ZEROD ; .WORD SUBR ; ; WHERE THE "SUBR" IS THE CHARACTER OUTPUT ROUTINE. "SUBR" WILL ; BE CALLED FOR EVERY CHARACTER OF THE CONVERSION VIA A ; 'JSR PC,' WITH THE CHARACTER IN R0. "SUBR" CAN CLOBBER ; ALL REGISTERS EXCEPT R4 AND R5. ;.GLOBL $E$??? ;JMP $E$??? ; NOTE: THE VARIOUS ERRORS THAT TECO ISSUES ARE ALL GLOBALIZED ; WITH A SYMBOL OF THE FORM $E$??? WHERE THE ??? IS THE ; THREE CHARACTER ERROR ABBREVIATION. $E$MEM IS THE ; MEMORY OVERFLOW ERROR FOR EXAMPLE. ; ; THESE ARE ERROR CALLS AND NO RETURN TO THE CALLER IS MADE. .GLOBL .III.I ;JSR PC,.III.I ; IN: R0 = CHARACTER TO INSERT @ "DOT" ; ; OUT: R0, R1, R2, R3 ARE CLOBBERED .GLOBL .VVV.V ;JSR PC,.VVV.V ; IN: R0 = THE NUMBER OF LINES (PLUS OR MINUS) TO MOVE "DOT" (WHICH ; IS P(R5)) FROM WHERE "DOT" CURRENTLY STANDS. (NOTE: THE ; ARGUMENT BEHAVES JUST LIKE THE L COMMAND TO TECO.) ; ; OUT: R1 = THE NEW "DOT" AS A RELATIVE VALUE (I.E., 0<=R1<=ZZ(R5)) ; P(R5) HAS ALSO BEEN UPDATED TO THE SAME VALUE ; R0, R2, R3 ARE CLOBBERED ; ; NOTE: THIS ROUTINE IS USED BY TECO FOR THE L COMMAND. IF IT IS NOT ; DESIRED THAT "DOT" SHOULD BE ALTERED, THEN THE CALLER MUST ; SAVE P(R5) BEFORE THE CALL AND RESTORE IT UPON RETURN. .GLOBL .YYY.Y ;JSR PC,.YYY.Y ; OUT: R0, R1, R2, R3, R4 ARE CLOBBERED ; ; NOTE: THIS IS SPECIAL ACCESS TO TECO'S ROUTINE FOR THE Y (YANK) ; COMMAND. IF SOME ERROR OCCURS DURING THE YANK NO RETURN WILL ; BE MADE TO THE CALLER. .SBTTL ASSEMBLY PARAMETERS ; IF THE SYMBOL "E$$TXT" IS DEFINED AS NON-ZERO, THEN ALL ERROR ; CALLS (INCLUDING THOSE FROM 'TECOIO') PASS AN ASCIZ ; STRING TO EXPLAIN THE ERROR. IF THE SYMBOL "E$$TXT" IS ; DEFINED AS ZERO, THEN NO ASCIZ STRINGS NEED BE PASSED ; AND NO EXPLANATIONS ARE EVER GIVEN. ; ; FURTHERMORE, IF THE SYMBOL "E$$TXT" IS DEFINED AS 1, THEN ALL ; ERROR MESSAGES IN TECO WILL BE UPPER AND LOWER CASE. IF ; THE SYMBOL "E$$TXT" IS DEFINED AS -1, THEN ALL MESSAGES ; WILL BE UPPER CASE ONLY. ; ; THE DEFAULT IS FOR "E$$TXT" TO BE DEFINED AS 1. .IIF NDF E$$TXT, E$$TXT=1 ;DO THE DEFAULT E$$TXT = E$$TXT ;LIST THE SYMBOL .GLOBL E$$TXT ; AND GLOBALIZE IT .IF GT E$$TXT .ENABL LC ;ONLY IF REQUESTED... .ENDC .SBTTL READ/WRITE AREAS USED BY TECO ; THERE ARE FOUR DIFFERENT READ/WRITE AREAS: ; ; 1) THE MAIN READ/WRITE AREA (TECO'S CRITICAL DATA [AND "WATCH" STATIC DATA]) ; ; THIS AREA IS DIVIDED INTO TWO ADJACENT SECTIONS: ; ; SECTION #1 - TECO'S CRITICAL DATA ; ; LENGTH: DEFINED (FOR 'TECOIO') BY THE TECO DEFINED ; GLOBAL "RWSIZE". THIS IS THIS SECTION'S SIZE ; IN BYTES. ; WHERE: 'TECOIO' DETERMINES WHERE THIS SECTION IS AND ; POINTS TO IT BY SETTING R5 TO POINT TO ITS START. ; SETUP: THIS WHOLE SECTION MUST BE CLEARED TO ALL ZERO ; EXCEPT FOR THE FOLLOWING ITEMS: ; TECOSP (SEE AREA #2) ; TECOPD, PDL, SCHBUF, FILBUF, TAGBUF ; (SEE AREA #3) ; TXSTOR, QRSTOR, ZMAX, QMAX, CURFRE ; (SEE AREA #4) ; INPNTR, OUPNTR (SEE 'TECOIO' SUBROUTINES) ; TECOJP (SEE INTERNAL GLOBALS) ; ETYPE (SET TO, AT LEAST, ET$XIT) ; OUTDNE (SET TO -1) ; SYMSPC (SPECIAL SYMBOL CHARACTER IF ; A-Z, ., AND $ DOESN'T SUFFICE) ; [NOTE: THE ABOVE ITEMS ARE DEFINED BY TECO AS ; GLOBAL OFFSET VALUES FROM R5.] ; ; SECTION #2 - "WATCH" STATIC DATA [OPTIONAL] ; ; LENGTH: THE OPTIONAL MODULE 'CRTRUB' INITIALLY DEFINES THE ; LENGTH OF THIS SECTION. IF "WATCH" IS NOT CONFIGURED ; OR 'CRTRUB' DECIDES THAT THE TERMINAL IS NOT SUPPORTED ; BY "WATCH", THE LENGTH WILL BE ZERO AND REMAIN ZERO. ; WHERE: ASSUMED IMMEDIATELY AFTER SECTION #1 ABOVE. ; SETUP: THIS WHOLE SECTION MUST BE CLEARED TO ALL ZERO ; BEFORE THE INITIAL CALL, IF ANY, TO 'CRTRUB' IS MADE. ; ; 2) THE SP STACK AREA (FOR TECO AND 'TECOIO' USAGE) ; ; LENGTH: WHATEVER SEEMS REASONABLE (200(8) BYTES SEEMS ; A GOOD GUESS). ; WHERE: 'TECOIO' INITIALLY SETS THE STACK POINTER (SP) ; TO POINT TO THE END OF THIS AREA +2. IN ADDITION, ; 'TECOIO' SETS "TECOSP" TO ALSO POINT TO THE END ; OF THIS AREA +2 (I.E., SP STACK RESET VALUE). ; SETUP: NONE NEEDED. ; ; 3) THE PUSH-DOWN LIST, SEARCH BUFFER, FILENAME BUFFER, AND TAG BUFFER ; ; LENGTH: WHATEVER SEEMS REASONABLE (100(8) BYTES FOR ; THE PUSH-DOWN LIST AND 200(8) BYTES EACH FOR THE ; SEARCH, FILENAME, AND TAG BUFFERS SEEM GOODLY NUMBERS). ; NOTE THAT THESE FOUR AREAS ARE COMBINED INTO ONE ; AREA. TECO DEPENDS ON THE FACT THAT THIS IS ; TRUE! FURTHERMORE, THE PUSH-DOWN LIST MUST BE ; THE LOWEST IN ADDRESS SPACE, THE SEARCH BUFFER ; IS NEXT, THE FILENAME BUFFER IS NEXT, AND THE TAG ; BUFFER MUST BE THE HIGHEST IN ADDRESS SPACE. ; WHERE: 'TECOIO' POINTS TO THIS AREA BY SETTING: ; "TECOPD" AND "PDL" TO POINT TO THE AREA'S ; START (PUSH-DOWN LIST). ; "SCHBUF" TO POINT INTO THE MIDDLE OF THE ; AREA (SEARCH BUFFER START). ; "FILBUF" TO POINT INTO THE MIDDLE OF THE ; AREA (FILENAME BUFFER START). ; "TAGBUF" TO POINT INTO THE MIDDLE OF THE ; AREA (TAG BUFFER START). ; SETUP: THIS WHOLE AREA IS CLEARED TO ALL ZERO EXCEPT ; FOR THE LAST BYTE OF THE SEARCH BUFFER, THE LAST ; BYTE OF THE FILENAME BUFFER, AND THE LAST BYTE OF ; THE TAG BUFFER WHICH ARE SET TO -1. ; ; 4) ["WATCH" DYNAMIC DATA,] TEXT BUFFER, Q-REGISTERS, AND FREE SPACE ; ; LENGTH: 'TECOIO' INITIALLY DEFINES THE LENGTH OF THIS AREA, BUT ; ITS SIZE IS CAPABLE OF BEING EXPANDED (IF YOUR ENVIRONMENT ; ALLOWS IT). THE AREA IS ORGANIZED SUCH THAT THE "WATCH" ; DYNAMIC DATA (IF ANY) COMES FIRST (LOWEST IN ADDRESS SPACE), ; TEXT STORAGE COMES NEXT, Q-REGISTER STORAGE COMES NEXT, ; AND FREE SPACE (IF ANY) COMES LAST. WITHOUT "WATCH", THE ; AREA'S LENGTH IS REFLECTED BY THE SUM OF "ZMAX" PLUS ; "QMAX" PLUS "CURFRE" CORRESPONDING TO TEXT SIZE, Q-REGISTER ; SIZE, AND FREE SPACE RESPECTIVELY. IF "WATCH" ALLOCATES ; ITS DYNAMIC DATA, IT WILL START WHERE THIS AREA ORIGINALLY ; STARTED. "WATCH" WILL SHUFFLE UP THE TEXT AND Q-REGISTERS ; AND PUNISH FREE SPACE. IF 'TECOIO' WISHES TO MOVE THIS AREA ; TO ANOTHER LOCATION, IT MUST REMEMBER THE INITIAL STARTING ; ADDRESS OF THE AREA AND, WHEN IT COMES TIME TO SHUFFLE, IT ; 1) FINDS THE SIZE OF THE DATA TO COPY BY COMPUTING ; ((TXSTOR)-(REMEMBERED ADDRESS))+(ZMAX)+(QMAX) ; 2) COPIES THE DATA FROM THE REMEMBERED ADDRESS TO ; THE NEW ADDRESS ; 3) UPDATES TXSTOR AND QRSTOR BY ; (NEW ADDRESS)-(REMEMBERED ADDRESS) ; 4) SETS A NEW REMEMBERED ADDRESS ; THE AREA CAN BE MOVED AT ALL 'TECOIO' CALLS EXCEPT THE ; "SIZER" CALL! ; WHERE: 'TECOIO' SETS UP TWO POINTERS TO THIS AREA ; "TXSTOR" POINTS TO AREA'S START (TEXT START) ; "QRSTOR" POINTS TO AREA'S MIDDLE (Q-REGISTER START) ; AND THREE SIZES FOR THIS AREA ; "ZMAX" INITIAL SIZE OF TEXT ; "QMAX" INITIAL SIZE OF Q-REGISTERS ; "CURFRE" INITIAL SIZE OF FREE SPACE (CAN BE ZERO) ; ONE OF THE 'TECOIO' SUBROUTINE CALLS IS FOR EXPANDING THIS ; AREA. WHEN 'TECOIO' EXPANDS THE AREA (BY ADDING MEMORY TO ; ITS END), 'TECOIO' MUST UPDATE (BY ADDING TO) "CURFRE" TO ; REFLECT THE ADDITION. ; SETUP: NONE NEEDED (BUT ZERO WOULDN'T HURT). .SBTTL EXTERNAL GLOBALS ; "ET" (EDIT TYPEOUT) BITS .GLOBL ET$BIN ; +1., OUTPUT IN BINARY (IMAGE) MODE .GLOBL ET$CRT ; +2., DO SCOPE TYPE RUBOUT AND CONTROL/U .GLOBL ET$LC ; +4., ACCEPT LOWER CASE INPUT .GLOBL ET$NCH ; +8., NO ECHO DURING INPUT FOR CTRL/T .GLOBL ET$CCO ; +16., CANCEL CONTROL/O ON OUTPUT .GLOBL ET$CKE ; +32., RETURN -1 IF ERROR/NO INPUT ON CTRL/T .GLOBL ET$DET ; +64., DETACH AND DETACHED FLAG .GLOBL ET$XIT ; +128., "NO PROMPT YET" FLAG .GLOBL ET$TRU ; +256., TRUNCATE LONG OUTPUT LINES .GLOBL ET$IAS ; +512., INTERACTIVE SCOPE AVAILABLE FOR "WATCH" .GLOBL ET$RFS ; +1024., REFRESH SCOPE AVAILABLE FOR "WATCH" ; +2048., RESERVED BY TECO-8 .GLOBL ET$8BT ; +4096., TERMINAL IS AN 8-BIT TERMINAL .GLOBL ET$GRV ; +8192., ACCEPT "`" AS ESCAPE DURING COMMAND INPUT ;+16384., UNUSED .GLOBL ET$CC ;-32768., ALLOW PROGRAM TO TRAP CONTROL/C ; "ED" (EDIT MODE) BITS .GLOBL ED$CTL ; +1., DON'T ALLOW "^" AS MEANING CONTROL CHARACTER .GLOBL ED$YNK ; +2., ALLOW YANKS, ETC. TO CLOBBER TEXT BUFFER .GLOBL ED$EXP ; +4., DON'T ALLOW ARBITRARY EXPANSION(S) ; +8., RESERVED BY TECO-8 .GLOBL ED$SRH ; +16., DON'T RESET "DOT" ON SEARCH FAILURE .GLOBL ED$IMD ; +32., ALLOW IMMEDIATE MODE COMMANDS .GLOBL ED$INC ; +64., ONLY MOVE "DOT" BY ONE ON ITERATIVE SEARCH FAILURES .GLOBL ED$WCH ; +128., DON'T DO AUTOMATIC "W" COMMAND BEFORE PROMPT ; +256., UNUSED ; +512., UNUSED ; +1024., UNUSED ; +2048., UNUSED ; +4096., UNUSED ; +8192., UNUSED ;+16384., UNUSED ;-32768., UNUSED .SBTTL DOCUMENTATION OF 'TECOIO' SUBROUTINES ; TECO WATCHES THE SIGN BIT (BIT 15) OF THE GLOBAL R5 OFFSET "TFLG" ; AS A 'STOP SOON' INDICATOR. THIS FLAG IS CLEARED EACH ; TIME TECO COMES BACK TO THE MAIN COMMAND LEVEL. IF, DURING THE ; EXECUTION OF TECO, 'TECOIO' WANTS TO STOP TECO (THE RESULT OF A ; CONTROL/C BEING TYPED FOR INSTANCE), ALL 'TECOIO' HAS TO DO IS SET ; BIT 15 INTO THE FLAG. FOR EXAMPLE: ; ; MOVB #-1,TFLG+1(R5) ; -OR- ; BIS #100000,TFLG(R5) ; ; WHEN TECO DETECTS THE SIGN BIT IN THE FLAG IT CALLS THE 'TECOIO' ; SUBROUTINE "STOPON" (SEE BELOW) FOR ANY FURTHER ACTION. ; NOTE THAT, UNLESS A REGISTER IS SPECIFICALLY MENTIONED AS ; OUTPUT FROM A SUBROUTINE, IT MUST BE PRESERVED! .GLOBL ALLERR ;JSR PC,ALLERR ; IN: R0 = RAD50 OF THE ERROR CODE ; ; NOTE: THIS CALL IS MADE EVERY TIME TECO DETECTS AN ERROR. IT ; ALLOWS FOR 'TECOIO' TO TAKE ANY NEEDED CLEANUP ACTION ; REQUIRED SUCH AS RE-ENABLING ECHO AND/OR DISABLING ANY ; INDIRECT COMMAND FILE CURRENTLY ACTIVE. ; ; IN ADDITION, IF 'TECOIO' EXITS FROM THIS ROUTINE WITH ; A JSR PC,@(SP)+ (I.E., A CO-ROUTINE RETURN), THEN IT WILL ; GET CONTROL BACK AFTER THE ERROR MESSAGE HAS BEEN PRINTED ; BY TECO (LESS THE TRAILING CR/LF). .GLOBL BACKUP ;JSR PC,BACKUP ; IN: R0 = POINTER TO BUFFER START ; R1 = NUMBER OF CHARACTERS TO OUTPUT ; R2 = -1 MEANS END BUFFER WITH FORM FEED ; = 0 MEANS DON'T ADD FORM FEED TO BUFFER ; R4 = -(NUMBER OF PAGES TO BACK UP) ; ; OUT: IF NO ERROR THEN CARRY BIT IS CLEAR AND: ; R4 = 0 => THE SPECIFIED NUMBER OF PAGES WERE BACKED UP ; <> 0 => BEGINNING OF FILE WAS HIT DURING THE BACKING UP ; SEE ERROR NOTES IF ERROR. ; ; NOTE: THIS CALL IS MADE FOR -P (BACKWARD PAGE) COMMANDS. ; THE CURRENT TEXT BUFFER AS DESCRIBED BY R0, R1, AND R2 IS ; FIRST SAVED ON THE CURRENT OUTPUT STREAM. THEN THE CURRENT ; INPUT STREAM IS BACKED UP SO THAT THE NEXT 'GETBUF' CALL ; WILL READ THE -(R4)TH PAGE GOING BACKWARDS. NOTE THAT THERE ; NEED NOT BE A CURRENT OUTPUT STREAM IF R1 = R2 = 0. .GLOBL CLSFIL ;JSR PC,CLSFIL ; NOTE: CLOSES THE CURRENTLY SELECTED INPUT FILE AND OUTPUT ; FILE AND DOES ANY EB RENAMING NEEDED. ; ; IF NO ERROR THEN CARRY BIT IS CLEAR. ; SEE ERROR NOTES IF ERROR. .GLOBL CLSOUT ;JSR PC,CLSOUT ; NOTE: CLOSES THE CURRENTLY SELECTED OUTPUT FILE AND DOES ANY ; EB RENAMING NEEDED. ; ; IF NO ERROR THEN CARRY BIT IS CLEAR. ; SEE ERROR NOTES IF ERROR. .GLOBL DELCHR ;JSR PC,DELCHR ; IN: R0 = DELETED CHARACTER ; ; OUT: R0, R1, R2, R3, R4 CAN BE CLOBBERED ; ; NOTE: THIS ROUTINE IS CALLED FOR EVERY CHARACTER "RUBBED OUT". THE ; MOST SIMPLE (AND TTY COMPATIBLE) IMPLEMENTATION IS TO MAKE ; THIS ROUTINE IDENTICAL TO THE 'TECOIO' "TYPE" ROUTINE. .GLOBL DELLIN ;JSR PC,DELLIN ; OUT: R0, R1, R2, R3, R4 CAN BE CLOBBERED ; ; NOTE: THIS ROUTINE IS CALLED EVERY TIME A LINE IS "CONTROL/U'D". THE ; MOST SIMPLE (AND TTY COMPATIBLE) IMPLEMENTATION IS TO MAKE ; THIS ROUTINE IDENTICAL TO THE TECO "CRLF" ROUTINE. .GLOBL FLAGRW ;JSR PC,FLAGRW ; IF: R2 <> 0 THEN FLAG READ/WRITE ; ; IN: R0 = VALUE ABOUT TO BE SET INTO THE FLAG (IF R3=-1) ; R2 = R5 OFFSET TO THE FLAG ; R3 = -1 => SETTING THE FLAG (FROM VALUE IN R0) ; <> -1 => READING THE FLAG (FROM C(R2+R5)) ; ; NOTE: THIS ROUTINE ALLOWS 'TECOIO' DO DETECT WHEN THE USER SETS AND/OR ; READS TECO FLAG VALUES. ; ; IF: R2 = 0 THEN READING EJ FLAG ; ; IN: R0 = -1 => RETURN AN OPERATING SYSTEM DEPENDENT UNIQUE VALUE ; 0 => RETURN A JOB/TASK/PROCESS UNIQUE VALUE (0 TO 99) ; 1 => RETURN JOB'S/TASK'S/PROCESS'S KEYBOARD NUMBER ; 2 => RETURN JOB'S/TASK'S/PROCESS'S PPN/UIC ; ; OUT: R0 = RETURNED EJ FLAG VALUE .GLOBL DATE ;JSR PC,DATE ; OUT: R0 = TODAY'S DATE IN SYSTEM INTERNAL FORM .GLOBL GETBUF ;JSR PC,GETBUF ; IN: R0 = POINTER TO BUFFER START ; R1 = MAXIMUM SIZE OF TRANSFER ; R2 = AMOUNT OF FREE SPACE TO LEAVE ; ; OUT: IF NO ERROR THEN CARRY BIT IS CLEAR AND: ; ZZ(R5) HAS BEEN UPDATED (ADDED TO) TO INDICATE THE AMOUNT ; TRANSFERED INTO THE BUFFER ; FFFLAG(R5) HAS BEEN SET TO: ; -1 IF BUFFER ENDED WITH A FORM FEED ; 0 IF BUFFER ENDED WITHOUT A FORM FEED ; NOTE: THE FORM FEED IS NOT STORED IN THE BUFFER OR ; COUNTED IN ZZ(R5). ; EOFLAG(R5) HAS BEEN SET TO: ; -1 IF FURTHER CALLS WOULD BE FUTILE (I.E., EOF) ; 0 IF FURTHER CALLS MIGHT OBTAIN MORE DATA ; SEE ERROR NOTES IF ERROR. ; ; NOTE: THIS CALL IS MADE FOR 'YANKS' AND 'APPENDS'. ; ; IF THE CALL IS FOR 'YANK' THEN: ; R0 -> START OF TEXT BUFFER ; R1 = CURRENT SIZE OF TEXT BUFFER ; NOTE: THE TEXT BUFFER HAS BEEN ENLARGED AS MUCH ; AS POSSIBLE WITHOUT CALLING FOR THE ; ADDITION OF MORE MEMORY. ; R2 = (1/4) OF THE SIZE OF THE ENLARGED TEXT BUFFER ; NOTE: R2 IS ALWAYS AT LEAST 256. ; ; IF THE CALL IS FOR 'APPEND' THEN: ; R0 -> FREE TEXT BUFFER AREA ; R1 = REMAINING SPACE IN THE ENLARGED TEXT BUFFER ; NOTE: R1 IS ALWAYS AT LEAST 256. FOR THIS CALL. ; R2 = (1/4) OF THE SIZE OF THE ENLARGED TEXT BUFFER ; NOTE: R2 IS ALWAYS AT LEAST 256. ; = R1 FOR 'N:A' (I.E., APPEND ONLY 1 LINE) ; ; THE BUFFER IS FILLED UNTIL: ; ; 1) FORM FEED FOUND. ; 2) LINE FEED FOUND AND (R1 - (# CHARS STORED)) < R2. ; 3) (R1 - (# CHARS STORED)) <= 128. .GLOBL GETFLS ;JSR PC,GETFLS ; IN: R2 = 'B-'R FOR EB CALL ; = 'I-'R FOR EI CALL ; = 'N-'R FOR EN CALL ; = 'R-'R FOR ER CALL ; = 'W-'R FOR EW CALL ; THE FILE SPECIFICATION STRING IS IN THE FILENAME ; BUFFER (STARTING AT FILBUF(R5)) AND IS TERMINATED ; WITH A BYTE OF 0. ; ; OUT: IF NO ERROR THEN CARRY BIT IS CLEAR. ; IF ERROR IS "THAT FILE DOESN'T EXIST" THEN ; 1) CARRY BIT IS SET ; 2) CODE IN R0 IS RAD50 FOR "FNF" ; 3) OPTIONAL ASCIZ STRING POINTER IN R2 ; SEE ERROR NOTES FOR OTHER ERRORS. ; ; NOTE: BY CONVENTION AN ER OR EW CALL WITH A NULL LENGTH FILE ; SPECIFICATION STRING MEANS THAT A SWITCH BACK TO THE ; PRIMARY INPUT OR OUTPUT FILE IS DESIRED. NO ACTUAL I/O ; CALLS NEED BE MADE; ONLY A POINTER SWITCH. ; ; THE R5 OFFSET LOCATIONS "INPNTR" AND "OUPNTR" ARE USED ; BY TECO TO DETERMINE WHETHER THE CURRENTLY SELECTED INPUT ; OR OUTPUT FILE IS OPEN. IF THE DATA POINTED TO BY THE ; ADDRESS IN "INPNTR" OR "OUPNTR" IS 0, THAT INPUT OR OUTPUT ; FILE IS ASSUMED NOT OPEN. ANY NON-ZERO VALUED DATA WORD ; MEANS THE INPUT OR OUTPUT FILE IS OPEN. IT IS THE JOB OF ; 'GETFLS' (AND 'CLSFLS', 'INPSAV', ETC.) TO KEEP THESE ; POINTERS MEANINGFUL. .GLOBL GEXIT ;JSR PC,GEXIT ; IF: NFLG(R5) >=0 THEN "EXIT AND GO" CALL ; ; IN: THE STRING ARGUMENT TO EG IS PASSED IN THE FILENAME ; BUFFER TERMINATED WITH A BYTE OF 0. ; ; NOTE: THIS IS THE WAY TECO EXITS TO THE OPERATING SYSTEM TO ; "GO". ; ; IF: NFLG(R5) <0 THEN "SPECIAL FUNCTION" CALL ; ; IN: N(R5) = -1 (PRESET FOR SUCCESS) ; THE STRING ARGUMENT TO EG IS PASSED IN THE FILENAME ; BUFFER TERMINATED WITH A BYTE OF 0. ; ; OUT: N(R5) = RETURNED VALUE ; ; NOTE: THIS IS THE WAY TECO GETS TO THE OPERATING SYSTEM FOR ; SPECIAL NON-STANDARD FUNCTIONS. .GLOBL INPSAV ;JSR PC,INPSAV ; IN: R3 = -1 => NUMERIC ARGUMENT SPECIFIED (IT IS IN N(R5)) ; <> -1 => NO NUMERIC ARGUMENT SPECIFIED ; ; NOTE: SWITCH TO THE SECONDARY INPUT FILE. THIS SWITCH SHOULD ONLY ; INVOLVE SWITCHING THE "INPNTR" POINTER. .GLOBL KILFIL ;JSR PC,KILFIL ; NOTE: CLOSES AND KILLS THE CURRENTLY SELECTED OUTPUT FILE. ; 'KILFIL' ALSO UNDOES ANY EB RENAMING THAT MIGHT BE PENDING ; ON THE CURRENTLY SELECTED OUTPUT FILE. ; ; IF NO ERROR THEN CARRY BIT IS CLEAR. ; SEE ERROR NOTES IF ERROR. .GLOBL LISTEN ;JSR PC,LISTEN ; IN: R0 = 0 MEANS DELIMITERS ARE: ESCAPE, DELETE, CTRL/U, CTRL/G, ; AND ACCENT GRAVE (BUT ONLY IF "ET$GRV" IN "ETYPE") ; R0 <> 0 MEANS ANYTHING IS A DELIMITER (SINGLE CHARACTER MODE) ; ; OUT: R0 = RETURNED CHARACTER ; ; NOTE: IT IS THE RESPONSIBILITY OF 'LISTEN' TO APPEND A LINE FEED ; TO A CARRIAGE RETURN (IF THE SYSTEM DOESN'T). IT IS ALSO THE ; RESPONSIBILITY OF 'LISTEN' TO ECHO THE TYPED CHARACTERS (IF ; THE SYSTEM DOESN'T) USING THE SAME LOGIC AS THE 'TECOIO' ; ROUTINE "TYPE". 'LISTEN' ALSO IMPLEMENTS "ET$LC" IN "ETYPE" ; (ALLOW LOWER CASE INPUT) AND "ET$8BT" IN "ETYPE" (8-BIT TERMINAL). .GLOBL NOCTLO ;JSR PC,NOCTLO ; NOTE: 'NOCTLO' CANCELS ANY CTRL/O EFFECT CURRENTLY IN PROGRESS. .GLOBL OUTSAV ;JSR PC,OUTSAV ; IN: R3 = -1 => NUMERIC ARGUMENT SPECIFIED (IT IS IN N(R5)) ; <> -1 => NO NUMERIC ARGUMENT SPECIFIED ; ; NOTE: SWITCH TO THE SECONDARY OUTPUT FILE. THIS SWITCH SHOULD ONLY ; INVOLVE SWITCHING THE "OUPNTR" POINTER. .GLOBL PRINT ;JSR PC,PRINT ; IN: R3 = POINTER TO STRING OF CHARACTERS TO PRINT ; R4 = NUMBER OF CHARACTERS TO PRINT (0 <= R4 <= 32767.) ; ; NOTE: 'PRINT' DOES TECO STANDARD CHARACTER CONVERSIONS (IF SYSTEM ; DOESN'T DO IT FOR YOU), BUT IGNORES BOTH "ET$BIN" IN "ETYPE" ; (BINARY OUTPUT MODE) AND "EUFLAG" (CASE FLAGGING). "ET$TRU" ; IN "ETYPE" (TRUNCATE LONG LINES) AND "ET$CCO" IN "ETYPE" ; (CANCEL CONTROL/O) BOTH ALWAYS APPLY. .GLOBL PRINTB ;JSR PC,PRINTB ; IN: R3 = POINTER TO STRING OF CHARACTERS TO PRINT ; R4 = NUMBER OF CHARACTERS TO PRINT (0 <= R4 <= 32767.) ; ; NOTE: 'PRINTB' DOES TECO MOST STANDARD CHARACTER CONVERSIONS (IF SYSTEM ; DOESN'T DO IT FOR YOU), BUT ALWAYS OUTPUTS NULL (ASCII OCTAL 000) ; AND BELL (ASCII OCTAL 007) AS THEMSELVES. IT CHECKS FOR "ET$BIN" ; IN "ETYPE" (BINARY MODE OUTPUT), BUT IGNORES "EUFLAG" (CASE ; FLAGGING). "ET$TRU" IN "ETYPE" (TRUNCATE LONG LINES) APPLIES ; IF "ET$BIN" IN "ETYPE" IS OFF. "ET$CCO" IN "ETYPE" (CANCEL ; CONTROL/O) ALWAYS APPLIES. .GLOBL PRINTF ;JSR PC,PRINTF ; IN: R3 = POINTER TO STRING OF CHARACTERS TO PRINT ; R4 = NUMBER OF CHARACTERS TO PRINT (0 <= R4 <= 32767.) ; ; NOTE: 'PRINTF' DOES TECO STANDARD CHARACTER CONVERSIONS (IF SYSTEM ; DOESN'T DO IT FOR YOU) AND CHECKS, IN THIS PRECEDENCE ORDER, ; "ET$BIN" IN "ETYPE" (BINARY OUTPUT MODE) AND "EUFLAG" (CASE ; FLAGGING). "ET$TRU" IN "ETYPE" (TRUNCATE LONG LINES) APPLIES ; IF "ET$BIN" IN "ETYPE" IS OFF. "ET$CCO" IN "ETYPE" (CANCEL ; CONTROL/O) ALWAYS APPLIES. .GLOBL PUTBUF ;JSR PC,PUTBUF ; IN: R0 = POINTER TO BUFFER START ; R1 = NUMBER OF CHARACTERS TO OUTPUT ; R2 = -1 MEANS END BUFFER WITH FORM FEED ; = 0 MEANS DON'T ADD FORM FEED TO BUFFER ; ; OUT: IF NO ERROR THEN CARRY BIT IS CLEAR. ; SEE ERROR NOTES IF ERROR. .GLOBL SIZER ;JSR PC,SIZER ; IN: R1 = AMOUNT IN BYTES TO EXPAND THE TEXT & Q-REG AREA ; ; OUT: IF AREA CAN BE (AND HAS BEEN) EXPANDED THE AMOUNT DESIRED, ; THEN EXIT WITH THE CARRY CLEAR AND "CURFRE" UPDATED. IF ; THE AREA CANNOT BE EXPANDED THAT AMOUNT, THEN EXIT WITH ; THE CARRY SET AND "CURFRE" UNTOUCHED. ; .GLOBL SIZERB ; NOTE: THIS IS THE AMOUNT TO CALL 'SIZER' WITH WHEN A 'GETBUF' CALL ; DOES NOT RETURN WITH THE FORM FEED FLAG SET (I.E., THE DEFAULT ; AMOUNT TO EXPAND MEMORY IN BYTES). .GLOBL STOPON ;JSR PC,STOPON ; NOTE: WHENEVER TECO DETECTS THE SIGN BIT (BIT 15) IN "TFLG(R5)" IT CALLS ; THIS SUBROUTINE. IF NO FURTHER ACTION IS NEEDED, AS IS THE CASE ; FOR CTRL/C AST SYSTEMS, THE SUBROUTINE CAN SIMPLY EXIT. IF MORE ; PROCESSING IS NEEDED, AS IS THE CASE FOR NON-AST CTRL/C INDICATION ; SYSTEMS, THE SUBROUTINE CAN EITHER: ; ; 1) SIMPLY RETURN - THIS CAUSES THE ?XAB ERROR TO OCCUR. ; ; 2) RETURN TO THE CALLER'S CALLER (E.G., TST (SP)+; RTS PC) - ; THIS CAUSES THE CONTINUED EXECUTION OF TECO. .GLOBL SWITCH ;JSR PC,SWITCH ; OUT: R0 = VALUE OF SWITCH REGISTER .GLOBL TEXIT ;JMP TEXIT ; NOTE: THIS IS THE WAY TECO EXITS TO THE OPERATING SYSTEM. .GLOBL TIME ;JSR PC,TIME ; OUT: R0 = TIME OF DAY IN SYSTEM INTERNAL FORM .GLOBL TLISTN ;JSR PC,TLISTN ; OUT: R0 = RETURNED CHARACTER ; ; NOTE: IT IS THE RESPONSIBILITY OF 'TLISTN' TO APPEND A LINE FEED ; TO A CARRIAGE RETURN (IF THE SYSTEM DOESN'T). IT IS ALSO THE ; RESPONSIBILITY OF 'TLISTN' TO ECHO THE TYPED CHARACTERS (IF ; THE SYSTEM DOESN'T) USING THE SAME LOGIC AS THE 'TECOIO' ; ROUTINE "TYPE" PROVIDED "ET$NCH" IN "ETYPE" IS NOT ON. ; 'TLISTN' ALSO IMPLEMENTS "ET$LC" IN "ETYPE" (ALLOW LOWER CASE ; INPUT), "ET$CKE" IN "ETYPE" (RETURN -1 IF NO INPUT AVAILABLE), ; AND "ET$8BT" IN "ETYPE" (8-BIT TERMINAL). .GLOBL TYPE ;JSR PC,TYPE ; IN: R0 = CHARACTER TO OUTPUT TO TERMINAL ; ; NOTE: 'TYPE' DOES TECO STANDARD CHARACTER CONVERSIONS (IF SYSTEM ; DOESN'T DO IT FOR YOU), BUT IGNORES BOTH "ET$BIN" IN "ETYPE" ; (BINARY OUTPUT MODE) AND "EUFLAG" (CASE FLAGGING). "ET$TRU" ; IN "ETYPE" (TRUNCATE LONG LINES) AND "ET$CCO" IN "ETYPE" ; (CANCEL CONTROL/O) BOTH ALWAYS APPLY. .GLOBL TYPEB ;JSR PC,TYPEB ; IN: R0 = CHARACTER TO OUTPUT TO TERMINAL ; ; NOTE: 'TYPEB' DOES TECO MOST STANDARD CHARACTER CONVERSIONS (IF SYSTEM ; DOESN'T DO IT FOR YOU), BUT ALWAYS OUTPUTS NULL (ASCII OCTAL 000) ; AND BELL (ASCII OCTAL 007) AS THEMSELVES. IT CHECKS FOR "ET$BIN" ; IN "ETYPE" (BINARY MODE OUTPUT), BUT IGNORES "EUFLAG" (CASE ; FLAGGING). "ET$TRU" IN "ETYPE" (TRUNCATE LONG LINES) APPLIES ; IF "ET$BIN" IN "ETYPE" IS OFF. "ET$CCO" IN "ETYPE" (CANCEL ; CONTROL/O) ALWAYS APPLIES. .GLOBL TYPEF ;JSR PC,TYPEF ; IN: R0 = CHARACTER TO OUTPUT TO TERMINAL ; ; NOTE: 'TYPEF' DOES TECO STANDARD CHARACTER CONVERSIONS (IF SYSTEM ; DOESN'T DO IT FOR YOU) AND CHECKS, IN THIS PRECEDENCE ORDER, ; "ET$BIN" IN "ETYPE" (BINARY OUTPUT MODE) AND "EUFLAG" (CASE ; FLAGGING). "ET$TRU" IN "ETYPE" (TRUNCATE LONG LINES) APPLIES ; IF "ET$BIN" IN "ETYPE" IS OFF. "ET$CCO" IN "ETYPE" (CANCEL ; CONTROL/O) ALWAYS APPLIES. .GLOBL WATCH ;JSR PC,WATCH ; IF: NFLG(R5) >=0 THEN SCOPE UPDATE CALL ; ; IN: R0 = NWATCH(R5) FOR THE DEFAULT CALL ; = ARGUMENT VALUE FOR THE EXPLICIT CALL ; ; OUT: R0 = WHAT TO PUT IN NWATCH(R5) FOR LATER DEFAULT CALLS ; (IF R0 IS <0 THEN NWATCH(R5) IS NOT CHANGED) ; ; NOTE: YOU CAN ALSO KEEP SCOPE BUSY AT ANY STALL TIME OF COURSE. ; THE NUMBER OF LINES TO WATCH IS ALWAYS AVAILABLE IN NWATCH(R5). ; ; IF: NFLG(R5) <0 THEN SCOPE PARAMETER READ/ALTER CALL ; IF CLFG(R5) =-1 THEN SCOPE PARAMETER ALTER CALL, M(R5) IS NEW VALUE ; ; IN: R0 = ARGUMENT VALUE (DEFAULT TO ZERO FOR NO EXPLICIT ARGUMENT) ; ; OUT: R0 = PARAMETER VALUE TO RETURN .GLOBL XITNOW ;JSR PC,XITNOW ; NOTE: IF 'TECOIO' CONDITIONED THE TERMINAL NON-NORMALLY FOR ; TECO, THEN THIS IS THE TIME TO UNCONDITION IT. SHOULD ; INPUT AND/OR OUTPUT BE REQUESTED AGAIN BY TECO (ONLY ; HAPPENS IN CASE OF AN I/O ERROR), YOU MUST DETECT THE ; FACT THAT YOU UNCONDITIONED THE TERMINAL AND RE-CONDITION ; IT. ; ERROR NOTES: ; ON ERROR EXITS SET: ; CARRY BIT ON (I.E., "BCS" BRANCHES) ; R0 = RAD50 OF ERROR CODE ; R2 = POINTER TO ASCIZ TEXT OF ERROR (OR 0 FOR NO TEXT) .SBTTL GENERAL PDP-11 DEFINITIONS ; GENERAL REGISTERS R0 = %0 R1 = %1 R2 = %2 R3 = %3 R4 = %4 R5 = %5 SP = %6 PC = %7 .SBTTL CHARACTER DEFINITIONS NUL = 000 ;ASCII NULL BEL = 007 ;ASCII BELL (CONTROL/G) BS = 010 ;ASCII BACKSPACE TAB = 011 ;ASCII HORIZONTAL TAB LF = 012 ;ASCII LINE FEED VT = 013 ;ASCII VERTICAL TAB FF = 014 ;ASCII FORM FEED CR = 015 ;ASCII CARRIAGE RETURN ESC = 033 ;ASCII ESCAPE (ALSO CALLED ALTMODE) SPACE = 040 ;ASCII SPACE APS = '' ;ASCII APOSTROPHE LAB = '< ;ASCII LEFT ANGLE BRACKET EQU = '= ;ASCII EQUAL SIZE RAB = '> ;ASCII RIGHT ANGLE BRACKET UND = '_ ;ASCII UNDERSCORE (ALSO CALLED BACKARROW) GRV = 140 ;ASCII ACCENT GRAVE LCB = 173 ;ASCII LEFT CURLY BRACE VBR = 174 ;ASCII VERTICAL BAR RCB = 175 ;ASCII RIGHT CURLY BRACE TDE = 176 ;ASCII TILDE DEL = 177 ;ASCII DELETE (ALSO CALLED RUBOUT) .SBTTL MACROS .MACRO .DSECT START=0 .PSECT ..ABS.,RW,D,LCL,ABS,OVR .IF NDF ..ABS. ..ABS.: .ENDC . = START!..ABS. .ENDM .DSECT .MACRO SORT TABLE,ENTRY JSR R4,SORT'ENTRY .WORD TABLE .ENDM SORT .MACRO PUSH A,B,C,D,E JSR R4,PUSH .NARG $$$$$$ .BYTE $$$$$$,A $$$$$$ = A-2 .IRP OFFSET, .IF NB $$$$$$ = $$$$$$+2 .IF NE $$$$$$-OFFSET .ERROR ; OFFSET IS OUT OF ORDER .ENDC .ENDC .ENDM .ENDM PUSH .MACRO PUSHP A,B,C,D,E JSR R4,PUSHP .NARG $$$$$$ .BYTE $$$$$$,A $$$$$$ = A-2 .IRP OFFSET, .IF NB $$$$$$ = $$$$$$+2 .IF NE $$$$$$-OFFSET .ERROR ; OFFSET IS OUT OF ORDER .ENDC .ENDC .ENDM .ENDM PUSHP .MACRO POP A,B,C,D,E JSR R4,POP .NARG $$$$$$ .BYTE $$$$$$,A+2 $$$$$$ = A+2 .IRP OFFSET, .IF NB $$$$$$ = $$$$$$-2 .IF NE $$$$$$-OFFSET .ERROR ; OFFSET IS OUT OF ORDER .ENDC .ENDC .ENDM .ENDM POP .MACRO SKPSET CHR JSR R4,SKPSET .WORD CHR .ENDM SKPSET .MACRO TSTNXT CHR JSR R4,TSTNXT .WORD CHR .ENDM TSTNXT .MACRO SIZE AREA .IF IDN , JSR R4,SIZE .WORD ZMAX .IFF .IF DIF , .ERROR ; AREA IS ILLEGAL IN SIZE CALL .ENDC JSR PC,SIZEQR .ENDC .ENDM SIZE .MACRO OFFSET LABEL,AMT LABEL: .BLKW AMT .GLOBL LABEL .ENDM OFFSET .MACRO .TABLE KIND,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z .IF NB .NARG $$$$$$ .IF NE $$$$$$&1 .LIST .ODD .NLIST .ENDC .BYTE -1 .ENDC .IRP CHR, .IF NB .NCHR $$$$$$, .IF EQ $$$$$$-1 .BYTE ''CHR .IFF .BYTE CHR .ENDC .ENDC .ENDM .LIST .'KIND: .NLIST .IRP CHR, .IF NB .WORD KIND''CHR .ENDC .ENDM .ENDM .TABLE .MACRO CMDCHR VAL .SBTTL COMMAND CHARACTER VAL .IRP NUM,<\> $$'NUM: .PSECT TECOCH .IF LE VAL-140 . = VAL*2+TECOCH .IFF . = VAL-32*2+TECOCH .ENDC .NLIST .WORD $$'NUM .LIST .ENDM .PSECT TECORO .ENDM CMDCHR .MACRO MESSAG TEXT .PSECT TECOER $$$$$$ = . .PSECT TECORO .WORD $$$$$$ .PSECT TECOER .NLIST BEX .ASCIZ TEXT .LIST BEX .PSECT TECORO .ENDM MESSAG .MACRO ERROR NUM,TEXT,STRING .IF NDF $E$'NUM $E$'NUM: .ENDC .GLOBL $E$'NUM $$$$$$ = .-$E$'NUM .IF GE $$$$$$-400 JMP $E$'NUM .MEXIT .ENDC .IF NE $$$$$$ BR $E$'NUM .MEXIT .ENDC .IF NE E$$TXT .IF NB JSR R4,ERRORS .RAD50 /NUM/ MESSAG $$$$$$ = 0 .MEXIT .ENDC $$$$$$ = 0 .IRPC CHR, $$$$$$ = $$$$$$*40+<''CHR-<'A-1>> .ENDM .IF EQ $$$$$$&177740-<'N-<'A-1>*40+'A-<'A-1>*40+0> JSR R4,ERRORA $$$$$$ = 1. .IRPC CHR, .IF EQ $$$$$$-3. .BYTE ''CHR-<'A-1> .ENDC $$$$$$ = $$$$$$+1. .ENDM .NCHR $$$$$$, .IF EQ $$$$$$-17. .IRPC CHR, .IF EQ $$$$$$-2. .BYTE ''CHR .ENDC $$$$$$ = $$$$$$-1. .ENDM .MEXIT .ENDC .IF EQ $$$$$$-24. .IRPC CHR, .IF EQ $$$$$$-6. .BYTE ''CHR-100 .ENDC $$$$$$ = $$$$$$-1. .ENDM .MEXIT .ENDC .ERROR ; NUM ERROR IN ILLEGAL FORMAT!! .BYTE '? .MEXIT .ENDC .IF EQ $$$$$$&176037-<'I-<'A-1>*40+0*40+'C-<'A-1>> JSR R4,ERRORC $$$$$$ = 1. .IRPC CHR, .IF EQ $$$$$$-2. .BYTE ''CHR-<'A-1>*5 .ENDC $$$$$$ = $$$$$$+1. .ENDM .NCHR $$$$$$, .IF EQ $$$$$$-21. .IRPC CHR, .IF EQ $$$$$$-12. .BYTE ''CHR .ENDC $$$$$$ = $$$$$$-1. .ENDM .MEXIT .ENDC .IF EQ $$$$$$-30. .IRPC CHR, .IF EQ $$$$$$-18. .BYTE ''CHR-100 .ENDC $$$$$$ = $$$$$$-1. .ENDM .MEXIT .ENDC .ERROR ; NUM ERROR IN ILLEGAL FORMAT!! .BYTE '? .MEXIT .ENDC .IFTF JSR R4,ERRMSG .RAD50 /NUM/ .IFT MESSAG .ENDC .ENDM ERROR .SBTTL Q-REGISTER NUMBER DEFINITIONS NUMQRG = <'Z-'A+1>+<'9-'0+1> ;NUMBER OF Q-REGS PER GROUP (A-Z, 0-9) .DSECT 1 .BLKB NUMQRG ;GLOBAL Q-REGISTERS A-Z & 0-9 AULQRG: .BLKB ;AUXILIARY REGISTER FOR LOCAL SAVE/RESTORE LCLQRG: .BLKB NUMQRG ;LOCAL LEVEL Q-REGISTERS .A-.Z & .0-.9 AUXQRG: .BLKB ;AUXILIARY REGISTER FOR Q-REG PUSH/POP CMDQRG: .BLKB ;COMMAND REGISTER .SBTTL DEFINE THE OFFSETS FROM R5 .DSECT OFFSET SCANP ;COMMAND LINE EXECUTION POINTER .IIF NE SCANP, .ERROR ;"SCANP" MUST BE AT OFFSET 0!! OFFSET MPDL ;MACRO FLAG (SAVED "PDL") OFFSET QCMND ;COMMAND LINE OR MACRO Q-REG NUMBER OFFSET LCLSIZ ;LOCAL LEVEL Q-REG SAVE/RESTORE SIZE OFFSET ITRST ;ITERATION START OFFSET ITRCNT ;ITERATION COUNT OFFSET NOPR ;ARITHMETIC OPERATOR OFFSET NACC ;EXPRESSION ACCULMULATOR OFFSET NFLG ;NUMBER FLAG OFFSET N ;NUMBER OFFSET M ; ARGUMENTS OFFSET OFLG ;OPERATOR FLAG OFFSET CFLG ;COMMA FLAG OFFSET CLNF ;COLON FLAG OFFSET QFLG ;QUOTED STRING FLAG OFFSET OSCANP ;BACKUP FOR "SCANP" OFFSET QUOTE ;QUOTE CHARACTER (NORMALLY ESCAPE) OFFSET QNMBR ;CURRENT Q-REG NUMBER OFFSET QLENGT ;COMMAND LINE LENGTH OFFSET CNDN ;COUNTER FOR " NESTING OFFSET NP ;VALUE OF CURRENT NUMBER OFFSET PST ;CHARACTER POSITION AT SEARCH START OFFSET TEMP ;GENERAL TEMPORARY READ/WRITE WORD OFFSET TFLG ;TRACE FLAG AND STOP INDICATOR OFFSET PCNT ;PAREN PUSH COUNTER OFFSET REPFLG ;REPLACE FLAG CLREND: ;END OF EACH COMMAND CLEAR AREA OFFSET P ;CURRENT TEXT POINTER (.) OFFSET QBASE ;COMMAND LINE Q-REG BASE OFFSET OFFSET NMRBAS ;RADIX (0=>DECIMAL, >0=>OCTAL, <0=>HEXIDECIMAL) OFFSET ERRPOS ;ERROR POSITION OFFSET PDL ;PUSH-DOWN LIST POINTER OFFSET LSCHSZ ;-(LENGTH) OF LAST SKIPPED QUOTED STRING OFFSET EVFLAG ;EDIT VERIFY FLAG OFFSET EUFLAG ;CASE FLAGGING FLAG OFFSET ETYPE ;EDIT TYPEOUT FLAG OFFSET ESFLAG ;EDIT SEARCH FLAG OFFSET EHELP ;EDIT HELP LEVEL OFFSET EEFLAG ;ESCAPE SYNONYM OFFSET EDIT ;EDIT LEVEL FLAG OFFSET SFLG ;SEARCH MODE FLAG OFFSET FFFLAG ;FORM FEED FLAG OFFSET EOFLAG ;END-OF-FILE FLAG OFFSET NWATCH ;NUMBER OF LINES TO DISPLAY ON SCOPE OFFSET CRTYPE ;SCOPE TYPE OFFSET OUTDNE ;MEMORY MESSAGE OUTPUT(+1) AND/OR TERMINAL OUTPUT(+2) OFFSET SEQCTL ;BYTE 0: ESC SEQ MODE ACTIVE; BYTE 1: SEQ IN PROGRESS OFFSET SYMSPC ;EXTRA SYMBOL SPECIAL CHARACTER OFFSET INDIR ;NON-ZERO IF PROCESSING INDIRECT COMMAND FILE OFFSET INPNTR ;@INPNTR(R5) IS NON-ZERO IF INPUT FILE ACTIVE OFFSET OUPNTR ;@OUPNTR(R5) IS NON-ZERO IF OUTPUT FILE ACTIVE OFFSET TXSTOR ;TEXT BUFFER BIAS OFFSET ZMAX ;TEXT BUFFER SIZE OFFSET ZZ ;TEXT BUFFER SIZE IN USE OFFSET QRSTOR ;Q-REG BUFFER BIAS OFFSET QMAX ;Q-REG BUFFER SIZE OFFSET QZ ;Q-REG BUFFER SIZE IN USE OFFSET CURFRE ;CURRENT FREE SPACE IN BYTES OFFSET QARRAY,<*2> ;Q-REGISTER ARRAY OFFSET QPNTR ;COMMAND Q-REGISTER OFFSET OFFSET QLCMD ;SIZE OF LAST COMMAND OFFSET TECOSP ;SP STACK RESET VALUE OFFSET TECOPD ;PDL RESET VALUE OFFSET SCHBUF ;SEARCH BUFFER POINTER OFFSET FILBUF ;FILENAME BUFFER POINTER OFFSET TAGBUF ;TAG BUFFER POINTER OFFSET TECOJP ;COMMAND JUMP DISPATCH TABLE VALUE RWSIZE: ;SIZE OF TOTAL READ/WRITE AREA IN BYTES .SBTTL INITIALIZE TECO'S CODE, LISTENING, DISPATCH, MESSAGE SECTIONS ; INITIALLY DEFINE THE SECTIONS .PSECT TECORO,RO,I,LCL,REL,CON .PSECT TECOLS,RO,I,GBL,REL,OVR .PSECT TECOLT,RO,I,GBL,REL,OVR .PSECT TECOCH,RO,D,GBL,REL,OVR .PSECT TECOER,RO,D,LCL,REL,CON ; INITIALLY DO ONLY NORMAL 'LISTEN' CALLS .PSECT TECOLS TECOLS: JMP LISTEN ;OFF TO THE 'LISTEN' ROUTINE... ; INITIALLY DO ONLY A SIMPLE :^T CALL .PSECT TECOLT TECOLT: JSR PC,TLISTN ;READ A ^T STYLE CHARACTER CLR R1 ;SET CODE 0 FOR NORMAL CHARACTER BIT R0,#^C<237> ;A CONTROL CHARACTER? BNE 10$ ;NO, GO EXIT WITH CODE 0 INC R1 ;SET CODE 1 FOR CONTROL CHARACTER CMP R0,#015 ;IS IT ? BNE 10$ ;NO, GO EXIT WITH CODE 1 JSR PC,TLISTN ;YES, READ THE AFTER THE MOV #015,R0 ;RESTORE CODE AS 10$: RTS PC ;EXIT ; THIS INITIALLY LOADS THE COMMAND DISPATCH TABLE .PSECT TECOCH TECOCH: ;WE NEED A LABEL AT OFFSET=0 .REPT 200-32 ;WHOLE 7-BIT ASCII SET LESS LOWER CASE ALPHA .NLIST .WORD ERROR ;DISPATCH TO "ILLEGAL COMMAND" .LIST .ENDR ; NOW BACK TO THE CODE SECTION .PSECT TECORO ERROR: ERROR ILL,<"Illegal command"> .ENABL LSB 10$: TST QPNTR(R5) ;ANYTHING LEFT TO REMOVE? BEQ 30$ ;NOPE, SO EXIT Z=1 AND C=0 DEC QZ(R5) ;YEP, REMOVE LAST CHARACTER DEC QPNTR(R5) ; ENTERED INTO COMMAND 20$: MOV QZ(R5),R3 ;GET POINTER TO END+1 ADD QRSTOR(R5),R3 ; AND MAKE IT ABSOLUTE MOVB (R3),R0 ; THEN SET THE REMOVED CHARACTER SEC ;SET C=1 TO SAY SOMETHING DONE MOV QPNTR(R5),R4 ;NOW GET SIZE OF THE COMMAND 30$: RTS PC ; AND EXIT WITH Z=1 IF NO COMMAND CHKSTP: TST TFLG(R5) ;SOMEONE TRYING TO STOP US? BPL 50$ ;NO, CONTINUE 40$: CLRB TFLG+1(R5) ;CLEAR THE STOP SOON INDICATOR JSR PC,STOPON ; AND ALERT 'TECOIO' ABOUT IT ERROR XAB,<"Execution aborted"> CMDCHR <'?> ;"?" IS THE TRACE FLIP/FLOP COMB TFLG(R5) ;SO FLIP THE FLOP 50$: RTS PC ; AND EXIT .SBTTL SCAN .CSMDQ: INC CNDN(R5) ;INTO ONE MORE CONDITIONAL LEVEL BR .CSMX ; AND THEN SKIP ONE CHARACTER 60$: CMP (SP),#340$ ;END OF COMMAND; MAIN CALL? BNE 70$ ;NOPE, SO MUST BE AN ERROR CMP MPDL(R5),PDL(R5) ;YES, IN MACRO? BNE 70$ ;NO (OR UNTERMINATED MACRO) POP ITRST,LCLSIZ,QCMND,MPDL,SCANP ;YES, RESTORE ALL ITEMS JSR PC,POPLCL ;GO POP LOCAL Q-REGS IF NEEDED MOV QCMND(R5),R0 ;GET COMMAND Q-REG NUMBER JSR PC,SETCMD ; AND (RE)SET COMMAND .CSMX: ;JUST SKIP NEXT CHARACTER SCAN: MOV (R5),R0 ;GET CURRENT COMMAND POINTER CMP R0,QLENGT(R5) ;END OF THIS COMMAND? BHIS 60$ ;YES, CHECK FOR A MACRO ADD QBASE(R5),R0 ;NO, ADD BASE OF COMMAND Q-REG ADD QRSTOR(R5),R0 ; AND MAKE ABSOLUTE POINTER MOVB (R0),R0 ;GET NEXT CHARACTER INC (R5) ; THEN BUMP POINTER ONE AHEAD TRACE: TST TFLG(R5) ;TRACING? BEQ 50$ ;NOPE BMI 40$ ;NO, BUT TRY TO STOP US NOW JMP TYPE ;YES, SO ANNOUNCE CHARACTER 70$: TST (SP)+ ;PURGE THE RETURN ADDRESS TST MPDL(R5) ;WITHIN MACRO? BEQ 120$ ;NO, BACK TO MAIN EDIT LEVEL ERROR UTM,<"Unterminated macro"> CMDCHR <'C-100> ;"CTRL/C" IS EXIT FROM MACRO/TECO TSTNXT 'C-100 ;TWO CTRL/C'S IN A ROW? BCS 80$ ;YES, ALWAYS EXIT FROM TECO CMP QCMND(R5),#CMDQRG ;ARE WE WITHIN A MACRO NOW? BNE TECO ;YES, JUST ABORT TECO EXECUTION 80$: JMP TEXIT ;NO, TOP LEVEL, SO EXIT RIGHT NOW .SBTTL COMMAND INPUT - STAR .CMDST: CLR R1 ;GUARANTEE NO COMPARES TST QPNTR(R5) ;WAS THIS THE 1ST THING TYPED? BNE 110$ ;NOPE, CHECK FOR PRECEEDING BELL JSR PC,LISTEN ;YEP, SO GET NEXT AS Q-REG NAME CMP R0,#'. ;LOCAL Q-REGISTER NAME PREFIX? BNE 90$ ;NOPE, GLOBAL Q-REG SPECIFIED (R1=0) JSR PC,LISTEN ;YEP, SO GET NEXT AS LOCAL Q-REG NAME MOV #LCLQRG-1,R1 ;FLAG AS LOCAL Q-REG WITH THE OFFSET 90$: JSR PC,QREFR1 ;VALIDATE NAME AND SUM IT MOV QLCMD(R5),R0 ;GET LAST COMMAND'S SIZE ADD R0,QZ(R5) ;INCREASE Q-REG AREA SIZE BY THAT MOV R0,QPNTR(R5) ; AND PLACE IT IN COMMAND Q-REG JSR PC,QADJ ;NOW ADJUST SELECTED REG TO THAT SIZE MOV R2,R3 ;SAVE OFFSET TO SELECTED Q-REG MOV #CMDQRG,R0 ;NOW SET TO SUM THE JSR PC,QSUMX ; COMMAND Q-REG ADD QRSTOR(R5),R3 ;ABS POINTER TO SELECTED Q-REG ADD QRSTOR(R5),R2 ;ABS POINTER TO COMMAND Q-REG MOV (R1),R1 ;GET SIZE OF DATA TO MOVE 100$: DEC R1 ;MORE TO MOVE? BMI TECOCR ;NO, RESTART US MOVB (R2)+,(R3)+ ;YES, MOVE A BYTE BR 100$ ; AND LOOP FOR MORE .SBTTL COMMAND INPUT - SPACE .CMDSP: MOV #LF,R1 ;COMPARE CHARACTER IS LINE FEED 110$: CMP TEMP(R5),#BEL ;PRECEEDED BY A BELL? BNE 200$ ;NO, SO NORMAL JSR PC,CRLFNO ;YES, RETURN THE CARRIAGE JSR PC,10$ ;REMOVE 1ST BELL AND GET POINTER, COUNT BEQ 140$ ;NOTHING, SO RE-PROMPT JSR PC,270$ ;RE-PRINT THE COMMAND LINE(S) BR 170$ ; AND CONTINUE .SBTTL COMMAND INPUT - BELL .CMDBL: MOV #100000,ERRPOS(R5) ;FLAG THIS AS A BELL CMP R0,TEMP(R5) ;2ND BELL? BNE 210$ ;NOPE, SO NORMAL JSR PC,10$ ;REMOVE 1ST BELL AND GET COUNT MOV R4,QLCMD(R5) ;NOW SAVE COUNT AS LAST COMMAND COUNT BR TECOCR ; AND RESTART US .SBTTL COMMAND INPUT - QUESTION MARK ERR4EH: JSR PC,CRLFNO ;NO CTRL/O AND RESTORE CARRIAGE .CMDQU: MOV ERRPOS(R5),R4 ;GET ERROR POSITION BLE 200$ ;IF NONE, THEN NORMAL CHARACTER MOV QBASE(R5),R3 ;GET BASE OF LAST COMMAND ADD QRSTOR(R5),R3 ;NOW MAKE POINTER ABSOLUTE JSR PC,PRINT ; AND PRINT THE ERRING LINE MOV #'?,R0 ;END LINE WITH JSR PC,TYPE ; A "?" .IIF NE .-TECOCR, .ERROR ; AND RESTART US .SBTTL MAIN ENTRY/RE-ENTRY POINT TECOCR: JSR PC,CRLFNO ;NO CTRL/O AND RESTORE CARRIAGE TECO: MOV TECOSP(R5),SP ;SET UP OUR SP STACK MOV TECOPD(R5),PDL(R5) ;NOW SET UP THE PUSH-DOWN LIST 120$: CMP SP,TECOSP(R5) ;IS SP STACK OK? BNE 240$ ;NOPE CMP PDL(R5),TECOPD(R5) ;WAS LAST COMMAND UNTERMINATED? BNE 240$ ;YEP, GO GIVE ERROR JSR PC,CLNLCL ;CLEAN UP ALL LOCAL SAVES MOV #CMDQRG,R0 ;INDICATE THE COMMAND Q-REG JSR PC,QREFR0 ;REFERENCE IT JSR PC,QADJ ; AND ADJUST TO 0 SIZE JSR PC,NOCTLO ;NO CONTROL/O PLEASE TST INDIR(R5) ;PROCESSING INDIRECT COMMANDS? BNE 150$ ;YES, SO NO ANNOUNCEMENTS BIC #ET$XIT,ETYPE(R5) ;NO, SAY PROMPT LEVEL REACHED BIT #ED$WCH,EDIT(R5) ;DO AUTOMATIC "W" COMMAND? BNE 130$ ;NOPE JSR PC,410$ ;YEP, SO GO DO IT 130$: MOV EVFLAG(R5),R0 ;GET THE EDIT VERIFY FLAG BLE 140$ ;<=0, NONE OR DISABLED, NO VERIFY JSR PC,.SCH.V ;ELSE VERIFY AROUND CURRENT . 140$: MOV #'*,R0 ;SET UP TO ANNOUNCE US JSR PC,TYPE ; AND DO IT 150$: MOV QCMND(R5),R0 ;SAVE (POSSIBLE ERRING) COMMAND Q-REG MOV R5,R1 ;GET OFFSET POINTER ADD #CLREND,R1 ; AND INDEX TO CLEAR AREA END (+2) 160$: CLR -(R1) ;NOW CLEAR OUR VARIABLES CMP R1,R5 ;MORE TO CLEAR? BHI 160$ ;YES, CONTINUE MOV R0,QCMND(R5) ;NO, RESTORE COMMAND Q-REG NUMBER JSR PC,IREST ;RESTORE QUOTE TO DEFAULT (ESCAPE) 170$: CLR TEMP(R5) ;AVOID DOUBLE CHARACTER INDICATIONS 180$: MOV ERRPOS(R5),R0 ;SELECT INPUT MODE TST QPNTR(R5) ;IS THIS THE FIRST INPUT REQUEST? BNE 190$ ;NO INC R0 ;YES, FIRST IS ALWAYS SINGLE 190$: JSR PC,TECOLS ;NOW GET A CHARACTER CMP R0,#ESC ;ESCAPE? BEQ 300$ ;YEP, CHECK FOR COMMAND TERMINATION TST INDIR(R5) ;NOPE, FROM AN INDIRECT COMMAND FILE? BNE 200$ ;INDIRECT ACTIVE, NO SPECIALS SORT ..CMD ;ELSE SORT OUT SPECIAL CHARACTERS 200$: CLR ERRPOS(R5) ;NO ERROR POSITION IF STORING 210$: CLR QLCMD(R5) ;NO LAST COMMAND IF STORING ANYTHING MOV #180$,-(SP) ;SET THE RETURN ADDRESS MOV R0,TEMP(R5) ;SAVE CHARACTER ABOUT TO BE STORED 220$: MOV QZ(R5),R1 ;GET OUR CURRENT SIZE CMP R1,QMAX(R5) ;CAN WE DO THIS? BHIS 250$ ;NO, GO GIVE ERROR INC QZ(R5) ;INDICATE 1 MORE IN COMMAND INC QPNTR(R5) ; Q-REGISTER ADD QRSTOR(R5),R1 ;GET POSITION TO STORE IN MOVB R0,(R1) ; AND STORE CHARACTER SUB QRSTOR(R5),R1 ;BACK TO RELATIVE AGAIN ADD #100.,R1 ;FUDGE BY 100. MORE CHARACTERS SIZE QREGS ;GET ROOM FOR THOSE CHARACTERS BCS 230$ ;ALL IS STILL O.K. MOV #BEL,R0 ;IF NOT, THEN RING THE BELL JSR PC,TYPEB ; FOR A WARNING 230$: RTS PC ;NOW CONTINUE 240$: ERROR UTC,<"Unterminated command"> 250$: ERROR MEM,<"Memory overflow"> .SBTTL COMMAND INPUT - DELETE .CMDEL: JSR PC,10$ ;REMOVE A CHARACTER BCC TECOCR ;NONE TO REMOVE, RESTART US JSR PC,DELCHR ;ONE REMOVED, SO SAY SO BR 170$ ; AND CONTINUE .SBTTL COMMAND INPUT - CONTROL/U .CMDCU: JSR PC,10$ ;REMOVE A CHARACTER BCC 260$ ;NONE TO REMOVE, QUIT CMP R0,#LF ;ONE, WAS IS LINE FEED? BNE .CMDCU ;NOT LINE FEED, KEEP REMOVING JSR PC,220$ ;LINE FEED, SO RESTORE IT 260$: JSR PC,DELLIN ;SAY 1 LINE WAS DELETED MOV #170$,-(SP) ;SET CONTINUATION RETURN ADDRESS PRTLIN: JSR PC,20$ ;FIND LINE'S START/LENGTH MOV #LF,R1 ;COMPARE CHARACTER IS LINE FEED 270$: DEC R4 ;ONE LESS IN COUNT NOW BMI 290$ ;ONLY ONE LINE WAS IN COMMAND CMPB R1,-(R3) ;BACKED UP ENOUGH? BNE 270$ ;NO, KEEP GOING INC R3 ;YES, SO CORRECT POINTER 280$: COM R4 ;NEGATE AND DECREMENT COUNT ADD QPNTR(R5),R4 ;FORM THE POSITIVE PRINT COUNT JMP PRINT ;PRINT THE LINE AND EXIT 290$: MOV #'*,R0 ;(RE-)TYPE JSR PC,TYPE ; THE ASTERISK BR 280$ ;NOW GO PRINT THE LINE .SBTTL COMMAND INPUT - ACCENT GRAVE .CMDGV: BIT #ET$GRV,ETYPE(R5) ;CONVERT ACCENT GRAVE INTO ESCAPE? BEQ 200$ ;NOPE MOV #ESC,R0 ;MAKE SURROGATE INTO .SBTTL COMMAND INPUT - ESCAPE 300$: MOV #1,R1 ;PRESUME THIS WAS FIRST THING TYPED TST QPNTR(R5) ;WAS THIS THE FIRST THING TYPED? BEQ ESC.LF ;YES, TREAT IT AS CMP R0,TEMP(R5) ;2ND ESCAPE? 310$: BNE 200$ ;NOPE, SO NORMAL CHARACTER JSR PC,220$ ;YES, SO STORE THE FINAL ESCAPE MOV QPNTR(R5),QLCMD(R5) ; AND SAVE COMMAND AS LAST TST INDIR(R5) ;PROCESSING INDIRECT OCMMANDS? BNE 320$ ;YES, SO NO CARRIAGE RESTORE JSR PC,CRLFNO ;NO, SO RESTORE THE CARRIAGE 320$: MOV #CMDQRG,R0 ;SET UP TO REFERENCE JSR PC,SETCMD ; THE COMMAND REGISTER .SBTTL INTERPRETER 330$: JSR PC,SCAN ;SCAN THE COMMAND 340$: JSR PC,UPPERC ; AND FORCE UPPER CASE 350$: MOVB R0,R1 ;COPY THE CHARACTER W/ SIGN EXTENSION BMI 370$ ;IT'S AN 8-BIT CHARACTER... CLR R0 ;LEAVE R0 (THE AC...) CLEAR MOV R1,R2 ;COPY THE CHARACTER AGAIN CMP R2,#'A+40 ;SPECIAL LOWER CASE CHARACTER? BLO 360$ ;NOPE SUB #32,R2 ;YEP, SO CORRECT CHARACTER 360$: ASL R2 ;DOUBLE CHARACTER FOR A WORD INDEX ADD TECOJP(R5),R2 ;NOW FORM THE JUMP DISPATCH ADDRESS JSR PC,@(R2)+ ; AND GO OFF TO THAT COMMAND... CMDDNE: TST NFLG(R5) ;NUMBER? BMI 330$ ;YES, SO JUST CONTINUE CLR N(R5) ;NO, SO CLEAR THE ARGUMENT CLR NFLG(R5) ; AND RESET NUMBER FLAG BR 330$ ;THEN CONTINUE 370$: ERROR ILL,<"Illegal command"> CMDCHR <'^> ;"^" MEANS NEXT IS CONTROL CHARACTER JSR PC,SCNCTL ;GET NEXT AS CONTROL CHARACTER BR 350$ ; AND CONTINUE WITH IT .SBTTL COMMAND INPUT - LINE FEED .CMDLF: ;MOV #12,R0 ;CODE IS 012 (LINE FEED) .SBTTL COMMAND INPUT - BACKSPACE .CMDBS: ;MOV #10,R0 ;CODE IS 010 (BACKSPACE) MOV R0,R1 ;SAVE THE CODE TST QPNTR(R5) ;WAS THIS THE 1ST THING TYPED? BNE 310$ ;NOPE, SO NORMAL MOV #CR,R0 ;YEP, ENSURE THAT THE CARRIAGE JSR PC,TYPE ; IS AT THE LEFT MARGIN SUB #11,R1 ;FORM THE MOVEMENT AMOUNT (+1 -OR- -1) BPL 380$ ;IT WAS , WE NEED NO TYPING ESC.LF: MOV #LF,R0 ;IT WASN'T A WHICH WAS TYPED, SO JSR PC,TYPE ; OUTPUT THAT NEEDED LINE FEED 380$: MOV #TECO,-(SP) ;SET UP SO FINAL EXIT WILL RETART US MOV P(R5),R4 ;SAVE THE ORIGINAL TEXT BUFFER POINTER MOV R1,R0 ;PUT THE DESIRED MOVEMENT AMOUNT HERE JSR PC,.VVV.V ; AND GO MOVE THE TEXT BUFFER POINTER TST EVFLAG(R5) ;DOES AN EDIT VERIFY FLAG EXIST? BNE 400$ ;ONE EXISTS, WE WON'T TRY TO PRINT CMP R1,R4 ;DID WE MOVE THE POINTER AT ALL? BNE 390$ ;YES, ALWAYS GO TYPE SOMETHING TST R1 ;NO, ARE WE THE BUFFER'S BEGINNING? BNE 400$ ;WE'RE AT THE END, DO NOTHING JSR PC,400$ ;WE'RE AT THE START, UP TWICE & TYPE 390$: MOV #.SCH.T,-(SP) ;DO EQUIVALENT OF "T" BEFORE EXIT 400$: BIT #ET$CRT,ETYPE(R5) ;SCOPE TYPE TERMINAL? BEQ RTS.PC ;NOPE MOV #LF,R0 ;YEP, SET "DELETED" CHAR TO LINE FEED JSR PC,DELCHR ; AND GO DO A CURSOR UP JMP DELLIN ; THEN ERASE THE LINE .SBTTL COMMAND INPUT - CONTROL/W .CMDCW: TST QPNTR(R5) ;WAS THIS THE 1ST THING TYPED? BNE 430$ ;NOPE, SO NORMAL MOV #ET$IAS!ET$CRT,-(SP) ;ARE BOTH "W" COMMAND SUPPORT BIC ETYPE(R5),(SP)+ ; AND SCOPE TERMINAL TRUE? BNE 430$ ;NOPE, SO NORMAL MOV #-1,NFLG(R5) ;SAY THIS IS A ":W" COMMAND CLR CFLG(R5) ; THAT IS READING A PARAMETER MOV #7,R0 ;WE WANT THE SCROLLING SIZE (+7) JSR PC,WATCH ;GO GET THE CURRENT SCOLLING SIZE MOV R0,-(SP) ; AND SAVE IT MOV #'W-100,R0 ;RESTORE CHARACTER AS "^W" CLR NFLG(R5) ; AND CLEAR THE NUMBER FLAG TST (SP)+ ;WAS THERE A SCROLLING SIZE? BEQ 430$ ;NOPE JSR PC,DELCHR ;GO DELETE THE "^W" MOV #-<1000.-1>,R0 ;SAY FORGET ALL POSSIBLE SCREEN LINES JSR PC,420$ ; AND GO DO THAT MOV #170$,-(SP) ;SET CONTINUATION RETURN ADDRESS 410$: MOV NWATCH(R5),R0 ;GET AMOUNT TO SCOPE WATCH 420$: CLR NFLG(R5) ;SAY NOT THE PARAMETER READ/ALTER CALL JMP WATCH ; AND REFRESH THE SCREEN, EXIT 430$: JMP 200$ ;LONG BRANCH FOR NORMAL CHARACTER... .DSABL LSB .ENABL LSB CMDCHR <'L> ;"L" IS THE LINE MOVER .VVV.N: JSR PC,GETN ;GET THE NUMBER OF LINES .VVV.V: MOV TXSTOR(R5),R2 ;GET TEXT POINTER BIAS MOV P(R5),R1 ;GET THE CURRENT . ADD R2,R1 ; AND MAKE THAT ABSOLUTE MOV #FF,R3 ;SPEED UP THE COMPARES TST R0 ;WHICH DIRECTION BLE 30$ ;<=0 IS BACKWARDS ADD ZZ(R5),R2 ;>0 IS FORWARDS; SO GET END OF TEXT 10$: CMP R1,R2 ;PAST END OF TEXT YET? BHIS 20$ ;YES, SO STOP THE MOVE CMPB R3,(R1)+ ;NOPE, IS THIS A FORM FEED? BLO 10$ ;NO, HIGHER, KEEP MOVING CMPB -1(R1),#LF ;YES, OR LOWER, SO CHECK IT BLO 10$ ;CONTINUE ON LOWER THAN LINE FEED DEC R0 ;GOT ONE, MORE TO GO? BGT 10$ ;KEEP GOING 20$: SUB TXSTOR(R5),R1 ;GET THE NEW . MOV R1,P(R5) ; AND STORE IT RTS.PC: RTS PC ;EXIT 30$: CMP R1,R2 ;TOO LOW? BLOS 20$ ;YES, SO QUIT CMPB R3,-(R1) ;NO, IS THIS A FORM FEED? BLO 30$ ;NOPE, HIGHER, KEEP GOING CMPB (R1),#LF ;YEP, OR LOWER, SO CHECK IT BLO 30$ ;CONTINUE ON LOWER THAN LINE FEED INC R0 ;GET ONE, MORE? BLE 30$ ;STILL ARE MORE TO GO INC R1 ;DONE, CORRECT . BR 20$ ; AND GO SET NEW . .DSABL LSB .ENABL LSB CMDCHR ;"<" STARTS AN ITERATION .CSMI: PUSH ITRST,ITRCNT ;SAVE ITERATION START AND COUNT MOV (R5),ITRST(R5) ;SET ITERATION START POINT CLR ITRCNT(R5) ;GUESS AT "INFINITE" ITERATION INC NFLG(R5) ;WAS THERE A NUMBER? BNE 10$ ;NO, SO IT IS "INFINITE" MOV N(R5),ITRCNT(R5) ;YES, USE THAT VALUE THEN BLE .SCH.I ;UNLESS <=0, WHICH IS A NOP BR 10$ ;EXIT RESTORING QUOTE .FFFRAB:;MOV #'>,R0 ;"F>" FLOWS TO ITERATION'S END CMDCHR ;">" ENDS AN ITERATION TST ITRST(R5) ;ARE WE IN AN ITERATION? BEQ 40$ ;NOPE, NO PLACE TO RESTART... TST ITRCNT(R5) ;"INFINITE" ITERATION? BEQ .FFFLAB ;YES, MAKE IT REALLY INFINITE DEC ITRCNT(R5) ;GO AROUND AGAIN? BEQ 20$ ;NO, SO GO END US .FFFLAB:MOV ITRST(R5),(R5) ;"F<" FLOWS TO ITERATION'S START 10$: CLR CFLG(R5) ;USE UP ANY PENDING COMMA CLR OFLG(R5) ; AND ANY PENDING OPERATOR CLR CLNF(R5) ; AND ANY PENDING COLON CLR NFLG(R5) ; AND USE UP ANY NUMBER JMP IREST ; THEN EXIT RESTORING NORMAL QUOTE 20$: TST R0 ;"F>" OR REAL ">"? BEQ .CSMO ;REAL ">", SO END US BR .SCH.I ;"F>", GO FIND END, THEN END US CMDCHR ;"ESC" SIMPLY EATS EVERYTHING TSTNXT ESC ;TWO ESC'S IN A ROW? BCC 10$ ;NOPE, JUST EAT UP AND CONTINUE 30$: MOV QLENGT(R5),(R5) ;SET TO END THIS MACRO/COMMAND RTS PC ; AND SIMPLY EXIT... 40$: TST R0 ;"F>" OR REAL ">"? BNE 30$ ;"F>", JUST GO END THIS MACRO/COMMAND ERROR BNI,<" not in iteration"> CMDCHR <';> ;";" IS SPECIAL ITERATION END TST ITRST(R5) ;ARE WE IN ITERATION? BEQ 70$ ;NO, ERROR INC NFLG(R5) ;ARGUMENT? BNE 80$ ;GIVE ERROR IF NONE INC CLNF(R5) ;COLON MODIFIED? BNE 50$ ;NOPE COM N(R5) ;YEP, REVERSE SENSE OF TEST 50$: TST N(R5) ;SUCCESSFUL? BMI 10$ ;YES, SO JUST CONTINUE .SCH.I: MOV ITRST(R5),-(SP) ;SAVE ITERATION START POINT 60$: SKPSET '> ;GO TO MATCHING > MOV #60$,-(SP) ;GUESS AT RE-CALLING SKPSET CMP 2(SP),ITRST(R5) ;MATCH THIS START POINT? BNE .CSMO ;NO, POP AND CONTINUE CMP (SP)+,(SP)+ ;YES, POP START AND ADDRESS JSR PC,TRACE ; BUT TRACE THE > IF TRACING .CSMO: POP ITRCNT,ITRST ;POP THE COUNT AND START BR 10$ ;GO RESET QUOTE CHARACTER 70$: ERROR SNI,<"; not in iteration"> 80$: ERROR NAS,<"No arg before ;"> .DSABL LSB .ENABL LSB CMDCHR <'=> ;"=" IS THE NUMBER PRINTER INC NFLG(R5) ;ANY NUMBER? BNE 20$ ;AN ERROR IF NOT MOV NMRBAS(R5),-(SP) ;SAVE CURRENT RADIX CLR NMRBAS(R5) ;SET RADIX=DECIMAL INITIALLY(0 = 0) TSTNXT '= ;IS IT REALLY "=="? ADC NMRBAS(R5) ;C=1 IF SO, SET RADIX=OCTAL(1 > 0) TSTNXT '= ;IS IT REALLY "==="?? BCC 10$ ;NOPE NEG NMRBAS(R5) ;YEP, SET RADIX=HEXIDECIMAL(-1 < 0) 10$: JSR R3,ZEROD ;THIS DOES THE REAL WORK .WORD TYPEB ;OUTPUT TO TERMINAL MOV (SP)+,NMRBAS(R5) ;RESTORE THE PREVIOUS RADIX INC CLNF(R5) ;IS THE = COLON MODIFIED? BEQ 30$ ;YES, SO NO CR/LF CLR CLNF(R5) ;NO, CLEAR THE COLON FLAG MOV #CR,R0 ;SET A RETURN JSR PC,TYPEB ; AND TYPE IT MOV #LF-FF,R0 ;NOW SET LINE FEED CMDCHR ;"FF" TYPES OUT A FORM FEED ADD #FF,R0 ;SET A FORM FEED (OR LINE FEED) JMP TYPEB ; AND TYPE IT THEN EXIT 20$: ERROR NAE,<"No arg before ="> CMDCHR <'!> ;"!" IS THE COMMENT DELIMITER CMP (R0)+,(R0)+ ;MAKE R0 = 4 (SKIP 2 WORDS) CMDCHR <'A-100> ;"CTRL/A" IS THE TEXT PRINTER MOV R0,R2 ;SAVE DETERMINATION CLR NFLG(R5) ;USE UP ANY NUMBER MOV R1,QUOTE(R5) ;END CHARACTER IS SAME AS STARTING JSR PC,QSKPR0 ;SKIP STRING AND RESTORE QUOTE MOV R0,R4 ;MOVE STRING SIZE TO CORRECT PLACE ADD QBASE(R5),R3 ;MAKE THE START POINTER ADD QRSTOR(R5),R3 ; FULLY ABSOLUTE ADD R2,PC ;SKIP PRINT IF REALLY A COMMENT JSR PC,PRINTB ; ELSE PRINT THE STRING BR 30$ ;NOW EXIT CMDCHR <'\> ;"\" IS NUMBER INSERTER/GETTER CLR LSCHSZ(R5) ;PRE-CLEAR INSERT/GET SIZE INC NFLG(R5) ;WAS THERE AN ARGUMENT? BNE 40$ ;NO, SO GET A NUMBER FROM TEXT JSR R3,ZEROD ;YES, INSERT NUMBER INTO TEXT .WORD .BSL.I 30$: RTS PC ;NOW EXIT 40$: JSR PC,NCOM ;SET UP NUMBER PROCESSOR JSR PC,GETXTP ;GET CHAR FROM TEXT BCC 30$ ;NOTHING THERE SUB #'+,R0 ;PLUS SIGN? BEQ 50$ ;YES, IGNORE IT CMP R0,#'--'+ ;MINUS SIGN? BNE 60$ ;NOPE MOV R0,NOPR(R5) ;YES, SET MINUS OPERATOR 50$: JSR PC,.BSL.P ;BUMP . AND COUNT IT 60$: JSR PC,GETXTP ;GET CHARACTER FROM TEXT BCC 30$ ;EXIT IF NO MORE TST NMRBAS(R5) ;RADIX? BGE 70$ ;DECIMAL OR OCTAL JSR PC,UPPERC ;HEXIDECIMAL, MAKE UPPER CASE CMP R0,#'A ;WITHIN HEXIDECIMAL RANGE? BLO 70$ ;NEVER CMP R0,#'F ;MIGHT BE... BLOS 80$ ;IT IS, USE IT 70$: JSR PC,NUMER ;CHECK FOR NUMERIC BCC 30$ ;NOT A NUMBER TST NMRBAS(R5) ;WHAT IS THE RADIX? BLE 80$ ;IT IS DECIMAL OR HEXIDECIMAL CMP R0,#'8 ;IT IS OCTAL, VALID DIGIT? BHIS 30$ ;NOT AN OCTAL DIGIT 80$: MOV R0,R1 ;MOVE DIGIT OVER TO HERE JSR PC,.BSL.N ;NUMBER, SO USE IT BR 50$ ; AND CONTINUE .DSABL LSB .ENABL LSB CMDCHR <'"> ;'"' IS THE CONDITIONAL INC NFLG(R5) ;ANY ARGUMENT? BNE 10$ ;THERE HAD BETTER BE SORT ..CND,C ; AND SPECIAL SORT ERROR IQC,<'Illegal " character'> 10$: ERROR NAQ,<'No arg before "'> .CNDV: ADD #ALPHAL-ALPHAU,R2 ;"V" IS LOWER CASE A-Z .CNDW: ADD #ALPHAU-SYMCHR,R2 ;"W" IS UPPER CASE A-Z .CNDC: ADD #SYMCHR-NUMER,R2 ;"C" IS SYMBOL CHARACTERS .CNDD: ADD #NUMER-ALPHA,R2 ;"D" IS 0-9 .CNDA: ADD #ALPHA-ALPHAN,R2 ;"A" IS A-Z .CNDR: ADD #ALPHAN,R2 ;"R" IS A-Z,0-9 MOV R3,R0 ;SET UP TEST CHARACTER JSR PC,(R2) ; AND GO CHECK IT BCS 50$ ;CARRY SET IS SUCCESS BR 20$ ;ELSE FAILURE .CNDN: TST R3 ;SET CC'S BNE 50$ ;"N" IS OK IF <> BR 20$ ;ELSE NOT OK .CNDRAB: ;">" IS OK IF > .CNDG: NEG R3 ;"G" IS OK IF > BVS 20$ ;TRAP -32768. CASE .CNDS: ;"S" IS SUCCESSFUL (-1) .CNDT: ;"T" IS TRUE (-1) .CNDLAB: ;"<" IS OK IF < .CNDL: TST R3 ;SET CC'S BMI 50$ ;"L" IS OK IF < BR 20$ ;ELSE NOT OK .CNDF: ;"F" IS FALSE (0) .CNDU: ;"U" IS UNSUCCESSFUL (0) .CNDEQU: ;"=" IS OK IF = .CNDE: TST R3 ;SET CC'S BEQ 50$ ;"E" IS OK IF = 20$: CLR R4 ;MATCH ' OR VBAR (IGNORE NOTHING) 30$: CLR CNDN(R5) ;INTO 1 LEVEL OF CONDITIONAL SKIP 40$: SKPSET ;SKIP TO A ' OR VERTICAL BAR CMP R0,R4 ;SHOULD WE IGNORE THIS HIT? BEQ 60$ ;YES TST CNDN(R5) ;ARE WE BACK TO THE ORIGINAL LEVEL? BNE 60$ ;NOT YET... JSR PC,TRACE ;TRACE FINAL ' OR VBAR IF TRACING CMDCHR <''> ;"'" IS END OF A CONDITIONAL 50$: CLR NFLG(R5) ;USE UP ANY NUMBER JMP IREST ;RESTORE QUOTE AND EXIT 60$: CMP R0,#VBR ;WAS IT A VBAR WE SAW? BEQ 40$ ;SAW VBAR, DON'T CHANGE THE LEVEL DEC CNDN(R5) ;SAW "'", CHANGE LEVEL BY ONE BPL 40$ ;CONTINUE SKIPPING IF LEVEL O.K. BR 30$ ;WHOOPS, UNDERFLOW, GO RESET LEVEL .FFFAPS: ;"F'" IS FLOW TO CONDITIONAL'S END CMDCHR ;"VERTICAL BAR" IS SKIP TO NEXT ' MOV #VBR,R4 ;MATCH ONLY ' (IGNORE VBAR) BR 30$ ; AND GO SKIP SOME... .FFFVBR:MOV #'',R4 ;"F" IS FLOW TO ELSE BR 30$ ;GO MATCH ONLY VBAR (IGNORE ') .DSABL LSB .ENABL LSB CMDCHR <'U-100> ;"CTRL/U" IS Q-REG TEXT INSERT JSR R4,70$ ;REFERENCE THE Q-REG AND GET BIAS JSR PC,QSKPR0 ;NOW SKIP THE QUOTED STRING BNE 10$ ;INSERT STRING EXISTS INC NFLG(R5) ;NO STRING, IS THERE AN ARGUMENT? BNE 20$ ;NO ARGUMENT EITHER, DO A NULL INSERT INC R0 ;ARGUMENT EXISTS, SET SIZE=1 MOV (SP),-(SP) ;RE-STACK THE APPEND SIZE MOV #50$,2(SP) ; SO WE CAN SET A RETURN ADDRESS 10$: INC NFLG(R5) ;ARGUMENT WITH NON-NULL STRING? BEQ 90$ ;YES, THAT'S AN ERROR 20$: ADD (SP),R0 ;UPDATE SIZE AS NEEDED JSR PC,QADJ ;ADJUST Q-REG TO ITS NEW SIZE CLR NFLG(R5) ;USE UP ANY NUMBER MOV OSCANP(R5),R0 ;GET INSERT STRING START ADD QBASE(R5),R0 ; AND ADD IN OFFSET ADD QRSTOR(R5),R0 ;NOW MAKE IT ABSOLUTE BR 30$ ; AND GO INSERT IT IN Q-REG CMDCHR <'X> ;"X" IS Q-REG TEXT INSERT JSR R4,70$ ;REFERENCE THE Q-REG JSR PC,NLINES ;GET NUMBER OF CHARACTERS ADD (SP),R0 ;UPDATE SIZE AS NEEDED JSR PC,QADJ ;ADJUST Q-REG TO ITS NEW SIZE MOV M(R5),R0 ;GET START OF TEXT ADD TXSTOR(R5),R0 ; AND MAKE IT ABSOLUTE 30$: ADD (SP),R2 ;BIAS THE POINTER AS NEEDED ADD QRSTOR(R5),R2 ;MAKE POINTER TO Q-REG ABSOLUTE MOV (R1),R1 ;NOW GET SIZE OF Q-REG SUB (SP)+,R1 ; LESS THE BIAS SIZE 40$: DEC R1 ;MORE TO MOVE? BMI 60$ ;NO, DONE MOVB (R0)+,(R2)+ ;YES, MOVE A BYTE BR 40$ ; AND LOOP FOR MORE 50$: MOVB N(R5),-(R2) ;PUT ARGUMENT VALUE THERE INSTEAD 60$: RTS PC ;EXIT 70$: JSR PC,QREF ;REALLY REFERENCE THE Q-REG MOV (R1),(SP) ;SAVE ITS CURRENT SIZE TST CLNF(R5) ;APPEND TO Q-REG? BMI 80$ ;YES, LEAVE THE OLD SIZE AS BIAS CLR (SP) ;NO, SO NO BIAS 80$: CLR CLNF(R5) ;TURN OFF THE COLON FLAG JMP (R4) ; AND EXIT 90$: ERROR IIA,<"Illegal insert arg"> .DSABL LSB .ENABL LSB CMDCHR <'F> ;"F" IS PREFIX FOR SPECIAL SEARCHES SORT ..FFF,S ; AND SORT ON IT ERROR IFC,<"Illegal F character"> .FFFC: MOV #-1,REPFLG(R5) ;"FC" IS BOUNDED SEARCH & REPLACE .FFFB: JSR PC,SEARCB ;"FB" IS BOUNDED SEARCH, GO SEARCH BR 10$ ; THEN GO FINISH UP .FFFS: MOV #-1,REPFLG(R5) ;"FS" IS SEARCH & REPLACE, SET FLAG CMDCHR <'S> ;"S" IS SEARCH JSR PC,SEARCH ;SEARCH FOR THE STRING 10$: TST REPFLG(R5) ;REPLACEMENT? BEQ 30$ ;NOPE MOVB R1,-(SP) ;YES, SO SAVE SUCCESS/FAILURE FLAG JSR PC,QSKP ; AND SKIP THE 2ND STRING MOVB (SP)+,R1 ;RESTORE SUCCESS/FAILURE FLAG BEQ 20$ ;NO REPLACEMENT IF FAILURE MOV PST(R5),R0 ;GET START OF FOUND STRING SUB P(R5),R0 ; AND NOW ITS -(LENGTH) MOV PST(R5),P(R5) ;THEN UPDATE . JSR PC,.SCH.R ;DO REPLACEMENT MOV #-1,R1 ;RESTORE SUCCESS FLAG 20$: CLR REPFLG(R5) ;CLEAR REPLACE FLAG 30$: JSR PC,IREST ;RESTORE ESCAPE AS QUOTE MOVB R1,R0 ;GET REAL NUMBER IN R0 JSR PC,NCOM ;INIT THE NUMBER PROCESSOR TST CLNF(R5) ;WAS THERE A ":" THERE? BMI 90$ ;YES, SO JUST RETURN FLAG CLR CLNF(R5) ;ELSE SET FLAG TO FALSE MOV ITRST(R5),R4 ;IN AN ITERATION? BEQ 50$ ;NOPE MOVB TFLG(R5),-(SP) ;YEP, SAVE TRACE FLAG CLRB TFLG(R5) ; THEN TURN OFF TRACING TSTNXT <';> ;IS SEARCH CHECKED FOR? BCS 80$ ;CHECKED FOR, SO RETURN VALUE TSTNXT ': ;CHECKED FOR BY ":;"? BCC 40$ ;CAN'T BE... TSTNXT <';> ;MIGHT BE, IS IT? BCS 70$ ;IT IS, SO RETURN VALUE DEC (R5) ;MAKE SURE WE SEE THE ":" AGAIN 40$: MOVB (SP)+,TFLG(R5) ;NOT CHECKED, RESTORE TRACE FLAG CLR NFLG(R5) ; AND EAT UP THE NUMBER TST N(R5) ;WAS SEARCH SUCCESSFUL BMI 100$ ;ALL O.K., SO JUST CONTINUE .IF NE E$$TXT JSR PC,CRLFNO ;NO CTRL/O AND RESTORE CARRIAGE MOV (PC)+,R3 ;GET MESSAGE POINTER MESSAG <"%Search fail in iter"> .PSECT TECOER . = .-1 ;BACK OVER ZERO BYTE $$$$$$ = .-$$$$$$ ;NOW FIND THE MESSAGE LENGTH .PSECT TECORO MOV #$$$$$$,R4 ;GET MESSAGE SIZE JSR PC,PRINT ;SO WE CAN PRINT A WARNING .ENDC JMP .SCH.I ;ELSE GET OUT OF ITERATION 50$: CLR NFLG(R5) ;USE UP THE NUMBER TST N(R5) ;SUCCESSFUL? BPL 60$ ;NOPE MOV ESFLAG(R5),R0 ;YES, GET EDIT SEARCH FLAG BEQ 90$ ;=0, SO EXIT JMP .SCH.V ;ELSE GO PRINT SOMETHING 60$: ERROR SRH,<"Search failure"<-1>>,STRING 70$: DEC (R5) ;MAKE SURE WE SEE THE ":;" 80$: DEC (R5) ;MAKE SURE WE SEE THE ";" MOVB (SP)+,TFLG(R5) ;RESTORE TRACE FLAG 90$: CLR CLNF(R5) ;CLEAR COLON FLAG 100$: RTS PC ;THEN EXIT .FFFN: TST (PC)+ ;"FN" IS PAGING SEARCH & REPLACE, C=0 .FFFUND:SEC ;"F_" IS DESTRUCT SEARCH & REPLACE, C=1 MOV #-1,REPFLG(R5) ;INDICATE A REPLACE BIC R0,R0 ;SET TO DO BUFFER DUMPING .IIF NE <150$-140$>, .ERROR ;BUFFER DUMPING HAS BEEN MISPLACED! .IIF NE <150$-140$>&^C<377>, .ERROR ;DISPATCH OFFSET MUST BE 0-377! BCC 110$ ;NOW JOIN UP IF "FN" CMDCHR <'_> ;"_" IS DESTRUCTIVE SEARCH MOV #180$-140$,R0 ;SET TO SKIP BUFFER DUMPING .IIF NE <180$-140$>&^C<377>, .ERROR ;DISPATCH OFFSET MUST BE 0-377! .IIF NE .-110$, .ERROR ;DISPATCH STORING HAS BEEN MISPLACED! CMDCHR <'N> ;"N" IS THE PAGING SEARCH ;CLR R0 ;SET TO DO BUFFER DUMPING .IIF NE <150$-140$>, .ERROR ;BUFFER DUMPING HAS BEEN MISPLACED! .IIF NE <150$-140$>&^C<377>, .ERROR ;DISPATCH OFFSET MUST BE 0-377! 110$: MOV R0,TEMP(R5) ;SAVE DISPATCH OFFSET JSR PC,SEARCH ; AND SEARCH 120$: BPL 130$ ;CONTINUE IF FORWARD DIRECTION FAILURE BIT R1,#377!400 ;SUCCESS(-1) OR BOUNDED FAIL(177400)? BNE 10$ ;ONE OF THE ABOVE, WE'RE DONE... NEG R2 ;BACKWARDS FAIL(1X0000), NEGATE COUNT 130$: MOV R2,-(SP) ;SAVE THE SEARCH COUNTER ADD TEMP(R5),PC ; AND DISPATCH TO CORRECT ROUTINE... 140$: ;REFERENCE ONLY 150$: TST (SP) ;WHAT DIRECTION ARE WE GOING? BMI 200$ ;BACKWARDS, MUST GO BACK UP A PAGE JSR PC,.PPP.P ;FORWARDS, GO DUMP THIS TEXT BUFFER 160$: JSR PC,.YYY.Y ;UNCONDITIONALLY YANK IN A TEXT PAGE 170$: MOV (SP)+,R2 ;RESTORE SEARCH COUNTER BIC R1,R1 ;PRE-INDICATE A FAILURE BCS 10$ ;NO DATA READ, SAY FAILURE JSR PC,CHKSTP ;CHECK FOR STOP FLAG NOW ON JSR PC,.SURCH ;CONTINUE THE SEARCH BR 120$ ;NOW CHECK FOR FAILURE AGAIN... 180$: JSR PC,.YYY.P ;DO WE PASS YANK PROTECTION? 190$: TST (SP) ;WHAT DIRECTION ARE WE GOING? BPL 160$ ;FORWARDS, JUST GO YANK THE NEXT PAGE JSR PC,.YYY.C ;BACKWARDS, ZAP THE TEXT BUFFER 200$: MOV #-1,R4 ;SET TO GO BACKWARDS ONE PAGE JSR PC,.PPP.B ; AND THEN GO OFF AND DO IT MOV ZZ(R5),P(R5) ;SET .=Z (KEEPING C-BIT) BR 170$ ;CONTINUE W/ C-BIT INDICATION... .EEEUND:MOV #190$-140$,R0 ;"E_" IS "_" WITHOUT YANK PROTECTION .IIF NE <190$-140$>&^C<377>, .ERROR ;DISPATCH OFFSET MUST BE 0-377! MOV R3,NFLG(R5) ;RESTORE THE ARGUMENT FLAG BR 110$ ;GO JOIN THE COMMON FLOW .DSABL LSB .ENABL LSB 10$: JSR PC,CVTSRH ;GO CONVERT THE SPECIAL(S) 20$: JSR PC,TYPEF ;TYPE A CHARACTER WITH CASE FLAGGING TYPSPC: MOVB (R2)+,R0 ;FETCH A STRING CHARACTER BMI 10$ ;IT'S A SPECIAL CHARACTER... BNE 20$ ;GO PRINT IF THERE'S SOMETHING THERE RTS PC ;EXIT .DSABL LSB .ENABL LSB CMDCHR <'G> ;"G" IS GET Q-REG INTO TEXT CLR NFLG(R5) ;USE UP ANY NUMBER JSR PC,GETQRG ;GET Q-REG OR "_" OR "*" BCC 20$ ;IT WAS "_" OR "*" INC CLNF(R5) ;COLON MODIFIED? BEQ 80$ ;YES, SO REALLY PRINT IT 10$: CLR CLNF(R5) ;CLEAR THE COLON FLAG MOV R2,-(SP) ;SAVE OFFSET TO Q-REG MOV R0,-(SP) ;SAVE INSERT LENGTH COM (SP) ;MAKE IT -(LENGTH)-1 BR 110$ ;NOW REALLY INSERT IT 20$: INC CLNF(R5) ;COLON MODIFIED? BEQ TYPSPC ;YES, SO REALLY PRINT IT MOV R2,R4 ;SAVE POINTER TO DATA 30$: CMPB (R2),#200 ;IS THIS THE SPECIAL DUMMY CODE? BNE 40$ ;NOPE DEC R0 ;YEP, PUNISH LENGTH BY ONE 40$: TSTB (R2)+ ;IS THIS THE END? BNE 30$ ;NOPE, KEEP CHECKING... CLR R2 ;DUMMY AN INSERT OFFSET JSR PC,10$ ;NOW DO THAT DUMMY INSERT MOV LSCHSZ(R5),R3 ;GET BACK THE -(LENGTH) BEQ 70$ ;LENGTH=0, EXIT ADD R3,R1 ;ELSE BACK UP THE INSERT POINTER MOV R4,R2 ; AND RESTORE THE DATA POINTER 50$: MOVB (R2)+,R0 ;REALLY GET THE INSERT DATA BPL 60$ ;IT'S NOT A SPECIAL JSR PC,CVTSRH ;GO CONVERT THE SPECIAL(S) 60$: MOVB R0,(R1)+ ;STORE IN THE INSERT AREA INC R3 ;MORE? BNE 50$ ;YES, LOOP 70$: RTS PC ;NO, DONE 80$: ADD QRSTOR(R5),R2 ;MAKE THE POINTER ABSOLUTE MOV R0,R4 ;SET THE PRINT COUNT MOV R2,R3 ; AND POINTER JMP PRINTF ; THEN PRINT IT AND EXIT CMDCHR <'I-100> ;"TAB" IS SPECIAL FORM OF "I" JSR PC,QSKPR0 ;SKIP THE QUOTED STRING DEC OSCANP(R5) ;THEN ENCLUDE THE TAB WITHIN IT JSR PC,90$ ;DO THE STRING INSERTION NOW ADD LSCHSZ(R5),R1 ;GET ABS POINTER TO START OF INSERTION MOVB #TAB,(R1) ; AND ENSURE TAB AS STARTING CHARACTER RTS PC ;EXIT ALL DONE CMDCHR <'I> ;"I" IS INSERT TEXT JSR PC,QSKPR0 ;SKIP THE QUOTED STRING BNE 90$ ;<>0 LENGTH, A REAL INSERT INC NFLG(R5) ;NUMBER TO INSERT? BNE 100$ ;NOPE, THE NULL INSERT... MOV N(R5),R0 ;YEP, SO GET THE NUMBER .III.I: CLR LSCHSZ(R5) ;PRE-CLEAR THE INSERT SIZE .BSL.I: BIC #^C<377>,R0 ;MAKE INTO A VALID CHARACTER MOV R0,-(SP) ; AND SAVE IT MOV #1,R0 ;ADJUST TEXT UP BY JSR PC,ADJ ; 1 CHARACTER MOV P(R5),R1 ;GET . ADD TXSTOR(R5),R1 ;MAKE ABSOLUTE MOVB (SP)+,(R1) ; AND STORE NEW CHARACTER .BSL.P: INC P(R5) ;BUMP . DEC LSCHSZ(R5) ; AND CORRECT INSERT SIZE RTS PC ; THEN EXIT 90$: INC NFLG(R5) ;WAS THERE AN ARGUMENT? BEQ 140$ ;YES, ERROR 100$: CLR R0 ;INDICATE NO BIAS .SCH.R: MOV OSCANP(R5),R3 ;GET STRING START MOV R3,-(SP) ; AND SAVE START ADD QBASE(R5),(SP) ;START NOW REAL SUB (R5),R3 ;NOW HAVE -(LENGTH)-1 SUB R3,R0 ;NOW HAVE (LENGTH)+1+(BIAS) DEC R0 ;NOW HAVE (LENGTH)+(BIAS) MOV R3,-(SP) ;SAVE INSERT -(LENGTH)-1 110$: JSR PC,ADJ ;ADJUST TEXT BUFFER SIZE MOV (SP)+,R3 ;RESTORE INSERT -(LENGTH)-1 INC R3 ;NOW MAKE INTO -(LENGTH) MOV (SP)+,R2 ;RESTORE STARTING POINT ADD QRSTOR(R5),R2 ;MAKE THE START ABSOLUTE MOV R3,LSCHSZ(R5) ;SAVE TEXTUAL -(LENGTH) BEQ 130$ ;EXIT RIGHT NOW IF NO LENGTH MOV P(R5),R1 ;NOW GET . SUB R3,P(R5) ;THEN UPDATE . TO INSERT'S END ADD TXSTOR(R5),R1 ; AND MAKE . ABOLUTE 120$: MOVB (R2)+,(R1)+ ;DO THE REAL INSERTION INC R3 ; FOR THE BNE 120$ ; WHOLE LENGTH 130$: RTS PC ;THEN EXIT 140$: ERROR IIA,<"Illegal insert arg"> .DSABL LSB .ENABL LSB 10$: ERROR IPA,<"Illegal P arg"> 20$: BEQ 10$ ;ERROR IF =0 PAGE WRITE COUNT TSTB TEMP(R5) ;"PW"? BMI 10$ ;YES, ALSO AN ERROR MOV #CLNXIT,-(SP) ;SET RETURN FOR COLON CHECKING .PPP.B: MOV TXSTOR(R5),R0 ;FROM THE BEGINNING TO MOV ZZ(R5),R1 ; THE END (ALL OF TEXT) MOV FFFLAG(R5),R2 ; WITH OPTIONAL FORM FEED JSR PC,BACKUP ;GO BACK UP ABS(R4) PAGES BCS IOERR ;I/O TYPE ERROR, DIE JSR PC,.YYY.C ;CLEAR AND SIZE UP THE TEXT BUFFER CLR EOFLAG(R5) ; AND SAY NOT AT END-OF-FILE NEG R4 ;SET C=1 IF ALL WAS NOT DONE BCS 80$ ;GO EXIT NOW IF ALL WASN'T DONE BR .YYY.Y ;SIMULATE THE YANK & EXIT W/ C-BIT 30$: MOV #-1,R2 ;GUESS AT ALWAYS A FINAL FORM FEED TSTB TEMP(R5) ;GOOD GUESS ("PW")? BMI 40$ ;YES .PPP.P: MOV FFFLAG(R5),R2 ;NO, OPTIONAL FORM FEED ("P") 40$: MOV TXSTOR(R5),R0 ;FROM THE BEGINNING TO MOV ZZ(R5),R1 ; THE END (ALL OF TEXT) BR 100$ ;NOW GO DO IT... CMDCHR <'P> ;"P" IS PAGE WRITER .SBTTL COMMAND CHARACTER "PW TSTNXT 'W ;REALLY "PW"? RORB TEMP(R5) ;SAVE THE DETERMINATION TST CFLG(R5) ;M,N?? BMI 90$ ;YES JSR PC,GETN ;NOPE, GET A NUMBER MOV R0,R4 ; AND SAVE IT BLE 20$ ;SPECIAL IF <=0 PAGE WRITE COUNT MOV #80$,-(SP) ;SET RETURN ADDRESS TO DO NOTHING 50$: JSR PC,30$ ;DUMP THE TEXT BUFFER TSTB TEMP(R5) ;"PW"? BMI 60$ ;YES, SO NO YANK JSR PC,.YYY.Y ;SIMULATE THE YANK MOV #CLNXIT,(SP) ; AND SET RETURN FOR COLON CHECKING BCS 80$ ;THE YANK DID NOTHING, EXIT RIGHT NOW 60$: JSR PC,CHKSTP ;CHECK FOR STOP FLAG NOW ON DEC R4 ;AGAIN? BNE 50$ ;YES 70$: CLC ;ENSURE CARRY=0 ON EXIT 80$: RTS PC ;NO, EXIT 90$: JSR PC,NLINES ;MAKE M,N INTO CHARACTERS MOV R0,R1 ;COUNT GOES HERE MOV M(R5),R0 ;START FROM HERE ADD TXSTOR(R5),R0 ; MAKE IT ABSOLUTE CLR R2 ;NEVER A FORM FEED 100$: JSR PC,PUTBUF ;NOW PUT IT BCC 80$ ;ALL O.K., EXIT IOERR: ;I/O ERRORS COME HERE .IF NE E$$TXT MOV SP,R4 ;INDICATE NO STRING .ENDC IOERRS: ;I/O ERROR WITH STRING COMES HERE JSR R2,ERRMIO ;SAVE TEXT POINTER AND SAY ERROR .EEEY: ;MOV #'Y,R0 ;"EY" IS YANK WITHOUT PROTECTION MOV R3,NFLG(R5) ;RESTORE THE ARGUMENT FLAG CMDCHR <'Y> ;"Y" IS YANK IN A BUFFER MOV #CLNXIT,-(SP) ;DO COLON CHECKING UPON FINAL EXIT MOV #.YYY.Y,-(SP) ;SET CHECKING RETURN TO DO THE YANK INC NFLG(R5) ;ANY ARGUMENT? BEQ 130$ ;YES, SOMEONE MADE AN ERROR... TST OFLG(R5) ;IS THERE AN OPERATOR PENDING? BEQ 110$ ;NOPE CMP NOPR(R5),#OP$SUB-OP$ADD ;IS THE OPERATOR "+" OR "-"? .IIF NE -2, .ERROR ;"+" = 0, "-" = 2, OTHERS > 2 ! BHI 130$ ;NEITHER "+" NOR "-", AN ERROR... BLO 110$ ;IT'S "+", LEAVE EVERYTHING ALONE CLR OFLG(R5) ;IT'S "-", TURN OFF THE OPERATOR MOV #120$,(SP) ;"-Y" IS YANK IN PREVIOUS BUFFER 110$: SUB #'Y,R0 ;DOING YANK PROTECTION CHECKING? BEQ 80$ ;NOPE, IT'S "EY", GO EXIT TO DO IT TST ZZ(R5) ;ANYTHING TO BE CLOBBERED IN TEXT? BEQ 80$ ;NO, SO OK TO YANK, GO EXIT .YYY.P: TST @OUPNTR(R5) ;ACTIVE OUTPUT FILE? BEQ 80$ ;NO, SO OK TO YANK, EXIT BIT EDIT(R5),#ED$YNK ;DOES USER REALLY WANT THIS?? BNE 80$ ;YES, SO ALWAYS OK TO YANK, EXIT ERROR YCA,<"Y command aborted"> 120$: JSR PC,.YYY.C ;ZAP THE CURRENT TEXT BUFFER MOV #-1,R4 ;SET TO GO BACKWARDS ONE PAGE BR .PPP.B ; AND THEN GO OFF AND DO IT & EXIT 130$: ERROR NYA,<"Numeric arg with Y"> .YYY.Y: JSR PC,.YYY.C ;CLEAR AND SIZE UP THE TEXT BUFFER CLRB TEMP+1(R5) ; AND ALWAYS DO A FULL BUFFER LOAD 140$: CMP #0,EOFLAG(R5) ;SET CARRY=1 IF "EOFLAG"=-1 BCS 80$ ;EXIT C=1 IF END-OF-FILE MOV ZZ(R5),R0 ;GET END OF CURRENT BUFFER MOV ZMAX(R5),R1 ;GET MAX SIZE DEC R1 ; LESS 1 FOR SAFETY MOV R1,R2 ;COPY THE MAX VALUE ASR R2 ; AND FIND THE ASR R2 ; MAX*(1/4) VALUE CMP R2,#256. ;IS MAX*(1/4) < 256.? BHIS 150$ ;NOPE MOV #256.,R2 ;YEP, SAY AT LEAST 256. 150$: SUB R0,R1 ;FIND REAL ROOM LEFT TSTB TEMP+1(R5) ;LOADING THE FULL BUFFER? BPL 160$ ;YES MOV R1,R2 ;NO, SET DESIRED FREE AS AMOUNT LEFT 160$: ADD TXSTOR(R5),R0 ;MAKE POINTER ABSOLUTE JSR PC,GETBUF ;GET SOME DATA IO.ERR: BCS IOERR ;I/O TYPE ERROR, DIE MOV FFFLAG(R5),R1 ;IS EITHER THE FORM FEED FLAG BIS EOFLAG(R5),R1 ; OR THE END-OF-FILE FLAG NOW ON? BNE 70$ ;ALL DONE IF SO, EXIT CARRY=0 TSTB TEMP+1(R5) ;LOADING FULL BUFFER? BMI 70$ ;NOPE, SO EXIT NOW MOV #SIZERB,R1 ;YEP, GET (TRIAL) AMOUNT TO EXPAND CMP R1,CURFRE(R5) ;HAVE WE ALREADY GOT THAT AMOUNT? BLOS 70$ ;IF SO THEN NO POINT IN ASKING FOR MORE BIT EDIT(R5),#ED$EXP ;ALLOWING ARBITRARY EXPANSIONS? BNE 70$ ;NOPE, SO DON'T... JSR PC,SIZER ;ELSE CALL THE MEMORY SIZING ROUTINE BCS 70$ ;IT FAILED, SO JUST EXIT .AAA.A: JSR PC,.YYY.F ;CLEAR FORM FEED AND RE-SHUFFLE AREAS BR 140$ ; THEN RECALL OURSELVES .DSABL LSB .ENABL LSB .EEEB: ;R0 GETS <0 FOR EB ('B-'R) .EEEG: ;SPECIAL HANDLING FOR "EG" .EEEI: ;R0 GETS <0 FOR EI ('I-'R) .EEEN: ;R0 GETS <0 FOR EN ('N-'R) .EEER: ;R0 GETS =0 FOR ER .EEEW: SUB #'R,R0 ;R0 GETS >0 FOR EW MOV FILBUF(R5),R4 ;GET POINTER TO FILENAME BUFFER JSR PC,GETSTG ;GET STRING AS ARGUMENT CLRB (R4) ;FORCE NULL STRINGS TO NULL JSR PC,IREST ; AND GO RESTORE THE QUOTE JSR PC,CHKCLN ;CHECK FOR A COLON MODIFIER CMP R2,#'G-'R ;IS IT REALLY "EG"? BEQ 70$ ;YES JSR PC,GETFLS ;NO, GET THE FILE STUFF DONE BCC 10$ ;NO ERROR, JUST EXIT CLR R4 ;ERROR, CLEAR R4 TO PRINT STRING CMP R0,#^RFNF ;IS THE ERROR "FNF"? BNE IOERRS ;OTHER ERROR, FATAL TST NFLG(R5) ;WERE WE REALLY RETURNING A VALUE? BPL IOERRS ;NO, SO DIE IN ANY CASE CLR N(R5) ;ELSE RETURN VALUE OF 0 10$: RTS PC ;EXIT CMDCHR <'E> ;"E" IS SPECIAL COMMANDS MOV NFLG(R5),R3 ;SAVE THE NUMBER FLAG CLR NFLG(R5) ;THEN NO MORE NUMBER SORT ..EEE,Z ;NOW SORT ERROR IEC,<"Illegal E character"> 20$: JSR PC,.YYY.Y ;CLEAR OUT AND READ MORE TEXT BCS 50$ ;END-OF-FILE, CLOSE INPUT & OUTPUT JSR PC,CHKSTP ;CHECK FOR STOP FLAG NOW ON 30$: MOV TXSTOR(R5),R0 ;SET START OF TEXT MOV ZZ(R5),R1 ; AND AMOUNT OF TEXT TO WRITE BNE 40$ ;THERE IS TEXT TO WRITE, DO IT TST @OUPNTR(R5) ;NO TEXT, IS THERE AN OUTPUT FILE? BEQ 50$ ;NO TEXT AND NO FILE, CLOSE INPUT 40$: MOV FFFLAG(R5),R2 ;SET THE OPTIONAL FORM FEED FLAG JSR PC,PUTBUF ; AND WRITE OUT THE TEXT BCS IO.ERR ;DIE ON ANY I/O TYPE ERROR TST @INPNTR(R5) ;DOES AN INPUT FILE EXIST? BNE 20$ ;YES, GET SOMETHING FROM IT 50$: JSR PC,CLSFIL ;CLOSE THE INPUT AND OUTPUT FILES 60$: BCS IO.ERR ;DIE ON ANY ERROR BR 10$ ;ELSE GO EXIT .EEEK: JSR PC,KILFIL ;CLOSE AND KILL OUTPUT FILE BR 60$ ; AND ERROR CHECK .EEEP: JSR PC,INPSAV ;SAVE INPUT FILE STATUS BR 60$ ; AND ERROR CHECK .EEEA: JSR PC,OUTSAV ;SAVE OUTPUT FILE STATUS BR 60$ ; AND ERROR CHECK 70$: MOV #GEXIT,-(SP) ;EXIT AND GO -OR- SPECIAL FUNCTION BR 80$ ;GO DE-CONDITION TECO MODE FIRST .EEEX: MOV #TEXIT,-(SP) ;EXIT FROM TECO 80$: JSR PC,XITNOW ;DE-CONDITION TECO MODE FOR EXITS TST NFLG(R5) ;REALLY THE SPECIAL FUNCTION CALL? BMI 10$ ;YES, JUST GO DO IT .EEEC: JSR PC,30$ ;PAGE OUT THE REST OF THE FILE JMP .YYY.C ;THEN EXIT CLEARING BUFFER .EEEF: JSR PC,CLSOUT ;CLOSE THE OUTPUT FILE BR 60$ ; AND ERROR CHECK .DSABL LSB .SCH.T: CLR R0 ;ENSURE NO SPECIAL TYPEOUT .SCH.V: CLR NFLG(R5) ;ENSURE NO NUMERIC ARGUMENT CLR CFLG(R5) ; AND NO COMMA FLAG CMDCHR <'V> ;"V" IS VERIFY MOV R0,-(SP) ;SAVE TYPEOUT DETERMINATION MOVB 1(SP),R0 ;GET NUMBER OF LINES FROM "ES" AND "EV" BGT 10$ ;NUMBER WAS EXPLICIT MOV #1,R0 ;ELSE DEFAULT TO ONE LINE 10$: INC NFLG(R5) ;IS THERE A NUMERIC ARGUMENT? BNE 20$ ;NOPE MOV N(R5),R0 ;YEP, SO USE IT 20$: MOV R0,-(SP) ;SAVE ARGUMENT FOR (N)T PART OF V INC CFLG(R5) ;IS IT M,N FORMAT? BNE 30$ ;NOPE, DEFAULT M TO N MOV M(R5),R0 ;YEP, SET EXPLICIT M 30$: NEG R0 ;CALCULATE THE (1-M)T INC R0 ; PART OF VERIFY JSR PC,60$ ; AND USE THAT FOR (1-M)T MOVB 2(SP),R0 ;GET TYPEOUT DETERMINATION BLE 50$ ;NOTHING SPECIAL CMP R0,#SPACE ;USE LINE FEED? BHIS 40$ ;NOPE MOV #LF,R0 ;YES 40$: JSR PC,TYPEF ;NOW TYPE THE CHARACTER WITH CASE FLAGGING 50$: MOV (SP)+,R0 ;SET ARGUMENT FOR (N)T PART OF V TST (SP)+ ;POP THAT TYPEOUT DETERMINATION 60$: JSR PC,NCOM ;COMPUTE A NUMBER; FALL INTO T COMMAND CMDCHR <'T> ;"T" IS THE PRINTER JSR PC,NLINES ;FIND NUMBER OF CHARACTERS MOV M(R5),R3 ;GET STARTING POINT ADD TXSTOR(R5),R3 ; AND MAKE ABSOLUTE MOV R0,R4 ;MOVE COUNT INTO HERE JMP PRINTF ; AND PRINT IT WITH CASE FLAGGING CMDCHR <'W> ;"W" IS SCOPE WATCH MOV N(R5),-(SP) ;PRESET THE POSSIBLE EXPLICIT ARGUMENT INC NFLG(R5) ;AN ARGUMENT THIS TIME? BEQ 10$ ;YES, WE'VE GOT IT ON THE STACK MOV NWATCH(R5),(SP) ;NO, GET THE OLD ARGUMENT TST CLNF(R5) ;IS THIS :W? BPL 10$ ;NOT :W, USE OLD ARGUMENT CLR (SP) ;IT IS :W, DEFAULT ARGUMENT TO ZERO 10$: JSR PC,CHKCLN ;CHECK FOR A COLON MODIFIER MOV (SP)+,R0 ;SET WATCH'S ARGUMENT HERE JSR PC,WATCH ;WATCH THE SCOPE MOV R0,N(R5) ;SAVE RETURNED ANSWER AS VALUE BMI 20$ ;VALUE IS <0, SO DON'T CHANGE DEFAULT TST NFLG(R5) ;WAS IT REALLY :W? BMI 20$ ;YES, JUST EXIT NOW MOV R0,NWATCH(R5) ;NO, REMEMBER THE LAST ARGUMENT 20$: RTS PC ;THEN EXIT CMDCHR <'O-100> ;"CTRL/O" MEANS OCTAL RADIX INC R0 ;MAKE A GREATER THAN ZERO CMDCHR <'D-100> ;"CTRL/D" MEANS DECIMAL RADIX MOV R0,NMRBAS(R5) ;SET THE RADIX RTS PC .ENABL LSB 10$: ERROR IAA,<"Illegal A arg"> 20$: ERROR MEM,<"Memory overflow"> 30$: MOV NFLG(R5),TEMP(R5) ;SET TEMP+1 <0 IF "N:A" BMI 50$ ;IT IS "N:A" 40$: MOV #1,N(R5) ;SET COUNT TO ONE CLR TEMP(R5) ; AND LOAD A WHOLE PAGE TST OFLG(R5) ;IS THERE AN OPERATOR PENDING? BEQ 50$ ;NOPE CMP NOPR(R5),#OP$SUB-OP$ADD ;IS THE OPERATOR "+" OR "-"? .IIF NE -2, .ERROR ;"+" = 0, "-" = 2, OTHERS > 2 ! BHI 10$ ;NEITHER "+" NOR "-", AN ERROR... BLO 50$ ;IT'S "+", LEAVE EVERYTHING ALONE CLR OFLG(R5) ;IT'S "-", TURN OFF THE OPERATOR NEG N(R5) ; AND SET COUNT TO MINUS ONE 50$: TST N(R5) ;LEGAL ARGUMENT? BLE 10$ ;NOPE, AN ERROR... 60$: MOV ZZ(R5),R1 ;GET CURRENT TEXT SIZE ADD #256.,R1 ;ENSURE ADDITION OF ONE LINE SIZE TEXT ; INTO TEXT BUFFER BCC 20$ ;FAILED, SO ERROR JSR PC,.AAA.A ;O.K., SO READ IT IN BCS 70$ ;NOTHING WAS DONE THIS CALL... TST FFFLAG(R5) ;DID THE FORM FEED FLAG GET SET? BNE 80$ ;YES, ALWAYS SAY SOMETHING ADDED DEC N(R5) ;SHOULD WE LOOP AGAIN? BNE 60$ ;YEP, SO DO SO 70$: INC (SP) ;FORM OLD TEXT SIZE +1 80$: CMP ZZ(R5),(SP)+ ;IS TEXT NOW > OLD SIZE (>= OLD +1)? ;BHIS ;YES, C=0 ('BHIS'='BCC') CLNXIT: ROR -(SP) ;SAVE C-BIT ON STACK JSR PC,CHKCLN ;CHECK FOR A COLON MODIFIER ASL (SP)+ ;DID WE NET NOTHING (C-BIT=1)? BCC 90$ ;NOPE, DID SOMETHING, RETURN A -1 CLR N(R5) ;YEP, RETURN 0 INSTEAD OF -1 90$: RTS PC ;EXIT CMDCHR <'A> ;"A" IS APPEND MOV ZZ(R5),-(SP) ;STACK INITIAL TEXT SIZE (Z) TST CLNF(R5) ;COLON MODIFIED? BMI 30$ ;YES, APPEND PAGE OR LINE INC NFLG(R5) ;NUMERIC ARGUMENT? BNE 40$ ;NO, APPEND PAGE W/O RETURNED VALUE COM R0 ;PRESET -1 RETURN VALUE FOR FAILURE MOV N(R5),R1 ;GET THE NUMBER ADD P(R5),R1 ;INDEXED BY . CMP R1,(SP)+ ;WITHIN RANGE? BHIS GONCOM ;NOPE, AT OR ABOVE Z, RETURN -1 ADD TXSTOR(R5),R1 ;YEP, MAKE IT ABSOLUTE CLR R0 ; AND GET THE CHARACTER BISB (R1),R0 ; AVOIDING ANY SIGN EXTENSION BR GONCOM ;NOW GO COMPUTE AS IF NUMBER .DSABL LSB CMDCHR <'N-100> ;"CTRL/N" IS EOF FLAG MOV EOFLAG(R5),R0 ;GET END-OF-FILE FLAG BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <'B-100> ;"CTRL/B" IS TODAY'S DATE JSR PC,DATE ;GET DATE BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <'S-100> ;"CTRL/S" IS -(LENGTH) OF LAST STRING MOV LSCHSZ(R5),R0 ;GET -(LENGTH) OF LAST BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <'F-100> ;"CTRL/F" IS SWITCH REGISTER VALUE JSR PC,SWITCH ;GET SWITCH REGISTER BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <'H-100> ;"CTRL/H" IS TIME OF DAY JSR PC,TIME ;GET TIME OF DAY BR GONCOM ; AND COMPUTE AS A NUMBER .ENABL LSB CMDCHR <'H> ;"H" MEANS ALL (0,Z) CLR N(R5) ;SIMULATE THE "B" (OR 0) JSR PC,20$ ;NOW SIMULATE THE COMMA CMDCHR <'Z> ;"Z" MEANS END OF TEXT MOV ZZ(R5),R0 ;GET END OF TEXT VALUE BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <'Y-100> ;"CTRL/Y" MEANS .+^S,. JSR PC,10$ ;SET NUMBER TO . ADD LSCHSZ(R5),N(R5) ; NOW ADD IN ^S JSR PC,20$ ;FAKE THE COMMA CMDCHR <'.> ;"." IS CURRENT POSITION 10$: MOV P(R5),R0 ;GET . BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <',> ;"," IS THE M,N SEPARATOR INC NFLG(R5) ;WAS THERE A "M"? BNE 30$ ;THERE SHOULD HAVE BEEN 20$: MOV N(R5),M(R5) ;SAVE "M" CLR N(R5) ;NOW CLEAR "N" AGAIN MOV #-1,CFLG(R5) ; AND INDICATE A COMMA CMDCHR ;"NUL" IS IGNORED CMDCHR ;"LF" IS IGNORED CMDCHR ;"CR" IS IGNORED CMDCHR ;"SPACE" IS IGNORED CMDCHR ;"DEL" IS IGNORED RTS PC ;NOW RETURN 30$: ERROR NAC,<"No arg before ,"> .DSABL LSB CMDCHR <'T-100> ;"CTRL/T" MEANS VALUE OF NEXT INPUT CHARACTER INC NFLG(R5) ;IS THERE AN ARGUMENT? BNE 30$ ;NO, SO GET INPUT AS NUMERIC VALUE MOV #ET$BIN,R1 ;GUESS AT SETTING BINARY OUTPUT MODE INC CLNF(R5) ;COLON MODIFIED? BNE 10$ ;NOPE BIT R1,ETYPE(R5) ;IS BINARY OUTPUT MODE ALREADY ON? BEQ 20$ ;NOT ON, WE MUST SET IT ON 10$: CLR R1 ;CHANGE TO NO "ET" MODIFICATION 20$: BIS R1,ETYPE(R5) ;OPTIONAL SETTING OF BINARY MODE MOV N(R5),R0 ;GET THE ARGUMENT JSR PC,TYPEB ; AND TYPE ITS VALUE ON TERMINAL BIC R1,ETYPE(R5) ;OPTIONAL CLEARING OF BINARY MODE CLR CLNF(R5) ;CLEAR THE COLON FLAG RTS PC ;EXIT 30$: INC CLNF(R5) ;COLON MODIFIED? BNE 40$ ;NOPE JSR PC,TECOLT ;YEP, CALL THE :^T INPUT ROUTINE MOV R1,M(R5) ;SET TYPE CODE INTO "M" MOV #-1,CFLG(R5) ; AND INDICATE "M" IS ACTIVE BR GONCOM ;COMPUTE FINAL CODE/VALUE AS A NUMBER 40$: CLR CLNF(R5) ;CLEAR THE COLON FLAG JSR PC,TLISTN ;GET A CTRL/T CHARACTER BR GONCOM ; AND COMPUTE AS A NUMBER CMDCHR <'^-100> ;"CTRL/^" MEANS VALUE OF NEXT CHARACTER JSR PC,SCAN ;GET NEXT CHARACTER BIC #^C<377>,R0 ;AVOID ANY SIGN EXTENSION BR GONCOM ; AND COMPUTE AS A NUMBER .EEEO: MOV #VERSON,R0 ;"EO" IS VERSION NUMBER BR GONCOM ;GO COMPUTE AS A NUMBER CMDCHR <'Z-100> ;"CTRL/Z" MEANS SIZE OF Q-REGS MOV QZ(R5),R0 ;GET SIZE OF Q-REGS BR GONCOM ; AND COMPUTE AS A NUMBER .ENABL LSB CMDCHR <'Q> ;"Q" IS VALUE/SIZE IN Q-REGISTER INC NFLG(R5) ;IS THERE AN ARGUMENT? BNE 10$ ;NOPE JSR PC,QREF ;YEP, REFERENCE Q-REG MOV N(R5),R3 ;GET THE ARGUMENT COM R0 ; AND PRESET -1 FOR OUT-OF-RANGE CMP R3,(R1) ;IS ARGUMENT WITHIN RANGE? BHIS NCOM ;NO, COMPUTE WITH -1 AS THE NUMBER ADD R2,R3 ;YES, ADD OFFSET TO THIS Q-REG ADD QRSTOR(R5),R3 ; AND ADD IN THE Q-REG BASE CLR R0 ;GET THE CHARACTER THERE BISB (R3),R0 ; WITHOUT SIGN EXTENSION GONCOM: BR NCOM ;GO COMPUTE AS A NUMBER CMDCHR <'%> ;"%" IS ADD TO Q-REG VALUE JSR PC,GETN ;GET THE NUMBER CLR CLNF(R5) ; AND ENSURE ADDITION TO VALUE 10$: MOV R0,R3 ;SAVE THE ADDITION VALUE (OR ZERO) JSR PC,QREFVL ;REFERENCE Q-REG FOR VALUE INC CLNF(R5) ;COLON MODIFIED? BNE 20$ ;NO, RETURN OR ADD TO VALUE TST -(R1) ;YES, SET TO Q-REG'S RETURN SIZE 20$: CLR CLNF(R5) ;ENSURE COLON FLAG IS NOW OFF ADD R3,-(R1) ;ADD TO Q-REG'S VALUE MOV (R1),R0 ;THEN GET THE NEW VALUE BR NCOM ; AND COMPUTE AS A NUMBER .DSABL LSB .ENABL LSB CMDCHR <'&> ;"&" IS LOGICAL 'AND' MOV #OP$AND-OP$OR,R0 ;SET FOR 'AND' CMDCHR <'#> ;"#" IS LOGICAL OR ADD #OP$OR-OP$DIV,R0 ;SET FOR 'OR' CMDCHR <'/> ;"/" IS DIVISION ADD #OP$DIV-OP$MUL,R0 ;SET FOR DIVIDE CMDCHR <'*> ;"*" IS MULTIPLICATION ADD #OP$MUL-OP$SUB,R0 ;SET FOR MULTIPLY CMDCHR <'-> ;"-" IS SUBTRACTION TST (R0)+ ;SET FOR SUBTRACT .IIF NE -2, .ERROR ;SUBTRACTION HAS BEEN MISPLACED! CMDCHR <'+> ;"+" IS ADDITION 10$: MOV R0,NOPR(R5) ;SAVE THE OPERATOR DISPATCH MOV N(R5),NACC(R5) ;SAVE CURRENT NUMBER IN ACCULMULATOR CLR NP(R5) ;NO DIGITS FOUND NOW MOV #-1,OFLG(R5) ;INDICATE OPERATOR PENDING CLR NFLG(R5) ;BUT NO NUMBER PENDING RTS PC ; AND RETURN CMDCHR <'(> ;"(" IS START OF NEW EXPRESSION TST OFLG(R5) ;OPERATOR PENDING? BNE 20$ ;YES JSR PC,NCOM ;NO, INITIALIZE US 20$: INC PCNT(R5) ;COUNT AS ANOTHER PAREN PUSH PUSHP NOPR,NACC ;SAVE ACCULMULATOR BR 10$ ;THEN SET UP AS IF "+" .DSABL LSB .ENABL LSB CMDCHR <')> ;")" IS END OF EXPRESSION TST NFLG(R5) ;ANYTHING BEFORE THIS? BPL 10$ ;BADNESS IF NOT DEC PCNT(R5) ;CAN WE POP A PAREN? BMI 10$ ;NO, ERROR POP NACC,NOPR ;RESTORE OPERATOR MOV N(R5),R0 ;GET VALUE INSIDE PARENS BR 60$ ; AND TREAT AS A NUMBER 10$: ERROR NAP,<"No arg before )"> 20$: ERROR ILN,<"Illegal number"> CMDCHR <'9> ;"9" IS A NUMERIC DIGIT CMDCHR <'8> ;"8" IS A NUMERIC DIGIT TST NMRBAS(R5) ;IS RADIX DECIMAL OR HEXIDECIMAL? BGT 20$ ;NO, OCTAL, SO ERROR CMDCHR <'7> ;"7" IS A NUMERIC DIGIT CMDCHR <'6> ;"6" IS A NUMERIC DIGIT CMDCHR <'5> ;"5" IS A NUMERIC DIGIT CMDCHR <'4> ;"4" IS A NUMERIC DIGIT CMDCHR <'3> ;"3" IS A NUMERIC DIGIT CMDCHR <'2> ;"2" IS A NUMERIC DIGIT CMDCHR <'1> ;"1" IS A NUMERIC DIGIT CMDCHR <'0> ;"0" IS A NUMERIC DIGIT .BSL.N: SUB #'0,R1 ;MAKE INTO BINARY DIGIT CMP R1,#9. ;HEXIDECIMAL DIGIT? BLOS 30$ ;NOPE SUB #<'A-10.>-'0,R1 ;YEP, SO CORRECT IT 30$: INC NFLG(R5) ;ANY DIGIT BEFORE THIS? BNE 90$ ;NO, SO INITIALIZE US MOV NP(R5),R0 ;YES, SO GET OLD NUMBER MOV R0,-(SP) ; AND SAVE IT ASL R0 ;TIMES 2 ASL R0 ;TIMES 4 NOW TST NMRBAS(R5) ;RADIX? BEQ 50$ ;DECIMAL BGT 40$ ;OCTAL ASL R0 ;HEXIDECIMAL 40$: CLR (SP) ;NO CORRECTION NEEDED 50$: ADD (SP)+,R0 ;ADD IN ANY CORRECTION FACTOR ASL R0 ;TIMES 8., 10., OR 16. BY NOW ADD R1,R0 ; AND ADD IN NEW DIGIT MOV R0,NP(R5) ;SAVE THE NUMBER 60$: ADD NOPR(R5),PC ;DISPATCH ON OPERATOR OP$ADD: BR 70$ ;+ OP$SUB: NEG R0 ;- 70$: ADD NACC(R5),R0 ;FORM RESULT 80$: MOV R0,N(R5) ;SAVE THE RESULT MOV #-1,NFLG(R5) ; AND INDICATE A NUMBER CLR OFLG(R5) ; BUT NO OPERATOR RTS PC ;THEN EXIT 90$: MOV R1,R0 ;COPY FIRST DIGIT MOV R1,NP(R5) ;SAVE IT IN NUMBER ACCUMULATOR BR 100$ ;ENTER PROCESSING CMDCHR <'B> ;"B" IS ZERO NCOM: CLR NP(R5) ;USUALLY WE SET NP TO 0 100$: TST OFLG(R5) ;OPERATOR? BNE 60$ ;YES CLR NACC(R5) ;NO, SO INITIALIZE US CLR NOPR(R5) BR 60$ ; AND CONTINUE OP$AND: MOV NACC(R5),R1 ;GET MASK COM R1 ;MAKE INTO AN 'AND' MASK BIC R1,R0 ; AND DO THE 'AND' BR 80$ ;THEN FINISH UP OP$OR: BIS NACC(R5),R0 ;DO THE 'OR' BR 80$ ;THEN FINISH UP OP$MUL: CLR R1 ;CLEAR THE HIGH ORDER MOV #16.+1,R2 ;NUMBER OF BITS(+1) IN A WORD 110$: CLC ;CLEAR THE DUMB CARRY ROR R1 ;SHIFT HIGH ORDER INTO ROR R0 ; LOW ORDER BCC 120$ ;NO NEED TO ADD HERE... ADD NACC(R5),R1 ;ADD INTO HIGH ORDER 120$: DEC R2 ;MORE? BGT 110$ ;YES BR 80$ ;NO OP$DIV: MOV R0,R2 ;SET THE DIVISOR MOV NACC(R5),R0 ; AND THE DIVIDEND MOV #80$,-(SP) ;STACK RETURN ADDRESS DIVD: CLR R1 ;CLEAR THE REMAINDER MOV #16.,R3 ;NUMBER OF BITS IN A WORD 130$: ASL R0 ;SHIFT THE DIVIDEND ROL R1 ; INTO THE REMAINDER CMP R2,R1 ;CAN WE SUBTRACT? BHI 140$ ;NOPE SUB R2,R1 ;YEP INC R0 ; AND COUNT IN ANSWER 140$: DEC R3 ;MORE? BGT 130$ ;YES RTS PC ;NO, EXIT .DSABL LSB CMDCHR <'_-100> ;"CTRL/_" IS THE UNARY COMPLEMENT OPERATOR TST NFLG(R5) ;IS THERE A NUMBER? BPL 10$ ;THERE SHOULD HAVE BEEN COM N(R5) ;DO A COMPLEMENT RTS PC ; AND LEAVE 10$: ERROR NAB,<"No arg before "<'_-100>> .ENABL LSB CMDCHR <'E-100> ;"CTRL/E" IS FORM FEED FLAG MOV #FFFLAG-EDIT,R2 ;SET OFFSET POINTER TO FLAG BR 10$ ; AND GO JOIN THE COMMON CODE CMDCHR <'X-100> ;"CTRL/X" IS SEARCH MODE FLAG MOV #SFLG-EDIT,R2 ;SET OFFSET POINTER TO FLAG 10$: MOV NFLG(R5),R3 ;SET ARGUMENT DETERMINATION CLR NFLG(R5) ; AND USE UP ANY NUMBER .EEED: TST (R2)+ ;"ED" IS EDITOR LEVEL .IIF NE EDIT-EEFLAG-2, .ERROR ;ORDER IS IMPORTANT! .EEEE: TST (R2)+ ;"EE" IS ESCAPE SYNONYM .IIF NE EEFLAG-EHELP-2, .ERROR ;ORDER IS IMPORTANT! .EEEH: TST (R2)+ ;"EH" IS EDIT HELP LEVEL .IIF NE EHELP-ESFLAG-2, .ERROR ;ORDER IS IMPORTANT! .EEES: TST (R2)+ ;"ES" IS EDIT SEARCH FLAG .IIF NE ESFLAG-ETYPE-2, .ERROR ;ORDER IS IMPORTANT! .EEET: TST (R2)+ ;"ET" IS EDIT TYPEOUT FLAG .IIF NE ETYPE-EUFLAG-2, .ERROR ;ORDER IS IMPORTANT! .EEEU: TST (R2)+ ;"EU" IS CASE FLAGGING FLAG .IIF NE EUFLAG-EVFLAG-2, .ERROR ;ORDER IS IMPORTANT! .EEEV: ADD #EVFLAG,R2 ;"EV" IS EDIT VERIFY FLAG CMP R3,#-1 ;SETTING A NEW VALUE? BNE 30$ ;NOPE MOV N(R5),R0 ;YEP, GET THE NEW VALUE INC CFLG(R5) ;M,N FORM? BNE 20$ ;NO ADD R5,R2 ;YES, MAKE POINTER ABSOLUTE BIS (R2),R0 ;.OR. OLD FLAG VALUE INTO N BIC M(R5),R0 ;.BIC. M FROM THAT RESULT SUB R5,R2 ;POINTER TO RELATIVE AGAIN 20$: CLR CFLG(R5) ;TURN OFF THE COMMA FLAG 30$: JSR PC,FLAGRW ;NOW ALERT 'TECOIO' ADD R5,R2 ;MAKE POINTER ABSOLUTE INC R3 ;ARGUMENT? BEQ 40$ ;YES MOV (R2),R0 ;NO, RETURN VALUE BR NCOM ; AND COMPUTE AS A NUMBER 40$: MOV R0,(R2) ;SET THE NEW VALUE RTS PC ; AND EXIT .DSABL LSB .EEEJ: MOV N(R5),R0 ;GET THE ARGUMENT VALUE JSR PC,FLAGRW ;ALERT 'TECOIO' WITH R2=0 BR NCOM ;COMPUTE WHAT'S RETURNED AS A NUMBER CMDCHR <'Q-100> ;"^Q" CONVERTS 'L' COMMANDS TO 'C' COMMANDS .QQQ.Q: MOV P(R5),-(SP) ;SAVE . JSR PC,.VVV.N ;NOW MOVE . ACCORDING TO 'L' COMMAND MOV (SP),P(R5) ;RESTORE ORIGINAL . MOV R1,R0 ;COPY THE NEW . SUB (SP)+,R0 ; AND FIND DELTA-DOT BRNCOM: BR NCOM ;USE THAT AS A NUMBER CMDCHR <'U> ;"U" IS Q-REG NUMBER SETTER INC NFLG(R5) ;ANY NUMBER? BNE 10$ ;THERE MUST BE JSR PC,QREFVL ;REFERENCE THE Q-REG FOR VALUE MOV N(R5),-(R1) ;NOW SET THE NUMBER MOV M(R5),R0 ;GET M IN CASE M,N FORM INC CFLG(R5) ;M,N FORM? BEQ BRNCOM ;YEP, GO EXIT COMPUTING AS A NUMBER CLR CFLG(R5) ;NOPE, CLEAR COMMA FLAG RTS PC ; THEN EXIT 10$: ERROR NAU,<"No arg before U"> CMDCHR <'R-100> ;"^R" READ/SET RADIX FLAG INC NFLG(R5) ;ANY ARGUMENT? BEQ 20$ ;YES, SETTING RADIX MOV #8.,R0 ;NO, READING RADIX, GUESS AT OCTAL TST NMRBAS(R5) ;RADIX? BGT BRNCOM ;OCTAL BEQ 10$ ;DECIMAL ADD #6,R0 ;HEXIDECIMAL 10$: TST (R0)+ ;FORM THE RADIX BR BRNCOM ; AND RETURN IT 20$: MOV N(R5),R1 ;GET THE RADIX TO SET CMP R1,#10. ;DECIMAL? BEQ 30$ ;YES, R0=0 INC R0 ;NO, SET R0=1 CMP R1,#8. ;OCTAL? BEQ 30$ ;YES, R0=1 NEG R0 ;NO, SET R0=-1 CMP R1,#16. ;HEXIDECIMAL? BNE 40$ ;NOPE, ERROR 30$: MOV R0,NMRBAS(R5) ;SET THE CORRECT RADIX RTS PC ; AND EXIT 40$: ERROR IRA,<"Illegal radix arg"> CMDCHR <':> ;":" IS THE SEARCH MODIFIER MOV #-1,CLNF(R5) ;SET COLON FLAG TSTNXT ': ;DOUBLE COLON? SBC CLNF(R5) ;YES MEANS FLAG=-2 RTS PC ; AND EXIT .ENABL LSB CMDCHR <'J> ;"J" IS MOVE POINTER CLR NFLG(R5) ;USE UP THE NUMBER MOV N(R5),R0 ;NOW GET THE NUMBER BR 10$ ; AND GO SET . CMDCHR <'R> ;"R" IS MOVE POINTER CHARACTERS JSR PC,GETN ;GET THE NUMBER OF CHARACTERS NEG R0 ;THIS IS THE REVERSE MOVE BR .FFF.R ;GO JOIN COMMON CODE CMDCHR <'C> ;"C" IS MOVE POINTER CHARACTERS JSR PC,GETN ;GET THE NUMBER OF CHARACTERS .FFF.R: ADD P(R5),R0 ;CALCULATE NEW . 10$: JSR PC,BZCHK ;CHECK FOR VALIDITY MOV R0,P(R5) ;SET NEW . RTS PC ; AND EXIT .DSABL LSB .ENABL LSB .FFFR: JSR PC,QSKPR0 ;"FR" IS REPLACE, SKIP INSERT STRING MOV LSCHSZ(R5),R0 ;GET -(LENGTH) OF LAST FOUND STRING TST CFLG(R5) ;IS IT M,N FORM? BPL 10$ ;NOPE JSR PC,NLINES ;YEP, CONVERT M,N INTO +(LENGTH) MOV M(R5),P(R5) ; AND POSITION TO THE START 10$: INC NFLG(R5) ;A NUMERIC ARGUMENT? BNE 20$ ;NOPE MOV N(R5),R0 ;YEP, GET IT FOR +/-(LENGTH) 20$: CLR NFLG(R5) ;USE UP ANY NUMBER MOV #.SCH.R,-(SP) ;SET RETURN TO DO ACTUAL REPLACEMENT 30$: MOV R0,R1 ;COPY DELETION AMOUNT/DIRECTION BPL 40$ ;>0 IS FORWARD DELETE JSR PC,.FFF.R ;<0 IS BACKWARD (-ND = -NC ND) MOV R1,R0 ;RESTORE THE DELETE COUNT RTS PC ; AND EXIT 40$: NEG R0 ;DELETE THIS MANY (<0 IS DELETE) RTS PC ; AND EXIT CMDCHR <'D> ;"D" IS DELETE CHARACTERS TST CFLG(R5) ;IS FORM M,ND ? BMI 50$ ;YES, SO PRETEND IT IS M,NK JSR PC,GETN ;GET THE NUMBER OF CHARACTERS BR 60$ ; AND JOIN COMMON DELETION CODE CMDCHR <'K> ;"K" IS THE LINE DELETER 50$: JSR PC,NLINES ;GET THE NUMBER OF LINES MOV M(R5),P(R5) ;STARTING FROM HERE 60$: JSR PC,30$ ;GO DO ANY POSITIONING NEEDED, ETC. .IIF NE .-ADJ, .ERROR ;NOW DO IT .DSABL LSB .SBTTL ADJUST TEXT AREA ROUTINE ; R0 = 0 MEANS NO ADJUSTMENT ; R0 < 0 MEANS SHRINK AREA BY ABS(R0) ; R0 > 0 MEANS ENLARGE AREA BY R0 ; (R0,R1,R2,R3 ARE CLOBBERED) .ENABL LSB ADJ: MOV P(R5),R2 ;GET . MOV ZZ(R5),R3 ; AND GET END OF TEXT MOV R0,R1 ;COPY THE CHANGE AMOUNT BMI 40$ ;<0 MEANS SHRINK AREA BEQ 20$ ;=0 MEANS NO CHANGE ADD R3,R1 ;NOW HAVE NEW SIZE SIZE TEXT ;CHECK OUT THE SIZE BCC 30$ ;WE CAN'T DO IT MOV R1,ZZ(R5) ;UPDATE THE BUFFER SIZE MOV TXSTOR(R5),R0 ;GET ABSOLUTE POINTER BIAS EXPAND: CMP R2,R3 ;ANYTHING TO DO? BEQ 20$ ;NO, FAST EXIT ADD R0,R1 ;MAKE NEW ZZ ABSOLUTE ADD R0,R2 ;MAKE . ABSOLUTE ADD R0,R3 ;MAKE OLD ZZ ABSOLUTE MOVB (R2),R0 ;SAVE CHARACTER AT . CLRB (R2) ;THEN FLAG THAT SPOT 10$: MOVB -(R3),-(R1) ;MOVE A BYTE UP FROM END BNE 10$ ;CANNOT BE END OF NON-ZERO CMP R3,R2 ;REACHED . YET? BHI 10$ ;NOPE, SO CONTINUE MOVB R0,(R2) ;YES, RESTORE CHARACTER AT . MOVB R0,(R1) ; AND RESTORE MOVED NULL BYTE 20$: RTS PC ;NOW EXIT 30$: ERROR MEM,<"Memory overflow"> 40$: MOV R2,R1 ;COPY . TO HERE SUB R0,R2 ;NOW FIND END OF THE DELETE CMP R2,R3 ;IS DELETE TOO BIG? BHI 70$ ;YEP ADD R0,ZZ(R5) ;SET NEW DATA SIZE MOV TXSTOR(R5),R0 ;GET BUFFER BIAS SHRINK: CMP R2,R3 ;ANYTHING TO DO? BEQ 60$ ;NO, FAST EXIT ADD R0,R1 ;MAKE . ABSOLUTE ADD R0,R2 ;MAKE END OF DELETE ABSOLUTE ADD R0,R3 ;MAKE END OF BUFFER ABSOLUTE MOVB -(R3),R0 ;SAVE END OF BUFFER BYTE CLRB (R3) ;THEN FLAG END OF BUFFER 50$: MOVB (R2)+,(R1)+ ;MOVE A BYTE DOWN BNE 50$ ;CANNOT BE END IF NON-ZERO CMP R2,R3 ;END OF BUFFER REACHED? BLOS 50$ ;NOT YET MOVB R0,-(R1) ;RESTORE END OF BUFFER BYTE MOVB R0,(R3) ; AND RESTORE THIS ALSO 60$: RTS PC ;NOW EXIT 70$: ERROR DTB,<"Delete too big"> .DSABL LSB CMDCHR <'O> ;"O" IS GOTO TAG MOV TAGBUF(R5),R4 ;GET THE TAG BUFFER POINTER JSR PC,GETSTG ;GET STRING AS ARGUMENT CLRB (R4) ; AND FORCE NULL TAGS TO NULL MOV TAGBUF(R5),R4 ;GET THE TAG BUFFER POINTER AGAIN INC NFLG(R5) ;INDEXED GOTO? BEQ 50$ ;YEP, FIND CORRECT TAG FROM LIST 10$: CLR NFLG(R5) ;USE UP ANY NUMBER MOV ITRST(R5),(R5) ;START SEARCH AT ITERATION START 20$: SKPSET '! ;SKIP UNTIL A ! JSR PC,TRACE ;TRACE THE ! IF TRACING MOV R0,QUOTE(R5) ;SET ! AS TERMINATING QUOTE JSR PC,QCHK ;UNLESS SOMETHING ELSE ENDS IT MOV R4,R3 ;GET BACK THE TAG'S START 30$: JSR PC,SCNQST ;SCAN FOR END OF FOUND TAG BEQ 80$ ;BR OUT IF END OF FOUND TAG FOUND CMPB R0,(R3)+ ;NOT END, A MATCH? BEQ 30$ ;CONTINUE UNTIL END IF MATCH JSR PC,QSKPE ;SCAN TO FOUND TAG'S END IF NO MATCH BR 20$ ; THEN FIND THE NEXT TAG 40$: TSTB (R3)+ ;TAG BUFFER EXHAUSTED? BEQ IREST ;YEP, NO MORE, JUST GO QUIT MOV R3,R4 ;RESET THE TAG STARTING POSITION 50$: MOV R4,R3 ;GET A POINTER TO THE TRIAL TAG 60$: CMPB (R3),#', ;COMMA SEPARATOR? BEQ 70$ ;YES, END THIS TAG TSTB (R3)+ ;NO, END OF TAG BUFFER? BNE 60$ ;NOT END, CONTINUE LOOPING... DEC R3 ;BUFFER END, CORRECT POINTER 70$: DEC N(R5) ;IS THIS THE OCCURANCE WE WANT? BPL 40$ ;NO, WE MUST KEEP LOOKING CLRB (R3) ;YES, FLAG TAG'S END WITH A NULL CMP R3,R4 ;IS IT A NULL TAG? BNE 10$ ;IT'S NON-NULL, GO JOIN COMMON FLOW BR IREST ;IT'S A NULL TAG, JUST QUIT 80$: TSTB (R3) ;ALSO AT DESIRED TAG'S END? BNE 20$ ;NOPE, SO FIND NEXT TAG BR IREST ;YEP, EXIT RESTORING QUOTE .SBTTL SKIP OVER COMMAND ; (R0,R1,R2,R3,"TEMP" ARE CLOBBERED) .ENABL LSB SKPSET: JSR PC,IREST ;RESTORE ESCAPE AS QUOTE MOVB TFLG(R5),TEMP(R5) ;SAVE TRACE FLAG CLRB TFLG(R5) ;THEN DISABLE TRACE DURING SKIP 10$: JSR PC,SCNUPP ;GET NEXT CHARACTER 20$: CMPB R0,(R4) ;IS IT THE SPECIAL CHARACTER? BEQ 40$ ;YES, SO EXIT TST R0 ;IS THIS A NULL? BEQ 30$ ;SIMPLY IGNORE ANY NULL... CMPB R0,1(R4) ;IS IT THE ALTERNATE CHARACTER? BEQ 40$ ;YES, SO EXIT 30$: MOV #10$,-(SP) ;STACK A RETURN ADDRESS SORT ..CSM ;SORT ON SPECIAL SKIPPERS RTS PC ;NON-SPECIALS ARE IGNORED 40$: MOVB TEMP(R5),TFLG(R5) ;RESTORE THE TRACE FLAG TST (R4)+ ;SKIP THE ARGUMENT(S) RTS R4 ; AND EXIT .CSMUA: JSR PC,SCNCTL ;GET NEXT AS CONTROL CHARACTER BR 20$ ; AND GO CHECK IT .DSABL LSB .ENABL LSB 10$: JSR PC,SCNUPP ;GET NEXT CHARACTER AS UPPER CASE MOV (R2)+,R1 ;GET TABLE POINTER 20$: CMPB R0,-(R1) ;IS IT IN THE TABLE? BHI 20$ ;NO, BUT KEEP CHECKING... ;BLO ;NO, AND IT CAN'T BE RTS R2 ;YES, EXIT Z=1 .CSME: JSR R2,10$ ;CHECK "E" CHARACTER .WORD ..CSME ; AGAINST EB, EG, EI, EN, ER, EW, E_ BEQ .CSMQ ;IT'S ONE OF THOSE, SKIP A STRING RTS PC ;ELSE DO NOTHING .CSMF: JSR R2,10$ ;CHECK "F" CHARACTER .WORD ..CSMF ; AGAINST FB, FC, FN, FR, FS, F_ BLO 50$ ;NONE OF THE ABOVE, DO NOTHING CMP R0,#'B ;"FB"? BEQ .CSMQ ;YES, ONLY SKIP 1 STRING CMP R0,#'R ;"FR"? BEQ .CSMQ ;YES, ONLY SKIP 1 STRING JSR PC,QSKP ;IGNORE 1 QUOTED STRING .CSMQ: JSR PC,QSKP ;IGNORE 1 QUOTED STRING IREST: MOV #ESC,R0 ;SET TO RESTORE QUOTE AS ESCAPE BR 30$ ;GO DO IT QCHK: TST QFLG(R5) ;QUOTE FLAG? BEQ 50$ ;NOPE JSR PC,SCAN ;YES, SO GET THE QUOTE CHARACTER 30$: CLR QFLG(R5) ;NOW CLEAR THE QUOTE FLAG 40$: MOV R0,QUOTE(R5) ; AND SET QUOTE CHARACTER 50$: RTS PC ;NOW EXIT .CSMY: MOV #.CSMQ,-(SP) ;IGNORE A STRING QUOTED ON BR 40$ ; THIS CHARACTER .CSMRQ: MOV #.CSMQ,-(SP) ;SKIP A QUOTED STRING AFTER THE Q-REG .CSMR: JSR PC,SCAN ;SKIP THE Q-REG NAME CMP R0,#'. ;WAS IT A LOCAL Q-REG NAME? BNE 50$ ;NOPE JMP SCAN ;YEP, SCAN OFF ONE MORE CHARACTER... .DSABL LSB CMDCHR <'@> ;"@" IS QUOTE FLAG SETTER .CSMA: MOV #-1,QFLG(R5) ;@ FOUND; SET QUOTE FLAG RTS PC ;EXIT .SBTTL ERROR MESSAGE PROCESSOR .IF NE E$$TXT .ENABL LSB ERRORA: MOVB (R4)+,R0 ;GET 3RD RAD50 CHARACTER ADD (PC)+,R0 ;NOW FORM "NA?" .RAD50 /NA / MOV (PC)+,-(SP) ;STACK MESSAGE POINTER MESSAG <"No arg before "<-1>> BR 10$ ; AND GO TO COMMON PROCESSING ERRORC: MOVB (R4)+,R0 ;GET 2ND RAD50 CHARACTER ASL R0 ;MAKE INTO ASL R0 ; REAL ASL R0 ; 2ND CHARACTER ADD (PC)+,R0 ;NOW FORM "I?C" .RAD50 /I C/ MOV (PC)+,-(SP) ;STACK MESSAGE POINTER MESSAG <"Illegal "<-1>" character"> 10$: MOVB (R4)+,R4 ;GET LAST/MIDDLE CHARACTER BR ERRMIO ; AND GO TO COMMON PROCESSING .DSABL LSB ERRORS: MOV (R4)+,R0 ;GET RAD50 OF ERROR CODE MOV (R4)+,-(SP) ;SAVE THE TEXT POINTER CLR R4 ;THEN FLAG FOR FOLLOWING STRING BR ERRMIO ;NOW DO IT .ENDC ERRMSG: MOV (R4)+,R0 ;GET RAD50 OF ERROR CODE .IF NE E$$TXT MOV (R4)+,-(SP) ;SAVE THE TEXT POINTER .IFTF ERRMIO: MOV (R5),ERRPOS(R5) ;SAVE ERRING "SCANP" .IFT MOV EHELP(R5),R2 ;GET EDIT HELP LEVEL BIC #^C<3>,R2 ; MASKED TO BITS <1-0> DEC R2 ; AND LESS 1 BNE 10$ ;NOT "EH"=1, SO KEEP STRING POINTER CLR (SP) ;"EH"=1, SO NO MORE STRING POINTER 10$: MOV (SP)+,TEMP(R5) ;NOW SAVE THE STRING POINTER .ENDC MOV #TECOCR,-(SP) ;SET THE RESTART RETURN ADDRESS BIT EHELP(R5),#4 ;DESIRE FAILING COMMAND AUTO-PRINT? BEQ 20$ ;NOPE TST ERRPOS(R5) ;YEP, IS THERE AN ERROR POSITION? BLE 20$ ;IF NONE, THEN FORGET IT... MOV #ERR4EH,(SP) ;ELSE PRINT FAILING COMMAND ON EXIT 20$: JSR PC,ALLERR ;TELL 'TECOIO' ABOUT THE ERROR MOV #50,R2 ;SET TO DIVIDE BY 50 CLR -(SP) ;FLAG END OF CHARACTERS 30$: JSR PC,DIVD ;DIVIDE BY 50 MOV R1,-(SP) ; AND SAVE REMAINDER TST R0 ; ANY ANSWER LEFT? BNE 30$ ; LOOP IF SO... JSR PC,CRLFNO ;NO CTRL/O AND RESTORE CARRIAGE MOV #'?-<'A-1>,R0 ;NOW SET FOR PRINTING A "?" 40$: ADD #'A-1,R0 ;MAKE A CHARACTER CMP R0,#'Z ;REALLY ALPHABETIC? BLOS 50$ ;YES, SO TYPE IT ADD #'0-36-<'A-1>,R0 ;NO, SO CONVERT TO NUMERIC 50$: JSR PC,TYPE ; AND TYPE IT MOV (SP)+,R0 ;GET NEXT BNE 40$ ; IF ANY... .IF NE E$$TXT MOV TEMP(R5),R1 ;GET THE STRING POINTER BEQ 90$ ;IF ANY... MOV FILBUF(R5),R2 ;PRESET FOR PRINTING A FILENAME MOV #TAB,R0 ;START WITH A TAB 60$: JSR PC,TYPE ;TYPE A CHARACTER 70$: MOVB (R1)+,R0 ;GET STRING CHARACTER BGT 60$ ; IF MORE... BEQ 80$ ; OR THE STRING'S END MOV R4,R0 ;ELSE GET LAST/MIDDLE CHARACTER BNE 60$ ; IF ANY... MOV SCHBUF(R5),R2 ;ELSE DO THE SEARCH BUFFER 80$: TST R4 ;IS A QUOTED STRING TO COME? BNE 90$ ;NO, FINAL END MOV #SPACE,R0 ;YES, START WITH JSR PC,TYPE ; A SPACE MOV #'",R0 ;THEN THE JSR PC,TYPE ; LEADING " JSR PC,TYPSPC ;NOW GO DO THE BUFFERED STRING MOV #'",R0 ;SET THE CLOSING " JSR PC,TYPE ; AND THEN TYPE THAT 90$: .ENDC RTS PC ;NOW EXIT .SBTTL Q-REGISTER REFERENCE ; RETURNS: R0 = 0 Q-REG # TIMES 4 ; R1 = POINTER TO Q-REG SIZE POINTER TO Q-REG VALUE +2 ; R2 = OFFSET TO BASE OF Q-REG 0 ; "QNMBR" SET AS SPECIFIED "QNMBR" SET AS SPECIFIED .ENABL LSB QREFVL: MOV #20$,-(SP) ;SET FLAG FOR VALUE REFERENCE ONLY QREF: JSR PC,SCNUPP ;GET NEXT CHARACTER CLR R1 ;GUESS AT A NORMAL Q-REGISTER NAME CMP R0,#'. ;LOCAL TO MACRO LEVEL Q-REGISTER? BNE QREFR1 ;NOPE JSR PC,SCNUPP ;YEP, FETCH THE SUB-NAME CHARACTER MOV #LCLQRG-1,R1 ;FLAG AS SUCH WITH THE OFFSET QREFR1: JSR PC,ALPHAN ;MUST BE ALPHANUMERIC BCC 60$ ; BUT IT IS NOT CMP R0,#'A ;IS IT ALPHA? BLO 10$ ;NOPE, IT IS NUMERIC ADD #1-'A-<33-'0>,R0 ;YEP, RANGE IS 1-32 10$: ADD #33-'0,R0 ;RANGE IS 33-44 ADD R1,R0 ;ADD IN ANY NEEDED LOCAL LEVEL BIAS QREFR0: MOV R0,QNMBR(R5) ;SAVE THE Q-REG NUMBER .SBTTL GET SUM OF Q-REGISTER IN "QNMBR" (QSUMY) QSUMY: MOV QNMBR(R5),R0 ;GET THE Q-REG NUMBER .SBTTL GET SUM OF Q-REGISTER IN R0 (QSUMX) QSUMX: MOV #QARRAY,R1 ;GET OFFSET TO Q-REG ARRAY ADD R5,R1 ;NOW FIND IT FOR REAL CLR R2 ;START OFFSET OF REG AT 0 CMP (SP),#20$ ;SPECIAL REFERENCE FOR VALUE ONLY? BNE 40$ ;NO, ENTER COUNTING LOOP ASL R0 ;Q-REG NUMBER TIMES 2 ASL R0 ; THEN TIMES 4 ADD R0,R1 ;POINT TO Q-REG VALUE +2 20$: RTS PC ; AND EXIT 30$: ADD (R1)+,R2 ;SUM THE TOTAL OFFSET TST (R1)+ ; AND SKIP THE VALUE SPOT 40$: DEC R0 ;MORE? BGT 30$ ;YES, LOOP 50$: RTS PC ;NO, EXIT 60$: ERROR IQN,<"Illegal Q-reg name"> CMDCHR <'[> ;"[" IS Q-REG PUSH JSR PC,QREF ;REFERENCE THE Q-REGISTER MOV QNMBR(R5),-(SP) ;SAVE NUMBER OF THAT REGISTER MOV (R1),R4 ;SAVE SIZE OF THAT REGISTER MOV #AUXQRG,QNMBR(R5) ;NOW SET THE AUX Q-REG'S NUMBER JSR PC,QSUMY ;SUM UP THE AUX Q-REG MOV (R1),R0 ;GET ITS CURRENT SIZE ADD R4,R0 ;ADD IN THE REF'D Q-REG'S SIZE ADD #4,R0 ; AND ADD IN 4 FOR GOODNESS JSR PC,QADJ ;NOW ADJUST(UP) ITS SIZE ADD (R1),R2 ;GET POINTER TO ITS END+1 MOV R2,R4 ; AND SAVE THAT POINTER MOV (SP)+,R0 ;GET BACK REF'D Q-REG NUMBER JSR PC,QSUMX ; AND SUM UP THAT Q-REG ADD QRSTOR(R5),R2 ;ABS PTR TO REF'D Q-REG ADD QRSTOR(R5),R4 ;ABS PTR TO AUX Q-REG END+1 CMP (R1)+,(R1)+ ;SKIP OVER THE SIZE/VALUE MOVB -(R1),-(R4) ;SAVE MSB OF VALUE AND MOVB -(R1),-(R4) ; LSB OF VALUE MOVB -(R1),-(R4) ;SAVE MSB OF SIZE AND MOVB -(R1),-(R4) ; LSB OF SIZE MOV (R1),R1 ;NOW GET SIZE INTO HERE 70$: DEC R1 ;MORE TO MOVE? BMI 50$ ;NO, DONE MOVB (R2)+,-(R4) ;YES, MOVE A BYTE BR 70$ ; AND LOOP FOR MORE .DSABL LSB .ENABL LSB 10$: TST NFLG(R5) ;RETURNING A VALUE? BPL 20$ ;NOPE, SO ERROR MOV (SP)+,N(R5) ;YEP, RETURN 0 AS THE VALUE RTS PC ; AND EXIT 20$: ERROR CPQ,<"Can't pop Q-reg"> CMDCHR <']> ;"]" IS Q-REG POP JSR PC,CHKCLO ;CHECK FOR OPTIONAL COLON MODIFIER JSR PC,QREF ;REFERENCE THE Q-REGISTER MOV #AUXQRG,R0 ;GET NUMBER OF AUX Q-REG JSR PC,QSUMX ; AND SUM IT UP MOV (R1),-(SP) ;SAVE ITS CURRENT SIZE BEQ 10$ ;NO SIZE, TOO MANY POP'S ADD (R1),R2 ;ELSE INDEX TO ITS END+1 ADD QRSTOR(R5),R2 ;MAKE THE POINTER ABSOLUTE MOVB -(R2),-(SP) ;SET MSB OF REG'S VALUE SWAB (SP) ;NOW PUT IT UP TO MSB MOVB -(R2),(SP) ; AND SET LSB OF REG'S VALUE MOVB -(R2),R0 ;SET MSB OF REG'S NEW SIZE SWAB R0 ; SWITCH IT TO HIGH BYTE BISB -(R2),R0 ; AND GET LSB OF SIZE JSR PC,QADJ ;ADJUST REF'D Q-REG TO THAT SIZE SUB (R1)+,2(SP) ;FIND NEW SIZE FOR AUX Q-REG MOV (SP)+,(R1) ;SET REF'D Q-REG'S NEW VALUE MOV -(R1),R3 ;GET NEW SIZE INTO HERE MOV R2,R4 ;SAVE POINTER TO ITS START MOV #AUXQRG,QNMBR(R5) ;GET AUX Q-REG # AGAIN JSR PC,QSUMY ; AND SUM IT UP NOW ADD (R1),R2 ;INDEX TO ITS END+1 ADD QRSTOR(R5),R2 ;MAKE POINTER ABSOLUTE ADD QRSTOR(R5),R4 ;MAKE REF'D Q-REG PTR ABS ALSO SUB #4,R2 ;BACK OVER SAVED VALUE/SIZE 30$: DEC R3 ;MORE DATA? BMI 40$ ;NO, ALMOST DONE MOVB -(R2),(R4)+ ;YES, MOVE 1 DATA BYTE BR 30$ ; AND LOOP... 40$: MOV (SP)+,R0 ;GET NEW AUX Q-REG SIZE SUB #4,R0 ; CORRECTING FOR THE FUDGE .IIF NE .-QADJ, .ERROR ;ADJUST IT (DOWN) AND EXIT .DSABL LSB .SBTTL Q-REGISTER SIZE ADJUST ROUTINE ; R0 = NEW SIZE OF Q-REGISTER IN "QNMBR" ; RETURNS: R0 = 0 ; R1 = POINTER TO NEW Q-REG SIZE ; R2 = OFFSET TO THIS Q-REG ; (R3,R4 ARE CLOBBERED) .ENABL LSB QADJ: MOV R0,R4 ;COPY THE NEW Q-REG SIZE JSR PC,QSUMY ; AND SUM CURRENT Q-REG OFFSET MOV QZ(R5),R3 ;GET END OF ALL Q-REGS MOV R1,R0 ;COPY Q-REG SIZE POINTER MOV R4,R1 ; AND GET WORKING COPY OF NEW SIZE ADD (R0),R2 ;POINTER TO CURRENT END OF Q-REG SUB (R0),R1 ;SIZE CHANGE (NEW-OLD) BLO 20$ ;NEW < OLD BEQ 10$ ;NEW = OLD ADD R3,R1 ;NEW > OLD; GET NEW QZ SIZE QREGS ;CHECK OUT THE SIZE BCC 30$ ;WE CAN'T DO IT MOV R4,(R0) ;SET NEW Q-REG SIZE MOV R1,QZ(R5) ;SET NEW TOTAL Q-REG SIZE MOV QRSTOR(R5),R0 ;GET Q-REG AREA POINTER JSR PC,EXPAND ;NOW EXPAND THE Q-REGS 10$: MOV QCMND(R5),R0 ;GET COMMAND Q-REG NUMBER MOV #QSUMY,-(SP) ;SET FOR COMMAND SETUP JUST IN CASE SETCMD: MOV R0,QCMND(R5) ;SET COMMAND Q-REG NUMBER JSR PC,QSUMX ; AND SUM UP FOR THAT REGISTER MOV R2,QBASE(R5) ;STORE THE BASE OFFSET MOV (R1),QLENGT(R5) ; AND THE LENGTH RTS PC ;THEN EXIT 20$: MOV R4,(R0) ;SET NEW Q-REG SIZE ADD R1,QZ(R5) ;LOWER THE TOTAL Q-REG SIZE ADD R2,R1 ;POINT TO THE END OF DELETE MOV QRSTOR(R5),R0 ;GET Q-REG AREA POINTER JSR PC,SHRINK ;NOW SHRINK THE Q-REGS BR 10$ ;ALL DONE 30$: ERROR MEM,<"Memory overflow"> .DSABL LSB CMDCHR <'M> ;"M" IS THE MACRO COMMAND JSR PC,QREF ;REFERENCE THE MACRO Q-REGISTER MOV QNMBR(R5),-(SP) ; AND SAVE ITS Q-REG NUMBER CMP (SP),#LCLQRG ;IS REF'D Q-REGISTER A LOCAL Q-REG? BLO 10$ ;NOPE MOV #-1,CLNF(R5) ;YEP, FAKE A COLON TO KEEP LOCALS 10$: MOV CLNF(R5),LCLSIZ(R5) ;COLON MODIFIED MACRO COMMAND? BMI 50$ ;YES, LEAVE LOCAL Q-REGS ALONE... CLR R0 ;CLEAR FLAG SAYING LOCAL VALUES EXIST CLR LCLSIZ(R5) ; AND CLEAR OUT THE TOTAL LOCAL SIZE MOV #QARRAY+<*4>,R1 ;GET REL POINTER TO LOCAL Q-REGS ADD R5,R1 ; AND MAKE IT ABSOLUTE MOV #NUMQRG,R2 ;SET NUMBER OF LOCALS TO LOOK AT 20$: ADD (R1)+,LCLSIZ(R5) ;ACCUMULATE THE TOTAL LOCAL SIZE BIS (R1)+,R0 ;SAVE NEEDED IF ANY LOCAL VALUE DEC R2 ;MORE TO GO? BNE 20$ ;YEP, LOOP... BIS LCLSIZ(R5),R0 ;DO WE REALLY NEED A LOCAL SAVE? BEQ 40$ ;NOPE MOV #NUMQRG*4,R0 ;SET 2 WD/SAVED Q-REG FOR SIZE INC ADD R0,LCLSIZ(R5) ; AND ALSO UPDATE THE TOTAL SAVED SIZE ADD -4(R1),R0 ;SET NEW SIZE FOR LAST LOCAL MOV #LCLQRG+,QNMBR(R5) ;SET THE LAST LOCAL Q-REG NUMBER JSR PC,QADJ ;GO ADJUST LAST LOCAL TO SAVE AREA ADD (R1)+,R2 ;POINT JUST BEYOND THE SAVE AREA ADD QRSTOR(R5),R2 ; AND MAKE THE POINTER ABSOLUTE TST (R1)+ ;SKIP LAST LOCAL'S VALUE FOR LOOPING MOV #NUMQRG*2,R3 ;SET NUMBER OF LOCAL WORDS TO SAVE 30$: MOVB -(R1),-(R2) ;SAVE THE MSB OF LOCAL'S SIZE/VALUE MOVB -(R1),-(R2) ; AND THE LSB CLR (R1) ; THEN ZAP ITS SIZE/VALUE TO NOTHING DEC R3 ;MORE TO GO? BNE 30$ ;YEP, LOOP... 40$: ADD LCLSIZ(R5),QARRAY+<*4>(R5) ;ADD SAVE SIZE TO THE AUX BNE 50$ ;EITHER PRIOR REALS OR THIS IS REAL INC QARRAY+<*4>+2(R5) ;ELSE COUNT INITIAL UNREAL SAVES 50$: CLR CLNF(R5) ;ENSURE THAT THE COLON FLAG IS OFF PUSH SCANP,MPDL,QCMND,LCLSIZ,ITRST ;NOW PUSH ALL OLD DATA MOV R2,MPDL(R5) ;SAVE PDL AT MACRO'S START CLR (R5) ;START MACRO OFF AT RELATIVE 0 CLR ITRST(R5) ;NOT INTO ANY ITERATION YET MOV (SP)+,R0 ;THIS IS Q-REG WITH THE MACRO IN IT BR SETCMD ;GO OFF AND START THE MACRO .SBTTL LOCAL Q-REGISTER HANDLING SUBROUTINES .ENABL LSB 10$: TST QARRAY+<*4>+2(R5) ;ANY UNREAL LOCAL SAVE TO RESTORE? BEQ 70$ ;NOPE, EXIT JSR PC,40$ ;YEP, ZAP THE CURRENT LOCALS CLNLCL: TST QARRAY+<*4>(R5) ;ANY LOCAL SAVE TO RESTORE? BEQ 10$ ;NOPE, GO CHECK FOR UNREAL SAVES MOV #CLNLCL,-(SP) ;YEP, COME BACK TO CHECK AGAIN... 20$: JSR PC,40$ ;CLEAR CURRENT LOCALS BEFORE THE POP MOV #AULQRG,R0 ;SET THE LOCAL AUX Q-REG NUMBER JSR PC,QREFR0 ; AND REFERENCE IT MOV R1,R4 ;SAVE POINTER TO AUX'S SIZE ADD (R1)+,R2 ;POINT JUST BEYOND THE SAVE AREA ADD QRSTOR(R5),R2 ; AND MAKE THE POINTER ABSOLUTE SUB #NUMQRG*4,R2 ; THEN ABSOLUTE TO SAVE AREA START TST (R1)+ ;SKIP UNREAL COUNT FOR THE LOOP BELOW MOV #NUMQRG,R3 ;SET NUMBER OF LOCAL Q-REGS TO RESTORE 30$: MOVB (R2)+,(R1)+ ;RESTORE THE LSB OF LOCAL'S SIZE MOVB (R2)+,(R1)+ ; AND THE MSB SUB -2(R1),(R4) ;REMOVE THAT SIZE FROM THE LOCAL AUX MOVB (R2)+,(R1)+ ;RESTORE THE LSB OF LOCAL'S VALUE MOVB (R2)+,(R1)+ ; AND THE MSB DEC R3 ;MORE TO GO? BNE 30$ ;YEP, LOOP... MOV -4(R1),R0 ;GET SIZE OF LAST LOCAL SUB #NUMQRG*4,R0 ;REMOVE THE 2 WDS/SAVED Q-REG MOV #LCLQRG+,QNMBR(R5) ;SET THE LAST LOCAL Q-REG NUMBER JMP QADJ ;ADJUST LAST LOCAL TO PURGE SAVE AREA POPLCL: TST LCLSIZ(R5) ;SHOULD WE POP A LOCAL Q-REG SAVE? BGT 20$ ;YEP, GO DO A LOCAL CLEAR THEN POP BLT 70$ ;NOPE, AND LEAVE CURRENT LOCALS ALONE 40$: TST QARRAY+<*4>(R5) ;NOPE, SET NULL, BUT IS THIS UNREAL? BNE 50$ ;CAN'T BE UNREAL IF MORE REAL IS LEFT DEC QARRAY+<*4>+2(R5) ;ELSE UNCOUNT INITIAL UNREAL SAVES 50$: CLR R0 ;CLEAR OUT CURRENT TOTAL LOCAL SIZE MOV #QARRAY+<*4>,R1 ;GET POINTER BEYOND LOCALS ADD R5,R1 ; AND MAKE IT ABSOLUTE MOV #NUMQRG,R2 ;SET NUMBER OF LOCALS TO LOOK AT 60$: CLR -(R1) ;CLEAR OUT ANY LOCAL VALUE ADD -(R1),R0 ;ACCUMULATE THE TOTAL LOCAL SIZE CLR (R1) ; THEN ZAP ALL SIZES TO NOTHING DEC R2 ;MORE TO GO? BNE 60$ ;YEP, LOOP... MOV R0,(R1) ;SET THE TOTAL SIZE INTO FIRST LOCAL BEQ 70$ ;ZERO, SO NOTHING TO PURGE MOV #LCLQRG,QNMBR(R5) ;SET THE FIRST LOCAL LEVEL Q-REG CLR R0 ;WE WANT TO PURGE AWAY ALL OLD DATA JMP QADJ ;GO ADJUST THE FIRST LOCAL TO ZERO... GETXTP: MOV P(R5),R0 ;GET . CMP R0,ZZ(R5) ;TOO FAR? BHIS 70$ ;YES [BHIS=BCC] ADD TXSTOR(R5),R0 ;NO, MAKE ABSOLUTE MOVB (R0),R0 ; AND GET CHARACTER SEC ;OK [CARRY SET] 70$: RTS PC ;EXIT .DSABL LSB .SBTTL GENERAL SUBROUTINES .ENABL LSB 10$: MOV R0,-(SP) ;MOVE CO-ROUTINE RETURN TO STACK MOVB (R4)+,R0 ;GET ITEM COUNT MOVB (R4)+,R1 ;GET STARTING OFFSET ADD R5,R1 ;MAKE THAT ABSOLUTE MOV PDL(R5),R2 ;GET THE CURRENT PUSH-DOWN POINTER JSR PC,@(SP)+ ; AND CO-ROUTINE IT MOV R2,PDL(R5) ;UPDATE THE PUSH-DOWN POINTER MOV (SP)+,R0 ;RESTORE R0 FROM THE 'JSR R0' RTS R4 ; AND FINAL EXIT PUSH: TST PCNT(R5) ;HAVE PAREN'S BEEN PUSHED? BNE 50$ ;YES, ERROR PUSHP: JSR R0,10$ ;DO THE COMMON THING 20$: CMP R2,SCHBUF(R5) ;OVERFLOW? BHIS 40$ ;YES, ERROR MOV (R1)+,(R2)+ ;NO, SO PUSH AN ITEM DEC R0 ; AND BNE 20$ ; LOOP RTS PC ;THEN CO-ROUTINE RETURN POP: JSR R0,10$ ;DO THE COMMON THING 30$: MOV -(R2),-(R1) ;POP AN ITEM DEC R0 ; AND BNE 30$ ; LOOP RTS PC ;THEN CO-ROUTINE RETURN 40$: ERROR PDO,<"Push-down list overflow"> 50$: ERROR MRP,<"Missing )"> .DSABL LSB .ENABL LSB QSKP: JSR PC,QCHK ;CHECK FOR A QUOTE CHARACTER MOV (R5),OSCANP(R5) ; AND SAVE "SCANP" QSKPE: JSR PC,SCNQST ;SCAN CHECKING THE QUOTE CHARACTER BNE QSKPE ;NOT A MATCH, CONTINUE SCANNING 10$: RTS PC ;EXIT BZCHK: CMP R0,ZZ(R5) ;TOO BIG? BLOS 10$ ;NOPE ERROR POP,<"Pointer off page"> .DSABL LSB .ENABL LSB 10$: MOV #1,R0 ;PRETEND WE SAW A ONE JSR PC,NCOM ; AND COMPUTE ON IT GETN: MOV N(R5),R0 ;GET THE NUMBER INC NFLG(R5) ;REALLY THERE? BNE 10$ ;NOPE RTS PC ;YES .DSABL LSB QSKPR0: JSR PC,QSKP ;SKIP THE QUOTED STRING JSR PC,IREST ;THEN RESTORE ESCAPE AS THE QUOTE MOV OSCANP(R5),R3 ;GET ORIGINAL SCAN POINTER MOV (R5),R0 ;GET ENDING (THE QUOTE) POINTER DEC R0 ;BACK UP OVER THE QUOTE SUB R3,R0 ; AND FIND THE STRING'S LENGTH RTS PC ;EXIT WITH CC'S AS INDICATION CHKCLN: CLR NFLG(R5) ;CLEAR THE NUMBER FLAG CHKCLO: TST CLNF(R5) ;IS COLON MODIFIER PENDING? BPL 10$ ;NO MOV #-1,R0 ;YES, SET UP RESULT JSR PC,NCOM ; AS A -1 10$: CLR CLNF(R5) ;NOW TURN OFF PENDING COLON RTS PC ; AND EXIT SCNUPP: JSR PC,SCAN ;SCAN FIRST UPPERC: CMP R0,#'A+40 ;ALREADY OK? BLO 10$ ;YES CMP R0,#'Z+40 ;MIGHT BE... BHI 10$ ;IT IS, JUST EXIT BIC #40,R0 ;ELSE MAKE LOWER CASE INTO UPPER CASE 10$: RTS PC ;NOW EXIT SCNCTL: MOV (SP)+,(SP) ;POP ONE STACK ITEM JSR PC,SCAN ;SCAN A CHARACTER MAKCTL: JSR PC,UPPERC ;FORCE CHARACTER TO UPPER CASE CMP R0,#'@ ;IS CHARACTER "@" OR GREATER? BLO 10$ ;NOPE, AN ERROR CMP R0,#'_ ;IS CHARACTER "_" OR LESS? BHI 10$ ;NOPE, AN ERROR ALSO BIC #100,R0 ;IT'S "@" THROUGH "_", MAKE A CONTROL RTS PC ; AND EXIT 10$: ERROR IUC,<"Illegal ^ character"> SCNQST: JSR PC,SCAN ;SCAN A CHARACTER CMP R0,QUOTE(R5) ;SET CC'S AGAINST MATCHING THE QUOTE RTS PC ; AND EXIT WITH CC'S SET .SBTTL SORT ; INVOKED VIA "SORT" MACRO ; R0 = CHARACTER TO SORT ; (R1 IS CLOBBERED) SORTC: MOV N(R5),R3 ;GET ARGUMENT SORTZ: CLR R2 ;SET UP FOR THE "ADD" CHAIN SORTS: JSR PC,SCNUPP ;GET CHARACTER TO SORT ON SORT: MOV (R4)+,R1 ;GET TABLE ADDRESS 10$: CMPB R0,-(R1) ;GET A MATCH? BHI 10$ ;NO, KEEP GOING BLO 20$ ;NO, TOO FAR CMPB (R1),#-1 ;A BOGUS MATCH ON THE TERMINATOR? BEQ 20$ ;YEP, DON'T CALL IT A MATCH... SUB -(R4),R1 ;NOPE, FIND NET CHANGE (<0) COM R1 ;MAKE THAT 0,1,2, ETC. ASL R1 ;NOW TIMES 2 FOR WORD ADDRESSING ADD (R4),R1 ;FIND POINTER INTO THE TABLE MOV (R1),R4 ;SET A NEW RETURN ADDRESS 20$: RTS R4 ;NOW EXIT .ENABL LSB TERMS: CMP R0,#FF+1 ;TERMINATOR TEST BHIS 20$ ;TOO BIG, RETURN C=0 10$: CMP #LF-1,R0 ;SET CARRY ON LOW RANGE 20$: RTS PC ;NOW EXIT NUMER: CMP R0,#'9+1 ;NUMERIC TEST BHIS 30$ ;RETURN CARRY CLEAR IF HIGH CMP #'0-1,R0 ;SET CARRY ON LOW RANGE 30$: RTS PC ;NOW EXIT SYMCHR: CMP R0,#'. ;.? BEQ 10$ ;YES, GO EXIT C=1 (LF .LO. ".") CMP R0,#'$ ;$? BEQ 10$ ;YES, GO EXIT C=1 (LF .LO. "$") CMP R0,SYMSPC(R5) ;OTHER SPECIAL? BEQ 10$ ;YES (LF .HIS. 0) OR (LF .LO. SPECIAL) ALPHAN: JSR PC,NUMER ;CHECK FOR NUMERIC FIRST BCS 40$ ;EXIT IF SO ALPHA: JSR PC,UPPERC ;FORCE LOWER CASE INTO UPPER CASE ALPHAU: CMP R0,#'Z+1 ;ALPHABETIC TEST BHIS 40$ ;RETURN C=0 IF TOO HIGH CMP #'A-1,R0 ;SET CARRY ON LOW RANGE 40$: RTS PC ;NOW EXIT ALPHAL: SUB #40,R0 ;MAKE LOWER CASE INTO UPPER CASE BR ALPHAU ; THEN GO CHECK FOR UPPER CASE .DSABL LSB TSTNXT: MOV (R4)+,-(SP) ;SAVE THE ARGUMENT CHARACTER MOV (R5),R0 ;GET COMMAND POINTER CMP R0,QLENGT(R5) ;END OF COMMAND? BHIS 10$ ;YES, SO EXIT (C=0) ADD QBASE(R5),R0 ;NO, ADD COMMAND OFFSET ADD QRSTOR(R5),R0 ; AND MAKE ABSOLUTE MOVB (R0),R0 ;FETCH CHARACTER JSR PC,UPPERC ; AND MAKE UPPER CASE CMP R0,(SP) ;MATCH? BNE 10$ ;NO, EXIT (C=0) INC (R5) ;YES, BUMP POINTER JSR PC,TRACE ;TRACE THE CHARACTER COM (SP) ;INDICATE FOUND (C=1) 10$: ASL (SP)+ ;SET C-BIT IF FOUND RTS R4 ; AND EXIT CRLFNO: JSR PC,NOCTLO ;CANCEL ANY CONTROL/O CRLF: MOV #CR,R0 ;NOW SET RETURN JSR PC,TYPE ; AND TYPE IT MOV #LF,R0 ;NOW SET LINE FEED JMP TYPE ; AND TYPE IT NLINES: INC CFLG(R5) ;WAS THERE A COMMA? BEQ 10$ ;YES CLR CFLG(R5) ;NO, CLEAR THE FLAG MOV P(R5),M(R5) ;SAVE . IN "M" JSR PC,.VVV.N ; AND MOVE . FORWARD "N" LINES MOV P(R5),N(R5) ;"N" IS THE NEW . MOV M(R5),P(R5) ;RESTORE THE ORIGINAL . 10$: CLR NFLG(R5) ;USE UP THE NUMBER MOV N(R5),R0 ;GET NTH CHARACTER POSITION CMP R0,M(R5) ;IS IT AFTER MTH CHARACTER? BHIS 20$ ;YES MOV M(R5),N(R5) ;NO, SO SWITCH MOV R0,M(R5) ; N AND M MOV N(R5),R0 ;NOW GET NTH POSITION AGAIN 20$: JSR PC,BZCHK ;IN RANGE? SUB M(R5),R0 ;FIND DISTANCE BETWEEN N AND M RTS PC ;THEN EXIT .ENABL LSB CVTSRH: CMPB R0,#240 ;DO WE NEED TO TRIM THIS CHARACTER BHIS 20$ ;NOPE BIC #^C<177>,R0 ;YEP, SO TRIM IT ALREADY BNE 20$ ;IT'S NOT THE "SPECIAL NEXT" CODE MOVB (R2)+,R0 ;ELSE GET THE REAL CHARACTER CVTSPC: BIT R0,#40 ;IS IT SPECIAL FOR 000 OR 200? BEQ 10$ ;NOPE, IT'S FOR 201-237 CMPB R0,#177 ;MIGHT BE... BEQ 10$ ;NOPE, IT'S FOR 377 BIC #^C<377>!40,R0 ;YEP, FIX UP FOR THE 000 OR 200 10$: ADD #^C<177>,R0 ;RESTORE ORIGINAL SPECIAL CHARACTER 20$: RTS PC ;EXIT .DSABL LSB GETQRG: MOV SCHBUF(R5),R2 ;GUESS AT "_" (SEARCH BUFFER) TSTNXT '_ ;SPECIAL CASE OF "_"? BCS 10$ ;YES TSTNXT '* ;SPECIAL CASE OF "*"? BCC 30$ ;NO, NORMAL Q-REG REFERENCE MOV FILBUF(R5),R2 ;YES, GET FILENAME BUFFER POINTER 10$: MOV R2,R0 ;COPY THE START OF DATA POINTER 20$: TSTB (R0)+ ;END OF DATA YET? BNE 20$ ;NOPE, LOOP SUB R2,R0 ;YEP, FIND SIZE+1 (THE NULL...) DEC R0 ; AND, THEN, THE REAL SIZE ;CLC ;C=0 FROM THE 'SUB' ABOVE RTS PC ;EXIT C=0 FOR "_" OR "*" 30$: JSR PC,QREF ;REFERENCE THE Q-REG MOV (R1),R0 ;PICKUP SIZE OF THE Q-REG SEC ;SET C=1 FOR NORMAL REFERENCE RTS PC ; AND EXIT ZEROD: MOV (R3)+,R4 ;PICKUP OUTPUT ROUTINE ADDRESS MOV R3,(SP) ;THEN SET THE RETURN ADDRESS MOV N(R5),-(SP) ;GET NUMBER BPL 10$ ;IT IS + TST NMRBAS(R5) ;IT IS -, BUT IS RADIX DECIMAL? BNE 10$ ;IF NOT DECIMAL, THEN NO SIGN MOV #'-,R0 ;IF DECIMAL, THEN SIGNED JSR PC,(R4) ;OUTPUT MINUS SIGN NEG (SP) ; AND MAKE + 10$: MOV (SP)+,R0 ;RESTORE THE NUMBER MOV #8.,R2 ;RADIX = 8? TST NMRBAS(R5) ;THIS TELLS US... BGT 30$ ;YES, OCTAL BEQ 20$ ;NO, DECIMAL ADD #6,R2 ;NO, HEXIDECIMAL 20$: TST (R2)+ ;FORM CORRECT RADIX 30$: JSR PC,DIVD ;NOW DIVIDE MOV R1,-(SP) ;SAVE REMAINDER TST R0 ;MORE TO GO? BNE 30$ ;YES 40$: MOV (SP)+,R0 ;GET BACK A DIGIT CMP R0,#15. ;DIGIT OR RETURN ADDRESS? BHI 60$ ;RETURN ADDRESS ADD #'0,R0 ;DIGIT CMP R0,#'9 ;HEXIDECIMAL DIGIT? BLOS 50$ ;NO ADD #<'A-10.>-'0,R0 ;YES, CORRECT IT 50$: JSR PC,(R4) ;OUTPUT IT BR 40$ ; AND LOOP 60$: JMP (R0) ;EXIT .ENABL LSB GETSCH: MOV SCHBUF(R5),R4 ;GET SEARCH BUFFER START GETSTG: MOV R0,-(SP) ;NOW SAVE THE ARGUMENT MOV R4,-(SP) ; AND THE STARTING POINT JSR PC,QCHK ;SET UP FOR ANY QUOTED STRING 10$: CLR R2 ;GET INPUT FROM SCAN 20$: TST R2 ;WHERE DO THEY COME FROM? BNE 100$ ;A Q-REG IF NON-ZERO JSR PC,SCNQST ;GET A CHARACTER CHECKING FOR QUOTE BEQ 170$ ;END OF SEARCH STRING IF QUOTE MATCH CMP R0,#'^ ;THE CONTROL CHARACTER PREFIX? BNE 30$ ;NOPE BIT EDIT(R5),#ED$CTL ;YEP, BUT ARE WE ALLOWING IT?? BNE 30$ ;SKIP CONVERSION IF NOT ALLOWED JSR PC,SCNQST ;GET CHARACTER TO MAKE A CONTROL CHAR BEQ 50$ ;WHOOPS, IT IS OUR QUOTE CHARACTER JSR PC,MAKCTL ;ELSE MAKE CHARACTER INTO CONTROL CHAR 30$: CLR R1 ;SIGNAL NO SPECIAL MODIFICATIONS CMP R0,#'Q-100 ;CTRL/Q? BEQ 40$ ;YES, GET NEXT LITERALLY CMP R0,#'R-100 ;CTRL/R? BEQ 40$ ;YES, GET NEXT LITERALLY COM R1 ;NO, SIGNAL FORCE LOWER CASE CMP R0,#'V-100 ;CTRL/V? BEQ 40$ ;YES, NEXT BECOMES LOWER CASE CMP R0,#'W-100 ;CTRL/W? BNE 110$ ;NOPE NEG R1 ;YES, SIGNAL FORCE UPPER CASE 40$: JSR PC,SCNQST ;GET THE CHARACTER TO MODIFY BEQ 50$ ;WHOOPS, IT IS OUR QUOTE CHARACTER ASL R1 ;WHAT SHOULD WE DO WITH IT?? BEQ 130$ ;NOTHING (CTRL/Q OR CTRL/R) BIT R0,#100 ;IS IT REALLY A CONTROL CHARACTER? BEQ 130$ ;YES, DON'T ALTER IT BIS #40,R0 ;FORCE INTO LOWER CASE BCS 130$ ;LOWER CASE IT IS (CTRL/V) BIC #40,R0 ;ELSE FORCE UPPER CASE (CTRL/W) BR 130$ ; THEN STORE IT IN SEARCH BUFFER 50$: CLRB (R4) ;ENSURE A MARKED END... ERROR ISS,<"Illegal search string"> 60$: TST R2 ;^E - ARE WE IN Q-REG FETCH? BNE 120$ ;YES, USE AS NORMAL ^E TSTNXT 'U ;NO, IS IT Q-REG VALUE? BCC 90$ ;NOPE JSR PC,QREFVL ;YEP, REFERENCE THE Q-REG FOR VALUE MOVB -2(R1),R0 ;GET Q-REG'S VALUE AS A BYTE BPL 130$ ;JUST GO STORE IT UNLESS NEGATIVE 70$: CMPB R0,#240 ;IS IT ONE OF THE C1 CONTROLS? BLO 80$ ;YES, WE MUST STORE IT SPECIALLY CMPB R0,#-1 ;WOULD IT LOOK LIKE THE TERMIATOR? BNE 130$ ;NOPE, JUST GO STORE IT AS IS 80$: BIC #^C<177>,R0 ;TRIM THE "NEGATIVE" BIT FROM VALUE BNE 160$ ;JUST GO STORE SPECIALLY IF WASN'T 200 MOV #40,R0 ;INDICATE A 200 WITH THIS CODE BR 160$ ; AND GO STORE IT SPECIALLY 90$: TSTNXT 'Q ;IS IT Q-REG FETCH? MOV #'E-100+200,R0 ;RESTORE CHARACTER AS CTRL/E BCC 130$ ;NOT Q, ENTER CTRL/E AS SPECIAL JSR PC,GETQRG ;Q, SO FIND Q-REG OR "_" OR "*" DEC (SP) ;ALWAYS SOMETHING STORED IF Q-REG MOV R0,R1 ;MOVE THE SIZE OVER TO HERE BCC 100$ ;"_" OR "*", ALL SET ADD QRSTOR(R5),R2 ;Q-REG, FIND THE ABSOLUTE START 100$: DEC R1 ;ANYTHING LEFT IN Q-REG? BMI 10$ ;NO, GO CLEAR FLAG MOVB (R2)+,R0 ;YES, GET A BYTE BMI 70$ ;HANDLE IT SPECIALLY IF NEGATIVE 110$: CMP R0,#'E-100 ;CTRL/E? BEQ 60$ ;YES CMP R0,#'N-100 ;CTRL/N? BEQ 120$ ;YES, THAT IS SPECIAL CMP R0,#'S-100 ;CTRL/S? BEQ 120$ ;YES, THAT IS SPECIAL CMP R0,#'X-100 ;CTRL/X? BNE 130$ ;NOPE, SO NORMAL SEARCH CHARACTER 120$: BIS #200,R0 ;FLAG THE SPECIAL CHARACTERS 130$: MOVB R0,(R4)+ ;STORE IN SEARCH BUFFER BEQ 150$ ;GO PROCESS NULL SPECIALLY CMPB 1(R4),#-1 ;MORE ROOM? BNE 20$ ;YES, SO CONTINUE 140$: CLRB (R4) ;NO, ENSURE A MARKED END... ERROR STL,<"String too long"> 150$: MOV #240,R0 ;INDICATE A NULL WITH THIS CODE DEC R4 ; AND BACK UP THE BUFFER POINTER 160$: MOVB #200,(R4)+ ;STORE THE SPECIAL "SPECIAL NEXT" CODE CMPB 1(R4),#-1 ;MORE ROOM LEFT? BNE 130$ ;YEP, GO STORE THE SPECIAL BR 140$ ;NOPE, STRING IS TOO LONG 170$: CMP R4,(SP)+ ;DID WE STORE ANYTHING? BEQ 180$ ;NOPE, USE PREVIOUS STRING CLRB (R4) ;YEP, ENSURE A MARKED END 180$: MOV (SP)+,R2 ;RESTORE THE ARGUMENT RTS PC ;EXIT WITH CC'S SET .DSABL LSB .ENABL LSB SEARCB: MOV M(R5),R0 ;GET START OF SEARCH BOUNDARY (M) INC CFLG(R5) ;IS IT REAL? BEQ 10$ ;YES CLR CFLG(R5) ;NO, CLEAR COMMA FLAG JSR PC,.QQQ.Q ;CALCULATE "N^Q" FOR END BOUNDARY MOV P(R5),R0 ;GET START BOUNDARY (.) ADD R0,N(R5) ; AND FORM END BOUNDARY (.+(N^Q)) 10$: JSR PC,BZCHK ;CHECK START FOR WITHIN RANGE MOV R0,-(SP) ; THEN SAVE START JSR PC,GETN ;GET END OF SEARCH BOUNDARY (N) JSR PC,BZCHK ;CHECK END OF WITHIN RANGE JSR PC,GETSCH ;NOW BUILD THE SEARCH ARGUMENT MOV (SP),R1 ;GET BACK START MOV #177400,(SP) ;SET FAILURE RETURN VALUE (177400) MOV R2,-(SP) ;SAVE END FOR DELTA-DOT CALCULATION MOV R2,-(SP) ; AND SAVE END AS END-OF-TEXT MOV #1,R2 ;GUESS AT FORWARDS, HIT COUNTER IS +1 SUB R1,2(SP) ;FIND ALLOWED DELTA-DOT (END-START) BPL 60$ ;IT'S FORWARDS, ALL SET MOV R1,(SP) ;IT'S BACKWARDS, SET REAL END-OF-TEXT NEG R2 ; AND HIT COUNTER IS -1 NEG 2(SP) ; AND MAKE DELTA-DOT POSITIVE INC 2(SP) ; AND WITH CORRECT CORRECTION BR 60$ ;NOW ALL SET SEARCH: CLR -(SP) ;SET FAILURE RETURN VALUE (0) MOV M(R5),-(SP) ;SET (TRIAL) DOT MOVEMENT BOUND BPL 20$ ;ENSURE THE BOUND LIMIT NEG (SP) ; IS POSITIVE 20$: INC CFLG(R5) ;REALLY A BOUNDED SEARCH? BEQ 30$ ;YES, BOUND ALL SET UP CLR CFLG(R5) ;NO, CLEAR THE COMMA FLAG CLR (SP) ;SET INFINITE (65536) BOUND LIMIT CMP CLNF(R5),#-2 ;OLD STYLE 'NO MOVE' SEARCH?? BNE 40$ ;NOPE INC (SP) ;YEP, SET BOUND FOR NO MOVEMENT 30$: COMB 3(SP) ;SET FAILURE RETURN VALUE (177400) 40$: JSR PC,GETN ;GET THE HIT NUMBER JSR PC,GETSCH ;NOW BUILD THE SEARCH ARGUMENT BNE 50$ ;NON-ZERO ARGUMENT, SO PROCEED ERROR ISA,<"Illegal search arg"> .SURCH: CLR -(SP) ;SET FAILURE RETURN VALUE (0) CLR -(SP) ;ALLOW INFINITE (65536) DOT MOVEMENTS 50$: MOV P(R5),R1 ;GET STARTING POINT MOV ZZ(R5),-(SP) ; AND ENDING POINT 60$: ADD TXSTOR(R5),R1 ;MAKE START ABSOLUTE ADD TXSTOR(R5),(SP) ; AND END ABSOLUTE MOV #1,-(SP) ;GUESS AT FORWARDS MOVEMENT (+1) MOV R2,-(SP) ;SAVE HIT COUNTER, CHECK ITS SIGN BPL 70$ ;POSITIVE, MOVE . BY +1 EACH FAILURE NEG 2(SP) ;NEGATIVE, MOVE . BY -1 EACH FAILURE ;SEC ; (C=1 FROM THE 'NEG' ABOVE) RORB 11(SP) ;INDICATE NO PAGING DESIRED NEG (SP) ;NOW GET A POSITIVE HIT COUNTER 70$: CLR LSCHSZ(R5) ;SET LAST STRING SIZE TO 0 80$: MOV R1,R3 ;GET STARTING POINT MOV SCHBUF(R5),R4 ; AND SEARCH STRING START MOV #-1,R2 ;SET CTRL/N INDICATOR INITIALLY .SUR.N: INC R2 ;FAILURE, BUT REVERSE SENSE? BNE 110$ ;O.K., A REAL FAILURE .SUR.C: CMP R3,4(SP) ;END OF TEXT? BLO 100$ ;NOPE TSTB (R4) ;YEP, BUT DOES IT MATCH END OF STRING? BEQ 140$ ;YES, SO ALL DONE (FOUND) TST 2(SP) ;NO, SEARCHING BACKWARDS?? BMI 110$ ;IF BACKWARDS THEN MOVE . IF POSSIBLE 90$: ASRB 11(SP) ;IS THIS A BOUNDED SEARCH? BCS 160$ ;YES, SO KEEP . BIT #ED$SRH,EDIT(R5) ;RESET . ON SEARCH FAILURE? BNE 160$ ;NOPE, SO DON'T CLR R3 ;YEP, SO .=0 BR 150$ ; AND EXIT 100$: MOVB (R4)+,R0 ;GET A STRING CHARACTER BMI .SUR.S ;PARITY BIT MEANS SPECIAL BEQ 140$ ;NULL MEANS END OF STRING .SUR.M: CMPB R0,(R3)+ ;MATCH? BNE 170$ ;NO, MIGHT BE A FAILURE .SUR.Y: INC R2 ;SUCCESS, BUT REVERSE SENSE? BNE .SUR.C ;O.K., SO CONTINUE 110$: MOV #-1,R4 ;SET MOVEMENT AMOUNT TO ONE 120$: INC R4 ;ARE WE DONE MOVING DOT YET? BGT 80$ ;YEP, KEEP SEARCHING ADD 2(SP),R1 ;NOPE, MOVE . ONE POSITION DEC 6(SP) ;ALLOWED TO MOVE DOT THIS FAR? BEQ 90$ ;NOPE, END THIS SEARCH CMP R1,TXSTOR(R5) ;IS . TOO SMALL NOW?? BHIS 120$ ;. IS O.K., CHECK FOR ANOTHER MOVEMENT BR 90$ ;. IS TOO SMALL, SEARCH FAILS 130$: BIT #ED$INC,EDIT(R5) ;ALWAYS MOVE . BY ONLY ONE? BEQ 120$ ;NOPE BR 110$ ;YEP, GO FORCE MOVEMENT AMOUNT TO ONE 140$: MOV R1,PST(R5) ;SAVE (ABS) STARTING POSITION MOV R1,R4 ;COPY (ABS) START AGAIN TO SUB R3,R4 ; GET "START"-"END" = -("LENGTH") DEC (SP) ;SEARCH ANOTHER TIME?? BGT 130$ ;YES, SO GO MOVE . AND SEARCH AGAIN MOV R4,LSCHSZ(R5) ;NO, DONE, STORE -("LENGTH") SUB TXSTOR(R5),R3 ;MAKE ENDING . RELATIVE SUB TXSTOR(R5),PST(R5) ;MAKE STARTING . RELATIVE MOV #-1,10(SP) ;INDICATE SUCCESS (-1) 150$: MOV R3,P(R5) ;SET . CORRECTLY 160$: MOV (SP)+,R2 ;RESTORE THE HIT COUNTER ADD #6,SP ;DUMP DIRECTION, DELTA-DOT, AND E-O-T MOV (SP)+,R1 ;SET CC'S AND RETURN INDICATOR RTS PC ; AND EXIT 170$: TST SFLG(R5) ;EXACT MODE SEARCHES? BNE .SUR.N ;YES, SO A REAL FAILURE JSR PC,180$ ;GO CONVERT THE PATTERN CHARACTER MOV R0,-(SP) ; AND SAVE IT MOVB -1(R3),R0 ;GET THE TEXT BUFFER CHARACTER JSR PC,180$ ;GO CONVERT THE TEXT BUFFER CHARACTER CMP R0,(SP)+ ;DO THEY REALLY MATCH? BEQ .SUR.Y ;YES, SUCCESS BR .SUR.N ;NO, A REAL FAILURE 180$: BIT R0,#100 ;CASE ALTERABLE (100-177, 300-377)? BEQ 190$ ;NOPE BIC #40,R0 ;YEP, UPPER CASE IT (100-137, 300-337) BPL 190$ ;IT'S NOT IN G1 RANGE (300-337) MOVB GENSRH+100(R0),R0 ;ELSE REMOVE THE DIACRITICAL 190$: RTS PC ;EXIT .DSABL LSB .SUR.S: CMPB R0,#240 ;IS IT POSSIBLY ONE OF OUR SPECIALS? BHIS 10$ ;NOPE, JUST GO MATCH ON IT CMPB R0,#'S-100+200 ;WAS SPECIAL CTRL/S? BEQ 60$ ;YES (IT IS CTRL/S) BHI 20$ ;NO (IT IS CTRL/X) CMPB R0,#'E-100+200 ;NO, IS IT CTRL/E? BEQ 80$ ;YES (IT IS CTRL/E) BHI 30$ ;NO (IT IS CTRL/N) MOVB (R4)+,R0 ;ELSE GET THE REAL MATCH CHARACTER JSR PC,CVTSPC ; AND GET IT CORRECTLY CONVERTED 10$: BR .SUR.M ;GO CHECK FOR A MATCH 20$: INC R3 ;CTRL/X IS ANY MATCH BR .SUR.Y ;INDICATE SUCCESS 30$: MOV #-1,R2 ;SET REVERSE FLAG BR .SUR.C ; AND CONTINUE 40$: MOV (R0),(SP) ;SET THE CORRECT DISPATCH ADDRESS MOVB (R3)+,R0 ;GET A TEXT CHATACTER JSR PC,@(SP)+ ;GO TEST CHARACTER 50$: BCS .SUR.Y ;MADE IT BR .SUR.N ;NO GO 60$: MOVB (R3)+,R0 ;GET A TEXT CHARACTER JSR PC,ALPHAN ;ALPHANUMERIC? 70$: BCC .SUR.Y ;NO, SO OK BR .SUR.N ;YES, SO NO 80$: MOVB (R4)+,R0 ;GET THE CTRL/E MODIFIER CHARACTER JSR PC,UPPERC ; AND FORCE IT TO UPPER CASE CMPB R0,#'S ;CTRL/E AND "S"? BEQ 110$ ;YES, MATCH NON-NULL SPACE/TAB CMPB R0,#'X ;X? BEQ 20$ ;YES, MATCH ANYTHING CMPB R0,#'G ;G? BEQ 180$ ;YES, DO Q-REG MATCHING CMPB R0,#'B ;B? BEQ 60$ ;YES, MATCH SEPARATORS MOV R0,-(SP) ;SAVE ^E CHARACTER ON THE STACK MOV #230$,R0 ;GET THE CHARACTER TABLE POINTER 90$: CMP (SP),(R0)+ ;CHARACTER MATCH TABLE? BEQ 40$ ;YES, WE HAVE A MATCH, GO DISPATCH TST (R0)+ ;NO, SKIP THE DISPATCH ADDRESS BNE 90$ ;MORE IN TABLE, KEEP CHECKING TST (SP)+ ;NOT IN TABLE, POP STACK 100$: DEC R4 ;OTHER, POINT BACK AGAIN MOVB #'E-100,R0 ; AND RESTORE THE CTRL/E BR 10$ ;NOW TRY FOR A CTRL/E MATCH 110$: MOV R3,-(SP) ;SAVE POINTER TO TEXT 120$: CMP R3,4+2(SP) ;END OF TEXT? BHIS 130$ ;YES, QUIT MOVB (R3)+,R0 ;NO, GET CHARACTER CMP R0,#SPACE ;SPACE? BEQ 120$ ;YES CMP R0,#TAB ;TAB? BEQ 120$ ;YES DEC R3 ;NEITHER, CORRECT TEST POINTER 130$: TST 2+2(SP) ;IS THIS A BACKWARDS SEARCH? BPL 170$ ;NOPE, BACKING UP WOULD BE WRONG CMP R3,(SP) ;YEP, DID WE FIND A NON-NULL SEQUENCE? BEQ 170$ ;NOTHING FOUND, JUST GO QUIT CMP R1,(SP) ;NON-NULL, WAS THE CTRL/E-S THE FIRST? BNE 170$ ;NOT FIRST, CAN'T BACKUP 140$: CMP R1,TXSTOR(R5) ;IS . AT BEGINNING OF TEXT? BLOS 170$ ;YES, CAN'T BACK UP FROM HERE CMPB -(R1),#SPACE ;CHECK FOR A SPACE BEQ 150$ ;IT'S A SPACE CMPB (R1),#TAB ;IS IT A TAB INSTEAD? BNE 160$ ;NOT A TAB, TIME TO QUIT 150$: DEC 6+2(SP) ;ALLOWED TO BACK UP? BNE 140$ ;YEP, WE DID SO, LOOP... INC 6+2(SP) ;CORRECT . MOVEMENT AMOUNT 160$: INC R1 ;CORRECT . POINTER 170$: CMP (SP)+,R3 ;CHECK FOR NON-NULL BLO 50$ ;NON-NULL, CONTINUE ('BLO'=>C=1) INC R3 ;NULL, SKIP SOMETHING BR 50$ ; AND CONTINUE ('BEQ'=>'BHIS'=>C=0) 180$: MOVB (R4),R0 ;GET Q-REG NAME CHARACTER CMP R0,#'. ;LOCAL TO MACRO LEVEL Q-REGISTER? BNE 190$ ;NOPE MOVB 1(R4),R0 ;YEP, GET THE REAL NAME CHARACTER 190$: JSR PC,ALPHAN ;IS IT LEGAL? BCC 100$ ;NOT LEGAL GROUP REFERENCE MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ; AND R2 CLR R1 ;GUESS AT A NORMAL REFERENCE CMPB (R4)+,#'. ;IS IT A LOCAL LEVEL REFERENCE? BNE 200$ ;NOPE INC R4 ;YEP, SKIP ONE MORE CHARACTER MOV #LCLQRG-1,R1 ;FLAG AS SUCH WITH THE OFFSET 200$: JSR PC,QREFR1 ;REFERENCE Q-REG BY CHARACTER MOVB (R3)+,R0 ;GET THE CHARACTER TO MATCH MOV (R1),R1 ;GET THE Q-REGISTER'S SIZE ADD QRSTOR(R5),R2 ;POINT ABSOLUTELY TO Q-REG 210$: SUB #1,R1 ;MORE CHARACTERS IN Q-REG? BLO 220$ ;NOPE, FAILURE (C=1 ALREADY) CMPB R0,(R2)+ ;CHECK THIS CHARACTER FOR A AMTCH BNE 210$ ;NOT A MATCH, LOOP ;CLC ;A MATCH, SUCCESS (C=0 ALREADY) 220$: MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ; AND R1 BR 70$ ;NOW EXIT WITH AN INDICATION 230$: .WORD 'A,ALPHA ;^EA MATCHES ALPHABETICS .WORD 'C,SYMCHR ;^EC MATCHES SYMBOL CHARACTERS .WORD 'D,NUMER ;^ED MATCHES NUMERICS .WORD 'L,TERMS ;^EL MATCHES TERMINATORS .WORD 'R,ALPHAN ;^ER MATCHES ALPHANUMERICS .WORD 'V,ALPHAL ;^EV MATCHES LOWER CASE ALPHAS .WORD 'W,ALPHAU ;^EW MATCHES UPPER CASE ALPHAS .WORD 100377,0 ;DUMMY TO TERMINATE THE LIST .SBTTL SIZING (SHUFFLING) ROUTINES .ENABL LSB SIZE: MOV R0,-(SP) ;SAVE R0 MOV (R4)+,R0 ;GET OFFSET TO MAX TO CHANGE TST R1 ;IS REQUEST AT ALL REASONABLE? BMI 80$ ;NOPE ['TST' => C=0 => FAILURE] MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ; AND SAVE R2 MOV R3,-(SP) ; AND SAVE R3 MOV R0,-(SP) ;SAVE THE MAX'S OFFSET VALUE ADD R5,R0 ;MAKE R0 ABS PTR TO MAX BIS #37,R1 ;FUDGE UP REQUEST A LITTLE SUB (R0),R1 ;FIND CHANGE AMOUNT BLO 60$ ;ALREADY DONE MOV #ZMAX,R2 ;GET TEXT AREA'S MAX OFFSET MOV ZZ(R5),R3 ; AND TEXT CURRENT INUSE SUB R2,(SP) ;0=>TEXT CHANGE; <>0=>Q-REG CHANGE BNE 10$ ;Q-REG CHANGE, WE HAVE TEXT MAX, INUSE MOV #QMAX,R2 ;TEXT CHANGE, GET Q-REG MAX OFFSET MOV QZ(R5),R3 ; AND Q-REG CURRENT INUSE 10$: JSR R4,50$ ;SEE IF CURRENT FREE DOES IT NEG R3 ;GET -(IN USE) ADD R5,R2 ;ABS PTR TO OTHER MAX ADD (R2),R3 ;FREE = MAX -(IN USE) SUB #400.,R3 ;FIND THE PUNISH AMOUNT BLOS 30$ ;NOT ENOUGH FREE TO PUNISH SUB R3,(R2) ;ELSE PUNISH THE OTHER MAX ADD R3,CURFRE(R5) ; AND UPDATE FREE SPACE TST (SP) ;WHICH AREA ARE WE CHANGING BEQ 20$ ;IF TEXT, THEN JUST PUNISHED QREGS MOV R0,-(SP) ;SAVE MAX POINTER MOV R1,-(SP) ;SAVE DELTA AMOUNT MOV QRSTOR(R5),R0 ;GET THE REGION'S BIAS SUB R3,QRSTOR(R5) ;CORRECT THE BASE ADDRESS CLR R2 ;START OF 0 OFFSET NEG R3 ;FIND -(PUNISH) MOV R3,R1 ; AND MOVE DATA TO THERE MOV QMAX(R5),R3 ;SET THE UPPER LIMIT JSR PC,SHRINK ;NOW SHRINK IT MOV (SP)+,R1 ;RESTORE DELTA AMOUNT MOV (SP)+,R0 ;RESTORE MAX POINTER 20$: JSR R4,50$ ;WILL FREE SPACE DO IT NOW? 30$: CMP R4,#100$ ;IS THIS THE SPECIAL CALL? BEQ 40$ ;YES, DON'T REALLY SIZE MOV R1,-(SP) ;SAVE FULL DELTA AMOUNT SUB CURFRE(R5),R1 ;NOW FIND AMOUNT WE NEED ADDED JSR PC,SIZER ;ASK WHOEVER FOR MORE PLEASE MOV (SP)+,R1 ;RESTORE FULL DELTA AMOUNT BCC 20$ ;WE GOT IT! TST (SP)+ ;DUMP THE AREA DETERMINATION BR 70$ ; AND EXIT (C=0 => FAILURE) 40$: MOV CURFRE(R5),R1 ;CHANGE REQUEST AMOUNT TO THIS BR 20$ ; AND TRY AGAIN (WON'T FAIL!) 50$: CMP R1,CURFRE(R5) ;DO WE HAVE ENOUGH FREE? BHI 90$ ;NO, SO RETURN SUB R1,CURFRE(R5) ;YES, CORRECT FREE COUNT MOV (SP)+,R4 ;RESTORE THE R4 VALUE ADD R1,(R0) ; AND CORRECT THE MAX TST (SP) ;WHICH AREA IS CHANGING? BNE 60$ ;QREGS, SO VERY EASY MOV QRSTOR(R5),R0 ;TEXT, SO GET OLD BEG PTR ADD R1,QRSTOR(R5) ;UPDATE QREG PTR MOV QMAX(R5),R3 ;GET MAX VALUE ADD R3,R1 ;FIND THE NEW MAX CLR R2 ;START MOVE AT OFFSET 0 JSR PC,EXPAND ;NOW GO DO THE EXPANSION 60$: COM (SP)+ ;DUMP AREA FLAG AND CARRY=1 70$: MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ; AND R2 MOV (SP)+,R1 ; AND R1 80$: MOV (SP)+,R0 ; AND R0 90$: RTS R4 ;FINALLY EXIT .YYY.C: CLR P(R5) ;.=0 CLR ZZ(R5) ;NO MORE TEXT .YYY.F: CLR FFFLAG(R5) ;NO MORE FORM FEED MOV #077777,R1 ;SET A VERY HIGH REQUEST VALUE SIZE TEXT ; AND SIZE UP TEXT 100$: RTS PC ;THIS ALWAYS WORKS!! .DSABL LSB SIZEQR: JSR R4,SIZE ;SIZE THE .WORD QMAX ; Q-REGISTER AREA RTS PC ;EXIT WITH C-BIT=1 FOR SUCCESS .SBTTL CHARACTER LIST FOR " COMMANDS .TABLE .CND,LAB,EQU,RAB,A,C,D,E,F,G,L,N,R,S,T,U,V,W .SBTTL CHARACTER LIST FOR E COMMANDS .TABLE .EEE,A,B,C,D,E,F,G,H,I,J,K,N,O,P,R,S,T,U,V,W,X,Y,UND .SBTTL CHARACTER LIST FOR F COMMANDS .TABLE .FFF,APS,LAB,RAB,B,C,N,R,S,UND,VBR .SBTTL COMMAND CHARACTER LIST .ODD .BYTE -1 .BYTE DEL .BYTE GRV .BYTE '? .BYTE '* .BYTE SPACE .BYTE 'W-100 .BYTE 'U-100 .BYTE LF .BYTE BS .BYTE BEL .TABLE .CMD .WORD .CMDBL .WORD .CMDBS .WORD .CMDLF .WORD .CMDCU .WORD .CMDCW .WORD .CMDSP .WORD .CMDST .WORD .CMDQU .WORD .CMDGV .WORD .CMDEL .SBTTL CHARACTER LIST FOR "SKPSET" .BYTE -1 .BYTE '_ .BYTE '^ .BYTE '] .BYTE '[ .BYTE 'X .BYTE 'U .BYTE 'S .BYTE 'Q .BYTE 'O .BYTE 'N .BYTE 'M .BYTE 'I .BYTE 'G .BYTE 'F .BYTE 'E .BYTE '@ .BYTE '> .BYTE '< .BYTE '% .BYTE '" .BYTE '! .BYTE '^-100 .BYTE 'U-100 .BYTE 'I-100 .BYTE 'A-100 .TABLE .CSM .WORD .CSMY ;CTRL/A SKIP QUOTED STRING USING CURRENT CHARACTER .WORD .CSMQ ;TAB SKIP QUOTED STRING .WORD .CSMRQ ;CTRL/U SKIP Q-REG NAME, QUOTED STRING .WORD .CSMX ;CTRL/^ SKIP ONE CHARACTER .WORD .CSMY ;! SKIP QUOTED STRING USING CURRENT CHARACTER .WORD .CSMDQ ;" INTO ONE MORE CONDITIONAL, SKIP ONE CHARACTER .WORD .CSMR ;% SKIP Q-REG NAME .WORD .CSMI ;< SIGNAL START OF AN ITERATION .WORD .CSMO ;> SIGNAL END OF AN ITERATION .WORD .CSMA ;@ SET THE SPECIAL QUOTED STRING FLAG .WORD .CSME ;E (EB, EG, EI, EN, ER, EW, E_) PROCESS "E" COMMANDS .WORD .CSMF ;F (FB, FC, FR, FS, FN, F_) PROCESS "F" COMMANDS .WORD .CSMR ;G SKIP Q-REG NAME .WORD .CSMQ ;I SKIP QUOTED STRING .WORD .CSMR ;M SKIP Q-REG NAME .WORD .CSMQ ;N SKIP QUOTED STRING .WORD .CSMQ ;O SKIP QUOTED STRING .WORD .CSMR ;Q SKIP Q-REG NAME .WORD .CSMQ ;S SKIP QUOTED STRING .WORD .CSMR ;U SKIP Q-REG NAME .WORD .CSMR ;X SKIP Q-REG NAME .WORD .CSMR ;[ SKIP Q-REG NAME .WORD .CSMR ;] SKIP Q-REG NAME .WORD .CSMUA ;^ RE-CHECK NEXT AS A CONTROL CHARACTER .WORD .CSMQ ;_ SKIP QUOTED STRING .BYTE -1 .BYTE '_ .BYTE 'W .BYTE 'R .BYTE 'N .BYTE 'I .BYTE 'G .BYTE 'B .TABLE .CSME .ODD .BYTE -1 .BYTE '_ .BYTE 'S .BYTE 'R .BYTE 'N .BYTE 'C .BYTE 'B .TABLE .CSMF .SBTTL GENERIC SEARCH MATCHING TABLE GENSRH: .BYTE 'A, 'A, 'A, 'A, 'A, 'A, 306, 'C .BYTE 'E, 'E, 'E, 'E, 'I, 'I, 'I, 'I .BYTE 320, 'N, 'O, 'O, 'O, 'O, 'O, 327 .BYTE 'O, 'U, 'U, 'U, 'U, 'Y, 336, 337 .SBTTL 8-BIT CHARACTER CONVERSION TABLE X = 100000 ;FLAG FOR HEX DIGIT PAIR .ENABL LC CNV8BT: .WORD "80!X, "81!X, "82!X, "83!X, "84!X, "85!X, "86!X, "87!X .WORD "88!X, "89!X, "8A!X, "8B!X, "8C!X, "8D!X, "8E!X, "8F!X .WORD "90!X, "91!X, "92!X, "93!X, "94!X, "95!X, "96!X, "97!X .WORD "98!X, "99!X, "9A!X, "9B!X, "9C!X, "9D!X, "9E!X, "9F!X .WORD "A0!X, "!!, "C/, "L-, "A4!X, "Y-, "A6!X, "S0 .WORD "X0, "C0, "a_, "<<, "AC!X, "AD!X, "AE!X, "AF!X .WORD "0^, "+-, "2^, "3^, "B4!X, "/U, "P!, ".^ .WORD "B8!X, "1^, "o_, ">>, "14, "12, "BE!X, "?? .WORD "A`, "A', "A^, "A~, "A", "A*, "AE, "C, .WORD "E`, "E', "E^, "E", "I`, "I', "I^, "I" .WORD "D0!X, "N~, "O`, "O', "O^, "O~, "O", "OE .WORD "O/, "U`, "U', "U^, "U", "Y", "DE!X, "ss .WORD "a`, "a', "a^, "a~, "a", "a*, "ae, "c, .WORD "e`, "e', "e^, "e", "i`, "i', "i^, "i" .WORD "F0!X, "n~, "o`, "o', "o^, "o~, "o", "oe .WORD "o/, "u`, "u', "u^, "u", "y", "FE!X, "FF!X .SBTTL FINAL FIXUPS... .PSECT TECOER .EVEN .END