home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cidsam.zip
/
SAMPLE2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-28
|
20KB
|
333 lines
/*********************************/
/* NOTE */
/* */
/* This sample code has been */
/* provided by IBM. It is not */
/* warranted for any particular */
/* use or purpose. */
/* */
/* IBM releases this code into */
/* the public domain. You may */
/* use it, modify it, or */
/* incorporate it into other */
/* products without restriction. */
/*********************************/
/* SAMPLE2.C */
/* */
/* This sample program uses the high-level Response File APIs to read a */
/* response file and extract the keyword/value pairs. It is a little */
/* more complicated than SAMPLE1.C in that */
/* - it reads all the keywords and values into memory */
/* - it understands the 'list' type (keywords in the form */
/* KW = ( */
/* ListKW1 = Value */
/* ListKW2 = Value */
/* ... */
/* ) */
/* - it's output is a little more complex */
/* */
/* SAMPLE1 did not need to keep track of previously-read keywords and */
/* values; this example does. Because the keywords and values */
/* returned from the Response File APIs are *temporary* copies, this */
/* sample program has a routine RFCopyString() to make permanent copies */
/* of these strings. The sample also uses RFCopyList() to make permanent*/
/* copies of list-type values. */
/* This example enforces a response file rule that is quite common: */
/* when a keyword is specified more than once in a response file, its */
/* value will be the *last* value specified. For example, if the */
/* response file contains the lines */
/* */
/* color = grey */
/* speed = slow */
/* color = red */
/* */
/* then the value used for 'color' will be red, not grey. */
/* */
/*************************************************************************
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hlrfio.h" /* This header file contains the prototypes for */
/* The Response File APIs, and defines for the */
/* codes returned by the Response File APIs */
char *ResponseFileName = "test.rsp"; /* This is the name of the response*/
/* file we will open first. It */
/* might contain imbedded */
/* (included) response files, but */
/* that's OK. */
/*************************************************************************/
/* This structure is an example of a *linked list*. Structures like */
/* this are useful for storing response file data in memory. */
/*************************************************************************/
struct keyword_value_pair { /* Structure to hold the keywords */
/* and values as they are read */
char *kw; /* Pointer to the keyword. */
int type; /* Type: string or list */
char *val; /* Pointer to the value */
struct keyword_value_pair *next; /* linked list pointer */
};
/*************************************************************************/
/* Function prototypes (Response File API prototypes are in hlrfio.h) */
/*************************************************************************/
struct keyword_value_pair *processString(char *keyword, char *value,
struct keyword_value_pair *first);
struct keyword_value_pair *processList(char *keyword, char *value,
struct keyword_value_pair *first);
struct keyword_value_pair *findKeyword(char *keyword,
struct keyword_value_pair *first);
void printData(struct keyword_value_pair *first);
void printItem(char *keyword, int type, char *value);
/*************************************************************************
**************************************************************************/
/*************************************************************************/
/* The main() routine is very similar to SAMPLE1. It opens the main */
/* response file, sequentially reads all keywords and values, processes */
/* them, and prints the data out. The processing is a little more */
/* complicated: we call processString when the value is string type, */
/* and processList when it is list type. */
/* */
/* As each keyword and value are placed in a memory structure, we keep */
/* a chain of them. The variable first points to the first structure; */
/* subsequent pointers are in each structure's 'next' member. */
/*************************************************************************/
int main(int argc, char **argv)
{
int rc; /* return code */
char *keyword; /* Holds address of the keyword */
char *value; /* Holds address of the value */
unsigned type; /* Indicates the type of the value */
/* (string or list) */
struct keyword_value_pair *first; /* Pointer to first keyword/value. */
struct keyword_value_pair *new; /* Pointer to a new keyword/value. */
struct keyword_value_pair *latest; /* Pointer to most recent kwd/val. */
first = (struct keyword_value_pair *)0; /* initialize 'first' pointer*/
latest= (struct keyword_value_pair *)0;
rc = RFOpen(ResponseFileName); /* Open the response file. If the */
/* open was successful, RFH0 is */
/* returned. Otherwise, RFHERR. */
if (rc == RFH0) /* If the open worked, */
{ /* look at each keyword/value pair*/
while (RFGetNextKeyword(&keyword, &value, &type) == RFH0)
{ /* Check if the value returned is a*/
if (type == RFHSTRING) /* string. If so, */
new = processString(keyword, value, first);/* process it. */
else /* Otherwise it must be a list so */
new = processList(keyword, value, first); /* process it. */
if (new) /* If we allocated a new structure */
if (latest) /* If this is not the first one, */
{ /* put the new one in the chain. */
latest->next = new;
latest = new; /* keep track of the end of the */
} /* chain. */
else /* But if this *is* the first one, */
{ /* then it will head the chain. */
latest = new;
first = latest;
}
} /* After all the response files are*/
printData(first); /* read, print the data out. */
} /* Note we don't have to close the */
} /* response file explicitely */
/*************************************************************************
**************************************************************************/
/*************************************************************************/
/* processString() */
/* */
/* This routine takes a keyword and value and puts them in a memory */
/* structure. This is very easy. First we see if the keyword has */
/* already been encountered. If it has, we replace the old value with */
/* the current one. If not, we create a new structure for the pair. */
/* */
/* Note that the we need to make a permanent copy of the keyword and */
/* value strings returned from RFGetNextKeyword(). If we don't, */
/* we will not have access to them later when we need them. */
/* */
/* Also note that we check to see if a keyword has already been */
/* encountered (routine findKeyword()). If it has, we don't need */
/* to allocate a new structure; we just replace the value pointer. */
/*************************************************************************/
struct keyword_value_pair *processString(char *keyword, char *value,
struct keyword_value_pair *first)
{
int structsize;
struct keyword_value_pair *Structure;/* address of the new or old */
/* memory structure. */
/* Try to find an previous */
/* listing for this keyword. */
if (Structure = findKeyword(keyword, first)) /* If found, */
{
free(Structure->val); /* free memory used for the old */
;/* value, and substitute a new */
Structure->val = RFCopyString(value); /* copy of the new value */
Structure->type = RFHSTRING; /* Note this is a string type */
return((struct keyword_value_pair *)NULL);
}
else /* But if this is the first use */
{ /* of this keyword, */
structsize = sizeof(struct keyword_value_pair);
/* Allocate memory for the struct */
Structure = (struct keyword_value_pair *)malloc(structsize);
if (Structure) /*If it was successfully allocated*/
{ /* make a new copy of the keyword*/
Structure->kw = RFCopyString(keyword);
Structure->val = RFCopyString(value); /* and the value */
Structure->type = RFHSTRING; /* Note this is a string type */
/* Make sure the chain pointer is */
/* empty; this structure will be */
/* added at the end of the list, */
/* and a NULL pointer lets us */
/* indicate that this is the end. */
Structure->next = (struct keyword_value_pair *)NULL;
}
return(Structure);
}
}
/*************************************************************************
**************************************************************************/
/*************************************************************************/
/* processList() */
/* */
/* This routine takes a keyword and list and puts them in a memory */
/* structure. This is only a little bit harder. */
/* */
/* This is very much like processString(), except we use the */
/* RFCopyList function to make a permanent copy of the list. */
/*************************************************************************/
struct keyword_value_pair *processList(char *keyword, char *value,
struct keyword_value_pair *first)
{
char *listname = NULL; /* Name in this list */
struct keyword_value_pair *Structure;/* address of the new or old */
/* memory structure. */
if (Structure = findKeyword(keyword, first))
{ /* If it exists, just replace */
free(Structure->val); /* the value with a new copy. */
Structure->val = RFCopyList(value);
Structure->type = RFHLIST; /* note that this is a list. */
return((struct keyword_value_pair *)NULL);
}
else
{ /* If this is a new keyword, */
/* Allocate memory for the struct */
Structure = (struct keyword_value_pair *)
malloc(sizeof(struct keyword_value_pair));
if (Structure) /*If it was successfully allocated*/
{ /* make a new copy of the keyword*/
Structure->kw = RFCopyString(keyword);
Structure->val = RFCopyList(value); /* and the value */
Structure->type = RFHLIST; /* Note this is a list type */
Structure->next = (struct keyword_value_pair *)NULL;
}
return(Structure);
}
}
/*************************************************************************
**************************************************************************/
/*************************************************************************/
/* This routine looks up the current keyword to see if we have already */
/* encountered it. It uses the pointer first to find the first */
/* structure, then 'walks the chain' looking at each keyword found so */
/* far. If it finds a matching keyword, it returns a pointer to the */
/* structure; otherwise, it returns NULL. */
/* */
/* Note that this routine treats keywords without regard to case; */
/* MyKeyword is assumed to be the same as mYkEYWORD. This is not */
/* a requirement, but it is a useful convention. */
/*************************************************************************/
struct keyword_value_pair *findKeyword(char *keyword,
struct keyword_value_pair *first)
{
struct keyword_value_pair *next;
for (next = first; next; next = next->next)
if (stricmp(keyword, next->kw) == 0)
return(next);
return((struct keyword_value_pair *)NULL);
}
/*************************************************************************/
/* printData() */
/* Print out whatever we have in memory */
/*************************************************************************/
void printData(struct keyword_value_pair *first)
{
struct keyword_value_pair *next;
for (next = first; next; next = next->next)
printItem(next->kw, next->type, next->val);
}
/*************************************************************************
**************************************************************************/
/*************************************************************************/
/* printItem() */
/* Because we want to display the contents of list values, this routine */
/* uses the Response File API RFGetNextKwdInList() to extract them. */
/* */
/* Note that this routine is called recursively because there may be */
/* lists imbedded within lists. */
/*************************************************************************/
void printItem(char *keyword, int type, char *value)
{
char *listkw, *listval; /* to hold keywords from within lists */
unsigned int listtype;
char *start; /* holds our place in the list */
if (type == RFHSTRING) /* string types are easy */
if (!value) /* We just have to check if there is */
printf("%s\n", keyword); /* is a value or not */
else
printf("%s = %s\n", keyword, value);
else /* list types a little harder */
{
printf("[BEGIN %s]\n", keyword);
start = value;
/* Read each item in the list */
while (RFGetNextKwdInList(&start, &listkw, &listval, &listtype)
== RFH0)
{ /* If this list contains an imbedded */
/* list, we have to make a copy of the*/
/* embedded list. This is because */
/* none of the objects that come back */
/* from RF API calls are permanent, */
/* and we need to use RF calls to */
/* process this imbedded list. */
if (listtype == RFHLIST)
{
listkw = RFCopyString(listkw);
listval = RFCopyList(listval);
}
/* Now we can process the list by */
/* calling ourselves recursively. */
printItem(listkw, listtype, listval);
/* If we made our own copies earlier, */
/* we can free them up now that we */
/* are done. */
if (listtype == RFHLIST)
{
free(listkw);
free(listval);
}
}
printf("[END %s]\n", keyword);
}
}