mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
949 lines
18 KiB
949 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ppdparse.c
|
|
|
|
Abstract:
|
|
|
|
PostScript driver PPD parser - PARSEROBJ implementation
|
|
|
|
[Notes:]
|
|
|
|
Revision History:
|
|
|
|
4/18/95 -davidx-
|
|
Created it.
|
|
|
|
mm/dd/yy -author-
|
|
description
|
|
|
|
--*/
|
|
|
|
|
|
#include "pslib.h"
|
|
#include "ppdfile.h"
|
|
#include "ppdchar.h"
|
|
#include "ppdparse.h"
|
|
|
|
|
|
|
|
PPARSEROBJ
|
|
PARSEROBJ_Create(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a parser object
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
Pointer to newly recreated parser object
|
|
NULL if an error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
PPARSEROBJ pParserObj;
|
|
|
|
// Allocate memory space and initialize its content to zero
|
|
|
|
pParserObj = (PPARSEROBJ) MEMALLOC(sizeof(PARSEROBJ));
|
|
|
|
if (pParserObj == NULL) {
|
|
|
|
DBGERRMSG("MEMALLOC");
|
|
|
|
} else {
|
|
|
|
PSTR pBuffer;
|
|
|
|
// Allocate memory to for holding the value.
|
|
// Since the value can be very long, we start out
|
|
// from a default sized buffer. When we run
|
|
// out of room during parsing, we will grow
|
|
// the buffer through GlobalReAlloc.
|
|
|
|
pBuffer = (PSTR) MEMALLOC(DefaultValueLen+1);
|
|
|
|
if (pBuffer == NULL) {
|
|
|
|
DBGERRMSG("MEMALLOC");
|
|
MEMFREE(pParserObj);
|
|
pParserObj = NULL;
|
|
} else {
|
|
|
|
memset(pParserObj, 0, sizeof(PARSEROBJ));
|
|
memset(pBuffer, 0, DefaultValueLen+1);
|
|
|
|
// Initialize the buffer objects.
|
|
|
|
BUFOBJ_Initialize(
|
|
& pParserObj->keyword,
|
|
pParserObj->mainKeyword,
|
|
MaxKeywordLen);
|
|
|
|
BUFOBJ_Initialize(
|
|
& pParserObj->option,
|
|
pParserObj->optionKeyword,
|
|
MaxKeywordLen);
|
|
|
|
BUFOBJ_Initialize(
|
|
& pParserObj->xlation,
|
|
pParserObj->translation,
|
|
MaxXlationLen);
|
|
|
|
BUFOBJ_Initialize(
|
|
& pParserObj->value,
|
|
pBuffer,
|
|
DefaultValueLen);
|
|
}
|
|
}
|
|
|
|
return pParserObj;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
PARSEROBJ_Delete(
|
|
PPARSEROBJ pParserObj
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a parser object
|
|
|
|
Arguments:
|
|
|
|
pParserObj - Pointer to parser object to be deleted
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(pParserObj != NULL);
|
|
|
|
// Free the buffer which is used to hold the value
|
|
// field from a PPD entry.
|
|
|
|
MEMFREE(pParserObj->value.pBuffer);
|
|
|
|
// Free the parser object itself.
|
|
|
|
MEMFREE(pParserObj);
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
PARSEROBJ_ParseEntry(
|
|
PPARSEROBJ pParserObj,
|
|
PFILEOBJ pFileObj
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse one entry out of a PPD file. The parse results
|
|
(main keyword, option, translation string, and value)
|
|
are stored in the parser object.
|
|
|
|
Arguments:
|
|
|
|
pParserObj - Pointer to a parser objct.
|
|
pFileObj - Pointer to a file object.
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - a PPD entry was successfully parsed
|
|
PPDERR_EOF - encountered end-of-file
|
|
PPDERR_xxx - other error conditions
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDERROR err;
|
|
char ch;
|
|
|
|
// Reset the parser object to its initial state
|
|
|
|
BUFOBJ_Reset(& pParserObj->keyword);
|
|
BUFOBJ_Reset(& pParserObj->option);
|
|
BUFOBJ_Reset(& pParserObj->xlation);
|
|
BUFOBJ_Reset(& pParserObj->value);
|
|
pParserObj->valueType = NO_VALUE;
|
|
|
|
// Parse the main keyword.
|
|
|
|
err = PARSEROBJ_ParseKeyword(pParserObj, pFileObj, &ch);
|
|
|
|
// If the main keyword is terminated by a space,
|
|
// then skip over any trailing spaces.
|
|
|
|
while (err == PPDERR_NONE && IsSpace(ch)) {
|
|
err = FILEOBJ_GetChar(pFileObj, &ch);
|
|
}
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
|
|
// Decide what to do next based on the first non-space
|
|
// character after the main keyword.
|
|
|
|
if (IsNewline(ch)) {
|
|
|
|
// If the main keyword is terminated by a newline,
|
|
// then the entry only has a main keyword.
|
|
|
|
return PPDERR_NONE;
|
|
}
|
|
|
|
if (ch != SEPARATOR_CHAR) {
|
|
|
|
// Look for the option keyword next.
|
|
|
|
err = PARSEROBJ_ParseOption(pParserObj, pFileObj, &ch);
|
|
|
|
// If the option keyword is terminated by a space,
|
|
// then skip over any trailing spaces.
|
|
|
|
while (err == PPDERR_NONE && IsSpace(ch)) {
|
|
err = FILEOBJ_GetChar(pFileObj, &ch);
|
|
}
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
|
|
// Decide what to do next based on the first non-space
|
|
// character after the option keyword.
|
|
|
|
if (ch == XLATION_CHAR) {
|
|
|
|
// The option keyword is terminated by a '/'.
|
|
// Look for translation string next.
|
|
|
|
err = PARSEROBJ_ParseXlation(pParserObj, pFileObj, &ch);
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
}
|
|
|
|
// The option keyword and/or translation string must
|
|
// be terminated by a ':'. If not, return syntax error.
|
|
|
|
if (ch != SEPARATOR_CHAR) {
|
|
DBGMSG1(DBG_LEVEL_ERROR,
|
|
"Missing ':' in *%s entry\n",
|
|
BUFOBJ_Buffer(& pParserObj->keyword));
|
|
return PPDERR_SYNTAX;
|
|
}
|
|
}
|
|
|
|
return PARSEROBJ_ParseValue(pParserObj, pFileObj, &ch);
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
PARSEROBJ_ParseKeyword(
|
|
PPARSEROBJ pParserObj,
|
|
PFILEOBJ pFileObj,
|
|
PSTR pCh
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse the main keyword.
|
|
|
|
Arguments:
|
|
|
|
pParserObj - pointer to the parser object
|
|
pFileObj - pointer to input file object
|
|
pCh - placeholder for returning the main keyword terminating character
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - main keyword was parsed successfully
|
|
PPDERR_xxx - an error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDERROR err;
|
|
|
|
// Find the first keyword character after '*'
|
|
|
|
for ( ; ; ) {
|
|
|
|
// Read a character from the file object
|
|
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
|
|
if (*pCh == KEYWORD_CHAR) {
|
|
|
|
// Get the first keyword character
|
|
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
|
|
// If it's not a '%', start parsing the keyword.
|
|
|
|
if (*pCh != COMMENT_CHAR)
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (! IsNewline(*pCh)) {
|
|
|
|
DBGMSG(DBG_LEVEL_VERBOSE,
|
|
"Lines not starting with a '*' are discarded\n");
|
|
}
|
|
}
|
|
|
|
|
|
if (! IsNewline(*pCh)) {
|
|
|
|
// If the line does not start with a '*' or
|
|
// it starts with "*%", then skip the line.
|
|
|
|
err = PARSEROBJ_SkipLine(pParserObj, pFileObj);
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
}
|
|
}
|
|
|
|
// Collect characters into the main keyword buffer
|
|
|
|
return BUFOBJ_GetString(
|
|
& pParserObj->keyword,
|
|
pFileObj,
|
|
pCh,
|
|
CC_KEYWORD);
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
PARSEROBJ_ParseOption(
|
|
PPARSEROBJ pParserObj,
|
|
PFILEOBJ pFileObj,
|
|
PSTR pCh
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse the option keyword.
|
|
|
|
Arguments:
|
|
|
|
pParserObj - pointer to the parser object
|
|
pFileObj - pointer to input file object
|
|
pCh - placeholder for returning the option keyword terminating character
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - option keyword was parsed successfully
|
|
PPDERR_xxx - an error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
// Collect characters into the option keyword buffer
|
|
|
|
return BUFOBJ_GetString(
|
|
& pParserObj->option,
|
|
pFileObj,
|
|
pCh,
|
|
CC_OPTION);
|
|
}
|
|
|
|
|
|
PPDERROR
|
|
PARSEROBJ_ParseXlation(
|
|
PPARSEROBJ pParserObj,
|
|
PFILEOBJ pFileObj,
|
|
PSTR pCh
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse the translation string.
|
|
|
|
Arguments:
|
|
|
|
pParserObj - pointer to the parser object
|
|
pFileObj - pointer to input file object
|
|
pCh - placeholder for returning the translation string
|
|
terminating character
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - translation string was parsed successfully
|
|
PPDERR_xxx - an error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDERROR err;
|
|
|
|
// Read the first character
|
|
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
|
|
// Collect characters into the translation string buffer
|
|
|
|
return BUFOBJ_GetString(
|
|
& pParserObj->xlation,
|
|
pFileObj,
|
|
pCh,
|
|
CC_XLATION);
|
|
}
|
|
|
|
|
|
PPDERROR
|
|
PARSEROBJ_ParseValue(
|
|
PPARSEROBJ pParserObj,
|
|
PFILEOBJ pFileObj,
|
|
PSTR pCh
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse the entry value.
|
|
|
|
Arguments:
|
|
|
|
pParserObj - pointer to the parser object
|
|
pFileObj - pointer to input file object
|
|
pCh - placeholder for returning the entry value terminating character
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - entry value was parsed successfully
|
|
PPDERR_xxx - an error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDERROR err;
|
|
BOOL bQuoted;
|
|
PBUFOBJ pBufObj = & pParserObj->value;
|
|
|
|
// Skip over any leading spaces
|
|
|
|
do {
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
if (err != PPDERR_NONE)
|
|
return err;
|
|
} while (IsSpace(*pCh));
|
|
|
|
// Check to see if the first character is a '"'.
|
|
// If it's a '"', then parse a quoted value (which
|
|
// can span multiple lines) until the matching quote
|
|
// is found. If the first character is not a quote,
|
|
// the parse a normal string value until a newline
|
|
// is found.
|
|
|
|
if (*pCh == QUOTE_CHAR) {
|
|
bQuoted = TRUE;
|
|
pParserObj->valueType = QUOTED_VALUE;
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
} else {
|
|
bQuoted = FALSE;
|
|
pParserObj->valueType = STRING_VALUE;
|
|
}
|
|
|
|
for ( ; ; ) {
|
|
|
|
// Read characters from the file until one of the
|
|
// following condition is true:
|
|
// an error occured
|
|
// found a '"' when parsing a quoted value
|
|
// found a newline or '/' when parsing a normal value
|
|
|
|
if ((err != PPDERR_NONE) ||
|
|
(bQuoted && *pCh == QUOTE_CHAR) ||
|
|
(!bQuoted && (IsNewline(*pCh) || *pCh == XLATION_CHAR)))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Add the character to the buffer
|
|
|
|
if (BUFOBJ_AddChar(pBufObj, *pCh) != PPDERR_NONE) {
|
|
|
|
PSTR pNewBuffer;
|
|
|
|
// The value string is longer than what our
|
|
// buffer can hold. Expand the buffer by
|
|
// DefaultValueLen.
|
|
|
|
pNewBuffer = (PSTR)
|
|
MEMALLOC(pBufObj->maxlen + 1 + DefaultValueLen);
|
|
|
|
if (pNewBuffer == NULL) {
|
|
|
|
DBGERRMSG("MEMALLOC");
|
|
return PPDERR_MEM;
|
|
} else {
|
|
|
|
memset(pNewBuffer, 0, pBufObj->maxlen + 1 + DefaultValueLen);
|
|
}
|
|
|
|
// Copy over the previous buffer contents
|
|
|
|
memcpy(pNewBuffer, pBufObj->pBuffer, pBufObj->curlen);
|
|
|
|
// Free the previous buffer
|
|
|
|
MEMFREE(pBufObj->pBuffer);
|
|
|
|
// Switch to the new buffer and update the buffer length.
|
|
|
|
pBufObj->pBuffer = pNewBuffer;
|
|
pBufObj->maxlen += DefaultValueLen;
|
|
|
|
// Try adding the character to the buffer again.
|
|
|
|
err = BUFOBJ_AddChar(pBufObj, *pCh);
|
|
ASSERT(err == PPDERR_NONE);
|
|
}
|
|
|
|
// Read the next character from the file
|
|
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
}
|
|
|
|
// Null-terminate the value string
|
|
|
|
pBufObj->pBuffer[pBufObj->curlen] = '\0';
|
|
|
|
// Skip the remaining characters on the line
|
|
// (which should be a translation string).
|
|
|
|
if (err == PPDERR_NONE && ! IsNewline(*pCh))
|
|
err = PARSEROBJ_SkipLine(pParserObj, pFileObj);
|
|
|
|
// Handle symbol value
|
|
|
|
if (pParserObj->valueType == STRING_VALUE && *(pBufObj->pBuffer) == SYMBOL_CHAR)
|
|
pParserObj->valueType = SYMBOL_VALUE;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
PARSEROBJ_SkipLine(
|
|
PPARSEROBJ pParserObj,
|
|
PFILEOBJ pFileObj
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Skip to the end of line.
|
|
|
|
Arguments:
|
|
|
|
pParserObj - pointer to parser object
|
|
pFileObj - pointer to input file object
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - a line was successfully skipped
|
|
PPDERR_xxx - an error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDERROR err;
|
|
char ch;
|
|
|
|
do {
|
|
// Read one character
|
|
err = FILEOBJ_GetChar(pFileObj, &ch);
|
|
|
|
// Repeat while the character is not newline
|
|
// and there is no error
|
|
|
|
} while (err == PPDERR_NONE && ! IsNewline(ch));
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
BUFOBJ_Initialize(
|
|
PBUFOBJ pBufObj,
|
|
PSTR pBuffer,
|
|
DWORD maxlen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize a buffer object
|
|
|
|
Arguments:
|
|
|
|
pBufObj - pointer to buffer object to be initialized
|
|
pBuffer - pointer to space managed by the buffer object
|
|
maxlen - maximum length of the buffer
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
pBufObj->pBuffer = pBuffer;
|
|
pBufObj->maxlen = maxlen;
|
|
BUFOBJ_Reset(pBufObj);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
BUFOBJ_Reset(
|
|
PBUFOBJ pBufObj
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Restore a buffer object to its initialize state
|
|
|
|
Arguments:
|
|
|
|
pBufObj - pointer to buffer object to be restored
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
pBufObj->curlen = 0;
|
|
pBufObj->pBuffer[0] = '\0';
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
BUFOBJ_AddChar(
|
|
PBUFOBJ pBufObj,
|
|
char ch
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a character to the end of a buffer object
|
|
|
|
Arguments:
|
|
|
|
pBufObj - pointer to a buffer object
|
|
ch - character to be added
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - character was added to the buffer
|
|
PPDERR_MEM - buffer overflow
|
|
|
|
--*/
|
|
|
|
{
|
|
// Make sure we don't overflow the buffer
|
|
|
|
if (pBufObj->curlen >= pBufObj->maxlen)
|
|
return PPDERR_MEM;
|
|
|
|
// Append the character to the end of buffer
|
|
|
|
pBufObj->pBuffer[pBufObj->curlen++] = ch;
|
|
return PPDERR_NONE;
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
BUFOBJ_GetString(
|
|
PBUFOBJ pBufObj,
|
|
PFILEOBJ pFileObj,
|
|
PSTR pCh,
|
|
BYTE charMask
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read a character string from a file object into
|
|
a buffer object.
|
|
|
|
Arguments:
|
|
|
|
pBufObj - pointer to the buffer object
|
|
pFileObj - pointer to input file object
|
|
pCh - pointer to a character variable
|
|
on entry, this contains the first character of the string
|
|
on exit, this contains the string terminating character
|
|
charMask - mask for determining which characters are
|
|
allowed in the string
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - string was successfully read
|
|
PPDERR_xxx - an error occured
|
|
|
|
[Note:]
|
|
|
|
Zero length string is considered an error. On entry,
|
|
the buffer object is assumed to be in its initial state.
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDERROR err = PPDERR_NONE;
|
|
|
|
|
|
if (! IsMaskChar(*pCh, charMask)) {
|
|
|
|
DBGMSG1(DBG_LEVEL_ERROR, "Illegal character: %c\n", *pCh);
|
|
}
|
|
|
|
// Read characters from the file object until
|
|
// we see a terminating character or there is
|
|
// an error.
|
|
|
|
while (IsMaskChar(*pCh, charMask) && err == PPDERR_NONE) {
|
|
|
|
// Add a character to the buffer object
|
|
|
|
err = BUFOBJ_AddChar(pBufObj, *pCh);
|
|
|
|
// Read the next character
|
|
|
|
if (err == PPDERR_NONE)
|
|
err = FILEOBJ_GetChar(pFileObj, pCh);
|
|
}
|
|
|
|
// Null-terminate the buffer object
|
|
|
|
pBufObj->pBuffer[pBufObj->curlen] = '\0';
|
|
|
|
// Check for zero length string
|
|
|
|
return (pBufObj->curlen == 0) ? PPDERR_SYNTAX : err;
|
|
}
|
|
|
|
|
|
|
|
PPDERROR
|
|
BUFOBJ_CopyStringHex(
|
|
PBUFOBJ pBufObj,
|
|
PSTR pTo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy string out of a buffer object and treat its contents
|
|
as a mix of normal characters and hex-decimal digits.
|
|
|
|
Arguments:
|
|
|
|
pBufObj - pointer to buffer object
|
|
pTo - pointer to destination character buffer
|
|
|
|
Return Value:
|
|
|
|
PPDERR_NONE - string was successfully copied
|
|
PPDERR_SYNTAX - invalid hex-decimal string
|
|
|
|
[Note:]
|
|
|
|
Since we use the null character to as a string terminator,
|
|
it cannot appear as embedded hex string. Otherwise, the
|
|
string will be terminated prematurely.
|
|
|
|
--*/
|
|
|
|
{
|
|
PSTR pFrom = pBufObj->pBuffer;
|
|
char ch;
|
|
BOOL bHexMode = FALSE;
|
|
|
|
// Go through the source string one character at a time
|
|
|
|
while ((ch = *pFrom++) != '\0') {
|
|
|
|
if (bHexMode) {
|
|
|
|
// Currently in hex mode
|
|
|
|
if (ch == HEXEND_CHAR) {
|
|
|
|
// Get out of hex mode when we see a '>'
|
|
|
|
bHexMode = FALSE;
|
|
|
|
} else if (IsHexChar(ch) && IsHexChar(*pFrom)) {
|
|
|
|
// Convert two hex digits into a single byte
|
|
|
|
ASSERT(ch != '0' || *pFrom != '0');
|
|
*pTo++ = (HexValue(ch) << 4) | HexValue(*pFrom);
|
|
pFrom++;
|
|
} else {
|
|
|
|
// illegal hex-decimal digits
|
|
|
|
DBGMSG(DBG_LEVEL_ERROR, "Invalid hex digits.\n");
|
|
return PPDERR_SYNTAX;
|
|
}
|
|
} else {
|
|
|
|
// Currently not in hex mode
|
|
|
|
if (ch == HEXBEGIN_CHAR) {
|
|
|
|
// Get into hex mode when we see a '<'
|
|
|
|
bHexMode = TRUE;
|
|
} else {
|
|
|
|
// Copy normal character
|
|
|
|
*pTo++ = ch;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Null-terminate the destination buffer
|
|
|
|
*pTo = '\0';
|
|
|
|
// Return success status code
|
|
|
|
return PPDERR_NONE;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
BUFOBJ_StripTrailingSpaces(
|
|
PBUFOBJ pBufObj
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Strip off trailing spaces from a buffer object.
|
|
|
|
Arguments:
|
|
|
|
pBufObj - pointer to a buffer object
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD len = pBufObj->curlen;
|
|
|
|
while (len > 0 && IsSpace(pBufObj->pBuffer[len-1]))
|
|
len--;
|
|
pBufObj->curlen = len;
|
|
pBufObj->pBuffer[len] = '\0';
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
|
|
VOID
|
|
PARSEROBJ_Dump(
|
|
PPARSEROBJ pParserObj
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the contents of of a parsed PPD entry
|
|
|
|
Arguments:
|
|
|
|
pParserObj - pointer to a parser object
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
DBGPRINT("%c%s",
|
|
KEYWORD_CHAR,
|
|
BUFOBJ_Buffer(& pParserObj->keyword));
|
|
|
|
if (! BUFOBJ_IsEmpty(& pParserObj->option)) {
|
|
DBGPRINT(" %s", BUFOBJ_Buffer(& pParserObj->option));
|
|
|
|
if (! BUFOBJ_IsEmpty(& pParserObj->xlation)) {
|
|
DBGPRINT("%c%s",
|
|
XLATION_CHAR,
|
|
BUFOBJ_Buffer(& pParserObj->xlation));
|
|
}
|
|
}
|
|
|
|
if (pParserObj->valueType != NO_VALUE) {
|
|
DBGPRINT("%c%s",
|
|
SEPARATOR_CHAR,
|
|
BUFOBJ_Buffer(& pParserObj->value));
|
|
}
|
|
DBGPRINT("\n");
|
|
}
|
|
|
|
#endif // DBG
|
|
|