xref: /aosp_15_r20/external/libcups/cups/options.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Option routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2017 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright 1997-2007 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker  */
9*5e7646d2SAndroid Build Coastguard Worker 
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker  */
13*5e7646d2SAndroid Build Coastguard Worker 
14*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker 
18*5e7646d2SAndroid Build Coastguard Worker /*
19*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
20*5e7646d2SAndroid Build Coastguard Worker  */
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker static int	cups_compare_options(cups_option_t *a, cups_option_t *b);
23*5e7646d2SAndroid Build Coastguard Worker static int	cups_find_option(const char *name, int num_options,
24*5e7646d2SAndroid Build Coastguard Worker 	                         cups_option_t *option, int prev, int *rdiff);
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker 
27*5e7646d2SAndroid Build Coastguard Worker /*
28*5e7646d2SAndroid Build Coastguard Worker  * 'cupsAddIntegerOption()' - Add an integer option to an option array.
29*5e7646d2SAndroid Build Coastguard Worker  *
30*5e7646d2SAndroid Build Coastguard Worker  * New option arrays can be initialized simply by passing 0 for the
31*5e7646d2SAndroid Build Coastguard Worker  * "num_options" parameter.
32*5e7646d2SAndroid Build Coastguard Worker  *
33*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 2.2.4/macOS 10.13@
34*5e7646d2SAndroid Build Coastguard Worker  */
35*5e7646d2SAndroid Build Coastguard Worker 
36*5e7646d2SAndroid Build Coastguard Worker int					/* O  - Number of options */
cupsAddIntegerOption(const char * name,int value,int num_options,cups_option_t ** options)37*5e7646d2SAndroid Build Coastguard Worker cupsAddIntegerOption(
38*5e7646d2SAndroid Build Coastguard Worker     const char    *name,		/* I  - Name of option */
39*5e7646d2SAndroid Build Coastguard Worker     int           value,		/* I  - Value of option */
40*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I  - Number of options */
41*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options)		/* IO - Pointer to options */
42*5e7646d2SAndroid Build Coastguard Worker {
43*5e7646d2SAndroid Build Coastguard Worker   char	strvalue[32];			/* String value */
44*5e7646d2SAndroid Build Coastguard Worker 
45*5e7646d2SAndroid Build Coastguard Worker 
46*5e7646d2SAndroid Build Coastguard Worker   snprintf(strvalue, sizeof(strvalue), "%d", value);
47*5e7646d2SAndroid Build Coastguard Worker 
48*5e7646d2SAndroid Build Coastguard Worker   return (cupsAddOption(name, strvalue, num_options, options));
49*5e7646d2SAndroid Build Coastguard Worker }
50*5e7646d2SAndroid Build Coastguard Worker 
51*5e7646d2SAndroid Build Coastguard Worker 
52*5e7646d2SAndroid Build Coastguard Worker /*
53*5e7646d2SAndroid Build Coastguard Worker  * 'cupsAddOption()' - Add an option to an option array.
54*5e7646d2SAndroid Build Coastguard Worker  *
55*5e7646d2SAndroid Build Coastguard Worker  * New option arrays can be initialized simply by passing 0 for the
56*5e7646d2SAndroid Build Coastguard Worker  * "num_options" parameter.
57*5e7646d2SAndroid Build Coastguard Worker  */
58*5e7646d2SAndroid Build Coastguard Worker 
59*5e7646d2SAndroid Build Coastguard Worker int					/* O  - Number of options */
cupsAddOption(const char * name,const char * value,int num_options,cups_option_t ** options)60*5e7646d2SAndroid Build Coastguard Worker cupsAddOption(const char    *name,	/* I  - Name of option */
61*5e7646d2SAndroid Build Coastguard Worker               const char    *value,	/* I  - Value of option */
62*5e7646d2SAndroid Build Coastguard Worker 	      int           num_options,/* I  - Number of options */
63*5e7646d2SAndroid Build Coastguard Worker               cups_option_t **options)	/* IO - Pointer to options */
64*5e7646d2SAndroid Build Coastguard Worker {
65*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*temp;			/* Pointer to new option */
66*5e7646d2SAndroid Build Coastguard Worker   int		insert,			/* Insertion point */
67*5e7646d2SAndroid Build Coastguard Worker 		diff;			/* Result of search */
68*5e7646d2SAndroid Build Coastguard Worker 
69*5e7646d2SAndroid Build Coastguard Worker 
70*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2cupsAddOption(name=\"%s\", value=\"%s\", num_options=%d, options=%p)", name, value, num_options, (void *)options));
71*5e7646d2SAndroid Build Coastguard Worker 
72*5e7646d2SAndroid Build Coastguard Worker   if (!name || !name[0] || !value || !options || num_options < 0)
73*5e7646d2SAndroid Build Coastguard Worker   {
74*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("3cupsAddOption: Returning %d", num_options));
75*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
76*5e7646d2SAndroid Build Coastguard Worker   }
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(name, "cupsPrintQuality"))
79*5e7646d2SAndroid Build Coastguard Worker     num_options = cupsRemoveOption("print-quality", num_options, options);
80*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strcasecmp(name, "print-quality"))
81*5e7646d2SAndroid Build Coastguard Worker     num_options = cupsRemoveOption("cupsPrintQuality", num_options, options);
82*5e7646d2SAndroid Build Coastguard Worker 
83*5e7646d2SAndroid Build Coastguard Worker  /*
84*5e7646d2SAndroid Build Coastguard Worker   * Look for an existing option with the same name...
85*5e7646d2SAndroid Build Coastguard Worker   */
86*5e7646d2SAndroid Build Coastguard Worker 
87*5e7646d2SAndroid Build Coastguard Worker   if (num_options == 0)
88*5e7646d2SAndroid Build Coastguard Worker   {
89*5e7646d2SAndroid Build Coastguard Worker     insert = 0;
90*5e7646d2SAndroid Build Coastguard Worker     diff   = 1;
91*5e7646d2SAndroid Build Coastguard Worker   }
92*5e7646d2SAndroid Build Coastguard Worker   else
93*5e7646d2SAndroid Build Coastguard Worker   {
94*5e7646d2SAndroid Build Coastguard Worker     insert = cups_find_option(name, num_options, *options, num_options - 1,
95*5e7646d2SAndroid Build Coastguard Worker                               &diff);
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker     if (diff > 0)
98*5e7646d2SAndroid Build Coastguard Worker       insert ++;
99*5e7646d2SAndroid Build Coastguard Worker   }
100*5e7646d2SAndroid Build Coastguard Worker 
101*5e7646d2SAndroid Build Coastguard Worker   if (diff)
102*5e7646d2SAndroid Build Coastguard Worker   {
103*5e7646d2SAndroid Build Coastguard Worker    /*
104*5e7646d2SAndroid Build Coastguard Worker     * No matching option name...
105*5e7646d2SAndroid Build Coastguard Worker     */
106*5e7646d2SAndroid Build Coastguard Worker 
107*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4cupsAddOption: New option inserted at index %d...",
108*5e7646d2SAndroid Build Coastguard Worker                   insert));
109*5e7646d2SAndroid Build Coastguard Worker 
110*5e7646d2SAndroid Build Coastguard Worker     if (num_options == 0)
111*5e7646d2SAndroid Build Coastguard Worker       temp = (cups_option_t *)malloc(sizeof(cups_option_t));
112*5e7646d2SAndroid Build Coastguard Worker     else
113*5e7646d2SAndroid Build Coastguard Worker       temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) * (size_t)(num_options + 1));
114*5e7646d2SAndroid Build Coastguard Worker 
115*5e7646d2SAndroid Build Coastguard Worker     if (!temp)
116*5e7646d2SAndroid Build Coastguard Worker     {
117*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("3cupsAddOption: Unable to expand option array, returning 0");
118*5e7646d2SAndroid Build Coastguard Worker       return (0);
119*5e7646d2SAndroid Build Coastguard Worker     }
120*5e7646d2SAndroid Build Coastguard Worker 
121*5e7646d2SAndroid Build Coastguard Worker     *options = temp;
122*5e7646d2SAndroid Build Coastguard Worker 
123*5e7646d2SAndroid Build Coastguard Worker     if (insert < num_options)
124*5e7646d2SAndroid Build Coastguard Worker     {
125*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("4cupsAddOption: Shifting %d options...",
126*5e7646d2SAndroid Build Coastguard Worker                     (int)(num_options - insert)));
127*5e7646d2SAndroid Build Coastguard Worker       memmove(temp + insert + 1, temp + insert, (size_t)(num_options - insert) * sizeof(cups_option_t));
128*5e7646d2SAndroid Build Coastguard Worker     }
129*5e7646d2SAndroid Build Coastguard Worker 
130*5e7646d2SAndroid Build Coastguard Worker     temp        += insert;
131*5e7646d2SAndroid Build Coastguard Worker     temp->name  = _cupsStrAlloc(name);
132*5e7646d2SAndroid Build Coastguard Worker     num_options ++;
133*5e7646d2SAndroid Build Coastguard Worker   }
134*5e7646d2SAndroid Build Coastguard Worker   else
135*5e7646d2SAndroid Build Coastguard Worker   {
136*5e7646d2SAndroid Build Coastguard Worker    /*
137*5e7646d2SAndroid Build Coastguard Worker     * Match found; free the old value...
138*5e7646d2SAndroid Build Coastguard Worker     */
139*5e7646d2SAndroid Build Coastguard Worker 
140*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4cupsAddOption: Option already exists at index %d...",
141*5e7646d2SAndroid Build Coastguard Worker                   insert));
142*5e7646d2SAndroid Build Coastguard Worker 
143*5e7646d2SAndroid Build Coastguard Worker     temp = *options + insert;
144*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(temp->value);
145*5e7646d2SAndroid Build Coastguard Worker   }
146*5e7646d2SAndroid Build Coastguard Worker 
147*5e7646d2SAndroid Build Coastguard Worker   temp->value = _cupsStrAlloc(value);
148*5e7646d2SAndroid Build Coastguard Worker 
149*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3cupsAddOption: Returning %d", num_options));
150*5e7646d2SAndroid Build Coastguard Worker 
151*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
152*5e7646d2SAndroid Build Coastguard Worker }
153*5e7646d2SAndroid Build Coastguard Worker 
154*5e7646d2SAndroid Build Coastguard Worker 
155*5e7646d2SAndroid Build Coastguard Worker /*
156*5e7646d2SAndroid Build Coastguard Worker  * 'cupsFreeOptions()' - Free all memory used by options.
157*5e7646d2SAndroid Build Coastguard Worker  */
158*5e7646d2SAndroid Build Coastguard Worker 
159*5e7646d2SAndroid Build Coastguard Worker void
cupsFreeOptions(int num_options,cups_option_t * options)160*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(
161*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
162*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options)		/* I - Pointer to options */
163*5e7646d2SAndroid Build Coastguard Worker {
164*5e7646d2SAndroid Build Coastguard Worker   int	i;				/* Looping var */
165*5e7646d2SAndroid Build Coastguard Worker 
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("cupsFreeOptions(num_options=%d, options=%p)", num_options, (void *)options));
168*5e7646d2SAndroid Build Coastguard Worker 
169*5e7646d2SAndroid Build Coastguard Worker   if (num_options <= 0 || !options)
170*5e7646d2SAndroid Build Coastguard Worker     return;
171*5e7646d2SAndroid Build Coastguard Worker 
172*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < num_options; i ++)
173*5e7646d2SAndroid Build Coastguard Worker   {
174*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(options[i].name);
175*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(options[i].value);
176*5e7646d2SAndroid Build Coastguard Worker   }
177*5e7646d2SAndroid Build Coastguard Worker 
178*5e7646d2SAndroid Build Coastguard Worker   free(options);
179*5e7646d2SAndroid Build Coastguard Worker }
180*5e7646d2SAndroid Build Coastguard Worker 
181*5e7646d2SAndroid Build Coastguard Worker 
182*5e7646d2SAndroid Build Coastguard Worker /*
183*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetIntegerOption()' - Get an integer option value.
184*5e7646d2SAndroid Build Coastguard Worker  *
185*5e7646d2SAndroid Build Coastguard Worker  * INT_MIN is returned when the option does not exist, is not an integer, or
186*5e7646d2SAndroid Build Coastguard Worker  * exceeds the range of values for the "int" type.
187*5e7646d2SAndroid Build Coastguard Worker  *
188*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 2.2.4/macOS 10.13@
189*5e7646d2SAndroid Build Coastguard Worker  */
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker int					/* O - Option value or @code INT_MIN@ */
cupsGetIntegerOption(const char * name,int num_options,cups_option_t * options)192*5e7646d2SAndroid Build Coastguard Worker cupsGetIntegerOption(
193*5e7646d2SAndroid Build Coastguard Worker     const char    *name,		/* I - Name of option */
194*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
195*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options)		/* I - Options */
196*5e7646d2SAndroid Build Coastguard Worker {
197*5e7646d2SAndroid Build Coastguard Worker   const char	*value = cupsGetOption(name, num_options, options);
198*5e7646d2SAndroid Build Coastguard Worker 					/* String value of option */
199*5e7646d2SAndroid Build Coastguard Worker   char		*ptr;			/* Pointer into string value */
200*5e7646d2SAndroid Build Coastguard Worker   long		intvalue;		/* Integer value */
201*5e7646d2SAndroid Build Coastguard Worker 
202*5e7646d2SAndroid Build Coastguard Worker 
203*5e7646d2SAndroid Build Coastguard Worker   if (!value || !*value)
204*5e7646d2SAndroid Build Coastguard Worker     return (INT_MIN);
205*5e7646d2SAndroid Build Coastguard Worker 
206*5e7646d2SAndroid Build Coastguard Worker   intvalue = strtol(value, &ptr, 10);
207*5e7646d2SAndroid Build Coastguard Worker   if (intvalue < INT_MIN || intvalue > INT_MAX || *ptr)
208*5e7646d2SAndroid Build Coastguard Worker     return (INT_MIN);
209*5e7646d2SAndroid Build Coastguard Worker 
210*5e7646d2SAndroid Build Coastguard Worker   return ((int)intvalue);
211*5e7646d2SAndroid Build Coastguard Worker }
212*5e7646d2SAndroid Build Coastguard Worker 
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker /*
215*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetOption()' - Get an option value.
216*5e7646d2SAndroid Build Coastguard Worker  */
217*5e7646d2SAndroid Build Coastguard Worker 
218*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - Option value or @code NULL@ */
cupsGetOption(const char * name,int num_options,cups_option_t * options)219*5e7646d2SAndroid Build Coastguard Worker cupsGetOption(const char    *name,	/* I - Name of option */
220*5e7646d2SAndroid Build Coastguard Worker               int           num_options,/* I - Number of options */
221*5e7646d2SAndroid Build Coastguard Worker               cups_option_t *options)	/* I - Options */
222*5e7646d2SAndroid Build Coastguard Worker {
223*5e7646d2SAndroid Build Coastguard Worker   int	diff,				/* Result of comparison */
224*5e7646d2SAndroid Build Coastguard Worker 	match;				/* Matching index */
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker 
227*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2cupsGetOption(name=\"%s\", num_options=%d, options=%p)", name, num_options, (void *)options));
228*5e7646d2SAndroid Build Coastguard Worker 
229*5e7646d2SAndroid Build Coastguard Worker   if (!name || num_options <= 0 || !options)
230*5e7646d2SAndroid Build Coastguard Worker   {
231*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("3cupsGetOption: Returning NULL");
232*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
233*5e7646d2SAndroid Build Coastguard Worker   }
234*5e7646d2SAndroid Build Coastguard Worker 
235*5e7646d2SAndroid Build Coastguard Worker   match = cups_find_option(name, num_options, options, -1, &diff);
236*5e7646d2SAndroid Build Coastguard Worker 
237*5e7646d2SAndroid Build Coastguard Worker   if (!diff)
238*5e7646d2SAndroid Build Coastguard Worker   {
239*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("3cupsGetOption: Returning \"%s\"", options[match].value));
240*5e7646d2SAndroid Build Coastguard Worker     return (options[match].value);
241*5e7646d2SAndroid Build Coastguard Worker   }
242*5e7646d2SAndroid Build Coastguard Worker 
243*5e7646d2SAndroid Build Coastguard Worker   DEBUG_puts("3cupsGetOption: Returning NULL");
244*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
245*5e7646d2SAndroid Build Coastguard Worker }
246*5e7646d2SAndroid Build Coastguard Worker 
247*5e7646d2SAndroid Build Coastguard Worker 
248*5e7646d2SAndroid Build Coastguard Worker /*
249*5e7646d2SAndroid Build Coastguard Worker  * 'cupsParseOptions()' - Parse options from a command-line argument.
250*5e7646d2SAndroid Build Coastguard Worker  *
251*5e7646d2SAndroid Build Coastguard Worker  * This function converts space-delimited name/value pairs according
252*5e7646d2SAndroid Build Coastguard Worker  * to the PAPI text option ABNF specification. Collection values
253*5e7646d2SAndroid Build Coastguard Worker  * ("name={a=... b=... c=...}") are stored with the curley brackets
254*5e7646d2SAndroid Build Coastguard Worker  * intact - use @code cupsParseOptions@ on the value to extract the
255*5e7646d2SAndroid Build Coastguard Worker  * collection attributes.
256*5e7646d2SAndroid Build Coastguard Worker  */
257*5e7646d2SAndroid Build Coastguard Worker 
258*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of options found */
cupsParseOptions(const char * arg,int num_options,cups_option_t ** options)259*5e7646d2SAndroid Build Coastguard Worker cupsParseOptions(
260*5e7646d2SAndroid Build Coastguard Worker     const char    *arg,			/* I - Argument to parse */
261*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
262*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options)		/* O - Options found */
263*5e7646d2SAndroid Build Coastguard Worker {
264*5e7646d2SAndroid Build Coastguard Worker   char	*copyarg,			/* Copy of input string */
265*5e7646d2SAndroid Build Coastguard Worker 	*ptr,				/* Pointer into string */
266*5e7646d2SAndroid Build Coastguard Worker 	*name,				/* Pointer to name */
267*5e7646d2SAndroid Build Coastguard Worker 	*value,				/* Pointer to value */
268*5e7646d2SAndroid Build Coastguard Worker 	sep,				/* Separator character */
269*5e7646d2SAndroid Build Coastguard Worker 	quote;				/* Quote character */
270*5e7646d2SAndroid Build Coastguard Worker 
271*5e7646d2SAndroid Build Coastguard Worker 
272*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options));
273*5e7646d2SAndroid Build Coastguard Worker 
274*5e7646d2SAndroid Build Coastguard Worker  /*
275*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
276*5e7646d2SAndroid Build Coastguard Worker   */
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker   if (!arg)
279*5e7646d2SAndroid Build Coastguard Worker   {
280*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
281*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
282*5e7646d2SAndroid Build Coastguard Worker   }
283*5e7646d2SAndroid Build Coastguard Worker 
284*5e7646d2SAndroid Build Coastguard Worker   if (!options || num_options < 0)
285*5e7646d2SAndroid Build Coastguard Worker   {
286*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsParseOptions: Returning 0");
287*5e7646d2SAndroid Build Coastguard Worker     return (0);
288*5e7646d2SAndroid Build Coastguard Worker   }
289*5e7646d2SAndroid Build Coastguard Worker 
290*5e7646d2SAndroid Build Coastguard Worker  /*
291*5e7646d2SAndroid Build Coastguard Worker   * Make a copy of the argument string and then divide it up...
292*5e7646d2SAndroid Build Coastguard Worker   */
293*5e7646d2SAndroid Build Coastguard Worker 
294*5e7646d2SAndroid Build Coastguard Worker   if ((copyarg = strdup(arg)) == NULL)
295*5e7646d2SAndroid Build Coastguard Worker   {
296*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsParseOptions: Unable to copy arg string");
297*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
298*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
299*5e7646d2SAndroid Build Coastguard Worker   }
300*5e7646d2SAndroid Build Coastguard Worker 
301*5e7646d2SAndroid Build Coastguard Worker   if (*copyarg == '{')
302*5e7646d2SAndroid Build Coastguard Worker   {
303*5e7646d2SAndroid Build Coastguard Worker    /*
304*5e7646d2SAndroid Build Coastguard Worker     * Remove surrounding {} so we can parse "{name=value ... name=value}"...
305*5e7646d2SAndroid Build Coastguard Worker     */
306*5e7646d2SAndroid Build Coastguard Worker 
307*5e7646d2SAndroid Build Coastguard Worker     if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}')
308*5e7646d2SAndroid Build Coastguard Worker     {
309*5e7646d2SAndroid Build Coastguard Worker       *ptr = '\0';
310*5e7646d2SAndroid Build Coastguard Worker       ptr  = copyarg + 1;
311*5e7646d2SAndroid Build Coastguard Worker     }
312*5e7646d2SAndroid Build Coastguard Worker     else
313*5e7646d2SAndroid Build Coastguard Worker       ptr = copyarg;
314*5e7646d2SAndroid Build Coastguard Worker   }
315*5e7646d2SAndroid Build Coastguard Worker   else
316*5e7646d2SAndroid Build Coastguard Worker     ptr = copyarg;
317*5e7646d2SAndroid Build Coastguard Worker 
318*5e7646d2SAndroid Build Coastguard Worker  /*
319*5e7646d2SAndroid Build Coastguard Worker   * Skip leading spaces...
320*5e7646d2SAndroid Build Coastguard Worker   */
321*5e7646d2SAndroid Build Coastguard Worker 
322*5e7646d2SAndroid Build Coastguard Worker   while (_cups_isspace(*ptr))
323*5e7646d2SAndroid Build Coastguard Worker     ptr ++;
324*5e7646d2SAndroid Build Coastguard Worker 
325*5e7646d2SAndroid Build Coastguard Worker  /*
326*5e7646d2SAndroid Build Coastguard Worker   * Loop through the string...
327*5e7646d2SAndroid Build Coastguard Worker   */
328*5e7646d2SAndroid Build Coastguard Worker 
329*5e7646d2SAndroid Build Coastguard Worker   while (*ptr != '\0')
330*5e7646d2SAndroid Build Coastguard Worker   {
331*5e7646d2SAndroid Build Coastguard Worker    /*
332*5e7646d2SAndroid Build Coastguard Worker     * Get the name up to a SPACE, =, or end-of-string...
333*5e7646d2SAndroid Build Coastguard Worker     */
334*5e7646d2SAndroid Build Coastguard Worker 
335*5e7646d2SAndroid Build Coastguard Worker     name = ptr;
336*5e7646d2SAndroid Build Coastguard Worker     while (!strchr("\f\n\r\t\v =", *ptr) && *ptr)
337*5e7646d2SAndroid Build Coastguard Worker       ptr ++;
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker    /*
340*5e7646d2SAndroid Build Coastguard Worker     * Avoid an empty name...
341*5e7646d2SAndroid Build Coastguard Worker     */
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker     if (ptr == name)
344*5e7646d2SAndroid Build Coastguard Worker       break;
345*5e7646d2SAndroid Build Coastguard Worker 
346*5e7646d2SAndroid Build Coastguard Worker    /*
347*5e7646d2SAndroid Build Coastguard Worker     * Skip trailing spaces...
348*5e7646d2SAndroid Build Coastguard Worker     */
349*5e7646d2SAndroid Build Coastguard Worker 
350*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*ptr))
351*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = '\0';
352*5e7646d2SAndroid Build Coastguard Worker 
353*5e7646d2SAndroid Build Coastguard Worker     if ((sep = *ptr) == '=')
354*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = '\0';
355*5e7646d2SAndroid Build Coastguard Worker 
356*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name));
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker     if (sep != '=')
359*5e7646d2SAndroid Build Coastguard Worker     {
360*5e7646d2SAndroid Build Coastguard Worker      /*
361*5e7646d2SAndroid Build Coastguard Worker       * Boolean option...
362*5e7646d2SAndroid Build Coastguard Worker       */
363*5e7646d2SAndroid Build Coastguard Worker 
364*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strncasecmp(name, "no", 2))
365*5e7646d2SAndroid Build Coastguard Worker         num_options = cupsAddOption(name + 2, "false", num_options,
366*5e7646d2SAndroid Build Coastguard Worker 	                            options);
367*5e7646d2SAndroid Build Coastguard Worker       else
368*5e7646d2SAndroid Build Coastguard Worker         num_options = cupsAddOption(name, "true", num_options, options);
369*5e7646d2SAndroid Build Coastguard Worker 
370*5e7646d2SAndroid Build Coastguard Worker       continue;
371*5e7646d2SAndroid Build Coastguard Worker     }
372*5e7646d2SAndroid Build Coastguard Worker 
373*5e7646d2SAndroid Build Coastguard Worker    /*
374*5e7646d2SAndroid Build Coastguard Worker     * Remove = and parse the value...
375*5e7646d2SAndroid Build Coastguard Worker     */
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker     value = ptr;
378*5e7646d2SAndroid Build Coastguard Worker 
379*5e7646d2SAndroid Build Coastguard Worker     while (*ptr && !_cups_isspace(*ptr))
380*5e7646d2SAndroid Build Coastguard Worker     {
381*5e7646d2SAndroid Build Coastguard Worker       if (*ptr == ',')
382*5e7646d2SAndroid Build Coastguard Worker         ptr ++;
383*5e7646d2SAndroid Build Coastguard Worker       else if (*ptr == '\'' || *ptr == '\"')
384*5e7646d2SAndroid Build Coastguard Worker       {
385*5e7646d2SAndroid Build Coastguard Worker        /*
386*5e7646d2SAndroid Build Coastguard Worker 	* Quoted string constant...
387*5e7646d2SAndroid Build Coastguard Worker 	*/
388*5e7646d2SAndroid Build Coastguard Worker 
389*5e7646d2SAndroid Build Coastguard Worker 	quote = *ptr;
390*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcpy(ptr, ptr + 1);
391*5e7646d2SAndroid Build Coastguard Worker 
392*5e7646d2SAndroid Build Coastguard Worker 	while (*ptr != quote && *ptr)
393*5e7646d2SAndroid Build Coastguard Worker 	{
394*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr == '\\' && ptr[1])
395*5e7646d2SAndroid Build Coastguard Worker 	    _cups_strcpy(ptr, ptr + 1);
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
398*5e7646d2SAndroid Build Coastguard Worker 	}
399*5e7646d2SAndroid Build Coastguard Worker 
400*5e7646d2SAndroid Build Coastguard Worker 	if (*ptr)
401*5e7646d2SAndroid Build Coastguard Worker 	  _cups_strcpy(ptr, ptr + 1);
402*5e7646d2SAndroid Build Coastguard Worker       }
403*5e7646d2SAndroid Build Coastguard Worker       else if (*ptr == '{')
404*5e7646d2SAndroid Build Coastguard Worker       {
405*5e7646d2SAndroid Build Coastguard Worker        /*
406*5e7646d2SAndroid Build Coastguard Worker 	* Collection value...
407*5e7646d2SAndroid Build Coastguard Worker 	*/
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker 	int depth;
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker 	for (depth = 0; *ptr; ptr ++)
412*5e7646d2SAndroid Build Coastguard Worker 	{
413*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr == '{')
414*5e7646d2SAndroid Build Coastguard Worker 	    depth ++;
415*5e7646d2SAndroid Build Coastguard Worker 	  else if (*ptr == '}')
416*5e7646d2SAndroid Build Coastguard Worker 	  {
417*5e7646d2SAndroid Build Coastguard Worker 	    depth --;
418*5e7646d2SAndroid Build Coastguard Worker 	    if (!depth)
419*5e7646d2SAndroid Build Coastguard Worker 	    {
420*5e7646d2SAndroid Build Coastguard Worker 	      ptr ++;
421*5e7646d2SAndroid Build Coastguard Worker 	      break;
422*5e7646d2SAndroid Build Coastguard Worker 	    }
423*5e7646d2SAndroid Build Coastguard Worker 	  }
424*5e7646d2SAndroid Build Coastguard Worker 	  else if (*ptr == '\\' && ptr[1])
425*5e7646d2SAndroid Build Coastguard Worker 	    _cups_strcpy(ptr, ptr + 1);
426*5e7646d2SAndroid Build Coastguard Worker 	}
427*5e7646d2SAndroid Build Coastguard Worker       }
428*5e7646d2SAndroid Build Coastguard Worker       else
429*5e7646d2SAndroid Build Coastguard Worker       {
430*5e7646d2SAndroid Build Coastguard Worker        /*
431*5e7646d2SAndroid Build Coastguard Worker 	* Normal space-delimited string...
432*5e7646d2SAndroid Build Coastguard Worker 	*/
433*5e7646d2SAndroid Build Coastguard Worker 
434*5e7646d2SAndroid Build Coastguard Worker 	while (*ptr && !_cups_isspace(*ptr))
435*5e7646d2SAndroid Build Coastguard Worker 	{
436*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr == '\\' && ptr[1])
437*5e7646d2SAndroid Build Coastguard Worker 	    _cups_strcpy(ptr, ptr + 1);
438*5e7646d2SAndroid Build Coastguard Worker 
439*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
440*5e7646d2SAndroid Build Coastguard Worker 	}
441*5e7646d2SAndroid Build Coastguard Worker       }
442*5e7646d2SAndroid Build Coastguard Worker     }
443*5e7646d2SAndroid Build Coastguard Worker 
444*5e7646d2SAndroid Build Coastguard Worker     if (*ptr != '\0')
445*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = '\0';
446*5e7646d2SAndroid Build Coastguard Worker 
447*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value));
448*5e7646d2SAndroid Build Coastguard Worker 
449*5e7646d2SAndroid Build Coastguard Worker    /*
450*5e7646d2SAndroid Build Coastguard Worker     * Skip trailing whitespace...
451*5e7646d2SAndroid Build Coastguard Worker     */
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*ptr))
454*5e7646d2SAndroid Build Coastguard Worker       ptr ++;
455*5e7646d2SAndroid Build Coastguard Worker 
456*5e7646d2SAndroid Build Coastguard Worker    /*
457*5e7646d2SAndroid Build Coastguard Worker     * Add the string value...
458*5e7646d2SAndroid Build Coastguard Worker     */
459*5e7646d2SAndroid Build Coastguard Worker 
460*5e7646d2SAndroid Build Coastguard Worker     num_options = cupsAddOption(name, value, num_options, options);
461*5e7646d2SAndroid Build Coastguard Worker   }
462*5e7646d2SAndroid Build Coastguard Worker 
463*5e7646d2SAndroid Build Coastguard Worker  /*
464*5e7646d2SAndroid Build Coastguard Worker   * Free the copy of the argument we made and return the number of options
465*5e7646d2SAndroid Build Coastguard Worker   * found.
466*5e7646d2SAndroid Build Coastguard Worker   */
467*5e7646d2SAndroid Build Coastguard Worker 
468*5e7646d2SAndroid Build Coastguard Worker   free(copyarg);
469*5e7646d2SAndroid Build Coastguard Worker 
470*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
471*5e7646d2SAndroid Build Coastguard Worker 
472*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
473*5e7646d2SAndroid Build Coastguard Worker }
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker 
476*5e7646d2SAndroid Build Coastguard Worker /*
477*5e7646d2SAndroid Build Coastguard Worker  * 'cupsRemoveOption()' - Remove an option from an option array.
478*5e7646d2SAndroid Build Coastguard Worker  *
479*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
480*5e7646d2SAndroid Build Coastguard Worker  */
481*5e7646d2SAndroid Build Coastguard Worker 
482*5e7646d2SAndroid Build Coastguard Worker int					/* O  - New number of options */
cupsRemoveOption(const char * name,int num_options,cups_option_t ** options)483*5e7646d2SAndroid Build Coastguard Worker cupsRemoveOption(
484*5e7646d2SAndroid Build Coastguard Worker     const char    *name,		/* I  - Option name */
485*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I  - Current number of options */
486*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options)		/* IO - Options */
487*5e7646d2SAndroid Build Coastguard Worker {
488*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
489*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*option;		/* Current option */
490*5e7646d2SAndroid Build Coastguard Worker 
491*5e7646d2SAndroid Build Coastguard Worker 
492*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2cupsRemoveOption(name=\"%s\", num_options=%d, options=%p)", name, num_options, (void *)options));
493*5e7646d2SAndroid Build Coastguard Worker 
494*5e7646d2SAndroid Build Coastguard Worker  /*
495*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
496*5e7646d2SAndroid Build Coastguard Worker   */
497*5e7646d2SAndroid Build Coastguard Worker 
498*5e7646d2SAndroid Build Coastguard Worker   if (!name || num_options < 1 || !options)
499*5e7646d2SAndroid Build Coastguard Worker   {
500*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("3cupsRemoveOption: Returning %d", num_options));
501*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
502*5e7646d2SAndroid Build Coastguard Worker   }
503*5e7646d2SAndroid Build Coastguard Worker 
504*5e7646d2SAndroid Build Coastguard Worker  /*
505*5e7646d2SAndroid Build Coastguard Worker   * Loop for the option...
506*5e7646d2SAndroid Build Coastguard Worker   */
507*5e7646d2SAndroid Build Coastguard Worker 
508*5e7646d2SAndroid Build Coastguard Worker   for (i = num_options, option = *options; i > 0; i --, option ++)
509*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(name, option->name))
510*5e7646d2SAndroid Build Coastguard Worker       break;
511*5e7646d2SAndroid Build Coastguard Worker 
512*5e7646d2SAndroid Build Coastguard Worker   if (i)
513*5e7646d2SAndroid Build Coastguard Worker   {
514*5e7646d2SAndroid Build Coastguard Worker    /*
515*5e7646d2SAndroid Build Coastguard Worker     * Remove this option from the array...
516*5e7646d2SAndroid Build Coastguard Worker     */
517*5e7646d2SAndroid Build Coastguard Worker 
518*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("4cupsRemoveOption: Found option, removing it...");
519*5e7646d2SAndroid Build Coastguard Worker 
520*5e7646d2SAndroid Build Coastguard Worker     num_options --;
521*5e7646d2SAndroid Build Coastguard Worker     i --;
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(option->name);
524*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(option->value);
525*5e7646d2SAndroid Build Coastguard Worker 
526*5e7646d2SAndroid Build Coastguard Worker     if (i > 0)
527*5e7646d2SAndroid Build Coastguard Worker       memmove(option, option + 1, (size_t)i * sizeof(cups_option_t));
528*5e7646d2SAndroid Build Coastguard Worker   }
529*5e7646d2SAndroid Build Coastguard Worker 
530*5e7646d2SAndroid Build Coastguard Worker  /*
531*5e7646d2SAndroid Build Coastguard Worker   * Return the new number of options...
532*5e7646d2SAndroid Build Coastguard Worker   */
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3cupsRemoveOption: Returning %d", num_options));
535*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
536*5e7646d2SAndroid Build Coastguard Worker }
537*5e7646d2SAndroid Build Coastguard Worker 
538*5e7646d2SAndroid Build Coastguard Worker 
539*5e7646d2SAndroid Build Coastguard Worker /*
540*5e7646d2SAndroid Build Coastguard Worker  * '_cupsGet1284Values()' - Get 1284 device ID keys and values.
541*5e7646d2SAndroid Build Coastguard Worker  *
542*5e7646d2SAndroid Build Coastguard Worker  * The returned dictionary is a CUPS option array that can be queried with
543*5e7646d2SAndroid Build Coastguard Worker  * cupsGetOption and freed with cupsFreeOptions.
544*5e7646d2SAndroid Build Coastguard Worker  */
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of key/value pairs */
_cupsGet1284Values(const char * device_id,cups_option_t ** values)547*5e7646d2SAndroid Build Coastguard Worker _cupsGet1284Values(
548*5e7646d2SAndroid Build Coastguard Worker     const char *device_id,		/* I - IEEE-1284 device ID string */
549*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **values)		/* O - Array of key/value pairs */
550*5e7646d2SAndroid Build Coastguard Worker {
551*5e7646d2SAndroid Build Coastguard Worker   int		num_values;		/* Number of values */
552*5e7646d2SAndroid Build Coastguard Worker   char		key[256],		/* Key string */
553*5e7646d2SAndroid Build Coastguard Worker 		value[256],		/* Value string */
554*5e7646d2SAndroid Build Coastguard Worker 		*ptr;			/* Pointer into key/value */
555*5e7646d2SAndroid Build Coastguard Worker 
556*5e7646d2SAndroid Build Coastguard Worker 
557*5e7646d2SAndroid Build Coastguard Worker  /*
558*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
559*5e7646d2SAndroid Build Coastguard Worker   */
560*5e7646d2SAndroid Build Coastguard Worker 
561*5e7646d2SAndroid Build Coastguard Worker   if (values)
562*5e7646d2SAndroid Build Coastguard Worker     *values = NULL;
563*5e7646d2SAndroid Build Coastguard Worker 
564*5e7646d2SAndroid Build Coastguard Worker   if (!device_id || !values)
565*5e7646d2SAndroid Build Coastguard Worker     return (0);
566*5e7646d2SAndroid Build Coastguard Worker 
567*5e7646d2SAndroid Build Coastguard Worker  /*
568*5e7646d2SAndroid Build Coastguard Worker   * Parse the 1284 device ID value into keys and values.  The format is
569*5e7646d2SAndroid Build Coastguard Worker   * repeating sequences of:
570*5e7646d2SAndroid Build Coastguard Worker   *
571*5e7646d2SAndroid Build Coastguard Worker   *   [whitespace]key:value[whitespace];
572*5e7646d2SAndroid Build Coastguard Worker   */
573*5e7646d2SAndroid Build Coastguard Worker 
574*5e7646d2SAndroid Build Coastguard Worker   num_values = 0;
575*5e7646d2SAndroid Build Coastguard Worker   while (*device_id)
576*5e7646d2SAndroid Build Coastguard Worker   {
577*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*device_id))
578*5e7646d2SAndroid Build Coastguard Worker       device_id ++;
579*5e7646d2SAndroid Build Coastguard Worker 
580*5e7646d2SAndroid Build Coastguard Worker     if (!*device_id)
581*5e7646d2SAndroid Build Coastguard Worker       break;
582*5e7646d2SAndroid Build Coastguard Worker 
583*5e7646d2SAndroid Build Coastguard Worker     for (ptr = key; *device_id && *device_id != ':'; device_id ++)
584*5e7646d2SAndroid Build Coastguard Worker       if (ptr < (key + sizeof(key) - 1))
585*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = *device_id;
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker     if (!*device_id)
588*5e7646d2SAndroid Build Coastguard Worker       break;
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker     while (ptr > key && _cups_isspace(ptr[-1]))
591*5e7646d2SAndroid Build Coastguard Worker       ptr --;
592*5e7646d2SAndroid Build Coastguard Worker 
593*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
594*5e7646d2SAndroid Build Coastguard Worker     device_id ++;
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*device_id))
597*5e7646d2SAndroid Build Coastguard Worker       device_id ++;
598*5e7646d2SAndroid Build Coastguard Worker 
599*5e7646d2SAndroid Build Coastguard Worker     if (!*device_id)
600*5e7646d2SAndroid Build Coastguard Worker       break;
601*5e7646d2SAndroid Build Coastguard Worker 
602*5e7646d2SAndroid Build Coastguard Worker     for (ptr = value; *device_id && *device_id != ';'; device_id ++)
603*5e7646d2SAndroid Build Coastguard Worker       if (ptr < (value + sizeof(value) - 1))
604*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = *device_id;
605*5e7646d2SAndroid Build Coastguard Worker 
606*5e7646d2SAndroid Build Coastguard Worker     while (ptr > value && _cups_isspace(ptr[-1]))
607*5e7646d2SAndroid Build Coastguard Worker       ptr --;
608*5e7646d2SAndroid Build Coastguard Worker 
609*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
610*5e7646d2SAndroid Build Coastguard Worker     num_values = cupsAddOption(key, value, num_values, values);
611*5e7646d2SAndroid Build Coastguard Worker 
612*5e7646d2SAndroid Build Coastguard Worker     if (!*device_id)
613*5e7646d2SAndroid Build Coastguard Worker       break;
614*5e7646d2SAndroid Build Coastguard Worker     device_id ++;
615*5e7646d2SAndroid Build Coastguard Worker   }
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker   return (num_values);
618*5e7646d2SAndroid Build Coastguard Worker }
619*5e7646d2SAndroid Build Coastguard Worker 
620*5e7646d2SAndroid Build Coastguard Worker 
621*5e7646d2SAndroid Build Coastguard Worker /*
622*5e7646d2SAndroid Build Coastguard Worker  * 'cups_compare_options()' - Compare two options.
623*5e7646d2SAndroid Build Coastguard Worker  */
624*5e7646d2SAndroid Build Coastguard Worker 
625*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
cups_compare_options(cups_option_t * a,cups_option_t * b)626*5e7646d2SAndroid Build Coastguard Worker cups_compare_options(cups_option_t *a,	/* I - First option */
627*5e7646d2SAndroid Build Coastguard Worker 		     cups_option_t *b)	/* I - Second option */
628*5e7646d2SAndroid Build Coastguard Worker {
629*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(a->name, b->name));
630*5e7646d2SAndroid Build Coastguard Worker }
631*5e7646d2SAndroid Build Coastguard Worker 
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker /*
634*5e7646d2SAndroid Build Coastguard Worker  * 'cups_find_option()' - Find an option using a binary search.
635*5e7646d2SAndroid Build Coastguard Worker  */
636*5e7646d2SAndroid Build Coastguard Worker 
637*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Index of match */
cups_find_option(const char * name,int num_options,cups_option_t * options,int prev,int * rdiff)638*5e7646d2SAndroid Build Coastguard Worker cups_find_option(
639*5e7646d2SAndroid Build Coastguard Worker     const char    *name,		/* I - Option name */
640*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
641*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options,		/* I - Options */
642*5e7646d2SAndroid Build Coastguard Worker     int           prev,			/* I - Previous index */
643*5e7646d2SAndroid Build Coastguard Worker     int           *rdiff)		/* O - Difference of match */
644*5e7646d2SAndroid Build Coastguard Worker {
645*5e7646d2SAndroid Build Coastguard Worker   int		left,			/* Low mark for binary search */
646*5e7646d2SAndroid Build Coastguard Worker 		right,			/* High mark for binary search */
647*5e7646d2SAndroid Build Coastguard Worker 		current,		/* Current index */
648*5e7646d2SAndroid Build Coastguard Worker 		diff;			/* Result of comparison */
649*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	key;			/* Search key */
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker 
652*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7cups_find_option(name=\"%s\", num_options=%d, options=%p, prev=%d, rdiff=%p)", name, num_options, (void *)options, prev, (void *)rdiff));
653*5e7646d2SAndroid Build Coastguard Worker 
654*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
655*5e7646d2SAndroid Build Coastguard Worker   for (left = 0; left < num_options; left ++)
656*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("9cups_find_option: options[%d].name=\"%s\", .value=\"%s\"",
657*5e7646d2SAndroid Build Coastguard Worker                   left, options[left].name, options[left].value));
658*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
659*5e7646d2SAndroid Build Coastguard Worker 
660*5e7646d2SAndroid Build Coastguard Worker   key.name = (char *)name;
661*5e7646d2SAndroid Build Coastguard Worker 
662*5e7646d2SAndroid Build Coastguard Worker   if (prev >= 0)
663*5e7646d2SAndroid Build Coastguard Worker   {
664*5e7646d2SAndroid Build Coastguard Worker    /*
665*5e7646d2SAndroid Build Coastguard Worker     * Start search on either side of previous...
666*5e7646d2SAndroid Build Coastguard Worker     */
667*5e7646d2SAndroid Build Coastguard Worker 
668*5e7646d2SAndroid Build Coastguard Worker     if ((diff = cups_compare_options(&key, options + prev)) == 0 ||
669*5e7646d2SAndroid Build Coastguard Worker         (diff < 0 && prev == 0) ||
670*5e7646d2SAndroid Build Coastguard Worker 	(diff > 0 && prev == (num_options - 1)))
671*5e7646d2SAndroid Build Coastguard Worker     {
672*5e7646d2SAndroid Build Coastguard Worker       *rdiff = diff;
673*5e7646d2SAndroid Build Coastguard Worker       return (prev);
674*5e7646d2SAndroid Build Coastguard Worker     }
675*5e7646d2SAndroid Build Coastguard Worker     else if (diff < 0)
676*5e7646d2SAndroid Build Coastguard Worker     {
677*5e7646d2SAndroid Build Coastguard Worker      /*
678*5e7646d2SAndroid Build Coastguard Worker       * Start with previous on right side...
679*5e7646d2SAndroid Build Coastguard Worker       */
680*5e7646d2SAndroid Build Coastguard Worker 
681*5e7646d2SAndroid Build Coastguard Worker       left  = 0;
682*5e7646d2SAndroid Build Coastguard Worker       right = prev;
683*5e7646d2SAndroid Build Coastguard Worker     }
684*5e7646d2SAndroid Build Coastguard Worker     else
685*5e7646d2SAndroid Build Coastguard Worker     {
686*5e7646d2SAndroid Build Coastguard Worker      /*
687*5e7646d2SAndroid Build Coastguard Worker       * Start wih previous on left side...
688*5e7646d2SAndroid Build Coastguard Worker       */
689*5e7646d2SAndroid Build Coastguard Worker 
690*5e7646d2SAndroid Build Coastguard Worker       left  = prev;
691*5e7646d2SAndroid Build Coastguard Worker       right = num_options - 1;
692*5e7646d2SAndroid Build Coastguard Worker     }
693*5e7646d2SAndroid Build Coastguard Worker   }
694*5e7646d2SAndroid Build Coastguard Worker   else
695*5e7646d2SAndroid Build Coastguard Worker   {
696*5e7646d2SAndroid Build Coastguard Worker    /*
697*5e7646d2SAndroid Build Coastguard Worker     * Start search in the middle...
698*5e7646d2SAndroid Build Coastguard Worker     */
699*5e7646d2SAndroid Build Coastguard Worker 
700*5e7646d2SAndroid Build Coastguard Worker     left  = 0;
701*5e7646d2SAndroid Build Coastguard Worker     right = num_options - 1;
702*5e7646d2SAndroid Build Coastguard Worker   }
703*5e7646d2SAndroid Build Coastguard Worker 
704*5e7646d2SAndroid Build Coastguard Worker   do
705*5e7646d2SAndroid Build Coastguard Worker   {
706*5e7646d2SAndroid Build Coastguard Worker     current = (left + right) / 2;
707*5e7646d2SAndroid Build Coastguard Worker     diff    = cups_compare_options(&key, options + current);
708*5e7646d2SAndroid Build Coastguard Worker 
709*5e7646d2SAndroid Build Coastguard Worker     if (diff == 0)
710*5e7646d2SAndroid Build Coastguard Worker       break;
711*5e7646d2SAndroid Build Coastguard Worker     else if (diff < 0)
712*5e7646d2SAndroid Build Coastguard Worker       right = current;
713*5e7646d2SAndroid Build Coastguard Worker     else
714*5e7646d2SAndroid Build Coastguard Worker       left = current;
715*5e7646d2SAndroid Build Coastguard Worker   }
716*5e7646d2SAndroid Build Coastguard Worker   while ((right - left) > 1);
717*5e7646d2SAndroid Build Coastguard Worker 
718*5e7646d2SAndroid Build Coastguard Worker   if (diff != 0)
719*5e7646d2SAndroid Build Coastguard Worker   {
720*5e7646d2SAndroid Build Coastguard Worker    /*
721*5e7646d2SAndroid Build Coastguard Worker     * Check the last 1 or 2 elements...
722*5e7646d2SAndroid Build Coastguard Worker     */
723*5e7646d2SAndroid Build Coastguard Worker 
724*5e7646d2SAndroid Build Coastguard Worker     if ((diff = cups_compare_options(&key, options + left)) <= 0)
725*5e7646d2SAndroid Build Coastguard Worker       current = left;
726*5e7646d2SAndroid Build Coastguard Worker     else
727*5e7646d2SAndroid Build Coastguard Worker     {
728*5e7646d2SAndroid Build Coastguard Worker       diff    = cups_compare_options(&key, options + right);
729*5e7646d2SAndroid Build Coastguard Worker       current = right;
730*5e7646d2SAndroid Build Coastguard Worker     }
731*5e7646d2SAndroid Build Coastguard Worker   }
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker  /*
734*5e7646d2SAndroid Build Coastguard Worker   * Return the closest destination and the difference...
735*5e7646d2SAndroid Build Coastguard Worker   */
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker   *rdiff = diff;
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker   return (current);
740*5e7646d2SAndroid Build Coastguard Worker }
741