]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/options.c
Merge changes from CUPS 1.4svn-r7282.
[thirdparty/cups.git] / cups / options.c
1 /*
2 * "$Id: options.c 7278 2008-01-31 01:23:09Z mike $"
3 *
4 * Option routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * cupsAddOption() - Add an option to an option array.
20 * cupsFreeOptions() - Free all memory used by options.
21 * cupsGetOption() - Get an option value.
22 * cupsParseOptions() - Parse options from a command-line argument.
23 * cupsRemoveOption() - Remove an option from an option array.
24 */
25
26 /*
27 * Include necessary headers...
28 */
29
30 #include "cups.h"
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include "string.h"
34 #include "debug.h"
35
36
37 /*
38 * 'cupsAddOption()' - Add an option to an option array.
39 *
40 * New option arrays can be initialized simply by passing 0 for the
41 * "num_options" parameter.
42 */
43
44 int /* O - Number of options */
45 cupsAddOption(const char *name, /* I - Name of option */
46 const char *value, /* I - Value of option */
47 int num_options,/* I - Number of options */
48 cups_option_t **options) /* IO - Pointer to options */
49 {
50 int i; /* Looping var */
51 cups_option_t *temp; /* Pointer to new option */
52
53
54 if (name == NULL || !name[0] || value == NULL ||
55 options == NULL || num_options < 0)
56 return (num_options);
57
58 /*
59 * Look for an existing option with the same name...
60 */
61
62 for (i = 0, temp = *options; i < num_options; i ++, temp ++)
63 if (!strcasecmp(temp->name, name))
64 break;
65
66 if (i >= num_options)
67 {
68 /*
69 * No matching option name...
70 */
71
72 if (num_options == 0)
73 temp = (cups_option_t *)malloc(sizeof(cups_option_t));
74 else
75 temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) *
76 (num_options + 1));
77
78 if (temp == NULL)
79 return (0);
80
81 *options = temp;
82 temp += num_options;
83 temp->name = _cupsStrAlloc(name);
84 num_options ++;
85 }
86 else
87 {
88 /*
89 * Match found; free the old value...
90 */
91
92 _cupsStrFree(temp->value);
93 }
94
95 temp->value = _cupsStrAlloc(value);
96
97 return (num_options);
98 }
99
100
101 /*
102 * 'cupsFreeOptions()' - Free all memory used by options.
103 */
104
105 void
106 cupsFreeOptions(
107 int num_options, /* I - Number of options */
108 cups_option_t *options) /* I - Pointer to options */
109 {
110 int i; /* Looping var */
111
112
113 if (num_options <= 0 || options == NULL)
114 return;
115
116 for (i = 0; i < num_options; i ++)
117 {
118 _cupsStrFree(options[i].name);
119 _cupsStrFree(options[i].value);
120 }
121
122 free(options);
123 }
124
125
126 /*
127 * 'cupsGetOption()' - Get an option value.
128 */
129
130 const char * /* O - Option value or @code NULL@ */
131 cupsGetOption(const char *name, /* I - Name of option */
132 int num_options,/* I - Number of options */
133 cups_option_t *options) /* I - Options */
134 {
135 int i; /* Looping var */
136
137
138 if (name == NULL || num_options <= 0 || options == NULL)
139 return (NULL);
140
141 for (i = 0; i < num_options; i ++)
142 if (strcasecmp(options[i].name, name) == 0)
143 return (options[i].value);
144
145 return (NULL);
146 }
147
148
149 /*
150 * 'cupsParseOptions()' - Parse options from a command-line argument.
151 *
152 * This function converts space-delimited name/value pairs according
153 * to the PAPI text option ABNF specification. Collection values
154 * ("name={a=... b=... c=...}") are stored with the curley brackets
155 * intact - use @code cupsParseOptions@ on the value to extract the
156 * collection attributes.
157 */
158
159 int /* O - Number of options found */
160 cupsParseOptions(
161 const char *arg, /* I - Argument to parse */
162 int num_options, /* I - Number of options */
163 cups_option_t **options) /* O - Options found */
164 {
165 char *copyarg, /* Copy of input string */
166 *ptr, /* Pointer into string */
167 *name, /* Pointer to name */
168 *value, /* Pointer to value */
169 quote; /* Quote character */
170
171
172 /*
173 * Range check input...
174 */
175
176 if (!arg)
177 return (num_options);
178
179 if (!options || num_options < 0)
180 return (0);
181
182 /*
183 * Make a copy of the argument string and then divide it up...
184 */
185
186 if ((copyarg = strdup(arg)) == NULL)
187 return (num_options);
188
189 ptr = copyarg;
190
191 /*
192 * Skip leading spaces...
193 */
194
195 while (isspace(*ptr & 255))
196 ptr ++;
197
198 /*
199 * Loop through the string...
200 */
201
202 while (*ptr != '\0')
203 {
204 /*
205 * Get the name up to a SPACE, =, or end-of-string...
206 */
207
208 name = ptr;
209 while (!isspace(*ptr & 255) && *ptr != '=' && *ptr)
210 ptr ++;
211
212 /*
213 * Avoid an empty name...
214 */
215
216 if (ptr == name)
217 break;
218
219 /*
220 * Skip trailing spaces...
221 */
222
223 while (isspace(*ptr & 255))
224 *ptr++ = '\0';
225
226 if (*ptr != '=')
227 {
228 /*
229 * Boolean option...
230 */
231
232 if (!strncasecmp(name, "no", 2))
233 num_options = cupsAddOption(name + 2, "false", num_options,
234 options);
235 else
236 num_options = cupsAddOption(name, "true", num_options, options);
237
238 continue;
239 }
240
241 /*
242 * Remove = and parse the value...
243 */
244
245 *ptr++ = '\0';
246
247 if (*ptr == '\'' || *ptr == '\"')
248 {
249 /*
250 * Quoted string constant...
251 */
252
253 quote = *ptr++;
254 value = ptr;
255
256 while (*ptr != quote && *ptr)
257 {
258 if (*ptr == '\\' && ptr[1])
259 _cups_strcpy(ptr, ptr + 1);
260
261 ptr ++;
262 }
263
264 if (*ptr != '\0')
265 *ptr++ = '\0';
266 }
267 else if (*ptr == '{')
268 {
269 /*
270 * Collection value...
271 */
272
273 int depth;
274
275 value = ptr;
276
277 for (depth = 1; *ptr; ptr ++)
278 if (*ptr == '{')
279 depth ++;
280 else if (*ptr == '}')
281 {
282 depth --;
283 if (!depth)
284 {
285 ptr ++;
286
287 if (*ptr != ',')
288 break;
289 }
290 }
291 else if (*ptr == '\\' && ptr[1])
292 _cups_strcpy(ptr, ptr + 1);
293
294 if (*ptr != '\0')
295 *ptr++ = '\0';
296 }
297 else
298 {
299 /*
300 * Normal space-delimited string...
301 */
302
303 value = ptr;
304
305 while (!isspace(*ptr & 255) && *ptr)
306 {
307 if (*ptr == '\\' && ptr[1])
308 _cups_strcpy(ptr, ptr + 1);
309
310 ptr ++;
311 }
312 }
313
314 /*
315 * Skip trailing whitespace...
316 */
317
318 while (isspace(*ptr & 255))
319 *ptr++ = '\0';
320
321 /*
322 * Add the string value...
323 */
324
325 num_options = cupsAddOption(name, value, num_options, options);
326 }
327
328 /*
329 * Free the copy of the argument we made and return the number of options
330 * found.
331 */
332
333 free(copyarg);
334
335 return (num_options);
336 }
337
338
339 /*
340 * 'cupsRemoveOption()' - Remove an option from an option array.
341 *
342 * @since CUPS 1.2@
343 */
344
345 int /* O - New number of options */
346 cupsRemoveOption(
347 const char *name, /* I - Option name */
348 int num_options, /* I - Current number of options */
349 cups_option_t **options) /* IO - Options */
350 {
351 int i; /* Looping var */
352 cups_option_t *option; /* Current option */
353
354
355 /*
356 * Range check input...
357 */
358
359 if (!name || num_options < 1 || !options)
360 return (num_options);
361
362 /*
363 * Loop for the option...
364 */
365
366 for (i = num_options, option = *options; i > 0; i --, option ++)
367 if (!strcasecmp(name, option->name))
368 break;
369
370 if (i)
371 {
372 /*
373 * Remove this option from the array...
374 */
375
376 num_options --;
377 i --;
378
379 _cupsStrFree(option->name);
380 _cupsStrFree(option->value);
381
382 if (i > 0)
383 memmove(option, option + 1, i * sizeof(cups_option_t));
384 }
385
386 /*
387 * Return the new number of options...
388 */
389
390 return (num_options);
391 }
392
393
394 /*
395 * End of "$Id: options.c 7278 2008-01-31 01:23:09Z mike $".
396 */