]> git.ipfire.org Git - thirdparty/cups-filters.git/commitdiff
libppd: Code clean-up for code of foomatic-rip
authorTill Kamppeter <till.kamppeter@gmail.com>
Wed, 19 Oct 2022 21:38:59 +0000 (23:38 +0200)
committerTill Kamppeter <till.kamppeter@gmail.com>
Wed, 19 Oct 2022 21:38:59 +0000 (23:38 +0200)
Cleaned up the code following the coding style rules in the
DEVELOPING.md file of the CUPS source code.

Comments are re-formatted to use "// ..." instead of "/* ... */", like
in PAPPL, so C and C++ files get the same comment style.

The indent width is set to 2 spaces instead of 4, to match the other
files.

This way we get rid of the mix of many different coding styles which
came together from the many code contributions received during more
than a decade, even before the start of the cups-filters project.

16 files changed:
filter/foomatic-rip/foomaticrip.c
filter/foomatic-rip/foomaticrip.h
filter/foomatic-rip/options.c
filter/foomatic-rip/options.h
filter/foomatic-rip/pdf.c
filter/foomatic-rip/pdf.h
filter/foomatic-rip/postscript.c
filter/foomatic-rip/postscript.h
filter/foomatic-rip/process.c
filter/foomatic-rip/process.h
filter/foomatic-rip/renderer.c
filter/foomatic-rip/renderer.h
filter/foomatic-rip/spooler.c
filter/foomatic-rip/spooler.h
filter/foomatic-rip/util.c
filter/foomatic-rip/util.h

index 8fcb716cede8f90e6687d108ccb4dee0d791916e..5fade51da8f3ebe29a4ca446ded653153af89661 100644 (file)
@@ -1,25 +1,26 @@
-/* foomaticrip.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// foomaticrip.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "foomaticrip.h"
 #include "util.h"
 #include <cupsfilters/colormanager.h>
 #include <cupsfilters/filter.h>
 
-/* Logging */
+
+// Logging
 FILE* logh = NULL;
 
-void _logv(const char *msg, va_list ap)
+
+void
+_logv(const char *msg,
+      va_list ap)
 {
-    if (!logh)
-        return;
-    vfprintf(logh, msg, ap);
-    fflush(logh);
+  if (!logh)
+    return;
+  vfprintf(logh, msg, ap);
+  fflush(logh);
 }
 
-void _log(const char* msg, ...)
+
+void
+_log(const char* msg,
+     ...)
 {
-    va_list ap;
-    va_start(ap, msg);
-    _logv(msg, ap);
-    va_end(ap);
+  va_list ap;
+  va_start(ap, msg);
+  _logv(msg, ap);
+  va_end(ap);
 }
 
-void close_log()
+
+void
+close_log()
 {
-    if (logh && logh != stderr)
-        fclose(logh);
+  if (logh && logh != stderr)
+    fclose(logh);
 }
 
-int redirect_log_to_stderr()
+
+int
+redirect_log_to_stderr()
 {
-    if (dup2(fileno(logh), fileno(stderr)) < 0) {
-        _log("Could not dup logh to stderr\n");
-        return 0;
-    }
-    return 1;
+  if (dup2(fileno(logh), fileno(stderr)) < 0)
+  {
+    _log("Could not dup logh to stderr\n");
+    return (0);
+  }
+  return (1);
 }
 
-void rip_die(int status, const char *msg, ...)
+
+void
+rip_die(int status,
+       const char *msg,
+       ...)
 {
-    va_list ap;
+  va_list ap;
 
-    _log("Process is dying with \"");
-    va_start(ap, msg);
-    _logv(msg, ap);
-    va_end(ap);
-    _log("\", exit stat %d\n", status);
+  _log("Process is dying with \"");
+  va_start(ap, msg);
+  _logv(msg, ap);
+  va_end(ap);
+  _log("\", exit stat %d\n", status);
 
-    _log("Cleaning up...\n");
-    kill_all_processes();
+  _log("Cleaning up...\n");
+  kill_all_processes();
 
-    exit(status);
+  exit(status);
 }
 
 
-jobparams_t  *job = NULL;
+jobparams_t *job = NULL;
+
 
-jobparams_t * get_current_job()
+jobparams_t *
+get_current_job()
 {
-    return job;
+  return (job);
 }
 
 
-dstr_t *postpipe = NULL;  /* command into which the output of this filter should be piped */
+dstr_t *postpipe = NULL;  // command into which the output of this filter
+                          // should be piped
 FILE *postpipe_fh = NULL;
 
-FILE * open_postpipe()
+
+FILE *
+open_postpipe()
 {
-    const char *p;
+  const char *p;
 
-    if (postpipe_fh)
-        return postpipe_fh;
+  if (postpipe_fh)
+    return (postpipe_fh);
 
-    if (isempty(postpipe->data))
-        return stdout;
+  if (isempty(postpipe->data))
+    return (stdout);
 
-    /* Delete possible '|' symbol in the beginning */
-    p = skip_whitespace(postpipe->data);
-    if (*p && *p == '|')
-        p += 1;
+  // Delete possible '|' symbol in the beginning
+  p = skip_whitespace(postpipe->data);
+  if (*p && *p == '|')
+    p += 1;
 
-    if (start_system_process("postpipe", p, &postpipe_fh, NULL) < 0)
-        rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
-                "Cannot execute postpipe %s\n", postpipe->data);
+  if (start_system_process("postpipe", p, &postpipe_fh, NULL) < 0)
+    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
+           "Cannot execute postpipe %s\n", postpipe->data);
 
-    return postpipe_fh;
+  return (postpipe_fh);
 }
 
 
@@ -139,38 +161,38 @@ int dontparse = 0;
 int jobhasjcl;
 int pdfconvertedtops;
 
-/* Streaming mode: Assume PostScript input, no zero-page job check */
+// Streaming mode: Assume PostScript input, no zero-page job check
 int streaming = 0;
 
-/* cm-calibration flag */
+// cm-calibration flag
 int cm_calibrate = 0;
 
 int cm_disabled = 0;
 
-/* These variables were in 'dat' before */
+// These variables were in 'dat' before
 char colorprofile [128];
 char cupsfilter[256];
 char **jclprepend = NULL;
 dstr_t *jclappend;
 
-/* Set debug to 1 to enable the debug logfile for this filter; it will
- * appear as defined by LOG_FILE. It will contain status from this
- * filter, plus the renderer's stderr output. You can also add a line
- * "debug: 1" to your /etc/cups/foomatic-rip.conf or
- * /etc/foomatic/filter.conf to get all your Foomatic filters into
- * debug mode.  WARNING: This logfile is a security hole; do not use
- * in production. */
+// Set debug to 1 to enable the debug logfile for this filter; it will
+// appear as defined by LOG_FILE. It will contain status from this
+// filter, plus the renderer's stderr output. You can also add a line
+// "debug: 1" to your /etc/cups/foomatic-rip.conf or
+// /etc/foomatic/filter.conf to get all your Foomatic filters into
+// debug mode.  WARNING: This logfile is a security hole; do not use
+// in production.
 int debug = 0;
 
-/* Path to the GhostScript which foomatic-rip shall use */
+// Path to the GhostScript which foomatic-rip shall use
 char gspath[PATH_MAX] = "gs";
 
-/* What 'echo' program to use.  It needs -e and -n.  Linux's builtin
-and regular echo work fine; non-GNU platforms may need to install
-gnu echo and put gecho here or something. */
+// What 'echo' program to use. It needs -e and -n. Linux's builtin
+// and regular echo work fine; non-GNU platforms may need to install
+// gnu echo and put gecho here or something.
 char echopath[PATH_MAX] = "echo";
 
-/* CUPS raster drivers are searched here */
+// CUPS raster drivers are searched here
 char cupsfilterpath[PATH_MAX] = "/usr/local/lib/cups/filter:"
                                 "/usr/local/libexec/cups/filter:"
                                 "/opt/cups/filter:"
@@ -178,1001 +200,1118 @@ char cupsfilterpath[PATH_MAX] = "/usr/local/lib/cups/filter:"
 
 char modern_shell[] = SHELL;
 
-void config_set_option(const char *key, const char *value)
-{
-    if (strcmp(key, "debug") == 0)
-        debug = atoi(value);
-
-    /* What path to use for filter programs and such
-     *
-     * Your printer driver must be in the path, as must be the renderer,
-     * and possibly other stuff. The default path is often fine on Linux,
-     * but may not be on other systems. */
-    else if (strcmp(key, "execpath") == 0 && !isempty(value))
-        setenv("PATH", value, 1);
-
-    else if (strcmp(key, "cupsfilterpath") == 0)
-        strlcpy(cupsfilterpath, value, PATH_MAX);
-    else if (strcmp(key, "preferred_shell") == 0)
-        strlcpy(modern_shell, value, 32);
-    else if (strcmp(key, "gspath") == 0)
-        strlcpy(gspath, value, PATH_MAX);
-    else if (strcmp(key, "echo") == 0)
-        strlcpy(echopath, value, PATH_MAX);
-}
 
-int config_from_file(const char *filename)
+void
+config_set_option(const char *key,
+                 const char *value)
 {
-    FILE *fh;
-    char line[256];
-    char *key, *value;
+  if (strcmp(key, "debug") == 0)
+    debug = atoi(value);
+
+  // What path to use for filter programs and such
+  //
+  // Your printer driver must be in the path, as must be the renderer,
+  // and possibly other stuff. The default path is often fine on Linux,
+  // but may not be on other systems.
+  else if (strcmp(key, "execpath") == 0 && !isempty(value))
+    setenv("PATH", value, 1);
+  else if (strcmp(key, "cupsfilterpath") == 0)
+    strlcpy(cupsfilterpath, value, PATH_MAX);
+  else if (strcmp(key, "preferred_shell") == 0)
+    strlcpy(modern_shell, value, 32);
+  else if (strcmp(key, "gspath") == 0)
+    strlcpy(gspath, value, PATH_MAX);
+  else if (strcmp(key, "echo") == 0)
+    strlcpy(echopath, value, PATH_MAX);
+}
 
-    fh = fopen(filename, "r");
-    if (fh == NULL)
-        return 0;
 
-    while (fgets(line, 256, fh) != NULL)
-    {
-        key = strtok(line, " :\t\r\n");
-        if (key == NULL || key[0] == '#')
-            continue;
-        value = strtok(NULL, " \t\r\n#");
-        config_set_option(key, value);
-    }
-    fclose(fh);
-
-    return 1;
+int
+config_from_file(const char *filename)
+{
+  FILE *fh;
+  char line[256];
+  char *key, *value;
+
+  fh = fopen(filename, "r");
+  if (fh == NULL)
+    return 0;
+
+  while (fgets(line, 256, fh) != NULL)
+  {
+    key = strtok(line, " :\t\r\n");
+    if (key == NULL || key[0] == '#')
+      continue;
+    value = strtok(NULL, " \t\r\n#");
+    config_set_option(key, value);
+  }
+  fclose(fh);
+
+  return (1);
 }
 
-const char * get_modern_shell()
+
+const char *
+get_modern_shell()
 {
-    return modern_shell;
+  return (modern_shell);
 }
 
-/* returns position in 'str' after the option */
-char * extract_next_option(char *str, char **pagerange, char **key, char **value)
-{
-    char *p = str;
-    char quotechar;
 
-    *pagerange = NULL;
-    *key = NULL;
-    *value = NULL;
+// returns position in 'str' after the option
+char *
+extract_next_option(char *str,
+                   char **pagerange,
+                   char **key,
+                   char **value)
+{
+  char *p = str;
+  char quotechar;
+
+  *pagerange = NULL;
+  *key = NULL;
+  *value = NULL;
+
+  if (!str)
+    return (NULL);
+
+  // skip whitespace
+  while (*p && isspace(*p))
+    p ++;
+
+  if (!*p)
+    return (NULL);
+
+  // read the pagerange if we have one
+  if (prefixcmp(p, "even:") == 0 || prefixcmp(p, "odd:") == 0 || isdigit(*p))
+  {
+    *pagerange = p;
+    p = strchr(p, ':');
+    if (!p)
+      return (NULL);
+    *p = '\0';
+    p++;
+  }
+
+  // read the key
+  if (*p == '\'' || *p == '\"')
+  {
+    quotechar = *p;
+    *key = p +1;
+    p = strchr(*key, quotechar);
+    if (!p)
+      return (NULL);
+  }
+  else
+  {
+    *key = p;
+    while (*p && *p != ':' && *p != '=' && !isspace(*p))
+      p ++;
+  }
+
+  if (*p != ':' && *p != '=')
+  { // no value for this option
+    if (!*p)
+      return NULL;
+    else if (isspace(*p)) {
+      *p = '\0';
+      return p +1;
+    }
+    return p;
+  }
+
+  *p++ = '\0'; // remove the separator char
+
+  if (*p == '\"' || *p == '\'')
+  {
+    quotechar = *p;
+    *value = p +1;
+    p = strchr(*value, quotechar);
+    if (!p)
+      return (NULL);
+    *p = '\0';
+    p++;
+  }
+  else
+  {
+    *value = p;
+    while (*p && !isspace(*p))
+      p ++;
+    if (*p == '\0')
+      return (NULL);
+    *p = '\0';
+    p++;
+  }
+
+  return *p ? p : NULL;
+}
 
-    if (!str)
-        return NULL;
 
-    /* skip whitespace */
-    while (*p && isspace(*p)) p++;
+// processes job->optstr
+void
+process_cmdline_options()
+{
+  char *p, *cmdlineopts, *nextopt, *pagerange, *key, *value;
+  option_t *opt, *opt2;
+  int optset;
+  char tmp [256];
+
+  _log("Printing system options:\n");
+  cmdlineopts = strdup(job->optstr->data);
+  for (nextopt = extract_next_option(cmdlineopts, &pagerange, &key, &value);
+       key;
+       nextopt = extract_next_option(nextopt, &pagerange, &key, &value))
+  {
+    // Consider only options which are not in the PPD file here
+    if ((opt = find_option(key)) != NULL)
+      continue;
+    if (value)
+      _log("Pondering option '%s=%s'\n", key, value);
+    else
+      _log("Pondering option '%s'\n", key);
 
-    if (!*p)
-        return NULL;
-
-    /* read the pagerange if we have one */
-    if (prefixcmp(p, "even:") == 0 || prefixcmp(p, "odd:") == 0 || isdigit(*p)) {
-        *pagerange = p;
-        p = strchr(p, ':');
-        if (!p)
-            return NULL;
-        *p = '\0';
-        p++;
+    // "profile" option to supply a color correction profile to a CUPS raster
+    // driver
+    if (!strcmp(key, "profile"))
+    {
+      strlcpy(colorprofile, value, 128);
+      continue;
     }
-
-    /* read the key */
-    if (*p == '\'' || *p == '\"') {
-        quotechar = *p;
-        *key = p +1;
-        p = strchr(*key, quotechar);
-        if (!p)
-            return NULL;
+    // option to set color calibration mode
+    if (!strcmp(key, "cm-calibration"))
+    {
+      cm_calibrate = 1;
+      continue;
     }
-    else {
-        *key = p;
-        while (*p && *p != ':' && *p != '=' && !isspace(*p)) p++;
+    // option to set color calibration mode
+    if (!strcmp(key, "filter-streaming-mode") &&
+       (!value ||
+        (strcasecmp(value, "false") && strcasecmp(value, "off") &&
+         strcasecmp(value, "no"))))
+    {
+      streaming = 1;
+      continue;
     }
+    // Solaris options that have no reason to be
+    if (!strcmp(key, "nobanner") || !strcmp(key, "dest") ||
+       !strcmp(key, "protocol"))
+      continue;
 
-    if (*p != ':' && *p != '=') { /* no value for this option */
-        if (!*p)
-            return NULL;
-        else if (isspace(*p)) {
-            *p = '\0';
-            return p +1;
-        }
-        return p;
+    if (pagerange)
+    {
+      snprintf(tmp, 256, "pages:%s", pagerange);
+      optset = optionset(tmp);
     }
+    else
+      optset = optionset("userval");
 
-    *p++ = '\0'; /* remove the separator sign */
-
-    if (*p == '\"' || *p == '\'') {
-        quotechar = *p;
-        *value = p +1;
-        p = strchr(*value, quotechar);
-        if (!p)
-            return NULL;
-        *p = '\0';
-        p++;
-    }
-    else {
-        *value = p;
-        while (*p && !isspace(*p)) p++;
-        if (*p == '\0')
-            return NULL;
-        *p = '\0';
-        p++;
-    }
+    if (value)
+    {
+      if (strcasecmp(key, "media") == 0)
+      {
+       // Standard arguments?
+       // media=x,y,z
+       // sides=one|two-sided-long|short-edge
+       //
+       // Rummage around in the media= option for known media, source,
+       // etc types.
+       // We ought to do something sensible to make the common manual
+       // boolean option work when specified as a media= tray thing.
+       //
+       // Note that this fails miserably when the option value is in
+       // fact a number; they all look alike.  It's unclear how many
+       // drivers do that.  We may have to standardize the verbose
+       // names to make them work as selections, too.
+
+       if (value[0] == '\0')
+         continue;
+       p = strtok(value, ",");
+       do
+       {
+         if ((opt = find_option("PageSize")) && option_accepts_value(opt, p))
+           option_set_value(opt, optset, p);
+         else if ((opt = find_option("MediaType")) &&
+                  option_has_choice(opt, p))
+           option_set_value(opt, optset, p);
+         else if ((opt = find_option("InputSlot")) &&
+                  option_has_choice(opt, p))
+           option_set_value(opt, optset, p);
+         else if (!strcasecmp(p, "manualfeed"))
+         {
+           // Special case for our typical boolean manual
+           // feeder option if we didn't match an InputSlot above
+           if ((opt = find_option("ManualFeed")))
+             option_set_value(opt, optset, "1");
+         }
+         else
+           _log("Unknown \"media\" component: \"%s\".\n", p);
 
-    return *p ? p : NULL;
-}
+       }
+       while ((p = strtok(NULL, ",")));
+      }
+      else if (!strcasecmp(key, "sides"))
+      {
+       // Handle the standard duplex option, mostly
+       if (!prefixcasecmp(value, "two-sided"))
+       {
+         if ((opt = find_option("Duplex")))
+         {
+           // Default to long-edge binding here, for the case that
+           // there is no binding setting
+           option_set_value(opt, optset, "DuplexNoTumble");
+
+           // Check the binding: "long edge" or "short edge"
+           if (strcasestr(value, "long-edge"))
+           {
+             if ((opt2 = find_option("Binding")))
+               option_set_value(opt2, optset, "LongEdge");
+             else
+               option_set_value(opt, optset, "DuplexNoTumble");
+           }
+           else if (strcasestr(value, "short-edge"))
+           {
+             if ((opt2 = find_option("Binding")))
+               option_set_value(opt2, optset, "ShortEdge");
+             else
+               option_set_value(opt, optset, "DuplexTumble");
+           }
+         }
+       }
+       else if (!prefixcasecmp(value, "one-sided"))
+       {
+         if ((opt = find_option("Duplex")))
+           option_set_value(opt, optset, "0");
+       }
 
-/* processes job->optstr */
-void process_cmdline_options()
-{
-    char *p, *cmdlineopts, *nextopt, *pagerange, *key, *value;
-    option_t *opt, *opt2;
-    int optset;
-    char tmp [256];
-
-    _log("Printing system options:\n");
-    cmdlineopts = strdup(job->optstr->data);
-    for (nextopt = extract_next_option(cmdlineopts, &pagerange, &key, &value);
-        key;
-        nextopt = extract_next_option(nextopt, &pagerange, &key, &value))
+       // TODO
+       // We should handle the other half of this option - the
+       // BindEdge bit.  Also, are there well-known ipp/cups options
+       // for Collate and StapleLocation?  These may be here...
+      }
+      else
+       _log("Unknown option %s=%s.\n", key, value);
+    }
+    // Custom paper size
+    else if ((opt = find_option("PageSize")) &&
+            option_set_value(opt, optset, key))
     {
-        /* Consider only options which are not in the PPD file here */
-        if ((opt = find_option(key)) != NULL) continue;
-        if (value)
-            _log("Pondering option '%s=%s'\n", key, value);
-        else
-            _log("Pondering option '%s'\n", key);
-
-        /* "profile" option to supply a color correction profile to a CUPS raster driver */
-        if (!strcmp(key, "profile")) {
-            strlcpy(colorprofile, value, 128);
-            continue;
-        }
-        /* option to set color calibration mode */
-        if (!strcmp(key, "cm-calibration")) {
-            cm_calibrate = 1;
-            continue;
-        }
-        /* option to set color calibration mode */
-        if (!strcmp(key, "filter-streaming-mode") &&
-           (!value ||
-            (strcasecmp(value, "false") && strcasecmp(value, "off") &&
-             strcasecmp(value, "no")))) {
-            streaming = 1;
-            continue;
-        }
-        /* Solaris options that have no reason to be */
-        if (!strcmp(key, "nobanner") || !strcmp(key, "dest") || !strcmp(key, "protocol"))
-            continue;
-
-        if (pagerange) {
-            snprintf(tmp, 256, "pages:%s", pagerange);
-            optset = optionset(tmp);
-        }
-        else
-            optset = optionset("userval");
-
-        if (value) {
-            if (strcasecmp(key, "media") == 0) {
-                /*  Standard arguments?
-                    media=x,y,z
-                    sides=one|two-sided-long|short-edge
-
-                    Rummage around in the media= option for known media, source,
-                    etc types.
-                    We ought to do something sensible to make the common manual
-                    boolean option work when specified as a media= tray thing.
-
-                    Note that this fails miserably when the option value is in
-                    fact a number; they all look alike.  It's unclear how many
-                    drivers do that.  We may have to standardize the verbose
-                    names to make them work as selections, too. */
-
-               if (value[0] == '\0')
-                   continue;
-                p = strtok(value, ",");
-                do {
-                    if ((opt = find_option("PageSize")) && option_accepts_value(opt, p))
-                        option_set_value(opt, optset, p);
-                    else if ((opt = find_option("MediaType")) && option_has_choice(opt, p))
-                        option_set_value(opt, optset, p);
-                    else if ((opt = find_option("InputSlot")) && option_has_choice(opt, p))
-                        option_set_value(opt, optset, p);
-                    else if (!strcasecmp(p, "manualfeed")) {
-                        /* Special case for our typical boolean manual
-                           feeder option if we didn't match an InputSlot above */
-                        if ((opt = find_option("ManualFeed")))
-                            option_set_value(opt, optset, "1");
-                    }
-                    else
-                        _log("Unknown \"media\" component: \"%s\".\n", p);
-
-                } while ((p = strtok(NULL, ",")));
-            }
-            else if (!strcasecmp(key, "sides")) {
-                /* Handle the standard duplex option, mostly */
-                if (!prefixcasecmp(value, "two-sided")) {
-                    if ((opt = find_option("Duplex"))) {
-                        /* Default to long-edge binding here, for the case that
-                           there is no binding setting */
-                        option_set_value(opt, optset, "DuplexNoTumble");
-
-                        /* Check the binding: "long edge" or "short edge" */
-                        if (strcasestr(value, "long-edge")) {
-                            if ((opt2 = find_option("Binding")))
-                                option_set_value(opt2, optset, "LongEdge");
-                            else
-                                option_set_value(opt, optset, "DuplexNoTumble");
-                        }
-                        else if (strcasestr(value, "short-edge")) {
-                            if ((opt2 = find_option("Binding")))
-                                option_set_value(opt2, optset, "ShortEdge");
-                            else
-                                option_set_value(opt, optset, "DuplexTumble");
-                        }
-                    }
-                }
-                else if (!prefixcasecmp(value, "one-sided")) {
-                    if ((opt = find_option("Duplex")))
-                        option_set_value(opt, optset, "0");
-                }
-
-                /*  TODO
-                    We should handle the other half of this option - the
-                    BindEdge bit.  Also, are there well-known ipp/cups options
-                    for Collate and StapleLocation?  These may be here...
-                */
-            }
-           else
-               _log("Unknown option %s=%s.\n", key, value);
-        }
-        /* Custom paper size */
-        else if ((opt = find_option("PageSize")) && option_set_value(opt, optset, key)) {
-            /* do nothing, if the value could be set, it has been set */
-        }
-        else
-            _log("Unknown boolean option \"%s\".\n", key);
+      // do nothing, if the value could be set, it has been set
     }
-    free(cmdlineopts);
+    else
+      _log("Unknown boolean option \"%s\".\n", key);
+  }
+  free(cmdlineopts);
+
+  // We 'clear' the profile if cm-calibration mode was specified
+  if (cm_calibrate)
+  {
+    colorprofile[0] = '\0';
+    cm_disabled = 1;
+  }
+
+  _log("Streaming Mode: %s\n", streaming ? "Activated" : "Off");
+  _log("CM Color Calibration Mode in CUPS: %s\n", cm_calibrate ? 
+       "Activated" : "Off");
+
+  _log("Options from the PPD file:\n");
+  cmdlineopts = strdup(job->optstr->data);
+  for (nextopt = extract_next_option(cmdlineopts, &pagerange, &key, &value);
+       key;
+       nextopt = extract_next_option(nextopt, &pagerange, &key, &value))
+  {
+    // Consider only PPD file options here
+    if ((opt = find_option(key)) == NULL) continue; 
+    if (value)
+      _log("Pondering option '%s=%s'\n", key, value);
+    else
+      _log("Pondering option '%s'\n", key);
 
-    /* We 'clear' the profile if cm-calibration mode was specified */
-    if (cm_calibrate) {
-        colorprofile[0] = '\0';
-        cm_disabled = 1;
+    if (pagerange)
+    {
+      snprintf(tmp, 256, "pages:%s", pagerange);
+      optset = optionset(tmp);
+
+      if (opt && (option_get_section(opt) != SECTION_ANYSETUP &&
+                 option_get_section(opt) != SECTION_PAGESETUP))
+      {
+       _log("This option (%s) is not a \"PageSetup\" or \"AnySetup\" option, so it cannot be restricted to a page range.\n", key);
+       continue;
+      }
     }
+    else
+      optset = optionset("userval");
 
-    _log("Streaming Mode: %s\n", streaming ? "Activated" : "Off");
-    _log("CM Color Calibration Mode in CUPS: %s\n", cm_calibrate ? 
-         "Activated" : "Off");
-
-    _log("Options from the PPD file:\n");
-    cmdlineopts = strdup(job->optstr->data);
-    for (nextopt = extract_next_option(cmdlineopts, &pagerange, &key, &value);
-        key;
-        nextopt = extract_next_option(nextopt, &pagerange, &key, &value))
+    if (value)
     {
-        /* Consider only PPD file options here */
-        if ((opt = find_option(key)) == NULL) continue; 
-        if (value)
-            _log("Pondering option '%s=%s'\n", key, value);
-        else
-            _log("Pondering option '%s'\n", key);
-
-        if (pagerange) {
-            snprintf(tmp, 256, "pages:%s", pagerange);
-            optset = optionset(tmp);
-
-            if (opt && (option_get_section(opt) != SECTION_ANYSETUP &&
-                        option_get_section(opt) != SECTION_PAGESETUP)) {
-                _log("This option (%s) is not a \"PageSetup\" or \"AnySetup\" option, so it cannot be restricted to a page range.\n", key);
-                continue;
-            }
-        }
-        else
-            optset = optionset("userval");
-
-        if (value) {
-           /* Various non-standard printer-specific options */
-           if (!option_set_value(opt, optset, value)) {
-               _log("  invalid choice \"%s\", using \"%s\" instead\n", 
-                    value, option_get_value(opt, optset));
-           }
-        }
-        /* Standard bool args:
-           landscape; what to do here?
-           duplex; we should just handle this one OK now? */
-        else if (!prefixcasecmp(key, "no"))
-            option_set_value(opt, optset, "0");
-        else
-            option_set_value(opt, optset, "1");
+      // Various non-standard printer-specific options
+      if (!option_set_value(opt, optset, value)) {
+       _log("  invalid choice \"%s\", using \"%s\" instead\n", 
+            value, option_get_value(opt, optset));
+      }
     }
-    free(cmdlineopts);
+    // Standard bool args:
+    // landscape; what to do here?
+    // duplex; we should just handle this one OK now?
+    else if (!prefixcasecmp(key, "no"))
+      option_set_value(opt, optset, "0");
+    else
+      option_set_value(opt, optset, "1");
+  }
+  free(cmdlineopts);
 }
 
-/*  Functions to let foomatic-rip fork to do several tasks in parallel.
-
-To do the filtering without loading the whole file into memory we work
-on a data stream, we read the data line by line analyse it to decide what
-filters to use and start the filters if we have found out which we need.
-We buffer the data only as long as we didn't determing which filters to
-use for this piece of data and with which options. There are no temporary
-files used.
 
-foomatic-rip splits into up to 3 parallel processes to do the whole
-filtering (listed in the order of the data flow):
+//
+// Functions to let foomatic-rip fork to do several tasks in parallel.
+//
+// To do the filtering without loading the whole file into memory we work
+// on a data stream, we read the data line by line analyse it to decide what
+// filters to use and start the filters if we have found out which we need.
+// We buffer the data only as long as we didn't determing which filters to
+// use for this piece of data and with which options. There are no temporary
+// files used.
+//
+// foomatic-rip splits into up to 3 parallel processes to do the whole
+// filtering (listed in the order of the data flow):
+//
+//    MAIN: Prepare the job auto-detecting the spooler, reading the PPD,
+//          extracting the options from the command line, and parsing
+//          the job data itself. It analyses the job data to check
+//          whether it is PostScript or PDF, it also stuffs PostScript
+//          code from option settings into the PostScript data stream.
+//          It starts the renderer (KID3/KID4) as soon as it knows its
+//          command line and restarts it when page-specific option
+//          settings need another command line or different JCL commands.
+//    KID3: The rendering process. In most cases Ghostscript, "cat"
+//          for native PostScript printers with their manufacturer's
+//          PPD files.
+//    KID4: Put together the JCL commands and the renderer's output
+//          and send all that either to STDOUT or pipe it into the
+//          command line defined with $postpipe.
+//
+
+
+void
+write_output(void *data,
+            size_t len)
+{
+  const char *p = (const char *)data;
+  size_t left = len;
+  FILE *postpipe = open_postpipe();
 
-   MAIN: Prepare the job auto-detecting the spooler, reading the PPD,
-         extracting the options from the command line, and parsing
-         the job data itself. It analyses the job data to check
-         whether it is PostScript or PDF, it also stuffs PostScript
-         code from option settings into the PostScript data stream.
-         It starts the renderer (KID3/KID4) as soon as it knows its
-         command line and restarts it when page-specific option
-         settings need another command line or different JCL commands.
-   KID3: The rendering process. In most cases Ghostscript, "cat"
-         for native PostScript printers with their manufacturer's
-         PPD files.
-   KID4: Put together the JCL commands and the renderer's output
-         and send all that either to STDOUT or pipe it into the
-         command line defined with $postpipe. */
+  // Remove leading whitespace
+  while (isspace(*p++) && left-- > 0);
 
+  fwrite_or_die((void *)p, left, 1, postpipe);
+  fflush(postpipe);
+}
 
 
-void write_output(void *data, size_t len)
+enum FileType
 {
-    const char *p = (const char *)data;
-    size_t left = len;
-    FILE *postpipe = open_postpipe();
+  UNKNOWN_FILE,
+  PDF_FILE,
+  PS_FILE
+};
 
-    /* Remove leading whitespace */
-    while (isspace(*p++) && left-- > 0)
-        ;
 
-    fwrite_or_die((void *)p, left, 1, postpipe);
-    fflush(postpipe);
+int
+guess_file_type(const char *begin,
+               size_t len,
+               int *startpos)
+{
+  const char *p, *end;
+
+  p = begin;
+  end = begin + len;
+
+  while (p < end)
+  {
+    p = memchr(p, '%', end - p);
+    if (!p)
+      return UNKNOWN_FILE;
+    *startpos = p - begin;
+    if ((end - p) >= 2 && !memcmp(p, "%!", 2))
+      return PS_FILE;
+    else if ((end - p) > 7 && !memcmp(p, "%PDF-1.", 7))
+      return PDF_FILE;
+    ++ p;
+  }
+  *startpos = 0;
+  return UNKNOWN_FILE;
 }
 
-enum FileType {
-    UNKNOWN_FILE,
-    PDF_FILE,
-    PS_FILE
-};
 
-int guess_file_type(const char *begin, size_t len, int *startpos)
-{
-    const char * p, * end;
-    p = begin;
-    end = begin + len;
+//
+// Prints 'filename'. If 'convert' is true, the file will be converted if it is
+// not Postscript or PDF
+//
 
-    while (p < end)
+int
+print_file(const char *filename,
+          int convert)
+{
+  FILE *file;
+  char buf[8192];
+  char tmpfilename[PATH_MAX] = "";
+  int type;
+  int startpos;
+  size_t n;
+  int ret;
+
+  if (!strcasecmp(filename, "<STDIN>"))
+    file = stdin;
+  else
+  {
+    file = fopen(filename, "r");
+    if (!file)
     {
-        p = memchr(p, '%', end - p);
-       if (!p)
-           return UNKNOWN_FILE;
-       *startpos = p - begin;
-       if ((end - p) >= 2 && !memcmp(p, "%!", 2))
-           return PS_FILE;
-       else if ((end - p) > 7 && !memcmp(p, "%PDF-1.", 7))
-           return PDF_FILE;
-       ++ p;
+      _log("Could not open \"%s\" for reading\n", filename);
+      return (0);
     }
-    *startpos = 0;
-    return UNKNOWN_FILE;
-}
-
-/*
- * Prints 'filename'. If 'convert' is true, the file will be converted if it is
- * not postscript or pdf
- */
-int print_file(const char *filename, int convert)
-{
-    FILE *file;
-    char buf[8192];
-    char tmpfilename[PATH_MAX] = "";
-    int type;
-    int startpos;
-    size_t n;
-    int ret;
-
-    if (!strcasecmp(filename, "<STDIN>"))
-        file = stdin;
-    else {
-        file = fopen(filename, "r");
-        if (!file) {
-            _log("Could not open \"%s\" for reading\n", filename);
-            return 0;
-        }
+  }
+
+  if (streaming == 0 || file != stdin)
+  {
+    n = fread_or_die(buf, 1, sizeof(buf) - 1, file);
+    if (!n) {
+      _log("Input is empty, outputting empty file.\n");
+      return (1);
     }
+    buf[n] = '\0';
+    type = guess_file_type(buf, n, &startpos);
+    // We do not use any JCL preceeded to the input data, as it is simply
+    // the PJL commands from the PPD file, and these commands we can also
+    // generate, end we even merge them with PJl from the driver
+    //if (startpos > 0)
+    //{
+    //  jobhasjcl = 1;
+    //  write_output(buf, startpos);
+    //}
+    if (file != stdin)
+      rewind(file);
+
+    if (convert) pdfconvertedtops = 0;
+  }
+  else
+  {
+    n = 0;
+    buf[0] = '\n';
+    type = PS_FILE;
+  }
+
+  switch (type)
+  {
+    case PDF_FILE:
+        _log("Filetype: PDF\n");
+
+       if (!ppd_supports_pdf())
+       {
+         char pdf2ps_cmd[CMDLINE_MAX];
+         FILE *out, *in;
+         int renderer_pid;
+
+         _log("Driver does not understand PDF input, "
+              "converting to PostScript\n");
+
+         pdfconvertedtops = 1;
+
+         // If reading from stdin, write everything into a temporary file
+         if (file == stdin)
+         {
+           int fd;
+           FILE *tmpfile;
+
+           snprintf(tmpfilename, PATH_MAX, "%s/foomatic-XXXXXX", temp_dir());
+           fd = mkstemp(tmpfilename);
+           if (fd < 0)
+           {
+             _log("Could not create temporary file: %s\n", strerror(errno));
+             return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+           }
+           tmpfile = fdopen(fd, "r+");
+           copy_file(tmpfile, stdin, buf, n);
+           fclose(tmpfile);
+
+           filename = tmpfilename;
+         }
+
+         // If the spooler is CUPS we use the pdftops filter of CUPS,
+         // to have always the same PDF->PostScript conversion method
+         // in the whole printing environment, including incompatibility
+         // workarounds in the CUPS filter (so this way we also have to
+         // maintain all these quirks only once).
+         //
+         // The "-dNOINTERPOLATE" makes Ghostscript rendering
+         // significantly faster.
+         //
+         // The "-dNOMEDIAATTRS" makes Ghostscript not checking the
+         // page sizes against a list of known sizes and try to
+         // correct them.
+         //
+         // Note that Ghostscript's "pswrite" output device turns text
+         // into bitmaps and therefore produces huge PostScript files.
+         // In addition, this output device is deprecated. Therefore
+         // we use "ps2write".
+         //
+         // We give priority to Ghostscript here and use Poppler if
+         // Ghostscript is not available.
+         if (spooler == SPOOLER_CUPS)
+           snprintf(pdf2ps_cmd, CMDLINE_MAX,
+                    "pdftops '%s' '%s' '%s' '%s' '%s' '%s'",
+                    job->id, job->user, job->title, "1", job->optstr->data,
+                    filename);
+         else
+           snprintf(pdf2ps_cmd, CMDLINE_MAX,
+                    "gs -q -sstdout=%%stderr -sDEVICE=ps2write -sOutputFile=- "
+                    "-dBATCH -dNOPAUSE -dSAFER -dNOINTERPOLATE -dNOMEDIAATTRS -dShowAcroForm %s 2>/dev/null || "
+                    "pdftops -level2 -origpagesizes %s - 2>/dev/null",
+                    filename, filename);
+
+         renderer_pid = start_system_process("pdf-to-ps", pdf2ps_cmd, &in, &out);
+
+         if (dup2(fileno(out), fileno(stdin)) < 0)
+           rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
+                   "Couldn't dup stdout of pdf-to-ps\n");
+
+         clearerr(stdin);
+
+         ret = print_file("<STDIN>", 0);
+
+         wait_for_process(renderer_pid);
+         if (in != NULL)
+           fclose(in);
+         if (out != NULL)
+           fclose(out);
+
+         // Delete temp file if we created one
+         if ( *tmpfilename )
+           unlink(tmpfilename);
+
+         return ret;
+       }
 
-    if (streaming == 0 || file != stdin) {
-      n = fread_or_die(buf, 1, sizeof(buf) - 1, file);
-      if (!n) {
-       _log("Input is empty, outputting empty file.\n");
-       return 1;
-      }
-      buf[n] = '\0';
-      type = guess_file_type(buf, n, &startpos);
-      /* We do not use any JCL preceeded to the input data, as it is simply
-        the PJL commands from the PPD file, and these commands we can also
-        generate, end we even merge them with PJl from the driver */
-      /*if (startpos > 0) {
-        jobhasjcl = 1;
-        write_output(buf, startpos);
-       }*/
-      if (file != stdin)
-        rewind(file);
-
-      if (convert) pdfconvertedtops = 0;
-    } else {
-      n = 0;
-      buf[0] = '\n';
-      type = PS_FILE;
-    }
+       if (file == stdin)
+         return (print_pdf(stdin, buf, n, filename, startpos));
+       else
+         return (print_pdf(file, NULL, 0, filename, startpos));
 
-    switch (type) {
-        case PDF_FILE:
-            _log("Filetype: PDF\n");
-
-            if (!ppd_supports_pdf())
-            {
-                char pdf2ps_cmd[CMDLINE_MAX];
-                FILE *out, *in;
-                int renderer_pid;
-
-                _log("Driver does not understand PDF input, "
-                     "converting to PostScript\n");
-
-               pdfconvertedtops = 1;
-
-               /* If reading from stdin, write everything into a temporary file */
-               if (file == stdin)
-                {
-                   int fd;
-                   FILE *tmpfile;
-
-                   snprintf(tmpfilename, PATH_MAX, "%s/foomatic-XXXXXX", temp_dir());
-                   fd = mkstemp(tmpfilename);
-                   if (fd < 0) {
-                       _log("Could not create temporary file: %s\n", strerror(errno));
-                       return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-                   }
-                   tmpfile = fdopen(fd, "r+");
-                   copy_file(tmpfile, stdin, buf, n);
-                   fclose(tmpfile);
-
-                   filename = tmpfilename;
-               }
-
-               /* If the spooler is CUPS we use the pdftops filter of CUPS,
-                  to have always the same PDF->PostScript conversion method
-                  in the whole printing environment, including incompatibility
-                  workarounds in the CUPS filter (so this way we also have to
-                  maintain all these quirks only once).
-
-                  The "-dNOINTERPOLATE" makes Ghostscript rendering
-                  significantly faster.
-
-                  The "-dNOMEDIAATTRS" makes Ghostscript not checking the
-                  page sizes against a list of known sizes and try to
-                  correct them.
-
-                  Note that Ghostscript's "pswrite" output device turns text
-                  into bitmaps and therefore produces huge PostScript files.
-                  In addition, this output device is deprecated. Therefore
-                  we use "ps2write".
-
-                  We give priority to Ghostscript here and use Poppler if
-                  Ghostscript is not available. */
-               if (spooler == SPOOLER_CUPS)
-                 snprintf(pdf2ps_cmd, CMDLINE_MAX,
-                          "pdftops '%s' '%s' '%s' '%s' '%s' '%s'",
-                          job->id, job->user, job->title, "1", job->optstr->data,
-                          filename);
-               else
-                 snprintf(pdf2ps_cmd, CMDLINE_MAX,
-                          "gs -q -sstdout=%%stderr -sDEVICE=ps2write -sOutputFile=- "
-                          "-dBATCH -dNOPAUSE -dSAFER -dNOINTERPOLATE -dNOMEDIAATTRS -dShowAcroForm %s 2>/dev/null || "
-                          "pdftops -level2 -origpagesizes %s - 2>/dev/null",
-                          filename, filename);
-
-                renderer_pid = start_system_process("pdf-to-ps", pdf2ps_cmd, &in, &out);
-
-                if (dup2(fileno(out), fileno(stdin)) < 0)
-                    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
-                            "Couldn't dup stdout of pdf-to-ps\n");
-
-                clearerr(stdin);
-
-                ret = print_file("<STDIN>", 0);
-
-                wait_for_process(renderer_pid);
-                if (in != NULL)
-                  fclose(in);
-                if (out != NULL)
-                  fclose(out);
-
-                // Delete temp file if we created one
-                if ( *tmpfilename )
-                    unlink(tmpfilename);
-
-                return ret;
-            }
-
-            if (file == stdin)
-                return print_pdf(stdin, buf, n, filename, startpos);
-            else
-                return print_pdf(file, NULL, 0, filename, startpos);
-
-        case PS_FILE:
-            _log("Filetype: PostScript\n");
-            if (file == stdin)
-                return print_ps(stdin, buf, n, filename);
-            else
-                return print_ps(file, NULL, 0, filename);
-
-        case UNKNOWN_FILE:
-           _log("Cannot process \"%s\": Unknown filetype.\n", filename);
-           if (file != NULL)
-             fclose(file);
-           return 0;
-    }
+    case PS_FILE:
+        _log("Filetype: PostScript\n");
+       if (file == stdin)
+         return (print_ps(stdin, buf, n, filename));
+       else
+         return (print_ps(file, NULL, 0, filename));
 
-    fclose(file);
-    return 1;
-}
+    case UNKNOWN_FILE:
+        _log("Cannot process \"%s\": Unknown filetype.\n", filename);
+       if (file != NULL)
+         fclose(file);
+       return (0);
+  }
 
-void signal_terminate(int signal)
-{
-    rip_die(EXIT_PRINTED, "Caught termination signal: Job canceled\n");
+  fclose(file);
+  return (1);
 }
 
-jobparams_t * create_job()
-{
-    jobparams_t *job = calloc(1, sizeof(jobparams_t));
-    struct passwd *passwd;
-
-    job->optstr = create_dstr();
-    job->time = time(NULL);
-    strcpy(job->copies, "1");
-    gethostname(job->host, 128);
-    passwd = getpwuid(getuid());
-    if (passwd)
-        strlcpy(job->user, passwd->pw_name, 128);
-    snprintf(job->title, 2048, "%s@%s", job->user, job->host);
-
-    return job;
-}
 
-void free_job(jobparams_t *job)
+void
+signal_terminate(int signal)
 {
-    free_dstr(job->optstr);
-    free(job);
+  rip_die(EXIT_PRINTED, "Caught termination signal: Job canceled\n");
 }
 
-int main(int argc, char** argv)
-{
-    int i;
-    int verbose = 0, quiet = 0;
-    const char* str;
-    char *p, *filename;
-    const char *path;
-    char tmp[1024], profile_arg[256], gstoraster[512];
-    int havefilter, havegstoraster;
-    dstr_t *filelist;
-    list_t * arglist;
-    cf_filter_data_t temp;
-    cf_filter_data_t *data = &temp;
-    data->logdata = NULL;
-    data->logfunc = cfCUPSLogFunc;
-    arglist = list_create_from_array(argc -1, (void**)&argv[1]);
-
-    if (argc == 2 && (arglist_find(arglist, "--version") || arglist_find(arglist, "--help") ||
-                arglist_find(arglist, "-v") || arglist_find(arglist, "-h"))) {
-        printf("foomatic-rip of cups-filters version "VERSION"\n");
-        printf("\"man foomatic-rip\" for help.\n");
-        list_free(arglist);
-        return 0;
-    }
 
-    filelist = create_dstr();
-    job = create_job();
+jobparams_t *
+create_job()
+{
+  jobparams_t *job = calloc(1, sizeof(jobparams_t));
+  struct passwd *passwd;
+
+  job->optstr = create_dstr();
+  job->time = time(NULL);
+  strcpy(job->copies, "1");
+  gethostname(job->host, 128);
+  passwd = getpwuid(getuid());
+  if (passwd)
+    strlcpy(job->user, passwd->pw_name, 128);
+  snprintf(job->title, 2048, "%s@%s", job->user, job->host);
+
+  return (job);
+}
 
-    jclprepend = NULL;
-    jclappend = create_dstr();
-    postpipe = create_dstr();
 
-    options_init();
+void
+free_job(jobparams_t *job)
+{
+  free_dstr(job->optstr);
+  free(job);
+}
 
-    signal(SIGTERM, signal_terminate);
-    signal(SIGINT, signal_terminate);
-    signal(SIGPIPE, SIG_IGN);
 
-    /* First try to find a config file in the CUS config directory, like
-       /etc/cups/foomatic-rip.conf */
-    i = 0;
-    if ((str = getenv("CUPS_SERVERROOT")) != NULL) {
-       snprintf(tmp, sizeof(tmp), "%s/foomatic-rip.conf", str);
-       i = config_from_file(tmp);
-    }
-    /* If there is none, fall back to /etc/foomatic/filter.conf */
-    if (i == 0) 
-        i = config_from_file(CONFIG_PATH "/filter.conf");
-
-    /* Command line options for verbosity */
-    if (arglist_remove_flag(arglist, "-v"))
-        verbose = 1;
-    if (arglist_remove_flag(arglist, "-q"))
-        quiet = 1;
-    if (arglist_remove_flag(arglist, "--debug"))
-        debug = 1;
-
-    if (debug) {
+int
+main(int argc,
+     char** argv)
+{
+  int i;
+  int verbose = 0, quiet = 0;
+  const char* str;
+  char *p, *filename;
+  const char *path;
+  char tmp[1024], profile_arg[256], gstoraster[512];
+  int havefilter, havegstoraster;
+  dstr_t *filelist;
+  list_t * arglist;
+  cf_filter_data_t temp;
+  cf_filter_data_t *data = &temp;
+  data->logdata = NULL;
+  data->logfunc = cfCUPSLogFunc;
+  arglist = list_create_from_array(argc -1, (void**)&argv[1]);
+
+  if (argc == 2 && (arglist_find(arglist, "--version") ||
+                   arglist_find(arglist, "--help") ||
+                   arglist_find(arglist, "-v") ||
+                   arglist_find(arglist, "-h")))
+  {
+    printf("foomatic-rip of cups-filters version "VERSION"\n");
+    printf("\"man foomatic-rip\" for help.\n");
+    list_free(arglist);
+    return (0);
+  }
+
+  filelist = create_dstr();
+  job = create_job();
+
+  jclprepend = NULL;
+  jclappend = create_dstr();
+  postpipe = create_dstr();
+
+  options_init();
+
+  signal(SIGTERM, signal_terminate);
+  signal(SIGINT, signal_terminate);
+  signal(SIGPIPE, SIG_IGN);
+
+  // First try to find a config file in the CUPS config directory, like
+  // /etc/cups/foomatic-rip.conf
+  i = 0;
+  if ((str = getenv("CUPS_SERVERROOT")) != NULL)
+  {
+    snprintf(tmp, sizeof(tmp), "%s/foomatic-rip.conf", str);
+    i = config_from_file(tmp);
+  }
+  // If there is none, fall back to /etc/foomatic/filter.conf
+  if (i == 0) 
+    i = config_from_file(CONFIG_PATH "/filter.conf");
+
+  // Command line options for verbosity
+  if (arglist_remove_flag(arglist, "-v"))
+    verbose = 1;
+  if (arglist_remove_flag(arglist, "-q"))
+    quiet = 1;
+  if (arglist_remove_flag(arglist, "--debug"))
+    debug = 1;
+
+  if (debug)
+  {
 #if defined(__UCLIBC__) || defined(__NetBSD__)
-       sprintf(tmp, "%s-log-XXXXXX", LOG_FILE);
-       int fd = mkstemp (tmp);
+    sprintf(tmp, "%s-log-XXXXXX", LOG_FILE);
+    int fd = mkstemp (tmp);
 #else
-       sprintf(tmp, "%s-XXXXXX.log", LOG_FILE);
-       int fd = mkstemps (tmp, 4);
+    sprintf(tmp, "%s-XXXXXX.log", LOG_FILE);
+    int fd = mkstemps (tmp, 4);
 #endif
-       if (fd != -1)
-           logh = fdopen(fd, "w");
-       else
-           logh = stderr;
-    } else if (quiet && !verbose)
-        logh = NULL; /* Quiet mode, do not log */
+    if (fd != -1)
+      logh = fdopen(fd, "w");
     else
-        logh = stderr; /* Default: log to stderr */
-
-    /* Start debug logging */
-    if (debug) {
-        /* If we are not in debug mode, we do this later, as we must find out at
-        first which spooler is used. When printing without spooler we
-        suppress logging because foomatic-rip is called directly on the
-        command line and so we avoid logging onto the console. */
-        _log("foomatic-rip version "VERSION" running...\n");
-
-        /* Print the command line only in debug mode, Mac OS X adds very many
-        options so that CUPS cannot handle the output of the command line
-        in its log files. If CUPS encounters a line with more than 1024
-        characters sent into its log files, it aborts the job with an error. */
-        if (spooler != SPOOLER_CUPS) {
-            _log("called with arguments: ");
-            for (i = 1; i < argc -1; i++)
-                _log("\'%s\', ", argv[i]);
-            _log("\'%s\'\n", argv[i]);
-        }
+      logh = stderr;
+  }
+  else if (quiet && !verbose)
+    logh = NULL; // Quiet mode, do not log
+  else
+    logh = stderr; // Default: log to stderr
+
+  // Start debug logging
+  if (debug)
+  {
+    // If we are not in debug mode, we do this later, as we must find out at
+    // first which spooler is used. When printing without spooler we
+    // suppress logging because foomatic-rip is called directly on the
+    // command line and so we avoid logging onto the console.
+    // _log("foomatic-rip version "VERSION" running...\n");
+
+    // Print the command line only in debug mode, Mac OS X adds very many
+    // options so that CUPS cannot handle the output of the command line
+    // in its log files. If CUPS encounters a line with more than 1024
+    // characters sent into its log files, it aborts the job with an error.
+    if (spooler != SPOOLER_CUPS)
+    {
+      _log("called with arguments: ");
+      for (i = 1; i < argc -1; i++)
+       _log("\'%s\', ", argv[i]);
+      _log("\'%s\'\n", argv[i]);
     }
-
-    if (getenv("PPD")) {
-        strncpy(job->ppdfile, getenv("PPD"), sizeof(job->ppdfile) - 1);
-        if (strlen(getenv("PPD")) > 2047)
-          job->ppdfile[2047] = '\0';
-        spooler = SPOOLER_CUPS;
-       strncpy_omit(job->printer, getenv("PRINTER"), 256, omit_shellescapes);
-       if (getenv("CUPS_SERVERBIN")) {
-            strncpy(cupsfilterpath, getenv("CUPS_SERVERBIN"),
-                    sizeof(cupsfilterpath) - 1);
-            if (strlen(getenv("CUPS_SERVERBIN")) > PATH_MAX-1)
-              cupsfilterpath[PATH_MAX-1] = '\0';
-        }
+  }
+
+  if (getenv("PPD"))
+  {
+    strncpy(job->ppdfile, getenv("PPD"), sizeof(job->ppdfile) - 1);
+    if (strlen(getenv("PPD")) > 2047)
+      job->ppdfile[2047] = '\0';
+    spooler = SPOOLER_CUPS;
+    strncpy_omit(job->printer, getenv("PRINTER"), 256, omit_shellescapes);
+    if (getenv("CUPS_SERVERBIN"))
+    {
+      strncpy(cupsfilterpath, getenv("CUPS_SERVERBIN"),
+             sizeof(cupsfilterpath) - 1);
+      if (strlen(getenv("CUPS_SERVERBIN")) > PATH_MAX-1)
+       cupsfilterpath[PATH_MAX-1] = '\0';
     }
-
-    /* CUPS calls foomatic-rip only with 5 or 6 positional parameters,
-       not with named options, like for example "-p <string>". */
-    if (spooler != SPOOLER_CUPS) {
-
-        if ((str = arglist_get_value(arglist, "-j")) || (str = arglist_get_value(arglist, "-J"))) {
-            strncpy_omit(job->title, str, 2048, omit_shellescapes);
-          if (!arglist_remove(arglist, "-j"))
-               arglist_remove(arglist, "-J");
-       }
-
-        /* PPD file name given via the command line
-           allow duplicates, and use the last specified one */
-            while ((str = arglist_get_value(arglist, "-p"))) {
-                strncpy(job->ppdfile, str, sizeof(job->ppdfile) - 1);
-                if (strlen(str) > 2047)
-                  job->ppdfile[2047] = '\0';
-                arglist_remove(arglist, "-p");
-            }
-           while ((str = arglist_get_value(arglist, "--ppd"))) {
-               strncpy(job->ppdfile, str, sizeof(job->ppdfile) - 1);
-               if (strlen(str) > 2047)
-                 job->ppdfile[2047] = '\0';
-               arglist_remove(arglist, "--ppd");
-           }
-
-        /* Options for spooler-less printing */
-        while ((str = arglist_get_value(arglist, "-o"))) {
-            strncpy_omit(tmp, str, 1024, omit_shellescapes);
-            dstrcatf(job->optstr, "%s ", tmp);
-            /* if "-o cm-calibration" was passed, we raise a flag */
-            if (!strcmp(tmp, "cm-calibration")) {
-                cm_calibrate = 1;
-                cm_disabled = 1;
-            }
-            arglist_remove(arglist, "-o");
-           /* We print without spooler */
-           spooler = SPOOLER_DIRECT;
-        }
-
-        /* Printer for spooler-less printing */
-        if ((str = arglist_get_value(arglist, "-d"))) {
-            strncpy_omit(job->printer, str, 256, omit_shellescapes);
-            arglist_remove(arglist, "-d");
-        }
-
-        /* Printer for spooler-less printing */
-        if ((str = arglist_get_value(arglist, "-P"))) {
-            strncpy_omit(job->printer, str, 256, omit_shellescapes);
-            arglist_remove(arglist, "-P");
-        }
-
+  }
+
+  // CUPS calls foomatic-rip only with 5 or 6 positional parameters,
+  // not with named options, like for example "-p <string>".
+  if (spooler != SPOOLER_CUPS)
+  {
+    if ((str = arglist_get_value(arglist, "-j")) ||
+       (str = arglist_get_value(arglist, "-J")))
+    {
+      strncpy_omit(job->title, str, 2048, omit_shellescapes);
+      if (!arglist_remove(arglist, "-j"))
+       arglist_remove(arglist, "-J");
     }
 
-    /* Check status of printer color management from the color manager */
-    data->printer = job->printer;
-    cm_disabled = cfCmIsPrinterCmDisabled(data);
-
-    _log("'CM Color Calibration' Mode in SPOOLER-LESS: %s\n", cm_calibrate ? 
-         "Activated" : "Off");
-
-    /* spooler specific initialization */
-    switch (spooler) {
-
-        case SPOOLER_CUPS:
-            init_cups(arglist, filelist, job);
-            break;
-
-        case SPOOLER_DIRECT:
-            init_direct(arglist, filelist, job);
-            break;
+    // PPD file name given via the command line
+    // allow duplicates, and use the last specified one
+    while ((str = arglist_get_value(arglist, "-p")))
+    {
+      strncpy(job->ppdfile, str, sizeof(job->ppdfile) - 1);
+      if (strlen(str) > 2047)
+       job->ppdfile[2047] = '\0';
+      arglist_remove(arglist, "-p");
     }
-
-    /* Files to be printed (can be more than one for spooler-less printing) */
-    /* Empty file list -> print STDIN */
-    dstrtrim(filelist);
-    if (filelist->len == 0)
-        dstrcpyf(filelist, "<STDIN>");
-
-    /* Check filelist */
-    p = strtok(strdup(filelist->data), " ");
-    while (p) {
-        if (strcmp(p, "<STDIN>") != 0) {
-            if (p[0] == '-')
-                rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Invalid argument: %s", p);
-            else if (access(p, R_OK) != 0) {
-                _log("File %s does not exist/is not readable\n", p);
-            strclr(p);
-            }
-        }
-        p = strtok(NULL, " ");
+    while ((str = arglist_get_value(arglist, "--ppd")))
+    {
+      strncpy(job->ppdfile, str, sizeof(job->ppdfile) - 1);
+      if (strlen(str) > 2047)
+       job->ppdfile[2047] = '\0';
+      arglist_remove(arglist, "--ppd");
     }
 
-    /* When we print without spooler do not log onto STDERR unless
-       the "-v" ('Verbose') is set or the debug mode is used */
-    if (spooler == SPOOLER_DIRECT && !verbose && !debug) {
-        if (logh && logh != stderr)
-            fclose(logh);
-        logh = NULL;
+    // Options for spooler-less printing
+    while ((str = arglist_get_value(arglist, "-o")))
+    {
+      strncpy_omit(tmp, str, 1024, omit_shellescapes);
+      dstrcatf(job->optstr, "%s ", tmp);
+      // if "-o cm-calibration" was passed, we raise a flag
+      if (!strcmp(tmp, "cm-calibration"))
+      {
+       cm_calibrate = 1;
+       cm_disabled = 1;
+      }
+      arglist_remove(arglist, "-o");
+      // We print without spooler
+      spooler = SPOOLER_DIRECT;
     }
 
-    /* If we are in debug mode, we do this earlier. */
-    if (!debug) {
-        _log("foomatic-rip version " VERSION " running...\n");
-        /* Print the command line only in debug mode, Mac OS X adds very many
-        options so that CUPS cannot handle the output of the command line
-        in its log files. If CUPS encounters a line with more than 1024
-        characters sent into its log files, it aborts the job with an error. */
-        if (spooler != SPOOLER_CUPS) {
-            _log("called with arguments: ");
-            for (i = 1; i < argc -1; i++)
-                _log("\'%s\', ", argv[i]);
-            _log("\'%s\'\n", argv[i]);
-        }
+    // Printer for spooler-less printing
+    if ((str = arglist_get_value(arglist, "-d")))
+    {
+      strncpy_omit(job->printer, str, 256, omit_shellescapes);
+      arglist_remove(arglist, "-d");
     }
 
-    /* PPD File */
-    /* Load the PPD file and build a data structure for the renderer's
-       command line and the options */
-    read_ppd_file(job->ppdfile);
-
-    /* We do not need to parse the PostScript job when we don't have
-       any options. If we have options, we must check whether the
-       default settings from the PPD file are valid and correct them
-       if nexessary. */
-    if (option_count() == 0) {
-        /* We don't have any options, so we do not need to parse the
-           PostScript data */
-        dontparse = 1;
+    // Printer for spooler-less printing
+    if ((str = arglist_get_value(arglist, "-P")))
+    {
+      strncpy_omit(job->printer, str, 256, omit_shellescapes);
+      arglist_remove(arglist, "-P");
     }
+  }
+
+  // Check status of printer color management from the color manager
+  data->printer = job->printer;
+  cm_disabled = cfCmIsPrinterCmDisabled(data);
+
+  _log("'CM Color Calibration' Mode in SPOOLER-LESS: %s\n", cm_calibrate ? 
+       "Activated" : "Off");
+
+  // spooler specific initialization
+  switch (spooler)
+  {
+    case SPOOLER_CUPS:
+        init_cups(arglist, filelist, job);
+       break;
+
+    case SPOOLER_DIRECT:
+        init_direct(arglist, filelist, job);
+       break;
+  }
+
+  // Files to be printed (can be more than one for spooler-less printing)
+  // Empty file list -> print STDIN
+  dstrtrim(filelist);
+  if (filelist->len == 0)
+    dstrcpyf(filelist, "<STDIN>");
+
+  // Check filelist
+  p = strtok(strdup(filelist->data), " ");
+  while (p)
+  {
+    if (strcmp(p, "<STDIN>") != 0)
+    {
+      if (p[0] == '-')
+       rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Invalid argument: %s", p);
+      else if (access(p, R_OK) != 0)
+      {
+       _log("File %s does not exist/is not readable\n", p);
+       strclr(p);
+      }
+    }
+    p = strtok(NULL, " ");
+  }
 
-    /* Is our PPD for a CUPS raster driver */
-    if (!isempty(cupsfilter)) {
-        /* Search the filter in cupsfilterpath
-           The %Y is a placeholder for the option settings */
-        havefilter = 0;
-        path = cupsfilterpath;
-        while ((path = strncpy_tochar(tmp, path, 1024, ":"))) {
-            strlcat(tmp, "/", 1024);
-            strlcat(tmp, cupsfilter, 1024);
-            if (access(tmp, X_OK) == 0) {
-                havefilter = 1;
-                strlcpy(cupsfilter, tmp, 256);
-                strlcat(cupsfilter, " 0 '' '' 0 '%Y%X'", 256);
-                break;
-            }
-        }
-
-        if (!havefilter) {
-            /* We do not have the required filter, so we assume that
-               rendering this job is supposed to be done on a remote
-               server. So we do not define a renderer command line and
-               embed only the option settings (as we had a PostScript
-               printer). This way the settings are taken into account
-               when the job is rendered on the server.*/
-            _log("CUPS filter for this PPD file not found - assuming that job will "
-                 "be rendered on a remote server. Only the PostScript of the options"
-                 "will be inserted into the PostScript data stream.\n");
-        }
-        else {
-            /* use gstoraster filter if available, otherwise run Ghostscript
-              directly */
-            havegstoraster = 0;
-            path = cupsfilterpath;
-            while ((path = strncpy_tochar(tmp, path, 1024, ":"))) {
-                strlcat(tmp, "/gstoraster", 1024);
-                if (access(tmp, X_OK) == 0) {
-                    havegstoraster = 1;
-                    strlcpy(gstoraster, tmp, 256);
-                    strlcat(gstoraster, " 0 '' '' 0 '%X'", 256);
-                    break;
-                }
-            }
-            if (!havegstoraster) {
-                const char **qualifier = NULL;
-                char *icc_profile = NULL;
-
-                if (!cm_disabled) {
-                  qualifier = get_ppd_qualifier();
-                  _log("INFO: Using qualifer: '%s.%s.%s'\n",
-                        qualifier[0], qualifier[1], qualifier[2]);
-
-                  /* fall back to PPD */
-                  if (icc_profile == NULL) {
-                    _log("INFO: need to look in PPD for matching qualifer\n");
-                    icc_profile = get_icc_profile_for_qualifier(qualifier);
-                  }
-                }
-
-                /* ICC profile is specified for Ghostscript unless
-                   "cm-calibration" option was passed in foomatic-rip */
-                if (icc_profile != NULL)
-                  snprintf(profile_arg, sizeof(profile_arg),
-                           "-sOutputICCProfile='%s'", icc_profile);
-                else
-                  profile_arg[0] = '\0';
-
-                snprintf(gstoraster, sizeof(gstoraster), "gs -dQUIET -dDEBUG -dSAFER -dNOPAUSE -dBATCH -dNOINTERPOLATE -dNOMEDIAATTRS -sDEVICE=cups -dShowAcroForm %s -sOutputFile=- -", profile_arg);
-                free(icc_profile);
-            }
-
-            /* build Ghostscript/CUPS driver command line */
-            snprintf(cmd, 1024, "%s | %s", gstoraster, cupsfilter);
-            _log("INFO: Using command line: %s\n", cmd);
-
-            /* Set environment variables */
-            setenv("PPD", job->ppdfile, 1);
-        }
+  // When we print without spooler do not log onto STDERR unless
+  // the "-v" ('Verbose') is set or the debug mode is used
+  if (spooler == SPOOLER_DIRECT && !verbose && !debug)
+  {
+    if (logh && logh != stderr)
+      fclose(logh);
+    logh = NULL;
+  }
+
+  // If we are in debug mode, we do this earlier.
+  if (!debug)
+  {
+    _log("foomatic-rip version " VERSION " running...\n");
+    // Print the command line only in debug mode, Mac OS X adds very many
+    // options so that CUPS cannot handle the output of the command line
+    // in its log files. If CUPS encounters a line with more than 1024
+    // characters sent into its log files, it aborts the job with an error.
+    if (spooler != SPOOLER_CUPS)
+    {
+      _log("called with arguments: ");
+      for (i = 1; i < argc -1; i++)
+       _log("\'%s\', ", argv[i]);
+      _log("\'%s\'\n", argv[i]);
+    }
+  }
+
+  // PPD File
+  // Load the PPD file and build a data structure for the renderer's
+  // command line and the options
+  read_ppd_file(job->ppdfile);
+
+  // We do not need to parse the PostScript job when we don't have
+  // any options. If we have options, we must check whether the
+  // default settings from the PPD file are valid and correct them
+  // if nexessary.
+  if (option_count() == 0)
+  {
+    // We don't have any options, so we do not need to parse the
+    // PostScript data
+    dontparse = 1;
+  }
+
+  // Is our PPD for a CUPS raster driver
+  if (!isempty(cupsfilter))
+  {
+    // Search the filter in cupsfilterpath
+    // The %Y is a placeholder for the option settings
+    havefilter = 0;
+    path = cupsfilterpath;
+    while ((path = strncpy_tochar(tmp, path, 1024, ":")))
+    {
+      strlcat(tmp, "/", 1024);
+      strlcat(tmp, cupsfilter, 1024);
+      if (access(tmp, X_OK) == 0) {
+       havefilter = 1;
+       strlcpy(cupsfilter, tmp, 256);
+       strlcat(cupsfilter, " 0 '' '' 0 '%Y%X'", 256);
+       break;
+      }
     }
 
-    /* Was the RIP command line defined in the PPD file? If not, we assume a PostScript printer
-       and do not render/translate the input data */
-    if (isempty(cmd)) {
-        strcpy(cmd, "cat%A%B%C%D%E%F%G%H%I%J%K%L%M%Z");
-        if (dontparse) {
-            /* No command line, no options, we have a raw queue, don't check
-               whether the input is PostScript, simply pass the input data to
-               the backend.*/
-            dontparse = 2;
-            strcpy(printer_model, "Raw queue");
-        }
+    if (!havefilter)
+    {
+      // We do not have the required filter, so we assume that
+      // rendering this job is supposed to be done on a remote
+      // server. So we do not define a renderer command line and
+      // embed only the option settings (as we had a PostScript
+      // printer). This way the settings are taken into account
+      // when the job is rendered on the server.
+      _log("CUPS filter for this PPD file not found - assuming that job will "
+          "be rendered on a remote server. Only the PostScript of the options"
+          "will be inserted into the PostScript data stream.\n");
     }
+    else
+    {
+      // use gstoraster filter if available, otherwise run Ghostscript
+      // directly
+      havegstoraster = 0;
+      path = cupsfilterpath;
+      while ((path = strncpy_tochar(tmp, path, 1024, ":")))
+      {
+       strlcat(tmp, "/gstoraster", 1024);
+       if (access(tmp, X_OK) == 0)
+       {
+         havegstoraster = 1;
+         strlcpy(gstoraster, tmp, 256);
+         strlcat(gstoraster, " 0 '' '' 0 '%X'", 256);
+         break;
+       }
+      }
+      if (!havegstoraster)
+      {
+       const char **qualifier = NULL;
+       char *icc_profile = NULL;
+
+       if (!cm_disabled)
+       {
+         qualifier = get_ppd_qualifier();
+         _log("INFO: Using qualifer: '%s.%s.%s'\n",
+              qualifier[0], qualifier[1], qualifier[2]);
+
+         // fall back to PPD
+         if (icc_profile == NULL)
+         {
+           _log("INFO: need to look in PPD for matching qualifer\n");
+           icc_profile = get_icc_profile_for_qualifier(qualifier);
+         }
+       }
+
+       // ICC profile is specified for Ghostscript unless
+       // "cm-calibration" option was passed in foomatic-rip
+       if (icc_profile != NULL)
+         snprintf(profile_arg, sizeof(profile_arg),
+                  "-sOutputICCProfile='%s'", icc_profile);
+       else
+         profile_arg[0] = '\0';
+
+       snprintf(gstoraster, sizeof(gstoraster), "gs -dQUIET -dDEBUG -dSAFER -dNOPAUSE -dBATCH -dNOINTERPOLATE -dNOMEDIAATTRS -sDEVICE=cups -dShowAcroForm %s -sOutputFile=- -", profile_arg);
+       free(icc_profile);
+      }
 
-    /* Summary for debugging */
-    _log("\nParameter Summary\n"
-         "-----------------\n\n"
-         "Spooler: %s\n"
-         "Printer: %s\n"
-         "Shell: %s\n"
-         "PPD file: %s\n"
-         "ATTR file: %s\n"
-         "Printer model: %s\n",
-        spooler_name(spooler), job->printer, get_modern_shell(), job->ppdfile, attrpath, printer_model);
-    /* Print the options string only in debug mode, Mac OS X adds very many
-       options so that CUPS cannot handle the output of the option string
-       in its log files. If CUPS encounters a line with more than 1024 characters
-       sent into its log files, it aborts the job with an error.*/
-    if (debug || spooler != SPOOLER_CUPS)
-        _log("Options: %s\n", job->optstr->data);
-    _log("Job title: %s\n", job->title);
-    _log("File(s) to be printed:\n");
-    _log("%s\n\n", filelist->data);
-    if (getenv("GS_LIB"))
-        _log("Ghostscript extra search path ('GS_LIB'): %s\n", getenv("GS_LIB"));
-
-    /* Process options from command line */
-    optionset_copy_values(optionset("default"), optionset("userval"));
-    process_cmdline_options();
-
-    /* no postpipe for CUPS , even if one is defined in the PPD file */
-    if (spooler == SPOOLER_CUPS )
-        dstrclear(postpipe);
-
-    if (postpipe->len)
-        _log("Output will be redirected to:\n%s\n", postpipe);
-
-
-    filename = strtok_r(filelist->data, " ", &p);
-    while (filename) {
-        _log("\n================================================\n\n"
-             "File: %s\n\n"
-             "================================================\n\n", filename);
-
-        /* Do we have a raw queue? */
-        if (dontparse == 2) {
-            /* Raw queue, simply pass the input into the postpipe (or to STDOUT
-               when there is no postpipe) */
-            _log("Raw printing, executing \"cat %%s\"\n\n");
-            snprintf(tmp, 1024, "cat %s", postpipe->data);
-            if (strcasecmp(filename, "<STDIN>")) {
-              FILE *fh = fopen(filename, "r");
-              if (!fh) {
-                _log("Failed to open \"%s\".\n", filename);
-                fclose(stdin);
-              } else {
-                dup2(fileno(fh), 0);
-                fclose(fh);
-              }
-            }
-            run_system_process("raw-printer", tmp);
-            filename = strtok_r(NULL, " ", &p);
-            continue;
-        }
-
-        /* First, for arguments with a default, stick the default in as
-           the initial value for the "header" option set, this option set
-           consists of the PPD defaults, the options specified on the
-           command line, and the options set in the header part of the
-           PostScript file (all before the first page begins). */
-        optionset_copy_values(optionset("userval"), optionset("header"));
-
-        if (!print_file(filename, 1))
-           rip_die(EXIT_PRNERR_NORETRY, "Could not print file %s\n", filename);
-        filename = strtok_r(NULL, " ", &p);
+      // build Ghostscript/CUPS driver command line
+      snprintf(cmd, 1024, "%s | %s", gstoraster, cupsfilter);
+      _log("INFO: Using command line: %s\n", cmd);
+
+      // Set environment variables
+      setenv("PPD", job->ppdfile, 1);
+    }
+  }
+
+  // Was the RIP command line defined in the PPD file? If not, we assume a
+  // PostScript printer and do not render/translate the input data
+  if (isempty(cmd))
+  {
+    strcpy(cmd, "cat%A%B%C%D%E%F%G%H%I%J%K%L%M%Z");
+    if (dontparse)
+    {
+      // No command line, no options, we have a raw queue, don't check
+      // whether the input is PostScript, simply pass the input data to
+      // the backend.
+      dontparse = 2;
+      strcpy(printer_model, "Raw queue");
+    }
+  }
+
+  // Summary for debugging
+  _log("\nParameter Summary\n"
+       "-----------------\n\n"
+       "Spooler: %s\n"
+       "Printer: %s\n"
+       "Shell: %s\n"
+       "PPD file: %s\n"
+       "ATTR file: %s\n"
+       "Printer model: %s\n",
+       spooler_name(spooler), job->printer, get_modern_shell(),
+       job->ppdfile, attrpath, printer_model);
+  // Print the options string only in debug mode, Mac OS X adds very many
+  // options so that CUPS cannot handle the output of the option string
+  // in its log files. If CUPS encounters a line with more than 1024 characters
+  // sent into its log files, it aborts the job with an error.
+  if (debug || spooler != SPOOLER_CUPS)
+    _log("Options: %s\n", job->optstr->data);
+  _log("Job title: %s\n", job->title);
+  _log("File(s) to be printed:\n");
+  _log("%s\n\n", filelist->data);
+  if (getenv("GS_LIB"))
+    _log("Ghostscript extra search path ('GS_LIB'): %s\n", getenv("GS_LIB"));
+
+  // Process options from command line
+  optionset_copy_values(optionset("default"), optionset("userval"));
+  process_cmdline_options();
+
+  // no postpipe for CUPS , even if one is defined in the PPD file
+  if (spooler == SPOOLER_CUPS )
+    dstrclear(postpipe);
+
+  if (postpipe->len)
+    _log("Output will be redirected to:\n%s\n", postpipe);
+
+  filename = strtok_r(filelist->data, " ", &p);
+  while (filename)
+  {
+    _log("\n================================================\n\n"
+        "File: %s\n\n"
+        "================================================\n\n", filename);
+
+    // Do we have a raw queue?
+    if (dontparse == 2)
+    {
+      // Raw queue, simply pass the input into the postpipe (or to STDOUT
+      // when there is no postpipe)
+      _log("Raw printing, executing \"cat %%s\"\n\n");
+      snprintf(tmp, 1024, "cat %s", postpipe->data);
+      if (strcasecmp(filename, "<STDIN>"))
+      {
+       FILE *fh = fopen(filename, "r");
+       if (!fh)
+       {
+         _log("Failed to open \"%s\".\n", filename);
+         fclose(stdin);
+       }
+       else
+       {
+         dup2(fileno(fh), 0);
+         fclose(fh);
+       }
+      }
+      run_system_process("raw-printer", tmp);
+      filename = strtok_r(NULL, " ", &p);
+      continue;
     }
 
-    /* Close the last input file */
-    fclose(stdin);
+    // First, for arguments with a default, stick the default in as
+    // the initial value for the "header" option set, this option set
+    // consists of the PPD defaults, the options specified on the
+    // command line, and the options set in the header part of the
+    // PostScript file (all before the first page begins).
+    optionset_copy_values(optionset("userval"), optionset("header"));
 
-    /* TODO dump everything in $dat when debug is turned on (necessary?) */
+    if (!print_file(filename, 1))
+      rip_die(EXIT_PRNERR_NORETRY, "Could not print file %s\n", filename);
+    filename = strtok_r(NULL, " ", &p);
+  }
 
-    _log("\nClosing foomatic-rip.\n");
+  // Close the last input file
+  fclose(stdin);
 
+  // TODO dump everything in $dat when debug is turned on (necessary?)
 
-    /* Cleanup */
-    free_job(job);
-    free_dstr(filelist);
-    options_free();
-    close_log();
+  _log("\nClosing foomatic-rip.\n");
 
-    argv_free(jclprepend);
-    free_dstr(jclappend);
+  // Cleanup
+  free_job(job);
+  free_dstr(filelist);
+  options_free();
+  close_log();
 
-    list_free(arglist);
+  argv_free(jclprepend);
+  free_dstr(jclappend);
 
-    return EXIT_PRINTED;
-}
+  list_free(arglist);
 
+  return (EXIT_PRINTED);
+}
index 35fd2429b98a61d6c98df8fb839ceed5e2f3efae..3a75d03054ecc1900459865325ab1a0667afbf19 100644 (file)
@@ -1,25 +1,26 @@
-/* foomaticrip.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// foomaticrip.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef foomatic_h
 #define foomatic_h
 #include <time.h>
 #include <limits.h>
 
-/* This is the location of the debug logfile (and also the copy of the
- * processed PostScript data) in case you have enabled debugging above.
- * The logfile will get the extension ".log", the PostScript data ".ps".
- */
+// This is the location of the debug logfile (and also the copy of the
+// processed PostScript data) in case you have enabled debugging above.
+// The logfile will get the extension ".log", the PostScript data ".ps".
+
 #ifndef LOG_FILE
 #define LOG_FILE "/tmp/foomatic-rip"
 #endif
 
 
-/* Constants used by this filter
- *
- * Error codes, as some spoolers behave different depending on the reason why
- * the RIP failed, we return an error code.
- */
-#define EXIT_PRINTED 0                          /* file was printed normally */
-#define EXIT_PRNERR 1                           /* printer error occured */
-#define EXIT_PRNERR_NORETRY 2                   /* printer error with no hope of retry */
-#define EXIT_JOBERR 3                           /* job is defective */
-#define EXIT_SIGNAL 4                           /* terminated after catching signal */
-#define EXIT_ENGAGED 5                          /* printer is otherwise engaged (connection refused) */
-#define EXIT_STARVED 6                          /* starved for system resources */
-#define EXIT_PRNERR_NORETRY_ACCESS_DENIED 7     /* bad password? bad port permissions? */
-#define EXIT_PRNERR_NOT_RESPONDING 8            /* just doesn't answer at all (turned off?) */
-#define EXIT_PRNERR_NORETRY_BAD_SETTINGS 9      /* interface settings are invalid */
-#define EXIT_PRNERR_NO_SUCH_ADDRESS 10          /* address lookup failed, may be transient */
-#define EXIT_PRNERR_NORETRY_NO_SUCH_ADDRESS 11  /* address lookup failed, not transient */
-#define EXIT_INCAPABLE 50                       /* printer wants (lacks) features or resources */
-
-
-/* Supported spoolers are currently:
- *
- *   cups    - CUPS - Common Unix Printing System
- *   direct  - Direct, spooler-less printing
- */
+// Constants used by this filter
+//
+// Error codes, as some spoolers behave different depending on the reason why
+// the RIP failed, we return an error code.
+
+#define EXIT_PRINTED 0                          // file was printed normally
+#define EXIT_PRNERR 1                           // printer error occured
+#define EXIT_PRNERR_NORETRY 2                   // printer error with no hope
+                                                // of retry
+#define EXIT_JOBERR 3                           // job is defective
+#define EXIT_SIGNAL 4                           // terminated after catching
+                                                // signal
+#define EXIT_ENGAGED 5                          // printer is otherwise engaged
+                                                // (connection refused)
+#define EXIT_STARVED 6                          // starved for system resources
+#define EXIT_PRNERR_NORETRY_ACCESS_DENIED 7     // bad password? bad port
+                                                // permissions?
+#define EXIT_PRNERR_NOT_RESPONDING 8            // just doesn't answer at all
+                                                // (turned off?)
+#define EXIT_PRNERR_NORETRY_BAD_SETTINGS 9      // interface settings are
+                                                // invalid
+#define EXIT_PRNERR_NO_SUCH_ADDRESS 10          // address lookup failed, may
+                                                // be transient
+#define EXIT_PRNERR_NORETRY_NO_SUCH_ADDRESS 11  // address lookup failed, not
+                                                // transient
+#define EXIT_INCAPABLE 50                       // printer wants (lacks)
+                                                // features or resources
+
+
+// Supported spoolers are currently:
+//
+//   cups    - CUPS - Common Unix Printing System
+//   direct  - Direct, spooler-less printing
+
 #define SPOOLER_CUPS      1
 #define SPOOLER_DIRECT    2
 
-/* The spooler from which foomatic-rip was called. set in main() */
+// The spooler from which foomatic-rip was called. set in main()
 extern int spooler;
 
 #ifndef PATH_MAX
@@ -80,7 +90,8 @@ extern int spooler;
 #endif
 #define CMDLINE_MAX 65536
 
-typedef struct {
+typedef struct
+{
     char printer[256];
     char id[128];
     char user[128];
@@ -94,14 +105,14 @@ typedef struct {
 } jobparams_t;
 
 
-jobparams_t * get_current_job();
+jobparams_t *get_current_job();
 
 void _log(const char* msg, ...);
 int redirect_log_to_stderr();
 void rip_die(int status, const char *msg, ...);
 
-const char * get_modern_shell();
-FILE * open_postpipe();
+const char *get_modern_shell();
+FILE *open_postpipe();
 
 extern struct dstr *currentcmd;
 extern struct dstr *jclappend;
index ef848b3663a29d0dcfd791e492ba6a1b8f8fd6aa..d3c025525947073aba881aac333442880a2ee1d0 100644 (file)
@@ -1,25 +1,26 @@
-/* options.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// options.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "foomaticrip.h"
 #include "options.h"
 #include <string.h>
 #include <math.h>
 
-/* qualifier -> filename mapping entry */
-typedef struct icc_mapping_entry_s {
-    char *qualifier;
-    char *filename;
+// qualifier -> filename mapping entry
+typedef struct icc_mapping_entry_s
+{
+  char *qualifier;
+  char *filename;
 } icc_mapping_entry_t;
 
-/* Values from foomatic keywords in the ppd file */
+// Values from foomatic keywords in the ppd file
 extern char printer_model [256];
 char printer_id [256];
 char driver [128];
 char cmd [4096];
 char cmd_pdf [4096];
-extern dstr_t *postpipe;  /* command into which the output of this
-                             filter should be piped */
+extern dstr_t *postpipe;  // command into which the output of this
+                          // filter should be piped
 extern char cupsfilter [256];
 int jobentitymaxlen = 0;
 int userentitymaxlen = 0;
@@ -51,20 +53,20 @@ int hostentitymaxlen = 0;
 int titleentitymaxlen = 0;
 int optionsentitymaxlen = 0;
 
-/* JCL prefix to put before the JCL options
- (Can be modified by a "*JCLBegin:" keyword in the ppd file): */
+// JCL prefix to put before the JCL options
+// (Can be modified by a "*JCLBegin:" keyword in the ppd file):
 char jclbegin[256] = "\033%-12345X@PJL\n";
 
-/* JCL command to switch the printer to the PostScript interpreter
- (Can be modified by a "*JCLToPSInterpreter:" keyword in the PPD file): */
+// JCL command to switch the printer to the PostScript interpreter
+// (Can be modified by a "*JCLToPSInterpreter:" keyword in the PPD file):
 char jcltointerpreter[256] = "";
 
-/* JCL command to close a print job
- (Can be modified by a "*JCLEnd:" keyword in the PPD file): */
+// JCL command to close a print job
+// (Can be modified by a "*JCLEnd:" keyword in the PPD file):
 char jclend[256] = "\033%-12345X@PJL RESET\n";
 
-/* Prefix for starting every JCL command
- (Can be modified by "*FoomaticJCLPrefix:" keyword in the PPD file): */
+// Prefix for starting every JCL command
+// (Can be modified by "*FoomaticJCLPrefix:" keyword in the PPD file):
 char jclprefix[256] = "@PJL ";
 int jclprefixset = 0;
 
@@ -83,2189 +85,2607 @@ int optionset_alloc, optionset_count;
 char **optionsets;
 
 
-char * get_icc_profile_for_qualifier(const char **qualifier)
+char *
+get_icc_profile_for_qualifier(const char **qualifier)
 {
-    char tmp[1024];
-    char *profile = NULL;
-    listitem_t *i;
-    icc_mapping_entry_t *entry;
+  char tmp[1024];
+  char *profile = NULL;
+  listitem_t *i;
+  icc_mapping_entry_t *entry;
 
-    /* no data */
-    if (qualifier_data == NULL)
-        goto out;
+  // no data
+  if (qualifier_data == NULL)
+    goto out;
 
-    /* search list for qualifier */
-    snprintf(tmp, sizeof(tmp), "%s.%s.%s",
-             qualifier[0], qualifier[1], qualifier[2]);
-    for (i = qualifier_data->first; i != NULL; i = i->next) {
-        entry = (icc_mapping_entry_t *) i->data;
-        if (strcmp(entry->qualifier, tmp) == 0) {
-            profile = entry->filename;
-            break;
-        }
+  // search list for qualifier
+  snprintf(tmp, sizeof(tmp), "%s.%s.%s",
+          qualifier[0], qualifier[1], qualifier[2]);
+  for (i = qualifier_data->first; i != NULL; i = i->next)
+  {
+    entry = (icc_mapping_entry_t *)i->data;
+    if (strcmp(entry->qualifier, tmp) == 0)
+    {
+      profile = entry->filename;
+      break;
     }
-out:
-    return profile;
+  }
+ out:
+  return (profile);
 }
 
-/* a selector is a general tri-dotted specification.
- * The 2nd and 3rd elements of the qualifier are optionally modified by
- * cupsICCQualifier2 and cupsICCQualifier3:
- *
- * [Colorspace].[{cupsICCQualifier2}].[{cupsICCQualifier3}]
- */
+
+// a selector is a general tri-dotted specification.
+// The 2nd and 3rd elements of the qualifier are optionally modified by
+// cupsICCQualifier2 and cupsICCQualifier3:
+//
+// [Colorspace].[{cupsICCQualifier2}].[{cupsICCQualifier3}]
+
 const char **
 get_ppd_qualifier ()
 {
-  return (const char**) qualifier;
-}
-
-const char * type_name(int type)
-{
-    switch (type) {
-        case TYPE_NONE:
-            return "none";
-        case TYPE_ENUM:
-            return "enum";
-        case TYPE_PICKMANY:
-            return "pickmany";
-        case TYPE_BOOL:
-            return "bool";
-        case TYPE_INT:
-            return "int";
-        case TYPE_FLOAT:
-            return "float";
-        case TYPE_STRING:
-            return "string";
-    };
-    _log("type '%d' does not exist\n", type);
-    return NULL;
+  return ((const char**)qualifier);
 }
 
-int type_from_string(const char *typestr)
+
+const char *
+type_name(int type)
+{
+  switch (type)
+  {
+    case TYPE_NONE:
+        return ("none");
+    case TYPE_ENUM:
+        return ("enum");
+    case TYPE_PICKMANY:
+        return ("pickmany");
+    case TYPE_BOOL:
+        return ("bool");
+    case TYPE_INT:
+        return ("int");
+    case TYPE_FLOAT:
+        return ("float");
+    case TYPE_STRING:
+        return ("string");
+  }
+  _log("type '%d' does not exist\n", type);
+  return (NULL);
+}
+
+
+int
+type_from_string(const char *typestr)
 {
-    int type = TYPE_NONE;
+  int type = TYPE_NONE;
 
-    /* Official PPD options */
-    if (!strcmp(typestr, "PickOne"))
-        type = TYPE_ENUM;
-    else if (!strcmp(typestr, "PickMany"))
-        type = TYPE_PICKMANY;
-    else if (!strcmp(typestr, "Boolean"))
-        type = TYPE_BOOL;
+  // Official PPD options
+  if (!strcmp(typestr, "PickOne"))
+    type = TYPE_ENUM;
+  else if (!strcmp(typestr, "PickMany"))
+    type = TYPE_PICKMANY;
+  else if (!strcmp(typestr, "Boolean"))
+    type = TYPE_BOOL;
 
-    /* FoomaticRIPOption */
-    else if (strcasecmp(typestr, "enum") == 0)
-        type = TYPE_ENUM;
-    else if (strcasecmp(typestr, "pickmany") == 0)
-        type = TYPE_PICKMANY;
-    else if (strcasecmp(typestr, "bool") == 0)
-        type = TYPE_BOOL;
-    else if (strcasecmp(typestr, "int") == 0)
-        type = TYPE_INT;
-    else if (strcasecmp(typestr, "float") == 0)
-        type = TYPE_FLOAT;
-    else if (strcasecmp(typestr, "string") == 0)
-        type = TYPE_STRING;
-    else if (strcasecmp(typestr, "password") == 0)
-        type = TYPE_PASSWORD;
+  // FoomaticRIPOption
+  else if (strcasecmp(typestr, "enum") == 0)
+    type = TYPE_ENUM;
+  else if (strcasecmp(typestr, "pickmany") == 0)
+    type = TYPE_PICKMANY;
+  else if (strcasecmp(typestr, "bool") == 0)
+    type = TYPE_BOOL;
+  else if (strcasecmp(typestr, "int") == 0)
+    type = TYPE_INT;
+  else if (strcasecmp(typestr, "float") == 0)
+    type = TYPE_FLOAT;
+  else if (strcasecmp(typestr, "string") == 0)
+    type = TYPE_STRING;
+  else if (strcasecmp(typestr, "password") == 0)
+    type = TYPE_PASSWORD;
 
-    return type;
+  return (type);
 }
 
-char style_from_string(const char *style)
-{
-    char r = '\0';
-    if (strcmp(style, "PS") == 0)
-        r = 'G';
-    else if (strcmp(style, "CmdLine") == 0)
-        r = 'C';
-    else if (strcmp(style, "JCL") == 0)
-        r = 'J';
-    else if (strcmp(style, "Composite") == 0)
-        r = 'X';
-    return r;
-}
 
-int section_from_string(const char *value)
+char
+style_from_string(const char *style)
 {
-    if (!strcasecmp(value, "AnySetup"))
-        return SECTION_ANYSETUP;
-    else if (!strcasecmp(value, "PageSetup"))
-        return SECTION_PAGESETUP;
-    else if (!strcasecmp(value, "Prolog"))
-        return SECTION_PROLOG;
-    else if (!strcasecmp(value, "DocumentSetup"))
-        return SECTION_DOCUMENTSETUP;
-    else if (!strcasecmp(value, "JCLSetup"))
-        return SECTION_JCLSETUP;
-
-    _log("Unknown section: \"%s\"\n", value);
-    return 0;
+  char r = '\0';
+  if (strcmp(style, "PS") == 0)
+    r = 'G';
+  else if (strcmp(style, "CmdLine") == 0)
+    r = 'C';
+  else if (strcmp(style, "JCL") == 0)
+    r = 'J';
+  else if (strcmp(style, "Composite") == 0)
+    r = 'X';
+  return (r);
 }
 
-void options_init()
+
+int
+section_from_string(const char *value)
 {
-    optionset_alloc = 8;
-    optionset_count = 0;
-    optionsets = calloc(optionset_alloc, sizeof(char *));
+  if (!strcasecmp(value, "AnySetup"))
+    return (SECTION_ANYSETUP);
+  else if (!strcasecmp(value, "PageSetup"))
+    return (SECTION_PAGESETUP);
+  else if (!strcasecmp(value, "Prolog"))
+    return (SECTION_PROLOG);
+  else if (!strcasecmp(value, "DocumentSetup"))
+    return (SECTION_DOCUMENTSETUP);
+  else if (!strcasecmp(value, "JCLSetup"))
+    return (SECTION_JCLSETUP);
 
-    prologprepend = create_dstr();
-    setupprepend = create_dstr();
-    pagesetupprepend = create_dstr();
+  _log("Unknown section: \"%s\"\n", value);
+  return (0);
 }
 
-static void free_param(param_t *param)
+
+void
+options_init()
 {
-    if (param->allowedchars) {
-        regfree(param->allowedchars);
-        free(param->allowedchars);
-    }
-
-    if (param->allowedregexp) {
-        regfree(param->allowedregexp);
-        free(param->allowedregexp);
-    }
+  optionset_alloc = 8;
+  optionset_count = 0;
+  optionsets = calloc(optionset_alloc, sizeof(char *));
 
-    free(param);
+  prologprepend = create_dstr();
+  setupprepend = create_dstr();
+  pagesetupprepend = create_dstr();
 }
 
-/*
- *  Values
- */
 
-static void free_value(value_t *val)
+static void
+free_param(param_t *param)
 {
-    if (val->value)
-        free(val->value);
-    free(val);
-}
+  if (param->allowedchars)
+  {
+    regfree(param->allowedchars);
+    free(param->allowedchars);
+  }
 
+  if (param->allowedregexp)
+  {
+    regfree(param->allowedregexp);
+    free(param->allowedregexp);
+  }
 
-/*
- *  Options
- */
-static void free_option(option_t *opt)
-{
-    choice_t *choice;
-    param_t *param;
-    value_t *value;
+  free(param);
+}
 
-    free(opt->custom_command);
-    free(opt->proto);
 
-    while (opt->valuelist) {
-        value = opt->valuelist;
-        opt->valuelist = opt->valuelist->next;
-        free_value(value);
-    }
-    while (opt->choicelist) {
-        choice = opt->choicelist;
-        opt->choicelist = opt->choicelist->next;
-        free(choice);
-    }
-    while (opt->paramlist) {
-        param = opt->paramlist;
-        opt->paramlist = opt->paramlist->next;
-        free_param(param);
-    }
-    if (opt->foomatic_param)
-        free_param(opt->foomatic_param);
+//
+//  Values
+//
 
-    free(opt);
+static void
+free_value(value_t *val)
+{
+  if (val->value)
+    free(val->value);
+  free(val);
 }
 
-void options_free()
-{
-    option_t *opt;
-    int i;
-    listitem_t *item;
-    icc_mapping_entry_t *entry;
 
-    for (i = 0; i < optionset_count; i++)
-        free(optionsets[i]);
-    free(optionsets);
-    optionsets = NULL;
-    optionset_alloc = 0;
-    optionset_count = 0;
+//
+//  Options
+//
 
-    if (qualifier_data) {
-        for (item = qualifier_data->first; item != NULL; item = item->next) {
-            entry = (icc_mapping_entry_t *) item->data;
-            free(entry->qualifier);
-            free(entry->filename);
-            free(entry);
-        }
-        list_free(qualifier_data);
+static void free_option(option_t *opt)
+{
+  choice_t *choice;
+  param_t *param;
+  value_t *value;
+
+  free(opt->custom_command);
+  free(opt->proto);
+
+  while (opt->valuelist)
+  {
+    value = opt->valuelist;
+    opt->valuelist = opt->valuelist->next;
+    free_value(value);
+  }
+  while (opt->choicelist)
+  {
+    choice = opt->choicelist;
+    opt->choicelist = opt->choicelist->next;
+    free(choice);
+  }
+  while (opt->paramlist)
+  {
+    param = opt->paramlist;
+    opt->paramlist = opt->paramlist->next;
+    free_param(param);
+  }
+  if (opt->foomatic_param)
+    free_param(opt->foomatic_param);
+
+  free(opt);
+}
+
+
+void
+options_free()
+{
+  option_t *opt;
+  int i;
+  listitem_t *item;
+  icc_mapping_entry_t *entry;
+
+  for (i = 0; i < optionset_count; i++)
+    free(optionsets[i]);
+  free(optionsets);
+  optionsets = NULL;
+  optionset_alloc = 0;
+  optionset_count = 0;
+
+  if (qualifier_data)
+  {
+    for (item = qualifier_data->first; item != NULL; item = item->next)
+    {
+      entry = (icc_mapping_entry_t *) item->data;
+      free(entry->qualifier);
+      free(entry->filename);
+      free(entry);
     }
+    list_free(qualifier_data);
+  }
 
-    for (i=0; i<3; i++)
-      free(qualifier[i]);
-    free(qualifier);
+  for (i = 0; i < 3; i ++)
+    free(qualifier[i]);
+  free(qualifier);
 
-    while (optionlist) {
-        opt = optionlist;
-        optionlist = optionlist->next;
-        free_option(opt);
-    }
+  while (optionlist)
+  {
+    opt = optionlist;
+    optionlist = optionlist->next;
+    free_option(opt);
+  }
 
-    if (postpipe)
-        free_dstr(postpipe);
+  if (postpipe)
+    free_dstr(postpipe);
 
-    free_dstr(prologprepend);
-    free_dstr(setupprepend);
-    free_dstr(pagesetupprepend);
+  free_dstr(prologprepend);
+  free_dstr(setupprepend);
+  free_dstr(pagesetupprepend);
 }
 
-size_t option_count()
+
+size_t
+option_count()
 {
-    option_t *opt;
-    size_t cnt = 0;
+  option_t *opt;
+  size_t cnt = 0;
 
-    for (opt = optionlist; opt; opt = opt->next)
-        cnt++;
-    return cnt;
+  for (opt = optionlist; opt; opt = opt->next)
+    cnt++;
+  return (cnt);
 }
 
-option_t * find_option(const char *name)
+
+option_t *
+find_option(const char *name)
 {
-    option_t *opt;
+  option_t *opt;
 
-    /* PageRegion and PageSize are the same options, just store one of them */
-    if (!strcasecmp(name, "PageRegion"))
-        return find_option("PageSize");
+  // PageRegion and PageSize are the same options, just store one of them
+  if (!strcasecmp(name, "PageRegion"))
+    return (find_option("PageSize"));
 
-    for (opt = optionlist; opt; opt = opt->next) {
-      if ((!strcasecmp(opt->name, name)) ||
-         ((!strcasecmp(opt->name, &name[2])) &&
-          (!prefixcasecmp(name, "no"))))
-            return opt;
-    }
-    return NULL;
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    if ((!strcasecmp(opt->name, name)) ||
+       ((!strcasecmp(opt->name, &name[2])) &&
+        (!prefixcasecmp(name, "no"))))
+      return (opt);
+  }
+  return (NULL);
 }
 
-option_t * assure_option(const char *name)
+
+option_t *
+assure_option(const char *name)
 {
-    option_t *opt, *last;
+  option_t *opt, *last;
 
-    if ((opt = find_option(name)))
-        return opt;
+  if ((opt = find_option(name)))
+    return (opt);
 
-    opt = calloc(1, sizeof(option_t));
+  opt = calloc(1, sizeof(option_t));
 
-    /* PageRegion and PageSize are the same options, just store one of them */
-    if (!strcmp(name, "PageRegion"))
-        strlcpy(opt->name, "PageSize", 128);
-    else
-        strlcpy(opt->name, name, 128);
+  // PageRegion and PageSize are the same options, just store one of them
+  if (!strcmp(name, "PageRegion"))
+    strlcpy(opt->name, "PageSize", 128);
+  else
+    strlcpy(opt->name, name, 128);
 
-    /* set varname */
-    strcpy(opt->varname, opt->name);
-    strrepl(opt->varname, "-/.", '_');
+  // set varname
+  strcpy(opt->varname, opt->name);
+  strrepl(opt->varname, "-/.", '_');
 
-    /* Default execution style is 'G' (PostScript) since all arguments for
-    which we don't find "*Foomatic..." keywords are usual PostScript options */
-    opt->style = 'G';
+  // Default execution style is 'G' (PostScript) since all arguments for
+  // which we don't find "*Foomatic..." keywords are usual PostScript options
+  opt->style = 'G';
 
-    opt->type = TYPE_NONE;
+  opt->type = TYPE_NONE;
 
-    /* append opt to optionlist */
-    if (optionlist) {
-        for (last = optionlist; last->next; last = last->next);
-        last->next = opt;
-    }
-    else
-        optionlist = opt;
+  // append opt to optionlist
+  if (optionlist)
+  {
+    for (last = optionlist; last->next; last = last->next);
+    last->next = opt;
+  }
+  else
+    optionlist = opt;
 
-    /* prepend opt to optionlist_sorted_by_order
-       (0 is always at the beginning) */
-    if (optionlist_sorted_by_order) {
-        opt->next_by_order = optionlist_sorted_by_order;
-        optionlist_sorted_by_order = opt;
-    }
-    else {
-        optionlist_sorted_by_order = opt;
-    }
+  // prepend opt to optionlist_sorted_by_order
+  // (0 is always at the beginning)
+  if (optionlist_sorted_by_order)
+  {
+    opt->next_by_order = optionlist_sorted_by_order;
+    optionlist_sorted_by_order = opt;
+  }
+  else
+    optionlist_sorted_by_order = opt;
 
-    _log("Added option %s\n", opt->name);
-    return opt;
+  _log("Added option %s\n", opt->name);
+  return (opt);
 }
 
-/* This functions checks if "opt" is named "name", or if it has any
-   alternative names "name" (e.g. PageSize / PageRegion) */
-int option_has_name(option_t *opt, const char *name)
+
+// This functions checks if "opt" is named "name", or if it has any
+// alternative names "name" (e.g. PageSize / PageRegion)
+int
+option_has_name(option_t *opt,
+               const char *name)
 {
-    if (!strcmp(opt->name, name))
-        return 1;
+  if (!strcmp(opt->name, name))
+    return (1);
 
-    if (!strcmp(opt->name, "PageSize") && !strcmp(name, "PageRegion"))
-        return 1;
+  if (!strcmp(opt->name, "PageSize") && !strcmp(name, "PageRegion"))
+    return (1);
 
-    return 0;
+  return (0);
 }
 
-int option_is_composite(option_t *opt)
+
+int
+option_is_composite(option_t *opt)
 {
-    return opt ? (opt->style == 'X') : 0;
+  return (opt ? (opt->style == 'X') : 0);
 }
 
-int option_is_ps_command(option_t *opt)
+
+int
+option_is_ps_command(option_t *opt)
 {
-    return opt->style == 'G';
+  return (opt->style == 'G');
 }
 
-int option_is_jcl_arg(option_t *opt)
+
+int
+option_is_jcl_arg(option_t *opt)
 {
-    return opt->style == 'J';
+  return (opt->style == 'J');
 }
 
-int option_is_commandline_arg(option_t *opt)
+
+int
+option_is_commandline_arg(option_t *opt)
 {
-    return opt->style == 'C';
+  return (opt->style == 'C');
 }
 
-int option_get_section(option_t *opt)
+
+int
+option_get_section(option_t *opt)
 {
-    return opt->section;
+  return (opt->section);
 }
 
-static value_t * option_find_value(option_t *opt, int optionset)
+
+static value_t *
+option_find_value(option_t *opt,
+                 int optionset)
 {
-    value_t *val;
+  value_t *val;
 
-    if (!opt)
-        return NULL;
+  if (!opt)
+    return (NULL);
 
-    for (val = opt->valuelist; val; val = val->next) {
-        if (val->optionset == optionset)
-            return val;
-    }
-    return NULL;
+  for (val = opt->valuelist; val; val = val->next)
+  {
+    if (val->optionset == optionset)
+      return (val);
+  }
+  return (NULL);
 }
 
-static value_t * option_assure_value(option_t *opt, int optionset)
+
+static value_t *
+option_assure_value(option_t *opt,
+                   int optionset)
 {
-    value_t *val, *last;
-    val = option_find_value(opt, optionset);
-    if (!val) {
-        val = calloc(1, sizeof(value_t));
-        val->optionset = optionset;
+  value_t *val, *last;
 
-        /* append to opt->valuelist */
-        if (opt->valuelist) {
-            for (last = opt->valuelist; last->next; last = last->next);
-            last->next = val;
-        }
-        else
-            opt->valuelist = val;
+  val = option_find_value(opt, optionset);
+  if (!val)
+  {
+    val = calloc(1, sizeof(value_t));
+    val->optionset = optionset;
+
+    // append to opt->valuelist
+    if (opt->valuelist)
+    {
+      for (last = opt->valuelist; last->next; last = last->next);
+      last->next = val;
     }
-    return val;
+    else
+      opt->valuelist = val;
+  }
+  return (val);
 }
 
-static param_t * option_find_param_index(option_t *opt, const char *name, int *idx)
+
+static param_t *
+option_find_param_index(option_t *opt,
+                       const char *name,
+                       int *idx)
 {
-    param_t *param;
-    int i;
-    for (param = opt->paramlist, i = 0; param; param = param->next, i += 1) {
-        if (!strcasecmp(param->name, name)) {
-            if (idx)
-                *idx = i;
-            return param;
-        }
+  param_t *param;
+  int i;
+  for (param = opt->paramlist, i = 0; param; param = param->next, i += 1)
+  {
+    if (!strcasecmp(param->name, name))
+    {
+      if (idx)
+       *idx = i;
+      return (param);
+    }
+  }
+  if (idx)
+    *idx = -1;
+  return (0);
+}
+
+static choice_t *
+option_find_choice(option_t *opt,
+                  const char *name)
+{
+  choice_t *choice;
+  if (!opt || !name)
+    return (NULL);
+  for (choice = opt->choicelist; choice; choice = choice->next)
+  {
+    if (!strcasecmp(choice->value, name))
+      return (choice);
+  }
+  return (NULL);
+}
+
+
+void
+free_paramvalues(option_t *opt,
+                char **paramvalues)
+{
+  int i;
+  if (!paramvalues)
+    return;
+  for (i = 0; i < opt->param_count; i++)
+    free(paramvalues[i]);
+  free(paramvalues);
+}
+
+
+char *
+get_valid_param_string(option_t *opt,
+                      param_t *param,
+                      const char *str)
+{
+  char *result;
+  int i, imin, imax;
+  float f, fmin, fmax;
+  size_t len;
+
+  switch (param->type)
+  {
+    case TYPE_INT:
+        i = atoi(str);
+       imin = !isempty(param->min) ? atoi(param->min) : -999999;
+       imax = !isempty(param->max) ? atoi(param->max) : 1000000;
+       if (i < imin)
+       {
+         _log("Value \"%s\" for option \"%s\", parameter \"%s\" is smaller than the minimum value \"%d\"\n",
+              str, opt->name, param->name, imin);
+         return (NULL);
+       }
+       else if (i > imax)
+       {
+         _log("Value \"%s\" for option \"%s\", parameter \"%s\" is larger than the maximum value \"%d\"\n",
+              str, opt->name, param->name, imax);
+         return (NULL);
+       }
+       result = malloc(32);
+       snprintf(result, 32, "%d", i);
+       return (result);
+
+    case TYPE_FLOAT:
+    case TYPE_CURVE:
+    case TYPE_INVCURVE:
+    case TYPE_POINTS:
+        f = atof(str);
+       fmin = !isempty(param->min) ? atof(param->min) : -999999.0;
+       fmax = !isempty(param->max) ? atof(param->max) : 1000000.0;
+       if (f < fmin)
+       {
+         _log("Value \"%s\" for option \"%s\", parameter \"%s\" is smaller than the minimum value \"%d\"\n",
+              str, opt->name, param->name, fmin);
+         return (NULL);
+       }
+       else if (f > fmax)
+       {
+         _log("Value \"%s\" for option \"%s\", parameter \"%s\" is larger than the maximum value \"%d\"\n",
+              str, opt->name, param->name, fmax);
+         return (NULL);
+       }
+       result = malloc(32);
+       snprintf(result, 32, "%f", f);
+       return (result);
+
+    case TYPE_STRING:
+    case TYPE_PASSWORD:
+    case TYPE_PASSCODE:
+        if (param->allowedchars &&
+           regexec(param->allowedchars, str, 0, NULL, 0) != 0)
+       {
+         _log("Custom string \"%s\" for \"%s\", parameter \"%s\" contains illegal characters.\n",
+              str, opt->name, param->name);
+         return (NULL);
+       }
+       if (param->allowedregexp &&
+           regexec(param->allowedregexp, str, 0, NULL, 0) != 0)
+       {
+         _log("Custom string \"%s\" for \"%s\", parameter \"%s\" does not match the allowed regexp.\n",
+              str, opt->name, param->name);
+         return (NULL);
+       }
+       len = strlen(str);
+       if (!isempty(param->min) && len < atoi(param->min))
+       {
+         _log("Custom value \"%s\" is too short for option \"%s\", parameter \"%s\".\n",
+              str, opt->name, param->name);
+         return (NULL);
+       }
+       if (!isempty(param->max) && len > atoi(param->max))
+       {
+         _log("Custom value \"%s\" is too long for option \"%s\", parameter \"%s\".\n",
+              str, opt->name, param->name);
+         return (NULL);
+       }
+       return (strdup(str));
+  }
+  return (NULL);
+}
+
+
+char *
+get_valid_param_string_int(option_t *opt,
+                          param_t *param,
+                          int value)
+{
+  char str[20];
+  snprintf(str, 20, "%d", value);
+  return (get_valid_param_string(opt, param, str));
+}
+
+
+char *
+get_valid_param_string_float(option_t *opt,
+                            param_t *param,
+                            float value)
+{
+  char str[20];
+  snprintf(str, 20, "%f", value);
+  return (get_valid_param_string(opt, param, str));
+}
+
+
+float
+convert_to_points(float f,
+                 const char *unit)
+{
+  if (!strcasecmp(unit, "pt"))
+    return (roundf(f));
+  if (!strcasecmp(unit, "in"))
+    return (roundf(f * 72.0));
+  if (!strcasecmp(unit, "cm"))
+    return (roundf(f * 72.0 / 2.54));
+  if (!strcasecmp(unit, "mm"))
+    return (roundf(f * 72.0 / 25.4));
+
+  _log("Unknown unit: \"%s\"\n", unit);
+  return (roundf(f));
+}
+
+
+static char **
+paramvalues_from_string(option_t *opt,
+                       const char *str)
+{
+  char **paramvalues;
+  int n, i;
+  param_t *param;
+  char *copy, *cur, *p;
+  float width, height;
+  char unit[3];
+
+  if (!strcmp(opt->name, "PageSize"))
+  {
+    if (startswith(str, "Custom."))
+      str = &str[7];
+    // 'unit' is optional, if it is not given, 'pt' is assumed
+    n = sscanf(str, "%fx%f%2s", &width, &height, unit);
+    if (n > 1)
+    {
+      if (n == 3)
+      {
+       width = convert_to_points(width, unit);
+       height = convert_to_points(height, unit);
+      }
+      paramvalues = calloc(opt->param_count, sizeof(char*));
+      for (param = opt->paramlist, i = 0; param; param = param->next, i++)
+      {
+       if (!strcasecmp(param->name, "width"))
+         paramvalues[i] = get_valid_param_string_int(opt, param, (int)width);
+       else if (!strcasecmp(param->name, "height"))
+         paramvalues[i] = get_valid_param_string_int(opt, param, (int)height);
+       else
+         paramvalues[i] = !isempty(param->min) ? param->min : "-999999";
+       if (!paramvalues[i])
+       {
+         free_paramvalues(opt, paramvalues);
+         return (NULL);
+       }
+      }
+      return (paramvalues);
+    }
+  }
+
+  if (opt->param_count == 1)
+  {
+    paramvalues = malloc(sizeof(char*));
+    paramvalues[0] =
+      get_valid_param_string(opt, opt->paramlist,
+                            startswith(str, "Custom.") ? &str[7] : str);
+    if (!paramvalues[0])
+    {
+      free(paramvalues);
+      return (NULL);
+    }
+  }
+  else
+  {
+    if (!(p = strchr(str, '{')))
+      return (NULL);
+    paramvalues = calloc(opt->param_count, sizeof(char*));
+    copy = strdup(p +1);
+    for (cur = strtok(copy, " \t}"); cur; cur = strtok(NULL, " \t}"))
+    {
+      p = strchr(cur, '=');
+      if (!p)
+       continue;
+      *p++ = '\0';
+      if ((param = option_find_param_index(opt, cur, &i)))
+       paramvalues[i] = get_valid_param_string(opt, param, p);
+      else
+       _log("Could not find param \"%s\" for option \"%s\"\n",
+            cur, opt->name);
     }
-    if (idx)
-        *idx = -1;
-    return 0;
-}
+    free(copy);
 
-static choice_t * option_find_choice(option_t *opt, const char *name)
-{
-    choice_t *choice;
-    if (!opt || !name)
-      return NULL;
-    for (choice = opt->choicelist; choice; choice = choice->next) {
-        if (!strcasecmp(choice->value, name))
-            return choice;
+    // check if all params have been set
+    for (i = 0; i < opt->param_count; i++)
+    {
+      if (!paramvalues[i])
+      {
+       free_paramvalues(opt, paramvalues);
+       return (NULL);
+      }
+    }
+  }
+  return (paramvalues);
+}
+
+
+char *
+paramvalues_to_string(option_t *opt,
+                     char **paramvalues)
+{
+  int i;
+  param_t *param;
+  dstr_t *res = create_dstr();
+  char *data;
+
+  if (opt->param_count < 1)
+  {
+    free (res);
+    return (NULL);
+  }
+
+  if (opt->param_count == 1)
+  {
+    param = opt->paramlist;
+    dstrcpyf(res, "Custom.%s", paramvalues[0]);
+  }
+  else
+  {
+    dstrcpyf(res, "{%s=%s", opt->paramlist->name, paramvalues[0]);
+    param = opt->paramlist->next;
+    i = 1;
+    while (param)
+    {
+      dstrcatf(res, " %s=%s", param->name, paramvalues[i]);
+      i++;
+      param = param->next;
     }
-    return NULL;
+    dstrcat(res, "}");
+  }
+  // only free dstr struct, NOT the string data
+  data = res->data;
+  free(res);
+  return (data);
 }
 
-void free_paramvalues(option_t *opt, char **paramvalues)
+
+char *
+get_valid_value_string(option_t *opt,
+                      const char *value)
 {
-    int i;
-    if (!paramvalues)
-        return;
-    for (i = 0; i < opt->param_count; i++)
-        free(paramvalues[i]);
-    free(paramvalues);
-}
-
-char * get_valid_param_string(option_t *opt, param_t *param, const char *str)
-{
-    char *result;
-    int i, imin, imax;
-    float f, fmin, fmax;
-    size_t len;
-
-    switch (param->type) {
-        case TYPE_INT:
-            i = atoi(str);
-            imin = !isempty(param->min) ? atoi(param->min) : -999999;
-            imax = !isempty(param->max) ? atoi(param->max) : 1000000;
-            if (i < imin) {
-                _log("Value \"%s\" for option \"%s\", parameter \"%s\" is smaller than the minimum value \"%d\"\n",
-                     str, opt->name, param->name, imin);
-                return NULL;
-            }
-            else if (i > imax) {
-                _log("Value \"%s\" for option \"%s\", parameter \"%s\" is larger than the maximum value \"%d\"\n",
-                     str, opt->name, param->name, imax);
-                return NULL;
-            }
-            result = malloc(32);
-            snprintf(result, 32, "%d", i);
-            return result;
-
-        case TYPE_FLOAT:
-        case TYPE_CURVE:
-        case TYPE_INVCURVE:
-        case TYPE_POINTS:
-            f = atof(str);
-            fmin = !isempty(param->min) ? atof(param->min) : -999999.0;
-            fmax = !isempty(param->max) ? atof(param->max) : 1000000.0;
-            if (f < fmin) {
-                _log("Value \"%s\" for option \"%s\", parameter \"%s\" is smaller than the minimum value \"%d\"\n",
-                     str, opt->name, param->name, fmin);
-                return NULL;
-            }
-            else if (f > fmax) {
-                _log("Value \"%s\" for option \"%s\", parameter \"%s\" is larger than the maximum value \"%d\"\n",
-                     str, opt->name, param->name, fmax);
-                return NULL;
-             }
-            result = malloc(32);
-            snprintf(result, 32, "%f", f);
-            return result;
-
-        case TYPE_STRING:
-        case TYPE_PASSWORD:
-        case TYPE_PASSCODE:
-            if (param->allowedchars &&
-                    regexec(param->allowedchars, str, 0, NULL, 0) != 0) {
-                _log("Custom string \"%s\" for \"%s\", parameter \"%s\" contains illegal characters.\n",
-                    str, opt->name, param->name);
-                return NULL;
-            }
-            if (param->allowedregexp &&
-                    regexec(param->allowedregexp, str, 0, NULL, 0) != 0) {
-                _log("Custom string \"%s\" for \"%s\", parameter \"%s\" does not match the allowed regexp.\n",
-                    str, opt->name, param->name);
-                return NULL;
-            }
-            len = strlen(str);
-            if (!isempty(param->min) && len < atoi(param->min)) {
-                _log("Custom value \"%s\" is too short for option \"%s\", parameter \"%s\".\n",
-                    str, opt->name, param->name);
-                return NULL;
-            }
-            if (!isempty(param->max) && len > atoi(param->max)) {
-                _log("Custom value \"%s\" is too long for option \"%s\", parameter \"%s\".\n",
-                    str, opt->name, param->name);
-                return NULL;
-            }
-            return strdup(str);
-    }
-    return NULL;
-}
-
-char * get_valid_param_string_int(option_t *opt, param_t *param, int value)
-{
-    char str[20];
-    snprintf(str, 20, "%d", value);
-    return get_valid_param_string(opt, param, str);
-}
-
-char * get_valid_param_string_float(option_t *opt, param_t *param, float value)
-{
-    char str[20];
-    snprintf(str, 20, "%f", value);
-    return get_valid_param_string(opt, param, str);
-}
-
-float convert_to_points(float f, const char *unit)
-{
-    if (!strcasecmp(unit, "pt"))
-        return roundf(f);
-    if (!strcasecmp(unit, "in"))
-        return roundf(f * 72.0);
-    if (!strcasecmp(unit, "cm"))
-        return roundf(f * 72.0 / 2.54);
-    if (!strcasecmp(unit, "mm"))
-        return roundf(f * 72.0 / 25.4);
-
-    _log("Unknown unit: \"%s\"\n", unit);
-    return roundf(f);
-}
-
-static char ** paramvalues_from_string(option_t *opt, const char *str)
-{
-    char ** paramvalues;
-    int n, i;
-    param_t *param;
-    char *copy, *cur, *p;
-    float width, height;
-    char unit[3];
-
-    if (!strcmp(opt->name, "PageSize"))
-    {
-        if (startswith(str, "Custom."))
-            str = &str[7];
-        /* 'unit' is optional, if it is not given, 'pt' is assumed */
-        n = sscanf(str, "%fx%f%2s", &width, &height, unit);
-        if (n > 1) {
-            if (n == 3) {
-                width = convert_to_points(width, unit);
-                height = convert_to_points(height, unit);
-            }
-            paramvalues = calloc(opt->param_count, sizeof(char*));
-            for (param = opt->paramlist, i = 0; param; param = param->next, i++) {
-                if (!strcasecmp(param->name, "width"))
-                    paramvalues[i] = get_valid_param_string_int(opt, param, (int)width);
-                else if (!strcasecmp(param->name, "height"))
-                    paramvalues[i] = get_valid_param_string_int(opt, param, (int)height);
-                else
-                    paramvalues[i] = !isempty(param->min) ? param->min : "-999999";
-                if (!paramvalues[i]) {
-                    free_paramvalues(opt, paramvalues);
-                    return NULL;
-                }
-            }
-            return paramvalues;
-        }
-    }
-
-    if (opt->param_count == 1) {
-        paramvalues = malloc(sizeof(char*));
-        paramvalues[0] = get_valid_param_string(opt, opt->paramlist,
-            startswith(str, "Custom.") ? &str[7] : str);
-        if (!paramvalues[0]) {
-            free(paramvalues);
-            return NULL;
-        }
-    }
-    else {
-        if (!(p = strchr(str, '{')))
-            return NULL;
-        paramvalues = calloc(opt->param_count, sizeof(char*));
-        copy = strdup(p +1);
-        for (cur = strtok(copy, " \t}"); cur; cur = strtok(NULL, " \t}")) {
-            p = strchr(cur, '=');
-            if (!p)
-                continue;
-            *p++ = '\0';
-            if ((param = option_find_param_index(opt, cur, &i)))
-                paramvalues[i] = get_valid_param_string(opt, param, p);
-            else
-                _log("Could not find param \"%s\" for option \"%s\"\n",
-                    cur, opt->name);
-        }
-        free(copy);
-
-        /* check if all params have been set */
-        for (i = 0; i < opt->param_count; i++) {
-            if (!paramvalues[i]) {
-                free_paramvalues(opt, paramvalues);
-                return NULL;
-            }
-        }
-    }
-    return paramvalues;
-}
-
-char * paramvalues_to_string(option_t *opt, char **paramvalues)
-{
-    int i;
-    param_t *param;
-    dstr_t *res = create_dstr();
-    char *data;
-
-    if (opt->param_count < 1) {
-        free (res);
-        return NULL;
-    }
-
-    if (opt->param_count == 1) {
-        param = opt->paramlist;
-        dstrcpyf(res, "Custom.%s", paramvalues[0]);
-    }
-    else {
-        dstrcpyf(res, "{%s=%s", opt->paramlist->name, paramvalues[0]);
-        param = opt->paramlist->next;
-        i = 1;
-        while (param) {
-            dstrcatf(res, " %s=%s", param->name, paramvalues[i]);
-            i++;
-            param = param->next;
-        }
-        dstrcat(res, "}");
-    }
-    /* only free dstr struct, NOT the string data */
-    data = res->data;
-    free(res);
-    return data;
-}
-
-char * get_valid_value_string(option_t *opt, const char *value)
-{
-    char *res;
-    choice_t *choice;
-    char **paramvalues;
-
-    if (!value)
-        return NULL;
-
-    if (startswith(value, "From") && option_is_composite(find_option(&value[4])))
-        return strdup(value);
-
-    if (opt->type == TYPE_BOOL) {
-        if (is_true_string(value))
-            return strdup("1");
-        else if (is_false_string(value))
-            return strdup("0");
-        else {
-            _log("Could not interpret \"%s\" as boolean value for option \"%s\".\n", value, opt->name);
-            return NULL;
-        }
-    }
+  char *res;
+  choice_t *choice;
+  char **paramvalues;
 
-    /* Check if "value" is a predefined choice (except for "Custom", which is
-     * not really a predefined choice, but an error if used without further
-     * parameters) */
-    if ((strcmp(value, "Custom") != 0 || strcmp(opt->name, "PageSize") == 0) &&
-       (choice = option_find_choice(opt, value)))
-        return strdup(choice->value);
+  if (!value)
+    return (NULL);
 
-    if (opt->type == TYPE_ENUM) {
-        if (!strcasecmp(value, "none"))
-            return strdup("None");
+  if (startswith(value, "From") && option_is_composite(find_option(&value[4])))
+    return (strdup(value));
 
-        /*
-         * CUPS assumes that options with the choices "Yes", "No", "On", "Off",
-         * "True", or "False" are boolean options and maps "-o Option=On" to
-         * "-o Option" and "-o Option=Off" to "-o noOption", which foomatic-rip
-         * maps to "0" and "1".  So when "0" or "1" is unavailable in the
-         * option, we try "Yes", "No", "On", "Off", "True", and "False". 
-         */
-        if (is_true_string(value)) {
-            for (choice = opt->choicelist; choice; choice = choice->next) {
-                if (is_true_string(choice->value))
-                    return strdup(choice->value);
-            }
-        }
-        else if (is_false_string(value)) {
-            for (choice = opt->choicelist; choice; choice = choice->next) {
-                if (is_false_string(choice->value))
-                    return strdup(choice->value);
-            }
-        }
+  if (opt->type == TYPE_BOOL)
+  {
+    if (is_true_string(value))
+      return (strdup("1"));
+    else if (is_false_string(value))
+      return (strdup("0"));
+    else
+    {
+      _log("Could not interpret \"%s\" as boolean value for option \"%s\".\n", value, opt->name);
+      return (NULL);
+    }
+  }
+
+  // Check if "value" is a predefined choice (except for "Custom", which is
+  // not really a predefined choice, but an error if used without further
+  // parameters)
+  if ((strcmp(value, "Custom") != 0 || strcmp(opt->name, "PageSize") == 0) &&
+      (choice = option_find_choice(opt, value)))
+    return (strdup(choice->value));
+
+  if (opt->type == TYPE_ENUM)
+  {
+    if (!strcasecmp(value, "none"))
+      return (strdup("None"));
+
+    //
+    // CUPS assumes that options with the choices "Yes", "No", "On", "Off",
+    // "True", or "False" are boolean options and maps "-o Option=On" to
+    // "-o Option" and "-o Option=Off" to "-o noOption", which foomatic-rip
+    // maps to "0" and "1".  So when "0" or "1" is unavailable in the
+    // option, we try "Yes", "No", "On", "Off", "True", and "False". 
+  
+    if (is_true_string(value))
+    {
+      for (choice = opt->choicelist; choice; choice = choice->next)
+      {
+       if (is_true_string(choice->value))
+         return (strdup(choice->value));
+      }
     }
-
-    /* Custom value */
-    if (opt->paramlist) {
-        paramvalues = paramvalues_from_string(opt, value);
-        if (paramvalues) {
-            res = paramvalues_to_string(opt, paramvalues);
-            free(paramvalues);
-            return (startswith(res, "Custom.") ? strdup(&res[7]) : strdup(res));
-        }
+    else if (is_false_string(value))
+    {
+      for (choice = opt->choicelist; choice; choice = choice->next)
+      {
+       if (is_false_string(choice->value))
+         return (strdup(choice->value));
+      }
+    }
+  }
+
+  // Custom value
+  if (opt->paramlist)
+  {
+    paramvalues = paramvalues_from_string(opt, value);
+    if (paramvalues)
+    {
+      res = paramvalues_to_string(opt, paramvalues);
+      free(paramvalues);
+      return (startswith(res, "Custom.") ? strdup(&res[7]) : strdup(res));
     }
-    else if (opt->foomatic_param)
-        return get_valid_param_string(opt, opt->foomatic_param,
-                              startswith(value, "Custom.") ? &value[7] : value);
+  }
+  else if (opt->foomatic_param)
+    return (get_valid_param_string(opt, opt->foomatic_param,
+                                  startswith(value, "Custom.") ?
+                                  &value[7] : value));
 
-    /* Return the default value */
-    return NULL;
+  // Return the default value
+  return (NULL);
 }
 
-/* Returns the current value for 'opt' in 'optionset'. */
-const char * option_get_value(option_t *opt, int optionset)
+
+// Returns the current value for 'opt' in 'optionset'.
+const char *
+option_get_value(option_t *opt, int optionset)
 {
-    value_t *val = option_find_value(opt, optionset);
-    return val ? val->value : NULL;
+  value_t *val = option_find_value(opt, optionset);
+  return (val ? val->value : NULL);
 }
 
-/* Returns non-zero if the foomatic prototype should be used for that
- * optionset, otherwise the custom_command will be used */
-int option_use_foomatic_prototype(option_t *opt)
+
+// Returns non-zero if the foomatic prototype should be used for that
+// optionset, otherwise the custom_command will be used
+int
+option_use_foomatic_prototype(option_t *opt)
 {
-    /* Only PostScript and JCL options can be CUPS custom options */
-    if (!option_is_ps_command(opt) && !option_is_jcl_arg(opt))
-        return 1;
+  // Only PostScript and JCL options can be CUPS custom options
+  if (!option_is_ps_command(opt) && !option_is_jcl_arg(opt))
+    return (1);
 
-    /* if only one of them exists, take that one */
-    if (opt->custom_command && !opt->proto)
-        return 0;
-    if (!opt->custom_command && opt->proto)
-        return 1;
-    return 0;
+  // if only one of them exists, take that one
+  if (opt->custom_command && !opt->proto)
+    return (0);
+  if (!opt->custom_command && opt->proto)
+    return (1);
+  return (0);
 }
 
-void build_foomatic_custom_command(dstr_t *cmd, option_t *opt, const char *values)
+
+void
+build_foomatic_custom_command(dstr_t *cmd,
+                             option_t *opt,
+                             const char *values)
 {
-    if (!opt->proto && !strcmp(opt->name, "PageSize"))
-    {
-        choice_t *choice = option_find_choice(opt, "Custom");
-        char **paramvalues = NULL;
-        char width[30], height[30];
-        int pos;
+  if (!opt->proto && !strcmp(opt->name, "PageSize"))
+  {
+    choice_t *choice = option_find_choice(opt, "Custom");
+    char **paramvalues = NULL;
+    char width[30], height[30];
+    int pos;
 
-        if (!choice)
-         return;
+    if (!choice)
+      return;
 
-       paramvalues = paramvalues_from_string(opt, values);
+    paramvalues = paramvalues_from_string(opt, values);
 
-        /* Get rid of the trailing ".00000", it confuses ghostscript */
-        snprintf(width, 20, "%d", atoi(paramvalues[0]));
-        snprintf(height, 20, "%d", atoi(paramvalues[1]));
+    // Get rid of the trailing ".00000", it confuses ghostscript
+    snprintf(width, 20, "%d", atoi(paramvalues[0]));
+    snprintf(height, 20, "%d", atoi(paramvalues[1]));
 
-        dstrcpy(cmd, choice->command);
+    dstrcpy(cmd, choice->command);
 
-        if ((pos = dstrreplace(cmd, "%0", width, 0)) < 0)
-            pos = dstrreplace(cmd, "0", width, 0);
+    if ((pos = dstrreplace(cmd, "%0", width, 0)) < 0)
+      pos = dstrreplace(cmd, "0", width, 0);
 
-        if (dstrreplace(cmd, "%1", height, pos) < 0)
-            dstrreplace(cmd, "0", height, pos);
+    if (dstrreplace(cmd, "%1", height, pos) < 0)
+      dstrreplace(cmd, "0", height, pos);
 
-        free_paramvalues(opt, paramvalues);
+    free_paramvalues(opt, paramvalues);
+  }
+  else
+  {
+    dstrcpy(cmd, opt->proto);
+    // use replace instead of printf-style because opt->proto could contain
+    // other format strings
+    dstrreplace(cmd, "%s", values, 0);
+  }
+}
+
+
+void
+build_cups_custom_ps_command(dstr_t *cmd, option_t *opt,
+                            const char *values)
+{
+  param_t *param;
+  int i;
+  char **paramvalues = paramvalues_from_string(opt, values);
+
+  dstrclear(cmd);
+  for (param = opt->paramlist, i = 0; param; param = param->next, i++)
+    dstrcatf(cmd, "%s ", paramvalues[i]);
+  dstrcat(cmd, opt->custom_command);
+  free_paramvalues(opt, paramvalues);
+}
+
+
+void
+build_cups_custom_jcl_command(dstr_t *cmd,
+                             option_t *opt,
+                             const char *values)
+{
+  param_t *param;
+  int i;
+  char orderstr[8];
+  char **paramvalues = paramvalues_from_string(opt, values);
+
+  dstrcpy(cmd, opt->custom_command);
+  for (param = opt->paramlist, i = 0; param; param = param->next, i++)
+  {
+    snprintf(orderstr, 8, "\\%d", param->order);
+    dstrreplace(cmd, orderstr, paramvalues[i], 0);
+  }
+  free_paramvalues(opt, paramvalues);
+}
+
+
+int
+composite_get_command(dstr_t *cmd,
+                     option_t *opt,
+                     int optionset,
+                     int section)
+{
+  char *copy, *cur, *p;
+  option_t *dep;
+  const char * valstr;
+  dstr_t *depcmd;
+
+  dstrclear(cmd);
+  if (!option_is_composite(opt))
+    return (0);
+
+  if (!(valstr = option_get_value(opt, optionset)))
+    return (0);
+
+  depcmd = create_dstr();
+  copy = strdup(valstr);
+  // Dependent options have been set to the right value in composite_set_values,
+  // so just find out which options depend on this composite and get their
+  // commands for "optionset" with option_get_command()
+  for (cur = strtok(copy, " \t"); cur; cur = strtok(NULL, " \t"))
+  {
+    dstrclear(depcmd);
+    if ((p = strchr(cur, '=')))
+    {
+      *p++ = '\0';
+      if ((dep = find_option(cur)))
+       option_get_command(depcmd, dep, optionset, section);
+    }
+    else if (startswith(cur, "no") || startswith(cur, "No"))
+    {
+      if ((dep = find_option(&cur[2])))
+       option_get_command(depcmd, dep, optionset, section);
     }
     else
     {
-        dstrcpy(cmd, opt->proto);
-        /* use replace instead of printf-style because opt->proto could contain
-           other format strings */
-        dstrreplace(cmd, "%s", values, 0);
+      if ((dep = find_option(cur)))
+       option_get_command(depcmd, dep, optionset, section);
     }
+    if (depcmd->len)
+      dstrcatf(cmd, "%s\n", depcmd->data);
+  }
+  free(copy);
+  free_dstr(depcmd);
+  return (cmd->len != 0);
 }
 
-void build_cups_custom_ps_command(dstr_t *cmd, option_t *opt, const char *values)
-{
-    param_t *param;
-    int i;
-    char **paramvalues = paramvalues_from_string(opt, values);
 
-    dstrclear(cmd);
-    for (param = opt->paramlist, i = 0; param; param = param->next, i++)
-        dstrcatf(cmd, "%s ", paramvalues[i]);
-    dstrcat(cmd, opt->custom_command);
-    free_paramvalues(opt, paramvalues);
+int
+option_is_in_section(option_t *opt,
+                    int section)
+{
+  if (opt->section == section)
+    return (1);
+  if (opt->section == SECTION_ANYSETUP &&
+      (section == SECTION_PAGESETUP || section == SECTION_DOCUMENTSETUP))
+    return (1);
+  return (0);
 }
 
-void build_cups_custom_jcl_command(dstr_t *cmd, option_t *opt, const char *values)
+
+int
+option_is_custom_value(option_t *opt,
+                      const char *value)
 {
-    param_t *param;
-    int i;
-    char orderstr[8];
-    char **paramvalues = paramvalues_from_string(opt, values);
+  if (opt->type == TYPE_BOOL || opt->type == TYPE_ENUM)
+    return (0);
 
-    dstrcpy(cmd, opt->custom_command);
-    for (param = opt->paramlist, i = 0; param; param = param->next, i++) {
-        snprintf(orderstr, 8, "\\%d", param->order);
-        dstrreplace(cmd, orderstr, paramvalues[i], 0);
-    }
-    free_paramvalues(opt, paramvalues);
+  return (!option_has_choice(opt, value));
 }
 
-int composite_get_command(dstr_t *cmd, option_t *opt, int optionset, int section)
-{
-    char *copy, *cur, *p;
-    option_t *dep;
-    const char * valstr;
-    dstr_t *depcmd;
-
-    dstrclear(cmd);
-    if (!option_is_composite(opt))
-        return 0;
-
-    if (!(valstr = option_get_value(opt, optionset)))
-        return 0;
-
-    depcmd = create_dstr();
-    copy = strdup(valstr);
-    /* Dependent options have been set to the right value in composite_set_values,
-       so just find out which options depend on this composite and get their commands
-       for "optionset" with option_get_command() */
-    for (cur = strtok(copy, " \t"); cur; cur = strtok(NULL, " \t")) {
-        dstrclear(depcmd);
-        if ((p = strchr(cur, '='))) {
-            *p++ = '\0';
-            if ((dep = find_option(cur)))
-                option_get_command(depcmd, dep, optionset, section);
-        }
-        else if (startswith(cur, "no") || startswith(cur, "No")) {
-            if ((dep = find_option(&cur[2])))
-                option_get_command(depcmd, dep, optionset, section);
-            }
-        else {
-            if ((dep = find_option(cur)))
-                option_get_command(depcmd, dep, optionset, section);
-        }
-        if (depcmd->len)
-            dstrcatf(cmd, "%s\n", depcmd->data);
-    }
-    free(copy);
-    free_dstr(depcmd);
-    return cmd->len != 0;
-}
 
-int option_is_in_section(option_t *opt, int section)
+int
+option_get_command(dstr_t *cmd,
+                  option_t *opt,
+                  int optionset,
+                  int section)
 {
-    if (opt->section == section)
-        return 1;
-    if (opt->section == SECTION_ANYSETUP && (section == SECTION_PAGESETUP || section == SECTION_DOCUMENTSETUP))
-        return 1;
-    return 0;
-}
+  const char *valstr;
+  choice_t *choice = NULL;
 
-int option_is_custom_value(option_t *opt, const char *value)
-{
-    if (opt->type == TYPE_BOOL || opt->type == TYPE_ENUM)
-        return 0;
+  dstrclear(cmd);
 
-    return !option_has_choice(opt, value);
+  if (option_is_composite(opt))
+    return (composite_get_command(cmd, opt, optionset, section));
+
+  if (section >= 0 && !option_is_in_section(opt, section))
+    return (1); // empty command for this section
+
+  valstr = option_get_value(opt, optionset);
+  if (!valstr)
+    return (0);
+
+  // If the value is set to a predefined choice
+  choice = option_find_choice(opt, valstr);
+  if (choice && (*choice->command ||
+                ((opt->type != TYPE_INT) && (opt->type != TYPE_FLOAT))))
+  {
+    dstrcpy(cmd, choice->command);
+    return (1);
+  }
+
+  // Consider "None" as "not set" for enumerated choice options
+  if (opt->type == TYPE_ENUM && !strcasecmp(valstr, "None"))
+    return (0);
+
+  // Consider "None" as the empty string for string and password options
+  if ((opt->type == TYPE_STRING || opt->type == TYPE_PASSWORD) &&
+      !strcasecmp(valstr, "None"))
+    valstr = "";
+
+  // Custom value
+  if (option_use_foomatic_prototype(opt))
+    build_foomatic_custom_command(cmd, opt, valstr);
+  else
+  {
+    dstrcpy(cmd, opt->custom_command);
+    if ((option_get_section(opt) == SECTION_JCLSETUP) ||
+       (opt->style == 'J'))
+      build_cups_custom_jcl_command(cmd, opt, valstr);
+    else
+      build_cups_custom_ps_command(cmd, opt, valstr);
+  }
+
+  return (cmd->len != 0);
 }
 
-int option_get_command(dstr_t *cmd, option_t *opt, int optionset, int section)
-{
-    const char *valstr;
-    choice_t *choice = NULL;
 
-    dstrclear(cmd);
+void
+composite_set_values(option_t *opt,
+                    int optionset,
+                    const char *values)
+{
+  char *copy, *cur, *p;
+  option_t *dep;
+  value_t *val;
 
-    if (option_is_composite(opt))
-        return composite_get_command(cmd, opt, optionset, section);
-
-    if (section >= 0 && !option_is_in_section(opt, section))
-        return 1; /* empty command for this section */
-
-    valstr = option_get_value(opt, optionset);
-    if (!valstr)
-        return 0;
-
-    /* If the value is set to a predefined choice */
-    choice = option_find_choice(opt, valstr);
-    if (choice && (*choice->command ||
-                  ((opt->type != TYPE_INT) && (opt->type != TYPE_FLOAT)))) {
-        dstrcpy(cmd, choice->command);
-        return 1;
-    }
-
-    /* Consider "None" as "not set" for enumerated choice options */
-    if (opt->type == TYPE_ENUM && !strcasecmp(valstr, "None"))
-        return 0;
-
-    /* Consider "None" as the empty string for string and password options */
-    if ((opt->type == TYPE_STRING || opt->type == TYPE_PASSWORD) &&
-       !strcasecmp(valstr, "None"))
-        valstr = "";
-
-    /* Custom value */
-    if (option_use_foomatic_prototype(opt))
-       build_foomatic_custom_command(cmd, opt, valstr);
-    else {
-       dstrcpy(cmd, opt->custom_command);
-       if ((option_get_section(opt) == SECTION_JCLSETUP) ||
-           (opt->style == 'J'))
-           build_cups_custom_jcl_command(cmd, opt, valstr);
-       else
-         build_cups_custom_ps_command(cmd, opt, valstr);
-    }
-
-    return cmd->len != 0;
-}
-
-void composite_set_values(option_t *opt, int optionset, const char *values)
-{
-    char *copy, *cur, *p;
-    option_t *dep;
-    value_t *val;
-
-    copy = strdup(values);
-    for (cur = strtok(copy, " \t"); cur; cur = strtok(NULL, " \t")) {
-        if ((p = strchr(cur, '='))) {
-            *p++ = '\0';
-            if ((dep = find_option(cur))) {
-                val = option_assure_value(dep, optionset);
-                val->fromoption = opt;
-                val->value = get_valid_value_string(dep, p);
-            }
-            else
-                _log("Could not find option \"%s\" (set from composite \"%s\")", cur, opt->name);
-        }
-        else if (startswith(cur, "no") || startswith(cur, "No")) {
-            if ((dep = find_option(&cur[2]))) {
-                val = option_assure_value(dep, optionset);
-                val->fromoption = opt;
-                val->value = get_valid_value_string(dep, "0");
-            }
-        }
-        else {
-            if ((dep = find_option(cur))) {
-                val = option_assure_value(dep, optionset);
-                val->fromoption = opt;
-                val->value = get_valid_value_string(dep, "1");
-            }
-        }
+  copy = strdup(values);
+  for (cur = strtok(copy, " \t"); cur; cur = strtok(NULL, " \t"))
+  {
+    if ((p = strchr(cur, '=')))
+    {
+      *p++ = '\0';
+      if ((dep = find_option(cur)))
+      {
+       val = option_assure_value(dep, optionset);
+       val->fromoption = opt;
+       val->value = get_valid_value_string(dep, p);
+      }
+      else
+       _log("Could not find option \"%s\" (set from composite \"%s\")",
+            cur, opt->name);
+    }
+    else if (startswith(cur, "no") || startswith(cur, "No"))
+    {
+      if ((dep = find_option(&cur[2])))
+      {
+       val = option_assure_value(dep, optionset);
+       val->fromoption = opt;
+       val->value = get_valid_value_string(dep, "0");
+      }
     }
-    free(copy);
+    else
+    {
+      if ((dep = find_option(cur)))
+      {
+       val = option_assure_value(dep, optionset);
+       val->fromoption = opt;
+       val->value = get_valid_value_string(dep, "1");
+      }
+    }
+  }
+  free(copy);
 }
 
-int option_set_value(option_t *opt, int optionset, const char *value)
+
+int
+option_set_value(option_t *opt,
+                int optionset,
+                const char *value)
 {
-    value_t *val = option_assure_value(opt, optionset);
-    char *newvalue;
-    choice_t *choice;
-    option_t *fromopt;
+  value_t *val = option_assure_value(opt, optionset);
+  char *newvalue;
+  choice_t *choice;
+  option_t *fromopt;
 
-    newvalue = get_valid_value_string(opt, value);
-    if (!newvalue)
-        return 0;
+  newvalue = get_valid_value_string(opt, value);
+  if (!newvalue)
+    return (0);
 
-    free(val->value);
-    val->value = NULL;
+  free(val->value);
+  val->value = NULL;
 
-    if (startswith(newvalue, "From") && (fromopt = find_option(&newvalue[4])) &&
-                option_is_composite(fromopt)) {
-        /* TODO only set the changed option, not all of them */
-        choice = option_find_choice(fromopt, 
-                                    option_get_value(fromopt, optionset));
-        composite_set_values(fromopt, optionset, choice->command);
-       free(newvalue);
-    } else
-        val->value = newvalue;
+  if (startswith(newvalue, "From") && (fromopt = find_option(&newvalue[4])) &&
+      option_is_composite(fromopt))
+  {
+    // TODO only set the changed option, not all of them
+    choice = option_find_choice(fromopt, 
+                               option_get_value(fromopt, optionset));
+    composite_set_values(fromopt, optionset, choice->command);
+    free(newvalue);
+  }
+  else
+    val->value = newvalue;
 
-    if (option_is_composite(opt)) {
-        /* set dependent values */
-        choice = option_find_choice(opt, value);
-        if (choice && !isempty(choice->command))
-            composite_set_values(opt, optionset, choice->command);
-    }
-    return 1;
+  if (option_is_composite(opt))
+  {
+    // set dependent values
+    choice = option_find_choice(opt, value);
+    if (choice && !isempty(choice->command))
+      composite_set_values(opt, optionset, choice->command);
+  }
+  return (1);
 }
 
-int option_accepts_value(option_t *opt, const char *value)
+
+int
+option_accepts_value(option_t *opt,
+                    const char *value)
 {
-    char *val = get_valid_value_string(opt, value);
-    if (!val)
-        return 0;
-    free(val);
-    return 1;
+  char *val = get_valid_value_string(opt, value);
+  if (!val)
+    return (0);
+  free(val);
+  return (1);
 }
 
-int option_has_choice(option_t *opt, const char *choice)
+
+int
+option_has_choice(option_t *opt,
+                 const char *choice)
 {
-    return option_find_choice(opt, choice) != NULL;
+  return (option_find_choice(opt, choice) != NULL);
 }
 
-const char * option_text(option_t *opt)
+
+const char *
+option_text(option_t *opt)
 {
-    if (isempty(opt->text))
-        return opt->text;
-    return opt->text;
+  if (isempty(opt->text))
+    return (opt->text);
+  return (opt->text);
 }
 
-int option_type(option_t *opt)
+
+int
+option_type(option_t *opt)
 {
-    return opt->type;
+  return (opt->type);
 }
 
-void option_set_order(option_t *opt, double order)
+
+void
+option_set_order(option_t *opt,
+                double order)
 {
-    option_t *prev;
+  option_t *prev;
 
-    /* remove opt from old position */
-    if (opt == optionlist_sorted_by_order)
-        optionlist_sorted_by_order = opt->next_by_order;
-    else {
-        for (prev = optionlist_sorted_by_order;
-             prev && prev->next_by_order != opt;
-             prev = prev->next_by_order);
-        prev->next_by_order = opt->next_by_order;
-    }
+  // remove opt from old position
+  if (opt == optionlist_sorted_by_order)
+    optionlist_sorted_by_order = opt->next_by_order;
+  else
+  {
+    for (prev = optionlist_sorted_by_order;
+        prev && prev->next_by_order != opt;
+        prev = prev->next_by_order);
+    prev->next_by_order = opt->next_by_order;
+  }
 
-    opt->order = order;
+  opt->order = order;
 
-    /* insert into new position */
-    if (!optionlist_sorted_by_order)
-        optionlist_sorted_by_order = opt;
-    else if (optionlist_sorted_by_order->order > opt->order) {
-        opt->next_by_order = optionlist_sorted_by_order;
-        optionlist_sorted_by_order = opt;
-    }
-    else {
-        for (prev = optionlist_sorted_by_order;
-            prev->next_by_order && prev->next_by_order->order < opt->order;
-            prev = prev->next_by_order);
-        opt->next_by_order = prev->next_by_order;
-        prev->next_by_order = opt;
-    }
-}
-
-/* Set option from *FoomaticRIPOption keyword */
-void option_set_from_string(option_t *opt, const char *str)
-{
-    char type[32], style[32];
-    double order;
-    int matches;
-
-    matches = sscanf(str, "%31s %31s %c %lf", type, style, &opt->spot, &order);
-    if (matches < 3) {
-        _log("Can't read the value of *FoomaticRIPOption for \"%s\"", opt->name);
-        return;
-    }
-    opt->type = type_from_string(type);
-    opt->style = style_from_string(style);
-
-    if (matches == 4)
-        option_set_order(opt, order);
-}
-
-static choice_t * option_assure_choice(option_t *opt, const char *name)
-{
-    choice_t *choice, *last = NULL;
-
-    for (choice = opt->choicelist; choice; choice = choice->next) {
-        if (!strcasecmp(choice->value, name))
-            return choice;
-        last = choice;
-    }
-    if (!choice) {
-        choice = calloc(1, sizeof(choice_t));
-        if (last)
-            last->next = choice;
-        else
-            opt->choicelist = choice;
-        strlcpy(choice->value, name, 128);
-    }
-    return choice;
-}
-
-static void unhtmlify(char *dest, size_t size, const char *src)
-{
-    jobparams_t *job = get_current_job();
-    char *pdest = dest;
-    const char *psrc = src, *p = NULL;
-    const char *repl;
-    struct tm *t = localtime(&job->time);
-    char tmpstr[16];
-    size_t s, l, n;
-
-    while (*psrc && pdest - dest < size - 1) {
-
-        if (*psrc == '&') {
-            psrc++;
-            repl = NULL;
-            p = NULL;
-            l = 0;
-
-            /* Replace HTML/XML entities by the original characters */
-            if (!prefixcmp(psrc, "apos")) {
-                repl = "\'";
-                p = psrc + 4;
-            } else if (!prefixcmp(psrc, "quot")) {
-                repl = "\"";
-                p = psrc + 4;
-            } else if (!prefixcmp(psrc, "gt")) {
-                repl = ">";
-                p = psrc + 2;
-            } else if (!prefixcmp(psrc, "lt")) {
-                repl = "<";
-                p = psrc + 2;
-            } else if (!prefixcmp(psrc, "amp")) {
-                repl = "&";
-                p = psrc + 3;
-
-            /* Replace special entities by job->data */
-            } else if (!prefixcmp(psrc, "job")) {
-                repl = job->id;
-                p = psrc + 3;
-                if (jobentitymaxlen != 0)
-                    l = jobentitymaxlen;
-            } else if (!prefixcmp(psrc, "user")) {
-                repl = job->user;
-                p = psrc + 4;
-                if (userentitymaxlen != 0)
-                    l = userentitymaxlen;
-            } else if (!prefixcmp(psrc, "host")) {
-                repl = job->host;
-                p = psrc + 4;
-                if (hostentitymaxlen != 0)
-                    l = hostentitymaxlen;
-            } else if (!prefixcmp(psrc, "title")) {
-                repl = job->title;
-                p = psrc + 5;
-                if (titleentitymaxlen != 0)
-                    l = titleentitymaxlen;
-            } else if (!prefixcmp(psrc, "copies")) {
-                repl = job->copies;
-                p = psrc + 6;
-            } else if (!prefixcmp(psrc, "rbinumcopies")) {
-                if (job->rbinumcopies > 0) {
-                    snprintf(tmpstr, 16, "%d", job->rbinumcopies);
-                    repl = tmpstr;
-                }
-                else
-                    repl = job->copies;
-                p = psrc + 12;
-            }
-            else if (!prefixcmp(psrc, "options")) {
-                repl = job->optstr->data;
-                p = psrc + 7;
-                if (optionsentitymaxlen != 0)
-                    l = optionsentitymaxlen;
-            } else if (!prefixcmp(psrc, "year")) {
-                sprintf(tmpstr, "%04d", t->tm_year + 1900);
-                repl = tmpstr;
-                p = psrc + 4;
-            }
-            else if (!prefixcmp(psrc, "month")) {
-                sprintf(tmpstr, "%02d", t->tm_mon + 1);
-                repl = tmpstr;
-                p = psrc + 5;
-            }
-            else if (!prefixcmp(psrc, "date")) {
-                sprintf(tmpstr, "%02d", t->tm_mday);
-                repl = tmpstr;
-                p = psrc + 4;
-            }
-            else if (!prefixcmp(psrc, "hour")) {
-                sprintf(tmpstr, "%02d", t->tm_hour);
-                repl = tmpstr;
-                p = psrc + 4;
-            }
-            else if (!prefixcmp(psrc, "min")) {
-                sprintf(tmpstr, "%02d", t->tm_min);
-                repl = tmpstr;
-                p = psrc + 3;
-            }
-            else if (!prefixcmp(psrc, "sec")) {
-                sprintf(tmpstr, "%02d", t->tm_sec);
-                repl = tmpstr;
-                p = psrc + 3;
-            }
-            if (p) {
-                n = strtol(p, (char **)(&p), 0);
-                if (n != 0)
-                    l = n;
-                if (*p != ';')
-                    repl = NULL;
-            } else
-                repl = NULL;
-            if (repl) {
-                if ((l == 0) || (l > strlen(repl)))
-                    l = strlen(repl);
-                s = size - (pdest - dest) - 1;
-                strncpy(pdest, repl, s);
-                if (s < l)
-                    pdest += s;
-                else
-                    pdest += l;
-                psrc = p + 1;
-            }
-            else {
-                *pdest = '&';
-                pdest++;
-            }
-        }
-        else {
-            *pdest = *psrc;
-            pdest++;
-            psrc++;
-        }
-    }
-    *pdest = '\0';
-}
-
-/*
- * Checks whether 'code' contains active PostScript, i.e. not only comments
- */
-static int contains_active_postscript(const char *code)
-{
-    char **line, **lines;
-    int contains_ps = 0;
-
-    if (!(lines = argv_split(code, "\n", NULL)))
-        return 0;
-
-    for (line = lines; *line && !contains_ps; line++)
-        contains_ps = !isempty(*line) && 
-                      !startswith(skip_whitespace(*line), "%");
-
-    argv_free(lines);
-    return contains_ps;
-}
-
-void option_set_choice(option_t *opt, const char *name, const char *text,
-                       const char *code)
+  // insert into new position
+  if (!optionlist_sorted_by_order)
+    optionlist_sorted_by_order = opt;
+  else if (optionlist_sorted_by_order->order > opt->order)
+  {
+    opt->next_by_order = optionlist_sorted_by_order;
+    optionlist_sorted_by_order = opt;
+  }
+  else
+  {
+    for (prev = optionlist_sorted_by_order;
+        prev->next_by_order && prev->next_by_order->order < opt->order;
+        prev = prev->next_by_order);
+    opt->next_by_order = prev->next_by_order;
+    prev->next_by_order = opt;
+  }
+}
+
+
+// Set option from *FoomaticRIPOption keyword
+void
+option_set_from_string(option_t *opt,
+                      const char *str)
 {
-    choice_t *choice;
+  char type[32], style[32];
+  double order;
+  int matches;
 
-    if (opt->type == TYPE_BOOL) {
-        if (is_true_string(name))
-            choice = option_assure_choice(opt, "1");
-        else
-            choice = option_assure_choice(opt, "0");
-    }
+  matches = sscanf(str, "%31s %31s %c %lf", type, style, &opt->spot, &order);
+  if (matches < 3)
+  {
+    _log("Can't read the value of *FoomaticRIPOption for \"%s\"", opt->name);
+    return;
+  }
+  opt->type = type_from_string(type);
+  opt->style = style_from_string(style);
+
+  if (matches == 4)
+    option_set_order(opt, order);
+}
+
+
+static choice_t *
+option_assure_choice(option_t *opt,
+                    const char *name)
+{
+  choice_t *choice, *last = NULL;
+
+  for (choice = opt->choicelist; choice; choice = choice->next)
+  {
+    if (!strcasecmp(choice->value, name))
+      return (choice);
+    last = choice;
+  }
+  if (!choice)
+  {
+    choice = calloc(1, sizeof(choice_t));
+    if (last)
+      last->next = choice;
     else
-        choice = option_assure_choice(opt, name);
+      opt->choicelist = choice;
+    strlcpy(choice->value, name, 128);
+  }
+  return (choice);
+}
 
-    if (text)
-        strlcpy(choice->text, text, 128);
 
-    if (!code)
+static void
+unhtmlify(char *dest,
+         size_t size,
+         const char *src)
+{
+  jobparams_t *job = get_current_job();
+  char *pdest = dest;
+  const char *psrc = src, *p = NULL;
+  const char *repl;
+  struct tm *t = localtime(&job->time);
+  char tmpstr[16];
+  size_t s, l, n;
+
+  while (*psrc && pdest - dest < size - 1)
+  {
+    if (*psrc == '&')
+    {
+      psrc++;
+      repl = NULL;
+      p = NULL;
+      l = 0;
+
+      // Replace HTML/XML entities by the original characters
+      if (!prefixcmp(psrc, "apos"))
+      {
+       repl = "\'";
+       p = psrc + 4;
+      }
+      else if (!prefixcmp(psrc, "quot"))
+      {
+       repl = "\"";
+       p = psrc + 4;
+      }
+      else if (!prefixcmp(psrc, "gt"))
+      {
+       repl = ">";
+       p = psrc + 2;
+      }
+      else if (!prefixcmp(psrc, "lt"))
+      {
+       repl = "<";
+       p = psrc + 2;
+      }
+      else if (!prefixcmp(psrc, "amp"))
+      {
+       repl = "&";
+       p = psrc + 3;
+      }
+      // Replace special entities by job->data
+      else if (!prefixcmp(psrc, "job"))
+      {
+       repl = job->id;
+       p = psrc + 3;
+       if (jobentitymaxlen != 0)
+         l = jobentitymaxlen;
+      }
+      else if (!prefixcmp(psrc, "user"))
+      {
+       repl = job->user;
+       p = psrc + 4;
+       if (userentitymaxlen != 0)
+         l = userentitymaxlen;
+      }
+      else if (!prefixcmp(psrc, "host"))
+      {
+       repl = job->host;
+       p = psrc + 4;
+       if (hostentitymaxlen != 0)
+         l = hostentitymaxlen;
+      }
+      else if (!prefixcmp(psrc, "title"))
+      {
+       repl = job->title;
+       p = psrc + 5;
+       if (titleentitymaxlen != 0)
+         l = titleentitymaxlen;
+      }
+      else if (!prefixcmp(psrc, "copies"))
+      {
+       repl = job->copies;
+       p = psrc + 6;
+      }
+      else if (!prefixcmp(psrc, "rbinumcopies"))
+      {
+       if (job->rbinumcopies > 0)
+       {
+         snprintf(tmpstr, 16, "%d", job->rbinumcopies);
+         repl = tmpstr;
+       }
+       else
+         repl = job->copies;
+       p = psrc + 12;
+      }
+      else if (!prefixcmp(psrc, "options"))
+      {
+       repl = job->optstr->data;
+       p = psrc + 7;
+       if (optionsentitymaxlen != 0)
+         l = optionsentitymaxlen;
+      }
+      else if (!prefixcmp(psrc, "year"))
+      {
+       sprintf(tmpstr, "%04d", t->tm_year + 1900);
+       repl = tmpstr;
+       p = psrc + 4;
+      }
+      else if (!prefixcmp(psrc, "month"))
+      {
+       sprintf(tmpstr, "%02d", t->tm_mon + 1);
+       repl = tmpstr;
+       p = psrc + 5;
+      }
+      else if (!prefixcmp(psrc, "date"))
+      {
+       sprintf(tmpstr, "%02d", t->tm_mday);
+       repl = tmpstr;
+       p = psrc + 4;
+      }
+      else if (!prefixcmp(psrc, "hour"))
+      {
+       sprintf(tmpstr, "%02d", t->tm_hour);
+       repl = tmpstr;
+       p = psrc + 4;
+      }
+      else if (!prefixcmp(psrc, "min"))
+      {
+       sprintf(tmpstr, "%02d", t->tm_min);
+       repl = tmpstr;
+       p = psrc + 3;
+      }
+      else if (!prefixcmp(psrc, "sec"))
+      {
+       sprintf(tmpstr, "%02d", t->tm_sec);
+       repl = tmpstr;
+       p = psrc + 3;
+      }
+      if (p)
+      {
+       n = strtol(p, (char **)(&p), 0);
+       if (n != 0)
+         l = n;
+       if (*p != ';')
+         repl = NULL;
+      }
+      else
+       repl = NULL;
+      if (repl)
+      {
+       if ((l == 0) || (l > strlen(repl)))
+         l = strlen(repl);
+       s = size - (pdest - dest) - 1;
+       strncpy(pdest, repl, s);
+       if (s < l)
+         pdest += s;
+       else
+         pdest += l;
+       psrc = p + 1;
+      }
+      else
+      {
+       *pdest = '&';
+       pdest++;
+      }
+    }
+    else
     {
-        _log("Warning: No code for choice \"%s\" of option \"%s\"\n",
-             choice->text, opt->name);
-        return;
+      *pdest = *psrc;
+      pdest++;
+      psrc++;
     }
+  }
+  *pdest = '\0';
+}
+
+
+//
+// Checks whether 'code' contains active PostScript, i.e. not only comments
+//
 
-    if (!startswith(code, "%% FoomaticRIPOptionSetting"))
-        unhtmlify(choice->command, 65536, code);
+static int
+contains_active_postscript(const char *code)
+{
+  char **line, **lines;
+  int contains_ps = 0;
+
+  if (!(lines = argv_split(code, "\n", NULL)))
+    return (0);
+
+  for (line = lines; *line && !contains_ps; line++)
+    contains_ps = !isempty(*line) && 
+      !startswith(skip_whitespace(*line), "%");
+
+  argv_free(lines);
+  return (contains_ps);
 }
 
-/*
- *  Parameters
- */
 
-int param_set_allowed_chars(param_t *param, const char *value)
+void
+option_set_choice(option_t *opt,
+                 const char *name,
+                 const char *text,
+                 const char *code)
 {
-    char rxstr[256], tmp[128];
+  choice_t *choice;
 
-    param->allowedchars = malloc(sizeof(regex_t));
-    unhtmlify(tmp, 128, value);
-    snprintf(rxstr, 256, "^[%s]*$", tmp);
-    if (regcomp(param->allowedchars, rxstr, 0) != 0) {
-        regfree(param->allowedchars);
-        param->allowedchars = NULL;
-        return 0;
-    }
-    return 1;
+  if (opt->type == TYPE_BOOL)
+  {
+    if (is_true_string(name))
+      choice = option_assure_choice(opt, "1");
+    else
+      choice = option_assure_choice(opt, "0");
+  }
+  else
+    choice = option_assure_choice(opt, name);
+
+  if (text)
+    strlcpy(choice->text, text, 128);
+
+  if (!code)
+  {
+    _log("Warning: No code for choice \"%s\" of option \"%s\"\n",
+        choice->text, opt->name);
+    return;
+  }
+
+  if (!startswith(code, "%% FoomaticRIPOptionSetting"))
+    unhtmlify(choice->command, 65536, code);
 }
 
-int param_set_allowed_regexp(param_t *param, const char *value)
+//
+// Parameters
+//
+
+int
+param_set_allowed_chars(param_t *param,
+                       const char *value)
 {
-    char tmp[128];
+  char rxstr[256], tmp[128];
 
-    param->allowedregexp = malloc(sizeof(regex_t));
-    unhtmlify(tmp, 128, value);
-    if (regcomp(param->allowedregexp, tmp, 0) != 0) {
-        regfree(param->allowedregexp);
-        param->allowedregexp = NULL;
-        return 0;
-    }
-    return 1;
+  param->allowedchars = malloc(sizeof(regex_t));
+  unhtmlify(tmp, 128, value);
+  snprintf(rxstr, 256, "^[%s]*$", tmp);
+  if (regcomp(param->allowedchars, rxstr, 0) != 0)
+  {
+    regfree(param->allowedchars);
+    param->allowedchars = NULL;
+    return (0);
+  }
+  return (1);
 }
 
-void option_set_custom_command(option_t *opt, const char *cmd)
+
+int
+param_set_allowed_regexp(param_t *param,
+                        const char *value)
 {
-    size_t len = strlen(cmd) + 50;
-    free(opt->custom_command);
-    opt->custom_command = malloc(len);
-    unhtmlify(opt->custom_command, len, cmd);
+  char tmp[128];
+
+  param->allowedregexp = malloc(sizeof(regex_t));
+  unhtmlify(tmp, 128, value);
+  if (regcomp(param->allowedregexp, tmp, 0) != 0)
+  {
+    regfree(param->allowedregexp);
+    param->allowedregexp = NULL;
+    return (0);
+  }
+  return (1);
 }
 
-param_t * option_add_custom_param_from_string(option_t *opt,
-    const char *name, const char *text, const char *str)
+
+void
+option_set_custom_command(option_t *opt,
+                         const char *cmd)
 {
-    param_t *param = calloc(1, sizeof(param_t));
-    param_t *p;
-    char typestr[33];
-    int n;
+  size_t len = strlen(cmd) + 50;
+  free(opt->custom_command);
+  opt->custom_command = malloc(len);
+  unhtmlify(opt->custom_command, len, cmd);
+}
 
-    strlcpy(param->name, name, 128);
-    strlcpy(param->text, text, 128);
 
-    n = sscanf(str, "%d%15s%19s%19s",
-        &param->order, typestr, param->min, param->max);
+param_t *
+option_add_custom_param_from_string(option_t *opt,
+                                   const char *name,
+                                   const char *text,
+                                   const char *str)
+{
+  param_t *param = calloc(1, sizeof(param_t));
+  param_t *p;
+  char typestr[33];
+  int n;
 
-    if (n != 4) {
-        _log("Could not parse custom parameter for '%s'!\n", opt->name);
-        free(param);
-        return NULL;
-    }
+  strlcpy(param->name, name, 128);
+  strlcpy(param->text, text, 128);
 
-    if (!strcmp(typestr, "curve"))
-        param->type = TYPE_CURVE;
-    else if (!strcmp(typestr, "invcurve"))
-        param->type = TYPE_INVCURVE;
-    else if (!strcmp(typestr, "int"))
-        param->type = TYPE_INT;
-    else if (!strcmp(typestr, "real"))
-        param->type = TYPE_FLOAT;
-    else if (!strcmp(typestr, "passcode"))
-        param->type = TYPE_PASSCODE;
-    else if (!strcmp(typestr, "password"))
-        param->type = TYPE_PASSWORD;
-    else if (!strcmp(typestr, "points"))
-        param->type = TYPE_POINTS;
-    else if (!strcmp(typestr, "string"))
-        param->type = TYPE_STRING;
-    else {
-        _log("Unknown custom parameter type for param '%s' for option '%s'\n", param->name, opt->name);
-        free(param);
-        return NULL;
-    }
+  n = sscanf(str, "%d%15s%19s%19s",
+            &param->order, typestr, param->min, param->max);
 
-    param->next = NULL;
+  if (n != 4)
+  {
+    _log("Could not parse custom parameter for '%s'!\n", opt->name);
+    free(param);
+    return (NULL);
+  }
+
+  if (!strcmp(typestr, "curve"))
+    param->type = TYPE_CURVE;
+  else if (!strcmp(typestr, "invcurve"))
+    param->type = TYPE_INVCURVE;
+  else if (!strcmp(typestr, "int"))
+    param->type = TYPE_INT;
+  else if (!strcmp(typestr, "real"))
+    param->type = TYPE_FLOAT;
+  else if (!strcmp(typestr, "passcode"))
+    param->type = TYPE_PASSCODE;
+  else if (!strcmp(typestr, "password"))
+    param->type = TYPE_PASSWORD;
+  else if (!strcmp(typestr, "points"))
+    param->type = TYPE_POINTS;
+  else if (!strcmp(typestr, "string"))
+    param->type = TYPE_STRING;
+  else
+  {
+    _log("Unknown custom parameter type for param '%s' for option '%s'\n", param->name, opt->name);
+    free(param);
+    return (NULL);
+  }
 
-    /* Insert param into opt->paramlist, sorted by order */
-    if (!opt->paramlist)
-        opt->paramlist = param;
-    else if (opt->paramlist->order > param->order) {
-        param->next = opt->paramlist;
-        opt->paramlist = param;
-    }
-    else {
-        for (p = opt->paramlist;
-             p->next && p->next->order < param->order;
-             p = p->next);
-        param->next = p->next;
-        p->next = param;
-    }
+  param->next = NULL;
+
+  // Insert param into opt->paramlist, sorted by order
+  if (!opt->paramlist)
+    opt->paramlist = param;
+  else if (opt->paramlist->order > param->order)
+  {
+    param->next = opt->paramlist;
+    opt->paramlist = param;
+  }
+  else
+  {
+    for (p = opt->paramlist;
+        p->next && p->next->order < param->order;
+        p = p->next);
+    param->next = p->next;
+    p->next = param;
+  }
 
-    opt->param_count++;
-    return param;
+  opt->param_count++;
+  return (param);
 }
 
-param_t * option_assure_foomatic_param(option_t *opt)
+
+param_t *
+option_assure_foomatic_param(option_t *opt)
 {
-    param_t *param;
+  param_t *param;
 
-    if (opt->foomatic_param)
-        return opt->foomatic_param;
+  if (opt->foomatic_param)
+    return (opt->foomatic_param);
 
-    param = calloc(1, sizeof(param_t));
-    strcpy(param->name, "foomatic-param");
-    param->order = 0;
-    param->type = opt->type;
+  param = calloc(1, sizeof(param_t));
+  strcpy(param->name, "foomatic-param");
+  param->order = 0;
+  param->type = opt->type;
 
-    opt->foomatic_param = param;
-    return param;
+  opt->foomatic_param = param;
+  return (param);
 }
 
 
-/*
- *  Optionsets
- */
+//
+//  Optionsets
+//
 
-const char * optionset_name(int idx)
+const char *
+optionset_name(int idx)
 {
-    if (idx < 0 || idx >= optionset_count) {
-        _log("Optionset with index %d does not exist\n", idx);
-        return NULL;
-    }
-    return optionsets[idx];
+  if (idx < 0 || idx >= optionset_count)
+  {
+    _log("Optionset with index %d does not exist\n", idx);
+    return (NULL);
+  }
+  return (optionsets[idx]);
 }
 
-int optionset(const char * name)
+
+int
+optionset(const char *name)
 {
-    int i;
+  int i;
 
-    for (i = 0; i < optionset_count; i++) {
-        if (!strcmp(optionsets[i], name))
-            return i;
-    }
+  for (i = 0; i < optionset_count; i ++)
+  {
+    if (!strcmp(optionsets[i], name))
+      return (i);
+  }
 
-    if (optionset_count == optionset_alloc) {
-        optionset_alloc *= 2;
-        optionsets = realloc(optionsets, optionset_alloc * sizeof(char *));
-        for (i = optionset_count; i < optionset_alloc; i++)
-            optionsets[i] = NULL;
-    }
+  if (optionset_count == optionset_alloc)
+  {
+    optionset_alloc *= 2;
+    optionsets = realloc(optionsets, optionset_alloc * sizeof(char *));
+    for (i = optionset_count; i < optionset_alloc; i++)
+      optionsets[i] = NULL;
+  }
 
-    optionsets[optionset_count] = strdup(name);
-    optionset_count++;
-    return optionset_count -1;
+  optionsets[optionset_count] = strdup(name);
+  optionset_count++;
+  return (optionset_count - 1);
 }
 
-void optionset_copy_values(int src_optset, int dest_optset)
+
+void
+optionset_copy_values(int src_optset,
+                     int dest_optset)
 {
-    option_t *opt;
-    value_t *val;
+  option_t *opt;
+  value_t *val;
 
-    for (opt = optionlist; opt; opt = opt->next) {
-        for (val = opt->valuelist; val; val = val->next) {
-            if (val->optionset == src_optset) {
-                option_set_value(opt, dest_optset, val->value);
-                break;
-            }
-        }
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    for (val = opt->valuelist; val; val = val->next)
+    {
+      if (val->optionset == src_optset)
+      {
+       option_set_value(opt, dest_optset, val->value);
+       break;
+      }
     }
+  }
 }
 
-void optionset_delete_values(int optionset)
+
+void
+optionset_delete_values(int optionset)
 {
-    option_t *opt;
-    value_t *val, *prev_val;
+  option_t *opt;
+  value_t *val, *prev_val;
 
-    for (opt = optionlist; opt; opt = opt->next) {
-        val = opt->valuelist;
-        prev_val = NULL;
-        while (val) {
-            if (val->optionset == optionset) {
-                if (prev_val)
-                    prev_val->next = val->next;
-                else
-                    opt->valuelist = val->next;
-                free_value(val);
-                val = prev_val ? prev_val->next : opt->valuelist;
-                break;
-            } else {
-                prev_val = val;
-                val = val->next;
-            }
-        }
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    val = opt->valuelist;
+    prev_val = NULL;
+    while (val)
+    {
+      if (val->optionset == optionset)
+      {
+       if (prev_val)
+         prev_val->next = val->next;
+       else
+         opt->valuelist = val->next;
+       free_value(val);
+       val = prev_val ? prev_val->next : opt->valuelist;
+       break;
+      }
+      else
+      {
+       prev_val = val;
+       val = val->next;
+      }
     }
+  }
 }
 
-int optionset_equal(int optset1, int optset2, int exceptPS)
+
+int
+optionset_equal(int optset1,
+               int optset2,
+               int exceptPS)
 {
-    option_t *opt;
-    const char *val1, *val2;
+  option_t *opt;
+  const char *val1, *val2;
 
-    for (opt = optionlist; opt; opt = opt->next) {
-        if (exceptPS && opt->style == 'G')
-            continue;
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    if (exceptPS && opt->style == 'G')
+      continue;
 
-        val1 = option_get_value(opt, optset1);
-        val2 = option_get_value(opt, optset2);
-
-        if (val1 && val2) { /* both entries exist */
-            if (strcmp(val1, val2) != 0)
-                return 0; /* but aren't equal */
-        }
-        else if (val1 || val2) /* one entry exists --> can't be equal */
-            return 0;
-        /* If no extry exists, the non-existing entries
-         * are considered as equal */
-    }
-    return 1;
-}
-
-/*
- *  read_ppd_file()
- */
-void read_ppd_file(const char *filename)
-{
-    FILE *fh;
-    const char *tmp;
-    char *icc_qual2 = NULL;
-    char *icc_qual3 = NULL;
-    char line [256];            /* PPD line length is max 255 (excl. \0) */
-    char *p;
-    char key[128], name[64], text[64];
-    dstr_t *value = create_dstr(); /* value can span multiple lines */
-    double order;
-    value_t *val;
-    option_t *opt, *current_opt = NULL;
-    param_t *param;
-    icc_mapping_entry_t *entry;
-
-    fh = fopen(filename, "r");
-    if (!fh)
-       rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Unable to open PPD file %s\n", filename);
-    _log("Parsing PPD file ...\n");
-
-    dstrassure(value, 256);
-
-    qualifier_data = list_create();
-    while (!feof(fh)) {
-        tmp = fgets(line, 256, fh);
-
-        if (line[0] != '*' || startswith(line, "*%"))
-            continue;
-
-        /* get the key */
-        if (!(p = strchr(line, ':')))
-            continue;
-        *p = '\0';
-
-        key[0] = name[0] = text[0] = '\0';
-        sscanf(line, "*%127s%*[ \t]%63[^ \t/=)]%*1[/=]%63[^\n]", key, name, text);
-
-        /* get the value */
-        dstrclear(value);
-        sscanf(p +1, " %255[^\r\n]", value->data);
-        value->len = strlen(value->data);
-        if (!value->len)
-            _log("PPD: Missing value for key \"%s\"\n", line);
-
-        while (1) {
-            /* "&&" is the continue-on-next-line marker */
-            if (dstrendswith(value, "&&")) {
-                value->len -= 2;
-                value->data[value->len] = '\0';
-            }
-            /* quoted but quotes are not yet closed */
-            else if (value->data[0] == '\"' && !strchr(value->data +1, '\"'))
-                dstrcat(value, "\n"); /* keep newlines in quoted string*/
-            /* not quoted, or quotes already closed */
-            else
-                break;
-
-            tmp = fgets(line, 256, fh);
-            dstrcat(value, line);
-            dstrremovenewline(value);
-        }
-
-        /* remove quotes */
-        if (value->data[0] == '\"') {
-            memmove(value->data, value->data +1, value->len +1);
-            p = strrchr(value->data, '\"');
-            if (!p) {
-                _log("Invalid line: \"%s: ...\"\n", key);
-                continue;
-            }
-            *p = '\0';
-        }
-        /* remove last newline */
-        dstrremovenewline(value);
-
-        /* remove last whitespace */
-        dstrtrim_right(value);
-
-        /* process key/value pairs */
-        if (strcmp(key, "NickName") == 0) {
-            unhtmlify(printer_model, 256, value->data);
-        }
-        else if (strcmp(key, "FoomaticIDs") == 0) {
-            /* *FoomaticIDs: <printer ID> <driver ID> */
-            sscanf(value->data, "%*[ \t]%127[^ \t]%*[ \t]%127[^ \t\n]",
-                printer_id, driver);
-        }
-        else if (strcmp(key, "FoomaticRIPPostPipe") == 0) {
-            if (!postpipe)
-                postpipe = create_dstr();
-            dstrassure(postpipe, value->len +128);
-            unhtmlify(postpipe->data, postpipe->alloc, value->data);
-        }
-        else if (strcmp(key, "FoomaticRIPCommandLine") == 0) {
-            unhtmlify(cmd, 4096, value->data);
-        }
-        else if (strcmp(key, "FoomaticRIPCommandLinePDF") == 0) {
-            unhtmlify(cmd_pdf, 4096, value->data);
-        }
-        else if (!strcmp(key, "cupsFilter")) {
-            /* cupsFilter: <code> */
-            /* only save the filter for "application/vnd.cups-raster" */
-            if (prefixcmp(value->data, "application/vnd.cups-raster") == 0) {
-                p = strrchr(value->data, ' ');
-                if (p)
-                    unhtmlify(cupsfilter, 256, p +1);
-            }
-        }
-        else if (startswith(key, "Custom") && !strcasecmp(name, "true")) {
-            /* Cups custom option: *CustomFoo True: "command" */
-            if (startswith(&key[6], "JCL")) {
-                opt = assure_option(&key[9]);
-                opt->style = 'J';
-            }
-            else
-                opt = assure_option(&key[6]);
-            option_set_custom_command(opt, value->data);
-            if (!strcmp(key, "CustomPageSize"))
-                option_set_custom_command(assure_option("PageRegion"), value->data);
-        }
-        else if (startswith(key, "ParamCustom")) {
-            /* Cups custom parameter:
-               *ParamCustomFoo Name/Text: order type minimum maximum */
-            if (startswith(&key[11], "JCL"))
-                opt = assure_option(&key[14]);
-            else
-                opt = assure_option(&key[11]);
-            option_add_custom_param_from_string(opt, name, text, value->data);
-        }
-        else if (!strcmp(key, "OpenUI") || !strcmp(key, "JCLOpenUI")) {
-            /* "*[JCL]OpenUI *<option>[/<translation>]: <type>" */
-            current_opt = assure_option(&name[1]);
-            if (!isempty(text))
-                strlcpy(current_opt->text, text, 128);
-            if (startswith(key, "JCL"))
-                current_opt->style = 'J';
-            /* Set the argument type only if not defined yet,
-            a definition in "*FoomaticRIPOption" has priority */
-            if (current_opt->type == TYPE_NONE)
-                current_opt->type = type_from_string(value->data);
-        }
-        else if (!strcmp(key, "CloseUI") || !strcmp(key, "JCLCloseUI")) {
-            /* *[JCL]CloseUI: *<option> */
-            if (!current_opt || !option_has_name(current_opt, value->data +1))
-                _log("CloseUI found without corresponding OpenUI (%s).\n", value->data +1);
-            current_opt = NULL;
-        }
-        else if (!strcmp(key, "FoomaticRIPOption")) {
-            /* "*FoomaticRIPOption <option>: <type> <style> <spot> [<order>]"
-               <order> only used for 1-choice enum options */
-            option_set_from_string(assure_option(name), value->data);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionPrototype")) {
-            /* "*FoomaticRIPOptionPrototype <option>: <code>"
-               Used for numerical and string options only */
-            opt = assure_option(name);
-            opt->proto = malloc(65536);
-            unhtmlify(opt->proto, 65536, value->data);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionRange")) {
-            /* *FoomaticRIPOptionRange <option>: <min> <max>
-               Used for numerical options only */
-            param = option_assure_foomatic_param(assure_option(name));
-            sscanf(value->data, "%19s %19s", param->min, param->max);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionMaxLength")) {
-            /*  "*FoomaticRIPOptionMaxLength <option>: <length>"
-                Used for string options only */
-            param = option_assure_foomatic_param(assure_option(name));
-            sscanf(value->data, "%19s", param->max);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionAllowedChars")) {
-            /* *FoomaticRIPOptionAllowedChars <option>: <code>
-                Used for string options only */
-            param = option_assure_foomatic_param(assure_option(name));
-            param_set_allowed_chars(param, value->data);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionAllowedRegExp")) {
-            /* "*FoomaticRIPOptionAllowedRegExp <option>: <code>"
-               Used for string options only */
-            param = option_assure_foomatic_param(assure_option(name));
-            param_set_allowed_regexp(param, value->data);
-        }
-        else if (!strcmp(key, "OrderDependency")) {
-            /* OrderDependency: <order> <section> *<option> */
-            /* use 'text' to read <section> */
-            sscanf(value->data, "%lf %63s *%63s", &order, text, name);
-            opt = assure_option(name);
-            opt->section = section_from_string(text);
-            option_set_order(opt, order);
-        }
-
-        /* Default options are not yet validated (not all options/choices
-           have been read yet) */
-        else if (!prefixcmp(key, "Default")) {
-            /* Default<option>: <value> */
-
-            opt = assure_option(&key[7]);
-            val = option_assure_value(opt, optionset("default"));
-            free(val->value);
-            val->value = strdup(value->data);
-        }
-        else if (!prefixcmp(key, "FoomaticRIPDefault")) {
-            /* FoomaticRIPDefault<option>: <value>
-               Used for numerical options only */
-            opt = assure_option(&key[18]);
-            val = option_assure_value(opt, optionset("default"));
-            free(val->value);
-            val->value = strdup(value->data);
-        }
-
-        /* Current argument */
-        else if (current_opt && !strcmp(key, current_opt->name)) {
-            /* *<option> <choice>[/translation]: <code> */
-            option_set_choice(current_opt, name, text, value->data);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionSetting")) {
-            /* "*FoomaticRIPOptionSetting <option>[=<choice>]: <code>
-               For boolean options <choice> is not given */
-            option_set_choice(assure_option(name),
-                isempty(text) ? "true" : text, NULL, value->data);
-        }
-
-        /* "*(Foomatic|)JCL(Begin|ToPSInterpreter|End|Prefix): <code>"
-           The printer supports PJL/JCL when there is such a line */
-        else if (!prefixcmp(key, "JCLBegin") ||
-                 !prefixcmp(key, "FoomaticJCLBegin")) {
-            unhexify(jclbegin, 256, value->data);
-            if (!jclprefixset && strstr(jclbegin, "PJL") == NULL)
-                jclprefix[0] = '\0';
-        }
-        else if (!prefixcmp(key, "JCLToPSInterpreter") ||
-                 !prefixcmp(key, "FoomaticJCLToPSInterpreter")) {
-             unhexify(jcltointerpreter, 256, value->data);
-        }
-        else if (!prefixcmp(key, "JCLEnd") ||
-                 !prefixcmp(key, "FoomaticJCLEnd")) {
-             unhexify(jclend, 256, value->data);
-        }
-        else if (!prefixcmp(key, "JCLPrefix") ||
-                 !prefixcmp(key, "FoomaticJCLPrefix")) {
-            unhexify(jclprefix, 256, value->data);
-            jclprefixset = 1;
-        }
-        else if (!prefixcmp(key, "% COMDATA #")) {
-            /* old foomtic 2.0.x PPD file */
-            _log("You are using an old Foomatic 2.0 PPD file, which is no "
-                 "longer supported by Foomatic >4.0. Exiting.\n");
-            exit(1); /* TODO exit more gracefully */
-        }
-        else if (!strcmp(key, "FoomaticRIPJobEntityMaxLength")) {
-            /*  "*FoomaticRIPJobEntityMaxLength: <length>" */
-            sscanf(value->data, "%d", &jobentitymaxlen);
-        }
-        else if (!strcmp(key, "FoomaticRIPUserEntityMaxLength")) {
-            /*  "*FoomaticRIPUserEntityMaxLength: <length>" */
-            sscanf(value->data, "%d", &userentitymaxlen);
-        }
-        else if (!strcmp(key, "FoomaticRIPHostEntityMaxLength")) {
-            /*  "*FoomaticRIPHostEntityMaxLength: <length>" */
-            sscanf(value->data, "%d", &hostentitymaxlen);
-        }
-        else if (!strcmp(key, "FoomaticRIPTitleEntityMaxLength")) {
-            /*  "*FoomaticRIPTitleEntityMaxLength: <length>" */
-            sscanf(value->data, "%d", &titleentitymaxlen);
-        }
-        else if (!strcmp(key, "FoomaticRIPOptionsEntityMaxLength")) {
-            /*  "*FoomaticRIPOptionsEntityMaxLength: <length>" */
-            sscanf(value->data, "%d", &optionsentitymaxlen);
-        }
-        else if (!strcmp(key, "cupsICCProfile")) {
-            /*  "*cupsICCProfile: <qualifier/Title> <filename>" */
-            entry = calloc(1, sizeof(icc_mapping_entry_t));
-            entry->qualifier = strdup(name);
-            entry->filename = strdup(value->data);
-            list_append (qualifier_data, entry);
-        }
-        else if (!strcmp(key, "cupsICCQualifier2")) {
-            /*  "*cupsICCQualifier2: <value>" */
-            icc_qual2 = strdup(value->data);
-        }
-        else if (!strcmp(key, "cupsICCQualifier3")) {
-            /*  "*cupsICCQualifier3: <value>" */
-            icc_qual3 = strdup(value->data);
-        }
-    }
-
-    fclose(fh);
-    free_dstr(value);
-
-    /* Validate default options by resetting them with option_set_value() */
-    for (opt = optionlist; opt; opt = opt->next) {
-        val = option_find_value(opt, optionset("default"));
-        if (val) {
-            /* if fromopt is set, this value has already been validated */
-            if (!val->fromoption)
-                option_set_value(opt, optionset("default"), val->value);
-        }
-        else
-            /* Make sure that this option has a default choice, even if none is
-               defined in the PPD file */
-            option_set_value(opt, optionset("default"), opt->choicelist->value);
-    }
-
-    /* create qualifier for this PPD */
-    qualifier = calloc(4, sizeof(char*));
-
-    /* get colorspace */
-    tmp = option_get_value(find_option("ColorSpace"), optionset("default"));
-    if (tmp == NULL)
-      tmp = option_get_value(find_option("ColorModel"), optionset("default"));
-    if (tmp == NULL)
-      tmp = "";
-    qualifier[0] = strdup(tmp);
-
-    /* get selector2 */
-    if (icc_qual2 == NULL)
-        icc_qual2 = strdup("MediaType");
-    tmp = option_get_value(find_option(icc_qual2), optionset("default"));
-    if (tmp == NULL)
-      tmp = "";
-    qualifier[1] = strdup(tmp);
-
-    /* get selectors */
-    if (icc_qual3 == NULL)
-        icc_qual3 = strdup("Resolution");
-    tmp = option_get_value(find_option(icc_qual3), optionset("default"));
-    if (tmp == NULL)
-      tmp = "";
-    qualifier[2] = strdup(tmp);
-
-    free (icc_qual2);
-    free (icc_qual3);
-}
-
-int ppd_supports_pdf()
-{
-    option_t *opt;
-
-    /* If at least one option inserts PostScript code, we cannot support PDF */
-    for (opt = optionlist; opt; opt = opt->next)
-    {
-        choice_t *choice;
-
-        if (!option_is_ps_command(opt) || option_is_composite(opt) ||
-           (opt->type == TYPE_NONE))
-         continue;
-
-        for (choice = opt->choicelist; choice; choice = choice->next)
-         if (contains_active_postscript(choice->command)) {
-           _log("  PostScript option found: %s=%s: \"%s\"\n",
-                opt->name, choice->value, choice->command);
-           return 0;
-         }
-    }
-
-    if (!isempty(cmd_pdf))
-        return 1;
-
-    /* Ghostscript also accepts PDF, use that if it is in the normal command
-     * line */
-    if (startswith(cmd, "gs"))
-    {
-        strncpy(cmd_pdf, cmd, 4096);
-        if (strlen(cmd) > 4095)
-          cmd_pdf[4095] = '\0';
-        return 1;
-    }
-
-    _log("  Neither PDF renderer command line nor Ghostscript-based renderer command line found\n");
-    return 0;
-}
-
-/* build a renderer command line, based on the given option set */
-int build_commandline(int optset, dstr_t *cmdline, int pdfcmdline)
-{
-    option_t *opt;
-    const char *userval;
-    char *s, *p;
-    dstr_t *cmdvar = create_dstr();
-    dstr_t *open = create_dstr();
-    dstr_t *close = create_dstr();
-    char letters[] = "%A %B %C %D %E %F %G %H %I %J %K %L %M %W %X %Y %Z";
-    int jcl = 0;
-
-    dstr_t *local_jclprepend = create_dstr();
-
-    dstrclear(prologprepend);
-    dstrclear(setupprepend);
-    dstrclear(pagesetupprepend);
-
-    if (cmdline)
-        dstrcpy(cmdline, pdfcmdline ? cmd_pdf : cmd);
-
-    for (opt = optionlist_sorted_by_order; opt; opt = opt->next_by_order) {
-        /* composite options have no direct influence, and all their dependents
-           have already been set */
-        if (option_is_composite(opt))
-            continue;
-
-        userval = option_get_value(opt, optset);
-        option_get_command(cmdvar, opt, optset, -1);
-
-        /* Insert the built snippet at the correct place */
-        if (option_is_ps_command(opt)) {
-            /* Place this Postscript command onto the prepend queue
-               for the appropriate section. */
-            if (cmdvar->len) {
-                dstrcpyf(open, "[{\n%%%%BeginFeature: *%s ", opt->name);
-                if (opt->type == TYPE_BOOL)
-                    dstrcatf(open, is_true_string(userval) ? "True\n" : "False\n");
-                else
-                    dstrcatf(open, "%s\n", userval);
-                dstrcpyf(close, "\n%%%%EndFeature\n} stopped cleartomark\n");
-
-                switch (option_get_section(opt)) {
-                    case SECTION_PROLOG:
-                        dstrcatf(prologprepend, "%s%s%s", open->data, cmdvar->data, close->data);
-                        break;
-
-                    case SECTION_ANYSETUP:
-                        if (optset != optionset("currentpage"))
-                            dstrcatf(setupprepend, "%s%s%s", open->data, cmdvar->data, close->data);
-                        else if (strcmp(option_get_value(opt, optionset("header")), userval) != 0)
-                            dstrcatf(pagesetupprepend, "%s%s%s", open->data, cmdvar->data, close->data);
-                        break;
-
-                    case SECTION_DOCUMENTSETUP:
-                        dstrcatf(setupprepend, "%s%s%s", open->data, cmdvar->data, close->data);
-                        break;
-
-                    case SECTION_PAGESETUP:
-                        dstrcatf(pagesetupprepend, "%s%s%s", open->data, cmdvar->data, close->data);
-                        break;
-
-                    case SECTION_JCLSETUP:          /* PCL/JCL argument */
-                        s = malloc(cmdvar->len +1);
-                        unhexify(s, cmdvar->len +1, cmdvar->data);
-                        dstrcatf(local_jclprepend, "%s", s);
-                        free(s);
-                        break;
-
-                    default:
-                        dstrcatf(setupprepend, "%s%s%s", open->data, cmdvar->data, close->data);
-                }
-            }
-        }
-        else if (option_is_jcl_arg(opt)) {
-            jcl = 1;
-            /* Put JCL commands onto JCL stack */
-            if (cmdvar->len) {
-                char *s = malloc(cmdvar->len +1);
-                unhexify(s, cmdvar->len +1, cmdvar->data);
-                if (!startswith(cmdvar->data, jclprefix))
-                    dstrcatf(local_jclprepend, "%s%s\n", jclprefix, s);
-                else
-                    dstrcat(local_jclprepend, s);
-                free(s);
-            }
-        }
-        else if (option_is_commandline_arg(opt) && cmdline) {
-            /* Insert the processed argument in the command line
-            just before every occurrence of the spot marker. */
-            p = malloc(3);
-            snprintf(p, 3, "%%%c", opt->spot);
-            s = malloc(cmdvar->len +3);
-            snprintf(s, cmdvar->len +3, "%s%%%c", cmdvar->data, opt->spot);
-            dstrreplace(cmdline, p, s, 0);
-            free(p);
-            free(s);
-        }
-
-        /* Insert option into command line of CUPS raster driver */
-        if (cmdline && strstr(cmdline->data, "%Y")) {
-            if (isempty(userval))
-                continue;
-            s = malloc(strlen(opt->name) + strlen(userval) + 20);
-            sprintf(s, "%s=%s %%Y", opt->name, userval);
-            dstrreplace(cmdline, "%Y", s, 0);
-            free(s);
-        }
-    }
-
-    /* Tidy up after computing option statements for all of P, J, and C types: */
-
-    /* C type finishing */
-    /* Pluck out all of the %n's from the command line prototype */
-    if (cmdline) {
-        s = strtok(letters, " ");
-        do {
-            dstrreplace(cmdline, s, "", 0);
-        } while ((s = strtok(NULL, " ")));
-    }
-
-    /* J type finishing */
-    /* Compute the proper stuff to say around the job */
-    if (jcl && !jobhasjcl) {
-        /* command to switch to the interpreter */
-        dstrcatf(local_jclprepend, "%s", jcltointerpreter);
-
-        /* Arrange for JCL RESET command at the end of job */
-        dstrcpy(jclappend, jclend);
-
-        argv_free(jclprepend);
-        jclprepend = argv_split(local_jclprepend->data, "\r\n", NULL);
-    }
-
-    free_dstr(cmdvar);
-    free_dstr(open);
-    free_dstr(close);
-    free_dstr(local_jclprepend);
-
-    return !isempty(cmd);
-}
-
-/* if "comments" is set, add "%%BeginProlog...%%EndProlog" */
-void append_prolog_section(dstr_t *str, int optset, int comments)
-{
-    /* Start comment */
-    if (comments) {
-        _log("\"Prolog\" section is missing, inserting it.\n");
-        dstrcat(str, "%%BeginProlog\n");
-    }
-
-    /* Generate the option code (not necessary when CUPS is spooler and
-       PostScript data is not converted from PDF) */
-    if ((spooler != SPOOLER_CUPS) || pdfconvertedtops) {
-        _log("Inserting option code into \"Prolog\" section.\n");
-        build_commandline(optset, NULL, 0);
-        dstrcat(str, prologprepend->data);
-    }
-
-    /* End comment */
-    if (comments)
-        dstrcat(str, "%%EndProlog\n");
-}
-
-void append_setup_section(dstr_t *str, int optset, int comments)
-{
-    /* Start comment */
-    if (comments) {
-        _log("\"Setup\" section is missing, inserting it.\n");
-        dstrcat(str, "%%BeginSetup\n");
-    }
-
-    /* Generate the option code (not necessary when CUPS is spooler and
-       PostScript data is not converted from PDF) */
-    if ((spooler != SPOOLER_CUPS) || pdfconvertedtops) {
-        _log("Inserting option code into \"Setup\" section.\n");
-        build_commandline(optset, NULL, 0);
-        dstrcat(str, setupprepend->data);
+    val1 = option_get_value(opt, optset1);
+    val2 = option_get_value(opt, optset2);
+
+    if (val1 && val2) // both entries exist
+    {
+      if (strcmp(val1, val2) != 0)
+       return (0); // but aren't equal
+    }
+    else if (val1 || val2) // one entry exists --> can't be equal
+      return (0);
+    // If no extry exists, the non-existing entries
+    // are considered as equal
+  }
+  return (1);
+}
+
+
+//
+// read_ppd_file()
+//
+
+void
+read_ppd_file(const char *filename)
+{
+  FILE *fh;
+  const char *tmp;
+  char *icc_qual2 = NULL;
+  char *icc_qual3 = NULL;
+  char line [256];            // PPD line length is max 255 (excl. \0)
+  char *p;
+  char key[128], name[64], text[64];
+  dstr_t *value = create_dstr(); // value can span multiple lines
+  double order;
+  value_t *val;
+  option_t *opt, *current_opt = NULL;
+  param_t *param;
+  icc_mapping_entry_t *entry;
+
+  fh = fopen(filename, "r");
+  if (!fh)
+    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Unable to open PPD file %s\n", filename);
+  _log("Parsing PPD file ...\n");
+
+  dstrassure(value, 256);
+
+  qualifier_data = list_create();
+  while (!feof(fh))
+  {
+    tmp = fgets(line, 256, fh);
+
+    if (line[0] != '*' || startswith(line, "*%"))
+      continue;
+
+    // get the key
+    if (!(p = strchr(line, ':')))
+      continue;
+    *p = '\0';
+
+    key[0] = name[0] = text[0] = '\0';
+    sscanf(line, "*%127s%*[ \t]%63[^ \t/=)]%*1[/=]%63[^\n]", key, name, text);
+
+    // get the value
+    dstrclear(value);
+    sscanf(p +1, " %255[^\r\n]", value->data);
+    value->len = strlen(value->data);
+    if (!value->len)
+      _log("PPD: Missing value for key \"%s\"\n", line);
+
+    while (1)
+    {
+      // "&&" is the continue-on-next-line marker
+      if (dstrendswith(value, "&&"))
+      {
+       value->len -= 2;
+       value->data[value->len] = '\0';
+      }
+      // quoted but quotes are not yet closed
+      else if (value->data[0] == '\"' && !strchr(value->data +1, '\"'))
+       dstrcat(value, "\n"); // keep newlines in quoted string
+      // not quoted, or quotes already closed
+      else
+       break;
+
+      tmp = fgets(line, 256, fh);
+      dstrcat(value, line);
+      dstrremovenewline(value);
+    }
+
+    // remove quotes
+    if (value->data[0] == '\"')
+    {
+      memmove(value->data, value->data +1, value->len +1);
+      p = strrchr(value->data, '\"');
+      if (!p)
+      {
+       _log("Invalid line: \"%s: ...\"\n", key);
+       continue;
+      }
+      *p = '\0';
+    }
+    // remove last newline
+    dstrremovenewline(value);
+
+    // remove last whitespace
+    dstrtrim_right(value);
+
+    // process key/value pairs
+    if (strcmp(key, "NickName") == 0)
+    {
+      unhtmlify(printer_model, 256, value->data);
+    }
+    else if (strcmp(key, "FoomaticIDs") == 0)
+    {
+      // *FoomaticIDs: <printer ID> <driver ID>
+      sscanf(value->data, "%*[ \t]%127[^ \t]%*[ \t]%127[^ \t\n]",
+            printer_id, driver);
+    }
+    else if (strcmp(key, "FoomaticRIPPostPipe") == 0)
+    {
+      if (!postpipe)
+       postpipe = create_dstr();
+      dstrassure(postpipe, value->len +128);
+      unhtmlify(postpipe->data, postpipe->alloc, value->data);
+    }
+    else if (strcmp(key, "FoomaticRIPCommandLine") == 0)
+    {
+      unhtmlify(cmd, 4096, value->data);
+    }
+    else if (strcmp(key, "FoomaticRIPCommandLinePDF") == 0)
+    {
+      unhtmlify(cmd_pdf, 4096, value->data);
+    }
+    else if (!strcmp(key, "cupsFilter"))
+    {
+      // cupsFilter: <code>
+      // only save the filter for "application/vnd.cups-raster"
+      if (prefixcmp(value->data, "application/vnd.cups-raster") == 0)
+      {
+       p = strrchr(value->data, ' ');
+       if (p)
+         unhtmlify(cupsfilter, 256, p +1);
+      }
+    }
+    else if (startswith(key, "Custom") && !strcasecmp(name, "true"))
+    {
+      // Cups custom option: *CustomFoo True: "command"
+      if (startswith(&key[6], "JCL"))
+      {
+       opt = assure_option(&key[9]);
+       opt->style = 'J';
+      }
+      else
+       opt = assure_option(&key[6]);
+      option_set_custom_command(opt, value->data);
+      if (!strcmp(key, "CustomPageSize"))
+       option_set_custom_command(assure_option("PageRegion"), value->data);
+    }
+    else if (startswith(key, "ParamCustom"))
+    {
+      // Cups custom parameter:
+      // *ParamCustomFoo Name/Text: order type minimum maximum
+      if (startswith(&key[11], "JCL"))
+       opt = assure_option(&key[14]);
+      else
+       opt = assure_option(&key[11]);
+      option_add_custom_param_from_string(opt, name, text, value->data);
+    }
+    else if (!strcmp(key, "OpenUI") || !strcmp(key, "JCLOpenUI"))
+    {
+      // "*[JCL]OpenUI *<option>[/<translation>]: <type>"
+      current_opt = assure_option(&name[1]);
+      if (!isempty(text))
+       strlcpy(current_opt->text, text, 128);
+      if (startswith(key, "JCL"))
+       current_opt->style = 'J';
+      // Set the argument type only if not defined yet,
+      // a definition in "*FoomaticRIPOption" has priority
+      if (current_opt->type == TYPE_NONE)
+       current_opt->type = type_from_string(value->data);
+    }
+    else if (!strcmp(key, "CloseUI") || !strcmp(key, "JCLCloseUI"))
+    {
+      // *[JCL]CloseUI: *<option>
+      if (!current_opt || !option_has_name(current_opt, value->data +1))
+       _log("CloseUI found without corresponding OpenUI (%s).\n",
+            value->data +1);
+      current_opt = NULL;
+    }
+    else if (!strcmp(key, "FoomaticRIPOption"))
+    {
+      // "*FoomaticRIPOption <option>: <type> <style> <spot> [<order>]"
+      // <order> only used for 1-choice enum options
+      option_set_from_string(assure_option(name), value->data);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionPrototype"))
+    {
+      // "*FoomaticRIPOptionPrototype <option>: <code>"
+      // Used for numerical and string options only
+      opt = assure_option(name);
+      opt->proto = malloc(65536);
+      unhtmlify(opt->proto, 65536, value->data);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionRange"))
+    {
+      // *FoomaticRIPOptionRange <option>: <min> <max>
+      // Used for numerical options only
+      param = option_assure_foomatic_param(assure_option(name));
+      sscanf(value->data, "%19s %19s", param->min, param->max);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionMaxLength"))
+    {
+      // "*FoomaticRIPOptionMaxLength <option>: <length>"
+      // Used for string options only
+      param = option_assure_foomatic_param(assure_option(name));
+      sscanf(value->data, "%19s", param->max);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionAllowedChars"))
+    {
+      // *FoomaticRIPOptionAllowedChars <option>: <code>
+      // Used for string options only
+      param = option_assure_foomatic_param(assure_option(name));
+      param_set_allowed_chars(param, value->data);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionAllowedRegExp"))
+    {
+      // "*FoomaticRIPOptionAllowedRegExp <option>: <code>"
+      // Used for string options only
+      param = option_assure_foomatic_param(assure_option(name));
+      param_set_allowed_regexp(param, value->data);
+    }
+    else if (!strcmp(key, "OrderDependency"))
+    {
+      // OrderDependency: <order> <section> *<option>
+      // use 'text' to read <section>
+      sscanf(value->data, "%lf %63s *%63s", &order, text, name);
+      opt = assure_option(name);
+      opt->section = section_from_string(text);
+      option_set_order(opt, order);
     }
 
-    /* End comment */
-    if (comments)
-        dstrcat(str, "%%EndSetup\n");
+    // Default options are not yet validated (not all options/choices
+    // have been read yet)
+    else if (!prefixcmp(key, "Default"))
+    {
+      // Default<option>: <value>
+      opt = assure_option(&key[7]);
+      val = option_assure_value(opt, optionset("default"));
+      free(val->value);
+      val->value = strdup(value->data);
+    }
+    else if (!prefixcmp(key, "FoomaticRIPDefault"))
+    {
+      // FoomaticRIPDefault<option>: <value>
+      // Used for numerical options only
+      opt = assure_option(&key[18]);
+      val = option_assure_value(opt, optionset("default"));
+      free(val->value);
+      val->value = strdup(value->data);
+    }
+
+    // Current argument
+    else if (current_opt && !strcmp(key, current_opt->name))
+    {
+      // *<option> <choice>[/translation]: <code>
+      option_set_choice(current_opt, name, text, value->data);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionSetting"))
+    {
+      // "*FoomaticRIPOptionSetting <option>[=<choice>]: <code>
+      // For boolean options <choice> is not given
+      option_set_choice(assure_option(name),
+                       isempty(text) ? "true" : text, NULL, value->data);
+    }
+
+    // "*(Foomatic|)JCL(Begin|ToPSInterpreter|End|Prefix): <code>"
+    // The printer supports PJL/JCL when there is such a line
+    else if (!prefixcmp(key, "JCLBegin") ||
+            !prefixcmp(key, "FoomaticJCLBegin"))
+    {
+      unhexify(jclbegin, 256, value->data);
+      if (!jclprefixset && strstr(jclbegin, "PJL") == NULL)
+       jclprefix[0] = '\0';
+    }
+    else if (!prefixcmp(key, "JCLToPSInterpreter") ||
+            !prefixcmp(key, "FoomaticJCLToPSInterpreter"))
+    {
+      unhexify(jcltointerpreter, 256, value->data);
+    }
+    else if (!prefixcmp(key, "JCLEnd") ||
+            !prefixcmp(key, "FoomaticJCLEnd"))
+    {
+      unhexify(jclend, 256, value->data);
+    }
+    else if (!prefixcmp(key, "JCLPrefix") ||
+            !prefixcmp(key, "FoomaticJCLPrefix"))
+    {
+      unhexify(jclprefix, 256, value->data);
+      jclprefixset = 1;
+    }
+    else if (!prefixcmp(key, "% COMDATA #"))
+    {
+      // old foomtic 2.0.x PPD file
+      _log("You are using an old Foomatic 2.0 PPD file, which is no "
+          "longer supported by Foomatic >4.0. Exiting.\n");
+      exit(1); // TODO exit more gracefully
+    }
+    else if (!strcmp(key, "FoomaticRIPJobEntityMaxLength"))
+    {
+      //  "*FoomaticRIPJobEntityMaxLength: <length>"
+      sscanf(value->data, "%d", &jobentitymaxlen);
+    }
+    else if (!strcmp(key, "FoomaticRIPUserEntityMaxLength"))
+    {
+      //  "*FoomaticRIPUserEntityMaxLength: <length>"
+      sscanf(value->data, "%d", &userentitymaxlen);
+    }
+    else if (!strcmp(key, "FoomaticRIPHostEntityMaxLength"))
+    {
+      //  "*FoomaticRIPHostEntityMaxLength: <length>"
+      sscanf(value->data, "%d", &hostentitymaxlen);
+    }
+    else if (!strcmp(key, "FoomaticRIPTitleEntityMaxLength"))
+    {
+      //  "*FoomaticRIPTitleEntityMaxLength: <length>"
+      sscanf(value->data, "%d", &titleentitymaxlen);
+    }
+    else if (!strcmp(key, "FoomaticRIPOptionsEntityMaxLength"))
+    {
+      //  "*FoomaticRIPOptionsEntityMaxLength: <length>"
+      sscanf(value->data, "%d", &optionsentitymaxlen);
+    }
+    else if (!strcmp(key, "cupsICCProfile"))
+    {
+      //  "*cupsICCProfile: <qualifier/Title> <filename>"
+      entry = calloc(1, sizeof(icc_mapping_entry_t));
+      entry->qualifier = strdup(name);
+      entry->filename = strdup(value->data);
+      list_append (qualifier_data, entry);
+    }
+    else if (!strcmp(key, "cupsICCQualifier2"))
+    {
+      //  "*cupsICCQualifier2: <value>"
+      icc_qual2 = strdup(value->data);
+    }
+    else if (!strcmp(key, "cupsICCQualifier3"))
+    {
+      //  "*cupsICCQualifier3: <value>"
+      icc_qual3 = strdup(value->data);
+    }
+  }
+
+  fclose(fh);
+  free_dstr(value);
+
+  // Validate default options by resetting them with option_set_value()
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    val = option_find_value(opt, optionset("default"));
+    if (val)
+    {
+      // if fromopt is set, this value has already been validated
+      if (!val->fromoption)
+       option_set_value(opt, optionset("default"), val->value);
+    }
+    else
+      // Make sure that this option has a default choice, even if none is
+      // defined in the PPD file
+      option_set_value(opt, optionset("default"), opt->choicelist->value);
+  }
+
+  // create qualifier for this PPD
+  qualifier = calloc(4, sizeof(char*));
+
+  // get colorspace
+  tmp = option_get_value(find_option("ColorSpace"), optionset("default"));
+  if (tmp == NULL)
+    tmp = option_get_value(find_option("ColorModel"), optionset("default"));
+  if (tmp == NULL)
+    tmp = "";
+  qualifier[0] = strdup(tmp);
+
+  // get selector2
+  if (icc_qual2 == NULL)
+    icc_qual2 = strdup("MediaType");
+  tmp = option_get_value(find_option(icc_qual2), optionset("default"));
+  if (tmp == NULL)
+    tmp = "";
+  qualifier[1] = strdup(tmp);
+
+  // get selectors
+  if (icc_qual3 == NULL)
+    icc_qual3 = strdup("Resolution");
+  tmp = option_get_value(find_option(icc_qual3), optionset("default"));
+  if (tmp == NULL)
+    tmp = "";
+  qualifier[2] = strdup(tmp);
+
+  free (icc_qual2);
+  free (icc_qual3);
+}
+
+
+int
+ppd_supports_pdf()
+{
+  option_t *opt;
+
+  // If at least one option inserts PostScript code, we cannot support PDF
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    choice_t *choice;
+
+    if (!option_is_ps_command(opt) || option_is_composite(opt) ||
+       (opt->type == TYPE_NONE))
+      continue;
+
+    for (choice = opt->choicelist; choice; choice = choice->next)
+      if (contains_active_postscript(choice->command))
+      {
+       _log("  PostScript option found: %s=%s: \"%s\"\n",
+            opt->name, choice->value, choice->command);
+       return (0);
+      }
+  }
+
+  if (!isempty(cmd_pdf))
+    return (1);
+
+  // Ghostscript also accepts PDF, use that if it is in the normal command
+  // line
+  if (startswith(cmd, "gs"))
+  {
+    strncpy(cmd_pdf, cmd, 4096);
+    if (strlen(cmd) > 4095)
+      cmd_pdf[4095] = '\0';
+    return (1);
+  }
+
+  _log("  Neither PDF renderer command line nor Ghostscript-based renderer command line found\n");
+  return (0);
+}
+
+
+// build a renderer command line, based on the given option set
+int
+build_commandline(int optset,
+                 dstr_t *cmdline,
+                 int pdfcmdline)
+{
+  option_t *opt;
+  const char *userval;
+  char *s, *p;
+  dstr_t *cmdvar = create_dstr();
+  dstr_t *open = create_dstr();
+  dstr_t *close = create_dstr();
+  char letters[] = "%A %B %C %D %E %F %G %H %I %J %K %L %M %W %X %Y %Z";
+  int jcl = 0;
+
+  dstr_t *local_jclprepend = create_dstr();
+
+  dstrclear(prologprepend);
+  dstrclear(setupprepend);
+  dstrclear(pagesetupprepend);
+
+  if (cmdline)
+    dstrcpy(cmdline, pdfcmdline ? cmd_pdf : cmd);
+
+  for (opt = optionlist_sorted_by_order; opt; opt = opt->next_by_order)
+  {
+    // composite options have no direct influence, and all their dependents
+    // have already been set
+    if (option_is_composite(opt))
+      continue;
+
+    userval = option_get_value(opt, optset);
+    option_get_command(cmdvar, opt, optset, -1);
+
+    // Insert the built snippet at the correct place
+    if (option_is_ps_command(opt))
+    {
+      // Place this Postscript command onto the prepend queue
+      // for the appropriate section.
+      if (cmdvar->len)
+      {
+       dstrcpyf(open, "[{\n%%%%BeginFeature: *%s ", opt->name);
+       if (opt->type == TYPE_BOOL)
+         dstrcatf(open, is_true_string(userval) ? "True\n" : "False\n");
+       else
+         dstrcatf(open, "%s\n", userval);
+       dstrcpyf(close, "\n%%%%EndFeature\n} stopped cleartomark\n");
+
+       switch (option_get_section(opt))
+       {
+         case SECTION_PROLOG:
+             dstrcatf(prologprepend, "%s%s%s", open->data, cmdvar->data,
+                      close->data);
+             break;
+
+         case SECTION_ANYSETUP:
+             if (optset != optionset("currentpage"))
+               dstrcatf(setupprepend, "%s%s%s", open->data, cmdvar->data,
+                        close->data);
+             else if (strcmp(option_get_value(opt, optionset("header")),
+                             userval) != 0)
+               dstrcatf(pagesetupprepend, "%s%s%s", open->data, cmdvar->data,
+                        close->data);
+             break;
+
+         case SECTION_DOCUMENTSETUP:
+             dstrcatf(setupprepend, "%s%s%s", open->data, cmdvar->data,
+                      close->data);
+             break;
+
+         case SECTION_PAGESETUP:
+             dstrcatf(pagesetupprepend, "%s%s%s", open->data, cmdvar->data,
+                      close->data);
+             break;
+
+         case SECTION_JCLSETUP:          // PCL/JCL argument
+             s = malloc(cmdvar->len +1);
+             unhexify(s, cmdvar->len +1, cmdvar->data);
+             dstrcatf(local_jclprepend, "%s", s);
+             free(s);
+             break;
+
+         default:
+             dstrcatf(setupprepend, "%s%s%s", open->data, cmdvar->data,
+                      close->data);
+       }
+      }
+    }
+    else if (option_is_jcl_arg(opt))
+    {
+      jcl = 1;
+      // Put JCL commands onto JCL stack
+      if (cmdvar->len)
+      {
+       char *s = malloc(cmdvar->len +1);
+       unhexify(s, cmdvar->len +1, cmdvar->data);
+       if (!startswith(cmdvar->data, jclprefix))
+         dstrcatf(local_jclprepend, "%s%s\n", jclprefix, s);
+       else
+         dstrcat(local_jclprepend, s);
+       free(s);
+      }
+    }
+    else if (option_is_commandline_arg(opt) && cmdline)
+    {
+      // Insert the processed argument in the command line
+      // just before every occurrence of the spot marker.
+      p = malloc(3);
+      snprintf(p, 3, "%%%c", opt->spot);
+      s = malloc(cmdvar->len +3);
+      snprintf(s, cmdvar->len +3, "%s%%%c", cmdvar->data, opt->spot);
+      dstrreplace(cmdline, p, s, 0);
+      free(p);
+      free(s);
+    }
+
+    // Insert option into command line of CUPS raster driver
+    if (cmdline && strstr(cmdline->data, "%Y"))
+    {
+      if (isempty(userval))
+       continue;
+      s = malloc(strlen(opt->name) + strlen(userval) + 20);
+      sprintf(s, "%s=%s %%Y", opt->name, userval);
+      dstrreplace(cmdline, "%Y", s, 0);
+      free(s);
+    }
+  }
+
+  // Tidy up after computing option statements for all of P, J, and C types:
+
+  // C type finishing
+  // Pluck out all of the %n's from the command line prototype
+  if (cmdline)
+  {
+    s = strtok(letters, " ");
+    do
+    {
+      dstrreplace(cmdline, s, "", 0);
+    }
+    while ((s = strtok(NULL, " ")));
+  }
+
+  // J type finishing
+  // Compute the proper stuff to say around the job
+  if (jcl && !jobhasjcl)
+  {
+    // command to switch to the interpreter
+    dstrcatf(local_jclprepend, "%s", jcltointerpreter);
+
+    // Arrange for JCL RESET command at the end of job
+    dstrcpy(jclappend, jclend);
+
+    argv_free(jclprepend);
+    jclprepend = argv_split(local_jclprepend->data, "\r\n", NULL);
+  }
+
+  free_dstr(cmdvar);
+  free_dstr(open);
+  free_dstr(close);
+  free_dstr(local_jclprepend);
+
+  return (!isempty(cmd));
 }
 
-void append_page_setup_section(dstr_t *str, int optset, int comments)
+
+// if "comments" is set, add "%%BeginProlog...%%EndProlog"
+void
+append_prolog_section(dstr_t *str,
+                     int optset,
+                     int comments)
 {
-    /* Start comment */
-    if (comments) {
-        _log("\"PageSetup\" section is missing, inserting it.\n");
-        dstrcat(str, "%%BeginPageSetup\n");
-    }
+  // Start comment
+  if (comments)
+  {
+    _log("\"Prolog\" section is missing, inserting it.\n");
+    dstrcat(str, "%%BeginProlog\n");
+  }
+
+  // Generate the option code (not necessary when CUPS is spooler and
+  // PostScript data is not converted from PDF)
+  if ((spooler != SPOOLER_CUPS) || pdfconvertedtops)
+  {
+    _log("Inserting option code into \"Prolog\" section.\n");
+    build_commandline(optset, NULL, 0);
+    dstrcat(str, prologprepend->data);
+  }
+
+  // End comment
+  if (comments)
+    dstrcat(str, "%%EndProlog\n");
+}
+
 
-    /* Generate the option code (not necessary when CUPS is spooler) */
-    _log("Inserting option code into \"PageSetup\" section.\n");
+void
+append_setup_section(dstr_t *str,
+                    int optset,
+                    int comments)
+{
+  // Start comment
+  if (comments)
+  {
+    _log("\"Setup\" section is missing, inserting it.\n");
+    dstrcat(str, "%%BeginSetup\n");
+  }
+
+  // Generate the option code (not necessary when CUPS is spooler and
+  // PostScript data is not converted from PDF)
+  if ((spooler != SPOOLER_CUPS) || pdfconvertedtops)
+  {
+    _log("Inserting option code into \"Setup\" section.\n");
     build_commandline(optset, NULL, 0);
-    dstrcat(str, pagesetupprepend->data);
+    dstrcat(str, setupprepend->data);
+  }
+
+  // End comment
+  if (comments)
+    dstrcat(str, "%%EndSetup\n");
+}
+
 
-    /* End comment */
-    if (comments)
-        dstrcat(str, "%%EndPageSetup\n");
+void
+append_page_setup_section(dstr_t *str,
+                         int optset,
+                         int comments)
+{
+  // Start comment
+  if (comments)
+  {
+    _log("\"PageSetup\" section is missing, inserting it.\n");
+    dstrcat(str, "%%BeginPageSetup\n");
+  }
+
+  // Generate the option code (not necessary when CUPS is spooler)
+  _log("Inserting option code into \"PageSetup\" section.\n");
+  build_commandline(optset, NULL, 0);
+  dstrcat(str, pagesetupprepend->data);
+
+  // End comment
+  if (comments)
+    dstrcat(str, "%%EndPageSetup\n");
 }
 
 
-typedef struct page_range {
-    short even, odd;
-    unsigned first, last;
-    struct page_range *next;
+typedef struct page_range
+{
+  short even, odd;
+  unsigned first, last;
+  struct page_range *next;
 } page_range_t;
 
-static page_range_t * parse_page_ranges(const char *ranges)
-{
-    page_range_t *head = NULL, *tail = NULL;
-    char *tokens, *tok;
-    int cnt;
-
-    tokens = strdup(ranges);
-    for (tok = strtok(tokens, ","); tok; tok = strtok(NULL, ",")) {
-        page_range_t *pr = calloc(1, sizeof(page_range_t));
-
-        if (startswith(tok, "even"))
-            pr->even = 1;
-        else if (startswith(tok, "odd"))
-            pr->odd = 1;
-        else if ((cnt = sscanf(tok, "%u-%u", &pr->first, &pr->last))) {
-            /* If 'last' has not been read, this could mean only one page (no
-             * hyphen) or all pages to the end */
-            if (cnt == 1 && !endswith(tok, "-"))
-                pr->last = pr->first;
-            else if (cnt == 2 && pr->first > pr->last) {
-                unsigned tmp = pr->first;
-                pr->first = pr->last;
-                pr->last = tmp;
-            }
-        }
-        else {
-            _log("Invalid page range: %s\n", tok);
-            free(pr);
-            continue;
-        }
-
-        if (tail) {
-            tail->next = pr;
-            tail = pr;
-        }
-        else
-            tail = head = pr;
-    }
-
-    free(tokens);
-    return head;
-}
-
-static void free_page_ranges(page_range_t *ranges)
-{
-    page_range_t *pr;
-    while (ranges) {
-        pr = ranges;
-        ranges = ranges->next;
-        free(pr);
-    }
-}
-
-/* Parse a string containing page ranges and either check whether a
-   given page is in the ranges or, if the given page number is zero,
-   determine the score how specific this page range string is.*/
-int get_page_score(const char *pages, int page)
-{
-    page_range_t *ranges = parse_page_ranges(pages);
-    page_range_t *pr;
-    int totalscore = 0;
-    int pageinside = 0;
-
-    for (pr = ranges; pr; pr = pr->next) {
-        if (pr->even) {
-            totalscore += 50000;
-            if (page % 2 == 0)
-                pageinside = 1;
-        }
-        else if (pr->odd) {
-            totalscore += 50000;
-            if (page % 2 == 1)
-                pageinside = 1;
-        }
-        else if (pr->first == pr->last) {   /* Single page */
-            totalscore += 1;
-            if (page == pr->first)
-                pageinside = 1;
-        }
-        else if (pr->last == 0) {           /* To the end of the document */
-            totalscore += 100000;
-            if (page >= pr->first)
-                pageinside = 1;
-        }
-        else {                              /* Sequence of pages */
-            totalscore += pr->last - pr->first +1;
-            if (page >= pr->first && page <= pr->last)
-                pageinside = 1;
-        }
-    }
-
-    free_page_ranges(ranges);
-
-    if (page == 0 || pageinside)
-        return totalscore;
-
-    return 0;
-}
-
-/* Set the options for a given page */
-void set_options_for_page(int optset, int page)
-{
-    int score, bestscore;
-    option_t *opt;
-    value_t *val, *bestvalue;
-    const char *ranges;
-    const char *optsetname;
-
-    for (opt = optionlist; opt; opt = opt->next) {
-
-        bestscore = 10000000;
-        bestvalue = NULL;
-        for (val = opt->valuelist; val; val = val->next) {
-
-            optsetname = optionset_name(val->optionset);
-            if (!startswith(optsetname, "pages:"))
-                continue;
-
-            ranges = &optsetname[6]; /* after "pages:" */
-            score = get_page_score(ranges, page);
-            if (score && score < bestscore) {
-                bestscore = score;
-                bestvalue = val;
-            }
-        }
 
-        if (bestvalue)
-            option_set_value(opt, optset, bestvalue->value);
+static page_range_t *
+parse_page_ranges(const char *ranges)
+{
+  page_range_t *head = NULL, *tail = NULL;
+  char *tokens, *tok;
+  int cnt;
+
+  tokens = strdup(ranges);
+  for (tok = strtok(tokens, ","); tok; tok = strtok(NULL, ","))
+  {
+    page_range_t *pr = calloc(1, sizeof(page_range_t));
+
+    if (startswith(tok, "even"))
+      pr->even = 1;
+    else if (startswith(tok, "odd"))
+      pr->odd = 1;
+    else if ((cnt = sscanf(tok, "%u-%u", &pr->first, &pr->last)))
+    {
+      // If 'last' has not been read, this could mean only one page (no
+      // hyphen) or all pages to the end
+      if (cnt == 1 && !endswith(tok, "-"))
+       pr->last = pr->first;
+      else if (cnt == 2 && pr->first > pr->last)
+      {
+       unsigned tmp = pr->first;
+       pr->first = pr->last;
+       pr->last = tmp;
+      }
+    }
+    else
+    {
+      _log("Invalid page range: %s\n", tok);
+      free(pr);
+      continue;
     }
+
+    if (tail)
+    {
+      tail->next = pr;
+      tail = pr;
+    }
+    else
+      tail = head = pr;
+  }
+
+  free(tokens);
+  return (head);
 }
 
+
+static
+void free_page_ranges(page_range_t *ranges)
+{
+  page_range_t *pr;
+  while (ranges)
+  {
+    pr = ranges;
+    ranges = ranges->next;
+    free(pr);
+  }
+}
+
+
+// Parse a string containing page ranges and either check whether a
+// given page is in the ranges or, if the given page number is zero,
+// determine the score how specific this page range string is.
+int
+get_page_score(const char *pages,
+              int page)
+{
+  page_range_t *ranges = parse_page_ranges(pages);
+  page_range_t *pr;
+  int totalscore = 0;
+  int pageinside = 0;
+
+  for (pr = ranges; pr; pr = pr->next)
+  {
+    if (pr->even)
+    {
+      totalscore += 50000;
+      if (page % 2 == 0)
+       pageinside = 1;
+    }
+    else if (pr->odd)
+    {
+      totalscore += 50000;
+      if (page % 2 == 1)
+       pageinside = 1;
+    }
+    else if (pr->first == pr->last)   // Single page
+    {
+      totalscore += 1;
+      if (page == pr->first)
+       pageinside = 1;
+    }
+    else if (pr->last == 0)           // To the end of the document
+    {
+      totalscore += 100000;
+      if (page >= pr->first)
+       pageinside = 1;
+    }
+    else                              // Sequence of pages
+    {
+      totalscore += pr->last - pr->first +1;
+      if (page >= pr->first && page <= pr->last)
+       pageinside = 1;
+    }
+  }
+
+  free_page_ranges(ranges);
+
+  if (page == 0 || pageinside)
+    return (totalscore);
+
+  return (0);
+}
+
+
+// Set the options for a given page
+void
+set_options_for_page(int optset,
+                    int page)
+{
+  int score, bestscore;
+  option_t *opt;
+  value_t *val, *bestvalue;
+  const char *ranges;
+  const char *optsetname;
+
+  for (opt = optionlist; opt; opt = opt->next)
+  {
+    bestscore = 10000000;
+    bestvalue = NULL;
+    for (val = opt->valuelist; val; val = val->next)
+    {
+      optsetname = optionset_name(val->optionset);
+      if (!startswith(optsetname, "pages:"))
+       continue;
+
+      ranges = &optsetname[6]; // after "pages:"
+      score = get_page_score(ranges, page);
+      if (score && score < bestscore)
+      {
+       bestscore = score;
+       bestvalue = val;
+      }
+    }
+
+    if (bestvalue)
+      option_set_value(opt, optset, bestvalue->value);
+  }
+}
index 3dd09795fc3ee84916a29d896ed76001d8b82642..5752a50a9c08051e7fe915360a2a6124b766ce13 100644 (file)
@@ -1,25 +1,26 @@
-/* options.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// options.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef options_h
 #define options_h
@@ -29,7 +30,7 @@
 #include <regex.h>
 #include "util.h"
 
-/* Option types */
+// Option types
 #define TYPE_NONE       0
 #define TYPE_ENUM       1
 #define TYPE_PICKMANY   2
@@ -43,7 +44,7 @@
 #define TYPE_PASSCODE   10
 #define TYPE_POINTS     11
 
-/* Sections */
+// Sections
 #define SECTION_ANYSETUP        1
 #define SECTION_PAGESETUP       2
 #define SECTION_PROLOG          3
 
 
 
-typedef struct choice_s {
-    char value [128];
-    char text [128];
-    char command[65536];
-    struct choice_s *next;
+typedef struct choice_s
+{
+  char value [128];
+  char text [128];
+  char command[65536];
+  struct choice_s *next;
 } choice_t;
 
-/* Custom option parameter */
-typedef struct param_s {
-    char name [128];
-    char text [128];       /* formerly comment, changed to 'text' to
-                              be consistent with cups */
-    int order;
+// Custom option parameter
+typedef struct param_s
+{
+  char name [128];
+  char text [128];       // formerly comment, changed to 'text' to
+                         // be consistent with cups
+  int order;
 
-    int type;
-    char min[20], max[20]; /* contents depend on 'type' */
+  int type;
+  char min[20], max[20]; // contents depend on 'type'
 
-    regex_t *allowedchars;
-    regex_t *allowedregexp;
+  regex_t *allowedchars;
+  regex_t *allowedregexp;
 
-    struct param_s *next;
+  struct param_s *next;
 } param_t;
 
-/* Option */
-typedef struct option_s {
-    char name [128];
-    char text [128];
-    char varname [128];         /* clean version of 'name' (no spaces etc.) */
-    int type;
-    int style;
-    char spot;
-    double order;
-    int section;
-
-    int notfirst;               /* TODO remove */
-
-    choice_t *choicelist;
-
-    /* Foomatic PPD extensions */
-    char *proto;                /* *FoomaticRIPOptionPrototype: if this is set
-                                   it will be used with only the first option
-                                   in paramlist (there should be only one) */
-    param_t *foomatic_param;
-
-    /* CUPS custom options */
-    char *custom_command;       /* *CustomFoo */
-    param_t *paramlist;         /* for custom values, sorted by stack order */
-    size_t param_count;
-
-    struct value_s *valuelist;
-
-    struct option_s *next;
-    struct option_s *next_by_order;
+// Option
+typedef struct option_s
+{
+  char name [128];
+  char text [128];
+  char varname [128];         // clean version of 'name' (no spaces etc.)
+  int type;
+  int style;
+  char spot;
+  double order;
+  int section;
+
+  int notfirst;               // TODO remove
+
+  choice_t *choicelist;
+
+  // Foomatic PPD extensions
+  char *proto;                // *FoomaticRIPOptionPrototype: if this is set
+                              // it will be used with only the first option
+                              // in paramlist (there should be only one)
+  param_t *foomatic_param;
+
+  // CUPS custom options
+  char *custom_command;       // *CustomFoo
+  param_t *paramlist;         // for custom values, sorted by stack order
+  size_t param_count;
+
+  struct value_s *valuelist;
+
+  struct option_s *next;
+  struct option_s *next_by_order;
 } option_t;
 
-
-/* A value for an option */
-typedef struct value_s {
-    int optionset;
-    char *value;
-    option_t *fromoption; /* This is set when this value is set by a composite */
-    struct value_s *next;
+// A value for an option
+typedef struct value_s
+{
+  int optionset;
+  char *value;
+  option_t *fromoption; // This is set when this value is set by a composite
+  struct value_s *next;
 } value_t;
 
 
@@ -135,9 +139,9 @@ int option_is_jcl_arg(option_t *opt);
 int option_is_commandline_arg(option_t *opt);
 
 
-int option_get_section(option_t *opt); /* TODO deprecated */
+int option_get_section(option_t *opt); // TODO deprecated
 
-/* handles ANYSETUP (for (PAGE|DOCUMENT)SETUP) */
+// handles ANYSETUP (for (PAGE|DOCUMENT)SETUP)
 int option_is_in_section(option_t *opt, int section);
 
 void options_init();
@@ -154,7 +158,7 @@ int ppd_supports_pdf();
 int option_set_value(option_t *opt, int optset, const char *value);
 const char * option_get_value(option_t *opt, int optset);
 
-/* section == -1 for all sections */
+// section == -1 for all sections
 int option_get_command(dstr_t *cmd, option_t *opt, int optset, int section);
 
 int option_accepts_value(option_t *opt, const char *value);
@@ -178,5 +182,4 @@ void set_options_for_page(int optset, int page);
 char *get_icc_profile_for_qualifier(const char **qualifier);
 const char **get_ppd_qualifier(void);
 
-#endif
-
+#endif // !options_h
index 83baf4d0eb20c714f6cb2604b160f0c2f45ab757..31bad47590cad798b051a0514d495640aeb68dfb 100644 (file)
@@ -1,25 +1,26 @@
-/* pdf.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// pdf.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "foomaticrip.h"
 #include "util.h"
 static int wait_for_renderer();
 
 
-int pdf_count_pages(const char *filename)
+int
+pdf_count_pages(const char *filename)
 {
-    char gscommand[CMDLINE_MAX];
-    char output[63] = "";
-    int pagecount;
-    size_t bytes;
-    char *p;
-
-    snprintf(gscommand, CMDLINE_MAX, "%s -dNODISPLAY -dNOSAFER -dNOPAUSE -q -c "
-            "'/pdffile (%s) (r) file runpdfbegin (PageCount: ) print "
-            "pdfpagecount = quit'",
-            gspath, filename);
-
-    FILE *pd = popen(gscommand, "r");
-    if (!pd)
-      rip_die(EXIT_STARVED, "Failed to execute ghostscript to determine number of input pages!\n");
-
-    bytes = fread_or_die(output, 1, sizeof(output), pd);
-    pclose(pd);
-
-    p = output;
-    pagecount = -1;
-    while (bytes > 0) {
-      if (sscanf(p, "PageCount: %d", &pagecount) >= 1)
-       break;
-      p = memchr(p, '\n', bytes);
-      if (p == NULL)
-       break;
-      p ++;
-      bytes = sizeof(output) - (p - output);
-    }
-
-    return pagecount;
+  char gscommand[CMDLINE_MAX];
+  char output[63] = "";
+  int pagecount;
+  size_t bytes;
+  char *p;
+
+  snprintf(gscommand, CMDLINE_MAX, "%s -dNODISPLAY -dNOSAFER -dNOPAUSE -q -c "
+          "'/pdffile (%s) (r) file runpdfbegin (PageCount: ) print "
+          "pdfpagecount = quit'",
+          gspath, filename);
+
+  FILE *pd = popen(gscommand, "r");
+  if (!pd)
+    rip_die(EXIT_STARVED,
+           "Failed to execute ghostscript to determine number of input pages!\n");
+
+  bytes = fread_or_die(output, 1, sizeof(output), pd);
+  pclose(pd);
+
+  p = output;
+  pagecount = -1;
+  while (bytes > 0)
+  {
+    if (sscanf(p, "PageCount: %d", &pagecount) >= 1)
+      break;
+    p = memchr(p, '\n', bytes);
+    if (p == NULL)
+      break;
+    p ++;
+    bytes = sizeof(output) - (p - output);
+  }
+
+  return (pagecount);
 }
 
 pid_t kid3 = 0;
 
 
-static int start_renderer(const char *cmd)
+static int
+start_renderer(const char *cmd)
 {
-    if (kid3 != 0)
-        wait_for_renderer();
+  if (kid3 != 0)
+    wait_for_renderer();
 
-    _log("Starting renderer with command: %s\n", cmd);
-    kid3 = start_process("kid3", exec_kid3, (void *)cmd, NULL, NULL);
-    if (kid3 < 0)
-        rip_die(EXIT_STARVED, "Could not start renderer\n");
+  _log("Starting renderer with command: %s\n", cmd);
+  kid3 = start_process("kid3", exec_kid3, (void *)cmd, NULL, NULL);
+  if (kid3 < 0)
+    rip_die(EXIT_STARVED, "Could not start renderer\n");
 
-    return 1;
+  return (1);
 }
 
-static int wait_for_renderer()
-{
-    int status;
-
-    waitpid(kid3, &status, 0);
-
-    if (!WIFEXITED(status)) {
-        _log("Kid3 did not finish normally.\n");
-        exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
-    }
-
-    _log("Kid3 exit status: %d\n", WEXITSTATUS(status));
-    if (WEXITSTATUS(status) != 0)
-        exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
-
-    kid3 = 0;
-    return 1;
-}
 
-/*
- * Extract pages 'first' through 'last' from the pdf and write them into a
- * temporary file.
- */
-static int pdf_extract_pages(char filename[PATH_MAX],
-                             const char *pdffilename,
-                             int first,
-                             int last)
+static int
+wait_for_renderer()
 {
-    char gscommand[CMDLINE_MAX];
-    char filename_arg[PATH_MAX], first_arg[50], last_arg[50];
-    int fd;
+  int status;
 
-    _log("Extracting pages %d through %d\n", first, last);
+  waitpid(kid3, &status, 0);
 
-    snprintf(filename, PATH_MAX, "%s/foomatic-XXXXXX", temp_dir());
-    if ((fd = mkstemp(filename)) == -1)
-        rip_die(EXIT_STARVED, "Unable to create temporary file!\n");
-    close (fd);
+  if (!WIFEXITED(status))
+  {
+    _log("Kid3 did not finish normally.\n");
+    exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+  }
 
-    snprintf(filename_arg, PATH_MAX, "-sOutputFile=%s", filename);
+  _log("Kid3 exit status: %d\n", WEXITSTATUS(status));
+  if (WEXITSTATUS(status) != 0)
+    exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
 
-    first_arg[0] = '\0';
-    last_arg[0] = '\0';
-    if (first > 1)
-    {
-        snprintf(first_arg, 50, "-dFirstPage=%d", first);
-        if (last >= first)
-            snprintf(last_arg, 50, "-dLastPage=%d", last);
-    }
+  kid3 = 0;
+  return (1);
+}
 
-    snprintf(gscommand, CMDLINE_MAX, "%s -q -dNOPAUSE -dBATCH -dSAFER -dNOINTERPOLATE -dNOMEDIAATTRS"
-            "-sDEVICE=pdfwrite -dShowAcroForm %s %s %s %s",
-            gspath, filename_arg, first_arg, last_arg, pdffilename);
 
-    FILE *pd = popen(gscommand, "r");
-    if (!pd)
-        rip_die(EXIT_STARVED, "Could not run ghostscript to extract the pages!\n");
-    pclose(pd);
+//
+// Extract pages 'first' through 'last' from the pdf and write them into a
+// temporary file.
+//
 
-    return 1;
+static int
+pdf_extract_pages(char filename[PATH_MAX],
+                 const char *pdffilename,
+                 int first,
+                 int last)
+{
+  char gscommand[CMDLINE_MAX];
+  char filename_arg[PATH_MAX], first_arg[50], last_arg[50];
+  int fd;
+
+  _log("Extracting pages %d through %d\n", first, last);
+
+  snprintf(filename, PATH_MAX, "%s/foomatic-XXXXXX", temp_dir());
+  if ((fd = mkstemp(filename)) == -1)
+    rip_die(EXIT_STARVED, "Unable to create temporary file!\n");
+  close (fd);
+
+  snprintf(filename_arg, PATH_MAX, "-sOutputFile=%s", filename);
+
+  first_arg[0] = '\0';
+  last_arg[0] = '\0';
+  if (first > 1)
+  {
+    snprintf(first_arg, 50, "-dFirstPage=%d", first);
+    if (last >= first)
+      snprintf(last_arg, 50, "-dLastPage=%d", last);
+  }
+
+  snprintf(gscommand, CMDLINE_MAX, "%s -q -dNOPAUSE -dBATCH -dSAFER -dNOINTERPOLATE -dNOMEDIAATTRS"
+          "-sDEVICE=pdfwrite -dShowAcroForm %s %s %s %s",
+          gspath, filename_arg, first_arg, last_arg, pdffilename);
+
+  FILE *pd = popen(gscommand, "r");
+  if (!pd)
+    rip_die(EXIT_STARVED, "Could not run ghostscript to extract the pages!\n");
+  pclose(pd);
+
+  return (1);
 }
 
-static int render_pages_with_generic_command(dstr_t *cmd,
-                                             const char *filename,
-                                             int firstpage,
-                                             int lastpage)
+
+static int
+render_pages_with_generic_command(dstr_t *cmd,
+                                 const char *filename,
+                                 int firstpage,
+                                 int lastpage)
 {
-    char tmpfile[PATH_MAX];
-    int result;
+  char tmpfile[PATH_MAX];
+  int result;
 
-    /* TODO it might be a good idea to give pdf command lines the possibility
-     * to get the file on the command line rather than piped through stdin
-     * (maybe introduce a &filename; ??) */
+  // TODO it might be a good idea to give pdf command lines the possibility
+  // to get the file on the command line rather than piped through stdin
+  // (maybe introduce a &filename; ??)
 
-    if (lastpage < 0)  /* i.e. print the whole document */
-        dstrcatf(cmd, " < %s", filename);
-    else
-    {
-        if (!pdf_extract_pages(tmpfile, filename, firstpage, lastpage))
-            rip_die(EXIT_STARVED, "Could not run ghostscript to extract the pages!\n");
-        dstrcatf(cmd, " < %s", tmpfile);
-    }
+  if (lastpage < 0)  // i.e. print the whole document
+    dstrcatf(cmd, " < %s", filename);
+  else
+  {
+    if (!pdf_extract_pages(tmpfile, filename, firstpage, lastpage))
+      rip_die(EXIT_STARVED,
+             "Could not run ghostscript to extract the pages!\n");
+    dstrcatf(cmd, " < %s", tmpfile);
+  }
 
-    result = start_renderer(cmd->data);
+  result = start_renderer(cmd->data);
 
-    if (lastpage > 0)
-        unlink(tmpfile);
+  if (lastpage > 0)
+    unlink(tmpfile);
 
-    return result;
+  return (result);
 }
 
-static int render_pages_with_ghostscript(dstr_t *cmd,
-                                         size_t start_gs_cmd,
-                                         size_t end_gs_cmd,
-                                         const char *filename,
-                                         int firstpage,
-                                         int lastpage)
-{
-    char *p;
 
-    /* No need to create a temporary file, just give ghostscript the file and
-     * first/last page on the command line */
+static int
+render_pages_with_ghostscript(dstr_t *cmd,
+                             size_t start_gs_cmd,
+                             size_t end_gs_cmd,
+                             const char *filename,
+                             int firstpage,
+                             int lastpage)
+{
+  char *p;
 
-    /* Some command lines want to read from stdin */
-    for (p = &cmd->data[end_gs_cmd -1]; isspace(*p); p--)
-        ;
-    if (*p == '-')
-        *p = ' ';
+  // No need to create a temporary file, just give ghostscript the file and
+  // first/last page on the command line
 
-    dstrinsertf(cmd, end_gs_cmd, " %s ", filename);
+  // Some command lines want to read from stdin
+  for (p = &cmd->data[end_gs_cmd -1]; isspace(*p); p--);
+  if (*p == '-')
+    *p = ' ';
 
-    dstrinsertf(cmd, start_gs_cmd + 2, " -dShowAcroForm ");
-    
-    if (firstpage > 1)
-    {
-        if (lastpage >= firstpage)
-            dstrinsertf(cmd, start_gs_cmd +2,
-                        " -dFirstPage=%d -dLastPage=%d ",
-                        firstpage, lastpage);
-        else
-            dstrinsertf(cmd, start_gs_cmd +2,
-                        " -dFirstPage=%d ", firstpage);
-    }
+  dstrinsertf(cmd, end_gs_cmd, " %s ", filename);
 
-    return start_renderer(cmd->data);
-}
+  dstrinsertf(cmd, start_gs_cmd + 2, " -dShowAcroForm ");
 
-static int render_pages(const char *filename, int firstpage, int lastpage)
-{
-    dstr_t *cmd = create_dstr();
-    size_t start, end;
-    int result;
-
-    build_commandline(optionset("currentpage"), cmd, 1);
-
-    extract_command(&start, &end, cmd->data, "gs");
-    if (start == end)
-        /* command is not Ghostscript */
-        result = render_pages_with_generic_command(cmd,
-                                                   filename,
-                                                   firstpage,
-                                                   lastpage);
+  if (firstpage > 1)
+  {
+    if (lastpage >= firstpage)
+      dstrinsertf(cmd, start_gs_cmd +2,
+                 " -dFirstPage=%d -dLastPage=%d ",
+                 firstpage, lastpage);
     else
-        /* Ghostscript command, tell it which pages we want to render */
-        result = render_pages_with_ghostscript(cmd,
-                                               start,
-                                               end,
-                                               filename,
-                                               firstpage,
-                                               lastpage);
-
-    free_dstr(cmd);
-    return result;
+      dstrinsertf(cmd, start_gs_cmd +2,
+                 " -dFirstPage=%d ", firstpage);
+  }
+
+  return (start_renderer(cmd->data));
 }
 
-static int print_pdf_file(const char *filename)
+
+static int
+render_pages(const char *filename,
+            int firstpage,
+            int lastpage)
 {
-    int page_count, i;
-    int firstpage;
+  dstr_t *cmd = create_dstr();
+  size_t start, end;
+  int result;
+
+  build_commandline(optionset("currentpage"), cmd, 1);
+
+  extract_command(&start, &end, cmd->data, "gs");
+  if (start == end)
+    // command is not Ghostscript
+    result = render_pages_with_generic_command(cmd,
+                                              filename,
+                                              firstpage,
+                                              lastpage);
+  else
+    // Ghostscript command, tell it which pages we want to render
+    result = render_pages_with_ghostscript(cmd,
+                                          start,
+                                          end,
+                                          filename,
+                                          firstpage,
+                                          lastpage);
+
+  free_dstr(cmd);
+  return (result);
+}
 
-    page_count = pdf_count_pages(filename);
 
-    if (page_count < 0)
-        rip_die(EXIT_JOBERR, "Unable to determine number of pages, page count: %d\n", page_count);
-    _log("File contains %d pages\n", page_count);
-    if (page_count == 0)
+static int
+print_pdf_file(const char *filename)
+{
+  int page_count, i;
+  int firstpage;
+
+  page_count = pdf_count_pages(filename);
+
+  if (page_count < 0)
+    rip_die(EXIT_JOBERR,
+           "Unable to determine number of pages, page count: %d\n",
+           page_count);
+  _log("File contains %d pages\n", page_count);
+  if (page_count == 0)
+  {
+    _log("No pages left, outputting empty file.\n");
+    return (1);
+  }
+
+  optionset_copy_values(optionset("header"), optionset("currentpage"));
+  optionset_copy_values(optionset("currentpage"), optionset("previouspage"));
+  firstpage = 1;
+  for (i = 1; i <= page_count; i++)
+  {
+    set_options_for_page(optionset("currentpage"), i);
+    if (!optionset_equal(optionset("currentpage"),
+                        optionset("previouspage"), 1))
     {
-        _log("No pages left, outputting empty file.\n");
-        return 1;
+      render_pages(filename, firstpage, i);
+      firstpage = i;
     }
-
-    optionset_copy_values(optionset("header"), optionset("currentpage"));
     optionset_copy_values(optionset("currentpage"), optionset("previouspage"));
-    firstpage = 1;
-    for (i = 1; i <= page_count; i++)
-    {
-        set_options_for_page(optionset("currentpage"), i);
-        if (!optionset_equal(optionset("currentpage"), optionset("previouspage"), 1))
-        {
-            render_pages(filename, firstpage, i);
-            firstpage = i;
-        }
-        optionset_copy_values(optionset("currentpage"), optionset("previouspage"));
-    }
-    if (firstpage == 1)
-        render_pages(filename, 1, -1); /* Render the whole document */
-    else
-        render_pages(filename, firstpage, page_count);
+  }
+  if (firstpage == 1)
+    render_pages(filename, 1, -1); // Render the whole document
+  else
+    render_pages(filename, firstpage, page_count);
 
-    wait_for_renderer();
+  wait_for_renderer();
 
-    return 1;
+  return (1);
 }
 
-int print_pdf(FILE *s,
-              const char *alreadyread,
-              size_t len,
-              const char *filename,
-              size_t startpos)
+
+int
+print_pdf(FILE *s,
+         const char *alreadyread,
+         size_t len,
+         const char *filename,
+         size_t startpos)
 {
-    char tmpfilename[PATH_MAX] = "";
-    int result;
+  char tmpfilename[PATH_MAX] = "";
+  int result;
 
-    /* If reading from stdin, write everything into a temporary file */
-    /* TODO don't do this if there aren't any pagerange-limited options */
-    if (s == stdin)
-    {
-        int fd;
-        FILE *tmpfile;
+  // If reading from stdin, write everything into a temporary file
+  // TODO don't do this if there aren't any pagerange-limited options
+  if (s == stdin)
+  {
+    int fd;
+    FILE *tmpfile;
 
-        snprintf(tmpfilename, PATH_MAX, "%s/foomatic-XXXXXX", temp_dir());
-        fd = mkstemp(tmpfilename);
-        if (fd < 0) {
-            _log("Could not create temporary file: %s\n", strerror(errno));
-            return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-        }
+    snprintf(tmpfilename, PATH_MAX, "%s/foomatic-XXXXXX", temp_dir());
+    fd = mkstemp(tmpfilename);
+    if (fd < 0)
+    {
+      _log("Could not create temporary file: %s\n", strerror(errno));
+      return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+    }
 
-        tmpfile = fdopen(fd, "r+");
-        copy_file(tmpfile, stdin, alreadyread, len);
-        fclose(tmpfile);
+    tmpfile = fdopen(fd, "r+");
+    copy_file(tmpfile, stdin, alreadyread, len);
+    fclose(tmpfile);
 
-        filename = tmpfilename;
-    }
+    filename = tmpfilename;
+  }
 
-    result = print_pdf_file(filename);
+  result = print_pdf_file(filename);
 
-    if (!isempty(tmpfilename))
-        unlink(tmpfilename);
+  if (!isempty(tmpfilename))
+    unlink(tmpfilename);
 
-    return result;
+  return (result);
 }
 
index be410fc43c482a0336a87a67feb5aeea26c062b4..eb2cb5fe3da16ec462c918a96cdd48cb0c3cf336 100644 (file)
@@ -1,31 +1,32 @@
-/* pdf.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// pdf.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef pdf_h
 #define pdf_h
 
-int print_pdf(FILE *s, const char *alreadyread, size_t len, const char *filename, size_t startpos);
+int print_pdf(FILE *s, const char *alreadyread, size_t len,
+             const char *filename, size_t startpos);
 int pdf_count_pages(const char *filename);
 
-#endif
-
+#endif // !pdf_h
index 10f48ead5f020f951a8e2f3b5f58d6be9af99138..898b806a00f2e166db3444d4df7015e50c48ffab 100644 (file)
@@ -1,25 +1,26 @@
-/* postscript.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// postscript.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "foomaticrip.h"
 #include "util.h"
@@ -38,96 +39,101 @@ int close_renderer_handle(FILE *rendererhandle, pid_t rendererpid);
 
 #define LT_BEGIN_FEATURE 1
 #define LT_FOOMATIC_RIP_OPTION_SETTING 2
-int line_type(const char *line)
+
+
+int
+line_type(const char *line)
 {
-    const char *p;
-    if (startswith(line, "%%BeginFeature:"))
-        return LT_BEGIN_FEATURE;
-    p = line;
-    while (*p && isspace(*p)) p++;
-    if (!startswith(p, "%%"))
-        return 0;
-    p += 2;
-    while (*p && isspace(*p)) p++;
-    if (startswith(p, "FoomaticRIPOptionSetting:"))
-        return LT_FOOMATIC_RIP_OPTION_SETTING;
-    return 0;
+  const char *p;
+  if (startswith(line, "%%BeginFeature:"))
+    return (LT_BEGIN_FEATURE);
+  p = line;
+  while (*p && isspace(*p)) p++;
+  if (!startswith(p, "%%"))
+    return (0);
+  p += 2;
+  while (*p && isspace(*p)) p++;
+  if (startswith(p, "FoomaticRIPOptionSetting:"))
+    return (LT_FOOMATIC_RIP_OPTION_SETTING);
+  return (0);
 }
 
 
-/*  Next, examine the PostScript job for traces of command-line and
-    JCL options. PPD-aware applications and spoolers stuff option
-    settings directly into the file, they do not necessarily send
-    PPD options by the command line. Also stuff in PostScript code
-    to apply option settings given by the command line and to set
-    the defaults given in the PPD file.
-
-    Examination strategy: read lines from STDIN until the first
-    %%Page: comment appears and save them as @psheader. This is the
-    page-independent header part of the PostScript file. The
-    PostScript interpreter (renderer) must execute this part once
-    before rendering any assortment of pages. Then pages can be
-    printed in any arbitrary selection or order. All option
-    settings we find here will be collected in the default option
-    set for the RIP command line.
-
-    Now the pages will be read and sent to the renderer, one after
-    the other. Every page is read into memory until the
-    %%EndPageSetup comment appears (or a certain amount of lines was
-    read). So we can get option settings only valid for this
-    page. If we have such settings we set them in the modified
-    command set for this page.
-
-    If the renderer is not running yet (first page) we start it with
-    the command line built from the current modified command set and
-    send the first page to it, in the end we leave the renderer
-    running and keep input and output pipes open, so that it can
-    accept further pages. If the renderer is still running from
-    the previous page and the current modified command set is the
-    same as the one for the previous page, we send the page. If
-    the command set is different, we close the renderer, re-start
-    it with the command line built from the new modified command
-    set, send the header again, and then the page.
-
-    After the last page the trailer (%%Trailer) is sent.
-
-    The output pipe of this program stays open all the time so that
-    the spooler does not assume that the job has finished when the
-    renderer is re-started.
-
-    Non DSC-conforming documents will be read until a certain line
-    number is reached. Command line or JCL options inserted later
-    will be ignored.
-
-    If options are implemented by PostScript code supposed to be
-    stuffed into the job's PostScript data we stuff the code for all
-    these options into our job data, So all default settings made in
-    the PPD file (the user can have edited the PPD file to change
-    them) are taken care of and command line options get also
-    applied. To give priority to settings made by applications we
-    insert the options's code in the beginnings of their respective
-    sections, so that sommething, which is already inserted, gets
-    executed after our code. Missing sections are automatically
-    created. In non-DSC-conforming files we insert the option code
-    in the beginning of the file. This is the same policy as used by
-    the "pstops" filter of CUPS.
-
-    If CUPS is the spooler, the option settings were already
-    inserted by the "pstops" filter, so we don't insert them
-    again. The only thing we do is correcting settings of numerical
-    options when they were set to a value not available as choice in
-    the PPD file, As "pstops" does not support "real" numerical
-    options, it sees these settings as an invalid choice and stays
-    with the default setting. In this case we correct the setting in
-    the first occurence of the option's code, as this one is the one
-    added by CUPS, later occurences come from applications and
-    should not be touched.
-
-    If the input is not PostScript (if there is no "%!" after
-    $maxlinestopsstart lines) we will abort the document with an error.
-*/
-
-/* PostScript sections */
+//
+// Next, examine the PostScript job for traces of command-line and
+// JCL options. PPD-aware applications and spoolers stuff option
+// settings directly into the file, they do not necessarily send
+// PPD options by the command line. Also stuff in PostScript code
+// to apply option settings given by the command line and to set
+// the defaults given in the PPD file.
+//
+// Examination strategy: read lines from STDIN until the first
+// %%Page: comment appears and save them as @psheader. This is the
+// page-independent header part of the PostScript file. The
+// PostScript interpreter (renderer) must execute this part once
+// before rendering any assortment of pages. Then pages can be
+// printed in any arbitrary selection or order. All option
+// settings we find here will be collected in the default option
+// set for the RIP command line.
+//
+// Now the pages will be read and sent to the renderer, one after
+// the other. Every page is read into memory until the
+// %%EndPageSetup comment appears (or a certain amount of lines was
+// read). So we can get option settings only valid for this
+// page. If we have such settings we set them in the modified
+// command set for this page.
+//
+// If the renderer is not running yet (first page) we start it with
+// the command line built from the current modified command set and
+// send the first page to it, in the end we leave the renderer
+// running and keep input and output pipes open, so that it can
+// accept further pages. If the renderer is still running from
+// the previous page and the current modified command set is the
+// same as the one for the previous page, we send the page. If
+// the command set is different, we close the renderer, re-start
+// it with the command line built from the new modified command
+// set, send the header again, and then the page.
+//
+// After the last page the trailer (%%Trailer) is sent.
+//
+// The output pipe of this program stays open all the time so that
+// the spooler does not assume that the job has finished when the
+// renderer is re-started.
+//
+// Non DSC-conforming documents will be read until a certain line
+// number is reached. Command line or JCL options inserted later
+// will be ignored.
+//
+// If options are implemented by PostScript code supposed to be
+// stuffed into the job's PostScript data we stuff the code for all
+// these options into our job data, So all default settings made in
+// the PPD file (the user can have edited the PPD file to change
+// them) are taken care of and command line options get also
+// applied. To give priority to settings made by applications we
+// insert the options's code in the beginnings of their respective
+// sections, so that sommething, which is already inserted, gets
+// executed after our code. Missing sections are automatically
+// created. In non-DSC-conforming files we insert the option code
+// in the beginning of the file. This is the same policy as used by
+// the "pstops" filter of CUPS.
+//
+// If CUPS is the spooler, the option settings were already
+// inserted by the "pstops" filter, so we don't insert them
+// again. The only thing we do is correcting settings of numerical
+// options when they were set to a value not available as choice in
+// the PPD file, As "pstops" does not support "real" numerical
+// options, it sees these settings as an invalid choice and stays
+// with the default setting. In this case we correct the setting in
+// the first occurence of the option's code, as this one is the one
+// added by CUPS, later occurences come from applications and
+// should not be touched.
+//
+// If the input is not PostScript (if there is no "%!" after
+// $maxlinestopsstart lines) we will abort the document with an error.
+//
+
+
+// PostScript sections
 #define PS_SECTION_JCLSETUP 1
 #define PS_SECTION_PROLOG 2
 #define PS_SECTION_SETUP 3
@@ -136,1187 +142,1340 @@ int line_type(const char *line)
 #define MAX_NON_DSC_LINES_IN_HEADER 1000
 #define MAX_LINES_FOR_PAGE_OPTIONS 200
 
-typedef struct {
-    size_t pos;
+typedef struct
+{
+  size_t pos;
 
-    FILE *file;
-    const char *alreadyread;
-    size_t len;
+  FILE *file;
+  const char *alreadyread;
+  size_t len;
 } stream_t;
 
+
 void _print_ps(stream_t *stream);
 
-int stream_next_line(dstr_t *line, stream_t *s)
+
+int
+stream_next_line(dstr_t *line,
+                stream_t *s)
 {
-    int c;
-    size_t cnt = 0;
-
-    dstrclear(line);
-    while (s->pos < s->len) {
-        c = s->alreadyread[s->pos++];
-        dstrputc(line, c);
-        cnt++;
-        if (c == '\n')
-            return cnt;
+  int c;
+  size_t cnt = 0;
+
+  dstrclear(line);
+  while (s->pos < s->len)
+  {
+    c = s->alreadyread[s->pos++];
+    dstrputc(line, c);
+    cnt++;
+    if (c == '\n')
+      return (cnt);
+  }
+
+  while ((c = fgetc(s->file)) != EOF)
+  {
+    dstrputc(line, c);
+    cnt++;
+    if (c == '\n')
+      return (cnt);
+  }
+  return (cnt);
+}
+
+
+int
+print_ps(FILE *file,
+        const char *alreadyread,
+        size_t len,
+        const char *filename)
+{
+  stream_t stream;
+  char gscommand[65536];
+  int pagefound = 0;
+  FILE *in, *out;
+  pid_t pid;
+  char buf[4096];
+  struct pollfd pfd;
+  size_t bytes, bytes_sent;
+  char *pos;
+  int pres;
+  dstr_t *line = create_dstr();
+  dstr_t *data_read = create_dstr();
+
+
+  // Define input data stream for reading
+  stream.pos = 0;
+  stream.file = file;
+  stream.alreadyread = alreadyread;
+  stream.len = len;
+
+  // If a buffer is supplied but with zero length, we are in streaming
+  // mode and do not pre-check for zero-page input, but print right away
+  if (alreadyread && len == 0)
+    // Simply print the file, without checking whether it has pages
+    _print_ps(&stream);
+  else
+  {
+    //
+    // Check whether the input file is not empty
+    //
+    // We only read the input data until discovering the first page, this
+    // way we can print PostScript files streaming, allowing for very large
+    // or even infinite PostScript jobs, making use of the fact that
+    // PostScript is a streamable data format.
+    //
+    // This also allows Printer Applications to work with foomatic-rip
+    // as they have to support streaming Apple/PWG Raster input data and
+    // infinite jobs in this format. This way we can simply encapsulate the
+    // Raster data in PostScript.
+    //
+    // Ghostscript command line to find out whether the PostScript input
+    // data actually produces pages. The "bbox" output device produces two
+    // lines of output per page on stderr. We suppress any general output
+    // lines ("-q") an redirect the "bbox" output to stdout, where we can
+    // read it.
+    //
+    // "-dDEVICEWIDTHPOINTS=1 -dDEVICEHEIGHTPOINTS=1" saves Ghostscript
+    // from needing to render the pages to find out the numbers in the input
+    // lines, we only need the boolean answer whether there are pages or
+    // not
+    //
+    
+    snprintf(gscommand, 65536, "%s -q -dNOPAUSE -dBATCH -sDEVICE=bbox -dDEVICEWIDTHPOINTS=1 -dDEVICEHEIGHTPOINTS=1 -_ 2>&1",
+            CUPS_GHOSTSCRIPT);
+    // Launch Ghostscript an return file handles for stdin and stdout of the
+    // Ghostscript process
+    pid = start_system_process("Check PostScript input non-empty", gscommand,
+                              &in, &out);
+    // We will observe Ghostscript's output with non-blocking poll(), prepare
+    // data structure
+    pfd.fd = fileno(out);
+    pfd.events = POLLIN;
+
+    // Read input as long as we do not find a page ("showpage" action in
+    // PostScript, makes the "bbox" device producing output)
+    while ((stream_next_line(line, &stream)) > 0)
+    {
+      // Save what we have already read, we need to re-feed it when actually
+      // rendering the job
+      dstrncat(data_read, line->data, line->len);
+      // Feed read line into Ghostscript
+      for (bytes = line->len, pos = line->data, bytes_sent = 0;
+          bytes_sent >= 0 && bytes_sent < bytes;
+          bytes -= bytes_sent, pos += bytes_sent)
+       bytes_sent = fwrite_or_die(pos, 1, bytes, in);
+      if (bytes_sent < 0)
+       break;
+      // Flush to make Ghostscript operate in as close to real-time as
+      // possible
+      fflush(in);
+      // Check if Ghostscript produced output, but do not block if not
+      // (timeout = 0)
+      pres = poll(&pfd, 1, 0);
+      if (pres < 0)
+      {
+       _log("Error reading Ghostscript output\n");
+       break;
+      }
+      else if (pres && (pfd.revents & POLLIN))
+      {
+       // Ghostscript produced output, meaning that the data read up to now
+       // has produced a page and so the file is not empty, stop reading
+       // further data
+       pagefound = 1;
+       break;
+      }
+    }
+
+    // If the input file has only a single page and the "showpage" is
+    // very close to the end of the file, it cannot have been
+    // discovered after the last bits of input data got
+    // read. Therefore we do an extra check here.
+    if (!pagefound)
+    {
+      pres = poll(&pfd, 1, 1000);
+      if (pres < 0)
+       _log("Error reading Ghostscript output\n");
+      else if (pres && (pfd.revents & POLLIN))
+       pagefound = 1;
     }
 
-    while ((c = fgetc(s->file)) != EOF) {
-        dstrputc(line, c);
-        cnt++;
-        if (c == '\n')
-            return cnt;
+    // Clean up and make Ghostscript stop by that
+    fclose(in);
+    fclose(out);
+    wait_for_process(pid);
+
+    if (pagefound)
+    {
+      _log("File not empty, contains at least one page.\n");
+
+      // Redefine stream for what we have read now
+      if (data_read->len < len)
+       dstrncat(data_read, buf + data_read->len, len - data_read->len);
+
+      stream.pos = 0;
+      stream.file = file;
+      stream.alreadyread = data_read->data;
+      stream.len = data_read->len;
+
+      // Print the file
+      _print_ps(&stream);
     }
-    return cnt;
+    else
+      _log("No pages left, outputting empty file.\n");
+
+    free_dstr(data_read);
+  }
+
+  return (1);
 }
 
-int print_ps(FILE *file, const char *alreadyread, size_t len, const char *filename)
+
+void
+_print_ps(stream_t *stream)
 {
-    stream_t stream;
-    char gscommand[65536];
-    int pagefound = 0;
-    FILE *in, *out;
-    pid_t pid;
-    char buf[4096];
-    struct pollfd pfd;
-    size_t bytes, bytes_sent;
-    char *pos;
-    int pres;
-    dstr_t *line = create_dstr();
-    dstr_t *data_read = create_dstr();
-
-
-    /* Define input data stream for reading */
-    stream.pos = 0;
-    stream.file = file;
-    stream.alreadyread = alreadyread;
-    stream.len = len;
-
-    /* If a buffer is supplied but with zero length, we are in streaming
-       mode and do not pre-check for zero-page input, but print right away */
-    if (alreadyread && len == 0)
-      /* Simply print the file, without checking whether it has pages */
-      _print_ps(&stream);
-    else {
-      /* Check whether the input file is not empty
-
-        We only read the input data until discovering the first page, this
-        way we can print PostScript files streaming, allowing for very large
-        or even infinite PostScript jobs, making use of the fact that
-        PostScript is a streamable data format.
-
-        This also allows Printer Applications to work with foomatic-rip
-        as they have to support streaming Apple/PWG Raster input data and
-        infinite jobs in this format. This way we can simply encapsulate the
-        Raster data in PostScript.
-
-        Ghostscript command line to find out whether the PostScript input
-        data actually produces pages. The "bbox" output device produces two
-        lines of output per page on stderr. We suppress any general output
-        lines ("-q") an redirect the "bbox" output to stdout, where we can
-        read it.
-
-        "-dDEVICEWIDTHPOINTS=1 -dDEVICEHEIGHTPOINTS=1" saves Ghostscript
-        from needing to render the pages to find out the numbers in the input
-        lines, we only need the boolean answer whether there are pages or
-        not */
-      snprintf(gscommand, 65536, "%s -q -dNOPAUSE -dBATCH -sDEVICE=bbox -dDEVICEWIDTHPOINTS=1 -dDEVICEHEIGHTPOINTS=1 -_ 2>&1",
-              CUPS_GHOSTSCRIPT);
-      /* Launch Ghostscript an return file handles for stdin and stdout of the
-        Ghostscript process */
-      pid = start_system_process("Check PostScript input non-empty", gscommand, &in, &out);
-      /* We will observe Ghostscript's output with non-blocking poll(), prepare
-        data structure */
-      pfd.fd = fileno(out);
-      pfd.events = POLLIN;
-
-      /* Read input as long as we do not find a page ("showpage" action in
-        PostScript, makes the "bbox" device producing output) */
-      while ((stream_next_line(line, &stream)) > 0) {
-       /* Save what we have already read, we need to re-feed it when actually
-          rendering the job */
-       dstrncat(data_read, line->data, line->len);
-       /* Feed read line into Ghostscript */
-       for (bytes = line->len, pos = line->data, bytes_sent = 0;
-            bytes_sent >= 0 && bytes_sent < bytes;
-            bytes -= bytes_sent, pos += bytes_sent)
-         bytes_sent = fwrite_or_die(pos, 1, bytes, in);
-       if (bytes_sent < 0)
-         break;
-       /* Flush to make Ghostscript operate in as close to real-time as
-          possible */
-       fflush(in);
-       /* Check if Ghostscript produced output, but do not block if not
-          (timeout = 0) */
-       pres = poll(&pfd, 1, 0);
-       if (pres < 0) {
-         _log("Error reading Ghostscript output\n");
-         break;
-       } else if (pres && (pfd.revents & POLLIN)) {
-         /* Ghostscript produced output, meaning that the data read up to now
-            has produced a page and so the file is not empty, stop reading
-            further data */
-         pagefound = 1;
-         break;
+  char *p;
+
+  int maxlines = 1000;    // Maximum number of lines to be read  when the
+                          // documenent is not  DSC-conforming.
+                          // "$maxlines = 0"  means that all will be read and
+                          // examined. If it is  discovered that the input
+                          // file  is DSC-conforming, this will  be set to 0.
+
+  int maxlinestopsstart = 200; // That many lines are allowed until the
+                               // "%!" indicating PS comes. These
+                               // additional lines in the
+                               // beginning are usually JCL
+                               // commands. The lines will be
+                               // ignored by our parsing but
+                               // passed through.
+
+  int printprevpage = 0;  // We set this when encountering "%%Page:" and the
+                          // previous page is not printed yet. Then it will
+                          // be printed and the new page will be prepared in
+                          // the next run of the loop (we don't read a new
+                          // line and don't increase the $linect then).
+
+  int linect = 0;         // how many lines have we examined
+  int nonpslines = 0;     // lines before "%!" found yet.
+  int more_stuff = 1;     // there is more stuff in stdin
+  int saved = 0;          // DSC line not precessed yet
+  int isdscjob = 0;       // is the job dsc conforming
+  int inheader = 1;       // Are we still in the header, before first
+                          // "%%Page:" comment=
+
+  int optionsalsointoheader = 0; // 1: We are in a "%%BeginSetup...
+                                 // %%EndSetup" section after the first
+                                 // "%%Page:..." line (OpenOffice.org
+                                 // does this and intends the options here
+                                 // apply to the whole document and not
+                                 // only to the current page). We have to
+                                 // add all lines also to the end of the
+                                 // @psheader now and we have to set
+                                 // non-PostScript options also in the
+                                 // "header" optionset. 0: otherwise.
+
+  int insertoptions = 1;  // If we find out that a file with a DSC magic
+                          // string ("%!PS-Adobe-") is not really DSC-
+                          // conforming, we insert the options directly
+                          // after the line with the magic string. We use
+                          // this variable to store the number of the line
+                          // with the magic string
+
+  int prologfound = 0;    // Did we find the
+                          // "%%BeginProlog...%%EndProlog" section?
+  int setupfound = 0;     // Did we find the
+                          // "%%BeginSetup...%%EndSetup" section?
+  int pagesetupfound = 0; // special page setup handling needed
+
+  int inprolog = 0;       // We are between "%%BeginProlog" and "%%EndProlog"
+  int insetup = 0;        // We are between "%%BeginSetup" and "%%EndSetup"
+  int infeature = 0;      // We are between "%%BeginFeature" and "%%EndFeature"
+
+  int optionreplaced = 0; // Will be set to 1 when we are in an
+                          // option ("%%BeginFeature...
+                          // %%EndFeature") which we have replaced.
+
+  int postscriptsection = PS_SECTION_JCLSETUP;
+                          // In which section of the PostScript file
+                          // are we currently ?
+
+  int nondsclines = 0;    // Number of subsequent lines found which are at a
+                          // non-DSC-conforming place, between the sections
+                          // of the header.
+
+  int nestinglevel = 0;   // Are we in the main document (0) or in an
+                          // embedded document bracketed by "%%BeginDocument"
+                          // and "%%EndDocument" (>0) We do not parse the
+                          // PostScript in an embedded document.
+
+  int inpageheader = 0;   // Are we in the header of a page,
+                          // between "%%BeginPageSetup" and
+                          // "%%EndPageSetup" (1) or not (0).
+
+  int passthru = 0;       // 0: write data into psfifo,
+                          // 1: pass data directly to the renderer
+
+  int lastpassthru = 0;   // State of 'passthru' in previous line
+                          // (to allow debug output when $passthru
+                          // switches.
+
+  int ignorepageheader = 0; // Will be set to 1 as soon as active
+                            // code (not between "%%BeginPageSetup"
+                            // and "%%EndPageSetup") appears after a
+                            // "%%Page:" comment. In this case
+                            // "%%BeginPageSetup" and
+                            // "%%EndPageSetup" is not allowed any
+                            // more on this page and will be ignored.
+                            // Will be set to 0 when a new "%%Page:"
+                            // comment appears.
+
+  int optset = optionset("header"); // Where do the option settings which
+                                    // we have found go?
+
+  // current line
+  dstr_t *line = create_dstr();
+
+  dstr_t *onelinebefore = create_dstr();
+  dstr_t *twolinesbefore = create_dstr();
+
+  // The header of the PostScript file, to be send after each start of the
+  // renderer
+  dstr_t *psheader = create_dstr();
+
+  // The input FIFO, data which we have pulled from stdin for examination,
+  // but not send to the renderer yet
+  dstr_t *psfifo = create_dstr();
+
+  int ignoreline;
+
+  int ooo110 = 0;        // Flag to work around an application bug
+
+  int currentpage = 0;   // The page which we are currently printing
+
+  option_t *o;
+  const char *val;
+
+  int linetype;
+
+  dstr_t *linesafterlastbeginfeature = create_dstr();
+                         // All codelines after the last "%%BeginFeature"
+
+  char optionname [128];
+  char value [128];
+  int fromcomposite = 0;
+
+  dstr_t *pdest;
+
+  double width, height;
+
+  pid_t rendererpid = 0;
+  FILE *rendererhandle = NULL;
+
+  int retval;
+
+  dstr_t *tmp = create_dstr();
+  jobhasjcl = 0;
+
+  // We do not parse the PostScript to find Foomatic options, we check
+  // only whether we have PostScript.
+  if (dontparse)
+    maxlines = 1;
+
+  _log("Reading PostScript input ...\n");
+
+  do
+  {
+    ignoreline = 0;
+
+    if (printprevpage || saved || stream_next_line(line, stream))
+    {
+      saved = 0;
+      if (linect == nonpslines)
+      {
+       // In the beginning should be the postscript leader,
+       // sometimes after some JCL commands
+       if (!(line->data[0] == '%' && line->data[1] == '!') &&
+           !(line->data[1] == '%' && line->data[2] == '!'))
+                       // There can be a Windows control character before "%!"
+       {
+         nonpslines++;
+         if (maxlines == nonpslines)
+           maxlines ++;
+         jobhasjcl = 1;
+
+         if (nonpslines > maxlinestopsstart)
+         {
+           // This is not a PostScript job, abort it
+           _log("Job does not start with \"%%!\", is it Postscript?\n");
+           rip_die(EXIT_JOBERR, "Unknown data format.\n");
+         }
+       }
+       else
+       {
+         // Do we have a DSC-conforming document?
+         if ((line->data[0] == '%' && startswith(line->data, "%!PS-Adobe-")) ||
+             (line->data[1] == '%' && startswith(line->data, "%!PS-Adobe-")))
+         {
+           // Do not stop parsing the document
+           if (!dontparse)
+           {
+             maxlines = 0;
+             isdscjob = 1;
+             insertoptions = linect + 1;
+             // We have written into psfifo before, now we continue in
+             // psheader and move over the data which is already in psfifo
+             dstrcat(psheader, psfifo->data);
+             dstrclear(psfifo);
+           }
+           _log("--> This document is DSC-conforming!\n");
+         }
+         else
+         {
+           // Job is not DSC-conforming, stick in all PostScript
+           // option settings in the beginning
+           append_prolog_section(line, optset, 1);
+           append_setup_section(line, optset, 1);
+           append_page_setup_section(line, optset, 1);
+           prologfound = 1;
+           setupfound = 1;
+           pagesetupfound = 1;
+         }
        }
       }
-
-      /* If the input file has only a single page and the "showpage" is
-        very close to the end of the file, it cannot have been
-        discovered after the last bits of input data got
-        read. Therefore we do an extra check here. */
-      if (!pagefound) {
-       pres = poll(&pfd, 1, 1000);
-       if (pres < 0)
-         _log("Error reading Ghostscript output\n");
-       else if (pres && (pfd.revents & POLLIN))
-         pagefound = 1;
+      else
+      {
+       if (startswith(line->data, "%"))
+       {
+         if (startswith(line->data, "%%BeginDocument"))
+         {
+           // Beginning of an embedded document
+           // Note that Adobe Acrobat has a bug and so uses
+           // "%%BeginDocument " instead of "%%BeginDocument:"
+           nestinglevel++;
+           _log("Embedded document, nesting level now: %d\n", nestinglevel);
+         }
+         else if (nestinglevel > 0 &&
+                  startswith(line->data, "%%EndDocument"))
+         {
+           // End of an embedded document
+           nestinglevel--;
+           _log("End of embedded document, nesting level now: %d\n",
+                nestinglevel);
+         }
+         else if (nestinglevel == 0 && startswith(line->data, "%%Creator"))
+         {
+           // Here we set flags to treat particular bugs of the
+           // PostScript produced by certain applications
+           p = strstr(line->data, "%%Creator") + 9;
+           while (*p && (isspace(*p) || *p == ':'))
+             p++;
+           if (!strcmp(p, "OpenOffice.org"))
+           {
+             p += 14;
+             while (*p && isspace(*p))
+               p++;
+             if (sscanf(p, "1.1.%d", &ooo110) == 1)
+             {
+               _log("Document created with OpenOffice.org 1.1.x\n");
+               ooo110 = 1;
+             }
+           }
+           else if (!strcmp(p, "StarOffice 8"))
+           {
+             p += 12;
+             _log("Document created with StarOffice 8\n");
+             ooo110 = 1;
+           }
+         }
+         else if (nestinglevel == 0 &&
+                  startswith(line->data, "%%BeginProlog"))
+         {
+           // Note: Below is another place where a "Prolog" section
+           // start will be considered. There we assume start of the
+           // "Prolog" if the job is DSC-Conformimg, but an arbitrary
+           // comment starting with "%%Begin", but not a comment
+           // explicitly treated here, is found. This is done because
+           // many "dvips" (TeX/LaTeX) files miss the "%%BeginProlog"
+           // comment.
+           // Beginning of Prolog
+           _log("\n-----------\nFound: %%%%BeginProlog\n");
+           inprolog = 1;
+           if (inheader)
+             postscriptsection = PS_SECTION_PROLOG;
+           nondsclines = 0;
+           // Insert options for "Prolog"
+           if (!prologfound)
+           {
+             append_prolog_section(line, optset, 0);
+             prologfound = 1;
+           }
+         }
+         else if (nestinglevel == 0 && startswith(line->data, "%%EndProlog"))
+         {
+           // End of Prolog
+           _log("Found: %%%%EndProlog\n");
+           inprolog = 0;
+           insertoptions = linect +1;
+         }
+         else if (nestinglevel == 0 && startswith(line->data, "%%BeginSetup"))
+         {
+           // Beginning of Setup
+           _log("\n-----------\nFound: %%%%BeginSetup\n");
+           insetup = 1;
+           nondsclines = 0;
+           // We need to distinguish with the $inheader variable
+           // here whether we are in the header or on a page, as
+           // OpenOffice.org inserts a "%%BeginSetup...%%EndSetup"
+           // section after the first "%%Page:..." line and assumes
+           // this section to be valid for all pages.
+           if (inheader)
+           {
+             postscriptsection = PS_SECTION_SETUP;
+             // If there was no "Prolog" but there are
+             // options for the "Prolog", push a "Prolog"
+             // with these options onto the psfifo here
+             if (!prologfound)
+             {
+               dstrclear(tmp);
+               append_prolog_section(tmp, optset, 1);
+               dstrprepend(line, tmp->data);
+               prologfound = 1;
+             }
+             // Insert options for "DocumentSetup" or "AnySetup"
+             if (spooler != SPOOLER_CUPS && !setupfound)
+             {
+               // For non-CUPS spoolers or no spooler at all,
+               // we leave everythnig as it is
+               append_setup_section(line, optset, 0);
+               setupfound = 1;
+             }
+           }
+           else
+           {
+             // Found option settings must be stuffed into both
+             // the header and the currrent page now. They will
+             // be written into both the "header" and the
+             // "currentpage" optionsets and the PostScript code
+             // lines of this section will not only go into the
+             // output stream, but also added to the end of the
+             // @psheader, so that they get repeated (to preserve
+             // the embedded PostScript option settings) on a
+             // restart of the renderer due to command line
+             // option changes
+             optionsalsointoheader = 1;
+             _log("\"%%%%BeginSetup\" in page header\n");
+           }
+         }
+         else if (nestinglevel == 0 && startswith(line->data, "%%EndSetup"))
+         {
+           // End of Setup
+           _log("Found: %%%%EndSetup\n");
+           insetup = 0;
+           if (inheader)
+             insertoptions = linect + 1;
+           else
+           {
+             // The "%%BeginSetup...%%EndSetup" which
+             // OpenOffice.org has inserted after the first
+             // "%%Page:..." line ends here, so the following
+             // options go only onto the current page again
+             optionsalsointoheader = 0;
+           }
+         }
+         else if (nestinglevel == 0 && startswith(line->data, "%%Page:"))
+         {
+           if (!lastpassthru && !inheader)
+           {
+             // In the last line we were not in passthru mode,
+             // so the last page is not printed. Prepare to do
+             // it now.
+             printprevpage = 1;
+             passthru = 1;
+             _log("New page found but previous not printed, print it now.\n");
+           }
+           else
+           {
+             // the previous page is printed, so we can prepare
+             // the current one
+             _log("\n-----------\nNew page: %s", line->data);
+             printprevpage = 0;
+             currentpage++;
+             // We consider the beginning of the page already as
+             // page setup section, as some apps do not use
+             // "%%PageSetup" tags.
+             postscriptsection = PS_SECTION_PAGESETUP;
+
+             // TODO can this be removed?
+             // Save PostScript state before beginning the page
+             // $line .= "/foomatic-saved-state save def\n";
+
+             // Here begins a new page
+             if (inheader)
+             {
+               build_commandline(optset, NULL, 0);
+               // Here we add some stuff which still
+               // belongs into the header
+               dstrclear(tmp);
+
+               // If there was no "Setup" but there are
+               // options for the "Setup", push a "Setup"
+               // with these options onto the @psfifo here
+               if (!setupfound)
+               {
+                 append_setup_section(tmp, optset, 1);
+                 setupfound = 1;
+               }
+               // If there was no "Prolog" but there are
+               // options for the "Prolog", push a "Prolog"
+               // with these options onto the @psfifo here
+               if (!prologfound)
+               {
+                 append_prolog_section(tmp, optset, 1);
+                 prologfound = 1;
+               }
+               // Now we push this into the header
+               dstrcat(psheader, tmp->data);
+
+               // The first page starts, so header ends
+               inheader = 0;
+               nondsclines = 0;
+               // Option setting should go into the page
+               // specific option set now
+               optset = optionset("currentpage");
+             }
+             else
+             {
+               // Restore PostScript state after completing the
+               // previous page:
+               //
+               //     foomatic-saved-state restore
+               //     %%Page: ...
+               //     /foomatic-saved-state save def
+               //
+               // Print this directly, so that if we need to
+               // restart the renderer for this page due to
+               // a command line change this is done under the
+               // old instance of the renderer
+               // rint $rendererhandle
+               // "foomatic-saved-state restore\n";
+
+               // Save the option settings of the previous page
+               optionset_copy_values(optionset("currentpage"),
+                                     optionset("previouspage"));
+               optionset_delete_values(optionset("currentpage"));
+             }
+             // Initialize the option set
+             optionset_copy_values(optionset("header"),
+                                   optionset("currentpage"));
+
+             // Set the command line options which apply only
+             // to given pages
+             set_options_for_page(optionset("currentpage"), currentpage);
+             pagesetupfound = 0;
+             if (spooler == SPOOLER_CUPS)
+             {
+               // Remove the "notfirst" flag from all options
+               // forseen for the "PageSetup" section, because
+               // when these are numerical options for CUPS.
+               // they have to be set to the correct value
+               // for every page
+               for (o = optionlist; o; o = o->next)
+               {
+                 if (option_get_section(o ) == SECTION_PAGESETUP)
+                   o->notfirst = 0;
+               }
+             }
+             // Now the page header comes, so buffer the data,
+             // because we must perhaps shut down and restart
+             // the renderer
+             passthru = 0;
+             ignorepageheader = 0;
+             optionsalsointoheader = 0;
+           }
+         }
+         else if (nestinglevel == 0 && !ignorepageheader &&
+                  startswith(line->data, "%%BeginPageSetup"))
+         {
+           // Start of the page header, up to %%EndPageSetup
+           // nothing of the page will be drawn, page-specific
+           // option settngs (as letter-head paper for page 1)
+           // go here
+           _log("\nFound: %%%%BeginPageSetup\n");
+           passthru = 0;
+           inpageheader = 1;
+           postscriptsection = PS_SECTION_PAGESETUP;
+           optionsalsointoheader = (ooo110 && currentpage == 1) ? 1 : 0;
+           // Insert PostScript option settings
+           // (options for section "PageSetup")
+           if (isdscjob)
+           {
+             append_page_setup_section(line, optset, 0);
+             pagesetupfound = 1;
+           }
+         }
+         else if (nestinglevel == 0 && !ignorepageheader &&
+                  startswith(line->data, "%%BeginPageSetup"))
+         {
+           // End of the page header, the page is ready to be printed
+           _log("Found: %%%%EndPageSetup\n");
+           _log("End of page header\n");
+           // We cannot for sure say that the page header ends here
+           // OpenOffice.org puts (due to a bug) a "%%BeginSetup...
+           // %%EndSetup" section after the first "%%Page:...". It
+           // is possible that CUPS inserts a "%%BeginPageSetup...
+           // %%EndPageSetup" before this section, which means that
+           // the options in the "%%BeginSetup...%%EndSetup"
+           // section are after the "%%EndPageSetup", so we
+           // continue for searching options up to the buffer size
+           // limit $maxlinesforpageoptions.
+           passthru = 0;
+           inpageheader = 0;
+           optionsalsointoheader = 0;
+         }
+         else if (nestinglevel == 0 && !optionreplaced &&
+                  (!passthru || !isdscjob) &&
+                  ((linetype = line_type(line->data)) &&
+                   (linetype == LT_BEGIN_FEATURE ||
+                    linetype == LT_FOOMATIC_RIP_OPTION_SETTING)))
+         {
+           // parse
+           if (linetype == LT_BEGIN_FEATURE)
+           {
+             dstrcpy(tmp, line->data);
+             p = strtok(tmp->data, " \t"); // %%BeginFeature:
+             p = strtok(NULL, " \t="); // Option
+             if (*p == '*') p++;
+             strlcpy(optionname, p, 128);
+             p = strtok(NULL, " \t\r\n"); // value
+             fromcomposite = 0;
+             strlcpy(value, p, 128);
+           }
+           else
+           { // LT_FOOMATIC_RIP_OPTION_SETTING
+             dstrcpy(tmp, line->data);
+             p = strstr(tmp->data, "FoomaticRIPOptionSetting:");
+             p = strtok(p, " \t");  // FoomaticRIPOptionSetting
+             p = strtok(NULL, " \t="); // Option
+             strlcpy(optionname, p, 128);
+             p = strtok(NULL, " \t\r\n"); // value
+             if (*p == '@')
+             { // fromcomposite
+               p++;
+               fromcomposite = 1;
+             }
+             else
+               fromcomposite = 0;
+             strlcpy(value, p, 128);
+           }
+
+           // Mark that we are in a "Feature" section
+           if (linetype == LT_BEGIN_FEATURE)
+           {
+             infeature = 1;
+             dstrclear(linesafterlastbeginfeature);
+           }
+
+           // OK, we have an option.  If it's not a
+           // Postscript-style option (ie, it's command-line or
+           // JCL) then we should note that fact, since the
+           // attribute-to-filter option passing in CUPS is kind of
+           // funky, especially wrt boolean options.
+           _log("Found: %s", line->data);
+           if ((o = find_option(optionname)) &&
+               (o->type != TYPE_NONE))
+           {
+             _log("   Option: %s=%s%s\n", optionname,
+                  fromcomposite ? "From" : "", value);
+             if (spooler == SPOOLER_CUPS &&
+                 linetype == LT_BEGIN_FEATURE &&
+                 !option_get_value(o, optionset("notfirst")) &&
+                 strcmp((val = option_get_value(o, optset)) ? val : "",
+                        value) != 0 &&
+                 (inheader || option_get_section(o) == SECTION_PAGESETUP))
+             {
+               // We have the first occurence of an option
+               // setting and the spooler is CUPS, so this
+               // setting is inserted by "pstops" or
+               // "imagetops". The value from the command
+               // line was not inserted by "pstops" or
+               // "imagetops" so it seems to be not under
+               // the choices in the PPD. Possible
+               // reasons:
+               //
+               // - "pstops" and "imagetops" ignore settings
+               //   of numerical or string options which are
+               //   not one of the choices in the PPD file,
+               //   and inserts the default value instead.
+               //
+               // - On the command line an option was applied
+               //   only to selected pages:
+               //   "-o <page ranges>:<option>=<values>
+               //   This is not supported by CUPS, so not
+               //   taken care of by "pstops".
+               //
+               // We must fix this here by replacing the
+               // setting inserted by "pstops" or "imagetops"
+               // with the exact setting given on the command
+               // line.
+               //
+               // $arg->{$optionset} is already
+               // range-checked, so do not check again here
+
+               // Insert DSC comment
+               pdest = (inheader && isdscjob) ? psheader : psfifo;
+               if (option_is_ps_command(o))
+               {
+                 // PostScript option, insert the code
+                 option_get_command(tmp, o, optset, -1);
+                 if (!(val = option_get_value(o, optset)))
+                   val = "";
+
+                 // Boolean and enumerated choice options can only be set in
+                 // the PageSetup section
+                 if ((inheader && option_is_custom_value(o, val)) || !inheader)
+                 {
+                   if (o->type == TYPE_BOOL)
+                     dstrcatf(pdest, "%%%%BeginFeature: *%s %s\n", o->name,
+                              val && !strcmp(val, "1") ? "True" : "False");
+                   else
+                     dstrcatf(pdest, "%%%%BeginFeature: *%s %s\n", o->name,
+                              val);
+
+                   dstrcatf(pdest, "%s\n", tmp->data);
+
+                   // We have replaced this option on the FIFO
+                   optionreplaced = 1;
+                 }
+               }
+               else
+               {
+                 // Command line or JCL option
+                 val = option_get_value(o, optset);
+
+                 if (!inheader || option_is_custom_value(o, val))
+                 {
+                   dstrcatf(pdest, "%%%% FoomaticRIPOptionSetting: %s=%s\n",
+                            o->name, val ? val : "");
+                   optionreplaced = 1;
+                 }
+               }
+
+               if (optionreplaced)
+               {
+                 val = option_get_value(o, optset);
+                 _log(" --> Correcting numerical/string option to %s=%s (Command line argument)\n",
+                      o->name, val ? val : "");
+               }
+             }
+
+             // Mark that we have already found this option
+             o->notfirst = 1;
+             if (!optionreplaced)
+             {
+               if (o->style != 'G')
+               {
+                 // Controlled by '<Composite>' setting of
+                 // a member option of a composite option
+                 if (fromcomposite)
+                 {
+                   dstrcpyf(tmp, "From%s", value);
+                   strlcpy(value, tmp->data, 128);
+                 }
+
+                 // Non PostScript option
+                 //Check whether it is valid
+                 if (option_set_value(o, optset, value))
+                 {
+                   _log("Setting option\n");
+                   strlcpy(value, option_get_value(o, optset), 128);
+                   if (optionsalsointoheader)
+                     option_set_value(o, optionset("header"), value);
+                   if (o->type == TYPE_ENUM &&
+                       (!strcmp(o->name, "PageSize") ||
+                        !strcmp(o->name, "PageRegion")) &&
+                       startswith(value, "Custom") &&
+                       linetype == LT_FOOMATIC_RIP_OPTION_SETTING)
+                   {
+                     // Custom Page size
+                     width = height = 0.0;
+                     p = linesafterlastbeginfeature->data;
+                     while (*p && isspace(*p)) p++;
+                     width = strtod(p, &p);
+                     while (*p && isspace(*p)) p++;
+                     height = strtod(p, &p);
+                     if (width && height)
+                     {
+                       dstrcpyf(tmp, "%s.%fx%f", value, width, height);
+                       strlcpy(value, tmp->data, 128);
+                       option_set_value(o, optset, value);
+                       if (optionsalsointoheader)
+                         option_set_value(o, optionset("header"), value);
+                     }
+                   }
+                   // For a composite option insert the
+                   // code from the member options with
+                   // current setting "From<composite>"
+                   // The code from the member options
+                   // is chosen according to the setting
+                   // of the composite option.
+                   if (option_is_composite(o) &&
+                       linetype == LT_FOOMATIC_RIP_OPTION_SETTING)
+                   {
+                     build_commandline(optset, NULL, 0);
+                                           // TODO can this be removed?
+                                            // TODO merge section and ps_section
+                     if (postscriptsection == PS_SECTION_JCLSETUP)
+                       option_get_command(tmp, o, optset, SECTION_JCLSETUP);
+                     else if (postscriptsection == PS_SECTION_PROLOG)
+                       option_get_command(tmp, o, optset, SECTION_PROLOG);
+                     else if (postscriptsection == PS_SECTION_SETUP)
+                       option_get_command(tmp, o, optset,
+                                          SECTION_DOCUMENTSETUP);
+                     else if (postscriptsection == PS_SECTION_PAGESETUP)
+                       option_get_command(tmp, o, optset, SECTION_PAGESETUP);
+                     dstrcat(line, tmp->data);
+                   }
+                 }
+                 else
+                   _log(" --> Invalid option setting found in job\n");
+               }
+               else if (fromcomposite)
+               {
+                 // PostScript option, but we have to look up
+                 // the PostScript code to be inserted from
+                 // the setting of a composite option, as
+                 // this option is set to "Controlled by
+                 // '<Composite>'".
+                 // Set the option
+                 dstrcpyf(tmp, "From%s", value);
+                 strlcpy(value, tmp->data, 128);
+                 if (option_set_value(o, optset, value))
+                 {
+                   _log(" --> Looking up setting in composite option %s\n",
+                        value);
+                   if (optionsalsointoheader)
+                     option_set_value(o, optionset("header"), value);
+                   // update composite options
+                   build_commandline(optset, NULL, 0);
+                   // Substitute PostScript comment by the real code
+                   // TODO what exactly is the next line doing?
+                   // dstrcpy(line, o->compositesubst->data);
+                 }
+                 else
+                   _log(" --> Invalid option setting found in job\n");
+               }
+               else
+                 // it is a PostScript style option with
+                 // the code readily inserted, no option
+                 // for the renderer command line/JCL to set,
+                 // no lookup of a composite option needed,
+                 // so nothing to do here...
+                 _log(" --> Option will be set by PostScript interpreter\n");
+             }
+           }
+           else
+             // This option is unknown to us, WTF?
+             _log("Unknown option %s=%s found in the job\n",
+                  optionname, value);
+         }
+         else if (nestinglevel == 0 &&
+                  startswith(line->data, "%%EndFeature"))
+         {
+           // End of feature
+           infeature = 0;
+           // If the option setting was replaced, it ends here,
+           // too, and the next option is not necessarily also replaced
+           optionreplaced = 0;
+           dstrclear(linesafterlastbeginfeature);
+         }
+         else if (nestinglevel == 0 && isdscjob && !prologfound &&
+                  startswith(line->data, "%%Begin"))
+         {
+           // In some PostScript files (especially when generated
+           // by "dvips" of TeX/LaTeX) the "%%BeginProlog" is
+           // missing, so assume that it was before the current
+           // line (the first line starting with "%%Begin".
+           _log("Job claims to be DSC-conforming, but \"%%%%BeginProlog\" "
+                "was missing before first line with another"
+                "\"%%%%BeginProlog\" comment (is this a TeX/LaTeX/dvips-generated"
+                " PostScript file?). Assuming start of \"Prolog\" here.\n");
+           // Beginning of Prolog
+           inprolog = 1;
+           nondsclines = 0;
+           // Insert options for "Prolog" before the current line
+           dstrcpyf(tmp, "%%%%BeginProlog\n");
+           append_prolog_section(tmp, optset, 0);
+           dstrprepend(line, tmp->data);
+           prologfound = 1;
+         }
+         else if (nestinglevel == 0 &&
+                  (startswith(line->data, "%RBINumCopies:") ||
+                   startswith(line->data, "%%RBINumCopies:")))
+         {
+           p = strchr(line->data, ':') + 1;
+           get_current_job()->rbinumcopies = atoi(p);
+           _log("Found %RBINumCopies: %d\n", get_current_job()->rbinumcopies);
+         }
+         else if (startswith(skip_whitespace(line->data), "%") ||
+                  startswith(skip_whitespace(line->data), "$"))
+           // This is an unknown PostScript comment or a blank
+           // line, no active code
+           ignoreline = 1;
+       }
+       else
+       {
+         // This line is active PostScript code
+         if (infeature)
+           // Collect coe in a "%%BeginFeature: ... %%EndFeature"
+           // section, to get the values for a custom option
+           // setting
+           dstrcat(linesafterlastbeginfeature, line->data);
+         if (inheader)
+         {
+           if (!inprolog && !insetup)
+           {
+             // Outside the "Prolog" and "Setup" section
+             // a correct DSC-conforming document has no
+             // active PostScript code, so consider the
+             // file as non-DSC-conforming when there are
+             // too many of such lines.
+             nondsclines++;
+             if (nondsclines > MAX_NON_DSC_LINES_IN_HEADER)
+             {
+               // Consider document as not DSC-conforming
+               _log("This job seems not to be DSC-conforming, "
+                    "DSC-comment for next section not found, "
+                    "stopping to parse the rest, passing it "
+                    "directly to the renderer.\n");
+               // Stop scanning for further option settings
+               maxlines = 1;
+               isdscjob = 0;
+               // Insert defaults and command line settings in
+               // the beginning of the job or after the last valid
+               // section
+               dstrclear(tmp);
+               if (!prologfound)
+                 append_prolog_section(tmp, optset, 1);
+               if (!setupfound)
+                 append_setup_section(tmp, optset, 1);
+               if (!pagesetupfound)
+                 append_page_setup_section(tmp, optset, 1);
+               dstrinsert(psheader, line_start(psheader->data,
+                                               insertoptions), tmp->data);
+               prologfound = 1;
+               setupfound = 1;
+               pagesetupfound = 1;
+             }
+           }
+         }
+         else if (!inpageheader)
+         {
+           // PostScript code inside a page, but not between
+           // "%%BeginPageSetup" and "%%EndPageSetup", so
+           // we are perhaps already drawing onto a page now
+           if (startswith(onelinebefore->data, "%%Page"))
+             _log("No page header or page header not DSC-conforming\n");
+           // Stop buffering lines to search for options
+           // placed not DSC-conforming
+           if (line_count(psfifo->data) >= MAX_LINES_FOR_PAGE_OPTIONS)
+           {
+             _log("Stopping search for page header options\n");
+             passthru = 1;
+             // If there comes a page header now, ignore it
+             ignorepageheader = 1;
+             optionsalsointoheader = 0;
+           }
+           // Insert PostScript option settings (options for the
+           // section "PageSetup"
+           if (isdscjob && !pagesetupfound)
+           {
+             append_page_setup_section(psfifo, optset, 1);
+             pagesetupfound = 1;
+           }
+         }
+       }
       }
 
-      /* Clean up and make Ghostscript stop by that */
-      fclose(in);
-      fclose(out);
-      wait_for_process(pid);
+      // Debug Info
+      if (lastpassthru != passthru)
+      {
+       if (passthru)
+         _log("Found: %s --> Output goes directly to the renderer now.\n\n",
+              line->data);
+       else
+         _log("Found: %s --> Output goes to the FIFO buffer now.\n\n",
+              line->data);
+      }
 
-      if (pagefound) {
-       _log("File not empty, contains at least one page.\n");
+      // We are in an option which was replaced, do not output the current line
+      if (optionreplaced)
+       dstrclear(line);
+
+      // If we are in a "%%BeginSetup...%%EndSetup" section after
+      // the first "%%Page:..." and the current line belongs to
+      // an option setting, we have to copy the line also to the
+      // @psheader.
+      if (optionsalsointoheader &&
+         (infeature || startswith(line->data, "%%EndFeature")))
+       dstrcat(psheader, line->data);
+
+      // Store or send the current line
+      if (inheader && isdscjob)
+      {
+       // We are still in the PostScript header, collect all lines
+       // in @psheader
+       dstrcat(psheader, line->data);
+      }
+      else
+      {
+       if (passthru && isdscjob)
+       {
+         if (!lastpassthru)
+         {
+           //
+           // We enter passthru mode with this line, so the
+           // command line can have changed, check it and close
+           // the renderer if needed
+           //
+           if (rendererpid &&
+               !optionset_equal(optionset("currentpage"),
+                                optionset("previouspage"), 0))
+           {
+             _log("Command line/JCL options changed, restarting renderer\n");
+             retval = close_renderer_handle(rendererhandle, rendererpid);
+             if (retval != EXIT_PRINTED)
+               rip_die(retval, "Error closing renderer\n");
+             rendererpid = 0;
+           }
+         }
+
+         // Flush psfifo and send line directly to the renderer
+         if (!rendererpid)
+         {
+           // No renderer running, start it
+           dstrcpy(tmp, psheader->data);
+           dstrcat(tmp, psfifo->data);
+           get_renderer_handle(tmp, &rendererhandle, &rendererpid);
+           // psfifo is sent out, flush it
+           dstrclear(psfifo);
+         }
+
+         if (!isempty(psfifo->data))
+         {
+           // Send psfifo to renderer
+           fwrite_or_die(psfifo->data, psfifo->len, 1, rendererhandle);
+           // flush psfifo
+           dstrclear(psfifo);
+         }
+
+         // Send line to renderer
+         if (!printprevpage)
+         {
+           fwrite_or_die(line->data, line->len, 1, rendererhandle);
+
+           while (stream_next_line(line, stream) > 0)
+           {
+             if (startswith(line->data, "%%"))
+             {
+               _log("Found: %s", line->data);
+               _log(" --> Continue DSC parsing now.\n\n");
+               saved = 1;
+               break;
+             }
+             else
+             {
+               fwrite_or_die(line->data, line->len, 1, rendererhandle);
+               linect++;
+             }
+           }
+         }
+       }
+       else
+       {
+         // Push the line onto the stack to split up later
+         dstrcat(psfifo, line->data);
+       }
+      }
 
-       /* Redefine stream for what we have read now */
-       if (data_read->len < len)
-         dstrncat(data_read, buf + data_read->len, len - data_read->len);
+      if (!printprevpage)
+       linect++;
+    }
+    else
+    {
+      // EOF!
+      more_stuff = 0;
+
+      // No PostScript header in the whole file? Then it's not
+      // PostScript, convert it.
+      // We open the file converter here when the file has less
+      // lines than the amount which we search for the PostScript
+      // header ($maxlinestopsstart).
+      if (linect <= nonpslines)
+      {
+       // This is not a PostScript job, abort it
+       _log("Job does not start with \"%%!\", is it Postscript?\n");
+       rip_die(EXIT_JOBERR, "Unknown data format.\n");
+      }
+    }
 
-       stream.pos = 0;
-       stream.file = file;
-       stream.alreadyread = data_read->data;
-       stream.len = data_read->len;
+    lastpassthru = passthru;
 
-       /* Print the file */
-       _print_ps(&stream);
-      } else
-       _log("No pages left, outputting empty file.\n");
+    if (!ignoreline && !printprevpage)
+    {
+      dstrcpy(twolinesbefore, onelinebefore->data);
+      dstrcpy(onelinebefore, line->data);
+    }
 
-      free_dstr(data_read);
+  }
+  while ((maxlines == 0 || linect < maxlines) && more_stuff != 0);
+
+  // Some buffer still containing data? Send it out to the renderer
+  if (more_stuff || inheader || !isempty(psfifo->data))
+  {
+    // Flush psfifo and send the remaining data to the renderer, this
+    // only happens with non-DSC-conforming jobs or non-Foomatic PPDs
+    if (more_stuff)
+      _log("Stopped parsing the PostScript data, "
+          "sending rest directly to the renderer.\n");
+    else
+      _log("Flushing FIFO.\n");
+
+    if (inheader)
+    {
+      build_commandline(optset, NULL, 0);
+      // No page initialized yet? Copy the "header" option set into the
+      // "currentpage" option set, so that the renderer will find the
+      // options settings.
+      optionset_copy_values(optionset("header"), optionset("currentpage"));
+      optset = optionset("currentpage");
+
+      // If not done yet, insert defaults and command line settings
+      // in the beginning of the job or after the last valid section
+      dstrclear(tmp);
+      if (!prologfound)
+       append_prolog_section(tmp, optset, 1);
+      if (!setupfound)
+       append_setup_section(tmp, optset, 1);
+      if (!pagesetupfound)
+       append_page_setup_section(tmp, optset, 1);
+      dstrinsert(psheader, line_start(psheader->data, insertoptions),
+                tmp->data);
+
+      prologfound = 1;
+      setupfound = 1;
+      pagesetupfound = 1;
     }
 
-    return 1;
-}
+    if (rendererpid > 0 &&
+       !optionset_equal(optionset("currentpage"),
+                        optionset("previouspage"), 0))
+    {
+      _log("Command line/JCL options changed, restarting renderer\n");
+      retval = close_renderer_handle(rendererhandle, rendererpid);
+      if (retval != EXIT_PRINTED)
+       rip_die(retval, "Error closing renderer\n");
+      rendererpid = 0;
+    }
 
-void _print_ps(stream_t *stream)
-{
-    char *p;
-
-    int maxlines = 1000;    /* Maximum number of lines to be read  when the
-                               documenent is not  DSC-conforming.
-                               "$maxlines = 0"  means that all will be read and
-                               examined. If it is  discovered that the input
-                               file  is DSC-conforming, this will  be set to 0. */
-
-    int maxlinestopsstart = 200;    /* That many lines are allowed until the
-                                      "%!" indicating PS comes. These
-                                      additional lines in the
-                                      beginning are usually JCL
-                                      commands. The lines will be
-                                      ignored by our parsing but
-                                      passed through. */
-
-    int printprevpage = 0;  /* We set this when encountering "%%Page:" and the
-                               previous page is not printed yet. Then it will
-                               be printed and the new page will be prepared in
-                               the next run of the loop (we don't read a new
-                               line and don't increase the $linect then). */
-
-    int linect = 0;         /* how many lines have we examined */
-    int nonpslines = 0;     /* lines before "%!" found yet. */
-    int more_stuff = 1;     /* there is more stuff in stdin */
-    int saved = 0;          /* DSC line not precessed yet */
-    int isdscjob = 0;       /* is the job dsc conforming */
-    int inheader = 1;       /* Are we still in the header, before first
-                               "%%Page:" comment= */
-
-    int optionsalsointoheader = 0; /* 1: We are in a "%%BeginSetup...
-                                    %%EndSetup" section after the first
-                                    "%%Page:..." line (OpenOffice.org
-                                    does this and intends the options here
-                                    apply to the whole document and not
-                                    only to the current page). We have to
-                                    add all lines also to the end of the
-                                    @psheader now and we have to set
-                                    non-PostScript options also in the
-                                    "header" optionset. 0: otherwise. */
-
-    int insertoptions = 1;  /* If we find out that a file with a DSC magic
-                               string ("%!PS-Adobe-") is not really DSC-
-                               conforming, we insert the options directly
-                               after the line with the magic string. We use
-                               this variable to store the number of the line
-                               with the magic string */
-
-    int prologfound = 0;    /* Did we find the
-                               "%%BeginProlog...%%EndProlog" section? */
-    int setupfound = 0;     /* Did we find the
-                               %%BeginSetup...%%EndSetup" section? */
-    int pagesetupfound = 0; /* special page setup handling needed */
-
-    int inprolog = 0;       /* We are between "%%BeginProlog" and "%%EndProlog" */
-    int insetup = 0;        /* We are between "%%BeginSetup" and "%%EndSetup" */
-    int infeature = 0;      /* We are between "%%BeginFeature" and "%%EndFeature" */
-
-    int optionreplaced = 0; /* Will be set to 1 when we are in an
-                               option ("%%BeginFeature...
-                               %%EndFeature") which we have replaced. */
-
-    int postscriptsection = PS_SECTION_JCLSETUP; /* In which section of the PostScript file
-                                                   are we currently ? */
-
-    int nondsclines = 0;    /* Number of subsequent lines found which are at a
-                               non-DSC-conforming place, between the sections
-                               of the header.*/
-
-    int nestinglevel = 0;   /* Are we in the main document (0) or in an
-                               embedded document bracketed by "%%BeginDocument"
-                               and "%%EndDocument" (>0) We do not parse the
-                               PostScript in an embedded document. */
-
-    int inpageheader = 0;   /* Are we in the header of a page,
-                               between "%%BeginPageSetup" and
-                               "%%EndPageSetup" (1) or not (0). */
-
-    int passthru = 0;       /* 0: write data into psfifo,
-                               1: pass data directly to the renderer */
-
-    int lastpassthru = 0;   /* State of 'passthru' in previous line
-                               (to allow debug output when $passthru
-                               switches. */
-
-    int ignorepageheader = 0; /* Will be set to 1 as soon as active
-                                 code (not between "%%BeginPageSetup"
-                                 and "%%EndPageSetup") appears after a
-                                 "%%Page:" comment. In this case
-                                 "%%BeginPageSetup" and
-                                 "%%EndPageSetup" is not allowed any
-                                 more on this page and will be ignored.
-                                 Will be set to 0 when a new "%%Page:"
-                                 comment appears. */
-
-    int optset = optionset("header"); /* Where do the option settings which
-                                         we have found go? */
-
-    /* current line */
-    dstr_t *line = create_dstr();
-
-    dstr_t *onelinebefore = create_dstr();
-    dstr_t *twolinesbefore = create_dstr();
-
-    /* The header of the PostScript file, to be send after each start of the renderer */
-    dstr_t *psheader = create_dstr();
-
-    /* The input FIFO, data which we have pulled from stdin for examination,
-       but not send to the renderer yet */
-    dstr_t *psfifo = create_dstr();
-
-    int ignoreline;
-
-    int ooo110 = 0;         /* Flag to work around an application bug */
-
-    int currentpage = 0;   /* The page which we are currently printing */
-
-    option_t *o;
-    const char *val;
-
-    int linetype;
-
-    dstr_t *linesafterlastbeginfeature = create_dstr(); /* All codelines after the last "%%BeginFeature" */
-
-    char optionname [128];
-    char value [128];
-    int fromcomposite = 0;
-
-    dstr_t *pdest;
-
-    double width, height;
-
-    pid_t rendererpid = 0;
-    FILE *rendererhandle = NULL;
-
-    int retval;
-
-    dstr_t *tmp = create_dstr();
-    jobhasjcl = 0;
-
-    /* We do not parse the PostScript to find Foomatic options, we check
-        only whether we have PostScript. */
-    if (dontparse)
-        maxlines = 1;
-
-    _log("Reading PostScript input ...\n");
-
-    do {
-        ignoreline = 0;
-
-        if (printprevpage || saved || stream_next_line(line, stream)) {
-            saved = 0;
-            if (linect == nonpslines) {
-                /* In the beginning should be the postscript leader,
-                   sometimes after some JCL commands */
-                if ( !(line->data[0] == '%' && line->data[1] == '!') &&
-                     !(line->data[1] == '%' && line->data[2] == '!')) /* There can be a Windows control character before "%!" */
-                {
-                    nonpslines++;
-                    if (maxlines == nonpslines)
-                        maxlines ++;
-                    jobhasjcl = 1;
-
-                    if (nonpslines > maxlinestopsstart) {
-                        /* This is not a PostScript job, abort it */
-                        _log("Job does not start with \"%%!\", is it Postscript?\n");
-                       rip_die(EXIT_JOBERR, "Unknown data format.\n");
-                    }
-                }
-                else {
-                    /* Do we have a DSC-conforming document? */
-                    if ((line->data[0] == '%' && startswith(line->data, "%!PS-Adobe-")) ||
-                        (line->data[1] == '%' && startswith(line->data, "%!PS-Adobe-")))
-                    {
-                        /* Do not stop parsing the document */
-                        if (!dontparse) {
-                            maxlines = 0;
-                            isdscjob = 1;
-                            insertoptions = linect + 1;
-                            /* We have written into psfifo before, now we continue in
-                               psheader and move over the data which is already in psfifo */
-                            dstrcat(psheader, psfifo->data);
-                            dstrclear(psfifo);
-                        }
-                        _log("--> This document is DSC-conforming!\n");
-                    }
-                    else {
-                        /* Job is not DSC-conforming, stick in all PostScript
-                           option settings in the beginning */
-                        append_prolog_section(line, optset, 1);
-                        append_setup_section(line, optset, 1);
-                        append_page_setup_section(line, optset, 1);
-                        prologfound = 1;
-                        setupfound = 1;
-                        pagesetupfound = 1;
-                    }
-                }
-            }
-            else {
-                if (startswith(line->data, "%")) {
-                    if (startswith(line->data, "%%BeginDocument")) {
-                        /* Beginning of an embedded document
-                        Note that Adobe Acrobat has a bug and so uses
-                        "%%BeginDocument " instead of "%%BeginDocument:" */
-                        nestinglevel++;
-                        _log("Embedded document, nesting level now: %d\n", nestinglevel);
-                    }
-                    else if (nestinglevel > 0 && startswith(line->data, "%%EndDocument")) {
-                        /* End of an embedded document */
-                        nestinglevel--;
-                        _log("End of embedded document, nesting level now: %d\n", nestinglevel);
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%Creator")) {
-                        /* Here we set flags to treat particular bugs of the
-                        PostScript produced by certain applications */
-                        p = strstr(line->data, "%%Creator") + 9;
-                        while (*p && (isspace(*p) || *p == ':')) p++;
-                        if (!strcmp(p, "OpenOffice.org")) {
-                            p += 14;
-                            while (*p && isspace(*p)) p++;
-                            if (sscanf(p, "1.1.%d", &ooo110) == 1) {
-                                _log("Document created with OpenOffice.org 1.1.x\n");
-                                ooo110 = 1;
-                            }
-                        } else if (!strcmp(p, "StarOffice 8")) {
-                            p += 12;
-                           _log("Document created with StarOffice 8\n");
-                           ooo110 = 1;
-                        }
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%BeginProlog")) {
-                        /* Note: Below is another place where a "Prolog" section
-                        start will be considered. There we assume start of the
-                        "Prolog" if the job is DSC-Conformimg, but an arbitrary
-                        comment starting with "%%Begin", but not a comment
-                        explicitly treated here, is found. This is done because
-                        many "dvips" (TeX/LaTeX) files miss the "%%BeginProlog"
-                        comment.
-                        Beginning of Prolog */
-                        _log("\n-----------\nFound: %%%%BeginProlog\n");
-                        inprolog = 1;
-                        if (inheader)
-                            postscriptsection = PS_SECTION_PROLOG;
-                        nondsclines = 0;
-                        /* Insert options for "Prolog" */
-                        if (!prologfound) {
-                            append_prolog_section(line, optset, 0);
-                            prologfound = 1;
-                        }
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%EndProlog")) {
-                        /* End of Prolog */
-                        _log("Found: %%%%EndProlog\n");
-                        inprolog = 0;
-                        insertoptions = linect +1;
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%BeginSetup")) {
-                        /* Beginning of Setup */
-                        _log("\n-----------\nFound: %%%%BeginSetup\n");
-                        insetup = 1;
-                        nondsclines = 0;
-                        /* We need to distinguish with the $inheader variable
-                        here whether we are in the header or on a page, as
-                        OpenOffice.org inserts a "%%BeginSetup...%%EndSetup"
-                        section after the first "%%Page:..." line and assumes
-                        this section to be valid for all pages. */
-                        if (inheader) {
-                            postscriptsection = PS_SECTION_SETUP;
-                            /* If there was no "Prolog" but there are
-                            options for the "Prolog", push a "Prolog"
-                            with these options onto the psfifo here */
-                            if (!prologfound) {
-                                dstrclear(tmp);
-                                append_prolog_section(tmp, optset, 1);
-                                dstrprepend(line, tmp->data);
-                                prologfound = 1;
-                            }
-                            /* Insert options for "DocumentSetup" or "AnySetup" */
-                            if (spooler != SPOOLER_CUPS && !setupfound) {
-                                /* For non-CUPS spoolers or no spooler at all,
-                                we leave everythnig as it is */
-                                append_setup_section(line, optset, 0);
-                                setupfound = 1;
-                            }
-                        }
-                        else {
-                            /* Found option settings must be stuffed into both
-                            the header and the currrent page now. They will
-                            be written into both the "header" and the
-                            "currentpage" optionsets and the PostScript code
-                            lines of this section will not only go into the
-                            output stream, but also added to the end of the
-                            @psheader, so that they get repeated (to preserve
-                            the embedded PostScript option settings) on a
-                            restart of the renderer due to command line
-                            option changes */
-                            optionsalsointoheader = 1;
-                            _log("\"%%%%BeginSetup\" in page header\n");
-                        }
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%EndSetup")) {
-                        /* End of Setup */
-                        _log("Found: %%%%EndSetup\n");
-                        insetup = 0;
-                        if (inheader)
-                            insertoptions = linect +1;
-                        else {
-                            /* The "%%BeginSetup...%%EndSetup" which
-                            OpenOffice.org has inserted after the first
-                            "%%Page:..." line ends here, so the following
-                            options go only onto the current page again */
-                            optionsalsointoheader = 0;
-                        }
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%Page:")) {
-                        if (!lastpassthru && !inheader) {
-                            /* In the last line we were not in passthru mode,
-                            so the last page is not printed. Prepare to do
-                            it now. */
-                            printprevpage = 1;
-                            passthru = 1;
-                            _log("New page found but previous not printed, print it now.\n");
-                        }
-                        else {
-                            /* the previous page is printed, so we can prepare
-                            the current one */
-                            _log("\n-----------\nNew page: %s", line->data);
-                            printprevpage = 0;
-                            currentpage++;
-                            /* We consider the beginning of the page already as
-                            page setup section, as some apps do not use
-                            "%%PageSetup" tags. */
-                            postscriptsection = PS_SECTION_PAGESETUP;
-
-                            /* TODO can this be removed?
-                            Save PostScript state before beginning the page
-                            $line .= "/foomatic-saved-state save def\n"; */
-
-                            /* Here begins a new page */
-                            if (inheader) {
-                                build_commandline(optset, NULL, 0);
-                                /* Here we add some stuff which still
-                                belongs into the header */
-                                dstrclear(tmp);
-
-                                /* If there was no "Setup" but there are
-                                options for the "Setup", push a "Setup"
-                                with these options onto the @psfifo here */
-                                if (!setupfound) {
-                                    append_setup_section(tmp, optset, 1);
-                                    setupfound = 1;
-                                }
-                                /* If there was no "Prolog" but there are
-                                options for the "Prolog", push a "Prolog"
-                                with these options onto the @psfifo here */
-                                if (!prologfound) {
-                                    append_prolog_section(tmp, optset, 1);
-                                    prologfound = 1;
-                                }
-                                /* Now we push this into the header */
-                                dstrcat(psheader, tmp->data);
-
-                                /* The first page starts, so header ends */
-                                inheader = 0;
-                                nondsclines = 0;
-                                /* Option setting should go into the page
-                                specific option set now */
-                                optset = optionset("currentpage");
-                            }
-                            else {
-                                /*  Restore PostScript state after completing the
-                                    previous page:
-
-                                        foomatic-saved-state restore
-                                        %%Page: ...
-                                        /foomatic-saved-state save def
-
-                                    Print this directly, so that if we need to
-                                    restart the renderer for this page due to
-                                    a command line change this is done under the
-                                    old instance of the renderer
-                                    rint $rendererhandle
-                                    "foomatic-saved-state restore\n"; */
-
-                                /* Save the option settings of the previous page */
-                                optionset_copy_values(optionset("currentpage"), optionset("previouspage"));
-                                optionset_delete_values(optionset("currentpage"));
-                            }
-                            /* Initialize the option set */
-                            optionset_copy_values(optionset("header"), optionset("currentpage"));
-
-                            /* Set the command line options which apply only
-                                to given pages */
-                            set_options_for_page(optionset("currentpage"), currentpage);
-                            pagesetupfound = 0;
-                            if (spooler == SPOOLER_CUPS) {
-                                /* Remove the "notfirst" flag from all options
-                                    forseen for the "PageSetup" section, because
-                                    when these are numerical options for CUPS.
-                                    they have to be set to the correct value
-                                    for every page */
-                                for (o = optionlist; o; o = o->next) {
-                                    if (option_get_section(o ) == SECTION_PAGESETUP)
-                                        o->notfirst = 0;
-                                }
-                            }
-                            /* Now the page header comes, so buffer the data,
-                                because we must perhaps shut down and restart
-                                the renderer */
-                            passthru = 0;
-                            ignorepageheader = 0;
-                            optionsalsointoheader = 0;
-                        }
-                    }
-                    else if (nestinglevel == 0 && !ignorepageheader &&
-                            startswith(line->data, "%%BeginPageSetup")) {
-                        /* Start of the page header, up to %%EndPageSetup
-                        nothing of the page will be drawn, page-specific
-                        option settngs (as letter-head paper for page 1)
-                        go here*/
-                        _log("\nFound: %%%%BeginPageSetup\n");
-                        passthru = 0;
-                        inpageheader = 1;
-                        postscriptsection = PS_SECTION_PAGESETUP;
-                        optionsalsointoheader = (ooo110 && currentpage == 1) ? 1 : 0;
-                        /* Insert PostScript option settings
-                           (options for section "PageSetup") */
-                        if (isdscjob) {
-                            append_page_setup_section(line, optset, 0);
-                            pagesetupfound = 1;
-                        }
-                    }
-                    else if (nestinglevel == 0 && !ignorepageheader &&
-                            startswith(line->data, "%%BeginPageSetup")) {
-                        /* End of the page header, the page is ready to be printed */
-                        _log("Found: %%%%EndPageSetup\n");
-                        _log("End of page header\n");
-                        /* We cannot for sure say that the page header ends here
-                        OpenOffice.org puts (due to a bug) a "%%BeginSetup...
-                        %%EndSetup" section after the first "%%Page:...". It
-                        is possible that CUPS inserts a "%%BeginPageSetup...
-                        %%EndPageSetup" before this section, which means that
-                        the options in the "%%BeginSetup...%%EndSetup"
-                        section are after the "%%EndPageSetup", so we
-                        continue for searching options up to the buffer size
-                        limit $maxlinesforpageoptions. */
-                        passthru = 0;
-                        inpageheader = 0;
-                        optionsalsointoheader = 0;
-                    }
-                    else if (nestinglevel == 0 && !optionreplaced && (!passthru || !isdscjob) &&
-                            ((linetype = line_type(line->data)) &&
-                            (linetype == LT_BEGIN_FEATURE || linetype == LT_FOOMATIC_RIP_OPTION_SETTING))) {
-
-                        /* parse */
-                        if (linetype == LT_BEGIN_FEATURE) {
-                            dstrcpy(tmp, line->data);
-                            p = strtok(tmp->data, " \t"); /* %%BeginFeature: */
-                            p = strtok(NULL, " \t="); /* Option */
-                            if (*p == '*') p++;
-                            strlcpy(optionname, p, 128);
-                            p = strtok(NULL, " \t\r\n"); /* value */
-                            fromcomposite = 0;
-                            strlcpy(value, p, 128);
-                        }
-                        else { /* LT_FOOMATIC_RIP_OPTION_SETTING */
-                            dstrcpy(tmp, line->data);
-                            p = strstr(tmp->data, "FoomaticRIPOptionSetting:");
-                            p = strtok(p, " \t");  /* FoomaticRIPOptionSetting */
-                            p = strtok(NULL, " \t="); /* Option */
-                            strlcpy(optionname, p, 128);
-                            p = strtok(NULL, " \t\r\n"); /* value */
-                            if (*p == '@') { /* fromcomposite */
-                                p++;
-                                fromcomposite = 1;
-                            }
-                            else
-                                fromcomposite = 0;
-                            strlcpy(value, p, 128);
-                        }
-
-                        /* Mark that we are in a "Feature" section */
-                        if (linetype == LT_BEGIN_FEATURE) {
-                            infeature = 1;
-                            dstrclear(linesafterlastbeginfeature);
-                        }
-
-                        /* OK, we have an option.  If it's not a
-                        Postscript-style option (ie, it's command-line or
-                        JCL) then we should note that fact, since the
-                        attribute-to-filter option passing in CUPS is kind of
-                        funky, especially wrt boolean options. */
-                        _log("Found: %s", line->data);
-                        if ((o = find_option(optionname)) &&
-                           (o->type != TYPE_NONE)) {
-                            _log("   Option: %s=%s%s\n", optionname, fromcomposite ? "From" : "", value);
-                            if (spooler == SPOOLER_CUPS &&
-                                linetype == LT_BEGIN_FEATURE &&
-                                !option_get_value(o, optionset("notfirst")) &&
-                               strcmp((val = option_get_value(o, optset)) ? val : "", value) != 0 &&
-                                (inheader || option_get_section(o) == SECTION_PAGESETUP)) {
-
-                                /* We have the first occurence of an option
-                                setting and the spooler is CUPS, so this
-                                setting is inserted by "pstops" or
-                                "imagetops". The value from the command
-                                line was not inserted by "pstops" or
-                                "imagetops" so it seems to be not under
-                                the choices in the PPD. Possible
-                                reasons:
-
-                                - "pstops" and "imagetops" ignore settings
-                                of numerical or string options which are
-                                not one of the choices in the PPD file,
-                                and inserts the default value instead.
-
-                                - On the command line an option was applied
-                                only to selected pages:
-                                "-o <page ranges>:<option>=<values>
-                                This is not supported by CUPS, so not
-                                taken care of by "pstops".
-
-                                We must fix this here by replacing the
-                                setting inserted by "pstops" or "imagetops"
-                                with the exact setting given on the command
-                                line. */
-
-                                /* $arg->{$optionset} is already
-                                range-checked, so do not check again here
-                                Insert DSC comment */
-                                pdest = (inheader && isdscjob) ? psheader : psfifo;
-                                if (option_is_ps_command(o)) {
-                                    /* PostScript option, insert the code */
-
-                                    option_get_command(tmp, o, optset, -1);
-                                    if (!(val = option_get_value(o, optset)))
-                                        val = "";
-
-                                    /* Boolean and enumerated choice options can only be set in the
-                                     * PageSetup section */
-                                    if ((inheader && option_is_custom_value(o, val)) || !inheader)
-                                    {
-                                        if (o->type == TYPE_BOOL)
-                                            dstrcatf(pdest, "%%%%BeginFeature: *%s %s\n", o->name,
-                                                     val && !strcmp(val, "1") ? "True" : "False");
-                                        else
-                                            dstrcatf(pdest, "%%%%BeginFeature: *%s %s\n", o->name, val);
-
-                                        dstrcatf(pdest, "%s\n", tmp->data);
-
-                                        /* We have replaced this option on the FIFO */
-                                        optionreplaced = 1;
-                                    }
-                                }
-                                else { /* Command line or JCL option */
-                                    val = option_get_value(o, optset);
-
-                                    if (!inheader || option_is_custom_value(o, val)) {
-                                        dstrcatf(pdest, "%%%% FoomaticRIPOptionSetting: %s=%s\n",
-                                                 o->name, val ? val : "");
-                                        optionreplaced = 1;
-                                    }
-                                }
-
-                                if (optionreplaced) {
-                                    val = option_get_value(o, optset);
-                                    _log(" --> Correcting numerical/string option to %s=%s (Command line argument)\n",
-                                            o->name, val ? val : "");
-                                }
-                            }
-
-                            /* Mark that we have already found this option */
-                            o->notfirst = 1;
-                            if (!optionreplaced) {
-                                if (o->style != 'G') {
-                                    /* Controlled by '<Composite>' setting of
-                                    a member option of a composite option */
-                                    if (fromcomposite) {
-                                        dstrcpyf(tmp, "From%s", value);
-                                        strlcpy(value, tmp->data, 128);
-                                    }
-
-                                    /* Non PostScript option
-                                    Check whether it is valid */
-                                    if (option_set_value(o, optset, value)) {
-                                        _log("Setting option\n");
-                                        strlcpy(value, option_get_value(o, optset), 128);
-                                        if (optionsalsointoheader)
-                                            option_set_value(o, optionset("header"), value);
-                                        if (o->type == TYPE_ENUM &&
-                                                (!strcmp(o->name, "PageSize") || !strcmp(o->name, "PageRegion")) &&
-                                                startswith(value, "Custom") &&
-                                                linetype == LT_FOOMATIC_RIP_OPTION_SETTING) {
-                                            /* Custom Page size */
-                                            width = height = 0.0;
-                                            p = linesafterlastbeginfeature->data;
-                                            while (*p && isspace(*p)) p++;
-                                            width = strtod(p, &p);
-                                            while (*p && isspace(*p)) p++;
-                                            height = strtod(p, &p);
-                                            if (width && height) {
-                                                dstrcpyf(tmp, "%s.%fx%f", value, width, height);
-                                                strlcpy(value, tmp->data, 128);
-                                                option_set_value(o, optset, value);
-                                                if (optionsalsointoheader)
-                                                    option_set_value(o, optionset("header"), value);
-                                            }
-                                        }
-                                        /* For a composite option insert the
-                                        code from the member options with
-                                        current setting "From<composite>"
-                                        The code from the member options
-                                        is chosen according to the setting
-                                        of the composite option. */
-                                        if (option_is_composite(o) && linetype == LT_FOOMATIC_RIP_OPTION_SETTING) {
-                                            build_commandline(optset, NULL, 0); /* TODO can this be removed? */
-
-                                            /* TODO merge section and ps_section */
-                                            if (postscriptsection == PS_SECTION_JCLSETUP)
-                                                option_get_command(tmp, o, optset, SECTION_JCLSETUP);
-                                            else if (postscriptsection == PS_SECTION_PROLOG)
-                                                option_get_command(tmp, o, optset, SECTION_PROLOG);
-                                            else if (postscriptsection == PS_SECTION_SETUP)
-                                                option_get_command(tmp, o, optset, SECTION_DOCUMENTSETUP);
-                                            else if (postscriptsection == PS_SECTION_PAGESETUP)
-                                                option_get_command(tmp, o, optset, SECTION_PAGESETUP);
-                                            dstrcat(line, tmp->data);
-                                        }
-                                    }
-                                    else
-                                        _log(" --> Invalid option setting found in job\n");
-                                }
-                                else if (fromcomposite) {
-                                    /* PostScript option, but we have to look up
-                                    the PostScript code to be inserted from
-                                    the setting of a composite option, as
-                                    this option is set to "Controlled by
-                                    '<Composite>'". */
-                                    /* Set the option */
-                                    dstrcpyf(tmp, "From%s", value);
-                                    strlcpy(value, tmp->data, 128);
-                                    if (option_set_value(o, optset, value)) {
-                                        _log(" --> Looking up setting in composite option %s\n", value);
-                                        if (optionsalsointoheader)
-                                            option_set_value(o, optionset("header"), value);
-                                        /* update composite options */
-                                        build_commandline(optset, NULL, 0);
-                                        /* Substitute PostScript comment by the real code */
-                                        /* TODO what exactly is the next line doing? */
-                                        /* dstrcpy(line, o->compositesubst->data); */
-                                    }
-                                    else
-                                        _log(" --> Invalid option setting found in job\n");
-                                }
-                                else
-                                    /* it is a PostScript style option with
-                                    the code readily inserted, no option
-                                    for the renderer command line/JCL to set,
-                                    no lookup of a composite option needed,
-                                    so nothing to do here... */
-                                    _log(" --> Option will be set by PostScript interpreter\n");
-                            }
-                        }
-                        else
-                            /* This option is unknown to us, WTF? */
-                            _log("Unknown option %s=%s found in the job\n", optionname, value);
-                    }
-                    else if (nestinglevel == 0 && startswith(line->data, "%%EndFeature")) {
-                        /* End of feature */
-                        infeature = 0;
-                        /* If the option setting was replaced, it ends here,
-                        too, and the next option is not necessarily also replaced */
-                        optionreplaced = 0;
-                        dstrclear(linesafterlastbeginfeature);
-                    }
-                    else if (nestinglevel == 0 && isdscjob && !prologfound &&
-                                startswith(line->data, "%%Begin")) {
-                        /* In some PostScript files (especially when generated
-                        by "dvips" of TeX/LaTeX) the "%%BeginProlog" is
-                        missing, so assume that it was before the current
-                        line (the first line starting with "%%Begin". */
-                        _log("Job claims to be DSC-conforming, but \"%%%%BeginProlog\" "
-                            "was missing before first line with another"
-                            "\"%%%%BeginProlog\" comment (is this a TeX/LaTeX/dvips-generated"
-                            " PostScript file?). Assuming start of \"Prolog\" here.\n");
-                        /* Beginning of Prolog */
-                        inprolog = 1;
-                        nondsclines = 0;
-                        /* Insert options for "Prolog" before the current line */
-                        dstrcpyf(tmp, "%%%%BeginProlog\n");
-                        append_prolog_section(tmp, optset, 0);
-                        dstrprepend(line, tmp->data);
-                        prologfound = 1;
-                    }
-                    else if (nestinglevel == 0 && (
-                                startswith(line->data, "%RBINumCopies:") ||
-                                startswith(line->data, "%%RBINumCopies:"))) {
-                        p = strchr(line->data, ':') +1;
-                        get_current_job()->rbinumcopies = atoi(p);
-                        _log("Found %RBINumCopies: %d\n", get_current_job()->rbinumcopies);
-                    }
-                    else if (startswith(skip_whitespace(line->data), "%") ||
-                            startswith(skip_whitespace(line->data), "$"))
-                        /* This is an unknown PostScript comment or a blank
-                        line, no active code */
-                        ignoreline = 1;
-                }
-                else {
-                    /* This line is active PostScript code */
-                    if (infeature)
-                        /* Collect coe in a "%%BeginFeature: ... %%EndFeature"
-                        section, to get the values for a custom option
-                        setting */
-                        dstrcat(linesafterlastbeginfeature, line->data);
-
-                    if (inheader) {
-                        if (!inprolog && !insetup) {
-                            /* Outside the "Prolog" and "Setup" section
-                            a correct DSC-conforming document has no
-                            active PostScript code, so consider the
-                            file as non-DSC-conforming when there are
-                            too many of such lines. */
-                            nondsclines++;
-                            if (nondsclines > MAX_NON_DSC_LINES_IN_HEADER) {
-                                /* Consider document as not DSC-conforming */
-                                _log("This job seems not to be DSC-conforming, "
-                                    "DSC-comment for next section not found, "
-                                    "stopping to parse the rest, passing it "
-                                    "directly to the renderer.\n");
-                                /* Stop scanning for further option settings */
-                                maxlines = 1;
-                                isdscjob = 0;
-                                /* Insert defaults and command line settings in
-                                the beginning of the job or after the last valid
-                                section */
-                                dstrclear(tmp);
-                                if (!prologfound)
-                                    append_prolog_section(tmp, optset, 1);
-                                if (!setupfound)
-                                    append_setup_section(tmp, optset, 1);
-                                if (!pagesetupfound)
-                                    append_page_setup_section(tmp, optset, 1);
-                                dstrinsert(psheader, line_start(psheader->data, insertoptions), tmp->data);
-
-                                prologfound = 1;
-                                setupfound = 1;
-                                pagesetupfound = 1;
-                            }
-                        }
-                    }
-                    else if (!inpageheader) {
-                        /* PostScript code inside a page, but not between
-                        "%%BeginPageSetup" and "%%EndPageSetup", so
-                        we are perhaps already drawing onto a page now */
-                        if (startswith(onelinebefore->data, "%%Page"))
-                            _log("No page header or page header not DSC-conforming\n");
-                        /* Stop buffering lines to search for options
-                        placed not DSC-conforming */
-                        if (line_count(psfifo->data) >= MAX_LINES_FOR_PAGE_OPTIONS) {
-                            _log("Stopping search for page header options\n");
-                            passthru = 1;
-                            /* If there comes a page header now, ignore it */
-                            ignorepageheader = 1;
-                            optionsalsointoheader = 0;
-                        }
-                        /* Insert PostScript option settings (options for the
-                         * section "PageSetup" */
-                        if (isdscjob && !pagesetupfound) {
-                            append_page_setup_section(psfifo, optset, 1);
-                            pagesetupfound = 1;
-                        }
-                    }
-                }
-            }
-
-            /* Debug Info */
-            if (lastpassthru != passthru) {
-                if (passthru)
-                    _log("Found: %s --> Output goes directly to the renderer now.\n\n", line->data);
-                else
-                    _log("Found: %s --> Output goes to the FIFO buffer now.\n\n", line->data);
-            }
-
-            /* We are in an option which was replaced, do not output the current line */
-            if (optionreplaced)
-                dstrclear(line);
-
-            /* If we are in a "%%BeginSetup...%%EndSetup" section after
-            the first "%%Page:..." and the current line belongs to
-            an option setting, we have to copy the line also to the
-            @psheader. */
-            if (optionsalsointoheader && (infeature || startswith(line->data, "%%EndFeature")))
-                dstrcat(psheader, line->data);
-
-            /* Store or send the current line */
-            if (inheader && isdscjob) {
-                /* We are still in the PostScript header, collect all lines
-                in @psheader */
-                dstrcat(psheader, line->data);
-            }
-            else {
-                if (passthru && isdscjob) {
-                    if (!lastpassthru) {
-                        /*
-                         * We enter passthru mode with this line, so the
-                         * command line can have changed, check it and close
-                         * the renderer if needed
-                         */
-                        if (rendererpid && !optionset_equal(optionset("currentpage"), optionset("previouspage"), 0)) {
-                            _log("Command line/JCL options changed, restarting renderer\n");
-                            retval = close_renderer_handle(rendererhandle, rendererpid);
-                            if (retval != EXIT_PRINTED)
-                                rip_die(retval, "Error closing renderer\n");
-                            rendererpid = 0;
-                        }
-                    }
-
-                    /* Flush psfifo and send line directly to the renderer */
-                    if (!rendererpid) {
-                        /* No renderer running, start it */
-                        dstrcpy(tmp, psheader->data);
-                        dstrcat(tmp, psfifo->data);
-                        get_renderer_handle(tmp, &rendererhandle, &rendererpid);
-                        /* psfifo is sent out, flush it */
-                        dstrclear(psfifo);
-                    }
-
-                    if (!isempty(psfifo->data)) {
-                        /* Send psfifo to renderer */
-                        fwrite_or_die(psfifo->data, psfifo->len, 1, rendererhandle);
-                        /* flush psfifo */
-                        dstrclear(psfifo);
-                    }
-
-                    /* Send line to renderer */
-                    if (!printprevpage) {
-                        fwrite_or_die(line->data, line->len, 1, rendererhandle);
-
-                        while (stream_next_line(line, stream) > 0) {
-                            if (startswith(line->data, "%%")) {
-                                _log("Found: %s", line->data);
-                                _log(" --> Continue DSC parsing now.\n\n");
-                                saved = 1;
-                                break;
-                            }
-                            else {
-                                fwrite_or_die(line->data, line->len, 1, rendererhandle);
-                                linect++;
-                            }
-                        }
-                    }
-                }
-                else {
-                    /* Push the line onto the stack to split up later */
-                    dstrcat(psfifo, line->data);
-                }
-            }
-
-            if (!printprevpage)
-                linect++;
-        }
-        else {
-            /* EOF! */
-            more_stuff = 0;
-
-            /* No PostScript header in the whole file? Then it's not
-            PostScript, convert it.
-            We open the file converter here when the file has less
-            lines than the amount which we search for the PostScript
-            header ($maxlinestopsstart). */
-            if (linect <= nonpslines) {
-               /* This is not a PostScript job, abort it */
-               _log("Job does not start with \"%%!\", is it Postscript?\n");
-               rip_die(EXIT_JOBERR, "Unknown data format.\n");
-            }
-        }
-
-        lastpassthru = passthru;
-
-        if (!ignoreline && !printprevpage) {
-            dstrcpy(twolinesbefore, onelinebefore->data);
-            dstrcpy(onelinebefore, line->data);
-        }
-
-    } while ((maxlines == 0 || linect < maxlines) && more_stuff != 0);
-
-    /* Some buffer still containing data? Send it out to the renderer */
-    if (more_stuff || inheader || !isempty(psfifo->data)) {
-        /* Flush psfifo and send the remaining data to the renderer, this
-        only happens with non-DSC-conforming jobs or non-Foomatic PPDs */
-        if (more_stuff)
-            _log("Stopped parsing the PostScript data, "
-                 "sending rest directly to the renderer.\n");
-        else
-            _log("Flushing FIFO.\n");
-
-        if (inheader) {
-            build_commandline(optset, NULL, 0);
-            /* No page initialized yet? Copy the "header" option set into the
-            "currentpage" option set, so that the renderer will find the
-            options settings. */
-            optionset_copy_values(optionset("header"), optionset("currentpage"));
-            optset = optionset("currentpage");
-
-            /* If not done yet, insert defaults and command line settings
-            in the beginning of the job or after the last valid section */
-            dstrclear(tmp);
-            if (!prologfound)
-                append_prolog_section(tmp, optset, 1);
-            if (!setupfound)
-                append_setup_section(tmp, optset, 1);
-            if (!pagesetupfound)
-                append_page_setup_section(tmp, optset, 1);
-            dstrinsert(psheader, line_start(psheader->data, insertoptions), tmp->data);
-
-            prologfound = 1;
-            setupfound = 1;
-            pagesetupfound = 1;
-        }
-
-        if (rendererpid > 0 && !optionset_equal(optionset("currentpage"), optionset("previouspage"), 0)) {
-            _log("Command line/JCL options changed, restarting renderer\n");
-            retval = close_renderer_handle(rendererhandle, rendererpid);
-            if (retval != EXIT_PRINTED)
-                rip_die(retval, "Error closing renderer\n");
-            rendererpid = 0;
-        }
-
-        if (!rendererpid) {
-            dstrcpy(tmp, psheader->data);
-            dstrcat(tmp, psfifo->data);
-            get_renderer_handle(tmp, &rendererhandle, &rendererpid);
-            /* We have sent psfifo now */
-            dstrclear(psfifo);
-        }
-
-        if (psfifo->len) {
-            /* Send psfifo to the renderer */
-            fwrite_or_die(psfifo->data, psfifo->len, 1, rendererhandle);
-            dstrclear(psfifo);
-        }
-
-        /* Print the rest of the input data */
-        if (more_stuff) {
-            while (stream_next_line(tmp, stream))
-                fwrite_or_die(tmp->data, tmp->len, 1, rendererhandle);
-        }
+    if (!rendererpid)
+    {
+      dstrcpy(tmp, psheader->data);
+      dstrcat(tmp, psfifo->data);
+      get_renderer_handle(tmp, &rendererhandle, &rendererpid);
+      // We have sent psfifo now
+      dstrclear(psfifo);
     }
 
-    /*  At every "%%Page:..." comment we have saved the PostScript state
-    and we have increased the page number. So if the page number is
-    non-zero we had at least one "%%Page:..." comment and so we have
-    to give a restore the PostScript state.
-    if ($currentpage > 0) {
-        print $rendererhandle "foomatic-saved-state restore\n";
-    } */
-
-    /* Close the renderer */
-    if (rendererpid) {
-        retval = close_renderer_handle(rendererhandle, rendererpid);
-        if (retval != EXIT_PRINTED)
-            rip_die(retval, "Error closing renderer\n");
-        rendererpid = 0;
+    if (psfifo->len)
+    {
+      // Send psfifo to the renderer
+      fwrite_or_die(psfifo->data, psfifo->len, 1, rendererhandle);
+      dstrclear(psfifo);
     }
 
-    free_dstr(line);
-    free_dstr(onelinebefore);
-    free_dstr(twolinesbefore);
-    free_dstr(psheader);
-    free_dstr(psfifo);
-    free_dstr(tmp);
+    // Print the rest of the input data
+    if (more_stuff)
+    {
+      while (stream_next_line(tmp, stream))
+       fwrite_or_die(tmp->data, tmp->len, 1, rendererhandle);
+    }
+  }
+
+  // At every "%%Page:..." comment we have saved the PostScript state
+  // and we have increased the page number. So if the page number is
+  // non-zero we had at least one "%%Page:..." comment and so we have
+  // to give a restore the PostScript state.
+  //     if ($currentpage > 0) {
+  //       print $rendererhandle "foomatic-saved-state restore\n";
+  //     }
+
+  // Close the renderer
+  if (rendererpid)
+  {
+    retval = close_renderer_handle(rendererhandle, rendererpid);
+    if (retval != EXIT_PRINTED)
+      rip_die(retval, "Error closing renderer\n");
+    rendererpid = 0;
+  }
+
+  free_dstr(line);
+  free_dstr(onelinebefore);
+  free_dstr(twolinesbefore);
+  free_dstr(psheader);
+  free_dstr(psfifo);
+  free_dstr(tmp);
 }
 
-/*
- * Run the renderer command line (and if defined also the postpipe) and returns
- * a file handle for stuffing in the PostScript data.
- */
-void get_renderer_handle(const dstr_t *prepend, FILE **fd, pid_t *pid)
+
+//
+// Run the renderer command line (and if defined also the postpipe) and returns
+// a file handle for stuffing in the PostScript data.
+//
+
+void
+get_renderer_handle(const dstr_t *prepend,
+                   FILE **fd,
+                   pid_t *pid)
 {
-    pid_t kid3;
-    FILE *kid3in;
-    dstr_t *cmdline = create_dstr();
+  pid_t kid3;
+  FILE *kid3in;
+  dstr_t *cmdline = create_dstr();
 
-    /* Build the command line and get the JCL commands */
-    build_commandline(optionset("currentpage"), cmdline, 0);
-    massage_gs_commandline(cmdline);
+  // Build the command line and get the JCL commands
+  build_commandline(optionset("currentpage"), cmdline, 0);
+  massage_gs_commandline(cmdline);
 
-    _log("\nStarting renderer with command: \"%s\"\n", cmdline->data);
-    kid3 = start_process("kid3", exec_kid3, (void *)cmdline->data, &kid3in, NULL);
-    if (kid3 < 0)
-        rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Cannot fork for kid3\n");
+  _log("\nStarting renderer with command: \"%s\"\n", cmdline->data);
+  kid3 = start_process("kid3", exec_kid3, (void *)cmdline->data, &kid3in, NULL);
+  if (kid3 < 0)
+    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Cannot fork for kid3\n");
 
-    /* Feed the PostScript header and the FIFO contents */
-    if (prepend)
-        fwrite_or_die(prepend->data, prepend->len, 1, kid3in);
+  // Feed the PostScript header and the FIFO contents
+  if (prepend)
+    fwrite_or_die(prepend->data, prepend->len, 1, kid3in);
 
-    /* We are the parent, return glob to the file handle */
-    *fd = kid3in;
-    *pid = kid3;
+  // We are the parent, return glob to the file handle
+  *fd = kid3in;
+  *pid = kid3;
 
-    free_dstr(cmdline);
+  free_dstr(cmdline);
 }
 
-/* Close the renderer process and wait until all kid processes finish */
-int close_renderer_handle(FILE *rendererhandle, pid_t rendererpid)
+
+// Close the renderer process and wait until all kid processes finish
+int
+close_renderer_handle(FILE *rendererhandle,
+                     pid_t rendererpid)
 {
-    int status;
+  int status;
 
-    _log("\nClosing renderer\n");
-    fclose(rendererhandle);
+  _log("\nClosing renderer\n");
+  fclose(rendererhandle);
 
-    status = wait_for_process(rendererpid);
-    if (WIFEXITED(status))
-        return WEXITSTATUS(status);
-    else
-        return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
+  status = wait_for_process(rendererpid);
+  if (WIFEXITED(status))
+    return (WEXITSTATUS(status));
+  else
+    return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
 }
-
index d3089cc9844ad1cf28d03a4a6e3a2f5904880c8a..36d78cd501d00c64d9cfcf1073633306f23d9c2b 100644 (file)
@@ -1,30 +1,31 @@
-/* postscript.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// postscript.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef postscript_h
 #define postscript_h
 
-int print_ps(FILE *s, const char *alreadyread, size_t len, const char *filename);
-
-#endif
+int print_ps(FILE *s, const char *alreadyread, size_t len,
+            const char *filename);
 
+#endif // !postscript_h
index 61492620f6c92e288ff51be50890842094f297b7..c0a1afc2e0ce14334f401bac2355bc3a8bd5a051 100644 (file)
@@ -1,25 +1,26 @@
-/* process.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// process.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "foomaticrip.h"
 #include "process.h"
 #include <stdlib.h>
 #include <signal.h>
 
+
 int kidgeneration = 0;
 
-struct process {
-    char name[64];
-    pid_t pid;
-    int isgroup;
+struct process
+{
+  char name[64];
+  pid_t pid;
+  int isgroup;
 };
 
 #define MAX_CHILDS 4
-struct process procs[MAX_CHILDS] = {
+struct process procs[MAX_CHILDS] =
+{
     { "", -1, 0 },
     { "", -1, 0 },
     { "", -1, 0 },
     { "", -1, 0 }
 };
 
-void add_process(const char *name, int pid, int isgroup)
+
+void
+add_process(const char *name,
+           int pid,
+           int isgroup)
 {
-    int i;
-    for (i = 0; i < MAX_CHILDS; i++) {
-        if (procs[i].pid == -1) {
-            strlcpy(procs[i].name, name, 64);
-            procs[i].pid = pid;
-            procs[i].isgroup = isgroup;
-            return;
-        }
+  int i;
+  for (i = 0; i < MAX_CHILDS; i++)
+  {
+    if (procs[i].pid == -1)
+    {
+      strlcpy(procs[i].name, name, 64);
+      procs[i].pid = pid;
+      procs[i].isgroup = isgroup;
+      return;
     }
-    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Didn't think there would be that many child processes... Exiting.\n");
+  }
+  rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
+         "Didn't think there would be that many child processes... Exiting.\n");
 }
 
-int find_process(int pid)
+
+int
+find_process(int pid)
 {
-    int i;
-    for (i = 0; i < MAX_CHILDS; i++)
-        if (procs[i].pid == pid)
-            return i;
-    return -1;
+  int i;
+  for (i = 0; i < MAX_CHILDS; i++)
+    if (procs[i].pid == pid)
+      return (i);
+  return (-1);
 }
 
-void clear_proc_list()
+
+void
+clear_proc_list()
 {
-    int i;
-    for (i = 0; i < MAX_CHILDS; i++)
-        procs[i].pid = -1;
+  int i;
+  for (i = 0; i < MAX_CHILDS; i++)
+    procs[i].pid = -1;
 }
 
-void kill_all_processes()
+
+void
+kill_all_processes()
 {
-    int i;
-
-    for (i = 0; i < MAX_CHILDS; i++) {
-        if (procs[i].pid == -1)
-            continue;
-        _log("Killing %s\n", procs[i].name);
-        kill(procs[i].isgroup ? -procs[i].pid : procs[i].pid, 15);
-        sleep(1 << (3 - kidgeneration));
-        kill(procs[i].isgroup ? -procs[i].pid : procs[i].pid, 9);
-    }
-    clear_proc_list();
+  int i;
+
+  for (i = 0; i < MAX_CHILDS; i++)
+  {
+    if (procs[i].pid == -1)
+      continue;
+    _log("Killing %s\n", procs[i].name);
+    kill(procs[i].isgroup ? -procs[i].pid : procs[i].pid, 15);
+    sleep(1 << (3 - kidgeneration));
+    kill(procs[i].isgroup ? -procs[i].pid : procs[i].pid, 9);
+  }
+  clear_proc_list();
 }
 
-static pid_t _start_process(const char *name,
-                          int (*proc_func)(FILE *, FILE *, void *),
-                          void *user_arg, FILE **pipe_in, FILE **pipe_out,
-                          int createprocessgroup)
-{
-    pid_t pid;
-    int pfdin[2], pfdout[2];
-    int ret;
-    FILE *in, *out;
 
+static pid_t
+_start_process(const char *name,
+              int (*proc_func)(FILE *, FILE *, void *),
+              void *user_arg,
+              FILE **pipe_in,
+              FILE **pipe_out,
+              int createprocessgroup)
+{
+  pid_t pid;
+  int pfdin[2], pfdout[2];
+  int ret;
+  FILE *in, *out;
+
+  if (pipe_in)
+    if (pipe(pfdin) < 0)
+      return (-1);
+  if (pipe_out)
+    if (pipe(pfdout) < 0)
+      return (-1);
+
+  _log("Starting process \"%s\" (generation %d)\n", name, kidgeneration +1);
+
+  pid = fork();
+  if (pid < 0)
+  {
+    _log("Could not fork for %s\n", name);
     if (pipe_in)
-      if (pipe(pfdin) < 0)
-       return -1;
+    {
+      close(pfdin[0]);
+      close(pfdin[1]);
+    }
     if (pipe_out)
-      if (pipe(pfdout) < 0)
-       return -1;
-
-    _log("Starting process \"%s\" (generation %d)\n", name, kidgeneration +1);
-
-    pid = fork();
-    if (pid < 0) {
-        _log("Could not fork for %s\n", name);
-        if (pipe_in) {
-            close(pfdin[0]);
-            close(pfdin[1]);
-        }
-        if (pipe_out) {
-            close(pfdout[0]);
-            close(pfdout[1]);
-        }
-        return -1;
+    {
+      close(pfdout[0]);
+      close(pfdout[1]);
     }
+    return (-1);
+  }
 
-    if (pid == 0) { /* Child */
-
-        // Reset sigpipe behavior to default for all children
-        signal(SIGPIPE, SIG_DFL);
-
-        if (pipe_in) {
-            close(pfdin[1]);
-            in = fdopen(pfdin[0], "r");
-        }
-        else
-            in = NULL;
-
-        if (pipe_out) {
-            close(pfdout[0]);
-            out = fdopen(pfdout[1], "w");
-        }
-        else
-            out = NULL;
-
-        if (createprocessgroup)
-            setpgid(0, 0);
-
-        kidgeneration++;
+  if (pid == 0)
+  {
+    // Child
 
-        /* The subprocess list is only valid for the parent. Clear it. */
-        clear_proc_list();
+    // Reset sigpipe behavior to default for all children
+    signal(SIGPIPE, SIG_DFL);
 
-        ret = proc_func(in, out, user_arg);
-        exit(ret);
+    if (pipe_in)
+    {
+      close(pfdin[1]);
+      in = fdopen(pfdin[0], "r");
     }
+    else
+      in = NULL;
 
-    /* Parent */
-    if (pipe_in) {
-        close(pfdin[0]);
-        *pipe_in = fdopen(pfdin[1], "w");
-        if (!*pipe_in)
-            _log("fdopen: %s\n", strerror(errno));
-    }
-    if (pipe_out) {
-        close(pfdout[1]);
-        *pipe_out = fdopen(pfdout[0], "r");
-        if (!*pipe_out)
-            _log("fdopen: %s\n", strerror(errno));
+    if (pipe_out)
+    {
+      close(pfdout[0]);
+      out = fdopen(pfdout[1], "w");
     }
+    else
+      out = NULL;
 
-    /* Add the child process to the list of open processes (to be able to kill
-     * them in case of a signal. */
-    add_process(name, pid, createprocessgroup);
+    if (createprocessgroup)
+      setpgid(0, 0);
 
-    return pid;
-}
+    kidgeneration ++;
 
-int exec_command(FILE *in, FILE *out, void *cmd)
-{
-    if (in && dup2(fileno(in), fileno(stdin)) < 0)
-        rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "%s: Could not dup stdin\n", (const char *)cmd);
-    if (out && dup2(fileno(out), fileno(stdout)) < 0)
-        rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "%s: Could not dup stdout\n", (const char *)cmd);
-
-    execl(get_modern_shell(), get_modern_shell(), "-e", "-c", (const char *)cmd, (char *)NULL);
+    // The subprocess list is only valid for the parent. Clear it.
+    clear_proc_list();
 
-    _log("Error: Executing \"%s -c %s\" failed (%s).\n", get_modern_shell(), (const char *)cmd, strerror(errno));
-    return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
+    ret = proc_func(in, out, user_arg);
+    exit(ret);
+  }
+
+  // Parent
+  if (pipe_in)
+  {
+    close(pfdin[0]);
+    *pipe_in = fdopen(pfdin[1], "w");
+    if (!*pipe_in)
+      _log("fdopen: %s\n", strerror(errno));
+  }
+  if (pipe_out)
+  {
+    close(pfdout[1]);
+    *pipe_out = fdopen(pfdout[0], "r");
+    if (!*pipe_out)
+      _log("fdopen: %s\n", strerror(errno));
+  }
+
+  // Add the child process to the list of open processes (to be able to kill
+  // them in case of a signal.
+  add_process(name, pid, createprocessgroup);
+
+  return (pid);
 }
 
-pid_t start_system_process(const char *name, const char *command, FILE **fdin, FILE **fdout)
+
+int
+exec_command(FILE *in,
+            FILE *out,
+            void *cmd)
 {
-    return _start_process(name, exec_command, (void*)command, fdin, fdout, 1);
+  if (in && dup2(fileno(in), fileno(stdin)) < 0)
+    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
+           "%s: Could not dup stdin\n", (const char *)cmd);
+  if (out && dup2(fileno(out), fileno(stdout)) < 0)
+    rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
+           "%s: Could not dup stdout\n", (const char *)cmd);
+
+  execl(get_modern_shell(), get_modern_shell(), "-e", "-c",
+       (const char *)cmd, (char *)NULL);
+
+  _log("Error: Executing \"%s -c %s\" failed (%s).\n", get_modern_shell(),
+       (const char *)cmd, strerror(errno));
+  return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
 }
 
-pid_t start_process(const char *name, int (*proc_func)(FILE *, FILE *, void *), void *user_arg, FILE **fdin, FILE **fdout)
+
+pid_t
+start_system_process(const char *name,
+                    const char *command,
+                    FILE **fdin,
+                    FILE **fdout)
 {
-    return _start_process(name, proc_func, user_arg, fdin, fdout, 0);
+  return (_start_process(name, exec_command, (void*)command, fdin, fdout, 1));
 }
 
-int wait_for_process(int pid)
-{
-    int i;
-    int status;
 
-    i = find_process(pid);
-    if (i < 0) {
-        _log("No such process \"%d\"", pid);
-        return -1;
-    }
+pid_t
+start_process(const char *name,
+             int (*proc_func)(FILE *, FILE *, void *),
+             void *user_arg,
+             FILE **fdin,
+             FILE **fdout)
+{
+  return (_start_process(name, proc_func, user_arg, fdin, fdout, 0));
+}
 
-    waitpid(procs[i].pid, &status, 0);
-    if (WIFEXITED(status))
-        _log("%s exited with status %d\n", procs[i].name, WEXITSTATUS(status));
-    else if (WIFSIGNALED(status))
-        _log("%s received signal %d\n", procs[i].name, WTERMSIG(status));
 
-    /* remove from process list */
-    procs[i].pid = -1;
-    return status;
+int
+wait_for_process(int pid)
+{
+  int i;
+  int status;
+
+  i = find_process(pid);
+  if (i < 0)
+  {
+    _log("No such process \"%d\"", pid);
+    return (-1);
+  }
+
+  waitpid(procs[i].pid, &status, 0);
+  if (WIFEXITED(status))
+    _log("%s exited with status %d\n", procs[i].name, WEXITSTATUS(status));
+  else if (WIFSIGNALED(status))
+    _log("%s received signal %d\n", procs[i].name, WTERMSIG(status));
+
+  // remove from process list
+  procs[i].pid = -1;
+  return (status);
 }
 
-int run_system_process(const char *name, const char *command)
+
+int
+run_system_process(const char *name,
+                  const char *command)
 {
-    int pid = start_system_process(name, command, NULL, NULL);
-    return wait_for_process(pid);
+  int pid = start_system_process(name, command, NULL, NULL);
+  return (wait_for_process(pid));
 }
-
index 04c8b92ebb41cd13963d3ec09765a3232e971256..af4c6abbd7bd242d891a02b763dbad3bc59e50c8 100644 (file)
@@ -1,25 +1,26 @@
-/* process.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// process.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef process_h
 #define process_h
 #include <sys/types.h>
 #include <sys/wait.h>
 
-pid_t start_process(const char *name, int (*proc_func)(), void *user_arg, FILE **fdin, FILE **fdout);
-pid_t start_system_process(const char *name, const char *command, FILE **fdin, FILE **fdout);
 
-/* returns command's return status (see waitpid(2)) */
+pid_t start_process(const char *name, int (*proc_func)(), void *user_arg,
+                   FILE **fdin, FILE **fdout);
+pid_t start_system_process(const char *name, const char *command, FILE **fdin,
+                          FILE **fdout);
+
+// returns command's return status (see waitpid(2))
 int run_system_process(const char *name, const char *command);
 
-pid_t create_pipe_process(const char *name,
-                          FILE *src,
-                          FILE *dest,
-                          const char *alreadyread,
-                          size_t alreadyread_len);
+pid_t create_pipe_process(const char *name, FILE *src, FILE *dest,
+                          const char *alreadyread, size_t alreadyread_len);
 
 int wait_for_process(int pid);
 
 void kill_all_processes();
 
-#endif
-
+#endif // !process_h
index 62cf5090eabb8ee402fb395b17fa65bdd850362a..62b8591c28047481bcd0a447316c3cc46c7375b4 100644 (file)
@@ -1,25 +1,27 @@
-/* renderer.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// renderer.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
+
 #include <config.h>
 #include <signal.h>
 #include <ctype.h>
 #include "process.h"
 #include "options.h"
 
-/*
- * Check whether we have a Ghostscript version with redirection of the standard
- * output of the PostScript programs via '-sstdout=%stderr'
- */
-int test_gs_output_redirection()
-{
-    char gstestcommand[CMDLINE_MAX];
-    char output[10] = "";
-    int bytes;
-
-    snprintf(gstestcommand, CMDLINE_MAX,
-            "%s -dQUIET -dSAFER -dNOPAUSE "
-             "-dBATCH -dNOMEDIAATTRS -sDEVICE=ps2write -sstdout=%%stderr "
-             "-sOutputFile=/dev/null -c '(hello\n) print flush' 2>&1", gspath);
-
-    FILE *pd = popen(gstestcommand, "r");
-    if (!pd) {
-        _log("Failed to execute ghostscript!\n");
-        return 0;
-    }
 
-    bytes = fread_or_die(output, 1, 10, pd);
-    pclose(pd);
+//
+// Check whether we have a Ghostscript version with redirection of the standard
+// output of the PostScript programs via '-sstdout=%stderr'
+//
 
-    if (bytes > 0 && startswith(output, "hello"))
-        return 1;
-
-    return 0;
-}
-
-/*
- * Massage arguments to make ghostscript execute properly as a filter, with
- * output on stdout and errors on stderr etc.  (This function does what
- * foomatic-gswrapper used to do)
- */
-void massage_gs_commandline(dstr_t *cmd)
+int
+test_gs_output_redirection()
 {
-    int gswithoutputredirection = test_gs_output_redirection();
-    size_t start, end;
-    dstr_t *gscmd, *cmdcopy;
-
-    extract_command(&start, &end, cmd->data, "gs");
-    if (start == end) /* cmd doesn't call ghostscript */
-        return;
-
-    gscmd = create_dstr();
-    dstrncpy(gscmd, &cmd->data[start], end - start);
-
-    /* If Ghostscript does not support redirecting the standard output
-       of the PostScript program to standard error with '-sstdout=%stderr', sen
-       the job output data to fd 3; errors will be on 2(stderr) and job ps
-       program interpreter output on 1(stdout). */
-    if (gswithoutputredirection)
-        dstrreplace(gscmd, "-sOutputFile=- ", "-sOutputFile=%stdout ", 0);
-    else
-        dstrreplace(gscmd, "-sOutputFile=- ", "-sOutputFile=/dev/fd/3 ", 0);
-
-    /* Use always buffered input. This works around a Ghostscript
-       bug which prevents printing encrypted PDF files with Adobe Reader 8.1.1
-       and Ghostscript built as shared library (Ghostscript bug #689577, Ubuntu
-       bug #172264) */
-    if (dstrendswith(gscmd, " -"))
-        dstrcat(gscmd, "_");
-    else
-        dstrreplace(gscmd, " - ", " -_ ", 0);
-    dstrreplace(gscmd, " /dev/fd/0", " -_ ", 0);
+  char gstestcommand[CMDLINE_MAX];
+  char output[10] = "";
+  int bytes;
 
-    /* Turn *off* -q (quiet!); now that stderr is useful! :) */
-    dstrreplace(gscmd, " -q ", " ", 0);
+  snprintf(gstestcommand, CMDLINE_MAX,
+          "%s -dQUIET -dSAFER -dNOPAUSE "
+          "-dBATCH -dNOMEDIAATTRS -sDEVICE=ps2write -sstdout=%%stderr "
+          "-sOutputFile=/dev/null -c '(hello\n) print flush' 2>&1", gspath);
 
-    /* Escape any quotes, and then quote everything just to be sure...
-       Escaping a single quote inside single quotes is a bit complex as the
-       shell takes everything literal there. So we have to assemble it by
-       concatinating different quoted strings.  Finally we get e.g.: 'x'"'"'y'
-       or ''"'"'xy' or 'xy'"'"'' or ... */
-    /* dstrreplace(cmd, "'", "'\"'\"'"); TODO tbd */
+  FILE *pd = popen(gstestcommand, "r");
+  if (!pd)
+  {
+    _log("Failed to execute ghostscript!\n");
+    return (0);
+  }
 
-    dstrremove(gscmd, 0, 2);     /* Remove 'gs' */
-    if (gswithoutputredirection)
-    {
-        dstrprepend(gscmd, " -sstdout=%stderr ");
-        dstrprepend(gscmd, gspath);
-    }
-    else
-    {
-        dstrprepend(gscmd, gspath);
-        dstrcat(gscmd, " 3>&1 1>&2");
-    }
+  bytes = fread_or_die(output, 1, 10, pd);
+  pclose(pd);
 
-    /* put gscmd back into cmd, between 'start' and 'end' */
-    cmdcopy = create_dstr();
-    dstrcpy(cmdcopy, cmd->data);
+  if (bytes > 0 && startswith(output, "hello"))
+    return (1);
 
-    dstrncpy(cmd, cmdcopy->data, start);
-    dstrcat(cmd, gscmd->data);
-    dstrcat(cmd, &cmdcopy->data[end]);
+  return (0);
+}
 
-    free_dstr(gscmd);
-    free_dstr(cmdcopy);
 
-    /* If the renderer command line contains the "echo" command, replace the
-     * "echo" by the user-chosen $myecho (important for non-GNU systems where
-     * GNU echo is in a special path */
-    dstrreplace(cmd, "echo", echopath, 0); /* TODO search for \wecho\w */
-}
+//
+// Massage arguments to make ghostscript execute properly as a filter, with
+// output on stdout and errors on stderr etc.  (This function does what
+// foomatic-gswrapper used to do)
+//
 
-char * read_line(FILE *stream, size_t *readbytes)
+void
+massage_gs_commandline(dstr_t *cmd)
 {
-    char *line;
-    size_t alloc = 64, len = 0;
-    int c;
-
-    line = malloc(alloc);
-
-    while ((c = fgetc(stream)) != EOF) {
-        if (len >= alloc -1) {
-            alloc *= 2;
-            line = realloc(line, alloc);
-        }
-        line[len] = (char)c;
-        len++;
-        if (c == '\n')
-            break;
-    }
-
-    line[len] = '\0';
-    *readbytes = len;
-    return line;
+  int gswithoutputredirection = test_gs_output_redirection();
+  size_t start, end;
+  dstr_t *gscmd, *cmdcopy;
+
+  extract_command(&start, &end, cmd->data, "gs");
+  if (start == end) // cmd doesn't call ghostscript
+    return;
+
+  gscmd = create_dstr();
+  dstrncpy(gscmd, &cmd->data[start], end - start);
+
+  // If Ghostscript does not support redirecting the standard output
+  // of the PostScript program to standard error with '-sstdout=%stderr', sen
+  // the job output data to fd 3; errors will be on 2(stderr) and job ps
+  // program interpreter output on 1(stdout).
+  if (gswithoutputredirection)
+    dstrreplace(gscmd, "-sOutputFile=- ", "-sOutputFile=%stdout ", 0);
+  else
+    dstrreplace(gscmd, "-sOutputFile=- ", "-sOutputFile=/dev/fd/3 ", 0);
+
+  // Use always buffered input. This works around a Ghostscript
+  // bug which prevents printing encrypted PDF files with Adobe Reader 8.1.1
+  // and Ghostscript built as shared library (Ghostscript bug #689577, Ubuntu
+  // bug #172264)
+  if (dstrendswith(gscmd, " -"))
+    dstrcat(gscmd, "_");
+  else
+    dstrreplace(gscmd, " - ", " -_ ", 0);
+  dstrreplace(gscmd, " /dev/fd/0", " -_ ", 0);
+
+  // Turn *off* -q (quiet!); now that stderr is useful! :)
+  dstrreplace(gscmd, " -q ", " ", 0);
+
+  // Escape any quotes, and then quote everything just to be sure...
+  // Escaping a single quote inside single quotes is a bit complex as the
+  // shell takes everything literal there. So we have to assemble it by
+  // concatinating different quoted strings.  Finally we get e.g.: 'x'"'"'y'
+  // or ''"'"'xy' or 'xy'"'"'' or ...
+  // dstrreplace(cmd, "'", "'\"'\"'"); TODO tbd
+
+  dstrremove(gscmd, 0, 2);     // Remove 'gs'
+  if (gswithoutputredirection)
+  {
+    dstrprepend(gscmd, " -sstdout=%stderr ");
+    dstrprepend(gscmd, gspath);
+  }
+  else
+  {
+    dstrprepend(gscmd, gspath);
+    dstrcat(gscmd, " 3>&1 1>&2");
+  }
+
+  // put gscmd back into cmd, between 'start' and 'end'
+  cmdcopy = create_dstr();
+  dstrcpy(cmdcopy, cmd->data);
+
+  dstrncpy(cmd, cmdcopy->data, start);
+  dstrcat(cmd, gscmd->data);
+  dstrcat(cmd, &cmdcopy->data[end]);
+
+  free_dstr(gscmd);
+  free_dstr(cmdcopy);
+
+  // If the renderer command line contains the "echo" command, replace the
+  // "echo" by the user-chosen $myecho (important for non-GNU systems where
+  // GNU echo is in a special path
+  dstrreplace(cmd, "echo", echopath, 0); // TODO search for \wecho\w
 }
 
-void write_binary_data(FILE *stream, const char *data, size_t bytes)
+
+char *
+read_line(FILE *stream,
+         size_t *readbytes)
 {
-    int i;
-    for (i=0; i < bytes; i++)
+  char *line;
+  size_t alloc = 64, len = 0;
+  int c;
+
+  line = malloc(alloc);
+
+  while ((c = fgetc(stream)) != EOF)
+  {
+    if (len >= alloc -1)
     {
-       fputc(data[i], stream);
+      alloc *= 2;
+      line = realloc(line, alloc);
     }
+    line[len] = (char)c;
+    len++;
+    if (c == '\n')
+      break;
+  }
+
+  line[len] = '\0';
+  *readbytes = len;
+  return (line);
 }
 
-/*
- * Read all lines containing 'jclstr' from 'stream' (actually, one more) and
- * return them in a zero terminated array.
- */
-static char ** read_jcl_lines(FILE *stream, const char *jclstr,
-                             size_t *readbinarybytes)
+
+void
+write_binary_data(FILE *stream,
+                 const char *data,
+                 size_t bytes)
 {
-    char *line;
-    char **result;
-    size_t alloc = 8, cnt = 0;
+  int i;
+  for (i=0; i < bytes; i++)
+  {
+    fputc(data[i], stream);
+  }
+}
+
 
-    result = malloc(alloc * sizeof(char *));
+//
+// Read all lines containing 'jclstr' from 'stream' (actually, one more) and
+// return them in a zero terminated array.
+//
 
-    /* read from the renderer output until the first non-JCL line appears */
-    while ((line = read_line(stream, readbinarybytes)))
+static char **
+read_jcl_lines(FILE *stream,
+              const char *jclstr,
+              size_t *readbinarybytes)
+{
+  char *line;
+  char **result;
+  size_t alloc = 8, cnt = 0;
+
+  result = malloc(alloc * sizeof(char *));
+
+  // read from the renderer output until the first non-JCL line appears
+  while ((line = read_line(stream, readbinarybytes)))
+  {
+    if (cnt >= alloc -1)
     {
-        if (cnt >= alloc -1)
-        {
-            alloc *= 2;
-            result = realloc(result, alloc * sizeof(char *));
-        }
-        result[cnt] = line;
-        if (!strstr(line, jclstr))
-            break;
-        /* Remove newline from the end of a line containing JCL */
-        result[cnt][*readbinarybytes - 1] = '\0';
-        cnt++;
+      alloc *= 2;
+      result = realloc(result, alloc * sizeof(char *));
     }
-
+    result[cnt] = line;
+    if (!strstr(line, jclstr))
+      break;
+    // Remove newline from the end of a line containing JCL
+    result[cnt][*readbinarybytes - 1] = '\0';
     cnt++;
-    result[cnt] = NULL;
-    return result;
+  }
+
+  cnt++;
+  result[cnt] = NULL;
+  return (result);
 }
 
-static int jcl_keywords_equal(const char *jclline1, const char *jclline2,
-                              const char *jclstr)
-{
-    char *j1, *j2, *p1, *p2;
 
-    j1 = strstr(jclline1, jclstr);
-    if (!j1) return 0;
-    if (!(p1 = strchr(skip_whitespace(j1), '=')))
-        p1 = j1 + strlen(j1);
+static int
+jcl_keywords_equal(const char *jclline1,
+                  const char *jclline2,
+                  const char *jclstr)
+{
+  char *j1, *j2, *p1, *p2;
+
+  j1 = strstr(jclline1, jclstr);
+  if (!j1)
+    return (0);
+  if (!(p1 = strchr(skip_whitespace(j1), '=')))
+    p1 = j1 + strlen(j1);
+  p1--;
+  while (p1 > j1 && isspace(*p1))
     p1--;
-    while (p1 > j1 && isspace(*p1))
-        p1--;
 
-    j2 = strstr(jclline2, jclstr);
-    if (!j2) return 0;
-    if (!(p2 = strchr(skip_whitespace(j2), '=')))
-        p2 = j2 + strlen(j2);
+  j2 = strstr(jclline2, jclstr);
+  if (!j2)
+    return (0);
+  if (!(p2 = strchr(skip_whitespace(j2), '=')))
+    p2 = j2 + strlen(j2);
+  p2--;
+  while (p2 > j2 && isspace(*p2))
     p2--;
-    while (p2 > j2 && isspace(*p2))
-        p2--;
 
-    if (p1 - j1 != p2 - j2) return 0;
-    return strncmp(j1, j2, p1 - j1 + 1) == 0;
+  if (p1 - j1 != p2 - j2)
+    return (0);
+
+  return (strncmp(j1, j2, p1 - j1 + 1) == 0);
 }
 
-/*
- * Finds the keyword of line in opts
- */
-static const char * jcl_options_find_keyword(char **opts, const char *line,
-                                             const char *jclstr)
-{
-    if (!opts)
-        return NULL;
+//
+// Finds the keyword of line in opts
+//
 
-    while (*opts)
-    {
-        if (jcl_keywords_equal(*opts, line, jclstr))
-            return *opts;
-        opts++;
-    }
-    return NULL;
+static const char *
+jcl_options_find_keyword(char **opts,
+                        const char *line,
+                        const char *jclstr)
+{
+  if (!opts)
+    return (NULL);
+
+  while (*opts)
+  {
+    if (jcl_keywords_equal(*opts, line, jclstr))
+      return (*opts);
+    opts ++;
+  }
+  return (NULL);
 }
 
-static void argv_write(FILE *stream, char **argv, const char *sep)
+
+static void
+argv_write(FILE *stream,
+          char **argv,
+          const char *sep)
 {
-    if (!argv)
-        return;
+  if (!argv)
+    return;
 
-    while (*argv)
-        fprintf(stream, "%s%s", *argv++, sep);
+  while (*argv)
+    fprintf(stream, "%s%s", *argv++, sep);
 }
 
-/*
- * Merges 'original_opts' and 'pref_opts' and writes them to 'stream'. Header /
- * footer is taken from 'original_opts'. If both have the same options, the one
- * from 'pref_opts' is preferred
- * Returns true, if original_opts was not empty
- */
-static int write_merged_jcl_options(FILE *stream,
-                                    char **original_opts,
-                                    char **opts,
-                                    size_t readbinarybytes,
-                                    const char *jclstr)
-{
-    char *p = strstr(original_opts[0], jclstr);
-    char header[128];
-    char **optsp1 = NULL, **optsp2 = NULL;
 
-    /* No JCL options in original_opts, just prepend opts */
-    if (argv_count(original_opts) == 1)
-    {
-        fprintf(stream, "%s", jclbegin);
-        argv_write(stream, opts, "\n");
-        write_binary_data(stream, original_opts[0], readbinarybytes);
-        return 0;
-    }
+//
+// Merges 'original_opts' and 'pref_opts' and writes them to 'stream'. Header /
+// footer is taken from 'original_opts'. If both have the same options, the one
+// from 'pref_opts' is preferred
+// Returns true, if original_opts was not empty
+//
 
-    if (argv_count(original_opts) == 2)
+static int
+write_merged_jcl_options(FILE *stream,
+                        char **original_opts,
+                        char **opts,
+                        size_t readbinarybytes,
+                        const char *jclstr)
+{
+  char *p = strstr(original_opts[0], jclstr);
+  char header[128];
+  char **optsp1 = NULL, **optsp2 = NULL;
+
+  // No JCL options in original_opts, just prepend opts
+  if (argv_count(original_opts) == 1)
+  {
+    fprintf(stream, "%s", jclbegin);
+    argv_write(stream, opts, "\n");
+    write_binary_data(stream, original_opts[0], readbinarybytes);
+    return (0);
+  }
+
+  if (argv_count(original_opts) == 2)
+  {
+    // If we have only one line of JCL it is probably something like the
+    // "@PJL ENTER LANGUAGE=..." line which has to be in the end, but it
+    // also contains the "<esc>%-12345X" which has to be in the beginning
+    // of the job
+    if (p)
+      fwrite_or_die(original_opts[0], 1, p - original_opts[0], stream);
+    else
+      fprintf(stream, "%s\n", original_opts[0]);
+
+    argv_write(stream, opts, "\n");
+
+    if (p)
+      fprintf(stream, "%s\n", p);
+
+    write_binary_data(stream, original_opts[1], readbinarybytes);
+    return (1);
+  }
+
+  // Write jcl header
+  strncpy(header, original_opts[0], p - original_opts[0]);
+  header[p - original_opts[0]] = '\0';
+  fprintf(stream, "%s", header);
+
+  // Insert the JCL commands from the PPD file right before the first
+  // "@PJL SET ..." line from the, if there are no "@PJL SET ..." lines,
+  // directly before "@PJL ENTER LANGUAGE ...", otherwise after the JCL
+  // commands from the driver
+  for (optsp1 = original_opts; *(optsp1 + 1); optsp1++)
+  {
+    if (optsp2 == NULL &&
+       ((strstr(*optsp1, "ENTER LANGUAGE") != NULL) ||
+        (strncasecmp(*optsp1, "@PJL SET ", 9) == 0)))
     {
-        /* If we have only one line of JCL it is probably something like the
-         * "@PJL ENTER LANGUAGE=..." line which has to be in the end, but it
-         * also contains the "<esc>%-12345X" which has to be in the beginning
-         * of the job */
-        if (p)
-            fwrite_or_die(original_opts[0], 1, p - original_opts[0], stream);
-        else
-            fprintf(stream, "%s\n", original_opts[0]);
-
-        argv_write(stream, opts, "\n");
-
-        if (p)
-            fprintf(stream, "%s\n", p);
-
-        write_binary_data(stream, original_opts[1], readbinarybytes);
-        return 1;
+      for (optsp2 = opts; *optsp2; optsp2++)
+       if (!jcl_options_find_keyword(original_opts, *optsp2, jclstr))
+         fprintf(stream, "%s\n", *optsp2);
     }
+    if (optsp1 != original_opts) p = *optsp1;
+    if (!p)
+      _log("write_merged_jcl_options() dereferences NULL pointer p\n");
+    if (jcl_options_find_keyword(opts, p, jclstr))
+      fprintf(stream, "%s\n", jcl_options_find_keyword(opts, p, jclstr));
+    else
+      fprintf(stream, "%s\n", p);
+  }
+  if (optsp2 == NULL)
+    for (optsp2 = opts; *optsp2; optsp2++)
+      if (!jcl_options_find_keyword(original_opts, *optsp2, jclstr))
+       fprintf(stream, "%s\n", *optsp2);
 
-    /* Write jcl header */
-    strncpy(header, original_opts[0], p - original_opts[0]);
-    header[p - original_opts[0]] = '\0';
-    fprintf(stream, "%s", header);
-
-    /* Insert the JCL commands from the PPD file right before the first
-       "@PJL SET ..." line from the, if there are no "@PJL SET ..." lines,
-       directly before "@PJL ENTER LANGUAGE ...", otherwise after the JCL
-       commands from the driver */
-    for (optsp1 = original_opts; *(optsp1 + 1); optsp1++) {
-        if (optsp2 == NULL &&
-           ((strstr(*optsp1, "ENTER LANGUAGE") != NULL) ||
-            (strncasecmp(*optsp1, "@PJL SET ", 9) == 0))) {
-           for (optsp2 = opts; *optsp2; optsp2++)
-               if (!jcl_options_find_keyword(original_opts, *optsp2, jclstr))
-                   fprintf(stream, "%s\n", *optsp2);
-       }
-        if (optsp1 != original_opts) p = *optsp1;
-        if (!p)
-            _log("write_merged_jcl_options() dereferences NULL pointer p\n");
-        if (jcl_options_find_keyword(opts, p, jclstr))
-         fprintf(stream, "%s\n", jcl_options_find_keyword(opts, p, jclstr));
-       else
-            fprintf(stream, "%s\n", p);
-    }
-    if (optsp2 == NULL)
-        for (optsp2 = opts; *optsp2; optsp2++)
-            if (!jcl_options_find_keyword(original_opts, *optsp2, jclstr))
-               fprintf(stream, "%s\n", *optsp2);
-
-    write_binary_data(stream, *optsp1, readbinarybytes);
+  write_binary_data(stream, *optsp1, readbinarybytes);
 
-    return 1;
+  return (1);
 }
 
-void log_jcl()
+
+void
+log_jcl()
 {
-    char **opt;
+  char **opt;
 
-    _log("JCL: %s", jclbegin);
-    if (jclprepend)
-        for (opt = jclprepend; *opt; opt++)
-            _log("%s\n", *opt);
+  _log("JCL: %s", jclbegin);
+  if (jclprepend)
+    for (opt = jclprepend; *opt; opt++)
+      _log("%s\n", *opt);
 
-    _log("<job data> %s\n\n", jclappend->data);
+  _log("<job data> %s\n\n", jclappend->data);
 }
 
-int exec_kid4(FILE *in, FILE *out, void *user_arg)
+
+int
+exec_kid4(FILE *in,
+         FILE *out,
+         void *user_arg)
 {
-    FILE *fileh = open_postpipe();
-    int driverjcl = 0;
-    size_t readbinarybytes;
+  FILE *fileh = open_postpipe();
+  int driverjcl = 0;
+  size_t readbinarybytes;
+
+  log_jcl();
+
+  // wrap the JCL around the job data, if there are any options specified...
+  // Should the driver already have inserted JCL commands we merge our JCL
+  // header with the one from the driver
+  if (argv_count(jclprepend) > 0)
+  {
+    if (!isspace(jclprepend[0][0]))
+    {
+      char *jclstr, **jclheader;
+      size_t pos;
 
-    log_jcl();
+      pos = strcspn(jclprepend[0], " \t\n\r");
+      jclstr = malloc(pos +1);
+      strncpy(jclstr, jclprepend[0], pos);
+      jclstr[pos] = '\0';
 
-    /* wrap the JCL around the job data, if there are any options specified...
-     * Should the driver already have inserted JCL commands we merge our JCL
-     * header with the one from the driver */
-    if (argv_count(jclprepend) > 0)
-    {
-        if (!isspace(jclprepend[0][0]))
-        {
-            char *jclstr, **jclheader;
-            size_t pos;
-
-            pos = strcspn(jclprepend[0], " \t\n\r");
-            jclstr = malloc(pos +1);
-            strncpy(jclstr, jclprepend[0], pos);
-            jclstr[pos] = '\0';
-
-            jclheader = read_jcl_lines(in, jclstr, &readbinarybytes);
-
-            driverjcl = write_merged_jcl_options(fileh,
-                                                 jclheader,
-                                                 jclprepend,
-                                                 readbinarybytes,
-                                                 jclstr);
-
-            free(jclstr);
-            argv_free(jclheader);
-        }
-        else
-            /* No merging of JCL header possible, simply prepend it */
-            argv_write(fileh, jclprepend, "\n");
+      jclheader = read_jcl_lines(in, jclstr, &readbinarybytes);
+
+      driverjcl = write_merged_jcl_options(fileh,
+                                          jclheader,
+                                          jclprepend,
+                                          readbinarybytes,
+                                          jclstr);
+
+      free(jclstr);
+      argv_free(jclheader);
     }
+    else
+      // No merging of JCL header possible, simply prepend it
+      argv_write(fileh, jclprepend, "\n");
+  }
 
-    /* The job data */
-    copy_file(fileh, in, NULL, 0);
+  // The job data
+  copy_file(fileh, in, NULL, 0);
 
-    /* A JCL trailer */
-    if (argv_count(jclprepend) > 0 && !driverjcl)
-        fwrite_or_die(jclappend->data, jclappend->len, 1, fileh);
+  // A JCL trailer
+  if (argv_count(jclprepend) > 0 && !driverjcl)
+    fwrite_or_die(jclappend->data, jclappend->len, 1, fileh);
 
-    fclose(in);
-    if (fclose(fileh) != 0)
-    {
-        _log("error closing postpipe\n");
-        return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-    }
+  fclose(in);
+  if (fclose(fileh) != 0)
+  {
+    _log("error closing postpipe\n");
+    return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+  }
 
-    return EXIT_PRINTED;
+  return (EXIT_PRINTED);
 }
 
-int exec_kid3(FILE *in, FILE *out, void *user_arg)
+
+int
+exec_kid3(FILE *in,
+         FILE *out,
+         void *user_arg)
 {
-    dstr_t *commandline;
-    int kid4;
-    FILE *kid4in;
-    int status;
-
-    commandline = create_dstr();
-    dstrcpy(commandline, (const char *)user_arg);
-
-    kid4 = start_process("kid4", exec_kid4, NULL, &kid4in, NULL);
-    if (kid4 < 0) {
-        free_dstr(commandline);
-        return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-    }
+  dstr_t *commandline;
+  int kid4;
+  FILE *kid4in;
+  int status;
 
-    if (in && dup2(fileno(in), fileno(stdin)) < 0) {
-        _log("kid3: Could not dup stdin\n");
-        fclose(kid4in);
-        free_dstr(commandline);
-        return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-    }
-    if (dup2(fileno(kid4in), fileno(stdout)) < 0) {
-        _log("kid3: Could not dup stdout to kid4\n");
-        fclose(kid4in);
-        free_dstr(commandline);
-        return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-    }
-    if (debug)
-    {
-        if (!redirect_log_to_stderr()) {
-            fclose(kid4in);
-            free_dstr(commandline);
-            return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
-        }
-
-        /* Save the data supposed to be fed into the renderer also into a file*/
-        dstrprepend(commandline, "tee $(mktemp " LOG_FILE "-XXXXXX.ps) | ( ");
-        dstrcat(commandline, ")");
-    }
+  commandline = create_dstr();
+  dstrcpy(commandline, (const char *)user_arg);
 
-    /* Actually run the thing */
-    status = run_system_process("renderer", commandline->data);
+  kid4 = start_process("kid4", exec_kid4, NULL, &kid4in, NULL);
+  if (kid4 < 0)
+  {
+    free_dstr(commandline);
+    return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+  }
 
-    if (in)
-        fclose(in);
+  if (in && dup2(fileno(in), fileno(stdin)) < 0)
+  {
+    _log("kid3: Could not dup stdin\n");
+    fclose(kid4in);
+    free_dstr(commandline);
+    return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+  }
+  if (dup2(fileno(kid4in), fileno(stdout)) < 0)
+  {
+    _log("kid3: Could not dup stdout to kid4\n");
     fclose(kid4in);
-    fclose(stdin);
-    fclose(stdout);
     free_dstr(commandline);
+    return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+  }
+  if (debug)
+  {
+    if (!redirect_log_to_stderr())
+    {
+      fclose(kid4in);
+      free_dstr(commandline);
+      return (EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+    }
+
+    // Save the data supposed to be fed into the renderer also into a file
+    dstrprepend(commandline, "tee $(mktemp " LOG_FILE "-XXXXXX.ps) | ( ");
+    dstrcat(commandline, ")");
+  }
+
+  // Actually run the thing
+  status = run_system_process("renderer", commandline->data);
 
-    if (WIFEXITED(status)) {
-        switch (WEXITSTATUS(status)) {
-            case 0:  /* Success! */
-                /* wait for postpipe/output child */
-                wait_for_process(kid4);
-                _log("kid3 finished\n");
-                return EXIT_PRINTED;
-            case 1:
-                _log("Possible error on renderer command line or PostScript error. Check options.");
-                return EXIT_JOBERR;
-            case 139:
-                _log("The renderer may have dumped core.");
-                return EXIT_JOBERR;
-            case 141:
-                _log("A filter used in addition to the renderer itself may have failed.");
-                return EXIT_PRNERR;
-            case 243:
-            case 255:  /* PostScript error? */
-                return EXIT_JOBERR;
-        }
+  if (in)
+    fclose(in);
+  fclose(kid4in);
+  fclose(stdin);
+  fclose(stdout);
+  free_dstr(commandline);
+
+  if (WIFEXITED(status))
+  {
+    switch (WEXITSTATUS(status))
+    {
+      case 0:  // Success!
+         // wait for postpipe/output child
+         wait_for_process(kid4);
+         _log("kid3 finished\n");
+         return (EXIT_PRINTED);
+      case 1:
+         _log("Possible error on renderer command line or PostScript error. Check options.");
+         return (EXIT_JOBERR);
+      case 139:
+         _log("The renderer may have dumped core.");
+         return (EXIT_JOBERR);
+      case 141:
+         _log("A filter used in addition to the renderer itself may have failed.");
+         return (EXIT_PRNERR);
+      case 243:
+      case 255:  // PostScript error?
+         return (EXIT_JOBERR);
     }
-    else if (WIFSIGNALED(status)) {
-        switch (WTERMSIG(status)) {
-            case SIGUSR1:
-                return EXIT_PRNERR;
-            case SIGUSR2:
-                return EXIT_PRNERR_NORETRY;
-            case SIGTTIN:
-                return EXIT_ENGAGED;
-        }
+  }
+  else if (WIFSIGNALED(status))
+  {
+    switch (WTERMSIG(status))
+    {
+      case SIGUSR1:
+         return (EXIT_PRNERR);
+      case SIGUSR2:
+         return (EXIT_PRNERR_NORETRY);
+      case SIGTTIN:
+         return (EXIT_ENGAGED);
     }
-    return EXIT_PRNERR;
+  }
+  return (EXIT_PRNERR);
 }
-
index fac8c2785f6ca03a46d6221e87fcfd7d33643f67..81d155b987d3288af8039742824c7ebfc642f1ac 100644 (file)
@@ -1,25 +1,26 @@
-/* renderer.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// renderer.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef renderer_h
 #define renderer_h
@@ -27,5 +28,4 @@
 void massage_gs_commandline(dstr_t *cmd);
 int exec_kid3(FILE *in, FILE *out, void *user_arg);
 
-#endif
-
+#endif // !renderer_h
index cc4ab2f04c2a2c2c83e4a8e06de2bd2b84b0957b..11213d65e8ed74b0b9c672cee83e5718d674af0e 100644 (file)
@@ -1,25 +1,26 @@
-/* spooler.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// spooler.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "spooler.h"
 #include "foomaticrip.h"
 #include <unistd.h>
 #include <limits.h>
 
-const char *spooler_name(int spooler)
+
+const char *
+spooler_name(int spooler)
 {
-    switch (spooler) {
-        case SPOOLER_CUPS: return "cups";
-        case SPOOLER_DIRECT: return "direct";
-    };
-    return "<unknown>";
+  switch (spooler)
+  {
+    case SPOOLER_CUPS:
+        return ("cups");
+    case SPOOLER_DIRECT:
+        return ("direct");
+  };
+  return ("<unknown>");
 }
 
-void init_cups(list_t *arglist, dstr_t *filelist, jobparams_t *job)
+
+void
+init_cups(list_t *arglist,
+         dstr_t *filelist,
+         jobparams_t *job)
 {
-    char path [PATH_MAX] = "";
-    char cups_jobid [128];
-    char cups_user [128];
-    char cups_jobtitle [2048];
-    char cups_copies [128];
-    int cups_options_len;
-    char *cups_options;
-    const char *pname;
-    char cups_filename [256];
-
-    if (getenv("CUPS_FONTPATH"))
-        strncpy(path, getenv("CUPS_FONTPATH"), PATH_MAX - 1);
-    else if (getenv("CUPS_DATADIR")) {
-       strncpy(path, getenv("CUPS_DATADIR"), PATH_MAX - 1);
-       strncat(path, "/fonts", PATH_MAX - strlen(path) - 1);
-    }
-    if (getenv("GS_LIB")) {
-        strncat(path, ":", PATH_MAX - strlen(path) - 1);
-        strncat(path, getenv("GS_LIB"), PATH_MAX - strlen(path) - 1);
-    }
-    setenv("GS_LIB", path, 1);
+  char path [PATH_MAX] = "";
+  char cups_jobid [128];
+  char cups_user [128];
+  char cups_jobtitle [2048];
+  char cups_copies [128];
+  int cups_options_len;
+  char *cups_options;
+  const char *pname;
+  char cups_filename [256];
 
-    /* Get all command line parameters */
-    strncpy_omit(cups_jobid, arglist_get(arglist, 0), 128, omit_shellescapes);
-    strncpy_omit(cups_user, arglist_get(arglist, 1), 128, omit_shellescapes);
-    strncpy_omit(cups_jobtitle, arglist_get(arglist, 2), 2048,
-                omit_shellescapes);
-    strncpy_omit(cups_copies, arglist_get(arglist, 3), 128, omit_shellescapes);
+  if (getenv("CUPS_FONTPATH"))
+    strncpy(path, getenv("CUPS_FONTPATH"), PATH_MAX - 1);
+  else if (getenv("CUPS_DATADIR"))
+  {
+    strncpy(path, getenv("CUPS_DATADIR"), PATH_MAX - 1);
+    strncat(path, "/fonts", PATH_MAX - strlen(path) - 1);
+  }
+  if (getenv("GS_LIB"))
+  {
+    strncat(path, ":", PATH_MAX - strlen(path) - 1);
+    strncat(path, getenv("GS_LIB"), PATH_MAX - strlen(path) - 1);
+  }
+  setenv("GS_LIB", path, 1);
 
-    cups_options_len = strlen(arglist_get(arglist, 4));
-    cups_options = malloc(cups_options_len + 1);
-    strncpy_omit(cups_options, arglist_get(arglist, 4), cups_options_len + 1,
-                omit_shellescapes);
+  // Get all command line parameters
+  strncpy_omit(cups_jobid, arglist_get(arglist, 0), 128, omit_shellescapes);
+  strncpy_omit(cups_user, arglist_get(arglist, 1), 128, omit_shellescapes);
+  strncpy_omit(cups_jobtitle, arglist_get(arglist, 2), 2048,
+              omit_shellescapes);
+  strncpy_omit(cups_copies, arglist_get(arglist, 3), 128, omit_shellescapes);
+
+  cups_options_len = strlen(arglist_get(arglist, 4));
+  cups_options = malloc(cups_options_len + 1);
+  strncpy_omit(cups_options, arglist_get(arglist, 4), cups_options_len + 1,
+              omit_shellescapes);
 
-    /* Common job parameters */
-    strcpy(job->id, cups_jobid);
-    strcpy(job->title, cups_jobtitle);
-    strcpy(job->user, cups_user);
-    strcpy(job->copies, cups_copies);
-    dstrcatf(job->optstr, " %s", cups_options);
-
-    /* Check for and handle inputfile vs stdin */
-    if (list_item_count(arglist) > 4) {
-        strncpy_omit(cups_filename, arglist_get(arglist, 5), 256, omit_shellescapes);
-        if (cups_filename[0] != '-') {
-            /* We get input from a file */
-            dstrcatf(filelist, "%s ", cups_filename);
-            _log("Getting input from file %s\n", cups_filename);
-        }
+  // Common job parameters
+  strcpy(job->id, cups_jobid);
+  strcpy(job->title, cups_jobtitle);
+  strcpy(job->user, cups_user);
+  strcpy(job->copies, cups_copies);
+  dstrcatf(job->optstr, " %s", cups_options);
+
+  // Check for and handle inputfile vs stdin
+  if (list_item_count(arglist) > 4)
+  {
+    strncpy_omit(cups_filename, arglist_get(arglist, 5), 256,
+                omit_shellescapes);
+    if (cups_filename[0] != '-')
+    {
+      // We get input from a file
+      dstrcatf(filelist, "%s ", cups_filename);
+      _log("Getting input from file %s\n", cups_filename);
     }
+  }
 
-    /* On which queue are we printing?
-       CUPS puts the print queue name into the PRINTER environment variable
-       when calling filters. */
-    pname = getenv("PRINTER");
-    if (pname == NULL)
-      pname = "unknown";
-    strncpy(job->printer, pname, 256);
-    job->printer[255] = '\0';
+  // On which queue are we printing?
+  // CUPS puts the print queue name into the PRINTER environment variable
+  // when calling filters.
+  pname = getenv("PRINTER");
+  if (pname == NULL)
+    pname = "unknown";
+  strncpy(job->printer, pname, 256);
+  job->printer[255] = '\0';
 
-    free(cups_options);
+  free(cups_options);
 }
 
-/* used by init_direct to find a ppd file */
-int find_ppdfile(const char *user_default_path, jobparams_t *job)
+
+// used by init_direct to find a ppd file
+int
+find_ppdfile(const char *user_default_path,
+            jobparams_t *job)
 {
-    /* Search also common spooler-specific locations, this way a printer
-       configured under a certain spooler can also be used without spooler */
-
-    strcpy(job->ppdfile, job->printer);
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-
-    snprintf(job->ppdfile, 2048, "%s.ppd", job->printer); /* current dir */
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-    snprintf(job->ppdfile, 2048, "%s/%s.ppd", user_default_path, job->printer); /* user dir */
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-    snprintf(job->ppdfile, 2048, "%s/direct/%s.ppd", CONFIG_PATH, job->printer); /* system dir */
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-    snprintf(job->ppdfile, 2048, "%s/%s.ppd", CONFIG_PATH, job->printer); /* system dir */
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-    snprintf(job->ppdfile, 2048, "/etc/cups/ppd/%s.ppd", job->printer); /* CUPS config dir */
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-    snprintf(job->ppdfile, 2048, "/usr/local/etc/cups/ppd/%s.ppd", job->printer); /* CUPS config dir */
-    if (access(job->ppdfile, R_OK) == 0)
-        return 1;
-
-    /* nothing found */
-    job->ppdfile[0] = '\0';
-    return 0;
+  // Search also common spooler-specific locations, this way a printer
+  // configured under a certain spooler can also be used without spooler
+
+  strcpy(job->ppdfile, job->printer);
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+
+  snprintf(job->ppdfile, 2048, "%s.ppd", job->printer); // current dir
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+  snprintf(job->ppdfile, 2048, "%s/%s.ppd", user_default_path, job->printer);
+                                                        // user dir
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+  snprintf(job->ppdfile, 2048, "%s/direct/%s.ppd", CONFIG_PATH, job->printer);
+                                                        // system dir
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+  snprintf(job->ppdfile, 2048, "%s/%s.ppd", CONFIG_PATH, job->printer);
+                                                        // system dir
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+  snprintf(job->ppdfile, 2048, "/etc/cups/ppd/%s.ppd", job->printer);
+                                                        // CUPS config dir
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+  snprintf(job->ppdfile, 2048, "/usr/local/etc/cups/ppd/%s.ppd", job->printer);
+                                                        // CUPS config dir
+  if (access(job->ppdfile, R_OK) == 0)
+    return (1);
+
+  // nothing found
+  job->ppdfile[0] = '\0';
+  return (0);
 }
 
-/* search 'configfile' for 'key', copy value into dest, return success */
-int configfile_find_option(const char *configfile, const char *key, char *dest, size_t destsize)
+
+// search 'configfile' for 'key', copy value into dest, return success
+int
+configfile_find_option(const char *configfile,
+                      const char *key,
+                      char *dest,
+                      size_t destsize)
 {
-    FILE *fh;
-    char line [1024];
-    char *p;
-
-    dest[0] = '\0';
-
-    if (!(fh = fopen(configfile, "r")))
-        return 0;
-
-    while (fgets(line, 1024, fh)) {
-        if (!prefixcmp(line, "default")) {
-            p = strchr(line, ':');
-            if (p) {
-                strncpy_omit(dest, p + 1, destsize, omit_whitespace_newline);
-                if (dest[0])
-                    break;
-            }
-        }
+  FILE *fh;
+  char line [1024];
+  char *p;
+
+  dest[0] = '\0';
+
+  if (!(fh = fopen(configfile, "r")))
+    return (0);
+
+  while (fgets(line, 1024, fh))
+  {
+    if (!prefixcmp(line, "default"))
+    {
+      p = strchr(line, ':');
+      if (p)
+      {
+       strncpy_omit(dest, p + 1, destsize, omit_whitespace_newline);
+       if (dest[0])
+         break;
+      }
     }
-    fclose(fh);
-    return dest[0] != '\0';
+  }
+  fclose(fh);
+  return (dest[0] != '\0');
 }
 
-/* tries to find a default printer name in various config files and copies the
- * result into the global var 'printer'. Returns success */
-int find_default_printer(const char *user_default_path, jobparams_t *job)
+
+// tries to find a default printer name in various config files and copies the
+// result into the global var 'printer'. Returns success
+int
+find_default_printer(const char *user_default_path,
+                    jobparams_t *job)
 {
-    char configfile [1024];
-    char *key = "default";
-
-    if (configfile_find_option("./.directconfig", key, job->printer, 256))
-        return 1;
-    if (configfile_find_option("./directconfig", key, job->printer, 256))
-        return 1;
-    if (configfile_find_option("./.config", key, job->printer, 256))
-        return 1;
-    strlcpy(configfile, user_default_path, 1024);
-    strlcat(configfile, "/direct/.config", 1024);
-    if (configfile_find_option(configfile, key, job->printer, 256))
-        return 1;
-    strlcpy(configfile, user_default_path, 1024);
-    strlcat(configfile, "/direct.conf", 1024);
-    if (configfile_find_option(configfile, key, job->printer, 256))
-        return 1;
-    if (configfile_find_option(CONFIG_PATH "/direct/.config", key, job->printer, 256))
-        return 1;
-    if (configfile_find_option(CONFIG_PATH "/direct.conf", key, job->printer, 256))
-        return 1;
-
-    return 0;
+  char configfile [1024];
+  char *key = "default";
+
+  if (configfile_find_option("./.directconfig", key, job->printer, 256))
+    return (1);
+  if (configfile_find_option("./directconfig", key, job->printer, 256))
+    return (1);
+  if (configfile_find_option("./.config", key, job->printer, 256))
+    return (1);
+  strlcpy(configfile, user_default_path, 1024);
+  strlcat(configfile, "/direct/.config", 1024);
+  if (configfile_find_option(configfile, key, job->printer, 256))
+    return (1);
+  strlcpy(configfile, user_default_path, 1024);
+  strlcat(configfile, "/direct.conf", 1024);
+  if (configfile_find_option(configfile, key, job->printer, 256))
+    return (1);
+  if (configfile_find_option(CONFIG_PATH "/direct/.config", key, job->printer,
+                            256))
+    return (1);
+  if (configfile_find_option(CONFIG_PATH "/direct.conf", key, job->printer,
+                            256))
+    return (1);
+
+  return (0);
 }
 
-void init_direct(list_t *arglist, dstr_t *filelist, jobparams_t *job)
+
+void
+init_direct(list_t *arglist,
+           dstr_t *filelist,
+           jobparams_t *job)
 {
-    char tmp [1024];
-    listitem_t *i;
-    char user_default_path [PATH_MAX];
+  char tmp [1024];
+  listitem_t *i;
+  char user_default_path [PATH_MAX];
+
+  strlcpy(user_default_path, getenv("HOME"), 256);
+  strlcat(user_default_path, "/.foomatic/", 256);
 
-    strlcpy(user_default_path, getenv("HOME"), 256);
-    strlcat(user_default_path, "/.foomatic/", 256);
+  // Which files do we want to print?
+  for (i = arglist->first; i; i = i->next)
+  {
+    strncpy_omit(tmp, (char*)i->data, 1024, omit_shellescapes);
+    dstrcatf(filelist, "%s ", tmp);
+  }
 
-    /* Which files do we want to print? */
-    for (i = arglist->first; i; i = i->next) {
-        strncpy_omit(tmp, (char*)i->data, 1024, omit_shellescapes);
-        dstrcatf(filelist, "%s ", tmp);
+  if (job->ppdfile[0] == '\0')
+  {
+    if (job->printer[0] == '\0')
+    {
+      // No printer definition file selected, check whether we have a
+      // default printer defined
+      find_default_printer(user_default_path, job);
     }
 
-    if (job->ppdfile[0] == '\0') {
-        if (job->printer[0] == '\0') {
-            /* No printer definition file selected, check whether we have a
-               default printer defined */
-            find_default_printer(user_default_path, job);
-        }
-
-        /* Neither in a config file nor on the command line a printer was selected */
-        if (!job->printer[0]) {
-            _log("No printer definition (option \"-P <name>\") specified!\n");
-            exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
-        }
-
-        /* Search for the PPD file */
-        if (!find_ppdfile(user_default_path, job)) {
-            _log("There is no readable PPD file for the printer %s, is it configured?\n", job->printer);
-            exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
-        }
+    // Neither in a config file nor on the command line a printer was selected
+    if (!job->printer[0])
+    {
+      _log("No printer definition (option \"-P <name>\") specified!\n");
+      exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
     }
-}
 
+    // Search for the PPD file
+    if (!find_ppdfile(user_default_path, job))
+    {
+      _log("There is no readable PPD file for the printer %s, is it configured?\n",
+          job->printer);
+      exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
+    }
+  }
+}
index fc4cb34de092bdb97c18779fa26a90dd7e222094..33749d3808d1b2ef8d2786fc6dfbab08e1a8d3d0 100644 (file)
@@ -1,25 +1,26 @@
-/* spooler.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// spooler.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef SPOOLER_H
 #define SPOOLER_H
@@ -31,5 +32,5 @@ const char *spooler_name(int spooler);
 void init_cups(list_t *arglist, dstr_t *filelist, jobparams_t *job);
 void init_direct(list_t *arglist, dstr_t *filelist, jobparams_t *job);
 
-#endif
+#endif // !SPOOLER_H
 
index 706e52ba693381a9d5ac24d79d6efa0f3860303c..fb619a94002d730ae617de6e9d1a5c68c9cd8f8d 100644 (file)
@@ -1,25 +1,26 @@
-/* util.c
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// util.c
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #include "util.h"
 #include "foomaticrip.h"
 #include <errno.h>
 
 
-const charshellescapes = "|;<>&!$\'\"`#*?()[]{}";
+const char *shellescapes = "|;<>&!$\'\"`#*?()[]{}";
 
-const char * temp_dir()
+
+const char *
+temp_dir()
 {
-    static const char *tmpdir = NULL;
+  static const char *tmpdir = NULL;
+
+  if (!tmpdir)
+  {
+    const char *dirs[] = { getenv("TMPDIR"), P_tmpdir, "/tmp" };
+    int i;
 
-    if (!tmpdir)
+    for (i = 0; i < (sizeof(dirs) / sizeof(dirs[0])); i++)
     {
-        const char *dirs[] = { getenv("TMPDIR"), P_tmpdir, "/tmp" };
-        int i;
-
-        for (i = 0; i < (sizeof(dirs) / sizeof(dirs[0])); i++) {
-            if (access(dirs[i], W_OK) == 0) {
-                tmpdir = dirs[i];
-                break;
-            }
-        }
-        if (tmpdir)
-        {
-            _log("Storing temporary files in %s\n", tmpdir);
-            setenv("TMPDIR", tmpdir, 1); /* for child processes */
-        }
-        else
-            rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
-                    "Cannot find a writable temp dir.");
+      if (access(dirs[i], W_OK) == 0)
+      {
+       tmpdir = dirs[i];
+       break;
+      }
     }
+    if (tmpdir)
+    {
+      _log("Storing temporary files in %s\n", tmpdir);
+      setenv("TMPDIR", tmpdir, 1); // for child processes
+    }
+    else
+      rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
+             "Cannot find a writable temp dir.");
+  }
 
-    return tmpdir;
+  return (tmpdir);
 }
 
-int prefixcmp(const char *str, const char *prefix)
+
+int
+prefixcmp(const char *str,
+         const char *prefix)
 {
-    return strncmp(str, prefix, strlen(prefix));
+  return (strncmp(str, prefix, strlen(prefix)));
 }
 
-int prefixcasecmp(const char *str, const char *prefix)
+
+int
+prefixcasecmp(const char *str,
+             const char *prefix)
 {
-    return strncasecmp(str, prefix, strlen(prefix));
+  return (strncasecmp(str, prefix, strlen(prefix)));
 }
 
-int startswith(const char *str, const char *prefix)
+
+int
+startswith(const char *str,
+          const char *prefix)
 {
-    return str ? (strncmp(str, prefix, strlen(prefix)) == 0) : 0;
+  return (str ? (strncmp(str, prefix, strlen(prefix)) == 0) : 0);
 }
 
-int endswith(const char *str, const char *postfix)
+
+int
+endswith(const char *str,
+        const char *postfix)
 {
-    int slen = strlen(str);
-    int plen = strlen(postfix);
-    const char *pstr;
+  int slen = strlen(str);
+  int plen = strlen(postfix);
+  const char *pstr;
 
-    if (slen < plen)
-        return 0;
+  if (slen < plen)
+    return (0);
 
-    pstr = &str[slen - plen];
-    return strcmp(pstr, postfix) == 0;
+  pstr = &str[slen - plen];
+  return (strcmp(pstr, postfix) == 0);
 }
 
-const char * skip_whitespace(const char *str)
+
+const char *
+skip_whitespace(const char *str)
 {
-    while (*str && isspace(*str))
-        str++;
-    return str;
+  while (*str && isspace(*str))
+    str ++;
+  return (str);
 }
 
-void strlower(char *dest, size_t destlen, const char *src)
+
+void
+strlower(char *dest,
+        size_t destlen,
+        const char *src)
 {
-    char *pdest = dest;
-    const char *psrc = src;
-    while (*psrc && --destlen > 0)
-    {
-        *pdest = tolower(*psrc);
-        pdest++;
-        psrc++;
-    }
-    *pdest = '\0';
+  char *pdest = dest;
+  const char *psrc = src;
+  while (*psrc && --destlen > 0)
+  {
+    *pdest = tolower(*psrc);
+    pdest++;
+    psrc++;
+  }
+  *pdest = '\0';
 }
 
+
 int isempty(const char *string)
 {
-    return !string || string[0] == '\0';
-}
-
-const char * strncpy_omit(char* dest, const char* src, size_t n, int (*omit_func)(int))
-{
-    const char* psrc = src;
-    char* pdest = dest;
-    int cnt = n -1;
-    if (!pdest)
-        return NULL;
-    if (psrc) {
-        while (*psrc != 0 && cnt > 0) {
-            if (!omit_func(*psrc)) {
-                *pdest = *psrc;
-                pdest++;
-                cnt--;
-            }
-            psrc++;
-        }
+  return (!string || string[0] == '\0');
+}
+
+
+const char *
+strncpy_omit(char* dest,
+            const char* src,
+            size_t n,
+            int (*omit_func)(int))
+{
+  const char* psrc = src;
+  char* pdest = dest;
+  int cnt = n - 1;
+
+  if (!pdest)
+    return (NULL);
+
+  if (psrc)
+  {
+    while (*psrc != 0 && cnt > 0)
+    {
+      if (!omit_func(*psrc))
+      {
+       *pdest = *psrc;
+       pdest++;
+       cnt--;
+      }
+      psrc++;
     }
-    *pdest = '\0';
-    return psrc;
+  }
+  *pdest = '\0';
+  return (psrc);
 }
-int omit_unprintables(int c) { return c>= '\x00' && c <= '\x1f'; }
-int omit_shellescapes(int c) { return strchr(shellescapes, c) != NULL; }
-int omit_specialchars(int c) { return omit_unprintables(c) || omit_shellescapes(c); }
-int omit_whitespace(int c) { return c == ' ' || c == '\t'; }
-int omit_whitespace_newline(int c) { return omit_whitespace(c) || c == '\n'; }
+
+
+int omit_unprintables(int c) { return (c >= '\x00' && c <= '\x1f'); }
+int omit_shellescapes(int c) { return (strchr(shellescapes, c) != NULL); }
+int omit_specialchars(int c) { return (omit_unprintables(c) ||
+                                      omit_shellescapes(c)); }
+int omit_whitespace(int c) { return (c == ' ' || c == '\t'); }
+int omit_whitespace_newline(int c) { return (omit_whitespace(c) || c == '\n'); }
+
 
 #ifndef HAVE_STRCASESTR
 char *
-strcasestr (const char *haystack, const char *needle)
-{
-    char *p, *startn = 0, *np = 0;
-
-    for (p = haystack; *p; p++) {
-        if (np) {
-           if (toupper(*p) == toupper(*np)) {
-               if (!*++np)
-                   return startn;
-           } else
-               np = 0;
-       } else if (toupper(*p) == toupper(*needle)) {
-           np = needle + 1;
-           startn = p;
-       }
+strcasestr (const char *haystack,
+           const char *needle)
+{
+  char *p, *startn = 0, *np = 0;
+
+  for (p = haystack; *p; p++)
+  {
+    if (np)
+    {
+      if (toupper(*p) == toupper(*np))
+      {
+       if (!*++np)
+         return (startn);
+      }
+      else
+       np = 0;
     }
+    else if (toupper(*p) == toupper(*needle))
+    {
+      np = needle + 1;
+      startn = p;
+    }
+  }
 
-    return 0;
+  return (0);
 }
 #endif
 
+
 #ifndef __OpenBSD__
 #ifndef HAVE_STRLCPY
-size_t strlcpy(char *dest, const char *src, size_t size)
-{
-    char *pdest = dest;
-    const char *psrc = src;
-
-    if (!src) {
-        dest[0] = '\0';
-        return 0;
-    }
+size_t
+strlcpy(char *dest,
+       const char *src,
+       size_t size)
+{
+  char *pdest = dest;
+  const char *psrc = src;
+
+  if (!src)
+  {
+    dest[0] = '\0';
+    return (0);
+  }
+
+  if (size)
+  {
+    while (--size && (*pdest++ = *psrc++) != '\0');
+    *pdest = '\0';
+  }
+  
+  if (!size)
+    while (*psrc++);
 
-    if (size) {
-        while (--size && (*pdest++ = *psrc++) != '\0');
-        *pdest = '\0';
-    }
-    if (!size)
-        while (*psrc++);
-    return (psrc - src -1);
+  return (psrc - src - 1);
 }
-#endif /* ! HAVE_STRLCPY */
+#endif // ! HAVE_STRLCPY
+
 
 #ifndef HAVE_STRLCAT
-size_t strlcat(char *dest, const char *src, size_t size)
+size_t
+strlcat(char *dest,
+       const char *src,
+       size_t size)
 {
-    char *pdest = dest;
-    const char *psrc = src;
-    size_t i = size;
-    size_t len;
+  char *pdest = dest;
+  const char *psrc = src;
+  size_t i = size;
+  size_t len;
 
-    while (--i && *pdest)
-        pdest++;
-    len = pdest - dest;
+  while (--i && *pdest)
+    pdest++;
+  len = pdest - dest;
 
-    if (!i)
-        return strlen(src) + len;
+  if (!i)
+    return (strlen(src) + len);
 
-    while (i-- && *psrc)
-        *pdest++ = *psrc++;
-    *pdest = '\0';
+  while (i-- && *psrc)
+    *pdest++ = *psrc++;
+  *pdest = '\0';
 
-    return len + (psrc - src);
+  return (len + (psrc - src));
 }
-#endif /* ! HAVE_STRLCAT */
-#endif /* ! __OpenBSD__ */
+#endif // ! HAVE_STRLCAT
+#endif // ! __OpenBSD__
 
-void strrepl(char *str, const char *chars, char repl)
+
+void
+strrepl(char *str,
+       const char *chars,
+       char repl)
 {
-    char *p = str;
+  char *p = str;
 
-    while (*p) {
-        if (strchr(chars, *p))
-            *p = repl;
-        p++;
-    }
+  while (*p)
+  {
+    if (strchr(chars, *p))
+      *p = repl;
+    p++;
+  }
 }
 
-void strrepl_nodups(char *str, const char *chars, char repl)
-{
-    char *pstr = str;
-    char *p = str;
-    int prev = 0;
-
-    while (*pstr) {
-        if (strchr(chars, *pstr) || *pstr == repl) {
-            if (!prev) {
-                *p = repl;
-                p++;
-                prev = 1;
-            }
-        }
-        else {
-            *p = *pstr;
-            p++;
-            prev = 0;
-        }
-        pstr++;
+
+void
+strrepl_nodups(char *str,
+              const char *chars,
+              char repl)
+{
+  char *pstr = str;
+  char *p = str;
+  int prev = 0;
+
+  while (*pstr)
+  {
+    if (strchr(chars, *pstr) || *pstr == repl)
+    {
+      if (!prev)
+      {
+       *p = repl;
+       p++;
+       prev = 1;
+      }
     }
-    *p = '\0';
+    else
+    {
+      *p = *pstr;
+      p++;
+      prev = 0;
+    }
+    pstr++;
+  }
+  *p = '\0';
 }
 
-void strclr(char *str)
+
+void
+strclr(char *str)
 {
-    while (*str) {
-        *str = '\0';
-        str++;
-    }
+  while (*str)
+  {
+    *str = '\0';
+    str++;
+  }
 }
 
-char * strnchr(const char *str, int c, size_t n)
+
+char *
+strnchr(const char *str,
+       int c,
+       size_t n)
 {
-    char *p = (char*)str;
+  char *p = (char*)str;
 
-    while (*p && --n > 0) {
-        if (*p == (char)c)
-            return p;
-        p++;
-    }
-    return p;
+  while (*p && --n > 0)
+  {
+    if (*p == (char)c)
+      return (p);
+    p++;
+  }
+  return (p);
 }
 
-void escapechars(char *dest, size_t size, const char *src, const char *esc_chars)
+
+void
+escapechars(char *dest,
+           size_t size,
+           const char *src,
+           const char *esc_chars)
 {
-    const char *psrc = src;
+  const char *psrc = src;
 
-    while (*psrc && --size > 0) {
-        if (strchr(esc_chars, *psrc))
-            *dest++ = '\\';
-        *dest++ = *psrc++;
-    }
+  while (*psrc && --size > 0)
+  {
+    if (strchr(esc_chars, *psrc))
+      *dest++ = '\\';
+    *dest++ = *psrc++;
+  }
 }
 
-const char * strncpy_tochar(char *dest, const char *src, size_t max, const char *stopchars)
+
+const char *
+strncpy_tochar(char *dest,
+              const char *src,
+              size_t max,
+              const char *stopchars)
 {
-    const char *psrc = src;
-    char *pdest = dest;
-    if (isempty(psrc)) {
-       return NULL;
-    }
-    while (*psrc && --max > 0 && !strchr(stopchars, *psrc)) {
-        *pdest = *psrc;
-        pdest++;
-        psrc++;
-    }
-    *pdest = '\0';
-    return psrc +1;
+  const char *psrc = src;
+  char *pdest = dest;
+
+  if (isempty(psrc))
+    return (NULL);
+  while (*psrc && --max > 0 && !strchr(stopchars, *psrc))
+  {
+    *pdest = *psrc;
+    pdest++;
+    psrc++;
+  }
+  *pdest = '\0';
+  return (psrc + 1);
 }
 
-size_t fwrite_or_die(const void* ptr, size_t size, size_t count, FILE* stream) {
+
+size_t
+fwrite_or_die(const void* ptr,
+             size_t size,
+             size_t count,
+             FILE* stream)
+{
   size_t res = fwrite(ptr, size, count, stream);
   if (ferror(stream))
     rip_die(EXIT_PRNERR, "Encountered error %s during fwrite", strerror(errno));
 
-  return res;
+  return (res);
 }
 
-size_t fread_or_die(void* ptr, size_t size, size_t count, FILE* stream) {
+
+size_t
+fread_or_die(void* ptr,
+            size_t size,
+            size_t count,
+            FILE* stream)
+{
   size_t res = fread(ptr, size, count, stream);
   if (ferror(stream))
     rip_die(EXIT_PRNERR, "Encountered error %s during fread", strerror(errno));
 
-  return res;
+  return (res);
 }
 
-int find_in_path(const char *progname, const char *paths, char *found_in)
+
+int
+find_in_path(const char *progname,
+            const char *paths,
+            char *found_in)
 {
-    char *pathscopy;
-    char *path;
-    char filepath[PATH_MAX];
+  char *pathscopy;
+  char *path;
+  char filepath[PATH_MAX];
 
-    if (access(progname, X_OK) == 0)
-        return 1;
+  if (access(progname, X_OK) == 0)
+    return (1);
 
-    pathscopy = strdup(paths);
-    for (path = strtok(pathscopy, ":"); path; path = strtok(NULL, ":")) {
-        strlcpy(filepath, path, PATH_MAX);
-        strlcat(filepath, "/", PATH_MAX);
-        strlcat(filepath, progname, PATH_MAX);
+  pathscopy = strdup(paths);
+  for (path = strtok(pathscopy, ":"); path; path = strtok(NULL, ":"))
+  {
+    strlcpy(filepath, path, PATH_MAX);
+    strlcat(filepath, "/", PATH_MAX);
+    strlcat(filepath, progname, PATH_MAX);
 
-        if (access(filepath, X_OK) == 0) {
-            if (found_in)
-                strlcpy(found_in, path, PATH_MAX);
-            free(pathscopy);
-            return 1;
-        }
+    if (access(filepath, X_OK) == 0)
+    {
+      if (found_in)
+       strlcpy(found_in, path, PATH_MAX);
+      free(pathscopy);
+      return (1);
     }
+  }
 
-    if (found_in)
-        found_in[0] = '\0';
-    free(pathscopy);
-    return 0;
+  if (found_in)
+    found_in[0] = '\0';
+  free(pathscopy);
+  return (0);
 }
 
-void file_basename(char *dest, const char *path, size_t dest_size)
+
+void
+file_basename(char *dest,
+             const char *path,
+             size_t dest_size)
 {
-    const char *p = strrchr(path, '/');
-    char *pdest = dest;
-    if (!pdest)
-        return;
-    if (p)
-        p += 1;
-    else
-        p = path;
-    while (*p != 0 && *p != '.' && --dest_size > 0) {
-        *pdest++ = *p++;
-    }
-    *pdest = '\0';
+  const char *p = strrchr(path, '/');
+  char *pdest = dest;
+
+  if (!pdest)
+    return;
+  if (p)
+    p += 1;
+  else
+    p = path;
+  while (*p != 0 && *p != '.' && --dest_size > 0)
+    *pdest++ = *p++;
+  *pdest = '\0';
 }
 
-void make_absolute_path(char *path, int len)
+
+void
+make_absolute_path(char *path,
+                  int len)
 {
-    char *tmp, *cwd;
+  char *tmp, *cwd;
 
-    if (path[0] != '/') {
-        tmp = malloc(len +1);
-        strlcpy(tmp, path, len);
+  if (path[0] != '/')
+  {
+    tmp = malloc(len +1);
+    strlcpy(tmp, path, len);
 
-        cwd = malloc(len);
-        if (getcwd(cwd, len) != NULL) {
-         strlcpy(path, cwd, len);
-         strlcat(path, "/", len);
-         strlcat(path, tmp, len);
-       }
-
-        free(tmp);
-        free(cwd);
+    cwd = malloc(len);
+    if (getcwd(cwd, len) != NULL)
+    {
+      strlcpy(path, cwd, len);
+      strlcat(path, "/", len);
+      strlcat(path, tmp, len);
     }
+
+    free(tmp);
+    free(cwd);
+  }
 }
 
-int is_true_string(const char *str)
+
+int
+is_true_string(const char *str)
 {
-    return str && (!strcmp(str, "1") || !strcasecmp(str, "Yes") ||
-        !strcasecmp(str, "On") || !strcasecmp(str, "True"));
+  return (str && (!strcmp(str, "1") || !strcasecmp(str, "Yes") ||
+                 !strcasecmp(str, "On") || !strcasecmp(str, "True")));
 }
 
-int is_false_string(const char *str)
+int
+is_false_string(const char *str)
 {
-    return str && (!strcmp(str, "0") || !strcasecmp(str, "No") ||
-        !strcasecmp(str, "Off") || !strcasecmp(str, "False") ||
-        !strcasecmp(str, "None"));
+  return (str && (!strcmp(str, "0") || !strcasecmp(str, "No") ||
+                 !strcasecmp(str, "Off") || !strcasecmp(str, "False") ||
+                 !strcasecmp(str, "None")));
 }
 
-int digit(char c)
+int
+digit(char c)
 {
-    if (c >= '0' && c <= '9')
-        return (int)c - (int)'0';
-    return -1;
+  if (c >= '0' && c <= '9')
+    return ((int)c - (int)'0');
+  return (-1);
 }
 
-static const char * next_token(const char *string, const char *separators)
+
+static const char *
+next_token(const char *string,
+          const char *separators)
 {
-    if (!string)
-        return NULL;
+  if (!string)
+    return (NULL);
 
-    while (*string && !strchr(separators, *string))
-        string++;
+  while (*string && !strchr(separators, *string))
+    string++;
 
-    while (*string && strchr(separators, *string))
-        string++;
+  while (*string && strchr(separators, *string))
+    string++;
 
-    return string;
+  return (string);
 }
 
-static unsigned count_separators(const char *string, const char *separators)
+
+static unsigned
+count_separators(const char *string,
+                const char *separators)
 {
-    const char *p;
-    unsigned cnt = 0;
+  const char *p;
+  unsigned cnt = 0;
 
-    if (!string)
-        return 0;
+  if (!string)
+    return (0);
 
-    for (p = string; *p; p = next_token(p, separators))
-        cnt++;
+  for (p = string; *p; p = next_token(p, separators))
+    cnt++;
 
-    return cnt;
+  return (cnt);
 }
 
-/*
- * Returns a zero terminated array of strings
- */
-char ** argv_split(const char *string, const char *separators, int *cntp)
+
+//
+// Returns a zero terminated array of strings
+//
+char **
+argv_split(const char *string,
+          const char *separators,
+          int *cntp)
 {
-    unsigned cnt;
-    int i;
-    char **argv;
+  unsigned cnt;
+  int i;
+  char **argv;
 
-    if (!string)
-        return NULL;
+  if (!string)
+    return (NULL);
 
-    if ((cnt = count_separators(string, separators)) == 0)
-        return NULL;
+  if ((cnt = count_separators(string, separators)) == 0)
+    return (NULL);
 
-    argv = malloc((cnt +1) * sizeof(char *));
-    argv[cnt] = NULL;
+  argv = malloc((cnt + 1) * sizeof(char *));
+  argv[cnt] = NULL;
 
-    for (i = 0; i < cnt; i++)
-    {
-        size_t len = strcspn(string, separators);
-       char *s;
-        s = malloc(len + 1);
-        strncpy(s, string, len);
-        s[len] = '\0';
-       argv[i] = s;
-        string = next_token(string, separators);
-    }
+  for (i = 0; i < cnt; i++)
+  {
+    size_t len = strcspn(string, separators);
+    char *s;
+    s = malloc(len + 1);
+    strncpy(s, string, len);
+    s[len] = '\0';
+    argv[i] = s;
+    string = next_token(string, separators);
+  }
 
-    if (cntp)
-        *cntp = cnt;
-    return argv;
+  if (cntp)
+    *cntp = cnt;
+  return (argv);
 }
 
-size_t argv_count(char **argv)
+
+size_t
+argv_count(char **argv)
 {
-    size_t cnt = 0;
+  size_t cnt = 0;
 
-    if (!argv)
-        return 0;
+  if (!argv)
+    return (0);
 
-    while (*argv++)
-        cnt++;
+  while (*argv++)
+    cnt++;
 
-    return cnt;
+  return (cnt);
 }
 
-void argv_free(char **argv)
+
+void
+argv_free(char **argv)
 {
-    char **p;
+  char **p;
 
-    if (!argv)
-        return;
+  if (!argv)
+    return;
 
-    for (p = argv; *p; p++)
-        free(*p);
+  for (p = argv; *p; p++)
+    free(*p);
 
-    free(argv);
+  free(argv);
 }
 
-int line_count(const char *str)
+
+int
+line_count(const char *str)
 {
-    int cnt = 0;
-    while (*str) {
-        if (*str == '\n')
-            cnt++;
-        str++;
-    }
-    return cnt;
+  int cnt = 0;
+  while (*str)
+  {
+    if (*str == '\n')
+      cnt++;
+    str++;
+  }
+  return (cnt);
 }
 
-int line_start(const char *str, int line_number)
+
+int
+line_start(const char *str,
+          int line_number)
 {
-    const char *p = str;
-    while (*p && line_number > 0) {
-        if (*p == '\n')
-            line_number--;
-        p++;
-    }
-    return p - str;
-}
-
-void unhexify(char *dest, size_t size, const char *src)
-{
-    char *pdest = dest;
-    const char *psrc = src;
-    char cstr[3];
-
-    cstr[2] = '\0';
-
-    while (*psrc && pdest - dest < size -1) {
-        if (*psrc == '<') {
-            psrc++;
-            do {
-                cstr[0] = *psrc++;
-                cstr[1] = *psrc++;
-                if (!isxdigit(cstr[0]) || !isxdigit(cstr[1])) {
-                    printf("Error replacing hex notation in %s!\n", src);
-                    break;
-                }
-                *pdest++ = (char)strtol(cstr, NULL, 16);
-            } while (*psrc != '>');
-            psrc++;
-        }
-        else
-            *pdest++ = *psrc++;
+  const char *p = str;
+  while (*p && line_number > 0)
+  {
+    if (*p == '\n')
+      line_number--;
+    p++;
+  }
+  return (p - str);
+}
+
+
+void
+unhexify(char *dest,
+        size_t size,
+        const char *src)
+{
+  char *pdest = dest;
+  const char *psrc = src;
+  char cstr[3];
+
+  cstr[2] = '\0';
+
+  while (*psrc && pdest - dest < size -1)
+  {
+    if (*psrc == '<')
+    {
+      psrc++;
+      do
+      {
+       cstr[0] = *psrc++;
+       cstr[1] = *psrc++;
+       if (!isxdigit(cstr[0]) || !isxdigit(cstr[1]))
+       {
+         printf("Error replacing hex notation in %s!\n", src);
+         break;
+       }
+       *pdest++ = (char)strtol(cstr, NULL, 16);
+      }
+      while (*psrc != '>');
+      psrc++;
     }
-    *pdest = '\0';
+    else
+      *pdest++ = *psrc++;
+  }
+  *pdest = '\0';
 }
 
-void extract_command(size_t *start, size_t *end, const char *cmdline, const char *cmd)
+
+void
+extract_command(size_t *start,
+               size_t *end,
+               const char *cmdline,
+               const char *cmd)
 {
-    char *copy = strdup(cmdline);
-    char *tok = NULL;
-    const char *delim = "|;";
+  char *copy = strdup(cmdline);
+  char *tok = NULL;
+  const char *delim = "|;";
 
-    *start = *end = 0;
-    for (tok = strtok(copy, delim); tok; tok = strtok(NULL, delim)) {
-        while (*tok && isspace(*tok))
-            tok++;
-        if (startswith(tok, cmd)) {
-            *start = tok - copy;
-            *end = tok + strlen(tok) - copy;
-            break;
-        }
+  *start = *end = 0;
+  for (tok = strtok(copy, delim); tok; tok = strtok(NULL, delim))
+  {
+    while (*tok && isspace(*tok))
+      tok++;
+    if (startswith(tok, cmd))
+    {
+      *start = tok - copy;
+      *end = tok + strlen(tok) - copy;
+      break;
     }
+  }
 
-    free(copy);
+  free(copy);
 }
 
-int contains_command(const char *cmdline, const char *cmd)
+
+int
+contains_command(const char *cmdline,
+                const char *cmd)
 {
-    size_t start = 0, end = 0;
+  size_t start = 0, end = 0;
 
-    extract_command(&start, &end, cmdline, cmd);
-    if (start == 0 && end == 0)
-        return 0;
+  extract_command(&start, &end, cmdline, cmd);
+  if (start == 0 && end == 0)
+    return (0);
 
-    return 1;
+  return (1);
 }
 
-/*
- * Dynamic strings
- */
-dstr_t * create_dstr()
+
+//
+// Dynamic strings
+//
+
+dstr_t *
+create_dstr()
 {
-    dstr_t *ds = malloc(sizeof(dstr_t));
-    ds->len = 0;
-    ds->alloc = 32;
-    ds->data = malloc(ds->alloc);
-    ds->data[0] = '\0';
-    return ds;
+  dstr_t *ds = malloc(sizeof(dstr_t));
+  ds->len = 0;
+  ds->alloc = 32;
+  ds->data = malloc(ds->alloc);
+  ds->data[0] = '\0';
+  return (ds);
 }
 
-void free_dstr(dstr_t *ds)
+
+void
+free_dstr(dstr_t *ds)
 {
-    free(ds->data);
-    free(ds);
+  free(ds->data);
+  free(ds);
 }
 
-void dstrclear(dstr_t *ds)
+
+void
+dstrclear(dstr_t *ds)
 {
-    ds->len = 0;
-    ds->data[0] = '\0';
+  ds->len = 0;
+  ds->data[0] = '\0';
 }
 
-void dstrassure(dstr_t *ds, size_t alloc)
+
+void
+dstrassure(dstr_t *ds,
+          size_t alloc)
 {
-       if (ds->alloc < alloc) {
-               ds->alloc = alloc;
-               ds->data = realloc(ds->data, ds->alloc);
-       }
+  if (ds->alloc < alloc)
+  {
+    ds->alloc = alloc;
+    ds->data = realloc(ds->data, ds->alloc);
+  }
 }
 
-void dstrcpy(dstr_t *ds, const char *src)
+
+void
+dstrcpy(dstr_t *ds,
+       const char *src)
 {
-    size_t srclen;
+  size_t srclen;
 
-    if (!src) {
-        ds->len = 0;
-        ds->data[0] = '\0';
-        return;
-    }
+  if (!src)
+  {
+    ds->len = 0;
+    ds->data[0] = '\0';
+    return;
+  }
 
-    srclen = strlen(src);
+  srclen = strlen(src);
 
-    if (srclen >= ds->alloc) {
-        do {
-            ds->alloc *= 2;
-        } while (srclen >= ds->alloc);
-        ds->data = realloc(ds->data, ds->alloc);
+  if (srclen >= ds->alloc)
+  {
+    do
+    {
+      ds->alloc *= 2;
     }
+    while (srclen >= ds->alloc);
+    ds->data = realloc(ds->data, ds->alloc);
+  }
 
-    strcpy(ds->data, src);
-    ds->len = srclen;
+  strcpy(ds->data, src);
+  ds->len = srclen;
 }
 
-void dstrncpy(dstr_t *ds, const char *src, size_t n)
+
+void
+dstrncpy(dstr_t *ds,
+        const char *src,
+        size_t n)
 {
-    if (n >= ds->alloc) {
-        do {
-            ds->alloc *= 2;
-        } while (n >= ds->alloc);
-        ds->data = realloc(ds->data, ds->alloc);
+  if (n >= ds->alloc)
+  {
+    do
+    {
+      ds->alloc *= 2;
     }
+    while (n >= ds->alloc);
+    ds->data = realloc(ds->data, ds->alloc);
+  }
 
-    strncpy(ds->data, src, n);
-    ds->len = n;
-    ds->data[ds->len] = '\0';
+  strncpy(ds->data, src, n);
+  ds->len = n;
+  ds->data[ds->len] = '\0';
 }
 
-void dstrncat(dstr_t *ds, const char *src, size_t n)
+
+void
+dstrncat(dstr_t *ds,
+        const char *src,
+        size_t n)
 {
-    size_t needed = ds->len + n;
+  size_t needed = ds->len + n;
 
-    if (needed >= ds->alloc) {
-        do {
-            ds->alloc *= 2;
-        } while (needed >= ds->alloc);
-        ds->data = realloc(ds->data, ds->alloc);
+  if (needed >= ds->alloc)
+  {
+    do
+    {
+      ds->alloc *= 2;
     }
+    while (needed >= ds->alloc);
+    ds->data = realloc(ds->data, ds->alloc);
+  }
 
-    strncpy(&ds->data[ds->len], src, n);
-    ds->len = needed;
-    ds->data[ds->len] = '\0';
+  strncpy(&ds->data[ds->len], src, n);
+  ds->len = needed;
+  ds->data[ds->len] = '\0';
 }
 
-void dstrcpyf(dstr_t *ds, const char *src, ...)
-{
-    va_list ap;
-    size_t srclen;
 
-    va_start(ap, src);
-    srclen = vsnprintf(ds->data, ds->alloc, src, ap);
-    va_end(ap);
+void
+dstrcpyf(dstr_t *ds,
+        const char *src,
+        ...)
+{
+  va_list ap;
+  size_t srclen;
 
-    if (srclen >= ds->alloc) {
-        do {
-            ds->alloc *= 2;
-        } while (srclen >= ds->alloc);
-        ds->data = realloc(ds->data, ds->alloc);
+  va_start(ap, src);
+  srclen = vsnprintf(ds->data, ds->alloc, src, ap);
+  va_end(ap);
 
-        va_start(ap, src);
-        vsnprintf(ds->data, ds->alloc, src, ap);
-        va_end(ap);
+  if (srclen >= ds->alloc)
+  {
+    do
+    {
+      ds->alloc *= 2;
     }
+    while (srclen >= ds->alloc);
+    ds->data = realloc(ds->data, ds->alloc);
+
+    va_start(ap, src);
+    vsnprintf(ds->data, ds->alloc, src, ap);
+    va_end(ap);
+  }
 
-    ds->len = srclen;
+  ds->len = srclen;
 }
 
-void dstrputc(dstr_t *ds, int c)
+
+void
+dstrputc(dstr_t *ds,
+        int c)
 {
-    if (ds->len +1 >= ds->alloc) {
-        ds->alloc *= 2;
-        ds->data = realloc(ds->data, ds->alloc);
-    }
-    ds->data[ds->len++] = c;
-    ds->data[ds->len] = '\0';
+  if (ds->len +1 >= ds->alloc)
+  {
+    ds->alloc *= 2;
+    ds->data = realloc(ds->data, ds->alloc);
+  }
+  ds->data[ds->len++] = c;
+  ds->data[ds->len] = '\0';
 }
 
-void dstrcat(dstr_t *ds, const char *src)
+
+void
+dstrcat(dstr_t *ds,
+       const char *src)
 {
-    size_t srclen = strlen(src);
-    size_t newlen = ds->len + srclen;
+  size_t srclen = strlen(src);
+  size_t newlen = ds->len + srclen;
 
-    if (newlen >= ds->alloc) {
-        do {
-            ds->alloc *= 2;
-        } while (newlen >= ds->alloc);
-        ds->data = realloc(ds->data, ds->alloc);
+  if (newlen >= ds->alloc)
+  {
+    do
+    {
+      ds->alloc *= 2;
     }
+    while (newlen >= ds->alloc);
+    ds->data = realloc(ds->data, ds->alloc);
+  }
 
-    memcpy(&ds->data[ds->len], src, srclen +1);
-    ds->len = newlen;
+  memcpy(&ds->data[ds->len], src, srclen +1);
+  ds->len = newlen;
 }
 
-void dstrcatf(dstr_t *ds, const char *src, ...)
+
+void
+dstrcatf(dstr_t *ds,
+        const char *src,
+        ...)
 {
-    va_list ap;
-    size_t restlen = ds->alloc - ds->len;
-    size_t srclen;
+  va_list ap;
+  size_t restlen = ds->alloc - ds->len;
+  size_t srclen;
+
+  va_start(ap, src);
+  srclen = vsnprintf(&ds->data[ds->len], restlen, src, ap);
+  va_end(ap);
+
+  if (srclen >= restlen)
+  {
+    do
+    {
+      ds->alloc *= 2;
+      restlen = ds->alloc - ds->len;
+    }
+    while (srclen >= restlen);
+    ds->data = realloc(ds->data, ds->alloc);
 
     va_start(ap, src);
     srclen = vsnprintf(&ds->data[ds->len], restlen, src, ap);
     va_end(ap);
+  }
 
-    if (srclen >= restlen) {
-        do {
-            ds->alloc *= 2;
-            restlen = ds->alloc - ds->len;
-        } while (srclen >= restlen);
-        ds->data = realloc(ds->data, ds->alloc);
-
-        va_start(ap, src);
-        srclen = vsnprintf(&ds->data[ds->len], restlen, src, ap);
-        va_end(ap);
-    }
-
-    ds->len += srclen;
+  ds->len += srclen;
 }
 
-size_t fgetdstr(dstr_t *ds, FILE *stream)
+
+size_t
+fgetdstr(dstr_t *ds,
+        FILE *stream)
 {
-    int c;
-    size_t cnt = 0;
+  int c;
+  size_t cnt = 0;
 
-    ds->len = 0;
-    if (ds->alloc == 0) {
-        ds->alloc = 256;
-        ds->data = malloc(ds->alloc);
-    }
+  ds->len = 0;
+  if (ds->alloc == 0)
+  {
+    ds->alloc = 256;
+    ds->data = malloc(ds->alloc);
+  }
 
-    while ((c = fgetc(stream)) != EOF) {
-        if (ds->len +1 == ds->alloc) {
-            ds->alloc *= 2;
-            ds->data = realloc(ds->data, ds->alloc);
-        }
-        ds->data[ds->len++] = (char)c;
-        cnt ++;
-        if (c == '\n')
-            break;
+  while ((c = fgetc(stream)) != EOF)
+  {
+    if (ds->len +1 == ds->alloc)
+    {
+      ds->alloc *= 2;
+      ds->data = realloc(ds->data, ds->alloc);
     }
-    ds->data[ds->len] = '\0';
-    return cnt;
+    ds->data[ds->len++] = (char)c;
+    cnt ++;
+    if (c == '\n')
+      break;
+  }
+  ds->data[ds->len] = '\0';
+  return (cnt);
 }
 
-/*
- * Replace the first occurrence of 'find' after the index 'start' with 'repl'
- * Returns the position right after the replaced string
- */
-int dstrreplace(dstr_t *ds, const char *find, const char *repl, int start)
+
+//
+// Replace the first occurrence of 'find' after the index 'start' with 'repl'
+// Returns the position right after the replaced string
+//
+
+int
+dstrreplace(dstr_t *ds,
+           const char *find,
+           const char *repl,
+           int start)
 {
-    char *p;
-    dstr_t *copy = create_dstr();
-    int end = -1;
+  char *p;
+  dstr_t *copy = create_dstr();
+  int end = -1;
 
-    dstrcpy(copy, ds->data);
+  dstrcpy(copy, ds->data);
 
-    if ((p = strstr(&copy->data[start], find)))
-    {
-        dstrncpy(ds, copy->data, p - copy->data);
-        dstrcatf(ds, "%s", repl);
-        end = ds->len;
-        dstrcatf(ds, "%s", p + strlen(find));
-    }
+  if ((p = strstr(&copy->data[start], find)))
+  {
+    dstrncpy(ds, copy->data, p - copy->data);
+    dstrcatf(ds, "%s", repl);
+    end = ds->len;
+    dstrcatf(ds, "%s", p + strlen(find));
+  }
 
-    free_dstr(copy);
-    return end;
+  free_dstr(copy);
+  return (end);
 }
 
-void dstrprepend(dstr_t *ds, const char *str)
+
+void
+dstrprepend(dstr_t *ds,
+           const char *str)
 {
-    dstr_t *copy = create_dstr();
-    dstrcpy(copy, ds->data);
-    dstrcpy(ds, str);
-    dstrcatf(ds, "%s", copy->data);
-    free_dstr(copy);
+  dstr_t *copy = create_dstr();
+  dstrcpy(copy, ds->data);
+  dstrcpy(ds, str);
+  dstrcatf(ds, "%s", copy->data);
+  free_dstr(copy);
 }
 
-void dstrinsert(dstr_t *ds, int idx, const char *str)
+
+void
+dstrinsert(dstr_t *ds,
+          int idx,
+          const char *str)
 {
-    char * copy = strdup(ds->data);
-    size_t len = strlen(str);
+  char * copy = strdup(ds->data);
+  size_t len = strlen(str);
 
-    if (idx >= ds->len)
-        idx = ds->len;
-    else if (idx < 0)
-        idx = 0;
+  if (idx >= ds->len)
+    idx = ds->len;
+  else if (idx < 0)
+    idx = 0;
 
-    if (ds->len + len >= ds->alloc) {
-        do {
-            ds->alloc *= 2;
-        } while (ds->len + len >= ds->alloc);
-        free(ds->data);
-        ds->data = malloc(ds->alloc);
+  if (ds->len + len >= ds->alloc)
+  {
+    do
+    {
+      ds->alloc *= 2;
     }
+    while (ds->len + len >= ds->alloc);
+    free(ds->data);
+    ds->data = malloc(ds->alloc);
+  }
 
-    strncpy(ds->data, copy, idx);
-    ds->data[idx] = '\0';
-    strcat(ds->data, str);
-    strcat(ds->data, &copy[idx]);
-    ds->len += len;
-    free(copy);
+  strncpy(ds->data, copy, idx);
+  ds->data[idx] = '\0';
+  strcat(ds->data, str);
+  strcat(ds->data, &copy[idx]);
+  ds->len += len;
+  free(copy);
 }
 
-void dstrinsertf(dstr_t *ds, int idx, const char *str, ...)
+
+void
+dstrinsertf(dstr_t *ds,
+           int idx,
+           const char *str,
+           ...)
 {
-    va_list ap;
-    char *strf;
-    size_t len;
+  va_list ap;
+  char *strf;
+  size_t len;
 
-    va_start(ap, str);
-    len = vsnprintf(NULL, 0, str, ap);
-    va_end(ap);
+  va_start(ap, str);
+  len = vsnprintf(NULL, 0, str, ap);
+  va_end(ap);
 
-    strf = malloc(len +1);
-    va_start(ap, str);
-    vsnprintf(strf, len +1, str, ap);
-    va_end(ap);
+  strf = malloc(len +1);
+  va_start(ap, str);
+  vsnprintf(strf, len +1, str, ap);
+  va_end(ap);
 
-    dstrinsert(ds, idx, strf);
+  dstrinsert(ds, idx, strf);
 
-    free(strf);
+  free(strf);
 }
 
-void dstrremove(dstr_t *ds, int idx, size_t count)
+
+void
+dstrremove(dstr_t *ds,
+          int idx,
+          size_t count)
 {
-    char *p1, *p2;
+  char *p1, *p2;
 
-    if (idx + count >= ds->len)
-        return;
+  if (idx + count >= ds->len)
+    return;
 
-    p1 = &ds->data[idx];
-    p2 = &ds->data[idx + count];
+  p1 = &ds->data[idx];
+  p2 = &ds->data[idx + count];
 
-    while (*p2) {
-        *p1 = *p2;
-        p1++;
-        p2++;
-    }
-    *p1 = '\0';
+  while (*p2)
+  {
+    *p1 = *p2;
+    p1++;
+    p2++;
+  }
+  *p1 = '\0';
 }
 
-static inline int isnewline(int c)
+
+static inline int
+isnewline(int c)
 {
-    return c == '\n' || c == '\r';
+  return (c == '\n' || c == '\r');
 }
 
-void dstrcatline(dstr_t *ds, const char *str)
+
+void
+dstrcatline(dstr_t *ds,
+           const char *str)
 {
-    size_t eol = strcspn(str, "\n\r");
-    if (isnewline(str[eol]))
-        eol++;
-    dstrncat(ds, str, eol);
+  size_t eol = strcspn(str, "\n\r");
+  if (isnewline(str[eol]))
+    eol++;
+  dstrncat(ds, str, eol);
 }
 
-int dstrendswith(dstr_t *ds, const char *str)
-{
-    int len = strlen(str);
-    char *pstr;
 
-    if (ds->len < len)
-        return 0;
-    pstr = &ds->data[ds->len - len];
-    return strcmp(pstr, str) == 0;
+int
+dstrendswith(dstr_t *ds,
+            const char *str)
+{
+  int len = strlen(str);
+  char *pstr;
 
+  if (ds->len < len)
+    return (0);
+  pstr = &ds->data[ds->len - len];
+  return (strcmp(pstr, str) == 0);
 }
 
-void dstrfixnewlines(dstr_t *ds)
+
+void
+dstrfixnewlines(dstr_t *ds)
 {
-    if (ds->data[ds->len -1] == '\r') {
-        ds->data[ds->len -1] = '\n';
-    }
-    else if (ds->data[ds->len -2] == '\r') {
-        ds->data[ds->len -1] = '\n';
-        ds->data[ds->len -2] = '\0';
-        ds->len -= 1;
-    }
+  if (ds->data[ds->len -1] == '\r')
+    ds->data[ds->len -1] = '\n';
+  else if (ds->data[ds->len -2] == '\r')
+  {
+    ds->data[ds->len -1] = '\n';
+    ds->data[ds->len -2] = '\0';
+    ds->len -= 1;
+  }
 }
 
-void dstrremovenewline(dstr_t *ds)
+
+void
+dstrremovenewline(dstr_t *ds)
 {
-    if (!ds->len)
-        return;
+  if (!ds->len)
+    return;
 
-    if (ds->data[ds->len -1] == '\r' || ds->data[ds->len -1] == '\n') {
-        ds->data[ds->len -1] = '\0';
-        ds->len -= 1;
-    }
+  if (ds->data[ds->len -1] == '\r' || ds->data[ds->len -1] == '\n')
+  {
+    ds->data[ds->len -1] = '\0';
+    ds->len -= 1;
+  }
 
-    if (ds->len < 2)
-        return;
+  if (ds->len < 2)
+    return;
 
-    if (ds->data[ds->len -2] == '\r') {
-        ds->data[ds->len -2] = '\0';
-        ds->len -= 2;
-    }
+  if (ds->data[ds->len -2] == '\r')
+  {
+    ds->data[ds->len -2] = '\0';
+    ds->len -= 2;
+  }
 }
 
-void dstrtrim(dstr_t *ds)
+
+void
+dstrtrim(dstr_t *ds)
 {
-    int pos = 0;
+  int pos = 0;
 
-    while (pos < ds->len && isspace(ds->data[pos]))
-        pos++;
+  while (pos < ds->len && isspace(ds->data[pos]))
+    pos++;
 
-    if (pos > 0) {
-        ds->len -= pos;
-        memmove(ds->data, &ds->data[pos], ds->len +1);
-    }
+  if (pos > 0)
+  {
+    ds->len -= pos;
+    memmove(ds->data, &ds->data[pos], ds->len +1);
+  }
 }
 
-void dstrtrim_right(dstr_t *ds)
+
+void
+dstrtrim_right(dstr_t *ds)
 {
-    if (!ds->len)
-        return;
+  if (!ds->len)
+    return;
 
-    while (isspace(ds->data[ds->len -1]))
-        ds->len -= 1;
-    ds->data[ds->len] = '\0';
+  while (isspace(ds->data[ds->len - 1]))
+    ds->len -= 1;
+  ds->data[ds->len] = '\0';
 }
 
 
+//
+//  LIST
+//
 
-/*
- *  LIST
- */
-
-list_t * list_create()
+list_t *
+list_create()
 {
-    list_t *l = malloc(sizeof(list_t));
-    l->first = NULL;
-    l->last = NULL;
-    return l;
+  list_t *l = malloc(sizeof(list_t));
+  l->first = NULL;
+  l->last = NULL;
+  return (l);
 }
 
-list_t * list_create_from_array(int count, void ** data)
+
+list_t *
+list_create_from_array(int count,
+                      void ** data)
 {
-    int i;
-    list_t *l = list_create();
+  int i;
+  list_t *l = list_create();
 
-    for (i = 0; i < count; i++)
-        list_append(l, data[i]);
+  for (i = 0; i < count; i++)
+    list_append(l, data[i]);
 
-    return l;
+  return (l);
 }
 
-void list_free(list_t *list)
+
+void
+list_free(list_t *list)
 {
-    listitem_t *i = list->first, *tmp;
-    while (i) {
-        tmp = i->next;
-        free(i);
-        i = tmp;
-    }
+  listitem_t *i = list->first, *tmp;
+  while (i)
+  {
+    tmp = i->next;
+    free(i);
+    i = tmp;
+  }
 }
 
-size_t list_item_count(list_t *list)
+
+size_t
+list_item_count(list_t *list)
 {
-    size_t cnt = 0;
-    listitem_t *i;
-    for (i = list->first; i; i = i->next)
-        cnt++;
-    return cnt;
+  size_t cnt = 0;
+  listitem_t *i;
+  for (i = list->first; i; i = i->next)
+    cnt++;
+  return (cnt);
 }
 
-list_t * list_copy(list_t *list)
+
+list_t *
+list_copy(list_t *list)
 {
-    list_t *l = list_create();
-    listitem_t *i;
+  list_t *l = list_create();
+  listitem_t *i;
 
-    for (i = list->first; i; i = i->next)
-        list_append(l, i->data);
-    return l;
+  for (i = list->first; i; i = i->next)
+    list_append(l, i->data);
+  return (l);
 }
 
-void list_prepend(list_t *list, void *data)
+
+void
+list_prepend(list_t *list,
+            void *data)
 {
-    listitem_t *item;
+  listitem_t *item;
 
-    if (!list)
-      return;
+  if (!list)
+    return;
 
-    item = malloc(sizeof(listitem_t));
-    item->data = data;
-    item->prev = NULL;
+  item = malloc(sizeof(listitem_t));
+  item->data = data;
+  item->prev = NULL;
 
-    if (list->first) {
-        item->next = list->first;
-        list->first->next = item;
-        list->first = item;
-    }
-    else {
-        item->next = NULL;
-        list->first = item;
-        list->last = item;
-    }
+  if (list->first)
+  {
+    item->next = list->first;
+    list->first->next = item;
+    list->first = item;
+  }
+  else
+  {
+    item->next = NULL;
+    list->first = item;
+    list->last = item;
+  }
 }
 
+
 void list_append(list_t *list, void *data)
 {
-    listitem_t *item;
+  listitem_t *item;
 
-    if (!list)
-      return;
+  if (!list)
+    return;
 
-    item = malloc(sizeof(listitem_t));
-    item->data = data;
-    item->next = NULL;
+  item = malloc(sizeof(listitem_t));
+  item->data = data;
+  item->next = NULL;
 
-    if (list->last) {
-        item->prev = list->last;
-        list->last->next = item;
-        list->last = item;
-    }
-    else {
-        item->prev = NULL;
-        list->first = item;
-        list->last = item;
-    }
+  if (list->last)
+  {
+    item->prev = list->last;
+    list->last->next = item;
+    list->last = item;
+  }
+  else
+  {
+    item->prev = NULL;
+    list->first = item;
+    list->last = item;
+  }
 }
 
-void list_remove(list_t *list, listitem_t *item)
+
+void
+list_remove(list_t *list,
+           listitem_t *item)
 {
-    if (!list || !item)
-      return;
+  if (!list || !item)
+    return;
 
-    if (item->prev)
-        item->prev->next = item->next;
-    if (item->next)
-        item->next->prev = item->prev;
-    if (item == list->first)
-        list->first = item->next;
-    if (item == list->last)
-        list->last = item->prev;
+  if (item->prev)
+    item->prev->next = item->next;
+  if (item->next)
+    item->next->prev = item->prev;
+  if (item == list->first)
+    list->first = item->next;
+  if (item == list->last)
+    list->last = item->prev;
 
-    free(item);
+  free(item);
 }
 
-listitem_t * list_get(list_t *list, int idx)
+
+listitem_t *
+list_get(list_t *list,
+        int idx)
 {
-    listitem_t *i;
-    for (i = list->first; i && idx; i = i->next)
-        idx--;
-    return i;
+  listitem_t *i;
+  for (i = list->first; i && idx; i = i->next)
+    idx--;
+  return (i);
 }
 
-listitem_t * arglist_find(list_t *list, const char *name)
+
+listitem_t *
+arglist_find(list_t *list,
+            const char *name)
 {
-    listitem_t *i;
-    for (i = list->first; i; i = i->next) {
-        if (!strcmp((const char*)i->data, name))
-            return i;
-    }
-    return NULL;
+  listitem_t *i;
+  for (i = list->first; i; i = i->next)
+  {
+    if (!strcmp((const char*)i->data, name))
+      return (i);
+  }
+  return (NULL);
 }
 
-listitem_t * arglist_find_prefix(list_t *list, const char *name)
+
+listitem_t *
+arglist_find_prefix(list_t *list,
+                   const char *name)
 {
-    listitem_t *i;
-    for (i = list->first; i; i= i->next) {
-        if (!prefixcmp((const char*)i->data, name))
-            return i;
-    }
-    return NULL;
+  listitem_t *i;
+  for (i = list->first; i; i= i->next)
+  {
+    if (!prefixcmp((const char*)i->data, name))
+      return (i);
+  }
+  return (NULL);
 }
 
 
-char * arglist_get_value(list_t *list, const char *name)
+char *
+arglist_get_value(list_t *list,
+                 const char *name)
 {
-    listitem_t *i;
-    char *p;
+  listitem_t *i;
+  char *p;
 
-    for (i = list->first; i; i = i->next) {
-        if (i->next && !strcmp(name, (char*)i->data))
-            return (char*)i->next->data;
-        else if (!prefixcmp((char*)i->data, name)) {
-            p = &((char*)i->data)[strlen(name)];
-            return *p == '=' ? p +1 : p;
-        }
+  for (i = list->first; i; i = i->next)
+  {
+    if (i->next && !strcmp(name, (char*)i->data))
+      return ((char*)i->next->data);
+    else if (!prefixcmp((char*)i->data, name))
+    {
+      p = &((char*)i->data)[strlen(name)];
+      return (*p == '=' ? p +1 : p);
     }
-    return NULL;
+  }
+  return (NULL);
 }
 
-char * arglist_get(list_t *list, int idx)
+
+char *
+arglist_get(list_t *list,
+           int idx)
 {
-    listitem_t *i = list_get(list, idx);
-    return i ? (char*)i->data : NULL;
+  listitem_t *i = list_get(list, idx);
+  return (i ? (char*)i->data : NULL);
 }
 
-int arglist_remove(list_t *list, const char *name)
+
+int
+arglist_remove(list_t *list,
+              const char *name)
 {
-    listitem_t *i;
-    char *i_name;
+  listitem_t *i;
+  char *i_name;
 
-    for (i = list->first; i; i = i->next) {
-        i_name = (char*)i->data;
-        if (i->next && !strcmp(name, i_name)) {
-            list_remove(list, i->next);
-            list_remove(list, i);
-            return 1;
-        }
-        else if (!prefixcmp(i_name, name)) {
-            list_remove(list, i);
-            return 1;
-        }
+  for (i = list->first; i; i = i->next)
+  {
+    i_name = (char*)i->data;
+    if (i->next && !strcmp(name, i_name))
+    {
+      list_remove(list, i->next);
+      list_remove(list, i);
+      return (1);
     }
-    return 0;
+    else if (!prefixcmp(i_name, name))
+    {
+      list_remove(list, i);
+      return (1);
+    }
+  }
+  return (0);
 }
 
-int arglist_remove_flag(list_t *list, const char *name)
+
+int
+arglist_remove_flag(list_t *list,
+                   const char *name)
 {
-    listitem_t *i = arglist_find(list, name);
-    if (i) {
-        list_remove(list, i);
-        return 1;
-    }
-    return 0;
+  listitem_t *i = arglist_find(list, name);
+
+  if (i)
+  {
+    list_remove(list, i);
+    return (1);
+  }
+  return (0);
 }
 
-int copy_file(FILE *dest,
-              FILE *src,
-              const char *alreadyread,
-              size_t alreadyread_len)
+
+int
+copy_file(FILE *dest,
+         FILE *src,
+         const char *alreadyread,
+         size_t alreadyread_len)
 {
-    char buf[8192];
-    size_t bytes;
+  char buf[8192];
+  size_t bytes;
 
-    if (alreadyread && alreadyread_len)
+  if (alreadyread && alreadyread_len)
+  {
+    if (fwrite_or_die(alreadyread, 1, alreadyread_len, dest) < alreadyread_len)
     {
-        if (fwrite_or_die(alreadyread, 1, alreadyread_len, dest) < alreadyread_len)
-        {
-            _log("Could not write to temp file\n");
-            return 0;
-        }
+      _log("Could not write to temp file\n");
+      return 0;
     }
+  }
 
-    while ((bytes = fread_or_die(buf, 1, 8192, src)))
-        fwrite_or_die(buf, 1, bytes, dest);
+  while ((bytes = fread_or_die(buf, 1, 8192, src)))
+    fwrite_or_die(buf, 1, bytes, dest);
 
-    return !ferror(src) && !ferror(dest);
+  return (!ferror(src) && !ferror(dest));
 }
-
index 8aa884e0bd6d626e73fcd298c66e783b1f56c648..5d5efbaa20ed1421a49facf368974cb04ce27279 100644 (file)
@@ -1,25 +1,26 @@
-/* util.h
- *
- * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
- * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
- *
- * This file is part of foomatic-rip.
- *
- * Foomatic-rip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Foomatic-rip is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+//
+// util.h
+//
+// Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
+// Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
+//
+// This file is part of foomatic-rip.
+//
+// Foomatic-rip is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Foomatic-rip is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
 
 #ifndef util_h
 #define util_h
@@ -47,11 +48,10 @@ const char * skip_whitespace(const char *str);
 
 void strlower(char *dest, size_t destlen, const char *src);
 
-/*
- * Like strncpy, but omits characters for which omit_func returns true
- * It also assures that dest is zero terminated.
- * Returns a pointer to the position in 'src' right after the last byte that has been copied.
- */
+// Like strncpy, but omits characters for which omit_func returns true
+// It also assures that dest is zero terminated.
+// Returns a pointer to the position in 'src' right after the last byte that
+// has been copied.
 const char * strncpy_omit(char* dest, const char* src, size_t n, int (*omit_func)(int));
 
 int omit_unprintables(int c);
@@ -61,90 +61,95 @@ int omit_whitespace(int c);
 int omit_whitespace_newline(int c);
 
 #ifndef HAVE_STRCASESTR
-/* strcasestr() is not available under Solaris */
+// strcasestr() is not available under Solaris
 char * strcasestr (const char *haystack, const char *needle);
 #endif
 
-/* TODO check for platforms which already have strlcpy and strlcat */
+// TODO check for platforms which already have strlcpy and strlcat
 
-/* Copy at most size-1 characters from src to dest
-   dest will always be \0 terminated (unless size == 0)
-   returns strlen(src) */
+// Copy at most size - 1 characters from src to dest
+// dest will always be \0 terminated (unless size == 0)
+// returns strlen(src)
 #ifndef HAVE_STRLCPY
 size_t strlcpy(char *dest, const char *src, size_t size);
-#endif /* ! HAVE_STRLCPY */
+#endif // ! HAVE_STRLCPY
 #ifndef HAVE_STRLCAT
 size_t strlcat(char *dest, const char *src, size_t size);
-#endif /* ! HAVE_STRLCAT */
+#endif // ! HAVE_STRLCAT
 
-/* Replace all occurences of each of the characters in 'chars' by 'repl' */
+// Replace all occurences of each of the characters in 'chars' by 'repl'
 void strrepl(char *str, const char *chars, char repl);
 
-/* Replace all occurences of each of the characters in 'chars' by 'repl',
-   but do not allow consecutive 'repl' chars */
+// Replace all occurences of each of the characters in 'chars' by 'repl',
+// but do not allow consecutive 'repl' chars
 void strrepl_nodups(char *str, const char *chars, char repl);
 
-/* clears 'str' with \0s */
+// clears 'str' with \0s
 void strclr(char *str);
 
-char * strnchr(const char *str, int c, size_t n);
+char *strnchr(const char *str, int c, size_t n);
 
-void escapechars(char *dest, size_t size, const char *src, const char *esc_chars);
+void escapechars(char *dest, size_t size, const char *src,
+                const char *esc_chars);
 
-/* copies characters from 'src' to 'dest', until 'src' contains a character from 'stopchars'
-   will not copy more than 'max' chars
-   dest will be zero terminated in either case
-   returns a pointer to the position right after the last byte that has been copied
-*/
-const char * strncpy_tochar(char *dest, const char *src, size_t max, const char *stopchars);
+// copies characters from 'src' to 'dest', until 'src' contains a character
+//from 'stopchars'
+// - will not copy more than 'max' chars
+// - dest will be zero terminated in either case
+// - returns a pointer to the position right after the last byte that has been
+//   copied
+const char *strncpy_tochar(char *dest, const char *src, size_t max,
+                          const char *stopchars);
 
-/* "safe" versions of standard <cstdio> fwrite and fread that will cause the
- * program to exit gracefully when a write/read fails */
+// "safe" versions of standard <cstdio> fwrite and fread that will cause the
+// program to exit gracefully when a write/read fails
 size_t fwrite_or_die(const void* ptr, size_t size, size_t count, FILE* stream);
 size_t fread_or_die(void* ptr, size_t size, size_t count, FILE* stream);
 
-/* 'paths' is a colon seperated list of paths (like $PATH) 
- * 'found_in' may be NULL if it is not needed */
+// 'paths' is a colon seperated list of paths (like $PATH)
+// 'found_in' may be NULL if it is not needed
 int find_in_path(const char *progname, const char *paths, char *found_in);
 
-/* extracts the base name of 'path', i.e. only the filename, without path or extension */
+// extracts the base name of 'path', i.e. only the filename, without path or
+// extension
 void file_basename(char *dest, const char *path, size_t dest_size);
 
-/* if 'path' is relative, prepend cwd */
+// if 'path' is relative, prepend cwd
 void make_absolute_path(char *path, int len);
 
-int is_true_string(const char *str); /* "1", "Yes", "On", "True" */
-int is_false_string(const char *str); /* "0", "No", "Off", "False", "None" */
+int is_true_string(const char *str); // "1", "Yes", "On", "True"
+int is_false_string(const char *str); // "0", "No", "Off", "False", "None"
 
-int digit(char c); /* returns 0-9 if c is a digit, otherwise -1 */
+int digit(char c); // returns 0-9 if c is a digit, otherwise -1
 
 int line_count(const char *str);
 
-/* returns the index of the beginning of the line_number'th line in str */
+// returns the index of the beginning of the line_number'th line in str
 int line_start(const char *str, int line_number);
 
-/* Replace hex notation for unprintable characters in PPD files
-   by the actual characters ex: "<0A>" --> chr(hex("0A")) */
+// Replace hex notation for unprintable characters in PPD files
+// by the actual characters ex: "<0A>" --> chr(hex("0A"))
 void unhexify(char *dest, size_t size, const char *src);
 
-void extract_command(size_t *start, size_t *end, const char *cmdline, const char *cmd);
+void extract_command(size_t *start, size_t *end, const char *cmdline,
+                    const char *cmd);
 
-char ** argv_split(const char *string, const char *separators, int *cntp);
+char **argv_split(const char *string, const char *separators, int *cntp);
 size_t argv_count(char **argv);
 void argv_free(char **argv);
 
-/*
- * Returns non-zero if 'cmdline' calls 'cmd' in some way
- */
+// Returns non-zero if 'cmdline' calls 'cmd' in some way
 int contains_command(const char *cmdline, const char *cmd);
 
-int copy_file(FILE *dest, FILE *src, const char *alreadyread, size_t alreadyread_len);
+int copy_file(FILE *dest, FILE *src, const char *alreadyread,
+             size_t alreadyread_len);
 
-/* Dynamic string */
-typedef struct dstr {
-    char *data;
-    size_t len;
-    size_t alloc;
+// Dynamic string
+typedef struct dstr
+{
+  char *data;
+  size_t len;
+  size_t alloc;
 } dstr_t;
 
 dstr_t * create_dstr();
@@ -158,13 +163,14 @@ void dstrcpyf(dstr_t *ds, const char *src, ...);
 void dstrcat(dstr_t *ds, const char *src);
 void dstrcatf(dstr_t *ds, const char *src, ...);
 void dstrputc(dstr_t *ds, int c);
-size_t fgetdstr(dstr_t *ds, FILE *stream); /* returns number of characters read */
+size_t fgetdstr(dstr_t *ds, FILE *stream); // returns number of characters read
 int dstrreplace(dstr_t *ds, const char *find, const char *repl, int start);
 void dstrprepend(dstr_t *ds, const char *str);
 void dstrinsert(dstr_t *ds, int idx, const char *str);
 void dstrinsertf(dstr_t *ds, int idx, const char *str, ...);
 void dstrremove(dstr_t *ds, int idx, size_t count);
-void dstrcatline(dstr_t *ds, const char *str); /* appends the first line from str to ds (incl. \n) */
+void dstrcatline(dstr_t *ds, const char *str);
+                            // appends the first line from str to ds (incl. \n)
 
 int dstrendswith(dstr_t *ds, const char *str);
 void dstrfixnewlines(dstr_t *ds);
@@ -172,19 +178,21 @@ void dstrremovenewline(dstr_t *ds);
 void dstrtrim(dstr_t *ds);
 void dstrtrim_right(dstr_t *ds);
 
-
-/* Doubly linked list of void pointers */
-typedef struct listitem_s {
-    void *data;
-    struct listitem_s *prev, *next;
+// Doubly linked list of void pointers
+typedef struct listitem_s
+{
+  void *data;
+  struct listitem_s *prev, *next;
 } listitem_t;
 
-typedef struct {
-    listitem_t *first, *last;
+typedef struct
+{
+  listitem_t *first, *last;
 } list_t;
 
 list_t * list_create();
-list_t * list_create_from_array(int count, void ** data); /* array values are NOT copied */
+list_t * list_create_from_array(int count, void ** data);
+                                                // array values are NOT copied
 void list_free(list_t *list);
 
 size_t list_item_count(list_t *list);
@@ -197,12 +205,11 @@ void list_remove(list_t *list, listitem_t *item);
 
 listitem_t * list_get(list_t *list, int idx);
 
+// Argument values may be seperated from their keys in the following ways:
+//  - with whitespace (i.e. it is in the next list entry)
+//  - with a '='
+//  - not at all
 
-/* Argument values may be seperated from their keys in the following ways:
-    - with whitespace (i.e. it is in the next list entry)
-    - with a '='
-    - not at all
-*/
 listitem_t * arglist_find(list_t *list, const char *name);
 listitem_t * arglist_find_prefix(list_t *list, const char *name);
 
@@ -212,5 +219,4 @@ char * arglist_get(list_t *list, int idx);
 int arglist_remove(list_t *list, const char *name);
 int arglist_remove_flag(list_t *list, const char *name);
 
-#endif
-
+#endif // !util_h