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 ((attr
= ppdFindAttr(ppd
, "FileVersion", NULL
)) != NULL
)
519 for (ptr
= attr
->value
; *ptr
; ptr
++)
520 if (!isdigit(*ptr
& 255) && *ptr
!= '.')
527 if (!errors
&& !verbose
)
528 _cupsLangPuts(stdout
, _(" FAIL\n"));
530 _cupsLangPrintf(stdout
,
531 _(" **FAIL** Bad FileVersion \"%s\"\n"
532 " REF: Page 56, section 5.3.\n"),
538 else if (verbose
> 0)
539 _cupsLangPuts(stdout
, _(" PASS FileVersion\n"));
545 if (!errors
&& !verbose
)
546 _cupsLangPuts(stdout
, _(" FAIL\n"));
548 _cupsLangPuts(stdout
,
549 _(" **FAIL** REQUIRED FileVersion\n"
550 " REF: Page 56, section 5.3.\n"));
556 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
)
559 if (*ptr
== '4' && ptr
[1] == '.')
562 for (ptr
+= 2; *ptr
; ptr
++)
563 if (!isdigit(*ptr
& 255))
571 if (!errors
&& !verbose
)
572 _cupsLangPuts(stdout
, _(" FAIL\n"));
574 _cupsLangPrintf(stdout
,
575 _(" **FAIL** Bad FormatVersion \"%s\"\n"
576 " REF: Page 56, section 5.3.\n"),
582 else if (verbose
> 0)
583 _cupsLangPuts(stdout
, _(" PASS FormatVersion\n"));
589 if (!errors
&& !verbose
)
590 _cupsLangPuts(stdout
, _(" FAIL\n"));
592 _cupsLangPuts(stdout
,
593 _(" **FAIL** REQUIRED FormatVersion\n"
594 " REF: Page 56, section 5.3.\n"));
600 if (ppd
->lang_encoding
!= NULL
)
603 _cupsLangPuts(stdout
, _(" PASS LanguageEncoding\n"));
605 else if (ppdversion
> 40)
609 if (!errors
&& !verbose
)
610 _cupsLangPuts(stdout
, _(" FAIL\n"));
612 _cupsLangPuts(stdout
,
613 _(" **FAIL** REQUIRED LanguageEncoding\n"
614 " REF: Pages 56-57, section 5.3.\n"));
620 if (ppd
->lang_version
!= NULL
)
623 _cupsLangPuts(stdout
, _(" PASS LanguageVersion\n"));
629 if (!errors
&& !verbose
)
630 _cupsLangPuts(stdout
, _(" FAIL\n"));
632 _cupsLangPuts(stdout
,
633 _(" **FAIL** REQUIRED LanguageVersion\n"
634 " REF: Pages 57-58, section 5.3.\n"));
640 if (ppd
->manufacturer
!= NULL
)
642 if (!strncasecmp(ppd
->manufacturer
, "Hewlett-Packard", 15) ||
643 !strncasecmp(ppd
->manufacturer
, "Hewlett Packard", 15))
647 if (!errors
&& !verbose
)
648 _cupsLangPuts(stdout
, _(" FAIL\n"));
650 _cupsLangPuts(stdout
,
651 _(" **FAIL** BAD Manufacturer (should be "
653 " REF: Page 211, table D.1.\n"));
658 else if (!strncasecmp(ppd
->manufacturer
, "OkiData", 7) ||
659 !strncasecmp(ppd
->manufacturer
, "Oki Data", 8))
663 if (!errors
&& !verbose
)
664 _cupsLangPuts(stdout
, _(" FAIL\n"));
666 _cupsLangPuts(stdout
,
667 _(" **FAIL** BAD Manufacturer (should be "
669 " REF: Page 211, table D.1.\n"));
674 else if (verbose
> 0)
675 _cupsLangPuts(stdout
, _(" PASS Manufacturer\n"));
677 else if (ppdversion
>= 43)
681 if (!errors
&& !verbose
)
682 _cupsLangPuts(stdout
, _(" FAIL\n"));
684 _cupsLangPuts(stdout
,
685 _(" **FAIL** REQUIRED Manufacturer\n"
686 " REF: Pages 58-59, section 5.3.\n"));
692 if (ppd
->modelname
!= NULL
)
694 for (ptr
= ppd
->modelname
; *ptr
; ptr
++)
695 if (!isalnum(*ptr
& 255) && !strchr(" ./-+", *ptr
))
702 if (!errors
&& !verbose
)
703 _cupsLangPuts(stdout
, _(" FAIL\n"));
705 _cupsLangPrintf(stdout
,
706 _(" **FAIL** BAD ModelName - \"%c\" not "
707 "allowed in string.\n"
708 " REF: Pages 59-60, section 5.3.\n"),
714 else if (verbose
> 0)
715 _cupsLangPuts(stdout
, _(" PASS ModelName\n"));
721 if (!errors
&& !verbose
)
722 _cupsLangPuts(stdout
, _(" FAIL\n"));
724 _cupsLangPuts(stdout
,
725 _(" **FAIL** REQUIRED ModelName\n"
726 " REF: Pages 59-60, section 5.3.\n"));
732 if (ppd
->nickname
!= NULL
)
735 _cupsLangPuts(stdout
, _(" PASS NickName\n"));
741 if (!errors
&& !verbose
)
742 _cupsLangPuts(stdout
, _(" FAIL\n"));
744 _cupsLangPuts(stdout
,
745 _(" **FAIL** REQUIRED NickName\n"
746 " REF: Page 60, section 5.3.\n"));
752 if (ppdFindOption(ppd
, "PageSize") != NULL
)
755 _cupsLangPuts(stdout
, _(" PASS PageSize\n"));
761 if (!errors
&& !verbose
)
762 _cupsLangPuts(stdout
, _(" FAIL\n"));
764 _cupsLangPuts(stdout
,
765 _(" **FAIL** REQUIRED PageSize\n"
766 " REF: Pages 99-100, section 5.14.\n"));
772 if (ppdFindOption(ppd
, "PageRegion") != NULL
)
775 _cupsLangPuts(stdout
, _(" PASS PageRegion\n"));
781 if (!errors
&& !verbose
)
782 _cupsLangPuts(stdout
, _(" FAIL\n"));
784 _cupsLangPuts(stdout
,
785 _(" **FAIL** REQUIRED PageRegion\n"
786 " REF: Page 100, section 5.14.\n"));
792 if (ppd
->pcfilename
!= NULL
)
795 _cupsLangPuts(stdout
, _(" PASS PCFileName\n"));
801 if (!errors
&& !verbose
)
802 _cupsLangPuts(stdout
, _(" FAIL\n"));
804 _cupsLangPuts(stdout
,
805 _(" **FAIL** REQUIRED PCFileName\n"
806 " REF: Pages 61-62, section 5.3.\n"));
812 if (ppd
->product
!= NULL
)
814 if (ppd
->product
[0] != '(' ||
815 ppd
->product
[strlen(ppd
->product
) - 1] != ')')
819 if (!errors
&& !verbose
)
820 _cupsLangPuts(stdout
, _(" FAIL\n"));
822 _cupsLangPuts(stdout
,
823 _(" **FAIL** BAD Product - not \"(string)\".\n"
824 " REF: Page 62, section 5.3.\n"));
829 else if (verbose
> 0)
830 _cupsLangPuts(stdout
, _(" PASS Product\n"));
836 if (!errors
&& !verbose
)
837 _cupsLangPuts(stdout
, _(" FAIL\n"));
839 _cupsLangPuts(stdout
,
840 _(" **FAIL** REQUIRED Product\n"
841 " REF: Page 62, section 5.3.\n"));
847 if ((attr
= ppdFindAttr(ppd
, "PSVersion", NULL
)) != NULL
&&
850 char junkstr
[255]; /* Temp string */
851 int junkint
; /* Temp integer */
854 if (sscanf(attr
->value
, "(%[^)])%d", junkstr
, &junkint
) != 2)
858 if (!errors
&& !verbose
)
859 _cupsLangPuts(stdout
, _(" FAIL\n"));
861 _cupsLangPuts(stdout
,
862 _(" **FAIL** BAD PSVersion - not \"(string) "
864 " REF: Pages 62-64, section 5.3.\n"));
869 else if (verbose
> 0)
870 _cupsLangPuts(stdout
, _(" PASS PSVersion\n"));
876 if (!errors
&& !verbose
)
877 _cupsLangPuts(stdout
, _(" FAIL\n"));
879 _cupsLangPuts(stdout
,
880 _(" **FAIL** REQUIRED PSVersion\n"
881 " REF: Pages 62-64, section 5.3.\n"));
887 if (ppd
->shortnickname
!= NULL
)
889 if (strlen(ppd
->shortnickname
) > 31)
893 if (!errors
&& !verbose
)
894 _cupsLangPuts(stdout
, _(" FAIL\n"));
896 _cupsLangPuts(stdout
,
897 _(" **FAIL** BAD ShortNickName - longer "
899 " REF: Pages 64-65, section 5.3.\n"));
904 else if (verbose
> 0)
905 _cupsLangPuts(stdout
, _(" PASS ShortNickName\n"));
907 else if (ppdversion
>= 43)
911 if (!errors
&& !verbose
)
912 _cupsLangPuts(stdout
, _(" FAIL\n"));
914 _cupsLangPuts(stdout
,
915 _(" **FAIL** REQUIRED ShortNickName\n"
916 " REF: Page 64-65, section 5.3.\n"));
922 if (ppd
->patches
!= NULL
&& strchr(ppd
->patches
, '\"') &&
923 strstr(ppd
->patches
, "*End"))
927 if (!errors
&& !verbose
)
928 _cupsLangPuts(stdout
, _(" FAIL\n"));
930 _cupsLangPuts(stdout
,
931 _(" **FAIL** BAD JobPatchFile attribute in file\n"
932 " REF: Page 24, section 3.4.\n"));
939 * Check for page sizes without the corresponding ImageableArea or
940 * PaperDimension values...
943 if (ppd
->num_sizes
== 0)
947 if (!errors
&& !verbose
)
948 _cupsLangPuts(stdout
, _(" FAIL\n"));
950 _cupsLangPuts(stdout
,
951 _(" **FAIL** REQUIRED PageSize\n"
952 " REF: Page 41, section 5.\n"
953 " REF: Page 99, section 5.14.\n"));
960 for (j
= 0, size
= ppd
->sizes
; j
< ppd
->num_sizes
; j
++, size
++)
963 * Don't check custom size...
966 if (!strcmp(size
->name
, "Custom"))
970 * Check for ImageableArea...
973 if (size
->left
== 0.0 && size
->bottom
== 0.0 &&
974 size
->right
== 0.0 && size
->top
== 0.0)
978 if (!errors
&& !verbose
)
979 _cupsLangPuts(stdout
, _(" FAIL\n"));
981 _cupsLangPrintf(stdout
,
982 _(" **FAIL** REQUIRED ImageableArea for "
984 " REF: Page 41, section 5.\n"
985 " REF: Page 102, section 5.15.\n"),
993 * Check for PaperDimension...
996 if (size
->width
== 0.0 && size
->length
== 0.0)
1000 if (!errors
&& !verbose
)
1001 _cupsLangPuts(stdout
, _(" FAIL\n"));
1003 _cupsLangPrintf(stdout
,
1004 _(" **FAIL** REQUIRED PaperDimension "
1006 " REF: Page 41, section 5.\n"
1007 " REF: Page 103, section 5.15.\n"),
1017 * Check for valid Resolution, JCLResolution, or SetResolution values...
1020 if ((option
= ppdFindOption(ppd
, "Resolution")) == NULL
)
1021 if ((option
= ppdFindOption(ppd
, "JCLResolution")) == NULL
)
1022 option
= ppdFindOption(ppd
, "SetResolution");
1026 for (j
= option
->num_choices
, choice
= option
->choices
; j
> 0; j
--, choice
++)
1029 * Verify that all resolution options are of the form NNNdpi
1033 xdpi
= strtol(choice
->choice
, (char **)&ptr
, 10);
1034 if (ptr
> choice
->choice
&& xdpi
> 0)
1037 ydpi
= strtol(ptr
+ 1, (char **)&ptr
, 10);
1044 if (xdpi
<= 0 || xdpi
> 99999 || ydpi
<= 0 || ydpi
> 99999 ||
1049 if (!errors
&& !verbose
)
1050 _cupsLangPuts(stdout
, _(" FAIL\n"));
1052 _cupsLangPrintf(stdout
,
1053 _(" **FAIL** Bad %s choice %s!\n"
1054 " REF: Page 84, section 5.9\n"),
1055 option
->keyword
, choice
->choice
);
1063 if ((attr
= ppdFindAttr(ppd
, "1284DeviceID", NULL
)) &&
1064 strcmp(attr
->name
, "1284DeviceID"))
1068 if (!errors
&& !verbose
)
1069 _cupsLangPuts(stdout
, _(" FAIL\n"));
1071 _cupsLangPrintf(stdout
,
1072 _(" **FAIL** %s must be 1284DeviceID!\n"
1073 " REF: Page 72, section 5.5\n"),
1080 errors
= check_case(ppd
, errors
, verbose
);
1082 if (!(warn
& WARN_CONSTRAINTS
))
1083 errors
= check_constraints(ppd
, errors
, verbose
, 0);
1085 if (!(warn
& WARN_FILTERS
))
1086 errors
= check_filters(ppd
, root
, errors
, verbose
, 0);
1088 if (!(warn
& WARN_PROFILES
))
1089 errors
= check_profiles(ppd
, root
, errors
, verbose
, 0);
1091 if (!(warn
& WARN_TRANSLATIONS
))
1092 errors
= check_translations(ppd
, errors
, verbose
, 0);
1094 if (!(warn
& WARN_DUPLEX
))
1095 errors
= check_duplex(ppd
, errors
, verbose
, 0);
1097 if ((attr
= ppdFindAttr(ppd
, "cupsLanguages", NULL
)) != NULL
&&
1101 * This file contains localizations, check for conformance of the
1102 * base translation...
1105 if ((attr
= ppdFindAttr(ppd
, "LanguageEncoding", NULL
)) != NULL
)
1107 if (!attr
->value
|| strcmp(attr
->value
, "ISOLatin1"))
1109 if (!errors
&& !verbose
)
1110 _cupsLangPuts(stdout
, _(" FAIL\n"));
1113 _cupsLangPrintf(stdout
,
1114 _(" **FAIL** Bad LanguageEncoding %s - "
1115 "must be ISOLatin1!\n"),
1116 attr
->value
? attr
->value
: "(null)");
1121 if (!ppd
->lang_version
|| strcmp(ppd
->lang_version
, "English"))
1123 if (!errors
&& !verbose
)
1124 _cupsLangPuts(stdout
, _(" FAIL\n"));
1127 _cupsLangPrintf(stdout
,
1128 _(" **FAIL** Bad LanguageVersion %s - "
1129 "must be English!\n"),
1130 ppd
->lang_version
? ppd
->lang_version
: "(null)");
1136 * Loop through all options and choices...
1139 for (option
= ppdFirstOption(ppd
);
1141 option
= ppdNextOption(ppd
))
1144 * Check for special characters outside A0 to BF, F7, or F8
1145 * that are used for languages other than English.
1148 for (ptr
= option
->text
; *ptr
; ptr
++)
1149 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1150 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1155 if (!errors
&& !verbose
)
1156 _cupsLangPuts(stdout
, _(" FAIL\n"));
1159 _cupsLangPrintf(stdout
,
1160 _(" **FAIL** Default translation "
1161 "string for option %s contains 8-bit "
1168 for (j
= 0; j
< option
->num_choices
; j
++)
1171 * Check for special characters outside A0 to BF, F7, or F8
1172 * that are used for languages other than English.
1175 for (ptr
= option
->choices
[j
].text
; *ptr
; ptr
++)
1176 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1177 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1182 if (!errors
&& !verbose
)
1183 _cupsLangPuts(stdout
, _(" FAIL\n"));
1186 _cupsLangPrintf(stdout
,
1187 _(" **FAIL** Default translation "
1188 "string for option %s choice %s contains "
1189 "8-bit characters!\n"),
1191 option
->choices
[j
].choice
);
1201 * Final pass/fail notification...
1205 status
= ERROR_CONFORMANCE
;
1207 _cupsLangPuts(stdout
, _(" PASS\n"));
1211 check_basics(argv
[i
]);
1213 if (warn
& WARN_CONSTRAINTS
)
1214 errors
= check_constraints(ppd
, errors
, verbose
, 1);
1216 if (warn
& WARN_DEFAULTS
)
1217 errors
= check_defaults(ppd
, errors
, verbose
, 1);
1219 if (warn
& WARN_PROFILES
)
1220 errors
= check_profiles(ppd
, root
, errors
, verbose
, 1);
1222 if (warn
& WARN_FILTERS
)
1223 errors
= check_filters(ppd
, root
, errors
, verbose
, 1);
1225 if (warn
& WARN_TRANSLATIONS
)
1226 errors
= check_translations(ppd
, errors
, verbose
, 1);
1228 if (warn
& WARN_DUPLEX
)
1229 errors
= check_duplex(ppd
, errors
, verbose
, 1);
1232 * Look for legacy duplex keywords...
1235 if ((option
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
1236 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
1237 option
= ppdFindOption(ppd
, "KD03Duplex");
1240 _cupsLangPrintf(stdout
,
1241 _(" WARN Duplex option keyword %s may not "
1242 "work as expected and should be named Duplex!\n"
1243 " REF: Page 122, section 5.17\n"),
1247 * Look for default keywords with no corresponding option...
1250 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1252 attr
= ppd
->attrs
[j
];
1254 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
1255 !strcmp(attr
->name
, "DefaultColorSep") ||
1256 !strcmp(attr
->name
, "DefaultFont") ||
1257 !strcmp(attr
->name
, "DefaultHalftoneType") ||
1258 !strcmp(attr
->name
, "DefaultImageableArea") ||
1259 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
1260 !strcmp(attr
->name
, "DefaultOutputOrder") ||
1261 !strcmp(attr
->name
, "DefaultPaperDimension") ||
1262 !strcmp(attr
->name
, "DefaultResolution") ||
1263 !strcmp(attr
->name
, "DefaultScreenProc") ||
1264 !strcmp(attr
->name
, "DefaultTransfer"))
1267 if (!strncmp(attr
->name
, "Default", 7) &&
1268 !ppdFindOption(ppd
, attr
->name
+ 7))
1269 _cupsLangPrintf(stdout
,
1270 _(" WARN %s has no corresponding "
1275 ppdMarkDefaults(ppd
);
1276 if (ppdConflicts(ppd
))
1278 _cupsLangPuts(stdout
,
1279 _(" WARN Default choices conflicting!\n"));
1281 show_conflicts(ppd
);
1284 if (ppdversion
< 43)
1286 _cupsLangPrintf(stdout
,
1287 _(" WARN Obsolete PPD version %.1f!\n"
1288 " REF: Page 42, section 5.2.\n"),
1292 if (!ppd
->lang_encoding
&& ppdversion
< 41)
1294 _cupsLangPuts(stdout
,
1295 _(" WARN LanguageEncoding required by PPD "
1297 " REF: Pages 56-57, section 5.3.\n"));
1300 if (!ppd
->manufacturer
&& ppdversion
< 43)
1302 _cupsLangPuts(stdout
,
1303 _(" WARN Manufacturer required by PPD "
1305 " REF: Pages 58-59, section 5.3.\n"));
1309 * Treat a PCFileName attribute longer than 12 characters as
1310 * a warning and not a hard error...
1313 if (ppd
->pcfilename
&& strlen(ppd
->pcfilename
) > 12)
1315 _cupsLangPuts(stdout
,
1316 _(" WARN PCFileName longer than 8.3 in "
1317 "violation of PPD spec.\n"
1318 " REF: Pages 61-62, section 5.3.\n"));
1321 if (!ppd
->shortnickname
&& ppdversion
< 43)
1323 _cupsLangPuts(stdout
,
1324 _(" WARN ShortNickName required by PPD "
1326 " REF: Pages 64-65, section 5.3.\n"));
1330 * Check the Protocols line and flag PJL + BCP since TBCP is
1331 * usually used with PJL...
1336 if (strstr(ppd
->protocols
, "PJL") &&
1337 strstr(ppd
->protocols
, "BCP") &&
1338 !strstr(ppd
->protocols
, "TBCP"))
1340 _cupsLangPuts(stdout
,
1341 _(" WARN Protocols contains both PJL "
1342 "and BCP; expected TBCP.\n"
1343 " REF: Pages 78-79, section 5.7.\n"));
1346 if (strstr(ppd
->protocols
, "PJL") &&
1347 (!ppd
->jcl_begin
|| !ppd
->jcl_end
|| !ppd
->jcl_ps
))
1349 _cupsLangPuts(stdout
,
1350 _(" WARN Protocols contains PJL but JCL "
1351 "attributes are not set.\n"
1352 " REF: Pages 78-79, section 5.7.\n"));
1357 * Check for options with a common prefix, e.g. Duplex and Duplexer,
1358 * which are errors according to the spec but won't cause problems
1359 * with CUPS specifically...
1362 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1363 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1365 len
= strlen(option
->keyword
);
1367 for (m
= 0, group2
= ppd
->groups
;
1368 m
< ppd
->num_groups
;
1370 for (n
= 0, option2
= group2
->options
;
1371 n
< group2
->num_options
;
1373 if (option
!= option2
&&
1374 len
< strlen(option2
->keyword
) &&
1375 !strncmp(option
->keyword
, option2
->keyword
, len
))
1377 _cupsLangPrintf(stdout
,
1378 _(" WARN %s shares a common "
1380 " REF: Page 15, section "
1382 option
->keyword
, option2
->keyword
);
1392 for (attr
= ppdFindAttr(ppd
, "APDialogExtension", NULL
);
1394 attr
= ppdFindNextAttr(ppd
, "APDialogExtension", NULL
))
1396 if ((!attr
->value
|| access(attr
->value
, 0)) && verbose
>= 0)
1397 _cupsLangPrintf(stdout
, _(" WARN Missing "
1398 "APDialogExtension file \"%s\"\n"),
1399 attr
->value
? attr
->value
: "<NULL>");
1406 for (attr
= ppdFindAttr(ppd
, "APPrinterIconPath", NULL
);
1408 attr
= ppdFindNextAttr(ppd
, "APPrinterIconPath", NULL
))
1410 if ((!attr
->value
|| access(attr
->value
, 0)) && verbose
>= 0)
1411 _cupsLangPrintf(stdout
, _(" WARN Missing "
1412 "APPrinterIconPath file \"%s\"\n"),
1413 attr
->value
? attr
->value
: "<NULL>");
1415 #endif /* __APPLE__ */
1420 _cupsLangPrintf(stdout
, _(" %d ERRORS FOUND\n"), errors
);
1422 _cupsLangPuts(stdout
, _(" NO ERRORS FOUND\n"));
1426 * Then list the options, if "-v" was provided...
1431 _cupsLangPrintf(stdout
,
1433 " language_level = %d\n"
1434 " color_device = %s\n"
1435 " variable_sizes = %s\n"
1436 " landscape = %d\n",
1437 ppd
->language_level
,
1438 ppd
->color_device
? "TRUE" : "FALSE",
1439 ppd
->variable_sizes
? "TRUE" : "FALSE",
1442 switch (ppd
->colorspace
)
1445 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMYK\n");
1448 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMY\n");
1451 _cupsLangPuts(stdout
, " colorspace = PPD_CS_GRAY\n");
1454 _cupsLangPuts(stdout
, " colorspace = PPD_CS_RGB\n");
1457 _cupsLangPuts(stdout
, " colorspace = <unknown>\n");
1461 _cupsLangPrintf(stdout
, " num_emulations = %d\n",
1462 ppd
->num_emulations
);
1463 for (j
= 0; j
< ppd
->num_emulations
; j
++)
1464 _cupsLangPrintf(stdout
, " emulations[%d] = %s\n",
1465 j
, ppd
->emulations
[j
].name
);
1467 _cupsLangPrintf(stdout
, " lang_encoding = %s\n",
1468 ppd
->lang_encoding
);
1469 _cupsLangPrintf(stdout
, " lang_version = %s\n",
1471 _cupsLangPrintf(stdout
, " modelname = %s\n", ppd
->modelname
);
1472 _cupsLangPrintf(stdout
, " ttrasterizer = %s\n",
1473 ppd
->ttrasterizer
== NULL
? "None" : ppd
->ttrasterizer
);
1474 _cupsLangPrintf(stdout
, " manufacturer = %s\n",
1476 _cupsLangPrintf(stdout
, " product = %s\n", ppd
->product
);
1477 _cupsLangPrintf(stdout
, " nickname = %s\n", ppd
->nickname
);
1478 _cupsLangPrintf(stdout
, " shortnickname = %s\n",
1479 ppd
->shortnickname
);
1480 _cupsLangPrintf(stdout
, " patches = %d bytes\n",
1481 ppd
->patches
== NULL
? 0 : (int)strlen(ppd
->patches
));
1483 _cupsLangPrintf(stdout
, " num_groups = %d\n", ppd
->num_groups
);
1484 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1486 _cupsLangPrintf(stdout
, " group[%d] = %s\n",
1489 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1491 _cupsLangPrintf(stdout
,
1492 " options[%d] = %s (%s) %s %s %.0f "
1494 k
, option
->keyword
, option
->text
, uis
[option
->ui
],
1495 sections
[option
->section
], option
->order
,
1496 option
->num_choices
);
1498 if (!strcmp(option
->keyword
, "PageSize") ||
1499 !strcmp(option
->keyword
, "PageRegion"))
1501 for (m
= option
->num_choices
, choice
= option
->choices
;
1505 size
= ppdPageSize(ppd
, choice
->choice
);
1508 _cupsLangPrintf(stdout
,
1510 choice
->choice
, choice
->text
);
1512 _cupsLangPrintf(stdout
,
1513 " %s (%s) = %.2fx%.2fin "
1514 "(%.1f,%.1f,%.1f,%.1f)",
1515 choice
->choice
, choice
->text
,
1516 size
->width
/ 72.0, size
->length
/ 72.0,
1517 size
->left
/ 72.0, size
->bottom
/ 72.0,
1518 size
->right
/ 72.0, size
->top
/ 72.0);
1520 if (!strcmp(option
->defchoice
, choice
->choice
))
1521 _cupsLangPuts(stdout
, " *\n");
1523 _cupsLangPuts(stdout
, "\n");
1528 for (m
= option
->num_choices
, choice
= option
->choices
;
1532 _cupsLangPrintf(stdout
, " %s (%s)",
1533 choice
->choice
, choice
->text
);
1535 if (!strcmp(option
->defchoice
, choice
->choice
))
1536 _cupsLangPuts(stdout
, " *\n");
1538 _cupsLangPuts(stdout
, "\n");
1544 _cupsLangPrintf(stdout
, " num_consts = %d\n",
1546 for (j
= 0; j
< ppd
->num_consts
; j
++)
1547 _cupsLangPrintf(stdout
,
1548 " consts[%d] = *%s %s *%s %s\n",
1549 j
, ppd
->consts
[j
].option1
, ppd
->consts
[j
].choice1
,
1550 ppd
->consts
[j
].option2
, ppd
->consts
[j
].choice2
);
1552 _cupsLangPrintf(stdout
, " num_profiles = %d\n",
1554 for (j
= 0; j
< ppd
->num_profiles
; j
++)
1555 _cupsLangPrintf(stdout
,
1556 " profiles[%d] = %s/%s %.3f %.3f "
1557 "[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
1558 j
, ppd
->profiles
[j
].resolution
,
1559 ppd
->profiles
[j
].media_type
,
1560 ppd
->profiles
[j
].gamma
, ppd
->profiles
[j
].density
,
1561 ppd
->profiles
[j
].matrix
[0][0],
1562 ppd
->profiles
[j
].matrix
[0][1],
1563 ppd
->profiles
[j
].matrix
[0][2],
1564 ppd
->profiles
[j
].matrix
[1][0],
1565 ppd
->profiles
[j
].matrix
[1][1],
1566 ppd
->profiles
[j
].matrix
[1][2],
1567 ppd
->profiles
[j
].matrix
[2][0],
1568 ppd
->profiles
[j
].matrix
[2][1],
1569 ppd
->profiles
[j
].matrix
[2][2]);
1571 _cupsLangPrintf(stdout
, " num_fonts = %d\n", ppd
->num_fonts
);
1572 for (j
= 0; j
< ppd
->num_fonts
; j
++)
1573 _cupsLangPrintf(stdout
, " fonts[%d] = %s\n",
1576 _cupsLangPrintf(stdout
, " num_attrs = %d\n", ppd
->num_attrs
);
1577 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1578 _cupsLangPrintf(stdout
,
1579 " attrs[%d] = %s %s%s%s: \"%s\"\n", j
,
1580 ppd
->attrs
[j
]->name
, ppd
->attrs
[j
]->spec
,
1581 ppd
->attrs
[j
]->text
[0] ? "/" : "",
1582 ppd
->attrs
[j
]->text
,
1583 ppd
->attrs
[j
]->value
?
1584 ppd
->attrs
[j
]->value
: "(null)");
1598 * 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1602 check_basics(const char *filename
) /* I - PPD file to check */
1604 cups_file_t
*fp
; /* File pointer */
1605 int ch
; /* Current character */
1606 int col
, /* Current column */
1607 whitespace
; /* Only seen whitespace? */
1608 int eol
; /* Line endings */
1609 int linenum
; /* Line number */
1610 int mixed
; /* Mixed line endings? */
1613 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
1622 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
1624 if (ch
== '\r' || ch
== '\n')
1628 if (eol
== EOL_NONE
)
1630 else if (eol
!= EOL_LF
)
1633 else if (ch
== '\r')
1635 if (cupsFilePeekChar(fp
) == '\n')
1637 cupsFileGetChar(fp
);
1639 if (eol
== EOL_NONE
)
1641 else if (eol
!= EOL_CRLF
)
1644 else if (eol
== EOL_NONE
)
1646 else if (eol
!= EOL_CR
)
1650 if (col
> 0 && whitespace
)
1651 _cupsLangPrintf(stdout
,
1652 _(" WARN Line %d only contains whitespace!\n"),
1661 if (ch
!= ' ' && ch
!= '\t')
1669 _cupsLangPuts(stdout
,
1670 _(" WARN File contains a mix of CR, LF, and "
1671 "CR LF line endings!\n"));
1673 if (eol
== EOL_CRLF
)
1674 _cupsLangPuts(stdout
,
1675 _(" WARN Non-Windows PPD files should use lines "
1676 "ending with only LF, not CR LF!\n"));
1683 * 'check_constraints()' - Check UIConstraints in the PPD file.
1686 static int /* O - Errors found */
1687 check_constraints(ppd_file_t
*ppd
, /* I - PPD file */
1688 int errors
, /* I - Errors found */
1689 int verbose
, /* I - Verbosity level */
1690 int warn
) /* I - Warnings only? */
1692 int i
; /* Looping var */
1693 const char *prefix
; /* WARN/FAIL prefix */
1694 ppd_const_t
*c
; /* Current UIConstraints data */
1695 ppd_attr_t
*constattr
; /* Current cupsUIConstraints attribute */
1696 const char *vptr
; /* Pointer into constraint value */
1697 char option
[PPD_MAX_NAME
],
1698 /* Option name/MainKeyword */
1699 choice
[PPD_MAX_NAME
],
1700 /* Choice/OptionKeyword */
1701 *ptr
; /* Pointer into option or choice */
1702 int num_options
; /* Number of options */
1703 cups_option_t
*options
; /* Options */
1704 ppd_option_t
*o
; /* PPD option */
1707 prefix
= warn
? " WARN " : "**FAIL**";
1711 * See what kind of constraint data we have in the PPD...
1714 if ((constattr
= ppdFindAttr(ppd
, "cupsUIConstraints", NULL
)) != NULL
)
1717 * Check new-style cupsUIConstraints data...
1721 constattr
= ppdFindNextAttr(ppd
, "cupsUIConstraints", NULL
))
1723 if (!constattr
->value
)
1725 if (!warn
&& !errors
&& !verbose
)
1726 _cupsLangPuts(stdout
, _(" FAIL\n"));
1728 _cupsLangPrintf(stdout
,
1729 _(" %s Empty cupsUIConstraints %s!\n"),
1730 prefix
, constattr
->spec
);
1738 for (i
= 0, vptr
= strchr(constattr
->value
, '*');
1740 i
++, vptr
= strchr(vptr
+ 1, '*'));
1744 if (!warn
&& !errors
&& !verbose
)
1745 _cupsLangPuts(stdout
, _(" FAIL\n"));
1747 _cupsLangPrintf(stdout
,
1748 _(" %s Bad cupsUIConstraints %s: \"%s\"!\n"),
1749 prefix
, constattr
->spec
, constattr
->value
);
1757 cupsArraySave(ppd
->sorted_attrs
);
1759 if (constattr
->spec
[0] &&
1760 !ppdFindAttr(ppd
, "cupsUIResolver", constattr
->spec
))
1762 if (!warn
&& !errors
&& !verbose
)
1763 _cupsLangPuts(stdout
, _(" FAIL\n"));
1765 _cupsLangPrintf(stdout
,
1766 _(" %s Missing cupsUIResolver %s!\n"),
1767 prefix
, constattr
->spec
);
1773 cupsArrayRestore(ppd
->sorted_attrs
);
1778 for (vptr
= strchr(constattr
->value
, '*');
1780 vptr
= strchr(vptr
, '*'))
1783 * Extract "*Option Choice" or just "*Option"...
1786 for (vptr
++, ptr
= option
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1787 if (ptr
< (option
+ sizeof(option
) - 1))
1792 while (isspace(*vptr
& 255))
1799 for (ptr
= choice
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1800 if (ptr
< (choice
+ sizeof(choice
) - 1))
1806 if (!strncasecmp(option
, "Custom", 6) && !strcasecmp(choice
, "True"))
1808 _cups_strcpy(option
, option
+ 6);
1809 strcpy(choice
, "Custom");
1812 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1814 if (!warn
&& !errors
&& !verbose
)
1815 _cupsLangPuts(stdout
, _(" FAIL\n"));
1817 _cupsLangPrintf(stdout
,
1818 _(" %s Missing option %s in "
1819 "cupsUIConstraints %s: \"%s\"!\n"),
1820 prefix
, option
, constattr
->spec
, constattr
->value
);
1828 if (choice
[0] && !ppdFindChoice(o
, choice
))
1830 if (!warn
&& !errors
&& !verbose
)
1831 _cupsLangPuts(stdout
, _(" FAIL\n"));
1833 _cupsLangPrintf(stdout
,
1834 _(" %s Missing choice *%s %s in "
1835 "cupsUIConstraints %s: \"%s\"!\n"),
1836 prefix
, option
, choice
, constattr
->spec
,
1846 num_options
= cupsAddOption(option
, choice
, num_options
, &options
);
1849 for (i
= 0; i
< o
->num_choices
; i
++)
1850 if (strcasecmp(o
->choices
[i
].choice
, "None") &&
1851 strcasecmp(o
->choices
[i
].choice
, "Off") &&
1852 strcasecmp(o
->choices
[i
].choice
, "False"))
1854 num_options
= cupsAddOption(option
, o
->choices
[i
].choice
,
1855 num_options
, &options
);
1862 * Test the resolver...
1865 if (!cupsResolveConflicts(ppd
, NULL
, NULL
, &num_options
, &options
))
1867 if (!warn
&& !errors
&& !verbose
)
1868 _cupsLangPuts(stdout
, _(" FAIL\n"));
1870 _cupsLangPrintf(stdout
,
1871 _(" %s cupsUIResolver %s causes a loop!\n"),
1872 prefix
, constattr
->spec
);
1878 cupsFreeOptions(num_options
, options
);
1884 * Check old-style [Non]UIConstraints data...
1887 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
1889 if (!strncasecmp(c
->option1
, "Custom", 6) &&
1890 !strcasecmp(c
->choice1
, "True"))
1892 strcpy(option
, c
->option1
+ 6);
1893 strcpy(choice
, "Custom");
1897 strcpy(option
, c
->option1
);
1898 strcpy(choice
, c
->choice1
);
1901 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1903 if (!warn
&& !errors
&& !verbose
)
1904 _cupsLangPuts(stdout
, _(" FAIL\n"));
1906 _cupsLangPrintf(stdout
,
1907 _(" %s Missing option %s in "
1908 "UIConstraints \"*%s %s *%s %s\"!\n"),
1910 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1915 else if (choice
[0] && !ppdFindChoice(o
, choice
))
1917 if (!warn
&& !errors
&& !verbose
)
1918 _cupsLangPuts(stdout
, _(" FAIL\n"));
1920 _cupsLangPrintf(stdout
,
1921 _(" %s Missing choice *%s %s in "
1922 "UIConstraints \"*%s %s *%s %s\"!\n"),
1923 prefix
, c
->option1
, c
->choice1
,
1924 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1930 if (!strncasecmp(c
->option2
, "Custom", 6) &&
1931 !strcasecmp(c
->choice2
, "True"))
1933 strcpy(option
, c
->option2
+ 6);
1934 strcpy(choice
, "Custom");
1938 strcpy(option
, c
->option2
);
1939 strcpy(choice
, c
->choice2
);
1942 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1944 if (!warn
&& !errors
&& !verbose
)
1945 _cupsLangPuts(stdout
, _(" FAIL\n"));
1947 _cupsLangPrintf(stdout
,
1948 _(" %s Missing option %s in "
1949 "UIConstraints \"*%s %s *%s %s\"!\n"),
1951 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1956 else if (choice
[0] && !ppdFindChoice(o
, choice
))
1958 if (!warn
&& !errors
&& !verbose
)
1959 _cupsLangPuts(stdout
, _(" FAIL\n"));
1961 _cupsLangPrintf(stdout
,
1962 _(" %s Missing choice *%s %s in "
1963 "UIConstraints \"*%s %s *%s %s\"!\n"),
1964 prefix
, c
->option2
, c
->choice2
,
1965 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1978 * 'check_case()' - Check that there are no duplicate groups, options,
1979 * or choices that differ only by case.
1982 static int /* O - Errors found */
1983 check_case(ppd_file_t
*ppd
, /* I - PPD file */
1984 int errors
, /* I - Errors found */
1985 int verbose
) /* I - Verbosity level */
1987 int i
, j
; /* Looping vars */
1988 ppd_group_t
*groupa
, /* First group */
1989 *groupb
; /* Second group */
1990 ppd_option_t
*optiona
, /* First option */
1991 *optionb
; /* Second option */
1992 ppd_choice_t
*choicea
, /* First choice */
1993 *choiceb
; /* Second choice */
1997 * Check that the groups do not have any duplicate names...
2000 for (i
= ppd
->num_groups
, groupa
= ppd
->groups
; i
> 1; i
--, groupa
++)
2001 for (j
= i
- 1, groupb
= groupa
+ 1; j
> 0; j
--, groupb
++)
2002 if (!strcasecmp(groupa
->name
, groupb
->name
))
2004 if (!errors
&& !verbose
)
2005 _cupsLangPuts(stdout
, _(" FAIL\n"));
2008 _cupsLangPrintf(stdout
,
2009 _(" **FAIL** Group names %s and %s differ only "
2011 groupa
->name
, groupb
->name
);
2017 * Check that the options do not have any duplicate names...
2020 for (optiona
= ppdFirstOption(ppd
); optiona
; optiona
= ppdNextOption(ppd
))
2022 cupsArraySave(ppd
->options
);
2023 for (optionb
= ppdNextOption(ppd
); optionb
; optionb
= ppdNextOption(ppd
))
2024 if (!strcasecmp(optiona
->keyword
, optionb
->keyword
))
2026 if (!errors
&& !verbose
)
2027 _cupsLangPuts(stdout
, _(" FAIL\n"));
2030 _cupsLangPrintf(stdout
,
2031 _(" **FAIL** Option names %s and %s differ only "
2033 optiona
->keyword
, optionb
->keyword
);
2037 cupsArrayRestore(ppd
->options
);
2040 * Then the choices...
2043 for (i
= optiona
->num_choices
, choicea
= optiona
->choices
;
2046 for (j
= i
- 1, choiceb
= choicea
+ 1; j
> 0; j
--, choiceb
++)
2047 if (!strcmp(choicea
->choice
, choiceb
->choice
))
2049 if (!errors
&& !verbose
)
2050 _cupsLangPuts(stdout
, _(" FAIL\n"));
2053 _cupsLangPrintf(stdout
,
2054 _(" **FAIL** Multiple occurrences of %s "
2055 "choice name %s!\n"),
2056 optiona
->keyword
, choicea
->choice
);
2064 else if (!strcasecmp(choicea
->choice
, choiceb
->choice
))
2066 if (!errors
&& !verbose
)
2067 _cupsLangPuts(stdout
, _(" FAIL\n"));
2070 _cupsLangPrintf(stdout
,
2071 _(" **FAIL** %s choice names %s and %s "
2072 "differ only by case!\n"),
2073 optiona
->keyword
, choicea
->choice
, choiceb
->choice
);
2080 * Return the number of errors found...
2088 * 'check_defaults()' - Check default option keywords in the PPD file.
2091 static int /* O - Errors found */
2092 check_defaults(ppd_file_t
*ppd
, /* I - PPD file */
2093 int errors
, /* I - Errors found */
2094 int verbose
, /* I - Verbosity level */
2095 int warn
) /* I - Warnings only? */
2097 int j
, k
; /* Looping vars */
2098 ppd_attr_t
*attr
; /* PPD attribute */
2099 ppd_option_t
*option
; /* Standard UI option */
2100 const char *prefix
; /* WARN/FAIL prefix */
2103 prefix
= warn
? " WARN " : "**FAIL**";
2105 for (j
= 0; j
< ppd
->num_attrs
; j
++)
2107 attr
= ppd
->attrs
[j
];
2109 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
2110 !strcmp(attr
->name
, "DefaultFont") ||
2111 !strcmp(attr
->name
, "DefaultHalftoneType") ||
2112 !strcmp(attr
->name
, "DefaultImageableArea") ||
2113 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
2114 !strcmp(attr
->name
, "DefaultOutputOrder") ||
2115 !strcmp(attr
->name
, "DefaultPaperDimension") ||
2116 !strcmp(attr
->name
, "DefaultResolution") ||
2117 !strcmp(attr
->name
, "DefaultTransfer"))
2120 if (!strncmp(attr
->name
, "Default", 7))
2122 if ((option
= ppdFindOption(ppd
, attr
->name
+ 7)) != NULL
&&
2123 strcmp(attr
->value
, "Unknown"))
2126 * Check that the default option value matches a choice...
2129 for (k
= 0; k
< option
->num_choices
; k
++)
2130 if (!strcmp(option
->choices
[k
].choice
, attr
->value
))
2133 if (k
>= option
->num_choices
)
2135 if (!warn
&& !errors
&& !verbose
)
2136 _cupsLangPuts(stdout
, _(" FAIL\n"));
2139 _cupsLangPrintf(stdout
,
2140 _(" %s %s %s does not exist!\n"),
2141 prefix
, attr
->name
, attr
->value
);
2155 * 'check_duplex()' - Check duplex keywords in the PPD file.
2158 static int /* O - Errors found */
2159 check_duplex(ppd_file_t
*ppd
, /* I - PPD file */
2160 int errors
, /* I - Error found */
2161 int verbose
, /* I - Verbosity level */
2162 int warn
) /* I - Warnings only? */
2164 int i
; /* Looping var */
2165 ppd_option_t
*option
; /* PPD option */
2166 ppd_choice_t
*choice
; /* Current choice */
2167 const char *prefix
; /* Message prefix */
2170 prefix
= warn
? " WARN " : "**FAIL**";
2173 * Check for a duplex option, and for standard values...
2176 if ((option
= ppdFindOption(ppd
, "Duplex")) != NULL
)
2178 if (!ppdFindChoice(option
, "None"))
2182 if (!warn
&& !errors
&& !verbose
)
2183 _cupsLangPuts(stdout
, _(" FAIL\n"));
2185 _cupsLangPrintf(stdout
,
2186 _(" %s REQUIRED %s does not define "
2188 " REF: Page 122, section 5.17\n"),
2189 prefix
, option
->keyword
);
2196 for (i
= option
->num_choices
, choice
= option
->choices
;
2199 if (strcmp(choice
->choice
, "None") &&
2200 strcmp(choice
->choice
, "DuplexNoTumble") &&
2201 strcmp(choice
->choice
, "DuplexTumble") &&
2202 strcmp(choice
->choice
, "SimplexTumble"))
2206 if (!warn
&& !errors
&& !verbose
)
2207 _cupsLangPuts(stdout
, _(" FAIL\n"));
2209 _cupsLangPrintf(stdout
,
2210 _(" %s Bad %s choice %s!\n"
2211 " REF: Page 122, section 5.17\n"),
2212 prefix
, option
->keyword
, choice
->choice
);
2225 * 'check_filters()' - Check filters in the PPD file.
2228 static int /* O - Errors found */
2229 check_filters(ppd_file_t
*ppd
, /* I - PPD file */
2230 const char *root
, /* I - Root directory */
2231 int errors
, /* I - Errors found */
2232 int verbose
, /* I - Verbosity level */
2233 int warn
) /* I - Warnings only? */
2235 int i
; /* Looping var */
2236 ppd_attr_t
*attr
; /* PPD attribute */
2237 const char *ptr
; /* Pointer into string */
2238 char super
[16], /* Super-type for filter */
2239 type
[256], /* Type for filter */
2240 program
[1024], /* Program/filter name */
2241 pathprog
[1024]; /* Complete path to program/filter */
2242 int cost
; /* Cost of filter */
2243 const char *prefix
; /* WARN/FAIL prefix */
2246 prefix
= warn
? " WARN " : "**FAIL**";
2248 for (i
= 0; i
< ppd
->num_filters
; i
++)
2250 if (sscanf(ppd
->filters
[i
], "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2251 &cost
, program
) != 4)
2253 if (!warn
&& !errors
&& !verbose
)
2254 _cupsLangPuts(stdout
, _(" FAIL\n"));
2257 _cupsLangPrintf(stdout
,
2258 _(" %s Bad cupsFilter value \"%s\"!\n"),
2259 prefix
, ppd
->filters
[i
]);
2264 else if (strcmp(program
, "-"))
2266 if (program
[0] == '/')
2267 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2270 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2271 ptr
= CUPS_SERVERBIN
;
2273 if (*ptr
== '/' || !*root
)
2274 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2277 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2281 if (access(pathprog
, X_OK
))
2283 if (!warn
&& !errors
&& !verbose
)
2284 _cupsLangPuts(stdout
, _(" FAIL\n"));
2287 _cupsLangPrintf(stdout
, _(" %s Missing cupsFilter "
2288 "file \"%s\"\n"), prefix
, program
);
2296 for (attr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
);
2298 attr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
))
2301 sscanf(attr
->value
, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2302 &cost
, program
) != 4)
2304 if (!warn
&& !errors
&& !verbose
)
2305 _cupsLangPuts(stdout
, _(" FAIL\n"));
2308 _cupsLangPrintf(stdout
,
2309 _(" %s Bad cupsPreFilter value \"%s\"!\n"),
2310 prefix
, attr
->value
? attr
->value
: "");
2315 else if (strcmp(program
, "-"))
2317 if (program
[0] == '/')
2318 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2321 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2322 ptr
= CUPS_SERVERBIN
;
2324 if (*ptr
== '/' || !*root
)
2325 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2328 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2332 if (access(pathprog
, X_OK
))
2334 if (!warn
&& !errors
&& !verbose
)
2335 _cupsLangPuts(stdout
, _(" FAIL\n"));
2338 _cupsLangPrintf(stdout
, _(" %s Missing cupsPreFilter "
2339 "file \"%s\"\n"), prefix
, program
);
2352 * 'check_profiles()' - Check ICC color profiles in the PPD file.
2355 static int /* O - Errors found */
2356 check_profiles(ppd_file_t
*ppd
, /* I - PPD file */
2357 const char *root
, /* I - Root directory */
2358 int errors
, /* I - Errors found */
2359 int verbose
, /* I - Verbosity level */
2360 int warn
) /* I - Warnings only? */
2362 int i
; /* Looping var */
2363 ppd_attr_t
*attr
; /* PPD attribute */
2364 const char *ptr
; /* Pointer into string */
2365 const char *prefix
; /* WARN/FAIL prefix */
2366 char filename
[1024]; /* Profile filename */
2367 int num_profiles
= 0; /* Number of profiles */
2368 unsigned hash
, /* Current hash value */
2369 hashes
[1000]; /* Hash values of profile names */
2370 const char *specs
[1000]; /* Specifiers for profiles */
2373 prefix
= warn
? " WARN " : "**FAIL**";
2375 for (attr
= ppdFindAttr(ppd
, "cupsICCProfile", NULL
);
2377 attr
= ppdFindNextAttr(ppd
, "cupsICCProfile", NULL
))
2380 * Check for valid selector...
2383 for (i
= 0, ptr
= strchr(attr
->spec
, '.'); ptr
; ptr
= strchr(ptr
+ 1, '.'))
2386 if (!attr
->value
|| i
< 2)
2388 if (!warn
&& !errors
&& !verbose
)
2389 _cupsLangPuts(stdout
, _(" FAIL\n"));
2392 _cupsLangPrintf(stdout
,
2393 _(" %s Bad cupsICCProfile %s!\n"),
2394 prefix
, attr
->spec
);
2403 * Check for valid profile filename...
2406 if (attr
->value
[0] == '/')
2407 snprintf(filename
, sizeof(filename
), "%s%s", root
, attr
->value
);
2410 if ((ptr
= getenv("CUPS_DATADIR")) == NULL
)
2413 if (*ptr
== '/' || !*root
)
2414 snprintf(filename
, sizeof(filename
), "%s%s/profiles/%s", root
, ptr
,
2417 snprintf(filename
, sizeof(filename
), "%s/%s/profiles/%s", root
, ptr
,
2421 if (access(filename
, 0))
2423 if (!warn
&& !errors
&& !verbose
)
2424 _cupsLangPuts(stdout
, _(" FAIL\n"));
2427 _cupsLangPrintf(stdout
, _(" %s Missing cupsICCProfile "
2428 "file \"%s\"!\n"), prefix
, attr
->value
);
2435 * Check for hash collisions...
2438 hash
= _ppdHashName(attr
->spec
);
2440 if (num_profiles
> 0)
2442 for (i
= 0; i
< num_profiles
; i
++)
2443 if (hashes
[i
] == hash
)
2446 if (i
< num_profiles
)
2448 if (!warn
&& !errors
&& !verbose
)
2449 _cupsLangPuts(stdout
, _(" FAIL\n"));
2452 _cupsLangPrintf(stdout
,
2453 _(" %s cupsICCProfile %s hash value "
2454 "collides with %s!\n"), prefix
, attr
->spec
,
2463 * Remember up to 1000 profiles...
2466 if (num_profiles
< 1000)
2468 hashes
[num_profiles
] = hash
;
2469 specs
[num_profiles
] = attr
->spec
;
2479 * 'check_translations()' - Check translations in the PPD file.
2482 static int /* O - Errors found */
2483 check_translations(ppd_file_t
*ppd
, /* I - PPD file */
2484 int errors
, /* I - Errors found */
2485 int verbose
, /* I - Verbosity level */
2486 int warn
) /* I - Warnings only? */
2488 int j
; /* Looping var */
2489 ppd_attr_t
*attr
; /* PPD attribute */
2490 cups_array_t
*languages
; /* Array of languages */
2491 int langlen
; /* Length of language */
2492 char *language
, /* Current language */
2493 keyword
[PPD_MAX_NAME
], /* Localization keyword (full) */
2494 llkeyword
[PPD_MAX_NAME
],/* Localization keyword (base) */
2495 ckeyword
[PPD_MAX_NAME
], /* Custom option keyword (full) */
2496 cllkeyword
[PPD_MAX_NAME
];
2497 /* Custom option keyword (base) */
2498 ppd_option_t
*option
; /* Standard UI option */
2499 ppd_coption_t
*coption
; /* Custom option */
2500 ppd_cparam_t
*cparam
; /* Custom parameter */
2501 char ll
[3]; /* Base language */
2502 const char *prefix
; /* WARN/FAIL prefix */
2503 const char *text
; /* Pointer into UI text */
2506 prefix
= warn
? " WARN " : "**FAIL**";
2508 if ((languages
= _ppdGetLanguages(ppd
)) != NULL
)
2511 * This file contains localizations, check them...
2514 for (language
= (char *)cupsArrayFirst(languages
);
2516 language
= (char *)cupsArrayNext(languages
))
2518 langlen
= strlen(language
);
2519 if (langlen
!= 2 && langlen
!= 5)
2521 if (!warn
&& !errors
&& !verbose
)
2522 _cupsLangPuts(stdout
, _(" FAIL\n"));
2525 _cupsLangPrintf(stdout
,
2526 _(" %s Bad language \"%s\"!\n"),
2535 if (!strcmp(language
, "en"))
2538 strlcpy(ll
, language
, sizeof(ll
));
2541 * Loop through all options and choices...
2544 for (option
= ppdFirstOption(ppd
);
2546 option
= ppdNextOption(ppd
))
2548 if (!strcmp(option
->keyword
, "PageRegion"))
2551 snprintf(keyword
, sizeof(keyword
), "%s.Translation", language
);
2552 snprintf(llkeyword
, sizeof(llkeyword
), "%s.Translation", ll
);
2554 if ((attr
= ppdFindAttr(ppd
, keyword
, option
->keyword
)) == NULL
&&
2555 (attr
= ppdFindAttr(ppd
, llkeyword
, option
->keyword
)) == NULL
)
2557 if (!warn
&& !errors
&& !verbose
)
2558 _cupsLangPuts(stdout
, _(" FAIL\n"));
2561 _cupsLangPrintf(stdout
,
2562 _(" %s Missing \"%s\" translation "
2563 "string for option %s!\n"),
2564 prefix
, language
, option
->keyword
);
2569 else if (!valid_utf8(attr
->text
))
2571 if (!warn
&& !errors
&& !verbose
)
2572 _cupsLangPuts(stdout
, _(" FAIL\n"));
2575 _cupsLangPrintf(stdout
,
2576 _(" %s Bad UTF-8 \"%s\" translation "
2577 "string for option %s!\n"),
2578 prefix
, language
, option
->keyword
);
2584 snprintf(keyword
, sizeof(keyword
), "%s.%s", language
,
2586 snprintf(llkeyword
, sizeof(llkeyword
), "%s.%s", ll
,
2589 for (j
= 0; j
< option
->num_choices
; j
++)
2592 * First see if this choice is a number; if so, don't require
2596 for (text
= option
->choices
[j
].text
; *text
; text
++)
2597 if (!strchr("0123456789-+.", *text
))
2604 * Check custom choices differently...
2607 if (!strcasecmp(option
->choices
[j
].choice
, "Custom") &&
2608 (coption
= ppdFindCustomOption(ppd
,
2609 option
->keyword
)) != NULL
)
2611 snprintf(ckeyword
, sizeof(ckeyword
), "%s.Custom%s",
2612 language
, option
->keyword
);
2614 if ((attr
= ppdFindAttr(ppd
, ckeyword
, "True")) != NULL
&&
2615 !valid_utf8(attr
->text
))
2617 if (!warn
&& !errors
&& !verbose
)
2618 _cupsLangPuts(stdout
, _(" FAIL\n"));
2621 _cupsLangPrintf(stdout
,
2622 _(" %s Bad UTF-8 \"%s\" "
2623 "translation string for option %s, "
2626 ckeyword
+ 1 + strlen(language
),
2633 if (strcasecmp(option
->keyword
, "PageSize"))
2635 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
2637 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
2639 snprintf(ckeyword
, sizeof(ckeyword
), "%s.ParamCustom%s",
2640 language
, option
->keyword
);
2641 snprintf(cllkeyword
, sizeof(cllkeyword
), "%s.ParamCustom%s",
2642 ll
, option
->keyword
);
2644 if ((attr
= ppdFindAttr(ppd
, ckeyword
,
2645 cparam
->name
)) == NULL
&&
2646 (attr
= ppdFindAttr(ppd
, cllkeyword
,
2647 cparam
->name
)) == NULL
)
2649 if (!warn
&& !errors
&& !verbose
)
2650 _cupsLangPuts(stdout
, _(" FAIL\n"));
2653 _cupsLangPrintf(stdout
,
2654 _(" %s Missing \"%s\" "
2655 "translation string for option %s, "
2658 ckeyword
+ 1 + strlen(language
),
2664 else if (!valid_utf8(attr
->text
))
2666 if (!warn
&& !errors
&& !verbose
)
2667 _cupsLangPuts(stdout
, _(" FAIL\n"));
2670 _cupsLangPrintf(stdout
,
2671 _(" %s Bad UTF-8 \"%s\" "
2672 "translation string for option %s, "
2675 ckeyword
+ 1 + strlen(language
),
2684 else if ((attr
= ppdFindAttr(ppd
, keyword
,
2685 option
->choices
[j
].choice
)) == NULL
&&
2686 (attr
= ppdFindAttr(ppd
, llkeyword
,
2687 option
->choices
[j
].choice
)) == NULL
)
2689 if (!warn
&& !errors
&& !verbose
)
2690 _cupsLangPuts(stdout
, _(" FAIL\n"));
2693 _cupsLangPrintf(stdout
,
2694 _(" %s Missing \"%s\" "
2695 "translation string for option %s, "
2697 prefix
, language
, option
->keyword
,
2698 option
->choices
[j
].choice
);
2703 else if (!valid_utf8(attr
->text
))
2705 if (!warn
&& !errors
&& !verbose
)
2706 _cupsLangPuts(stdout
, _(" FAIL\n"));
2709 _cupsLangPrintf(stdout
,
2710 _(" %s Bad UTF-8 \"%s\" "
2711 "translation string for option %s, "
2713 prefix
, language
, option
->keyword
,
2714 option
->choices
[j
].choice
);
2724 * Verify that we have the base language for each localized one...
2727 for (language
= (char *)cupsArrayFirst(languages
);
2729 language
= (char *)cupsArrayNext(languages
))
2733 * Lookup the base language...
2736 cupsArraySave(languages
);
2738 strlcpy(ll
, language
, sizeof(ll
));
2740 if (!cupsArrayFind(languages
, ll
) &&
2741 strcmp(ll
, "zh") && strcmp(ll
, "en"))
2743 if (!warn
&& !errors
&& !verbose
)
2744 _cupsLangPuts(stdout
, _(" FAIL\n"));
2747 _cupsLangPrintf(stdout
,
2748 _(" %s No base translation \"%s\" "
2749 "is included in file!\n"), prefix
, ll
);
2755 cupsArrayRestore(languages
);
2759 * Free memory used for the languages...
2762 _ppdFreeLanguages(languages
);
2770 * 'show_conflicts()' - Show option conflicts in a PPD file.
2774 show_conflicts(ppd_file_t
*ppd
) /* I - PPD to check */
2776 int i
, j
; /* Looping variables */
2777 ppd_const_t
*c
; /* Current constraint */
2778 ppd_option_t
*o1
, *o2
; /* Options */
2779 ppd_choice_t
*c1
, *c2
; /* Choices */
2783 * Loop through all of the UI constraints and report any options
2787 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
2790 * Grab pointers to the first option...
2793 o1
= ppdFindOption(ppd
, c
->option1
);
2797 else if (c
->choice1
[0] != '\0')
2800 * This constraint maps to a specific choice.
2803 c1
= ppdFindChoice(o1
, c
->choice1
);
2808 * This constraint applies to any choice for this option.
2811 for (j
= o1
->num_choices
, c1
= o1
->choices
; j
> 0; j
--, c1
++)
2816 !strcasecmp(c1
->choice
, "None") ||
2817 !strcasecmp(c1
->choice
, "Off") ||
2818 !strcasecmp(c1
->choice
, "False"))
2823 * Grab pointers to the second option...
2826 o2
= ppdFindOption(ppd
, c
->option2
);
2830 else if (c
->choice2
[0] != '\0')
2833 * This constraint maps to a specific choice.
2836 c2
= ppdFindChoice(o2
, c
->choice2
);
2841 * This constraint applies to any choice for this option.
2844 for (j
= o2
->num_choices
, c2
= o2
->choices
; j
> 0; j
--, c2
++)
2849 !strcasecmp(c2
->choice
, "None") ||
2850 !strcasecmp(c2
->choice
, "Off") ||
2851 !strcasecmp(c2
->choice
, "False"))
2856 * If both options are marked then there is a conflict...
2859 if (c1
!= NULL
&& c1
->marked
&& c2
!= NULL
&& c2
->marked
)
2860 _cupsLangPrintf(stdout
,
2861 _(" WARN \"%s %s\" conflicts with \"%s %s\"\n"
2862 " (constraint=\"%s %s %s %s\")\n"),
2863 o1
->keyword
, c1
->choice
, o2
->keyword
, c2
->choice
,
2864 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2870 * 'test_raster()' - Test PostScript commands for raster printers.
2873 static int /* O - 1 on success, 0 on failure */
2874 test_raster(ppd_file_t
*ppd
, /* I - PPD file */
2875 int verbose
) /* I - Verbosity */
2877 cups_page_header2_t header
; /* Page header */
2880 ppdMarkDefaults(ppd
);
2881 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
2884 _cupsLangPuts(stdout
, _(" FAIL\n"));
2887 _cupsLangPrintf(stdout
,
2888 _(" **FAIL** Default option code cannot be "
2889 "interpreted: %s\n"), cupsRasterErrorString());
2895 * Try a test of custom page size code, if available...
2898 if (!ppdPageSize(ppd
, "Custom.612x792"))
2901 ppdMarkOption(ppd
, "PageSize", "Custom.612x792");
2903 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
2906 _cupsLangPuts(stdout
, _(" FAIL\n"));
2909 _cupsLangPrintf(stdout
,
2910 _(" **FAIL** Default option code cannot be "
2911 "interpreted: %s\n"), cupsRasterErrorString());
2921 * 'usage()' - Show program usage...
2927 _cupsLangPuts(stdout
,
2928 _("Usage: cupstestppd [options] filename1.ppd[.gz] "
2929 "[... filenameN.ppd[.gz]]\n"
2930 " program | cupstestppd [options] -\n"
2934 " -R root-directory Set alternate root\n"
2935 " -W {all,none,constraints,defaults,duplex,filters,"
2937 " Issue warnings instead of errors\n"
2938 " -q Run silently\n"
2939 " -r Use 'relaxed' open mode\n"
2940 " -v Be slightly verbose\n"
2941 " -vv Be very verbose\n"));
2948 * 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
2951 static int /* O - 1 if valid, 0 if not */
2952 valid_utf8(const char *s
) /* I - String to check */
2959 * Check for valid UTF-8 sequence...
2962 if ((*s
& 0xc0) == 0x80)
2963 return (0); /* Illegal suffix byte */
2964 else if ((*s
& 0xe0) == 0xc0)
2967 * 2-byte sequence...
2972 if ((*s
& 0xc0) != 0x80)
2973 return (0); /* Missing suffix byte */
2975 else if ((*s
& 0xf0) == 0xe0)
2978 * 3-byte sequence...
2983 if ((*s
& 0xc0) != 0x80)
2984 return (0); /* Missing suffix byte */
2988 if ((*s
& 0xc0) != 0x80)
2989 return (0); /* Missing suffix byte */
2991 else if ((*s
& 0xf8) == 0xf0)
2994 * 4-byte sequence...
2999 if ((*s
& 0xc0) != 0x80)
3000 return (0); /* Missing suffix byte */
3004 if ((*s
& 0xc0) != 0x80)
3005 return (0); /* Missing suffix byte */
3009 if ((*s
& 0xc0) != 0x80)
3010 return (0); /* Missing suffix byte */
3013 return (0); /* Bad sequence */
3024 * End of "$Id: cupstestppd.c 7807 2008-07-28 21:54:24Z mike $".