4glWorks reference: Input/Output subsystem

The routines described here return errors via the status global variable. Most status codes come from the errno variable. Refer to errno (3) for their meaning.

fd_1stlineheader

file cfioc.c
declaration
function fd_1stlineheader(fd, s)
    define fd	integer,	#IO stream id
	   s	char(4)		#line header
returns nothing
purpose sets the line header for paragraph lines (i.e. those following a NL)
example see file_open
notes when opening a new stream, the line header defaults to the null string

fd_2ndlineheader

file cfioc.c
declaration
function fd_2ndlineheader(fd, s)
    define fd	integer,	#IO stream id
	   s	char(4)		#line header
returns nothing
purpose sets the line header for continuation lines (i.e. those NOT following a NL)
example see file_open
notes when opening a new stream, the line header defaults to the null string

fd_blobread

file cfioc.c
declaration
function fd_blobread(fd, t)
    define fd	integer,	#IO stream id
	   t	text		#destination blob (could be a byte as well)
returns nothing
purpose loads a text or byte variable located in memory from a file or pipe
example none
notes none

fd_blobwrite

file cfioc.c
declaration
function fd_blobwrite(fd, t)
    define fd	integer,	#IO stream id
	   t	text		#destination blob (could be a byte as well)
returns nothing
purpose writes a text or byte variable located in memory to a file or pipe
example none
notes none

fd_close

file cfioc.c
declaration
function fd_close(fd)
    define fd	integer		#IO stream id
returns r (smallint), exit code (pipes), or 0 (anything else)
purpose closes the IO stream indicated by fd, possibly waiting for child termination.
example see file_open
notes removes locks applied to the file

fd_crnl

file cfioc.c
declaration
function fd_crnl(fd, cr)
    define fd	integer,	#IO stream id
	   cr	integer		#output line terminator flag
returns nothing
purpose sets the line terminator flag for fd_writeln. A non zero second argument will force fd_writeln to append a CR NL to the text to be output rather than a NL
example none
notes
  • when a new stream is opened, the terminator flag defaults to false
  • this function does not affect fd_read functionality. fd_read treats both NL and CR NL as being valid end of line markers.

fd_droptoeol

file cfioc.c
declaration
function fd_droptoeol(fd)
    define fd	integer		#IO stream id
returns nothing
purpose discards all chars till next EOL, if not already at EOL
example see file_open
notes none

fd_eof

file cfioc.c
declaration
function fd_eof(fd)
    define fd	integer		#IO stream id
returns eof (integer), true if currently positioned at the EOF.
purpose returns true if at end of file
example see file_open
notes none

fd_eol

file cfioc.c
declaration
function fd_eol(fd)
    define fd	integer		#IO stream id
returns eol (integer), true if currently positioned on an EOL.
purpose returns true if at an end of line
example none
notes none

fd_linelen

file cfioc.c
declaration
function fd_linelen(fd, l)
    define fd	integer,	#IO stream id
	   l	integer		#input buffer size
returns nothing
purpose sets max line length returned by fd_read
example see file_open
notes
  • when a new stream is opened, the maximum string lenght defaults to 78 (the size of the largest non wordwrap field displayable on a 80 chars wide screen)
  • the maximum string lenght set with this function comprises the lenght of the line headers set with fd_1stlineheader and fd_2ndlineheader

fd_postwordsep

file cfioc.c
declaration
function fd_postwordsep(fd)
    define fd	integer,	#IO stream id
	   s	char(4)		#word separator characters
returns nothing
purpose sets the list of characters separating words.
example see file_open
notes
  • when opening a new stream, the separator list defaults to the null string, i.e. line splitting takes place at the maximum permissible line length, as set by fd_linelen
  • the separators set via this function are returned at the end of the current line, following the last word

fd_prewordsep

file cfioc.c
declaration
function fd_prewordsep(fd, s)
    define fd	integer,	#IO stream id
	   s	char(4)		#word separator characters
returns nothing
purpose sets the list of characters separating words.
example none
notes
  • when opening a new stream, the separator list defaults to the null string, i.e. line splitting takes place at the maximum permissible line length, as set by fd_linelen
  • the separators set via this function are returned at the beginning of the next (folded) line, after the line header (if set)

fd_read

file cfioc.c
declaration
function fd_read(fd)
    define fd	integer		#IO stream id
returns str (char), line of text (possibly folded)
purpose reads a string from a stream opened for input
example see file_open
notes none

fd_write

file cfioc.c
declaration
function fd_write(fd, s)
    define fd	integer,	#IO stream id
	   s	char(512)	#output string
returns nothing
purpose writes a string to a stream
example none
notes see file_open

fd_writeln

file cfioc.c
declaration
function fd_writeln(fd, s)
    define fd	integer,	#IO stream id
	   s	char(512)	#output string
returns nothing
purpose writes a string to a stream, appending [CR]LF at the end
example see pipe_open
notes see file_open

file_lock

file cfioc.c
declaration
function file_lock(fd, mandatory)
    define fd		integer,	#IO stream id
	   mandatory	integer		#true for exclusive locking
returns nothing
purpose locks the file identified by fd in advisory or mandatory mode
example none
notes none

file_open

file cfioc.c
declaration
function file_open(p, m)
    define p	char(90),	#file path
	   m	char(1)		#mode: "r","w","a","r+","w+","a+", as for fopen (3)
returns fd (integer), the id of the stream just opened
purpose opens a file for reading or writing
example
fd=file_open("a_file", "r")		#open for reading only
call fd_postwordsep(fd, ",;. ")		#split at blanks & punctuation marks
call fd_1stlineheader(fd, "  ")		#lines after NL marked by a double blank
call fd_2ndlineheader(fd, "+ ")		#all the other start with a plus
call fd_filelen(fd, 60)			#no more than 60 chars at a time
while not fd_eof(fd)
    let s=fd_read(fd)
    let i=pos(s, "#")
    if (i>0)				#drop comments
    then
	call fd_droptoeol(fd)		#don't process continuation lines
	if (i>i)
	then
	    let i=i-1
	    let s=s[1, i]
	else
	    let s=""
	end if
    end if
    call do_something(s)
end while
let r=fd_close(fd)
notes Opening a file mode "a+" causes writes to be performed at the end of the file, even after invoking file_seek (some_number), exactly like for fopen (some c mans are not clear over this point). This is due to the fact that the O_RDWR & O_APPEND flags are used when opening files in "a+" mode.

file_seek

file cfioc.c
declaration
function file_seek(fd, pos)
   define fd	integer,	#IO stream id
	  pos	integer		#absolute position within file
returns nothing
purpose moves the file pointer relative to file fd to absolute position pos
example none
notes see file_open

file_tell

file cfioc.c
declaration
function file_tell(fd)
    define fd	integer		#IO stream id
returns pos (integer), current file pointer absolute position
purpose returns file pointer position
example none
notes none

file_unlock

file cfioc.c
declaration
function file_unlock(fd)
    define fd	integer			#IO stream id
returns nothing
purpose unlocks a previously locked file
example none
notes none

pipe_open

file cfioc.c
declaration
function pipe_open(p, m)
    define p	char(32000),	#command line
	   m	char(2)		#mode: "r","w" as for popen (3)
returns fd (integer), the id of the stream just opened
purpose opens a pipe for reading or writing
example
let fd=pipe_open("sendmail -t", "w")
call fd_writeln(fd, "To: someone@somewhere.org")
call fd_writeln(fd, "Subject: no subject")
call fd_writeln(fd, "")
call fd_writeln(fd, "some text")
let r=fd_close(fd)
notes none

stdfd_open

file cfioc.c
declaration
function stdfd_open(f)
    define f    smallint        #only 0, 1, 2 are valid
returns fd, integer, id of the stream just opened
purpose Associates a stream handle to one of the standard IO streams
example none
notes Useful to quickly write something to the standard error, or to read strings while in SCREEN MODE


User defined Input/Output streams

The following section briefly explains how to build user defined input streams.
In essence, the 4glworks IO subsystem needs to be informed on how to open, read from, write to and close the stream.
This is done by writing a function that actually opens a stream of the type to be defined, and have this pass to the 4glWorks IO subsystem pointers to the appropriate read, write and close functions (whose prototype matches that of read (2), write (2) and close (2) respectively), via the internal function
fgw_addfd, described later.
Outlined below is a stripped down (add header files inclusion, data definition and clip a few strings, to make it work) example of a simple sockets client, which should clearly illustrate the actual procedure needed to create user defined streams.

fgw_addfd

file cfioc.c
declaration
int fgw_addfd(id, r, w, c)
int id;				/* user defined IO stream identifier */
int (*r)(), (*w)(), (*c)();	/* read, write, close function pointers */
returns fd (integer), the id of the stream just opened, or -1 if a new fd structure cannot be allocated.
purpose reserves a fd data structure on the heap for the newly opened user defined stream, and associates to it the supplied read, write and close functions. Typically used within functions that open user defined IO streams.
example
fgw_sokread(s, b, l)
int s;
void *b;
int l;
{
    return recv(s, b, l, 0);
}

fgw_sokwrite(s, b, l)
int s;
void *b;
int l;
{
    return send(s, b, l, 0);
}

socket_open(nargs)
int nargs;
{
    popquote(proto,10);
    popquote(serv,20);
    popquote(host,120);
    if ((hostrec=gethostbyname(host))!=NULL)
    {
	if ((servrec=getservbyname(serv, proto))!=NULL)
	{
	    name.sin_port=servrec->s_port;
	    name.sin_family=hostrec->h_addrtype;
	    fgw_move((char *) &name.sin_addr, (char *) hostrec->h_addr,
		hostrec->h_length);
	    if ((sock=socket(AF_INET,SOCK_STREAM,0))!=-1)
    		if (connect(sock,(struct sockaddr *) &name,sizeof(name))!=-1)
		    if ((fd_id=fgw_addfd(sock, fgw_sokread,
					 fgw_sokwrite, close))!=-1)
		    {
			retint(fd_id);
			return(1);
		    }
		    else
		    {
			close(sock);
			errno=-1;
		    }
	}
    }
    status=errno;
    retquote("");
    return(1);
}
notes none


Please address questions or comments to marco greco
(last updated Thu, 28 March 2002 16:04:28 GMT)