First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xprint / Oid.c
bloba2af00108ef60e918be74c0204b25057ffdbd5a9
1 /*
2 (c) Copyright 1996 Hewlett-Packard Company
3 (c) Copyright 1996 International Business Machines Corp.
4 (c) Copyright 1996 Sun Microsystems, Inc.
5 (c) Copyright 1996 Novell, Inc.
6 (c) Copyright 1996 Digital Equipment Corp.
7 (c) Copyright 1996 Fujitsu Limited
8 (c) Copyright 1996 Hitachi, Ltd.
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 Except as contained in this notice, the names of the copyright holders shall
28 not be used in advertising or otherwise to promote the sale, use or other
29 dealings in this Software without prior written authorization from said
30 copyright holders.
33 #ifdef HAVE_DIX_CONFIG_H
34 #include <dix-config.h>
35 #endif
37 #include "attributes.h"
40 * XpOidNotify value strings
42 #define NOTIFY_EMAIL_STR "{{event-report-job-completed} electronic-mail}"
43 #define NOTIFY_NONE_STR "{}"
45 #define SafeStrLen(s) ((s) ? strlen((s)) : 0)
48 * entry type for the object identifier string map
50 typedef struct _XpOidStringMapEntry
52 const char* string;
53 int length;
54 int msg_set;
55 int msg_number;
56 const char* default_message;
58 } XpOidStringMapEntry;
61 * include the auto-generated static XpOidStringMap
63 #include "OidStrs.h"
66 * XpOid static function declarations
68 static XpOid XpOidParse(const char* value_string,
69 const char** ptr_return);
71 * XpOidList static function declarations
73 static XpOidList* XpOidListParse(const char* value_string,
74 const XpOidList* valid_oids,
75 const char** ptr_return, int i);
78 * XpOidList static function declarations
80 static XpOidCardList* XpOidCardListParse(const char* value_string,
81 const XpOidCardList* valid_cards,
82 const char** ptr_return, int i);
85 * XpOidMediumSourceSize static function declarations
87 static XpOidMediumSS* MediumSSParse(const char* value_string,
88 const XpOidList* valid_trays,
89 const XpOidList* valid_medium_sizes,
90 const char** ptr_return, int i);
91 static XpOidMediumContinuousSize* MediumContinuousSizeParse(const char*,
92 const char**);
93 static void MediumContinuousSizeDelete(XpOidMediumContinuousSize* me);
94 static XpOidMediumDiscreteSizeList* MediumDiscreteSizeListParse(const char*,
95 const XpOidList*,
96 const char**,
97 int i);
98 static void MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list);
100 static BOOL ParseArea(const char* value_string,
101 const char** ptr_return,
102 XpOidArea* area_return);
103 static BOOL ParseRealRange(const char* value_string,
104 const char** ptr_return,
105 XpOidRealRange* range_return);
108 * XpOidTrayMediumList static function declarations
110 static XpOidTrayMediumList* TrayMediumListParse(const char* value_string,
111 const XpOidList* valid_trays,
112 const char** ptr_return,
113 int i);
114 static void TrayMediumListValidate(XpOidTrayMediumList* me,
115 const XpOidMediumSS* msss);
118 * XpOidDocFmt
120 static BOOL XpOidDocFmtNext(XpOidDocFmt* doc_fmt,
121 const char* value_string,
122 const char** ptr_return);
125 * XpOidDocFmtListParse
127 static XpOidDocFmtList* XpOidDocFmtListParse(const char* value_string,
128 const XpOidDocFmtList* valid_fmts,
129 const char** ptr_return, int i);
132 * misc. parsing static function declarations
134 static BOOL ParseBoolValue(const char* value_string,
135 const char** ptr_return,
136 BOOL* bool_return);
137 static BOOL ParseRealValue(const char* value_string,
138 const char** ptr_return,
139 float* real_return);
140 static BOOL ParseSeqEnd(
141 const char* value_string,
142 const char** ptr_return);
143 static BOOL ParseSeqStart(
144 const char* value_string,
145 const char** ptr_return);
146 static BOOL ParseUnspecifiedValue(
147 const char* value_string,
148 const char** ptr_return);
149 static int SpanToken(
150 const char* string);
151 static int SpanWhitespace(
152 const char* string);
155 * String comparison function.
157 #ifdef HAVE_STRCASECMP
158 # define StrnCaseCmp(s1, s2, len) strncasecmp(s1, s2, len)
159 #else
160 static int StrnCaseCmp(const char *s1, const char *s2, size_t len);
161 #endif
164 * ------------------------------------------------------------------------
165 * Name: XpOidString
167 * Description:
169 * Obtain the string representation of an XpOid.
171 * Example: XpOidString(xpoid_copy_count) returns "copy-count".
173 * Return value:
175 * A const pointer to the string.
177 const char*
178 XpOidString(XpOid xp_oid)
181 * XpOid enum values are index values into the string map
183 return XpOidStringMap[xp_oid].string;
187 * ------------------------------------------------------------------------
188 * Name: XpOidStringLength
190 * Description:
192 * Obtain the length of the string representation for a given
193 * XpOid.
195 * Return value:
197 * The string length in bytes.
201 XpOidStringLength(XpOid xp_oid)
204 * XpOid enum values are index values into the string map
206 return XpOidStringMap[xp_oid].length;
210 * ------------------------------------------------------------------------
211 * Name: XpOidFromString
213 * Description:
215 * Obtains the XpOid given a string representation of an XpOid.
217 * Example: XpOidFromString("copy-count") returns 'xpoid_copy_count'.
219 * Return value:
221 * The XpOid if successful. 'xpoid_none' if the string pointed to by
222 * 'value is not recognized or if 'value' is NULL.
224 XpOid
225 XpOidFromString(const char* value)
227 if(value == (const char*)NULL)
228 return xpoid_none;
229 else
230 return XpOidParse(value, (const char**)NULL);
234 * ------------------------------------------------------------------------
235 * Name: XpOidParse
237 * Description:
239 * Parse the next whitespace-delimited string from 'value_string'
240 * updating 'ptr_return' to point to the next unparsed location in
241 * 'value_string'. 'ptr_return' can be NULL.
243 * Return value:
245 * The corresponding XpOid for the parsed name string.
246 * A return value of xpoid_none is returned if the parsed name
247 * was not a valid oid or if no name was found.
250 static XpOid
251 XpOidParse(const char* value_string,
252 const char** ptr_return)
254 const char* ptr;
255 int length;
256 int i;
258 * skip leading whitespace
260 ptr = value_string + SpanWhitespace(value_string);
262 * get the whitespace-delimited token length
264 length = SpanToken(ptr);
266 * match the oid string in the map
268 for(i = 0; i < XpOidStringMapCount; i++)
269 if(length == XpOidStringMap[i].length)
270 if(strncmp(ptr, XpOidStringMap[i].string, length) == 0)
271 break;
272 if(i == XpOidStringMapCount)
273 i = xpoid_none;
275 * update the return pointer and return
277 if(ptr_return != (const char**)NULL)
278 *ptr_return = ptr+length;
279 return i;
283 * ------------------------------------------------------------------------
284 * Name: XpOidListNew
286 * Description:
288 * Creates a new XpOidList initialized from a whitespace-delimited
289 * list of recognized string representations of oids. The returned
290 * list will contain only oids found within the passed 'valid_oids'
291 * XpOidList.
293 * Note: One may notice that in order to create an XpOidList with
294 * this function, an XpOidList is needed; the 'valid_oids' list
295 * is often an statically initialized structure. XpOidListInit
296 * can also be used.
298 * Return value:
300 * NULL if the passed 'value_string' is NULL.
302 * If the list indicated by 'value_string' is empty or contains only
303 * unrecognized oid string representations, a new XpOidList
304 * containing zero elements is returned.
306 * If 'valid_oids' is NULL all oids are considered valid.
309 XpOidList*
310 XpOidListNew(const char* value_string,
311 const XpOidList* valid_oids)
313 if(value_string == (const char*)NULL)
314 return (XpOidList*)NULL;
315 else
317 const char* ptr;
318 return XpOidListParse(value_string, valid_oids, &ptr, 0);
323 * ------------------------------------------------------------------------
324 * Name: XpOidListDelete
326 * Description:
328 * Frees the memory allocated for 'list'.
330 * Return value:
332 * None.
335 void
336 XpOidListDelete(XpOidList* list)
338 if(list != (XpOidList*)NULL)
340 XpOidFree((char*)list->list);
341 XpOidFree((char*)list);
346 * ------------------------------------------------------------------------
347 * Name: XpOidListParse
349 * Description:
351 * This function recursively parses the whitespace-delimited list of
352 * oid string representations passed via 'value_string'. Oids are
353 * only added to the resulting list if they are found within the
354 * passed 'valid_oids' XpOidList.
356 * 'ptr_return' points to a char* variable allocated by the
357 * caller, and is really only of use during recursion (upon return to
358 * the original caller, it will point to the end of value_string).
360 * 'value_string' and 'ptr_return' *cannot* be NULL.
362 * Return value:
364 * A newly allocated and initialized XpOidList.
366 * If the list indicated by 'value_string' is empty or contains only
367 * unrecognized oid string representations, a new XpOidList
368 * containing zero elements is returned.
370 * If 'valid_oids' is NULL all oids are considered valid.
373 static XpOidList*
374 XpOidListParse(const char* value_string,
375 const XpOidList* valid_oids,
376 const char** ptr_return,
377 int i)
379 XpOid oid;
380 XpOidList* list;
382 * parse the next valid oid out of the value string
384 ptr_return = &value_string;
385 while(1)
387 if(**ptr_return == '\0')
390 * end of value string; stop parsing
392 oid = xpoid_none;
393 break;
396 * parse the next oid from the value
398 oid = XpOidParse(*ptr_return, ptr_return);
399 if(xpoid_none == oid)
402 * unrecognized oid; keep parsing
404 continue;
406 if((const XpOidList*)NULL == valid_oids
408 XpOidListHasOid(valid_oids, oid))
411 * valid oid found; stop parsing
413 break;
417 if(oid == xpoid_none)
420 * end of value string; allocate the list structure
422 list = (XpOidList*)XpOidCalloc(1, sizeof(XpOidList));
423 list->count = i;
424 list->list = (XpOid*)XpOidCalloc(i, sizeof(XpOid));
426 else
429 * recurse
431 list = XpOidListParse(*ptr_return, valid_oids, ptr_return, i+1);
433 * set the oid in the list
435 list->list[i] = oid;
438 * return
440 return list;
444 * ------------------------------------------------------------------------
445 * Name: XpOidListHasOid
447 * Description:
449 * Determines if 'oid' is an element of 'list'.
451 * Return value:
453 * xTrue if the oid is found in the list.
455 * xFalse if the oid is not in the list, or if 'list' is NULL.
458 BOOL
459 XpOidListHasOid(const XpOidList* list, XpOid oid)
461 int i;
462 if(list != (XpOidList*)NULL)
463 for(i = 0; i < list->count; i++)
464 if(list->list[i] == oid)
465 return xTrue;
466 return xFalse;
470 * ------------------------------------------------------------------------
471 * Name: XpOidListGetIndex
473 * Description:
475 * Returns the array index of 'oid' in 'list'
477 * Return value:
479 * The index of 'oid' in list.
481 * -1 if the oid is not in the list, or if 'list' is NULL.
485 XpOidListGetIndex(const XpOidList* list, XpOid oid)
487 int i;
488 if(list != (XpOidList*)NULL)
489 for(i = 0; i < list->count; i++)
490 if(list->list[i] == oid)
491 return i;
492 return -1;
496 * ------------------------------------------------------------------------
497 * Name: XpOidListString
499 * Description:
501 * Creates a string representation of an XpOidList structure.
503 * Return value:
505 * A newly allocated
508 char*
509 XpOidListString(const XpOidList* me)
511 int i;
512 int length;
513 char* str;
514 char* ptr;
516 * allocate enough memory for the oid string representations,
517 * including intervening whitespace
519 for(i = 0, length = 0; i < XpOidListCount(me); i++)
520 length += XpOidStringLength(XpOidListGetOid(me, i)) + 1;
521 str = XpOidMalloc(length+1);
523 * format the list
525 for(i = 0, ptr = str; i < XpOidListCount(me); i++)
526 #if defined(sun) && !defined(SVR4)
528 sprintf(ptr, "%s ", XpOidString(XpOidListGetOid(me, i)));
529 ptr += strlen(ptr);
531 #else
532 ptr += sprintf(ptr, "%s ", XpOidString(XpOidListGetOid(me, i)));
533 #endif
535 * chop trailing whitespace or terminate empty string
537 str[length] = '\0';
539 * return
541 return str;
545 * ------------------------------------------------------------------------
546 * Name: XpOidLinkedListNew
548 * Description:
550 * Creates a new instance of an empty XpOidLinkedList.
552 * Return value:
554 * The new XpOidLinkedList.
557 XpOidLinkedList*
558 XpOidLinkedListNew()
560 return (XpOidLinkedList*)XpOidCalloc(1, sizeof(XpOidLinkedList));
564 * ------------------------------------------------------------------------
565 * Name: XpOidLinkedListDelete
567 * Description:
569 * Frees the memory allocated for a XpOidLinkedList.
571 * Return value:
573 * None.
576 void
577 XpOidLinkedListDelete(XpOidLinkedList* me)
579 if(me != (XpOidLinkedList*)NULL)
581 while(me->head)
583 me->current = me->head;
584 me->head = me->current->next;
585 XpOidFree((char*)me->current);
587 XpOidFree((char*)me);
592 * ------------------------------------------------------------------------
593 * Name: XpOidLinkedListGetOid
595 * Description:
597 * Retrieves the oid at position 'i' (zero-based) in the
598 * XpOidLinkedList 'me'.
600 * Return value:
602 * The oid at position 'i'.
604 * xpoid_none if the oid was not found, or the list is empty (or if
605 * the list contains xpoid_none at position 'i').
607 XpOid
608 XpOidLinkedListGetOid(XpOidLinkedList* me, int i)
610 if(me == (XpOidLinkedList*)NULL || i < 0 || i >= me->count)
612 return xpoid_none;
614 else
616 me->current = me->head;
617 while(i--) me->current = me->current->next;
618 return me->current->oid;
623 * ------------------------------------------------------------------------
624 * Name: XpOidLinkedListAddOid
626 * Description:
628 * Adds an oid to the end of an XpOidLinkedList.
630 * Return value:
632 * None.
635 void
636 XpOidLinkedListAddOid(XpOidLinkedList* me, XpOid oid)
638 me->current = (XpOidNode)XpOidCalloc(1, sizeof(struct XpOidNodeStruct));
639 me->current->oid = oid;
640 ++me->count;
641 if(me->tail)
643 me->tail->next = me->current;
644 me->tail = me->current;
646 else
647 me->head = me->tail = me->current;
651 * ------------------------------------------------------------------------
652 * Name: XpOidLinkedListGetIndex
654 * Description:
656 * Returns the position of an oid in a XpOidLinkedList.
658 * Return value:
660 * The zero-based position of 'oid' in the list.
662 * -1 if the oid is not in the list, or if 'me' is NULL.
666 XpOidLinkedListGetIndex(XpOidLinkedList* me, XpOid oid)
668 if((XpOidLinkedList*)NULL != me)
670 int i = 0;
671 me->current = me->head;
672 while(me->current)
673 if(me->current->oid == oid)
675 return i;
677 else
679 ++i;
680 me->current = me->current->next;
683 return -1;
687 * ------------------------------------------------------------------------
688 * Name: XpOidLinkedListHasOid
690 * Description:
692 * Determines if an oid is an element of a XpOidLinkedList.
694 * Return value:
696 * xTrue if the oid is found in the list.
698 * xFalse if the oid is not in the list, or if 'me' is NULL.
700 BOOL
701 XpOidLinkedListHasOid(XpOidLinkedList* me,
702 XpOid oid)
704 if((XpOidLinkedList*)NULL != me)
706 me->current = me->head;
707 while(me->current)
708 if(me->current->oid == oid)
709 return xTrue;
710 else
711 me->current = me->current->next;
713 return xFalse;
717 * ------------------------------------------------------------------------
718 * Name: XpOidLinkedListFirstOid
720 * Description:
722 * Positions the XpOidLinkedList 'current' pointer to the first entry
723 * in the list.
725 * Return value:
727 * The first oid in the list, or xpoid_none if the list NULL or
728 * empty.
730 XpOid
731 XpOidLinkedListFirstOid(XpOidLinkedList* me)
733 if((XpOidLinkedList*)NULL != me && (me->current = me->head))
734 return me->current->oid;
735 else
736 return xpoid_none;
740 * ------------------------------------------------------------------------
741 * Name: XpOidLinkedListNextOid
743 * Description:
745 * Positions the XpOidLinkedList 'current' pointer to the next entry
746 * in the list.
748 * Return value:
750 * The next oid, or xpoid_none if the end of the list has been
751 * reached.
753 XpOid
754 XpOidLinkedListNextOid(XpOidLinkedList* me)
756 if(me->current ? (me->current = me->current->next) : xFalse)
757 return me->current->oid;
758 else
759 return xpoid_none;
763 * ------------------------------------------------------------------------
764 * Name: XpOidMediumSSNew
766 * Description:
768 * Creates a new XpOidMediumSS initialized from a string value
769 * specified using the medium-source-sizes syntax. See
770 * MediumSSParse() below for parsing details.
772 * Return value:
774 * NULL if the passed 'value_string' is NULL, or if a syntax error is
775 * encountered while parsing the medium-source-sizes value.
778 XpOidMediumSS*
779 XpOidMediumSSNew(const char* value_string,
780 const XpOidList* valid_trays,
781 const XpOidList* valid_medium_sizes)
783 if(value_string == (const char*)NULL)
784 return (XpOidMediumSS*)NULL;
785 else
787 const char* ptr = value_string + SpanWhitespace(value_string);
788 if(*ptr == '\0')
789 return (XpOidMediumSS*)NULL;
790 else
791 return MediumSSParse(ptr, valid_trays, valid_medium_sizes,
792 &ptr, 0);
797 * ------------------------------------------------------------------------
798 * Name: MediumSSParse
800 * Description:
802 * 'ptr_return' *cannot* be NULL.
805 * Return value:
810 static XpOidMediumSS*
811 MediumSSParse(const char* value_string,
812 const XpOidList* valid_trays,
813 const XpOidList* valid_medium_sizes,
814 const char** ptr_return,
815 int i)
817 XpOidMediumSS* medium_ss;
818 XpOidMediumSourceSize mss;
820 * check for the start of a new MediumSourceSize sequence
822 if(ParseSeqStart(value_string, ptr_return))
825 * check for an unspecified tray value
827 if(ParseUnspecifiedValue(*ptr_return, ptr_return))
828 mss.input_tray = xpoid_unspecified;
829 else
831 const char* tray_str;
832 *ptr_return += SpanWhitespace(*ptr_return);
833 tray_str = *ptr_return;
835 * parse out the input tray
837 mss.input_tray = XpOidParse(*ptr_return, ptr_return);
838 if((const XpOidList*)NULL != valid_trays
840 !XpOidListHasOid(valid_trays, mss.input_tray)
842 mss.input_tray = xpoid_none;
843 if(xpoid_none == mss.input_tray)
845 char* invalid_tray_str;
846 int len = *ptr_return - tray_str;
847 if(len > 0)
849 invalid_tray_str = XpOidMalloc(len+1);
850 strncpy(invalid_tray_str, tray_str, len);
851 invalid_tray_str[len] = '\0';
852 ErrorF("%s\nInvalid tray (%s) found. Will attempt to continue parsing.\n",
853 XPMSG_WARN_MSS, invalid_tray_str);
854 XpOidFree(invalid_tray_str);
859 * attempt to parse a Continuous MediumSize sequence
861 mss.ms.continuous_size =
862 MediumContinuousSizeParse(*ptr_return, ptr_return);
863 if(mss.ms.continuous_size != (XpOidMediumContinuousSize*)NULL)
865 mss.mstag = XpOidMediumSS_CONTINUOUS;
867 else
870 * not continuous, try Discrete MediumSize
872 mss.ms.discrete =
873 MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
874 ptr_return, 0);
875 if(mss.ms.discrete == (XpOidMediumDiscreteSizeList*)NULL)
877 const char* tray_str;
879 * syntax error (MediumDiscreteSizeListParse reports error)
881 switch(mss.input_tray)
883 case xpoid_none:
884 tray_str = "an invalid";
885 break;
886 case xpoid_unspecified:
887 tray_str = "default (tray specifier omitted)";
888 break;
889 default:
890 tray_str = XpOidString(mss.input_tray);
891 break;
893 ErrorF("%s\nError occurred while parsing medium sizes for %s tray.\n",
894 XPMSG_WARN_MSS, tray_str);
895 return NULL;
897 mss.mstag = XpOidMediumSS_DISCRETE;
900 * parse out the MediumSourceSize sequence end
902 if(!ParseSeqEnd(*ptr_return, ptr_return))
905 * syntax error
907 ErrorF("%s\nSequence End expected. Unparsed data: %s\n",
908 XPMSG_WARN_MSS, *ptr_return);
909 return NULL;
912 * recurse to parse the next MediumSourceSize sequence
914 medium_ss = MediumSSParse(*ptr_return,
915 valid_trays, valid_medium_sizes,
916 ptr_return,
917 xpoid_none == mss.input_tray ? i : i+1);
918 if(medium_ss == (XpOidMediumSS*)NULL
920 xpoid_none == mss.input_tray)
923 * syntax error or invalid tray - clean up
925 switch(mss.mstag)
927 case XpOidMediumSS_CONTINUOUS:
928 MediumContinuousSizeDelete(mss.ms.continuous_size);
929 break;
930 case XpOidMediumSS_DISCRETE:
931 MediumDiscreteSizeListDelete(mss.ms.discrete);
932 break;
934 if(medium_ss == (XpOidMediumSS*)NULL)
936 * syntax error - return
938 return NULL;
940 if(xpoid_none != mss.input_tray)
943 * copy the current MediumSourceSize into the array
945 memmove((medium_ss->mss)+i, &mss, sizeof(XpOidMediumSourceSize));
948 else
951 * MediumSourceSize sequence start not found
953 if(**ptr_return == '\0')
955 if(0 == i)
957 ErrorF("%s\nNo valid trays found.\n", XPMSG_WARN_MSS);
958 return NULL;
961 * end of value string; allocate the MediumSS structure
963 medium_ss = (XpOidMediumSS*)XpOidCalloc(1, sizeof(XpOidMediumSS));
964 medium_ss->count = i;
965 medium_ss->mss = (XpOidMediumSourceSize*)
966 XpOidCalloc(i, sizeof(XpOidMediumSourceSize));
968 else
971 * syntax error
973 ErrorF("%s\nSequence Start expected.\nunparsed data: %s\n",
974 XPMSG_WARN_MSS, *ptr_return);
975 return NULL;
978 return medium_ss;
982 * ------------------------------------------------------------------------
983 * Name: XpOidMediumSSDelete
985 * Description:
989 * Return value:
994 void
995 XpOidMediumSSDelete(XpOidMediumSS* me)
997 if(me != (XpOidMediumSS*)NULL)
999 int i;
1000 for(i = 0; i < me->count; i++)
1002 switch((me->mss)[i].mstag)
1004 case XpOidMediumSS_CONTINUOUS:
1005 MediumContinuousSizeDelete((me->mss)[i].ms.continuous_size);
1006 break;
1007 case XpOidMediumSS_DISCRETE:
1008 MediumDiscreteSizeListDelete((me->mss)[i].ms.discrete);
1009 break;
1012 XpOidFree((char*)me);
1017 * ------------------------------------------------------------------------
1018 * Name: XpOidMediumSSHasSize
1020 * Description:
1024 * Return value:
1029 BOOL
1030 XpOidMediumSSHasSize(XpOidMediumSS* me, XpOid page_size)
1032 int i_mss, i_ds;
1033 XpOidMediumDiscreteSizeList* ds_list;
1035 if(me != (XpOidMediumSS*)NULL && page_size != xpoid_none)
1036 for(i_mss = 0; i_mss < me->count; i_mss++)
1038 switch((me->mss)[i_mss].mstag)
1040 case XpOidMediumSS_DISCRETE:
1041 ds_list = (me->mss)[i_mss].ms.discrete;
1042 for(i_ds = 0; i_ds < ds_list->count; i_ds++)
1043 if(page_size == (ds_list->list)[i_ds].page_size)
1044 return xTrue;
1045 break;
1047 case XpOidMediumSS_CONTINUOUS:
1049 * unsupported
1051 break;
1055 * return
1057 return xFalse;
1061 * ------------------------------------------------------------------------
1062 * Name: XpOidMediumSSString
1064 * Description:
1066 * Creates a string representation of an XpOidMediumSS structure.
1068 * Return value:
1070 * A newly allocated
1073 char* XpOidMediumSSString(const XpOidMediumSS* me)
1075 int itray, isize;
1076 int valid_size_count;
1077 int length;
1078 char* str;
1079 char* ptr;
1080 XpOidMediumDiscreteSize* ds;
1081 char buf[128];
1083 * determine the size of the string representation
1085 for(itray = 0, length = 0; itray < XpOidMediumSSCount(me); itray++)
1087 if(xpoid_none == me->mss[itray].input_tray
1089 XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag)
1092 * skip invalid tray or unsupported continuous size spec
1094 continue;
1096 for(isize = 0, valid_size_count = 0;
1097 isize < me->mss[itray].ms.discrete->count;
1098 isize++)
1100 ds = me->mss[itray].ms.discrete->list+isize;
1101 if(ds->page_size == xpoid_none)
1102 continue;
1103 ++valid_size_count;
1104 length += XpOidStringLength(ds->page_size);
1105 length += ds->long_edge_feeds ? 4 : 5; /* "True" or "False" */
1106 #if defined(sun) && !defined(SVR4)
1107 sprintf(buf, "{%.4f %.4f %.4f %.4f}",
1108 ds->assured_reproduction_area.minimum_x,
1109 ds->assured_reproduction_area.maximum_x,
1110 ds->assured_reproduction_area.minimum_y,
1111 ds->assured_reproduction_area.maximum_y);
1112 length += strlen(buf);
1113 #else
1114 length += sprintf(buf, "{%.4f %.4f %.4f %.4f}",
1115 ds->assured_reproduction_area.minimum_x,
1116 ds->assured_reproduction_area.maximum_x,
1117 ds->assured_reproduction_area.minimum_y,
1118 ds->assured_reproduction_area.maximum_y);
1119 #endif
1120 length += 5; /* "{<size> <feed> <area>} " */
1122 if(valid_size_count == 0)
1125 * no valid sizes, skip
1127 continue;
1129 if(xpoid_unspecified == me->mss[itray].input_tray)
1130 length += 2; /* "''" */
1131 else
1132 length += XpOidStringLength(me->mss[itray].input_tray);
1133 length += 4; /* "{<tray> <sizes>} " */
1136 * allocate
1138 str = XpOidMalloc(length+1);
1140 * format
1142 for(itray = 0, ptr = str; itray < XpOidMediumSSCount(me); itray++)
1144 if(xpoid_none == me->mss[itray].input_tray
1146 XpOidMediumSS_CONTINUOUS == me->mss[itray].mstag)
1149 * skip invalid tray or unsupported continuous size spec
1151 continue;
1154 * check to ensure all of the specified sizes are valid
1156 for(isize = 0, valid_size_count = 0;
1157 isize < me->mss[itray].ms.discrete->count;
1158 isize++)
1160 ds = me->mss[itray].ms.discrete->list+isize;
1161 if(ds->page_size != xpoid_none)
1162 ++valid_size_count;
1164 if(valid_size_count == 0)
1167 * no valid sizes, skip
1169 continue;
1172 if(xpoid_unspecified == me->mss[itray].input_tray)
1174 #if defined(sun) && !defined(SVR4)
1175 sprintf(ptr, "{'' ");
1176 ptr += strlen(ptr);
1177 #else
1178 ptr += sprintf(ptr, "{'' ");
1179 #endif
1181 else
1183 #if defined(sun) && !defined(SVR4)
1184 sprintf(ptr, "{%s ", XpOidString(me->mss[itray].input_tray));
1185 ptr += strlen(ptr);
1186 #else
1187 ptr += sprintf(ptr, "{%s ",
1188 XpOidString(me->mss[itray].input_tray));
1189 #endif
1191 for(isize = 0; isize < me->mss[itray].ms.discrete->count; isize++)
1193 ds = me->mss[itray].ms.discrete->list+isize;
1194 if(ds->page_size != xpoid_none)
1195 #if defined(sun) && !defined(SVR4)
1197 sprintf(ptr, "{%s %s {%.4f %.4f %.4f %.4f}} ",
1198 XpOidString(ds->page_size),
1199 ds->long_edge_feeds ? "True" : "False",
1200 ds->assured_reproduction_area.minimum_x,
1201 ds->assured_reproduction_area.maximum_x,
1202 ds->assured_reproduction_area.minimum_y,
1203 ds->assured_reproduction_area.maximum_y);
1204 ptr += strlen(ptr);
1206 #else
1207 ptr += sprintf(ptr, "{%s %s {%.4f %.4f %.4f %.4f}} ",
1208 XpOidString(ds->page_size),
1209 ds->long_edge_feeds ? "True" : "False",
1210 ds->assured_reproduction_area.minimum_x,
1211 ds->assured_reproduction_area.maximum_x,
1212 ds->assured_reproduction_area.minimum_y,
1213 ds->assured_reproduction_area.maximum_y);
1214 #endif
1216 #if defined(sun) && !defined(SVR4)
1217 sprintf(ptr, "} ");
1218 ptr += strlen(ptr);
1219 #else
1220 ptr += sprintf(ptr, "} ");
1221 #endif
1224 * chop trailing whitespace or terminate empty string
1226 str[length] = '\0';
1228 * return
1230 return str;
1234 * ------------------------------------------------------------------------
1235 * Name: MediumContinuousSizeParse
1237 * Description:
1239 * 'ptr_return' *cannot* be NULL.
1242 * Return value:
1247 static XpOidMediumContinuousSize*
1248 MediumContinuousSizeParse(const char* value_string,
1249 const char** ptr_return)
1251 const char* first_nonws_ptr;
1252 XpOidMediumContinuousSize* mcs = NULL;
1254 * skip leading whitespace
1256 first_nonws_ptr = value_string + SpanWhitespace(value_string);
1258 * parse out the MediumSize sequence start char
1260 if(!ParseSeqStart(first_nonws_ptr, ptr_return))
1261 goto MediumContinuousSizeParse_error;
1263 * peek ahead to see if it looks like we actually have a continuous
1264 * size spec (looking for the sequence start char on the 1st range spec)
1266 if(!ParseSeqStart(*ptr_return, (const char**)NULL))
1267 goto MediumContinuousSizeParse_error;
1269 * Ok, let's go for it
1271 mcs = (XpOidMediumContinuousSize*)
1272 XpOidCalloc(1, sizeof(XpOidMediumContinuousSize));
1274 * "range across the feed direction"
1276 if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_across_feed))
1277 goto MediumContinuousSizeParse_error;
1279 * "increment across the feed direction" (optional, default 0)
1281 if(!ParseUnspecifiedValue(*ptr_return, ptr_return))
1282 if(!ParseRealValue(*ptr_return, ptr_return,
1283 &mcs->increment_across_feed))
1284 goto MediumContinuousSizeParse_error;
1286 * "range in the feed direction"
1288 if(!ParseRealRange(*ptr_return, ptr_return, &mcs->range_in_feed))
1289 goto MediumContinuousSizeParse_error;
1291 * "increment in the feed direction" (optional, default 0)
1293 if(!ParseUnspecifiedValue(*ptr_return, ptr_return))
1294 if(!ParseRealValue(*ptr_return, ptr_return,
1295 &mcs->increment_in_feed))
1296 goto MediumContinuousSizeParse_error;
1298 * "long edge feeds" flag (default TRUE)
1300 if(ParseUnspecifiedValue(*ptr_return, ptr_return))
1301 mcs->long_edge_feeds = xTrue;
1302 else
1303 if(!ParseBoolValue(*ptr_return, ptr_return, &mcs->long_edge_feeds))
1304 goto MediumContinuousSizeParse_error;
1306 * "generic assured reproduction area"
1308 if(!ParseArea(*ptr_return, ptr_return, &mcs->assured_reproduction_area))
1309 goto MediumContinuousSizeParse_error;
1311 * parse out the MediumSize sequence end character
1313 if(!ParseSeqEnd(*ptr_return, ptr_return))
1314 goto MediumContinuousSizeParse_error;
1316 * return
1318 return mcs;
1321 MediumContinuousSizeParse_error:
1323 * syntax error - don't log since this function may be called
1324 * as a lookahead
1326 *ptr_return = first_nonws_ptr;
1327 XpOidFree((char*)mcs);
1328 return NULL;
1332 * ------------------------------------------------------------------------
1333 * Name: MediumContinuousSizeDelete
1335 * Description:
1337 * 'ptr_return' *cannot* be NULL.
1340 * Return value:
1345 static void
1346 MediumContinuousSizeDelete(XpOidMediumContinuousSize* me)
1348 XpOidFree((char*)me);
1352 * ------------------------------------------------------------------------
1353 * Name: MediumDiscreteSizeListParse
1355 * Description:
1357 * 'ptr_return' *cannot* be NULL.
1359 * Return value:
1364 static XpOidMediumDiscreteSizeList*
1365 MediumDiscreteSizeListParse(const char* value_string,
1366 const XpOidList* valid_medium_sizes,
1367 const char** ptr_return,
1368 int i)
1370 XpOidMediumDiscreteSizeList* list;
1371 XpOidMediumDiscreteSize mds;
1373 * check for the start of a new MediumSize sequence
1375 if(ParseSeqStart(value_string, ptr_return))
1378 * "page size"
1380 mds.page_size = XpOidParse(*ptr_return, ptr_return);
1381 if((const XpOidList*)NULL != valid_medium_sizes
1383 !XpOidListHasOid(valid_medium_sizes, mds.page_size)
1385 mds.page_size = xpoid_none;
1387 * "long edge feeds" flag (default TRUE)
1389 if(ParseUnspecifiedValue(*ptr_return, ptr_return))
1390 mds.long_edge_feeds = xTrue;
1391 else
1392 if(!ParseBoolValue(*ptr_return, ptr_return,
1393 &mds.long_edge_feeds))
1396 * syntax error
1398 ErrorF("%s\nBoolean expected.\nunparsed data: %s\n",
1399 XPMSG_WARN_MSS, *ptr_return);
1400 return (XpOidMediumDiscreteSizeList*)NULL;
1403 * "assured reproduction area"
1405 if(!ParseArea(*ptr_return, ptr_return,
1406 &mds.assured_reproduction_area))
1409 * syntax error
1411 ErrorF("%s\nArea specification error.\nunparsed data: %s\n",
1412 XPMSG_WARN_MSS, *ptr_return);
1413 return (XpOidMediumDiscreteSizeList*)NULL;
1416 * parse out the MediumSize sequence end character
1418 if(!ParseSeqEnd(*ptr_return, ptr_return))
1420 ErrorF("%s\nSequence End expected. Unparsed data: %s\n",
1421 XPMSG_WARN_MSS, *ptr_return);
1422 return (XpOidMediumDiscreteSizeList*)NULL;
1425 * recurse to parse the next Discrete MediumSize sequence
1427 if(mds.page_size == xpoid_none)
1429 list = MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
1430 ptr_return, i);
1432 else
1434 list = MediumDiscreteSizeListParse(*ptr_return, valid_medium_sizes,
1435 ptr_return, i+1);
1436 if(list != (XpOidMediumDiscreteSizeList*)NULL)
1439 * copy the current discrete MediumSize into the list
1441 memmove((list->list)+i, &mds, sizeof(XpOidMediumDiscreteSize));
1445 else
1448 * MediumSize sequence start not found; end of the discrete sizes
1449 * list
1451 if(0 == i)
1453 ErrorF("%s\nNo valid medium sizes found for tray.\n",
1454 XPMSG_WARN_MSS);
1455 return (XpOidMediumDiscreteSizeList*)NULL;
1457 list = (XpOidMediumDiscreteSizeList*)
1458 XpOidCalloc(1, sizeof(XpOidMediumDiscreteSizeList));
1459 list->count = i;
1460 list->list = (XpOidMediumDiscreteSize*)
1461 XpOidCalloc(i, sizeof(XpOidMediumDiscreteSize));
1463 return list;
1467 * ------------------------------------------------------------------------
1468 * Name: MediumDiscreteSizeListDelete
1470 * Description:
1474 * Return value:
1479 static void
1480 MediumDiscreteSizeListDelete(XpOidMediumDiscreteSizeList* list)
1482 if(list != (XpOidMediumDiscreteSizeList*)NULL)
1484 XpOidFree((char*)list->list);
1485 XpOidFree((char*)list);
1490 * ------------------------------------------------------------------------
1491 * Name: XpOidTrayMediumListNew
1493 * Description:
1495 * Only need the valid trays; validation requires bumping up against
1496 * msss using TrayMediumListValidate; this needs valid trays
1497 * because of unspecified trays ion msss, but
1498 * TrayMediumListValidate will take care of invalid sizes...
1500 * Return value:
1505 XpOidTrayMediumList*
1506 XpOidTrayMediumListNew(const char* value_string,
1507 const XpOidList* valid_trays,
1508 const XpOidMediumSS* msss)
1510 if(value_string == (const char*)NULL)
1511 return (XpOidTrayMediumList*)NULL;
1512 else
1514 const char* ptr;
1515 XpOidTrayMediumList* me;
1516 me = TrayMediumListParse(value_string, valid_trays, &ptr, 0);
1517 if((XpOidTrayMediumList*)NULL != me)
1518 TrayMediumListValidate(me, msss);
1519 return me;
1524 * ------------------------------------------------------------------------
1525 * Name: XpOidTrayMediumListDelete
1527 * Description:
1531 * Return value:
1536 void
1537 XpOidTrayMediumListDelete(XpOidTrayMediumList* list)
1539 if(list != (XpOidTrayMediumList*)NULL)
1541 XpOidFree((char*)list->list);
1542 XpOidFree((char*)list);
1547 * ------------------------------------------------------------------------
1548 * Name: TrayMediumListParse
1550 * Description:
1552 * 'ptr_return' *cannot* be NULL.
1554 * Return value:
1559 static XpOidTrayMediumList*
1560 TrayMediumListParse(const char* value_string,
1561 const XpOidList* valid_trays,
1562 const char** ptr_return, int i)
1564 XpOidTrayMedium tm;
1565 XpOidTrayMediumList* list;
1567 * check for the start of a new InputTrayMedium sequence
1569 if(ParseSeqStart(value_string, ptr_return))
1572 * "input tray"
1574 tm.input_tray = XpOidParse(*ptr_return, ptr_return);
1575 if((XpOidList*)NULL != valid_trays
1577 !XpOidListHasOid(valid_trays, tm.input_tray)
1579 tm.input_tray = xpoid_none;
1581 * "medium"
1583 tm.medium = XpOidParse(*ptr_return, ptr_return);
1585 * parse out the InputTrayMedium sequence end character
1587 if(!ParseSeqEnd(*ptr_return, ptr_return))
1589 ErrorF("%s\n", XPMSG_WARN_ITM);
1590 return NULL;
1593 * recurse to parse the next InputTrayMedium sequence
1595 list = TrayMediumListParse(*ptr_return, valid_trays, ptr_return, i+1);
1596 if(list != (XpOidTrayMediumList*)NULL)
1599 * copy the current InputTrayMedium into the list
1601 memmove((list->list)+i, &tm, sizeof(XpOidTrayMedium));
1604 else
1607 * InputTrayMedium sequence start not found
1609 if(**ptr_return == '\0')
1612 * end of the list
1614 list = (XpOidTrayMediumList*)
1615 XpOidCalloc(1, sizeof(XpOidTrayMediumList));
1616 list->count = i;
1617 list->list = (XpOidTrayMedium*)
1618 XpOidCalloc(i, sizeof(XpOidTrayMedium));
1620 else
1623 * syntax error
1625 ErrorF("%s\n", XPMSG_WARN_ITM);
1626 return NULL;
1630 * return
1632 return list;
1636 * ------------------------------------------------------------------------
1637 * Name: TrayMediumListValidate
1639 * Description:
1641 * Validate the input-trays-medium list based on a passed
1642 * medium-source-sizes-supported structure. The validated
1643 * input-trays-medium list will have the same number of entries upon
1644 * return from this function. Invalid entries are indicated by
1645 * setting the tray specification to xpoid_none.
1647 * Return value:
1649 * None.
1652 static void
1653 TrayMediumListValidate(XpOidTrayMediumList* me,
1654 const XpOidMediumSS* msss)
1656 int i_mss, i_ds, i_itm;
1657 XpOid current_tray, current_medium;
1658 XpOidMediumDiscreteSizeList* unspecified_tray_ds;
1659 XpOidMediumDiscreteSizeList* tray_ds;
1661 if(msss == (XpOidMediumSS*)NULL
1663 me == (XpOidTrayMediumList*)NULL)
1665 return;
1668 * loop through the input trays medium list
1670 for(i_itm = 0; i_itm < XpOidTrayMediumListCount(me); i_itm++)
1672 current_tray = XpOidTrayMediumListTray(me, i_itm);
1673 if(current_tray == xpoid_none)
1674 continue;
1675 current_medium = XpOidTrayMediumListMedium(me, i_itm);
1676 if(current_medium == xpoid_none)
1679 * no medium; invalidate this entry
1681 me->list[i_itm].input_tray = xpoid_none;
1682 continue;
1685 * loop through the MediumSourceSizes, looking for an appropriate
1686 * discrete sizes spec for the current tray
1688 unspecified_tray_ds = (XpOidMediumDiscreteSizeList*)NULL;
1689 tray_ds = (XpOidMediumDiscreteSizeList*)NULL;
1690 for(i_mss = 0;
1691 i_mss < msss->count &&
1692 tray_ds == (XpOidMediumDiscreteSizeList*)NULL;
1693 i_mss++)
1695 switch((msss->mss)[i_mss].mstag)
1697 case XpOidMediumSS_DISCRETE:
1698 if((msss->mss)[i_mss].input_tray == current_tray)
1699 tray_ds = (msss->mss)[i_mss].ms.discrete;
1700 else if((msss->mss)[i_mss].input_tray == xpoid_unspecified)
1701 unspecified_tray_ds = (msss->mss)[i_mss].ms.discrete;
1702 break;
1704 case XpOidMediumSS_CONTINUOUS:
1706 * unsupported
1708 break;
1712 * if the tray was not matched, use the unspecified tray size
1713 * list
1715 if(tray_ds == (XpOidMediumDiscreteSizeList*)NULL)
1717 if(unspecified_tray_ds == (XpOidMediumDiscreteSizeList*)NULL)
1720 * not even an unspecified tray, invalidate this
1721 * input-trays-medium entry.
1723 me->list[i_itm].input_tray = xpoid_none;
1724 continue;
1726 else
1727 tray_ds = unspecified_tray_ds;
1730 * loop through the discrete sizes list, looking for a size that
1731 * matches the medium for the current input tray
1733 for(i_ds = 0; i_ds < tray_ds->count; i_ds++)
1736 * check to see if the current input tray's medium size
1737 * matches the current discrete size
1739 * Note: in the CDEnext SI, medium identifiers coincide with
1740 * medium-size identifiers. If the DP-Medium object is
1741 * ever implemented, this check would need to be
1742 * changed so that the input tray's medium size is
1743 * obtained from the indicated Medium object, and not
1744 * inferred from the medium identifier itself.
1746 if((tray_ds->list)[i_ds].page_size == current_medium)
1749 * The current input tray's medium size matches the
1750 * current discrete medium size.
1752 break;
1755 if(i_ds == tray_ds->count)
1758 * The current input tray's medium size was not found in the
1759 * discrete size list; mark the input tray medium entry
1760 * invalid
1762 me->list[i_itm].input_tray = xpoid_none;
1769 * ------------------------------------------------------------------------
1770 * Name: XpOidTrayMediumListString
1772 * Description:
1774 * Creates a string representation of an XpOidTrayMediumList structure.
1776 * Return value:
1778 * A newly allocated
1781 char* XpOidTrayMediumListString(const XpOidTrayMediumList* me)
1783 int i;
1784 int length;
1785 char* str;
1786 char* ptr;
1787 XpOid tray;
1789 * allocate enough memory for the string representation,
1790 * including intervening delimiters and whitespace
1792 for(i = 0, length = 0; i < XpOidTrayMediumListCount(me); i++)
1794 tray = XpOidTrayMediumListTray(me, i);
1795 if(xpoid_none != tray)
1797 length += XpOidStringLength(tray);
1798 length += XpOidStringLength(XpOidTrayMediumListMedium(me, i));
1799 length += 4;
1802 str = XpOidMalloc(length+1);
1804 * format the list
1806 for(i = 0, ptr = str; i < XpOidTrayMediumListCount(me); i++)
1808 tray = XpOidTrayMediumListTray(me, i);
1809 if(xpoid_none != tray)
1811 #if defined(sun) && !defined(SVR4)
1812 sprintf(ptr, "{%s %s} ",
1813 XpOidString(tray),
1814 XpOidString(XpOidTrayMediumListMedium(me, i)));
1815 ptr += strlen(ptr);
1816 #else
1817 ptr += sprintf(ptr, "{%s %s} ",
1818 XpOidString(tray),
1819 XpOidString(XpOidTrayMediumListMedium(me, i)));
1820 #endif
1824 * chop trailing whitespace or terminate empty string
1826 str[length] = '\0';
1828 * return
1830 return str;
1834 * ------------------------------------------------------------------------
1835 * Name: XpOidTrayMediumListHasTray
1837 * Description:
1839 * Determines if 'tray' is found in 'list'.
1841 * Return value:
1843 * xTrue if the tray is found in the list.
1845 * xFalse if the tray is not in the list, or if 'list' is NULL.
1848 BOOL
1849 XpOidTrayMediumListHasTray(const XpOidTrayMediumList* list, XpOid tray)
1851 int i;
1852 if(list != (XpOidTrayMediumList*)NULL && tray != xpoid_none)
1853 for(i = 0; i < list->count; i++)
1854 if(XpOidTrayMediumListTray(list, i) == tray)
1855 return xTrue;
1856 return xFalse;
1860 * ------------------------------------------------------------------------
1861 * Name: ParseArea
1863 * Description:
1865 * Skips leading whitespace and parses out and returns a XpOidArea.
1867 * Return value:
1869 * xTrue if the XpOidArea was successfully parsed. ptr_return is
1870 * updated to point to location where the parsing ended.
1872 * xFalse if a XpOidArea was not found; ptr_return is updated
1873 * to point to the first non-whitespace char in value_string.
1876 static BOOL
1877 ParseArea(const char* value_string,
1878 const char** ptr_return,
1879 XpOidArea* area_return)
1881 const char* first_nonws_ptr;
1882 const char* ptr;
1884 * skip leading whitespace
1886 first_nonws_ptr = value_string + SpanWhitespace(value_string);
1888 * parse out the area sequence start
1890 if(!ParseSeqStart(first_nonws_ptr, &ptr))
1891 goto ParseArea_error;
1893 * parse the minimum x value
1895 if(!ParseRealValue(ptr, &ptr,
1896 area_return ? &area_return->minimum_x : NULL))
1897 goto ParseArea_error;
1899 * parse the maximum x value
1901 if(!ParseRealValue(ptr, &ptr,
1902 area_return ? &area_return->maximum_x : NULL))
1903 goto ParseArea_error;
1905 * parse the minimum y value
1907 if(!ParseRealValue(ptr, &ptr,
1908 area_return ? &area_return->minimum_y : NULL))
1909 goto ParseArea_error;
1911 * parse the maximum y value
1913 if(!ParseRealValue(ptr, &ptr,
1914 area_return ? &area_return->maximum_y : NULL))
1915 goto ParseArea_error;
1917 * parse out the area sequence end
1919 if(!ParseSeqEnd(ptr, &ptr))
1920 goto ParseArea_error;
1922 * update the return pointer
1924 if(ptr_return != (const char**)NULL)
1925 *ptr_return = ptr;
1927 * return
1929 return xTrue;
1932 ParseArea_error:
1934 * syntax error
1936 if(ptr_return != (const char**)NULL)
1937 *ptr_return = first_nonws_ptr;
1938 return xFalse;
1942 * ------------------------------------------------------------------------
1943 * Name: ParseRealRange
1945 * Description:
1947 * Skips leading whitespace and parses out and returns a
1948 * XpOidRealRange.
1950 * Return value:
1952 * xTrue if the XpOidRealRange was successfully
1953 * parsed. ptr_return is updated to point to location where the
1954 * parsing ended.
1956 * xFalse if a XpOidRealRange was not found; ptr_return is
1957 * updated to point to the first non-whitespace char in value_string.
1960 static BOOL
1961 ParseRealRange(const char* value_string,
1962 const char** ptr_return,
1963 XpOidRealRange* range_return)
1965 const char* first_nonws_ptr;
1966 const char* ptr;
1968 * skip leading whitespace
1970 first_nonws_ptr = value_string + SpanWhitespace(value_string);
1972 * parse out the range sequence start
1974 if(!ParseSeqStart(first_nonws_ptr, &ptr))
1975 goto ParseRealRange_error;
1977 * parse the lower bound
1979 if(!ParseRealValue(ptr, &ptr,
1980 range_return ? &range_return->lower_bound : NULL))
1981 goto ParseRealRange_error;
1983 * parse the upper bound
1985 if(!ParseRealValue(ptr, &ptr,
1986 range_return ? &range_return->upper_bound : NULL))
1987 goto ParseRealRange_error;
1989 * parse out the range sequence end
1991 if(!ParseSeqEnd(ptr, &ptr))
1992 goto ParseRealRange_error;
1994 * update the return pointer
1996 if(ptr_return != (const char**)NULL)
1997 *ptr_return = ptr;
1999 * return
2001 return xTrue;
2004 ParseRealRange_error:
2006 * syntax error
2008 if(ptr_return != (const char**)NULL)
2009 *ptr_return = first_nonws_ptr;
2010 return xFalse;
2014 * ------------------------------------------------------------------------
2015 * Name: XpOidNotifyParse
2017 * Description:
2020 * Return value:
2024 XpOidNotify XpOidNotifyParse(const char* value_string)
2026 const char* ptr = value_string;
2028 if(value_string == (const char*)NULL)
2029 return XPOID_NOTIFY_NONE;
2031 * look for an event handling profile sequence start
2033 if(!ParseSeqStart(value_string, &ptr))
2035 if('\0' == *ptr)
2037 * empty value is valid
2039 return XPOID_NOTIFY_NONE;
2040 else
2041 return XPOID_NOTIFY_UNSUPPORTED;
2044 * look for an event set sequence start
2046 if(!ParseSeqStart(ptr, &ptr))
2049 * check for an empty event handling profile
2051 if(ParseSeqEnd(ptr, &ptr))
2053 ptr += SpanWhitespace(ptr);
2054 if(*ptr == '\0')
2056 * valid empty event handling profile sequence
2058 return XPOID_NOTIFY_NONE;
2060 return XPOID_NOTIFY_UNSUPPORTED;
2063 * the only event in the set should be report job completed
2065 if(xpoid_val_event_report_job_completed != XpOidParse(ptr, &ptr))
2066 return XPOID_NOTIFY_UNSUPPORTED;
2068 * event set sequence end
2070 if(!ParseSeqEnd(ptr, &ptr))
2071 return XPOID_NOTIFY_UNSUPPORTED;
2073 * delivery method of electronic mail
2075 if(xpoid_val_delivery_method_electronic_mail != XpOidParse(ptr, &ptr))
2076 return XPOID_NOTIFY_UNSUPPORTED;
2078 * event handling profile sequence end
2080 if(!ParseSeqEnd(ptr, &ptr))
2081 return XPOID_NOTIFY_UNSUPPORTED;
2083 * end of value
2085 ptr += SpanWhitespace(ptr);
2086 if('\0' == *ptr)
2088 * valid supported notification profile
2090 return XPOID_NOTIFY_EMAIL;
2091 else
2092 return XPOID_NOTIFY_UNSUPPORTED;
2096 * ------------------------------------------------------------------------
2097 * Name: XpOidNotifyString
2099 * Description:
2102 * Return value:
2106 const char* XpOidNotifyString(XpOidNotify notify)
2108 switch(notify)
2110 case XPOID_NOTIFY_NONE:
2111 return NOTIFY_NONE_STR;
2112 case XPOID_NOTIFY_EMAIL:
2113 return NOTIFY_EMAIL_STR;
2114 case XPOID_NOTIFY_UNSUPPORTED:
2115 return (const char *)NULL;
2118 ErrorF("XpOidNotifyString: Unsupported notify=%ld\n", (long)notify);
2119 return (const char *)NULL;
2123 * ------------------------------------------------------------------------
2124 * Name: XpOidDocFmtNew
2126 * Description:
2129 * Return value:
2133 XpOidDocFmt*
2134 XpOidDocFmtNew(const char* value_string)
2136 XpOidDocFmt* doc_fmt;
2137 const char* ptr;
2139 if((const char*)NULL == value_string)
2140 return (XpOidDocFmt*)NULL;
2141 ptr = value_string + SpanWhitespace(value_string);
2142 if('\0' == *ptr)
2143 return (XpOidDocFmt*)NULL;
2145 * get the document format from the value string
2147 doc_fmt = (XpOidDocFmt*)XpOidCalloc(1, sizeof(XpOidDocFmt));
2148 if(xTrue == XpOidDocFmtNext(doc_fmt, ptr, &ptr))
2151 * verify that the document format is the only value specified
2153 ptr += SpanWhitespace(ptr);
2154 if('\0' == *ptr)
2156 * valid document-format value
2158 return doc_fmt;
2161 * invalid
2163 XpOidDocFmtDelete(doc_fmt);
2164 ErrorF("%s\n", XPMSG_WARN_DOC_FMT);
2165 return (XpOidDocFmt*)NULL;
2169 * ------------------------------------------------------------------------
2170 * Name: XpOidDocFmtDelete
2172 * Description:
2175 * Return value:
2179 void
2180 XpOidDocFmtDelete(XpOidDocFmt* doc_fmt)
2182 if((XpOidDocFmt*)NULL != doc_fmt)
2184 XpOidFree(doc_fmt->format);
2185 XpOidFree(doc_fmt->variant);
2186 XpOidFree(doc_fmt->version);
2187 XpOidFree(doc_fmt);
2192 * ------------------------------------------------------------------------
2193 * Name: XpOidDocFmtString
2195 * Description:
2198 * Return value:
2202 char*
2203 XpOidDocFmtString(XpOidDocFmt* doc_fmt)
2205 if((XpOidDocFmt*)NULL != doc_fmt)
2207 if((char*)NULL != doc_fmt->format)
2209 char* str = XpOidMalloc(1+SafeStrLen(doc_fmt->format)+
2210 1+SafeStrLen(doc_fmt->variant)+
2211 1+SafeStrLen(doc_fmt->version)+
2212 1+1);
2213 sprintf(str, "{%s %s %s}", doc_fmt->format,
2214 (char*)NULL != doc_fmt->variant ? doc_fmt->variant : "",
2215 (char*)NULL != doc_fmt->version ? doc_fmt->version : "");
2216 return str;
2219 return (char*)NULL;
2223 * ------------------------------------------------------------------------
2224 * Name: XpOidDocFmtNext
2226 * Description:
2228 * Assumes non-NULL value string.
2230 * Return value:
2234 static BOOL
2235 XpOidDocFmtNext(XpOidDocFmt* doc_fmt,
2236 const char* value_string,
2237 const char** ptr_return)
2239 const char* ptr;
2240 const char* first_nonws_ptr;
2241 const char* format;
2242 const char* variant;
2243 const char* version;
2244 int format_len;
2245 int variant_len;
2246 int version_len;
2248 * skip leading whitespace
2250 ptr = value_string + SpanWhitespace(value_string);
2251 first_nonws_ptr = ptr;
2253 * sequence start
2255 if(!ParseSeqStart(ptr, &ptr))
2256 goto XpOidDocFmtNext_error;
2258 * skip whitepace to the start of the document format, and save the
2259 * location
2261 ptr += SpanWhitespace(ptr);
2262 format = ptr;
2264 * document format
2266 if(0 == (format_len = SpanToken(ptr)))
2267 goto XpOidDocFmtNext_error;
2268 ptr += format_len;
2270 * optional variant
2272 ptr += SpanWhitespace(ptr);
2273 variant = ptr;
2274 if(0 != (variant_len = SpanToken(ptr)))
2276 ptr += variant_len;
2278 * optional version
2280 ptr += SpanWhitespace(ptr);
2281 version = ptr;
2282 version_len = SpanToken(ptr);
2283 ptr += version_len;
2285 else
2286 version_len = 0;
2288 * sequence end
2290 if(!ParseSeqEnd(ptr, &ptr))
2291 goto XpOidDocFmtNext_error;
2293 * update return pointer
2295 if((const char**)NULL != ptr_return)
2296 *ptr_return = ptr;
2298 * update the passed document format struct
2300 memset(doc_fmt, 0, sizeof(XpOidDocFmt));
2301 doc_fmt->format = XpOidMalloc(format_len+1);
2302 strncpy(doc_fmt->format, format, format_len);
2303 doc_fmt->format[format_len] = '\0';
2304 if(0 < variant_len)
2306 doc_fmt->variant = XpOidMalloc(variant_len+1);
2307 strncpy(doc_fmt->variant, variant, variant_len);
2308 doc_fmt->variant[variant_len] = '\0';
2309 if(0 < version_len)
2311 doc_fmt->version = XpOidMalloc(version_len+1);
2312 strncpy(doc_fmt->version, version, version_len);
2313 doc_fmt->version[version_len] = '\0';
2316 return xTrue;
2318 XpOidDocFmtNext_error:
2319 if((const char**)NULL != ptr_return)
2320 *ptr_return = first_nonws_ptr;
2321 return xFalse;
2325 * ------------------------------------------------------------------------
2326 * Name: XpOidDocFmtListNew
2328 * Description:
2331 * Return value:
2335 XpOidDocFmtList*
2336 XpOidDocFmtListNew(const char* value_string,
2337 const XpOidDocFmtList* valid_fmts)
2339 if((char*)NULL != value_string)
2341 const char* ptr;
2342 return XpOidDocFmtListParse(value_string, valid_fmts, &ptr, 0);
2344 return (XpOidDocFmtList*)NULL;
2348 * ------------------------------------------------------------------------
2349 * Name: XpOidDocFmtListDelete
2351 * Description:
2354 * Return value:
2358 void
2359 XpOidDocFmtListDelete(XpOidDocFmtList* list)
2361 if((XpOidDocFmtList*)NULL != list)
2363 int i;
2364 for(i = 0; i < list->count; i++)
2366 XpOidFree(list->list[i].format);
2367 XpOidFree(list->list[i].variant);
2368 XpOidFree(list->list[i].version);
2370 XpOidFree(list->list);
2371 XpOidFree(list);
2376 * ------------------------------------------------------------------------
2377 * Name: XpOidDocFmtListString
2379 * Description:
2381 * Assumes the passed structure is valid.
2383 * Return value:
2387 char*
2388 XpOidDocFmtListString(const XpOidDocFmtList* list)
2390 if((XpOidDocFmtList*)NULL != list)
2392 if(0 < list->count)
2394 int i;
2395 int str_len;
2396 char* str;
2397 char* ptr;
2399 * allocate the return string
2401 for(i = 0, str_len = 0; i < list->count; i++)
2403 str_len +=
2404 1 + SafeStrLen(list->list[i].format) +
2405 1 + SafeStrLen(list->list[i].variant) +
2406 1 + SafeStrLen(list->list[i].version) + 2;
2408 str = XpOidMalloc(str_len+1);
2410 * print the list into the string and return it
2412 ptr = str;
2413 for(i = 0; i < list->count; i++)
2415 XpOidDocFmt* df = &list->list[i];
2417 #if defined(sun) && !defined(SVR4)
2418 sprintf(ptr, "{%s %s %s} ",
2419 df->format,
2420 (char*)NULL != df->variant ? df->variant : "",
2421 (char*)NULL != df->version ? df->version : "");
2422 ptr += strlen(ptr);
2423 #else
2424 ptr +=
2425 sprintf(ptr, "{%s %s %s} ",
2426 df->format,
2427 (char*)NULL != df->variant ? df->variant : "",
2428 (char*)NULL != df->version ? df->version : "");
2429 #endif
2431 return str;
2434 return (char*)NULL;
2438 * ------------------------------------------------------------------------
2439 * Name: XpOidDocFmtListParse
2441 * Description:
2443 * Assumes the passed value_string and ptr_return are non-NULL.
2445 * Return value:
2449 static XpOidDocFmtList*
2450 XpOidDocFmtListParse(const char* value_string,
2451 const XpOidDocFmtList* valid_fmts,
2452 const char** ptr_return,
2453 int i)
2455 XpOidDocFmt doc_fmt;
2456 XpOidDocFmtList* list;
2457 BOOL status;
2459 * get the next document-format from the value string, skipping
2460 * values not found in the passed list of valid formats
2462 *ptr_return = value_string;
2463 while((status = XpOidDocFmtNext(&doc_fmt, *ptr_return, ptr_return))
2465 (const XpOidDocFmtList*)NULL != valid_fmts
2467 !XpOidDocFmtListHasFmt(valid_fmts, &doc_fmt)
2470 if(xFalse == status)
2472 if('\0' == **ptr_return)
2474 if(0 == i)
2477 * empty value string
2479 return (XpOidDocFmtList*)NULL;
2481 else
2484 * done parsing; allocate the list and return
2486 list =
2487 (XpOidDocFmtList*)XpOidCalloc(1, sizeof(XpOidDocFmtList));
2488 list->count = i;
2489 list->list = (XpOidDocFmt*)XpOidCalloc(i, sizeof(XpOidDocFmt));
2490 return list;
2493 else
2496 * invalid document format
2498 ErrorF("%s\n", XPMSG_WARN_DOCFMT_LIST);
2499 return (XpOidDocFmtList*)NULL;
2502 else
2505 * recurse to parse remaining document formats
2507 list = XpOidDocFmtListParse(*ptr_return, valid_fmts, ptr_return, i+1);
2508 if((XpOidDocFmtList*)NULL != list)
2511 * add this doc fmt to the list
2513 list->list[i].format = doc_fmt.format;
2514 list->list[i].variant = doc_fmt.variant;
2515 list->list[i].version = doc_fmt.version;
2517 return list;
2522 * ------------------------------------------------------------------------
2523 * Name: XpOidDocFmtListHasFmt
2525 * Description:
2527 * Assumes the passed structure is valid.
2529 * Return value:
2533 BOOL
2534 XpOidDocFmtListHasFmt(const XpOidDocFmtList* list,
2535 const XpOidDocFmt* fmt)
2537 int i;
2538 if(list != (XpOidDocFmtList*)NULL
2540 fmt != (XpOidDocFmt*)NULL
2542 fmt->format != (char*)NULL
2545 for(i = 0; i < list->count; i++)
2548 * formats must match
2550 if(strcmp(fmt->format, list->list[i].format) != 0)
2551 continue;
2553 * variants must both be NULL or match
2555 if(fmt->variant == (char*)NULL)
2557 if(list->list[i].variant == (char*)NULL)
2558 return xTrue;
2559 else
2560 continue;
2562 if(list->list[i].variant == (char*)NULL)
2563 continue;
2564 if(strcmp(fmt->variant, list->list[i].variant) != 0)
2565 continue;
2567 * versions must both be NULL or match
2569 if(fmt->version == (char*)NULL)
2571 if(list->list[i].version == (char*)NULL)
2572 return xTrue;
2573 else
2574 continue;
2576 if(list->list[i].version == (char*)NULL)
2577 continue;
2578 if(strcmp(fmt->version, list->list[i].version) == 0)
2579 return xTrue;
2582 return xFalse;
2586 * ------------------------------------------------------------------------
2587 * Name: XpOidCardListNew
2589 * Description:
2592 * Return value:
2596 XpOidCardList*
2597 XpOidCardListNew(const char* value_string, const XpOidCardList* valid_cards)
2599 if((const char*)NULL != value_string)
2601 const char* ptr;
2603 return XpOidCardListParse(value_string, valid_cards, &ptr, 0);
2605 else
2606 return (XpOidCardList*)NULL;
2610 * ------------------------------------------------------------------------
2611 * Name: XpOidCardListDelete
2613 * Description:
2616 * Return value:
2620 void
2621 XpOidCardListDelete(XpOidCardList* list)
2623 if((XpOidCardList*)NULL != list)
2625 XpOidFree(list->list);
2626 XpOidFree(list);
2631 * ------------------------------------------------------------------------
2632 * Name: XpOidCardListString
2634 * Description:
2637 * Return value:
2641 char*
2642 XpOidCardListString(const XpOidCardList* list)
2644 if((XpOidCardList*)NULL != list)
2646 char buf[48];
2647 int str_len;
2648 char* str;
2649 int i;
2650 char* ptr;
2652 * allocate the output string
2654 for(i = 0, str_len = 0; i < list->count; i++)
2655 #if defined(sun) && !defined(SVR4)
2657 sprintf(buf, "%lu", list->list[i]) + 1;
2658 str_len += strlen(buf);
2660 #else
2661 str_len += sprintf(buf, "%lu", list->list[i]) + 1;
2662 #endif
2663 str = XpOidMalloc(str_len+1);
2665 * write the list to the string
2667 for(i = 0, ptr = str; i < list->count; i++)
2668 #if defined(sun) && !defined(SVR4)
2670 sprintf(ptr, "%lu ", list->list[i]);
2671 ptr += strlen(ptr);
2673 #else
2674 ptr += sprintf(ptr, "%lu ", list->list[i]);
2675 #endif
2676 return str;
2678 else
2679 return (char*)NULL;
2683 * ------------------------------------------------------------------------
2684 * Name: XpOidCardListHasCard
2686 * Description:
2688 * Determines if 'card' is an element of 'list'.
2690 * Return value:
2692 * xTrue if the card is found in the list.
2694 * xFalse if the card is not in the list, or if 'list' is NULL.
2697 BOOL
2698 XpOidCardListHasCard(const XpOidCardList* list, unsigned long card)
2700 int i;
2701 if(list != (XpOidCardList*)NULL)
2702 for(i = 0; i < list->count; i++)
2703 if(list->list[i] == card)
2704 return xTrue;
2705 return xFalse;
2709 * ------------------------------------------------------------------------
2710 * Name: XpOidCardListParse
2712 * Description:
2714 * Assumes the passed value_string and ptr_return are non-NULL.
2716 * Return value:
2720 static XpOidCardList*
2721 XpOidCardListParse(const char* value_string,
2722 const XpOidCardList* valid_cards,
2723 const char** ptr_return,
2724 int i)
2726 unsigned long card;
2727 XpOidCardList* list;
2728 BOOL status;
2731 * get the next card from the value string, skipping values not
2732 * found in the passed list of valid cards
2734 *ptr_return = value_string;
2735 while((status = XpOidParseUnsignedValue(*ptr_return, ptr_return, &card))
2737 (const XpOidCardList*)NULL != valid_cards
2739 !XpOidCardListHasCard(valid_cards, card)
2742 if(xFalse == status)
2744 if('\0' == **ptr_return)
2746 if(0 == i)
2749 * empty value string
2751 return (XpOidCardList*)NULL;
2753 else
2756 * done parsing; allocate the list and return
2758 list = (XpOidCardList*)XpOidCalloc(1, sizeof(XpOidCardList));
2759 list->count = i;
2760 list->list =
2761 (unsigned long*)XpOidCalloc(i, sizeof(unsigned long));
2762 return list;
2765 else
2768 * parsing error
2770 ErrorF("%s\n", XPMSG_WARN_CARD_LIST);
2771 return (XpOidCardList*)NULL;
2774 else
2777 * recurse to parse remaining cardinal values
2779 list = XpOidCardListParse(*ptr_return, valid_cards, ptr_return, i+1);
2780 if((XpOidCardList*)NULL != list)
2783 * add this value to the list
2785 list->list[i] = card;
2787 return list;
2792 * ------------------------------------------------------------------------
2793 * Name: ParseBoolValue
2795 * Description:
2798 * Return value:
2802 static BOOL
2803 ParseBoolValue(const char* value_string,
2804 const char** ptr_return,
2805 BOOL* bool_return)
2807 const char* ptr;
2808 int length;
2809 BOOL status;
2811 * skip leading whitespace
2813 ptr = value_string + SpanWhitespace(value_string);
2815 * get the whitespace-delimited token length
2817 length = SpanToken(ptr);
2819 * determine if true or false or bad
2821 if(StrnCaseCmp(ptr, "TRUE", length) == 0)
2823 if(bool_return != (BOOL*)NULL)
2824 *bool_return = xTrue;
2825 status = xTrue;
2827 else if(StrnCaseCmp(ptr, "FALSE", length) == 0)
2829 if(bool_return != (BOOL*)NULL)
2830 *bool_return = xFalse;
2831 status = xTrue;
2833 else
2836 * syntax error
2838 status = xFalse;
2841 * update the return pointer and return
2843 if(ptr_return != (const char**)NULL)
2844 *ptr_return = status ? ptr+length : ptr;
2845 return status;
2849 * ------------------------------------------------------------------------
2850 * Name: XpOidParseUnsignedValue
2852 * Description:
2854 * Skips leading whitespace and parses out and returns a unsigned number.
2856 * Return value:
2858 * xTrue if a unsigned number was successfully parsed. ptr_return is
2859 * updated to point to location where the unsigned number parsing
2860 * ended.
2862 * xFalse if a unsigned number was not found; ptr_return is updated
2863 * to point to the first non-whitespace char in value_string.
2866 BOOL
2867 XpOidParseUnsignedValue(const char* value_string,
2868 const char** ptr_return,
2869 unsigned long* unsigned_return)
2871 long value;
2872 BOOL status;
2873 const char* first_nonws_ptr;
2874 const char* ptr;
2876 * skip leading whitespace
2878 first_nonws_ptr = value_string + SpanWhitespace(value_string);
2879 value = strtol(first_nonws_ptr, (char**)(&ptr), 0);
2880 if(ptr == first_nonws_ptr || value < 0)
2881 status = xFalse;
2882 else
2883 status = xTrue;
2885 * update return parms
2887 if(ptr_return != (const char**)NULL)
2888 *ptr_return = ptr;
2889 if(unsigned_return != (unsigned long*)NULL)
2890 *unsigned_return = (unsigned long)value;
2892 * return
2894 return status;
2898 * ------------------------------------------------------------------------
2899 * Name: ParseRealValue
2901 * Description:
2903 * Skips leading whitespace and parses out and returns a real number.
2905 * Return value:
2907 * xTrue if a real number was successfully parsed. ptr_return is
2908 * updated to point to location where the real number parsing
2909 * ended.
2911 * xFalse if a real number was not found; ptr_return is updated
2912 * to point to the first non-whitespace char in value_string.
2915 static BOOL
2916 ParseRealValue(const char* value_string,
2917 const char** ptr_return,
2918 float* real_return)
2920 float real_value;
2921 BOOL status;
2922 const char* first_nonws_ptr;
2923 const char* ptr;
2925 * skip leading whitespace
2927 first_nonws_ptr = value_string + SpanWhitespace(value_string);
2928 real_value = (float)strtod(first_nonws_ptr, (char**)(&ptr));
2929 if(ptr == first_nonws_ptr)
2930 status = xFalse;
2931 else
2932 status = xTrue;
2934 * update return parms
2936 if(ptr_return != (const char**)NULL)
2937 *ptr_return = ptr;
2938 if(real_return != (float*)NULL)
2939 *real_return = real_value;
2941 * return
2943 return status;
2947 * ------------------------------------------------------------------------
2948 * Name: ParseSeqEnd
2950 * Description:
2952 * Description:
2954 * Skips leading whitespace and parses out the sequence end
2955 * character '}'.
2957 * Return value:
2959 * xTrue if the sequence end character was parsed; ptr_return is
2960 * updated to point to the first char following the sequence end
2961 * character.
2963 * xFalse if the sequence end character was not found; ptr_return is
2964 * updated to point to the first non-whitespace char in value_string.
2967 static BOOL
2968 ParseSeqEnd(const char* value_string,
2969 const char** ptr_return)
2971 const char* ptr;
2972 BOOL status;
2974 * skip leading whitespace
2976 ptr = value_string + SpanWhitespace(value_string);
2978 * parse out the sequence end character
2980 if(*ptr == '}')
2982 status = xTrue;
2983 ++ptr;
2985 else
2986 status = xFalse;
2988 * update the return pointer
2990 if(ptr_return != (const char**)NULL)
2991 *ptr_return = ptr;
2993 * return
2995 return status;
2999 * ------------------------------------------------------------------------
3000 * Name: ParseSeqStart
3002 * Description:
3004 * Skips leading whitespace and parses out the sequence start
3005 * character '{'.
3007 * Return value:
3009 * xTrue if the sequence start character was parsed; ptr_return is
3010 * updated to point to the first char following the sequence start
3011 * character.
3013 * xFalse if the sequence start character was not found; ptr_return is
3014 * updated to point to the first non-whitespace char in value_string.
3017 static BOOL
3018 ParseSeqStart(const char* value_string,
3019 const char** ptr_return)
3021 const char* ptr;
3022 BOOL status;
3024 * skip leading whitespace
3026 ptr = value_string + SpanWhitespace(value_string);
3028 * parse out the sequence start character
3030 if(*ptr == '{')
3032 status = xTrue;
3033 ++ptr;
3035 else
3036 status = xFalse;
3038 * update the return pointer
3040 if(ptr_return != (const char**)NULL)
3041 *ptr_return = ptr;
3043 * return
3045 return status;
3049 * ------------------------------------------------------------------------
3050 * Name: ParseUnspecifiedValue
3052 * Description:
3054 * Skips leading whitespace and parses out an unspecified optional
3055 * value (i.e. matching '' or "" - skips all data between the set of
3056 * quotes).
3058 * Return value:
3060 * xTrue if an unspecified value was parsed; ptr_return is updated to
3061 * point to the first char following the trailing quote.
3063 * xFalse if an unspecified value was not found; ptr_return is updated
3064 * to point to the first non-whitespace char in value_string.
3067 static BOOL
3068 ParseUnspecifiedValue(const char* value_string,
3069 const char** ptr_return)
3071 BOOL status;
3072 const char* ptr;
3074 * skip leading whitespace
3076 ptr = value_string + SpanWhitespace(value_string);
3078 * parse out an unspecified optional value ('' or "")
3080 if(*ptr == '\'' || *ptr == '"')
3082 char delim[2];
3084 if(ptr_return != (const char**)NULL)
3086 delim[0] = *ptr;
3087 delim[1] = '\0';
3089 * skip over the matching delimiter
3091 ++ptr;
3092 ptr += strcspn(ptr, delim);
3093 if(*ptr != '\0')
3094 ++ptr;
3096 status = xTrue;
3098 else
3099 status = xFalse;
3101 * update the return pointer
3103 if(ptr_return != (const char**)NULL)
3104 *ptr_return = ptr;
3106 * return
3108 return status;
3112 * ------------------------------------------------------------------------
3113 * Name: SpanToken
3115 * Description:
3117 * Returns the length of the initial segment of the passed string
3118 * that consists entirely of non-whitespace and non-sequence
3119 * delimiter characters.
3123 static int
3124 SpanToken(const char* string)
3126 const char* ptr;
3127 for(ptr = string;
3128 *ptr != '\0' && !isspace(*ptr) && *ptr != '{' && *ptr != '}';
3129 ++ptr);
3130 return ptr - string;
3134 * ------------------------------------------------------------------------
3135 * Name: SpanWhitespace
3137 * Description:
3139 * Returns the length of the initial segment of the passed string
3140 * that consists entirely of whitespace characters.
3144 static int
3145 SpanWhitespace(const char* string)
3147 const char* ptr;
3148 for(ptr = string; *ptr != '\0' && isspace(*ptr); ++ptr);
3149 return ptr - string;
3152 #ifndef HAVE_STRCASECMP
3154 * ------------------------------------------------------------------------
3155 * Name: StrnCaseCmp
3157 * Description:
3159 * Implements strncasecmp() for those platforms that need it.
3163 static int
3164 StrnCaseCmp(const char *s1, const char *s2, size_t len)
3166 char c1, c2;
3167 int result;
3169 while (len--)
3171 c1 = *s1++;
3172 c2 = *s2++;
3173 result = tolower(c1) - tolower(c2);
3175 if (result != 0)
3176 return result;
3179 return 0;
3181 #endif