2 * "$Id: cupstestppd.c 7807 2008-07-28 21:54:24Z mike $"
4 * PPD test program for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * PostScript is a trademark of Adobe Systems, Inc.
17 * This file is subject to the Apple OS-Developed Software exception.
21 * main() - Main entry for test program.
22 * check_basics() - Check for CR LF, mixed line endings, and blank
24 * check_case() - Check that there are no duplicate groups, options,
25 * or choices that differ only by case.
26 * check_constraints() - Check UIConstraints in the PPD file.
27 * check_defaults() - Check default option keywords in the PPD file.
28 * check_duplex() - Check duplex keywords in the PPD file.
29 * check_filters() - Check filters in the PPD file.
30 * check_profiles() - Check ICC color profiles in the PPD file.
31 * check_translations() - Check translations in the PPD file.
32 * show_conflicts() - Show option conflicts in a PPD file.
33 * test_raster() - Test PostScript commands for raster printers.
34 * usage() - Show program usage...
35 * valid_utf8() - Check whether a string contains valid UTF-8 text.
39 * Include necessary headers...
42 #include <cups/string.h>
43 #include <cups/cups.h>
44 #include <cups/ppd-private.h>
45 #include <cups/i18n.h>
46 #include <cups/raster.h>
53 * Error warning overrides...
63 WARN_TRANSLATIONS
= 16,
100 static void check_basics(const char *filename
);
101 static int check_constraints(ppd_file_t
*ppd
, int errors
, int verbose
,
103 static int check_case(ppd_file_t
*ppd
, int errors
, int verbose
);
104 static int check_defaults(ppd_file_t
*ppd
, int errors
, int verbose
,
106 static int check_duplex(ppd_file_t
*ppd
, int errors
, int verbose
,
108 static int check_filters(ppd_file_t
*ppd
, const char *root
, int errors
,
109 int verbose
, int warn
);
110 static int check_profiles(ppd_file_t
*ppd
, const char *root
, int errors
,
111 int verbose
, int warn
);
112 static int check_translations(ppd_file_t
*ppd
, int errors
, int verbose
,\
114 static void show_conflicts(ppd_file_t
*ppd
);
115 static int test_raster(ppd_file_t
*ppd
, int verbose
);
116 static void usage(void);
117 static int valid_utf8(const char *s
);
121 * 'main()' - Main entry for test program.
124 int /* O - Exit status */
125 main(int argc
, /* I - Number of command-line args */
126 char *argv
[]) /* I - Command-line arguments */
128 int i
, j
, k
, m
, n
; /* Looping vars */
129 int len
; /* Length of option name */
130 char *opt
; /* Option character */
131 const char *ptr
; /* Pointer into string */
132 int files
; /* Number of files */
133 int verbose
; /* Want verbose output? */
134 int warn
; /* Which errors to just warn about */
135 int status
; /* Exit status */
136 int errors
; /* Number of conformance errors */
137 int ppdversion
; /* PPD spec version in PPD file */
138 ppd_status_t error
; /* Status of ppdOpen*() */
139 int line
; /* Line number for error */
140 char *root
; /* Root directory */
141 int xdpi
, /* X resolution */
142 ydpi
; /* Y resolution */
143 ppd_file_t
*ppd
; /* PPD file record */
144 ppd_attr_t
*attr
; /* PPD attribute */
145 ppd_size_t
*size
; /* Size record */
146 ppd_group_t
*group
; /* UI group */
147 ppd_option_t
*option
; /* Standard UI option */
148 ppd_group_t
*group2
; /* UI group */
149 ppd_option_t
*option2
; /* Standard UI option */
150 ppd_choice_t
*choice
; /* Standard UI option choice */
151 struct lconv
*loc
; /* Locale data */
152 static char *uis
[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
153 static char *sections
[] = { "ANY", "DOCUMENT", "EXIT",
154 "JCL", "PAGE", "PROLOG" };
157 _cupsSetLocale(argv
);
161 * Display PPD files for each file listed on the command-line...
164 ppdSetConformance(PPD_CONFORM_STRICT
);
173 for (i
= 1; i
< argc
; i
++)
174 if (argv
[i
][0] == '-' && argv
[i
][1])
176 for (opt
= argv
[i
] + 1; *opt
; opt
++)
179 case 'R' : /* Alternate root directory */
188 case 'W' : /* Turn errors into warnings */
194 if (!strcmp(argv
[i
], "none"))
196 else if (!strcmp(argv
[i
], "constraints"))
197 warn
|= WARN_CONSTRAINTS
;
198 else if (!strcmp(argv
[i
], "defaults"))
199 warn
|= WARN_DEFAULTS
;
200 else if (!strcmp(argv
[i
], "duplex"))
202 else if (!strcmp(argv
[i
], "filters"))
203 warn
|= WARN_FILTERS
;
204 else if (!strcmp(argv
[i
], "profiles"))
205 warn
|= WARN_PROFILES
;
206 else if (!strcmp(argv
[i
], "translations"))
207 warn
|= WARN_TRANSLATIONS
;
208 else if (!strcmp(argv
[i
], "all"))
214 case 'q' : /* Quiet mode */
217 _cupsLangPuts(stderr
,
218 _("cupstestppd: The -q option is incompatible "
219 "with the -v option.\n"));
226 case 'r' : /* Relaxed mode */
227 ppdSetConformance(PPD_CONFORM_RELAXED
);
230 case 'v' : /* Verbose mode */
233 _cupsLangPuts(stderr
,
234 _("cupstestppd: The -v option is incompatible "
235 "with the -q option.\n"));
250 * Open the PPD file...
253 if (files
&& verbose
>= 0)
254 _cupsLangPuts(stdout
, "\n");
258 if (argv
[i
][0] == '-')
264 ppd
= ppdOpen(stdin
);
267 printf("%s:", (ppd
&& ppd
->pcfilename
) ? ppd
->pcfilename
: "(stdin)");
272 * Read from a file...
276 printf("%s:", argv
[i
]);
278 ppd
= ppdOpenFile(argv
[i
]);
283 error
= ppdLastError(&line
);
285 if (error
<= PPD_ALLOC_ERROR
)
287 status
= ERROR_FILE_OPEN
;
290 _cupsLangPrintf(stdout
,
292 " **FAIL** Unable to open PPD file - %s\n"),
297 status
= ERROR_PPD_FORMAT
;
301 _cupsLangPrintf(stdout
,
303 " **FAIL** Unable to open PPD file - "
305 ppdErrorString(error
), line
);
309 case PPD_MISSING_PPDADOBE4
:
310 _cupsLangPuts(stdout
,
311 _(" REF: Page 42, section 5.2.\n"));
313 case PPD_MISSING_VALUE
:
314 _cupsLangPuts(stdout
,
315 _(" REF: Page 20, section 3.4.\n"));
317 case PPD_BAD_OPEN_GROUP
:
318 case PPD_NESTED_OPEN_GROUP
:
319 _cupsLangPuts(stdout
,
320 _(" REF: Pages 45-46, section 5.2.\n"));
322 case PPD_BAD_OPEN_UI
:
323 case PPD_NESTED_OPEN_UI
:
324 _cupsLangPuts(stdout
,
325 _(" REF: Pages 42-45, section 5.2.\n"));
327 case PPD_BAD_ORDER_DEPENDENCY
:
328 _cupsLangPuts(stdout
,
329 _(" REF: Pages 48-49, section 5.2.\n"));
331 case PPD_BAD_UI_CONSTRAINTS
:
332 _cupsLangPuts(stdout
,
333 _(" REF: Pages 52-54, section 5.2.\n"));
335 case PPD_MISSING_ASTERISK
:
336 _cupsLangPuts(stdout
,
337 _(" REF: Page 15, section 3.2.\n"));
339 case PPD_LINE_TOO_LONG
:
340 _cupsLangPuts(stdout
,
341 _(" REF: Page 15, section 3.1.\n"));
343 case PPD_ILLEGAL_CHARACTER
:
344 _cupsLangPuts(stdout
,
345 _(" REF: Page 15, section 3.1.\n"));
347 case PPD_ILLEGAL_MAIN_KEYWORD
:
348 _cupsLangPuts(stdout
,
349 _(" REF: Pages 16-17, section 3.2.\n"));
351 case PPD_ILLEGAL_OPTION_KEYWORD
:
352 _cupsLangPuts(stdout
,
353 _(" REF: Page 19, section 3.3.\n"));
355 case PPD_ILLEGAL_TRANSLATION
:
356 _cupsLangPuts(stdout
,
357 _(" REF: Page 27, section 3.5.\n"));
363 check_basics(argv
[i
]);
371 * Show the header and then perform basic conformance tests (limited
372 * only by what the CUPS PPD functions actually load...)
379 _cupsLangPuts(stdout
,
380 _("\n DETAILED CONFORMANCE TEST RESULTS\n"));
382 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
&&
384 ppdversion
= (int)(10 * _cupsStrScand(attr
->value
, NULL
, loc
) + 0.5);
386 for (j
= 0; j
< ppd
->num_filters
; j
++)
387 if (strstr(ppd
->filters
[j
], "application/vnd.cups-raster"))
389 if (!test_raster(ppd
, verbose
))
395 * Look for default keywords with no matching option...
398 if (!(warn
& WARN_DEFAULTS
))
399 errors
= check_defaults(ppd
, errors
, verbose
, 0);
401 if ((attr
= ppdFindAttr(ppd
, "DefaultImageableArea", NULL
)) == NULL
)
405 if (!errors
&& !verbose
)
406 _cupsLangPuts(stdout
, _(" FAIL\n"));
408 _cupsLangPuts(stdout
,
409 _(" **FAIL** REQUIRED DefaultImageableArea\n"
410 " REF: Page 102, section 5.15.\n"));
415 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
416 strcmp(attr
->value
, "Unknown"))
420 if (!errors
&& !verbose
)
421 _cupsLangPuts(stdout
, _(" FAIL\n"));
423 _cupsLangPrintf(stdout
,
424 _(" **FAIL** BAD DefaultImageableArea %s!\n"
425 " REF: Page 102, section 5.15.\n"),
434 _cupsLangPuts(stdout
, _(" PASS DefaultImageableArea\n"));
437 if ((attr
= ppdFindAttr(ppd
, "DefaultPaperDimension", NULL
)) == NULL
)
441 if (!errors
&& !verbose
)
442 _cupsLangPuts(stdout
, _(" FAIL\n"));
444 _cupsLangPuts(stdout
,
445 _(" **FAIL** REQUIRED DefaultPaperDimension\n"
446 " REF: Page 103, section 5.15.\n"));
451 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
452 strcmp(attr
->value
, "Unknown"))
456 if (!errors
&& !verbose
)
457 _cupsLangPuts(stdout
, _(" FAIL\n"));
459 _cupsLangPrintf(stdout
,
460 _(" **FAIL** BAD DefaultPaperDimension %s!\n"
461 " REF: Page 103, section 5.15.\n"),
467 else if (verbose
> 0)
468 _cupsLangPuts(stdout
, _(" PASS DefaultPaperDimension\n"));
470 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
471 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
474 * Verify that we have a default choice...
477 if (option
->defchoice
[0])
479 if (ppdFindChoice(option
, option
->defchoice
) == NULL
&&
480 strcmp(option
->defchoice
, "Unknown"))
484 if (!errors
&& !verbose
)
485 _cupsLangPuts(stdout
, _(" FAIL\n"));
487 _cupsLangPrintf(stdout
,
488 _(" **FAIL** BAD Default%s %s\n"
489 " REF: Page 40, section 4.5.\n"),
490 option
->keyword
, option
->defchoice
);
495 else if (verbose
> 0)
496 _cupsLangPrintf(stdout
,
497 _(" PASS Default%s\n"),
504 if (!errors
&& !verbose
)
505 _cupsLangPuts(stdout
, _(" FAIL\n"));
507 _cupsLangPrintf(stdout
,
508 _(" **FAIL** REQUIRED Default%s\n"
509 " REF: Page 40, section 4.5.\n"),
517 if (ppdFindAttr(ppd
, "FileVersion", NULL
) != NULL
)
520 _cupsLangPuts(stdout
, _(" PASS FileVersion\n"));
526 if (!errors
&& !verbose
)
527 _cupsLangPuts(stdout
, _(" FAIL\n"));
529 _cupsLangPuts(stdout
,
530 _(" **FAIL** REQUIRED FileVersion\n"
531 " REF: Page 56, section 5.3.\n"));
537 if (ppdFindAttr(ppd
, "FormatVersion", NULL
) != NULL
)
540 _cupsLangPuts(stdout
, _(" PASS FormatVersion\n"));
546 if (!errors
&& !verbose
)
547 _cupsLangPuts(stdout
, _(" FAIL\n"));
549 _cupsLangPuts(stdout
,
550 _(" **FAIL** REQUIRED FormatVersion\n"
551 " REF: Page 56, section 5.3.\n"));
557 if (ppd
->lang_encoding
!= NULL
)
560 _cupsLangPuts(stdout
, _(" PASS LanguageEncoding\n"));
562 else if (ppdversion
> 40)
566 if (!errors
&& !verbose
)
567 _cupsLangPuts(stdout
, _(" FAIL\n"));
569 _cupsLangPuts(stdout
,
570 _(" **FAIL** REQUIRED LanguageEncoding\n"
571 " REF: Pages 56-57, section 5.3.\n"));
577 if (ppd
->lang_version
!= NULL
)
580 _cupsLangPuts(stdout
, _(" PASS LanguageVersion\n"));
586 if (!errors
&& !verbose
)
587 _cupsLangPuts(stdout
, _(" FAIL\n"));
589 _cupsLangPuts(stdout
,
590 _(" **FAIL** REQUIRED LanguageVersion\n"
591 " REF: Pages 57-58, section 5.3.\n"));
597 if (ppd
->manufacturer
!= NULL
)
599 if (!strncasecmp(ppd
->manufacturer
, "Hewlett-Packard", 15) ||
600 !strncasecmp(ppd
->manufacturer
, "Hewlett Packard", 15))
604 if (!errors
&& !verbose
)
605 _cupsLangPuts(stdout
, _(" FAIL\n"));
607 _cupsLangPuts(stdout
,
608 _(" **FAIL** BAD Manufacturer (should be "
610 " REF: Page 211, table D.1.\n"));
615 else if (!strncasecmp(ppd
->manufacturer
, "OkiData", 7) ||
616 !strncasecmp(ppd
->manufacturer
, "Oki Data", 8))
620 if (!errors
&& !verbose
)
621 _cupsLangPuts(stdout
, _(" FAIL\n"));
623 _cupsLangPuts(stdout
,
624 _(" **FAIL** BAD Manufacturer (should be "
626 " REF: Page 211, table D.1.\n"));
631 else if (verbose
> 0)
632 _cupsLangPuts(stdout
, _(" PASS Manufacturer\n"));
634 else if (ppdversion
>= 43)
638 if (!errors
&& !verbose
)
639 _cupsLangPuts(stdout
, _(" FAIL\n"));
641 _cupsLangPuts(stdout
,
642 _(" **FAIL** REQUIRED Manufacturer\n"
643 " REF: Pages 58-59, section 5.3.\n"));
649 if (ppd
->modelname
!= NULL
)
651 for (ptr
= ppd
->modelname
; *ptr
; ptr
++)
652 if (!isalnum(*ptr
& 255) && !strchr(" ./-+", *ptr
))
659 if (!errors
&& !verbose
)
660 _cupsLangPuts(stdout
, _(" FAIL\n"));
662 _cupsLangPrintf(stdout
,
663 _(" **FAIL** BAD ModelName - \"%c\" not "
664 "allowed in string.\n"
665 " REF: Pages 59-60, section 5.3.\n"),
671 else if (verbose
> 0)
672 _cupsLangPuts(stdout
, _(" PASS ModelName\n"));
678 if (!errors
&& !verbose
)
679 _cupsLangPuts(stdout
, _(" FAIL\n"));
681 _cupsLangPuts(stdout
,
682 _(" **FAIL** REQUIRED ModelName\n"
683 " REF: Pages 59-60, section 5.3.\n"));
689 if (ppd
->nickname
!= NULL
)
692 _cupsLangPuts(stdout
, _(" PASS NickName\n"));
698 if (!errors
&& !verbose
)
699 _cupsLangPuts(stdout
, _(" FAIL\n"));
701 _cupsLangPuts(stdout
,
702 _(" **FAIL** REQUIRED NickName\n"
703 " REF: Page 60, section 5.3.\n"));
709 if (ppdFindOption(ppd
, "PageSize") != NULL
)
712 _cupsLangPuts(stdout
, _(" PASS PageSize\n"));
718 if (!errors
&& !verbose
)
719 _cupsLangPuts(stdout
, _(" FAIL\n"));
721 _cupsLangPuts(stdout
,
722 _(" **FAIL** REQUIRED PageSize\n"
723 " REF: Pages 99-100, section 5.14.\n"));
729 if (ppdFindOption(ppd
, "PageRegion") != NULL
)
732 _cupsLangPuts(stdout
, _(" PASS PageRegion\n"));
738 if (!errors
&& !verbose
)
739 _cupsLangPuts(stdout
, _(" FAIL\n"));
741 _cupsLangPuts(stdout
,
742 _(" **FAIL** REQUIRED PageRegion\n"
743 " REF: Page 100, section 5.14.\n"));
749 if (ppd
->pcfilename
!= NULL
)
752 _cupsLangPuts(stdout
, _(" PASS PCFileName\n"));
758 if (!errors
&& !verbose
)
759 _cupsLangPuts(stdout
, _(" FAIL\n"));
761 _cupsLangPuts(stdout
,
762 _(" **FAIL** REQUIRED PCFileName\n"
763 " REF: Pages 61-62, section 5.3.\n"));
769 if (ppd
->product
!= NULL
)
771 if (ppd
->product
[0] != '(' ||
772 ppd
->product
[strlen(ppd
->product
) - 1] != ')')
776 if (!errors
&& !verbose
)
777 _cupsLangPuts(stdout
, _(" FAIL\n"));
779 _cupsLangPuts(stdout
,
780 _(" **FAIL** BAD Product - not \"(string)\".\n"
781 " REF: Page 62, section 5.3.\n"));
786 else if (verbose
> 0)
787 _cupsLangPuts(stdout
, _(" PASS Product\n"));
793 if (!errors
&& !verbose
)
794 _cupsLangPuts(stdout
, _(" FAIL\n"));
796 _cupsLangPuts(stdout
,
797 _(" **FAIL** REQUIRED Product\n"
798 " REF: Page 62, section 5.3.\n"));
804 if ((attr
= ppdFindAttr(ppd
, "PSVersion", NULL
)) != NULL
&&
807 char junkstr
[255]; /* Temp string */
808 int junkint
; /* Temp integer */
811 if (sscanf(attr
->value
, "(%[^)])%d", junkstr
, &junkint
) != 2)
815 if (!errors
&& !verbose
)
816 _cupsLangPuts(stdout
, _(" FAIL\n"));
818 _cupsLangPuts(stdout
,
819 _(" **FAIL** BAD PSVersion - not \"(string) "
821 " REF: Pages 62-64, section 5.3.\n"));
826 else if (verbose
> 0)
827 _cupsLangPuts(stdout
, _(" PASS PSVersion\n"));
833 if (!errors
&& !verbose
)
834 _cupsLangPuts(stdout
, _(" FAIL\n"));
836 _cupsLangPuts(stdout
,
837 _(" **FAIL** REQUIRED PSVersion\n"
838 " REF: Pages 62-64, section 5.3.\n"));
844 if (ppd
->shortnickname
!= NULL
)
846 if (strlen(ppd
->shortnickname
) > 31)
850 if (!errors
&& !verbose
)
851 _cupsLangPuts(stdout
, _(" FAIL\n"));
853 _cupsLangPuts(stdout
,
854 _(" **FAIL** BAD ShortNickName - longer "
856 " REF: Pages 64-65, section 5.3.\n"));
861 else if (verbose
> 0)
862 _cupsLangPuts(stdout
, _(" PASS ShortNickName\n"));
864 else if (ppdversion
>= 43)
868 if (!errors
&& !verbose
)
869 _cupsLangPuts(stdout
, _(" FAIL\n"));
871 _cupsLangPuts(stdout
,
872 _(" **FAIL** REQUIRED ShortNickName\n"
873 " REF: Page 64-65, section 5.3.\n"));
879 if (ppd
->patches
!= NULL
&& strchr(ppd
->patches
, '\"') &&
880 strstr(ppd
->patches
, "*End"))
884 if (!errors
&& !verbose
)
885 _cupsLangPuts(stdout
, _(" FAIL\n"));
887 _cupsLangPuts(stdout
,
888 _(" **FAIL** BAD JobPatchFile attribute in file\n"
889 " REF: Page 24, section 3.4.\n"));
896 * Check for page sizes without the corresponding ImageableArea or
897 * PaperDimension values...
900 if (ppd
->num_sizes
== 0)
904 if (!errors
&& !verbose
)
905 _cupsLangPuts(stdout
, _(" FAIL\n"));
907 _cupsLangPuts(stdout
,
908 _(" **FAIL** REQUIRED PageSize\n"
909 " REF: Page 41, section 5.\n"
910 " REF: Page 99, section 5.14.\n"));
917 for (j
= 0, size
= ppd
->sizes
; j
< ppd
->num_sizes
; j
++, size
++)
920 * Don't check custom size...
923 if (!strcmp(size
->name
, "Custom"))
927 * Check for ImageableArea...
930 if (size
->left
== 0.0 && size
->bottom
== 0.0 &&
931 size
->right
== 0.0 && size
->top
== 0.0)
935 if (!errors
&& !verbose
)
936 _cupsLangPuts(stdout
, _(" FAIL\n"));
938 _cupsLangPrintf(stdout
,
939 _(" **FAIL** REQUIRED ImageableArea for "
941 " REF: Page 41, section 5.\n"
942 " REF: Page 102, section 5.15.\n"),
950 * Check for PaperDimension...
953 if (size
->width
== 0.0 && size
->length
== 0.0)
957 if (!errors
&& !verbose
)
958 _cupsLangPuts(stdout
, _(" FAIL\n"));
960 _cupsLangPrintf(stdout
,
961 _(" **FAIL** REQUIRED PaperDimension "
963 " REF: Page 41, section 5.\n"
964 " REF: Page 103, section 5.15.\n"),
974 * Check for valid Resolution, JCLResolution, or SetResolution values...
977 if ((option
= ppdFindOption(ppd
, "Resolution")) == NULL
)
978 if ((option
= ppdFindOption(ppd
, "JCLResolution")) == NULL
)
979 option
= ppdFindOption(ppd
, "SetResolution");
983 for (j
= option
->num_choices
, choice
= option
->choices
; j
> 0; j
--, choice
++)
986 * Verify that all resolution options are of the form NNNdpi
990 xdpi
= strtol(choice
->choice
, (char **)&ptr
, 10);
991 if (ptr
> choice
->choice
&& xdpi
> 0)
994 ydpi
= strtol(ptr
+ 1, (char **)&ptr
, 10);
1001 if (xdpi
<= 0 || xdpi
> 99999 || ydpi
<= 0 || ydpi
> 99999 ||
1006 if (!errors
&& !verbose
)
1007 _cupsLangPuts(stdout
, _(" FAIL\n"));
1009 _cupsLangPrintf(stdout
,
1010 _(" **FAIL** Bad %s choice %s!\n"
1011 " REF: Page 84, section 5.9\n"),
1012 option
->keyword
, choice
->choice
);
1020 if ((attr
= ppdFindAttr(ppd
, "1284DeviceID", NULL
)) &&
1021 strcmp(attr
->name
, "1284DeviceID"))
1025 if (!errors
&& !verbose
)
1026 _cupsLangPuts(stdout
, _(" FAIL\n"));
1028 _cupsLangPrintf(stdout
,
1029 _(" **FAIL** %s must be 1284DeviceID!\n"
1030 " REF: Page 72, section 5.5\n"),
1037 errors
= check_case(ppd
, errors
, verbose
);
1039 if (!(warn
& WARN_CONSTRAINTS
))
1040 errors
= check_constraints(ppd
, errors
, verbose
, 0);
1042 if (!(warn
& WARN_FILTERS
))
1043 errors
= check_filters(ppd
, root
, errors
, verbose
, 0);
1045 if (!(warn
& WARN_PROFILES
))
1046 errors
= check_profiles(ppd
, root
, errors
, verbose
, 0);
1048 if (!(warn
& WARN_TRANSLATIONS
))
1049 errors
= check_translations(ppd
, errors
, verbose
, 0);
1051 if (!(warn
& WARN_DUPLEX
))
1052 errors
= check_duplex(ppd
, errors
, verbose
, 0);
1054 if ((attr
= ppdFindAttr(ppd
, "cupsLanguages", NULL
)) != NULL
&&
1058 * This file contains localizations, check for conformance of the
1059 * base translation...
1062 if ((attr
= ppdFindAttr(ppd
, "LanguageEncoding", NULL
)) != NULL
)
1064 if (!attr
->value
|| strcmp(attr
->value
, "ISOLatin1"))
1066 if (!errors
&& !verbose
)
1067 _cupsLangPuts(stdout
, _(" FAIL\n"));
1070 _cupsLangPrintf(stdout
,
1071 _(" **FAIL** Bad LanguageEncoding %s - "
1072 "must be ISOLatin1!\n"),
1073 attr
->value
? attr
->value
: "(null)");
1078 if (!ppd
->lang_version
|| strcmp(ppd
->lang_version
, "English"))
1080 if (!errors
&& !verbose
)
1081 _cupsLangPuts(stdout
, _(" FAIL\n"));
1084 _cupsLangPrintf(stdout
,
1085 _(" **FAIL** Bad LanguageVersion %s - "
1086 "must be English!\n"),
1087 ppd
->lang_version
? ppd
->lang_version
: "(null)");
1093 * Loop through all options and choices...
1096 for (option
= ppdFirstOption(ppd
);
1098 option
= ppdNextOption(ppd
))
1101 * Check for special characters outside A0 to BF, F7, or F8
1102 * that are used for languages other than English.
1105 for (ptr
= option
->text
; *ptr
; ptr
++)
1106 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1107 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1112 if (!errors
&& !verbose
)
1113 _cupsLangPuts(stdout
, _(" FAIL\n"));
1116 _cupsLangPrintf(stdout
,
1117 _(" **FAIL** Default translation "
1118 "string for option %s contains 8-bit "
1125 for (j
= 0; j
< option
->num_choices
; j
++)
1128 * Check for special characters outside A0 to BF, F7, or F8
1129 * that are used for languages other than English.
1132 for (ptr
= option
->choices
[j
].text
; *ptr
; ptr
++)
1133 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1134 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1139 if (!errors
&& !verbose
)
1140 _cupsLangPuts(stdout
, _(" FAIL\n"));
1143 _cupsLangPrintf(stdout
,
1144 _(" **FAIL** Default translation "
1145 "string for option %s choice %s contains "
1146 "8-bit characters!\n"),
1148 option
->choices
[j
].choice
);
1158 * Final pass/fail notification...
1162 status
= ERROR_CONFORMANCE
;
1164 _cupsLangPuts(stdout
, _(" PASS\n"));
1168 check_basics(argv
[i
]);
1170 if (warn
& WARN_CONSTRAINTS
)
1171 errors
= check_constraints(ppd
, errors
, verbose
, 1);
1173 if (warn
& WARN_DEFAULTS
)
1174 errors
= check_defaults(ppd
, errors
, verbose
, 1);
1176 if (warn
& WARN_PROFILES
)
1177 errors
= check_profiles(ppd
, root
, errors
, verbose
, 1);
1179 if (warn
& WARN_FILTERS
)
1180 errors
= check_filters(ppd
, root
, errors
, verbose
, 1);
1182 if (warn
& WARN_TRANSLATIONS
)
1183 errors
= check_translations(ppd
, errors
, verbose
, 1);
1185 if (warn
& WARN_DUPLEX
)
1186 errors
= check_duplex(ppd
, errors
, verbose
, 1);
1189 * Look for legacy duplex keywords...
1192 if ((option
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
1193 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
1194 option
= ppdFindOption(ppd
, "KD03Duplex");
1197 _cupsLangPrintf(stdout
,
1198 _(" WARN Duplex option keyword %s may not "
1199 "work as expected and should be named Duplex!\n"
1200 " REF: Page 122, section 5.17\n"),
1204 * Look for default keywords with no corresponding option...
1207 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1209 attr
= ppd
->attrs
[j
];
1211 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
1212 !strcmp(attr
->name
, "DefaultColorSep") ||
1213 !strcmp(attr
->name
, "DefaultFont") ||
1214 !strcmp(attr
->name
, "DefaultHalftoneType") ||
1215 !strcmp(attr
->name
, "DefaultImageableArea") ||
1216 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
1217 !strcmp(attr
->name
, "DefaultOutputOrder") ||
1218 !strcmp(attr
->name
, "DefaultPaperDimension") ||
1219 !strcmp(attr
->name
, "DefaultResolution") ||
1220 !strcmp(attr
->name
, "DefaultScreenProc") ||
1221 !strcmp(attr
->name
, "DefaultTransfer"))
1224 if (!strncmp(attr
->name
, "Default", 7) &&
1225 !ppdFindOption(ppd
, attr
->name
+ 7))
1226 _cupsLangPrintf(stdout
,
1227 _(" WARN %s has no corresponding "
1232 ppdMarkDefaults(ppd
);
1233 if (ppdConflicts(ppd
))
1235 _cupsLangPuts(stdout
,
1236 _(" WARN Default choices conflicting!\n"));
1238 show_conflicts(ppd
);
1241 if (ppdversion
< 43)
1243 _cupsLangPrintf(stdout
,
1244 _(" WARN Obsolete PPD version %.1f!\n"
1245 " REF: Page 42, section 5.2.\n"),
1249 if (!ppd
->lang_encoding
&& ppdversion
< 41)
1251 _cupsLangPuts(stdout
,
1252 _(" WARN LanguageEncoding required by PPD "
1254 " REF: Pages 56-57, section 5.3.\n"));
1257 if (!ppd
->manufacturer
&& ppdversion
< 43)
1259 _cupsLangPuts(stdout
,
1260 _(" WARN Manufacturer required by PPD "
1262 " REF: Pages 58-59, section 5.3.\n"));
1266 * Treat a PCFileName attribute longer than 12 characters as
1267 * a warning and not a hard error...
1270 if (ppd
->pcfilename
&& strlen(ppd
->pcfilename
) > 12)
1272 _cupsLangPuts(stdout
,
1273 _(" WARN PCFileName longer than 8.3 in "
1274 "violation of PPD spec.\n"
1275 " REF: Pages 61-62, section 5.3.\n"));
1278 if (!ppd
->shortnickname
&& ppdversion
< 43)
1280 _cupsLangPuts(stdout
,
1281 _(" WARN ShortNickName required by PPD "
1283 " REF: Pages 64-65, section 5.3.\n"));
1287 * Check the Protocols line and flag PJL + BCP since TBCP is
1288 * usually used with PJL...
1293 if (strstr(ppd
->protocols
, "PJL") &&
1294 strstr(ppd
->protocols
, "BCP") &&
1295 !strstr(ppd
->protocols
, "TBCP"))
1297 _cupsLangPuts(stdout
,
1298 _(" WARN Protocols contains both PJL "
1299 "and BCP; expected TBCP.\n"
1300 " REF: Pages 78-79, section 5.7.\n"));
1303 if (strstr(ppd
->protocols
, "PJL") &&
1304 (!ppd
->jcl_begin
|| !ppd
->jcl_end
|| !ppd
->jcl_ps
))
1306 _cupsLangPuts(stdout
,
1307 _(" WARN Protocols contains PJL but JCL "
1308 "attributes are not set.\n"
1309 " REF: Pages 78-79, section 5.7.\n"));
1314 * Check for options with a common prefix, e.g. Duplex and Duplexer,
1315 * which are errors according to the spec but won't cause problems
1316 * with CUPS specifically...
1319 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1320 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1322 len
= strlen(option
->keyword
);
1324 for (m
= 0, group2
= ppd
->groups
;
1325 m
< ppd
->num_groups
;
1327 for (n
= 0, option2
= group2
->options
;
1328 n
< group2
->num_options
;
1330 if (option
!= option2
&&
1331 len
< strlen(option2
->keyword
) &&
1332 !strncmp(option
->keyword
, option2
->keyword
, len
))
1334 _cupsLangPrintf(stdout
,
1335 _(" WARN %s shares a common "
1337 " REF: Page 15, section "
1339 option
->keyword
, option2
->keyword
);
1349 for (attr
= ppdFindAttr(ppd
, "APDialogExtension", NULL
);
1351 attr
= ppdFindNextAttr(ppd
, "APDialogExtension", NULL
))
1353 if ((!attr
->value
|| access(attr
->value
, 0)) && verbose
>= 0)
1354 _cupsLangPrintf(stdout
, _(" WARN Missing "
1355 "APDialogExtension file \"%s\"\n"),
1356 attr
->value
? attr
->value
: "<NULL>");
1363 for (attr
= ppdFindAttr(ppd
, "APPrinterIconPath", NULL
);
1365 attr
= ppdFindNextAttr(ppd
, "APPrinterIconPath", NULL
))
1367 if ((!attr
->value
|| access(attr
->value
, 0)) && verbose
>= 0)
1368 _cupsLangPrintf(stdout
, _(" WARN Missing "
1369 "APPrinterIconPath file \"%s\"\n"),
1370 attr
->value
? attr
->value
: "<NULL>");
1372 #endif /* __APPLE__ */
1377 _cupsLangPrintf(stdout
, _(" %d ERRORS FOUND\n"), errors
);
1379 _cupsLangPuts(stdout
, _(" NO ERRORS FOUND\n"));
1383 * Then list the options, if "-v" was provided...
1388 _cupsLangPrintf(stdout
,
1390 " language_level = %d\n"
1391 " color_device = %s\n"
1392 " variable_sizes = %s\n"
1393 " landscape = %d\n",
1394 ppd
->language_level
,
1395 ppd
->color_device
? "TRUE" : "FALSE",
1396 ppd
->variable_sizes
? "TRUE" : "FALSE",
1399 switch (ppd
->colorspace
)
1402 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMYK\n");
1405 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMY\n");
1408 _cupsLangPuts(stdout
, " colorspace = PPD_CS_GRAY\n");
1411 _cupsLangPuts(stdout
, " colorspace = PPD_CS_RGB\n");
1414 _cupsLangPuts(stdout
, " colorspace = <unknown>\n");
1418 _cupsLangPrintf(stdout
, " num_emulations = %d\n",
1419 ppd
->num_emulations
);
1420 for (j
= 0; j
< ppd
->num_emulations
; j
++)
1421 _cupsLangPrintf(stdout
, " emulations[%d] = %s\n",
1422 j
, ppd
->emulations
[j
].name
);
1424 _cupsLangPrintf(stdout
, " lang_encoding = %s\n",
1425 ppd
->lang_encoding
);
1426 _cupsLangPrintf(stdout
, " lang_version = %s\n",
1428 _cupsLangPrintf(stdout
, " modelname = %s\n", ppd
->modelname
);
1429 _cupsLangPrintf(stdout
, " ttrasterizer = %s\n",
1430 ppd
->ttrasterizer
== NULL
? "None" : ppd
->ttrasterizer
);
1431 _cupsLangPrintf(stdout
, " manufacturer = %s\n",
1433 _cupsLangPrintf(stdout
, " product = %s\n", ppd
->product
);
1434 _cupsLangPrintf(stdout
, " nickname = %s\n", ppd
->nickname
);
1435 _cupsLangPrintf(stdout
, " shortnickname = %s\n",
1436 ppd
->shortnickname
);
1437 _cupsLangPrintf(stdout
, " patches = %d bytes\n",
1438 ppd
->patches
== NULL
? 0 : (int)strlen(ppd
->patches
));
1440 _cupsLangPrintf(stdout
, " num_groups = %d\n", ppd
->num_groups
);
1441 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1443 _cupsLangPrintf(stdout
, " group[%d] = %s\n",
1446 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1448 _cupsLangPrintf(stdout
,
1449 " options[%d] = %s (%s) %s %s %.0f "
1451 k
, option
->keyword
, option
->text
, uis
[option
->ui
],
1452 sections
[option
->section
], option
->order
,
1453 option
->num_choices
);
1455 if (!strcmp(option
->keyword
, "PageSize") ||
1456 !strcmp(option
->keyword
, "PageRegion"))
1458 for (m
= option
->num_choices
, choice
= option
->choices
;
1462 size
= ppdPageSize(ppd
, choice
->choice
);
1465 _cupsLangPrintf(stdout
,
1467 choice
->choice
, choice
->text
);
1469 _cupsLangPrintf(stdout
,
1470 " %s (%s) = %.2fx%.2fin "
1471 "(%.1f,%.1f,%.1f,%.1f)",
1472 choice
->choice
, choice
->text
,
1473 size
->width
/ 72.0, size
->length
/ 72.0,
1474 size
->left
/ 72.0, size
->bottom
/ 72.0,
1475 size
->right
/ 72.0, size
->top
/ 72.0);
1477 if (!strcmp(option
->defchoice
, choice
->choice
))
1478 _cupsLangPuts(stdout
, " *\n");
1480 _cupsLangPuts(stdout
, "\n");
1485 for (m
= option
->num_choices
, choice
= option
->choices
;
1489 _cupsLangPrintf(stdout
, " %s (%s)",
1490 choice
->choice
, choice
->text
);
1492 if (!strcmp(option
->defchoice
, choice
->choice
))
1493 _cupsLangPuts(stdout
, " *\n");
1495 _cupsLangPuts(stdout
, "\n");
1501 _cupsLangPrintf(stdout
, " num_consts = %d\n",
1503 for (j
= 0; j
< ppd
->num_consts
; j
++)
1504 _cupsLangPrintf(stdout
,
1505 " consts[%d] = *%s %s *%s %s\n",
1506 j
, ppd
->consts
[j
].option1
, ppd
->consts
[j
].choice1
,
1507 ppd
->consts
[j
].option2
, ppd
->consts
[j
].choice2
);
1509 _cupsLangPrintf(stdout
, " num_profiles = %d\n",
1511 for (j
= 0; j
< ppd
->num_profiles
; j
++)
1512 _cupsLangPrintf(stdout
,
1513 " profiles[%d] = %s/%s %.3f %.3f "
1514 "[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
1515 j
, ppd
->profiles
[j
].resolution
,
1516 ppd
->profiles
[j
].media_type
,
1517 ppd
->profiles
[j
].gamma
, ppd
->profiles
[j
].density
,
1518 ppd
->profiles
[j
].matrix
[0][0],
1519 ppd
->profiles
[j
].matrix
[0][1],
1520 ppd
->profiles
[j
].matrix
[0][2],
1521 ppd
->profiles
[j
].matrix
[1][0],
1522 ppd
->profiles
[j
].matrix
[1][1],
1523 ppd
->profiles
[j
].matrix
[1][2],
1524 ppd
->profiles
[j
].matrix
[2][0],
1525 ppd
->profiles
[j
].matrix
[2][1],
1526 ppd
->profiles
[j
].matrix
[2][2]);
1528 _cupsLangPrintf(stdout
, " num_fonts = %d\n", ppd
->num_fonts
);
1529 for (j
= 0; j
< ppd
->num_fonts
; j
++)
1530 _cupsLangPrintf(stdout
, " fonts[%d] = %s\n",
1533 _cupsLangPrintf(stdout
, " num_attrs = %d\n", ppd
->num_attrs
);
1534 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1535 _cupsLangPrintf(stdout
,
1536 " attrs[%d] = %s %s%s%s: \"%s\"\n", j
,
1537 ppd
->attrs
[j
]->name
, ppd
->attrs
[j
]->spec
,
1538 ppd
->attrs
[j
]->text
[0] ? "/" : "",
1539 ppd
->attrs
[j
]->text
,
1540 ppd
->attrs
[j
]->value
?
1541 ppd
->attrs
[j
]->value
: "(null)");
1555 * 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1559 check_basics(const char *filename
) /* I - PPD file to check */
1561 cups_file_t
*fp
; /* File pointer */
1562 int ch
; /* Current character */
1563 int col
, /* Current column */
1564 whitespace
; /* Only seen whitespace? */
1565 int eol
; /* Line endings */
1566 int linenum
; /* Line number */
1567 int mixed
; /* Mixed line endings? */
1570 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
1579 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
1581 if (ch
== '\r' || ch
== '\n')
1585 if (eol
== EOL_NONE
)
1587 else if (eol
!= EOL_LF
)
1590 else if (ch
== '\r')
1592 if (cupsFilePeekChar(fp
) == '\n')
1594 cupsFileGetChar(fp
);
1596 if (eol
== EOL_NONE
)
1598 else if (eol
!= EOL_CRLF
)
1601 else if (eol
== EOL_NONE
)
1603 else if (eol
!= EOL_CR
)
1607 if (col
> 0 && whitespace
)
1608 _cupsLangPrintf(stdout
,
1609 _(" WARN Line %d only contains whitespace!\n"),
1618 if (ch
!= ' ' && ch
!= '\t')
1626 _cupsLangPuts(stdout
,
1627 _(" WARN File contains a mix of CR, LF, and "
1628 "CR LF line endings!\n"));
1630 if (eol
== EOL_CRLF
)
1631 _cupsLangPuts(stdout
,
1632 _(" WARN Non-Windows PPD files should use lines "
1633 "ending with only LF, not CR LF!\n"));
1640 * 'check_constraints()' - Check UIConstraints in the PPD file.
1643 static int /* O - Errors found */
1644 check_constraints(ppd_file_t
*ppd
, /* I - PPD file */
1645 int errors
, /* I - Errors found */
1646 int verbose
, /* I - Verbosity level */
1647 int warn
) /* I - Warnings only? */
1649 int i
; /* Looping var */
1650 const char *prefix
; /* WARN/FAIL prefix */
1651 ppd_const_t
*c
; /* Current UIConstraints data */
1652 ppd_attr_t
*constattr
; /* Current cupsUIConstraints attribute */
1653 const char *vptr
; /* Pointer into constraint value */
1654 char option
[PPD_MAX_NAME
],
1655 /* Option name/MainKeyword */
1656 choice
[PPD_MAX_NAME
],
1657 /* Choice/OptionKeyword */
1658 *ptr
; /* Pointer into option or choice */
1659 int num_options
; /* Number of options */
1660 cups_option_t
*options
; /* Options */
1661 ppd_option_t
*o
; /* PPD option */
1664 prefix
= warn
? " WARN " : "**FAIL**";
1668 * See what kind of constraint data we have in the PPD...
1671 if ((constattr
= ppdFindAttr(ppd
, "cupsUIConstraints", NULL
)) != NULL
)
1674 * Check new-style cupsUIConstraints data...
1678 constattr
= ppdFindNextAttr(ppd
, "cupsUIConstraints", NULL
))
1680 if (!constattr
->value
)
1682 if (!warn
&& !errors
&& !verbose
)
1683 _cupsLangPuts(stdout
, _(" FAIL\n"));
1685 _cupsLangPrintf(stdout
,
1686 _(" %s Empty cupsUIConstraints %s!\n"),
1687 prefix
, constattr
->spec
);
1695 for (i
= 0, vptr
= strchr(constattr
->value
, '*');
1697 i
++, vptr
= strchr(vptr
+ 1, '*'));
1701 if (!warn
&& !errors
&& !verbose
)
1702 _cupsLangPuts(stdout
, _(" FAIL\n"));
1704 _cupsLangPrintf(stdout
,
1705 _(" %s Bad cupsUIConstraints %s: \"%s\"!\n"),
1706 prefix
, constattr
->spec
, constattr
->value
);
1714 cupsArraySave(ppd
->sorted_attrs
);
1716 if (constattr
->spec
[0] &&
1717 !ppdFindAttr(ppd
, "cupsUIResolver", constattr
->spec
))
1719 if (!warn
&& !errors
&& !verbose
)
1720 _cupsLangPuts(stdout
, _(" FAIL\n"));
1722 _cupsLangPrintf(stdout
,
1723 _(" %s Missing cupsUIResolver %s!\n"),
1724 prefix
, constattr
->spec
);
1730 cupsArrayRestore(ppd
->sorted_attrs
);
1735 for (vptr
= strchr(constattr
->value
, '*');
1737 vptr
= strchr(vptr
, '*'))
1740 * Extract "*Option Choice" or just "*Option"...
1743 for (vptr
++, ptr
= option
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1744 if (ptr
< (option
+ sizeof(option
) - 1))
1749 while (isspace(*vptr
& 255))
1756 for (ptr
= choice
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1757 if (ptr
< (choice
+ sizeof(choice
) - 1))
1763 if (!strncasecmp(option
, "Custom", 6) && !strcasecmp(choice
, "True"))
1765 _cups_strcpy(option
, option
+ 6);
1766 strcpy(choice
, "Custom");
1769 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1771 if (!warn
&& !errors
&& !verbose
)
1772 _cupsLangPuts(stdout
, _(" FAIL\n"));
1774 _cupsLangPrintf(stdout
,
1775 _(" %s Missing option %s in "
1776 "cupsUIConstraints %s: \"%s\"!\n"),
1777 prefix
, option
, constattr
->spec
, constattr
->value
);
1785 if (choice
[0] && !ppdFindChoice(o
, choice
))
1787 if (!warn
&& !errors
&& !verbose
)
1788 _cupsLangPuts(stdout
, _(" FAIL\n"));
1790 _cupsLangPrintf(stdout
,
1791 _(" %s Missing choice *%s %s in "
1792 "cupsUIConstraints %s: \"%s\"!\n"),
1793 prefix
, option
, choice
, constattr
->spec
,
1803 num_options
= cupsAddOption(option
, choice
, num_options
, &options
);
1806 for (i
= 0; i
< o
->num_choices
; i
++)
1807 if (strcasecmp(o
->choices
[i
].choice
, "None") &&
1808 strcasecmp(o
->choices
[i
].choice
, "Off") &&
1809 strcasecmp(o
->choices
[i
].choice
, "False"))
1811 num_options
= cupsAddOption(option
, o
->choices
[i
].choice
,
1812 num_options
, &options
);
1819 * Test the resolver...
1822 if (!cupsResolveConflicts(ppd
, NULL
, NULL
, &num_options
, &options
))
1824 if (!warn
&& !errors
&& !verbose
)
1825 _cupsLangPuts(stdout
, _(" FAIL\n"));
1827 _cupsLangPrintf(stdout
,
1828 _(" %s cupsUIResolver %s causes a loop!\n"),
1829 prefix
, constattr
->spec
);
1835 cupsFreeOptions(num_options
, options
);
1841 * Check old-style [Non]UIConstraints data...
1844 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
1846 if (!strncasecmp(c
->option1
, "Custom", 6) &&
1847 !strcasecmp(c
->choice1
, "True"))
1849 strcpy(option
, c
->option1
+ 6);
1850 strcpy(choice
, "Custom");
1854 strcpy(option
, c
->option1
);
1855 strcpy(choice
, c
->choice1
);
1858 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1860 if (!warn
&& !errors
&& !verbose
)
1861 _cupsLangPuts(stdout
, _(" FAIL\n"));
1863 _cupsLangPrintf(stdout
,
1864 _(" %s Missing option %s in "
1865 "UIConstraints \"*%s %s *%s %s\"!\n"),
1867 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1872 else if (choice
[0] && !ppdFindChoice(o
, choice
))
1874 if (!warn
&& !errors
&& !verbose
)
1875 _cupsLangPuts(stdout
, _(" FAIL\n"));
1877 _cupsLangPrintf(stdout
,
1878 _(" %s Missing choice *%s %s in "
1879 "UIConstraints \"*%s %s *%s %s\"!\n"),
1880 prefix
, c
->option1
, c
->choice1
,
1881 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1887 if (!strncasecmp(c
->option2
, "Custom", 6) &&
1888 !strcasecmp(c
->choice2
, "True"))
1890 strcpy(option
, c
->option2
+ 6);
1891 strcpy(choice
, "Custom");
1895 strcpy(option
, c
->option2
);
1896 strcpy(choice
, c
->choice2
);
1899 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1901 if (!warn
&& !errors
&& !verbose
)
1902 _cupsLangPuts(stdout
, _(" FAIL\n"));
1904 _cupsLangPrintf(stdout
,
1905 _(" %s Missing option %s in "
1906 "UIConstraints \"*%s %s *%s %s\"!\n"),
1908 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1913 else if (choice
[0] && !ppdFindChoice(o
, choice
))
1915 if (!warn
&& !errors
&& !verbose
)
1916 _cupsLangPuts(stdout
, _(" FAIL\n"));
1918 _cupsLangPrintf(stdout
,
1919 _(" %s Missing choice *%s %s in "
1920 "UIConstraints \"*%s %s *%s %s\"!\n"),
1921 prefix
, c
->option2
, c
->choice2
,
1922 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1935 * 'check_case()' - Check that there are no duplicate groups, options,
1936 * or choices that differ only by case.
1939 static int /* O - Errors found */
1940 check_case(ppd_file_t
*ppd
, /* I - PPD file */
1941 int errors
, /* I - Errors found */
1942 int verbose
) /* I - Verbosity level */
1944 int i
, j
; /* Looping vars */
1945 ppd_group_t
*groupa
, /* First group */
1946 *groupb
; /* Second group */
1947 ppd_option_t
*optiona
, /* First option */
1948 *optionb
; /* Second option */
1949 ppd_choice_t
*choicea
, /* First choice */
1950 *choiceb
; /* Second choice */
1954 * Check that the groups do not have any duplicate names...
1957 for (i
= ppd
->num_groups
, groupa
= ppd
->groups
; i
> 1; i
--, groupa
++)
1958 for (j
= i
- 1, groupb
= groupa
+ 1; j
> 0; j
--, groupb
++)
1959 if (!strcasecmp(groupa
->name
, groupb
->name
))
1961 if (!errors
&& !verbose
)
1962 _cupsLangPuts(stdout
, _(" FAIL\n"));
1965 _cupsLangPrintf(stdout
,
1966 _(" **FAIL** Group names %s and %s differ only "
1968 groupa
->name
, groupb
->name
);
1974 * Check that the options do not have any duplicate names...
1977 for (optiona
= ppdFirstOption(ppd
); optiona
; optiona
= ppdNextOption(ppd
))
1979 cupsArraySave(ppd
->options
);
1980 for (optionb
= ppdNextOption(ppd
); optionb
; optionb
= ppdNextOption(ppd
))
1981 if (!strcasecmp(optiona
->keyword
, optionb
->keyword
))
1983 if (!errors
&& !verbose
)
1984 _cupsLangPuts(stdout
, _(" FAIL\n"));
1987 _cupsLangPrintf(stdout
,
1988 _(" **FAIL** Option names %s and %s differ only "
1990 optiona
->keyword
, optionb
->keyword
);
1994 cupsArrayRestore(ppd
->options
);
1997 * Then the choices...
2000 for (i
= optiona
->num_choices
, choicea
= optiona
->choices
;
2003 for (j
= i
- 1, choiceb
= choicea
+ 1; j
> 0; j
--, choiceb
++)
2004 if (!strcmp(choicea
->choice
, choiceb
->choice
))
2006 if (!errors
&& !verbose
)
2007 _cupsLangPuts(stdout
, _(" FAIL\n"));
2010 _cupsLangPrintf(stdout
,
2011 _(" **FAIL** Multiple occurrences of %s "
2012 "choice name %s!\n"),
2013 optiona
->keyword
, choicea
->choice
);
2021 else if (!strcasecmp(choicea
->choice
, choiceb
->choice
))
2023 if (!errors
&& !verbose
)
2024 _cupsLangPuts(stdout
, _(" FAIL\n"));
2027 _cupsLangPrintf(stdout
,
2028 _(" **FAIL** %s choice names %s and %s "
2029 "differ only by case!\n"),
2030 optiona
->keyword
, choicea
->choice
, choiceb
->choice
);
2037 * Return the number of errors found...
2045 * 'check_defaults()' - Check default option keywords in the PPD file.
2048 static int /* O - Errors found */
2049 check_defaults(ppd_file_t
*ppd
, /* I - PPD file */
2050 int errors
, /* I - Errors found */
2051 int verbose
, /* I - Verbosity level */
2052 int warn
) /* I - Warnings only? */
2054 int j
, k
; /* Looping vars */
2055 ppd_attr_t
*attr
; /* PPD attribute */
2056 ppd_option_t
*option
; /* Standard UI option */
2057 const char *prefix
; /* WARN/FAIL prefix */
2060 prefix
= warn
? " WARN " : "**FAIL**";
2062 for (j
= 0; j
< ppd
->num_attrs
; j
++)
2064 attr
= ppd
->attrs
[j
];
2066 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
2067 !strcmp(attr
->name
, "DefaultFont") ||
2068 !strcmp(attr
->name
, "DefaultHalftoneType") ||
2069 !strcmp(attr
->name
, "DefaultImageableArea") ||
2070 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
2071 !strcmp(attr
->name
, "DefaultOutputOrder") ||
2072 !strcmp(attr
->name
, "DefaultPaperDimension") ||
2073 !strcmp(attr
->name
, "DefaultResolution") ||
2074 !strcmp(attr
->name
, "DefaultTransfer"))
2077 if (!strncmp(attr
->name
, "Default", 7))
2079 if ((option
= ppdFindOption(ppd
, attr
->name
+ 7)) != NULL
&&
2080 strcmp(attr
->value
, "Unknown"))
2083 * Check that the default option value matches a choice...
2086 for (k
= 0; k
< option
->num_choices
; k
++)
2087 if (!strcmp(option
->choices
[k
].choice
, attr
->value
))
2090 if (k
>= option
->num_choices
)
2092 if (!warn
&& !errors
&& !verbose
)
2093 _cupsLangPuts(stdout
, _(" FAIL\n"));
2096 _cupsLangPrintf(stdout
,
2097 _(" %s %s %s does not exist!\n"),
2098 prefix
, attr
->name
, attr
->value
);
2112 * 'check_duplex()' - Check duplex keywords in the PPD file.
2115 static int /* O - Errors found */
2116 check_duplex(ppd_file_t
*ppd
, /* I - PPD file */
2117 int errors
, /* I - Error found */
2118 int verbose
, /* I - Verbosity level */
2119 int warn
) /* I - Warnings only? */
2121 int i
; /* Looping var */
2122 ppd_option_t
*option
; /* PPD option */
2123 ppd_choice_t
*choice
; /* Current choice */
2124 const char *prefix
; /* Message prefix */
2127 prefix
= warn
? " WARN " : "**FAIL**";
2130 * Check for a duplex option, and for standard values...
2133 if ((option
= ppdFindOption(ppd
, "Duplex")) != NULL
)
2135 if (!ppdFindChoice(option
, "None"))
2139 if (!warn
&& !errors
&& !verbose
)
2140 _cupsLangPuts(stdout
, _(" FAIL\n"));
2142 _cupsLangPrintf(stdout
,
2143 _(" %s REQUIRED %s does not define "
2145 " REF: Page 122, section 5.17\n"),
2146 prefix
, option
->keyword
);
2153 for (i
= option
->num_choices
, choice
= option
->choices
;
2156 if (strcmp(choice
->choice
, "None") &&
2157 strcmp(choice
->choice
, "DuplexNoTumble") &&
2158 strcmp(choice
->choice
, "DuplexTumble") &&
2159 strcmp(choice
->choice
, "SimplexTumble"))
2163 if (!warn
&& !errors
&& !verbose
)
2164 _cupsLangPuts(stdout
, _(" FAIL\n"));
2166 _cupsLangPrintf(stdout
,
2167 _(" %s Bad %s choice %s!\n"
2168 " REF: Page 122, section 5.17\n"),
2169 prefix
, option
->keyword
, choice
->choice
);
2182 * 'check_filters()' - Check filters in the PPD file.
2185 static int /* O - Errors found */
2186 check_filters(ppd_file_t
*ppd
, /* I - PPD file */
2187 const char *root
, /* I - Root directory */
2188 int errors
, /* I - Errors found */
2189 int verbose
, /* I - Verbosity level */
2190 int warn
) /* I - Warnings only? */
2192 int i
; /* Looping var */
2193 ppd_attr_t
*attr
; /* PPD attribute */
2194 const char *ptr
; /* Pointer into string */
2195 char super
[16], /* Super-type for filter */
2196 type
[256], /* Type for filter */
2197 program
[1024], /* Program/filter name */
2198 pathprog
[1024]; /* Complete path to program/filter */
2199 int cost
; /* Cost of filter */
2200 const char *prefix
; /* WARN/FAIL prefix */
2203 prefix
= warn
? " WARN " : "**FAIL**";
2205 for (i
= 0; i
< ppd
->num_filters
; i
++)
2207 if (sscanf(ppd
->filters
[i
], "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2208 &cost
, program
) != 4)
2210 if (!warn
&& !errors
&& !verbose
)
2211 _cupsLangPuts(stdout
, _(" FAIL\n"));
2214 _cupsLangPrintf(stdout
,
2215 _(" %s Bad cupsFilter value \"%s\"!\n"),
2216 prefix
, ppd
->filters
[i
]);
2221 else if (strcmp(program
, "-"))
2223 if (program
[0] == '/')
2224 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2227 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2228 ptr
= CUPS_SERVERBIN
;
2230 if (*ptr
== '/' || !*root
)
2231 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2234 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2238 if (access(pathprog
, X_OK
))
2240 if (!warn
&& !errors
&& !verbose
)
2241 _cupsLangPuts(stdout
, _(" FAIL\n"));
2244 _cupsLangPrintf(stdout
, _(" %s Missing cupsFilter "
2245 "file \"%s\"\n"), prefix
, program
);
2253 for (attr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
);
2255 attr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
))
2258 sscanf(attr
->value
, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2259 &cost
, program
) != 4)
2261 if (!warn
&& !errors
&& !verbose
)
2262 _cupsLangPuts(stdout
, _(" FAIL\n"));
2265 _cupsLangPrintf(stdout
,
2266 _(" %s Bad cupsPreFilter value \"%s\"!\n"),
2267 prefix
, attr
->value
? attr
->value
: "");
2272 else if (strcmp(program
, "-"))
2274 if (program
[0] == '/')
2275 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2278 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2279 ptr
= CUPS_SERVERBIN
;
2281 if (*ptr
== '/' || !*root
)
2282 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2285 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2289 if (access(pathprog
, X_OK
))
2291 if (!warn
&& !errors
&& !verbose
)
2292 _cupsLangPuts(stdout
, _(" FAIL\n"));
2295 _cupsLangPrintf(stdout
, _(" %s Missing cupsPreFilter "
2296 "file \"%s\"\n"), prefix
, program
);
2309 * 'check_profiles()' - Check ICC color profiles in the PPD file.
2312 static int /* O - Errors found */
2313 check_profiles(ppd_file_t
*ppd
, /* I - PPD file */
2314 const char *root
, /* I - Root directory */
2315 int errors
, /* I - Errors found */
2316 int verbose
, /* I - Verbosity level */
2317 int warn
) /* I - Warnings only? */
2319 int i
; /* Looping var */
2320 ppd_attr_t
*attr
; /* PPD attribute */
2321 const char *ptr
; /* Pointer into string */
2322 const char *prefix
; /* WARN/FAIL prefix */
2323 char filename
[1024]; /* Profile filename */
2324 int num_profiles
= 0; /* Number of profiles */
2325 unsigned hash
, /* Current hash value */
2326 hashes
[1000]; /* Hash values of profile names */
2327 const char *specs
[1000]; /* Specifiers for profiles */
2330 prefix
= warn
? " WARN " : "**FAIL**";
2332 for (attr
= ppdFindAttr(ppd
, "cupsICCProfile", NULL
);
2334 attr
= ppdFindNextAttr(ppd
, "cupsICCProfile", NULL
))
2337 * Check for valid selector...
2340 for (i
= 0, ptr
= strchr(attr
->spec
, '.'); ptr
; ptr
= strchr(ptr
+ 1, '.'))
2343 if (!attr
->value
|| i
< 2)
2345 if (!warn
&& !errors
&& !verbose
)
2346 _cupsLangPuts(stdout
, _(" FAIL\n"));
2349 _cupsLangPrintf(stdout
,
2350 _(" %s Bad cupsICCProfile %s!\n"),
2351 prefix
, attr
->spec
);
2360 * Check for valid profile filename...
2363 if (attr
->value
[0] == '/')
2364 snprintf(filename
, sizeof(filename
), "%s%s", root
, attr
->value
);
2367 if ((ptr
= getenv("CUPS_DATADIR")) == NULL
)
2370 if (*ptr
== '/' || !*root
)
2371 snprintf(filename
, sizeof(filename
), "%s%s/profiles/%s", root
, ptr
,
2374 snprintf(filename
, sizeof(filename
), "%s/%s/profiles/%s", root
, ptr
,
2378 if (access(filename
, 0))
2380 if (!warn
&& !errors
&& !verbose
)
2381 _cupsLangPuts(stdout
, _(" FAIL\n"));
2384 _cupsLangPrintf(stdout
, _(" %s Missing cupsICCProfile "
2385 "file \"%s\"!\n"), prefix
, attr
->value
);
2392 * Check for hash collisions...
2395 hash
= _ppdHashName(attr
->spec
);
2397 if (num_profiles
> 0)
2399 for (i
= 0; i
< num_profiles
; i
++)
2400 if (hashes
[i
] == hash
)
2403 if (i
< num_profiles
)
2405 if (!warn
&& !errors
&& !verbose
)
2406 _cupsLangPuts(stdout
, _(" FAIL\n"));
2409 _cupsLangPrintf(stdout
,
2410 _(" %s cupsICCProfile %s hash value "
2411 "collides with %s!\n"), prefix
, attr
->spec
,
2420 * Remember up to 1000 profiles...
2423 if (num_profiles
< 1000)
2425 hashes
[num_profiles
] = hash
;
2426 specs
[num_profiles
] = attr
->spec
;
2436 * 'check_translations()' - Check translations in the PPD file.
2439 static int /* O - Errors found */
2440 check_translations(ppd_file_t
*ppd
, /* I - PPD file */
2441 int errors
, /* I - Errors found */
2442 int verbose
, /* I - Verbosity level */
2443 int warn
) /* I - Warnings only? */
2445 int j
; /* Looping var */
2446 ppd_attr_t
*attr
; /* PPD attribute */
2447 cups_array_t
*languages
; /* Array of languages */
2448 int langlen
; /* Length of language */
2449 char *language
, /* Current language */
2450 keyword
[PPD_MAX_NAME
], /* Localization keyword (full) */
2451 llkeyword
[PPD_MAX_NAME
],/* Localization keyword (base) */
2452 ckeyword
[PPD_MAX_NAME
], /* Custom option keyword (full) */
2453 cllkeyword
[PPD_MAX_NAME
];
2454 /* Custom option keyword (base) */
2455 ppd_option_t
*option
; /* Standard UI option */
2456 ppd_coption_t
*coption
; /* Custom option */
2457 ppd_cparam_t
*cparam
; /* Custom parameter */
2458 char ll
[3]; /* Base language */
2459 const char *prefix
; /* WARN/FAIL prefix */
2460 const char *text
; /* Pointer into UI text */
2463 prefix
= warn
? " WARN " : "**FAIL**";
2465 if ((languages
= _ppdGetLanguages(ppd
)) != NULL
)
2468 * This file contains localizations, check them...
2471 for (language
= (char *)cupsArrayFirst(languages
);
2473 language
= (char *)cupsArrayNext(languages
))
2475 langlen
= strlen(language
);
2476 if (langlen
!= 2 && langlen
!= 5)
2478 if (!warn
&& !errors
&& !verbose
)
2479 _cupsLangPuts(stdout
, _(" FAIL\n"));
2482 _cupsLangPrintf(stdout
,
2483 _(" %s Bad language \"%s\"!\n"),
2492 if (!strcmp(language
, "en"))
2495 strlcpy(ll
, language
, sizeof(ll
));
2498 * Loop through all options and choices...
2501 for (option
= ppdFirstOption(ppd
);
2503 option
= ppdNextOption(ppd
))
2505 if (!strcmp(option
->keyword
, "PageRegion"))
2508 snprintf(keyword
, sizeof(keyword
), "%s.Translation", language
);
2509 snprintf(llkeyword
, sizeof(llkeyword
), "%s.Translation", ll
);
2511 if ((attr
= ppdFindAttr(ppd
, keyword
, option
->keyword
)) == NULL
&&
2512 (attr
= ppdFindAttr(ppd
, llkeyword
, option
->keyword
)) == NULL
)
2514 if (!warn
&& !errors
&& !verbose
)
2515 _cupsLangPuts(stdout
, _(" FAIL\n"));
2518 _cupsLangPrintf(stdout
,
2519 _(" %s Missing \"%s\" translation "
2520 "string for option %s!\n"),
2521 prefix
, language
, option
->keyword
);
2526 else if (!valid_utf8(attr
->text
))
2528 if (!warn
&& !errors
&& !verbose
)
2529 _cupsLangPuts(stdout
, _(" FAIL\n"));
2532 _cupsLangPrintf(stdout
,
2533 _(" %s Bad UTF-8 \"%s\" translation "
2534 "string for option %s!\n"),
2535 prefix
, language
, option
->keyword
);
2541 snprintf(keyword
, sizeof(keyword
), "%s.%s", language
,
2543 snprintf(llkeyword
, sizeof(llkeyword
), "%s.%s", ll
,
2546 for (j
= 0; j
< option
->num_choices
; j
++)
2549 * First see if this choice is a number; if so, don't require
2553 for (text
= option
->choices
[j
].text
; *text
; text
++)
2554 if (!strchr("0123456789-+.", *text
))
2561 * Check custom choices differently...
2564 if (!strcasecmp(option
->choices
[j
].choice
, "Custom") &&
2565 (coption
= ppdFindCustomOption(ppd
,
2566 option
->keyword
)) != NULL
)
2568 snprintf(ckeyword
, sizeof(ckeyword
), "%s.Custom%s",
2569 language
, option
->keyword
);
2571 if ((attr
= ppdFindAttr(ppd
, ckeyword
, "True")) != NULL
&&
2572 !valid_utf8(attr
->text
))
2574 if (!warn
&& !errors
&& !verbose
)
2575 _cupsLangPuts(stdout
, _(" FAIL\n"));
2578 _cupsLangPrintf(stdout
,
2579 _(" %s Bad UTF-8 \"%s\" "
2580 "translation string for option %s, "
2583 ckeyword
+ 1 + strlen(language
),
2590 if (strcasecmp(option
->keyword
, "PageSize"))
2592 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
2594 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
2596 snprintf(ckeyword
, sizeof(ckeyword
), "%s.ParamCustom%s",
2597 language
, option
->keyword
);
2598 snprintf(cllkeyword
, sizeof(cllkeyword
), "%s.ParamCustom%s",
2599 ll
, option
->keyword
);
2601 if ((attr
= ppdFindAttr(ppd
, ckeyword
,
2602 cparam
->name
)) == NULL
&&
2603 (attr
= ppdFindAttr(ppd
, cllkeyword
,
2604 cparam
->name
)) == NULL
)
2606 if (!warn
&& !errors
&& !verbose
)
2607 _cupsLangPuts(stdout
, _(" FAIL\n"));
2610 _cupsLangPrintf(stdout
,
2611 _(" %s Missing \"%s\" "
2612 "translation string for option %s, "
2615 ckeyword
+ 1 + strlen(language
),
2621 else if (!valid_utf8(attr
->text
))
2623 if (!warn
&& !errors
&& !verbose
)
2624 _cupsLangPuts(stdout
, _(" FAIL\n"));
2627 _cupsLangPrintf(stdout
,
2628 _(" %s Bad UTF-8 \"%s\" "
2629 "translation string for option %s, "
2632 ckeyword
+ 1 + strlen(language
),
2641 else if ((attr
= ppdFindAttr(ppd
, keyword
,
2642 option
->choices
[j
].choice
)) == NULL
&&
2643 (attr
= ppdFindAttr(ppd
, llkeyword
,
2644 option
->choices
[j
].choice
)) == NULL
)
2646 if (!warn
&& !errors
&& !verbose
)
2647 _cupsLangPuts(stdout
, _(" FAIL\n"));
2650 _cupsLangPrintf(stdout
,
2651 _(" %s Missing \"%s\" "
2652 "translation string for option %s, "
2654 prefix
, language
, option
->keyword
,
2655 option
->choices
[j
].choice
);
2660 else if (!valid_utf8(attr
->text
))
2662 if (!warn
&& !errors
&& !verbose
)
2663 _cupsLangPuts(stdout
, _(" FAIL\n"));
2666 _cupsLangPrintf(stdout
,
2667 _(" %s Bad UTF-8 \"%s\" "
2668 "translation string for option %s, "
2670 prefix
, language
, option
->keyword
,
2671 option
->choices
[j
].choice
);
2681 * Verify that we have the base language for each localized one...
2684 for (language
= (char *)cupsArrayFirst(languages
);
2686 language
= (char *)cupsArrayNext(languages
))
2690 * Lookup the base language...
2693 cupsArraySave(languages
);
2695 strlcpy(ll
, language
, sizeof(ll
));
2697 if (!cupsArrayFind(languages
, ll
) &&
2698 strcmp(ll
, "zh") && strcmp(ll
, "en"))
2700 if (!warn
&& !errors
&& !verbose
)
2701 _cupsLangPuts(stdout
, _(" FAIL\n"));
2704 _cupsLangPrintf(stdout
,
2705 _(" %s No base translation \"%s\" "
2706 "is included in file!\n"), prefix
, ll
);
2712 cupsArrayRestore(languages
);
2716 * Free memory used for the languages...
2719 _ppdFreeLanguages(languages
);
2727 * 'show_conflicts()' - Show option conflicts in a PPD file.
2731 show_conflicts(ppd_file_t
*ppd
) /* I - PPD to check */
2733 int i
, j
; /* Looping variables */
2734 ppd_const_t
*c
; /* Current constraint */
2735 ppd_option_t
*o1
, *o2
; /* Options */
2736 ppd_choice_t
*c1
, *c2
; /* Choices */
2740 * Loop through all of the UI constraints and report any options
2744 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
2747 * Grab pointers to the first option...
2750 o1
= ppdFindOption(ppd
, c
->option1
);
2754 else if (c
->choice1
[0] != '\0')
2757 * This constraint maps to a specific choice.
2760 c1
= ppdFindChoice(o1
, c
->choice1
);
2765 * This constraint applies to any choice for this option.
2768 for (j
= o1
->num_choices
, c1
= o1
->choices
; j
> 0; j
--, c1
++)
2773 !strcasecmp(c1
->choice
, "None") ||
2774 !strcasecmp(c1
->choice
, "Off") ||
2775 !strcasecmp(c1
->choice
, "False"))
2780 * Grab pointers to the second option...
2783 o2
= ppdFindOption(ppd
, c
->option2
);
2787 else if (c
->choice2
[0] != '\0')
2790 * This constraint maps to a specific choice.
2793 c2
= ppdFindChoice(o2
, c
->choice2
);
2798 * This constraint applies to any choice for this option.
2801 for (j
= o2
->num_choices
, c2
= o2
->choices
; j
> 0; j
--, c2
++)
2806 !strcasecmp(c2
->choice
, "None") ||
2807 !strcasecmp(c2
->choice
, "Off") ||
2808 !strcasecmp(c2
->choice
, "False"))
2813 * If both options are marked then there is a conflict...
2816 if (c1
!= NULL
&& c1
->marked
&& c2
!= NULL
&& c2
->marked
)
2817 _cupsLangPrintf(stdout
,
2818 _(" WARN \"%s %s\" conflicts with \"%s %s\"\n"
2819 " (constraint=\"%s %s %s %s\")\n"),
2820 o1
->keyword
, c1
->choice
, o2
->keyword
, c2
->choice
,
2821 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2827 * 'test_raster()' - Test PostScript commands for raster printers.
2830 static int /* O - 1 on success, 0 on failure */
2831 test_raster(ppd_file_t
*ppd
, /* I - PPD file */
2832 int verbose
) /* I - Verbosity */
2834 cups_page_header2_t header
; /* Page header */
2837 ppdMarkDefaults(ppd
);
2838 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
2841 _cupsLangPuts(stdout
, _(" FAIL\n"));
2844 _cupsLangPrintf(stdout
,
2845 _(" **FAIL** Default option code cannot be "
2846 "interpreted: %s\n"), cupsRasterErrorString());
2852 * Try a test of custom page size code, if available...
2855 if (!ppdPageSize(ppd
, "Custom.612x792"))
2858 ppdMarkOption(ppd
, "PageSize", "Custom.612x792");
2860 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
2863 _cupsLangPuts(stdout
, _(" FAIL\n"));
2866 _cupsLangPrintf(stdout
,
2867 _(" **FAIL** Default option code cannot be "
2868 "interpreted: %s\n"), cupsRasterErrorString());
2878 * 'usage()' - Show program usage...
2884 _cupsLangPuts(stdout
,
2885 _("Usage: cupstestppd [options] filename1.ppd[.gz] "
2886 "[... filenameN.ppd[.gz]]\n"
2887 " program | cupstestppd [options] -\n"
2891 " -R root-directory Set alternate root\n"
2892 " -W {all,none,constraints,defaults,duplex,filters,"
2894 " Issue warnings instead of errors\n"
2895 " -q Run silently\n"
2896 " -r Use 'relaxed' open mode\n"
2897 " -v Be slightly verbose\n"
2898 " -vv Be very verbose\n"));
2905 * 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
2908 static int /* O - 1 if valid, 0 if not */
2909 valid_utf8(const char *s
) /* I - String to check */
2916 * Check for valid UTF-8 sequence...
2919 if ((*s
& 0xc0) == 0x80)
2920 return (0); /* Illegal suffix byte */
2921 else if ((*s
& 0xe0) == 0xc0)
2924 * 2-byte sequence...
2929 if ((*s
& 0xc0) != 0x80)
2930 return (0); /* Missing suffix byte */
2932 else if ((*s
& 0xf0) == 0xe0)
2935 * 3-byte sequence...
2940 if ((*s
& 0xc0) != 0x80)
2941 return (0); /* Missing suffix byte */
2945 if ((*s
& 0xc0) != 0x80)
2946 return (0); /* Missing suffix byte */
2948 else if ((*s
& 0xf8) == 0xf0)
2951 * 4-byte sequence...
2956 if ((*s
& 0xc0) != 0x80)
2957 return (0); /* Missing suffix byte */
2961 if ((*s
& 0xc0) != 0x80)
2962 return (0); /* Missing suffix byte */
2966 if ((*s
& 0xc0) != 0x80)
2967 return (0); /* Missing suffix byte */
2970 return (0); /* Bad sequence */
2981 * End of "$Id: cupstestppd.c 7807 2008-07-28 21:54:24Z mike $".