2 * "$Id: cupstestppd.c 6444 2007-04-04 22:13:58Z mike $"
4 * PPD test program for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * PostScript is a trademark of Adobe Systems, Inc.
26 * This file is subject to the Apple OS-Developed Software exception.
30 * main() - Main entry for test program.
31 * show_conflicts() - Show option conflicts in a PPD file.
32 * usage() - Show program usage...
33 * valid_utf8() - Check whether a string contains valid UTF-8 text.
37 * Include necessary headers...
40 #include <cups/string.h>
41 #include <cups/cups.h>
42 #include <cups/i18n.h>
79 void check_basics(const char *filename
);
80 void show_conflicts(ppd_file_t
*ppd
);
82 int valid_utf8(const char *s
);
85 * 'main()' - Main entry for test program.
88 int /* O - Exit status */
89 main(int argc
, /* I - Number of command-line args */
90 char *argv
[]) /* I - Command-line arguments */
92 int i
, j
, k
, m
, n
; /* Looping vars */
93 int len
; /* Length of option name */
94 char *opt
; /* Option character */
95 const char *ptr
; /* Pointer into string */
96 int files
; /* Number of files */
97 int verbose
; /* Want verbose output? */
98 int status
; /* Exit status */
99 int errors
; /* Number of conformance errors */
100 int ppdversion
; /* PPD spec version in PPD file */
101 ppd_status_t error
; /* Status of ppdOpen*() */
102 int line
; /* Line number for error */
103 struct stat statbuf
; /* File information */
104 char super
[16], /* Super-type for filter */
105 type
[256], /* Type for filter */
106 program
[256], /* Program/filter name */
107 pathprog
[1024], /* Complete path to program/filter */
108 *root
; /* Root directory */
109 int cost
; /* Cost of filter */
110 int xdpi
, /* X resolution */
111 ydpi
; /* Y resolution */
112 ppd_file_t
*ppd
; /* PPD file record */
113 ppd_attr_t
*attr
; /* PPD attribute */
114 ppd_size_t
*size
; /* Size record */
115 ppd_group_t
*group
; /* UI group */
116 ppd_option_t
*option
; /* Standard UI option */
117 ppd_group_t
*group2
; /* UI group */
118 ppd_option_t
*option2
; /* Standard UI option */
119 ppd_choice_t
*choice
; /* Standard UI option choice */
120 ppd_const_t
*c
; /* Current constraint */
121 static char *uis
[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
122 static char *sections
[] = { "ANY", "DOCUMENT", "EXIT",
123 "JCL", "PAGE", "PROLOG" };
126 _cupsSetLocale(argv
);
129 * Display PPD files for each file listed on the command-line...
132 ppdSetConformance(PPD_CONFORM_STRICT
);
140 for (i
= 1; i
< argc
; i
++)
141 if (argv
[i
][0] == '-' && argv
[i
][1])
143 for (opt
= argv
[i
] + 1; *opt
; opt
++)
146 case 'R' : /* Alternate root directory */
155 case 'q' : /* Quiet mode */
158 _cupsLangPuts(stderr
,
159 _("cupstestppd: The -q option is incompatible "
160 "with the -v option.\n"));
167 case 'r' : /* Relaxed mode */
168 ppdSetConformance(PPD_CONFORM_RELAXED
);
171 case 'v' : /* Verbose mode */
174 _cupsLangPuts(stderr
,
175 _("cupstestppd: The -v option is incompatible "
176 "with the -q option.\n"));
191 * Open the PPD file...
194 if (files
&& verbose
>= 0)
195 _cupsLangPuts(stdout
, "\n");
199 if (argv
[i
][0] == '-')
208 ppd
= ppdOpen(stdin
);
213 * Read from a file...
217 printf("%s:", argv
[i
]);
219 ppd
= ppdOpenFile(argv
[i
]);
224 error
= ppdLastError(&line
);
226 if (error
<= PPD_ALLOC_ERROR
)
228 status
= ERROR_FILE_OPEN
;
231 _cupsLangPrintf(stdout
,
233 " **FAIL** Unable to open PPD file - %s\n"),
238 status
= ERROR_PPD_FORMAT
;
242 _cupsLangPrintf(stdout
,
244 " **FAIL** Unable to open PPD file - "
246 ppdErrorString(error
), line
);
250 case PPD_MISSING_PPDADOBE4
:
251 _cupsLangPuts(stdout
,
252 _(" REF: Page 42, section 5.2.\n"));
254 case PPD_MISSING_VALUE
:
255 _cupsLangPuts(stdout
,
256 _(" REF: Page 20, section 3.4.\n"));
258 case PPD_BAD_OPEN_GROUP
:
259 case PPD_NESTED_OPEN_GROUP
:
260 _cupsLangPuts(stdout
,
261 _(" REF: Pages 45-46, section 5.2.\n"));
263 case PPD_BAD_OPEN_UI
:
264 case PPD_NESTED_OPEN_UI
:
265 _cupsLangPuts(stdout
,
266 _(" REF: Pages 42-45, section 5.2.\n"));
268 case PPD_BAD_ORDER_DEPENDENCY
:
269 _cupsLangPuts(stdout
,
270 _(" REF: Pages 48-49, section 5.2.\n"));
272 case PPD_BAD_UI_CONSTRAINTS
:
273 _cupsLangPuts(stdout
,
274 _(" REF: Pages 52-54, section 5.2.\n"));
276 case PPD_MISSING_ASTERISK
:
277 _cupsLangPuts(stdout
,
278 _(" REF: Page 15, section 3.2.\n"));
280 case PPD_LINE_TOO_LONG
:
281 _cupsLangPuts(stdout
,
282 _(" REF: Page 15, section 3.1.\n"));
284 case PPD_ILLEGAL_CHARACTER
:
285 _cupsLangPuts(stdout
,
286 _(" REF: Page 15, section 3.1.\n"));
288 case PPD_ILLEGAL_MAIN_KEYWORD
:
289 _cupsLangPuts(stdout
,
290 _(" REF: Pages 16-17, section 3.2.\n"));
292 case PPD_ILLEGAL_OPTION_KEYWORD
:
293 _cupsLangPuts(stdout
,
294 _(" REF: Page 19, section 3.3.\n"));
296 case PPD_ILLEGAL_TRANSLATION
:
297 _cupsLangPuts(stdout
,
298 _(" REF: Page 27, section 3.5.\n"));
304 check_basics(argv
[i
]);
312 * Show the header and then perform basic conformance tests (limited
313 * only by what the CUPS PPD functions actually load...)
320 _cupsLangPuts(stdout
,
321 _("\n DETAILED CONFORMANCE TEST RESULTS\n"));
323 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
&&
325 ppdversion
= (int)(10 * atof(attr
->value
) + 0.5);
328 * Look for default keywords with no matching option...
331 for (j
= 0; j
< ppd
->num_attrs
; j
++)
333 attr
= ppd
->attrs
[j
];
335 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
336 !strcmp(attr
->name
, "DefaultFont") ||
337 !strcmp(attr
->name
, "DefaultImageableArea") ||
338 !strcmp(attr
->name
, "DefaultOutputOrder") ||
339 !strcmp(attr
->name
, "DefaultPaperDimension") ||
340 !strcmp(attr
->name
, "DefaultResolution") ||
341 !strcmp(attr
->name
, "DefaultTransfer"))
344 if (!strncmp(attr
->name
, "Default", 7))
346 if ((option
= ppdFindOption(ppd
, attr
->name
+ 7)) != NULL
&&
347 strcmp(attr
->value
, "Unknown"))
350 * Check that the default option value matches a choice...
353 for (k
= 0; k
< option
->num_choices
; k
++)
354 if (!strcmp(option
->choices
[k
].choice
, attr
->value
))
357 if (k
>= option
->num_choices
)
361 if (!errors
&& !verbose
)
362 _cupsLangPuts(stdout
, _(" FAIL\n"));
364 _cupsLangPrintf(stdout
,
365 _(" **FAIL** %s %s does not exist!\n"),
366 attr
->name
, attr
->value
);
375 if ((attr
= ppdFindAttr(ppd
, "DefaultImageableArea", NULL
)) == NULL
)
379 if (!errors
&& !verbose
)
380 _cupsLangPuts(stdout
, _(" FAIL\n"));
382 _cupsLangPuts(stdout
,
383 _(" **FAIL** REQUIRED DefaultImageableArea\n"
384 " REF: Page 102, section 5.15.\n"));
389 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
390 strcmp(attr
->value
, "Unknown"))
394 if (!errors
&& !verbose
)
395 _cupsLangPuts(stdout
, _(" FAIL\n"));
397 _cupsLangPrintf(stdout
,
398 _(" **FAIL** BAD DefaultImageableArea %s!\n"
399 " REF: Page 102, section 5.15.\n"),
408 _cupsLangPuts(stdout
, _(" PASS DefaultImageableArea\n"));
411 if ((attr
= ppdFindAttr(ppd
, "DefaultPaperDimension", NULL
)) == NULL
)
415 if (!errors
&& !verbose
)
416 _cupsLangPuts(stdout
, _(" FAIL\n"));
418 _cupsLangPuts(stdout
,
419 _(" **FAIL** REQUIRED DefaultPaperDimension\n"
420 " REF: Page 103, section 5.15.\n"));
425 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
426 strcmp(attr
->value
, "Unknown"))
430 if (!errors
&& !verbose
)
431 _cupsLangPuts(stdout
, _(" FAIL\n"));
433 _cupsLangPrintf(stdout
,
434 _(" **FAIL** BAD DefaultPaperDimension %s!\n"
435 " REF: Page 103, section 5.15.\n"),
441 else if (verbose
> 0)
442 _cupsLangPuts(stdout
, _(" PASS DefaultPaperDimension\n"));
444 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
445 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
448 * Verify that we have a default choice...
451 if (option
->defchoice
[0])
453 if (ppdFindChoice(option
, option
->defchoice
) == NULL
&&
454 strcmp(option
->defchoice
, "Unknown"))
458 if (!errors
&& !verbose
)
459 _cupsLangPuts(stdout
, _(" FAIL\n"));
461 _cupsLangPrintf(stdout
,
462 _(" **FAIL** BAD Default%s %s\n"
463 " REF: Page 40, section 4.5.\n"),
464 option
->keyword
, option
->defchoice
);
469 else if (verbose
> 0)
470 _cupsLangPrintf(stdout
,
471 _(" PASS Default%s\n"),
478 if (!errors
&& !verbose
)
479 _cupsLangPuts(stdout
, _(" FAIL\n"));
481 _cupsLangPrintf(stdout
,
482 _(" **FAIL** REQUIRED Default%s\n"
483 " REF: Page 40, section 4.5.\n"),
491 if (ppdFindAttr(ppd
, "FileVersion", NULL
) != NULL
)
494 _cupsLangPuts(stdout
, _(" PASS FileVersion\n"));
500 if (!errors
&& !verbose
)
501 _cupsLangPuts(stdout
, _(" FAIL\n"));
503 _cupsLangPuts(stdout
,
504 _(" **FAIL** REQUIRED FileVersion\n"
505 " REF: Page 56, section 5.3.\n"));
511 if (ppdFindAttr(ppd
, "FormatVersion", NULL
) != NULL
)
514 _cupsLangPuts(stdout
, _(" PASS FormatVersion\n"));
520 if (!errors
&& !verbose
)
521 _cupsLangPuts(stdout
, _(" FAIL\n"));
523 _cupsLangPuts(stdout
,
524 _(" **FAIL** REQUIRED FormatVersion\n"
525 " REF: Page 56, section 5.3.\n"));
531 if (ppd
->lang_encoding
!= NULL
)
534 _cupsLangPuts(stdout
, _(" PASS LanguageEncoding\n"));
536 else if (ppdversion
> 40)
540 if (!errors
&& !verbose
)
541 _cupsLangPuts(stdout
, _(" FAIL\n"));
543 _cupsLangPuts(stdout
,
544 _(" **FAIL** REQUIRED LanguageEncoding\n"
545 " REF: Pages 56-57, section 5.3.\n"));
551 if (ppd
->lang_version
!= NULL
)
554 _cupsLangPuts(stdout
, _(" PASS LanguageVersion\n"));
560 if (!errors
&& !verbose
)
561 _cupsLangPuts(stdout
, _(" FAIL\n"));
563 _cupsLangPuts(stdout
,
564 _(" **FAIL** REQUIRED LanguageVersion\n"
565 " REF: Pages 57-58, section 5.3.\n"));
571 if (ppd
->manufacturer
!= NULL
)
573 if (!strncasecmp(ppd
->manufacturer
, "Hewlett-Packard", 15) ||
574 !strncasecmp(ppd
->manufacturer
, "Hewlett Packard", 15))
578 if (!errors
&& !verbose
)
579 _cupsLangPuts(stdout
, _(" FAIL\n"));
581 _cupsLangPuts(stdout
,
582 _(" **FAIL** BAD Manufacturer (should be "
584 " REF: Page 211, table D.1.\n"));
589 else if (verbose
> 0)
590 _cupsLangPuts(stdout
, _(" PASS Manufacturer\n"));
592 else if (ppdversion
>= 43)
596 if (!errors
&& !verbose
)
597 _cupsLangPuts(stdout
, _(" FAIL\n"));
599 _cupsLangPuts(stdout
,
600 _(" **FAIL** REQUIRED Manufacturer\n"
601 " REF: Pages 58-59, section 5.3.\n"));
607 if (ppd
->modelname
!= NULL
)
609 for (ptr
= ppd
->modelname
; *ptr
; ptr
++)
610 if (!isalnum(*ptr
& 255) && !strchr(" ./-+", *ptr
))
617 if (!errors
&& !verbose
)
618 _cupsLangPuts(stdout
, _(" FAIL\n"));
620 _cupsLangPrintf(stdout
,
621 _(" **FAIL** BAD ModelName - \"%c\" not "
622 "allowed in string.\n"
623 " REF: Pages 59-60, section 5.3.\n"),
629 else if (verbose
> 0)
630 _cupsLangPuts(stdout
, _(" PASS ModelName\n"));
636 if (!errors
&& !verbose
)
637 _cupsLangPuts(stdout
, _(" FAIL\n"));
639 _cupsLangPuts(stdout
,
640 _(" **FAIL** REQUIRED ModelName\n"
641 " REF: Pages 59-60, section 5.3.\n"));
647 if (ppd
->nickname
!= NULL
)
650 _cupsLangPuts(stdout
, _(" PASS NickName\n"));
656 if (!errors
&& !verbose
)
657 _cupsLangPuts(stdout
, _(" FAIL\n"));
659 _cupsLangPuts(stdout
,
660 _(" **FAIL** REQUIRED NickName\n"
661 " REF: Page 60, section 5.3.\n"));
667 if (ppdFindOption(ppd
, "PageSize") != NULL
)
670 _cupsLangPuts(stdout
, _(" PASS PageSize\n"));
676 if (!errors
&& !verbose
)
677 _cupsLangPuts(stdout
, _(" FAIL\n"));
679 _cupsLangPuts(stdout
,
680 _(" **FAIL** REQUIRED PageSize\n"
681 " REF: Pages 99-100, section 5.14.\n"));
687 if (ppdFindOption(ppd
, "PageRegion") != NULL
)
690 _cupsLangPuts(stdout
, _(" PASS PageRegion\n"));
696 if (!errors
&& !verbose
)
697 _cupsLangPuts(stdout
, _(" FAIL\n"));
699 _cupsLangPuts(stdout
,
700 _(" **FAIL** REQUIRED PageRegion\n"
701 " REF: Page 100, section 5.14.\n"));
707 if (ppd
->pcfilename
!= NULL
)
710 _cupsLangPuts(stdout
, _(" PASS PCFileName\n"));
716 if (!errors
&& !verbose
)
717 _cupsLangPuts(stdout
, _(" FAIL\n"));
719 _cupsLangPuts(stdout
,
720 _(" **FAIL** REQUIRED PCFileName\n"
721 " REF: Pages 61-62, section 5.3.\n"));
727 if (ppd
->product
!= NULL
)
729 if (ppd
->product
[0] != '(' ||
730 ppd
->product
[strlen(ppd
->product
) - 1] != ')')
734 if (!errors
&& !verbose
)
735 _cupsLangPuts(stdout
, _(" FAIL\n"));
737 _cupsLangPuts(stdout
,
738 _(" **FAIL** BAD Product - not \"(string)\".\n"
739 " REF: Page 62, section 5.3.\n"));
744 else if (verbose
> 0)
745 _cupsLangPuts(stdout
, _(" PASS Product\n"));
751 if (!errors
&& !verbose
)
752 _cupsLangPuts(stdout
, _(" FAIL\n"));
754 _cupsLangPuts(stdout
,
755 _(" **FAIL** REQUIRED Product\n"
756 " REF: Page 62, section 5.3.\n"));
762 if ((attr
= ppdFindAttr(ppd
, "PSVersion", NULL
)) != NULL
&&
765 char junkstr
[255]; /* Temp string */
766 int junkint
; /* Temp integer */
769 if (sscanf(attr
->value
, "(%[^)])%d", junkstr
, &junkint
) != 2)
773 if (!errors
&& !verbose
)
774 _cupsLangPuts(stdout
, _(" FAIL\n"));
776 _cupsLangPuts(stdout
,
777 _(" **FAIL** BAD PSVersion - not \"(string) "
779 " REF: Pages 62-64, section 5.3.\n"));
784 else if (verbose
> 0)
785 _cupsLangPuts(stdout
, _(" PASS PSVersion\n"));
791 if (!errors
&& !verbose
)
792 _cupsLangPuts(stdout
, _(" FAIL\n"));
794 _cupsLangPuts(stdout
,
795 _(" **FAIL** REQUIRED PSVersion\n"
796 " REF: Pages 62-64, section 5.3.\n"));
802 if (ppd
->shortnickname
!= NULL
)
804 if (strlen(ppd
->shortnickname
) > 31)
808 if (!errors
&& !verbose
)
809 _cupsLangPuts(stdout
, _(" FAIL\n"));
811 _cupsLangPuts(stdout
,
812 _(" **FAIL** BAD ShortNickName - longer "
814 " REF: Pages 64-65, section 5.3.\n"));
819 else if (verbose
> 0)
820 _cupsLangPuts(stdout
, _(" PASS ShortNickName\n"));
822 else if (ppdversion
>= 43)
826 if (!errors
&& !verbose
)
827 _cupsLangPuts(stdout
, _(" FAIL\n"));
829 _cupsLangPuts(stdout
,
830 _(" **FAIL** REQUIRED ShortNickName\n"
831 " REF: Page 64-65, section 5.3.\n"));
837 if (ppd
->patches
!= NULL
&& strchr(ppd
->patches
, '\"') &&
838 strstr(ppd
->patches
, "*End"))
842 if (!errors
&& !verbose
)
843 _cupsLangPuts(stdout
, _(" FAIL\n"));
845 _cupsLangPuts(stdout
,
846 _(" **FAIL** BAD JobPatchFile attribute in file\n"
847 " REF: Page 24, section 3.4.\n"));
854 * Check for page sizes without the corresponding ImageableArea or
855 * PaperDimension values...
858 if (ppd
->num_sizes
== 0)
862 if (!errors
&& !verbose
)
863 _cupsLangPuts(stdout
, _(" FAIL\n"));
865 _cupsLangPuts(stdout
,
866 _(" **FAIL** REQUIRED PageSize\n"
867 " REF: Page 41, section 5.\n"
868 " REF: Page 99, section 5.14.\n"));
875 for (j
= 0, size
= ppd
->sizes
; j
< ppd
->num_sizes
; j
++, size
++)
878 * Don't check custom size...
881 if (!strcmp(size
->name
, "Custom"))
885 * Check for ImageableArea...
888 if (size
->left
== 0.0 && size
->bottom
== 0.0 &&
889 size
->right
== 0.0 && size
->top
== 0.0)
893 if (!errors
&& !verbose
)
894 _cupsLangPuts(stdout
, _(" FAIL\n"));
896 _cupsLangPrintf(stdout
,
897 _(" **FAIL** REQUIRED ImageableArea for "
899 " REF: Page 41, section 5.\n"
900 " REF: Page 102, section 5.15.\n"),
908 * Check for PaperDimension...
911 if (size
->width
== 0.0 && size
->length
== 0.0)
915 if (!errors
&& !verbose
)
916 _cupsLangPuts(stdout
, _(" FAIL\n"));
918 _cupsLangPrintf(stdout
,
919 _(" **FAIL** REQUIRED PaperDimension "
921 " REF: Page 41, section 5.\n"
922 " REF: Page 103, section 5.15.\n"),
932 * Check for valid Resolution, JCLResolution, or SetResolution values...
935 if ((option
= ppdFindOption(ppd
, "Resolution")) == NULL
)
936 if ((option
= ppdFindOption(ppd
, "JCLResolution")) == NULL
)
937 option
= ppdFindOption(ppd
, "SetResolution");
941 for (j
= option
->num_choices
, choice
= option
->choices
; j
> 0; j
--, choice
++)
944 * Verify that all resolution options are of the form NNNdpi
948 xdpi
= strtol(choice
->choice
, (char **)&ptr
, 10);
949 if (ptr
> choice
->choice
&& xdpi
> 0)
952 ydpi
= strtol(ptr
+ 1, (char **)&ptr
, 10);
959 if (xdpi
<= 0 || ydpi
<= 0 || strcmp(ptr
, "dpi"))
963 if (!errors
&& !verbose
)
964 _cupsLangPuts(stdout
, _(" FAIL\n"));
966 _cupsLangPrintf(stdout
,
967 _(" **FAIL** Bad %s choice %s!\n"
968 " REF: Page 84, section 5.9\n"),
969 option
->keyword
, choice
->choice
);
978 * Check for a duplex option, and for standard values...
981 if ((option
= ppdFindOption(ppd
, "Duplex")) == NULL
)
982 if ((option
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
983 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
984 option
= ppdFindOption(ppd
, "KD03Duplex");
988 if (ppdFindChoice(option
, "None") == NULL
)
992 if (!errors
&& !verbose
)
993 _cupsLangPuts(stdout
, _(" FAIL\n"));
995 _cupsLangPrintf(stdout
,
996 _(" **FAIL** REQUIRED %s does not define "
998 " REF: Page 122, section 5.17\n"),
1005 for (j
= option
->num_choices
, choice
= option
->choices
; j
> 0; j
--, choice
++)
1006 if (strcmp(choice
->choice
, "None") &&
1007 strcmp(choice
->choice
, "DuplexNoTumble") &&
1008 strcmp(choice
->choice
, "DuplexTumble") &&
1009 strcmp(choice
->choice
, "SimplexTumble"))
1013 if (!errors
&& !verbose
)
1014 _cupsLangPuts(stdout
, _(" FAIL\n"));
1016 _cupsLangPrintf(stdout
,
1017 _(" **FAIL** Bad %s choice %s!\n"
1018 " REF: Page 122, section 5.17\n"),
1019 option
->keyword
, choice
->choice
);
1026 if ((attr
= ppdFindAttr(ppd
, "cupsLanguages", NULL
)) != NULL
&&
1030 * This file contains localizations, check them...
1033 char *languages
, /* Copy of attribute value */
1034 *langstart
, /* Start of current language */
1035 *langptr
, /* Pointer into languages */
1036 keyword
[PPD_MAX_NAME
],
1037 /* Localization keyword */
1038 ckeyword
[PPD_MAX_NAME
];
1039 /* Custom option keyword */
1040 ppd_coption_t
*coption
; /* Custom option */
1041 ppd_cparam_t
*cparam
; /* Custom parameter */
1042 cups_array_t
*langlist
; /* List of languages so far */
1043 char ll
[3]; /* Base language */
1046 languages
= strdup(attr
->value
);
1047 langlist
= cupsArrayNew((cups_array_func_t
)strcmp
, NULL
);
1049 for (langptr
= languages
; *langptr
;)
1052 * Skip leading whitespace...
1055 while (isspace(*langptr
& 255))
1062 * Find the end of this language name...
1065 for (langstart
= langptr
;
1066 *langptr
&& !isspace(*langptr
& 255);
1072 j
= strlen(langstart
);
1073 if (j
!= 2 && j
!= 5)
1077 if (!errors
&& !verbose
)
1078 _cupsLangPuts(stdout
, _(" FAIL\n"));
1080 _cupsLangPrintf(stdout
,
1081 _(" **FAIL** Bad language \"%s\"!\n"),
1089 cupsArrayAdd(langlist
, langstart
);
1092 * Loop through all options and choices...
1095 for (option
= ppdFirstOption(ppd
);
1097 option
= ppdNextOption(ppd
))
1099 snprintf(keyword
, sizeof(keyword
), "%s.Translation", langstart
);
1100 if ((attr
= ppdFindAttr(ppd
, keyword
, option
->keyword
)) == NULL
)
1104 if (!errors
&& !verbose
)
1105 _cupsLangPuts(stdout
, _(" FAIL\n"));
1107 _cupsLangPrintf(stdout
,
1108 _(" **FAIL** Missing \"%s\" translation "
1109 "string for option %s!\n"),
1110 langstart
, option
->keyword
);
1115 else if (!valid_utf8(attr
->text
))
1119 if (!errors
&& !verbose
)
1120 _cupsLangPuts(stdout
, _(" FAIL\n"));
1122 _cupsLangPrintf(stdout
,
1123 _(" **FAIL** Bad UTF-8 \"%s\" translation "
1124 "string for option %s!\n"),
1125 langstart
, option
->keyword
);
1131 for (ptr
= option
->text
; *ptr
; ptr
++)
1139 if (!errors
&& !verbose
)
1140 _cupsLangPuts(stdout
, _(" FAIL\n"));
1142 _cupsLangPrintf(stdout
,
1143 _(" **FAIL** Default translation "
1144 "string for option %s contains 8-bit "
1152 snprintf(keyword
, sizeof(keyword
), "%s.%s", langstart
,
1154 for (j
= 0; j
< option
->num_choices
; j
++)
1156 if (!strcasecmp(option
->choices
[j
].choice
, "Custom") &&
1157 (coption
= ppdFindCustomOption(ppd
,
1158 option
->keyword
)) != NULL
)
1160 snprintf(ckeyword
, sizeof(ckeyword
), "%s.Custom%s",
1161 langstart
, option
->keyword
);
1163 if ((attr
= ppdFindAttr(ppd
, ckeyword
, "True")) != NULL
&&
1164 !valid_utf8(attr
->text
))
1168 if (!errors
&& !verbose
)
1169 _cupsLangPuts(stdout
, _(" FAIL\n"));
1171 _cupsLangPrintf(stdout
,
1172 _(" **FAIL** Bad UTF-8 \"%s\" "
1173 "translation string for option %s, "
1175 langstart
, ckeyword
+ 1 + strlen(langstart
),
1182 if (strcasecmp(option
->keyword
, "PageSize"))
1184 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
1186 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
1188 snprintf(ckeyword
, sizeof(ckeyword
), "%s.ParamCustom%s",
1189 langstart
, option
->keyword
);
1190 if ((attr
= ppdFindAttr(ppd
, ckeyword
, cparam
->name
)) == NULL
)
1194 if (!errors
&& !verbose
)
1195 _cupsLangPuts(stdout
, _(" FAIL\n"));
1197 _cupsLangPrintf(stdout
,
1198 _(" **FAIL** Missing \"%s\" "
1199 "translation string for option %s, "
1202 ckeyword
+ 1 + strlen(langstart
),
1208 else if (!valid_utf8(attr
->text
))
1212 if (!errors
&& !verbose
)
1213 _cupsLangPuts(stdout
, _(" FAIL\n"));
1215 _cupsLangPrintf(stdout
,
1216 _(" **FAIL** Bad UTF-8 \"%s\" "
1217 "translation string for option %s, "
1220 ckeyword
+ 1 + strlen(langstart
),
1229 else if ((attr
= ppdFindAttr(ppd
, keyword
, option
->choices
[j
].choice
)) == NULL
)
1233 if (!errors
&& !verbose
)
1234 _cupsLangPuts(stdout
, _(" FAIL\n"));
1236 _cupsLangPrintf(stdout
,
1237 _(" **FAIL** Missing \"%s\" "
1238 "translation string for option %s, "
1240 langstart
, option
->keyword
,
1241 option
->choices
[j
].choice
);
1246 else if (!valid_utf8(attr
->text
))
1250 if (!errors
&& !verbose
)
1251 _cupsLangPuts(stdout
, _(" FAIL\n"));
1253 _cupsLangPrintf(stdout
,
1254 _(" **FAIL** Bad UTF-8 \"%s\" "
1255 "translation string for option %s, "
1257 langstart
, option
->keyword
,
1258 option
->choices
[j
].choice
);
1264 for (ptr
= option
->choices
[j
].text
; *ptr
; ptr
++)
1272 if (!errors
&& !verbose
)
1273 _cupsLangPuts(stdout
, _(" FAIL\n"));
1275 _cupsLangPrintf(stdout
,
1276 _(" **FAIL** Default translation "
1277 "string for option %s choice %s contains "
1278 "8-bit characters!\n"),
1280 option
->choices
[j
].choice
);
1290 * Verify that we have the base language for each localized one...
1293 for (langptr
= (char *)cupsArrayFirst(langlist
);
1295 langptr
= (char *)cupsArrayNext(langlist
))
1299 * Lookup the base language...
1302 cupsArraySave(langlist
);
1304 strlcpy(ll
, langptr
, sizeof(ll
));
1306 if (!cupsArrayFind(langlist
, ll
))
1310 if (!errors
&& !verbose
)
1311 _cupsLangPuts(stdout
, _(" FAIL\n"));
1313 _cupsLangPrintf(stdout
,
1314 _(" **FAIL** No base translation \"%s\" "
1315 "is included in file!\n"), ll
);
1321 cupsArrayRestore(langlist
);
1325 * Free memory used for the languages...
1328 cupsArrayDelete(langlist
);
1332 for (attr
= ppdFindAttr(ppd
, "cupsFilter", NULL
);
1334 attr
= ppdFindNextAttr(ppd
, "cupsFilter", NULL
))
1337 sscanf(attr
->value
, "%15[^/]/%255s%d%255s", super
, type
, &cost
,
1342 if (!errors
&& !verbose
)
1343 _cupsLangPuts(stdout
, _(" FAIL\n"));
1345 _cupsLangPrintf(stdout
,
1346 _(" **FAIL** Bad cupsFilter value \"%s\"!\n"),
1347 attr
->value
? attr
->value
: "");
1354 if (program
[0] == '/')
1355 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
1358 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
1359 ptr
= CUPS_SERVERBIN
;
1361 if (*ptr
== '/' || !*root
)
1362 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
1365 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
1369 if (stat(pathprog
, &statbuf
))
1373 if (!errors
&& !verbose
)
1374 _cupsLangPuts(stdout
, _(" FAIL\n"));
1376 _cupsLangPrintf(stdout
, _(" **FAIL** Missing cupsFilter "
1377 "file \"%s\"\n"), program
);
1385 for (attr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
);
1387 attr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
))
1390 sscanf(attr
->value
, "%15[^/]/%255s%d%255s", super
, type
, &cost
,
1395 if (!errors
&& !verbose
)
1396 _cupsLangPuts(stdout
, _(" FAIL\n"));
1398 _cupsLangPrintf(stdout
,
1399 _(" **FAIL** Bad cupsPreFilter value \"%s\"!\n"),
1400 attr
->value
? attr
->value
: "");
1407 if (program
[0] == '/')
1408 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
1411 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
1412 ptr
= CUPS_SERVERBIN
;
1414 if (*ptr
== '/' || !*root
)
1415 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
1418 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
1422 if (stat(pathprog
, &statbuf
))
1426 if (!errors
&& !verbose
)
1427 _cupsLangPuts(stdout
, _(" FAIL\n"));
1429 _cupsLangPrintf(stdout
, _(" **FAIL** Missing cupsPreFilter "
1430 "file \"%s\"\n"), program
);
1438 if ((attr
= ppdFindAttr(ppd
, "1284DeviceID", NULL
)) &&
1439 strcmp(attr
->name
, "1284DeviceID"))
1443 if (!errors
&& !verbose
)
1444 _cupsLangPuts(stdout
, _(" FAIL\n"));
1446 _cupsLangPrintf(stdout
,
1447 _(" **FAIL** %s must be 1284DeviceID!\n"
1448 " REF: Page 72, section 5.5\n"),
1456 * Check for bad UIConstraints...
1459 for (j
= ppd
->num_consts
, c
= ppd
->consts
; j
> 0; j
--, c
++)
1461 option
= ppdFindOption(ppd
, c
->option1
);
1462 option2
= ppdFindOption(ppd
, c
->option2
);
1464 if (!option
|| !option2
)
1466 if (!errors
&& !verbose
)
1467 _cupsLangPuts(stdout
, _(" FAIL\n"));
1470 _cupsLangPrintf(stdout
,
1471 _(" **FAIL** Missing option %s in "
1472 "UIConstraint \"*%s %s *%s %s\"!\n"),
1474 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1477 _cupsLangPrintf(stdout
,
1478 _(" **FAIL** Missing option %s in "
1479 "UIConstraint \"*%s %s *%s %s\"!\n"),
1481 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1486 if (c
->choice1
[0] && !ppdFindChoice(option
, c
->choice1
))
1488 if (!errors
&& !verbose
)
1489 _cupsLangPuts(stdout
, _(" FAIL\n"));
1491 _cupsLangPrintf(stdout
,
1492 _(" **FAIL** Missing choice *%s %s in "
1493 "UIConstraint \"*%s %s *%s %s\"!\n"),
1494 c
->option1
, c
->choice1
,
1495 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1498 if (c
->choice2
[0] && !ppdFindChoice(option2
, c
->choice2
))
1500 if (!errors
&& !verbose
)
1501 _cupsLangPuts(stdout
, _(" FAIL\n"));
1503 _cupsLangPrintf(stdout
,
1504 _(" **FAIL** Missing choice *%s %s in "
1505 "UIConstraint \"*%s %s *%s %s\"!\n"),
1506 c
->option2
, c
->choice2
,
1507 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1512 * Final pass/fail notification...
1516 status
= ERROR_CONFORMANCE
;
1518 _cupsLangPuts(stdout
, _(" PASS\n"));
1522 check_basics(argv
[i
]);
1525 * Look for default keywords with no corresponding option...
1528 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1530 attr
= ppd
->attrs
[j
];
1532 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
1533 !strcmp(attr
->name
, "DefaultColorSep") ||
1534 !strcmp(attr
->name
, "DefaultFont") ||
1535 !strcmp(attr
->name
, "DefaultImageableArea") ||
1536 !strcmp(attr
->name
, "DefaultOutputOrder") ||
1537 !strcmp(attr
->name
, "DefaultPaperDimension") ||
1538 !strcmp(attr
->name
, "DefaultScreenProc") ||
1539 !strcmp(attr
->name
, "DefaultTransfer"))
1542 if (!strncmp(attr
->name
, "Default", 7) &&
1543 !ppdFindOption(ppd
, attr
->name
+ 7))
1544 _cupsLangPrintf(stdout
,
1545 _(" WARN %s has no corresponding "
1551 * Check for old Duplex option names...
1554 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
1555 option
= ppdFindOption(ppd
, "KD03Duplex");
1559 _cupsLangPrintf(stdout
,
1560 _(" WARN Duplex option keyword %s "
1561 "should be named Duplex or JCLDuplex!\n"
1562 " REF: Page 122, section 5.17\n"),
1566 ppdMarkDefaults(ppd
);
1567 if (ppdConflicts(ppd
))
1569 _cupsLangPuts(stdout
,
1570 _(" WARN Default choices conflicting!\n"));
1572 show_conflicts(ppd
);
1575 if (ppdversion
< 43)
1577 _cupsLangPrintf(stdout
,
1578 _(" WARN Obsolete PPD version %.1f!\n"
1579 " REF: Page 42, section 5.2.\n"),
1583 if (!ppd
->lang_encoding
&& ppdversion
< 41)
1585 _cupsLangPuts(stdout
,
1586 _(" WARN LanguageEncoding required by PPD "
1588 " REF: Pages 56-57, section 5.3.\n"));
1591 if (!ppd
->manufacturer
&& ppdversion
< 43)
1593 _cupsLangPuts(stdout
,
1594 _(" WARN Manufacturer required by PPD "
1596 " REF: Pages 58-59, section 5.3.\n"));
1600 * Treat a PCFileName attribute longer than 12 characters as
1601 * a warning and not a hard error...
1604 if (ppd
->pcfilename
&& strlen(ppd
->pcfilename
) > 12)
1606 _cupsLangPuts(stdout
,
1607 _(" WARN PCFileName longer than 8.3 in "
1608 "violation of PPD spec.\n"
1609 " REF: Pages 61-62, section 5.3.\n"));
1612 if (!ppd
->shortnickname
&& ppdversion
< 43)
1614 _cupsLangPuts(stdout
,
1615 _(" WARN ShortNickName required by PPD "
1617 " REF: Pages 64-65, section 5.3.\n"));
1621 * Check the Protocols line and flag PJL + BCP since TBCP is
1622 * usually used with PJL...
1627 if (strstr(ppd
->protocols
, "PJL") &&
1628 strstr(ppd
->protocols
, "BCP") &&
1629 !strstr(ppd
->protocols
, "TBCP"))
1631 _cupsLangPuts(stdout
,
1632 _(" WARN Protocols contains both PJL "
1633 "and BCP; expected TBCP.\n"
1634 " REF: Pages 78-79, section 5.7.\n"));
1637 if (strstr(ppd
->protocols
, "PJL") &&
1638 (!ppd
->jcl_begin
|| !ppd
->jcl_end
|| !ppd
->jcl_ps
))
1640 _cupsLangPuts(stdout
,
1641 _(" WARN Protocols contains PJL but JCL "
1642 "attributes are not set.\n"
1643 " REF: Pages 78-79, section 5.7.\n"));
1648 * Check for options with a common prefix, e.g. Duplex and Duplexer,
1649 * which are errors according to the spec but won't cause problems
1650 * with CUPS specifically...
1653 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1654 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1656 len
= strlen(option
->keyword
);
1658 for (m
= 0, group2
= ppd
->groups
;
1659 m
< ppd
->num_groups
;
1661 for (n
= 0, option2
= group2
->options
;
1662 n
< group2
->num_options
;
1664 if (option
!= option2
&&
1665 len
< strlen(option2
->keyword
) &&
1666 !strncmp(option
->keyword
, option2
->keyword
, len
))
1668 _cupsLangPrintf(stdout
,
1669 _(" WARN %s shares a common "
1671 " REF: Page 15, section "
1673 option
->keyword
, option2
->keyword
);
1682 for (attr
= ppdFindAttr(ppd
, "cupsICCProfile", NULL
);
1684 attr
= ppdFindNextAttr(ppd
, "cupsICCProfile", NULL
))
1688 if (attr
->value
[0] == '/')
1689 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, attr
->value
);
1692 if ((ptr
= getenv("CUPS_DATADIR")) == NULL
)
1695 if (*ptr
== '/' || !*root
)
1696 snprintf(pathprog
, sizeof(pathprog
), "%s%s/profiles/%s", root
,
1699 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/profiles/%s", root
,
1704 if (!attr
->value
|| !attr
->value
[0] || stat(pathprog
, &statbuf
))
1707 _cupsLangPrintf(stdout
,
1708 _(" WARN Missing cupsICCProfile "
1710 !attr
->value
|| !attr
->value
[0] ? "<NULL>" :
1720 for (attr
= ppdFindAttr(ppd
, "APDialogExtension", NULL
);
1722 attr
= ppdFindNextAttr(ppd
, "APDialogExtension", NULL
))
1724 if ((!attr
->value
|| stat(attr
->value
, &statbuf
)) && verbose
>= 0)
1725 _cupsLangPrintf(stdout
, _(" WARN Missing "
1726 "APDialogExtension file \"%s\"\n"),
1727 attr
->value
? attr
->value
: "<NULL>");
1734 for (attr
= ppdFindAttr(ppd
, "APPrinterIconPath", NULL
);
1736 attr
= ppdFindNextAttr(ppd
, "APPrinterIconPath", NULL
))
1738 if ((!attr
->value
|| stat(attr
->value
, &statbuf
)) && verbose
>= 0)
1739 _cupsLangPrintf(stdout
, _(" WARN Missing "
1740 "APPrinterIconPath file \"%s\"\n"),
1741 attr
->value
? attr
->value
: "<NULL>");
1743 #endif /* __APPLE__ */
1748 _cupsLangPrintf(stdout
, _(" %d ERRORS FOUND\n"), errors
);
1750 _cupsLangPuts(stdout
, _(" NO ERRORS FOUND\n"));
1754 * Then list the options, if "-v" was provided...
1759 _cupsLangPrintf(stdout
,
1761 " language_level = %d\n"
1762 " color_device = %s\n"
1763 " variable_sizes = %s\n"
1764 " landscape = %d\n",
1765 ppd
->language_level
,
1766 ppd
->color_device
? "TRUE" : "FALSE",
1767 ppd
->variable_sizes
? "TRUE" : "FALSE",
1770 switch (ppd
->colorspace
)
1773 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMYK\n");
1776 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMY\n");
1779 _cupsLangPuts(stdout
, " colorspace = PPD_CS_GRAY\n");
1782 _cupsLangPuts(stdout
, " colorspace = PPD_CS_RGB\n");
1785 _cupsLangPuts(stdout
, " colorspace = <unknown>\n");
1789 _cupsLangPrintf(stdout
, " num_emulations = %d\n",
1790 ppd
->num_emulations
);
1791 for (j
= 0; j
< ppd
->num_emulations
; j
++)
1792 _cupsLangPrintf(stdout
, " emulations[%d] = %s\n",
1793 j
, ppd
->emulations
[j
].name
);
1795 _cupsLangPrintf(stdout
, " lang_encoding = %s\n",
1796 ppd
->lang_encoding
);
1797 _cupsLangPrintf(stdout
, " lang_version = %s\n",
1799 _cupsLangPrintf(stdout
, " modelname = %s\n", ppd
->modelname
);
1800 _cupsLangPrintf(stdout
, " ttrasterizer = %s\n",
1801 ppd
->ttrasterizer
== NULL
? "None" : ppd
->ttrasterizer
);
1802 _cupsLangPrintf(stdout
, " manufacturer = %s\n",
1804 _cupsLangPrintf(stdout
, " product = %s\n", ppd
->product
);
1805 _cupsLangPrintf(stdout
, " nickname = %s\n", ppd
->nickname
);
1806 _cupsLangPrintf(stdout
, " shortnickname = %s\n",
1807 ppd
->shortnickname
);
1808 _cupsLangPrintf(stdout
, " patches = %d bytes\n",
1809 ppd
->patches
== NULL
? 0 : (int)strlen(ppd
->patches
));
1811 _cupsLangPrintf(stdout
, " num_groups = %d\n", ppd
->num_groups
);
1812 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1814 _cupsLangPrintf(stdout
, " group[%d] = %s\n",
1817 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1819 _cupsLangPrintf(stdout
,
1820 " options[%d] = %s (%s) %s %s %.0f "
1822 k
, option
->keyword
, option
->text
, uis
[option
->ui
],
1823 sections
[option
->section
], option
->order
,
1824 option
->num_choices
);
1826 if (!strcmp(option
->keyword
, "PageSize") ||
1827 !strcmp(option
->keyword
, "PageRegion"))
1829 for (m
= option
->num_choices
, choice
= option
->choices
;
1833 size
= ppdPageSize(ppd
, choice
->choice
);
1836 _cupsLangPrintf(stdout
,
1838 choice
->choice
, choice
->text
);
1840 _cupsLangPrintf(stdout
,
1841 " %s (%s) = %.2fx%.2fin "
1842 "(%.1f,%.1f,%.1f,%.1f)",
1843 choice
->choice
, choice
->text
,
1844 size
->width
/ 72.0, size
->length
/ 72.0,
1845 size
->left
/ 72.0, size
->bottom
/ 72.0,
1846 size
->right
/ 72.0, size
->top
/ 72.0);
1848 if (!strcmp(option
->defchoice
, choice
->choice
))
1849 _cupsLangPuts(stdout
, " *\n");
1851 _cupsLangPuts(stdout
, "\n");
1856 for (m
= option
->num_choices
, choice
= option
->choices
;
1860 _cupsLangPrintf(stdout
, " %s (%s)",
1861 choice
->choice
, choice
->text
);
1863 if (!strcmp(option
->defchoice
, choice
->choice
))
1864 _cupsLangPuts(stdout
, " *\n");
1866 _cupsLangPuts(stdout
, "\n");
1872 _cupsLangPrintf(stdout
, " num_profiles = %d\n",
1874 for (j
= 0; j
< ppd
->num_profiles
; j
++)
1875 _cupsLangPrintf(stdout
,
1876 " profiles[%d] = %s/%s %.3f %.3f "
1877 "[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
1878 j
, ppd
->profiles
[j
].resolution
,
1879 ppd
->profiles
[j
].media_type
,
1880 ppd
->profiles
[j
].gamma
, ppd
->profiles
[j
].density
,
1881 ppd
->profiles
[j
].matrix
[0][0],
1882 ppd
->profiles
[j
].matrix
[0][1],
1883 ppd
->profiles
[j
].matrix
[0][2],
1884 ppd
->profiles
[j
].matrix
[1][0],
1885 ppd
->profiles
[j
].matrix
[1][1],
1886 ppd
->profiles
[j
].matrix
[1][2],
1887 ppd
->profiles
[j
].matrix
[2][0],
1888 ppd
->profiles
[j
].matrix
[2][1],
1889 ppd
->profiles
[j
].matrix
[2][2]);
1891 _cupsLangPrintf(stdout
, " num_fonts = %d\n", ppd
->num_fonts
);
1892 for (j
= 0; j
< ppd
->num_fonts
; j
++)
1893 _cupsLangPrintf(stdout
, " fonts[%d] = %s\n",
1896 _cupsLangPrintf(stdout
, " num_attrs = %d\n", ppd
->num_attrs
);
1897 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1898 _cupsLangPrintf(stdout
,
1899 " attrs[%d] = %s %s%s%s: \"%s\"\n", j
,
1900 ppd
->attrs
[j
]->name
, ppd
->attrs
[j
]->spec
,
1901 ppd
->attrs
[j
]->text
[0] ? "/" : "",
1902 ppd
->attrs
[j
]->text
,
1903 ppd
->attrs
[j
]->value
?
1904 ppd
->attrs
[j
]->value
: "(null)");
1918 * 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1922 check_basics(const char *filename
) /* I - PPD file to check */
1924 cups_file_t
*fp
; /* File pointer */
1925 int ch
; /* Current character */
1926 int col
, /* Current column */
1927 whitespace
; /* Only seen whitespace? */
1928 int eol
; /* Line endings */
1929 int linenum
; /* Line number */
1930 int mixed
; /* Mixed line endings? */
1933 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
1942 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
1944 if (ch
== '\r' || ch
== '\n')
1948 if (eol
== EOL_NONE
)
1950 else if (eol
!= EOL_LF
)
1953 else if (ch
== '\r')
1955 if (cupsFilePeekChar(fp
) == '\n')
1957 cupsFileGetChar(fp
);
1959 if (eol
== EOL_NONE
)
1964 else if (eol
== EOL_NONE
)
1970 if (col
> 0 && whitespace
)
1971 _cupsLangPrintf(stdout
,
1972 _(" WARN Line %d only contains whitespace!\n"),
1981 if (ch
!= ' ' && ch
!= '\t')
1989 _cupsLangPuts(stdout
,
1990 _(" WARN File contains a mix of CR, LF, and "
1991 "CR LF line endings!\n"));
1993 if (eol
== EOL_CRLF
)
1994 _cupsLangPuts(stdout
,
1995 _(" WARN Non-Windows PPD files should use lines "
1996 "ending with only LF, not CR LF!\n"));
2003 * 'show_conflicts()' - Show option conflicts in a PPD file.
2007 show_conflicts(ppd_file_t
*ppd
) /* I - PPD to check */
2009 int i
, j
; /* Looping variables */
2010 ppd_const_t
*c
; /* Current constraint */
2011 ppd_option_t
*o1
, *o2
; /* Options */
2012 ppd_choice_t
*c1
, *c2
; /* Choices */
2016 * Loop through all of the UI constraints and report any options
2020 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
2023 * Grab pointers to the first option...
2026 o1
= ppdFindOption(ppd
, c
->option1
);
2030 else if (c
->choice1
[0] != '\0')
2033 * This constraint maps to a specific choice.
2036 c1
= ppdFindChoice(o1
, c
->choice1
);
2041 * This constraint applies to any choice for this option.
2044 for (j
= o1
->num_choices
, c1
= o1
->choices
; j
> 0; j
--, c1
++)
2049 !strcasecmp(c1
->choice
, "None") ||
2050 !strcasecmp(c1
->choice
, "Off") ||
2051 !strcasecmp(c1
->choice
, "False"))
2056 * Grab pointers to the second option...
2059 o2
= ppdFindOption(ppd
, c
->option2
);
2063 else if (c
->choice2
[0] != '\0')
2066 * This constraint maps to a specific choice.
2069 c2
= ppdFindChoice(o2
, c
->choice2
);
2074 * This constraint applies to any choice for this option.
2077 for (j
= o2
->num_choices
, c2
= o2
->choices
; j
> 0; j
--, c2
++)
2082 !strcasecmp(c2
->choice
, "None") ||
2083 !strcasecmp(c2
->choice
, "Off") ||
2084 !strcasecmp(c2
->choice
, "False"))
2089 * If both options are marked then there is a conflict...
2092 if (c1
!= NULL
&& c1
->marked
&& c2
!= NULL
&& c2
->marked
)
2093 _cupsLangPrintf(stdout
,
2094 _(" WARN \"%s %s\" conflicts with \"%s %s\"\n"
2095 " (constraint=\"%s %s %s %s\")\n"),
2096 o1
->keyword
, c1
->choice
, o2
->keyword
, c2
->choice
,
2097 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2103 * 'usage()' - Show program usage...
2109 _cupsLangPuts(stdout
,
2110 _("Usage: cupstestppd [-R root-directory] [-q] [-r] [-v[v]] "
2111 "filename1.ppd[.gz] [... filenameN.ppd[.gz]]\n"
2112 " program | cupstestppd [-R root-directory] [-q] [-r] "
2120 * 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
2123 int /* O - 1 if valid, 0 if not */
2124 valid_utf8(const char *s
) /* I - String to check */
2131 * Check for valid UTF-8 sequence...
2134 if ((*s
& 0xc0) == 0x80)
2135 return (0); /* Illegal suffix byte */
2136 else if ((*s
& 0xe0) == 0xc0)
2139 * 2-byte sequence...
2144 if ((*s
& 0xc0) != 0x80)
2145 return (0); /* Missing suffix byte */
2147 else if ((*s
& 0xf0) == 0xe0)
2150 * 3-byte sequence...
2155 if ((*s
& 0xc0) != 0x80)
2156 return (0); /* Missing suffix byte */
2160 if ((*s
& 0xc0) != 0x80)
2161 return (0); /* Missing suffix byte */
2163 else if ((*s
& 0xf8) == 0xf0)
2166 * 4-byte sequence...
2171 if ((*s
& 0xc0) != 0x80)
2172 return (0); /* Missing suffix byte */
2176 if ((*s
& 0xc0) != 0x80)
2177 return (0); /* Missing suffix byte */
2181 if ((*s
& 0xc0) != 0x80)
2182 return (0); /* Missing suffix byte */
2185 return (0); /* Bad sequence */
2196 * End of "$Id: cupstestppd.c 6444 2007-04-04 22:13:58Z mike $".