]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - ppdc/ppdc-source.cxx
Merge changes from CUPS 1.5svn-r8950.
[thirdparty/cups.git] / ppdc / ppdc-source.cxx
index 237b0fd0f95ff0dbbedd6ad9d16eb9f01e85ff74..3b211534715960bd79003540e36a2564753d632f 100644 (file)
@@ -3,7 +3,7 @@
 //
 //   Source class for the CUPS PPD Compiler.
 //
-//   Copyright 2007-2009 by Apple Inc.
+//   Copyright 2007-2010 by Apple Inc.
 //   Copyright 2002-2007 by Easy Software Products.
 //
 //   These coded instructions, statements, and computer programs are the
@@ -71,6 +71,9 @@
 #include "data/hp.h"
 #include "data/label.h"
 #include "data/pcl.h"
+#ifndef WIN32
+#  include <sys/utsname.h>
+#endif // !WIN32
 
 
 //
@@ -110,6 +113,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);
 }
@@ -197,7 +227,7 @@ ppdcSource::find_include(
     if (*ptr != '>')
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Invalid #include/#po filename \"%s\"!\n"), n);
+                      _("ppdc: Invalid #include/#po filename \"%s\"\n"), n);
       return (0);
     }
 
@@ -323,7 +353,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\n"),
                    loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
     return (0);
   }
@@ -331,7 +361,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\n"),
                    loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
     return (0);
   }
@@ -342,7 +372,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\n"),
                    loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
     return (0);
   }
@@ -450,7 +480,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -463,7 +493,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -474,7 +504,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -485,7 +515,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -543,7 +573,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -666,7 +696,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -675,7 +705,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -698,7 +728,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -797,7 +827,7 @@ 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\n"), fp->line, fp->filename);
     return;
   }
 
@@ -876,7 +906,7 @@ ppdcSource::get_duplex(ppdcFile   *fp,      // I - File to read from
   }
   else
     _cupsLangPrintf(stderr,
-                    _("ppdc: Unknown duplex type \"%s\" on line %d of %s!\n"),
+                    _("ppdc: Unknown duplex type \"%s\" on line %d of %s\n"),
                    temp, fp->line, fp->filename);
 }
 
@@ -902,7 +932,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -925,7 +955,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\n"),
                      fp->line, fp->filename);
       return (NULL);
     }
@@ -935,14 +965,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\n"), 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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -951,7 +981,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -974,7 +1004,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\n"),
                    fp->line, fp->filename);
     return (-1.0f);
   }
@@ -985,7 +1015,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\n"), temp, fp->line, fp->filename);
     return (-1.0f);
   }
   else
@@ -1028,7 +1058,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\n"),
                    fp->line, fp->filename);
     return (0);
   }
@@ -1048,7 +1078,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\n"), fp->line, fp->filename);
       return (0);
     }
 
@@ -1056,7 +1086,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\n"), fp->line, fp->filename);
       return (0);
     }
 
@@ -1064,14 +1094,14 @@ 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\n"), 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\n"),
                      fp->line, fp->filename);
       return (0);
     }
@@ -1083,7 +1113,7 @@ ppdcSource::get_font(ppdcFile *fp)        // I - File to read
     else
     {
       _cupsLangPrintf(stderr,
-                      _("ppdc: Bad status keyword %s on line %d of %s!\n"),
+                      _("ppdc: Bad status keyword %s on line %d of %s\n"),
                      temp, fp->line, fp->filename);
       return (0);
     }
@@ -1126,7 +1156,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\n"),
                    keyword, fp->line, fp->filename);
     return (NULL);
   }
@@ -1175,7 +1205,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1216,7 +1246,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1291,7 +1321,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 == ')')
@@ -1471,7 +1501,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\n"),
                    fp->line, fp->filename);
     return (-1);
   }
@@ -1534,6 +1564,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:
@@ -1542,7 +1573,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1554,7 +1585,7 @@ 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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1568,7 +1599,7 @@ ppdcSource::get_option(ppdcFile   *fp,    // I - File to read
   else
   {
     _cupsLangPrintf(stderr,
-                    _("ppdc: Invalid option type \"%s\" on line %d of %s!\n"),
+                    _("ppdc: Invalid option type \"%s\" on line %d of %s\n"),
                    type, fp->line, fp->filename);
     return (NULL);
   }
@@ -1576,7 +1607,7 @@ 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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1597,14 +1628,14 @@ ppdcSource::get_option(ppdcFile   *fp,  // I - File to read
   {
     _cupsLangPrintf(stderr,
                     _("ppdc: Invalid option section \"%s\" on line %d of "
-                     "%s!\n"), type, fp->line, fp->filename);
+                     "%s\n"), 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);
@@ -1613,7 +1644,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\n"), 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\n"), name, fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1642,7 +1680,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -1651,7 +1689,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\n"), locale, fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1659,7 +1697,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\n"),
                    locale, fp->line, fp->filename);
     return (NULL);
   }
@@ -1691,7 +1729,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\n"),
                    poname, fp->line, fp->filename);
     return (NULL);
   }
@@ -1727,7 +1765,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1744,7 +1782,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\n"), fp->line, fp->filename);
     return (NULL);
   }
 
@@ -1758,7 +1796,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\n"), name, fp->line, fp->filename);
         break;
     case 1 :
         ydpi = xdpi;
@@ -1825,7 +1863,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\n"),
                    fp->line, fp->filename);
     return (NULL);
   }
@@ -2013,9 +2051,11 @@ ppdcSource::get_token(ppdcFile *fp,      // I - File to read
        }
        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.\n"), name, fp->line, fp->filename);
+
          snprintf(bufptr, bufend - bufptr + 1, "$%s", name);
          bufptr += strlen(name) + 1;
        }
@@ -2124,7 +2164,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\n"), quote, startline, fp->filename);
     return (NULL);
   }
 
@@ -2361,7 +2401,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\"\n"), f);
 }
 
 
@@ -2376,6 +2416,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
@@ -2387,7 +2428,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);
 
@@ -2440,13 +2484,13 @@ ppdcSource::scan_file(ppdcFile   *fp,   // I - File to read
       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\n"),
                        fp->line, fp->filename);
        break;
       }
 
       cond_current ++;
-      if (get_integer(fp))
+      if (get_integer(fp) > 0)
         *cond_current = PPDC_COND_SATISFIED;
       else
       {
@@ -2458,7 +2502,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
     {
       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\n"),
                        fp->line, fp->filename);
         break;
       }
@@ -2468,7 +2512,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;
@@ -2493,7 +2537,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
     {
       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\n"),
                        fp->line, fp->filename);
         break;
       }
@@ -2523,7 +2567,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
     {
       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\n"),
                        fp->line, fp->filename);
         break;
       }
@@ -2565,7 +2609,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\n"), fp->line, fp->filename);
         break;
       }
 
@@ -2589,7 +2633,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\"\n"),
                          incname);
       }
       else
@@ -2597,7 +2641,7 @@ 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\n"), inctemp, fp->line, fp->filename);
        break;
       }
     }
@@ -2665,7 +2709,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\n"), fp->line, fp->filename);
         break;
       }
 
@@ -2740,7 +2784,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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -2817,13 +2861,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\n"), "cupsDarkness", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -2842,7 +2895,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\n"),
                        fp->line, fp->filename);
         continue;
       }
@@ -2860,7 +2913,7 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
         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\n"),
                        temp, fp->line, fp->filename);
     }
     else if (!strcasecmp(temp, "Duplex"))
@@ -2894,13 +2947,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\n"), "cupsFinishing", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -2976,7 +3038,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",
@@ -2984,6 +3047,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\n"), "InputSlot", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -3026,7 +3098,7 @@ 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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -3059,7 +3131,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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -3072,7 +3144,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\n"), name, fp->line, fp->filename);
        break;
       }
 
@@ -3100,7 +3172,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",
@@ -3108,6 +3180,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\n"), "MediaType", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -3140,7 +3221,7 @@ 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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -3186,7 +3267,7 @@ 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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -3203,7 +3284,7 @@ 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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -3224,7 +3305,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,
@@ -3232,6 +3313,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\n"), "Resolution", fp->line,
+                       fp->filename);
+       c->release();
+       continue;
+      }
 
       o->add_choice(c);
 
@@ -3297,7 +3387,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\n"), fp->line, fp->filename);
        break;
       }
 
@@ -3307,7 +3397,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\n"),
                      temp, fp->line, fp->filename);
       break;
     }
@@ -3328,6 +3418,8 @@ ppdcSource::scan_file(ppdcFile   *fp,     // I - File to read
       drivers->add(d);
     }
   }
+  else if (inc && td)
+    td->release();
 }
 
 
@@ -3422,7 +3514,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...