include	clib.inc
include	io.inc
include	stdio.inc
include fcntl.inc
include stat.inc
include	errno.inc

	extrn	_fmode:word
	extrn	_umaskval:word

PPROC	fopen, FILENAME:DPTR, MODE:DPTR
local	fpo:word
local	fps:word
local	flag:word
local	fmode:word
local	create:word
local	isdev:word
local	attrib:byte
local	filepos:dword
local	oflag:word
local	sflag:word
local	wflag:word
	push	si
	push	di
	xor	ax,ax
	mov	oflag,ax
	mov	sflag,ax
	mov	wflag,ax
	mov	si,ax
	call	_getst
	test	ax,ax
	jz	fopen_02
	mov	fpo,ax
	MMOV	fps,dx
	MLES	bx,MODE
	mov	al,es:[bx]
	xor	dx,dx
	mov	bx,dx
	cmp	al,'r'
	jne	fopen_00
	mov	dx,O_RDONLY	; oflag
	mov	bx,_IOREAD	; sflag
	jmp	fopen_03
    fopen_00:
	cmp	al,'w'
	jne	fopen_01
	mov	dx,O_WRONLY or O_CREAT or O_TRUNC
	mov	bx,_IOWRT
	jmp	fopen_03
    fopen_01:
	cmp	al,'a'
	jne	fopen_02
	mov	dx,O_WRONLY or O_CREAT or O_APPEND
	mov	bx,_IOWRT
	jmp	fopen_03
    fopen_02:
	jmp	fopen_NULL
    fopen_03:
	mov	oflag,dx
	mov	sflag,bx
	mov	wflag,1
	MLES	bx,MODE
    fopen_04:
	inc	bx
	mov	al,es:[bx]
	test	al,al
	jz	fopen_11
	cmp	wflag,0
	je	fopen_11
	cmp	al,'+'
	je	fopen_05
	cmp	al,'b'
	je	fopen_07
	cmp	al,'t'
	je	fopen_09
	mov	wflag,0
	jmp	fopen_11
    fopen_05:
	test	oflag,O_RDWR
	jz	fopen_06
	mov	wflag,0
	jmp	fopen_11
    fopen_06:
	or	oflag,O_RDWR
	and	oflag,not (O_RDONLY or O_WRONLY)
	or	sflag,_IORW
	and	sflag,not (_IOREAD or _IOWRT)
	jmp	fopen_11
    fopen_07:
	test	oflag,O_TEXT or O_BINARY
	jz	fopen_08
	mov	wflag,0
	jmp	fopen_11
    fopen_08:
	or	oflag,O_BINARY
	jmp	fopen_11
    fopen_09:
	test	oflag,O_TEXT or O_BINARY
	jz	fopen_10
	mov	wflag,0
	jmp	fopen_11
    fopen_10:
	or	oflag,O_TEXT
    fopen_11:
	test	oflag,O_BINARY
	jz	fopen_12
	mov	flag,0
	jmp	fopen_15
    fopen_12:
	test	oflag,O_TEXT
	jz	fopen_13
	mov	flag,FH_TEXT
	jmp	fopen_15
    fopen_13:
	cmp	_fmode,O_BINARY
	jne	fopen_14
	mov	flag,0
	jmp	fopen_15
    fopen_14:
	mov	flag,FH_TEXT
    fopen_15:
	mov	ax,oflag
	and	ax,O_RDONLY or O_WRONLY or O_RDWR
	cmp	ax,O_RDONLY
	je	fopen_17
	cmp	ax,O_WRONLY
	je	fopen_17
	cmp	ax,O_RDWR
	je	fopen_17
    fopen_16:
	mov	errno,EINVAL
	mov	doserrno,0
	jmp	fopen_NULL
    fopen_17:
	mov	fmode,ax
	mov	ax,oflag
	and	ax,O_CREAT or O_EXCL or O_TRUNC
	jz	fopen_18
	cmp	ax,O_EXCL
	je	fopen_18
	cmp	ax,O_CREAT
	je	fopen_19
	cmp	ax,O_CREAT or O_EXCL
	je	fopen_20
	cmp	ax,O_CREAT or O_TRUNC or O_EXCL
	je	fopen_20
	cmp	ax,O_TRUNC
	je	fopen_21
	cmp	ax,O_TRUNC or O_EXCL
	je	fopen_21
	cmp	ax,O_CREAT or O_TRUNC
	je	fopen_22
	jmp	fopen_16
    fopen_18:
	mov	create,A_OPEN
	jmp	fopen_23
    fopen_19:
	mov	create,A_OPEN or A_CREATE
	jmp	fopen_23
    fopen_20:
	mov	create,A_CREATE or A_TRUNC
	jmp	fopen_23
    fopen_21:
	mov	create,A_TRUNC
	jmp	fopen_23
    fopen_22:
	mov	create,A_CREATE or A_TRUNC
    fopen_23:
	mov	attrib,_A_NORMAL
	test	oflag,O_CREAT
	jz	fopen_24
	mov	ax,_umaskval
	not	ax
	and	ax,0284h
	and	ax,S_IWRITE
	jnz	fopen_24
	mov	attrib,_A_RDONLY
    fopen_24:
	MPUSH	word ptr FILENAME+2
	push	word ptr FILENAME
	mov	al,attrib
	mov	ah,0
	push	ax
	push	fmode
	push	create
	call	osopen
	mov	si,ax
	cmp	ax,-1
	je	fopen_NULL
	push	ax
	call	osfiletype
	mov	isdev,ax
	cmp	ax,DEV_UNKNOWN
	jne	fopen_25
	push	si
	call	close
	mov	ax,doserrno
	call	@dosmaper
	jmp	fopen_NULL
    fopen_25:
	cmp	ax,DEV_CHAR
	jne	fopen_26
	or	flag,FH_DEVICE
    fopen_26:
	or	flag,FH_OPEN
	mov	ax,flag
	mov	_osfile[si],al
	test	al,FH_DEVICE or FH_PIPE
	jnz	fopen_30
	test	al,FH_TEXT
	jz	fopen_30
	test	oflag,O_RDWR
	jz	fopen_30
	push	si
	mov	ax,-1
	push	ax
	push	ax
	push	SEEK_END
	call	lseek
	mov	word ptr filepos,ax
	mov	word ptr filepos+2,dx
	cmp	dx,-1
	jne	fopen_27
	cmp	ax,-1
	jne	fopen_27
	cmp	errno,EINVAL
	je	fopen_30
	push	si
	call	close
    fopen_NULL:
	xor	ax,ax
	cwd
	jmp	fopen_32
    fopen_30:
	mov	ax,flag
	and	ax,FH_DEVICE or FH_PIPE
	jnz	fopen_33
	test	oflag,O_APPEND
	jz	fopen_33
    fopen_31:
	or	_osfile[si],FH_APPEND
    fopen_33:
	mov	bx,fpo
	mov	ax,sflag
	mov	[bx.iob_flag],ax
	xor	ax,ax
	mov	[bx.iob_cnt],ax
	mov	word ptr [bx.iob_bp],ax
	mov	word ptr [bx.iob_bp+2],ax
	mov	word ptr [bx.iob_base],ax
	mov	word ptr [bx.iob_base+2],ax
	mov	[bx.iob_file],si
	mov	dx,ds
	mov	ax,bx
	jmp	fopen_32
    fopen_29:
	push	si
	push	0
	push	0
	push	SEEK_SET
	call	lseek
	cmp	dx,-1
	jne	fopen_30
	cmp	ax,dx
	je	fopen_28
	jmp	fopen_30
    fopen_27:
	xor	ax,ax
	mov	word ptr MODE,ax
	push	si
	push	ss
	lea	dx,MODE
	push	dx
	inc	ax
	push	ax
	call	osread
	test	ax,ax
	jnz	fopen_29
	mov	al,byte ptr MODE
	cmp	al,26
	jne	fopen_29
	push	si
	push	word ptr filepos+2
	push	word ptr filepos
	call	chsize
	cmp	dx,-1
	jne	fopen_29
	cmp	ax,dx
	jne	fopen_29
    fopen_28:
	push	si
	call	close
	jmp	fopen_NULL
    fopen_32:
	pop	di
	pop	si
	ret
PEND	fopen

	END
