Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-11 - 43,50530/scn.mac
There are 2 other files named scn.mac in the archive. Click here to see a list.
	title PASSCN - SCAN interface for PASCAL programs

;Note: This file is a prototype.  Some tables and routines will need
;to be changed to fit your application.  Hopefully the file is self-
;explanatory.

;page 1 of this file contains the two routines ISCAN and TSCAN, which
;actually scan the command line.  These routines are more or less the
;same for all applications.  Only some table entries change, as shown
;below.  The things you will want to change are put near the beginning
;of the page.

;page 2 of this file contains prototypes for routines to actually open
;the files.  These routines should be written by the user.  There will
;need to be one routine for each file to be openned.  Note that the
;examples supplied here are sufficiently general that normally you will
;only need to delete unwanted code (as the examples have all possible
;bells and whistles) and change a few SIXBIT constants for default
;names, extensions, etc.  Again, the routines you need to worry about
;have been put at the beginning of the page

;page 3 of this file contains prototypes for routines that use WILD.
;You may safely delete page 3 (except the END statement) if you don't
;intend to use WILD.  If you use only things on page 3, the example
;routines (OPENIN and OPENOU) may be deleted from page 2, but the
;various low level routines on page 2 are also used by the WILD
;package.

	search macten,uuosym,scnmac
	.request rel:scn7bx,rel:helpx

	t0=0
	t1=1
	reg=2
	reg1=3
	reg2=4
	reg3=5
	reg4=6
	reg5=7
	reg6=10
	p=17

	.lklen==20	;length of our extended lookup/enter blocks

	FILPTR= 0	;LH = FUNNY BUSINESS IF WE ARE DOING STRING I/O:
			;  BIT 0 IS ALWAYS ON FOR STRING I/O
			;  REST OF WORD IS LMAX FOR THE ARRAY
			;FOR A FILE, LH=ERROR CODE IF REWRITE/RESET FAILS
	FILEOF= 1	;input: 0 = normal state
			;	1 = eof or error - no more data in file (some
			;	    errors will allow reading to continue, and
			;	    thus will NOT set FILEOF)
			;output:1 = normal state
			;	0 = error (but program will abort so this will
			;	     never show up)
	FILEOL= 2
	FILERR= 3
	FILLKP= 4
	FILENT= 5
	FILIN=	6
	FILOUT= 7
	FILCLS=10
	FILSTA=11	; .+0  FOR FILESTATUS
	FILDEV=12	; .+1  FOR DEVICE
	FILBFP=13	; .+2  FOR POINTER TO BUFFERHEADER
	FILNAM=14
	FILEXT=15
	FILPRO=16
	FILPPN=20
	FILBFH=26	;BUFFER HEADER
	FILBTP=27	;BYTE POINTER
	FILBTC=30	;BYTE COUNT IN BUFFER
	FILLNR=31	;IF ASCII MODE - LINENR IN ASCIICHARACTERS
	FILCNT=32	;LH= if non-text file: neg. number of words in comp.
			;    if text file: zero
			;test sign bit of this loc to see if an ASCII file
			;RH= ADDRESS OF FIRST WORD IN COMPONENT
	FILCMP=33	;FIRST WORD OF COMPONENT

	twoseg
	reloc 400000

;here begin the magic blocks that you may want to edit

comnds:	sixbit /FOO/	;table of monitor commands this program processes
	sixbit /BAR/

iblk:	iowd 2,comnds	;length of comnds list, comnds
	xwd %cclsw##,'FOO'	;RH=name of CCL or tmpcore file

	reloc 0

retblk::	;tscan returns a pointer to this block.  Your PASCAL
		;program will consider it a record with an entry for each
		;possible switch.  There should be one entry here for
		;each switch.
asw:	exp 0	;These values don't matter
bsw:	exp 0
csw:	exp 0

	reloc

define	swtchs<	;This is the definition of the switches.  It uses macros
		;from SCNMAC.  We will not document them here.
	sn *A,asw,fs.nue
	sn *B,bsw,fs.nue
	sn *C,csw,fs.nue
	>

clrans:	;This routine will be called before scanning each line.  It
	;should usually set all the switch values to -1, which is a
	;special value that SCAN uses as a code to indicate that nothing
	;has been typed yet.  You should see to it that there is a
	;SETOM for each location in retblk, unless you are dealing with
	;wierd switch types. (Some should be set to 0 instead.)

	setom asw
	setom bsw
	setom csw
	setzm firsti	;from here we do reinitialing that you needn't
	setzm firsto	;understand
	move t1,oldff
	movem t1,.jbff##
	popj p,

defans:	;This routine is called after all switch values have been scanned.
	;It should check all of the locations in retblk.  If any is still
	;-1, it should be given a default value (unless you like -1).
	;Note that PASCAL assumes that Booleans are 0 for false, 1 for true.

	seto t0,	;t0 gets -1, as it will be compared to the switches
	movei t1,1	;t1 gets 1, for ease in setting things to 1
	camn t0,asw	;is asw still -1?
	setzm asw	;yes - default it to 0
	camn t0,bsw	;is bsw still -1?
	movem t1,bsw	;yes - default it to 1
	came t0,csw	;is csw still -1?
	jrst .+3	;no - skip defaulting
	movei reg,100	;yes -default it to 100 octal
	movem reg,csw
	popj p,

;This ends the section that most users will need to redefine.  There
;are also a couple of things in tblk and oblk that you might want to
;play with, but probably not.

	doscan(passw)	;defines symbols passwx - a macro in SCNMAC

tblk:	iowd passwl,passwn
	xwd passwd,passwm
	xwd 0,passwp
	exp -1		;or sixbit /name/ to define file name for /HELP
			;-1 to use name of prog from GETTAB
	xwd clrans,0
	xwd allin,allout
	exp 0
	exp 0		;allows only one output file spec.
			;use exp 1b18 to allow .gt. 1
			;but if you turn on 1b18, it will require a =
	exp 0

oblk:	iowd passwl,passwn
	xwd passwd,passwm
	xwd 0,passwp
	exp -1		;as above
	exp 0		;or sixbit /option/ to define SWITCH.INI line
			;0 to use name of progm from GETTAB

;function iscan:integer

;Must be done once only, before doing tscan, etc. Returns index in
;comnds for monitor command typed, if any.

iscan::	movsi t1,2	;length of block
	hrri t1,iblk
	pushj p,.iscan##
	movem t1,1(p)	;returned value goes in 1(p) for PASCAL
	popj p,

;function tscan:retblkptr

;Must be done once for each command line.  Returns pointer to a
;record containing values of switches. retblkptr must be defined
;as ^retblk, where retblk is a record (not packed) whose definition
;matches the structure of retblk, above.

;File names are put in scan blocks, which are put in one contiguous
;part of the HEAP (i.e. NEW is used to allocate the space.  Thus
;to save on core, you should do mark and release at the beginning
;and end of the main loop of your program.
;You must not do release and expect the scan blocks to still be there!!
;FSCAN will not known that you have done that, and as likely as not
;will return garbage.

tscan::	setzm firsti	;sign that no input file spec seen
	setzm firsto	;ditto, output
	move t1,.jbff##	;we put scan blocks at .jbff, temporarily, so
	movem t1,oldff	; we will want to restore old .jbff at the end, to
			; return that space
	movsi t1,10	;length of tblk
	hrri t1,tblk
	pushj p,.tscan##
	movsi t1,5	;length of oblk
	hrri t1,oblk
	pushj p,.oscan##
	pushj p,defans	;user's routine to give default values for switches
			;that are still -1
;We now have the scan blocks at .jbff.  We want to move them to the heap, so
;That the space is recoverable (by release).  Then we restore the original
;.jbff, which reclaims the temporary storage (though we don't release the
;core -- sorry, folks)
	move t1,firsti	;skip to noin if no input blocks to move
	jumpe t1,noin
	move reg,lasti	;reg _ length of input blocks
	addi reg,.fxlen	; we now have addr of end of last block+1
	sub reg,t1	; now have length
	push p,reg	;new will lose this, and we want it for later
	pushj p,new##	;get space of this length on heap
		;reg is set to first location of the block
	pop p,t1	;length of block
	addi t1,-1(reg)	;t1 _last location in block on heap
	hrl reg,firsti	;reg _ firsti,,first location in heap
	hrrzm reg,firsti;update firsti to point into heap
	blt reg,(t1)	;now blt from .jbff area to heap
	subi t1,.fxlen-1;t1 _ begin. of last block (in heap)
	hrrzm t1,lasti	;that becomes new lasti
noin:	move t1,firsto	;now we to the same for output blocks, if any
	jumpe t1,noout
	move reg,lasto
	addi reg,.fxlen
	sub reg,t1
	push p,reg
	pushj p,new##
	pop p,t1
	addi t1,-1(reg)
	hrl reg,firsto
	hrrzm reg,firsto
	blt reg,(t1)
	subi t1,.fxlen-1
	hrrzm t1,lasto
noout:	move t1,oldff	;restore .jbff, since finished with temp storage
	movem t1,.jbff##
	movei t1,retblk	;this is return pointer for PASCAL caller
	movem t1,1(p)
	setzm wptr	;tell wild we are restarting
	popj p,

;allin and allout are called by .tscan when it needs a place to put a
;scan block.  They return the address in t1, length in reg.  They just
;put it at .jbff and update .jbff.  If this should overlap the heap,
;the NEW above will catch it, since .jbff is properly updated.

allin:	move t1,.jbff##	;next location to use
	skipn firsti	;see if firsti set up
	movem t1,firsti	;no - do so
	movem t1,lasti	;this is last input so far
;from here on we have common code for allin and allout
allall:	move t0,t1	;compute location for next time
	addi t0,.fxlen	;length of a scan block
	movem t0,.jbff##
	subi t0,1	;end of this block
	camg t0,.jbrel##;see if memory exists
	jrst all1	;yes
	core t0,	;no - get it
	 halt .
all1:	movei reg,.fxlen	;length of block
				;t1 already has its address
	popj p,

allout:	move t1,.jbff##	;as above, but for output
	skipn firsto
	movem t1,firsto
	movem t1,lasto
	jrst allall	;now go to common section

	reloc

firsti:	z
lasti:	z
firsto:	z
lasto:	z
oldff:	z
wptr:	z	;pointer to scan block currently in use by WILD
	reloc

;The following routine is an example of a routine to open an input
;file.  It supplies defaults for anything that is missing (except
;the path - SCAN defaults that to your default path, which seems to
;be what one wants).  If the user does not type an extension, we
;first try the default extension.  If there is no such file, we then
;try a null extension.  We call ANALYS, so an appropriate error
;message is printed if the lookup fails.  However the user must still
;examine EOF and realize that he will have to ask for another command
;line if EOF is true, since that means there was no such file.
; (NB:  If the file exists but is empty, i.e. is of zero length,
;EOF will still be set initially.  If it is desired to be able to
;handle zero-length files, the implicit get should be surpressed,
;as explained below.  Then EOF will be set if and only if the file
;does not exist.  However then the user will have to do an explicit
;GET after checking EOF.)

;procedure openin(f:text);

;The file will appear in REG

openin::movei t1,1		;This specifies the first file spec on
				;the input side.  -1 is the first spec on
				;the output side.
	pushj p,getscn		;returns addr of scan block in t1
	 jrst noinsp		;no input spec typed
	move t0,.fxmod(t1)	;word of useful bits from the scan block
;Delete the following code if you don't want to define a default device.
;If you delete it SCAN will supply DSK for you
	move reg1,[sixbit /DEFDEV/] ;default device 
	tlne t0,(fx.ndv)	;user supplied no device?
	movem reg1,.fxdev(t1)	;yes - use our default
;Delete the following if you don't want to define a default file name.
	move reg1,[sixbit /DEFNAM/] ;default file name
	skipe .fxnam(t1)	;user supplied name?
	jrst .+3		;yes - use his
	movem reg1,.fxnam(t1)	;no - use ours
	setom .fxnmm(t1)	;and specify no wildcards in it
;Delete the following if you don't want to define a default extension.
	hrloi reg1,'DEF'	;default extension - no wildcards
	tlne t0,(fx.nul)	;user typed one?
	movem reg1,.fxext(t1)	;no - use ours
;The following code should always be present.
	movei reg1,0		;I/O mode - use this for ASCII, 16 for binary
	movem reg1,filsta(reg)
	setzm xbloc1+1		;clear extended lookup block
	move reg1,[xwd xbloc1+1,xbloc1+2]
	blt reg1,xbloc1+.lklen
	movei reg1,xbloc1	;address of extended lookup block for this file
	pushj p,initfi		;t1 - addr of scan block
	 jrst oiwld		;reg - addr of file control block
				;reg1 - addr of extended lookup block
		;sets up the lookup block and file control block according to
		;the file spec in the scan block
agn:	setzb reg1,reg2		;here we set up the args for the PASCAL open
	setz reg3,		;use seto reg3, to surpress implicit GET
	movei reg4,xbloc1
	movei reg5,4		;number of I/O buffers.  Typically you will
				;use 0 - which gives you default number
	move reg6,filsta(reg)
;The following push's and pop's are needed only if you want to retry with
;null extension if defaulted extension is not found. (See below.)
	push p,t1
	push p,reg
	pushj p,resetf##	;Use resetf,rewrit, or update as appropriate
	pop p,reg
	pop p,t1
	skipn fileof(reg)	;Did we find the file?
	popj p,			;yes - return
;The following code analyses the error and retries with a null extension
;under the following conditions: (1) The user did not supply an extension
;(2) We did supply a default extension.  If you don't default the extension
;all you need at this point is 
;	pjrst analys##
;Which will print an error message and return to the user.
	hlrz t0,(reg)		;get the error code
	skipn t0		;something other than file not found?
	skipn filext(reg)	;or null extension used (i.e. 2nd time around)
	pjrst analys##		;just print message and return
	move t0,.fxmod(t1)	;get bits from scan block
	tlnn t0,(fx.nul)	;user defaulted extension?
	pjrst analys##		;no - no need to retry
	setzm filext(reg)	;yes - try null extension
	jrst agn

oiwld:		;here if input spec has wild cards in it
	outstr [asciz /
?  Wild card in input file spec
/]
	jrst oierr

noinsp:		;here if no input spec typed
	outstr [asciz /
?  No input file spec given
/]
oierr:	movni t0,10
	movem t0,fileof(reg)	;set EOF so the user knows it failed
	popj p,

	reloc

xbloc1: exp .lklen			;length of the extended lookup block
	block .lklen		;the block itself

	reloc

;The following routine is for openning a file whose defaults come from
;another file spec.  Typcially this would be an output file.  Note that
;this is appropriate for the output file of a compiler, etc., where
;wild is not used.  If wild cards appear in the file specs, a different
;routine using the secondary wildcard logic (which is in WILD) should
;be used.  Note that I do not show how to default the path or the device
;from the input, as this is not normally done in this context.  To do
;it correctly would require using the PATH. UUO on the input channel
;to get the path, and getting the logical device from the input lookup
;block.  Again, the user should check EOF after calling this function
;to see whether it worked.  (For an output file, EOF will be true
;if it worked.)  We print the error message if it fails, but the
;user will have to see that another command line is gotten.

;procedure openout(f:text);

;the address of the file control block will be in REG

openou::movni t1,1		;first file on the output side
	pushj p,getscn		;returns scanblock addr in t1
	 jrst defblk		;no spec typed - use default
gotdef:	move t0,.fxmod(t1)	;get bits from scan block
;Delete the following code if you don't want to default the device
	move reg1,[sixbit /DEFDEV/] ;default device
	tlne t0,(fx.ndv)	;did he supply one?
	movem reg1,.fxdev(t1)	;no - use default
;Delete the following code if you don't want to default the file name
	move reg1,xbloc1+.rbnam	;input file name
		;following two instructions needed only if you don't
		;default the input name.
	skipn reg1		;is there one?
	move reg1,[sixbit /DEFNAM/] ;no - use fixed default
	skipe .fxnam(t1)	;user supplied output file name?
	jrst .+3		;yes - use it
	movem reg1,.fxnam(t1)	;no - use default
	setom .fxnmm(t1)	;and note that no wildcards
;Delete the following code if you don't want to default the extension
;Usually you will use only one of the following two methods of
;defaulting.
	hllo reg1,xbloc1+.rbext	;input file extension finally used
	tlnn reg1,777777	;is there any?
	hrloi reg1,'DEF'	;no - use fixed default
	tlne t0,(fx.nul)	;user supplied output file extension?
	movem reg1,.fxext(t1)	;no - use default
;Delete the following code if you don't want to default the protection.
;This code uses the protection of the input file as the default.  To
;use a fixed default, replace it with
;	movei reg1,055		;default protection.
;or movei reg1,0 for the system default protection (the usual case)
	ldb reg1,[point 9,xbloc1+.rbprv,8] ;input file protection
	move t0,.fxmom(t1)	;bits from output file spec scan block
	trne t0,fx.pro		;protection specified?
	jrst .+4		;yes - use his
	dpb reg1,[point 9,.fxmod(t1),35] ;no - use default
	tro reg1,777
	dpb reg1,[point 9,.fxmom(t1),35] ;and show we did so
;Delete the following code if you don't want to default the version
;number.  To use a fixed default, use move reg1,[xxx] instead of
;the first instruction below
	move reg1,xbloc1+.rbver	;use input version number as default
	move t0,.fxver(t1)	;look at user's specified version no.
	camn t0,[-1]		;did he set it?
	movem reg1,.fxver(t1)	;no - use this one
;Delete the following code if you don't want to default the estimated
;file length from the length of the input.  Actually this is a fairly
;unusual thing to do, though SOS does it.
	move reg1,xbloc1+.rbsiz	;use input length as estimate
	skipge .fxest(t1)	;unless user specified one
	movem reg1,.fxest(t1)
;The following code should always be used
	movei reg1,0		;mode - 0 for ascii, 16 for binary
	movem reg1,filsta(reg)
	setzm xbloc2+1		;clear enter block
	move reg1,[xwd xbloc2+1,xbloc2+2]
	blt reg1,xbloc2+.lklen
	movei reg1,xbloc2
	pushj p,initfi		;set up xtended enter block etc.
	 jrst oowld		;wild card in the spec - can't handle it
	setzb reg1,reg2
	ldb reg3,[point 9,filpro(reg),8] ;or movei reg3 protection if
					;want to used a fixed value
	movei reg4,xbloc2
	movei reg5,4		;number of buffers.  Usually use 0,
				;which gives default
	move reg6,filsta(reg)
	pushj p,rewrit##	;or resetf or update
	pjrst analys		;print error if any and return to user

oowld:	outstr [asciz /
?  Wildcard in output file spec
/]
	setzm fileof(reg)	;set error indicator
	popj p,

defblk:		;here if no output spec typed.  Use default scan block
	move t0,[xwd nulpro,nulblk]
	blt t0,nulblk+.fxlen-1
	movei t1,nulblk
	jrst gotdef

	reloc

nulblk:	block .fxlen

	reloc

nulpro:	sixbit /nul/		;prototype for the default block
	block 3
	exp 600000000000
	exp 607000000000
	block 14
	repeat 10,<exp -1>

	reloc

xbloc2:	exp .lklen			;length of block
	block .lklen

	reloc

;The following routines are used by the code above.  You will not
;need to modify them (or even understand them).

getscn:		;serial number of file spec in t1. +n for nth input spec
		;-n for nth output spec.  Return addr of scan block in t1.
	;skip return if find the specified file spec
	;non-skip return if not enough typed (or t1=0)
			;t0=last block user typed
			;t1=counter for how many spec's . Count down to 0
			;reg=spec being looked at now
			;reg1=working reg
	push p,reg
	push p,reg1
	cain t1,0	;0 is illegal
	jrst nospec
	jumpge t1,getin	;see if input or output
	move reg,firsto	;here for output
	jumpe reg,nospec
	move t0,lasto
	jrst getio
getin:	move reg,firsti	;here for input
	jumpe reg,nospec
	move t0,lasti
getio:	movm t1,t1	;turn t1 into positive count
	soje t1,getgot	;if 1, want the first spec
getlop:	camn reg,t0	;need another spec
	jrst nospec	;this is last - not enough
	addi reg,.fxlen	;go to next one
	move reg1,.fxmod(reg) ;look at funny bits in the new spec
	tlne reg1,(fx.trm) ;is it 'and', etc.?
	jrst getlop	;yes - it doesn't count as a new spec
	sojg t1,getlop	;got new spec - go for more if counter isn't to zero
getgot:	move t1,reg	;have desired spec - get it in return reg
	pop p,reg1
	pop p,reg	;and restore ac's
	aos (p)		;good retur
	popj p,
nospec:	pop p,reg1	;return if no such spec
	pop p,reg	;may be error, or may just use a default
	popj p,

initfi:		;reg=addr of PASCAL file control block
		;t1=addr of scan block
		;reg1=addr of lookup/enter block
			;sets up PASCAL file control block and lookup block
			;given a scan block that has been defaulted
			;skip return if successful
			;non-skip return if not (means there were wildcards
			;  in the file spec)
	aos (p)			;assume successful return
	push p,reg
	push p,t1
	push p,reg1
	hrli t1,.fxlen		;length of scan block
	movei reg,filsta(reg)	;open block
	hrl reg1,(reg1)		;length of lookup/enter block
	movei reg2,pathbl	;place to put path
	pushj p,.stopb##	;converts scan block
	sos -3(p)		;wildcards in file spec
	pop p,reg1
	pop p,t1
	pop p,reg
		;alternate entry to put stuff from the lookup block into
		;the PASCAL file control block.  Used when WILD has done
		;the main conversion.  Always returns non-skip.
cvblk:	move t0,.rbnam(reg1)	;move other stuff from lookup block into
	movem t0,filnam(reg)	; file control block
	move t0,.rbext(reg1)
	hllzm t0,filext(reg)
	hllz t0,.rbprv(reg1)
	tlz t0,777
	movem t0,filpro(reg)
	move t0,.rbppn(reg1)	;ppn or path pointer
	caie t0,0		;if zero
	tlne t0,777777		;or non-zero LH
	jrst cvblk1		;then it's simple
	addi t0,2		;else pointer - here is path
	hrl t0,t0		;now make it the source
	hrri t0,filppn(reg)	;here is where path goes
	blt t0,filppn+5(reg)	;now move it
	popj p,
cvblk1:	movem t0,filppn(reg)	;if simple ppn, put it there
	setzm filppn+1(reg)	;and clear next so no SFD's
	popj p,

	reloc

pathbl:	block 9

	reloc
	.request rel:wld7b

;The routine WILDIN is an example of a procedure for handling
;a list of files with wildcards and looking them all up.  Each time
;you call WILDIN it will open a new file.  It will return TRUE as
;long as there was another file.  FALSE means you have come to the
;end of the list.  Note that a return of TRUE does not necessarily
;mean that the lookup succeeded.  You must still check EOF to be
;sure of that.  However, if there was any trouble this routine has
;already printed an error message, so in most cases you just go on
;to the next file.  There is little defaulting done in this routine.
;The only change you are likely to want to make is to modify it
;to read only one file spec instead of the whole input side, but even
;that doesn't seem likely.  If you want a default device other than
;DSK:, you can mimic the code from OPENIN, above.  Also, you will have
;to change a movei near the beginning if you want some I/O mode other
;than 0, and the stuff near the RESETF if you want other options for
;the RESET.  (Note that here I specify 4 buffers.  You may prefer to
;use zero, which gives the monitor default.)

;function wildin(f:text):Boolean;

;The file will appear in reg

wildin::move t1,firsti		;wild needs to know which scan blocks to use
				;here we will say all on the input side
	jumpe t1,widon		;none - treat it as an empty list
	movem t1,wfirst
	move t1,lasti
	movem t1,wlast
;alternatively, if you wanted just one file spec, you would use
;	movei t1,1		;first file spec on the input side
;	pushj p,getscn
;	 jrst widon
;	movem t1,wfirst		;addr of scan block for that file spec
;	setzm wlast		;a zero means use just one file spec

	movei t1,filsta(reg)
	hrlm t1,wblk+1		;tell WILD where the OPEN block is
	push p,reg		;because of loop below
wiagn:	pop p,reg
	movei t1,0		;I/O mode
	movem t1,filsta(reg)	;put it in the open block - must be done
	setzm wxblk+1		;clear lookup block
	move t1,[xwd wxblk+1,wxblk+2]
	blt t1,wxblk+.lklen
	move t1,[xwd 5,wblk]	;each time, as WILD may change it
	push p,reg
	pushj p,.lkwld##
	 jrst widon-1		;here if no more files
	pop p,reg
	movei reg1,wxblk	;extended lookup block
	pushj p,cvblk		;puts the info WILD set up in the PASCAL file
	setzb reg1,reg2		;now we set up for the RESET
	setz reg3,		;use seto reg3, to suppress the implicit GET
	movei reg4,wxblk
	movei reg5,4		;number of buffers - 0 for default
	move reg6,filsta(reg)
	pushj p,resetf##	;open and lookup the file
	skipe fileof(reg)	;worked?
	jrst wilker		;no - analyse the error
	push p,reg
	pushj p,.chktm##	;yes - see if OK with /SINCE, etc.
	jrst wiagn		;no - try the next one
	pop p,reg
	setom 1(p)		;yes - successful return
	popj p,

wilker:	hlrz t0,(reg)		;here if RESET failed.  Get cause
	movei t1,analys##	;The default error analyzer
	cain t0,^D101		;open failed
	movei t1,e.dfo##	;WILD's open failure printer
	caige t0,^D100		;lookup failed
	movei t1,e.dfl##	;WILD's lookup failure printer
	pushj p,(t1)
	setom 1(p)		;Successful return (there was a file)
	popj p,

	pop p,reg		;entry for when reg was saved
widon:	setzm 1(p)		;here when no more files - return false
	setom fileof(reg)	;and set end of file
	popj p,

	reloc

wblk:	xwd wfirst,wlast
	xwd 0,wxblk
	xwd .fxlen,.lklen		;length of lookup block below
	xwd 440000,wptr
	0

wxblk:	exp .lklen			;extended lookup block
	block .lklen

wfirst:	z
wlast:	z

	reloc

;The following is a routine for handling "secondary" files, i.e. files
;whose names are a function of the input file name.  For example in
;the command   *.doc=*.rno  the .doc file is secondary to the .rno files.
;For each .rno file we produce a (hopefully) different .doc file.
;Thus this routine takes two inputs:  The file spec for the secondary
;file (*.doc in this case) and that for the primary file that is to be
;the source of the names.  Note that this routine is connected to the
;one above directly, in that it knows about the lookup block that WILDIN
;uses.  It would not really be necessary to do any defaulting here, but
;most people don't like the way WILD handles wildcards in secondary files.
;One is accustomed to saying DSKB:=*.sai.  This turns into DSKB:*.*=*.sai,
;which gives an error message because there are more wildcards on the
;left than on the right.  As a convenience, I supply a defaulter below
;that simply copies the input spec into the output when no file name or
;extension is given.  I also tell you how to supply a default extension
;for the output, which is useful in many applications.  You can tell
;whether this routine succeeded by looking at EOF.  It will be true
;(since this is for output) if the thing succeeds.  An error message
;will be printed if anything goes wrong.

;procedure wildou(secondary,primary:text);

;the primary file will be in reg1, secondary in reg1.  Note that it is
;the secondary that is actually being openned. The primary is merely
;the source of defaults.


wildou::movni t1,1		;use the first spec on the output side
	push p,reg1
	pushj p,getscn		;returns addr of scan block in t1
	 movei t1,nulpro	;if none there, use default block
;The following code establishes various defaults.  It may be completely
;skipped if you like.  The thing just below with the BLT should be used
;if any defaulting is done, so that the original scan block is not
;changed, but rather a copy is used.
	hrl t1,t1		;source of copy
	hrri t1,nulblk		;this is an empty place to copy it to
	blt t1,nulblk+.fxlen-1	;now copy it
	movei t1,nulblk		;now we use the copy
	move reg1,wptr		;this is the scan block currently being
				;used by wild, and is the source for
				;some of the defaults.
	move t0,.fxmod(t1)	;the usual word of bits from scan block
;delete the following if you don't want to default the device
	move reg2,[sixbit /DEFDEV/]
	tlne t0,(fx.ndv)	;did he specify device?
	movem reg2,.fxdev(t1)	;no - use default
;delete the following if you don't want to copy the input spec as default
;for name.  Of course you could also have a fixed default name as with
;OPENOU above, but you normally wouldn't use wild to handle that.
	skipe .fxnam(t1)	;name specified?
	jrst .+5		;yes - use it
	move reg2,.fxnam(reg1)	;no - copy from input scan block
	movem reg2,.fxnam(t1)
	move reg2,.fxnmm(reg1)	;mask word
	movem reg2,.fxnmm(t1)
;delete the following if you don't want to copy the input spec as default
;for extension.
	tlnn t0,(fx.nul)	;extension specified?
	jrst .+5		;yes - use it
	move reg2,.fxext(reg1)	;input spec
	skipn reg2		;is it null?
	hrlzi reg2,'*  '	;yes - must use this on output to match
	movem reg2,.fxext(t1)
;or to use a fixed default extension you would use the following code
;	hrloi reg2,'DEF'
;	tlne t0,(fx.nul)
;	movem reg2,.fxext(t1)
;delete the following if you don't want to use the input version number
;as default.
	move reg2,wxblk+.rbver	;version no. of input file
	move t0,.fxver(t1)	;his version no. spec
	camn t0,[-1]		;default?
	movem reg2,.fxver(t1)	;yes - use input instead
;delete the following if you don't want to use the input length as an
;estimate of the output file length.  This is fairly unusual.
	move reg2,wxblk+.rbsiz	;input file length
	skipge .fxest(t1)	;specified anything?
	movem reg2,.fxest(t1)	;no - use default
;The code following here is always used, whether defaulting or not.
	movem t1,sfirst		;addr of secondary scan block
	pop p,reg1		;restore the PASCAL file block for pri. file
	hrlm reg1,sblk+1
	movei t0,0		;I/O mode - this is ASCII
	movem t0,filsta(reg)
	movei t0,filsta(reg)
	hrrm t0,sblk+1		;store addr of OPEN block for WILD
	setzm sxblk+1		;clear enter block
	move t1,[xwd sxblk+1,sxblk+2]
	blt t1,sxblk+.lklen
	move t1,[xwd 4,sblk]
	push p,filbfp(reg)	;.scwld zeros this for us - nice, huh?
	push p,reg
	pushj p,.scwld##	;does all the wild card fixups
	 jrst woerr		;couldn't convert names somehow
	pop p,reg
	pop p,filbfp(reg)
	movei reg1,sxblk	;now we convert to PASCAL file block
	pushj p,cvblk
	setzb reg1,reg2		;prepare for REWRITE
	ldb reg3,[point 9,filpro(reg),8] ;or movei reg3,0 for monitor default
	movei reg4,sxblk
	movei reg5,4		;no. of buffers. 0 for monitor default
	move reg6,filsta(reg)
	pushj p,rewrit##
	skipe fileof(reg)	;did it work?
	popj p,			;yes
	hlrz t0,(reg)		;no - find cause
	cain t0,^D101		;OPEN failed
	pjrst e.sco##		;wild's open failure printer
	caige t0,^D100		;ENTER failed
	pjrst e.scl##		;wild lookup failure printer
	pjrst analys##		;otherwise use normal printer

woerr:	pop p,reg		;here if problem with wildcards
	pop p,filbfp(reg)
	setzm fileof(reg)	;tell him it didn't work
	popj p,

	reloc

sblk:	xwd wptr,sfirst
	0
	xwd wxblk,sxblk
	xwd 0,.lklen		;length of lookup blocks

sxblk:	exp .lklen			;extended enter block
	block .lklen
sfirst:	z

;Here follows a routine to print the name of the last file used
;on the TTY:.  Note that it is potentially usable to print any
;file spec you might want to, just by changing a couple of
;instructions at the beginning.  Also, should you need the name
;in a string, you could open a file on the string with strset,
;and then redefine SCANs character output routine to use
;PUTCH.  This can be done by calling .TYOCH##  See the SCAN
;listing.

;procedure typein;

typein::hrl t1,wptr		;source is the current block being
				;used by WILD.  This could be any
				;SCAN block.
	hrri t1,nulblk		;a convenient working space
	blt t1,nulblk+.fxlen-1
	movei reg,wxblk		;this is the lookup block being used
				;by WILD.  It could be any lookup
				;block, so long as it was used with
				;the SCAN block loaded above.
	skipn t1,.rbdev(reg)	;get real device
	jrst .+7		;none - use what we have
	movem t1,dcblk		;this is physical name - get logical
	move t0,[xwd 5,dcblk]	;using dskchr
	dskchr t0,uu.phy
	 movem t1,dcblk+4	;not a disk - use what we have
	move t1,dcblk+4
	movem t1,.fxdev+nulblk
	skipe t1,.rbnam(reg)	;get real name found
	movem t1,.fxnam+nulblk	;and use it
	hllz t1,.rbext(reg)	;get real extension
	movem t1,.fxext+nulblk
	move t1,.rbppn(reg)	;see if we have a better PPN
	tlne t1,-1
	movem t1,.fxdir+nulblk	;yes - use it
	tlne t1,-1
	setom .fxdir+1+nulblk	;say no wildcards
	movei t1,nulblk		;arg for routine
	pjrst .tfblk##		;part of SCAN

dcblk:	block 5			;block for dskchr

	end