; ************************** AMUS Program Label ******************************
; Filename: WLDSCN.M68 -> WLDSCN.OBJ -> WLDSCN.LIB          Date: 02/06/90
; Category: UTIL         Hash Code: 275-510-373-412      Version: 2.0(106)
; Initials: ULTR/AM      Name: DAVID PALLMANN
; Company: ULTRASOFT CORPORATION                   Telephone #: 5163484848
; Related Files:
; Min. Op. Sys.: AMOSL 1.3B                    Expertise Level: BEG
; Special: .M68 WLDSCN then .LIBLIT WLDSCN=WLDSCN to make WLDSCN.LIB
; Description: Wildcard directory scanner.  Supports traditional and
; extended directory formats.  Required by many utilities that perform
; wildcard directory processing (such as D.LIT). Requires 2.0 assembler
; ****************************************************************************

;****************************************************************************
;*                                                                          *
;*                                 WLDSCN                                   *
;*                       Wildcard Directory Scanner                         *
;*                                                                          *
;****************************************************************************
;Copyright (C) 1986, 1989 UltraSoft Corp.  All Rights Reserved.
;
;Written by: David Pallmann
;
;Edit History:
;1.0(100)  20-Dec-83 created. /DFP
;1.1(101)  09-Feb-84 add hyphen ('not') command line prefix support. /DFP
;1.2(102)  12-Sep-86 add WLIST and WFULL calls. /DFP
;1.3(103)  12-Sep-86 add support of AMOS/L 1.3 user-defineable ersatz
;                    devices. /DFP
;1.4(104)  15-Sep-86 allow PPN spec before or after file spec. /DFP
;1.5(105)  27-Sep-86 add @ (alphabetic wildcard) and # (digit wildcard)
;                    support. /DFP
;1.6(106)  05-May-88 fix bug with device drivers not in system memory. /DFP
;1.6A(107) 03-Oct-88 change CMMx's to CMP's where allowed for compacter
;                    code. /DFP
;1.7(108)  30-Dec-88 add support for AMOS 2.0 extended directory
;                    structure. /DFP
;1.7A(109) 30-Dec-88 add WS$DEL flag to return deleted file entries. /DFP
;1.8(110)  19-Feb-89 add {output=}input support. /DFP
;1.8(111)  21-Apr-89 don't process deleted PPNs!. /DFP
;1.8(112)  14-Jul-89 fix problem with redirection & length of filenames. /DFP
;1.8(113)  27-Nov-89 fix ersatz/non-DSK device problems. /DFP
;1.9(114)  06-Feb-90 fix bug where we returned deleted files when processing
;                    extended directories. /DFP

       INTERN  W.INIT,W.SPEC,W.SCAN,W.FULL,W.LIST,W.DEL,W.OUT

       SEARCH  SYS
       SEARCH  SYSSYM

;MFD symbols (traditional directory structure)

       MF.LNK  =506.
       MF.PPN  =0
       MF.UFD  =2
       MF.SIZ  =8.

;UFD symbols (traditional directory structure)

       UF.FIL  =0
       UF.EXT  =4
       UF.BLK  =6
       UF.ACT  =10
       UF.LNK  =12
       UF.SIZ  =14

;extended directory MFD entry

       .OFINI
       .OFDEF  D$TYP,  4               ; flags
       .OFDEF  D$PRT,  4               ; protection code
       .OFDEF  D$DAT,  4*3             ; creation, update, backup dates
       .OFDEF  D$NXT,  4               ; pointer to next directory level
       .OFDEF  D$CUR,  4               ; reserved
       .OFDEF  D$PRV,  4               ; reserved
       .OFDEF  D$NAM,  6               ; account information
       .OFDEF  D$SIZ                   ; size of entry

;extended directory UFD entry

       .OFINI
       .OFDEF  D$TYP,  4               ; flags
       .OFDEF  D$PRT,  4               ; protection code
       .OFDEF  D$DAT,  4*3             ; creation, update, backup dates
       .OFDEF  D$BAS,  4               ; base of file
       .OFDEF  D$FSZ,  4               ; file size
       .OFDEF  D$RSV,  2               ; default record size
       .OFDEF  D$LSZ,  2               ; bytes in last block
       .OFDEF  D$NAM,  6               ; filename information
       .OFDEF  D$SIZ                   ; size of entry

;impure area

       .OFINI
       .OFDEF  WS.DDB,D.DDB            ; DDB for disk I/O
       .OFDEF  WS.REN,6                ; rename area                   [109]
       .OFDEF  WS.DEV,4                ; device code RAD50             [103]
       .OFDEF  WS.DRV,2                ; drive number
       .OFDEF  WS.FIL,6                ; filename
       .OFDEF  WS.EXT,4                ; extension
       .OFDEF  WS.PRG,3                ; programmer number
       .OFDEF  WS.PRJ,3                ; project number
       .OFDEF  WS.TMP,10.              ; temporary storage
       .OFDEF  WS.DFX,4                ; default extension
       .OFDEF  WS.DTI,4                ; device table index
       .OFDEF  WS.MFL,4                ; MFD link
       .OFDEF  WS.MFB,512.             ; MFD buffer
       .OFDEF  WS.MFI,4                ; MFD index
       .OFDEF  WS.RPN,2                ; remaining PPNs in MFD block
       .OFDEF  WS.UFL,4                ; UFD link
       .OFDEF  WS.UFB,512.             ; UFD buffer
       .OFDEF  WS.UFI,4                ; UFD index
       .OFDEF  WS.RFN,2                ; remaining files in UFD block
       .OFDEF  WS.FLG,4                ; flags:
               WS$DEV  =1              ;   device was specified
               WS$ALL  =2              ;   device ALL: was specified
               WS$ERZ  =4              ;   erastz device was specified
               WS$FIL  =10             ;   filename was specified
               WS$EXT  =20             ;   extension was specified
               WS$PPN  =40             ;   [P,PN] was specified
               WS$ERR  =100            ;   specification invalid
               WS$UNM  =200            ;   device not mounted
               WS$DNE  =400            ;   device does not exist
               WS$NOT  =1000           ;   'NOT' specified
               WS$EXD  =2000           ;   current device is extended format   [108]
               WS$DEL  =4000           ;   return deleted file entries
               WS$OUT  =10000          ;   redirection (output=input) specified [110]
       .OFDEF  WS.ODV,4                ; redirected device code RAD50  [110]
       .OFDEF  WS.ODR,2                ; redirected drive number       [110]
       .OFDEF  WS.OFL,6                ; redirected filename           [110]
       .OFDEF  WS.OEX,4                ; redirected extension          [110]
       .OFDEF  WS.OPG,3                ; redirected programmer number  [110]
       .OFDEF  WS.OPJ,3                ; redirected project number     [110]
       .OFSIZ  WS.IMP

;macros

DEFINE  MOVBLK  SRC,DST,SIZE
       MOV     #SIZE-1,D0
       LEA     A0,SRC
       LEA     A1,DST
10$$:   MOVB    (A0)+,(A1)+
       DBF     D0,10$$
       ENDM

DEFINE  CEQ     ADDR
       BNE     1$$
       CALL    ADDR
1$$:
       ENDM

DEFINE  CNE     ADDR
       BEQ     1$$
       CALL    ADDR
1$$:
       ENDM

DEFINE  REQ
       BNE     1$$
       RTN
1$$:
       ENDM

DEFINE  BIT     SRC,DST
       MOV     DST,D7
       AND     SRC,D7
       ENDM

DEFINE  BITW    SRC,DST
       MOVW    DST,D7
       ANDW    SRC,D7
       ENDM

PAGE
;************
;*  W.INIT  *
;************
;Function:      Allocate local memory for other WLDSCN calls
;
;Outputs:       A4 - set to base of impure area MEM:WLDSCN.IMP

W.INIT: GETIMP  WS.IMP,A4               ; allocate impure area
       MOVW    #[IMP],-2(A4)           ; name module WLDSCN.IMP
       MOVW    #[SCN],-4(A4)           ;
       MOVW    #[WLD],-6(A4)           ;
       INIT    WS.DDB(A4)              ;
       CLR     WS.DDB+D.DVR(A4)        ;                               [113]
       RTN                             ;

PAGE
;************
;*  W.SPEC  *
;************
;Function:      Process wildcard file specification
;
;Inputs:        A2 - address of file specification
;               A4 - address of work area (normally set-up by W.INIT)
;
;Outputs:       Z  - set if specification is valid, -or- cleared if invalid
;               A2 - updated past file specification

W.SPEC: POP     A6                      ;
       MOV     (A6)+,WS.DFX(A4)        ;
       PUSH    A6                      ;
       CLR     WS.FLG(A4)              ; clear flags
       CMPB    @A2,#'-                 ; leading dash?                 [1.1]
       BNE     10$                     ;  no                           [1.1]
       OR      #WS$NOT,WS.FLG(A4)      ;  yes - set NOT flag           [1.1]
       INC     A2                      ;  bypass dash                  [1.1]
       BYP                             ;  bypass white space           [1.1]
10$:    CALL    DEFDEV                  ; set default device
       CALL    CHKDEV                  ; device specified?
       CEQ     GETDEV                  ; yes - get device
       CALL    DEFFIL                  ; set default filename
       CALL    DEFPPN                  ; set default PPN
       CALL    CHKPPN                  ;
       CEQ     GETPPN                  ;
       CALL    CHKFIL                  ; filename specified?
       CEQ     GETFIL                  ;  yes - get filename
       CALL    DEFEXT                  ; set default extension
       CALL    CHKEXT                  ; extension specified?
       CEQ     GETEXT                  ;  yes - get extension
       CALL    CHKPPN                  ; PPN specified?
       CEQ     GETPPN                  ;  yes - get PPN
       CALL    CHKRED                  ; redirection present?          [110]
       BNE     20$                     ;   no                          [110]
       CALL    GETRED                  ; shift input specs to output   [110]
       BR      10$                     ; go get input specs again      [110]
20$:    CALL    INIMEM                  ; initialize impure area
       CALL    ERROR                   ; display errmsg if required
       RTN                             ;

;************
;*  DEFDEV  *
;************
;Function:      Define default device

DEFDEV: MOV     JOBCUR,A6               ;
       MOVW    JOBDEV(A6),WS.DEV(A4)   ;
       CLRW    WS.DEV+2(A4)            ;                               [113]
       MOVW    JOBDRV(A6),WS.DRV(A4)   ;
       RTN                             ;

;************
;*  CHKDEV  *
;************
;Function:      Check for device specification

CHKDEV: SAVE    A2,D0                   ;
       MOV     #6,D0                   ;
10$:    ALF                             ;
       BEQ     20$                     ;
       NUM                             ;
       BEQ     20$                     ;
       BR      30$                     ;
20$:    INC     A2                      ;
       SOB     D0,10$                  ;
30$:    CMPB    @A2,#':                 ;                               [1.6A]
       BNE     40$                     ;
       OR      #WS$DEV,WS.FLG(A4)      ;
       REST    A2,D0                   ;
       LCC     #PS.Z                   ;
       RTN                             ;
40$:    REST    A2,D0                   ;
       LCC     #0                      ;
       RTN                             ;

;************
;*  GETDEV  *
;************
;Function:      Get device specification

GETDEV: SAVE    A1                      ;
       LEA     A1,WS.DEV(A4)           ;
       CLR     @A1                     ;                               [113]
       PACK                            ;
       SAVE    A1,A2                   ;
       GTDEC                           ;
       MOVW    D1,WS.DRV(A4)           ;
       REST    A1,A2                   ;
       PACK                            ;
10$:    INC     A2                      ;
       CMP     WS.DEV(A4),#[ALL]_16.   ;                               [1.6A]
       BNE     20$                     ;
       OR      #WS$ALL,WS.FLG(A4)      ;
       REST    A1                      ;
       RTN                             ;
20$:    CALL    ERZDEV                  ;
       CALL    PHYDEV                  ;
       REST    A1                      ;
       RTN                             ;

;************
;*  PHYDEV  *
;************
;Function:      Search for mounted physical device matching specification

PHYDEV: MOV     DEVTBL,A6               ;
10$:    CMMW    DV.DEV(A6),WS.DEV(A4)   ;
       BNE     30$                     ;
       CMMW    DV.UNT(A6),WS.DRV(A4)   ;
       BNE     30$                     ;
       BITW    #DV$MNT,DV.FLG(A6)      ;
       BNE     20$                     ;
       OR      #<WS$ERR!WS$UNM>,WS.FLG(A4)
20$:    LCC     #PS.Z                   ;
       RTN                             ;
30$:    TST     @A6                     ;
       BEQ     40$                     ;
       MOV     @A6,A6                  ;
       BR      10$                     ;
40$:    OR      #<WS$ERR!WS$DNE>,WS.FLG(A4)
       LCC     #0                      ;
       RTN                             ;

;************
;*  ERZDEV  *
;************
;Function:      Search for device in ersatz table

ERZDEV: SAVE    A0                      ;
       TST     ERSATZ                  ; new ersatz table defined?
       JNE     ERZNEW                  ;  yes - use it

;no user-defineable ersatz table, use our own definitions of OPR:, SYS:, etc.

ERZOLD: TSTW    WS.DEV+2(A4)            ; >3 character ersatz name?     [113]
       BNE     20$                     ;   yes - automatically not found [113]
       LEA     A0,ERZTBL               ;
10$:    TSTW    @A0                     ;
       BEQ     20$                     ;
       ADD     #4,A0                   ;
       CMMW    -4(A0),WS.DEV(A4)       ;
       BNE     10$                     ;
       BR      30$                     ;
20$:    REST    A0                      ;
       LCC     #0                      ;
       RTN                             ;
30$:    SAVE    A2,D1                   ;
       CLR     D1                      ;
       LEA     A2,WS.PRG(A4)           ;
       MOVB    -2(A0),D1               ;
       MOVB    #40,@A2                 ;
       MOVB    #40,1(A2)               ;
       MOVB    #40,2(A2)               ;
       OCVT    0,OT$MEM                ;
       LEA     A2,WS.PRJ(A4)           ;
       MOVB    -1(A0),D1               ;
       MOVB    #40,@A2                 ;
       MOVB    #40,1(A2)               ;
       MOVB    #40,2(A2)               ;
       OCVT    0,OT$MEM                ;
       REST    A2,D1                   ;
       MOVW    #[DSK],WS.DEV(A4)       ;
       CLRW    WS.DEV+2(A4)            ;                               [113]
       CLRW    WS.DRV(A4)              ;
       OR      #WS$ERZ,WS.FLG(A4)      ;
       REST    A0                      ;
       LCC     #PS.Z                   ;
       RTN                             ;

;process new ersatz device table

ERZNEW: MOV     ERSATZ,A0               ;
10$:    CMM     WS.DEV(A4),EZ.NAM(A0)   ;
       BEQ     20$                     ;
       ADD     #EZ.SIZ,A0              ;
       TSTW    @A0                     ;
       BNE     10$                     ;
       REST    A0                      ;
       LCC     #0                      ;
       RTN                             ;
20$:    SAVE    A2,D1                   ;
       LEA     A2,WS.PRG(A4)           ;
       MOVB    #40,@A2                 ;
       MOVB    #40,1(A2)               ;
       MOVB    #40,2(A2)               ;
       CLR     D1                      ;
       MOVW    EZ.PPN(A0),D1           ;
       RORW    D1,#8.                  ;
       AND     #377,D1                 ;
       OCVT    0,OT$MEM                ;
       LEA     A2,WS.PRJ(A4)           ;
       MOVB    #40,@A2                 ;
       MOVB    #40,1(A2)               ;
       MOVB    #40,2(A2)               ;
       CLR     D1                      ;
       MOVW    EZ.PPN(A0),D1           ;
       AND     #377,D1                 ;
       OCVT    0,OT$MEM                ;
       REST    A2,D1                   ;
       MOVW    EZ.DEV(A0),WS.DEV(A4)   ;
       CLRW    WS.DEV+2(A4)            ;                               [113]
       MOVW    EZ.UNT(A0),WS.DRV(A4)   ;
       OR      #WS$ERZ,WS.FLG(A4)      ;
       REST    A0                      ;
       LCC     #PS.Z                   ;
       RTN                             ;

;************
;*  DEFFIL  *
;************
;Function:      Define default filename

DEFFIL: LEA     A6,WS.FIL(A4)           ;
       MOV     #5,D7                   ;
10$:    MOVB    #'?,(A6)+               ;
       DBF     D7,10$                  ;
       RTN                             ;

;************
;*  CHKFIL  *
;************
;Function:      Check for filename specification

CHKFIL: NUM                             ;
       BEQ     10$                     ;
       ALF                             ;
       BEQ     10$                     ;
       CMPB    @A2,#'?                 ;                               [1.6A]
       BEQ     10$                     ;
       CMPB    @A2,#'@                 ;                               [1.5][1.6A]
       BEQ     10$                     ;                               [1.5]
       CMPB    @A2,#'#                 ;                               [1.5][1.6A]
       BEQ     10$                     ;                               [1.5]
       CMPB    @A2,#'*                 ;                               [1.6A]
       BEQ     10$                     ;
       LCC     #0                      ;
       RTN                             ;
10$:    OR      #WS$FIL,WS.FLG(A4)      ;
       LCC     #PS.Z                   ;
       RTN                             ;

;************
;*  GETFIL  *
;************
;Function:      Get filename

GETFIL: SAVE    A0,D0                   ;
       LEA     A0,WS.FIL(A4)           ;
       MOV     #6,D0                   ;
10$:    ALF                             ;
       BEQ     20$                     ;
       NUM                             ;
       BEQ     20$                     ;
       CMPB    @A2,#'?                 ;
       BEQ     20$                     ;
       CMPB    @A2,#'@                                                 ;[1.5]
       BEQ     20$                                                     ;[1.5]
       CMPB    @A2,#'#                                                 ;[1.5]
       BEQ     20$                                                     ;[1.5]
       CMPB    @A2,#'*                 ;
       BEQ     30$                     ;
14$:    MOVB    #40,(A0)+               ;
       SOB     D0,14$                  ;
       BR      50$                     ;
20$:    MOVB    (A2)+,(A0)+             ;
       SOB     D0,10$                  ;
       BR      50$                     ;
30$:    INC     A2                      ;
40$:    MOVB    #'?,(A0)+               ;
       SOB     D0,40$                  ;
50$:    REST    A0,D0                   ;
       RTN                             ;

;DEFEXT - define default extension

DEFEXT: MOV     WS.DFX(A4),WS.EXT(A4)   ;
       RTN                             ;

;CHKEXT - check for extension present

CHKEXT: CMPB    @A2,#'.                 ;
       BEQ     10$                     ;
       LCC     #0                      ;
       RTN                             ;
10$:    OR      #WS$EXT,WS.FLG(A4)      ;
       LCC     #PS.Z                   ;
       RTN                             ;

;GETEXT - get extension

GETEXT: SAVE    A0,D0                   ;
       INC     A2                      ;
       LEA     A0,WS.EXT(A4)           ;
       MOV     #3,D0                   ;
10$:    ALF                             ;
       BEQ     20$                     ;
       NUM                             ;
       BEQ     20$                     ;
       CMPB    @A2,#'?                 ;
       BEQ     20$                     ;
       CMPB    @A2,#'@                                                 ;[1.5]
       BEQ     20$                                                     ;[1.5]
       CMPB    @A2,#'#                                                 ;[1.5]
       BEQ     20$                                                     ;[1.5]
       CMPB    @A2,#'*                 ;
       BEQ     30$                     ;
14$:    MOVB    #40,(A0)+               ;
       SOB     D0,14$                  ;
       BR      50$                     ;
20$:    MOVB    (A2)+,(A0)+             ;
       SOB     D0,10$                  ;
       BR      50$                     ;
30$:    INC     A2                      ;
40$:    MOVB    #'?,(A0)+               ;
       SOB     D0,40$                  ;
50$:    REST    A0,D0                   ;
       RTN                             ;

;DEFPPN - define default [P,PN]

DEFPPN: SAVE    A1-A2,D1                ;
       BIT     #WS$ERZ,WS.FLG(A4)      ;
       BNE     10$                     ;
       CLR     D1                      ;
       MOV     JOBCUR,A1               ;
       MOVB    JOBUSR+1(A1),D1         ;
       LEA     A2,WS.PRG(A4)           ;
       CALL    20$                     ;
       MOVB    JOBUSR(A1),D1           ;
       LEA     A2,WS.PRJ(A4)           ;
       CALL    20$                     ;
10$:    REST    A1-A2,D1                ;
       RTN                             ;
20$:    MOVB    #40,@A2                 ;
       MOVB    #40,1(A2)               ;
       MOVB    #40,2(A2)               ;
       OCVT    0,OT$MEM                ;
       RTN                             ;

;CHKPPN - check for PPN

CHKPPN: BIT     #WS$PPN,WS.FLG(A4)      ; PPN already specified?
       BNE     10$                     ;  yes
       CMPB    @A2,#'[                 ;
       BEQ     20$                     ;
10$:    LCC     #0                      ;
       RTN                             ;
20$:    OR      #WS$PPN,WS.FLG(A4)      ;
       LCC     #PS.Z                   ;
       RTN                             ;

;GETPPN - get PPN

GETPPN: SAVE    A0,D0                   ;
       INC     A2                      ;
       CMPB    @A2,#']                 ;                               [1.6A]
       BEQ     10$                     ;
       LEA     A0,WS.PRG(A4)           ;
       MOV     #3,D0                   ;
       CALL    GETNUM                  ;
       CMPB    (A2)+,#<',>             ;                               [1.6A]
       BNE     40$                     ;
       LEA     A0,WS.PRJ(A4)           ;
       MOV     #3,D0                   ;
       CALL    GETNUM                  ;
       CMPB    (A2)+,#']               ;                               [1.6A]
       BNE     40$                     ;
       BR      30$                     ;
10$:    INC     A2                      ;
       LEA     A6,WS.PRG(A4)           ;
       MOV     #5,D7                   ;
20$:    MOVB    #'?,(A6)+               ;
       DBF     D7,20$                  ;
30$:    REST    A0,D0                   ;
       RTN                             ;
40$:    OR      #WS$ERR,WS.FLG(A4)      ;
       BR      30$                     ;

GETNUM: NUM                             ;
       BEQ     20$                     ;
       CMPB    @A2,#'?                 ;
       BEQ     20$                     ;
       CMPB    @A2,#'#                                                 ;[1.5]
       BEQ     20$                                                     ;[1.5]
       CMPB    @A2,#'*                 ;
       BEQ     30$                     ;
10$:    MOVB    #40,(A0)+               ;
       SOB     D0,10$                  ;
       BR      50$                     ;
20$:    MOVB    (A2)+,(A0)+             ;
       SOB     D0,GETNUM               ;
       BR      50$                     ;
30$:    INC     A2                      ;
40$:    MOVB    #'?,(A0)+               ;
       SOB     D0,40$                  ;
50$:    RTN                             ;

;************
;*  CHKRED  *
;************
;Function:      Check for redirection (= in command line)

CHKRED: BYP                             ;                               [110]
       CMPB    @A2,#'=                 ;                               [110]
       BEQ     10$                     ;                               [110]
       LCC     #0                      ;                               [110]
       RTN                             ;                               [110]
10$:    INC     A2                      ; bypass =                      [110]
       BYP                             ;                               [110]
       LCC     #PS.Z                   ;                               [110]
       RTN                             ;                               [110]

;************
;*  GETRED  *
;************
;Function:      Get redirection (copy input specs to output)

GETRED: OR      #WS$OUT,WS.FLG(A4)      ; set redirection flag          [110]
       MOV     WS.DEV(A4),WS.ODV(A4)   ; copy device code              [110]
       MOVW    WS.DRV(A4),WS.ODR(A4)   ; copy drive number             [110]
       MOVBLK  WS.FIL(A4),WS.OFL(A4),6 ; copy filename                 [110]
       MOV     WS.EXT(A4),WS.OEX(A4)   ; copy extension                [110]
       MOVBLK  WS.PRG(A4),WS.OPG(A4),3 ; copy programmer number        [110]
       MOVBLK  WS.PRJ(A4),WS.OPJ(A4),3 ; copy project number           [110]
       RTN                             ; return                        [110]

;************
;*  INIMEM  *
;************

INIMEM: CLRW    WS.RFN(A4)              ;initialize impure area
       CLR     WS.UFL(A4)              ;
       CLRW    WS.RPN(A4)              ;
       CLR     WS.MFL(A4)              ;
       MOV     DEVTBL,WS.DTI(A4)       ;
       RTN                             ;

ERROR:  BIT     #WS$ERR,WS.FLG(A4)      ;
       BNE     10$                     ;
       LCC     #PS.Z                   ;
       RTN                             ;
10$:    BIT     #WS$UNM,WS.FLG(A4)      ;
       BEQ     20$                     ;
       TYPECR  ?Device not mounted     ;
       BR      40$                     ;
20$:    BIT     #WS$DNE,WS.FLG(A4)      ;
       BEQ     30$                     ;
       TYPECR  ?Device does not exist  ;
       BR      40$                     ;
30$:    TYPECR  ?Specification error    ;
40$:    LCC     #0                      ;
       RTN                             ;

PAGE
;***********
;*  WSCAN  *
;***********
;Function:      Return next matching file

W.SCAN:

NEWFIL: CALL    NXTFIL                  ;
       REQ                             ;
NEWUFD: CALL    NXTUFD                  ;
       BEQ     NEWFIL                  ;
       CTRLC   EXIT                    ;
NEWPPN: CALL    NXTPPN                  ;
       BEQ     NEWUFD                  ;
NEWMFD: CALL    NXTMFD                  ;
       BEQ     NEWPPN                  ;
NEWDEV: CALL    NXTDEV                  ;
       BEQ     NEWMFD                  ;
EXIT:   RTN                             ;

;************
;*  NXTFIL  *
;************
;Function:      Return next file from UFD
;               Automatically redirect if {output=input} was present in
;               command line

NXTFIL: SAVE    A0                      ; save registers

NF.LOP: TSTW    WS.RFN(A4)              ; is remaining file count zero?
       JEQ     NF.ERR                  ;   yes
       DECW    WS.RFN(A4)              ; decrement remaining file count
       MOV     WS.UFI(A4),A0           ; get UFD index
       BIT     #WS$EXD,WS.FLG(A4)      ; extended directory?           [108]
       BNE     NF.EXT
       ;  yes                          [108]

;traditional directory structure

NF.TRA: ADD     #UF.SIZ,WS.UFI(A4)      ; add UFD size to index
       TSTW    UF.FIL(A0)              ; end of UFD?
       JEQ     NF.ERR                  ;   yes
       BIT     #WS$DEL,WS.FLG(A4)      ; do we want deleted files?
       BNE     10$                     ;   yes
       CMPW    UF.FIL(A0),#-1          ; deleted file entry?           [1.6A]
       BEQ     NF.LOP                  ;   yes - go get next one
       CALL    MATFIL                  ; matching file specification?
       BNE     NF.LOP                  ;   no - go get next one
10$:    MOV     UF.FIL(A0),WS.DDB+D.FIL(A4);
       MOVW    UF.EXT(A0),WS.DDB+D.EXT(A4);
       MOVW    UF.BLK(A0),WS.DDB+D.WRK+2(A4);
       MOVW    UF.ACT(A0),WS.DDB+D.WRK+6(A4);
       MOVW    UF.LNK(A0),WS.DDB+D.WRK+12(A4);
       CLR     WS.DDB+D.DVR(A4)        ;                               [113]
       LCC     #PS.Z                   ; set Z (file returned)
       BR      NF.RTN                  ; return

;extended directory structure

NF.EXT: ADD     #D$SIZ,WS.UFI(A4)       ; add UFD size to index         [108]
       ADD     #D$NAM,A0               ; point to file information     [108]
       MOVW    UF.FIL(A0),D7           ; end of UFD?                   [108]
       BEQ     NF.ERR                  ;   yes                         [108]
       BIT     #WS$DEL,WS.FLG(A4)      ; do we want deleted files?
       BNE     10$                     ;   yes

       MOVW    D$TYP-D$NAM(A0),D7      ;                               [114]
       ANDW    #100000,D7              ; deleted file entry?           [114]
       JNE     NF.LOP                  ;  yes - go get next one        [114]

       MOVW    UF.FIL(A0),D7           ;
       CMPW    D7,#-1                  ; deleted file entry?           [108]
       JEQ     NF.LOP                  ;   yes - go get next one       [108]
       CMPW    D7,#[$  ]               ; is this a hidden file?        [108]
       JEQ     NF.LOP                  ;   yes - go get next one       [108]
       CMPW    D7,#[$$ ]               ; is this a hidden file?        [108]
       JEQ     NF.LOP                  ;   yes - go get next one       [108]
       CALL    MATFIL                  ; matching file specification?  [108]
       JNE     NF.LOP                  ;   no - go get next one        [108]
10$:    MOV     UF.FIL(A0),WS.DDB+D.FIL(A4);                            [108]
       MOVW    UF.EXT(A0),WS.DDB+D.EXT(A4);                            [108]
       SUB     #D$NAM,A0               ;                               [108]
       MOV     D$FSZ(A0),WS.DDB+D.WRK(A4);                             [108]
       MOVW    D$LSZ(A0),WS.DDB+D.WRK+6(A4);                           [108]
       MOV     D$BAS(A0),WS.DDB+D.WRK+10(A4);                          [108]
       CLR     WS.DDB+D.DVR(A4)        ;                               [113]
       LCC     #PS.Z                   ; set Z (file returned)         [108]
       BR      NF.RTN                  ; return                        [108]

NF.ERR: LCC     #0                      ; clear Z (end of UFD)

NF.RTN: REST    A0                      ; restore registers
       RTN                             ; return

;************
;*  MATFIL  *
;************
;Function:      Check for matching file specification
;
;Inputs:        A0 - address of 6-word UFD file information

MATFIL: SAVE    A0-A2,D0                ; save registers
       LEA     A1,UF.FIL(A0)           ;
       LEA     A2,WS.TMP(A4)           ;
       UNPACK                          ;
       UNPACK                          ;
       UNPACK                          ;
       LEA     A0,WS.FIL(A4)           ;
       LEA     A1,WS.TMP(A4)           ;
       MOV     #9.,D0                  ;
10$:    CMPB    (A0)+,(A1)+             ;                               [1.6A]
       BNE     30$                     ;
20$:    SOB     D0,10$                  ;
       BIT     #WS$NOT,WS.FLG(A4)      ;
       JNE     MATCHN                  ;
       BR      MATCHY                  ;
30$:    CMPB    -1(A0),#'?              ;                               [1.6A]
       BEQ     20$
       CMPB    -1(A0),#'@                                              ;[1.5][1.6A]
       BEQ     50$                                                     ;[1.5]
       CMPB    -1(A0),#'#                                              ;[1.5][1.6A]
       BEQ     60$                                                     ;[1.5]
40$:    BIT     #WS$NOT,WS.FLG(A4)      ;
       BNE     MATCHY                  ;
       BR      MATCHN                  ;
50$:    CMPB    -1(A1),#'A                                              ;[1.5]
       BLO     40$                                                     ;[1.5]
       CMPB    -1(A1),#'Z                                              ;[1.5]
       BHI     40$                                                     ;[1.5]
       BR      20$                                                     ;[1.5]
60$:    CMPB    -1(A1),#'0                                              ;[1.5]
       BLO     40$                                                     ;[1.5]
       CMPB    -1(A1),#'9                                              ;[1.5]
       BHI     40$                                                     ;[1.5]
       BR      20$                                                     ;[1.5]
MATCHN: LCC     #0                      ;
       BR      MATCHR                  ;
MATCHY: LCC     #PS.Z                   ;
MATCHR: REST    A0-A2,D0                ;
       RTN                             ;

;************
;*  NXTUFD  *
;************
;Function:      Return next UFD block

NXTUFD: SAVE    A0,D0                   ; save registers
       CTRLC   NU.ERR                  ; ^C check
       TST     WS.UFL(A4)              ; check link
       BEQ     NU.ERR                  ;   end of user file directory chain
       MOV     WS.UFL(A4),WS.DDB+D.REC(A4); set block number
       PUSH    WS.DDB+D.BUF(A4)        ; push buffer address
       LEA     A0,WS.UFB(A4)           ; change buffer address
       MOV     A0,WS.DDB+D.BUF(A4)     ;   to UFD buffer
       CLR     WS.DDB+D.DVR(A4)        ; clear driver address          [1.6]
       READ    WS.DDB(A4)              ; read UFD block
       POP     WS.DDB+D.BUF(A4)        ; restore buffer address
       CLR     D0                      ; get
       BIT     #WS$EXD,WS.FLG(A4)      ; extended directory structure? [108]
       BNE     NU.EXT                  ;   yes

;traditional directory structure

NU.TRA: MOVW    (A0)+,D0                ;   link
       MOV     D0,WS.UFL(A4)           ; store link
       MOVW    #42.,WS.RFN(A4)         ; set number of files to be processed
       MOV     A0,WS.UFI(A4)           ; set UFD index
       LCC     #PS.Z                   ; set Z
       BR      NU.RTN                  ; return

;extended directory structure

NU.EXT: MOV     (A0)+,WS.UFL(A4)        ; store link
       MOVW    #<512.-4>/D$SIZ,WS.RFN(A4); set number of files to be processed
       MOV     A0,WS.UFI(A4)           ; set UFD index
       LCC     #PS.Z                   ; set Z
       BR      NU.RTN                  ; return

NU.ERR: LCC     #0                      ; clear Z

NU.RTN: REST    A0,D0                   ; restore registers
       RTN                             ; return

;************
;*  NXTDEV  *
;************
;Function:      Find next mounted disk in device table & setup for processing
;
;Sets or clears WS$EXD bit to flag extended or traditional directory format

NXTDEV: SAVE    A0                      ;
10$:    TST     WS.DTI(A4)              ;
       JEQ     40$                     ;
       MOV     WS.DTI(A4),A0           ;
       MOV     DV.NXT(A0),WS.DTI(A4)   ;
       BITW    #DV$MNT,DV.FLG(A0)      ;
       BEQ     10$                     ;
       BIT     #WS$ALL,WS.FLG(A4)      ;
       BNE     30$                     ;
20$:    CMMW    WS.DEV(A4),DV.DEV(A0)   ;
       BNE     10$                     ;
       CMMW    WS.DRV(A4),DV.UNT(A0)   ;
       BNE     10$                     ;
30$:    MOVW    DV.DEV(A0),WS.DDB+D.DEV(A4)
       MOVW    DV.UNT(A0),WS.DDB+D.DRV(A4)
       CLR     WS.DDB+D.DVR(A4)        ;                               [113]

       AND     #^C<WS$EXD>,WS.FLG(A4)  ; clear extended flag           [108]
       BITW    #DV$14D,DV.FLG(A0)      ; extended directory?           [108]
       BEQ     32$                     ;   no                          [108]
       OR      #WS$EXD,WS.FLG(A4)      ; set extended flag             [108]
32$:

       MOV     JOBCUR,A0               ;
       CMMW    WS.DDB+D.DEV(A4),JOBDEV(A0)
       BNE     34$                     ;
       CMMW    WS.DDB+D.DRV(A4),JOBDRV(A0)
       BNE     34$                     ;
       CLRW    WS.DDB+D.DEV(A4)        ;
       MOVW    #-1,WS.DDB+D.DRV(A4)    ;
       CLR     WS.DDB+D.DVR(A4)        ;                               [113]

34$:    MOV     #1,WS.MFL(A4)           ; set MFD block number to 1
       LCC     #PS.Z                   ; set Z
       BR      50$                     ;
40$:    LCC     #0                      ;
50$:    REST    A0                      ;
       RTN                             ;

;************
;*  NXTMFD  *
;************
;Function:      Load next block of master file directory
;
;Inputs:        WS.MFL(A4) - link to next block of MFD

NXTMFD: SAVE    A0,D0                   ;
       MOV     WS.MFL(A4),D0           ;
       BEQ     NM.ERR                  ;
       MOV     D0,WS.DDB+D.REC(A4)     ;
       PUSH    WS.DDB+D.BUF(A4)        ;
       LEA     A0,WS.MFB(A4)           ;
       MOV     A0,WS.DDB+D.BUF(A4)     ;
       CLR     WS.DDB+D.DVR(A4)        ; clear driver address          [1.6]
       READ    WS.DDB(A4)              ;
       POP     WS.DDB+D.BUF(A4)        ;
       BIT     #WS$EXD,WS.FLG(A4)      ; extended directory?           [108]
       BNE     NM.EXT                  ;   yes                         [108]

;traditional directory structure
;A0 indexes buffer

NM.TRA: CLR     D0                      ; get
       MOVW    MF.LNK(A0),D0           ;   MFD link
       MOV     D0,WS.MFL(A4)           ; set link to next MFD block
       LEA     A0,WS.MFB(A4)           ; set MFD
       MOV     A0,WS.MFI(A4)           ;   index
       MOVW    #63.,WS.RPN(A4)         ; set remaining PPN count
       LCC     #PS.Z                   ; set Z
       BR      NM.RTN                  ; return

;extended directory structure
;A0 indexes buffer

NM.EXT: MOV     (A0)+,WS.MFL(A4)        ; store link to next block      [108]
       MOV     A0,WS.MFI(A4)           ; set MFD index                 [108]
       MOVW    #<512.-4>/D$SIZ,WS.RPN(A4); set remaining PPN count     [108]
       LCC     #PS.Z                   ; set Z                         [108]
       BR      NM.RTN                  ; return                        [108]

NM.ERR: LCC     #0                      ;

NM.RTN: REST    A0,D0                   ;
       RTN                             ;

;************
;*  NXTPPN  *
;************
;Function:      Return next PPN of MFD
;
;Outputs:       Z  - 0 if end of this MFD block

NXTPPN: SAVE    A0,D0,D5                ; save registers                [108]
NP.LOP: TSTW    WS.RPN(A4)              ; is remaining PPN count zero?
       BEQ     NP.ERR                  ;   yes
       DECW    WS.RPN(A4)              ; decrement remaining PPN count
       MOV     WS.MFI(A4),A0           ; get MFD index
       BIT     #WS$EXD,WS.FLG(A4)      ; extended directory structure? [108]
       BNE     NP.EXT                  ;   yes                         [108]

;traditional directory structure

NP.TRA: ADD     #MF.SIZ,WS.MFI(A4)      ; add size of traditional MFD entry
       MOVW    MF.PPN(A0),D5           ; is this the end of the MFD?   [108]
       BEQ     NP.ERR                  ;   yes
       CMPW    D5,#-1                  ; deleted PPN?                  [111]
       BEQ     NP.LOP                  ;   yes - skip it               [111]
       CALL    MATPPN                  ; matching PPN?
       BNE     NP.LOP                  ;   no - go try next PPN
       CLR     D0                      ; get
       MOVW    MF.UFD(A0),D0           ;   UFD pointer
       BEQ     NP.LOP                  ;                               [113]
       MOV     D0,WS.UFL(A4)           ; store UFD pointer
       MOVW    #42.,WS.RFN(A4)         ; set remaining file count
       MOVW    MF.PPN(A0),WS.DDB+D.PPN(A4); set PPN into DDB
       LCC     #PS.Z                   ; set Z
       BR      NP.RTN                  ; return

;extended directory structure

NP.EXT: ADD     #D$SIZ,WS.MFI(A4)       ; add size of MFD entry         [108]
       MOVW    D$NAM(A0),D5            ; is this the end of the MFD?   [108]
       BEQ     NP.ERR                  ;   yes                         [108]
       CMPW    D5,#-1                  ; deleted PPN?                  [108]
       BEQ     NP.LOP                  ;   yes - ignore it             [108]
       CALL    MATPPN                  ; matching PPN?                 [108]
       BNE     NP.LOP                  ;   no - go try next PPN        [108]
       MOV     D$NXT(A0),D0            ; get UFD pointer               [108]
       MOV     D0,WS.UFL(A4)           ; store UFD pointer             [108]
       MOVW    #<512.-4>/D$SIZ,WS.RFN(A4); set remaining file count    [108]
       MOVW    D$NAM(A0),WS.DDB+D.PPN(A4); set PPN into DDB            [108]
       LCC     #PS.Z                   ; set Z                         [108]
       BR      NP.RTN                  ; return                        [108]

NP.ERR: LCC     #0                      ; clear Z
NP.RTN: REST    A0,D0,D5                ; restore registers             [108]
       RTN                             ; return

;************
;*  MATPPN  *
;************
;Function:      Determine if current PPN entry in MFD matches specification
;               Traditional file structure
;
;Inputs:        D5 - current PPN
;
;Outputs:       Z  - set if we have a match

MATPPN: SAVE    A2-A3,D0-D1,D5          ; save registers
       CLR     D1                      ; get
       RORW    D5,#8.                  ;                               [108]
       MOVB    D5,D1                   ;   programmer number           [108]
       LEA     A2,WS.TMP(A4)           ; index buffer
       MOVB    #40,WS.TMP+1(A4)        ; load w/
       MOVB    #40,WS.TMP+2(A4)        ;   spaces
       OCVT    0,OT$MEM                ; output as an octal number
       LEA     A2,WS.PRG(A4)           ; index programmer number spec
       LEA     A3,WS.TMP(A4)           ; index current programmer number
       CALL    30$                     ; compare
       BNE     10$                     ;   no match

       ROLW    D5,#8.                  ; move project into low byte    [108]
       CLR     D1                      ;                               [108]
       MOVB    D5,D1                   ; get project number            [108]
       LEA     A2,WS.TMP(A4)           ; index buffer
       MOVB    #40,WS.TMP+1(A4)        ; load w/
       MOVB    #40,WS.TMP+2(A4)        ;   spaces
       OCVT    0,OT$MEM                ; output as an octal number
       LEA     A2,WS.PRJ(A4)           ; index project number spec
       LEA     A3,WS.TMP(A4)           ; index current project
       CALL    30$                     ; compare
       BNE     10$                     ;   no match

       LCC     #PS.Z                   ; set Z
       BR      20$                     ; return

10$:    LCC     #0                      ; clear Z

20$:    REST    A2-A3,D0-D1,D5          ; restore registers
       RTN                             ; return

;compare

30$:    MOV     #3,D0                   ; max count is three
40$:    CMPB    (A2)+,(A3)+             ; match?                        [1.6A]
       BNE     60$                     ;   no
50$:    SOB     D0,40$                  ; loop
       LCC     #PS.Z                   ; set Z - we have a match
       RTN                             ; return
60$:    CMPB    -1(A2),#'?              ; wildcard?                     [1.6A]
       BEQ     50$                     ;   yes
       LCC     #0                      ; clear Z - no match
       RTN                             ; return

PAGE
;************
;*  W.FULL  *
;************
;Function:      Insure full file specification @A4

W.FULL: JOBIDX
       TSTW    D.DEV(A4)
       BNE     10$
       MOVW    JOBDEV(A6),D.DEV(A4)
       MOVW    JOBDRV(A6),D.DRV(A4)
10$:    TSTW    D.PPN(A4)
       BNE     20$
       MOVW    JOBUSR(A6),D.PPN(A4)
20$:    RTN

PAGE
;************
;*  W.LIST  *
;************
;Function:      Return list of matching file specifications
;
;Inputs:        A4 - must have been pre-indexed by W.INIT and W.SPEC calls
;               A0 - must index table to return list in
;               D0 - must contain maximum number of files table can hold
;
;Outputs:       A0 - unchanged
;               D0 - contains number of filenames returned

W.LIST: SAVE    A0,D2                   ;
       CLR     D2                      ;
10$:    CTRLC   30$                     ;
       CALL    W.SCAN                  ;
       BNE     30$                     ;
20$:    INC     D2                      ;
       MOVW    D.DEV(A4),(A0)+         ;
       MOVW    D.DRV(A4),(A0)+         ;
       MOV     D.FIL(A4),(A0)+         ;
       MOVW    D.EXT(A4),(A0)+         ;
       MOVW    D.PPN(A4),(A0)+         ;
       SOB     D0,10$                  ;
30$:    MOV     D2,D0                   ;
       REST    A0,D2                   ;
       RTN                             ;

PAGE
;"default" ersatz table - used if no user-definable ersatz table defined

DEFINE  ERSATZ  NAM,A,B
       RAD50   /'NAM/
       BYTE    A,B
       ENDM

ERZTBL: ERSATZ  OPR,1,2
       ERSATZ  SYS,1,4
       ERSATZ  DVR,1,6
       ERSATZ  CMD,2,2
       ERSATZ  LIB,7,0
       ERSATZ  HLP,7,1
       ERSATZ  BOX,7,2
       ERSATZ  VUE,7,3
       ERSATZ  LSP,7,4
       ERSATZ  PAS,7,5
       ERSATZ  BAS,7,6
       ERSATZ  MAC,7,7
       ERSATZ  MNU,7,11
       0

PAGE
;***********
;*  W.DEL  *
;***********
;Function:      Set WS$DEL flag, which returns all files (even deleted ones)
;               in each account.

W.DEL:  OR      #WS$DEL,WS.FLG(A4)      ;
       RTN                             ;

PAGE
;***********
;*  W.OUT  *
;***********
;Function:      Transform WS.DDB(A4) as per output redirection specification
;               Normally, this call immediately follows a W.SCAN call
;
;Inputs:        A4 - pointer to wildcard scanner impure area
;
;Outputs:       Z          - set if output redirection was specified and performed
;               WS.DDB(A4) - modified appropriately

W.OUT:  BIT     #WS$OUT,WS.FLG(A4)      ; was redirection specified?
       BEQ     W.ONR                   ;   no
       SAVE    A0-A2,D0-D2             ; save registers
       CALL    REDDEV                  ; redirect device
       CALL    REDDRV                  ; redirect drive
       CALL    REDFIL                  ; redirect filename
       CALL    REDEXT                  ; redirect extension
       CALL    REDPRG                  ; redirect programmer number
       CALL    REDPRJ                  ; redirect project number
       REST    A0-A2,D0-D2             ; restore registers
       LCC     #PS.Z                   ; set Z (redirection performed)
       RTN                             ; return
W.ONR:  LCC     #0                      ; no redirection
       RTN                             ; return

;************
;*  REDDEV  *
;************
;Function:      Redirect device code

REDDEV: MOVW    WS.ODV(A4),D0           ; get redirected device code
       BEQ     10$                     ;   none - leave device alone
       CMPW    D0,#[ALL]               ; ALL:?
       BEQ     10$                     ;   yes - leave device alone
       MOVW    D0,WS.DDB+D.DEV(A4)     ; set new device code
10$:    JOBIDX                          ; index JCB with A6
       CMMW    WS.DDB+D.DEV(A4),JOBDEV(A6); login device?
       BNE     20$                     ;   no
       CLRW    WS.DDB+D.DEV(A4)        ;   yes - set default
20$:    RTN                             ;

;************
;*  REDDRV  *
;************
;Function:      Redirect drive number

REDDRV: CMPW    WS.ODV(A4),#[ALL]       ; ALL:?
       BEQ     10$                     ;   yes - leave drive alone
       MOVW    WS.ODR(A4),WS.DDB+D.DRV(A4); set new drive number
10$:    JOBIDX                          ; index JCB with A6
       CMMW    WS.DDB+D.DRV(A4),JOBDRV(A6); login drive?
       BNE     20$                     ;   no
       MOVW    #-1,WS.DDB+D.DRV(A4)    ;   yes - set default
20$:    CLR     WS.DDB+D.DVR(A4)        ;                               [113]
       RTN                             ;

;************
;*  REDFIL  *
;************
;Function:      Redirect filename

REDFIL: LEA     A1,WS.DDB+D.FIL(A4)     ; index
       LEA     A2,WS.TMP(A4)           ;
       UNPACK                          ;
       UNPACK                          ;
10$:    CMPB    -(A2),#40               ;
       BEQ     10$                     ;
       CLRB    1(A2)                   ;

       LEA     A0,WS.OFL(A4)           ; index output filename
       LEA     A1,WS.TMP(A4)           ;
       MOV     #6.,D2                  ;
20$:    MOVB    (A0)+,D0                ; get char of output spec
       BEQ     40$                     ;   end of filename
       MOVB    @A1,D1                  ; get original filename char    [112]
       CMPB    D0,#'?                  ; wildcard in redirected spec?  [112]
       BNE     30$                     ;   no                          [112]
       MOVB    D1,D0                   ;   yes - use original character[112]
30$:    MOVB    D0,(A1)+                ; set new char in filename      [112]
       SOB     D2,20$                  ; loop till done
40$:    CLRB    @A1                     ; end of string

       LEA     A1,WS.DDB+D.FIL(A4)     ;
       LEA     A2,WS.TMP(A4)           ;
       PACK                            ;
       PACK                            ;

       RTN                             ;

;************
;*  REDEXT  *
;************
;Function:      Redirect extension

REDEXT: LEA     A1,WS.DDB+D.EXT(A4)     ; index
       LEA     A2,WS.TMP(A4)           ;
       UNPACK                          ;
10$:    CMPB    -(A2),#40               ;
       BEQ     10$                     ;
       CLRB    1(A2)                   ;

       LEA     A0,WS.OEX(A4)           ; index output filename
       LEA     A1,WS.TMP(A4)           ;
       MOV     #3,D2                   ;
20$:    MOVB    (A0)+,D0                ;
       BEQ     40$                     ;
       MOVB    (A1)+,D1                ;
       BEQ     40$                     ;
       CMPB    D0,#'?                  ;
       BEQ     30$                     ;
       MOVB    D0,-1(A1)               ;
30$:    SOB     D2,20$                  ;
40$:    CLRB    @A1                     ;

       LEA     A1,WS.DDB+D.EXT(A4)     ;
       LEA     A2,WS.TMP(A4)           ;
       PACK                            ;

       RTN                             ;

;************
;*  REDPRJ  *
;************
;Function:      Redirect project number

REDPRJ: CLR     D1                      ;
       MOVB    WS.DDB+D.PPN(A4),D1     ; index
       LEA     A2,WS.TMP(A4)           ;
       OCVT    0,OT$MEM                ;
       MOVB    #40,(A2)+               ;
       MOVB    #40,(A2)+               ;

       LEA     A0,WS.OPJ(A4)           ; index output
       LEA     A1,WS.TMP(A4)           ;
       MOV     #3,D2                   ;
20$:    MOVB    (A0)+,D0                ;
       BEQ     40$                     ;
       MOVB    (A1)+,D1                ;
       BEQ     40$                     ;
       CMPB    D0,#'?                  ;
       BEQ     30$                     ;
       MOVB    D0,-1(A1)               ;
30$:    SOB     D2,20$                  ;
40$:    CLRB    @A1                     ;

       LEA     A2,WS.TMP(A4)           ;
       GTOCT                           ;
       MOVB    D1,WS.DDB+D.PPN(A4)     ;

       RTN                             ;

;************
;*  REDPRG  *
;************
;Function:      Redirect programmer number

REDPRG: CLR     D1                      ;
       MOVB    WS.DDB+D.PPN+1(A4),D1   ; index
       LEA     A2,WS.TMP(A4)           ;
       OCVT    0,OT$MEM                ;
       MOVB    #40,(A2)+               ;
       MOVB    #40,(A2)+               ;

       LEA     A0,WS.OPG(A4)           ; index output
       LEA     A1,WS.TMP(A4)           ;
       MOV     #3,D2                   ;
20$:    MOVB    (A0)+,D0                ;
       BEQ     40$                     ;
       MOVB    (A1)+,D1                ;
       BEQ     40$                     ;
       CMPB    D0,#'?                  ;
       BEQ     30$                     ;
       MOVB    D0,-1(A1)               ;
30$:    SOB     D2,20$                  ;
40$:    CLRB    @A1                     ;

       LEA     A2,WS.TMP(A4)           ;
       GTOCT                           ;
       MOVB    D1,WS.DDB+D.PPN+1(A4)   ;

       JOBIDX                          ; index JCB with A6
       CMPW    D1,WS.DDB+D.PPN(A4)     ; is PPN login default?
       BNE     50$                     ;   no
       CLRW    WS.DDB+D.PPN(A4)        ;

50$:    RTN                             ;

       END