Generic IO is the name given to VFX Forth's entire input/output architecture. This system allows for a "device-driver" to be written to a standard format such that the drivers are all interchangeable within the Forth System. As noted later you will see that all standard Forth I/O words (such as EMIT) are passed through Generic I/O. )
Under VFX each thread has it's own current input and output stream and can be accessed via the standard Forth IO words and a general purpose wordset which acts upon current thread devices. (See Later) In addition Generic IO also supports a wordset which can use a nominated device directly. This second wordset follows the same naming convention as the current-thread wordset.
An instance of a Generic Driver is described by the following structure, the address of such a structure is called a SID (structure-identifier).
|
The function table is a list of execution tokens for words to perform various standard actions. Each action word will receive the SID to operate upon at the top of the data stack.
To be a "Generic Device" the vector table must hold valid entries for:
|
Devices that require additional functions may add these at the end of the table. If additional functions are added the first three must be as below. It is valid for these to perform no action except to return a zero ior.
|
The following definitions act upon the nominated input or output stream for the calling thread. Definitions declared with IPFUNC act upon the current input stream and definitions declared with OPFUNC act upon the current output stream.
struct gen-sid \ -- len
Define the generic I/O structure known as a SID. This
structure does not include any private data.
cell field gen-handle cell field gen-vector 0 field gen-private end-struct
OpenFnid OPFunc open-gen \ addr len attribs -- handle/sid ior
Perform the Generic IO "OPEN" action for current output device.
CloseFnid OPFunc close-gen \ -- ior
Perform the Generic IO "CLOSE" action for current output device.
ReadFnid IPFunc read-gen \ addr len -- ior
Perform the Generic IO "READ" action for current input device.
WriteFnid OPFunc write-gen \ addr len -- ior
Perform the Generic IO "WRITE" action for current output device.
KeyFnid IPFunc key-gen \ -- char
Perform the Generic IO "KEY" action for current input device.
This operation is identical to the Forth word KEY.
Key?Fnid IPFunc key?-gen \ -- flag
Perform the Generic IO "KEY?" action for current input device.
This operation is identical to the Forth word KEY?.
EKeyFnid IPFunc ekey-gen \ -- echar
Perform the Generic IO "EKEY" action for current input device.
This operation is identical to the Forth word EKEY.
EKey?Fnid IPFunc ekey?-gen \ -- flag
Perform the Generic IO "EKEY?" action for current input device.
This operation is identical to the Forth word EKEY?.
AcceptFnid IPFUnc accept-gen \ addr len -- len'
Perform the Generic IO "ACCEPT" action for current input device.
This operation is identical to the Forth word ACCEPT.
EmitFnid OPFunc emit-gen \ char --
Perform the Generic IO "EMIT" action for current output device.
This operation is identical to the Forth word EMIT.
Emit?Fnid OPFunc emit?-gen \ -- flag
Perform the Generic IO "EMIT?" action for current output device.
This operation is identical to the Forth word EMIT?.
TypeFnid OPFunc type-gen \ addr len --
Perform the Generic IO "TYPE" action for current output device.
This operation is identical to the Forth word TYPE.
CRFnid OPFunc cr-gen \ --
Perform the Generic IO "CR" action for current output device.
This operation is identical to the Forth word CR.
LFFnid OPFunc lf-gen \ --
Perform the Generic IO "LF" action for current output device.
FFFnid OPFunc ff-gen \ --
Perform the Generic IO "FF" action for current output device.
This operation is identical to the Forth word PAGE.
BSFnid OPFunc bs-gen \ --
Perform the Generic IO "BS" action for current output device.
BellFnid OPFunc bell-gen \ --
Perform the Generic IO "BELL" action for current output device.
SetposFnid OPFunc setpos-gen \ d mode -- ior ; x y mode -- ior
Perform the Generic IO "SETPOS" action for current output device.
GetposFnid OPFunc getpos-gen \ mode -- d ior ; mode -- x y ior
Perform the Generic IO "GETPOS" action for current output device.
IoctlFnid OPFunc ioctl-gen \ addr len fn# -- ior
Perform the Generic IO "IOCTL" action for current output device.
FlushOPFnid OPFunc FlushOP-gen \ -- ior
Perform the Generic IO "FLUSH" action for current output device.
ReadExFnid IPFunc ReadEx-gen \ addr len -- #read ior
Perform the Generic IO "READEX" action for current input device.
Generic IO allows you to perform an action on any device without changing the thread's current Input or Output Channel. All the definitions listed as xxx-GEN also have an equivalent definition called xxx-GIO which has as top of stack an additional parameter which is the SID of the nominated device.
OpenFnid GIOFunc open-gio \ addr len attribs sid -- handle/sid ior CloseFnid GIOFunc close-gio \ sid -- ior ReadFnid GIOFunc read-gio \ addr len sid -- ior WriteFnid GIOFunc write-gio \ addr len sid -- ior KeyFnid GIOFunc key-gio \ sid -- char Key?Fnid GIOFunc key?-gio \ sid -- flag EKeyFnid GIOFunc ekey-gio \ sid -- echar EKey?Fnid GIOFunc ekey?-gio \ sid -- flag AcceptFnid GIOFunc accept-gio \ addr len sid -- len' EmitFnid GIOFunc emit-gio \ char sid -- Emit?Fnid GIOFunc emit?-gio \ -- flag TypeFnid GIOFunc type-gio \ addr len sid -- CRFnid GIOFunc cr-gio \ sid -- LFFnid GIOFunc lf-gio \ sid -- FFFnid GIOFunc ff-gio \ sid -- BSFnid GIOFunc bs-gio \ sid -- BellFnid GIOFunc bell-gio \ sid -- SetposFnid GIOFunc setpos-gio \ d mode sid -- ior ; x y mode sid -- ior GetposFnid GIOFunc getpos-gio \ mode sid -- d ior ; mode -- x y ior IoctlFnid GIOFunc ioctl-gio \ addr len fn# sid -- ior FlushOPFnid GIOFunc FlushOP-gio \ sid -- ior ReadExFnid GIOFunc ReadEx-gio \ addr len sid -- #read ior RFUFnid GIOFunc RFU-gio \ sid -- InitFnid GIOFunc init-gio \ addr len sid -- ior TermFnid GIOFunc term-gio \ sid -- ior ConfigFnid GIOFunc config-gio \ sid -- ior
The following standard Forth definitions are already vectored through their generic IO equivalents. The SID device handle used comes from the USER variables OP-HANDLE and IP-HANDLE.
|
Also affected are any I/O words within the ANS Core wordset that use these primitives, such as:
|
The following IO words are defined along with Generic IO and will use the standard Generic IO vectors.
: page \ --
Performs a FORM-FEED operation. The effect of this differs from
device to device. Binary devices will simply output the #12
character, screen devices will clear the screen and printer devices
will move on to the next page.
: cls \ --
An alias for PAGE which reads more clearly when using a screen
based device.
: at-xy \ x y --
The ANS cursor relocation definition. Attempt to move the cursor
to relative position X Y. The actual translation of this varies
from device to device since it is implemented with the SETPOS
generic IO vector.
: SetIO \ sid --
Set the given device as the current I/O device.
: [IO \ -- ; R: -- ip-handle op-handle
Used inside a colon definition only to preserve the
the current I/O devices before switching them temporarily.
Usually used in the form:
|
: IO] \ -- ; R: ip-handle op-handle --
Used inside a colon definition only to restore the
the current I/O devices after switching them temporarily.
See [IO for more details.
create szSID \ -- addr ; used as a property string
Within a winproc controlling a device, it is often useful
to be able to reference the SID of the device. This is best
done by using the SetProp Windows call to set a property for the
Window - see the STUDIO directories for examples. MPE code uses the
property string "SID" for this, and szSID is the address of the
zero terminated property string.
The following Generic IO device implementations can all be found in the supplied source library folder LIB\GENIO.
This Generic IO Device uses blocks of memory for input and/or output. The source code is in LIB\GENIO\Buffer.fth. This is not a circular buffer system. After a buffer has been used, the read and write pointers are not reset. You must reset the buffer pointers using the IOCTL functions.
As of VFX Forth build 2380, this code has been overhauled. If this causes you problems, the file BUFFER.old.FTH contains the previous (but now unsupported) version. The major changes are:
Note that the ACCEPT operation does not echo. It is designed for extracting lines from saved input.
In order to create a device use the TEXTBUFF: definition given later. TEXTBUFF: is compatible with ProForth 2.
When opening a memory device the parameters to OPEN-GEN have the following meaning:
ADDR |
Address of memory to use as buffer or ignored if dynamic allocation is required. |
LEN |
The maximum length of the memory image. |
ATTRIBS |
When zero the ADDR parameter is ignored and LEN bytes of memory are allocated from the heap. |
struct textbuff-sid \ -- len
Defines the length of a SID for a text buffer device.
gen-sid + \ handle=buffer, reuse field names of GEN-SID int tb-len \ length of buffer int tb-attribs \ attributes int tb-wr \ address to write to, set by SETPOS, WRITE int tb-rd \ address to read from set by SETPOS, READ end-struct
: ff-tb \ sid -- ; page/cls on display devices
This word is run by PAGE, CLS and FF-GEN. It resets
(empties) the buffer.
: setpos-tb \ x y mode sid -- ior
This word is run by SETPOS-GEN. Mode controls the x and y
input values as follows.
0 |
x = #bytes written, y is ignored |
-1 |
x=col, y=line for next character to be written |
-2 |
x = #bytes read, y is ignored |
-3 |
x=col, y=line for next character to be read |
: getpos-tb \ mode sid -- x y ior
This word is run by GETPOS-GEN. Mode controls the x and y
return values as follows.
0 |
x = #bytes written, y = 0 |
-1 |
x,y for next character to be written |
-2 |
x = #bytes read, y = 0 |
-3 |
x,y for next character to be read |
-4 |
x = addr, y = len of unread data |
-5 |
x = base address, y = size of data area |
: ioctl-tb \ addr len fn sid -- ior
This word is run by IOCTL-GEN and IOCTL-GIO.
Fn controls the meaning of addr, len and the
ior return value as follows:
0 |
Get buffer address: addr=0, len=0, ior=addr. |
-1 |
Set write pointer: addr=0, len=offset, ior=0. |
-2 |
Get write pointer: addr=0, len=0, ior=offset. |
-3 |
Set read pointer: addr=0, len=offset, ior=0. |
-4 |
Get read pointer: addr=0, len=0, ior=offset. |
: initTextBuffSid \ addr --
Initialise a previously allocated SID for
a text buffer to the default values.
: textbuff: \ "name" -- ; Exec: -- sid
Create a memory buffer called name.
: SizedTextBuff \ size -- sid|0
Allocates and opens a SID with a buffer of size size
bytes, and returns the SID on success or 0 on failure.
: AllocTextBuff \ -- sid|0
Allocates and opens a SID with a default 16kb text buffer
and returns the SID on success or 0 on failure.
: FreeTextBuff \ sid --
Closes the SID and frees memory allocated by AllocTextBuff
or SizedTextBuff.
This Generic IO Device operates on a disk file for input and/or output. The source code can be found in Lib\Genio\File.fth. Neither input nor output are buffered, so that this device should not be used when speed is required.
In order to create a device use the FILEDEV: definition given later. FILEDEV: is compatible with ProForth 2.
When opening a file device the parameters to OPEN-GEN have the following meaning:
|
The ReadEx function is now implemented.
struct /FileDev \ -- len
Returns the size of the sid structure for a file device.
: initFileDev \ sid --
Initialise the sid for a file device. Mostly used when
the structure has been allocated from the heap.
: filedev: \ "name" -- ; Exec: -- sid
Create a File based Generic IO device in the dictionary.
This Generic IO Device is used as a bit bucket for unwanted output. When used as input KEY? is always false and and read will never return.
In order to create a device use the NULLDEV: definition given later.
When opening a null device the parameters to OPEN-GEN have no meaning.
: nulldev: \ "name" -- ; Exec: -- sid
Create a NULL Generic IO device in the dictionary.
This Generic IO Device operates on a serial port for input and/or output.
In order to create a device use the SERDEV: definition given later.
When opening a serial device the parameters to OPEN-GEN and open-gio have the following meaning:
|
The configuration string takes the form:
|
for Serial Port 0 at 9600 baud, 8 data bits, no parity, 1 stop bit. Only the device name is mandatory. Words and IOCTL functions are available to modify the port setting later. Split baud rates are not supported - you will have to set these yourself. If only the device name is given, the line will be set to 115200 baud, N81 in raw mode. Additional configuration comands are documented later in this section, e.g. for setting the DTR and RTS lines. The configuration string is processed with BASE set to DECIMAL. USB serial devices are discussed at the end of this section.
When using USB serial devices, the name used varies according to your distribution. The most common names appear to be:
/dev/ttyUSBx
/dev/ttyACMx
struct /serial-sid \ -- len
Defines the SID of a serial device.
struct /termios \ -- size
A structure corresponding to the termios structure used by
tcgetattr and tcsetattr.
4 field termios.c_iflag \ input mode flags 4 field termios.c_oflag \ output mode flags 4 field termios.c_cflag \ control mode flags 4 field termios.c_lflag \ local mode flags 1 field termios.c_line \ line discipline NCCS field termios.c_cc \ control characters 3 field termios.padding \ C aligns everything to 32-bits 4 field termios.c_ispeed \ input speed 4 field termios.c_ospeed \ output speed end-struct
: setBaud \ hertz fildes -- ior ; 0=success
Set the baud rate for an opened file descriptor.
: setParity \ char fildes -- ior ; 0=success
Set the parity for an opened file descriptor.
The character must be one of N,E,O.
: setData \ u fildes -- ior ; 0=success
Set the data size for an opened file descriptor.
The data size u must be one of 5,6,7,8.
: setStop \ u fildes -- ior ; 0=success
Set the number of stop bits for an opened file descriptor.
The value of *i{u} must be one of 1 or 2.
: setDTR \ flag fildes -- ior ; 0=success
Set DTR inactive if flag is zero, otherwise set it active.
: setRTS \ flag fildes -- ior ; 0=success
Set RTS inactive if flag is zero, otherwise set it active.
: setUnix \ sid --
Set the line to have Unix line handling.
: setDOS \ sid --
Set the line to have Windows/DOS line handling.
' setBaud SerCfg: baud \ sid ior baud -- sid ior'
Used in the configuration string to set the baud rate, e.g.
9600 baud
' setData SerCfg: data \ sid ior u -- sid ior'
Used in the configuration string to set the number of data bits, e.g.
8 data
' setParity SerCfg: parity \ sid ior u -- sid ior'
Used in the configuration string to set parity, where u
is one of the characters N, E, or O. Constants are defined, e.g.
no parity
even parity
odd parity
' setStop SerCfg: stop \ sid ior u -- sid ior'
Used in the configuration string to set the number of stop bits, e.g.
1 stop
2 stop
: 8n1 \ sid ior -- sid ior'
Used in the configuration string to set the most common case,
8 data bits, no parity, 1 stop bit, e.g.
8n1
' setDTR SerCfg: DTR \ sid ior flag -- sid ior'
Used in the configuration string to set the DTR line, where
flag is non-zero for active and zero for inactive.
1 DTR
' setRTS SerCfg: RTS \ sid ior flag -- sid ior'
Used in the configuration string to set the RTS line, where
flag is non-zero for active and zero for inactive.
1 RTS
: Unix \ sid ior -- sid ior
Used in the configuration string.
Set the serial line to use LF as the line terminator sequence.
CR characters will be ignored by ACCEPT.
: DOS \ sid ior -- sid ior
Used in the configuration string.
Set the serial line to use CR/LF as the line terminator sequence.
This can also be used for Macs before OS X, but LF characters will be
ignored by ACCEPT.
: open-Ser \ addr len attribs sid -- sid ior
The string caddr/len is split into two. The space delimited
left hand side is used as the device, e.g. "/dev/ttyS4" which is
opened in raw mode. A default set up of 115200 baud, n81 and Unix
line handling is applied, and then the right hand side of the string
is parsed. Only the words documented as available in the serial
configuration string may be used.
: ioctl-ser \ addr len fn sid -- ior
The serial ioctl functions provide control over the
serial line outputs and Unix/DOS mode handling. Where
parameters are shown as ??, their value is ignored.
|
: initSerDev \ sid --
Initialise the sid for a serial device.
: serdev: \ "name" -- ; Exec: -- sid
Create a Serial Port based Generic IO device in the dictionary.
serdev: <name>
When using USB serial devices, the name used varies according to your distribution. The most common names appear to be:
/dev/ttyUSBx
/dev/ttyACMx
There are several methods of finding USB serial ports. The simplest seems to be to unplug the device, then reconnect it, then type the following incantation:
dmesg | grep tty
where you must have root access. On many systems, e.g. Ubuntu
sudo dmesg | grep tty
is required. The last few lines should then tell you which USB serial port, e.g. /dev/ttyUSB0 was selected for your device. If the last tells you that the device is now disconnected, it is probably because of the "brltty bug". Unless you need the Braille TTY access, remove the package brltty. Repeat:
sudo dmesg | grep tty
to check that device remains connected. Some forums suggest that you may also need to create the /dev/ttyUSBx entries. Do this with:
sudo mknod /dev/ttyUSB0 c 188 0
sudo mknod /dev/ttyUSB1 c 188 1
sudo mknod /dev/ttyUSB2 c 188 2
The most widely used Linux equivalent to Windows' HyperTerm appears to be minicom. It isn't pretty, but it works and is easy to use. There are plenty of others, including GUI ones, but minicom is the one we come back to as it is available for nearly all distributions.
The XTERM Generic IO Device controls an xterm or equivalent device. Facilities are provided for cursor positioning, setting the foreground and background colours, line editing and line history. Cursor positioning uses ANSI escape sequences. Any terminal emulator which supports these sequences, e.g. in ANSI or VT100 mode, should work with this code. A good introduction to ANSI escape sequences may be found at http://en.wikipedia.org/wiki/ANSI_escape_code.
In order to create a device use the XTERM: definition given later. When opening a file device the parameters to OPEN-GEN are unused. For compatibility with future versions please set them to -1, e.g.
-1 -1 -1 <sid> open-gio
The IOCTL function has the following action
You can set the text foreground and background colours:
<fcolour> <bcolour> #10 <sid> IOCTL-GIO drop
where colour is a colour in the XTERM format. If a colour is set to -1 the existing colour is left unchanged. For XTERMs and VT100/220 compatible terminals, the following colours are standard.
|
Similarly, terminal positioning control uses ANSI (VT100 and VT220) sequences. If you are connecting using Telnet or other remote access techniques (or even a real terminal), set it to ANSI, VT100 or VT220 compatibility mode.
Line editing is performed using the cursor keys, BS (<- or ^H) to delete before the cursor, and the DELETE keys to delete after the cursor. You can also use ^W and ^R for cursor movement. You can recall lines using the up (previous) and down (next) cursor keys. Lines can be edited after recall. You can also use ^E and ^D instead of the up and down keys. Note that Linux implementations are not consistent in the codes returned by keys such as BS and DELETE.
Unlike other devices, an XTERM uses three handles that correspond to stdin, stdout and stderr. By default these are handles 0, 1 and 2 respectively. If you wish to use different handles, you are responsible for their management. Use these handles by setting them into the /xterm-sid structure below. By default, the open operation uses the preset handles, which are not closed by the close operation.
The source code can be found in the file Lib/Lin32/Genio/xterm.fth, which is compiled during the second stage build. If you change this file, perform a second stage build when you wish to commit to using the changed file.
struct /xterm-sid \ -- len
Defines the SID of an xterm console device.
gen-sid + \ reuse field names of GEN-SID int xs.hIn \ input handle int xs.hOut \ output handle int xs.hErr \ error handle int xs.flags \ control flags \ bit 0 - QUIT control \ bit 1 - rfu \ bit 2 - 1=maintain history, 0=none \ bit 3 - 1=history in system ini file int xs.hiBuff \ address of 64k history buffer int xs.hiIndex \ current history line# int xs.hiLowIndex \ lowest history line# int xs.hiSection \ pointer to INI file section name end-struct
: initXtermSid \ addr --
Initialise a /xterm structure at addr.
: xterm: \ -- ; -- sid ; XTERM: <name>
Create a new terminal device.
xterm: xconsole \ -- addr
VFX Forth console.
: init-xcon \ --
Set up to use the xconsole device. Performed at start up
and compilation.
: term-xcon \ --
Shut down the xconsole device. Performed at shut down.
This Generic IO Device operates on a Linux socket for input or output. General socket programming words are made available in the Forth vocabulary.
In order to create a device use the SOCKDEV: definition given later.
When opening a socket device the parameters to OPEN-GEN have the following meaning:
|
Many of the Linux socket functions are defined. Note that the accept function is accessed by SACCEPT to avoid a name clash with the ANS word ACCEPT.
AliasedExtern: saccept int OSCALL accept( int, void *, int *);
Because the sockets accept function has a name clash
with the Forth word ACCEPT it is made available as
SACCEPT.
TCP/IP protocols usually send data in what is called network order, which just means most-significant byte first. In memory, numbers are thus stored in big-endian form. The following words provide memory operations for this. These functions have to be capable of fetching 32 bit cells from 16 bit aligned addresses, not just from 32 bit aligned addresses.
: w@(n) \ addr -- u16
Network order 16 bit fetch.
: w!(n) \ u16 addr --
Network order 16 bit store.
: @(n) \ addr -- u32
Network order 32 bit fetch.
: !(n) \ u32 addr --
Network order 32 bit store.
: w,(n) \ w --
Network order W,
: ,(n) \ x --
Network order version of , (comma).
These words are available in the FORTH vocabulary for general socket programming.
max_path buffer: IPname \ -- addr
Holds the local computer's name as a zero terminated string.
2 cells buffer: IPaddress \ -- addr
Holds the local computer's IP address as a four byte
IPv4 number in network order. A value of 0 indicates
that the address is unknown.
: findLinkIP \ caddr len addr --
Find the IP address assigned to the given link, e.g. eth0,
and place the link address at addr.
#256 buffer: NetIF$ \ -- addr
Holds the name of the default network device, usually eth0.
This is a counted string. The default string is "eth0". Note that
recent versions of Fedora use "emx" for Ethernet ports.
: InitLinuxSockets \ --
Initialise sockets; called by the cold chain and during
compilation.
: ?sockerr \ serr -- ior
If serr is -1, the actual errno value is
returned, otherwise zero is returned.
: writesock \ c-addr u hsock -- len ior
Write the buffer to a socket, returning the length actually
written and 0 on success, otherwise returning SOCKET_ERROR
and the Linux error code.
: readsock \ c-addr u hsock -- len ior
Read into a buffer from a socket, returning the length actually
read and 0 on success, otherwise returning SOCKET_ERROR
and the Linux error code.
: pollsock \ hsock -- #bytes|-1
Poll a socket and return the number of bytes available to be
read.
: sockReadLen \ caddr len hsock -- ior
Read len bytes of input from a socket to the buffer
at caddr, returning ior=0 if all bytes have been read.
This is a blocking function which will not return until
len bytes have been read or an error occurs.
: bindTo \ hs af port ipaddr -- res
A non-BSD function that binds a socket to the given set of
address family (af, usually AF_INET), port (port) and
IP address (ipaddr). The returned result (res) is 0 for
success, otherwise -1. See BIND.
: (Connect) \ caddr u port# socket -- socket ior
Attempt to connect to a server. The socket has already been
created in the appropriate mode.
Caddr/u describes the server address either as a name
or an IPaddress string and port# is the requested port.
If u is zero, caddr is treated as a 32 bit number
representing an IPv4 address.
On success, the socket and zero are returned, otherwise
SOCKET_ERROR and the Linux error code are returned.
: TCPConnect \ c-addr u port# -- socket ior
Attempt to create a TCP socket and connect to a server.
*/i{Caddr/u} describes the server address either as a name
or an IPaddress string and port# is the requested port.
If u is zero, caddr is treated as a 32 bit number
representing an IPv4 address.
On success, the socket and zero are returned, otherwise
SOCKET_ERROR and the Linux error code are returned.
: UDPConnect \ c-addr u port# -- socket ior
Attempt to create a TCP socket and connect to a server.
*/i{Caddr/u} describes the server address either as a name
or an IPaddress string and port# is the requested port.
If u is zero, caddr is treated as a 32 bit number
representing an IPv4 address.
On success, the socket and zero are returned, otherwise
SOCKET_ERROR and the Linux error code are returned.
A socket device is created by SOCKETDEV: <name>.
|
When opening a socket device the parameters to OPEN-GEN have the following meaning:
|
The following constants define the modes used to open socket:
SD_SOCKET SD_CONNECT SD_LISTEN
struct /SDopen \ -- len
The structure required for opening a socket Generic I/O
device. Not all fields are used by all modes.
The */fo{/SDopen} structure is defined as follows:
int SDO.af \ address family, usually AF_INET int SDO.type \ socket type, e.g. SOCK_STREAM int SDO.protocol \ IPPROTO_TCP ... sockaddr_in field SDO.sa \ SOCKADDR_IN structure end-struct
The SDO.af field is AF_INET for all TCP/IP operations. The SDO.TYPE field is SOCK_STREAM for TCP or SOCK_DGRAM for UDP. The SDO.protocol field is IPPROTO_TCP for TCP or IPPROTO_UDP for UDP. The SDO.sa field is a SOCKADDR or SOCKADDR_IN structure (same sizes), defined as follows:
|
Note that only the first field is stored in native (little-endian for Intel i32) order. The other fields contain data in network (big-endian) form.
To open a socket, fill in a /SDopen structure, and call OPEN-GEN. The following example connects to a server.
|
This will return the sid again and a result code (0=success).
The socket can then be used as the current I/O device.
|
struct /socket-sid \ -- len
Defines the SID of a socket device.
: sd-flush \ sid -- ior
Output to the socket is buffered to avoid running out
of Linux buffers. Call FLUSHOP-GEN ( -- ior ) or
KEY? to transmit the buffered output.
: sd-close \ sid -- ior
The close function flushes pending output, closes the
event object if used, performs shutdown with how=1, and
closes the socket.
: sd-type \ caddr len sid --
Buffered output.
: sd-write \ caddr len sid -- ior
Buffered output.
: sd-emit \ char sid --
Buffered output.
: sd-cr \ sid --
Buffered output.
: sd-key? \ sid -- #bytes|-1
The KEY? primitive for a socket returns the number
of bytes available. If an error occurs, -1 is returned
and KEY returns CR (ASCII code 13) so that KEY
and ACCEPT do not block. Use the IOCTL function
if you want to test for a specific error return code.
Any buffered output is sent first.
: sd-key \ sid -- char
If an error occurs, CR (ASCII code 13) is returned.
Any buffered output is sent first.
: sd-ioctl ( addr len fn# sid -- ior )
The IOCTL primitive for a socket is used to get or set
socket status. The following functions
are supported by IOCTL-GEN for sockets.
addr 0 #10 sid -- ior
Place the number of bytes available to be read by recv at addr.
0 0 #11 sid -- ior
Set the socket to notify when closed. N.B. This is not currently implemented
0 0 #12 sid -- ior
Ior is returned non-zero if the socket has been closed. Ior is is returned false (zero) if the socket is still open or notification has not been requested. The socket must be open.
state FD_xxx #20 sid -- ior
Set the created socket to notify on the FD_xxx flags. If state is zero the socket is set/restored to blocking mode otherwise it is set to blocking mode. N.B. This is not currently implemented
state FD_xxx #21 sid -- flags
Flags contains FD_xxx bits which indicate what events have occurred from the set rquested by the call above. Flags is is returned false (zero) if no events have been reported or notification has not been requested. The socket must be open. N.B. This is not currently implemented
0 0 #22 sid -- ior
Reset any notifications returned by function 21 above. Ior is zero for success or the Linux error code. N.B. This is not currently implemented
0 0 #23 sid -- ior
Stop notification. Ior is zero for success or the Linux error code. N.B. This is not currently implemented
0 flags #30 sid -- 0 ; set the device flags
0 0 #31 sid -- flags ; get the device flags
The device flags control how some operations behave. Flags is a set of bits as follows:
|
: InitSD \ addr --
Initialise the data required for a socket device at addr.
: SocketDev: \ "name" -- ; Exec: -- sid
Create a new socket device called name in the dictionary.