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