Home

GEONius.com
2-Apr-2011
E-mail

Forth-Inspired Network Commands (FINC)

Introduction
The Software
Licensing
FINC on a Nintendo DS
Network-Lookup Words
Socket Words
TCP/IP Words
LF-Terminated Communications Words
I/O Event Dispatcher Words
   
Forth, Meet Scheme! Directory Scanning Words
Timeval Words
Miscellaneous Words

 
[Ficl Logo]

FINC is a set of C networking extensions to John Sadler's Ficl (Forth Inspired Command Language) interpreter. These are the first extensions I wrote and I'm working on becoming a more experienced Forth programmer. (I've read about Forth over the years and I once bought a Forth cartridge for my Commodore 64 [HES 64 Forth?] - but I immediately returned it because the instruction booklet was missing!)

Caveats about Ficl:

Still, I like Ficl because it's another example of Tiny Code. The FTH Forth Scripting Language embeds its own, heavily-modified copy of Ficl that fixes some of the problems above.

libfinc.a - Forth-Inspired Network Commands (library)

This library has the actual FINC extensions and can be linked with any Ficl-based program (along with the CSOFT library mentioned below). Sets of words can be left in or left out by calling or not calling the functions that register the words:

    #include  "finc.h"			/* Forth-Inspired Network Commands. */

    ...

    /* Initialize FICL. */

        ficlSystem  *sys = ficlSystemCreate (NULL) ;

    /* Compile extra words. */

        ficlSystemCompileExtras (sys) ;

    /* Compile FINC extensions. */

        buildWordsDRS (sys) ;
        buildWordsLFN (sys) ;
        buildWordsMISC (sys) ;
        buildWordsNET (sys) ;
        buildWordsIOX (sys) ;
        buildWordsSKT (sys) ;
        buildWordsTCP (sys) ;

        ...

finc - Forth-Inspired Network Commands (executable)

finc (description and command-line invocation) is the basic stand-alone ficl intepreter with network extensions.

nicl - Network Ficl Server (executable)

nicl (description and command-line invocation) is a network server that provides each client with its own Ficl virtual machine with network extensions.

echod - an Echo Daemon in Forth

ECHOD (source) is an example of an event-loop-based network server that simultaneously handles multiple clients. Since this was my first "big" Forth program (i.e., a small program), the in-line comments are mostly stack descriptions to help me keep track of what was on the stack and where. The IOX-ONIO command, in particular, having 5 arguments, required some major "stackrobatics"! Refactoring, if not revisiting, is definitely in order. Still, the program shows the basic structure for writing an event-loop-based network server.

httpd - a Web Server in Forth

HTTPD (source) and UTILITY (source) implement a web server that simultaneously serves pages to multiple clients. The server is currently in use on my home LAN serving pages from a local copy of my web site. As I expected, the web server also runs on a Nintendo DS, serving out web pages over wireless connections! (Instructions for installing and running the web server on a DS.)

 

The Software

Ficl

Ficl is downloaded from its SourceForge website. There are two Makefiles, "Makefile.ansi" and "Makefile.linux". I've had no trouble building Ficl with the Linux Makefile on Unix-based systems. I manually copy the executable, the header files, and the libraries to the /usr/local directory tree. (Don't forget to copy the ficlplatform/*.h header files to /usr/local/include/ficl/ficlplatform/!) See the Nintendo DS installation instructions for information on building Ficl for the DS.

The Ficl distribution also includes the Microsoft Visual C++ 6.0 workspace and project files. If you're using Visual Studio, it will automatically convert the files to Visual Studio's format. Ficl offers a number of options for building Ficl in Windows; I use the single-threaded debug mode. As a result, the Ficl library that FINC links to is "\ficl\lib\debug\singlethreaded\ficl.lib". (The header files are in the top-level "\ficl\" directory.)

FINC

The source code for FINC (the library and the applications) is included in my CSOFT distribution. Building the software is a simple matter:

  1. Download csoft.tgz or csoft.zip, whichever archive type you feel most comfortable with. Extract the archive contents to your desired directory.

  2. Build the General Purpose Library (libgpl):


  3. Build FINC:

In all cases, you might need to modify FINC's Makefiles or Visual C++/Studio project files to point to where the Ficl header files and libraries are found. The UNIX Makefiles assume the header files are in "/usr/local/include/ficl/" and the library is in "/usr/local/lib/". The Windows project files assume the Ficl header files are found in a Ficl source directory at the same level as the csoft directory; the Ficl library is "\ficl\lib\debug\singlethreaded\ficl.lib".

 

Licensing

The CSOFT library and the FINC library and application are covered by the MIT License. (Also see the Ficl License.) Basically, you are free to use the software however you see fit, in commercial or non-commerical applications. I only ask that, if your time permits, you report any bugs or portability problems you encounter. Suggestions for improvements and enhancements are welcome, but I do not guarantee I will act upon them.

 

The Network-Lookup Word Set


Introduction

The NET word set defines words for translating IP addresses, host names, and service ports:

"host" NET-ADDR
address dotted? NET-HOST
"service" udp? NET-PORT

Source: words_net.c


Glossary


Network-Lookup words


NET-ADDR
NET

	( c-addr u1 -- u2 )

Lookup the host name represented by c-addr,u1 and return its IP address in network-byte-order in u2.


NET-HOST
NET

	( u1 f -- c-addr u2 )

Lookup the IP address u1 and return the corresponding host name string as c-addr,u2. If the flag f is true, return the address in dotted IP format. The string is NUL-terminated and stored internally; it should be used or duplicated before calling NET-HOST again.


NET-PORT
NET

	( c-addr u f -- i )

Lookup the service name c-addr,u in the network services database (the "/etc/services" file) and return the corresponding port number. If flag f is true, the "udp" port is returned; otherwise, the "tcp" port is returned.

 

The Socket Word Set


Introduction

The SKT word set defines words for monitoring sockets:

SKT-CLEANUP
fd SKT-PEER
fd SKT-PORT
fd SKT-READABLE?
fd recvSize sendSize SKT-SETBUF
SKT-STARTUP
fd SKT-UP?
fd SKT-WRITEABLE?

Source: words_skt.c


Glossary


Socket words


SKT-CLEANUP
SKT

	( -- ior )

Shut down the socket library; ior returns an error indication.


SKT-PEER
SKT

	( fd -- u )

Determine the host at the other end of network socket connection fd and returns its IP address in u in network-byte-order.


SKT-PORT
SKT

	( fd -- n )

Get the number of the port to which socket fd is bound; -1 is returned in the event of an error.


SKT-READABLE?
SKT

	( fd -- f )

Check if data is waiting to be read from socket fd; return true if the socket is readable and false otherwise.


SKT-SETBUF
SKT

	( fd n1 n2 -- ior )

Set the size of socket fd's receive buffer to n1 bytes and the size of its send buffer to n2 bytes; ior returns an error indication. If a buffer size is less than zero, the respective buffer retains its current size.


SKT-STARTUP
SKT

	( -- ior )

Start up the socket library; ior returns an error indication.


SKT-UP?
SKT

	( fd -- f )

Check socket fd to see if its network connection is still up; return true if the connection is up and false otherwise.


SKT-WRITEABLE?
SKT

	( fd -- f )

Check if data can be written to socket fd; return true if the socket is writeable and false otherwise.

 

The TCP/IP Word Set


Introduction

The TCP word set defines words for establishing and communicating over TCP/IP network connections:

endpoint timeout TCP-ANSWER
"service[@host]" noWait? TCP-CALL
endpoint timeout destroy? TCP-COMPLETE
value TCP-DEBUG
endpoint TCP-DESTROY
endpoint TCP-FD
port backlog TCP-LISTEN
endpoint TCP-NAME
endpoint TCP-PENDING?
buffer length endpoint timeout TCP-READ
endpoint TCP-READABLE?
endpoint TCP-UP?
buffer length endpoint timeout TCP-WRITE
endpoint TCP-WRITEABLE?

Source: words_tcp.c


Glossary


TCP/IP words


TCP-ANSWER
TCP

	( ep1 r -- ep2 0 | ior )

Wait at most r seconds for a connection request to be received on listening endpoint ep1. If a request is received, accept the request. The operating system automatically creates a new endpoint ep2 (the "data" endpoint) through which the server can talk to the client. The I/O result indicates the status of answering the connection request.


TCP-CALL
TCP

	( c-addr u f -- ep 0 | ior )

Request a network connection to the server at c-addr/u ("service[@host]"). If the no-wait flag f is false, TCP-CALL waits until the connection is established (or refused) before returning. If the no-wait flag f is false, TCP-CALL waits until the connection is established (or refused) before returning. If the no-wait flag f is true, TCP-CALL initiates the connection attempt and returns immediately; the application should subsequently invoke TCP-COMPLETE to complete the connection. In all cases, the data endpoint is returned on the stack, along with the I/O result of the connection attempt.


TCP-COMPLETE
TCP

	( ep r f -- ior )

Wait for an asynchronous, network connection attempt to complete. Invoking TCP-CALL in no-wait mode initiates an attempt to connect to a network server. At some later time, the application must call TCP-COMPLETE to complete the connection attempt (if it is fated to complete).

Timeout r specifies the maximum amount of time (in seconds) that the caller wishes to wait for the call to complete. A negative timeout (e.g., -1E0) causes an infinite wait; a zero timeout (0E0) causes an immediate return if the connection is not yet established.

If the connection attempt times out or otherwise fails and flag f is true, TCP-COMPLETE will automatically destroy the endpoint. This mode is useful when the application plans to make a single go/no-go call to TCP-COMPLETE.

If, under the same circumstances, flag f is false, TCP-COMPLETE will NOT destroy the endpoint; the application is responsible for executing TCP-DESTROY explicitly. This mode is useful when the application plans to periodically call TCP-COMPLETE (perhaps with a timeout of 0E0) until the connection is successfully established.

In all cases, the I/O result is returned on the stack: 0 if the connection was established, EWOULDBLOCK if the timeout period expired, and ERRNO otherwise.


TCP-DEBUG
TCP

	( n -- )

Set the TCP/IP networking debug flag to n. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.


TCP-DESTROY
TCP

	( ep -- ior )

Close a listening or data endpoint; the endpoint should no longer be referenced.


TCP-FD
TCP

	( ep -- fd )

Get a listening or data endpoint's socket.


TCP-LISTEN
TCP

	( n1 n2 -- ep 0 | ior )

Create a "listening" endpoint bound to port n1 at which the application will listen for connection requests from clients; at most n2 requests may be pending. The listening endpoint ep and the I/O result of creating the endpoint are returned on the stack. The application uses the TCP-ANSWER word to accept incoming connection requests.


TCP-NAME
TCP

	( ep -- c-addr u )

Get a listening or data endpoint's name and return it as c-addr/u. The string is NUL-terminated and stored internally; it should be used or duplicated before calling TCP-NAME again. An address of NULL and a length of zero are returned in the event of an error.


TCP-PENDING?
TCP

	( ep -- f )

Check if any connection requests from potential clients are waiting to be answered on listening endpoint ep; return true if requests are pending and false otherwise. This word should only be applied to listening endpoints created by TCP-LISTEN.


TCP-READ
TCP

	( c-addr n ep r -- u ior )

Read n bytes of data into buffer c-addr from network connection ep. The actual number of bytes read, u, and the I/O result are returned on the stack.

Because of the way network I/O works, a single record written to a connection by one task may be read in multiple "chunks" by the task at the other end of the connection. TCP-READ takes this into account and, if you ask it for 100 bytes, it will automatically perform however many network reads are necessary to collect the 100 bytes.

If n is negative, TCP-READ returns after reading the first "chunk" of input received; the number of bytes read from that first "chunk" is limited to the absolute value of n. The actual number of bytes read is returned as u on the stack.

Timeout r specifies the maximum amount of time (in seconds) that the application wishes to wait for the first data to arrive. A negative timeout (e.g., -1E0) causes an infinite wait; a zero timeout (0E0) allows a read only if input is immediately available. If the timeout expires before the requested amount of data has been read, the actual number of bytes read is returned on the stack as u, along with an I/O result of EWOULDBLOCK.


TCP-READABLE?
TCP

	( ep -- f )

Check if data is waiting to be read from network connection ep; return true if the connection is readable and false otherwise. This word is equivalent to "endpoint TCP-FD SKT-READABLE?".


TCP-UP?
TCP

	( ep -- f )

Check if network connection ep is still up; return true if the connection is up and false otherwise. This word is equivalent to "endpoint TCP-FD SKT-UP?".


TCP-WRITE
TCP

	( c-addr u1 ep r -- u2 ior )

Write u1 bytes of data from buffer c-addr to network connection ep. The actual number of bytes written, u2, and the I/O result are returned on the stack.

Because of the way network I/O works, attempting to output a given amount of data to a network connection may require multiple network writes. TCP-WRITE takes this into account and, if you ask it to output 100 bytes, it will perform however many network writes are necessary to output the full 100 bytes of data to the connection.

Timeout r specifies the maximum amount of time (in seconds) that the application wishes to wait for the data to be output. A negative timeout (e.g., -1E0) causes an infinite wait; TCP-WRITE will wait as long as necessary to output all of the data. A zero timeout (0E0) specifies no wait: if the connection is not ready for writing, TCP-WRITE returns immediately; if the connection is ready for writing, TCP-WRITE returns after outputting whatever it can.

If the timeout expires before the requested amount of data has been written, the actual number of bytes written is returned on the stack as u2, along with an I/O result of EWOULDBLOCK.


TCP-WRITEABLE?
TCP

	( fd -- f )

Check if data can be written to network connection ep; return true if the connection is writeable and false otherwise. This word is equivalent to "endpoint TCP-FD SKT-WRITEABLE?".

 

The LF-Terminated Communications Word Set


Introduction

The LFN word set defines words for sending and receiving LF-terminated text over a network connection:

endpoint "options" LFN-CREATE
value LFN-DEBUG
stream LFN-DESTROY
stream LFN-FD
stream timeout LFN-GETLINE
stream LFN-NAME
string stream crlf timeout LFN-PUTLINE
buffer length stream timeout LFN-READ
stream LFN-READABLE?
stream LFN-UP?
buffer length stream timeout LFN-WRITE
stream LFN-WRITEABLE?

Source: words_lfn.c


Glossary


LF-Terminated Communications words


LFN-CREATE
LFN

	( ep c-addr u -- st 0 | ior )

Create a LF-terminated network stream on top of previously-created network endpoint ep (i.e., using TCP-ANSWER or TCP-CALL). The stream takes ownership of the endpoint; the endpoint will automatically be destroyed when the stream is destroyed. The stream is returned on the stack as st, along with the I/O result ior.

The c-addr/u string contains zero or more of the following UNIX command line-style options:

"-input size"
specifies the size of the stream's internal input buffer; the default is 2048 bytes. NOTE that this is only a limit on the input buffer, not on incoming strings.
"-output length"
specifies the maximum output message size for the stream; the default is 2047 bytes.

LFN-DEBUG
LFN

	( n -- )

Set the LF-terminated networking debug flag to n. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.


LFN-DESTROY
LFN

	( st -- ior )

Close LF-terminated network stream st and its underlying TCP/IP endpoint; the stream should no longer be referenced.


LFN-FD
LFN

	( st -- fd )

Get LF-terminated stream st's socket.


LFN-GETLINE
LFN

	( st r -- c-addr u ior )

Read the next CR/LF-delimited line of input from LF-terminated network stream st and return it as c-addr/u. The string is NUL-terminated and stored internally; it should be used or duplicated before calling LFN-GETLINE on this stream again. An address of NULL and a length of zero are returned in the event of an error.

Timeout r specifies the maximum amount of time (in seconds) that the application wishes to wait for the next line to be read. A negative timeout (e.g., -1E0) causes an infinite wait; a zero timeout (0E0) allows a read only if input is immediately available. If the timeout expires before a line of input has been read, the I/O result is EWOULDBLOCK.


LFN-NAME
LFN

	( st -- c-addr u )

Get LF-terminated network stream st's name and return it as c-addr/u. The string is NUL-terminated and stored internally; it should be used or duplicated before calling LFN-NAME again. An address of NULL and a length of zero are returned in the event of an error.


LFN-PUTLINE
LFN

	( c-addr u st n r -- ior )

Write the string c-addr/u to LF-terminated network stream st. The I/O result is returned on the stack.

Bit mask n specifies line terminators to be appended to the output string: 0 = no terminator, 1 = LF only, 2 = CR only, and 3 = CR/LF. Zero is typically used if the application explicitly puts the line terminators in the output string.

Timeout r specifies the maximum amount of time (in seconds) that the application wishes to wait for the line to be output. A negative timeout (e.g., -1E0) causes an infinite wait. A zero timeout (0E0) specifies no wait: if the connection is not ready for writing, LFN-PUTLINE returns immediately; if the connection is ready for writing, LFN-PUTLINE returns after outputting whatever it can. If the timeout expires before the output line has been written, an I/O result of EWOULDBLOCK is returned on the stack.


LFN-READ
LFN

	( c-addr n st r -- u ior )

Read n bytes of unformatted data into buffer c-addr from LF-terminated network stream st. The actual number of bytes read, u, and the I/O result are returned on the stack.

Because of the way network I/O works, a single record written to a connection by one task may be read in multiple "chunks" by the task at the other end of the connection. LFN-READ takes this into account and, if you ask it for 100 bytes, it will automatically perform however many network reads are necessary to collect the 100 bytes.

If n is negative, LFN-READ returns after reading the first "chunk" of input received; the number of bytes read from that first "chunk" is limited to the absolute value of n. The actual number of bytes read is returned as u on the stack.

Timeout r specifies the maximum amount of time (in seconds) that the application wishes to wait for the first data to arrive. A negative timeout (e.g., -1E0) causes an infinite wait; a zero timeout (0E0) allows a read only if input is immediately available. If the timeout expires before the requested amount of data has been read, the actual number of bytes read is returned on the stack as u, along with an I/O result of EWOULDBLOCK.


LFN-READABLE?
LFN

	( st -- f )

Check if data is waiting to be read from LF-terminated network stream st; return true if the stream is readable and false otherwise. Because input is buffered, LFN-READABLE? is not equivalent to "stream LFN-FD SKT-READABLE?". LFN-ISREADBLE first checks for currently buffered input; if there is none, LFN-READABLE? then checks the socket.


LFN-UP?
LFN

	( st -- f )

Check LF-terminated network stream st to see if its network connection is still up; return true if the connection is up and false otherwise.


LFN-WRITE
LFN

	( c-addr u1 st r -- u2 ior )

Write u1 bytes of unformatted data from buffer c-addr to LF-terminated network stream st. The actual number of bytes written, u2, and the I/O result are returned on the stack.

Because of the way network I/O works, attempting to output a given amount of data to a network connection may require multiple network writes. LFN-WRITE takes this into account and, if you ask it to output 100 bytes, it will perform however many network writes are necessary to output the full 100 bytes of data to the connection.

Timeout r specifies the maximum amount of time (in seconds) that the application wishes to wait for the data to be output. A negative timeout (e.g., -1E0) causes an infinite wait; LFN-WRITE will wait as long as necessary to output all of the data. A zero timeout (0E0) specifies no wait: if the connection is not ready for writing, LFN-WRITE returns immediately; if the connection is ready for writing, LFN-WRITE returns after outputting whatever it can.

If the timeout expires before the requested amount of data has been written, the actual number of bytes written is returned on the stack as u2, along with an I/O result of EWOULDBLOCK.


LFN-WRITEABLE?
LFN

	( st -- f )

Check if data can be written to LF-terminated network stream st; return true if the stream is writeable and false otherwise.

 

The I/O Event Dispatcher Word Set


Introduction

The IOX word set defines words for monitoring and responding to network I/O events:

seconds user word dispatcher IOX-AFTER
callback IOX-CANCEL
IOX-CREATE
value IOX-DEBUG
dispatcher IOX-DESTROY
callback IOX-DISPATCHER
seconds user word dispatcher IOX-EVERY
dispatcher timeout IOX-MONITOR
socket mode user word dispatcher IOX-ONIO
user word dispatcher IOX-WHENIDLE

IOX-AFTER, IOX-EVERY, IOX-ONIO, and IOX-WHENIDLE register callbacks to be invoked when monitored events occur. When a monitored event occurs, the specified word is executed with three arguments:

	( cb c-addr n -- )

where cb is the handle returned when the callback was registered, c-addr is the user data supplied by the application when the callback was registered, and n is a bit mask specifying the reason(s) for the callback (0x1=readable, 0x2=writeable, 0x4=OOB, 0x8=timer, 0x10=idle). Constants are predefined for the reasons:

IOX_READ - socket is readable.
IOX_WRITE - socket is writeable.
IOX_EXCEPT - socket has out-of-bound input available for reading.
IOX_IO - the bit-wise OR of the three conditions above.
IOX_FIRE - timer has fired.
IOX_IDLE - dispatcher is idle.

Source: words_iox.c


Glossary


I/O Event Dispatcher words


IOX-AFTER
IOX

	( r c-addr xt dp -- cb )

Register a single-shot timer of duration r seconds with I/O event dispatcher dp. A handle, cb, is returned on the stack and can be used to cancel the callback with IOX-CANCEL.

When the timer expires, (i) callback handle cb, user data c-addr, and reason n (IOX_FIRE) are pushed on the stack and (ii) execution token xt is executed. After xt completes, the callback is automatically cancelled.


IOX-CANCEL
IOX

	( cb -- ior )

Cancel callback cb; the callback should no longer be referenced. The I/O result of cancelling the callback is returned on the stack.


IOX-CREATE
IOX

	( -- dp 0 | ior )

Create an I/O event dispatcher. The dispatcher is returned on the stack as dp, along with the I/O result ior.


IOX-DEBUG
IOX

	( n -- )

Set the I/O event dispatching debug flag to n. A value of 0 disables debug; a non-zero value enables debug. Debug is written to standard output.


IOX-DESTROY
IOX

	( dp -- ior )

Destroy I/O event dispatcher dp; the dispatcher should no longer be referenced.


IOX-DISPATCHER
IOX

	( cb -- dp )

Get callback cb's dispatcher dp. This capability is useful when a callback needs to access its dispatcher. For example, a callback that answers a network connection request may wish to register an I/O callback for the new data connection.


IOX-EVERY
IOX

	( r c-addr xt dp -- cb )

Register a periodic timer of interval r seconds with I/O event dispatcher dp. A handle, cb, is returned on the stack and can be used to cancel the callback with IOX-CANCEL.

Each time the timer fires, (i) callback handle cb, user data c-addr, and reason n (IOX_FIRE) are pushed on the stack and (ii) execution token xt is executed. Unless explicity cancelled, the timer will continue firing every r seconds.


IOX-MONITOR
IOX

	( dp r -- ior )

Monitor and dispatch I/O events, timers, and idle tasks for r seconds using dispatcher dp. If r is less than zero, the dispatcher will monitor events forever. The I/O result of monitoring events is returned on the stack.


IOX-ONIO
IOX

	( fd n c-addr xt dp -- cb )

Register I/O file descriptor fd with I/O event dispatcher dp. Mask n is the bit-wise OR of the types of I/O events to monitor: IOX_READ for input-pending, IOX_WRITE for output-ready, and IOX_EXCEPT for OOB-input-pending. A handle, cb, is returned on the stack and can be used to cancel the callback with IOX-CANCEL.

When an event of the monitored types is detected on the I/O source, (i) callback handle cb, user data c-addr, and reason n (IOX_READ, IOX_WRITE, or IOX_EXCEPT) are pushed on the stack and (ii) execution token xt is executed.

To register a callback for a TCP/IP listening socket (created by TCP-LISTEN), specify IOX_READ as the event type to be monitored. When a connection request is received from a client, the listening socket becomes readable. The callback should then execute TCP-ANSWER to accept the connection request.


IOX-WHENIDLE
IOX

	( c-addr xt dp -- cb )

Register an idle task with I/O event dispatcher dp. A handle, cb, is returned on the stack and can be used to cancel the callback with IOX-CANCEL.

When the dispatcher is idle, (i) callback handle cb, user data c-addr, and reason n (IOX_IDLE) are pushed on the stack and (ii) execution token xt is executed.

 

The Directory Scanning Word Set


Introduction

The DRS word set defines words for scanning files in a directory.

"pathname" DRS-CREATE
scan DRS-DESTROY
"pathname" DRS-DIRECTORY?
scan DRS-FIRST
scan DRS-NEXT
scan DRS-COUNT
scan index DRS-GET

The DRS-FIRST and DRS-NEXT words are useful for sequencing through files in a BEGIN loop. DRS-COUNT and DRS-GET are suited for DO loops.

Source: words_drs.c


Glossary


Directory Scanning words


DRS-CREATE
DRS

	( c-addr u -- scan 0 | ior )

Create a directory scan for the directory specified in the c-addr/u pathname string. The pathname may contain wildcard characters for the files in the directory. If the scan is successfully created, the scan is returned on the stack with a status of zero. If there was an error, only a non-zero I/O result is returned on the stack.


DRS-DESTROY
DRS

	( scan -- ior )

Destroy a directory scan and return the I/O result ior on the stack.


DRS-DIRECTORY?
DRS

	( c-addr u -- flag )

Determine if the c-addr/u pathname string refers to a directory. Return (i) true if the pathname does refer to a directory and (ii) false if it doesn't or if there was an error.

Ficl does have the DPANS94 FILE-STATUS word (from the optional File-Access word set), but FILE-STATUS returns an implementation-defined status value. In particular, Ficl returns different values under Windows than it does on other platforms (e.g., UNIX). DRS-DIRECTORY? always uses the UNIX stat(2) call, which is available on Windows.


DRS-FIRST
DRS

	( scan -- c-addr u | 0 )

Get the first matching file in a directory scan. The file's full pathname is returned on the stack as c-addr/u. Zero (0) is returned if there are no matching files in the scan.


DRS-NEXT
DRS

	( scan -- c-addr u | 0 )

Get the next matching file in a directory scan. The file's full pathname is returned on the stack as c-addr/u. Zero (0) is returned if there are no more matching files in the scan.


DRS-COUNT
DRS

	( scan -- u )

Get the number of files, u, in a directory scan that matched the wildcard file specification supplied to DRS-CREATE.


DRS-GET
DRS

	( scan n -- c-addr u | 0 )

Get the indexed, n, matching file in a directory scan. Indices are numbered from 1 to the value returned by DRS-COUNT. The file's full pathname is returned on the stack as c-addr/u. Zero (0) is returned if the index is out of range. Getting a file name by index does not affect the sequence of file names returned by DRS-FIRST and DRS-NEXT.

 

The Timeval Word Set


Introduction

The TV word set defines words for manipulating UNIX timeval structures. A UNIX timeval structure consists of two signed integer values represeting the number of seconds and microseconds since the start of January 1, 1970. (Strictly speaking, the fields in a UNIX timeval structure are not necessarily signed and not necessarily integers. See the Wikipedia entries for Unix time and time_t for detailed information about the complexities of even Unix's simple time scheme.) The timeval fields are placed on the stack with the most significant seconds field first. For example, TV-TOD returns the time-of-day on the stack as two signed integers:

        TV-TOD		( -- seconds microseconds )

NOTE that these can't be treated as double-cell numbers, since a value of zero seconds, -123,000 microseconds has no indication in the seconds field that the time value is negative. Hence, I put the most significant seconds field first on the stack to prevent any confusion.

time1 time2 TV-ADD
time1 time2 TV-COMPARE
time inLocal? "format" TV-SHOW
time1 time2 TV-SUBTRACT
TV-TOD

Source: words_tv.c


Glossary


Timeval words


TV-ADD
TV

	( time1 time2 -- time3 )

Add two UNIX timevals, time1 plus time2, and return the sum, time3.


TV-COMPARE
TV

	( time1 time2 -- n )

Compare two UNIX timevals, time1 and time2, and return a signed integer indicating the result of the comparison: -1 if time1 is less than time2, zero if time1 equals time2, and +1 if time1 is greater than time2.


TV-SHOW
TV

	( time inLocal? c-addr1 u1 -- c-addr2 u2 | 0 )

Format a binary timeval, time, in ASCII using the strftime(3) format specified by c-addr1/u1. If inLocal? is true, the local time is used; otherwise the GMT is used. The formatted time is returned on the stack as c-addr2/u2, a string whose storage is private to the TV-SHOW word. If the conversion fails for any reason, only zero (0) is returned on the stack.

NOTE: If the O/S library does not support the gmtime(3) and localtime(3) functions, the binary time is assumed to be GMT and the inLocal? argument is ignored. If the O/S library does not support strftime(3), the format argument is ignored and the binary time is formatted as "YYYY-DOY-HR:MN:SC.MLS". Experiment with TV-SHOW to determine into which category your FINC build falls.


TV-SUBTRACT
TV

	( time1 time2 -- time3 )

Subtract two UNIX timevals, time1 minus time2, and return the difference, time3.


TV-TOD
TV

	( -- time )

Get the current time-of-day in seconds and microsecond since the start of January 1, 1970.

 

The Miscellaneous Word Set


Introduction

The MISC word set defines a miscellaneous collection of unrelated words.

"name" GETENV

Source: words_misc.c


Glossary


Miscellaneous words


GETENV
MISC

	( c-addr1 u1 -- c-addr2 u2 | 0 )

Get the value of the environment variable whose name is c-addr1/u1. The value, c-addr2/u2, is returned on the stack. If the named environment variable is not defined, then 0 is returned instead of c-addr2/u2.


Alex Measday  /  E-mail