2 * "$Id: cupstestppd.c 4990 2006-01-26 02:21:45Z mike $"
4 * PPD test program for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 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...
36 * Include necessary headers...
39 #include <cups/string.h>
40 #include <cups/cups.h>
41 #include <cups/i18n.h>
77 void check_basics(const char *filename
);
78 void show_conflicts(ppd_file_t
*ppd
);
83 * 'main()' - Main entry for test program.
86 int /* O - Exit status */
87 main(int argc
, /* I - Number of command-line arguments */
88 char *argv
[]) /* I - Command-line arguments */
90 int i
, j
, k
, m
, n
; /* Looping vars */
91 int len
; /* Length of option name */
92 char *opt
; /* Option character */
93 const char *ptr
; /* Pointer into string */
94 int files
; /* Number of files */
95 int verbose
; /* Want verbose output? */
96 int status
; /* Exit status */
97 int errors
; /* Number of conformance errors */
98 int ppdversion
; /* PPD spec version in PPD file */
99 ppd_status_t error
; /* Status of ppdOpen*() */
100 int line
; /* Line number for error */
101 int xdpi
, /* X resolution */
102 ydpi
; /* Y resolution */
103 ppd_file_t
*ppd
; /* PPD file record */
104 ppd_attr_t
*attr
; /* PPD attribute */
105 ppd_size_t
*size
; /* Size record */
106 ppd_group_t
*group
; /* UI group */
107 ppd_option_t
*option
; /* Standard UI option */
108 ppd_group_t
*group2
; /* UI group */
109 ppd_option_t
*option2
; /* Standard UI option */
110 ppd_choice_t
*choice
; /* Standard UI option choice */
111 static char *uis
[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
112 static char *sections
[] = { "ANY", "DOCUMENT", "EXIT",
113 "JCL", "PAGE", "PROLOG" };
117 * Display PPD files for each file listed on the command-line...
120 ppdSetConformance(PPD_CONFORM_STRICT
);
127 for (i
= 1; i
< argc
; i
++)
128 if (argv
[i
][0] == '-' && argv
[i
][1])
130 for (opt
= argv
[i
] + 1; *opt
; opt
++)
133 case 'q' : /* Quiet mode */
136 _cupsLangPuts(stderr
,
137 _("cupstestppd: The -q option is incompatible "
138 "with the -v option.\n"));
145 case 'r' : /* Relaxed mode */
146 ppdSetConformance(PPD_CONFORM_RELAXED
);
149 case 'v' : /* Verbose mode */
152 _cupsLangPuts(stderr
,
153 _("cupstestppd: The -v option is incompatible "
154 "with the -q option.\n"));
169 * Open the PPD file...
172 if (files
&& verbose
>= 0)
173 _cupsLangPuts(stdout
, "\n");
177 if (argv
[i
][0] == '-')
186 ppd
= ppdOpen(stdin
);
191 * Read from a file...
195 printf("%s:", argv
[i
]);
197 ppd
= ppdOpenFile(argv
[i
]);
202 error
= ppdLastError(&line
);
204 if (error
<= PPD_ALLOC_ERROR
)
206 status
= ERROR_FILE_OPEN
;
209 _cupsLangPrintf(stdout
,
211 " **FAIL** Unable to open PPD file - %s\n"),
216 status
= ERROR_PPD_FORMAT
;
220 _cupsLangPrintf(stdout
,
222 " **FAIL** Unable to open PPD file - "
224 ppdErrorString(error
), line
);
228 case PPD_MISSING_PPDADOBE4
:
229 _cupsLangPuts(stdout
,
230 _(" REF: Page 42, section 5.2.\n"));
232 case PPD_MISSING_VALUE
:
233 _cupsLangPuts(stdout
,
234 _(" REF: Page 20, section 3.4.\n"));
236 case PPD_BAD_OPEN_GROUP
:
237 case PPD_NESTED_OPEN_GROUP
:
238 _cupsLangPuts(stdout
,
239 _(" REF: Pages 45-46, section 5.2.\n"));
241 case PPD_BAD_OPEN_UI
:
242 case PPD_NESTED_OPEN_UI
:
243 _cupsLangPuts(stdout
,
244 _(" REF: Pages 42-45, section 5.2.\n"));
246 case PPD_BAD_ORDER_DEPENDENCY
:
247 _cupsLangPuts(stdout
,
248 _(" REF: Pages 48-49, section 5.2.\n"));
250 case PPD_BAD_UI_CONSTRAINTS
:
251 _cupsLangPuts(stdout
,
252 _(" REF: Pages 52-54, section 5.2.\n"));
254 case PPD_MISSING_ASTERISK
:
255 _cupsLangPuts(stdout
,
256 _(" REF: Page 15, section 3.2.\n"));
258 case PPD_LINE_TOO_LONG
:
259 _cupsLangPuts(stdout
,
260 _(" REF: Page 15, section 3.1.\n"));
262 case PPD_ILLEGAL_CHARACTER
:
263 _cupsLangPuts(stdout
,
264 _(" REF: Page 15, section 3.1.\n"));
266 case PPD_ILLEGAL_MAIN_KEYWORD
:
267 _cupsLangPuts(stdout
,
268 _(" REF: Pages 16-17, section 3.2.\n"));
270 case PPD_ILLEGAL_OPTION_KEYWORD
:
271 _cupsLangPuts(stdout
,
272 _(" REF: Page 19, section 3.3.\n"));
274 case PPD_ILLEGAL_TRANSLATION
:
275 _cupsLangPuts(stdout
,
276 _(" REF: Page 27, section 3.5.\n"));
282 check_basics(argv
[i
]);
290 * Show the header and then perform basic conformance tests (limited
291 * only by what the CUPS PPD functions actually load...)
298 _cupsLangPuts(stdout
,
299 _("\n DETAILED CONFORMANCE TEST RESULTS\n"));
301 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
&&
303 ppdversion
= (int)(10 * atof(attr
->value
) + 0.5);
308 * Look for default keywords with no matching option...
311 for (i
= 0; i
< ppd
->num_attrs
; i
++)
313 attr
= ppd
->attrs
[i
];
315 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
316 !strcmp(attr
->name
, "DefaultFont") ||
317 !strcmp(attr
->name
, "DefaultImageableArea") ||
318 !strcmp(attr
->name
, "DefaultOutputOrder") ||
319 !strcmp(attr
->name
, "DefaultPaperDimension") ||
320 !strcmp(attr
->name
, "DefaultTransfer"))
323 if (!strncmp(attr
->name
, "Default", 7) &&
324 !ppdFindOption(ppd
, attr
->name
+ 7))
325 _cupsLangPrintf(stdout
,
326 _(" WARN %s has no corresponding "
332 if ((attr
= ppdFindAttr(ppd
, "DefaultImageableArea", NULL
)) == NULL
)
336 if (!errors
&& !verbose
)
337 _cupsLangPuts(stdout
, _(" FAIL\n"));
339 _cupsLangPuts(stdout
,
340 _(" **FAIL** REQUIRED DefaultImageableArea\n"
341 " REF: Page 102, section 5.15.\n"));
346 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
347 strcmp(attr
->value
, "Unknown"))
351 if (!errors
&& !verbose
)
352 _cupsLangPuts(stdout
, _(" FAIL\n"));
354 _cupsLangPrintf(stdout
,
355 _(" **FAIL** BAD DefaultImageableArea %s!\n"
356 " REF: Page 102, section 5.15.\n"),
365 _cupsLangPuts(stdout
, _(" PASS DefaultImageableArea\n"));
368 if ((attr
= ppdFindAttr(ppd
, "DefaultPaperDimension", NULL
)) == NULL
)
372 if (!errors
&& !verbose
)
373 _cupsLangPuts(stdout
, _(" FAIL\n"));
375 _cupsLangPuts(stdout
,
376 _(" **FAIL** REQUIRED DefaultPaperDimension\n"
377 " REF: Page 103, section 5.15.\n"));
382 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
383 strcmp(attr
->value
, "Unknown"))
387 if (!errors
&& !verbose
)
388 _cupsLangPuts(stdout
, _(" FAIL\n"));
390 _cupsLangPrintf(stdout
,
391 _(" **FAIL** BAD DefaultPaperDimension %s!\n"
392 " REF: Page 103, section 5.15.\n"),
398 else if (verbose
> 0)
399 _cupsLangPuts(stdout
, _(" PASS DefaultPaperDimension\n"));
401 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
402 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
405 * Verify that we have a default choice...
408 if (option
->defchoice
[0])
410 if (ppdFindChoice(option
, option
->defchoice
) == NULL
&&
411 strcmp(option
->defchoice
, "Unknown"))
415 if (!errors
&& !verbose
)
416 _cupsLangPuts(stdout
, _(" FAIL\n"));
418 _cupsLangPrintf(stdout
,
419 _(" **FAIL** BAD Default%s %s\n"
420 " REF: Page 40, section 4.5.\n"),
421 option
->keyword
, option
->defchoice
);
426 else if (verbose
> 0)
427 _cupsLangPrintf(stdout
,
428 _(" PASS Default%s\n"),
435 if (!errors
&& !verbose
)
436 _cupsLangPuts(stdout
, _(" FAIL\n"));
438 _cupsLangPrintf(stdout
,
439 _(" **FAIL** REQUIRED Default%s\n"
440 " REF: Page 40, section 4.5.\n"),
448 if (ppdFindAttr(ppd
, "FileVersion", NULL
) != NULL
)
451 _cupsLangPuts(stdout
, _(" PASS FileVersion\n"));
457 if (!errors
&& !verbose
)
458 _cupsLangPuts(stdout
, _(" FAIL\n"));
460 _cupsLangPuts(stdout
,
461 _(" **FAIL** REQUIRED FileVersion\n"
462 " REF: Page 56, section 5.3.\n"));
468 if (ppdFindAttr(ppd
, "FormatVersion", NULL
) != NULL
)
471 _cupsLangPuts(stdout
, _(" PASS FormatVersion\n"));
477 if (!errors
&& !verbose
)
478 _cupsLangPuts(stdout
, _(" FAIL\n"));
480 _cupsLangPuts(stdout
,
481 _(" **FAIL** REQUIRED FormatVersion\n"
482 " REF: Page 56, section 5.3.\n"));
488 if (ppd
->lang_encoding
!= NULL
)
491 _cupsLangPuts(stdout
, _(" PASS LanguageEncoding\n"));
493 else if (ppdversion
> 40)
497 if (!errors
&& !verbose
)
498 _cupsLangPuts(stdout
, _(" FAIL\n"));
500 _cupsLangPuts(stdout
,
501 _(" **FAIL** REQUIRED LanguageEncoding\n"
502 " REF: Pages 56-57, section 5.3.\n"));
508 if (ppd
->lang_version
!= NULL
)
511 _cupsLangPuts(stdout
, _(" PASS LanguageVersion\n"));
517 if (!errors
&& !verbose
)
518 _cupsLangPuts(stdout
, _(" FAIL\n"));
520 _cupsLangPuts(stdout
,
521 _(" **FAIL** REQUIRED LanguageVersion\n"
522 " REF: Pages 57-58, section 5.3.\n"));
528 if (ppd
->manufacturer
!= NULL
)
530 if (!strncasecmp(ppd
->manufacturer
, "Hewlett-Packard", 15) ||
531 !strncasecmp(ppd
->manufacturer
, "Hewlett Packard", 15))
535 if (!errors
&& !verbose
)
536 _cupsLangPuts(stdout
, _(" FAIL\n"));
538 _cupsLangPuts(stdout
,
539 _(" **FAIL** BAD Manufacturer (should be "
541 " REF: Page 211, table D.1.\n"));
546 else if (verbose
> 0)
547 _cupsLangPuts(stdout
, _(" PASS Manufacturer\n"));
549 else if (ppdversion
>= 43)
553 if (!errors
&& !verbose
)
554 _cupsLangPuts(stdout
, _(" FAIL\n"));
556 _cupsLangPuts(stdout
,
557 _(" **FAIL** REQUIRED Manufacturer\n"
558 " REF: Pages 58-59, section 5.3.\n"));
564 if (ppd
->modelname
!= NULL
)
566 for (ptr
= ppd
->modelname
; *ptr
; ptr
++)
567 if (!isalnum(*ptr
& 255) && !strchr(" ./-+", *ptr
))
574 if (!errors
&& !verbose
)
575 _cupsLangPuts(stdout
, _(" FAIL\n"));
577 _cupsLangPrintf(stdout
,
578 _(" **FAIL** BAD ModelName - \"%c\" not "
579 "allowed in string.\n"
580 " REF: Pages 59-60, section 5.3.\n"),
586 else if (verbose
> 0)
587 _cupsLangPuts(stdout
, _(" PASS ModelName\n"));
593 if (!errors
&& !verbose
)
594 _cupsLangPuts(stdout
, _(" FAIL\n"));
596 _cupsLangPuts(stdout
,
597 _(" **FAIL** REQUIRED ModelName\n"
598 " REF: Pages 59-60, section 5.3.\n"));
604 if (ppd
->nickname
!= NULL
)
607 _cupsLangPuts(stdout
, _(" PASS NickName\n"));
613 if (!errors
&& !verbose
)
614 _cupsLangPuts(stdout
, _(" FAIL\n"));
616 _cupsLangPuts(stdout
,
617 _(" **FAIL** REQUIRED NickName\n"
618 " REF: Page 60, section 5.3.\n"));
624 if (ppdFindOption(ppd
, "PageSize") != NULL
)
627 _cupsLangPuts(stdout
, _(" PASS PageSize\n"));
633 if (!errors
&& !verbose
)
634 _cupsLangPuts(stdout
, _(" FAIL\n"));
636 _cupsLangPuts(stdout
,
637 _(" **FAIL** REQUIRED PageSize\n"
638 " REF: Pages 99-100, section 5.14.\n"));
644 if (ppdFindOption(ppd
, "PageRegion") != NULL
)
647 _cupsLangPuts(stdout
, _(" PASS PageRegion\n"));
653 if (!errors
&& !verbose
)
654 _cupsLangPuts(stdout
, _(" FAIL\n"));
656 _cupsLangPuts(stdout
,
657 _(" **FAIL** REQUIRED PageRegion\n"
658 " REF: Page 100, section 5.14.\n"));
664 if (ppd
->pcfilename
!= NULL
)
667 _cupsLangPuts(stdout
, _(" PASS PCFileName\n"));
673 if (!errors
&& !verbose
)
674 _cupsLangPuts(stdout
, _(" FAIL\n"));
676 _cupsLangPuts(stdout
,
677 _(" **FAIL** REQUIRED PCFileName\n"
678 " REF: Pages 61-62, section 5.3.\n"));
684 if (ppd
->product
!= NULL
)
686 if (ppd
->product
[0] != '(' ||
687 ppd
->product
[strlen(ppd
->product
) - 1] != ')')
691 if (!errors
&& !verbose
)
692 _cupsLangPuts(stdout
, _(" FAIL\n"));
694 _cupsLangPuts(stdout
,
695 _(" **FAIL** BAD Product - not \"(string)\".\n"
696 " REF: Page 62, section 5.3.\n"));
701 else if (verbose
> 0)
702 _cupsLangPuts(stdout
, _(" PASS Product\n"));
708 if (!errors
&& !verbose
)
709 _cupsLangPuts(stdout
, _(" FAIL\n"));
711 _cupsLangPuts(stdout
,
712 _(" **FAIL** REQUIRED Product\n"
713 " REF: Page 62, section 5.3.\n"));
719 if ((attr
= ppdFindAttr(ppd
, "PSVersion", NULL
)) != NULL
&&
722 char junkstr
[255]; /* Temp string */
723 int junkint
; /* Temp integer */
726 if (sscanf(attr
->value
, "(%[^)])%d", junkstr
, &junkint
) != 2)
730 if (!errors
&& !verbose
)
731 _cupsLangPuts(stdout
, _(" FAIL\n"));
733 _cupsLangPuts(stdout
,
734 _(" **FAIL** BAD PSVersion - not \"(string) "
736 " REF: Pages 62-64, section 5.3.\n"));
741 else if (verbose
> 0)
742 _cupsLangPuts(stdout
, _(" PASS PSVersion\n"));
748 if (!errors
&& !verbose
)
749 _cupsLangPuts(stdout
, _(" FAIL\n"));
751 _cupsLangPuts(stdout
,
752 _(" **FAIL** REQUIRED PSVersion\n"
753 " REF: Pages 62-64, section 5.3.\n"));
759 if (ppd
->shortnickname
!= NULL
)
761 if (strlen(ppd
->shortnickname
) > 31)
765 if (!errors
&& !verbose
)
766 _cupsLangPuts(stdout
, _(" FAIL\n"));
768 _cupsLangPuts(stdout
,
769 _(" **FAIL** BAD ShortNickName - longer "
771 " REF: Pages 64-65, section 5.3.\n"));
776 else if (verbose
> 0)
777 _cupsLangPuts(stdout
, _(" PASS ShortNickName\n"));
779 else if (ppdversion
>= 43)
783 if (!errors
&& !verbose
)
784 _cupsLangPuts(stdout
, _(" FAIL\n"));
786 _cupsLangPuts(stdout
,
787 _(" **FAIL** REQUIRED ShortNickName\n"
788 " REF: Page 64-65, section 5.3.\n"));
794 if (ppd
->patches
!= NULL
&& strchr(ppd
->patches
, '\"') &&
795 strstr(ppd
->patches
, "*End"))
799 if (!errors
&& !verbose
)
800 _cupsLangPuts(stdout
, _(" FAIL\n"));
802 _cupsLangPuts(stdout
,
803 _(" **FAIL** BAD JobPatchFile attribute in file\n"
804 " REF: Page 24, section 3.4.\n"));
811 * Check for page sizes without the corresponding ImageableArea or
812 * PaperDimension values...
815 if (ppd
->num_sizes
== 0)
819 if (!errors
&& !verbose
)
820 _cupsLangPuts(stdout
, _(" FAIL\n"));
822 _cupsLangPuts(stdout
,
823 _(" **FAIL** REQUIRED PageSize\n"
824 " REF: Page 41, section 5.\n"
825 " REF: Page 99, section 5.14.\n"));
832 for (j
= 0, size
= ppd
->sizes
; j
< ppd
->num_sizes
; j
++, size
++)
835 * Don't check custom size...
838 if (!strcmp(size
->name
, "Custom"))
842 * Check for ImageableArea...
845 if (size
->left
== 0.0 && size
->bottom
== 0.0 &&
846 size
->right
== 0.0 && size
->top
== 0.0)
850 if (!errors
&& !verbose
)
851 _cupsLangPuts(stdout
, _(" FAIL\n"));
853 _cupsLangPrintf(stdout
,
854 _(" **FAIL** REQUIRED ImageableArea for "
856 " REF: Page 41, section 5.\n"
857 " REF: Page 102, section 5.15.\n"),
865 * Check for PaperDimension...
868 if (size
->width
== 0.0 && size
->length
== 0.0)
872 if (!errors
&& !verbose
)
873 _cupsLangPuts(stdout
, _(" FAIL\n"));
875 _cupsLangPrintf(stdout
,
876 _(" **FAIL** REQUIRED PaperDimension "
878 " REF: Page 41, section 5.\n"
879 " REF: Page 103, section 5.15.\n"),
889 * Check for valid Resolution, JCLResolution, or SetResolution values...
892 if ((option
= ppdFindOption(ppd
, "Resolution")) == NULL
)
893 if ((option
= ppdFindOption(ppd
, "JCLResolution")) == NULL
)
894 option
= ppdFindOption(ppd
, "SetResolution");
898 for (j
= option
->num_choices
, choice
= option
->choices
; j
> 0; j
--, choice
++)
901 * Verify that all resolution options are of the form NNNdpi
905 xdpi
= strtol(choice
->choice
, (char **)&ptr
, 10);
906 if (ptr
> choice
->choice
&& xdpi
> 0)
909 ydpi
= strtol(ptr
+ 1, (char **)&ptr
, 10);
916 if (xdpi
<= 0 || ydpi
<= 0 || strcmp(ptr
, "dpi"))
920 if (!errors
&& !verbose
)
921 _cupsLangPuts(stdout
, _(" FAIL\n"));
923 _cupsLangPrintf(stdout
,
924 _(" **FAIL** Bad %s choice %s!\n"
925 " REF: Page 84, section 5.9\n"),
926 option
->keyword
, choice
->choice
);
935 * Check for a duplex option, and for standard values...
938 if ((option
= ppdFindOption(ppd
, "Duplex")) == NULL
)
939 if ((option
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
940 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
941 option
= ppdFindOption(ppd
, "KD03Duplex");
945 if (ppdFindChoice(option
, "None") == NULL
)
949 if (!errors
&& !verbose
)
950 _cupsLangPuts(stdout
, _(" FAIL\n"));
952 _cupsLangPrintf(stdout
,
953 _(" **FAIL** REQUIRED %s does not define "
955 " REF: Page 122, section 5.17\n"),
962 for (j
= option
->num_choices
, choice
= option
->choices
; j
> 0; j
--, choice
++)
963 if (strcmp(choice
->choice
, "None") &&
964 strcmp(choice
->choice
, "DuplexNoTumble") &&
965 strcmp(choice
->choice
, "DuplexTumble") &&
966 strcmp(choice
->choice
, "SimplexTumble"))
970 if (!errors
&& !verbose
)
971 _cupsLangPuts(stdout
, _(" FAIL\n"));
973 _cupsLangPrintf(stdout
,
974 _(" **FAIL** Bad %s choice %s!\n"
975 " REF: Page 122, section 5.17\n"),
976 option
->keyword
, choice
->choice
);
984 status
= ERROR_CONFORMANCE
;
986 _cupsLangPuts(stdout
, _(" PASS\n"));
990 check_basics(argv
[i
]);
993 strcmp(option
->keyword
, "Duplex") &&
994 strcmp(option
->keyword
, "JCLDuplex"))
996 _cupsLangPrintf(stdout
,
997 _(" WARN Duplex option keyword %s "
998 "should be named Duplex or JCLDuplex!\n"
999 " REF: Page 122, section 5.17\n"),
1003 ppdMarkDefaults(ppd
);
1004 if (ppdConflicts(ppd
))
1006 _cupsLangPuts(stdout
,
1007 _(" WARN Default choices conflicting!\n"));
1009 show_conflicts(ppd
);
1012 if (ppdversion
< 43)
1014 _cupsLangPrintf(stdout
,
1015 _(" WARN Obsolete PPD version %.1f!\n"
1016 " REF: Page 42, section 5.2.\n"),
1020 if (!ppd
->lang_encoding
&& ppdversion
< 41)
1022 _cupsLangPuts(stdout
,
1023 _(" WARN LanguageEncoding required by PPD "
1025 " REF: Pages 56-57, section 5.3.\n"));
1028 if (!ppd
->manufacturer
&& ppdversion
< 43)
1030 _cupsLangPuts(stdout
,
1031 _(" WARN Manufacturer required by PPD "
1033 " REF: Pages 58-59, section 5.3.\n"));
1037 * Treat a PCFileName attribute longer than 12 characters as
1038 * a warning and not a hard error...
1041 if (ppd
->pcfilename
&& strlen(ppd
->pcfilename
) > 12)
1043 _cupsLangPuts(stdout
,
1044 _(" WARN PCFileName longer than 8.3 in "
1045 "violation of PPD spec.\n"
1046 " REF: Pages 61-62, section 5.3.\n"));
1049 if (!ppd
->shortnickname
&& ppdversion
< 43)
1051 _cupsLangPuts(stdout
,
1052 _(" WARN ShortNickName required by PPD "
1054 " REF: Pages 64-65, section 5.3.\n"));
1058 * Check the Protocols line and flag PJL + BCP since TBCP is
1059 * usually used with PJL...
1064 if (strstr(ppd
->protocols
, "PJL") &&
1065 strstr(ppd
->protocols
, "BCP") &&
1066 !strstr(ppd
->protocols
, "TBCP"))
1068 _cupsLangPuts(stdout
,
1069 _(" WARN Protocols contains both PJL "
1070 "and BCP; expected TBCP.\n"
1071 " REF: Pages 78-79, section 5.7.\n"));
1074 if (strstr(ppd
->protocols
, "PJL") &&
1075 (!ppd
->jcl_begin
|| !ppd
->jcl_end
|| !ppd
->jcl_ps
))
1077 _cupsLangPuts(stdout
,
1078 _(" WARN Protocols contains PJL but JCL "
1079 "attributes are not set.\n"
1080 " REF: Pages 78-79, section 5.7.\n"));
1085 * Check for options with a common prefix, e.g. Duplex and Duplexer,
1086 * which are errors according to the spec but won't cause problems
1087 * with CUPS specifically...
1090 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1091 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1093 len
= strlen(option
->keyword
);
1095 for (m
= 0, group2
= ppd
->groups
;
1096 m
< ppd
->num_groups
;
1098 for (n
= 0, option2
= group2
->options
;
1099 n
< group2
->num_options
;
1101 if (option
!= option2
&&
1102 len
< strlen(option2
->keyword
) &&
1103 !strncmp(option
->keyword
, option2
->keyword
, len
))
1105 _cupsLangPrintf(stdout
,
1106 _(" WARN %s shares a common "
1108 " REF: Page 15, section "
1110 option
->keyword
, option2
->keyword
);
1118 _cupsLangPrintf(stdout
, _(" %d ERROR%s FOUND\n"),
1119 errors
, errors
== 1 ? "" : "S");
1121 _cupsLangPuts(stdout
, _(" NO ERRORS FOUND\n"));
1125 * Then list the options, if "-v" was provided...
1130 _cupsLangPrintf(stdout
,
1132 " language_level = %d\n"
1133 " color_device = %s\n"
1134 " variable_sizes = %s\n"
1135 " landscape = %d\n",
1136 ppd
->language_level
,
1137 ppd
->color_device
? "TRUE" : "FALSE",
1138 ppd
->variable_sizes
? "TRUE" : "FALSE",
1141 switch (ppd
->colorspace
)
1144 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMYK\n");
1147 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMY\n");
1150 _cupsLangPuts(stdout
, " colorspace = PPD_CS_GRAY\n");
1153 _cupsLangPuts(stdout
, " colorspace = PPD_CS_RGB\n");
1156 _cupsLangPuts(stdout
, " colorspace = <unknown>\n");
1160 _cupsLangPrintf(stdout
, " num_emulations = %d\n",
1161 ppd
->num_emulations
);
1162 for (j
= 0; j
< ppd
->num_emulations
; j
++)
1163 _cupsLangPrintf(stdout
, " emulations[%d] = %s\n",
1164 j
, ppd
->emulations
[j
].name
);
1166 _cupsLangPrintf(stdout
, " lang_encoding = %s\n",
1167 ppd
->lang_encoding
);
1168 _cupsLangPrintf(stdout
, " lang_version = %s\n",
1170 _cupsLangPrintf(stdout
, " modelname = %s\n", ppd
->modelname
);
1171 _cupsLangPrintf(stdout
, " ttrasterizer = %s\n",
1172 ppd
->ttrasterizer
== NULL
? "None" : ppd
->ttrasterizer
);
1173 _cupsLangPrintf(stdout
, " manufacturer = %s\n",
1175 _cupsLangPrintf(stdout
, " product = %s\n", ppd
->product
);
1176 _cupsLangPrintf(stdout
, " nickname = %s\n", ppd
->nickname
);
1177 _cupsLangPrintf(stdout
, " shortnickname = %s\n",
1178 ppd
->shortnickname
);
1179 _cupsLangPrintf(stdout
, " patches = %d bytes\n",
1180 ppd
->patches
== NULL
? 0 : (int)strlen(ppd
->patches
));
1182 _cupsLangPrintf(stdout
, " num_groups = %d\n", ppd
->num_groups
);
1183 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1185 _cupsLangPrintf(stdout
, " group[%d] = %s\n",
1188 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1190 _cupsLangPrintf(stdout
,
1191 " options[%d] = %s (%s) %s %s %.0f "
1193 k
, option
->keyword
, option
->text
, uis
[option
->ui
],
1194 sections
[option
->section
], option
->order
,
1195 option
->num_choices
);
1197 if (!strcmp(option
->keyword
, "PageSize") ||
1198 !strcmp(option
->keyword
, "PageRegion"))
1200 for (m
= option
->num_choices
, choice
= option
->choices
;
1204 size
= ppdPageSize(ppd
, choice
->choice
);
1207 _cupsLangPrintf(stdout
,
1209 choice
->choice
, choice
->text
);
1211 _cupsLangPrintf(stdout
,
1212 " %s (%s) = %.2fx%.2fin "
1213 "(%.1f,%.1f,%.1f,%.1f)",
1214 choice
->choice
, choice
->text
,
1215 size
->width
/ 72.0, size
->length
/ 72.0,
1216 size
->left
/ 72.0, size
->bottom
/ 72.0,
1217 size
->right
/ 72.0, size
->top
/ 72.0);
1219 if (!strcmp(option
->defchoice
, choice
->choice
))
1220 _cupsLangPuts(stdout
, " *\n");
1222 _cupsLangPuts(stdout
, "\n");
1227 for (m
= option
->num_choices
, choice
= option
->choices
;
1231 _cupsLangPrintf(stdout
, " %s (%s)",
1232 choice
->choice
, choice
->text
);
1234 if (!strcmp(option
->defchoice
, choice
->choice
))
1235 _cupsLangPuts(stdout
, " *\n");
1237 _cupsLangPuts(stdout
, "\n");
1243 _cupsLangPrintf(stdout
, " num_profiles = %d\n",
1245 for (j
= 0; j
< ppd
->num_profiles
; j
++)
1246 _cupsLangPrintf(stdout
,
1247 " profiles[%d] = %s/%s %.3f %.3f "
1248 "[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
1249 j
, ppd
->profiles
[j
].resolution
,
1250 ppd
->profiles
[j
].media_type
,
1251 ppd
->profiles
[j
].gamma
, ppd
->profiles
[j
].density
,
1252 ppd
->profiles
[j
].matrix
[0][0],
1253 ppd
->profiles
[j
].matrix
[0][1],
1254 ppd
->profiles
[j
].matrix
[0][2],
1255 ppd
->profiles
[j
].matrix
[1][0],
1256 ppd
->profiles
[j
].matrix
[1][1],
1257 ppd
->profiles
[j
].matrix
[1][2],
1258 ppd
->profiles
[j
].matrix
[2][0],
1259 ppd
->profiles
[j
].matrix
[2][1],
1260 ppd
->profiles
[j
].matrix
[2][2]);
1262 _cupsLangPrintf(stdout
, " num_fonts = %d\n", ppd
->num_fonts
);
1263 for (j
= 0; j
< ppd
->num_fonts
; j
++)
1264 _cupsLangPrintf(stdout
, " fonts[%d] = %s\n",
1267 _cupsLangPrintf(stdout
, " num_attrs = %d\n", ppd
->num_attrs
);
1268 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1269 _cupsLangPrintf(stdout
,
1270 " attrs[%d] = %s %s%s%s: \"%s\"\n", j
,
1271 ppd
->attrs
[j
]->name
, ppd
->attrs
[j
]->spec
,
1272 ppd
->attrs
[j
]->text
[0] ? "/" : "",
1273 ppd
->attrs
[j
]->text
,
1274 ppd
->attrs
[j
]->value
?
1275 ppd
->attrs
[j
]->value
: "(null)");
1289 * 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1293 check_basics(const char *filename
) /* I - PPD file to check */
1295 cups_file_t
*fp
; /* File pointer */
1296 int ch
; /* Current character */
1297 int col
, /* Current column */
1298 whitespace
; /* Only seen whitespace? */
1299 int eol
; /* Line endings */
1300 int linenum
; /* Line number */
1301 int mixed
; /* Mixed line endings? */
1304 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
1313 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
1315 if (ch
== '\r' || ch
== '\n')
1319 if (eol
== EOL_NONE
)
1321 else if (eol
!= EOL_LF
)
1324 else if (ch
== '\r')
1326 if (cupsFilePeekChar(fp
) == '\n')
1328 cupsFileGetChar(fp
);
1330 if (eol
== EOL_NONE
)
1335 else if (eol
== EOL_NONE
)
1341 if (col
> 0 && whitespace
)
1342 _cupsLangPrintf(stdout
,
1343 _(" WARN Line %d only contains whitespace!\n"),
1352 if (ch
!= ' ' && ch
!= '\t')
1360 _cupsLangPuts(stdout
,
1361 _(" WARN File contains a mix of CR, LF, and "
1362 "CR LF line endings!\n"));
1364 if (eol
== EOL_CRLF
)
1365 _cupsLangPuts(stdout
,
1366 _(" WARN Non-Windows PPD files should use lines "
1367 "ending with only LF, not CR LF!\n"));
1374 * 'show_conflicts()' - Show option conflicts in a PPD file.
1378 show_conflicts(ppd_file_t
*ppd
) /* I - PPD to check */
1380 int i
, j
; /* Looping variables */
1381 ppd_const_t
*c
; /* Current constraint */
1382 ppd_option_t
*o1
, *o2
; /* Options */
1383 ppd_choice_t
*c1
, *c2
; /* Choices */
1387 * Loop through all of the UI constraints and report any options
1391 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
1394 * Grab pointers to the first option...
1397 o1
= ppdFindOption(ppd
, c
->option1
);
1401 else if (c
->choice1
[0] != '\0')
1404 * This constraint maps to a specific choice.
1407 c1
= ppdFindChoice(o1
, c
->choice1
);
1412 * This constraint applies to any choice for this option.
1415 for (j
= o1
->num_choices
, c1
= o1
->choices
; j
> 0; j
--, c1
++)
1420 !strcasecmp(c1
->choice
, "None") ||
1421 !strcasecmp(c1
->choice
, "Off") ||
1422 !strcasecmp(c1
->choice
, "False"))
1427 * Grab pointers to the second option...
1430 o2
= ppdFindOption(ppd
, c
->option2
);
1434 else if (c
->choice2
[0] != '\0')
1437 * This constraint maps to a specific choice.
1440 c2
= ppdFindChoice(o2
, c
->choice2
);
1445 * This constraint applies to any choice for this option.
1448 for (j
= o2
->num_choices
, c2
= o2
->choices
; j
> 0; j
--, c2
++)
1453 !strcasecmp(c2
->choice
, "None") ||
1454 !strcasecmp(c2
->choice
, "Off") ||
1455 !strcasecmp(c2
->choice
, "False"))
1460 * If both options are marked then there is a conflict...
1463 if (c1
!= NULL
&& c1
->marked
&& c2
!= NULL
&& c2
->marked
)
1464 _cupsLangPrintf(stdout
,
1465 _(" WARN \"%s %s\" conflicts with \"%s %s\"\n"
1466 " (constraint=\"%s %s %s %s\")\n"),
1467 o1
->keyword
, c1
->choice
, o2
->keyword
, c2
->choice
,
1468 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1474 * 'usage()' - Show program usage...
1480 _cupsLangPuts(stdout
,
1481 _("Usage: cupstestppd [-q] [-r] [-v[v]] filename1.ppd[.gz] "
1482 "[... filenameN.ppd[.gz]]\n"
1483 " program | cupstestppd [-q] [-r] [-v[v]] -\n"));
1490 * End of "$Id: cupstestppd.c 4990 2006-01-26 02:21:45Z mike $".