• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * PPD test program for CUPS.
3  *
4  * Copyright © 2020-2024 by OpenPrinting.
5  * Copyright © 2007-2018 by Apple Inc.
6  * Copyright © 1997-2006 by Easy Software Products.
7  *
8  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
9  * information.
10  */
11 
12 /*
13  * Include necessary headers...
14  */
15 
16 #undef _CUPS_NO_DEPRECATED
17 #include "cups-private.h"
18 #include "ppd-private.h"
19 #include "raster-private.h"
20 #include <sys/stat.h>
21 #ifdef _WIN32
22 #  include <io.h>
23 #else
24 #  include <unistd.h>
25 #  include <fcntl.h>
26 #endif /* _WIN32 */
27 #include <math.h>
28 
29 
30 /*
31  * Local functions...
32  */
33 
34 static int	do_ppd_tests(const char *filename, int num_options, cups_option_t *options);
35 static int	do_ps_tests(void);
36 static void	print_changes(cups_page_header2_t *header, cups_page_header2_t *expected);
37 
38 
39 /*
40  * Test data...
41  */
42 
43 static const char *dsc_code =
44 "[{\n"
45 "%%BeginFeature: *PageSize Tabloid\n"
46 "<</PageSize[792 1224]>>setpagedevice\n"
47 "%%EndFeature\n"
48 "} stopped cleartomark\n";
49 static const char *setpagedevice_code =
50 "<<"
51 "/MediaClass(Media Class)"
52 "/MediaColor((Media Color))"
53 "/MediaType(Media\\\\Type)"
54 "/OutputType<416263>"
55 "/AdvanceDistance 1000"
56 "/AdvanceMedia 1"
57 "/Collate false"
58 "/CutMedia 2"
59 "/Duplex true"
60 "/HWResolution[100 200]"
61 "/InsertSheet true"
62 "/Jog 3"
63 "/LeadingEdge 1"
64 "/ManualFeed true"
65 "/MediaPosition 8#777"
66 "/MediaWeight 16#fe01"
67 "/MirrorPrint true"
68 "/NegativePrint true"
69 "/NumCopies 1"
70 "/Orientation 1"
71 "/OutputFaceUp true"
72 "/PageSize[612 792.1]"
73 "/Separations true"
74 "/TraySwitch true"
75 "/Tumble true"
76 "/cupsMediaType 2"
77 "/cupsColorOrder 1"
78 "/cupsColorSpace 1"
79 "/cupsCompression 1"
80 "/cupsRowCount 1"
81 "/cupsRowFeed 1"
82 "/cupsRowStep 1"
83 "/cupsBorderlessScalingFactor 1.001"
84 "/cupsInteger0 1"
85 "/cupsInteger1 2"
86 "/cupsInteger2 3"
87 "/cupsInteger3 4"
88 "/cupsInteger4 5"
89 "/cupsInteger5 6"
90 "/cupsInteger6 7"
91 "/cupsInteger7 8"
92 "/cupsInteger8 9"
93 "/cupsInteger9 10"
94 "/cupsInteger10 11"
95 "/cupsInteger11 12"
96 "/cupsInteger12 13"
97 "/cupsInteger13 14"
98 "/cupsInteger14 15"
99 "/cupsInteger15 16"
100 "/cupsReal0 1.1"
101 "/cupsReal1 2.1"
102 "/cupsReal2 3.1"
103 "/cupsReal3 4.1"
104 "/cupsReal4 5.1"
105 "/cupsReal5 6.1"
106 "/cupsReal6 7.1"
107 "/cupsReal7 8.1"
108 "/cupsReal8 9.1"
109 "/cupsReal9 10.1"
110 "/cupsReal10 11.1"
111 "/cupsReal11 12.1"
112 "/cupsReal12 13.1"
113 "/cupsReal13 14.1"
114 "/cupsReal14 15.1"
115 "/cupsReal15 16.1"
116 "/cupsString0(1)"
117 "/cupsString1(2)"
118 "/cupsString2(3)"
119 "/cupsString3(4)"
120 "/cupsString4(5)"
121 "/cupsString5(6)"
122 "/cupsString6(7)"
123 "/cupsString7(8)"
124 "/cupsString8(9)"
125 "/cupsString9(10)"
126 "/cupsString10(11)"
127 "/cupsString11(12)"
128 "/cupsString12(13)"
129 "/cupsString13(14)"
130 "/cupsString14(15)"
131 "/cupsString15(16)"
132 "/cupsMarkerType(Marker Type)"
133 "/cupsRenderingIntent(Rendering Intent)"
134 "/cupsPageSizeName(Letter)"
135 "/cupsPreferredBitsPerColor 17"
136 ">> setpagedevice";
137 
138 static cups_page_header2_t setpagedevice_header =
139 {
140   "Media Class",			/* MediaClass */
141   "(Media Color)",			/* MediaColor */
142   "Media\\Type",			/* MediaType */
143   "Abc",				/* OutputType */
144   1000,					/* AdvanceDistance */
145   CUPS_ADVANCE_FILE,			/* AdvanceMedia */
146   CUPS_FALSE,				/* Collate */
147   CUPS_CUT_JOB,				/* CutMedia */
148   CUPS_TRUE,				/* Duplex */
149   { 100, 200 },				/* HWResolution */
150   { 0, 0, 0, 0 },			/* ImagingBoundingBox */
151   CUPS_TRUE,				/* InsertSheet */
152   CUPS_JOG_SET,				/* Jog */
153   CUPS_EDGE_RIGHT,			/* LeadingEdge */
154   { 0, 0 },				/* Margins */
155   CUPS_TRUE,				/* ManualFeed */
156   0777,					/* MediaPosition */
157   0xfe01,				/* MediaWeight */
158   CUPS_TRUE,				/* MirrorPrint */
159   CUPS_TRUE,				/* NegativePrint */
160   1,					/* NumCopies */
161   CUPS_ORIENT_90,			/* Orientation */
162   CUPS_TRUE,				/* OutputFaceUp */
163   { 612, 792 },				/* PageSize */
164   CUPS_TRUE,				/* Separations */
165   CUPS_TRUE,				/* TraySwitch */
166   CUPS_TRUE,				/* Tumble */
167   0,					/* cupsWidth */
168   0,					/* cupsHeight */
169   2,					/* cupsMediaType */
170   0,					/* cupsBitsPerColor */
171   0,					/* cupsBitsPerPixel */
172   0,					/* cupsBytesPerLine */
173   CUPS_ORDER_BANDED,			/* cupsColorOrder */
174   CUPS_CSPACE_RGB,			/* cupsColorSpace */
175   1,					/* cupsCompression */
176   1,					/* cupsRowCount */
177   1,					/* cupsRowFeed */
178   1,					/* cupsRowStep */
179   0,					/* cupsNumColors */
180   1.001f,				/* cupsBorderlessScalingFactor */
181   { 612.0f, 792.1f },			/* cupsPageSize */
182   { 0.0f, 0.0f, 0.0f, 0.0f },		/* cupsImagingBBox */
183   { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
184 					/* cupsInteger[16] */
185   { 1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1f, 8.1f, 9.1f, 10.1f, 11.1f, 12.1f, 13.1f, 14.1f, 15.1f, 16.1f },			/* cupsReal[16] */
186   { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
187     "14", "15", "16" },			/* cupsString[16] */
188   "Marker Type",			/* cupsMarkerType */
189   "Rendering Intent",			/* cupsRenderingIntent */
190   "Letter"				/* cupsPageSizeName */
191 };
192 
193 static const char	*default_code =
194 			"[{\n"
195 			"%%BeginFeature: *InstalledDuplexer False\n"
196 			"%%EndFeature\n"
197 			"} stopped cleartomark\n"
198 			"[{\n"
199 			"%%BeginFeature: *PageRegion Letter\n"
200 			"PageRegion=Letter\n"
201 			"%%EndFeature\n"
202 			"} stopped cleartomark\n"
203 			"[{\n"
204 			"%%BeginFeature: *InputSlot Tray\n"
205 			"InputSlot=Tray\n"
206 			"%%EndFeature\n"
207 			"} stopped cleartomark\n"
208 			"[{\n"
209 			"%%BeginFeature: *OutputBin Tray1\n"
210 			"OutputBin=Tray1\n"
211 			"%%EndFeature\n"
212 			"} stopped cleartomark\n"
213 			"[{\n"
214 			"%%BeginFeature: *MediaType Plain\n"
215 			"MediaType=Plain\n"
216 			"%%EndFeature\n"
217 			"} stopped cleartomark\n"
218 			"[{\n"
219 			"%%BeginFeature: *IntOption None\n"
220 			"%%EndFeature\n"
221 			"} stopped cleartomark\n"
222 			"[{\n"
223 			"%%BeginFeature: *StringOption None\n"
224 			"%%EndFeature\n"
225 			"} stopped cleartomark\n";
226 
227 static const char	*custom_code =
228 			"[{\n"
229 			"%%BeginFeature: *InstalledDuplexer False\n"
230 			"%%EndFeature\n"
231 			"} stopped cleartomark\n"
232 			"[{\n"
233 			"%%BeginFeature: *InputSlot Tray\n"
234 			"InputSlot=Tray\n"
235 			"%%EndFeature\n"
236 			"} stopped cleartomark\n"
237 			"[{\n"
238 			"%%BeginFeature: *MediaType Plain\n"
239 			"MediaType=Plain\n"
240 			"%%EndFeature\n"
241 			"} stopped cleartomark\n"
242 			"[{\n"
243 			"%%BeginFeature: *OutputBin Tray1\n"
244 			"OutputBin=Tray1\n"
245 			"%%EndFeature\n"
246 			"} stopped cleartomark\n"
247 			"[{\n"
248 			"%%BeginFeature: *IntOption None\n"
249 			"%%EndFeature\n"
250 			"} stopped cleartomark\n"
251 			"[{\n"
252 			"%%BeginFeature: *CustomStringOption True\n"
253 			"(value\\0502\\051)\n"
254 			"(value 1)\n"
255 			"StringOption=Custom\n"
256 			"%%EndFeature\n"
257 			"} stopped cleartomark\n"
258 			"[{\n"
259 			"%%BeginFeature: *CustomPageSize True\n"
260 			"400\n"
261 			"500\n"
262 			"0\n"
263 			"0\n"
264 			"0\n"
265 			"PageSize=Custom\n"
266 			"%%EndFeature\n"
267 			"} stopped cleartomark\n";
268 
269 static const char	*default2_code =
270 			"[{\n"
271 			"%%BeginFeature: *InstalledDuplexer False\n"
272 			"%%EndFeature\n"
273 			"} stopped cleartomark\n"
274 			"[{\n"
275 			"%%BeginFeature: *InputSlot Tray\n"
276 			"InputSlot=Tray\n"
277 			"%%EndFeature\n"
278 			"} stopped cleartomark\n"
279 			"[{\n"
280 			"%%BeginFeature: *Quality Normal\n"
281 			"Quality=Normal\n"
282 			"%%EndFeature\n"
283 			"} stopped cleartomark\n"
284 			"[{\n"
285 			"%%BeginFeature: *IntOption None\n"
286 			"%%EndFeature\n"
287 			"} stopped cleartomark\n"
288 			"[{\n"
289 			"%%BeginFeature: *StringOption None\n"
290 			"%%EndFeature\n"
291 			"} stopped cleartomark\n";
292 
293 
294 /*
295  * 'main()' - Main entry.
296  */
297 
298 int					/* O - Exit status */
main(int argc,char * argv[])299 main(int  argc,				/* I - Number of command-line arguments */
300      char *argv[])			/* I - Command-line arguments */
301 {
302   int		i;			/* Looping var */
303   ppd_file_t	*ppd = NULL;		/* PPD file loaded from disk */
304   int		status;			/* Status of tests (0 = success, 1 = fail) */
305   int		conflicts;		/* Number of conflicts */
306   char		*s;			/* String */
307   char		buffer[8192];		/* String buffer */
308   const char	*text,			/* Localized text */
309 		*val;			/* Option value */
310   int		num_options;		/* Number of options */
311   cups_option_t	*options;		/* Options */
312   ppd_size_t	minsize,		/* Minimum size */
313 		maxsize,		/* Maximum size */
314 		*size;			/* Current size */
315   ppd_attr_t	*attr;			/* Current attribute */
316   _ppd_cache_t	*pc;			/* PPD cache */
317 
318 
319   status = 0;
320 
321   if (argc == 1)
322   {
323    /*
324     * Setup directories for locale stuff...
325     */
326 
327     if (access("locale", 0))
328     {
329       mkdir("locale", 0777);
330       mkdir("locale/fr", 0777);
331       symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po");
332       mkdir("locale/zh_TW", 0777);
333       symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po");
334     }
335 
336     putenv("LOCALEDIR=locale");
337     putenv("SOFTWARE=CUPS");
338 
339    /*
340     * Do tests with test.ppd...
341     */
342 
343     fputs("ppdOpenFile(test.ppd): ", stdout);
344 
345     if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL)
346       puts("PASS");
347     else
348     {
349       ppd_status_t	err;		/* Last error in file */
350       int		line;		/* Line number in file */
351 
352 
353       status ++;
354       err = ppdLastError(&line);
355 
356       printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
357     }
358 
359     fputs("ppdFindAttr(wildcard): ", stdout);
360     if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL)
361     {
362       status ++;
363       puts("FAIL (not found)");
364     }
365     else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
366     {
367       status ++;
368       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
369     }
370     else
371       puts("PASS");
372 
373     fputs("ppdFindNextAttr(wildcard): ", stdout);
374     if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL)
375     {
376       status ++;
377       puts("FAIL (not found)");
378     }
379     else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar"))
380     {
381       status ++;
382       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
383     }
384     else
385       puts("PASS");
386 
387     fputs("ppdFindAttr(Foo): ", stdout);
388     if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL)
389     {
390       status ++;
391       puts("FAIL (not found)");
392     }
393     else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
394     {
395       status ++;
396       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
397     }
398     else
399       puts("PASS");
400 
401     fputs("ppdFindNextAttr(Foo): ", stdout);
402     if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL)
403     {
404       status ++;
405       printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
406     }
407     else
408       puts("PASS");
409 
410     fputs("ppdMarkDefaults: ", stdout);
411     ppdMarkDefaults(ppd);
412 
413     if ((conflicts = ppdConflicts(ppd)) == 0)
414       puts("PASS");
415     else
416     {
417       status ++;
418       printf("FAIL (%d conflicts)\n", conflicts);
419     }
420 
421     fputs("ppdEmitString (defaults): ", stdout);
422     if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
423 	!strcmp(s, default_code))
424       puts("PASS");
425     else
426     {
427       status ++;
428       printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
429 	     (int)strlen(default_code));
430 
431       if (s)
432 	puts(s);
433     }
434 
435     if (s)
436       free(s);
437 
438     fputs("ppdEmitString (custom size and string): ", stdout);
439     ppdMarkOption(ppd, "PageSize", "Custom.400x500");
440     ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}");
441 
442     if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
443 	!strcmp(s, custom_code))
444       puts("PASS");
445     else
446     {
447       status ++;
448       printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
449 	     (int)strlen(custom_code));
450 
451       if (s)
452 	puts(s);
453     }
454 
455     if (s)
456       free(s);
457 
458    /*
459     * Test constraints...
460     */
461 
462     fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout);
463     ppdMarkOption(ppd, "PageSize", "Letter");
464 
465     num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options);
466     if (num_options != 2 ||
467         (val = cupsGetOption("PageRegion", num_options, options)) == NULL ||
468 	_cups_strcasecmp(val, "Letter") ||
469 	(val = cupsGetOption("PageSize", num_options, options)) == NULL ||
470 	_cups_strcasecmp(val, "Letter"))
471     {
472       printf("FAIL (%d options:", num_options);
473       for (i = 0; i < num_options; i ++)
474         printf(" %s=%s", options[i].name, options[i].value);
475       puts(")");
476       status ++;
477     }
478     else
479       puts("PASS");
480 
481     fputs("ppdConflicts(): ", stdout);
482     ppdMarkOption(ppd, "InputSlot", "Envelope");
483 
484     if ((conflicts = ppdConflicts(ppd)) == 2)
485       puts("PASS (2)");
486     else
487     {
488       printf("FAIL (%d)\n", conflicts);
489       status ++;
490     }
491 
492     fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout);
493     num_options = 0;
494     options     = NULL;
495     if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
496                              &options))
497     {
498       puts("FAIL (Unable to resolve)");
499       status ++;
500     }
501     else if (num_options != 2 ||
502              !cupsGetOption("PageSize", num_options, options))
503     {
504       printf("FAIL (%d options:", num_options);
505       for (i = 0; i < num_options; i ++)
506         printf(" %s=%s", options[i].name, options[i].value);
507       puts(")");
508       status ++;
509     }
510     else
511       puts("PASS (Resolved by changing PageSize)");
512 
513     cupsFreeOptions(num_options, options);
514 
515     fputs("cupsResolveConflicts(No option/choice): ", stdout);
516     num_options = 0;
517     options     = NULL;
518     if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
519         num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") &&
520 	!_cups_strcasecmp(options[0].value, "Tray"))
521       puts("PASS (Resolved by changing InputSlot)");
522     else if (num_options > 0)
523     {
524       printf("FAIL (%d options:", num_options);
525       for (i = 0; i < num_options; i ++)
526         printf(" %s=%s", options[i].name, options[i].value);
527       puts(")");
528       status ++;
529     }
530     else
531     {
532       puts("FAIL (Unable to resolve)");
533       status ++;
534     }
535     cupsFreeOptions(num_options, options);
536 
537     fputs("ppdInstallableConflict(): ", stdout);
538     if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
539         !ppdInstallableConflict(ppd, "Duplex", "None"))
540       puts("PASS");
541     else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
542     {
543       puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
544       status ++;
545     }
546     else
547     {
548       puts("FAIL (Duplex=None conflicted)");
549       status ++;
550     }
551 
552    /*
553     * ppdPageSizeLimits
554     */
555 
556     fputs("ppdPageSizeLimits: ", stdout);
557     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
558     {
559       if (fabs(minsize.width - 36.0) > 0.001 || fabs(minsize.length - 36.0) > 0.001 ||
560           fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001)
561       {
562         printf("FAIL (got min=%.3fx%.3f, max=%.3fx%.3f, "
563 	       "expected min=36x36, max=1080x86400)\n", minsize.width,
564 	       minsize.length, maxsize.width, maxsize.length);
565         status ++;
566       }
567       else
568         puts("PASS");
569     }
570     else
571     {
572       puts("FAIL (returned 0)");
573       status ++;
574     }
575 
576    /*
577     * cupsMarkOptions with PWG and IPP size names.
578     */
579 
580     fputs("cupsMarkOptions(media=iso-a4): ", stdout);
581     num_options = cupsAddOption("media", "iso-a4", 0, &options);
582     cupsMarkOptions(ppd, num_options, options);
583     cupsFreeOptions(num_options, options);
584 
585     size = ppdPageSize(ppd, NULL);
586     if (!size || strcmp(size->name, "A4"))
587     {
588       printf("FAIL (%s)\n", size ? size->name : "unknown");
589       status ++;
590     }
591     else
592       puts("PASS");
593 
594     fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout);
595     num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options);
596     cupsMarkOptions(ppd, num_options, options);
597     cupsFreeOptions(num_options, options);
598 
599     size = ppdPageSize(ppd, NULL);
600     if (!size || strcmp(size->name, "Letter"))
601     {
602       printf("FAIL (%s)\n", size ? size->name : "unknown");
603       status ++;
604     }
605     else
606       puts("PASS");
607 
608     fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout);
609     num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0,
610                                 &options);
611     cupsMarkOptions(ppd, num_options, options);
612     cupsFreeOptions(num_options, options);
613 
614     size = ppdPageSize(ppd, NULL);
615     if (!size || strcmp(size->name, "Letter.Fullbleed"))
616     {
617       printf("FAIL (%s)\n", size ? size->name : "unknown");
618       status ++;
619     }
620     else
621       puts("PASS");
622 
623     fputs("cupsMarkOptions(media=A4): ", stdout);
624     num_options = cupsAddOption("media", "A4", 0, &options);
625     cupsMarkOptions(ppd, num_options, options);
626     cupsFreeOptions(num_options, options);
627 
628     size = ppdPageSize(ppd, NULL);
629     if (!size || strcmp(size->name, "A4"))
630     {
631       printf("FAIL (%s)\n", size ? size->name : "unknown");
632       status ++;
633     }
634     else
635       puts("PASS");
636 
637    /*
638     * Custom sizes...
639     */
640 
641     fputs("cupsMarkOptions(media=Custom.8x10in): ", stdout);
642     num_options = cupsAddOption("media", "Custom.8x10in", 0, &options);
643     cupsMarkOptions(ppd, num_options, options);
644     cupsFreeOptions(num_options, options);
645 
646     size = ppdPageSize(ppd, NULL);
647     if (!size || strcmp(size->name, "Custom") ||
648         fabs(size->width - 576.0) > 0.001 ||
649         fabs(size->length - 720.0) > 0.001)
650     {
651       printf("FAIL (%s - %gx%g)\n", size ? size->name : "unknown",
652              size ? size->width : 0.0, size ? size->length : 0.0);
653       status ++;
654     }
655     else
656       puts("PASS");
657 
658    /*
659     * Test localization...
660     */
661 
662     /* Force US English base locale */
663     putenv("LANG=en");
664     putenv("LC_ALL=en");
665     putenv("LC_CTYPE=en");
666     putenv("LC_MESSAGES=en");
667 
668     fputs("ppdLocalizeIPPReason(text): ", stdout);
669     if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
670         !strcmp(buffer, "Foo Reason"))
671       puts("PASS");
672     else
673     {
674       status ++;
675       printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer);
676     }
677 
678     fputs("ppdLocalizeIPPReason(http): ", stdout);
679     if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) &&
680         !strcmp(buffer, "http://foo/bar.html"))
681       puts("PASS");
682     else
683     {
684       status ++;
685       printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer);
686     }
687 
688     fputs("ppdLocalizeIPPReason(help): ", stdout);
689     if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) &&
690         !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help"))
691       puts("PASS");
692     else
693     {
694       status ++;
695       printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer);
696     }
697 
698     fputs("ppdLocalizeIPPReason(file): ", stdout);
699     if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) &&
700         !strcmp(buffer, "/help/foo/bar.html"))
701       puts("PASS");
702     else
703     {
704       status ++;
705       printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer);
706     }
707 
708     /* Force French */
709     putenv("LANG=fr");
710     putenv("LC_ALL=fr");
711     putenv("LC_CTYPE=fr");
712     putenv("LC_MESSAGES=fr");
713 
714     fputs("ppdLocalizeIPPReason(fr text): ", stdout);
715     if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
716         !strcmp(buffer, "La Long Foo Reason"))
717       puts("PASS");
718     else
719     {
720       status ++;
721       printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer);
722     }
723 
724     /* Force Simplified Chinese */
725     putenv("LANG=zh_TW");
726     putenv("LC_ALL=zh_TW");
727     putenv("LC_CTYPE=zh_TW");
728     putenv("LC_MESSAGES=zh_TW");
729 
730     fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout);
731     if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
732         !strcmp(buffer, "Number 1 Foo Reason"))
733       puts("PASS");
734     else
735     {
736       status ++;
737       printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer);
738     }
739 
740    /*
741     * cupsMarkerName localization...
742     */
743 
744     /* Force US English base locale */
745     putenv("LANG=en");
746     putenv("LC_ALL=en");
747     putenv("LC_CTYPE=en");
748     putenv("LC_MESSAGES=en");
749 
750     fputs("ppdLocalizeMarkerName(bogus): ", stdout);
751 
752     if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL)
753     {
754       status ++;
755       printf("FAIL (\"%s\" instead of NULL)\n", text);
756     }
757     else
758       puts("PASS");
759 
760     fputs("ppdLocalizeMarkerName(cyan): ", stdout);
761 
762     if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
763         !strcmp(text, "Cyan Toner"))
764       puts("PASS");
765     else
766     {
767       status ++;
768       printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n",
769              text ? text : "(null)");
770     }
771 
772     /* Force French locale */
773     putenv("LANG=fr");
774     putenv("LC_ALL=fr");
775     putenv("LC_CTYPE=fr");
776     putenv("LC_MESSAGES=fr");
777 
778     fputs("ppdLocalizeMarkerName(fr cyan): ", stdout);
779     if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
780         !strcmp(text, "La Toner Cyan"))
781       puts("PASS");
782     else
783     {
784       status ++;
785       printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n",
786              text ? text : "(null)");
787     }
788 
789     /* Force Simplified Chinese locale */
790     putenv("LANG=zh_TW");
791     putenv("LC_ALL=zh_TW");
792     putenv("LC_CTYPE=zh_TW");
793     putenv("LC_MESSAGES=zh_TW");
794 
795     fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout);
796     if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
797         !strcmp(text, "Number 1 Cyan Toner"))
798       puts("PASS");
799     else
800     {
801       status ++;
802       printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n",
803              text ? text : "(null)");
804     }
805 
806     ppdClose(ppd);
807 
808     /* Force US English base locale */
809     putenv("LANG=en");
810     putenv("LC_ALL=en");
811     putenv("LC_CTYPE=en");
812     putenv("LC_MESSAGES=en");
813 
814    /*
815     * Test new constraints...
816     */
817 
818     fputs("ppdOpenFile(test2.ppd): ", stdout);
819 
820     if ((ppd = ppdOpenFile("test2.ppd")) != NULL)
821       puts("PASS");
822     else
823     {
824       ppd_status_t	err;		/* Last error in file */
825       int		line;		/* Line number in file */
826 
827 
828       status ++;
829       err = ppdLastError(&line);
830 
831       printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
832     }
833 
834     fputs("ppdMarkDefaults: ", stdout);
835     ppdMarkDefaults(ppd);
836 
837     if ((conflicts = ppdConflicts(ppd)) == 0)
838       puts("PASS");
839     else
840     {
841       status ++;
842       printf("FAIL (%d conflicts)\n", conflicts);
843     }
844 
845     fputs("ppdEmitString (defaults): ", stdout);
846     if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
847 	!strcmp(s, default2_code))
848       puts("PASS");
849     else
850     {
851       status ++;
852       printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
853 	     (int)strlen(default2_code));
854 
855       if (s)
856 	puts(s);
857     }
858 
859     if (s)
860       free(s);
861 
862     fputs("ppdConflicts(): ", stdout);
863     ppdMarkOption(ppd, "PageSize", "Env10");
864     ppdMarkOption(ppd, "InputSlot", "Envelope");
865     ppdMarkOption(ppd, "Quality", "Photo");
866 
867     if ((conflicts = ppdConflicts(ppd)) == 1)
868       puts("PASS (1)");
869     else
870     {
871       printf("FAIL (%d)\n", conflicts);
872       status ++;
873     }
874 
875     fputs("cupsResolveConflicts(Quality=Photo): ", stdout);
876     num_options = 0;
877     options     = NULL;
878     if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
879                              &options))
880     {
881       printf("FAIL (%d options:", num_options);
882       for (i = 0; i < num_options; i ++)
883         printf(" %s=%s", options[i].name, options[i].value);
884       puts(")");
885       status ++;
886     }
887     else
888       puts("PASS (Unable to resolve)");
889     cupsFreeOptions(num_options, options);
890 
891     fputs("cupsResolveConflicts(No option/choice): ", stdout);
892     num_options = 0;
893     options     = NULL;
894     if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
895         num_options == 1 && !_cups_strcasecmp(options->name, "Quality") &&
896 	!_cups_strcasecmp(options->value, "Normal"))
897       puts("PASS");
898     else if (num_options > 0)
899     {
900       printf("FAIL (%d options:", num_options);
901       for (i = 0; i < num_options; i ++)
902         printf(" %s=%s", options[i].name, options[i].value);
903       puts(")");
904       status ++;
905     }
906     else
907     {
908       puts("FAIL (Unable to resolve!)");
909       status ++;
910     }
911     cupsFreeOptions(num_options, options);
912 
913     fputs("cupsResolveConflicts(loop test): ", stdout);
914     ppdMarkOption(ppd, "PageSize", "A4");
915     ppdMarkOption(ppd, "InputSlot", "Tray");
916     ppdMarkOption(ppd, "Quality", "Photo");
917     num_options = 0;
918     options     = NULL;
919     if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
920       puts("PASS");
921     else if (num_options > 0)
922     {
923       printf("FAIL (%d options:", num_options);
924       for (i = 0; i < num_options; i ++)
925         printf(" %s=%s", options[i].name, options[i].value);
926       puts(")");
927     }
928     else
929       puts("FAIL (No conflicts!)");
930 
931     fputs("ppdInstallableConflict(): ", stdout);
932     if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
933         !ppdInstallableConflict(ppd, "Duplex", "None"))
934       puts("PASS");
935     else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
936     {
937       puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
938       status ++;
939     }
940     else
941     {
942       puts("FAIL (Duplex=None conflicted)");
943       status ++;
944     }
945 
946    /*
947     * ppdPageSizeLimits
948     */
949 
950     ppdMarkDefaults(ppd);
951 
952     fputs("ppdPageSizeLimits(default): ", stdout);
953     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
954     {
955       if (fabs(minsize.width - 36.0) > 0.001 || fabs(minsize.length - 36.0) > 0.001 ||
956           fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001)
957       {
958         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
959 	       "expected min=36x36, max=1080x86400)\n", minsize.width,
960 	       minsize.length, maxsize.width, maxsize.length);
961         status ++;
962       }
963       else
964         puts("PASS");
965     }
966     else
967     {
968       puts("FAIL (returned 0)");
969       status ++;
970     }
971 
972     ppdMarkOption(ppd, "InputSlot", "Manual");
973 
974     fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout);
975     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
976     {
977       if (fabs(minsize.width - 100.0) > 0.001 || fabs(minsize.length - 100.0) > 0.001 ||
978           fabs(maxsize.width - 1000.0) > 0.001 || fabs(maxsize.length - 1000.0) > 0.001)
979       {
980         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
981 	       "expected min=100x100, max=1000x1000)\n", minsize.width,
982 	       minsize.length, maxsize.width, maxsize.length);
983         status ++;
984       }
985       else
986         puts("PASS");
987     }
988     else
989     {
990       puts("FAIL (returned 0)");
991       status ++;
992     }
993 
994     ppdMarkOption(ppd, "Quality", "Photo");
995 
996     fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
997     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
998     {
999       if (fabs(minsize.width - 200.0) > 0.001 || fabs(minsize.length - 200.0) > 0.001 ||
1000           fabs(maxsize.width - 1000.0) > 0.001 || fabs(maxsize.length - 1000.0) > 0.001)
1001       {
1002         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
1003 	       "expected min=200x200, max=1000x1000)\n", minsize.width,
1004 	       minsize.length, maxsize.width, maxsize.length);
1005         status ++;
1006       }
1007       else
1008         puts("PASS");
1009     }
1010     else
1011     {
1012       puts("FAIL (returned 0)");
1013       status ++;
1014     }
1015 
1016     ppdMarkOption(ppd, "InputSlot", "Tray");
1017 
1018     fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
1019     if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
1020     {
1021       if (fabs(minsize.width - 300.0) > 0.001 || fabs(minsize.length - 300.0) > 0.001 ||
1022           fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001)
1023       {
1024         printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
1025 	       "expected min=300x300, max=1080x86400)\n", minsize.width,
1026 	       minsize.length, maxsize.width, maxsize.length);
1027         status ++;
1028       }
1029       else
1030         puts("PASS");
1031     }
1032     else
1033     {
1034       puts("FAIL (returned 0)");
1035       status ++;
1036     }
1037 
1038     status += do_ps_tests();
1039   }
1040   else if (!strcmp(argv[1], "--raster"))
1041   {
1042     for (status = 0, num_options = 0, options = NULL, i = 1; i < argc; i ++)
1043     {
1044       if (argv[i][0] == '-')
1045       {
1046         if (argv[i][1] == 'o')
1047         {
1048           if (argv[i][2])
1049             num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
1050           else
1051           {
1052             i ++;
1053             if (i < argc)
1054               num_options = cupsParseOptions(argv[i], num_options, &options);
1055             else
1056             {
1057               puts("Usage: testppd --raster [-o name=value ...] [filename.ppd ...]");
1058               return (1);
1059             }
1060           }
1061         }
1062         else
1063         {
1064 	  puts("Usage: testppd --raster [-o name=value ...] [filename.ppd ...]");
1065 	  return (1);
1066         }
1067       }
1068       else
1069 	status += do_ppd_tests(argv[i], num_options, options);
1070     }
1071 
1072     cupsFreeOptions(num_options, options);
1073   }
1074   else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7))
1075   {
1076    /*
1077     * ipp://... or ipps://...
1078     */
1079 
1080     http_t	*http;			/* Connection to printer */
1081     ipp_t	*request,		/* Get-Printer-Attributes request */
1082 		*response;		/* Get-Printer-Attributes response */
1083     char	scheme[32],		/* URI scheme */
1084 		userpass[256],		/* Username:password */
1085 		host[256],		/* Hostname */
1086 		resource[256];		/* Resource path */
1087     int		port;			/* Port number */
1088     static const char * const pattrs[] =/* Requested printer attributes */
1089     {
1090       "job-template",
1091       "printer-defaults",
1092       "printer-description",
1093       "media-col-database"
1094     };
1095 
1096     if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
1097     {
1098       printf("Bad URI \"%s\".\n", argv[1]);
1099       return (1);
1100     }
1101 
1102     http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
1103     if (!http)
1104     {
1105       printf("Unable to connect to \"%s:%d\": %s\n", host, port, cupsLastErrorString());
1106       return (1);
1107     }
1108 
1109     request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1110     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, argv[1]);
1111     ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
1112     response = cupsDoRequest(http, request, resource);
1113 
1114     if (_ppdCreateFromIPP(buffer, sizeof(buffer), response))
1115       printf("Created PPD: %s\n", buffer);
1116     else
1117       puts("Unable to create PPD.");
1118 
1119     ippDelete(response);
1120     httpClose(http);
1121     return (0);
1122   }
1123   else
1124   {
1125     const char	*filename;		/* PPD filename */
1126     struct stat	fileinfo;		/* File information */
1127 
1128 
1129     if (strchr(argv[1], ':'))
1130     {
1131      /*
1132       * Server PPD...
1133       */
1134 
1135       if ((filename = cupsGetServerPPD(CUPS_HTTP_DEFAULT, argv[1])) == NULL)
1136       {
1137         printf("%s: %s\n", argv[1], cupsLastErrorString());
1138         return (1);
1139       }
1140     }
1141     else if (!strncmp(argv[1], "-d", 2))
1142     {
1143       const char *printer;		/* Printer name */
1144 
1145       if (argv[1][2])
1146 	printer = argv[1] + 2;
1147       else if (argv[2])
1148 	printer = argv[2];
1149       else
1150       {
1151         puts("Usage: ./testppd -d printer");
1152 	return (1);
1153       }
1154 
1155       filename = cupsGetPPD(printer);
1156 
1157       if (!filename)
1158       {
1159         printf("%s: %s\n", printer, cupsLastErrorString());
1160         return (1);
1161       }
1162     }
1163     else
1164       filename = argv[1];
1165 
1166     if (lstat(filename, &fileinfo))
1167     {
1168       printf("%s: %s\n", filename, strerror(errno));
1169       return (1);
1170     }
1171 
1172     if (S_ISLNK(fileinfo.st_mode))
1173     {
1174       char	realfile[1024];		/* Real file path */
1175       ssize_t	realsize;		/* Size of real file path */
1176 
1177 
1178       if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
1179         strlcpy(realfile, "Unknown", sizeof(realfile));
1180       else
1181         realfile[realsize] = '\0';
1182 
1183       if (stat(realfile, &fileinfo))
1184 	printf("%s: symlink to \"%s\", %s\n", filename, realfile,
1185 	       strerror(errno));
1186       else
1187 	printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile,
1188 	       (long)fileinfo.st_size);
1189     }
1190     else
1191       printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size);
1192 
1193     if ((ppd = ppdOpenFile(filename)) == NULL)
1194     {
1195       ppd_status_t	err;		/* Last error in file */
1196       int		line;		/* Line number in file */
1197 
1198 
1199       status ++;
1200       err = ppdLastError(&line);
1201 
1202       printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
1203     }
1204     else
1205     {
1206       int		j, k;		/* Looping vars */
1207       ppd_group_t	*group;		/* Option group */
1208       ppd_option_t	*option;	/* Option */
1209       ppd_coption_t	*coption;	/* Custom option */
1210       ppd_cparam_t	*cparam;	/* Custom parameter */
1211       ppd_const_t	*c;		/* UIConstraints */
1212       char		lang[255],	/* LANG environment variable */
1213 			lc_all[255],	/* LC_ALL environment variable */
1214 			lc_ctype[255],	/* LC_CTYPE environment variable */
1215 			lc_messages[255];/* LC_MESSAGES environment variable */
1216 
1217 
1218       if (argc > 2)
1219       {
1220         snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
1221 	putenv(lang);
1222         snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]);
1223 	putenv(lc_all);
1224         snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]);
1225 	putenv(lc_ctype);
1226         snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]);
1227 	putenv(lc_messages);
1228       }
1229 
1230       ppdLocalize(ppd);
1231       ppdMarkDefaults(ppd);
1232 
1233       if (argc > 3)
1234       {
1235         text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer));
1236 	printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3],
1237 	       text ? text : "(null)");
1238 	return (text == NULL);
1239       }
1240 
1241       for (i = ppd->num_groups, group = ppd->groups;
1242 	   i > 0;
1243 	   i --, group ++)
1244       {
1245 	printf("%s (%s):\n", group->name, group->text);
1246 
1247 	for (j = group->num_options, option = group->options;
1248 	     j > 0;
1249 	     j --, option ++)
1250 	{
1251 	  printf("    %s (%s):\n", option->keyword, option->text);
1252 
1253 	  for (k = 0; k < option->num_choices; k ++)
1254 	    printf("        - %s%s (%s)\n",
1255 	           option->choices[k].marked ? "*" : "",
1256 		   option->choices[k].choice, option->choices[k].text);
1257 
1258           if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
1259 	  {
1260 	    for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
1261 	         cparam;
1262 		 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
1263             {
1264 	      switch (cparam->type)
1265 	      {
1266 	        case PPD_CUSTOM_UNKNOWN :
1267 		    printf("              %s(%s): PPD_CUSTOM_UNKNOWN (error)\n", cparam->name, cparam->text);
1268 	            break;
1269 
1270 	        case PPD_CUSTOM_CURVE :
1271 		    printf("              %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
1272 		           cparam->name, cparam->text,
1273 			   cparam->minimum.custom_curve,
1274 			   cparam->maximum.custom_curve);
1275 		    break;
1276 
1277 	        case PPD_CUSTOM_INT :
1278 		    printf("              %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
1279 		           cparam->name, cparam->text,
1280 			   cparam->minimum.custom_int,
1281 			   cparam->maximum.custom_int);
1282 		    break;
1283 
1284 	        case PPD_CUSTOM_INVCURVE :
1285 		    printf("              %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
1286 		           cparam->name, cparam->text,
1287 			   cparam->minimum.custom_invcurve,
1288 			   cparam->maximum.custom_invcurve);
1289 		    break;
1290 
1291 	        case PPD_CUSTOM_PASSCODE :
1292 		    printf("              %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
1293 		           cparam->name, cparam->text,
1294 			   cparam->minimum.custom_passcode,
1295 			   cparam->maximum.custom_passcode);
1296 		    break;
1297 
1298 	        case PPD_CUSTOM_PASSWORD :
1299 		    printf("              %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
1300 		           cparam->name, cparam->text,
1301 			   cparam->minimum.custom_password,
1302 			   cparam->maximum.custom_password);
1303 		    break;
1304 
1305 	        case PPD_CUSTOM_POINTS :
1306 		    printf("              %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
1307 		           cparam->name, cparam->text,
1308 			   cparam->minimum.custom_points,
1309 			   cparam->maximum.custom_points);
1310 		    break;
1311 
1312 	        case PPD_CUSTOM_REAL :
1313 		    printf("              %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
1314 		           cparam->name, cparam->text,
1315 			   cparam->minimum.custom_real,
1316 			   cparam->maximum.custom_real);
1317 		    break;
1318 
1319 	        case PPD_CUSTOM_STRING :
1320 		    printf("              %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
1321 		           cparam->name, cparam->text,
1322 			   cparam->minimum.custom_string,
1323 			   cparam->maximum.custom_string);
1324 		    break;
1325 	      }
1326 	    }
1327 	  }
1328 	}
1329       }
1330 
1331       puts("\nSizes:");
1332       for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
1333         printf("    %s = %gx%g, [%g %g %g %g]\n", size->name, size->width,
1334 	       size->length, size->left, size->bottom, size->right, size->top);
1335 
1336       puts("\nConstraints:");
1337 
1338       for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
1339         printf("    *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
1340 	       c->option2, c->choice2);
1341       if (ppd->num_consts == 0)
1342         puts("    NO CONSTRAINTS");
1343 
1344       puts("\nFilters:");
1345 
1346       for (i = 0; i < ppd->num_filters; i ++)
1347         printf("    %s\n", ppd->filters[i]);
1348 
1349       if (ppd->num_filters == 0)
1350         puts("    NO FILTERS");
1351 
1352       puts("\nAttributes:");
1353 
1354       for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
1355            attr;
1356 	   attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
1357         printf("    *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
1358 	       attr->text, attr->value ? attr->value : "");
1359 
1360       puts("\nPPD Cache:");
1361       if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
1362         printf("    Unable to create: %s\n", cupsLastErrorString());
1363       else
1364       {
1365         _ppdCacheWriteFile(pc, "t.cache", NULL);
1366         puts("    Wrote t.cache.");
1367       }
1368     }
1369 
1370     if (!strncmp(argv[1], "-d", 2))
1371       unlink(filename);
1372   }
1373 
1374 #ifdef __APPLE__
1375   if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
1376   {
1377     char	command[1024];		/* malloc_history command */
1378 
1379     snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
1380 	     getpid());
1381     fflush(stdout);
1382     system(command);
1383   }
1384 #endif /* __APPLE__ */
1385 
1386   ppdClose(ppd);
1387 
1388   return (status);
1389 }
1390 
1391 
1392 /*
1393  * 'do_ppd_tests()' - Test the default option commands in a PPD file.
1394  */
1395 
1396 static int				/* O - Number of errors */
do_ppd_tests(const char * filename,int num_options,cups_option_t * options)1397 do_ppd_tests(const char    *filename,	/* I - PPD file */
1398              int           num_options,	/* I - Number of options */
1399              cups_option_t *options)	/* I - Options */
1400 {
1401   ppd_file_t		*ppd;		/* PPD file data */
1402   cups_page_header2_t	header;		/* Page header */
1403 
1404 
1405   printf("\"%s\": ", filename);
1406   fflush(stdout);
1407 
1408   if ((ppd = ppdOpenFile(filename)) == NULL)
1409   {
1410     ppd_status_t	status;		/* Status from PPD loader */
1411     int			line;		/* Line number containing error */
1412 
1413 
1414     status = ppdLastError(&line);
1415 
1416     puts("FAIL (bad PPD file)");
1417     printf("    %s on line %d\n", ppdErrorString(status), line);
1418 
1419     return (1);
1420   }
1421 
1422   ppdMarkDefaults(ppd);
1423   cupsMarkOptions(ppd, num_options, options);
1424 
1425   if (cupsRasterInterpretPPD(&header, ppd, 0, NULL, NULL))
1426   {
1427     puts("FAIL (error from function)");
1428     puts(cupsRasterErrorString());
1429 
1430     return (1);
1431   }
1432   else
1433   {
1434     puts("PASS");
1435 
1436     return (0);
1437   }
1438 }
1439 
1440 
1441 /*
1442  * 'do_ps_tests()' - Test standard PostScript commands.
1443  */
1444 
1445 static int
do_ps_tests(void)1446 do_ps_tests(void)
1447 {
1448   cups_page_header2_t	header;		/* Page header */
1449   int			preferred_bits;	/* Preferred bits */
1450   int			errors = 0;	/* Number of errors */
1451 
1452 
1453  /*
1454   * Test PS exec code...
1455   */
1456 
1457   fputs("_cupsRasterExecPS(\"setpagedevice\"): ", stdout);
1458   fflush(stdout);
1459 
1460   memset(&header, 0, sizeof(header));
1461   header.Collate = CUPS_TRUE;
1462   preferred_bits = 0;
1463 
1464   if (_cupsRasterExecPS(&header, &preferred_bits, setpagedevice_code))
1465   {
1466     puts("FAIL (error from function)");
1467     puts(cupsRasterErrorString());
1468     errors ++;
1469   }
1470   else if (preferred_bits != 17 ||
1471            memcmp(&header, &setpagedevice_header, sizeof(header)))
1472   {
1473     puts("FAIL (bad header)");
1474 
1475     if (preferred_bits != 17)
1476       printf("    cupsPreferredBitsPerColor %d, expected 17\n",
1477              preferred_bits);
1478 
1479     print_changes(&setpagedevice_header, &header);
1480     errors ++;
1481   }
1482   else
1483     puts("PASS");
1484 
1485   fputs("_cupsRasterExecPS(\"roll\"): ", stdout);
1486   fflush(stdout);
1487 
1488   if (_cupsRasterExecPS(&header, &preferred_bits,
1489                         "792 612 0 0 0\n"
1490 			"pop pop pop\n"
1491 			"<</PageSize[5 -2 roll]/ImagingBBox null>>"
1492 			"setpagedevice\n"))
1493   {
1494     puts("FAIL (error from function)");
1495     puts(cupsRasterErrorString());
1496     errors ++;
1497   }
1498   else if (header.PageSize[0] != 792 || header.PageSize[1] != 612)
1499   {
1500     printf("FAIL (PageSize [%d %d], expected [792 612])\n", header.PageSize[0],
1501            header.PageSize[1]);
1502     errors ++;
1503   }
1504   else
1505     puts("PASS");
1506 
1507   fputs("_cupsRasterExecPS(\"dup index\"): ", stdout);
1508   fflush(stdout);
1509 
1510   if (_cupsRasterExecPS(&header, &preferred_bits,
1511                         "true false dup\n"
1512 			"<</Collate 4 index"
1513 			"/Duplex 5 index"
1514 			"/Tumble 6 index>>setpagedevice\n"
1515 			"pop pop pop"))
1516   {
1517     puts("FAIL (error from function)");
1518     puts(cupsRasterErrorString());
1519     errors ++;
1520   }
1521   else
1522   {
1523     if (!header.Collate)
1524     {
1525       printf("FAIL (Collate false, expected true)\n");
1526       errors ++;
1527     }
1528 
1529     if (header.Duplex)
1530     {
1531       printf("FAIL (Duplex true, expected false)\n");
1532       errors ++;
1533     }
1534 
1535     if (header.Tumble)
1536     {
1537       printf("FAIL (Tumble true, expected false)\n");
1538       errors ++;
1539     }
1540 
1541     if(header.Collate && !header.Duplex && !header.Tumble)
1542       puts("PASS");
1543   }
1544 
1545   fputs("_cupsRasterExecPS(\"%%Begin/EndFeature code\"): ", stdout);
1546   fflush(stdout);
1547 
1548   if (_cupsRasterExecPS(&header, &preferred_bits, dsc_code))
1549   {
1550     puts("FAIL (error from function)");
1551     puts(cupsRasterErrorString());
1552     errors ++;
1553   }
1554   else if (header.PageSize[0] != 792 || header.PageSize[1] != 1224)
1555   {
1556     printf("FAIL (bad PageSize [%d %d], expected [792 1224])\n",
1557            header.PageSize[0], header.PageSize[1]);
1558     errors ++;
1559   }
1560   else
1561     puts("PASS");
1562 
1563   return (errors);
1564 }
1565 
1566 
1567 
1568 
1569 /*
1570  * 'print_changes()' - Print differences in the page header.
1571  */
1572 
1573 static void
print_changes(cups_page_header2_t * header,cups_page_header2_t * expected)1574 print_changes(
1575     cups_page_header2_t *header,	/* I - Actual page header */
1576     cups_page_header2_t *expected)	/* I - Expected page header */
1577 {
1578   int	i;				/* Looping var */
1579 
1580 
1581   if (strcmp(header->MediaClass, expected->MediaClass))
1582     printf("    MediaClass (%s), expected (%s)\n", header->MediaClass,
1583            expected->MediaClass);
1584 
1585   if (strcmp(header->MediaColor, expected->MediaColor))
1586     printf("    MediaColor (%s), expected (%s)\n", header->MediaColor,
1587            expected->MediaColor);
1588 
1589   if (strcmp(header->MediaType, expected->MediaType))
1590     printf("    MediaType (%s), expected (%s)\n", header->MediaType,
1591            expected->MediaType);
1592 
1593   if (strcmp(header->OutputType, expected->OutputType))
1594     printf("    OutputType (%s), expected (%s)\n", header->OutputType,
1595            expected->OutputType);
1596 
1597   if (header->AdvanceDistance != expected->AdvanceDistance)
1598     printf("    AdvanceDistance %d, expected %d\n", header->AdvanceDistance,
1599            expected->AdvanceDistance);
1600 
1601   if (header->AdvanceMedia != expected->AdvanceMedia)
1602     printf("    AdvanceMedia %d, expected %d\n", header->AdvanceMedia,
1603            expected->AdvanceMedia);
1604 
1605   if (header->Collate != expected->Collate)
1606     printf("    Collate %d, expected %d\n", header->Collate,
1607            expected->Collate);
1608 
1609   if (header->CutMedia != expected->CutMedia)
1610     printf("    CutMedia %d, expected %d\n", header->CutMedia,
1611            expected->CutMedia);
1612 
1613   if (header->Duplex != expected->Duplex)
1614     printf("    Duplex %d, expected %d\n", header->Duplex,
1615            expected->Duplex);
1616 
1617   if (header->HWResolution[0] != expected->HWResolution[0] ||
1618       header->HWResolution[1] != expected->HWResolution[1])
1619     printf("    HWResolution [%d %d], expected [%d %d]\n",
1620            header->HWResolution[0], header->HWResolution[1],
1621            expected->HWResolution[0], expected->HWResolution[1]);
1622 
1623   if (memcmp(header->ImagingBoundingBox, expected->ImagingBoundingBox,
1624              sizeof(header->ImagingBoundingBox)))
1625     printf("    ImagingBoundingBox [%d %d %d %d], expected [%d %d %d %d]\n",
1626            header->ImagingBoundingBox[0],
1627            header->ImagingBoundingBox[1],
1628            header->ImagingBoundingBox[2],
1629            header->ImagingBoundingBox[3],
1630            expected->ImagingBoundingBox[0],
1631            expected->ImagingBoundingBox[1],
1632            expected->ImagingBoundingBox[2],
1633            expected->ImagingBoundingBox[3]);
1634 
1635   if (header->InsertSheet != expected->InsertSheet)
1636     printf("    InsertSheet %d, expected %d\n", header->InsertSheet,
1637            expected->InsertSheet);
1638 
1639   if (header->Jog != expected->Jog)
1640     printf("    Jog %d, expected %d\n", header->Jog,
1641            expected->Jog);
1642 
1643   if (header->LeadingEdge != expected->LeadingEdge)
1644     printf("    LeadingEdge %d, expected %d\n", header->LeadingEdge,
1645            expected->LeadingEdge);
1646 
1647   if (header->Margins[0] != expected->Margins[0] ||
1648       header->Margins[1] != expected->Margins[1])
1649     printf("    Margins [%d %d], expected [%d %d]\n",
1650            header->Margins[0], header->Margins[1],
1651            expected->Margins[0], expected->Margins[1]);
1652 
1653   if (header->ManualFeed != expected->ManualFeed)
1654     printf("    ManualFeed %d, expected %d\n", header->ManualFeed,
1655            expected->ManualFeed);
1656 
1657   if (header->MediaPosition != expected->MediaPosition)
1658     printf("    MediaPosition %d, expected %d\n", header->MediaPosition,
1659            expected->MediaPosition);
1660 
1661   if (header->MediaWeight != expected->MediaWeight)
1662     printf("    MediaWeight %d, expected %d\n", header->MediaWeight,
1663            expected->MediaWeight);
1664 
1665   if (header->MirrorPrint != expected->MirrorPrint)
1666     printf("    MirrorPrint %d, expected %d\n", header->MirrorPrint,
1667            expected->MirrorPrint);
1668 
1669   if (header->NegativePrint != expected->NegativePrint)
1670     printf("    NegativePrint %d, expected %d\n", header->NegativePrint,
1671            expected->NegativePrint);
1672 
1673   if (header->NumCopies != expected->NumCopies)
1674     printf("    NumCopies %d, expected %d\n", header->NumCopies,
1675            expected->NumCopies);
1676 
1677   if (header->Orientation != expected->Orientation)
1678     printf("    Orientation %d, expected %d\n", header->Orientation,
1679            expected->Orientation);
1680 
1681   if (header->OutputFaceUp != expected->OutputFaceUp)
1682     printf("    OutputFaceUp %d, expected %d\n", header->OutputFaceUp,
1683            expected->OutputFaceUp);
1684 
1685   if (header->PageSize[0] != expected->PageSize[0] ||
1686       header->PageSize[1] != expected->PageSize[1])
1687     printf("    PageSize [%d %d], expected [%d %d]\n",
1688            header->PageSize[0], header->PageSize[1],
1689            expected->PageSize[0], expected->PageSize[1]);
1690 
1691   if (header->Separations != expected->Separations)
1692     printf("    Separations %d, expected %d\n", header->Separations,
1693            expected->Separations);
1694 
1695   if (header->TraySwitch != expected->TraySwitch)
1696     printf("    TraySwitch %d, expected %d\n", header->TraySwitch,
1697            expected->TraySwitch);
1698 
1699   if (header->Tumble != expected->Tumble)
1700     printf("    Tumble %d, expected %d\n", header->Tumble,
1701            expected->Tumble);
1702 
1703   if (header->cupsWidth != expected->cupsWidth)
1704     printf("    cupsWidth %d, expected %d\n", header->cupsWidth,
1705            expected->cupsWidth);
1706 
1707   if (header->cupsHeight != expected->cupsHeight)
1708     printf("    cupsHeight %d, expected %d\n", header->cupsHeight,
1709            expected->cupsHeight);
1710 
1711   if (header->cupsMediaType != expected->cupsMediaType)
1712     printf("    cupsMediaType %d, expected %d\n", header->cupsMediaType,
1713            expected->cupsMediaType);
1714 
1715   if (header->cupsBitsPerColor != expected->cupsBitsPerColor)
1716     printf("    cupsBitsPerColor %d, expected %d\n", header->cupsBitsPerColor,
1717            expected->cupsBitsPerColor);
1718 
1719   if (header->cupsBitsPerPixel != expected->cupsBitsPerPixel)
1720     printf("    cupsBitsPerPixel %d, expected %d\n", header->cupsBitsPerPixel,
1721            expected->cupsBitsPerPixel);
1722 
1723   if (header->cupsBytesPerLine != expected->cupsBytesPerLine)
1724     printf("    cupsBytesPerLine %d, expected %d\n", header->cupsBytesPerLine,
1725            expected->cupsBytesPerLine);
1726 
1727   if (header->cupsColorOrder != expected->cupsColorOrder)
1728     printf("    cupsColorOrder %d, expected %d\n", header->cupsColorOrder,
1729            expected->cupsColorOrder);
1730 
1731   if (header->cupsColorSpace != expected->cupsColorSpace)
1732     printf("    cupsColorSpace %s, expected %s\n", _cupsRasterColorSpaceString(header->cupsColorSpace),
1733            _cupsRasterColorSpaceString(expected->cupsColorSpace));
1734 
1735   if (header->cupsCompression != expected->cupsCompression)
1736     printf("    cupsCompression %d, expected %d\n", header->cupsCompression,
1737            expected->cupsCompression);
1738 
1739   if (header->cupsRowCount != expected->cupsRowCount)
1740     printf("    cupsRowCount %d, expected %d\n", header->cupsRowCount,
1741            expected->cupsRowCount);
1742 
1743   if (header->cupsRowFeed != expected->cupsRowFeed)
1744     printf("    cupsRowFeed %d, expected %d\n", header->cupsRowFeed,
1745            expected->cupsRowFeed);
1746 
1747   if (header->cupsRowStep != expected->cupsRowStep)
1748     printf("    cupsRowStep %d, expected %d\n", header->cupsRowStep,
1749            expected->cupsRowStep);
1750 
1751   if (header->cupsNumColors != expected->cupsNumColors)
1752     printf("    cupsNumColors %d, expected %d\n", header->cupsNumColors,
1753            expected->cupsNumColors);
1754 
1755   if (fabs(header->cupsBorderlessScalingFactor - expected->cupsBorderlessScalingFactor) > 0.001)
1756     printf("    cupsBorderlessScalingFactor %g, expected %g\n",
1757            header->cupsBorderlessScalingFactor,
1758            expected->cupsBorderlessScalingFactor);
1759 
1760   if (fabs(header->cupsPageSize[0] - expected->cupsPageSize[0]) > 0.001 ||
1761       fabs(header->cupsPageSize[1] - expected->cupsPageSize[1]) > 0.001)
1762     printf("    cupsPageSize [%g %g], expected [%g %g]\n",
1763            header->cupsPageSize[0], header->cupsPageSize[1],
1764            expected->cupsPageSize[0], expected->cupsPageSize[1]);
1765 
1766   if (fabs(header->cupsImagingBBox[0] - expected->cupsImagingBBox[0]) > 0.001 ||
1767       fabs(header->cupsImagingBBox[1] - expected->cupsImagingBBox[1]) > 0.001 ||
1768       fabs(header->cupsImagingBBox[2] - expected->cupsImagingBBox[2]) > 0.001 ||
1769       fabs(header->cupsImagingBBox[3] - expected->cupsImagingBBox[3]) > 0.001)
1770     printf("    cupsImagingBBox [%g %g %g %g], expected [%g %g %g %g]\n",
1771            header->cupsImagingBBox[0], header->cupsImagingBBox[1],
1772            header->cupsImagingBBox[2], header->cupsImagingBBox[3],
1773            expected->cupsImagingBBox[0], expected->cupsImagingBBox[1],
1774            expected->cupsImagingBBox[2], expected->cupsImagingBBox[3]);
1775 
1776   for (i = 0; i < 16; i ++)
1777     if (header->cupsInteger[i] != expected->cupsInteger[i])
1778       printf("    cupsInteger%d %d, expected %d\n", i, header->cupsInteger[i],
1779              expected->cupsInteger[i]);
1780 
1781   for (i = 0; i < 16; i ++)
1782     if (fabs(header->cupsReal[i] - expected->cupsReal[i]) > 0.001)
1783       printf("    cupsReal%d %g, expected %g\n", i, header->cupsReal[i],
1784              expected->cupsReal[i]);
1785 
1786   for (i = 0; i < 16; i ++)
1787     if (strcmp(header->cupsString[i], expected->cupsString[i]))
1788       printf("    cupsString%d (%s), expected (%s)\n", i,
1789 	     header->cupsString[i], expected->cupsString[i]);
1790 
1791   if (strcmp(header->cupsMarkerType, expected->cupsMarkerType))
1792     printf("    cupsMarkerType (%s), expected (%s)\n", header->cupsMarkerType,
1793            expected->cupsMarkerType);
1794 
1795   if (strcmp(header->cupsRenderingIntent, expected->cupsRenderingIntent))
1796     printf("    cupsRenderingIntent (%s), expected (%s)\n",
1797            header->cupsRenderingIntent,
1798            expected->cupsRenderingIntent);
1799 
1800   if (strcmp(header->cupsPageSizeName, expected->cupsPageSizeName))
1801     printf("    cupsPageSizeName (%s), expected (%s)\n",
1802            header->cupsPageSizeName,
1803            expected->cupsPageSizeName);
1804 }
1805