]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdc-source.cxx
Merge changes from CUPS 1.6svn-r9939.
[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
MS
22// ppdcSource::find_po() - Find a message catalog for the given
23// locale...
ac884b6a
MS
24// ppdcSource::find_size() - Find a media size.
25// ppdcSource::find_variable() - Find a variable.
26// ppdcSource::get_attr() - Get an attribute.
27// ppdcSource::get_boolean() - Get a boolean value.
28// ppdcSource::get_choice() - Get a choice.
29// ppdcSource::get_color_model() - Get an old-style color model option.
30// ppdcSource::get_color_order() - Get an old-style color order value.
31// ppdcSource::get_color_profile() - Get a color profile definition.
32// ppdcSource::get_color_space() - Get an old-style colorspace value.
33// ppdcSource::get_constraint() - Get a constraint.
94da7e34
MS
34// ppdcSource::get_custom_size() - Get a custom media size definition from
35// a file.
36// ppdcSource::get_duplex() - Get a duplex option.
ac884b6a
MS
37// ppdcSource::get_filter() - Get a filter.
38// ppdcSource::get_float() - Get a single floating-point number.
39// ppdcSource::get_font() - Get a font definition.
40// ppdcSource::get_generic() - Get a generic old-style option.
41// ppdcSource::get_group() - Get an option group.
42// ppdcSource::get_installable() - Get an installable option.
ac884b6a
MS
43// ppdcSource::get_integer() - Get an integer value from a file.
44// ppdcSource::get_measurement() - Get a measurement value.
45// ppdcSource::get_option() - Get an option definition.
94da7e34 46// ppdcSource::get_po() - Get a message catalog.
ac884b6a
MS
47// ppdcSource::get_resolution() - Get an old-style resolution option.
48// ppdcSource::get_simple_profile() - Get a simple color profile definition.
49// ppdcSource::get_size() - Get a media size definition from a file.
50// ppdcSource::get_token() - Get a token from a file.
51// ppdcSource::get_variable() - Get a variable definition.
52// ppdcSource::quotef() - Write a formatted, quoted string...
53// ppdcSource::read_file() - Read a driver source file.
54// ppdcSource::scan_file() - Scan a driver source file.
55// ppdcSource::set_variable() - Set a variable.
56// ppdcSource::write_file() - Write the current source data to a file.
57//
58
59//
60// Include necessary headers...
61//
62
38e73f87 63#include "ppdc-private.h"
ac884b6a
MS
64#include <limits.h>
65#include <math.h>
66#include <unistd.h>
67#include <cups/raster.h>
68#include "data/epson.h"
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//
278// 'ppdcSource::find_po()' - Find a message catalog for the given locale...
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++;
2276
2277 if (!*format)
2278 break;
2279
2280 type = *format++;
2281
2282 switch (type)
2283 {
2284 case 'E' : // Floating point formats
2285 case 'G' :
2286 case 'e' :
2287 case 'f' :
2288 case 'g' :
2289 if ((format - bufformat + 1) > (int)sizeof(tformat))
2290 break;
2291
2292 strncpy(tformat, bufformat, format - bufformat);
2293 tformat[format - bufformat] = '\0';
2294
2295 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double));
2296 break;
2297
2298 case 'B' : // Integer formats
2299 case 'X' :
2300 case 'b' :
2301 case 'd' :
2302 case 'i' :
2303 case 'o' :
2304 case 'u' :
2305 case 'x' :
2306 if ((format - bufformat + 1) > (int)sizeof(tformat))
2307 break;
2308
2309 strncpy(tformat, bufformat, format - bufformat);
2310 tformat[format - bufformat] = '\0';
2311
2312 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
2313 break;
88f9aafc 2314
ac884b6a
MS
2315 case 'p' : // Pointer value
2316 if ((format - bufformat + 1) > (int)sizeof(tformat))
2317 break;
2318
2319 strncpy(tformat, bufformat, format - bufformat);
2320 tformat[format - bufformat] = '\0';
2321
2322 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *));
2323 break;
2324
2325 case 'c' : // Character or character array
2326 if (width <= 1)
2327 {
2328 bytes ++;
2329 cupsFilePutChar(fp, va_arg(ap, int));
2330 }
2331 else
2332 {
2333 cupsFileWrite(fp, va_arg(ap, char *), width);
2334 bytes += width;
2335 }
2336 break;
2337
2338 case 's' : // String
2339 if ((s = va_arg(ap, char *)) == NULL)
2340 s = (char *)"(nil)";
2341
2342 slen = strlen(s);
2343 if (slen > width && prec != width)
2344 width = slen;
2345
2346 if (slen > width)
2347 slen = width;
2348
2349 if (sign != '-')
2350 {
2351 for (i = width - slen; i > 0; i --, bytes ++)
2352 cupsFilePutChar(fp, ' ');
2353 }
2354
2355 for (i = slen; i > 0; i --, s ++, bytes ++)
2356 {
2357 if (*s == '\\' || *s == '\"')
2358 {
2359 cupsFilePutChar(fp, '\\');
2360 bytes ++;
2361 }
2362
2363 cupsFilePutChar(fp, *s);
2364 }
2365
2366 if (sign == '-')
2367 {
2368 for (i = width - slen; i > 0; i --, bytes ++)
2369 cupsFilePutChar(fp, ' ');
2370 }
2371 break;
2372 }
2373 }
2374 else
2375 {
2376 cupsFilePutChar(fp, *format++);
2377 bytes ++;
2378 }
2379 }
2380
2381 va_end(ap);
2382
2383 // Return the number of characters written.
2384 return (bytes);
2385}
2386
2387
2388//
2389// 'ppdcSource::read_file()' - Read a driver source file.
2390//
2391
2392void
4509bb49
MS
2393ppdcSource::read_file(const char *f, // I - File to read
2394 cups_file_t *ffp) // I - File pointer to use
ac884b6a 2395{
4509bb49 2396 ppdcFile *fp = new ppdcFile(f, ffp);
ac884b6a
MS
2397 scan_file(fp);
2398 delete fp;
bdd6c45b
MS
2399
2400 if (cond_current != cond_stack)
0837b7e8 2401 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."), f);
ac884b6a
MS
2402}
2403
2404
2405//
2406// 'ppdcSource::scan_file()' - Scan a driver source file.
2407//
2408
2409void
2410ppdcSource::scan_file(ppdcFile *fp, // I - File to read
2411 ppdcDriver *td, // I - Driver template
2412 bool inc) // I - Including?
2413{
2414 ppdcDriver *d; // Current driver
2415 ppdcGroup *g, // Current group
97c9a8d7 2416 *mg, // Matching group
ac884b6a
MS
2417 *general, // General options group
2418 *install; // Installable options group
2419 ppdcOption *o; // Current option
2420 ppdcChoice *c; // Current choice
2421 char temp[256], // Token from file...
2422 *ptr; // Pointer into token
2423 int isdefault; // Default option?
2424
2425
2426 // Initialize things as needed...
2427 if (inc && td)
97c9a8d7 2428 {
ac884b6a 2429 d = td;
97c9a8d7
MS
2430 d->retain();
2431 }
ac884b6a
MS
2432 else
2433 d = new ppdcDriver(td);
2434
2435 if ((general = d->find_group("General")) == NULL)
2436 {
2437 general = new ppdcGroup("General", NULL);
2438 d->add_group(general);
2439 }
2440
2441 if ((install = d->find_group("InstallableOptions")) == NULL)
2442 {
2443 install = new ppdcGroup("InstallableOptions", "Installable Options");
2444 d->add_group(install);
2445 }
2446
2447 // Loop until EOF or }
2448 o = 0;
2449 g = general;
bdd6c45b 2450
ac884b6a
MS
2451 while (get_token(fp, temp, sizeof(temp)))
2452 {
2453 if (temp[0] == '*')
2454 {
2455 // Mark the next choice as the default
2456 isdefault = 1;
2457
2458 for (ptr = temp; ptr[1]; ptr ++)
2459 *ptr = ptr[1];
2460
2461 *ptr = '\0';
2462 }
2463 else
2464 {
2465 // Don't mark the next choice as the default
2466 isdefault = 0;
2467 }
2468
88f9aafc 2469 if (!_cups_strcasecmp(temp, "}"))
ac884b6a
MS
2470 {
2471 // Close this one out...
2472 break;
2473 }
88f9aafc 2474 else if (!_cups_strcasecmp(temp, "{"))
ac884b6a
MS
2475 {
2476 // Open a new child...
2477 scan_file(fp, d);
2478 }
88f9aafc 2479 else if (!_cups_strcasecmp(temp, "#if"))
bdd6c45b
MS
2480 {
2481 if ((cond_current - cond_stack) >= 100)
2482 {
61cf44e2 2483 _cupsLangPrintf(stderr,
0837b7e8 2484 _("ppdc: Too many nested #if's on line %d of %s."),
61cf44e2 2485 fp->line, fp->filename);
bdd6c45b
MS
2486 break;
2487 }
2488
2489 cond_current ++;
97c9a8d7 2490 if (get_integer(fp) > 0)
bdd6c45b
MS
2491 *cond_current = PPDC_COND_SATISFIED;
2492 else
2493 {
2494 *cond_current = PPDC_COND_SKIP;
2495 cond_state |= PPDC_COND_SKIP;
2496 }
2497 }
88f9aafc 2498 else if (!_cups_strcasecmp(temp, "#elif"))
bdd6c45b
MS
2499 {
2500 if (cond_current == cond_stack)
2501 {
0837b7e8 2502 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
61cf44e2 2503 fp->line, fp->filename);
bdd6c45b
MS
2504 break;
2505 }
2506
2507 if (*cond_current & PPDC_COND_SATISFIED)
2508 {
2509 get_integer(fp);
2510 *cond_current |= PPDC_COND_SKIP;
2511 }
97c9a8d7 2512 else if (get_integer(fp) > 0)
bdd6c45b
MS
2513 {
2514 *cond_current |= PPDC_COND_SATISFIED;
2515 *cond_current &= ~PPDC_COND_SKIP;
2516 }
2517 else
2518 *cond_current |= PPDC_COND_SKIP;
2519
2520 // Update the current state
2521 int *cond_temp = cond_current; // Temporary stack pointer
2522
2523 cond_state = PPDC_COND_NORMAL;
2524 while (cond_temp > cond_stack)
2525 if (*cond_temp & PPDC_COND_SKIP)
2526 {
2527 cond_state = PPDC_COND_SKIP;
2528 break;
2529 }
2530 else
2531 cond_temp --;
2532 }
88f9aafc 2533 else if (!_cups_strcasecmp(temp, "#else"))
bdd6c45b
MS
2534 {
2535 if (cond_current == cond_stack)
2536 {
0837b7e8 2537 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
61cf44e2 2538 fp->line, fp->filename);
bdd6c45b
MS
2539 break;
2540 }
2541
2542 if (*cond_current & PPDC_COND_SATISFIED)
2543 *cond_current |= PPDC_COND_SKIP;
2544 else
2545 {
2546 *cond_current |= PPDC_COND_SATISFIED;
2547 *cond_current &= ~PPDC_COND_SKIP;
2548 }
2549
2550 // Update the current state
2551 int *cond_temp = cond_current; // Temporary stack pointer
2552
2553 cond_state = PPDC_COND_NORMAL;
2554 while (cond_temp > cond_stack)
2555 if (*cond_temp & PPDC_COND_SKIP)
2556 {
2557 cond_state = PPDC_COND_SKIP;
2558 break;
2559 }
2560 else
2561 cond_temp --;
2562 }
88f9aafc 2563 else if (!_cups_strcasecmp(temp, "#endif"))
bdd6c45b
MS
2564 {
2565 if (cond_current == cond_stack)
2566 {
0837b7e8 2567 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
61cf44e2 2568 fp->line, fp->filename);
bdd6c45b
MS
2569 break;
2570 }
2571
2572 cond_current --;
2573
2574 // Update the current state
2575 int *cond_temp = cond_current; // Temporary stack pointer
2576
2577 cond_state = PPDC_COND_NORMAL;
2578 while (cond_temp > cond_stack)
2579 if (*cond_temp & PPDC_COND_SKIP)
2580 {
2581 cond_state = PPDC_COND_SKIP;
2582 break;
2583 }
2584 else
2585 cond_temp --;
2586 }
88f9aafc 2587 else if (!_cups_strcasecmp(temp, "#define"))
ac884b6a
MS
2588 {
2589 // Get the variable...
2590 get_variable(fp);
2591 }
88f9aafc 2592 else if (!_cups_strcasecmp(temp, "#include"))
ac884b6a
MS
2593 {
2594 // #include filename
2595 char basedir[1024], // Base directory
2596 *baseptr, // Pointer into directory
2597 inctemp[1024], // Initial filename
2598 incname[1024]; // Include filename
2599 ppdcFile *incfile; // Include file
bdd6c45b
MS
2600 int *old_current = cond_current;
2601 // Previous current stack
ac884b6a
MS
2602
2603
2604 // Get the include name...
2605 if (!get_token(fp, inctemp, sizeof(inctemp)))
2606 {
61cf44e2
MS
2607 _cupsLangPrintf(stderr,
2608 _("ppdc: Expected include filename on line %d of "
0837b7e8 2609 "%s."), fp->line, fp->filename);
ac884b6a
MS
2610 break;
2611 }
2612
bdd6c45b
MS
2613 if (cond_state)
2614 continue;
2615
ac884b6a
MS
2616 // Figure out the current directory...
2617 strlcpy(basedir, fp->filename, sizeof(basedir));
2618
2619 if ((baseptr = strrchr(basedir, '/')) != NULL)
bdd6c45b 2620 *baseptr = '\0';
ac884b6a 2621 else
bdd6c45b 2622 strcpy(basedir, ".");
ac884b6a
MS
2623
2624 // Find the include file...
2625 if (find_include(inctemp, basedir, incname, sizeof(incname)))
2626 {
2627 // Open the include file, scan it, and then close it...
2628 incfile = new ppdcFile(incname);
2629 scan_file(incfile, d, true);
2630 delete incfile;
bdd6c45b
MS
2631
2632 if (cond_current != old_current)
0837b7e8 2633 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."),
61cf44e2 2634 incname);
ac884b6a
MS
2635 }
2636 else
2637 {
bdd6c45b 2638 // Can't find it!
61cf44e2
MS
2639 _cupsLangPrintf(stderr,
2640 _("ppdc: Unable to find include file \"%s\" on line %d "
0837b7e8 2641 "of %s."), inctemp, fp->line, fp->filename);
ac884b6a
MS
2642 break;
2643 }
2644 }
88f9aafc 2645 else if (!_cups_strcasecmp(temp, "#media"))
ac884b6a
MS
2646 {
2647 ppdcMediaSize *m; // Media size
2648
2649
2650 // Get a media size...
2651 m = get_size(fp);
2652 if (m)
bdd6c45b
MS
2653 {
2654 if (cond_state)
2655 m->release();
2656 else
2657 sizes->add(m);
2658 }
ac884b6a 2659 }
88f9aafc 2660 else if (!_cups_strcasecmp(temp, "#po"))
ac884b6a
MS
2661 {
2662 ppdcCatalog *cat; // Message catalog
2663
2664
2665 // Get a message catalog...
2666 cat = get_po(fp);
2667 if (cat)
bdd6c45b
MS
2668 {
2669 if (cond_state)
2670 cat->release();
2671 else
2672 po_files->add(cat);
2673 }
ac884b6a 2674 }
88f9aafc
MS
2675 else if (!_cups_strcasecmp(temp, "Attribute") ||
2676 !_cups_strcasecmp(temp, "LocAttribute"))
ac884b6a
MS
2677 {
2678 ppdcAttr *a; // Attribute
2679
2680
2681 // Get an attribute...
88f9aafc 2682 a = get_attr(fp, !_cups_strcasecmp(temp, "LocAttribute"));
ac884b6a 2683 if (a)
bdd6c45b
MS
2684 {
2685 if (cond_state)
2686 a->release();
2687 else
2688 d->add_attr(a);
2689 }
ac884b6a 2690 }
88f9aafc 2691 else if (!_cups_strcasecmp(temp, "Choice"))
ac884b6a
MS
2692 {
2693 // Get a choice...
bdd6c45b
MS
2694 c = get_choice(fp);
2695 if (!c)
2696 break;
2697
2698 if (cond_state)
2699 {
2700 c->release();
2701 continue;
2702 }
2703
2704 // Add it to the current option...
ac884b6a
MS
2705 if (!o)
2706 {
61cf44e2
MS
2707 _cupsLangPrintf(stderr,
2708 _("ppdc: Choice found on line %d of %s with no "
0837b7e8 2709 "Option."), fp->line, fp->filename);
ac884b6a
MS
2710 break;
2711 }
2712
ac884b6a
MS
2713 o->add_choice(c);
2714
2715 if (isdefault)
2716 o->set_defchoice(c);
2717 }
88f9aafc 2718 else if (!_cups_strcasecmp(temp, "ColorDevice"))
ac884b6a
MS
2719 {
2720 // ColorDevice boolean
bdd6c45b
MS
2721 if (cond_state)
2722 get_boolean(fp);
2723 else
2724 d->color_device = get_boolean(fp);
ac884b6a 2725 }
88f9aafc 2726 else if (!_cups_strcasecmp(temp, "ColorModel"))
ac884b6a
MS
2727 {
2728 // Get the color model
2729 c = get_color_model(fp);
2730 if (!c)
2731 continue;
2732
bdd6c45b
MS
2733 if (cond_state)
2734 {
2735 c->release();
2736 continue;
2737 }
2738
ac884b6a
MS
2739 // Add the choice to the ColorModel option...
2740 if ((o = d->find_option("ColorModel")) == NULL)
2741 {
2742 // Create the ColorModel option...
2743 o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f);
2744 g = general;
2745 g->add_option(o);
2746 }
2747
2748 o->add_choice(c);
2749
2750 if (isdefault)
2751 o->set_defchoice(c);
2752
2753 o = NULL;
2754 }
88f9aafc 2755 else if (!_cups_strcasecmp(temp, "ColorProfile"))
ac884b6a
MS
2756 {
2757 ppdcProfile *p; // Color profile
2758
2759
2760 // Get the color profile...
2761 p = get_color_profile(fp);
2762
2763 if (p)
bdd6c45b
MS
2764 {
2765 if (cond_state)
2766 p->release();
2767 else
2768 d->profiles->add(p);
2769 }
ac884b6a 2770 }
88f9aafc 2771 else if (!_cups_strcasecmp(temp, "Copyright"))
ac884b6a
MS
2772 {
2773 // Copyright string
2774 char copytemp[8192], // Copyright string
2775 *copyptr, // Pointer into string
2776 *copyend; // Pointer to end of string
2777
2778
2779 // Get the copyright string...
2780 if (!get_token(fp, copytemp, sizeof(temp)))
2781 {
61cf44e2
MS
2782 _cupsLangPrintf(stderr,
2783 _("ppdc: Expected string after Copyright on line %d "
0837b7e8 2784 "of %s."), fp->line, fp->filename);
ac884b6a
MS
2785 break;
2786 }
2787
bdd6c45b
MS
2788 if (cond_state)
2789 continue;
2790
ac884b6a
MS
2791 // Break it up into individual lines...
2792 for (copyptr = copytemp; copyptr; copyptr = copyend)
2793 {
2794 if ((copyend = strchr(copyptr, '\n')) != NULL)
2795 *copyend++ = '\0';
2796
2797 d->copyright->add(new ppdcString(copyptr));
2798 }
2799 }
88f9aafc 2800 else if (!_cups_strcasecmp(temp, "CustomMedia"))
ac884b6a
MS
2801 {
2802 ppdcMediaSize *m; // Media size
2803
2804
2805 // Get a custom media size...
2806 m = get_custom_size(fp);
bdd6c45b
MS
2807
2808 if (cond_state)
2809 {
2810 m->release();
2811 continue;
2812 }
2813
ac884b6a
MS
2814 if (m)
2815 d->sizes->add(m);
2816
2817 if (isdefault)
2818 d->set_default_size(m);
2819 }
88f9aafc 2820 else if (!_cups_strcasecmp(temp, "Cutter"))
ac884b6a
MS
2821 {
2822 // Cutter boolean
2823 int have_cutter; // Have a paper cutter?
2824
2825
2826 have_cutter = get_boolean(fp);
bdd6c45b 2827 if (have_cutter <= 0 || cond_state)
ac884b6a
MS
2828 continue;
2829
2830 if ((o = d->find_option("CutMedia")) == NULL)
2831 {
2832 o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f);
2833
2834 g = general;
2835 g->add_option(o);
2836
2837 c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice");
2838 o->add_choice(c);
2839 o->set_defchoice(c);
2840
2841 c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice");
2842 o->add_choice(c);
2843 }
2844
2845 o = NULL;
2846 }
88f9aafc 2847 else if (!_cups_strcasecmp(temp, "Darkness"))
ac884b6a
MS
2848 {
2849 // Get the darkness choice...
2850 c = get_generic(fp, "Darkness", NULL, "cupsCompression");
2851 if (!c)
2852 continue;
2853
bdd6c45b
MS
2854 if (cond_state)
2855 {
2856 c->release();
2857 continue;
2858 }
2859
ac884b6a 2860 // Add the choice to the cupsDarkness option...
97c9a8d7 2861 if ((o = d->find_option_group("cupsDarkness", &mg)) == NULL)
ac884b6a
MS
2862 {
2863 // Create the cupsDarkness option...
2864 o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
2865 g = general;
2866 g->add_option(o);
2867 }
97c9a8d7
MS
2868 else if (mg != general)
2869 {
2870 _cupsLangPrintf(stderr,
2871 _("ppdc: Option %s defined in two different groups on "
0837b7e8 2872 "line %d of %s."), "cupsDarkness", fp->line,
97c9a8d7
MS
2873 fp->filename);
2874 c->release();
2875 continue;
2876 }
ac884b6a
MS
2877
2878 o->add_choice(c);
2879
2880 if (isdefault)
2881 o->set_defchoice(c);
2882
2883 o = NULL;
2884 }
88f9aafc 2885 else if (!_cups_strcasecmp(temp, "DriverType"))
ac884b6a
MS
2886 {
2887 int i; // Looping var
2888
2889
2890 // DriverType keyword
2891 if (!get_token(fp, temp, sizeof(temp)))
2892 {
61cf44e2
MS
2893 _cupsLangPrintf(stderr,
2894 _("ppdc: Expected driver type keyword following "
0837b7e8 2895 "DriverType on line %d of %s."),
61cf44e2 2896 fp->line, fp->filename);
ac884b6a
MS
2897 continue;
2898 }
2899
bdd6c45b
MS
2900 if (cond_state)
2901 continue;
2902
ac884b6a 2903 for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
88f9aafc 2904 if (!_cups_strcasecmp(temp, driver_types[i]))
ac884b6a
MS
2905 break;
2906
2907 if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
2908 d->type = (ppdcDrvType)i;
88f9aafc 2909 else if (!_cups_strcasecmp(temp, "dymo"))
ac884b6a
MS
2910 d->type = PPDC_DRIVER_LABEL;
2911 else
61cf44e2 2912 _cupsLangPrintf(stderr,
0837b7e8 2913 _("ppdc: Unknown driver type %s on line %d of %s."),
61cf44e2 2914 temp, fp->line, fp->filename);
ac884b6a 2915 }
88f9aafc 2916 else if (!_cups_strcasecmp(temp, "Duplex"))
ac884b6a 2917 get_duplex(fp, d);
88f9aafc 2918 else if (!_cups_strcasecmp(temp, "Filter"))
ac884b6a
MS
2919 {
2920 ppdcFilter *f; // Filter
2921
2922
2923 // Get the filter value...
2924 f = get_filter(fp);
2925 if (f)
bdd6c45b
MS
2926 {
2927 if (cond_state)
2928 f->release();
2929 else
2930 d->filters->add(f);
2931 }
ac884b6a 2932 }
88f9aafc 2933 else if (!_cups_strcasecmp(temp, "Finishing"))
ac884b6a
MS
2934 {
2935 // Get the finishing choice...
2936 c = get_generic(fp, "Finishing", "OutputType", NULL);
2937 if (!c)
2938 continue;
2939
bdd6c45b
MS
2940 if (cond_state)
2941 {
2942 c->release();
2943 continue;
2944 }
2945
ac884b6a 2946 // Add the choice to the cupsFinishing option...
97c9a8d7 2947 if ((o = d->find_option_group("cupsFinishing", &mg)) == NULL)
ac884b6a
MS
2948 {
2949 // Create the cupsFinishing option...
2950 o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
2951 g = general;
2952 g->add_option(o);
2953 }
97c9a8d7
MS
2954 else if (mg != general)
2955 {
2956 _cupsLangPrintf(stderr,
2957 _("ppdc: Option %s defined in two different groups on "
0837b7e8 2958 "line %d of %s."), "cupsFinishing", fp->line,
97c9a8d7
MS
2959 fp->filename);
2960 c->release();
2961 continue;
2962 }
ac884b6a
MS
2963
2964 o->add_choice(c);
2965
2966 if (isdefault)
2967 o->set_defchoice(c);
2968
2969 o = NULL;
2970 }
88f9aafc
MS
2971 else if (!_cups_strcasecmp(temp, "Font") ||
2972 !_cups_strcasecmp(temp, "#font"))
ac884b6a
MS
2973 {
2974 ppdcFont *f; // Font
2975
2976
2977 // Get a font...
2978 f = get_font(fp);
2979 if (f)
2980 {
bdd6c45b
MS
2981 if (cond_state)
2982 f->release();
2983 else
2984 {
88f9aafc 2985 if (!_cups_strcasecmp(temp, "#font"))
bdd6c45b
MS
2986 base_fonts->add(f);
2987 else
2988 d->add_font(f);
ac884b6a 2989
bdd6c45b
MS
2990 if (isdefault)
2991 d->set_default_font(f);
2992 }
ac884b6a
MS
2993 }
2994 }
88f9aafc 2995 else if (!_cups_strcasecmp(temp, "Group"))
ac884b6a
MS
2996 {
2997 // Get a group...
bdd6c45b
MS
2998 ppdcGroup *tempg = get_group(fp, d);
2999
3000 if (!tempg)
ac884b6a 3001 break;
bdd6c45b
MS
3002
3003 if (cond_state)
3004 {
3005 if (!d->find_group(tempg->name->value))
3006 tempg->release();
3007 }
3008 else
3009 {
3010 if (!d->find_group(tempg->name->value))
3011 d->add_group(tempg);
3012
3013 g = tempg;
3014 }
ac884b6a 3015 }
88f9aafc 3016 else if (!_cups_strcasecmp(temp, "HWMargins"))
ac884b6a
MS
3017 {
3018 // HWMargins left bottom right top
3019 d->left_margin = get_measurement(fp);
3020 d->bottom_margin = get_measurement(fp);
3021 d->right_margin = get_measurement(fp);
3022 d->top_margin = get_measurement(fp);
3023 }
88f9aafc 3024 else if (!_cups_strcasecmp(temp, "InputSlot"))
ac884b6a
MS
3025 {
3026 // Get the input slot choice...
3027 c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
3028 if (!c)
3029 continue;
3030
bdd6c45b
MS
3031 if (cond_state)
3032 {
3033 c->release();
3034 continue;
3035 }
3036
ac884b6a 3037 // Add the choice to the InputSlot option...
88f9aafc 3038
97c9a8d7 3039 if ((o = d->find_option_group("InputSlot", &mg)) == NULL)
ac884b6a
MS
3040 {
3041 // Create the InputSlot option...
3042 o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
3043 PPDC_SECTION_ANY, 10.0f);
3044 g = general;
3045 g->add_option(o);
3046 }
97c9a8d7
MS
3047 else if (mg != general)
3048 {
3049 _cupsLangPrintf(stderr,
3050 _("ppdc: Option %s defined in two different groups on "
0837b7e8 3051 "line %d of %s."), "InputSlot", fp->line,
97c9a8d7
MS
3052 fp->filename);
3053 c->release();
3054 continue;
3055 }
ac884b6a
MS
3056
3057 o->add_choice(c);
3058
3059 if (isdefault)
3060 o->set_defchoice(c);
3061
3062 o = NULL;
3063 }
88f9aafc 3064 else if (!_cups_strcasecmp(temp, "Installable"))
ac884b6a
MS
3065 {
3066 // Get the installable option...
3067 o = get_installable(fp);
3068
3069 // Add it as needed...
3070 if (o)
3071 {
bdd6c45b
MS
3072 if (cond_state)
3073 o->release();
3074 else
3075 install->add_option(o);
3076
ac884b6a
MS
3077 o = NULL;
3078 }
3079 }
88f9aafc 3080 else if (!_cups_strcasecmp(temp, "ManualCopies"))
ac884b6a
MS
3081 {
3082 // ManualCopies boolean
bdd6c45b
MS
3083 if (cond_state)
3084 get_boolean(fp);
3085 else
3086 d->manual_copies = get_boolean(fp);
ac884b6a 3087 }
88f9aafc 3088 else if (!_cups_strcasecmp(temp, "Manufacturer"))
ac884b6a
MS
3089 {
3090 // Manufacturer name
3091 char name[256]; // Model name string
3092
3093
3094 if (!get_token(fp, name, sizeof(name)))
3095 {
61cf44e2
MS
3096 _cupsLangPrintf(stderr,
3097 _("ppdc: Expected name after Manufacturer on line %d "
0837b7e8 3098 "of %s."), fp->line, fp->filename);
ac884b6a
MS
3099 break;
3100 }
3101
bdd6c45b
MS
3102 if (!cond_state)
3103 d->set_manufacturer(name);
ac884b6a 3104 }
88f9aafc 3105 else if (!_cups_strcasecmp(temp, "MaxSize"))
ac884b6a
MS
3106 {
3107 // MaxSize width length
bdd6c45b
MS
3108 if (cond_state)
3109 {
3110 get_measurement(fp);
3111 get_measurement(fp);
3112 }
3113 else
3114 {
3115 d->max_width = get_measurement(fp);
3116 d->max_length = get_measurement(fp);
3117 }
ac884b6a 3118 }
88f9aafc 3119 else if (!_cups_strcasecmp(temp, "MediaSize"))
ac884b6a
MS
3120 {
3121 // MediaSize keyword
3122 char name[41]; // Media size name
3123 ppdcMediaSize *m, // Matching media size...
3124 *dm; // Driver media size...
3125
3126
3127 if (get_token(fp, name, sizeof(name)) == NULL)
3128 {
61cf44e2
MS
3129 _cupsLangPrintf(stderr,
3130 _("ppdc: Expected name after MediaSize on line %d of "
0837b7e8 3131 "%s."), fp->line, fp->filename);
ac884b6a
MS
3132 break;
3133 }
3134
bdd6c45b
MS
3135 if (cond_state)
3136 continue;
3137
ac884b6a
MS
3138 m = find_size(name);
3139
3140 if (!m)
3141 {
61cf44e2
MS
3142 _cupsLangPrintf(stderr,
3143 _("ppdc: Unknown media size \"%s\" on line %d of "
0837b7e8 3144 "%s."), name, fp->line, fp->filename);
ac884b6a
MS
3145 break;
3146 }
3147
3148 // Add this size to the driver...
3149 dm = new ppdcMediaSize(m->name->value, m->text->value,
3150 m->width, m->length, d->left_margin,
3151 d->bottom_margin, d->right_margin,
3152 d->top_margin);
3153 d->sizes->add(dm);
3154
3155 if (isdefault)
3156 d->set_default_size(dm);
3157 }
88f9aafc 3158 else if (!_cups_strcasecmp(temp, "MediaType"))
ac884b6a
MS
3159 {
3160 // Get the media type choice...
3161 c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
3162 if (!c)
3163 continue;
3164
bdd6c45b
MS
3165 if (cond_state)
3166 {
3167 c->release();
3168 continue;
3169 }
3170
ac884b6a 3171 // Add the choice to the MediaType option...
97c9a8d7 3172 if ((o = d->find_option_group("MediaType", &mg)) == NULL)
ac884b6a
MS
3173 {
3174 // Create the MediaType option...
3175 o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
3176 PPDC_SECTION_ANY, 10.0f);
3177 g = general;
3178 g->add_option(o);
3179 }
97c9a8d7
MS
3180 else if (mg != general)
3181 {
3182 _cupsLangPrintf(stderr,
3183 _("ppdc: Option %s defined in two different groups on "
0837b7e8 3184 "line %d of %s."), "MediaType", fp->line,
97c9a8d7
MS
3185 fp->filename);
3186 c->release();
3187 continue;
3188 }
ac884b6a
MS
3189
3190 o->add_choice(c);
3191
3192 if (isdefault)
3193 o->set_defchoice(c);
3194
3195 o = NULL;
3196 }
88f9aafc 3197 else if (!_cups_strcasecmp(temp, "MinSize"))
ac884b6a
MS
3198 {
3199 // MinSize width length
bdd6c45b
MS
3200 if (cond_state)
3201 {
3202 get_measurement(fp);
3203 get_measurement(fp);
3204 }
3205 else
3206 {
3207 d->min_width = get_measurement(fp);
3208 d->min_length = get_measurement(fp);
3209 }
ac884b6a 3210 }
88f9aafc 3211 else if (!_cups_strcasecmp(temp, "ModelName"))
ac884b6a
MS
3212 {
3213 // ModelName name
3214 char name[256]; // Model name string
3215
3216
3217 if (!get_token(fp, name, sizeof(name)))
3218 {
61cf44e2
MS
3219 _cupsLangPrintf(stderr,
3220 _("ppdc: Expected name after ModelName on line %d of "
0837b7e8 3221 "%s."), fp->line, fp->filename);
ac884b6a
MS
3222 break;
3223 }
3224
bdd6c45b
MS
3225 if (!cond_state)
3226 d->set_model_name(name);
ac884b6a 3227 }
88f9aafc 3228 else if (!_cups_strcasecmp(temp, "ModelNumber"))
ac884b6a
MS
3229 {
3230 // ModelNumber number
bdd6c45b
MS
3231 if (cond_state)
3232 get_integer(fp);
3233 else
3234 d->model_number = get_integer(fp);
ac884b6a 3235 }
88f9aafc 3236 else if (!_cups_strcasecmp(temp, "Option"))
ac884b6a
MS
3237 {
3238 // Get an option...
bdd6c45b
MS
3239 ppdcOption *tempo = get_option(fp, d, g);
3240
3241 if (!tempo)
ac884b6a 3242 break;
bdd6c45b
MS
3243
3244 if (cond_state)
3245 {
3246 if (!g->find_option(tempo->name->value))
3247 tempo->release();
3248 }
3249 else
3250 {
3251 if (!g->find_option(tempo->name->value))
3252 g->add_option(tempo);
3253
3254 o = tempo;
3255 }
3256 }
88f9aafc 3257 else if (!_cups_strcasecmp(temp, "FileName"))
bdd6c45b
MS
3258 {
3259 // FileName name
3260 char name[256]; // Filename string
3261
3262
3263 if (!get_token(fp, name, sizeof(name)))
3264 {
61cf44e2
MS
3265 _cupsLangPrintf(stderr,
3266 _("ppdc: Expected name after FileName on line %d of "
0837b7e8 3267 "%s."), fp->line, fp->filename);
bdd6c45b
MS
3268 break;
3269 }
3270
3271 if (!cond_state)
3272 d->set_file_name(name);
ac884b6a 3273 }
88f9aafc 3274 else if (!_cups_strcasecmp(temp, "PCFileName"))
ac884b6a
MS
3275 {
3276 // PCFileName name
bdd6c45b 3277 char name[256]; // PC filename string
ac884b6a
MS
3278
3279
3280 if (!get_token(fp, name, sizeof(name)))
3281 {
61cf44e2
MS
3282 _cupsLangPrintf(stderr,
3283 _("ppdc: Expected name after PCFileName on line %d of "
0837b7e8 3284 "%s."), fp->line, fp->filename);
ac884b6a
MS
3285 break;
3286 }
3287
bdd6c45b
MS
3288 if (!cond_state)
3289 d->set_pc_file_name(name);
ac884b6a 3290 }
88f9aafc 3291 else if (!_cups_strcasecmp(temp, "Resolution"))
ac884b6a
MS
3292 {
3293 // Get the resolution choice...
3294 c = get_resolution(fp);
3295 if (!c)
3296 continue;
3297
bdd6c45b
MS
3298 if (cond_state)
3299 {
3300 c->release();
3301 continue;
3302 }
3303
ac884b6a 3304 // Add the choice to the Resolution option...
97c9a8d7 3305 if ((o = d->find_option_group("Resolution", &mg)) == NULL)
ac884b6a
MS
3306 {
3307 // Create the Resolution option...
bdd6c45b
MS
3308 o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
3309 10.0f);
ac884b6a
MS
3310 g = general;
3311 g->add_option(o);
3312 }
97c9a8d7
MS
3313 else if (mg != general)
3314 {
3315 _cupsLangPrintf(stderr,
3316 _("ppdc: Option %s defined in two different groups on "
0837b7e8 3317 "line %d of %s."), "Resolution", fp->line,
97c9a8d7
MS
3318 fp->filename);
3319 c->release();
3320 continue;
3321 }
ac884b6a
MS
3322
3323 o->add_choice(c);
3324
3325 if (isdefault)
3326 o->set_defchoice(c);
3327
3328 o = NULL;
3329 }
88f9aafc 3330 else if (!_cups_strcasecmp(temp, "SimpleColorProfile"))
ac884b6a
MS
3331 {
3332 ppdcProfile *p; // Color profile
3333
3334
3335 // Get the color profile...
3336 p = get_simple_profile(fp);
3337
3338 if (p)
bdd6c45b
MS
3339 {
3340 if (cond_state)
3341 p->release();
3342 else
3343 d->profiles->add(p);
3344 }
ac884b6a 3345 }
88f9aafc 3346 else if (!_cups_strcasecmp(temp, "Throughput"))
ac884b6a
MS
3347 {
3348 // Throughput number
bdd6c45b
MS
3349 if (cond_state)
3350 get_integer(fp);
3351 else
3352 d->throughput = get_integer(fp);
ac884b6a 3353 }
88f9aafc 3354 else if (!_cups_strcasecmp(temp, "UIConstraints"))
ac884b6a
MS
3355 {
3356 ppdcConstraint *con; // Constraint
3357
3358
3359 con = get_constraint(fp);
3360
3361 if (con)
bdd6c45b
MS
3362 {
3363 if (cond_state)
3364 con->release();
3365 else
3366 d->constraints->add(con);
3367 }
ac884b6a 3368 }
88f9aafc 3369 else if (!_cups_strcasecmp(temp, "VariablePaperSize"))
ac884b6a
MS
3370 {
3371 // VariablePaperSize boolean
bdd6c45b
MS
3372 if (cond_state)
3373 get_boolean(fp);
3374 else
3375 d->variable_paper_size = get_boolean(fp);
ac884b6a 3376 }
88f9aafc 3377 else if (!_cups_strcasecmp(temp, "Version"))
ac884b6a
MS
3378 {
3379 // Version string
3380 char name[256]; // Model name string
3381
3382
3383 if (!get_token(fp, name, sizeof(name)))
3384 {
61cf44e2
MS
3385 _cupsLangPrintf(stderr,
3386 _("ppdc: Expected string after Version on line %d of "
0837b7e8 3387 "%s."), fp->line, fp->filename);
ac884b6a
MS
3388 break;
3389 }
3390
bdd6c45b
MS
3391 if (!cond_state)
3392 d->set_version(name);
ac884b6a
MS
3393 }
3394 else
3395 {
61cf44e2 3396 _cupsLangPrintf(stderr,
0837b7e8 3397 _("ppdc: Unknown token \"%s\" seen on line %d of %s."),
61cf44e2 3398 temp, fp->line, fp->filename);
ac884b6a
MS
3399 break;
3400 }
3401 }
3402
3403 // Done processing this block, is there anything to save?
3404 if (!inc)
3405 {
3406 if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version ||
3407 !d->sizes->count)
3408 {
3409 // Nothing to save...
3410 d->release();
3411 }
3412 else
3413 {
3414 // Got a driver, save it...
3415 drivers->add(d);
3416 }
3417 }
97c9a8d7
MS
3418 else if (inc && td)
3419 td->release();
ac884b6a
MS
3420}
3421
3422
3423//
3424// 'ppdcSource::set_variable()' - Set a variable.
3425//
3426
3427ppdcVariable * // O - Variable
3428ppdcSource::set_variable(
3429 const char *name, // I - Name
3430 const char *value) // I - Value
3431{
3432 ppdcVariable *v; // Variable
3433
3434
3435 // See if the variable exists already...
3436 v = find_variable(name);
3437 if (v)
3438 {
3439 // Change the variable value...
3440 v->set_value(value);
3441 }
3442 else
3443 {
3444 // Create a new variable and add it...
3445 v = new ppdcVariable(name, value);
3446 vars->add(v);
3447 }
3448
3449 return (v);
3450}
3451
3452
3453//
3454// 'ppdcSource::write_file()' - Write the current source data to a file.
3455//
3456
3457int // O - 0 on success, -1 on error
3458ppdcSource::write_file(const char *f) // I - File to write
3459{
3460 cups_file_t *fp; // Output file
3461 char bckname[1024]; // Backup file
3462 ppdcDriver *d; // Current driver
3463 ppdcString *st; // Current string
3464 ppdcAttr *a; // Current attribute
3465 ppdcConstraint *co; // Current constraint
3466 ppdcFilter *fi; // Current filter
3467 ppdcFont *fo; // Current font
3468 ppdcGroup *g; // Current group
3469 ppdcOption *o; // Current option
3470 ppdcChoice *ch; // Current choice
3471 ppdcProfile *p; // Current color profile
3472 ppdcMediaSize *si; // Current media size
3473 float left, // Current left margin
3474 bottom, // Current bottom margin
3475 right, // Current right margin
3476 top; // Current top margin
3477 int dtused[PPDC_DRIVER_MAX];// Driver type usage...
3478
3479
3480 // Rename the current file, if any, to .bck...
3481 snprintf(bckname, sizeof(bckname), "%s.bck", f);
3482 rename(f, bckname);
3483
3484 // Open the output file...
3485 fp = cupsFileOpen(f, "w");
3486
3487 if (!fp)
3488 {
3489 // Can't create file; restore backup and return...
3490 rename(bckname, f);
3491 return (-1);
3492 }
3493
3494 cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n");
3495
3496 // Include standard files...
3497 cupsFilePuts(fp, "// Include necessary files...\n");
3498 cupsFilePuts(fp, "#include <font.defs>\n");
3499 cupsFilePuts(fp, "#include <media.defs>\n");
3500
3501 memset(dtused, 0, sizeof(dtused));
3502
3503 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3504 if (d->type > PPDC_DRIVER_PS && !dtused[d->type])
3505 {
3506 cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]);
3507 dtused[d->type] = 1;
3508 }
3509
3510 // Output each driver...
3511 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3512 {
3513 // Start the driver...
41681883
MS
3514 cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value,
3515 d->model_name->value);
ac884b6a
MS
3516 cupsFilePuts(fp, "{\n");
3517
3518 // Write the copyright stings...
3519 for (st = (ppdcString *)d->copyright->first();
3520 st;
3521 st = (ppdcString *)d->copyright->next())
3522 quotef(fp, " Copyright \"%s\"\n", st->value);
3523
3524 // Write other strings and values...
d2354e63 3525 if (d->manufacturer && d->manufacturer->value)
ac884b6a
MS
3526 quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value);
3527 if (d->model_name->value)
3528 quotef(fp, " ModelName \"%s\"\n", d->model_name->value);
d2354e63 3529 if (d->file_name && d->file_name->value)
bdd6c45b 3530 quotef(fp, " FileName \"%s\"\n", d->file_name->value);
d2354e63 3531 if (d->pc_file_name && d->pc_file_name->value)
ac884b6a 3532 quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
d2354e63 3533 if (d->version && d->version->value)
ac884b6a
MS
3534 quotef(fp, " Version \"%s\"\n", d->version->value);
3535
3536 cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]);
3537
3538 if (d->model_number)
3539 {
3540 switch (d->type)
3541 {
ac884b6a
MS
3542 case PPDC_DRIVER_LABEL :
3543 cupsFilePuts(fp, " ModelNumber ");
3544
3545 switch (d->model_number)
3546 {
3547 case DYMO_3x0 :
3548 cupsFilePuts(fp, "$DYMO_3x0\n");
3549 break;
3550
3551 case ZEBRA_EPL_LINE :
3552 cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n");
3553 break;
3554
3555 case ZEBRA_EPL_PAGE :
3556 cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n");
3557 break;
3558
3559 case ZEBRA_ZPL :
3560 cupsFilePuts(fp, "$ZEBRA_ZPL\n");
3561 break;
3562
3563 case ZEBRA_CPCL :
3564 cupsFilePuts(fp, "$ZEBRA_CPCL\n");
3565 break;
3566
3567 case INTELLITECH_PCL :
3568 cupsFilePuts(fp, "$INTELLITECH_PCL\n");
3569 break;
3570
3571 default :
3572 cupsFilePrintf(fp, "%d\n", d->model_number);
3573 break;
3574 }
3575 break;
3576
3577 case PPDC_DRIVER_EPSON :
3578 cupsFilePuts(fp, " ModelNumber ");
3579
3580 switch (d->model_number)
3581 {
3582 case EPSON_9PIN :
3583 cupsFilePuts(fp, "$EPSON_9PIN\n");
3584 break;
3585
3586 case EPSON_24PIN :
3587 cupsFilePuts(fp, "$EPSON_24PIN\n");
3588 break;
3589
3590 case EPSON_COLOR :
3591 cupsFilePuts(fp, "$EPSON_COLOR\n");
3592 break;
3593
3594 case EPSON_PHOTO :
3595 cupsFilePuts(fp, "$EPSON_PHOTO\n");
3596 break;
3597
3598 case EPSON_ICOLOR :
3599 cupsFilePuts(fp, "$EPSON_ICOLOR\n");
3600 break;
3601
3602 case EPSON_IPHOTO :
3603 cupsFilePuts(fp, "$EPSON_IPHOTO\n");
3604 break;
3605
3606 default :
3607 cupsFilePrintf(fp, "%d\n", d->model_number);
3608 break;
3609 }
3610 break;
3611
3612 case PPDC_DRIVER_HP :
3613 cupsFilePuts(fp, " ModelNumber ");
3614 switch (d->model_number)
3615 {
3616 case HP_LASERJET :
3617 cupsFilePuts(fp, "$HP_LASERJET\n");
3618 break;
3619
3620 case HP_DESKJET :
3621 cupsFilePuts(fp, "$HP_DESKJET\n");
3622 break;
3623
3624 case HP_DESKJET2 :
3625 cupsFilePuts(fp, "$HP_DESKJET2\n");
3626 break;
3627
3628 default :
3629 cupsFilePrintf(fp, "%d\n", d->model_number);
3630 break;
3631 }
3632
3633 cupsFilePuts(fp, ")\n");
3634 break;
3635
3636 default :
3637 cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number);
3638 break;
3639 }
3640 }
3641
3642 if (d->manual_copies)
3643 cupsFilePuts(fp, " ManualCopies Yes\n");
3644
3645 if (d->color_device)
3646 cupsFilePuts(fp, " ColorDevice Yes\n");
3647
3648 if (d->throughput)
3649 cupsFilePrintf(fp, " Throughput %d\n", d->throughput);
3650
3651 // Output all of the attributes...
3652 for (a = (ppdcAttr *)d->attrs->first();
3653 a;
3654 a = (ppdcAttr *)d->attrs->next())
3655 if (a->text->value && a->text->value[0])
3656 quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
3657 a->name->value, a->selector->value ? a->selector->value : "",
3658 a->text->value, a->value->value ? a->value->value : "");
3659 else
3660 quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n",
3661 a->name->value, a->selector->value ? a->selector->value : "",
3662 a->value->value ? a->value->value : "");
3663
3664 // Output all of the constraints...
3665 for (co = (ppdcConstraint *)d->constraints->first();
3666 co;
3667 co = (ppdcConstraint *)d->constraints->next())
3668 {
3669 if (co->option1->value[0] == '*')
3670 cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value,
3671 co->choice1->value ? co->choice1->value : "");
3672 else
3673 cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value,
3674 co->choice1->value ? co->choice1->value : "");
3675
3676 if (co->option2->value[0] == '*')
3677 cupsFilePrintf(fp, " %s %s\"\n", co->option2->value,
3678 co->choice2->value ? co->choice2->value : "");
3679 else
3680 cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value,
3681 co->choice2->value ? co->choice2->value : "");
3682 }
3683
3684 // Output all of the filters...
3685 for (fi = (ppdcFilter *)d->filters->first();
3686 fi;
3687 fi = (ppdcFilter *)d->filters->next())
3688 cupsFilePrintf(fp, " Filter \"%s %d %s\"\n",
3689 fi->mime_type->value, fi->cost, fi->program->value);
3690
3691 // Output all of the fonts...
3692 for (fo = (ppdcFont *)d->fonts->first();
3693 fo;
3694 fo = (ppdcFont *)d->fonts->next())
3695 if (!strcmp(fo->name->value, "*"))
3696 cupsFilePuts(fp, " Font *\n");
3697 else
3698 cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
3699 fo->name->value, fo->encoding->value,
3700 fo->version->value, fo->charset->value,
3701 fo->status == PPDC_FONT_ROM ? "ROM" : "Disk");
3702
3703 // Output all options...
3704 for (g = (ppdcGroup *)d->groups->first();
3705 g;
3706 g = (ppdcGroup *)d->groups->next())
3707 {
3708 if (g->options->count == 0)
3709 continue;
3710
3711 if (g->text->value && g->text->value[0])
3712 quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value);
3713 else
3714 cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value);
3715
3716 for (o = (ppdcOption *)g->options->first();
3717 o;
3718 o = (ppdcOption *)g->options->next())
3719 {
3720 if (o->choices->count == 0)
3721 continue;
3722
3723 if (o->text->value && o->text->value[0])
3724 quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value);
3725 else
3726 cupsFilePrintf(fp, " Option \"%s\"", o->name->value);
3727
3728 cupsFilePrintf(fp, " %s %s %.1f\n",
3729 o->type == PPDC_BOOLEAN ? "Boolean" :
3730 o->type == PPDC_PICKONE ? "PickOne" : "PickMany",
3731 o->section == PPDC_SECTION_ANY ? "AnySetup" :
3732 o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" :
3733 o->section == PPDC_SECTION_EXIT ? "ExitServer" :
3734 o->section == PPDC_SECTION_JCL ? "JCLSetup" :
3735 o->section == PPDC_SECTION_PAGE ? "PageSetup" :
3736 "Prolog",
3737 o->order);
3738
3739 for (ch = (ppdcChoice *)o->choices->first();
3740 ch;
3741 ch = (ppdcChoice *)o->choices->next())
3742 {
3743 if (ch->text->value && ch->text->value[0])
3744 quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n",
3745 o->defchoice == ch->name ? "*" : "",
3746 ch->name->value, ch->text->value,
3747 ch->code->value ? ch->code->value : "");
3748 else
3749 quotef(fp, " %sChoice \"%s\" \"%s\"\n",
3750 o->defchoice == ch->name ? "*" : "",
3751 ch->name->value,
3752 ch->code->value ? ch->code->value : "");
3753 }
3754 }
3755 }
3756
3757 // Output all of the color profiles...
3758 for (p = (ppdcProfile *)d->profiles->first();
3759 p;
3760 p = (ppdcProfile *)d->profiles->next())
3761 cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f "
3762 "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
3763 p->resolution->value, p->media_type->value,
3764 p->density, p->gamma,
3765 p->profile[0], p->profile[1], p->profile[2],
3766 p->profile[3], p->profile[4], p->profile[5],
3767 p->profile[6], p->profile[7], p->profile[8]);
3768
3769 // Output all of the media sizes...
3770 left = 0.0;
3771 bottom = 0.0;
3772 right = 0.0;
3773 top = 0.0;
3774
3775 for (si = (ppdcMediaSize *)d->sizes->first();
3776 si;
3777 si = (ppdcMediaSize *)d->sizes->next())
3778 if (si->size_code->value && si->region_code->value)
3779 {
3780 // Output a custom media size...
3781 quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
3782 si->name == d->default_size ? "*" : "", si->name->value,
3783 si->text->value, si->width, si->length, si->left, si->bottom,
3784 si->right, si->top, si->size_code->value,
3785 si->region_code->value);
3786 }
3787 else
3788 {
3789 // Output a standard media size...
3790 if (fabs(left - si->left) > 0.1 ||
3791 fabs(bottom - si->bottom) > 0.1 ||
3792 fabs(right - si->right) > 0.1 ||
3793 fabs(top - si->top) > 0.1)
3794 {
3795 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3796 si->left, si->bottom, si->right, si->top);
3797
3798 left = si->left;
3799 bottom = si->bottom;
3800 right = si->right;
3801 top = si->top;
3802 }
3803
3804 cupsFilePrintf(fp, " %sMediaSize %s\n",
3805 si->name == d->default_size ? "*" : "",
3806 si->name->value);
3807 }
3808
3809 if (d->variable_paper_size)
3810 {
3811 cupsFilePuts(fp, " VariablePaperSize Yes\n");
3812
3813 if (fabs(left - d->left_margin) > 0.1 ||
3814 fabs(bottom - d->bottom_margin) > 0.1 ||
3815 fabs(right - d->right_margin) > 0.1 ||
3816 fabs(top - d->top_margin) > 0.1)
3817 {
3818 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3819 d->left_margin, d->bottom_margin, d->right_margin,
3820 d->top_margin);
3821 }
3822
3823 cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length);
3824 cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length);
3825 }
3826
3827 // End the driver...
3828 cupsFilePuts(fp, "}\n");
3829 }
3830
3831 // Close the file and return...
3832 cupsFileClose(fp);
3833
3834 return (0);
3835}
3836
3837
3838//
3839// End of "$Id$".
3840//