home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cidsam.zip / SAMPLE2.C < prev    next >
C/C++ Source or Header  |  1993-06-28  |  20KB  |  333 lines

  1.                   /*********************************/
  2.                   /*              NOTE             */
  3.                   /*                               */
  4.                   /* This sample code has been     */
  5.                   /* provided by IBM.  It is not   */
  6.                   /* warranted for any particular  */
  7.                   /* use or purpose.               */
  8.                   /*                               */
  9.                   /* IBM releases this code into   */
  10.                   /* the public domain.  You may   */
  11.                   /* use it, modify it, or         */
  12.                   /* incorporate it into other     */
  13.                   /* products without restriction. */
  14.                   /*********************************/
  15. /* SAMPLE2.C                                                             */
  16. /*                                                                       */
  17. /* This sample program uses the high-level Response File APIs  to read a */
  18. /* response file and extract the keyword/value pairs.   It is a little  */
  19. /* more complicated than SAMPLE1.C in that                               */
  20. /*          - it reads all the keywords and values into memory           */
  21. /*          - it understands the 'list' type (keywords in the form       */
  22. /*                  KW = (                                               */
  23. /*                         ListKW1 = Value                               */
  24. /*                         ListKW2 = Value                               */
  25. /*                           ...                                         */
  26. /*                       )                                               */
  27. /*          - it's output is a little more complex                       */
  28. /*                                                                       */
  29. /* SAMPLE1 did not need to keep track of previously-read keywords and    */
  30. /* values; this example does.  Because the keywords and values           */
  31. /* returned from the Response File APIs are *temporary* copies, this     */
  32. /* sample program has a routine RFCopyString() to make permanent copies  */
  33. /* of these strings.  The sample also uses RFCopyList() to make permanent*/
  34. /* copies of list-type values.                                           */
  35.  
  36. /* This example enforces a response file rule that is quite common:      */
  37. /* when a keyword is specified more than once in a response file, its    */
  38. /* value will be the *last* value specified.  For example, if the        */
  39. /* response file contains the lines                                      */
  40. /*                                                                       */
  41. /*          color = grey                                                 */
  42. /*          speed = slow                                                 */
  43. /*          color = red                                                  */
  44. /*                                                                       */
  45. /* then the value used for 'color' will be red, not grey.                */
  46. /*                                                                       */
  47. /*************************************************************************  
  48. **************************************************************************/
  49. #include <stdio.h>           
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include "hlrfio.h"      /* This header file contains the prototypes for */
  53.                          /* The Response File APIs, and defines for the  */
  54.                          /* codes returned by the Response File APIs     */
  55.  
  56. char *ResponseFileName = "test.rsp";  /* This is the name of the response*/
  57.                                       /* file we will open first.  It    */
  58.                                       /* might contain imbedded          */
  59.                                       /* (included) response files, but  */
  60.                                       /* that's OK.                      */
  61.  
  62. /*************************************************************************/
  63. /* This structure is an example of a *linked list*.  Structures like     */
  64. /* this are useful for storing response file data in memory.             */
  65. /*************************************************************************/
  66. struct keyword_value_pair   {         /* Structure to hold the keywords  */
  67.                                       /* and values as they are read     */
  68.          char *kw;                    /* Pointer to the keyword.         */
  69.          int  type;                   /* Type: string or list            */
  70.          char *val;                   /* Pointer to the value            */
  71.          struct keyword_value_pair *next;  /* linked list pointer        */
  72.                             };      
  73.  
  74.  
  75. /*************************************************************************/
  76. /* Function prototypes (Response File API prototypes are in hlrfio.h)    */
  77. /*************************************************************************/
  78. struct keyword_value_pair *processString(char *keyword, char *value,
  79.                                         struct keyword_value_pair *first);
  80. struct keyword_value_pair *processList(char *keyword, char *value,
  81.                                         struct keyword_value_pair *first);
  82. struct keyword_value_pair *findKeyword(char *keyword,
  83.                                           struct keyword_value_pair *first);
  84. void printData(struct keyword_value_pair *first);
  85. void printItem(char *keyword, int type, char *value);
  86. /*************************************************************************  
  87. **************************************************************************/
  88.  
  89. /*************************************************************************/
  90. /* The main() routine is very similar to SAMPLE1.  It opens the main     */
  91. /* response file, sequentially reads all keywords and values, processes  */
  92. /* them, and prints the data out.  The processing is a little more       */
  93. /* complicated: we call processString when the value is string type,     */
  94. /* and processList when it is list type.                                 */
  95. /*                                                                       */
  96. /* As each keyword and value are placed in a memory structure, we keep   */
  97. /* a chain of them.  The variable first points to the first structure;   */
  98. /* subsequent pointers are in each structure's 'next' member.            */
  99. /*************************************************************************/
  100. int main(int argc, char **argv)
  101. {
  102.    int rc;                            /* return code                     */
  103.    char *keyword;                     /* Holds address of the keyword    */
  104.    char *value;                       /* Holds address of the value      */
  105.    unsigned type;                     /* Indicates the type of the value */
  106.                                       /* (string or list)                */
  107.    struct keyword_value_pair *first;  /* Pointer to first keyword/value. */
  108.    struct keyword_value_pair *new;    /* Pointer to a new keyword/value. */
  109.    struct keyword_value_pair *latest; /* Pointer to most recent kwd/val. */
  110.  
  111.    first = (struct keyword_value_pair *)0;  /* initialize 'first' pointer*/
  112.    latest= (struct keyword_value_pair *)0;
  113.  
  114.    rc = RFOpen(ResponseFileName);     /* Open the response file.  If the */
  115.                                       /* open was successful, RFH0 is    */
  116.                                       /* returned.  Otherwise, RFHERR.   */
  117.    if (rc == RFH0)                    /* If the open worked,             */
  118.      {                                /*  look at each keyword/value pair*/
  119.         while (RFGetNextKeyword(&keyword, &value, &type) == RFH0)
  120.  
  121.           {                           /* Check if the value returned is a*/
  122.              if (type == RFHSTRING)   /* string.   If so,                */
  123.                new = processString(keyword, value, first);/* process it. */
  124.              else                     /* Otherwise it must be a list  so */
  125.                new = processList(keyword, value, first); /* process it.  */
  126.  
  127.              if (new)                 /* If we allocated a new structure */
  128.                if (latest)            /* If this is not the first one,   */
  129.                  {                    /* put the new one in the chain.   */
  130.                    latest->next = new;
  131.                    latest = new;      /* keep track of the end of the    */
  132.                  }                    /*   chain.                        */
  133.                else                   /* But if this *is* the first one, */
  134.                  {                    /* then it will head the chain.    */
  135.                    latest = new;
  136.                    first = latest;
  137.                  }
  138.           }                           /* After all the response files are*/
  139.         printData(first);             /* read, print the data out.       */
  140.       }                               /* Note we don't have to close the */
  141. }                                     /* response file explicitely       */
  142. /*************************************************************************  
  143. **************************************************************************/
  144.  
  145. /*************************************************************************/
  146. /* processString()                                                       */
  147. /*                                                                       */
  148. /* This routine takes a keyword and value and puts them in a memory      */
  149. /* structure.  This is very easy.  First we see if the keyword has       */
  150. /* already been encountered.  If it has, we replace the old value with   */
  151. /* the current one.  If not, we create a new structure for the pair.     */
  152. /*                                                                       */
  153. /* Note that the we need to make a permanent copy of the keyword and     */
  154. /* value strings returned from RFGetNextKeyword().  If we don't,         */
  155. /* we will not have access to them later when we need them.              */
  156. /*                                                                       */
  157. /* Also note that we check to see if a keyword has already been          */
  158. /* encountered (routine findKeyword()).  If it has, we don't need        */
  159. /* to allocate a new structure; we just replace the value pointer.       */
  160. /*************************************************************************/
  161. struct keyword_value_pair *processString(char *keyword, char *value,
  162.                                         struct keyword_value_pair *first)
  163. {
  164.    int structsize;
  165.    struct keyword_value_pair *Structure;/* address of the new or old     */
  166.                                        /* memory structure.              */
  167.  
  168.                                        /* Try to find an previous        */
  169.                                        /* listing for this keyword.      */
  170.    if (Structure = findKeyword(keyword, first))   /* If found,           */
  171.      {
  172.         free(Structure->val);          /* free memory used for the old   */
  173.                                        ;/* value, and substitute a new   */
  174.         Structure->val = RFCopyString(value); /* copy of the new value   */
  175.         Structure->type = RFHSTRING;   /* Note this is a string type     */
  176.         return((struct keyword_value_pair *)NULL);
  177.      }
  178.    else                                /* But if this is the first use   */
  179.      {                                 /* of this keyword,               */
  180.        structsize = sizeof(struct keyword_value_pair);
  181.                                        /* Allocate memory for the struct */
  182.        Structure = (struct keyword_value_pair *)malloc(structsize);
  183.        if (Structure)                  /*If it was successfully allocated*/
  184.          {                             /*  make a new copy of the keyword*/
  185.            Structure->kw = RFCopyString(keyword);
  186.            Structure->val = RFCopyString(value); /* and the value        */
  187.            Structure->type = RFHSTRING; /* Note this is a string type    */
  188.                                        /* Make sure the chain pointer is */
  189.                                        /* empty; this structure will be  */
  190.                                        /* added at the end of the list,  */
  191.                                        /* and a NULL pointer lets us     */
  192.                                        /* indicate that this is the end. */
  193.            Structure->next = (struct keyword_value_pair *)NULL;
  194.          }
  195.        return(Structure);
  196.      }
  197. }
  198. /*************************************************************************  
  199. **************************************************************************/
  200.  
  201.  
  202. /*************************************************************************/
  203. /* processList()                                                         */
  204. /*                                                                       */
  205. /* This routine takes a keyword and list and  puts them in a memory      */
  206. /* structure.  This is only a little bit harder.                         */
  207. /*                                                                       */
  208. /* This is very much like processString(), except we use the             */
  209. /* RFCopyList function to make a permanent copy of the list.             */
  210. /*************************************************************************/
  211. struct keyword_value_pair *processList(char *keyword, char *value,
  212.                                         struct keyword_value_pair *first)
  213. {
  214.    char *listname = NULL;              /* Name in this list              */
  215.    struct keyword_value_pair *Structure;/* address of the new or old     */
  216.                                        /* memory structure.              */
  217.  
  218.    if (Structure = findKeyword(keyword, first)) 
  219.      {                                 /* If it exists, just replace     */
  220.         free(Structure->val);        /* the value with a new copy.     */
  221.         Structure->val = RFCopyList(value); 
  222.         Structure->type = RFHLIST;     /* note that this is a list.      */
  223.         return((struct keyword_value_pair *)NULL);
  224.      }
  225.    else                            
  226.      {                                 /* If this is a new keyword,      */
  227.                                        /* Allocate memory for the struct */
  228.        Structure = (struct keyword_value_pair *)
  229.                                  malloc(sizeof(struct keyword_value_pair));
  230.        if (Structure)                  /*If it was successfully allocated*/
  231.          {                             /*  make a new copy of the keyword*/
  232.            Structure->kw = RFCopyString(keyword);
  233.            Structure->val = RFCopyList(value); /* and the value          */
  234.            Structure->type = RFHLIST;  /* Note this is a list   type     */
  235.            Structure->next = (struct keyword_value_pair *)NULL;
  236.          }
  237.        return(Structure);
  238.      }
  239. }
  240. /*************************************************************************  
  241. **************************************************************************/
  242.  
  243. /*************************************************************************/
  244. /* This routine looks up the current keyword to see if we have already   */
  245. /* encountered it.  It uses the pointer first to find the first          */
  246. /* structure, then  'walks the chain' looking at each keyword found so   */
  247. /* far.  If it finds a matching keyword, it returns a pointer to the     */
  248. /* structure; otherwise, it returns NULL.                                */
  249. /*                                                                       */
  250. /* Note that this routine treats keywords without regard to case;        */
  251. /* MyKeyword is assumed to be the same as mYkEYWORD.  This is not        */
  252. /* a requirement, but it is a useful convention.                         */
  253. /*************************************************************************/
  254. struct keyword_value_pair *findKeyword(char *keyword,
  255.                                           struct keyword_value_pair *first)
  256. {
  257.    struct keyword_value_pair *next;
  258.  
  259.    for (next = first; next; next = next->next)
  260.       if (stricmp(keyword, next->kw) == 0)
  261.         return(next);
  262.    return((struct keyword_value_pair *)NULL);
  263. }
  264.  
  265. /*************************************************************************/
  266. /* printData()                                                           */
  267. /* Print out whatever we have in memory                                  */
  268. /*************************************************************************/
  269. void printData(struct keyword_value_pair *first)
  270. {
  271.    struct keyword_value_pair *next;
  272.  
  273.    for (next = first; next; next = next->next)
  274.       printItem(next->kw, next->type, next->val);
  275. }
  276. /*************************************************************************  
  277. **************************************************************************/
  278.  
  279.  
  280. /*************************************************************************/
  281. /* printItem()                                                           */
  282. /* Because we want to display the contents of list values, this routine  */
  283. /* uses the Response File API RFGetNextKwdInList() to extract them.      */
  284. /*                                                                       */
  285. /* Note that this routine is called recursively because there may be     */
  286. /* lists imbedded within lists.                                          */
  287. /*************************************************************************/
  288. void printItem(char *keyword, int type, char *value)
  289. {
  290.    char *listkw, *listval;         /* to hold keywords from within lists */
  291.    unsigned int listtype;
  292.    char *start;                    /* holds our place in the list        */
  293.  
  294.    if (type == RFHSTRING)           /* string types are easy              */
  295.      if (!value)                    /* We just have to check if there is  */
  296.        printf("%s\n", keyword);     /* is a value or not                  */
  297.      else
  298.        printf("%s = %s\n", keyword, value);
  299.    else                            /* list types a little harder         */
  300.      {
  301.         printf("[BEGIN %s]\n", keyword);
  302.         start = value;
  303.                                    /* Read each item in the list         */
  304.         while (RFGetNextKwdInList(&start, &listkw, &listval, &listtype)
  305.                                                                    == RFH0)
  306.           {                        /* If this list contains an imbedded  */
  307.                                    /* list, we have to make a copy of the*/
  308.                                    /* embedded list.  This is because    */
  309.                                    /* none of the objects that come back */
  310.                                    /* from RF API calls are permanent,   */
  311.                                    /* and we need to use RF calls to     */
  312.                                    /* process this imbedded list.        */
  313.             if (listtype == RFHLIST)
  314.               {
  315.                 listkw = RFCopyString(listkw);
  316.                 listval = RFCopyList(listval);
  317.               }
  318.                                    /* Now we can process the list by     */
  319.                                    /* calling ourselves recursively.     */
  320.             printItem(listkw, listtype, listval);
  321.                                    /* If we made our own copies earlier, */
  322.                                    /* we can free them up now that we    */
  323.                                    /* are done.                          */
  324.             if (listtype == RFHLIST)
  325.               {
  326.                 free(listkw);
  327.                 free(listval);
  328.               }
  329.           }
  330.         printf("[END %s]\n", keyword);
  331.       }
  332. }
  333.