2 * "$Id: ppd.c,v 1.51.2.65 2004/06/29 13:15:08 mike Exp $"
4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2004 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-3142 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.
79 #if defined(WIN32) || defined(__EMX__)
80 # define READ_BINARY "rb" /* Open a binary file for reading */
81 # define WRITE_BINARY "wb" /* Open a binary file for writing */
83 # define READ_BINARY "r" /* Open a binary file for reading */
84 # define WRITE_BINARY "w" /* Open a binary file for writing */
85 #endif /* WIN32 || __EMX__ */
87 #define ppd_free(p) if (p) free(p) /* Safe free macro */
89 #define PPD_KEYWORD 1 /* Line contained a keyword */
90 #define PPD_OPTION 2 /* Line contained an option name */
91 #define PPD_TEXT 4 /* Line contained human-readable text */
92 #define PPD_STRING 8 /* Line contained a string or code */
99 static ppd_status_t ppd_status
= PPD_OK
;
100 /* Status of last ppdOpen*() */
101 static int ppd_line
= 0; /* Current line number */
102 static ppd_conform_t ppd_conform
= PPD_CONFORM_RELAXED
;
103 /* Level of conformance required */
110 static ppd_attr_t
*ppd_add_attr(ppd_file_t
*ppd
, const char *name
,
111 const char *spec
, const char *text
,
113 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, const char *name
);
114 static ppd_size_t
*ppd_add_size(ppd_file_t
*ppd
, const char *name
);
116 static int ppd_compare_groups(ppd_group_t
*g0
, ppd_group_t
*g1
);
117 static int ppd_compare_options(ppd_option_t
*o0
, ppd_option_t
*o1
);
118 #endif /* !__APPLE__ */
119 static int ppd_decode(char *string
);
121 static void ppd_fix(char *string
);
124 #endif /* !__APPLE__ */
125 static void ppd_free_group(ppd_group_t
*group
);
126 static void ppd_free_option(ppd_option_t
*option
);
127 static ppd_ext_option_t
*ppd_get_extoption(ppd_file_t
*ppd
, const char *name
);
128 static ppd_ext_param_t
*ppd_get_extparam(ppd_ext_option_t
*opt
,
131 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, const char *name
,
133 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, const char *name
);
134 static int ppd_read(FILE *fp
, char *keyword
, char *option
,
135 char *text
, char **string
, int ignoreblank
);
139 * '_ppd_attr_compare()' - Compare two attributes.
142 int /* O - Result of comparison */
143 _ppd_attr_compare(ppd_attr_t
**a
, /* I - First attribute */
144 ppd_attr_t
**b
) /* I - Second attribute */
146 int ret
; /* Result of comparison */
149 if ((ret
= strcasecmp((*a
)->name
, (*b
)->name
)) != 0)
151 else if ((*a
)->spec
[0] && (*b
)->spec
[0])
152 return (strcasecmp((*a
)->spec
, (*b
)->spec
));
159 * 'ppdClose()' - Free all memory used by the PPD file.
163 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
165 int i
, j
; /* Looping var */
166 ppd_emul_t
*emul
; /* Current emulation */
167 ppd_group_t
*group
; /* Current group */
168 char **font
; /* Current font */
169 char **filter
; /* Current filter */
170 ppd_attr_t
**attr
; /* Current attribute */
171 ppd_ext_option_t
**opt
; /* Current extended option */
172 ppd_ext_param_t
**param
; /* Current extended parameter */
176 * Range check the PPD file record...
183 * Free all strings at the top level...
186 ppd_free(ppd
->patches
);
187 ppd_free(ppd
->jcl_begin
);
188 ppd_free(ppd
->jcl_end
);
189 ppd_free(ppd
->jcl_ps
);
192 * Free any emulations...
195 if (ppd
->num_emulations
> 0)
197 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
199 ppd_free(emul
->start
);
200 ppd_free(emul
->stop
);
203 ppd_free(ppd
->emulations
);
207 * Free any UI groups, subgroups, and options...
210 if (ppd
->num_groups
> 0)
212 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
213 ppd_free_group(group
);
215 ppd_free(ppd
->groups
);
219 * Free any page sizes...
222 if (ppd
->num_sizes
> 0)
224 ppd_free(ppd
->sizes
);
228 * Free any constraints...
231 if (ppd
->num_consts
> 0)
233 ppd_free(ppd
->consts
);
237 * Free any filters...
240 if (ppd
->num_filters
> 0)
242 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
247 ppd_free(ppd
->filters
);
254 if (ppd
->num_fonts
> 0)
256 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
261 ppd_free(ppd
->fonts
);
265 * Free any profiles...
268 if (ppd
->num_profiles
> 0)
270 ppd_free(ppd
->profiles
);
274 * Free any attributes...
277 if (ppd
->num_attrs
> 0)
279 for (i
= ppd
->num_attrs
, attr
= ppd
->attrs
; i
> 0; i
--, attr
++)
281 ppd_free((*attr
)->value
);
285 ppd_free(ppd
->attrs
);
288 if (ppd
->num_extended
)
290 for (i
= ppd
->num_extended
, opt
= ppd
->extended
; i
> 0; i
--, opt
++)
292 ppd_free((*opt
)->code
);
294 for (j
= (*opt
)->num_params
, param
= (*opt
)->params
; j
> 0; j
--, param
++)
295 ppd_free((*param
)->value
);
297 ppd_free((*opt
)->params
);
300 ppd_free(ppd
->extended
);
304 * Free the whole record...
312 * 'ppdErrorString()' - Returns the text assocated with a status.
315 const char * /* O - Status string */
316 ppdErrorString(ppd_status_t status
) /* I - PPD status */
318 static const char * const messages
[] =/* Status messages */
321 "Unable to open PPD file",
322 "NULL PPD file pointer",
323 "Memory allocation error",
324 "Missing PPD-Adobe-4.x header",
325 "Missing value string",
328 "OpenGroup without a CloseGroup first",
329 "Bad OpenUI/JCLOpenUI",
330 "OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first",
331 "Bad OrderDependency",
333 "Missing asterisk in column 1",
334 "Line longer than the maximum allowed (255 characters)",
335 "Illegal control character",
336 "Illegal main keyword string",
337 "Illegal option keyword string",
338 "Illegal translation string",
339 "Illegal whitespace character"
343 if (status
< PPD_OK
|| status
> PPD_ILLEGAL_WHITESPACE
)
346 return (messages
[status
]);
351 * 'ppdLastError()' - Return the status from the last ppdOpen*().
354 ppd_status_t
/* O - Status code */
355 ppdLastError(int *line
) /* O - Line number */
365 * 'ppdOpen()' - Read a PPD file into memory.
368 ppd_file_t
* /* O - PPD file record */
369 ppdOpen(FILE *fp
) /* I - File to read from */
371 char *oldlocale
; /* Old locale settings */
372 int i
, j
, k
, m
; /* Looping vars */
373 int count
; /* Temporary count */
374 ppd_file_t
*ppd
; /* PPD file record */
375 ppd_group_t
*group
, /* Current group */
376 *subgroup
; /* Current sub-group */
377 ppd_option_t
*option
; /* Current option */
378 ppd_ext_option_t
*extopt
; /* Current extended option */
379 ppd_choice_t
*choice
; /* Current choice */
380 ppd_const_t
*constraint
; /* Current constraint */
381 ppd_size_t
*size
; /* Current page size */
382 int mask
; /* Line data mask */
383 char keyword
[PPD_MAX_NAME
],
384 /* Keyword from file */
386 /* Option from file */
388 /* Human-readable text from file */
389 *string
, /* Code/text from file */
390 *sptr
, /* Pointer into string */
391 *nameptr
, /* Pointer into name */
392 *temp
, /* Temporary string pointer */
393 **tempfonts
; /* Temporary fonts pointer */
394 float order
; /* Order dependency number */
395 ppd_section_t section
; /* Order dependency section */
396 ppd_profile_t
*profile
; /* Pointer to color profile */
397 char **filter
; /* Pointer to filter */
398 cups_lang_t
*language
; /* Default language */
399 int ui_keyword
; /* Is this line a UI keyword? */
400 static const char * const ui_keywords
[] =
402 /* Boolean keywords */
412 /* PickOne keywords */
425 "JCLFrameBufferSize",
450 * Default to "OK" status...
457 * Range check input...
462 ppd_status
= PPD_NULL_FILE
;
467 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
470 mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 0);
472 DEBUG_printf(("mask=%x, keyword=\"%s\"...\n", mask
, keyword
));
475 strcmp(keyword
, "PPD-Adobe") != 0 ||
476 string
== NULL
|| string
[0] != '4')
479 * Either this is not a PPD file, or it is not a 4.x PPD file.
482 if (ppd_status
== PPD_OK
)
483 ppd_status
= PPD_MISSING_PPDADOBE4
;
490 DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword
, string
));
495 * Allocate memory for the PPD file record...
498 if ((ppd
= calloc(1, sizeof(ppd_file_t
))) == NULL
)
500 ppd_status
= PPD_ALLOC_ERROR
;
505 ppd
->language_level
= 1;
506 ppd
->color_device
= 0;
507 ppd
->colorspace
= PPD_CS_GRAY
;
508 ppd
->landscape
= -90;
511 * Get the default language for the user...
514 language
= cupsLangDefault();
517 oldlocale
= _cupsSaveLocale(LC_NUMERIC
, "C");
519 oldlocale
= _cupsSaveLocale(LC_ALL
, "C");
520 #endif /* LC_NUMERIC */
523 * Read lines from the PPD file and add them to the file record...
532 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
, 1)) != 0)
535 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
538 printf(", name = \"%s\"", name
);
541 printf(", text = \"%s\"", text
);
545 if (strlen(string
) > 40)
546 printf(", string = %p", string
);
548 printf(", string = \"%s\"", string
);
554 if (strcmp(keyword
, "CloseUI") && strcmp(keyword
, "CloseGroup") &&
555 strcmp(keyword
, "CloseSubGroup") && strncmp(keyword
, "Default", 7) &&
556 strcmp(keyword
, "JCLCloseUI") && strcmp(keyword
, "JCLOpenUI") &&
557 strcmp(keyword
, "OpenUI") && strcmp(keyword
, "OpenGroup") &&
558 strcmp(keyword
, "OpenSubGroup") && string
== NULL
)
561 * Need a string value!
564 ppd_status
= PPD_MISSING_VALUE
;
570 * Certain main keywords (as defined by the PPD spec) may be used
571 * without the usual OpenUI/CloseUI stuff. Presumably this is just
572 * so that Adobe wouldn't completely break compatibility with PPD
573 * files prior to v4.0 of the spec, but it is hopelessly
574 * inconsistent... Catch these main keywords and automatically
575 * create the corresponding option, as needed...
581 * Previous line was a UI keyword...
588 if (option
== NULL
&&
589 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
590 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
592 for (i
= 0; i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])); i
++)
593 if (!strcmp(keyword
, ui_keywords
[i
]))
596 if (i
< (int)(sizeof(ui_keywords
) / sizeof(ui_keywords
[0])))
599 * Create the option in the appropriate group...
604 DEBUG_printf(("**** FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!\n",
609 if (strcmp(keyword
, "Collate") && strcmp(keyword
, "Duplex") &&
610 strcmp(keyword
, "InputSlot") && strcmp(keyword
, "ManualFeed") &&
611 strcmp(keyword
, "MediaType") && strcmp(keyword
, "MediaColor") &&
612 strcmp(keyword
, "MediaWeight") && strcmp(keyword
, "OutputBin") &&
613 strcmp(keyword
, "OutputMode") && strcmp(keyword
, "OutputOrder") &&
614 strcmp(keyword
, "PageSize") && strcmp(keyword
, "PageRegion"))
615 group
= ppd_get_group(ppd
, "Extra",
616 cupsLangString(language
, CUPS_MSG_EXTRA
));
618 group
= ppd_get_group(ppd
, "General",
619 cupsLangString(language
, CUPS_MSG_GENERAL
));
624 DEBUG_printf(("Adding to group %s...\n", group
->text
));
625 option
= ppd_get_option(group
, keyword
);
629 option
= ppd_get_option(group
, keyword
);
633 ppd_status
= PPD_ALLOC_ERROR
;
639 * Now fill in the initial information for the option...
642 if (!strncmp(keyword
, "JCL", 3))
643 option
->section
= PPD_ORDER_JCL
;
645 option
->section
= PPD_ORDER_ANY
;
647 option
->order
= 10.0f
;
650 option
->ui
= PPD_UI_BOOLEAN
;
652 option
->ui
= PPD_UI_PICKONE
;
654 for (j
= 0; j
< ppd
->num_attrs
; j
++)
655 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
656 !strcmp(ppd
->attrs
[j
]->name
+ 7, keyword
) &&
657 ppd
->attrs
[j
]->value
)
659 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
660 option
->keyword
, ppd
->attrs
[j
]->value
));
661 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
662 sizeof(option
->defchoice
));
666 if (strcmp(keyword
, "PageSize") == 0)
667 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
),
668 sizeof(option
->text
));
669 else if (strcmp(keyword
, "MediaType") == 0)
670 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
),
671 sizeof(option
->text
));
672 else if (strcmp(keyword
, "InputSlot") == 0)
673 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
),
674 sizeof(option
->text
));
675 else if (strcmp(keyword
, "ColorModel") == 0)
676 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_OUTPUT_MODE
),
677 sizeof(option
->text
));
678 else if (strcmp(keyword
, "Resolution") == 0)
679 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_RESOLUTION
),
680 sizeof(option
->text
));
682 strlcpy(option
->text
, keyword
, sizeof(option
->text
));
686 if (strcmp(keyword
, "LanguageLevel") == 0)
687 ppd
->language_level
= atoi(string
);
688 else if (strcmp(keyword
, "LanguageEncoding") == 0)
689 ppd
->lang_encoding
= string
;
690 else if (strcmp(keyword
, "LanguageVersion") == 0)
691 ppd
->lang_version
= string
;
692 else if (strcmp(keyword
, "Manufacturer") == 0)
693 ppd
->manufacturer
= string
;
694 else if (strcmp(keyword
, "ModelName") == 0)
695 ppd
->modelname
= string
;
696 else if (strcmp(keyword
, "Protocols") == 0)
697 ppd
->protocols
= string
;
698 else if (strcmp(keyword
, "PCFileName") == 0)
699 ppd
->pcfilename
= string
;
700 else if (strcmp(keyword
, "NickName") == 0)
701 ppd
->nickname
= string
;
702 else if (strcmp(keyword
, "Product") == 0)
703 ppd
->product
= string
;
704 else if (strcmp(keyword
, "ShortNickName") == 0)
705 ppd
->shortnickname
= string
;
706 else if (strcmp(keyword
, "TTRasterizer") == 0)
707 ppd
->ttrasterizer
= string
;
708 else if (strcmp(keyword
, "JCLBegin") == 0)
710 ppd
->jcl_begin
= strdup(string
);
711 ppd_decode(ppd
->jcl_begin
); /* Decode quoted string */
713 else if (strcmp(keyword
, "JCLEnd") == 0)
715 ppd
->jcl_end
= strdup(string
);
716 ppd_decode(ppd
->jcl_end
); /* Decode quoted string */
718 else if (strcmp(keyword
, "JCLToPSInterpreter") == 0)
720 ppd
->jcl_ps
= strdup(string
);
721 ppd_decode(ppd
->jcl_ps
); /* Decode quoted string */
723 else if (strcmp(keyword
, "AccurateScreensSupport") == 0)
724 ppd
->accurate_screens
= strcmp(string
, "True") == 0;
725 else if (strcmp(keyword
, "ColorDevice") == 0)
726 ppd
->color_device
= strcmp(string
, "True") == 0;
727 else if (strcmp(keyword
, "ContoneOnly") == 0)
728 ppd
->contone_only
= strcmp(string
, "True") == 0;
729 else if (strcmp(keyword
, "cupsFlipDuplex") == 0)
730 ppd
->flip_duplex
= strcmp(string
, "True") == 0;
731 else if (strcmp(keyword
, "cupsManualCopies") == 0)
732 ppd
->manual_copies
= strcmp(string
, "True") == 0;
733 else if (strcmp(keyword
, "cupsModelNumber") == 0)
734 ppd
->model_number
= atoi(string
);
735 else if (strcmp(keyword
, "cupsColorProfile") == 0)
737 if (ppd
->num_profiles
== 0)
738 profile
= malloc(sizeof(ppd_profile_t
));
740 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
741 (ppd
->num_profiles
+ 1));
743 ppd
->profiles
= profile
;
744 profile
+= ppd
->num_profiles
;
745 ppd
->num_profiles
++;
747 memset(profile
, 0, sizeof(ppd_profile_t
));
748 strlcpy(profile
->resolution
, name
, sizeof(profile
->resolution
));
749 strlcpy(profile
->media_type
, text
, sizeof(profile
->media_type
));
750 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
752 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
753 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
754 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
755 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
756 profile
->matrix
[2] + 2);
758 else if (strcmp(keyword
, "cupsFilter") == 0)
760 if (ppd
->num_filters
== 0)
761 filter
= malloc(sizeof(char *));
763 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
769 ppd_status
= PPD_ALLOC_ERROR
;
774 ppd
->filters
= filter
;
775 filter
+= ppd
->num_filters
;
779 * Copy filter string and prevent it from being freed below...
785 else if (strcmp(keyword
, "Throughput") == 0)
786 ppd
->throughput
= atoi(string
);
787 else if (strcmp(keyword
, "Font") == 0)
790 * Add this font to the list of available fonts...
793 if (ppd
->num_fonts
== 0)
794 tempfonts
= (char **)malloc(sizeof(char *));
796 tempfonts
= (char **)realloc(ppd
->fonts
,
797 sizeof(char *) * (ppd
->num_fonts
+ 1));
799 if (tempfonts
== NULL
)
801 ppd_status
= PPD_ALLOC_ERROR
;
806 ppd
->fonts
= tempfonts
;
807 ppd
->fonts
[ppd
->num_fonts
] = strdup(name
);
810 else if (strcmp(keyword
, "ParamCustomPageSize") == 0)
812 if (strcmp(name
, "Width") == 0)
813 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
814 ppd
->custom_max
+ 0);
815 else if (strcmp(name
, "Height") == 0)
816 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
817 ppd
->custom_max
+ 1);
819 else if (strcmp(keyword
, "HWMargins") == 0)
820 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
821 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
822 ppd
->custom_margins
+ 3);
823 else if (strcmp(keyword
, "CustomPageSize") == 0 &&
824 strcmp(name
, "True") == 0)
826 DEBUG_puts("Processing CustomPageSize...");
828 if (!ppd
->variable_sizes
)
830 ppd
->variable_sizes
= 1;
833 * Add a "Custom" page size entry...
836 ppd_add_size(ppd
, "Custom");
839 * Add a "Custom" page size option...
842 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
847 DEBUG_puts("PageSize option not found for CustomPageSize...");
849 if ((temp
= ppd_get_group(ppd
, "General",
850 cupsLangString(language
,
851 CUPS_MSG_GENERAL
))) == NULL
)
853 DEBUG_puts("Unable to get general group!");
858 if ((option
= ppd_get_option(temp
, "PageSize")) == NULL
)
860 DEBUG_puts("Unable to get PageSize option!");
862 ppd_status
= PPD_ALLOC_ERROR
;
868 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
870 DEBUG_puts("Unable to add Custom choice!");
872 ppd_status
= PPD_ALLOC_ERROR
;
877 strlcpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
),
878 sizeof(choice
->text
));
882 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
884 DEBUG_puts("Unable to find PageSize option!");
886 ppd_status
= PPD_INTERNAL_ERROR
;
891 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
893 DEBUG_puts("Unable to find Custom choice!");
895 ppd_status
= PPD_INTERNAL_ERROR
;
900 choice
->code
= string
;
902 string
= NULL
; /* Don't add as an attribute below */
904 else if (strcmp(keyword
, "LandscapeOrientation") == 0)
906 if (strcmp(string
, "Minus90") == 0)
907 ppd
->landscape
= -90;
908 else if (strcmp(string
, "Plus90") == 0)
911 else if (strcmp(keyword
, "Emulators") == 0)
913 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
914 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
921 ppd
->num_emulations
= count
;
922 ppd
->emulations
= calloc(count
, sizeof(ppd_emul_t
));
924 for (i
= 0, sptr
= string
; i
< count
; i
++)
926 for (nameptr
= ppd
->emulations
[i
].name
;
927 *sptr
!= '\0' && *sptr
!= ' ';
929 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
938 else if (strncmp(keyword
, "StartEmulator_", 14) == 0)
942 for (i
= 0; i
< ppd
->num_emulations
; i
++)
943 if (strcmp(keyword
+ 14, ppd
->emulations
[i
].name
) == 0)
945 ppd
->emulations
[i
].start
= string
;
949 else if (strncmp(keyword
, "StopEmulator_", 13) == 0)
953 for (i
= 0; i
< ppd
->num_emulations
; i
++)
954 if (strcmp(keyword
+ 13, ppd
->emulations
[i
].name
) == 0)
956 ppd
->emulations
[i
].stop
= string
;
960 else if (strcmp(keyword
, "JobPatchFile") == 0)
962 if (ppd
->patches
== NULL
)
963 ppd
->patches
= strdup(string
);
966 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
970 ppd_status
= PPD_ALLOC_ERROR
;
977 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
980 else if (strcmp(keyword
, "OpenUI") == 0)
983 * Don't allow nesting of options...
986 if (option
&& ppd_conform
== PPD_CONFORM_STRICT
)
988 ppd_status
= PPD_NESTED_OPEN_UI
;
994 * Add an option record to the current sub-group, group, or file...
998 cups_strcpy(name
, name
+ 1); /* Eliminate leading asterisk */
1000 for (i
= strlen(name
) - 1; i
> 0 && isspace(name
[i
] & 255); i
--)
1001 name
[i
] = '\0'; /* Eliminate trailing spaces */
1003 DEBUG_printf(("OpenUI of %s in group %s...\n", name
,
1004 group
? group
->text
: "(null)"));
1006 if (subgroup
!= NULL
)
1007 option
= ppd_get_option(subgroup
, name
);
1008 else if (group
== NULL
)
1010 if (strcmp(name
, "Collate") && strcmp(name
, "Duplex") &&
1011 strcmp(name
, "InputSlot") && strcmp(name
, "ManualFeed") &&
1012 strcmp(name
, "MediaType") && strcmp(name
, "MediaColor") &&
1013 strcmp(name
, "MediaWeight") && strcmp(name
, "OutputBin") &&
1014 strcmp(name
, "OutputMode") && strcmp(name
, "OutputOrder") &&
1015 strcmp(name
, "PageSize") && strcmp(name
, "PageRegion"))
1016 group
= ppd_get_group(ppd
, "Extra",
1017 cupsLangString(language
, CUPS_MSG_EXTRA
));
1019 group
= ppd_get_group(ppd
, "General",
1020 cupsLangString(language
, CUPS_MSG_GENERAL
));
1025 DEBUG_printf(("Adding to group %s...\n", group
->text
));
1026 option
= ppd_get_option(group
, name
);
1030 option
= ppd_get_option(group
, name
);
1034 ppd_status
= PPD_ALLOC_ERROR
;
1040 * Now fill in the initial information for the option...
1043 if (string
&& strcmp(string
, "PickMany") == 0)
1044 option
->ui
= PPD_UI_PICKMANY
;
1045 else if (string
&& strcmp(string
, "Boolean") == 0)
1046 option
->ui
= PPD_UI_BOOLEAN
;
1047 else if (string
&& strcmp(string
, "PickOne") == 0)
1048 option
->ui
= PPD_UI_PICKONE
;
1049 else if (ppd_conform
== PPD_CONFORM_STRICT
)
1051 ppd_status
= PPD_BAD_OPEN_UI
;
1056 option
->ui
= PPD_UI_PICKONE
;
1058 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1059 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1060 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1061 ppd
->attrs
[j
]->value
)
1063 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1064 option
->keyword
, ppd
->attrs
[j
]->value
));
1065 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1066 sizeof(option
->defchoice
));
1072 strlcpy(option
->text
, text
, sizeof(option
->text
));
1073 ppd_fix(option
->text
);
1077 if (strcmp(name
, "PageSize") == 0)
1078 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
),
1079 sizeof(option
->text
));
1080 else if (strcmp(name
, "MediaType") == 0)
1081 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
),
1082 sizeof(option
->text
));
1083 else if (strcmp(name
, "InputSlot") == 0)
1084 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
),
1085 sizeof(option
->text
));
1086 else if (strcmp(name
, "ColorModel") == 0)
1087 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_OUTPUT_MODE
),
1088 sizeof(option
->text
));
1089 else if (strcmp(name
, "Resolution") == 0)
1090 strlcpy(option
->text
, cupsLangString(language
, CUPS_MSG_RESOLUTION
),
1091 sizeof(option
->text
));
1093 strlcpy(option
->text
, name
, sizeof(option
->text
));
1096 option
->section
= PPD_ORDER_ANY
;
1101 else if (strcmp(keyword
, "JCLOpenUI") == 0)
1104 * Don't allow nesting of options...
1107 if (option
&& ppd_conform
== PPD_CONFORM_STRICT
)
1109 ppd_status
= PPD_NESTED_OPEN_UI
;
1115 * Find the JCL group, and add if needed...
1118 group
= ppd_get_group(ppd
, "JCL", "JCL");
1124 * Add an option record to the current JCLs...
1128 cups_strcpy(name
, name
+ 1);
1130 option
= ppd_get_option(group
, name
);
1134 ppd_status
= PPD_ALLOC_ERROR
;
1140 * Now fill in the initial information for the option...
1143 if (string
&& strcmp(string
, "PickMany") == 0)
1144 option
->ui
= PPD_UI_PICKMANY
;
1145 else if (string
&& strcmp(string
, "Boolean") == 0)
1146 option
->ui
= PPD_UI_BOOLEAN
;
1147 else if (string
&& strcmp(string
, "PickOne") == 0)
1148 option
->ui
= PPD_UI_PICKONE
;
1151 ppd_status
= PPD_BAD_OPEN_UI
;
1156 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1157 if (!strncmp(ppd
->attrs
[j
]->name
, "Default", 7) &&
1158 !strcmp(ppd
->attrs
[j
]->name
+ 7, name
) &&
1159 ppd
->attrs
[j
]->value
)
1161 DEBUG_printf(("Setting Default%s to %s via attribute...\n",
1162 option
->keyword
, ppd
->attrs
[j
]->value
));
1163 strlcpy(option
->defchoice
, ppd
->attrs
[j
]->value
,
1164 sizeof(option
->defchoice
));
1168 strlcpy(option
->text
, text
, sizeof(option
->text
));
1170 option
->section
= PPD_ORDER_JCL
;
1176 else if (strcmp(keyword
, "CloseUI") == 0 ||
1177 strcmp(keyword
, "JCLCloseUI") == 0)
1184 else if (strcmp(keyword
, "OpenGroup") == 0)
1187 * Open a new group...
1192 ppd_status
= PPD_NESTED_OPEN_GROUP
;
1199 ppd_status
= PPD_BAD_OPEN_GROUP
;
1205 * Separate the group name from the text (name/text)...
1208 if ((sptr
= strchr(string
, '/')) != NULL
)
1214 * Fix up the text...
1221 * Find/add the group...
1224 group
= ppd_get_group(ppd
, string
, sptr
);
1232 else if (strcmp(keyword
, "CloseGroup") == 0)
1239 else if (strcmp(keyword
, "OrderDependency") == 0 ||
1240 strcmp(keyword
, "NonUIOrderDependency") == 0)
1242 if (sscanf(string
, "%f%40s%40s", &order
, name
, keyword
) != 3)
1244 ppd_status
= PPD_BAD_ORDER_DEPENDENCY
;
1249 if (keyword
[0] == '*')
1250 cups_strcpy(keyword
, keyword
+ 1);
1252 if (strcmp(name
, "ExitServer") == 0)
1253 section
= PPD_ORDER_EXIT
;
1254 else if (strcmp(name
, "Prolog") == 0)
1255 section
= PPD_ORDER_PROLOG
;
1256 else if (strcmp(name
, "DocumentSetup") == 0)
1257 section
= PPD_ORDER_DOCUMENT
;
1258 else if (strcmp(name
, "PageSetup") == 0)
1259 section
= PPD_ORDER_PAGE
;
1260 else if (strcmp(name
, "JCLSetup") == 0)
1261 section
= PPD_ORDER_JCL
;
1263 section
= PPD_ORDER_ANY
;
1271 * Only valid for Non-UI options...
1274 for (i
= ppd
->num_groups
, temp
= ppd
->groups
; i
> 0; i
--, temp
++)
1275 if (temp
->text
[0] == '\0')
1279 for (i
= 0; i
< temp
->num_options
; i
++)
1280 if (strcmp(keyword
, temp
->options
[i
].keyword
) == 0)
1282 temp
->options
[i
].section
= section
;
1283 temp
->options
[i
].order
= order
;
1289 option
->section
= section
;
1290 option
->order
= order
;
1296 else if (strncmp(keyword
, "Default", 7) == 0)
1302 * Drop UI text, if any, from value...
1305 if (strchr(string
, '/') != NULL
)
1306 *strchr(string
, '/') = '\0';
1309 * Assign the default value as appropriate...
1312 if (strcmp(keyword
, "DefaultColorSpace") == 0)
1315 * Set default colorspace...
1318 if (strcmp(string
, "CMY") == 0)
1319 ppd
->colorspace
= PPD_CS_CMY
;
1320 else if (strcmp(string
, "CMYK") == 0)
1321 ppd
->colorspace
= PPD_CS_CMYK
;
1322 else if (strcmp(string
, "RGB") == 0)
1323 ppd
->colorspace
= PPD_CS_RGB
;
1324 else if (strcmp(string
, "RGBK") == 0)
1325 ppd
->colorspace
= PPD_CS_RGBK
;
1326 else if (strcmp(string
, "N") == 0)
1327 ppd
->colorspace
= PPD_CS_N
;
1329 ppd
->colorspace
= PPD_CS_GRAY
;
1331 else if (option
&& strcmp(keyword
+ 7, option
->keyword
) == 0)
1334 * Set the default as part of the current option...
1337 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1339 strlcpy(option
->defchoice
, string
, sizeof(option
->defchoice
));
1341 DEBUG_printf(("%s is now %s...\n", keyword
, option
->defchoice
));
1346 * Lookup option and set if it has been defined...
1349 ppd_option_t
*toption
; /* Temporary option */
1352 if ((toption
= ppdFindOption(ppd
, keyword
+ 7)) != NULL
)
1354 DEBUG_printf(("Setting %s to %s...\n", keyword
, string
));
1355 strlcpy(toption
->defchoice
, string
, sizeof(toption
->defchoice
));
1359 else if (strcmp(keyword
, "UIConstraints") == 0 ||
1360 strcmp(keyword
, "NonUIConstraints") == 0)
1362 if (ppd
->num_consts
== 0)
1363 constraint
= calloc(1, sizeof(ppd_const_t
));
1365 constraint
= realloc(ppd
->consts
,
1366 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1368 if (constraint
== NULL
)
1370 ppd_status
= PPD_ALLOC_ERROR
;
1375 ppd
->consts
= constraint
;
1376 constraint
+= ppd
->num_consts
;
1379 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1380 constraint
->choice1
, constraint
->option2
,
1381 constraint
->choice2
))
1383 case 0 : /* Error */
1384 case 1 : /* Error */
1385 ppd_status
= PPD_BAD_UI_CONSTRAINTS
;
1388 case 2 : /* Two options... */
1390 * The following strcpy's are safe, as optionN and
1391 * choiceN are all the same size (size defined by PPD spec...)
1394 if (constraint
->option1
[0] == '*')
1395 cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1397 if (constraint
->choice1
[0] == '*')
1398 cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1400 cups_strcpy(constraint
->option2
, constraint
->choice1
);
1402 constraint
->choice1
[0] = '\0';
1403 constraint
->choice2
[0] = '\0';
1406 case 3 : /* Two options, one choice... */
1408 * The following cups_strcpy's are safe, as optionN and
1409 * choiceN are all the same size (size defined by PPD spec...)
1412 if (constraint
->option1
[0] == '*')
1413 cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1415 if (constraint
->choice1
[0] == '*')
1417 cups_strcpy(constraint
->choice2
, constraint
->option2
);
1418 cups_strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1419 constraint
->choice1
[0] = '\0';
1423 if (constraint
->option2
[0] == '*')
1424 cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1426 constraint
->choice2
[0] = '\0';
1430 case 4 : /* Two options, two choices... */
1431 if (constraint
->option1
[0] == '*')
1432 cups_strcpy(constraint
->option1
, constraint
->option1
+ 1);
1434 if (constraint
->option2
[0] == '*')
1435 cups_strcpy(constraint
->option2
, constraint
->option2
+ 1);
1442 else if (strcmp(keyword
, "PaperDimension") == 0)
1444 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1445 size
= ppd_add_size(ppd
, name
);
1450 * Unable to add or find size!
1453 ppd_status
= PPD_ALLOC_ERROR
;
1458 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1463 else if (strcmp(keyword
, "ImageableArea") == 0)
1465 if ((size
= ppdPageSize(ppd
, name
)) == NULL
)
1466 size
= ppd_add_size(ppd
, name
);
1471 * Unable to add or find size!
1474 ppd_status
= PPD_ALLOC_ERROR
;
1479 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1480 &(size
->right
), &(size
->top
));
1485 else if (option
!= NULL
&&
1486 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1487 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
) &&
1488 strcmp(keyword
, option
->keyword
) == 0)
1490 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1492 if (strcmp(keyword
, "PageSize") == 0)
1495 * Add a page size...
1498 if (ppdPageSize(ppd
, name
) == NULL
)
1499 ppd_add_size(ppd
, name
);
1503 * Add the option choice...
1506 choice
= ppd_add_choice(option
, name
);
1508 if (mask
& PPD_TEXT
)
1510 strlcpy(choice
->text
, text
, sizeof(choice
->text
));
1511 ppd_fix(choice
->text
);
1513 else if (strcmp(name
, "True") == 0)
1514 strcpy(choice
->text
, "Yes");
1515 else if (strcmp(name
, "False") == 0)
1516 strcpy(choice
->text
, "No");
1518 strlcpy(choice
->text
, name
, sizeof(choice
->text
));
1520 if (option
->section
== PPD_ORDER_JCL
)
1521 ppd_decode(string
); /* Decode quoted string */
1523 choice
->code
= string
;
1524 string
= NULL
; /* Don't add as an attribute below */
1527 else if (strcmp(keyword
, "cupsUIType") == 0 &&
1528 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1532 * Define an extended option value type...
1535 extopt
= ppd_get_extoption(ppd
, name
);
1537 if (strcmp(string
, "Text") == 0)
1538 option
->ui
= PPD_UI_CUPS_TEXT
;
1539 else if (strcmp(string
, "Integer") == 0)
1541 option
->ui
= PPD_UI_CUPS_INTEGER
;
1542 extopt
->defval
.integer
= 0;
1543 extopt
->minval
.integer
= 0;
1544 extopt
->maxval
.integer
= 100;
1546 else if (strcmp(string
, "Real") == 0)
1548 option
->ui
= PPD_UI_CUPS_REAL
;
1549 extopt
->defval
.real
= 0.0;
1550 extopt
->minval
.real
= 0.0;
1551 extopt
->maxval
.real
= 1.0;
1553 else if (strcmp(string
, "Gamma") == 0)
1555 option
->ui
= PPD_UI_CUPS_GAMMA
;
1556 extopt
->defval
.gamma
= 1.0;
1557 extopt
->minval
.gamma
= 1.0;
1558 extopt
->maxval
.gamma
= 10.0;
1560 else if (strcmp(string
, "Curve") == 0)
1562 option
->ui
= PPD_UI_CUPS_CURVE
;
1563 extopt
->defval
.curve
.start
= 0.0;
1564 extopt
->defval
.curve
.end
= 0.0;
1565 extopt
->defval
.curve
.gamma
= 1.0;
1566 extopt
->minval
.curve
.start
= 0.0;
1567 extopt
->minval
.curve
.end
= 0.0;
1568 extopt
->minval
.curve
.gamma
= 1.0;
1569 extopt
->maxval
.curve
.start
= 1.0;
1570 extopt
->maxval
.curve
.end
= 1.0;
1571 extopt
->maxval
.curve
.gamma
= 10.0;
1573 else if (strcmp(string
, "IntegerArray") == 0)
1575 option
->ui
= PPD_UI_CUPS_INTEGER_ARRAY
;
1576 extopt
->defval
.integer_array
.num_elements
= 2;
1577 extopt
->minval
.integer_array
.num_elements
= 2;
1578 extopt
->maxval
.integer_array
.num_elements
= 16;
1580 else if (strcmp(string
, "RealArray") == 0)
1582 option
->ui
= PPD_UI_CUPS_REAL_ARRAY
;
1583 extopt
->defval
.real_array
.num_elements
= 2;
1584 extopt
->minval
.real_array
.num_elements
= 2;
1585 extopt
->maxval
.real_array
.num_elements
= 16;
1588 else if (strcmp(keyword
, "cupsUIDefault") == 0 &&
1589 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1593 * Define an extended option minimum value...
1596 extopt
= ppd_get_extoption(ppd
, name
);
1600 case PPD_UI_CUPS_INTEGER
:
1601 sscanf(string
, "%d", &(extopt
->defval
.integer
));
1604 case PPD_UI_CUPS_REAL
:
1605 sscanf(string
, "%f", &(extopt
->defval
.real
));
1608 case PPD_UI_CUPS_GAMMA
:
1609 sscanf(string
, "%f", &(extopt
->defval
.gamma
));
1612 case PPD_UI_CUPS_CURVE
:
1613 sscanf(string
, "%f%f%f", &(extopt
->defval
.curve
.start
),
1614 &(extopt
->defval
.curve
.end
),
1615 &(extopt
->defval
.curve
.gamma
));
1618 case PPD_UI_CUPS_INTEGER_ARRAY
:
1619 extopt
->defval
.integer_array
.elements
= calloc(1, sizeof(int));
1620 sscanf(string
, "%d%d", &(extopt
->defval
.integer_array
.num_elements
),
1621 extopt
->defval
.integer_array
.elements
);
1624 case PPD_UI_CUPS_REAL_ARRAY
:
1625 extopt
->defval
.real_array
.elements
= calloc(1, sizeof(float));
1626 sscanf(string
, "%d%f", &(extopt
->defval
.real_array
.num_elements
),
1627 extopt
->defval
.real_array
.elements
);
1634 else if (strcmp(keyword
, "cupsUIMinimum") == 0 &&
1635 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1639 * Define an extended option minimum value...
1642 extopt
= ppd_get_extoption(ppd
, name
);
1646 case PPD_UI_CUPS_INTEGER
:
1647 sscanf(string
, "%d", &(extopt
->minval
.integer
));
1650 case PPD_UI_CUPS_REAL
:
1651 sscanf(string
, "%f", &(extopt
->minval
.real
));
1654 case PPD_UI_CUPS_GAMMA
:
1655 sscanf(string
, "%f", &(extopt
->minval
.gamma
));
1658 case PPD_UI_CUPS_CURVE
:
1659 sscanf(string
, "%f%f%f", &(extopt
->minval
.curve
.start
),
1660 &(extopt
->minval
.curve
.end
),
1661 &(extopt
->minval
.curve
.gamma
));
1664 case PPD_UI_CUPS_INTEGER_ARRAY
:
1665 extopt
->minval
.integer_array
.elements
= calloc(1, sizeof(int));
1666 sscanf(string
, "%d%d", &(extopt
->minval
.integer_array
.num_elements
),
1667 extopt
->minval
.integer_array
.elements
);
1670 case PPD_UI_CUPS_REAL_ARRAY
:
1671 extopt
->minval
.real_array
.elements
= calloc(1, sizeof(float));
1672 sscanf(string
, "%d%f", &(extopt
->minval
.real_array
.num_elements
),
1673 extopt
->minval
.real_array
.elements
);
1680 else if (strcmp(keyword
, "cupsUIMaximum") == 0 &&
1681 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1685 * Define an extended option maximum value...
1688 extopt
= ppd_get_extoption(ppd
, name
);
1692 case PPD_UI_CUPS_INTEGER
:
1693 sscanf(string
, "%d", &(extopt
->maxval
.integer
));
1696 case PPD_UI_CUPS_REAL
:
1697 sscanf(string
, "%f", &(extopt
->maxval
.real
));
1700 case PPD_UI_CUPS_GAMMA
:
1701 sscanf(string
, "%f", &(extopt
->maxval
.gamma
));
1704 case PPD_UI_CUPS_CURVE
:
1705 sscanf(string
, "%f%f%f", &(extopt
->maxval
.curve
.start
),
1706 &(extopt
->maxval
.curve
.end
),
1707 &(extopt
->maxval
.curve
.gamma
));
1710 case PPD_UI_CUPS_INTEGER_ARRAY
:
1711 extopt
->maxval
.integer_array
.elements
= calloc(1, sizeof(int));
1712 sscanf(string
, "%d%d", &(extopt
->maxval
.integer_array
.num_elements
),
1713 extopt
->maxval
.integer_array
.elements
);
1716 case PPD_UI_CUPS_REAL_ARRAY
:
1717 extopt
->maxval
.real_array
.elements
= calloc(1, sizeof(float));
1718 sscanf(string
, "%d%f", &(extopt
->maxval
.real_array
.num_elements
),
1719 extopt
->maxval
.real_array
.elements
);
1726 else if (strcmp(keyword
, "cupsUICommand") == 0 &&
1727 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
) &&
1731 * Define an extended option command...
1734 extopt
= ppd_get_extoption(ppd
, name
);
1736 extopt
->command
= string
;
1742 * Add remaining lines with keywords and string values as attributes...
1746 (mask
& (PPD_KEYWORD
| PPD_STRING
)) == (PPD_KEYWORD
| PPD_STRING
))
1747 ppd_add_attr(ppd
, keyword
, name
, text
, string
);
1755 * Reset language preferences...
1758 cupsLangFree(language
);
1761 _cupsRestoreLocale(LC_NUMERIC
, oldlocale
);
1763 _cupsRestoreLocale(LC_ALL
, oldlocale
);
1764 #endif /* LC_NUMERIC */
1768 printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp
));
1771 if (ppd_status
!= PPD_OK
)
1774 * Had an error reading the PPD file, cannot continue!
1784 * Make sure that all PPD files with an InputSlot option have an
1785 * "auto" choice that maps to no specific tray or media type.
1788 if ((option
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1790 for (i
= 0; i
< option
->num_choices
; i
++)
1791 if (option
->choices
[i
].code
== NULL
|| !option
->choices
[i
].code
[0] ||
1792 !strncasecmp(option
->choices
[i
].choice
, "Auto", 4))
1795 if (i
>= option
->num_choices
)
1798 * No "auto" input slot, add one...
1801 choice
= ppd_add_choice(option
, "Auto");
1803 strlcpy(choice
->text
, cupsLangString(language
, CUPS_MSG_AUTO
),
1804 sizeof(choice
->text
));
1805 choice
->code
= NULL
;
1808 #endif /* !__APPLE__ */
1811 * Set the option back-pointer for each choice...
1815 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1816 (int (*)(const void *, const void *))ppd_compare_groups
);
1817 #endif /* !__APPLE__ */
1819 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1824 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1825 (int (*)(const void *, const void *))ppd_compare_options
);
1826 #endif /* !__APPLE__ */
1828 for (j
= group
->num_options
, option
= group
->options
;
1832 for (k
= 0; k
< option
->num_choices
; k
++)
1833 option
->choices
[k
].option
= (void *)option
;
1837 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1838 (int (*)(const void *, const void *))ppd_compare_groups
);
1839 #endif /* !__APPLE__ */
1841 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1846 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1847 (int (*)(const void *, const void *))ppd_compare_options
);
1848 #endif /* !__APPLE__ */
1850 for (k
= group
->num_options
, option
= group
->options
;
1854 for (m
= 0; m
< option
->num_choices
; m
++)
1855 option
->choices
[m
].option
= (void *)option
;
1861 * Set the option pointers for all extended options...
1864 for (i
= 0; i
< ppd
->num_extended
; i
++)
1865 ppd
->extended
[i
]->option
= ppdFindOption(ppd
, ppd
->extended
[i
]->keyword
);
1868 * Sort the attributes...
1871 if (ppd
->num_attrs
> 1)
1872 qsort(ppd
->attrs
, ppd
->num_attrs
, sizeof(ppd_attr_t
*),
1873 (int (*)(const void *, const void *))_ppd_attr_compare
);
1876 * Return the PPD file structure...
1882 * Common exit point for errors to save code size...
1891 cupsLangFree(language
);
1894 _cupsRestoreLocale(LC_NUMERIC
, oldlocale
);
1896 _cupsRestoreLocale(LC_ALL
, oldlocale
);
1897 #endif /* LC_NUMERIC */
1904 * 'ppdOpenFd()' - Read a PPD file into memory.
1907 ppd_file_t
* /* O - PPD file record */
1908 ppdOpenFd(int fd
) /* I - File to read from */
1910 FILE *fp
; /* File pointer */
1911 ppd_file_t
*ppd
; /* PPD file record */
1915 * Set the line number to 0...
1921 * Range check input...
1926 ppd_status
= PPD_NULL_FILE
;
1932 * Try to open the file and parse it...
1935 if ((fp
= fdopen(fd
, "r")) != NULL
)
1945 ppd_status
= PPD_FILE_OPEN_ERROR
;
1954 * 'ppdOpenFile()' - Read a PPD file into memory.
1957 ppd_file_t
* /* O - PPD file record */
1958 ppdOpenFile(const char *filename
) /* I - File to read from */
1960 FILE *fp
; /* File pointer */
1961 ppd_file_t
*ppd
; /* PPD file record */
1965 * Set the line number to 0...
1971 * Range check input...
1974 if (filename
== NULL
)
1976 ppd_status
= PPD_NULL_FILE
;
1982 * Try to open the file and parse it...
1985 if ((fp
= fopen(filename
, "r")) != NULL
)
1993 ppd_status
= PPD_FILE_OPEN_ERROR
;
2002 * 'ppdSetConformance()' - Set the conformance level for PPD files.
2006 ppdSetConformance(ppd_conform_t c
) /* I - Conformance level */
2013 * 'ppd_add_attr()' - Add an attribute to the PPD data.
2016 static ppd_attr_t
* /* O - New attribute */
2017 ppd_add_attr(ppd_file_t
*ppd
, /* I - PPD file data */
2018 const char *name
, /* I - Attribute name */
2019 const char *spec
, /* I - Specifier string, if any */
2020 const char *text
, /* I - Text string, if any */
2021 const char *value
) /* I - Value of attribute */
2023 ppd_attr_t
**ptr
, /* New array */
2024 *temp
; /* New attribute */
2028 * Range check input...
2031 if (ppd
== NULL
|| name
== NULL
|| spec
== NULL
)
2035 * Allocate memory for the new attribute...
2038 if (ppd
->num_attrs
== 0)
2039 ptr
= malloc(sizeof(ppd_attr_t
*));
2041 ptr
= realloc(ppd
->attrs
, (ppd
->num_attrs
+ 1) * sizeof(ppd_attr_t
*));
2047 ptr
+= ppd
->num_attrs
;
2049 if ((temp
= calloc(1, sizeof(ppd_attr_t
))) == NULL
)
2060 strlcpy(temp
->name
, name
, sizeof(temp
->name
));
2061 strlcpy(temp
->spec
, spec
, sizeof(temp
->spec
));
2062 strlcpy(temp
->text
, text
, sizeof(temp
->text
));
2063 temp
->value
= (char *)value
;
2066 * Return the attribute...
2074 * 'ppd_add_choice()' - Add a choice to an option.
2077 static ppd_choice_t
* /* O - Named choice */
2078 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
2079 const char *name
) /* I - Name of choice */
2081 ppd_choice_t
*choice
; /* Choice */
2084 if (option
->num_choices
== 0)
2085 choice
= malloc(sizeof(ppd_choice_t
));
2087 choice
= realloc(option
->choices
,
2088 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
2093 option
->choices
= choice
;
2094 choice
+= option
->num_choices
;
2095 option
->num_choices
++;
2097 memset(choice
, 0, sizeof(ppd_choice_t
));
2098 strlcpy(choice
->choice
, name
, sizeof(choice
->choice
));
2105 * 'ppd_add_size()' - Add a page size.
2108 static ppd_size_t
* /* O - Named size */
2109 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
2110 const char *name
) /* I - Name of size */
2112 ppd_size_t
*size
; /* Size */
2115 if (ppd
->num_sizes
== 0)
2116 size
= malloc(sizeof(ppd_size_t
));
2118 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
2124 size
+= ppd
->num_sizes
;
2127 memset(size
, 0, sizeof(ppd_size_t
));
2128 strlcpy(size
->name
, name
, sizeof(size
->name
));
2136 * 'ppd_compare_groups()' - Compare two groups.
2139 static int /* O - Result of comparison */
2140 ppd_compare_groups(ppd_group_t
*g0
, /* I - First group */
2141 ppd_group_t
*g1
) /* I - Second group */
2143 return (strcasecmp(g0
->text
, g1
->text
));
2148 * 'ppd_compare_options()' - Compare two options.
2151 static int /* O - Result of comparison */
2152 ppd_compare_options(ppd_option_t
*o0
, /* I - First option */
2153 ppd_option_t
*o1
) /* I - Second option */
2155 return (strcasecmp(o0
->text
, o1
->text
));
2157 #endif /* !__APPLE__ */
2161 * 'ppd_decode()' - Decode a string value...
2164 static int /* O - Length of decoded string */
2165 ppd_decode(char *string
) /* I - String to decode */
2167 char *inptr
, /* Input pointer */
2168 *outptr
; /* Output pointer */
2174 while (*inptr
!= '\0')
2175 if (*inptr
== '<' && isxdigit(inptr
[1] & 255))
2178 * Convert hex to 8-bit values...
2182 while (isxdigit(*inptr
& 255))
2184 if (isalpha(*inptr
))
2185 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
2187 *outptr
= (*inptr
- '0') << 4;
2191 if (!isxdigit(*inptr
& 255))
2194 if (isalpha(*inptr
))
2195 *outptr
|= tolower(*inptr
) - 'a' + 10;
2197 *outptr
|= *inptr
- '0';
2203 while (*inptr
!= '>' && *inptr
!= '\0')
2205 while (*inptr
== '>')
2209 *outptr
++ = *inptr
++;
2213 return (outptr
- string
);
2219 * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be
2220 * valid ISO-8859-1 characters...
2224 ppd_fix(char *string
) /* IO - String to fix */
2226 unsigned char *p
; /* Pointer into string */
2227 static const unsigned char lut
[32] = /* Lookup table for characters */
2251 0x20, /* circumflex */
2253 0x20, /* double dot */
2258 '\"', /* should be right quotes */
2264 for (p
= (unsigned char *)string
; *p
; p
++)
2265 if (*p
>= 0x80 && *p
< 0xa0)
2266 *p
= lut
[*p
- 0x80];
2268 #endif /* !__APPLE__ */
2272 * 'ppd_free_group()' - Free a single UI group.
2276 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
2278 int i
; /* Looping var */
2279 ppd_option_t
*option
; /* Current option */
2280 ppd_group_t
*subgroup
; /* Current sub-group */
2283 if (group
->num_options
> 0)
2285 for (i
= group
->num_options
, option
= group
->options
;
2288 ppd_free_option(option
);
2290 ppd_free(group
->options
);
2293 if (group
->num_subgroups
> 0)
2295 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
2298 ppd_free_group(subgroup
);
2300 ppd_free(group
->subgroups
);
2306 * 'ppd_free_option()' - Free a single option.
2310 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
2312 int i
; /* Looping var */
2313 ppd_choice_t
*choice
; /* Current choice */
2316 if (option
->num_choices
> 0)
2318 for (i
= option
->num_choices
, choice
= option
->choices
;
2322 ppd_free(choice
->code
);
2325 ppd_free(option
->choices
);
2331 * 'ppd_get_extoption()' - Get an extended option record.
2334 static ppd_ext_option_t
* /* O - Extended option... */
2335 ppd_get_extoption(ppd_file_t
*ppd
, /* I - PPD file */
2336 const char *name
) /* I - Name of option */
2338 ppd_ext_option_t
**temp
, /* New array pointer */
2339 *extopt
; /* New extended option */
2343 * See if the option already exists...
2346 if ((extopt
= ppdFindExtOption(ppd
, name
)) != NULL
)
2350 * Not found, so create the extended option record...
2353 if ((extopt
= calloc(1, sizeof(ppd_ext_option_t
))) == NULL
)
2356 strlcpy(extopt
->keyword
, name
, sizeof(extopt
->keyword
));
2359 * Add this record to the end of the array...
2362 if (ppd
->num_extended
== 0)
2363 temp
= malloc(sizeof(ppd_ext_option_t
*));
2365 temp
= realloc(ppd
->extended
, sizeof(ppd_ext_option_t
*) *
2366 (ppd
->num_extended
+ 1));
2374 ppd
->extended
= temp
;
2375 temp
[ppd
->num_extended
] = extopt
;
2377 ppd
->num_extended
++;
2380 * Return the new record...
2388 * 'ppd_get_extparam()' - Get an extended parameter record.
2391 static ppd_ext_param_t
* /* O - Extended option... */
2392 ppd_get_extparam(ppd_ext_option_t
*opt
, /* I - PPD file */
2393 const char *param
,/* I - Name of parameter */
2394 const char *text
) /* I - Human-readable text */
2396 ppd_ext_param_t
**temp
, /* New array pointer */
2397 *extparam
; /* New extended parameter */
2401 * See if the parameter already exists...
2404 if ((extparam
= ppdFindExtParam(opt
, param
)) != NULL
)
2408 * Not found, so create the extended parameter record...
2411 if ((extparam
= calloc(1, sizeof(ppd_ext_param_t
))) == NULL
)
2414 if ((extparam
->value
= calloc(4, sizeof(ppd_ext_value_t
))) == NULL
)
2420 extparam
->defval
= extparam
->value
+ 1;
2421 extparam
->minval
= extparam
->value
+ 2;
2422 extparam
->maxval
= extparam
->value
+ 3;
2424 strlcpy(extparam
->keyword
, param
, sizeof(extparam
->keyword
));
2425 strlcpy(extparam
->text
, text
, sizeof(extparam
->text
));
2428 * Add this record to the end of the array...
2431 if (opt
->num_params
== 0)
2432 temp
= malloc(sizeof(ppd_ext_param_t
*));
2434 temp
= realloc(opt
->params
, sizeof(ppd_ext_param_t
*) *
2435 (opt
->num_params
+ 1));
2444 temp
[opt
->num_params
] = extparam
;
2449 * Return the new record...
2457 * 'ppd_get_group()' - Find or create the named group as needed.
2460 static ppd_group_t
* /* O - Named group */
2461 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
2462 const char *name
, /* I - Name of group */
2463 const char *text
) /* I - Text for group */
2465 int i
; /* Looping var */
2466 ppd_group_t
*group
; /* Group */
2469 DEBUG_printf(("ppd_get_group(%p, \"%s\")\n", ppd
, name
));
2471 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
2472 if (strcmp(group
->name
, name
) == 0)
2477 DEBUG_printf(("Adding group %s...\n", name
));
2479 if (ppd_conform
== PPD_CONFORM_STRICT
&& strlen(text
) >= sizeof(group
->text
))
2481 ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2486 if (ppd
->num_groups
== 0)
2487 group
= malloc(sizeof(ppd_group_t
));
2489 group
= realloc(ppd
->groups
,
2490 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
2494 ppd_status
= PPD_ALLOC_ERROR
;
2499 ppd
->groups
= group
;
2500 group
+= ppd
->num_groups
;
2503 memset(group
, 0, sizeof(ppd_group_t
));
2504 strlcpy(group
->name
, name
, sizeof(group
->name
));
2505 strlcpy(group
->text
, text
, sizeof(group
->text
));
2513 * 'ppd_get_option()' - Find or create the named option as needed.
2516 static ppd_option_t
* /* O - Named option */
2517 ppd_get_option(ppd_group_t
*group
, /* I - Group */
2518 const char *name
) /* I - Name of option */
2520 int i
; /* Looping var */
2521 ppd_option_t
*option
; /* Option */
2524 DEBUG_printf(("ppd_get_option(group=%p(\"%s\"), name=\"%s\")\n",
2525 group
, group
->name
, name
));
2527 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
2528 if (strcmp(option
->keyword
, name
) == 0)
2533 if (group
->num_options
== 0)
2534 option
= malloc(sizeof(ppd_option_t
));
2536 option
= realloc(group
->options
,
2537 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
2542 group
->options
= option
;
2543 option
+= group
->num_options
;
2544 group
->num_options
++;
2546 memset(option
, 0, sizeof(ppd_option_t
));
2547 strlcpy(option
->keyword
, name
, sizeof(option
->keyword
));
2555 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2559 static int /* O - Bitmask of fields read */
2560 ppd_read(FILE *fp
, /* I - File to read from */
2561 char *keyword
, /* O - Keyword from line */
2562 char *option
, /* O - Option from line */
2563 char *text
, /* O - Human-readable text from line */
2564 char **string
, /* O - Code/string data */
2565 int ignoreblank
) /* I - Ignore blank lines? */
2567 int ch
, /* Character from file */
2568 col
, /* Column in line */
2569 colon
, /* Colon seen? */
2570 endquote
, /* Waiting for an end quote */
2571 mask
, /* Mask to be returned */
2572 startline
, /* Start line */
2573 textlen
; /* Length of text */
2574 char *keyptr
, /* Keyword pointer */
2575 *optptr
, /* Option pointer */
2576 *textptr
, /* Text pointer */
2577 *strptr
, /* Pointer into string */
2578 *lineptr
, /* Current position in line buffer */
2579 line
[65536]; /* Line buffer (64k) */
2583 * Range check everything...
2586 if (fp
== NULL
|| keyword
== NULL
|| option
== NULL
|| text
== NULL
||
2591 * Now loop until we have a valid line...
2596 startline
= ppd_line
+ 1;
2608 while ((ch
= getc(fp
)) != EOF
&&
2609 (lineptr
- line
) < (sizeof(line
) - 1))
2611 if (ch
== '\r' || ch
== '\n')
2614 * Line feed or carriage return...
2623 * Check for a trailing line feed...
2626 if ((ch
= getc(fp
)) == EOF
)
2632 if (lineptr
== line
&& ignoreblank
)
2633 continue; /* Skip blank lines */
2637 if (!endquote
) /* Continue for multi-line text */
2642 else if (ch
< ' ' && ch
!= '\t' && ppd_conform
== PPD_CONFORM_STRICT
)
2645 * Other control characters...
2648 ppd_line
= startline
;
2649 ppd_status
= PPD_ILLEGAL_CHARACTER
;
2653 else if (ch
!= 0x1a)
2656 * Any other character...
2662 if (col
> (PPD_MAX_LINE
- 1))
2665 * Line is too long...
2668 ppd_line
= startline
;
2669 ppd_status
= PPD_LINE_TOO_LONG
;
2674 if (ch
== ':' && strncmp(line
, "*%", 2) != 0)
2677 if (ch
== '\"' && colon
)
2678 endquote
= !endquote
;
2685 * Didn't finish this quoted string...
2688 while ((ch
= getc(fp
)) != EOF
)
2691 else if (ch
== '\r' || ch
== '\n')
2699 * Check for a trailing line feed...
2702 if ((ch
= getc(fp
)) == EOF
)
2710 else if (ch
< ' ' && ch
!= '\t' && ppd_conform
== PPD_CONFORM_STRICT
)
2713 * Other control characters...
2716 ppd_line
= startline
;
2717 ppd_status
= PPD_ILLEGAL_CHARACTER
;
2721 else if (ch
!= 0x1a)
2725 if (col
> (PPD_MAX_LINE
- 1))
2728 * Line is too long...
2731 ppd_line
= startline
;
2732 ppd_status
= PPD_LINE_TOO_LONG
;
2742 * Didn't finish this line...
2745 while ((ch
= getc(fp
)) != EOF
)
2746 if (ch
== '\r' || ch
== '\n')
2749 * Line feed or carriage return...
2758 * Check for a trailing line feed...
2761 if ((ch
= getc(fp
)) == EOF
)
2769 else if (ch
< ' ' && ch
!= '\t' && ppd_conform
== PPD_CONFORM_STRICT
)
2772 * Other control characters...
2775 ppd_line
= startline
;
2776 ppd_status
= PPD_ILLEGAL_CHARACTER
;
2780 else if (ch
!= 0x1a)
2784 if (col
> (PPD_MAX_LINE
- 1))
2787 * Line is too long...
2790 ppd_status
= PPD_LINE_TOO_LONG
;
2797 if (lineptr
> line
&& lineptr
[-1] == '\n')
2802 DEBUG_printf(("LINE = \"%s\"\n", line
));
2804 if (ch
== EOF
&& lineptr
== line
)
2819 if ((!line
[0] || /* Blank line */
2820 strncmp(line
, "*%", 2) == 0 || /* Comment line */
2821 strcmp(line
, "*End") == 0) && /* End of multi-line string */
2822 ignoreblank
) /* Ignore these? */
2824 startline
= ppd_line
+ 1;
2828 if (strcmp(line
, "*") == 0) /* (Bad) comment line */
2830 if (ppd_conform
== PPD_CONFORM_RELAXED
)
2832 startline
= ppd_line
+ 1;
2837 ppd_line
= startline
;
2838 ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2844 if (line
[0] != '*') /* All lines start with an asterisk */
2846 if (ppd_conform
== PPD_CONFORM_STRICT
)
2848 ppd_status
= PPD_MISSING_ASTERISK
;
2853 * Allow lines consisting of just whitespace...
2856 for (lineptr
= line
; *lineptr
; lineptr
++)
2857 if (!isspace(*lineptr
& 255))
2862 ppd_status
= PPD_MISSING_ASTERISK
;
2865 else if (ignoreblank
)
2877 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
& 255))
2879 if (*lineptr
<= ' ' || *lineptr
> 126 || *lineptr
== '/' ||
2880 (keyptr
- keyword
) >= (PPD_MAX_NAME
- 1))
2882 ppd_status
= PPD_ILLEGAL_MAIN_KEYWORD
;
2886 *keyptr
++ = *lineptr
++;
2891 if (strcmp(keyword
, "End") == 0)
2894 mask
|= PPD_KEYWORD
;
2896 /* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/
2898 if (isspace(*lineptr
& 255))
2901 * Get an option name...
2904 while (isspace(*lineptr
& 255))
2909 while (*lineptr
!= '\0' && !isspace(*lineptr
& 255) && *lineptr
!= ':' &&
2912 if (*lineptr
<= ' ' || *lineptr
> 126 ||
2913 (optptr
- option
) >= (PPD_MAX_NAME
- 1))
2915 ppd_status
= PPD_ILLEGAL_OPTION_KEYWORD
;
2919 *optptr
++ = *lineptr
++;
2924 if (isspace(*lineptr
& 255) && ppd_conform
== PPD_CONFORM_STRICT
)
2926 ppd_status
= PPD_ILLEGAL_WHITESPACE
;
2930 while (isspace(*lineptr
& 255))
2935 /* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/
2937 if (*lineptr
== '/')
2940 * Get human-readable text...
2947 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':')
2949 if (((unsigned char)*lineptr
< ' ' && *lineptr
!= '\t') ||
2950 (textptr
- text
) >= (PPD_MAX_LINE
- 1))
2952 ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2956 *textptr
++ = *lineptr
++;
2960 textlen
= ppd_decode(text
);
2962 if (textlen
> PPD_MAX_TEXT
&& ppd_conform
== PPD_CONFORM_STRICT
)
2964 ppd_status
= PPD_ILLEGAL_TRANSLATION
;
2971 /* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/
2974 if (isspace(*lineptr
& 255) && ppd_conform
== PPD_CONFORM_STRICT
)
2976 ppd_status
= PPD_ILLEGAL_WHITESPACE
;
2980 while (isspace(*lineptr
& 255))
2983 if (*lineptr
== ':')
2986 * Get string after triming leading and trailing whitespace...
2990 while (isspace(*lineptr
& 255))
2993 strptr
= lineptr
+ strlen(lineptr
) - 1;
2994 while (strptr
>= lineptr
&& isspace(*strptr
& 255))
2997 if (*strptr
== '\"')
3000 * Quoted string by itself...
3003 *string
= malloc(strlen(lineptr
) + 1);
3007 for (; *lineptr
!= '\0'; lineptr
++)
3008 if (*lineptr
!= '\"')
3009 *strptr
++ = *lineptr
;
3014 *string
= strdup(lineptr
);
3016 /* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/
3028 * End of "$Id: ppd.c,v 1.51.2.65 2004/06/29 13:15:08 mike Exp $".