2 * "$Id: ppd.c 7906 2008-09-03 20:19:43Z 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_group() - Free a single UI group.
47 * ppd_free_option() - Free a single option.
48 * ppd_get_coption() - Get a custom option record.
49 * ppd_get_cparam() - Get a custom parameter record.
50 * ppd_get_group() - Find or create the named group as needed.
51 * ppd_get_option() - Find or create the named option as needed.
52 * ppd_hash_option() - Generate a hash of the option name...
53 * ppd_read() - Read a line from a PPD file, skipping comment
58 * Include necessary headers.
61 #include "cups-private.h"
62 #include "ppd-private.h"
69 #if defined(WIN32) || defined(__EMX__)
70 # define READ_BINARY "rb" /* Open a binary file for reading */
71 # define WRITE_BINARY "wb" /* Open a binary file for writing */
73 # define READ_BINARY "r" /* Open a binary file for reading */
74 # define WRITE_BINARY "w" /* Open a binary file for writing */
75 #endif /* WIN32 || __EMX__ */
77 #define ppd_free(p) if (p) free(p) /* Safe free macro */
79 #define PPD_KEYWORD 1 /* Line contained a keyword */
80 #define PPD_OPTION 2 /* Line contained an option name */
81 #define PPD_TEXT 4 /* Line contained human-readable text */
82 #define PPD_STRING 8 /* Line contained a string or code */
84 #define PPD_HASHSIZE 512 /* Size of hash */
88 * Line buffer structure...
91 typedef struct _ppd_line_s
93 char *buffer
; /* Pointer to buffer */
94 size_t bufsize
; /* Size of the buffer */
102 static ppd_attr_t
*ppd_add_attr(ppd_file_t
*ppd
, const char *name
,
103 const char *spec
, const char *text
,
105 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, const char *name
);
106 static ppd_size_t
*ppd_add_size(ppd_file_t
*ppd
, const char *name
);
107 static int ppd_compare_attrs(ppd_attr_t
*a
, ppd_attr_t
*b
);
108 static int ppd_compare_choices(ppd_choice_t
*a
, ppd_choice_t
*b
);
109 static int ppd_compare_coptions(ppd_coption_t
*a
,
111 static int ppd_compare_options(ppd_option_t
*a
, ppd_option_t
*b
);
112 static int ppd_decode(char *string
);
113 static void ppd_free_group(ppd_group_t
*group
);
114 static void ppd_free_option(ppd_option_t
*option
);
115 static ppd_coption_t
*ppd_get_coption(ppd_file_t
*ppd
, const char *name
);
116 static ppd_cparam_t
*ppd_get_cparam(ppd_coption_t
*opt
,
119 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, const char *name
,
120 const char *text
, _cups_globals_t
*cg
,
121 cups_encoding_t encoding
);
122 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, const char *name
);
123 static int ppd_hash_option(ppd_option_t
*option
);
124 static int ppd_read(cups_file_t
*fp
, _ppd_line_t
*line
,
125 char *keyword
, char *option
, char *text
,
126 char **string
, int ignoreblank
,
127 _cups_globals_t
*cg
);
131 * 'ppdClose()' - Free all memory used by the PPD file.
135 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
137 int i
; /* Looping var */
138 ppd_emul_t
*emul
; /* Current emulation */
139 ppd_group_t
*group
; /* Current group */
140 char **font
; /* Current font */
141 char **filter
; /* Current filter */
142 ppd_attr_t
**attr
; /* Current attribute */
143 ppd_coption_t
*coption
; /* Current custom option */
144 ppd_cparam_t
*cparam
; /* Current custom parameter */
148 * Range check arguments...
155 * Free all strings at the top level...
158 _cupsStrFree(ppd
->lang_encoding
);
159 _cupsStrFree(ppd
->nickname
);
162 _cupsStrFree(ppd
->jcl_begin
);
163 _cupsStrFree(ppd
->jcl_end
);
164 _cupsStrFree(ppd
->jcl_ps
);
167 * Free any emulations...
170 if (ppd
->num_emulations
> 0)
172 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
174 _cupsStrFree(emul
->start
);
175 _cupsStrFree(emul
->stop
);
178 ppd_free(ppd
->emulations
);
182 * Free any UI groups, subgroups, and options...
185 if (ppd
->num_groups
> 0)
187 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
188 ppd_free_group(group
);
190 ppd_free(ppd
->groups
);
193 cupsArrayDelete(ppd
->options
);
194 cupsArrayDelete(ppd
->marked
);
197 * Free any page sizes...
200 if (ppd
->num_sizes
> 0)
201 ppd_free(ppd
->sizes
);
204 * Free any constraints...
207 if (ppd
->num_consts
> 0)
208 ppd_free(ppd
->consts
);
211 * Free any filters...
214 if (ppd
->num_filters
> 0)
216 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
217 _cupsStrFree(*filter
);
219 ppd_free(ppd
->filters
);
226 if (ppd
->num_fonts
> 0)
228 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
231 ppd_free(ppd
->fonts
);
235 * Free any profiles...
238 if (ppd
->num_profiles
> 0)
239 ppd_free(ppd
->profiles
);
242 * Free any attributes...
245 if (ppd
->num_attrs
> 0)
247 for (i
= ppd
->num_attrs
, attr
= ppd
->attrs
; i
> 0; i
--, attr
++)
249 _cupsStrFree((*attr
)->value
);
253 ppd_free(ppd
->attrs
);
256 cupsArrayDelete(ppd
->sorted_attrs
);
259 * Free custom options...
262 for (coption
= (ppd_coption_t
*)cupsArrayFirst(ppd
->coptions
);
264 coption
= (ppd_coption_t
*)cupsArrayNext(ppd
->coptions
))
266 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
268 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
270 switch (cparam
->type
)
272 case PPD_CUSTOM_PASSCODE
:
273 case PPD_CUSTOM_PASSWORD
:
274 case PPD_CUSTOM_STRING
:
275 _cupsStrFree(cparam
->current
.custom_string
);
285 cupsArrayDelete(coption
->params
);
290 cupsArrayDelete(ppd
->coptions
);
293 * Free constraints...
296 if (ppd
->cups_uiconstraints
)
298 _ppd_cups_uiconsts_t
*consts
; /* Current constraints */
301 for (consts
= (_ppd_cups_uiconsts_t
*)cupsArrayFirst(ppd
->cups_uiconstraints
);
303 consts
= (_ppd_cups_uiconsts_t
*)cupsArrayNext(ppd
->cups_uiconstraints
))
305 free(consts
->constraints
);
309 cupsArrayDelete(ppd
->cups_uiconstraints
);
313 * Free any PPD cache/mapping data...
317 _ppdCacheDestroy(ppd
->cache
);
320 * Free the whole record...
328 * 'ppdErrorString()' - Returns the text assocated with a status.
330 * @since CUPS 1.1.19/Mac OS X 10.3@
333 const char * /* O - Status string */
334 ppdErrorString(ppd_status_t status
) /* I - PPD status */
336 static const char * const messages
[] =/* Status messages */
339 _("Unable to open PPD file"),
340 _("NULL PPD file pointer"),
341 _("Memory allocation error"),
342 _("Missing PPD-Adobe-4.x header"),
343 _("Missing value string"),
346 _("OpenGroup without a CloseGroup first"),
347 _("Bad OpenUI/JCLOpenUI"),
348 _("OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first"),
349 _("Bad OrderDependency"),
350 _("Bad UIConstraints"),
351 _("Missing asterisk in column 1"),
352 _("Line longer than the maximum allowed (255 characters)"),
353 _("Illegal control character"),
354 _("Illegal main keyword string"),
355 _("Illegal option keyword string"),
356 _("Illegal translation string"),
357 _("Illegal whitespace character"),
358 _("Bad custom parameter"),
359 _("Missing option keyword"),
360 _("Bad value string"),
361 _("Missing CloseGroup")
365 if (status
< PPD_OK
|| status
>= PPD_MAX_STATUS
)
366 return (_cupsLangString(cupsLangDefault(), _("Unknown")));
368 return (_cupsLangString(cupsLangDefault(), messages
[status
]));
373 * '_ppdGetEncoding()' - Get the CUPS encoding value for the given
377 cups_encoding_t
/* O - CUPS encoding value */
378 _ppdGetEncoding(const char *name
) /* I - LanguageEncoding string */
380 if (!strcasecmp(name
, "ISOLatin1"))
381 return (CUPS_ISO8859_1
);
382 else if (!strcasecmp(name
, "ISOLatin2"))
383 return (CUPS_ISO8859_2
);
384 else if (!strcasecmp(name
, "ISOLatin5"))
385 return (CUPS_ISO8859_5
);
386 else if (!strcasecmp(name
, "JIS83-RKSJ"))
387 return (CUPS_JIS_X0213
);
388 else if (!strcasecmp(name
, "MacStandard"))
389 return (CUPS_MAC_ROMAN
);
390 else if (!strcasecmp(name
, "WindowsANSI"))
391 return (CUPS_WINDOWS_1252
);
398 * 'ppdLastError()' - Return the status from the last ppdOpen*().
400 * @since CUPS 1.1.19/Mac OS X 10.3@
403 ppd_status_t
/* O - Status code */
404 ppdLastError(int *line
) /* O - Line number */
406 _cups_globals_t
*cg
= _cupsGlobals();
411 *line
= cg
->ppd_line
;
413 return (cg
->ppd_status
);
418 * 'ppdOpen()' - Read a PPD file into memory.
421 ppd_file_t
* /* O - PPD file record */
422 ppdOpen(FILE *fp
) /* I - File to read from */
424 ppd_file_t
*ppd
; /* PPD file record */
425 cups_file_t
*cf
; /* CUPS file */
429 * Reopen the stdio file as a CUPS file...
432 if ((cf
= cupsFileOpenFd(fileno(fp
), "r")) == NULL
)
436 * Load the PPD file using the newer API...
442 * Close the CUPS file and return the PPD...
452 * 'ppdOpen2()' - Read a PPD file into memory.
454 * @since CUPS 1.2/Mac OS X 10.5@
457 ppd_file_t
* /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
458 ppdOpen2(cups_file_t
*fp
) /* I - File to read from */
460 int i
, j
, k
; /* Looping vars */
461 int count
; /* Temporary count */
462 _ppd_line_t line
; /* Line buffer */
463 ppd_file_t
*ppd
; /* PPD file record */
464 ppd_group_t
*group
, /* Current group */
465 *subgroup
; /* Current sub-group */
466 ppd_option_t
*option
; /* Current option */
467 ppd_choice_t
*choice
; /* Current choice */
468 ppd_const_t
*constraint
; /* Current constraint */
469 ppd_size_t
*size
; /* Current page size */
470 int mask
; /* Line data mask */
471 char keyword
[PPD_MAX_NAME
],
472 /* Keyword from file */
474 /* Option from file */
476 /* Human-readable text from file */
477 *string
, /* Code/text from file */
478 *sptr
, /* Pointer into string */
479 *nameptr
, /* Pointer into name */
480 *temp
, /* Temporary string pointer */
481 **tempfonts
; /* Temporary fonts pointer */
482 float order
; /* Order dependency number */
483 ppd_section_t section
; /* Order dependency section */
484 ppd_profile_t
*profile
; /* Pointer to color profile */
485 char **filter
; /* Pointer to filter */
486 cups_lang_t
*language
; /* Default language */
487 struct lconv
*loc
; /* Locale data */
488 int ui_keyword
; /* Is this line a UI keyword? */
489 cups_encoding_t encoding
; /* Encoding of PPD file */
490 _cups_globals_t
*cg
= _cupsGlobals();
492 char custom_name
[PPD_MAX_NAME
];
493 /* CustomFoo attribute name */
494 ppd_attr_t
*custom_attr
; /* CustomFoo attribute */
495 static const char * const ui_keywords
[] =
497 #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST
499 * Adobe defines some 41 keywords as "UI", meaning that they are
500 * user interface elements and that they should be treated as such
501 * even if the PPD creator doesn't use Open/CloseUI around them.
503 * Since this can cause previously invisible options to appear and
504 * confuse users, the default is to only treat the PageSize and
505 * PageRegion keywords this way.
507 /* Boolean keywords */
517 /* PickOne keywords */
530 "JCLFrameBufferSize",
551 #else /* !CUPS_USE_FULL_UI_KEYWORDS_LIST */
554 #endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */
558 DEBUG_printf(("ppdOpen2(fp=%p)", fp
));
561 * Default to "OK" status...
564 cg
->ppd_status
= PPD_OK
;
568 * Range check input...
573 cg
->ppd_status
= PPD_NULL_FILE
;
578 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
584 mask
= ppd_read(fp
, &line
, keyword
, name
, text
, &string
, 0, cg
);
586 DEBUG_printf(("2ppdOpen2: mask=%x, keyword=\"%s\"...", mask
, keyword
));
589 strcmp(keyword
, "PPD-Adobe") ||
590 string
== NULL
|| string
[0] != '4')
593 * Either this is not a PPD file, or it is not a 4.x PPD file.
596 if (cg
->ppd_status
== PPD_OK
)
597 cg
->ppd_status
= PPD_MISSING_PPDADOBE4
;
599 _cupsStrFree(string
);
600 ppd_free(line
.buffer
);
605 DEBUG_printf(("2ppdOpen2: keyword=%s, string=%p", keyword
, string
));
607 _cupsStrFree(string
);
610 * Allocate memory for the PPD file record...
613 if ((ppd
= calloc(1, sizeof(ppd_file_t
))) == NULL
)
615 cg
->ppd_status
= PPD_ALLOC_ERROR
;
617 _cupsStrFree(string
);
618 ppd_free(line
.buffer
);
623 ppd
->language_level
= 2;
624 ppd
->color_device
= 0;
625 ppd
->colorspace
= PPD_CS_N
;
626 ppd
->landscape
= -90;
627 ppd
->coptions
= cupsArrayNew((cups_array_func_t
)ppd_compare_coptions
,
631 * Get the default language for the user...
634 language
= cupsLangDefault();
638 * Read lines from the PPD file and add them to the file record...
646 encoding
= CUPS_ISO8859_1
;
648 while ((mask
= ppd_read(fp
, &line
, keyword
, name
, text
, &string
, 1, cg
)) != 0)
650 DEBUG_printf(("2ppdOpen2: mask=%x, keyword=\"%s\", name=\"%s\", "
651 "text=\"%s\", string=%d chars...", mask
, keyword
, name
, text
,
652 string
? (int)strlen(string
) : 0));
654 if (strncmp(keyword
, "Default", 7) && !string
&&
655 cg
->ppd_conform
!= PPD_CONFORM_RELAXED
)
658 * Need a string value!
661 cg
->ppd_status
= PPD_MISSING_VALUE
;
669 * Certain main keywords (as defined by the PPD spec) may be used
670 * without the usual OpenUI/CloseUI stuff. Presumably this is just
671 * so that Adobe wouldn't completely break compatibility with PPD
672 * files prior to v4.0 of the spec, but it is hopelessly
673 * inconsistent... Catch these main keywords and automatically
674 * create the corresponding option, as needed...
680 * Previous line was a UI keyword...
687 if (option
== NULL
&&
688 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
689 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
691 for (i
= 0; i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])); i
++)
692 if (!strcmp(keyword
, ui_keywords
[i
]))
695 if (i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])))
698 * Create the option in the appropriate group...
703 DEBUG_printf(("2ppdOpen2: FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!",
708 if ((group
= ppd_get_group(ppd
, "General", _("General"), cg
,
712 DEBUG_printf(("2ppdOpen2: Adding to group %s...", group
->text
));
713 option
= ppd_get_option(group
, keyword
);
717 option
= ppd_get_option(group
, keyword
);
721 cg
->ppd_status
= PPD_ALLOC_ERROR
;
727 * Now fill in the initial information for the option...
730 if (!strncmp(keyword
, "JCL", 3))
731 option
->section
= PPD_ORDER_JCL
;
733 option
->section
= PPD_ORDER_ANY
;
735 option
->order
= 10.0f
;
738 option
->ui
= PPD_UI_BOOLEAN
;
740 option
->ui
= PPD_UI_PICKONE
;
742 for (j
= 0; j
< ppd
->num_attrs
; j
++)
743 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
744 !strcmp(ppd
->attrs
[j
]->name
+ 7, keyword
) &&
745 ppd
->attrs
[j
]->value
)
747 DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
748 option
->keyword
, ppd
->attrs
[j
]->value
));
749 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
750 sizeof(option
->defchoice
));
754 if (!strcmp(keyword
, "PageSize"))
755 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
756 else if (!strcmp(keyword
, "MediaType"))
757 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
758 else if (!strcmp(keyword
, "InputSlot"))
759 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
760 else if (!strcmp(keyword
, "ColorModel"))
761 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
762 else if (!strcmp(keyword
, "Resolution"))
763 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
765 strlcpy(option
->text
, keyword
, sizeof(option
->text
));
769 if (!strcmp(keyword
, "LanguageLevel"))
770 ppd
->language_level
= atoi(string
);
771 else if (!strcmp(keyword
, "LanguageEncoding"))
774 * Say all PPD files are UTF-8, since we convert to UTF-8...
777 ppd
->lang_encoding
= _cupsStrAlloc("UTF-8");
778 encoding
= _ppdGetEncoding(string
);
780 else if (!strcmp(keyword
, "LanguageVersion"))
781 ppd
->lang_version
= string
;
782 else if (!strcmp(keyword
, "Manufacturer"))
783 ppd
->manufacturer
= string
;
784 else if (!strcmp(keyword
, "ModelName"))
785 ppd
->modelname
= string
;
786 else if (!strcmp(keyword
, "Protocols"))
787 ppd
->protocols
= string
;
788 else if (!strcmp(keyword
, "PCFileName"))
789 ppd
->pcfilename
= string
;
790 else if (!strcmp(keyword
, "NickName"))
792 if (encoding
!= CUPS_UTF8
)
794 cups_utf8_t utf8
[256]; /* UTF-8 version of NickName */
797 cupsCharsetToUTF8(utf8
, string
, sizeof(utf8
), encoding
);
798 ppd
->nickname
= _cupsStrAlloc((char *)utf8
);
801 ppd
->nickname
= _cupsStrAlloc(string
);
803 else if (!strcmp(keyword
, "Product"))
804 ppd
->product
= string
;
805 else if (!strcmp(keyword
, "ShortNickName"))
806 ppd
->shortnickname
= string
;
807 else if (!strcmp(keyword
, "TTRasterizer"))
808 ppd
->ttrasterizer
= string
;
809 else if (!strcmp(keyword
, "JCLBegin"))
811 ppd
->jcl_begin
= _cupsStrAlloc(string
);
812 ppd_decode(ppd
->jcl_begin
); /* Decode quoted string */
814 else if (!strcmp(keyword
, "JCLEnd"))
816 ppd
->jcl_end
= _cupsStrAlloc(string
);
817 ppd_decode(ppd
->jcl_end
); /* Decode quoted string */
819 else if (!strcmp(keyword
, "JCLToPSInterpreter"))
821 ppd
->jcl_ps
= _cupsStrAlloc(string
);
822 ppd_decode(ppd
->jcl_ps
); /* Decode quoted string */
824 else if (!strcmp(keyword
, "AccurateScreensSupport"))
825 ppd
->accurate_screens
= !strcmp(string
, "True");
826 else if (!strcmp(keyword
, "ColorDevice"))
827 ppd
->color_device
= !strcmp(string
, "True");
828 else if (!strcmp(keyword
, "ContoneOnly"))
829 ppd
->contone_only
= !strcmp(string
, "True");
830 else if (!strcmp(keyword
, "cupsFlipDuplex"))
831 ppd
->flip_duplex
= !strcmp(string
, "True");
832 else if (!strcmp(keyword
, "cupsManualCopies"))
833 ppd
->manual_copies
= !strcmp(string
, "True");
834 else if (!strcmp(keyword
, "cupsModelNumber"))
835 ppd
->model_number
= atoi(string
);
836 else if (!strcmp(keyword
, "cupsColorProfile"))
838 if (ppd
->num_profiles
== 0)
839 profile
= malloc(sizeof(ppd_profile_t
));
841 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
842 (ppd
->num_profiles
+ 1));
846 cg
->ppd_status
= PPD_ALLOC_ERROR
;
851 ppd
->profiles
= profile
;
852 profile
+= ppd
->num_profiles
;
853 ppd
->num_profiles
++;
855 memset(profile
, 0, sizeof(ppd_profile_t
));
856 strlcpy(profile
->resolution
, name
, sizeof(profile
->resolution
));
857 strlcpy(profile
->media_type
, text
, sizeof(profile
->media_type
));
859 profile
->density
= (float)_cupsStrScand(string
, &sptr
, loc
);
860 profile
->gamma
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
861 profile
->matrix
[0][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
862 profile
->matrix
[0][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
863 profile
->matrix
[0][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
864 profile
->matrix
[1][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
865 profile
->matrix
[1][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
866 profile
->matrix
[1][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
867 profile
->matrix
[2][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
868 profile
->matrix
[2][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
869 profile
->matrix
[2][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
871 else if (!strcmp(keyword
, "cupsFilter"))
873 if (ppd
->num_filters
== 0)
874 filter
= malloc(sizeof(char *));
876 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
880 cg
->ppd_status
= PPD_ALLOC_ERROR
;
885 ppd
->filters
= filter
;
886 filter
+= ppd
->num_filters
;
890 * Copy filter string and prevent it from being freed below...
896 else if (!strcmp(keyword
, "Throughput"))
897 ppd
->throughput
= atoi(string
);
898 else if (!strcmp(keyword
, "Font"))
901 * Add this font to the list of available fonts...
904 if (ppd
->num_fonts
== 0)
905 tempfonts
= (char **)malloc(sizeof(char *));
907 tempfonts
= (char **)realloc(ppd
->fonts
,
908 sizeof(char *) * (ppd
->num_fonts
+ 1));
910 if (tempfonts
== NULL
)
912 cg
->ppd_status
= PPD_ALLOC_ERROR
;
917 ppd
->fonts
= tempfonts
;
918 ppd
->fonts
[ppd
->num_fonts
] = _cupsStrAlloc(name
);
921 else if (!strncmp(keyword
, "ParamCustom", 11))
923 ppd_coption_t
*coption
; /* Custom option */
924 ppd_cparam_t
*cparam
; /* Custom parameter */
925 int corder
; /* Order number */
926 char ctype
[33], /* Data type */
927 cminimum
[65], /* Minimum value */
928 cmaximum
[65]; /* Maximum value */
932 * Get the custom option and parameter...
935 if ((coption
= ppd_get_coption(ppd
, keyword
+ 11)) == NULL
)
937 cg
->ppd_status
= PPD_ALLOC_ERROR
;
942 if ((cparam
= ppd_get_cparam(coption
, name
, text
)) == NULL
)
944 cg
->ppd_status
= PPD_ALLOC_ERROR
;
950 * Get the parameter data...
954 sscanf(string
, "%d%32s%64s%64s", &corder
, ctype
, cminimum
,
957 cg
->ppd_status
= PPD_BAD_CUSTOM_PARAM
;
962 cparam
->order
= corder
;
964 if (!strcmp(ctype
, "curve"))
966 cparam
->type
= PPD_CUSTOM_CURVE
;
967 cparam
->minimum
.custom_curve
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
968 cparam
->maximum
.custom_curve
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
970 else if (!strcmp(ctype
, "int"))
972 cparam
->type
= PPD_CUSTOM_INT
;
973 cparam
->minimum
.custom_int
= atoi(cminimum
);
974 cparam
->maximum
.custom_int
= atoi(cmaximum
);
976 else if (!strcmp(ctype
, "invcurve"))
978 cparam
->type
= PPD_CUSTOM_INVCURVE
;
979 cparam
->minimum
.custom_invcurve
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
980 cparam
->maximum
.custom_invcurve
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
982 else if (!strcmp(ctype
, "passcode"))
984 cparam
->type
= PPD_CUSTOM_PASSCODE
;
985 cparam
->minimum
.custom_passcode
= atoi(cminimum
);
986 cparam
->maximum
.custom_passcode
= atoi(cmaximum
);
988 else if (!strcmp(ctype
, "password"))
990 cparam
->type
= PPD_CUSTOM_PASSWORD
;
991 cparam
->minimum
.custom_password
= atoi(cminimum
);
992 cparam
->maximum
.custom_password
= atoi(cmaximum
);
994 else if (!strcmp(ctype
, "points"))
996 cparam
->type
= PPD_CUSTOM_POINTS
;
997 cparam
->minimum
.custom_points
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
998 cparam
->maximum
.custom_points
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
1000 else if (!strcmp(ctype
, "real"))
1002 cparam
->type
= PPD_CUSTOM_REAL
;
1003 cparam
->minimum
.custom_real
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
1004 cparam
->maximum
.custom_real
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
1006 else if (!strcmp(ctype
, "string"))
1008 cparam
->type
= PPD_CUSTOM_STRING
;
1009 cparam
->minimum
.custom_string
= atoi(cminimum
);
1010 cparam
->maximum
.custom_string
= atoi(cmaximum
);
1014 cg
->ppd_status
= PPD_BAD_CUSTOM_PARAM
;
1020 * Now special-case for CustomPageSize...
1023 if (!strcmp(coption
->keyword
, "PageSize"))
1025 if (!strcmp(name
, "Width"))
1027 ppd
->custom_min
[0] = cparam
->minimum
.custom_points
;
1028 ppd
->custom_max
[0] = cparam
->maximum
.custom_points
;
1030 else if (!strcmp(name
, "Height"))
1032 ppd
->custom_min
[1] = cparam
->minimum
.custom_points
;
1033 ppd
->custom_max
[1] = cparam
->maximum
.custom_points
;
1037 else if (!strcmp(keyword
, "HWMargins"))
1039 for (i
= 0, sptr
= string
; i
< 4; i
++)
1040 ppd
->custom_margins
[i
] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
1042 else if (!strncmp(keyword
, "Custom", 6) && !strcmp(name
, "True") && !option
)
1044 ppd_option_t
*custom_option
; /* Custom option */
1046 DEBUG_puts("2ppdOpen2: Processing Custom option...");
1049 * Get the option and custom option...
1052 if (!ppd_get_coption(ppd
, keyword
+ 6))
1054 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1059 if (option
&& !strcasecmp(option
->keyword
, keyword
+ 6))
1060 custom_option
= option
;
1062 custom_option
= ppdFindOption(ppd
, keyword
+ 6);
1067 * Add the "custom" option...
1070 if ((choice
= ppdFindChoice(custom_option
, "Custom")) == NULL
)
1071 if ((choice
= ppd_add_choice(custom_option
, "Custom")) == NULL
)
1073 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1075 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1080 strlcpy(choice
->text
, text
[0] ? text
: _("Custom"),
1081 sizeof(choice
->text
));
1083 choice
->code
= _cupsStrAlloc(string
);
1085 if (custom_option
->section
== PPD_ORDER_JCL
)
1086 ppd_decode(choice
->code
);
1090 * Now process custom page sizes specially...
1093 if (!strcmp(keyword
, "CustomPageSize"))
1096 * Add a "Custom" page size entry...
1099 ppd
->variable_sizes
= 1;
1101 ppd_add_size(ppd
, "Custom");
1103 if (option
&& !strcasecmp(option
->keyword
, "PageRegion"))
1104 custom_option
= option
;
1106 custom_option
= ppdFindOption(ppd
, "PageRegion");
1110 if ((choice
= ppdFindChoice(custom_option
, "Custom")) == NULL
)
1111 if ((choice
= ppd_add_choice(custom_option
, "Custom")) == NULL
)
1113 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1115 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1120 strlcpy(choice
->text
, text
[0] ? text
: _("Custom"),
1121 sizeof(choice
->text
));
1125 else if (!strcmp(keyword
, "LandscapeOrientation"))
1127 if (!strcmp(string
, "Minus90"))
1128 ppd
->landscape
= -90;
1129 else if (!strcmp(string
, "Plus90"))
1130 ppd
->landscape
= 90;
1132 else if (!strcmp(keyword
, "Emulators") && string
)
1134 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
1135 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
1138 while (*sptr
== ' ')
1142 ppd
->num_emulations
= count
;
1143 if ((ppd
->emulations
= calloc(count
, sizeof(ppd_emul_t
))) == NULL
)
1145 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1150 for (i
= 0, sptr
= string
; i
< count
; i
++)
1152 for (nameptr
= ppd
->emulations
[i
].name
;
1153 *sptr
!= '\0' && *sptr
!= ' ';
1155 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
1160 while (*sptr
== ' ')
1164 else if (!strncmp(keyword
, "StartEmulator_", 14))
1168 for (i
= 0; i
< ppd
->num_emulations
; i
++)
1169 if (!strcmp(keyword
+ 14, ppd
->emulations
[i
].name
))
1171 ppd
->emulations
[i
].start
= string
;
1175 else if (!strncmp(keyword
, "StopEmulator_", 13))
1179 for (i
= 0; i
< ppd
->num_emulations
; i
++)
1180 if (!strcmp(keyword
+ 13, ppd
->emulations
[i
].name
))
1182 ppd
->emulations
[i
].stop
= string
;
1186 else if (!strcmp(keyword
, "JobPatchFile"))
1189 * CUPS STR #3421: Check for "*JobPatchFile: int: string"
1192 if (isdigit(*string
& 255))
1194 for (sptr
= string
+ 1; isdigit(*sptr
& 255); sptr
++);
1199 * Found "*JobPatchFile: int: string"...
1202 cg
->ppd_status
= PPD_BAD_VALUE
;
1208 if (!name
[0] && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1211 * Found "*JobPatchFile: string"...
1214 cg
->ppd_status
= PPD_MISSING_OPTION_KEYWORD
;
1219 if (ppd
->patches
== NULL
)
1220 ppd
->patches
= strdup(string
);
1223 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
1224 strlen(string
) + 1);
1227 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1232 ppd
->patches
= temp
;
1234 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
1237 else if (!strcmp(keyword
, "OpenUI"))
1240 * Don't allow nesting of options...
1243 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1245 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1251 * Add an option record to the current sub-group, group, or file...
1254 DEBUG_printf(("2ppdOpen2: name=\"%s\" (%d)", name
, (int)strlen(name
)));
1257 _cups_strcpy(name
, name
+ 1); /* Eliminate leading asterisk */
1259 for (i
= (int)strlen(name
) - 1; i
> 0 && _cups_isspace(name
[i
]); i
--)
1260 name
[i
] = '\0'; /* Eliminate trailing spaces */
1262 DEBUG_printf(("2ppdOpen2: OpenUI of %s in group %s...", name
,
1263 group
? group
->text
: "(null)"));
1265 if (subgroup
!= NULL
)
1266 option
= ppd_get_option(subgroup
, name
);
1267 else if (group
== NULL
)
1269 if ((group
= ppd_get_group(ppd
, "General", _("General"), cg
,
1273 DEBUG_printf(("2ppdOpen2: Adding to group %s...", group
->text
));
1274 option
= ppd_get_option(group
, name
);
1278 option
= ppd_get_option(group
, name
);
1282 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1288 * Now fill in the initial information for the option...
1291 if (string
&& !strcmp(string
, "PickMany"))
1292 option
->ui
= PPD_UI_PICKMANY
;
1293 else if (string
&& !strcmp(string
, "Boolean"))
1294 option
->ui
= PPD_UI_BOOLEAN
;
1295 else if (string
&& !strcmp(string
, "PickOne"))
1296 option
->ui
= PPD_UI_PICKONE
;
1297 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1299 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1304 option
->ui
= PPD_UI_PICKONE
;
1306 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1307 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1308 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1309 ppd
->attrs
[j
]->value
)
1311 DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
1312 option
->keyword
, ppd
->attrs
[j
]->value
));
1313 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1314 sizeof(option
->defchoice
));
1319 cupsCharsetToUTF8((cups_utf8_t
*)option
->text
, text
,
1320 sizeof(option
->text
), encoding
);
1323 if (!strcmp(name
, "PageSize"))
1324 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
1325 else if (!strcmp(name
, "MediaType"))
1326 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
1327 else if (!strcmp(name
, "InputSlot"))
1328 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
1329 else if (!strcmp(name
, "ColorModel"))
1330 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
1331 else if (!strcmp(name
, "Resolution"))
1332 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
1334 strlcpy(option
->text
, name
, sizeof(option
->text
));
1337 option
->section
= PPD_ORDER_ANY
;
1339 _cupsStrFree(string
);
1343 * Add a custom option choice if we have already seen a CustomFoo
1347 if (!strcasecmp(name
, "PageRegion"))
1348 strcpy(custom_name
, "CustomPageSize");
1350 snprintf(custom_name
, sizeof(custom_name
), "Custom%s", name
);
1352 if ((custom_attr
= ppdFindAttr(ppd
, custom_name
, "True")) != NULL
)
1354 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
1355 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
1357 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1359 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1364 strlcpy(choice
->text
,
1365 custom_attr
->text
[0] ? custom_attr
->text
: _("Custom"),
1366 sizeof(choice
->text
));
1367 choice
->code
= _cupsStrRetain(custom_attr
->value
);
1370 else if (!strcmp(keyword
, "JCLOpenUI"))
1373 * Don't allow nesting of options...
1376 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1378 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1384 * Find the JCL group, and add if needed...
1387 group
= ppd_get_group(ppd
, "JCL", _("JCL"), cg
, encoding
);
1393 * Add an option record to the current JCLs...
1397 _cups_strcpy(name
, name
+ 1);
1399 option
= ppd_get_option(group
, name
);
1403 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1409 * Now fill in the initial information for the option...
1412 if (string
&& !strcmp(string
, "PickMany"))
1413 option
->ui
= PPD_UI_PICKMANY
;
1414 else if (string
&& !strcmp(string
, "Boolean"))
1415 option
->ui
= PPD_UI_BOOLEAN
;
1416 else if (string
&& !strcmp(string
, "PickOne"))
1417 option
->ui
= PPD_UI_PICKONE
;
1420 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1425 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1426 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1427 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1428 ppd
->attrs
[j
]->value
)
1430 DEBUG_printf(("2ppdOpen2: Setting Default%s to %s via attribute...",
1431 option
->keyword
, ppd
->attrs
[j
]->value
));
1432 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1433 sizeof(option
->defchoice
));
1438 cupsCharsetToUTF8((cups_utf8_t
*)option
->text
, text
,
1439 sizeof(option
->text
), encoding
);
1441 strlcpy(option
->text
, name
, sizeof(option
->text
));
1443 option
->section
= PPD_ORDER_JCL
;
1446 _cupsStrFree(string
);
1450 * Add a custom option choice if we have already seen a CustomFoo
1454 snprintf(custom_name
, sizeof(custom_name
), "Custom%s", name
);
1456 if ((custom_attr
= ppdFindAttr(ppd
, custom_name
, "True")) != NULL
)
1458 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
1460 DEBUG_puts("1ppdOpen2: Unable to add Custom choice!");
1462 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1467 strlcpy(choice
->text
,
1468 custom_attr
->text
[0] ? custom_attr
->text
: _("Custom"),
1469 sizeof(choice
->text
));
1470 choice
->code
= _cupsStrRetain(custom_attr
->value
);
1473 else if (!strcmp(keyword
, "CloseUI") || !strcmp(keyword
, "JCLCloseUI"))
1477 _cupsStrFree(string
);
1480 else if (!strcmp(keyword
, "OpenGroup"))
1483 * Open a new group...
1488 cg
->ppd_status
= PPD_NESTED_OPEN_GROUP
;
1495 cg
->ppd_status
= PPD_BAD_OPEN_GROUP
;
1501 * Separate the group name from the text (name/text)...
1504 if ((sptr
= strchr(string
, '/')) != NULL
)
1510 * Fix up the text...
1516 * Find/add the group...
1519 group
= ppd_get_group(ppd
, string
, sptr
, cg
, encoding
);
1524 _cupsStrFree(string
);
1527 else if (!strcmp(keyword
, "CloseGroup"))
1531 _cupsStrFree(string
);
1534 else if (!strcmp(keyword
, "OrderDependency"))
1536 order
= (float)_cupsStrScand(string
, &sptr
, loc
);
1538 if (!sptr
|| sscanf(sptr
, "%40s%40s", name
, keyword
) != 2)
1540 cg
->ppd_status
= PPD_BAD_ORDER_DEPENDENCY
;
1545 if (keyword
[0] == '*')
1546 _cups_strcpy(keyword
, keyword
+ 1);
1548 if (!strcmp(name
, "ExitServer"))
1549 section
= PPD_ORDER_EXIT
;
1550 else if (!strcmp(name
, "Prolog"))
1551 section
= PPD_ORDER_PROLOG
;
1552 else if (!strcmp(name
, "DocumentSetup"))
1553 section
= PPD_ORDER_DOCUMENT
;
1554 else if (!strcmp(name
, "PageSetup"))
1555 section
= PPD_ORDER_PAGE
;
1556 else if (!strcmp(name
, "JCLSetup"))
1557 section
= PPD_ORDER_JCL
;
1559 section
= PPD_ORDER_ANY
;
1567 * Only valid for Non-UI options...
1570 for (i
= ppd
->num_groups
, gtemp
= ppd
->groups
; i
> 0; i
--, gtemp
++)
1571 if (gtemp
->text
[0] == '\0')
1575 for (i
= 0; i
< gtemp
->num_options
; i
++)
1576 if (!strcmp(keyword
, gtemp
->options
[i
].keyword
))
1578 gtemp
->options
[i
].section
= section
;
1579 gtemp
->options
[i
].order
= order
;
1585 option
->section
= section
;
1586 option
->order
= order
;
1589 _cupsStrFree(string
);
1592 else if (!strncmp(keyword
, "Default", 7))
1598 * Drop UI text, if any, from value...
1601 if (strchr(string
, '/') != NULL
)
1602 *strchr(string
, '/') = '\0';
1605 * Assign the default value as appropriate...
1608 if (!strcmp(keyword
, "DefaultColorSpace"))
1611 * Set default colorspace...
1614 if (!strcmp(string
, "CMY"))
1615 ppd
->colorspace
= PPD_CS_CMY
;
1616 else if (!strcmp(string
, "CMYK"))
1617 ppd
->colorspace
= PPD_CS_CMYK
;
1618 else if (!strcmp(string
, "RGB"))
1619 ppd
->colorspace
= PPD_CS_RGB
;
1620 else if (!strcmp(string
, "RGBK"))
1621 ppd
->colorspace
= PPD_CS_RGBK
;
1622 else if (!strcmp(string
, "N"))
1623 ppd
->colorspace
= PPD_CS_N
;
1625 ppd
->colorspace
= PPD_CS_GRAY
;
1627 else if (option
&& !strcmp(keyword
+ 7, option
->keyword
))
1630 * Set the default as part of the current option...
1633 DEBUG_printf(("2ppdOpen2: Setting %s to %s...", keyword
, string
));
1635 strlcpy(option
->defchoice
, string
, sizeof(option
->defchoice
));
1637 DEBUG_printf(("2ppdOpen2: %s is now %s...", keyword
, option
->defchoice
));
1642 * Lookup option and set if it has been defined...
1645 ppd_option_t
*toption
; /* Temporary option */
1648 if ((toption
= ppdFindOption(ppd
, keyword
+ 7)) != NULL
)
1650 DEBUG_printf(("2ppdOpen2: Setting %s to %s...", keyword
, string
));
1651 strlcpy(toption
->defchoice
, string
, sizeof(toption
->defchoice
));
1655 else if (!strcmp(keyword
, "UIConstraints") ||
1656 !strcmp(keyword
, "NonUIConstraints"))
1660 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1664 if (ppd
->num_consts
== 0)
1665 constraint
= calloc(2, sizeof(ppd_const_t
));
1667 constraint
= realloc(ppd
->consts
,
1668 (ppd
->num_consts
+ 2) * sizeof(ppd_const_t
));
1670 if (constraint
== NULL
)
1672 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1677 ppd
->consts
= constraint
;
1678 constraint
+= ppd
->num_consts
;
1681 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1682 constraint
->choice1
, constraint
->option2
,
1683 constraint
->choice2
))
1685 case 0 : /* Error */
1686 case 1 : /* Error */
1687 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1690 case 2 : /* Two options... */
1692 * Check for broken constraints like "* Option"...
1695 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1696 (!strcmp(constraint
->option1
, "*") ||
1697 !strcmp(constraint
->choice1
, "*")))
1699 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1704 * The following strcpy's are safe, as optionN and
1705 * choiceN are all the same size (size defined by PPD spec...)
1708 if (constraint
->option1
[0] == '*')
1709 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1710 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1712 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1716 if (constraint
->choice1
[0] == '*')
1717 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1718 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1720 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1724 constraint
->choice1
[0] = '\0';
1725 constraint
->choice2
[0] = '\0';
1728 case 3 : /* Two options, one choice... */
1730 * Check for broken constraints like "* Option"...
1733 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1734 (!strcmp(constraint
->option1
, "*") ||
1735 !strcmp(constraint
->choice1
, "*") ||
1736 !strcmp(constraint
->option2
, "*")))
1738 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1743 * The following _cups_strcpy's are safe, as optionN and
1744 * choiceN are all the same size (size defined by PPD spec...)
1747 if (constraint
->option1
[0] == '*')
1748 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1749 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1751 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1755 if (constraint
->choice1
[0] == '*')
1757 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1758 constraint
->option2
[0] == '*')
1760 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1764 _cups_strcpy(constraint
->choice2
, constraint
->option2
);
1765 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1766 constraint
->choice1
[0] = '\0';
1770 if (constraint
->option2
[0] == '*')
1771 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1772 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1774 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1778 constraint
->choice2
[0] = '\0';
1782 case 4 : /* Two options, two choices... */
1784 * Check for broken constraints like "* Option"...
1787 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1788 (!strcmp(constraint
->option1
, "*") ||
1789 !strcmp(constraint
->choice1
, "*") ||
1790 !strcmp(constraint
->option2
, "*") ||
1791 !strcmp(constraint
->choice2
, "*")))
1793 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1797 if (constraint
->option1
[0] == '*')
1798 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1799 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1801 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1805 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1806 constraint
->choice1
[0] == '*')
1808 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1812 if (constraint
->option2
[0] == '*')
1813 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1814 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1816 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1820 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1821 constraint
->choice2
[0] == '*')
1823 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1830 * Don't add this one as an attribute...
1833 _cupsStrFree(string
);
1836 else if (!strcmp(keyword
, "PaperDimension"))
1838 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1839 size
= ppd_add_size(ppd
, name
);
1844 * Unable to add or find size!
1847 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1852 size
->width
= (float)_cupsStrScand(string
, &sptr
, loc
);
1853 size
->length
= (float)_cupsStrScand(sptr
, NULL
, loc
);
1855 _cupsStrFree(string
);
1858 else if (!strcmp(keyword
, "ImageableArea"))
1860 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1861 size
= ppd_add_size(ppd
, name
);
1866 * Unable to add or find size!
1869 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1874 size
->left
= (float)_cupsStrScand(string
, &sptr
, loc
);
1875 size
->bottom
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
1876 size
->right
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
1877 size
->top
= (float)_cupsStrScand(sptr
, NULL
, loc
);
1879 _cupsStrFree(string
);
1882 else if (option
!= NULL
&&
1883 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1884 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
) &&
1885 !strcmp(keyword
, option
->keyword
))
1887 DEBUG_printf(("2ppdOpen2: group=%p, subgroup=%p", group
, subgroup
));
1889 if (!strcmp(keyword
, "PageSize"))
1892 * Add a page size...
1895 if (ppdPageSize(ppd
, name
) == NULL
)
1896 ppd_add_size(ppd
, name
);
1900 * Add the option choice...
1903 if ((choice
= ppd_add_choice(option
, name
)) == NULL
)
1905 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1911 cupsCharsetToUTF8((cups_utf8_t
*)choice
->text
, text
,
1912 sizeof(choice
->text
), encoding
);
1913 else if (!strcmp(name
, "True"))
1914 strcpy(choice
->text
, _("Yes"));
1915 else if (!strcmp(name
, "False"))
1916 strcpy(choice
->text
, _("No"));
1918 strlcpy(choice
->text
, name
, sizeof(choice
->text
));
1920 if (option
->section
== PPD_ORDER_JCL
)
1921 ppd_decode(string
); /* Decode quoted string */
1923 choice
->code
= string
;
1924 string
= NULL
; /* Don't add as an attribute below */
1928 * Add remaining lines with keywords and string values as attributes...
1932 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
))
1933 ppd_add_attr(ppd
, keyword
, name
, text
, string
);
1935 _cupsStrFree(string
);
1939 * Check for a missing CloseGroup...
1942 if (group
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1944 cg
->ppd_status
= PPD_MISSING_CLOSE_GROUP
;
1948 ppd_free(line
.buffer
);
1951 * Reset language preferences...
1954 cupsLangFree(language
);
1957 if (!cupsFileEOF(fp
))
1958 DEBUG_printf(("1ppdOpen2: Premature EOF at %lu...\n",
1959 (unsigned long)cupsFileTell(fp
)));
1962 if (cg
->ppd_status
!= PPD_OK
)
1965 * Had an error reading the PPD file, cannot continue!
1974 * Create the sorted options array and set the option back-pointer for
1975 * each choice and custom option...
1978 ppd
->options
= cupsArrayNew2((cups_array_func_t
)ppd_compare_options
, NULL
,
1979 (cups_ahash_func_t
)ppd_hash_option
,
1982 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1986 for (j
= group
->num_options
, option
= group
->options
;
1990 ppd_coption_t
*coption
; /* Custom option */
1993 cupsArrayAdd(ppd
->options
, option
);
1995 for (k
= 0; k
< option
->num_choices
; k
++)
1996 option
->choices
[k
].option
= option
;
1998 if ((coption
= ppdFindCustomOption(ppd
, option
->keyword
)) != NULL
)
1999 coption
->option
= option
;
2004 * Create an array to track the marked choices...
2007 ppd
->marked
= cupsArrayNew((cups_array_func_t
)ppd_compare_choices
, NULL
);
2010 * Return the PPD file structure...
2016 * Common exit point for errors to save code size...
2021 _cupsStrFree(string
);
2022 ppd_free(line
.buffer
);
2026 cupsLangFree(language
);
2033 * 'ppdOpenFd()' - Read a PPD file into memory.
2036 ppd_file_t
* /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
2037 ppdOpenFd(int fd
) /* I - File to read from */
2039 cups_file_t
*fp
; /* CUPS file pointer */
2040 ppd_file_t
*ppd
; /* PPD file record */
2041 _cups_globals_t
*cg
= _cupsGlobals();
2046 * Set the line number to 0...
2052 * Range check input...
2057 cg
->ppd_status
= PPD_NULL_FILE
;
2063 * Try to open the file and parse it...
2066 if ((fp
= cupsFileOpenFd(fd
, "r")) != NULL
)
2074 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
2083 * 'ppdOpenFile()' - Read a PPD file into memory.
2086 ppd_file_t
* /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
2087 ppdOpenFile(const char *filename
) /* I - File to read from */
2089 cups_file_t
*fp
; /* File pointer */
2090 ppd_file_t
*ppd
; /* PPD file record */
2091 _cups_globals_t
*cg
= _cupsGlobals();
2096 * Set the line number to 0...
2102 * Range check input...
2105 if (filename
== NULL
)
2107 cg
->ppd_status
= PPD_NULL_FILE
;
2113 * Try to open the file and parse it...
2116 if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
2124 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
2133 * 'ppdSetConformance()' - Set the conformance level for PPD files.
2135 * @since CUPS 1.1.20/Mac OS X 10.4@
2139 ppdSetConformance(ppd_conform_t c
) /* I - Conformance level */
2141 _cups_globals_t
*cg
= _cupsGlobals();
2145 cg
->ppd_conform
= c
;
2150 * 'ppd_add_attr()' - Add an attribute to the PPD data.
2153 static ppd_attr_t
* /* O - New attribute */
2154 ppd_add_attr(ppd_file_t
*ppd
, /* I - PPD file data */
2155 const char *name
, /* I - Attribute name */
2156 const char *spec
, /* I - Specifier string, if any */
2157 const char *text
, /* I - Text string, if any */
2158 const char *value
) /* I - Value of attribute */
2160 ppd_attr_t
**ptr
, /* New array */
2161 *temp
; /* New attribute */
2165 * Range check input...
2168 if (ppd
== NULL
|| name
== NULL
|| spec
== NULL
)
2172 * Create the array as needed...
2175 if (!ppd
->sorted_attrs
)
2176 ppd
->sorted_attrs
= cupsArrayNew((cups_array_func_t
)ppd_compare_attrs
,
2180 * Allocate memory for the new attribute...
2183 if (ppd
->num_attrs
== 0)
2184 ptr
= malloc(sizeof(ppd_attr_t
*));
2186 ptr
= realloc(ppd
->attrs
, (ppd
->num_attrs
+ 1) * sizeof(ppd_attr_t
*));
2192 ptr
+= ppd
->num_attrs
;
2194 if ((temp
= calloc(1, sizeof(ppd_attr_t
))) == NULL
)
2205 strlcpy(temp
->name
, name
, sizeof(temp
->name
));
2206 strlcpy(temp
->spec
, spec
, sizeof(temp
->spec
));
2207 strlcpy(temp
->text
, text
, sizeof(temp
->text
));
2208 temp
->value
= (char *)value
;
2211 * Add the attribute to the sorted array...
2214 cupsArrayAdd(ppd
->sorted_attrs
, temp
);
2217 * Return the attribute...
2225 * 'ppd_add_choice()' - Add a choice to an option.
2228 static ppd_choice_t
* /* O - Named choice */
2229 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
2230 const char *name
) /* I - Name of choice */
2232 ppd_choice_t
*choice
; /* Choice */
2235 if (option
->num_choices
== 0)
2236 choice
= malloc(sizeof(ppd_choice_t
));
2238 choice
= realloc(option
->choices
,
2239 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
2244 option
->choices
= choice
;
2245 choice
+= option
->num_choices
;
2246 option
->num_choices
++;
2248 memset(choice
, 0, sizeof(ppd_choice_t
));
2249 strlcpy(choice
->choice
, name
, sizeof(choice
->choice
));
2256 * 'ppd_add_size()' - Add a page size.
2259 static ppd_size_t
* /* O - Named size */
2260 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
2261 const char *name
) /* I - Name of size */
2263 ppd_size_t
*size
; /* Size */
2266 if (ppd
->num_sizes
== 0)
2267 size
= malloc(sizeof(ppd_size_t
));
2269 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
2275 size
+= ppd
->num_sizes
;
2278 memset(size
, 0, sizeof(ppd_size_t
));
2279 strlcpy(size
->name
, name
, sizeof(size
->name
));
2286 * 'ppd_compare_attrs()' - Compare two attributes.
2289 static int /* O - Result of comparison */
2290 ppd_compare_attrs(ppd_attr_t
*a
, /* I - First attribute */
2291 ppd_attr_t
*b
) /* I - Second attribute */
2293 return (strcasecmp(a
->name
, b
->name
));
2298 * 'ppd_compare_choices()' - Compare two choices...
2301 static int /* O - Result of comparison */
2302 ppd_compare_choices(ppd_choice_t
*a
, /* I - First choice */
2303 ppd_choice_t
*b
) /* I - Second choice */
2305 return (strcmp(a
->option
->keyword
, b
->option
->keyword
));
2310 * 'ppd_compare_coptions()' - Compare two custom options.
2313 static int /* O - Result of comparison */
2314 ppd_compare_coptions(ppd_coption_t
*a
, /* I - First option */
2315 ppd_coption_t
*b
) /* I - Second option */
2317 return (strcasecmp(a
->keyword
, b
->keyword
));
2322 * 'ppd_compare_options()' - Compare two options.
2325 static int /* O - Result of comparison */
2326 ppd_compare_options(ppd_option_t
*a
, /* I - First option */
2327 ppd_option_t
*b
) /* I - Second option */
2329 return (strcasecmp(a
->keyword
, b
->keyword
));
2334 * 'ppd_decode()' - Decode a string value...
2337 static int /* O - Length of decoded string */
2338 ppd_decode(char *string
) /* I - String to decode */
2340 char *inptr
, /* Input pointer */
2341 *outptr
; /* Output pointer */
2347 while (*inptr
!= '\0')
2348 if (*inptr
== '<' && isxdigit(inptr
[1] & 255))
2351 * Convert hex to 8-bit values...
2355 while (isxdigit(*inptr
& 255))
2357 if (_cups_isalpha(*inptr
))
2358 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
2360 *outptr
= (*inptr
- '0') << 4;
2364 if (!isxdigit(*inptr
& 255))
2367 if (_cups_isalpha(*inptr
))
2368 *outptr
|= tolower(*inptr
) - 'a' + 10;
2370 *outptr
|= *inptr
- '0';
2376 while (*inptr
!= '>' && *inptr
!= '\0')
2378 while (*inptr
== '>')
2382 *outptr
++ = *inptr
++;
2386 return ((int)(outptr
- string
));
2391 * 'ppd_free_group()' - Free a single UI group.
2395 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
2397 int i
; /* Looping var */
2398 ppd_option_t
*option
; /* Current option */
2399 ppd_group_t
*subgroup
; /* Current sub-group */
2402 if (group
->num_options
> 0)
2404 for (i
= group
->num_options
, option
= group
->options
;
2407 ppd_free_option(option
);
2409 ppd_free(group
->options
);
2412 if (group
->num_subgroups
> 0)
2414 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
2417 ppd_free_group(subgroup
);
2419 ppd_free(group
->subgroups
);
2425 * 'ppd_free_option()' - Free a single option.
2429 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
2431 int i
; /* Looping var */
2432 ppd_choice_t
*choice
; /* Current choice */
2435 if (option
->num_choices
> 0)
2437 for (i
= option
->num_choices
, choice
= option
->choices
;
2441 _cupsStrFree(choice
->code
);
2444 ppd_free(option
->choices
);
2450 * 'ppd_get_coption()' - Get a custom option record.
2453 static ppd_coption_t
* /* O - Custom option... */
2454 ppd_get_coption(ppd_file_t
*ppd
, /* I - PPD file */
2455 const char *name
) /* I - Name of option */
2457 ppd_coption_t
*copt
; /* New custom option */
2461 * See if the option already exists...
2464 if ((copt
= ppdFindCustomOption(ppd
, name
)) != NULL
)
2468 * Not found, so create the custom option record...
2471 if ((copt
= calloc(1, sizeof(ppd_coption_t
))) == NULL
)
2474 strlcpy(copt
->keyword
, name
, sizeof(copt
->keyword
));
2476 copt
->params
= cupsArrayNew((cups_array_func_t
)NULL
, NULL
);
2478 cupsArrayAdd(ppd
->coptions
, copt
);
2481 * Return the new record...
2489 * 'ppd_get_cparam()' - Get a custom parameter record.
2492 static ppd_cparam_t
* /* O - Extended option... */
2493 ppd_get_cparam(ppd_coption_t
*opt
, /* I - PPD file */
2494 const char *param
, /* I - Name of parameter */
2495 const char *text
) /* I - Human-readable text */
2497 ppd_cparam_t
*cparam
; /* New custom parameter */
2501 * See if the parameter already exists...
2504 if ((cparam
= ppdFindCustomParam(opt
, param
)) != NULL
)
2508 * Not found, so create the custom parameter record...
2511 if ((cparam
= calloc(1, sizeof(ppd_cparam_t
))) == NULL
)
2514 strlcpy(cparam
->name
, param
, sizeof(cparam
->name
));
2515 strlcpy(cparam
->text
, text
[0] ? text
: param
, sizeof(cparam
->text
));
2518 * Add this record to the array...
2521 cupsArrayAdd(opt
->params
, cparam
);
2524 * Return the new record...
2532 * 'ppd_get_group()' - Find or create the named group as needed.
2535 static ppd_group_t
* /* O - Named group */
2536 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
2537 const char *name
, /* I - Name of group */
2538 const char *text
, /* I - Text for group */
2539 _cups_globals_t
*cg
, /* I - Global data */
2540 cups_encoding_t encoding
) /* I - Encoding of text */
2542 int i
; /* Looping var */
2543 ppd_group_t
*group
; /* Group */
2546 DEBUG_printf(("7ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)",
2547 ppd
, name
, text
, cg
));
2549 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
2550 if (!strcmp(group
->name
, name
))
2555 DEBUG_printf(("8ppd_get_group: Adding group %s...", name
));
2557 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&& strlen(text
) >= sizeof(group
->text
))
2559 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2564 if (ppd
->num_groups
== 0)
2565 group
= malloc(sizeof(ppd_group_t
));
2567 group
= realloc(ppd
->groups
,
2568 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
2572 cg
->ppd_status
= PPD_ALLOC_ERROR
;
2577 ppd
->groups
= group
;
2578 group
+= ppd
->num_groups
;
2581 memset(group
, 0, sizeof(ppd_group_t
));
2582 strlcpy(group
->name
, name
, sizeof(group
->name
));
2584 cupsCharsetToUTF8((cups_utf8_t
*)group
->text
, text
,
2585 sizeof(group
->text
), encoding
);
2593 * 'ppd_get_option()' - Find or create the named option as needed.
2596 static ppd_option_t
* /* O - Named option */
2597 ppd_get_option(ppd_group_t
*group
, /* I - Group */
2598 const char *name
) /* I - Name of option */
2600 int i
; /* Looping var */
2601 ppd_option_t
*option
; /* Option */
2604 DEBUG_printf(("7ppd_get_option(group=%p(\"%s\"), name=\"%s\")",
2605 group
, group
->name
, name
));
2607 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
2608 if (!strcmp(option
->keyword
, name
))
2613 if (group
->num_options
== 0)
2614 option
= malloc(sizeof(ppd_option_t
));
2616 option
= realloc(group
->options
,
2617 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
2622 group
->options
= option
;
2623 option
+= group
->num_options
;
2624 group
->num_options
++;
2626 memset(option
, 0, sizeof(ppd_option_t
));
2627 strlcpy(option
->keyword
, name
, sizeof(option
->keyword
));
2635 * 'ppd_hash_option()' - Generate a hash of the option name...
2638 static int /* O - Hash index */
2639 ppd_hash_option(ppd_option_t
*option
) /* I - Option */
2641 int hash
= 0; /* Hash index */
2642 const char *k
; /* Pointer into keyword */
2645 for (hash
= option
->keyword
[0], k
= option
->keyword
+ 1; *k
;)
2646 hash
= 33 * hash
+ *k
++;
2648 return (hash
& 511);
2653 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2657 static int /* O - Bitmask of fields read */
2658 ppd_read(cups_file_t
*fp
, /* I - File to read from */
2659 _ppd_line_t
*line
, /* I - Line buffer */
2660 char *keyword
, /* O - Keyword from line */
2661 char *option
, /* O - Option from line */
2662 char *text
, /* O - Human-readable text from line */
2663 char **string
, /* O - Code/string data */
2664 int ignoreblank
, /* I - Ignore blank lines? */
2665 _cups_globals_t
*cg
) /* I - Global data */
2667 int ch
, /* Character from file */
2668 col
, /* Column in line */
2669 colon
, /* Colon seen? */
2670 endquote
, /* Waiting for an end quote */
2671 mask
, /* Mask to be returned */
2672 startline
, /* Start line */
2673 textlen
; /* Length of text */
2674 char *keyptr
, /* Keyword pointer */
2675 *optptr
, /* Option pointer */
2676 *textptr
, /* Text pointer */
2677 *strptr
, /* Pointer into string */
2678 *lineptr
; /* Current position in line buffer */
2682 * Now loop until we have a valid line...
2687 startline
= cg
->ppd_line
+ 1;
2691 line
->bufsize
= 1024;
2692 line
->buffer
= malloc(1024);
2704 lineptr
= line
->buffer
;
2708 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2710 if (lineptr
>= (line
->buffer
+ line
->bufsize
- 1))
2713 * Expand the line buffer...
2716 char *temp
; /* Temporary line pointer */
2719 line
->bufsize
+= 1024;
2720 if (line
->bufsize
> 262144)
2723 * Don't allow lines longer than 256k!
2726 cg
->ppd_line
= startline
;
2727 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2732 temp
= realloc(line
->buffer
, line
->bufsize
);
2735 cg
->ppd_line
= startline
;
2736 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2741 lineptr
= temp
+ (lineptr
- line
->buffer
);
2742 line
->buffer
= temp
;
2745 if (ch
== '\r' || ch
== '\n')
2748 * Line feed or carriage return...
2757 * Check for a trailing line feed...
2760 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2767 cupsFileGetChar(fp
);
2770 if (lineptr
== line
->buffer
&& ignoreblank
)
2771 continue; /* Skip blank lines */
2775 if (!endquote
) /* Continue for multi-line text */
2780 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2783 * Other control characters...
2786 cg
->ppd_line
= startline
;
2787 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2791 else if (ch
!= 0x1a)
2794 * Any other character...
2800 if (col
> (PPD_MAX_LINE
- 1))
2803 * Line is too long...
2806 cg
->ppd_line
= startline
;
2807 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2812 if (ch
== ':' && strncmp(line
->buffer
, "*%", 2) != 0)
2815 if (ch
== '\"' && colon
)
2816 endquote
= !endquote
;
2823 * Didn't finish this quoted string...
2826 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2829 else if (ch
== '\r' || ch
== '\n')
2837 * Check for a trailing line feed...
2840 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2843 cupsFileGetChar(fp
);
2846 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2849 * Other control characters...
2852 cg
->ppd_line
= startline
;
2853 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2857 else if (ch
!= 0x1a)
2861 if (col
> (PPD_MAX_LINE
- 1))
2864 * Line is too long...
2867 cg
->ppd_line
= startline
;
2868 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2878 * Didn't finish this line...
2881 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2882 if (ch
== '\r' || ch
== '\n')
2885 * Line feed or carriage return...
2894 * Check for a trailing line feed...
2897 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2900 cupsFileGetChar(fp
);
2905 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2908 * Other control characters...
2911 cg
->ppd_line
= startline
;
2912 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2916 else if (ch
!= 0x1a)
2920 if (col
> (PPD_MAX_LINE
- 1))
2923 * Line is too long...
2926 cg
->ppd_line
= startline
;
2927 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2934 if (lineptr
> line
->buffer
&& lineptr
[-1] == '\n')
2939 DEBUG_printf(("9ppd_read: LINE=\"%s\"", line
->buffer
));
2942 * The dynamically created PPDs for older style Mac OS X
2943 * drivers include a large blob of data inserted as comments
2944 * at the end of the file. As an optimization we can stop
2945 * reading the PPD when we get to the start of this data.
2948 if (!strcmp(line
->buffer
, "*%APLWORKSET START"))
2951 if (ch
== EOF
&& lineptr
== line
->buffer
)
2959 lineptr
= line
->buffer
+ 1;
2966 if ((!line
->buffer
[0] || /* Blank line */
2967 !strncmp(line
->buffer
, "*%", 2) || /* Comment line */
2968 !strcmp(line
->buffer
, "*End")) && /* End of multi-line string */
2969 ignoreblank
) /* Ignore these? */
2971 startline
= cg
->ppd_line
+ 1;
2975 if (!strcmp(line
->buffer
, "*")) /* (Bad) comment line */
2977 if (cg
->ppd_conform
== PPD_CONFORM_RELAXED
)
2979 startline
= cg
->ppd_line
+ 1;
2984 cg
->ppd_line
= startline
;
2985 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2991 if (line
->buffer
[0] != '*') /* All lines start with an asterisk */
2994 * Allow lines consisting of just whitespace...
2997 for (lineptr
= line
->buffer
; *lineptr
; lineptr
++)
2998 if (*lineptr
&& !_cups_isspace(*lineptr
))
3003 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
3006 else if (ignoreblank
)
3018 while (*lineptr
&& *lineptr
!= ':' && !_cups_isspace(*lineptr
))
3020 if (*lineptr
<= ' ' || *lineptr
> 126 || *lineptr
== '/' ||
3021 (keyptr
- keyword
) >= (PPD_MAX_NAME
- 1))
3023 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
3027 *keyptr
++ = *lineptr
++;
3032 if (!strcmp(keyword
, "End"))
3035 mask
|= PPD_KEYWORD
;
3037 if (_cups_isspace(*lineptr
))
3040 * Get an option name...
3043 while (_cups_isspace(*lineptr
))
3048 while (*lineptr
&& !_cups_isspace(*lineptr
) && *lineptr
!= ':' &&
3051 if (*lineptr
<= ' ' || *lineptr
> 126 ||
3052 (optptr
- option
) >= (PPD_MAX_NAME
- 1))
3054 cg
->ppd_status
= PPD_ILLEGAL_OPTION_KEYWORD
;
3058 *optptr
++ = *lineptr
++;
3063 if (_cups_isspace(*lineptr
) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3065 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3069 while (_cups_isspace(*lineptr
))
3074 if (*lineptr
== '/')
3077 * Get human-readable text...
3084 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':')
3086 if (((unsigned char)*lineptr
< ' ' && *lineptr
!= '\t') ||
3087 (textptr
- text
) >= (PPD_MAX_LINE
- 1))
3089 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3093 *textptr
++ = *lineptr
++;
3097 textlen
= ppd_decode(text
);
3099 if (textlen
> PPD_MAX_TEXT
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3101 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3109 if (_cups_isspace(*lineptr
) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3111 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3115 while (_cups_isspace(*lineptr
))
3118 if (*lineptr
== ':')
3121 * Get string after triming leading and trailing whitespace...
3125 while (_cups_isspace(*lineptr
))
3128 strptr
= lineptr
+ strlen(lineptr
) - 1;
3129 while (strptr
>= lineptr
&& _cups_isspace(*strptr
))
3132 if (*strptr
== '\"')
3135 * Quoted string by itself, remove quotes...
3142 *string
= _cupsStrAlloc(lineptr
);
3154 * End of "$Id: ppd.c 7906 2008-09-03 20:19:43Z mike $".