#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "attributes.h"
#define NOTIFY_EMAIL_STR "{{event-report-job-completed} electronic-mail}"
#define NOTIFY_NONE_STR "{}"
#define SafeStrLen(s) ((s) ? strlen((s)) : 0)
typedef struct _XpOidStringMapEntry
{
const char* string;
int length;
int msg_set;
int msg_number;
const char* default_message;
} XpOidStringMapEntry;
#include "OidStrs.h"
static XpOid XpOidParse(const char* value_string,
const char** ptr_return);
static XpOidList* XpOidListParse(const char* value_string,
const XpOidList* valid_oids,
const char** ptr_return, int i);
static XpOidCardList* XpOidCardListParse(const char* value_string,
const XpOidCardList* valid_cards,
const char** ptr_return, int i);
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);
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);
static BOOL XpOidDocFmtNext(XpOidDocFmt* doc_fmt,
const char* value_string,
const char** ptr_return);
static XpOidDocFmtList* XpOidDocFmtListParse(const char* value_string,
const XpOidDocFmtList* valid_fmts,
const char** ptr_return, int i);
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);
#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
const char*
XpOidString(XpOid xp_oid)
{
return XpOidStringMap[xp_oid].string;
}
int
XpOidStringLength(XpOid xp_oid)
{
return XpOidStringMap[xp_oid].length;
}
XpOid
XpOidFromString(const char* value)
{
if(value == (const char*)NULL)
return xpoid_none;
else
return XpOidParse(value, (const char**)NULL);
}
static XpOid
XpOidParse(const char* value_string,
const char** ptr_return)
{
const char* ptr;
int length;
int i;
ptr = value_string + SpanWhitespace(value_string);
length = SpanToken(ptr);
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;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr+length;
return i;
}
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);
}
}
void
XpOidListDelete(XpOidList* list)
{
if(list != (XpOidList*)NULL)
{
XpOidFree((char*)list->list);
XpOidFree((char*)list);
}
}
static XpOidList*
XpOidListParse(const char* value_string,
const XpOidList* valid_oids,
const char** ptr_return,
int i)
{
XpOid oid;
XpOidList* list;
ptr_return = &value_string;
while(1)
{
if(**ptr_return == '\0')
{
oid = xpoid_none;
break;
}
oid = XpOidParse(*ptr_return, ptr_return);
if(xpoid_none == oid)
{
continue;
}
if((const XpOidList*)NULL == valid_oids
||
XpOidListHasOid(valid_oids, oid))
{
break;
}
}
if(oid == xpoid_none)
{
list = (XpOidList*)XpOidCalloc(1, sizeof(XpOidList));
list->count = i;
list->list = (XpOid*)XpOidCalloc(i, sizeof(XpOid));
}
else
{
list = XpOidListParse(*ptr_return, valid_oids, ptr_return, i+1);
list->list[i] = oid;
}
return list;
}
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;
}
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;
}
char*
XpOidListString(const XpOidList* me)
{
int i;
int length;
char* str;
char* ptr;
for(i = 0, length = 0; i < XpOidListCount(me); i++)
length += XpOidStringLength(XpOidListGetOid(me, i)) + 1;
str = XpOidMalloc(length+1);
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
str[length] = '\0';
return str;
}
XpOidLinkedList*
XpOidLinkedListNew()
{
return (XpOidLinkedList*)XpOidCalloc(1, sizeof(XpOidLinkedList));
}
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);
}
}
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;
}
}
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;
}
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;
}
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;
}
XpOid
XpOidLinkedListFirstOid(XpOidLinkedList* me)
{
if((XpOidLinkedList*)NULL != me && (me->current = me->head))
return me->current->oid;
else
return xpoid_none;
}
XpOid
XpOidLinkedListNextOid(XpOidLinkedList* me)
{
if(me->current ? (me->current = me->current->next) : xFalse)
return me->current->oid;
else
return xpoid_none;
}
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);
}
}
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;
if(ParseSeqStart(value_string, ptr_return))
{
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;
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);
}
}
}
mss.ms.continuous_size =
MediumContinuousSizeParse(*ptr_return, ptr_return);
if(mss.ms.continuous_size != (XpOidMediumContinuousSize*)NULL)
{
mss.mstag = XpOidMediumSS_CONTINUOUS;
}
else
{
mss.ms.discrete =
MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
ptr_return, 0);
if(mss.ms.discrete == (XpOidMediumDiscreteSizeList*)NULL)
{
const char* tray_str;
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;
}
if(!ParseSeqEnd(*ptr_return, ptr_return))
{
ErrorF("%s\nSequence End expected. Unparsed data: %s\n",
XPMSG_WARN_MSS, *ptr_return);
return NULL;
}
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)
{
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)
return NULL;
}
if(xpoid_none != mss.input_tray)
{
memmove((medium_ss->mss)+i, &mss, sizeof(XpOidMediumSourceSize));
}
}
else
{
if(**ptr_return == '\0')
{
if(0 == i)
{
ErrorF("%s\nNo valid trays found.\n", XPMSG_WARN_MSS);
return NULL;
}
medium_ss = (XpOidMediumSS*)XpOidCalloc(1, sizeof(XpOidMediumSS));
medium_ss->count = i;
medium_ss->mss = (XpOidMediumSourceSize*)
XpOidCalloc(i, sizeof(XpOidMediumSourceSize));
}
else
{
ErrorF("%s\nSequence Start expected.\nunparsed data: %s\n",
XPMSG_WARN_MSS, *ptr_return);
return NULL;
}
}
return medium_ss;
}
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);
}
}
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:
break;
}
}
return xFalse;
}
char* XpOidMediumSSString(const XpOidMediumSS* me)
{
int itray, isize;
int valid_size_count;
int length;
char* str;
char* ptr;
XpOidMediumDiscreteSize* ds;
char buf[128];
for(itray = 0, length = 0; itray < XpOidMediumSSCount(me); itray++)
{
if(xpoid_none == me->mss[itray].input_tray
||
XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag)
{
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;
#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;
}
if(valid_size_count == 0)
{
continue;
}
if(xpoid_unspecified == me->mss[itray].input_tray)
length += 2;
else
length += XpOidStringLength(me->mss[itray].input_tray);
length += 4;
}
str = XpOidMalloc(length+1);
for(itray = 0, ptr = str; itray < XpOidMediumSSCount(me); itray++)
{
if(xpoid_none == me->mss[itray].input_tray
||
XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag)
{
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)
++valid_size_count;
}
if(valid_size_count == 0)
{
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
}
str[length] = '\0';
return str;
}
static XpOidMediumContinuousSize*
MediumContinuousSizeParse(const char* value_string,
const char** ptr_return)
{
const char* first_nonws_ptr;
XpOidMediumContinuousSize* mcs = NULL;
first_nonws_ptr = value_string + SpanWhitespace(value_string);
if(!ParseSeqStart(first_nonws_ptr, ptr_return))
goto MediumContinuousSizeParse_error;
if(!ParseSeqStart(*ptr_return, (const char**)NULL))
goto MediumContinuousSizeParse_error;
mcs = (XpOidMediumContinuousSize*)
XpOidCalloc(1, sizeof(XpOidMediumContinuousSize));
if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_across_feed))
goto MediumContinuousSizeParse_error;
if(!ParseUnspecifiedValue(*ptr_return, ptr_return))
if(!ParseRealValue(*ptr_return, ptr_return,
&mcs->increment_across_feed))
goto MediumContinuousSizeParse_error;
if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_in_feed))
goto MediumContinuousSizeParse_error;
if(!ParseUnspecifiedValue(*ptr_return, ptr_return))
if(!ParseRealValue(*ptr_return, ptr_return,
&mcs->increment_in_feed))
goto MediumContinuousSizeParse_error;
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;
if(!ParseArea(*ptr_return, ptr_return, &mcs->assured_reproduction_area))
goto MediumContinuousSizeParse_error;
if(!ParseSeqEnd(*ptr_return, ptr_return))
goto MediumContinuousSizeParse_error;
return mcs;
MediumContinuousSizeParse_error:
*ptr_return = first_nonws_ptr;
XpOidFree((char*)mcs);
return NULL;
}
static void
MediumContinuousSizeDelete(XpOidMediumContinuousSize* me)
{
XpOidFree((char*)me);
}
static XpOidMediumDiscreteSizeList*
MediumDiscreteSizeListParse(const char* value_string,
const XpOidList* valid_medium_sizes,
const char** ptr_return,
int i)
{
XpOidMediumDiscreteSizeList* list;
XpOidMediumDiscreteSize mds;
if(ParseSeqStart(value_string, ptr_return))
{
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;
if(ParseUnspecifiedValue(*ptr_return, ptr_return))
mds.long_edge_feeds = xTrue;
else
if(!ParseBoolValue(*ptr_return, ptr_return,
&mds.long_edge_feeds))
{
ErrorF("%s\nBoolean expected.\nunparsed data: %s\n",
XPMSG_WARN_MSS, *ptr_return);
return (XpOidMediumDiscreteSizeList*)NULL;
}
if(!ParseArea(*ptr_return, ptr_return,
&mds.assured_reproduction_area))
{
ErrorF("%s\nArea specification error.\nunparsed data: %s\n",
XPMSG_WARN_MSS, *ptr_return);
return (XpOidMediumDiscreteSizeList*)NULL;
}
if(!ParseSeqEnd(*ptr_return, ptr_return))
{
ErrorF("%s\nSequence End expected. Unparsed data: %s\n",
XPMSG_WARN_MSS, *ptr_return);
return (XpOidMediumDiscreteSizeList*)NULL;
}
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)
{
memmove((list->list)+i, &mds, sizeof(XpOidMediumDiscreteSize));
}
}
}
else
{
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;
}
static void
MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list)
{
if(list != (XpOidMediumDiscreteSizeList*)NULL)
{
XpOidFree((char*)list->list);
XpOidFree((char*)list);
}
}
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;
}
}
void
XpOidTrayMediumListDelete(XpOidTrayMediumList* list)
{
if(list != (XpOidTrayMediumList*)NULL)
{
XpOidFree((char*)list->list);
XpOidFree((char*)list);
}
}
static XpOidTrayMediumList*
TrayMediumListParse(const char* value_string,
const XpOidList* valid_trays,
const char** ptr_return, int i)
{
XpOidTrayMedium tm;
XpOidTrayMediumList* list;
if(ParseSeqStart(value_string, ptr_return))
{
tm.input_tray = XpOidParse(*ptr_return, ptr_return);
if((XpOidList*)NULL != valid_trays
&&
!XpOidListHasOid(valid_trays, tm.input_tray)
)
tm.input_tray = xpoid_none;
tm.medium = XpOidParse(*ptr_return, ptr_return);
if(!ParseSeqEnd(*ptr_return, ptr_return))
{
ErrorF("%s\n", XPMSG_WARN_ITM);
return NULL;
}
list = TrayMediumListParse(*ptr_return, valid_trays, ptr_return, i+1);
if(list != (XpOidTrayMediumList*)NULL)
{
memmove((list->list)+i, &tm, sizeof(XpOidTrayMedium));
}
}
else
{
if(**ptr_return == '\0')
{
list = (XpOidTrayMediumList*)
XpOidCalloc(1, sizeof(XpOidTrayMediumList));
list->count = i;
list->list = (XpOidTrayMedium*)
XpOidCalloc(i, sizeof(XpOidTrayMedium));
}
else
{
ErrorF("%s\n", XPMSG_WARN_ITM);
return NULL;
}
}
return list;
}
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;
}
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)
{
me->list[i_itm].input_tray = xpoid_none;
continue;
}
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:
break;
}
}
if(tray_ds == (XpOidMediumDiscreteSizeList*)NULL)
{
if(unspecified_tray_ds == (XpOidMediumDiscreteSizeList*)NULL)
{
me->list[i_itm].input_tray = xpoid_none;
continue;
}
else
tray_ds = unspecified_tray_ds;
}
for(i_ds = 0; i_ds < tray_ds->count; i_ds++)
{
if((tray_ds->list)[i_ds].page_size == current_medium)
{
break;
}
}
if(i_ds == tray_ds->count)
{
me->list[i_itm].input_tray = xpoid_none;
}
}
}
char* XpOidTrayMediumListString(const XpOidTrayMediumList* me)
{
int i;
int length;
char* str;
char* ptr;
XpOid tray;
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);
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
}
}
str[length] = '\0';
return str;
}
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;
}
static BOOL
ParseArea(const char* value_string,
const char** ptr_return,
XpOidArea* area_return)
{
const char* first_nonws_ptr;
const char* ptr;
first_nonws_ptr = value_string + SpanWhitespace(value_string);
if(!ParseSeqStart(first_nonws_ptr, &ptr))
goto ParseArea_error;
if(!ParseRealValue(ptr, &ptr,
area_return ? &area_return->minimum_x : NULL))
goto ParseArea_error;
if(!ParseRealValue(ptr, &ptr,
area_return ? &area_return->maximum_x : NULL))
goto ParseArea_error;
if(!ParseRealValue(ptr, &ptr,
area_return ? &area_return->minimum_y : NULL))
goto ParseArea_error;
if(!ParseRealValue(ptr, &ptr,
area_return ? &area_return->maximum_y : NULL))
goto ParseArea_error;
if(!ParseSeqEnd(ptr, &ptr))
goto ParseArea_error;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
return xTrue;
ParseArea_error:
if(ptr_return != (const char**)NULL)
*ptr_return = first_nonws_ptr;
return xFalse;
}
static BOOL
ParseRealRange(const char* value_string,
const char** ptr_return,
XpOidRealRange* range_return)
{
const char* first_nonws_ptr;
const char* ptr;
first_nonws_ptr = value_string + SpanWhitespace(value_string);
if(!ParseSeqStart(first_nonws_ptr, &ptr))
goto ParseRealRange_error;
if(!ParseRealValue(ptr, &ptr,
range_return ? &range_return->lower_bound : NULL))
goto ParseRealRange_error;
if(!ParseRealValue(ptr, &ptr,
range_return ? &range_return->upper_bound : NULL))
goto ParseRealRange_error;
if(!ParseSeqEnd(ptr, &ptr))
goto ParseRealRange_error;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
return xTrue;
ParseRealRange_error:
if(ptr_return != (const char**)NULL)
*ptr_return = first_nonws_ptr;
return xFalse;
}
XpOidNotify XpOidNotifyParse(const char* value_string)
{
const char* ptr = value_string;
if(value_string == (const char*)NULL)
return XPOID_NOTIFY_NONE;
if(!ParseSeqStart(value_string, &ptr))
{
if('\0' == *ptr)
return XPOID_NOTIFY_NONE;
else
return XPOID_NOTIFY_UNSUPPORTED;
}
if(!ParseSeqStart(ptr, &ptr))
{
if(ParseSeqEnd(ptr, &ptr))
{
ptr += SpanWhitespace(ptr);
if(*ptr == '\0')
return XPOID_NOTIFY_NONE;
}
return XPOID_NOTIFY_UNSUPPORTED;
}
if(xpoid_val_event_report_job_completed != XpOidParse(ptr, &ptr))
return XPOID_NOTIFY_UNSUPPORTED;
if(!ParseSeqEnd(ptr, &ptr))
return XPOID_NOTIFY_UNSUPPORTED;
if(xpoid_val_delivery_method_electronic_mail != XpOidParse(ptr, &ptr))
return XPOID_NOTIFY_UNSUPPORTED;
if(!ParseSeqEnd(ptr, &ptr))
return XPOID_NOTIFY_UNSUPPORTED;
ptr += SpanWhitespace(ptr);
if('\0' == *ptr)
return XPOID_NOTIFY_EMAIL;
else
return XPOID_NOTIFY_UNSUPPORTED;
}
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;
}
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;
doc_fmt = (XpOidDocFmt*)XpOidCalloc(1, sizeof(XpOidDocFmt));
if(xTrue == XpOidDocFmtNext(doc_fmt, ptr, &ptr))
{
ptr += SpanWhitespace(ptr);
if('\0' == *ptr)
return doc_fmt;
}
XpOidDocFmtDelete(doc_fmt);
ErrorF("%s\n", XPMSG_WARN_DOC_FMT);
return (XpOidDocFmt*)NULL;
}
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);
}
}
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;
}
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;
ptr = value_string + SpanWhitespace(value_string);
first_nonws_ptr = ptr;
if(!ParseSeqStart(ptr, &ptr))
goto XpOidDocFmtNext_error;
ptr += SpanWhitespace(ptr);
format = ptr;
if(0 == (format_len = SpanToken(ptr)))
goto XpOidDocFmtNext_error;
ptr += format_len;
ptr += SpanWhitespace(ptr);
variant = ptr;
if(0 != (variant_len = SpanToken(ptr)))
{
ptr += variant_len;
ptr += SpanWhitespace(ptr);
version = ptr;
version_len = SpanToken(ptr);
ptr += version_len;
}
else
version_len = 0;
if(!ParseSeqEnd(ptr, &ptr))
goto XpOidDocFmtNext_error;
if((const char**)NULL != ptr_return)
*ptr_return = ptr;
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;
}
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;
}
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);
}
}
char*
XpOidDocFmtListString(const XpOidDocFmtList* list)
{
if((XpOidDocFmtList*)NULL != list)
{
if(0 < list->count)
{
int i;
int str_len;
char* str;
char* ptr;
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);
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;
}
static XpOidDocFmtList*
XpOidDocFmtListParse(const char* value_string,
const XpOidDocFmtList* valid_fmts,
const char** ptr_return,
int i)
{
XpOidDocFmt doc_fmt;
XpOidDocFmtList* list;
BOOL status;
*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)
{
return (XpOidDocFmtList*)NULL;
}
else
{
list =
(XpOidDocFmtList*)XpOidCalloc(1, sizeof(XpOidDocFmtList));
list->count = i;
list->list = (XpOidDocFmt*)XpOidCalloc(i, sizeof(XpOidDocFmt));
return list;
}
}
else
{
ErrorF("%s\n", XPMSG_WARN_DOCFMT_LIST);
return (XpOidDocFmtList*)NULL;
}
}
else
{
list = XpOidDocFmtListParse(*ptr_return, valid_fmts, ptr_return, i+1);
if((XpOidDocFmtList*)NULL != list)
{
list->list[i].format = doc_fmt.format;
list->list[i].variant = doc_fmt.variant;
list->list[i].version = doc_fmt.version;
}
return list;
}
}
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++)
{
if(strcmp(fmt->format, list->list[i].format) != 0)
continue;
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;
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;
}
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;
}
void
XpOidCardListDelete(XpOidCardList* list)
{
if((XpOidCardList*)NULL != list)
{
XpOidFree(list->list);
XpOidFree(list);
}
}
char*
XpOidCardListString(const XpOidCardList* list)
{
if((XpOidCardList*)NULL != list)
{
char buf[48];
int str_len;
char* str;
int i;
char* ptr;
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);
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;
}
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;
}
static XpOidCardList*
XpOidCardListParse(const char* value_string,
const XpOidCardList* valid_cards,
const char** ptr_return,
int i)
{
unsigned long card;
XpOidCardList* list;
BOOL status;
*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)
{
return (XpOidCardList*)NULL;
}
else
{
list = (XpOidCardList*)XpOidCalloc(1, sizeof(XpOidCardList));
list->count = i;
list->list =
(unsigned long*)XpOidCalloc(i, sizeof(unsigned long));
return list;
}
}
else
{
ErrorF("%s\n", XPMSG_WARN_CARD_LIST);
return (XpOidCardList*)NULL;
}
}
else
{
list = XpOidCardListParse(*ptr_return, valid_cards, ptr_return, i+1);
if((XpOidCardList*)NULL != list)
{
list->list[i] = card;
}
return list;
}
}
static BOOL
ParseBoolValue(const char* value_string,
const char** ptr_return,
BOOL* bool_return)
{
const char* ptr;
int length;
BOOL status;
ptr = value_string + SpanWhitespace(value_string);
length = SpanToken(ptr);
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
{
status = xFalse;
}
if(ptr_return != (const char**)NULL)
*ptr_return = status ? ptr+length : ptr;
return status;
}
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;
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;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
if(unsigned_return != (unsigned long*)NULL)
*unsigned_return = (unsigned long)value;
return status;
}
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;
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;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
if(real_return != (float*)NULL)
*real_return = real_value;
return status;
}
static BOOL
ParseSeqEnd(const char* value_string,
const char** ptr_return)
{
const char* ptr;
BOOL status;
ptr = value_string + SpanWhitespace(value_string);
if(*ptr == '}')
{
status = xTrue;
++ptr;
}
else
status = xFalse;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
return status;
}
static BOOL
ParseSeqStart(const char* value_string,
const char** ptr_return)
{
const char* ptr;
BOOL status;
ptr = value_string + SpanWhitespace(value_string);
if(*ptr == '{')
{
status = xTrue;
++ptr;
}
else
status = xFalse;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
return status;
}
static BOOL
ParseUnspecifiedValue(const char* value_string,
const char** ptr_return)
{
BOOL status;
const char* ptr;
ptr = value_string + SpanWhitespace(value_string);
if(*ptr == '\'' || *ptr == '"')
{
char delim[2];
if(ptr_return != (const char**)NULL)
{
delim[0] = *ptr;
delim[1] = '\0';
++ptr;
ptr += strcspn(ptr, delim);
if(*ptr != '\0')
++ptr;
}
status = xTrue;
}
else
status = xFalse;
if(ptr_return != (const char**)NULL)
*ptr_return = ptr;
return status;
}
static int
SpanToken(const char* string)
{
const char* ptr;
for(ptr = string;
*ptr != '\0' && !isspace(*ptr) && *ptr != '{' && *ptr != '}';
++ptr);
return ptr - string;
}
static int
SpanWhitespace(const char* string)
{
const char* ptr;
for(ptr = string; *ptr != '\0' && isspace(*ptr); ++ptr);
return ptr - string;
}
#ifndef HAVE_STRCASECMP
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