]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/cupstestppd.c
Only use the 1-second IPP timeout on non-blocking HTTP connections (STR #377)
[thirdparty/cups.git] / systemv / cupstestppd.c
CommitLineData
4b0b2cf9 1/*
857d50e5 2 * "$Id: cupstestppd.c,v 1.25 2003/08/01 14:58:41 mike Exp $"
4b0b2cf9 3 *
4 * PPD test program for the Common UNIX Printing System (CUPS).
5 *
997fbfa7 6 * Copyright 1997-2003 by Easy Software Products, all rights reserved.
4b0b2cf9 7 *
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
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * PostScript is a trademark of Adobe Systems, Inc.
25 *
26 * This file is subject to the Apple OS-Developed Software exception.
27 *
28 * Contents:
29 *
31e1c01a 30 * main() - Main entry for test program.
31 * show_conflicts() - Show option conflicts in a PPD file.
32 * usage() - Show program usage...
4b0b2cf9 33 */
34
35/*
36 * Include necessary headers...
37 */
38
39#include <cups/cups.h>
40#include <cups/string.h>
41#include <errno.h>
f249be22 42#include <stdlib.h>
4b0b2cf9 43
44
45/*
46 * Error codes...
47 */
48
49#define ERROR_NONE 0
50#define ERROR_USAGE 1
51#define ERROR_FILE_OPEN 2
52#define ERROR_PPD_FORMAT 3
53#define ERROR_CONFORMANCE 4
54
55
f249be22 56/*
57 * Local functions...
58 */
59
31e1c01a 60void show_conflicts(ppd_file_t *ppd);
f249be22 61void usage(void);
62
63
4b0b2cf9 64/*
65 * 'main()' - Main entry for test program.
66 */
67
68int /* O - Exit status */
69main(int argc, /* I - Number of command-line arguments */
70 char *argv[]) /* I - Command-line arguments */
71{
5c61431a 72 int i, j, k, m, n; /* Looping vars */
73 int len; /* Length of option name */
f249be22 74 char *opt; /* Option character */
75 const char *ptr; /* Pointer into string */
1391e7cb 76 int files; /* Number of files */
4b0b2cf9 77 int verbose; /* Want verbose output? */
78 int status; /* Exit status */
79 int errors; /* Number of conformance errors */
f9d01894 80 int ppdversion; /* PPD spec version in PPD file */
1391e7cb 81 ppd_status_t error; /* Status of ppdOpen*() */
82 int line; /* Line number for error */
4b0b2cf9 83 ppd_file_t *ppd; /* PPD file record */
f0e7bfbd 84 ppd_attr_t *attr; /* PPD attribute */
4b0b2cf9 85 ppd_size_t *size; /* Size record */
86 ppd_group_t *group; /* UI group */
87 ppd_option_t *option; /* Standard UI option */
5c61431a 88 ppd_group_t *group2; /* UI group */
89 ppd_option_t *option2; /* Standard UI option */
4b0b2cf9 90 ppd_choice_t *choice; /* Standard UI option choice */
91 static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
92 static char *sections[] = { "ANY", "DOCUMENT", "EXIT",
93 "JCL", "PAGE", "PROLOG" };
94
95
4b0b2cf9 96 /*
97 * Display PPD files for each file listed on the command-line...
98 */
99
857d50e5 100 ppdSetConformance(PPD_CONFORM_STRICT);
101
4b0b2cf9 102 verbose = 0;
103 ppd = NULL;
1391e7cb 104 files = 0;
4b0b2cf9 105 status = ERROR_NONE;
106
107 for (i = 1; i < argc; i ++)
f249be22 108 if (argv[i][0] == '-' && argv[i][1])
77f83108 109 {
f249be22 110 for (opt = argv[i] + 1; *opt; opt ++)
111 switch (*opt)
112 {
857d50e5 113 case 'q' : /* Quiet mode */
f249be22 114 if (verbose > 0)
115 {
116 fputs("cupstestppd: The -q option is incompatible with the -v option.\n",
117 stderr);
118 return (1);
119 }
77f83108 120
f249be22 121 verbose --;
122 break;
77f83108 123
857d50e5 124 case 'r' : /* Relaxed mode */
125 ppdSetConformance(PPD_CONFORM_RELAXED);
126 break;
127
128 case 'v' : /* Verbose mode */
f249be22 129 if (verbose < 0)
130 {
131 fputs("cupstestppd: The -v option is incompatible with the -q option.\n",
132 stderr);
133 return (1);
134 }
135
136 verbose ++;
137 break;
138
139 default :
140 usage();
141 break;
142 }
4b0b2cf9 143 }
144 else
145 {
146 /*
147 * Open the PPD file...
148 */
149
e7848a5b 150 if (files && verbose >= 0)
5f7c946a 151 putchar('\n');
152
1391e7cb 153 files ++;
154
4b0b2cf9 155 if (argv[i][0] == '-')
156 {
157 /*
158 * Read from stdin...
159 */
160
77f83108 161 if (verbose >= 0)
f249be22 162 printf("(stdin):");
4b0b2cf9 163
164 ppd = ppdOpen(stdin);
165 }
f249be22 166 else if (strlen(argv[i]) > 3 &&
167 !strcmp(argv[i] + strlen(argv[i]) - 3, ".gz"))
168 {
169 /*
170 * Read from a gzipped file...
171 */
172
173 char command[1024]; /* Command string */
174 FILE *gunzip; /* Pipe file */
175
176
177 if (verbose >= 0)
178 printf("%s:", argv[i]);
179
ad10470c 180 snprintf(command, sizeof(command), "gunzip -c \"%s\"", argv[i]);
f249be22 181 gunzip = popen(command, "r");
182 ppd = ppdOpen(gunzip);
183
184 if (gunzip != NULL)
185 pclose(gunzip);
186 }
4b0b2cf9 187 else
188 {
189 /*
190 * Read from a file...
191 */
192
77f83108 193 if (verbose >= 0)
f249be22 194 printf("%s:", argv[i]);
4b0b2cf9 195
196 ppd = ppdOpenFile(argv[i]);
197 }
198
199 if (ppd == NULL)
200 {
1391e7cb 201 error = ppdLastError(&line);
202
8b952de6 203 if (verbose >= 0)
204 printf(" FAIL\n **FAIL** Unable to open PPD file - ");
f69d5f26 205
621b77a6 206 if (error <= PPD_ALLOC_ERROR)
4b0b2cf9 207 {
208 status = ERROR_FILE_OPEN;
77f83108 209
5f7c946a 210 if (verbose >= 0)
f69d5f26 211 puts(strerror(errno));
4b0b2cf9 212 }
213 else
214 {
215 status = ERROR_PPD_FORMAT;
77f83108 216
5f7c946a 217 if (verbose >= 0)
218 {
f69d5f26 219 printf("%s on line %d.\n", ppdErrorString(error), line);
5f7c946a 220
221 switch (error)
222 {
223 case PPD_MISSING_PPDADOBE4 :
8e524f97 224 puts(" REF: Page 42, section 5.2.");
5f7c946a 225 break;
226 case PPD_MISSING_VALUE :
8e524f97 227 puts(" REF: Page 20, section 3.4.");
5f7c946a 228 break;
229 case PPD_BAD_OPEN_GROUP :
230 case PPD_NESTED_OPEN_GROUP :
8e524f97 231 puts(" REF: Pages 45-46, section 5.2.");
5f7c946a 232 break;
233 case PPD_BAD_OPEN_UI :
234 case PPD_NESTED_OPEN_UI :
8e524f97 235 puts(" REF: Pages 42-45, section 5.2.");
5f7c946a 236 break;
237 case PPD_BAD_ORDER_DEPENDENCY :
8e524f97 238 puts(" REF: Pages 48-49, section 5.2.");
5f7c946a 239 break;
240 case PPD_BAD_UI_CONSTRAINTS :
8e524f97 241 puts(" REF: Pages 52-54, section 5.2.");
5f7c946a 242 break;
243 case PPD_MISSING_ASTERISK :
8e524f97 244 puts(" REF: Page 15, section 3.2.");
5f7c946a 245 break;
246 case PPD_LINE_TOO_LONG :
8e524f97 247 puts(" REF: Page 15, section 3.1.");
5f7c946a 248 break;
249 case PPD_ILLEGAL_CHARACTER :
8e524f97 250 puts(" REF: Page 15, section 3.1.");
5f7c946a 251 break;
252 case PPD_ILLEGAL_MAIN_KEYWORD :
8e524f97 253 puts(" REF: Pages 16-17, section 3.2.");
5f7c946a 254 break;
255 case PPD_ILLEGAL_OPTION_KEYWORD :
8e524f97 256 puts(" REF: Page 19, section 3.3.");
5f7c946a 257 break;
258 case PPD_ILLEGAL_TRANSLATION :
8e524f97 259 puts(" REF: Page 27, section 3.5.");
5f7c946a 260 break;
261 default :
262 break;
263 }
264 }
4b0b2cf9 265 }
266
267 continue;
268 }
269
270 /*
271 * Show the header and then perform basic conformance tests (limited
272 * only by what the CUPS PPD functions actually load...)
273 */
274
f9d01894 275 errors = 0;
276 ppdversion = 43;
5f7c946a 277
278 if (verbose > 0)
279 puts("\n DETAILED CONFORMANCE TEST RESULTS");
280
f0e7bfbd 281 if ((attr = ppdFindAttr(ppd, "FormatVersion", NULL)) != NULL &&
282 attr->value)
283 ppdversion = (int)(10 * atof(attr->value) + 0.5);
f9d01894 284
f249be22 285 if (ppdFindAttr(ppd, "DefaultImageableArea", NULL) != NULL)
286 {
287 if (verbose > 0)
288 puts(" PASS DefaultImageableArea");
289 }
290 else
291 {
5f7c946a 292 if (verbose >= 0)
293 {
294 if (!errors && !verbose)
295 puts(" FAIL");
f249be22 296
f249be22 297 puts(" **FAIL** REQUIRED DefaultImageableArea");
5f7c946a 298 puts(" REF: Page 102, section 5.15.");
299 }
300
301 errors ++;
f249be22 302 }
303
304 if (ppdFindAttr(ppd, "DefaultPaperDimension", NULL) != NULL)
305 {
306 if (verbose > 0)
307 puts(" PASS DefaultPaperDimension");
308 }
309 else
310 {
5f7c946a 311 if (verbose >= 0)
312 {
313 if (!errors && !verbose)
314 puts(" FAIL");
f249be22 315
f249be22 316 puts(" **FAIL** REQUIRED DefaultPaperDimension");
5f7c946a 317 puts(" REF: Page 103, section 5.15.");
318 }
319
320 errors ++;
f249be22 321 }
322
4b0b2cf9 323 for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
324 for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
5c61431a 325 {
326 /*
327 * Verify that we have a default choice...
328 */
329
4b0b2cf9 330 if (option->defchoice[0])
331 {
f249be22 332 if (verbose > 0)
77f83108 333 printf(" PASS Default%s\n", option->keyword);
4b0b2cf9 334 }
335 else
336 {
5f7c946a 337 if (verbose >= 0)
338 {
339 if (!errors && !verbose)
340 puts(" FAIL");
77f83108 341
77f83108 342 printf(" **FAIL** REQUIRED Default%s\n", option->keyword);
5f7c946a 343 puts(" REF: Page 40, section 4.5.");
344 }
345
346 errors ++;
4b0b2cf9 347 }
5c61431a 348 }
349
f249be22 350 if (ppdFindAttr(ppd, "FileVersion", NULL) != NULL)
77f83108 351 {
f249be22 352 if (verbose > 0)
353 puts(" PASS FileVersion");
77f83108 354 }
4b0b2cf9 355 else
356 {
5f7c946a 357 if (verbose >= 0)
358 {
359 if (!errors && !verbose)
360 puts(" FAIL");
77f83108 361
f249be22 362 puts(" **FAIL** REQUIRED FileVersion");
5f7c946a 363 puts(" REF: Page 56, section 5.3.");
364 }
365
366 errors ++;
f249be22 367 }
368
369 if (ppdFindAttr(ppd, "FormatVersion", NULL) != NULL)
370 {
371 if (verbose > 0)
372 puts(" PASS FormatVersion");
373 }
374 else
375 {
5f7c946a 376 if (verbose >= 0)
377 {
378 if (!errors && !verbose)
379 puts(" FAIL");
f249be22 380
f249be22 381 puts(" **FAIL** REQUIRED FormatVersion");
5f7c946a 382 puts(" REF: Page 56, section 5.3.");
383 }
384
385 errors ++;
4b0b2cf9 386 }
387
388 if (ppd->lang_encoding != NULL)
77f83108 389 {
f249be22 390 if (verbose > 0)
77f83108 391 puts(" PASS LanguageEncoding");
392 }
5f7c946a 393 else if (ppdversion > 40)
4b0b2cf9 394 {
5f7c946a 395 if (verbose >= 0)
396 {
397 if (!errors && !verbose)
398 puts(" FAIL");
77f83108 399
77f83108 400 puts(" **FAIL** REQUIRED LanguageEncoding");
5f7c946a 401 puts(" REF: Pages 56-57, section 5.3.");
402 }
403
404 errors ++;
4b0b2cf9 405 }
406
407 if (ppd->lang_version != NULL)
77f83108 408 {
f249be22 409 if (verbose > 0)
77f83108 410 puts(" PASS LanguageVersion");
411 }
4b0b2cf9 412 else
413 {
5f7c946a 414 if (verbose >= 0)
415 {
416 if (!errors && !verbose)
417 puts(" FAIL");
77f83108 418
77f83108 419 puts(" **FAIL** REQUIRED LanguageVersion");
5f7c946a 420 puts(" REF: Pages 57-58, section 5.3.");
421 }
422
423 errors ++;
4b0b2cf9 424 }
425
426 if (ppd->manufacturer != NULL)
77f83108 427 {
5acae611 428 if (!strncasecmp(ppd->manufacturer, "Hewlett-Packard", 15) ||
429 !strncasecmp(ppd->manufacturer, "Hewlett Packard", 15))
430 {
431 if (verbose >= 0)
432 {
433 if (!errors && !verbose)
434 puts(" FAIL");
435
436 puts(" **FAIL** BAD Manufacturer (should be \"HP\")");
437 puts(" REF: Page 211, table D.1.");
438 }
439
440 errors ++;
441 }
442 else if (verbose > 0)
77f83108 443 puts(" PASS Manufacturer");
444 }
5f7c946a 445 else if (ppdversion >= 43)
4b0b2cf9 446 {
5f7c946a 447 if (verbose >= 0)
448 {
449 if (!errors && !verbose)
450 puts(" FAIL");
77f83108 451
77f83108 452 puts(" **FAIL** REQUIRED Manufacturer");
5f7c946a 453 puts(" REF: Pages 58-59, section 5.3.");
454 }
455
456 errors ++;
4b0b2cf9 457 }
458
459 if (ppd->modelname != NULL)
77f83108 460 {
f249be22 461 for (ptr = ppd->modelname; *ptr; ptr ++)
462 if (!isalnum(*ptr) && !strchr(" ./-+", *ptr))
463 break;
464
465 if (*ptr)
466 {
5f7c946a 467 if (verbose >= 0)
468 {
469 if (!errors && !verbose)
470 puts(" FAIL");
f249be22 471
5f7c946a 472 printf(" **FAIL** BAD ModelName - \"%c\" not allowed in string.\n",
473 *ptr);
474 puts(" REF: Pages 59-60, section 5.3.");
475 }
476
477 errors ++;
f249be22 478 }
479 else if (verbose > 0)
77f83108 480 puts(" PASS ModelName");
481 }
4b0b2cf9 482 else
483 {
5f7c946a 484 if (verbose >= 0)
485 {
486 if (!errors && !verbose)
487 puts(" FAIL");
77f83108 488
77f83108 489 puts(" **FAIL** REQUIRED ModelName");
5f7c946a 490 puts(" REF: Pages 59-60, section 5.3.");
491 }
492
493 errors ++;
4b0b2cf9 494 }
495
496 if (ppd->nickname != NULL)
77f83108 497 {
f249be22 498 if (verbose > 0)
77f83108 499 puts(" PASS NickName");
500 }
4b0b2cf9 501 else
502 {
5f7c946a 503 if (verbose >= 0)
504 {
505 if (!errors && !verbose)
506 puts(" FAIL");
77f83108 507
77f83108 508 puts(" **FAIL** REQUIRED NickName");
5f7c946a 509 puts(" REF: Page 60, section 5.3.");
510 }
511
512 errors ++;
4b0b2cf9 513 }
514
515 if (ppdFindOption(ppd, "PageSize") != NULL)
77f83108 516 {
f249be22 517 if (verbose > 0)
77f83108 518 puts(" PASS PageSize");
519 }
4b0b2cf9 520 else
521 {
5f7c946a 522 if (verbose >= 0)
523 {
524 if (!errors && !verbose)
525 puts(" FAIL");
77f83108 526
77f83108 527 puts(" **FAIL** REQUIRED PageSize");
5f7c946a 528 puts(" REF: Pages 99-100, section 5.14.");
529 }
530
531 errors ++;
4b0b2cf9 532 }
533
534 if (ppdFindOption(ppd, "PageRegion") != NULL)
77f83108 535 {
f249be22 536 if (verbose > 0)
77f83108 537 puts(" PASS PageRegion");
538 }
4b0b2cf9 539 else
540 {
5f7c946a 541 if (verbose >= 0)
542 {
543 if (!errors && !verbose)
544 puts(" FAIL");
77f83108 545
77f83108 546 puts(" **FAIL** REQUIRED PageRegion");
5f7c946a 547 puts(" REF: Page 100, section 5.14.");
548 }
549
550 errors ++;
4b0b2cf9 551 }
552
23f5e659 553 if (ppd->pcfilename != NULL)
554 {
f249be22 555 if (verbose > 0)
5f7c946a 556 puts(" PASS PCFileName");
23f5e659 557 }
558 else
559 {
5f7c946a 560 if (verbose >= 0)
561 {
562 if (!errors && !verbose)
563 puts(" FAIL");
23f5e659 564
23f5e659 565 puts(" **FAIL** REQUIRED PCFileName");
5f7c946a 566 puts(" REF: Pages 61-62, section 5.3.");
567 }
568
569 errors ++;
23f5e659 570 }
571
4b0b2cf9 572 if (ppd->product != NULL)
77f83108 573 {
f249be22 574 if (ppd->product[0] != '(' ||
575 ppd->product[strlen(ppd->product) - 1] != ')')
576 {
5f7c946a 577 if (verbose >= 0)
578 {
579 if (!errors && !verbose)
580 puts(" FAIL");
581
582 puts(" **FAIL** BAD Product - not \"(string)\".");
583 puts(" REF: Page 62, section 5.3.");
584 }
f249be22 585
5f7c946a 586 errors ++;
f249be22 587 }
588 else if (verbose > 0)
77f83108 589 puts(" PASS Product");
590 }
4b0b2cf9 591 else
592 {
5f7c946a 593 if (verbose >= 0)
594 {
595 if (!errors && !verbose)
596 puts(" FAIL");
77f83108 597
77f83108 598 puts(" **FAIL** REQUIRED Product");
5f7c946a 599 puts(" REF: Page 62, section 5.3.");
600 }
601
602 errors ++;
4b0b2cf9 603 }
604
f0e7bfbd 605 if ((attr = ppdFindAttr(ppd, "PSVersion", NULL)) != NULL &&
606 attr->value != NULL)
f249be22 607 {
608 char junkstr[255]; /* Temp string */
609 int junkint; /* Temp integer */
610
611
f0e7bfbd 612 if (sscanf(attr->value, "(%[^)])%d", junkstr, &junkint) != 2)
f249be22 613 {
5f7c946a 614 if (verbose >= 0)
615 {
616 if (!errors && !verbose)
617 puts(" FAIL");
618
619 puts(" **FAIL** BAD PSVersion - not \"(string) int\".");
620 puts(" REF: Pages 62-64, section 5.3.");
621 }
f249be22 622
5f7c946a 623 errors ++;
f249be22 624 }
625 else if (verbose > 0)
626 puts(" PASS PSVersion");
627 }
628 else
629 {
5f7c946a 630 if (verbose >= 0)
631 {
632 if (!errors && !verbose)
633 puts(" FAIL");
f249be22 634
f249be22 635 puts(" **FAIL** REQUIRED PSVersion");
5f7c946a 636 puts(" REF: Pages 62-64, section 5.3.");
637 }
638
639 errors ++;
f249be22 640 }
641
4b0b2cf9 642 if (ppd->shortnickname != NULL)
77f83108 643 {
f249be22 644 if (strlen(ppd->shortnickname) > 31)
645 {
5f7c946a 646 if (verbose >= 0)
647 {
648 if (!errors && !verbose)
649 puts(" FAIL");
650
651 puts(" **FAIL** BAD ShortNickName - longer than 31 chars.");
652 puts(" REF: Pages 64-65, section 5.3.");
653 }
f249be22 654
5f7c946a 655 errors ++;
f249be22 656 }
657 else if (verbose > 0)
77f83108 658 puts(" PASS ShortNickName");
659 }
5f7c946a 660 else if (ppdversion >= 43)
f9d01894 661 {
5f7c946a 662 if (verbose >= 0)
663 {
664 if (!errors && !verbose)
665 puts(" FAIL");
77f83108 666
77f83108 667 puts(" **FAIL** REQUIRED ShortNickName");
5f7c946a 668 puts(" REF: Page 64-65, section 5.3.");
669 }
670
671 errors ++;
4b0b2cf9 672 }
673
5acae611 674 if (ppd->patches != NULL && strchr(ppd->patches, '\"') &&
675 strstr(ppd->patches, "*End"))
676 {
677 if (verbose >= 0)
678 {
679 if (!errors && !verbose)
680 puts(" FAIL");
681
682 puts(" **FAIL** BAD JobPatchFile attribute in file");
683 puts(" REF: Page 24, section 3.4.");
684 }
685
686 errors ++;
687 }
688
4b0b2cf9 689 if (errors)
5f7c946a 690 status = ERROR_CONFORMANCE;
691 else if (!verbose)
692 puts(" PASS");
693
694 if (verbose >= 0)
4b0b2cf9 695 {
eafe419c 696 ppdMarkDefaults(ppd);
697 if (ppdConflicts(ppd))
31e1c01a 698 {
eafe419c 699 puts(" WARN Default choices conflicting!");
700
31e1c01a 701 show_conflicts(ppd);
702 }
703
5f7c946a 704 if (ppdversion < 43)
705 {
f0e7bfbd 706 printf(" WARN Obsolete PPD version %.1f!\n",
707 0.1f * ppdversion);
5f7c946a 708 puts(" REF: Page 42, section 5.2.");
709 }
77f83108 710
6fab737b 711 if (!ppd->lang_encoding && ppdversion < 41)
5f7c946a 712 {
713 puts(" WARN LanguageEncoding required by PPD 4.3 spec.");
714 puts(" REF: Pages 56-57, section 5.3.");
715 }
716
717 if (!ppd->manufacturer && ppdversion < 43)
718 {
719 puts(" WARN Manufacturer required by PPD 4.3 spec.");
720 puts(" REF: Pages 58-59, section 5.3.");
721 }
722
723 /*
724 * Treat a PCFileName attribute longer than 12 characters as
725 * a warning and not a hard error...
726 */
727
728 if (ppd->pcfilename && strlen(ppd->pcfilename) > 12)
729 {
730 puts(" WARN PCFileName longer than 8.3 in violation of PPD spec.");
731 puts(" REF: Pages 61-62, section 5.3.");
732 }
733
734 if (!ppd->shortnickname && ppdversion < 43)
735 {
736 puts(" WARN ShortNickName required by PPD 4.3 spec.");
737 puts(" REF: Pages 64-65, section 5.3.");
738 }
b8f94d24 739
740 /*
741 * Check for options with a common prefix, e.g. Duplex and Duplexer,
742 * which are errors according to the spec but won't cause problems
743 * with CUPS specifically...
744 */
745
746 for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
747 for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
748 {
749 len = strlen(option->keyword);
750
751 for (m = 0, group2 = ppd->groups;
752 m < ppd->num_groups;
753 m ++, group2 ++)
754 for (n = 0, option2 = group2->options;
755 n < group2->num_options;
756 n ++, option2 ++)
757 if (option != option2 &&
758 len < strlen(option2->keyword) &&
759 !strncmp(option->keyword, option2->keyword, len))
760 {
761 printf(" WARN %s shares a common prefix with %s\n",
762 option->keyword, option2->keyword);
763 puts(" REF: Page 15, section 3.2.");
764 }
765 }
4b0b2cf9 766 }
767
f249be22 768 if (verbose > 0)
5f7c946a 769 {
770 if (errors)
771 printf(" %d ERROR%s FOUND\n", errors, errors == 1 ? "" : "S");
772 else
773 puts(" NO ERRORS FOUND");
774 }
775
4b0b2cf9 776
777 /*
778 * Then list the options, if "-v" was provided...
779 */
780
f249be22 781 if (verbose > 1)
4b0b2cf9 782 {
783 puts("");
4b0b2cf9 784 printf(" language_level = %d\n", ppd->language_level);
785 printf(" color_device = %s\n", ppd->color_device ? "TRUE" : "FALSE");
786 printf(" variable_sizes = %s\n", ppd->variable_sizes ? "TRUE" : "FALSE");
787 printf(" landscape = %d\n", ppd->landscape);
788
789 switch (ppd->colorspace)
790 {
791 case PPD_CS_CMYK :
792 puts(" colorspace = PPD_CS_CMYK");
793 break;
794 case PPD_CS_CMY :
795 puts(" colorspace = PPD_CS_CMY");
796 break;
797 case PPD_CS_GRAY :
798 puts(" colorspace = PPD_CS_GRAY");
799 break;
800 case PPD_CS_RGB :
801 puts(" colorspace = PPD_CS_RGB");
802 break;
803 default :
804 puts(" colorspace = <unknown>");
805 break;
806 }
807
808 printf(" num_emulations = %d\n", ppd->num_emulations);
809 for (j = 0; j < ppd->num_emulations; j ++)
810 printf(" emulations[%d] = %s\n", j, ppd->emulations[j].name);
811
812 printf(" lang_encoding = %s\n", ppd->lang_encoding);
813 printf(" lang_version = %s\n", ppd->lang_version);
814 printf(" modelname = %s\n", ppd->modelname);
815 printf(" ttrasterizer = %s\n",
816 ppd->ttrasterizer == NULL ? "None" : ppd->ttrasterizer);
817 printf(" manufacturer = %s\n", ppd->manufacturer);
818 printf(" product = %s\n", ppd->product);
819 printf(" nickname = %s\n", ppd->nickname);
820 printf(" shortnickname = %s\n", ppd->shortnickname);
821 printf(" patches = %d bytes\n",
822 ppd->patches == NULL ? 0 : (int)strlen(ppd->patches));
823
824 printf(" num_groups = %d\n", ppd->num_groups);
825 for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
826 {
827 printf(" group[%d] = %s\n", j, group->text);
828
829 for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
830 {
831 printf(" options[%d] = %s (%s) %s %s %.0f (%d choices)\n", k,
832 option->keyword, option->text, uis[option->ui],
833 sections[option->section], option->order,
834 option->num_choices);
835
836 if (strcmp(option->keyword, "PageSize") == 0 ||
837 strcmp(option->keyword, "PageRegion") == 0)
838 {
839 for (m = option->num_choices, choice = option->choices;
840 m > 0;
841 m --, choice ++)
842 {
843 size = ppdPageSize(ppd, choice->choice);
844
845 if (size == NULL)
846 printf(" %s (%s) = ERROR", choice->choice, choice->text);
847 else
848 printf(" %s (%s) = %.2fx%.2fin (%.1f,%.1f,%.1f,%.1f)", choice->choice,
849 choice->text, size->width / 72.0, size->length / 72.0,
850 size->left / 72.0, size->bottom / 72.0,
851 size->right / 72.0, size->top / 72.0);
852
853 if (strcmp(option->defchoice, choice->choice) == 0)
854 puts(" *");
855 else
856 putchar('\n');
857 }
858 }
859 else
860 {
861 for (m = option->num_choices, choice = option->choices;
862 m > 0;
863 m --, choice ++)
864 {
865 printf(" %s (%s)", choice->choice, choice->text);
866
867 if (strcmp(option->defchoice, choice->choice) == 0)
868 puts(" *");
869 else
870 putchar('\n');
871 }
872 }
873 }
874 }
875
876 printf(" num_profiles = %d\n", ppd->num_profiles);
877 for (j = 0; j < ppd->num_profiles; j ++)
878 printf(" profiles[%d] = %s/%s %.3f %.3f [ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
879 j, ppd->profiles[j].resolution, ppd->profiles[j].media_type,
880 ppd->profiles[j].gamma, ppd->profiles[j].density,
881 ppd->profiles[j].matrix[0][0], ppd->profiles[j].matrix[0][1],
882 ppd->profiles[j].matrix[0][2], ppd->profiles[j].matrix[1][0],
883 ppd->profiles[j].matrix[1][1], ppd->profiles[j].matrix[1][2],
884 ppd->profiles[j].matrix[2][0], ppd->profiles[j].matrix[2][1],
885 ppd->profiles[j].matrix[2][2]);
886
887 printf(" num_fonts = %d\n", ppd->num_fonts);
888 for (j = 0; j < ppd->num_fonts; j ++)
889 printf(" fonts[%d] = %s\n", j, ppd->fonts[j]);
5f31ff31 890
891 printf(" num_attrs = %d\n", ppd->num_attrs);
892 for (j = 0; j < ppd->num_attrs; j ++)
893 printf(" attrs[%d] = %s %s%s%s: \"%s\"\n", j,
894 ppd->attrs[j]->name, ppd->attrs[j]->spec,
895 ppd->attrs[j]->text[0] ? "/" : "", ppd->attrs[j]->text,
896 ppd->attrs[j]->value ? ppd->attrs[j]->value : "(null)");
4b0b2cf9 897 }
898
899 ppdClose(ppd);
900 }
901
f249be22 902 if (!files)
903 usage();
904
905 return (status);
906}
907
908
31e1c01a 909/*
910 * 'show_conflicts()' - Show option conflicts in a PPD file.
911 */
912
913void
914show_conflicts(ppd_file_t *ppd) /* I - PPD to check */
915{
916 int i, j; /* Looping variables */
917 ppd_const_t *c; /* Current constraint */
918 ppd_option_t *o1, *o2; /* Options */
919 ppd_choice_t *c1, *c2; /* Choices */
920
921
922 /*
923 * Loop through all of the UI constraints and report any options
924 * that conflict...
925 */
926
927 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
928 {
929 /*
930 * Grab pointers to the first option...
931 */
932
933 o1 = ppdFindOption(ppd, c->option1);
934
935 if (o1 == NULL)
936 continue;
937 else if (c->choice1[0] != '\0')
938 {
939 /*
940 * This constraint maps to a specific choice.
941 */
942
943 c1 = ppdFindChoice(o1, c->choice1);
944 }
945 else
946 {
947 /*
948 * This constraint applies to any choice for this option.
949 */
950
951 for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
952 if (c1->marked)
953 break;
954
955 if (j == 0 ||
956 strcasecmp(c1->choice, "None") == 0 ||
957 strcasecmp(c1->choice, "Off") == 0 ||
958 strcasecmp(c1->choice, "False") == 0)
959 c1 = NULL;
960 }
961
962 /*
963 * Grab pointers to the second option...
964 */
965
966 o2 = ppdFindOption(ppd, c->option2);
967
968 if (o2 == NULL)
969 continue;
970 else if (c->choice2[0] != '\0')
971 {
972 /*
973 * This constraint maps to a specific choice.
974 */
975
976 c2 = ppdFindChoice(o2, c->choice2);
977 }
978 else
979 {
980 /*
981 * This constraint applies to any choice for this option.
982 */
983
984 for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
985 if (c2->marked)
986 break;
987
988 if (j == 0 ||
989 strcasecmp(c2->choice, "None") == 0 ||
990 strcasecmp(c2->choice, "Off") == 0 ||
991 strcasecmp(c2->choice, "False") == 0)
992 c2 = NULL;
993 }
994
995 /*
996 * If both options are marked then there is a conflict...
997 */
998
999 if (c1 != NULL && c1->marked && c2 != NULL && c2->marked)
1000 printf(" WARN \"%s %s\" conflicts with \"%s %s\"\n"
1001 " (constraint=\"%s %s %s %s\")\n",
1002 o1->keyword, c1->choice, o2->keyword, c2->choice,
1003 c->option1, c->choice1, c->option2, c->choice2);
1004 }
1005}
1006
1007
f249be22 1008/*
1009 * 'usage()' - Show program usage...
1010 */
1011
1012void
1013usage(void)
1014{
857d50e5 1015 puts("Usage: cupstestppd [-q] [-r] [-v[v]] filename1.ppd[.gz] [... filenameN.ppd[.gz]]");
1016 puts(" program | cupstestppd [-q] [-r] [-v[v]] -");
4b0b2cf9 1017
f249be22 1018 exit(ERROR_USAGE);
4b0b2cf9 1019}
1020
1021
1022/*
857d50e5 1023 * End of "$Id: cupstestppd.c,v 1.25 2003/08/01 14:58:41 mike Exp $".
4b0b2cf9 1024 */