	.enable lsb
	.title	opncre	Open and create files
	.ident	"V02.00"
;+
; Index 	Open a file
; Index		Create a file
;
; Usage
;
;	stream = ropen(fsb, fsb_size, cmode, dprot, options)
;	int stream;      /* stream number */
;	char *fsb;	 /* pointer to fsb */
;	int  fsb_size;   /* size of fsb */
;	char *cmode;	 /* connect mode */
;	char *dprot;	 /* dynamic protection */
;	char *options;	 /* string of options */
;
;
;	stream = rcreat(fsb, fsb_size, cmode, dprot, options)
;	int stream;      /* stream number */
;	char *fsb;	 /* pointer to fsb */
;	int  fsb_size;   /* size of fsb */
;	char *cmode;	 /* connect mode */
;	char *dprot;	 /* dynamic protection */
;	char *options;	 /* string of options */
;
;
; Description
;
;	ropen() connects a file with a stream number and opens it
;	according to the fsb. It returns the stream number on success
;	and 0 on error. The stream number may then be used on subsequent
;	file server function calls as it identifies the connection.
;
;	A file may be opened with different connect and dynamic protection
;	modes.  The following is a list of the possible connect and dynamic
;	protection modes:
;
;		Connect:
;	     	   i - open for input only
;	           o - open for output only
;	    	  io - open for input and output
;	     	   a - open for append
;
;		Dynamic protection:
;	     	   s - The file may be connected to by any
;		       other user (with proper static privilege)
;		       for either INPUT, I/O or APPEND. This is
;		       the "multiple writers" mode.
;	     	   p - The file may be connected to by any other
;		       user (with proper static privilege) for
;		       INPUT only. This is the "single writer
;		       multiple readers" mode.
;	           e - The file may not be connected to by any
;		       other user.
;
;	The options available with the ropen() function are as follows:
;
; 		Options:
;	     	   d - auto-delete on disconnect if dprot
;		       EXCLUSIVE
;	     	   n - do not auto-extend
;	     	   w - disable write thru caching
;		       (for writes)
;
;
;	rcreat() connects a file with a stream number and creates a new file
;	according to the fsb. It returns the stream number on success and
;	and 0 on error. The stream number may then be used on subsequent
;	file server function calls as it identifies the connection.
;
;	A file may be created with different connect and dynamic protection
;	modes.  The following is a list of the possible connect and dynamic
;	protection modes:
;
;		Connect:
;	     	   i - open for input only
;	     	   o - open for output only
;	    	  io - open for input and output
;	     	   a - open for append
;
;		Dynamic protection:
;	     	   s - The file may be connected to by any
;		       other user (with proper static privilege)
;		       for either INPUT, I/O or APPEND. This is
;		       the "multiple writers" mode.
;	     	   p - The file may be connected to by any other
;		       user (with proper static privilege) for
;		       INPUT only. This is the "single writer
;		       multiple readers" mode.
;	           e - The file may not be connected to by any
;		       other user.
;
;	The options available with the rcreat() function are as follows:
;
; 		Options:
;	     	   d - auto-delete on disconnect if dprot
;		       EXCLUSIVE
;	     	   n - do not auto-extend
;	     	   s - supersede existing file if same version
;	     	   w - disable write thru caching
;		       (for writes)
;
;-
; Edit History
; V02.00 18-Oct-82 TTC		Rework of CS library
;

	.MCALL	FSDEF$	ALUN$S
	FSDEF$

scr0 	=	C$AUTO-2	; Define 2 scratch areas.
scr1	=	C$AUTO-4

	.psect	c$strn
;
; Connect modes.
;
input:	.asciz	"i"
output:	.asciz	"o"
io:	.asciz	"io"
append:	.asciz	"a"

;
; Dynamic Protection.
;
shared:	.asciz	"s"
prot:	.asciz	"p"
exclu:	.asciz	"e"

;
; Options.
;
delete:	.asciz	"d"
nxt:	.asciz	"n"
wtd:	.asciz	"w"
sup:	.asciz	"s"
	.even

	.psect	c$data
;
; Connect mode table.
;
cmodes:	.word	input,	CM.INP
	.word	output,	CM.OTP
	.word	io,	CM.IO
	.word	append,	CM.APD
	.word	0
;
; Dynamic protection table.
;
dprot:	.word	shared,	DP.SHR
	.word	prot,	DP.PRO
	.word	exclu,	DP.EXC
	.word	0

;
; Table of options for open.
;
opnopt:	.word	delete,	O.DEL
        .word   nxt,	O.NXT
	.word	wtd,	O.WTD
	.word   0

;
; Table of options for create.
;
creopt: .word	delete,	O.DEL
	.word	nxt,	O.NXT
	.word	wtd,	O.WTD
	.word	sup,	O.SUP
	.word	0

	.psect	c$code

ropen::	jsr	r5,csv$			; Link environments
	mov	#opnopt,r3		; r3 --> open options table
	mov	#FS.CON,fsqio+q.iofn	; Function: FS.CON
	br	10$			; Branch to common code

rcreat::
	jsr	r5,csv$			; Link environments
	mov	#creopt,r3		; r3 --> create options table
	mov	#FS.CRE,fsqio+q.iofn	; Function: FS.CRE

10$:	sub	#<2*2>,sp		; make 2 scratch variables
	mov	C$PMTR+4(r5),r1		; r1 --> passed cmode string
	mov	r1,-(sp)		; Push passed cmode string
20$:	bisb	#040,(r1)+		; convert cmode to lower case
	tstb	(r1)			; More to convert?
	bne	20$			; (Yes)
	mov	#cmodes,r2		; r2 --> cmode table
	mov	(r2)+,-(sp)		; Push cmode string, r2 --> value
30$:	call	strcmp			; check passed cmode with table
	tst	r0			; Equal?
	beq	40$			; (Yes)
	tst	(r2)+			; Not this one, so r2 --> next
	tst	(r2)			; End of table?
	beq	80$			; (Yes), Invalid cmode
	mov	(r2)+,(sp)		; Push next table cmode string entry
	br	30$			; try again
40$:	mov	(r2),scr0(r5)		; Save cmode value in scratch area 0
	mov	C$PMTR+6(r5),r0		; r0 --> passed dprot string
	mov	r0,2(sp)		; Push dprot string
	bisb	#040,(r0)+		; Convert lower case
	tstb	(r0)			; Only one dprot parameter allowed
	bne	80$			; If more than one char. then invalid
	mov	#dprot,r2		; r2 --> dprot table
50$:	mov	(r2)+,(sp)		; Push dprot string on stack
	call	strcmp			; check with passed dprot
	tst	r0			; Equal?
	beq	60$			; (Yes)
	tst	(r2)+			; Not this one, so r2 -> next
	tst	(r2)			; End of table?
	bne	50$			; (No)
	br	80$			; Invalid dprot
60$:	mov	(r2),scr1(r5)		; Save dprot value in scratch area 1
	mov	r3,r1			; r1 --> option table
	mov	C$PMTR+10(r5),r0	; r0 --> list of passed options
	call	option			; check options
	tst	r0			; Error?
	beq	80$			; (Yes)
70$:	ALUN$S	#fs.lun,#"FS,#0		; Assign FS lun
	mov	#fsqio+q.iopl,r0	; r0 --> parameter #1
	clr	(r0)+			; Clear first parameter
	mov	C$PMTR+0(r5),(r0)+	; Parameter #2: Address of fsb
	mov	C$PMTR+2(r5),(r0)+	; Parameter #3: Size of fsb
	mov	scr0(r5),(r0)+		; Parameter #4: Connect mode
	mov	scr1(r5),(r0)+		; Parameter #5: Dynamic prot.
	mov	r1,(r0)+		; Parameter #6: incl-or of opts
	mov	#fsqio,r0		; r0 must = qio for xqiow
	call	.xqiow			; Do connection
	cmp	$dsw,#is.suc		; How'd it go
	blo	80$			; Not so good
	mov	f.iosb+2,r0		; r0 = stream number
	jmp	cret$
80$:	clr	r0			; Branch here if error, r0 = 0
	jmp	cret$

;
; STRCMP - String compare.
;
; Compare two strings, returning -1 if first string is
; less than second, 0 if there are equal and 1 if first
; string is greater than second.
;
strcmp:
	mov	2(sp),r0		; r0 --> first string
	mov	4(sp),r1		; r1 --> second string

90$:	cmpb	(r0)+,(r1)		; Are they the same?
	bne	100$			; (No)
	tstb	(r1)+			; At the end of the string?
	bne	90$			; (No)
	clr	r0			; Equal
	return

100$:	blo	110$			; Br if 1st < 2nd
	mov	#1,r0			; 1st > 2nd
	return

110$:	mov	#-1,r0			; 1st < 2nd
	return

	.end
