2 * "$Id: ppd.c 6187 2007-01-10 16:20:42Z mike $"
4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * PostScript is a trademark of Adobe Systems, Inc.
26 * This code and any derivative of it may be used and distributed
27 * freely under the terms of the GNU General Public License when
28 * used with GNU Ghostscript or its derivatives. Use of the code
29 * (or any derivative of it) with software other than GNU
30 * GhostScript (or its derivatives) is governed by the CUPS license
33 * This file is subject to the Apple OS-Developed Software exception.
37 * ppdClose() - Free all memory used by the PPD file.
38 * ppdErrorString() - Returns the text assocated with a status.
39 * _ppdGetEncoding() - Get the CUPS encoding value for the given
41 * ppdLastError() - Return the status from the last ppdOpen*().
42 * ppdOpen() - Read a PPD file into memory.
43 * ppdOpen2() - Read a PPD file into memory.
44 * ppdOpenFd() - Read a PPD file into memory.
45 * ppdOpenFile() - Read a PPD file into memory.
46 * ppdSetConformance() - Set the conformance level for PPD files.
47 * ppd_add_attr() - Add an attribute to the PPD data.
48 * ppd_add_choice() - Add a choice to an option.
49 * ppd_add_size() - Add a page size.
50 * ppd_compare_attrs() - Compare two attributes.
51 * ppd_compare_coptions() - Compare two custom options.
52 * ppd_compare_cparams() - Compare two custom parameters.
53 * ppd_compare_options() - Compare two options.
54 * ppd_decode() - Decode a string value...
55 * ppd_free_group() - Free a single UI group.
56 * ppd_free_option() - Free a single option.
57 * ppd_get_coption() - Get a custom option record.
58 * ppd_get_cparam() - Get a custom parameter record.
59 * ppd_get_group() - Find or create the named group as needed.
60 * ppd_get_option() - Find or create the named option as needed.
61 * ppd_read() - Read a line from a PPD file, skipping comment
66 * Include necessary headers.
78 #if defined(WIN32) || defined(__EMX__)
79 # define READ_BINARY "rb" /* Open a binary file for reading */
80 # define WRITE_BINARY "wb" /* Open a binary file for writing */
82 # define READ_BINARY "r" /* Open a binary file for reading */
83 # define WRITE_BINARY "w" /* Open a binary file for writing */
84 #endif /* WIN32 || __EMX__ */
86 #define ppd_free(p) if (p) free(p) /* Safe free macro */
88 #define PPD_KEYWORD 1 /* Line contained a keyword */
89 #define PPD_OPTION 2 /* Line contained an option name */
90 #define PPD_TEXT 4 /* Line contained human-readable text */
91 #define PPD_STRING 8 /* Line contained a string or code */
98 static ppd_attr_t
*ppd_add_attr(ppd_file_t
*ppd
, const char *name
,
99 const char *spec
, const char *text
,
101 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, const char *name
);
102 static ppd_size_t
*ppd_add_size(ppd_file_t
*ppd
, const char *name
);
103 static int ppd_compare_attrs(ppd_attr_t
*a
, ppd_attr_t
*b
);
104 static int ppd_compare_coptions(ppd_coption_t
*a
,
106 static int ppd_compare_cparams(ppd_cparam_t
*a
, ppd_cparam_t
*b
);
107 static int ppd_compare_options(ppd_option_t
*a
, ppd_option_t
*b
);
108 static int ppd_decode(char *string
);
109 static void ppd_free_group(ppd_group_t
*group
);
110 static void ppd_free_option(ppd_option_t
*option
);
111 static ppd_coption_t
*ppd_get_coption(ppd_file_t
*ppd
, const char *name
);
112 static ppd_cparam_t
*ppd_get_cparam(ppd_coption_t
*opt
,
115 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, const char *name
,
116 const char *text
, _cups_globals_t
*cg
,
117 cups_encoding_t encoding
);
118 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, const char *name
);
119 static int ppd_read(cups_file_t
*fp
, char *keyword
, char *option
,
120 char *text
, char **string
, int ignoreblank
,
121 _cups_globals_t
*cg
);
125 * 'ppdClose()' - Free all memory used by the PPD file.
129 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
131 int i
; /* Looping var */
132 ppd_emul_t
*emul
; /* Current emulation */
133 ppd_group_t
*group
; /* Current group */
134 char **font
; /* Current font */
135 char **filter
; /* Current filter */
136 ppd_attr_t
**attr
; /* Current attribute */
137 ppd_coption_t
*coption
; /* Current custom option */
138 ppd_cparam_t
*cparam
; /* Current custom parameter */
142 * Range check arguments...
149 * Free all strings at the top level...
152 ppd_free(ppd
->lang_encoding
);
153 ppd_free(ppd
->nickname
);
154 ppd_free(ppd
->patches
);
155 ppd_free(ppd
->jcl_begin
);
156 ppd_free(ppd
->jcl_end
);
157 ppd_free(ppd
->jcl_ps
);
160 * Free any emulations...
163 if (ppd
->num_emulations
> 0)
165 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
167 ppd_free(emul
->start
);
168 ppd_free(emul
->stop
);
171 ppd_free(ppd
->emulations
);
175 * Free any UI groups, subgroups, and options...
178 if (ppd
->num_groups
> 0)
180 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
181 ppd_free_group(group
);
183 ppd_free(ppd
->groups
);
186 cupsArrayDelete(ppd
->options
);
189 * Free any page sizes...
192 if (ppd
->num_sizes
> 0)
193 ppd_free(ppd
->sizes
);
196 * Free any constraints...
199 if (ppd
->num_consts
> 0)
200 ppd_free(ppd
->consts
);
203 * Free any filters...
206 if (ppd
->num_filters
> 0)
208 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
213 ppd_free(ppd
->filters
);
220 if (ppd
->num_fonts
> 0)
222 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
227 ppd_free(ppd
->fonts
);
231 * Free any profiles...
234 if (ppd
->num_profiles
> 0)
235 ppd_free(ppd
->profiles
);
238 * Free any attributes...
241 if (ppd
->num_attrs
> 0)
243 for (i
= ppd
->num_attrs
, attr
= ppd
->attrs
; i
> 0; i
--, attr
++)
245 ppd_free((*attr
)->value
);
249 ppd_free(ppd
->attrs
);
252 cupsArrayDelete(ppd
->sorted_attrs
);
255 * Free custom options...
258 for (coption
= (ppd_coption_t
*)cupsArrayFirst(ppd
->coptions
);
260 coption
= (ppd_coption_t
*)cupsArrayNext(ppd
->coptions
))
262 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
264 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
266 switch (cparam
->type
)
268 case PPD_CUSTOM_PASSCODE
:
269 case PPD_CUSTOM_PASSWORD
:
270 case PPD_CUSTOM_STRING
:
271 ppd_free(cparam
->current
.custom_string
);
281 cupsArrayDelete(coption
->params
);
286 cupsArrayDelete(ppd
->coptions
);
289 * Free the whole record...
297 * 'ppdErrorString()' - Returns the text assocated with a status.
299 * @since CUPS 1.1.19@
302 const char * /* O - Status string */
303 ppdErrorString(ppd_status_t status
) /* I - PPD status */
305 static const char * const messages
[] =/* Status messages */
308 _("Unable to open PPD file"),
309 _("NULL PPD file pointer"),
310 _("Memory allocation error"),
311 _("Missing PPD-Adobe-4.x header"),
312 _("Missing value string"),
315 _("OpenGroup without a CloseGroup first"),
316 _("Bad OpenUI/JCLOpenUI"),
317 _("OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first"),
318 _("Bad OrderDependency"),
319 _("Bad UIConstraints"),
320 _("Missing asterisk in column 1"),
321 _("Line longer than the maximum allowed (255 characters)"),
322 _("Illegal control character"),
323 _("Illegal main keyword string"),
324 _("Illegal option keyword string"),
325 _("Illegal translation string"),
326 _("Illegal whitespace character"),
327 _("Bad custom parameter")
331 if (status
< PPD_OK
|| status
> PPD_ILLEGAL_WHITESPACE
)
332 return (_cupsLangString(cupsLangDefault(), _("Unknown")));
334 return (_cupsLangString(cupsLangDefault(), messages
[status
]));
339 * '_ppdGetEncoding()' - Get the CUPS encoding value for the given
343 cups_encoding_t
/* O - CUPS encoding value */
344 _ppdGetEncoding(const char *name
) /* I - LanguageEncoding string */
346 if (!strcasecmp(name
, "ISOLatin1"))
347 return (CUPS_ISO8859_1
);
348 else if (!strcasecmp(name
, "ISOLatin2"))
349 return (CUPS_ISO8859_2
);
350 else if (!strcasecmp(name
, "ISOLatin5"))
351 return (CUPS_ISO8859_5
);
352 else if (!strcasecmp(name
, "JIS83-RKSJ"))
353 return (CUPS_WINDOWS_932
);
354 else if (!strcasecmp(name
, "MacStandard"))
355 return (CUPS_MAC_ROMAN
);
356 else if (!strcasecmp(name
, "WindowsANSI"))
357 return (CUPS_WINDOWS_1252
);
364 * 'ppdLastError()' - Return the status from the last ppdOpen*().
366 * @since CUPS 1.1.19@
369 ppd_status_t
/* O - Status code */
370 ppdLastError(int *line
) /* O - Line number */
372 _cups_globals_t
*cg
= _cupsGlobals();
377 *line
= cg
->ppd_line
;
379 return (cg
->ppd_status
);
384 * 'ppdOpen()' - Read a PPD file into memory.
387 ppd_file_t
* /* O - PPD file record */
388 ppdOpen(FILE *fp
) /* I - File to read from */
390 ppd_file_t
*ppd
; /* PPD file record */
391 cups_file_t
*cf
; /* CUPS file */
395 * Reopen the stdio file as a CUPS file...
398 if ((cf
= cupsFileOpenFd(fileno(fp
), "r")) == NULL
)
402 * Load the PPD file using the newer API...
408 * Close the CUPS file and return the PPD...
418 * 'ppdOpen2()' - Read a PPD file into memory.
423 ppd_file_t
* /* O - PPD file record */
424 ppdOpen2(cups_file_t
*fp
) /* I - File to read from */
426 int i
, j
, k
; /* Looping vars */
427 int count
; /* Temporary count */
428 ppd_file_t
*ppd
; /* PPD file record */
429 ppd_group_t
*group
, /* Current group */
430 *subgroup
; /* Current sub-group */
431 ppd_option_t
*option
; /* Current option */
432 ppd_choice_t
*choice
; /* Current choice */
433 ppd_const_t
*constraint
; /* Current constraint */
434 ppd_size_t
*size
; /* Current page size */
435 int mask
; /* Line data mask */
436 char keyword
[PPD_MAX_NAME
],
437 /* Keyword from file */
439 /* Option from file */
441 /* Human-readable text from file */
442 *string
, /* Code/text from file */
443 *sptr
, /* Pointer into string */
444 *nameptr
, /* Pointer into name */
445 *temp
, /* Temporary string pointer */
446 **tempfonts
; /* Temporary fonts pointer */
447 float order
; /* Order dependency number */
448 ppd_section_t section
; /* Order dependency section */
449 ppd_profile_t
*profile
; /* Pointer to color profile */
450 char **filter
; /* Pointer to filter */
451 cups_lang_t
*language
; /* Default language */
452 struct lconv
*loc
; /* Locale data */
453 int ui_keyword
; /* Is this line a UI keyword? */
454 cups_encoding_t encoding
; /* Encoding of PPD file */
455 _cups_globals_t
*cg
= _cupsGlobals();
457 static const char * const ui_keywords
[] =
459 #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST
461 * Adobe defines some 41 keywords as "UI", meaning that they are
462 * user interface elements and that they should be treated as such
463 * even if the PPD creator doesn't use Open/CloseUI around them.
465 * Since this can cause previously invisible options to appear and
466 * confuse users, the default is to only treat the PageSize and
467 * PageRegion keywords this way.
469 /* Boolean keywords */
479 /* PickOne keywords */
492 "JCLFrameBufferSize",
513 #else /* !CUPS_USE_FULL_UI_KEYWORDS_LIST */
516 #endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */
521 * Default to "OK" status...
524 cg
->ppd_status
= PPD_OK
;
528 * Range check input...
533 cg
->ppd_status
= PPD_NULL_FILE
;
538 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
541 mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 0, cg
);
543 DEBUG_printf(("mask=%x, keyword=\"%s\"...\n", mask
, keyword
));
546 strcmp(keyword
, "PPD-Adobe") ||
547 string
== NULL
|| string
[0] != '4')
550 * Either this is not a PPD file, or it is not a 4.x PPD file.
553 if (cg
->ppd_status
== PPD_OK
)
554 cg
->ppd_status
= PPD_MISSING_PPDADOBE4
;
561 DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword
, string
));
566 * Allocate memory for the PPD file record...
569 if ((ppd
= calloc(1, sizeof(ppd_file_t
))) == NULL
)
571 cg
->ppd_status
= PPD_ALLOC_ERROR
;
576 ppd
->language_level
= 1;
577 ppd
->color_device
= 0;
578 ppd
->colorspace
= PPD_CS_GRAY
;
579 ppd
->landscape
= -90;
580 ppd
->coptions
= cupsArrayNew((cups_array_func_t
)ppd_compare_coptions
,
584 * Get the default language for the user...
587 language
= cupsLangDefault();
591 * Read lines from the PPD file and add them to the file record...
599 encoding
= CUPS_ISO8859_1
;
601 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 1, cg
)) != 0)
604 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
607 printf(", name = \"%s\"", name
);
610 printf(", text = \"%s\"", text
);
614 if (strlen(string
) > 40)
615 printf(", string = %p", string
);
617 printf(", string = \"%s\"", string
);
623 if (strcmp(keyword
, "CloseUI") && strcmp(keyword
, "CloseGroup") &&
624 strcmp(keyword
, "CloseSubGroup") && strncmp(keyword
, "Default", 7) &&
625 strcmp(keyword
, "JCLCloseUI") && strcmp(keyword
, "JCLOpenUI") &&
626 strcmp(keyword
, "OpenUI") && strcmp(keyword
, "OpenGroup") &&
627 strcmp(keyword
, "OpenSubGroup") && string
== NULL
)
630 * Need a string value!
633 cg
->ppd_status
= PPD_MISSING_VALUE
;
639 * Certain main keywords (as defined by the PPD spec) may be used
640 * without the usual OpenUI/CloseUI stuff. Presumably this is just
641 * so that Adobe wouldn't completely break compatibility with PPD
642 * files prior to v4.0 of the spec, but it is hopelessly
643 * inconsistent... Catch these main keywords and automatically
644 * create the corresponding option, as needed...
650 * Previous line was a UI keyword...
657 if (option
== NULL
&&
658 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
659 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
661 for (i
= 0; i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])); i
++)
662 if (!strcmp(keyword
, ui_keywords
[i
]))
665 if (i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])))
668 * Create the option in the appropriate group...
673 DEBUG_printf(("**** FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!\n",
678 if ((group
= ppd_get_group(ppd
, "General", _("General"), cg
,
682 DEBUG_printf(("Adding to group %s...\n", group
->text
));
683 option
= ppd_get_option(group
, keyword
);
687 option
= ppd_get_option(group
, keyword
);
691 cg
->ppd_status
= PPD_ALLOC_ERROR
;
697 * Now fill in the initial information for the option...
700 if (!strncmp(keyword
, "JCL", 3))
701 option
->section
= PPD_ORDER_JCL
;
703 option
->section
= PPD_ORDER_ANY
;
705 option
->order
= 10.0f
;
708 option
->ui
= PPD_UI_BOOLEAN
;
710 option
->ui
= PPD_UI_PICKONE
;
712 for (j
= 0; j
< ppd
->num_attrs
; j
++)
713 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
714 !strcmp(ppd
->attrs
[j
]->name
+ 7, keyword
) &&
715 ppd
->attrs
[j
]->value
)
717 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
718 option
->keyword
, ppd
->attrs
[j
]->value
));
719 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
720 sizeof(option
->defchoice
));
724 if (!strcmp(keyword
, "PageSize"))
725 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
726 else if (!strcmp(keyword
, "MediaType"))
727 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
728 else if (!strcmp(keyword
, "InputSlot"))
729 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
730 else if (!strcmp(keyword
, "ColorModel"))
731 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
732 else if (!strcmp(keyword
, "Resolution"))
733 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
735 strlcpy(option
->text
, keyword
, sizeof(option
->text
));
739 if (!strcmp(keyword
, "LanguageLevel"))
740 ppd
->language_level
= atoi(string
);
741 else if (!strcmp(keyword
, "LanguageEncoding"))
744 * Say all PPD files are UTF-8, since we convert to UTF-8...
747 ppd
->lang_encoding
= strdup("UTF-8");
748 encoding
= _ppdGetEncoding(string
);
750 else if (!strcmp(keyword
, "LanguageVersion"))
751 ppd
->lang_version
= string
;
752 else if (!strcmp(keyword
, "Manufacturer"))
753 ppd
->manufacturer
= string
;
754 else if (!strcmp(keyword
, "ModelName"))
755 ppd
->modelname
= string
;
756 else if (!strcmp(keyword
, "Protocols"))
757 ppd
->protocols
= string
;
758 else if (!strcmp(keyword
, "PCFileName"))
759 ppd
->pcfilename
= string
;
760 else if (!strcmp(keyword
, "NickName"))
762 if (encoding
!= CUPS_UTF8
)
764 cups_utf8_t utf8
[256]; /* UTF-8 version of NickName */
767 cupsCharsetToUTF8(utf8
, string
, sizeof(utf8
), encoding
);
768 ppd
->nickname
= strdup((char *)utf8
);
771 ppd
->nickname
= strdup(string
);
773 else if (!strcmp(keyword
, "Product"))
774 ppd
->product
= string
;
775 else if (!strcmp(keyword
, "ShortNickName"))
776 ppd
->shortnickname
= string
;
777 else if (!strcmp(keyword
, "TTRasterizer"))
778 ppd
->ttrasterizer
= string
;
779 else if (!strcmp(keyword
, "JCLBegin"))
781 ppd
->jcl_begin
= strdup(string
);
782 ppd_decode(ppd
->jcl_begin
); /* Decode quoted string */
784 else if (!strcmp(keyword
, "JCLEnd"))
786 ppd
->jcl_end
= strdup(string
);
787 ppd_decode(ppd
->jcl_end
); /* Decode quoted string */
789 else if (!strcmp(keyword
, "JCLToPSInterpreter"))
791 ppd
->jcl_ps
= strdup(string
);
792 ppd_decode(ppd
->jcl_ps
); /* Decode quoted string */
794 else if (!strcmp(keyword
, "AccurateScreensSupport"))
795 ppd
->accurate_screens
= !strcmp(string
, "True");
796 else if (!strcmp(keyword
, "ColorDevice"))
797 ppd
->color_device
= !strcmp(string
, "True");
798 else if (!strcmp(keyword
, "ContoneOnly"))
799 ppd
->contone_only
= !strcmp(string
, "True");
800 else if (!strcmp(keyword
, "cupsFlipDuplex"))
801 ppd
->flip_duplex
= !strcmp(string
, "True");
802 else if (!strcmp(keyword
, "cupsManualCopies"))
803 ppd
->manual_copies
= !strcmp(string
, "True");
804 else if (!strcmp(keyword
, "cupsModelNumber"))
805 ppd
->model_number
= atoi(string
);
806 else if (!strcmp(keyword
, "cupsColorProfile"))
808 if (ppd
->num_profiles
== 0)
809 profile
= malloc(sizeof(ppd_profile_t
));
811 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
812 (ppd
->num_profiles
+ 1));
814 ppd
->profiles
= profile
;
815 profile
+= ppd
->num_profiles
;
816 ppd
->num_profiles
++;
818 memset(profile
, 0, sizeof(ppd_profile_t
));
819 strlcpy(profile
->resolution
, name
, sizeof(profile
->resolution
));
820 strlcpy(profile
->media_type
, text
, sizeof(profile
->media_type
));
822 profile
->density
= (float)_cupsStrScand(string
, &sptr
, loc
);
823 profile
->gamma
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
824 profile
->matrix
[0][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
825 profile
->matrix
[0][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
826 profile
->matrix
[0][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
827 profile
->matrix
[1][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
828 profile
->matrix
[1][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
829 profile
->matrix
[1][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
830 profile
->matrix
[2][0] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
831 profile
->matrix
[2][1] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
832 profile
->matrix
[2][2] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
834 else if (!strcmp(keyword
, "cupsFilter"))
836 if (ppd
->num_filters
== 0)
837 filter
= malloc(sizeof(char *));
839 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
845 cg
->ppd_status
= PPD_ALLOC_ERROR
;
850 ppd
->filters
= filter
;
851 filter
+= ppd
->num_filters
;
855 * Copy filter string and prevent it from being freed below...
861 else if (!strcmp(keyword
, "Throughput"))
862 ppd
->throughput
= atoi(string
);
863 else if (!strcmp(keyword
, "Font"))
866 * Add this font to the list of available fonts...
869 if (ppd
->num_fonts
== 0)
870 tempfonts
= (char **)malloc(sizeof(char *));
872 tempfonts
= (char **)realloc(ppd
->fonts
,
873 sizeof(char *) * (ppd
->num_fonts
+ 1));
875 if (tempfonts
== NULL
)
877 cg
->ppd_status
= PPD_ALLOC_ERROR
;
882 ppd
->fonts
= tempfonts
;
883 ppd
->fonts
[ppd
->num_fonts
] = strdup(name
);
886 else if (!strncmp(keyword
, "ParamCustom", 11))
888 ppd_coption_t
*coption
; /* Custom option */
889 ppd_cparam_t
*cparam
; /* Custom parameter */
890 int corder
; /* Order number */
891 char ctype
[33], /* Data type */
892 cminimum
[65], /* Minimum value */
893 cmaximum
[65]; /* Maximum value */
897 * Get the custom option and parameter...
900 if ((coption
= ppd_get_coption(ppd
, keyword
+ 11)) == NULL
)
902 cg
->ppd_status
= PPD_ALLOC_ERROR
;
907 if ((cparam
= ppd_get_cparam(coption
, name
, text
)) == NULL
)
909 cg
->ppd_status
= PPD_ALLOC_ERROR
;
915 * Get the parameter data...
918 if (sscanf(string
, "%d%32s%64s%64s", &corder
, ctype
, cminimum
,
921 cg
->ppd_status
= PPD_BAD_CUSTOM_PARAM
;
926 cparam
->order
= corder
;
928 if (!strcmp(ctype
, "curve"))
930 cparam
->type
= PPD_CUSTOM_CURVE
;
931 cparam
->minimum
.custom_curve
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
932 cparam
->maximum
.custom_curve
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
934 else if (!strcmp(ctype
, "int"))
936 cparam
->type
= PPD_CUSTOM_INT
;
937 cparam
->minimum
.custom_int
= atoi(cminimum
);
938 cparam
->maximum
.custom_int
= atoi(cmaximum
);
940 else if (!strcmp(ctype
, "invcurve"))
942 cparam
->type
= PPD_CUSTOM_INVCURVE
;
943 cparam
->minimum
.custom_invcurve
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
944 cparam
->maximum
.custom_invcurve
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
946 else if (!strcmp(ctype
, "passcode"))
948 cparam
->type
= PPD_CUSTOM_PASSCODE
;
949 cparam
->minimum
.custom_passcode
= atoi(cminimum
);
950 cparam
->maximum
.custom_passcode
= atoi(cmaximum
);
952 else if (!strcmp(ctype
, "password"))
954 cparam
->type
= PPD_CUSTOM_PASSWORD
;
955 cparam
->minimum
.custom_password
= atoi(cminimum
);
956 cparam
->maximum
.custom_password
= atoi(cmaximum
);
958 else if (!strcmp(ctype
, "points"))
960 cparam
->type
= PPD_CUSTOM_POINTS
;
961 cparam
->minimum
.custom_points
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
962 cparam
->maximum
.custom_points
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
964 else if (!strcmp(ctype
, "real"))
966 cparam
->type
= PPD_CUSTOM_REAL
;
967 cparam
->minimum
.custom_real
= (float)_cupsStrScand(cminimum
, NULL
, loc
);
968 cparam
->maximum
.custom_real
= (float)_cupsStrScand(cmaximum
, NULL
, loc
);
970 else if (!strcmp(ctype
, "string"))
972 cparam
->type
= PPD_CUSTOM_STRING
;
973 cparam
->minimum
.custom_string
= atoi(cminimum
);
974 cparam
->maximum
.custom_string
= atoi(cmaximum
);
978 cg
->ppd_status
= PPD_BAD_CUSTOM_PARAM
;
984 * Now special-case for CustomPageSize...
987 if (!strcmp(coption
->keyword
, "PageSize"))
989 if (!strcmp(name
, "Width"))
991 ppd
->custom_min
[0] = cparam
->minimum
.custom_points
;
992 ppd
->custom_max
[0] = cparam
->maximum
.custom_points
;
994 else if (!strcmp(name
, "Height"))
996 ppd
->custom_min
[1] = cparam
->minimum
.custom_points
;
997 ppd
->custom_max
[1] = cparam
->maximum
.custom_points
;
1001 else if (!strcmp(keyword
, "HWMargins"))
1003 for (i
= 0, sptr
= string
; i
< 4; i
++)
1004 ppd
->custom_margins
[i
] = (float)_cupsStrScand(sptr
, &sptr
, loc
);
1006 else if (!strncmp(keyword
, "Custom", 6) && !strcmp(name
, "True"))
1008 DEBUG_puts("Processing Custom option...");
1011 * Get the option and custom option...
1014 if ((option
= ppdFindOption(ppd
, keyword
+ 6)) == NULL
)
1016 ppd_group_t
*gtemp
; /* Temporary group */
1019 DEBUG_printf(("%s option not found for %s...\n", keyword
+ 6, keyword
));
1021 if ((gtemp
= ppd_get_group(ppd
, "General", _("General"), cg
,
1024 DEBUG_puts("Unable to get general group!");
1029 if ((option
= ppd_get_option(gtemp
, keyword
+ 6)) == NULL
)
1031 DEBUG_printf(("Unable to get %s option!\n", keyword
+ 6));
1033 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1039 if (!ppd_get_coption(ppd
, keyword
+ 6))
1041 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1047 * Add the "custom" option...
1050 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
1052 DEBUG_puts("Unable to add Custom choice!");
1054 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1059 strlcpy(choice
->text
, text
[0] ? text
: _("Custom"),
1060 sizeof(choice
->text
));
1062 choice
->code
= string
;
1063 string
= NULL
; /* Don't add as an attribute below */
1067 * Now process custom page sizes specially...
1070 if (!strcmp(keyword
, "CustomPageSize"))
1072 ppd
->variable_sizes
= 1;
1075 * Add a "Custom" page size entry...
1078 ppd_add_size(ppd
, "Custom");
1081 else if (!strcmp(keyword
, "LandscapeOrientation"))
1083 if (!strcmp(string
, "Minus90"))
1084 ppd
->landscape
= -90;
1085 else if (!strcmp(string
, "Plus90"))
1086 ppd
->landscape
= 90;
1088 else if (!strcmp(keyword
, "Emulators"))
1090 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
1091 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
1094 while (*sptr
== ' ')
1098 ppd
->num_emulations
= count
;
1099 ppd
->emulations
= calloc(count
, sizeof(ppd_emul_t
));
1101 for (i
= 0, sptr
= string
; i
< count
; i
++)
1103 for (nameptr
= ppd
->emulations
[i
].name
;
1104 *sptr
!= '\0' && *sptr
!= ' ';
1106 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
1111 while (*sptr
== ' ')
1115 else if (!strncmp(keyword
, "StartEmulator_", 14))
1119 for (i
= 0; i
< ppd
->num_emulations
; i
++)
1120 if (!strcmp(keyword
+ 14, ppd
->emulations
[i
].name
))
1122 ppd
->emulations
[i
].start
= string
;
1126 else if (!strncmp(keyword
, "StopEmulator_", 13))
1130 for (i
= 0; i
< ppd
->num_emulations
; i
++)
1131 if (!strcmp(keyword
+ 13, ppd
->emulations
[i
].name
))
1133 ppd
->emulations
[i
].stop
= string
;
1137 else if (!strcmp(keyword
, "JobPatchFile"))
1139 if (ppd
->patches
== NULL
)
1140 ppd
->patches
= strdup(string
);
1143 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
1144 strlen(string
) + 1);
1147 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1152 ppd
->patches
= temp
;
1154 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
1157 else if (!strcmp(keyword
, "OpenUI"))
1160 * Don't allow nesting of options...
1163 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1165 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1171 * Add an option record to the current sub-group, group, or file...
1175 _cups_strcpy(name
, name
+ 1); /* Eliminate leading asterisk */
1177 for (i
= (int)strlen(name
) - 1; i
> 0 && isspace(name
[i
] & 255); i
--)
1178 name
[i
] = '\0'; /* Eliminate trailing spaces */
1180 DEBUG_printf(("OpenUI of %s in group %s...\n", name
,
1181 group
? group
->text
: "(null)"));
1183 if (subgroup
!= NULL
)
1184 option
= ppd_get_option(subgroup
, name
);
1185 else if (group
== NULL
)
1187 if ((group
= ppd_get_group(ppd
, "General", _("General"), cg
,
1191 DEBUG_printf(("Adding to group %s...\n", group
->text
));
1192 option
= ppd_get_option(group
, name
);
1196 option
= ppd_get_option(group
, name
);
1200 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1206 * Now fill in the initial information for the option...
1209 if (string
&& !strcmp(string
, "PickMany"))
1210 option
->ui
= PPD_UI_PICKMANY
;
1211 else if (string
&& !strcmp(string
, "Boolean"))
1212 option
->ui
= PPD_UI_BOOLEAN
;
1213 else if (string
&& !strcmp(string
, "PickOne"))
1214 option
->ui
= PPD_UI_PICKONE
;
1215 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1217 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1222 option
->ui
= PPD_UI_PICKONE
;
1224 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1225 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1226 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1227 ppd
->attrs
[j
]->value
)
1229 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1230 option
->keyword
, ppd
->attrs
[j
]->value
));
1231 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1232 sizeof(option
->defchoice
));
1237 cupsCharsetToUTF8((cups_utf8_t
*)option
->text
, text
,
1238 sizeof(option
->text
), encoding
);
1241 if (!strcmp(name
, "PageSize"))
1242 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
1243 else if (!strcmp(name
, "MediaType"))
1244 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
1245 else if (!strcmp(name
, "InputSlot"))
1246 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
1247 else if (!strcmp(name
, "ColorModel"))
1248 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
1249 else if (!strcmp(name
, "Resolution"))
1250 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
1252 strlcpy(option
->text
, name
, sizeof(option
->text
));
1255 option
->section
= PPD_ORDER_ANY
;
1260 else if (!strcmp(keyword
, "JCLOpenUI"))
1263 * Don't allow nesting of options...
1266 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1268 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1274 * Find the JCL group, and add if needed...
1277 group
= ppd_get_group(ppd
, "JCL", _("JCL"), cg
, encoding
);
1283 * Add an option record to the current JCLs...
1287 _cups_strcpy(name
, name
+ 1);
1289 option
= ppd_get_option(group
, name
);
1293 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1299 * Now fill in the initial information for the option...
1302 if (string
&& !strcmp(string
, "PickMany"))
1303 option
->ui
= PPD_UI_PICKMANY
;
1304 else if (string
&& !strcmp(string
, "Boolean"))
1305 option
->ui
= PPD_UI_BOOLEAN
;
1306 else if (string
&& !strcmp(string
, "PickOne"))
1307 option
->ui
= PPD_UI_PICKONE
;
1310 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1315 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1316 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1317 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1318 ppd
->attrs
[j
]->value
)
1320 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1321 option
->keyword
, ppd
->attrs
[j
]->value
));
1322 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1323 sizeof(option
->defchoice
));
1328 cupsCharsetToUTF8((cups_utf8_t
*)option
->text
, text
,
1329 sizeof(option
->text
), encoding
);
1331 strlcpy(option
->text
, name
, sizeof(option
->text
));
1333 option
->section
= PPD_ORDER_JCL
;
1339 else if (!strcmp(keyword
, "CloseUI") || !strcmp(keyword
, "JCLCloseUI"))
1346 else if (!strcmp(keyword
, "OpenGroup"))
1349 * Open a new group...
1354 cg
->ppd_status
= PPD_NESTED_OPEN_GROUP
;
1361 cg
->ppd_status
= PPD_BAD_OPEN_GROUP
;
1367 * Separate the group name from the text (name/text)...
1370 if ((sptr
= strchr(string
, '/')) != NULL
)
1376 * Fix up the text...
1382 * Find/add the group...
1385 group
= ppd_get_group(ppd
, string
, sptr
, cg
, encoding
);
1393 else if (!strcmp(keyword
, "CloseGroup"))
1400 else if (!strcmp(keyword
, "OrderDependency") ||
1401 !strcmp(keyword
, "NonUIOrderDependency"))
1403 order
= (float)_cupsStrScand(string
, &sptr
, loc
);
1405 if (!sptr
|| sscanf(sptr
, "%40s%40s", name
, keyword
) != 2)
1407 cg
->ppd_status
= PPD_BAD_ORDER_DEPENDENCY
;
1412 if (keyword
[0] == '*')
1413 _cups_strcpy(keyword
, keyword
+ 1);
1415 if (!strcmp(name
, "ExitServer"))
1416 section
= PPD_ORDER_EXIT
;
1417 else if (!strcmp(name
, "Prolog"))
1418 section
= PPD_ORDER_PROLOG
;
1419 else if (!strcmp(name
, "DocumentSetup"))
1420 section
= PPD_ORDER_DOCUMENT
;
1421 else if (!strcmp(name
, "PageSetup"))
1422 section
= PPD_ORDER_PAGE
;
1423 else if (!strcmp(name
, "JCLSetup"))
1424 section
= PPD_ORDER_JCL
;
1426 section
= PPD_ORDER_ANY
;
1434 * Only valid for Non-UI options...
1437 for (i
= ppd
->num_groups
, gtemp
= ppd
->groups
; i
> 0; i
--, gtemp
++)
1438 if (gtemp
->text
[0] == '\0')
1442 for (i
= 0; i
< gtemp
->num_options
; i
++)
1443 if (!strcmp(keyword
, gtemp
->options
[i
].keyword
))
1445 gtemp
->options
[i
].section
= section
;
1446 gtemp
->options
[i
].order
= order
;
1452 option
->section
= section
;
1453 option
->order
= order
;
1459 else if (!strncmp(keyword
, "Default", 7))
1465 * Drop UI text, if any, from value...
1468 if (strchr(string
, '/') != NULL
)
1469 *strchr(string
, '/') = '\0';
1472 * Assign the default value as appropriate...
1475 if (!strcmp(keyword
, "DefaultColorSpace"))
1478 * Set default colorspace...
1481 if (!strcmp(string
, "CMY"))
1482 ppd
->colorspace
= PPD_CS_CMY
;
1483 else if (!strcmp(string
, "CMYK"))
1484 ppd
->colorspace
= PPD_CS_CMYK
;
1485 else if (!strcmp(string
, "RGB"))
1486 ppd
->colorspace
= PPD_CS_RGB
;
1487 else if (!strcmp(string
, "RGBK"))
1488 ppd
->colorspace
= PPD_CS_RGBK
;
1489 else if (!strcmp(string
, "N"))
1490 ppd
->colorspace
= PPD_CS_N
;
1492 ppd
->colorspace
= PPD_CS_GRAY
;
1494 else if (option
&& !strcmp(keyword
+ 7, option
->keyword
))
1497 * Set the default as part of the current option...
1500 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1502 strlcpy(option
->defchoice
, string
, sizeof(option
->defchoice
));
1504 DEBUG_printf(("%s is now %s...\n", keyword
, option
->defchoice
));
1509 * Lookup option and set if it has been defined...
1512 ppd_option_t
*toption
; /* Temporary option */
1515 if ((toption
= ppdFindOption(ppd
, keyword
+ 7)) != NULL
)
1517 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1518 strlcpy(toption
->defchoice
, string
, sizeof(toption
->defchoice
));
1522 else if (!strcmp(keyword
, "UIConstraints") ||
1523 !strcmp(keyword
, "NonUIConstraints"))
1525 if (ppd
->num_consts
== 0)
1526 constraint
= calloc(1, sizeof(ppd_const_t
));
1528 constraint
= realloc(ppd
->consts
,
1529 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1531 if (constraint
== NULL
)
1533 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1538 ppd
->consts
= constraint
;
1539 constraint
+= ppd
->num_consts
;
1542 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1543 constraint
->choice1
, constraint
->option2
,
1544 constraint
->choice2
))
1546 case 0 : /* Error */
1547 case 1 : /* Error */
1548 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1551 case 2 : /* Two options... */
1553 * Check for broken constraints like "* Option"...
1556 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1557 (!strcmp(constraint
->option1
, "*") ||
1558 !strcmp(constraint
->choice1
, "*")))
1560 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1565 * The following strcpy's are safe, as optionN and
1566 * choiceN are all the same size (size defined by PPD spec...)
1569 if (constraint
->option1
[0] == '*')
1570 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1571 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1573 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1577 if (constraint
->choice1
[0] == '*')
1578 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1579 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1581 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1585 constraint
->choice1
[0] = '\0';
1586 constraint
->choice2
[0] = '\0';
1589 case 3 : /* Two options, one choice... */
1591 * Check for broken constraints like "* Option"...
1594 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1595 (!strcmp(constraint
->option1
, "*") ||
1596 !strcmp(constraint
->choice1
, "*") ||
1597 !strcmp(constraint
->option2
, "*")))
1599 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1604 * The following _cups_strcpy's are safe, as optionN and
1605 * choiceN are all the same size (size defined by PPD spec...)
1608 if (constraint
->option1
[0] == '*')
1609 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1610 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1612 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1616 if (constraint
->choice1
[0] == '*')
1618 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1619 constraint
->option2
[0] == '*')
1621 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1625 _cups_strcpy(constraint
->choice2
, constraint
->option2
);
1626 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1627 constraint
->choice1
[0] = '\0';
1631 if (constraint
->option2
[0] == '*')
1632 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1633 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1635 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1639 constraint
->choice2
[0] = '\0';
1643 case 4 : /* Two options, two choices... */
1645 * Check for broken constraints like "* Option"...
1648 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1649 (!strcmp(constraint
->option1
, "*") ||
1650 !strcmp(constraint
->choice1
, "*") ||
1651 !strcmp(constraint
->option2
, "*") ||
1652 !strcmp(constraint
->choice2
, "*")))
1654 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1658 if (constraint
->option1
[0] == '*')
1659 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1660 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1662 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1666 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1667 constraint
->choice1
[0] == '*')
1669 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1673 if (constraint
->option2
[0] == '*')
1674 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1675 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1677 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1681 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&&
1682 constraint
->choice2
[0] == '*')
1684 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1691 * Handle CustomFoo option constraints...
1694 if (!strncasecmp(constraint
->option1
, "Custom", 6) &&
1695 !strcasecmp(constraint
->choice1
, "True"))
1697 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 6);
1698 strcpy(constraint
->choice1
, "Custom");
1701 if (!strncasecmp(constraint
->option2
, "Custom", 6) &&
1702 !strcasecmp(constraint
->choice2
, "True"))
1704 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 6);
1705 strcpy(constraint
->choice2
, "Custom");
1709 * Don't add this one as an attribute...
1715 else if (!strcmp(keyword
, "PaperDimension"))
1717 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1718 size
= ppd_add_size(ppd
, name
);
1723 * Unable to add or find size!
1726 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1731 size
->width
= (float)_cupsStrScand(string
, &sptr
, loc
);
1732 size
->length
= (float)_cupsStrScand(sptr
, NULL
, loc
);
1737 else if (!strcmp(keyword
, "ImageableArea"))
1739 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1740 size
= ppd_add_size(ppd
, name
);
1745 * Unable to add or find size!
1748 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1753 size
->left
= (float)_cupsStrScand(string
, &sptr
, loc
);
1754 size
->bottom
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
1755 size
->right
= (float)_cupsStrScand(sptr
, &sptr
, loc
);
1756 size
->top
= (float)_cupsStrScand(sptr
, NULL
, loc
);
1761 else if (option
!= NULL
&&
1762 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1763 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
) &&
1764 !strcmp(keyword
, option
->keyword
))
1766 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1768 if (!strcmp(keyword
, "PageSize"))
1771 * Add a page size...
1774 if (ppdPageSize(ppd
, name
) == NULL
)
1775 ppd_add_size(ppd
, name
);
1779 * Add the option choice...
1782 choice
= ppd_add_choice(option
, name
);
1785 cupsCharsetToUTF8((cups_utf8_t
*)choice
->text
, text
,
1786 sizeof(choice
->text
), encoding
);
1787 else if (!strcmp(name
, "True"))
1788 strcpy(choice
->text
, _("Yes"));
1789 else if (!strcmp(name
, "False"))
1790 strcpy(choice
->text
, _("No"));
1792 strlcpy(choice
->text
, name
, sizeof(choice
->text
));
1794 if (option
->section
== PPD_ORDER_JCL
)
1795 ppd_decode(string
); /* Decode quoted string */
1797 choice
->code
= string
;
1798 string
= NULL
; /* Don't add as an attribute below */
1802 * Add remaining lines with keywords and string values as attributes...
1806 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
))
1807 ppd_add_attr(ppd
, keyword
, name
, text
, string
);
1813 * Reset language preferences...
1816 cupsLangFree(language
);
1820 printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp
));
1823 if (cg
->ppd_status
!= PPD_OK
)
1826 * Had an error reading the PPD file, cannot continue!
1835 * Create the sorted options array and set the option back-pointer for
1836 * each choice and custom option...
1839 ppd
->options
= cupsArrayNew((cups_array_func_t
)ppd_compare_options
, NULL
);
1841 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1845 for (j
= group
->num_options
, option
= group
->options
;
1849 ppd_coption_t
*coption
; /* Custom option */
1852 cupsArrayAdd(ppd
->options
, option
);
1854 for (k
= 0; k
< option
->num_choices
; k
++)
1855 option
->choices
[k
].option
= option
;
1857 if ((coption
= ppdFindCustomOption(ppd
, option
->keyword
)) != NULL
)
1858 coption
->option
= option
;
1863 * Return the PPD file structure...
1869 * Common exit point for errors to save code size...
1878 cupsLangFree(language
);
1885 * 'ppdOpenFd()' - Read a PPD file into memory.
1888 ppd_file_t
* /* O - PPD file record */
1889 ppdOpenFd(int fd
) /* I - File to read from */
1891 cups_file_t
*fp
; /* CUPS file pointer */
1892 ppd_file_t
*ppd
; /* PPD file record */
1893 _cups_globals_t
*cg
= _cupsGlobals();
1898 * Set the line number to 0...
1904 * Range check input...
1909 cg
->ppd_status
= PPD_NULL_FILE
;
1915 * Try to open the file and parse it...
1918 if ((fp
= cupsFileOpenFd(fd
, "r")) != NULL
)
1926 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
1935 * 'ppdOpenFile()' - Read a PPD file into memory.
1938 ppd_file_t
* /* O - PPD file record */
1939 ppdOpenFile(const char *filename
) /* I - File to read from */
1941 cups_file_t
*fp
; /* File pointer */
1942 ppd_file_t
*ppd
; /* PPD file record */
1943 _cups_globals_t
*cg
= _cupsGlobals();
1948 * Set the line number to 0...
1954 * Range check input...
1957 if (filename
== NULL
)
1959 cg
->ppd_status
= PPD_NULL_FILE
;
1965 * Try to open the file and parse it...
1968 if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
1976 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
1985 * 'ppdSetConformance()' - Set the conformance level for PPD files.
1987 * @since CUPS 1.1.20@
1991 ppdSetConformance(ppd_conform_t c
) /* I - Conformance level */
1993 _cups_globals_t
*cg
= _cupsGlobals();
1997 cg
->ppd_conform
= c
;
2002 * 'ppd_add_attr()' - Add an attribute to the PPD data.
2005 static ppd_attr_t
* /* O - New attribute */
2006 ppd_add_attr(ppd_file_t
*ppd
, /* I - PPD file data */
2007 const char *name
, /* I - Attribute name */
2008 const char *spec
, /* I - Specifier string, if any */
2009 const char *text
, /* I - Text string, if any */
2010 const char *value
) /* I - Value of attribute */
2012 ppd_attr_t
**ptr
, /* New array */
2013 *temp
; /* New attribute */
2017 * Range check input...
2020 if (ppd
== NULL
|| name
== NULL
|| spec
== NULL
)
2024 * Create the array as needed...
2027 if (!ppd
->sorted_attrs
)
2028 ppd
->sorted_attrs
= cupsArrayNew((cups_array_func_t
)ppd_compare_attrs
,
2032 * Allocate memory for the new attribute...
2035 if (ppd
->num_attrs
== 0)
2036 ptr
= malloc(sizeof(ppd_attr_t
*));
2038 ptr
= realloc(ppd
->attrs
, (ppd
->num_attrs
+ 1) * sizeof(ppd_attr_t
*));
2044 ptr
+= ppd
->num_attrs
;
2046 if ((temp
= calloc(1, sizeof(ppd_attr_t
))) == NULL
)
2057 strlcpy(temp
->name
, name
, sizeof(temp
->name
));
2058 strlcpy(temp
->spec
, spec
, sizeof(temp
->spec
));
2059 strlcpy(temp
->text
, text
, sizeof(temp
->text
));
2060 temp
->value
= (char *)value
;
2063 * Add the attribute to the sorted array...
2066 cupsArrayAdd(ppd
->sorted_attrs
, temp
);
2069 * Return the attribute...
2077 * 'ppd_add_choice()' - Add a choice to an option.
2080 static ppd_choice_t
* /* O - Named choice */
2081 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
2082 const char *name
) /* I - Name of choice */
2084 ppd_choice_t
*choice
; /* Choice */
2087 if (option
->num_choices
== 0)
2088 choice
= malloc(sizeof(ppd_choice_t
));
2090 choice
= realloc(option
->choices
,
2091 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
2096 option
->choices
= choice
;
2097 choice
+= option
->num_choices
;
2098 option
->num_choices
++;
2100 memset(choice
, 0, sizeof(ppd_choice_t
));
2101 strlcpy(choice
->choice
, name
, sizeof(choice
->choice
));
2108 * 'ppd_add_size()' - Add a page size.
2111 static ppd_size_t
* /* O - Named size */
2112 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
2113 const char *name
) /* I - Name of size */
2115 ppd_size_t
*size
; /* Size */
2118 if (ppd
->num_sizes
== 0)
2119 size
= malloc(sizeof(ppd_size_t
));
2121 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
2127 size
+= ppd
->num_sizes
;
2130 memset(size
, 0, sizeof(ppd_size_t
));
2131 strlcpy(size
->name
, name
, sizeof(size
->name
));
2138 * 'ppd_compare_attrs()' - Compare two attributes.
2141 static int /* O - Result of comparison */
2142 ppd_compare_attrs(ppd_attr_t
*a
, /* I - First attribute */
2143 ppd_attr_t
*b
) /* I - Second attribute */
2145 int ret
; /* Result of comparison */
2148 if ((ret
= strcasecmp(a
->name
, b
->name
)) != 0)
2151 return (strcasecmp(a
->spec
, b
->spec
));
2156 * 'ppd_compare_coptions()' - Compare two custom options.
2159 static int /* O - Result of comparison */
2160 ppd_compare_coptions(ppd_coption_t
*a
, /* I - First option */
2161 ppd_coption_t
*b
) /* I - Second option */
2163 return (strcasecmp(a
->keyword
, b
->keyword
));
2168 * 'ppd_compare_cparams()' - Compare two custom parameters.
2171 static int /* O - Result of comparison */
2172 ppd_compare_cparams(ppd_cparam_t
*a
, /* I - First parameter */
2173 ppd_cparam_t
*b
) /* I - Second parameter */
2175 return (strcasecmp(a
->name
, b
->name
));
2180 * 'ppd_compare_options()' - Compare two options.
2183 static int /* O - Result of comparison */
2184 ppd_compare_options(ppd_option_t
*a
, /* I - First option */
2185 ppd_option_t
*b
) /* I - Second option */
2187 return (strcasecmp(a
->keyword
, b
->keyword
));
2192 * 'ppd_decode()' - Decode a string value...
2195 static int /* O - Length of decoded string */
2196 ppd_decode(char *string
) /* I - String to decode */
2198 char *inptr
, /* Input pointer */
2199 *outptr
; /* Output pointer */
2205 while (*inptr
!= '\0')
2206 if (*inptr
== '<' && isxdigit(inptr
[1] & 255))
2209 * Convert hex to 8-bit values...
2213 while (isxdigit(*inptr
& 255))
2215 if (isalpha(*inptr
))
2216 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
2218 *outptr
= (*inptr
- '0') << 4;
2222 if (!isxdigit(*inptr
& 255))
2225 if (isalpha(*inptr
))
2226 *outptr
|= tolower(*inptr
) - 'a' + 10;
2228 *outptr
|= *inptr
- '0';
2234 while (*inptr
!= '>' && *inptr
!= '\0')
2236 while (*inptr
== '>')
2240 *outptr
++ = *inptr
++;
2244 return ((int)(outptr
- string
));
2249 * 'ppd_free_group()' - Free a single UI group.
2253 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
2255 int i
; /* Looping var */
2256 ppd_option_t
*option
; /* Current option */
2257 ppd_group_t
*subgroup
; /* Current sub-group */
2260 if (group
->num_options
> 0)
2262 for (i
= group
->num_options
, option
= group
->options
;
2265 ppd_free_option(option
);
2267 ppd_free(group
->options
);
2270 if (group
->num_subgroups
> 0)
2272 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
2275 ppd_free_group(subgroup
);
2277 ppd_free(group
->subgroups
);
2283 * 'ppd_free_option()' - Free a single option.
2287 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
2289 int i
; /* Looping var */
2290 ppd_choice_t
*choice
; /* Current choice */
2293 if (option
->num_choices
> 0)
2295 for (i
= option
->num_choices
, choice
= option
->choices
;
2299 ppd_free(choice
->code
);
2302 ppd_free(option
->choices
);
2308 * 'ppd_get_coption()' - Get a custom option record.
2311 static ppd_coption_t
* /* O - Custom option... */
2312 ppd_get_coption(ppd_file_t
*ppd
, /* I - PPD file */
2313 const char *name
) /* I - Name of option */
2315 ppd_coption_t
*copt
; /* New custom option */
2319 * See if the option already exists...
2322 if ((copt
= ppdFindCustomOption(ppd
, name
)) != NULL
)
2326 * Not found, so create the custom option record...
2329 if ((copt
= calloc(1, sizeof(ppd_coption_t
))) == NULL
)
2332 strlcpy(copt
->keyword
, name
, sizeof(copt
->keyword
));
2334 copt
->params
= cupsArrayNew((cups_array_func_t
)ppd_compare_cparams
, NULL
);
2336 cupsArrayAdd(ppd
->coptions
, copt
);
2339 * Return the new record...
2347 * 'ppd_get_cparam()' - Get a custom parameter record.
2350 static ppd_cparam_t
* /* O - Extended option... */
2351 ppd_get_cparam(ppd_coption_t
*opt
, /* I - PPD file */
2352 const char *param
, /* I - Name of parameter */
2353 const char *text
) /* I - Human-readable text */
2355 ppd_cparam_t
*cparam
; /* New custom parameter */
2359 * See if the parameter already exists...
2362 if ((cparam
= ppdFindCustomParam(opt
, param
)) != NULL
)
2366 * Not found, so create the custom parameter record...
2369 if ((cparam
= calloc(1, sizeof(ppd_cparam_t
))) == NULL
)
2372 strlcpy(cparam
->name
, param
, sizeof(cparam
->name
));
2373 strlcpy(cparam
->text
, text
[0] ? text
: param
, sizeof(cparam
->text
));
2376 * Add this record to the array...
2379 cupsArrayAdd(opt
->params
, cparam
);
2382 * Return the new record...
2390 * 'ppd_get_group()' - Find or create the named group as needed.
2393 static ppd_group_t
* /* O - Named group */
2394 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
2395 const char *name
, /* I - Name of group */
2396 const char *text
, /* I - Text for group */
2397 _cups_globals_t
*cg
, /* I - Global data */
2398 cups_encoding_t encoding
) /* I - Encoding of text */
2400 int i
; /* Looping var */
2401 ppd_group_t
*group
; /* Group */
2404 DEBUG_printf(("ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)\n",
2405 ppd
, name
, text
, cg
));
2407 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
2408 if (!strcmp(group
->name
, name
))
2413 DEBUG_printf(("Adding group %s...\n", name
));
2415 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&& strlen(text
) >= sizeof(group
->text
))
2417 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2422 if (ppd
->num_groups
== 0)
2423 group
= malloc(sizeof(ppd_group_t
));
2425 group
= realloc(ppd
->groups
,
2426 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
2430 cg
->ppd_status
= PPD_ALLOC_ERROR
;
2435 ppd
->groups
= group
;
2436 group
+= ppd
->num_groups
;
2439 memset(group
, 0, sizeof(ppd_group_t
));
2440 strlcpy(group
->name
, name
, sizeof(group
->name
));
2442 cupsCharsetToUTF8((cups_utf8_t
*)group
->text
, text
,
2443 sizeof(group
->text
), encoding
);
2451 * 'ppd_get_option()' - Find or create the named option as needed.
2454 static ppd_option_t
* /* O - Named option */
2455 ppd_get_option(ppd_group_t
*group
, /* I - Group */
2456 const char *name
) /* I - Name of option */
2458 int i
; /* Looping var */
2459 ppd_option_t
*option
; /* Option */
2462 DEBUG_printf(("ppd_get_option(group=%p(\"%s\"), name=\"%s\")\n",
2463 group
, group
->name
, name
));
2465 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
2466 if (!strcmp(option
->keyword
, name
))
2471 if (group
->num_options
== 0)
2472 option
= malloc(sizeof(ppd_option_t
));
2474 option
= realloc(group
->options
,
2475 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
2480 group
->options
= option
;
2481 option
+= group
->num_options
;
2482 group
->num_options
++;
2484 memset(option
, 0, sizeof(ppd_option_t
));
2485 strlcpy(option
->keyword
, name
, sizeof(option
->keyword
));
2493 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2497 static int /* O - Bitmask of fields read */
2498 ppd_read(cups_file_t
*fp
, /* I - File to read from */
2499 char *keyword
, /* O - Keyword from line */
2500 char *option
, /* O - Option from line */
2501 char *text
, /* O - Human-readable text from line */
2502 char **string
, /* O - Code/string data */
2503 int ignoreblank
, /* I - Ignore blank lines? */
2504 _cups_globals_t
*cg
) /* I - Global data */
2506 int ch
, /* Character from file */
2507 col
, /* Column in line */
2508 colon
, /* Colon seen? */
2509 endquote
, /* Waiting for an end quote */
2510 mask
, /* Mask to be returned */
2511 startline
, /* Start line */
2512 textlen
; /* Length of text */
2513 char *keyptr
, /* Keyword pointer */
2514 *optptr
, /* Option pointer */
2515 *textptr
, /* Text pointer */
2516 *strptr
, /* Pointer into string */
2517 *lineptr
, /* Current position in line buffer */
2518 *line
; /* Line buffer */
2519 int linesize
; /* Current size of line buffer */
2522 * Range check everything...
2525 if (!fp
|| !keyword
|| !option
|| !text
|| !string
)
2529 * Now loop until we have a valid line...
2534 startline
= cg
->ppd_line
+ 1;
2536 line
= malloc(linesize
);
2551 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2553 if (lineptr
>= (line
+ linesize
- 1))
2556 * Expand the line buffer...
2559 char *temp
; /* Temporary line pointer */
2563 if (linesize
> 262144)
2566 * Don't allow lines longer than 256k!
2569 cg
->ppd_line
= startline
;
2570 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2577 temp
= realloc(line
, linesize
);
2580 cg
->ppd_line
= startline
;
2581 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2588 lineptr
= temp
+ (lineptr
- line
);
2592 if (ch
== '\r' || ch
== '\n')
2595 * Line feed or carriage return...
2604 * Check for a trailing line feed...
2607 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2614 cupsFileGetChar(fp
);
2617 if (lineptr
== line
&& ignoreblank
)
2618 continue; /* Skip blank lines */
2622 if (!endquote
) /* Continue for multi-line text */
2627 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2630 * Other control characters...
2633 cg
->ppd_line
= startline
;
2634 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2640 else if (ch
!= 0x1a)
2643 * Any other character...
2649 if (col
> (PPD_MAX_LINE
- 1))
2652 * Line is too long...
2655 cg
->ppd_line
= startline
;
2656 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2663 if (ch
== ':' && strncmp(line
, "*%", 2) != 0)
2666 if (ch
== '\"' && colon
)
2667 endquote
= !endquote
;
2674 * Didn't finish this quoted string...
2677 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2680 else if (ch
== '\r' || ch
== '\n')
2688 * Check for a trailing line feed...
2691 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2694 cupsFileGetChar(fp
);
2699 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2702 * Other control characters...
2705 cg
->ppd_line
= startline
;
2706 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2712 else if (ch
!= 0x1a)
2716 if (col
> (PPD_MAX_LINE
- 1))
2719 * Line is too long...
2722 cg
->ppd_line
= startline
;
2723 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2735 * Didn't finish this line...
2738 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2739 if (ch
== '\r' || ch
== '\n')
2742 * Line feed or carriage return...
2751 * Check for a trailing line feed...
2754 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2757 cupsFileGetChar(fp
);
2762 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2765 * Other control characters...
2768 cg
->ppd_line
= startline
;
2769 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2775 else if (ch
!= 0x1a)
2779 if (col
> (PPD_MAX_LINE
- 1))
2782 * Line is too long...
2785 cg
->ppd_line
= startline
;
2786 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2795 if (lineptr
> line
&& lineptr
[-1] == '\n')
2800 DEBUG_printf(("LINE = \"%s\"\n", line
));
2803 * The dynamically created PPDs for older style Mac OS X
2804 * drivers include a large blob of data inserted as comments
2805 * at the end of the file. As an optimization we can stop
2806 * reading the PPD when we get to the start of this data.
2809 if (!strcmp(line
, "*%APLWORKSET START"))
2815 if (ch
== EOF
&& lineptr
== line
)
2833 if ((!line
[0] || /* Blank line */
2834 !strncmp(line
, "*%", 2) || /* Comment line */
2835 !strcmp(line
, "*End")) && /* End of multi-line string */
2836 ignoreblank
) /* Ignore these? */
2838 startline
= cg
->ppd_line
+ 1;
2842 if (!strcmp(line
, "*")) /* (Bad) comment line */
2844 if (cg
->ppd_conform
== PPD_CONFORM_RELAXED
)
2846 startline
= cg
->ppd_line
+ 1;
2851 cg
->ppd_line
= startline
;
2852 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2859 if (line
[0] != '*') /* All lines start with an asterisk */
2862 * Allow lines consisting of just whitespace...
2865 for (lineptr
= line
; *lineptr
; lineptr
++)
2866 if (!isspace(*lineptr
& 255))
2871 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
2875 else if (ignoreblank
)
2890 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
& 255))
2892 if (*lineptr
<= ' ' || *lineptr
> 126 || *lineptr
== '/' ||
2893 (keyptr
- keyword
) >= (PPD_MAX_NAME
- 1))
2895 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2900 *keyptr
++ = *lineptr
++;
2905 if (!strcmp(keyword
, "End"))
2908 mask
|= PPD_KEYWORD
;
2910 /* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/
2912 if (isspace(*lineptr
& 255))
2915 * Get an option name...
2918 while (isspace(*lineptr
& 255))
2923 while (*lineptr
!= '\0' && !isspace(*lineptr
& 255) && *lineptr
!= ':' &&
2926 if (*lineptr
<= ' ' || *lineptr
> 126 ||
2927 (optptr
- option
) >= (PPD_MAX_NAME
- 1))
2929 cg
->ppd_status
= PPD_ILLEGAL_OPTION_KEYWORD
;
2934 *optptr
++ = *lineptr
++;
2939 if (isspace(*lineptr
& 255) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2941 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
2946 while (isspace(*lineptr
& 255))
2951 /* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/
2953 if (*lineptr
== '/')
2956 * Get human-readable text...
2963 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':')
2965 if (((unsigned char)*lineptr
< ' ' && *lineptr
!= '\t') ||
2966 (textptr
- text
) >= (PPD_MAX_LINE
- 1))
2968 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2973 *textptr
++ = *lineptr
++;
2977 textlen
= ppd_decode(text
);
2979 if (textlen
> PPD_MAX_TEXT
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2981 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2989 /* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/
2992 if (isspace(*lineptr
& 255) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2994 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
2999 while (isspace(*lineptr
& 255))
3002 if (*lineptr
== ':')
3005 * Get string after triming leading and trailing whitespace...
3009 while (isspace(*lineptr
& 255))
3012 strptr
= lineptr
+ strlen(lineptr
) - 1;
3013 while (strptr
>= lineptr
&& isspace(*strptr
& 255))
3016 if (*strptr
== '\"')
3019 * Quoted string by itself...
3022 *string
= malloc(strlen(lineptr
) + 1);
3026 for (; *lineptr
!= '\0'; lineptr
++)
3027 if (*lineptr
!= '\"')
3028 *strptr
++ = *lineptr
;
3033 *string
= strdup(lineptr
);
3035 /* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/
3049 * End of "$Id: ppd.c 6187 2007-01-10 16:20:42Z mike $".