home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / INST / INFPARSE.C < prev    next >
C/C++ Source or Header  |  1993-12-01  |  14KB  |  693 lines

  1. /*
  2.  * Infparse.c - Setup.inf parsing code.
  3.  */
  4.  
  5. #include <stdlib.h>
  6.  
  7. #include "lobotomy.h"
  8. #include <windows.h>
  9.  
  10. #include "sulib.h"
  11.  
  12. #ifdef FAR_HEAP
  13. /*** hack.  to avoid realloc problems we make READ_BUFSIZE
  14.             as big as the inf file, thus avoiding any reallocs */
  15.  
  16. #define READ_BUFSIZE    27000    /* size of inf buffer */
  17. #endif
  18. #define TMP_BUFSIZE    1024    /* size of temp reads */
  19.  
  20. #define ISSEP(c)   ((c) == '='  || (c) == ',')
  21. #define ISWHITE(c) ((c) == ' '  || (c) == '\t' || (c) == '\n' || (c) == '\r')
  22. #define ISNOISE(c) ((c) == '"')
  23. #define EOF     26
  24.  
  25. #define QUOTE   '"'
  26. #define COMMA   ','
  27. #define SPACE   ' '
  28. #define EQUAL   '='
  29.  
  30. PINF   pinfDefault = NULL;
  31.  
  32. static PSTR    pBuf;
  33. static PINF    pInf;
  34. static WORD    iBuf;
  35. static WORD    iInf;
  36.  
  37. /* Globaly used pointers to non-translatable text strings. */
  38.  
  39. char        *pszINFFILE    =   "setup.inf";
  40. char        *pszPATH       =   "PATH";
  41.  
  42. /* Local prototypes */
  43.  
  44. BOOL multifields(PINF);
  45.  
  46.  
  47. static char GETC(int fh)
  48. {
  49.     register WORD n;
  50.  
  51.     if (!pBuf)
  52.         return EOF;
  53.  
  54.     n = iBuf % TMP_BUFSIZE;
  55.  
  56.     if (n == 0)
  57.     {
  58.        FREAD(fh,pBuf,TMP_BUFSIZE);
  59.     }
  60.     iBuf++;
  61.     return pBuf[n];
  62. }
  63.  
  64. #ifdef FAR_HEAP
  65.  
  66. static void PUTC(char c)
  67. {
  68.     if (!pInf)
  69.         return;
  70.  
  71.     pInf[iInf++] = c;
  72. }
  73.  
  74. #else
  75.  
  76. static void PUTC(char c)
  77. {
  78.     register WORD    n;
  79.     register PINF    pInfT;
  80.  
  81.     if (!pInf)
  82.         return;
  83.  
  84.     n = iInf % READ_BUFSIZE;
  85.     if (n == 0)
  86.     {
  87.         n = (iInf / READ_BUFSIZE) + 1;
  88.         pInfT = REALLOC(pInf,n * READ_BUFSIZE);
  89.  
  90.         if (pInfT)
  91.         {
  92.             pInf = pInfT;
  93.         }
  94.         else
  95.         {
  96.             AssertF(FALSE);
  97.             FREE(pInf);
  98.             pInf = NULL;
  99.         }
  100.     }
  101.     if (pInf)
  102.         pInf[iInf++] = c;
  103. }
  104. #endif
  105.  
  106. /* int infLoadFile()      Load a entire INF file into memory
  107.  *              comments are removed, each line is terminated
  108.  *              by a \0 each section is terminated by a \0\0
  109.  *              ONLY spaces inside of " " are preserved
  110.  *              the end of file is marked with a ^Z
  111.  *
  112.  *   RETURNS:  A pointer to a block of memory containg file, NULL if failure
  113.  *
  114.  */
  115. PINF infLoadFile(int fh)
  116. {
  117.     WORD    len;
  118.     PINF    pInfT;
  119.     register char    c;
  120.     register BOOL    fQuote = FALSE;
  121.  
  122.     if (fh == -1)
  123.       return NULL;
  124.  
  125.     len = (WORD)FSEEK(fh,0L,SEEK_END);
  126.  
  127.     FSEEK(fh,0L,SEEK_SET);
  128.  
  129.     pBuf = ALLOC(TMP_BUFSIZE);        // temp buffer
  130. #ifdef FAR_HEAP
  131.     pInf = FALLOC(len);            // destination, at least as big as file
  132. #else
  133.     pInf = ALLOC(READ_BUFSIZE);
  134. #endif
  135.     iBuf = 0;
  136.     iInf = 0;
  137.  
  138.     AssertF(pBuf && pInf);
  139.     if (!pBuf || !pInf)
  140.     return NULL;
  141.  
  142.  
  143.     while (iBuf < len)
  144.     {
  145.     c = GETC(fh);
  146. loop:
  147.         if (iBuf >= len)
  148.             break;
  149.  
  150.     switch (c)
  151.     {
  152.         case '\r':        /* ignore '\r' */
  153.         break;
  154.  
  155.         case '\n':
  156.         for (; ISWHITE(c); c = GETC(fh))
  157.             ;
  158.         if (c != ';')
  159.             PUTC(0);    /* all lines end in a \0 */
  160.  
  161.         if (c == '[')
  162.             PUTC(0);    /* all sections end with \0\0 */
  163.  
  164.         fQuote = FALSE;
  165.         goto loop;
  166.         break;
  167.  
  168.         case '\t':
  169.         case ' ':
  170.         if (fQuote)
  171.             PUTC(c);
  172.         break;
  173.  
  174.         case '"':
  175.         fQuote = !fQuote;
  176.         PUTC(c);
  177.         break;
  178.  
  179.         case ';':
  180.         for (; !ISEOL(c); c = GETC(fh))
  181.             ;
  182.         goto loop;
  183.         break;
  184.  
  185.         default:
  186.         PUTC(c);
  187.         break;
  188.     }
  189.     }
  190.  
  191.     PUTC(0);
  192.     PUTC(0);
  193.     PUTC(EOF);
  194.     FREE((HANDLE)pBuf);
  195.  
  196.     // try to shrink this block
  197.  
  198. #ifdef FAR_HEAP
  199.  
  200.     // just leave pInf it's original size.  don't bother shrinking it
  201.  
  202. #else
  203.     pInfT = REALLOC(pInf,iInf);
  204.  
  205.     if (pInfT)        // if REALLOC fails just leave pInf as is
  206.         pInf = pInfT;
  207. #endif
  208.  
  209.     AssertF(pInf);
  210.     return pInf;
  211. }
  212.  
  213. static int near pascal
  214. strncmpi(LPSTR pch1, LPSTR pch2, int n)
  215. {
  216.     while (*pch1 && --n > 0 && UP_CASE(*pch1) == UP_CASE(*pch2))
  217.          *pch1++,*pch2++;
  218.     return UP_CASE(*pch1) != UP_CASE(*pch2);
  219. }
  220.  
  221. /* PINF infOpen()    takes the string held in szBasePath as the path
  222.  *                   to find SETUP.INF and attempts to open it. Returns
  223.  *                   a valid file handle is successful.
  224.  *   
  225.  *   RETURNS:  A file pointer if successful, Null pointer in the case of
  226.  *           a failure.
  227.  *
  228.  *   ENTER:
  229.  *   EXIT:   To caller
  230.  */
  231. PINF FAR PASCAL infOpen(PSTR szInf)
  232. {
  233.     char    szBuf[MAXPATHLEN];
  234.     short   fh;
  235.     PINF    pinf;
  236.  
  237.     fh = -1;
  238.  
  239.     if (szInf == NULL)
  240.         szInf = pszINFFILE;
  241.  
  242.     /*
  243.      * Next try to open passed parameter as is. For Dos half.
  244.      */
  245.     if (fh == -1)
  246.     {
  247.         fh = FOPEN(szInf);
  248.     }
  249.     /*
  250.      * Next try destination path\system. for win half.
  251.      */
  252.     if (fh == -1) {
  253.       lstrcpy(szBuf, szSetupPath);
  254.       catpath(szBuf, "system");
  255.       catpath(szBuf, szInf);
  256.       fh = FOPEN(szBuf);
  257.     }
  258.     /*
  259.      * Next try destination path. for initial setup.
  260.      */
  261.     if (fh == -1) {
  262.       lstrcpy(szBuf, szSetupPath);
  263.       catpath(szBuf, szInf);
  264.       fh = FOPEN(szBuf);
  265.     }
  266.     /*
  267.      * May need to look on the path to find the .inf file.
  268.      */
  269.     if ( fh == -1 ) {
  270.       _searchenv(szInf,pszPATH,szBuf);
  271.       if ( *szBuf )
  272.          fh = FOPEN(szBuf);
  273.     }
  274.  
  275.     if (fh != -1)
  276.     {
  277.         pinf = infLoadFile(fh);
  278.         FCLOSE(fh);
  279.  
  280.         if (pinf && !pinfDefault)
  281.             pinfDefault = pinf;
  282.  
  283.         return pinf;
  284.     }
  285.     return NULL;
  286. }
  287.  
  288. /* void CloseSetupInf()
  289.  *
  290.  *   ENTER:
  291.  *   EXIT:   To caller
  292.  */
  293. void FAR PASCAL infClose(PINF pinf)
  294. {
  295.     if (pinf == NULL)
  296.         pinf = pinfDefault;
  297.  
  298.     if (pinf != NULL)
  299.     {
  300.     FFREE(pinf);
  301.  
  302.     if (pinf == pinfDefault)
  303.         pinfDefault = NULL;
  304.     }
  305. }
  306.  
  307.  
  308. /* FindSection    locates a section in Setup.Inf.  Sections are
  309.  *               assumed to be delimited by a '[' as the first
  310.  *               character on a line.
  311.  *
  312.  * Arguments:    pInf     Pointer to SETUP.INF buffer
  313.  *        pszSect  PSTR to section name
  314.  *
  315.  * Return:    WORD file position of the first line in the section
  316.  *               0 if section not found
  317.  */
  318.  
  319. WORD FindSection(PINF pInf, PSTR pszSect)
  320. {
  321.     BOOL    fFound = FALSE;
  322.     short    nLen = lstrlen(pszSect);
  323.     PINF    pch;
  324.     char        ch;
  325.  
  326.     if (!pInf)
  327.         return 0;
  328.  
  329.     pch = pInf;
  330.     while (!fFound && *pch != EOF)
  331.     {
  332.     if (*pch++ == '[')
  333.     {
  334.         fFound = !strncmpi(pszSect, pch, nLen) && pch[nLen] == ']';
  335.     }
  336.  
  337.     /*
  338.      * go to the next line, dont forget to skip over \0 and \0\0
  339.      */
  340.     while (*pch != EOF && *pch != '\0')
  341.         pch++;
  342.  
  343.     while (*pch == 0)
  344.         pch++;
  345.     }
  346.     return((fFound && *pch != '[' && *pch != EOF) ? pch - pInf : 0);
  347. }
  348.  
  349. /* char* fnGetDataString(npszData,szDataStr)
  350.  *
  351.  * Called by functions that read sections of information from setup.inf
  352.  * to obtain strings that are set equal to keywords. Example:
  353.  *
  354.  * welcome=("Hello There")
  355.  * 
  356.  * This function will return a pointer to the null terminated string
  357.  * "Hello There".
  358.  *
  359.  * ENTRY:
  360.  *
  361.  * npszData    : pointer to entire section taken from setup.inf
  362.  * npszDataStr : pointer to key word to look for (welcome in example above.)
  363.  *
  364.  * EXIT: retutns pointer to string if successful, NULL if failure.
  365.  *
  366.  */
  367. BOOL fnGetDataString(PINF npszData, PSTR szDataStr, LPSTR szBuf)
  368. {
  369.     unsigned char  *clocation;
  370.     unsigned char  *pStringHead;
  371.     int len = lstrlen(szDataStr);
  372.  
  373.     while (npszData)
  374.     {
  375.         if (!strncmpi(npszData,szDataStr,len))  // looking for correct prof.
  376.         {
  377.            npszData += len;            // found !, look past prof str.
  378.            while (ISWHITE(*npszData))  // suck out the crap.
  379.                npszData++;
  380.           if (*npszData == EQUAL)     // Now we have what were looking for !
  381.            {
  382.                npszData++;
  383.                
  384.              if (!multifields(npszData) )
  385.              {
  386.                 while (ISWHITE(*npszData) || ISNOISE(*npszData))
  387.                      npszData++;
  388.  
  389.                   while (*npszData)
  390.                      *szBuf++ = *npszData++;
  391.  
  392.                   /*
  393.                    * remove trailing spaces, and those pesky ()'s
  394.                    */
  395.  
  396.                 while (ISWHITE(szBuf[-1]) || ISNOISE(szBuf[-1]))
  397.                      szBuf--;
  398.  
  399.                   *szBuf = 0;
  400.                   return TRUE;
  401.              }
  402.              else
  403.              {
  404.                 while (*npszData)
  405.                    *szBuf++ = *npszData++;
  406.                 *szBuf = '\0';
  407.                 return TRUE;
  408.              }
  409.            }
  410.        }
  411.        npszData = infNextLine(npszData);
  412.     }
  413.     *szBuf = 0;
  414.     return FALSE;
  415. }
  416.  
  417. /*  PINF infSetDefault(pinf)
  418.  *
  419.  *  Sets the default INF file
  420.  *
  421.  * ENTRY:
  422.  *      pinf            : inf file to be new default
  423.  *
  424.  * EXIT: retutns old default
  425.  *
  426.  */
  427. PINF FAR PASCAL infSetDefault(PINF pinf)
  428. {
  429.     PINF pinfT;
  430.  
  431.     pinfT = pinfDefault;
  432.     pinfDefault = pinf;
  433.     return pinfT;
  434. }
  435.  
  436. /*  PINF infFindSection(pinf,szSection)
  437.  *
  438.  *  Reads a entire section into memory and returns a pointer to it
  439.  *
  440.  * ENTRY:
  441.  *      pinf            : inf file to search for section
  442.  *    szSection    : section name to read
  443.  *
  444.  * EXIT: retutns pointer to section, NULL if error
  445.  *
  446.  */
  447. PINF FAR PASCAL infFindSection(PINF pinf, PSTR szSection)
  448. {
  449.     WORD   pos;
  450.  
  451.     if (pinf == NULL)
  452.         pinf = pinfDefault;
  453.  
  454.     pos = FindSection(pinf, szSection);
  455.     return pos ? pinf + pos : NULL;
  456. }
  457.  
  458. /*  BOOL infGetProfileString(szSection,szItem,szBuf)
  459.  *
  460.  *  Reads a single string from a section in SETUP.INF
  461.  *
  462.  *  [section]
  463.  *    item = string
  464.  *
  465.  * ENTRY:
  466.  *    szSection    : pointer to section name to read.
  467.  *    szItem        : pointer to item name to read
  468.  *    szBuf        : pointer to a buffer to hold result
  469.  *
  470.  * EXIT: retutns TRUE if successful, FALSE if failure.
  471.  *
  472.  */
  473. BOOL FAR PASCAL infGetProfileString(PINF pinf, PSTR szSection,PSTR szItem,LPSTR szBuf)
  474. {
  475.     PINF    pSection;
  476.  
  477.     if (pSection = infFindSection(pinf,szSection))
  478.         return fnGetDataString(pSection,szItem,szBuf);
  479.     else
  480.         *szBuf = 0;
  481.     return FALSE;
  482. }
  483.  
  484. /* BOOL infParseField(szData,n,szBuf)
  485.  *
  486.  * Given a line from SETUP.INF, will extract the nth field from the string
  487.  * fields are assumed separated by comma's.  Leading and trailing spaces
  488.  * are removed.
  489.  *
  490.  * ENTRY:
  491.  *
  492.  * szData    : pointer to line from SETUP.INF
  493.  * n         : field to extract. ( 1 based )
  494.  *             0 is field before a '=' sign
  495.  * szDataStr : pointer to buffer to hold extracted field
  496.  *
  497.  * EXIT: retutns TRUE if successful, FALSE if failure.
  498.  *
  499.  */
  500. BOOL FAR PASCAL infParseField(PINF szData, int n, LPSTR szBuf)
  501. {
  502.     BOOL    fQuote = FALSE;
  503.     PINF    pch;
  504.     LPSTR   ptr;
  505.  
  506.     if (!szData || !szBuf)
  507.         return FALSE;
  508.  
  509.     /*
  510.      * find the first separator
  511.      */
  512.     for (pch=szData; *pch && !ISSEP(*pch); pch++) {
  513.       if ( *pch == QUOTE )
  514.          fQuote = !fQuote;
  515.     }
  516.  
  517.     if (n == 0 && *pch != '=')
  518.         return FALSE;
  519.  
  520.     if (n > 0 && *pch == '=' && !fQuote)
  521.         szData = ++pch;
  522.  
  523.     /*
  524.      *    locate the nth comma, that is not inside of quotes
  525.      */
  526.     fQuote = FALSE;
  527.     while (n > 1)
  528.     {
  529.         while (*szData)
  530.         {
  531.           if (!fQuote && ISSEP(*szData))
  532.                break;
  533.  
  534.           if (*szData == QUOTE)
  535.                fQuote = !fQuote;
  536.  
  537.            szData++;
  538.         }
  539.  
  540.         if (!*szData) {
  541.            szBuf[0] = 0;        // make szBuf empty
  542.            return FALSE;
  543.         }
  544.  
  545.         szData++;
  546.         n--;
  547.     }
  548.     /*
  549.      * now copy the field to szBuf
  550.      */
  551.     while (ISWHITE(*szData))
  552.         szData++;
  553.  
  554.     fQuote = FALSE;
  555.     ptr = szBuf;        // fill output buffer with this
  556.     while (*szData)
  557.     {
  558.        if (*szData == QUOTE)
  559.            fQuote = !fQuote;
  560.        else if (!fQuote && ISSEP(*szData))
  561.            break;
  562.         else
  563.            *ptr++ = *szData;
  564.         szData++;
  565.     }
  566.     /*
  567.      * remove trailing spaces, and those pesky ()'s
  568.      */
  569.     while ((ptr > szBuf) && (ISWHITE(ptr[-1]) || ISNOISE(ptr[-1])))
  570.         ptr--;
  571.  
  572.     *ptr = 0;
  573.     return TRUE;
  574. }
  575.  
  576. /* BOOL multifields(PSTR npszData);
  577.  *
  578.  * Given a line line from setup.inf that was phycisacaly after a profile
  579.  * string this function will determine if that line has more than one
  580.  * field. ie. Fields are seperated by commas that are NOT contained between
  581.  * quotes.
  582.  *
  583.  * ENYRY:
  584.  *
  585.  * npszData : a line from setup.inf Example "xyz adapter",1:foobar.drv
  586.  *
  587.  * EXIT: This function will return TRUE if the line containes more than
  588.  *       one field, ie the function would return TRUE for the example line
  589.  *       shown above.
  590.  *
  591.  */
  592. BOOL multifields(PINF npszData)
  593. {
  594.    BOOL    fQuote = FALSE;
  595.  
  596.     while (*npszData)
  597.     {
  598.       if (!fQuote && ISSEP(*npszData))
  599.            return TRUE;
  600.  
  601.       if (*npszData == QUOTE)
  602.            fQuote = !fQuote;
  603.  
  604.        npszData++;
  605.     }
  606.    return FALSE;
  607. }
  608.  
  609. /* PSTR infNextLine(sz)
  610.  *
  611.  * Given a line from SETUP.INF, advance to the next line.  will skip past the
  612.  * ending NULL character checking for end of buffer \0\0
  613.  *
  614.  * ENTRY:
  615.  *
  616.  * sz         : pointer to line from a SETUP.INF section
  617.  *
  618.  * EXIT: retutns pointer to next line if successful, NULL if failure.
  619.  *
  620.  */
  621. PINF FAR PASCAL infNextLine(PINF pinf)
  622. {
  623.     if (!pinf)
  624.         return NULL;
  625.  
  626.     while (*pinf != 0 || *(pinf + 1) == ' ')
  627.         pinf++;
  628.  
  629.     return *++pinf ? pinf : NULL;
  630. }
  631.  
  632. /* int infLineCount(pinf)
  633.  *
  634.  * Given a section from SETUP.INF, returns the number of lines in the section
  635.  *
  636.  * ENTRY:
  637.  *
  638.  * pinf         : pointer to a section from SETUP.INF
  639.  *
  640.  * EXIT: retutns line count
  641.  *
  642.  */
  643. int FAR PASCAL infLineCount(PINF pinf)
  644. {
  645.     int n = 0;
  646.  
  647.     for (n=0; pinf; pinf = infNextLine(pinf))
  648.     n++;
  649.  
  650.     return n;
  651. }
  652.  
  653. /* int infLookup(szInf,szBuf)
  654.  *
  655.  * lookup a section/key in SETUP.INF
  656.  *
  657.  * ENTRY:
  658.  *
  659.  * szInf        : pointer to a string of the form section.key
  660.  * szBuf        : pointer to buffer to recive string
  661.  *
  662.  * EXIT: retutns TRUE/FALSE
  663.  *
  664.  */
  665. BOOL FAR PASCAL infLookup(PSTR szInf, LPSTR szBuf)
  666. {
  667.     PSTR pch;
  668.     BOOL f;
  669.  
  670.     /*
  671.      * find the LAST .
  672.      */
  673.     for (pch = szInf; *pch; pch++)
  674.     ;
  675.  
  676.     for (; pch > szInf && *pch != '.'; pch--)
  677.     ;
  678.  
  679.     if (*pch == '.')
  680.     {
  681.     *pch++ = 0;
  682.         f = infGetProfileString(NULL,szInf,pch,szBuf);
  683.         if (szInf != szBuf)
  684.             *pch = '.';
  685.         return f;
  686.     }
  687.     else
  688.     {
  689.         *szBuf = 0;
  690.         return FALSE;
  691.     }
  692. }
  693.