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