ABSOFT FORTRAN Big Files

Here is my code for using Windows API for accessing big files >>4GB. I have now used this to substitute for most standard disk I/O.

This only works on Windows 2000 and Windows XP: earlier versions of Windows do not support files larger than 4GB and report "SetFilePointerEx does not exist in Kernel32.dll"

Example:

            CHARACTER*20 MYRECORD
            K = 100
            CALL OPENWRITES (36, 'myfile.txt')
            IF (IOS.NE.0) GOTO 9140
            DO 8140 I = 1, K
                CALL WRITES (36, 'hello world')
            IF (IOS.NE.0) GOTO 9140
8140           CONTINUE
            CALL CLOSEFILE (36)
            IF (IOS.NE.0) GOTO 9140
            CALL OPENREADS (36, 'myfile.txt')
            IF (IOS.NE.0) GOTO 9140
  DO WHILE (IOS.NE.0)
               CALL READS (36, MYRECORD)
               IF (IOS.EQ.0) WRITE (*,*) MYRECORD
            END DO
            CALL CLOSEFILE (36)
            IF (IOS.NE.0) GOTO 9140
            ....
9140        ERROR CODE
c IOS has error code
c OLDFNUM has file number last accessed
c OLDFTYPE has last operation


File "iocommon.inc":

C AREA FOR 40 OUTPUT FILES USING WINAPI ACCESS
C THIS ALLOWS US TO USE BIG FILES FOR OUTPUT
C the structure to read a file directly
C allows positioning to suit ourselves

       INTEGER *4 FILECOUNT, BUFSIZE, IOS
       PARAMETER (FILECOUNT=40, BUFSIZE=80)

        STRUCTURE /APIFILEINFO/
C THE HANDLE GOES HERE
        INTEGER*4             FILELIST
C CURRENT POINTER IN RECORD
        INTEGER*4              bpointer
C BYTES READ IN
        INTEGER*4              bread
C IOS FOR NEXT TIME, E.G., END-OF-FILE
        INTEGER*4              NEXTIOS
C FOR RANDOM ACCESS: RECORD SIZE
        INTEGER*4              RECSIZE
C READ BUFFER
        CHARACTER*(BUFSIZE)    buffer

        END STRUCTURE

 record /APIFILEINFO/ fp(FILECOUNT)

C HOLD TO CHECK VALIDITY
        INTEGER*4 iocommonF, OLDFNUM
        CHARACTER*8 OLDFTYPE
        CHARACTER*260 iocommonP
        COMMON /OVERINC/ IOS, fp, iocommonF, iocommonP, OLDFNUM, OLDFTYPE


I/O ROUTINES:
c 3.56.2 problem with file names in FULLPATH
***************************************************
*
*   Various file and API routines
*

        global define
        include "windef.inc"
        include "winuser.inc"
          include "commdlg.inc"
          include "winbase.inc"
        include "winreg.inc"
        EXTERNAL AITOCFN, ITOCFN
        CHARACTER*12 AITOCFN, ITOCFN
        end


***************************************************
*
*  OPENREADR - open readING random
*
        subroutine OPENREADR (fnumber, pathin, reclen)
c the file handle is stored in ohandle
        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        integer*4 fnumber, ohandle, reclen

        CHARACTER*(*) pathin
        CHARACTER*(260) pathname

        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA

        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'OPNREADR'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 !incorrect function
        ELSEIF (fp(fnumber).FILELIST.NE.INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS STILL OPEN
            CALL WRITESUB ('OPEN FILE FOR READ RANDOM: FILE HANDLE '
     +         //TRIM(AITOCFN(fnumber))//' ALREADY IN USE: '//TRIM(pathin))
            IOS = 85
        ELSE
            pathname = trim(pathin)//char(0)
            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val(GENERIC_READ),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(OPEN_EXISTING),val(FILE_FLAG_RANDOM_ACCESS),
     +                      val(0))
C SAVE HANDLE
            fp(fnumber).FILELIST = ohandle

            if (ohandle == INVALID_HANDLE_VALUE) then
C ERROR RETURNS IN IOS
              IOS = GetLastError()
            ENDIF
c nothing in the input buffer yet. No error message waiting.
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            fp(fnumber).buffer=' '
            fp(fnumber).RECSIZE=reclen
          endif

          END

***************************************************
*
* CLOSEFILE
* the old CLOSEFILE IS fnumber = 40
*
        subroutine CLOSEFILE (fnumber)
c the file handle is stored in
        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        integer iostat, fnumber, ohandle

        IOS=0
        OLDFNUM = fnumber
        OLDFTYPE = 'CLOSE'

        if ((fnumber.ge.0).and.(fnumber.le.FILECOUNT)) then
            ohandle = fp(fnumber).FILELIST
            fp(fnumber).buffer=' '
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            if (ohandle == INVALID_HANDLE_VALUE) then
c nothing is open
            else
c flag nothing in the buffer
                 iostat = CloseHandle(val(ohandle))
                 if (iostat == 0) then
                     IOS = GetLastError()
                 endif
C SHOW THAT NOTHING IS OPEN
                 fp(fnumber).FILELIST = INVALID_HANDLE_VALUE
             endif
        endif
        end


***************************************************
*
*       OPENWRITES (pathin, fnumber)
*
* OPEN WRITE SEQUENTIAL
*
* use 40 for old unnumbered OPENFILE

        SUBROUTINE OPENWRITES (fnumber, pathin)
        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) pathin
        character*260 pathname
        integer *4 fnumber, ohandle
        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA

C SHOW NO ERROR
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'OPNWRITS'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function

        ELSEIF (fp(fnumber).FILELIST.NE.INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS STILL OPEN
            CALL WRITESUB ('OPEN FILE FOR WRITE SEQUENTIAL: FILE HANDLE '
     +         //TRIM(AITOCFN(fnumber))//' ALREADY IN USE: '//TRIM(pathin))
            IOS = 85
        ELSE
            pathname = trim(pathin)//char(0)

            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val(GENERIC_WRITE),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(CREATE_ALWAYS),val(FILE_FLAG_SEQUENTIAL_SCAN),
     +                      val(0))

            if (ohandle == INVALID_HANDLE_VALUE) then
              IOS = GetLastError()
            ENDIF
C ERROR RETURNS IN IOS
c nothing in the input buffer yet. No error message waiting.
            fp(fnumber).FILELIST = ohandle
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            fp(fnumber).buffer=' '
        ENDIF
        END


***************************************************
*
*  OPENREADS - SEQUENTIAL
*
        subroutine OPENREADS (fnumber, pathin)
c the file handle is stored in ohandle

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        integer*4 fnumber, ohandle

        CHARACTER*(*) pathin
        CHARACTER*(260) pathname

        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA

        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'OPNREADS'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 !incorrect function
        ELSEIF (fp(fnumber).FILELIST.NE.INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS STILL OPEN
            CALL WRITESUB ('OPEN FILE FOR READ SEQUENTIAL: FILE HANDLE '
     +         //TRIM(AITOCFN(fnumber))//' ALREADY IN USE: '//TRIM(pathin))
            IOS = 85
        ELSE
            pathname = trim(pathin)//char(0)
            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val(GENERIC_READ),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(OPEN_EXISTING),val(FILE_FLAG_SEQUENTIAL_SCAN),
     +                      val(0))
C SAVE HANDLE


            if (ohandle == INVALID_HANDLE_VALUE) then
C ERROR RETURNS IN IOS
              IOS = GetLastError()
            ENDIF
c nothing in the input buffer yet. No error message waiting.
            fp(fnumber).FILELIST = ohandle
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            fp(fnumber).buffer=' '
          endif

          END


***************************************************
*
*   WRITEMORES - WRITING MORE SEQUENTIAL
* to output without writing an crlf MARKER
*
        subroutine WRITEMORES (fnumber, wbuffer)

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) wbuffer
        integer ohandle, fnumber

c m is the number of bytes written
        integer m, iostat

C SHOW NO ERROR
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'WRTMORES'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function
        ELSE
            ohandle = fp(fnumber).FILELIST
            IF (ohandle == INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS not OPEN
                IOS = 114
            ELSE
C CHANGE TO LENGTH BUFFER - TO ALLOW INTERMEDIATE BLANKS 3.49
         iostat = WriteFile(val(ohandle),val(loc(wbuffer)),
     +             val(len(wbuffer)),val(loc(m)),val(0))
                if (iostat == 0) then
                    IOS = GetLastError()
                endif
            endif
         endif
         end


***************************************************
*
*   WRITES : WRITE SEQUENTIAL WITH CRLF

*
        subroutine WRITES (fnumber, wbuffer)

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) wbuffer
        integer ohandle, fnumber

        integer m, iostat

C SHOW NO ERROR
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'WRITSEQU'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function
        ELSE
            ohandle = fp(fnumber).FILELIST
            if (ohandle == INVALID_HANDLE_VALUE) then
                IOS = 114
            else
                if (len_trim(wbuffer).eq.0) then
c always write out at least one blank
                 iostat = WriteFile(val(ohandle),val(loc(" ")),
     +                  val(1),val(loc(m)),val(0))
                else
c else write out the value
                 iostat = WriteFile(val(ohandle),val(loc(wbuffer)),
     +                  val(len_trim(wbuffer)),val(loc(m)),val(0))
                endif
                if (iostat == 0) then
                    IOS = GetLastError()
                    return
                endif

c value is little-endian
                iostat = WriteFile(val(ohandle),val(loc(z'0a0d')),
     +                             val(2),val(loc(m)),val(0))
                if (iostat == 0) then
                    IOS = GetLastError()
                    return
                endif
             endif
         endif
         end


***************************************************
*
        SUBROUTINE REWINDFILE (fnumber)
c restart the text input file
        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        integer *4 fnumber, iostat, ohandle
        integer*4 SetFilePointer
        stdcall external SetFilePointer

c        CALL WRITESUB ('rewindfile'//AITOCFN( fnumber))
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'REWIND'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function
        ELSE
            ohandle = fp(fnumber).FILELIST
            if (ohandle == INVALID_HANDLE_VALUE) then
                IOS = 114
            else
                iostat = SetFilePointer
     +             (val(ohandle),
     +              val(0),val(0),
     +              val(FILE_BEGIN))
           endif
        endif
C NOT SURE ABOUT THE ERROR MESSAGE HERE ....
        fp(fnumber).bpointer =0
        fp(fnumber).bread  = 0
        fp(fnumber).NEXTIOS = 0
        fp(fnumber).buffer = " "
        END



***************************************************
*
*  READS READING SEQUENTIAL WITH EOL CODES
*  BYPASS EOF CODE
* 0 for datalen
        subroutine READS (fnumber, data)

c datalen is number of bytes input
c data is the buffer to put them in

c if datalen=0, then we have reached end-of-file
c this never returns null records!
c the file handle is stored in

c fp(fnumber).buffer has what is left over in the buffer
c buffer(bpointer) is the next byte in the buffer to read
c buffer(bread) is the last byte in the buffer

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) data
        integer p_buffer, datalen

       EXTERNAL ITOCFN
       CHARACTER*12 ITOCFN

        integer iostat, lNEXTIOS
        logical eoline, crlffound
        integer*4 a, d, bend, fnumber, ohandle, lbread, lbpointer, bincr, datamax
        CHARACTER*(BUFSIZE) lbuffer
        POINTER (plbuffer,lbuffer), (plbread, lbread), (plbpointer,lbpointer)
        pointer (plNEXTIOS, lNEXTIOS)

        datalen=0
        IOS=0
        OLDFNUM = fnumber
        OLDFTYPE = 'READSEQU'
        datamax=len(data)
c initialize
        data = ' '
        crlffound = .FALSE.
C SHOW NO ERROR
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1  ! incorrect function
        ELSE
            ohandle = fp(fnumber).FILELIST
            IF (ohandle == INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS not OPEN
                IOS = 114
            ELSE
                p_buffer = loc(fp(fnumber).buffer)
                plbuffer = loc(fp(fnumber).buffer)
                plbread = loc(fp(fnumber).bread)
                plbpointer = loc(fp(fnumber).bpointer)
                plNEXTIOS = loc(fp(fnumber).NEXTIOS)

                IF (lNEXTIOS.NE.0) THEN
C READING IN A RECORD LAST TIME THAT WAS AN ERROR OR eof THIS TIME
                    IOS = lNEXTIOS
                    GOTO 100
                ENDIF

                eoline=.FALSE.
c loop until we hit the end-of-line
                do while (.not.eoline)
                   if ((lbpointer.lt.1).or.
     +                 (lbpointer.gt.lbread)) then


c we need to readING another record into the buffer
                       lbuffer(1:BUFSIZE) =" "
                       lbread=0
                       lNEXTIOS=0
                       iostat = ReadFile(val(ohandle),val(p_buffer),
     +                               val(BUFSIZE), lbread,val(0))

                       if (iostat == 0) then
c an error was encountered: report next time?
                           lNEXTIOS = GetLastError()
                           eoline=.true.
                           lbpointer=0
                       elseif (lbread.eq.0) then
c end-of-file encountered
                           lNEXTIOS = -1
                           eoline=.true.
                           lbpointer=0
                       ENDIF
c what do we find? - if it is 0a or 0d, we are at eofline
c empty buffer from bread onwards - to clear the problem
                       lbpointer=1
                   endif
c let's look for the next 0a or 0d
c look for next line in current buffer
                   do while ((lbpointer.le.lbread).and.(.not.eoline))
                       a = index(lbuffer(lbpointer:lbread),char(10))  !LF
                       d = index(lbuffer(lbpointer:lbread),char(13))  !CR
                       if ((a.eq.0).and.(d.eq.0)) then
                           if (lbread.ge.lbpointer) then
                            if (datalen+1.le.datamax) then
                               data(datalen+1:) = lbuffer(lbpointer:lbread)
                               datalen = min(datamax, datalen + lbread - lbpointer + 1)
                            endif
                           endif
                           lbpointer = lbread+1
                       else
                           crlffound = .TRUE.
c we found an end of line
                           bincr=1
                           if (a.eq.0) then
                               bend = d
                           elseif (d.eq.0) then
                               bend = a
                           else
                               bend = min(a,d)
c 2 codes next to each other
                               if ((a.eq.d+1).or.(a+1.eq.d)) bincr=2
                           endif
c point to byte before EOL code
                           bend = bend + lbpointer - 2
                           if (bend.ge.lbpointer) then
                              if (datalen+1.le.datamax) then
                                data(datalen+1:) = lbuffer(lbpointer:bend)
                                datalen = min(datamax,datalen + bend - lbpointer + 1)
                              endif
                           endif
c skip an eol codes
                           lbpointer = bend + bincr +1
c is the next one at the start of the next record?
                           if ((bincr.eq.1).and.(lbpointer.eq.BUFSIZE+1)
     +                         .and.(IOS.eq.0).and.(lNEXTIOS.eq.0)) then
c readING in the next record and check the first character
c we may have overshot the butter!
c next record may start with an EOL code!
c readING it into the buffer
                               lbuffer(1:BUFSIZE) =" "
                               lbread = 0
                               lbpointer=0
                               iostat = ReadFile(val(ohandle),val(p_buffer),
     +                               val(BUFSIZE), lbread,val(0))
                               if (iostat == 0) then
c nothing was readING in
                                   lNEXTIOS = GetLastError()
                                   lbpointer=0
                               elseif (lbread.eq.0) then
                                   lNEXTIOS = -1
                                   lbpointer=0
                               elseif
     +  (((lbuffer(1:1).eq.char(10)).and.(a.eq.0)) .or.
     +   ((lbuffer(1:1).eq.char(13)).and.(d.eq.0))) then
c the other of a pair
c skip an eol code
                                   lbpointer=2
                               else
                                   lbpointer=1
                               endif
                           endif
                           eoline = .TRUE.
                       endif
                   enddo
                enddo

C DID WE HAVE A LAST LINE THAT CONCLUDES WITH CHAR(26)
c if we are at the end-of-file is char(26) the last byte: DOS EOF
                if (.not.crlffound) then
c last record of the file
                   if (datalen.gt.0) then
                     if (data(datalen:datalen).eq.char(26)) then
                       data(datalen:datalen)=' '
                       datalen=datalen-1
                     endif
                   endif
c nothing in the line, so end-of-file after CRLF
                   if (datalen.eq.0) IOS=lNEXTIOS
                endif
            endif
        endif
100     CONTINUE
        end


***************************************************
*
*  OPENWRITER - OPEN WRITE RANDOM
*
        subroutine OPENWRITER (fnumber, pathin, reclen)
c the file handle is stored in ohandle

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        integer*4 fnumber, ohandle, reclen

        CHARACTER*(*) pathin
        CHARACTER*(260) pathname

        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA

        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'OPNWRITR'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 !incorrect function
        ELSEIF (fp(fnumber).FILELIST.NE.INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS STILL OPEN
            CALL WRITESUB ('OPEN FILE FOR WRITE RANDOM: FILE HANDLE '
     +         //TRIM(AITOCFN(fnumber))//' ALREADY IN USE: '//TRIM(pathin))
            IOS = 85
        ELSE
            pathname = trim(pathin)//char(0)
            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val(GENERIC_WRITE),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(CREATE_ALWAYS),val(FILE_FLAG_RANDOM_ACCESS),
     +                      val(0))

            if (ohandle == INVALID_HANDLE_VALUE) then
C ERROR RETURNS IN IOS
              IOS = GetLastError()
            ENDIF
c nothing in the input buffer yet. No error message waiting.
            fp(fnumber).FILELIST = ohandle
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            fp(fnumber).buffer=' '
            fp(fnumber).RECSIZE=reclen
          endif

          END


***************************************************
*
*   WRITER WRITING RANDOM
* to output a fixed length random record
* wbuffer - what to write
* fnumber - the file number
* rnumber - the record number

        subroutine WRITER (fnumber, wbuffer, rnumber)

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) wbuffer
        integer ohandle, fnumber

c m is the number of bytes written
        integer m, iostat, rnumber, reclen, TYPE

c these are 8 bit characters
c fset(1) is the low order: fset(2) is the high order
c the computation wraps the negative!
        integer*4 fset(2), fplace(2)

        integer*4 SetFilePointerEx
        stdcall external SetFilePointerEx
        integer*4 SetFilePointer
        stdcall external SetFilePointer

C SHOW NO ERROR
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'WRITERAN'

        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function
        ELSE
            ohandle = fp(fnumber).FILELIST
            IF (ohandle == INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS not OPEN
                IOS = 114
            ELSE
                   fplace(1)=0
                   fplace(2)=0
                   reclen = fp(fnumber).RECSIZE
c multiply the record length by the record number by the

               CALL MULT (reclen, rnumber, fset(1),TYPE)

               IF (TYPE.EQ.0) THEN
C 32-bit address
                iostat = SetFilePointer
     +             (val(ohandle),
     +              val(fset(1)),val(0),
     +              val(FILE_BEGIN))

               ELSE
c produces reclen*(rnumber-1)+1 - 64 BIT ADDRESS
                iostat = SetFilePointerEx
     +             (val(ohandle),
     +              val(fset(1)),val(fset(2)),
     +              val(loc(fplace(1))),
     +              val(FILE_BEGIN))
               ENDIF
c

c ok don't overshoot reclen
               iostat = WriteFile(val(ohandle),val(loc(wbuffer)),
     +             val(reclen),val(loc(m)),val(0))
                if (iostat == 0) then
                    IOS = GetLastError()
                endif
            endif
         endif
         end

***************************************************
*
*   READR
* to input a fixed length random record
* wbuffer - where to store the readING material
* fnumber - the file number
* rnumber - the record number
*
        subroutine READR (fnumber, wbuffer, rnumber)

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) wbuffer
        integer ohandle, fnumber

c m is the number of bytes written
        integer iostat, rnumber, reclen, lbread, TYPE

c these are 8 bit characters
c fset(1) is the low order: fset(2) is the high order
c the computation wraps the negative!
        integer*4 fset(2), fplace(2)

        integer*4 SetFilePointerEx
        stdcall external SetFilePointerEx
        integer*4 SetFilePointer
        stdcall external SetFilePointer

c        CALL WRITESUB ('readr'//AITOCFN( fnumber))
cc      READ (5,'(A)') TLINE
C SHOW NO ERROR
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'READRAND'

        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function
        ELSE
            ohandle = fp(fnumber).FILELIST
            IF (ohandle == INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS not OPEN
                IOS = 114
            ELSE
C CHANGE TO LENGTH BUFFER - TO ALLOW INTERMEDIATE BLANKS 3.49
c ok - position correctly
c we have trouble incrementing
c                   fset(1)=0
c                   fset(2)=0
                   fplace(1)=0
                   fplace(2)=0
                   reclen = fp(fnumber).RECSIZE

c multiply the record length by the record number by the
                   CALL MULT (reclen, rnumber, fset(1), TYPE)
               IF (TYPE.EQ.0) THEN
C 32-bit address: maintains compatibility with Windowss-98
                iostat = SetFilePointer
     +             (val(ohandle),
     +              val(fset(1)),val(0),
     +              val(FILE_BEGIN))

               ELSE
c produces reclen*(rnumber-1)+1

                iostat = SetFilePointerEx
     +             (val(ohandle),
     +              val(fset(1)),val(fset(2)),
     +              val(loc(fplace(1))),
     +              val(FILE_BEGIN))
               ENDIF
c ok don't overshoot reclen
                iostat = ReadFile(val(ohandle),val(loc(wbuffer)),
     +                               val(reclen), lbread, val(0))
                if (iostat == 0) then
                    IOS = GetLastError()
                endif
            endif
         endif
         end


*************************************************************************
*
* MULT  32 x 32 to 64
*
c produces reclen*(rnumber-1)+1
c           Y32-1  z32-1

        SUBROUTINE MULT (Y32,Z32, X64, TYPE)
        IMPLICIT NONE
        AUTOMATIC

C THIS MULTIPLES TWO 32-BITS INTO A  64-BIT
        INTEGER*4 X64(2), Y32, Z32

C THE INPUT VALUES
        INTEGER*4   Z1, Y1
C       INTEGER*32  BIT32
        CHARACTER*4 Z1C, Y1C
        EQUIVALENCE (Z1C, Z1)
        EQUIVALENCE (Y1C, Y1)

C THE OUTPUT VALUES
        INTEGER*4   H(2), TYPE
        CHARACTER*8 H64
        EQUIVALENCE (H(1), H64)

C INTERMEDIATE VALUES
        INTEGER*4 W1, W2, W3, W4
        CHARACTER*4 W1C, W2C, W3C, W4C
        EQUIVALENCE (W1C, W1)
        EQUIVALENCE (W2C, W2)
        EQUIVALENCE (W3C, W3)
        EQUIVALENCE (W4C, W4)
c        STDCALL EXTERNAL UInt32x32To64
c        INTEGER*4 UInt32x32To64
C POINTERS
        INTEGER*4 I1, I2, I3, I11,I12
        INTEGER*4 MAX32
        PARAMETER (MAX32 = 2147483647)
C WHEN WE FIND OUT HOW TO ACTION THIS!
c        INTEGER*4 LONGLONG(2)
c        LONGLONG(1) = UInt32x32To64 (val(Y),val(Z))

C TRANSFER INPUT VALUES
        Y1=Y32
c subtract 1 from the record number
        Z1=Z32-1

C INITIALIZE THE FIELDS
C CAN WE DO A 32-BIT OPERATION?
        W1 = MAX32 / Y1
        IF (Z1.LE.W1) THEN
C WE CAN DO 32-BIT MULTIPLICATION!
            X64(1)=Y1*Z1
            TYPE = 0
C THIS IS A 32-BIT ADDRESS: FOR WINDOWS-98
            RETURN
        ENDIF

C FOR 64 BIT MULTIPLICATION
        TYPE = 1
        H(1)=0
        H(2)=0
        W1=0
        W2=0
c the first byte is byte 0
        W3=0
        W4=0

C OK THE MULTIPLICATION IS IN 8 BIT ARITHMETIC
C GO DOWN IN SUMMING PAIRS
c start by adding 1
        DO 1 I1 = 2, 8
           I11 = MAX(1,I1-4)
           I12 = MIN(4,I1-1)
           DO 2 I2 = I11,I12
              I3 = I1-I2
C GO DOWN Y FIELD
              W1C(1:1) = Y1C(I2:I2)
C GO DOWN Z FIELD
              W2C(1:1) = Z1C(I3:I3)
C MULTIPLY - W3 NO HAS 16 BITS ACTIVE
              W3 = W3 + W1 * W2
2          CONTINUE
C TRANSFER TO THE 64 BIT VALUE
           IF (W3.GT.0) THEN
               H64(I1-1:I1-1) = W3C(1:1)
C FOR WHAT CARRIES OVER
               W4C(1:3) = W3C(2:4)
               W3 = W4
           ENDIF
1       CONTINUE

        X64(1)=H(1)
        X64(2)=H(2)

       END



***************************************************
*
*  OPENREADWR - open read-write random
*
        subroutine OPENREADWR (fnumber, pathin, reclen)
c the file handle is stored in ohandle

        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"

        integer*4 fnumber, ohandle, reclen
        CHARACTER*(*) pathin
        CHARACTER*(260) pathname
        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA

        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'OPENRDWR'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 !incorrect function
        ELSEIF (fp(fnumber).FILELIST.NE.INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS STILL OPEN
            CALL WRITESUB ('OPEN FILE FOR READ-WRITE RANDOM: FILE HANDLE '
     +         //TRIM(AITOCFN(fnumber))//' ALREADY IN USE: '//TRIM(pathin))
            IOS = 85
        ELSE
            pathname = trim(pathin)//char(0)
            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val((GENERIC_READ).or.(GENERIC_WRITE)),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(OPEN_ALWAYS),val(FILE_FLAG_RANDOM_ACCESS),
     +                      val(0))
C SAVE HANDLE
            fp(fnumber).FILELIST = ohandle

            if (ohandle == INVALID_HANDLE_VALUE) then
C ERROR RETURNS IN IOS
              IOS = GetLastError()
            ENDIF
c nothing in the input buffer yet. No error message waiting.
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            fp(fnumber).buffer=' '
            fp(fnumber).RECSIZE=reclen
          endif

          END


***************************************************
*
*       OPENWRITESA (pathin, fnumber)
*
* OPEN WRITE SEQUENTIAL APPEND
*

        SUBROUTINE OPENWRITESA (fnumber, pathin)
        IMPLICIT NONE
        AUTOMATIC
        include "iocommon.inc"
        character*(*) pathin
        character*260 pathname
        integer *4 fnumber, ohandle, iostat
        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA
        integer*4 SetFilePointer
        stdcall external SetFilePointer

C SHOW NO ERROR
        IOS = 0
        OLDFNUM = fnumber
        OLDFTYPE = 'OPENWRSA'
        IF ((fnumber.lt.1).or.(fnumber.gt.FILECOUNT)) then
c file number out of range: programming bug
            IOS = 1 ! incorrect function

        ELSEIF (fp(fnumber).FILELIST.NE.INVALID_HANDLE_VALUE) THEN
C THIS FILE NUMBER IS STILL OPEN
            CALL WRITESUB ('OPEN FILE FOR READ SEQUENTIAL APPEND: FILE HANDLE '
     +         //TRIM(AITOCFN(fnumber))//' ALREADY IN USE: '//TRIM(pathin))
            IOS = 85
        ELSE
            pathname = trim(pathin)//char(0)

            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val(GENERIC_WRITE),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(OPEN_ALWAYS),val(FILE_FLAG_SEQUENTIAL_SCAN),
     +                      val(0))

            if (ohandle == INVALID_HANDLE_VALUE) then
              IOS = GetLastError()
            ENDIF
C ERROR RETURNS IN IOS
c nothing in the input buffer yet. No error message waiting.
            fp(fnumber).FILELIST = ohandle
            fp(fnumber).bpointer=0
            fp(fnumber).bread=0
            fp(fnumber).NEXTIOS = 0
            fp(fnumber).buffer=' '
C NOW WE NEED TO POSITION AT EOF: COMPATIBLE WITH WINDOWS-98
                iostat = SetFilePointer
     +             (val(ohandle),
     +              val(0),val(0),
     +              val(FILE_END))

        ENDIF
        END


***************************************************
*
* DELETEFILE
*
        subroutine DELETEFILE (pathin)
c the file handle is stored in
         IMPLICIT NONE
         AUTOMATIC
        CHARACTER*(*) pathin
        CHARACTER*261 pathname

        integer iostat
        integer DeleteFile
      stdcall external DeleteFile

c        CALL WRITESUB ('deletefile: '//trim(pathin))
        pathname = trim(pathin)//char(0)

        iostat = DeleteFile (val(loc(pathin)))
        END

***************************************************
*
*  INQUIREFILE - does file exist
*
        LOGICAL FUNCTION INQUIREFILE (pathin)
C       LOGICAL INQUIREFILE
C       EXTERNAL INQUIREFILE

         IMPLICIT NONE
         AUTOMATIC
        CHARACTER*(*) pathin
        CHARACTER*261 pathname

        integer iostat

c        CALL WRITESUB ('INQUIREfile: '//trim(pathin))
        pathname = trim(pathin)//char(0)

        iostat = GetFileAttributes (val(loc(pathname)))

        if (iostat.EQ.-1) THEN
           INQUIREFILE = .FALSE.
        ELSE
           INQUIREFILE = .TRUE.
        ENDIF
        END

***************************************************
*
*  SIZEFILE - does file exist
*
        INTEGER*4 FUNCTION SIZEFILE (pathin)
C       INTEGER*4 SIZEFILE
C       EXTERNAL SIZEFILE

         IMPLICIT NONE
         AUTOMATIC
        CHARACTER*(*) pathin
        CHARACTER*261 pathname

        integer iostat, ohandle, high
        integer CreateFileA            ! avoids using wrapper "winbase.f"
        stdcall external CreateFileA

        pathname = trim(pathin)//char(0)
C TRY TO OPENTHE FILE
            ohandle = CreateFileA(
     +                      val(loc(pathname)),
     +                      val(GENERIC_READ),
     +                      val(FILE_SHARE_READ.OR.FILE_SHARE_WRITE),
     +                      val(0),
     +                      val(OPEN_EXISTING),val(FILE_ATTRIBUTE_NORMAL),
     +                      val(0))
         if (ohandle == INVALID_HANDLE_VALUE) then
c show zero length
             iostat = 0
         else

             iostat = GetFileSize (val(ohandle), val(loc(high)))
             if (iostat.eq.-1) then
c probably an error
                 iostat = GetLastError()
                 if (iostat.eq.NO_ERROR) then
c non-zero size
                     iostat = 1
                 else
                     iostat = 0
                 endif
             endif
c we don't want this return code to foul things up
             high = CloseHandle(val(ohandle))
c iostat has a size indicator
         endif
         SIZEFILE = iostat
        END

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
c
        CHARACTER*12 FUNCTION AITOCFN (IFIELD)
        IMPLICIT NONE
        AUTOMATIC
c SET UP THE CONVERSION AS A FUNCTION
C LEFT ADJUSTS
C       EXTERNAL AITOCFN
C       CHARACTER*12 AITOCFN
C          AITOCFN(IFIELD)
        CHARACTER*12 OFIELD
        INTEGER*4 IFIELD
        CALL IEDIT (IFIELD, OFIELD)
        AITOCFN = ADJUSTL(OFIELD)
        END

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
c **
*   Subroutines for internal writes which cause problems!
*    THIS RIGHT-ALIGNS AN INTEGER FROM IFIELD INTO OFIELD
*
        SUBROUTINE  IEDIT (IFIELD, OFIELD)
        IMPLICIT NONE
        AUTOMATIC
C EXAMPLE
C        CALL IEDIT (SC+MINSCORE,WORKP(1:6))

        INTEGER*4 IFIELD, POINTER, IWORK, IHOLD, DIGIT, ISIGN
        CHARACTER*(*) OFIELD
        CHARACTER*10 DIGITS
        REAL*8 OMAX, OMIN
C X changed to * in 2.42
 DATA DIGITS/'0123456789'/

        IF ((IFIELD.GT.0).AND.(LEN(OFIELD).LT.10)) THEN
C IN CASE OVERFLOW PLUS
            OMAX = 10**LEN(OFIELD)
            IF (IFIELD.GE.OMAX) THEN
              OFIELD = REPEAT('9',LEN(OFIELD))
              RETURN
            ENDIF

        ELSEIF ((IFIELD.LT.0).AND.(LEN(OFIELD).LT.11)) THEN
C IN CASE OVERFLOW MINUS
           OMIN = -10**(LEN(OFIELD)-1)
           IF (IFIELD.LE.OMIN) THEN
              OFIELD = '-'//REPEAT('9',LEN(OFIELD)-1)
              RETURN
           ENDIF
        ENDIF

        OFIELD = ' '
        IHOLD = ABS(IFIELD)
* NOW PICK UP THE DIGITS
        DO 10 POINTER = LEN(OFIELD),1,-1
           IWORK = IHOLD/10
           DIGIT = IHOLD - IWORK*10 +1
           OFIELD(POINTER:POINTER) = DIGITS(DIGIT:DIGIT)
           IHOLD=IWORK
           IF (IHOLD.EQ.0) EXIT
10      CONTINUE
        IF (IFIELD.LT.0) THEN
            POINTER = MAX(1, POINTER-1)
            OFIELD(POINTER:POINTER) = '-'
        ENDIF
        END


Go to Top of Page
Go to Winsteps & Facets Home Page

Facets Rasch measurement software. Buy for $149. & site licenses. Freeware student/evaluation Minifac download
Winsteps Rasch measurement software. Buy for $149. & site licenses. Freeware student/evaluation Ministep download

Rasch Books and Publications: Winsteps and Facets
Applying the Rasch Model (Winsteps, Facets) 4th Ed., Bond, Yan, Heene Advances in Rasch Analyses in the Human Sciences (Winsteps, Facets) 1st Ed., Boone, Staver Advances in Applications of Rasch Measurement in Science Education, X. Liu & W. J. Boone Rasch Analysis in the Human Sciences (Winsteps) Boone, Staver, Yale Appliquer le modèle de Rasch: Défis et pistes de solution (Winsteps) E. Dionne, S. Béland
Introduction to Many-Facet Rasch Measurement (Facets), Thomas Eckes Rasch Models for Solving Measurement Problems (Facets), George Engelhard, Jr. & Jue Wang Statistical Analyses for Language Testers (Facets), Rita Green Invariant Measurement with Raters and Rating Scales: Rasch Models for Rater-Mediated Assessments (Facets), George Engelhard, Jr. & Stefanie Wind Aplicação do Modelo de Rasch (Português), de Bond, Trevor G., Fox, Christine M
Exploring Rating Scale Functioning for Survey Research (R, Facets), Stefanie Wind Rasch Measurement: Applications, Khine Winsteps Tutorials - free
Facets Tutorials - free
Many-Facet Rasch Measurement (Facets) - free, J.M. Linacre Fairness, Justice and Language Assessment (Winsteps, Facets), McNamara, Knoch, Fan
Other Rasch-Related Resources: Rasch Measurement YouTube Channel
Rasch Measurement Transactions & Rasch Measurement research papers - free An Introduction to the Rasch Model with Examples in R (eRm, etc.), Debelak, Strobl, Zeigenfuse Rasch Measurement Theory Analysis in R, Wind, Hua Applying the Rasch Model in Social Sciences Using R, Lamprianou El modelo métrico de Rasch: Fundamentación, implementación e interpretación de la medida en ciencias sociales (Spanish Edition), Manuel González-Montesinos M.
Rasch Models: Foundations, Recent Developments, and Applications, Fischer & Molenaar Probabilistic Models for Some Intelligence and Attainment Tests, Georg Rasch Rasch Models for Measurement, David Andrich Constructing Measures, Mark Wilson Best Test Design - free, Wright & Stone
Rating Scale Analysis - free, Wright & Masters
Virtual Standard Setting: Setting Cut Scores, Charalambos Kollias Diseño de Mejores Pruebas - free, Spanish Best Test Design A Course in Rasch Measurement Theory, Andrich, Marais Rasch Models in Health, Christensen, Kreiner, Mesba Multivariate and Mixture Distribution Rasch Models, von Davier, Carstensen
As an Amazon Associate I earn from qualifying purchases. This does not change what you pay.

facebook Forum: Rasch Measurement Forum to discuss any Rasch-related topic

To receive News Emails about Winsteps and Facets by subscribing to the Winsteps.com email list,
enter your email address here:

I want to Subscribe: & click below
I want to Unsubscribe: & click below

Please set your SPAM filter to accept emails from Winsteps.com
The Winsteps.com email list is only used to email information about Winsteps, Facets and associated Rasch Measurement activities. Your email address is not shared with third-parties. Every email sent from the list includes the option to unsubscribe.

Questions, Suggestions? Want to update Winsteps or Facets? Please email Mike Linacre, author of Winsteps mike@winsteps.com


State-of-the-art : single-user and site licenses : free student/evaluation versions : download immediately : instructional PDFs : user forum : assistance by email : bugs fixed fast : free update eligibility : backwards compatible : money back if not satisfied
 
Rasch, Winsteps, Facets online Tutorials

Coming Rasch-related Events
May 17 - June 21, 2024, Fri.-Fri. On-line workshop: Rasch Measurement - Core Topics (E. Smith, Winsteps), www.statistics.com
June 12 - 14, 2024, Wed.-Fri. 1st Scandinavian Applied Measurement Conference, Kristianstad University, Kristianstad, Sweden http://www.hkr.se/samc2024
June 21 - July 19, 2024, Fri.-Fri. On-line workshop: Rasch Measurement - Further Topics (E. Smith, Winsteps), www.statistics.com
Aug. 5 - Aug. 7, 2024, Mon.-Wed. 2024 Inaugural Conference of the Society for the Study of Measurement (Berkeley, CA), Call for Proposals
Aug. 9 - Sept. 6, 2024, Fri.-Fri. On-line workshop: Many-Facet Rasch Measurement (E. Smith, Facets), www.statistics.com
Oct. 4 - Nov. 8, 2024, Fri.-Fri. On-line workshop: Rasch Measurement - Core Topics (E. Smith, Winsteps), www.statistics.com
Jan. 17 - Feb. 21, 2025, Fri.-Fri. On-line workshop: Rasch Measurement - Core Topics (E. Smith, Winsteps), www.statistics.com
May 16 - June 20, 2025, Fri.-Fri. On-line workshop: Rasch Measurement - Core Topics (E. Smith, Winsteps), www.statistics.com
June 20 - July 18, 2025, Fri.-Fri. On-line workshop: Rasch Measurement - Further Topics (E. Smith, Facets), www.statistics.com
Oct. 3 - Nov. 7, 2025, Fri.-Fri. On-line workshop: Rasch Measurement - Core Topics (E. Smith, Winsteps), www.statistics.com

 

Our current URL is www.winsteps.com

Winsteps® is a registered trademark
 

The URL of this page is www.winsteps.com/g4.htm