Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!husc6!sri-unix!sri-spam!ames!ucbcad!ucbvax!ENGVAX.SCG.HAC.COM!PORTIA
From: PORTIA@ENGVAX.SCG.HAC.COM (Portia 616-2635)
Newsgroups: comp.os.vms
Subject: virtual file editor (VFE) source (1 of 5) (54 blocks)
Message-ID: <8707252006.AA14521@ucbvax.Berkeley.EDU>
Date: Sat, 25-Jul-87 13:14:00 EDT
Article-I.D.: ucbvax.8707252006.AA14521
Posted: Sat Jul 25 13:14:00 1987
Date-Received: Sun, 26-Jul-87 02:41:40 EDT
Sender: daemon@ucbvax.BERKELEY.EDU
Distribution: world
Organization: The ARPA Internet
Lines: 1054

$ show default
$ check_sum = 1521235
$ write sys$output "Creating AAAREADME.TXT"
$ create AAAREADME.TXT
$ DECK/DOLLARS="$*$*EOD*$*$"
     VFE is a block-oriented, type insensitive VMS file editor.  It
can edit user files, FOREIGN-mounted tapes, and disk devices.  Data
can be displayed in ASCII, EBCDIC, hex, binary, and integer format.
User-defined sections of single or multiple contiguous blocks can be
changed, compared, and transferred within a file or between files.
VFE also has a very fast search which can target a string, hex or
integer constant.  All or part of a terminal session can be logged
to a sequential file for later lineprinter output.

     For more information, see VFE.DOC.

     This is the second release of VFE, with many useful enhancements.
If you are a user of the original version, released on the fall 1984
VAX SIG tapes, be sure to look at VFENEW.DOC.

     This utility was presented at the "VAX magic" session of the fall
1984 DECUS symposium.  Submitted by:

     Ward Condit
     Maricopa Community Colleges
     P. O. Box 13349
     Phoenix, Az.  85002
$*$*EOD*$*$
$ checksum AAAREADME.TXT
$ if checksum$checksum .ne. check_sum then -
$   write sys$output "Checksum failed, file probably corrupted"
$ check_sum = 1326833389
$ write sys$output "Creating COMMAND.MAR"
$ create COMMAND.MAR
$ DECK/DOLLARS="$*$*EOD*$*$"
        .TITLE  COMMAND Read and interpret command lines

        .ENABLE SUPPRESSION

        .LIBRARY        'VFELIB'

        $TPADEF

        .PSECT  CODE,EXE,NOWRT
        .PAGE
        .SBTTL  GETCMD - Get command
GETCMD::
100$:
        CLRB    HLPON
        MOVL    #25,OUTDSC
        TSTB    TAPFLG
        BNEQ    200$
        CMPL    BUFFCT,#1
        BNEQ    150$
        $FAO_S  CTRSTR=SOLDSK0,OUTLEN=OUTDSC,OUTBUF=OUTDSC,-
                P1=CURBLK
        BRW     300$
150$:
        $FAO_S  CTRSTR=SOLDSK1,OUTLEN=OUTDSC,OUTBUF=OUTDSC,-
                P1=CURBLK,P2=CURBCT
        BRB     300$
200$:
        TSTL    CURBCT
        BGTR    250$
        $FAO_S  CTRSTR=SOLTP0,OUTLEN=OUTDSC,OUTBUF=OUTDSC,-
                P1=CURFIL,P2=CURBLK
        BRB     300$
250$:
        $FAO_S  CTRSTR=SOLTP1,OUTLEN=OUTDSC,OUTBUF=OUTDSC,-
                P1=CURFIL,P2=CURBLK,P3=CURBCT
300$:
        INPUT   OUTDSC,OUT_BUFF,#80,FUNC
        CMPB    TSTATUS+2,#0
        BGTR    450$
        MOVL    #1,PARA1
        MOVAL   NEXT,JMPADR
        BRW     800$
450$:
        MOVZWL  TSTATUS+2,R3
        MOVAL   FUNC,R4
500$:
        CMPB    (R4),#^A/ /
        BNEQ    550$
        INCL    R4
        SOBGTR  R3,500$
        BRB     650$
550$:
        CMPB    (R4),#^A/a/
        BLSSU   600$
        CMPB    (R4),#^A/z/
        BGTRU   650$
        SUBB2   #^X20,(R4)
600$:
        CMPB    (R4),#^A/A/
        BLSS    650$
        CMPB    (R4),#^A/Z/
        BGTR    650$
        INCL    R4
        SOBGTR  R3,550$
650$:
        CLRL    JMPADR
        CLRL    MFLAG
        CLRL    SETMASK
        CLRL    SHOMASK
        CLRB    DPBFLG
        CLRB    RFLAG
        CLRB    LGFLAG
        CLRB    POSFLG
        MOVL    #TPA$K_COUNT0,TPBLK+TPA$L_COUNT
        MOVL    #TPA$M_ABBRFM,TPBLK+TPA$L_OPTIONS
        MOVZWL  TSTATUS+2,TPBLK+TPA$L_STRINGCNT
        MOVAL   FUNC,TPBLK+TPA$L_STRINGPTR
        PUSHAL  VFE_KEY
        PUSHAL  VFE_STATE
        PUSHAL  TPBLK
        CALLS   #3,G^LIB$TPARSE
        BLBS    R0,700$
        BSBW    ERROUT
        BRW     100$
700$:
        CMPL    #0,JMPADR
        BNEQ    800$
        BRW     100$
800$:
        RSB
        .PAGE
        .SBTTL  FPARSE - Parse file spec w/qualifiers
FPARSE::
        MOVL    #TPA$K_COUNT0,TPBLK+TPA$L_COUNT
        MOVL    #TPA$M_BLANKS!TPA$M_ABBRFM,TPBLK+TPA$L_OPTIONS
        MOVZWL  DESC,TPBLK+TPA$L_STRINGCNT
        MOVL    DESC+4,TPBLK+TPA$L_STRINGPTR
        CLRW    FDESC
        CLRL    SETMASK
        PUSHAL  VFE_KEY
        PUSHAL  FP1
        PUSHAL  TPBLK
        CALLS   #3,G^LIB$TPARSE
        BLBS    R0,200$
        BSBW    ERROUT
        BRB     600$
200$:
        TSTB    OVRFLG
        BEQL    800$
        TSTB    WRTFLG
        BEQL    800$
        OUTMSG  #NWOL,NWOMSG
        CLRW    OVRWRT
600$:
        CLRL    R0
800$:
        RSB
        .PAGE
        .SBTTL  Parser state table

COMMA=^A/,/
DQUOTE=^A/"/
SQUOTE=^A/'/
QUEST=^A/?/

        $INIT_STATE  VFE_STATE,VFE_KEY

        $STATE  BEGIN
        $TRAN   TPA$_DECIMAL,DEFGET,,,PARA1
        $TRAN   'ALPHA',PARAM2P,ALPHINIT
        $TRAN   'ASCII',PARAM2P,AINIT,ASCII,JMPADR
        $TRAN   'ADD',ADDPAR,ADDINI,ADD,JMPADR
        $TRAN   'BINARY',PARAM2P,AINIT,BINARY,JMPADR
        $TRAN   'CHANGE',CPARA,,CHANGE,JMPADR
        $TRAN   'CUT',PARAM2,CINIT,CUT,JMPADR
        $TRAN   'DIFFERENCES',PARAM2,DPINIT,DIFF,JMPADR
        $TRAN   'DATE',PARAM2P,DTINIT,DATE,JMPADR
        $TRAN   'EXIT',TSTEOS,,EXIT,JMPADR
        $TRAN   'EBCDIC',PARAM2P,AINIT,EBCDIC,JMPADR
        $TRAN   'EOF',TSTEOS,,EOF,JMPADR
        $TRAN   'FILE',FPARM
        $TRAN   'GET',PARAM1,GINIT,READ,JMPADR
        $TRAN   'HEX',PARAM2P,AINIT,HEX,JMPADR
        $TRAN   'HELP',HLPPAR,,HELP,JMPADR
        $TRAN   'IBYTE',PARAM2P,AINIT,IBYTE,JMPADR
        $TRAN   'IWORD',PARAM2P,IWINIT,IWLDSP,JMPADR
        $TRAN   'ILONG',PARAM2P,ILINIT,IWLDSP,JMPADR
        $TRAN   'LOCATE',LPARA,,LOCATE,JMPADR
        $TRAN   'LGLOBAL',LPARA,LGINIT,LOCATE,JMPADR
        $TRAN   'LAST',TSTEOS,,LAST,JMPADR
        $TRAN   'MULTI',PARAM2P,AINIT,MULTI,JMPADR
        $TRAN   'MOVE',NPARA,NINIT,MOVE,JMPADR
        $TRAN   'NEXT',NPARA,NINIT,NEXT,JMPADR
        $TRAN   'PASTE',PARAM2,DPINIT,PASTE,JMPADR
        $TRAN   'RECORD',PARAM2,RINIT,RECORD,JMPADR
        $TRAN   'REWIND',TSTEOS,,REWIND,JMPADR
        $TRAN   'SET',SETPAR,UCASE,SETCMD,JMPADR
        $TRAN   'SHOW',SHOPAR,UCASE,SHOCMD,JMPADR
        $TRAN   'TOP',TSTEOS,,TOP,JMPADR
        $TRAN   'WRITE',TSTEOS,,WRITEDISK,JMPADR
        $TRAN   '+',NPARA2,NINIT,NEXT,JMPADR
        $TRAN   '-',NPARA2,NINITM,NEXT,JMPADR
        $TRAN   TPA$_EOS,TPA$_EXIT,NINIT,NEXT,JMPADR
        $TRAN   TPA$_LAMBDA,TPA$_EXIT,BDCOMM

        $STATE  DEFGET
        $TRAN   TPA$_EOS,TPA$_EXIT,,READ,JMPADR

        $STATE  PARAM2P
        $TRAN   '/',,UCASE
        $TRAN   TPA$_LAMBDA,PARAM2
        $STATE
        $TRAN   'PASTE',,PASTON
        $STATE  PARAM2
        $TRAN   TPA$_DECIMAL,,HEXTST,,PARA1
        $TRAN   TPA$_HEX,,,,PARA1
        $TRAN   COMMA,P2S2
        $TRAN   ':',P2S3,RECCHK
        $TRAN   TPA$_EOS,TPA$_EXIT
        $STATE
        $TRAN   COMMA,P2S2
        $TRAN   ':',P2S3,RECCHK
        $TRAN   TPA$_EOS,TPA$_EXIT,SINGLE
        $STATE  P2S2
        $TRAN   TPA$_DECIMAL,TSTEOS,,,PARA2
        $STATE  P2S3
        $TRAN   TPA$_DECIMAL,,HEXTST,,PARA2
        $TRAN   TPA$_HEX,,,,PARA2
        $STATE
        $TRAN   TPA$_EOS,TPA$_EXIT,OFFSET

        $STATE  PARAM1
        $TRAN   TPA$_DECIMAL,TSTEOS,,,PARA1
        $TRAN   TPA$_EOS,TPA$_EXIT

        $STATE  NPARA
        $TRAN   '-',,NINITM
        $TRAN   '+'
        $TRAN   TPA$_LAMBDA
        $STATE  NPARA2
        $TRAN   TPA$_DECIMAL,,,,PARA1
        $TRAN   TPA$_LAMBDA
        $STATE
        $TRAN   TPA$_EOS,TPA$_EXIT,NEGATE

        $STATE  ADDPAR
        $TRAN   '-',,,1,MFLAG
        $TRAN   '+'
        $TRAN   TPA$_LAMBDA
        $STATE
        $TRAN   'H',HEXX
        $TRAN   'h',HEXX
        $TRAN   '0',OCT
        $TRAN   TPA$_DECIMAL,ADDP2,ACCUML
        $STATE  HEXX
        $TRAN   TPA$_HEX,ADDP2,ACCUML
        $STATE  OCT
        $TRAN   TPA$_OCTAL,ADDP2,ACCUML
        $STATE  ADDP2
        $TRAN   COMMA,ADDPAR
        $TRAN   TPA$_EOS,TPA$_EXIT

        $STATE  CPARA
        $TRAN   TPA$_DECIMAL,,HEXTST,,PARA1
        $TRAN   TPA$_HEX,,,,PARA1
        $TRAN   '*',,CHGLOC
        $TRAN   TPA$_EOS,,CHGLOC
        $STATE
        $TRAN   TPA$_EOS,TPA$_EXIT,CNULL
        $TRAN   COMMA,QPARSE

        $STATE  LPARA
        $TRAN   TPA$_EOS,TPA$_EXIT,LNULL
        $TRAN   TPA$_LAMBDA,QPARSE

        $STATE  QPARSE
        $TRAN   TPA$_HEX,TSTEOS,CNUM
        $TRAN   '+',DECCL
        $TRAN   '-',DECCL,,1,MFLAG
        $TRAN   SQUOTE,,SPACON,,QCHAR
        $TRAN   DQUOTE,,SPACON,,QCHAR
        $STATE
        $TRAN   !QSTRING,,,,QDESC
        $STATE
        $TRAN   TPA$_EOS,TPA$_EXIT,CHKSTR
        $TRAN   TPA$_ANY,TSTEOS,CHKSTR

        $STATE  QSTRING
        $TRAN   TPA$_ANY,QSTRING,TESTQ
        $TRAN   TPA$_LAMBDA,TPA$_EXIT

        $STATE  DECCL
        $TRAN   TPA$_DECIMAL,TSTEOS,CDEC

        $STATE  FPARM
        $TRAN   QUEST,TSTEOS,,SHOFILE,JMPADR
        $TRAN   TPA$_LAMBDA,TPA$_EXIT,GENDESC,GETFILE,JMPADR

        $STATE  HLPPAR
        $TRAN   TPA$_BLANK
        $TRAN   TPA$_LAMBDA
        $STATE
        $TRAN   TPA$_LAMBDA,TPA$_EXIT,GENDESC

        $STATE  SETPAR
        $TRAN   !SETSUB,TSTEOS
        $TRAN   TPA$_LAMBDA,TPA$_EXIT,BDCOMM

        $STATE  SHOPAR
        $TRAN   'MODES',TSTEOS,,<^X1>,SHOMASK
        $TRAN   'CHANGE',TSTEOS,,<^X2>,SHOMASK
        $TRAN   'LOCATE',TSTEOS,,<^X4>,SHOMASK
        $TRAN   'PASTE',TSTEOS,,<^X8>,SHOMASK
        $TRAN   'FILE',TSTEOS,,<^X10>,SHOMASK
        $TRAN   'DEVICE',TSTEOS,,<^X10>,SHOMASK
        $TRAN   'ALL',TSTEOS,,<^X1F>,SHOMASK
        $TRAN   TPA$_LAMBDA,TPA$_EXIT,BDCOMM

        $STATE  FP1
        $TRAN   TPA$_BLANK,,UCASE
        $TRAN   TPA$_LAMBDA,,UCASE

        $STATE  FP2
        $TRAN   '/',FP3
        $TRAN   TPA$_EOS,TPA$_EXIT
        $TRAN   TPA$_LAMBDA,FP4

        $STATE  FP3
        $TRAN   'OVERRIDE',FP1,SETOVR
        $TRAN   'WRITE',FP1,SETWRT
        $TRAN   'NOREWIND',FP3A,CHAR3
        $TRAN   'REWIND',FP1
        $TRAN   'POSITION',FP3B
        $TRAN   TPA$_LAMBDA,,TSTINIT
        $STATE
        $TRAN   !SETSUB,FP1
        $STATE  FP3A
        $TRAN   TPA$_LAMBDA,FP1,CLRREW
        $STATE  FP3B
        $TRAN   !POSSUB,FP1

        $STATE  FP4
        $TRAN   TPA$_LAMBDA,,TESTF
        $STATE
        $TRAN   !FSTRING,,,,FDESC

        $STATE  FP5
        $TRAN   TPA$_BLANK,FP2
        $TRAN   TPA$_LAMBDA,FP2

        $STATE  SETSUB
        $TRAN   'LOG',LOGPAR,,<^X1>,SETMASK
        $TRAN   'NOLOG',TPA$_EXIT,CHAR3,<^X1000>,SETMASK
        $TRAN   'DISPLAY',TPA$_EXIT,,<^X2>,SETMASK
        $TRAN   'NODISPLAY',TPA$_EXIT,CHAR3,<^X2000>,SETMASK
        $TRAN   'SIGN',TPA$_EXIT,,<^X4>,SETMASK
        $TRAN   'NOSIGN',TPA$_EXIT,CHAR3,<^X4000>,SETMASK
        $TRAN   'HEADER',TPA$_EXIT,,<^X8>,SETMASK
        $TRAN   'NOHEADER',TPA$_EXIT,CHAR3,<^X8000>,SETMASK
        $TRAN   'CASE',TPA$_EXIT,,<^X10>,SETMASK
        $TRAN   'NOCASE',TPA$_EXIT,CHAR3,<^X10000>,SETMASK
        $TRAN   'RADIX',RADPAR
        $TRAN   'BUFF',BUFPAR
        $TRAN   'SKIP',SKIPPAR
        $TRAN   'WIDTH',WIDPAR
        $TRAN   'CHARSET',CHARPAR
        $TRAN   'POSITION',POSPAR

        $STATE  LOGPAR
        $TRAN   '='
        $TRAN   TPA$_LAMBDA,TPA$_EXIT,LOGDEF
        $STATE
        $TRAN   !FSTRING,TPA$_EXIT,,,DESC

        $STATE  RADPAR
        $TRAN   '='
        $STATE
        $TRAN   'HEX',TPA$_EXIT,,<^X20>,SETMASK
        $TRAN   'DECIMAL',TPA$_EXIT,,<^X20000>,SETMASK

        $STATE  BUFPAR
        $TRAN   '=',,,<^X100000>,SETMASK
        $STATE
        $TRAN   TPA$_DECIMAL,TPA$_EXIT,,,NBUFCT

        $STATE  SKIPPAR
        $TRAN   '='
        $STATE
        $TRAN   'FAST',TPA$_EXIT,,<^X100>,SETMASK
        $TRAN   'SLOW',TPA$_EXIT,,<^X200>,SETMASK
        $TRAN   'NORMAL',TPA$_EXIT,,<^X400>,SETMASK

        $STATE  WIDPAR
        $TRAN   '=',,,<^X800>,SETMASK
        $STATE
        $TRAN   TPA$_DECIMAL,TPA$_EXIT,,,NEWWID

        $STATE  CHARPAR
        $TRAN   '='
        $STATE
        $TRAN   'EBCDIC',TPA$_EXIT,,<^X40>,SETMASK
        $TRAN   'ASCII',TPA$_EXIT,,<^X40000>,SETMASK

        $STATE  POSPAR
        $TRAN   !POSSUB,TPA$_EXIT

        $STATE  POSSUB
        $TRAN   '=',,POSINIT
        $STATE
        $TRAN   '('
        $TRAN   TPA$_DECIMAL,TPA$_EXIT,,,POSBLK
        $STATE
        $TRAN   TPA$_DECIMAL,,,,POSFIL
        $STATE
        $TRAN   ':'
        $STATE
        $TRAN   TPA$_DECIMAL,,,,POSBLK
        $STATE
        $TRAN   ')',TPA$_EXIT

        $STATE  FSTRING
        $TRAN   TPA$_ANY,,FSSL

        $STATE  FS1
        $TRAN   TPA$_BLANK,TPA$_EXIT
        $TRAN   TPA$_ANY,FS1,FSSL
        $TRAN   TPA$_LAMBDA,TPA$_EXIT

        $STATE  TSTEOS
        $TRAN   TPA$_EOS,TPA$_EXIT

        $END_STATE
        .PAGE
        .SBTTL  Action routines

ALPHINIT:
        .WORD   0
        MOVAL   ASCII,JMPADR
        TSTB    EBCFLG
        BEQL    100$
        MOVAL   EBCDIC,JMPADR
100$:
        MOVL    #1,DSPCNT
        CLRL    PARA1
        MNEGL   #1,PARA2
        RET

AINIT:
        .WORD   0
        MOVL    #1,DSPCNT
        CLRL    PARA1
        MNEGL   #1,PARA2
        RET

CINIT:
        .WORD   0
        MOVL    #1,DSPCNT
        CLRL    PARA1
        MOVL    CURBCT,PARA2
        INCL    MFLAG
        RET

DPINIT:
        .WORD   0
        MOVL    #1,DSPCNT
        MOVL    PBOFF,PARA1
        SUBL3   PBOFF,CURBCT,PARA2
        CMPL    PARA2,PBBCT
        BLEQ    100$
        MOVL    PBBCT,PARA2
100$:
        DECL    MFLAG
        RET

DTINIT:
        .WORD   0
        MOVL    #8,DSPCNT
        MNEGL   #1,PARA1
        RET

IWINIT:
        .WORD   0
        MOVL    #2,DSPCNT
        CLRL    PARA1
        MNEGL   #1,PARA2
        MOVL    #8,WLPARM
        MOVL    #6,WLPOSN
        RET

ILINIT:
        .WORD   0
        MOVL    #4,DSPCNT
        CLRL    PARA1
        MNEGL   #1,PARA2
        MOVL    #4,WLPARM
        MOVL    #11,WLPOSN
        RET

LGINIT:
        .WORD   0
        MOVB    #1,LGFLAG
        RET

RINIT:
        .WORD   0
        MNEGL   #1,PARA1
        MNEGL   #1,PARA2
        MOVB    #1,RFLAG
        RET

PASTON:
        .WORD   0
        INCB    DPBFLG
        DIVL3   DSPCNT,PBBCT,PARA2
        RET

HEXTST:
        .WORD   0
        TSTB    HEXFLG
        BEQL    100$
        CLRL    R0
100$:
        RET

RECCHK:
        .WORD   0
        TSTB    RFLAG
        BEQL    100$
        CLRL    R0
100$:
        RET

SINGLE:
        .WORD   0
        TSTL    MFLAG
        BNEQ    100$
        MOVL    #1,PARA2
        BRB     200$
100$:
        SUBL3   PARA1,CURBCT,PARA2
        TSTL    MFLAG
        BGTR    200$
        CMPL    PARA2,PBBCT
        BLEQ    200$
        MOVL    PBBCT,PARA2
200$:
        RET

OFFSET:
        .WORD   0
        SUBL2   PARA1,PARA2
        ADDL2   DSPCNT,PARA2
        BGTR    100$
        CLRL    PARA2
100$:
        DIVL2   DSPCNT,PARA2
        RET

ADDINI:
        .WORD   0
        CLRL    ACCUM
        CLRL    MFLAG
        RET

ACCUML:
        .WORD   0
        CMPL    MFLAG,#0
        BEQL    100$
        SUBL2   TPA$L_NUMBER(AP),ACCUM
        BRB     200$
100$:
        ADDL2   TPA$L_NUMBER(AP),ACCUM
200$:
        CLRL    MFLAG
        RET

GINIT:
        .WORD   0
        MOVL    CURBLK,PARA1
        RET

NINIT:
        .WORD   0
        CLRL    MFLAG
        MOVL    #1,PARA1
        RET

NINITM:
        .WORD   0
        MOVL    #1,MFLAG
        MOVL    #1,PARA1
        RET

NEGATE:
        .WORD   0
        TSTL    MFLAG
        BEQL    100$
        MNEGL   PARA1,PARA1
100$:
        RET

CHGLOC:
        .WORD   0
        MOVL    LPTR,PARA1
        DECL    PARA1
        RET

CNULL:
        .WORD   0
        TSTW    CSTRL
        BGTR    100$
        CLRL    R0
        BRB     200$
100$:
        MOVW    CSTRL,QDESC
        MOVAL   CSTR,QDESC+4
        MOVB    CSTRT,QTYPE
200$:
        RET

LNULL:
        .WORD   0
        CMPW    LSTRL,#0
        BGTR    100$
        CLRL    R0
        BRB     200$
100$:
        MOVW    LSTRL,QDESC
        MOVAL   LSTR,QDESC+4
        MOVB    LSTRT,QTYPE
200$:
        RET

CNUM:
        .WORD   ^M
        MOVAL   QSTR,R6
        MOVL    R6,QDESC+4
        ADDL3   #1,TPA$L_TOKENCNT(AP),R7
        DIVL2   #2,R7
        MOVW    R7,QDESC
        CMPL    R7,#4
        BLEQ    100$
        SUBL3   #4,R7,R8
        MOVC5   #0,BUFF,#0,R8,(R6)
        ADDL2   R8,R6
        MOVL    #4,R7
100$:
        MOVAL   TPA$L_NUMBER(AP),R8
        ADDL2   R7,R8
200$:
        MOVB    -(R8),(R6)+
        SOBGTR  R7,200$
        MOVB    #3,QTYPE
        MOVL    #1,R0
        RET

CDEC:
        .WORD   0
        MOVL    TPA$L_NUMBER(AP),R1
        CMPL    TPA$L_TOKENCNT(AP),#5
        BGTR    600$
        CMPL    TPA$L_TOKENCNT(AP),#3
        BGTR    400$
        CMPL    R1,#255
        BGTR    400$
        TSTL    MFLAG
        BEQL    300$
        CMPL    R1,#128
        BGTR    400$
        MNEGL   R1,R1
300$:
        MOVB    R1,QSTR
        MOVW    #1,QDESC
        BRB     850$
400$:
        CMPL    R1,#65535
        BGTR    600$
        TSTL    MFLAG
        BEQL    500$
        CMPL    R1,#32768
        BGTR    600$
        MNEGL   R1,R1
500$:
        MOVW    R1,QSTR
        MOVW    #2,QDESC
        BRB     850$
600$:
        TSTL    MFLAG
        BEQL    800$
        TSTL    R1
        BGEQ    700$
        CLRL    R0
        BRB     900$
700$:
        MNEGL   R1,R1
800$:
        MOVL    R1,QSTR
        MOVW    #4,QDESC
850$:
        MOVAL   QSTR,QDESC+4
        MOVB    #1,QTYPE
        TSTL    MFLAG
        BEQL    900$
        MOVB    #2,QTYPE
900$:
        RET

SPACON:
        .WORD   0
        MOVL    #TPA$M_ABBRFM!TPA$M_BLANKS,TPA$L_OPTIONS(AP)
        RET

CHKSTR:
        .WORD   0
        CLRB    QTYPE
        MOVL    #TPA$M_ABBRFM,TPA$L_OPTIONS(AP)
        CMPW    QDESC,#0
        BGTR    100$
        CLRL    R0
100$:
        RET

TESTQ:
        .WORD   0
        CMPB    TPA$B_CHAR(AP),QCHAR
        BNEQ    100$
        CLRL    R0
100$:
        RET

UCASE:
        .WORD   ^M
        MOVL    TPA$L_STRINGCNT(AP),R2
        BLEQ    900$
        MOVL    TPA$L_STRINGPTR(AP),R3
100$:
        CMPB    (R3),#^A/a/
        BLSS    200$
        CMPB    (R3),#^A/z/
        BGTR    200$
        SUBB2   #^X20,(R3)
200$:
        INCL    R3
        SOBGTR  R2,100$
900$:
        RET

CHAR3:
        .WORD   0
        CMPL    TPA$L_TOKENCNT(AP),#3
        BGEQ    100$
        CLRL    R0
100$:
        RET

GENDESC:
        .WORD   0
        MOVW    TPA$L_STRINGCNT(AP),DESC
        MOVL    TPA$L_STRINGPTR(AP),DESC+4
        RET

LOGDEF:
        .WORD   0
        MOVQ    DEFLOG,DESC
        RET

BDCOMM:
        .WORD   0
        OUTMSG  #BDCL,BDC
        CLRL    JMPADR
        RET

SETOVR:
        .WORD   0
        MOVB    #1,OVRFLG
        RET

SETWRT:
        .WORD   0
        MOVB    #1,WRTFLG
        RET

CLRREW:
        .WORD   0
        MOVB    #1,NOREW
        RET

TSTINIT:
        .WORD   0
        TSTB    INITFLG
        BNEQ    100$
        CLRL    R0
100$:
        RET

TESTF:
        .WORD   0
        TSTW    FDESC
        BEQL    100$
        CLRL    R0
100$:
        RET

POSINIT:
        .WORD   0
        MOVB    #1,POSFLG
        MOVL    CURFIL,POSFIL
        RET

FSSL:
        .WORD   0
        CMPB    TPA$B_CHAR(AP),#^A./.
        BNEQ    100$
        CLRL    R0
100$:
        RET
        .PAGE
        .SBTTL  Data definitions

        .PSECT  DATA,WRT,NOEXE

SOLDSK0: .ASCID /!UL> /
SOLDSK1: .ASCID /!UL(!UL)> /
SOLTP0: .ASCID  /!SL:!SL> /
SOLTP1: .ASCID  /!SL:!SL(!UL)> /
FUNC:   .BLKB   80

DEFLOG: .ASCID  /VFE.LOG/

BDC:    .ASCII  /Invalid command./
BDCL=.-BDC

NWOMSG: .ASCII  "/OVERRIDE and /WRITE may not be used together."
NWOL=.-NWOMSG

TPBLK:  .BLKB   TPA$K_LENGTH0

INITFLG:: .BYTE 1
JMPADR:: .LONG  0
SETMASK:: .LONG 0
SHOMASK:: .LONG 0
PARA1:: .LONG   0
        .LONG   0
PARA2:: .LONG   0

MFLAG:  .LONG   0
DPBFLG:: .BYTE  0
RFLAG:  .BYTE   0

QCHAR:  .BYTE   0
QDESC:: .QUAD   0
QTYPE:: .BYTE   0
QSTR:   .BLKB   100

        .END
$*$*EOD*$*$
$ checksum COMMAND.MAR
$ if checksum$checksum .ne. check_sum then -
$   write sys$output "Checksum failed, file probably corrupted"
$ check_sum = 1327248427
$ write sys$output "Creating VFE.DOC"
$ create VFE.DOC
$ DECK/DOLLARS="$*$*EOD*$*$"
     The following files are contained in this release (V2.0) of VFE:

     VFE.DOC - This document
     VFENEW.DOC - A description of changes from V1.0 to V2.0
     VFE.EXE - The VFE utility in executable format (linked under VMS 4.2)
     VFE.HLB - The VFE help file in library format
     VFE.RNH - Source for the help file in runoff format

               Source and objects for the VFE utility:

     VFE, COMMAND, DISPLAY, FILEHDLR, TERMHDLR, VFELIB

-----------------------------------------------------------------------------

     To install VFE:

1) Copy the file VFE.HLB to SYS$HELP.  This is the default - you may decide  to
   keep  the  help  file in a different directory, in which case line # 1086 of
   VFE.MAR must be changed and a new executable produced.

2) Copy the file VFE.EXE to SYS$SYSTEM, or wherever else you choose to keep it.
   (Relink first if your system level is earlier than VMS 4.2 - see below)

3) Modify the LOGIN.COM file(s) of the users who are to use VFE by inserting:

   $ VFE:==$VFE                       (if VFE resides in SYS$SYSTEM)
   $ VFE:==$device:[directory]VFE     (otherwise)   is mandatory!

------------------------------------------------------------------------------

To compile a single module, set your default to a directory which contains  the
VFE source (be sure VFELIB.MLB is present) and type:

   $ MACRO 

You will need to produce a new executable if you change a module or if your VMS
level is lower than 4.2.  To do this, type:

   $ LINK VFE+COMMAND+DISPLAY+FILEHDLR+TERMHLDR

No special options or parameters are required.

To produce a new HELP library file, type:

   $ RUNOFF VFE.RNH
   $ LIBRARY/CREATE/HELP VFE.HLB VFE.HLP

------------------------------------------------------------------------------

To execute VFE once it is installed and the symbol VFE is known, type:

   $ VFE 

The  parameter is required.   If  not  supplied,  a  file  name  will  be
solicited.  Commands cannot be given until a file is open for edit.

Commands are solicited with the current block number followed with  a  "greater
than"  sign  (>).   Commands  are  documented  in the help file.  A list of all
commands can be obtained by typing HELP.  Specific info on a particular command
is displayed by typing HELP .  Most commands can be abbreviated to one
or two letters.  The  unessential  part  of  each  command  word  is  shown  in
parenthesis in the help file.

The signon  line  has  optional  parameters  which  are  not  shown  above.   A
description of the complete signon line is available via HELP SIGNON.

------------------------------------------------------------------------------

Read-only mode is the default access mode.  In  read-only  mode,  all  commands
except  for  WRITE  are  allowed.   Even  for experienced users, it is strongly
suggested that VFE be operated only in read-only  mode  when  examining  system
files.   Critical  files for which there exist no current backup should also be
examined in read-only mode.

------------------------------------------------------------------------------

When using VFE interactively, control-C interrupts are recognized  and  can  be
used  to  interrupt a large volume of output or a LOCATE or LGLOBAL search of a
large file.  In either case, the user will be left positioned at the last block
processed.   It  is  perfectly  valid,  for example, to type LOCATE "ABC", wait
awhile, control-C, and then another LOCATE to continue the search.   Since  the
block number is displayed at every prompt, this is particularly handy when only
a part of a very large file is to be searched.

------------------------------------------------------------------------------

Questions, comments, and suggestions for improvements will be gladly  accepted.
If  you  have  a suggested improvement, please include a description of how you
would like to see it implemented.  Address all correspondence to:

     Ward Condit
     Maricopa Community Colleges
     P.  O.  Box 13349
     Phoenix, Az.  85002
     (602) 267-4403
$*$*EOD*$*$
$ checksum VFE.DOC
$ if checksum$checksum .ne. check_sum then -
$   write sys$output "Checksum failed, file probably corrupted"
$ check_sum = 319015572
$ write sys$output "Creating VFENEW.DOC"
$ create VFENEW.DOC
$ DECK/DOLLARS="$*$*EOD*$*$"
                            * VFE version 2.0 *

     VFE level 2.0 contains many significant enhancements to the earlier  level
(1.0).  The new version contains more than twice as many lines of code, and has
been broken into five modules for  compilation  efficiency.   It  is,  however,
almost totally upward-compatible with version 1.0.

     This level has been run exclusively on VMS 4+ systems.  I do  not  have  a
version  3  system  to test with, but do not know of any limitations that would
preclude operation on such a system, other than the required relink.

     Following are the major enhancements in VFE 2.0:

   - Operation has been extended to include tapes and disk devices.  Tapes must
     be  mounted  FOREIGN  and  are  read-only.   Disk  devices  require LOG_IO
     privilege to edit, and are also read-only unless FOREIGN mounted.

   - The original block restrictions on CUT and PASTE have been eliminated.   A
     new  command,  SET  BUFF,  is  available  for  disk operation which allows
     expansion of the current and paste buffers.  "Chunks" of data which can be
     up to 50 blocks in size and begin at an arbitrary location can be compared
     and moved within a file or between files.

   - The RECORD command will now search for the record start address  within  a
     positioned block if none is given.  This has proven to be extremely useful
     for examining very large print files at locations hundreds or thousands of
     blocks  from  the beginning.  There is also a new output format, activated
     by SET NOHEADER, which causes  only  the  record  data  to  be  displayed,
     producing output similar to TYPE.

   - The EBCDIC character set is now fully supported for display,  change,  and
     locate operations.  SET CHARSET can be used to select the character set to
     be used (ASCII is the default).

   - The LOCATE command now can search in case-insensitive mode with  character
     string  data,  as  directed  by  the  SET  NOCASE command.  There is a new
     command, LGLOBAL, which can search for all occurrences of a target  string
     within a file or device.

   - There are two new display  formats,  MULTI  and  BINARY.   MULTI  displays
     simultaneously in character and hex format.

   - Most display commands  now  output  and  accept  hex  byte  addresses,  as
     directed  by  SET  RADIX.   Ranges  can  now be given in either counted or
     address-delimited forms (see HELP RANGE).

   - VFE now is aware of SYS$INPUT and SYS$OUTPUT, so can be  run  from  within
     command files and from batch jobs.

   - Most display commands now have a normal and a wide output size.  The  wide
     format can be used to save paper and display more information on a screen.
     There is now a SET WIDTH command  which  can  change  the  terminal  width
     dynamically.

   - A SHOW command has been added to  display  useful  information  about  the
     current VFE environment.

   - The VFE command line can now be used to specify default  SET  options  and
     file qualifiers.  See HELP SIGNON.

     These and other minor enhancements have been designed as much as  possible
to  be upward-compatible with VFE 1.0.  The following are changes which are not
compatible with the earlier version.

   - The ROTATE command has been removed, since the current and  paste  buffers
     can  now be of different lengths.  Contents of the paste buffer can now be
     examined by adding the /PASTE option to most display commands.

   - The range specification on DIFFERENCES originally applied to both buffers.
     Since  the  paste  buffer can now be cut with any desired byte offset, all
     operations with  it  begin  at  its  own  byte  zero,  and  the  range  on
     DIFFERENCES  only  applies  to the current buffer.  The following examples
     illustrate this change:

  V1.0: CUT  DIFF          V2.0: CUT          DIFF (no change)
  V1.0: CUT  DIFF 300,100  V2.0: CUT 300,100  DIFF 300,100
  V1.0: CUT  DIFF 300,100  V2.0: CUT 300,100  DIFF (range defaults to CUT rng)
  V1.0: CUT  DIFF 300      V2.0: CUT 300,1    DIFF (count doesn't default to 1)

   - The method of specifiying WRITE access to a file has changed.  The  /WRITE
     qualifier  is  used  now  instead of the "pound" sign (#).  Information on
     specification of /WRITE is now in the help file.  It  was  felt  that  few
     users would wish to restrict this type of access.  Anyone wishing to do so
     with the new version may remove line 290 of COMMAND and edit the help file
     source to their liking.

   - The command used to display the current file has been changed from "F?" to
     SHOW FILE.  The original method, though undocumented, still operates.
$*$*EOD*$*$
$ checksum VFENEW.DOC
$ if checksum$checksum .ne. check_sum then -
$   write sys$output "Checksum failed, file probably corrupted"
$ exit