Revert manifest to default one
[external/cups.git] / cups / testppd.c
1 /*
2  * "$Id: testppd.c 9793 2011-05-20 03:49:49Z mike $"
3  *
4  *   PPD test program for CUPS.
5  *
6  *   Copyright 2007-2011 by Apple Inc.
7  *   Copyright 1997-2006 by Easy Software Products.
8  *
9  *   These coded instructions, statements, and computer programs are the
10  *   property of Apple Inc. and are protected by Federal copyright
11  *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
12  *   which should have been included with this file.  If this file is
13  *   file is missing or damaged, see the license at "http://www.cups.org/".
14  *
15  *   This file is subject to the Apple OS-Developed Software exception.
16  *
17  * Contents:
18  *
19  *   main() - Main entry.
20  */
21
22 /*
23  * Include necessary headers...
24  */
25
26 #include "cups-private.h"
27 #include <sys/stat.h>
28 #ifdef WIN32
29 #  include <io.h>
30 #else
31 #  include <unistd.h>
32 #  include <fcntl.h>
33 #endif /* WIN32 */
34
35
36 /*
37  * Test data...
38  */
39
40 static const char       *default_code =
41                         "[{\n"
42                         "%%BeginFeature: *InstalledDuplexer False\n"
43                         "%%EndFeature\n"
44                         "} stopped cleartomark\n"
45                         "[{\n"
46                         "%%BeginFeature: *PageRegion Letter\n"
47                         "PageRegion=Letter\n"
48                         "%%EndFeature\n"
49                         "} stopped cleartomark\n"
50                         "[{\n"
51                         "%%BeginFeature: *InputSlot Tray\n"
52                         "InputSlot=Tray\n"
53                         "%%EndFeature\n"
54                         "} stopped cleartomark\n"
55                         "[{\n"
56                         "%%BeginFeature: *MediaType Plain\n"
57                         "MediaType=Plain\n"
58                         "%%EndFeature\n"
59                         "} stopped cleartomark\n"
60                         "[{\n"
61                         "%%BeginFeature: *IntOption None\n"
62                         "%%EndFeature\n"
63                         "} stopped cleartomark\n"
64                         "[{\n"
65                         "%%BeginFeature: *StringOption None\n"
66                         "%%EndFeature\n"
67                         "} stopped cleartomark\n";
68
69 static const char       *custom_code =
70                         "[{\n"
71                         "%%BeginFeature: *InstalledDuplexer False\n"
72                         "%%EndFeature\n"
73                         "} stopped cleartomark\n"
74                         "[{\n"
75                         "%%BeginFeature: *InputSlot Tray\n"
76                         "InputSlot=Tray\n"
77                         "%%EndFeature\n"
78                         "} stopped cleartomark\n"
79                         "[{\n"
80                         "%%BeginFeature: *MediaType Plain\n"
81                         "MediaType=Plain\n"
82                         "%%EndFeature\n"
83                         "} stopped cleartomark\n"
84                         "[{\n"
85                         "%%BeginFeature: *IntOption None\n"
86                         "%%EndFeature\n"
87                         "} stopped cleartomark\n"
88                         "[{\n"
89                         "%%BeginFeature: *CustomStringOption True\n"
90                         "(value\\0502\\051)\n"
91                         "(value 1)\n"
92                         "StringOption=Custom\n"
93                         "%%EndFeature\n"
94                         "} stopped cleartomark\n"
95                         "[{\n"
96                         "%%BeginFeature: *CustomPageSize True\n"
97                         "400\n"
98                         "500\n"
99                         "0\n"
100                         "0\n"
101                         "0\n"
102                         "PageSize=Custom\n"
103                         "%%EndFeature\n"
104                         "} stopped cleartomark\n";
105
106 static const char       *default2_code =
107                         "[{\n"
108                         "%%BeginFeature: *InstalledDuplexer False\n"
109                         "%%EndFeature\n"
110                         "} stopped cleartomark\n"
111                         "[{\n"
112                         "%%BeginFeature: *InputSlot Tray\n"
113                         "InputSlot=Tray\n"
114                         "%%EndFeature\n"
115                         "} stopped cleartomark\n"
116                         "[{\n"
117                         "%%BeginFeature: *Quality Normal\n"
118                         "Quality=Normal\n"
119                         "%%EndFeature\n"
120                         "} stopped cleartomark\n"
121                         "[{\n"
122                         "%%BeginFeature: *IntOption None\n"
123                         "%%EndFeature\n"
124                         "} stopped cleartomark\n"
125                         "[{\n"
126                         "%%BeginFeature: *StringOption None\n"
127                         "%%EndFeature\n"
128                         "} stopped cleartomark\n";
129
130
131 /*
132  * 'main()' - Main entry.
133  */
134
135 int                                     /* O - Exit status */
136 main(int  argc,                         /* I - Number of command-line arguments */
137      char *argv[])                      /* I - Command-line arguments */
138 {
139   int           i;                      /* Looping var */
140   ppd_file_t    *ppd;                   /* PPD file loaded from disk */
141   int           status;                 /* Status of tests (0 = success, 1 = fail) */
142   int           conflicts;              /* Number of conflicts */
143   char          *s;                     /* String */
144   char          buffer[8192];           /* String buffer */
145   const char    *text,                  /* Localized text */
146                 *val;                   /* Option value */
147   int           num_options;            /* Number of options */
148   cups_option_t *options;               /* Options */
149   ppd_size_t    minsize,                /* Minimum size */
150                 maxsize,                /* Maximum size */
151                 *size;                  /* Current size */
152   ppd_attr_t    *attr;                  /* Current attribute */
153
154
155   status = 0;
156
157   if (argc == 1)
158   {
159    /*
160     * Setup directories for locale stuff...
161     */
162
163     if (access("locale", 0))
164     {
165       mkdir("locale", 0777);
166       mkdir("locale/fr", 0777);
167       symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po");
168       mkdir("locale/zh_TW", 0777);
169       symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po");
170     }
171
172     putenv("LOCALEDIR=locale");
173     putenv("SOFTWARE=CUPS");
174
175    /*
176     * Do tests with test.ppd...
177     */
178
179     fputs("ppdOpenFile(test.ppd): ", stdout);
180
181     if ((ppd = ppdOpenFile("test.ppd")) != NULL)
182       puts("PASS");
183     else
184     {
185       ppd_status_t      err;            /* Last error in file */
186       int               line;           /* Line number in file */
187
188
189       status ++;
190       err = ppdLastError(&line);
191
192       printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
193     }
194
195     fputs("ppdFindAttr(wildcard): ", stdout);
196     if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL)
197     {
198       status ++;
199       puts("FAIL (not found)");
200     }
201     else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
202     {
203       status ++;
204       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
205     }
206     else
207       puts("PASS");
208
209     fputs("ppdFindNextAttr(wildcard): ", stdout);
210     if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL)
211     {
212       status ++;
213       puts("FAIL (not found)");
214     }
215     else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar"))
216     {
217       status ++;
218       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
219     }
220     else
221       puts("PASS");
222
223     fputs("ppdFindAttr(Foo): ", stdout);
224     if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL)
225     {
226       status ++;
227       puts("FAIL (not found)");
228     }
229     else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
230     {
231       status ++;
232       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
233     }
234     else
235       puts("PASS");
236
237     fputs("ppdFindNextAttr(Foo): ", stdout);
238     if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL)
239     {
240       status ++;
241       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
242     }
243     else
244       puts("PASS");
245
246     fputs("ppdMarkDefaults: ", stdout);
247     ppdMarkDefaults(ppd);
248
249     if ((conflicts = ppdConflicts(ppd)) == 0)
250       puts("PASS");
251     else
252     {
253       status ++;
254       printf("FAIL (%d conflicts)\n", conflicts);
255     }
256
257     fputs("ppdEmitString (defaults): ", stdout);
258     if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
259         !strcmp(s, default_code))
260       puts("PASS");
261     else
262     {
263       status ++;
264       printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
265              (int)strlen(default_code));
266
267       if (s)
268         puts(s);
269     }
270
271     if (s)
272       free(s);
273
274     fputs("ppdEmitString (custom size and string): ", stdout);
275     ppdMarkOption(ppd, "PageSize", "Custom.400x500");
276     ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}");
277
278     if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
279         !strcmp(s, custom_code))
280       puts("PASS");
281     else
282     {
283       status ++;
284       printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
285              (int)strlen(custom_code));
286
287       if (s)
288         puts(s);
289     }
290
291     if (s)
292       free(s);
293
294    /*
295     * Test constraints...
296     */
297
298     fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout);
299     ppdMarkOption(ppd, "PageSize", "Letter");
300
301     num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options);
302     if (num_options != 2 ||
303         (val = cupsGetOption("PageRegion", num_options, options)) == NULL ||
304         _cups_strcasecmp(val, "Letter") ||
305         (val = cupsGetOption("PageSize", num_options, options)) == NULL ||
306         _cups_strcasecmp(val, "Letter"))
307     {
308       printf("FAIL (%d options:", num_options);
309       for (i = 0; i < num_options; i ++)
310         printf(" %s=%s", options[i].name, options[i].value);
311       puts(")");
312       status ++;
313     }
314     else
315       puts("PASS");
316
317     fputs("ppdConflicts(): ", stdout);
318     ppdMarkOption(ppd, "InputSlot", "Envelope");
319
320     if ((conflicts = ppdConflicts(ppd)) == 2)
321       puts("PASS (2)");
322     else
323     {
324       printf("FAIL (%d)\n", conflicts);
325       status ++;
326     }
327
328     fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout);
329     num_options = 0;
330     options     = NULL;
331     if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
332                              &options))
333     {
334       puts("FAIL (Unable to resolve)");
335       status ++;
336     }
337     else if (num_options != 2 ||
338              !cupsGetOption("PageSize", num_options, options))
339     {
340       printf("FAIL (%d options:", num_options);
341       for (i = 0; i < num_options; i ++)
342         printf(" %s=%s", options[i].name, options[i].value);
343       puts(")");
344       status ++;
345     }
346     else
347       puts("PASS (Resolved by changing PageSize)");
348
349     cupsFreeOptions(num_options, options);
350
351     fputs("cupsResolveConflicts(No option/choice): ", stdout);
352     num_options = 0;
353     options     = NULL;
354     if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
355         num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") &&
356         !_cups_strcasecmp(options[0].value, "Tray"))
357       puts("PASS (Resolved by changing InputSlot)");
358     else if (num_options > 0)
359     {
360       printf("FAIL (%d options:", num_options);
361       for (i = 0; i < num_options; i ++)
362         printf(" %s=%s", options[i].name, options[i].value);
363       puts(")");
364       status ++;
365     }
366     else
367     {
368       puts("FAIL (Unable to resolve)");
369       status ++;
370     }
371     cupsFreeOptions(num_options, options);
372
373     fputs("ppdInstallableConflict(): ", stdout);
374     if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
375         !ppdInstallableConflict(ppd, "Duplex", "None"))
376       puts("PASS");
377     else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
378     {
379       puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
380       status ++;
381     }
382     else
383     {
384       puts("FAIL (Duplex=None conflicted)");
385       status ++;
386     }
387
388    /*
389     * ppdPageSizeLimits
390     */
391
392     fputs("ppdPageSizeLimits: ", stdout);
393     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
394     {
395       if (minsize.width != 36 || minsize.length != 36 ||
396           maxsize.width != 1080 || maxsize.length != 86400)
397       {
398         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
399                "expected min=36x36, max=1080x86400)\n", minsize.width,
400                minsize.length, maxsize.width, maxsize.length);
401         status ++;
402       }
403       else
404         puts("PASS");
405     }
406     else
407     {
408       puts("FAIL (returned 0)");
409       status ++;
410     }
411
412    /*
413     * cupsMarkOptions with PWG and IPP size names.
414     */
415
416     fputs("cupsMarkOptions(media=iso-a4): ", stdout);
417     num_options = cupsAddOption("media", "iso-a4", 0, &options);
418     cupsMarkOptions(ppd, num_options, options);
419     cupsFreeOptions(num_options, options);
420
421     size = ppdPageSize(ppd, NULL);
422     if (!size || strcmp(size->name, "A4"))
423     {
424       printf("FAIL (%s)\n", size ? size->name : "unknown");
425       status ++;
426     }
427     else
428       puts("PASS");
429
430     fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout);
431     num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options);
432     cupsMarkOptions(ppd, num_options, options);
433     cupsFreeOptions(num_options, options);
434
435     size = ppdPageSize(ppd, NULL);
436     if (!size || strcmp(size->name, "Letter"))
437     {
438       printf("FAIL (%s)\n", size ? size->name : "unknown");
439       status ++;
440     }
441     else
442       puts("PASS");
443
444     fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout);
445     num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0,
446                                 &options);
447     cupsMarkOptions(ppd, num_options, options);
448     cupsFreeOptions(num_options, options);
449
450     size = ppdPageSize(ppd, NULL);
451     if (!size || strcmp(size->name, "Letter.Fullbleed"))
452     {
453       printf("FAIL (%s)\n", size ? size->name : "unknown");
454       status ++;
455     }
456     else
457       puts("PASS");
458
459     fputs("cupsMarkOptions(media=A4): ", stdout);
460     num_options = cupsAddOption("media", "A4", 0, &options);
461     cupsMarkOptions(ppd, num_options, options);
462     cupsFreeOptions(num_options, options);
463
464     size = ppdPageSize(ppd, NULL);
465     if (!size || strcmp(size->name, "A4"))
466     {
467       printf("FAIL (%s)\n", size ? size->name : "unknown");
468       status ++;
469     }
470     else
471       puts("PASS");
472
473    /*
474     * Test localization...
475     */
476
477     fputs("ppdLocalizeIPPReason(text): ", stdout);
478     if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
479         !strcmp(buffer, "Foo Reason"))
480       puts("PASS");
481     else
482     {
483       status ++;
484       printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer);
485     }
486
487     fputs("ppdLocalizeIPPReason(http): ", stdout);
488     if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) &&
489         !strcmp(buffer, "http://foo/bar.html"))
490       puts("PASS");
491     else
492     {
493       status ++;
494       printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer);
495     }
496
497     fputs("ppdLocalizeIPPReason(help): ", stdout);
498     if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) &&
499         !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help"))
500       puts("PASS");
501     else
502     {
503       status ++;
504       printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer);
505     }
506
507     fputs("ppdLocalizeIPPReason(file): ", stdout);
508     if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) &&
509         !strcmp(buffer, "/help/foo/bar.html"))
510       puts("PASS");
511     else
512     {
513       status ++;
514       printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer);
515     }
516
517     putenv("LANG=fr");
518     putenv("LC_ALL=fr");
519     putenv("LC_CTYPE=fr");
520     putenv("LC_MESSAGES=fr");
521
522     fputs("ppdLocalizeIPPReason(fr text): ", stdout);
523     if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
524         !strcmp(buffer, "La Long Foo Reason"))
525       puts("PASS");
526     else
527     {
528       status ++;
529       printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer);
530     }
531
532     putenv("LANG=zh_TW");
533     putenv("LC_ALL=zh_TW");
534     putenv("LC_CTYPE=zh_TW");
535     putenv("LC_MESSAGES=zh_TW");
536
537     fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout);
538     if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
539         !strcmp(buffer, "Number 1 Foo Reason"))
540       puts("PASS");
541     else
542     {
543       status ++;
544       printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer);
545     }
546
547    /*
548     * cupsMarkerName localization...
549     */
550
551     putenv("LANG=en");
552     putenv("LC_ALL=en");
553     putenv("LC_CTYPE=en");
554     putenv("LC_MESSAGES=en");
555
556     fputs("ppdLocalizeMarkerName(bogus): ", stdout);
557
558     if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL)
559     {
560       status ++;
561       printf("FAIL (\"%s\" instead of NULL)\n", text);
562     }
563     else
564       puts("PASS");
565
566     fputs("ppdLocalizeMarkerName(cyan): ", stdout);
567
568     if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
569         !strcmp(text, "Cyan Toner"))
570       puts("PASS");
571     else
572     {
573       status ++;
574       printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n",
575              text ? text : "(null)");
576     }
577
578     putenv("LANG=fr");
579     putenv("LC_ALL=fr");
580     putenv("LC_CTYPE=fr");
581     putenv("LC_MESSAGES=fr");
582
583     fputs("ppdLocalizeMarkerName(fr cyan): ", stdout);
584     if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
585         !strcmp(text, "La Toner Cyan"))
586       puts("PASS");
587     else
588     {
589       status ++;
590       printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n",
591              text ? text : "(null)");
592     }
593
594     putenv("LANG=zh_TW");
595     putenv("LC_ALL=zh_TW");
596     putenv("LC_CTYPE=zh_TW");
597     putenv("LC_MESSAGES=zh_TW");
598
599     fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout);
600     if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
601         !strcmp(text, "Number 1 Cyan Toner"))
602       puts("PASS");
603     else
604     {
605       status ++;
606       printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n",
607              text ? text : "(null)");
608     }
609
610     ppdClose(ppd);
611
612    /*
613     * Test new constraints...
614     */
615
616     fputs("ppdOpenFile(test2.ppd): ", stdout);
617
618     if ((ppd = ppdOpenFile("test2.ppd")) != NULL)
619       puts("PASS");
620     else
621     {
622       ppd_status_t      err;            /* Last error in file */
623       int               line;           /* Line number in file */
624
625
626       status ++;
627       err = ppdLastError(&line);
628
629       printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
630     }
631
632     fputs("ppdMarkDefaults: ", stdout);
633     ppdMarkDefaults(ppd);
634
635     if ((conflicts = ppdConflicts(ppd)) == 0)
636       puts("PASS");
637     else
638     {
639       status ++;
640       printf("FAIL (%d conflicts)\n", conflicts);
641     }
642
643     fputs("ppdEmitString (defaults): ", stdout);
644     if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
645         !strcmp(s, default2_code))
646       puts("PASS");
647     else
648     {
649       status ++;
650       printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
651              (int)strlen(default2_code));
652
653       if (s)
654         puts(s);
655     }
656
657     if (s)
658       free(s);
659
660     fputs("ppdConflicts(): ", stdout);
661     ppdMarkOption(ppd, "PageSize", "Env10");
662     ppdMarkOption(ppd, "InputSlot", "Envelope");
663     ppdMarkOption(ppd, "Quality", "Photo");
664
665     if ((conflicts = ppdConflicts(ppd)) == 1)
666       puts("PASS (1)");
667     else
668     {
669       printf("FAIL (%d)\n", conflicts);
670       status ++;
671     }
672
673     fputs("cupsResolveConflicts(Quality=Photo): ", stdout);
674     num_options = 0;
675     options     = NULL;
676     if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
677                              &options))
678     {
679       printf("FAIL (%d options:", num_options);
680       for (i = 0; i < num_options; i ++)
681         printf(" %s=%s", options[i].name, options[i].value);
682       puts(")");
683       status ++;
684     }
685     else
686       puts("PASS (Unable to resolve)");
687     cupsFreeOptions(num_options, options);
688
689     fputs("cupsResolveConflicts(No option/choice): ", stdout);
690     num_options = 0;
691     options     = NULL;
692     if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
693         num_options == 1 && !_cups_strcasecmp(options->name, "Quality") &&
694         !_cups_strcasecmp(options->value, "Normal"))
695       puts("PASS");
696     else if (num_options > 0)
697     {
698       printf("FAIL (%d options:", num_options);
699       for (i = 0; i < num_options; i ++)
700         printf(" %s=%s", options[i].name, options[i].value);
701       puts(")");
702       status ++;
703     }
704     else
705     {
706       puts("FAIL (Unable to resolve!)");
707       status ++;
708     }
709     cupsFreeOptions(num_options, options);
710
711     fputs("cupsResolveConflicts(loop test): ", stdout);
712     ppdMarkOption(ppd, "PageSize", "A4");
713     ppdMarkOption(ppd, "InputSlot", "Tray");
714     ppdMarkOption(ppd, "Quality", "Photo");
715     num_options = 0;
716     options     = NULL;
717     if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
718       puts("PASS");
719     else if (num_options > 0)
720     {
721       printf("FAIL (%d options:", num_options);
722       for (i = 0; i < num_options; i ++)
723         printf(" %s=%s", options[i].name, options[i].value);
724       puts(")");
725     }
726     else
727       puts("FAIL (No conflicts!)");
728
729     fputs("ppdInstallableConflict(): ", stdout);
730     if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
731         !ppdInstallableConflict(ppd, "Duplex", "None"))
732       puts("PASS");
733     else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
734     {
735       puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
736       status ++;
737     }
738     else
739     {
740       puts("FAIL (Duplex=None conflicted)");
741       status ++;
742     }
743
744    /*
745     * ppdPageSizeLimits
746     */
747
748     ppdMarkDefaults(ppd);
749
750     fputs("ppdPageSizeLimits(default): ", stdout);
751     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
752     {
753       if (minsize.width != 36 || minsize.length != 36 ||
754           maxsize.width != 1080 || maxsize.length != 86400)
755       {
756         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
757                "expected min=36x36, max=1080x86400)\n", minsize.width,
758                minsize.length, maxsize.width, maxsize.length);
759         status ++;
760       }
761       else
762         puts("PASS");
763     }
764     else
765     {
766       puts("FAIL (returned 0)");
767       status ++;
768     }
769
770     ppdMarkOption(ppd, "InputSlot", "Manual");
771
772     fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout);
773     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
774     {
775       if (minsize.width != 100 || minsize.length != 100 ||
776           maxsize.width != 1000 || maxsize.length != 1000)
777       {
778         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
779                "expected min=100x100, max=1000x1000)\n", minsize.width,
780                minsize.length, maxsize.width, maxsize.length);
781         status ++;
782       }
783       else
784         puts("PASS");
785     }
786     else
787     {
788       puts("FAIL (returned 0)");
789       status ++;
790     }
791
792     ppdMarkOption(ppd, "Quality", "Photo");
793
794     fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
795     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
796     {
797       if (minsize.width != 200 || minsize.length != 200 ||
798           maxsize.width != 1000 || maxsize.length != 1000)
799       {
800         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
801                "expected min=200x200, max=1000x1000)\n", minsize.width,
802                minsize.length, maxsize.width, maxsize.length);
803         status ++;
804       }
805       else
806         puts("PASS");
807     }
808     else
809     {
810       puts("FAIL (returned 0)");
811       status ++;
812     }
813
814     ppdMarkOption(ppd, "InputSlot", "Tray");
815
816     fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
817     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
818     {
819       if (minsize.width != 300 || minsize.length != 300 ||
820           maxsize.width != 1080 || maxsize.length != 86400)
821       {
822         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
823                "expected min=300x300, max=1080x86400)\n", minsize.width,
824                minsize.length, maxsize.width, maxsize.length);
825         status ++;
826       }
827       else
828         puts("PASS");
829     }
830     else
831     {
832       puts("FAIL (returned 0)");
833       status ++;
834     }
835   }
836   else
837   {
838     const char  *filename;              /* PPD filename */
839     struct stat fileinfo;               /* File information */
840
841
842     if (!strncmp(argv[1], "-d", 2))
843     {
844       const char *printer;              /* Printer name */
845
846       if (argv[1][2])
847         printer = argv[1] + 2;
848       else if (argv[2])
849         printer = argv[2];
850       else
851       {
852         puts("Usage: ./testppd -d printer");
853         return (1);
854       }
855
856       filename = cupsGetPPD(printer);
857
858       if (!filename)
859       {
860         printf("%s: %s\n", printer, cupsLastErrorString());
861         return (1);
862       }
863     }
864     else
865       filename = argv[1];
866
867     if (lstat(filename, &fileinfo))
868     {
869       printf("%s: %s\n", filename, strerror(errno));
870       return (1);
871     }
872
873     if (S_ISLNK(fileinfo.st_mode))
874     {
875       char      realfile[1024];         /* Real file path */
876       ssize_t   realsize;               /* Size of real file path */
877
878
879       if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
880         strcpy(realfile, "Unknown");
881       else
882         realfile[realsize] = '\0';
883
884       if (stat(realfile, &fileinfo))
885         printf("%s: symlink to \"%s\", %s\n", filename, realfile,
886                strerror(errno));
887       else
888         printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile,
889                (long)fileinfo.st_size);
890     }
891     else
892       printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size);
893
894     if ((ppd = ppdOpenFile(filename)) == NULL)
895     {
896       ppd_status_t      err;            /* Last error in file */
897       int               line;           /* Line number in file */
898
899
900       status ++;
901       err = ppdLastError(&line);
902
903       printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
904     }
905     else
906     {
907       int               j, k;           /* Looping vars */
908       ppd_group_t       *group;         /* Option group */
909       ppd_option_t      *option;        /* Option */
910       ppd_coption_t     *coption;       /* Custom option */
911       ppd_cparam_t      *cparam;        /* Custom parameter */
912       ppd_const_t       *c;             /* UIConstraints */
913       char              lang[255],      /* LANG environment variable */
914                         lc_all[255],    /* LC_ALL environment variable */
915                         lc_ctype[255],  /* LC_CTYPE environment variable */
916                         lc_messages[255];/* LC_MESSAGES environment variable */
917
918
919       if (argc > 2)
920       {
921         snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
922         putenv(lang);
923         snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]);
924         putenv(lc_all);
925         snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]);
926         putenv(lc_ctype);
927         snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]);
928         putenv(lc_messages);
929       }
930
931       ppdLocalize(ppd);
932       ppdMarkDefaults(ppd);
933
934       if (argc > 3)
935       {
936         text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer));
937         printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3],
938                text ? text : "(null)");
939         return (text == NULL);
940       }
941
942       for (i = ppd->num_groups, group = ppd->groups;
943            i > 0;
944            i --, group ++)
945       {
946         printf("%s (%s):\n", group->name, group->text);
947
948         for (j = group->num_options, option = group->options;
949              j > 0;
950              j --, option ++)
951         {
952           printf("    %s (%s):\n", option->keyword, option->text);
953
954           for (k = 0; k < option->num_choices; k ++)
955             printf("        - %s%s (%s)\n",
956                    option->choices[k].marked ? "*" : "",
957                    option->choices[k].choice, option->choices[k].text);
958
959           if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
960           {
961             for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
962                  cparam;
963                  cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
964             {
965               switch (cparam->type)
966               {
967                 case PPD_CUSTOM_CURVE :
968                     printf("              %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
969                            cparam->name, cparam->text,
970                            cparam->minimum.custom_curve,
971                            cparam->maximum.custom_curve);
972                     break;
973
974                 case PPD_CUSTOM_INT :
975                     printf("              %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
976                            cparam->name, cparam->text,
977                            cparam->minimum.custom_int,
978                            cparam->maximum.custom_int);
979                     break;
980
981                 case PPD_CUSTOM_INVCURVE :
982                     printf("              %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
983                            cparam->name, cparam->text,
984                            cparam->minimum.custom_invcurve,
985                            cparam->maximum.custom_invcurve);
986                     break;
987
988                 case PPD_CUSTOM_PASSCODE :
989                     printf("              %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
990                            cparam->name, cparam->text,
991                            cparam->minimum.custom_passcode,
992                            cparam->maximum.custom_passcode);
993                     break;
994
995                 case PPD_CUSTOM_PASSWORD :
996                     printf("              %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
997                            cparam->name, cparam->text,
998                            cparam->minimum.custom_password,
999                            cparam->maximum.custom_password);
1000                     break;
1001
1002                 case PPD_CUSTOM_POINTS :
1003                     printf("              %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
1004                            cparam->name, cparam->text,
1005                            cparam->minimum.custom_points,
1006                            cparam->maximum.custom_points);
1007                     break;
1008
1009                 case PPD_CUSTOM_REAL :
1010                     printf("              %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
1011                            cparam->name, cparam->text,
1012                            cparam->minimum.custom_real,
1013                            cparam->maximum.custom_real);
1014                     break;
1015
1016                 case PPD_CUSTOM_STRING :
1017                     printf("              %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
1018                            cparam->name, cparam->text,
1019                            cparam->minimum.custom_string,
1020                            cparam->maximum.custom_string);
1021                     break;
1022               }
1023             }
1024           }
1025         }
1026       }
1027
1028       puts("\nSizes:");
1029       for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
1030         printf("    %s = %gx%g, [%g %g %g %g]\n", size->name, size->width,
1031                size->length, size->left, size->bottom, size->right, size->top);
1032
1033       puts("\nConstraints:");
1034
1035       for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
1036         printf("    *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
1037                c->option2, c->choice2);
1038       if (ppd->num_consts == 0)
1039         puts("    NO CONSTRAINTS");
1040
1041       puts("\nFilters:");
1042
1043       for (i = 0; i < ppd->num_filters; i ++)
1044         printf("    %s\n", ppd->filters[i]);
1045
1046       if (ppd->num_filters == 0)
1047         puts("    NO FILTERS");
1048
1049       puts("\nAttributes:");
1050
1051       for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
1052            attr;
1053            attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
1054         printf("    *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
1055                attr->text, attr->value ? attr->value : "");
1056     }
1057
1058     if (!strncmp(argv[1], "-d", 2))
1059       unlink(filename);
1060   }
1061
1062 #ifdef __APPLE__
1063   if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
1064   {
1065     char        command[1024];          /* malloc_history command */
1066
1067     snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
1068              getpid());
1069     fflush(stdout);
1070     system(command);
1071   }
1072 #endif /* __APPLE__ */
1073
1074   ppdClose(ppd);
1075
1076   return (status);
1077 }
1078
1079
1080 /*
1081  * End of "$Id: testppd.c 9793 2011-05-20 03:49:49Z mike $".
1082  */