3182 lines
70 KiB
C
3182 lines
70 KiB
C
/*
|
|
(c) Copyright 1996 Hewlett-Packard Company
|
|
(c) Copyright 1996 International Business Machines Corp.
|
|
(c) Copyright 1996 Sun Microsystems, Inc.
|
|
(c) Copyright 1996 Novell, Inc.
|
|
(c) Copyright 1996 Digital Equipment Corp.
|
|
(c) Copyright 1996 Fujitsu Limited
|
|
(c) Copyright 1996 Hitachi, Ltd.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the names of the copyright holders shall
|
|
not be used in advertising or otherwise to promote the sale, use or other
|
|
dealings in this Software without prior written authorization from said
|
|
copyright holders.
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include "attributes.h"
|
|
|
|
/*
|
|
* XpOidNotify value strings
|
|
*/
|
|
#define NOTIFY_EMAIL_STR "{{event-report-job-completed} electronic-mail}"
|
|
#define NOTIFY_NONE_STR "{}"
|
|
|
|
#define SafeStrLen(s) ((s) ? strlen((s)) : 0)
|
|
|
|
/*
|
|
* entry type for the object identifier string map
|
|
*/
|
|
typedef struct _XpOidStringMapEntry
|
|
{
|
|
const char* string;
|
|
int length;
|
|
int msg_set;
|
|
int msg_number;
|
|
const char* default_message;
|
|
|
|
} XpOidStringMapEntry;
|
|
|
|
/*
|
|
* include the auto-generated static XpOidStringMap
|
|
*/
|
|
#include "OidStrs.h"
|
|
|
|
/*
|
|
* XpOid static function declarations
|
|
*/
|
|
static XpOid XpOidParse(const char* value_string,
|
|
const char** ptr_return);
|
|
/*
|
|
* XpOidList static function declarations
|
|
*/
|
|
static XpOidList* XpOidListParse(const char* value_string,
|
|
const XpOidList* valid_oids,
|
|
const char** ptr_return, int i);
|
|
|
|
/*
|
|
* XpOidList static function declarations
|
|
*/
|
|
static XpOidCardList* XpOidCardListParse(const char* value_string,
|
|
const XpOidCardList* valid_cards,
|
|
const char** ptr_return, int i);
|
|
|
|
/*
|
|
* XpOidMediumSourceSize static function declarations
|
|
*/
|
|
static XpOidMediumSS* MediumSSParse(const char* value_string,
|
|
const XpOidList* valid_trays,
|
|
const XpOidList* valid_medium_sizes,
|
|
const char** ptr_return, int i);
|
|
static XpOidMediumContinuousSize* MediumContinuousSizeParse(const char*,
|
|
const char**);
|
|
static void MediumContinuousSizeDelete(XpOidMediumContinuousSize* me);
|
|
static XpOidMediumDiscreteSizeList* MediumDiscreteSizeListParse(const char*,
|
|
const XpOidList*,
|
|
const char**,
|
|
int i);
|
|
static void MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list);
|
|
|
|
static BOOL ParseArea(const char* value_string,
|
|
const char** ptr_return,
|
|
XpOidArea* area_return);
|
|
static BOOL ParseRealRange(const char* value_string,
|
|
const char** ptr_return,
|
|
XpOidRealRange* range_return);
|
|
|
|
/*
|
|
* XpOidTrayMediumList static function declarations
|
|
*/
|
|
static XpOidTrayMediumList* TrayMediumListParse(const char* value_string,
|
|
const XpOidList* valid_trays,
|
|
const char** ptr_return,
|
|
int i);
|
|
static void TrayMediumListValidate(XpOidTrayMediumList* me,
|
|
const XpOidMediumSS* msss);
|
|
|
|
/*
|
|
* XpOidDocFmt
|
|
*/
|
|
static BOOL XpOidDocFmtNext(XpOidDocFmt* doc_fmt,
|
|
const char* value_string,
|
|
const char** ptr_return);
|
|
|
|
/*
|
|
* XpOidDocFmtListParse
|
|
*/
|
|
static XpOidDocFmtList* XpOidDocFmtListParse(const char* value_string,
|
|
const XpOidDocFmtList* valid_fmts,
|
|
const char** ptr_return, int i);
|
|
|
|
/*
|
|
* misc. parsing static function declarations
|
|
*/
|
|
static BOOL ParseBoolValue(const char* value_string,
|
|
const char** ptr_return,
|
|
BOOL* bool_return);
|
|
static BOOL ParseRealValue(const char* value_string,
|
|
const char** ptr_return,
|
|
float* real_return);
|
|
static BOOL ParseSeqEnd(
|
|
const char* value_string,
|
|
const char** ptr_return);
|
|
static BOOL ParseSeqStart(
|
|
const char* value_string,
|
|
const char** ptr_return);
|
|
static BOOL ParseUnspecifiedValue(
|
|
const char* value_string,
|
|
const char** ptr_return);
|
|
static int SpanToken(
|
|
const char* string);
|
|
static int SpanWhitespace(
|
|
const char* string);
|
|
|
|
/*
|
|
* String comparison function.
|
|
*/
|
|
#ifdef HAVE_STRCASECMP
|
|
# define StrnCaseCmp(s1, s2, len) strncasecmp(s1, s2, len)
|
|
#else
|
|
static int StrnCaseCmp(const char *s1, const char *s2, size_t len);
|
|
#endif
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidString
|
|
*
|
|
* Description:
|
|
*
|
|
* Obtain the string representation of an XpOid.
|
|
*
|
|
* Example: XpOidString(xpoid_copy_count) returns "copy-count".
|
|
*
|
|
* Return value:
|
|
*
|
|
* A const pointer to the string.
|
|
*/
|
|
const char*
|
|
XpOidString(XpOid xp_oid)
|
|
{
|
|
/*
|
|
* XpOid enum values are index values into the string map
|
|
*/
|
|
return XpOidStringMap[xp_oid].string;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidStringLength
|
|
*
|
|
* Description:
|
|
*
|
|
* Obtain the length of the string representation for a given
|
|
* XpOid.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The string length in bytes.
|
|
*
|
|
*/
|
|
int
|
|
XpOidStringLength(XpOid xp_oid)
|
|
{
|
|
/*
|
|
* XpOid enum values are index values into the string map
|
|
*/
|
|
return XpOidStringMap[xp_oid].length;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidFromString
|
|
*
|
|
* Description:
|
|
*
|
|
* Obtains the XpOid given a string representation of an XpOid.
|
|
*
|
|
* Example: XpOidFromString("copy-count") returns 'xpoid_copy_count'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The XpOid if successful. 'xpoid_none' if the string pointed to by
|
|
* 'value is not recognized or if 'value' is NULL.
|
|
*/
|
|
XpOid
|
|
XpOidFromString(const char* value)
|
|
{
|
|
if(value == (const char*)NULL)
|
|
return xpoid_none;
|
|
else
|
|
return XpOidParse(value, (const char**)NULL);
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidParse
|
|
*
|
|
* Description:
|
|
*
|
|
* Parse the next whitespace-delimited string from 'value_string'
|
|
* updating 'ptr_return' to point to the next unparsed location in
|
|
* 'value_string'. 'ptr_return' can be NULL.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The corresponding XpOid for the parsed name string.
|
|
* A return value of xpoid_none is returned if the parsed name
|
|
* was not a valid oid or if no name was found.
|
|
*
|
|
*/
|
|
static XpOid
|
|
XpOidParse(const char* value_string,
|
|
const char** ptr_return)
|
|
{
|
|
const char* ptr;
|
|
int length;
|
|
int i;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* get the whitespace-delimited token length
|
|
*/
|
|
length = SpanToken(ptr);
|
|
/*
|
|
* match the oid string in the map
|
|
*/
|
|
for(i = 0; i < XpOidStringMapCount; i++)
|
|
if(length == XpOidStringMap[i].length)
|
|
if(strncmp(ptr, XpOidStringMap[i].string, length) == 0)
|
|
break;
|
|
if(i == XpOidStringMapCount)
|
|
i = xpoid_none;
|
|
/*
|
|
* update the return pointer and return
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr+length;
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidListNew
|
|
*
|
|
* Description:
|
|
*
|
|
* Creates a new XpOidList initialized from a whitespace-delimited
|
|
* list of recognized string representations of oids. The returned
|
|
* list will contain only oids found within the passed 'valid_oids'
|
|
* XpOidList.
|
|
*
|
|
* Note: One may notice that in order to create an XpOidList with
|
|
* this function, an XpOidList is needed; the 'valid_oids' list
|
|
* is often an statically initialized structure. XpOidListInit
|
|
* can also be used.
|
|
*
|
|
* Return value:
|
|
*
|
|
* NULL if the passed 'value_string' is NULL.
|
|
*
|
|
* If the list indicated by 'value_string' is empty or contains only
|
|
* unrecognized oid string representations, a new XpOidList
|
|
* containing zero elements is returned.
|
|
*
|
|
* If 'valid_oids' is NULL all oids are considered valid.
|
|
*
|
|
*/
|
|
XpOidList*
|
|
XpOidListNew(const char* value_string,
|
|
const XpOidList* valid_oids)
|
|
{
|
|
if(value_string == (const char*)NULL)
|
|
return (XpOidList*)NULL;
|
|
else
|
|
{
|
|
const char* ptr;
|
|
return XpOidListParse(value_string, valid_oids, &ptr, 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidListDelete
|
|
*
|
|
* Description:
|
|
*
|
|
* Frees the memory allocated for 'list'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* None.
|
|
*
|
|
*/
|
|
void
|
|
XpOidListDelete(XpOidList* list)
|
|
{
|
|
if(list != (XpOidList*)NULL)
|
|
{
|
|
XpOidFree((char*)list->list);
|
|
XpOidFree((char*)list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidListParse
|
|
*
|
|
* Description:
|
|
*
|
|
* This function recursively parses the whitespace-delimited list of
|
|
* oid string representations passed via 'value_string'. Oids are
|
|
* only added to the resulting list if they are found within the
|
|
* passed 'valid_oids' XpOidList.
|
|
*
|
|
* 'ptr_return' points to a char* variable allocated by the
|
|
* caller, and is really only of use during recursion (upon return to
|
|
* the original caller, it will point to the end of value_string).
|
|
*
|
|
* 'value_string' and 'ptr_return' *cannot* be NULL.
|
|
*
|
|
* Return value:
|
|
*
|
|
* A newly allocated and initialized XpOidList.
|
|
*
|
|
* If the list indicated by 'value_string' is empty or contains only
|
|
* unrecognized oid string representations, a new XpOidList
|
|
* containing zero elements is returned.
|
|
*
|
|
* If 'valid_oids' is NULL all oids are considered valid.
|
|
*
|
|
*/
|
|
static XpOidList*
|
|
XpOidListParse(const char* value_string,
|
|
const XpOidList* valid_oids,
|
|
const char** ptr_return,
|
|
int i)
|
|
{
|
|
XpOid oid;
|
|
XpOidList* list;
|
|
/*
|
|
* parse the next valid oid out of the value string
|
|
*/
|
|
ptr_return = &value_string;
|
|
while(1)
|
|
{
|
|
if(**ptr_return == '\0')
|
|
{
|
|
/*
|
|
* end of value string; stop parsing
|
|
*/
|
|
oid = xpoid_none;
|
|
break;
|
|
}
|
|
/*
|
|
* parse the next oid from the value
|
|
*/
|
|
oid = XpOidParse(*ptr_return, ptr_return);
|
|
if(xpoid_none == oid)
|
|
{
|
|
/*
|
|
* unrecognized oid; keep parsing
|
|
*/
|
|
continue;
|
|
}
|
|
if((const XpOidList*)NULL == valid_oids
|
|
||
|
|
XpOidListHasOid(valid_oids, oid))
|
|
{
|
|
/*
|
|
* valid oid found; stop parsing
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(oid == xpoid_none)
|
|
{
|
|
/*
|
|
* end of value string; allocate the list structure
|
|
*/
|
|
list = (XpOidList*)XpOidCalloc(1, sizeof(XpOidList));
|
|
list->count = i;
|
|
list->list = (XpOid*)XpOidCalloc(i, sizeof(XpOid));
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* recurse
|
|
*/
|
|
list = XpOidListParse(*ptr_return, valid_oids, ptr_return, i+1);
|
|
/*
|
|
* set the oid in the list
|
|
*/
|
|
list->list[i] = oid;
|
|
}
|
|
/*
|
|
* return
|
|
*/
|
|
return list;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidListHasOid
|
|
*
|
|
* Description:
|
|
*
|
|
* Determines if 'oid' is an element of 'list'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the oid is found in the list.
|
|
*
|
|
* xFalse if the oid is not in the list, or if 'list' is NULL.
|
|
*
|
|
*/
|
|
BOOL
|
|
XpOidListHasOid(const XpOidList* list, XpOid oid)
|
|
{
|
|
int i;
|
|
if(list != (XpOidList*)NULL)
|
|
for(i = 0; i < list->count; i++)
|
|
if(list->list[i] == oid)
|
|
return xTrue;
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidListGetIndex
|
|
*
|
|
* Description:
|
|
*
|
|
* Returns the array index of 'oid' in 'list'
|
|
*
|
|
* Return value:
|
|
*
|
|
* The index of 'oid' in list.
|
|
*
|
|
* -1 if the oid is not in the list, or if 'list' is NULL.
|
|
*
|
|
*/
|
|
int
|
|
XpOidListGetIndex(const XpOidList* list, XpOid oid)
|
|
{
|
|
int i;
|
|
if(list != (XpOidList*)NULL)
|
|
for(i = 0; i < list->count; i++)
|
|
if(list->list[i] == oid)
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidListString
|
|
*
|
|
* Description:
|
|
*
|
|
* Creates a string representation of an XpOidList structure.
|
|
*
|
|
* Return value:
|
|
*
|
|
* A newly allocated
|
|
*
|
|
*/
|
|
char*
|
|
XpOidListString(const XpOidList* me)
|
|
{
|
|
int i;
|
|
int length;
|
|
char* str;
|
|
char* ptr;
|
|
/*
|
|
* allocate enough memory for the oid string representations,
|
|
* including intervening whitespace
|
|
*/
|
|
for(i = 0, length = 0; i < XpOidListCount(me); i++)
|
|
length += XpOidStringLength(XpOidListGetOid(me, i)) + 1;
|
|
str = XpOidMalloc(length+1);
|
|
/*
|
|
* format the list
|
|
*/
|
|
for(i = 0, ptr = str; i < XpOidListCount(me); i++)
|
|
#if defined(sun) && !defined(SVR4)
|
|
{
|
|
sprintf(ptr, "%s ", XpOidString(XpOidListGetOid(me, i)));
|
|
ptr += strlen(ptr);
|
|
}
|
|
#else
|
|
ptr += sprintf(ptr, "%s ", XpOidString(XpOidListGetOid(me, i)));
|
|
#endif
|
|
/*
|
|
* chop trailing whitespace or terminate empty string
|
|
*/
|
|
str[length] = '\0';
|
|
/*
|
|
* return
|
|
*/
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListNew
|
|
*
|
|
* Description:
|
|
*
|
|
* Creates a new instance of an empty XpOidLinkedList.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The new XpOidLinkedList.
|
|
*
|
|
*/
|
|
XpOidLinkedList*
|
|
XpOidLinkedListNew()
|
|
{
|
|
return (XpOidLinkedList*)XpOidCalloc(1, sizeof(XpOidLinkedList));
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListDelete
|
|
*
|
|
* Description:
|
|
*
|
|
* Frees the memory allocated for a XpOidLinkedList.
|
|
*
|
|
* Return value:
|
|
*
|
|
* None.
|
|
*
|
|
*/
|
|
void
|
|
XpOidLinkedListDelete(XpOidLinkedList* me)
|
|
{
|
|
if(me != (XpOidLinkedList*)NULL)
|
|
{
|
|
while(me->head)
|
|
{
|
|
me->current = me->head;
|
|
me->head = me->current->next;
|
|
XpOidFree((char*)me->current);
|
|
}
|
|
XpOidFree((char*)me);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListGetOid
|
|
*
|
|
* Description:
|
|
*
|
|
* Retrieves the oid at position 'i' (zero-based) in the
|
|
* XpOidLinkedList 'me'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The oid at position 'i'.
|
|
*
|
|
* xpoid_none if the oid was not found, or the list is empty (or if
|
|
* the list contains xpoid_none at position 'i').
|
|
*/
|
|
XpOid
|
|
XpOidLinkedListGetOid(XpOidLinkedList* me, int i)
|
|
{
|
|
if(me == (XpOidLinkedList*)NULL || i < 0 || i >= me->count)
|
|
{
|
|
return xpoid_none;
|
|
}
|
|
else
|
|
{
|
|
me->current = me->head;
|
|
while(i--) me->current = me->current->next;
|
|
return me->current->oid;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListAddOid
|
|
*
|
|
* Description:
|
|
*
|
|
* Adds an oid to the end of an XpOidLinkedList.
|
|
*
|
|
* Return value:
|
|
*
|
|
* None.
|
|
*
|
|
*/
|
|
void
|
|
XpOidLinkedListAddOid(XpOidLinkedList* me, XpOid oid)
|
|
{
|
|
me->current = (XpOidNode)XpOidCalloc(1, sizeof(struct XpOidNodeStruct));
|
|
me->current->oid = oid;
|
|
++me->count;
|
|
if(me->tail)
|
|
{
|
|
me->tail->next = me->current;
|
|
me->tail = me->current;
|
|
}
|
|
else
|
|
me->head = me->tail = me->current;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListGetIndex
|
|
*
|
|
* Description:
|
|
*
|
|
* Returns the position of an oid in a XpOidLinkedList.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The zero-based position of 'oid' in the list.
|
|
*
|
|
* -1 if the oid is not in the list, or if 'me' is NULL.
|
|
*
|
|
*/
|
|
int
|
|
XpOidLinkedListGetIndex(XpOidLinkedList* me, XpOid oid)
|
|
{
|
|
if((XpOidLinkedList*)NULL != me)
|
|
{
|
|
int i = 0;
|
|
me->current = me->head;
|
|
while(me->current)
|
|
if(me->current->oid == oid)
|
|
{
|
|
return i;
|
|
}
|
|
else
|
|
{
|
|
++i;
|
|
me->current = me->current->next;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListHasOid
|
|
*
|
|
* Description:
|
|
*
|
|
* Determines if an oid is an element of a XpOidLinkedList.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the oid is found in the list.
|
|
*
|
|
* xFalse if the oid is not in the list, or if 'me' is NULL.
|
|
*/
|
|
BOOL
|
|
XpOidLinkedListHasOid(XpOidLinkedList* me,
|
|
XpOid oid)
|
|
{
|
|
if((XpOidLinkedList*)NULL != me)
|
|
{
|
|
me->current = me->head;
|
|
while(me->current)
|
|
if(me->current->oid == oid)
|
|
return xTrue;
|
|
else
|
|
me->current = me->current->next;
|
|
}
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListFirstOid
|
|
*
|
|
* Description:
|
|
*
|
|
* Positions the XpOidLinkedList 'current' pointer to the first entry
|
|
* in the list.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The first oid in the list, or xpoid_none if the list NULL or
|
|
* empty.
|
|
*/
|
|
XpOid
|
|
XpOidLinkedListFirstOid(XpOidLinkedList* me)
|
|
{
|
|
if((XpOidLinkedList*)NULL != me && (me->current = me->head))
|
|
return me->current->oid;
|
|
else
|
|
return xpoid_none;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidLinkedListNextOid
|
|
*
|
|
* Description:
|
|
*
|
|
* Positions the XpOidLinkedList 'current' pointer to the next entry
|
|
* in the list.
|
|
*
|
|
* Return value:
|
|
*
|
|
* The next oid, or xpoid_none if the end of the list has been
|
|
* reached.
|
|
*/
|
|
XpOid
|
|
XpOidLinkedListNextOid(XpOidLinkedList* me)
|
|
{
|
|
if(me->current ? (me->current = me->current->next) : xFalse)
|
|
return me->current->oid;
|
|
else
|
|
return xpoid_none;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidMediumSSNew
|
|
*
|
|
* Description:
|
|
*
|
|
* Creates a new XpOidMediumSS initialized from a string value
|
|
* specified using the medium-source-sizes syntax. See
|
|
* MediumSSParse() below for parsing details.
|
|
*
|
|
* Return value:
|
|
*
|
|
* NULL if the passed 'value_string' is NULL, or if a syntax error is
|
|
* encountered while parsing the medium-source-sizes value.
|
|
*
|
|
*/
|
|
XpOidMediumSS*
|
|
XpOidMediumSSNew(const char* value_string,
|
|
const XpOidList* valid_trays,
|
|
const XpOidList* valid_medium_sizes)
|
|
{
|
|
if(value_string == (const char*)NULL)
|
|
return (XpOidMediumSS*)NULL;
|
|
else
|
|
{
|
|
const char* ptr = value_string + SpanWhitespace(value_string);
|
|
if(*ptr == '\0')
|
|
return (XpOidMediumSS*)NULL;
|
|
else
|
|
return MediumSSParse(ptr, valid_trays, valid_medium_sizes,
|
|
&ptr, 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: MediumSSParse
|
|
*
|
|
* Description:
|
|
*
|
|
* 'ptr_return' *cannot* be NULL.
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
static XpOidMediumSS*
|
|
MediumSSParse(const char* value_string,
|
|
const XpOidList* valid_trays,
|
|
const XpOidList* valid_medium_sizes,
|
|
const char** ptr_return,
|
|
int i)
|
|
{
|
|
XpOidMediumSS* medium_ss;
|
|
XpOidMediumSourceSize mss;
|
|
/*
|
|
* check for the start of a new MediumSourceSize sequence
|
|
*/
|
|
if(ParseSeqStart(value_string, ptr_return))
|
|
{
|
|
/*
|
|
* check for an unspecified tray value
|
|
*/
|
|
if(ParseUnspecifiedValue(*ptr_return, ptr_return))
|
|
mss.input_tray = xpoid_unspecified;
|
|
else
|
|
{
|
|
const char* tray_str;
|
|
*ptr_return += SpanWhitespace(*ptr_return);
|
|
tray_str = *ptr_return;
|
|
/*
|
|
* parse out the input tray
|
|
*/
|
|
mss.input_tray = XpOidParse(*ptr_return, ptr_return);
|
|
if((const XpOidList*)NULL != valid_trays
|
|
&&
|
|
!XpOidListHasOid(valid_trays, mss.input_tray)
|
|
)
|
|
mss.input_tray = xpoid_none;
|
|
if(xpoid_none == mss.input_tray)
|
|
{
|
|
char* invalid_tray_str;
|
|
int len = *ptr_return - tray_str;
|
|
if(len > 0)
|
|
{
|
|
invalid_tray_str = XpOidMalloc(len+1);
|
|
strncpy(invalid_tray_str, tray_str, len);
|
|
invalid_tray_str[len] = '\0';
|
|
ErrorF("%s\nInvalid tray (%s) found. Will attempt to continue parsing.\n",
|
|
XPMSG_WARN_MSS, invalid_tray_str);
|
|
XpOidFree(invalid_tray_str);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* attempt to parse a Continuous MediumSize sequence
|
|
*/
|
|
mss.ms.continuous_size =
|
|
MediumContinuousSizeParse(*ptr_return, ptr_return);
|
|
if(mss.ms.continuous_size != (XpOidMediumContinuousSize*)NULL)
|
|
{
|
|
mss.mstag = XpOidMediumSS_CONTINUOUS;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* not continuous, try Discrete MediumSize
|
|
*/
|
|
mss.ms.discrete =
|
|
MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
|
|
ptr_return, 0);
|
|
if(mss.ms.discrete == (XpOidMediumDiscreteSizeList*)NULL)
|
|
{
|
|
const char* tray_str;
|
|
/*
|
|
* syntax error (MediumDiscreteSizeListParse reports error)
|
|
*/
|
|
switch(mss.input_tray)
|
|
{
|
|
case xpoid_none:
|
|
tray_str = "an invalid";
|
|
break;
|
|
case xpoid_unspecified:
|
|
tray_str = "default (tray specifier omitted)";
|
|
break;
|
|
default:
|
|
tray_str = XpOidString(mss.input_tray);
|
|
break;
|
|
}
|
|
ErrorF("%s\nError occurred while parsing medium sizes for %s tray.\n",
|
|
XPMSG_WARN_MSS, tray_str);
|
|
return NULL;
|
|
}
|
|
mss.mstag = XpOidMediumSS_DISCRETE;
|
|
}
|
|
/*
|
|
* parse out the MediumSourceSize sequence end
|
|
*/
|
|
if(!ParseSeqEnd(*ptr_return, ptr_return))
|
|
{
|
|
/*
|
|
* syntax error
|
|
*/
|
|
ErrorF("%s\nSequence End expected. Unparsed data: %s\n",
|
|
XPMSG_WARN_MSS, *ptr_return);
|
|
return NULL;
|
|
}
|
|
/*
|
|
* recurse to parse the next MediumSourceSize sequence
|
|
*/
|
|
medium_ss = MediumSSParse(*ptr_return,
|
|
valid_trays, valid_medium_sizes,
|
|
ptr_return,
|
|
xpoid_none == mss.input_tray ? i : i+1);
|
|
if(medium_ss == (XpOidMediumSS*)NULL
|
|
||
|
|
xpoid_none == mss.input_tray)
|
|
{
|
|
/*
|
|
* syntax error or invalid tray - clean up
|
|
*/
|
|
switch(mss.mstag)
|
|
{
|
|
case XpOidMediumSS_CONTINUOUS:
|
|
MediumContinuousSizeDelete(mss.ms.continuous_size);
|
|
break;
|
|
case XpOidMediumSS_DISCRETE:
|
|
MediumDiscreteSizeListDelete(mss.ms.discrete);
|
|
break;
|
|
}
|
|
if(medium_ss == (XpOidMediumSS*)NULL)
|
|
/*
|
|
* syntax error - return
|
|
*/
|
|
return NULL;
|
|
}
|
|
if(xpoid_none != mss.input_tray)
|
|
{
|
|
/*
|
|
* copy the current MediumSourceSize into the array
|
|
*/
|
|
memmove((medium_ss->mss)+i, &mss, sizeof(XpOidMediumSourceSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* MediumSourceSize sequence start not found
|
|
*/
|
|
if(**ptr_return == '\0')
|
|
{
|
|
if(0 == i)
|
|
{
|
|
ErrorF("%s\nNo valid trays found.\n", XPMSG_WARN_MSS);
|
|
return NULL;
|
|
}
|
|
/*
|
|
* end of value string; allocate the MediumSS structure
|
|
*/
|
|
medium_ss = (XpOidMediumSS*)XpOidCalloc(1, sizeof(XpOidMediumSS));
|
|
medium_ss->count = i;
|
|
medium_ss->mss = (XpOidMediumSourceSize*)
|
|
XpOidCalloc(i, sizeof(XpOidMediumSourceSize));
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* syntax error
|
|
*/
|
|
ErrorF("%s\nSequence Start expected.\nunparsed data: %s\n",
|
|
XPMSG_WARN_MSS, *ptr_return);
|
|
return NULL;
|
|
}
|
|
}
|
|
return medium_ss;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidMediumSSDelete
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
void
|
|
XpOidMediumSSDelete(XpOidMediumSS* me)
|
|
{
|
|
if(me != (XpOidMediumSS*)NULL)
|
|
{
|
|
int i;
|
|
for(i = 0; i < me->count; i++)
|
|
{
|
|
switch((me->mss)[i].mstag)
|
|
{
|
|
case XpOidMediumSS_CONTINUOUS:
|
|
MediumContinuousSizeDelete((me->mss)[i].ms.continuous_size);
|
|
break;
|
|
case XpOidMediumSS_DISCRETE:
|
|
MediumDiscreteSizeListDelete((me->mss)[i].ms.discrete);
|
|
break;
|
|
}
|
|
}
|
|
XpOidFree((char*)me);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidMediumSSHasSize
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
BOOL
|
|
XpOidMediumSSHasSize(XpOidMediumSS* me, XpOid page_size)
|
|
{
|
|
int i_mss, i_ds;
|
|
XpOidMediumDiscreteSizeList* ds_list;
|
|
|
|
if(me != (XpOidMediumSS*)NULL && page_size != xpoid_none)
|
|
for(i_mss = 0; i_mss < me->count; i_mss++)
|
|
{
|
|
switch((me->mss)[i_mss].mstag)
|
|
{
|
|
case XpOidMediumSS_DISCRETE:
|
|
ds_list = (me->mss)[i_mss].ms.discrete;
|
|
for(i_ds = 0; i_ds < ds_list->count; i_ds++)
|
|
if(page_size == (ds_list->list)[i_ds].page_size)
|
|
return xTrue;
|
|
break;
|
|
|
|
case XpOidMediumSS_CONTINUOUS:
|
|
/*
|
|
* unsupported
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
* return
|
|
*/
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidMediumSSString
|
|
*
|
|
* Description:
|
|
*
|
|
* Creates a string representation of an XpOidMediumSS structure.
|
|
*
|
|
* Return value:
|
|
*
|
|
* A newly allocated
|
|
*
|
|
*/
|
|
char* XpOidMediumSSString(const XpOidMediumSS* me)
|
|
{
|
|
int itray, isize;
|
|
int valid_size_count;
|
|
int length;
|
|
char* str;
|
|
char* ptr;
|
|
XpOidMediumDiscreteSize* ds;
|
|
char buf[128];
|
|
/*
|
|
* determine the size of the string representation
|
|
*/
|
|
for(itray = 0, length = 0; itray < XpOidMediumSSCount(me); itray++)
|
|
{
|
|
if(xpoid_none == me->mss[itray].input_tray
|
|
||
|
|
XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag)
|
|
{
|
|
/*
|
|
* skip invalid tray or unsupported continuous size spec
|
|
*/
|
|
continue;
|
|
}
|
|
for(isize = 0, valid_size_count = 0;
|
|
isize < me->mss[itray].ms.discrete->count;
|
|
isize++)
|
|
{
|
|
ds = me->mss[itray].ms.discrete->list+isize;
|
|
if(ds->page_size == xpoid_none)
|
|
continue;
|
|
++valid_size_count;
|
|
length += XpOidStringLength(ds->page_size);
|
|
length += ds->long_edge_feeds ? 4 : 5; /* "True" or "False" */
|
|
#if defined(sun) && !defined(SVR4)
|
|
sprintf(buf, "{%.4f %.4f %.4f %.4f}",
|
|
ds->assured_reproduction_area.minimum_x,
|
|
ds->assured_reproduction_area.maximum_x,
|
|
ds->assured_reproduction_area.minimum_y,
|
|
ds->assured_reproduction_area.maximum_y);
|
|
length += strlen(buf);
|
|
#else
|
|
length += sprintf(buf, "{%.4f %.4f %.4f %.4f}",
|
|
ds->assured_reproduction_area.minimum_x,
|
|
ds->assured_reproduction_area.maximum_x,
|
|
ds->assured_reproduction_area.minimum_y,
|
|
ds->assured_reproduction_area.maximum_y);
|
|
#endif
|
|
length += 5; /* "{<size> <feed> <area>} " */
|
|
}
|
|
if(valid_size_count == 0)
|
|
{
|
|
/*
|
|
* no valid sizes, skip
|
|
*/
|
|
continue;
|
|
}
|
|
if(xpoid_unspecified == me->mss[itray].input_tray)
|
|
length += 2; /* "''" */
|
|
else
|
|
length += XpOidStringLength(me->mss[itray].input_tray);
|
|
length += 4; /* "{<tray> <sizes>} " */
|
|
}
|
|
/*
|
|
* allocate
|
|
*/
|
|
str = XpOidMalloc(length+1);
|
|
/*
|
|
* format
|
|
*/
|
|
for(itray = 0, ptr = str; itray < XpOidMediumSSCount(me); itray++)
|
|
{
|
|
if(xpoid_none == me->mss[itray].input_tray
|
|
||
|
|
XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag)
|
|
{
|
|
/*
|
|
* skip invalid tray or unsupported continuous size spec
|
|
*/
|
|
continue;
|
|
}
|
|
/*
|
|
* check to ensure all of the specified sizes are valid
|
|
*/
|
|
for(isize = 0, valid_size_count = 0;
|
|
isize < me->mss[itray].ms.discrete->count;
|
|
isize++)
|
|
{
|
|
ds = me->mss[itray].ms.discrete->list+isize;
|
|
if(ds->page_size != xpoid_none)
|
|
++valid_size_count;
|
|
}
|
|
if(valid_size_count == 0)
|
|
{
|
|
/*
|
|
* no valid sizes, skip
|
|
*/
|
|
continue;
|
|
}
|
|
|
|
if(xpoid_unspecified == me->mss[itray].input_tray)
|
|
{
|
|
#if defined(sun) && !defined(SVR4)
|
|
sprintf(ptr, "{'' ");
|
|
ptr += strlen(ptr);
|
|
#else
|
|
ptr += sprintf(ptr, "{'' ");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if defined(sun) && !defined(SVR4)
|
|
sprintf(ptr, "{%s ", XpOidString(me->mss[itray].input_tray));
|
|
ptr += strlen(ptr);
|
|
#else
|
|
ptr += sprintf(ptr, "{%s ",
|
|
XpOidString(me->mss[itray].input_tray));
|
|
#endif
|
|
}
|
|
for(isize = 0; isize < me->mss[itray].ms.discrete->count; isize++)
|
|
{
|
|
ds = me->mss[itray].ms.discrete->list+isize;
|
|
if(ds->page_size != xpoid_none)
|
|
#if defined(sun) && !defined(SVR4)
|
|
{
|
|
sprintf(ptr, "{%s %s {%.4f %.4f %.4f %.4f}} ",
|
|
XpOidString(ds->page_size),
|
|
ds->long_edge_feeds ? "True" : "False",
|
|
ds->assured_reproduction_area.minimum_x,
|
|
ds->assured_reproduction_area.maximum_x,
|
|
ds->assured_reproduction_area.minimum_y,
|
|
ds->assured_reproduction_area.maximum_y);
|
|
ptr += strlen(ptr);
|
|
}
|
|
#else
|
|
ptr += sprintf(ptr, "{%s %s {%.4f %.4f %.4f %.4f}} ",
|
|
XpOidString(ds->page_size),
|
|
ds->long_edge_feeds ? "True" : "False",
|
|
ds->assured_reproduction_area.minimum_x,
|
|
ds->assured_reproduction_area.maximum_x,
|
|
ds->assured_reproduction_area.minimum_y,
|
|
ds->assured_reproduction_area.maximum_y);
|
|
#endif
|
|
}
|
|
#if defined(sun) && !defined(SVR4)
|
|
sprintf(ptr, "} ");
|
|
ptr += strlen(ptr);
|
|
#else
|
|
ptr += sprintf(ptr, "} ");
|
|
#endif
|
|
}
|
|
/*
|
|
* chop trailing whitespace or terminate empty string
|
|
*/
|
|
str[length] = '\0';
|
|
/*
|
|
* return
|
|
*/
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: MediumContinuousSizeParse
|
|
*
|
|
* Description:
|
|
*
|
|
* 'ptr_return' *cannot* be NULL.
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
static XpOidMediumContinuousSize*
|
|
MediumContinuousSizeParse(const char* value_string,
|
|
const char** ptr_return)
|
|
{
|
|
const char* first_nonws_ptr;
|
|
XpOidMediumContinuousSize* mcs = NULL;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
first_nonws_ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* parse out the MediumSize sequence start char
|
|
*/
|
|
if(!ParseSeqStart(first_nonws_ptr, ptr_return))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* peek ahead to see if it looks like we actually have a continuous
|
|
* size spec (looking for the sequence start char on the 1st range spec)
|
|
*/
|
|
if(!ParseSeqStart(*ptr_return, (const char**)NULL))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* Ok, let's go for it
|
|
*/
|
|
mcs = (XpOidMediumContinuousSize*)
|
|
XpOidCalloc(1, sizeof(XpOidMediumContinuousSize));
|
|
/*
|
|
* "range across the feed direction"
|
|
*/
|
|
if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_across_feed))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* "increment across the feed direction" (optional, default 0)
|
|
*/
|
|
if(!ParseUnspecifiedValue(*ptr_return, ptr_return))
|
|
if(!ParseRealValue(*ptr_return, ptr_return,
|
|
&mcs->increment_across_feed))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* "range in the feed direction"
|
|
*/
|
|
if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_in_feed))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* "increment in the feed direction" (optional, default 0)
|
|
*/
|
|
if(!ParseUnspecifiedValue(*ptr_return, ptr_return))
|
|
if(!ParseRealValue(*ptr_return, ptr_return,
|
|
&mcs->increment_in_feed))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* "long edge feeds" flag (default TRUE)
|
|
*/
|
|
if(ParseUnspecifiedValue(*ptr_return, ptr_return))
|
|
mcs->long_edge_feeds = xTrue;
|
|
else
|
|
if(!ParseBoolValue(*ptr_return, ptr_return, &mcs->long_edge_feeds))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* "generic assured reproduction area"
|
|
*/
|
|
if(!ParseArea(*ptr_return, ptr_return, &mcs->assured_reproduction_area))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* parse out the MediumSize sequence end character
|
|
*/
|
|
if(!ParseSeqEnd(*ptr_return, ptr_return))
|
|
goto MediumContinuousSizeParse_error;
|
|
/*
|
|
* return
|
|
*/
|
|
return mcs;
|
|
|
|
|
|
MediumContinuousSizeParse_error:
|
|
/*
|
|
* syntax error - don't log since this function may be called
|
|
* as a lookahead
|
|
*/
|
|
*ptr_return = first_nonws_ptr;
|
|
XpOidFree((char*)mcs);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: MediumContinuousSizeDelete
|
|
*
|
|
* Description:
|
|
*
|
|
* 'ptr_return' *cannot* be NULL.
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
static void
|
|
MediumContinuousSizeDelete(XpOidMediumContinuousSize* me)
|
|
{
|
|
XpOidFree((char*)me);
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: MediumDiscreteSizeListParse
|
|
*
|
|
* Description:
|
|
*
|
|
* 'ptr_return' *cannot* be NULL.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
static XpOidMediumDiscreteSizeList*
|
|
MediumDiscreteSizeListParse(const char* value_string,
|
|
const XpOidList* valid_medium_sizes,
|
|
const char** ptr_return,
|
|
int i)
|
|
{
|
|
XpOidMediumDiscreteSizeList* list;
|
|
XpOidMediumDiscreteSize mds;
|
|
/*
|
|
* check for the start of a new MediumSize sequence
|
|
*/
|
|
if(ParseSeqStart(value_string, ptr_return))
|
|
{
|
|
/*
|
|
* "page size"
|
|
*/
|
|
mds.page_size = XpOidParse(*ptr_return, ptr_return);
|
|
if((const XpOidList*)NULL != valid_medium_sizes
|
|
&&
|
|
!XpOidListHasOid(valid_medium_sizes, mds.page_size)
|
|
)
|
|
mds.page_size = xpoid_none;
|
|
/*
|
|
* "long edge feeds" flag (default TRUE)
|
|
*/
|
|
if(ParseUnspecifiedValue(*ptr_return, ptr_return))
|
|
mds.long_edge_feeds = xTrue;
|
|
else
|
|
if(!ParseBoolValue(*ptr_return, ptr_return,
|
|
&mds.long_edge_feeds))
|
|
{
|
|
/*
|
|
* syntax error
|
|
*/
|
|
ErrorF("%s\nBoolean expected.\nunparsed data: %s\n",
|
|
XPMSG_WARN_MSS, *ptr_return);
|
|
return (XpOidMediumDiscreteSizeList*)NULL;
|
|
}
|
|
/*
|
|
* "assured reproduction area"
|
|
*/
|
|
if(!ParseArea(*ptr_return, ptr_return,
|
|
&mds.assured_reproduction_area))
|
|
{
|
|
/*
|
|
* syntax error
|
|
*/
|
|
ErrorF("%s\nArea specification error.\nunparsed data: %s\n",
|
|
XPMSG_WARN_MSS, *ptr_return);
|
|
return (XpOidMediumDiscreteSizeList*)NULL;
|
|
}
|
|
/*
|
|
* parse out the MediumSize sequence end character
|
|
*/
|
|
if(!ParseSeqEnd(*ptr_return, ptr_return))
|
|
{
|
|
ErrorF("%s\nSequence End expected. Unparsed data: %s\n",
|
|
XPMSG_WARN_MSS, *ptr_return);
|
|
return (XpOidMediumDiscreteSizeList*)NULL;
|
|
}
|
|
/*
|
|
* recurse to parse the next Discrete MediumSize sequence
|
|
*/
|
|
if(mds.page_size == xpoid_none)
|
|
{
|
|
list = MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
|
|
ptr_return, i);
|
|
}
|
|
else
|
|
{
|
|
list = MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
|
|
ptr_return, i+1);
|
|
if(list != (XpOidMediumDiscreteSizeList*)NULL)
|
|
{
|
|
/*
|
|
* copy the current discrete MediumSize into the list
|
|
*/
|
|
memmove((list->list)+i, &mds, sizeof(XpOidMediumDiscreteSize));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* MediumSize sequence start not found; end of the discrete sizes
|
|
* list
|
|
*/
|
|
if(0 == i)
|
|
{
|
|
ErrorF("%s\nNo valid medium sizes found for tray.\n",
|
|
XPMSG_WARN_MSS);
|
|
return (XpOidMediumDiscreteSizeList*)NULL;
|
|
}
|
|
list = (XpOidMediumDiscreteSizeList*)
|
|
XpOidCalloc(1, sizeof(XpOidMediumDiscreteSizeList));
|
|
list->count = i;
|
|
list->list = (XpOidMediumDiscreteSize*)
|
|
XpOidCalloc(i, sizeof(XpOidMediumDiscreteSize));
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: MediumDiscreteSizeListDelete
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
static void
|
|
MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list)
|
|
{
|
|
if(list != (XpOidMediumDiscreteSizeList*)NULL)
|
|
{
|
|
XpOidFree((char*)list->list);
|
|
XpOidFree((char*)list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidTrayMediumListNew
|
|
*
|
|
* Description:
|
|
*
|
|
* Only need the valid trays; validation requires bumping up against
|
|
* msss using TrayMediumListValidate; this needs valid trays
|
|
* because of unspecified trays ion msss, but
|
|
* TrayMediumListValidate will take care of invalid sizes...
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
XpOidTrayMediumList*
|
|
XpOidTrayMediumListNew(const char* value_string,
|
|
const XpOidList* valid_trays,
|
|
const XpOidMediumSS* msss)
|
|
{
|
|
if(value_string == (const char*)NULL)
|
|
return (XpOidTrayMediumList*)NULL;
|
|
else
|
|
{
|
|
const char* ptr;
|
|
XpOidTrayMediumList* me;
|
|
me = TrayMediumListParse(value_string, valid_trays, &ptr, 0);
|
|
if((XpOidTrayMediumList*)NULL != me)
|
|
TrayMediumListValidate(me, msss);
|
|
return me;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidTrayMediumListDelete
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
void
|
|
XpOidTrayMediumListDelete(XpOidTrayMediumList* list)
|
|
{
|
|
if(list != (XpOidTrayMediumList*)NULL)
|
|
{
|
|
XpOidFree((char*)list->list);
|
|
XpOidFree((char*)list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: TrayMediumListParse
|
|
*
|
|
* Description:
|
|
*
|
|
* 'ptr_return' *cannot* be NULL.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
static XpOidTrayMediumList*
|
|
TrayMediumListParse(const char* value_string,
|
|
const XpOidList* valid_trays,
|
|
const char** ptr_return, int i)
|
|
{
|
|
XpOidTrayMedium tm;
|
|
XpOidTrayMediumList* list;
|
|
/*
|
|
* check for the start of a new InputTrayMedium sequence
|
|
*/
|
|
if(ParseSeqStart(value_string, ptr_return))
|
|
{
|
|
/*
|
|
* "input tray"
|
|
*/
|
|
tm.input_tray = XpOidParse(*ptr_return, ptr_return);
|
|
if((XpOidList*)NULL != valid_trays
|
|
&&
|
|
!XpOidListHasOid(valid_trays, tm.input_tray)
|
|
)
|
|
tm.input_tray = xpoid_none;
|
|
/*
|
|
* "medium"
|
|
*/
|
|
tm.medium = XpOidParse(*ptr_return, ptr_return);
|
|
/*
|
|
* parse out the InputTrayMedium sequence end character
|
|
*/
|
|
if(!ParseSeqEnd(*ptr_return, ptr_return))
|
|
{
|
|
ErrorF("%s\n", XPMSG_WARN_ITM);
|
|
return NULL;
|
|
}
|
|
/*
|
|
* recurse to parse the next InputTrayMedium sequence
|
|
*/
|
|
list = TrayMediumListParse(*ptr_return, valid_trays, ptr_return, i+1);
|
|
if(list != (XpOidTrayMediumList*)NULL)
|
|
{
|
|
/*
|
|
* copy the current InputTrayMedium into the list
|
|
*/
|
|
memmove((list->list)+i, &tm, sizeof(XpOidTrayMedium));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* InputTrayMedium sequence start not found
|
|
*/
|
|
if(**ptr_return == '\0')
|
|
{
|
|
/*
|
|
* end of the list
|
|
*/
|
|
list = (XpOidTrayMediumList*)
|
|
XpOidCalloc(1, sizeof(XpOidTrayMediumList));
|
|
list->count = i;
|
|
list->list = (XpOidTrayMedium*)
|
|
XpOidCalloc(i, sizeof(XpOidTrayMedium));
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* syntax error
|
|
*/
|
|
ErrorF("%s\n", XPMSG_WARN_ITM);
|
|
return NULL;
|
|
}
|
|
}
|
|
/*
|
|
* return
|
|
*/
|
|
return list;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: TrayMediumListValidate
|
|
*
|
|
* Description:
|
|
*
|
|
* Validate the input-trays-medium list based on a passed
|
|
* medium-source-sizes-supported structure. The validated
|
|
* input-trays-medium list will have the same number of entries upon
|
|
* return from this function. Invalid entries are indicated by
|
|
* setting the tray specification to xpoid_none.
|
|
*
|
|
* Return value:
|
|
*
|
|
* None.
|
|
*
|
|
*/
|
|
static void
|
|
TrayMediumListValidate(XpOidTrayMediumList* me,
|
|
const XpOidMediumSS* msss)
|
|
{
|
|
int i_mss, i_ds, i_itm;
|
|
XpOid current_tray, current_medium;
|
|
XpOidMediumDiscreteSizeList* unspecified_tray_ds;
|
|
XpOidMediumDiscreteSizeList* tray_ds;
|
|
|
|
if(msss == (XpOidMediumSS*)NULL
|
|
||
|
|
me == (XpOidTrayMediumList*)NULL)
|
|
{
|
|
return;
|
|
}
|
|
/*
|
|
* loop through the input trays medium list
|
|
*/
|
|
for(i_itm = 0; i_itm < XpOidTrayMediumListCount(me); i_itm++)
|
|
{
|
|
current_tray = XpOidTrayMediumListTray(me, i_itm);
|
|
if(current_tray == xpoid_none)
|
|
continue;
|
|
current_medium = XpOidTrayMediumListMedium(me, i_itm);
|
|
if(current_medium == xpoid_none)
|
|
{
|
|
/*
|
|
* no medium; invalidate this entry
|
|
*/
|
|
me->list[i_itm].input_tray = xpoid_none;
|
|
continue;
|
|
}
|
|
/*
|
|
* loop through the MediumSourceSizes, looking for an appropriate
|
|
* discrete sizes spec for the current tray
|
|
*/
|
|
unspecified_tray_ds = (XpOidMediumDiscreteSizeList*)NULL;
|
|
tray_ds = (XpOidMediumDiscreteSizeList*)NULL;
|
|
for(i_mss = 0;
|
|
i_mss < msss->count &&
|
|
tray_ds == (XpOidMediumDiscreteSizeList*)NULL;
|
|
i_mss++)
|
|
{
|
|
switch((msss->mss)[i_mss].mstag)
|
|
{
|
|
case XpOidMediumSS_DISCRETE:
|
|
if((msss->mss)[i_mss].input_tray == current_tray)
|
|
tray_ds = (msss->mss)[i_mss].ms.discrete;
|
|
else if((msss->mss)[i_mss].input_tray == xpoid_unspecified)
|
|
unspecified_tray_ds = (msss->mss)[i_mss].ms.discrete;
|
|
break;
|
|
|
|
case XpOidMediumSS_CONTINUOUS:
|
|
/*
|
|
* unsupported
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
* if the tray was not matched, use the unspecified tray size
|
|
* list
|
|
*/
|
|
if(tray_ds == (XpOidMediumDiscreteSizeList*)NULL)
|
|
{
|
|
if(unspecified_tray_ds == (XpOidMediumDiscreteSizeList*)NULL)
|
|
{
|
|
/*
|
|
* not even an unspecified tray, invalidate this
|
|
* input-trays-medium entry.
|
|
*/
|
|
me->list[i_itm].input_tray = xpoid_none;
|
|
continue;
|
|
}
|
|
else
|
|
tray_ds = unspecified_tray_ds;
|
|
}
|
|
/*
|
|
* loop through the discrete sizes list, looking for a size that
|
|
* matches the medium for the current input tray
|
|
*/
|
|
for(i_ds = 0; i_ds < tray_ds->count; i_ds++)
|
|
{
|
|
/*
|
|
* check to see if the current input tray's medium size
|
|
* matches the current discrete size
|
|
*
|
|
* Note: in the CDEnext SI, medium identifiers coincide with
|
|
* medium-size identifiers. If the DP-Medium object is
|
|
* ever implemented, this check would need to be
|
|
* changed so that the input tray's medium size is
|
|
* obtained from the indicated Medium object, and not
|
|
* inferred from the medium identifier itself.
|
|
*/
|
|
if((tray_ds->list)[i_ds].page_size == current_medium)
|
|
{
|
|
/*
|
|
* The current input tray's medium size matches the
|
|
* current discrete medium size.
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
if(i_ds == tray_ds->count)
|
|
{
|
|
/*
|
|
* The current input tray's medium size was not found in the
|
|
* discrete size list; mark the input tray medium entry
|
|
* invalid
|
|
*/
|
|
me->list[i_itm].input_tray = xpoid_none;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidTrayMediumListString
|
|
*
|
|
* Description:
|
|
*
|
|
* Creates a string representation of an XpOidTrayMediumList structure.
|
|
*
|
|
* Return value:
|
|
*
|
|
* A newly allocated
|
|
*
|
|
*/
|
|
char* XpOidTrayMediumListString(const XpOidTrayMediumList* me)
|
|
{
|
|
int i;
|
|
int length;
|
|
char* str;
|
|
char* ptr;
|
|
XpOid tray;
|
|
/*
|
|
* allocate enough memory for the string representation,
|
|
* including intervening delimiters and whitespace
|
|
*/
|
|
for(i = 0, length = 0; i < XpOidTrayMediumListCount(me); i++)
|
|
{
|
|
tray = XpOidTrayMediumListTray(me, i);
|
|
if(xpoid_none != tray)
|
|
{
|
|
length += XpOidStringLength(tray);
|
|
length += XpOidStringLength(XpOidTrayMediumListMedium(me, i));
|
|
length += 4;
|
|
}
|
|
}
|
|
str = XpOidMalloc(length+1);
|
|
/*
|
|
* format the list
|
|
*/
|
|
for(i = 0, ptr = str; i < XpOidTrayMediumListCount(me); i++)
|
|
{
|
|
tray = XpOidTrayMediumListTray(me, i);
|
|
if(xpoid_none != tray)
|
|
{
|
|
#if defined(sun) && !defined(SVR4)
|
|
sprintf(ptr, "{%s %s} ",
|
|
XpOidString(tray),
|
|
XpOidString(XpOidTrayMediumListMedium(me, i)));
|
|
ptr += strlen(ptr);
|
|
#else
|
|
ptr += sprintf(ptr, "{%s %s} ",
|
|
XpOidString(tray),
|
|
XpOidString(XpOidTrayMediumListMedium(me, i)));
|
|
#endif
|
|
}
|
|
}
|
|
/*
|
|
* chop trailing whitespace or terminate empty string
|
|
*/
|
|
str[length] = '\0';
|
|
/*
|
|
* return
|
|
*/
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidTrayMediumListHasTray
|
|
*
|
|
* Description:
|
|
*
|
|
* Determines if 'tray' is found in 'list'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the tray is found in the list.
|
|
*
|
|
* xFalse if the tray is not in the list, or if 'list' is NULL.
|
|
*
|
|
*/
|
|
BOOL
|
|
XpOidTrayMediumListHasTray(const XpOidTrayMediumList* list, XpOid tray)
|
|
{
|
|
int i;
|
|
if(list != (XpOidTrayMediumList*)NULL && tray != xpoid_none)
|
|
for(i = 0; i < list->count; i++)
|
|
if(XpOidTrayMediumListTray(list, i) == tray)
|
|
return xTrue;
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseArea
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out and returns a XpOidArea.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the XpOidArea was successfully parsed. ptr_return is
|
|
* updated to point to location where the parsing ended.
|
|
*
|
|
* xFalse if a XpOidArea was not found; ptr_return is updated
|
|
* to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseArea(const char* value_string,
|
|
const char** ptr_return,
|
|
XpOidArea* area_return)
|
|
{
|
|
const char* first_nonws_ptr;
|
|
const char* ptr;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
first_nonws_ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* parse out the area sequence start
|
|
*/
|
|
if(!ParseSeqStart(first_nonws_ptr, &ptr))
|
|
goto ParseArea_error;
|
|
/*
|
|
* parse the minimum x value
|
|
*/
|
|
if(!ParseRealValue(ptr, &ptr,
|
|
area_return ? &area_return->minimum_x : NULL))
|
|
goto ParseArea_error;
|
|
/*
|
|
* parse the maximum x value
|
|
*/
|
|
if(!ParseRealValue(ptr, &ptr,
|
|
area_return ? &area_return->maximum_x : NULL))
|
|
goto ParseArea_error;
|
|
/*
|
|
* parse the minimum y value
|
|
*/
|
|
if(!ParseRealValue(ptr, &ptr,
|
|
area_return ? &area_return->minimum_y : NULL))
|
|
goto ParseArea_error;
|
|
/*
|
|
* parse the maximum y value
|
|
*/
|
|
if(!ParseRealValue(ptr, &ptr,
|
|
area_return ? &area_return->maximum_y : NULL))
|
|
goto ParseArea_error;
|
|
/*
|
|
* parse out the area sequence end
|
|
*/
|
|
if(!ParseSeqEnd(ptr, &ptr))
|
|
goto ParseArea_error;
|
|
/*
|
|
* update the return pointer
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
/*
|
|
* return
|
|
*/
|
|
return xTrue;
|
|
|
|
|
|
ParseArea_error:
|
|
/*
|
|
* syntax error
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = first_nonws_ptr;
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseRealRange
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out and returns a
|
|
* XpOidRealRange.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the XpOidRealRange was successfully
|
|
* parsed. ptr_return is updated to point to location where the
|
|
* parsing ended.
|
|
*
|
|
* xFalse if a XpOidRealRange was not found; ptr_return is
|
|
* updated to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseRealRange(const char* value_string,
|
|
const char** ptr_return,
|
|
XpOidRealRange* range_return)
|
|
{
|
|
const char* first_nonws_ptr;
|
|
const char* ptr;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
first_nonws_ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* parse out the range sequence start
|
|
*/
|
|
if(!ParseSeqStart(first_nonws_ptr, &ptr))
|
|
goto ParseRealRange_error;
|
|
/*
|
|
* parse the lower bound
|
|
*/
|
|
if(!ParseRealValue(ptr, &ptr,
|
|
range_return ? &range_return->lower_bound : NULL))
|
|
goto ParseRealRange_error;
|
|
/*
|
|
* parse the upper bound
|
|
*/
|
|
if(!ParseRealValue(ptr, &ptr,
|
|
range_return ? &range_return->upper_bound : NULL))
|
|
goto ParseRealRange_error;
|
|
/*
|
|
* parse out the range sequence end
|
|
*/
|
|
if(!ParseSeqEnd(ptr, &ptr))
|
|
goto ParseRealRange_error;
|
|
/*
|
|
* update the return pointer
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
/*
|
|
* return
|
|
*/
|
|
return xTrue;
|
|
|
|
|
|
ParseRealRange_error:
|
|
/*
|
|
* syntax error
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = first_nonws_ptr;
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidNotifyParse
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
XpOidNotify XpOidNotifyParse(const char* value_string)
|
|
{
|
|
const char* ptr = value_string;
|
|
|
|
if(value_string == (const char*)NULL)
|
|
return XPOID_NOTIFY_NONE;
|
|
/*
|
|
* look for an event handling profile sequence start
|
|
*/
|
|
if(!ParseSeqStart(value_string, &ptr))
|
|
{
|
|
if('\0' == *ptr)
|
|
/*
|
|
* empty value is valid
|
|
*/
|
|
return XPOID_NOTIFY_NONE;
|
|
else
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
}
|
|
/*
|
|
* look for an event set sequence start
|
|
*/
|
|
if(!ParseSeqStart(ptr, &ptr))
|
|
{
|
|
/*
|
|
* check for an empty event handling profile
|
|
*/
|
|
if(ParseSeqEnd(ptr, &ptr))
|
|
{
|
|
ptr += SpanWhitespace(ptr);
|
|
if(*ptr == '\0')
|
|
/*
|
|
* valid empty event handling profile sequence
|
|
*/
|
|
return XPOID_NOTIFY_NONE;
|
|
}
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
}
|
|
/*
|
|
* the only event in the set should be report job completed
|
|
*/
|
|
if(xpoid_val_event_report_job_completed != XpOidParse(ptr, &ptr))
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
/*
|
|
* event set sequence end
|
|
*/
|
|
if(!ParseSeqEnd(ptr, &ptr))
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
/*
|
|
* delivery method of electronic mail
|
|
*/
|
|
if(xpoid_val_delivery_method_electronic_mail != XpOidParse(ptr, &ptr))
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
/*
|
|
* event handling profile sequence end
|
|
*/
|
|
if(!ParseSeqEnd(ptr, &ptr))
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
/*
|
|
* end of value
|
|
*/
|
|
ptr += SpanWhitespace(ptr);
|
|
if('\0' == *ptr)
|
|
/*
|
|
* valid supported notification profile
|
|
*/
|
|
return XPOID_NOTIFY_EMAIL;
|
|
else
|
|
return XPOID_NOTIFY_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidNotifyString
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
const char* XpOidNotifyString(XpOidNotify notify)
|
|
{
|
|
switch(notify)
|
|
{
|
|
case XPOID_NOTIFY_NONE:
|
|
return NOTIFY_NONE_STR;
|
|
case XPOID_NOTIFY_EMAIL:
|
|
return NOTIFY_EMAIL_STR;
|
|
case XPOID_NOTIFY_UNSUPPORTED:
|
|
return (const char *)NULL;
|
|
}
|
|
|
|
ErrorF("XpOidNotifyString: Unsupported notify=%ld\n", (long)notify);
|
|
return (const char *)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtNew
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
XpOidDocFmt*
|
|
XpOidDocFmtNew(const char* value_string)
|
|
{
|
|
XpOidDocFmt* doc_fmt;
|
|
const char* ptr;
|
|
|
|
if((const char*)NULL == value_string)
|
|
return (XpOidDocFmt*)NULL;
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
if('\0' == *ptr)
|
|
return (XpOidDocFmt*)NULL;
|
|
/*
|
|
* get the document format from the value string
|
|
*/
|
|
doc_fmt = (XpOidDocFmt*)XpOidCalloc(1, sizeof(XpOidDocFmt));
|
|
if(xTrue == XpOidDocFmtNext(doc_fmt, ptr, &ptr))
|
|
{
|
|
/*
|
|
* verify that the document format is the only value specified
|
|
*/
|
|
ptr += SpanWhitespace(ptr);
|
|
if('\0' == *ptr)
|
|
/*
|
|
* valid document-format value
|
|
*/
|
|
return doc_fmt;
|
|
}
|
|
/*
|
|
* invalid
|
|
*/
|
|
XpOidDocFmtDelete(doc_fmt);
|
|
ErrorF("%s\n", XPMSG_WARN_DOC_FMT);
|
|
return (XpOidDocFmt*)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtDelete
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
void
|
|
XpOidDocFmtDelete(XpOidDocFmt* doc_fmt)
|
|
{
|
|
if((XpOidDocFmt*)NULL != doc_fmt)
|
|
{
|
|
XpOidFree(doc_fmt->format);
|
|
XpOidFree(doc_fmt->variant);
|
|
XpOidFree(doc_fmt->version);
|
|
XpOidFree(doc_fmt);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtString
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
char*
|
|
XpOidDocFmtString(XpOidDocFmt* doc_fmt)
|
|
{
|
|
if((XpOidDocFmt*)NULL != doc_fmt)
|
|
{
|
|
if((char*)NULL != doc_fmt->format)
|
|
{
|
|
char* str = XpOidMalloc(1+SafeStrLen(doc_fmt->format)+
|
|
1+SafeStrLen(doc_fmt->variant)+
|
|
1+SafeStrLen(doc_fmt->version)+
|
|
1+1);
|
|
sprintf(str, "{%s %s %s}", doc_fmt->format,
|
|
(char*)NULL != doc_fmt->variant ? doc_fmt->variant : "",
|
|
(char*)NULL != doc_fmt->version ? doc_fmt->version : "");
|
|
return str;
|
|
}
|
|
}
|
|
return (char*)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtNext
|
|
*
|
|
* Description:
|
|
*
|
|
* Assumes non-NULL value string.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
static BOOL
|
|
XpOidDocFmtNext(XpOidDocFmt* doc_fmt,
|
|
const char* value_string,
|
|
const char** ptr_return)
|
|
{
|
|
const char* ptr;
|
|
const char* first_nonws_ptr;
|
|
const char* format;
|
|
const char* variant;
|
|
const char* version;
|
|
int format_len;
|
|
int variant_len;
|
|
int version_len;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
first_nonws_ptr = ptr;
|
|
/*
|
|
* sequence start
|
|
*/
|
|
if(!ParseSeqStart(ptr, &ptr))
|
|
goto XpOidDocFmtNext_error;
|
|
/*
|
|
* skip whitepace to the start of the document format, and save the
|
|
* location
|
|
*/
|
|
ptr += SpanWhitespace(ptr);
|
|
format = ptr;
|
|
/*
|
|
* document format
|
|
*/
|
|
if(0 == (format_len = SpanToken(ptr)))
|
|
goto XpOidDocFmtNext_error;
|
|
ptr += format_len;
|
|
/*
|
|
* optional variant
|
|
*/
|
|
ptr += SpanWhitespace(ptr);
|
|
variant = ptr;
|
|
if(0 != (variant_len = SpanToken(ptr)))
|
|
{
|
|
ptr += variant_len;
|
|
/*
|
|
* optional version
|
|
*/
|
|
ptr += SpanWhitespace(ptr);
|
|
version = ptr;
|
|
version_len = SpanToken(ptr);
|
|
ptr += version_len;
|
|
}
|
|
else
|
|
version_len = 0;
|
|
/*
|
|
* sequence end
|
|
*/
|
|
if(!ParseSeqEnd(ptr, &ptr))
|
|
goto XpOidDocFmtNext_error;
|
|
/*
|
|
* update return pointer
|
|
*/
|
|
if((const char**)NULL != ptr_return)
|
|
*ptr_return = ptr;
|
|
/*
|
|
* update the passed document format struct
|
|
*/
|
|
memset(doc_fmt, 0, sizeof(XpOidDocFmt));
|
|
doc_fmt->format = XpOidMalloc(format_len+1);
|
|
strncpy(doc_fmt->format, format, format_len);
|
|
doc_fmt->format[format_len] = '\0';
|
|
if(0 < variant_len)
|
|
{
|
|
doc_fmt->variant = XpOidMalloc(variant_len+1);
|
|
strncpy(doc_fmt->variant, variant, variant_len);
|
|
doc_fmt->variant[variant_len] = '\0';
|
|
if(0 < version_len)
|
|
{
|
|
doc_fmt->version = XpOidMalloc(version_len+1);
|
|
strncpy(doc_fmt->version, version, version_len);
|
|
doc_fmt->version[version_len] = '\0';
|
|
}
|
|
}
|
|
return xTrue;
|
|
|
|
XpOidDocFmtNext_error:
|
|
if((const char**)NULL != ptr_return)
|
|
*ptr_return = first_nonws_ptr;
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtListNew
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
XpOidDocFmtList*
|
|
XpOidDocFmtListNew(const char* value_string,
|
|
const XpOidDocFmtList* valid_fmts)
|
|
{
|
|
if((char*)NULL != value_string)
|
|
{
|
|
const char* ptr;
|
|
return XpOidDocFmtListParse(value_string, valid_fmts, &ptr, 0);
|
|
}
|
|
return (XpOidDocFmtList*)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtListDelete
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
void
|
|
XpOidDocFmtListDelete(XpOidDocFmtList* list)
|
|
{
|
|
if((XpOidDocFmtList*)NULL != list)
|
|
{
|
|
int i;
|
|
for(i = 0; i < list->count; i++)
|
|
{
|
|
XpOidFree(list->list[i].format);
|
|
XpOidFree(list->list[i].variant);
|
|
XpOidFree(list->list[i].version);
|
|
}
|
|
XpOidFree(list->list);
|
|
XpOidFree(list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtListString
|
|
*
|
|
* Description:
|
|
*
|
|
* Assumes the passed structure is valid.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
char*
|
|
XpOidDocFmtListString(const XpOidDocFmtList* list)
|
|
{
|
|
if((XpOidDocFmtList*)NULL != list)
|
|
{
|
|
if(0 < list->count)
|
|
{
|
|
int i;
|
|
int str_len;
|
|
char* str;
|
|
char* ptr;
|
|
/*
|
|
* allocate the return string
|
|
*/
|
|
for(i = 0, str_len = 0; i < list->count; i++)
|
|
{
|
|
str_len +=
|
|
1 + SafeStrLen(list->list[i].format) +
|
|
1 + SafeStrLen(list->list[i].variant) +
|
|
1 + SafeStrLen(list->list[i].version) + 2;
|
|
}
|
|
str = XpOidMalloc(str_len+1);
|
|
/*
|
|
* print the list into the string and return it
|
|
*/
|
|
ptr = str;
|
|
for(i = 0; i < list->count; i++)
|
|
{
|
|
XpOidDocFmt* df = &list->list[i];
|
|
|
|
#if defined(sun) && !defined(SVR4)
|
|
sprintf(ptr, "{%s %s %s} ",
|
|
df->format,
|
|
(char*)NULL != df->variant ? df->variant : "",
|
|
(char*)NULL != df->version ? df->version : "");
|
|
ptr += strlen(ptr);
|
|
#else
|
|
ptr +=
|
|
sprintf(ptr, "{%s %s %s} ",
|
|
df->format,
|
|
(char*)NULL != df->variant ? df->variant : "",
|
|
(char*)NULL != df->version ? df->version : "");
|
|
#endif
|
|
}
|
|
return str;
|
|
}
|
|
}
|
|
return (char*)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtListParse
|
|
*
|
|
* Description:
|
|
*
|
|
* Assumes the passed value_string and ptr_return are non-NULL.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
static XpOidDocFmtList*
|
|
XpOidDocFmtListParse(const char* value_string,
|
|
const XpOidDocFmtList* valid_fmts,
|
|
const char** ptr_return,
|
|
int i)
|
|
{
|
|
XpOidDocFmt doc_fmt;
|
|
XpOidDocFmtList* list;
|
|
BOOL status;
|
|
/*
|
|
* get the next document-format from the value string, skipping
|
|
* values not found in the passed list of valid formats
|
|
*/
|
|
*ptr_return = value_string;
|
|
while((status = XpOidDocFmtNext(&doc_fmt, *ptr_return, ptr_return))
|
|
&&
|
|
(const XpOidDocFmtList*)NULL != valid_fmts
|
|
&&
|
|
!XpOidDocFmtListHasFmt(valid_fmts, &doc_fmt)
|
|
);
|
|
|
|
if(xFalse == status)
|
|
{
|
|
if('\0' == **ptr_return)
|
|
{
|
|
if(0 == i)
|
|
{
|
|
/*
|
|
* empty value string
|
|
*/
|
|
return (XpOidDocFmtList*)NULL;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* done parsing; allocate the list and return
|
|
*/
|
|
list =
|
|
(XpOidDocFmtList*)XpOidCalloc(1, sizeof(XpOidDocFmtList));
|
|
list->count = i;
|
|
list->list = (XpOidDocFmt*)XpOidCalloc(i, sizeof(XpOidDocFmt));
|
|
return list;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* invalid document format
|
|
*/
|
|
ErrorF("%s\n", XPMSG_WARN_DOCFMT_LIST);
|
|
return (XpOidDocFmtList*)NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* recurse to parse remaining document formats
|
|
*/
|
|
list = XpOidDocFmtListParse(*ptr_return, valid_fmts, ptr_return, i+1);
|
|
if((XpOidDocFmtList*)NULL != list)
|
|
{
|
|
/*
|
|
* add this doc fmt to the list
|
|
*/
|
|
list->list[i].format = doc_fmt.format;
|
|
list->list[i].variant = doc_fmt.variant;
|
|
list->list[i].version = doc_fmt.version;
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidDocFmtListHasFmt
|
|
*
|
|
* Description:
|
|
*
|
|
* Assumes the passed structure is valid.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
BOOL
|
|
XpOidDocFmtListHasFmt(const XpOidDocFmtList* list,
|
|
const XpOidDocFmt* fmt)
|
|
{
|
|
int i;
|
|
if(list != (XpOidDocFmtList*)NULL
|
|
&&
|
|
fmt != (XpOidDocFmt*)NULL
|
|
&&
|
|
fmt->format != (char*)NULL
|
|
)
|
|
{
|
|
for(i = 0; i < list->count; i++)
|
|
{
|
|
/*
|
|
* formats must match
|
|
*/
|
|
if(strcmp(fmt->format, list->list[i].format) != 0)
|
|
continue;
|
|
/*
|
|
* variants must both be NULL or match
|
|
*/
|
|
if(fmt->variant == (char*)NULL)
|
|
{
|
|
if(list->list[i].variant == (char*)NULL)
|
|
return xTrue;
|
|
else
|
|
continue;
|
|
}
|
|
if(list->list[i].variant == (char*)NULL)
|
|
continue;
|
|
if(strcmp(fmt->variant, list->list[i].variant) != 0)
|
|
continue;
|
|
/*
|
|
* versions must both be NULL or match
|
|
*/
|
|
if(fmt->version == (char*)NULL)
|
|
{
|
|
if(list->list[i].version == (char*)NULL)
|
|
return xTrue;
|
|
else
|
|
continue;
|
|
}
|
|
if(list->list[i].version == (char*)NULL)
|
|
continue;
|
|
if(strcmp(fmt->version, list->list[i].version) == 0)
|
|
return xTrue;
|
|
}
|
|
}
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidCardListNew
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
XpOidCardList*
|
|
XpOidCardListNew(const char* value_string, const XpOidCardList* valid_cards)
|
|
{
|
|
if((const char*)NULL != value_string)
|
|
{
|
|
const char* ptr;
|
|
|
|
return XpOidCardListParse(value_string, valid_cards, &ptr, 0);
|
|
}
|
|
else
|
|
return (XpOidCardList*)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidCardListDelete
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
void
|
|
XpOidCardListDelete(XpOidCardList* list)
|
|
{
|
|
if((XpOidCardList*)NULL != list)
|
|
{
|
|
XpOidFree(list->list);
|
|
XpOidFree(list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidCardListString
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
char*
|
|
XpOidCardListString(const XpOidCardList* list)
|
|
{
|
|
if((XpOidCardList*)NULL != list)
|
|
{
|
|
char buf[48];
|
|
int str_len;
|
|
char* str;
|
|
int i;
|
|
char* ptr;
|
|
/*
|
|
* allocate the output string
|
|
*/
|
|
for(i = 0, str_len = 0; i < list->count; i++)
|
|
#if defined(sun) && !defined(SVR4)
|
|
{
|
|
sprintf(buf, "%lu", list->list[i]) + 1;
|
|
str_len += strlen(buf);
|
|
}
|
|
#else
|
|
str_len += sprintf(buf, "%lu", list->list[i]) + 1;
|
|
#endif
|
|
str = XpOidMalloc(str_len+1);
|
|
/*
|
|
* write the list to the string
|
|
*/
|
|
for(i = 0, ptr = str; i < list->count; i++)
|
|
#if defined(sun) && !defined(SVR4)
|
|
{
|
|
sprintf(ptr, "%lu ", list->list[i]);
|
|
ptr += strlen(ptr);
|
|
}
|
|
#else
|
|
ptr += sprintf(ptr, "%lu ", list->list[i]);
|
|
#endif
|
|
return str;
|
|
}
|
|
else
|
|
return (char*)NULL;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidCardListHasCard
|
|
*
|
|
* Description:
|
|
*
|
|
* Determines if 'card' is an element of 'list'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the card is found in the list.
|
|
*
|
|
* xFalse if the card is not in the list, or if 'list' is NULL.
|
|
*
|
|
*/
|
|
BOOL
|
|
XpOidCardListHasCard(const XpOidCardList* list, unsigned long card)
|
|
{
|
|
int i;
|
|
if(list != (XpOidCardList*)NULL)
|
|
for(i = 0; i < list->count; i++)
|
|
if(list->list[i] == card)
|
|
return xTrue;
|
|
return xFalse;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidCardListParse
|
|
*
|
|
* Description:
|
|
*
|
|
* Assumes the passed value_string and ptr_return are non-NULL.
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
static XpOidCardList*
|
|
XpOidCardListParse(const char* value_string,
|
|
const XpOidCardList* valid_cards,
|
|
const char** ptr_return,
|
|
int i)
|
|
{
|
|
unsigned long card;
|
|
XpOidCardList* list;
|
|
BOOL status;
|
|
|
|
/*
|
|
* get the next card from the value string, skipping values not
|
|
* found in the passed list of valid cards
|
|
*/
|
|
*ptr_return = value_string;
|
|
while((status = XpOidParseUnsignedValue(*ptr_return, ptr_return, &card))
|
|
&&
|
|
(const XpOidCardList*)NULL != valid_cards
|
|
&&
|
|
!XpOidCardListHasCard(valid_cards, card)
|
|
);
|
|
|
|
if(xFalse == status)
|
|
{
|
|
if('\0' == **ptr_return)
|
|
{
|
|
if(0 == i)
|
|
{
|
|
/*
|
|
* empty value string
|
|
*/
|
|
return (XpOidCardList*)NULL;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* done parsing; allocate the list and return
|
|
*/
|
|
list = (XpOidCardList*)XpOidCalloc(1, sizeof(XpOidCardList));
|
|
list->count = i;
|
|
list->list =
|
|
(unsigned long*)XpOidCalloc(i, sizeof(unsigned long));
|
|
return list;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* parsing error
|
|
*/
|
|
ErrorF("%s\n", XPMSG_WARN_CARD_LIST);
|
|
return (XpOidCardList*)NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* recurse to parse remaining cardinal values
|
|
*/
|
|
list = XpOidCardListParse(*ptr_return, valid_cards, ptr_return, i+1);
|
|
if((XpOidCardList*)NULL != list)
|
|
{
|
|
/*
|
|
* add this value to the list
|
|
*/
|
|
list->list[i] = card;
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseBoolValue
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Return value:
|
|
*
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseBoolValue(const char* value_string,
|
|
const char** ptr_return,
|
|
BOOL* bool_return)
|
|
{
|
|
const char* ptr;
|
|
int length;
|
|
BOOL status;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* get the whitespace-delimited token length
|
|
*/
|
|
length = SpanToken(ptr);
|
|
/*
|
|
* determine if true or false or bad
|
|
*/
|
|
if(StrnCaseCmp(ptr, "TRUE", length) == 0)
|
|
{
|
|
if(bool_return != (BOOL*)NULL)
|
|
*bool_return = xTrue;
|
|
status = xTrue;
|
|
}
|
|
else if(StrnCaseCmp(ptr, "FALSE", length) == 0)
|
|
{
|
|
if(bool_return != (BOOL*)NULL)
|
|
*bool_return = xFalse;
|
|
status = xTrue;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* syntax error
|
|
*/
|
|
status = xFalse;
|
|
}
|
|
/*
|
|
* update the return pointer and return
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = status ? ptr+length : ptr;
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: XpOidParseUnsignedValue
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out and returns a unsigned number.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if a unsigned number was successfully parsed. ptr_return is
|
|
* updated to point to location where the unsigned number parsing
|
|
* ended.
|
|
*
|
|
* xFalse if a unsigned number was not found; ptr_return is updated
|
|
* to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
BOOL
|
|
XpOidParseUnsignedValue(const char* value_string,
|
|
const char** ptr_return,
|
|
unsigned long* unsigned_return)
|
|
{
|
|
long value;
|
|
BOOL status;
|
|
const char* first_nonws_ptr;
|
|
const char* ptr;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
first_nonws_ptr = value_string + SpanWhitespace(value_string);
|
|
value = strtol(first_nonws_ptr, (char**)(&ptr), 0);
|
|
if(ptr == first_nonws_ptr || value < 0)
|
|
status = xFalse;
|
|
else
|
|
status = xTrue;
|
|
/*
|
|
* update return parms
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
if(unsigned_return != (unsigned long*)NULL)
|
|
*unsigned_return = (unsigned long)value;
|
|
/*
|
|
* return
|
|
*/
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseRealValue
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out and returns a real number.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if a real number was successfully parsed. ptr_return is
|
|
* updated to point to location where the real number parsing
|
|
* ended.
|
|
*
|
|
* xFalse if a real number was not found; ptr_return is updated
|
|
* to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseRealValue(const char* value_string,
|
|
const char** ptr_return,
|
|
float* real_return)
|
|
{
|
|
float real_value;
|
|
BOOL status;
|
|
const char* first_nonws_ptr;
|
|
const char* ptr;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
first_nonws_ptr = value_string + SpanWhitespace(value_string);
|
|
real_value = (float)strtod(first_nonws_ptr, (char**)(&ptr));
|
|
if(ptr == first_nonws_ptr)
|
|
status = xFalse;
|
|
else
|
|
status = xTrue;
|
|
/*
|
|
* update return parms
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
if(real_return != (float*)NULL)
|
|
*real_return = real_value;
|
|
/*
|
|
* return
|
|
*/
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseSeqEnd
|
|
*
|
|
* Description:
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out the sequence end
|
|
* character '}'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the sequence end character was parsed; ptr_return is
|
|
* updated to point to the first char following the sequence end
|
|
* character.
|
|
*
|
|
* xFalse if the sequence end character was not found; ptr_return is
|
|
* updated to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseSeqEnd(const char* value_string,
|
|
const char** ptr_return)
|
|
{
|
|
const char* ptr;
|
|
BOOL status;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* parse out the sequence end character
|
|
*/
|
|
if(*ptr == '}')
|
|
{
|
|
status = xTrue;
|
|
++ptr;
|
|
}
|
|
else
|
|
status = xFalse;
|
|
/*
|
|
* update the return pointer
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
/*
|
|
* return
|
|
*/
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseSeqStart
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out the sequence start
|
|
* character '{'.
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if the sequence start character was parsed; ptr_return is
|
|
* updated to point to the first char following the sequence start
|
|
* character.
|
|
*
|
|
* xFalse if the sequence start character was not found; ptr_return is
|
|
* updated to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseSeqStart(const char* value_string,
|
|
const char** ptr_return)
|
|
{
|
|
const char* ptr;
|
|
BOOL status;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* parse out the sequence start character
|
|
*/
|
|
if(*ptr == '{')
|
|
{
|
|
status = xTrue;
|
|
++ptr;
|
|
}
|
|
else
|
|
status = xFalse;
|
|
/*
|
|
* update the return pointer
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
/*
|
|
* return
|
|
*/
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: ParseUnspecifiedValue
|
|
*
|
|
* Description:
|
|
*
|
|
* Skips leading whitespace and parses out an unspecified optional
|
|
* value (i.e. matching '' or "" - skips all data between the set of
|
|
* quotes).
|
|
*
|
|
* Return value:
|
|
*
|
|
* xTrue if an unspecified value was parsed; ptr_return is updated to
|
|
* point to the first char following the trailing quote.
|
|
*
|
|
* xFalse if an unspecified value was not found; ptr_return is updated
|
|
* to point to the first non-whitespace char in value_string.
|
|
*
|
|
*/
|
|
static BOOL
|
|
ParseUnspecifiedValue(const char* value_string,
|
|
const char** ptr_return)
|
|
{
|
|
BOOL status;
|
|
const char* ptr;
|
|
/*
|
|
* skip leading whitespace
|
|
*/
|
|
ptr = value_string + SpanWhitespace(value_string);
|
|
/*
|
|
* parse out an unspecified optional value ('' or "")
|
|
*/
|
|
if(*ptr == '\'' || *ptr == '"')
|
|
{
|
|
char delim[2];
|
|
|
|
if(ptr_return != (const char**)NULL)
|
|
{
|
|
delim[0] = *ptr;
|
|
delim[1] = '\0';
|
|
/*
|
|
* skip over the matching delimiter
|
|
*/
|
|
++ptr;
|
|
ptr += strcspn(ptr, delim);
|
|
if(*ptr != '\0')
|
|
++ptr;
|
|
}
|
|
status = xTrue;
|
|
}
|
|
else
|
|
status = xFalse;
|
|
/*
|
|
* update the return pointer
|
|
*/
|
|
if(ptr_return != (const char**)NULL)
|
|
*ptr_return = ptr;
|
|
/*
|
|
* return
|
|
*/
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: SpanToken
|
|
*
|
|
* Description:
|
|
*
|
|
* Returns the length of the initial segment of the passed string
|
|
* that consists entirely of non-whitespace and non-sequence
|
|
* delimiter characters.
|
|
*
|
|
*
|
|
*/
|
|
static int
|
|
SpanToken(const char* string)
|
|
{
|
|
const char* ptr;
|
|
for(ptr = string;
|
|
*ptr != '\0' && !isspace(*ptr) && *ptr != '{' && *ptr != '}';
|
|
++ptr);
|
|
return ptr - string;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: SpanWhitespace
|
|
*
|
|
* Description:
|
|
*
|
|
* Returns the length of the initial segment of the passed string
|
|
* that consists entirely of whitespace characters.
|
|
*
|
|
*
|
|
*/
|
|
static int
|
|
SpanWhitespace(const char* string)
|
|
{
|
|
const char* ptr;
|
|
for(ptr = string; *ptr != '\0' && isspace(*ptr); ++ptr);
|
|
return ptr - string;
|
|
}
|
|
|
|
#ifndef HAVE_STRCASECMP
|
|
/*
|
|
* ------------------------------------------------------------------------
|
|
* Name: StrnCaseCmp
|
|
*
|
|
* Description:
|
|
*
|
|
* Implements strncasecmp() for those platforms that need it.
|
|
*
|
|
*
|
|
*/
|
|
static int
|
|
StrnCaseCmp(const char *s1, const char *s2, size_t len)
|
|
{
|
|
char c1, c2;
|
|
int result;
|
|
|
|
while (len--)
|
|
{
|
|
c1 = *s1++;
|
|
c2 = *s2++;
|
|
result = tolower(c1) - tolower(c2);
|
|
|
|
if (result != 0)
|
|
return result;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|