EOF Function

Syntax

Syntax: result = EOF(#n)
Source: pb_cg_emit_eof (pb_codegen.c:6160)

Description

Returns -1 (TRUE) if the file pointer for file number #n has reached or passed the end of the file. Returns 0 (FALSE) if there is still data to read. EOF is typically used as the condition in a WHILE NOT EOF(#n) loop to read through all lines or records in a file.

Internally, EOF works by querying the total file size via GetFileSize and comparing it against the current file pointer position obtained via SetFilePointer with FILE_CURRENT. If the current position is greater than or equal to the file size, EOF returns TRUE.

Parameters

ParameterDescription
nThe integer file number to check. The file must be open.

Return Value

ValueMeaning
-1 (TRUE)File pointer is at or beyond the end of the file. No more data to read.
0 (FALSE)File pointer is before the end of the file. Data is still available.

Example

FUNCTION PBMAIN() AS LONG
    LOCAL ln AS STRING
    LOCAL count AS LONG

    count = 0
    OPEN "data.txt" FOR INPUT AS #1

    ' Read file line by line until EOF
    WHILE NOT EOF(1)
        INCR count
        LINE INPUT #1, ln
        PRINT count; ": "; ln
    WEND

    PRINT "Total lines: "; count
    CLOSE #1
    FUNCTION = 0
END FUNCTION

Binary Mode EOF Check

OPEN "data.bin" FOR BINARY AS #2
WHILE NOT EOF(2)
    GET #2, , val        ' read 4-byte LONG
    PRINT val
WEND
CLOSE #2

Generated Assembly

WinAPI Implementation

; EOF(#n) implementation using GetFileSize and SetFilePointer
; Step 1: Get total file size
mov    rcx, [rbp - handle_offset]       ; file handle
xor    rdx, rdx                         ; lpFileSizeHigh = NULL (32-bit size only)
call   [__imp_GetFileSize]              ; returns file size in EAX (0xFFFFFFFF on error)
cmp    rax, -1                          ; INVALID_FILE_SIZE
je     __pb_eof_error                   ; handle error, assume TRUE
mov    [rbp - file_size], rax            ; save total file size

; Step 2: Get current file pointer position
mov    rcx, [rbp - handle_offset]       ; file handle
xor    rdx, rdx                         ; lDistanceToMove = 0
xor    r8, r8                           ; lpDistanceToMoveHigh = NULL
mov    r9, 1                            ; FILE_CURRENT (move 0 bytes from current)
call   [__imp_SetFilePointer]           ; returns current position in EAX
mov    [rbp - current_pos], rax          ; save current position

; Step 3: Compare position against file size
mov    rax, [rbp - current_pos]
cmp    rax, [rbp - file_size]
jge    __pb_eof_true                    ; position >= file size -> TRUE
xor    rax, rax                         ; FALSE = 0
jmp    __pb_eof_done
__pb_eof_true:
mov    rax, -1                          ; TRUE = -1
__pb_eof_done:
; result is in RAX

__pb_eof_error:
mov    rax, -1                          ; on error, assume EOF = TRUE

Simplified/Alternative Path

; Some implementations cache the file size after each read.
; In that case, EOF is simply:
mov    rcx, [rbp - handle_offset]
xor    rdx, rdx
call   [__imp_GetFileSize]              ; get total size
cmp    [rbp - bytes_read_total], eax     ; compare cumulative bytes read
jae    __pb_eof_true                    ; if read >= total, EOF = TRUE
xor    rax, rax                         ; FALSE
jmp    __pb_eof_done
__pb_eof_true:
mov    rax, -1                          ; TRUE
__pb_eof_done:

Imported WinAPI Functions

FunctionDLLPurpose
GetFileSizekernel32.dllRetrieve the total size of the file in bytes
SetFilePointerkernel32.dllQuery current file pointer position with FILE_CURRENT (0 offset)

Notes