| 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
|