home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boston 2
/
boston-2.iso
/
DOS
/
PROGRAM
/
C
/
INST
/
INFPARSE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-01
|
14KB
|
693 lines
/*
* Infparse.c - Setup.inf parsing code.
*/
#include <stdlib.h>
#include "lobotomy.h"
#include <windows.h>
#include "sulib.h"
#ifdef FAR_HEAP
/*** hack. to avoid realloc problems we make READ_BUFSIZE
as big as the inf file, thus avoiding any reallocs */
#define READ_BUFSIZE 27000 /* size of inf buffer */
#endif
#define TMP_BUFSIZE 1024 /* size of temp reads */
#define ISSEP(c) ((c) == '=' || (c) == ',')
#define ISWHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
#define ISNOISE(c) ((c) == '"')
#define EOF 26
#define QUOTE '"'
#define COMMA ','
#define SPACE ' '
#define EQUAL '='
PINF pinfDefault = NULL;
static PSTR pBuf;
static PINF pInf;
static WORD iBuf;
static WORD iInf;
/* Globaly used pointers to non-translatable text strings. */
char *pszINFFILE = "setup.inf";
char *pszPATH = "PATH";
/* Local prototypes */
BOOL multifields(PINF);
static char GETC(int fh)
{
register WORD n;
if (!pBuf)
return EOF;
n = iBuf % TMP_BUFSIZE;
if (n == 0)
{
FREAD(fh,pBuf,TMP_BUFSIZE);
}
iBuf++;
return pBuf[n];
}
#ifdef FAR_HEAP
static void PUTC(char c)
{
if (!pInf)
return;
pInf[iInf++] = c;
}
#else
static void PUTC(char c)
{
register WORD n;
register PINF pInfT;
if (!pInf)
return;
n = iInf % READ_BUFSIZE;
if (n == 0)
{
n = (iInf / READ_BUFSIZE) + 1;
pInfT = REALLOC(pInf,n * READ_BUFSIZE);
if (pInfT)
{
pInf = pInfT;
}
else
{
AssertF(FALSE);
FREE(pInf);
pInf = NULL;
}
}
if (pInf)
pInf[iInf++] = c;
}
#endif
/* int infLoadFile() Load a entire INF file into memory
* comments are removed, each line is terminated
* by a \0 each section is terminated by a \0\0
* ONLY spaces inside of " " are preserved
* the end of file is marked with a ^Z
*
* RETURNS: A pointer to a block of memory containg file, NULL if failure
*
*/
PINF infLoadFile(int fh)
{
WORD len;
PINF pInfT;
register char c;
register BOOL fQuote = FALSE;
if (fh == -1)
return NULL;
len = (WORD)FSEEK(fh,0L,SEEK_END);
FSEEK(fh,0L,SEEK_SET);
pBuf = ALLOC(TMP_BUFSIZE); // temp buffer
#ifdef FAR_HEAP
pInf = FALLOC(len); // destination, at least as big as file
#else
pInf = ALLOC(READ_BUFSIZE);
#endif
iBuf = 0;
iInf = 0;
AssertF(pBuf && pInf);
if (!pBuf || !pInf)
return NULL;
while (iBuf < len)
{
c = GETC(fh);
loop:
if (iBuf >= len)
break;
switch (c)
{
case '\r': /* ignore '\r' */
break;
case '\n':
for (; ISWHITE(c); c = GETC(fh))
;
if (c != ';')
PUTC(0); /* all lines end in a \0 */
if (c == '[')
PUTC(0); /* all sections end with \0\0 */
fQuote = FALSE;
goto loop;
break;
case '\t':
case ' ':
if (fQuote)
PUTC(c);
break;
case '"':
fQuote = !fQuote;
PUTC(c);
break;
case ';':
for (; !ISEOL(c); c = GETC(fh))
;
goto loop;
break;
default:
PUTC(c);
break;
}
}
PUTC(0);
PUTC(0);
PUTC(EOF);
FREE((HANDLE)pBuf);
// try to shrink this block
#ifdef FAR_HEAP
// just leave pInf it's original size. don't bother shrinking it
#else
pInfT = REALLOC(pInf,iInf);
if (pInfT) // if REALLOC fails just leave pInf as is
pInf = pInfT;
#endif
AssertF(pInf);
return pInf;
}
static int near pascal
strncmpi(LPSTR pch1, LPSTR pch2, int n)
{
while (*pch1 && --n > 0 && UP_CASE(*pch1) == UP_CASE(*pch2))
*pch1++,*pch2++;
return UP_CASE(*pch1) != UP_CASE(*pch2);
}
/* PINF infOpen() takes the string held in szBasePath as the path
* to find SETUP.INF and attempts to open it. Returns
* a valid file handle is successful.
*
* RETURNS: A file pointer if successful, Null pointer in the case of
* a failure.
*
* ENTER:
* EXIT: To caller
*/
PINF FAR PASCAL infOpen(PSTR szInf)
{
char szBuf[MAXPATHLEN];
short fh;
PINF pinf;
fh = -1;
if (szInf == NULL)
szInf = pszINFFILE;
/*
* Next try to open passed parameter as is. For Dos half.
*/
if (fh == -1)
{
fh = FOPEN(szInf);
}
/*
* Next try destination path\system. for win half.
*/
if (fh == -1) {
lstrcpy(szBuf, szSetupPath);
catpath(szBuf, "system");
catpath(szBuf, szInf);
fh = FOPEN(szBuf);
}
/*
* Next try destination path. for initial setup.
*/
if (fh == -1) {
lstrcpy(szBuf, szSetupPath);
catpath(szBuf, szInf);
fh = FOPEN(szBuf);
}
/*
* May need to look on the path to find the .inf file.
*/
if ( fh == -1 ) {
_searchenv(szInf,pszPATH,szBuf);
if ( *szBuf )
fh = FOPEN(szBuf);
}
if (fh != -1)
{
pinf = infLoadFile(fh);
FCLOSE(fh);
if (pinf && !pinfDefault)
pinfDefault = pinf;
return pinf;
}
return NULL;
}
/* void CloseSetupInf()
*
* ENTER:
* EXIT: To caller
*/
void FAR PASCAL infClose(PINF pinf)
{
if (pinf == NULL)
pinf = pinfDefault;
if (pinf != NULL)
{
FFREE(pinf);
if (pinf == pinfDefault)
pinfDefault = NULL;
}
}
/* FindSection locates a section in Setup.Inf. Sections are
* assumed to be delimited by a '[' as the first
* character on a line.
*
* Arguments: pInf Pointer to SETUP.INF buffer
* pszSect PSTR to section name
*
* Return: WORD file position of the first line in the section
* 0 if section not found
*/
WORD FindSection(PINF pInf, PSTR pszSect)
{
BOOL fFound = FALSE;
short nLen = lstrlen(pszSect);
PINF pch;
char ch;
if (!pInf)
return 0;
pch = pInf;
while (!fFound && *pch != EOF)
{
if (*pch++ == '[')
{
fFound = !strncmpi(pszSect, pch, nLen) && pch[nLen] == ']';
}
/*
* go to the next line, dont forget to skip over \0 and \0\0
*/
while (*pch != EOF && *pch != '\0')
pch++;
while (*pch == 0)
pch++;
}
return((fFound && *pch != '[' && *pch != EOF) ? pch - pInf : 0);
}
/* char* fnGetDataString(npszData,szDataStr)
*
* Called by functions that read sections of information from setup.inf
* to obtain strings that are set equal to keywords. Example:
*
* welcome=("Hello There")
*
* This function will return a pointer to the null terminated string
* "Hello There".
*
* ENTRY:
*
* npszData : pointer to entire section taken from setup.inf
* npszDataStr : pointer to key word to look for (welcome in example above.)
*
* EXIT: retutns pointer to string if successful, NULL if failure.
*
*/
BOOL fnGetDataString(PINF npszData, PSTR szDataStr, LPSTR szBuf)
{
unsigned char *clocation;
unsigned char *pStringHead;
int len = lstrlen(szDataStr);
while (npszData)
{
if (!strncmpi(npszData,szDataStr,len)) // looking for correct prof.
{
npszData += len; // found !, look past prof str.
while (ISWHITE(*npszData)) // suck out the crap.
npszData++;
if (*npszData == EQUAL) // Now we have what were looking for !
{
npszData++;
if (!multifields(npszData) )
{
while (ISWHITE(*npszData) || ISNOISE(*npszData))
npszData++;
while (*npszData)
*szBuf++ = *npszData++;
/*
* remove trailing spaces, and those pesky ()'s
*/
while (ISWHITE(szBuf[-1]) || ISNOISE(szBuf[-1]))
szBuf--;
*szBuf = 0;
return TRUE;
}
else
{
while (*npszData)
*szBuf++ = *npszData++;
*szBuf = '\0';
return TRUE;
}
}
}
npszData = infNextLine(npszData);
}
*szBuf = 0;
return FALSE;
}
/* PINF infSetDefault(pinf)
*
* Sets the default INF file
*
* ENTRY:
* pinf : inf file to be new default
*
* EXIT: retutns old default
*
*/
PINF FAR PASCAL infSetDefault(PINF pinf)
{
PINF pinfT;
pinfT = pinfDefault;
pinfDefault = pinf;
return pinfT;
}
/* PINF infFindSection(pinf,szSection)
*
* Reads a entire section into memory and returns a pointer to it
*
* ENTRY:
* pinf : inf file to search for section
* szSection : section name to read
*
* EXIT: retutns pointer to section, NULL if error
*
*/
PINF FAR PASCAL infFindSection(PINF pinf, PSTR szSection)
{
WORD pos;
if (pinf == NULL)
pinf = pinfDefault;
pos = FindSection(pinf, szSection);
return pos ? pinf + pos : NULL;
}
/* BOOL infGetProfileString(szSection,szItem,szBuf)
*
* Reads a single string from a section in SETUP.INF
*
* [section]
* item = string
*
* ENTRY:
* szSection : pointer to section name to read.
* szItem : pointer to item name to read
* szBuf : pointer to a buffer to hold result
*
* EXIT: retutns TRUE if successful, FALSE if failure.
*
*/
BOOL FAR PASCAL infGetProfileString(PINF pinf, PSTR szSection,PSTR szItem,LPSTR szBuf)
{
PINF pSection;
if (pSection = infFindSection(pinf,szSection))
return fnGetDataString(pSection,szItem,szBuf);
else
*szBuf = 0;
return FALSE;
}
/* BOOL infParseField(szData,n,szBuf)
*
* Given a line from SETUP.INF, will extract the nth field from the string
* fields are assumed separated by comma's. Leading and trailing spaces
* are removed.
*
* ENTRY:
*
* szData : pointer to line from SETUP.INF
* n : field to extract. ( 1 based )
* 0 is field before a '=' sign
* szDataStr : pointer to buffer to hold extracted field
*
* EXIT: retutns TRUE if successful, FALSE if failure.
*
*/
BOOL FAR PASCAL infParseField(PINF szData, int n, LPSTR szBuf)
{
BOOL fQuote = FALSE;
PINF pch;
LPSTR ptr;
if (!szData || !szBuf)
return FALSE;
/*
* find the first separator
*/
for (pch=szData; *pch && !ISSEP(*pch); pch++) {
if ( *pch == QUOTE )
fQuote = !fQuote;
}
if (n == 0 && *pch != '=')
return FALSE;
if (n > 0 && *pch == '=' && !fQuote)
szData = ++pch;
/*
* locate the nth comma, that is not inside of quotes
*/
fQuote = FALSE;
while (n > 1)
{
while (*szData)
{
if (!fQuote && ISSEP(*szData))
break;
if (*szData == QUOTE)
fQuote = !fQuote;
szData++;
}
if (!*szData) {
szBuf[0] = 0; // make szBuf empty
return FALSE;
}
szData++;
n--;
}
/*
* now copy the field to szBuf
*/
while (ISWHITE(*szData))
szData++;
fQuote = FALSE;
ptr = szBuf; // fill output buffer with this
while (*szData)
{
if (*szData == QUOTE)
fQuote = !fQuote;
else if (!fQuote && ISSEP(*szData))
break;
else
*ptr++ = *szData;
szData++;
}
/*
* remove trailing spaces, and those pesky ()'s
*/
while ((ptr > szBuf) && (ISWHITE(ptr[-1]) || ISNOISE(ptr[-1])))
ptr--;
*ptr = 0;
return TRUE;
}
/* BOOL multifields(PSTR npszData);
*
* Given a line line from setup.inf that was phycisacaly after a profile
* string this function will determine if that line has more than one
* field. ie. Fields are seperated by commas that are NOT contained between
* quotes.
*
* ENYRY:
*
* npszData : a line from setup.inf Example "xyz adapter",1:foobar.drv
*
* EXIT: This function will return TRUE if the line containes more than
* one field, ie the function would return TRUE for the example line
* shown above.
*
*/
BOOL multifields(PINF npszData)
{
BOOL fQuote = FALSE;
while (*npszData)
{
if (!fQuote && ISSEP(*npszData))
return TRUE;
if (*npszData == QUOTE)
fQuote = !fQuote;
npszData++;
}
return FALSE;
}
/* PSTR infNextLine(sz)
*
* Given a line from SETUP.INF, advance to the next line. will skip past the
* ending NULL character checking for end of buffer \0\0
*
* ENTRY:
*
* sz : pointer to line from a SETUP.INF section
*
* EXIT: retutns pointer to next line if successful, NULL if failure.
*
*/
PINF FAR PASCAL infNextLine(PINF pinf)
{
if (!pinf)
return NULL;
while (*pinf != 0 || *(pinf + 1) == ' ')
pinf++;
return *++pinf ? pinf : NULL;
}
/* int infLineCount(pinf)
*
* Given a section from SETUP.INF, returns the number of lines in the section
*
* ENTRY:
*
* pinf : pointer to a section from SETUP.INF
*
* EXIT: retutns line count
*
*/
int FAR PASCAL infLineCount(PINF pinf)
{
int n = 0;
for (n=0; pinf; pinf = infNextLine(pinf))
n++;
return n;
}
/* int infLookup(szInf,szBuf)
*
* lookup a section/key in SETUP.INF
*
* ENTRY:
*
* szInf : pointer to a string of the form section.key
* szBuf : pointer to buffer to recive string
*
* EXIT: retutns TRUE/FALSE
*
*/
BOOL FAR PASCAL infLookup(PSTR szInf, LPSTR szBuf)
{
PSTR pch;
BOOL f;
/*
* find the LAST .
*/
for (pch = szInf; *pch; pch++)
;
for (; pch > szInf && *pch != '.'; pch--)
;
if (*pch == '.')
{
*pch++ = 0;
f = infGetProfileString(NULL,szInf,pch,szBuf);
if (szInf != szBuf)
*pch = '.';
return f;
}
else
{
*szBuf = 0;
return FALSE;
}
}