2 // "$Id: ppdc-source.cxx 10379 2012-03-23 22:16:22Z mike $"
4 // Source class for the CUPS PPD Compiler.
6 // Copyright 2007-2012 by Apple Inc.
7 // Copyright 2002-2007 by Easy Software Products.
9 // These coded instructions, statements, and computer programs are the
10 // property of Apple Inc. and are protected by Federal copyright
11 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 // which should have been included with this file. If this file is
13 // file is missing or damaged, see the license at "http://www.cups.org/".
17 // ppdcSource::ppdcSource() - Load a driver source file.
18 // ppdcSource::~ppdcSource() - Free a driver source file.
19 // ppdcSource::add_include() - Add an include directory.
20 // ppdcSource::find_driver() - Find a driver.
21 // ppdcSource::find_include() - Find an include file.
22 // ppdcSource::find_po() - Find a message catalog for the given
24 // ppdcSource::find_size() - Find a media size.
25 // ppdcSource::find_variable() - Find a variable.
26 // ppdcSource::get_attr() - Get an attribute.
27 // ppdcSource::get_boolean() - Get a boolean value.
28 // ppdcSource::get_choice() - Get a choice.
29 // ppdcSource::get_color_model() - Get an old-style color model option.
30 // ppdcSource::get_color_order() - Get an old-style color order value.
31 // ppdcSource::get_color_profile() - Get a color profile definition.
32 // ppdcSource::get_color_space() - Get an old-style colorspace value.
33 // ppdcSource::get_constraint() - Get a constraint.
34 // ppdcSource::get_custom_size() - Get a custom media size definition from
36 // ppdcSource::get_duplex() - Get a duplex option.
37 // ppdcSource::get_filter() - Get a filter.
38 // ppdcSource::get_float() - Get a single floating-point number.
39 // ppdcSource::get_font() - Get a font definition.
40 // ppdcSource::get_generic() - Get a generic old-style option.
41 // ppdcSource::get_group() - Get an option group.
42 // ppdcSource::get_installable() - Get an installable option.
43 // ppdcSource::get_integer() - Get an integer value from a file.
44 // ppdcSource::get_measurement() - Get a measurement value.
45 // ppdcSource::get_option() - Get an option definition.
46 // ppdcSource::get_po() - Get a message catalog.
47 // ppdcSource::get_resolution() - Get an old-style resolution option.
48 // ppdcSource::get_simple_profile() - Get a simple color profile definition.
49 // ppdcSource::get_size() - Get a media size definition from a file.
50 // ppdcSource::get_token() - Get a token from a file.
51 // ppdcSource::get_variable() - Get a variable definition.
52 // ppdcSource::quotef() - Write a formatted, quoted string...
53 // ppdcSource::read_file() - Read a driver source file.
54 // ppdcSource::scan_file() - Scan a driver source file.
55 // ppdcSource::set_variable() - Set a variable.
56 // ppdcSource::write_file() - Write the current source data to a file.
60 // Include necessary headers...
63 #include "ppdc-private.h"
67 #include <cups/raster.h>
68 #include "data/epson.h"
69 #include "data/escp.h"
71 #include "data/label.h"
74 # include <sys/utsname.h>
82 ppdcArray *ppdcSource::includes = 0;
83 const char *ppdcSource::driver_types[] =
96 // 'ppdcSource::ppdcSource()' - Load a driver source file.
99 ppdcSource::ppdcSource(const char *f, // I - File to read
100 cups_file_t *ffp)// I - File pointer to use
105 filename = new ppdcString(f);
106 base_fonts = new ppdcArray();
107 drivers = new ppdcArray();
108 po_files = new ppdcArray();
109 sizes = new ppdcArray();
110 vars = new ppdcArray();
111 cond_state = PPDC_COND_NORMAL;
112 cond_current = cond_stack;
113 cond_stack[0] = PPDC_COND_NORMAL;
115 // Add standard #define variables...
116 #define MAKE_STRING(x) #x
118 vars->add(new ppdcVariable("CUPS_VERSION", MAKE_STRING(CUPS_VERSION)));
119 vars->add(new ppdcVariable("CUPS_VERSION_MAJOR", MAKE_STRING(CUPS_VERSION_MAJOR)));
120 vars->add(new ppdcVariable("CUPS_VERSION_MINOR", MAKE_STRING(CUPS_VERSION_MINOR)));
121 vars->add(new ppdcVariable("CUPS_VERSION_PATCH", MAKE_STRING(CUPS_VERSION_PATCH)));
124 vars->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
125 vars->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
128 struct utsname name; // uname information
132 vars->add(new ppdcVariable("PLATFORM_NAME", name.sysname));
133 vars->add(new ppdcVariable("PLATFORM_ARCH", name.machine));
137 vars->add(new ppdcVariable("PLATFORM_NAME", "unknown"));
138 vars->add(new ppdcVariable("PLATFORM_ARCH", "unknown"));
148 // 'ppdcSource::~ppdcSource()' - Free a driver source file.
151 ppdcSource::~ppdcSource()
156 base_fonts->release();
165 // 'ppdcSource::add_include()' - Add an include directory.
169 ppdcSource::add_include(const char *d) // I - Include directory
175 includes = new ppdcArray();
177 includes->add(new ppdcString(d));
182 // 'ppdcSource::find_driver()' - Find a driver.
185 ppdcDriver * // O - Driver
186 ppdcSource::find_driver(const char *f) // I - Driver file name
188 ppdcDriver *d; // Current driver
191 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
192 if (!_cups_strcasecmp(f, d->pc_file_name->value))
200 // 'ppdcSource::find_include()' - Find an include file.
203 char * // O - Found path or NULL
204 ppdcSource::find_include(
205 const char *f, // I - Include filename
206 const char *base, // I - Current directory
207 char *n, // I - Path buffer
208 int nlen) // I - Path buffer length
210 ppdcString *dir; // Include directory
211 char temp[1024], // Temporary path
212 *ptr; // Pointer to end of path
215 // Range check input...
216 if (!f || !*f || !n || nlen < 2)
219 // Check the first character to see if we have <name> or "name"...
222 // Remove the surrounding <> from the name...
223 strlcpy(temp, f + 1, sizeof(temp));
224 ptr = temp + strlen(temp) - 1;
228 _cupsLangPrintf(stderr,
229 _("ppdc: Invalid #include/#po filename \"%s\"."), n);
238 // Check for the local file relative to the current directory...
239 if (base && *base && f[0] != '/')
240 snprintf(n, nlen, "%s/%s", base, f);
248 // Absolute path that doesn't exist...
253 // Search the include directories, if any...
256 for (dir = (ppdcString *)includes->first(); dir; dir = (ppdcString *)includes->next())
258 snprintf(n, nlen, "%s/%s", dir->value, f);
264 // Search the standard include directories...
265 _cups_globals_t *cg = _cupsGlobals(); // Global data
267 snprintf(n, nlen, "%s/ppdc/%s", cg->cups_datadir, f);
271 snprintf(n, nlen, "%s/po/%s", cg->cups_datadir, f);
280 // 'ppdcSource::find_po()' - Find a message catalog for the given locale.
283 ppdcCatalog * // O - Message catalog or NULL
284 ppdcSource::find_po(const char *l) // I - Locale name
286 ppdcCatalog *cat; // Current message catalog
289 for (cat = (ppdcCatalog *)po_files->first();
291 cat = (ppdcCatalog *)po_files->next())
292 if (!_cups_strcasecmp(l, cat->locale->value))
300 // 'ppdcSource::find_size()' - Find a media size.
303 ppdcMediaSize * // O - Size
304 ppdcSource::find_size(const char *s) // I - Size name
306 ppdcMediaSize *m; // Current media size
309 for (m = (ppdcMediaSize *)sizes->first(); m; m = (ppdcMediaSize *)sizes->next())
310 if (!_cups_strcasecmp(s, m->name->value))
318 // 'ppdcSource::find_variable()' - Find a variable.
321 ppdcVariable * // O - Variable
322 ppdcSource::find_variable(const char *n)// I - Variable name
324 ppdcVariable *v; // Current variable
327 for (v = (ppdcVariable *)vars->first(); v; v = (ppdcVariable *)vars->next())
328 if (!_cups_strcasecmp(n, v->name->value))
336 // 'ppdcSource::get_attr()' - Get an attribute.
339 ppdcAttr * // O - Attribute
340 ppdcSource::get_attr(ppdcFile *fp, // I - File to read
341 bool loc) // I - Localize this attribute?
343 char name[1024], // Name string
344 selector[1024], // Selector string
345 *text, // Text string
346 value[1024]; // Value string
349 // Get the attribute parameters:
351 // Attribute name selector value
352 if (!get_token(fp, name, sizeof(name)))
354 _cupsLangPrintf(stderr,
355 _("ppdc: Expected name after %s on line %d of %s."),
356 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
360 if (!get_token(fp, selector, sizeof(selector)))
362 _cupsLangPrintf(stderr,
363 _("ppdc: Expected selector after %s on line %d of %s."),
364 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
368 if ((text = strchr(selector, '/')) != NULL)
371 if (!get_token(fp, value, sizeof(value)))
373 _cupsLangPrintf(stderr,
374 _("ppdc: Expected value after %s on line %d of %s."),
375 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
379 return (new ppdcAttr(name, selector, text, value, loc));
384 // 'ppdcSource::get_boolean()' - Get a boolean value.
387 int // O - Boolean value
388 ppdcSource::get_boolean(ppdcFile *fp) // I - File to read
390 char buffer[256]; // String buffer
393 if (!get_token(fp, buffer, sizeof(buffer)))
395 _cupsLangPrintf(stderr,
396 _("ppdc: Expected boolean value on line %d of %s."),
397 fp->line, fp->filename);
401 if (!_cups_strcasecmp(buffer, "on") ||
402 !_cups_strcasecmp(buffer, "yes") ||
403 !_cups_strcasecmp(buffer, "true"))
405 else if (!_cups_strcasecmp(buffer, "off") ||
406 !_cups_strcasecmp(buffer, "no") ||
407 !_cups_strcasecmp(buffer, "false"))
411 _cupsLangPrintf(stderr,
412 _("ppdc: Bad boolean value (%s) on line %d of %s."),
413 buffer, fp->line, fp->filename);
420 // 'ppdcSource::get_choice()' - Get a choice.
423 ppdcChoice * // O - Choice data
424 ppdcSource::get_choice(ppdcFile *fp) // I - File to read
426 char name[1024], // Name
431 // Read a choice from the file:
433 // Choice name/text code
434 if (!get_token(fp, name, sizeof(name)))
436 _cupsLangPrintf(stderr,
437 _("ppdc: Expected choice name/text on line %d of %s."),
438 fp->line, fp->filename);
442 if ((text = strchr(name, '/')) != NULL)
447 if (!get_token(fp, code, sizeof(code)))
449 _cupsLangPrintf(stderr, _("ppdc: Expected choice code on line %d of %s."),
450 fp->line, fp->filename);
454 // Return the new choice
455 return (new ppdcChoice(name, text, code));
460 // 'ppdcSource::get_color_model()' - Get an old-style color model option.
463 ppdcChoice * // O - Choice data
464 ppdcSource::get_color_model(ppdcFile *fp)
467 char name[1024], // Option name
468 *text, // Text option
469 temp[256]; // Temporary string
470 int color_space, // Colorspace
471 color_order, // Color order
472 compression; // Compression mode
475 // Get the ColorModel parameters:
477 // ColorModel name/text colorspace colororder compression
478 if (!get_token(fp, name, sizeof(name)))
480 _cupsLangPrintf(stderr,
481 _("ppdc: Expected name/text combination for ColorModel on "
482 "line %d of %s."), fp->line, fp->filename);
486 if ((text = strchr(name, '/')) != NULL)
491 if (!get_token(fp, temp, sizeof(temp)))
493 _cupsLangPrintf(stderr,
494 _("ppdc: Expected colorspace for ColorModel on line %d of "
495 "%s."), fp->line, fp->filename);
499 if ((color_space = get_color_space(temp)) < 0)
500 color_space = get_integer(temp);
502 if (!get_token(fp, temp, sizeof(temp)))
504 _cupsLangPrintf(stderr,
505 _("ppdc: Expected color order for ColorModel on line %d of "
506 "%s."), fp->line, fp->filename);
510 if ((color_order = get_color_order(temp)) < 0)
511 color_order = get_integer(temp);
513 if (!get_token(fp, temp, sizeof(temp)))
515 _cupsLangPrintf(stderr,
516 _("ppdc: Expected compression for ColorModel on line %d of "
517 "%s."), fp->line, fp->filename);
521 compression = get_integer(temp);
523 snprintf(temp, sizeof(temp),
524 "<</cupsColorSpace %d/cupsColorOrder %d/cupsCompression %d>>"
526 color_space, color_order, compression);
528 return (new ppdcChoice(name, text, temp));
533 // 'ppdcSource::get_color_order()' - Get an old-style color order value.
536 int // O - Color order value
537 ppdcSource::get_color_order(
538 const char *co) // I - Color order string
540 if (!_cups_strcasecmp(co, "chunked") ||
541 !_cups_strcasecmp(co, "chunky"))
542 return (CUPS_ORDER_CHUNKED);
543 else if (!_cups_strcasecmp(co, "banded"))
544 return (CUPS_ORDER_BANDED);
545 else if (!_cups_strcasecmp(co, "planar"))
546 return (CUPS_ORDER_PLANAR);
553 // 'ppdcSource::get_color_profile()' - Get a color profile definition.
556 ppdcProfile * // O - Color profile
557 ppdcSource::get_color_profile(
558 ppdcFile *fp) // I - File to read
560 char resolution[1024], // Resolution/media type
561 *media_type; // Media type
562 int i; // Looping var
563 float g, // Gamma value
565 m[9]; // Transform matrix
568 // Get the ColorProfile parameters:
570 // ColorProfile resolution/mediatype gamma density m00 m01 m02 ... m22
571 if (!get_token(fp, resolution, sizeof(resolution)))
573 _cupsLangPrintf(stderr,
574 _("ppdc: Expected resolution/mediatype following "
575 "ColorProfile on line %d of %s."),
576 fp->line, fp->filename);
580 if ((media_type = strchr(resolution, '/')) != NULL)
581 *media_type++ = '\0';
583 media_type = resolution;
587 for (i = 0; i < 9; i ++)
588 m[i] = get_float(fp);
590 return (new ppdcProfile(resolution, media_type, g, d, m));
595 // 'ppdcSource::get_color_space()' - Get an old-style colorspace value.
598 int // O - Colorspace value
599 ppdcSource::get_color_space(
600 const char *cs) // I - Colorspace string
602 if (!_cups_strcasecmp(cs, "w"))
603 return (CUPS_CSPACE_W);
604 else if (!_cups_strcasecmp(cs, "rgb"))
605 return (CUPS_CSPACE_RGB);
606 else if (!_cups_strcasecmp(cs, "rgba"))
607 return (CUPS_CSPACE_RGBA);
608 else if (!_cups_strcasecmp(cs, "k"))
609 return (CUPS_CSPACE_K);
610 else if (!_cups_strcasecmp(cs, "cmy"))
611 return (CUPS_CSPACE_CMY);
612 else if (!_cups_strcasecmp(cs, "ymc"))
613 return (CUPS_CSPACE_YMC);
614 else if (!_cups_strcasecmp(cs, "cmyk"))
615 return (CUPS_CSPACE_CMYK);
616 else if (!_cups_strcasecmp(cs, "ymck"))
617 return (CUPS_CSPACE_YMCK);
618 else if (!_cups_strcasecmp(cs, "kcmy"))
619 return (CUPS_CSPACE_KCMY);
620 else if (!_cups_strcasecmp(cs, "kcmycm"))
621 return (CUPS_CSPACE_KCMYcm);
622 else if (!_cups_strcasecmp(cs, "gmck"))
623 return (CUPS_CSPACE_GMCK);
624 else if (!_cups_strcasecmp(cs, "gmcs"))
625 return (CUPS_CSPACE_GMCS);
626 else if (!_cups_strcasecmp(cs, "white"))
627 return (CUPS_CSPACE_WHITE);
628 else if (!_cups_strcasecmp(cs, "gold"))
629 return (CUPS_CSPACE_GOLD);
630 else if (!_cups_strcasecmp(cs, "silver"))
631 return (CUPS_CSPACE_SILVER);
632 else if (!_cups_strcasecmp(cs, "CIEXYZ"))
633 return (CUPS_CSPACE_CIEXYZ);
634 else if (!_cups_strcasecmp(cs, "CIELab"))
635 return (CUPS_CSPACE_CIELab);
636 else if (!_cups_strcasecmp(cs, "RGBW"))
637 return (CUPS_CSPACE_RGBW);
638 else if (!_cups_strcasecmp(cs, "ICC1"))
639 return (CUPS_CSPACE_ICC1);
640 else if (!_cups_strcasecmp(cs, "ICC2"))
641 return (CUPS_CSPACE_ICC2);
642 else if (!_cups_strcasecmp(cs, "ICC3"))
643 return (CUPS_CSPACE_ICC3);
644 else if (!_cups_strcasecmp(cs, "ICC4"))
645 return (CUPS_CSPACE_ICC4);
646 else if (!_cups_strcasecmp(cs, "ICC5"))
647 return (CUPS_CSPACE_ICC5);
648 else if (!_cups_strcasecmp(cs, "ICC6"))
649 return (CUPS_CSPACE_ICC6);
650 else if (!_cups_strcasecmp(cs, "ICC7"))
651 return (CUPS_CSPACE_ICC7);
652 else if (!_cups_strcasecmp(cs, "ICC8"))
653 return (CUPS_CSPACE_ICC8);
654 else if (!_cups_strcasecmp(cs, "ICC9"))
655 return (CUPS_CSPACE_ICC9);
656 else if (!_cups_strcasecmp(cs, "ICCA"))
657 return (CUPS_CSPACE_ICCA);
658 else if (!_cups_strcasecmp(cs, "ICCB"))
659 return (CUPS_CSPACE_ICCB);
660 else if (!_cups_strcasecmp(cs, "ICCC"))
661 return (CUPS_CSPACE_ICCC);
662 else if (!_cups_strcasecmp(cs, "ICCD"))
663 return (CUPS_CSPACE_ICCD);
664 else if (!_cups_strcasecmp(cs, "ICCE"))
665 return (CUPS_CSPACE_ICCE);
666 else if (!_cups_strcasecmp(cs, "ICCF"))
667 return (CUPS_CSPACE_ICCF);
674 // 'ppdcSource::get_constraint()' - Get a constraint.
677 ppdcConstraint * // O - Constraint
678 ppdcSource::get_constraint(ppdcFile *fp)// I - File to read
680 char temp[1024], // One string to rule them all
681 *ptr, // Pointer into string
682 *option1, // Constraint option 1
683 *choice1, // Constraint choice 1
684 *option2, // Constraint option 2
685 *choice2; // Constraint choice 2
688 // Read the UIConstaints parameter in one of the following forms:
690 // UIConstraints "*Option1 *Option2"
691 // UIConstraints "*Option1 Choice1 *Option2"
692 // UIConstraints "*Option1 *Option2 Choice2"
693 // UIConstraints "*Option1 Choice1 *Option2 Choice2"
694 if (!get_token(fp, temp, sizeof(temp)))
696 _cupsLangPrintf(stderr,
697 _("ppdc: Expected constraints string for UIConstraints on "
698 "line %d of %s."), fp->line, fp->filename);
702 for (ptr = temp; isspace(*ptr); ptr ++);
706 _cupsLangPrintf(stderr,
707 _("ppdc: Option constraint must *name on line %d of %s."),
708 fp->line, fp->filename);
714 for (; *ptr && !isspace(*ptr); ptr ++);
715 for (; isspace(*ptr); *ptr++ = '\0');
721 for (; *ptr && !isspace(*ptr); ptr ++);
722 for (; isspace(*ptr); *ptr++ = '\0');
729 _cupsLangPrintf(stderr,
730 _("ppdc: Expected two option names on line %d of %s."),
731 fp->line, fp->filename);
737 for (; *ptr && !isspace(*ptr); ptr ++);
738 for (; isspace(*ptr); *ptr++ = '\0');
745 return (new ppdcConstraint(option1, choice1, option2, choice2));
750 // 'ppdcSource::get_custom_size()' - Get a custom media size definition from a file.
753 ppdcMediaSize * // O - Media size
754 ppdcSource::get_custom_size(ppdcFile *fp)
757 char name[1024], // Name
759 size_code[10240], // PageSize code
760 region_code[10240]; // PageRegion
761 float width, // Width
764 bottom, // Bottom margin
765 right, // Right margin
769 // Get the name, text, width, length, margins, and code:
771 // CustomMedia name/text width length left bottom right top size-code region-code
772 if (!get_token(fp, name, sizeof(name)))
775 if ((text = strchr(name, '/')) != NULL)
780 if ((width = get_measurement(fp)) < 0.0f)
783 if ((length = get_measurement(fp)) < 0.0f)
786 if ((left = get_measurement(fp)) < 0.0f)
789 if ((bottom = get_measurement(fp)) < 0.0f)
792 if ((right = get_measurement(fp)) < 0.0f)
795 if ((top = get_measurement(fp)) < 0.0f)
798 if (!get_token(fp, size_code, sizeof(size_code)))
801 if (!get_token(fp, region_code, sizeof(region_code)))
804 // Return the new media size...
805 return (new ppdcMediaSize(name, text, width, length, left, bottom,
806 right, top, size_code, region_code));
811 // 'ppdcSource::get_duplex()' - Get a duplex option.
815 ppdcSource::get_duplex(ppdcFile *fp, // I - File to read from
816 ppdcDriver *d) // I - Current driver
818 char temp[256]; // Duplex keyword
819 ppdcAttr *attr; // cupsFlipDuplex attribute
820 ppdcGroup *g; // Current group
821 ppdcOption *o; // Duplex option
824 // Duplex {boolean|none|normal|flip}
825 if (!get_token(fp, temp, sizeof(temp)))
827 _cupsLangPrintf(stderr,
828 _("ppdc: Expected duplex type after Duplex on line %d of "
829 "%s."), fp->line, fp->filename);
836 if (!_cups_strcasecmp(temp, "none") || !_cups_strcasecmp(temp, "false") ||
837 !_cups_strcasecmp(temp, "no") || !_cups_strcasecmp(temp, "off"))
839 g = d->find_group("General");
840 if ((o = g->find_option("Duplex")) != NULL)
841 g->options->remove(o);
843 for (attr = (ppdcAttr *)d->attrs->first();
845 attr = (ppdcAttr *)d->attrs->next())
846 if (!strcmp(attr->name->value, "cupsFlipDuplex"))
848 d->attrs->remove(attr);
852 else if (!_cups_strcasecmp(temp, "normal") || !_cups_strcasecmp(temp, "true") ||
853 !_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "on") ||
854 !_cups_strcasecmp(temp, "flip") || !_cups_strcasecmp(temp, "rotated") ||
855 !_cups_strcasecmp(temp, "manualtumble"))
857 g = d->find_group("General");
858 o = g->find_option("Duplex");
862 o = new ppdcOption(PPDC_PICKONE, "Duplex", "2-Sided Printing",
863 !_cups_strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE :
864 PPDC_SECTION_ANY, 10.0f);
865 o->add_choice(new ppdcChoice("None", "Off (1-Sided)",
866 "<</Duplex false>>setpagedevice"));
867 o->add_choice(new ppdcChoice("DuplexNoTumble", "Long-Edge (Portrait)",
868 "<</Duplex true/Tumble false>>setpagedevice"));
869 o->add_choice(new ppdcChoice("DuplexTumble", "Short-Edge (Landscape)",
870 "<</Duplex true/Tumble true>>setpagedevice"));
875 for (attr = (ppdcAttr *)d->attrs->first();
877 attr = (ppdcAttr *)d->attrs->next())
878 if (!strcmp(attr->name->value, "cupsFlipDuplex"))
880 if (_cups_strcasecmp(temp, "flip"))
881 d->attrs->remove(attr);
885 if (!_cups_strcasecmp(temp, "flip") && !attr)
886 d->add_attr(new ppdcAttr("cupsFlipDuplex", NULL, NULL, "true"));
888 for (attr = (ppdcAttr *)d->attrs->first();
890 attr = (ppdcAttr *)d->attrs->next())
891 if (!strcmp(attr->name->value, "cupsBackSide"))
893 d->attrs->remove(attr);
897 if (!_cups_strcasecmp(temp, "flip"))
898 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Flipped"));
899 else if (!_cups_strcasecmp(temp, "rotated"))
900 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Rotated"));
901 else if (!_cups_strcasecmp(temp, "manualtumble"))
902 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "ManualTumble"));
904 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Normal"));
907 _cupsLangPrintf(stderr,
908 _("ppdc: Unknown duplex type \"%s\" on line %d of %s."),
909 temp, fp->line, fp->filename);
914 // 'ppdcSource::get_filter()' - Get a filter.
917 ppdcFilter * // O - Filter
918 ppdcSource::get_filter(ppdcFile *fp) // I - File to read
920 char type[1024], // MIME type
921 program[1024], // Filter program
922 *ptr; // Pointer into MIME type
923 int cost; // Relative cost
926 // Read filter parameters in one of the following formats:
928 // Filter "type cost program"
929 // Filter type cost program
931 if (!get_token(fp, type, sizeof(type)))
933 _cupsLangPrintf(stderr,
934 _("ppdc: Expected a filter definition on line %d of %s."),
935 fp->line, fp->filename);
939 if ((ptr = strchr(type, ' ')) != NULL)
941 // Old-style filter definition in one string...
943 cost = strtol(ptr, &ptr, 10);
945 while (isspace(*ptr))
948 strcpy(program, ptr);
952 cost = get_integer(fp);
954 if (!get_token(fp, program, sizeof(program)))
956 _cupsLangPrintf(stderr,
957 _("ppdc: Expected a program name on line %d of %s."),
958 fp->line, fp->filename);
965 _cupsLangPrintf(stderr,
966 _("ppdc: Invalid empty MIME type for filter on line %d of "
967 "%s."), fp->line, fp->filename);
971 if (cost < 0 || cost > 200)
973 _cupsLangPrintf(stderr,
974 _("ppdc: Invalid cost for filter on line %d of %s."),
975 fp->line, fp->filename);
981 _cupsLangPrintf(stderr,
982 _("ppdc: Invalid empty program name for filter on line %d "
983 "of %s."), fp->line, fp->filename);
987 return (new ppdcFilter(type, program, cost));
992 // 'ppdcSource::get_float()' - Get a single floating-point number.
996 ppdcSource::get_float(ppdcFile *fp) // I - File to read
998 char temp[256], // String buffer
999 *ptr; // Pointer into buffer
1000 float val; // Floating point value
1003 // Get the number from the file and range-check...
1004 if (!get_token(fp, temp, sizeof(temp)))
1006 _cupsLangPrintf(stderr, _("ppdc: Expected real number on line %d of %s."),
1007 fp->line, fp->filename);
1011 val = (float)strtod(temp, &ptr);
1015 _cupsLangPrintf(stderr,
1016 _("ppdc: Unknown trailing characters in real number \"%s\" "
1017 "on line %d of %s."), temp, fp->line, fp->filename);
1026 // 'ppdcSource::get_font()' - Get a font definition.
1029 ppdcFont * // O - Font data
1030 ppdcSource::get_font(ppdcFile *fp) // I - File to read
1032 char name[256], // Font name
1033 encoding[256], // Font encoding
1034 version[256], // Font version
1035 charset[256], // Font charset
1036 temp[256]; // Font status string
1037 ppdcFontStatus status; // Font status enumeration
1040 // Read font parameters as follows:
1043 // Font name encoding version charset status
1044 // %font name encoding version charset status
1046 // "Name" is the PostScript font name.
1048 // "Encoding" is the default encoding of the font: Standard, ISOLatin1,
1049 // Special, Expert, ExpertSubset, etc.
1051 // "Version" is the version number string.
1053 // "Charset" specifies the characters that are included in the font:
1054 // Standard, Special, Expert, Adobe-Identity, etc.
1056 // "Status" is the keyword ROM or Disk.
1057 if (!get_token(fp, name, sizeof(name)))
1059 _cupsLangPrintf(stderr,
1060 _("ppdc: Expected name after Font on line %d of %s."),
1061 fp->line, fp->filename);
1065 if (!strcmp(name, "*"))
1067 // Include all base fonts...
1071 status = PPDC_FONT_ROM;
1075 // Load a full font definition...
1076 if (!get_token(fp, encoding, sizeof(encoding)))
1078 _cupsLangPrintf(stderr,
1079 _("ppdc: Expected encoding after Font on line %d of "
1080 "%s."), fp->line, fp->filename);
1084 if (!get_token(fp, version, sizeof(version)))
1086 _cupsLangPrintf(stderr,
1087 _("ppdc: Expected version after Font on line %d of "
1088 "%s."), fp->line, fp->filename);
1092 if (!get_token(fp, charset, sizeof(charset)))
1094 _cupsLangPrintf(stderr,
1095 _("ppdc: Expected charset after Font on line %d of "
1096 "%s."), fp->line, fp->filename);
1100 if (!get_token(fp, temp, sizeof(temp)))
1102 _cupsLangPrintf(stderr,
1103 _("ppdc: Expected status after Font on line %d of %s."),
1104 fp->line, fp->filename);
1108 if (!_cups_strcasecmp(temp, "ROM"))
1109 status = PPDC_FONT_ROM;
1110 else if (!_cups_strcasecmp(temp, "Disk"))
1111 status = PPDC_FONT_DISK;
1114 _cupsLangPrintf(stderr,
1115 _("ppdc: Bad status keyword %s on line %d of %s."),
1116 temp, fp->line, fp->filename);
1121 // printf("Font %s %s %s %s %s\n", name, encoding, version, charset, temp);
1123 return (new ppdcFont(name, encoding, version, charset, status));
1128 // 'ppdcSource::get_generic()' - Get a generic old-style option.
1131 ppdcChoice * // O - Choice data
1132 ppdcSource::get_generic(ppdcFile *fp, // I - File to read
1133 const char *keyword,
1136 // I - Text attribute
1138 // I - Numeric attribute
1140 char name[1024], // Name
1142 command[256]; // Command string
1143 int val; // Numeric value
1146 // Read one of the following parameters:
1149 // Foo integer name/text
1151 val = get_integer(fp);
1155 if (!get_token(fp, name, sizeof(name)))
1157 _cupsLangPrintf(stderr,
1158 _("ppdc: Expected name/text after %s on line %d of %s."),
1159 keyword, fp->line, fp->filename);
1163 if ((text = strchr(name, '/')) != NULL)
1171 snprintf(command, sizeof(command),
1172 "<</%s(%s)/%s %d>>setpagedevice",
1173 tattr, name, nattr, val);
1175 snprintf(command, sizeof(command),
1176 "<</%s %d>>setpagedevice",
1180 snprintf(command, sizeof(command),
1181 "<</%s(%s)>>setpagedevice",
1184 return (new ppdcChoice(name, text, command));
1189 // 'ppdcSource::get_group()' - Get an option group.
1192 ppdcGroup * // O - Group
1193 ppdcSource::get_group(ppdcFile *fp, // I - File to read
1194 ppdcDriver *d) // I - Printer driver
1196 char name[1024], // UI name
1198 ppdcGroup *g; // Group
1201 // Read the Group parameters:
1204 if (!get_token(fp, name, sizeof(name)))
1206 _cupsLangPrintf(stderr,
1207 _("ppdc: Expected group name/text on line %d of %s."),
1208 fp->line, fp->filename);
1212 if ((text = strchr(name, '/')) != NULL)
1217 // See if the group already exists...
1218 if ((g = d->find_group(name)) == NULL)
1220 // Nope, add a new one...
1221 g = new ppdcGroup(name, text);
1229 // 'ppdcSource::get_installable()' - Get an installable option.
1232 ppdcOption * // O - Option
1233 ppdcSource::get_installable(ppdcFile *fp)
1236 char name[1024], // Name for installable option
1237 *text; // Text for installable option
1238 ppdcOption *o; // Option
1241 // Read the parameter for an installable option:
1243 // Installable name/text
1244 if (!get_token(fp, name, sizeof(name)))
1246 _cupsLangPrintf(stderr,
1247 _("ppdc: Expected name/text after Installable on line %d "
1248 "of %s."), fp->line, fp->filename);
1252 if ((text = strchr(name, '/')) != NULL)
1257 // Create the option...
1258 o = new ppdcOption(PPDC_BOOLEAN, name, text, PPDC_SECTION_ANY, 10.0f);
1260 // Add the false and true choices...
1261 o->add_choice(new ppdcChoice("False", "Not Installed", ""));
1262 o->add_choice(new ppdcChoice("True", "Installed", ""));
1269 // 'ppdcSource::get_integer()' - Get an integer value from a string.
1272 #define PPDC_XX -1 // Bad
1273 #define PPDC_EQ 0 // ==
1274 #define PPDC_NE 1 // !=
1275 #define PPDC_LT 2 // <
1276 #define PPDC_LE 3 // <=
1277 #define PPDC_GT 4 // >
1278 #define PPDC_GE 5 // >=
1280 int // O - Integer value
1281 ppdcSource::get_integer(const char *v) // I - Value string
1284 long temp, // Temporary value
1285 temp2; // Second temporary value
1286 char *newv, // New value string pointer
1287 ch; // Temporary character
1288 ppdcVariable *var; // #define variable
1289 int compop; // Comparison operator
1292 // Parse the value string...
1296 if (isdigit(*v & 255) || *v == '-' || *v == '+')
1298 // Return a simple integer value
1299 val = strtol(v, (char **)&v, 0);
1300 if (*v || val == LONG_MIN)
1307 // Evaluate and expression in any of the following formats:
1309 // (number number ... number) Bitwise OR of all numbers
1310 // (NAME == value) 1 if equal, 0 otherwise
1311 // (NAME != value) 1 if not equal, 0 otherwise
1312 // (NAME < value) 1 if less than, 0 otherwise
1313 // (NAME <= value) 1 if less than or equal, 0 otherwise
1314 // (NAME > value) 1 if greater than, 0 otherwise
1315 // (NAME >= value) 1 if greater than or equal, 0 otherwise
1320 while (*v && *v != ')')
1322 // Skip leading whitespace...
1323 while (*v && isspace(*v & 255))
1326 if (!*v || *v == ')')
1329 if (isdigit(*v & 255) || *v == '-' || *v == '+')
1331 // Bitwise OR a number...
1332 temp = strtol(v, &newv, 0);
1334 if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
1340 // NAME logicop value
1341 for (newv = (char *)v + 1;
1342 *newv && (isalnum(*newv & 255) || *newv == '_');
1349 if ((var = find_variable(v)) != NULL)
1351 if (!var->value || !var->value->value || !var->value->value[0])
1353 else if (isdigit(var->value->value[0] & 255) ||
1354 var->value->value[0] == '-' ||
1355 var->value->value[0] == '+')
1356 temp = strtol(var->value->value, NULL, 0);
1364 while (isspace(*newv & 255))
1367 if (!strncmp(newv, "==", 2))
1372 else if (!strncmp(newv, "!=", 2))
1377 else if (!strncmp(newv, "<=", 2))
1382 else if (*newv == '<')
1387 else if (!strncmp(newv, ">=", 2))
1392 else if (*newv == '>')
1400 if (compop != PPDC_XX)
1402 while (isspace(*newv & 255))
1405 if (*newv == ')' || !*newv)
1408 if (isdigit(*newv & 255) || *newv == '-' || *newv == '+')
1410 // Get the second number...
1411 temp2 = strtol(newv, &newv, 0);
1412 if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
1418 // Lookup the second name...
1419 for (v = newv, newv ++;
1420 *newv && (isalnum(*newv & 255) || *newv == '_');
1426 if ((var = find_variable(v)) != NULL)
1428 if (!var->value || !var->value->value || !var->value->value[0])
1430 else if (isdigit(var->value->value[0] & 255) ||
1431 var->value->value[0] == '-' ||
1432 var->value->value[0] == '+')
1433 temp2 = strtol(var->value->value, NULL, 0);
1443 // Do the comparison...
1447 temp = temp == temp2;
1450 temp = temp != temp2;
1453 temp = temp < temp2;
1456 temp = temp <= temp2;
1459 temp = temp > temp2;
1462 temp = temp >= temp2;
1472 if (*v == ')' && !v[1])
1477 else if ((var = find_variable(v)) != NULL)
1479 // NAME by itself returns 1 if the #define variable is not blank and
1481 return (var->value->value && var->value->value[0] &&
1482 strcmp(var->value->value, "0"));
1486 // Anything else is an error...
1493 // 'ppdcSource::get_integer()' - Get an integer value from a file.
1496 int // O - Integer value
1497 ppdcSource::get_integer(ppdcFile *fp) // I - File to read
1499 char temp[1024]; // String buffer
1502 if (!get_token(fp, temp, sizeof(temp)))
1504 _cupsLangPrintf(stderr, _("ppdc: Expected integer on line %d of %s."),
1505 fp->line, fp->filename);
1509 return (get_integer(temp));
1514 // 'ppdcSource::get_measurement()' - Get a measurement value.
1517 float // O - Measurement value in points
1518 ppdcSource::get_measurement(ppdcFile *fp)
1521 char buffer[256], // Number buffer
1522 *ptr; // Pointer into buffer
1523 float val; // Measurement value
1526 // Grab a token from the file...
1527 if (!get_token(fp, buffer, sizeof(buffer)))
1530 // Get the floating point value of "s" and skip all digits and decimal points.
1531 val = (float)strtod(buffer, &ptr);
1533 // Check for a trailing unit specifier...
1534 if (!_cups_strcasecmp(ptr, "mm"))
1535 val *= 72.0f / 25.4f;
1536 else if (!_cups_strcasecmp(ptr, "cm"))
1537 val *= 72.0f / 2.54f;
1538 else if (!_cups_strcasecmp(ptr, "m"))
1539 val *= 72.0f / 0.0254f;
1540 else if (!_cups_strcasecmp(ptr, "in"))
1542 else if (!_cups_strcasecmp(ptr, "ft"))
1543 val *= 72.0f * 12.0f;
1544 else if (_cups_strcasecmp(ptr, "pt") && *ptr)
1552 // 'ppdcSource::get_option()' - Get an option definition.
1555 ppdcOption * // O - Option
1556 ppdcSource::get_option(ppdcFile *fp, // I - File to read
1557 ppdcDriver *d, // I - Printer driver
1558 ppdcGroup *g) // I - Current group
1560 char name[1024], // UI name
1562 type[256]; // UI type string
1563 ppdcOptType ot; // Option type value
1564 ppdcOptSection section; // Option section
1565 float order; // Option order
1566 ppdcOption *o; // Option
1567 ppdcGroup *mg; // Matching group, if any
1570 // Read the Option parameters:
1572 // Option name/text type section order
1573 if (!get_token(fp, name, sizeof(name)))
1575 _cupsLangPrintf(stderr,
1576 _("ppdc: Expected option name/text on line %d of %s."),
1577 fp->line, fp->filename);
1581 if ((text = strchr(name, '/')) != NULL)
1586 if (!get_token(fp, type, sizeof(type)))
1588 _cupsLangPrintf(stderr, _("ppdc: Expected option type on line %d of %s."),
1589 fp->line, fp->filename);
1593 if (!_cups_strcasecmp(type, "boolean"))
1595 else if (!_cups_strcasecmp(type, "pickone"))
1597 else if (!_cups_strcasecmp(type, "pickmany"))
1601 _cupsLangPrintf(stderr,
1602 _("ppdc: Invalid option type \"%s\" on line %d of %s."),
1603 type, fp->line, fp->filename);
1607 if (!get_token(fp, type, sizeof(type)))
1609 _cupsLangPrintf(stderr,
1610 _("ppdc: Expected option section on line %d of %s."),
1611 fp->line, fp->filename);
1615 if (!_cups_strcasecmp(type, "AnySetup"))
1616 section = PPDC_SECTION_ANY;
1617 else if (!_cups_strcasecmp(type, "DocumentSetup"))
1618 section = PPDC_SECTION_DOCUMENT;
1619 else if (!_cups_strcasecmp(type, "ExitServer"))
1620 section = PPDC_SECTION_EXIT;
1621 else if (!_cups_strcasecmp(type, "JCLSetup"))
1622 section = PPDC_SECTION_JCL;
1623 else if (!_cups_strcasecmp(type, "PageSetup"))
1624 section = PPDC_SECTION_PAGE;
1625 else if (!_cups_strcasecmp(type, "Prolog"))
1626 section = PPDC_SECTION_PROLOG;
1629 _cupsLangPrintf(stderr,
1630 _("ppdc: Invalid option section \"%s\" on line %d of "
1631 "%s."), type, fp->line, fp->filename);
1635 order = get_float(fp);
1637 // See if the option already exists...
1638 if ((o = d->find_option_group(name, &mg)) == NULL)
1640 // Nope, add a new one...
1641 o = new ppdcOption(ot, name, text, section, order);
1643 else if (o->type != ot)
1645 _cupsLangPrintf(stderr,
1646 _("ppdc: Option %s redefined with a different type on line "
1647 "%d of %s."), name, fp->line, fp->filename);
1652 _cupsLangPrintf(stderr,
1653 _("ppdc: Option %s defined in two different groups on line "
1654 "%d of %s."), name, fp->line, fp->filename);
1663 // 'ppdcSource::get_po()' - Get a message catalog.
1666 ppdcCatalog * // O - Message catalog
1667 ppdcSource::get_po(ppdcFile *fp) // I - File to read
1669 char locale[32], // Locale name
1670 poname[1024], // Message catalog filename
1671 basedir[1024], // Base directory
1672 *baseptr, // Pointer into directory
1673 pofilename[1024]; // Full filename of message catalog
1674 ppdcCatalog *cat; // Message catalog
1677 // Read the #po parameters:
1679 // #po locale "filename.po"
1680 if (!get_token(fp, locale, sizeof(locale)))
1682 _cupsLangPrintf(stderr,
1683 _("ppdc: Expected locale after #po on line %d of %s."),
1684 fp->line, fp->filename);
1688 if (!get_token(fp, poname, sizeof(poname)))
1690 _cupsLangPrintf(stderr,
1691 _("ppdc: Expected filename after #po %s on line %d of "
1692 "%s."), locale, fp->line, fp->filename);
1696 // See if the locale is already loaded...
1697 if (find_po(locale))
1699 _cupsLangPrintf(stderr,
1700 _("ppdc: Duplicate #po for locale %s on line %d of %s."),
1701 locale, fp->line, fp->filename);
1705 // Figure out the current directory...
1706 strlcpy(basedir, fp->filename, sizeof(basedir));
1708 if ((baseptr = strrchr(basedir, '/')) != NULL)
1711 strcpy(basedir, ".");
1713 // Find the po file...
1714 pofilename[0] = '\0';
1717 find_include(poname, basedir, pofilename, sizeof(pofilename)))
1719 // Found it, so load it...
1720 cat = new ppdcCatalog(locale, pofilename);
1722 // Reset the filename to the name supplied by the user...
1723 cat->filename->release();
1724 cat->filename = new ppdcString(poname);
1726 // Return the catalog...
1731 _cupsLangPrintf(stderr,
1732 _("ppdc: Unable to find #po file %s on line %d of %s."),
1733 poname, fp->line, fp->filename);
1740 // 'ppdcSource::get_resolution()' - Get an old-style resolution option.
1743 ppdcChoice * // O - Choice data
1744 ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
1746 char name[1024], // Name
1748 temp[256], // Temporary string
1749 command[256], // Command string
1750 *commptr; // Pointer into command
1751 int xdpi, ydpi, // X + Y resolution
1752 color_order, // Color order
1753 color_space, // Colorspace
1754 compression, // Compression mode
1755 depth, // Bits per color
1756 row_count, // Row count
1757 row_feed, // Row feed
1758 row_step; // Row step/interval
1761 // Read the resolution parameters:
1763 // Resolution colorspace bits row-count row-feed row-step name/text
1764 if (!get_token(fp, temp, sizeof(temp)))
1766 _cupsLangPrintf(stderr,
1767 _("ppdc: Expected override field after Resolution on line "
1768 "%d of %s."), fp->line, fp->filename);
1772 color_order = get_color_order(temp);
1773 color_space = get_color_space(temp);
1774 compression = get_integer(temp);
1776 depth = get_integer(fp);
1777 row_count = get_integer(fp);
1778 row_feed = get_integer(fp);
1779 row_step = get_integer(fp);
1781 if (!get_token(fp, name, sizeof(name)))
1783 _cupsLangPrintf(stderr,
1784 _("ppdc: Expected name/text after Resolution on line %d of "
1785 "%s."), fp->line, fp->filename);
1789 if ((text = strchr(name, '/')) != NULL)
1794 switch (sscanf(name, "%dx%d", &xdpi, &ydpi))
1797 _cupsLangPrintf(stderr,
1798 _("ppdc: Bad resolution name \"%s\" on line %d of "
1799 "%s."), name, fp->line, fp->filename);
1806 // Create the necessary PS commands...
1807 snprintf(command, sizeof(command),
1808 "<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d"
1809 "/cupsRowFeed %d/cupsRowStep %d",
1810 xdpi, ydpi, depth, row_count, row_feed, row_step);
1811 commptr = command + strlen(command);
1813 if (color_order >= 0)
1815 snprintf(commptr, sizeof(command) - (commptr - command),
1816 "/cupsColorOrder %d", color_order);
1817 commptr += strlen(commptr);
1820 if (color_space >= 0)
1822 snprintf(commptr, sizeof(command) - (commptr - command),
1823 "/cupsColorSpace %d", color_space);
1824 commptr += strlen(commptr);
1827 if (compression >= 0)
1829 snprintf(commptr, sizeof(command) - (commptr - command),
1830 "/cupsCompression %d", compression);
1831 commptr += strlen(commptr);
1834 snprintf(commptr, sizeof(command) - (commptr - command), ">>setpagedevice");
1836 // Return the new choice...
1837 return (new ppdcChoice(name, text, command));
1842 // 'ppdcSource::get_simple_profile()' - Get a simple color profile definition.
1845 ppdcProfile * // O - Color profile
1846 ppdcSource::get_simple_profile(ppdcFile *fp)
1849 char resolution[1024], // Resolution/media type
1850 *media_type; // Media type
1851 float m[9]; // Transform matrix
1852 float kd, rd, g; // Densities and gamma
1853 float red, green, blue; // RGB adjustments
1854 float yellow; // Yellow density
1855 float color; // Color density values
1858 // Get the SimpleColorProfile parameters:
1860 // SimpleColorProfile resolution/mediatype black-density yellow-density
1861 // red-density gamma red-adjust green-adjust blue-adjust
1862 if (!get_token(fp, resolution, sizeof(resolution)))
1864 _cupsLangPrintf(stderr,
1865 _("ppdc: Expected resolution/mediatype following "
1866 "SimpleColorProfile on line %d of %s."),
1867 fp->line, fp->filename);
1871 if ((media_type = strchr(resolution, '/')) != NULL)
1872 *media_type++ = '\0';
1874 media_type = resolution;
1876 // Collect the profile parameters...
1878 yellow = get_float(fp);
1881 red = get_float(fp);
1882 green = get_float(fp);
1883 blue = get_float(fp);
1885 // Build the color profile...
1886 color = 0.5f * rd / kd - kd;
1888 m[1] = color + blue; // C + M (blue)
1889 m[2] = color - green; // C + Y (green)
1890 m[3] = color - blue; // M + C (blue)
1892 m[5] = color + red; // M + Y (red)
1893 m[6] = yellow * (color + green); // Y + C (green)
1894 m[7] = yellow * (color - red); // Y + M (red)
1902 else if (m[3] > 0.0f)
1913 else if (m[6] > 0.0f)
1924 else if (m[7] > 0.0f)
1930 // Return the new profile...
1931 return (new ppdcProfile(resolution, media_type, g, kd, m));
1936 // 'ppdcSource::get_size()' - Get a media size definition from a file.
1939 ppdcMediaSize * // O - Media size
1940 ppdcSource::get_size(ppdcFile *fp) // I - File to read
1942 char name[1024], // Name
1944 float width, // Width
1948 // Get the name, text, width, and length:
1950 // #media name/text width length
1951 if (!get_token(fp, name, sizeof(name)))
1954 if ((text = strchr(name, '/')) != NULL)
1959 if ((width = get_measurement(fp)) < 0.0f)
1962 if ((length = get_measurement(fp)) < 0.0f)
1965 // Return the new media size...
1966 return (new ppdcMediaSize(name, text, width, length, 0.0f, 0.0f, 0.0f, 0.0f));
1971 // 'ppdcSource::get_token()' - Get a token from a file.
1974 char * // O - Token string or NULL
1975 ppdcSource::get_token(ppdcFile *fp, // I - File to read
1976 char *buffer, // I - Buffer
1977 int buflen) // I - Length of buffer
1979 char *bufptr, // Pointer into string buffer
1980 *bufend; // End of string buffer
1981 int ch, // Character from file
1982 nextch, // Next char in file
1983 quote, // Quote character used...
1984 empty, // Empty input?
1985 startline; // Start line for quote
1986 char name[256], // Name string
1987 *nameptr; // Name pointer
1988 ppdcVariable *var; // Variable pointer
1991 // Mark the beginning and end of the buffer...
1993 bufend = buffer + buflen - 1;
1995 // Loop intil we've read a token...
2000 while ((ch = fp->get()) != EOF)
2002 if (isspace(ch) && !quote)
2011 // Variable substitution
2014 for (nameptr = name; (ch = fp->peek()) != EOF;)
2016 if (!isalnum(ch) && ch != '_')
2018 else if (nameptr < (name + sizeof(name) - 1))
2019 *nameptr++ = fp->get();
2022 if (nameptr == name)
2024 // Just substitute this character...
2028 if (bufptr < bufend)
2029 *bufptr++ = fp->get();
2034 _cupsLangPrintf(stderr,
2035 _("ppdc: Bad variable substitution ($%c) on line %d "
2036 "of %s."), ch, fp->line, fp->filename);
2038 if (bufptr < bufend)
2044 // Substitute the variable value...
2046 var = find_variable(name);
2049 strlcpy(bufptr, var->value->value, bufend - bufptr + 1);
2050 bufptr += strlen(bufptr);
2054 if (!(cond_state & PPDC_COND_SKIP))
2055 _cupsLangPrintf(stderr,
2056 _("ppdc: Undefined variable (%s) on line %d of "
2057 "%s."), name, fp->line, fp->filename);
2059 snprintf(bufptr, bufend - bufptr + 1, "$%s", name);
2060 bufptr += strlen(bufptr);
2064 else if (ch == '/' && !quote)
2066 // Possibly a comment...
2067 nextch = fp->peek();
2074 while ((nextch = fp->get()) != EOF)
2076 if (ch == '*' && nextch == '/')
2085 else if (nextch == '/')
2088 while ((nextch = fp->get()) != EOF)
2100 if (bufptr < bufend)
2104 else if (ch == '\'' || ch == '\"')
2110 // Ending the current quoted string...
2115 // Insert the opposing quote char...
2116 if (bufptr < bufend)
2121 // Start a new quoted string...
2122 startline = fp->line;
2126 else if ((ch == '(' || ch == '<') && !quote)
2130 startline = fp->line;
2132 if (bufptr < bufend)
2135 else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<'))
2139 if (bufptr < bufend)
2142 else if (ch == '\\')
2146 if ((ch = fp->get()) == EOF)
2149 if (bufptr < bufend)
2152 else if (bufptr < bufend)
2158 if ((ch == '{' || ch == '}') && !quote)
2165 _cupsLangPrintf(stderr,
2166 _("ppdc: Unterminated string starting with %c on line %d "
2167 "of %s."), quote, startline, fp->filename);
2183 // 'ppdcSource::get_variable()' - Get a variable definition.
2186 ppdcVariable * // O - Variable
2187 ppdcSource::get_variable(ppdcFile *fp) // I - File to read
2189 char name[1024], // Name
2190 value[1024]; // Value
2193 // Get the name and value:
2195 // #define name value
2196 if (!get_token(fp, name, sizeof(name)))
2199 if (!get_token(fp, value, sizeof(value)))
2202 // Set the variable...
2203 return (set_variable(name, value));
2208 // 'ppdcSource::quotef()' - Write a formatted, quoted string...
2211 int // O - Number bytes on success, -1 on failure
2212 ppdcSource::quotef(cups_file_t *fp, // I - File to write to
2213 const char *format, // I - Printf-style format string
2214 ...) // I - Additional args as needed
2216 va_list ap; // Pointer to additional arguments
2217 int bytes; // Bytes written
2218 char sign, // Sign of format width
2219 size, // Size character (h, l, L)
2220 type; // Format type character
2221 const char *bufformat; // Start of format
2222 int width, // Width of field
2223 prec; // Number of characters of precision
2224 char tformat[100]; // Temporary format string for fprintf()
2225 char *s; // Pointer to string
2226 int slen; // Length of string
2227 int i; // Looping var
2230 // Range check input...
2234 // Loop through the format string, formatting as needed...
2235 va_start(ap, format);
2248 cupsFilePutChar(fp, *format++);
2252 else if (strchr(" -+#\'", *format))
2258 while (isdigit(*format))
2259 width = width * 10 + *format++ - '0';
2266 while (isdigit(*format))
2267 prec = prec * 10 + *format++ - '0';
2272 if (*format == 'l' && format[1] == 'l')
2277 else if (*format == 'h' || *format == 'l' || *format == 'L')
2289 case 'E' : // Floating point formats
2294 if ((format - bufformat + 1) > (int)sizeof(tformat))
2297 strncpy(tformat, bufformat, format - bufformat);
2298 tformat[format - bufformat] = '\0';
2300 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double));
2303 case 'B' : // Integer formats
2311 if ((format - bufformat + 1) > (int)sizeof(tformat))
2314 strncpy(tformat, bufformat, format - bufformat);
2315 tformat[format - bufformat] = '\0';
2317 # ifdef HAVE_LONG_LONG
2319 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, long long));
2321 # endif /* HAVE_LONG_LONG */
2323 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, long));
2325 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
2328 case 'p' : // Pointer value
2329 if ((format - bufformat + 1) > (int)sizeof(tformat))
2332 strncpy(tformat, bufformat, format - bufformat);
2333 tformat[format - bufformat] = '\0';
2335 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *));
2338 case 'c' : // Character or character array
2342 cupsFilePutChar(fp, va_arg(ap, int));
2346 cupsFileWrite(fp, va_arg(ap, char *), width);
2351 case 's' : // String
2352 if ((s = va_arg(ap, char *)) == NULL)
2353 s = (char *)"(nil)";
2356 if (slen > width && prec != width)
2364 for (i = width - slen; i > 0; i --, bytes ++)
2365 cupsFilePutChar(fp, ' ');
2368 for (i = slen; i > 0; i --, s ++, bytes ++)
2370 if (*s == '\\' || *s == '\"')
2372 cupsFilePutChar(fp, '\\');
2376 cupsFilePutChar(fp, *s);
2381 for (i = width - slen; i > 0; i --, bytes ++)
2382 cupsFilePutChar(fp, ' ');
2389 cupsFilePutChar(fp, *format++);
2396 // Return the number of characters written.
2402 // 'ppdcSource::read_file()' - Read a driver source file.
2406 ppdcSource::read_file(const char *f, // I - File to read
2407 cups_file_t *ffp) // I - File pointer to use
2409 ppdcFile *fp = new ppdcFile(f, ffp);
2413 if (cond_current != cond_stack)
2414 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."), f);
2419 // 'ppdcSource::scan_file()' - Scan a driver source file.
2423 ppdcSource::scan_file(ppdcFile *fp, // I - File to read
2424 ppdcDriver *td, // I - Driver template
2425 bool inc) // I - Including?
2427 ppdcDriver *d; // Current driver
2428 ppdcGroup *g, // Current group
2429 *mg, // Matching group
2430 *general, // General options group
2431 *install; // Installable options group
2432 ppdcOption *o; // Current option
2433 ppdcChoice *c; // Current choice
2434 char temp[256], // Token from file...
2435 *ptr; // Pointer into token
2436 int isdefault; // Default option?
2439 // Initialize things as needed...
2446 d = new ppdcDriver(td);
2448 if ((general = d->find_group("General")) == NULL)
2450 general = new ppdcGroup("General", NULL);
2451 d->add_group(general);
2454 if ((install = d->find_group("InstallableOptions")) == NULL)
2456 install = new ppdcGroup("InstallableOptions", "Installable Options");
2457 d->add_group(install);
2460 // Loop until EOF or }
2464 while (get_token(fp, temp, sizeof(temp)))
2468 // Mark the next choice as the default
2471 for (ptr = temp; ptr[1]; ptr ++)
2478 // Don't mark the next choice as the default
2482 if (!_cups_strcasecmp(temp, "}"))
2484 // Close this one out...
2487 else if (!_cups_strcasecmp(temp, "{"))
2489 // Open a new child...
2492 else if (!_cups_strcasecmp(temp, "#if"))
2494 if ((cond_current - cond_stack) >= 100)
2496 _cupsLangPrintf(stderr,
2497 _("ppdc: Too many nested #if's on line %d of %s."),
2498 fp->line, fp->filename);
2503 if (get_integer(fp) > 0)
2504 *cond_current = PPDC_COND_SATISFIED;
2507 *cond_current = PPDC_COND_SKIP;
2508 cond_state |= PPDC_COND_SKIP;
2511 else if (!_cups_strcasecmp(temp, "#elif"))
2513 if (cond_current == cond_stack)
2515 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
2516 fp->line, fp->filename);
2520 if (*cond_current & PPDC_COND_SATISFIED)
2523 *cond_current |= PPDC_COND_SKIP;
2525 else if (get_integer(fp) > 0)
2527 *cond_current |= PPDC_COND_SATISFIED;
2528 *cond_current &= ~PPDC_COND_SKIP;
2531 *cond_current |= PPDC_COND_SKIP;
2533 // Update the current state
2534 int *cond_temp = cond_current; // Temporary stack pointer
2536 cond_state = PPDC_COND_NORMAL;
2537 while (cond_temp > cond_stack)
2538 if (*cond_temp & PPDC_COND_SKIP)
2540 cond_state = PPDC_COND_SKIP;
2546 else if (!_cups_strcasecmp(temp, "#else"))
2548 if (cond_current == cond_stack)
2550 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
2551 fp->line, fp->filename);
2555 if (*cond_current & PPDC_COND_SATISFIED)
2556 *cond_current |= PPDC_COND_SKIP;
2559 *cond_current |= PPDC_COND_SATISFIED;
2560 *cond_current &= ~PPDC_COND_SKIP;
2563 // Update the current state
2564 int *cond_temp = cond_current; // Temporary stack pointer
2566 cond_state = PPDC_COND_NORMAL;
2567 while (cond_temp > cond_stack)
2568 if (*cond_temp & PPDC_COND_SKIP)
2570 cond_state = PPDC_COND_SKIP;
2576 else if (!_cups_strcasecmp(temp, "#endif"))
2578 if (cond_current == cond_stack)
2580 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
2581 fp->line, fp->filename);
2587 // Update the current state
2588 int *cond_temp = cond_current; // Temporary stack pointer
2590 cond_state = PPDC_COND_NORMAL;
2591 while (cond_temp > cond_stack)
2592 if (*cond_temp & PPDC_COND_SKIP)
2594 cond_state = PPDC_COND_SKIP;
2600 else if (!_cups_strcasecmp(temp, "#define"))
2602 // Get the variable...
2605 else if (!_cups_strcasecmp(temp, "#include"))
2607 // #include filename
2608 char basedir[1024], // Base directory
2609 *baseptr, // Pointer into directory
2610 inctemp[1024], // Initial filename
2611 incname[1024]; // Include filename
2612 ppdcFile *incfile; // Include file
2613 int *old_current = cond_current;
2614 // Previous current stack
2617 // Get the include name...
2618 if (!get_token(fp, inctemp, sizeof(inctemp)))
2620 _cupsLangPrintf(stderr,
2621 _("ppdc: Expected include filename on line %d of "
2622 "%s."), fp->line, fp->filename);
2629 // Figure out the current directory...
2630 strlcpy(basedir, fp->filename, sizeof(basedir));
2632 if ((baseptr = strrchr(basedir, '/')) != NULL)
2635 strcpy(basedir, ".");
2637 // Find the include file...
2638 if (find_include(inctemp, basedir, incname, sizeof(incname)))
2640 // Open the include file, scan it, and then close it...
2641 incfile = new ppdcFile(incname);
2642 scan_file(incfile, d, true);
2645 if (cond_current != old_current)
2646 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."),
2652 _cupsLangPrintf(stderr,
2653 _("ppdc: Unable to find include file \"%s\" on line %d "
2654 "of %s."), inctemp, fp->line, fp->filename);
2658 else if (!_cups_strcasecmp(temp, "#media"))
2660 ppdcMediaSize *m; // Media size
2663 // Get a media size...
2673 else if (!_cups_strcasecmp(temp, "#po"))
2675 ppdcCatalog *cat; // Message catalog
2678 // Get a message catalog...
2688 else if (!_cups_strcasecmp(temp, "Attribute") ||
2689 !_cups_strcasecmp(temp, "LocAttribute"))
2691 ppdcAttr *a; // Attribute
2694 // Get an attribute...
2695 a = get_attr(fp, !_cups_strcasecmp(temp, "LocAttribute"));
2704 else if (!_cups_strcasecmp(temp, "Choice"))
2717 // Add it to the current option...
2720 _cupsLangPrintf(stderr,
2721 _("ppdc: Choice found on line %d of %s with no "
2722 "Option."), fp->line, fp->filename);
2729 o->set_defchoice(c);
2731 else if (!_cups_strcasecmp(temp, "ColorDevice"))
2733 // ColorDevice boolean
2737 d->color_device = get_boolean(fp);
2739 else if (!_cups_strcasecmp(temp, "ColorModel"))
2741 // Get the color model
2742 c = get_color_model(fp);
2752 // Add the choice to the ColorModel option...
2753 if ((o = d->find_option("ColorModel")) == NULL)
2755 // Create the ColorModel option...
2756 o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f);
2764 o->set_defchoice(c);
2768 else if (!_cups_strcasecmp(temp, "ColorProfile"))
2770 ppdcProfile *p; // Color profile
2773 // Get the color profile...
2774 p = get_color_profile(fp);
2781 d->profiles->add(p);
2784 else if (!_cups_strcasecmp(temp, "Copyright"))
2787 char copytemp[8192], // Copyright string
2788 *copyptr, // Pointer into string
2789 *copyend; // Pointer to end of string
2792 // Get the copyright string...
2793 if (!get_token(fp, copytemp, sizeof(temp)))
2795 _cupsLangPrintf(stderr,
2796 _("ppdc: Expected string after Copyright on line %d "
2797 "of %s."), fp->line, fp->filename);
2804 // Break it up into individual lines...
2805 for (copyptr = copytemp; copyptr; copyptr = copyend)
2807 if ((copyend = strchr(copyptr, '\n')) != NULL)
2810 d->copyright->add(new ppdcString(copyptr));
2813 else if (!_cups_strcasecmp(temp, "CustomMedia"))
2815 ppdcMediaSize *m; // Media size
2818 // Get a custom media size...
2819 m = get_custom_size(fp);
2831 d->set_default_size(m);
2833 else if (!_cups_strcasecmp(temp, "Cutter"))
2836 int have_cutter; // Have a paper cutter?
2839 have_cutter = get_boolean(fp);
2840 if (have_cutter <= 0 || cond_state)
2843 if ((o = d->find_option("CutMedia")) == NULL)
2845 o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f);
2850 c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice");
2852 o->set_defchoice(c);
2854 c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice");
2860 else if (!_cups_strcasecmp(temp, "Darkness"))
2862 // Get the darkness choice...
2863 c = get_generic(fp, "Darkness", NULL, "cupsCompression");
2873 // Add the choice to the cupsDarkness option...
2874 if ((o = d->find_option_group("cupsDarkness", &mg)) == NULL)
2876 // Create the cupsDarkness option...
2877 o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
2881 else if (mg != general)
2883 _cupsLangPrintf(stderr,
2884 _("ppdc: Option %s defined in two different groups on "
2885 "line %d of %s."), "cupsDarkness", fp->line,
2894 o->set_defchoice(c);
2898 else if (!_cups_strcasecmp(temp, "DriverType"))
2900 int i; // Looping var
2903 // DriverType keyword
2904 if (!get_token(fp, temp, sizeof(temp)))
2906 _cupsLangPrintf(stderr,
2907 _("ppdc: Expected driver type keyword following "
2908 "DriverType on line %d of %s."),
2909 fp->line, fp->filename);
2916 for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
2917 if (!_cups_strcasecmp(temp, driver_types[i]))
2920 if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
2921 d->type = (ppdcDrvType)i;
2922 else if (!_cups_strcasecmp(temp, "dymo"))
2923 d->type = PPDC_DRIVER_LABEL;
2925 _cupsLangPrintf(stderr,
2926 _("ppdc: Unknown driver type %s on line %d of %s."),
2927 temp, fp->line, fp->filename);
2929 else if (!_cups_strcasecmp(temp, "Duplex"))
2931 else if (!_cups_strcasecmp(temp, "Filter"))
2933 ppdcFilter *f; // Filter
2936 // Get the filter value...
2946 else if (!_cups_strcasecmp(temp, "Finishing"))
2948 // Get the finishing choice...
2949 c = get_generic(fp, "Finishing", "OutputType", NULL);
2959 // Add the choice to the cupsFinishing option...
2960 if ((o = d->find_option_group("cupsFinishing", &mg)) == NULL)
2962 // Create the cupsFinishing option...
2963 o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
2967 else if (mg != general)
2969 _cupsLangPrintf(stderr,
2970 _("ppdc: Option %s defined in two different groups on "
2971 "line %d of %s."), "cupsFinishing", fp->line,
2980 o->set_defchoice(c);
2984 else if (!_cups_strcasecmp(temp, "Font") ||
2985 !_cups_strcasecmp(temp, "#font"))
2987 ppdcFont *f; // Font
2998 if (!_cups_strcasecmp(temp, "#font"))
3004 d->set_default_font(f);
3008 else if (!_cups_strcasecmp(temp, "Group"))
3011 ppdcGroup *tempg = get_group(fp, d);
3018 if (!d->find_group(tempg->name->value))
3023 if (!d->find_group(tempg->name->value))
3024 d->add_group(tempg);
3029 else if (!_cups_strcasecmp(temp, "HWMargins"))
3031 // HWMargins left bottom right top
3032 d->left_margin = get_measurement(fp);
3033 d->bottom_margin = get_measurement(fp);
3034 d->right_margin = get_measurement(fp);
3035 d->top_margin = get_measurement(fp);
3037 else if (!_cups_strcasecmp(temp, "InputSlot"))
3039 // Get the input slot choice...
3040 c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
3050 // Add the choice to the InputSlot option...
3052 if ((o = d->find_option_group("InputSlot", &mg)) == NULL)
3054 // Create the InputSlot option...
3055 o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
3056 PPDC_SECTION_ANY, 10.0f);
3060 else if (mg != general)
3062 _cupsLangPrintf(stderr,
3063 _("ppdc: Option %s defined in two different groups on "
3064 "line %d of %s."), "InputSlot", fp->line,
3073 o->set_defchoice(c);
3077 else if (!_cups_strcasecmp(temp, "Installable"))
3079 // Get the installable option...
3080 o = get_installable(fp);
3082 // Add it as needed...
3088 install->add_option(o);
3093 else if (!_cups_strcasecmp(temp, "ManualCopies"))
3095 // ManualCopies boolean
3099 d->manual_copies = get_boolean(fp);
3101 else if (!_cups_strcasecmp(temp, "Manufacturer"))
3103 // Manufacturer name
3104 char name[256]; // Model name string
3107 if (!get_token(fp, name, sizeof(name)))
3109 _cupsLangPrintf(stderr,
3110 _("ppdc: Expected name after Manufacturer on line %d "
3111 "of %s."), fp->line, fp->filename);
3116 d->set_manufacturer(name);
3118 else if (!_cups_strcasecmp(temp, "MaxSize"))
3120 // MaxSize width length
3123 get_measurement(fp);
3124 get_measurement(fp);
3128 d->max_width = get_measurement(fp);
3129 d->max_length = get_measurement(fp);
3132 else if (!_cups_strcasecmp(temp, "MediaSize"))
3134 // MediaSize keyword
3135 char name[41]; // Media size name
3136 ppdcMediaSize *m, // Matching media size...
3137 *dm; // Driver media size...
3140 if (get_token(fp, name, sizeof(name)) == NULL)
3142 _cupsLangPrintf(stderr,
3143 _("ppdc: Expected name after MediaSize on line %d of "
3144 "%s."), fp->line, fp->filename);
3151 m = find_size(name);
3155 _cupsLangPrintf(stderr,
3156 _("ppdc: Unknown media size \"%s\" on line %d of "
3157 "%s."), name, fp->line, fp->filename);
3161 // Add this size to the driver...
3162 dm = new ppdcMediaSize(m->name->value, m->text->value,
3163 m->width, m->length, d->left_margin,
3164 d->bottom_margin, d->right_margin,
3169 d->set_default_size(dm);
3171 else if (!_cups_strcasecmp(temp, "MediaType"))
3173 // Get the media type choice...
3174 c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
3184 // Add the choice to the MediaType option...
3185 if ((o = d->find_option_group("MediaType", &mg)) == NULL)
3187 // Create the MediaType option...
3188 o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
3189 PPDC_SECTION_ANY, 10.0f);
3193 else if (mg != general)
3195 _cupsLangPrintf(stderr,
3196 _("ppdc: Option %s defined in two different groups on "
3197 "line %d of %s."), "MediaType", fp->line,
3206 o->set_defchoice(c);
3210 else if (!_cups_strcasecmp(temp, "MinSize"))
3212 // MinSize width length
3215 get_measurement(fp);
3216 get_measurement(fp);
3220 d->min_width = get_measurement(fp);
3221 d->min_length = get_measurement(fp);
3224 else if (!_cups_strcasecmp(temp, "ModelName"))
3227 char name[256]; // Model name string
3230 if (!get_token(fp, name, sizeof(name)))
3232 _cupsLangPrintf(stderr,
3233 _("ppdc: Expected name after ModelName on line %d of "
3234 "%s."), fp->line, fp->filename);
3239 d->set_model_name(name);
3241 else if (!_cups_strcasecmp(temp, "ModelNumber"))
3243 // ModelNumber number
3247 d->model_number = get_integer(fp);
3249 else if (!_cups_strcasecmp(temp, "Option"))
3252 ppdcOption *tempo = get_option(fp, d, g);
3259 if (!g->find_option(tempo->name->value))
3264 if (!g->find_option(tempo->name->value))
3265 g->add_option(tempo);
3270 else if (!_cups_strcasecmp(temp, "FileName"))
3273 char name[256]; // Filename string
3276 if (!get_token(fp, name, sizeof(name)))
3278 _cupsLangPrintf(stderr,
3279 _("ppdc: Expected name after FileName on line %d of "
3280 "%s."), fp->line, fp->filename);
3285 d->set_file_name(name);
3287 else if (!_cups_strcasecmp(temp, "PCFileName"))
3290 char name[256]; // PC filename string
3293 if (!get_token(fp, name, sizeof(name)))
3295 _cupsLangPrintf(stderr,
3296 _("ppdc: Expected name after PCFileName on line %d of "
3297 "%s."), fp->line, fp->filename);
3302 d->set_pc_file_name(name);
3304 else if (!_cups_strcasecmp(temp, "Resolution"))
3306 // Get the resolution choice...
3307 c = get_resolution(fp);
3317 // Add the choice to the Resolution option...
3318 if ((o = d->find_option_group("Resolution", &mg)) == NULL)
3320 // Create the Resolution option...
3321 o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
3326 else if (mg != general)
3328 _cupsLangPrintf(stderr,
3329 _("ppdc: Option %s defined in two different groups on "
3330 "line %d of %s."), "Resolution", fp->line,
3339 o->set_defchoice(c);
3343 else if (!_cups_strcasecmp(temp, "SimpleColorProfile"))
3345 ppdcProfile *p; // Color profile
3348 // Get the color profile...
3349 p = get_simple_profile(fp);
3356 d->profiles->add(p);
3359 else if (!_cups_strcasecmp(temp, "Throughput"))
3361 // Throughput number
3365 d->throughput = get_integer(fp);
3367 else if (!_cups_strcasecmp(temp, "UIConstraints"))
3369 ppdcConstraint *con; // Constraint
3372 con = get_constraint(fp);
3379 d->constraints->add(con);
3382 else if (!_cups_strcasecmp(temp, "VariablePaperSize"))
3384 // VariablePaperSize boolean
3388 d->variable_paper_size = get_boolean(fp);
3390 else if (!_cups_strcasecmp(temp, "Version"))
3393 char name[256]; // Model name string
3396 if (!get_token(fp, name, sizeof(name)))
3398 _cupsLangPrintf(stderr,
3399 _("ppdc: Expected string after Version on line %d of "
3400 "%s."), fp->line, fp->filename);
3405 d->set_version(name);
3409 _cupsLangPrintf(stderr,
3410 _("ppdc: Unknown token \"%s\" seen on line %d of %s."),
3411 temp, fp->line, fp->filename);
3416 // Done processing this block, is there anything to save?
3419 if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version ||
3422 // Nothing to save...
3427 // Got a driver, save it...
3437 // 'ppdcSource::set_variable()' - Set a variable.
3440 ppdcVariable * // O - Variable
3441 ppdcSource::set_variable(
3442 const char *name, // I - Name
3443 const char *value) // I - Value
3445 ppdcVariable *v; // Variable
3448 // See if the variable exists already...
3449 v = find_variable(name);
3452 // Change the variable value...
3453 v->set_value(value);
3457 // Create a new variable and add it...
3458 v = new ppdcVariable(name, value);
3467 // 'ppdcSource::write_file()' - Write the current source data to a file.
3470 int // O - 0 on success, -1 on error
3471 ppdcSource::write_file(const char *f) // I - File to write
3473 cups_file_t *fp; // Output file
3474 char bckname[1024]; // Backup file
3475 ppdcDriver *d; // Current driver
3476 ppdcString *st; // Current string
3477 ppdcAttr *a; // Current attribute
3478 ppdcConstraint *co; // Current constraint
3479 ppdcFilter *fi; // Current filter
3480 ppdcFont *fo; // Current font
3481 ppdcGroup *g; // Current group
3482 ppdcOption *o; // Current option
3483 ppdcChoice *ch; // Current choice
3484 ppdcProfile *p; // Current color profile
3485 ppdcMediaSize *si; // Current media size
3486 float left, // Current left margin
3487 bottom, // Current bottom margin
3488 right, // Current right margin
3489 top; // Current top margin
3490 int dtused[PPDC_DRIVER_MAX];// Driver type usage...
3493 // Rename the current file, if any, to .bck...
3494 snprintf(bckname, sizeof(bckname), "%s.bck", f);
3497 // Open the output file...
3498 fp = cupsFileOpen(f, "w");
3502 // Can't create file; restore backup and return...
3507 cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n");
3509 // Include standard files...
3510 cupsFilePuts(fp, "// Include necessary files...\n");
3511 cupsFilePuts(fp, "#include <font.defs>\n");
3512 cupsFilePuts(fp, "#include <media.defs>\n");
3514 memset(dtused, 0, sizeof(dtused));
3516 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3517 if (d->type > PPDC_DRIVER_PS && !dtused[d->type])
3519 cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]);
3520 dtused[d->type] = 1;
3523 // Output each driver...
3524 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3526 // Start the driver...
3527 cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value,
3528 d->model_name->value);
3529 cupsFilePuts(fp, "{\n");
3531 // Write the copyright stings...
3532 for (st = (ppdcString *)d->copyright->first();
3534 st = (ppdcString *)d->copyright->next())
3535 quotef(fp, " Copyright \"%s\"\n", st->value);
3537 // Write other strings and values...
3538 if (d->manufacturer && d->manufacturer->value)
3539 quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value);
3540 if (d->model_name->value)
3541 quotef(fp, " ModelName \"%s\"\n", d->model_name->value);
3542 if (d->file_name && d->file_name->value)
3543 quotef(fp, " FileName \"%s\"\n", d->file_name->value);
3544 if (d->pc_file_name && d->pc_file_name->value)
3545 quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
3546 if (d->version && d->version->value)
3547 quotef(fp, " Version \"%s\"\n", d->version->value);
3549 cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]);
3551 if (d->model_number)
3555 case PPDC_DRIVER_ESCP :
3556 cupsFilePuts(fp, " ModelNumber (");
3558 if (d->model_number & ESCP_DOTMATRIX)
3559 cupsFilePuts(fp, " $ESCP_DOTMATRIX");
3560 if (d->model_number & ESCP_MICROWEAVE)
3561 cupsFilePuts(fp, " $ESCP_MICROWEAVE");
3562 if (d->model_number & ESCP_STAGGER)
3563 cupsFilePuts(fp, " $ESCP_STAGGER");
3564 if (d->model_number & ESCP_ESCK)
3565 cupsFilePuts(fp, " $ESCP_ESCK");
3566 if (d->model_number & ESCP_EXT_UNITS)
3567 cupsFilePuts(fp, " $ESCP_EXT_UNITS");
3568 if (d->model_number & ESCP_EXT_MARGINS)
3569 cupsFilePuts(fp, " $ESCP_EXT_MARGINS");
3570 if (d->model_number & ESCP_USB)
3571 cupsFilePuts(fp, " $ESCP_USB");
3572 if (d->model_number & ESCP_PAGE_SIZE)
3573 cupsFilePuts(fp, " $ESCP_PAGE_SIZE");
3574 if (d->model_number & ESCP_RASTER_ESCI)
3575 cupsFilePuts(fp, " $ESCP_RASTER_ESCI");
3576 if (d->model_number & ESCP_REMOTE)
3577 cupsFilePuts(fp, " $ESCP_REMOTE");
3579 cupsFilePuts(fp, ")\n");
3582 case PPDC_DRIVER_PCL :
3583 cupsFilePuts(fp, " ModelNumber (");
3585 if (d->model_number & PCL_PAPER_SIZE)
3586 cupsFilePuts(fp, " $PCL_PAPER_SIZE");
3587 if (d->model_number & PCL_INKJET)
3588 cupsFilePuts(fp, " $PCL_INKJET");
3589 if (d->model_number & PCL_RASTER_END_COLOR)
3590 cupsFilePuts(fp, " $PCL_RASTER_END_COLOR");
3591 if (d->model_number & PCL_RASTER_CID)
3592 cupsFilePuts(fp, " $PCL_RASTER_CID");
3593 if (d->model_number & PCL_RASTER_CRD)
3594 cupsFilePuts(fp, " $PCL_RASTER_CRD");
3595 if (d->model_number & PCL_RASTER_SIMPLE)
3596 cupsFilePuts(fp, " $PCL_RASTER_SIMPLE");
3597 if (d->model_number & PCL_RASTER_RGB24)
3598 cupsFilePuts(fp, " $PCL_RASTER_RGB24");
3599 if (d->model_number & PCL_PJL)
3600 cupsFilePuts(fp, " $PCL_PJL");
3601 if (d->model_number & PCL_PJL_PAPERWIDTH)
3602 cupsFilePuts(fp, " $PCL_PJL_PAPERWIDTH");
3603 if (d->model_number & PCL_PJL_HPGL2)
3604 cupsFilePuts(fp, " $PCL_PJL_HPGL2");
3605 if (d->model_number & PCL_PJL_PCL3GUI)
3606 cupsFilePuts(fp, " $PCL_PJL_PCL3GUI");
3607 if (d->model_number & PCL_PJL_RESOLUTION)
3608 cupsFilePuts(fp, " $PCL_PJL_RESOLUTION");
3610 cupsFilePuts(fp, ")\n");
3613 case PPDC_DRIVER_LABEL :
3614 cupsFilePuts(fp, " ModelNumber ");
3616 switch (d->model_number)
3619 cupsFilePuts(fp, "$DYMO_3x0\n");
3622 case ZEBRA_EPL_LINE :
3623 cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n");
3626 case ZEBRA_EPL_PAGE :
3627 cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n");
3631 cupsFilePuts(fp, "$ZEBRA_ZPL\n");
3635 cupsFilePuts(fp, "$ZEBRA_CPCL\n");
3638 case INTELLITECH_PCL :
3639 cupsFilePuts(fp, "$INTELLITECH_PCL\n");
3643 cupsFilePrintf(fp, "%d\n", d->model_number);
3648 case PPDC_DRIVER_EPSON :
3649 cupsFilePuts(fp, " ModelNumber ");
3651 switch (d->model_number)
3654 cupsFilePuts(fp, "$EPSON_9PIN\n");
3658 cupsFilePuts(fp, "$EPSON_24PIN\n");
3662 cupsFilePuts(fp, "$EPSON_COLOR\n");
3666 cupsFilePuts(fp, "$EPSON_PHOTO\n");
3670 cupsFilePuts(fp, "$EPSON_ICOLOR\n");
3674 cupsFilePuts(fp, "$EPSON_IPHOTO\n");
3678 cupsFilePrintf(fp, "%d\n", d->model_number);
3683 case PPDC_DRIVER_HP :
3684 cupsFilePuts(fp, " ModelNumber ");
3685 switch (d->model_number)
3688 cupsFilePuts(fp, "$HP_LASERJET\n");
3692 cupsFilePuts(fp, "$HP_DESKJET\n");
3696 cupsFilePuts(fp, "$HP_DESKJET2\n");
3700 cupsFilePrintf(fp, "%d\n", d->model_number);
3704 cupsFilePuts(fp, ")\n");
3708 cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number);
3713 if (d->manual_copies)
3714 cupsFilePuts(fp, " ManualCopies Yes\n");
3716 if (d->color_device)
3717 cupsFilePuts(fp, " ColorDevice Yes\n");
3720 cupsFilePrintf(fp, " Throughput %d\n", d->throughput);
3722 // Output all of the attributes...
3723 for (a = (ppdcAttr *)d->attrs->first();
3725 a = (ppdcAttr *)d->attrs->next())
3726 if (a->text->value && a->text->value[0])
3727 quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
3728 a->name->value, a->selector->value ? a->selector->value : "",
3729 a->text->value, a->value->value ? a->value->value : "");
3731 quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n",
3732 a->name->value, a->selector->value ? a->selector->value : "",
3733 a->value->value ? a->value->value : "");
3735 // Output all of the constraints...
3736 for (co = (ppdcConstraint *)d->constraints->first();
3738 co = (ppdcConstraint *)d->constraints->next())
3740 if (co->option1->value[0] == '*')
3741 cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value,
3742 co->choice1->value ? co->choice1->value : "");
3744 cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value,
3745 co->choice1->value ? co->choice1->value : "");
3747 if (co->option2->value[0] == '*')
3748 cupsFilePrintf(fp, " %s %s\"\n", co->option2->value,
3749 co->choice2->value ? co->choice2->value : "");
3751 cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value,
3752 co->choice2->value ? co->choice2->value : "");
3755 // Output all of the filters...
3756 for (fi = (ppdcFilter *)d->filters->first();
3758 fi = (ppdcFilter *)d->filters->next())
3759 cupsFilePrintf(fp, " Filter \"%s %d %s\"\n",
3760 fi->mime_type->value, fi->cost, fi->program->value);
3762 // Output all of the fonts...
3763 for (fo = (ppdcFont *)d->fonts->first();
3765 fo = (ppdcFont *)d->fonts->next())
3766 if (!strcmp(fo->name->value, "*"))
3767 cupsFilePuts(fp, " Font *\n");
3769 cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
3770 fo->name->value, fo->encoding->value,
3771 fo->version->value, fo->charset->value,
3772 fo->status == PPDC_FONT_ROM ? "ROM" : "Disk");
3774 // Output all options...
3775 for (g = (ppdcGroup *)d->groups->first();
3777 g = (ppdcGroup *)d->groups->next())
3779 if (g->options->count == 0)
3782 if (g->text->value && g->text->value[0])
3783 quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value);
3785 cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value);
3787 for (o = (ppdcOption *)g->options->first();
3789 o = (ppdcOption *)g->options->next())
3791 if (o->choices->count == 0)
3794 if (o->text->value && o->text->value[0])
3795 quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value);
3797 cupsFilePrintf(fp, " Option \"%s\"", o->name->value);
3799 cupsFilePrintf(fp, " %s %s %.1f\n",
3800 o->type == PPDC_BOOLEAN ? "Boolean" :
3801 o->type == PPDC_PICKONE ? "PickOne" : "PickMany",
3802 o->section == PPDC_SECTION_ANY ? "AnySetup" :
3803 o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" :
3804 o->section == PPDC_SECTION_EXIT ? "ExitServer" :
3805 o->section == PPDC_SECTION_JCL ? "JCLSetup" :
3806 o->section == PPDC_SECTION_PAGE ? "PageSetup" :
3810 for (ch = (ppdcChoice *)o->choices->first();
3812 ch = (ppdcChoice *)o->choices->next())
3814 if (ch->text->value && ch->text->value[0])
3815 quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n",
3816 o->defchoice == ch->name ? "*" : "",
3817 ch->name->value, ch->text->value,
3818 ch->code->value ? ch->code->value : "");
3820 quotef(fp, " %sChoice \"%s\" \"%s\"\n",
3821 o->defchoice == ch->name ? "*" : "",
3823 ch->code->value ? ch->code->value : "");
3828 // Output all of the color profiles...
3829 for (p = (ppdcProfile *)d->profiles->first();
3831 p = (ppdcProfile *)d->profiles->next())
3832 cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f "
3833 "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
3834 p->resolution->value, p->media_type->value,
3835 p->density, p->gamma,
3836 p->profile[0], p->profile[1], p->profile[2],
3837 p->profile[3], p->profile[4], p->profile[5],
3838 p->profile[6], p->profile[7], p->profile[8]);
3840 // Output all of the media sizes...
3846 for (si = (ppdcMediaSize *)d->sizes->first();
3848 si = (ppdcMediaSize *)d->sizes->next())
3849 if (si->size_code->value && si->region_code->value)
3851 // Output a custom media size...
3852 quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
3853 si->name == d->default_size ? "*" : "", si->name->value,
3854 si->text->value, si->width, si->length, si->left, si->bottom,
3855 si->right, si->top, si->size_code->value,
3856 si->region_code->value);
3860 // Output a standard media size...
3861 if (fabs(left - si->left) > 0.1 ||
3862 fabs(bottom - si->bottom) > 0.1 ||
3863 fabs(right - si->right) > 0.1 ||
3864 fabs(top - si->top) > 0.1)
3866 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3867 si->left, si->bottom, si->right, si->top);
3870 bottom = si->bottom;
3875 cupsFilePrintf(fp, " %sMediaSize %s\n",
3876 si->name == d->default_size ? "*" : "",
3880 if (d->variable_paper_size)
3882 cupsFilePuts(fp, " VariablePaperSize Yes\n");
3884 if (fabs(left - d->left_margin) > 0.1 ||
3885 fabs(bottom - d->bottom_margin) > 0.1 ||
3886 fabs(right - d->right_margin) > 0.1 ||
3887 fabs(top - d->top_margin) > 0.1)
3889 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3890 d->left_margin, d->bottom_margin, d->right_margin,
3894 cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length);
3895 cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length);
3898 // End the driver...
3899 cupsFilePuts(fp, "}\n");
3902 // Close the file and return...
3910 // End of "$Id: ppdc-source.cxx 10379 2012-03-23 22:16:22Z mike $".