Tables, Rules and Hypothetical Reasoning
Hypothetical Reasoning
categories
I/O, Modules and System Interface
Communication ports
Printing

I/O, Modules and System Interface

Communication ports [XL]

In XL CLAIRE, the entire port interface has been rewritten such port is now the root class for an extensible hierarchy of communication interface (In CLAIRE 3, ports are based on a C++ import). We define two sorts of port :

Definition : A device is a communication port that is connected to a physical port like a file or a socket that can be handled through a chain of filter

Definition : A filter is a communication port that may modify, buffer or look at a data read or written from a device.

Given this sorts, we define the descriptor device as a wrapper for UNIX descriptor which handles read, write (read_port and write_port interface) and close (close_port interface) operations in a unified way for each derived class (disk_file, socket, pipe). At startup, 3 global variables named stdin, stdout and stderr are created to hold the standard input, output, and error devices respectively (UNIX descriptors 0,1,2 on most system).

Languages often provide these standard ports in a buffered way, that is system calls read(2) or write(2) are made by chunks. So XL CLAIRE comes with two kind of filter, the buffer (as created by buffer!) that perform read (or write) once for each read (or written) chunk of a given size and the line_buffer (as created by line_buffer!) that perform write calls once for each written line. Depending on how the program was launched, the standard output may be a terminal or something else (e.g. pipe). In the later case we'll always provide stdout as a buffer but when it is found that the output is a terminal device, which is often shared by multiple processes, we'll provide stdout as a line_buffer. On the other hand the standard error port is always provided unbuffered, such that in case of crash we avoid data miss that could be hold by a buffer.

To avoid problems of synchronization between reading and writing, it is sometimes useful to ensure that the buffer of a given port is empty. This is done by the command flush(p:port). flush(p) will perform all printing instructions for the port p that are waiting in the associated buffer (flush_port interface).

A (buffered) file is opened with fopen(s:string,m:string) where s is the file path and m the opening mode ("r": read, "w": write, "a": append). For instance :
 inefficient_show_size(filepath:string: void ->
     let f := fopen(filepath"r"),
         content := fread(f)
     in printf("File ~A has ~S bytes\n"filepathlength(content))
An other provided interface is the ability to make a port from a string and vice versa. In XL CLAIRE we call that blob (based on device), the internal data representing the string is a chunk of memory allocated dynamically outside CLAIRE memory (CLAIRE 3 port! interface is supported for compatibility). Blob can be made in various ways with blob! including blob!(s:string) that would initialize the internal data with the string s :
 let b := blob!("toto")
 in assert(fread(b= "toto")

 let b := blob!()
 in (fwrite("toto",b),
     assert(fread(b= "toto"))


categories Communication portsnormal dispatch operation[XL] Core method

+(self:char*, n:integer) -> char*

translate the char* pointer self with an offset of n bytes


categories Communication portsephemeral [XL] Core class

blob <: device

blob is a port interface for strings, data are stored in a chunk of memory allocated outside claire memory.


categories Communication portsnormal dispatch [XL] Core method

blob!() -> blob

allocate an empty blob


categories Communication portsnormal dispatch [XL] Core method

blob!(n:integer) -> blob

allocate a blob that can receive at least n bytes (i.e. writing more than n bytes may cause further allocation)


categories Communication portsnormal dispatch [XL] Core method

blob!(p:blob) -> blob

allocate a blob that is a copy of the given blob


categories Communication portsnormal dispatch [XL] Core method

blob!(self:string) -> blob

allocate a blob with the string self has the initial data


categories Communication portsnormal dispatch [XL] Core method

blob!(p:port) -> blob

allocate a blob that is filled with all data that can be read on p


categories Communication portsnormal dispatch [XL] Core method

bqexpand(s:string) -> string

perform a back-quote expansion of the system command s. subexpressions enclosed by '`' are substituted by the output generated by the corresponding command ex: bexpand("`ls`") returns the result of an ls command


categories Communication portsephemeral [XL] Core class

buffer <: filter

a buffer filter performs a single read/write call on its target for each data raw of a given size (buffer_length). It comes as replacement of the C FILE* buffering capability.


categories Communication portsnormal dispatch [XL] Core method

buffer!(self:port, bufsize:integer) -> buffer

buffer! creates a buffer filter on the port self with an internal buffer bufsize bytes long.


categories Communication portsephemeral [XL] Core class

byte_counter <: filter

byte_counter is a pure filter that count the number of bytes transfered in both directions


categories Communication portsabstract [XL] Core class

char* <: import

read_port and write_port operate on a given buffer of a given size. these buffers are char* imported from C, this way we have an interface similar to read(2) and write(2)


categories Communication portsnormal dispatch [XL] Core method

client!(addr:string) -> socket

creates a UNIX domain connected socket on the UNIX domain server at file addr


categories Communication portsnormal dispatch [XL] Core method

client!(addr:string, p:integer) -> socket

creates a connected socket at the address "addr:p", addr may be a numeric IP or a server name and p is the TCP port on which the connection should be made. For instance we could implement a simple HTTP GET :
 httpget(addr:stringf:string: string ->
     let c := client!(addr80)
     in (printf(c"GET /~A HTTP/1.0\r\n\r\n"f),
         let response := fread(c)
         in (fclose(c), response))


categories Communication portsfast dispatch [XL] Core interface

close_port :: property(open = 3, range = void)

interface to close the port :
 close_port(self:my_port: void ->
     ...


categories Communication portsnormal dispatch [XL] Core method

close_target!(self:filter) -> type[self]

tell that the filter should close its target when it is itself closed (cascading close)


categories Communication portsnormal dispatch [XL] Kernel method

decode64(pr:port, pw:port) -> void

decode64(pr,pw) reads pr until EOF. read data is assumed to be encoded in base 64, the decoded data is written on pw.


categories Communication portsephemeral [XL] Core class

descriptor <: device

UNIX file descriptor wrapping. we do not use C stream capabilities (FILE*) but the descriptor itself, which make the API relying on system calls read(2) and write(2), stream interface is provided by filters (buffer)


categories Communication portsephemeral [XL] Core class

device <: port

physical port like a descriptor or a blob that may be handled through a chain of filter


categories Communication portsephemeral [XL] Core class

disk_file <: descriptor

disk_file is the interface for file located on the hard drive


categories Communication portsnormal dispatch [XL] Kernel method

encode64(pr:port, pw:port, line_length:integer) -> void

encode64(pr,pw,line_length) reads pr until EOF. read data are encoded in base 64 and then written on the port pw. line_length specify the length at which carriage return are inserted.


categories Communication portsnormal dispatch [XL] Core method

eof?(self:port) -> boolean

check whether the end-of-file condition has been reached


categories Communication portsfast dispatch [XL] Core interface

eof_port? :: property(open = 3, range = boolean)

interface to check the end-of-file condition on a given port :
 eof_port?(self:my_port: boolean ->
     ...


categories Communication portsephemeral [XL] Core class

filter <: port

port that may analyze and/or transform and/or collect read and/or written data like a buffer, a line counter or even a MIME decoder or any kind embedded protocols.


categories Communication portsnormal dispatch [XL] Core method

filter!(self:filter, p:port) -> type[self]

filter! should be used by filter constructors, it ensures the good shape of the inner relations (i.e. between the filter and its device)


categories Communication portsnormal dispatch Core method

flush(self:port) -> void

flush pending buffers in the filter chain such pending data are actually written on the device


categories Communication portsnormal dispatch Core method

flush(self:port, n:integer) -> void

for compatibility with <ycs> mainly used for stdin


categories Communication portsfast dispatch [XL] Core interface

flush_port :: property(open = 3, range = void)

interface to flush pending buffered data
 flush_port(self:my_port: void ->
     ...


categories Communication portsnormal dispatch [XL] Core method

fopen(self:string, mode:OPEN_MODE) -> buffer

open a file on disk. the returned port is buffered. This is a lib C like fopen API (see man for details). note: unlike in C lib there is no support for the 'b' mode (binary) i.e. always open in binary mode. For instance here is a simple file copy method :
 file_copy(src:stringcpy:string: void ->
     let fsrc := fopen(src"r"),
         fcpy := fopen(cpy,"w")
     in (freadwrite(fsrcfcpy),
         fclose(fsrc),
         fclose(fcpy))
Notice this method does not properly set the mode of the copied file as done by fcopy.


categories Communication portsnormal dispatch [XL] Kernel method

fread(self:port) -> string

read all data on self until eof


categories Communication portsnormal dispatch [XL] Kernel method

fread(self:port, s:string) -> integer

read inside an existing string, this overwrites the string content and may modify the string length if an eof condition is reached on self. the amount of queried bytes is the length of the input string


categories Communication portsnormal dispatch [XL] Kernel method

fread(self:port, n:integer) -> string

read a string of n bytes on self the length of the returned string may be lower than n if an eof condition is reached on self


categories Communication portsnormal dispatch [XL] Kernel method

freadline(p:port) -> string

freadline(p) read a single line on the port p. The end-on-line marker is either CRLF, CR or LF and is not part of the returned line.


categories Communication portsnormal dispatch [XL] Kernel method

freadline(p:port, sep:string) -> string

Equivalent to freadline(p, sep, true)[1]


categories Communication portsnormal dispatch [XL] Kernel method

freadline(p:port, seps:bag) -> tuple(string, string U char)

Equivalent to freadline(p, seps, true) For instance :
 parse_line_of_floats(p:port: list[float->
     let l := list[float]
     in (while not(eof?(p))
             let (datasep:= freadline(p, {','';''\n'})
             in (if (length(data) > 0l add float!(data),
                 case sep ({""break())), l)


categories Communication portsnormal dispatch [XL] Kernel method

freadline(p:port, seps:bag, sensitive?:boolean) -> tuple(string, string U char)

Equivalent to freadline(p, list(sep), sensitive?) but without support for escaping.


categories Communication portsnormal dispatch [XL] Kernel method

freadline(p:port, seps:bag, sensitive?:boolean, esc:char) -> tuple(string, string U char)

read a raw data from p until a separator in seps matches. If sensitive? is false the separator matching is made insensitively. esc is an escape char that is used while reading the raw data so that the char that follows cannot be part of a match. The return value is a tuple made of :


categories Communication portsnormal dispatch [XL] Kernel method

freadline(p:port, sep:string, sensitive?:boolean, esc:char) -> string

Equivalent to freadline(p, list(sep), sensitive?, esc)[1]


categories Communication portsnormal dispatch [XL] Kernel method

freadwrite(src:port, trgt:port) -> integer

read all data from src until eof and write it on trgt without performing any allocation. returns the amount of byte transfered.


categories Communication portsnormal dispatch [XL] Kernel method

freadwrite(src:port, trgt:port, len:integer) -> integer

read up-to len bytes from src and write them on trgt without performing any allocation. returns the amount of bytes actually transferred (may be lower than len if an eof condition is reached on src)


categories Communication portsnormal dispatch [XL] Core method

fskip(self:port, len:integer) -> integer

skip n bytes from self (dummy read) without performing any allocation and return the amount of bytes actually skipped (may be lower than len if an eof condition is reached)


categories Communication portsnormal dispatch [XL] Kernel method

fwrite(self:string, p:port) -> integer

writes a raw string on the port p


categories Communication portsnormal dispatch [XL] Kernel method

get_index(self:blob) -> integer

returns the current reading index


categories Communication portsnormal dispatch [XL] Core method

getc(self:port) -> char

read a single char on self reading an EOF char does not mean that the end-of-file is reached, one should use eof? @ port to check the eof condition


categories Communication portsnormal dispatch [XL] Core method

gethostname() -> string

returns the name of the host running CLAIRE


categories Communication portsnormal dispatch [XL] Kernel method

length(self:blob) -> integer

return the total amount of bytes contained in the blob, string! @ blob will return a string with that length


categories Communication portsephemeral [XL] Core class

line_buffer <: filter

line_buffer is a write filter that collects written data until a new line character. each line is flushed with a single write on the target port. It is mainly used for terminal output such to prevent line overlap when multiple process share the same terminal output or when a trace file is shared by multiple process.


categories Communication portsnormal dispatch [XL] Core method

line_buffer!(self:port) -> line_buffer

line_buffer! creates a new line_buffer filter on the port self.


categories Communication portsephemeral [XL] Core class

line_counter <: filter

line_counter is a pure filter that count the number of lines transfered in both directions


categories Communication portsnormal dispatch [XL] Core method

linger(self:socket) -> void

since socket are bi-channel communication ports a simple close (i.e. the two channel at once) may cause the client to miss information already sent on the socket but still unsent from the underlying system point of view. This is the purpose of the linger that will ensure that what is sent is actually received: first, the write channel is closed then we wait for the read channel to be closed by the remote part. For sanity this operation has a timeout of 3 seconds


categories Communication portsephemeral [XL] Core class

listener <: socket

the interface for listening sockets. such socket are used with accept to handle new connections.


categories Communication portsnormal dispatch [XL] Kernel method

nth(self:blob, n:integer) -> char

buffer access on the blob


categories Communication portsnormal dispatch [XL] Kernel method

nth(self:char*, n:integer) -> char

get the char at position n in self (n is a 1 based index). Warning : there is no bound check !


categories Communication portsnormal dispatch [XL] Kernel method

nth=(self:blob, n:integer, c:char) -> void

buffer access on the blob


categories Communication portsnormal dispatch [XL] Kernel method

nth=(self:char*, n:integer, c:char) -> void

sets the nthchar in self with c (n is a 1 based index). Warning : there is no bound check !


categories Communication portsephemeral [XL] Core class

pipe <: descriptor

interface for UNIX pipes


categories Communication portsnormal dispatch [XL] Core method

Core/pipe!() -> tuple(pipe, pipe)

create a pair of unidirectional pipe connected to each other. The first one is intended for read and the second one for write. note: some system may return bi-directional pipes...


categories Communication portsnormal dispatch [XL] Core method

popen(file:string, mod:{"r", "w", "rw"}) -> popen_device

popen creates a new process with a redirected input ("r") or output (w). popen may be a two way communication device, this is system dependent


categories Communication ports [XL] Core constant

port! :: blob!

compatibility with <ycs>, one should use blob! instead.


categories Communication portsnormal dispatch Core method

putc(self:char, p:port) -> void

writes a single byte on p


categories Communication portsnormal dispatch [XL] Core method

read!(self:port) -> void

read!(self) put the descriptor self in the selection set used for the select? operation


categories Communication portsfast dispatch [XL] Core interface

read_port :: property(open = 3, range = integer)

interface to read a chunk of data :
 read_port(self:my_portbuf:data*len:integer: integer ->
     ...
the returned value should be the amount of bytes that were actually read


categories Communication portsnormal dispatch [XL] Core method

readable?(self:port) -> boolean

readable?(self) returns true when self has been selected (see select?) and that a read operation is guaranteed to succeed.


categories Communication portsnormal dispatch [XL] Core method

reopen(self:port) -> port

reopen a file for read, the current offset of the reopened file is moved at the same place if a buffer is present on the filter chain then it contents and index are restored


categories Communication portsnormal dispatch [XL] Core method

select?() -> boolean

select?() waits for selected descriptors for a write or read condition to occur. This method blocks until a condition occur and will always return true as soon as a condition is satisfied. selected descriptors are the one for which read! or write! has been called first. In order to test whether a condition was satisfied on a selected descriptor one should use readable? or writeable?.


categories Communication portsnormal dispatch [XL] Core method

select?(ms:integer) -> boolean

select?(ms) is the non-blocking version of select?. It returns true whenever a read or write condition is satisfied on a selected descriptor before a timeout of ms milliseconds could occur. If the timeout is reached before a condition could occur then select?(ms) returns false.

When true is returned a read (resp. write) operation is guaranteed to succeed on a descriptor for which readable? (resp. writable?) returns true. If the descriptor is a listener socket and readable? returns true then accept is guaranteed to succeed.
 get_one_char(c:socket: string ->
     (read!(c),
     if (select?(10& readable?(c))
         fread(c1// always succeed
     else "")


categories Communication portsnormal dispatch [XL] Core method

server!(addr:string) -> listener

creates a UNIX domain listener socket. addr is the absolutepath (i.e. must start with '/') to a file that will be used by the subsystem as listener descriptor.


categories Communication portsnormal dispatch [XL] Core method

server!(p:integer) -> listener

creates a INET domain listener socket listening on the port p. For instance here is a basic HTTP server :
 http_server(n:integer: void ->
     let s := server!(n)
     in (while true
             let c := accept(s)
             in serve_client(c))

 serve_client(c:socket: void ->
     (printf(c"Hello world\n"),
     fclose(c))

 (http_server(80))


categories Communication portsnormal dispatch [XL] Core method

server!(addr:string, p:integer, qlen:integer) -> listener

creates a INET domain listener socket listening on the port p with an internal queue of qlen connections.


categories Communication portsnormal dispatch [XL] Kernel method

set_index(self:blob, n:integer) -> void

sets the current reading index


categories Communication portsnormal dispatch [XL] Core method

set_length(self:blob, n:integer) -> void

sets the amount of bytes contained in the blob, when 0 is given a new chunk is reallocated for the internal data


categories Communication portsephemeral [XL] Core class

socket <: descriptor

the interface for UNIX stream oriented sockets, sockets are two way communication ports connected to a remote client.


categories Communication portsnormal dispatch [XL] Core method

socketpair() -> tuple(socket, socket)

return a pair of inter-connected socket


categories Communication ports [XL] Core global variable

stderr : port := Clib_stderr

the standard error output port


categories Communication ports [XL] Core global variable

stdin : port := Clib_stdin

the standard input port


categories Communication ports [XL] Core global variable

stdout : port := Clib_stdout

the standard output port


categories Communication portsnormal dispatch [XL] Kernel method

string!(self:blob) -> string

string! converts a blob in a string


categories Communication portsnormal dispatch [XL] Kernel method

string!(self:char*, len:integer) -> string

make a new string of length len from a char*


categories Communication portsnormal dispatch [XL] Kernel method

substring(self:blob, i:integer, j:integer) -> string

returns a substring of the internal data considered, i and j are 1 base indexed


categories Communication portsnormal dispatch [XL] Core method

unget(self:port, c:char) -> void

unget a string such the next char that can be read is c


categories Communication portsnormal dispatch [XL] Core method

unget(self:port, s:string) -> void

unget a string such the next data that can be read is s


categories Communication portsfast dispatch [XL] Core interface

unget_port :: property(open = 3, range = void)

interface to unget a chunk of data :
 unget_port(self:my_portbuf:data*len:integer: void ->
     ...


categories Communication portsnormal dispatch [XL] Kernel method

unlink(self:listener) -> void

unlink the UNIX domain socket file associated with the given listener socket


categories Communication portsnormal dispatch Kernel method

use_as_output(p:port) -> port

use_as_output(p) changes the value of the current output (the port where all print instructions will be sent AKA cout()) to p. It returns the previous port that was used as output which can thus be saved and possibly restored later.


categories Communication portsnormal dispatch [XL] Core method

writable?(self:port) -> boolean

writable?(self) returns true when self has been selected (see select?) and that a write operation is guaranteed to succeed.


categories Communication portsnormal dispatch [XL] Core method

write!(self:port) -> void

write!(self) put the descriptor self in the selection set used for the select? operation


categories Communication portsfast dispatch [XL] Core interface

write_port :: property(open = 3, range = integer)

interface to write a chunk of data
 write_port(self:my_portbuf:data*len:integer: integer ->
     ...
the returned value should be the amount of bytes that were actualy written