]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - ppdc/ppdc-source.cxx
Merge changes from CUPS 1.6svn-r9939.
[thirdparty/cups.git] / ppdc / ppdc-source.cxx
index 7450291e3f9dbdd2dac1dc3a127318678baf9be8..2e4934a6330208ddafd8751be93fa32d3ecdf5b5 100644 (file)
@@ -3,7 +3,7 @@
 //
 //   Source class for the CUPS PPD Compiler.
 //
-//   Copyright 2007-2008 by Apple Inc.
+//   Copyright 2007-2011 by Apple Inc.
 //   Copyright 2002-2007 by Easy Software Products.
 //
 //   These coded instructions, statements, and computer programs are the
@@ -19,6 +19,8 @@
 //   ppdcSource::add_include()        - Add an include directory.
 //   ppdcSource::find_driver()        - Find a driver.
 //   ppdcSource::find_include()       - Find an include file.
+//   ppdcSource::find_po()            - Find a message catalog for the given
+//                                      locale...
 //   ppdcSource::find_size()          - Find a media size.
 //   ppdcSource::find_variable()      - Find a variable.
 //   ppdcSource::get_attr()           - Get an attribute.
 //   ppdcSource::get_color_profile()  - Get a color profile definition.
 //   ppdcSource::get_color_space()    - Get an old-style colorspace value.
 //   ppdcSource::get_constraint()     - Get a constraint.
-//   ppdcSource::get_custom_size()    - Get a custom media size definition
-//                                      from a file.
+//   ppdcSource::get_custom_size()    - Get a custom media size definition from
+//                                      a file.
+//   ppdcSource::get_duplex()         - Get a duplex option.
 //   ppdcSource::get_filter()         - Get a filter.
 //   ppdcSource::get_float()          - Get a single floating-point number.
 //   ppdcSource::get_font()           - Get a font definition.
 //   ppdcSource::get_generic()        - Get a generic old-style option.
 //   ppdcSource::get_group()          - Get an option group.
 //   ppdcSource::get_installable()    - Get an installable option.
-//   ppdcSource::get_integer()        - Get an integer value from a string.
 //   ppdcSource::get_integer()        - Get an integer value from a file.
 //   ppdcSource::get_measurement()    - Get a measurement value.
 //   ppdcSource::get_option()         - Get an option definition.
+//   ppdcSource::get_po()             - Get a message catalog.
 //   ppdcSource::get_resolution()     - Get an old-style resolution option.
 //   ppdcSource::get_simple_profile() - Get a simple color profile definition.
 //   ppdcSource::get_size()           - Get a media size definition from a file.
 // Include necessary headers...
 //
 
-#include "ppdc.h"
-#include <cups/globals.h>
+#include "ppdc-private.h"
 #include <limits.h>
 #include <math.h>
 #include <unistd.h>
 #include <cups/raster.h>
 #include "data/epson.h"
-#include "data/escp.h"
 #include "data/hp.h"
 #include "data/label.h"
-#include "data/pcl.h"
+#ifndef WIN32
+#  include <sys/utsname.h>
+#endif // !WIN32
 
 
 //
@@ -93,7 +96,10 @@ const char   *ppdcSource::driver_types[] =
 
 ppdcSource::ppdcSource(const char  *f, // I - File to read
                        cups_file_t *ffp)// I - File pointer to use
+  : ppdcShared()
 {
+  PPDC_NEW;
+
   filename      = new ppdcString(f);
   base_fonts    = new ppdcArray();
   drivers       = new ppdcArray();
@@ -104,6 +110,33 @@ ppdcSource::ppdcSource(const char  *f,     // I - File to read
   cond_current  = cond_stack;
   cond_stack[0] = PPDC_COND_NORMAL;
 
+  // Add standard #define variables...
+#define MAKE_STRING(x) #x
+
+  vars->add(new ppdcVariable("CUPS_VERSION", MAKE_STRING(CUPS_VERSION)));
+  vars->add(new ppdcVariable("CUPS_VERSION_MAJOR", MAKE_STRING(CUPS_VERSION_MAJOR)));
+  vars->add(new ppdcVariable("CUPS_VERSION_MINOR", MAKE_STRING(CUPS_VERSION_MINOR)));
+  vars->add(new ppdcVariable("CUPS_VERSION_PATCH", MAKE_STRING(CUPS_VERSION_PATCH)));
+
+#ifdef WIN32
+  vars->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
+  vars->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
+
+#else
+  struct utsname name;                 // uname information
+
+  if (!uname(&name))
+  {
+    vars->add(new ppdcVariable("PLATFORM_NAME", name.sysname));
+    vars->add(new ppdcVariable("PLATFORM_ARCH", name.machine));
+  }
+  else
+  {
+    vars->add(new ppdcVariable("PLATFORM_NAME", "unknown"));
+    vars->add(new ppdcVariable("PLATFORM_ARCH", "unknown"));
+  }
+#endif // WIN32
+
   if (f)
     read_file(f, ffp);
 }
@@ -115,12 +148,14 @@ ppdcSource::ppdcSource(const char  *f,    // I - File to read
 
 ppdcSource::~ppdcSource()
 {
-  delete filename;
-  delete base_fonts;
-  delete drivers;
-  delete po_files;
-  delete sizes;
-  delete vars;
+  PPDC_DELETE;
+
+  filename->release();
+  base_fonts->release();
+  drivers->release();
+  po_files->release();
+  sizes->release();
+  vars->release();
 }
 
 
@@ -152,7 +187,7 @@ ppdcSource::find_driver(const char *f)      // I - Driver file name
 
 
   for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
-    if (!strcasecmp(f, d->pc_file_name->value))
+    if (!_cups_strcasecmp(f, d->pc_file_name->value))
       return (d);
 
   return (NULL);
@@ -189,7 +224,7 @@ ppdcSource::find_include(
     if (*ptr != '>')
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Invalid #include/#po filename \"%s\"!\n"), n);
+                      _("ppdc: Invalid #include/#po filename \"%s\"."), n);
       return (0);
     }
 
@@ -252,7 +287,7 @@ ppdcSource::find_po(const char *l)  // I - Locale name
   for (cat = (ppdcCatalog *)po_files->first();
        cat;
        cat = (ppdcCatalog *)po_files->next())
-    if (!strcasecmp(l, cat->locale->value))
+    if (!_cups_strcasecmp(l, cat->locale->value))
       return (cat);
 
   return (NULL);
@@ -270,7 +305,7 @@ ppdcSource::find_size(const char *s)        // I - Size name
 
 
   for (m = (ppdcMediaSize *)sizes->first(); m; m = (ppdcMediaSize *)sizes->next())
-    if (!strcasecmp(s, m->name->value))
+    if (!_cups_strcasecmp(s, m->name->value))
       return (m);
 
   return (NULL);
@@ -288,7 +323,7 @@ ppdcSource::find_variable(const char *n)// I - Variable name
 
 
   for (v = (ppdcVariable *)vars->first(); v; v = (ppdcVariable *)vars->next())
-    if (!strcasecmp(n, v->name->value))
+    if (!_cups_strcasecmp(n, v->name->value))
       return (v);
 
   return (NULL);
@@ -315,7 +350,7 @@ ppdcSource::get_attr(ppdcFile *fp,  // I - File to read
   if (!get_token(fp, name, sizeof(name)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected name after %s on line %d of %s!\n"),
+                    _("ppdc: Expected name after %s on line %d of %s."),
                    loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
     return (0);
   }
@@ -323,7 +358,7 @@ ppdcSource::get_attr(ppdcFile *fp,  // I - File to read
   if (!get_token(fp, selector, sizeof(selector)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected selector after %s on line %d of %s!\n"),
+                    _("ppdc: Expected selector after %s on line %d of %s."),
                    loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
     return (0);
   }
@@ -334,7 +369,7 @@ ppdcSource::get_attr(ppdcFile *fp,  // I - File to read
   if (!get_token(fp, value, sizeof(value)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected value after %s on line %d of %s!\n"),
+                    _("ppdc: Expected value after %s on line %d of %s."),
                    loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
     return (0);
   }
@@ -356,23 +391,23 @@ ppdcSource::get_boolean(ppdcFile *fp)     // I - File to read
   if (!get_token(fp, buffer, sizeof(buffer)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected boolean value on line %d of %s.\n"),
+                    _("ppdc: Expected boolean value on line %d of %s."),
                    fp->line, fp->filename);
     return (-1);
   }
 
-  if (!strcasecmp(buffer, "on") ||
-      !strcasecmp(buffer, "yes") ||
-      !strcasecmp(buffer, "true"))
+  if (!_cups_strcasecmp(buffer, "on") ||
+      !_cups_strcasecmp(buffer, "yes") ||
+      !_cups_strcasecmp(buffer, "true"))
     return (1);
-  else if (!strcasecmp(buffer, "off") ||
-          !strcasecmp(buffer, "no") ||
-          !strcasecmp(buffer, "false"))
+  else if (!_cups_strcasecmp(buffer, "off") ||
+          !_cups_strcasecmp(buffer, "no") ||
+          !_cups_strcasecmp(buffer, "false"))
     return (0);
   else
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Bad boolean value (%s) on line %d of %s.\n"),
+                    _("ppdc: Bad boolean value (%s) on line %d of %s."),
                    buffer, fp->line, fp->filename);
     return (-1);
   }
@@ -397,7 +432,7 @@ ppdcSource::get_choice(ppdcFile *fp)        // I - File to read
   if (!get_token(fp, name, sizeof(name)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected choice name/text on line %d of %s.\n"),
+                    _("ppdc: Expected choice name/text on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -409,7 +444,7 @@ ppdcSource::get_choice(ppdcFile *fp)        // I - File to read
 
   if (!get_token(fp, code, sizeof(code)))
   {
-    _cupsLangPrintf(stderr, _("ppdc: Expected choice code on line %d of %s.\n"),
+    _cupsLangPrintf(stderr, _("ppdc: Expected choice code on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -442,7 +477,7 @@ ppdcSource::get_color_model(ppdcFile *fp)
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected name/text combination for ColorModel on "
-                     "line %d of %s!\n"), fp->line, fp->filename);
+                     "line %d of %s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -455,7 +490,7 @@ ppdcSource::get_color_model(ppdcFile *fp)
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected colorspace for ColorModel on line %d of "
-                     "%s!\n"), fp->line, fp->filename);
+                     "%s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -466,7 +501,7 @@ ppdcSource::get_color_model(ppdcFile *fp)
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected color order for ColorModel on line %d of "
-                     "%s!\n"), fp->line, fp->filename);
+                     "%s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -477,7 +512,7 @@ ppdcSource::get_color_model(ppdcFile *fp)
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected compression for ColorModel on line %d of "
-                     "%s!\n"), fp->line, fp->filename);
+                     "%s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -500,12 +535,12 @@ int                                       // O - Color order value
 ppdcSource::get_color_order(
     const char *co)                    // I - Color order string
 {
-  if (!strcasecmp(co, "chunked") ||
-      !strcasecmp(co, "chunky"))
+  if (!_cups_strcasecmp(co, "chunked") ||
+      !_cups_strcasecmp(co, "chunky"))
     return (CUPS_ORDER_CHUNKED);
-  else if (!strcasecmp(co, "banded"))
+  else if (!_cups_strcasecmp(co, "banded"))
     return (CUPS_ORDER_BANDED);
-  else if (!strcasecmp(co, "planar"))
+  else if (!_cups_strcasecmp(co, "planar"))
     return (CUPS_ORDER_PLANAR);
   else
     return (-1);
@@ -535,7 +570,7 @@ ppdcSource::get_color_profile(
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected resolution/mediatype following "
-                     "ColorProfile on line %d of %s!\n"),
+                     "ColorProfile on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -562,71 +597,71 @@ int                                       // O - Colorspace value
 ppdcSource::get_color_space(
     const char *cs)                    // I - Colorspace string
 {
-  if (!strcasecmp(cs, "w"))
+  if (!_cups_strcasecmp(cs, "w"))
     return (CUPS_CSPACE_W);
-  else if (!strcasecmp(cs, "rgb"))
+  else if (!_cups_strcasecmp(cs, "rgb"))
     return (CUPS_CSPACE_RGB);
-  else if (!strcasecmp(cs, "rgba"))
+  else if (!_cups_strcasecmp(cs, "rgba"))
     return (CUPS_CSPACE_RGBA);
-  else if (!strcasecmp(cs, "k"))
+  else if (!_cups_strcasecmp(cs, "k"))
     return (CUPS_CSPACE_K);
-  else if (!strcasecmp(cs, "cmy"))
+  else if (!_cups_strcasecmp(cs, "cmy"))
     return (CUPS_CSPACE_CMY);
-  else if (!strcasecmp(cs, "ymc"))
+  else if (!_cups_strcasecmp(cs, "ymc"))
     return (CUPS_CSPACE_YMC);
-  else if (!strcasecmp(cs, "cmyk"))
+  else if (!_cups_strcasecmp(cs, "cmyk"))
     return (CUPS_CSPACE_CMYK);
-  else if (!strcasecmp(cs, "ymck"))
+  else if (!_cups_strcasecmp(cs, "ymck"))
     return (CUPS_CSPACE_YMCK);
-  else if (!strcasecmp(cs, "kcmy"))
+  else if (!_cups_strcasecmp(cs, "kcmy"))
     return (CUPS_CSPACE_KCMY);
-  else if (!strcasecmp(cs, "kcmycm"))
+  else if (!_cups_strcasecmp(cs, "kcmycm"))
     return (CUPS_CSPACE_KCMYcm);
-  else if (!strcasecmp(cs, "gmck"))
+  else if (!_cups_strcasecmp(cs, "gmck"))
     return (CUPS_CSPACE_GMCK);
-  else if (!strcasecmp(cs, "gmcs"))
+  else if (!_cups_strcasecmp(cs, "gmcs"))
     return (CUPS_CSPACE_GMCS);
-  else if (!strcasecmp(cs, "white"))
+  else if (!_cups_strcasecmp(cs, "white"))
     return (CUPS_CSPACE_WHITE);
-  else if (!strcasecmp(cs, "gold"))
+  else if (!_cups_strcasecmp(cs, "gold"))
     return (CUPS_CSPACE_GOLD);
-  else if (!strcasecmp(cs, "silver"))
+  else if (!_cups_strcasecmp(cs, "silver"))
     return (CUPS_CSPACE_SILVER);
-  else if (!strcasecmp(cs, "CIEXYZ"))
+  else if (!_cups_strcasecmp(cs, "CIEXYZ"))
     return (CUPS_CSPACE_CIEXYZ);
-  else if (!strcasecmp(cs, "CIELab"))
+  else if (!_cups_strcasecmp(cs, "CIELab"))
     return (CUPS_CSPACE_CIELab);
-  else if (!strcasecmp(cs, "RGBW"))
+  else if (!_cups_strcasecmp(cs, "RGBW"))
     return (CUPS_CSPACE_RGBW);
-  else if (!strcasecmp(cs, "ICC1"))
+  else if (!_cups_strcasecmp(cs, "ICC1"))
     return (CUPS_CSPACE_ICC1);
-  else if (!strcasecmp(cs, "ICC2"))
+  else if (!_cups_strcasecmp(cs, "ICC2"))
     return (CUPS_CSPACE_ICC2);
-  else if (!strcasecmp(cs, "ICC3"))
+  else if (!_cups_strcasecmp(cs, "ICC3"))
     return (CUPS_CSPACE_ICC3);
-  else if (!strcasecmp(cs, "ICC4"))
+  else if (!_cups_strcasecmp(cs, "ICC4"))
     return (CUPS_CSPACE_ICC4);
-  else if (!strcasecmp(cs, "ICC5"))
+  else if (!_cups_strcasecmp(cs, "ICC5"))
     return (CUPS_CSPACE_ICC5);
-  else if (!strcasecmp(cs, "ICC6"))
+  else if (!_cups_strcasecmp(cs, "ICC6"))
     return (CUPS_CSPACE_ICC6);
-  else if (!strcasecmp(cs, "ICC7"))
+  else if (!_cups_strcasecmp(cs, "ICC7"))
     return (CUPS_CSPACE_ICC7);
-  else if (!strcasecmp(cs, "ICC8"))
+  else if (!_cups_strcasecmp(cs, "ICC8"))
     return (CUPS_CSPACE_ICC8);
-  else if (!strcasecmp(cs, "ICC9"))
+  else if (!_cups_strcasecmp(cs, "ICC9"))
     return (CUPS_CSPACE_ICC9);
-  else if (!strcasecmp(cs, "ICCA"))
+  else if (!_cups_strcasecmp(cs, "ICCA"))
     return (CUPS_CSPACE_ICCA);
-  else if (!strcasecmp(cs, "ICCB"))
+  else if (!_cups_strcasecmp(cs, "ICCB"))
     return (CUPS_CSPACE_ICCB);
-  else if (!strcasecmp(cs, "ICCC"))
+  else if (!_cups_strcasecmp(cs, "ICCC"))
     return (CUPS_CSPACE_ICCC);
-  else if (!strcasecmp(cs, "ICCD"))
+  else if (!_cups_strcasecmp(cs, "ICCD"))
     return (CUPS_CSPACE_ICCD);
-  else if (!strcasecmp(cs, "ICCE"))
+  else if (!_cups_strcasecmp(cs, "ICCE"))
     return (CUPS_CSPACE_ICCE);
-  else if (!strcasecmp(cs, "ICCF"))
+  else if (!_cups_strcasecmp(cs, "ICCF"))
     return (CUPS_CSPACE_ICCF);
   else
     return (-1);
@@ -658,7 +693,7 @@ ppdcSource::get_constraint(ppdcFile *fp)// I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected constraints string for UIConstraints on "
-                     "line %d of %s!\n"), fp->line, fp->filename);
+                     "line %d of %s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -667,7 +702,7 @@ ppdcSource::get_constraint(ppdcFile *fp)// I - File to read
   if (*ptr != '*')
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Option constraint must *name on line %d of %s!\n"),
+                    _("ppdc: Option constraint must *name on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -690,7 +725,7 @@ ppdcSource::get_constraint(ppdcFile *fp)// I - File to read
   if (*ptr != '*')
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected two option names on line %d of %s!\n"),
+                    _("ppdc: Expected two option names on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -789,15 +824,15 @@ ppdcSource::get_duplex(ppdcFile   *fp,    // I - File to read from
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected duplex type after Duplex on line %d of "
-                     "%s!\n"), fp->line, fp->filename);
+                     "%s."), fp->line, fp->filename);
     return;
   }
 
   if (cond_state)
     return;
 
-  if (!strcasecmp(temp, "none") || !strcasecmp(temp, "false") ||
-      !strcasecmp(temp, "no") || !strcasecmp(temp, "off"))
+  if (!_cups_strcasecmp(temp, "none") || !_cups_strcasecmp(temp, "false") ||
+      !_cups_strcasecmp(temp, "no") || !_cups_strcasecmp(temp, "off"))
   {
     g = d->find_group("General");
     if ((o = g->find_option("Duplex")) != NULL)
@@ -812,10 +847,10 @@ ppdcSource::get_duplex(ppdcFile   *fp,    // I - File to read from
        break;
       }
   }
-  else if (!strcasecmp(temp, "normal") || !strcasecmp(temp, "true") ||
-          !strcasecmp(temp, "yes") || !strcasecmp(temp, "on") ||
-          !strcasecmp(temp, "flip") || !strcasecmp(temp, "rotated") ||
-          !strcasecmp(temp, "manualtumble"))
+  else if (!_cups_strcasecmp(temp, "normal") || !_cups_strcasecmp(temp, "true") ||
+          !_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "on") ||
+          !_cups_strcasecmp(temp, "flip") || !_cups_strcasecmp(temp, "rotated") ||
+          !_cups_strcasecmp(temp, "manualtumble"))
   {
     g = d->find_group("General");
     o = g->find_option("Duplex");
@@ -823,7 +858,7 @@ ppdcSource::get_duplex(ppdcFile   *fp,      // I - File to read from
     if (!o)
     {
       o = new ppdcOption(PPDC_PICKONE, "Duplex", "2-Sided Printing",
-                        !strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE :
+                        !_cups_strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE :
                                                     PPDC_SECTION_ANY, 10.0f);
       o->add_choice(new ppdcChoice("None", "Off (1-Sided)",
                                   "<</Duplex false>>setpagedevice"));
@@ -840,12 +875,12 @@ ppdcSource::get_duplex(ppdcFile   *fp,    // I - File to read from
         attr = (ppdcAttr *)d->attrs->next())
       if (!strcmp(attr->name->value, "cupsFlipDuplex"))
       {
-        if (strcasecmp(temp, "flip"))
+        if (_cups_strcasecmp(temp, "flip"))
           d->attrs->remove(attr);
        break;
       }
 
-    if (!strcasecmp(temp, "flip") && !attr)
+    if (!_cups_strcasecmp(temp, "flip") && !attr)
       d->add_attr(new ppdcAttr("cupsFlipDuplex", NULL, NULL, "true"));
 
     for (attr = (ppdcAttr *)d->attrs->first();
@@ -857,18 +892,18 @@ ppdcSource::get_duplex(ppdcFile   *fp,    // I - File to read from
        break;
       }
 
-    if (!strcasecmp(temp, "flip"))
+    if (!_cups_strcasecmp(temp, "flip"))
       d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Flipped"));
-    else if (!strcasecmp(temp, "rotated"))
+    else if (!_cups_strcasecmp(temp, "rotated"))
       d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Rotated"));
-    else if (!strcasecmp(temp, "manualtumble"))
+    else if (!_cups_strcasecmp(temp, "manualtumble"))
       d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "ManualTumble"));
     else
       d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Normal"));
   }
   else
     _cupsLangPrintf(stderr,
-                    _("ppdc: Unknown duplex type \"%s\" on line %d of %s!\n"),
+                    _("ppdc: Unknown duplex type \"%s\" on line %d of %s."),
                    temp, fp->line, fp->filename);
 }
 
@@ -894,7 +929,7 @@ ppdcSource::get_filter(ppdcFile *fp)        // I - File to read
   if (!get_token(fp, type, sizeof(type)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected a filter definition on line %d of %s!\n"),
+                    _("ppdc: Expected a filter definition on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -917,7 +952,7 @@ ppdcSource::get_filter(ppdcFile *fp)        // I - File to read
     if (!get_token(fp, program, sizeof(program)))
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Expected a program name on line %d of %s!\n"),
+                      _("ppdc: Expected a program name on line %d of %s."),
                      fp->line, fp->filename);
       return (NULL);
     }
@@ -927,14 +962,14 @@ ppdcSource::get_filter(ppdcFile *fp)      // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Invalid empty MIME type for filter on line %d of "
-                     "%s!\n"), fp->line, fp->filename);
+                     "%s."), fp->line, fp->filename);
     return (NULL);
   }
 
   if (cost < 0 || cost > 200)
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Invalid cost for filter on line %d of %s!\n"),
+                    _("ppdc: Invalid cost for filter on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -943,7 +978,7 @@ ppdcSource::get_filter(ppdcFile *fp)        // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Invalid empty program name for filter on line %d "
-                     "of %s!\n"), fp->line, fp->filename);
+                     "of %s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -966,7 +1001,7 @@ ppdcSource::get_float(ppdcFile *fp)        // I - File to read
   // Get the number from the file and range-check...
   if (!get_token(fp, temp, sizeof(temp)))
   {
-    _cupsLangPrintf(stderr, _("ppdc: Expected real number on line %d of %s!\n"),
+    _cupsLangPrintf(stderr, _("ppdc: Expected real number on line %d of %s."),
                    fp->line, fp->filename);
     return (-1.0f);
   }
@@ -977,7 +1012,7 @@ ppdcSource::get_float(ppdcFile *fp)        // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Unknown trailing characters in real number \"%s\" "
-                     "on line %d of %s!\n"), temp, fp->line, fp->filename);
+                     "on line %d of %s."), temp, fp->line, fp->filename);
     return (-1.0f);
   }
   else
@@ -1020,7 +1055,7 @@ ppdcSource::get_font(ppdcFile *fp)        // I - File to read
   if (!get_token(fp, name, sizeof(name)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected name after Font on line %d of %s!\n"),
+                    _("ppdc: Expected name after Font on line %d of %s."),
                    fp->line, fp->filename);
     return (0);
   }
@@ -1040,7 +1075,7 @@ ppdcSource::get_font(ppdcFile *fp)        // I - File to read
     {
       _cupsLangPrintf(stderr,
                       _("ppdc: Expected encoding after Font on line %d of "
-                       "%s!\n"), fp->line, fp->filename);
+                       "%s."), fp->line, fp->filename);
       return (0);
     }
 
@@ -1048,7 +1083,7 @@ ppdcSource::get_font(ppdcFile *fp)        // I - File to read
     {
       _cupsLangPrintf(stderr,
                       _("ppdc: Expected version after Font on line %d of "
-                       "%s!\n"), fp->line, fp->filename);
+                       "%s."), fp->line, fp->filename);
       return (0);
     }
 
@@ -1056,26 +1091,26 @@ ppdcSource::get_font(ppdcFile *fp)      // I - File to read
     {
       _cupsLangPrintf(stderr,
                       _("ppdc: Expected charset after Font on line %d of "
-                       "%s!\n"), fp->line, fp->filename);
+                       "%s."), fp->line, fp->filename);
       return (0);
     }
 
     if (!get_token(fp, temp, sizeof(temp)))
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Expected status after Font on line %d of %s!\n"),
+                      _("ppdc: Expected status after Font on line %d of %s."),
                      fp->line, fp->filename);
       return (0);
     }
 
-    if (!strcasecmp(temp, "ROM"))
+    if (!_cups_strcasecmp(temp, "ROM"))
       status = PPDC_FONT_ROM;
-    else if (!strcasecmp(temp, "Disk"))
+    else if (!_cups_strcasecmp(temp, "Disk"))
       status = PPDC_FONT_DISK;
     else
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Bad status keyword %s on line %d of %s!\n"),
+                      _("ppdc: Bad status keyword %s on line %d of %s."),
                      temp, fp->line, fp->filename);
       return (0);
     }
@@ -1118,7 +1153,7 @@ ppdcSource::get_generic(ppdcFile   *fp,   // I - File to read
   if (!get_token(fp, name, sizeof(name)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected name/text after %s on line %d of %s!\n"),
+                    _("ppdc: Expected name/text after %s on line %d of %s."),
                    keyword, fp->line, fp->filename);
     return (NULL);
   }
@@ -1167,7 +1202,7 @@ ppdcSource::get_group(ppdcFile   *fp,     // I - File to read
   if (!get_token(fp, name, sizeof(name)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected group name/text on line %d of %s!\n"),
+                    _("ppdc: Expected group name/text on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1208,7 +1243,7 @@ ppdcSource::get_installable(ppdcFile *fp)
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected name/text after Installable on line %d "
-                     "of %s!\n"), fp->line, fp->filename);
+                     "of %s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1283,7 +1318,7 @@ ppdcSource::get_integer(const char *v)    // I - Value string
     while (*v && *v != ')')
     {
       // Skip leading whitespace...
-      while (*v && isspace(*v & 255));
+      while (*v && isspace(*v & 255))
         v ++;
 
       if (!*v || *v == ')')
@@ -1326,17 +1361,17 @@ ppdcSource::get_integer(const char *v)  // I - Value string
        while (isspace(*newv & 255))
          newv ++;
 
-        if (strncmp(newv, "==", 2))
+        if (!strncmp(newv, "==", 2))
        {
          compop = PPDC_EQ;
          newv += 2;
        }
-        else if (strncmp(newv, "!=", 2))
+        else if (!strncmp(newv, "!=", 2))
         {
          compop = PPDC_NE;
          newv += 2;
        }
-        else if (strncmp(newv, "<=", 2))
+        else if (!strncmp(newv, "<=", 2))
         {
          compop = PPDC_LE;
          newv += 2;
@@ -1346,7 +1381,7 @@ ppdcSource::get_integer(const char *v)    // I - Value string
          compop = PPDC_LT;
          newv ++;
        }
-        else if (strncmp(newv, ">=", 2))
+        else if (!strncmp(newv, ">=", 2))
         {
          compop = PPDC_GE;
          newv += 2;
@@ -1367,7 +1402,7 @@ ppdcSource::get_integer(const char *v)    // I - Value string
           if (*newv == ')' || !*newv)
            return (-1);
 
-         if (isdigit(*v & 255) || *v == '-' || *v == '+')
+         if (isdigit(*newv & 255) || *newv == '-' || *newv == '+')
          {
            // Get the second number...
            temp2 = strtol(newv, &newv, 0);
@@ -1463,7 +1498,7 @@ ppdcSource::get_integer(ppdcFile *fp)     // I - File to read
 
   if (!get_token(fp, temp, sizeof(temp)))
   {
-    _cupsLangPrintf(stderr, _("ppdc: Expected integer on line %d of %s!\n"),
+    _cupsLangPrintf(stderr, _("ppdc: Expected integer on line %d of %s."),
                    fp->line, fp->filename);
     return (-1);
   }
@@ -1493,17 +1528,17 @@ ppdcSource::get_measurement(ppdcFile *fp)
   val = (float)strtod(buffer, &ptr);
 
   // Check for a trailing unit specifier...
-  if (!strcasecmp(ptr, "mm"))
+  if (!_cups_strcasecmp(ptr, "mm"))
     val *= 72.0f / 25.4f;
-  else if (!strcasecmp(ptr, "cm"))
+  else if (!_cups_strcasecmp(ptr, "cm"))
     val *= 72.0f / 2.54f;
-  else if (!strcasecmp(ptr, "m"))
+  else if (!_cups_strcasecmp(ptr, "m"))
     val *= 72.0f / 0.0254f;
-  else if (!strcasecmp(ptr, "in"))
+  else if (!_cups_strcasecmp(ptr, "in"))
     val *= 72.0f;
-  else if (!strcasecmp(ptr, "ft"))
+  else if (!_cups_strcasecmp(ptr, "ft"))
     val *= 72.0f * 12.0f;
-  else if (strcasecmp(ptr, "pt") && *ptr)
+  else if (_cups_strcasecmp(ptr, "pt") && *ptr)
     return (-1.0f);
 
   return (val);
@@ -1526,6 +1561,7 @@ ppdcSource::get_option(ppdcFile   *fp,    // I - File to read
   ppdcOptSection section;              // Option section
   float                order;                  // Option order
   ppdcOption   *o;                     // Option
+  ppdcGroup    *mg;                    // Matching group, if any
 
 
   // Read the Option parameters:
@@ -1534,7 +1570,7 @@ ppdcSource::get_option(ppdcFile   *fp,    // I - File to read
   if (!get_token(fp, name, sizeof(name)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected option name/text on line %d of %s!\n"),
+                    _("ppdc: Expected option name/text on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1546,21 +1582,21 @@ ppdcSource::get_option(ppdcFile   *fp,  // I - File to read
 
   if (!get_token(fp, type, sizeof(type)))
   {
-    _cupsLangPrintf(stderr, _("ppdc: Expected option type on line %d of %s!\n"),
+    _cupsLangPrintf(stderr, _("ppdc: Expected option type on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
 
-  if (!strcasecmp(type, "boolean"))
+  if (!_cups_strcasecmp(type, "boolean"))
     ot = PPDC_BOOLEAN;
-  else if (!strcasecmp(type, "pickone"))
+  else if (!_cups_strcasecmp(type, "pickone"))
     ot = PPDC_PICKONE;
-  else if (!strcasecmp(type, "pickmany"))
+  else if (!_cups_strcasecmp(type, "pickmany"))
     ot = PPDC_PICKMANY;
   else
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Invalid option type \"%s\" on line %d of %s!\n"),
+                    _("ppdc: Invalid option type \"%s\" on line %d of %s."),
                    type, fp->line, fp->filename);
     return (NULL);
   }
@@ -1568,35 +1604,35 @@ ppdcSource::get_option(ppdcFile   *fp,  // I - File to read
   if (!get_token(fp, type, sizeof(type)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected option section on line %d of %s!\n"),
+                    _("ppdc: Expected option section on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
 
-  if (!strcasecmp(type, "AnySetup"))
+  if (!_cups_strcasecmp(type, "AnySetup"))
     section = PPDC_SECTION_ANY;
-  else if (!strcasecmp(type, "DocumentSetup"))
+  else if (!_cups_strcasecmp(type, "DocumentSetup"))
     section = PPDC_SECTION_DOCUMENT;
-  else if (!strcasecmp(type, "ExitServer"))
+  else if (!_cups_strcasecmp(type, "ExitServer"))
     section = PPDC_SECTION_EXIT;
-  else if (!strcasecmp(type, "JCLSetup"))
+  else if (!_cups_strcasecmp(type, "JCLSetup"))
     section = PPDC_SECTION_JCL;
-  else if (!strcasecmp(type, "PageSetup"))
+  else if (!_cups_strcasecmp(type, "PageSetup"))
     section = PPDC_SECTION_PAGE;
-  else if (!strcasecmp(type, "Prolog"))
+  else if (!_cups_strcasecmp(type, "Prolog"))
     section = PPDC_SECTION_PROLOG;
   else
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Invalid option section \"%s\" on line %d of "
-                     "%s!\n"), type, fp->line, fp->filename);
+                     "%s."), type, fp->line, fp->filename);
     return (NULL);
   }
 
   order = get_float(fp);
 
   // See if the option already exists...
-  if ((o = d->find_option(name)) == NULL)
+  if ((o = d->find_option_group(name, &mg)) == NULL)
   {
     // Nope, add a new one...
     o = new ppdcOption(ot, name, text, section, order);
@@ -1605,7 +1641,14 @@ ppdcSource::get_option(ppdcFile   *fp,   // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Option %s redefined with a different type on line "
-                     "%d of %s!\n"), name, fp->line, fp->filename);
+                     "%d of %s."), name, fp->line, fp->filename);
+    return (NULL);
+  }
+  else if (g != mg)
+  {
+    _cupsLangPrintf(stderr,
+                    _("ppdc: Option %s defined in two different groups on line "
+                     "%d of %s."), name, fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1634,7 +1677,7 @@ ppdcSource::get_po(ppdcFile *fp)  // I - File to read
   if (!get_token(fp, locale, sizeof(locale)))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Expected locale after #po on line %d of %s!\n"),
+                    _("ppdc: Expected locale after #po on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1643,7 +1686,7 @@ ppdcSource::get_po(ppdcFile *fp)  // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected filename after #po %s on line %d of "
-                     "%s!\n"), locale, fp->line, fp->filename);
+                     "%s."), locale, fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1651,7 +1694,7 @@ ppdcSource::get_po(ppdcFile *fp)  // I - File to read
   if (find_po(locale))
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Duplicate #po for locale %s on line %d of %s!\n"),
+                    _("ppdc: Duplicate #po for locale %s on line %d of %s."),
                    locale, fp->line, fp->filename);
     return (NULL);
   }
@@ -1665,14 +1708,16 @@ ppdcSource::get_po(ppdcFile *fp)        // I - File to read
     strcpy(basedir, ".");
 
   // Find the po file...
-  if (!pofilename[0] ||
+  pofilename[0] = '\0';
+
+  if (!poname[0] ||
       find_include(poname, basedir, pofilename, sizeof(pofilename)))
   {
     // Found it, so load it...
     cat = new ppdcCatalog(locale, pofilename);
 
     // Reset the filename to the name supplied by the user...
-    delete cat->filename;
+    cat->filename->release();
     cat->filename = new ppdcString(poname);
 
     // Return the catalog...
@@ -1681,7 +1726,7 @@ ppdcSource::get_po(ppdcFile *fp)  // I - File to read
   else
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Unable to find #po file %s on line %d of %s!\n"),
+                    _("ppdc: Unable to find #po file %s on line %d of %s."),
                    poname, fp->line, fp->filename);
     return (NULL);
   }
@@ -1717,7 +1762,7 @@ ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected override field after Resolution on line "
-                     "%d of %s!\n"), fp->line, fp->filename);
+                     "%d of %s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1734,7 +1779,7 @@ ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
   {
     _cupsLangPrintf(stderr,
                    _("ppdc: Expected name/text after Resolution on line %d of "
-                     "%s!\n"), fp->line, fp->filename);
+                     "%s."), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1748,7 +1793,7 @@ ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
     case 0 :
         _cupsLangPrintf(stderr,
                        _("ppdc: Bad resolution name \"%s\" on line %d of "
-                         "%s!\n"), name, fp->line, fp->filename);
+                         "%s."), name, fp->line, fp->filename);
         break;
     case 1 :
         ydpi = xdpi;
@@ -1815,7 +1860,7 @@ ppdcSource::get_simple_profile(ppdcFile *fp)
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Expected resolution/mediatype following "
-                     "SimpleColorProfile on line %d of %s!\n"),
+                     "SimpleColorProfile on line %d of %s."),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1985,7 +2030,7 @@ ppdcSource::get_token(ppdcFile *fp,       // I - File to read
          // $ch = $ch
           _cupsLangPrintf(stderr,
                          _("ppdc: Bad variable substitution ($%c) on line %d "
-                           "of %s.\n"), ch, fp->line, fp->filename);
+                           "of %s."), ch, fp->line, fp->filename);
 
          if (bufptr < bufend)
            *bufptr++ = '$';
@@ -1998,16 +2043,18 @@ ppdcSource::get_token(ppdcFile *fp,     // I - File to read
        var = find_variable(name);
        if (var)
        {
-         strncpy(bufptr, var->value->value, bufend - bufptr);
-         bufptr += strlen(var->value->value);
+         strlcpy(bufptr, var->value->value, bufend - bufptr + 1);
+         bufptr += strlen(bufptr);
        }
        else
        {
-         _cupsLangPrintf(stderr,
-                         _("ppdc: Undefined variable (%s) on line %d of "
-                           "%s.\n"), name, fp->line, fp->filename);
+         if (!(cond_state & PPDC_COND_SKIP))
+           _cupsLangPrintf(stderr,
+                           _("ppdc: Undefined variable (%s) on line %d of "
+                             "%s."), name, fp->line, fp->filename);
+
          snprintf(bufptr, bufend - bufptr + 1, "$%s", name);
-         bufptr += strlen(name) + 1;
+         bufptr += strlen(bufptr);
        }
       }
     }
@@ -2114,7 +2161,7 @@ ppdcSource::get_token(ppdcFile *fp,       // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Unterminated string starting with %c on line %d "
-                     "of %s!\n"), quote, startline, fp->filename);
+                     "of %s."), quote, startline, fp->filename);
     return (NULL);
   }
 
@@ -2264,7 +2311,7 @@ ppdcSource::quotef(cups_file_t *fp,       // I - File to write to
 
            bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
            break;
-           
+
        case 'p' : // Pointer value
            if ((format - bufformat + 1) > (int)sizeof(tformat))
              break;
@@ -2351,7 +2398,7 @@ ppdcSource::read_file(const char  *f,     // I - File to read
   delete fp;
 
   if (cond_current != cond_stack)
-    _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"), f);
+    _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."), f);
 }
 
 
@@ -2366,6 +2413,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 {
   ppdcDriver   *d;                     // Current driver
   ppdcGroup    *g,                     // Current group
+               *mg,                    // Matching group
                *general,               // General options group
                *install;               // Installable options group
   ppdcOption   *o;                     // Current option
@@ -2377,7 +2425,10 @@ ppdcSource::scan_file(ppdcFile   *fp,    // I - File to read
 
   // Initialize things as needed...
   if (inc && td)
+  {
     d = td;
+    d->retain();
+  }
   else
     d = new ppdcDriver(td);
 
@@ -2415,28 +2466,28 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       isdefault = 0;
     }
 
-    if (!strcasecmp(temp, "}"))
+    if (!_cups_strcasecmp(temp, "}"))
     {
       // Close this one out...
       break;
     }
-    else if (!strcasecmp(temp, "{"))
+    else if (!_cups_strcasecmp(temp, "{"))
     {
       // Open a new child...
       scan_file(fp, d);
     }
-    else if (!strcasecmp(temp, "#if"))
+    else if (!_cups_strcasecmp(temp, "#if"))
     {
       if ((cond_current - cond_stack) >= 100)
       {
         _cupsLangPrintf(stderr,
-                       _("ppdc: Too many nested #if's on line %d of %s!\n"),
+                       _("ppdc: Too many nested #if's on line %d of %s."),
                        fp->line, fp->filename);
        break;
       }
 
       cond_current ++;
-      if (get_integer(fp))
+      if (get_integer(fp) > 0)
         *cond_current = PPDC_COND_SATISFIED;
       else
       {
@@ -2444,11 +2495,11 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
        cond_state    |= PPDC_COND_SKIP;
       }
     }
-    else if (!strcasecmp(temp, "#elif"))
+    else if (!_cups_strcasecmp(temp, "#elif"))
     {
       if (cond_current == cond_stack)
       {
-        _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
+        _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
                        fp->line, fp->filename);
         break;
       }
@@ -2458,7 +2509,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
         get_integer(fp);
        *cond_current |= PPDC_COND_SKIP;
       }
-      else if (get_integer(fp))
+      else if (get_integer(fp) > 0)
       {
         *cond_current |= PPDC_COND_SATISFIED;
        *cond_current &= ~PPDC_COND_SKIP;
@@ -2479,11 +2530,11 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
        else
          cond_temp --;
     }
-    else if (!strcasecmp(temp, "#else"))
+    else if (!_cups_strcasecmp(temp, "#else"))
     {
       if (cond_current == cond_stack)
       {
-        _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
+        _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
                        fp->line, fp->filename);
         break;
       }
@@ -2509,11 +2560,11 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
        else
          cond_temp --;
     }
-    else if (!strcasecmp(temp, "#endif"))
+    else if (!_cups_strcasecmp(temp, "#endif"))
     {
       if (cond_current == cond_stack)
       {
-        _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
+        _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s."),
                        fp->line, fp->filename);
         break;
       }
@@ -2533,12 +2584,12 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
        else
          cond_temp --;
     }
-    else if (!strcasecmp(temp, "#define"))
+    else if (!_cups_strcasecmp(temp, "#define"))
     {
       // Get the variable...
       get_variable(fp);
     }
-    else if (!strcasecmp(temp, "#include"))
+    else if (!_cups_strcasecmp(temp, "#include"))
     {
       // #include filename
       char     basedir[1024],          // Base directory
@@ -2555,7 +2606,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected include filename on line %d of "
-                         "%s!\n"), fp->line, fp->filename);
+                         "%s."), fp->line, fp->filename);
         break;
       }
 
@@ -2579,7 +2630,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
        delete incfile;
 
        if (cond_current != old_current)
-         _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"),
+         _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"."),
                          incname);
       }
       else
@@ -2587,11 +2638,11 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
        // Can't find it!
        _cupsLangPrintf(stderr,
                        _("ppdc: Unable to find include file \"%s\" on line %d "
-                         "of %s!\n"), inctemp, fp->line, fp->filename);
+                         "of %s."), inctemp, fp->line, fp->filename);
        break;
       }
     }
-    else if (!strcasecmp(temp, "#media"))
+    else if (!_cups_strcasecmp(temp, "#media"))
     {
       ppdcMediaSize    *m;             // Media size
 
@@ -2606,7 +2657,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
           sizes->add(m);
       }
     }
-    else if (!strcasecmp(temp, "#po"))
+    else if (!_cups_strcasecmp(temp, "#po"))
     {
       ppdcCatalog      *cat;           // Message catalog
 
@@ -2621,14 +2672,14 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
          po_files->add(cat);
       }
     }
-    else if (!strcasecmp(temp, "Attribute") ||
-             !strcasecmp(temp, "LocAttribute"))
+    else if (!_cups_strcasecmp(temp, "Attribute") ||
+             !_cups_strcasecmp(temp, "LocAttribute"))
     {
       ppdcAttr *a;                     // Attribute
 
 
       // Get an attribute...
-      a = get_attr(fp, !strcasecmp(temp, "LocAttribute"));
+      a = get_attr(fp, !_cups_strcasecmp(temp, "LocAttribute"));
       if (a)
       {
         if (cond_state)
@@ -2637,7 +2688,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
           d->add_attr(a);
       }
     }
-    else if (!strcasecmp(temp, "Choice"))
+    else if (!_cups_strcasecmp(temp, "Choice"))
     {
       // Get a choice...
       c = get_choice(fp);
@@ -2655,7 +2706,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Choice found on line %d of %s with no "
-                         "Option!\n"), fp->line, fp->filename);
+                         "Option."), fp->line, fp->filename);
         break;
       }
 
@@ -2664,7 +2715,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       if (isdefault)
         o->set_defchoice(c);
     }
-    else if (!strcasecmp(temp, "ColorDevice"))
+    else if (!_cups_strcasecmp(temp, "ColorDevice"))
     {
       // ColorDevice boolean
       if (cond_state)
@@ -2672,7 +2723,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       else
         d->color_device = get_boolean(fp);
     }
-    else if (!strcasecmp(temp, "ColorModel"))
+    else if (!_cups_strcasecmp(temp, "ColorModel"))
     {
       // Get the color model
       c = get_color_model(fp);
@@ -2701,7 +2752,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "ColorProfile"))
+    else if (!_cups_strcasecmp(temp, "ColorProfile"))
     {
       ppdcProfile      *p;             // Color profile
 
@@ -2717,7 +2768,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
           d->profiles->add(p);
       }
     }
-    else if (!strcasecmp(temp, "Copyright"))
+    else if (!_cups_strcasecmp(temp, "Copyright"))
     {
       // Copyright string
       char     copytemp[8192],         // Copyright string
@@ -2730,7 +2781,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected string after Copyright on line %d "
-                         "of %s!\n"), fp->line, fp->filename);
+                         "of %s."), fp->line, fp->filename);
        break;
       }
 
@@ -2746,7 +2797,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
         d->copyright->add(new ppdcString(copyptr));
       }
     }
-    else if (!strcasecmp(temp, "CustomMedia"))
+    else if (!_cups_strcasecmp(temp, "CustomMedia"))
     {
       ppdcMediaSize    *m;             // Media size
 
@@ -2766,7 +2817,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       if (isdefault)
         d->set_default_size(m);
     }
-    else if (!strcasecmp(temp, "Cutter"))
+    else if (!_cups_strcasecmp(temp, "Cutter"))
     {
       // Cutter boolean
       int      have_cutter;            // Have a paper cutter?
@@ -2793,7 +2844,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "Darkness"))
+    else if (!_cups_strcasecmp(temp, "Darkness"))
     {
       // Get the darkness choice...
       c = get_generic(fp, "Darkness", NULL, "cupsCompression");
@@ -2807,13 +2858,22 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       }
 
       // Add the choice to the cupsDarkness option...
-      if ((o = d->find_option("cupsDarkness")) == NULL)
+      if ((o = d->find_option_group("cupsDarkness", &mg)) == NULL)
       {
        // Create the cupsDarkness option...
        o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
        g = general;
        g->add_option(o);
       }
+      else if (mg != general)
+      {
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Option %s defined in two different groups on "
+                         "line %d of %s."), "cupsDarkness", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -2822,7 +2882,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "DriverType"))
+    else if (!_cups_strcasecmp(temp, "DriverType"))
     {
       int      i;                      // Looping var
 
@@ -2832,7 +2892,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected driver type keyword following "
-                         "DriverType on line %d of %s!\n"),
+                         "DriverType on line %d of %s."),
                        fp->line, fp->filename);
         continue;
       }
@@ -2841,21 +2901,21 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
         continue;
 
       for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
-        if (!strcasecmp(temp, driver_types[i]))
+        if (!_cups_strcasecmp(temp, driver_types[i]))
          break;
 
       if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
         d->type = (ppdcDrvType)i;
-      else if (!strcasecmp(temp, "dymo"))
+      else if (!_cups_strcasecmp(temp, "dymo"))
         d->type = PPDC_DRIVER_LABEL;
       else
         _cupsLangPrintf(stderr,
-                       _("ppdc: Unknown driver type %s on line %d of %s!\n"),
+                       _("ppdc: Unknown driver type %s on line %d of %s."),
                        temp, fp->line, fp->filename);
     }
-    else if (!strcasecmp(temp, "Duplex"))
+    else if (!_cups_strcasecmp(temp, "Duplex"))
       get_duplex(fp, d);
-    else if (!strcasecmp(temp, "Filter"))
+    else if (!_cups_strcasecmp(temp, "Filter"))
     {
       ppdcFilter       *f;             // Filter
 
@@ -2870,7 +2930,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
           d->filters->add(f);
       }
     }
-    else if (!strcasecmp(temp, "Finishing"))
+    else if (!_cups_strcasecmp(temp, "Finishing"))
     {
       // Get the finishing choice...
       c = get_generic(fp, "Finishing", "OutputType", NULL);
@@ -2884,13 +2944,22 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       }
 
       // Add the choice to the cupsFinishing option...
-      if ((o = d->find_option("cupsFinishing")) == NULL)
+      if ((o = d->find_option_group("cupsFinishing", &mg)) == NULL)
       {
        // Create the cupsFinishing option...
        o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
        g = general;
        g->add_option(o);
       }
+      else if (mg != general)
+      {
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Option %s defined in two different groups on "
+                         "line %d of %s."), "cupsFinishing", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -2899,8 +2968,8 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "Font") ||
-             !strcasecmp(temp, "#font"))
+    else if (!_cups_strcasecmp(temp, "Font") ||
+             !_cups_strcasecmp(temp, "#font"))
     {
       ppdcFont *f;                     // Font
 
@@ -2913,7 +2982,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
          f->release();
        else
        {
-         if (!strcasecmp(temp, "#font"))
+         if (!_cups_strcasecmp(temp, "#font"))
            base_fonts->add(f);
          else
            d->add_font(f);
@@ -2923,7 +2992,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
        }
       }
     }
-    else if (!strcasecmp(temp, "Group"))
+    else if (!_cups_strcasecmp(temp, "Group"))
     {
       // Get a group...
       ppdcGroup *tempg = get_group(fp, d);
@@ -2944,7 +3013,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
         g = tempg;
       }
     }
-    else if (!strcasecmp(temp, "HWMargins"))
+    else if (!_cups_strcasecmp(temp, "HWMargins"))
     {
       // HWMargins left bottom right top
       d->left_margin   = get_measurement(fp);
@@ -2952,7 +3021,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       d->right_margin  = get_measurement(fp);
       d->top_margin    = get_measurement(fp);
     }
-    else if (!strcasecmp(temp, "InputSlot"))
+    else if (!_cups_strcasecmp(temp, "InputSlot"))
     {
       // Get the input slot choice...
       c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
@@ -2966,7 +3035,8 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       }
 
       // Add the choice to the InputSlot option...
-      if ((o = d->find_option("InputSlot")) == NULL)
+
+      if ((o = d->find_option_group("InputSlot", &mg)) == NULL)
       {
        // Create the InputSlot option...
        o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
@@ -2974,6 +3044,15 @@ ppdcSource::scan_file(ppdcFile   *fp,    // I - File to read
        g = general;
        g->add_option(o);
       }
+      else if (mg != general)
+      {
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Option %s defined in two different groups on "
+                         "line %d of %s."), "InputSlot", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -2982,7 +3061,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "Installable"))
+    else if (!_cups_strcasecmp(temp, "Installable"))
     {
       // Get the installable option...
       o = get_installable(fp);
@@ -2998,7 +3077,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
         o = NULL;
       }
     }
-    else if (!strcasecmp(temp, "ManualCopies"))
+    else if (!_cups_strcasecmp(temp, "ManualCopies"))
     {
       // ManualCopies boolean
       if (cond_state)
@@ -3006,7 +3085,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       else
         d->manual_copies = get_boolean(fp);
     }
-    else if (!strcasecmp(temp, "Manufacturer"))
+    else if (!_cups_strcasecmp(temp, "Manufacturer"))
     {
       // Manufacturer name
       char     name[256];              // Model name string
@@ -3016,14 +3095,14 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected name after Manufacturer on line %d "
-                         "of %s!\n"), fp->line, fp->filename);
+                         "of %s."), fp->line, fp->filename);
        break;
       }
 
       if (!cond_state)
         d->set_manufacturer(name);
     }
-    else if (!strcasecmp(temp, "MaxSize"))
+    else if (!_cups_strcasecmp(temp, "MaxSize"))
     {
       // MaxSize width length
       if (cond_state)
@@ -3037,7 +3116,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
        d->max_length = get_measurement(fp);
       }
     }
-    else if (!strcasecmp(temp, "MediaSize"))
+    else if (!_cups_strcasecmp(temp, "MediaSize"))
     {
       // MediaSize keyword
       char             name[41];       // Media size name
@@ -3049,7 +3128,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected name after MediaSize on line %d of "
-                         "%s!\n"), fp->line, fp->filename);
+                         "%s."), fp->line, fp->filename);
        break;
       }
 
@@ -3062,7 +3141,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Unknown media size \"%s\" on line %d of "
-                         "%s!\n"), name, fp->line, fp->filename);
+                         "%s."), name, fp->line, fp->filename);
        break;
       }
 
@@ -3076,7 +3155,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       if (isdefault)
         d->set_default_size(dm);
     }
-    else if (!strcasecmp(temp, "MediaType"))
+    else if (!_cups_strcasecmp(temp, "MediaType"))
     {
       // Get the media type choice...
       c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
@@ -3090,7 +3169,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       }
 
       // Add the choice to the MediaType option...
-      if ((o = d->find_option("MediaType")) == NULL)
+      if ((o = d->find_option_group("MediaType", &mg)) == NULL)
       {
        // Create the MediaType option...
        o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
@@ -3098,6 +3177,15 @@ ppdcSource::scan_file(ppdcFile   *fp,    // I - File to read
        g = general;
        g->add_option(o);
       }
+      else if (mg != general)
+      {
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Option %s defined in two different groups on "
+                         "line %d of %s."), "MediaType", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -3106,7 +3194,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "MinSize"))
+    else if (!_cups_strcasecmp(temp, "MinSize"))
     {
       // MinSize width length
       if (cond_state)
@@ -3120,7 +3208,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
        d->min_length = get_measurement(fp);
       }
     }
-    else if (!strcasecmp(temp, "ModelName"))
+    else if (!_cups_strcasecmp(temp, "ModelName"))
     {
       // ModelName name
       char     name[256];              // Model name string
@@ -3130,14 +3218,14 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected name after ModelName on line %d of "
-                         "%s!\n"), fp->line, fp->filename);
+                         "%s."), fp->line, fp->filename);
        break;
       }
 
       if (!cond_state)
         d->set_model_name(name);
     }
-    else if (!strcasecmp(temp, "ModelNumber"))
+    else if (!_cups_strcasecmp(temp, "ModelNumber"))
     {
       // ModelNumber number
       if (cond_state)
@@ -3145,7 +3233,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       else
         d->model_number = get_integer(fp);
     }
-    else if (!strcasecmp(temp, "Option"))
+    else if (!_cups_strcasecmp(temp, "Option"))
     {
       // Get an option...
       ppdcOption *tempo = get_option(fp, d, g);
@@ -3166,7 +3254,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
         o = tempo;
       }
     }
-    else if (!strcasecmp(temp, "FileName"))
+    else if (!_cups_strcasecmp(temp, "FileName"))
     {
       // FileName name
       char     name[256];              // Filename string
@@ -3176,14 +3264,14 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected name after FileName on line %d of "
-                         "%s!\n"), fp->line, fp->filename);
+                         "%s."), fp->line, fp->filename);
        break;
       }
 
       if (!cond_state)
         d->set_file_name(name);
     }
-    else if (!strcasecmp(temp, "PCFileName"))
+    else if (!_cups_strcasecmp(temp, "PCFileName"))
     {
       // PCFileName name
       char     name[256];              // PC filename string
@@ -3193,14 +3281,14 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected name after PCFileName on line %d of "
-                         "%s!\n"), fp->line, fp->filename);
+                         "%s."), fp->line, fp->filename);
        break;
       }
 
       if (!cond_state)
         d->set_pc_file_name(name);
     }
-    else if (!strcasecmp(temp, "Resolution"))
+    else if (!_cups_strcasecmp(temp, "Resolution"))
     {
       // Get the resolution choice...
       c = get_resolution(fp);
@@ -3214,7 +3302,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       }
 
       // Add the choice to the Resolution option...
-      if ((o = d->find_option("Resolution")) == NULL)
+      if ((o = d->find_option_group("Resolution", &mg)) == NULL)
       {
        // Create the Resolution option...
        o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
@@ -3222,6 +3310,15 @@ ppdcSource::scan_file(ppdcFile   *fp,    // I - File to read
        g = general;
        g->add_option(o);
       }
+      else if (mg != general)
+      {
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Option %s defined in two different groups on "
+                         "line %d of %s."), "Resolution", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -3230,7 +3327,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
 
       o = NULL;
     }
-    else if (!strcasecmp(temp, "SimpleColorProfile"))
+    else if (!_cups_strcasecmp(temp, "SimpleColorProfile"))
     {
       ppdcProfile      *p;             // Color profile
 
@@ -3246,7 +3343,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
           d->profiles->add(p);
       }
     }
-    else if (!strcasecmp(temp, "Throughput"))
+    else if (!_cups_strcasecmp(temp, "Throughput"))
     {
       // Throughput number
       if (cond_state)
@@ -3254,7 +3351,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       else
         d->throughput = get_integer(fp);
     }
-    else if (!strcasecmp(temp, "UIConstraints"))
+    else if (!_cups_strcasecmp(temp, "UIConstraints"))
     {
       ppdcConstraint   *con;           // Constraint
 
@@ -3269,7 +3366,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
          d->constraints->add(con);
       }
     }
-    else if (!strcasecmp(temp, "VariablePaperSize"))
+    else if (!_cups_strcasecmp(temp, "VariablePaperSize"))
     {
       // VariablePaperSize boolean
       if (cond_state)
@@ -3277,7 +3374,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       else
        d->variable_paper_size = get_boolean(fp);
     }
-    else if (!strcasecmp(temp, "Version"))
+    else if (!_cups_strcasecmp(temp, "Version"))
     {
       // Version string
       char     name[256];              // Model name string
@@ -3287,7 +3384,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       {
         _cupsLangPrintf(stderr,
                        _("ppdc: Expected string after Version on line %d of "
-                         "%s!\n"), fp->line, fp->filename);
+                         "%s."), fp->line, fp->filename);
        break;
       }
 
@@ -3297,7 +3394,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
     else
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Unknown token \"%s\" seen on line %d of %s!\n"),
+                      _("ppdc: Unknown token \"%s\" seen on line %d of %s."),
                      temp, fp->line, fp->filename);
       break;
     }
@@ -3318,6 +3415,8 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       drivers->add(d);
     }
   }
+  else if (inc && td)
+    td->release();
 }
 
 
@@ -3412,7 +3511,8 @@ ppdcSource::write_file(const char *f)     // I - File to write
   for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
   {
     // Start the driver...
-    cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value, d->model_name->value);
+    cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value,
+                   d->model_name->value);
     cupsFilePuts(fp, "{\n");
 
     // Write the copyright stings...
@@ -3422,15 +3522,15 @@ ppdcSource::write_file(const char *f)   // I - File to write
       quotef(fp, "  Copyright \"%s\"\n", st->value);
 
     // Write other strings and values...
-    if (d->manufacturer->value)
+    if (d->manufacturer && d->manufacturer->value)
       quotef(fp, "  Manufacturer \"%s\"\n", d->manufacturer->value);
     if (d->model_name->value)
       quotef(fp, "  ModelName \"%s\"\n", d->model_name->value);
-    if (d->file_name->value)
+    if (d->file_name && d->file_name->value)
       quotef(fp, "  FileName \"%s\"\n", d->file_name->value);
-    if (d->pc_file_name->value)
+    if (d->pc_file_name && d->pc_file_name->value)
       quotef(fp, "  PCFileName \"%s\"\n", d->pc_file_name->value);
-    if (d->version->value)
+    if (d->version && d->version->value)
       quotef(fp, "  Version \"%s\"\n", d->version->value);
 
     cupsFilePrintf(fp, "  DriverType %s\n", driver_types[d->type]);
@@ -3439,64 +3539,6 @@ ppdcSource::write_file(const char *f)    // I - File to write
     {
       switch (d->type)
       {
-        case PPDC_DRIVER_ESCP :
-           cupsFilePuts(fp, "  ModelNumber (");
-
-           if (d->model_number & ESCP_DOTMATRIX)
-             cupsFilePuts(fp, " $ESCP_DOTMATRIX");
-           if (d->model_number & ESCP_MICROWEAVE)
-             cupsFilePuts(fp, " $ESCP_MICROWEAVE");
-           if (d->model_number & ESCP_STAGGER)
-             cupsFilePuts(fp, " $ESCP_STAGGER");
-           if (d->model_number & ESCP_ESCK)
-             cupsFilePuts(fp, " $ESCP_ESCK");
-           if (d->model_number & ESCP_EXT_UNITS)
-             cupsFilePuts(fp, " $ESCP_EXT_UNITS");
-           if (d->model_number & ESCP_EXT_MARGINS)
-             cupsFilePuts(fp, " $ESCP_EXT_MARGINS");
-           if (d->model_number & ESCP_USB)
-             cupsFilePuts(fp, " $ESCP_USB");
-           if (d->model_number & ESCP_PAGE_SIZE)
-             cupsFilePuts(fp, " $ESCP_PAGE_SIZE");
-           if (d->model_number & ESCP_RASTER_ESCI)
-             cupsFilePuts(fp, " $ESCP_RASTER_ESCI");
-           if (d->model_number & ESCP_REMOTE)
-             cupsFilePuts(fp, " $ESCP_REMOTE");
-
-           cupsFilePuts(fp, ")\n");
-           break;
-
-       case PPDC_DRIVER_PCL :
-           cupsFilePuts(fp, "  ModelNumber (");
-
-           if (d->model_number & PCL_PAPER_SIZE)
-             cupsFilePuts(fp, " $PCL_PAPER_SIZE");
-           if (d->model_number & PCL_INKJET)
-             cupsFilePuts(fp, " $PCL_INKJET");
-           if (d->model_number & PCL_RASTER_END_COLOR)
-             cupsFilePuts(fp, " $PCL_RASTER_END_COLOR");
-           if (d->model_number & PCL_RASTER_CID)
-             cupsFilePuts(fp, " $PCL_RASTER_CID");
-           if (d->model_number & PCL_RASTER_CRD)
-             cupsFilePuts(fp, " $PCL_RASTER_CRD");
-           if (d->model_number & PCL_RASTER_SIMPLE)
-             cupsFilePuts(fp, " $PCL_RASTER_SIMPLE");
-           if (d->model_number & PCL_RASTER_RGB24)
-             cupsFilePuts(fp, " $PCL_RASTER_RGB24");
-           if (d->model_number & PCL_PJL)
-             cupsFilePuts(fp, " $PCL_PJL");
-           if (d->model_number & PCL_PJL_PAPERWIDTH)
-             cupsFilePuts(fp, " $PCL_PJL_PAPERWIDTH");
-           if (d->model_number & PCL_PJL_HPGL2)
-             cupsFilePuts(fp, " $PCL_PJL_HPGL2");
-           if (d->model_number & PCL_PJL_PCL3GUI)
-             cupsFilePuts(fp, " $PCL_PJL_PCL3GUI");
-           if (d->model_number & PCL_PJL_RESOLUTION)
-             cupsFilePuts(fp, " $PCL_PJL_RESOLUTION");
-
-           cupsFilePuts(fp, ")\n");
-           break;
-
        case PPDC_DRIVER_LABEL :
            cupsFilePuts(fp, "  ModelNumber ");