]> git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-source.cxx
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / ppdc / ppdc-source.cxx
1 //
2 // Source class for the CUPS PPD Compiler.
3 //
4 // Copyright 2007-2014 by Apple Inc.
5 // Copyright 2002-2007 by Easy Software Products.
6 //
7 // Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8 //
9
10 //
11 // Include necessary headers...
12 //
13
14 #include "ppdc-private.h"
15 #include <limits.h>
16 #include <math.h>
17 #include <unistd.h>
18 #include <cups/raster.h>
19 #include "data/epson.h"
20 #include "data/hp.h"
21 #include "data/label.h"
22 #ifndef WIN32
23 # include <sys/utsname.h>
24 #endif // !WIN32
25
26
27 //
28 // Class globals...
29 //
30
31 ppdcArray *ppdcSource::includes = 0;
32 const char *ppdcSource::driver_types[] =
33 {
34 "custom",
35 "ps",
36 "escp",
37 "pcl",
38 "label",
39 "epson",
40 "hp"
41 };
42
43
44 //
45 // 'ppdcSource::ppdcSource()' - Load a driver source file.
46 //
47
48 ppdcSource::ppdcSource(const char *f, // I - File to read
49 cups_file_t *ffp)// I - File pointer to use
50 : ppdcShared()
51 {
52 PPDC_NEW;
53
54 filename = new ppdcString(f);
55 base_fonts = new ppdcArray();
56 drivers = new ppdcArray();
57 po_files = new ppdcArray();
58 sizes = new ppdcArray();
59 vars = new ppdcArray();
60 cond_state = PPDC_COND_NORMAL;
61 cond_current = cond_stack;
62 cond_stack[0] = PPDC_COND_NORMAL;
63
64 // Add standard #define variables...
65 #define MAKE_STRING(x) #x
66
67 vars->add(new ppdcVariable("CUPS_VERSION", MAKE_STRING(CUPS_VERSION)));
68 vars->add(new ppdcVariable("CUPS_VERSION_MAJOR", MAKE_STRING(CUPS_VERSION_MAJOR)));
69 vars->add(new ppdcVariable("CUPS_VERSION_MINOR", MAKE_STRING(CUPS_VERSION_MINOR)));
70 vars->add(new ppdcVariable("CUPS_VERSION_PATCH", MAKE_STRING(CUPS_VERSION_PATCH)));
71
72 #ifdef WIN32
73 vars->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
74 vars->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
75
76 #else
77 struct utsname name; // uname information
78
79 if (!uname(&name))
80 {
81 vars->add(new ppdcVariable("PLATFORM_NAME", name.sysname));
82 vars->add(new ppdcVariable("PLATFORM_ARCH", name.machine));
83 }
84 else
85 {
86 vars->add(new ppdcVariable("PLATFORM_NAME", "unknown"));
87 vars->add(new ppdcVariable("PLATFORM_ARCH", "unknown"));
88 }
89 #endif // WIN32
90
91 if (f)
92 read_file(f, ffp);
93 }
94
95
96 //
97 // 'ppdcSource::~ppdcSource()' - Free a driver source file.
98 //
99
100 ppdcSource::~ppdcSource()
101 {
102 PPDC_DELETE;
103
104 filename->release();
105 base_fonts->release();
106 drivers->release();
107 po_files->release();
108 sizes->release();
109 vars->release();
110 }
111
112
113 //
114 // 'ppdcSource::add_include()' - Add an include directory.
115 //
116
117 void
118 ppdcSource::add_include(const char *d) // I - Include directory
119 {
120 if (!d)
121 return;
122
123 if (!includes)
124 includes = new ppdcArray();
125
126 includes->add(new ppdcString(d));
127 }
128
129
130 //
131 // 'ppdcSource::find_driver()' - Find a driver.
132 //
133
134 ppdcDriver * // O - Driver
135 ppdcSource::find_driver(const char *f) // I - Driver file name
136 {
137 ppdcDriver *d; // Current driver
138
139
140 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
141 if (!_cups_strcasecmp(f, d->pc_file_name->value))
142 return (d);
143
144 return (NULL);
145 }
146
147
148 //
149 // 'ppdcSource::find_include()' - Find an include file.
150 //
151
152 char * // O - Found path or NULL
153 ppdcSource::find_include(
154 const char *f, // I - Include filename
155 const char *base, // I - Current directory
156 char *n, // I - Path buffer
157 int nlen) // I - Path buffer length
158 {
159 ppdcString *dir; // Include directory
160 char temp[1024], // Temporary path
161 *ptr; // Pointer to end of path
162
163
164 // Range check input...
165 if (!f || !*f || !n || nlen < 2)
166 return (0);
167
168 // Check the first character to see if we have <name> or "name"...
169 if (*f == '<')
170 {
171 // Remove the surrounding <> from the name...
172 strlcpy(temp, f + 1, sizeof(temp));
173 ptr = temp + strlen(temp) - 1;
174
175 if (*ptr != '>')
176 {
177 _cupsLangPrintf(stderr,
178 _("ppdc: Invalid #include/#po filename \"%s\"."), n);
179 return (0);
180 }
181
182 *ptr = '\0';
183 f = temp;
184 }
185 else
186 {
187 // Check for the local file relative to the current directory...
188 if (base && *base && f[0] != '/')
189 snprintf(n, (size_t)nlen, "%s/%s", base, f);
190 else
191 strlcpy(n, f, (size_t)nlen);
192
193 if (!access(n, 0))
194 return (n);
195 else if (*f == '/')
196 {
197 // Absolute path that doesn't exist...
198 return (0);
199 }
200 }
201
202 // Search the include directories, if any...
203 if (includes)
204 {
205 for (dir = (ppdcString *)includes->first(); dir; dir = (ppdcString *)includes->next())
206 {
207 snprintf(n, (size_t)nlen, "%s/%s", dir->value, f);
208 if (!access(n, 0))
209 return (n);
210 }
211 }
212
213 // Search the standard include directories...
214 _cups_globals_t *cg = _cupsGlobals(); // Global data
215
216 snprintf(n, (size_t)nlen, "%s/ppdc/%s", cg->cups_datadir, f);
217 if (!access(n, 0))
218 return (n);
219
220 snprintf(n, (size_t)nlen, "%s/po/%s", cg->cups_datadir, f);
221 if (!access(n, 0))
222 return (n);
223 else
224 return (0);
225 }
226
227
228 //
229 // 'ppdcSource::find_po()' - Find a message catalog for the given locale.
230 //
231
232 ppdcCatalog * // O - Message catalog or NULL
233 ppdcSource::find_po(const char *l) // I - Locale name
234 {
235 ppdcCatalog *cat; // Current message catalog
236
237
238 for (cat = (ppdcCatalog *)po_files->first();
239 cat;
240 cat = (ppdcCatalog *)po_files->next())
241 if (!_cups_strcasecmp(l, cat->locale->value))
242 return (cat);
243
244 return (NULL);
245 }
246
247
248 //
249 // 'ppdcSource::find_size()' - Find a media size.
250 //
251
252 ppdcMediaSize * // O - Size
253 ppdcSource::find_size(const char *s) // I - Size name
254 {
255 ppdcMediaSize *m; // Current media size
256
257
258 for (m = (ppdcMediaSize *)sizes->first(); m; m = (ppdcMediaSize *)sizes->next())
259 if (!_cups_strcasecmp(s, m->name->value))
260 return (m);
261
262 return (NULL);
263 }
264
265
266 //
267 // 'ppdcSource::find_variable()' - Find a variable.
268 //
269
270 ppdcVariable * // O - Variable
271 ppdcSource::find_variable(const char *n)// I - Variable name
272 {
273 ppdcVariable *v; // Current variable
274
275
276 for (v = (ppdcVariable *)vars->first(); v; v = (ppdcVariable *)vars->next())
277 if (!_cups_strcasecmp(n, v->name->value))
278 return (v);
279
280 return (NULL);
281 }
282
283
284 //
285 // 'ppdcSource::get_attr()' - Get an attribute.
286 //
287
288 ppdcAttr * // O - Attribute
289 ppdcSource::get_attr(ppdcFile *fp, // I - File to read
290 bool loc) // I - Localize this attribute?
291 {
292 char name[1024], // Name string
293 selector[1024], // Selector string
294 *text, // Text string
295 value[1024]; // Value string
296
297
298 // Get the attribute parameters:
299 //
300 // Attribute name selector value
301 if (!get_token(fp, name, sizeof(name)))
302 {
303 _cupsLangPrintf(stderr,
304 _("ppdc: Expected name after %s on line %d of %s."),
305 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
306 return (0);
307 }
308
309 if (!get_token(fp, selector, sizeof(selector)))
310 {
311 _cupsLangPrintf(stderr,
312 _("ppdc: Expected selector after %s on line %d of %s."),
313 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
314 return (0);
315 }
316
317 if ((text = strchr(selector, '/')) != NULL)
318 *text++ = '\0';
319
320 if (!get_token(fp, value, sizeof(value)))
321 {
322 _cupsLangPrintf(stderr,
323 _("ppdc: Expected value after %s on line %d of %s."),
324 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
325 return (0);
326 }
327
328 return (new ppdcAttr(name, selector, text, value, loc));
329 }
330
331
332 //
333 // 'ppdcSource::get_boolean()' - Get a boolean value.
334 //
335
336 int // O - Boolean value
337 ppdcSource::get_boolean(ppdcFile *fp) // I - File to read
338 {
339 char buffer[256]; // String buffer
340
341
342 if (!get_token(fp, buffer, sizeof(buffer)))
343 {
344 _cupsLangPrintf(stderr,
345 _("ppdc: Expected boolean value on line %d of %s."),
346 fp->line, fp->filename);
347 return (-1);
348 }
349
350 if (!_cups_strcasecmp(buffer, "on") ||
351 !_cups_strcasecmp(buffer, "yes") ||
352 !_cups_strcasecmp(buffer, "true"))
353 return (1);
354 else if (!_cups_strcasecmp(buffer, "off") ||
355 !_cups_strcasecmp(buffer, "no") ||
356 !_cups_strcasecmp(buffer, "false"))
357 return (0);
358 else
359 {
360 _cupsLangPrintf(stderr,
361 _("ppdc: Bad boolean value (%s) on line %d of %s."),
362 buffer, fp->line, fp->filename);
363 return (-1);
364 }
365 }
366
367
368 //
369 // 'ppdcSource::get_choice()' - Get a choice.
370 //
371
372 ppdcChoice * // O - Choice data
373 ppdcSource::get_choice(ppdcFile *fp) // I - File to read
374 {
375 char name[1024], // Name
376 *text, // Text
377 code[10240]; // Code
378
379
380 // Read a choice from the file:
381 //
382 // Choice name/text code
383 if (!get_token(fp, name, sizeof(name)))
384 {
385 _cupsLangPrintf(stderr,
386 _("ppdc: Expected choice name/text on line %d of %s."),
387 fp->line, fp->filename);
388 return (NULL);
389 }
390
391 if ((text = strchr(name, '/')) != NULL)
392 *text++ = '\0';
393 else
394 text = name;
395
396 if (!get_token(fp, code, sizeof(code)))
397 {
398 _cupsLangPrintf(stderr, _("ppdc: Expected choice code on line %d of %s."),
399 fp->line, fp->filename);
400 return (NULL);
401 }
402
403 // Return the new choice
404 return (new ppdcChoice(name, text, code));
405 }
406
407
408 //
409 // 'ppdcSource::get_color_model()' - Get an old-style color model option.
410 //
411
412 ppdcChoice * // O - Choice data
413 ppdcSource::get_color_model(ppdcFile *fp)
414 // I - File to read
415 {
416 char name[1024], // Option name
417 *text, // Text option
418 temp[256]; // Temporary string
419 int color_space, // Colorspace
420 color_order, // Color order
421 compression; // Compression mode
422
423
424 // Get the ColorModel parameters:
425 //
426 // ColorModel name/text colorspace colororder compression
427 if (!get_token(fp, name, sizeof(name)))
428 {
429 _cupsLangPrintf(stderr,
430 _("ppdc: Expected name/text combination for ColorModel on "
431 "line %d of %s."), fp->line, fp->filename);
432 return (NULL);
433 }
434
435 if ((text = strchr(name, '/')) != NULL)
436 *text++ = '\0';
437 else
438 text = name;
439
440 if (!get_token(fp, temp, sizeof(temp)))
441 {
442 _cupsLangPrintf(stderr,
443 _("ppdc: Expected colorspace for ColorModel on line %d of "
444 "%s."), fp->line, fp->filename);
445 return (NULL);
446 }
447
448 if ((color_space = get_color_space(temp)) < 0)
449 color_space = get_integer(temp);
450
451 if (!get_token(fp, temp, sizeof(temp)))
452 {
453 _cupsLangPrintf(stderr,
454 _("ppdc: Expected color order for ColorModel on line %d of "
455 "%s."), fp->line, fp->filename);
456 return (NULL);
457 }
458
459 if ((color_order = get_color_order(temp)) < 0)
460 color_order = get_integer(temp);
461
462 if (!get_token(fp, temp, sizeof(temp)))
463 {
464 _cupsLangPrintf(stderr,
465 _("ppdc: Expected compression for ColorModel on line %d of "
466 "%s."), fp->line, fp->filename);
467 return (NULL);
468 }
469
470 compression = get_integer(temp);
471
472 snprintf(temp, sizeof(temp),
473 "<</cupsColorSpace %d/cupsColorOrder %d/cupsCompression %d>>"
474 "setpagedevice",
475 color_space, color_order, compression);
476
477 return (new ppdcChoice(name, text, temp));
478 }
479
480
481 //
482 // 'ppdcSource::get_color_order()' - Get an old-style color order value.
483 //
484
485 int // O - Color order value
486 ppdcSource::get_color_order(
487 const char *co) // I - Color order string
488 {
489 if (!_cups_strcasecmp(co, "chunked") ||
490 !_cups_strcasecmp(co, "chunky"))
491 return (CUPS_ORDER_CHUNKED);
492 else if (!_cups_strcasecmp(co, "banded"))
493 return (CUPS_ORDER_BANDED);
494 else if (!_cups_strcasecmp(co, "planar"))
495 return (CUPS_ORDER_PLANAR);
496 else
497 return (-1);
498 }
499
500
501 //
502 // 'ppdcSource::get_color_profile()' - Get a color profile definition.
503 //
504
505 ppdcProfile * // O - Color profile
506 ppdcSource::get_color_profile(
507 ppdcFile *fp) // I - File to read
508 {
509 char resolution[1024], // Resolution/media type
510 *media_type; // Media type
511 int i; // Looping var
512 float g, // Gamma value
513 d, // Density value
514 m[9]; // Transform matrix
515
516
517 // Get the ColorProfile parameters:
518 //
519 // ColorProfile resolution/mediatype gamma density m00 m01 m02 ... m22
520 if (!get_token(fp, resolution, sizeof(resolution)))
521 {
522 _cupsLangPrintf(stderr,
523 _("ppdc: Expected resolution/mediatype following "
524 "ColorProfile on line %d of %s."),
525 fp->line, fp->filename);
526 return (NULL);
527 }
528
529 if ((media_type = strchr(resolution, '/')) != NULL)
530 *media_type++ = '\0';
531 else
532 media_type = resolution;
533
534 g = get_float(fp);
535 d = get_float(fp);
536 for (i = 0; i < 9; i ++)
537 m[i] = get_float(fp);
538
539 return (new ppdcProfile(resolution, media_type, g, d, m));
540 }
541
542
543 //
544 // 'ppdcSource::get_color_space()' - Get an old-style colorspace value.
545 //
546
547 int // O - Colorspace value
548 ppdcSource::get_color_space(
549 const char *cs) // I - Colorspace string
550 {
551 if (!_cups_strcasecmp(cs, "w"))
552 return (CUPS_CSPACE_W);
553 else if (!_cups_strcasecmp(cs, "rgb"))
554 return (CUPS_CSPACE_RGB);
555 else if (!_cups_strcasecmp(cs, "rgba"))
556 return (CUPS_CSPACE_RGBA);
557 else if (!_cups_strcasecmp(cs, "k"))
558 return (CUPS_CSPACE_K);
559 else if (!_cups_strcasecmp(cs, "cmy"))
560 return (CUPS_CSPACE_CMY);
561 else if (!_cups_strcasecmp(cs, "ymc"))
562 return (CUPS_CSPACE_YMC);
563 else if (!_cups_strcasecmp(cs, "cmyk"))
564 return (CUPS_CSPACE_CMYK);
565 else if (!_cups_strcasecmp(cs, "ymck"))
566 return (CUPS_CSPACE_YMCK);
567 else if (!_cups_strcasecmp(cs, "kcmy"))
568 return (CUPS_CSPACE_KCMY);
569 else if (!_cups_strcasecmp(cs, "kcmycm"))
570 return (CUPS_CSPACE_KCMYcm);
571 else if (!_cups_strcasecmp(cs, "gmck"))
572 return (CUPS_CSPACE_GMCK);
573 else if (!_cups_strcasecmp(cs, "gmcs"))
574 return (CUPS_CSPACE_GMCS);
575 else if (!_cups_strcasecmp(cs, "white"))
576 return (CUPS_CSPACE_WHITE);
577 else if (!_cups_strcasecmp(cs, "gold"))
578 return (CUPS_CSPACE_GOLD);
579 else if (!_cups_strcasecmp(cs, "silver"))
580 return (CUPS_CSPACE_SILVER);
581 else if (!_cups_strcasecmp(cs, "CIEXYZ"))
582 return (CUPS_CSPACE_CIEXYZ);
583 else if (!_cups_strcasecmp(cs, "CIELab"))
584 return (CUPS_CSPACE_CIELab);
585 else if (!_cups_strcasecmp(cs, "RGBW"))
586 return (CUPS_CSPACE_RGBW);
587 else if (!_cups_strcasecmp(cs, "ICC1"))
588 return (CUPS_CSPACE_ICC1);
589 else if (!_cups_strcasecmp(cs, "ICC2"))
590 return (CUPS_CSPACE_ICC2);
591 else if (!_cups_strcasecmp(cs, "ICC3"))
592 return (CUPS_CSPACE_ICC3);
593 else if (!_cups_strcasecmp(cs, "ICC4"))
594 return (CUPS_CSPACE_ICC4);
595 else if (!_cups_strcasecmp(cs, "ICC5"))
596 return (CUPS_CSPACE_ICC5);
597 else if (!_cups_strcasecmp(cs, "ICC6"))
598 return (CUPS_CSPACE_ICC6);
599 else if (!_cups_strcasecmp(cs, "ICC7"))
600 return (CUPS_CSPACE_ICC7);
601 else if (!_cups_strcasecmp(cs, "ICC8"))
602 return (CUPS_CSPACE_ICC8);
603 else if (!_cups_strcasecmp(cs, "ICC9"))
604 return (CUPS_CSPACE_ICC9);
605 else if (!_cups_strcasecmp(cs, "ICCA"))
606 return (CUPS_CSPACE_ICCA);
607 else if (!_cups_strcasecmp(cs, "ICCB"))
608 return (CUPS_CSPACE_ICCB);
609 else if (!_cups_strcasecmp(cs, "ICCC"))
610 return (CUPS_CSPACE_ICCC);
611 else if (!_cups_strcasecmp(cs, "ICCD"))
612 return (CUPS_CSPACE_ICCD);
613 else if (!_cups_strcasecmp(cs, "ICCE"))
614 return (CUPS_CSPACE_ICCE);
615 else if (!_cups_strcasecmp(cs, "ICCF"))
616 return (CUPS_CSPACE_ICCF);
617 else
618 return (-1);
619 }
620
621
622 //
623 // 'ppdcSource::get_constraint()' - Get a constraint.
624 //
625
626 ppdcConstraint * // O - Constraint
627 ppdcSource::get_constraint(ppdcFile *fp)// I - File to read
628 {
629 char temp[1024], // One string to rule them all
630 *ptr, // Pointer into string
631 *option1, // Constraint option 1
632 *choice1, // Constraint choice 1
633 *option2, // Constraint option 2
634 *choice2; // Constraint choice 2
635
636
637 // Read the UIConstaints parameter in one of the following forms:
638 //
639 // UIConstraints "*Option1 *Option2"
640 // UIConstraints "*Option1 Choice1 *Option2"
641 // UIConstraints "*Option1 *Option2 Choice2"
642 // UIConstraints "*Option1 Choice1 *Option2 Choice2"
643 if (!get_token(fp, temp, sizeof(temp)))
644 {
645 _cupsLangPrintf(stderr,
646 _("ppdc: Expected constraints string for UIConstraints on "
647 "line %d of %s."), fp->line, fp->filename);
648 return (NULL);
649 }
650
651 for (ptr = temp; isspace(*ptr); ptr ++);
652
653 if (*ptr != '*')
654 {
655 _cupsLangPrintf(stderr,
656 _("ppdc: Option constraint must *name on line %d of %s."),
657 fp->line, fp->filename);
658 return (NULL);
659 }
660
661 option1 = ptr;
662
663 for (; *ptr && !isspace(*ptr); ptr ++);
664 for (; isspace(*ptr); *ptr++ = '\0');
665
666 if (*ptr != '*')
667 {
668 choice1 = ptr;
669
670 for (; *ptr && !isspace(*ptr); ptr ++);
671 for (; isspace(*ptr); *ptr++ = '\0');
672 }
673 else
674 choice1 = NULL;
675
676 if (*ptr != '*')
677 {
678 _cupsLangPrintf(stderr,
679 _("ppdc: Expected two option names on line %d of %s."),
680 fp->line, fp->filename);
681 return (NULL);
682 }
683
684 option2 = ptr;
685
686 for (; *ptr && !isspace(*ptr); ptr ++);
687 for (; isspace(*ptr); *ptr++ = '\0');
688
689 if (*ptr)
690 choice2 = ptr;
691 else
692 choice2 = NULL;
693
694 return (new ppdcConstraint(option1, choice1, option2, choice2));
695 }
696
697
698 //
699 // 'ppdcSource::get_custom_size()' - Get a custom media size definition from a file.
700 //
701
702 ppdcMediaSize * // O - Media size
703 ppdcSource::get_custom_size(ppdcFile *fp)
704 // I - File to read
705 {
706 char name[1024], // Name
707 *text, // Text
708 size_code[10240], // PageSize code
709 region_code[10240]; // PageRegion
710 float width, // Width
711 length, // Length
712 left, // Left margin
713 bottom, // Bottom margin
714 right, // Right margin
715 top; // Top margin
716
717
718 // Get the name, text, width, length, margins, and code:
719 //
720 // CustomMedia name/text width length left bottom right top size-code region-code
721 if (!get_token(fp, name, sizeof(name)))
722 return (NULL);
723
724 if ((text = strchr(name, '/')) != NULL)
725 *text++ = '\0';
726 else
727 text = name;
728
729 if ((width = get_measurement(fp)) < 0.0f)
730 return (NULL);
731
732 if ((length = get_measurement(fp)) < 0.0f)
733 return (NULL);
734
735 if ((left = get_measurement(fp)) < 0.0f)
736 return (NULL);
737
738 if ((bottom = get_measurement(fp)) < 0.0f)
739 return (NULL);
740
741 if ((right = get_measurement(fp)) < 0.0f)
742 return (NULL);
743
744 if ((top = get_measurement(fp)) < 0.0f)
745 return (NULL);
746
747 if (!get_token(fp, size_code, sizeof(size_code)))
748 return (NULL);
749
750 if (!get_token(fp, region_code, sizeof(region_code)))
751 return (NULL);
752
753 // Return the new media size...
754 return (new ppdcMediaSize(name, text, width, length, left, bottom,
755 right, top, size_code, region_code));
756 }
757
758
759 //
760 // 'ppdcSource::get_duplex()' - Get a duplex option.
761 //
762
763 void
764 ppdcSource::get_duplex(ppdcFile *fp, // I - File to read from
765 ppdcDriver *d) // I - Current driver
766 {
767 char temp[256]; // Duplex keyword
768 ppdcAttr *attr; // cupsFlipDuplex attribute
769 ppdcGroup *g; // Current group
770 ppdcOption *o; // Duplex option
771
772
773 // Duplex {boolean|none|normal|flip}
774 if (!get_token(fp, temp, sizeof(temp)))
775 {
776 _cupsLangPrintf(stderr,
777 _("ppdc: Expected duplex type after Duplex on line %d of "
778 "%s."), fp->line, fp->filename);
779 return;
780 }
781
782 if (cond_state)
783 return;
784
785 if (!_cups_strcasecmp(temp, "none") || !_cups_strcasecmp(temp, "false") ||
786 !_cups_strcasecmp(temp, "no") || !_cups_strcasecmp(temp, "off"))
787 {
788 g = d->find_group("General");
789 if ((o = g->find_option("Duplex")) != NULL)
790 g->options->remove(o);
791
792 for (attr = (ppdcAttr *)d->attrs->first();
793 attr;
794 attr = (ppdcAttr *)d->attrs->next())
795 if (!strcmp(attr->name->value, "cupsFlipDuplex"))
796 {
797 d->attrs->remove(attr);
798 break;
799 }
800 }
801 else if (!_cups_strcasecmp(temp, "normal") || !_cups_strcasecmp(temp, "true") ||
802 !_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "on") ||
803 !_cups_strcasecmp(temp, "flip") || !_cups_strcasecmp(temp, "rotated") ||
804 !_cups_strcasecmp(temp, "manualtumble"))
805 {
806 g = d->find_group("General");
807 o = g->find_option("Duplex");
808
809 if (!o)
810 {
811 o = new ppdcOption(PPDC_PICKONE, "Duplex", "2-Sided Printing",
812 !_cups_strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE :
813 PPDC_SECTION_ANY, 10.0f);
814 o->add_choice(new ppdcChoice("None", "Off (1-Sided)",
815 "<</Duplex false>>setpagedevice"));
816 o->add_choice(new ppdcChoice("DuplexNoTumble", "Long-Edge (Portrait)",
817 "<</Duplex true/Tumble false>>setpagedevice"));
818 o->add_choice(new ppdcChoice("DuplexTumble", "Short-Edge (Landscape)",
819 "<</Duplex true/Tumble true>>setpagedevice"));
820
821 g->add_option(o);
822 }
823
824 for (attr = (ppdcAttr *)d->attrs->first();
825 attr;
826 attr = (ppdcAttr *)d->attrs->next())
827 if (!strcmp(attr->name->value, "cupsFlipDuplex"))
828 {
829 if (_cups_strcasecmp(temp, "flip"))
830 d->attrs->remove(attr);
831 break;
832 }
833
834 if (!_cups_strcasecmp(temp, "flip") && !attr)
835 d->add_attr(new ppdcAttr("cupsFlipDuplex", NULL, NULL, "true"));
836
837 for (attr = (ppdcAttr *)d->attrs->first();
838 attr;
839 attr = (ppdcAttr *)d->attrs->next())
840 if (!strcmp(attr->name->value, "cupsBackSide"))
841 {
842 d->attrs->remove(attr);
843 break;
844 }
845
846 if (!_cups_strcasecmp(temp, "flip"))
847 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Flipped"));
848 else if (!_cups_strcasecmp(temp, "rotated"))
849 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Rotated"));
850 else if (!_cups_strcasecmp(temp, "manualtumble"))
851 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "ManualTumble"));
852 else
853 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Normal"));
854 }
855 else
856 _cupsLangPrintf(stderr,
857 _("ppdc: Unknown duplex type \"%s\" on line %d of %s."),
858 temp, fp->line, fp->filename);
859 }
860
861
862 //
863 // 'ppdcSource::get_filter()' - Get a filter.
864 //
865
866 ppdcFilter * // O - Filter
867 ppdcSource::get_filter(ppdcFile *fp) // I - File to read
868 {
869 char type[1024], // MIME type
870 program[1024], // Filter program
871 *ptr; // Pointer into MIME type
872 int cost; // Relative cost
873
874
875 // Read filter parameters in one of the following formats:
876 //
877 // Filter "type cost program"
878 // Filter type cost program
879
880 if (!get_token(fp, type, sizeof(type)))
881 {
882 _cupsLangPrintf(stderr,
883 _("ppdc: Expected a filter definition on line %d of %s."),
884 fp->line, fp->filename);
885 return (NULL);
886 }
887
888 if ((ptr = strchr(type, ' ')) != NULL)
889 {
890 // Old-style filter definition in one string...
891 *ptr++ = '\0';
892 cost = strtol(ptr, &ptr, 10);
893
894 while (isspace(*ptr))
895 ptr ++;
896
897 strlcpy(program, ptr, sizeof(program));
898 }
899 else
900 {
901 cost = get_integer(fp);
902
903 if (!get_token(fp, program, sizeof(program)))
904 {
905 _cupsLangPrintf(stderr,
906 _("ppdc: Expected a program name on line %d of %s."),
907 fp->line, fp->filename);
908 return (NULL);
909 }
910 }
911
912 if (!type[0])
913 {
914 _cupsLangPrintf(stderr,
915 _("ppdc: Invalid empty MIME type for filter on line %d of "
916 "%s."), fp->line, fp->filename);
917 return (NULL);
918 }
919
920 if (cost < 0 || cost > 200)
921 {
922 _cupsLangPrintf(stderr,
923 _("ppdc: Invalid cost for filter on line %d of %s."),
924 fp->line, fp->filename);
925 return (NULL);
926 }
927
928 if (!program[0])
929 {
930 _cupsLangPrintf(stderr,
931 _("ppdc: Invalid empty program name for filter on line %d "
932 "of %s."), fp->line, fp->filename);
933 return (NULL);
934 }
935
936 return (new ppdcFilter(type, program, cost));
937 }
938
939
940 //
941 // 'ppdcSource::get_float()' - Get a single floating-point number.
942 //
943
944 float // O - Number
945 ppdcSource::get_float(ppdcFile *fp) // I - File to read
946 {
947 char temp[256], // String buffer
948 *ptr; // Pointer into buffer
949 float val; // Floating point value
950
951
952 // Get the number from the file and range-check...
953 if (!get_token(fp, temp, sizeof(temp)))
954 {
955 _cupsLangPrintf(stderr, _("ppdc: Expected real number on line %d of %s."),
956 fp->line, fp->filename);
957 return (-1.0f);
958 }
959
960 val = (float)strtod(temp, &ptr);
961
962 if (*ptr)
963 {
964 _cupsLangPrintf(stderr,
965 _("ppdc: Unknown trailing characters in real number \"%s\" "
966 "on line %d of %s."), temp, fp->line, fp->filename);
967 return (-1.0f);
968 }
969 else
970 return (val);
971 }
972
973
974 //
975 // 'ppdcSource::get_font()' - Get a font definition.
976 //
977
978 ppdcFont * // O - Font data
979 ppdcSource::get_font(ppdcFile *fp) // I - File to read
980 {
981 char name[256], // Font name
982 encoding[256], // Font encoding
983 version[256], // Font version
984 charset[256], // Font charset
985 temp[256]; // Font status string
986 ppdcFontStatus status; // Font status enumeration
987
988
989 // Read font parameters as follows:
990 //
991 // Font *
992 // Font name encoding version charset status
993 // %font name encoding version charset status
994 //
995 // "Name" is the PostScript font name.
996 //
997 // "Encoding" is the default encoding of the font: Standard, ISOLatin1,
998 // Special, Expert, ExpertSubset, etc.
999 //
1000 // "Version" is the version number string.
1001 //
1002 // "Charset" specifies the characters that are included in the font:
1003 // Standard, Special, Expert, Adobe-Identity, etc.
1004 //
1005 // "Status" is the keyword ROM or Disk.
1006 if (!get_token(fp, name, sizeof(name)))
1007 {
1008 _cupsLangPrintf(stderr,
1009 _("ppdc: Expected name after Font on line %d of %s."),
1010 fp->line, fp->filename);
1011 return (0);
1012 }
1013
1014 if (!strcmp(name, "*"))
1015 {
1016 // Include all base fonts...
1017 encoding[0] = '\0';
1018 version[0] = '\0';
1019 charset[0] = '\0';
1020 status = PPDC_FONT_ROM;
1021 }
1022 else
1023 {
1024 // Load a full font definition...
1025 if (!get_token(fp, encoding, sizeof(encoding)))
1026 {
1027 _cupsLangPrintf(stderr,
1028 _("ppdc: Expected encoding after Font on line %d of "
1029 "%s."), fp->line, fp->filename);
1030 return (0);
1031 }
1032
1033 if (!get_token(fp, version, sizeof(version)))
1034 {
1035 _cupsLangPrintf(stderr,
1036 _("ppdc: Expected version after Font on line %d of "
1037 "%s."), fp->line, fp->filename);
1038 return (0);
1039 }
1040
1041 if (!get_token(fp, charset, sizeof(charset)))
1042 {
1043 _cupsLangPrintf(stderr,
1044 _("ppdc: Expected charset after Font on line %d of "
1045 "%s."), fp->line, fp->filename);
1046 return (0);
1047 }
1048
1049 if (!get_token(fp, temp, sizeof(temp)))
1050 {
1051 _cupsLangPrintf(stderr,
1052 _("ppdc: Expected status after Font on line %d of %s."),
1053 fp->line, fp->filename);
1054 return (0);
1055 }
1056
1057 if (!_cups_strcasecmp(temp, "ROM"))
1058 status = PPDC_FONT_ROM;
1059 else if (!_cups_strcasecmp(temp, "Disk"))
1060 status = PPDC_FONT_DISK;
1061 else
1062 {
1063 _cupsLangPrintf(stderr,
1064 _("ppdc: Bad status keyword %s on line %d of %s."),
1065 temp, fp->line, fp->filename);
1066 return (0);
1067 }
1068 }
1069
1070 // printf("Font %s %s %s %s %s\n", name, encoding, version, charset, temp);
1071
1072 return (new ppdcFont(name, encoding, version, charset, status));
1073 }
1074
1075
1076 //
1077 // 'ppdcSource::get_generic()' - Get a generic old-style option.
1078 //
1079
1080 ppdcChoice * // O - Choice data
1081 ppdcSource::get_generic(ppdcFile *fp, // I - File to read
1082 const char *keyword,
1083 // I - Keyword name
1084 const char *tattr,
1085 // I - Text attribute
1086 const char *nattr)
1087 // I - Numeric attribute
1088 {
1089 char name[1024], // Name
1090 *text, // Text
1091 command[256]; // Command string
1092 int val; // Numeric value
1093
1094
1095 // Read one of the following parameters:
1096 //
1097 // Foo name/text
1098 // Foo integer name/text
1099 if (nattr)
1100 val = get_integer(fp);
1101 else
1102 val = 0;
1103
1104 if (!get_token(fp, name, sizeof(name)))
1105 {
1106 _cupsLangPrintf(stderr,
1107 _("ppdc: Expected name/text after %s on line %d of %s."),
1108 keyword, fp->line, fp->filename);
1109 return (NULL);
1110 }
1111
1112 if ((text = strchr(name, '/')) != NULL)
1113 *text++ = '\0';
1114 else
1115 text = name;
1116
1117 if (nattr)
1118 {
1119 if (tattr)
1120 snprintf(command, sizeof(command),
1121 "<</%s(%s)/%s %d>>setpagedevice",
1122 tattr, name, nattr, val);
1123 else
1124 snprintf(command, sizeof(command),
1125 "<</%s %d>>setpagedevice",
1126 nattr, val);
1127 }
1128 else
1129 snprintf(command, sizeof(command),
1130 "<</%s(%s)>>setpagedevice",
1131 tattr, name);
1132
1133 return (new ppdcChoice(name, text, command));
1134 }
1135
1136
1137 //
1138 // 'ppdcSource::get_group()' - Get an option group.
1139 //
1140
1141 ppdcGroup * // O - Group
1142 ppdcSource::get_group(ppdcFile *fp, // I - File to read
1143 ppdcDriver *d) // I - Printer driver
1144 {
1145 char name[1024], // UI name
1146 *text; // UI text
1147 ppdcGroup *g; // Group
1148
1149
1150 // Read the Group parameters:
1151 //
1152 // Group name/text
1153 if (!get_token(fp, name, sizeof(name)))
1154 {
1155 _cupsLangPrintf(stderr,
1156 _("ppdc: Expected group name/text on line %d of %s."),
1157 fp->line, fp->filename);
1158 return (NULL);
1159 }
1160
1161 if ((text = strchr(name, '/')) != NULL)
1162 *text++ = '\0';
1163 else
1164 text = name;
1165
1166 // See if the group already exists...
1167 if ((g = d->find_group(name)) == NULL)
1168 {
1169 // Nope, add a new one...
1170 g = new ppdcGroup(name, text);
1171 }
1172
1173 return (g);
1174 }
1175
1176
1177 //
1178 // 'ppdcSource::get_installable()' - Get an installable option.
1179 //
1180
1181 ppdcOption * // O - Option
1182 ppdcSource::get_installable(ppdcFile *fp)
1183 // I - File to read
1184 {
1185 char name[1024], // Name for installable option
1186 *text; // Text for installable option
1187 ppdcOption *o; // Option
1188
1189
1190 // Read the parameter for an installable option:
1191 //
1192 // Installable name/text
1193 if (!get_token(fp, name, sizeof(name)))
1194 {
1195 _cupsLangPrintf(stderr,
1196 _("ppdc: Expected name/text after Installable on line %d "
1197 "of %s."), fp->line, fp->filename);
1198 return (NULL);
1199 }
1200
1201 if ((text = strchr(name, '/')) != NULL)
1202 *text++ = '\0';
1203 else
1204 text = name;
1205
1206 // Create the option...
1207 o = new ppdcOption(PPDC_BOOLEAN, name, text, PPDC_SECTION_ANY, 10.0f);
1208
1209 // Add the false and true choices...
1210 o->add_choice(new ppdcChoice("False", "Not Installed", ""));
1211 o->add_choice(new ppdcChoice("True", "Installed", ""));
1212
1213 return (o);
1214 }
1215
1216
1217 //
1218 // 'ppdcSource::get_integer()' - Get an integer value from a string.
1219 //
1220
1221 #define PPDC_XX -1 // Bad
1222 #define PPDC_EQ 0 // ==
1223 #define PPDC_NE 1 // !=
1224 #define PPDC_LT 2 // <
1225 #define PPDC_LE 3 // <=
1226 #define PPDC_GT 4 // >
1227 #define PPDC_GE 5 // >=
1228
1229 int // O - Integer value
1230 ppdcSource::get_integer(const char *v) // I - Value string
1231 {
1232 long val; // Value
1233 long temp, // Temporary value
1234 temp2; // Second temporary value
1235 char *newv, // New value string pointer
1236 ch; // Temporary character
1237 ppdcVariable *var; // #define variable
1238 int compop; // Comparison operator
1239
1240
1241 // Parse the value string...
1242 if (!v)
1243 return (-1);
1244
1245 if (isdigit(*v & 255) || *v == '-' || *v == '+')
1246 {
1247 // Return a simple integer value
1248 val = strtol(v, (char **)&v, 0);
1249 if (*v || val == LONG_MIN)
1250 return (-1);
1251 else
1252 return ((int)val);
1253 }
1254 else if (*v == '(')
1255 {
1256 // Evaluate and expression in any of the following formats:
1257 //
1258 // (number number ... number) Bitwise OR of all numbers
1259 // (NAME == value) 1 if equal, 0 otherwise
1260 // (NAME != value) 1 if not equal, 0 otherwise
1261 // (NAME < value) 1 if less than, 0 otherwise
1262 // (NAME <= value) 1 if less than or equal, 0 otherwise
1263 // (NAME > value) 1 if greater than, 0 otherwise
1264 // (NAME >= value) 1 if greater than or equal, 0 otherwise
1265
1266 v ++;
1267 val = 0;
1268
1269 while (*v && *v != ')')
1270 {
1271 // Skip leading whitespace...
1272 while (*v && isspace(*v & 255))
1273 v ++;
1274
1275 if (!*v || *v == ')')
1276 break;
1277
1278 if (isdigit(*v & 255) || *v == '-' || *v == '+')
1279 {
1280 // Bitwise OR a number...
1281 temp = strtol(v, &newv, 0);
1282
1283 if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
1284 temp == LONG_MIN)
1285 return (-1);
1286 }
1287 else
1288 {
1289 // NAME logicop value
1290 for (newv = (char *)v + 1;
1291 *newv && (isalnum(*newv & 255) || *newv == '_');
1292 newv ++)
1293 /* do nothing */;
1294
1295 ch = *newv;
1296 *newv = '\0';
1297
1298 if ((var = find_variable(v)) != NULL)
1299 {
1300 if (!var->value || !var->value->value || !var->value->value[0])
1301 temp = 0;
1302 else if (isdigit(var->value->value[0] & 255) ||
1303 var->value->value[0] == '-' ||
1304 var->value->value[0] == '+')
1305 temp = strtol(var->value->value, NULL, 0);
1306 else
1307 temp = 1;
1308 }
1309 else
1310 temp = 0;
1311
1312 *newv = ch;
1313 while (isspace(*newv & 255))
1314 newv ++;
1315
1316 if (!strncmp(newv, "==", 2))
1317 {
1318 compop = PPDC_EQ;
1319 newv += 2;
1320 }
1321 else if (!strncmp(newv, "!=", 2))
1322 {
1323 compop = PPDC_NE;
1324 newv += 2;
1325 }
1326 else if (!strncmp(newv, "<=", 2))
1327 {
1328 compop = PPDC_LE;
1329 newv += 2;
1330 }
1331 else if (*newv == '<')
1332 {
1333 compop = PPDC_LT;
1334 newv ++;
1335 }
1336 else if (!strncmp(newv, ">=", 2))
1337 {
1338 compop = PPDC_GE;
1339 newv += 2;
1340 }
1341 else if (*newv == '>')
1342 {
1343 compop = PPDC_GT;
1344 newv ++;
1345 }
1346 else
1347 compop = PPDC_XX;
1348
1349 if (compop != PPDC_XX)
1350 {
1351 while (isspace(*newv & 255))
1352 newv ++;
1353
1354 if (*newv == ')' || !*newv)
1355 return (-1);
1356
1357 if (isdigit(*newv & 255) || *newv == '-' || *newv == '+')
1358 {
1359 // Get the second number...
1360 temp2 = strtol(newv, &newv, 0);
1361 if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
1362 temp == LONG_MIN)
1363 return (-1);
1364 }
1365 else
1366 {
1367 // Lookup the second name...
1368 for (v = newv, newv ++;
1369 *newv && (isalnum(*newv & 255) || *newv == '_');
1370 newv ++);
1371
1372 ch = *newv;
1373 *newv = '\0';
1374
1375 if ((var = find_variable(v)) != NULL)
1376 {
1377 if (!var->value || !var->value->value || !var->value->value[0])
1378 temp2 = 0;
1379 else if (isdigit(var->value->value[0] & 255) ||
1380 var->value->value[0] == '-' ||
1381 var->value->value[0] == '+')
1382 temp2 = strtol(var->value->value, NULL, 0);
1383 else
1384 temp2 = 1;
1385 }
1386 else
1387 temp2 = 0;
1388
1389 *newv = ch;
1390 }
1391
1392 // Do the comparison...
1393 switch (compop)
1394 {
1395 case PPDC_EQ :
1396 temp = temp == temp2;
1397 break;
1398 case PPDC_NE :
1399 temp = temp != temp2;
1400 break;
1401 case PPDC_LT :
1402 temp = temp < temp2;
1403 break;
1404 case PPDC_LE :
1405 temp = temp <= temp2;
1406 break;
1407 case PPDC_GT :
1408 temp = temp > temp2;
1409 break;
1410 case PPDC_GE :
1411 temp = temp >= temp2;
1412 break;
1413 }
1414 }
1415 }
1416
1417 val |= temp;
1418 v = newv;
1419 }
1420
1421 if (*v == ')' && !v[1])
1422 return ((int)val);
1423 else
1424 return (-1);
1425 }
1426 else if ((var = find_variable(v)) != NULL)
1427 {
1428 // NAME by itself returns 1 if the #define variable is not blank and
1429 // not "0"...
1430 return (var->value->value && var->value->value[0] &&
1431 strcmp(var->value->value, "0"));
1432 }
1433 else
1434 {
1435 // Anything else is an error...
1436 return (-1);
1437 }
1438 }
1439
1440
1441 //
1442 // 'ppdcSource::get_integer()' - Get an integer value from a file.
1443 //
1444
1445 int // O - Integer value
1446 ppdcSource::get_integer(ppdcFile *fp) // I - File to read
1447 {
1448 char temp[1024]; // String buffer
1449
1450
1451 if (!get_token(fp, temp, sizeof(temp)))
1452 {
1453 _cupsLangPrintf(stderr, _("ppdc: Expected integer on line %d of %s."),
1454 fp->line, fp->filename);
1455 return (-1);
1456 }
1457 else
1458 return (get_integer(temp));
1459 }
1460
1461
1462 //
1463 // 'ppdcSource::get_measurement()' - Get a measurement value.
1464 //
1465
1466 float // O - Measurement value in points
1467 ppdcSource::get_measurement(ppdcFile *fp)
1468 // I - File to read
1469 {
1470 char buffer[256], // Number buffer
1471 *ptr; // Pointer into buffer
1472 float val; // Measurement value
1473
1474
1475 // Grab a token from the file...
1476 if (!get_token(fp, buffer, sizeof(buffer)))
1477 return (-1.0f);
1478
1479 // Get the floating point value of "s" and skip all digits and decimal points.
1480 val = (float)strtod(buffer, &ptr);
1481
1482 // Check for a trailing unit specifier...
1483 if (!_cups_strcasecmp(ptr, "mm"))
1484 val *= 72.0f / 25.4f;
1485 else if (!_cups_strcasecmp(ptr, "cm"))
1486 val *= 72.0f / 2.54f;
1487 else if (!_cups_strcasecmp(ptr, "m"))
1488 val *= 72.0f / 0.0254f;
1489 else if (!_cups_strcasecmp(ptr, "in"))
1490 val *= 72.0f;
1491 else if (!_cups_strcasecmp(ptr, "ft"))
1492 val *= 72.0f * 12.0f;
1493 else if (_cups_strcasecmp(ptr, "pt") && *ptr)
1494 return (-1.0f);
1495
1496 return (val);
1497 }
1498
1499
1500 //
1501 // 'ppdcSource::get_option()' - Get an option definition.
1502 //
1503
1504 ppdcOption * // O - Option
1505 ppdcSource::get_option(ppdcFile *fp, // I - File to read
1506 ppdcDriver *d, // I - Printer driver
1507 ppdcGroup *g) // I - Current group
1508 {
1509 char name[1024], // UI name
1510 *text, // UI text
1511 type[256]; // UI type string
1512 ppdcOptType ot; // Option type value
1513 ppdcOptSection section; // Option section
1514 float order; // Option order
1515 ppdcOption *o; // Option
1516 ppdcGroup *mg; // Matching group, if any
1517
1518
1519 // Read the Option parameters:
1520 //
1521 // Option name/text type section order
1522 if (!get_token(fp, name, sizeof(name)))
1523 {
1524 _cupsLangPrintf(stderr,
1525 _("ppdc: Expected option name/text on line %d of %s."),
1526 fp->line, fp->filename);
1527 return (NULL);
1528 }
1529
1530 if ((text = strchr(name, '/')) != NULL)
1531 *text++ = '\0';
1532 else
1533 text = name;
1534
1535 if (!get_token(fp, type, sizeof(type)))
1536 {
1537 _cupsLangPrintf(stderr, _("ppdc: Expected option type on line %d of %s."),
1538 fp->line, fp->filename);
1539 return (NULL);
1540 }
1541
1542 if (!_cups_strcasecmp(type, "boolean"))
1543 ot = PPDC_BOOLEAN;
1544 else if (!_cups_strcasecmp(type, "pickone"))
1545 ot = PPDC_PICKONE;
1546 else if (!_cups_strcasecmp(type, "pickmany"))
1547 ot = PPDC_PICKMANY;
1548 else
1549 {
1550 _cupsLangPrintf(stderr,
1551 _("ppdc: Invalid option type \"%s\" on line %d of %s."),
1552 type, fp->line, fp->filename);
1553 return (NULL);
1554 }
1555
1556 if (!get_token(fp, type, sizeof(type)))
1557 {
1558 _cupsLangPrintf(stderr,
1559 _("ppdc: Expected option section on line %d of %s."),
1560 fp->line, fp->filename);
1561 return (NULL);
1562 }
1563
1564 if (!_cups_strcasecmp(type, "AnySetup"))
1565 section = PPDC_SECTION_ANY;
1566 else if (!_cups_strcasecmp(type, "DocumentSetup"))
1567 section = PPDC_SECTION_DOCUMENT;
1568 else if (!_cups_strcasecmp(type, "ExitServer"))
1569 section = PPDC_SECTION_EXIT;
1570 else if (!_cups_strcasecmp(type, "JCLSetup"))
1571 section = PPDC_SECTION_JCL;
1572 else if (!_cups_strcasecmp(type, "PageSetup"))
1573 section = PPDC_SECTION_PAGE;
1574 else if (!_cups_strcasecmp(type, "Prolog"))
1575 section = PPDC_SECTION_PROLOG;
1576 else
1577 {
1578 _cupsLangPrintf(stderr,
1579 _("ppdc: Invalid option section \"%s\" on line %d of "
1580 "%s."), type, fp->line, fp->filename);
1581 return (NULL);
1582 }
1583
1584 order = get_float(fp);
1585
1586 // See if the option already exists...
1587 if ((o = d->find_option_group(name, &mg)) == NULL)
1588 {
1589 // Nope, add a new one...
1590 o = new ppdcOption(ot, name, text, section, order);
1591 }
1592 else if (o->type != ot)
1593 {
1594 _cupsLangPrintf(stderr,
1595 _("ppdc: Option %s redefined with a different type on line "
1596 "%d of %s."), name, fp->line, fp->filename);
1597 return (NULL);
1598 }
1599 else if (g != mg)
1600 {
1601 _cupsLangPrintf(stderr,
1602 _("ppdc: Option %s defined in two different groups on line "
1603 "%d of %s."), name, fp->line, fp->filename);
1604 return (NULL);
1605 }
1606
1607 return (o);
1608 }
1609
1610
1611 //
1612 // 'ppdcSource::get_po()' - Get a message catalog.
1613 //
1614
1615 ppdcCatalog * // O - Message catalog
1616 ppdcSource::get_po(ppdcFile *fp) // I - File to read
1617 {
1618 char locale[32], // Locale name
1619 poname[1024], // Message catalog filename
1620 basedir[1024], // Base directory
1621 *baseptr, // Pointer into directory
1622 pofilename[1024]; // Full filename of message catalog
1623 ppdcCatalog *cat; // Message catalog
1624
1625
1626 // Read the #po parameters:
1627 //
1628 // #po locale "filename.po"
1629 if (!get_token(fp, locale, sizeof(locale)))
1630 {
1631 _cupsLangPrintf(stderr,
1632 _("ppdc: Expected locale after #po on line %d of %s."),
1633 fp->line, fp->filename);
1634 return (NULL);
1635 }
1636
1637 if (!get_token(fp, poname, sizeof(poname)))
1638 {
1639 _cupsLangPrintf(stderr,
1640 _("ppdc: Expected filename after #po %s on line %d of "
1641 "%s."), locale, fp->line, fp->filename);
1642 return (NULL);
1643 }
1644
1645 // See if the locale is already loaded...
1646 if (find_po(locale))
1647 {
1648 _cupsLangPrintf(stderr,
1649 _("ppdc: Duplicate #po for locale %s on line %d of %s."),
1650 locale, fp->line, fp->filename);
1651 return (NULL);
1652 }
1653
1654 // Figure out the current directory...
1655 strlcpy(basedir, fp->filename, sizeof(basedir));
1656
1657 if ((baseptr = strrchr(basedir, '/')) != NULL)
1658 *baseptr = '\0';
1659 else
1660 strlcpy(basedir, ".", sizeof(basedir));
1661
1662 // Find the po file...
1663 pofilename[0] = '\0';
1664
1665 if (!poname[0] ||
1666 find_include(poname, basedir, pofilename, sizeof(pofilename)))
1667 {
1668 // Found it, so load it...
1669 cat = new ppdcCatalog(locale, pofilename);
1670
1671 // Reset the filename to the name supplied by the user...
1672 cat->filename->release();
1673 cat->filename = new ppdcString(poname);
1674
1675 // Return the catalog...
1676 return (cat);
1677 }
1678 else
1679 {
1680 _cupsLangPrintf(stderr,
1681 _("ppdc: Unable to find #po file %s on line %d of %s."),
1682 poname, fp->line, fp->filename);
1683 return (NULL);
1684 }
1685 }
1686
1687
1688 //
1689 // 'ppdcSource::get_resolution()' - Get an old-style resolution option.
1690 //
1691
1692 ppdcChoice * // O - Choice data
1693 ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
1694 {
1695 char name[1024], // Name
1696 *text, // Text
1697 temp[256], // Temporary string
1698 command[256], // Command string
1699 *commptr; // Pointer into command
1700 int xdpi, ydpi, // X + Y resolution
1701 color_order, // Color order
1702 color_space, // Colorspace
1703 compression, // Compression mode
1704 depth, // Bits per color
1705 row_count, // Row count
1706 row_feed, // Row feed
1707 row_step; // Row step/interval
1708
1709
1710 // Read the resolution parameters:
1711 //
1712 // Resolution colorspace bits row-count row-feed row-step name/text
1713 if (!get_token(fp, temp, sizeof(temp)))
1714 {
1715 _cupsLangPrintf(stderr,
1716 _("ppdc: Expected override field after Resolution on line "
1717 "%d of %s."), fp->line, fp->filename);
1718 return (NULL);
1719 }
1720
1721 color_order = get_color_order(temp);
1722 color_space = get_color_space(temp);
1723 compression = get_integer(temp);
1724
1725 depth = get_integer(fp);
1726 row_count = get_integer(fp);
1727 row_feed = get_integer(fp);
1728 row_step = get_integer(fp);
1729
1730 if (!get_token(fp, name, sizeof(name)))
1731 {
1732 _cupsLangPrintf(stderr,
1733 _("ppdc: Expected name/text after Resolution on line %d of "
1734 "%s."), fp->line, fp->filename);
1735 return (NULL);
1736 }
1737
1738 if ((text = strchr(name, '/')) != NULL)
1739 *text++ = '\0';
1740 else
1741 text = name;
1742
1743 switch (sscanf(name, "%dx%d", &xdpi, &ydpi))
1744 {
1745 case 0 :
1746 _cupsLangPrintf(stderr,
1747 _("ppdc: Bad resolution name \"%s\" on line %d of "
1748 "%s."), name, fp->line, fp->filename);
1749 break;
1750 case 1 :
1751 ydpi = xdpi;
1752 break;
1753 }
1754
1755 // Create the necessary PS commands...
1756 snprintf(command, sizeof(command),
1757 "<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d"
1758 "/cupsRowFeed %d/cupsRowStep %d",
1759 xdpi, ydpi, depth, row_count, row_feed, row_step);
1760 commptr = command + strlen(command);
1761
1762 if (color_order >= 0)
1763 {
1764 snprintf(commptr, sizeof(command) - (size_t)(commptr - command),
1765 "/cupsColorOrder %d", color_order);
1766 commptr += strlen(commptr);
1767 }
1768
1769 if (color_space >= 0)
1770 {
1771 snprintf(commptr, sizeof(command) - (size_t)(commptr - command),
1772 "/cupsColorSpace %d", color_space);
1773 commptr += strlen(commptr);
1774 }
1775
1776 if (compression >= 0)
1777 {
1778 snprintf(commptr, sizeof(command) - (size_t)(commptr - command),
1779 "/cupsCompression %d", compression);
1780 commptr += strlen(commptr);
1781 }
1782
1783 snprintf(commptr, sizeof(command) - (size_t)(commptr - command), ">>setpagedevice");
1784
1785 // Return the new choice...
1786 return (new ppdcChoice(name, text, command));
1787 }
1788
1789
1790 //
1791 // 'ppdcSource::get_simple_profile()' - Get a simple color profile definition.
1792 //
1793
1794 ppdcProfile * // O - Color profile
1795 ppdcSource::get_simple_profile(ppdcFile *fp)
1796 // I - File to read
1797 {
1798 char resolution[1024], // Resolution/media type
1799 *media_type; // Media type
1800 float m[9]; // Transform matrix
1801 float kd, rd, g; // Densities and gamma
1802 float red, green, blue; // RGB adjustments
1803 float yellow; // Yellow density
1804 float color; // Color density values
1805
1806
1807 // Get the SimpleColorProfile parameters:
1808 //
1809 // SimpleColorProfile resolution/mediatype black-density yellow-density
1810 // red-density gamma red-adjust green-adjust blue-adjust
1811 if (!get_token(fp, resolution, sizeof(resolution)))
1812 {
1813 _cupsLangPrintf(stderr,
1814 _("ppdc: Expected resolution/mediatype following "
1815 "SimpleColorProfile on line %d of %s."),
1816 fp->line, fp->filename);
1817 return (NULL);
1818 }
1819
1820 if ((media_type = strchr(resolution, '/')) != NULL)
1821 *media_type++ = '\0';
1822 else
1823 media_type = resolution;
1824
1825 // Collect the profile parameters...
1826 kd = get_float(fp);
1827 yellow = get_float(fp);
1828 rd = get_float(fp);
1829 g = get_float(fp);
1830 red = get_float(fp);
1831 green = get_float(fp);
1832 blue = get_float(fp);
1833
1834 // Build the color profile...
1835 color = 0.5f * rd / kd - kd;
1836 m[0] = 1.0f; // C
1837 m[1] = color + blue; // C + M (blue)
1838 m[2] = color - green; // C + Y (green)
1839 m[3] = color - blue; // M + C (blue)
1840 m[4] = 1.0f; // M
1841 m[5] = color + red; // M + Y (red)
1842 m[6] = yellow * (color + green); // Y + C (green)
1843 m[7] = yellow * (color - red); // Y + M (red)
1844 m[8] = yellow; // Y
1845
1846 if (m[1] > 0.0f)
1847 {
1848 m[3] -= m[1];
1849 m[1] = 0.0f;
1850 }
1851 else if (m[3] > 0.0f)
1852 {
1853 m[1] -= m[3];
1854 m[3] = 0.0f;
1855 }
1856
1857 if (m[2] > 0.0f)
1858 {
1859 m[6] -= m[2];
1860 m[2] = 0.0f;
1861 }
1862 else if (m[6] > 0.0f)
1863 {
1864 m[2] -= m[6];
1865 m[6] = 0.0f;
1866 }
1867
1868 if (m[5] > 0.0f)
1869 {
1870 m[7] -= m[5];
1871 m[5] = 0.0f;
1872 }
1873 else if (m[7] > 0.0f)
1874 {
1875 m[5] -= m[7];
1876 m[7] = 0.0f;
1877 }
1878
1879 // Return the new profile...
1880 return (new ppdcProfile(resolution, media_type, g, kd, m));
1881 }
1882
1883
1884 //
1885 // 'ppdcSource::get_size()' - Get a media size definition from a file.
1886 //
1887
1888 ppdcMediaSize * // O - Media size
1889 ppdcSource::get_size(ppdcFile *fp) // I - File to read
1890 {
1891 char name[1024], // Name
1892 *text; // Text
1893 float width, // Width
1894 length; // Length
1895
1896
1897 // Get the name, text, width, and length:
1898 //
1899 // #media name/text width length
1900 if (!get_token(fp, name, sizeof(name)))
1901 return (NULL);
1902
1903 if ((text = strchr(name, '/')) != NULL)
1904 *text++ = '\0';
1905 else
1906 text = name;
1907
1908 if ((width = get_measurement(fp)) < 0.0f)
1909 return (NULL);
1910
1911 if ((length = get_measurement(fp)) < 0.0f)
1912 return (NULL);
1913
1914 // Return the new media size...
1915 return (new ppdcMediaSize(name, text, width, length, 0.0f, 0.0f, 0.0f, 0.0f));
1916 }
1917
1918
1919 //
1920 // 'ppdcSource::get_token()' - Get a token from a file.
1921 //
1922
1923 char * // O - Token string or NULL
1924 ppdcSource::get_token(ppdcFile *fp, // I - File to read
1925 char *buffer, // I - Buffer
1926 int buflen) // I - Length of buffer
1927 {
1928 char *bufptr, // Pointer into string buffer
1929 *bufend; // End of string buffer
1930 int ch, // Character from file
1931 nextch, // Next char in file
1932 quote, // Quote character used...
1933 empty, // Empty input?
1934 startline; // Start line for quote
1935 char name[256], // Name string
1936 *nameptr; // Name pointer
1937 ppdcVariable *var; // Variable pointer
1938
1939
1940 // Mark the beginning and end of the buffer...
1941 bufptr = buffer;
1942 bufend = buffer + buflen - 1;
1943
1944 // Loop intil we've read a token...
1945 quote = 0;
1946 startline = 0;
1947 empty = 1;
1948
1949 while ((ch = fp->get()) != EOF)
1950 {
1951 if (isspace(ch) && !quote)
1952 {
1953 if (empty)
1954 continue;
1955 else
1956 break;
1957 }
1958 else if (ch == '$')
1959 {
1960 // Variable substitution
1961 empty = 0;
1962
1963 for (nameptr = name; (ch = fp->peek()) != EOF;)
1964 {
1965 if (!isalnum(ch) && ch != '_')
1966 break;
1967 else if (nameptr < (name + sizeof(name) - 1))
1968 *nameptr++ = (char)fp->get();
1969 }
1970
1971 if (nameptr == name)
1972 {
1973 // Just substitute this character...
1974 if (ch == '$')
1975 {
1976 // $$ = $
1977 if (bufptr < bufend)
1978 *bufptr++ = (char)fp->get();
1979 }
1980 else
1981 {
1982 // $ch = $ch
1983 _cupsLangPrintf(stderr,
1984 _("ppdc: Bad variable substitution ($%c) on line %d "
1985 "of %s."), ch, fp->line, fp->filename);
1986
1987 if (bufptr < bufend)
1988 *bufptr++ = '$';
1989 }
1990 }
1991 else
1992 {
1993 // Substitute the variable value...
1994 *nameptr = '\0';
1995 var = find_variable(name);
1996 if (var)
1997 {
1998 strlcpy(bufptr, var->value->value, (size_t)(bufend - bufptr + 1));
1999 bufptr += strlen(bufptr);
2000 }
2001 else
2002 {
2003 if (!(cond_state & PPDC_COND_SKIP))
2004 _cupsLangPrintf(stderr,
2005 _("ppdc: Undefined variable (%s) on line %d of "
2006 "%s."), name, fp->line, fp->filename);
2007
2008 snprintf(bufptr, (size_t)(bufend - bufptr + 1), "$%s", name);
2009 bufptr += strlen(bufptr);
2010 }
2011 }
2012 }
2013 else if (ch == '/' && !quote)
2014 {
2015 // Possibly a comment...
2016 nextch = fp->peek();
2017
2018 if (nextch == '*')
2019 {
2020 // C comment...
2021 fp->get();
2022 ch = fp->get();
2023 while ((nextch = fp->get()) != EOF)
2024 {
2025 if (ch == '*' && nextch == '/')
2026 break;
2027
2028 ch = nextch;
2029 }
2030
2031 if (nextch == EOF)
2032 break;
2033 }
2034 else if (nextch == '/')
2035 {
2036 // C++ comment...
2037 while ((nextch = fp->get()) != EOF)
2038 if (nextch == '\n')
2039 break;
2040
2041 if (nextch == EOF)
2042 break;
2043 }
2044 else
2045 {
2046 // Not a comment...
2047 empty = 0;
2048
2049 if (bufptr < bufend)
2050 *bufptr++ = (char)ch;
2051 }
2052 }
2053 else if (ch == '\'' || ch == '\"')
2054 {
2055 empty = 0;
2056
2057 if (quote == ch)
2058 {
2059 // Ending the current quoted string...
2060 quote = 0;
2061 }
2062 else if (quote)
2063 {
2064 // Insert the opposing quote char...
2065 if (bufptr < bufend)
2066 *bufptr++ = (char)ch;
2067 }
2068 else
2069 {
2070 // Start a new quoted string...
2071 startline = fp->line;
2072 quote = ch;
2073 }
2074 }
2075 else if ((ch == '(' || ch == '<') && !quote)
2076 {
2077 empty = 0;
2078 quote = ch;
2079 startline = fp->line;
2080
2081 if (bufptr < bufend)
2082 *bufptr++ = (char)ch;
2083 }
2084 else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<'))
2085 {
2086 quote = 0;
2087
2088 if (bufptr < bufend)
2089 *bufptr++ = (char)ch;
2090 }
2091 else if (ch == '\\')
2092 {
2093 empty = 0;
2094
2095 if ((ch = fp->get()) == EOF)
2096 break;
2097
2098 if (bufptr < bufend)
2099 *bufptr++ = (char)ch;
2100 }
2101 else if (bufptr < bufend)
2102 {
2103 empty = 0;
2104
2105 *bufptr++ = (char)ch;
2106
2107 if ((ch == '{' || ch == '}') && !quote)
2108 break;
2109 }
2110 }
2111
2112 if (quote)
2113 {
2114 _cupsLangPrintf(stderr,
2115 _("ppdc: Unterminated string starting with %c on line %d "
2116 "of %s."), quote, startline, fp->filename);
2117 return (NULL);
2118 }
2119
2120 if (empty)
2121 return (NULL);
2122 else
2123 {
2124 *bufptr = '\0';
2125 return (buffer);
2126 }
2127 }
2128
2129
2130 //
2131 // 'ppdcSource::get_variable()' - Get a variable definition.
2132 //
2133
2134 ppdcVariable * // O - Variable
2135 ppdcSource::get_variable(ppdcFile *fp) // I - File to read
2136 {
2137 char name[1024], // Name
2138 value[1024]; // Value
2139
2140
2141 // Get the name and value:
2142 //
2143 // #define name value
2144 if (!get_token(fp, name, sizeof(name)))
2145 return (NULL);
2146
2147 if (!get_token(fp, value, sizeof(value)))
2148 return (NULL);
2149
2150 // Set the variable...
2151 return (set_variable(name, value));
2152 }
2153
2154
2155 //
2156 // 'ppdcSource::quotef()' - Write a formatted, quoted string...
2157 //
2158
2159 int // O - Number bytes on success, -1 on failure
2160 ppdcSource::quotef(cups_file_t *fp, // I - File to write to
2161 const char *format, // I - Printf-style format string
2162 ...) // I - Additional args as needed
2163 {
2164 va_list ap; // Pointer to additional arguments
2165 int bytes; // Bytes written
2166 char sign, // Sign of format width
2167 size, // Size character (h, l, L)
2168 type; // Format type character
2169 const char *bufformat; // Start of format
2170 int width, // Width of field
2171 prec; // Number of characters of precision
2172 char tformat[100]; // Temporary format string for fprintf()
2173 char *s; // Pointer to string
2174 int slen; // Length of string
2175 int i; // Looping var
2176
2177
2178 // Range check input...
2179 if (!fp || !format)
2180 return (-1);
2181
2182 // Loop through the format string, formatting as needed...
2183 va_start(ap, format);
2184
2185 bytes = 0;
2186
2187 while (*format)
2188 {
2189 if (*format == '%')
2190 {
2191 bufformat = format;
2192 format ++;
2193
2194 if (*format == '%')
2195 {
2196 cupsFilePutChar(fp, *format++);
2197 bytes ++;
2198 continue;
2199 }
2200 else if (strchr(" -+#\'", *format))
2201 sign = *format++;
2202 else
2203 sign = 0;
2204
2205 width = 0;
2206 while (isdigit(*format))
2207 width = width * 10 + *format++ - '0';
2208
2209 if (*format == '.')
2210 {
2211 format ++;
2212 prec = 0;
2213
2214 while (isdigit(*format))
2215 prec = prec * 10 + *format++ - '0';
2216 }
2217 else
2218 prec = -1;
2219
2220 if (*format == 'l' && format[1] == 'l')
2221 {
2222 size = 'L';
2223 format += 2;
2224 }
2225 else if (*format == 'h' || *format == 'l' || *format == 'L')
2226 size = *format++;
2227 else
2228 size = '\0';
2229
2230 if (!*format)
2231 break;
2232
2233 type = *format++;
2234
2235 switch (type)
2236 {
2237 case 'E' : // Floating point formats
2238 case 'G' :
2239 case 'e' :
2240 case 'f' :
2241 case 'g' :
2242 if ((format - bufformat + 1) > (int)sizeof(tformat))
2243 break;
2244
2245 memcpy(tformat, bufformat, (size_t)(format - bufformat));
2246 tformat[format - bufformat] = '\0';
2247
2248 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double));
2249 break;
2250
2251 case 'B' : // Integer formats
2252 case 'X' :
2253 case 'b' :
2254 case 'd' :
2255 case 'i' :
2256 case 'o' :
2257 case 'u' :
2258 case 'x' :
2259 if ((format - bufformat + 1) > (int)sizeof(tformat))
2260 break;
2261
2262 memcpy(tformat, bufformat, (size_t)(format - bufformat));
2263 tformat[format - bufformat] = '\0';
2264
2265 # ifdef HAVE_LONG_LONG
2266 if (size == 'L')
2267 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, long long));
2268 else
2269 # endif /* HAVE_LONG_LONG */
2270 if (size == 'l')
2271 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, long));
2272 else
2273 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
2274 break;
2275
2276 case 'p' : // Pointer value
2277 if ((format - bufformat + 1) > (int)sizeof(tformat))
2278 break;
2279
2280 memcpy(tformat, bufformat, (size_t)(format - bufformat));
2281 tformat[format - bufformat] = '\0';
2282
2283 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *));
2284 break;
2285
2286 case 'c' : // Character or character array
2287 if (width <= 1)
2288 {
2289 bytes ++;
2290 cupsFilePutChar(fp, va_arg(ap, int));
2291 }
2292 else
2293 {
2294 cupsFileWrite(fp, va_arg(ap, char *), (size_t)width);
2295 bytes += width;
2296 }
2297 break;
2298
2299 case 's' : // String
2300 if ((s = va_arg(ap, char *)) == NULL)
2301 s = (char *)"(nil)";
2302
2303 slen = (int)strlen(s);
2304 if (slen > width && prec != width)
2305 width = slen;
2306
2307 if (slen > width)
2308 slen = width;
2309
2310 if (sign != '-')
2311 {
2312 for (i = width - slen; i > 0; i --, bytes ++)
2313 cupsFilePutChar(fp, ' ');
2314 }
2315
2316 for (i = slen; i > 0; i --, s ++, bytes ++)
2317 {
2318 if (*s == '\\' || *s == '\"')
2319 {
2320 cupsFilePutChar(fp, '\\');
2321 bytes ++;
2322 }
2323
2324 cupsFilePutChar(fp, *s);
2325 }
2326
2327 if (sign == '-')
2328 {
2329 for (i = width - slen; i > 0; i --, bytes ++)
2330 cupsFilePutChar(fp, ' ');
2331 }
2332 break;
2333 }
2334 }
2335 else
2336 {
2337 cupsFilePutChar(fp, *format++);
2338 bytes ++;
2339 }
2340 }
2341
2342 va_end(ap);
2343
2344 // Return the number of characters written.
2345 return (bytes);
2346 }
2347
2348
2349 //
2350 // 'ppdcSource::read_file()' - Read a driver source file.
2351 //
2352
2353 void
2354 ppdcSource::read_file(const char *f, // I - File to read
2355 cups_file_t *ffp) // I - File pointer to use
2356 {
2357 ppdcFile *fp = new ppdcFile(f, ffp);
2358 scan_file(fp);
2359 delete fp;
2360
2361 if (cond_current != cond_stack)
2362 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."), f);
2363 }
2364
2365
2366 //
2367 // 'ppdcSource::scan_file()' - Scan a driver source file.
2368 //
2369
2370 void
2371 ppdcSource::scan_file(ppdcFile *fp, // I - File to read
2372 ppdcDriver *td, // I - Driver template
2373 bool inc) // I - Including?
2374 {
2375 ppdcDriver *d; // Current driver
2376 ppdcGroup *g, // Current group
2377 *mg, // Matching group
2378 *general, // General options group
2379 *install; // Installable options group
2380 ppdcOption *o; // Current option
2381 ppdcChoice *c; // Current choice
2382 char temp[256], // Token from file...
2383 *ptr; // Pointer into token
2384 int isdefault; // Default option?
2385
2386
2387 // Initialize things as needed...
2388 if (inc && td)
2389 {
2390 d = td;
2391 d->retain();
2392 }
2393 else
2394 d = new ppdcDriver(td);
2395
2396 if ((general = d->find_group("General")) == NULL)
2397 {
2398 general = new ppdcGroup("General", NULL);
2399 d->add_group(general);
2400 }
2401
2402 if ((install = d->find_group("InstallableOptions")) == NULL)
2403 {
2404 install = new ppdcGroup("InstallableOptions", "Installable Options");
2405 d->add_group(install);
2406 }
2407
2408 // Loop until EOF or }
2409 o = 0;
2410 g = general;
2411
2412 while (get_token(fp, temp, sizeof(temp)))
2413 {
2414 if (temp[0] == '*')
2415 {
2416 // Mark the next choice as the default
2417 isdefault = 1;
2418
2419 for (ptr = temp; ptr[1]; ptr ++)
2420 *ptr = ptr[1];
2421
2422 *ptr = '\0';
2423 }
2424 else
2425 {
2426 // Don't mark the next choice as the default
2427 isdefault = 0;
2428 }
2429
2430 if (!_cups_strcasecmp(temp, "}"))
2431 {
2432 // Close this one out...
2433 break;
2434 }
2435 else if (!_cups_strcasecmp(temp, "{"))
2436 {
2437 // Open a new child...
2438 scan_file(fp, d);
2439 }
2440 else if (!_cups_strcasecmp(temp, "#if"))
2441 {
2442 if ((cond_current - cond_stack) >= 100)
2443 {
2444 _cupsLangPrintf(stderr,
2445 _("ppdc: Too many nested #if's on line %d of %s."),
2446 fp->line, fp->filename);
2447 break;
2448 }
2449
2450 cond_current ++;
2451 if (get_integer(fp) > 0)
2452 *cond_current = PPDC_COND_SATISFIED;
2453 else
2454 {
2455 *cond_current = PPDC_COND_SKIP;
2456 cond_state |= PPDC_COND_SKIP;
2457 }
2458 }
2459 else if (!_cups_strcasecmp(temp, "#elif"))
2460 {
2461 if (cond_current == cond_stack)
2462 {
2463 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
2464 fp->line, fp->filename);
2465 break;
2466 }
2467
2468 if (*cond_current & PPDC_COND_SATISFIED)
2469 {
2470 get_integer(fp);
2471 *cond_current |= PPDC_COND_SKIP;
2472 }
2473 else if (get_integer(fp) > 0)
2474 {
2475 *cond_current |= PPDC_COND_SATISFIED;
2476 *cond_current &= ~PPDC_COND_SKIP;
2477 }
2478 else
2479 *cond_current |= PPDC_COND_SKIP;
2480
2481 // Update the current state
2482 int *cond_temp = cond_current; // Temporary stack pointer
2483
2484 cond_state = PPDC_COND_NORMAL;
2485 while (cond_temp > cond_stack)
2486 if (*cond_temp & PPDC_COND_SKIP)
2487 {
2488 cond_state = PPDC_COND_SKIP;
2489 break;
2490 }
2491 else
2492 cond_temp --;
2493 }
2494 else if (!_cups_strcasecmp(temp, "#else"))
2495 {
2496 if (cond_current == cond_stack)
2497 {
2498 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
2499 fp->line, fp->filename);
2500 break;
2501 }
2502
2503 if (*cond_current & PPDC_COND_SATISFIED)
2504 *cond_current |= PPDC_COND_SKIP;
2505 else
2506 {
2507 *cond_current |= PPDC_COND_SATISFIED;
2508 *cond_current &= ~PPDC_COND_SKIP;
2509 }
2510
2511 // Update the current state
2512 int *cond_temp = cond_current; // Temporary stack pointer
2513
2514 cond_state = PPDC_COND_NORMAL;
2515 while (cond_temp > cond_stack)
2516 if (*cond_temp & PPDC_COND_SKIP)
2517 {
2518 cond_state = PPDC_COND_SKIP;
2519 break;
2520 }
2521 else
2522 cond_temp --;
2523 }
2524 else if (!_cups_strcasecmp(temp, "#endif"))
2525 {
2526 if (cond_current == cond_stack)
2527 {
2528 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
2529 fp->line, fp->filename);
2530 break;
2531 }
2532
2533 cond_current --;
2534
2535 // Update the current state
2536 int *cond_temp = cond_current; // Temporary stack pointer
2537
2538 cond_state = PPDC_COND_NORMAL;
2539 while (cond_temp > cond_stack)
2540 if (*cond_temp & PPDC_COND_SKIP)
2541 {
2542 cond_state = PPDC_COND_SKIP;
2543 break;
2544 }
2545 else
2546 cond_temp --;
2547 }
2548 else if (!_cups_strcasecmp(temp, "#define"))
2549 {
2550 // Get the variable...
2551 get_variable(fp);
2552 }
2553 else if (!_cups_strcasecmp(temp, "#include"))
2554 {
2555 // #include filename
2556 char basedir[1024], // Base directory
2557 *baseptr, // Pointer into directory
2558 inctemp[1024], // Initial filename
2559 incname[1024]; // Include filename
2560 ppdcFile *incfile; // Include file
2561 int *old_current = cond_current;
2562 // Previous current stack
2563
2564
2565 // Get the include name...
2566 if (!get_token(fp, inctemp, sizeof(inctemp)))
2567 {
2568 _cupsLangPrintf(stderr,
2569 _("ppdc: Expected include filename on line %d of "
2570 "%s."), fp->line, fp->filename);
2571 break;
2572 }
2573
2574 if (cond_state)
2575 continue;
2576
2577 // Figure out the current directory...
2578 strlcpy(basedir, fp->filename, sizeof(basedir));
2579
2580 if ((baseptr = strrchr(basedir, '/')) != NULL)
2581 *baseptr = '\0';
2582 else
2583 strlcpy(basedir, ".", sizeof(basedir));
2584
2585 // Find the include file...
2586 if (find_include(inctemp, basedir, incname, sizeof(incname)))
2587 {
2588 // Open the include file, scan it, and then close it...
2589 incfile = new ppdcFile(incname);
2590 scan_file(incfile, d, true);
2591 delete incfile;
2592
2593 if (cond_current != old_current)
2594 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."),
2595 incname);
2596 }
2597 else
2598 {
2599 // Can't find it!
2600 _cupsLangPrintf(stderr,
2601 _("ppdc: Unable to find include file \"%s\" on line %d "
2602 "of %s."), inctemp, fp->line, fp->filename);
2603 break;
2604 }
2605 }
2606 else if (!_cups_strcasecmp(temp, "#media"))
2607 {
2608 ppdcMediaSize *m; // Media size
2609
2610
2611 // Get a media size...
2612 m = get_size(fp);
2613 if (m)
2614 {
2615 if (cond_state)
2616 m->release();
2617 else
2618 sizes->add(m);
2619 }
2620 }
2621 else if (!_cups_strcasecmp(temp, "#po"))
2622 {
2623 ppdcCatalog *cat; // Message catalog
2624
2625
2626 // Get a message catalog...
2627 cat = get_po(fp);
2628 if (cat)
2629 {
2630 if (cond_state)
2631 cat->release();
2632 else
2633 po_files->add(cat);
2634 }
2635 }
2636 else if (!_cups_strcasecmp(temp, "Attribute") ||
2637 !_cups_strcasecmp(temp, "LocAttribute"))
2638 {
2639 ppdcAttr *a; // Attribute
2640
2641
2642 // Get an attribute...
2643 a = get_attr(fp, !_cups_strcasecmp(temp, "LocAttribute"));
2644 if (a)
2645 {
2646 if (cond_state)
2647 a->release();
2648 else
2649 d->add_attr(a);
2650 }
2651 }
2652 else if (!_cups_strcasecmp(temp, "Choice"))
2653 {
2654 // Get a choice...
2655 c = get_choice(fp);
2656 if (!c)
2657 break;
2658
2659 if (cond_state)
2660 {
2661 c->release();
2662 continue;
2663 }
2664
2665 // Add it to the current option...
2666 if (!o)
2667 {
2668 _cupsLangPrintf(stderr,
2669 _("ppdc: Choice found on line %d of %s with no "
2670 "Option."), fp->line, fp->filename);
2671 break;
2672 }
2673
2674 o->add_choice(c);
2675
2676 if (isdefault)
2677 o->set_defchoice(c);
2678 }
2679 else if (!_cups_strcasecmp(temp, "ColorDevice"))
2680 {
2681 // ColorDevice boolean
2682 if (cond_state)
2683 get_boolean(fp);
2684 else
2685 d->color_device = get_boolean(fp);
2686 }
2687 else if (!_cups_strcasecmp(temp, "ColorModel"))
2688 {
2689 // Get the color model
2690 c = get_color_model(fp);
2691 if (!c)
2692 continue;
2693
2694 if (cond_state)
2695 {
2696 c->release();
2697 continue;
2698 }
2699
2700 // Add the choice to the ColorModel option...
2701 if ((o = d->find_option("ColorModel")) == NULL)
2702 {
2703 // Create the ColorModel option...
2704 o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f);
2705 g = general;
2706 g->add_option(o);
2707 }
2708
2709 o->add_choice(c);
2710
2711 if (isdefault)
2712 o->set_defchoice(c);
2713
2714 o = NULL;
2715 }
2716 else if (!_cups_strcasecmp(temp, "ColorProfile"))
2717 {
2718 ppdcProfile *p; // Color profile
2719
2720
2721 // Get the color profile...
2722 p = get_color_profile(fp);
2723
2724 if (p)
2725 {
2726 if (cond_state)
2727 p->release();
2728 else
2729 d->profiles->add(p);
2730 }
2731 }
2732 else if (!_cups_strcasecmp(temp, "Copyright"))
2733 {
2734 // Copyright string
2735 char copytemp[8192], // Copyright string
2736 *copyptr, // Pointer into string
2737 *copyend; // Pointer to end of string
2738
2739
2740 // Get the copyright string...
2741 if (!get_token(fp, copytemp, sizeof(temp)))
2742 {
2743 _cupsLangPrintf(stderr,
2744 _("ppdc: Expected string after Copyright on line %d "
2745 "of %s."), fp->line, fp->filename);
2746 break;
2747 }
2748
2749 if (cond_state)
2750 continue;
2751
2752 // Break it up into individual lines...
2753 for (copyptr = copytemp; copyptr; copyptr = copyend)
2754 {
2755 if ((copyend = strchr(copyptr, '\n')) != NULL)
2756 *copyend++ = '\0';
2757
2758 d->copyright->add(new ppdcString(copyptr));
2759 }
2760 }
2761 else if (!_cups_strcasecmp(temp, "CustomMedia"))
2762 {
2763 ppdcMediaSize *m; // Media size
2764
2765
2766 // Get a custom media size...
2767 m = get_custom_size(fp);
2768
2769 if (cond_state)
2770 {
2771 m->release();
2772 continue;
2773 }
2774
2775 if (m)
2776 d->sizes->add(m);
2777
2778 if (isdefault)
2779 d->set_default_size(m);
2780 }
2781 else if (!_cups_strcasecmp(temp, "Cutter"))
2782 {
2783 // Cutter boolean
2784 int have_cutter; // Have a paper cutter?
2785
2786
2787 have_cutter = get_boolean(fp);
2788 if (have_cutter <= 0 || cond_state)
2789 continue;
2790
2791 if ((o = d->find_option("CutMedia")) == NULL)
2792 {
2793 o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f);
2794
2795 g = general;
2796 g->add_option(o);
2797
2798 c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice");
2799 o->add_choice(c);
2800 o->set_defchoice(c);
2801
2802 c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice");
2803 o->add_choice(c);
2804 }
2805
2806 o = NULL;
2807 }
2808 else if (!_cups_strcasecmp(temp, "Darkness"))
2809 {
2810 // Get the darkness choice...
2811 c = get_generic(fp, "Darkness", NULL, "cupsCompression");
2812 if (!c)
2813 continue;
2814
2815 if (cond_state)
2816 {
2817 c->release();
2818 continue;
2819 }
2820
2821 // Add the choice to the cupsDarkness option...
2822 if ((o = d->find_option_group("cupsDarkness", &mg)) == NULL)
2823 {
2824 // Create the cupsDarkness option...
2825 o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
2826 g = general;
2827 g->add_option(o);
2828 }
2829 else if (mg != general)
2830 {
2831 _cupsLangPrintf(stderr,
2832 _("ppdc: Option %s defined in two different groups on "
2833 "line %d of %s."), "cupsDarkness", fp->line,
2834 fp->filename);
2835 c->release();
2836 continue;
2837 }
2838
2839 o->add_choice(c);
2840
2841 if (isdefault)
2842 o->set_defchoice(c);
2843
2844 o = NULL;
2845 }
2846 else if (!_cups_strcasecmp(temp, "DriverType"))
2847 {
2848 int i; // Looping var
2849
2850
2851 // DriverType keyword
2852 if (!get_token(fp, temp, sizeof(temp)))
2853 {
2854 _cupsLangPrintf(stderr,
2855 _("ppdc: Expected driver type keyword following "
2856 "DriverType on line %d of %s."),
2857 fp->line, fp->filename);
2858 continue;
2859 }
2860
2861 if (cond_state)
2862 continue;
2863
2864 for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
2865 if (!_cups_strcasecmp(temp, driver_types[i]))
2866 break;
2867
2868 if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
2869 d->type = (ppdcDrvType)i;
2870 else if (!_cups_strcasecmp(temp, "dymo"))
2871 d->type = PPDC_DRIVER_LABEL;
2872 else
2873 _cupsLangPrintf(stderr,
2874 _("ppdc: Unknown driver type %s on line %d of %s."),
2875 temp, fp->line, fp->filename);
2876 }
2877 else if (!_cups_strcasecmp(temp, "Duplex"))
2878 get_duplex(fp, d);
2879 else if (!_cups_strcasecmp(temp, "Filter"))
2880 {
2881 ppdcFilter *f; // Filter
2882
2883
2884 // Get the filter value...
2885 f = get_filter(fp);
2886 if (f)
2887 {
2888 if (cond_state)
2889 f->release();
2890 else
2891 d->filters->add(f);
2892 }
2893 }
2894 else if (!_cups_strcasecmp(temp, "Finishing"))
2895 {
2896 // Get the finishing choice...
2897 c = get_generic(fp, "Finishing", "OutputType", NULL);
2898 if (!c)
2899 continue;
2900
2901 if (cond_state)
2902 {
2903 c->release();
2904 continue;
2905 }
2906
2907 // Add the choice to the cupsFinishing option...
2908 if ((o = d->find_option_group("cupsFinishing", &mg)) == NULL)
2909 {
2910 // Create the cupsFinishing option...
2911 o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
2912 g = general;
2913 g->add_option(o);
2914 }
2915 else if (mg != general)
2916 {
2917 _cupsLangPrintf(stderr,
2918 _("ppdc: Option %s defined in two different groups on "
2919 "line %d of %s."), "cupsFinishing", fp->line,
2920 fp->filename);
2921 c->release();
2922 continue;
2923 }
2924
2925 o->add_choice(c);
2926
2927 if (isdefault)
2928 o->set_defchoice(c);
2929
2930 o = NULL;
2931 }
2932 else if (!_cups_strcasecmp(temp, "Font") ||
2933 !_cups_strcasecmp(temp, "#font"))
2934 {
2935 ppdcFont *f; // Font
2936
2937
2938 // Get a font...
2939 f = get_font(fp);
2940 if (f)
2941 {
2942 if (cond_state)
2943 f->release();
2944 else
2945 {
2946 if (!_cups_strcasecmp(temp, "#font"))
2947 base_fonts->add(f);
2948 else
2949 d->add_font(f);
2950
2951 if (isdefault)
2952 d->set_default_font(f);
2953 }
2954 }
2955 }
2956 else if (!_cups_strcasecmp(temp, "Group"))
2957 {
2958 // Get a group...
2959 ppdcGroup *tempg = get_group(fp, d);
2960
2961 if (!tempg)
2962 break;
2963
2964 if (cond_state)
2965 {
2966 if (!d->find_group(tempg->name->value))
2967 tempg->release();
2968 }
2969 else
2970 {
2971 if (!d->find_group(tempg->name->value))
2972 d->add_group(tempg);
2973
2974 g = tempg;
2975 }
2976 }
2977 else if (!_cups_strcasecmp(temp, "HWMargins"))
2978 {
2979 // HWMargins left bottom right top
2980 d->left_margin = get_measurement(fp);
2981 d->bottom_margin = get_measurement(fp);
2982 d->right_margin = get_measurement(fp);
2983 d->top_margin = get_measurement(fp);
2984 }
2985 else if (!_cups_strcasecmp(temp, "InputSlot"))
2986 {
2987 // Get the input slot choice...
2988 c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
2989 if (!c)
2990 continue;
2991
2992 if (cond_state)
2993 {
2994 c->release();
2995 continue;
2996 }
2997
2998 // Add the choice to the InputSlot option...
2999
3000 if ((o = d->find_option_group("InputSlot", &mg)) == NULL)
3001 {
3002 // Create the InputSlot option...
3003 o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
3004 PPDC_SECTION_ANY, 10.0f);
3005 g = general;
3006 g->add_option(o);
3007 }
3008 else if (mg != general)
3009 {
3010 _cupsLangPrintf(stderr,
3011 _("ppdc: Option %s defined in two different groups on "
3012 "line %d of %s."), "InputSlot", fp->line,
3013 fp->filename);
3014 c->release();
3015 continue;
3016 }
3017
3018 o->add_choice(c);
3019
3020 if (isdefault)
3021 o->set_defchoice(c);
3022
3023 o = NULL;
3024 }
3025 else if (!_cups_strcasecmp(temp, "Installable"))
3026 {
3027 // Get the installable option...
3028 o = get_installable(fp);
3029
3030 // Add it as needed...
3031 if (o)
3032 {
3033 if (cond_state)
3034 o->release();
3035 else
3036 install->add_option(o);
3037
3038 o = NULL;
3039 }
3040 }
3041 else if (!_cups_strcasecmp(temp, "ManualCopies"))
3042 {
3043 // ManualCopies boolean
3044 if (cond_state)
3045 get_boolean(fp);
3046 else
3047 d->manual_copies = get_boolean(fp);
3048 }
3049 else if (!_cups_strcasecmp(temp, "Manufacturer"))
3050 {
3051 // Manufacturer name
3052 char name[256]; // Model name string
3053
3054
3055 if (!get_token(fp, name, sizeof(name)))
3056 {
3057 _cupsLangPrintf(stderr,
3058 _("ppdc: Expected name after Manufacturer on line %d "
3059 "of %s."), fp->line, fp->filename);
3060 break;
3061 }
3062
3063 if (!cond_state)
3064 d->set_manufacturer(name);
3065 }
3066 else if (!_cups_strcasecmp(temp, "MaxSize"))
3067 {
3068 // MaxSize width length
3069 if (cond_state)
3070 {
3071 get_measurement(fp);
3072 get_measurement(fp);
3073 }
3074 else
3075 {
3076 d->max_width = get_measurement(fp);
3077 d->max_length = get_measurement(fp);
3078 }
3079 }
3080 else if (!_cups_strcasecmp(temp, "MediaSize"))
3081 {
3082 // MediaSize keyword
3083 char name[41]; // Media size name
3084 ppdcMediaSize *m, // Matching media size...
3085 *dm; // Driver media size...
3086
3087
3088 if (get_token(fp, name, sizeof(name)) == NULL)
3089 {
3090 _cupsLangPrintf(stderr,
3091 _("ppdc: Expected name after MediaSize on line %d of "
3092 "%s."), fp->line, fp->filename);
3093 break;
3094 }
3095
3096 if (cond_state)
3097 continue;
3098
3099 m = find_size(name);
3100
3101 if (!m)
3102 {
3103 _cupsLangPrintf(stderr,
3104 _("ppdc: Unknown media size \"%s\" on line %d of "
3105 "%s."), name, fp->line, fp->filename);
3106 break;
3107 }
3108
3109 // Add this size to the driver...
3110 dm = new ppdcMediaSize(m->name->value, m->text->value,
3111 m->width, m->length, d->left_margin,
3112 d->bottom_margin, d->right_margin,
3113 d->top_margin);
3114 d->sizes->add(dm);
3115
3116 if (isdefault)
3117 d->set_default_size(dm);
3118 }
3119 else if (!_cups_strcasecmp(temp, "MediaType"))
3120 {
3121 // Get the media type choice...
3122 c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
3123 if (!c)
3124 continue;
3125
3126 if (cond_state)
3127 {
3128 c->release();
3129 continue;
3130 }
3131
3132 // Add the choice to the MediaType option...
3133 if ((o = d->find_option_group("MediaType", &mg)) == NULL)
3134 {
3135 // Create the MediaType option...
3136 o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
3137 PPDC_SECTION_ANY, 10.0f);
3138 g = general;
3139 g->add_option(o);
3140 }
3141 else if (mg != general)
3142 {
3143 _cupsLangPrintf(stderr,
3144 _("ppdc: Option %s defined in two different groups on "
3145 "line %d of %s."), "MediaType", fp->line,
3146 fp->filename);
3147 c->release();
3148 continue;
3149 }
3150
3151 o->add_choice(c);
3152
3153 if (isdefault)
3154 o->set_defchoice(c);
3155
3156 o = NULL;
3157 }
3158 else if (!_cups_strcasecmp(temp, "MinSize"))
3159 {
3160 // MinSize width length
3161 if (cond_state)
3162 {
3163 get_measurement(fp);
3164 get_measurement(fp);
3165 }
3166 else
3167 {
3168 d->min_width = get_measurement(fp);
3169 d->min_length = get_measurement(fp);
3170 }
3171 }
3172 else if (!_cups_strcasecmp(temp, "ModelName"))
3173 {
3174 // ModelName name
3175 char name[256]; // Model name string
3176
3177
3178 if (!get_token(fp, name, sizeof(name)))
3179 {
3180 _cupsLangPrintf(stderr,
3181 _("ppdc: Expected name after ModelName on line %d of "
3182 "%s."), fp->line, fp->filename);
3183 break;
3184 }
3185
3186 if (!cond_state)
3187 d->set_model_name(name);
3188 }
3189 else if (!_cups_strcasecmp(temp, "ModelNumber"))
3190 {
3191 // ModelNumber number
3192 if (cond_state)
3193 get_integer(fp);
3194 else
3195 d->model_number = get_integer(fp);
3196 }
3197 else if (!_cups_strcasecmp(temp, "Option"))
3198 {
3199 // Get an option...
3200 ppdcOption *tempo = get_option(fp, d, g);
3201
3202 if (!tempo)
3203 break;
3204
3205 if (cond_state)
3206 {
3207 if (!g->find_option(tempo->name->value))
3208 tempo->release();
3209 }
3210 else
3211 {
3212 if (!g->find_option(tempo->name->value))
3213 g->add_option(tempo);
3214
3215 o = tempo;
3216 }
3217 }
3218 else if (!_cups_strcasecmp(temp, "FileName"))
3219 {
3220 // FileName name
3221 char name[256]; // Filename string
3222
3223
3224 if (!get_token(fp, name, sizeof(name)))
3225 {
3226 _cupsLangPrintf(stderr,
3227 _("ppdc: Expected name after FileName on line %d of "
3228 "%s."), fp->line, fp->filename);
3229 break;
3230 }
3231
3232 if (!cond_state)
3233 d->set_file_name(name);
3234 }
3235 else if (!_cups_strcasecmp(temp, "PCFileName"))
3236 {
3237 // PCFileName name
3238 char name[256]; // PC filename string
3239
3240
3241 if (!get_token(fp, name, sizeof(name)))
3242 {
3243 _cupsLangPrintf(stderr,
3244 _("ppdc: Expected name after PCFileName on line %d of "
3245 "%s."), fp->line, fp->filename);
3246 break;
3247 }
3248
3249 if (!cond_state)
3250 d->set_pc_file_name(name);
3251 }
3252 else if (!_cups_strcasecmp(temp, "Resolution"))
3253 {
3254 // Get the resolution choice...
3255 c = get_resolution(fp);
3256 if (!c)
3257 continue;
3258
3259 if (cond_state)
3260 {
3261 c->release();
3262 continue;
3263 }
3264
3265 // Add the choice to the Resolution option...
3266 if ((o = d->find_option_group("Resolution", &mg)) == NULL)
3267 {
3268 // Create the Resolution option...
3269 o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
3270 10.0f);
3271 g = general;
3272 g->add_option(o);
3273 }
3274 else if (mg != general)
3275 {
3276 _cupsLangPrintf(stderr,
3277 _("ppdc: Option %s defined in two different groups on "
3278 "line %d of %s."), "Resolution", fp->line,
3279 fp->filename);
3280 c->release();
3281 continue;
3282 }
3283
3284 o->add_choice(c);
3285
3286 if (isdefault)
3287 o->set_defchoice(c);
3288
3289 o = NULL;
3290 }
3291 else if (!_cups_strcasecmp(temp, "SimpleColorProfile"))
3292 {
3293 ppdcProfile *p; // Color profile
3294
3295
3296 // Get the color profile...
3297 p = get_simple_profile(fp);
3298
3299 if (p)
3300 {
3301 if (cond_state)
3302 p->release();
3303 else
3304 d->profiles->add(p);
3305 }
3306 }
3307 else if (!_cups_strcasecmp(temp, "Throughput"))
3308 {
3309 // Throughput number
3310 if (cond_state)
3311 get_integer(fp);
3312 else
3313 d->throughput = get_integer(fp);
3314 }
3315 else if (!_cups_strcasecmp(temp, "UIConstraints"))
3316 {
3317 ppdcConstraint *con; // Constraint
3318
3319
3320 con = get_constraint(fp);
3321
3322 if (con)
3323 {
3324 if (cond_state)
3325 con->release();
3326 else
3327 d->constraints->add(con);
3328 }
3329 }
3330 else if (!_cups_strcasecmp(temp, "VariablePaperSize"))
3331 {
3332 // VariablePaperSize boolean
3333 if (cond_state)
3334 get_boolean(fp);
3335 else
3336 d->variable_paper_size = get_boolean(fp);
3337 }
3338 else if (!_cups_strcasecmp(temp, "Version"))
3339 {
3340 // Version string
3341 char name[256]; // Model name string
3342
3343
3344 if (!get_token(fp, name, sizeof(name)))
3345 {
3346 _cupsLangPrintf(stderr,
3347 _("ppdc: Expected string after Version on line %d of "
3348 "%s."), fp->line, fp->filename);
3349 break;
3350 }
3351
3352 if (!cond_state)
3353 d->set_version(name);
3354 }
3355 else
3356 {
3357 _cupsLangPrintf(stderr,
3358 _("ppdc: Unknown token \"%s\" seen on line %d of %s."),
3359 temp, fp->line, fp->filename);
3360 break;
3361 }
3362 }
3363
3364 // Done processing this block, is there anything to save?
3365 if (!inc)
3366 {
3367 if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version ||
3368 !d->sizes->count)
3369 {
3370 // Nothing to save...
3371 d->release();
3372 }
3373 else
3374 {
3375 // Got a driver, save it...
3376 drivers->add(d);
3377 }
3378 }
3379 else if (inc && td)
3380 td->release();
3381 }
3382
3383
3384 //
3385 // 'ppdcSource::set_variable()' - Set a variable.
3386 //
3387
3388 ppdcVariable * // O - Variable
3389 ppdcSource::set_variable(
3390 const char *name, // I - Name
3391 const char *value) // I - Value
3392 {
3393 ppdcVariable *v; // Variable
3394
3395
3396 // See if the variable exists already...
3397 v = find_variable(name);
3398 if (v)
3399 {
3400 // Change the variable value...
3401 v->set_value(value);
3402 }
3403 else
3404 {
3405 // Create a new variable and add it...
3406 v = new ppdcVariable(name, value);
3407 vars->add(v);
3408 }
3409
3410 return (v);
3411 }
3412
3413
3414 //
3415 // 'ppdcSource::write_file()' - Write the current source data to a file.
3416 //
3417
3418 int // O - 0 on success, -1 on error
3419 ppdcSource::write_file(const char *f) // I - File to write
3420 {
3421 cups_file_t *fp; // Output file
3422 char bckname[1024]; // Backup file
3423 ppdcDriver *d; // Current driver
3424 ppdcString *st; // Current string
3425 ppdcAttr *a; // Current attribute
3426 ppdcConstraint *co; // Current constraint
3427 ppdcFilter *fi; // Current filter
3428 ppdcFont *fo; // Current font
3429 ppdcGroup *g; // Current group
3430 ppdcOption *o; // Current option
3431 ppdcChoice *ch; // Current choice
3432 ppdcProfile *p; // Current color profile
3433 ppdcMediaSize *si; // Current media size
3434 float left, // Current left margin
3435 bottom, // Current bottom margin
3436 right, // Current right margin
3437 top; // Current top margin
3438 int dtused[PPDC_DRIVER_MAX];// Driver type usage...
3439
3440
3441 // Rename the current file, if any, to .bck...
3442 snprintf(bckname, sizeof(bckname), "%s.bck", f);
3443 rename(f, bckname);
3444
3445 // Open the output file...
3446 fp = cupsFileOpen(f, "w");
3447
3448 if (!fp)
3449 {
3450 // Can't create file; restore backup and return...
3451 rename(bckname, f);
3452 return (-1);
3453 }
3454
3455 cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n");
3456
3457 // Include standard files...
3458 cupsFilePuts(fp, "// Include necessary files...\n");
3459 cupsFilePuts(fp, "#include <font.defs>\n");
3460 cupsFilePuts(fp, "#include <media.defs>\n");
3461
3462 memset(dtused, 0, sizeof(dtused));
3463
3464 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3465 if (d->type > PPDC_DRIVER_PS && !dtused[d->type])
3466 {
3467 cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]);
3468 dtused[d->type] = 1;
3469 }
3470
3471 // Output each driver...
3472 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3473 {
3474 // Start the driver...
3475 cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value,
3476 d->model_name->value);
3477 cupsFilePuts(fp, "{\n");
3478
3479 // Write the copyright stings...
3480 for (st = (ppdcString *)d->copyright->first();
3481 st;
3482 st = (ppdcString *)d->copyright->next())
3483 quotef(fp, " Copyright \"%s\"\n", st->value);
3484
3485 // Write other strings and values...
3486 if (d->manufacturer && d->manufacturer->value)
3487 quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value);
3488 if (d->model_name->value)
3489 quotef(fp, " ModelName \"%s\"\n", d->model_name->value);
3490 if (d->file_name && d->file_name->value)
3491 quotef(fp, " FileName \"%s\"\n", d->file_name->value);
3492 if (d->pc_file_name && d->pc_file_name->value)
3493 quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
3494 if (d->version && d->version->value)
3495 quotef(fp, " Version \"%s\"\n", d->version->value);
3496
3497 cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]);
3498
3499 if (d->model_number)
3500 {
3501 switch (d->type)
3502 {
3503 case PPDC_DRIVER_LABEL :
3504 cupsFilePuts(fp, " ModelNumber ");
3505
3506 switch (d->model_number)
3507 {
3508 case DYMO_3x0 :
3509 cupsFilePuts(fp, "$DYMO_3x0\n");
3510 break;
3511
3512 case ZEBRA_EPL_LINE :
3513 cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n");
3514 break;
3515
3516 case ZEBRA_EPL_PAGE :
3517 cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n");
3518 break;
3519
3520 case ZEBRA_ZPL :
3521 cupsFilePuts(fp, "$ZEBRA_ZPL\n");
3522 break;
3523
3524 case ZEBRA_CPCL :
3525 cupsFilePuts(fp, "$ZEBRA_CPCL\n");
3526 break;
3527
3528 case INTELLITECH_PCL :
3529 cupsFilePuts(fp, "$INTELLITECH_PCL\n");
3530 break;
3531
3532 default :
3533 cupsFilePrintf(fp, "%d\n", d->model_number);
3534 break;
3535 }
3536 break;
3537
3538 case PPDC_DRIVER_EPSON :
3539 cupsFilePuts(fp, " ModelNumber ");
3540
3541 switch (d->model_number)
3542 {
3543 case EPSON_9PIN :
3544 cupsFilePuts(fp, "$EPSON_9PIN\n");
3545 break;
3546
3547 case EPSON_24PIN :
3548 cupsFilePuts(fp, "$EPSON_24PIN\n");
3549 break;
3550
3551 case EPSON_COLOR :
3552 cupsFilePuts(fp, "$EPSON_COLOR\n");
3553 break;
3554
3555 case EPSON_PHOTO :
3556 cupsFilePuts(fp, "$EPSON_PHOTO\n");
3557 break;
3558
3559 case EPSON_ICOLOR :
3560 cupsFilePuts(fp, "$EPSON_ICOLOR\n");
3561 break;
3562
3563 case EPSON_IPHOTO :
3564 cupsFilePuts(fp, "$EPSON_IPHOTO\n");
3565 break;
3566
3567 default :
3568 cupsFilePrintf(fp, "%d\n", d->model_number);
3569 break;
3570 }
3571 break;
3572
3573 case PPDC_DRIVER_HP :
3574 cupsFilePuts(fp, " ModelNumber ");
3575 switch (d->model_number)
3576 {
3577 case HP_LASERJET :
3578 cupsFilePuts(fp, "$HP_LASERJET\n");
3579 break;
3580
3581 case HP_DESKJET :
3582 cupsFilePuts(fp, "$HP_DESKJET\n");
3583 break;
3584
3585 case HP_DESKJET2 :
3586 cupsFilePuts(fp, "$HP_DESKJET2\n");
3587 break;
3588
3589 default :
3590 cupsFilePrintf(fp, "%d\n", d->model_number);
3591 break;
3592 }
3593
3594 cupsFilePuts(fp, ")\n");
3595 break;
3596
3597 default :
3598 cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number);
3599 break;
3600 }
3601 }
3602
3603 if (d->manual_copies)
3604 cupsFilePuts(fp, " ManualCopies Yes\n");
3605
3606 if (d->color_device)
3607 cupsFilePuts(fp, " ColorDevice Yes\n");
3608
3609 if (d->throughput)
3610 cupsFilePrintf(fp, " Throughput %d\n", d->throughput);
3611
3612 // Output all of the attributes...
3613 for (a = (ppdcAttr *)d->attrs->first();
3614 a;
3615 a = (ppdcAttr *)d->attrs->next())
3616 if (a->text->value && a->text->value[0])
3617 quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
3618 a->name->value, a->selector->value ? a->selector->value : "",
3619 a->text->value, a->value->value ? a->value->value : "");
3620 else
3621 quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n",
3622 a->name->value, a->selector->value ? a->selector->value : "",
3623 a->value->value ? a->value->value : "");
3624
3625 // Output all of the constraints...
3626 for (co = (ppdcConstraint *)d->constraints->first();
3627 co;
3628 co = (ppdcConstraint *)d->constraints->next())
3629 {
3630 if (co->option1->value[0] == '*')
3631 cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value,
3632 co->choice1->value ? co->choice1->value : "");
3633 else
3634 cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value,
3635 co->choice1->value ? co->choice1->value : "");
3636
3637 if (co->option2->value[0] == '*')
3638 cupsFilePrintf(fp, " %s %s\"\n", co->option2->value,
3639 co->choice2->value ? co->choice2->value : "");
3640 else
3641 cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value,
3642 co->choice2->value ? co->choice2->value : "");
3643 }
3644
3645 // Output all of the filters...
3646 for (fi = (ppdcFilter *)d->filters->first();
3647 fi;
3648 fi = (ppdcFilter *)d->filters->next())
3649 cupsFilePrintf(fp, " Filter \"%s %d %s\"\n",
3650 fi->mime_type->value, fi->cost, fi->program->value);
3651
3652 // Output all of the fonts...
3653 for (fo = (ppdcFont *)d->fonts->first();
3654 fo;
3655 fo = (ppdcFont *)d->fonts->next())
3656 if (!strcmp(fo->name->value, "*"))
3657 cupsFilePuts(fp, " Font *\n");
3658 else
3659 cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
3660 fo->name->value, fo->encoding->value,
3661 fo->version->value, fo->charset->value,
3662 fo->status == PPDC_FONT_ROM ? "ROM" : "Disk");
3663
3664 // Output all options...
3665 for (g = (ppdcGroup *)d->groups->first();
3666 g;
3667 g = (ppdcGroup *)d->groups->next())
3668 {
3669 if (g->options->count == 0)
3670 continue;
3671
3672 if (g->text->value && g->text->value[0])
3673 quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value);
3674 else
3675 cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value);
3676
3677 for (o = (ppdcOption *)g->options->first();
3678 o;
3679 o = (ppdcOption *)g->options->next())
3680 {
3681 if (o->choices->count == 0)
3682 continue;
3683
3684 if (o->text->value && o->text->value[0])
3685 quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value);
3686 else
3687 cupsFilePrintf(fp, " Option \"%s\"", o->name->value);
3688
3689 cupsFilePrintf(fp, " %s %s %.1f\n",
3690 o->type == PPDC_BOOLEAN ? "Boolean" :
3691 o->type == PPDC_PICKONE ? "PickOne" : "PickMany",
3692 o->section == PPDC_SECTION_ANY ? "AnySetup" :
3693 o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" :
3694 o->section == PPDC_SECTION_EXIT ? "ExitServer" :
3695 o->section == PPDC_SECTION_JCL ? "JCLSetup" :
3696 o->section == PPDC_SECTION_PAGE ? "PageSetup" :
3697 "Prolog",
3698 o->order);
3699
3700 for (ch = (ppdcChoice *)o->choices->first();
3701 ch;
3702 ch = (ppdcChoice *)o->choices->next())
3703 {
3704 if (ch->text->value && ch->text->value[0])
3705 quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n",
3706 o->defchoice == ch->name ? "*" : "",
3707 ch->name->value, ch->text->value,
3708 ch->code->value ? ch->code->value : "");
3709 else
3710 quotef(fp, " %sChoice \"%s\" \"%s\"\n",
3711 o->defchoice == ch->name ? "*" : "",
3712 ch->name->value,
3713 ch->code->value ? ch->code->value : "");
3714 }
3715 }
3716 }
3717
3718 // Output all of the color profiles...
3719 for (p = (ppdcProfile *)d->profiles->first();
3720 p;
3721 p = (ppdcProfile *)d->profiles->next())
3722 cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f "
3723 "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
3724 p->resolution->value, p->media_type->value,
3725 p->density, p->gamma,
3726 p->profile[0], p->profile[1], p->profile[2],
3727 p->profile[3], p->profile[4], p->profile[5],
3728 p->profile[6], p->profile[7], p->profile[8]);
3729
3730 // Output all of the media sizes...
3731 left = 0.0;
3732 bottom = 0.0;
3733 right = 0.0;
3734 top = 0.0;
3735
3736 for (si = (ppdcMediaSize *)d->sizes->first();
3737 si;
3738 si = (ppdcMediaSize *)d->sizes->next())
3739 if (si->size_code->value && si->region_code->value)
3740 {
3741 // Output a custom media size...
3742 quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
3743 si->name == d->default_size ? "*" : "", si->name->value,
3744 si->text->value, si->width, si->length, si->left, si->bottom,
3745 si->right, si->top, si->size_code->value,
3746 si->region_code->value);
3747 }
3748 else
3749 {
3750 // Output a standard media size...
3751 if (fabs(left - si->left) > 0.1 ||
3752 fabs(bottom - si->bottom) > 0.1 ||
3753 fabs(right - si->right) > 0.1 ||
3754 fabs(top - si->top) > 0.1)
3755 {
3756 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3757 si->left, si->bottom, si->right, si->top);
3758
3759 left = si->left;
3760 bottom = si->bottom;
3761 right = si->right;
3762 top = si->top;
3763 }
3764
3765 cupsFilePrintf(fp, " %sMediaSize %s\n",
3766 si->name == d->default_size ? "*" : "",
3767 si->name->value);
3768 }
3769
3770 if (d->variable_paper_size)
3771 {
3772 cupsFilePuts(fp, " VariablePaperSize Yes\n");
3773
3774 if (fabs(left - d->left_margin) > 0.1 ||
3775 fabs(bottom - d->bottom_margin) > 0.1 ||
3776 fabs(right - d->right_margin) > 0.1 ||
3777 fabs(top - d->top_margin) > 0.1)
3778 {
3779 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3780 d->left_margin, d->bottom_margin, d->right_margin,
3781 d->top_margin);
3782 }
3783
3784 cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length);
3785 cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length);
3786 }
3787
3788 // End the driver...
3789 cupsFilePuts(fp, "}\n");
3790 }
3791
3792 // Close the file and return...
3793 cupsFileClose(fp);
3794
3795 return (0);
3796 }