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