$Id: README.TXT 1.9 1999/12/13 02:23:46 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) 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.1) All functions to scan the command line arguments for options. 5.2) getopt(): original - accept two option classes: argumented, non-argumented - options are marked with SWCHAR (hard coded) - arguments are delimited by ARGCHAR (hard coded) - arguments must not be empty - options must not fall into both classes - a SWCHAR within an option string is ignored - the '?' invokes helpScreen() - an switch char without following options returns '?' 5.3) getopt1(): as getopt() except: - options may fall into more than one option class - arguments may be empty - options are marked either by SWCHAR or SWCHAR1 (hard coded) - arguments are marked either by ARGCHAR or ARGCHAR1 (hard coded) - non-argumented options may be controlled by a boolean state character '+' or '-' (hard coded). The character must immediately follow the switchar, e.g.: /+x but not: /x+y 5.4) getopt2(): as getopt1() except: - third option class: /x* with: / an option indicator x the option character * the option argument (may be empty) This class is overridden by the argumented class, if the first character of '*' is an argument indicator. - If '?' is a 3rd class option, it does not invoke hlpScreen() 5.5) getoptG(): generic getopt(), as getopt2() except: - option indicator characters stored in a string - argument indicator characters stored in a string - boolean state characters stored in a string - If '?' is a member of opt3rd or optBOOL, it does not invoke hlpScreen() - controlled by flags: -- completely handled options will be marked as empty options. A '\0' character will be placed behind the switch character. -- skipping of non-option command line arguments Those two flags allow to completely scan the command line for options, then, in a second pass, process the non-option arguments. -- skipping of following command line arguments This allows options in tar-style: tar -cBf 512 dummy.tar files where "512" belongs to "-B",& "dummy.tar" to "-f". While processing the options of "-cBf" the variable optFlags can be incremented to indicate, that the next argument(s) are already used up. Setting (optFlags & GETOPT_ADVANCE) to "2" causes the two arguments "512" and "dummy.tar" to be skipped and getoptG() will continue scanning for options with the argument "files". There can be a maximum of GETOPT_ADVANCE arguments to be skipped! -- If GETOPT_NOHELPSCREEN is set, '?' does not invoke hlpScreen() 5.6) variables: - optind: index into argv[] array - optchar: index into argv[optind][] array - optarg: either the address of argument of an argumented option or the address of a set/unset modifier or NULL, if non set. 5.7) control variables/defines for getoptG() only: - opt1st: non-argumented options - opt2nd: argumented options - opt3rd: special argumented options - optSWCHAR: switch characters, defaults to "/=" - optARGCHAR: argument characters, defaults to ":=" - optBOOL: set/clear characters, defaults to "+-" - optFlags: Hold the following flags (all initially cleared): -- GETOPT_NOHELPSCREEN: don't invoke hlpScreen() on '?' -- GETOPT_IGNORE: skip non-option arguments -- GETOPT_MARKEMPTY: place '\0' behind switchar to mark the argument as used -- GETOPT_ADVANCE: skip (optFlags & GETOPT_ADVANCE) arguments the next time getoptG() is called 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 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 , 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.