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