mirror of
https://github.com/PDP-10/its.git
synced 2026-02-04 15:53:01 +00:00
Added support for RMTDEV
This commit is contained in:
committed by
Lars Brinkhoff
parent
6a76142071
commit
800803e9c4
2096
src/gz/rmtdev.59
Normal file
2096
src/gz/rmtdev.59
Normal file
File diff suppressed because it is too large
Load Diff
679
src/midas/macsym.14
Normal file
679
src/midas/macsym.14
Normal file
@@ -0,0 +1,679 @@
|
||||
;;The official source for this file is MIDAS;MACSYM >
|
||||
;;Midas versions of some MACSYM.MAC macros, by GZ@MC.
|
||||
;;(Also some useful macros/symbols no supported by MACSYM.MAC)
|
||||
|
||||
;Stuff supported (will add more stuff as need arises):
|
||||
; PGVER. VMAJ,VMIN,VEDIT,VWHO and related masks(VI%MAJ,VI%MIN,VI%EDN,VI%WHO)
|
||||
; Random symbols (.INFIN,.MINFI,.LHALF,.RHALF,.FWORD, .CHxxx,
|
||||
; ASCPTR, USRLH, PSLH, .PRxxx)
|
||||
; FLD(VAL,MSK) & BIT(n) & POINT SIZE,ADDR,OFFSET & ERNOP & ERSKP
|
||||
; MOVX AC,MASK & TXxx AC,MASK & JXx AC,MASK,ADDR & LOAD/STOR AC,MASK,ADDR
|
||||
; DO./ENDDO. macros (and related stuff)
|
||||
; IFxxx/ANxxx macros
|
||||
; TMSG /text/, FMSG /text/, EMSG /text/
|
||||
; SAVEACS [A,B,C,D] & SAVE. [LOC,LOC,LOC]
|
||||
; FLDDB.(FUNC,FLAGS,DATA,"Help","Default",NEXT)
|
||||
; FLDBK.(FUNC,FLAGS,DATA,"Help","Default",BRKMASK,NEXT)
|
||||
; BRMSK.(INI0,INI1,INI2,INI3,[ALLOW],[DISALLOW])
|
||||
IFNDEF $$JSER,$$JSER==0 ; Conditional on $$JSER:
|
||||
; PERSTR /optional msg/
|
||||
; ERMSG /text/
|
||||
; JSERR/EJSERR/JSHLT/EJSHLT
|
||||
; and support code for above.
|
||||
IFNDEF $$STK,$$STK==0 ; Conditional on $$STK:
|
||||
; CALL/RET/RETSKP/CALLRET
|
||||
; STKVAR [AA,[QQ,5],ZZ]/ENDSV.
|
||||
; labels RSKP and R
|
||||
; and support code for above.
|
||||
|
||||
|
||||
.KILL ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3,TOP.
|
||||
.XCREF ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3
|
||||
.XCREF ..DX,..IX,..EX,.SAVX1,.SAVX2,..BRK
|
||||
|
||||
IF2,IFE $$STK\$$JSER,.INEOF ;Don't bother if no code
|
||||
|
||||
;.NSTGW ;No storage words in this part
|
||||
|
||||
DEFINE PGVER. (VMAJ,VMIN,VEDIT,VWHO)
|
||||
..XX==.
|
||||
LOC 137
|
||||
.JBVER: .BYTE 3.,9.,6.,18.
|
||||
VWHO
|
||||
VMAJ
|
||||
VMIN
|
||||
VEDIT
|
||||
.BYTE
|
||||
LOC ..XX
|
||||
TERMIN
|
||||
|
||||
;MASKS FOR THE ABOVE
|
||||
|
||||
VI%WHO==:700000,,000000 ;Customer edit code
|
||||
VI%MAJ==:077700,,000000 ;Major version number
|
||||
VI%MIN==:000077,,000000 ;Minor version/update
|
||||
VI%EDN==:000000,,777777 ;Edit number
|
||||
|
||||
;MISC CONSTANTS
|
||||
|
||||
.INFIN==:377777,,777777 ;PLUS INFINITY
|
||||
.MINFI==:400000,,000000 ;MINUS INFINITY
|
||||
.LHALF==:-1,,0 ;LEFT HALF
|
||||
.RHALF==:0,,-1 ;RIGHT HALF
|
||||
.FWORD==:-1 ;FULL WORD
|
||||
ASCPTR==:440700,,0
|
||||
USERLH==:500000
|
||||
PSLH==:540000
|
||||
|
||||
;MIT EXEC PRARG command codes
|
||||
.PRCCL==0 ;redo last CCL command
|
||||
.PRKEP==1 ;keep fork, and halt it
|
||||
.PRKIL==2 ;kill fork
|
||||
.PRBKG==3 ;continue fork in background
|
||||
|
||||
|
||||
;SYMBOLS FOR THE CONTROL CHARACTERS
|
||||
|
||||
.CHNUL==:000 ;NULL
|
||||
.CHCNA==:001
|
||||
.CHCNB==:002
|
||||
.CHCNC==:003
|
||||
.CHCND==:004
|
||||
.CHCNE==:005
|
||||
.CHCNF==:006
|
||||
.CHBEL==:007 ;BELL
|
||||
.CHBSP==:010 ;BACKSPACE
|
||||
.CHTAB==:011 ;TAB
|
||||
.CHLFD==:012 ;LINE-FEED
|
||||
.CHVTB==:013 ;VERTICAL TAB
|
||||
.CHFFD==:014 ;FORM FEED
|
||||
.CHCRT==:015 ;CARRIAGE RETURN
|
||||
.CHCNN==:016
|
||||
.CHCNO==:017
|
||||
.CHCNP==:020
|
||||
.CHCNQ==:021
|
||||
.CHCNR==:022
|
||||
.CHCNS==:023
|
||||
.CHCNT==:024
|
||||
.CHCNU==:025
|
||||
.CHCNV==:026
|
||||
.CHCNW==:027
|
||||
.CHCNX==:030
|
||||
.CHCNY==:031
|
||||
.CHCNZ==:032
|
||||
.CHESC==:033 ;ESCAPE
|
||||
.CHCBS==:034 ;CONTROL BACK SLASH
|
||||
.CHCRB==:035 ;CONTROL RIGHT BRACKET
|
||||
.CHCCF==:036 ;CONTROL CIRCUMFLEX
|
||||
.CHCUN==:037 ;CONTROL UNDERLINE
|
||||
.CHSPC==:040 ;SPACE
|
||||
|
||||
.CHALT==:175 ;OLD ALTMODE
|
||||
.CHAL2==:176 ;ALTERNATE OLD ALTMODE
|
||||
.CHDEL==:177 ;DELETE
|
||||
|
||||
;PC FLAGS
|
||||
|
||||
PC%OVF==:400000,,0 ;OVERFLOW
|
||||
PC%CY0==:200000,,0 ;CARRY 0
|
||||
PC%CY1==:100000,,0 ;CARRY 1
|
||||
PC%FOV==:040000,,0 ;FLOATING OVERFLOW
|
||||
PC%BIS==:020000,,0 ;BYTE INCREMENT SUPPRESSION
|
||||
PC%USR==:010000,,0 ;USER MODE
|
||||
PC%UIO==:004000,,0 ;USER IOT MODE
|
||||
PC%LIP==:002000,,0 ;LAST INSTRUCTION PUBLIC
|
||||
PC%AFI==:001000,,0 ;ADDRESS FAILURE INHIBIT
|
||||
PC%ATN==:000600,,0 ;APR TRAP NUMBER
|
||||
PC%FUF==:000100,,0 ;FLOATING UNDERFLOW
|
||||
PC%NDV==:000040,,0 ;NO DIVIDE
|
||||
|
||||
|
||||
DEFINE FLD (VAL,MASK)
|
||||
<.DPB <VAL>,<.BP <MASK>,>,0>TERMIN
|
||||
|
||||
DEFINE BIT (N)
|
||||
<1_<35.-<N>>>TERMIN
|
||||
|
||||
DEFINE POINT SIZE=7,ADDR=0,COUNT=0
|
||||
RADIX 8+2
|
||||
..X1==SIZE
|
||||
..X2==COUNT
|
||||
RADIX 8
|
||||
..XX==<..X2-1>/<36./..X1>
|
||||
..X2==..X2-..XX*<36./..X1>
|
||||
<<<36.-<..X1*..X2>>_30.>+<..X1_24.>+<ADDR>+..X1>
|
||||
TERMIN
|
||||
|
||||
DEFINE ERNOP
|
||||
ERJMP .+1
|
||||
TERMIN
|
||||
|
||||
DEFINE ERSKP
|
||||
ERJMP .+2
|
||||
TERMIN
|
||||
|
||||
ABSKP==:TRNA
|
||||
|
||||
;MOVX - LOAD AC WITH CONSTANT
|
||||
|
||||
DEFINE MOVX AC,#MSK
|
||||
IFE <-1,,0>&MSK,[MOVEI AC,MSK]
|
||||
.ELSE [IFE <0,,-1>&MSK,[MOVSI AC,(MSK)]
|
||||
.ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[HRROI AC,MSK]
|
||||
.ELSE [IFE <<0,,-1>&MSK>-<0,,-1>,[HRLOI AC,(MSK&.LHALF)]
|
||||
.ELSE [MOVE AC,[MSK]]]]]
|
||||
TERMIN
|
||||
|
||||
;TX - TEST MASK
|
||||
|
||||
IRP OP,,[N,NA,OE,ON,OA,ZE,ZN,ZA,CE,CN,CA]
|
||||
DEFINE TX!OP AC,#MSK
|
||||
IFE <-1,,0>&MSK,[TR!OP AC,MSK]
|
||||
.ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)]
|
||||
.ELSE [TD!OP AC,[MSK]]]
|
||||
TERMIN
|
||||
TERMIN
|
||||
|
||||
IRP OP,,[N,E]
|
||||
DEFINE TXN!OP AC,#MSK
|
||||
IFE <-1,,0>&MSK,[TRN!OP AC,MSK]
|
||||
.ELSE [IFE <0,,-1>&MSK,[TLN!OP AC,(MSK)]
|
||||
.ELSE [IFE MSK+1,[CAI!OP AC,0]
|
||||
.ELSE [TDN!OP AC,[MSK]]]]
|
||||
TERMIN
|
||||
TERMIN
|
||||
|
||||
..TXZ==ANDI
|
||||
..TXO==ORCMI
|
||||
..TXC==EQVI
|
||||
IRP OP,,[Z,O,C]
|
||||
DEFINE TX!OP AC,#MSK
|
||||
IFE <-1,,0>&MSK,[TR!OP AC,MSK]
|
||||
.ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)]
|
||||
.ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[..TX!OP AC,-1#MSK]
|
||||
.ELSE [TD!OP AC,[MSK]]]]
|
||||
TERMIN
|
||||
TERMIN
|
||||
|
||||
EQUALS IORX,TXO
|
||||
EQUALS XORX,TXC
|
||||
|
||||
DEFINE ANDX AC,#MSK
|
||||
TXZ AC,-1#MSK
|
||||
TERMIN
|
||||
|
||||
SUBTTL JX -- JUMP ON MASK
|
||||
|
||||
;JXE -- JUMP IF MASKED BITS ARE EQUAL TO 0
|
||||
;JXN -- JUMP IF MASKED BITS ARE NOT EQUAL TO 0
|
||||
;JXO -- JUMP IF MASKED BITS ARE ALL ONES
|
||||
;JXF -- JUMP IF MASKED BITS ARE NOT ALL ONES (FALSE)
|
||||
|
||||
DEFINE JXE AC,#MSK,?ADR
|
||||
IFE MSK-.MINFI,[JUMPGE AC,ADR]
|
||||
.ELSE [IFE MSK+1,[JUMPE AC,ADR]
|
||||
.ELSE [TXNN AC,MSK
|
||||
JRST ADR]]
|
||||
TERMIN
|
||||
|
||||
DEFINE JXN AC,#MSK,?ADR
|
||||
IFE MSK-.MINFI,[JUMPL AC,ADR]
|
||||
.ELSE [IFE MSK+1,[JUMPN AC,ADR]
|
||||
.ELSE [TXNE AC,MSK
|
||||
JRST ADR]]
|
||||
TERMIN
|
||||
|
||||
DEFINE JXO AC,#MSK,?ADR
|
||||
IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXN AC,MSK,ADR]
|
||||
.ELSE [TXC AC,MSK
|
||||
TXCN AC,MSK
|
||||
JRST ADR]
|
||||
TERMIN
|
||||
|
||||
DEFINE JXF AC,#MSK,?ADR
|
||||
IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXE AC,MSK,ADR]
|
||||
.ELSE [TXC AC,MSK
|
||||
TXCE AC,MSK
|
||||
JRST ADR]
|
||||
TERMIN
|
||||
|
||||
;LOAD, STOR
|
||||
DEFINE LOAD AC,#MSK,?LOCN
|
||||
IFE MSK+1,[MOVE AC,LOCN]
|
||||
.ELSE [IFE MSK-777777,[HRRZ AC,LOCN]
|
||||
.ELSE [IFE MSK-<-1,,0>,[HLRZ AC,LOCN]
|
||||
.ELSE [LDB AC,[.BP MSK,LOCN]]]]
|
||||
TERMIN
|
||||
|
||||
DEFINE STOR AC,#MSK,?LOCN
|
||||
IFE MSK+1,[MOVEM AC,LOCN]
|
||||
.ELSE [IFE MSK-777777,[HRRM AC,LOCN]
|
||||
.ELSE [IFE MSK-<-1,,0>,[HRLM AC,LOCN]
|
||||
.ELSE [DPB AC,[.BP MSK,LOCN]]]]
|
||||
TERMIN
|
||||
|
||||
SUBTTL BLOCK MACROS
|
||||
|
||||
;MACROS TO PROVIDE SOME BLOCK HANDLING OF CODE
|
||||
|
||||
;DO. - LOOP STRUCTURE, DECLARES TOP OF LOOP
|
||||
; LOOP. - JUMPS TO TOP OF LOOP
|
||||
; EXIT. - EXITS LOOP
|
||||
; TOP. - TAG AT TOP OF LOOP FOR JUMPS, E.G. SOJG T4,TOP.
|
||||
; ENDLP. - TAG AT END OF LOOP FOR JUMPS, E.G. SOJL T4,ENDLP.
|
||||
|
||||
DEFINE DO.
|
||||
..DX
|
||||
TERMIN
|
||||
|
||||
DEFINE ..DX \%TGE,%SV1,%SV2,%SV3
|
||||
EQUALS %SV1,TOP. ? EQUALS %SV2,ENDDO. ? EQUALS %SV3,ENDLP.
|
||||
.KILL %SV1
|
||||
TOP.==.
|
||||
DEFINE ENDDO.
|
||||
%TGE::EQUALS TOP.,%SV1 ? EQUALS ENDDO.,%SV2 ? EQUALS ENDLP.,%SV3
|
||||
.KILL %TGE
|
||||
TERMIN
|
||||
DEFINE ENDLP.
|
||||
%TGE!!TERMIN
|
||||
TERMIN
|
||||
|
||||
DEFINE ENDDO.
|
||||
.ERR ENDDO. outside loop
|
||||
TERMIN
|
||||
DEFINE ENDLP.
|
||||
.ERR ENDLP. outside loop
|
||||
TERMIN
|
||||
TOP.==-1
|
||||
|
||||
DEFINE OD.
|
||||
ENDDO.!TERMIN
|
||||
|
||||
DEFINE LOOP.
|
||||
JRST TOP.!TERMIN
|
||||
|
||||
DEFINE EXIT.
|
||||
JRST ENDLP.!TERMIN
|
||||
|
||||
|
||||
;Conditionals
|
||||
|
||||
DEFINE IFSKP.
|
||||
..IX [JRST ]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFNSK.
|
||||
ABSKP
|
||||
..IX [JRST ]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFXN. AC,#MASK
|
||||
IFE 1_35.-MASK,..IX [JUMPGE AC,]
|
||||
.ELSE [IFE MASK+1,..IX [JUMPE AC,]
|
||||
.ELSE [TXNN AC,MASK
|
||||
..IX [JRST ]
|
||||
]]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFXE. AC,#MASK
|
||||
IFE 1_35.-MASK,..IX [JUMPL AC,]
|
||||
.ELSE [IFE MASK+1,..IX [JUMPN AC,]
|
||||
.ELSE [TXNE AC,MASK
|
||||
..IX [JRST ]
|
||||
]]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFJER.
|
||||
ERJMP .+2
|
||||
..IX [JRST ]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFNES.
|
||||
PRINTX /% IFNES. should be changed to IFJER.
|
||||
/
|
||||
IFJER.
|
||||
TERMIN
|
||||
|
||||
DEFINE IFNJE.
|
||||
..IX [ERJMP ]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFESK.
|
||||
PRINTX /% IFESK. should be changed to IFNJE.
|
||||
/
|
||||
IFNJE.
|
||||
TERMIN
|
||||
|
||||
DEFINE IFE. AC
|
||||
..IX [JUMPN AC,]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFN. AC
|
||||
..IX [JUMPE AC,]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFG. AC
|
||||
..IX [JUMPLE AC,]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFGE. AC
|
||||
..IX [JUMPL AC,]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFLE. AC
|
||||
..IX [JUMPG AC,]
|
||||
TERMIN
|
||||
|
||||
DEFINE IFL. AC
|
||||
..IX [JUMPGE AC,]
|
||||
TERMIN
|
||||
|
||||
DEFINE ..IX OP,\%TAG,%SV1,%SV2
|
||||
OP!%TAG
|
||||
EQUALS %SV1,..TG ? EQUALS %SV2,ENDIF.
|
||||
DEFINE ..TG LBL
|
||||
%TAG!!LBL!TERMIN
|
||||
DEFINE ENDIF.
|
||||
..TG [::]
|
||||
.KILL ..TG
|
||||
EQUALS ..TG,%SV1 ? EQUALS ENDIF.,%SV2
|
||||
TERMIN
|
||||
TERMIN
|
||||
|
||||
DEFINE ELSE.
|
||||
..EX
|
||||
TERMIN
|
||||
|
||||
DEFINE ..EX \%TAG
|
||||
JRST %TAG
|
||||
..TG [::]
|
||||
DEFINE ..TG LBL
|
||||
%TAG!!LBL!TERMIN
|
||||
TERMIN
|
||||
|
||||
DEFINE ..TG LBL
|
||||
.ERR Conditional construct outside a conditional
|
||||
TERMIN
|
||||
|
||||
DEFINE ENDIF.
|
||||
.ERR ENDIF. outside a conditional
|
||||
TERMIN
|
||||
|
||||
|
||||
;GENERAL CASES WITHIN CONDITIONALS
|
||||
|
||||
DEFINE ANSKP.
|
||||
JRST ..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANNSK.
|
||||
ABSKP
|
||||
JRST ..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANJER.
|
||||
ERJMP .+2
|
||||
JRST ..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANNJE.
|
||||
ERJMP ..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDXN. AC,#MASK
|
||||
IFE 1_35.-MASK,JUMPGE AC,..TG
|
||||
.ELSE [IFE MASK+1,JUMPE AC,..TG
|
||||
.ELSE [TXNN AC,MASK
|
||||
JRST ..TG
|
||||
]]
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDXE. AC,#MASK
|
||||
IFE 1_35.-MASK,JUMPL AC,..TG
|
||||
.ELSE [IFE MASK+1,JUMPN AC,..TG
|
||||
.ELSE [TXNE AC,MASK
|
||||
JRST ..TG
|
||||
]]
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDE. AC
|
||||
JUMPN AC,..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDN. AC
|
||||
JUMPE AC,..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDG. AC
|
||||
JUMPLE AC,..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDGE. AC
|
||||
JUMPL AC,..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDLE. AC
|
||||
JUMPG AC,..TG
|
||||
TERMIN
|
||||
|
||||
DEFINE ANDL. AC
|
||||
JUMPGE AC,..TG
|
||||
TERMIN
|
||||
|
||||
|
||||
;MACRO TO PRINT MESSAGE ON TERMINAL
|
||||
|
||||
DEFINE TMSG &MSG
|
||||
HRROI 1,[ASCIZ MSG]
|
||||
PSOUT
|
||||
TERMIN
|
||||
|
||||
;MACRO TO OUTPUT MESSAGE TO FILE
|
||||
; ASSUMES JFN ALREADY IN .AC1
|
||||
|
||||
DEFINE FMSG &MSG
|
||||
HRROI 2,[ASCIZ MSG]
|
||||
MOVEI 3,0
|
||||
SOUT
|
||||
TERMIN
|
||||
|
||||
DEFINE EMSG &MSG
|
||||
HRROI 1,[ASCIZ MSG]
|
||||
ESOUT
|
||||
TERMIN
|
||||
|
||||
; SAVEAC [A,B,C]
|
||||
; Supports +1/+2 returns.
|
||||
; Unlike macro version, supports arbitrary locations (not just AC's)
|
||||
; and doesn't clobber AC16.
|
||||
|
||||
DEFINE SAVEAC ACS
|
||||
IRP AC,,[ACS]
|
||||
PUSH P,AC
|
||||
..XX==.IRPCNT
|
||||
TERMIN
|
||||
.SAVX1 ..XX+1,[ACS]
|
||||
TERMIN
|
||||
|
||||
EQUALS SAVE.,SAVEAC ;Not in MACRO version...
|
||||
|
||||
DEFINE .SAVX1 #N#,ACS
|
||||
PUSH P,[[ABSKP
|
||||
AOS -N(P)
|
||||
.SAVX2 [ACS]
|
||||
POPJ P,
|
||||
]]
|
||||
TERMIN
|
||||
|
||||
DEFINE .SAVX2 ACS
|
||||
IRP AC,REST,[ACS]
|
||||
.SAVX2 [REST]
|
||||
POP P,AC
|
||||
.ISTOP
|
||||
TERMIN
|
||||
TERMIN
|
||||
|
||||
DEFINE BRMSK. INI0=0,INI1=0,INI2=0,INI3=0,ALLOW,DISALW
|
||||
..X0==INI0
|
||||
..X1==INI1
|
||||
..X2==INI2
|
||||
..X3==INI3
|
||||
IRPC CH,,[ALLOW]
|
||||
..BRK 0,<.ASCVL /CH>/32.,35.-<.ASCVL /CH>&31.
|
||||
TERMIN
|
||||
IRPC CH,,[DISALW]
|
||||
..BRK 1,<.ASCVL /CH>/32.,35.-<.ASCVL /CH>&31.
|
||||
TERMIN
|
||||
..X0 ? ..X1 ? ..X2 ? ..X3
|
||||
TERMIN
|
||||
|
||||
DEFINE ..BRK VAL,#WD,BT
|
||||
..X!WD==.DPB VAL,BT!0100,..X!WD
|
||||
TERMIN
|
||||
|
||||
DEFINE FLDDB. ?FNC,FLAGS=0,DATA=0,&HLPM,DEFM,?NXT=0
|
||||
FLDBK.(FNC,FLAGS,DATA,HLPM,DEFM,,NXT)TERMIN
|
||||
|
||||
DEFINE FLDBK. ?FNC,FLAGS=0,DATA=0,&HLPM,DEFM,?BRK,NXT=0
|
||||
..XX==0
|
||||
IFSN [HLPM][] ..XX==..XX\CM%HPP
|
||||
IFSN [DEFM][] ..XX==..XX\CM%DPP
|
||||
IFSN [BRK][] ..XX==..XX\CM%BRK
|
||||
<<FNC>_27.>\<FLAGS>\..XX\<0,,NXT>
|
||||
DATA
|
||||
IFSN [HLPM][][440700,,[ASCIZ HLPM]]
|
||||
.ELSE [IFSN [DEFM!BRK][][0]]
|
||||
IFSN [DEFM][][440700,,[ASCIZ DEFM]]
|
||||
.ELSE [IFSN [BRK][][0]]
|
||||
IFSN [BRK][][BRK]
|
||||
TERMIN
|
||||
|
||||
;.YSTGW ;Allow storage words again
|
||||
|
||||
IFN $$JSER,[ ;Optional Jsys error support
|
||||
|
||||
IFNDEF P,P==:17
|
||||
|
||||
;MACRO TO PRINT MESSAGE FOR LAST ERROR, RETURNS +1
|
||||
|
||||
DEFINE PERSTR &MSG
|
||||
IFSN [MSG][]TMSG MSG
|
||||
PUSHJ P,JSMSG0
|
||||
TERMIN
|
||||
|
||||
;PRINT ERROR MESSAGE IF JSYS FAILS
|
||||
|
||||
DEFINE ERMSG *TEXT
|
||||
ERJMP [TMSG ¿!TEXTŠ
|
||||
JSHLT]
|
||||
TERMIN
|
||||
|
||||
;JSYS ERROR HANDLER
|
||||
; CALL JSERR0
|
||||
; RETURNS +1: ALWAYS, CAN BE USED IN +1 RETURN OF JSYS'S
|
||||
|
||||
JSERR0: MOVEI 1,.PRIIN
|
||||
CFIBF ;CLEAR TYPAHEAD
|
||||
MOVEI 1,.PRIOU
|
||||
DOBE ;WAIT FOR PREVIOUS OUTPUT TO FINISH
|
||||
TMSG "
|
||||
?JSYS error: "
|
||||
JSMSG0: MOVEI 1,.PRIOU
|
||||
HRLOI 2,.FHSLF ;SAY THIS FORK ,, LAST ERROR
|
||||
SETZ 3,
|
||||
ERSTR
|
||||
NOP
|
||||
NOP
|
||||
TMSG "
|
||||
"
|
||||
POPJ P,
|
||||
|
||||
JSERR=:<PUSHJ P,JSERR0> ;Prints last jsys error, returns +1
|
||||
EJSERR=:<ERCAL JSERR0>
|
||||
|
||||
;FATAL JSYS ERROR - PRINT MESSAGE AND HALT
|
||||
; CALL JSHLT0
|
||||
; RETURNS: NEVER
|
||||
|
||||
JSHLT0: JSERR ;PRINT THE MSG
|
||||
JSHLT1: HALTF
|
||||
TMSG "?Program cannot continue
|
||||
"
|
||||
JRST JSHLT1 ;HALT AGAIN IF CONTINUED
|
||||
|
||||
.KILL JSHLT1
|
||||
|
||||
JSHLT=:<PUSHJ P,JSHLT0> ;Prints last jsys error, halts
|
||||
EJSHLT=:<ERCAL JSHLT0>
|
||||
|
||||
];$$JSER
|
||||
|
||||
|
||||
IFN $$STK,[ ;Optional stack related support
|
||||
|
||||
SUBTTL STKVAR - STACK VARIABLE FACILITY
|
||||
|
||||
IFNDEF P,P==:17
|
||||
|
||||
CALL=:<PUSHJ P,>
|
||||
RET=:<POPJ P,>
|
||||
CALLRET==:<JRST>
|
||||
|
||||
;; STKVAR [AA,BB,[QQ,5],ZZ]
|
||||
;; ENDSV. (end of scope, flush names)
|
||||
;; Supports return and skip return.
|
||||
;; Unlike the macro version, AC16 is NOT clobbered.
|
||||
;; Unlike the macro version, variables defined in left-to-right order
|
||||
;; (so above, DMOVEM 1,AA will put 1 in AA and 2 in BB)
|
||||
DEFINE STKVAR ARGS
|
||||
..STKN==1+IRP VAR,,[ARGS] <.STKV1(VAR)>+TERMIN
|
||||
..STKQ==..STKN
|
||||
IRP VAR,,[ARGS]
|
||||
.STKV2 ..STKQ,VAR
|
||||
TERMIN
|
||||
DEFINE ENDSV.
|
||||
IRP ARG,,[ARGS]
|
||||
.ENSV1(ARG)
|
||||
TERMIN
|
||||
.KILL ..STKN,..STKQ
|
||||
TERMIN
|
||||
ADJSP P,..STKN
|
||||
PUSHJ P,.STKST
|
||||
TERMIN
|
||||
|
||||
DEFINE .STKV1 ?VAR,SIZE=1
|
||||
SIZE!TERMIN
|
||||
|
||||
DEFINE .STKV2 #LOC#,VAR,SIZE=1
|
||||
DEFINE VAR
|
||||
-LOC(P)TERMIN
|
||||
..STKQ==LOC-SIZE
|
||||
TERMIN
|
||||
|
||||
DEFINE .ENSV1 (VAR)
|
||||
EXPUNGE VAR
|
||||
TERMIN
|
||||
|
||||
|
||||
.STKST: EXCH 16,(P) ;Get return address, save AC16
|
||||
MOVEM 16,-1(P) ;Save ret address
|
||||
MOVN 16,-2(16) ;Fetch the word with ..stkn in it, negated
|
||||
MOVEI 16,(16) ;Clear lhs to allow indirecting in .STKRT
|
||||
EXCH 16,-1(P) ;Save it, get return address
|
||||
PUSH P,16 ;Set up for popj
|
||||
HRRI 16,.STKRT ;Fake return address for caller
|
||||
EXCH 16,-1(P) ;set it up, restoring AC16
|
||||
POPJ P,
|
||||
|
||||
.STKRT: JRST STKRT0 ;Normal return
|
||||
ADJSP P,@(P) ;Skip return
|
||||
RSKP: AOS (P)
|
||||
R: POPJ P,
|
||||
|
||||
STKRT0: ADJSP P,@(P)
|
||||
POPJ P,
|
||||
|
||||
.KILL STKRT0
|
||||
|
||||
RETSKP=:<JRST RSKP>
|
||||
];$$STK
|
||||
636
src/syseng/rfnl.26
Normal file
636
src/syseng/rfnl.26
Normal file
@@ -0,0 +1,636 @@
|
||||
|
||||
.BEGIN RFNL ;-*-MIDAS-*-
|
||||
|
||||
SUBTTL Routines for parsing and printing filenames
|
||||
|
||||
;Basic conventions:
|
||||
|
||||
;We assume that there are accumulators A, B, C, and D, not necessarily
|
||||
;consecutive, and that the stack is in P.
|
||||
;No routine clobbers ACs other than the
|
||||
;ones it is documented to clobber, and none touches even temporarily
|
||||
;any AC other than A, B, C, D and P.
|
||||
;All code generated is pure, except for a few .SCALAR definitions.
|
||||
;The main routines PFN, PFNCT and PFNMCH never skip.
|
||||
;The main routines RFN and MERGE skip if the filename block to
|
||||
;be filled in was big enough for the data to be put in it.
|
||||
;The main routine STKMRG skips if it was able to allocate the result string.
|
||||
|
||||
;;; Filename blocks:
|
||||
|
||||
;A filename block consists any number of two-word entries,
|
||||
;each of which holds a pair of byte pointers to the beginning and end
|
||||
;of one component of a filename string.
|
||||
;The last character in the component is one of ":", ";", " ", ^@, ^X or ^Y,
|
||||
;and it identifies the type of component.
|
||||
|
||||
;;; Parsing and unparsing filenames:
|
||||
|
||||
;This file contains two routines, RFN to read filenames and PFN to print.
|
||||
;The $$RFN and $$PFN assembly switches control them.
|
||||
;Both expect a b.p. for ILDB'ing or IDPB'ing the text, in D.
|
||||
;Both expect an AOBJN pointer to a filename block in B.
|
||||
|
||||
;For RFN, the AOBJN pointer in B should point to the space
|
||||
;available for a filename block. On return, B will be an AOBJN
|
||||
;pointer to the space actually used. RFN skips unless data
|
||||
;was lost because the block was full.
|
||||
|
||||
;The filename block constructed by RFN contains pointers into the
|
||||
;argument string, so that string must be kept intact until after the
|
||||
;filename block is no longer needed. In particular, it does not work
|
||||
;to PFN the same filename block, or the result of merging it with another,
|
||||
;into the same space that the original string was in.
|
||||
|
||||
;The RFN routine assumes that the user has defined the label RFNSPC
|
||||
;which says which characters are terminators or start switches.
|
||||
;RFNSPC should examine the character in A and skip if it should
|
||||
;either terminate the filename or start a switch.
|
||||
;If the character is "/" or "(" and $$SWITCH is 1, it will start
|
||||
;a switch; otherwise, it will terminate the filespec.
|
||||
;If RFNSPC does not skip, the character will neither terminate nor start a switch.
|
||||
;However, RFNSPC is not called for the characters ":", ";", " ", and ^Q.
|
||||
;For CR and ^@, it makes no difference whether RFNSPC skips.
|
||||
|
||||
;PFN similarly assumes that there is a routine PFNSPC which will
|
||||
;skip for a character in A that needs a ^Q printed in front of it.
|
||||
;Normally, RFNSPC and PFNSPC can be the same routine.
|
||||
|
||||
;If you want switches to be processed in filenames,
|
||||
;set $$SWITCH to 1 and define the label SWITCH as a routine to read a switch.
|
||||
;It will be called with the first character of the switch in A.
|
||||
;It can read more characters off D, or by calling RFN"RUC
|
||||
;If it skips, RFN assumes that the character in A should be reprocessed.
|
||||
;A slash is followed by a single switch, while parentheses enclose
|
||||
;any number of switches. However, neither slash nor "(" will be
|
||||
;recognized unless RFNSPC skips for it. This gives the caller
|
||||
;run-time control of whether switches are to be processed.
|
||||
|
||||
;If $$MNAME is set, the user must define MNAME to point to
|
||||
;a word holding this machine's name in SIXBIT.
|
||||
|
||||
;;; Merging defaults:
|
||||
|
||||
;The MERGE routine takes two filename blocks (A and B) as input
|
||||
;and a third AOBJN pointer in C to space to store a filename block as output.
|
||||
;It copies the components of the first block, putting them in canonical order,
|
||||
;and defaulting missing components from the second block.
|
||||
;The results go in the third block.
|
||||
;On return, C is an AOBJN pointer to the part of the output block
|
||||
;which was actually filled with data,
|
||||
;and MERGE skips unless data was lost because the block was full.
|
||||
|
||||
;Because the merged filename block contains pointers copied from the
|
||||
;two input filename blocks, the strings which those input filename blocks
|
||||
;were parsed from must be kept intact until the merged filename block
|
||||
;is passed to PFN.
|
||||
|
||||
;^X and ^Y components in the first argument are replaced by the
|
||||
;default names from the second argument to which they refer.
|
||||
|
||||
;The STKMRG routine is a high level interface which parses, merges
|
||||
;and makes a string all on one. It takes two ASCIZ strings,
|
||||
;does RFN on each, does MERGE to the two filename blocks,
|
||||
;then does PFN on the result, storing into a dynamically allocated string
|
||||
;All temporary storage comes from the stack.
|
||||
|
||||
;These symbols should be defined by the user to select parts of this file:
|
||||
IFNDEF $$RFN,$$RFN==0 ;Include RFN, the routine for reading filenames.
|
||||
IFNDEF $$SWITCH,$$SWITCH==0 ;Include routines for processing "/" and "(-)" switches.
|
||||
IFNDEF $$PFN,$$PFN==0 ;Include PFN, the routine for printing filenames.
|
||||
IFNDEF $$MNAME,$$MNAME==0 ;1 => assume MNAME is defined and holds this machine's name.
|
||||
IFNDEF $$MERGE,$$MERGE==0 ;1 => provide MERGE routine to merge defaults.
|
||||
IFNDEF $$STKMRG,$$STKMRG==0 ;1 => provide STKMRG routine.
|
||||
|
||||
.AUXIL ;Don't mention all our internal symbols in crefs.
|
||||
|
||||
;PRINT VERSION NUMBER
|
||||
.TYO6 .IFNM1
|
||||
.TYO 40
|
||||
.TYO6 .IFNM2
|
||||
PRINTX/ INCLUDED IN THIS ASSEMBLY.
|
||||
/
|
||||
|
||||
DEFINE SYSCAL NAME,ARGS
|
||||
.CALL [SETZ ? SIXBIT/NAME/ ? ARGS ((SETZ))]
|
||||
TERMIN
|
||||
|
||||
IFN $$RFN,[ ;Routine for parsing a filename.
|
||||
|
||||
;Given a BP in D pointing to a filename,
|
||||
;store in the filename block <- AOBJN ptr in B
|
||||
;pointers to the beginnings and ends of the components of the filename.
|
||||
|
||||
;The block <- B contains two-word entries.
|
||||
;In each entry is placed a pair of BPs, pointing to the start
|
||||
;and end of one name (or device or directory) in the filename.
|
||||
|
||||
;Since B contains only pointers to the originally supplied string,
|
||||
;you must not clobber the string itself until after you are through
|
||||
;with the data in the filename block.
|
||||
|
||||
;Advances D through the string.
|
||||
;Sets B to an AOBJN pointer to the used portion of the table;
|
||||
;skips if the table was long enough.
|
||||
;Clobbers C and A.
|
||||
|
||||
;If B's right half starts out as 0, then only the left half is incremented
|
||||
;and the table is not stored. So call with B/ SETZ to compute how long
|
||||
;a table is required for a given string.
|
||||
rfn: push p,b
|
||||
rfn0: move c,d
|
||||
rfn1: ildb a,d
|
||||
rfnunr: caie a,";
|
||||
cain a,": ;Check for special pathname syntax chars
|
||||
jrst rfn2 ;that always have these special meanings.
|
||||
cain a,40
|
||||
jrst rfn2
|
||||
caie a,^X
|
||||
cain a,^Y
|
||||
jrst rfn3
|
||||
cain a,^Q
|
||||
jrst [ ildb a,d
|
||||
jrst rfn4]
|
||||
pushj p,rfnspc ;Otherwise, ask user whether char is special.
|
||||
jrst rfn4 ;No skip => treat char as ordinary.
|
||||
ifn $$switch,[
|
||||
cain a,"/ ;If stopped on "/" or "(", call switch rtn.
|
||||
jrst rfnsl ;Read 1 switch.
|
||||
cain a,"(
|
||||
jrst rfnpar ;Read many switches until ).
|
||||
];ifn $$switch
|
||||
setz a, ;If any unrecognized char is "special" according to the user,
|
||||
jrst rfn2 ;it must be a terminator.
|
||||
|
||||
rfn4: cain a,^M ;CR and null character terminate, even if quoted.
|
||||
setz a,
|
||||
jumpn a,rfn1
|
||||
rfn2: push p,c ;Push this entry iff it contains more than one character.
|
||||
ibp c
|
||||
camn c,d
|
||||
jrst [ pop p,c
|
||||
jrst rfn5]
|
||||
pop p,c
|
||||
;Push this component, regardless of its length.
|
||||
rfn3: trnn b,-1
|
||||
jrst [ add b,[2,,] ;But if B's rh is 0, just increment the lh; don't store.
|
||||
jrst rfn5]
|
||||
jumpge b,rfn6 ;Don't actually store in table if past the end.
|
||||
movem c,(b)
|
||||
movem d,1(b)
|
||||
rfn6: add b,[2,,2]
|
||||
rfn5: jumpn a,rfn0 ;If string not terminated, keep parsing.
|
||||
camge b,[2,,] ;Else skip if we did not run out of space in the table.
|
||||
aos -1(p)
|
||||
;Adjust B to contain a pointer to the used portion of the filename block.
|
||||
pop p,c ;Else pop original B into C.
|
||||
sub b,c
|
||||
trz b,-1 ;LH(B) gets number of words pushed onto the filename block.
|
||||
movns b
|
||||
hrr b,c ;B gets AOBJN ptr to used portion.
|
||||
popj p,
|
||||
|
||||
IFN $$SWITCH,[ ;Code for processing switches, when a "/" or "(" is seen.
|
||||
|
||||
rfnpar: pushj p,ruc ;Get next char. Is it a ")"?
|
||||
rfnpa1: cain a,")
|
||||
jrst rfn1 ;Paren ends switches; gobble next character.
|
||||
caie a,0
|
||||
cain a,^M
|
||||
jrst rfnunr ;CR ends spec even in switch list; reread it.
|
||||
pushj p,switch ;Try to gobble the switch.
|
||||
jrst rfnpar ;Char in A used up, get another.
|
||||
jrst rfnpa1 ;Char in A not part of switch; is it ")"?
|
||||
|
||||
rfnsl: pushj p,ruc
|
||||
caie a,0
|
||||
cain a,^M ;/<CR> ends spec; reread it.
|
||||
jrst rfnunr
|
||||
pushj p,switch ;Otherwise, process it as switch.
|
||||
jrst rfnunr ;No skip => char in A was gobbled by switch.
|
||||
jrst rfn1 ;Skip => let next RSIXG gobble the char now in A.
|
||||
|
||||
;Read a char into A off the bp in D and convert to upper case.
|
||||
ruc: ildb a,d
|
||||
cail a,140
|
||||
subi a,40
|
||||
popj p,
|
||||
|
||||
];IFN $$SWITCH
|
||||
|
||||
];IFN $$RFN
|
||||
|
||||
IFN $$PFN,[ ;Routine to turn a filename block into a single string.
|
||||
|
||||
;Given a filename block of two-word entries <- AOBJN ptr in B,
|
||||
;output a filename down the BP in D.
|
||||
;Clobbers A and C. Counts B out through the filename block.
|
||||
|
||||
;The filename components are printed in the order they appear.
|
||||
;If you want them permuted into standard order,
|
||||
;merge them with an empty block of defaults first with MERGE
|
||||
;(since the output from MERGE always has the components in standard order).
|
||||
pfn: jumpge b,pfn2
|
||||
pfnmc2: jumpge b,pfn2a
|
||||
move c,(b)
|
||||
pushj p,pfn1
|
||||
add b,[2,,2]
|
||||
jumpl b,pfnmc2
|
||||
pfn2a: setz a, ;Replace the space at the end of the last
|
||||
dpb a,d ;entry with a null;
|
||||
ldb a,[300600,,d] ;then decrement the bp in D to point before the null.
|
||||
ldb c,[360600,,d]
|
||||
add c,a
|
||||
dpb c,[360600,,d]
|
||||
popj p,
|
||||
|
||||
pfn2: setz a, ;If filename block is empty,
|
||||
move c,d ;store a null, but don't advance over it.
|
||||
idpb a,c
|
||||
popj p,
|
||||
|
||||
;Copy one entry's string into the output string.
|
||||
pfn1: camn c,1(b) ;Stop at end of entry.
|
||||
jrst [ cain a,40 ;If the entry ended in other than space, put in a space.
|
||||
popj p,
|
||||
movei a,40
|
||||
idpb a,d
|
||||
popj p,]
|
||||
ildb a,c ;Fetch the next character.
|
||||
cain a,0 ;If it's a terminating null,
|
||||
movei a,40 ;output a space instead.
|
||||
pushj p,pfnspc ;Is it special in this program?
|
||||
jrst pfn3
|
||||
push p,a ;If so, put a ^Q in front of it.
|
||||
movei a,^Q
|
||||
idpb a,d
|
||||
pop p,a
|
||||
pfn3: idpb a,d ;In any case, output the char itself.
|
||||
caie a,^Q ;If it is a ^Q, don't check the following char
|
||||
jrst pfn1 ;for being special or for being ^Q.
|
||||
camn c,1(b)
|
||||
popj p,
|
||||
ildb a,c
|
||||
idpb a,d
|
||||
movei a,1 ;Don't leave space in A if it was quoted.
|
||||
jrst pfn1
|
||||
|
||||
;Return in D the number of characters required to hold a single string
|
||||
;made from the parsed block of two-word entries pointed to by B.
|
||||
;Clobbers A and C.
|
||||
|
||||
;Use this to decide how long a block to allocate for a string to be
|
||||
;constructed with PFN.
|
||||
|
||||
;Note that the value returned is the length of the contents of the ASCIZ
|
||||
;string that PFN will write. It does not count the zero written
|
||||
;to terminate that string.
|
||||
pfnct: setz d,
|
||||
jumpge b,cpopj
|
||||
pfnct0: jumpge b,[soja d,cpopj]
|
||||
move c,(b)
|
||||
pushj p,pfnct1
|
||||
add b,[2,,2]
|
||||
jrst pfnct0
|
||||
|
||||
pfnct1: camn c,1(b) ;Stop at end of entry, but count one
|
||||
jrst [ caie a,40 ;for a following space if the entry didn't end in one.
|
||||
cain a,0
|
||||
aos d
|
||||
popj p,]
|
||||
ildb a,c ;Fetch the next character.
|
||||
addi d,1 ;Count it.
|
||||
pushj p,pfnspc ;Is it special in this program?
|
||||
jrst pfnct3
|
||||
addi d,1 ;If so, count a ^Q for it.
|
||||
pfnct3: caie a,^Q ;If it is a ^Q, don't check the following char
|
||||
jrst pfnct1 ;for being special or for being ^Q.
|
||||
camn c,1(b)
|
||||
popj p,
|
||||
ibp c ;Skip that char, but leave ^Q in A.
|
||||
aoja d,pfnct1 ;DO count the char.
|
||||
|
||||
;Like PFN, but if the first component in the filename block is "DSK:"
|
||||
;we output the machine name instead.
|
||||
pfnmch: pushj p,pfnmc1 ;IS the first component "DSK:"?
|
||||
jrst pfn ;No, just print normally.
|
||||
push p,b
|
||||
IFN $$MNAME,move a,mname ;Yes, print the machine name instead
|
||||
.ELSE [ syscal sstatu,[repeat 6,[? %clout,,a]]
|
||||
.lose %lssys
|
||||
]
|
||||
movei b,": ;with a colon after it
|
||||
pushj p,sixstr
|
||||
movei b,40 ;and a space just as PFN would put after that.
|
||||
idpb b,d
|
||||
pop p,b
|
||||
add b,[2,,2] ;Discard the component "DSK:" and
|
||||
jrst pfnmc2 ;process the remaining components.
|
||||
|
||||
;Skip if the first component in the filename block in B is "DSK:".
|
||||
pfnmc1: move c,(b)
|
||||
irpc char,,[DSK:]
|
||||
ildb a,c
|
||||
caie a,"char
|
||||
popj p, ;Return non-skip if a character doesn't match.
|
||||
termin
|
||||
camn c,1(b) ;Skip only if the entry length is correct.
|
||||
aos (p)
|
||||
popj p,
|
||||
|
||||
;Output sixbit word in A as ASCII down BP in D
|
||||
;followed by terminator in B and a null character. Clobbers C.
|
||||
sixstr: push p,b
|
||||
move b,[440600,,a]
|
||||
sixst1: ildb c,b
|
||||
addi c,40
|
||||
idpb c,d
|
||||
setz c,
|
||||
dpb c,b
|
||||
jumpn a,sixst1
|
||||
sixst2: pop p,b
|
||||
idpb b,d
|
||||
push p,d
|
||||
setz c,
|
||||
idpb c,d
|
||||
pop p,d
|
||||
popj p,
|
||||
|
||||
];IFN $$PFN
|
||||
|
||||
IFN $$MERGE,[ ;Routine to merge defaults from one filename block with another filename block.
|
||||
|
||||
;Given in A and B two AOBJN pointers to filename blocks of input data,
|
||||
;and in C an AOBJN pointer to an output filename block,
|
||||
;merge the two input blocks writing the result in the output one.
|
||||
;The first argument's components take priority over the second argument's.
|
||||
|
||||
;D should contain nonzero if a single name specified in the
|
||||
;first argument should override all names of the second argument.
|
||||
;This value is stored in MRGFN2 while MERGE is running.
|
||||
;If MRGFN2 is nonzero, then if the first argument contains only one NAME,
|
||||
;the second NAME (if any) from the second argument is used as well.
|
||||
;If MRGFN2 is zero, then if the first argument contains only one NAME,
|
||||
;only that NAME is used.
|
||||
.scalar mrgfn2
|
||||
|
||||
;On return, C's lh is set to minus the number of words used.
|
||||
;We skip if the space provided was sufficient.
|
||||
merge: push p,mrgfn2
|
||||
movem d,mrgfn2
|
||||
push p,c
|
||||
movei d,":
|
||||
pushj p,merge1
|
||||
movei d,";
|
||||
pushj p,merge1
|
||||
movei d,40
|
||||
push p,a
|
||||
push p,b
|
||||
pushj p,msrch
|
||||
jrst merge2
|
||||
move a,(p) ;No NAME found in input 1 => copy all NAMEs from input 2.
|
||||
merge3: move b,(p)
|
||||
pushj p,mcopy
|
||||
mergex: pop p,b
|
||||
pop p,a
|
||||
mergx1: pop p,d ;Pop original C into D.
|
||||
caml c,[2,,]
|
||||
jrst [ move c,d
|
||||
jrst mergx2]
|
||||
sub c,d
|
||||
andi c,-1 ;C gets number of words pushed onto filename block now in D.
|
||||
movns c
|
||||
hrlzs c
|
||||
hrr c,d ;C gets AOBJN ptr to used portion of filename block.
|
||||
aos -1(p)
|
||||
mergx2: move d,mrgfn2
|
||||
pop p,mrgfn2
|
||||
cpopj: popj p,
|
||||
|
||||
merge2: move b,(p)
|
||||
pushj p,mcopnm ;One NAME found in input 1 => copy it to output.
|
||||
add a,[2,,2]
|
||||
pushj p,msrch ;Search for a second one.
|
||||
jrst merge3 ;Found => copy all remaining NAMEs from input 1.
|
||||
move a,(p)
|
||||
skipe mrgfn2 ;Not found: if want no default fn2, return with just this one.
|
||||
pushj p,mergln
|
||||
jrst mergex
|
||||
|
||||
;Search the filename block <- AOBJN ptr in A for an entry whose string
|
||||
;ends in the character in D. Skip if NOT found.
|
||||
;Leave A pointing at the entry if it is found.
|
||||
;Clobbers B.
|
||||
;An entry ending in a null character is considered to end with a space.
|
||||
msrch: jumpge a,popj1
|
||||
move b,1(a)
|
||||
ldb b,b
|
||||
skipn b
|
||||
movei b,40
|
||||
caie b,^X ;Finding either a ^X or a ^Y
|
||||
cain b,^Y ;counts as finding a name.
|
||||
movei b,40
|
||||
cain b,(d)
|
||||
popj p,
|
||||
add a,[2,,2]
|
||||
jrst msrch
|
||||
|
||||
popj1: aos (p)
|
||||
popj p,
|
||||
|
||||
;Copy all the elements ending in the character in D
|
||||
;from the filename block <- AOBJN ptr in A if it contains any;
|
||||
;otherwise, copy all the ones from the filename block <- AOBJN ptr in B.
|
||||
;D should NOT contain a space.
|
||||
merge1: push p,a
|
||||
push p,b
|
||||
pushj p,msrch
|
||||
jrst merge9
|
||||
move a,(p)
|
||||
pushj p,msrch
|
||||
merge9: pushj p,mcopy
|
||||
popbaj: pop p,b
|
||||
pop p,a
|
||||
popj p,
|
||||
|
||||
;Copy entries from the filename block <- AOBJN ptr in A to that in C.
|
||||
;Copy all those whose ending character matches that in D.
|
||||
;When copying NAMEs (D contains a space)
|
||||
;^X and ^Y entries are processed as well,
|
||||
;using the filename block <- AOBJN ptr in B.
|
||||
mcopy: push p,b
|
||||
mcopy0: jumpge c,popbj
|
||||
jumpge a,popbj
|
||||
move b,1(a)
|
||||
ldb b,b
|
||||
caie b,^X
|
||||
cain b,^Y
|
||||
caie d,40
|
||||
caia
|
||||
jrst mcopy3
|
||||
skipn b
|
||||
movei b,40
|
||||
came b,d
|
||||
jrst mcopy1
|
||||
mcopy3: move b,(p)
|
||||
pushj p,mcopnm
|
||||
mcopy1: add a,[2,,2]
|
||||
jrst mcopy0
|
||||
|
||||
;Copy the filename component that A points to
|
||||
;into the filename block in C, assuming that B
|
||||
;contains the filename block to find defaults in (for ^X and ^Y).
|
||||
mcopnm: push p,b
|
||||
move b,1(a)
|
||||
ldb b,b
|
||||
caie b,^X
|
||||
cain b,^Y
|
||||
jrst mcopy2
|
||||
jumpge c,mcopn1
|
||||
move b,(a)
|
||||
movem b,(c)
|
||||
move b,1(a)
|
||||
movem b,1(c)
|
||||
mcopn1: add c,[2,,2]
|
||||
jrst popbj
|
||||
|
||||
;Copy a NAME which is really a ^X or ^Y.
|
||||
;Get, off the stack, the second arg block
|
||||
;and copy either its first NAME or its last one.
|
||||
mcopy2: exch a,(p)
|
||||
push p,a
|
||||
pushj p,[cain b,^X
|
||||
jrst mergfn
|
||||
jrst mergln]
|
||||
jrst popbaj
|
||||
|
||||
;Copy the first NAME from the arg block in A into the output here.
|
||||
mergfn: push p,b
|
||||
push p,d
|
||||
movei d,40
|
||||
pushj p,msrch
|
||||
jrst mergf1
|
||||
jrst popdbj
|
||||
|
||||
;Copy the last NAME from the arg block in A into the output here.
|
||||
mergln: push p,b
|
||||
push p,d
|
||||
movei d,40
|
||||
pushj p,msrch ;Don't even consider the first name. Find it now
|
||||
caia ;so we can start from after it.
|
||||
jrst popdbj
|
||||
push p,[0]
|
||||
mergl1: add a,[2,,2]
|
||||
pushj p,msrch ;Keep searching, and remember the last place we found one.
|
||||
jrst [ movem a,(p)
|
||||
jrst mergl1]
|
||||
pop p,a
|
||||
mergf1: jumpe a,popdbj
|
||||
jumpge c,mergf2
|
||||
move b,(a) ;Copy that last one into the output.
|
||||
movem b,(c)
|
||||
move b,1(a)
|
||||
movem b,1(c)
|
||||
mergf2: add c,[2,,2]
|
||||
popdbj: pop p,d
|
||||
popbj: pop p,b
|
||||
popj p,
|
||||
|
||||
];IFN $$MERGE
|
||||
|
||||
IFN $$STKMRG,[
|
||||
|
||||
;Parse and merge filenames using temprary storage on the stack.
|
||||
|
||||
.scalar stkmp1,stkmp2,stkmp3 ;Temporaries used by STKMRG.
|
||||
|
||||
;Merge two filename strings to produce a new string,
|
||||
;which is stored into freshly allocated storage.
|
||||
;The user-provided STRALC routine is used to allocate that new string.
|
||||
;All other temporary space is allocated on the stack.
|
||||
|
||||
;Call with byte pointers to the two strings in A and B.
|
||||
;A points to the specified string and B points to the defaults.
|
||||
;On return, A points to the newly allocated string's contents.
|
||||
;No accumulators except A, B, C and D are touched,
|
||||
;so the allocation routine can return additional information
|
||||
;or other sorts of pointers to the string
|
||||
;in any of the other accumulators.
|
||||
|
||||
;You must supply a subroutine named STRALC which should
|
||||
;allocate a string of a size given in C, and return a byte pointer
|
||||
;to the string in A. It should skip if successful,
|
||||
;and not skip if such a string cannot be allocated
|
||||
;(length is too great).
|
||||
|
||||
;STKMRG skips if STRALC did.
|
||||
|
||||
stkmrg: push p,a
|
||||
push p,b
|
||||
move d,a
|
||||
movsi b,(setz) ;How much space do we need for a filename block for the 1st arg?
|
||||
pushj p,rfn
|
||||
hrri b,1(p)
|
||||
movem b,stkmp1 ;Save an AOBJN ptr to table we are allocating.
|
||||
hlre c,b
|
||||
movns c ;C gets length required.
|
||||
hrls c
|
||||
move d,-1(p)
|
||||
add p,c ;Mark space as in use.
|
||||
pushj p,rfn ;Parse the 1st arg into the space allocated.
|
||||
move a,stkmp1
|
||||
move d,-1(a)
|
||||
movsi b,(setz)
|
||||
pushj p,rfn ;How much space do we need for a filename block for 2nd arg?
|
||||
hrri b,1(p)
|
||||
movem b,stkmp2 ;Save an AOBJN ptr to table we are allocating.
|
||||
hlre c,b
|
||||
movns c ;C gets length required.
|
||||
hrls c
|
||||
add p,c ;Mark space as in use.
|
||||
move a,stkmp1
|
||||
move d,-1(a) ;Get back our 2nd arg and parse into that space.
|
||||
pushj p,rfn
|
||||
move a,stkmp1
|
||||
move b,stkmp2 ;Get the AOBJN ptrs to the two tables in the stack.
|
||||
hlre d,a
|
||||
hlre c,b
|
||||
subi c,2
|
||||
addb d,c ;Get (minus) sum of their lengths; allocate filename block
|
||||
hrlzs c ;that long to hold the merged filenames.
|
||||
hrri c,1(p)
|
||||
movem c,stkmp3
|
||||
movns d ;D gets length allocated for merged filename block,
|
||||
hrls d ;in both halves.
|
||||
add p,d ;Allocate the space.
|
||||
pushj p,merge ;Now merge into that table.
|
||||
movem c,stkmp3 ;Save ptr to what was used.
|
||||
move b,c
|
||||
pushj p,pfnct ;Put length in D.
|
||||
move c,d
|
||||
pushj p,stralc ;Call user-supplied routine to allocate and put BP in A.
|
||||
jrst stkmr1
|
||||
move b,stkmp3
|
||||
push p,a
|
||||
move d,a
|
||||
pushj p,pfn ;Store the ultimate name into the user-supplied string.
|
||||
pop p,a
|
||||
move b,p ;Deallocate the temporary storage
|
||||
sub b,stkmp1
|
||||
hrls b
|
||||
sub p,b
|
||||
sub p,[3,,3]
|
||||
aos (p)
|
||||
popj p,
|
||||
|
||||
;Return non-skipping.
|
||||
stkmr1: move b,p ;Deallocate the temporary storage
|
||||
sub b,stkmp1
|
||||
hrls b
|
||||
sub p,b
|
||||
sub p,[3,,3]
|
||||
popj p,
|
||||
|
||||
] ;end $$STKMRG
|
||||
|
||||
.end rfnl
|
||||
Reference in New Issue
Block a user