|  |     The following software will do what you want.  It expects to find
    a file WORDS.DAT of lowercase words, one word per line, as might
    be created by a text editor (i.e., RMS record format assumed).
    It asks you "Pattern: " and you type in what you're looking for,
    using VAX wildcarding conventions.  E.g.,
>	like all 3-letter words ending in "j";
    
    Pattern: %%j
    haj
    raj
    
>	all 7-letter words with "que" in the 3, 4, and 5 spot;
    
    Pattern: %%que%%
    bequest
    request
    
>	formed that can be formed from the following combination: SA_INE 
    
    Pattern: sa%ine
    
    All words ending in "handing":
    
    Pattern: *handing
    
    ^Z to exit.
    
    Disclaimer:  hey, folks, I wrote this program 10 years ago as one of
    several learning exercises.  The code is not very pretty, I'm not very
    proud of it, but it does seem to work and that's what's most important
    (I think) to the author of .0.  I recall being particularly proud of
    the SUBB instruction, but I was young and foolish back then...
    
      John
    ----------------------------- cut here --------------------------
	.TITLE	WORDS
	.PSECT	WORDS,PAGE,EXE
PSIZE=100			; Max input string size
	.ENTRY	WORDS ^M<>
	CLRL	FLAG
	CALLS	#0,OPENIT
	MOVW	INFAB+FAB$L_STV,CHAN
	CALLS	#0,MAPIT
	BICW	#^X1FF,RETADR+4	; Set up real end-of-file address
	BISW	HEADERXAB+XAB$W_FFB,RETADR+4
LOOP:	MOVW	#PSIZE,PATTERN
	BLBC	FLAG,10$
	PUSHAQ	BLANK
	CALLS	#1,G^LIB$PUT_OUTPUT
10$:	PUSHAW	ACTLEN
	PUSHAQ	PROMPT
	PUSHAQ	PATTERN
	CALLS	#3,G^LIB$GET_INPUT
	CMPL	R0,#RMS$_EOF	; EOF (^Z) detected?
	BNEQ	GOT		; No
	$EXIT_S			; Yes
GOT:	TSTW	ACTLEN		; <CR> only?
	BEQL	LOOP		; Yes
; The "pattern" is in descriptor PATTERN
	MOVZWL	ACTLEN,R1	; Length
	MOVL	PATTERN+4,R2	; Address
	DECL	R1		; Length-1
CLOOP:	CMPB	(R2)[R1],#^A/A/	; Uppercase? (1 of 2)
	BLSS	ELOOP		; Nope
	CMPB	(R2)[R1],#^A/Z/	; Uppercase? (2 of 2)
	BGTR	ELOOP		; Nope
	SUBB	#<^A/A/-^a/a/>,(R2)[R1]	; Make lowercase
ELOOP:	SOBGEQ	R1,CLOOP	; Go do next character
; Invoke filescan pattern search
	PUSHL	PATTERN+4
	MOVZWL	ACTLEN,-(SP)
	CLRL	FLAG
	CALLS	#2,SEARCH
	BRW	LOOP
	.ENTRY	SEARCH ^M<R10,R11>
	MOVL	4(AP),R10	; R10:  length of pattern
	MOVL	8(AP),R11	; R11:  address of pattern
	MOVL	RETADR,R7	; R7 -> next record
10$:	MOVZWL	(R7),R8		; R8:  length of next record
	MOVAL	2(R7),R9	; R9:  address of next record
	MOVQ	R8,NEXTREC	; Save descriptor
	PUSHAQ	4(AP)		; Pattern descriptor address
	PUSHAQ	NEXTREC		; Candidate string address
	CALLS	#2,G^STR$MATCH_WILD
	BLBC	R0,20$		; Branch if no match
	MOVL	#1,FLAG		; Set flag for extra blank line
	PUSHAQ	NEXTREC		; Matching string address
	CALLS	#1,G^LIB$PUT_OUTPUT
20$:	BLBC	R8,30$		; Odd-length record?
	INCL	R9		; Yes, advance pointer
30$:	ADDL3	R8,R9,R7	; Advance pointer by length
	CMPL	R7,RETADR+4	; Done yet?
	BLSS	10$		; No, continue
40$:	RET			; Yes, quit
	.ENTRY	OPENIT, ^M<>
	$OPEN	FAB=INFAB
	BLBC	R0,9$
	RET
9$:	BSBW	OOPS
	HALT
	.ALIGN	LONG
INFAB:	$FAB	FNM=<WORDS.DAT>,FOP=UFO,XAB=HEADERXAB
HEADERXAB:
	$XABFHC
	.ENTRY	MAPIT,^M<>
	$CRMPSC_S INADR=INADR,RETADR=RETADR,GSDNAM=GSDNAM,-
		  CHAN=CHAN,PFC=#40
	BLBC	R0,9$
	RET
9$:	BSBW	OOPS
	HALT
OOPS::	PUSHL	R0
	CALLS	#1,G^LIB$STOP
INADR:	.LONG	^X100000,^X200000
RETADR:	.LONG	0,0
GSDNAM:	.ASCID	/FILE/
CHAN:	.WORD	0
PATTERN:.LONG	^X010E0000,SPACE
SPACE:	.BLKB	PSIZE
PROMPT:	.ASCID	/Pattern: /
ACTLEN:	.BLKW	1
ANSWER:	.LONG	^X010E0000,0
FLAG:	.LONG	0
NEXTREC:.BLKQ	1
BLANK:	.ASCID	//
	.END	WORDS
    
 |