EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

linf32.htm
Class
FILE
Encoding
FileStatusEnc
Macros
FileAppend
FileAssign
FileClose
FileCreate
FileDelete
FileEach
FileEnclose
FileEnclose$
FileEncloseLn
FileExists?
FileFlush
FileGetSize
FileLoad
FileMapCreate
FileMapOpen
FileMkDir
FileMove
FileNameParse
FileOpen
FileRead
FileReset
FileStore
FileStreamAppend
FileStreamCreate
FileStreamOpen
FileStreamRead
FileStreamReadByte
FileStreamReadLn
FileStreamWrite
FileStreamWriteByte
FileStreamWriteWord
FileStreamWriteDword
FileStreamWrite$
FileStreamWriteLn
FileWrite
FileWrite$
FileWriteLn

This library contains wrapper macros which encapsulate LinAPI calls for most typical file operations in 32bit Linux . See also equivalent homonymous macroinstructions in linf64.htm, winf32.htm, winf64.htm.

File Access methodOpenData transferClose
read file at once - FileLoad FileClose
write file at once - FileStore-
standard readFileOpen FileReadFileClose
standard writeFileCreate FileWrite, FileWriteLn, FileWrite$FileClose
standard write at the end of fileFileAppend FileWrite, FileWriteLn, FileWrite$FileClose
memory mapped readFileMapOpen- FileClose
memory mapped writeFileMapCreate -FileClose
buffered readFileStreamOpen FileStreamReadByte, FileStreamRead, FileStreamReadLn FileClose
buffered writeFileStreamCreate FileStreamWriteByte, FileStreamWriteWord, FileStreamWriteDword, FileStreamWrite, FileStreamWriteLn, FileStreamWrite$FileClose
buffered write at end of fileFileStreamAppend FileStreamWriteByte, FileStreamWriteWord, FileStreamWriteDword, FileStreamWrite, FileStreamWriteLn, FileStreamWrite$FileClose
append to file - FileEnclose, FileEncloseLn, FileEnclose$-
special functionsFileReset FileAssign, FileExists?, FileNameParse, FileMove, FileMkDir, FileEach FileDelete

Macros return the results in registers, usually EAX. Other registers do not change. CF is set when error occurs, ZF is set at the end of file, DF must be always reset. Other flags are undefined.

Association of the FILE object with the name of file is provided separately, using the macro FileAssign. File must be assigned before opening.

Macro names suffixed with ~Ln write LineFeed character after the data. Macro names suffixed with ~$ expect NULL-terminated input data.

Acces methods at once, stream, memory-map allocate dynamic virtual memory. It will be freed in FileClose.

Access methodVirtual memory
reservedcomitted
At once loadfilesizefilesize
At once storenonenone
Standardnonenone
MemoryMappedfilesizepagesize
Streamedbuffersizebuffersize

File access method at once loads entire file content into comitted memory, so it is suitable for small files only. The loaded/stored file doesn't need explicit opening nor closing.

This access method is equivalent to PHP functions file_get_contents, file_put_contents.

Access method enclose opens the file at its end for writing, appends the data and closes file in one operation.

Standard read/write methods only encapsulate API functions read/write and they can process files of any size. Example:


[.bss] InpFile DS FILE OutFile DS FILE Record: DB 512 * BYTE [.text] FileAssign InpFile, ="Input.dat" FileAssign OutFile, ="Output.dat" FileOpen InpFile JC .InpErr: FileCreate OutFile JC .OutErr: .Next: FileRead InpFile, Record, SIZE# Record JC .InpErr: JZ .EOF: CALL ModifyRecord FileWrite OutFile, Record, SIZE# Record JC .OutErr: JMP .Next: .InpErr: StdOutput ="Error reading ",InpFile.Name JMP .EOF: .OutErr: StdOutput ="Error writing ",OutFile.Name .EOF: FileClose OutFile, InpFile TerminateProgram

Memory mapped file access reserves memory for the entire file contents virtually loaded to memory.

Streamed (buffered) file access method allocates its own memory buffer to accelerate reading/writing of small pieces of data. This method is also suitable for processing text files line by line. Example:

FileAssign InpFile, ="Input.txt" FileAssign OutFile, ="Output.txt" FileStreamOpen InpFile JC .Error: FileStreamCreate OutFile JC .Error: .Next:FileStreamReadLn InpFile JC .Error: JZ .EOF: MOV ECX,EAX ; EAX=Line size, ESI=pointer to the line in buffer. MOV EDI,WorkLine REP MOVSB CALL ModifyWorkLine FileStreamWrite OutFile, WorkLine, EAX JC .Error: JMP .Next: .EOF: FileClose OutFile, InpFile

Common limitations: This library cannot be used if special requirements are required, such as overlapped file access, other than normal file attributes, nonstandard share disposition, files bigger than 2 GB, filename longer than 260 characters.

Runtime procedures defined in this library use macros LinAPI, Dispatch, status32.htm.


linf32 HEAD
 INCLUDEHEAD1 lins.htm, linsfile.htm, linapi.htm, cpuext.htm, status32.htm
FILE
structure keeps information about the file status. Variable with FILE structure should be defined for each file used in program, either statically (in .data segment) or cleared when defined on stack or .bss. Pointer to a FILE structured variable is passed as the first parameter to all macros in this library.
FILE      STRUC
 .Ptr       DD  D ; Pointer to the current data content in memory-mapped|buffered data.
 .Top       DD  D ; Pointer to the end of the memory-mapped|buffered data.
 .BufPtr    DD  D ; Address of the start of memory-map|allocated buffer.
 .BufSize   DD  D ; Size of memory map|buffer.
 .Pos       DD  D ; Zero based offset of the current file position: lseek(.Handle,.Pos,SEEK_SET).
 .Size      DD  D ; File size in bytes.
 .Handle    DD  D ; File descriptor.
 .MapHandle DD  D ; Pointer to the start of mapped memory, identical with .BufPtr.
 .Status    DD  D ; File status flags, see FileStatusEnc.
 .NameOffs  DD  D ; Offset of the filename without path inside the .Name. Zero if no path in .Name.
 .ExtOffs   DD  D ; Offset of the file extension inside the .Name.
 .Name      D NAME_MAX * B ; Zero terminated file name.
 ENDSTRUC FILE
FileStatusEnc
Definition of flags which describe FILE.Status.
fileStFound      EQU 0x00000010 ; File was once succesfully opened.
fileStAppend     EQU 0x00100000 ; Created file should move its pointer to the end.
fileStStdIO      EQU 0x00200000 ; FILE.Handle is standard input|output.
fileStAllocated  EQU 0x00400000 ; FILE.BufPtr is pointer to the allocated memory.
fileStUnicode    EQU 0x00800000 ; FILE.Name is in WIDE characters (not used in Linux).
fileStMapCreated EQU 0x01000000 ; FILE.MapHandle is valid for writing.
fileStMapOpened  EQU 0x02000000 ; FILE.MapHandle is valid for reading.
fileStMapped     EQU 0x04000000 ; FILE.Ptr is pointer to the mapped memory.
fileStCreated    EQU 0x10000000 ; FILE.Handle is valid for writing.
fileStOpened     EQU 0x20000000 ; FILE.Handle is valid for reading.
FileNameParse FileNamePtr, Size= -1, Unicode=%^UNICODE
FileNameParse will analyze string with complete FileName, which may contain path, name, extension. It returns pointers to the name without path and to the file extension.
Name starts behind the last slash /, backslash \ or colon:. If no such characters exists, the whole input string is name.
File extension starts at the last point . in the name. If there is no point in name, the extension is empty.
Input
FileNamePtr is pointer to a string of characters.
Size=-1 is the size of input string in bytes. By default it is unlimited and the string must be zero terminated in this case.
Unicode=%^UNICODE is ignored.
Output
EAX is pointer to the start of name without path.
ECX is pointer to the start of extension.
EDX points behind the last FileName character.
Path starts at %FileNamePtr, size=EAX - OFFSET#FileNamePtr
Name starts at EAX, size=ECX - EAX
Extension starts at ECX, size=EDX - ECX
Error
-
Examples
%FileNamePtr │ │ │ │ "D:\path.ext\nam.part1.txt" "\plain" "./.profile" "name" │ │ │ │ │ │ │ │ │ EAX │ │ EAX │ EAX │ EAX │ ECX │ ECX ECX │ ECX EDX EDX EDX EDX
FileNameParse %MACRO FileNamePtr,Size=-1, Unicode=%^UNICODE
    PUSHD %Size,%FileNamePtr
    CALL FileNameParse@RT::
FileNameParse@RT:: PROC1
    PUSHAD
     MOV EBP,ESP
     MOV ESI,[%Param1] ; %FileNamePtr.
     MOV EDX,[%Param2] ; %Size.
     SUB ECX,ECX
     TEST EDX
     JS .UnlimitedSize:
     ADD EDX,ESI ; End of input string.
 .UnlimitedSize:
     MOV [%ReturnEAX],ECX
     MOV [%ReturnECX],ECX
     MOV [%ReturnEDX],ECX
 .NextChar:
     CMP ESI,EDX
     JNB .E0:
     LODSB
     Dispatch AL,58,92,47,46,0 ; colon, backslash, slash, dot, NULL.
     ; Ordinary character
     LEA EAX,[ESI-1]
     CMP [%ReturnEAX],ECX
     JNZ .NextChar:
     MOV [%ReturnEAX],EAX
     JMP .NextChar:
.46: ; dot .
     LEA EAX,[ESI-1]
     MOV [%ReturnECX],EAX
     CMP [%ReturnEAX],ECX
     JNE .NextChar:
     MOV [%ReturnEAX],EAX
     JMP .NextChar:
.47: ; colon, slash, backslash
.58:
.92: MOV [%ReturnEAX],ESI
     MOV [%ReturnECX],ECX
     JMP .NextChar:
.0:  DEC ESI ; Byte NULL.
 .E0:MOV [%ReturnEDX],ESI
     CMP [%ReturnECX],ECX
     JNE .E1:
     MOV [%ReturnECX],ESI
 .E1:CMP [%ReturnEAX],ECX
     JNE .E2:
     MOV EAX,[%ReturnECX]
     MOV [%ReturnEAX],EAX
 .E2:POPAD
    RET 8
   ENDPROC1 FileNameParse@RT::
 %ENDMACRO FileNameParse
FileAssign theFile, Name$1, Name$2,,,Size=-1, Unicode=%^UNICODE
Macro FileAssign associates file name with the FILE data object. Name of the file is copied to theFile.Name member.
The file must be assigned with file name before it is created or opened. FileAssign can concatenate the filename from several input strings, e.g. path, name, extension.
Input
theFile is pointer to a FILE structured memory variable.
Name$* is pointer to a zero terminated string with the file name or its part. It needs not be zero terminated when Size= is expicitly specified. Filename will be concatenated when more than one string is provided.
Name$1 may also be 0 or pointer to an empty string. The file is then assigned to standard input or output.
Device name may be assigned instead of a disk file.
Size= applies to all input strings. Size is unlimited by default and the strings must be zero terminated in this case.
Unicode=%^UNICODE is ignored in Linux
Output
Members of theFile .Name, .NameOffs, .ExtOffs, .Status:fileStUnicode of theFile are set.
Error
CF=1 if the concatenated name length exceeds SIZE# FILE.Name, i.e. NAME_MAX=260 characters.
Depends on
FileNameParse
Examples
File1 DS FILE Path$ DB "C:\Text\",0 Name$ DB "Some",0 Ext$ DB ".txt",0 [.text] FileAssign File1,Path$,Name$,Ext$ FileAssign File1,0 ; Standard output, by default redirected to console. FileAssign File1,="/dev/prn" ; Output to a line printer.
FileAssign %MACRO theFile,Name$1,Name$2,,, Size=-1, Unicode=%^UNICODE
   %IF %#<2                                                                 ; >
     %ERROR ID=5941, 'File name missing in macro "FileAssign".'
     %EXITMACRO FileAssign
   %ENDIF
   PUSHD 0 ; Mark the end of arguments.
   ArgNr %FOR %#..2,STEP=-1
     PUSHD %*{%ArgNr}
   %ENDFOR ArgNr
   PUSHD %Size, %theFile, ESP
   ADDD [ESP],4*(%#+2)
   CALL FileAssign@RT::
FileAssign@RT:: PROC1
   PUSHAD
    MOV EBX,[ESP+40] ; %theFile
    LEA EBP,[ESP+48] ; %Name$1
    LEA EDI,[EBX+FILE.Name]
    RstSt   [EBX+FILE.Status],fileStUnicode
    LEA EDX,[EDI+NAME_MAX]
.10:XCHG EBP,ESI
    LODSD ; Offset of source string.
    MOV EBP,EAX
    XCHG ESI,EBP
    TEST EAX
    JZ .50:
    MOV ECX,[ESP+44] ; %Size.
.20:LODSB
    CMP AL,0
    JE .10:
    CMP EDI,EDX
    JNB .40:
    STOSB
    LOOP .20:
    JMP .10:
.40:SUB EAX,EAX
    STC ; Overflow.
.50:MOV ECX,EDI
    STOSB
    LEA EDX,[EBX+FILE.Name]
    PUSHFD
      SUB ECX,EDX
      FileNameParse EDX,Size=ECX
      LEA EDX,[EBX+FILE.Name]
      SUB EAX,EDX
      SUB ECX,EDX
      MOV [EBX+FILE.NameOffs],EAX
      MOV [EBX+FILE.ExtOffs],ECX
    POPFD
   POPAD
   RET
ENDPROC1 FileAssign@RT::
   POP ESP
%ENDMACRO FileAssign
FileExists? theFile
will test if the given file with assigned name exists on disk. File may be opened or closed. Wildcard characters * ? are allowed in the file name.
This macro can test the presence of a directory, too.
Input
theFile is pointer to FILE object which was assigned with the name of file or directory.
Output
CF=1 if the file | directory does not exist.
CF=0 ZF=1 if the file exists.
CF=0 ZF=0 if the directory exists.
Example
FileExists? =".\Config.ini" JC ErrorIniNotFound
FileExists? %MACRO theFile
     PUSHD %theFile
     CALL FileExists?@RT::
FileExists?@RT:: PROC1
    PUSHAD
     MOV EBP,[ESP+36] ; theFile.
     LEA EBX,[EBP+FILE.Name]
     MOV ECX,O_RDONLY+O_PATH+O_DIRECTORY
     XOR EDX,EDX
     LinAPI open,EBX,ECX,EDX, Fastmode=Yes ; Try to open a directory.
     MOV EDI,EAX ; Returned fd or error.
     SAL EAX     ; Copy SF to CF.
     JNC .80:    ; Return with CF=0,ZF=0 if directory exists.
     MOV ECX,O_RDONLY+O_PATH
     LinAPI open,EBX,ECX,EDX, Fastmode=Yes ; Try to open a file.
     MOV EDI,EAX ; Returned fd or error.
     SAL EAX     ; Copy SF to CF.
     JC .80:
     SetSt [EBP+FILE.Status],fileStFound
     XOR EDX,EDX ; Set CF=0, ZF=1 if file exists.
.80: PUSHFD
      JC .90:    ; Do not close if EDI is invalid handle.
      LinAPI close,EDI,Fastmode=Yes
.90: POPFD
    POPAD
    RET 1*4
  ENDPROC1 FileExists?@RT::
 %ENDMACRO FileExists?
FileMkDir theFile
will parse the file name and create all directories in its path if they didn't exist.
The last portion of assigned name is treated as directory only if
it is terminated with slash.
Input
theFile is pointer to FILE object with assigned name.
Output
CF=0
EAX=0 if the directory was created or it existed before.
Error

CF=1
EAX=last error if CreateDirectory failed.
Example
FileAssign SomeFile, ="/var/lib/mydir/file.txt" FileMkDir SomeFile ; will create folders /var/lib/ and /var/lib/mydir/. FileAssign SomeFile, ="/var/lib/mydir/file.txt/" FileMkDir SomeFile ; will create folders /var/lib/, /var/lib/mydir/, /var/lib/mydir/file.txt/.
FileMkDir %MACRO theFile
     PUSHD %theFile
     CALL FileMkDir@RT::
FileMkDir@RT:: PROC1
   PUSHAD
     MOV EBP,[ESP+36] ; theFile.
     LEA EBX,[EBP+FILE.Name]
     SUB ECX,ECX
     MOV EDI,EBX
     DEC ECX
     SUB EAX,EAX
     REPNE SCASB
     MOV EBP,EDI      ; ASCIIZ FileName is now EBX..EBP.
     MOV EDI,EBX
.20: MOV ECX,EBP
     MOV EAX,'/'
     CMP [EDI],AL
     JNE .30:
     INC EDI
.30: SUB ECX,EDI
     REPNE SCASB      ; Search for the next slash.
     MOV AL,0
     JNE .80:         ; Done when no more slashes left in FileName.
     MOV [EDI-1],AL   ; Temporarily replace slash with NULL.
     MOV ECX,00777q
     LinAPI mkdir,EBX,ECX,Fastmode=Yes
     MOVB [EDI-1],'/' ; Restore original slash.
     TEST EAX
     JZ .20:
     CMP EAX,-17      ; EEXIST is the only tolerated error.
     JE .20:
.80: MOV [ESP+28],EAX ; Returned EAX.
     SAL EAX,1        ; Copy SF to CF.
    POPAD
    RET 1*4
  ENDPROC1 FileMkDir@RT::
%ENDMACRO FileMkDir
FileGetSize theFile
is a service macro used internally in FileOpen, FileCreate, FileMap* to get the size of opened/closed file.
Then it may be obtained faster as FILE.Size.
Input
theFile is pointer to an assigned FILE object.
Output
CF=0
EAX= file size in bytes.
Error
CF=1
EAX= error code.
FileGetSize %MACRO theFile
      PUSHD %theFile
      CALL FileGetSize@RT::
FileGetSize@RT:: PROC1
   PUSHAD
    MOV EBP,ESP
    MOV EDI,[%Param1]          ; %theFile.
    SUB ESP,SIZE# STAT64
    MOV ECX,ESP                ; STAT32 or STAT64
    LEA EBX,[EDI+FILE.Name]
    LinAPI stat,EBX,ECX,Fastmode=Yes ; Try old 32bit fstat first.
    MOV EDX,[ECX+STAT32.st_size]
    TEST EAX
    JZ .90:
    CMP EAX,-EOVERFLOW
    JNE .80:
    ; 32bit application is run on 64bit Linux, it may fail due to kernel mess when inode number exceeds 4G.
    MOV ECX,EBX                ; ^FILE.Name.
    MOV EDX,ESP                ; ^STAT64.
    XOR ESI,ESI                ; flags.
    MOV EBX,AT_FDCWD           ; Obey the current directory for relative path.
    LinAPI fstatat64,EBX,ECX,EDX,ESI,Fastmode=Yes
    MOV EDX,[EDX+STAT64.st_size]
    TEST EAX
    JZ .90:
.80:MOV EDX,EAX
    STC
.90:MOV [%ReturnEAX],EDX
    MOV ESP,EBP
   POPAD
   RET 1*4
 ENDPROC1 FileGetSize@RT::
%ENDMACRO FileGetSize
FileOpen theFile
opens the assigned file for reading.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX= file size.
Error
CF=1
EAX= is errorCode.
FileOpen %MACRO theFile
         PUSHD %theFile
         CALL FileOpen@RT::
FileOpen@RT:: PROC1
    PUSHAD
     MOV EDI,[ESP+36]          ; theFile.
     LEA EBX,[EDI+FILE.Name]
     XOR EDX,EDX
     MOV [EDI+FILE.Size],EDX
     MOV [EDI+FILE.Pos],EDX
     MOV [EDI+FILE.Ptr],EDX
     MOV [EDI+FILE.Top],EDX
     LinAPI open,EBX,O_RDONLY,EDX,Fastmode=Yes
     TEST EAX
     STC
     JS .90:
     SetSt [EDI+FILE.Status],fileStOpened+fileStFound
     MOV [EDI+FILE.Handle],EAX
     FileGetSize EDI
     JC .90:
     MOV [EDI+FILE.Size],EAX
     MOV [EDI+FILE.Top],EAX
.90: MOV [ESP+28],EAX          ; Returned EAX.
    POPAD
    RET 1*4
  ENDPROC1 FileOpen@RT::
 %ENDMACRO FileOpen
FileFlush theFile
is a service macro used internally in FileClose, FileStreamWrite* to write the contents of file buffer on disk. There is no reason to invoke this macro explicitly by the programmer.
Output
CF=0
EAX= number of flushed bytes.
Error
CF=1
EAX= errorCode or EAX=0 (file not created for write).
FileFlush %MACRO theFile
      PUSHD %theFile
      CALL FileFlush@RT::
FileFlush@RT:: PROC1
    PUSHAD
     MOV EDI,[ESP+36]          ; theFile.
     MOV EAX,-EBADFD           ; Error: file is not open for write.
     JNSt [EDI+FILE.Status],fileStAllocated,.Err:
     JNSt [EDI+FILE.Status],fileStCreated,  .Err:
     MOV ECX,[EDI+FILE.BufPtr] ; Start of buffer.
     MOV EDX,[EDI+FILE.Ptr]    ; Next free position in buffer.
     MOV [EDI+FILE.Ptr],ECX
     SUB EDX,ECX
     MOV EAX,EDX
     JZ .80:
     LinAPI write,[EDI+FILE.Handle],ECX,EDX,Fastmode=Yes
     CMP EAX,-ERR_MAX
     CMC
     JNC .80:
.Err:STC
.80: MOV [ESP+28],EAX         ; Returned EAX.
.90:POPAD
    RET 1*4
 ENDPROC1 FileFlush@RT::
%ENDMACRO FileFlush
FileClose theFile1, theFile2,,,
Macro FileClose will flush and deallocate the buffer, close file mapping, close the file, clear pointers in the FILE structure.
FileClose does not clear the name assignment, so the closed file may be reopen with the same name without invoking FileAssign again.
Input
theFile is pointer to a FILE object. More than one file may be specified simultaneously.
Output
-
Error
-
Depends on
FileFlush
FileClose %MACRO theFile1
  ArgNr %FOR 1..%#
       PUSHD %*{%ArgNr}
       CALL FileClose@RT::
     %ENDFOR ArgNr
FileClose@RT:: PROC1
    PUSHAD
     MOV EDI,[ESP+36] ; theFile
     JSt [EDI+FILE.Status],fileStMapped,.10:
     FileFlush EDI
     JMPS .20:
.10: LinAPI munmap,[EDI+FILE.MapHandle],[EDI+FILE.Size],Fastmode=Yes
.20: JNSt [EDI+FILE.Status],fileStAllocated,.30:
     LinAPI munmap,[EDI+FILE.BufPtr],[EDI+FILE.BufSize],Fastmode=Yes
.30: JNSt [EDI+FILE.Status],fileStOpened|fileStCreated, .40:
     LinAPI close,[EDI+FILE.Handle],Fastmode=Yes
.40: LEA ECX,[EDI+FILE.NameOffs]
     SUB ECX,EDI
     SHR ECX,2
     XOR EAX,EAX
     REP STOSD        ; Clear the FILE object except for Name and Offs.
    POPAD
    RET 1*4
  ENDPROC1 FileClose@RT::
%ENDMACRO FileClose
FileMove SourceFile, DestinationFile
FileMove renames directory on the same volume or moves the source file to the destination. Files will be closed first, if necessarry. The destination file will be erased if it existed before.
Directories in the destination file name will be maked, if necessarry. Both files must have been assigned.
Input
SourceFile and DestinationFile are pointers to assigned FILE objects.
Output
CF=0
EAX=0
Error
CF=1
EAX= error.
Depends on
FileClose, FileMkDir
FileMove %MACRO SourceFile, DestinationFile
       PUSHD %DestinationFile, %SourceFile
       CALL FileMove@RT::
FileMove@RT:: PROC1
     PUSHAD
      MOV ESI,[ESP+36] ; SourceFile.
      MOV EDI,[ESP+40] ; DestinationFile.
      FileClose ESI,EDI
      FileMkDir EDI
      JC .EndWithEAX:
      LEA EBX,[ESI+FILE.Name]
      LEA ECX,[EDI+FILE.Name]
      LinAPI rename,EBX,ECX,Fastmode=Yes
.EndWithEAX:
      MOV [ESP+28],EAX ; ReturnEAX.
      SAL EAX,1        ; Copy SF to CF.
     POPAD
     RET 2*4
   ENDPROC1 FileMove@RT::
 %ENDMACRO FileMove
FileDelete theFile1, theFile2,,,
will close and erase the disk file(s).
FileDelete does not clear the name assignment, so the deleted file may be reopen with the same name without invoking FileAssign again.
Input
theFile* is pointer to a FILEobject. More than one file may be specified simultaneously.
Output
CF=0,
EAX=0 if the last file was succesfully deleted.
Error
CF=1
EAX= error.
Depends on
FileClose
FileDelete %MACRO theFile
ArgNr %FOR 1..%#
       PUSHD %*{%ArgNr}
       CALL FileDelete@RT::
      %ENDFOR ArgNr
FileDelete@RT:: PROC1
     PUSHAD
      MOV EDI,[ESP+36] ; theFile.
      FileClose EDI
      LEA ESI,[EDI+FILE.Name]
      LinAPI unlink,ESI,Fastmode=Yes
      MOV [ESP+28],EAX ; ReturnEAX.
      SAL EAX,1        ; Copy SF to CF.
     POPAD
     RET 4
   ENDPROC1 FileDelete@RT::
 %ENDMACRO FileDelete
FileEach theFile, CallbackProc
Macro FileEach expects the file object assigned with file name which can contain wildcard characters * and ?. FileEach will resolve the mask and performs callback procedure with each such filename. If no file matches the mask, CallbackProc is never called.
Input
theFile is a pointer to FILE object which must have assigned the requested file path and file name mask.
CallbackProc is the address of callback procedure.
Output
EAX=content of EAX at the last CallbackProc exit, or 0 if the CallbackProc was never called.
CallbackProc
is called with register calling convention. CallbackProc should return CF=0 to let FileEach continue with the next file, otherwise FileEach stops searching.
CallbackProc input registers:
EBX=%theFile where the mask in FILE.Name is replaced with the resolved file name found in directory. The file is not open.
ESI=pointer to the file name without path inside EBX+FILE.Name.
EBP=EBP at FileEach macro entry. This allows to address local stack variables of the procedure which invoked FileEach.
Other registers are undefined at CallbackProc entry.
CallbackProc output registers:
EAX is passed through. FileEach returns EAX value from the last called CallbackProc, or 0 if it was never called.
CF=0 to continue with the next file
CF=1 to break further searching.
CallbackProc may destroy any GP register.
Depends on
FileNameParse
Example
MyFile DS FILE FileAssign MyFile,="/var/lib/t??_*.txt" FileEach MyFile, ListFile TerminateProgram ListFile PROC StdOutput ESI,Eol=Yes RET ENDP ListFile
FileEach %MACRO theFile, CallbackProc
     PUSHD %CallbackProc, %theFile
     CALL FileEach@RT::
FileEach@RT:: PROC1
%FileEachBufSize %SETA 40 ; 512  ; Local buffer for DIRENT records.
      PUSHAD
       MOV EBP,ESP
       MOV ECX,(SIZE# FILE.Name + 3) & ~3
       SUB ESP,ECX
%FileEachMask$ %SET EBP-(SIZE#FILE.Name+3&~3)
       MOV EBX,[%Param1]   ; theFile.
       SUB EAX,EAX
       MOV [%ReturnEAX],EAX
       ADD EAX,[EBX+FILE.NameOffs] ; ZF indicates the absence of path.
       LEA ESI,[EAX+EBX+FILE.Name]
       MOV EDI,ESP
       REP MOVSB           ; Copy the ASCIIZ mask without path to LocalVar %FileEachMask$.
       JNZ .10:            ; Test if FILE.NameOffs=0.
       ; The mask was specified without path, e.g. doc*.txt.
       ; Default path . will be injected to FILE.Name, e.g. ./doc*.txt.
       MOV ECX,SIZE#FILE.Name-2
       LEA ESI,[ECX+EBX+FILE.Name-1]
       LEA EDI,[ESI+2]
       STD
        REP MOVSB
       CLD
       DEC EDI
       MOVW [EDI],'./'
       MOVB [EDI+SIZE#FILE.Name-1],0
       FileNameParse EDI
       SUB EAX,EDI
       SUB ECX,EDI
       MOV [EBX+FILE.NameOffs],EAX
       MOV [EBX+FILE.ExtOffs],ECX
.10:   LEA EDI,[EBX+FILE.Name]      ; EAX=FILE.NameOffs.
       MOVB [EDI+EAX-1],0           ; Temporary replace / with NULL.
       LinAPI open,EDI,O_RDONLY+O_DIRECTORY+O_NOATIME,0,Fastmode=Yes
       MOV EBX,[%Param1]            ; Restore theFile.
       MOV EDX,[EBX+FILE.NameOffs]
       MOVB [EDI+EDX-1],'/'         ; Replace temporary NULL back with slash in the mask name.
       MOV ECX,%FileEachBufSize
       SUB ESP,ECX                  ; LocalVar for DIRENT records.
%FileEachBuf %SET %FileEachMask$-%FileEachBufSize
       PUSH EAX                     ; LocalVar for fd (directory file descriptor).
       CMP EAX,-ERR_MAX
       JNC .Abort:
       MOV EBX,EAX                  ; fd.
.20:   LEA ESI,[%FileEachBuf]
       LinAPI getdents,EBX,ESI,%FileEachBufSize,Fastmode=Yes
       TEST EAX
       JZ .Abort:                   ; No more dir entries.
       CMP EAX,-ERR_MAX
       JNC .Abort:
       LEA EDX,[ESI+EAX]            ; End of DIRENT records in %FileEachBuf.
.30:   CMP ESI,EDX
       JNB .20:
       CALL .DirEnt:                ; Process the DIRENT record ESI.
       JC .Abort:
       MOVZX EAX,[ESI+DIRENT.d_reclen]
       ADD ESI,EAX
       JMP .30:
.DirEnt:PROC1 ; If the resolved name [ESI+DIRENT.d_name] complies with %FileEachMask$,
              ; update FILE.Name [%Param1] with the DIRENT.d_name and then callback [%Param2].
         PUSHAD
          LEA EDI,[ESI+DIRENT.d_name]
          MOVZX ECX,[ESI+DIRENT.d_reclen]
          MOV ESI,EDI
          SUB ECX,DIRENT.d_name
          XOR EAX,EAX
          REPNE SCASB
          DEC EDI
          MOV ECX,EDI   ; ECX=Pointer to the end of DIRENT.d_name ( NUL).
          MOV EDI,ESI   ; EDI..ECX is a filename in DIRENT.
          LEA ESI,[%FileEachMask$]
          LEA EDX,[ESI+SIZE#FILE.Name]
          XOR EBX,EBX
.40:      CMP ESI,EDX   ; Test on end-of-mask.
          JNB .80:
          LODSB         ; Byte from the mask.
          MOV AH,[EDI]  ; Byte from dir entry.
          INC EDI
          Dispatch AL,0x00, 0x3F, 0x2A ; Wildcards NUL, '?', '*'
          CMP AL,AH     ; Ordinary character/byte.
          JE .40:
          CLC
          JMP .90:      ; Mask does not comply.
.0x00:    CMP AH,0
          JE .80:
          JMP .90:      ; Mask does not comply.
.0x3F:    CMP AH,0      ; Question mark in mask complies with one not-nul UTF8 character.
          JE .90:
          NOT EAX       ; Invert bits in UTF8 AH.
          BSR BX,AX     ; Scan AH.
          SUB EBX,15
          JZ .40:
          INC EBX
          SUB EDI,EBX   ; Advance EDI by the size of UTF8 character - 1.
          JMP .40:
.0x2A:    ; Asterix '*' in mask complies with zero or more UTF8 characters.
          LODSB         ; The mask character/byte following '*'.
          CMP AL,0
          JE .80:
          CMP AL,'?'
          JE .0x2A:
          CMP AL,'*'
          JE .0x2A:
          DEC EDI
          PUSH ECX      ; Temporary save the end of name in dir entry.
            SUB ECX,EDI
            REPNE SCASB ; Search for the character which follows '*'.
          POP ECX
          CLC
          JNE .90:
          JMP .40:
.80:      ; Mask complies.
          MOV ESI,[ESP+04]  ; Restore ^DIRENT.
          MOV EBX,[%Param1] ; Restore theFile.
          MOV EAX,[EBX+FILE.NameOffs]
          LEA ECX,[EBX+FILE.Name+SIZE#FILE.Name]
          LEA EDI,[EAX+EBX+FILE.Name]
          ADD ESI,DIRENT.d_name
          SUB ECX,EDI
          PUSH EDI
            REP MOVSB
          POP ESI
          MOV EAX,[%Param2]     ; CallbackProc.
          PUSH EBP
           MOV EBP,[%ReturnEBP] ; Parent's stack frame.
           CALL EAX             ; Perform the callback.
          POP EBP
          MOV [%ReturnEAX],EAX  ; Value returned from callback.
.90:     POPAD
         RET
        ENDPROC1 .DirEnt:
.Abort:POP EBX
       LinAPI close,EBX, Fastmode=On
      MOV ESP,EBP
     POPAD
     RET 2*4
 ENDPROC1 FileEach@RT:
%ENDMACRO FileEach
FileLoad theFile
will allocate memory buffer from OS, open the file, read entire file content to a block of memory allocated by FileLoad and then close the file.
Although the file handle is closed immediately, you should always use FileClose to free allocated buffer when the file content is no longer needed.
Input
theFile is pointer to an assigned existing FILE object.
Output
CF=0
EAX= file size,
ESI= pointer to the file contents in allocated memory.
Error
CF=1
EAX= errorCode.
ESI= is undefined.
Depends on
FileOpen
FileLoad %MACRO theFile
    PUSHD %theFile
    CALL FileLoad@RT::
FileLoad@RT:: PROC1
   PUSHAD
    MOV EDI,[ESP+9*4]      ; theFile.
    FileOpen EDI           ; Returns CF=0,EAX=file size.
    JC .80:
    MOV [EDI+FILE.BufSize],EAX
    TEST EAX
    JZ .80:                 ; Zero-sized files are not supported.
    PUSHD 0,-1,MAP_PRIVATE+MAP_ANONYMOUS,PROT_READ+PROT_WRITE,EAX,0
     MOV EBX,ESP
     LinAPI mmap,EBX,Fastmode=Yes
    ADD ESP,6*4
    CMP EAX,-ERR_MAX
    CMC
    JC .80:
    MOV [EDI+FILE.BufPtr],EAX
    MOV [EDI+FILE.Ptr],EAX
    ADD [EDI+FILE.Top],EAX
    MOV [ESP+1*4],EAX      ; Returned ESI.
    SetSt [EDI+FILE.Status],fileStAllocated
    MOV EDX,[EDI+FILE.Size]
    LinAPI read,[EDI+FILE.Handle],EAX,EDX,Fastmode=Yes
    CMP EAX,-ERR_MAX
    CMC
.80:MOV [ESP+7*4],EAX      ; Returned EAX.
    PUSHFD      ; Save CF.
     JNSt [EDI+FILE.Status],fileStOpened,.90:
     LinAPI close,[EDI+FILE.Handle],Fastmode=Yes
.90: RstSt [EDI+FILE.Status],fileStOpened
     MOVD [EDI+FILE.Handle],-1
    POPFD       ; Restore CF.
   POPAD
   RET 1*4
 ENDPROC1 FileLoad@RT::
%ENDMACRO FileLoad
 
FileStore theFile, DataPtr, DataSize
Macro FileStore will open the file, write data and close the file.
Input
theFile is pointer to an assigned unopened FILE object,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes, i.e. future file size.
Output
CF=0
EAX= is the data size of written data.
Error
CF=1
EAX= is error code.
Example
FileStore File1, MyDataPtr, MyDataEnd-MyDataPtr
FileStore %MACRO theFile,DataPtr,DataSize
      PUSHD %DataSize,%DataPtr,%theFile
      CALL FileStore@RT::
FileStore@RT:: PROC1
   PUSHAD
    MOV EBP,[ESP+36] ; theFile.
    MOV EAX,[ESP+40] ; DataPtr.
    MOV ECX,[ESP+44] ; DataSize.
    LEA EDI,[EBP+FILE.Name]
    MOV [EBP+FILE.Ptr],EAX
    MOV [EBP+FILE.Top],EAX
    MOV [EBP+FILE.Size],ECX
    ADD [EBP+FILE.Top],ECX
    MOV [ESP+28],ECX  ; Returned EAX.
    SUB EAX,EAX
    MOV [EBP+FILE.Pos],EAX
    LEA EBX,[EBP+FILE.Name]
    LinAPI open,EBX,O_WRONLY+O_CREAT+O_TRUNC,777q,Fastmode=Yes
    TEST EAX
    JNS .OK:
.ErrorEAX: STC
    JMP .EndWithEAX:
.OK:MOV EBX,EAX       ; File descriptor.
    LinAPI write,EBX,[EBP+FILE.Ptr],[EBP+FILE.Size],Fastmode=Yes
    TEST EAX
    JS .ErrorEAX:
    LinAPI close,EBX,Fastmode=Yes
    MOV EAX,[EBP+FILE.Size]
    ADD [EBP+FILE.Pos],EAX
.EndWithEAX:
    MOV [ESP+28],EAX ; Returned EAX.
   POPAD
   RET 3*4
 ENDPROC1 FileStore@RT::
%ENDMACRO FileStore
FileReset theFile, Position
Macro FileReset will reset internal file pointers to a new Position in the file.
Input
theFile is pointer to a FILE object, which must have been opened with FileOpen, FileMapOpen or FileStreamOpen.
Position specifies the number of bytes from the beginning of theFile. Zero is used if omitted.
Output
CF=0
EAX=Position
Error
CF=1
EAX= error code.
FileReset %MACRO theFile, Position
     %IF "%Position" === ""
       PUSHD 0
     %ELSE
       PUSHD %Position
     %ENDIF    
     PUSHD %theFile
     CALL FileReset@RT::
FileReset@RT:: PROC1
     PUSHAD
      MOV EBP,ESP
      MOV EDI,[%Param1]  ; theFile.
      MOV ESI,[%Param2]  ; Position.
      MOV EAX,EBADF      ; Error code file is not opened.
      JNSt [EBX+FILE.Status],fileStOpened,.ErrorEAX:
      LinAPI lseek,[EDI+FILE.Handle],ESI,SEEK_SET,Fastmode=Yes
      TEST EAX
      JNS .50:
.ErrorEAX: STC
      JMP .EndWithEAX:
.50:  MOV [EDI+FILE.Pos],EAX
      MOV ESI,[EDI+FILE.BufPtr]
      ADD ESI,EAX
      MOV [EDI+FILE.Ptr],ESI
      JSt [EDI+FILE.Status],fileStMapOpened,.EndWithEAX:
      MOV [EDI+FILE.Top],ESI
.EndWithEAX:
      MOV [%ReturnEAX],EAX
.90: POPAD
     RET 2*4
    ENDPROC1 FileReset@RT::
 %ENDMACRO FileReset
FileRead theFile, DataPtr, DataSize
reads from an opened file to the memory provided by caller.
Input
theFile is pointer to a FILE object opened for reading.
DataPtr is pointer where the data will be read,
DataSize is requested number of bytes (<2GB).
Output
CF=0
ZF=0
EAX= the actually read size (may be less than DataSize if the file is not large enough).
End of file
CF=0
ZF=1
EAX=0 if all data have been read from the file (EOF).
Error
CF=1
EAX= errorCode.
Example
FileRead InpFile,aLine,80 JC .ErrorReadingFile JZ .EOF
FileRead %MACRO theFile,DataPtr,DataSize
       PUSHD %DataSize,%DataPtr,%theFile
       CALL FileRead@RT::
FileRead@RT:: PROC1
    PUSHAD
     MOV EBP,ESP
     MOV EDI,[%Param1]     ; theFile.
     MOV EAX, -EBADFD      ; Error code: file is not open.
     TEST [EDI+FILE.Status],fileStOpened
     STC
     JZ .EndWithEAX:
     LinAPI read,[EDI+FILE.Handle],[%Param2],[%Param3],Fastmode=Yes
     TEST EAX
     STC
     JS .EndWithEAX:
     ADD [EDI+FILE.Pos],EAX
     TEST EAX              ; Check EOF.
.EndWithEAX:
     MOV [%ReturnEAX],EAX
    POPAD
    RET 3*4
  ENDPROC1 FileRead@RT::
 %ENDMACRO FileRead
FileCreate theFile
creates a new file or rewrites an existing file for writing.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX=0 (size of just rewritten file).
Error
CF=1
EAX=errorCode.
FileCreate %MACRO theFile
         PUSHD %theFile
         CALL FileCreate@RT::
FileCreate@RT:: PROC1
   PUSHAD
    MOV EDI,[ESP+36]             ; theFile.
    LEA EBX,[EDI+FILE.Name]
    SUB ESI,ESI
    MOV [EDI+FILE.Size],ESI
    MOV [EDI+FILE.Pos],ESI
    MOV [EDI+FILE.Ptr],ESI
    MOV [EDI+FILE.Top],ESI
    MOV ECX,O_CREAT|O_WRONLY|O_TRUNC
    JNSt [EDI+FILE.Status],fileStAppend,.10:
    MOV ECX,O_CREAT|O_WRONLY|O_APPEND
.10:LinAPI open,EBX,ECX,777q,Fastmode=Yes
    CMP EAX,-ERR_MAX
    CMC
    JC .Error:
    SetSt [EDI+FILE.Status],fileStCreated
    MOV [EDI+FILE.Handle],EAX
    FileGetSize EDI
    JC .Error:
    MOV [ESP+28],EAX          ; Returned EAX.
    MOV [EDI+FILE.Size],EAX
    MOV [EDI+FILE.Pos],EAX
.Error:
    MOV [ESP+28],EAX
   POPAD
   RET 1*4
  ENDPROC1 FileCreate@RT::
%ENDMACRO FileCreate
FileAppend theFile
Macro FileAppend creates a new file or opens an existing file for writing and sets file pointer to its end.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX= file size.
Error
CF=1
EAX=errorCode as returned from GetLastError.
Depends on
FileCreate
FileAppend %MACRO theFile
       PUSHD %theFile
       CALL FileAppend@RT::
 FileAppend@RT:: PROC1
     PUSH EBX
       MOV EBX,[ESP+8] ; theFile
       SetSt [EBX+FILE.Status],fileStAppend
       FileCreate EBX
     POP EBX
     RET 1*4
   ENDPROC1 FileAppend@RT::
 %ENDMACRO FileAppend
FileWriteRT
is a runtime definition macro used internally by FileWrite, FileWriteLn, FileWrite$.
FileWriteRT %MACRO ; Common runtime procedure declaration for macros FileWrite*
FileWrite@RT:: PROC1
    PUSHAD
     MOV EDI,[ESP+40] ; theFile
     LEA ESI,[ESP+44] ; 1st string ptr.
     MOV EAX,-EBADFD  ; File is not opened.
     JNSt [EDI+FILE.Status],fileStCreated, .ErrorEAX:
     SUB EAX,EAX
     MOV [ESP+28],EAX ; %Return EAX.
.10: LODSD            ; DataPtr.
     MOV ECX,EAX
     JECXZ .90        ; End of data.
     LODSD            ; DataSize.
     LinAPI write,[EDI+FILE.Handle],ECX,EAX,Fastmode=Yes
     TEST EAX
     JS .ErrorEAX:
     ADD [ESP+28],EAX ; %ReturnEAX
     ADD [EDI+FILE.Pos],EAX
     ADD [EDI+FILE.Size],EAX
     JMP .10:
.ErrorEAX: STC
     MOV [%ReturnEAX],EAX
.90:POPAD
    RET
FileWrite$size@RT::
    PUSH EAX,ECX,EDI
     SUB ECX,ECX
     SUB EAX,EAX
     DEC ECX
     MOV EDI,[ESP+16] ; DataPtr.
     REPNE SCASB
     SUB EAX,ECX
     SUB EAX,2
     MOV [ESP+20],EAX ; DataSize.
    POP EDI,ECX,EAX
    RET
 ENDPROC1 FileWrite@RT::
%ENDMACRO FileWriteRT
FileWrite theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data to the file previously opened for writing with FileCreate or FileAppend.
Multiple data may be written in one macro invocation.
Input
theFile is pointer to an open FILE object,
DataPtr* points to the data to be written,
DataSize* is the size of data in bytes.
Output
CF=0
EAX=total written size in bytes.
Error
CF=1
EAX=errorCode.
Depends on
FileWriteRT
FileWrite %MACRO theFile,DataPtr,DataSize,,,,
    %IF %# & 1 = 0
      %ERROR ID=5944, 'Macro "%0" expects odd number of arguments.'
      %EXITMACRO FileWrite
    %ENDIF
    PUSHD 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-2
      PUSHD %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],(%#+1)*4
     CALL FileWrite@RT::
    POP ESP
    FileWriteRT ; Invoke the common runtime macro.
 %ENDMACRO FileWrite
FileWriteLn theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
Macro FileWriteLn writes data to the file previously opened for writing with FileCreate or FileAppend.
Multiple data may be written in one macro invocation. End of line LF character is written in the end.
Input
theFile is pointer to an open FILE object,
DataPtr* points to the data to be written,
DataSize* is size of data in bytes.
Output
CF=0
EAX= is the total written size including LF.
Error
CF=1
EAX= errorCode.
Depends on
FileWriteRT
FileWriteLn %MACRO theFile,DataPtr,DataSize,,,
    %IF %# & 1 = 0
      %ERROR ID=5945, 'Macro "%0" expects odd number of arguments.'
      %EXITMACRO FileWriteLn
    %ENDIF
    PUSHD 0x0A       ; CR+LF.
    PUSHD 0          ; Mark the end of arguments.
    PUSHD 1          ; Size of LF.
    PUSHD ESP
    ADDD [ESP],2*4   ; Pointer to LF.
    ArgNr %FOR %#..2,STEP=-2
      PUSHD %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],(%#+4)*4
     CALL FileWrite@RT::
    POP ESP
    FileWriteRT  ; Invoke the common runtime macro.
 %ENDMACRO FileWriteLn
FileWrite$ theFile, DataPtr$1, DataPtr$2,,,
This macro writes zero terminated ANSI string(s) to the file previously opened for writing with FileCreate or FileAppend.
More than one string may be written in one macro invocation. The terminating zeros are not written to the file.
Input
theFile is pointer to an open FILE object,
DataPtr$* are pointers to zero terminated strings to be written.
Output
CF=0
EAX= total written size in bytes.
Error
CF=1
EAX= errorCode.
Depends on
FileWriteRT
FileWrite$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
    PUSHD 0       ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-1
      PUSHD EAX,%*{%ArgNr}
      CALL FileWrite$size@RT::
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],2 * %# * 4
     CALL FileWrite@RT::
    POP ESP
    FileWriteRT   ; Invoke the common runtime macro.
  %ENDMACRO FileWrite$
FileEncloseRT
is a runtime defining macro used internally by FileEnclose, FileEncloseLn, FileEnclose$.
Input stack
ReturnEIP,ReturnESP,theFile,DataPtr1,DataSize1,DataPtr2,DataSize2,,,0
Depends on
FileCreate, FileClose.
FileEncloseRT %MACRO ; Common RT procedure declaration for macros FileEnclose*
FileEnclose@RT:: PROC1
     PUSHAD
      MOV EDI,[ESP+40] ; theFile
      SetSt [EDI+FILE.Status],fileStAppend
      FileCreate EDI
      JC .Error:
      LEA ESI,[ESP+44] ; Pointer to 1st string pointer.
      SUB EAX,EAX
      MOV [ESP+28],EAX ; %ReturnEAX.
 .10: LODSD            ; DataPtr.
      MOV ECX,EAX
      JECXZ .90        ; End of data pointers.
      LODSD            ; DataSize.
      LinAPI write,[EDI+FILE.Handle],ECX,EAX,Fastmode=Yes
      TEST EAX
      JS .Error:
      ADD [ESP+28],EAX ; %ReturnEAX.
      ADD [EDI+FILE.Pos],EAX
      ADD [EDI+FILE.Size],EAX
      JMP .10:
.Error:STC
      MOV [ESP+28],EAX ; %ReturnEAX.
.90:  PUSHFD           ; Save CF.
        FileClose EDI
      POPFD            ; Restore CF.
     POPAD
     RET
 FileEnclose$size@RT: ; Subprocedure for zero-terminated strings.
     PUSH EAX,ECX,EDI
      SUB ECX,ECX
      SUB EAX,EAX
      DEC ECX
      MOV EDI,[ESP+16] ; DataPtr.
      REPNE SCASB
      SUB EAX,ECX
      SUB EAX,2
      MOV [ESP+20],EAX ; DataSize.
     POP EDI,ECX,EAX
     RET
  ENDPROC1 FileEnclose@RT::
%ENDMACRO FileEncloseRT
FileEnclose theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data at the end of existing file or creates a new one and then closes the file.
Multiple data can be appended with one invocation.
The file should be assigned but not open.
Input
theFile is pointer to FILE object with assigned name,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes.
Output
CF=0
EAX= it total written size in bytes.
Error
CF=1
EAX= errorCode.
Depends on
FileEncloseRT
Example
FileEnclose LogFile,Datum,SIZE#Datum
FileEnclose %MACRO theFile,DataPtr,DataSize,,,,
    %IF %# & 1 = 0
      %ERROR ID=5942, 'Macro "%0" expects odd number of arguments.'
      %EXITMACRO FileEnclose
    %ENDIF
    PUSHD 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-2
      PUSHD %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
      ADDD [ESP],(%#+1)*4
      CALL FileEnclose@RT
    POP ESP
    FileEncloseRT ; Invoke the common runtime macro.
 %ENDMACRO FileEnclose
FileEncloseLn theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data at the end of existing file or creates a new one and then closes the file.
More than one data item can be appended with one invocation.
When all data have been written, it appends end-of-line character LF to the file.
The file should be assigned but not open.
Input
theFile is pointer to FILE object with assigned name,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes.
Output
CF=0
EAX= it total written size in bytes, including CR+LF.
Error
CF=1
EAX= errorCode.
Depends on
FileEncloseRT
FileEncloseLn %MACRO theFile,DataPtr,DataSize,DataPtr2,DataSize2,,,
    %IF %# & 1 = 0
      %ERROR ID=5943, 'Macro "FileEncloseLn" expects odd number of arguments.'
      %EXITMACRO FileEncloseLn
    %ENDIF
    PUSHD 0x0A      ; LF.
    PUSHD 0         ; Mark the end of arguments.
    PUSHD 1         ; Size of LF.
    PUSHD ESP
    ADDD [ESP],2*4  ; Pointer to LF.
    ArgNr %FOR %#..2,STEP=-2
      PUSHD %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],(%#+4)*4
     CALL FileEnclose@RT
    POP ESP
    FileEncloseRT ; Invoke the common runtime macro.
 %ENDMACRO FileEncloseLn
FileEnclose$ theFile, DataPtr$1, DataPtr$2,,,
This macro writes one or more zero-terminated data strings at the end of existing file or it creates a new one and then closes the file.
The file should be assigned but not open.
More than one string can be appended with one invocation. The terminating NULL is not written.
Input
theFile is pointer to FILE object with assigned name,
DataPtr$* are pointers to zero-terminated ANSI strings. Terminating zeroes are not written to the file.
Output
CF=0
EAX= total written size.
Error
CF=1
EAX= is errorCode.
Depends on
FileEncloseRT
Example
FileEnclose$ LogFile, Time$, =" Job started"
FileEnclose$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
    PUSHD 0                    ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-1
      PUSHD EAX,%*{%ArgNr}
      CALL FileEnclose$size@RT ; Using subprocedure in FileEncloseRT get datasize to EAX.
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],2 * %# * 4
     CALL FileEnclose@RT
    POP ESP
    FileEncloseRT              ; Invoke the common runtime macro.
  %ENDMACRO FileEnclose$
FileMapOpen theFile
opens an existing regular file for reading and creates file mapping to memory.
Content of the file will be available for reading and pointed to with ESI.
The file cannot be assigned with device, pipe or empty name.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX= file size,
ESI= pointer to the memory-mapped file contents.
Error
CF=1
ESI=0
EAX= errorCode.
Depends on
FileOpen
FileMapOpen %MACRO theFile
       PUSHD %theFile
       CALL FileMapOpen@RT::
FileMapOpen@RT:: PROC1
    PUSHAD
     MOV EDI,[ESP+36]             ; theFile.
     FileOpen EDI
.Err:MOV [ESP+28],EAX             ; Return EAX.
     JC .End:
     MOV [EDI+FILE.Size],EAX
     MOV EDX,[EDI+FILE.Handle]
     PUSHD 0,EDX,MAP_SHARED,PROT_READ+PROT_EXEC,EAX,0
     MOV EBX,ESP
     LinAPI mmap,EBX,Fastmode=Yes
     ADD ESP,6*4
     CMP EAX,-ERR_MAX
     CMC
     JC .Err:
     MOV [ESP+4],EAX              ; Return ESI=Pointer to the mapped memory.
     MOV [EDI+FILE.Ptr],EAX
     MOV [EDI+FILE.BufPtr],EAX
     MOV [EDI+FILE.MapHandle],EAX
     ADD EAX,[EDI+FILE.Size]
     MOV [EDI+FILE.Top],EAX
     SetSt [EDI+FILE.Status],fileStMapped+fileStMapOpened
.End:POPAD
    RET 1*4
  ENDPROC1 FileMapOpen@RT::
%ENDMACRO FileMapOpen
FileMapCreate theFile, FileSize
Macro FileMapCreate will create or rewrite an existing file for writing and create file mapping. Size of the file being created should be specified with FileSize.
File content can be copied to the mapped memory returned in EDI but not more than FileSize bytes.
The file cannot be assigned with device, pipe or empty name.
Input
theFile is pointer to a FILE object with assigned name.
FileSize is the size of memory mapped file. It may be omitted when FileMapCreate opens an existing file.
Output
CF=0
EAX=FileSize
EDI= is pointer to the memory mapped file content.
Error
CF=1
EDI=0
EAX= errorCode as returned from GetLastError.
FileMapCreate %MACRO theFile,FileSize
       %IF %# > 1
         PUSHD %FileSize
       %ELSE
         PUSHD 0
       %ENDIF
       PUSHD %theFile
       CALL FileMapCreate@RT::
FileMapCreate@RT:: PROC1
      PUSHAD
       MOV EDI,[ESP+36]         ; theFile.
       LEA EBX,[EDI+FILE.Name]
       LinAPI open,EBX,O_RDWR|O_CREAT,777q,Fastmode=Yes
       TEST EAX
       JNS .10:
.Error:MOVD [ESP+0],0            ; Returned EDI.
       MOV [ESP+28],EAX          ; Returned EAX.
       STC
       JMP .90:
.10:   MOV [EDI+FILE.Handle],EAX
       MOV ESI,EAX
       MOV ECX,[ESP+40]          ; Requested file size.
       LinAPI ftruncate,ESI,ECX,Fastmode=Yes
       TEST EAX
       JNZ .Error:
       PUSHD EAX,ESI,MAP_SHARED+MAP_32BITS,PROT_READ+PROT_WRITE+PROT_EXEC,ECX,EAX
        MOV EBX,ESP
        LinAPI mmap,EBX, Fastmode=Yes
       ADD ESP,6*4
       CMP EAX,-ERR_MAX
       JNC .Error:
       MOV [ESP+0],EAX           ; Returned EDI=Pointer to mapped memory.
       SetSt [EDI+FILE.Status],fileStMapCreated+fileStMapped+fileStCreated
       MOV [EDI+FILE.MapHandle],EAX
       MOV [EDI+FILE.Ptr],EAX
       MOV [EDI+FILE.BufPtr],EAX
       ADD EAX,[EDI+FILE.Size]
       MOV [EDI+FILE.Top],EAX
.90: POPAD
     RET 2*4
   ENDPROC1 FileMapCreate@RT::
 %ENDMACRO FileMapCreate
FileStreamOpen theFile, BufSize=16K
This macro opens an existing file for reading and allocates memory buffer from OS heap. Buffer will be read from file on the FileStreamRead* request.
Input
theFile is pointer to a FILE object with assignemd name.
BuffSize= specifies the buffer size.
Output
CF=0
EAX= file size.
Error
CF=1
EAX= errorCode
Depends on
FileOpen
FileStreamOpen %MACRO theFile,BufSize=16K
       PUSHD %BufSize,%theFile
       CALL FileStreamOpen@RT::
FileStreamOpen@RT:: PROC1
     PUSHAD
      MOV EDI,[ESP+36]   ; theFile.
      MOV ECX,[ESP+40]   ; BufSize.
      MOV [EDI+FILE.BufSize],ECX
      XOR EAX,EAX
      PUSHD EAX,-1,MAP_PRIVATE+MAP_ANONYMOUS,PROT_READ+PROT_WRITE,ECX,EAX
       MOV EBX,ESP
       LinAPI mmap,EBX,Fastmode=Yes
      ADD ESP,6*4
      CMP EAX,-ERR_MAX
      CMC
      JC .90:
      SetSt [EDI+FILE.Status],fileStAllocated
      MOV [EDI+FILE.MapHandle],EAX
      MOV [EDI+FILE.BufPtr],EAX
      MOV EBX,EAX
      FileOpen EDI
      MOV [EDI+FILE.Ptr],EBX
      MOV [EDI+FILE.Top],EBX
.90:  MOV [ESP+28],EAX         ; Returned EAX.
     POPAD
     RET 2*4
  ENDPROC1 FileStreamOpen@RT::
 %ENDMACRO FileStreamOpen
FileStreamRead theFile, DataPtr, DataSize
reads data from the file opened with FileStreamOpen.
Input
theFile is pointer to a FILE object.
DataPtr points to a memory area allocated by the caller,
DataSize is amount of bytes to read.
Output
CF=0
ZF=0
EAX= how many bytes was read (may be less the DataSize).
End of file
CF=0
ZF=1
EAX= 0 when there are no more bytes in the file (EOF).
error
CF=1
EAX= errorCode.
FileStreamRead %MACRO theFile,DataPtr,DataSize
       PUSHD %DataSize,%DataPtr,%theFile
       CALL FileStreamRead@RT::
FileStreamRead@RT:: PROC1
     PUSHAD
       SUB EDX,EDX
       MOV EBX,[ESP+36]       ; theFile.
       MOV EAX,-EBADFD        ; Error: file is not open.
       JNSt [EBX+FILE.Status],fileStOpened,.ErrorEAX:
       JNSt [EBX+FILE.Status],fileStAllocated,.ErrorEAX:
       MOV EDI,[ESP+40]       ; DataPtr.
.10:   MOV ESI,[EBX+FILE.Ptr]
.20:   MOV ECX,[EBX+FILE.Top]
       SUB ECX,ESI            ; How many bytes is left in buffer.
       JNA .50:
       CMP ECX,[ESP+44]       ; Is it enough for the requested DataSize?
       JA .60:
       SUB [ESP+44],ECX
       ADD EDX,ECX
       REP MOVSB
       MOV [EBX+FILE.Ptr],ESI
       JMP .20:
.50:   MOV ESI,[EBX+FILE.BufPtr]
       MOV [EBX+FILE.Ptr],ESI
       MOV [EBX+FILE.Top],ESI
       PUSH EBX
         LinAPI read,[EBX+FILE.Handle],ESI,[EBX+FILE.BufSize],Fastmode=Yes
       POP EBX
       CMP EAX,-ERR_MAX
       CMC
       JC .80:
       ADD [EBX+FILE.Top],EAX
       JMP .20:
.60:   MOV ECX,[ESP+44]         ; DataSize.
       ADD EDX,ECX
       REP MOVSB
       MOV [EBX+FILE.Ptr],ESI
.70:   MOV EAX,EDX
       ADD [EBX+FILE.Pos],EDX
       TEST EAX
.80:   MOV [ESP+28],EAX         ; Returned EAX.
.90: POPAD
     RET 3*4
 ENDPROC1 FileStreamRead@RT::
%ENDMACRO FileStreamRead
FileStreamReadLn theFile
reads one LineFeed-terminated physical line from the file opened with FileStreamOpen.
When the size of physical line exceeds the size of buffer allocated with FileStreamOpen, returned data may not terminate with 0x0A (LineFeed) and FileStreamReadLn should be invoked again - per partes reading.
Input
theFile is pointer to a FILE object.
Output
CF=0
ZF=0
EAX= line size (never bigger than theFILE.BufSize)
ESI= pointer to the line in buffer.
End of file
CF=0
ZF=1
EAX=0 when there are no more data in file (EOF).
ESI= undefined
Error
CF=1
EAX= errorCode.
ESI= undefined.
FileStreamReadLn %MACRO theFile
      PUSHD %theFile
      CALL FileStreamReadLn@RT::
FileStreamReadLn@RT:: PROC1
    PUSHAD
      MOV EBP,[ESP+36]      ; theFile.
      MOV EAX,-EBADFD       ; Error: file is not open.
      JNSt [EBP+FILE.Status],fileStOpened, .Err:
      JNSt [EBP+FILE.Status],fileStAllocated, .Err:
      MOV EDI,[EBP+FILE.Ptr]
.10:  MOV ECX,[EBP+FILE.Top]
      MOV [ESP+4],EDI       ; Returned ESI.
      MOV EDX,EDI
      SUB ECX,EDI
      JNA .30:
      MOV AL,10             ; Search for LineFeed.
      REPNE SCASB
      JE .50:
      CMP EDX,[EBP+FILE.BufPtr]
      JE .50:
      ; When EOL is out of buffer and start of line is not
      ;  at buffer's beginning, the buffer will be reloaded with the current line.
      MOV ECX,EDX
      SUB ECX,EDI
      LinAPI lseek,[EBP+FILE.Handle],ECX,SEEK_CUR,Fastmode=Yes
      CMP EAX,-ERR_MAX
      JNC .Err:
.30:  MOV EDI,[EBP+FILE.BufPtr]
      MOV [EBP+FILE.Ptr],EDI
      MOV [EBP+FILE.Top],EDI
      LinAPI read,[EBP+FILE.Handle],EDI,[EBP+FILE.BufSize],Fastmode=Yes
      CMP EAX,-ERR_MAX
      JNC .Err:
      TEST EAX
      JZ .Eof:
      ADD EAX,EDI
      MOV [EBP+FILE.Top],EAX
      JMP .10:
.Err: STC
      JMP .80:
.Eof: SUB EAX,EAX
      JMP .80:
.50:  MOV [EBP+FILE.Ptr],EDI
      MOV EAX,EDI
      SUB EAX,EDX
      ADD [EBP+FILE.Pos],EAX
.80:  MOV [ESP+28],EAX       ; Returned EAX.
    POPAD
    RET 4
 ENDPROC1 FileStreamReadLn@RT::
%ENDMACRO FileStreamReadLn
FileStreamReadByte theFile
reads one byte from the file opened with FileStreamOpen.
Input
theFile is pointer to a FILE object.
Output
CF=0
ZF=0
AL= the byte read from file. Upper 3 bytes in EAX are preserved.
End of file
CF=0
ZF=1
AL=0 when there are no more bytes in the file (EOF).
Error
CF=1
EAX= errorCode.
FileStreamReadByte %MACRO theFile
     PUSHD %theFile
     CALL FileStreamReadByte@RT::
FileStreamReadByte@RT:: PROC1
     PUSHAD
      MOV EDI,[ESP+36]       ; theFile.
.10:  MOV ESI,[EDI+FILE.Ptr]
      CMP ESI,[EDI+FILE.Top]
      JB .50:
      MOV EAX,-EBADFD        ; Error: file is not open.
      JNSt [EDI+FILE.Status],fileStOpened,.Error:
      JNSt [EDI+FILE.Status],fileStAllocated,.Error:
      MOV ECX,[EDI+FILE.BufPtr]
      MOV [EDI+FILE.Ptr],ECX
      MOV [EDI+FILE.Top],ECX
      LinAPI read,[EDI+FILE.Handle],ECX,[EDI+FILE.BufSize],Fastmode=Yes
      CMP EAX,-ERR_MAX
      JNC .Error:
      TEST EAX
      JZ .80:
      ADD [EDI+FILE.Top],EAX
      JMP .10:              ; This time it will not fail.
.Error:STC
      JMP .80:
.50:  MOV EAX,[ESP+28]      ; Do not clobber other bytes in EAX but AL.
      LODSB
      MOV [EDI+FILE.Ptr],ESI
      INCD [EDI+FILE.Pos]
      CLC
.80:  MOV [ESP+28],EAX      ; Returned EAX.
     POPAD
     RET 4
  ENDPROC1 FileStreamReadByte@RT::
 %ENDMACRO FileStreamReadByte
FileStreamCreate theFile, BufSize=16K
This macro creates a new file or rewrites an existing file for writing and allocates memory buffer from OS heap. The buffer will be automatically written to the file whenever it is completely filled with FileStreamWrite*.
Input
theFile is pointer to a FILE object with assigned filename.
BuffSize= specifies the buffer size.
Output
CF=0
EAX=0 (size of just rewritten file).
Error
CF=1
EAX= errorCode.
Depends on
FileCreate
FileStreamCreate %MACRO theFile,BufSize=16K
       PUSHD %BufSize,%theFile
       CALL FileStreamCreate@RT::
FileStreamCreate@RT:: PROC1
    PUSHAD
     MOV EDI,[ESP+36]     ; theFile.
     FileCreate EDI
     JC .80:
     MOV ECX,[ESP+40]     ; BufSize.
     PUSH 0,-1,MAP_PRIVATE+MAP_ANONYMOUS,PROT_READ+PROT_WRITE+PROT_EXEC,ECX,0
      MOV EBX,ESP
      LinAPI mmap,EBX,Fastmode=Yes
     ADD ESP,6*4
     CMP EAX,-ERR_MAX
     CMC
     JC .80:
     MOV [EDI+FILE.BufSize],ECX
     MOV [EDI+FILE.BufPtr],EAX
     MOV [EDI+FILE.Ptr],EAX
     ADD EAX,ECX
     MOV [EDI+FILE.Top],EAX
     SetSt [EDI+FILE.Status],fileStAllocated
     MOV EAX,[EDI+FILE.Size]
.80: MOV [ESP+28],EAX      ; Returned EAX.
    POPAD
    RET 2*4
  ENDPROC1 FileStreamCreate@RT::
%ENDMACRO FileStreamCreate
FileStreamAppend theFile, BufSize=16K
This macro creates a new file or rewrites an existing file for writing at its end and allocates memory buffer from heap. Buffer will be written to file every time it is completely filled with FileStreamWrite*.
Input
theFile is pointer to a FILE object,
BuffSize= specifies the buffer size.
Output
CF=0
EAX= is the old file size.
Error
CF=1
EAX= errorCode.
Depends on
FileStreamCreate
FileStreamAppend %MACRO theFile,BufSize=16K
       PUSHD %BufSize,%theFile
       CALL FileStreamAppend@RT::
FileStreamAppend@RT:: PROC1
     PUSH EBX,ECX
       MOV EBX,[ESP+12] ; theFile
       MOV ECX,[ESP+16] ; BufSize
       SetSt [EBX+FILE.Status],fileStAppend
       FileStreamCreate EBX,ECX
     POP ECX,EBX
     RET 2*4
   ENDPROC1 FileStreamAppend@RT::
 %ENDMACRO FileStreamAppend
FileStreamWriteByte theFile
This macro writes one byte from AL to the file opened with FileStreamCreate or FileStreamAppend.
Input
theFile is pointer to a FILE object,
AL contains the data byte to write.
Output
CF=0, registers unchanged.
Error
CF=1
EAX= errorCode.
Depends on
FileFlush
FileStreamWriteByte %MACRO theFile
      PUSHD %theFile
      CALL FileStreamWriteByte@RT::
FileStreamWriteByte@RT:: PROC1
     PUSHAD
      MOV EBX,[ESP+36]           ; theFile.
.10:  MOV EDI,[EBX+FILE.Ptr]
      CMP EDI,[EBX+FILE.Top]
      JB .50
      FileFlush EBX              ; Write the buffer if it is full.
      JNC .10:
      MOV [ESP+28],EAX           ; Returned EAX on error.
      JMP .90:
.50:  STOSB
      MOV EAX,[EBX+FILE.Pos]
      MOV [EBX+FILE.Ptr],EDI
      ADD EAX,1
      MOV [EBX+FILE.Pos],EAX
      MOV [EBX+FILE.Size],EAX
.90: POPAD
     RET 4
  ENDPROC1 FileStreamWriteByte@RT::
 %ENDMACRO FileStreamWriteByte
FileStreamWriteWord theFile
This macro writes one word from AX to the file opened with FileStreamCreate or FileStreamAppend.
Input
theFile is pointer to a FILE object,
AX contains the data word to write.
Output
CF=0, registers unchanged.
Error
CF=1
EAX= errorCode.
Depends on
FileFlush
FileStreamWriteWord %MACRO theFile
      PUSHD %theFile
      CALL FileStreamWriteWord@RT::
FileStreamWriteWord@RT:: PROC1
     PUSHAD
      MOV EBX,[ESP+36]           ; theFile.
.10:  MOV EDI,[EBX+FILE.Ptr]
      LEA EDX,[EDI+1]
      CMP EDX,[EBX+FILE.Top]
      JB .50:
      FileFlush EBX              ; Write the buffer if it is full.
      JNC .10:
      MOV [ESP+28],EAX           ; Returned EAX on error.
      JMP .90:
.50:  STOSW
      MOV EAX,[EBX+FILE.Pos]
      MOV [EBX+FILE.Ptr],EDI
      ADD EAX,2
      MOV [EBX+FILE.Pos],EAX
      MOV [EBX+FILE.Size],EAX
      CLC
.90: POPAD
     RET 4
  ENDPROC1 FileStreamWriteWord@RT::
 %ENDMACRO FileStreamWriteWord
FileStreamWriteDword theFile
This macro writes one doubleword from EAX to the file opened with FileStreamCreate or FileStreamAppend.
Input
theFile is pointer to a FILE object,
EAX contains the data word to write.
Output
CF=0, registers unchanged.
Error
CF=1
EAX= errorCode .
Depends on
FileFlush
FileStreamWriteDword %MACRO theFile
      PUSHD %theFile
      CALL FileStreamWriteDword@RT::
FileStreamWriteDword@RT:: PROC1
     PUSHAD
      MOV EBX,[ESP+36]           ; the File.
.10:  MOV EDI,[EBX+FILE.Ptr]
      LEA EDX,[EDI+3]
      CMP EDX,[EBX+FILE.Top]
      JB .50
      FileFlush EBX              ; Write the buffer if it is full.
      JNC .10:
      MOV [ESP+28],EAX           ; Returned EAX on error.
      JMP .90:
.50:  STOSD
      MOV EAX,[EBX+FILE.Pos]
      MOV [EBX+FILE.Ptr],EDI
      ADD EAX,4
      MOV [EBX+FILE.Pos],EAX
      MOV [EBX+FILE.Size],EAX
      CLC
.90: POPAD
     RET 4
  ENDPROC1 FileStreamWriteDword@RT::
 %ENDMACRO FileStreamWriteDword
FileStreamWriteRT
is a runtime defining macro used internally by FileStreamWrite*.
Macro returns CF=0, EAX=total written size, or CF=error
Depends on
FileFlush
FileStreamWriteRT %MACRO ; Common runtime procedure for macros FileStreamWrite*
FileStreamWrite@RT: PROC1
    PUSHAD
     MOV EBX,[ESP+40]   ; theFile
     LEA ESI,[ESP+44]   ; 1st string pointer.
     MOV EAX,-EBADFD    ; File was not opened.
     JNSt [EBX+FILE.Status],fileStCreated,.Err:
     JNSt [EBX+FILE.Status],fileStAllocated,.Err:
     SUB EAX,EAX
     MOV [ESP+28],EAX   ; %Returned EAX is accumulator of written size.
.10: LODSD              ; DataPtr.
     MOV EBP,EAX
     TEST EAX
     JZ .90             ; End of data.
     LODSD              ; DataSize.
     MOV EDX,EAX
     ADD [ESP+28],EAX   ; %Returned EAX.
     PUSH ESI
      MOV ESI,EBP
      ADD [EBX+FILE.Size],EDX
      ADD [EBX+FILE.Pos],EDX
.20:  TEST EDX
      JZ .70
.30:  MOV ECX,[EBX+FILE.Top]
      MOV EDI,[EBX+FILE.Ptr]
      SUB ECX,EDI       ; Remaining free room in Buf.
      JNZ .40:
      FileFlush EBX     ; Flush will reset FILE.Ptr to FILE.BufPtr.
      JNC .30:
      JC .70:
.40:  CMP ECX,EDX
      JBE .50:
      MOV ECX,EDX
.50:  SUB EDX,ECX
      REP MOVSB
      MOV [EBX+FILE.Ptr],EDI
      JA .20:
.70: POP ESI
     JNC .10
.Err:STC
     MOV [ESP+28],EAX
.90:POPAD
    RET

FileStreamWrite$size@RT:
    PUSH EAX,ECX,EDI
     SUB ECX,ECX
     SUB EAX,EAX
     DEC ECX
     MOV EDI,[ESP+16] ; DataPtr.
     REPNE SCASB
     SUB EAX,ECX
     SUB EAX,2
     MOV [ESP+20],EAX ; DataSize.
    POP EDI,ECX,EAX
    RET
 ENDPROC1 FileStreamWrite@RT:
 %ENDMACRO FileStreamWriteRT
FileStreamWrite theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data to the file previously opened with FileStreamCreate or FileStreamAppend.
Multiple data portions may be written in one macro invocation.
Input
theFile is pointer to an open FILE object,
DataPtr* is pointer to the data to be written,
DataSize* is the size of the data in bytes to be written. It may be bigger than the buffer size specified on opening the file.
Output
CF=0
EAX= Total written size in bytes.
Error
CF=1
EAX= errorCode.
Depends on
FileStreamWriteRT
FileStreamWrite %MACRO theFile,DataPtr1,DataSize1,DataPtr2,DataSize2,,,
    %IF %# & 1 = 0
      %ERROR ID=5946, 'Macro "%0" expects odd number of arguments.'
      %EXITMACRO FileStreamWrite
    %ENDIF
    PUSHD 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-2
      PUSHD %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],4*(%#+1)
     CALL FileStreamWrite@RT
    POP ESP
    FileStreamWriteRT ; Invoke the common runtime macro.
 %ENDMACRO FileStreamWrite
FileStreamWriteLn theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data to the file previously opened with FileStreamCreate or FileStreamAppend.
Multiple data portions may be written in one macro invocation. End of line LF character is written in the end.
Input
theFile is pointer to an open FILE object,
DataPtr* is pointer to the data to be written,
DataSize* is the size of the data to be written, including the LF. It may be bigger than the buffer size specified on opening the file.
Output
CF=0
EAX= total written size including LF.
Error
CF=1
EAX= errorCode.
Depends on
FileStreamWriteRT
FileStreamWriteLn %MACRO theFile,DataPtr1,DataSize1,DataPtr2,DataSize2,,,
    %IF %# & 1 = 0
      %ERROR ID=5947, 'Macro "FileStreamWriteLn" expects odd number of arguments.'
      %EXITMACRO FileStreamWriteLn
    %ENDIF
    PUSHD 0x0000000A ; LF.
    PUSHD 0 ; Mark the end of arguments.
    PUSHD 1
    PUSHD ESP
    ADDD [ESP],8 ; Pointer to the LF on stack.
    ArgNr %FOR %#..2,STEP=-2
      PUSHD %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],4*(%#+4)
     CALL FileStreamWrite@RT
    POP ESP
    FileStreamWriteRT ; Invoke the common runtime macro.
 %ENDMACRO FileStreamWriteLn
FileStreamWrite$ theFile, DataPtr$1, DataPtr$2,,,
This macro writes zero terminated ANSI string(s) to the file previously opened with FileStreamCreate or FileStreamAppend.
Multiple strings may be written in one macro invocation. The terminating zeros are not written to the file.
Input
theFile is pointer to an open FILE object,
DataPtr$* are pointers to the zero terminated strings to be written.
Output
CF=0
EAX= total written size.
Error
CF=1
EAX= errorCode.
Depends on
FileStreamWriteRT
FileStreamWrite$ %MACRO theFile,DataPtr$1,DataPtr$2,DataPtr$3,,,
    PUSHD 0 ; mark end of arguments
    ArgNr %FOR %#..2,STEP=-1
      PUSHD EAX,%*{%ArgNr}
      CALL FileStreamWrite$size@RT
    %ENDFOR ArgNr
    PUSHD %theFile
    PUSH ESP
     ADDD [ESP],8*%#
     CALL FileStreamWrite@RT
    POP ESP
    FileStreamWriteRT ; Invoke the common runtime macro.
  %ENDMACRO FileStreamWrite$
  ENDHEAD linf32

▲Back to the top▲