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).
CELL Device Handle (interpretation depends on device),
CELL Pointer to function Table (see below),
???? Device Private Data.
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:
Index Name Description
0 OPEN Open/Initialise a device.
1 CLOSE Close a device.
2 READ Read to a block of memory.
3 WRITE Write a specified block of memory.
4 KEY Perform an action equivalent to Forths
KEY definition, (i.e. a blocking character
read.)
5 KEY? Perform an action equivalent to Forths
KEY?, (i.e. any-input-pending?)
6 EKEY Supports EKEY
7 EKEY? Supports EKEY?
8 ACCEPT Added to support FORTH definition of the
same name. Read a character stream into
a memory buffer.
9 EMIT Write a single character to a stream.
10 EMIT? Check that EMIT can work.
11 TYPE As with Forths TYPE. Write a string of
characters to a device.
12 CR Perform nearest equivalent action of
"carriage return" on the device.
13 LR As with CR except for "line-feed"
14 FF As with CR except for "form-feed"
15 BS As with CR except for "backspace"
16 BELL Where applicable to the device emit an
audible beep.
17 SETPOS Set current position. May reflect screen
cursor/file position etc.
18 GETPOS Read current position.
19 IOCTL Perform a special function. Each device
may or may not support various IOCTL
codes. The currently assigned function
codes used by MPE are documented later.
20 FLUSHOP Flush any pending output for device.
21 RFU/READEX As READ with additional return of count.
Not available on all devices.
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.
22 initialise device addr len sid -- ior
23 terminate device sid -- ior
24 configure device sid -- ior ; produces a dialog
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
.
ACCEPT KEY KEY? EKEY EKEY? EMIT EMIT? TYPE CR
Also affected are any I/O words within the ANS Core wordset that use these primitives, such as:
. .S SEE U. ) $. F. DUMP EXPECT QUERY
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 SomeDev SetIO
...
io]
: 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:
KEY
operation (and hence ACCEPT
blocks if no
data is available.KEY?
operation returns the number of unread bytes.EMIT?
operation returns the number of unwritten bytes
in the buffer..ReadEx
function is implemented.Textbuff-sid
GENIO structure has been documented.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. A buffered version is available in Lib\Genio\FileBuff.fth.
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:
ADDR Address of string for filename.
LEN Length of string at ADDR.
ATTRIBS Open flags. These match the ANS r/o r/w etc.
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:
ADDR Address of configuration string.
LEN Length of string at ADDR.
ATTRIBS file fam, usually R/W.
The configuration string takes the form:
/dev/ttyS0 9600 baud no parity 8 data 1 stop
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.
A good description of Mac OS X serial ports is at:
http://pbxbook.com/other/mac-tty.html
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. 32 bit specific.
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.
\ ?? ?? #50 sid -- ior ; Unix mode, LF
\ ?? ?? #51 sid -- ior ; DOS/Windows mode, CR/LF
\ ?? ?? #52 sid -- ior ; Mac mode, CR
\ ?? ?? #53 sid -- ior ; native mode, LF for Unices
\ caddr len #55 sid -- ior ; set string for CR.
\ linechar ignchar #56 sid -- ior ; set input chars for ACCEPT
\ ?? flag #60 sid -- ior ; set DTR, nz=active
\ ?? flag #61 sid -- ior ; set RTS, nz=active
: 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 the function. The names are:
/dev/tty.usb??????
/dev/cu.usb?????
You can list them at a Terminal prompt with
ls /dev/tty*
ls /dev/cu*
The /dev/tty* devices are for modems waiting for a call into the OS X machine. It is assumed that the DCD line is active. Hence these are of little use for the three wire connections (RX, TX, Gnd) typically used to connect to embedded systems.
The /dev/cu* devices are much better suited for connecting out (calling up) to other systems.
The ones listed here are just ones recommended by others.
screen - on every Mac. For hardcore Unix buffs.
screen /dev/cu.usbserial 19200
http://hints.macworld.com/article.php?story=20061109133825654
Coolterm - GUI app.
http://freeware.the-meiers.org
goSerial - GUI app.
http://www.furrysoft.de/?page=goserial
The most widely used equivalent to Windows' HyperTerm appears to be minicom. It isn't pretty, but it works and is easy to use.
http://pbxbook.com/other/mac-tty.html#minicom
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 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.
0 constant Black
1 constant Red
2 constant Green
3 constant Yellow
4 constant Blue
5 constant Magenta
6 constant Cyan
7 constant White
: +bright \ color -- color'
\ Convert a colour into its bright version.
#60 +
;
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/Osx32/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 Mac OS X 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:
ADDR Address of configuration data structure
LEN connection name zstring
ATTRIBS 0=socket, 1=connect, 2=listen.
Many of the BSD 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.
: findCurrIP \ addr --
Place the IP address of the current network at addr.
This word assumes that only one link is active at a time.
The assumption is usually true.
#256 buffer: NetIF$ \ -- addr
Holds the name of the default network device, usually en0.
This is a counted string.
: InitOSXSockets \ --
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>
.
SocketDev: SDsid \ -- addr
When opening a socket device the parameters to OPEN-GEN
have the following meaning:
ADDR Address of an /SDopen data structure.
LEN Address of Windows IP address zstring
If 0, /SDopen contains the IP adress.
ATTRIBS mode: 0=socket, 1=connect,
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:
struct sockaddr_in \ -- len
2 field sin_family \ address family, usually AF_INET
2 field sin_port \ port ; in network order
4 field sin_addr \ IP address ; in network order
8 field sin_reserved \ RFU
end-struct
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.
SocketDev: SDsid \ -- addr ; device
create zserver$ \ -- z$addr ; server name
z", www.mpeforth.com"
create MySDopen \ -- addr
AF_INET , \ internet family
SOCK_STREAM , \ connection type
IPPROTO_TCP , \ TCP protocol
AF_INET w, \ server family, start of SOCKADDR_IN
#80 w,(n) \ server port
#0 ,(n) \ server IP address if known
8 allot&erase \ reserved
...
MySDopen zserver$ SD_connect SDsid open-gio
This will return the sid again and a result code (0=success).
The socket can then be used as the current I/O device.
: UseSDsid \ --
SDsid dup op-handle ! ip-handle !
;
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:
Bit 0 - set to stop echoing during ACCEPT
.
: 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.