.MCALL .MODULE .MODULE IGTENT,VERSION=03,COMMENT=,IDENT=NO,LIB=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ;++ ; ; Edit Who Date Description of modification ; ---- --- ---- --------------------------- ; 001 WLD 05-OCT-90 Use CMPB to check number ; of arguments. ;-- .SBTTL Functional Description ; ; RT-11 SYSTEM LIBRARY (SYSLIB) FUNCTION ; ; MODULE: ; ; IGTENT() - "GET ENTRY" ; ; FUNCTIONAL DESCRIPTION: ; ; This function is used in conjunction with IGTDIR to retrieve ; directory entries according to a wildcard file specification and ; other criteria. ; ; CALLING SEQUENCE: ; ; BYTE ASCNAM(11) ; INTEGER*2 WKAREA(64), ENTRY(7), ENTOFS, FILBLK ; INTEGER*2 I ; ... ; I = IGTENT( WKAREA, ENTRY, [ENTOFS], [FILBLK], [ASCNAM]) ; ; PASSED ARGUMENTS: ; ; WKAREA is a work area, also specified in call to IGTDIR ; ; RETURNED ARGUMENT VALUES: ; ; ENTRY is a returned 7-word directory entry. If HEADER was ; specified in IGTDIR call, then the number of words ; returned in ENTRY includes any extra words defined by ; that directory's header. ; ENTOFS is a unique entry offset value for the returned entry ; FILBLK is the starting block of the file ; ASCNAM is the ASCII filename in form "filnam.ext". ; The name is returned null-terminated, left-justified ; and padded with spaces. Thus, A.B would be returned as ; ; A<5 spaces>.B<2 spaces> ; ; RETURNED FUNCTION VALUE: ; ; I < 0 indicates NO MATCH ; I > 0 indicates a MATCH. Bits 0-7 indicate which of several ; filespecs in match string caused a match. Bit-8 (EXT) ; indicates that at least one filespec in the match ; string (passed to IGTDIR) matched the file entry with an ; EXACT extension field. Bit-9 (NAM) indicates that at ; least one filespec in the match string matched the file ; entry with an EXACT match of BOTH the name and extension ; fields. ; ; +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ; | 0 | reserved |NAM|EXT|FS8|FS7|FS6|FS5|FS4|FS3|FS2|FS1| ; +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ; MACRO REFERENCES: .MCALL .BR, .ASSUME ; LOCAL MACRO DEFINITIONS: .MACRO ...... .ENDM ...... ; EXTERNAL INCLUDE FILES: ; ; IGTWAO.MAC - Work Area Offset Definitions ; EXTERNAL REFERENCES: .GLOBL $SYSLB .GLOBL $NXADR .GLOBL $NOARG .SBTTL Equates and Definitions ; Equates and Definitions: BLK =: 1000 ; Size of one block ERRBYT =: 52 ; System Error Byte address ENTRY =: 4 ; (offsets off R5) .INCLUDE 'SRC:IGTWAO.MAC' .SBTTL Data .PSECT SYS$S,D ; SYSLIB Pure data WFNLEN: .WORD FNLEN ; An actual word holding name len .SBTTL IGTENT Entry and Argument Processing .PSECT SYS$I,I .ENABL LSB IGTENT::MOV R5,R2 ; save arg pointer MOV (R5)+,R4 ; Get arg count CMPB R4,#2 ; at least 1st 2 are mandatory BLT 10$ ; so branch if not supplied. CALL $NXADR ; get work area pointer BCC 20$ 10$: MOV #E.IVAR,R0 ; Invalid Argument Error return RETURN ............ 20$: MOV R0,R1 ; put work area adrs in R1 MOV R2,IG.SV5(R1) ; put arg pointer in work area .ASSUME IG.WSZ EQ 0 CMP (R1),#IG.ID ; Is the WKAREA genuine IGTDIR stuff? BNE 30$ ; If not, return with error. CMP IG.LFO(R1),#IG.ID ; File open? BEQ 50$ ; If so, proceed below 30$: MOV #E.NODO,R0 ; Error: No Directory Open 40$: RETURN ............ ; Get the next directory entry 50$: MOV IG.BUF(R1),R2 ; Point to buffer ; If the segment in the buffer is not the one that should be there, ; re-read it now. This can happen if IGTENT is being used with more ; than one work area. CMP D.NEXT(R2),(R1) ; Segment is current? BEQ 54$ ; Branch if so. MOV IG.LSG(R1),R3 ; Get the desired segment number CALL IG$SEG ; re-read that segment BNE 40$ ; Return on error BR 50$ ; or go back up and try again. ........... 54$: MOV IG.LDP(R1),R3 ; Get current starting offset BEQ 70$ ; If first time, init it. ADD R3,R2 ; Point to current entry BIT #E.EOS,@R2 ; End of segment? BNE 60$ ; If so, try next one. ADD E.LENG(R2),IG.LQL(R1) ; Accumulate length ADD #E.ELEN,R3 ; Point to next entry. ADD (R1),R3 ; Add "extra bytes" value CMP R3,#<2*BLK> ; Pointing beyond segment? BLT 80$ ; Branch if not. 60$: MOV IG.BUF(R1),R2 ; Point to buffer MOV D.NEXT(R2),R3 ; Get next Segment Number BNE 64$ JMP NOMORE ; Branch if no more segments 64$: CALL IG$SEG ; Read the segment, return error code BNE 40$ ; Branch on read errors CLR IG.LQL(R1) ; Reset file length accumulator 70$: MOV #D.LENG,R3 ; Initialize offset ; Look at entry and decide whether it matches caller's criteria. 80$: MOV R3,IG.LDP(R1) ; Update Data Pointer MOV IG.BUF(R1),R2 ; Point to buffer ADD R3,R2 ; Point to entry MOV R2,IG.ENT(R1) ; Save entry's address. MOV IG.LBM(R1),R0 ; Get bit mask MOV (R2),R5 ; Get entry status word BIC R0,R5 ; STATUS .AND. MASK CMP R5,IG.LST(R1) ; Does status agree? BEQ 100$ ; If so, come on down! 90$: BR 50$ ; Try next one. ; Status matches. Check date against IGTDIR's criteria. 100$: CALL DATEOK ; check date criteria BNE 50$ ; no good ; Date AND status matches. Convert filename to ASCII. ; Plant a null and insert a dot. ; Try wildcard string match, if STRING was specified. TST (R2)+ ; Advance to RAD50 name MOV R1,-(SP) ADD #IG.ASN,(SP) ; 3rd arg is address of ASCII dest MOV R2,-(SP) ; 2nd arg is address of RAD50 name MOV #WFNLEN,-(SP) ; 1st arg is address of name len MOV #3,-(SP) ; 3 args... MOV SP,R5 MOV #R50ASC,R0 ; Point to R50ASC routine CALL CALL$F ; Convert RAD50 filespec to ASCII ADD #8.,SP MOV R1,R0 ; point to impure area ADD #,R0 ; point just beyond last char pos CLRB -(R0) ; Plant a NULL, MOV R0,R5 DEC R0 ; back up one, MOVB -(R0),-(R5) ; Advance MOVB -(R0),-(R5) ; EXT field MOVB -(R0),-(R5) ; one character MOVB #'.,-(R5) ; Plant a DOT. ; Get ready for wildcard-match routine MOV IG.STR(R1),R0 ; Get address of string CMP R0,#$NOARG ; STRING specified in IGTDIR? BEQ 110$ ; If not, go on to other things. TSTB (R0) ; Null string? BEQ 110$ ; If so, don't check. SUCCESS. MOV R0,-(SP) ; 2nd arg is addr of string, MOV R1,-(SP) ADD #IG.ASN,(SP) ; 1st arg is addr of test string, MOV #2,-(SP) ; 2 args... MOV SP,R5 MOV #IFWILD,R0 ; Point to IFWILD routine CALL CALL$F ; Do wildcard test ADD #6,SP ; fix the stack after call. TST R0 ; Test IFWILD's return code BPL USEENT ; Branch if matched. TST IG.RET(R1) ; Was ALWAYS_RETURN specified? BEQ 90$ ; Skip entry if not BR USEENT ; Use this one. ............ 110$: CLR R0 ; Indicate MATCH .BR USEENT .DSABL LSB .SBTTL Entry found - finish up ; A suitable entry has been found. ; If HEADER was specified in call to IGTDIR, a full entry is returned, ; including extra directory entry words. Otherwise, the standard ; seven-word entry is returned. .ENABL LSB USEENT: MOV R0,-(SP) ; Save IFWILD's return code MOV IG.SV5(R1),R5 ; Restore spoiled arg block pointer MOV ENTRY(R5),R0 ; Point to caller's ENTRY array MOV #</2>,R5 ; Normally, move this many words CMP IG.HED(R1),#$NOARG ; HEADER specified? BEQ 10$ ; Branch if not. MOV (R1),R2 ; Get no. of extra BYTEs ASR R2 ; make it extra WORDs ADD R2,R5 ; Add extra words to count 10$: MOV IG.ENT(R1),R2 ; Get entry's address 20$: MOV (R2)+,(R0)+ ; of directory entry to DEC R5 ; caller's array BGT 20$ ; Calculate ENTOFS for return value ; (R4 should still be holding the number of passed arguments remaining. ; Decrement it to account for the fact that $NXADR was not used to obtain ; the address of ENTRY.) DEC R4 ; Set R4 with args-left count MOV IG.SV5(R1),R5 ; Get arg block pointer ADD #6,R5 ; point to 3rd arg in R5 list CALL $NXADR ; 3rd arg (ENTOFS) specified? BCS 30$ ; branch if not. MOV IG.LSG(R1),R2 ; Get current segment, SWAB R2 ; SEG*400 ASL R2 ; SEG*1000 ASL R2 ; SEG*2000 BIS R3,R2 ; Combine current offset MOV R2,(R0) ; Return ENTOFS as requested. 30$: CALL $NXADR ; 4th arg (FILBLK) specified? BCS 40$ ; branch if not. MOV (R1),@R0 ; Get base block num for segment. ADD IG.LQL(R1),@R0 ; Return cumulative length as FILBLK 40$: CALL $NXADR ; 5 args passed? BCS 60$ ; branch if not. MOV R1,R2 ADD #IG.ASN,R2 ; Point to our ASCII name MOV #,R4 ; Move Filename+DOT+NULL 50$: MOVB (R2)+,(R0)+ ; Move name byte, DEC R4 BGT 50$ 60$: MOV (SP)+,R0 ; get IFWILD's return BPL 70$ ; if match, just return MOV #E.NOMA,R0 ; otherwise return NO_MATCH code 70$: RETURN ; a GOOD return. NOMORE: MOV IG.DEV(R1),R0 ; Get address of DEVICE arg CMP R0,#$NOARG ; If DEVICE not specified, BEQ 80$ ; or TST (R0) ; first word of DEVICE = 0, BEQ 80$ ; don't close input. CALL IG$CLO ; Otherwise, close it now. 80$: MOV #E.ENDS,R0 ; Signal END_OF_DIRECTORY 90$: RETURN .DSABL LSB .SBTTL DATEOK - Check date against specified criteria ; Subroutine DATEOK ; On entry R1 points to work space, ; R2 points to a directory entry ; ; On exit, R0 is ZERO if the date satisfies the criteria, or ; is NON-ZERO if not. .ENABL LSB DATEOK: MOV IG.LDR(R1),R0 ; Get Date relation offset .ASSUME R.ALL EQ 0 BNE 10$ ; branch if not ALL CLR R0 ; indicate MATCH BR 50$ ; Branch if so. MATCH. ............ ; Use IDCOMP to compare the file's date with that specified in IGTDIR 10$: MOV R1,-(SP) ; save impure pointer MOV R1,-(SP) ; bld arg block for IDCOMP MOV R0,R1 ; save relation offset in R1 ADD #IG.LDV,(SP) ; 2nd arg points to test date MOV R2,-(SP) ADD #E.DATE,(SP) ; 1st arg points to file date MOV #2,-(SP) ; number of args MOV SP,R5 ; Let R5 point to arg block MOV #IDCOMP,R0 ; Point to IDCOMP routine CALL CALL$F ; R0 = IDCOMP( DATE1, DATE2) ADD #6,SP ; reclaim stack space ; Use an appropriate conditional branch to determine SUCCESS or FAILURE. TST R0 ; Test IDCOMP's return value... JMP (R1) ; do appropriate conditional branch ; (-4 accounts for the ALL case, ; which is handled separately) BRS: BEQ 20$ ; success on EQ BR 30$ ; fail EQ BLT 20$ ; success on LT BR 30$ ; fail LT BLE 20$ ; success on LE BR 30$ ; fail LE BGT 20$ ; success on GT BR 30$ ; fail GT BGE 20$ ; success on GE BR 30$ ; fail GE BEQ 30$ ; fail NE .BR 20$ ; success on NE ; (The ALL case is handled separately above) ; Set an appropriate result code in R0 (0 means SUCCESS, non-zero means ; failure), clean the stack, and return. 20$: CLR R0 ; Indicate favorable comparison BR 40$ 30$: MOV SP,R0 ; any non-zero value will do 40$: MOV (SP)+,R1 ; restore impure pointer 50$: TST R0 ; get set for caller's branch RETURN .DSABL LSB .END