xref: /aosp_15_r20/external/libcups/cups/ppd.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * PPD file routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  *
10*5e7646d2SAndroid Build Coastguard Worker  * PostScript is a trademark of Adobe Systems, Inc.
11*5e7646d2SAndroid Build Coastguard Worker  */
12*5e7646d2SAndroid Build Coastguard Worker 
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers.
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
18*5e7646d2SAndroid Build Coastguard Worker #include "ppd-private.h"
19*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker  * Definitions...
24*5e7646d2SAndroid Build Coastguard Worker  */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker #define PPD_KEYWORD	1		/* Line contained a keyword */
27*5e7646d2SAndroid Build Coastguard Worker #define PPD_OPTION	2		/* Line contained an option name */
28*5e7646d2SAndroid Build Coastguard Worker #define PPD_TEXT	4		/* Line contained human-readable text */
29*5e7646d2SAndroid Build Coastguard Worker #define PPD_STRING	8		/* Line contained a string or code */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker #define PPD_HASHSIZE	512		/* Size of hash */
32*5e7646d2SAndroid Build Coastguard Worker 
33*5e7646d2SAndroid Build Coastguard Worker 
34*5e7646d2SAndroid Build Coastguard Worker /*
35*5e7646d2SAndroid Build Coastguard Worker  * Line buffer structure...
36*5e7646d2SAndroid Build Coastguard Worker  */
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker typedef struct _ppd_line_s
39*5e7646d2SAndroid Build Coastguard Worker {
40*5e7646d2SAndroid Build Coastguard Worker   char		*buffer;		/* Pointer to buffer */
41*5e7646d2SAndroid Build Coastguard Worker   size_t	bufsize;		/* Size of the buffer */
42*5e7646d2SAndroid Build Coastguard Worker } _ppd_line_t;
43*5e7646d2SAndroid Build Coastguard Worker 
44*5e7646d2SAndroid Build Coastguard Worker 
45*5e7646d2SAndroid Build Coastguard Worker /*
46*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
47*5e7646d2SAndroid Build Coastguard Worker  */
48*5e7646d2SAndroid Build Coastguard Worker 
49*5e7646d2SAndroid Build Coastguard Worker static _cups_threadkey_t ppd_globals_key = _CUPS_THREADKEY_INITIALIZER;
50*5e7646d2SAndroid Build Coastguard Worker 					/* Thread local storage key */
51*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
52*5e7646d2SAndroid Build Coastguard Worker static pthread_once_t	ppd_globals_key_once = PTHREAD_ONCE_INIT;
53*5e7646d2SAndroid Build Coastguard Worker 					/* One-time initialization object */
54*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
55*5e7646d2SAndroid Build Coastguard Worker 
56*5e7646d2SAndroid Build Coastguard Worker 
57*5e7646d2SAndroid Build Coastguard Worker /*
58*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
59*5e7646d2SAndroid Build Coastguard Worker  */
60*5e7646d2SAndroid Build Coastguard Worker 
61*5e7646d2SAndroid Build Coastguard Worker static ppd_attr_t	*ppd_add_attr(ppd_file_t *ppd, const char *name,
62*5e7646d2SAndroid Build Coastguard Worker 			              const char *spec, const char *text,
63*5e7646d2SAndroid Build Coastguard Worker 				      const char *value);
64*5e7646d2SAndroid Build Coastguard Worker static ppd_choice_t	*ppd_add_choice(ppd_option_t *option, const char *name);
65*5e7646d2SAndroid Build Coastguard Worker static ppd_size_t	*ppd_add_size(ppd_file_t *ppd, const char *name);
66*5e7646d2SAndroid Build Coastguard Worker static int		ppd_compare_attrs(ppd_attr_t *a, ppd_attr_t *b);
67*5e7646d2SAndroid Build Coastguard Worker static int		ppd_compare_choices(ppd_choice_t *a, ppd_choice_t *b);
68*5e7646d2SAndroid Build Coastguard Worker static int		ppd_compare_coptions(ppd_coption_t *a,
69*5e7646d2SAndroid Build Coastguard Worker 			                     ppd_coption_t *b);
70*5e7646d2SAndroid Build Coastguard Worker static int		ppd_compare_options(ppd_option_t *a, ppd_option_t *b);
71*5e7646d2SAndroid Build Coastguard Worker static int		ppd_decode(char *string);
72*5e7646d2SAndroid Build Coastguard Worker static void		ppd_free_filters(ppd_file_t *ppd);
73*5e7646d2SAndroid Build Coastguard Worker static void		ppd_free_group(ppd_group_t *group);
74*5e7646d2SAndroid Build Coastguard Worker static void		ppd_free_option(ppd_option_t *option);
75*5e7646d2SAndroid Build Coastguard Worker static ppd_coption_t	*ppd_get_coption(ppd_file_t *ppd, const char *name);
76*5e7646d2SAndroid Build Coastguard Worker static ppd_cparam_t	*ppd_get_cparam(ppd_coption_t *opt,
77*5e7646d2SAndroid Build Coastguard Worker 			                const char *param,
78*5e7646d2SAndroid Build Coastguard Worker 					const char *text);
79*5e7646d2SAndroid Build Coastguard Worker static ppd_group_t	*ppd_get_group(ppd_file_t *ppd, const char *name,
80*5e7646d2SAndroid Build Coastguard Worker 			               const char *text, _ppd_globals_t *pg,
81*5e7646d2SAndroid Build Coastguard Worker 				       cups_encoding_t encoding);
82*5e7646d2SAndroid Build Coastguard Worker static ppd_option_t	*ppd_get_option(ppd_group_t *group, const char *name);
83*5e7646d2SAndroid Build Coastguard Worker static _ppd_globals_t	*ppd_globals_alloc(void);
84*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
85*5e7646d2SAndroid Build Coastguard Worker static void		ppd_globals_free(_ppd_globals_t *g);
86*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H || _WIN32 */
87*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
88*5e7646d2SAndroid Build Coastguard Worker static void		ppd_globals_init(void);
89*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
90*5e7646d2SAndroid Build Coastguard Worker static int		ppd_hash_option(ppd_option_t *option);
91*5e7646d2SAndroid Build Coastguard Worker static int		ppd_read(cups_file_t *fp, _ppd_line_t *line,
92*5e7646d2SAndroid Build Coastguard Worker 			         char *keyword, char *option, char *text,
93*5e7646d2SAndroid Build Coastguard Worker 				 char **string, int ignoreblank,
94*5e7646d2SAndroid Build Coastguard Worker 				 _ppd_globals_t *pg);
95*5e7646d2SAndroid Build Coastguard Worker static int		ppd_update_filters(ppd_file_t *ppd,
96*5e7646d2SAndroid Build Coastguard Worker 			                   _ppd_globals_t *pg);
97*5e7646d2SAndroid Build Coastguard Worker 
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker /*
100*5e7646d2SAndroid Build Coastguard Worker  * 'ppdClose()' - Free all memory used by the PPD file.
101*5e7646d2SAndroid Build Coastguard Worker  */
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker void
ppdClose(ppd_file_t * ppd)104*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
105*5e7646d2SAndroid Build Coastguard Worker {
106*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
107*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t		*group;		/* Current group */
108*5e7646d2SAndroid Build Coastguard Worker   char			**font;		/* Current font */
109*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t		**attr;		/* Current attribute */
110*5e7646d2SAndroid Build Coastguard Worker   ppd_coption_t		*coption;	/* Current custom option */
111*5e7646d2SAndroid Build Coastguard Worker   ppd_cparam_t		*cparam;	/* Current custom parameter */
112*5e7646d2SAndroid Build Coastguard Worker 
113*5e7646d2SAndroid Build Coastguard Worker 
114*5e7646d2SAndroid Build Coastguard Worker  /*
115*5e7646d2SAndroid Build Coastguard Worker   * Range check arguments...
116*5e7646d2SAndroid Build Coastguard Worker   */
117*5e7646d2SAndroid Build Coastguard Worker 
118*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
119*5e7646d2SAndroid Build Coastguard Worker     return;
120*5e7646d2SAndroid Build Coastguard Worker 
121*5e7646d2SAndroid Build Coastguard Worker  /*
122*5e7646d2SAndroid Build Coastguard Worker   * Free all strings at the top level...
123*5e7646d2SAndroid Build Coastguard Worker   */
124*5e7646d2SAndroid Build Coastguard Worker 
125*5e7646d2SAndroid Build Coastguard Worker   free(ppd->lang_encoding);
126*5e7646d2SAndroid Build Coastguard Worker   free(ppd->nickname);
127*5e7646d2SAndroid Build Coastguard Worker   free(ppd->patches);
128*5e7646d2SAndroid Build Coastguard Worker   free(ppd->emulations);
129*5e7646d2SAndroid Build Coastguard Worker   free(ppd->jcl_begin);
130*5e7646d2SAndroid Build Coastguard Worker   free(ppd->jcl_end);
131*5e7646d2SAndroid Build Coastguard Worker   free(ppd->jcl_ps);
132*5e7646d2SAndroid Build Coastguard Worker 
133*5e7646d2SAndroid Build Coastguard Worker  /*
134*5e7646d2SAndroid Build Coastguard Worker   * Free any UI groups, subgroups, and options...
135*5e7646d2SAndroid Build Coastguard Worker   */
136*5e7646d2SAndroid Build Coastguard Worker 
137*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_groups > 0)
138*5e7646d2SAndroid Build Coastguard Worker   {
139*5e7646d2SAndroid Build Coastguard Worker     for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
140*5e7646d2SAndroid Build Coastguard Worker       ppd_free_group(group);
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker     free(ppd->groups);
143*5e7646d2SAndroid Build Coastguard Worker   }
144*5e7646d2SAndroid Build Coastguard Worker 
145*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(ppd->options);
146*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(ppd->marked);
147*5e7646d2SAndroid Build Coastguard Worker 
148*5e7646d2SAndroid Build Coastguard Worker  /*
149*5e7646d2SAndroid Build Coastguard Worker   * Free any page sizes...
150*5e7646d2SAndroid Build Coastguard Worker   */
151*5e7646d2SAndroid Build Coastguard Worker 
152*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_sizes > 0)
153*5e7646d2SAndroid Build Coastguard Worker     free(ppd->sizes);
154*5e7646d2SAndroid Build Coastguard Worker 
155*5e7646d2SAndroid Build Coastguard Worker  /*
156*5e7646d2SAndroid Build Coastguard Worker   * Free any constraints...
157*5e7646d2SAndroid Build Coastguard Worker   */
158*5e7646d2SAndroid Build Coastguard Worker 
159*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_consts > 0)
160*5e7646d2SAndroid Build Coastguard Worker     free(ppd->consts);
161*5e7646d2SAndroid Build Coastguard Worker 
162*5e7646d2SAndroid Build Coastguard Worker  /*
163*5e7646d2SAndroid Build Coastguard Worker   * Free any filters...
164*5e7646d2SAndroid Build Coastguard Worker   */
165*5e7646d2SAndroid Build Coastguard Worker 
166*5e7646d2SAndroid Build Coastguard Worker   ppd_free_filters(ppd);
167*5e7646d2SAndroid Build Coastguard Worker 
168*5e7646d2SAndroid Build Coastguard Worker  /*
169*5e7646d2SAndroid Build Coastguard Worker   * Free any fonts...
170*5e7646d2SAndroid Build Coastguard Worker   */
171*5e7646d2SAndroid Build Coastguard Worker 
172*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_fonts > 0)
173*5e7646d2SAndroid Build Coastguard Worker   {
174*5e7646d2SAndroid Build Coastguard Worker     for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++)
175*5e7646d2SAndroid Build Coastguard Worker       free(*font);
176*5e7646d2SAndroid Build Coastguard Worker 
177*5e7646d2SAndroid Build Coastguard Worker     free(ppd->fonts);
178*5e7646d2SAndroid Build Coastguard Worker   }
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker  /*
181*5e7646d2SAndroid Build Coastguard Worker   * Free any profiles...
182*5e7646d2SAndroid Build Coastguard Worker   */
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_profiles > 0)
185*5e7646d2SAndroid Build Coastguard Worker     free(ppd->profiles);
186*5e7646d2SAndroid Build Coastguard Worker 
187*5e7646d2SAndroid Build Coastguard Worker  /*
188*5e7646d2SAndroid Build Coastguard Worker   * Free any attributes...
189*5e7646d2SAndroid Build Coastguard Worker   */
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_attrs > 0)
192*5e7646d2SAndroid Build Coastguard Worker   {
193*5e7646d2SAndroid Build Coastguard Worker     for (i = ppd->num_attrs, attr = ppd->attrs; i > 0; i --, attr ++)
194*5e7646d2SAndroid Build Coastguard Worker     {
195*5e7646d2SAndroid Build Coastguard Worker       free((*attr)->value);
196*5e7646d2SAndroid Build Coastguard Worker       free(*attr);
197*5e7646d2SAndroid Build Coastguard Worker     }
198*5e7646d2SAndroid Build Coastguard Worker 
199*5e7646d2SAndroid Build Coastguard Worker     free(ppd->attrs);
200*5e7646d2SAndroid Build Coastguard Worker   }
201*5e7646d2SAndroid Build Coastguard Worker 
202*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(ppd->sorted_attrs);
203*5e7646d2SAndroid Build Coastguard Worker 
204*5e7646d2SAndroid Build Coastguard Worker  /*
205*5e7646d2SAndroid Build Coastguard Worker   * Free custom options...
206*5e7646d2SAndroid Build Coastguard Worker   */
207*5e7646d2SAndroid Build Coastguard Worker 
208*5e7646d2SAndroid Build Coastguard Worker   for (coption = (ppd_coption_t *)cupsArrayFirst(ppd->coptions);
209*5e7646d2SAndroid Build Coastguard Worker        coption;
210*5e7646d2SAndroid Build Coastguard Worker        coption = (ppd_coption_t *)cupsArrayNext(ppd->coptions))
211*5e7646d2SAndroid Build Coastguard Worker   {
212*5e7646d2SAndroid Build Coastguard Worker     for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
213*5e7646d2SAndroid Build Coastguard Worker          cparam;
214*5e7646d2SAndroid Build Coastguard Worker 	 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
215*5e7646d2SAndroid Build Coastguard Worker     {
216*5e7646d2SAndroid Build Coastguard Worker       switch (cparam->type)
217*5e7646d2SAndroid Build Coastguard Worker       {
218*5e7646d2SAndroid Build Coastguard Worker         case PPD_CUSTOM_PASSCODE :
219*5e7646d2SAndroid Build Coastguard Worker         case PPD_CUSTOM_PASSWORD :
220*5e7646d2SAndroid Build Coastguard Worker         case PPD_CUSTOM_STRING :
221*5e7646d2SAndroid Build Coastguard Worker             free(cparam->current.custom_string);
222*5e7646d2SAndroid Build Coastguard Worker 	    break;
223*5e7646d2SAndroid Build Coastguard Worker 
224*5e7646d2SAndroid Build Coastguard Worker 	default :
225*5e7646d2SAndroid Build Coastguard Worker 	    break;
226*5e7646d2SAndroid Build Coastguard Worker       }
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker       free(cparam);
229*5e7646d2SAndroid Build Coastguard Worker     }
230*5e7646d2SAndroid Build Coastguard Worker 
231*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(coption->params);
232*5e7646d2SAndroid Build Coastguard Worker 
233*5e7646d2SAndroid Build Coastguard Worker     free(coption);
234*5e7646d2SAndroid Build Coastguard Worker   }
235*5e7646d2SAndroid Build Coastguard Worker 
236*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(ppd->coptions);
237*5e7646d2SAndroid Build Coastguard Worker 
238*5e7646d2SAndroid Build Coastguard Worker  /*
239*5e7646d2SAndroid Build Coastguard Worker   * Free constraints...
240*5e7646d2SAndroid Build Coastguard Worker   */
241*5e7646d2SAndroid Build Coastguard Worker 
242*5e7646d2SAndroid Build Coastguard Worker   if (ppd->cups_uiconstraints)
243*5e7646d2SAndroid Build Coastguard Worker   {
244*5e7646d2SAndroid Build Coastguard Worker     _ppd_cups_uiconsts_t *consts;	/* Current constraints */
245*5e7646d2SAndroid Build Coastguard Worker 
246*5e7646d2SAndroid Build Coastguard Worker 
247*5e7646d2SAndroid Build Coastguard Worker     for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints);
248*5e7646d2SAndroid Build Coastguard Worker          consts;
249*5e7646d2SAndroid Build Coastguard Worker 	 consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints))
250*5e7646d2SAndroid Build Coastguard Worker     {
251*5e7646d2SAndroid Build Coastguard Worker       free(consts->constraints);
252*5e7646d2SAndroid Build Coastguard Worker       free(consts);
253*5e7646d2SAndroid Build Coastguard Worker     }
254*5e7646d2SAndroid Build Coastguard Worker 
255*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(ppd->cups_uiconstraints);
256*5e7646d2SAndroid Build Coastguard Worker   }
257*5e7646d2SAndroid Build Coastguard Worker 
258*5e7646d2SAndroid Build Coastguard Worker  /*
259*5e7646d2SAndroid Build Coastguard Worker   * Free any PPD cache/mapping data...
260*5e7646d2SAndroid Build Coastguard Worker   */
261*5e7646d2SAndroid Build Coastguard Worker 
262*5e7646d2SAndroid Build Coastguard Worker   if (ppd->cache)
263*5e7646d2SAndroid Build Coastguard Worker     _ppdCacheDestroy(ppd->cache);
264*5e7646d2SAndroid Build Coastguard Worker 
265*5e7646d2SAndroid Build Coastguard Worker  /*
266*5e7646d2SAndroid Build Coastguard Worker   * Free the whole record...
267*5e7646d2SAndroid Build Coastguard Worker   */
268*5e7646d2SAndroid Build Coastguard Worker 
269*5e7646d2SAndroid Build Coastguard Worker   free(ppd);
270*5e7646d2SAndroid Build Coastguard Worker }
271*5e7646d2SAndroid Build Coastguard Worker 
272*5e7646d2SAndroid Build Coastguard Worker 
273*5e7646d2SAndroid Build Coastguard Worker /*
274*5e7646d2SAndroid Build Coastguard Worker  * 'ppdErrorString()' - Returns the text associated with a status.
275*5e7646d2SAndroid Build Coastguard Worker  *
276*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
277*5e7646d2SAndroid Build Coastguard Worker  */
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - Status string */
ppdErrorString(ppd_status_t status)280*5e7646d2SAndroid Build Coastguard Worker ppdErrorString(ppd_status_t status)	/* I - PPD status */
281*5e7646d2SAndroid Build Coastguard Worker {
282*5e7646d2SAndroid Build Coastguard Worker   static const char * const messages[] =/* Status messages */
283*5e7646d2SAndroid Build Coastguard Worker 		{
284*5e7646d2SAndroid Build Coastguard Worker 		  _("OK"),
285*5e7646d2SAndroid Build Coastguard Worker 		  _("Unable to open PPD file"),
286*5e7646d2SAndroid Build Coastguard Worker 		  _("NULL PPD file pointer"),
287*5e7646d2SAndroid Build Coastguard Worker 		  _("Memory allocation error"),
288*5e7646d2SAndroid Build Coastguard Worker 		  _("Missing PPD-Adobe-4.x header"),
289*5e7646d2SAndroid Build Coastguard Worker 		  _("Missing value string"),
290*5e7646d2SAndroid Build Coastguard Worker 		  _("Internal error"),
291*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad OpenGroup"),
292*5e7646d2SAndroid Build Coastguard Worker 		  _("OpenGroup without a CloseGroup first"),
293*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad OpenUI/JCLOpenUI"),
294*5e7646d2SAndroid Build Coastguard Worker 		  _("OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first"),
295*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad OrderDependency"),
296*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad UIConstraints"),
297*5e7646d2SAndroid Build Coastguard Worker 		  _("Missing asterisk in column 1"),
298*5e7646d2SAndroid Build Coastguard Worker 		  _("Line longer than the maximum allowed (255 characters)"),
299*5e7646d2SAndroid Build Coastguard Worker 		  _("Illegal control character"),
300*5e7646d2SAndroid Build Coastguard Worker 		  _("Illegal main keyword string"),
301*5e7646d2SAndroid Build Coastguard Worker 		  _("Illegal option keyword string"),
302*5e7646d2SAndroid Build Coastguard Worker 		  _("Illegal translation string"),
303*5e7646d2SAndroid Build Coastguard Worker 		  _("Illegal whitespace character"),
304*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad custom parameter"),
305*5e7646d2SAndroid Build Coastguard Worker 		  _("Missing option keyword"),
306*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad value string"),
307*5e7646d2SAndroid Build Coastguard Worker 		  _("Missing CloseGroup"),
308*5e7646d2SAndroid Build Coastguard Worker 		  _("Bad CloseUI/JCLCloseUI"),
309*5e7646d2SAndroid Build Coastguard Worker 		  _("Missing CloseUI/JCLCloseUI")
310*5e7646d2SAndroid Build Coastguard Worker 		};
311*5e7646d2SAndroid Build Coastguard Worker 
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker   if (status < PPD_OK || status >= PPD_MAX_STATUS)
314*5e7646d2SAndroid Build Coastguard Worker     return (_cupsLangString(cupsLangDefault(), _("Unknown")));
315*5e7646d2SAndroid Build Coastguard Worker   else
316*5e7646d2SAndroid Build Coastguard Worker     return (_cupsLangString(cupsLangDefault(), messages[status]));
317*5e7646d2SAndroid Build Coastguard Worker }
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker 
320*5e7646d2SAndroid Build Coastguard Worker /*
321*5e7646d2SAndroid Build Coastguard Worker  * '_ppdGetEncoding()' - Get the CUPS encoding value for the given
322*5e7646d2SAndroid Build Coastguard Worker  *                       LanguageEncoding.
323*5e7646d2SAndroid Build Coastguard Worker  */
324*5e7646d2SAndroid Build Coastguard Worker 
325*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t				/* O - CUPS encoding value */
_ppdGetEncoding(const char * name)326*5e7646d2SAndroid Build Coastguard Worker _ppdGetEncoding(const char *name)	/* I - LanguageEncoding string */
327*5e7646d2SAndroid Build Coastguard Worker {
328*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(name, "ISOLatin1"))
329*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_ISO8859_1);
330*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strcasecmp(name, "ISOLatin2"))
331*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_ISO8859_2);
332*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strcasecmp(name, "ISOLatin5"))
333*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_ISO8859_5);
334*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strcasecmp(name, "JIS83-RKSJ"))
335*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_JIS_X0213);
336*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strcasecmp(name, "MacStandard"))
337*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_MAC_ROMAN);
338*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strcasecmp(name, "WindowsANSI"))
339*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_WINDOWS_1252);
340*5e7646d2SAndroid Build Coastguard Worker   else
341*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_UTF8);
342*5e7646d2SAndroid Build Coastguard Worker }
343*5e7646d2SAndroid Build Coastguard Worker 
344*5e7646d2SAndroid Build Coastguard Worker 
345*5e7646d2SAndroid Build Coastguard Worker /*
346*5e7646d2SAndroid Build Coastguard Worker  * '_ppdGlobals()' - Return a pointer to thread local storage
347*5e7646d2SAndroid Build Coastguard Worker  */
348*5e7646d2SAndroid Build Coastguard Worker 
349*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *			/* O - Pointer to global data */
_ppdGlobals(void)350*5e7646d2SAndroid Build Coastguard Worker _ppdGlobals(void)
351*5e7646d2SAndroid Build Coastguard Worker {
352*5e7646d2SAndroid Build Coastguard Worker   _ppd_globals_t *pg;			/* Pointer to global data */
353*5e7646d2SAndroid Build Coastguard Worker 
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
356*5e7646d2SAndroid Build Coastguard Worker  /*
357*5e7646d2SAndroid Build Coastguard Worker   * Initialize the global data exactly once...
358*5e7646d2SAndroid Build Coastguard Worker   */
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker   pthread_once(&ppd_globals_key_once, ppd_globals_init);
361*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
362*5e7646d2SAndroid Build Coastguard Worker 
363*5e7646d2SAndroid Build Coastguard Worker  /*
364*5e7646d2SAndroid Build Coastguard Worker   * See if we have allocated the data yet...
365*5e7646d2SAndroid Build Coastguard Worker   */
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker   if ((pg = (_ppd_globals_t *)_cupsThreadGetData(ppd_globals_key)) == NULL)
368*5e7646d2SAndroid Build Coastguard Worker   {
369*5e7646d2SAndroid Build Coastguard Worker    /*
370*5e7646d2SAndroid Build Coastguard Worker     * No, allocate memory as set the pointer for the key...
371*5e7646d2SAndroid Build Coastguard Worker     */
372*5e7646d2SAndroid Build Coastguard Worker 
373*5e7646d2SAndroid Build Coastguard Worker     if ((pg = ppd_globals_alloc()) != NULL)
374*5e7646d2SAndroid Build Coastguard Worker       _cupsThreadSetData(ppd_globals_key, pg);
375*5e7646d2SAndroid Build Coastguard Worker   }
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker  /*
378*5e7646d2SAndroid Build Coastguard Worker   * Return the pointer to the data...
379*5e7646d2SAndroid Build Coastguard Worker   */
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker   return (pg);
382*5e7646d2SAndroid Build Coastguard Worker }
383*5e7646d2SAndroid Build Coastguard Worker 
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker /*
386*5e7646d2SAndroid Build Coastguard Worker  * 'ppdLastError()' - Return the status from the last ppdOpen*().
387*5e7646d2SAndroid Build Coastguard Worker  *
388*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
389*5e7646d2SAndroid Build Coastguard Worker  */
390*5e7646d2SAndroid Build Coastguard Worker 
391*5e7646d2SAndroid Build Coastguard Worker ppd_status_t				/* O - Status code */
ppdLastError(int * line)392*5e7646d2SAndroid Build Coastguard Worker ppdLastError(int *line)			/* O - Line number */
393*5e7646d2SAndroid Build Coastguard Worker {
394*5e7646d2SAndroid Build Coastguard Worker   _ppd_globals_t	*pg = _ppdGlobals();
395*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker   if (line)
399*5e7646d2SAndroid Build Coastguard Worker     *line = pg->ppd_line;
400*5e7646d2SAndroid Build Coastguard Worker 
401*5e7646d2SAndroid Build Coastguard Worker   return (pg->ppd_status);
402*5e7646d2SAndroid Build Coastguard Worker }
403*5e7646d2SAndroid Build Coastguard Worker 
404*5e7646d2SAndroid Build Coastguard Worker 
405*5e7646d2SAndroid Build Coastguard Worker /*
406*5e7646d2SAndroid Build Coastguard Worker  * '_ppdOpen()' - Read a PPD file into memory.
407*5e7646d2SAndroid Build Coastguard Worker  *
408*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
409*5e7646d2SAndroid Build Coastguard Worker  */
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *				/* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
_ppdOpen(cups_file_t * fp,_ppd_localization_t localization)412*5e7646d2SAndroid Build Coastguard Worker _ppdOpen(
413*5e7646d2SAndroid Build Coastguard Worker     cups_file_t		*fp,		/* I - File to read from */
414*5e7646d2SAndroid Build Coastguard Worker     _ppd_localization_t	localization)	/* I - Localization to load */
415*5e7646d2SAndroid Build Coastguard Worker {
416*5e7646d2SAndroid Build Coastguard Worker   int			i, j, k;	/* Looping vars */
417*5e7646d2SAndroid Build Coastguard Worker   _ppd_line_t		line;		/* Line buffer */
418*5e7646d2SAndroid Build Coastguard Worker   ppd_file_t		*ppd;		/* PPD file record */
419*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t		*group,		/* Current group */
420*5e7646d2SAndroid Build Coastguard Worker 			*subgroup;	/* Current sub-group */
421*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t		*option;	/* Current option */
422*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t		*choice;	/* Current choice */
423*5e7646d2SAndroid Build Coastguard Worker   ppd_const_t		*constraint;	/* Current constraint */
424*5e7646d2SAndroid Build Coastguard Worker   ppd_size_t		*size;		/* Current page size */
425*5e7646d2SAndroid Build Coastguard Worker   int			mask;		/* Line data mask */
426*5e7646d2SAndroid Build Coastguard Worker   char			keyword[PPD_MAX_NAME],
427*5e7646d2SAndroid Build Coastguard Worker   					/* Keyword from file */
428*5e7646d2SAndroid Build Coastguard Worker 			name[PPD_MAX_NAME],
429*5e7646d2SAndroid Build Coastguard Worker 					/* Option from file */
430*5e7646d2SAndroid Build Coastguard Worker 			text[PPD_MAX_LINE],
431*5e7646d2SAndroid Build Coastguard Worker 					/* Human-readable text from file */
432*5e7646d2SAndroid Build Coastguard Worker 			*string,	/* Code/text from file */
433*5e7646d2SAndroid Build Coastguard Worker 			*sptr,		/* Pointer into string */
434*5e7646d2SAndroid Build Coastguard Worker 			*temp,		/* Temporary string pointer */
435*5e7646d2SAndroid Build Coastguard Worker 			**tempfonts;	/* Temporary fonts pointer */
436*5e7646d2SAndroid Build Coastguard Worker   float			order;		/* Order dependency number */
437*5e7646d2SAndroid Build Coastguard Worker   ppd_section_t		section;	/* Order dependency section */
438*5e7646d2SAndroid Build Coastguard Worker   ppd_profile_t		*profile;	/* Pointer to color profile */
439*5e7646d2SAndroid Build Coastguard Worker   char			**filter;	/* Pointer to filter */
440*5e7646d2SAndroid Build Coastguard Worker   struct lconv		*loc;		/* Locale data */
441*5e7646d2SAndroid Build Coastguard Worker   int			ui_keyword;	/* Is this line a UI keyword? */
442*5e7646d2SAndroid Build Coastguard Worker   cups_lang_t		*lang;		/* Language data */
443*5e7646d2SAndroid Build Coastguard Worker   cups_encoding_t	encoding;	/* Encoding of PPD file */
444*5e7646d2SAndroid Build Coastguard Worker   _ppd_globals_t	*pg = _ppdGlobals();
445*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
446*5e7646d2SAndroid Build Coastguard Worker   char			custom_name[PPD_MAX_NAME];
447*5e7646d2SAndroid Build Coastguard Worker 					/* CustomFoo attribute name */
448*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t		*custom_attr;	/* CustomFoo attribute */
449*5e7646d2SAndroid Build Coastguard Worker   char			ll[7],		/* Base language + '.' */
450*5e7646d2SAndroid Build Coastguard Worker 			ll_CC[7];	/* Language w/country + '.' */
451*5e7646d2SAndroid Build Coastguard Worker   size_t		ll_len = 0,	/* Base language length */
452*5e7646d2SAndroid Build Coastguard Worker 			ll_CC_len = 0;	/* Language w/country length */
453*5e7646d2SAndroid Build Coastguard Worker   static const char * const ui_keywords[] =
454*5e7646d2SAndroid Build Coastguard Worker 			{
455*5e7646d2SAndroid Build Coastguard Worker #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST
456*5e7646d2SAndroid Build Coastguard Worker  /*
457*5e7646d2SAndroid Build Coastguard Worker   * Adobe defines some 41 keywords as "UI", meaning that they are
458*5e7646d2SAndroid Build Coastguard Worker   * user interface elements and that they should be treated as such
459*5e7646d2SAndroid Build Coastguard Worker   * even if the PPD creator doesn't use Open/CloseUI around them.
460*5e7646d2SAndroid Build Coastguard Worker   *
461*5e7646d2SAndroid Build Coastguard Worker   * Since this can cause previously invisible options to appear and
462*5e7646d2SAndroid Build Coastguard Worker   * confuse users, the default is to only treat the PageSize and
463*5e7646d2SAndroid Build Coastguard Worker   * PageRegion keywords this way.
464*5e7646d2SAndroid Build Coastguard Worker   */
465*5e7646d2SAndroid Build Coastguard Worker 			  /* Boolean keywords */
466*5e7646d2SAndroid Build Coastguard Worker 			  "BlackSubstitution",
467*5e7646d2SAndroid Build Coastguard Worker 			  "Booklet",
468*5e7646d2SAndroid Build Coastguard Worker 			  "Collate",
469*5e7646d2SAndroid Build Coastguard Worker 			  "ManualFeed",
470*5e7646d2SAndroid Build Coastguard Worker 			  "MirrorPrint",
471*5e7646d2SAndroid Build Coastguard Worker 			  "NegativePrint",
472*5e7646d2SAndroid Build Coastguard Worker 			  "Sorter",
473*5e7646d2SAndroid Build Coastguard Worker 			  "TraySwitch",
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker 			  /* PickOne keywords */
476*5e7646d2SAndroid Build Coastguard Worker 			  "AdvanceMedia",
477*5e7646d2SAndroid Build Coastguard Worker 			  "BindColor",
478*5e7646d2SAndroid Build Coastguard Worker 			  "BindEdge",
479*5e7646d2SAndroid Build Coastguard Worker 			  "BindType",
480*5e7646d2SAndroid Build Coastguard Worker 			  "BindWhen",
481*5e7646d2SAndroid Build Coastguard Worker 			  "BitsPerPixel",
482*5e7646d2SAndroid Build Coastguard Worker 			  "ColorModel",
483*5e7646d2SAndroid Build Coastguard Worker 			  "CutMedia",
484*5e7646d2SAndroid Build Coastguard Worker 			  "Duplex",
485*5e7646d2SAndroid Build Coastguard Worker 			  "FoldType",
486*5e7646d2SAndroid Build Coastguard Worker 			  "FoldWhen",
487*5e7646d2SAndroid Build Coastguard Worker 			  "InputSlot",
488*5e7646d2SAndroid Build Coastguard Worker 			  "JCLFrameBufferSize",
489*5e7646d2SAndroid Build Coastguard Worker 			  "JCLResolution",
490*5e7646d2SAndroid Build Coastguard Worker 			  "Jog",
491*5e7646d2SAndroid Build Coastguard Worker 			  "MediaColor",
492*5e7646d2SAndroid Build Coastguard Worker 			  "MediaType",
493*5e7646d2SAndroid Build Coastguard Worker 			  "MediaWeight",
494*5e7646d2SAndroid Build Coastguard Worker 			  "OutputBin",
495*5e7646d2SAndroid Build Coastguard Worker 			  "OutputMode",
496*5e7646d2SAndroid Build Coastguard Worker 			  "OutputOrder",
497*5e7646d2SAndroid Build Coastguard Worker 			  "PageRegion",
498*5e7646d2SAndroid Build Coastguard Worker 			  "PageSize",
499*5e7646d2SAndroid Build Coastguard Worker 			  "Resolution",
500*5e7646d2SAndroid Build Coastguard Worker 			  "Separations",
501*5e7646d2SAndroid Build Coastguard Worker 			  "Signature",
502*5e7646d2SAndroid Build Coastguard Worker 			  "Slipsheet",
503*5e7646d2SAndroid Build Coastguard Worker 			  "Smoothing",
504*5e7646d2SAndroid Build Coastguard Worker 			  "StapleLocation",
505*5e7646d2SAndroid Build Coastguard Worker 			  "StapleOrientation",
506*5e7646d2SAndroid Build Coastguard Worker 			  "StapleWhen",
507*5e7646d2SAndroid Build Coastguard Worker 			  "StapleX",
508*5e7646d2SAndroid Build Coastguard Worker 			  "StapleY"
509*5e7646d2SAndroid Build Coastguard Worker #else /* !CUPS_USE_FULL_UI_KEYWORDS_LIST */
510*5e7646d2SAndroid Build Coastguard Worker 			  "PageRegion",
511*5e7646d2SAndroid Build Coastguard Worker 			  "PageSize"
512*5e7646d2SAndroid Build Coastguard Worker #endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */
513*5e7646d2SAndroid Build Coastguard Worker 			};
514*5e7646d2SAndroid Build Coastguard Worker   static const char * const color_keywords[] =	/* Keywords associated with color profiles */
515*5e7646d2SAndroid Build Coastguard Worker 			{
516*5e7646d2SAndroid Build Coastguard Worker 			  ".cupsICCProfile",
517*5e7646d2SAndroid Build Coastguard Worker 			  ".ColorModel",
518*5e7646d2SAndroid Build Coastguard Worker 			};
519*5e7646d2SAndroid Build Coastguard Worker 
520*5e7646d2SAndroid Build Coastguard Worker 
521*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_ppdOpen(fp=%p)", fp));
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker  /*
524*5e7646d2SAndroid Build Coastguard Worker   * Default to "OK" status...
525*5e7646d2SAndroid Build Coastguard Worker   */
526*5e7646d2SAndroid Build Coastguard Worker 
527*5e7646d2SAndroid Build Coastguard Worker   pg->ppd_status = PPD_OK;
528*5e7646d2SAndroid Build Coastguard Worker   pg->ppd_line   = 0;
529*5e7646d2SAndroid Build Coastguard Worker 
530*5e7646d2SAndroid Build Coastguard Worker  /*
531*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
532*5e7646d2SAndroid Build Coastguard Worker   */
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker   if (fp == NULL)
535*5e7646d2SAndroid Build Coastguard Worker   {
536*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_NULL_FILE;
537*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
538*5e7646d2SAndroid Build Coastguard Worker   }
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker  /*
541*5e7646d2SAndroid Build Coastguard Worker   * If only loading a single localization set up the strings to match...
542*5e7646d2SAndroid Build Coastguard Worker   */
543*5e7646d2SAndroid Build Coastguard Worker 
544*5e7646d2SAndroid Build Coastguard Worker   if (localization == _PPD_LOCALIZATION_DEFAULT)
545*5e7646d2SAndroid Build Coastguard Worker   {
546*5e7646d2SAndroid Build Coastguard Worker     if ((lang = cupsLangDefault()) == NULL)
547*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
548*5e7646d2SAndroid Build Coastguard Worker 
549*5e7646d2SAndroid Build Coastguard Worker     snprintf(ll_CC, sizeof(ll_CC), "%s.", lang->language);
550*5e7646d2SAndroid Build Coastguard Worker 
551*5e7646d2SAndroid Build Coastguard Worker    /*
552*5e7646d2SAndroid Build Coastguard Worker     * <rdar://problem/22130168>
553*5e7646d2SAndroid Build Coastguard Worker     * <rdar://problem/27245567>
554*5e7646d2SAndroid Build Coastguard Worker     *
555*5e7646d2SAndroid Build Coastguard Worker     * Need to use a different base language for some locales...
556*5e7646d2SAndroid Build Coastguard Worker     */
557*5e7646d2SAndroid Build Coastguard Worker 
558*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(lang->language, "zh_HK"))
559*5e7646d2SAndroid Build Coastguard Worker     {					/* Traditional Chinese + variants */
560*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll_CC, "zh_TW.", sizeof(ll_CC));
561*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll, "zh_", sizeof(ll));
562*5e7646d2SAndroid Build Coastguard Worker     }
563*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(lang->language, "zh", 2))
564*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll, "zh_", sizeof(ll));	/* Any Chinese variant */
565*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(lang->language, "jp", 2))
566*5e7646d2SAndroid Build Coastguard Worker     {					/* Any Japanese variant */
567*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll_CC, "ja", sizeof(ll_CC));
568*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll, "jp", sizeof(ll));
569*5e7646d2SAndroid Build Coastguard Worker     }
570*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(lang->language, "nb", 2) || !strncmp(lang->language, "no", 2))
571*5e7646d2SAndroid Build Coastguard Worker     {					/* Any Norwegian variant */
572*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll_CC, "nb", sizeof(ll_CC));
573*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ll, "no", sizeof(ll));
574*5e7646d2SAndroid Build Coastguard Worker     }
575*5e7646d2SAndroid Build Coastguard Worker     else
576*5e7646d2SAndroid Build Coastguard Worker       snprintf(ll, sizeof(ll), "%2.2s.", lang->language);
577*5e7646d2SAndroid Build Coastguard Worker 
578*5e7646d2SAndroid Build Coastguard Worker     ll_CC_len = strlen(ll_CC);
579*5e7646d2SAndroid Build Coastguard Worker     ll_len    = strlen(ll);
580*5e7646d2SAndroid Build Coastguard Worker 
581*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("2_ppdOpen: Loading localizations matching \"%s\" and \"%s\"",
582*5e7646d2SAndroid Build Coastguard Worker                   ll_CC, ll));
583*5e7646d2SAndroid Build Coastguard Worker   }
584*5e7646d2SAndroid Build Coastguard Worker 
585*5e7646d2SAndroid Build Coastguard Worker  /*
586*5e7646d2SAndroid Build Coastguard Worker   * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
587*5e7646d2SAndroid Build Coastguard Worker   */
588*5e7646d2SAndroid Build Coastguard Worker 
589*5e7646d2SAndroid Build Coastguard Worker   line.buffer  = NULL;
590*5e7646d2SAndroid Build Coastguard Worker   line.bufsize = 0;
591*5e7646d2SAndroid Build Coastguard Worker 
592*5e7646d2SAndroid Build Coastguard Worker   mask = ppd_read(fp, &line, keyword, name, text, &string, 0, pg);
593*5e7646d2SAndroid Build Coastguard Worker 
594*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\"...", mask, keyword));
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker   if (mask == 0 ||
597*5e7646d2SAndroid Build Coastguard Worker       strcmp(keyword, "PPD-Adobe") ||
598*5e7646d2SAndroid Build Coastguard Worker       string == NULL || string[0] != '4')
599*5e7646d2SAndroid Build Coastguard Worker   {
600*5e7646d2SAndroid Build Coastguard Worker    /*
601*5e7646d2SAndroid Build Coastguard Worker     * Either this is not a PPD file, or it is not a 4.x PPD file.
602*5e7646d2SAndroid Build Coastguard Worker     */
603*5e7646d2SAndroid Build Coastguard Worker 
604*5e7646d2SAndroid Build Coastguard Worker     if (pg->ppd_status == PPD_OK)
605*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_MISSING_PPDADOBE4;
606*5e7646d2SAndroid Build Coastguard Worker 
607*5e7646d2SAndroid Build Coastguard Worker     free(string);
608*5e7646d2SAndroid Build Coastguard Worker     free(line.buffer);
609*5e7646d2SAndroid Build Coastguard Worker 
610*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
611*5e7646d2SAndroid Build Coastguard Worker   }
612*5e7646d2SAndroid Build Coastguard Worker 
613*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2_ppdOpen: keyword=%s, string=%p", keyword, string));
614*5e7646d2SAndroid Build Coastguard Worker 
615*5e7646d2SAndroid Build Coastguard Worker  /*
616*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory for the PPD file record...
617*5e7646d2SAndroid Build Coastguard Worker   */
618*5e7646d2SAndroid Build Coastguard Worker 
619*5e7646d2SAndroid Build Coastguard Worker   if ((ppd = calloc(1, sizeof(ppd_file_t))) == NULL)
620*5e7646d2SAndroid Build Coastguard Worker   {
621*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_ALLOC_ERROR;
622*5e7646d2SAndroid Build Coastguard Worker 
623*5e7646d2SAndroid Build Coastguard Worker     free(string);
624*5e7646d2SAndroid Build Coastguard Worker     free(line.buffer);
625*5e7646d2SAndroid Build Coastguard Worker 
626*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
627*5e7646d2SAndroid Build Coastguard Worker   }
628*5e7646d2SAndroid Build Coastguard Worker 
629*5e7646d2SAndroid Build Coastguard Worker   free(string);
630*5e7646d2SAndroid Build Coastguard Worker   string = NULL;
631*5e7646d2SAndroid Build Coastguard Worker 
632*5e7646d2SAndroid Build Coastguard Worker   ppd->language_level = 2;
633*5e7646d2SAndroid Build Coastguard Worker   ppd->color_device   = 0;
634*5e7646d2SAndroid Build Coastguard Worker   ppd->colorspace     = PPD_CS_N;
635*5e7646d2SAndroid Build Coastguard Worker   ppd->landscape      = -90;
636*5e7646d2SAndroid Build Coastguard Worker   ppd->coptions       = cupsArrayNew((cups_array_func_t)ppd_compare_coptions, NULL);
637*5e7646d2SAndroid Build Coastguard Worker 
638*5e7646d2SAndroid Build Coastguard Worker  /*
639*5e7646d2SAndroid Build Coastguard Worker   * Read lines from the PPD file and add them to the file record...
640*5e7646d2SAndroid Build Coastguard Worker   */
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker   group      = NULL;
643*5e7646d2SAndroid Build Coastguard Worker   subgroup   = NULL;
644*5e7646d2SAndroid Build Coastguard Worker   option     = NULL;
645*5e7646d2SAndroid Build Coastguard Worker   choice     = NULL;
646*5e7646d2SAndroid Build Coastguard Worker   ui_keyword = 0;
647*5e7646d2SAndroid Build Coastguard Worker   encoding   = CUPS_ISO8859_1;
648*5e7646d2SAndroid Build Coastguard Worker   loc        = localeconv();
649*5e7646d2SAndroid Build Coastguard Worker 
650*5e7646d2SAndroid Build Coastguard Worker   while ((mask = ppd_read(fp, &line, keyword, name, text, &string, 1, pg)) != 0)
651*5e7646d2SAndroid Build Coastguard Worker   {
652*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\", name=\"%s\", "
653*5e7646d2SAndroid Build Coastguard Worker                   "text=\"%s\", string=%d chars...", mask, keyword, name, text,
654*5e7646d2SAndroid Build Coastguard Worker 		  string ? (int)strlen(string) : 0));
655*5e7646d2SAndroid Build Coastguard Worker 
656*5e7646d2SAndroid Build Coastguard Worker     if (strncmp(keyword, "Default", 7) && !string &&
657*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_conform != PPD_CONFORM_RELAXED)
658*5e7646d2SAndroid Build Coastguard Worker     {
659*5e7646d2SAndroid Build Coastguard Worker      /*
660*5e7646d2SAndroid Build Coastguard Worker       * Need a string value!
661*5e7646d2SAndroid Build Coastguard Worker       */
662*5e7646d2SAndroid Build Coastguard Worker 
663*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_MISSING_VALUE;
664*5e7646d2SAndroid Build Coastguard Worker 
665*5e7646d2SAndroid Build Coastguard Worker       goto error;
666*5e7646d2SAndroid Build Coastguard Worker     }
667*5e7646d2SAndroid Build Coastguard Worker     else if (!string)
668*5e7646d2SAndroid Build Coastguard Worker       continue;
669*5e7646d2SAndroid Build Coastguard Worker 
670*5e7646d2SAndroid Build Coastguard Worker    /*
671*5e7646d2SAndroid Build Coastguard Worker     * Certain main keywords (as defined by the PPD spec) may be used
672*5e7646d2SAndroid Build Coastguard Worker     * without the usual OpenUI/CloseUI stuff.  Presumably this is just
673*5e7646d2SAndroid Build Coastguard Worker     * so that Adobe wouldn't completely break compatibility with PPD
674*5e7646d2SAndroid Build Coastguard Worker     * files prior to v4.0 of the spec, but it is hopelessly
675*5e7646d2SAndroid Build Coastguard Worker     * inconsistent...  Catch these main keywords and automatically
676*5e7646d2SAndroid Build Coastguard Worker     * create the corresponding option, as needed...
677*5e7646d2SAndroid Build Coastguard Worker     */
678*5e7646d2SAndroid Build Coastguard Worker 
679*5e7646d2SAndroid Build Coastguard Worker     if (ui_keyword)
680*5e7646d2SAndroid Build Coastguard Worker     {
681*5e7646d2SAndroid Build Coastguard Worker      /*
682*5e7646d2SAndroid Build Coastguard Worker       * Previous line was a UI keyword...
683*5e7646d2SAndroid Build Coastguard Worker       */
684*5e7646d2SAndroid Build Coastguard Worker 
685*5e7646d2SAndroid Build Coastguard Worker       option     = NULL;
686*5e7646d2SAndroid Build Coastguard Worker       ui_keyword = 0;
687*5e7646d2SAndroid Build Coastguard Worker     }
688*5e7646d2SAndroid Build Coastguard Worker 
689*5e7646d2SAndroid Build Coastguard Worker    /*
690*5e7646d2SAndroid Build Coastguard Worker     * If we are filtering out keyword localizations, see if this line needs to
691*5e7646d2SAndroid Build Coastguard Worker     * be used...
692*5e7646d2SAndroid Build Coastguard Worker     */
693*5e7646d2SAndroid Build Coastguard Worker 
694*5e7646d2SAndroid Build Coastguard Worker     if (localization != _PPD_LOCALIZATION_ALL &&
695*5e7646d2SAndroid Build Coastguard Worker         (temp = strchr(keyword, '.')) != NULL &&
696*5e7646d2SAndroid Build Coastguard Worker         ((temp - keyword) == 2 || (temp - keyword) == 5) &&
697*5e7646d2SAndroid Build Coastguard Worker         _cups_isalpha(keyword[0]) &&
698*5e7646d2SAndroid Build Coastguard Worker         _cups_isalpha(keyword[1]) &&
699*5e7646d2SAndroid Build Coastguard Worker         (keyword[2] == '.' ||
700*5e7646d2SAndroid Build Coastguard Worker          (keyword[2] == '_' && _cups_isalpha(keyword[3]) &&
701*5e7646d2SAndroid Build Coastguard Worker           _cups_isalpha(keyword[4]) && keyword[5] == '.')))
702*5e7646d2SAndroid Build Coastguard Worker     {
703*5e7646d2SAndroid Build Coastguard Worker       if (localization == _PPD_LOCALIZATION_NONE ||
704*5e7646d2SAndroid Build Coastguard Worker 	  (localization == _PPD_LOCALIZATION_DEFAULT &&
705*5e7646d2SAndroid Build Coastguard Worker 	   strncmp(ll_CC, keyword, ll_CC_len) &&
706*5e7646d2SAndroid Build Coastguard Worker 	   strncmp(ll, keyword, ll_len)))
707*5e7646d2SAndroid Build Coastguard Worker       {
708*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword));
709*5e7646d2SAndroid Build Coastguard Worker 	free(string);
710*5e7646d2SAndroid Build Coastguard Worker 	string = NULL;
711*5e7646d2SAndroid Build Coastguard Worker 	continue;
712*5e7646d2SAndroid Build Coastguard Worker       }
713*5e7646d2SAndroid Build Coastguard Worker       else if (localization == _PPD_LOCALIZATION_ICC_PROFILES)
714*5e7646d2SAndroid Build Coastguard Worker       {
715*5e7646d2SAndroid Build Coastguard Worker        /*
716*5e7646d2SAndroid Build Coastguard Worker         * Only load localizations for the color profile related keywords...
717*5e7646d2SAndroid Build Coastguard Worker         */
718*5e7646d2SAndroid Build Coastguard Worker 
719*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0;
720*5e7646d2SAndroid Build Coastguard Worker 	     i < (int)(sizeof(color_keywords) / sizeof(color_keywords[0]));
721*5e7646d2SAndroid Build Coastguard Worker 	     i ++)
722*5e7646d2SAndroid Build Coastguard Worker 	{
723*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strcasecmp(temp, color_keywords[i]))
724*5e7646d2SAndroid Build Coastguard Worker 	    break;
725*5e7646d2SAndroid Build Coastguard Worker 	}
726*5e7646d2SAndroid Build Coastguard Worker 
727*5e7646d2SAndroid Build Coastguard Worker 	if (i >= (int)(sizeof(color_keywords) / sizeof(color_keywords[0])))
728*5e7646d2SAndroid Build Coastguard Worker 	{
729*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword));
730*5e7646d2SAndroid Build Coastguard Worker 	  free(string);
731*5e7646d2SAndroid Build Coastguard Worker 	  string = NULL;
732*5e7646d2SAndroid Build Coastguard Worker 	  continue;
733*5e7646d2SAndroid Build Coastguard Worker 	}
734*5e7646d2SAndroid Build Coastguard Worker       }
735*5e7646d2SAndroid Build Coastguard Worker     }
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker     if (option == NULL &&
738*5e7646d2SAndroid Build Coastguard Worker         (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
739*5e7646d2SAndroid Build Coastguard Worker 	    (PPD_KEYWORD | PPD_OPTION | PPD_STRING))
740*5e7646d2SAndroid Build Coastguard Worker     {
741*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < (int)(sizeof(ui_keywords) / sizeof(ui_keywords[0])); i ++)
742*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(keyword, ui_keywords[i]))
743*5e7646d2SAndroid Build Coastguard Worker 	  break;
744*5e7646d2SAndroid Build Coastguard Worker 
745*5e7646d2SAndroid Build Coastguard Worker       if (i < (int)(sizeof(ui_keywords) / sizeof(ui_keywords[0])))
746*5e7646d2SAndroid Build Coastguard Worker       {
747*5e7646d2SAndroid Build Coastguard Worker        /*
748*5e7646d2SAndroid Build Coastguard Worker         * Create the option in the appropriate group...
749*5e7646d2SAndroid Build Coastguard Worker 	*/
750*5e7646d2SAndroid Build Coastguard Worker 
751*5e7646d2SAndroid Build Coastguard Worker         ui_keyword = 1;
752*5e7646d2SAndroid Build Coastguard Worker 
753*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("2_ppdOpen: FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!",
754*5e7646d2SAndroid Build Coastguard Worker 	              keyword));
755*5e7646d2SAndroid Build Coastguard Worker 
756*5e7646d2SAndroid Build Coastguard Worker         if (!group)
757*5e7646d2SAndroid Build Coastguard Worker 	{
758*5e7646d2SAndroid Build Coastguard Worker           if ((group = ppd_get_group(ppd, "General", _("General"), pg,
759*5e7646d2SAndroid Build Coastguard Worker 	                             encoding)) == NULL)
760*5e7646d2SAndroid Build Coastguard Worker 	    goto error;
761*5e7646d2SAndroid Build Coastguard Worker 
762*5e7646d2SAndroid Build Coastguard Worker           DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text));
763*5e7646d2SAndroid Build Coastguard Worker           option = ppd_get_option(group, keyword);
764*5e7646d2SAndroid Build Coastguard Worker 	  group  = NULL;
765*5e7646d2SAndroid Build Coastguard Worker 	}
766*5e7646d2SAndroid Build Coastguard Worker 	else
767*5e7646d2SAndroid Build Coastguard Worker           option = ppd_get_option(group, keyword);
768*5e7646d2SAndroid Build Coastguard Worker 
769*5e7646d2SAndroid Build Coastguard Worker 	if (option == NULL)
770*5e7646d2SAndroid Build Coastguard Worker 	{
771*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_ALLOC_ERROR;
772*5e7646d2SAndroid Build Coastguard Worker 
773*5e7646d2SAndroid Build Coastguard Worker           goto error;
774*5e7646d2SAndroid Build Coastguard Worker 	}
775*5e7646d2SAndroid Build Coastguard Worker 
776*5e7646d2SAndroid Build Coastguard Worker        /*
777*5e7646d2SAndroid Build Coastguard Worker 	* Now fill in the initial information for the option...
778*5e7646d2SAndroid Build Coastguard Worker 	*/
779*5e7646d2SAndroid Build Coastguard Worker 
780*5e7646d2SAndroid Build Coastguard Worker 	if (!strncmp(keyword, "JCL", 3))
781*5e7646d2SAndroid Build Coastguard Worker           option->section = PPD_ORDER_JCL;
782*5e7646d2SAndroid Build Coastguard Worker 	else
783*5e7646d2SAndroid Build Coastguard Worker           option->section = PPD_ORDER_ANY;
784*5e7646d2SAndroid Build Coastguard Worker 
785*5e7646d2SAndroid Build Coastguard Worker 	option->order = 10.0f;
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker 	if (i < 8)
788*5e7646d2SAndroid Build Coastguard Worker           option->ui = PPD_UI_BOOLEAN;
789*5e7646d2SAndroid Build Coastguard Worker 	else
790*5e7646d2SAndroid Build Coastguard Worker           option->ui = PPD_UI_PICKONE;
791*5e7646d2SAndroid Build Coastguard Worker 
792*5e7646d2SAndroid Build Coastguard Worker         for (j = 0; j < ppd->num_attrs; j ++)
793*5e7646d2SAndroid Build Coastguard Worker 	  if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
794*5e7646d2SAndroid Build Coastguard Worker 	      !strcmp(ppd->attrs[j]->name + 7, keyword) &&
795*5e7646d2SAndroid Build Coastguard Worker 	      ppd->attrs[j]->value)
796*5e7646d2SAndroid Build Coastguard Worker 	  {
797*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...",
798*5e7646d2SAndroid Build Coastguard Worker 	                  option->keyword, ppd->attrs[j]->value));
799*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(option->defchoice, ppd->attrs[j]->value,
800*5e7646d2SAndroid Build Coastguard Worker 	            sizeof(option->defchoice));
801*5e7646d2SAndroid Build Coastguard Worker 	    break;
802*5e7646d2SAndroid Build Coastguard Worker 	  }
803*5e7646d2SAndroid Build Coastguard Worker 
804*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(keyword, "PageSize"))
805*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Media Size"), sizeof(option->text));
806*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(keyword, "MediaType"))
807*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Media Type"), sizeof(option->text));
808*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(keyword, "InputSlot"))
809*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Media Source"), sizeof(option->text));
810*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(keyword, "ColorModel"))
811*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Output Mode"), sizeof(option->text));
812*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(keyword, "Resolution"))
813*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Resolution"), sizeof(option->text));
814*5e7646d2SAndroid Build Coastguard Worker         else
815*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, keyword, sizeof(option->text));
816*5e7646d2SAndroid Build Coastguard Worker       }
817*5e7646d2SAndroid Build Coastguard Worker     }
818*5e7646d2SAndroid Build Coastguard Worker 
819*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(keyword, "LanguageLevel"))
820*5e7646d2SAndroid Build Coastguard Worker       ppd->language_level = atoi(string);
821*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "LanguageEncoding"))
822*5e7646d2SAndroid Build Coastguard Worker     {
823*5e7646d2SAndroid Build Coastguard Worker      /*
824*5e7646d2SAndroid Build Coastguard Worker       * Say all PPD files are UTF-8, since we convert to UTF-8...
825*5e7646d2SAndroid Build Coastguard Worker       */
826*5e7646d2SAndroid Build Coastguard Worker 
827*5e7646d2SAndroid Build Coastguard Worker       ppd->lang_encoding = strdup("UTF-8");
828*5e7646d2SAndroid Build Coastguard Worker       encoding           = _ppdGetEncoding(string);
829*5e7646d2SAndroid Build Coastguard Worker     }
830*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "LanguageVersion"))
831*5e7646d2SAndroid Build Coastguard Worker       ppd->lang_version = string;
832*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "Manufacturer"))
833*5e7646d2SAndroid Build Coastguard Worker       ppd->manufacturer = string;
834*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "ModelName"))
835*5e7646d2SAndroid Build Coastguard Worker       ppd->modelname = string;
836*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "Protocols"))
837*5e7646d2SAndroid Build Coastguard Worker       ppd->protocols = string;
838*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "PCFileName"))
839*5e7646d2SAndroid Build Coastguard Worker       ppd->pcfilename = string;
840*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "NickName"))
841*5e7646d2SAndroid Build Coastguard Worker     {
842*5e7646d2SAndroid Build Coastguard Worker       if (encoding != CUPS_UTF8)
843*5e7646d2SAndroid Build Coastguard Worker       {
844*5e7646d2SAndroid Build Coastguard Worker         cups_utf8_t	utf8[256];	/* UTF-8 version of NickName */
845*5e7646d2SAndroid Build Coastguard Worker 
846*5e7646d2SAndroid Build Coastguard Worker 
847*5e7646d2SAndroid Build Coastguard Worker         cupsCharsetToUTF8(utf8, string, sizeof(utf8), encoding);
848*5e7646d2SAndroid Build Coastguard Worker 	ppd->nickname = strdup((char *)utf8);
849*5e7646d2SAndroid Build Coastguard Worker       }
850*5e7646d2SAndroid Build Coastguard Worker       else
851*5e7646d2SAndroid Build Coastguard Worker         ppd->nickname = strdup(string);
852*5e7646d2SAndroid Build Coastguard Worker     }
853*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "Product"))
854*5e7646d2SAndroid Build Coastguard Worker       ppd->product = string;
855*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "ShortNickName"))
856*5e7646d2SAndroid Build Coastguard Worker       ppd->shortnickname = string;
857*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "TTRasterizer"))
858*5e7646d2SAndroid Build Coastguard Worker       ppd->ttrasterizer = string;
859*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "JCLBegin"))
860*5e7646d2SAndroid Build Coastguard Worker     {
861*5e7646d2SAndroid Build Coastguard Worker       ppd->jcl_begin = strdup(string);
862*5e7646d2SAndroid Build Coastguard Worker       ppd_decode(ppd->jcl_begin);	/* Decode quoted string */
863*5e7646d2SAndroid Build Coastguard Worker     }
864*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "JCLEnd"))
865*5e7646d2SAndroid Build Coastguard Worker     {
866*5e7646d2SAndroid Build Coastguard Worker       ppd->jcl_end = strdup(string);
867*5e7646d2SAndroid Build Coastguard Worker       ppd_decode(ppd->jcl_end);		/* Decode quoted string */
868*5e7646d2SAndroid Build Coastguard Worker     }
869*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "JCLToPSInterpreter"))
870*5e7646d2SAndroid Build Coastguard Worker     {
871*5e7646d2SAndroid Build Coastguard Worker       ppd->jcl_ps = strdup(string);
872*5e7646d2SAndroid Build Coastguard Worker       ppd_decode(ppd->jcl_ps);		/* Decode quoted string */
873*5e7646d2SAndroid Build Coastguard Worker     }
874*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "AccurateScreensSupport"))
875*5e7646d2SAndroid Build Coastguard Worker       ppd->accurate_screens = !strcasecmp(string, "True");
876*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "ColorDevice"))
877*5e7646d2SAndroid Build Coastguard Worker       ppd->color_device = !strcasecmp(string, "True");
878*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "ContoneOnly"))
879*5e7646d2SAndroid Build Coastguard Worker       ppd->contone_only = !strcasecmp(string, "True");
880*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "cupsFlipDuplex"))
881*5e7646d2SAndroid Build Coastguard Worker       ppd->flip_duplex = !strcasecmp(string, "True");
882*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "cupsManualCopies"))
883*5e7646d2SAndroid Build Coastguard Worker       ppd->manual_copies = !strcasecmp(string, "True");
884*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "cupsModelNumber"))
885*5e7646d2SAndroid Build Coastguard Worker       ppd->model_number = atoi(string);
886*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "cupsColorProfile"))
887*5e7646d2SAndroid Build Coastguard Worker     {
888*5e7646d2SAndroid Build Coastguard Worker       if (ppd->num_profiles == 0)
889*5e7646d2SAndroid Build Coastguard Worker         profile = malloc(sizeof(ppd_profile_t));
890*5e7646d2SAndroid Build Coastguard Worker       else
891*5e7646d2SAndroid Build Coastguard Worker         profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * (size_t)(ppd->num_profiles + 1));
892*5e7646d2SAndroid Build Coastguard Worker 
893*5e7646d2SAndroid Build Coastguard Worker       if (!profile)
894*5e7646d2SAndroid Build Coastguard Worker       {
895*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
896*5e7646d2SAndroid Build Coastguard Worker 
897*5e7646d2SAndroid Build Coastguard Worker 	goto error;
898*5e7646d2SAndroid Build Coastguard Worker       }
899*5e7646d2SAndroid Build Coastguard Worker 
900*5e7646d2SAndroid Build Coastguard Worker       ppd->profiles     = profile;
901*5e7646d2SAndroid Build Coastguard Worker       profile           += ppd->num_profiles;
902*5e7646d2SAndroid Build Coastguard Worker       ppd->num_profiles ++;
903*5e7646d2SAndroid Build Coastguard Worker 
904*5e7646d2SAndroid Build Coastguard Worker       memset(profile, 0, sizeof(ppd_profile_t));
905*5e7646d2SAndroid Build Coastguard Worker       strlcpy(profile->resolution, name, sizeof(profile->resolution));
906*5e7646d2SAndroid Build Coastguard Worker       strlcpy(profile->media_type, text, sizeof(profile->media_type));
907*5e7646d2SAndroid Build Coastguard Worker 
908*5e7646d2SAndroid Build Coastguard Worker       profile->density      = (float)_cupsStrScand(string, &sptr, loc);
909*5e7646d2SAndroid Build Coastguard Worker       profile->gamma        = (float)_cupsStrScand(sptr, &sptr, loc);
910*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[0][0] = (float)_cupsStrScand(sptr, &sptr, loc);
911*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[0][1] = (float)_cupsStrScand(sptr, &sptr, loc);
912*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[0][2] = (float)_cupsStrScand(sptr, &sptr, loc);
913*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[1][0] = (float)_cupsStrScand(sptr, &sptr, loc);
914*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[1][1] = (float)_cupsStrScand(sptr, &sptr, loc);
915*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[1][2] = (float)_cupsStrScand(sptr, &sptr, loc);
916*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[2][0] = (float)_cupsStrScand(sptr, &sptr, loc);
917*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[2][1] = (float)_cupsStrScand(sptr, &sptr, loc);
918*5e7646d2SAndroid Build Coastguard Worker       profile->matrix[2][2] = (float)_cupsStrScand(sptr, &sptr, loc);
919*5e7646d2SAndroid Build Coastguard Worker     }
920*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "cupsFilter"))
921*5e7646d2SAndroid Build Coastguard Worker     {
922*5e7646d2SAndroid Build Coastguard Worker       if (ppd->num_filters == 0)
923*5e7646d2SAndroid Build Coastguard Worker         filter = malloc(sizeof(char *));
924*5e7646d2SAndroid Build Coastguard Worker       else
925*5e7646d2SAndroid Build Coastguard Worker         filter = realloc(ppd->filters, sizeof(char *) * (size_t)(ppd->num_filters + 1));
926*5e7646d2SAndroid Build Coastguard Worker 
927*5e7646d2SAndroid Build Coastguard Worker       if (filter == NULL)
928*5e7646d2SAndroid Build Coastguard Worker       {
929*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
930*5e7646d2SAndroid Build Coastguard Worker 
931*5e7646d2SAndroid Build Coastguard Worker 	goto error;
932*5e7646d2SAndroid Build Coastguard Worker       }
933*5e7646d2SAndroid Build Coastguard Worker 
934*5e7646d2SAndroid Build Coastguard Worker       ppd->filters     = filter;
935*5e7646d2SAndroid Build Coastguard Worker       filter           += ppd->num_filters;
936*5e7646d2SAndroid Build Coastguard Worker       ppd->num_filters ++;
937*5e7646d2SAndroid Build Coastguard Worker 
938*5e7646d2SAndroid Build Coastguard Worker      /*
939*5e7646d2SAndroid Build Coastguard Worker       * Make a copy of the filter string...
940*5e7646d2SAndroid Build Coastguard Worker       */
941*5e7646d2SAndroid Build Coastguard Worker 
942*5e7646d2SAndroid Build Coastguard Worker       *filter = strdup(string);
943*5e7646d2SAndroid Build Coastguard Worker     }
944*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "Throughput"))
945*5e7646d2SAndroid Build Coastguard Worker       ppd->throughput = atoi(string);
946*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "Font"))
947*5e7646d2SAndroid Build Coastguard Worker     {
948*5e7646d2SAndroid Build Coastguard Worker      /*
949*5e7646d2SAndroid Build Coastguard Worker       * Add this font to the list of available fonts...
950*5e7646d2SAndroid Build Coastguard Worker       */
951*5e7646d2SAndroid Build Coastguard Worker 
952*5e7646d2SAndroid Build Coastguard Worker       if (ppd->num_fonts == 0)
953*5e7646d2SAndroid Build Coastguard Worker         tempfonts = (char **)malloc(sizeof(char *));
954*5e7646d2SAndroid Build Coastguard Worker       else
955*5e7646d2SAndroid Build Coastguard Worker         tempfonts = (char **)realloc(ppd->fonts, sizeof(char *) * (size_t)(ppd->num_fonts + 1));
956*5e7646d2SAndroid Build Coastguard Worker 
957*5e7646d2SAndroid Build Coastguard Worker       if (tempfonts == NULL)
958*5e7646d2SAndroid Build Coastguard Worker       {
959*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
960*5e7646d2SAndroid Build Coastguard Worker 
961*5e7646d2SAndroid Build Coastguard Worker 	goto error;
962*5e7646d2SAndroid Build Coastguard Worker       }
963*5e7646d2SAndroid Build Coastguard Worker 
964*5e7646d2SAndroid Build Coastguard Worker       ppd->fonts                 = tempfonts;
965*5e7646d2SAndroid Build Coastguard Worker       ppd->fonts[ppd->num_fonts] = strdup(name);
966*5e7646d2SAndroid Build Coastguard Worker       ppd->num_fonts ++;
967*5e7646d2SAndroid Build Coastguard Worker     }
968*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(keyword, "ParamCustom", 11))
969*5e7646d2SAndroid Build Coastguard Worker     {
970*5e7646d2SAndroid Build Coastguard Worker       ppd_coption_t	*coption;	/* Custom option */
971*5e7646d2SAndroid Build Coastguard Worker       ppd_cparam_t	*cparam;	/* Custom parameter */
972*5e7646d2SAndroid Build Coastguard Worker       int		corder;		/* Order number */
973*5e7646d2SAndroid Build Coastguard Worker       char		ctype[33],	/* Data type */
974*5e7646d2SAndroid Build Coastguard Worker 			cminimum[65],	/* Minimum value */
975*5e7646d2SAndroid Build Coastguard Worker 			cmaximum[65];	/* Maximum value */
976*5e7646d2SAndroid Build Coastguard Worker 
977*5e7646d2SAndroid Build Coastguard Worker 
978*5e7646d2SAndroid Build Coastguard Worker      /*
979*5e7646d2SAndroid Build Coastguard Worker       * Get the custom option and parameter...
980*5e7646d2SAndroid Build Coastguard Worker       */
981*5e7646d2SAndroid Build Coastguard Worker 
982*5e7646d2SAndroid Build Coastguard Worker       if ((coption = ppd_get_coption(ppd, keyword + 11)) == NULL)
983*5e7646d2SAndroid Build Coastguard Worker       {
984*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
985*5e7646d2SAndroid Build Coastguard Worker 
986*5e7646d2SAndroid Build Coastguard Worker 	goto error;
987*5e7646d2SAndroid Build Coastguard Worker       }
988*5e7646d2SAndroid Build Coastguard Worker 
989*5e7646d2SAndroid Build Coastguard Worker       if ((cparam = ppd_get_cparam(coption, name, text)) == NULL)
990*5e7646d2SAndroid Build Coastguard Worker       {
991*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
992*5e7646d2SAndroid Build Coastguard Worker 
993*5e7646d2SAndroid Build Coastguard Worker 	goto error;
994*5e7646d2SAndroid Build Coastguard Worker       }
995*5e7646d2SAndroid Build Coastguard Worker 
996*5e7646d2SAndroid Build Coastguard Worker       if (cparam->type != PPD_CUSTOM_UNKNOWN)
997*5e7646d2SAndroid Build Coastguard Worker       {
998*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
999*5e7646d2SAndroid Build Coastguard Worker 
1000*5e7646d2SAndroid Build Coastguard Worker         goto error;
1001*5e7646d2SAndroid Build Coastguard Worker       }
1002*5e7646d2SAndroid Build Coastguard Worker 
1003*5e7646d2SAndroid Build Coastguard Worker      /*
1004*5e7646d2SAndroid Build Coastguard Worker       * Get the parameter data...
1005*5e7646d2SAndroid Build Coastguard Worker       */
1006*5e7646d2SAndroid Build Coastguard Worker 
1007*5e7646d2SAndroid Build Coastguard Worker       if (!string ||
1008*5e7646d2SAndroid Build Coastguard Worker           sscanf(string, "%d%32s%64s%64s", &corder, ctype, cminimum,
1009*5e7646d2SAndroid Build Coastguard Worker                  cmaximum) != 4)
1010*5e7646d2SAndroid Build Coastguard Worker       {
1011*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
1012*5e7646d2SAndroid Build Coastguard Worker 
1013*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1014*5e7646d2SAndroid Build Coastguard Worker       }
1015*5e7646d2SAndroid Build Coastguard Worker 
1016*5e7646d2SAndroid Build Coastguard Worker       cparam->order = corder;
1017*5e7646d2SAndroid Build Coastguard Worker 
1018*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(ctype, "curve"))
1019*5e7646d2SAndroid Build Coastguard Worker       {
1020*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_CURVE;
1021*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_curve = (float)_cupsStrScand(cminimum, NULL, loc);
1022*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_curve = (float)_cupsStrScand(cmaximum, NULL, loc);
1023*5e7646d2SAndroid Build Coastguard Worker       }
1024*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "int"))
1025*5e7646d2SAndroid Build Coastguard Worker       {
1026*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_INT;
1027*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_int = atoi(cminimum);
1028*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_int = atoi(cmaximum);
1029*5e7646d2SAndroid Build Coastguard Worker       }
1030*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "invcurve"))
1031*5e7646d2SAndroid Build Coastguard Worker       {
1032*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_INVCURVE;
1033*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_invcurve = (float)_cupsStrScand(cminimum, NULL, loc);
1034*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_invcurve = (float)_cupsStrScand(cmaximum, NULL, loc);
1035*5e7646d2SAndroid Build Coastguard Worker       }
1036*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "passcode"))
1037*5e7646d2SAndroid Build Coastguard Worker       {
1038*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_PASSCODE;
1039*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_passcode = atoi(cminimum);
1040*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_passcode = atoi(cmaximum);
1041*5e7646d2SAndroid Build Coastguard Worker       }
1042*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "password"))
1043*5e7646d2SAndroid Build Coastguard Worker       {
1044*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_PASSWORD;
1045*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_password = atoi(cminimum);
1046*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_password = atoi(cmaximum);
1047*5e7646d2SAndroid Build Coastguard Worker       }
1048*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "points"))
1049*5e7646d2SAndroid Build Coastguard Worker       {
1050*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_POINTS;
1051*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_points = (float)_cupsStrScand(cminimum, NULL, loc);
1052*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_points = (float)_cupsStrScand(cmaximum, NULL, loc);
1053*5e7646d2SAndroid Build Coastguard Worker       }
1054*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "real"))
1055*5e7646d2SAndroid Build Coastguard Worker       {
1056*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_REAL;
1057*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_real = (float)_cupsStrScand(cminimum, NULL, loc);
1058*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_real = (float)_cupsStrScand(cmaximum, NULL, loc);
1059*5e7646d2SAndroid Build Coastguard Worker       }
1060*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ctype, "string"))
1061*5e7646d2SAndroid Build Coastguard Worker       {
1062*5e7646d2SAndroid Build Coastguard Worker         cparam->type = PPD_CUSTOM_STRING;
1063*5e7646d2SAndroid Build Coastguard Worker 	cparam->minimum.custom_string = atoi(cminimum);
1064*5e7646d2SAndroid Build Coastguard Worker 	cparam->maximum.custom_string = atoi(cmaximum);
1065*5e7646d2SAndroid Build Coastguard Worker       }
1066*5e7646d2SAndroid Build Coastguard Worker       else
1067*5e7646d2SAndroid Build Coastguard Worker       {
1068*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
1069*5e7646d2SAndroid Build Coastguard Worker 
1070*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1071*5e7646d2SAndroid Build Coastguard Worker       }
1072*5e7646d2SAndroid Build Coastguard Worker 
1073*5e7646d2SAndroid Build Coastguard Worker      /*
1074*5e7646d2SAndroid Build Coastguard Worker       * Now special-case for CustomPageSize...
1075*5e7646d2SAndroid Build Coastguard Worker       */
1076*5e7646d2SAndroid Build Coastguard Worker 
1077*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(coption->keyword, "PageSize"))
1078*5e7646d2SAndroid Build Coastguard Worker       {
1079*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(name, "Width"))
1080*5e7646d2SAndroid Build Coastguard Worker 	{
1081*5e7646d2SAndroid Build Coastguard Worker 	  ppd->custom_min[0] = cparam->minimum.custom_points;
1082*5e7646d2SAndroid Build Coastguard Worker 	  ppd->custom_max[0] = cparam->maximum.custom_points;
1083*5e7646d2SAndroid Build Coastguard Worker 	}
1084*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(name, "Height"))
1085*5e7646d2SAndroid Build Coastguard Worker 	{
1086*5e7646d2SAndroid Build Coastguard Worker 	  ppd->custom_min[1] = cparam->minimum.custom_points;
1087*5e7646d2SAndroid Build Coastguard Worker 	  ppd->custom_max[1] = cparam->maximum.custom_points;
1088*5e7646d2SAndroid Build Coastguard Worker 	}
1089*5e7646d2SAndroid Build Coastguard Worker       }
1090*5e7646d2SAndroid Build Coastguard Worker     }
1091*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "HWMargins"))
1092*5e7646d2SAndroid Build Coastguard Worker     {
1093*5e7646d2SAndroid Build Coastguard Worker       for (i = 0, sptr = string; i < 4; i ++)
1094*5e7646d2SAndroid Build Coastguard Worker         ppd->custom_margins[i] = (float)_cupsStrScand(sptr, &sptr, loc);
1095*5e7646d2SAndroid Build Coastguard Worker     }
1096*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(keyword, "Custom", 6) && !strcmp(name, "True") && !option)
1097*5e7646d2SAndroid Build Coastguard Worker     {
1098*5e7646d2SAndroid Build Coastguard Worker       ppd_option_t	*custom_option;	/* Custom option */
1099*5e7646d2SAndroid Build Coastguard Worker 
1100*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("2_ppdOpen: Processing Custom option...");
1101*5e7646d2SAndroid Build Coastguard Worker 
1102*5e7646d2SAndroid Build Coastguard Worker      /*
1103*5e7646d2SAndroid Build Coastguard Worker       * Get the option and custom option...
1104*5e7646d2SAndroid Build Coastguard Worker       */
1105*5e7646d2SAndroid Build Coastguard Worker 
1106*5e7646d2SAndroid Build Coastguard Worker       if (!ppd_get_coption(ppd, keyword + 6))
1107*5e7646d2SAndroid Build Coastguard Worker       {
1108*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
1109*5e7646d2SAndroid Build Coastguard Worker 
1110*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1111*5e7646d2SAndroid Build Coastguard Worker       }
1112*5e7646d2SAndroid Build Coastguard Worker 
1113*5e7646d2SAndroid Build Coastguard Worker       if (option && !_cups_strcasecmp(option->keyword, keyword + 6))
1114*5e7646d2SAndroid Build Coastguard Worker         custom_option = option;
1115*5e7646d2SAndroid Build Coastguard Worker       else
1116*5e7646d2SAndroid Build Coastguard Worker         custom_option = ppdFindOption(ppd, keyword + 6);
1117*5e7646d2SAndroid Build Coastguard Worker 
1118*5e7646d2SAndroid Build Coastguard Worker       if (custom_option)
1119*5e7646d2SAndroid Build Coastguard Worker       {
1120*5e7646d2SAndroid Build Coastguard Worker        /*
1121*5e7646d2SAndroid Build Coastguard Worker 	* Add the "custom" option...
1122*5e7646d2SAndroid Build Coastguard Worker 	*/
1123*5e7646d2SAndroid Build Coastguard Worker 
1124*5e7646d2SAndroid Build Coastguard Worker         if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
1125*5e7646d2SAndroid Build Coastguard Worker 	  if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
1126*5e7646d2SAndroid Build Coastguard Worker 	  {
1127*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1128*5e7646d2SAndroid Build Coastguard Worker 
1129*5e7646d2SAndroid Build Coastguard Worker 	    pg->ppd_status = PPD_ALLOC_ERROR;
1130*5e7646d2SAndroid Build Coastguard Worker 
1131*5e7646d2SAndroid Build Coastguard Worker 	    goto error;
1132*5e7646d2SAndroid Build Coastguard Worker 	  }
1133*5e7646d2SAndroid Build Coastguard Worker 
1134*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(choice->text, text[0] ? text : _("Custom"),
1135*5e7646d2SAndroid Build Coastguard Worker 		sizeof(choice->text));
1136*5e7646d2SAndroid Build Coastguard Worker 
1137*5e7646d2SAndroid Build Coastguard Worker 	choice->code = strdup(string);
1138*5e7646d2SAndroid Build Coastguard Worker 
1139*5e7646d2SAndroid Build Coastguard Worker 	if (custom_option->section == PPD_ORDER_JCL)
1140*5e7646d2SAndroid Build Coastguard Worker 	  ppd_decode(choice->code);
1141*5e7646d2SAndroid Build Coastguard Worker       }
1142*5e7646d2SAndroid Build Coastguard Worker 
1143*5e7646d2SAndroid Build Coastguard Worker      /*
1144*5e7646d2SAndroid Build Coastguard Worker       * Now process custom page sizes specially...
1145*5e7646d2SAndroid Build Coastguard Worker       */
1146*5e7646d2SAndroid Build Coastguard Worker 
1147*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(keyword, "CustomPageSize"))
1148*5e7646d2SAndroid Build Coastguard Worker       {
1149*5e7646d2SAndroid Build Coastguard Worker        /*
1150*5e7646d2SAndroid Build Coastguard Worker 	* Add a "Custom" page size entry...
1151*5e7646d2SAndroid Build Coastguard Worker 	*/
1152*5e7646d2SAndroid Build Coastguard Worker 
1153*5e7646d2SAndroid Build Coastguard Worker 	ppd->variable_sizes = 1;
1154*5e7646d2SAndroid Build Coastguard Worker 
1155*5e7646d2SAndroid Build Coastguard Worker 	ppd_add_size(ppd, "Custom");
1156*5e7646d2SAndroid Build Coastguard Worker 
1157*5e7646d2SAndroid Build Coastguard Worker 	if (option && !_cups_strcasecmp(option->keyword, "PageRegion"))
1158*5e7646d2SAndroid Build Coastguard Worker 	  custom_option = option;
1159*5e7646d2SAndroid Build Coastguard Worker 	else
1160*5e7646d2SAndroid Build Coastguard Worker 	  custom_option = ppdFindOption(ppd, "PageRegion");
1161*5e7646d2SAndroid Build Coastguard Worker 
1162*5e7646d2SAndroid Build Coastguard Worker         if (custom_option)
1163*5e7646d2SAndroid Build Coastguard Worker 	{
1164*5e7646d2SAndroid Build Coastguard Worker 	  if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
1165*5e7646d2SAndroid Build Coastguard Worker 	    if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
1166*5e7646d2SAndroid Build Coastguard Worker 	    {
1167*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1168*5e7646d2SAndroid Build Coastguard Worker 
1169*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_ALLOC_ERROR;
1170*5e7646d2SAndroid Build Coastguard Worker 
1171*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1172*5e7646d2SAndroid Build Coastguard Worker 	    }
1173*5e7646d2SAndroid Build Coastguard Worker 
1174*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(choice->text, text[0] ? text : _("Custom"),
1175*5e7646d2SAndroid Build Coastguard Worker 		  sizeof(choice->text));
1176*5e7646d2SAndroid Build Coastguard Worker         }
1177*5e7646d2SAndroid Build Coastguard Worker       }
1178*5e7646d2SAndroid Build Coastguard Worker     }
1179*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "LandscapeOrientation"))
1180*5e7646d2SAndroid Build Coastguard Worker     {
1181*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(string, "Minus90"))
1182*5e7646d2SAndroid Build Coastguard Worker         ppd->landscape = -90;
1183*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(string, "Plus90"))
1184*5e7646d2SAndroid Build Coastguard Worker         ppd->landscape = 90;
1185*5e7646d2SAndroid Build Coastguard Worker     }
1186*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0)
1187*5e7646d2SAndroid Build Coastguard Worker     {
1188*5e7646d2SAndroid Build Coastguard Worker      /*
1189*5e7646d2SAndroid Build Coastguard Worker       * Issue #5562: Samsung printer drivers incorrectly use Emulators keyword
1190*5e7646d2SAndroid Build Coastguard Worker       *              to configure themselves
1191*5e7646d2SAndroid Build Coastguard Worker       *
1192*5e7646d2SAndroid Build Coastguard Worker       * The Emulators keyword was loaded but never used by anything in CUPS,
1193*5e7646d2SAndroid Build Coastguard Worker       * and has no valid purpose in CUPS.  The old code was removed due to a
1194*5e7646d2SAndroid Build Coastguard Worker       * memory leak (Issue #5475), so the following (new) code supports a single
1195*5e7646d2SAndroid Build Coastguard Worker       * name for the Emulators keyword, allowing these drivers to work until we
1196*5e7646d2SAndroid Build Coastguard Worker       * remove PPD and driver support entirely in a future version of CUPS.
1197*5e7646d2SAndroid Build Coastguard Worker       */
1198*5e7646d2SAndroid Build Coastguard Worker 
1199*5e7646d2SAndroid Build Coastguard Worker       ppd->num_emulations = 1;
1200*5e7646d2SAndroid Build Coastguard Worker       ppd->emulations     = calloc(1, sizeof(ppd_emul_t));
1201*5e7646d2SAndroid Build Coastguard Worker 
1202*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ppd->emulations[0].name, string, sizeof(ppd->emulations[0].name));
1203*5e7646d2SAndroid Build Coastguard Worker     }
1204*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "JobPatchFile"))
1205*5e7646d2SAndroid Build Coastguard Worker     {
1206*5e7646d2SAndroid Build Coastguard Worker      /*
1207*5e7646d2SAndroid Build Coastguard Worker       * CUPS STR #3421: Check for "*JobPatchFile: int: string"
1208*5e7646d2SAndroid Build Coastguard Worker       */
1209*5e7646d2SAndroid Build Coastguard Worker 
1210*5e7646d2SAndroid Build Coastguard Worker       if (isdigit(*string & 255))
1211*5e7646d2SAndroid Build Coastguard Worker       {
1212*5e7646d2SAndroid Build Coastguard Worker         for (sptr = string + 1; isdigit(*sptr & 255); sptr ++);
1213*5e7646d2SAndroid Build Coastguard Worker 
1214*5e7646d2SAndroid Build Coastguard Worker         if (*sptr == ':')
1215*5e7646d2SAndroid Build Coastguard Worker         {
1216*5e7646d2SAndroid Build Coastguard Worker          /*
1217*5e7646d2SAndroid Build Coastguard Worker           * Found "*JobPatchFile: int: string"...
1218*5e7646d2SAndroid Build Coastguard Worker           */
1219*5e7646d2SAndroid Build Coastguard Worker 
1220*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_BAD_VALUE;
1221*5e7646d2SAndroid Build Coastguard Worker 
1222*5e7646d2SAndroid Build Coastguard Worker 	  goto error;
1223*5e7646d2SAndroid Build Coastguard Worker         }
1224*5e7646d2SAndroid Build Coastguard Worker       }
1225*5e7646d2SAndroid Build Coastguard Worker 
1226*5e7646d2SAndroid Build Coastguard Worker       if (!name[0] && pg->ppd_conform == PPD_CONFORM_STRICT)
1227*5e7646d2SAndroid Build Coastguard Worker       {
1228*5e7646d2SAndroid Build Coastguard Worker        /*
1229*5e7646d2SAndroid Build Coastguard Worker         * Found "*JobPatchFile: string"...
1230*5e7646d2SAndroid Build Coastguard Worker         */
1231*5e7646d2SAndroid Build Coastguard Worker 
1232*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_MISSING_OPTION_KEYWORD;
1233*5e7646d2SAndroid Build Coastguard Worker 
1234*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1235*5e7646d2SAndroid Build Coastguard Worker       }
1236*5e7646d2SAndroid Build Coastguard Worker 
1237*5e7646d2SAndroid Build Coastguard Worker       if (ppd->patches == NULL)
1238*5e7646d2SAndroid Build Coastguard Worker         ppd->patches = strdup(string);
1239*5e7646d2SAndroid Build Coastguard Worker       else
1240*5e7646d2SAndroid Build Coastguard Worker       {
1241*5e7646d2SAndroid Build Coastguard Worker         temp = realloc(ppd->patches, strlen(ppd->patches) +
1242*5e7646d2SAndroid Build Coastguard Worker 	                             strlen(string) + 1);
1243*5e7646d2SAndroid Build Coastguard Worker         if (temp == NULL)
1244*5e7646d2SAndroid Build Coastguard Worker 	{
1245*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_ALLOC_ERROR;
1246*5e7646d2SAndroid Build Coastguard Worker 
1247*5e7646d2SAndroid Build Coastguard Worker 	  goto error;
1248*5e7646d2SAndroid Build Coastguard Worker 	}
1249*5e7646d2SAndroid Build Coastguard Worker 
1250*5e7646d2SAndroid Build Coastguard Worker         ppd->patches = temp;
1251*5e7646d2SAndroid Build Coastguard Worker 
1252*5e7646d2SAndroid Build Coastguard Worker         memcpy(ppd->patches + strlen(ppd->patches), string, strlen(string) + 1);
1253*5e7646d2SAndroid Build Coastguard Worker       }
1254*5e7646d2SAndroid Build Coastguard Worker     }
1255*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "OpenUI"))
1256*5e7646d2SAndroid Build Coastguard Worker     {
1257*5e7646d2SAndroid Build Coastguard Worker      /*
1258*5e7646d2SAndroid Build Coastguard Worker       * Don't allow nesting of options...
1259*5e7646d2SAndroid Build Coastguard Worker       */
1260*5e7646d2SAndroid Build Coastguard Worker 
1261*5e7646d2SAndroid Build Coastguard Worker       if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
1262*5e7646d2SAndroid Build Coastguard Worker       {
1263*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_NESTED_OPEN_UI;
1264*5e7646d2SAndroid Build Coastguard Worker 
1265*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1266*5e7646d2SAndroid Build Coastguard Worker       }
1267*5e7646d2SAndroid Build Coastguard Worker 
1268*5e7646d2SAndroid Build Coastguard Worker      /*
1269*5e7646d2SAndroid Build Coastguard Worker       * Add an option record to the current sub-group, group, or file...
1270*5e7646d2SAndroid Build Coastguard Worker       */
1271*5e7646d2SAndroid Build Coastguard Worker 
1272*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("2_ppdOpen: name=\"%s\" (%d)", name, (int)strlen(name)));
1273*5e7646d2SAndroid Build Coastguard Worker 
1274*5e7646d2SAndroid Build Coastguard Worker       if (name[0] == '*')
1275*5e7646d2SAndroid Build Coastguard Worker         _cups_strcpy(name, name + 1); /* Eliminate leading asterisk */
1276*5e7646d2SAndroid Build Coastguard Worker 
1277*5e7646d2SAndroid Build Coastguard Worker       for (i = (int)strlen(name) - 1; i > 0 && _cups_isspace(name[i]); i --)
1278*5e7646d2SAndroid Build Coastguard Worker         name[i] = '\0'; /* Eliminate trailing spaces */
1279*5e7646d2SAndroid Build Coastguard Worker 
1280*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("2_ppdOpen: OpenUI of %s in group %s...", name,
1281*5e7646d2SAndroid Build Coastguard Worker                     group ? group->text : "(null)"));
1282*5e7646d2SAndroid Build Coastguard Worker 
1283*5e7646d2SAndroid Build Coastguard Worker       if (subgroup != NULL)
1284*5e7646d2SAndroid Build Coastguard Worker         option = ppd_get_option(subgroup, name);
1285*5e7646d2SAndroid Build Coastguard Worker       else if (group == NULL)
1286*5e7646d2SAndroid Build Coastguard Worker       {
1287*5e7646d2SAndroid Build Coastguard Worker 	if ((group = ppd_get_group(ppd, "General", _("General"), pg,
1288*5e7646d2SAndroid Build Coastguard Worker 	                           encoding)) == NULL)
1289*5e7646d2SAndroid Build Coastguard Worker 	  goto error;
1290*5e7646d2SAndroid Build Coastguard Worker 
1291*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text));
1292*5e7646d2SAndroid Build Coastguard Worker         option = ppd_get_option(group, name);
1293*5e7646d2SAndroid Build Coastguard Worker 	group  = NULL;
1294*5e7646d2SAndroid Build Coastguard Worker       }
1295*5e7646d2SAndroid Build Coastguard Worker       else
1296*5e7646d2SAndroid Build Coastguard Worker         option = ppd_get_option(group, name);
1297*5e7646d2SAndroid Build Coastguard Worker 
1298*5e7646d2SAndroid Build Coastguard Worker       if (option == NULL)
1299*5e7646d2SAndroid Build Coastguard Worker       {
1300*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
1301*5e7646d2SAndroid Build Coastguard Worker 
1302*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1303*5e7646d2SAndroid Build Coastguard Worker       }
1304*5e7646d2SAndroid Build Coastguard Worker 
1305*5e7646d2SAndroid Build Coastguard Worker      /*
1306*5e7646d2SAndroid Build Coastguard Worker       * Now fill in the initial information for the option...
1307*5e7646d2SAndroid Build Coastguard Worker       */
1308*5e7646d2SAndroid Build Coastguard Worker 
1309*5e7646d2SAndroid Build Coastguard Worker       if (string && !strcmp(string, "PickMany"))
1310*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_PICKMANY;
1311*5e7646d2SAndroid Build Coastguard Worker       else if (string && !strcmp(string, "Boolean"))
1312*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_BOOLEAN;
1313*5e7646d2SAndroid Build Coastguard Worker       else if (string && !strcmp(string, "PickOne"))
1314*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_PICKONE;
1315*5e7646d2SAndroid Build Coastguard Worker       else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1316*5e7646d2SAndroid Build Coastguard Worker       {
1317*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_OPEN_UI;
1318*5e7646d2SAndroid Build Coastguard Worker 
1319*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1320*5e7646d2SAndroid Build Coastguard Worker       }
1321*5e7646d2SAndroid Build Coastguard Worker       else
1322*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_PICKONE;
1323*5e7646d2SAndroid Build Coastguard Worker 
1324*5e7646d2SAndroid Build Coastguard Worker       for (j = 0; j < ppd->num_attrs; j ++)
1325*5e7646d2SAndroid Build Coastguard Worker 	if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
1326*5e7646d2SAndroid Build Coastguard Worker 	    !strcmp(ppd->attrs[j]->name + 7, name) &&
1327*5e7646d2SAndroid Build Coastguard Worker 	    ppd->attrs[j]->value)
1328*5e7646d2SAndroid Build Coastguard Worker 	{
1329*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...",
1330*5e7646d2SAndroid Build Coastguard Worker 	                option->keyword, ppd->attrs[j]->value));
1331*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->defchoice, ppd->attrs[j]->value,
1332*5e7646d2SAndroid Build Coastguard Worker 	          sizeof(option->defchoice));
1333*5e7646d2SAndroid Build Coastguard Worker 	  break;
1334*5e7646d2SAndroid Build Coastguard Worker 	}
1335*5e7646d2SAndroid Build Coastguard Worker 
1336*5e7646d2SAndroid Build Coastguard Worker       if (text[0])
1337*5e7646d2SAndroid Build Coastguard Worker         cupsCharsetToUTF8((cups_utf8_t *)option->text, text,
1338*5e7646d2SAndroid Build Coastguard Worker 	                   sizeof(option->text), encoding);
1339*5e7646d2SAndroid Build Coastguard Worker       else
1340*5e7646d2SAndroid Build Coastguard Worker       {
1341*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(name, "PageSize"))
1342*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Media Size"), sizeof(option->text));
1343*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(name, "MediaType"))
1344*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Media Type"), sizeof(option->text));
1345*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(name, "InputSlot"))
1346*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Media Source"), sizeof(option->text));
1347*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(name, "ColorModel"))
1348*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Output Mode"), sizeof(option->text));
1349*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(name, "Resolution"))
1350*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, _("Resolution"), sizeof(option->text));
1351*5e7646d2SAndroid Build Coastguard Worker         else
1352*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->text, name, sizeof(option->text));
1353*5e7646d2SAndroid Build Coastguard Worker       }
1354*5e7646d2SAndroid Build Coastguard Worker 
1355*5e7646d2SAndroid Build Coastguard Worker       option->section = PPD_ORDER_ANY;
1356*5e7646d2SAndroid Build Coastguard Worker 
1357*5e7646d2SAndroid Build Coastguard Worker       free(string);
1358*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1359*5e7646d2SAndroid Build Coastguard Worker 
1360*5e7646d2SAndroid Build Coastguard Worker      /*
1361*5e7646d2SAndroid Build Coastguard Worker       * Add a custom option choice if we have already seen a CustomFoo
1362*5e7646d2SAndroid Build Coastguard Worker       * attribute...
1363*5e7646d2SAndroid Build Coastguard Worker       */
1364*5e7646d2SAndroid Build Coastguard Worker 
1365*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(name, "PageRegion"))
1366*5e7646d2SAndroid Build Coastguard Worker         strlcpy(custom_name, "CustomPageSize", sizeof(custom_name));
1367*5e7646d2SAndroid Build Coastguard Worker       else
1368*5e7646d2SAndroid Build Coastguard Worker         snprintf(custom_name, sizeof(custom_name), "Custom%s", name);
1369*5e7646d2SAndroid Build Coastguard Worker 
1370*5e7646d2SAndroid Build Coastguard Worker       if ((custom_attr = ppdFindAttr(ppd, custom_name, "True")) != NULL)
1371*5e7646d2SAndroid Build Coastguard Worker       {
1372*5e7646d2SAndroid Build Coastguard Worker         if ((choice = ppdFindChoice(option, "Custom")) == NULL)
1373*5e7646d2SAndroid Build Coastguard Worker 	  if ((choice = ppd_add_choice(option, "Custom")) == NULL)
1374*5e7646d2SAndroid Build Coastguard Worker 	  {
1375*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1376*5e7646d2SAndroid Build Coastguard Worker 
1377*5e7646d2SAndroid Build Coastguard Worker 	    pg->ppd_status = PPD_ALLOC_ERROR;
1378*5e7646d2SAndroid Build Coastguard Worker 
1379*5e7646d2SAndroid Build Coastguard Worker 	    goto error;
1380*5e7646d2SAndroid Build Coastguard Worker 	  }
1381*5e7646d2SAndroid Build Coastguard Worker 
1382*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(choice->text,
1383*5e7646d2SAndroid Build Coastguard Worker 	        custom_attr->text[0] ? custom_attr->text : _("Custom"),
1384*5e7646d2SAndroid Build Coastguard Worker 		sizeof(choice->text));
1385*5e7646d2SAndroid Build Coastguard Worker         choice->code = strdup(custom_attr->value);
1386*5e7646d2SAndroid Build Coastguard Worker       }
1387*5e7646d2SAndroid Build Coastguard Worker     }
1388*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "JCLOpenUI"))
1389*5e7646d2SAndroid Build Coastguard Worker     {
1390*5e7646d2SAndroid Build Coastguard Worker      /*
1391*5e7646d2SAndroid Build Coastguard Worker       * Don't allow nesting of options...
1392*5e7646d2SAndroid Build Coastguard Worker       */
1393*5e7646d2SAndroid Build Coastguard Worker 
1394*5e7646d2SAndroid Build Coastguard Worker       if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
1395*5e7646d2SAndroid Build Coastguard Worker       {
1396*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_NESTED_OPEN_UI;
1397*5e7646d2SAndroid Build Coastguard Worker 
1398*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1399*5e7646d2SAndroid Build Coastguard Worker       }
1400*5e7646d2SAndroid Build Coastguard Worker 
1401*5e7646d2SAndroid Build Coastguard Worker      /*
1402*5e7646d2SAndroid Build Coastguard Worker       * Find the JCL group, and add if needed...
1403*5e7646d2SAndroid Build Coastguard Worker       */
1404*5e7646d2SAndroid Build Coastguard Worker 
1405*5e7646d2SAndroid Build Coastguard Worker       group = ppd_get_group(ppd, "JCL", _("JCL"), pg, encoding);
1406*5e7646d2SAndroid Build Coastguard Worker 
1407*5e7646d2SAndroid Build Coastguard Worker       if (group == NULL)
1408*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1409*5e7646d2SAndroid Build Coastguard Worker 
1410*5e7646d2SAndroid Build Coastguard Worker      /*
1411*5e7646d2SAndroid Build Coastguard Worker       * Add an option record to the current JCLs...
1412*5e7646d2SAndroid Build Coastguard Worker       */
1413*5e7646d2SAndroid Build Coastguard Worker 
1414*5e7646d2SAndroid Build Coastguard Worker       if (name[0] == '*')
1415*5e7646d2SAndroid Build Coastguard Worker         _cups_strcpy(name, name + 1);
1416*5e7646d2SAndroid Build Coastguard Worker 
1417*5e7646d2SAndroid Build Coastguard Worker       option = ppd_get_option(group, name);
1418*5e7646d2SAndroid Build Coastguard Worker 
1419*5e7646d2SAndroid Build Coastguard Worker       if (option == NULL)
1420*5e7646d2SAndroid Build Coastguard Worker       {
1421*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
1422*5e7646d2SAndroid Build Coastguard Worker 
1423*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1424*5e7646d2SAndroid Build Coastguard Worker       }
1425*5e7646d2SAndroid Build Coastguard Worker 
1426*5e7646d2SAndroid Build Coastguard Worker      /*
1427*5e7646d2SAndroid Build Coastguard Worker       * Now fill in the initial information for the option...
1428*5e7646d2SAndroid Build Coastguard Worker       */
1429*5e7646d2SAndroid Build Coastguard Worker 
1430*5e7646d2SAndroid Build Coastguard Worker       if (string && !strcmp(string, "PickMany"))
1431*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_PICKMANY;
1432*5e7646d2SAndroid Build Coastguard Worker       else if (string && !strcmp(string, "Boolean"))
1433*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_BOOLEAN;
1434*5e7646d2SAndroid Build Coastguard Worker       else if (string && !strcmp(string, "PickOne"))
1435*5e7646d2SAndroid Build Coastguard Worker         option->ui = PPD_UI_PICKONE;
1436*5e7646d2SAndroid Build Coastguard Worker       else
1437*5e7646d2SAndroid Build Coastguard Worker       {
1438*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_OPEN_UI;
1439*5e7646d2SAndroid Build Coastguard Worker 
1440*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1441*5e7646d2SAndroid Build Coastguard Worker       }
1442*5e7646d2SAndroid Build Coastguard Worker 
1443*5e7646d2SAndroid Build Coastguard Worker       for (j = 0; j < ppd->num_attrs; j ++)
1444*5e7646d2SAndroid Build Coastguard Worker 	if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
1445*5e7646d2SAndroid Build Coastguard Worker 	    !strcmp(ppd->attrs[j]->name + 7, name) &&
1446*5e7646d2SAndroid Build Coastguard Worker 	    ppd->attrs[j]->value)
1447*5e7646d2SAndroid Build Coastguard Worker 	{
1448*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...",
1449*5e7646d2SAndroid Build Coastguard Worker 	                option->keyword, ppd->attrs[j]->value));
1450*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->defchoice, ppd->attrs[j]->value,
1451*5e7646d2SAndroid Build Coastguard Worker 	          sizeof(option->defchoice));
1452*5e7646d2SAndroid Build Coastguard Worker 	  break;
1453*5e7646d2SAndroid Build Coastguard Worker 	}
1454*5e7646d2SAndroid Build Coastguard Worker 
1455*5e7646d2SAndroid Build Coastguard Worker       if (text[0])
1456*5e7646d2SAndroid Build Coastguard Worker         cupsCharsetToUTF8((cups_utf8_t *)option->text, text,
1457*5e7646d2SAndroid Build Coastguard Worker 	                   sizeof(option->text), encoding);
1458*5e7646d2SAndroid Build Coastguard Worker       else
1459*5e7646d2SAndroid Build Coastguard Worker         strlcpy(option->text, name, sizeof(option->text));
1460*5e7646d2SAndroid Build Coastguard Worker 
1461*5e7646d2SAndroid Build Coastguard Worker       option->section = PPD_ORDER_JCL;
1462*5e7646d2SAndroid Build Coastguard Worker       group = NULL;
1463*5e7646d2SAndroid Build Coastguard Worker 
1464*5e7646d2SAndroid Build Coastguard Worker       free(string);
1465*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1466*5e7646d2SAndroid Build Coastguard Worker 
1467*5e7646d2SAndroid Build Coastguard Worker      /*
1468*5e7646d2SAndroid Build Coastguard Worker       * Add a custom option choice if we have already seen a CustomFoo
1469*5e7646d2SAndroid Build Coastguard Worker       * attribute...
1470*5e7646d2SAndroid Build Coastguard Worker       */
1471*5e7646d2SAndroid Build Coastguard Worker 
1472*5e7646d2SAndroid Build Coastguard Worker       snprintf(custom_name, sizeof(custom_name), "Custom%s", name);
1473*5e7646d2SAndroid Build Coastguard Worker 
1474*5e7646d2SAndroid Build Coastguard Worker       if ((custom_attr = ppdFindAttr(ppd, custom_name, "True")) != NULL)
1475*5e7646d2SAndroid Build Coastguard Worker       {
1476*5e7646d2SAndroid Build Coastguard Worker 	if ((choice = ppd_add_choice(option, "Custom")) == NULL)
1477*5e7646d2SAndroid Build Coastguard Worker 	{
1478*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1479*5e7646d2SAndroid Build Coastguard Worker 
1480*5e7646d2SAndroid Build Coastguard Worker 	  pg->ppd_status = PPD_ALLOC_ERROR;
1481*5e7646d2SAndroid Build Coastguard Worker 
1482*5e7646d2SAndroid Build Coastguard Worker 	  goto error;
1483*5e7646d2SAndroid Build Coastguard Worker 	}
1484*5e7646d2SAndroid Build Coastguard Worker 
1485*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(choice->text,
1486*5e7646d2SAndroid Build Coastguard Worker 	        custom_attr->text[0] ? custom_attr->text : _("Custom"),
1487*5e7646d2SAndroid Build Coastguard Worker 		sizeof(choice->text));
1488*5e7646d2SAndroid Build Coastguard Worker         choice->code = strdup(custom_attr->value);
1489*5e7646d2SAndroid Build Coastguard Worker       }
1490*5e7646d2SAndroid Build Coastguard Worker     }
1491*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "CloseUI"))
1492*5e7646d2SAndroid Build Coastguard Worker     {
1493*5e7646d2SAndroid Build Coastguard Worker       if ((!option || option->section == PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT)
1494*5e7646d2SAndroid Build Coastguard Worker       {
1495*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_CLOSE_UI;
1496*5e7646d2SAndroid Build Coastguard Worker 
1497*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1498*5e7646d2SAndroid Build Coastguard Worker       }
1499*5e7646d2SAndroid Build Coastguard Worker 
1500*5e7646d2SAndroid Build Coastguard Worker       if (option && (!_cups_strcasecmp(option->defchoice, "custom") || !_cups_strncasecmp(option->defchoice, "custom.", 7)))
1501*5e7646d2SAndroid Build Coastguard Worker       {
1502*5e7646d2SAndroid Build Coastguard Worker        /*
1503*5e7646d2SAndroid Build Coastguard Worker 	* "*DefaultOption: Custom..." may set the default to a custom value
1504*5e7646d2SAndroid Build Coastguard Worker 	* or (for a very small number of incompatible PPD files) select a
1505*5e7646d2SAndroid Build Coastguard Worker 	* standard choice for the option, which CUPS renames to "_Custom..."
1506*5e7646d2SAndroid Build Coastguard Worker 	* to avoid compatibility issues.  See which this is...
1507*5e7646d2SAndroid Build Coastguard Worker 	*/
1508*5e7646d2SAndroid Build Coastguard Worker 
1509*5e7646d2SAndroid Build Coastguard Worker         char tchoice[PPD_MAX_NAME];	/* Temporary choice name */
1510*5e7646d2SAndroid Build Coastguard Worker 
1511*5e7646d2SAndroid Build Coastguard Worker 	snprintf(tchoice, sizeof(tchoice), "_%s", option->defchoice);
1512*5e7646d2SAndroid Build Coastguard Worker 
1513*5e7646d2SAndroid Build Coastguard Worker 	if (ppdFindChoice(option, tchoice))
1514*5e7646d2SAndroid Build Coastguard Worker 	{
1515*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->defchoice, tchoice, sizeof(option->defchoice));
1516*5e7646d2SAndroid Build Coastguard Worker 
1517*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2_ppdOpen: Reset Default%s to %s...", option->keyword, tchoice));
1518*5e7646d2SAndroid Build Coastguard Worker 	}
1519*5e7646d2SAndroid Build Coastguard Worker       }
1520*5e7646d2SAndroid Build Coastguard Worker 
1521*5e7646d2SAndroid Build Coastguard Worker       option = NULL;
1522*5e7646d2SAndroid Build Coastguard Worker 
1523*5e7646d2SAndroid Build Coastguard Worker       free(string);
1524*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1525*5e7646d2SAndroid Build Coastguard Worker     }
1526*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "JCLCloseUI"))
1527*5e7646d2SAndroid Build Coastguard Worker     {
1528*5e7646d2SAndroid Build Coastguard Worker       if ((!option || option->section != PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT)
1529*5e7646d2SAndroid Build Coastguard Worker       {
1530*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_CLOSE_UI;
1531*5e7646d2SAndroid Build Coastguard Worker 
1532*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1533*5e7646d2SAndroid Build Coastguard Worker       }
1534*5e7646d2SAndroid Build Coastguard Worker 
1535*5e7646d2SAndroid Build Coastguard Worker       if (option && (!_cups_strcasecmp(option->defchoice, "custom") || !_cups_strncasecmp(option->defchoice, "custom.", 7)))
1536*5e7646d2SAndroid Build Coastguard Worker       {
1537*5e7646d2SAndroid Build Coastguard Worker        /*
1538*5e7646d2SAndroid Build Coastguard Worker 	* "*DefaultOption: Custom..." may set the default to a custom value
1539*5e7646d2SAndroid Build Coastguard Worker 	* or (for a very small number of incompatible PPD files) select a
1540*5e7646d2SAndroid Build Coastguard Worker 	* standard choice for the option, which CUPS renames to "_Custom..."
1541*5e7646d2SAndroid Build Coastguard Worker 	* to avoid compatibility issues.  See which this is...
1542*5e7646d2SAndroid Build Coastguard Worker 	*/
1543*5e7646d2SAndroid Build Coastguard Worker 
1544*5e7646d2SAndroid Build Coastguard Worker         char tchoice[PPD_MAX_NAME];	/* Temporary choice name */
1545*5e7646d2SAndroid Build Coastguard Worker 
1546*5e7646d2SAndroid Build Coastguard Worker 	snprintf(tchoice, sizeof(tchoice), "_%s", option->defchoice);
1547*5e7646d2SAndroid Build Coastguard Worker 
1548*5e7646d2SAndroid Build Coastguard Worker 	if (ppdFindChoice(option, tchoice))
1549*5e7646d2SAndroid Build Coastguard Worker 	{
1550*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(option->defchoice, tchoice, sizeof(option->defchoice));
1551*5e7646d2SAndroid Build Coastguard Worker 
1552*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2_ppdOpen: Reset Default%s to %s...", option->keyword, tchoice));
1553*5e7646d2SAndroid Build Coastguard Worker 	}
1554*5e7646d2SAndroid Build Coastguard Worker       }
1555*5e7646d2SAndroid Build Coastguard Worker 
1556*5e7646d2SAndroid Build Coastguard Worker       option = NULL;
1557*5e7646d2SAndroid Build Coastguard Worker 
1558*5e7646d2SAndroid Build Coastguard Worker       free(string);
1559*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1560*5e7646d2SAndroid Build Coastguard Worker     }
1561*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "OpenGroup"))
1562*5e7646d2SAndroid Build Coastguard Worker     {
1563*5e7646d2SAndroid Build Coastguard Worker      /*
1564*5e7646d2SAndroid Build Coastguard Worker       * Open a new group...
1565*5e7646d2SAndroid Build Coastguard Worker       */
1566*5e7646d2SAndroid Build Coastguard Worker 
1567*5e7646d2SAndroid Build Coastguard Worker       if (group != NULL)
1568*5e7646d2SAndroid Build Coastguard Worker       {
1569*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_NESTED_OPEN_GROUP;
1570*5e7646d2SAndroid Build Coastguard Worker 
1571*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1572*5e7646d2SAndroid Build Coastguard Worker       }
1573*5e7646d2SAndroid Build Coastguard Worker 
1574*5e7646d2SAndroid Build Coastguard Worker       if (!string)
1575*5e7646d2SAndroid Build Coastguard Worker       {
1576*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_OPEN_GROUP;
1577*5e7646d2SAndroid Build Coastguard Worker 
1578*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1579*5e7646d2SAndroid Build Coastguard Worker       }
1580*5e7646d2SAndroid Build Coastguard Worker 
1581*5e7646d2SAndroid Build Coastguard Worker      /*
1582*5e7646d2SAndroid Build Coastguard Worker       * Separate the group name from the text (name/text)...
1583*5e7646d2SAndroid Build Coastguard Worker       */
1584*5e7646d2SAndroid Build Coastguard Worker 
1585*5e7646d2SAndroid Build Coastguard Worker       if ((sptr = strchr(string, '/')) != NULL)
1586*5e7646d2SAndroid Build Coastguard Worker         *sptr++ = '\0';
1587*5e7646d2SAndroid Build Coastguard Worker       else
1588*5e7646d2SAndroid Build Coastguard Worker         sptr = string;
1589*5e7646d2SAndroid Build Coastguard Worker 
1590*5e7646d2SAndroid Build Coastguard Worker      /*
1591*5e7646d2SAndroid Build Coastguard Worker       * Fix up the text...
1592*5e7646d2SAndroid Build Coastguard Worker       */
1593*5e7646d2SAndroid Build Coastguard Worker 
1594*5e7646d2SAndroid Build Coastguard Worker       ppd_decode(sptr);
1595*5e7646d2SAndroid Build Coastguard Worker 
1596*5e7646d2SAndroid Build Coastguard Worker      /*
1597*5e7646d2SAndroid Build Coastguard Worker       * Find/add the group...
1598*5e7646d2SAndroid Build Coastguard Worker       */
1599*5e7646d2SAndroid Build Coastguard Worker 
1600*5e7646d2SAndroid Build Coastguard Worker       group = ppd_get_group(ppd, string, sptr, pg, encoding);
1601*5e7646d2SAndroid Build Coastguard Worker 
1602*5e7646d2SAndroid Build Coastguard Worker       if (group == NULL)
1603*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1604*5e7646d2SAndroid Build Coastguard Worker 
1605*5e7646d2SAndroid Build Coastguard Worker       free(string);
1606*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1607*5e7646d2SAndroid Build Coastguard Worker     }
1608*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "CloseGroup"))
1609*5e7646d2SAndroid Build Coastguard Worker     {
1610*5e7646d2SAndroid Build Coastguard Worker       group = NULL;
1611*5e7646d2SAndroid Build Coastguard Worker 
1612*5e7646d2SAndroid Build Coastguard Worker       free(string);
1613*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1614*5e7646d2SAndroid Build Coastguard Worker     }
1615*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "OrderDependency"))
1616*5e7646d2SAndroid Build Coastguard Worker     {
1617*5e7646d2SAndroid Build Coastguard Worker       order = (float)_cupsStrScand(string, &sptr, loc);
1618*5e7646d2SAndroid Build Coastguard Worker 
1619*5e7646d2SAndroid Build Coastguard Worker       if (!sptr || sscanf(sptr, "%40s%40s", name, keyword) != 2)
1620*5e7646d2SAndroid Build Coastguard Worker       {
1621*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_BAD_ORDER_DEPENDENCY;
1622*5e7646d2SAndroid Build Coastguard Worker 
1623*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1624*5e7646d2SAndroid Build Coastguard Worker       }
1625*5e7646d2SAndroid Build Coastguard Worker 
1626*5e7646d2SAndroid Build Coastguard Worker       if (keyword[0] == '*')
1627*5e7646d2SAndroid Build Coastguard Worker         _cups_strcpy(keyword, keyword + 1);
1628*5e7646d2SAndroid Build Coastguard Worker 
1629*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(name, "ExitServer"))
1630*5e7646d2SAndroid Build Coastguard Worker         section = PPD_ORDER_EXIT;
1631*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(name, "Prolog"))
1632*5e7646d2SAndroid Build Coastguard Worker         section = PPD_ORDER_PROLOG;
1633*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(name, "DocumentSetup"))
1634*5e7646d2SAndroid Build Coastguard Worker         section = PPD_ORDER_DOCUMENT;
1635*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(name, "PageSetup"))
1636*5e7646d2SAndroid Build Coastguard Worker         section = PPD_ORDER_PAGE;
1637*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(name, "JCLSetup"))
1638*5e7646d2SAndroid Build Coastguard Worker         section = PPD_ORDER_JCL;
1639*5e7646d2SAndroid Build Coastguard Worker       else
1640*5e7646d2SAndroid Build Coastguard Worker         section = PPD_ORDER_ANY;
1641*5e7646d2SAndroid Build Coastguard Worker 
1642*5e7646d2SAndroid Build Coastguard Worker       if (option == NULL)
1643*5e7646d2SAndroid Build Coastguard Worker       {
1644*5e7646d2SAndroid Build Coastguard Worker         ppd_group_t	*gtemp;
1645*5e7646d2SAndroid Build Coastguard Worker 
1646*5e7646d2SAndroid Build Coastguard Worker 
1647*5e7646d2SAndroid Build Coastguard Worker        /*
1648*5e7646d2SAndroid Build Coastguard Worker         * Only valid for Non-UI options...
1649*5e7646d2SAndroid Build Coastguard Worker 	*/
1650*5e7646d2SAndroid Build Coastguard Worker 
1651*5e7646d2SAndroid Build Coastguard Worker         for (i = ppd->num_groups, gtemp = ppd->groups; i > 0; i --, gtemp ++)
1652*5e7646d2SAndroid Build Coastguard Worker           if (gtemp->text[0] == '\0')
1653*5e7646d2SAndroid Build Coastguard Worker 	    break;
1654*5e7646d2SAndroid Build Coastguard Worker 
1655*5e7646d2SAndroid Build Coastguard Worker         if (i > 0)
1656*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < gtemp->num_options; i ++)
1657*5e7646d2SAndroid Build Coastguard Worker 	    if (!strcmp(keyword, gtemp->options[i].keyword))
1658*5e7646d2SAndroid Build Coastguard Worker 	    {
1659*5e7646d2SAndroid Build Coastguard Worker 	      gtemp->options[i].section = section;
1660*5e7646d2SAndroid Build Coastguard Worker 	      gtemp->options[i].order   = order;
1661*5e7646d2SAndroid Build Coastguard Worker 	      break;
1662*5e7646d2SAndroid Build Coastguard Worker 	    }
1663*5e7646d2SAndroid Build Coastguard Worker       }
1664*5e7646d2SAndroid Build Coastguard Worker       else
1665*5e7646d2SAndroid Build Coastguard Worker       {
1666*5e7646d2SAndroid Build Coastguard Worker         option->section = section;
1667*5e7646d2SAndroid Build Coastguard Worker 	option->order   = order;
1668*5e7646d2SAndroid Build Coastguard Worker       }
1669*5e7646d2SAndroid Build Coastguard Worker 
1670*5e7646d2SAndroid Build Coastguard Worker       free(string);
1671*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1672*5e7646d2SAndroid Build Coastguard Worker     }
1673*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(keyword, "Default", 7))
1674*5e7646d2SAndroid Build Coastguard Worker     {
1675*5e7646d2SAndroid Build Coastguard Worker       if (string == NULL)
1676*5e7646d2SAndroid Build Coastguard Worker         continue;
1677*5e7646d2SAndroid Build Coastguard Worker 
1678*5e7646d2SAndroid Build Coastguard Worker      /*
1679*5e7646d2SAndroid Build Coastguard Worker       * Drop UI text, if any, from value...
1680*5e7646d2SAndroid Build Coastguard Worker       */
1681*5e7646d2SAndroid Build Coastguard Worker 
1682*5e7646d2SAndroid Build Coastguard Worker       if (strchr(string, '/') != NULL)
1683*5e7646d2SAndroid Build Coastguard Worker         *strchr(string, '/') = '\0';
1684*5e7646d2SAndroid Build Coastguard Worker 
1685*5e7646d2SAndroid Build Coastguard Worker      /*
1686*5e7646d2SAndroid Build Coastguard Worker       * Assign the default value as appropriate...
1687*5e7646d2SAndroid Build Coastguard Worker       */
1688*5e7646d2SAndroid Build Coastguard Worker 
1689*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(keyword, "DefaultColorSpace"))
1690*5e7646d2SAndroid Build Coastguard Worker       {
1691*5e7646d2SAndroid Build Coastguard Worker        /*
1692*5e7646d2SAndroid Build Coastguard Worker         * Set default colorspace...
1693*5e7646d2SAndroid Build Coastguard Worker 	*/
1694*5e7646d2SAndroid Build Coastguard Worker 
1695*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(string, "CMY"))
1696*5e7646d2SAndroid Build Coastguard Worker           ppd->colorspace = PPD_CS_CMY;
1697*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(string, "CMYK"))
1698*5e7646d2SAndroid Build Coastguard Worker           ppd->colorspace = PPD_CS_CMYK;
1699*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(string, "RGB"))
1700*5e7646d2SAndroid Build Coastguard Worker           ppd->colorspace = PPD_CS_RGB;
1701*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(string, "RGBK"))
1702*5e7646d2SAndroid Build Coastguard Worker           ppd->colorspace = PPD_CS_RGBK;
1703*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(string, "N"))
1704*5e7646d2SAndroid Build Coastguard Worker           ppd->colorspace = PPD_CS_N;
1705*5e7646d2SAndroid Build Coastguard Worker 	else
1706*5e7646d2SAndroid Build Coastguard Worker           ppd->colorspace = PPD_CS_GRAY;
1707*5e7646d2SAndroid Build Coastguard Worker       }
1708*5e7646d2SAndroid Build Coastguard Worker       else if (option && !strcmp(keyword + 7, option->keyword))
1709*5e7646d2SAndroid Build Coastguard Worker       {
1710*5e7646d2SAndroid Build Coastguard Worker        /*
1711*5e7646d2SAndroid Build Coastguard Worker         * Set the default as part of the current option...
1712*5e7646d2SAndroid Build Coastguard Worker 	*/
1713*5e7646d2SAndroid Build Coastguard Worker 
1714*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(option->defchoice, string, sizeof(option->defchoice));
1715*5e7646d2SAndroid Build Coastguard Worker 
1716*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("2_ppdOpen: Set %s to %s...", keyword, option->defchoice));
1717*5e7646d2SAndroid Build Coastguard Worker       }
1718*5e7646d2SAndroid Build Coastguard Worker       else
1719*5e7646d2SAndroid Build Coastguard Worker       {
1720*5e7646d2SAndroid Build Coastguard Worker        /*
1721*5e7646d2SAndroid Build Coastguard Worker         * Lookup option and set if it has been defined...
1722*5e7646d2SAndroid Build Coastguard Worker 	*/
1723*5e7646d2SAndroid Build Coastguard Worker 
1724*5e7646d2SAndroid Build Coastguard Worker         ppd_option_t	*toption;	/* Temporary option */
1725*5e7646d2SAndroid Build Coastguard Worker 
1726*5e7646d2SAndroid Build Coastguard Worker         if ((toption = ppdFindOption(ppd, keyword + 7)) != NULL)
1727*5e7646d2SAndroid Build Coastguard Worker 	{
1728*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strcasecmp(string, "custom") || !_cups_strncasecmp(string, "custom.", 7))
1729*5e7646d2SAndroid Build Coastguard Worker 	  {
1730*5e7646d2SAndroid Build Coastguard Worker 	   /*
1731*5e7646d2SAndroid Build Coastguard Worker 	    * "*DefaultOption: Custom..." may set the default to a custom value
1732*5e7646d2SAndroid Build Coastguard Worker 	    * or (for a very small number of incompatible PPD files) select a
1733*5e7646d2SAndroid Build Coastguard Worker 	    * standard choice for the option, which CUPS renames to "_Custom..."
1734*5e7646d2SAndroid Build Coastguard Worker 	    * to avoid compatibility issues.  See which this is...
1735*5e7646d2SAndroid Build Coastguard Worker 	    */
1736*5e7646d2SAndroid Build Coastguard Worker 
1737*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(toption->defchoice, sizeof(toption->defchoice), "_%s", string);
1738*5e7646d2SAndroid Build Coastguard Worker 	    if (!ppdFindChoice(toption, toption->defchoice))
1739*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
1740*5e7646d2SAndroid Build Coastguard Worker 	  }
1741*5e7646d2SAndroid Build Coastguard Worker 	  else
1742*5e7646d2SAndroid Build Coastguard Worker 	  {
1743*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
1744*5e7646d2SAndroid Build Coastguard Worker 	  }
1745*5e7646d2SAndroid Build Coastguard Worker 
1746*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2_ppdOpen: Set %s to %s...", keyword, toption->defchoice));
1747*5e7646d2SAndroid Build Coastguard Worker 	}
1748*5e7646d2SAndroid Build Coastguard Worker       }
1749*5e7646d2SAndroid Build Coastguard Worker     }
1750*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "UIConstraints") ||
1751*5e7646d2SAndroid Build Coastguard Worker              !strcmp(keyword, "NonUIConstraints"))
1752*5e7646d2SAndroid Build Coastguard Worker     {
1753*5e7646d2SAndroid Build Coastguard Worker       if (!string)
1754*5e7646d2SAndroid Build Coastguard Worker       {
1755*5e7646d2SAndroid Build Coastguard Worker 	pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1756*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1757*5e7646d2SAndroid Build Coastguard Worker       }
1758*5e7646d2SAndroid Build Coastguard Worker 
1759*5e7646d2SAndroid Build Coastguard Worker       if (ppd->num_consts == 0)
1760*5e7646d2SAndroid Build Coastguard Worker 	constraint = calloc(2, sizeof(ppd_const_t));
1761*5e7646d2SAndroid Build Coastguard Worker       else
1762*5e7646d2SAndroid Build Coastguard Worker 	constraint = realloc(ppd->consts, (size_t)(ppd->num_consts + 2) * sizeof(ppd_const_t));
1763*5e7646d2SAndroid Build Coastguard Worker 
1764*5e7646d2SAndroid Build Coastguard Worker       if (constraint == NULL)
1765*5e7646d2SAndroid Build Coastguard Worker       {
1766*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
1767*5e7646d2SAndroid Build Coastguard Worker 
1768*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1769*5e7646d2SAndroid Build Coastguard Worker       }
1770*5e7646d2SAndroid Build Coastguard Worker 
1771*5e7646d2SAndroid Build Coastguard Worker       ppd->consts = constraint;
1772*5e7646d2SAndroid Build Coastguard Worker       constraint += ppd->num_consts;
1773*5e7646d2SAndroid Build Coastguard Worker       ppd->num_consts ++;
1774*5e7646d2SAndroid Build Coastguard Worker 
1775*5e7646d2SAndroid Build Coastguard Worker       switch (sscanf(string, "%40s%40s%40s%40s", constraint->option1,
1776*5e7646d2SAndroid Build Coastguard Worker                      constraint->choice1, constraint->option2,
1777*5e7646d2SAndroid Build Coastguard Worker 		     constraint->choice2))
1778*5e7646d2SAndroid Build Coastguard Worker       {
1779*5e7646d2SAndroid Build Coastguard Worker         default : /* Error */
1780*5e7646d2SAndroid Build Coastguard Worker 	    pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1781*5e7646d2SAndroid Build Coastguard Worker 	    goto error;
1782*5e7646d2SAndroid Build Coastguard Worker 
1783*5e7646d2SAndroid Build Coastguard Worker 	case 2 : /* Two options... */
1784*5e7646d2SAndroid Build Coastguard Worker 	   /*
1785*5e7646d2SAndroid Build Coastguard Worker 	    * Check for broken constraints like "* Option"...
1786*5e7646d2SAndroid Build Coastguard Worker 	    */
1787*5e7646d2SAndroid Build Coastguard Worker 
1788*5e7646d2SAndroid Build Coastguard Worker 	    if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1789*5e7646d2SAndroid Build Coastguard Worker 	        (!strcmp(constraint->option1, "*") ||
1790*5e7646d2SAndroid Build Coastguard Worker 	         !strcmp(constraint->choice1, "*")))
1791*5e7646d2SAndroid Build Coastguard Worker 	    {
1792*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1793*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1794*5e7646d2SAndroid Build Coastguard Worker 	    }
1795*5e7646d2SAndroid Build Coastguard Worker 
1796*5e7646d2SAndroid Build Coastguard Worker 	   /*
1797*5e7646d2SAndroid Build Coastguard Worker 	    * The following strcpy's are safe, as optionN and
1798*5e7646d2SAndroid Build Coastguard Worker 	    * choiceN are all the same size (size defined by PPD spec...)
1799*5e7646d2SAndroid Build Coastguard Worker 	    */
1800*5e7646d2SAndroid Build Coastguard Worker 
1801*5e7646d2SAndroid Build Coastguard Worker 	    if (constraint->option1[0] == '*')
1802*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(constraint->option1, constraint->option1 + 1);
1803*5e7646d2SAndroid Build Coastguard Worker 	    else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1804*5e7646d2SAndroid Build Coastguard Worker 	    {
1805*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1806*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1807*5e7646d2SAndroid Build Coastguard Worker 	    }
1808*5e7646d2SAndroid Build Coastguard Worker 
1809*5e7646d2SAndroid Build Coastguard Worker 	    if (constraint->choice1[0] == '*')
1810*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(constraint->option2, constraint->choice1 + 1);
1811*5e7646d2SAndroid Build Coastguard Worker 	    else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1812*5e7646d2SAndroid Build Coastguard Worker 	    {
1813*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1814*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1815*5e7646d2SAndroid Build Coastguard Worker 	    }
1816*5e7646d2SAndroid Build Coastguard Worker 
1817*5e7646d2SAndroid Build Coastguard Worker             constraint->choice1[0] = '\0';
1818*5e7646d2SAndroid Build Coastguard Worker             constraint->choice2[0] = '\0';
1819*5e7646d2SAndroid Build Coastguard Worker 	    break;
1820*5e7646d2SAndroid Build Coastguard Worker 
1821*5e7646d2SAndroid Build Coastguard Worker 	case 3 : /* Two options, one choice... */
1822*5e7646d2SAndroid Build Coastguard Worker 	   /*
1823*5e7646d2SAndroid Build Coastguard Worker 	    * Check for broken constraints like "* Option"...
1824*5e7646d2SAndroid Build Coastguard Worker 	    */
1825*5e7646d2SAndroid Build Coastguard Worker 
1826*5e7646d2SAndroid Build Coastguard Worker 	    if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1827*5e7646d2SAndroid Build Coastguard Worker 	        (!strcmp(constraint->option1, "*") ||
1828*5e7646d2SAndroid Build Coastguard Worker 	         !strcmp(constraint->choice1, "*") ||
1829*5e7646d2SAndroid Build Coastguard Worker 	         !strcmp(constraint->option2, "*")))
1830*5e7646d2SAndroid Build Coastguard Worker 	    {
1831*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1832*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1833*5e7646d2SAndroid Build Coastguard Worker 	    }
1834*5e7646d2SAndroid Build Coastguard Worker 
1835*5e7646d2SAndroid Build Coastguard Worker 	   /*
1836*5e7646d2SAndroid Build Coastguard Worker 	    * The following _cups_strcpy's are safe, as optionN and
1837*5e7646d2SAndroid Build Coastguard Worker 	    * choiceN are all the same size (size defined by PPD spec...)
1838*5e7646d2SAndroid Build Coastguard Worker 	    */
1839*5e7646d2SAndroid Build Coastguard Worker 
1840*5e7646d2SAndroid Build Coastguard Worker 	    if (constraint->option1[0] == '*')
1841*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(constraint->option1, constraint->option1 + 1);
1842*5e7646d2SAndroid Build Coastguard Worker 	    else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1843*5e7646d2SAndroid Build Coastguard Worker 	    {
1844*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1845*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1846*5e7646d2SAndroid Build Coastguard Worker 	    }
1847*5e7646d2SAndroid Build Coastguard Worker 
1848*5e7646d2SAndroid Build Coastguard Worker 	    if (constraint->choice1[0] == '*')
1849*5e7646d2SAndroid Build Coastguard Worker 	    {
1850*5e7646d2SAndroid Build Coastguard Worker 	      if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1851*5e7646d2SAndroid Build Coastguard Worker 	          constraint->option2[0] == '*')
1852*5e7646d2SAndroid Build Coastguard Worker 	      {
1853*5e7646d2SAndroid Build Coastguard Worker 		pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1854*5e7646d2SAndroid Build Coastguard Worker 		goto error;
1855*5e7646d2SAndroid Build Coastguard Worker 	      }
1856*5e7646d2SAndroid Build Coastguard Worker 
1857*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(constraint->choice2, constraint->option2);
1858*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(constraint->option2, constraint->choice1 + 1);
1859*5e7646d2SAndroid Build Coastguard Worker               constraint->choice1[0] = '\0';
1860*5e7646d2SAndroid Build Coastguard Worker 	    }
1861*5e7646d2SAndroid Build Coastguard Worker 	    else
1862*5e7646d2SAndroid Build Coastguard Worker 	    {
1863*5e7646d2SAndroid Build Coastguard Worker 	      if (constraint->option2[0] == '*')
1864*5e7646d2SAndroid Build Coastguard Worker   	        _cups_strcpy(constraint->option2, constraint->option2 + 1);
1865*5e7646d2SAndroid Build Coastguard Worker 	      else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1866*5e7646d2SAndroid Build Coastguard Worker 	      {
1867*5e7646d2SAndroid Build Coastguard Worker 		pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1868*5e7646d2SAndroid Build Coastguard Worker 		goto error;
1869*5e7646d2SAndroid Build Coastguard Worker 	      }
1870*5e7646d2SAndroid Build Coastguard Worker 
1871*5e7646d2SAndroid Build Coastguard Worker               constraint->choice2[0] = '\0';
1872*5e7646d2SAndroid Build Coastguard Worker 	    }
1873*5e7646d2SAndroid Build Coastguard Worker 	    break;
1874*5e7646d2SAndroid Build Coastguard Worker 
1875*5e7646d2SAndroid Build Coastguard Worker 	case 4 : /* Two options, two choices... */
1876*5e7646d2SAndroid Build Coastguard Worker 	   /*
1877*5e7646d2SAndroid Build Coastguard Worker 	    * Check for broken constraints like "* Option"...
1878*5e7646d2SAndroid Build Coastguard Worker 	    */
1879*5e7646d2SAndroid Build Coastguard Worker 
1880*5e7646d2SAndroid Build Coastguard Worker 	    if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1881*5e7646d2SAndroid Build Coastguard Worker 	        (!strcmp(constraint->option1, "*") ||
1882*5e7646d2SAndroid Build Coastguard Worker 	         !strcmp(constraint->choice1, "*") ||
1883*5e7646d2SAndroid Build Coastguard Worker 	         !strcmp(constraint->option2, "*") ||
1884*5e7646d2SAndroid Build Coastguard Worker 	         !strcmp(constraint->choice2, "*")))
1885*5e7646d2SAndroid Build Coastguard Worker 	    {
1886*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1887*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1888*5e7646d2SAndroid Build Coastguard Worker 	    }
1889*5e7646d2SAndroid Build Coastguard Worker 
1890*5e7646d2SAndroid Build Coastguard Worker 	    if (constraint->option1[0] == '*')
1891*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(constraint->option1, constraint->option1 + 1);
1892*5e7646d2SAndroid Build Coastguard Worker 	    else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1893*5e7646d2SAndroid Build Coastguard Worker 	    {
1894*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1895*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1896*5e7646d2SAndroid Build Coastguard Worker 	    }
1897*5e7646d2SAndroid Build Coastguard Worker 
1898*5e7646d2SAndroid Build Coastguard Worker             if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1899*5e7646d2SAndroid Build Coastguard Worker 	        constraint->choice1[0] == '*')
1900*5e7646d2SAndroid Build Coastguard Worker 	    {
1901*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1902*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1903*5e7646d2SAndroid Build Coastguard Worker 	    }
1904*5e7646d2SAndroid Build Coastguard Worker 
1905*5e7646d2SAndroid Build Coastguard Worker 	    if (constraint->option2[0] == '*')
1906*5e7646d2SAndroid Build Coastguard Worker   	      _cups_strcpy(constraint->option2, constraint->option2 + 1);
1907*5e7646d2SAndroid Build Coastguard Worker 	    else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1908*5e7646d2SAndroid Build Coastguard Worker 	    {
1909*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1910*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1911*5e7646d2SAndroid Build Coastguard Worker 	    }
1912*5e7646d2SAndroid Build Coastguard Worker 
1913*5e7646d2SAndroid Build Coastguard Worker             if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1914*5e7646d2SAndroid Build Coastguard Worker 	        constraint->choice2[0] == '*')
1915*5e7646d2SAndroid Build Coastguard Worker 	    {
1916*5e7646d2SAndroid Build Coastguard Worker 	      pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1917*5e7646d2SAndroid Build Coastguard Worker 	      goto error;
1918*5e7646d2SAndroid Build Coastguard Worker 	    }
1919*5e7646d2SAndroid Build Coastguard Worker 	    break;
1920*5e7646d2SAndroid Build Coastguard Worker       }
1921*5e7646d2SAndroid Build Coastguard Worker 
1922*5e7646d2SAndroid Build Coastguard Worker      /*
1923*5e7646d2SAndroid Build Coastguard Worker       * Don't add this one as an attribute...
1924*5e7646d2SAndroid Build Coastguard Worker       */
1925*5e7646d2SAndroid Build Coastguard Worker 
1926*5e7646d2SAndroid Build Coastguard Worker       free(string);
1927*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1928*5e7646d2SAndroid Build Coastguard Worker     }
1929*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "PaperDimension"))
1930*5e7646d2SAndroid Build Coastguard Worker     {
1931*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
1932*5e7646d2SAndroid Build Coastguard Worker       {
1933*5e7646d2SAndroid Build Coastguard Worker         char cname[PPD_MAX_NAME];	/* Rewrite with a leading underscore */
1934*5e7646d2SAndroid Build Coastguard Worker         snprintf(cname, sizeof(cname), "_%s", name);
1935*5e7646d2SAndroid Build Coastguard Worker         strlcpy(name, cname, sizeof(name));
1936*5e7646d2SAndroid Build Coastguard Worker       }
1937*5e7646d2SAndroid Build Coastguard Worker 
1938*5e7646d2SAndroid Build Coastguard Worker       if ((size = ppdPageSize(ppd, name)) == NULL)
1939*5e7646d2SAndroid Build Coastguard Worker 	size = ppd_add_size(ppd, name);
1940*5e7646d2SAndroid Build Coastguard Worker 
1941*5e7646d2SAndroid Build Coastguard Worker       if (size == NULL)
1942*5e7646d2SAndroid Build Coastguard Worker       {
1943*5e7646d2SAndroid Build Coastguard Worker        /*
1944*5e7646d2SAndroid Build Coastguard Worker         * Unable to add or find size!
1945*5e7646d2SAndroid Build Coastguard Worker 	*/
1946*5e7646d2SAndroid Build Coastguard Worker 
1947*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
1948*5e7646d2SAndroid Build Coastguard Worker 
1949*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1950*5e7646d2SAndroid Build Coastguard Worker       }
1951*5e7646d2SAndroid Build Coastguard Worker 
1952*5e7646d2SAndroid Build Coastguard Worker       size->width  = (float)_cupsStrScand(string, &sptr, loc);
1953*5e7646d2SAndroid Build Coastguard Worker       size->length = (float)_cupsStrScand(sptr, NULL, loc);
1954*5e7646d2SAndroid Build Coastguard Worker 
1955*5e7646d2SAndroid Build Coastguard Worker       free(string);
1956*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1957*5e7646d2SAndroid Build Coastguard Worker     }
1958*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(keyword, "ImageableArea"))
1959*5e7646d2SAndroid Build Coastguard Worker     {
1960*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
1961*5e7646d2SAndroid Build Coastguard Worker       {
1962*5e7646d2SAndroid Build Coastguard Worker         char cname[PPD_MAX_NAME];	/* Rewrite with a leading underscore */
1963*5e7646d2SAndroid Build Coastguard Worker         snprintf(cname, sizeof(cname), "_%s", name);
1964*5e7646d2SAndroid Build Coastguard Worker         strlcpy(name, cname, sizeof(name));
1965*5e7646d2SAndroid Build Coastguard Worker       }
1966*5e7646d2SAndroid Build Coastguard Worker 
1967*5e7646d2SAndroid Build Coastguard Worker       if ((size = ppdPageSize(ppd, name)) == NULL)
1968*5e7646d2SAndroid Build Coastguard Worker 	size = ppd_add_size(ppd, name);
1969*5e7646d2SAndroid Build Coastguard Worker 
1970*5e7646d2SAndroid Build Coastguard Worker       if (size == NULL)
1971*5e7646d2SAndroid Build Coastguard Worker       {
1972*5e7646d2SAndroid Build Coastguard Worker        /*
1973*5e7646d2SAndroid Build Coastguard Worker         * Unable to add or find size!
1974*5e7646d2SAndroid Build Coastguard Worker 	*/
1975*5e7646d2SAndroid Build Coastguard Worker 
1976*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
1977*5e7646d2SAndroid Build Coastguard Worker 
1978*5e7646d2SAndroid Build Coastguard Worker 	goto error;
1979*5e7646d2SAndroid Build Coastguard Worker       }
1980*5e7646d2SAndroid Build Coastguard Worker 
1981*5e7646d2SAndroid Build Coastguard Worker       size->left   = (float)_cupsStrScand(string, &sptr, loc);
1982*5e7646d2SAndroid Build Coastguard Worker       size->bottom = (float)_cupsStrScand(sptr, &sptr, loc);
1983*5e7646d2SAndroid Build Coastguard Worker       size->right  = (float)_cupsStrScand(sptr, &sptr, loc);
1984*5e7646d2SAndroid Build Coastguard Worker       size->top    = (float)_cupsStrScand(sptr, NULL, loc);
1985*5e7646d2SAndroid Build Coastguard Worker 
1986*5e7646d2SAndroid Build Coastguard Worker       free(string);
1987*5e7646d2SAndroid Build Coastguard Worker       string = NULL;
1988*5e7646d2SAndroid Build Coastguard Worker     }
1989*5e7646d2SAndroid Build Coastguard Worker     else if (option != NULL &&
1990*5e7646d2SAndroid Build Coastguard Worker              (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
1991*5e7646d2SAndroid Build Coastguard Worker 	         (PPD_KEYWORD | PPD_OPTION | PPD_STRING) &&
1992*5e7646d2SAndroid Build Coastguard Worker 	     !strcmp(keyword, option->keyword))
1993*5e7646d2SAndroid Build Coastguard Worker     {
1994*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("2_ppdOpen: group=%p, subgroup=%p", group, subgroup));
1995*5e7646d2SAndroid Build Coastguard Worker 
1996*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
1997*5e7646d2SAndroid Build Coastguard Worker       {
1998*5e7646d2SAndroid Build Coastguard Worker         char cname[PPD_MAX_NAME];	/* Rewrite with a leading underscore */
1999*5e7646d2SAndroid Build Coastguard Worker         snprintf(cname, sizeof(cname), "_%s", name);
2000*5e7646d2SAndroid Build Coastguard Worker         strlcpy(name, cname, sizeof(name));
2001*5e7646d2SAndroid Build Coastguard Worker       }
2002*5e7646d2SAndroid Build Coastguard Worker 
2003*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(keyword, "PageSize"))
2004*5e7646d2SAndroid Build Coastguard Worker       {
2005*5e7646d2SAndroid Build Coastguard Worker        /*
2006*5e7646d2SAndroid Build Coastguard Worker         * Add a page size...
2007*5e7646d2SAndroid Build Coastguard Worker 	*/
2008*5e7646d2SAndroid Build Coastguard Worker 
2009*5e7646d2SAndroid Build Coastguard Worker         if (ppdPageSize(ppd, name) == NULL)
2010*5e7646d2SAndroid Build Coastguard Worker 	  ppd_add_size(ppd, name);
2011*5e7646d2SAndroid Build Coastguard Worker       }
2012*5e7646d2SAndroid Build Coastguard Worker 
2013*5e7646d2SAndroid Build Coastguard Worker      /*
2014*5e7646d2SAndroid Build Coastguard Worker       * Add the option choice...
2015*5e7646d2SAndroid Build Coastguard Worker       */
2016*5e7646d2SAndroid Build Coastguard Worker 
2017*5e7646d2SAndroid Build Coastguard Worker       if ((choice = ppd_add_choice(option, name)) == NULL)
2018*5e7646d2SAndroid Build Coastguard Worker       {
2019*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ALLOC_ERROR;
2020*5e7646d2SAndroid Build Coastguard Worker 
2021*5e7646d2SAndroid Build Coastguard Worker 	goto error;
2022*5e7646d2SAndroid Build Coastguard Worker       }
2023*5e7646d2SAndroid Build Coastguard Worker 
2024*5e7646d2SAndroid Build Coastguard Worker       if (text[0])
2025*5e7646d2SAndroid Build Coastguard Worker         cupsCharsetToUTF8((cups_utf8_t *)choice->text, text,
2026*5e7646d2SAndroid Build Coastguard Worker 	                   sizeof(choice->text), encoding);
2027*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(name, "True"))
2028*5e7646d2SAndroid Build Coastguard Worker         strlcpy(choice->text, _("Yes"), sizeof(choice->text));
2029*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(name, "False"))
2030*5e7646d2SAndroid Build Coastguard Worker         strlcpy(choice->text, _("No"), sizeof(choice->text));
2031*5e7646d2SAndroid Build Coastguard Worker       else
2032*5e7646d2SAndroid Build Coastguard Worker         strlcpy(choice->text, name, sizeof(choice->text));
2033*5e7646d2SAndroid Build Coastguard Worker 
2034*5e7646d2SAndroid Build Coastguard Worker       if (option->section == PPD_ORDER_JCL)
2035*5e7646d2SAndroid Build Coastguard Worker         ppd_decode(string);		/* Decode quoted string */
2036*5e7646d2SAndroid Build Coastguard Worker 
2037*5e7646d2SAndroid Build Coastguard Worker       choice->code = string;
2038*5e7646d2SAndroid Build Coastguard Worker       string       = NULL;		/* Don't add as an attribute below */
2039*5e7646d2SAndroid Build Coastguard Worker     }
2040*5e7646d2SAndroid Build Coastguard Worker 
2041*5e7646d2SAndroid Build Coastguard Worker    /*
2042*5e7646d2SAndroid Build Coastguard Worker     * Add remaining lines with keywords and string values as attributes...
2043*5e7646d2SAndroid Build Coastguard Worker     */
2044*5e7646d2SAndroid Build Coastguard Worker 
2045*5e7646d2SAndroid Build Coastguard Worker     if (string &&
2046*5e7646d2SAndroid Build Coastguard Worker         (mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING))
2047*5e7646d2SAndroid Build Coastguard Worker       ppd_add_attr(ppd, keyword, name, text, string);
2048*5e7646d2SAndroid Build Coastguard Worker     else
2049*5e7646d2SAndroid Build Coastguard Worker       free(string);
2050*5e7646d2SAndroid Build Coastguard Worker   }
2051*5e7646d2SAndroid Build Coastguard Worker 
2052*5e7646d2SAndroid Build Coastguard Worker  /*
2053*5e7646d2SAndroid Build Coastguard Worker   * Check for a missing CloseUI/JCLCloseUI...
2054*5e7646d2SAndroid Build Coastguard Worker   */
2055*5e7646d2SAndroid Build Coastguard Worker 
2056*5e7646d2SAndroid Build Coastguard Worker   if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
2057*5e7646d2SAndroid Build Coastguard Worker   {
2058*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_MISSING_CLOSE_UI;
2059*5e7646d2SAndroid Build Coastguard Worker     goto error;
2060*5e7646d2SAndroid Build Coastguard Worker   }
2061*5e7646d2SAndroid Build Coastguard Worker 
2062*5e7646d2SAndroid Build Coastguard Worker  /*
2063*5e7646d2SAndroid Build Coastguard Worker   * Check for a missing CloseGroup...
2064*5e7646d2SAndroid Build Coastguard Worker   */
2065*5e7646d2SAndroid Build Coastguard Worker 
2066*5e7646d2SAndroid Build Coastguard Worker   if (group && pg->ppd_conform == PPD_CONFORM_STRICT)
2067*5e7646d2SAndroid Build Coastguard Worker   {
2068*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_MISSING_CLOSE_GROUP;
2069*5e7646d2SAndroid Build Coastguard Worker     goto error;
2070*5e7646d2SAndroid Build Coastguard Worker   }
2071*5e7646d2SAndroid Build Coastguard Worker 
2072*5e7646d2SAndroid Build Coastguard Worker   free(line.buffer);
2073*5e7646d2SAndroid Build Coastguard Worker 
2074*5e7646d2SAndroid Build Coastguard Worker  /*
2075*5e7646d2SAndroid Build Coastguard Worker   * Reset language preferences...
2076*5e7646d2SAndroid Build Coastguard Worker   */
2077*5e7646d2SAndroid Build Coastguard Worker 
2078*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
2079*5e7646d2SAndroid Build Coastguard Worker   if (!cupsFileEOF(fp))
2080*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1_ppdOpen: Premature EOF at %lu...\n",
2081*5e7646d2SAndroid Build Coastguard Worker                   (unsigned long)cupsFileTell(fp)));
2082*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
2083*5e7646d2SAndroid Build Coastguard Worker 
2084*5e7646d2SAndroid Build Coastguard Worker   if (pg->ppd_status != PPD_OK)
2085*5e7646d2SAndroid Build Coastguard Worker   {
2086*5e7646d2SAndroid Build Coastguard Worker    /*
2087*5e7646d2SAndroid Build Coastguard Worker     * Had an error reading the PPD file, cannot continue!
2088*5e7646d2SAndroid Build Coastguard Worker     */
2089*5e7646d2SAndroid Build Coastguard Worker 
2090*5e7646d2SAndroid Build Coastguard Worker     ppdClose(ppd);
2091*5e7646d2SAndroid Build Coastguard Worker 
2092*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2093*5e7646d2SAndroid Build Coastguard Worker   }
2094*5e7646d2SAndroid Build Coastguard Worker 
2095*5e7646d2SAndroid Build Coastguard Worker  /*
2096*5e7646d2SAndroid Build Coastguard Worker   * Update the filters array as needed...
2097*5e7646d2SAndroid Build Coastguard Worker   */
2098*5e7646d2SAndroid Build Coastguard Worker 
2099*5e7646d2SAndroid Build Coastguard Worker   if (!ppd_update_filters(ppd, pg))
2100*5e7646d2SAndroid Build Coastguard Worker   {
2101*5e7646d2SAndroid Build Coastguard Worker     ppdClose(ppd);
2102*5e7646d2SAndroid Build Coastguard Worker 
2103*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2104*5e7646d2SAndroid Build Coastguard Worker   }
2105*5e7646d2SAndroid Build Coastguard Worker 
2106*5e7646d2SAndroid Build Coastguard Worker  /*
2107*5e7646d2SAndroid Build Coastguard Worker   * Create the sorted options array and set the option back-pointer for
2108*5e7646d2SAndroid Build Coastguard Worker   * each choice and custom option...
2109*5e7646d2SAndroid Build Coastguard Worker   */
2110*5e7646d2SAndroid Build Coastguard Worker 
2111*5e7646d2SAndroid Build Coastguard Worker   ppd->options = cupsArrayNew2((cups_array_func_t)ppd_compare_options, NULL,
2112*5e7646d2SAndroid Build Coastguard Worker                                (cups_ahash_func_t)ppd_hash_option,
2113*5e7646d2SAndroid Build Coastguard Worker 			       PPD_HASHSIZE);
2114*5e7646d2SAndroid Build Coastguard Worker 
2115*5e7646d2SAndroid Build Coastguard Worker   for (i = ppd->num_groups, group = ppd->groups;
2116*5e7646d2SAndroid Build Coastguard Worker        i > 0;
2117*5e7646d2SAndroid Build Coastguard Worker        i --, group ++)
2118*5e7646d2SAndroid Build Coastguard Worker   {
2119*5e7646d2SAndroid Build Coastguard Worker     for (j = group->num_options, option = group->options;
2120*5e7646d2SAndroid Build Coastguard Worker          j > 0;
2121*5e7646d2SAndroid Build Coastguard Worker 	 j --, option ++)
2122*5e7646d2SAndroid Build Coastguard Worker     {
2123*5e7646d2SAndroid Build Coastguard Worker       ppd_coption_t	*coption;	/* Custom option */
2124*5e7646d2SAndroid Build Coastguard Worker 
2125*5e7646d2SAndroid Build Coastguard Worker 
2126*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(ppd->options, option);
2127*5e7646d2SAndroid Build Coastguard Worker 
2128*5e7646d2SAndroid Build Coastguard Worker       for (k = 0; k < option->num_choices; k ++)
2129*5e7646d2SAndroid Build Coastguard Worker         option->choices[k].option = option;
2130*5e7646d2SAndroid Build Coastguard Worker 
2131*5e7646d2SAndroid Build Coastguard Worker       if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
2132*5e7646d2SAndroid Build Coastguard Worker         coption->option = option;
2133*5e7646d2SAndroid Build Coastguard Worker     }
2134*5e7646d2SAndroid Build Coastguard Worker   }
2135*5e7646d2SAndroid Build Coastguard Worker 
2136*5e7646d2SAndroid Build Coastguard Worker  /*
2137*5e7646d2SAndroid Build Coastguard Worker   * Create an array to track the marked choices...
2138*5e7646d2SAndroid Build Coastguard Worker   */
2139*5e7646d2SAndroid Build Coastguard Worker 
2140*5e7646d2SAndroid Build Coastguard Worker   ppd->marked = cupsArrayNew((cups_array_func_t)ppd_compare_choices, NULL);
2141*5e7646d2SAndroid Build Coastguard Worker 
2142*5e7646d2SAndroid Build Coastguard Worker  /*
2143*5e7646d2SAndroid Build Coastguard Worker   * Return the PPD file structure...
2144*5e7646d2SAndroid Build Coastguard Worker   */
2145*5e7646d2SAndroid Build Coastguard Worker 
2146*5e7646d2SAndroid Build Coastguard Worker   return (ppd);
2147*5e7646d2SAndroid Build Coastguard Worker 
2148*5e7646d2SAndroid Build Coastguard Worker  /*
2149*5e7646d2SAndroid Build Coastguard Worker   * Common exit point for errors to save code size...
2150*5e7646d2SAndroid Build Coastguard Worker   */
2151*5e7646d2SAndroid Build Coastguard Worker 
2152*5e7646d2SAndroid Build Coastguard Worker   error:
2153*5e7646d2SAndroid Build Coastguard Worker 
2154*5e7646d2SAndroid Build Coastguard Worker   free(string);
2155*5e7646d2SAndroid Build Coastguard Worker   free(line.buffer);
2156*5e7646d2SAndroid Build Coastguard Worker 
2157*5e7646d2SAndroid Build Coastguard Worker   ppdClose(ppd);
2158*5e7646d2SAndroid Build Coastguard Worker 
2159*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2160*5e7646d2SAndroid Build Coastguard Worker }
2161*5e7646d2SAndroid Build Coastguard Worker 
2162*5e7646d2SAndroid Build Coastguard Worker 
2163*5e7646d2SAndroid Build Coastguard Worker /*
2164*5e7646d2SAndroid Build Coastguard Worker  * 'ppdOpen()' - Read a PPD file into memory.
2165*5e7646d2SAndroid Build Coastguard Worker  */
2166*5e7646d2SAndroid Build Coastguard Worker 
2167*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *				/* O - PPD file record */
ppdOpen(FILE * fp)2168*5e7646d2SAndroid Build Coastguard Worker ppdOpen(FILE *fp)			/* I - File to read from */
2169*5e7646d2SAndroid Build Coastguard Worker {
2170*5e7646d2SAndroid Build Coastguard Worker   ppd_file_t	*ppd;			/* PPD file record */
2171*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*cf;			/* CUPS file */
2172*5e7646d2SAndroid Build Coastguard Worker 
2173*5e7646d2SAndroid Build Coastguard Worker 
2174*5e7646d2SAndroid Build Coastguard Worker  /*
2175*5e7646d2SAndroid Build Coastguard Worker   * Reopen the stdio file as a CUPS file...
2176*5e7646d2SAndroid Build Coastguard Worker   */
2177*5e7646d2SAndroid Build Coastguard Worker 
2178*5e7646d2SAndroid Build Coastguard Worker   if ((cf = cupsFileOpenFd(fileno(fp), "r")) == NULL)
2179*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2180*5e7646d2SAndroid Build Coastguard Worker 
2181*5e7646d2SAndroid Build Coastguard Worker  /*
2182*5e7646d2SAndroid Build Coastguard Worker   * Load the PPD file using the newer API...
2183*5e7646d2SAndroid Build Coastguard Worker   */
2184*5e7646d2SAndroid Build Coastguard Worker 
2185*5e7646d2SAndroid Build Coastguard Worker   ppd = _ppdOpen(cf, _PPD_LOCALIZATION_DEFAULT);
2186*5e7646d2SAndroid Build Coastguard Worker 
2187*5e7646d2SAndroid Build Coastguard Worker  /*
2188*5e7646d2SAndroid Build Coastguard Worker   * Close the CUPS file and return the PPD...
2189*5e7646d2SAndroid Build Coastguard Worker   */
2190*5e7646d2SAndroid Build Coastguard Worker 
2191*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(cf);
2192*5e7646d2SAndroid Build Coastguard Worker 
2193*5e7646d2SAndroid Build Coastguard Worker   return (ppd);
2194*5e7646d2SAndroid Build Coastguard Worker }
2195*5e7646d2SAndroid Build Coastguard Worker 
2196*5e7646d2SAndroid Build Coastguard Worker 
2197*5e7646d2SAndroid Build Coastguard Worker /*
2198*5e7646d2SAndroid Build Coastguard Worker  * 'ppdOpen2()' - Read a PPD file into memory.
2199*5e7646d2SAndroid Build Coastguard Worker  *
2200*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
2201*5e7646d2SAndroid Build Coastguard Worker  */
2202*5e7646d2SAndroid Build Coastguard Worker 
2203*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *				/* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
ppdOpen2(cups_file_t * fp)2204*5e7646d2SAndroid Build Coastguard Worker ppdOpen2(cups_file_t *fp)		/* I - File to read from */
2205*5e7646d2SAndroid Build Coastguard Worker {
2206*5e7646d2SAndroid Build Coastguard Worker   return _ppdOpen(fp, _PPD_LOCALIZATION_DEFAULT);
2207*5e7646d2SAndroid Build Coastguard Worker }
2208*5e7646d2SAndroid Build Coastguard Worker 
2209*5e7646d2SAndroid Build Coastguard Worker 
2210*5e7646d2SAndroid Build Coastguard Worker /*
2211*5e7646d2SAndroid Build Coastguard Worker  * 'ppdOpenFd()' - Read a PPD file into memory.
2212*5e7646d2SAndroid Build Coastguard Worker  */
2213*5e7646d2SAndroid Build Coastguard Worker 
2214*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *				/* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
ppdOpenFd(int fd)2215*5e7646d2SAndroid Build Coastguard Worker ppdOpenFd(int fd)			/* I - File to read from */
2216*5e7646d2SAndroid Build Coastguard Worker {
2217*5e7646d2SAndroid Build Coastguard Worker   cups_file_t		*fp;		/* CUPS file pointer */
2218*5e7646d2SAndroid Build Coastguard Worker   ppd_file_t		*ppd;		/* PPD file record */
2219*5e7646d2SAndroid Build Coastguard Worker   _ppd_globals_t	*pg = _ppdGlobals();
2220*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
2221*5e7646d2SAndroid Build Coastguard Worker 
2222*5e7646d2SAndroid Build Coastguard Worker 
2223*5e7646d2SAndroid Build Coastguard Worker  /*
2224*5e7646d2SAndroid Build Coastguard Worker   * Set the line number to 0...
2225*5e7646d2SAndroid Build Coastguard Worker   */
2226*5e7646d2SAndroid Build Coastguard Worker 
2227*5e7646d2SAndroid Build Coastguard Worker   pg->ppd_line = 0;
2228*5e7646d2SAndroid Build Coastguard Worker 
2229*5e7646d2SAndroid Build Coastguard Worker  /*
2230*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2231*5e7646d2SAndroid Build Coastguard Worker   */
2232*5e7646d2SAndroid Build Coastguard Worker 
2233*5e7646d2SAndroid Build Coastguard Worker   if (fd < 0)
2234*5e7646d2SAndroid Build Coastguard Worker   {
2235*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_NULL_FILE;
2236*5e7646d2SAndroid Build Coastguard Worker 
2237*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2238*5e7646d2SAndroid Build Coastguard Worker   }
2239*5e7646d2SAndroid Build Coastguard Worker 
2240*5e7646d2SAndroid Build Coastguard Worker  /*
2241*5e7646d2SAndroid Build Coastguard Worker   * Try to open the file and parse it...
2242*5e7646d2SAndroid Build Coastguard Worker   */
2243*5e7646d2SAndroid Build Coastguard Worker 
2244*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpenFd(fd, "r")) != NULL)
2245*5e7646d2SAndroid Build Coastguard Worker   {
2246*5e7646d2SAndroid Build Coastguard Worker     ppd = ppdOpen2(fp);
2247*5e7646d2SAndroid Build Coastguard Worker 
2248*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
2249*5e7646d2SAndroid Build Coastguard Worker   }
2250*5e7646d2SAndroid Build Coastguard Worker   else
2251*5e7646d2SAndroid Build Coastguard Worker   {
2252*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_FILE_OPEN_ERROR;
2253*5e7646d2SAndroid Build Coastguard Worker     ppd            = NULL;
2254*5e7646d2SAndroid Build Coastguard Worker   }
2255*5e7646d2SAndroid Build Coastguard Worker 
2256*5e7646d2SAndroid Build Coastguard Worker   return (ppd);
2257*5e7646d2SAndroid Build Coastguard Worker }
2258*5e7646d2SAndroid Build Coastguard Worker 
2259*5e7646d2SAndroid Build Coastguard Worker 
2260*5e7646d2SAndroid Build Coastguard Worker /*
2261*5e7646d2SAndroid Build Coastguard Worker  * '_ppdOpenFile()' - Read a PPD file into memory.
2262*5e7646d2SAndroid Build Coastguard Worker  */
2263*5e7646d2SAndroid Build Coastguard Worker 
2264*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *				/* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
_ppdOpenFile(const char * filename,_ppd_localization_t localization)2265*5e7646d2SAndroid Build Coastguard Worker _ppdOpenFile(const char		  *filename,	/* I - File to read from */
2266*5e7646d2SAndroid Build Coastguard Worker 	     _ppd_localization_t  localization)	/* I - Localization to load */
2267*5e7646d2SAndroid Build Coastguard Worker {
2268*5e7646d2SAndroid Build Coastguard Worker   cups_file_t		*fp;		/* File pointer */
2269*5e7646d2SAndroid Build Coastguard Worker   ppd_file_t		*ppd;		/* PPD file record */
2270*5e7646d2SAndroid Build Coastguard Worker   _ppd_globals_t	*pg = _ppdGlobals();
2271*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
2272*5e7646d2SAndroid Build Coastguard Worker 
2273*5e7646d2SAndroid Build Coastguard Worker 
2274*5e7646d2SAndroid Build Coastguard Worker  /*
2275*5e7646d2SAndroid Build Coastguard Worker   * Set the line number to 0...
2276*5e7646d2SAndroid Build Coastguard Worker   */
2277*5e7646d2SAndroid Build Coastguard Worker 
2278*5e7646d2SAndroid Build Coastguard Worker   pg->ppd_line = 0;
2279*5e7646d2SAndroid Build Coastguard Worker 
2280*5e7646d2SAndroid Build Coastguard Worker  /*
2281*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2282*5e7646d2SAndroid Build Coastguard Worker   */
2283*5e7646d2SAndroid Build Coastguard Worker 
2284*5e7646d2SAndroid Build Coastguard Worker   if (filename == NULL)
2285*5e7646d2SAndroid Build Coastguard Worker   {
2286*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_NULL_FILE;
2287*5e7646d2SAndroid Build Coastguard Worker 
2288*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2289*5e7646d2SAndroid Build Coastguard Worker   }
2290*5e7646d2SAndroid Build Coastguard Worker 
2291*5e7646d2SAndroid Build Coastguard Worker  /*
2292*5e7646d2SAndroid Build Coastguard Worker   * Try to open the file and parse it...
2293*5e7646d2SAndroid Build Coastguard Worker   */
2294*5e7646d2SAndroid Build Coastguard Worker 
2295*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(filename, "r")) != NULL)
2296*5e7646d2SAndroid Build Coastguard Worker   {
2297*5e7646d2SAndroid Build Coastguard Worker     ppd = _ppdOpen(fp, localization);
2298*5e7646d2SAndroid Build Coastguard Worker 
2299*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
2300*5e7646d2SAndroid Build Coastguard Worker   }
2301*5e7646d2SAndroid Build Coastguard Worker   else
2302*5e7646d2SAndroid Build Coastguard Worker   {
2303*5e7646d2SAndroid Build Coastguard Worker     pg->ppd_status = PPD_FILE_OPEN_ERROR;
2304*5e7646d2SAndroid Build Coastguard Worker     ppd            = NULL;
2305*5e7646d2SAndroid Build Coastguard Worker   }
2306*5e7646d2SAndroid Build Coastguard Worker 
2307*5e7646d2SAndroid Build Coastguard Worker   return (ppd);
2308*5e7646d2SAndroid Build Coastguard Worker }
2309*5e7646d2SAndroid Build Coastguard Worker 
2310*5e7646d2SAndroid Build Coastguard Worker 
2311*5e7646d2SAndroid Build Coastguard Worker /*
2312*5e7646d2SAndroid Build Coastguard Worker  * 'ppdOpenFile()' - Read a PPD file into memory.
2313*5e7646d2SAndroid Build Coastguard Worker  */
2314*5e7646d2SAndroid Build Coastguard Worker 
2315*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *				/* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
ppdOpenFile(const char * filename)2316*5e7646d2SAndroid Build Coastguard Worker ppdOpenFile(const char *filename)	/* I - File to read from */
2317*5e7646d2SAndroid Build Coastguard Worker {
2318*5e7646d2SAndroid Build Coastguard Worker   return _ppdOpenFile(filename, _PPD_LOCALIZATION_DEFAULT);
2319*5e7646d2SAndroid Build Coastguard Worker }
2320*5e7646d2SAndroid Build Coastguard Worker 
2321*5e7646d2SAndroid Build Coastguard Worker 
2322*5e7646d2SAndroid Build Coastguard Worker /*
2323*5e7646d2SAndroid Build Coastguard Worker  * 'ppdSetConformance()' - Set the conformance level for PPD files.
2324*5e7646d2SAndroid Build Coastguard Worker  *
2325*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.20/macOS 10.4@
2326*5e7646d2SAndroid Build Coastguard Worker  */
2327*5e7646d2SAndroid Build Coastguard Worker 
2328*5e7646d2SAndroid Build Coastguard Worker void
ppdSetConformance(ppd_conform_t c)2329*5e7646d2SAndroid Build Coastguard Worker ppdSetConformance(ppd_conform_t c)	/* I - Conformance level */
2330*5e7646d2SAndroid Build Coastguard Worker {
2331*5e7646d2SAndroid Build Coastguard Worker   _ppd_globals_t	*pg = _ppdGlobals();
2332*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
2333*5e7646d2SAndroid Build Coastguard Worker 
2334*5e7646d2SAndroid Build Coastguard Worker 
2335*5e7646d2SAndroid Build Coastguard Worker   pg->ppd_conform = c;
2336*5e7646d2SAndroid Build Coastguard Worker }
2337*5e7646d2SAndroid Build Coastguard Worker 
2338*5e7646d2SAndroid Build Coastguard Worker 
2339*5e7646d2SAndroid Build Coastguard Worker /*
2340*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_add_attr()' - Add an attribute to the PPD data.
2341*5e7646d2SAndroid Build Coastguard Worker  */
2342*5e7646d2SAndroid Build Coastguard Worker 
2343*5e7646d2SAndroid Build Coastguard Worker static ppd_attr_t *			/* O - New attribute */
ppd_add_attr(ppd_file_t * ppd,const char * name,const char * spec,const char * text,const char * value)2344*5e7646d2SAndroid Build Coastguard Worker ppd_add_attr(ppd_file_t *ppd,		/* I - PPD file data */
2345*5e7646d2SAndroid Build Coastguard Worker              const char *name,		/* I - Attribute name */
2346*5e7646d2SAndroid Build Coastguard Worker              const char *spec,		/* I - Specifier string, if any */
2347*5e7646d2SAndroid Build Coastguard Worker 	     const char *text,		/* I - Text string, if any */
2348*5e7646d2SAndroid Build Coastguard Worker 	     const char *value)		/* I - Value of attribute */
2349*5e7646d2SAndroid Build Coastguard Worker {
2350*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	**ptr,			/* New array */
2351*5e7646d2SAndroid Build Coastguard Worker 		*temp;			/* New attribute */
2352*5e7646d2SAndroid Build Coastguard Worker 
2353*5e7646d2SAndroid Build Coastguard Worker 
2354*5e7646d2SAndroid Build Coastguard Worker  /*
2355*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2356*5e7646d2SAndroid Build Coastguard Worker   */
2357*5e7646d2SAndroid Build Coastguard Worker 
2358*5e7646d2SAndroid Build Coastguard Worker   if (ppd == NULL || name == NULL || spec == NULL)
2359*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2360*5e7646d2SAndroid Build Coastguard Worker 
2361*5e7646d2SAndroid Build Coastguard Worker  /*
2362*5e7646d2SAndroid Build Coastguard Worker   * Create the array as needed...
2363*5e7646d2SAndroid Build Coastguard Worker   */
2364*5e7646d2SAndroid Build Coastguard Worker 
2365*5e7646d2SAndroid Build Coastguard Worker   if (!ppd->sorted_attrs)
2366*5e7646d2SAndroid Build Coastguard Worker     ppd->sorted_attrs = cupsArrayNew((cups_array_func_t)ppd_compare_attrs,
2367*5e7646d2SAndroid Build Coastguard Worker                                      NULL);
2368*5e7646d2SAndroid Build Coastguard Worker 
2369*5e7646d2SAndroid Build Coastguard Worker  /*
2370*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory for the new attribute...
2371*5e7646d2SAndroid Build Coastguard Worker   */
2372*5e7646d2SAndroid Build Coastguard Worker 
2373*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_attrs == 0)
2374*5e7646d2SAndroid Build Coastguard Worker     ptr = malloc(sizeof(ppd_attr_t *));
2375*5e7646d2SAndroid Build Coastguard Worker   else
2376*5e7646d2SAndroid Build Coastguard Worker     ptr = realloc(ppd->attrs, (size_t)(ppd->num_attrs + 1) * sizeof(ppd_attr_t *));
2377*5e7646d2SAndroid Build Coastguard Worker 
2378*5e7646d2SAndroid Build Coastguard Worker   if (ptr == NULL)
2379*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2380*5e7646d2SAndroid Build Coastguard Worker 
2381*5e7646d2SAndroid Build Coastguard Worker   ppd->attrs = ptr;
2382*5e7646d2SAndroid Build Coastguard Worker   ptr += ppd->num_attrs;
2383*5e7646d2SAndroid Build Coastguard Worker 
2384*5e7646d2SAndroid Build Coastguard Worker   if ((temp = calloc(1, sizeof(ppd_attr_t))) == NULL)
2385*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2386*5e7646d2SAndroid Build Coastguard Worker 
2387*5e7646d2SAndroid Build Coastguard Worker   *ptr = temp;
2388*5e7646d2SAndroid Build Coastguard Worker 
2389*5e7646d2SAndroid Build Coastguard Worker   ppd->num_attrs ++;
2390*5e7646d2SAndroid Build Coastguard Worker 
2391*5e7646d2SAndroid Build Coastguard Worker  /*
2392*5e7646d2SAndroid Build Coastguard Worker   * Copy data over...
2393*5e7646d2SAndroid Build Coastguard Worker   */
2394*5e7646d2SAndroid Build Coastguard Worker 
2395*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(spec, "custom") || !_cups_strncasecmp(spec, "custom.", 7))
2396*5e7646d2SAndroid Build Coastguard Worker   {
2397*5e7646d2SAndroid Build Coastguard Worker     temp->spec[0] = '_';
2398*5e7646d2SAndroid Build Coastguard Worker     strlcpy(temp->spec + 1, spec, sizeof(temp->spec) - 1);
2399*5e7646d2SAndroid Build Coastguard Worker   }
2400*5e7646d2SAndroid Build Coastguard Worker   else {
2401*5e7646d2SAndroid Build Coastguard Worker       strlcpy(temp->spec, spec, sizeof(temp->spec));
2402*5e7646d2SAndroid Build Coastguard Worker   }
2403*5e7646d2SAndroid Build Coastguard Worker 
2404*5e7646d2SAndroid Build Coastguard Worker   strlcpy(temp->name, name, sizeof(temp->name));
2405*5e7646d2SAndroid Build Coastguard Worker   strlcpy(temp->text, text, sizeof(temp->text));
2406*5e7646d2SAndroid Build Coastguard Worker   temp->value = (char *)value;
2407*5e7646d2SAndroid Build Coastguard Worker 
2408*5e7646d2SAndroid Build Coastguard Worker  /*
2409*5e7646d2SAndroid Build Coastguard Worker   * Add the attribute to the sorted array...
2410*5e7646d2SAndroid Build Coastguard Worker   */
2411*5e7646d2SAndroid Build Coastguard Worker 
2412*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(ppd->sorted_attrs, temp);
2413*5e7646d2SAndroid Build Coastguard Worker 
2414*5e7646d2SAndroid Build Coastguard Worker  /*
2415*5e7646d2SAndroid Build Coastguard Worker   * Return the attribute...
2416*5e7646d2SAndroid Build Coastguard Worker   */
2417*5e7646d2SAndroid Build Coastguard Worker 
2418*5e7646d2SAndroid Build Coastguard Worker   return (temp);
2419*5e7646d2SAndroid Build Coastguard Worker }
2420*5e7646d2SAndroid Build Coastguard Worker 
2421*5e7646d2SAndroid Build Coastguard Worker 
2422*5e7646d2SAndroid Build Coastguard Worker /*
2423*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_add_choice()' - Add a choice to an option.
2424*5e7646d2SAndroid Build Coastguard Worker  */
2425*5e7646d2SAndroid Build Coastguard Worker 
2426*5e7646d2SAndroid Build Coastguard Worker static ppd_choice_t *			/* O - Named choice */
ppd_add_choice(ppd_option_t * option,const char * name)2427*5e7646d2SAndroid Build Coastguard Worker ppd_add_choice(ppd_option_t *option,	/* I - Option */
2428*5e7646d2SAndroid Build Coastguard Worker                const char   *name)	/* I - Name of choice */
2429*5e7646d2SAndroid Build Coastguard Worker {
2430*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*choice;		/* Choice */
2431*5e7646d2SAndroid Build Coastguard Worker 
2432*5e7646d2SAndroid Build Coastguard Worker 
2433*5e7646d2SAndroid Build Coastguard Worker   if (option->num_choices == 0)
2434*5e7646d2SAndroid Build Coastguard Worker     choice = malloc(sizeof(ppd_choice_t));
2435*5e7646d2SAndroid Build Coastguard Worker   else
2436*5e7646d2SAndroid Build Coastguard Worker     choice = realloc(option->choices, sizeof(ppd_choice_t) * (size_t)(option->num_choices + 1));
2437*5e7646d2SAndroid Build Coastguard Worker 
2438*5e7646d2SAndroid Build Coastguard Worker   if (choice == NULL)
2439*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2440*5e7646d2SAndroid Build Coastguard Worker 
2441*5e7646d2SAndroid Build Coastguard Worker   option->choices = choice;
2442*5e7646d2SAndroid Build Coastguard Worker   choice += option->num_choices;
2443*5e7646d2SAndroid Build Coastguard Worker   option->num_choices ++;
2444*5e7646d2SAndroid Build Coastguard Worker 
2445*5e7646d2SAndroid Build Coastguard Worker   memset(choice, 0, sizeof(ppd_choice_t));
2446*5e7646d2SAndroid Build Coastguard Worker   strlcpy(choice->choice, name, sizeof(choice->choice));
2447*5e7646d2SAndroid Build Coastguard Worker 
2448*5e7646d2SAndroid Build Coastguard Worker   return (choice);
2449*5e7646d2SAndroid Build Coastguard Worker }
2450*5e7646d2SAndroid Build Coastguard Worker 
2451*5e7646d2SAndroid Build Coastguard Worker 
2452*5e7646d2SAndroid Build Coastguard Worker /*
2453*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_add_size()' - Add a page size.
2454*5e7646d2SAndroid Build Coastguard Worker  */
2455*5e7646d2SAndroid Build Coastguard Worker 
2456*5e7646d2SAndroid Build Coastguard Worker static ppd_size_t *			/* O - Named size */
ppd_add_size(ppd_file_t * ppd,const char * name)2457*5e7646d2SAndroid Build Coastguard Worker ppd_add_size(ppd_file_t *ppd,		/* I - PPD file */
2458*5e7646d2SAndroid Build Coastguard Worker              const char *name)		/* I - Name of size */
2459*5e7646d2SAndroid Build Coastguard Worker {
2460*5e7646d2SAndroid Build Coastguard Worker   ppd_size_t	*size;			/* Size */
2461*5e7646d2SAndroid Build Coastguard Worker 
2462*5e7646d2SAndroid Build Coastguard Worker 
2463*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_sizes == 0)
2464*5e7646d2SAndroid Build Coastguard Worker     size = malloc(sizeof(ppd_size_t));
2465*5e7646d2SAndroid Build Coastguard Worker   else
2466*5e7646d2SAndroid Build Coastguard Worker     size = realloc(ppd->sizes, sizeof(ppd_size_t) * (size_t)(ppd->num_sizes + 1));
2467*5e7646d2SAndroid Build Coastguard Worker 
2468*5e7646d2SAndroid Build Coastguard Worker   if (size == NULL)
2469*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2470*5e7646d2SAndroid Build Coastguard Worker 
2471*5e7646d2SAndroid Build Coastguard Worker   ppd->sizes = size;
2472*5e7646d2SAndroid Build Coastguard Worker   size += ppd->num_sizes;
2473*5e7646d2SAndroid Build Coastguard Worker   ppd->num_sizes ++;
2474*5e7646d2SAndroid Build Coastguard Worker 
2475*5e7646d2SAndroid Build Coastguard Worker   memset(size, 0, sizeof(ppd_size_t));
2476*5e7646d2SAndroid Build Coastguard Worker   strlcpy(size->name, name, sizeof(size->name));
2477*5e7646d2SAndroid Build Coastguard Worker 
2478*5e7646d2SAndroid Build Coastguard Worker   return (size);
2479*5e7646d2SAndroid Build Coastguard Worker }
2480*5e7646d2SAndroid Build Coastguard Worker 
2481*5e7646d2SAndroid Build Coastguard Worker 
2482*5e7646d2SAndroid Build Coastguard Worker /*
2483*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_compare_attrs()' - Compare two attributes.
2484*5e7646d2SAndroid Build Coastguard Worker  */
2485*5e7646d2SAndroid Build Coastguard Worker 
2486*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
ppd_compare_attrs(ppd_attr_t * a,ppd_attr_t * b)2487*5e7646d2SAndroid Build Coastguard Worker ppd_compare_attrs(ppd_attr_t *a,	/* I - First attribute */
2488*5e7646d2SAndroid Build Coastguard Worker                   ppd_attr_t *b)	/* I - Second attribute */
2489*5e7646d2SAndroid Build Coastguard Worker {
2490*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(a->name, b->name));
2491*5e7646d2SAndroid Build Coastguard Worker }
2492*5e7646d2SAndroid Build Coastguard Worker 
2493*5e7646d2SAndroid Build Coastguard Worker 
2494*5e7646d2SAndroid Build Coastguard Worker /*
2495*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_compare_choices()' - Compare two choices...
2496*5e7646d2SAndroid Build Coastguard Worker  */
2497*5e7646d2SAndroid Build Coastguard Worker 
2498*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
ppd_compare_choices(ppd_choice_t * a,ppd_choice_t * b)2499*5e7646d2SAndroid Build Coastguard Worker ppd_compare_choices(ppd_choice_t *a,	/* I - First choice */
2500*5e7646d2SAndroid Build Coastguard Worker                     ppd_choice_t *b)	/* I - Second choice */
2501*5e7646d2SAndroid Build Coastguard Worker {
2502*5e7646d2SAndroid Build Coastguard Worker   return (strcmp(a->option->keyword, b->option->keyword));
2503*5e7646d2SAndroid Build Coastguard Worker }
2504*5e7646d2SAndroid Build Coastguard Worker 
2505*5e7646d2SAndroid Build Coastguard Worker 
2506*5e7646d2SAndroid Build Coastguard Worker /*
2507*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_compare_coptions()' - Compare two custom options.
2508*5e7646d2SAndroid Build Coastguard Worker  */
2509*5e7646d2SAndroid Build Coastguard Worker 
2510*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
ppd_compare_coptions(ppd_coption_t * a,ppd_coption_t * b)2511*5e7646d2SAndroid Build Coastguard Worker ppd_compare_coptions(ppd_coption_t *a,	/* I - First option */
2512*5e7646d2SAndroid Build Coastguard Worker                      ppd_coption_t *b)	/* I - Second option */
2513*5e7646d2SAndroid Build Coastguard Worker {
2514*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(a->keyword, b->keyword));
2515*5e7646d2SAndroid Build Coastguard Worker }
2516*5e7646d2SAndroid Build Coastguard Worker 
2517*5e7646d2SAndroid Build Coastguard Worker 
2518*5e7646d2SAndroid Build Coastguard Worker /*
2519*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_compare_options()' - Compare two options.
2520*5e7646d2SAndroid Build Coastguard Worker  */
2521*5e7646d2SAndroid Build Coastguard Worker 
2522*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
ppd_compare_options(ppd_option_t * a,ppd_option_t * b)2523*5e7646d2SAndroid Build Coastguard Worker ppd_compare_options(ppd_option_t *a,	/* I - First option */
2524*5e7646d2SAndroid Build Coastguard Worker                     ppd_option_t *b)	/* I - Second option */
2525*5e7646d2SAndroid Build Coastguard Worker {
2526*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(a->keyword, b->keyword));
2527*5e7646d2SAndroid Build Coastguard Worker }
2528*5e7646d2SAndroid Build Coastguard Worker 
2529*5e7646d2SAndroid Build Coastguard Worker 
2530*5e7646d2SAndroid Build Coastguard Worker /*
2531*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_decode()' - Decode a string value...
2532*5e7646d2SAndroid Build Coastguard Worker  */
2533*5e7646d2SAndroid Build Coastguard Worker 
2534*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Length of decoded string */
ppd_decode(char * string)2535*5e7646d2SAndroid Build Coastguard Worker ppd_decode(char *string)		/* I - String to decode */
2536*5e7646d2SAndroid Build Coastguard Worker {
2537*5e7646d2SAndroid Build Coastguard Worker   char	*inptr,				/* Input pointer */
2538*5e7646d2SAndroid Build Coastguard Worker 	*outptr;			/* Output pointer */
2539*5e7646d2SAndroid Build Coastguard Worker 
2540*5e7646d2SAndroid Build Coastguard Worker 
2541*5e7646d2SAndroid Build Coastguard Worker   inptr  = string;
2542*5e7646d2SAndroid Build Coastguard Worker   outptr = string;
2543*5e7646d2SAndroid Build Coastguard Worker 
2544*5e7646d2SAndroid Build Coastguard Worker   while (*inptr != '\0')
2545*5e7646d2SAndroid Build Coastguard Worker     if (*inptr == '<' && isxdigit(inptr[1] & 255))
2546*5e7646d2SAndroid Build Coastguard Worker     {
2547*5e7646d2SAndroid Build Coastguard Worker      /*
2548*5e7646d2SAndroid Build Coastguard Worker       * Convert hex to 8-bit values...
2549*5e7646d2SAndroid Build Coastguard Worker       */
2550*5e7646d2SAndroid Build Coastguard Worker 
2551*5e7646d2SAndroid Build Coastguard Worker       inptr ++;
2552*5e7646d2SAndroid Build Coastguard Worker       while (isxdigit(*inptr & 255))
2553*5e7646d2SAndroid Build Coastguard Worker       {
2554*5e7646d2SAndroid Build Coastguard Worker 	if (_cups_isalpha(*inptr))
2555*5e7646d2SAndroid Build Coastguard Worker 	  *outptr = (char)((tolower(*inptr) - 'a' + 10) << 4);
2556*5e7646d2SAndroid Build Coastguard Worker 	else
2557*5e7646d2SAndroid Build Coastguard Worker 	  *outptr = (char)((*inptr - '0') << 4);
2558*5e7646d2SAndroid Build Coastguard Worker 
2559*5e7646d2SAndroid Build Coastguard Worker 	inptr ++;
2560*5e7646d2SAndroid Build Coastguard Worker 
2561*5e7646d2SAndroid Build Coastguard Worker         if (!isxdigit(*inptr & 255))
2562*5e7646d2SAndroid Build Coastguard Worker 	  break;
2563*5e7646d2SAndroid Build Coastguard Worker 
2564*5e7646d2SAndroid Build Coastguard Worker 	if (_cups_isalpha(*inptr))
2565*5e7646d2SAndroid Build Coastguard Worker 	  *outptr |= (char)(tolower(*inptr) - 'a' + 10);
2566*5e7646d2SAndroid Build Coastguard Worker 	else
2567*5e7646d2SAndroid Build Coastguard Worker 	  *outptr |= (char)(*inptr - '0');
2568*5e7646d2SAndroid Build Coastguard Worker 
2569*5e7646d2SAndroid Build Coastguard Worker 	inptr ++;
2570*5e7646d2SAndroid Build Coastguard Worker 	outptr ++;
2571*5e7646d2SAndroid Build Coastguard Worker       }
2572*5e7646d2SAndroid Build Coastguard Worker 
2573*5e7646d2SAndroid Build Coastguard Worker       while (*inptr != '>' && *inptr != '\0')
2574*5e7646d2SAndroid Build Coastguard Worker 	inptr ++;
2575*5e7646d2SAndroid Build Coastguard Worker       while (*inptr == '>')
2576*5e7646d2SAndroid Build Coastguard Worker 	inptr ++;
2577*5e7646d2SAndroid Build Coastguard Worker     }
2578*5e7646d2SAndroid Build Coastguard Worker     else
2579*5e7646d2SAndroid Build Coastguard Worker       *outptr++ = *inptr++;
2580*5e7646d2SAndroid Build Coastguard Worker 
2581*5e7646d2SAndroid Build Coastguard Worker   *outptr = '\0';
2582*5e7646d2SAndroid Build Coastguard Worker 
2583*5e7646d2SAndroid Build Coastguard Worker   return ((int)(outptr - string));
2584*5e7646d2SAndroid Build Coastguard Worker }
2585*5e7646d2SAndroid Build Coastguard Worker 
2586*5e7646d2SAndroid Build Coastguard Worker 
2587*5e7646d2SAndroid Build Coastguard Worker /*
2588*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_free_filters()' - Free the filters array.
2589*5e7646d2SAndroid Build Coastguard Worker  */
2590*5e7646d2SAndroid Build Coastguard Worker 
2591*5e7646d2SAndroid Build Coastguard Worker static void
ppd_free_filters(ppd_file_t * ppd)2592*5e7646d2SAndroid Build Coastguard Worker ppd_free_filters(ppd_file_t *ppd)	/* I - PPD file */
2593*5e7646d2SAndroid Build Coastguard Worker {
2594*5e7646d2SAndroid Build Coastguard Worker   int	i;				/* Looping var */
2595*5e7646d2SAndroid Build Coastguard Worker   char	**filter;			/* Current filter */
2596*5e7646d2SAndroid Build Coastguard Worker 
2597*5e7646d2SAndroid Build Coastguard Worker 
2598*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_filters > 0)
2599*5e7646d2SAndroid Build Coastguard Worker   {
2600*5e7646d2SAndroid Build Coastguard Worker     for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++)
2601*5e7646d2SAndroid Build Coastguard Worker       free(*filter);
2602*5e7646d2SAndroid Build Coastguard Worker 
2603*5e7646d2SAndroid Build Coastguard Worker     free(ppd->filters);
2604*5e7646d2SAndroid Build Coastguard Worker 
2605*5e7646d2SAndroid Build Coastguard Worker     ppd->num_filters = 0;
2606*5e7646d2SAndroid Build Coastguard Worker     ppd->filters     = NULL;
2607*5e7646d2SAndroid Build Coastguard Worker   }
2608*5e7646d2SAndroid Build Coastguard Worker }
2609*5e7646d2SAndroid Build Coastguard Worker 
2610*5e7646d2SAndroid Build Coastguard Worker 
2611*5e7646d2SAndroid Build Coastguard Worker /*
2612*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_free_group()' - Free a single UI group.
2613*5e7646d2SAndroid Build Coastguard Worker  */
2614*5e7646d2SAndroid Build Coastguard Worker 
2615*5e7646d2SAndroid Build Coastguard Worker static void
ppd_free_group(ppd_group_t * group)2616*5e7646d2SAndroid Build Coastguard Worker ppd_free_group(ppd_group_t *group)	/* I - Group to free */
2617*5e7646d2SAndroid Build Coastguard Worker {
2618*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2619*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t	*option;		/* Current option */
2620*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t	*subgroup;		/* Current sub-group */
2621*5e7646d2SAndroid Build Coastguard Worker 
2622*5e7646d2SAndroid Build Coastguard Worker 
2623*5e7646d2SAndroid Build Coastguard Worker   if (group->num_options > 0)
2624*5e7646d2SAndroid Build Coastguard Worker   {
2625*5e7646d2SAndroid Build Coastguard Worker     for (i = group->num_options, option = group->options;
2626*5e7646d2SAndroid Build Coastguard Worker          i > 0;
2627*5e7646d2SAndroid Build Coastguard Worker 	 i --, option ++)
2628*5e7646d2SAndroid Build Coastguard Worker       ppd_free_option(option);
2629*5e7646d2SAndroid Build Coastguard Worker 
2630*5e7646d2SAndroid Build Coastguard Worker     free(group->options);
2631*5e7646d2SAndroid Build Coastguard Worker   }
2632*5e7646d2SAndroid Build Coastguard Worker 
2633*5e7646d2SAndroid Build Coastguard Worker   if (group->num_subgroups > 0)
2634*5e7646d2SAndroid Build Coastguard Worker   {
2635*5e7646d2SAndroid Build Coastguard Worker     for (i = group->num_subgroups, subgroup = group->subgroups;
2636*5e7646d2SAndroid Build Coastguard Worker          i > 0;
2637*5e7646d2SAndroid Build Coastguard Worker 	 i --, subgroup ++)
2638*5e7646d2SAndroid Build Coastguard Worker       ppd_free_group(subgroup);
2639*5e7646d2SAndroid Build Coastguard Worker 
2640*5e7646d2SAndroid Build Coastguard Worker     free(group->subgroups);
2641*5e7646d2SAndroid Build Coastguard Worker   }
2642*5e7646d2SAndroid Build Coastguard Worker }
2643*5e7646d2SAndroid Build Coastguard Worker 
2644*5e7646d2SAndroid Build Coastguard Worker 
2645*5e7646d2SAndroid Build Coastguard Worker /*
2646*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_free_option()' - Free a single option.
2647*5e7646d2SAndroid Build Coastguard Worker  */
2648*5e7646d2SAndroid Build Coastguard Worker 
2649*5e7646d2SAndroid Build Coastguard Worker static void
ppd_free_option(ppd_option_t * option)2650*5e7646d2SAndroid Build Coastguard Worker ppd_free_option(ppd_option_t *option)	/* I - Option to free */
2651*5e7646d2SAndroid Build Coastguard Worker {
2652*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2653*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*choice;		/* Current choice */
2654*5e7646d2SAndroid Build Coastguard Worker 
2655*5e7646d2SAndroid Build Coastguard Worker 
2656*5e7646d2SAndroid Build Coastguard Worker   if (option->num_choices > 0)
2657*5e7646d2SAndroid Build Coastguard Worker   {
2658*5e7646d2SAndroid Build Coastguard Worker     for (i = option->num_choices, choice = option->choices;
2659*5e7646d2SAndroid Build Coastguard Worker          i > 0;
2660*5e7646d2SAndroid Build Coastguard Worker          i --, choice ++)
2661*5e7646d2SAndroid Build Coastguard Worker     {
2662*5e7646d2SAndroid Build Coastguard Worker       free(choice->code);
2663*5e7646d2SAndroid Build Coastguard Worker     }
2664*5e7646d2SAndroid Build Coastguard Worker 
2665*5e7646d2SAndroid Build Coastguard Worker     free(option->choices);
2666*5e7646d2SAndroid Build Coastguard Worker   }
2667*5e7646d2SAndroid Build Coastguard Worker }
2668*5e7646d2SAndroid Build Coastguard Worker 
2669*5e7646d2SAndroid Build Coastguard Worker 
2670*5e7646d2SAndroid Build Coastguard Worker /*
2671*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_get_coption()' - Get a custom option record.
2672*5e7646d2SAndroid Build Coastguard Worker  */
2673*5e7646d2SAndroid Build Coastguard Worker 
2674*5e7646d2SAndroid Build Coastguard Worker static ppd_coption_t	*		/* O - Custom option... */
ppd_get_coption(ppd_file_t * ppd,const char * name)2675*5e7646d2SAndroid Build Coastguard Worker ppd_get_coption(ppd_file_t *ppd,	/* I - PPD file */
2676*5e7646d2SAndroid Build Coastguard Worker                 const char *name)	/* I - Name of option */
2677*5e7646d2SAndroid Build Coastguard Worker {
2678*5e7646d2SAndroid Build Coastguard Worker   ppd_coption_t	*copt;			/* New custom option */
2679*5e7646d2SAndroid Build Coastguard Worker 
2680*5e7646d2SAndroid Build Coastguard Worker 
2681*5e7646d2SAndroid Build Coastguard Worker  /*
2682*5e7646d2SAndroid Build Coastguard Worker   * See if the option already exists...
2683*5e7646d2SAndroid Build Coastguard Worker   */
2684*5e7646d2SAndroid Build Coastguard Worker 
2685*5e7646d2SAndroid Build Coastguard Worker   if ((copt = ppdFindCustomOption(ppd, name)) != NULL)
2686*5e7646d2SAndroid Build Coastguard Worker     return (copt);
2687*5e7646d2SAndroid Build Coastguard Worker 
2688*5e7646d2SAndroid Build Coastguard Worker  /*
2689*5e7646d2SAndroid Build Coastguard Worker   * Not found, so create the custom option record...
2690*5e7646d2SAndroid Build Coastguard Worker   */
2691*5e7646d2SAndroid Build Coastguard Worker 
2692*5e7646d2SAndroid Build Coastguard Worker   if ((copt = calloc(1, sizeof(ppd_coption_t))) == NULL)
2693*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2694*5e7646d2SAndroid Build Coastguard Worker 
2695*5e7646d2SAndroid Build Coastguard Worker   strlcpy(copt->keyword, name, sizeof(copt->keyword));
2696*5e7646d2SAndroid Build Coastguard Worker 
2697*5e7646d2SAndroid Build Coastguard Worker   copt->params = cupsArrayNew((cups_array_func_t)NULL, NULL);
2698*5e7646d2SAndroid Build Coastguard Worker 
2699*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(ppd->coptions, copt);
2700*5e7646d2SAndroid Build Coastguard Worker 
2701*5e7646d2SAndroid Build Coastguard Worker  /*
2702*5e7646d2SAndroid Build Coastguard Worker   * Return the new record...
2703*5e7646d2SAndroid Build Coastguard Worker   */
2704*5e7646d2SAndroid Build Coastguard Worker 
2705*5e7646d2SAndroid Build Coastguard Worker   return (copt);
2706*5e7646d2SAndroid Build Coastguard Worker }
2707*5e7646d2SAndroid Build Coastguard Worker 
2708*5e7646d2SAndroid Build Coastguard Worker 
2709*5e7646d2SAndroid Build Coastguard Worker /*
2710*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_get_cparam()' - Get a custom parameter record.
2711*5e7646d2SAndroid Build Coastguard Worker  */
2712*5e7646d2SAndroid Build Coastguard Worker 
2713*5e7646d2SAndroid Build Coastguard Worker static ppd_cparam_t *			/* O - Extended option... */
ppd_get_cparam(ppd_coption_t * opt,const char * param,const char * text)2714*5e7646d2SAndroid Build Coastguard Worker ppd_get_cparam(ppd_coption_t *opt,	/* I - PPD file */
2715*5e7646d2SAndroid Build Coastguard Worker                const char    *param,	/* I - Name of parameter */
2716*5e7646d2SAndroid Build Coastguard Worker 	       const char    *text)	/* I - Human-readable text */
2717*5e7646d2SAndroid Build Coastguard Worker {
2718*5e7646d2SAndroid Build Coastguard Worker   ppd_cparam_t	*cparam;		/* New custom parameter */
2719*5e7646d2SAndroid Build Coastguard Worker 
2720*5e7646d2SAndroid Build Coastguard Worker 
2721*5e7646d2SAndroid Build Coastguard Worker  /*
2722*5e7646d2SAndroid Build Coastguard Worker   * See if the parameter already exists...
2723*5e7646d2SAndroid Build Coastguard Worker   */
2724*5e7646d2SAndroid Build Coastguard Worker 
2725*5e7646d2SAndroid Build Coastguard Worker   if ((cparam = ppdFindCustomParam(opt, param)) != NULL)
2726*5e7646d2SAndroid Build Coastguard Worker     return (cparam);
2727*5e7646d2SAndroid Build Coastguard Worker 
2728*5e7646d2SAndroid Build Coastguard Worker  /*
2729*5e7646d2SAndroid Build Coastguard Worker   * Not found, so create the custom parameter record...
2730*5e7646d2SAndroid Build Coastguard Worker   */
2731*5e7646d2SAndroid Build Coastguard Worker 
2732*5e7646d2SAndroid Build Coastguard Worker   if ((cparam = calloc(1, sizeof(ppd_cparam_t))) == NULL)
2733*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2734*5e7646d2SAndroid Build Coastguard Worker 
2735*5e7646d2SAndroid Build Coastguard Worker   cparam->type = PPD_CUSTOM_UNKNOWN;
2736*5e7646d2SAndroid Build Coastguard Worker   strlcpy(cparam->name, param, sizeof(cparam->name));
2737*5e7646d2SAndroid Build Coastguard Worker   strlcpy(cparam->text, text[0] ? text : param, sizeof(cparam->text));
2738*5e7646d2SAndroid Build Coastguard Worker 
2739*5e7646d2SAndroid Build Coastguard Worker  /*
2740*5e7646d2SAndroid Build Coastguard Worker   * Add this record to the array...
2741*5e7646d2SAndroid Build Coastguard Worker   */
2742*5e7646d2SAndroid Build Coastguard Worker 
2743*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(opt->params, cparam);
2744*5e7646d2SAndroid Build Coastguard Worker 
2745*5e7646d2SAndroid Build Coastguard Worker  /*
2746*5e7646d2SAndroid Build Coastguard Worker   * Return the new record...
2747*5e7646d2SAndroid Build Coastguard Worker   */
2748*5e7646d2SAndroid Build Coastguard Worker 
2749*5e7646d2SAndroid Build Coastguard Worker   return (cparam);
2750*5e7646d2SAndroid Build Coastguard Worker }
2751*5e7646d2SAndroid Build Coastguard Worker 
2752*5e7646d2SAndroid Build Coastguard Worker 
2753*5e7646d2SAndroid Build Coastguard Worker /*
2754*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_get_group()' - Find or create the named group as needed.
2755*5e7646d2SAndroid Build Coastguard Worker  */
2756*5e7646d2SAndroid Build Coastguard Worker 
2757*5e7646d2SAndroid Build Coastguard Worker static ppd_group_t *			/* O - Named group */
ppd_get_group(ppd_file_t * ppd,const char * name,const char * text,_ppd_globals_t * pg,cups_encoding_t encoding)2758*5e7646d2SAndroid Build Coastguard Worker ppd_get_group(ppd_file_t      *ppd,	/* I - PPD file */
2759*5e7646d2SAndroid Build Coastguard Worker               const char      *name,	/* I - Name of group */
2760*5e7646d2SAndroid Build Coastguard Worker 	      const char      *text,	/* I - Text for group */
2761*5e7646d2SAndroid Build Coastguard Worker               _ppd_globals_t  *pg,	/* I - Global data */
2762*5e7646d2SAndroid Build Coastguard Worker 	      cups_encoding_t encoding)	/* I - Encoding of text */
2763*5e7646d2SAndroid Build Coastguard Worker {
2764*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2765*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t	*group;			/* Group */
2766*5e7646d2SAndroid Build Coastguard Worker 
2767*5e7646d2SAndroid Build Coastguard Worker 
2768*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)",
2769*5e7646d2SAndroid Build Coastguard Worker                 ppd, name, text, pg));
2770*5e7646d2SAndroid Build Coastguard Worker 
2771*5e7646d2SAndroid Build Coastguard Worker   for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
2772*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(group->name, name))
2773*5e7646d2SAndroid Build Coastguard Worker       break;
2774*5e7646d2SAndroid Build Coastguard Worker 
2775*5e7646d2SAndroid Build Coastguard Worker   if (i == 0)
2776*5e7646d2SAndroid Build Coastguard Worker   {
2777*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("8ppd_get_group: Adding group %s...", name));
2778*5e7646d2SAndroid Build Coastguard Worker 
2779*5e7646d2SAndroid Build Coastguard Worker     if (pg->ppd_conform == PPD_CONFORM_STRICT && strlen(text) >= sizeof(group->text))
2780*5e7646d2SAndroid Build Coastguard Worker     {
2781*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_ILLEGAL_TRANSLATION;
2782*5e7646d2SAndroid Build Coastguard Worker 
2783*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
2784*5e7646d2SAndroid Build Coastguard Worker     }
2785*5e7646d2SAndroid Build Coastguard Worker 
2786*5e7646d2SAndroid Build Coastguard Worker     if (ppd->num_groups == 0)
2787*5e7646d2SAndroid Build Coastguard Worker       group = malloc(sizeof(ppd_group_t));
2788*5e7646d2SAndroid Build Coastguard Worker     else
2789*5e7646d2SAndroid Build Coastguard Worker       group = realloc(ppd->groups, (size_t)(ppd->num_groups + 1) * sizeof(ppd_group_t));
2790*5e7646d2SAndroid Build Coastguard Worker 
2791*5e7646d2SAndroid Build Coastguard Worker     if (group == NULL)
2792*5e7646d2SAndroid Build Coastguard Worker     {
2793*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_ALLOC_ERROR;
2794*5e7646d2SAndroid Build Coastguard Worker 
2795*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
2796*5e7646d2SAndroid Build Coastguard Worker     }
2797*5e7646d2SAndroid Build Coastguard Worker 
2798*5e7646d2SAndroid Build Coastguard Worker     ppd->groups = group;
2799*5e7646d2SAndroid Build Coastguard Worker     group += ppd->num_groups;
2800*5e7646d2SAndroid Build Coastguard Worker     ppd->num_groups ++;
2801*5e7646d2SAndroid Build Coastguard Worker 
2802*5e7646d2SAndroid Build Coastguard Worker     memset(group, 0, sizeof(ppd_group_t));
2803*5e7646d2SAndroid Build Coastguard Worker     strlcpy(group->name, name, sizeof(group->name));
2804*5e7646d2SAndroid Build Coastguard Worker 
2805*5e7646d2SAndroid Build Coastguard Worker     cupsCharsetToUTF8((cups_utf8_t *)group->text, text,
2806*5e7646d2SAndroid Build Coastguard Worker 	               sizeof(group->text), encoding);
2807*5e7646d2SAndroid Build Coastguard Worker   }
2808*5e7646d2SAndroid Build Coastguard Worker 
2809*5e7646d2SAndroid Build Coastguard Worker   return (group);
2810*5e7646d2SAndroid Build Coastguard Worker }
2811*5e7646d2SAndroid Build Coastguard Worker 
2812*5e7646d2SAndroid Build Coastguard Worker 
2813*5e7646d2SAndroid Build Coastguard Worker /*
2814*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_get_option()' - Find or create the named option as needed.
2815*5e7646d2SAndroid Build Coastguard Worker  */
2816*5e7646d2SAndroid Build Coastguard Worker 
2817*5e7646d2SAndroid Build Coastguard Worker static ppd_option_t *			/* O - Named option */
ppd_get_option(ppd_group_t * group,const char * name)2818*5e7646d2SAndroid Build Coastguard Worker ppd_get_option(ppd_group_t *group,	/* I - Group */
2819*5e7646d2SAndroid Build Coastguard Worker                const char  *name)	/* I - Name of option */
2820*5e7646d2SAndroid Build Coastguard Worker {
2821*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2822*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t	*option;		/* Option */
2823*5e7646d2SAndroid Build Coastguard Worker 
2824*5e7646d2SAndroid Build Coastguard Worker 
2825*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7ppd_get_option(group=%p(\"%s\"), name=\"%s\")",
2826*5e7646d2SAndroid Build Coastguard Worker                 group, group->name, name));
2827*5e7646d2SAndroid Build Coastguard Worker 
2828*5e7646d2SAndroid Build Coastguard Worker   for (i = group->num_options, option = group->options; i > 0; i --, option ++)
2829*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(option->keyword, name))
2830*5e7646d2SAndroid Build Coastguard Worker       break;
2831*5e7646d2SAndroid Build Coastguard Worker 
2832*5e7646d2SAndroid Build Coastguard Worker   if (i == 0)
2833*5e7646d2SAndroid Build Coastguard Worker   {
2834*5e7646d2SAndroid Build Coastguard Worker     if (group->num_options == 0)
2835*5e7646d2SAndroid Build Coastguard Worker       option = malloc(sizeof(ppd_option_t));
2836*5e7646d2SAndroid Build Coastguard Worker     else
2837*5e7646d2SAndroid Build Coastguard Worker       option = realloc(group->options, (size_t)(group->num_options + 1) * sizeof(ppd_option_t));
2838*5e7646d2SAndroid Build Coastguard Worker 
2839*5e7646d2SAndroid Build Coastguard Worker     if (option == NULL)
2840*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
2841*5e7646d2SAndroid Build Coastguard Worker 
2842*5e7646d2SAndroid Build Coastguard Worker     group->options = option;
2843*5e7646d2SAndroid Build Coastguard Worker     option += group->num_options;
2844*5e7646d2SAndroid Build Coastguard Worker     group->num_options ++;
2845*5e7646d2SAndroid Build Coastguard Worker 
2846*5e7646d2SAndroid Build Coastguard Worker     memset(option, 0, sizeof(ppd_option_t));
2847*5e7646d2SAndroid Build Coastguard Worker     strlcpy(option->keyword, name, sizeof(option->keyword));
2848*5e7646d2SAndroid Build Coastguard Worker   }
2849*5e7646d2SAndroid Build Coastguard Worker 
2850*5e7646d2SAndroid Build Coastguard Worker   return (option);
2851*5e7646d2SAndroid Build Coastguard Worker }
2852*5e7646d2SAndroid Build Coastguard Worker 
2853*5e7646d2SAndroid Build Coastguard Worker 
2854*5e7646d2SAndroid Build Coastguard Worker /*
2855*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_globals_alloc()' - Allocate and initialize global data.
2856*5e7646d2SAndroid Build Coastguard Worker  */
2857*5e7646d2SAndroid Build Coastguard Worker 
2858*5e7646d2SAndroid Build Coastguard Worker static _ppd_globals_t *		/* O - Pointer to global data */
ppd_globals_alloc(void)2859*5e7646d2SAndroid Build Coastguard Worker ppd_globals_alloc(void)
2860*5e7646d2SAndroid Build Coastguard Worker {
2861*5e7646d2SAndroid Build Coastguard Worker   return ((_ppd_globals_t *)calloc(1, sizeof(_ppd_globals_t)));
2862*5e7646d2SAndroid Build Coastguard Worker }
2863*5e7646d2SAndroid Build Coastguard Worker 
2864*5e7646d2SAndroid Build Coastguard Worker 
2865*5e7646d2SAndroid Build Coastguard Worker /*
2866*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_globals_free()' - Free global data.
2867*5e7646d2SAndroid Build Coastguard Worker  */
2868*5e7646d2SAndroid Build Coastguard Worker 
2869*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
2870*5e7646d2SAndroid Build Coastguard Worker static void
ppd_globals_free(_ppd_globals_t * pg)2871*5e7646d2SAndroid Build Coastguard Worker ppd_globals_free(_ppd_globals_t *pg)	/* I - Pointer to global data */
2872*5e7646d2SAndroid Build Coastguard Worker {
2873*5e7646d2SAndroid Build Coastguard Worker   free(pg);
2874*5e7646d2SAndroid Build Coastguard Worker }
2875*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H || _WIN32 */
2876*5e7646d2SAndroid Build Coastguard Worker 
2877*5e7646d2SAndroid Build Coastguard Worker 
2878*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
2879*5e7646d2SAndroid Build Coastguard Worker /*
2880*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_globals_init()' - Initialize per-thread globals...
2881*5e7646d2SAndroid Build Coastguard Worker  */
2882*5e7646d2SAndroid Build Coastguard Worker 
2883*5e7646d2SAndroid Build Coastguard Worker static void
ppd_globals_init(void)2884*5e7646d2SAndroid Build Coastguard Worker ppd_globals_init(void)
2885*5e7646d2SAndroid Build Coastguard Worker {
2886*5e7646d2SAndroid Build Coastguard Worker  /*
2887*5e7646d2SAndroid Build Coastguard Worker   * Register the global data for this thread...
2888*5e7646d2SAndroid Build Coastguard Worker   */
2889*5e7646d2SAndroid Build Coastguard Worker 
2890*5e7646d2SAndroid Build Coastguard Worker   pthread_key_create(&ppd_globals_key, (void (*)(void *))ppd_globals_free);
2891*5e7646d2SAndroid Build Coastguard Worker }
2892*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
2893*5e7646d2SAndroid Build Coastguard Worker 
2894*5e7646d2SAndroid Build Coastguard Worker 
2895*5e7646d2SAndroid Build Coastguard Worker /*
2896*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_hash_option()' - Generate a hash of the option name...
2897*5e7646d2SAndroid Build Coastguard Worker  */
2898*5e7646d2SAndroid Build Coastguard Worker 
2899*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Hash index */
ppd_hash_option(ppd_option_t * option)2900*5e7646d2SAndroid Build Coastguard Worker ppd_hash_option(ppd_option_t *option)	/* I - Option */
2901*5e7646d2SAndroid Build Coastguard Worker {
2902*5e7646d2SAndroid Build Coastguard Worker   int		hash = 0;		/* Hash index */
2903*5e7646d2SAndroid Build Coastguard Worker   const char	*k;			/* Pointer into keyword */
2904*5e7646d2SAndroid Build Coastguard Worker 
2905*5e7646d2SAndroid Build Coastguard Worker 
2906*5e7646d2SAndroid Build Coastguard Worker   for (hash = option->keyword[0], k = option->keyword + 1; *k;)
2907*5e7646d2SAndroid Build Coastguard Worker     hash = (int)(33U * (unsigned)hash) + *k++;
2908*5e7646d2SAndroid Build Coastguard Worker 
2909*5e7646d2SAndroid Build Coastguard Worker   return (hash & 511);
2910*5e7646d2SAndroid Build Coastguard Worker }
2911*5e7646d2SAndroid Build Coastguard Worker 
2912*5e7646d2SAndroid Build Coastguard Worker 
2913*5e7646d2SAndroid Build Coastguard Worker /*
2914*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2915*5e7646d2SAndroid Build Coastguard Worker  *                necessary.
2916*5e7646d2SAndroid Build Coastguard Worker  */
2917*5e7646d2SAndroid Build Coastguard Worker 
2918*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Bitmask of fields read */
ppd_read(cups_file_t * fp,_ppd_line_t * line,char * keyword,char * option,char * text,char ** string,int ignoreblank,_ppd_globals_t * pg)2919*5e7646d2SAndroid Build Coastguard Worker ppd_read(cups_file_t    *fp,		/* I - File to read from */
2920*5e7646d2SAndroid Build Coastguard Worker          _ppd_line_t    *line,		/* I - Line buffer */
2921*5e7646d2SAndroid Build Coastguard Worker          char           *keyword,	/* O - Keyword from line */
2922*5e7646d2SAndroid Build Coastguard Worker 	 char           *option,	/* O - Option from line */
2923*5e7646d2SAndroid Build Coastguard Worker          char           *text,		/* O - Human-readable text from line */
2924*5e7646d2SAndroid Build Coastguard Worker 	 char           **string,	/* O - Code/string data */
2925*5e7646d2SAndroid Build Coastguard Worker          int            ignoreblank,	/* I - Ignore blank lines? */
2926*5e7646d2SAndroid Build Coastguard Worker 	 _ppd_globals_t *pg)		/* I - Global data */
2927*5e7646d2SAndroid Build Coastguard Worker {
2928*5e7646d2SAndroid Build Coastguard Worker   int		ch,			/* Character from file */
2929*5e7646d2SAndroid Build Coastguard Worker 		col,			/* Column in line */
2930*5e7646d2SAndroid Build Coastguard Worker 		colon,			/* Colon seen? */
2931*5e7646d2SAndroid Build Coastguard Worker 		endquote,		/* Waiting for an end quote */
2932*5e7646d2SAndroid Build Coastguard Worker 		mask,			/* Mask to be returned */
2933*5e7646d2SAndroid Build Coastguard Worker 		startline,		/* Start line */
2934*5e7646d2SAndroid Build Coastguard Worker 		textlen;		/* Length of text */
2935*5e7646d2SAndroid Build Coastguard Worker   char		*keyptr,		/* Keyword pointer */
2936*5e7646d2SAndroid Build Coastguard Worker 		*optptr,		/* Option pointer */
2937*5e7646d2SAndroid Build Coastguard Worker 		*textptr,		/* Text pointer */
2938*5e7646d2SAndroid Build Coastguard Worker 		*strptr,		/* Pointer into string */
2939*5e7646d2SAndroid Build Coastguard Worker 		*lineptr;		/* Current position in line buffer */
2940*5e7646d2SAndroid Build Coastguard Worker 
2941*5e7646d2SAndroid Build Coastguard Worker 
2942*5e7646d2SAndroid Build Coastguard Worker  /*
2943*5e7646d2SAndroid Build Coastguard Worker   * Now loop until we have a valid line...
2944*5e7646d2SAndroid Build Coastguard Worker   */
2945*5e7646d2SAndroid Build Coastguard Worker 
2946*5e7646d2SAndroid Build Coastguard Worker   *string   = NULL;
2947*5e7646d2SAndroid Build Coastguard Worker   col       = 0;
2948*5e7646d2SAndroid Build Coastguard Worker   startline = pg->ppd_line + 1;
2949*5e7646d2SAndroid Build Coastguard Worker 
2950*5e7646d2SAndroid Build Coastguard Worker   if (!line->buffer)
2951*5e7646d2SAndroid Build Coastguard Worker   {
2952*5e7646d2SAndroid Build Coastguard Worker     line->bufsize = 1024;
2953*5e7646d2SAndroid Build Coastguard Worker     line->buffer  = malloc(1024);
2954*5e7646d2SAndroid Build Coastguard Worker 
2955*5e7646d2SAndroid Build Coastguard Worker     if (!line->buffer)
2956*5e7646d2SAndroid Build Coastguard Worker       return (0);
2957*5e7646d2SAndroid Build Coastguard Worker   }
2958*5e7646d2SAndroid Build Coastguard Worker 
2959*5e7646d2SAndroid Build Coastguard Worker   do
2960*5e7646d2SAndroid Build Coastguard Worker   {
2961*5e7646d2SAndroid Build Coastguard Worker    /*
2962*5e7646d2SAndroid Build Coastguard Worker     * Read the line...
2963*5e7646d2SAndroid Build Coastguard Worker     */
2964*5e7646d2SAndroid Build Coastguard Worker 
2965*5e7646d2SAndroid Build Coastguard Worker     lineptr  = line->buffer;
2966*5e7646d2SAndroid Build Coastguard Worker     endquote = 0;
2967*5e7646d2SAndroid Build Coastguard Worker     colon    = 0;
2968*5e7646d2SAndroid Build Coastguard Worker 
2969*5e7646d2SAndroid Build Coastguard Worker     while ((ch = cupsFileGetChar(fp)) != EOF)
2970*5e7646d2SAndroid Build Coastguard Worker     {
2971*5e7646d2SAndroid Build Coastguard Worker       if (lineptr >= (line->buffer + line->bufsize - 1))
2972*5e7646d2SAndroid Build Coastguard Worker       {
2973*5e7646d2SAndroid Build Coastguard Worker        /*
2974*5e7646d2SAndroid Build Coastguard Worker         * Expand the line buffer...
2975*5e7646d2SAndroid Build Coastguard Worker 	*/
2976*5e7646d2SAndroid Build Coastguard Worker 
2977*5e7646d2SAndroid Build Coastguard Worker         char *temp;			/* Temporary line pointer */
2978*5e7646d2SAndroid Build Coastguard Worker 
2979*5e7646d2SAndroid Build Coastguard Worker 
2980*5e7646d2SAndroid Build Coastguard Worker         line->bufsize += 1024;
2981*5e7646d2SAndroid Build Coastguard Worker 	if (line->bufsize > 262144)
2982*5e7646d2SAndroid Build Coastguard Worker 	{
2983*5e7646d2SAndroid Build Coastguard Worker 	 /*
2984*5e7646d2SAndroid Build Coastguard Worker 	  * Don't allow lines longer than 256k!
2985*5e7646d2SAndroid Build Coastguard Worker 	  */
2986*5e7646d2SAndroid Build Coastguard Worker 
2987*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_line   = startline;
2988*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_LINE_TOO_LONG;
2989*5e7646d2SAndroid Build Coastguard Worker 
2990*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
2991*5e7646d2SAndroid Build Coastguard Worker 	}
2992*5e7646d2SAndroid Build Coastguard Worker 
2993*5e7646d2SAndroid Build Coastguard Worker         temp = realloc(line->buffer, line->bufsize);
2994*5e7646d2SAndroid Build Coastguard Worker 	if (!temp)
2995*5e7646d2SAndroid Build Coastguard Worker 	{
2996*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_line   = startline;
2997*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_LINE_TOO_LONG;
2998*5e7646d2SAndroid Build Coastguard Worker 
2999*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
3000*5e7646d2SAndroid Build Coastguard Worker 	}
3001*5e7646d2SAndroid Build Coastguard Worker 
3002*5e7646d2SAndroid Build Coastguard Worker         lineptr      = temp + (lineptr - line->buffer);
3003*5e7646d2SAndroid Build Coastguard Worker 	line->buffer = temp;
3004*5e7646d2SAndroid Build Coastguard Worker       }
3005*5e7646d2SAndroid Build Coastguard Worker 
3006*5e7646d2SAndroid Build Coastguard Worker       if (ch == '\r' || ch == '\n')
3007*5e7646d2SAndroid Build Coastguard Worker       {
3008*5e7646d2SAndroid Build Coastguard Worker        /*
3009*5e7646d2SAndroid Build Coastguard Worker 	* Line feed or carriage return...
3010*5e7646d2SAndroid Build Coastguard Worker 	*/
3011*5e7646d2SAndroid Build Coastguard Worker 
3012*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_line ++;
3013*5e7646d2SAndroid Build Coastguard Worker 	col = 0;
3014*5e7646d2SAndroid Build Coastguard Worker 
3015*5e7646d2SAndroid Build Coastguard Worker 	if (ch == '\r')
3016*5e7646d2SAndroid Build Coastguard Worker 	{
3017*5e7646d2SAndroid Build Coastguard Worker 	 /*
3018*5e7646d2SAndroid Build Coastguard Worker           * Check for a trailing line feed...
3019*5e7646d2SAndroid Build Coastguard Worker 	  */
3020*5e7646d2SAndroid Build Coastguard Worker 
3021*5e7646d2SAndroid Build Coastguard Worker 	  if ((ch = cupsFilePeekChar(fp)) == EOF)
3022*5e7646d2SAndroid Build Coastguard Worker 	  {
3023*5e7646d2SAndroid Build Coastguard Worker 	    ch = '\n';
3024*5e7646d2SAndroid Build Coastguard Worker 	    break;
3025*5e7646d2SAndroid Build Coastguard Worker 	  }
3026*5e7646d2SAndroid Build Coastguard Worker 
3027*5e7646d2SAndroid Build Coastguard Worker 	  if (ch == 0x0a)
3028*5e7646d2SAndroid Build Coastguard Worker 	    cupsFileGetChar(fp);
3029*5e7646d2SAndroid Build Coastguard Worker 	}
3030*5e7646d2SAndroid Build Coastguard Worker 
3031*5e7646d2SAndroid Build Coastguard Worker 	if (lineptr == line->buffer && ignoreblank)
3032*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Skip blank lines */
3033*5e7646d2SAndroid Build Coastguard Worker 
3034*5e7646d2SAndroid Build Coastguard Worker 	ch = '\n';
3035*5e7646d2SAndroid Build Coastguard Worker 
3036*5e7646d2SAndroid Build Coastguard Worker 	if (!endquote)			/* Continue for multi-line text */
3037*5e7646d2SAndroid Build Coastguard Worker           break;
3038*5e7646d2SAndroid Build Coastguard Worker 
3039*5e7646d2SAndroid Build Coastguard Worker 	*lineptr++ = '\n';
3040*5e7646d2SAndroid Build Coastguard Worker       }
3041*5e7646d2SAndroid Build Coastguard Worker       else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT)
3042*5e7646d2SAndroid Build Coastguard Worker       {
3043*5e7646d2SAndroid Build Coastguard Worker        /*
3044*5e7646d2SAndroid Build Coastguard Worker         * Other control characters...
3045*5e7646d2SAndroid Build Coastguard Worker 	*/
3046*5e7646d2SAndroid Build Coastguard Worker 
3047*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_line   = startline;
3048*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ILLEGAL_CHARACTER;
3049*5e7646d2SAndroid Build Coastguard Worker 
3050*5e7646d2SAndroid Build Coastguard Worker         return (0);
3051*5e7646d2SAndroid Build Coastguard Worker       }
3052*5e7646d2SAndroid Build Coastguard Worker       else if (ch != 0x1a)
3053*5e7646d2SAndroid Build Coastguard Worker       {
3054*5e7646d2SAndroid Build Coastguard Worker        /*
3055*5e7646d2SAndroid Build Coastguard Worker 	* Any other character...
3056*5e7646d2SAndroid Build Coastguard Worker 	*/
3057*5e7646d2SAndroid Build Coastguard Worker 
3058*5e7646d2SAndroid Build Coastguard Worker 	*lineptr++ = (char)ch;
3059*5e7646d2SAndroid Build Coastguard Worker 	col ++;
3060*5e7646d2SAndroid Build Coastguard Worker 
3061*5e7646d2SAndroid Build Coastguard Worker 	if (col > (PPD_MAX_LINE - 1))
3062*5e7646d2SAndroid Build Coastguard Worker 	{
3063*5e7646d2SAndroid Build Coastguard Worker 	 /*
3064*5e7646d2SAndroid Build Coastguard Worker           * Line is too long...
3065*5e7646d2SAndroid Build Coastguard Worker 	  */
3066*5e7646d2SAndroid Build Coastguard Worker 
3067*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_line   = startline;
3068*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_LINE_TOO_LONG;
3069*5e7646d2SAndroid Build Coastguard Worker 
3070*5e7646d2SAndroid Build Coastguard Worker           return (0);
3071*5e7646d2SAndroid Build Coastguard Worker 	}
3072*5e7646d2SAndroid Build Coastguard Worker 
3073*5e7646d2SAndroid Build Coastguard Worker 	if (ch == ':' && strncmp(line->buffer, "*%", 2) != 0)
3074*5e7646d2SAndroid Build Coastguard Worker 	  colon = 1;
3075*5e7646d2SAndroid Build Coastguard Worker 
3076*5e7646d2SAndroid Build Coastguard Worker 	if (ch == '\"' && colon)
3077*5e7646d2SAndroid Build Coastguard Worker 	  endquote = !endquote;
3078*5e7646d2SAndroid Build Coastguard Worker       }
3079*5e7646d2SAndroid Build Coastguard Worker     }
3080*5e7646d2SAndroid Build Coastguard Worker 
3081*5e7646d2SAndroid Build Coastguard Worker     if (endquote)
3082*5e7646d2SAndroid Build Coastguard Worker     {
3083*5e7646d2SAndroid Build Coastguard Worker      /*
3084*5e7646d2SAndroid Build Coastguard Worker       * Didn't finish this quoted string...
3085*5e7646d2SAndroid Build Coastguard Worker       */
3086*5e7646d2SAndroid Build Coastguard Worker 
3087*5e7646d2SAndroid Build Coastguard Worker       while ((ch = cupsFileGetChar(fp)) != EOF)
3088*5e7646d2SAndroid Build Coastguard Worker         if (ch == '\"')
3089*5e7646d2SAndroid Build Coastguard Worker 	  break;
3090*5e7646d2SAndroid Build Coastguard Worker 	else if (ch == '\r' || ch == '\n')
3091*5e7646d2SAndroid Build Coastguard Worker 	{
3092*5e7646d2SAndroid Build Coastguard Worker 	  pg->ppd_line ++;
3093*5e7646d2SAndroid Build Coastguard Worker 	  col = 0;
3094*5e7646d2SAndroid Build Coastguard Worker 
3095*5e7646d2SAndroid Build Coastguard Worker 	  if (ch == '\r')
3096*5e7646d2SAndroid Build Coastguard Worker 	  {
3097*5e7646d2SAndroid Build Coastguard Worker 	   /*
3098*5e7646d2SAndroid Build Coastguard Worker             * Check for a trailing line feed...
3099*5e7646d2SAndroid Build Coastguard Worker 	    */
3100*5e7646d2SAndroid Build Coastguard Worker 
3101*5e7646d2SAndroid Build Coastguard Worker 	    if ((ch = cupsFilePeekChar(fp)) == EOF)
3102*5e7646d2SAndroid Build Coastguard Worker 	      break;
3103*5e7646d2SAndroid Build Coastguard Worker 	    if (ch == 0x0a)
3104*5e7646d2SAndroid Build Coastguard Worker 	      cupsFileGetChar(fp);
3105*5e7646d2SAndroid Build Coastguard Worker 	  }
3106*5e7646d2SAndroid Build Coastguard Worker 	}
3107*5e7646d2SAndroid Build Coastguard Worker 	else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT)
3108*5e7646d2SAndroid Build Coastguard Worker 	{
3109*5e7646d2SAndroid Build Coastguard Worker 	 /*
3110*5e7646d2SAndroid Build Coastguard Worker           * Other control characters...
3111*5e7646d2SAndroid Build Coastguard Worker 	  */
3112*5e7646d2SAndroid Build Coastguard Worker 
3113*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_line   = startline;
3114*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_ILLEGAL_CHARACTER;
3115*5e7646d2SAndroid Build Coastguard Worker 
3116*5e7646d2SAndroid Build Coastguard Worker           return (0);
3117*5e7646d2SAndroid Build Coastguard Worker 	}
3118*5e7646d2SAndroid Build Coastguard Worker 	else if (ch != 0x1a)
3119*5e7646d2SAndroid Build Coastguard Worker 	{
3120*5e7646d2SAndroid Build Coastguard Worker 	  col ++;
3121*5e7646d2SAndroid Build Coastguard Worker 
3122*5e7646d2SAndroid Build Coastguard Worker 	  if (col > (PPD_MAX_LINE - 1))
3123*5e7646d2SAndroid Build Coastguard Worker 	  {
3124*5e7646d2SAndroid Build Coastguard Worker 	   /*
3125*5e7646d2SAndroid Build Coastguard Worker             * Line is too long...
3126*5e7646d2SAndroid Build Coastguard Worker 	    */
3127*5e7646d2SAndroid Build Coastguard Worker 
3128*5e7646d2SAndroid Build Coastguard Worker             pg->ppd_line   = startline;
3129*5e7646d2SAndroid Build Coastguard Worker             pg->ppd_status = PPD_LINE_TOO_LONG;
3130*5e7646d2SAndroid Build Coastguard Worker 
3131*5e7646d2SAndroid Build Coastguard Worker             return (0);
3132*5e7646d2SAndroid Build Coastguard Worker 	  }
3133*5e7646d2SAndroid Build Coastguard Worker 	}
3134*5e7646d2SAndroid Build Coastguard Worker     }
3135*5e7646d2SAndroid Build Coastguard Worker 
3136*5e7646d2SAndroid Build Coastguard Worker     if (ch != '\n')
3137*5e7646d2SAndroid Build Coastguard Worker     {
3138*5e7646d2SAndroid Build Coastguard Worker      /*
3139*5e7646d2SAndroid Build Coastguard Worker       * Didn't finish this line...
3140*5e7646d2SAndroid Build Coastguard Worker       */
3141*5e7646d2SAndroid Build Coastguard Worker 
3142*5e7646d2SAndroid Build Coastguard Worker       while ((ch = cupsFileGetChar(fp)) != EOF)
3143*5e7646d2SAndroid Build Coastguard Worker 	if (ch == '\r' || ch == '\n')
3144*5e7646d2SAndroid Build Coastguard Worker 	{
3145*5e7646d2SAndroid Build Coastguard Worker 	 /*
3146*5e7646d2SAndroid Build Coastguard Worker 	  * Line feed or carriage return...
3147*5e7646d2SAndroid Build Coastguard Worker 	  */
3148*5e7646d2SAndroid Build Coastguard Worker 
3149*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_line ++;
3150*5e7646d2SAndroid Build Coastguard Worker 	  col = 0;
3151*5e7646d2SAndroid Build Coastguard Worker 
3152*5e7646d2SAndroid Build Coastguard Worker 	  if (ch == '\r')
3153*5e7646d2SAndroid Build Coastguard Worker 	  {
3154*5e7646d2SAndroid Build Coastguard Worker 	   /*
3155*5e7646d2SAndroid Build Coastguard Worker             * Check for a trailing line feed...
3156*5e7646d2SAndroid Build Coastguard Worker 	    */
3157*5e7646d2SAndroid Build Coastguard Worker 
3158*5e7646d2SAndroid Build Coastguard Worker 	    if ((ch = cupsFilePeekChar(fp)) == EOF)
3159*5e7646d2SAndroid Build Coastguard Worker 	      break;
3160*5e7646d2SAndroid Build Coastguard Worker 	    if (ch == 0x0a)
3161*5e7646d2SAndroid Build Coastguard Worker 	      cupsFileGetChar(fp);
3162*5e7646d2SAndroid Build Coastguard Worker 	  }
3163*5e7646d2SAndroid Build Coastguard Worker 
3164*5e7646d2SAndroid Build Coastguard Worker 	  break;
3165*5e7646d2SAndroid Build Coastguard Worker 	}
3166*5e7646d2SAndroid Build Coastguard Worker 	else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT)
3167*5e7646d2SAndroid Build Coastguard Worker 	{
3168*5e7646d2SAndroid Build Coastguard Worker 	 /*
3169*5e7646d2SAndroid Build Coastguard Worker           * Other control characters...
3170*5e7646d2SAndroid Build Coastguard Worker 	  */
3171*5e7646d2SAndroid Build Coastguard Worker 
3172*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_line   = startline;
3173*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_ILLEGAL_CHARACTER;
3174*5e7646d2SAndroid Build Coastguard Worker 
3175*5e7646d2SAndroid Build Coastguard Worker           return (0);
3176*5e7646d2SAndroid Build Coastguard Worker 	}
3177*5e7646d2SAndroid Build Coastguard Worker 	else if (ch != 0x1a)
3178*5e7646d2SAndroid Build Coastguard Worker 	{
3179*5e7646d2SAndroid Build Coastguard Worker 	  col ++;
3180*5e7646d2SAndroid Build Coastguard Worker 
3181*5e7646d2SAndroid Build Coastguard Worker 	  if (col > (PPD_MAX_LINE - 1))
3182*5e7646d2SAndroid Build Coastguard Worker 	  {
3183*5e7646d2SAndroid Build Coastguard Worker 	   /*
3184*5e7646d2SAndroid Build Coastguard Worker             * Line is too long...
3185*5e7646d2SAndroid Build Coastguard Worker 	    */
3186*5e7646d2SAndroid Build Coastguard Worker 
3187*5e7646d2SAndroid Build Coastguard Worker             pg->ppd_line   = startline;
3188*5e7646d2SAndroid Build Coastguard Worker             pg->ppd_status = PPD_LINE_TOO_LONG;
3189*5e7646d2SAndroid Build Coastguard Worker 
3190*5e7646d2SAndroid Build Coastguard Worker             return (0);
3191*5e7646d2SAndroid Build Coastguard Worker 	  }
3192*5e7646d2SAndroid Build Coastguard Worker 	}
3193*5e7646d2SAndroid Build Coastguard Worker     }
3194*5e7646d2SAndroid Build Coastguard Worker 
3195*5e7646d2SAndroid Build Coastguard Worker     if (lineptr > line->buffer && lineptr[-1] == '\n')
3196*5e7646d2SAndroid Build Coastguard Worker       lineptr --;
3197*5e7646d2SAndroid Build Coastguard Worker 
3198*5e7646d2SAndroid Build Coastguard Worker     *lineptr = '\0';
3199*5e7646d2SAndroid Build Coastguard Worker 
3200*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("9ppd_read: LINE=\"%s\"", line->buffer));
3201*5e7646d2SAndroid Build Coastguard Worker 
3202*5e7646d2SAndroid Build Coastguard Worker    /*
3203*5e7646d2SAndroid Build Coastguard Worker     * The dynamically created PPDs for older style macOS
3204*5e7646d2SAndroid Build Coastguard Worker     * drivers include a large blob of data inserted as comments
3205*5e7646d2SAndroid Build Coastguard Worker     * at the end of the file.  As an optimization we can stop
3206*5e7646d2SAndroid Build Coastguard Worker     * reading the PPD when we get to the start of this data.
3207*5e7646d2SAndroid Build Coastguard Worker     */
3208*5e7646d2SAndroid Build Coastguard Worker 
3209*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(line->buffer, "*%APLWORKSET START"))
3210*5e7646d2SAndroid Build Coastguard Worker       return (0);
3211*5e7646d2SAndroid Build Coastguard Worker 
3212*5e7646d2SAndroid Build Coastguard Worker     if (ch == EOF && lineptr == line->buffer)
3213*5e7646d2SAndroid Build Coastguard Worker       return (0);
3214*5e7646d2SAndroid Build Coastguard Worker 
3215*5e7646d2SAndroid Build Coastguard Worker    /*
3216*5e7646d2SAndroid Build Coastguard Worker     * Now parse it...
3217*5e7646d2SAndroid Build Coastguard Worker     */
3218*5e7646d2SAndroid Build Coastguard Worker 
3219*5e7646d2SAndroid Build Coastguard Worker     mask    = 0;
3220*5e7646d2SAndroid Build Coastguard Worker     lineptr = line->buffer + 1;
3221*5e7646d2SAndroid Build Coastguard Worker 
3222*5e7646d2SAndroid Build Coastguard Worker     keyword[0] = '\0';
3223*5e7646d2SAndroid Build Coastguard Worker     option[0]  = '\0';
3224*5e7646d2SAndroid Build Coastguard Worker     text[0]    = '\0';
3225*5e7646d2SAndroid Build Coastguard Worker     *string    = NULL;
3226*5e7646d2SAndroid Build Coastguard Worker 
3227*5e7646d2SAndroid Build Coastguard Worker     if ((!line->buffer[0] ||		/* Blank line */
3228*5e7646d2SAndroid Build Coastguard Worker          !strncmp(line->buffer, "*%", 2) || /* Comment line */
3229*5e7646d2SAndroid Build Coastguard Worker          !strcmp(line->buffer, "*End")) && /* End of multi-line string */
3230*5e7646d2SAndroid Build Coastguard Worker         ignoreblank)			/* Ignore these? */
3231*5e7646d2SAndroid Build Coastguard Worker     {
3232*5e7646d2SAndroid Build Coastguard Worker       startline = pg->ppd_line + 1;
3233*5e7646d2SAndroid Build Coastguard Worker       continue;
3234*5e7646d2SAndroid Build Coastguard Worker     }
3235*5e7646d2SAndroid Build Coastguard Worker 
3236*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(line->buffer, "*"))	/* (Bad) comment line */
3237*5e7646d2SAndroid Build Coastguard Worker     {
3238*5e7646d2SAndroid Build Coastguard Worker       if (pg->ppd_conform == PPD_CONFORM_RELAXED)
3239*5e7646d2SAndroid Build Coastguard Worker       {
3240*5e7646d2SAndroid Build Coastguard Worker 	startline = pg->ppd_line + 1;
3241*5e7646d2SAndroid Build Coastguard Worker 	continue;
3242*5e7646d2SAndroid Build Coastguard Worker       }
3243*5e7646d2SAndroid Build Coastguard Worker       else
3244*5e7646d2SAndroid Build Coastguard Worker       {
3245*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_line   = startline;
3246*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD;
3247*5e7646d2SAndroid Build Coastguard Worker 
3248*5e7646d2SAndroid Build Coastguard Worker         return (0);
3249*5e7646d2SAndroid Build Coastguard Worker       }
3250*5e7646d2SAndroid Build Coastguard Worker     }
3251*5e7646d2SAndroid Build Coastguard Worker 
3252*5e7646d2SAndroid Build Coastguard Worker     if (line->buffer[0] != '*')		/* All lines start with an asterisk */
3253*5e7646d2SAndroid Build Coastguard Worker     {
3254*5e7646d2SAndroid Build Coastguard Worker      /*
3255*5e7646d2SAndroid Build Coastguard Worker       * Allow lines consisting of just whitespace...
3256*5e7646d2SAndroid Build Coastguard Worker       */
3257*5e7646d2SAndroid Build Coastguard Worker 
3258*5e7646d2SAndroid Build Coastguard Worker       for (lineptr = line->buffer; *lineptr; lineptr ++)
3259*5e7646d2SAndroid Build Coastguard Worker         if (*lineptr && !_cups_isspace(*lineptr))
3260*5e7646d2SAndroid Build Coastguard Worker 	  break;
3261*5e7646d2SAndroid Build Coastguard Worker 
3262*5e7646d2SAndroid Build Coastguard Worker       if (*lineptr)
3263*5e7646d2SAndroid Build Coastguard Worker       {
3264*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_MISSING_ASTERISK;
3265*5e7646d2SAndroid Build Coastguard Worker         return (0);
3266*5e7646d2SAndroid Build Coastguard Worker       }
3267*5e7646d2SAndroid Build Coastguard Worker       else if (ignoreblank)
3268*5e7646d2SAndroid Build Coastguard Worker         continue;
3269*5e7646d2SAndroid Build Coastguard Worker       else
3270*5e7646d2SAndroid Build Coastguard Worker         return (0);
3271*5e7646d2SAndroid Build Coastguard Worker     }
3272*5e7646d2SAndroid Build Coastguard Worker 
3273*5e7646d2SAndroid Build Coastguard Worker    /*
3274*5e7646d2SAndroid Build Coastguard Worker     * Get a keyword...
3275*5e7646d2SAndroid Build Coastguard Worker     */
3276*5e7646d2SAndroid Build Coastguard Worker 
3277*5e7646d2SAndroid Build Coastguard Worker     keyptr = keyword;
3278*5e7646d2SAndroid Build Coastguard Worker 
3279*5e7646d2SAndroid Build Coastguard Worker     while (*lineptr && *lineptr != ':' && !_cups_isspace(*lineptr))
3280*5e7646d2SAndroid Build Coastguard Worker     {
3281*5e7646d2SAndroid Build Coastguard Worker       if (*lineptr <= ' ' || *lineptr > 126 || *lineptr == '/' ||
3282*5e7646d2SAndroid Build Coastguard Worker           (keyptr - keyword) >= (PPD_MAX_NAME - 1))
3283*5e7646d2SAndroid Build Coastguard Worker       {
3284*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD;
3285*5e7646d2SAndroid Build Coastguard Worker 	return (0);
3286*5e7646d2SAndroid Build Coastguard Worker       }
3287*5e7646d2SAndroid Build Coastguard Worker 
3288*5e7646d2SAndroid Build Coastguard Worker       *keyptr++ = *lineptr++;
3289*5e7646d2SAndroid Build Coastguard Worker     }
3290*5e7646d2SAndroid Build Coastguard Worker 
3291*5e7646d2SAndroid Build Coastguard Worker     *keyptr = '\0';
3292*5e7646d2SAndroid Build Coastguard Worker 
3293*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(keyword, "End"))
3294*5e7646d2SAndroid Build Coastguard Worker       continue;
3295*5e7646d2SAndroid Build Coastguard Worker 
3296*5e7646d2SAndroid Build Coastguard Worker     mask |= PPD_KEYWORD;
3297*5e7646d2SAndroid Build Coastguard Worker 
3298*5e7646d2SAndroid Build Coastguard Worker     if (_cups_isspace(*lineptr))
3299*5e7646d2SAndroid Build Coastguard Worker     {
3300*5e7646d2SAndroid Build Coastguard Worker      /*
3301*5e7646d2SAndroid Build Coastguard Worker       * Get an option name...
3302*5e7646d2SAndroid Build Coastguard Worker       */
3303*5e7646d2SAndroid Build Coastguard Worker 
3304*5e7646d2SAndroid Build Coastguard Worker       while (_cups_isspace(*lineptr))
3305*5e7646d2SAndroid Build Coastguard Worker         lineptr ++;
3306*5e7646d2SAndroid Build Coastguard Worker 
3307*5e7646d2SAndroid Build Coastguard Worker       optptr = option;
3308*5e7646d2SAndroid Build Coastguard Worker 
3309*5e7646d2SAndroid Build Coastguard Worker       while (*lineptr && !_cups_isspace(*lineptr) && *lineptr != ':' &&
3310*5e7646d2SAndroid Build Coastguard Worker              *lineptr != '/')
3311*5e7646d2SAndroid Build Coastguard Worker       {
3312*5e7646d2SAndroid Build Coastguard Worker 	if (*lineptr <= ' ' || *lineptr > 126 ||
3313*5e7646d2SAndroid Build Coastguard Worker 	    (optptr - option) >= (PPD_MAX_NAME - 1))
3314*5e7646d2SAndroid Build Coastguard Worker         {
3315*5e7646d2SAndroid Build Coastguard Worker           pg->ppd_status = PPD_ILLEGAL_OPTION_KEYWORD;
3316*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
3317*5e7646d2SAndroid Build Coastguard Worker 	}
3318*5e7646d2SAndroid Build Coastguard Worker 
3319*5e7646d2SAndroid Build Coastguard Worker         *optptr++ = *lineptr++;
3320*5e7646d2SAndroid Build Coastguard Worker       }
3321*5e7646d2SAndroid Build Coastguard Worker 
3322*5e7646d2SAndroid Build Coastguard Worker       *optptr = '\0';
3323*5e7646d2SAndroid Build Coastguard Worker 
3324*5e7646d2SAndroid Build Coastguard Worker       if (_cups_isspace(*lineptr) && pg->ppd_conform == PPD_CONFORM_STRICT)
3325*5e7646d2SAndroid Build Coastguard Worker       {
3326*5e7646d2SAndroid Build Coastguard Worker         pg->ppd_status = PPD_ILLEGAL_WHITESPACE;
3327*5e7646d2SAndroid Build Coastguard Worker 	return (0);
3328*5e7646d2SAndroid Build Coastguard Worker       }
3329*5e7646d2SAndroid Build Coastguard Worker 
3330*5e7646d2SAndroid Build Coastguard Worker       while (_cups_isspace(*lineptr))
3331*5e7646d2SAndroid Build Coastguard Worker 	lineptr ++;
3332*5e7646d2SAndroid Build Coastguard Worker 
3333*5e7646d2SAndroid Build Coastguard Worker       mask |= PPD_OPTION;
3334*5e7646d2SAndroid Build Coastguard Worker 
3335*5e7646d2SAndroid Build Coastguard Worker       if (*lineptr == '/')
3336*5e7646d2SAndroid Build Coastguard Worker       {
3337*5e7646d2SAndroid Build Coastguard Worker        /*
3338*5e7646d2SAndroid Build Coastguard Worker         * Get human-readable text...
3339*5e7646d2SAndroid Build Coastguard Worker 	*/
3340*5e7646d2SAndroid Build Coastguard Worker 
3341*5e7646d2SAndroid Build Coastguard Worker         lineptr ++;
3342*5e7646d2SAndroid Build Coastguard Worker 
3343*5e7646d2SAndroid Build Coastguard Worker 	textptr = text;
3344*5e7646d2SAndroid Build Coastguard Worker 
3345*5e7646d2SAndroid Build Coastguard Worker 	while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':')
3346*5e7646d2SAndroid Build Coastguard Worker 	{
3347*5e7646d2SAndroid Build Coastguard Worker 	  if (((unsigned char)*lineptr < ' ' && *lineptr != '\t') ||
3348*5e7646d2SAndroid Build Coastguard Worker 	      (textptr - text) >= (PPD_MAX_LINE - 1))
3349*5e7646d2SAndroid Build Coastguard Worker 	  {
3350*5e7646d2SAndroid Build Coastguard Worker 	    pg->ppd_status = PPD_ILLEGAL_TRANSLATION;
3351*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
3352*5e7646d2SAndroid Build Coastguard Worker 	  }
3353*5e7646d2SAndroid Build Coastguard Worker 
3354*5e7646d2SAndroid Build Coastguard Worker 	  *textptr++ = *lineptr++;
3355*5e7646d2SAndroid Build Coastguard Worker         }
3356*5e7646d2SAndroid Build Coastguard Worker 
3357*5e7646d2SAndroid Build Coastguard Worker 	*textptr = '\0';
3358*5e7646d2SAndroid Build Coastguard Worker 	textlen  = ppd_decode(text);
3359*5e7646d2SAndroid Build Coastguard Worker 
3360*5e7646d2SAndroid Build Coastguard Worker 	if (textlen > PPD_MAX_TEXT && pg->ppd_conform == PPD_CONFORM_STRICT)
3361*5e7646d2SAndroid Build Coastguard Worker 	{
3362*5e7646d2SAndroid Build Coastguard Worker 	  pg->ppd_status = PPD_ILLEGAL_TRANSLATION;
3363*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
3364*5e7646d2SAndroid Build Coastguard Worker 	}
3365*5e7646d2SAndroid Build Coastguard Worker 
3366*5e7646d2SAndroid Build Coastguard Worker 	mask |= PPD_TEXT;
3367*5e7646d2SAndroid Build Coastguard Worker       }
3368*5e7646d2SAndroid Build Coastguard Worker     }
3369*5e7646d2SAndroid Build Coastguard Worker 
3370*5e7646d2SAndroid Build Coastguard Worker     if (_cups_isspace(*lineptr) && pg->ppd_conform == PPD_CONFORM_STRICT)
3371*5e7646d2SAndroid Build Coastguard Worker     {
3372*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_ILLEGAL_WHITESPACE;
3373*5e7646d2SAndroid Build Coastguard Worker       return (0);
3374*5e7646d2SAndroid Build Coastguard Worker     }
3375*5e7646d2SAndroid Build Coastguard Worker 
3376*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*lineptr))
3377*5e7646d2SAndroid Build Coastguard Worker       lineptr ++;
3378*5e7646d2SAndroid Build Coastguard Worker 
3379*5e7646d2SAndroid Build Coastguard Worker     if (*lineptr == ':')
3380*5e7646d2SAndroid Build Coastguard Worker     {
3381*5e7646d2SAndroid Build Coastguard Worker      /*
3382*5e7646d2SAndroid Build Coastguard Worker       * Get string after triming leading and trailing whitespace...
3383*5e7646d2SAndroid Build Coastguard Worker       */
3384*5e7646d2SAndroid Build Coastguard Worker 
3385*5e7646d2SAndroid Build Coastguard Worker       lineptr ++;
3386*5e7646d2SAndroid Build Coastguard Worker       while (_cups_isspace(*lineptr))
3387*5e7646d2SAndroid Build Coastguard Worker         lineptr ++;
3388*5e7646d2SAndroid Build Coastguard Worker 
3389*5e7646d2SAndroid Build Coastguard Worker       strptr = lineptr + strlen(lineptr) - 1;
3390*5e7646d2SAndroid Build Coastguard Worker       while (strptr >= lineptr && _cups_isspace(*strptr))
3391*5e7646d2SAndroid Build Coastguard Worker         *strptr-- = '\0';
3392*5e7646d2SAndroid Build Coastguard Worker 
3393*5e7646d2SAndroid Build Coastguard Worker       if (*strptr == '\"')
3394*5e7646d2SAndroid Build Coastguard Worker       {
3395*5e7646d2SAndroid Build Coastguard Worker        /*
3396*5e7646d2SAndroid Build Coastguard Worker         * Quoted string by itself, remove quotes...
3397*5e7646d2SAndroid Build Coastguard Worker 	*/
3398*5e7646d2SAndroid Build Coastguard Worker 
3399*5e7646d2SAndroid Build Coastguard Worker         *strptr = '\0';
3400*5e7646d2SAndroid Build Coastguard Worker 	lineptr ++;
3401*5e7646d2SAndroid Build Coastguard Worker       }
3402*5e7646d2SAndroid Build Coastguard Worker 
3403*5e7646d2SAndroid Build Coastguard Worker       *string = strdup(lineptr);
3404*5e7646d2SAndroid Build Coastguard Worker 
3405*5e7646d2SAndroid Build Coastguard Worker       mask |= PPD_STRING;
3406*5e7646d2SAndroid Build Coastguard Worker     }
3407*5e7646d2SAndroid Build Coastguard Worker   }
3408*5e7646d2SAndroid Build Coastguard Worker   while (mask == 0);
3409*5e7646d2SAndroid Build Coastguard Worker 
3410*5e7646d2SAndroid Build Coastguard Worker   return (mask);
3411*5e7646d2SAndroid Build Coastguard Worker }
3412*5e7646d2SAndroid Build Coastguard Worker 
3413*5e7646d2SAndroid Build Coastguard Worker 
3414*5e7646d2SAndroid Build Coastguard Worker /*
3415*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_update_filters()' - Update the filters array as needed.
3416*5e7646d2SAndroid Build Coastguard Worker  *
3417*5e7646d2SAndroid Build Coastguard Worker  * This function re-populates the filters array with cupsFilter2 entries that
3418*5e7646d2SAndroid Build Coastguard Worker  * have been stripped of the destination MIME media types and any maxsize hints.
3419*5e7646d2SAndroid Build Coastguard Worker  *
3420*5e7646d2SAndroid Build Coastguard Worker  * (All for backwards-compatibility)
3421*5e7646d2SAndroid Build Coastguard Worker  */
3422*5e7646d2SAndroid Build Coastguard Worker 
3423*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on success, 0 on failure */
ppd_update_filters(ppd_file_t * ppd,_ppd_globals_t * pg)3424*5e7646d2SAndroid Build Coastguard Worker ppd_update_filters(ppd_file_t     *ppd,	/* I - PPD file */
3425*5e7646d2SAndroid Build Coastguard Worker                    _ppd_globals_t *pg)	/* I - Global data */
3426*5e7646d2SAndroid Build Coastguard Worker {
3427*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	*attr;			/* Current cupsFilter2 value */
3428*5e7646d2SAndroid Build Coastguard Worker   char		srcsuper[16],		/* Source MIME media type */
3429*5e7646d2SAndroid Build Coastguard Worker 		srctype[256],
3430*5e7646d2SAndroid Build Coastguard Worker 		dstsuper[16],		/* Destination MIME media type */
3431*5e7646d2SAndroid Build Coastguard Worker 		dsttype[256],
3432*5e7646d2SAndroid Build Coastguard Worker 		program[1024],		/* Command to run */
3433*5e7646d2SAndroid Build Coastguard Worker 		*ptr,			/* Pointer into command to run */
3434*5e7646d2SAndroid Build Coastguard Worker 		buffer[1024],		/* Re-written cupsFilter value */
3435*5e7646d2SAndroid Build Coastguard Worker 		**filter;		/* Current filter */
3436*5e7646d2SAndroid Build Coastguard Worker   int		cost;			/* Cost of filter */
3437*5e7646d2SAndroid Build Coastguard Worker 
3438*5e7646d2SAndroid Build Coastguard Worker 
3439*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4ppd_update_filters(ppd=%p, cg=%p)", ppd, pg));
3440*5e7646d2SAndroid Build Coastguard Worker 
3441*5e7646d2SAndroid Build Coastguard Worker  /*
3442*5e7646d2SAndroid Build Coastguard Worker   * See if we have any cupsFilter2 lines...
3443*5e7646d2SAndroid Build Coastguard Worker   */
3444*5e7646d2SAndroid Build Coastguard Worker 
3445*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) == NULL)
3446*5e7646d2SAndroid Build Coastguard Worker   {
3447*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("5ppd_update_filters: No cupsFilter2 keywords present.");
3448*5e7646d2SAndroid Build Coastguard Worker     return (1);
3449*5e7646d2SAndroid Build Coastguard Worker   }
3450*5e7646d2SAndroid Build Coastguard Worker 
3451*5e7646d2SAndroid Build Coastguard Worker  /*
3452*5e7646d2SAndroid Build Coastguard Worker   * Yes, free the cupsFilter-defined filters and re-build...
3453*5e7646d2SAndroid Build Coastguard Worker   */
3454*5e7646d2SAndroid Build Coastguard Worker 
3455*5e7646d2SAndroid Build Coastguard Worker   ppd_free_filters(ppd);
3456*5e7646d2SAndroid Build Coastguard Worker 
3457*5e7646d2SAndroid Build Coastguard Worker   do
3458*5e7646d2SAndroid Build Coastguard Worker   {
3459*5e7646d2SAndroid Build Coastguard Worker    /*
3460*5e7646d2SAndroid Build Coastguard Worker     * Parse the cupsFilter2 string:
3461*5e7646d2SAndroid Build Coastguard Worker     *
3462*5e7646d2SAndroid Build Coastguard Worker     *   src/type dst/type cost program
3463*5e7646d2SAndroid Build Coastguard Worker     *   src/type dst/type cost maxsize(n) program
3464*5e7646d2SAndroid Build Coastguard Worker     */
3465*5e7646d2SAndroid Build Coastguard Worker 
3466*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("5ppd_update_filters: cupsFilter2=\"%s\"", attr->value));
3467*5e7646d2SAndroid Build Coastguard Worker 
3468*5e7646d2SAndroid Build Coastguard Worker     if (sscanf(attr->value, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
3469*5e7646d2SAndroid Build Coastguard Worker 	       srcsuper, srctype, dstsuper, dsttype, &cost, program) != 6)
3470*5e7646d2SAndroid Build Coastguard Worker     {
3471*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("5ppd_update_filters: Bad cupsFilter2 line.");
3472*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_BAD_VALUE;
3473*5e7646d2SAndroid Build Coastguard Worker 
3474*5e7646d2SAndroid Build Coastguard Worker       return (0);
3475*5e7646d2SAndroid Build Coastguard Worker     }
3476*5e7646d2SAndroid Build Coastguard Worker 
3477*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("5ppd_update_filters: srcsuper=\"%s\", srctype=\"%s\", "
3478*5e7646d2SAndroid Build Coastguard Worker                   "dstsuper=\"%s\", dsttype=\"%s\", cost=%d, program=\"%s\"",
3479*5e7646d2SAndroid Build Coastguard Worker 		  srcsuper, srctype, dstsuper, dsttype, cost, program));
3480*5e7646d2SAndroid Build Coastguard Worker 
3481*5e7646d2SAndroid Build Coastguard Worker     if (!strncmp(program, "maxsize(", 8) &&
3482*5e7646d2SAndroid Build Coastguard Worker         (ptr = strchr(program + 8, ')')) != NULL)
3483*5e7646d2SAndroid Build Coastguard Worker     {
3484*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("5ppd_update_filters: Found maxsize(nnn).");
3485*5e7646d2SAndroid Build Coastguard Worker 
3486*5e7646d2SAndroid Build Coastguard Worker       ptr ++;
3487*5e7646d2SAndroid Build Coastguard Worker       while (_cups_isspace(*ptr))
3488*5e7646d2SAndroid Build Coastguard Worker 	ptr ++;
3489*5e7646d2SAndroid Build Coastguard Worker 
3490*5e7646d2SAndroid Build Coastguard Worker       _cups_strcpy(program, ptr);
3491*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("5ppd_update_filters: New program=\"%s\"", program));
3492*5e7646d2SAndroid Build Coastguard Worker     }
3493*5e7646d2SAndroid Build Coastguard Worker 
3494*5e7646d2SAndroid Build Coastguard Worker    /*
3495*5e7646d2SAndroid Build Coastguard Worker     * Convert to cupsFilter format:
3496*5e7646d2SAndroid Build Coastguard Worker     *
3497*5e7646d2SAndroid Build Coastguard Worker     *   src/type cost program
3498*5e7646d2SAndroid Build Coastguard Worker     */
3499*5e7646d2SAndroid Build Coastguard Worker 
3500*5e7646d2SAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer), "%s/%s %d %s", srcsuper, srctype, cost,
3501*5e7646d2SAndroid Build Coastguard Worker              program);
3502*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("5ppd_update_filters: Adding \"%s\".", buffer));
3503*5e7646d2SAndroid Build Coastguard Worker 
3504*5e7646d2SAndroid Build Coastguard Worker    /*
3505*5e7646d2SAndroid Build Coastguard Worker     * Add a cupsFilter-compatible string to the filters array.
3506*5e7646d2SAndroid Build Coastguard Worker     */
3507*5e7646d2SAndroid Build Coastguard Worker 
3508*5e7646d2SAndroid Build Coastguard Worker     if (ppd->num_filters == 0)
3509*5e7646d2SAndroid Build Coastguard Worker       filter = malloc(sizeof(char *));
3510*5e7646d2SAndroid Build Coastguard Worker     else
3511*5e7646d2SAndroid Build Coastguard Worker       filter = realloc(ppd->filters, sizeof(char *) * (size_t)(ppd->num_filters + 1));
3512*5e7646d2SAndroid Build Coastguard Worker 
3513*5e7646d2SAndroid Build Coastguard Worker     if (filter == NULL)
3514*5e7646d2SAndroid Build Coastguard Worker     {
3515*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("5ppd_update_filters: Out of memory.");
3516*5e7646d2SAndroid Build Coastguard Worker       pg->ppd_status = PPD_ALLOC_ERROR;
3517*5e7646d2SAndroid Build Coastguard Worker 
3518*5e7646d2SAndroid Build Coastguard Worker       return (0);
3519*5e7646d2SAndroid Build Coastguard Worker     }
3520*5e7646d2SAndroid Build Coastguard Worker 
3521*5e7646d2SAndroid Build Coastguard Worker     ppd->filters     = filter;
3522*5e7646d2SAndroid Build Coastguard Worker     filter           += ppd->num_filters;
3523*5e7646d2SAndroid Build Coastguard Worker     ppd->num_filters ++;
3524*5e7646d2SAndroid Build Coastguard Worker 
3525*5e7646d2SAndroid Build Coastguard Worker     *filter = strdup(buffer);
3526*5e7646d2SAndroid Build Coastguard Worker   }
3527*5e7646d2SAndroid Build Coastguard Worker   while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
3528*5e7646d2SAndroid Build Coastguard Worker 
3529*5e7646d2SAndroid Build Coastguard Worker   DEBUG_puts("5ppd_update_filters: Completed OK.");
3530*5e7646d2SAndroid Build Coastguard Worker   return (1);
3531*5e7646d2SAndroid Build Coastguard Worker }
3532