% $Id: SUPPLIO.TEX 1.2 2000/07/10 14:12:00 ska Exp ska $
\section{\label{sssupplio}\subsys{supplio}}

Originally designed to overcome differences between Micro-C and ISO9899
this subsystem does contain several advances and also helps to perform
several tasks more efficient on some platforms.

Furthermore, Input/Output operations (IO-operations) are one of the most
commonly used functions, as they are the base of all file processing,
and most commonly {\em differently} interpreted functions, when it comes
to to handle failures, ranging from meaningless messages like: \quote{\tt
General I/O error} to \quote{\tt Cannot read record #49573 from file D:\bs
TEMP\bs MEHO0381.$$$ when expecting tag shift form A7}.
To help to let various program speak equally to user in the same
circumstances this subsystem implements functions to issue error messages,
for instance when a file could not be opened. This functionality
is achieved by using \subsys{error}, so refer to section \ref{sserror}
on page \fpageref{sserror} for more details.


\subsection{Design}

\subsubsection{\hfile{stdio.h} Wrapper Functions}

The first set of functions implemented to unify the IO-operation
of Micro-C and ISO9899 wraps the functions declared in \hfile{stdio.h},
also known as \quote{buffered IO}, stream functions or
just the \tok{f}-functions.

Although, especially in the DOS environment, where memory is a short
resource, some programmers won't use the buffered IO, because it
adds to much {\em overhead} to a program in their views. Looking at
DOS real-mode programming, this is true, but after all the \hfile{stdio.h}
functions {\bf\em are} the standard according ISO9899! 

\subsys{supplio} implements more or less the same interface as
\hfile{stdio.h} does, to differ between both sets of functions the
ones of \subsys{supplio} start with at least one capital {\bf F},
corresponding to the lower-case {\bf f} the functions of \hfile{stdio.h}
have; so \fct{fopen()} becomes \fct{Fopen()}, \fct{feof()} becomes
\fct{Feof()}, but \fct{clearerr()} becomes \fct{Fclearerr()}.

But all the functions do work over the same \tok{FILE *} pointers and do
have the same prototypes as described in ISO9899.  The only exception is
that side effects are removed and that to support platforms without
\tok{(long)} variables several things had to be removed from the
interface, one example is \fct{ftell()}, for which there is no
equivalent in \subsys{supplio}, because a compiler without \fct{(long})
values cannot return a 32-bit file position directly.

\paragraphe{Extended attributes} can be additionally applied to
streams. They are created while a file is opened by the function
\fct{Fxopen()}, though the return value is just a \tok{FILE *} pointer
as \fct{Fopen()} does. But in parallel and {\em independed on} the
\tok{FILE} structure a list of Extended Attributes (EAs) is maintained.
Because both structures are different, a stream opened with \fct{Fxopen()}
must be closed with \fct{Fxclose()}, in order to apply all EAs correctly
and deallocte all the resources of this stream. However, \fct{Fxclose()}
can be called with traditionally opened streams as well.

The common \tok{FILE*} pointer is the key to address the EAs, but this
requires to invoke function \fct{Fxinfo()}. Because all the other functions
remain intact and the EAs are {\em not} frequently used generally, this
design seems to be more efficient, because, unless the compiler's 
\tok{FILE} is modified, there has to be two different structures and
the alternative is to create another wrapper transforming \tok{FXFILE*}
pointers into usual \tok{FILE*} pointers.

The EAs currently contain only two information:
\begin{enumerate}
\item\label{EA1} The absolute filename of the opened stream.
\item\label{EA2} A flag if the stream has been created temporarily.
\end{enumerate}

EA\ref{EA2} overcomes a common problem with function \fct{tmpfile()}
of DOS C compilers: One the file is closed the current working
path {\em must be the same} one as when it was created. This limit
simplifies the implementation enormeous, but also bestows the
programmer with duties. Furthermore, ISO9899 didn't thought about
the difference between text and binary files at this point, although
it did when designing \fct{fopen()}.

EA\ref{EA1} is used by EA\ref{EA2}, of course, but also by the
above mentioned and below described error functions. To store the
name of the file within the EAs allows every function at any nesting
level to aquire the name of the file from the passed \tok{FILE*}
pointer! It removes the need to keep track of the filename,
for instance to keep it as a global variable or pass it down
with every function. The disadvantage buying the pros is that
the filename is kept, even if there is not even the potential
possibility, it might be used.

The design of function \fct{Fxinfo()}, which returns the pointer
to the EAs associated with a given \tok{FILE*} pointer, allows
an almost unconditional use of the return value, even if there
are no EAs for the stream, in cases such as error messages:
The returned value points to an EA structure containing the following
dummy member values:
\begin{itemize}
\item The \quote{associated \tok{FILE*} pointer} has the value
\tok{NULL}, what indicates the dummy EA structure.
\item The \quote{absolute filename} names something like
\ttytext{<<unknown filename>>}.
\item The \quote{temporary file flag} is false.
\end{itemize}
These dummy values allow almost any useful error message without
a special handling whether or not the stream had been associated
with EAs.

\subsubsection{Error Functions}

Many programs contain source code like this:
\begin{verbatim*}
#include <stdio.h>

/* ... */

{	FILE *fp;

	/* ... */

	if((fp = fopen(filename, openmode)) == NULL) {
		fprintf(stderr, "Icks! open(%s) failed, stop!\n", filename);
		exit(1);
	}
	if(fwrite(array, sizeof(array[0]), items, fp) != items) {
		fprintf(stderr, "Write error\n");
		exit(1);
	}

	/* ... */
\end{verbatim*}

Usually the error message itself looks different from program to
program, even when written by the same natural person, even differs
among the same program.

Not only does this confuse a not-so-often user, because the same error
looks different all the time, there are simple problems to {\em understand}
certain messages, considering some users do not speak the program's
favorite language natively and/or fluently.

\suppl  wants to help to remove both the expense of the programmer to
type the code all the time and the confusion of the user.
Therefore a set of functions is provided that perform a task,
probe the success and, on failure, terminate the program with the
appropriate error message. That means that the return value of
such function is {\em always} valid, so it can directly be used with
other statements.

Error probing functions of \subsys{supplio} are named conforming their
{\bf F} counterpart, but use a capital {\bf E}; for instance
\fct{Fopen()} becomes \fct{Eopen()} and \fct{Fread()} becomes \fct{Eread()}.

Above example could like this:
\begin{verbatim*}
#include <supplio.h>

/* ... */

{	FILE *fp;

	/* ... */

	Ewrite(array, sizeof(array[0]), items, fp = Eopen(filename, openmode));

	/* ... */
\end{verbatim*}

Unless changed, \fct{Eopen()} issues \ttytext{Cannot open file
\quote{\%s}} and \fct{Ewrite()} does \ttytext{Cannot write to file
\quote{\%s}}. The filename is taken from the EAs described above. So in
this example, in case of a failure the error messages, except
\fct{Eopen()}, would substitute \ttytext{<<unknown filename>>}, because
no EAs are associated with the file. But if \fct{Exopen()} had been used
instead of just \fct{Eopen()}, the EAs had been created and even
\fct{Ewrite()} would display the proper filename.

Of course, if the error messages had been choosen colourfully in
above example, individual messages would be more useful.

\subsection{Implementation}

\subsubsection{Types and Macros}

\begin{tabTS}
\fct{SUPPL\_USE\_EXTENDED\_ATTRIBUTES} & Causes to install macros
	that map the standard EA-ignoring functions \fct{Fopen()},
	\fct{Fclose()}, \fct{Eopen()} and \fct{Eclose()} to the EA-aware
	functions \fct{Fxopen()}, \fct{Fxclose()}, \fct{Exopen()} and
	\fct{Exclose()} respectively. \\
\fct{Suppl\_ExtAttr} & A structure of the EAs. The members are:
\begin{describe}
\item[\tok{FILE *sea\_fp}] associated \tok{FILE*} pointer; if equal
	to \tok{NULL} this is the default entry.
\item[\tok{char *sea\_fnam}] absolute filename; default:
	\ttytext{<<unknown filename>>}
\item[\tok{FLAG sea\_istmp}] true if it is a temporary file and will be
	removed on close via \fct{Fxclose()}.
\end{describe}\\
\fct{fpos\_t} & Datatype to hold a file position (black-box). (Missing
	in Micro-C and Pacific HiTech C) \\
\fct{SEEK\_SET} & Passed to \fct{fseek()} as the \tok{whence} parameter
	to seek relatively from the beginning of the file. (Possibly
	missing in Micro-C) \\
\fct{SEEK\_CUR} & Passed to \fct{fseek()} as the \tok{whence} parameter
	to seek relatively from the current file position. (Possibly
	missing in Micro-C) \\
\fct{SEEK\_END} & Passed to \fct{fseek()} as the \tok{whence} parameter
	to seek relatively from the end of the file. (Possibly
	missing in Micro-C) \\
\fct{FF\_RD} & Passed to \fct{Fsetmode()} to switch to read access\\
\fct{FF\_WR} & Passed to \fct{Fsetmode()} to switch to write access\\
\fct{FF\_RW} & Passed to \fct{Fsetmode()} to switch to read \& write access\\
\end{tabTS}

\subsubsection{Functions}

\paragraphe{Compatibly functions} are mostly implemented to
unify the interface between Micro-C and ISO9899 compliant compilers,
therefore most of them really are macros for latter ones.

\begin{tabTS}
\fct{fsetpos} & Seeks to a file position contained within a
	\tok{(fpos\_t)} value. (Missing in Pacific HiTech C) \\
\fct{fgetpos} & Retrieves the file position of a stream and stores it
	into a \tok{(fpos\_t)} value. (Missing in Pacific HiTech C) \\
\fct{Fclose()} & analogeous to \fct{fclose()}. \\
\fct{Frewind()} & analogeous to \fct{rewind()}. \\
\fct{Fgetc()} & analogeous to \fct{getc()}. \\
\fct{Fputc()} & analogeous to \fct{putc()}. \\
\fct{FFgetc()} & analogeous to \fct{fgetc()}. \\
\fct{FFputc()} & analogeous to \fct{fputc()}. \\
\fct{Fgetc()} & analogeous to \fct{fgets()}. \\
\fct{Fputc()} & analogeous to \fct{fputs()}. \\
\fct{Ferror()} & analogeous to \fct{ferror()}. \\
\fct{Fclearerr()} & analogeous to \fct{clearerr()}. \\
\fct{Fileno()} & analogeous to \fct{fileno()}. \\
\fct{Fdopen()} & analogeous to \fct{fdopen()}. \\
\fct{Feof()} & analogeous to \fct{feof()}. \\
\fct{Ftmpfile()} & Creates and opens a temporary binary file.
	It {\em must} be closed with \fct{Fxclose()} in order to
	remove the file.\\
\fct{Fgetpos()} & analogeous to \fct{fgetpos()}\\
\fct{Fsetpos()} & analogeous to \fct{fsetpos()}\\
\end{tabTS}

Note:
\begin{enumerate}
\item the absence of \fct{Fgets()}, in the sense of \quote{analogeous to
	\fct{gets()}}, and \fct{Ftell()}.  Latter must be replaced by the
	function pair \fct{Fsetpos()} and \fct{Fgetpos()}, and their helpers
	\fct{Fposcmp()} and \fct{Fpos2dword()}.

\item the absence of \fct{Fseek()} and \fct{Ftmpnam()} as well as
	\fct{Fsetpos} and \fct{Fgetpos}, but their implementation in the
	table {\em below}.
\end{enumerate}

\paragraphe{Additional function of portability reasons} are required to
cope with the inability of some compilers to handle \tok{(long)} values
natively as \quote{parameter-by-value} or return values.

Besides this little inportability, there is another problem, some
compilers cannot generate an address of a structure, whereas in
other compilers, such as ISO9899-comliant ones, it is a must.

\begin{tabTS}
\fct{FFgetpos()} & analogeous to \fct{fgetpos()}, but the file position
	parameter must be true a \fct{(fpos\_t)} value and not a pointer. \\
\fct{FFsetpos()} & analogeous to \fct{fsetpos()}, but the file position
	parameter must be true a \fct{(fpos\_t)} value and not a pointer. \\
\fct(Fposcpy} & Copies one \tok{(fpos\_t)} value to another
	location. Both are addressed by pointers. \\
\fct(Fposcmp} & Compares two \tok{(fpos\_t)} values addressed to by
	pointers.\\
\fct{Fpos2dword} & Extracts the \tok{(long)} file offset from a
	\tok{(fpos\_t)} structure \\
\fct{Fpos2dword} & Extracts the \tok{(long)} file offset from a
	\tok{(fpos\_t)} structure and stored it into a real variable. \\
\fct{Fppos2dword} & Extracts the \tok{(long)} file offset from a
	\tok{(fpos\_t)} structure and stored it into a variable
	addressed to by a pointer. \\
\fct{Fseek} &	analogeous to \fct{fseek()}, but the file offset to
	seek to must be located in a \tok{(dword}) variable, or must be
	zero.\\
\fct{Fpseek} & Analogeous to \fct{Fseek()}, but the offset is
	addressed to by a pointer.\\
\fct{Fseeki} &	Seeks relatively from the current file offset
	a signed \tok{(int)} (signed 16-bit!) amount of bytes. \\
\fct{Fseekc} &	Seeks relatively from the current file offset
	an amount of bytes specified in a real \tok{(dword)} variable.\\
\fct{Fpseekc} &	Analogeous to \fct{Fseekc()}, but the value is
	stored in a \tok{(dword)} value addressed by a pointer.\\
\fct{Fseeke} &	Seek to the end of the stream \\
\fct{Fsetmode} & Changes the read-, write- or read/write mode of the
stream. This call is ignored in all compilers except Micro-C, because
there seeking within r\&w-files would destroy its contents. See \fct{FF\_RD}
macro and associated ones.\\
\fct{Fyopen} & As \fct{fopen()}, but definitely bypasses \fct{Fxopen()}
or if \fct{fopen()} has been re-\#define'ed.
\end{tabTS}


\paragraphe{New functions} implementing often used functionality or
simplify the API.
\begin{tabTS}
\fct{Fget} & Analogeous to \fct{fread()}, but the buffer is specified
by only one length argument. \\
\fct{Fput} & Analogeous to \fct{fwrite()}, but the buffer is specified
by only one length argument. \\
\fct{FFget} & Analogeous to \fct{FFget()}, but returns the success
status only. \\
\fct{FFput} & Analogeous to \fct{FFput()}, but returns the success
status only. \\
\fct{Fgetline} & Reads a text line of any length into dynamic memory.\\
\fct{F\_tmpfile} & Opens the given filename as temporary file via
\fct{Fxopen()} in binary mode.\\
\fct{Ftmpfile} & Creates and returns the name of a temporary file with the
given extension and creates a zero-length file of this name.\\
\fct{Ftmpdir} & Returns the current writable temporary directory.\\
\fct{Fmaxbuf} & Allocate a large chunk of memory, but no more
as the system is capable to transfer to or from a file at one time.\\
\fct{Fcopy} & Copies all remaining bytes from one file to another.\\
\fct{Fcopyto} & Copies a portion of one file to another upto, but including
a given position.\\
\fct{Fcopyi} & Copies \tok{(int)n} bytes from one file to another.\\
\fct{Fcopyl} & Copies \tok{(long)n} bytes from one file to another.\\
\fct{Fcopybuf} & Copies one block from one file to another.\\
\end{tabTS}

\paragraphe{Functions dealing with Extended Attributes} are the base
of the \fct{E*()} functions of this subsystem and preserve the absolute
name of the file during the complete time it is opened.
\begin{tabTS}
\fct{Fxopen} & As \fct{fopen()}, but fully-qualify the filename and
keep it within the EAs.\\
\fct{F\_xopen} & As \fct{Fxopen()}, but returns a pointer to the
EAs rather than to the stream.\\
\fct{Fxclose} & Closes a stream and removes the EAs probably associated
with the stream.\\
\fct{Fxcloseall} & Closes all streams opened via \fct{Fxclose()}.\\
\fct{Fxinfo} & Returns a pointer to the EAs of a given stream.\\
\fct{F\_xinfo} & Returns a pointer to the EAs of a given stream and to the
previous stream within the list of EAs.\\
\end{tabTS}

\paragraphe{Functions issuing error messages} combine the interface of
\subsys{supplio} with \subsys{error}. Whenever the function fails, the
program is terminated with an appropriate error message, otherwise the
return value is {\em always} valid; the last sentence of the following 
table displays the error message of the particular function. If the 
file had been opened using \fct{Fxopen()}, the error message always contains
the name of the file, otherwise the name is substituted by
\ttytext{<<unknown>>}.

\begin{tabTS}
\fct{Exopen} & As \fct{Fopen()}; \ttytext{Cannot open file \quote{\%s}}\\
\fct{Eopen} & As \fct{Fxopen()}; \ttytext{Cannot open file \quote{\%s}}\\
\fct{Ecreate} & As \fct{Fxopen()}; \ttytext{Cannot create file \quote{\%s}}\\
\fct{Exclose} & As \fct{Fxclose()}; terminates the program if the error flag
is set -- see \fct{Ferror()} --; \ttytext{Error to access file \quote{\%s}}\\
\fct{Eclose} & As \fct{Fxclose()}; terminates the program if the error flag
is set -- see \fct{Ferror()} --; \ttytext{Error to access file \quote{\%s}}\\
\fct{Eclearerr} & As \fct{Fclearerr()}; terminates the program if the error flag
is set -- see \fct{Ferror()} --; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Eerror} & If error flag is set -- see \fct{Ferror()} -- terminates program with \ttytext{Cannot access file \quote{\%s}}\\
\fct{Ereaderr} & If error flag is set -- see \fct{Ferror()} -- terminates program with \ttytext{Cannot read from file \quote{\%s}}\\
\fct{Ewriteerr} & If error flag is set -- see \fct{Ferror()} -- terminates program with \ttytext{Cannot write into file \quote{\%s}}\\
\fct{Egets} & As \fct{Fgets()}; \ttytext{Cannot read from file \quote{\%s}}\\
\fct{Eputs} & As \fct{Fputs()}; \ttytext{Cannot write into file \quote{\%s}}\\
\fct{Eget} & As \fct{Fget()}; \ttytext{Cannot read from file \quote{\%s}}\\
\fct{Eput} & As \fct{Fput()}; \ttytext{Cannot write into file \quote{\%s}}\\
\fct{Egetpos} & As \fct{Fgetpos()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Epgetpos} & As \fct{Fpgetpos()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Esetpos} & As \fct{Fsetpos()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Epsetpos} & As \fct{Fpsetpos()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Eseek} & As \fct{Fseek()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Eseeki} & As \fct{Fseeki()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Eseekc} & As \fct{Fseekc()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Eseeke} & As \fct{Fseeke()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Epseekc} & As \fct{Fpseekc()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Epseek} & As \fct{Fpseek()}; \ttytext{Cannot access file \quote{\%s}}\\
\fct{Erewind} & Dummy, because \fct{Frewind()} does not return any error status.\\
\fct{Egetline} & As \fct{Fgetline()}; \ttytext{Cannot read from file \quote{\%s}} or \ttytext{Out of memory}\\
\fct{Etmpfile} & As \fct{Ftmpfile()}; \ttytext{Cannot create temporary file \quote{\%s}} or \ttytext{Out of memory}\\
\fct{Etmpnam} & As \fct{Ftmpnam()}; \ttytext{Cannot create temporary file \quote{\%s}} or \ttytext{Out of memory}\\
\fct{Etmpdir} & As \fct{Ftmpdir()}; \ttytext{Out of memory}\\
\fct{Egetc} & Dummy, because \fct{Fgetc()} does not return any error status.\\
\fct{Efgetc} & Dummy, because \fct{FFgetc()} does not return any error status.\\
\fct{Efputc} & Dummy, because \fct{FFputc()} does not return any error status.\\
\fct{Eputc} & Dummy, because \fct{Fputc()} does not return any error status.\\
\fct{Esetmode} & Dummy, because \fct{Fsetmode()} does not return any error status.\\
\fct{Efileno} & Dummy, because \fct{Ffileno()} does not return any error status.\\
\fct{Exinfo} & Dummy, because \fct{Fxinfo()} does not return any error status.\\
\fct{E\_xinfo} & Dummy, because \fct{F\_xinfo()} does not return any error status.\\
\end{tabTS}
