2 * "$Id: ppd.c 9900 2011-08-17 20:59:46Z mike $"
4 * PPD file routines for CUPS.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * PostScript is a trademark of Adobe Systems, Inc.
17 * This code and any derivative of it may be used and distributed
18 * freely under the terms of the GNU General Public License when
19 * used with GNU Ghostscript or its derivatives. Use of the code
20 * (or any derivative of it) with software other than GNU
21 * GhostScript (or its derivatives) is governed by the CUPS license
24 * This file is subject to the Apple OS-Developed Software exception.
28 * ppdClose() - Free all memory used by the PPD file.
29 * ppdErrorString() - Returns the text assocated with a status.
30 * _ppdGetEncoding() - Get the CUPS encoding value for the given
32 * ppdLastError() - Return the status from the last ppdOpen*().
33 * ppdOpen() - Read a PPD file into memory.
34 * ppdOpen2() - Read a PPD file into memory.
35 * ppdOpenFd() - Read a PPD file into memory.
36 * ppdOpenFile() - Read a PPD file into memory.
37 * ppdSetConformance() - Set the conformance level for PPD files.
38 * ppd_add_attr() - Add an attribute to the PPD data.
39 * ppd_add_choice() - Add a choice to an option.
40 * ppd_add_size() - Add a page size.
41 * ppd_compare_attrs() - Compare two attributes.
42 * ppd_compare_choices() - Compare two choices...
43 * ppd_compare_coptions() - Compare two custom options.
44 * ppd_compare_options() - Compare two options.
45 * ppd_decode() - Decode a string value...
46 * ppd_free_filters() - Free the filters array.
47 * ppd_free_group() - Free a single UI group.
48 * ppd_free_option() - Free a single option.
49 * ppd_get_coption() - Get a custom option record.
50 * ppd_get_cparam() - Get a custom parameter record.
51 * ppd_get_group() - Find or create the named group as needed.
52 * ppd_get_option() - Find or create the named option as needed.
53 * ppd_hash_option() - Generate a hash of the option name...
54 * ppd_read() - Read a line from a PPD file, skipping comment
56 * ppd_update_filters() - Update the filters array as needed.
60 * Include necessary headers.
63 #include "cups-private.h"
64 #include "ppd-private.h"
71 #if defined(WIN32) || defined(__EMX__)
72 # define READ_BINARY "rb" /* Open a binary file for reading */
73 # define WRITE_BINARY "wb" /* Open a binary file for writing */
75 # define READ_BINARY "r" /* Open a binary file for reading */
76 # define WRITE_BINARY "w" /* Open a binary file for writing */
77 #endif /* WIN32 || __EMX__ */
79 #define ppd_free(p) if (p) free(p) /* Safe free macro */
81 #define PPD_KEYWORD 1 /* Line contained a keyword */
82 #define PPD_OPTION 2 /* Line contained an option name */
83 #define PPD_TEXT 4 /* Line contained human-readable text */
84 #define PPD_STRING 8 /* Line contained a string or code */
86 #define PPD_HASHSIZE 512 /* Size of hash */
90 * Line buffer structure...
93 typedef struct _ppd_line_s
95 char *buffer
; /* Pointer to buffer */
96 size_t bufsize
; /* Size of the buffer */
104 static ppd_attr_t
*ppd_add_attr(ppd_file_t
*ppd
, const char *name
,
105 const char *spec
, const char *text
,
107 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, const char *name
);
108 static ppd_size_t
*ppd_add_size(ppd_file_t
*ppd
, const char *name
);
109 static int ppd_compare_attrs(ppd_attr_t
*a
, ppd_attr_t
*b
);
110 static int ppd_compare_choices(ppd_choice_t
*a
, ppd_choice_t
*b
);
111 static int ppd_compare_coptions(ppd_coption_t
*a
,
113 static int ppd_compare_options(ppd_option_t
*a
, ppd_option_t
*b
);
114 static int ppd_decode(char *string
);
115 static void ppd_free_filters(ppd_file_t
*ppd
);
116 static void ppd_free_group(ppd_group_t
*group
);
117 static void ppd_free_option(ppd_option_t
*option
);
118 static ppd_coption_t
*ppd_get_coption(ppd_file_t
*ppd
, const char *name
);
119 static ppd_cparam_t
*ppd_get_cparam(ppd_coption_t
*opt
,
122 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, const char *name
,
123 const char *text
, _cups_globals_t
*cg
,
124 cups_encoding_t encoding
);
125 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, const char *name
);
126 static int ppd_hash_option(ppd_option_t
*option
);
127 static int ppd_read(cups_file_t
*fp
, _ppd_line_t
*line
,
128 char *keyword
, char *option
, char *text
,
129 char **string
, int ignoreblank
,
130 _cups_globals_t
*cg
);
131 static int ppd_update_filters(ppd_file_t
*ppd
,
132 _cups_globals_t
*cg
);
136 * 'ppdClose()' - Free all memory used by the PPD file.
140 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
142 int i
; /* Looping var */
143 ppd_emul_t
*emul
; /* Current emulation */
144 ppd_group_t
*group
; /* Current group */
145 char **font
; /* Current font */
146 ppd_attr_t
**attr
; /* Current attribute */
147 ppd_coption_t
*coption
; /* Current custom option */
148 ppd_cparam_t
*cparam
; /* Current custom parameter */
152 * Range check arguments...
159 * Free all strings at the top level...
162 _cupsStrFree(ppd
->lang_encoding
);
163 _cupsStrFree(ppd
->nickname
);
166 _cupsStrFree(ppd
->jcl_begin
);
167 _cupsStrFree(ppd
->jcl_end
);
168 _cupsStrFree(ppd
->jcl_ps
);
171 * Free any emulations...
174 if (ppd
->num_emulations
> 0)
176 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
178 _cupsStrFree(emul
->start
);
179 _cupsStrFree(emul
->stop
);
182 ppd_free(ppd
->emulations
);
186 * Free any UI groups, subgroups, and options...
189 if (ppd
->num_groups
> 0)
191 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
192 ppd_free_group(group
);
194 ppd_free(ppd
->groups
);
197 cupsArrayDelete(ppd
->options
);
198 cupsArrayDelete(ppd
->marked
);
201 * Free any page sizes...
204 if (ppd
->num_sizes
> 0)
205 ppd_free(ppd
->sizes
);
208 * Free any constraints...
211 if (ppd
->num_consts
> 0)
212 ppd_free(ppd
->consts
);
215 * Free any filters...
218 ppd_free_filters(ppd
);
224 if (ppd
->num_fonts
> 0)
226 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
229 ppd_free(ppd
->fonts
);
233 * Free any profiles...
236 if (ppd
->num_profiles
> 0)
237 ppd_free(ppd
->profiles
);
240 * Free any attributes...
243 if (ppd
->num_attrs
> 0)
245 for (i
= ppd
->num_attrs
, attr
= ppd
->attrs
; i
> 0; i
--, attr
++)
247 _cupsStrFree((*attr
)->value
);
251 ppd_free(ppd
->attrs
);
254 cupsArrayDelete(ppd
->sorted_attrs
);
257 * Free custom options...
260 for (coption
= (ppd_coption_t
*)cupsArrayFirst(ppd
->coptions
);
262 coption
= (ppd_coption_t
*)cupsArrayNext(ppd
->coptions
))
264 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
266 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
268 switch (cparam
->type
)
270 case PPD_CUSTOM_PASSCODE
:
271 case PPD_CUSTOM_PASSWORD
:
272 case PPD_CUSTOM_STRING
:
273 _cupsStrFree(cparam
->current
.custom_string
);
283 cupsArrayDelete(coption
->params
);
288 cupsArrayDelete(ppd
->coptions
);
291 * Free constraints...
294 if (ppd
->cups_uiconstraints
)
296 _ppd_cups_uiconsts_t
*consts
; /* Current constraints */
299 for (consts
= (_ppd_cups_uiconsts_t
*)cupsArrayFirst(ppd
->cups_uiconstraints
);
301 consts
= (_ppd_cups_uiconsts_t
*)cupsArrayNext(ppd
->cups_uiconstraints
))
303 free(consts
->constraints
);
307 cupsArrayDelete(ppd
->cups_uiconstraints
);
311 * Free any PPD cache/mapping data...
315 _ppdCacheDestroy(ppd
->cache
);
318 * Free the whole record...
326 * 'ppdErrorString()' - Returns the text assocated with a status.
328 * @since CUPS 1.1.19/Mac OS X 10.3@
331 const char * /* O - Status string */
332 ppdErrorString(ppd_status_t status
) /* I - PPD status */
334 static const char * const messages
[] =/* Status messages */
337 _("Unable to open PPD file"),
338 _("NULL PPD file pointer"),
339 _("Memory allocation error"),
340 _("Missing PPD-Adobe-4.x header"),
341 _("Missing value string"),
344 _("OpenGroup without a CloseGroup first"),
345 _("Bad OpenUI/JCLOpenUI"),
346 _("OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first"),
347 _("Bad OrderDependency"),
348 _("Bad UIConstraints"),
349 _("Missing asterisk in column 1"),
350 _("Line longer than the maximum allowed (255 characters)"),
351 _("Illegal control character"),
352 _("Illegal main keyword string"),
353 _("Illegal option keyword string"),
354 _("Illegal translation string"),
355 _("Illegal whitespace character"),
356 _("Bad custom parameter"),
357 _("Missing option keyword"),
358 _("Bad value string"),
359 _("Missing CloseGroup")
363 if (status
< PPD_OK
|| status
>= PPD_MAX_STATUS
)
364 return (_cupsLangString(cupsLangDefault(), _("Unknown")));
366 return (_cupsLangString(cupsLangDefault(), messages
[status
]));
371 * '_ppdGetEncoding()' - Get the CUPS encoding value for the given
375 cups_encoding_t
/* O - CUPS encoding value */
376 _ppdGetEncoding(const char *name
) /* I - LanguageEncoding string */
378 if (!_cups_strcasecmp(name
, "ISOLatin1"))
379 return (CUPS_ISO8859_1
);
380 else if (!_cups_strcasecmp(name
, "ISOLatin2"))
381 return (CUPS_ISO8859_2
);
382 else if (!_cups_strcasecmp(name
, "ISOLatin5"))
383 return (CUPS_ISO8859_5
);
384 else if (!_cups_strcasecmp(name
, "JIS83-RKSJ"))
385 return (CUPS_JIS_X0213
);
386 else if (!_cups_strcasecmp(name
, "MacStandard"))
387 return (CUPS_MAC_ROMAN
);
388 else if (!_cups_strcasecmp(name
, "WindowsANSI"))
389 return (CUPS_WINDOWS_1252
);
396 * 'ppdLastError()' - Return the status from the last ppdOpen*().
398 * @since CUPS 1.1.19/Mac OS X 10.3@
401 ppd_status_t
/* O - Status code */
402 ppdLastError(int *line
) /* O - Line number */
404 _cups_globals_t
*cg
= _cupsGlobals();
409 *line
= cg
->ppd_line
;
411 return (cg
->ppd_status
);
416 * 'ppdOpen()' - Read a PPD file into memory.
419 ppd_file_t
* /* O - PPD file record */
420 ppdOpen(FILE *fp
) /* I - File to read from */
422 ppd_file_t
*ppd
; /* PPD file record */
423 cups_file_t
*cf
; /* CUPS file */
427 * Reopen the stdio file as a CUPS file...
430 if ((cf
= cupsFileOpenFd(fileno(fp
), "r")) == NULL
)
434 * Load the PPD file using the newer API...
440 * Close the CUPS file and return the PPD...
450 * 'ppdOpen2()' - Read a PPD file into memory.
452 * @since CUPS 1.2/Mac OS X 10.5@
455 ppd_file_t
* /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
456 ppdOpen2(cups_file_t
*fp
) /* I - File to read from */
458 int i
, j
, k
; /* Looping vars */
459 int count
; /* Temporary count */
460 _ppd_line_t line
; /* Line buffer */
461 ppd_file_t
*ppd
; /* PPD file record */
462 ppd_group_t
*group
, /* Current group */
463 *subgroup
; /* Current sub-group */
464 ppd_option_t
*option
; /* Current option */
465 ppd_choice_t
*choice
; /* Current choice */
466 ppd_const_t
*constraint
; /* Current constraint */
467 ppd_size_t
*size
; /* Current page size */
468 int mask
; /* Line data mask */
469 char keyword
[PPD_MAX_NAME
],
470 /* Keyword from file */
472 /* Option from file */
474 /* Human-readable text from file */
475 *string
, /* Code/text from file */
476 *sptr
, /* Pointer into string */
477 *nameptr
, /* Pointer into name */
478 *temp
, /* Temporary string pointer */
479 **tempfonts
; /* Temporary fonts pointer */
480 float order
; /* Order dependency number */
481 ppd_section_t section
; /* Order dependency section */
482 ppd_profile_t
*profile
; /* Pointer to color profile */
483 char **filter
; /* Pointer to filter */
484 struct lconv
*loc
; /* Locale data */
485 int ui_keyword
; /* Is this line a UI keyword? */
486 cups_encoding_t encoding
; /* Encoding of PPD file */
487 _cups_globals_t
*cg
= _cupsGlobals();
489 char custom_name
[PPD_MAX_NAME
];
490 /* CustomFoo attribute name */
491 ppd_attr_t
*custom_attr
; /* CustomFoo attribute */
492 static const char * const ui_keywords
[] =
494 #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST
496 * Adobe defines some 41 keywords as "UI", meaning that they are
497 * user interface elements and that they should be treated as such
498 * even if the PPD creator doesn't use Open/CloseUI around them.
500 * Since this can cause previously invisible options to appear and
501 * confuse users, the default is to only treat the PageSize and
502 * PageRegion keywords this way.
504 /* Boolean keywords */
514 /* PickOne keywords */
527 "JCLFrameBufferSize",
548 #else /* !CUPS_USE_FULL_UI_KEYWORDS_LIST */
551 #endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */
555 DEBUG_printf(("ppdOpen2(fp=%p)", fp
));
558 * Default to "OK" status...
561 cg
->ppd_status
= PPD_OK
;
565 * Range check input...
570 cg
->ppd_status
= PPD_NULL_FILE
;
575 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
581 mask
= ppd_read(fp
, &line
, keyword
, name
, text
, &string
, 0, cg
);
583 DEBUG_printf(("2ppdOpen2: mask=%x, keyword=\"%s\"...", mask
, keyword
));
586 strcmp(keyword
, "PPD-Adobe") ||
587 string
== NULL
|| string
[0] != '4')
590 * Either this is not a PPD file, or it is not a 4.x PPD file.
593 if (cg
->ppd_status
== PPD_OK
)
594 cg
->ppd_status
= PPD_MISSING_PPDADOBE4
;
596 _cupsStrFree(string
);
597 ppd_free(line
.buffer
);
602 DEBUG_printf(("2ppdOpen2: keyword=%s, string=%p", keyword
, string
));
604 _cupsStrFree(string
);
607 * Allocate memory for the PPD file record...
610 if ((ppd
= calloc(1, sizeof(ppd_file_t
))) == NULL
)
612 cg
->ppd_status
= PPD_ALLOC_ERROR
;
614 _cupsStrFree(string
);
615 ppd_free(line
.buffer
);
620 ppd
->language_level
= 2;
621 ppd
->color_device
= 0;
622 ppd
->colorspace
= PPD_CS_N
;
623 ppd
->landscape
= -90;
624 ppd
->coptions
= cupsArrayNew((cups_array_func_t
)ppd_compare_coptions
,
628 * Read lines from the PPD file and add them to the file record...
636 encoding
= CUPS_ISO8859_1
;
639 while ((mask
= ppd_read(fp
, &line
, keyword
, name
, text
, &string
, 1, cg
)) != 0)
641 DEBUG_printf(("2ppdOpen2: mask=%x, keyword=\"%s\", name=\"%s\", "
642 "text=\"%s\", string=%d chars...", mask
, keyword
, name
, text
,
643 string
? (int)strlen(string
) : 0));
645 if (strncmp(keyword
, "Default", 7) && !string
&&
646 cg
->ppd_conform
!= PPD_CONFORM_RELAXED
)
649 * Need a string value!
652 cg
->ppd_status
= PPD_MISSING_VALUE
;
660 * Certain main keywords (as defined by the PPD spec) may be used
661 * without the usual OpenUI/CloseUI stuff. Presumably this is just
662 * so that Adobe wouldn't completely break compatibility with PPD
663 * files prior to v4.0 of the spec, but it is hopelessly
664 * inconsistent... Catch these main keywords and automatically
665 * create the corresponding option, as needed...
671 * Previous line was a UI keyword...
678 if (option
== NULL
&&
679 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
680 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
682 for (i
= 0; i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])); i
++)
683 if (!strcmp(keyword
, ui_keywords
[i
]))
686 if (i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])))
689 * Create the option in the appropriate group...
694 DEBUG_printf(("2ppdOpen2: FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!",
699 if ((group
= ppd_get_group(ppd
, "General", _("General"), cg
,
703 DEBUG_printf(("2ppdOpen2: Adding to group %s...", group
->text
));
704 option
= ppd_get_option(group
, keyword
);
708 option
= ppd_get_option(group
, keyword
);
712 cg
->ppd_status
= PPD_ALLOC_ERROR
;
718 * Now fill in the initial information for the option...
721 if (!strncmp(keyword
, "JCL", 3))
722 option
->section
= PPD_ORDER_JCL
;
724 option
->section
= PPD_ORDER_ANY
;
726 option
->order
= 10.0f
;
729 option
->ui
= PPD_UI_BOOLEAN
;
731 option
->ui
= PPD_UI_PICKONE
;
733 for (j
= 0; j
< ppd
->num_attrs
; j
++)
734 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
735 !strcmp(ppd
->attrs
[j
]->name
+ 7, keyword
) &&
736 ppd
->attrs
[j
]->value
)
738 DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
739 option
->keyword
, ppd
->attrs
[j
]->value
));
740 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
741 sizeof(option
->defchoice
));
745 if (!strcmp(keyword
, "PageSize"))
746 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
747 else if (!strcmp(keyword
, "MediaType"))
748 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
749 else if (!strcmp(keyword
, "InputSlot"))
750 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
751 else if (!strcmp(keyword
, "ColorModel"))
752 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
753 else if (!strcmp(keyword
, "Resolution"))
754 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
756 strlcpy(option
->text
, keyword
, sizeof(option
->text
));
760 if (!strcmp(keyword
, "LanguageLevel"))
761 ppd
->language_level
= atoi(string
);
762 else if (!strcmp(keyword
, "LanguageEncoding"))
765 * Say all PPD files are UTF-8, since we convert to UTF-8...
768 ppd
->lang_encoding
= _cupsStrAlloc("UTF-8");
769 encoding
= _ppdGetEncoding(string
);
771 else if (!strcmp(keyword
, "LanguageVersion"))
772 ppd
->lang_version
= string
;
773 else if (!strcmp(keyword
, "Manufacturer"))
774 ppd
->manufacturer
= string
;
775 else if (!strcmp(keyword
, "ModelName"))
776 ppd
->modelname
= string
;
777 else if (!strcmp(keyword
, "Protocols"))
778 ppd
->protocols
= string
;
779 else if (!strcmp(keyword
, "PCFileName"))
780 ppd
->pcfilename
= string
;
781 else if (!strcmp(keyword
, "NickName"))
783 if (encoding
!= CUPS_UTF8
)
785 cups_utf8_t utf8
[256]; /* UTF-8 version of NickName */
788 cupsCharsetToUTF8(utf8
, string
, sizeof(utf8
), encoding
);
789 ppd
->nickname
= _cupsStrAlloc((char *)utf8
);
792 ppd
->nickname
= _cupsStrAlloc(string
);
794 else if (!strcmp(keyword
, "Product"))
795 ppd
->product
= string
;
796 else if (!strcmp(keyword
, "ShortNickName"))
797 ppd
->shortnickname
= string
;
798 else if (!strcmp(keyword
, "TTRasterizer"))
799 ppd
->ttrasterizer
= string
;
800 else if (!strcmp(keyword
, "JCLBegin"))
802 ppd
->jcl_begin
= _cupsStrAlloc(string
);
803 ppd_decode(ppd
->jcl_begin
); /* Decode quoted string */
805 else if (!strcmp(keyword
, "JCLEnd"))
807 ppd
->jcl_end
= _cupsStrAlloc(string
);
808 ppd_decode(ppd
->jcl_end
); /* Decode quoted string */
810 else if (!strcmp(keyword
, "JCLToPSInterpreter"))
812 ppd
->jcl_ps
= _cupsStrAlloc(string
);
813 ppd_decode(ppd
->jcl_ps
); /* Decode quoted string */
815 else if (!strcmp(keyword
, "AccurateScreensSupport"))
816 ppd
->accurate_screens
= !strcmp(string
, "True");
817 else if (!strcmp(keyword
, "ColorDevice"))
818 ppd
->color_device
= !strcmp(string
, "True");
819 else if (!strcmp(keyword
, "ContoneOnly"))
820 ppd
->contone_only
= !strcmp(string
, "True");
821 else if (!strcmp(keyword
, "cupsFlipDuplex"))
822 ppd
->flip_duplex
= !strcmp(string
, "True");
823 else if (!strcmp(keyword
, "cupsManualCopies"))
824 ppd
->manual_copies
= !strcmp(string
, "True");
825 else if (!strcmp(keyword
, "cupsModelNumber"))
826 ppd
->model_number
= atoi(string
);
827 else if (!strcmp(keyword
, "cupsColorProfile"))
829 if (ppd
->num_profiles
== 0)
830 profile
= malloc(sizeof(ppd_profile_t
));
832 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
833 (ppd
->num_profiles
+ 1));
837 cg
->ppd_status
= PPD_ALLOC_ERROR
;
842 ppd
->profiles
= profile
;
843 profile
+= ppd
->num_profiles
;
844 ppd
->num_profiles
++;
846 memset(profile
, 0, sizeof(ppd_profile_t
));
847 strlcpy(profile
->resolution
, name
, sizeof(profile
->resolution
));
848 strlcpy(profile
->media_type
, text
, sizeof(profile
->media_type
));
850 profile
->density
= (float)_cupsStrScand(string
, &sptr
, loc
);
851 profile
->gamma
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
852 profile
->matrix
[0][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
853 profile
->matrix
[0][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
854 profile
->matrix
[0][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
855 profile
->matrix
[1][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
856 profile
->matrix
[1][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
857 profile
->matrix
[1][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
858 profile
->matrix
[2][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
859 profile
->matrix
[2][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
860 profile
->matrix
[2][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
862 else if (!strcmp(keyword
, "cupsFilter"))
864 if (ppd
->num_filters
== 0)
865 filter
= malloc(sizeof(char *));
867 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
871 cg
->ppd_status
= PPD_ALLOC_ERROR
;
876 ppd
->filters
= filter
;
877 filter
+= ppd
->num_filters
;
881 * Retain a copy of the filter string...
884 *filter
= _cupsStrRetain(string
);
886 else if (!strcmp(keyword
, "Throughput"))
887 ppd
->throughput
= atoi(string
);
888 else if (!strcmp(keyword
, "Font"))
891 * Add this font to the list of available fonts...
894 if (ppd
->num_fonts
== 0)
895 tempfonts
= (char **)malloc(sizeof(char *));
897 tempfonts
= (char **)realloc(ppd
->fonts
,
898 sizeof(char *) * (ppd
->num_fonts
+ 1));
900 if (tempfonts
== NULL
)
902 cg
->ppd_status
= PPD_ALLOC_ERROR
;
907 ppd
->fonts
= tempfonts
;
908 ppd
->fonts
[ppd
->num_fonts
] = _cupsStrAlloc(name
);
911 else if (!strncmp(keyword
, "ParamCustom", 11))
913 ppd_coption_t
*coption
; /* Custom option */
914 ppd_cparam_t
*cparam
; /* Custom parameter */
915 int corder
; /* Order number */
916 char ctype
[33], /* Data type */
917 cminimum
[65], /* Minimum value */
918 cmaximum
[65]; /* Maximum value */
922 * Get the custom option and parameter...
925 if ((coption
= ppd_get_coption(ppd
, keyword
+ 11)) == NULL
)
927 cg
->ppd_status
= PPD_ALLOC_ERROR
;
932 if ((cparam
= ppd_get_cparam(coption
, name
, text
)) == NULL
)
934 cg
->ppd_status
= PPD_ALLOC_ERROR
;
940 * Get the parameter data...
944 sscanf(string
, "%d%32s%64s%64s", &corder
, ctype
, cminimum
,
947 cg
->ppd_status
= PPD_BAD_CUSTOM_PARAM
;
952 cparam
->order
= corder
;
954 if (!strcmp(ctype
, "curve"))
956 cparam
->type
= PPD_CUSTOM_CURVE
;
957 cparam
->minimum
.custom_curve
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
958 cparam
->maximum
.custom_curve
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
960 else if (!strcmp(ctype
, "int"))
962 cparam
->type
= PPD_CUSTOM_INT
;
963 cparam
->minimum
.custom_int
= atoi(cminimum
);
964 cparam
->maximum
.custom_int
= atoi(cmaximum
);
966 else if (!strcmp(ctype
, "invcurve"))
968 cparam
->type
= PPD_CUSTOM_INVCURVE
;
969 cparam
->minimum
.custom_invcurve
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
970 cparam
->maximum
.custom_invcurve
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
972 else if (!strcmp(ctype
, "passcode"))
974 cparam
->type
= PPD_CUSTOM_PASSCODE
;
975 cparam
->minimum
.custom_passcode
= atoi(cminimum
);
976 cparam
->maximum
.custom_passcode
= atoi(cmaximum
);
978 else if (!strcmp(ctype
, "password"))
980 cparam
->type
= PPD_CUSTOM_PASSWORD
;
981 cparam
->minimum
.custom_password
= atoi(cminimum
);
982 cparam
->maximum
.custom_password
= atoi(cmaximum
);
984 else if (!strcmp(ctype
, "points"))
986 cparam
->type
= PPD_CUSTOM_POINTS
;
987 cparam
->minimum
.custom_points
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
988 cparam
->maximum
.custom_points
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
990 else if (!strcmp(ctype
, "real"))
992 cparam
->type
= PPD_CUSTOM_REAL
;
993 cparam
->minimum
.custom_real
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
994 cparam
->maximum
.custom_real
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
996 else if (!strcmp(ctype
, "string"))
998 cparam
->type
= PPD_CUSTOM_STRING
;
999 cparam
->minimum
.custom_string
= atoi(cminimum
);
1000 cparam
->maximum
.custom_string
= atoi(cmaximum
);
1004 cg
->ppd_status
= PPD_BAD_CUSTOM_PARAM
;
1010 * Now special-case for CustomPageSize...
1013 if (!strcmp(coption
->keyword
, "PageSize"))
1015 if (!strcmp(name
, "Width"))
1017 ppd
->custom_min
[0] = cparam
->minimum
.custom_points
;
1018 ppd
->custom_max
[0] = cparam
->maximum
.custom_points
;
1020 else if (!strcmp(name
, "Height"))
1022 ppd
->custom_min
[1] = cparam
->minimum
.custom_points
;
1023 ppd
->custom_max
[1] = cparam
->maximum
.custom_points
;
1027 else if (!strcmp(keyword
, "HWMargins"))
1029 for (i
= 0, sptr
= string
; i
< 4; i
++)
1030 ppd
->custom_margins
[i
] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
1032 else if (!strncmp(keyword
, "Custom", 6) && !strcmp(name
, "True") && !option
)
1034 ppd_option_t
*custom_option
; /* Custom option */
1036 DEBUG_puts("2ppdOpen2: Processing Custom option...");
1039 * Get the option and custom option...
1042 if (!ppd_get_coption(ppd
, keyword
+ 6))
1044 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1049 if (option
&& !_cups_strcasecmp(option
->keyword
, keyword
+ 6))
1050 custom_option
= option
;
1052 custom_option
= ppdFindOption(ppd
, keyword
+ 6);
1057 * Add the "custom" option...
1060 if ((choice
= ppdFindChoice(custom_option
, "Custom")) == NULL
)
1061 if ((choice
= ppd_add_choice(custom_option
, "Custom")) == NULL
)
1063 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1065 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1070 strlcpy(choice
->text
, text
[0] ? text
: _("Custom"),
1071 sizeof(choice
->text
));
1073 choice
->code
= _cupsStrAlloc(string
);
1075 if (custom_option
->section
== PPD_ORDER_JCL
)
1076 ppd_decode(choice
->code
);
1080 * Now process custom page sizes specially...
1083 if (!strcmp(keyword
, "CustomPageSize"))
1086 * Add a "Custom" page size entry...
1089 ppd
->variable_sizes
= 1;
1091 ppd_add_size(ppd
, "Custom");
1093 if (option
&& !_cups_strcasecmp(option
->keyword
, "PageRegion"))
1094 custom_option
= option
;
1096 custom_option
= ppdFindOption(ppd
, "PageRegion");
1100 if ((choice
= ppdFindChoice(custom_option
, "Custom")) == NULL
)
1101 if ((choice
= ppd_add_choice(custom_option
, "Custom")) == NULL
)
1103 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1105 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1110 strlcpy(choice
->text
, text
[0] ? text
: _("Custom"),
1111 sizeof(choice
->text
));
1115 else if (!strcmp(keyword
, "LandscapeOrientation"))
1117 if (!strcmp(string
, "Minus90"))
1118 ppd
->landscape
= -90;
1119 else if (!strcmp(string
, "Plus90"))
1120 ppd
->landscape
= 90;
1122 else if (!strcmp(keyword
, "Emulators") && string
)
1124 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
1125 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
1128 while (*sptr
== ' ')
1132 ppd
->num_emulations
= count
;
1133 if ((ppd
->emulations
= calloc(count
, sizeof(ppd_emul_t
))) == NULL
)
1135 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1140 for (i
= 0, sptr
= string
; i
< count
; i
++)
1142 for (nameptr
= ppd
->emulations
[i
].name
;
1143 *sptr
!= '\0' && *sptr
!= ' ';
1145 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
1150 while (*sptr
== ' ')
1154 else if (!strncmp(keyword
, "StartEmulator_", 14))
1158 for (i
= 0; i
< ppd
->num_emulations
; i
++)
1159 if (!strcmp(keyword
+ 14, ppd
->emulations
[i
].name
))
1161 ppd
->emulations
[i
].start
= string
;
1165 else if (!strncmp(keyword
, "StopEmulator_", 13))
1169 for (i
= 0; i
< ppd
->num_emulations
; i
++)
1170 if (!strcmp(keyword
+ 13, ppd
->emulations
[i
].name
))
1172 ppd
->emulations
[i
].stop
= string
;
1176 else if (!strcmp(keyword
, "JobPatchFile"))
1179 * CUPS STR #3421: Check for "*JobPatchFile: int: string"
1182 if (isdigit(*string
& 255))
1184 for (sptr
= string
+ 1; isdigit(*sptr
& 255); sptr
++);
1189 * Found "*JobPatchFile: int: string"...
1192 cg
->ppd_status
= PPD_BAD_VALUE
;
1198 if (!name
[0] && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1201 * Found "*JobPatchFile: string"...
1204 cg
->ppd_status
= PPD_MISSING_OPTION_KEYWORD
;
1209 if (ppd
->patches
== NULL
)
1210 ppd
->patches
= strdup(string
);
1213 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
1214 strlen(string
) + 1);
1217 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1222 ppd
->patches
= temp
;
1224 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
1227 else if (!strcmp(keyword
, "OpenUI"))
1230 * Don't allow nesting of options...
1233 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1235 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1241 * Add an option record to the current sub-group, group, or file...
1244 DEBUG_printf(("2ppdOpen2: name=\"%s\" (%d)", name
, (int)strlen(name
)));
1247 _cups_strcpy(name
, name
+ 1); /* Eliminate leading asterisk */
1249 for (i
= (int)strlen(name
) - 1; i
> 0 && _cups_isspace(name
[i
]); i
--)
1250 name
[i
] = '\0'; /* Eliminate trailing spaces */
1252 DEBUG_printf(("2ppdOpen2: OpenUI of %s in group %s...", name
,
1253 group
? group
->text
: "(null)"));
1255 if (subgroup
!= NULL
)
1256 option
= ppd_get_option(subgroup
, name
);
1257 else if (group
== NULL
)
1259 if ((group
= ppd_get_group(ppd
, "General", _("General"), cg
,
1263 DEBUG_printf(("2ppdOpen2: Adding to group %s...", group
->text
));
1264 option
= ppd_get_option(group
, name
);
1268 option
= ppd_get_option(group
, name
);
1272 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1278 * Now fill in the initial information for the option...
1281 if (string
&& !strcmp(string
, "PickMany"))
1282 option
->ui
= PPD_UI_PICKMANY
;
1283 else if (string
&& !strcmp(string
, "Boolean"))
1284 option
->ui
= PPD_UI_BOOLEAN
;
1285 else if (string
&& !strcmp(string
, "PickOne"))
1286 option
->ui
= PPD_UI_PICKONE
;
1287 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1289 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1294 option
->ui
= PPD_UI_PICKONE
;
1296 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1297 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1298 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1299 ppd
->attrs
[j
]->value
)
1301 DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
1302 option
->keyword
, ppd
->attrs
[j
]->value
));
1303 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1304 sizeof(option
->defchoice
));
1309 cupsCharsetToUTF8((cups_utf8_t
*)option
->text
, text
,
1310 sizeof(option
->text
), encoding
);
1313 if (!strcmp(name
, "PageSize"))
1314 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
1315 else if (!strcmp(name
, "MediaType"))
1316 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
1317 else if (!strcmp(name
, "InputSlot"))
1318 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
1319 else if (!strcmp(name
, "ColorModel"))
1320 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
1321 else if (!strcmp(name
, "Resolution"))
1322 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
1324 strlcpy(option
->text
, name
, sizeof(option
->text
));
1327 option
->section
= PPD_ORDER_ANY
;
1329 _cupsStrFree(string
);
1333 * Add a custom option choice if we have already seen a CustomFoo
1337 if (!_cups_strcasecmp(name
, "PageRegion"))
1338 strcpy(custom_name
, "CustomPageSize");
1340 snprintf(custom_name
, sizeof(custom_name
), "Custom%s", name
);
1342 if ((custom_attr
= ppdFindAttr(ppd
, custom_name
, "True")) != NULL
)
1344 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
1345 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
1347 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1349 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1354 strlcpy(choice
->text
,
1355 custom_attr
->text
[0] ? custom_attr
->text
: _("Custom"),
1356 sizeof(choice
->text
));
1357 choice
->code
= _cupsStrRetain(custom_attr
->value
);
1360 else if (!strcmp(keyword
, "JCLOpenUI"))
1363 * Don't allow nesting of options...
1366 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1368 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1374 * Find the JCL group, and add if needed...
1377 group
= ppd_get_group(ppd
, "JCL", _("JCL"), cg
, encoding
);
1383 * Add an option record to the current JCLs...
1387 _cups_strcpy(name
, name
+ 1);
1389 option
= ppd_get_option(group
, name
);
1393 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1399 * Now fill in the initial information for the option...
1402 if (string
&& !strcmp(string
, "PickMany"))
1403 option
->ui
= PPD_UI_PICKMANY
;
1404 else if (string
&& !strcmp(string
, "Boolean"))
1405 option
->ui
= PPD_UI_BOOLEAN
;
1406 else if (string
&& !strcmp(string
, "PickOne"))
1407 option
->ui
= PPD_UI_PICKONE
;
1410 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1415 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1416 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1417 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1418 ppd
->attrs
[j
]->value
)
1420 DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
1421 option
->keyword
, ppd
->attrs
[j
]->value
));
1422 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1423 sizeof(option
->defchoice
));
1428 cupsCharsetToUTF8((cups_utf8_t
*)option
->text
, text
,
1429 sizeof(option
->text
), encoding
);
1431 strlcpy(option
->text
, name
, sizeof(option
->text
));
1433 option
->section
= PPD_ORDER_JCL
;
1436 _cupsStrFree(string
);
1440 * Add a custom option choice if we have already seen a CustomFoo
1444 snprintf(custom_name
, sizeof(custom_name
), "Custom%s", name
);
1446 if ((custom_attr
= ppdFindAttr(ppd
, custom_name
, "True")) != NULL
)
1448 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
1450 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1452 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1457 strlcpy(choice
->text
,
1458 custom_attr
->text
[0] ? custom_attr
->text
: _("Custom"),
1459 sizeof(choice
->text
));
1460 choice
->code
= _cupsStrRetain(custom_attr
->value
);
1463 else if (!strcmp(keyword
, "CloseUI") || !strcmp(keyword
, "JCLCloseUI"))
1467 _cupsStrFree(string
);
1470 else if (!strcmp(keyword
, "OpenGroup"))
1473 * Open a new group...
1478 cg
->ppd_status
= PPD_NESTED_OPEN_GROUP
;
1485 cg
->ppd_status
= PPD_BAD_OPEN_GROUP
;
1491 * Separate the group name from the text (name/text)...
1494 if ((sptr
= strchr(string
, '/')) != NULL
)
1500 * Fix up the text...
1506 * Find/add the group...
1509 group
= ppd_get_group(ppd
, string
, sptr
, cg
, encoding
);
1514 _cupsStrFree(string
);
1517 else if (!strcmp(keyword
, "CloseGroup"))
1521 _cupsStrFree(string
);
1524 else if (!strcmp(keyword
, "OrderDependency"))
1526 order
= (float)_cupsStrScand(string
, &sptr
, loc
);
1528 if (!sptr
|| sscanf(sptr
, "%40s%40s", name
, keyword
) != 2)
1530 cg
->ppd_status
= PPD_BAD_ORDER_DEPENDENCY
;
1535 if (keyword
[0] == '*')
1536 _cups_strcpy(keyword
, keyword
+ 1);
1538 if (!strcmp(name
, "ExitServer"))
1539 section
= PPD_ORDER_EXIT
;
1540 else if (!strcmp(name
, "Prolog"))
1541 section
= PPD_ORDER_PROLOG
;
1542 else if (!strcmp(name
, "DocumentSetup"))
1543 section
= PPD_ORDER_DOCUMENT
;
1544 else if (!strcmp(name
, "PageSetup"))
1545 section
= PPD_ORDER_PAGE
;
1546 else if (!strcmp(name
, "JCLSetup"))
1547 section
= PPD_ORDER_JCL
;
1549 section
= PPD_ORDER_ANY
;
1557 * Only valid for Non-UI options...
1560 for (i
= ppd
->num_groups
, gtemp
= ppd
->groups
; i
> 0; i
--, gtemp
++)
1561 if (gtemp
->text
[0] == '\0')
1565 for (i
= 0; i
< gtemp
->num_options
; i
++)
1566 if (!strcmp(keyword
, gtemp
->options
[i
].keyword
))
1568 gtemp
->options
[i
].section
= section
;
1569 gtemp
->options
[i
].order
= order
;
1575 option
->section
= section
;
1576 option
->order
= order
;
1579 _cupsStrFree(string
);
1582 else if (!strncmp(keyword
, "Default", 7))
1588 * Drop UI text, if any, from value...
1591 if (strchr(string
, '/') != NULL
)
1592 *strchr(string
, '/') = '\0';
1595 * Assign the default value as appropriate...
1598 if (!strcmp(keyword
, "DefaultColorSpace"))
1601 * Set default colorspace...
1604 if (!strcmp(string
, "CMY"))
1605 ppd
->colorspace
= PPD_CS_CMY
;
1606 else if (!strcmp(string
, "CMYK"))
1607 ppd
->colorspace
= PPD_CS_CMYK
;
1608 else if (!strcmp(string
, "RGB"))
1609 ppd
->colorspace
= PPD_CS_RGB
;
1610 else if (!strcmp(string
, "RGBK"))
1611 ppd
->colorspace
= PPD_CS_RGBK
;
1612 else if (!strcmp(string
, "N"))
1613 ppd
->colorspace
= PPD_CS_N
;
1615 ppd
->colorspace
= PPD_CS_GRAY
;
1617 else if (option
&& !strcmp(keyword
+ 7, option
->keyword
))
1620 * Set the default as part of the current option...
1623 DEBUG_printf(("2ppdOpen2: Setting %s to %s...", keyword
, string
));
1625 strlcpy(option
->defchoice
, string
, sizeof(option
->defchoice
));
1627 DEBUG_printf(("2ppdOpen2: %s is now %s...", keyword
, option
->defchoice
));
1632 * Lookup option and set if it has been defined...
1635 ppd_option_t
*toption
; /* Temporary option */
1638 if ((toption
= ppdFindOption(ppd
, keyword
+ 7)) != NULL
)
1640 DEBUG_printf(("2ppdOpen2: Setting %s to %s...", keyword
, string
));
1641 strlcpy(toption
->defchoice
, string
, sizeof(toption
->defchoice
));
1645 else if (!strcmp(keyword
, "UIConstraints") ||
1646 !strcmp(keyword
, "NonUIConstraints"))
1650 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1654 if (ppd
->num_consts
== 0)
1655 constraint
= calloc(2, sizeof(ppd_const_t
));
1657 constraint
= realloc(ppd
->consts
,
1658 (ppd
->num_consts
+ 2) * sizeof(ppd_const_t
));
1660 if (constraint
== NULL
)
1662 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1667 ppd
->consts
= constraint
;
1668 constraint
+= ppd
->num_consts
;
1671 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1672 constraint
->choice1
, constraint
->option2
,
1673 constraint
->choice2
))
1675 case 0 : /* Error */
1676 case 1 : /* Error */
1677 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1680 case 2 : /* Two options... */
1682 * Check for broken constraints like "* Option"...
1685 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1686 (!strcmp(constraint
->option1
, "*") ||
1687 !strcmp(constraint
->choice1
, "*")))
1689 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1694 * The following strcpy's are safe, as optionN and
1695 * choiceN are all the same size (size defined by PPD spec...)
1698 if (constraint
->option1
[0] == '*')
1699 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1700 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1702 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1706 if (constraint
->choice1
[0] == '*')
1707 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1708 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1710 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1714 constraint
->choice1
[0] = '\0';
1715 constraint
->choice2
[0] = '\0';
1718 case 3 : /* Two options, one choice... */
1720 * Check for broken constraints like "* Option"...
1723 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1724 (!strcmp(constraint
->option1
, "*") ||
1725 !strcmp(constraint
->choice1
, "*") ||
1726 !strcmp(constraint
->option2
, "*")))
1728 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1733 * The following _cups_strcpy's are safe, as optionN and
1734 * choiceN are all the same size (size defined by PPD spec...)
1737 if (constraint
->option1
[0] == '*')
1738 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1739 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1741 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1745 if (constraint
->choice1
[0] == '*')
1747 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1748 constraint
->option2
[0] == '*')
1750 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1754 _cups_strcpy(constraint
->choice2
, constraint
->option2
);
1755 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1756 constraint
->choice1
[0] = '\0';
1760 if (constraint
->option2
[0] == '*')
1761 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1762 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1764 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1768 constraint
->choice2
[0] = '\0';
1772 case 4 : /* Two options, two choices... */
1774 * Check for broken constraints like "* Option"...
1777 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1778 (!strcmp(constraint
->option1
, "*") ||
1779 !strcmp(constraint
->choice1
, "*") ||
1780 !strcmp(constraint
->option2
, "*") ||
1781 !strcmp(constraint
->choice2
, "*")))
1783 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1787 if (constraint
->option1
[0] == '*')
1788 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1789 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1791 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1795 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1796 constraint
->choice1
[0] == '*')
1798 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1802 if (constraint
->option2
[0] == '*')
1803 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1804 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1806 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1810 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1811 constraint
->choice2
[0] == '*')
1813 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1820 * Don't add this one as an attribute...
1823 _cupsStrFree(string
);
1826 else if (!strcmp(keyword
, "PaperDimension"))
1828 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1829 size
= ppd_add_size(ppd
, name
);
1834 * Unable to add or find size!
1837 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1842 size
->width
= (float)_cupsStrScand(string
, &sptr
, loc
);
1843 size
->length
= (float)_cupsStrScand(sptr
, NULL
, loc
);
1845 _cupsStrFree(string
);
1848 else if (!strcmp(keyword
, "ImageableArea"))
1850 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1851 size
= ppd_add_size(ppd
, name
);
1856 * Unable to add or find size!
1859 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1864 size
->left
= (float)_cupsStrScand(string
, &sptr
, loc
);
1865 size
->bottom
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
1866 size
->right
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
1867 size
->top
= (float)_cupsStrScand(sptr
, NULL
, loc
);
1869 _cupsStrFree(string
);
1872 else if (option
!= NULL
&&
1873 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1874 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
) &&
1875 !strcmp(keyword
, option
->keyword
))
1877 DEBUG_printf(("2ppdOpen2: group=%p, subgroup=%p", group
, subgroup
));
1879 if (!strcmp(keyword
, "PageSize"))
1882 * Add a page size...
1885 if (ppdPageSize(ppd
, name
) == NULL
)
1886 ppd_add_size(ppd
, name
);
1890 * Add the option choice...
1893 if ((choice
= ppd_add_choice(option
, name
)) == NULL
)
1895 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1901 cupsCharsetToUTF8((cups_utf8_t
*)choice
->text
, text
,
1902 sizeof(choice
->text
), encoding
);
1903 else if (!strcmp(name
, "True"))
1904 strcpy(choice
->text
, _("Yes"));
1905 else if (!strcmp(name
, "False"))
1906 strcpy(choice
->text
, _("No"));
1908 strlcpy(choice
->text
, name
, sizeof(choice
->text
));
1910 if (option
->section
== PPD_ORDER_JCL
)
1911 ppd_decode(string
); /* Decode quoted string */
1913 choice
->code
= string
;
1914 string
= NULL
; /* Don't add as an attribute below */
1918 * Add remaining lines with keywords and string values as attributes...
1922 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
))
1923 ppd_add_attr(ppd
, keyword
, name
, text
, string
);
1925 _cupsStrFree(string
);
1929 * Check for a missing CloseGroup...
1932 if (group
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1934 cg
->ppd_status
= PPD_MISSING_CLOSE_GROUP
;
1938 ppd_free(line
.buffer
);
1941 * Reset language preferences...
1945 if (!cupsFileEOF(fp
))
1946 DEBUG_printf(("1ppdOpen2: Premature EOF at %lu...\n",
1947 (unsigned long)cupsFileTell(fp
)));
1950 if (cg
->ppd_status
!= PPD_OK
)
1953 * Had an error reading the PPD file, cannot continue!
1962 * Update the filters array as needed...
1965 if (!ppd_update_filters(ppd
, cg
))
1973 * Create the sorted options array and set the option back-pointer for
1974 * each choice and custom option...
1977 ppd
->options
= cupsArrayNew2((cups_array_func_t
)ppd_compare_options
, NULL
,
1978 (cups_ahash_func_t
)ppd_hash_option
,
1981 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1985 for (j
= group
->num_options
, option
= group
->options
;
1989 ppd_coption_t
*coption
; /* Custom option */
1992 cupsArrayAdd(ppd
->options
, option
);
1994 for (k
= 0; k
< option
->num_choices
; k
++)
1995 option
->choices
[k
].option
= option
;
1997 if ((coption
= ppdFindCustomOption(ppd
, option
->keyword
)) != NULL
)
1998 coption
->option
= option
;
2003 * Create an array to track the marked choices...
2006 ppd
->marked
= cupsArrayNew((cups_array_func_t
)ppd_compare_choices
, NULL
);
2009 * Return the PPD file structure...
2015 * Common exit point for errors to save code size...
2020 _cupsStrFree(string
);
2021 ppd_free(line
.buffer
);
2030 * 'ppdOpenFd()' - Read a PPD file into memory.
2033 ppd_file_t
* /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
2034 ppdOpenFd(int fd
) /* I - File to read from */
2036 cups_file_t
*fp
; /* CUPS file pointer */
2037 ppd_file_t
*ppd
; /* PPD file record */
2038 _cups_globals_t
*cg
= _cupsGlobals();
2043 * Set the line number to 0...
2049 * Range check input...
2054 cg
->ppd_status
= PPD_NULL_FILE
;
2060 * Try to open the file and parse it...
2063 if ((fp
= cupsFileOpenFd(fd
, "r")) != NULL
)
2071 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
2080 * 'ppdOpenFile()' - Read a PPD file into memory.
2083 ppd_file_t
* /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
2084 ppdOpenFile(const char *filename
) /* I - File to read from */
2086 cups_file_t
*fp
; /* File pointer */
2087 ppd_file_t
*ppd
; /* PPD file record */
2088 _cups_globals_t
*cg
= _cupsGlobals();
2093 * Set the line number to 0...
2099 * Range check input...
2102 if (filename
== NULL
)
2104 cg
->ppd_status
= PPD_NULL_FILE
;
2110 * Try to open the file and parse it...
2113 if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
2121 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
2130 * 'ppdSetConformance()' - Set the conformance level for PPD files.
2132 * @since CUPS 1.1.20/Mac OS X 10.4@
2136 ppdSetConformance(ppd_conform_t c
) /* I - Conformance level */
2138 _cups_globals_t
*cg
= _cupsGlobals();
2142 cg
->ppd_conform
= c
;
2147 * 'ppd_add_attr()' - Add an attribute to the PPD data.
2150 static ppd_attr_t
* /* O - New attribute */
2151 ppd_add_attr(ppd_file_t
*ppd
, /* I - PPD file data */
2152 const char *name
, /* I - Attribute name */
2153 const char *spec
, /* I - Specifier string, if any */
2154 const char *text
, /* I - Text string, if any */
2155 const char *value
) /* I - Value of attribute */
2157 ppd_attr_t
**ptr
, /* New array */
2158 *temp
; /* New attribute */
2162 * Range check input...
2165 if (ppd
== NULL
|| name
== NULL
|| spec
== NULL
)
2169 * Create the array as needed...
2172 if (!ppd
->sorted_attrs
)
2173 ppd
->sorted_attrs
= cupsArrayNew((cups_array_func_t
)ppd_compare_attrs
,
2177 * Allocate memory for the new attribute...
2180 if (ppd
->num_attrs
== 0)
2181 ptr
= malloc(sizeof(ppd_attr_t
*));
2183 ptr
= realloc(ppd
->attrs
, (ppd
->num_attrs
+ 1) * sizeof(ppd_attr_t
*));
2189 ptr
+= ppd
->num_attrs
;
2191 if ((temp
= calloc(1, sizeof(ppd_attr_t
))) == NULL
)
2202 strlcpy(temp
->name
, name
, sizeof(temp
->name
));
2203 strlcpy(temp
->spec
, spec
, sizeof(temp
->spec
));
2204 strlcpy(temp
->text
, text
, sizeof(temp
->text
));
2205 temp
->value
= (char *)value
;
2208 * Add the attribute to the sorted array...
2211 cupsArrayAdd(ppd
->sorted_attrs
, temp
);
2214 * Return the attribute...
2222 * 'ppd_add_choice()' - Add a choice to an option.
2225 static ppd_choice_t
* /* O - Named choice */
2226 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
2227 const char *name
) /* I - Name of choice */
2229 ppd_choice_t
*choice
; /* Choice */
2232 if (option
->num_choices
== 0)
2233 choice
= malloc(sizeof(ppd_choice_t
));
2235 choice
= realloc(option
->choices
,
2236 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
2241 option
->choices
= choice
;
2242 choice
+= option
->num_choices
;
2243 option
->num_choices
++;
2245 memset(choice
, 0, sizeof(ppd_choice_t
));
2246 strlcpy(choice
->choice
, name
, sizeof(choice
->choice
));
2253 * 'ppd_add_size()' - Add a page size.
2256 static ppd_size_t
* /* O - Named size */
2257 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
2258 const char *name
) /* I - Name of size */
2260 ppd_size_t
*size
; /* Size */
2263 if (ppd
->num_sizes
== 0)
2264 size
= malloc(sizeof(ppd_size_t
));
2266 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
2272 size
+= ppd
->num_sizes
;
2275 memset(size
, 0, sizeof(ppd_size_t
));
2276 strlcpy(size
->name
, name
, sizeof(size
->name
));
2283 * 'ppd_compare_attrs()' - Compare two attributes.
2286 static int /* O - Result of comparison */
2287 ppd_compare_attrs(ppd_attr_t
*a
, /* I - First attribute */
2288 ppd_attr_t
*b
) /* I - Second attribute */
2290 return (_cups_strcasecmp(a
->name
, b
->name
));
2295 * 'ppd_compare_choices()' - Compare two choices...
2298 static int /* O - Result of comparison */
2299 ppd_compare_choices(ppd_choice_t
*a
, /* I - First choice */
2300 ppd_choice_t
*b
) /* I - Second choice */
2302 return (strcmp(a
->option
->keyword
, b
->option
->keyword
));
2307 * 'ppd_compare_coptions()' - Compare two custom options.
2310 static int /* O - Result of comparison */
2311 ppd_compare_coptions(ppd_coption_t
*a
, /* I - First option */
2312 ppd_coption_t
*b
) /* I - Second option */
2314 return (_cups_strcasecmp(a
->keyword
, b
->keyword
));
2319 * 'ppd_compare_options()' - Compare two options.
2322 static int /* O - Result of comparison */
2323 ppd_compare_options(ppd_option_t
*a
, /* I - First option */
2324 ppd_option_t
*b
) /* I - Second option */
2326 return (_cups_strcasecmp(a
->keyword
, b
->keyword
));
2331 * 'ppd_decode()' - Decode a string value...
2334 static int /* O - Length of decoded string */
2335 ppd_decode(char *string
) /* I - String to decode */
2337 char *inptr
, /* Input pointer */
2338 *outptr
; /* Output pointer */
2344 while (*inptr
!= '\0')
2345 if (*inptr
== '<' && isxdigit(inptr
[1] & 255))
2348 * Convert hex to 8-bit values...
2352 while (isxdigit(*inptr
& 255))
2354 if (_cups_isalpha(*inptr
))
2355 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
2357 *outptr
= (*inptr
- '0') << 4;
2361 if (!isxdigit(*inptr
& 255))
2364 if (_cups_isalpha(*inptr
))
2365 *outptr
|= tolower(*inptr
) - 'a' + 10;
2367 *outptr
|= *inptr
- '0';
2373 while (*inptr
!= '>' && *inptr
!= '\0')
2375 while (*inptr
== '>')
2379 *outptr
++ = *inptr
++;
2383 return ((int)(outptr
- string
));
2388 * 'ppd_free_filters()' - Free the filters array.
2392 ppd_free_filters(ppd_file_t
*ppd
) /* I - PPD file */
2394 int i
; /* Looping var */
2395 char **filter
; /* Current filter */
2398 if (ppd
->num_filters
> 0)
2400 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
2401 _cupsStrFree(*filter
);
2403 ppd_free(ppd
->filters
);
2405 ppd
->num_filters
= 0;
2406 ppd
->filters
= NULL
;
2412 * 'ppd_free_group()' - Free a single UI group.
2416 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
2418 int i
; /* Looping var */
2419 ppd_option_t
*option
; /* Current option */
2420 ppd_group_t
*subgroup
; /* Current sub-group */
2423 if (group
->num_options
> 0)
2425 for (i
= group
->num_options
, option
= group
->options
;
2428 ppd_free_option(option
);
2430 ppd_free(group
->options
);
2433 if (group
->num_subgroups
> 0)
2435 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
2438 ppd_free_group(subgroup
);
2440 ppd_free(group
->subgroups
);
2446 * 'ppd_free_option()' - Free a single option.
2450 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
2452 int i
; /* Looping var */
2453 ppd_choice_t
*choice
; /* Current choice */
2456 if (option
->num_choices
> 0)
2458 for (i
= option
->num_choices
, choice
= option
->choices
;
2462 _cupsStrFree(choice
->code
);
2465 ppd_free(option
->choices
);
2471 * 'ppd_get_coption()' - Get a custom option record.
2474 static ppd_coption_t
* /* O - Custom option... */
2475 ppd_get_coption(ppd_file_t
*ppd
, /* I - PPD file */
2476 const char *name
) /* I - Name of option */
2478 ppd_coption_t
*copt
; /* New custom option */
2482 * See if the option already exists...
2485 if ((copt
= ppdFindCustomOption(ppd
, name
)) != NULL
)
2489 * Not found, so create the custom option record...
2492 if ((copt
= calloc(1, sizeof(ppd_coption_t
))) == NULL
)
2495 strlcpy(copt
->keyword
, name
, sizeof(copt
->keyword
));
2497 copt
->params
= cupsArrayNew((cups_array_func_t
)NULL
, NULL
);
2499 cupsArrayAdd(ppd
->coptions
, copt
);
2502 * Return the new record...
2510 * 'ppd_get_cparam()' - Get a custom parameter record.
2513 static ppd_cparam_t
* /* O - Extended option... */
2514 ppd_get_cparam(ppd_coption_t
*opt
, /* I - PPD file */
2515 const char *param
, /* I - Name of parameter */
2516 const char *text
) /* I - Human-readable text */
2518 ppd_cparam_t
*cparam
; /* New custom parameter */
2522 * See if the parameter already exists...
2525 if ((cparam
= ppdFindCustomParam(opt
, param
)) != NULL
)
2529 * Not found, so create the custom parameter record...
2532 if ((cparam
= calloc(1, sizeof(ppd_cparam_t
))) == NULL
)
2535 strlcpy(cparam
->name
, param
, sizeof(cparam
->name
));
2536 strlcpy(cparam
->text
, text
[0] ? text
: param
, sizeof(cparam
->text
));
2539 * Add this record to the array...
2542 cupsArrayAdd(opt
->params
, cparam
);
2545 * Return the new record...
2553 * 'ppd_get_group()' - Find or create the named group as needed.
2556 static ppd_group_t
* /* O - Named group */
2557 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
2558 const char *name
, /* I - Name of group */
2559 const char *text
, /* I - Text for group */
2560 _cups_globals_t
*cg
, /* I - Global data */
2561 cups_encoding_t encoding
) /* I - Encoding of text */
2563 int i
; /* Looping var */
2564 ppd_group_t
*group
; /* Group */
2567 DEBUG_printf(("7ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)",
2568 ppd
, name
, text
, cg
));
2570 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
2571 if (!strcmp(group
->name
, name
))
2576 DEBUG_printf(("8ppd_get_group: Adding group %s...", name
));
2578 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&& strlen(text
) >= sizeof(group
->text
))
2580 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2585 if (ppd
->num_groups
== 0)
2586 group
= malloc(sizeof(ppd_group_t
));
2588 group
= realloc(ppd
->groups
,
2589 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
2593 cg
->ppd_status
= PPD_ALLOC_ERROR
;
2598 ppd
->groups
= group
;
2599 group
+= ppd
->num_groups
;
2602 memset(group
, 0, sizeof(ppd_group_t
));
2603 strlcpy(group
->name
, name
, sizeof(group
->name
));
2605 cupsCharsetToUTF8((cups_utf8_t
*)group
->text
, text
,
2606 sizeof(group
->text
), encoding
);
2614 * 'ppd_get_option()' - Find or create the named option as needed.
2617 static ppd_option_t
* /* O - Named option */
2618 ppd_get_option(ppd_group_t
*group
, /* I - Group */
2619 const char *name
) /* I - Name of option */
2621 int i
; /* Looping var */
2622 ppd_option_t
*option
; /* Option */
2625 DEBUG_printf(("7ppd_get_option(group=%p(\"%s\"), name=\"%s\")",
2626 group
, group
->name
, name
));
2628 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
2629 if (!strcmp(option
->keyword
, name
))
2634 if (group
->num_options
== 0)
2635 option
= malloc(sizeof(ppd_option_t
));
2637 option
= realloc(group
->options
,
2638 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
2643 group
->options
= option
;
2644 option
+= group
->num_options
;
2645 group
->num_options
++;
2647 memset(option
, 0, sizeof(ppd_option_t
));
2648 strlcpy(option
->keyword
, name
, sizeof(option
->keyword
));
2656 * 'ppd_hash_option()' - Generate a hash of the option name...
2659 static int /* O - Hash index */
2660 ppd_hash_option(ppd_option_t
*option
) /* I - Option */
2662 int hash
= 0; /* Hash index */
2663 const char *k
; /* Pointer into keyword */
2666 for (hash
= option
->keyword
[0], k
= option
->keyword
+ 1; *k
;)
2667 hash
= 33 * hash
+ *k
++;
2669 return (hash
& 511);
2674 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2678 static int /* O - Bitmask of fields read */
2679 ppd_read(cups_file_t
*fp
, /* I - File to read from */
2680 _ppd_line_t
*line
, /* I - Line buffer */
2681 char *keyword
, /* O - Keyword from line */
2682 char *option
, /* O - Option from line */
2683 char *text
, /* O - Human-readable text from line */
2684 char **string
, /* O - Code/string data */
2685 int ignoreblank
, /* I - Ignore blank lines? */
2686 _cups_globals_t
*cg
) /* I - Global data */
2688 int ch
, /* Character from file */
2689 col
, /* Column in line */
2690 colon
, /* Colon seen? */
2691 endquote
, /* Waiting for an end quote */
2692 mask
, /* Mask to be returned */
2693 startline
, /* Start line */
2694 textlen
; /* Length of text */
2695 char *keyptr
, /* Keyword pointer */
2696 *optptr
, /* Option pointer */
2697 *textptr
, /* Text pointer */
2698 *strptr
, /* Pointer into string */
2699 *lineptr
; /* Current position in line buffer */
2703 * Now loop until we have a valid line...
2708 startline
= cg
->ppd_line
+ 1;
2712 line
->bufsize
= 1024;
2713 line
->buffer
= malloc(1024);
2725 lineptr
= line
->buffer
;
2729 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2731 if (lineptr
>= (line
->buffer
+ line
->bufsize
- 1))
2734 * Expand the line buffer...
2737 char *temp
; /* Temporary line pointer */
2740 line
->bufsize
+= 1024;
2741 if (line
->bufsize
> 262144)
2744 * Don't allow lines longer than 256k!
2747 cg
->ppd_line
= startline
;
2748 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2753 temp
= realloc(line
->buffer
, line
->bufsize
);
2756 cg
->ppd_line
= startline
;
2757 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2762 lineptr
= temp
+ (lineptr
- line
->buffer
);
2763 line
->buffer
= temp
;
2766 if (ch
== '\r' || ch
== '\n')
2769 * Line feed or carriage return...
2778 * Check for a trailing line feed...
2781 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2788 cupsFileGetChar(fp
);
2791 if (lineptr
== line
->buffer
&& ignoreblank
)
2792 continue; /* Skip blank lines */
2796 if (!endquote
) /* Continue for multi-line text */
2801 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2804 * Other control characters...
2807 cg
->ppd_line
= startline
;
2808 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2812 else if (ch
!= 0x1a)
2815 * Any other character...
2821 if (col
> (PPD_MAX_LINE
- 1))
2824 * Line is too long...
2827 cg
->ppd_line
= startline
;
2828 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2833 if (ch
== ':' && strncmp(line
->buffer
, "*%", 2) != 0)
2836 if (ch
== '\"' && colon
)
2837 endquote
= !endquote
;
2844 * Didn't finish this quoted string...
2847 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2850 else if (ch
== '\r' || ch
== '\n')
2858 * Check for a trailing line feed...
2861 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2864 cupsFileGetChar(fp
);
2867 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2870 * Other control characters...
2873 cg
->ppd_line
= startline
;
2874 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2878 else if (ch
!= 0x1a)
2882 if (col
> (PPD_MAX_LINE
- 1))
2885 * Line is too long...
2888 cg
->ppd_line
= startline
;
2889 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2899 * Didn't finish this line...
2902 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2903 if (ch
== '\r' || ch
== '\n')
2906 * Line feed or carriage return...
2915 * Check for a trailing line feed...
2918 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2921 cupsFileGetChar(fp
);
2926 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2929 * Other control characters...
2932 cg
->ppd_line
= startline
;
2933 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2937 else if (ch
!= 0x1a)
2941 if (col
> (PPD_MAX_LINE
- 1))
2944 * Line is too long...
2947 cg
->ppd_line
= startline
;
2948 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2955 if (lineptr
> line
->buffer
&& lineptr
[-1] == '\n')
2960 DEBUG_printf(("9ppd_read: LINE=\"%s\"", line
->buffer
));
2963 * The dynamically created PPDs for older style Mac OS X
2964 * drivers include a large blob of data inserted as comments
2965 * at the end of the file. As an optimization we can stop
2966 * reading the PPD when we get to the start of this data.
2969 if (!strcmp(line
->buffer
, "*%APLWORKSET START"))
2972 if (ch
== EOF
&& lineptr
== line
->buffer
)
2980 lineptr
= line
->buffer
+ 1;
2987 if ((!line
->buffer
[0] || /* Blank line */
2988 !strncmp(line
->buffer
, "*%", 2) || /* Comment line */
2989 !strcmp(line
->buffer
, "*End")) && /* End of multi-line string */
2990 ignoreblank
) /* Ignore these? */
2992 startline
= cg
->ppd_line
+ 1;
2996 if (!strcmp(line
->buffer
, "*")) /* (Bad) comment line */
2998 if (cg
->ppd_conform
== PPD_CONFORM_RELAXED
)
3000 startline
= cg
->ppd_line
+ 1;
3005 cg
->ppd_line
= startline
;
3006 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
3012 if (line
->buffer
[0] != '*') /* All lines start with an asterisk */
3015 * Allow lines consisting of just whitespace...
3018 for (lineptr
= line
->buffer
; *lineptr
; lineptr
++)
3019 if (*lineptr
&& !_cups_isspace(*lineptr
))
3024 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
3027 else if (ignoreblank
)
3039 while (*lineptr
&& *lineptr
!= ':' && !_cups_isspace(*lineptr
))
3041 if (*lineptr
<= ' ' || *lineptr
> 126 || *lineptr
== '/' ||
3042 (keyptr
- keyword
) >= (PPD_MAX_NAME
- 1))
3044 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
3048 *keyptr
++ = *lineptr
++;
3053 if (!strcmp(keyword
, "End"))
3056 mask
|= PPD_KEYWORD
;
3058 if (_cups_isspace(*lineptr
))
3061 * Get an option name...
3064 while (_cups_isspace(*lineptr
))
3069 while (*lineptr
&& !_cups_isspace(*lineptr
) && *lineptr
!= ':' &&
3072 if (*lineptr
<= ' ' || *lineptr
> 126 ||
3073 (optptr
- option
) >= (PPD_MAX_NAME
- 1))
3075 cg
->ppd_status
= PPD_ILLEGAL_OPTION_KEYWORD
;
3079 *optptr
++ = *lineptr
++;
3084 if (_cups_isspace(*lineptr
) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3086 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3090 while (_cups_isspace(*lineptr
))
3095 if (*lineptr
== '/')
3098 * Get human-readable text...
3105 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':')
3107 if (((unsigned char)*lineptr
< ' ' && *lineptr
!= '\t') ||
3108 (textptr
- text
) >= (PPD_MAX_LINE
- 1))
3110 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3114 *textptr
++ = *lineptr
++;
3118 textlen
= ppd_decode(text
);
3120 if (textlen
> PPD_MAX_TEXT
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3122 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3130 if (_cups_isspace(*lineptr
) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3132 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3136 while (_cups_isspace(*lineptr
))
3139 if (*lineptr
== ':')
3142 * Get string after triming leading and trailing whitespace...
3146 while (_cups_isspace(*lineptr
))
3149 strptr
= lineptr
+ strlen(lineptr
) - 1;
3150 while (strptr
>= lineptr
&& _cups_isspace(*strptr
))
3153 if (*strptr
== '\"')
3156 * Quoted string by itself, remove quotes...
3163 *string
= _cupsStrAlloc(lineptr
);
3175 * 'ppd_update_filters()' - Update the filters array as needed.
3177 * This function re-populates the filters array with cupsFilter2 entries that
3178 * have been stripped of the destination MIME media types and any maxsize hints.
3180 * (All for backwards-compatibility)
3183 static int /* O - 1 on success, 0 on failure */
3184 ppd_update_filters(ppd_file_t
*ppd
,/* I - PPD file */
3185 _cups_globals_t
*cg
) /* I - Global data */
3187 ppd_attr_t
*attr
; /* Current cupsFilter2 value */
3188 char srcsuper
[16], /* Source MIME media type */
3190 dstsuper
[16], /* Destination MIME media type */
3192 program
[1024], /* Command to run */
3193 *ptr
, /* Pointer into command to run */
3194 buffer
[1024], /* Re-written cupsFilter value */
3195 **filter
; /* Current filter */
3196 int cost
; /* Cost of filter */
3199 DEBUG_printf(("4ppd_update_filters(ppd=%p, cg=%p)", ppd
, cg
));
3202 * See if we have any cupsFilter2 lines...
3205 if ((attr
= ppdFindAttr(ppd
, "cupsFilter2", NULL
)) == NULL
)
3207 DEBUG_puts("5ppd_update_filters: No cupsFilter2 keywords present.");
3212 * Yes, free the cupsFilter-defined filters and re-build...
3215 ppd_free_filters(ppd
);
3220 * Parse the cupsFilter2 string:
3222 * src/type dst/type cost program
3223 * src/type dst/type cost maxsize(n) program
3226 DEBUG_printf(("5ppd_update_filters: cupsFilter2=\"%s\"", attr
->value
));
3228 if (sscanf(attr
->value
, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
3229 srcsuper
, srctype
, dstsuper
, dsttype
, &cost
, program
) != 6)
3231 DEBUG_puts("5ppd_update_filters: Bad cupsFilter2 line.");
3232 cg
->ppd_status
= PPD_BAD_VALUE
;
3237 DEBUG_printf(("5ppd_update_filters: srcsuper=\"%s\", srctype=\"%s\", "
3238 "dstsuper=\"%s\", dsttype=\"%s\", cost=%d, program=\"%s\"",
3239 srcsuper
, srctype
, dstsuper
, dsttype
, cost
, program
));
3241 if (!strncmp(program
, "maxsize(", 8) &&
3242 (ptr
= strchr(program
+ 8, ')')) != NULL
)
3244 DEBUG_puts("5ppd_update_filters: Found maxsize(nnn).");
3247 while (_cups_isspace(*ptr
))
3250 _cups_strcpy(program
, ptr
);
3251 DEBUG_printf(("5ppd_update_filters: New program=\"%s\"", program
));
3255 * Convert to cupsFilter format:
3257 * src/type cost program
3260 snprintf(buffer
, sizeof(buffer
), "%s/%s %d %s", srcsuper
, srctype
, cost
,
3262 DEBUG_printf(("5ppd_update_filters: Adding \"%s\".", buffer
));
3265 * Add a cupsFilter-compatible string to the filters array.
3268 if (ppd
->num_filters
== 0)
3269 filter
= malloc(sizeof(char *));
3271 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
3275 DEBUG_puts("5ppd_update_filters: Out of memory.");
3276 cg
->ppd_status
= PPD_ALLOC_ERROR
;
3281 ppd
->filters
= filter
;
3282 filter
+= ppd
->num_filters
;
3283 ppd
->num_filters
++;
3285 *filter
= _cupsStrAlloc(buffer
);
3287 while ((attr
= ppdFindNextAttr(ppd
, "cupsFilter2", NULL
)) != NULL
);
3289 DEBUG_puts("5ppd_update_filters: Completed OK.");
3295 * End of "$Id: ppd.c 9900 2011-08-17 20:59:46Z mike $".