The functions in this module allow easy retrieval, addition, deletion and storage of information from user-editable plain-text config files, much like the Windows WIN.INI files.
Available functions:
ReadConfig
: Read config file given full name.
ReadMyconfig
: Read config, given program name.
GetConfigString
: Retrieve a string from config data.
GetConfigInt
: Retrieve an integer from config data.
GetFirstEntry
: Used to scan sections: init scan.
GetNextEntry
: Used to scan sections: continue scan.
GetCfgLine
: Retrieve line number info during scan.
GetFirstSection
: Scan file for sections: init scan
GetNextSection
: Scan file for sections: continue scan
AddConfigString
: Add entries to a config file
ReplaceConfigString
: Replace a keys value in a config file
DeleteConfigString
: Delete a config entry
WriteConfig
: Write a config file back to disk
ReadConfig
Reads a config file and stores the settings in an internal
database for later retrieval. #include "pal.h"
void ReadConfig(char *CfgName); CfgName - the name of the config file - including the
extension. ReadConfig has no return value - if the file is not found,
that is not considered an error, since your program may
still use the default value system supported by the
GetConfigXXX functions. If you need a mandatory entry in
the config file, you can detect its absence - see
GetConfigString for a tip how this can be done.
An extra section is created in memory when the file is read.
This section is called the "Prolog" section. The actual section
name is the fully qualified file specification of the config
file. This section header is NOT written back to the file. It
is used solely to keep track of and maintain comments in the
config file, prior to the first real section. void main(void)
{
ReadConfig("MYAPP.CFG"); /* Load config data for future use */
/* ... */
ReadMyConfig
This function is very similar to ReadConfig, but is able to infer the
name of the config file from the full pathname of your application.
This is available as the argv[0] argument to C programs. Whatever
your program is called and wherever it is stored, using this
device will find the config file located in the same directory under
the same name. #include "pal.h"
void ReadMyConfig(char *MyName);MyName - the name of your application, including the '.EXE' extension.
ReadMyConfig has no return value - if the file is not found,
that is not considered an error, since your program may
still use the default value system supported by the
GetConfigXXX functions. If you need a mandatory entry in
the config file, you can detect its absence - see
GetConfigString for a tip how this can be done.
An extra section is created in memory when the file is read.
This section is called the "Prolog" section. The actual section
name is the fully qualified file specification of the config
file. This section header is NOT written back to the file. It
is used solely to keep track of and maintain comments in the
config file, prior to the first real section. int main(int argc, char *argv[])
{
/* read config file, whatever program is called and
wherever it is stored. */
ReadMyConfig(argv[0]);
/* ... */
}NewConfig
Creates a new config file in memory. Once created you can add to
it as usual. #include "pal.h"
void NewConfig(char *CfgName); CfgName - the name of the config file - this does NOT have to be
a real file name. It is used only for the Prolog
section. NewConfig has no return value
An extra section is created in memory when the file is read. This
section is called the "Prolog" section. The actual section name
is what you passed in in CfgName This section header is NOT
written back to the file. It is used solely to keep track of and
maintain comments in the config file, prior to the first real
section. void main(void)
{
NewConfig("MYAPP.CFG"); /* Create config file for future use */
/* ... */
GetConfigString
GetConfigString will retrieve a string value from the config file,
given a section name and a key. If the section and/or the key does
not exist, it will return a default value that you provide. #include "pal.h"
char *GetConfigString(char *Section, char *Key, char *Default); Section - The name of the section (in angular brackets in the CFG)
where you want your value retrieved from.
Key - The key, i.e. the left hand side of the assignment in the
CFG file.
Default - what should be returned if the section/key pair cannot be
found. A pointer to the value, or the default. Note that you should not
write to this pointer since its storage belongs to the config
routines. Copy the string to a local buffer if you need to modify
it. You can also pass NULL as default string. This is useful to detect
the absence of a certain section/key pair in the config file. (Or
the absence of the config file altogether) If you pass NULL as
default value and get NULL as return value, you can be certain that
the section/key was not present - GetConfigString will never return
NULL otherwise. char *SerialCode;
SerialCode = GetConfigString("User", "Serial", NULL);
if(SerialCode == NULL) {
FatalExit("No 'Serial =' in [User] section of CFG file);
}GetConfigInt
GetConfigInt will retrieve a integer value from the config file,
given a section name and a key. If the section and/or the key does
not exist or is not valid, it will return a default value that you
provide. #include "pal.h"
int GetConfigInt(char *Section, char *Key, int Default); Section - The name of the section (in angular brackets in the CFG)
where you want your value retrieved from.
Key - The key, i.e. the left hand side of the assignment in the
CFG file.
Default - what should be returned if the section/key pair cannot be
found. Note that 'Default' is an int here. There is no error
condition, the default is returned if the entry does not
exist or is not valid. The integer value, or the default. (If the section/key pair does
not exist or if the value is syntactically wrong) GetConfigInt can also handle hexadecimal and octal values. It assumes
hex when a value starts with 0x or 0X. Octal is assumed for values
starting with a zero. int ComBase;
/* Get COM base address */
ComBase = GetConfigInt("SerialPort", "Address", 0x3f8);GetFirstEntry
Used to scan all entries of a given section - initiates scan. Returns
a pointer to the first value string if the section exists, or NULL if
it does not. Can also return a pointer to the key. #include "pal.h"
char *GetFirstEntry(char *Section, char **pKey); Section - The name of the section you want to scan.
pKey - a pointer to a string pointer - if not NULL, will be
set to point to the first key string if found. Will return a pointer to the first value in the section, or NULL if
the specified section/key pair does not exist. GetFirstEntry and GetNextEntry use internal static variables to
store state information. You can only have one active
GetFirst/NextEntry loop at a time. (That is, in such a loop, you
can't call a function that itself uses these routines)See the GetNextEntry description for a complete example.
GetNextEntry
Returns the next entry in a section scan. If char **pKey is not NULL,
the pointer *pKey will be set to point to the key string too. #include "pal.h"
char *GetNextEntry(char **pKey); pKey - a pointer to a string pointer - if not NULL, will be
set to point to the next key string if found. Will return a pointer to the next value in the section, or NULL if
there is no next value. (i.e. you have retrieved the last one) GetFirstEntry and GetNextEntry use internal static variables to
store state information. You can only have one active
GetFirst/NextEntry loop at a time. (That is, in such a loop, you
can't call a function that itself uses these routines) This program will scan and print all key/name pairs of the 'Printer'
section in 'SETUP.CFG'. It also illustrates a typical GetFirst/Next
loop.
#include <stdio.h>
#include <stdlib.h>
#include "pal.h"
void main(void)
{
char *Key;
char *Value;
ReadConfig("SETUP.CFG");
if(Value = GetFirstEntry("Printer", &Key)) do {
printf("The key %s has the value '%s'", Key, Value);
} while(Value = GetNextEntry(&Key);
else printf("Section 'Printer' not found or empty\n");
DiscardConfig();
}GetFirstSection
Used to scan all sections of a given file - initiates scan. Returns
a pointer to the first section string if a section exists, or NULL if
it does not. #include "pal.h"
char *GetFirstSection( void ); Will return a pointer to the first section in the file, or NULL if
no sections exist. GetFirstSection and GetNextSection use internal static variables to
store state information. You can only have one active
GetFirst/NextSection loop at a time. (That is, in such a loop, you
can't call a function that itself uses these routines)
An extra section is created in memory when the file is read.
This section is called the "Prolog" section. The actual section
name is the fully qualified file specification of the config
file. This section header is NOT written back to the file. It
is used solely to keep track of and maintain comments in the
config file, prior to the first real section.See the GetNextSection description for a complete example.
GetNextSection
Returns the next section in a config file scan.
#include "pal.h"
char *GetNextSection( void ); Will return a pointer to the next section in the config file, or NULL if
there is no next section. (i.e. you have retrieved the last one) GetFirstSection and GetNextSection use internal static variables to
store state information. You can only have one active
GetFirst/NextSection loop at a time. (That is, in such a loop, you
can't call a function that itself uses these routines)
An extra section is created in memory when the file is read.
This section is called the "Prolog" section. The actual section
name is the fully qualified file specification of the config
file. This section header is NOT written back to the file. It
is used solely to keep track of and maintain comments in the
config file, prior to the first real section.
This program will scan and print sections in the config file 'SETUP.CFG'.
It also illustrates a typical GetFirst/Next loop.
#include <stdio.h>
#include <stdlib.h>
#include "pal.h"
void main(void)
{
char *Section;
ReadConfig("SETUP.CFG");
if(Section = GetFirstSection()) do {
printf("The section is %s\n", Section);
} while(Section = GetNextSection();
else printf("No Sections found\n");
DiscardConfig();
}GetCfgLine
Returns, for the last entry retrieved via GetFirstEntry/GetNextEntry,
the line number of the config file this entry was defined on - useful
if you need to output line number information in an error message. #include "pal.h"
int GetCfgLine(void); printf("The last line was %d\n", GetCfgLine());AddConfigString
This function will add a new key=value pair to the currently opened
config file. It will search for the Section provided and if found add
the new pair as the last entry in that section. If the Section dows
not exist, it will be created and the entry added to it.
AddConfigString does not check to see if there is another key of the
same name already there. This allows multiple values with the same
key. If you need to just replace the value for a key use
ReplaceConfigString. #include "pal.h"
void AddConfigString(char *Section, char *Key, char *Value ); char *Section - Section header in config file. Do not include the
surrounding [].
char *Key - Key of the key=value pair. If this is a NULL string
("") then the value takes on a special meaning.
char *Value - Value of the key=value pair. If Key is a NULL string
("") then if value starts with a ; a comment is
inserted in the config file. If value is also a NULL
string then a blank line is inserted in the config
file.None
This sample reads in the config file "Setup.Cfg", adds the
printer=lpt1: pair to the DEVICES section, writes the file to disk,
and cleans up the storage that was allocated for the file.
#include "pal.h"
void main(void)
{
ReadConfig("SETUP.CFG");
AddConfigString("DEVICES","printer","lpt1:");
WriteConfig("SETUP.CFG")
DiscardConfig();
}ReplaceConfigString
This function will replace the value from an existing key=value pair
if it exists in a config file. If the key does not exist it will be
added similr to AddConfigString().
#include "pal.h"
void ReplaceConfigString(char *Section, char *Key, char *Value );
char *Section - Section header in config file. Do not include the
surrounding [].
char *Key - Key of the key=value pair. This is the value
searched for in the given Section.
char *Value - Value of the key=value pair.None
This sample reads in the config file "Setup.Cfg", replaces the
printer keys value with the value lpt2: in the DEVICES section,
writes the file to disk, and cleans up the storage that was allocated
for the file.
#include "pal.h"
void main(void)
{
ReadConfig("SETUP.CFG");
ReplaceConfigString("DEVICES","printer","lpt2:");
WriteConfig("SETUP.CFG")
DiscardConfig();
}AddConfigInt
This function will add a new key=value pair to the currently opened
config file. It will search for the Section provided and if found add
the new pair as the last entry in that section. If the Section dows
not exist, it will be created and the entry added to it.
AddConfigInt does not check to see if there is another key of the
same name already there. This allows multiple values with the same
key. If you need to just replace the value for a key use
ReplaceConfigInt. #include "pal.h"
void AddConfigInt(char *Section, char *Key, int Value ); char *Section - Section header in config file. Do not include the
surrounding [].
char *Key - Key of the key=value pair.
int Value - Value of the key=value pair.None
This sample reads in the config file "Setup.Cfg", adds the
printers=1 pair to the DEVICES section, writes the file to disk,
and cleans up the storage that was allocated for the file.
#include "pal.h"
void main(void)
{
ReadConfig("SETUP.CFG");
AddConfigInt("DEVICES","printers=,1);
WriteConfig("SETUP.CFG")
DiscardConfig();
}ReplaceConfigInt
This function will replace the value from an existing key=value pair
if it exists in a config file. If the key does not exist it will be
added similr to AddConfigString().
#include "pal.h"
void ReplaceConfigInt(char *Section, char *Key, int Value ); char *Section - Section header in config file. Do not include the
surrounding [].
char *Key - Key of the key=value pair. This is the value
searched for in the given Section.
int Value - Value of the key=value pair.None
This sample reads in the config file "Setup.Cfg", replaces the
printers keys value with the value 2 in the DEVICES section,
writes the file to disk, and cleans up the storage that was allocated
for the file.
#include "pal.h"
void main(void)
{
ReadConfig("SETUP.CFG");
ReplaceConfigString("DEVICES","printers",2);
WriteConfig("SETUP.CFG")
DiscardConfig();
}DeleteConfigString
Deletes a ConfigEntry. If Section is found then the action depends on
Key. If Key is NULL then the complete section is removed. If Key is
provided and is not found nothing is done. If Key is found then the
action depends on Value. If Value is NULL then all Matching keys are
deleted. If Value is provided and it is not found then nothing is
done. If Value is provided and found it is deleted. #include "pal.h"
int DeleteConfigString(char *Section, char *Key, char *Value);parm - parm description
Number of lines/entries deleted.
Section must be provided and found or nothing is done.
This sample reads in the config file "Setup.Cfg", deletes the printer
key that has a value of lpt2: in the DEVICES section, writes the file
to disk, and cleans up the storage that was allocated for the file.
#include "pal.h"
void main(void)
{
ReadConfig("SETUP.CFG");
DeleteConfigString("DEVICES","printer","lpt2:");
WriteConfig("SETUP.CFG")
DiscardConfig();
}WriteConfig
Write the current Config file data from memory to a file.
#include "pal.h"
int WriteConfig(char *CfgName); CfgName - the name of the config file - including the
extension.
1 = Success, 0 = Failure
All comments and blank lines from the original config file are
preserved. This sample reads in the config file "Setup.Cfg", replaces the
printer keys value with the value lpt2: in the DEVICES section,
writes the file to disk, and cleans up the storage that was allocated
for the file.
#include "pal.h"
void main(void)
{
ReadConfig("SETUP.CFG");
ReplaceConfigString("DEVICES","printer","lpt2:");
WriteConfig("SETUP.CFG")
DiscardConfig();
}DiscardConfig
Call this function when you don't need access to the config data
any more. You must again load a config file before you may
retrieve data again. #include "pal.h"
void DiscardConfig(void);See the GetNextEntry description for a sample call to DiscardConfig.