$Id: README.TXT 1.10 2001/02/27 01:29:38 ska Exp ska $

These are supplemental functions, currently covering:
	0) others (anything else)
	1) environment handling (env_*.c)
	2) MCB handling (mcb_*.c)
	3) far memory access for Micro-C (f*.c)
	4) additional functions for longmath Micro-C only (long*.c)
	5) getopt() functionality (getopt*.c)
	6) filename functions (dfn*.c)
	7) dynamic string functions (dstr*.c, dmem*.c)
	8) <stdio.h> replacements (ff*.c, ee*.c)
	9) memory allocation functions with program termination (gm_*.c)
	10) SUPPL internal message handling (msgs.h, msgs.lng, NLS\*, erfc*.c)
	11) NLS information (cntry.*, nls*.*)
	12) Secure string functions (str_func.dat, sstr.h, stfc_*.c, sstr.src)
	13) appName subsystem (app*.*)
	14) Command line / INI file parser (cfg*.c)
	15) syslog (syslog*.*)
	16) debug support files (dbg*.c suppldbg.h)

The current state is:
+ supported in the sense "used by the author": Micro-C v3.15 (MC)
	& Borland C v5 (BC)
+ compiles under: Pacific C (Hi tech C) v7.51 (PAC), Watcom C v10.6 (WC)
+ should work with: Borland C pre-v5
+ I strongly recommend to update to Micro-C v3.15, however, expect a change
	int the options of CC.COM.
Functions not dedicated for a particular compiler will be compiled with
it, too, but they result in an empty OBJ file (only containing the
module header and trailer and the debug info). No program size or
symbols are located in them.

Overview about what to compile with what compiler:
	*.C	all compiler, some files will produce an empty output
	*.ASM	Micro-C only
	*.AS	Pacific C only
Note: These patterns might change in the future!

When making the library via DMAKE, LIB will possibly warn for not found
OBJ files. This sucks but it seems that the Make rule is incorrectly
informed that all prerequisites are out-of-date.

NOTE: DON'T FORGET TO GENERATE/LINK THIS ARCHIVE WITH CASE-SENSITIVE
symbols enabled for both: librarian and linker! Otherwise you could end
up in an infinite loop!

Notes:
0.1) ctrlbrk.c: ctrlbrk(fct)
	cb_catch.asm: _cbreak_catcher	(companion for ctrlbrk())	Micro-C only!
	pac_cbc?.as: _cbreak_catcher_??	(companion for ctrlbrk())	PAC only!
	Installs a hook on the DOS called ^Break interrupt to call the function
	fct. If fct() returns with a zero value, the current program will be
	terminated by DOS. longjmp() should be possible within fct().
0.2) poked.c: poked(seg,ofs,dword)
	pokedd.c: pokedd(seg,ofs,hi,lo)
	 peekd.c: peekd(seg,ofs,&dword)
	peekdd.c: peekdd(seg,ofs,&hi,&lo)
	dpeekb.c: dpeekb(tbl, idx) [ dpeekc(tbl, idx) ]
	dpeekw.c: dpeekw(tbl, idx)
	Peeking/poking double word values from/into memory, *d() uses the
	dword structure; *dd() two word values.
	The peek*() functions return 0, if the peek()'ed value is zero.
	The pointers in the *dd() function maybe NULL; in this case the
	particular value is not copied.
	The peekdd() function return in Bit 0, if the *hi value is non-zero;
	and in Bit 1, if the *lo value is non-zero.
	The dpeek?() functions use a (fartbl) == (dword) or (char far*)
	to address the memory.
0.3) mem*.c, st*.c:	String handling functions for Micro-C/Pacific C:
	stpcat.c: stpcat(): Concats two strings and return the end address
	strtol.c: strtol(): Transforms a number in ASCII notation into its
		binary interpretation. Various radixes and C-style numbers
		are supported.
	memicmp.c: memicmp(): as stricmp(), but for a memory block
0.4) dosalloc.c: DOSalloc(): Allocate a chunk of memory via the DOS API
		and automatically link in UMB chain and set the allocation
		strategy. Or return largest available block of memory.
	dosfree.c: DOSfree(): Free an allocated chunk.
	dossize.c: DOSresize(): Resize an allocacted chunk.
	byte2par.c: BLK_byte2para(): Calculate the number of paragraphes needed
		to hold an amount of bytes (both (unsigned) range).
0.5) addu.c: addu(): Performs a += operation and returns, if an overflow
	occured.
0.6) setdisk.c/getdisk.c: setdisk()/getdisk() for PAC.
0.7) getbdisk.c: getbootdisk(): return the boot drive; may fail

1.1) The implementation does not make use of far pointers, rather it
	addresses via the segment:offset pair. To access the far memory
	the peek*() functions or the _fmem*()/_fstr*() functions are
	used.
1.2) There is no getenv() function. This is because this function differs
	between Micro-C and other compilers, but is used internally in the
	C libraries. Use the cpyenv() function instead.
1.3) The functionality covers both the environment strings and the additionial
	string area at the end.
1.4) All functions assume that the string area is initialized. This is
	true for DOS 3.0+ and all environments initialized by functions of
	this library.
1.5) The size of the environment can range from 1..65535 bytes. If it is
	larger than that, the portion above 64KB is lost. If this portion is
	already in use, the behaviour of the functions, except env_check()
	and env_delete(), are undefinied.
	Note: To my knowledge MS-DOS's accessable largest environment is 32KB.
1.6) If "0" is specified as the segment address, most of the functions
	replace it by the current used environment. The env_replace() function
	will also call the env_setGlbSeg() function in this case.
1.7) No shell I know supports the string table in their environment segment.
	Because all functions assumes that the string table is present, the
	env_nullStrings() function will initialize an empty string table.

2.1) All functions to identify owners and shells of memory blocks.
2.2) Most of the functions uses the MCB number rather the "normal" memory
	handle used by DOS API functions. The macros MCB2SEG() and SEG2MCB()
	transform between both numbers.

3.1) The far memory implementation bases on the _fmem*()/_fstr*()
	functions of Borland C. Those functions require a far pointer at
	various places, which is created by the MK_FP() macro.
	The Micro-C implementation simply leaves both values in the parameter
	list, thus, passing two arguments to the _f*() functions.
	This allows a quite useful protability between MC and other compilers,
	but does not handle the question of far pointer variables themselves.
3.2) The amount of implemented functions is limited to the currently used
	functions. ;-)
3.3) _fdupstr(): Duplicate far string into local heap

4.1) All provided longmath additions assume that the numbers are dwords!
4.2) The *i()/*u() functions provide the normal *() functionality, but
	the second operand, the one which is not the result, is an (int) or
	(unsigned int) value.

5) All functions to scan the command line arguments for options.
5.0) This is a re-implementation of the three getopt() functions shipped
	with GCC, it is capable to produce the Unix-counterpart exactly,
	however except some additions of GCC (see getopt.src).
	Tweak getopt() into DOS environment some compile-time options may
	be set _prior_ to #include "getopt.src" into the C file, see below.
5.1) GETOPT.SRC: Implements the three getopt() functions and supports these
Tweaking options:
	GETOPT_LONG_ONLY: compiles getopt_long_only(), superceeds GETOPT_LONG
	GETOPT_LONG: compiles getopt_long()
	GETOPT_SILENT: no visual error reporting
	GETOPT_HELPSCREEN: if '?' is specified as option, hlpScreen() is
		invoked
	GETOPT_ERROR_WRAPPER: Instead of displaying an error message with
		"fprintf(stderr, )" it is passed to a function wrapper, which
		allows to localize SUPPL and/or use the message library.
	GETOPT_USE_DOS_NLS: Use DOS NLS to upcase characters
	GETOPT_UPCASE: Upcase characters read from argument string as
		short option; optopt remains non-upcased
	GETOPT_UPCASE_LONG: Compare long options case-insensitively
	GETOPT_LONG_ALWAYS_FULL: don't match for partial long options
	GETOPT_EMBEDDED_OPTIONS: Option signs embedded into options
		start a new option, e.g. "/opt1/opt2" is "/opt1" "/opt2"
		Options with a required argument followed by an
		embedded option sign span to the next argv[] item, e.g.:
		"/opt1/opt2:arg2" "arg1" is "/opt1:arg1" "/opt2:arg2"
		--> The dash is no embedded option sign!
	GETOPT_NEED_ARGSIGN: Short options need an argument sign
	GETOPT_NO_ARG_SPANNING: Don't use next argv[] entry as argument
	GETOPT_LONG_NO_FLAG_MEMBER: Don't include "flag" into struct option;
		This macro can/must be defined prior #include'ing "GETOPT.H".
	GETOPT_OPTSIGN_DASH: Support the dash as an option sign, but
		not as embedded option sign
	GETOPT_OPTSIGN_SLASH: Support the forward slash as an option sign
	GETOPT_ARGSIGN_EQUAL_SIGN: Support the equal sign as an
		argument sign
	GETOPT_ARGSIGN_COLON: Support the colon as an argument sign
Debugging macros:
	GETOPT_LOCAL_VARS: Defines the global variables locally
	GETOPT_JUST_VERSION_NUMBER: Just the rcsid field
Standard arguments:
	- A single option sign is interpreted as an argument, e.g. "-",
		but also: "/"
	- The same option sign twice is interpreted as an argument, too:
		e.g. "--" and "//", but not "-/"
Whitepaces:
	- getopt() does not break a command line into argument, thus, it
		does not care about whitespaces any specially.
5.2) getopt():	Scans single character options only, e.g.:
		/abcd --> /a/b/c/d --> /a /b /c /d /e
	 Uses the following tweaking options:
		 GETOPT_UPCASE
		 GETOPT_ERROR_WRAPPER
		 GETOPT_HELPSCREEN
		 GETOPT_EMBEDDED_OPTIONS
		 GETOPT_NEED_ARGSIGN
		 GETOPT_NO_ARG_SPANNING
		 GETOPT_ARGSIGN_EQUAL_SIGN
		 GETOPT_ARGSIGN_COLON
		 GETOPT_OPTSIGN_SLASH
5.3) getopt_long(): includes standard getopt(), but options prefixed by
	a doubled option sign are interpreted as long options, which are
	enumerated in the lopts[] array.
	Uses these tweaking options in additions to the ones of getopt():
		GETOPT_LONG
		GETOPT_UPCASE_LONG
5.4) getopt_long_only(): is a mixture of getopt() and getopt_long().
	Options with just one option sign prefixed are first matched as
	long options and, on failure, tried to be interpreted as exactly
	one single character option, e.g.:
		"/long_option/a//b" --> "long_option" must be a long option,
	otherwise an error occures; "a" may be either long or short option;
	"b" must be a long option.
	Uses these tweaking options in additions to the ones of getopt():
		GETOPT_LONG_ONLY
		GETOPT_UPCASE_LONG
5.5) variables:
	- optind: current index into argv[] array
	- optcur: pointer to next character of the option string
	- optarg: either the address of argument of an argumented option or
		the address of a set/unset modifier or NULL, if non set.
5.6) To support multiple getopt() cycles at once the internal variables
	of getopt() can be saved and restored using the functions
	getopt_save() and getopt_restore(). A new cycle should call
	getopt_init() to reset the internal variables to values suiteable
	to parse an argv[] array anew; this is: optcur := NULL, opterr := 1,
	optind := 1 [[Note: this supports argv[] passed by main()!!]]

6.0) The filename functions base upon dynamic memory. This allows to forget
	about the "maximal" length of some components, and thus, it can handle
	any-sized filenames, including "long" filenames of newer filesystems.
6.0.1) DFN_FILENAME_BUFFER_LENGTH: constant that defines how large the internal
	buffers are, that shall hold a fully-qualified filename. Currently it's
	512 bytes. (Twice as much as one path component in Win95 can have.)
	This value is only used, if a buffer must be created, that will
	receive a path from the operating system's API.
6.0.2) If the macro SUPPORT_UNC_PATH is defined before #include'ing the
	"dfn.h" header file, the dfn*() functions are mapped to the ones,
	which will handle UNC path specifications. You should not intermix
	calls to functions supporting and not supporting UNC paths.
	The functions assume that the path is an UNC path, if it starts
	with two backslashes; the UNC drive itself will then consume all
	characters up to the second backslash, e.g.:
		\\server\volume\path\filename.ext
		\\server\volume
	both return "\\\\server\\volume" as UNC drive spec.
	Note: To my knowledge most UNC paths are formed like that; but, of course,
	there is an exception; in MS Windows for Workgroups Network the second
	portion, called "volume" above, is missing.
6.1) dfnsplit.c: dnfsplit(): split a filename into its components. The
	filename is not (except flipping '/' -> '\\' & squeezing multiple '\\')
	altered in any way.
6.2) dfnmerge.c: dnfmerge(): merge components into a filename. It is possible
	to use "ill-formed" arguments, such as:
		dnfmerge(NULL, "a", "path\\name.ext", NULL, NULL);
	--> "a:path\\name.ext"
6.3) dfnsquee.c: dfnsqueeze(): upcase the filename, flips '/' -> '\\', squeezes
	'\\\\' -> '\\', '\\.\\' -> '\\', '\\.\0' -> '\\'.
6.4) dfnpath.c: dfnpath(): return the fully-qualifed path of the current
	working directory of the specified drive.
6.5) dfnexpan.c: dfnexpand(): expand a filename to a fully-qualified one.
	Expanding is made according a given fully-qualified path or the current
	working directory of the particular drive.
6.6) dfntruen.c: dfntruename(): return the physical access path of the given
	file. The file need not exist. The returned path is dedicated for comparing,
	if two logical access paths point to the same file in reality. The
	physical access path need not to be accessable through the DOS API calls.
6.7) dfnsearc.c: dfnsearch(): search a file through a PATH and with varying
	extensions.
6.8) dnfmatch.c: dfnmatch(): match a filename against a (DOS-wildcard) pattern
6.8) dnfmatc2.c: dfnmatch2(): match a filename against a (Win32-wildcard)
	pattern
6.9) dfnmkfil.c: dfnmkfile(): atomic (semophore) make _new_ file operation
6.10) dfnstat.c: dfnstat(): retreive file attributes
6.11) dfnwrdir.c: dfnwrdir(): probe if directory is writeble
6.12) dfnfnam.c: dfnfilename(): return a pointer of the filename component


7.0) The dynamic string functions assume that the strings are hold in the
	heap. All functions start with "Str" and the next component also starts
	with a capital letter.
7.0.1) If an argument of such function receives a dynamic string as a result,
	the function is a macro that creates a pointer from this argument, e.g.:
		#define StrRepl(dest,src) StrRepl_(&(dest),(src))
		char *StrRepl_(char **dest, char *src);
	The naming convention is the same with all functions.
	On the other hand, the pointer 'dest' is never checked for NULL and the
	pointer '*dest' must be pre-initialized, because the prior is free()'ed.
7.1) dstrchar.c: StrChar(): create a new string containing of the single letter
7.2) dstrconc.c: StrConcat(): create a new string containing the concatenation
	of all arguments.
7.3) dstrrepl.c: StrRepl(): assigns a string to a dynamic string variable.
		The string is not duplicated.
	dstrrepl.c: StrFree(): assigns NULL.
7.4) dstrstri.c: StrStrip(): strip any number of the given character from the
		end of the string.
7.5) dstrtrim.c: StrTrim(): reallocate a dynamic string to the lenght:
		(strlen(string) + 1)
7.6) toUpperx.c: toUpper(): upcases a character using the DOS NLS API.
	toUpperx.c: toFUpper(): upcases a character using the DOS NLS API
		according the upcase table for filenames.
	toUpperx.c: rereadUpcaseTable(): causes to re-read the internally stored
		pointers to the upcase tables for normal characters and for filenames.
	dstrcmp.c: StriCmp(): compare two strings case-insensitively using toUpper()
	dstrcmpf.c: _fStriCmp(): compare two far strings case-insensitively
		using toUpper()
	dmemcmp.c: MemiCmp(): compare two memory areas case-insensitively
		using toUpper()
	dmemcmpf.c: _fMemCmp(): compare two far memory areas
		case-insensitively using toUpper()
	dmemcmp2.c: MemFCmp(): compare two memory areas case-insensitively
		using toFUpper()
	dmemcmp3.c: _fMemFCmp(): compare two far memory areas
		case-insensitively using toFUpper()
	dstrupr.c: StrUpr(): Upcase the string using the toUpper() function.
	dmemupr.c: MemUpr(): Upcase the memory area using the toUpper() function.
	dstruprf.c: _fStrUpr(): Upcase the string using the toUpper() function.
	dmemuprf.c: _fMemUpr(): Upcase the memory area using the toUpper() function.
7.7) dstrdup.c: StrDup(): Duplicate string.
7.8) dstrcpy.c: StrCpy(): Copy (duplicate) a string into a variable.
7.9) dstrcat.c: StrCat(): Append a string to a string.
7.10) dstrappe.c: StrAppend(): Append a string including delimiting and quoting
	the appended string.
7.11) dstrappc.c: StrAppChr(): Append a single character to a string.
7.12) dstrtoke.c: StrTokenize(): analogeous of strtok(), but non-destructive
	dstrtoke.c: StrSaveTokens(): makes StrTokenize() re-entrant
7.13) dstrleft.c: StrLeft(): Return the left portion of a string
	dstrrigh.c: StrRight(): Return the right portion of a string
	dstrmid.c: StrMiddle(): Return a specific portion out of a string
	dstrtail.c: StrTail(): Return the last portion of a string
7.14) dstrbeg.c: StrBeg(): Compare if one string begins with another
7.15) isodigit.c: isodigit(): Check for an octal digit
	toxdigit.c: toxdigit(): Transform an hexa-decimal digit into an integer
		number
7.16) dstrcstr.c: StrCString(): Interprete C-style character string
7.17) dstrword.c: StrWord(): as StrTrim() and strip any leading and trailing
	characters
7.18) dstrchr.c: StrChr(): searches for a character within a string
7.19) dstrnlen.c: StrnLen(): return the length of a string, but ensures not to
	exceed a certain length
7.20) dstrdupe.c: StrDupe(): duplicate a part of a string

8) Various functions from the <stdio.h> package
	They begin with an uppercase 'F'. If the next character is a
	small 'f', it is suppressed.
	They usually implement the same calling interface as standard ANSI, but
	overcome some Micro-C incompatibilities.
	Seek operations return "0" (zero) on success.
	Some functions are available in two versions:
		Fy...() and Fx...(): The y-variant is the original one without
		additional functionality. The x-variant maintains a structure, so
		called "Extended Attributes". They contain (at least) two items:
		1) The fully-qualified (absolute) path of the opened file,
		2) some flags (e.g. "temporary").
		Both have exactly the same interface, especially the native pointer
		is still a valid (FILE*) pointer.
		By default the y-variants are active, thus, are available as macros
		without the 'y'/'x'. If the macro SUPPL_USE_EXTENDED_ATTRIBUTES is
		defined prior #include'ing the SUPPLIO.H header file, the x-variants
		are enabled.
	There are a bunch of E*() files that terminate the program if
	the action fails.
8.1) supplio.h: Fyclose(): standard
	Fget(): read a sequence of bytes from a file
	Fput(): write a sequence of bytes into a file
	Fpgetpos(): aquire the current file position into (fpos_t*)
	Fsetpos(): set the current file position from (fpos_t)
	Fpsetpos(): set the current file position from (fpos_t*)
	SEEK_*: Micro-C only, macros for the Fseek(,, whence)
	Fpseekc(): relative seek by (long*) offset, returns 0 on success
	Frewind(): rewind stream
	Fseeke(): seek to end of file
	Fpseek(): seek to a (long*) position
	Fgetc(): as getc()
	Fputc(): as putc()
	Ffgetc(): as fgetc()
	Ffputc(): as fputc()
	Fgets(): as fgets(): Note: Micro-C strips the '\n'
	Fputs(): as fputs()
	Fileno(): returns the file descriptor assoc. with the FILE
	Ferror(): return the error status
	Fclearerr(): clear error status
8.2) stdsetm.c: Fsetmode(): switch between read & write in R&W files
		for Mircro-C only
8.3) supplio.h/stdseki.c: Fseeki(): relative seek by (int), returns
	0 on success
8.4) supplio.h/stdsekc.c: Fseekc(): relative seek by (long) offset,
	returns 0 on success
8.5) supplio.h/stdsekc.c: Fseek(): seek by (long) offset,
	returns 0 on success
8.6) supplio.h/stdopen.c: Fyopen(): re-implements mode scanning for
	Micro-C
8.7) supplio.h/stdgetp.c: Fgetpos(): aquire the current file position
	into (fpos_t)
8.8) ffxopen.c: Fxopen(): Open a file via Fyopen() and save the extended attrs
8.9) ffxclose.c: Fxclose(): Close an open file via Fyopen() and remove the
	extended attributes
8.10) ffxinfo.c: Fxinfo(): Retrieve the extended file attributes of an
	open (FILE*) pointer
8.11) ffdopen.c/supplio.h: Fdopen(): creates a FILE* from a descriptor
8.12) ffeof.c/supplio.h: Feof(): return the EOF status (uses fseek() to
	ungetc() in Micro-C)
8.13) fftmpfil.c: Ftmpfile(): return a newly created & opened temporary file
8.14) fftmpnam.c: Ftmpnam(): create a temporary file name and create
	an empty file of that name
8.15) fftmpdir.c: Ftmpdir(): Return the current temporary directory
8.16) supplio.h/fgetpos.c: fpos_t/fgetpos()/fsetpos(): ANSI C compliant
	functions missing in PAC

9) These functions wrap malloc()/realloc() etc. and will terminate
	the program with an error message, if the action failed.
9.1) gm_chgm.c: Erealloc(): realloc() wrapper
9.2) gm_cmem.c: Ecalloc(): getmem() with zero allocated memory
9.3) gm_dup.c: Estrdup(): strdup() wrapper
9.4) gm_dupe.c: Estrdupe(): strdup() a range of the string
9.5) gm_gtmem.c: Emalloc(): malloc wrapper
9.6) gm_nwstr.c: Estrchg()/Estrchg_(): replaces an allocated string
	with the duplicate of another. Estrchg() passes &(str)
9.7) gm_res.c: Eresize(): wrapper of Erealloc(); reallocates variable
9.8) gm_ssize.c: Esetsize(): as Eresize(), but might destroy the contents
	of the memory block

10) Some functions make use of strings showed to the user, e.g.
	the E*() functions that terminate a program with the proper
	error message if an action fails.
	The current implementation uses functions Esuppl_*() to
	issue error messages onto the screen and terminate the
	program. There is one function for each error message.
	SUPPL already contains functions (created by the MKERRFCT.PL
	script from the MSGS.H) that will use the NLS information
	specified within the MSGS.LNG include file at compile-time.
	Some other strings (they start with Y_) are available as
	normal #define's as well, e.g. Y_noFnam.

	The definition is such that one can re-create all the erfc????.c
	files into another library and link it _before_ SUPPL. That
	way these functions/strings are used by SUPPL to issue errors
	or to represent certain default messages. One of such implementation
	will be maintained with the message library MSGLIB.

11) The NLS/country information functions shall provide an easy
	access to the DOS NLS API.
11.1) cntry.c: nlsInfo()/nlsNewInfo(): retrieve/return all currently
	available NLS information

12) They mimic the behaviour of the normal str*(), stp*(), and mem*()
	functions, but accept NULLs as pointers and return usual values.

	In string functions, str*() and stp*(), a NULL source is interpreted
	as "", a pointer to '\0'.
	In memory functions, mem*(), or when the NULL pointer is a destination
	address, the function is ignored and usually returns NULL.

	The functions are named equally as their counterparts, but with a
	capital letter, e.g. strcpy() --> Strcpy().

	If SUPPL_STR_REMAP is defined prior #includ'ing <sstr.h>, all
	standard names are #define'ed to their replacements, e.g.
	"strcpy()" will invoke "Strcpy()" now.

	Note: All these functions are created by the "mkstrfct.pl" Perl
	script. To add other functions, just add them to "str_func.dat"
	and re-run "mkstrfct.pl".

13) The appName subsystem provides information about the current
	application, such as its name, its folder location and its main
	executable.

14) Command line parser and INI file read/write access.
	Please refer to:
		cfg.txt - for general information
		cfg.h - infos about command line parser
		inifile.h - INI file subsystem
		inifile.txt - some thoughts of mine

15) The syslog subsystem is a simple re-write of the Unix syslog
	fitted into the DOS environment.
	See syslog.TXT or syslog.MAN.

16) The debug and logging subsystem is to help the implementor of a
	program to easily and early detect problems while implementing.
	It is not intend to be ueable within a released program.
	See SupplDBG.h
	Using the memory logging and function logging features increases
	a program by not less than 9KB.
