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
 |