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