The copyright holder (Laszlo Menczel) hereby grants you the additional right to statically link the MUTIL library to your application and distribute the resulting binary executable under a licence of your own choice.
The above clause does not free you from the obligation of providing (upon request) to the recipients of your binary executable the full source code of the MUTIL library used for building said executable. In the documentation accompanying your binary executable you must inform the end user that the source code of the library is available upon request.
If you distribute modified versions of the MUTIL library you must also grant end users the additional right of static linking as described above.
This library is a collection of assorted utilities I have developed while working on various software projects. This is general purpose stuff (written in C) which can be quite useful (and is frequently needed) but is missing from standard C libraries. Among other goodies, you will find here improved versions of the 'fgets', 'atoi' and 'atof' functions of Glibc, functions for parsing command line arguments and INI files, and an easy to use (high-level) file globbing function.
The library can be used under Win32 and Linux. Both versions have been developed using the GCC compiler system (MinGW under Win32). I guess that other compilers could be used, but I have no motivation to do anything about this. Feel free to port the library to any compiler of your choice.
Error handling in the library is performed according to the following general principles:
The following error codes are defined in 'mutil.h':
NO_ERROR operation was successful MUTERR_BAD_ARG bad function argument MUTERR_ALLOC memory allocation failed MUTERR_FILE file open error MUTERR_FILE_TYPE file type incorrect MUTERR_FILE_READ error when reading file MUTERR_FILE_WRITE error when writing file MUTERR_TOO_MANY too many items MUTERR_TOO_FEW not enough items MUTERR_BAD_TOKEN bad token MUTERR_RANGE range error MUTERR_EMPTY no data (empty) MUTERR_TYPE type error MUTERR_SIZE size error MUTERR_END_OF_STR unexpected end of string MUTERR_TIMEOUT operation timeout MUTERR_DLL_LOAD cannot load the DLL specified MUTERR_NOT_FOUND object not found MUTERR_NOT_READY the device is not ready or not initialized MUTERR_DIR directory not found MUTERR_SYSINFO cannot obtain requested system information MUTERR_OVERFLOW buffer overflow MUTERR_PARTIAL_READ only part of the object was retrieved MUTERR_END_OF_FILE end of file reached MUTERR_WIN32PROC WinAPI error: process creation failed MUTERR_WIN32WAIT WinAPI error: cannot wait on specified object MUTERR_WIN32EXITCODE WinAPI error: cannot get process exit code MUTERR_ACCESS_FILE cannot access file MUTERR_ACCESS_DIR cannot access directory MUTERR_SYSCALL system call failed MUTERR_BUSY resource is used by other process MUTERR_READ_ONLY file or directory is read-only MUTERR_BAD_INT bad integer (not a number?) MUTERR_BAD_FLOAT bad float (not a number?) MUTERR_INT_BASE invalid base for integer value MUTERR_TOO_MANY_DIG too many digits MUTERR_NO_DIG no digits MUTERR_NOT_DIG not a digit MUTERR_EXTRA_CHAR extra characters in numeric string MUTERR_EXP_RANGE exponent out of range MUTERR_NO_EXP no exponent value specified MUTERR_BAD_EXP bad exponent value MUTERR_TOO_MANY_DOTS too many decimal points MUTERR_PAR_FILE cannot open/read config file MUTERR_PAR_NAME parameter name NULL or empty MUTERR_PAR_TYPE invalid parameter type MUTERR_PAR_VAR pointer to parameter target variable is NULL MUTERR_PAR_SIZE size of specified string buffer < 1 MUTERR_PAR_INDEX bad parameter index MUTERR_PAR_VALUE no value specified for a parameter MUTERR_PAR_CONV error when converting numeric parameter MUTERR_PAR_LOAD at least one parameter is not loaded MUTERR_ARG_PROGNAME program name is too long to store MUTERR_ARG_SIZE argument string too long MUTERR_ARG_NAME argument not recognized MUTERR_ARG_PARAM paired argument has no value MUTERR_ARG_PARSIZE value string too long MUTERR_ARG_BAD_PARAM invalid characters in a value MUTERR_ARG_DUPLIC duplicate argument MUTERR_ARG_MISSING at least one required argument missing
There are a couple of functions for error handling, see Section 15.. The error messages retrieved by mut_errmsg are defined in 'error.c', they can be replaced by translated versions if necessary.
The version of GLIBC supplied with the MinGW system does not fully implement the functions for the execution of a program from another one. The main problem is that there is no way to wait for the child program to finish (no 'wait_pid'). This function provides the missing functionality using the Win32 system calls 'CreateProcess', 'WaitForSingleObject' and 'GetExitCodeProcess'.
Runs the program 'prog' as a separate process. 'prog' must be a complete command line containing the name (path) of the program and all arguments.
The behaviour of the function after starting 'prog' is controlled by the value of 'wait' as follows:
wait == -1 waits until 'prog' terminates and returns a non-zero value wait == 0 starts 'prog' and immediately returns a non-zero value wait > 0 waits for 'prog' to terminate, but after 'wait' milliseconds returns zero and sets the error code to MUTERR_TIMEOUT
If 'wait' is set to -1, or in case if wait is non-zero and 'prog' terminates within the specified time period, the integer variable 'retval' will contain the return code of 'prog', otherwise it is set to zero. If '*retval' is NULL, the return code is ignored.
The string 'outfile' may contain a filename to which screen output from 'prog' should be redirected. If 'outfile' is NULL, 'stdout' is used. Please note that 'wait' must be -1 (wait for termination) if the output of 'prog' is redirected to a file.
Note: This function is provided for starting console mode applications. I have not tested it with GUI mode apps, it will probably fail. You have been warned :-)
Notes:
1. These functions should not be used in GUI-mode programs, only for console mode.
2. Under Linux the program using these functions should use the NCURSES library
and at the start of the program the function 'mut_kbd_init' should be called.
Initializes the NCURSES library for the keyboard input modules.
Clears the keyboard input buffer (i.e. 'mut_keypress' will return zero after this function has been called).
Returns non-zero if there is at least one character waiting in the keyboard input buffer, othwerwise returns zero.
Extracts and returns the next character waiting in the keyboard buffer. If there is no character to extract, the function will wait for input. Special key codes returned by 'mut_getkey' are defined in 'mutil.h'.
Reads characters from the keyboard input buffer and copies them to 'buf', until the RETURN (ENTER) key is pressed. Maximum 'max' characters are copied. The characters are echoed to the screen at the current cursor location (the cursor is advanced). Pressing ESC aborts input and clears 'buf'. The BACKSPACE key may be used for simple editing of the string input.
Return the sum of the elements of an array (integer or double) up to and including the element 'last_index'. In case of error the functions return zero. Since zero is a legitim sum, you should check the library error code to determine if an error indeed occurred when zero is returned.
Creates a string array, i.e. returns an array of
Discards a string array previously created by 'mut_alloc_str_array'. 'count' must match the originally specified size of array. There is no check, beware!
'array' must be defined as an array of 'count' string pointers. The function allocates 'count' new strings buffers each 'size' characters long, and stores the pointers in 'array'.
Discards the string buffers located at the pointers stored in 'array'. 'count' must match the originally specified number of buffers. There is no check, beware!
Obtains the local date and time of the system, converts it to a string and stores the result in 'buf' using the format 'month day year hour:min:sec'.
Obtains the local time of the system, converts it to a string and stores the result in 'buf' using the format 'hour:min:sec'.
Obtains the local date and time of the system, converts it to a string and stores the result in 'buf' using the format 'MM/DD/YYYY hour:min:sec'.
Obtains the local date and time of the system, converts it to a string and stores the result in 'buf' using the format 'YYYY-MM-DD-XXhYYm' where XX is the hour and YY is the minute. This is useful for creating a timestamp to be attached to e.g. filenames. 'buf' should be large enough to hold at least 18 characters.
Removes the extension (i.e. the section after the last '.' character from 's'. Assumes that 's' is a properly formed filename. If no '.' character is present, the string is not changed. The maximum length of string 's' defaults to 512 characters.
Replaces in 's' the first newline character with zero, then quits. 'mut_stripn_eol' scans maximum 'max' characters. Useful for stripping the newline from strings read by 'fgets'. Returns the position of newline replaced, or zero if failed.
Returns a pointer to the end of string 's' (i.e. to the terminating zero character) or NULL if error. 'mut_strn_end' scans maximum 'max' characters.
Removes the quotes from the beginning and end of string 's'. Assumes that the first character of 's' is a quote ("). Shifts to the left characters until another quote or the end of string is found. Replaces the closing quote with zero. Maximum 'len' characters are scanned ('len' must be at least 2).
Find the last/first occurence of character 'c' in string 's'. Return a pointer to its position, or NULL if the character is not present in 's'. Maximum 'len' characters are scanned.
Finds the first or last occurence of character 'c' in string 's' depending on the value of 'dir' (MUT_FIND_FIRST or MUT_FIND_LAST, defined in 'mutil.h'). Returns a pointer to its position, or NULL if the character is not present in 's'. Maximum 'len' characters are scanned.
Note: this is just a wrapper for 'mut_str_first' and 'mut_str_last'.
Replaces all occurences of the character 'old' in string 's' by 'new'. 'old' may be any character except zero. 'new' may be any character including zero.
Splits 's' into substrings using the characters in 'delim' as delimiter. 'delim' may be NULL in which case ' ', '\t' and '\n' are used as delimiters. If two or more delimiter characters occur in a sequence, they act as a single delimiter.
Returns an array of pointers to newly allocated buffers containing the substrings. The integer 'res' is set to the number of substrings found. If an error occurs, 'res' is set to an error code and the function returns NULL.
Don't forget to call 'mut_free_string_array()' to discard the returned array if not needed any more.
Note: The number of substrings is limited to MUT_MAX_SUB_STRINGS (defined in 'mutil.h'). If the number of substrings exceeds this value, 'res' is set to MUTERR_TOO_MANY, but the return value is a valid pointer to an array which contains pointers to the first MUT_MAX_SUB_STRING substrings found.
Scans the string 'buf' and returns an array of string pointers for each substring in 'buf' which is delimited by the character 'delim'. Returns NULL in case of error and sets the library error code as follows:
MUTERR_BAD_ARG ---> 'buf' is NULL MUTERR_ALLOC -----> cannot allocate the pointer array MUTERR_EMPTY -----> no delimiter 'delim' found in 'buf'
Converts the string 's' to an integer value using number base 'base' (MUT_BASE_BIN, MUT_BASE_DEC or MUT_BASE_HEX, these are defined in 'mutil.h'). The result is stored at address 'dest'. This is a replacement for the practically useless 'atoi' function supplied in the standard C library. This function will properly report any error which may occur during conversion.
Converts string 's' to a floating point number and stores the result at address 'dest'. Accepts different formats including scientific notation (exponent specified). This is a replacement for the rather primitive 'atof' function supplied in the standard C library. This function will properly report any error which may occur during conversion.
This function converts the data value (8, 16 or 32 bit) located at address 'data' to a binary string. The length of data is specified in argument 'len'. The string is stored in 'buf'.
Scans string 's' to find the first character which is not part of the string 'templ'. Returns a pointer to this character in the string. Returns NULL if the line is empty (no significant characters) or 'len' characters have been scanned w/o finding a significant one.
Scans string 's' to find the first character which is not a whitespace (i.e. 'space' or 'tab'). Returns a pointer to this character in the string. Returns NULL if the line is empty (no significant characters) or 'len' characters have been scanned w/o finding a significant one.
Scans the string 'buf' and extracts a 'token', i.e. a substring which is separated from other parts of the string by characters in the string 'delim'. The token is copied to 'dest'. At most 'maxlen' characters are scanned. Returns a pointer to the first character beyond the end of token, or NULL if error. 'mut_get_token_ex' processes only that part of 'buf' which is between its start and 'end'.
'delim' may be NULL in which case it defaults to 'space' and 'tab'.
When a newline '\n' or a zero character is found, it is assumed that the end of string 'buf' has been reached. These characters are also interpreted as delimiters.
Scan the string 'buf' and extracts a 'token', i.e. a substring which is separated from other parts of the string by characters in the string 'delim'. Try to convert the extracted token to an integer value using the number base 'base'. If successful, the value is copied to the integer variable 'dest'. Return a pointer to the first character beyond the end of token, or NULL if error. 'mut_parse_int_ex' processes only that part of 'buf' which is between its start and 'end'.
'delim' may be NULL in which case it defaults to 'space' and 'tab'.
When a newline '\n' or a zero character is found, it is assumed that the end of string 'buf' has been reached. These characters are also interpreted as delimiters.
Scan the string 'buf' and extracts a 'token', i.e. a substring which is separated from other parts of the string by characters in the string 'delim'. Try to convert the extracted token to a double value. If successful, the value is copied to the double variable 'dest'. Return a pointer to the first character beyond the end of token, or NULL if error. 'mut_parse_float_ex' processes only that part of 'buf' which is between its start and 'end'.
'delim' may be NULL in which case it defaults to 'space' and 'tab'.
When a newline '\n' or a zero character is found, it is assumed that the end of string 'buf' has been reached. These characters are also interpreted as delimiters.
Returns non-zero if character 'c' is legal in a filename, otherwise returns zero. This is a partial implementation of the Win32 filename rules, it allows the following special characters if compiled for Win32:
'a-z' 'A-Z' '0-9' . _ ! @ # $ % ^ & * ( ) [ ] { } = + - < > SPACE
Under Linux all characters except '/' are allowed.
Note: The tests assume ASCII character encoding.
Returns non-zero if the file 'name' exists, zero if not or in case of error (NULL pointer argument, empty file name, etc.).
Note: The function simply tries to open the file and returns non-zero if the operation succeded. Under Linux, file access permisssions may interfere (i.e. any file to which you have no access is reported as not found).
These are just wrappers for the 'unlink' and 'rename' functions in the C library. They provide error codes consistent with the error reporting system of MUTIL.
MUTERR_ACCESS_FILE --> acces denied MUTERR_BUSY ---------> file is used by another process MUTERR_READ_ONLY ----> file is read-only MUTERR_UNDEF --------> cause of error is unknown
Splits the string 's' to a path specification and a filename. These parts are copied to 'path' and 'name', respectively. 'path' and 'name' may be NULL if the corresponding part is not required. These buffers must be capable of holding MUT_MAX_PATH_LEN and MUT_MAX_NAME_LEN characters, respectively. If 's' does not contain a path or a filename, the corresponding buffer will contain the empty string "". Returns non-zero if OK, zero if the path or name part exceeds the limit imposed by the currently used OS.
Note: The '\', '/' or ':' character terminating the path part is *not* removed.
These are wrappers for 'mut_fname_split' to obtain the filename or path part of 's' alone ('mut_fname_split(s, path, NULL)' and 'mut_fname_split(s, NULL, name)').
This is an improved version of 'fgets' providing proper error checking and reporting. In case of error plain 'fgets' just returns NULL and you have three guesses what the problem may be :-)
'mut_fget_line' reads the next line of file 'f' (using 'fgetc') into the buffer 'buf'. The return value may be one of the following:
positive integer
The line was sucessfully copied, the return value is the number of characters in
the buffer w/o the terminating zero.
Notes:
1. 'f' should be opened in text mode.
2. 'buf' will always be terminated by a zero character.
Replaces '/' and '\' delimiters so that 'path' conforms to the pathname conventions of of the currently used operating system. Returns zero if no replacement was done or an error occured (check the error code pof the library), non-zero if delimiters were replaced. If 'path' is longer than MUT_MAX_PATH_LEN, it is truncated and the error code is set to MUTERR_TOO_MANY.
Checks the string 's' which is assumed to be a path to a file or directory, or a single filename. Returns non-zero if the path and name parts do not exceed the limit for the currently used operating system, otherwise returns zero.
Checks if the string 's' contains only path delimiters and legal filename characters (OS specific). Returns non-zero if yes, zero otherwise.
The file globbing module of the GNU Libc is rather primitive (or should I be more respectful and say that only low-level functionality is provided?). Anyway, if you want to obtain a decent list of files and/or subdirectories (with recursive processing of subdirectories, and preferably with all the relevant info attached), you have a lot of coding to do. The functions in this module of MUTIL will save you the coding work.
You invoke the function 'mut_glob_dir' with the appropriate arguments (see below). Information obtained by globbing is returned in a linked list of the following structures:
#define MUT_MAX_PAH_LEN 256 typedef struct flist_s flist_t; struct flist_s { int flag; // see below int count; // total number of items in 'files' int filenum; // number of file items int dirnum; // number of directory items int dirlen; // length of directory name char dir[MUT_MAX_PATH_LEN]; // name of base directory finfo_t *files; // 'finfo_t' array (see below) flist_t *next; // next structure in the list };
The following bitmasks may be used to test 'flag':
MUT_FLIST_HAS_DIR --> the list 'files' has directory entries MUT_FLIST_EMPTY ----> no items (files or directories) found MUT_FLIST_NO_MATCH -> no files matching the search pattern
Information on individual items (in the array 'files') is stored in the following structure:
#define MUT_MAX_NAME_LEN 256 typedef struct { int flag; // see below int len; // length of item name char name[MUT_MAX_NAME_LEN]; // item (file or directory) name } finfo_t;
The following bitmasks may be used to test 'flag':
MUT_FINFO_IS_DIR --> item is a directory MUT_FINFO_HIDDEN --> item is hidden
In the info array files are listed first, then the subdirectories. Both sublists are sorted alphabetically. The two special dirctories '.' and '..' are not stored.
If simple (non-recursive) globbing is requested (see 'mut_glob_dir()' below), the list returned is actually a single structure. Otherwise the order of items in the linked list follows the order of expansion of subdirectories. Consider the following directory tree:
current directory | -- dir_a | | | |-- file_a1 | | | -- file_a2 | |-- dir_b | | | |-- dir_ba | | | | | |-- file_ba1 | | | | | -- file_ba2 | | | |-- dir_bb | | | | | |-- file_bb1 | | | | | -- file_bb2 | | | |-- file_b1 | | | -- file_b2 | |-- file_1 | -- file_2
If you perform recursive globbing, then follow the resulting linked list and display the contents of the structures you get:
file_1 structure 1 file_2 dir_a\ dir_b\ file_a1 structure 2 file_a2 file_b1 structure 3 file_b2 dir_ba\ dir_bb\ file_ba1 structure 4 file_ba2 file_bb1 structure 5 file_bb2
This function performs file & directory name globbing in the specified directory. The following arguments are accepted:
GLOB_SIMPLE --> do not enter subdirectories GLOB_RECURS --> recursively process subdirectories
Returns a pointer to a new linked list of flist_t structures if the operation was successful. In case of a simple (non-recursive) search the list contains a single member only.
A valid pointer return means that the globbing operation was completed w/o error. It *does not* automatically mean that there is useful data in any or all of the structures in the list. You should check the 'flag' fields of the structures for non-fatal errors like the directory being empty or containing no files matching the search pattern (see the description of the flist_t type for useful bitmasks).
In case of error the function returns NULL. The error code of the library is set to one of the following values:
MUTERR_BAD_ARG -----> 'mode' is unknown MUTERR_ALLOC -------> memory allocation error MUTERR_SYSCALL -----> a system call (getcwd, chdir, etc.) failed MUTERR_ACCESS_DIR --> access denied when opening a (sub)directory MUTERR_OVERFLOW ----> a pathname is longer than MUT_MAX_PATH_LEN
The error code can be obtained by mut_last_error.
Discards the linked list of flist_t structures starting with the item to which '*list' points. If a NULL pointer is passed, error (zero) is returned. If '*list' is NULL, nothing is done. Sets '*list' to NULL after the structures have been destroyed.
Constructs a list of all items in the structures of the linked list 'list'. Returns a newly allocated buffer which contains a sequence of strings, one for each item (file or directory). The strings contain the names of the items.
The strings are separated by the character 'delim' (pass zero for normal string termination). The buffer is always terminated by a zero, regardless of the value of 'delim'.
'mode' controls the content of buffer as follows:
MUT_FLIST_ALL ---> both files and directories MUT_FLIST_FILES --> files only MUT_FLIST_DIRS ---> directories only
The flag 'MUT_FLIST_PATH' may be ORed to 'mode' to get a list in which filenames are prepended by the appropriate directory name.
Passing zero is equivalent to MUT_FLIST_ALL.
This is a convenience function to test if an 'finfo_t' item is hidden or not. Returns 1 if yes, zero if not, a negative error code if 'f' is NULL.
This is a convenience function to test if an 'finfo_t' item is a directory or not. Returns 1 if yes, zero if not, a negative error code if 'f' is NULL.
The functions described above are sufficient for most of the normal tasks involved in file globbing. For those of you who like to experiment, the library provides the following low-level functions.
Returns a pointer to a newly allocated flist_t structure.
Adds the structure 'f' to the end of the linked list starting with 'target'. Cannot add an element to an empty list.
Inserts 'f' into the linked list right after the structure 'pos'.
This function obtains information on the items in directory 'dir' and stores it in the structure 'f'. 'dir' may be NULL, in this case the current directory is used.
The wildcard pattern 'patt' is used for filtering file items in the usual way (however, directory items are *not* filtered). Passing NULL or "" means to use '*'.
In the 'finfo_t' array of 'f' files are stored first, followed by directories. Both sublists are sorted alphabetically (ascending order).
Possible error codes:
MUTERR_BAD_ARG -----> unknown 'mode' value or 'dir' is longer than MUT_MAX_PATH_LEN MUTERR_OVERFLOW ----> name of an item is longer than MUT_MAX_NAME_LEN MUTERR_SYSCALL -----> a system call (getcwd, chdir, etc.) failed MUTERR_ACCESS_DIR --> could not access the directory specified
In order to use the command line parsing utility of this library, the arguments must be supplied according to the rules described below:
Arguments to search for are specified using the following structure:
typedef struct arg_list { int type; // see below int req; // see below char *templ; // argument string to search for void *dst; // pointer to integer flag or string buffer int found; // set to non-zero if this argument was found } arglist_t;
'type' may be 'MUT_ARG_SWITCH' or 'MUT_ARG_PAIRED'
'req' may be 'MUT_ARG_REQUIRED' or 'MUT_ARG_OPTIONAL'.
Note: When initializing the defining structure, omit the '-' minus character from the beginning of the string used for the initialization the field 'templ'! E.g. for the definition of the switch '-x' use 'x' only.
The list of allowed and/or required arguments is specified using an array of such structures. Please note that there must be an excess terminating element at the end of the array, and its type must be set to MUT_ARG_END (types are defined in 'mutil.h').
Parses the array of command line arguments 'argv' which contains 'argc' entries (including the name of program at index 0). 'argc' and 'argv' must be the arguments passed by the OS to the executing program.
First the name of program in argv[0] is extracted and stored in 'progname' (but only if 'progname' is not NULL).
The argument string vector is then searched for the template strings specified in the array 'arglist'. If a template is found, the following actions are carried out:
The function returns non-zero if the arguments were successfully parsed, zero in case of error. An appropriate error message can be retrieved by calling the function mut_errmsg.
This function can be used for the initialization of variables or arrays of variables (integer, floating point number or string) with values loaded from a configuration file.
Configuration files must be ASCII text files. Each line must contain either a comment starting with the character '#' in position zero, or a value specification in one of the following formats:
name value name[x] value
where 'name' is the description of the parameter, '[x]' is an optional index ('x' must be a non-negative integer) and 'value' is the parameter's desired value. These two fields must be separated by at least one space character. Additional space characters are allowed within the lines in any position (but see the note on string parameters below). For example:
DataDirectory c:/foobar/data ProgName Widget Factory vers. 1.0 ErrorLimit 1.0e-005 MaxUser 16 Day[0] Monday Day[1] Friday
Note: In the case of string parameters, all characters up to the end of line (including any spaces) are copied to the destination variable.
Parameters to be loaded must be specified in an array of 'config_t' structures:
typedef struct config_info { int type; // see below char *name; // name to search for in the INI file void *var; // pointer to the variable to initialize int len; // maximum length if string variable int error; // set to non-zero if an error occurs int loaded; // see below } config_t;
The array must be terminated with a 'config_t' structure in which 'type' is set to 'MUT_INI_END'.
'type' indicates what kind of variable is to be initialized as follows:
MUT_INI_INT MUT_INI_FLT MUT_INI_STR ----> integer, double or string variable MUT_INI_AINT MUT_INI_AFLT MUT_INI_ASTR ---> integer, double or string array
'name' is the name (path) of the configuration file. 'par' is an array of 'config_t' structures (see above). The function returns non-zero if all parameters have been loaded successfully, zero in case of error. In each structure, the field 'loaded' will indicate how many times the corresponding variable has been updated (for arrays it will show how many array elements have been initialized). The field 'error' will be non-zero if any error occured when processing the value specified in the config file.
Please note that any line in the config file which does not have a corresponding 'config_t' structure in the list is silently ignored. If there is more than one line for a parameter, the value of the corresponding variable will be the one specified on the last line found. Cases of multiple initialization can be identified by checking the values of the 'loaded' fields of the structures.
Together with 'printf', the functions in this module constitute the only debugger I ever need :-)
These functions print their argument and wait for the user to press ENTER.
Sets the name of logfile to use to 'name'. If 'name' is NULL, the name of logfile is reset to 'deafult.log'.
Sets the maximum number of logged messages to 'count'. If count is < 0, the limit is set to 1. If it is > MAX_LOG_COUNT (#defined in 'mutil.h'), the limit is set to MAX_LOG_COUNT.
Set tracing level to 'level. This value should be between zero and 2 (inclusive). This value controls whether the functions 'mut_logtrace' and 'mut_logtrace2' write to the logfile or not (0 = no tracing, 1 = mut_logtrace active, 2 = both active).
These functions write their arguments to the logfile depending on the value set by 'mut_settrace' (see above).
Starts the logging system, subsequent messages are written to the file 'name'.
Stops logging, log functions (see below) are inactivated.
If logging is curently active, appends 'msg' to the previously designated logfile. The file is opened and closed for each transaction, to avoid the corruption of file content in case of a program crash.
If logging is curently active, writes the values of variables as indicated in the 'format' string and the following arguments ('printf' style) to the previously designated logfile. The file is opened and closed for each transaction, to avoid the corruption of file content in case of a program crash.
The functions described below can be used for obtaining the error code and human readable info on the cause of errors.
Returns the value of the variable '__mut_errcode', which has the value set by the last called library function.
Returns a pointer to a string which describes the error corresponding to error code 'code'. This is a static string, do not attempt to free!
Appropriate Makefiles and build scripts are present in the directories 'build-mingw' and 'build-linux'. They should work 'out of the box'. In case of the Win32 version you must set an environmental variable to reflect your configuration (see the batch file 'mk.bat').
Precompiled versions of the library are included in the directories 'bin\linux' and 'bin\win32'. After compiling the library you can save a copy of the new version by running the script 'save(.bat)' from the build directory. The library can be installed by running the 'inst(.bat)' script from 'bin\linux' or 'bin\win32'.
Most of the functions in the library depend only on Glibc and (under Linux) on 'libm' (math libary). The keyboard module under Linux needs the 'ncurses' library. Programs using the library should include the header file 'mutil.h' and link to the libraries listed above. That's all.
I have tested only the static version of the library. Since it is rather small (the Linux lib is just over 40K), linking the static version does not increase the size of applications by a significant amount. In fact, shared versions (DLL or .so) may not work correctly, since I paid no attention to this aspect when I wrote the code. The library is most probably not thread-safe. I have plans to add code to protect the relevant variables by mutexes. There may be a couple of functions which are not re-entrant.