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