Chapter 11

Ports and the Filesystem

Ports are represented as Scheme values with the types scheme_input_port_type and scheme_output_port_type. The function scheme_read takes an input port value and returns the next S-expression from the port. The function scheme_write takes an output port and a value and writes the value to the port. Other standard low-level port functions are also provided, such as scheme_getc.

File ports are created with scheme_make_file_input_port and scheme_make_file_output_port; these functions take a FILE * file pointer and return a Scheme port. Strings are read or written with scheme_make_string_input_port, which takes a null-terminated string, and scheme_make_string_output_port, which takes no arguments. The contents of a string output port are obtained with scheme_get_string_output.

Custom ports, with arbitrary read/write handlers, are created with scheme_make_input_port and scheme_make_output_port.

When opening a file for any reason using a name provided from Scheme, use scheme_expand_filename to normalize the filename and resolve relative paths.

11.1  Library Functions

¤ Scheme_Object * scheme_read(Scheme_Object *port)

Reads the next S-expression from the given input port.

¤ void scheme_write(Scheme_Object *obj, Scheme_Object *port)

writes the Scheme value obj to the given output port.

¤ void scheme_write_w_max(Scheme_Object *obj, Scheme_Object *port, int n)

Like scheme_write, but the printing is truncated to n characters. (If printing is truncated, the last three characters are printed as ``.''.)

¤ void scheme_display(Scheme_Object *obj, Scheme_Object *port)

displays the Scheme value obj to the given output port.

¤ void scheme_display_w_max(Scheme_Object *obj, Scheme_Object *port, int n)

Like scheme_display, but the printing is truncated to n characters. (If printing is truncated, the last three characters are printed as ``.''.)

¤ void scheme_write_string(char *str, long d, long len, Scheme_Object *port)

displays len characters of str, starting with the dth character, to the given output port.

¤ long scheme_put_string(const char *who, Scheme_Object *port, char *str, long d, long len,
    int rarely_block)

Writes len characters of str, starting with the dth character. Characters are written to the given output port, and errors are reported as from who.

If rarely_block is 0, the write blocks until all len characters are written, possibly to an internal buffer. If rarely_block is 2, the write never blocks, and written characters are not buffered. If rarely_block is 1, the write blocks only until at least one character is written (without buffering) or until part of an internal buffer is flushed.

The result is -1 if no characters are written from str and unflushed characters remain in the internal buffer. Otherwise, the return value is the number of written characters.

¤ char * scheme_write_to_string(Scheme_Object *obj, long *len)

writes the Scheme value obj to a newly allocated string. If len is not NULL, *len is set to the length of the string.

¤ void scheme_write_to_string_w_max(Scheme_Object *obj, long *len, int n)

Like scheme_write_to_string, but the string is truncated to n characters. (If the string is truncated, the last three characters are ``.''.)

¤ char * scheme_display_to_string(Scheme_Object *obj, long *len)

displays the Scheme value obj to a newly allocated string. If len is not NULL, *len is set to the length of the string.

¤ void scheme_display_to_string_w_max(Scheme_Object *obj, long *len, int n)

Like scheme_display_to_string, but the string is truncated to n characters. (If the string is truncated, the last three characters are ``.''.)

¤ void scheme_debug_print(Scheme_Object *obj)

writes the Scheme value obj to the main thread's output port.

¤ void scheme_flush_output(Scheme_Object *port)

If port is a file port, a buffered data is written to the file. Otherwise, there is no effect. port must be an output port.

¤ int scheme_getc(Scheme_Object *port)

Get the next character from the given input port.

¤ int scheme_peekc(Scheme_Object *port)

Peeks the next character from the given input port.

¤ long scheme_get_string(const char *who, Scheme_Object *port, char *buffer, int offset, long size,
   int only_avail, int peek, Scheme_Object *peek_skip)

Gets multiple characters at once from a port, reporting errors with the name who. The size argument indicates the number of requested characters, to be put into the buffer array starting at offset. The return value is the number of characters actually read, or EOF if an end-of-file is encountered without reading any characters.

If only_avail is 0, then the function blocks until size characters are read or an end-of-file is reached. If only_avail is 1, the function blocks only until at least one character is read. If only_avail is 2, the function never blocks.

If peek is non-zero, then the port is peeked instead of read. The peek_skip argument indicates a portion of the input stream to skip as a non-negative, exact integer (fixnum or bignum). In this case, a only_avail value of 1 means to continue the skip until at least one character can be returned, even if it means multiple blocking reads to skip characters.

If peek is zero, then peek_skip should be either NULL (which means zero) or the fixnum zero.

¤ long scheme_get_chars(Scheme_Object *port, long size, char *buffer, int offset)

For backward compatibility: calls scheme_get_string in essentially the obvious way with only_avail as 0; if size is negative, then it reads -size characters with only_avail as 1.

¤ void scheme_ungetc(int ch, Scheme_Object *port)

Puts the character ch back as the next character to be read from the given input port. The character need not have been read from port, and scheme_ungetc can be called to insert any number of characters at the start of port.

Use scheme_getc followed by scheme_unget only when your program will certainly call scheme_getc again to consume the character. Otherwsie, use scheme_peekc, because some a port may implement peeking and getting differently.

¤ int scheme_char_ready(Scheme_Object *port)

Returns 1 if a call to scheme_getc is guranteed not to block for the given input port.

¤ void scheme_need_wakeup(Scheme_Object *port, void *fds)

Requests that appropriate bits are set in fds to specify which file descriptors(s) the given input port reads from. (fds is sortof a pointer to an fd_set struct; see section 8.4.1.)

¤ long scheme_tell(Scheme_Object *port)

Returns the current read position of the given input port, or the current file position of the given output port.

¤ long scheme_tell_line(Scheme_Object *port)

Returns the current read line of the given input port. If lines are not counted, -1 is returned.

¤ void scheme_count_lines(Scheme_Object *port)

Turns on line-counting for the given input port. To get accurate line counts, call this function immediately after creating a port.

¤ long scheme_set_file_position(Scheme_Object *port, long pos)

Sets the file position of the given input or output port (from the start of the file). If the port does not support position setting, an exception is raised.

¤ void scheme_close_input_port(Scheme_Object *port)

Closes the given input port.

¤ void scheme_close_output_port(Scheme_Object *port)

Closes the given output port.

¤ Scheme_Object * scheme_make_port_type(char *name)

Creates a new port subtype.

¤ Scheme_Input_Port * scheme_make_input_port(Scheme_Object *subtype,
    void *data,
    Scheme_Get_String_Fun get_string_fun,
    Scheme_Peek_String_Fun peek_string_fun,
    Scheme_In_Ready_Fun char_ready_fun,
    Scheme_Close_Input_Fun close_fun,
    Scheme_Need_Wakeup_Input_Fun need_wakeup_fun,
    int must_close)

Creates a new input port with arbitary control functions. The subtype is an arbitrary value to distinguish the port's class. The pointer data will be installed as the port's user data, which can be extracted/set with the SCHEME_INPORT_VAL macro.

The functions are as follows:

If must_close is non-zero, the new port will be registered with the current custodian, and close_fun is guranteed to be called before the port is garbage-collected.

Although the return type of scheme_make_input_port is Scheme_Input_Port *, it can be cast into a Scheme_Object *.

¤ Scheme_Output_Port * scheme_make_output_port(Scheme_Object *subtype,
    void *data,
    Scheme_Write_String_Fun write_string_fun,
    Scheme_Out_Ready_Fun char_ready_fun,
    Scheme_Close_Output_Fun close_fun,
    Scheme_Need_Wakeup_Output_Fun need_wakeup_fun,
    int must_close)

Creates a new output port with arbitary control functions. The subtype is an arbitrary value to distinguish the port's class. The pointer data will be installed as the port's user data, which can be extracted/set with the SCHEME_OUTPORT_VAL macro.

The functions are as follows:

If must_close is non-zero, the new port will be registered with the current custodian, and close_fun is guranteed to be called before the port is garbage-collected.

Although the return type of scheme_make_output_port is Scheme_Output_Port *, it can be cast into a Scheme_Object *.

¤ Scheme_Object * scheme_make_file_input_port(FILE *fp)

Creates a Scheme input file port from an ANSI C file pointer. The file must never block on reads.

¤ Scheme_Object * scheme_open_input_file(const char *filename, const char *who)

Opens filename for reading. In an exception is raised, the exception message uses who as the name of procedure that raised the exception.

¤ Scheme_Object * scheme_make_named_file_input_port(FILE *fp, char *filename)

Creates a Scheme input file port from an ANSI C file pointer. The file must never block on reads. The filename is used for error reporting.

¤ Scheme_Object * scheme_open_output_file(const char *filename, const char *who)

Opens filename for writing in 'truncate/replace mode. If an exception is raised, the exception message uses who as the name of procedure that raised the exception.

¤ Scheme_Object * scheme_make_file_output_port(FILE *fp)

Creates a Scheme output file port from an ANSI C file pointer. The file must never block on writes.

¤ Scheme_Object * scheme_make_string_input_port(char *str)

Creates a Scheme input port from a string; successive read-chars on the port return successive characters in the string.

¤ Scheme_Object * scheme_make_string_output_port()

Creates a Scheme output port; all writes to the port are kept in a string, which can be obtained with scheme_get_string_output.

¤ char * scheme_get_string_output(Scheme_Object *port)

Returns (in a newly allocated string) all data that has been written to the given string output port so far. (The returned string is null-terminated.)

¤ char * scheme_get_sized_string_output(Scheme_Object *port, long *len)

Returns (in a newly allocated string) all data that has been written to the given string output port so far and fills in *len with the length of the string (not including the null terminator).

¤ void scheme_pipe(Scheme_Object **read, Scheme_Object **write)

Creates a pair of ports, setting *read and *write; data written to *write can be read back out of *read. The pipe can store arbitrarily many unread characters,

¤ void scheme_pipe_with_limit(Scheme_Object **read, Scheme_Object **write, int limit)

Like scheme_pipe is limit is 0. If limit is positive, creates a pipe that stores at most limit unread characters, blocking writes when the pipe is full.

¤ int scheme_file_exists(char *name)

Returns 1 if a file by the given name exists, 0 otherwise. If name specifies a directory, FALSE is returned. The name should be already expanded.

¤ int scheme_directory_exists(char *name)

Returns 1 if a directory by the given name exists, 0 otherwise. The name should be already expanded.

¤ char * scheme_expand_filename(const char *name, int len, const char *where, int *expanded,
    int checks)

Expands the pathname name, resolving relative paths with respect to the current directory parameter. Under Unix, this expands ``~'' into a user's home directory. On the Macintosh, aliases are resolved to real pathnames. The len argument is the length of the input string; if it is -1, the string is assumed to be null-terminated. The where argument is used to raise an exception if there is an error in the filename; if this is NULL, an error is not reported and NULL is returned instead. If expanded is not NULL, *expanded is set to 1 if some expansion takes place, or 0 if the input name is simply returned.

If guards is not 0, then scheme_security_check_file (see section 13) is called with name, where, and checks (which implies that where should never be NULL unless guards is 0). Normally, guards should be SCHEME_GUARD_FILE_EXISTS at a minimum. Note that a failed access check will result in an exception.

¤ char * scheme_build_mac_filename(FSSpec *spec, int isdir)

Mac OS only: Converts an FSSpec record (defined by Mac OS) into a pathname string. If spec contains only directory information (via the vRefNum and parID fields), isdir should be 1, otherwise it should be 0.

¤ int scheme_mac_path_to_spec(const char *filename, FSSpec *spec, long *type)

Mac OS only: Converts a pathname into an FSSpec record (defined by Mac OS), returning 1 if successful and 0 otherwise. If type is not NULL and filename is a file that exists, type is filled with the file's four-character Mac OS type. If type is not NULL and filename is not a file that exists, type is filled with 0.

¤ char * scheme_os_getcwd(char *buf, int buflen, int *actlen, int noexn)

Gets the current working directory according to the operating system. This is separate from MzScheme's current directory parameter.

The direcory path is written into buf, of length buflen, if it fits. Otherwise, a new (collectable) string is allocated for the directory path. If actlen is not NULL, *actlen is set to the length of the current directory path. If noexn is no 0, then an exception is raised if the operation fails.

¤ int scheme_os_setcwd(char *buf, int noexn)

Sets the current working directory according to the operating system. This is separate from MzScheme's current directory parameter.

If noexn is not 0, then an exception is raised if the operation fails.

¤ char * scheme_format(char *format, int flen, int argc, Scheme_Object **argv, long *rlen)

Creates a string like MzScheme's format procedure, using the format string format (of length flen) and the extra arguments specified in argc and argv. If rlen is not NULL, *rlen is filled with the length of the resulting string.

¤ void scheme_printf(char *format, int flen, int argc, Scheme_Object **argv)

Writes to the current output port like MzScheme's printf procedure, using the format string format (of length flen) and the extra arguments specified in argc and argv.