$include (..\lib\compStch.ext) /* *============================================================================ * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE * * Permission to use for any purpose, modify, copy, and make enhancements * and derivative works of the software is granted if attribution is given to * R.M. Gillmore, dba the ACME Software Deli, as the author * * While the ACME Software Deli does not work for money, there is nonetheless * a significant amount of work involved. The ACME Software Deli maintains the * rights to all code written, though it may be used and distributed as long as * the following conditions are maintained. * * 1. The copyright statement at the top of each code block is maintained in * your distribution. * 2. You do not identify yourself as the ACME Software Deli * 3. Any changes made to the software are sent to the ACME Software Deli *============================================================================ */ fopenModule: do; $if not noID declare IDString (*) byte data ( '@(#)fopen.p86 $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0 ); $endif $set( fopenSource ) $include (..\lib\fileIO.ext) $include (..\lib\sysCalls.ext) $include (..\lib\string.ext) $include (..\lib\errCode.ext) fopen: procedure ( fileNameString, openTypeString ) word reentrant public; declare fileNameString pointer, openTypeString pointer, fileHandle word; declare OPEN_FILE literally '0000$0001b', TRUNCATE_FILE literally '0000$0010b', CREATE_FILE literally '0001$0000b', /* * Bitfields for Windows95 file access/sharing modes: * * Bit(s) Description (Table 01782) * 2-0 file access mode. * 000 read-only. * 001 write-only. * 010 read-write. * 100 read-only, do not modify file's last-access time * 3 unused * 6-4 file sharing modes * 7 no-inherit flag * 8 do not buffer data (requires that all reads/writes be exact * physical sectors) * 9 do not compress file even if volume normally compresses files * 10 use alias hint in DI as numeric tail for short-name alias * 12-11 unused??? (0) * 13 return error code instead of generating INT 24h if critical * error while opening file * 14 commit file after every write operation */ /* file access/sharing modes */ READ_ONLY_MODE literally '000b', WRITE_ONLY_MODE literally '001b', READ_WRITE_MODE literally '010b'; declare cpuRegisters; declare openString based openTypeString (*) byte, index word, readSpecified boolean, writeSpecified boolean, startAtEnd boolean; readSpecified, writeSpecified, startAtEnd = FALSE; /* * parse the access flags. This will help us to know how were are to * open/create a file */ index = 0; do while ( openString( index ) <> NUL ); if ( openString( index ) = 'r' ) then readSpecified = TRUE; else if ( openString( index ) = 'w' ) then writeSpecified = TRUE; else if ( openString( index ) = '+' ) then do; startAtEnd = TRUE; readSpecified = TRUE; writeSpecified = TRUE; end; index = index + 1; end; if ( lfnSupported ) then do; call memset( @wordRegs, 0, size( wordRegs ) ); /* * We will get here when long file names are supported. */ wordRegs.Ax = 0716ch; wordRegs.Cx = 0; wordRegs.Ds = selector$of( fileNameString ); wordRegs.Si = offset$of( fileNameString ); /* * since long file names are supported, the write mode is specified using * the BX and DX registers */ if ( readSpecified and writeSpecified ) then do; wordRegs.Bx = READ_WRITE_MODE; wordRegs.Dx = OPEN_FILE or CREATE_FILE; end; else if ( readSpecified ) then do; wordRegs.Bx = READ_ONLY_MODE; wordRegs.Dx = OPEN_FILE; end; else if ( writeSpecified ) then do; wordRegs.Bx = WRITE_ONLY_MODE; wordRegs.Dx = TRUNCATE_FILE or CREATE_FILE; end; call int86( DOS_CALL, @wordRegs ); if ( not carryClear( @wordRegs ) ) then do; errno = wordRegs.Ax; fileHandle = unsign( -1 ); end; else do; fileHandle = wordRegs.Ax; errno = 0; if ( startAtEnd ) then do; call fseek( fileHandle, FROM_END_OF_FILE, 0 ); end; end; end; /* lfnSupported IS supported */ else do; /* lfnSupported is NOT supported */ call memset( @wordRegs, 0, size( wordRegs ) ); byteRegs.Ah = 3dh; /* Open Handle */ wordRegs.Cx = 0; /* let file attributes fall where they may */ wordRegs.Ds = selector$of( fileNameString ); wordRegs.Dx = offset$of( fileNameString ); /* * when long file names are NOT supported, creating a file is different * than simply opening it. What this logic will help us to do is to * open the file using the proper interrupt function */ if ( readSpecified and writeSpecified ) then do; byteRegs.Al = READ_WRITE_MODE; end; else if ( readSpecified ) then do; byteRegs.Al = READ_ONLY_MODE; end; else if ( writeSpecified ) then do; /* * create the file, not simply open it */ wordRegs.Ax = 3c00h; end; else do; byteRegs.Al = READ_ONLY_MODE; end; /* * make the call to DOS */ call int86( DOS_CALL, @wordRegs ); if ( not carryClear( @wordRegs ) ) then do; errno = 0; /* * If the file does not exist, and if writeSpecified is TRUE, * then we will create the file */ if ( writeSpecified ) then do; call memset( @wordRegs, 0, size( wordRegs ) ); byteRegs.Ah = 3ch; /* Open Handle */ wordRegs.Cx = 0; /* this must be zero because this should be * a "regular file" */ wordRegs.Ds = selector$of( fileNameString ); wordRegs.Dx = offset$of( fileNameString ); call int86( DOS_CALL, @wordRegs ); if ( not carryClear( @wordRegs ) ) then do; errno = wordRegs.Ax; fileHandle = unsign( -1 ); end; else do; fileHandle = wordRegs.Ax; errno = 0; end; end; else do; errno = wordRegs.Ax; fileHandle = 0ffffh; end; end; else do; errno = 0; fileHandle = wordRegs.Ax; if ( startAtEnd ) then do; call fseek( fileHandle, FROM_END_OF_FILE, 0 ); end; end; end; /* lfnSupported is NOT supported */ return ( fileHandle ); end fopen; end fopenModule;