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