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