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