2 * "$Id: ppd.c 4910 2006-01-10 21:30:48Z mike $"
4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 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 * _ppd_attr_compare() - Compare two attributes.
38 * ppdClose() - Free all memory used by the PPD file.
39 * ppdErrorString() - Returns the text assocated with a status.
40 * ppdLastError() - Return the status from the last ppdOpen*().
41 * ppdOpen() - Read a PPD file into memory.
42 * ppdOpenFd() - Read a PPD file into memory.
43 * ppdOpenFile() - Read a PPD file into memory.
44 * ppdSetConformance() - Set the conformance level for PPD files.
45 * ppd_add_attr() - Add an attribute to the PPD data.
46 * ppd_add_choice() - Add a choice to an option.
47 * ppd_add_size() - Add a page size.
48 * ppd_compare_groups() - Compare two groups.
49 * ppd_compare_options() - Compare two options.
50 * ppd_decode() - Decode a string value...
51 * ppd_free_group() - Free a single UI group.
52 * ppd_free_option() - Free a single option.
53 * ppd_get_extoption() - Get an extended option record.
54 * ppd_get_extparam() - Get an extended parameter record.
55 * ppd_get_group() - Find or create the named group as needed.
56 * ppd_get_option() - Find or create the named option as needed.
57 * ppd_read() - Read a line from a PPD file, skipping comment
62 * Include necessary headers.
74 #if defined(WIN32) || defined(__EMX__)
75 # define READ_BINARY "rb" /* Open a binary file for reading */
76 # define WRITE_BINARY "wb" /* Open a binary file for writing */
78 # define READ_BINARY "r" /* Open a binary file for reading */
79 # define WRITE_BINARY "w" /* Open a binary file for writing */
80 #endif /* WIN32 || __EMX__ */
82 #define ppd_free(p) if (p) free(p) /* Safe free macro */
84 #define PPD_KEYWORD 1 /* Line contained a keyword */
85 #define PPD_OPTION 2 /* Line contained an option name */
86 #define PPD_TEXT 4 /* Line contained human-readable text */
87 #define PPD_STRING 8 /* Line contained a string or code */
94 static ppd_attr_t
*ppd_add_attr(ppd_file_t
*ppd
, const char *name
,
95 const char *spec
, const char *text
,
97 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, const char *name
);
98 static ppd_size_t
*ppd_add_size(ppd_file_t
*ppd
, const char *name
);
100 static int ppd_compare_groups(ppd_group_t
*g0
, ppd_group_t
*g1
);
101 static int ppd_compare_options(ppd_option_t
*o0
, ppd_option_t
*o1
);
102 #endif /* !__APPLE__ */
103 static int ppd_decode(char *string
);
104 static void ppd_free_group(ppd_group_t
*group
);
105 static void ppd_free_option(ppd_option_t
*option
);
107 static ppd_ext_option_t
*ppd_get_extoption(ppd_file_t
*ppd
, const char *name
);
108 static ppd_ext_param_t
*ppd_get_extparam(ppd_ext_option_t
*opt
,
112 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, const char *name
,
113 const char *text
, _cups_globals_t
*cg
);
114 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, const char *name
);
115 static int ppd_read(cups_file_t
*fp
, char *keyword
, char *option
,
116 char *text
, char **string
, int ignoreblank
,
117 _cups_globals_t
*cg
);
121 * '_ppd_attr_compare()' - Compare two attributes.
124 int /* O - Result of comparison */
125 _ppd_attr_compare(ppd_attr_t
**a
, /* I - First attribute */
126 ppd_attr_t
**b
) /* I - Second attribute */
128 int ret
; /* Result of comparison */
131 if ((ret
= strcasecmp((*a
)->name
, (*b
)->name
)) != 0)
133 else if ((*a
)->spec
[0] && (*b
)->spec
[0])
134 return (strcasecmp((*a
)->spec
, (*b
)->spec
));
141 * 'ppdClose()' - Free all memory used by the PPD file.
145 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
147 int i
; /* Looping var */
148 ppd_emul_t
*emul
; /* Current emulation */
149 ppd_group_t
*group
; /* Current group */
150 char **font
; /* Current font */
151 char **filter
; /* Current filter */
152 ppd_attr_t
**attr
; /* Current attribute */
154 int j
; /* Looping var */
155 ppd_ext_option_t
**opt
; /* Current extended option */
156 ppd_ext_param_t
**param
; /* Current extended parameter */
161 * Range check the PPD file record...
168 * Free all strings at the top level...
171 ppd_free(ppd
->patches
);
172 ppd_free(ppd
->jcl_begin
);
173 ppd_free(ppd
->jcl_end
);
174 ppd_free(ppd
->jcl_ps
);
177 * Free any emulations...
180 if (ppd
->num_emulations
> 0)
182 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
184 ppd_free(emul
->start
);
185 ppd_free(emul
->stop
);
188 ppd_free(ppd
->emulations
);
192 * Free any UI groups, subgroups, and options...
195 if (ppd
->num_groups
> 0)
197 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
198 ppd_free_group(group
);
200 ppd_free(ppd
->groups
);
204 * Free any page sizes...
207 if (ppd
->num_sizes
> 0)
209 ppd_free(ppd
->sizes
);
213 * Free any constraints...
216 if (ppd
->num_consts
> 0)
218 ppd_free(ppd
->consts
);
222 * Free any filters...
225 if (ppd
->num_filters
> 0)
227 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
232 ppd_free(ppd
->filters
);
239 if (ppd
->num_fonts
> 0)
241 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
246 ppd_free(ppd
->fonts
);
250 * Free any profiles...
253 if (ppd
->num_profiles
> 0)
255 ppd_free(ppd
->profiles
);
259 * Free any attributes...
262 if (ppd
->num_attrs
> 0)
264 for (i
= ppd
->num_attrs
, attr
= ppd
->attrs
; i
> 0; i
--, attr
++)
266 ppd_free((*attr
)->value
);
270 ppd_free(ppd
->attrs
);
274 if (ppd
->num_extended
)
276 for (i
= ppd
->num_extended
, opt
= ppd
->extended
; i
> 0; i
--, opt
++)
278 ppd_free((*opt
)->code
);
280 for (j
= (*opt
)->num_params
, param
= (*opt
)->params
; j
> 0; j
--, param
++)
281 ppd_free((*param
)->value
);
283 ppd_free((*opt
)->params
);
286 ppd_free(ppd
->extended
);
291 * Free the whole record...
299 * 'ppdErrorString()' - Returns the text assocated with a status.
301 * @since CUPS 1.1.19@
304 const char * /* O - Status string */
305 ppdErrorString(ppd_status_t status
) /* I - PPD status */
307 static const char * const messages
[] =/* Status messages */
310 "Unable to open PPD file",
311 "NULL PPD file pointer",
312 "Memory allocation error",
313 "Missing PPD-Adobe-4.x header",
314 "Missing value string",
317 "OpenGroup without a CloseGroup first",
318 "Bad OpenUI/JCLOpenUI",
319 "OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first",
320 "Bad OrderDependency",
322 "Missing asterisk in column 1",
323 "Line longer than the maximum allowed (255 characters)",
324 "Illegal control character",
325 "Illegal main keyword string",
326 "Illegal option keyword string",
327 "Illegal translation string",
328 "Illegal whitespace character"
332 if (status
< PPD_OK
|| status
> PPD_ILLEGAL_WHITESPACE
)
335 return (messages
[status
]);
340 * 'ppdLastError()' - Return the status from the last ppdOpen*().
342 * @since CUPS 1.1.19@
345 ppd_status_t
/* O - Status code */
346 ppdLastError(int *line
) /* O - Line number */
348 _cups_globals_t
*cg
= _cupsGlobals();
353 *line
= cg
->ppd_line
;
355 return (cg
->ppd_status
);
360 * 'ppdOpen()' - Read a PPD file into memory.
363 ppd_file_t
* /* O - PPD file record */
364 ppdOpen(FILE *fp
) /* I - File to read from */
366 ppd_file_t
*ppd
; /* PPD file record */
367 cups_file_t
*cf
; /* CUPS file */
371 * Reopen the stdio file as a CUPS file...
374 if ((cf
= cupsFileOpenFd(fileno(fp
), "r")) == NULL
)
378 * Load the PPD file using the newer API...
384 * Close the CUPS file and return the PPD...
394 * 'ppdOpen2()' - Read a PPD file into memory.
399 ppd_file_t
* /* O - PPD file record */
400 ppdOpen2(cups_file_t
*fp
) /* I - File to read from */
402 char *oldlocale
; /* Old locale settings */
403 int i
, j
, k
, m
; /* Looping vars */
404 int count
; /* Temporary count */
405 ppd_file_t
*ppd
; /* PPD file record */
406 ppd_group_t
*group
, /* Current group */
407 *subgroup
; /* Current sub-group */
408 ppd_option_t
*option
; /* Current option */
409 ppd_choice_t
*choice
; /* Current choice */
410 ppd_const_t
*constraint
; /* Current constraint */
411 ppd_size_t
*size
; /* Current page size */
412 int mask
; /* Line data mask */
413 char keyword
[PPD_MAX_NAME
],
414 /* Keyword from file */
416 /* Option from file */
418 /* Human-readable text from file */
419 *string
, /* Code/text from file */
420 *sptr
, /* Pointer into string */
421 *nameptr
, /* Pointer into name */
422 *temp
, /* Temporary string pointer */
423 **tempfonts
; /* Temporary fonts pointer */
424 float order
; /* Order dependency number */
425 ppd_section_t section
; /* Order dependency section */
426 ppd_profile_t
*profile
; /* Pointer to color profile */
427 char **filter
; /* Pointer to filter */
428 cups_lang_t
*language
; /* Default language */
429 int ui_keyword
; /* Is this line a UI keyword? */
430 _cups_globals_t
*cg
= _cupsGlobals();
432 static const char * const ui_keywords
[] =
434 /* Boolean keywords */
444 /* PickOne keywords */
457 "JCLFrameBufferSize",
482 * Default to "OK" status...
485 cg
->ppd_status
= PPD_OK
;
489 * Range check input...
494 cg
->ppd_status
= PPD_NULL_FILE
;
499 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
502 mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 0, cg
);
504 DEBUG_printf(("mask=%x, keyword=\"%s\"...\n", mask
, keyword
));
507 strcmp(keyword
, "PPD-Adobe") ||
508 string
== NULL
|| string
[0] != '4')
511 * Either this is not a PPD file, or it is not a 4.x PPD file.
514 if (cg
->ppd_status
== PPD_OK
)
515 cg
->ppd_status
= PPD_MISSING_PPDADOBE4
;
522 DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword
, string
));
527 * Allocate memory for the PPD file record...
530 if ((ppd
= calloc(1, sizeof(ppd_file_t
))) == NULL
)
532 cg
->ppd_status
= PPD_ALLOC_ERROR
;
537 ppd
->language_level
= 1;
538 ppd
->color_device
= 0;
539 ppd
->colorspace
= PPD_CS_GRAY
;
540 ppd
->landscape
= -90;
543 * Get the default language for the user...
546 language
= cupsLangDefault();
549 oldlocale
= _cupsSaveLocale(LC_NUMERIC
, "C");
551 oldlocale
= _cupsSaveLocale(LC_ALL
, "C");
552 #endif /* LC_NUMERIC */
555 * Read lines from the PPD file and add them to the file record...
564 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 1, cg
)) != 0)
567 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
570 printf(", name = \"%s\"", name
);
573 printf(", text = \"%s\"", text
);
577 if (strlen(string
) > 40)
578 printf(", string = %p", string
);
580 printf(", string = \"%s\"", string
);
586 if (strcmp(keyword
, "CloseUI") && strcmp(keyword
, "CloseGroup") &&
587 strcmp(keyword
, "CloseSubGroup") && strncmp(keyword
, "Default", 7) &&
588 strcmp(keyword
, "JCLCloseUI") && strcmp(keyword
, "JCLOpenUI") &&
589 strcmp(keyword
, "OpenUI") && strcmp(keyword
, "OpenGroup") &&
590 strcmp(keyword
, "OpenSubGroup") && string
== NULL
)
593 * Need a string value!
596 cg
->ppd_status
= PPD_MISSING_VALUE
;
602 * Certain main keywords (as defined by the PPD spec) may be used
603 * without the usual OpenUI/CloseUI stuff. Presumably this is just
604 * so that Adobe wouldn't completely break compatibility with PPD
605 * files prior to v4.0 of the spec, but it is hopelessly
606 * inconsistent... Catch these main keywords and automatically
607 * create the corresponding option, as needed...
613 * Previous line was a UI keyword...
620 if (option
== NULL
&&
621 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
622 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
624 for (i
= 0; i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])); i
++)
625 if (!strcmp(keyword
, ui_keywords
[i
]))
628 if (i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])))
631 * Create the option in the appropriate group...
636 DEBUG_printf(("**** FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!\n",
641 if (strcmp(keyword
, "Collate") && strcmp(keyword
, "Duplex") &&
642 strcmp(keyword
, "InputSlot") && strcmp(keyword
, "ManualFeed") &&
643 strcmp(keyword
, "MediaType") && strcmp(keyword
, "MediaColor") &&
644 strcmp(keyword
, "MediaWeight") && strcmp(keyword
, "OutputBin") &&
645 strcmp(keyword
, "OutputMode") && strcmp(keyword
, "OutputOrder") &&
646 strcmp(keyword
, "PageSize") && strcmp(keyword
, "PageRegion"))
647 group
= ppd_get_group(ppd
, "Extra", _("Extra"), cg
);
649 group
= ppd_get_group(ppd
, "General", _("General"), cg
);
654 DEBUG_printf(("Adding to group %s...\n", group
->text
));
655 option
= ppd_get_option(group
, keyword
);
659 option
= ppd_get_option(group
, keyword
);
663 cg
->ppd_status
= PPD_ALLOC_ERROR
;
669 * Now fill in the initial information for the option...
672 if (!strncmp(keyword
, "JCL", 3))
673 option
->section
= PPD_ORDER_JCL
;
675 option
->section
= PPD_ORDER_ANY
;
677 option
->order
= 10.0f
;
680 option
->ui
= PPD_UI_BOOLEAN
;
682 option
->ui
= PPD_UI_PICKONE
;
684 for (j
= 0; j
< ppd
->num_attrs
; j
++)
685 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
686 !strcmp(ppd
->attrs
[j
]->name
+ 7, keyword
) &&
687 ppd
->attrs
[j
]->value
)
689 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
690 option
->keyword
, ppd
->attrs
[j
]->value
));
691 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
692 sizeof(option
->defchoice
));
696 if (!strcmp(keyword
, "PageSize"))
697 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
698 else if (!strcmp(keyword
, "MediaType"))
699 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
700 else if (!strcmp(keyword
, "InputSlot"))
701 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
702 else if (!strcmp(keyword
, "ColorModel"))
703 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
704 else if (!strcmp(keyword
, "Resolution"))
705 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
707 strlcpy(option
->text
, keyword
, sizeof(option
->text
));
711 if (!strcmp(keyword
, "LanguageLevel"))
712 ppd
->language_level
= atoi(string
);
713 else if (!strcmp(keyword
, "LanguageEncoding"))
714 ppd
->lang_encoding
= string
;
715 else if (!strcmp(keyword
, "LanguageVersion"))
716 ppd
->lang_version
= string
;
717 else if (!strcmp(keyword
, "Manufacturer"))
718 ppd
->manufacturer
= string
;
719 else if (!strcmp(keyword
, "ModelName"))
720 ppd
->modelname
= string
;
721 else if (!strcmp(keyword
, "Protocols"))
722 ppd
->protocols
= string
;
723 else if (!strcmp(keyword
, "PCFileName"))
724 ppd
->pcfilename
= string
;
725 else if (!strcmp(keyword
, "NickName"))
726 ppd
->nickname
= string
;
727 else if (!strcmp(keyword
, "Product"))
728 ppd
->product
= string
;
729 else if (!strcmp(keyword
, "ShortNickName"))
730 ppd
->shortnickname
= string
;
731 else if (!strcmp(keyword
, "TTRasterizer"))
732 ppd
->ttrasterizer
= string
;
733 else if (!strcmp(keyword
, "JCLBegin"))
735 ppd
->jcl_begin
= strdup(string
);
736 ppd_decode(ppd
->jcl_begin
); /* Decode quoted string */
738 else if (!strcmp(keyword
, "JCLEnd"))
740 ppd
->jcl_end
= strdup(string
);
741 ppd_decode(ppd
->jcl_end
); /* Decode quoted string */
743 else if (!strcmp(keyword
, "JCLToPSInterpreter"))
745 ppd
->jcl_ps
= strdup(string
);
746 ppd_decode(ppd
->jcl_ps
); /* Decode quoted string */
748 else if (!strcmp(keyword
, "AccurateScreensSupport"))
749 ppd
->accurate_screens
= !strcmp(string
, "True");
750 else if (!strcmp(keyword
, "ColorDevice"))
751 ppd
->color_device
= !strcmp(string
, "True");
752 else if (!strcmp(keyword
, "ContoneOnly"))
753 ppd
->contone_only
= !strcmp(string
, "True");
754 else if (!strcmp(keyword
, "cupsFlipDuplex"))
755 ppd
->flip_duplex
= !strcmp(string
, "True");
756 else if (!strcmp(keyword
, "cupsManualCopies"))
757 ppd
->manual_copies
= !strcmp(string
, "True");
758 else if (!strcmp(keyword
, "cupsModelNumber"))
759 ppd
->model_number
= atoi(string
);
760 else if (!strcmp(keyword
, "cupsColorProfile"))
762 if (ppd
->num_profiles
== 0)
763 profile
= malloc(sizeof(ppd_profile_t
));
765 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
766 (ppd
->num_profiles
+ 1));
768 ppd
->profiles
= profile
;
769 profile
+= ppd
->num_profiles
;
770 ppd
->num_profiles
++;
772 memset(profile
, 0, sizeof(ppd_profile_t
));
773 strlcpy(profile
->resolution
, name
, sizeof(profile
->resolution
));
774 strlcpy(profile
->media_type
, text
, sizeof(profile
->media_type
));
775 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
777 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
778 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
779 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
780 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
781 profile
->matrix
[2] + 2);
783 else if (!strcmp(keyword
, "cupsFilter"))
785 if (ppd
->num_filters
== 0)
786 filter
= malloc(sizeof(char *));
788 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
794 cg
->ppd_status
= PPD_ALLOC_ERROR
;
799 ppd
->filters
= filter
;
800 filter
+= ppd
->num_filters
;
804 * Copy filter string and prevent it from being freed below...
810 else if (!strcmp(keyword
, "Throughput"))
811 ppd
->throughput
= atoi(string
);
812 else if (!strcmp(keyword
, "Font"))
815 * Add this font to the list of available fonts...
818 if (ppd
->num_fonts
== 0)
819 tempfonts
= (char **)malloc(sizeof(char *));
821 tempfonts
= (char **)realloc(ppd
->fonts
,
822 sizeof(char *) * (ppd
->num_fonts
+ 1));
824 if (tempfonts
== NULL
)
826 cg
->ppd_status
= PPD_ALLOC_ERROR
;
831 ppd
->fonts
= tempfonts
;
832 ppd
->fonts
[ppd
->num_fonts
] = strdup(name
);
835 else if (!strcmp(keyword
, "ParamCustomPageSize"))
837 if (!strcmp(name
, "Width"))
838 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
839 ppd
->custom_max
+ 0);
840 else if (!strcmp(name
, "Height"))
841 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
842 ppd
->custom_max
+ 1);
844 else if (!strcmp(keyword
, "HWMargins"))
845 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
846 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
847 ppd
->custom_margins
+ 3);
848 else if (!strcmp(keyword
, "CustomPageSize") &&
849 !strcmp(name
, "True"))
851 DEBUG_puts("Processing CustomPageSize...");
853 if (!ppd
->variable_sizes
)
855 ppd
->variable_sizes
= 1;
858 * Add a "Custom" page size entry...
861 ppd_add_size(ppd
, "Custom");
864 * Add a "Custom" page size option...
867 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
872 DEBUG_puts("PageSize option not found for CustomPageSize...");
874 if ((gtemp
= ppd_get_group(ppd
, "General", _("General"), cg
)) == NULL
)
876 DEBUG_puts("Unable to get general group!");
881 if ((option
= ppd_get_option(gtemp
, "PageSize")) == NULL
)
883 DEBUG_puts("Unable to get PageSize option!");
885 cg
->ppd_status
= PPD_ALLOC_ERROR
;
891 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
893 DEBUG_puts("Unable to add Custom choice!");
895 cg
->ppd_status
= PPD_ALLOC_ERROR
;
900 strlcpy(choice
->text
, _("Variable"), sizeof(choice
->text
));
904 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
906 DEBUG_puts("Unable to find PageSize option!");
908 cg
->ppd_status
= PPD_INTERNAL_ERROR
;
913 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
915 DEBUG_puts("Unable to find Custom choice!");
917 cg
->ppd_status
= PPD_INTERNAL_ERROR
;
922 choice
->code
= string
;
924 string
= NULL
; /* Don't add as an attribute below */
926 else if (!strcmp(keyword
, "LandscapeOrientation"))
928 if (!strcmp(string
, "Minus90"))
929 ppd
->landscape
= -90;
930 else if (!strcmp(string
, "Plus90"))
933 else if (!strcmp(keyword
, "Emulators"))
935 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
936 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
943 ppd
->num_emulations
= count
;
944 ppd
->emulations
= calloc(count
, sizeof(ppd_emul_t
));
946 for (i
= 0, sptr
= string
; i
< count
; i
++)
948 for (nameptr
= ppd
->emulations
[i
].name
;
949 *sptr
!= '\0' && *sptr
!= ' ';
951 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
960 else if (!strncmp(keyword
, "StartEmulator_", 14))
964 for (i
= 0; i
< ppd
->num_emulations
; i
++)
965 if (!strcmp(keyword
+ 14, ppd
->emulations
[i
].name
))
967 ppd
->emulations
[i
].start
= string
;
971 else if (!strncmp(keyword
, "StopEmulator_", 13))
975 for (i
= 0; i
< ppd
->num_emulations
; i
++)
976 if (!strcmp(keyword
+ 13, ppd
->emulations
[i
].name
))
978 ppd
->emulations
[i
].stop
= string
;
982 else if (!strcmp(keyword
, "JobPatchFile"))
984 if (ppd
->patches
== NULL
)
985 ppd
->patches
= strdup(string
);
988 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
992 cg
->ppd_status
= PPD_ALLOC_ERROR
;
999 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
1002 else if (!strcmp(keyword
, "OpenUI"))
1005 * Don't allow nesting of options...
1008 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1010 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1016 * Add an option record to the current sub-group, group, or file...
1020 _cups_strcpy(name
, name
+ 1); /* Eliminate leading asterisk */
1022 for (i
= (int)strlen(name
) - 1; i
> 0 && isspace(name
[i
] & 255); i
--)
1023 name
[i
] = '\0'; /* Eliminate trailing spaces */
1025 DEBUG_printf(("OpenUI of %s in group %s...\n", name
,
1026 group
? group
->text
: "(null)"));
1028 if (subgroup
!= NULL
)
1029 option
= ppd_get_option(subgroup
, name
);
1030 else if (group
== NULL
)
1032 if (strcmp(name
, "Collate") && strcmp(name
, "Duplex") &&
1033 strcmp(name
, "InputSlot") && strcmp(name
, "ManualFeed") &&
1034 strcmp(name
, "MediaType") && strcmp(name
, "MediaColor") &&
1035 strcmp(name
, "MediaWeight") && strcmp(name
, "OutputBin") &&
1036 strcmp(name
, "OutputMode") && strcmp(name
, "OutputOrder") &&
1037 strcmp(name
, "PageSize") && strcmp(name
, "PageRegion"))
1038 group
= ppd_get_group(ppd
, "Extra", _("Extra"), cg
);
1040 group
= ppd_get_group(ppd
, "General", _("General"), cg
);
1045 DEBUG_printf(("Adding to group %s...\n", group
->text
));
1046 option
= ppd_get_option(group
, name
);
1050 option
= ppd_get_option(group
, name
);
1054 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1060 * Now fill in the initial information for the option...
1063 if (string
&& !strcmp(string
, "PickMany"))
1064 option
->ui
= PPD_UI_PICKMANY
;
1065 else if (string
&& !strcmp(string
, "Boolean"))
1066 option
->ui
= PPD_UI_BOOLEAN
;
1067 else if (string
&& !strcmp(string
, "PickOne"))
1068 option
->ui
= PPD_UI_PICKONE
;
1069 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1071 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1076 option
->ui
= PPD_UI_PICKONE
;
1078 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1079 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1080 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1081 ppd
->attrs
[j
]->value
)
1083 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1084 option
->keyword
, ppd
->attrs
[j
]->value
));
1085 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1086 sizeof(option
->defchoice
));
1091 strlcpy(option
->text
, text
, sizeof(option
->text
));
1094 if (!strcmp(name
, "PageSize"))
1095 strlcpy(option
->text
, _("Media Size"), sizeof(option
->text
));
1096 else if (!strcmp(name
, "MediaType"))
1097 strlcpy(option
->text
, _("Media Type"), sizeof(option
->text
));
1098 else if (!strcmp(name
, "InputSlot"))
1099 strlcpy(option
->text
, _("Media Source"), sizeof(option
->text
));
1100 else if (!strcmp(name
, "ColorModel"))
1101 strlcpy(option
->text
, _("Output Mode"), sizeof(option
->text
));
1102 else if (!strcmp(name
, "Resolution"))
1103 strlcpy(option
->text
, _("Resolution"), sizeof(option
->text
));
1105 strlcpy(option
->text
, name
, sizeof(option
->text
));
1108 option
->section
= PPD_ORDER_ANY
;
1113 else if (!strcmp(keyword
, "JCLOpenUI"))
1116 * Don't allow nesting of options...
1119 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1121 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1127 * Find the JCL group, and add if needed...
1130 group
= ppd_get_group(ppd
, "JCL", "JCL", cg
);
1136 * Add an option record to the current JCLs...
1140 _cups_strcpy(name
, name
+ 1);
1142 option
= ppd_get_option(group
, name
);
1146 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1152 * Now fill in the initial information for the option...
1155 if (string
&& !strcmp(string
, "PickMany"))
1156 option
->ui
= PPD_UI_PICKMANY
;
1157 else if (string
&& !strcmp(string
, "Boolean"))
1158 option
->ui
= PPD_UI_BOOLEAN
;
1159 else if (string
&& !strcmp(string
, "PickOne"))
1160 option
->ui
= PPD_UI_PICKONE
;
1163 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1168 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1169 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1170 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1171 ppd
->attrs
[j
]->value
)
1173 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1174 option
->keyword
, ppd
->attrs
[j
]->value
));
1175 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1176 sizeof(option
->defchoice
));
1180 strlcpy(option
->text
, text
, sizeof(option
->text
));
1182 option
->section
= PPD_ORDER_JCL
;
1188 else if (!strcmp(keyword
, "CloseUI") || !strcmp(keyword
, "JCLCloseUI"))
1195 else if (!strcmp(keyword
, "OpenGroup"))
1198 * Open a new group...
1203 cg
->ppd_status
= PPD_NESTED_OPEN_GROUP
;
1210 cg
->ppd_status
= PPD_BAD_OPEN_GROUP
;
1216 * Separate the group name from the text (name/text)...
1219 if ((sptr
= strchr(string
, '/')) != NULL
)
1225 * Fix up the text...
1231 * Find/add the group...
1234 group
= ppd_get_group(ppd
, string
, sptr
, cg
);
1242 else if (!strcmp(keyword
, "CloseGroup"))
1249 else if (!strcmp(keyword
, "OrderDependency") ||
1250 !strcmp(keyword
, "NonUIOrderDependency"))
1252 if (sscanf(string
, "%f%40s%40s", &order
, name
, keyword
) != 3)
1254 cg
->ppd_status
= PPD_BAD_ORDER_DEPENDENCY
;
1259 if (keyword
[0] == '*')
1260 _cups_strcpy(keyword
, keyword
+ 1);
1262 if (!strcmp(name
, "ExitServer"))
1263 section
= PPD_ORDER_EXIT
;
1264 else if (!strcmp(name
, "Prolog"))
1265 section
= PPD_ORDER_PROLOG
;
1266 else if (!strcmp(name
, "DocumentSetup"))
1267 section
= PPD_ORDER_DOCUMENT
;
1268 else if (!strcmp(name
, "PageSetup"))
1269 section
= PPD_ORDER_PAGE
;
1270 else if (!strcmp(name
, "JCLSetup"))
1271 section
= PPD_ORDER_JCL
;
1273 section
= PPD_ORDER_ANY
;
1281 * Only valid for Non-UI options...
1284 for (i
= ppd
->num_groups
, gtemp
= ppd
->groups
; i
> 0; i
--, gtemp
++)
1285 if (gtemp
->text
[0] == '\0')
1289 for (i
= 0; i
< gtemp
->num_options
; i
++)
1290 if (!strcmp(keyword
, gtemp
->options
[i
].keyword
))
1292 gtemp
->options
[i
].section
= section
;
1293 gtemp
->options
[i
].order
= order
;
1299 option
->section
= section
;
1300 option
->order
= order
;
1306 else if (!strncmp(keyword
, "Default", 7))
1312 * Drop UI text, if any, from value...
1315 if (strchr(string
, '/') != NULL
)
1316 *strchr(string
, '/') = '\0';
1319 * Assign the default value as appropriate...
1322 if (!strcmp(keyword
, "DefaultColorSpace"))
1325 * Set default colorspace...
1328 if (!strcmp(string
, "CMY"))
1329 ppd
->colorspace
= PPD_CS_CMY
;
1330 else if (!strcmp(string
, "CMYK"))
1331 ppd
->colorspace
= PPD_CS_CMYK
;
1332 else if (!strcmp(string
, "RGB"))
1333 ppd
->colorspace
= PPD_CS_RGB
;
1334 else if (!strcmp(string
, "RGBK"))
1335 ppd
->colorspace
= PPD_CS_RGBK
;
1336 else if (!strcmp(string
, "N"))
1337 ppd
->colorspace
= PPD_CS_N
;
1339 ppd
->colorspace
= PPD_CS_GRAY
;
1341 else if (option
&& !strcmp(keyword
+ 7, option
->keyword
))
1344 * Set the default as part of the current option...
1347 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1349 strlcpy(option
->defchoice
, string
, sizeof(option
->defchoice
));
1351 DEBUG_printf(("%s is now %s...\n", keyword
, option
->defchoice
));
1356 * Lookup option and set if it has been defined...
1359 ppd_option_t
*toption
; /* Temporary option */
1362 if ((toption
= ppdFindOption(ppd
, keyword
+ 7)) != NULL
)
1364 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1365 strlcpy(toption
->defchoice
, string
, sizeof(toption
->defchoice
));
1369 else if (!strcmp(keyword
, "UIConstraints") ||
1370 !strcmp(keyword
, "NonUIConstraints"))
1372 if (ppd
->num_consts
== 0)
1373 constraint
= calloc(1, sizeof(ppd_const_t
));
1375 constraint
= realloc(ppd
->consts
,
1376 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1378 if (constraint
== NULL
)
1380 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1385 ppd
->consts
= constraint
;
1386 constraint
+= ppd
->num_consts
;
1389 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1390 constraint
->choice1
, constraint
->option2
,
1391 constraint
->choice2
))
1393 case 0 : /* Error */
1394 case 1 : /* Error */
1395 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1398 case 2 : /* Two options... */
1400 * The following strcpy's are safe, as optionN and
1401 * choiceN are all the same size (size defined by PPD spec...)
1404 if (constraint
->option1
[0] == '*')
1405 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1407 if (constraint
->choice1
[0] == '*')
1408 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1410 _cups_strcpy(constraint
->option2
, constraint
->choice1
);
1412 constraint
->choice1
[0] = '\0';
1413 constraint
->choice2
[0] = '\0';
1416 case 3 : /* Two options, one choice... */
1418 * The following _cups_strcpy's are safe, as optionN and
1419 * choiceN are all the same size (size defined by PPD spec...)
1422 if (constraint
->option1
[0] == '*')
1423 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1425 if (constraint
->choice1
[0] == '*')
1427 _cups_strcpy(constraint
->choice2
, constraint
->option2
);
1428 _cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1429 constraint
->choice1
[0] = '\0';
1433 if (constraint
->option2
[0] == '*')
1434 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1436 constraint
->choice2
[0] = '\0';
1440 case 4 : /* Two options, two choices... */
1441 if (constraint
->option1
[0] == '*')
1442 _cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1444 if (constraint
->option2
[0] == '*')
1445 _cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1452 else if (!strcmp(keyword
, "PaperDimension"))
1454 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1455 size
= ppd_add_size(ppd
, name
);
1460 * Unable to add or find size!
1463 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1468 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1473 else if (!strcmp(keyword
, "ImageableArea"))
1475 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1476 size
= ppd_add_size(ppd
, name
);
1481 * Unable to add or find size!
1484 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1489 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1490 &(size
->right
), &(size
->top
));
1495 else if (option
!= NULL
&&
1496 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1497 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
) &&
1498 !strcmp(keyword
, option
->keyword
))
1500 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1502 if (!strcmp(keyword
, "PageSize"))
1505 * Add a page size...
1508 if (ppdPageSize(ppd
, name
) == NULL
)
1509 ppd_add_size(ppd
, name
);
1513 * Add the option choice...
1516 choice
= ppd_add_choice(option
, name
);
1518 if (mask
& PPD_TEXT
)
1519 strlcpy(choice
->text
, text
, sizeof(choice
->text
));
1520 else if (!strcmp(name
, "True"))
1521 strcpy(choice
->text
, _("Yes"));
1522 else if (!strcmp(name
, "False"))
1523 strcpy(choice
->text
, _("No"));
1525 strlcpy(choice
->text
, name
, sizeof(choice
->text
));
1527 if (option
->section
== PPD_ORDER_JCL
)
1528 ppd_decode(string
); /* Decode quoted string */
1530 choice
->code
= string
;
1531 string
= NULL
; /* Don't add as an attribute below */
1534 else if (strcmp(keyword
, "cupsUIType") == 0 &&
1535 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1539 * Define an extended option value type...
1542 extopt
= ppd_get_extoption(ppd
, name
);
1544 if (strcmp(string
, "Text") == 0)
1545 option
->ui
= PPD_UI_CUPS_TEXT
;
1546 else if (strcmp(string
, "Integer") == 0)
1548 option
->ui
= PPD_UI_CUPS_INTEGER
;
1549 extopt
->defval
.integer
= 0;
1550 extopt
->minval
.integer
= 0;
1551 extopt
->maxval
.integer
= 100;
1553 else if (strcmp(string
, "Real") == 0)
1555 option
->ui
= PPD_UI_CUPS_REAL
;
1556 extopt
->defval
.real
= 0.0;
1557 extopt
->minval
.real
= 0.0;
1558 extopt
->maxval
.real
= 1.0;
1560 else if (strcmp(string
, "Gamma") == 0)
1562 option
->ui
= PPD_UI_CUPS_GAMMA
;
1563 extopt
->defval
.gamma
= 1.0;
1564 extopt
->minval
.gamma
= 1.0;
1565 extopt
->maxval
.gamma
= 10.0;
1567 else if (strcmp(string
, "Curve") == 0)
1569 option
->ui
= PPD_UI_CUPS_CURVE
;
1570 extopt
->defval
.curve
.start
= 0.0;
1571 extopt
->defval
.curve
.end
= 0.0;
1572 extopt
->defval
.curve
.gamma
= 1.0;
1573 extopt
->minval
.curve
.start
= 0.0;
1574 extopt
->minval
.curve
.end
= 0.0;
1575 extopt
->minval
.curve
.gamma
= 1.0;
1576 extopt
->maxval
.curve
.start
= 1.0;
1577 extopt
->maxval
.curve
.end
= 1.0;
1578 extopt
->maxval
.curve
.gamma
= 10.0;
1580 else if (strcmp(string
, "IntegerArray") == 0)
1582 option
->ui
= PPD_UI_CUPS_INTEGER_ARRAY
;
1583 extopt
->defval
.integer_array
.num_elements
= 2;
1584 extopt
->minval
.integer_array
.num_elements
= 2;
1585 extopt
->maxval
.integer_array
.num_elements
= 16;
1587 else if (strcmp(string
, "RealArray") == 0)
1589 option
->ui
= PPD_UI_CUPS_REAL_ARRAY
;
1590 extopt
->defval
.real_array
.num_elements
= 2;
1591 extopt
->minval
.real_array
.num_elements
= 2;
1592 extopt
->maxval
.real_array
.num_elements
= 16;
1595 else if (strcmp(keyword
, "cupsUIDefault") == 0 &&
1596 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1600 * Define an extended option minimum value...
1603 extopt
= ppd_get_extoption(ppd
, name
);
1607 case PPD_UI_CUPS_INTEGER
:
1608 sscanf(string
, "%d", &(extopt
->defval
.integer
));
1611 case PPD_UI_CUPS_REAL
:
1612 sscanf(string
, "%f", &(extopt
->defval
.real
));
1615 case PPD_UI_CUPS_GAMMA
:
1616 sscanf(string
, "%f", &(extopt
->defval
.gamma
));
1619 case PPD_UI_CUPS_CURVE
:
1620 sscanf(string
, "%f%f%f", &(extopt
->defval
.curve
.start
),
1621 &(extopt
->defval
.curve
.end
),
1622 &(extopt
->defval
.curve
.gamma
));
1625 case PPD_UI_CUPS_INTEGER_ARRAY
:
1626 extopt
->defval
.integer_array
.elements
= calloc(1, sizeof(int));
1627 sscanf(string
, "%d%d", &(extopt
->defval
.integer_array
.num_elements
),
1628 extopt
->defval
.integer_array
.elements
);
1631 case PPD_UI_CUPS_REAL_ARRAY
:
1632 extopt
->defval
.real_array
.elements
= calloc(1, sizeof(float));
1633 sscanf(string
, "%d%f", &(extopt
->defval
.real_array
.num_elements
),
1634 extopt
->defval
.real_array
.elements
);
1641 else if (strcmp(keyword
, "cupsUIMinimum") == 0 &&
1642 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1646 * Define an extended option minimum value...
1649 extopt
= ppd_get_extoption(ppd
, name
);
1653 case PPD_UI_CUPS_INTEGER
:
1654 sscanf(string
, "%d", &(extopt
->minval
.integer
));
1657 case PPD_UI_CUPS_REAL
:
1658 sscanf(string
, "%f", &(extopt
->minval
.real
));
1661 case PPD_UI_CUPS_GAMMA
:
1662 sscanf(string
, "%f", &(extopt
->minval
.gamma
));
1665 case PPD_UI_CUPS_CURVE
:
1666 sscanf(string
, "%f%f%f", &(extopt
->minval
.curve
.start
),
1667 &(extopt
->minval
.curve
.end
),
1668 &(extopt
->minval
.curve
.gamma
));
1671 case PPD_UI_CUPS_INTEGER_ARRAY
:
1672 extopt
->minval
.integer_array
.elements
= calloc(1, sizeof(int));
1673 sscanf(string
, "%d%d", &(extopt
->minval
.integer_array
.num_elements
),
1674 extopt
->minval
.integer_array
.elements
);
1677 case PPD_UI_CUPS_REAL_ARRAY
:
1678 extopt
->minval
.real_array
.elements
= calloc(1, sizeof(float));
1679 sscanf(string
, "%d%f", &(extopt
->minval
.real_array
.num_elements
),
1680 extopt
->minval
.real_array
.elements
);
1687 else if (strcmp(keyword
, "cupsUIMaximum") == 0 &&
1688 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1692 * Define an extended option maximum value...
1695 extopt
= ppd_get_extoption(ppd
, name
);
1699 case PPD_UI_CUPS_INTEGER
:
1700 sscanf(string
, "%d", &(extopt
->maxval
.integer
));
1703 case PPD_UI_CUPS_REAL
:
1704 sscanf(string
, "%f", &(extopt
->maxval
.real
));
1707 case PPD_UI_CUPS_GAMMA
:
1708 sscanf(string
, "%f", &(extopt
->maxval
.gamma
));
1711 case PPD_UI_CUPS_CURVE
:
1712 sscanf(string
, "%f%f%f", &(extopt
->maxval
.curve
.start
),
1713 &(extopt
->maxval
.curve
.end
),
1714 &(extopt
->maxval
.curve
.gamma
));
1717 case PPD_UI_CUPS_INTEGER_ARRAY
:
1718 extopt
->maxval
.integer_array
.elements
= calloc(1, sizeof(int));
1719 sscanf(string
, "%d%d", &(extopt
->maxval
.integer_array
.num_elements
),
1720 extopt
->maxval
.integer_array
.elements
);
1723 case PPD_UI_CUPS_REAL_ARRAY
:
1724 extopt
->maxval
.real_array
.elements
= calloc(1, sizeof(float));
1725 sscanf(string
, "%d%f", &(extopt
->maxval
.real_array
.num_elements
),
1726 extopt
->maxval
.real_array
.elements
);
1733 else if (strcmp(keyword
, "cupsUICommand") == 0 &&
1734 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1738 * Define an extended option command...
1741 extopt
= ppd_get_extoption(ppd
, name
);
1743 extopt
->command
= string
;
1749 * Add remaining lines with keywords and string values as attributes...
1753 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
))
1754 ppd_add_attr(ppd
, keyword
, name
, text
, string
);
1762 * Reset language preferences...
1765 cupsLangFree(language
);
1768 _cupsRestoreLocale(LC_NUMERIC
, oldlocale
);
1770 _cupsRestoreLocale(LC_ALL
, oldlocale
);
1771 #endif /* LC_NUMERIC */
1775 printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp
));
1778 if (cg
->ppd_status
!= PPD_OK
)
1781 * Had an error reading the PPD file, cannot continue!
1791 * Make sure that all PPD files with an InputSlot option have an
1792 * "auto" choice that maps to no specific tray or media type.
1795 if ((option
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1797 for (i
= 0; i
< option
->num_choices
; i
++)
1798 if (option
->choices
[i
].code
== NULL
|| !option
->choices
[i
].code
[0] ||
1799 !strncasecmp(option
->choices
[i
].choice
, "Auto", 4))
1802 if (i
>= option
->num_choices
)
1805 * No "auto" input slot, add one...
1808 choice
= ppd_add_choice(option
, "Auto");
1810 strlcpy(choice
->text
, _("Auto"), sizeof(choice
->text
));
1811 choice
->code
= NULL
;
1814 #endif /* !__APPLE__ */
1817 * Set the option back-pointer for each choice...
1821 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1822 (int (*)(const void *, const void *))ppd_compare_groups
);
1823 #endif /* !__APPLE__ */
1825 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1830 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1831 (int (*)(const void *, const void *))ppd_compare_options
);
1832 #endif /* !__APPLE__ */
1834 for (j
= group
->num_options
, option
= group
->options
;
1838 for (k
= 0; k
< option
->num_choices
; k
++)
1839 option
->choices
[k
].option
= (void *)option
;
1843 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1844 (int (*)(const void *, const void *))ppd_compare_groups
);
1845 #endif /* !__APPLE__ */
1847 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1852 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1853 (int (*)(const void *, const void *))ppd_compare_options
);
1854 #endif /* !__APPLE__ */
1856 for (k
= group
->num_options
, option
= group
->options
;
1860 for (m
= 0; m
< option
->num_choices
; m
++)
1861 option
->choices
[m
].option
= (void *)option
;
1868 * Set the option pointers for all extended options...
1871 for (i
= 0; i
< ppd
->num_extended
; i
++)
1872 ppd
->extended
[i
]->option
= ppdFindOption(ppd
, ppd
->extended
[i
]->keyword
);
1876 * Sort the attributes...
1879 if (ppd
->num_attrs
> 1)
1880 qsort(ppd
->attrs
, ppd
->num_attrs
, sizeof(ppd_attr_t
*),
1881 (int (*)(const void *, const void *))_ppd_attr_compare
);
1884 * Return the PPD file structure...
1890 * Common exit point for errors to save code size...
1899 cupsLangFree(language
);
1902 _cupsRestoreLocale(LC_NUMERIC
, oldlocale
);
1904 _cupsRestoreLocale(LC_ALL
, oldlocale
);
1905 #endif /* LC_NUMERIC */
1912 * 'ppdOpenFd()' - Read a PPD file into memory.
1915 ppd_file_t
* /* O - PPD file record */
1916 ppdOpenFd(int fd
) /* I - File to read from */
1918 FILE *fp
; /* File pointer */
1919 ppd_file_t
*ppd
; /* PPD file record */
1920 _cups_globals_t
*cg
= _cupsGlobals();
1925 * Set the line number to 0...
1931 * Range check input...
1936 cg
->ppd_status
= PPD_NULL_FILE
;
1942 * Try to open the file and parse it...
1945 if ((fp
= fdopen(fd
, "r")) != NULL
)
1955 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
1964 * 'ppdOpenFile()' - Read a PPD file into memory.
1967 ppd_file_t
* /* O - PPD file record */
1968 ppdOpenFile(const char *filename
) /* I - File to read from */
1970 cups_file_t
*fp
; /* File pointer */
1971 ppd_file_t
*ppd
; /* PPD file record */
1972 _cups_globals_t
*cg
= _cupsGlobals();
1977 * Set the line number to 0...
1983 * Range check input...
1986 if (filename
== NULL
)
1988 cg
->ppd_status
= PPD_NULL_FILE
;
1994 * Try to open the file and parse it...
1997 if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
2005 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
2014 * 'ppdSetConformance()' - Set the conformance level for PPD files.
2016 * @since CUPS 1.1.20@
2020 ppdSetConformance(ppd_conform_t c
) /* I - Conformance level */
2022 _cups_globals_t
*cg
= _cupsGlobals();
2026 cg
->ppd_conform
= c
;
2031 * 'ppd_add_attr()' - Add an attribute to the PPD data.
2034 static ppd_attr_t
* /* O - New attribute */
2035 ppd_add_attr(ppd_file_t
*ppd
, /* I - PPD file data */
2036 const char *name
, /* I - Attribute name */
2037 const char *spec
, /* I - Specifier string, if any */
2038 const char *text
, /* I - Text string, if any */
2039 const char *value
) /* I - Value of attribute */
2041 ppd_attr_t
**ptr
, /* New array */
2042 *temp
; /* New attribute */
2046 * Range check input...
2049 if (ppd
== NULL
|| name
== NULL
|| spec
== NULL
)
2053 * Allocate memory for the new attribute...
2056 if (ppd
->num_attrs
== 0)
2057 ptr
= malloc(sizeof(ppd_attr_t
*));
2059 ptr
= realloc(ppd
->attrs
, (ppd
->num_attrs
+ 1) * sizeof(ppd_attr_t
*));
2065 ptr
+= ppd
->num_attrs
;
2067 if ((temp
= calloc(1, sizeof(ppd_attr_t
))) == NULL
)
2078 strlcpy(temp
->name
, name
, sizeof(temp
->name
));
2079 strlcpy(temp
->spec
, spec
, sizeof(temp
->spec
));
2080 strlcpy(temp
->text
, text
, sizeof(temp
->text
));
2081 temp
->value
= (char *)value
;
2084 * Return the attribute...
2092 * 'ppd_add_choice()' - Add a choice to an option.
2095 static ppd_choice_t
* /* O - Named choice */
2096 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
2097 const char *name
) /* I - Name of choice */
2099 ppd_choice_t
*choice
; /* Choice */
2102 if (option
->num_choices
== 0)
2103 choice
= malloc(sizeof(ppd_choice_t
));
2105 choice
= realloc(option
->choices
,
2106 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
2111 option
->choices
= choice
;
2112 choice
+= option
->num_choices
;
2113 option
->num_choices
++;
2115 memset(choice
, 0, sizeof(ppd_choice_t
));
2116 strlcpy(choice
->choice
, name
, sizeof(choice
->choice
));
2123 * 'ppd_add_size()' - Add a page size.
2126 static ppd_size_t
* /* O - Named size */
2127 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
2128 const char *name
) /* I - Name of size */
2130 ppd_size_t
*size
; /* Size */
2133 if (ppd
->num_sizes
== 0)
2134 size
= malloc(sizeof(ppd_size_t
));
2136 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
2142 size
+= ppd
->num_sizes
;
2145 memset(size
, 0, sizeof(ppd_size_t
));
2146 strlcpy(size
->name
, name
, sizeof(size
->name
));
2154 * 'ppd_compare_groups()' - Compare two groups.
2157 static int /* O - Result of comparison */
2158 ppd_compare_groups(ppd_group_t
*g0
, /* I - First group */
2159 ppd_group_t
*g1
) /* I - Second group */
2161 return (strcasecmp(g0
->text
, g1
->text
));
2166 * 'ppd_compare_options()' - Compare two options.
2169 static int /* O - Result of comparison */
2170 ppd_compare_options(ppd_option_t
*o0
, /* I - First option */
2171 ppd_option_t
*o1
) /* I - Second option */
2173 return (strcasecmp(o0
->text
, o1
->text
));
2175 #endif /* !__APPLE__ */
2179 * 'ppd_decode()' - Decode a string value...
2182 static int /* O - Length of decoded string */
2183 ppd_decode(char *string
) /* I - String to decode */
2185 char *inptr
, /* Input pointer */
2186 *outptr
; /* Output pointer */
2192 while (*inptr
!= '\0')
2193 if (*inptr
== '<' && isxdigit(inptr
[1] & 255))
2196 * Convert hex to 8-bit values...
2200 while (isxdigit(*inptr
& 255))
2202 if (isalpha(*inptr
))
2203 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
2205 *outptr
= (*inptr
- '0') << 4;
2209 if (!isxdigit(*inptr
& 255))
2212 if (isalpha(*inptr
))
2213 *outptr
|= tolower(*inptr
) - 'a' + 10;
2215 *outptr
|= *inptr
- '0';
2221 while (*inptr
!= '>' && *inptr
!= '\0')
2223 while (*inptr
== '>')
2227 *outptr
++ = *inptr
++;
2231 return ((int)(outptr
- string
));
2236 * 'ppd_free_group()' - Free a single UI group.
2240 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
2242 int i
; /* Looping var */
2243 ppd_option_t
*option
; /* Current option */
2244 ppd_group_t
*subgroup
; /* Current sub-group */
2247 if (group
->num_options
> 0)
2249 for (i
= group
->num_options
, option
= group
->options
;
2252 ppd_free_option(option
);
2254 ppd_free(group
->options
);
2257 if (group
->num_subgroups
> 0)
2259 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
2262 ppd_free_group(subgroup
);
2264 ppd_free(group
->subgroups
);
2270 * 'ppd_free_option()' - Free a single option.
2274 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
2276 int i
; /* Looping var */
2277 ppd_choice_t
*choice
; /* Current choice */
2280 if (option
->num_choices
> 0)
2282 for (i
= option
->num_choices
, choice
= option
->choices
;
2286 ppd_free(choice
->code
);
2289 ppd_free(option
->choices
);
2296 * 'ppd_get_extoption()' - Get an extended option record.
2299 static ppd_ext_option_t
* /* O - Extended option... */
2300 ppd_get_extoption(ppd_file_t
*ppd
, /* I - PPD file */
2301 const char *name
) /* I - Name of option */
2303 ppd_ext_option_t
**temp
, /* New array pointer */
2304 *extopt
; /* New extended option */
2308 * See if the option already exists...
2311 if ((extopt
= ppdFindExtOption(ppd
, name
)) != NULL
)
2315 * Not found, so create the extended option record...
2318 if ((extopt
= calloc(1, sizeof(ppd_ext_option_t
))) == NULL
)
2321 strlcpy(extopt
->keyword
, name
, sizeof(extopt
->keyword
));
2324 * Add this record to the end of the array...
2327 if (ppd
->num_extended
== 0)
2328 temp
= malloc(sizeof(ppd_ext_option_t
*));
2330 temp
= realloc(ppd
->extended
, sizeof(ppd_ext_option_t
*) *
2331 (ppd
->num_extended
+ 1));
2339 ppd
->extended
= temp
;
2340 temp
[ppd
->num_extended
] = extopt
;
2342 ppd
->num_extended
++;
2345 * Return the new record...
2353 * 'ppd_get_extparam()' - Get an extended parameter record.
2356 static ppd_ext_param_t
* /* O - Extended option... */
2357 ppd_get_extparam(ppd_ext_option_t
*opt
, /* I - PPD file */
2358 const char *param
,/* I - Name of parameter */
2359 const char *text
) /* I - Human-readable text */
2361 ppd_ext_param_t
**temp
, /* New array pointer */
2362 *extparam
; /* New extended parameter */
2366 * See if the parameter already exists...
2369 if ((extparam
= ppdFindExtParam(opt
, param
)) != NULL
)
2373 * Not found, so create the extended parameter record...
2376 if ((extparam
= calloc(1, sizeof(ppd_ext_param_t
))) == NULL
)
2379 if ((extparam
->value
= calloc(4, sizeof(ppd_ext_value_t
))) == NULL
)
2385 extparam
->defval
= extparam
->value
+ 1;
2386 extparam
->minval
= extparam
->value
+ 2;
2387 extparam
->maxval
= extparam
->value
+ 3;
2389 strlcpy(extparam
->keyword
, param
, sizeof(extparam
->keyword
));
2390 strlcpy(extparam
->text
, text
, sizeof(extparam
->text
));
2393 * Add this record to the end of the array...
2396 if (opt
->num_params
== 0)
2397 temp
= malloc(sizeof(ppd_ext_param_t
*));
2399 temp
= realloc(opt
->params
, sizeof(ppd_ext_param_t
*) *
2400 (opt
->num_params
+ 1));
2409 temp
[opt
->num_params
] = extparam
;
2414 * Return the new record...
2423 * 'ppd_get_group()' - Find or create the named group as needed.
2426 static ppd_group_t
* /* O - Named group */
2427 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
2428 const char *name
, /* I - Name of group */
2429 const char *text
, /* I - Text for group */
2430 _cups_globals_t
*cg
) /* I - Global data */
2432 int i
; /* Looping var */
2433 ppd_group_t
*group
; /* Group */
2436 DEBUG_printf(("ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)\n",
2437 ppd
, name
, text
, cg
));
2439 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
2440 if (!strcmp(group
->name
, name
))
2445 DEBUG_printf(("Adding group %s...\n", name
));
2447 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&& strlen(text
) >= sizeof(group
->text
))
2449 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2454 if (ppd
->num_groups
== 0)
2455 group
= malloc(sizeof(ppd_group_t
));
2457 group
= realloc(ppd
->groups
,
2458 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
2462 cg
->ppd_status
= PPD_ALLOC_ERROR
;
2467 ppd
->groups
= group
;
2468 group
+= ppd
->num_groups
;
2471 memset(group
, 0, sizeof(ppd_group_t
));
2472 strlcpy(group
->name
, name
, sizeof(group
->name
));
2473 strlcpy(group
->text
, text
, sizeof(group
->text
));
2481 * 'ppd_get_option()' - Find or create the named option as needed.
2484 static ppd_option_t
* /* O - Named option */
2485 ppd_get_option(ppd_group_t
*group
, /* I - Group */
2486 const char *name
) /* I - Name of option */
2488 int i
; /* Looping var */
2489 ppd_option_t
*option
; /* Option */
2492 DEBUG_printf(("ppd_get_option(group=%p(\"%s\"), name=\"%s\")\n",
2493 group
, group
->name
, name
));
2495 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
2496 if (!strcmp(option
->keyword
, name
))
2501 if (group
->num_options
== 0)
2502 option
= malloc(sizeof(ppd_option_t
));
2504 option
= realloc(group
->options
,
2505 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
2510 group
->options
= option
;
2511 option
+= group
->num_options
;
2512 group
->num_options
++;
2514 memset(option
, 0, sizeof(ppd_option_t
));
2515 strlcpy(option
->keyword
, name
, sizeof(option
->keyword
));
2523 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2527 static int /* O - Bitmask of fields read */
2528 ppd_read(cups_file_t
*fp
, /* I - File to read from */
2529 char *keyword
, /* O - Keyword from line */
2530 char *option
, /* O - Option from line */
2531 char *text
, /* O - Human-readable text from line */
2532 char **string
, /* O - Code/string data */
2533 int ignoreblank
, /* I - Ignore blank lines? */
2534 _cups_globals_t
*cg
) /* I - Global data */
2536 int ch
, /* Character from file */
2537 col
, /* Column in line */
2538 colon
, /* Colon seen? */
2539 endquote
, /* Waiting for an end quote */
2540 mask
, /* Mask to be returned */
2541 startline
, /* Start line */
2542 textlen
; /* Length of text */
2543 char *keyptr
, /* Keyword pointer */
2544 *optptr
, /* Option pointer */
2545 *textptr
, /* Text pointer */
2546 *strptr
, /* Pointer into string */
2547 *lineptr
, /* Current position in line buffer */
2548 *line
; /* Line buffer */
2549 int linesize
; /* Current size of line buffer */
2552 * Range check everything...
2555 if (!fp
|| !keyword
|| !option
|| !text
|| !string
)
2559 * Now loop until we have a valid line...
2564 startline
= cg
->ppd_line
+ 1;
2566 line
= malloc(linesize
);
2581 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2583 if (lineptr
>= (line
+ linesize
- 1))
2586 * Expand the line buffer...
2589 char *temp
; /* Temporary line pointer */
2593 if (linesize
> 262144)
2596 * Don't allow lines longer than 256k!
2599 cg
->ppd_line
= startline
;
2600 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2607 temp
= realloc(line
, linesize
);
2610 cg
->ppd_line
= startline
;
2611 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2618 lineptr
= temp
+ (lineptr
- line
);
2622 if (ch
== '\r' || ch
== '\n')
2625 * Line feed or carriage return...
2634 * Check for a trailing line feed...
2637 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2640 cupsFileGetChar(fp
);
2643 if (lineptr
== line
&& ignoreblank
)
2644 continue; /* Skip blank lines */
2648 if (!endquote
) /* Continue for multi-line text */
2653 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2656 * Other control characters...
2659 cg
->ppd_line
= startline
;
2660 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2666 else if (ch
!= 0x1a)
2669 * Any other character...
2675 if (col
> (PPD_MAX_LINE
- 1))
2678 * Line is too long...
2681 cg
->ppd_line
= startline
;
2682 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2689 if (ch
== ':' && strncmp(line
, "*%", 2) != 0)
2692 if (ch
== '\"' && colon
)
2693 endquote
= !endquote
;
2700 * Didn't finish this quoted string...
2703 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2706 else if (ch
== '\r' || ch
== '\n')
2714 * Check for a trailing line feed...
2717 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2720 cupsFileGetChar(fp
);
2725 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2728 * Other control characters...
2731 cg
->ppd_line
= startline
;
2732 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2738 else if (ch
!= 0x1a)
2742 if (col
> (PPD_MAX_LINE
- 1))
2745 * Line is too long...
2748 cg
->ppd_line
= startline
;
2749 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2761 * Didn't finish this line...
2764 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2765 if (ch
== '\r' || ch
== '\n')
2768 * Line feed or carriage return...
2777 * Check for a trailing line feed...
2780 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2783 cupsFileGetChar(fp
);
2788 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2791 * Other control characters...
2794 cg
->ppd_line
= startline
;
2795 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2801 else if (ch
!= 0x1a)
2805 if (col
> (PPD_MAX_LINE
- 1))
2808 * Line is too long...
2811 cg
->ppd_line
= startline
;
2812 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2821 if (lineptr
> line
&& lineptr
[-1] == '\n')
2826 DEBUG_printf(("LINE = \"%s\"\n", line
));
2828 if (ch
== EOF
&& lineptr
== line
)
2846 if ((!line
[0] || /* Blank line */
2847 !strncmp(line
, "*%", 2) || /* Comment line */
2848 !strcmp(line
, "*End")) && /* End of multi-line string */
2849 ignoreblank
) /* Ignore these? */
2851 startline
= cg
->ppd_line
+ 1;
2855 if (!strcmp(line
, "*")) /* (Bad) comment line */
2857 if (cg
->ppd_conform
== PPD_CONFORM_RELAXED
)
2859 startline
= cg
->ppd_line
+ 1;
2864 cg
->ppd_line
= startline
;
2865 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2872 if (line
[0] != '*') /* All lines start with an asterisk */
2874 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2876 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
2882 * Allow lines consisting of just whitespace...
2885 for (lineptr
= line
; *lineptr
; lineptr
++)
2886 if (!isspace(*lineptr
& 255))
2891 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
2895 else if (ignoreblank
)
2910 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
& 255))
2912 if (*lineptr
<= ' ' || *lineptr
> 126 || *lineptr
== '/' ||
2913 (keyptr
- keyword
) >= (PPD_MAX_NAME
- 1))
2915 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2920 *keyptr
++ = *lineptr
++;
2925 if (!strcmp(keyword
, "End"))
2928 mask
|= PPD_KEYWORD
;
2930 /* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/
2932 if (isspace(*lineptr
& 255))
2935 * Get an option name...
2938 while (isspace(*lineptr
& 255))
2943 while (*lineptr
!= '\0' && !isspace(*lineptr
& 255) && *lineptr
!= ':' &&
2946 if (*lineptr
<= ' ' || *lineptr
> 126 ||
2947 (optptr
- option
) >= (PPD_MAX_NAME
- 1))
2949 cg
->ppd_status
= PPD_ILLEGAL_OPTION_KEYWORD
;
2954 *optptr
++ = *lineptr
++;
2959 if (isspace(*lineptr
& 255) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2961 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
2966 while (isspace(*lineptr
& 255))
2971 /* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/
2973 if (*lineptr
== '/')
2976 * Get human-readable text...
2983 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':')
2985 if (((unsigned char)*lineptr
< ' ' && *lineptr
!= '\t') ||
2986 (textptr
- text
) >= (PPD_MAX_LINE
- 1))
2988 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2993 *textptr
++ = *lineptr
++;
2997 textlen
= ppd_decode(text
);
2999 if (textlen
> PPD_MAX_TEXT
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3001 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3009 /* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/
3012 if (isspace(*lineptr
& 255) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3014 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3019 while (isspace(*lineptr
& 255))
3022 if (*lineptr
== ':')
3025 * Get string after triming leading and trailing whitespace...
3029 while (isspace(*lineptr
& 255))
3032 strptr
= lineptr
+ strlen(lineptr
) - 1;
3033 while (strptr
>= lineptr
&& isspace(*strptr
& 255))
3036 if (*strptr
== '\"')
3039 * Quoted string by itself...
3042 *string
= malloc(strlen(lineptr
) + 1);
3046 for (; *lineptr
!= '\0'; lineptr
++)
3047 if (*lineptr
!= '\"')
3048 *strptr
++ = *lineptr
;
3053 *string
= strdup(lineptr
);
3055 /* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/
3069 * End of "$Id: ppd.c 4910 2006-01-10 21:30:48Z mike $".