Trailing-Edge
-
PDP-10 Archives
-
dec-10-omona-u-mc9
-
rsxt10.mac
There are 6 other files named rsxt10.mac in the archive. Click here to see a list.
;<2BELANGER>RSXT10.MAC.2, 10-Nov-76 11:52:58, EDIT BY BELANGER
SUBTTL INITIALIZATION AND RESTART
RSXFMT:
JFCL 0,0 ; NO-OP
SETZ 0,0 ; CLEAR ACS
MOVEI 17,1
BLT 17,17 ; ZAP!
RESET 0,0 ; CLEAR REST OF THE WORLD
SETZM 0,CLRBEG ; NOW CLEAR LOCAL VARIABLES
MOVE T1,[XWD CLRBEG,CLRBEG+1]
BLT T1,CLREND ; SO
OPEN TTYCH,TTYOPN ; OPEN THE TTY CHANNEL
JRST [OUTSTR [ASCIZ %
?? CAN'T OPEN TTY%]
EXIT 0,0]
INBUF TTYCH,0 ; SET UP THE BUFFERS
OUTBUF TTYCH,0 ; SO
GETPPN T1,0 ; READ OUR PPN
JFCL 0,0 ; GUARD AGAINST [1,2]
MOVEM T1,OURPPN ; STASH IT AWAY
MOVX T1,<XWD M$DEF,M$DEF>
MOVEM T1,MODE ; SET DEFAULT MODE
MOVEI T1,^D256 ; SET DEFAULT
MOVEM T1,RCDSIZ ; RECORD SIZE
MOVX F,F.ADDR ; DEFAULT TO ADDRESSES
CMDRST:
MOVE P,[IOWD PDLEN,PDL]
CLOSE CMDCH,0 ; CLOSE THE COMMAND CHANNEL
RELEASE CMDCH,0 ; AND RELEASE IT
CMDINI:
TXZE F,F.EXIT ; EXIT?
EXIT 0,0 ; YUP -- BYE...
MOVEI T2,[ASCIZ %RSXFMT>%]
TXNN F,F.CMND ; DON'T PROMPT IF COMMAND MODE
CALL TYPSTR ; PROMPT THE USER
CALL GETCMD ; GET THE COMMAND STRING
JUMPE P1,CMDINI ; JUMP IF NULL STRING
CMDNXT:
MOVEI P1,CMDTAB ; MAIN COMMAND TABLE POINTER TO P1
CONCMD:
CALL TABSCN ; SCAN THE TABLE
HRRZ P1,0(P1) ; GET THE DISPATCH
CALL 0(P1) ; DO IT TO IT
SKIPA 0,0 ; SEE IF WE MUST CONTINUE THIS COMMAND
JRST CONCMD ; CONTINUE THIS COMMAND
LDB C,CMDPTR ; LOOK AT THE LAST BYTE
JUMPE C,CMDINI ; DO ANOTHER COMMAND
JRST CMDNXT ; DO THE NEXT COMMAND
SUBTTL ERROR PROCESSING ROUTINES
; HERE ON "IGNORE"-ABLE ERROR, PREFIX MESSAGE POINTED TO BY P1 WITH "%"
CMDERI:
TXNN F,F.IGNR ; IGNORE THIS ERROR?
JRST CMDERR ; NO -- FATAL
CALL TYPTST ; SEE IF WE NEED A <CRLF>
MOVEI T2,[ASCIZ /% /]
CALL TYPSTR ; WARNING PREFIX
MOVE T2,P1 ; STRING POINTER
CALLR TYPSTC ; DO THE LINE AND EXIT
; HERE ON FATAL ERROR, PREFIX MESSAGE WITH "?" AND TYPE ERROR STRING
CMDERR:
CLOSE TTYCH,0 ; CLOSE THE TTY CHANNEL
OPEN TTYCH,TTYOPN ; RE-OPEN IT (FLUSH TYPE AHEAD)
JRST [OUTSTR [ASCIZ %? CAN'T REOPEN TTY%]
EXIT 0,0]
CALL TYPTST ; SEE IF WE NEED A <CRLF>
MOVEI T2,[ASCIZ %? %]
CALL TYPSTR ; PRINT IT
MOVE T2,P1 ; ERROR STRING
CALL TYPSTR ; PRINT THAT
TXZN F,F.CMND ; ARE WE IN COMMAND MODE?
JRST CMDER2 ; NO -- JUST GO ON
MOVEI T2,[ASCIZ %:
RSXFMT>%]
CALL TYPSTR ; TYPE A PROMPT
MOVEI T2,CMDBUF ; POINT TO THE COMMAND
CALL TYPSTR ; PRINT IT
CMDER2:
CALL TYPTST ; DO <CRLF> IF REQUIRED
CALLR CMDRST ; AND TRY AGAIN
SUBTTL $CONVE -- THE "CONVERT COMMAND
; HERE TO CONVERT A FILE FROM ONE FORMAT TO ANOTHER
; COMMAND IS
;
; CONVERT INPUT-FILE-SPEC OUTPUT-FILE-SPEC
;
; IF THE OUTPUT FILE-SPEC IS OMMITTED THE ORIGINAL FILE IS SUPERCEDED.
$CONVE:
TXZ F,F.TTEM ; CLEAR TEMP FLAG
JUMPE C,[ERR (<ILLEGAL FILE SPEC>)]
CONVEA:
MOVE P1,[XWD INOPN,INPLEB]
CALL GETFIL ; GET THE INPUT FILE SPEC
JUMPN C,CNVRTA ; JUMP IF WE HAVE A FULL FILE SPEC
MOVEI T2,[ASCIZ %OUTPUT FILE: %]
CALL TYPSTR ; PROMPT
CALL GETCMD ; READ THE FILE-SPEC
JUMPN P1,CNVRTA ; JUMP IF NOT DEFAULT
CONVEB:
MOVE T1,[XWD INPLEB,OUTLEB]
BLT T1,OUTOPN+1 ; COPY INPUT FILE SPEC TO OUTPUT FILE SPEC
JRST NXTFIL ; JUMP OVER THE CALL
CNVRTA:
MOVE P1,[XWD OUTOPN,OUTLEB]
CALL GETFIL ; GET THE OUTPUT FILE SPEC
; HERE TO DETERMINE THE INPUT FILE MODE
NXTFIL:
HLRZ IM,MODE ; GET THE MODE
CAIE IM,M$DEF ; DEFAULT?
JRST CNVRTC ; NO -- WE HAVE THE MODE ALREADY
CALL OPNINA ; YES -- OPEN THE FILE
LOOKUP INCH,INPLEB ; LOOK THE FILE UP
ERR <CAN'T FIND INPUT FILE>
CALL FILIN ; READ THE FIRST BYTE FROM THE FILE
ERR <PREMATURE END OF FILE>
CLOSE INCH,0 ; CLOSE THE INPUT FILE
RELEASE INCH,0 ; RELEASE IT
HLLZS 0,INPLEB+LE.EXT ; RESET THE LOOKUP BLOCK
MOVE T1,INPLEB+LE.PPS; FOR THE NEXT LOOKUP
MOVEM T1,INPLEB+LE.PPN
MOVEI T1,EXTTAB ; EXTENSION TABLE POINTER
HLLZS 0,INPLEB+LE.EXT ; FLUSH JUNK FORM EXTENSION
MOVN T4,0(T1) ; NEGATE THE LIST COUNT
HRLS 0,T4 ; SET THE COUNT
HRRI T4,1(T1) ; MAKE AN "AOBJN" POINTER
; HERE TO DETERMINE THE FILE MODE FROM THE EXTENSION
CNVRTB:
HLRZ T1,0(T4) ; GET THE POINTER TO THE EXTENSION
MOVE T1,0(T1) ; GET THE EXTENSION
CAME T1,INPLEB+LE.EXT
AOBJN T4,CNVRTB ; NO MATCH -- GO ON LOOKING
JUMPG T4,ASCFIL ; NO MATCH AT ALL -- ASSUME ASCII
HRRE IM,0(T4) ; MATCH -- GET THE MODE
JUMPL IM,ASCFL0 ; GO SET SPECIAL ASCII FLAGS
CAIE IM,M$RSB ; BINARY FILE?
JRST CNVRTC ; NO -- MODE IS SET UP
TLNN C,177776 ; YES -- DOS FORMAT?
MOVEI IM,M$DSB ; YES -- MARK IT
JRST CNVRTC ; AND EXIT
; HERE TO SET UP ASCII FILE MODES
ASCFL0:
HRLZS 0,IM ; ASCII FLAGS TO LH IM
TXZ IM,1B0 ; FLUSH THE SIGN BIT
TXNN F,F.IBCR!F.IPCR!F.LFSS
TDO F,IM ; SET THE MODE FLAGS FOR THIS FILE
ASCFIL:
MOVEI IM,M$RSA ; ASSUME RSX-ASCII
TXNE C,177B6 ; IS IT 7-BIT ASCII?
MOVEI IM,M$DSA ; YES -- MARK IT
; HERE TO SET UP THE OUTPUT FILE MODES
CNVRTC:
HRRZ OM,MODE ; SET THE OUTPUT MODE
CAIN OM,M$DEF ; DEFAULT?
HRRZ OM,MSGTAB(IM) ; NO -- SET THE MODE
CALL OPENIN ; OPEN THE INPUT FILE
CALL OPNOUT ; OPEN THE OUTPUT FILE
LOOKUP INCH,INPLEB ; FIND THE INPUT FILE
ERR <CAN'T FIND INPUT FILE>
ENTER OUTCH,OUTLEB ; FIND THE OUTPUT FILE
ERR <CAN'T ENTER OUTPUT FILE>
MOVE P1,[XWD INOPN,INPLEB]
MOVE P2,IM ; FILE TYPE OFFSET TO P2
CALL TYPFIL ; PRINT THE FILE DESCRIPTION
MOVEI T2,[ASCIZ % ==> %]
CALL TYPSTR
MOVE P1,[XWD OUTOPN,OUTLEB]
MOVE P2,OM ; FILE TYPE OFFSET TO P2
CALL TYPFIL ; PRINT THE FILE DESCRIPTION
SETZB IC,INADR ; RESET INPUT CHARACTER AND ADDRESS
SETZB OC,OUTADR ; RESET OUTPUT TOO
; HERE TO PROCESS THE FILE
CNVTLP:
CALL @GRCTAB(IM) ; GET AN INPUT RECORD BYTE COUNT
JRST DONE ; E-O-F RETURN
MOVE P1,C ; BYTE COUNT TO P1
CALL @PRCTAB(OM) ; WRITE IT
JUMPE P1,ENDRCD ; E-O-R -- CLEAN UP
; HERE TO COPY THE FILE, BYTE COUNT IN P1
COPYLP:
CALL @GBYTAB(IM) ; GET AN INPUT BYTE
ERRI <PREMATURE END-OF-FILE>,CRET
CALL @PBYTAB(OM) ; WRITE IT
SOJG P1,COPYLP ; DO ENTIRE RECORD
; HERE ON END OF RECORD
ENDRCD:
CALL @EORTAB(OM) ; FINISH OUTPUT RECORD
CALL @EIRTAB(IM) ; AND THE INPUT RECORD
JRST CNVTLP ; GET THE NEXT RECORD
; HERE TO FINISH THE FILE AND CLOSE IT
DONE:
SKIPGE C,OC ; SKIP IF CHARACTER ALREADY OUTPUT
CALL FILOUT ; PUT THE LAST BYTE INTO THE FILE
CALL OUTFIL ; FORCE THE FILE OUT
CLOSE INCH,0 ; CLOSE THE INPUT FILE
RELEASE INCH,0 ; RELEASE THE CHANNEL
CLOSE OUTCH,0 ; CLOSE THE OUTPUT FILE
RELEASE OUTCH,0 ; RELEASE THE CHANNEL
CALLR TYPCR ; TYPE A <CRNL> AND EXIT
SUBTTL $CRLF -- THE "CRLF" COMMAND
$CRLF:
SETZ P1,0 ; SET DEFAULT
JUMPE C,CRLFX ; EXIT NOW IF DEFAULT
CRLFA:
MOVEI P1,ASCTAB ; TABLE POINTER TO P1
CALL TABSCN ; SCAN THE TABLE
HRRZ P1,0(P1) ; GET THE FLAGS
CRLFX:
TXZ F,F.IBCR!F.IPCR!F.LFSS
TLO F,0(P1) ; SET NEW FLAGS
RETURN ; TO CALLER
; $EXIT -- THE "EXIT" COMMAND
$EXIT:
EXIT 1,0 ; EXIT
JRST RSXFMT ; RESTART
;$HELP -- THE "HELP" COMMAND
$HELP:
SETZM 0,INOPN ; ASCII MODE
MOVSI T1,'HLP' ; DEFAULT DEVICE
MOVEM T1,INOPN+1 ; SET IT
MOVE T1,[SIXBIT /RSXFMT/]
MOVEM T1,INPLEB ; FILE NAME
MOVSI T1,'HLP' ; EXTENSION
MOVEM T1,INPLEB+LE.EXT
OPEN INCH,INOPN ; OPEN THE CHANNEL
ERR <CAN'T OPEN HELP FILE>
LOOKUP INCH,INPLEB ; FIND THE FILE
ERR <CAN'T FIND HELP FILE>
HELPA:
SOSGE 0,INPBLK+2 ; COUNT THIS BYTE
JRST HLPMOR ; EMPTY BUFFER -- GET MORE
ILDB C,INPBLK+1 ; LOAD THE BYTE
JUMPE C,HELPEX ; DONE IF <NULL>
CALL TTYOUT ; OUTPUT IT
JRST HELPA ; AND GET ANOTHER
HLPMOR:
IN INCH,0 ; GET ANOTHER BUFFER
JRST HELPA ; GOT IT -- GO ON
STATO INCH,IO.EOF ; END-OF-FILE?
ERR <INPUT ERROR ON HELP FILE>
SKIPLE 0,INPBLK+2 ; ANYTHING IN THE BUFFER?
JRST HELPA ; YES -- CONTINUE
HELPEX:
CLOSE INCH,0 ; NO -- CLOSE THE FILE
RELEASE INCH,0 ; RELEASE THE CHANNEL
RETURN ; RETURN
SUBTTL $INFOR -- THE "INFORMATION" COMMAND
$INFOR:
MOVX P4,-1 ; TO PREVENT RECURSION IN "ALL"
JUMPE C,INFALL ; DEFAULT IS ALL
MOVEI P1,INFTAB ; TABLE POINTER TO P1
RETSKP ; SKIP RETURN
; INFORMATION ABOUT "ALL"
INFALL:
AOJN P4,CRET ; QUIT IF RECURSING
MOVSI P3,-INFSIZ ; POINTER TO ALL
INFAL1:
HRRZ T4,INFTAB+1(P3) ; GET A DISPATCH
CALL 0(T4) ; DO IT
AOBJN P3,INFAL1 ; TILL DONE
RETURN ; EXIT
; INFORMATION ABOUT "ADDRESS WORDS"
INFADR:
MOVX P1,F.ADDR ; FLAG TO P1
MOVEI P2,[ASCIZ % ADDRESS (WORDS EXIST IN IMAGE FILES)%]
CALLR INFNOC
; INFORMATION ABOUT "CRLF"
INFCR:
MOVEI T2,[ASCIZ % CRLF (IN ASCII FILES IS) %]
CALL TYPSTR
MOVEI T2,[ASCIZ %DEFAULT%]
TXNE F,F.IBCR
MOVEI T2,[ASCIZ %IMBEDDED%]
TXNE F,F.IPCR
MOVEI T2,[ASCIZ %IMPLIED%]
TXNE F,F.LFSS
MOVEI T2,[ASCIZ %CARRIAGE-RETURN-SINGLE-SPACE%]
CALLR TYPSTC
; INFORMATION ABOUT "IGNORE"
INFIGN:
MOVX P1,F.IGNR
MOVEI P2,[ASCIZ % IGNORE (FILE FORMAT ERRORS)%]
CALLR INFNOC
; INFORMATION ABOUT "MODE"
INFMOD:
MOVEI T2,[ASCIZ % MODE (OF INPUT) %]
CALL TYPSTR
HLRZ T2,MODE
HLRZ T2,MSGTAB(T2)
CALL TYPSTR
MOVEI T2,[ASCIZ % (AND OUTPUT) %]
CALL TYPSTR
HRRZ T2,MODE
HLRZ T2,MSGTAB(T2)
CALLR TYPSTC
; INFORMATION ABOUT "RECORD-SIZE"
INFRCD:
MOVEI T2,[ASCIZ % RECORD-SIZE (OF IMAGE FILES IS) %]
CALL TYPSTR
MOVE P1,RCDSIZ
CALL TYPDEC
CALLR TYPCR
; INFORMATION ABOUT "NO-THING"
INFNOC:
MOVEI T2,[ASCIZ % NO%]
TDNN F,P1
CALL TYPSTR
MOVE T2,P2
CALLR TYPSTC
SUBTTL $MODE -- THE "MODE" COMMAND
$MODE:
MOVEI P4,MSGTAB ; SO WE CAN COMPUTE OFFSET
PUSH P,MODE ; CURRENT MODE TO STACK
JUMPN C,MODEA ; CONTINUE PROCESSING
MOVEI P1,M$DEF ; DEFAULT
JRST MODEB ; SET IT
MODEA:
MOVEI P1,FMTTAB ; MODE TABLE POINTER TO P1
CALL TABSCN ; SCAN THE TABLE
SUB P1,P4 ; GET THE OFFSET
MODEB:
HRLM P1,0(P) ; SET THE INPUT MODE
MOVEI P1,M$DEF ; ASSUME DEFAULT
JUMPN C,MODEC ; DEFAULT?
JRST MODEX ; YES -- SET IT AND EXIT
MODEC:
MOVEI P1,FMTTAB ; MODE TABLE POINTER TO P1
CALL TABSCN ; SCAN IT
SUB P1,P4 ; GET THE OFFSET
MODEX:
HRRM P1,0(P) ; SET THE OUTPUT MODE
POP P,MODE ; SET THE NEW MODE WORD
RETURN ; AND EXIT
SUBTTL $NO -- THE "NO" COMMAND
; THE "NO" COMMAND
$NO:
TXC F,F.NO ; FLOP THE FLAG
MOVEI P1,NOCTAB ; "NO" OBJECT TABLE
RETSKP ; SKIP RETURN
; THE "IGNORE" COMMAND
$IGNOR:
MOVX P1,F.IGNR ; "IGNORE" FLAG TO P1
CALLR NOSETF ; SET / CLEAR AND EXIT
; THE "ADDRESS" COMMAND
$ADDRE:
MOVX P1,F.ADDR ; "ADDRESS" FLAG TO P1
CALLRX NOSETF ; SET / CLEAR AND EXIT
; HERE TO SET OR CLEAR THE FLAG BIT IN "F" FROM THAT IN "P1"
NOSETF:
TXZE F,F.NO ; DID HE SAY "NO"?
TDZA F,P1 ; YES -- CLEAR THE FLAG
TDO F,P1 ; NO -- SET THE FLAG
RETURN ; EXIT
; $RECOR -- THE RECORD SIZE COMMAND
; HERE TO GET THE FILE RECORD SIZE
$RECOR:
CALL GETDEC ; GET THE RECORD SIZE IN WORDS
MOVEM P1,RCDSIZ ; SET UP THE RECORD SIZE
RETURN ; AND EXIT
; $TAKE -- THE "TAKE" COMMAND
; HERE TO GET A FILE SPEC FOR A COMMAND FILE AND OPEN IT
$TAKE:
MOVE P1,[XWD CMDOPN,CMDLEB]
CALL GETFIL ; GET THE FILE SPEC
OPEN CMDCH,CMDOPN ; OPEN THE FILE
ERR <CAN'T OPEN COMMAND FILE>
LOOKUP CMDCH,CMDLEB ; LOOK THE FILE UP
ERR <CAN'T FIND COMMAND FILE>
TXO F,F.CMND ; OK -- MARK COMMAND MODE
RETURN ; AND GO PROCESS
SUBTTL TABSCN -- SYMBOL TABLE SCANNER SUBROUTINE
; THIS SUBROUTINE WILL SCAN THE TABLE POINTED TO BY "P1" IN THE CALL
; FOR A MATCH WITH THE SYMBOL CURRENTLY POINTED TO BY THE INPUT POINTER.
; THE DISPATCH FOR THE SYMBOL IS RETURNED IN "P1".
TABSCN:
PUSH P,P2 ; SAVE P2 ON THE STACK
PUSH P,P3 ; AND P3
SETZ P2,0 ; CLEAR IT
MOVN T1,0(P1) ; NEGATE THE TABLE LENGTH WORD
MOVEI P1,1(P1) ; GET OVER THE LENGTH WORD
HRL P1,T1 ; MAKE AN "AOBJN" POINTER FROM IT
TBSCNA:
SETZ T1,0 ; CLEAR THE MATCH COUNTER
HLRZ T4,0(P1) ; GET THE SYMBOL POINTER
HRLI T4,(POINT 7,) ; MAKE A BYTE POINTER FROM IT
MOVE T3,CMDPTR ; GET THE CURRENT COMMAND POINTER
TBSCNB:
ILDB C,T3 ; GET THE CHARACTER FROM INPUT
SKIPN 0,C ; END-OF-LINE?
MOVEI C," " ; YES -- FAKE A <SPACE>
ILDB T2,T4 ; AND THAT FROM SYMBOL
JUMPE T2,TBSCNC ; JUMP ON END OF SYMBOL
CAMN C,T2 ; DO THE CHARACTERS MATCH?
AOJA T1,TBSCNB ; YES -- GO ON
TBSCNC:
JUMPE T1,TBSCND ; JUMP IF NO MATCH
CAIE C," " ; LAST INPUT CHARACTER A <SPACE>?
JRST TBSCND ; NO -- NO MATCH
JUMPE T2,TBSCNE ; YES -- JUMP IF EXACT MATCH
MOVE T4,T1 ; CURRENT MATCH COUNT TO T4
HLRZ T2,P2 ; LAST MATCH COUNT TO T2
SUB T4,T2 ; DIFFERENCE TO T4
JUMPL T4,TBSCND ; NO MATCH IF .LT. 0
JUMPE T4,[ERR (<AMBIGUOUS SYMBOL>)]
HRLZ P2,T1 ; PARTIAL MATCH -- SAVE MATCH COUNT
HRR P2,P1 ; SAVE THE DISPATCH POINTER
MOVE P3,T3 ; SAVE THE BYTE POINTER
TBSCND:
AOBJN P1,TBSCNA ; LOOK AT THE NEXT SYMBOL
JUMPE P2,[ERR (<UKNOWN SYMBOL>)]
HRRZS 0,P2 ; FLUSH THE MATCH COUNT
MOVE T3,P3 ; BYTE POINTER TO T3
SKIPA P1,P2 ; PUT THE DISPATCH IN P1
TBSCNE:
HRRZS P1,P1 ; EXACT MATCH -- FLUSH WORD COUNT
MOVEM T3,CMDPTR ; SET UP THE NEW INPUT POINTER
LDB C,T3 ; READ THE LAST BYTE INTO "C"
POP P,P3 ; RESTORE P3
POP P,P2 ; RESTORE P2
RETURN
SUBTTL GETCMD -- COMMAND STRING INPUT ROUTINE
; HERE TO INPUT A COMMAND STRING. RETURNS WITH A POINTER TO THE
; COMMAND STRING IN "CMDPTR" AND THE BYTE COUNT IN P1.
GETCMD:
MOVE T1,[POINT 7, CMDBUF]
MOVEM T1,CMDPTR ; INIT BYTE POINTERS
MOVEI T2,<CMDSIZ*5> ; INIT THE BYTE COUNT
GTCMD1:
CALL TTYINP ; READ A CHARACTER
JRST GTCMDX ; BREAK CHARACTER -- GO PROCESS
CAIN C,.CHTAB ; IS THIS A <TAB>?
MOVEI C," " ; YES -- CONVERT TO <SPACE>
IDPB C,T1 ; PUT THE BYTE IN THE BUFFER
SOJG T2,GTCMD1 ; LOOP TILL EXHAUSTED
ERR <COMMAND BUFFER OVERFLOW>
GTCMDX:
CAIE C,.CHLFD ; LAST CHARACTER A <NEW-LINE>?
CALL TYPCR ; YES -- GIVE A FREE <CR-NL>
SETZ C,0 ; RENDER CHARACTER NULL
IDPB C,T1 ; NULL TERMINATOR TO BUFFER
MOVEI P1,<CMDSIZ*5> ; RETURN THE TRUE BYTE COUNT
SUB P1,T2 ; BYTE COUNT TO P1
RETURN ; TO CALLER
SUBTTL GETFIL -- FILE SPEC INPUT SUBROUTINE
; THIS SUBROUTINE WILL INPUT AND SET A COMPLETE FILE SPEC OF THE FORM:
;
; DEV:[PROJ,PROG]FILE.EXT
;
; THE DEFAULT FOR "DEV:" IS "DSK:", AND THE DEFAULT FOR [PROJ,PROG]
; IS "SELF". THE MINIMUM SPECIFICATION IS THE FILENAME.
; ENTER WITH LH P1 POINTING TO THE OPEN BLOCK AND RH P1 POINTING TO
; THE LOOKUP (ENTER) BLOCK. RETURNS WITH BOTH BLOCKS SET UP AND P1 INTACT.
GETFIL:
PUSH P,P4 ; SAVE P4
PUSH P,P3 ; AND P3
MOVS P4,P1 ; CALLER'S POINTER TO P4
SETZB C,1(P4) ; RESET THE DEVICE NAME
MOVSS 0,P4 ; SWAP THE POINTERS
SETZM 0,LE.NAM(P4) ; RESET THE LOOKUP / ENTER BLOCK
SETZM 0,LE.EXT(P4)
SETZM 0,LE.DAT(P4)
SETZM 0,LE.PPN(P4)
SETZM 0,LE.PPS(P4)
GTFILA:
MOVE P3,CMDPTR ; BYTE POINTER TO P3
ILDB C,CMDPTR ; READ A BYTE
JUMPE C,GTFILX ; EXIT IF <NULL>
CAIN C,"[" ; PPN?
JRST GTFILP ; YES -- GO PROCESS
MOVEM P3,CMDPTR ; NO -- RESTORE BYTE POINTER
CALL GETSIX ; LOOK FOR FILE OR DEVICE SPEC
JUMPE P1,[ERR (<NULL DEVICE OR FILENAME ILLEGAL>)]
CAIN C,":" ; END CHARACTER A <COLON>?
JRST GTFILD ; YES -- GO SET DEVICE
CAIN C,"." ; <PERIOD>?
JRST GTFILN ; YES -- SET THE FILE NAME
SKIPN 0,LE.EXT(P4) ; ALREADY HAVE AN EXTENSION?
SKIPN 0,LE.NAM(P4) ; NO -- MUST HAVE A NAME
ERR <FILE-SPEC SYNTAX ERROR>
TRNE P1,-1 ; 3 CHARACTERS?
ERR <ILLEGAL EXTENSION FORMAT>
MOVEM P1,LE.EXT(P4) ; YES -- SET THE EXTENSION
JRST GTFILB ; AND CONTINUE
GTFILD:
SKIPN 0,LE.PPN(P4) ; ALREADY HAVE A PPN?
SKIPE 0,LE.NAM(P4) ; OR A FILENAME?
ERR <FILE-SPEC SYNTAX ERROR>
MOVSS 0,P4 ; NO -- SWAP THE POINTERS
SKIPE 0,1(P4) ; ALREADY HAVE A DEVICE?
ERR <DOUBLE DEVICE SPECIFICATION ILLEGAL>
MOVEM P1,1(P4) ; NO -- SET UP THE DEVICE
MOVSS 0,P4 ; STRAIGHTEN OUT THE POINTER
GTFILB:
CAIE C," " ; DONE IF SPACE
JUMPN C,GTFILA ; GO LOOK FOR MORE
JRST GTFILX ; EXIT
GTFILN:
SKIPE 0,LE.NAM(P4) ; ALREADY HAVE A NAME?
ERR <DOUBLE FILENAME ILLEGAL>
SKIPE 0,LE.EXT(P4) ; OR AN EXTENSION?
ERR <FILE-SPEC SYNTAX ERROR>
MOVEM P1,LE.NAM(P4) ; NO -- SET THE NAME
JRST GTFILB ; AND GO GET THE REST OF THE FILE SPEC
GTFILP:
SKIPE 0,LE.NAM(P4) ; ALREADY HAVE A NAME?
ERR <FILE-SPEC SYNTAX ERROR>
SKIPE 0,LE.PPN(P4) ; ALREADY HAVE A PPN?
ERR <DOUBLE PPN ILLEGAL>
CALL GTOPPN ; NO -- READ THE PROJECT NUMBER
CAIN C,"," ; TERMINATOR OK?
TLNE P1,-1 ; IS IT LEGAL?
ERR <ILLEGAL PPN FORMAT>
MOVSS 0,P1 ; YES -- SWAP HALVES
PUSH P,P1 ; AND SAVE IT
CALL GTOPPN ; READ THE PROGRAMMER NUMBER
CAIN C,"]" ; TERMINATOR OK?
TLNE P1,-1 ; IN RANGE?
ERR <ILLEGAL PPN FORMAT>
IORM P1,0(P) ; YES -- BUILD COMPLETE PPN
POP P,LE.PPN(P4) ; SET IT UP
JRST GTFILB ; AND GO GET THE REST OF FILE SPEC
GTFILX:
CAIE C," " ; PROPER TERMINATOR?
SKIPN 0,C
SKIPN 0,LE.NAM(P4) ; YES -- HAVE AT LEAST A FILENAME?
ERR <ILLEGAL FILE SPEC>
MOVSS 0,P4 ; YES -- POINT TO THE OPEN BLOCK
MOVSI T1,'DSK' ; DEFAULT DEVICE NAME
SKIPN 0,1(P4) ; SPECIFY A DEVICE?
MOVEM T1,1(P4) ; NO -- SET THE DEFAULT DEVICE
MOVS P1,P4 ; RESTORE CALLER'S P1
SKIPE T1,LE.PPN(P1) ; DEFAULT PPN?
MOVEM T1,LE.PPS(P1) ; NO -- SAVE IT
POP P,P3 ; YES -- RESTORE P3
POP P,P4 ; RESTORE P4
RETURN ; TO CALLER
SUBTTL GETXXX -- INPUT PROCESSING SUBROUTINES
; HERE TO INPUT EITHER HALF OF A PPN.
GTOPPN:
TXO F,F.PPN ; SET THE FLAG
; HERE TO INPUT AN OCTAL NUMBER
GETOCT:
SKIPA T4,[EXP ^D8] ; SET THE RADIX TO OCTAL
; HERE TO INPUT A DECIMAL NUMBER
GETDEC:
MOVEI T4,^D10 ; SET THE RADIX TO DECIMAL
; HERE TO INPUT A NUMBER, RADIX IN "T4"
GETNUM:
SETZB T1,T2 ; CLEAR T1 AND T2
GTNUM1:
ILDB C,CMDPTR ; GET THE BYTE INTO "C"
JUMPE C,GTNUMX ; EXIT ON NULL
CAIN C," " ; DELIMITER?
JRST GTNUMX ; YES -- EXIT
CAIL C,"0" ; CHECK RANGE
CAILE C,"0"(T4) ; AGAINST RADIX
JRST GTNUME ; SEE IF REAL ERROR
ANDCMI C,"0" ; DE-ASCIIZE IT
MOVE T2,T1 ; ACCUMULATION TO T2
MUL T2,T4 ; MAKE ROOM FOR THIS DIGIT
MOVE T1,T3 ; PRODUCT TO T1
ADD T1,C ; INSERT THIS DIGIT
JRST GTNUM1 ; AND GO ON
GTNUME:
CAIE C,"," ; IS THE CHARACTER A <COMMA>?
CAIN C,"]" ; OR A <RIGHT BRACKET>?
TXZN F,F.PPN ; YES -- ARE WE LOOKING FOR A PPN?
ERR <INPUT IS NOT NUMERIC>
GTNUMX:
TXNE T2,<EXP -2> ; DID WE OVERFLOW
ERR <INPUT NUMBER TOO LARGE>
TXNE T2,1B35 ; DID WE OVERFLOW ONCE?
TXO T1,1B0 ; YES -- PUT IT BACK
MOVE P1,T1 ; SET RETURN
RETURN
SUBTTL GETSIX -- SIXBIT CONVERSION SUBROUTINE
; HERE TO CONVERT UP TO SIX ASCII CHARACTERS TO SIXBIT.
; SIXBIT STRING IS RETURNED IN P1. OK RETURN IS SKIP RETURN
; DIRECT RETURN INDICATES NULL STRING. THIS ROUTINE WILL STOP
; CONVERSION UPON ENCOUNTERING A SPACE, PERIOD OR COLON.
GETSIX:
MOVE T1,[POINT 6,P1] ; BYTE POINTER TO T1
MOVEI T4,^D6 ; SIX CHARACTERS MAX.
SETZ P1,0 ; CLEAR FOR RETURN
GTSIXA:
ILDB C,CMDPTR ; READ THE ASCII BYTE
JUMPE C,GTSIXE ; DONE IF <NULL>
CAIL C,"0" ; SEE IF NUMERIC
CAILE C,"9"
SKIPA 0,0 ; NOT NUMERIC -- TRY ALPHABETIC
JRST GTSIXB ; NUMERIC -- CONVERT IT
CAIL C,"A" ; SEE IF ALPHABETIC
CAILE C,"Z"
JRST GTSIXE ; NOT ALPHABETIC -- EXIT
GTSIXB:
SUBI C,40 ; CONVERT IT
IDPB C,T1 ; LOAD THIS BYTE
SOJG T4,GTSIXA ; LOOP TILL DONE
ILDB C,CMDPTR ; GET THE TERMINATOR BYTE
GTSIXE:
JUMPE P1,CRET ; DIRECT RETURN FOR NULL STRING
RETSKP ; OK SKIP RETURN
SUBTTL FILIN -- INPUT FILE HANDLER ROUTINES
; HERE TO OUTPUT ONE BLOCK OF THE FILE. AFTER THE OUTPUT IS DONE,
; IF THE BYTE SIZE OF THE FILE IS 18 BITS, THE BYTE SIZE IN THE
; BYTE POINTER IS HALVED AND THE BYTE COUNT IS DOUBLED.
FILIN:
SOSGE 0,INPBLK+2 ; COUNT THE BYTE OUT OF THE BUFFER
JRST INFIL ; EXHAUSTED -- GET ANOTHER
ILDB C,INPBLK+1 ; GET THE BYTE INTO "C"
RETSKP ; SKIP RETURN
INFIL:
IN INCH,0 ; GET A BUFFER FULL
JRST INFILX ; OK -- FIX POINTERS IF NEEDED
STATO INCH,IO.EOF ; END-OF-FILE?
ERR <INPUT FILE ERROR>
SKIPG 0,INPBLK+2 ; MORE IN BUFFER?
RETURN ; NO -- EXIT
INFILX:
PUSH P,T1 ; SAVE T1
HLRZ T1,BSZTAB(IM) ; BYTE SIZE TO T1
TXNN F,F.IBHM ; HEADER ALREADY MODIFIED?
CAIE T1,<^D18_^D12> ; NO -- IS IT .EQ. 18.?
JRST INFILY ; NO -- JUST EXIT
MOVE T1,INPBLK+1 ; YES -- GET MONITOR BYTE POINTER
TXZ T1,<77B11> ; FLUSH THE OLD SIZE FIELD
TXO T1,<^D18B11> ; SET IT TO 18 BITS
MOVEM T1,INPBLK+1 ; IN THE BUFFER HEADER
MOVE T1,INPBLK+2 ; GET THE BYTE COUNT
ADDM T1,INPBLK+2 ; DOUBLE IT
TXO F,F.IBHM ; FLAG THE MODIFICATION
INFILY:
POP P,T1 ; RESTORE T1
JRST FILIN ; AND TRY AGAIN
; HERE TO OPEN THE INPUT FILE. IF THE FILE IS AN ASCII FILE, IT IS
; OPENED IN ASCII MODE, OTHERWISE IT IS OPENED IN IMAGE MODE.
OPENIN:
TXZ F,F.IBHM ; RESET THE HEADER MODIFICATION FLAG
HLRZ T1,BSZTAB(IM) ; INPUT BYTE SIZE TO T1
CAIE T1,<^D7_^D12> ; IS IT AN ASCII FILE?
OPNINA:
SKIPA T1,[EXP .IOIMG] ; NO -- OPEN IN IMAGE MODE
SETZ T1,0 ; YES -- OPEN IT IN ASCII MODE
MOVEM T1,INOPN ; SET THE MODE IN THE OPEN BLOCK
OPEN INCH,INOPN ; OPEN THE CHANNEL
ERR <CAN'T OPEN INPUT FILE>
RETURN ; EXIT
SUBTTL FILOUT -- OUTPUT FILE HANDLER ROUTINES
; HERE TO INPUT ONE BLOCK OF THE FILE. AFTER THE INPUT IS DONE,
; IF THE BYTE SIZE OF THE FILE IS 18 BITS, THE BYTE SIZE IN THE
; BYTE POINTER IS HALVED AND THE BYTE COUNT IS DOUBLED.
FILOUT:
SOSG 0,OUTBLK+2 ; COUNT THIS BYTE
CALL OUTFIL ; EXHAUSTED -- GET ANOTHER
IDPB C,OUTBLK+1 ; PUT THE BYTE IN THE BUFFER
RETURN ; EXIT
OUTFIL:
OUT OUTCH,0 ; OUTPUT THIS BUFFER
SKIPA 0,0 ; SKIP OVER THE ERROR
ERR <OUTPUT FILE ERROR>
PUSH P,T1 ; SAVE T1
HLRZ T1,BSZTAB(OM) ; GET THE FILE BYTE SIZE
TXNN F,F.OBHM ; HEADER ALREADY MODIFIED?
CAIE T1,<^D18_^D12> ; NO -- BYTE SIZE .EQ. 18?
JRST OUTFLX ; YES -- JUST EXIT
MOVE T1,OUTBLK+1 ; YES -- GET MONITOR BYTE POINTER
TXZ T1,<77B11> ; FLUSH THE OLD SIZE FIELD
TXO T1,<^D18B11> ; SET IT TO 18 BITS
MOVEM T1,OUTBLK+1 ; IN THE BUFFER HEADER
MOVE T1,OUTBLK+2 ; NOW THE BYTE COUNT
ADDM T1,OUTBLK+2 ; DOUBLE IT
TXO F,F.OBHM ; FLAG THE MODIFICATION
OUTFLX:
POP P,T1 ; RESTORE T1
RETURN ; AND EXIT
; HERE TO OPEN THE OUTPUT FILE. IF THE FILE IS AN ASCII FILE, IT IS
; OPENED IN ASCII MODE, OTHERWISE IT IS OPENED IN IMAGE MODE.
OPNOUT:
TXZ F,F.OBHM ; RESET THE MODIFICATION FLAG
HLRZ T1,BSZTAB(OM) ; BYTE SIZE TO T1
CAIE T1,<^D7_^D12> ; IS IT AN ASCII FILE?
SKIPA T1,[EXP .IOIMG] ; NO -- OPEN IN IMAGE MODE
SETZ T1,0 ; YES -- OPEN IT IN ASCII MODE
MOVEM T1,OUTOPN ; SET THE MODE IN THE OPEN BLOCK
OPEN OUTCH,OUTOPN ; OPEN THE CHANNEL
ERR <CAN'T OPEN OUTPUT FILE>
RETURN ; EXIT
SUBTTL TTYINP -- TELETYPE INPUT SUBROUTINE
; HERE TO READ THE CURRENT INPUT DEVICE
TTYINP:
TXNE F,F.CMND ; "TAKE" COMMAND?
JRST CMDINP ; YES -- LOOK AT COMMAND DEVICE
SOSGE 0,TTIBLK+2 ; COUNT THE BYTE FROM THE BUFFER
JRST TTYBFR ; EXHAUSTED, GET ANOTHER
ILDB C,TTIBLK+1 ; GET THE BYTE OUT OF THE BUFFER
TTINPA:
CAIE C,0 ; IS THIS A <NULL>?
CAIN C,.CHDEL ; OR A <RUBOUT>?
JRST TTYINP ; YES -- IGNORE EITHER
CAIN C,.CHCNZ ; E-O-F CHARACTER?
JRST [TXO F,F.EXIT
JRST CRET]
CAIL C,.CHALT ; NO -- SOME FLAVOR OF <ALT-MODE>?
MOVEI C,.CHESC ; YES -- CONVERT TO THIS FLAVOR
CAIL C,140 ; NO -- LOWER CASE?
ANDCMI C,40 ; YES -- MAKE IT UPPER CASE
CAIN C,.CHCRT ; NO -- <CARRIAGE-RETURN>?
JRST TTYINP ; YES -- IGNORE IT
CAIG C,.CHCRT ; SOME KIND OF VERTICAL FORMAT?
CAIGE C,.CHLFD ; BETWEEN <CR> AND <NEW-LINE>?
CAIN C,.CHESC ; OR <ALT-MODE>?
RETURN ; YES -- DIRECT RETURN
RETSKP ; NO -- SKIP RETURN
; HERE TO GET ANOTHER BUFFER
TTYBFR:
IN TTYCH,0 ; GET ANOTHER BUFFER
JRST TTYINP ; GOT IT -- CONTINUE
STATO TTYCH,IO.EOF ; DIDN'T GET IT -- EOF?
JRST [OUTSTR [ASCIZ %
? ERROR ON TTY INPUT%]
EXIT 0,0]
TXO F,F.EXIT ; SET THE EXIT FLAG
SKIPLE 0,TTIBLK+2 ; ANYTHING IN THE BUFFER?
JRST TTYINP ; YES -- GO GET IT
RETURN ; NO -- EXIT
SUBTTL CMDINP -- COMMAND FILE INPUT SUBROUTINE
; HERE TO READ THE CURRENT COMMAND FILE
CMDINP:
SOSGE 0,CMDBLK+2 ; COUNT THIS BYTE
JRST CMDBFR ; NO MORE -- GET ANOTHER BUFFER
ILDB C,CMDBLK+1 ; READ THE BYTE INTO "C"
JRST TTINPA ; AND GO PROCESS IT
; HERE TO GET ANOTHER BUFFER
CMDBFR:
IN CMDCH,0 ; READ THE NEW BUFFER
JRST CMDINP ; OK -- GO ON
STATO CMDCH,IO.EOF ; END-OF-FILE?
ERR <ERROR ON COMMAND FILE INPUT>
SKIPLE 0,CMDBLK+2 ; ANYTHING IN THE BUFFER?
JRST CMDINP ; YES -- GO GET IT
TXZ F,F.CMND ; NO -- CLEAR THE COMMAND FLAG
CLOSE CMDCH,0 ; CLOSE THE FILE
RELEASE CMDCH,0 ; RELEASE THE CHANNEL
RETURN ; AND EXIT
SUBTTL TYPFIL -- TYPE A FILE DESCRIPTION
; THIS SUBROUTINE WILL TYPE A FILE DESCRIPTION.
; P1 POINTS TO THE LOOKUP / ENTER BLOCK, AND P2 CONTAINS AN OFFSET INTO
; THE FILE FORMAT TABLE
TYPFIL:
MOVSS 0,P1 ; SWAP THE POINTER
HRLZI T1,'DSK' ; DEFAULT DEVICE NAME
CAMN T1,1(P1) ; IS IT DEFAULT?
JRST TYPFLA ; YES -- GO ON
MOVE T1,1(P1) ; NO -- GET THE STRUCTURE NAME
CALL SIXTYP ; AND TYPE IT
MOVEI T2,[ASCIZ %:%]
CALL TYPSTR
TYPFLA:
MOVSS 0,P1 ; SWAP THE POINTER AGAIN
MOVE T1,LE.PPS(P1) ; GET THE PPN
JUMPE T1,TYPFLB ; JUMP IF DEFAULT
CAMN T1,OURPPN ; ARE THEY THE SAME?
JRST TYPFLB ; YES -- GO ON
PUSH P,P1 ; SAVE OUR POINTER
HRRZS 0,T1 ; GET THE LOW HALF OF THE PPN
PUSH P,T1 ; SAVE THAT
HLRZ P1,LE.PPS(P1) ; GET THE HIGH HALF OF PPN
MOVEI T2,[ASCIZ %[%]
CALL TYPSTR ; PRINT BRACKET
CALL TYPOCT ; TYPE IT
MOVEI T2,[ASCIZ %,%]
CALL TYPSTR
POP P,P1 ; GET THE LOW HALF
CALL TYPOCT ; PRINT IT
MOVEI T2,[ASCIZ %]%]
CALL TYPSTR ; PRINT BRACKET
POP P,P1 ; RESTORE OUR POINTER
TYPFLB:
MOVE T1,LE.NAM(P1) ; GET THE SIXBIT NAME
CALL SIXTYP ; PRINT IT
MOVEI T2,[ASCIZ %.%] ; NAME DELIMITER
CALL TYPSTR ; TYPE THAT
HLLZ T1,LE.EXT(P1) ; GET THE EXTENSION
CALL SIXTYP ; TYPE THAT
MOVEI T2,[ASCIZ % [%]
CALL TYPSTR ; SET UP FOR FILE TYPE
HLRZ T2,MSGTAB(P2) ; GET THE FILE TYPE
CALL TYPSTR ; PRINT IT
MOVEI T2,[ASCIZ %]%]
CALLR TYPSTR ; FINISH DESCRIPTION AND EXIT
SUBTTL TYPSTR -- OUTPUT A STRING
; HERE TO SEE IF WE MUST PREFIX THE LINE WITH A <CRLF>
TYPTST:
SKIPE 0,TTOCCT ; ARE WE AT THE BEGINNING OF THE LINE?
CALLR TYPCR ; NO -- GET US THERE
RETURN ; YES -- GO AWAY
; HERE TO OUTPUT AN ASCIZ STRING AND APPEND A <CRLF>
TYPSTC:
CALL TYPSTR ; TYPE THE STRING
CALLRX TYPCR ; AND THE <CRLF>
; HERE TO OUTPUT A <CRLF>
TYPCR:
PUSH P,T2 ; SAVE T2
MOVEI T2,[ASCIZ %
%]
CALL TYPSTR ; END THE LINE
POP P,T2 ; RESTORE T2
RETURN ; TO CALLER
; HERE TO OUTPUT THE SIXBIT STRING IN T1
SIXTYP:
MOVE T2,[POINT 6,T1] ; BYTE POINTER TO T2
MOVEI T3,^D6 ; SIX BYTES, MAX
SIXTYA:
ILDB C,T2 ; GET THE BYTE
JUMPE C,SIXTYX ; EXIT IF NULL
ADDI C,40 ; MAKE IT ASCII
CALL TTYOUT ; PUT IT IN THE BUFFER
SOJN T3,SIXTYA ; LOOP TILL DONE
SIXTYX:
CALLR TTOBFR ; OUTPUT AND RETURN
; HERE TO OUTPUT THE DECIMAL NUMBER IN P1
TYPDEC:
SKIPA T4,[EXP ^D10]
;HERE TO OUTPUT THE OCTAL NUMBER IN P1
TYPOCT:
MOVEI T4,^D8
; HERE TO OUTPUT THE NUMBER IN P1, RADIX IN T4
TYPNUM:
MOVE T1,P1 ; NUMBER TO T1
TYPNMA:
IDIV T1,T4 ; DIVIDE IT
HRLM T2,0(P) ; SAVE IT ON THE STACK
SKIPE 0,T1 ; DONE?
CALL TYPNMA ; NO -- GO ON
TYPNMB:
HLRZ C,0(P) ; GET THE NUMBER OFF THE STACK
ADDI C,"0" ; ASCIIIZE IT
CALLR TTYOUT ; OUTPUT IT AND RETURN
; HERE TO OUTPUT AN ASCIZ STRING WITH POINTER TO STRING IN RH OF T2.
; T2 IS CLOBBERED ON EXIT.
TYPSTR:
HRLI T2,(POINT 7,) ; MAKE A BYTE POINTER
TYPSTL:
ILDB C,T2 ; PUT THE BYTE INTO "C"
JUMPE C,TTOBFR ; DUMP THE BUFFER ON DELIMITER
AOS 0,TTOCCT ; COUNT THIS CHARACTER
CALL TTYOUT ; PUT THIS BYTE INTO THE BUFFER
JRST TYPSTL ; AND GO GET ANOTHER
; HERE TO PUT THE BYTE IN AC "C" INTO THE BUFFER AND OUTPUT IF THE
; BUFFER IS FULL OR THE BYTE IS A <NEW-LINE> CHARACTER.
TTYOUT:
SOSG 0,TTOBLK+2 ; DO WE HAVE ROOM FOR THE BYTE?
CALL TTOBFR ; NO -- DUMP THIS BUFFER
IDPB C,TTOBLK+1 ; YES -- PUT IT INTO THE BUFFER
CAIGE C,.CHCRT ; IS THIS A <CARRIAGE-RETURN>?
CAIGE C,.CHLFD ; NO -- VERTICAL FORMAT?
RETURN ; NO -- JUST GO AWAY
; HERE TO OUTPUT THE BUFFER
TTOBFR:
OUT TTYCH,0 ; OUTPUT IT
SKIPA 0,0 ; SKIP OVER THE ERROR
JRST [OUTSTR [ASCIZ %
? ERROR ON TTY OUTPUT%]
EXIT 0,0]
CAIN C,.CHLFD ; IS THIS A REAL E-O-L?
SETZM 0,TTOCCT ; YES -- RESET THE CHARACTER COUNT
RETURN ; NO -- GO ON