4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 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_fix() - Fix WinANSI characters in the range 0x80 to
52 * 0x9f to be valid ISO-8859-1 characters...
53 * ppd_free_group() - Free a single UI group.
54 * ppd_free_option() - Free a single option.
55 * ppd_get_extoption() - Get an extended option record.
56 * ppd_get_extparam() - Get an extended parameter record.
57 * ppd_get_group() - Find or create the named group as needed.
58 * ppd_get_option() - Find or create the named option as needed.
59 * ppd_read() - Read a line from a PPD file, skipping comment
64 * Include necessary headers.
76 #if defined(WIN32) || defined(__EMX__)
77 # define READ_BINARY "rb" /* Open a binary file for reading */
78 # define WRITE_BINARY "wb" /* Open a binary file for writing */
80 # define READ_BINARY "r" /* Open a binary file for reading */
81 # define WRITE_BINARY "w" /* Open a binary file for writing */
82 #endif /* WIN32 || __EMX__ */
84 #define ppd_free(p) if (p) free(p) /* Safe free macro */
86 #define PPD_KEYWORD 1 /* Line contained a keyword */
87 #define PPD_OPTION 2 /* Line contained an option name */
88 #define PPD_TEXT 4 /* Line contained human-readable text */
89 #define PPD_STRING 8 /* Line contained a string or code */
96 static ppd_attr_t
*ppd_add_attr(ppd_file_t
*ppd
, const char *name
,
97 const char *spec
, const char *text
,
99 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, const char *name
);
100 static ppd_size_t
*ppd_add_size(ppd_file_t
*ppd
, const char *name
);
102 static int ppd_compare_groups(ppd_group_t
*g0
, ppd_group_t
*g1
);
103 static int ppd_compare_options(ppd_option_t
*o0
, ppd_option_t
*o1
);
104 #endif /* !__APPLE__ */
105 static int ppd_decode(char *string
);
107 static void ppd_fix(char *string
);
110 #endif /* !__APPLE__ */
111 static void ppd_free_group(ppd_group_t
*group
);
112 static void ppd_free_option(ppd_option_t
*option
);
114 static ppd_ext_option_t
*ppd_get_extoption(ppd_file_t
*ppd
, const char *name
);
115 static ppd_ext_param_t
*ppd_get_extparam(ppd_ext_option_t
*opt
,
119 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, const char *name
,
120 const char *text
, cups_globals_t
*cg
);
121 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, const char *name
);
122 static int ppd_read(cups_file_t
*fp
, char *keyword
, char *option
,
123 char *text
, char **string
, int ignoreblank
,
128 * '_ppd_attr_compare()' - Compare two attributes.
131 int /* O - Result of comparison */
132 _ppd_attr_compare(ppd_attr_t
**a
, /* I - First attribute */
133 ppd_attr_t
**b
) /* I - Second attribute */
135 int ret
; /* Result of comparison */
138 if ((ret
= strcasecmp((*a
)->name
, (*b
)->name
)) != 0)
140 else if ((*a
)->spec
[0] && (*b
)->spec
[0])
141 return (strcasecmp((*a
)->spec
, (*b
)->spec
));
148 * 'ppdClose()' - Free all memory used by the PPD file.
152 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
154 int i
; /* Looping var */
155 ppd_emul_t
*emul
; /* Current emulation */
156 ppd_group_t
*group
; /* Current group */
157 char **font
; /* Current font */
158 char **filter
; /* Current filter */
159 ppd_attr_t
**attr
; /* Current attribute */
161 int j
; /* Looping var */
162 ppd_ext_option_t
**opt
; /* Current extended option */
163 ppd_ext_param_t
**param
; /* Current extended parameter */
168 * Range check the PPD file record...
175 * Free all strings at the top level...
178 ppd_free(ppd
->patches
);
179 ppd_free(ppd
->jcl_begin
);
180 ppd_free(ppd
->jcl_end
);
181 ppd_free(ppd
->jcl_ps
);
184 * Free any emulations...
187 if (ppd
->num_emulations
> 0)
189 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
191 ppd_free(emul
->start
);
192 ppd_free(emul
->stop
);
195 ppd_free(ppd
->emulations
);
199 * Free any UI groups, subgroups, and options...
202 if (ppd
->num_groups
> 0)
204 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
205 ppd_free_group(group
);
207 ppd_free(ppd
->groups
);
211 * Free any page sizes...
214 if (ppd
->num_sizes
> 0)
216 ppd_free(ppd
->sizes
);
220 * Free any constraints...
223 if (ppd
->num_consts
> 0)
225 ppd_free(ppd
->consts
);
229 * Free any filters...
232 if (ppd
->num_filters
> 0)
234 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
239 ppd_free(ppd
->filters
);
246 if (ppd
->num_fonts
> 0)
248 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
253 ppd_free(ppd
->fonts
);
257 * Free any profiles...
260 if (ppd
->num_profiles
> 0)
262 ppd_free(ppd
->profiles
);
266 * Free any attributes...
269 if (ppd
->num_attrs
> 0)
271 for (i
= ppd
->num_attrs
, attr
= ppd
->attrs
; i
> 0; i
--, attr
++)
273 ppd_free((*attr
)->value
);
277 ppd_free(ppd
->attrs
);
281 if (ppd
->num_extended
)
283 for (i
= ppd
->num_extended
, opt
= ppd
->extended
; i
> 0; i
--, opt
++)
285 ppd_free((*opt
)->code
);
287 for (j
= (*opt
)->num_params
, param
= (*opt
)->params
; j
> 0; j
--, param
++)
288 ppd_free((*param
)->value
);
290 ppd_free((*opt
)->params
);
293 ppd_free(ppd
->extended
);
298 * Free the whole record...
306 * 'ppdErrorString()' - Returns the text assocated with a status.
309 const char * /* O - Status string */
310 ppdErrorString(ppd_status_t status
) /* I - PPD status */
312 static const char * const messages
[] =/* Status messages */
315 "Unable to open PPD file",
316 "NULL PPD file pointer",
317 "Memory allocation error",
318 "Missing PPD-Adobe-4.x header",
319 "Missing value string",
322 "OpenGroup without a CloseGroup first",
323 "Bad OpenUI/JCLOpenUI",
324 "OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first",
325 "Bad OrderDependency",
327 "Missing asterisk in column 1",
328 "Line longer than the maximum allowed (255 characters)",
329 "Illegal control character",
330 "Illegal main keyword string",
331 "Illegal option keyword string",
332 "Illegal translation string",
333 "Illegal whitespace character"
337 if (status
< PPD_OK
|| status
> PPD_ILLEGAL_WHITESPACE
)
340 return (messages
[status
]);
345 * 'ppdLastError()' - Return the status from the last ppdOpen*().
348 ppd_status_t
/* O - Status code */
349 ppdLastError(int *line
) /* O - Line number */
351 cups_globals_t
*cg
= _cupsGlobals();
356 *line
= cg
->ppd_line
;
358 return (cg
->ppd_status
);
363 * 'ppdOpen()' - Read a PPD file into memory.
366 ppd_file_t
* /* O - PPD file record */
367 ppdOpen(FILE *fp
) /* I - File to read from */
369 ppd_file_t
*ppd
; /* PPD file record */
370 cups_file_t
*cf
; /* CUPS file */
374 * Reopen the stdio file as a CUPS file...
377 if ((cf
= cupsFileOpenFd(fileno(fp
), "r")) == NULL
)
381 * Load the PPD file using the newer API...
387 * Close the CUPS file and return the PPD...
397 * 'ppdOpen2()' - Read a PPD file into memory.
400 ppd_file_t
* /* O - PPD file record */
401 ppdOpen2(cups_file_t
*fp
) /* I - File to read from */
403 char *oldlocale
; /* Old locale settings */
404 int i
, j
, k
, m
; /* Looping vars */
405 int count
; /* Temporary count */
406 ppd_file_t
*ppd
; /* PPD file record */
407 ppd_group_t
*group
, /* Current group */
408 *subgroup
; /* Current sub-group */
409 ppd_option_t
*option
; /* Current option */
410 ppd_choice_t
*choice
; /* Current choice */
411 ppd_const_t
*constraint
; /* Current constraint */
412 ppd_size_t
*size
; /* Current page size */
413 int mask
; /* Line data mask */
414 char keyword
[PPD_MAX_NAME
],
415 /* Keyword from file */
417 /* Option from file */
419 /* Human-readable text from file */
420 *string
, /* Code/text from file */
421 *sptr
, /* Pointer into string */
422 *nameptr
, /* Pointer into name */
423 *temp
, /* Temporary string pointer */
424 **tempfonts
; /* Temporary fonts pointer */
425 float order
; /* Order dependency number */
426 ppd_section_t section
; /* Order dependency section */
427 ppd_profile_t
*profile
; /* Pointer to color profile */
428 char **filter
; /* Pointer to filter */
429 cups_lang_t
*language
; /* Default language */
430 int ui_keyword
; /* Is this line a UI keyword? */
431 cups_globals_t
*cg
= _cupsGlobals();
433 static const char * const ui_keywords
[] =
435 /* Boolean keywords */
445 /* PickOne keywords */
458 "JCLFrameBufferSize",
483 * Default to "OK" status...
486 cg
->ppd_status
= PPD_OK
;
490 * Range check input...
495 cg
->ppd_status
= PPD_NULL_FILE
;
500 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
503 mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 0, cg
);
505 DEBUG_printf(("mask=%x, keyword=\"%s\"...\n", mask
, keyword
));
508 strcmp(keyword
, "PPD-Adobe") != 0 ||
509 string
== NULL
|| string
[0] != '4')
512 * Either this is not a PPD file, or it is not a 4.x PPD file.
515 if (cg
->ppd_status
== PPD_OK
)
516 cg
->ppd_status
= PPD_MISSING_PPDADOBE4
;
523 DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword
, string
));
528 * Allocate memory for the PPD file record...
531 if ((ppd
= calloc(1, sizeof(ppd_file_t
))) == NULL
)
533 cg
->ppd_status
= PPD_ALLOC_ERROR
;
538 ppd
->language_level
= 1;
539 ppd
->color_device
= 0;
540 ppd
->colorspace
= PPD_CS_GRAY
;
541 ppd
->landscape
= -90;
544 * Get the default language for the user...
547 language
= cupsLangDefault();
550 oldlocale
= _cupsSaveLocale(LC_NUMERIC
, "C");
552 oldlocale
= _cupsSaveLocale(LC_ALL
, "C");
553 #endif /* LC_NUMERIC */
556 * Read lines from the PPD file and add them to the file record...
565 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 1, cg
)) != 0)
568 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
571 printf(", name = \"%s\"", name
);
574 printf(", text = \"%s\"", text
);
578 if (strlen(string
) > 40)
579 printf(", string = %p", string
);
581 printf(", string = \"%s\"", string
);
587 if (strcmp(keyword
, "CloseUI") && strcmp(keyword
, "CloseGroup") &&
588 strcmp(keyword
, "CloseSubGroup") && strncmp(keyword
, "Default", 7) &&
589 strcmp(keyword
, "JCLCloseUI") && strcmp(keyword
, "JCLOpenUI") &&
590 strcmp(keyword
, "OpenUI") && strcmp(keyword
, "OpenGroup") &&
591 strcmp(keyword
, "OpenSubGroup") && string
== NULL
)
594 * Need a string value!
597 cg
->ppd_status
= PPD_MISSING_VALUE
;
603 * Certain main keywords (as defined by the PPD spec) may be used
604 * without the usual OpenUI/CloseUI stuff. Presumably this is just
605 * so that Adobe wouldn't completely break compatibility with PPD
606 * files prior to v4.0 of the spec, but it is hopelessly
607 * inconsistent... Catch these main keywords and automatically
608 * create the corresponding option, as needed...
614 * Previous line was a UI keyword...
621 if (option
== NULL
&&
622 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
623 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
625 for (i
= 0; i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])); i
++)
626 if (!strcmp(keyword
, ui_keywords
[i
]))
629 if (i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])))
632 * Create the option in the appropriate group...
637 DEBUG_printf(("**** FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!\n",
642 if (strcmp(keyword
, "Collate") && strcmp(keyword
, "Duplex") &&
643 strcmp(keyword
, "InputSlot") && strcmp(keyword
, "ManualFeed") &&
644 strcmp(keyword
, "MediaType") && strcmp(keyword
, "MediaColor") &&
645 strcmp(keyword
, "MediaWeight") && strcmp(keyword
, "OutputBin") &&
646 strcmp(keyword
, "OutputMode") && strcmp(keyword
, "OutputOrder") &&
647 strcmp(keyword
, "PageSize") && strcmp(keyword
, "PageRegion"))
648 group
= ppd_get_group(ppd
, "Extra",
649 cupsLangString(language
, CUPS_MSG_EXTRA
), cg
);
651 group
= ppd_get_group(ppd
, "General",
652 cupsLangString(language
, CUPS_MSG_GENERAL
), cg
);
657 DEBUG_printf(("Adding to group %s...\n", group
->text
));
658 option
= ppd_get_option(group
, keyword
);
662 option
= ppd_get_option(group
, keyword
);
666 cg
->ppd_status
= PPD_ALLOC_ERROR
;
672 * Now fill in the initial information for the option...
675 if (!strncmp(keyword
, "JCL", 3))
676 option
->section
= PPD_ORDER_JCL
;
678 option
->section
= PPD_ORDER_ANY
;
680 option
->order
= 10.0f
;
683 option
->ui
= PPD_UI_BOOLEAN
;
685 option
->ui
= PPD_UI_PICKONE
;
687 for (j
= 0; j
< ppd
->num_attrs
; j
++)
688 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
689 !strcmp(ppd
->attrs
[j
]->name
+ 7, keyword
) &&
690 ppd
->attrs
[j
]->value
)
692 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
693 option
->keyword
, ppd
->attrs
[j
]->value
));
694 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
695 sizeof(option
->defchoice
));
699 if (strcmp(keyword
, "PageSize") == 0)
700 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
),
701 sizeof(option
->text
));
702 else if (strcmp(keyword
, "MediaType") == 0)
703 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
),
704 sizeof(option
->text
));
705 else if (strcmp(keyword
, "InputSlot") == 0)
706 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
),
707 sizeof(option
->text
));
708 else if (strcmp(keyword
, "ColorModel") == 0)
709 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_OUTPUT_MODE
),
710 sizeof(option
->text
));
711 else if (strcmp(keyword
, "Resolution") == 0)
712 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_RESOLUTION
),
713 sizeof(option
->text
));
715 strlcpy(option
->text
, keyword
, sizeof(option
->text
));
719 if (strcmp(keyword
, "LanguageLevel") == 0)
720 ppd
->language_level
= atoi(string
);
721 else if (strcmp(keyword
, "LanguageEncoding") == 0)
722 ppd
->lang_encoding
= string
;
723 else if (strcmp(keyword
, "LanguageVersion") == 0)
724 ppd
->lang_version
= string
;
725 else if (strcmp(keyword
, "Manufacturer") == 0)
726 ppd
->manufacturer
= string
;
727 else if (strcmp(keyword
, "ModelName") == 0)
728 ppd
->modelname
= string
;
729 else if (strcmp(keyword
, "Protocols") == 0)
730 ppd
->protocols
= string
;
731 else if (strcmp(keyword
, "PCFileName") == 0)
732 ppd
->pcfilename
= string
;
733 else if (strcmp(keyword
, "NickName") == 0)
734 ppd
->nickname
= string
;
735 else if (strcmp(keyword
, "Product") == 0)
736 ppd
->product
= string
;
737 else if (strcmp(keyword
, "ShortNickName") == 0)
738 ppd
->shortnickname
= string
;
739 else if (strcmp(keyword
, "TTRasterizer") == 0)
740 ppd
->ttrasterizer
= string
;
741 else if (strcmp(keyword
, "JCLBegin") == 0)
743 ppd
->jcl_begin
= strdup(string
);
744 ppd_decode(ppd
->jcl_begin
); /* Decode quoted string */
746 else if (strcmp(keyword
, "JCLEnd") == 0)
748 ppd
->jcl_end
= strdup(string
);
749 ppd_decode(ppd
->jcl_end
); /* Decode quoted string */
751 else if (strcmp(keyword
, "JCLToPSInterpreter") == 0)
753 ppd
->jcl_ps
= strdup(string
);
754 ppd_decode(ppd
->jcl_ps
); /* Decode quoted string */
756 else if (strcmp(keyword
, "AccurateScreensSupport") == 0)
757 ppd
->accurate_screens
= strcmp(string
, "True") == 0;
758 else if (strcmp(keyword
, "ColorDevice") == 0)
759 ppd
->color_device
= strcmp(string
, "True") == 0;
760 else if (strcmp(keyword
, "ContoneOnly") == 0)
761 ppd
->contone_only
= strcmp(string
, "True") == 0;
762 else if (strcmp(keyword
, "cupsFlipDuplex") == 0)
763 ppd
->flip_duplex
= strcmp(string
, "True") == 0;
764 else if (strcmp(keyword
, "cupsManualCopies") == 0)
765 ppd
->manual_copies
= strcmp(string
, "True") == 0;
766 else if (strcmp(keyword
, "cupsModelNumber") == 0)
767 ppd
->model_number
= atoi(string
);
768 else if (strcmp(keyword
, "cupsColorProfile") == 0)
770 if (ppd
->num_profiles
== 0)
771 profile
= malloc(sizeof(ppd_profile_t
));
773 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
774 (ppd
->num_profiles
+ 1));
776 ppd
->profiles
= profile
;
777 profile
+= ppd
->num_profiles
;
778 ppd
->num_profiles
++;
780 memset(profile
, 0, sizeof(ppd_profile_t
));
781 strlcpy(profile
->resolution
, name
, sizeof(profile
->resolution
));
782 strlcpy(profile
->media_type
, text
, sizeof(profile
->media_type
));
783 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
785 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
786 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
787 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
788 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
789 profile
->matrix
[2] + 2);
791 else if (strcmp(keyword
, "cupsFilter") == 0)
793 if (ppd
->num_filters
== 0)
794 filter
= malloc(sizeof(char *));
796 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
802 cg
->ppd_status
= PPD_ALLOC_ERROR
;
807 ppd
->filters
= filter
;
808 filter
+= ppd
->num_filters
;
812 * Copy filter string and prevent it from being freed below...
818 else if (strcmp(keyword
, "Throughput") == 0)
819 ppd
->throughput
= atoi(string
);
820 else if (strcmp(keyword
, "Font") == 0)
823 * Add this font to the list of available fonts...
826 if (ppd
->num_fonts
== 0)
827 tempfonts
= (char **)malloc(sizeof(char *));
829 tempfonts
= (char **)realloc(ppd
->fonts
,
830 sizeof(char *) * (ppd
->num_fonts
+ 1));
832 if (tempfonts
== NULL
)
834 cg
->ppd_status
= PPD_ALLOC_ERROR
;
839 ppd
->fonts
= tempfonts
;
840 ppd
->fonts
[ppd
->num_fonts
] = strdup(name
);
843 else if (strcmp(keyword
, "ParamCustomPageSize") == 0)
845 if (strcmp(name
, "Width") == 0)
846 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
847 ppd
->custom_max
+ 0);
848 else if (strcmp(name
, "Height") == 0)
849 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
850 ppd
->custom_max
+ 1);
852 else if (strcmp(keyword
, "HWMargins") == 0)
853 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
854 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
855 ppd
->custom_margins
+ 3);
856 else if (strcmp(keyword
, "CustomPageSize") == 0 &&
857 strcmp(name
, "True") == 0)
859 DEBUG_puts("Processing CustomPageSize...");
861 if (!ppd
->variable_sizes
)
863 ppd
->variable_sizes
= 1;
866 * Add a "Custom" page size entry...
869 ppd_add_size(ppd
, "Custom");
872 * Add a "Custom" page size option...
875 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
880 DEBUG_puts("PageSize option not found for CustomPageSize...");
882 if ((gtemp
= ppd_get_group(ppd
, "General",
883 cupsLangString(language
,
884 CUPS_MSG_GENERAL
), cg
)) == NULL
)
886 DEBUG_puts("Unable to get general group!");
891 if ((option
= ppd_get_option(gtemp
, "PageSize")) == NULL
)
893 DEBUG_puts("Unable to get PageSize option!");
895 cg
->ppd_status
= PPD_ALLOC_ERROR
;
901 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
903 DEBUG_puts("Unable to add Custom choice!");
905 cg
->ppd_status
= PPD_ALLOC_ERROR
;
910 strlcpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
),
911 sizeof(choice
->text
));
915 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
917 DEBUG_puts("Unable to find PageSize option!");
919 cg
->ppd_status
= PPD_INTERNAL_ERROR
;
924 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
926 DEBUG_puts("Unable to find Custom choice!");
928 cg
->ppd_status
= PPD_INTERNAL_ERROR
;
933 choice
->code
= string
;
935 string
= NULL
; /* Don't add as an attribute below */
937 else if (strcmp(keyword
, "LandscapeOrientation") == 0)
939 if (strcmp(string
, "Minus90") == 0)
940 ppd
->landscape
= -90;
941 else if (strcmp(string
, "Plus90") == 0)
944 else if (strcmp(keyword
, "Emulators") == 0)
946 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
947 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
954 ppd
->num_emulations
= count
;
955 ppd
->emulations
= calloc(count
, sizeof(ppd_emul_t
));
957 for (i
= 0, sptr
= string
; i
< count
; i
++)
959 for (nameptr
= ppd
->emulations
[i
].name
;
960 *sptr
!= '\0' && *sptr
!= ' ';
962 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
971 else if (strncmp(keyword
, "StartEmulator_", 14) == 0)
975 for (i
= 0; i
< ppd
->num_emulations
; i
++)
976 if (strcmp(keyword
+ 14, ppd
->emulations
[i
].name
) == 0)
978 ppd
->emulations
[i
].start
= string
;
982 else if (strncmp(keyword
, "StopEmulator_", 13) == 0)
986 for (i
= 0; i
< ppd
->num_emulations
; i
++)
987 if (strcmp(keyword
+ 13, ppd
->emulations
[i
].name
) == 0)
989 ppd
->emulations
[i
].stop
= string
;
993 else if (strcmp(keyword
, "JobPatchFile") == 0)
995 if (ppd
->patches
== NULL
)
996 ppd
->patches
= strdup(string
);
999 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
1000 strlen(string
) + 1);
1003 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1008 ppd
->patches
= temp
;
1010 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
1013 else if (strcmp(keyword
, "OpenUI") == 0)
1016 * Don't allow nesting of options...
1019 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1021 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1027 * Add an option record to the current sub-group, group, or file...
1031 cups_strcpy(name
, name
+ 1); /* Eliminate leading asterisk */
1033 for (i
= strlen(name
) - 1; i
> 0 && isspace(name
[i
] & 255); i
--)
1034 name
[i
] = '\0'; /* Eliminate trailing spaces */
1036 DEBUG_printf(("OpenUI of %s in group %s...\n", name
,
1037 group
? group
->text
: "(null)"));
1039 if (subgroup
!= NULL
)
1040 option
= ppd_get_option(subgroup
, name
);
1041 else if (group
== NULL
)
1043 if (strcmp(name
, "Collate") && strcmp(name
, "Duplex") &&
1044 strcmp(name
, "InputSlot") && strcmp(name
, "ManualFeed") &&
1045 strcmp(name
, "MediaType") && strcmp(name
, "MediaColor") &&
1046 strcmp(name
, "MediaWeight") && strcmp(name
, "OutputBin") &&
1047 strcmp(name
, "OutputMode") && strcmp(name
, "OutputOrder") &&
1048 strcmp(name
, "PageSize") && strcmp(name
, "PageRegion"))
1049 group
= ppd_get_group(ppd
, "Extra",
1050 cupsLangString(language
, CUPS_MSG_EXTRA
), cg
);
1052 group
= ppd_get_group(ppd
, "General",
1053 cupsLangString(language
, CUPS_MSG_GENERAL
), cg
);
1058 DEBUG_printf(("Adding to group %s...\n", group
->text
));
1059 option
= ppd_get_option(group
, name
);
1063 option
= ppd_get_option(group
, name
);
1067 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1073 * Now fill in the initial information for the option...
1076 if (string
&& strcmp(string
, "PickMany") == 0)
1077 option
->ui
= PPD_UI_PICKMANY
;
1078 else if (string
&& strcmp(string
, "Boolean") == 0)
1079 option
->ui
= PPD_UI_BOOLEAN
;
1080 else if (string
&& strcmp(string
, "PickOne") == 0)
1081 option
->ui
= PPD_UI_PICKONE
;
1082 else if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1084 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1089 option
->ui
= PPD_UI_PICKONE
;
1091 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1092 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1093 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1094 ppd
->attrs
[j
]->value
)
1096 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1097 option
->keyword
, ppd
->attrs
[j
]->value
));
1098 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1099 sizeof(option
->defchoice
));
1105 strlcpy(option
->text
, text
, sizeof(option
->text
));
1106 ppd_fix(option
->text
);
1110 if (strcmp(name
, "PageSize") == 0)
1111 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
),
1112 sizeof(option
->text
));
1113 else if (strcmp(name
, "MediaType") == 0)
1114 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
),
1115 sizeof(option
->text
));
1116 else if (strcmp(name
, "InputSlot") == 0)
1117 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
),
1118 sizeof(option
->text
));
1119 else if (strcmp(name
, "ColorModel") == 0)
1120 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_OUTPUT_MODE
),
1121 sizeof(option
->text
));
1122 else if (strcmp(name
, "Resolution") == 0)
1123 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_RESOLUTION
),
1124 sizeof(option
->text
));
1126 strlcpy(option
->text
, name
, sizeof(option
->text
));
1129 option
->section
= PPD_ORDER_ANY
;
1134 else if (strcmp(keyword
, "JCLOpenUI") == 0)
1137 * Don't allow nesting of options...
1140 if (option
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
1142 cg
->ppd_status
= PPD_NESTED_OPEN_UI
;
1148 * Find the JCL group, and add if needed...
1151 group
= ppd_get_group(ppd
, "JCL", "JCL", cg
);
1157 * Add an option record to the current JCLs...
1161 cups_strcpy(name
, name
+ 1);
1163 option
= ppd_get_option(group
, name
);
1167 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1173 * Now fill in the initial information for the option...
1176 if (string
&& strcmp(string
, "PickMany") == 0)
1177 option
->ui
= PPD_UI_PICKMANY
;
1178 else if (string
&& strcmp(string
, "Boolean") == 0)
1179 option
->ui
= PPD_UI_BOOLEAN
;
1180 else if (string
&& strcmp(string
, "PickOne") == 0)
1181 option
->ui
= PPD_UI_PICKONE
;
1184 cg
->ppd_status
= PPD_BAD_OPEN_UI
;
1189 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1190 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1191 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1192 ppd
->attrs
[j
]->value
)
1194 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1195 option
->keyword
, ppd
->attrs
[j
]->value
));
1196 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1197 sizeof(option
->defchoice
));
1201 strlcpy(option
->text
, text
, sizeof(option
->text
));
1203 option
->section
= PPD_ORDER_JCL
;
1209 else if (strcmp(keyword
, "CloseUI") == 0 ||
1210 strcmp(keyword
, "JCLCloseUI") == 0)
1217 else if (strcmp(keyword
, "OpenGroup") == 0)
1220 * Open a new group...
1225 cg
->ppd_status
= PPD_NESTED_OPEN_GROUP
;
1232 cg
->ppd_status
= PPD_BAD_OPEN_GROUP
;
1238 * Separate the group name from the text (name/text)...
1241 if ((sptr
= strchr(string
, '/')) != NULL
)
1247 * Fix up the text...
1254 * Find/add the group...
1257 group
= ppd_get_group(ppd
, string
, sptr
, cg
);
1265 else if (strcmp(keyword
, "CloseGroup") == 0)
1272 else if (strcmp(keyword
, "OrderDependency") == 0 ||
1273 strcmp(keyword
, "NonUIOrderDependency") == 0)
1275 if (sscanf(string
, "%f%40s%40s", &order
, name
, keyword
) != 3)
1277 cg
->ppd_status
= PPD_BAD_ORDER_DEPENDENCY
;
1282 if (keyword
[0] == '*')
1283 cups_strcpy(keyword
, keyword
+ 1);
1285 if (strcmp(name
, "ExitServer") == 0)
1286 section
= PPD_ORDER_EXIT
;
1287 else if (strcmp(name
, "Prolog") == 0)
1288 section
= PPD_ORDER_PROLOG
;
1289 else if (strcmp(name
, "DocumentSetup") == 0)
1290 section
= PPD_ORDER_DOCUMENT
;
1291 else if (strcmp(name
, "PageSetup") == 0)
1292 section
= PPD_ORDER_PAGE
;
1293 else if (strcmp(name
, "JCLSetup") == 0)
1294 section
= PPD_ORDER_JCL
;
1296 section
= PPD_ORDER_ANY
;
1304 * Only valid for Non-UI options...
1307 for (i
= ppd
->num_groups
, gtemp
= ppd
->groups
; i
> 0; i
--, gtemp
++)
1308 if (gtemp
->text
[0] == '\0')
1312 for (i
= 0; i
< gtemp
->num_options
; i
++)
1313 if (strcmp(keyword
, gtemp
->options
[i
].keyword
) == 0)
1315 gtemp
->options
[i
].section
= section
;
1316 gtemp
->options
[i
].order
= order
;
1322 option
->section
= section
;
1323 option
->order
= order
;
1329 else if (strncmp(keyword
, "Default", 7) == 0)
1335 * Drop UI text, if any, from value...
1338 if (strchr(string
, '/') != NULL
)
1339 *strchr(string
, '/') = '\0';
1342 * Assign the default value as appropriate...
1345 if (strcmp(keyword
, "DefaultColorSpace") == 0)
1348 * Set default colorspace...
1351 if (strcmp(string
, "CMY") == 0)
1352 ppd
->colorspace
= PPD_CS_CMY
;
1353 else if (strcmp(string
, "CMYK") == 0)
1354 ppd
->colorspace
= PPD_CS_CMYK
;
1355 else if (strcmp(string
, "RGB") == 0)
1356 ppd
->colorspace
= PPD_CS_RGB
;
1357 else if (strcmp(string
, "RGBK") == 0)
1358 ppd
->colorspace
= PPD_CS_RGBK
;
1359 else if (strcmp(string
, "N") == 0)
1360 ppd
->colorspace
= PPD_CS_N
;
1362 ppd
->colorspace
= PPD_CS_GRAY
;
1364 else if (option
&& strcmp(keyword
+ 7, option
->keyword
) == 0)
1367 * Set the default as part of the current option...
1370 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1372 strlcpy(option
->defchoice
, string
, sizeof(option
->defchoice
));
1374 DEBUG_printf(("%s is now %s...\n", keyword
, option
->defchoice
));
1379 * Lookup option and set if it has been defined...
1382 ppd_option_t
*toption
; /* Temporary option */
1385 if ((toption
= ppdFindOption(ppd
, keyword
+ 7)) != NULL
)
1387 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1388 strlcpy(toption
->defchoice
, string
, sizeof(toption
->defchoice
));
1392 else if (strcmp(keyword
, "UIConstraints") == 0 ||
1393 strcmp(keyword
, "NonUIConstraints") == 0)
1395 if (ppd
->num_consts
== 0)
1396 constraint
= calloc(1, sizeof(ppd_const_t
));
1398 constraint
= realloc(ppd
->consts
,
1399 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1401 if (constraint
== NULL
)
1403 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1408 ppd
->consts
= constraint
;
1409 constraint
+= ppd
->num_consts
;
1412 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1413 constraint
->choice1
, constraint
->option2
,
1414 constraint
->choice2
))
1416 case 0 : /* Error */
1417 case 1 : /* Error */
1418 cg
->ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1421 case 2 : /* Two options... */
1423 * The following strcpy's are safe, as optionN and
1424 * choiceN are all the same size (size defined by PPD spec...)
1427 if (constraint
->option1
[0] == '*')
1428 cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1430 if (constraint
->choice1
[0] == '*')
1431 cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1433 cups_strcpy(constraint
->option2
, constraint
->choice1
);
1435 constraint
->choice1
[0] = '\0';
1436 constraint
->choice2
[0] = '\0';
1439 case 3 : /* Two options, one choice... */
1441 * The following cups_strcpy's are safe, as optionN and
1442 * choiceN are all the same size (size defined by PPD spec...)
1445 if (constraint
->option1
[0] == '*')
1446 cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1448 if (constraint
->choice1
[0] == '*')
1450 cups_strcpy(constraint
->choice2
, constraint
->option2
);
1451 cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1452 constraint
->choice1
[0] = '\0';
1456 if (constraint
->option2
[0] == '*')
1457 cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1459 constraint
->choice2
[0] = '\0';
1463 case 4 : /* Two options, two choices... */
1464 if (constraint
->option1
[0] == '*')
1465 cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1467 if (constraint
->option2
[0] == '*')
1468 cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1475 else if (strcmp(keyword
, "PaperDimension") == 0)
1477 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1478 size
= ppd_add_size(ppd
, name
);
1483 * Unable to add or find size!
1486 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1491 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1496 else if (strcmp(keyword
, "ImageableArea") == 0)
1498 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1499 size
= ppd_add_size(ppd
, name
);
1504 * Unable to add or find size!
1507 cg
->ppd_status
= PPD_ALLOC_ERROR
;
1512 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1513 &(size
->right
), &(size
->top
));
1518 else if (option
!= NULL
&&
1519 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1520 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
) &&
1521 strcmp(keyword
, option
->keyword
) == 0)
1523 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1525 if (strcmp(keyword
, "PageSize") == 0)
1528 * Add a page size...
1531 if (ppdPageSize(ppd
, name
) == NULL
)
1532 ppd_add_size(ppd
, name
);
1536 * Add the option choice...
1539 choice
= ppd_add_choice(option
, name
);
1541 if (mask
& PPD_TEXT
)
1543 strlcpy(choice
->text
, text
, sizeof(choice
->text
));
1544 ppd_fix(choice
->text
);
1546 else if (strcmp(name
, "True") == 0)
1547 strcpy(choice
->text
, "Yes");
1548 else if (strcmp(name
, "False") == 0)
1549 strcpy(choice
->text
, "No");
1551 strlcpy(choice
->text
, name
, sizeof(choice
->text
));
1553 if (option
->section
== PPD_ORDER_JCL
)
1554 ppd_decode(string
); /* Decode quoted string */
1556 choice
->code
= string
;
1557 string
= NULL
; /* Don't add as an attribute below */
1560 else if (strcmp(keyword
, "cupsUIType") == 0 &&
1561 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1565 * Define an extended option value type...
1568 extopt
= ppd_get_extoption(ppd
, name
);
1570 if (strcmp(string
, "Text") == 0)
1571 option
->ui
= PPD_UI_CUPS_TEXT
;
1572 else if (strcmp(string
, "Integer") == 0)
1574 option
->ui
= PPD_UI_CUPS_INTEGER
;
1575 extopt
->defval
.integer
= 0;
1576 extopt
->minval
.integer
= 0;
1577 extopt
->maxval
.integer
= 100;
1579 else if (strcmp(string
, "Real") == 0)
1581 option
->ui
= PPD_UI_CUPS_REAL
;
1582 extopt
->defval
.real
= 0.0;
1583 extopt
->minval
.real
= 0.0;
1584 extopt
->maxval
.real
= 1.0;
1586 else if (strcmp(string
, "Gamma") == 0)
1588 option
->ui
= PPD_UI_CUPS_GAMMA
;
1589 extopt
->defval
.gamma
= 1.0;
1590 extopt
->minval
.gamma
= 1.0;
1591 extopt
->maxval
.gamma
= 10.0;
1593 else if (strcmp(string
, "Curve") == 0)
1595 option
->ui
= PPD_UI_CUPS_CURVE
;
1596 extopt
->defval
.curve
.start
= 0.0;
1597 extopt
->defval
.curve
.end
= 0.0;
1598 extopt
->defval
.curve
.gamma
= 1.0;
1599 extopt
->minval
.curve
.start
= 0.0;
1600 extopt
->minval
.curve
.end
= 0.0;
1601 extopt
->minval
.curve
.gamma
= 1.0;
1602 extopt
->maxval
.curve
.start
= 1.0;
1603 extopt
->maxval
.curve
.end
= 1.0;
1604 extopt
->maxval
.curve
.gamma
= 10.0;
1606 else if (strcmp(string
, "IntegerArray") == 0)
1608 option
->ui
= PPD_UI_CUPS_INTEGER_ARRAY
;
1609 extopt
->defval
.integer_array
.num_elements
= 2;
1610 extopt
->minval
.integer_array
.num_elements
= 2;
1611 extopt
->maxval
.integer_array
.num_elements
= 16;
1613 else if (strcmp(string
, "RealArray") == 0)
1615 option
->ui
= PPD_UI_CUPS_REAL_ARRAY
;
1616 extopt
->defval
.real_array
.num_elements
= 2;
1617 extopt
->minval
.real_array
.num_elements
= 2;
1618 extopt
->maxval
.real_array
.num_elements
= 16;
1621 else if (strcmp(keyword
, "cupsUIDefault") == 0 &&
1622 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1626 * Define an extended option minimum value...
1629 extopt
= ppd_get_extoption(ppd
, name
);
1633 case PPD_UI_CUPS_INTEGER
:
1634 sscanf(string
, "%d", &(extopt
->defval
.integer
));
1637 case PPD_UI_CUPS_REAL
:
1638 sscanf(string
, "%f", &(extopt
->defval
.real
));
1641 case PPD_UI_CUPS_GAMMA
:
1642 sscanf(string
, "%f", &(extopt
->defval
.gamma
));
1645 case PPD_UI_CUPS_CURVE
:
1646 sscanf(string
, "%f%f%f", &(extopt
->defval
.curve
.start
),
1647 &(extopt
->defval
.curve
.end
),
1648 &(extopt
->defval
.curve
.gamma
));
1651 case PPD_UI_CUPS_INTEGER_ARRAY
:
1652 extopt
->defval
.integer_array
.elements
= calloc(1, sizeof(int));
1653 sscanf(string
, "%d%d", &(extopt
->defval
.integer_array
.num_elements
),
1654 extopt
->defval
.integer_array
.elements
);
1657 case PPD_UI_CUPS_REAL_ARRAY
:
1658 extopt
->defval
.real_array
.elements
= calloc(1, sizeof(float));
1659 sscanf(string
, "%d%f", &(extopt
->defval
.real_array
.num_elements
),
1660 extopt
->defval
.real_array
.elements
);
1667 else if (strcmp(keyword
, "cupsUIMinimum") == 0 &&
1668 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1672 * Define an extended option minimum value...
1675 extopt
= ppd_get_extoption(ppd
, name
);
1679 case PPD_UI_CUPS_INTEGER
:
1680 sscanf(string
, "%d", &(extopt
->minval
.integer
));
1683 case PPD_UI_CUPS_REAL
:
1684 sscanf(string
, "%f", &(extopt
->minval
.real
));
1687 case PPD_UI_CUPS_GAMMA
:
1688 sscanf(string
, "%f", &(extopt
->minval
.gamma
));
1691 case PPD_UI_CUPS_CURVE
:
1692 sscanf(string
, "%f%f%f", &(extopt
->minval
.curve
.start
),
1693 &(extopt
->minval
.curve
.end
),
1694 &(extopt
->minval
.curve
.gamma
));
1697 case PPD_UI_CUPS_INTEGER_ARRAY
:
1698 extopt
->minval
.integer_array
.elements
= calloc(1, sizeof(int));
1699 sscanf(string
, "%d%d", &(extopt
->minval
.integer_array
.num_elements
),
1700 extopt
->minval
.integer_array
.elements
);
1703 case PPD_UI_CUPS_REAL_ARRAY
:
1704 extopt
->minval
.real_array
.elements
= calloc(1, sizeof(float));
1705 sscanf(string
, "%d%f", &(extopt
->minval
.real_array
.num_elements
),
1706 extopt
->minval
.real_array
.elements
);
1713 else if (strcmp(keyword
, "cupsUIMaximum") == 0 &&
1714 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1718 * Define an extended option maximum value...
1721 extopt
= ppd_get_extoption(ppd
, name
);
1725 case PPD_UI_CUPS_INTEGER
:
1726 sscanf(string
, "%d", &(extopt
->maxval
.integer
));
1729 case PPD_UI_CUPS_REAL
:
1730 sscanf(string
, "%f", &(extopt
->maxval
.real
));
1733 case PPD_UI_CUPS_GAMMA
:
1734 sscanf(string
, "%f", &(extopt
->maxval
.gamma
));
1737 case PPD_UI_CUPS_CURVE
:
1738 sscanf(string
, "%f%f%f", &(extopt
->maxval
.curve
.start
),
1739 &(extopt
->maxval
.curve
.end
),
1740 &(extopt
->maxval
.curve
.gamma
));
1743 case PPD_UI_CUPS_INTEGER_ARRAY
:
1744 extopt
->maxval
.integer_array
.elements
= calloc(1, sizeof(int));
1745 sscanf(string
, "%d%d", &(extopt
->maxval
.integer_array
.num_elements
),
1746 extopt
->maxval
.integer_array
.elements
);
1749 case PPD_UI_CUPS_REAL_ARRAY
:
1750 extopt
->maxval
.real_array
.elements
= calloc(1, sizeof(float));
1751 sscanf(string
, "%d%f", &(extopt
->maxval
.real_array
.num_elements
),
1752 extopt
->maxval
.real_array
.elements
);
1759 else if (strcmp(keyword
, "cupsUICommand") == 0 &&
1760 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1764 * Define an extended option command...
1767 extopt
= ppd_get_extoption(ppd
, name
);
1769 extopt
->command
= string
;
1775 * Add remaining lines with keywords and string values as attributes...
1779 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
))
1780 ppd_add_attr(ppd
, keyword
, name
, text
, string
);
1788 * Reset language preferences...
1791 cupsLangFree(language
);
1794 _cupsRestoreLocale(LC_NUMERIC
, oldlocale
);
1796 _cupsRestoreLocale(LC_ALL
, oldlocale
);
1797 #endif /* LC_NUMERIC */
1801 printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp
));
1804 if (cg
->ppd_status
!= PPD_OK
)
1807 * Had an error reading the PPD file, cannot continue!
1817 * Make sure that all PPD files with an InputSlot option have an
1818 * "auto" choice that maps to no specific tray or media type.
1821 if ((option
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1823 for (i
= 0; i
< option
->num_choices
; i
++)
1824 if (option
->choices
[i
].code
== NULL
|| !option
->choices
[i
].code
[0] ||
1825 !strncasecmp(option
->choices
[i
].choice
, "Auto", 4))
1828 if (i
>= option
->num_choices
)
1831 * No "auto" input slot, add one...
1834 choice
= ppd_add_choice(option
, "Auto");
1836 strlcpy(choice
->text
, cupsLangString(language
, CUPS_MSG_AUTO
),
1837 sizeof(choice
->text
));
1838 choice
->code
= NULL
;
1841 #endif /* !__APPLE__ */
1844 * Set the option back-pointer for each choice...
1848 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1849 (int (*)(const void *, const void *))ppd_compare_groups
);
1850 #endif /* !__APPLE__ */
1852 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1857 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1858 (int (*)(const void *, const void *))ppd_compare_options
);
1859 #endif /* !__APPLE__ */
1861 for (j
= group
->num_options
, option
= group
->options
;
1865 for (k
= 0; k
< option
->num_choices
; k
++)
1866 option
->choices
[k
].option
= (void *)option
;
1870 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1871 (int (*)(const void *, const void *))ppd_compare_groups
);
1872 #endif /* !__APPLE__ */
1874 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1879 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1880 (int (*)(const void *, const void *))ppd_compare_options
);
1881 #endif /* !__APPLE__ */
1883 for (k
= group
->num_options
, option
= group
->options
;
1887 for (m
= 0; m
< option
->num_choices
; m
++)
1888 option
->choices
[m
].option
= (void *)option
;
1895 * Set the option pointers for all extended options...
1898 for (i
= 0; i
< ppd
->num_extended
; i
++)
1899 ppd
->extended
[i
]->option
= ppdFindOption(ppd
, ppd
->extended
[i
]->keyword
);
1903 * Sort the attributes...
1906 if (ppd
->num_attrs
> 1)
1907 qsort(ppd
->attrs
, ppd
->num_attrs
, sizeof(ppd_attr_t
*),
1908 (int (*)(const void *, const void *))_ppd_attr_compare
);
1911 * Return the PPD file structure...
1917 * Common exit point for errors to save code size...
1926 cupsLangFree(language
);
1929 _cupsRestoreLocale(LC_NUMERIC
, oldlocale
);
1931 _cupsRestoreLocale(LC_ALL
, oldlocale
);
1932 #endif /* LC_NUMERIC */
1939 * 'ppdOpenFd()' - Read a PPD file into memory.
1942 ppd_file_t
* /* O - PPD file record */
1943 ppdOpenFd(int fd
) /* I - File to read from */
1945 FILE *fp
; /* File pointer */
1946 ppd_file_t
*ppd
; /* PPD file record */
1947 cups_globals_t
*cg
= _cupsGlobals();
1952 * Set the line number to 0...
1958 * Range check input...
1963 cg
->ppd_status
= PPD_NULL_FILE
;
1969 * Try to open the file and parse it...
1972 if ((fp
= fdopen(fd
, "r")) != NULL
)
1982 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
1991 * 'ppdOpenFile()' - Read a PPD file into memory.
1994 ppd_file_t
* /* O - PPD file record */
1995 ppdOpenFile(const char *filename
) /* I - File to read from */
1997 cups_file_t
*fp
; /* File pointer */
1998 ppd_file_t
*ppd
; /* PPD file record */
1999 cups_globals_t
*cg
= _cupsGlobals();
2004 * Set the line number to 0...
2010 * Range check input...
2013 if (filename
== NULL
)
2015 cg
->ppd_status
= PPD_NULL_FILE
;
2021 * Try to open the file and parse it...
2024 if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
2032 cg
->ppd_status
= PPD_FILE_OPEN_ERROR
;
2041 * 'ppdSetConformance()' - Set the conformance level for PPD files.
2045 ppdSetConformance(ppd_conform_t c
) /* I - Conformance level */
2047 cups_globals_t
*cg
= _cupsGlobals();
2051 cg
->ppd_conform
= c
;
2056 * 'ppd_add_attr()' - Add an attribute to the PPD data.
2059 static ppd_attr_t
* /* O - New attribute */
2060 ppd_add_attr(ppd_file_t
*ppd
, /* I - PPD file data */
2061 const char *name
, /* I - Attribute name */
2062 const char *spec
, /* I - Specifier string, if any */
2063 const char *text
, /* I - Text string, if any */
2064 const char *value
) /* I - Value of attribute */
2066 ppd_attr_t
**ptr
, /* New array */
2067 *temp
; /* New attribute */
2071 * Range check input...
2074 if (ppd
== NULL
|| name
== NULL
|| spec
== NULL
)
2078 * Allocate memory for the new attribute...
2081 if (ppd
->num_attrs
== 0)
2082 ptr
= malloc(sizeof(ppd_attr_t
*));
2084 ptr
= realloc(ppd
->attrs
, (ppd
->num_attrs
+ 1) * sizeof(ppd_attr_t
*));
2090 ptr
+= ppd
->num_attrs
;
2092 if ((temp
= calloc(1, sizeof(ppd_attr_t
))) == NULL
)
2103 strlcpy(temp
->name
, name
, sizeof(temp
->name
));
2104 strlcpy(temp
->spec
, spec
, sizeof(temp
->spec
));
2105 strlcpy(temp
->text
, text
, sizeof(temp
->text
));
2106 temp
->value
= (char *)value
;
2109 * Return the attribute...
2117 * 'ppd_add_choice()' - Add a choice to an option.
2120 static ppd_choice_t
* /* O - Named choice */
2121 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
2122 const char *name
) /* I - Name of choice */
2124 ppd_choice_t
*choice
; /* Choice */
2127 if (option
->num_choices
== 0)
2128 choice
= malloc(sizeof(ppd_choice_t
));
2130 choice
= realloc(option
->choices
,
2131 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
2136 option
->choices
= choice
;
2137 choice
+= option
->num_choices
;
2138 option
->num_choices
++;
2140 memset(choice
, 0, sizeof(ppd_choice_t
));
2141 strlcpy(choice
->choice
, name
, sizeof(choice
->choice
));
2148 * 'ppd_add_size()' - Add a page size.
2151 static ppd_size_t
* /* O - Named size */
2152 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
2153 const char *name
) /* I - Name of size */
2155 ppd_size_t
*size
; /* Size */
2158 if (ppd
->num_sizes
== 0)
2159 size
= malloc(sizeof(ppd_size_t
));
2161 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
2167 size
+= ppd
->num_sizes
;
2170 memset(size
, 0, sizeof(ppd_size_t
));
2171 strlcpy(size
->name
, name
, sizeof(size
->name
));
2179 * 'ppd_compare_groups()' - Compare two groups.
2182 static int /* O - Result of comparison */
2183 ppd_compare_groups(ppd_group_t
*g0
, /* I - First group */
2184 ppd_group_t
*g1
) /* I - Second group */
2186 return (strcasecmp(g0
->text
, g1
->text
));
2191 * 'ppd_compare_options()' - Compare two options.
2194 static int /* O - Result of comparison */
2195 ppd_compare_options(ppd_option_t
*o0
, /* I - First option */
2196 ppd_option_t
*o1
) /* I - Second option */
2198 return (strcasecmp(o0
->text
, o1
->text
));
2200 #endif /* !__APPLE__ */
2204 * 'ppd_decode()' - Decode a string value...
2207 static int /* O - Length of decoded string */
2208 ppd_decode(char *string
) /* I - String to decode */
2210 char *inptr
, /* Input pointer */
2211 *outptr
; /* Output pointer */
2217 while (*inptr
!= '\0')
2218 if (*inptr
== '<' && isxdigit(inptr
[1] & 255))
2221 * Convert hex to 8-bit values...
2225 while (isxdigit(*inptr
& 255))
2227 if (isalpha(*inptr
))
2228 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
2230 *outptr
= (*inptr
- '0') << 4;
2234 if (!isxdigit(*inptr
& 255))
2237 if (isalpha(*inptr
))
2238 *outptr
|= tolower(*inptr
) - 'a' + 10;
2240 *outptr
|= *inptr
- '0';
2246 while (*inptr
!= '>' && *inptr
!= '\0')
2248 while (*inptr
== '>')
2252 *outptr
++ = *inptr
++;
2256 return (outptr
- string
);
2262 * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be
2263 * valid ISO-8859-1 characters...
2267 ppd_fix(char *string
) /* IO - String to fix */
2269 unsigned char *p
; /* Pointer into string */
2270 static const unsigned char lut
[32] = /* Lookup table for characters */
2294 0x20, /* circumflex */
2296 0x20, /* double dot */
2301 '\"', /* should be right quotes */
2307 for (p
= (unsigned char *)string
; *p
; p
++)
2308 if (*p
>= 0x80 && *p
< 0xa0)
2309 *p
= lut
[*p
- 0x80];
2311 #endif /* !__APPLE__ */
2315 * 'ppd_free_group()' - Free a single UI group.
2319 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
2321 int i
; /* Looping var */
2322 ppd_option_t
*option
; /* Current option */
2323 ppd_group_t
*subgroup
; /* Current sub-group */
2326 if (group
->num_options
> 0)
2328 for (i
= group
->num_options
, option
= group
->options
;
2331 ppd_free_option(option
);
2333 ppd_free(group
->options
);
2336 if (group
->num_subgroups
> 0)
2338 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
2341 ppd_free_group(subgroup
);
2343 ppd_free(group
->subgroups
);
2349 * 'ppd_free_option()' - Free a single option.
2353 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
2355 int i
; /* Looping var */
2356 ppd_choice_t
*choice
; /* Current choice */
2359 if (option
->num_choices
> 0)
2361 for (i
= option
->num_choices
, choice
= option
->choices
;
2365 ppd_free(choice
->code
);
2368 ppd_free(option
->choices
);
2375 * 'ppd_get_extoption()' - Get an extended option record.
2378 static ppd_ext_option_t
* /* O - Extended option... */
2379 ppd_get_extoption(ppd_file_t
*ppd
, /* I - PPD file */
2380 const char *name
) /* I - Name of option */
2382 ppd_ext_option_t
**temp
, /* New array pointer */
2383 *extopt
; /* New extended option */
2387 * See if the option already exists...
2390 if ((extopt
= ppdFindExtOption(ppd
, name
)) != NULL
)
2394 * Not found, so create the extended option record...
2397 if ((extopt
= calloc(1, sizeof(ppd_ext_option_t
))) == NULL
)
2400 strlcpy(extopt
->keyword
, name
, sizeof(extopt
->keyword
));
2403 * Add this record to the end of the array...
2406 if (ppd
->num_extended
== 0)
2407 temp
= malloc(sizeof(ppd_ext_option_t
*));
2409 temp
= realloc(ppd
->extended
, sizeof(ppd_ext_option_t
*) *
2410 (ppd
->num_extended
+ 1));
2418 ppd
->extended
= temp
;
2419 temp
[ppd
->num_extended
] = extopt
;
2421 ppd
->num_extended
++;
2424 * Return the new record...
2432 * 'ppd_get_extparam()' - Get an extended parameter record.
2435 static ppd_ext_param_t
* /* O - Extended option... */
2436 ppd_get_extparam(ppd_ext_option_t
*opt
, /* I - PPD file */
2437 const char *param
,/* I - Name of parameter */
2438 const char *text
) /* I - Human-readable text */
2440 ppd_ext_param_t
**temp
, /* New array pointer */
2441 *extparam
; /* New extended parameter */
2445 * See if the parameter already exists...
2448 if ((extparam
= ppdFindExtParam(opt
, param
)) != NULL
)
2452 * Not found, so create the extended parameter record...
2455 if ((extparam
= calloc(1, sizeof(ppd_ext_param_t
))) == NULL
)
2458 if ((extparam
->value
= calloc(4, sizeof(ppd_ext_value_t
))) == NULL
)
2464 extparam
->defval
= extparam
->value
+ 1;
2465 extparam
->minval
= extparam
->value
+ 2;
2466 extparam
->maxval
= extparam
->value
+ 3;
2468 strlcpy(extparam
->keyword
, param
, sizeof(extparam
->keyword
));
2469 strlcpy(extparam
->text
, text
, sizeof(extparam
->text
));
2472 * Add this record to the end of the array...
2475 if (opt
->num_params
== 0)
2476 temp
= malloc(sizeof(ppd_ext_param_t
*));
2478 temp
= realloc(opt
->params
, sizeof(ppd_ext_param_t
*) *
2479 (opt
->num_params
+ 1));
2488 temp
[opt
->num_params
] = extparam
;
2493 * Return the new record...
2502 * 'ppd_get_group()' - Find or create the named group as needed.
2505 static ppd_group_t
* /* O - Named group */
2506 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
2507 const char *name
, /* I - Name of group */
2508 const char *text
, /* I - Text for group */
2509 cups_globals_t
*cg
) /* I - Global data */
2511 int i
; /* Looping var */
2512 ppd_group_t
*group
; /* Group */
2515 DEBUG_printf(("ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)\n",
2516 ppd
, name
, text
, cg
));
2518 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
2519 if (strcmp(group
->name
, name
) == 0)
2524 DEBUG_printf(("Adding group %s...\n", name
));
2526 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
&& strlen(text
) >= sizeof(group
->text
))
2528 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2533 if (ppd
->num_groups
== 0)
2534 group
= malloc(sizeof(ppd_group_t
));
2536 group
= realloc(ppd
->groups
,
2537 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
2541 cg
->ppd_status
= PPD_ALLOC_ERROR
;
2546 ppd
->groups
= group
;
2547 group
+= ppd
->num_groups
;
2550 memset(group
, 0, sizeof(ppd_group_t
));
2551 strlcpy(group
->name
, name
, sizeof(group
->name
));
2552 strlcpy(group
->text
, text
, sizeof(group
->text
));
2560 * 'ppd_get_option()' - Find or create the named option as needed.
2563 static ppd_option_t
* /* O - Named option */
2564 ppd_get_option(ppd_group_t
*group
, /* I - Group */
2565 const char *name
) /* I - Name of option */
2567 int i
; /* Looping var */
2568 ppd_option_t
*option
; /* Option */
2571 DEBUG_printf(("ppd_get_option(group=%p(\"%s\"), name=\"%s\")\n",
2572 group
, group
->name
, name
));
2574 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
2575 if (strcmp(option
->keyword
, name
) == 0)
2580 if (group
->num_options
== 0)
2581 option
= malloc(sizeof(ppd_option_t
));
2583 option
= realloc(group
->options
,
2584 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
2589 group
->options
= option
;
2590 option
+= group
->num_options
;
2591 group
->num_options
++;
2593 memset(option
, 0, sizeof(ppd_option_t
));
2594 strlcpy(option
->keyword
, name
, sizeof(option
->keyword
));
2602 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2606 static int /* O - Bitmask of fields read */
2607 ppd_read(cups_file_t
*fp
, /* I - File to read from */
2608 char *keyword
, /* O - Keyword from line */
2609 char *option
, /* O - Option from line */
2610 char *text
, /* O - Human-readable text from line */
2611 char **string
, /* O - Code/string data */
2612 int ignoreblank
, /* I - Ignore blank lines? */
2613 cups_globals_t
*cg
) /* I - Global data */
2615 int ch
, /* Character from file */
2616 col
, /* Column in line */
2617 colon
, /* Colon seen? */
2618 endquote
, /* Waiting for an end quote */
2619 mask
, /* Mask to be returned */
2620 startline
, /* Start line */
2621 textlen
; /* Length of text */
2622 char *keyptr
, /* Keyword pointer */
2623 *optptr
, /* Option pointer */
2624 *textptr
, /* Text pointer */
2625 *strptr
, /* Pointer into string */
2626 *lineptr
, /* Current position in line buffer */
2627 *line
; /* Line buffer */
2628 int linesize
; /* Current size of line buffer */
2631 * Range check everything...
2634 if (!fp
|| !keyword
|| !option
|| !text
|| !string
)
2638 * Now loop until we have a valid line...
2643 startline
= cg
->ppd_line
+ 1;
2645 line
= malloc(linesize
);
2660 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2662 if (lineptr
>= (line
+ linesize
- 1))
2665 * Expand the line buffer...
2668 char *temp
; /* Temporary line pointer */
2672 if (linesize
> 262144)
2675 * Don't allow lines longer than 256k!
2678 cg
->ppd_line
= startline
;
2679 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2686 temp
= realloc(line
, linesize
);
2689 cg
->ppd_line
= startline
;
2690 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2697 lineptr
= temp
+ (lineptr
- line
);
2701 if (ch
== '\r' || ch
== '\n')
2704 * Line feed or carriage return...
2713 * Check for a trailing line feed...
2716 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2719 cupsFileGetChar(fp
);
2722 if (lineptr
== line
&& ignoreblank
)
2723 continue; /* Skip blank lines */
2727 if (!endquote
) /* Continue for multi-line text */
2732 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2735 * Other control characters...
2738 cg
->ppd_line
= startline
;
2739 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2745 else if (ch
!= 0x1a)
2748 * Any other character...
2754 if (col
> (PPD_MAX_LINE
- 1))
2757 * Line is too long...
2760 cg
->ppd_line
= startline
;
2761 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2768 if (ch
== ':' && strncmp(line
, "*%", 2) != 0)
2771 if (ch
== '\"' && colon
)
2772 endquote
= !endquote
;
2779 * Didn't finish this quoted string...
2782 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2785 else if (ch
== '\r' || ch
== '\n')
2793 * Check for a trailing line feed...
2796 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2799 cupsFileGetChar(fp
);
2804 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2807 * Other control characters...
2810 cg
->ppd_line
= startline
;
2811 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2817 else if (ch
!= 0x1a)
2821 if (col
> (PPD_MAX_LINE
- 1))
2824 * Line is too long...
2827 cg
->ppd_line
= startline
;
2828 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2840 * Didn't finish this line...
2843 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
2844 if (ch
== '\r' || ch
== '\n')
2847 * Line feed or carriage return...
2856 * Check for a trailing line feed...
2859 if ((ch
= cupsFilePeekChar(fp
)) == EOF
)
2862 cupsFileGetChar(fp
);
2867 else if (ch
< ' ' && ch
!= '\t' && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2870 * Other control characters...
2873 cg
->ppd_line
= startline
;
2874 cg
->ppd_status
= PPD_ILLEGAL_CHARACTER
;
2880 else if (ch
!= 0x1a)
2884 if (col
> (PPD_MAX_LINE
- 1))
2887 * Line is too long...
2890 cg
->ppd_line
= startline
;
2891 cg
->ppd_status
= PPD_LINE_TOO_LONG
;
2900 if (lineptr
> line
&& lineptr
[-1] == '\n')
2905 DEBUG_printf(("LINE = \"%s\"\n", line
));
2907 if (ch
== EOF
&& lineptr
== line
)
2925 if ((!line
[0] || /* Blank line */
2926 strncmp(line
, "*%", 2) == 0 || /* Comment line */
2927 strcmp(line
, "*End") == 0) && /* End of multi-line string */
2928 ignoreblank
) /* Ignore these? */
2930 startline
= cg
->ppd_line
+ 1;
2934 if (strcmp(line
, "*") == 0) /* (Bad) comment line */
2936 if (cg
->ppd_conform
== PPD_CONFORM_RELAXED
)
2938 startline
= cg
->ppd_line
+ 1;
2943 cg
->ppd_line
= startline
;
2944 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2951 if (line
[0] != '*') /* All lines start with an asterisk */
2953 if (cg
->ppd_conform
== PPD_CONFORM_STRICT
)
2955 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
2961 * Allow lines consisting of just whitespace...
2964 for (lineptr
= line
; *lineptr
; lineptr
++)
2965 if (!isspace(*lineptr
& 255))
2970 cg
->ppd_status
= PPD_MISSING_ASTERISK
;
2974 else if (ignoreblank
)
2989 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
& 255))
2991 if (*lineptr
<= ' ' || *lineptr
> 126 || *lineptr
== '/' ||
2992 (keyptr
- keyword
) >= (PPD_MAX_NAME
- 1))
2994 cg
->ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2999 *keyptr
++ = *lineptr
++;
3004 if (strcmp(keyword
, "End") == 0)
3007 mask
|= PPD_KEYWORD
;
3009 /* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/
3011 if (isspace(*lineptr
& 255))
3014 * Get an option name...
3017 while (isspace(*lineptr
& 255))
3022 while (*lineptr
!= '\0' && !isspace(*lineptr
& 255) && *lineptr
!= ':' &&
3025 if (*lineptr
<= ' ' || *lineptr
> 126 ||
3026 (optptr
- option
) >= (PPD_MAX_NAME
- 1))
3028 cg
->ppd_status
= PPD_ILLEGAL_OPTION_KEYWORD
;
3033 *optptr
++ = *lineptr
++;
3038 if (isspace(*lineptr
& 255) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3040 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3045 while (isspace(*lineptr
& 255))
3050 /* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/
3052 if (*lineptr
== '/')
3055 * Get human-readable text...
3062 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':')
3064 if (((unsigned char)*lineptr
< ' ' && *lineptr
!= '\t') ||
3065 (textptr
- text
) >= (PPD_MAX_LINE
- 1))
3067 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3072 *textptr
++ = *lineptr
++;
3076 textlen
= ppd_decode(text
);
3078 if (textlen
> PPD_MAX_TEXT
&& cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3080 cg
->ppd_status
= PPD_ILLEGAL_TRANSLATION
;
3088 /* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/
3091 if (isspace(*lineptr
& 255) && cg
->ppd_conform
== PPD_CONFORM_STRICT
)
3093 cg
->ppd_status
= PPD_ILLEGAL_WHITESPACE
;
3098 while (isspace(*lineptr
& 255))
3101 if (*lineptr
== ':')
3104 * Get string after triming leading and trailing whitespace...
3108 while (isspace(*lineptr
& 255))
3111 strptr
= lineptr
+ strlen(lineptr
) - 1;
3112 while (strptr
>= lineptr
&& isspace(*strptr
& 255))
3115 if (*strptr
== '\"')
3118 * Quoted string by itself...
3121 *string
= malloc(strlen(lineptr
) + 1);
3125 for (; *lineptr
!= '\0'; lineptr
++)
3126 if (*lineptr
!= '\"')
3127 *strptr
++ = *lineptr
;
3132 *string
= strdup(lineptr
);
3134 /* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/