FILE OPERATIONS A file is a sequence of bytes. The bytes may be accessed either sequentially or randomly. Most files may be accessed either way, and sequential and random accesses may be arbitrarily interspersed. Some Unix special files may be only accessed sequentially. File Names A file name is a counted string. Under Unix, legal filenames are the usual Unix pathnames, for instance: foo.c /usr/wmb/foo.c ../foo.c Addressing The bytes within a file may be thought of as being numbered from 0 up to one less than the number of bytes in the file. For random accesses to files, the address is specified with each access. The address is a 32-bit number, allowing files to be up to 2**32 bytes (about 4* 10**9). A file may be thought of as an alternate address space, allowing things like meta-compilation to a file. Definitions: file descriptor denoted in stack diagrams by "fd". A number that is used to refer to a file once the file has been opened. file name denoted in stack diagrams by "name". The address of a packed string which is the ascci representation of the name of a file. See the section entitled "File Names". file pointer denoted in stack diagrams by "l.addr". A 32-bit number which is the number of the byte which will be returned by the next sequential access to the file. Each file descriptor has a separate file pointer associated with it. Glossary: OPEN name mode -- fd name is the address of a packed string which is the name of a file to open. mode is one of READ , WRITE , or MODIFY , and specifies which sorts of operations will be performed on the file. fd is a file descriptor which may be used to subsequently access the file. If the file is not accessible, for example it doesn't exist, then 0 will be returned as the fd value. A successful open will set the file pointer to 0, so that the next sequential access will occur at the beginning of the file. CLOSE fd -- fd is the file descriptor (as returned by a previous OPEN) of an open file. That file is closed so that it may no longer be accessed using that file descriptor. Since the number of file descriptors may be limited, a file should be CLOSEd when it is no longer being used, so that the file descriptor may be reused. FPUTC byte fd -- The least significant 8 bits of byte are put on the open file whose file descriptor is fd. The byte is put at a position within the file determined by the current value of the file pointer. The file pointer is then incremented. FGETC fd -- byte byte is the byte from the open file whose file descriptor is fd. The byte comes from a position in the file determined by the current value of the file pointer. The file pointer is then incremented. If there are no more bytes in the file, byte is EOF (-1). Note that any byte is in the range {0..255}, whereas EOF is -1, so they are distinct. FPUTS addr count fd -- count bytes starting at addr are written to the open file whose file descriptor is fd. Bytes are put on the file starting at the current file pointer position. The file pointer is advanced to point to the byte just after the last byte put on the file. FGETS addr count fd -- nread Transfer bytes from the open file whose file descriptor is fd. Bytes are transferred to memory starting at addr. count is the maximum number of bytes to transfer; if possible, exactly count bytes will be transferred. nread is the number of bytes actually read, which may be less than count, but not more. If nread is 0, it means that the file pointer was already at the end of the file. FILEC! byte l.addr fd -- byte is stored into the open file whose file descriptor is fd, at the position indicated by l.addr (a 32-bit number). The file pointer is moved to l.addr+1. FILEC@ l.addr fd -- byte byte is the byte from the open file whose file descriptor is fd, from the position indicated by l.addr (a 32-bit number). The file pointer is moved to l.addr+1. FSEEK l.addr fd -- The file pointer for the open file whose file descriptor is fd is moved to the position indicated by l.addr (a 32-bit number). FTELL fd -- l.addr l.addr (a 32-bit number) is the current position of the file pointer for the open file whose file descriptor is fd. GETWORD addr fd -- addr Accept the next sequence of non-white characters from the open file whose file descriptor is fd, placing them as a counted string into memory starting at addr. The byte at addr will contain the character count. addr is left on the stack unchanged. A "non-white" character is any character except blank, tab, newline, or carriage return. Leading "white" characters are skipped. If there were no more non-white characters in the file, the byte at addr will contain zero. GETCWORD addr delim fd -- addr Accept the next sequence of non-delimiter characters from the open file whose file descriptor is fd, placing them as a counted string into memory starting at addr. The byte at addr will contain the character count. addr is left on the stack unchanged. A non-delimiter character is any character except delim. newline, or carriage return. Leading delimiter characters are NOT skipped. If there were no more characters in the file, the byte at addr will contain zero. The behavior of GETWORD and GETCWORD with respect to leading delimiters is consistent with the way that they are actually used in practice. Specifically, BL WORD is used to scan for the next Forth word, and it is desirable to ignore leading blanks. Tabs, newlines, and carriage returns do not appear in Forth screens, so it is not necessary to deal with them. They do appear in files created by other operating systems, so a file system which attempts to be compatible with other operating systems must also deal with them. When WORD is used with some delimiter other than BL, the intention is really that leading delimiters should NOT be ignored! For example, when WORD is used to scan for the ")" which terminates a comment, it is desireable to find one immediately in case of the null comment ( ). Similarly, ." and ABORT" should work with null strings, as in ." " ABORT" " . The usual work-around is to explicitly check the input stream to see if a delimiter is there before calling WORD. This just points to the fact that there should be two different versions of WORD, one which gets non-white characters, ignoring leading white-space, and one which takes an explicit delimiter off the stack and terminates as soon as it encounters a delimiter. The actual delimiter which terminated the GETWORD or GETCWORD is stored in the global variable DELIMITER. If an end-of-file condition terminated the operation, the value of DELIMITER is EOF. MAKE name -- A new file is created with the given name. name is the address of a counted string. If the file already exists, an error condition exists. DELETE name -- flag The file with the given name is removed from the system. flag is true if the operation succeeded. FILES -- Show the names of the files in the current directory are displayed. FILE-ERROR -- error error is zero if the most recent file operation succeeded. If it failed, error is a system dependent error code. *****Implement me******* FSIZE fd -- l.size l.size is the size of the file whose descriptor is fd.