% $Id: FARMEM.TEX 1.1 2000/01/24 10:18:50 ska Exp ska $
\section{\label{ssfarmem}\subsys{farmem}}

\subsection{Design}

This subsystem is designed to help to write portable programs for
compilers that do and do not support \tok{far} pointers, in particular
Micro-C does {\em not} support neither the \tok{(long)} data type nor
any \tok{far} pointers, which are usually represented by \tok{(long)}
values.

The naming convention inherits the name from the usual C standard string
and memory functions, but prefixes the names by \tok{\_f}, thus, the
\tok{far} variant of \fct{strcpy()} is named \fct{\_fstrcpy()}. This
follows the way Borland compilers offer.

The problem is how to pass a \tok{far} pointer to the functions, because
to support compilers that do not support any data type suitable for
\tok{far} pointers themselves. Therefore this subsystem targets on
the functions, but cannot really implement how the compiler handles
\tok{far} variables.

Internally \tok{far} pointers are represented by two values of the data
type \tok{(WORD)}, which are numerical unsigned 16bit values.  The
subsystem therefore assumes that compilers not supporting \tok{far}
pointers natively must handle \tok{far} pointers as two individual
variables of the data type \tok{(WORD)}, one is called the {\em segment}
and the other the {\em offset} of the \tok{far} address. This handling
can be simulated by the other compilers as well, but most possibly
result in a less efficient program. For an example to try to overcome
this problem please refer to the far tables (\tok{fartbl})
implementation on page \refpage{fartbl}.

To summarize above paragraphes, the expression \tok{strlen(string)}
becomes \tok{\_fstrlen(segment\_of\_string, offset\_of\_string)}, when
\tok{string} is a \tok{far} pointer actually; for both types of compilers,
the ones do and don't support \tok{far} pointers natively.

Though, although the user of functions of subsystem \subsys{farmem}
must represent the \tok{far} pointers seperated in segment and offset
value manually; the compiler should use real \tok{far} pointers, if
available. Therefore the seperation is covered by macros against the
compiler. These macros let the call of farmem functions look the
same on both type of compilers, thus, making the useage of
farmem functions {\em portable}. So to say, one must make it ugly looking
in order to make it work.

One set of macros transform the segment/offset pair into a \tok{far}
pointer, if possible; a second set extracts the segment and offset from
a pointer. Latter is a bit confusing because there is no portable way to
represent \tok{far} variables; so this implementation assumes that, if
the compiler does not support \tok{far} pointers natively, the compiler
does support memory models Tiny and Small only; which means that both
code and data segments must not exceed 64KB in size and that a segment
extractable from a pointer is always the default data segment of the
program.

\paragraphe{The limited useability} of \subsys{farmem} may hide the
few circumstances, these functions are {\em useful}. The reason to
implement \subsys{farmem} was to implement a portable way to
communicate with the DOS API, because here one must use the
segment/offset pair to specify \tok{far} pointers.

Because this subsystem assumes that no data type \tok{(void far*)} is
available, no function can return a pointer, as \fct{strcpy()}
would normally do.

\subsection{Implementation}

\subsubsection{Macros}

\begin{tabTS}
\fct{MK\_FP(segment, offset)} & Creates a \tok{far} pointer from the
	segment/offset pair. For compilers supporting \tok{far} pointers
	natively the result is a value of the data type \tok{(void far*)};
	otherwise, both arguments are passed unchanged, thus, mapping
	the function call \tok{\_fstrlen(MK\_FP(segm, offs))} into
	\tok{\_fstrlen(segm, offs)}. \\
\fct{TO\_FP(pointer)} & Creates a \tok{far} pointer from a native
	pointer. For compilers supporting \tok{far} pointers natively
	the result is a value of the data type \tok{(void far*)};
	otherwise, the argument is considered to be the offset of the
	\tok{far} pointer and the segment is the default data segment
	of the program, thus, mapping
	the function call \tok{\_fstrlen(TO\_FP(poi))} into
	\tok{\_fstrlen(get_default_data_segment(), poi)}. \\
\fct{FP\_SEG(pointer)} & Returns the segment of the pointer. Because
	compilers not supporting \tok{far} pointers natively are considered
	to address one segment only, this function always returns the
	default data segment in this case; otherwise, the function returns
	the segment portion of the \tok{far} pointer. \\
\fct{FP\_OFF(pointer)} & Returns the offset of the pointer. Because
	compilers not supporting \tok{far} pointers natively are considered
	to address one segment only, this function always returns the
	pointer itself in this case; otherwise, the function returns
	the offset portion of the \tok{far} pointer. \\
\end{tabTS}

The following examples shall help to illustrate, how the macros work:
\newline\noindent Consider the following source snippet:\newline\noindent
\begin{verbatim*}
WORD segm, offs;
char *buf;
size_t len;

len = _fstrlen(MK_FP(segm, offs)) + 1;
buf = malloc(len);
_fmemcpy(TO_FP(buf), MK_FP(segm, offs), len);
\end{verbatim*}

On a compiler supporting \tok{far} pointers natively the snippet would
look like this:\newline\noindent
\begin{verbatim*}
WORD segm, offs;
char *buf;
size_t len;

len = _fstrlen((void far*)MK_FP(segm, offs)) + 1;
buf = malloc(len);
_fmemcpy((void far*)(buf), (void far*)MK_FP(segm, offs), len);
\end{verbatim*}
The \tok{(void far*)MK\_FP()} is some compiler-depended function or
macro that transform the segment/offset pair into the compiler-internal
format of a \tok{far} pointer.

Whereas on a compiler that does not support \tok{far} pointers:\newline\noindent
\begin{verbatim*}
WORD segm, offs;
char *buf;
size_t len;

len = _fstrlen(segm, offs) + 1;
buf = malloc(len);
_fmemcpy(get_default_data_segment(), (WORD)buf, segm, offs, len);
\end{verbatim*}
Instead of {\bf one} argument of data type \tok{(void far*)}, the
farmem functions are passed {\bf two} arguments of data type \tok{(WORD)}.

\par Consider the following source snippet:\newline\noindent
\begin{verbatim*}
struct REGPACK r;
char buf[80];

	/* code to fill buf[] with some useful string */

r.r_ax = 0x900;		/* DOS API: Write string to stdout */
r.r_ds = FP_SEG(buf);
r.r_dx = FP_OFF(buf);
intr(0x21, &r);
\end{verbatim*}

On a compiler supporting \tok{far} pointers natively --- Note: This includes
that the compiler supports Large memory model, where the array buf[]
is a \tok{far} pointer itself --- the snippet would
look like this:\newline\noindent
\begin{verbatim*}
struct REGPACK r;
char buf[80];

	/* code to fill buf[] with some useful string */

r.r_ax = 0x900;		/* DOS API: Write string to stdout */
r.r_ds = (WORD)FP_SEG(buf);
r.r_dx = (WORD)FP_OFF(buf);
intr(0x21, &r);
\end{verbatim*}
The \tok{(WORD)FP\_???()} are some compiler-depended functions or
macros that transform extract the segment or offset portion from
the compiler-internal format of a \tok{far} pointer. These macros do
support non-\tok{far} pointers automatically.

Whereas on a compiler that does not support \tok{far} pointers:\newline\noindent
\begin{verbatim*}
struct REGPACK r;
char buf[80];

	/* code to fill buf[] with some useful string */

r.r_ax = 0x900;		/* DOS API: Write string to stdout */
r.r_ds = get_default_data_segment();
r.r_dx = (WORD)buf;
intr(0x21, &r);
\end{verbatim*}

The advantage to use the macros is that the macros let the source code
look the very same, regardless whether or not the compiler supports
\tok{far} pointers natively.

\subsubsection{Functions}

\begin{tabTS}
\fct{\_fnormalize()} & Normalizes a \tok{far} pointer, meaning adjusts the
	segment/offset pair so that the offset is a positive number less than
	16. The calling interface is compiler-depended and should not be used
	outside \suppl. \\
\fct{\_fdupstr()} & Duplicates a \tok{far} string into the local heap. \\
\fct{\_fmemcmp()} & Compares a \tok{far} memory block with another one
	case-sensitively. \\
\fct{\_fmemcpy()} & Copies a \tok{far} memory block into another one.
	Does not support overlapped memory blocks.\\
\fct{\_fmemmove()} & Copies a \tok{far} memory block into another one.
	Does support overlapped memory blocks.\\
\fct{\_fmemset()} & Fills a \tok{far} memory block with a character. \\
\fct{\_fstrlen()} & Returns the length of a \tok{far} string. \\
\fct{\_fstrchr()} & Locates a character within a \tok{far} string. \\
\fct{\_fstrcpy()} & Copies a \tok{far} string into another one.
	Does not support overlapped memory blocks.\\
\fct{\_fstrcmp()} & Compares a \tok{far} string with another one
	case-sensitively. \\
\fct{\_fstrcmp()} & Compares a \tok{far} string with another one
	case-insensitively. \\
\end{tabTS}
