]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - filter/interpret.c
Fix source file header text duplication text duplication.
[thirdparty/cups.git] / filter / interpret.c
index 6f9c9f855512b7e9243b4614f1923bc2935476ad..031b1d5abb1706e59b99f0cf80dd9bc239f76390 100644 (file)
@@ -1,54 +1,24 @@
 /*
- * "$Id: interpret.c 6282 2007-02-14 16:33:54Z mike $"
+ * PPD command interpreter for CUPS.
  *
- *   PPD command interpreter for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2015 by Apple Inc.
+ * Copyright 1993-2007 by Easy Software Products.
  *
- *   Copyright 1993-2007 by Easy Software Products.
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at "http://www.cups.org/".
  *
- *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
- *
- *   This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- *   cupsRasterInterpretPPD() - Interpret PPD commands to create a page header.
- *   _cupsRasterExecPS()      - Execute PostScript code to initialize a page
- *                              header.
- *   cleartomark_stack()      - Clear to the last mark ([) on the stack.
- *   copy_stack()             - Copy the top N stack objects.
- *   delete_stack()           - Free memory used by a stack.
- *   index_stack()            - Copy the Nth value on the stack.
- *   new_stack()              - Create a new stack.
- *   pop_stock()              - Pop the top object off the stack.
- *   push_stack()             - Push an object on the stack.
- *   roll_stack()             - Rotate stack objects.
- *   scan_ps()                - Scan a string for the next PS object.
- *   setpagedevice()          - Simulate the PostScript setpagedevice operator.
- *   DEBUG_object()           - Print an object value.
- *   DEBUG_stack()            - Print a stack.
+ * This file is subject to the Apple OS-Developed Software exception.
  */
 
 /*
  * Include necessary headers...
  */
 
-#include <cups/string.h>
-#include "image-private.h"
-#include <stdlib.h>
+#include <cups/raster-private.h>
+#include <cups/ppd.h>
 
 
 /*
@@ -107,6 +77,8 @@ typedef struct
 static int             cleartomark_stack(_cups_ps_stack_t *st);
 static int             copy_stack(_cups_ps_stack_t *st, int count);
 static void            delete_stack(_cups_ps_stack_t *st);
+static void            error_object(_cups_ps_obj_t *obj);
+static void            error_stack(_cups_ps_stack_t *st, const char *title);
 static _cups_ps_obj_t  *index_stack(_cups_ps_stack_t *st, int n);
 static _cups_ps_stack_t        *new_stack(void);
 static _cups_ps_obj_t  *pop_stack(_cups_ps_stack_t *st);
@@ -118,39 +90,48 @@ static int         setpagedevice(_cups_ps_stack_t *st,
                                        cups_page_header2_t *h,
                                        int *preferred_bits);
 #ifdef DEBUG
-static void            DEBUG_object(_cups_ps_obj_t *obj);
-static void            DEBUG_stack(_cups_ps_stack_t *st);
+static void            DEBUG_object(const char *prefix, _cups_ps_obj_t *obj);
+static void            DEBUG_stack(const char *prefix, _cups_ps_stack_t *st);
 #endif /* DEBUG */
 
 
 /*
  * 'cupsRasterInterpretPPD()' - Interpret PPD commands to create a page header.
  *
- * This function does not mark the options in the PPD using the "num_options"
- * and "options" arguments.  Instead, mark the options prior to calling
- * cupsRasterInterpretPPD() - this allows you to do per-page options
- * without manipulating the options array.
+ * This function is used by raster image processing (RIP) filters like
+ * cgpdftoraster and imagetoraster when writing CUPS raster data for a page.
+ * It is not used by raster printer driver filters which only read CUPS
+ * raster data.
+ *
+ *
+ * @code cupsRasterInterpretPPD@ does not mark the options in the PPD using
+ * the "num_options" and "options" arguments.  Instead, mark the options with
+ * @code cupsMarkOptions@ and @code ppdMarkOption@ prior to calling it -
+ * this allows for per-page options without manipulating the options array.
  *
  * The "func" argument specifies an optional callback function that is
  * called prior to the computation of the final raster data.  The function
- * can make changes to the cups_page_header2_t data as needed to use a
+ * can make changes to the @link cups_page_header2_t@ data as needed to use a
  * supported raster format and then returns 0 on success and -1 if the
  * requested attributes cannot be supported.
  *
- * cupsRasterInterpretPPD() supports a subset of the PostScript language.
- * Currently only the [, ], <<, >>, {, }, cleartomark, copy, dup, index,
- * pop, roll, setpagedevice, and stopped operators are supported.
  *
- * @since CUPS 1.2@
+ * @code cupsRasterInterpretPPD@ supports a subset of the PostScript language.
+ * Currently only the @code [@, @code ]@, @code <<@, @code >>@, @code {@,
+ * @code }@, @code cleartomark@, @code copy@, @code dup@, @code index@,
+ * @code pop@, @code roll@, @code setpagedevice@, and @code stopped@ operators
+ * are supported.
+ *
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on failure */
 cupsRasterInterpretPPD(
-    cups_page_header2_t *h,            /* O - Page header */
+    cups_page_header2_t *h,            /* O - Page header to create */
     ppd_file_t          *ppd,          /* I - PPD file */
     int                 num_options,   /* I - Number of options */
     cups_option_t       *options,      /* I - Options */
-    cups_interpret_cb_t func)          /* I - Optional page header callback */
+    cups_interpret_cb_t func)          /* I - Optional page header callback (@code NULL@ for none) */
 {
   int          status;                 /* Cummulative status */
   char         *code;                  /* Code to run */
@@ -159,7 +140,8 @@ cupsRasterInterpretPPD(
   float                left,                   /* Left position */
                bottom,                 /* Bottom position */
                right,                  /* Right position */
-               top;                    /* Top position */
+               top,                    /* Top position */
+               temp1, temp2;           /* Temporary variables for swapping */
   int          preferred_bits;         /* Preferred bits per color */
 
 
@@ -167,8 +149,13 @@ cupsRasterInterpretPPD(
   * Range check input...
   */
 
+  _cupsRasterClearError();
+
   if (!h)
+  {
+    _cupsRasterAddError("Page header cannot be NULL!\n");
     return (-1);
+  }
 
  /*
   * Reset the page header to the defaults...
@@ -181,7 +168,7 @@ cupsRasterInterpretPPD(
   h->PageSize[1]                 = 792;
   h->HWResolution[0]             = 100;
   h->HWResolution[1]             = 100;
-  h->cupsBitsPerColor            =  1;
+  h->cupsBitsPerColor            = 1;
   h->cupsColorOrder              = CUPS_ORDER_CHUNKED;
   h->cupsColorSpace              = CUPS_CSPACE_K;
   h->cupsBorderlessScalingFactor = 1.0f;
@@ -192,7 +179,16 @@ cupsRasterInterpretPPD(
   h->cupsImagingBBox[2]          = 612.0f;
   h->cupsImagingBBox[3]          = 792.0f;
 
-  strcpy(h->cupsPageSizeName, "Letter");
+  strlcpy(h->cupsPageSizeName, "Letter", sizeof(h->cupsPageSizeName));
+
+#ifdef __APPLE__
+ /*
+  * cupsInteger0 is also used for the total page count on macOS; set an
+  * uncommon default value so we can tell if the driver is using cupsInteger0.
+  */
+
+  h->cupsInteger[0] = 0x80000000;
+#endif /* __APPLE__ */
 
  /*
   * Apply patches and options to the page header...
@@ -246,10 +242,10 @@ cupsRasterInterpretPPD(
   if ((val = cupsGetOption("cupsBorderlessScalingFactor", num_options,
                            options)) != NULL)
   {
-    float sc = atof(val);
+    double sc = atof(val);             /* Scale factor */
 
-    if (sc >= 0.9 && sc <= 1.1)
-      h->cupsBorderlessScalingFactor = sc;
+    if (sc >= 0.1 && sc <= 2.0)
+      h->cupsBorderlessScalingFactor = (float)sc;
   }
 
  /*
@@ -284,27 +280,97 @@ cupsRasterInterpretPPD(
     top    = 792.0f;
   }
 
-  h->PageSize[0]           = h->cupsPageSize[0] *
-                             h->cupsBorderlessScalingFactor;
-  h->PageSize[1]           = h->cupsPageSize[1] *
-                             h->cupsBorderlessScalingFactor;
-  h->Margins[0]            = left * h->cupsBorderlessScalingFactor;
-  h->Margins[1]            = bottom * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[0] = left * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[1] = bottom * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[2] = right * h->cupsBorderlessScalingFactor;
-  h->ImagingBoundingBox[3] = top * h->cupsBorderlessScalingFactor;
-  h->cupsImagingBBox[0]    = left;
-  h->cupsImagingBBox[1]    = bottom;
-  h->cupsImagingBBox[2]    = right;
-  h->cupsImagingBBox[3]    = top;
+ /*
+  * Handle orientation...
+  */
+
+  switch (h->Orientation)
+  {
+    case CUPS_ORIENT_0 :
+    default :
+        /* Do nothing */
+        break;
+
+    case CUPS_ORIENT_90 :
+        temp1              = h->cupsPageSize[0];
+        h->cupsPageSize[0] = h->cupsPageSize[1];
+        h->cupsPageSize[1] = temp1;
+
+        temp1  = left;
+        temp2  = right;
+        left   = h->cupsPageSize[0] - top;
+        right  = h->cupsPageSize[0] - bottom;
+        bottom = h->cupsPageSize[1] - temp1;
+        top    = h->cupsPageSize[1] - temp2;
+        break;
+
+    case CUPS_ORIENT_180 :
+        temp1  = left;
+        temp2  = bottom;
+        left   = h->cupsPageSize[0] - right;
+        right  = h->cupsPageSize[0] - temp1;
+        bottom = h->cupsPageSize[1] - top;
+        top    = h->cupsPageSize[1] - temp2;
+        break;
+
+    case CUPS_ORIENT_270 :
+        temp1              = h->cupsPageSize[0];
+        h->cupsPageSize[0] = h->cupsPageSize[1];
+        h->cupsPageSize[1] = temp1;
+
+        temp1  = left;
+        temp2  = right;
+        left   = bottom;
+        right  = top;
+        bottom = h->cupsPageSize[1] - temp2;
+        top    = h->cupsPageSize[1] - temp1;
+        break;
+  }
+
+  if (left > right)
+  {
+    temp1 = left;
+    left  = right;
+    right = temp1;
+  }
+
+  if (bottom > top)
+  {
+    temp1  = bottom;
+    bottom = top;
+    top    = temp1;
+  }
+
+  h->PageSize[0]           = (unsigned)(h->cupsPageSize[0] *
+                                        h->cupsBorderlessScalingFactor);
+  h->PageSize[1]           = (unsigned)(h->cupsPageSize[1] *
+                                        h->cupsBorderlessScalingFactor);
+  h->Margins[0]            = (unsigned)(left *
+                                        h->cupsBorderlessScalingFactor);
+  h->Margins[1]            = (unsigned)(bottom *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[0] = (unsigned)(left *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[1] = (unsigned)(bottom *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[2] = (unsigned)(right *
+                                        h->cupsBorderlessScalingFactor);
+  h->ImagingBoundingBox[3] = (unsigned)(top *
+                                        h->cupsBorderlessScalingFactor);
+  h->cupsImagingBBox[0]    = (float)left;
+  h->cupsImagingBBox[1]    = (float)bottom;
+  h->cupsImagingBBox[2]    = (float)right;
+  h->cupsImagingBBox[3]    = (float)top;
 
  /*
   * Use the callback to validate the page header...
   */
 
   if (func && (*func)(h, preferred_bits))
+  {
+    _cupsRasterAddError("Page header callback returned error.\n");
     return (-1);
+  }
 
  /*
   * Check parameters...
@@ -315,17 +381,20 @@ cupsRasterInterpretPPD(
       (h->cupsBitsPerColor != 1 && h->cupsBitsPerColor != 2 &&
        h->cupsBitsPerColor != 4 && h->cupsBitsPerColor != 8 &&
        h->cupsBitsPerColor != 16) ||
-      h->cupsBorderlessScalingFactor < 0.5 ||
+      h->cupsBorderlessScalingFactor < 0.1 ||
       h->cupsBorderlessScalingFactor > 2.0)
+  {
+    _cupsRasterAddError("Page header uses unsupported values.\n");
     return (-1);
+  }
 
  /*
   * Compute the bitmap parameters...
   */
 
-  h->cupsWidth  = (int)((right - left) * h->cupsBorderlessScalingFactor *
+  h->cupsWidth  = (unsigned)((right - left) * h->cupsBorderlessScalingFactor *
                         h->HWResolution[0] / 72.0f + 0.5f);
-  h->cupsHeight = (int)((top - bottom) * h->cupsBorderlessScalingFactor *
+  h->cupsHeight = (unsigned)((top - bottom) * h->cupsBorderlessScalingFactor *
                         h->HWResolution[1] / 72.0f + 0.5f);
 
   switch (h->cupsColorSpace)
@@ -335,6 +404,7 @@ cupsRasterInterpretPPD(
     case CUPS_CSPACE_WHITE :
     case CUPS_CSPACE_GOLD :
     case CUPS_CSPACE_SILVER :
+    case CUPS_CSPACE_SW :
         h->cupsNumColors    = 1;
         h->cupsBitsPerPixel = h->cupsBitsPerColor;
        break;
@@ -396,6 +466,29 @@ cupsRasterInterpretPPD(
 
         h->cupsNumColors = 4;
        break;
+
+    case CUPS_CSPACE_DEVICE1 :
+    case CUPS_CSPACE_DEVICE2 :
+    case CUPS_CSPACE_DEVICE3 :
+    case CUPS_CSPACE_DEVICE4 :
+    case CUPS_CSPACE_DEVICE5 :
+    case CUPS_CSPACE_DEVICE6 :
+    case CUPS_CSPACE_DEVICE7 :
+    case CUPS_CSPACE_DEVICE8 :
+    case CUPS_CSPACE_DEVICE9 :
+    case CUPS_CSPACE_DEVICEA :
+    case CUPS_CSPACE_DEVICEB :
+    case CUPS_CSPACE_DEVICEC :
+    case CUPS_CSPACE_DEVICED :
+    case CUPS_CSPACE_DEVICEE :
+    case CUPS_CSPACE_DEVICEF :
+        h->cupsNumColors = h->cupsColorSpace - CUPS_CSPACE_DEVICE1 + 1;
+
+        if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
+          h->cupsBitsPerPixel = h->cupsBitsPerColor * h->cupsNumColors;
+       else
+         h->cupsBitsPerPixel = h->cupsBitsPerColor;
+       break;
   }
 
   h->cupsBytesPerLine = (h->cupsBitsPerPixel * h->cupsWidth + 7) / 8;
@@ -417,6 +510,7 @@ _cupsRasterExecPS(
     int                 *preferred_bits,/* O - Preferred bits per color */
     const char          *code)         /* I - PS code to execute */
 {
+  int                  error = 0;      /* Error condition? */
   _cups_ps_stack_t     *st;            /* PostScript value stack */
   _cups_ps_obj_t       *obj;           /* Object from top of stack */
   char                 *codecopy,      /* Copy of code */
@@ -424,17 +518,21 @@ _cupsRasterExecPS(
 
 
   DEBUG_printf(("_cupsRasterExecPS(h=%p, preferred_bits=%p, code=\"%s\")\n",
-                h, preferred_bits, code ? code : "(null)"));
+                h, preferred_bits, code));
 
  /*
   * Copy the PostScript code and create a stack...
   */
 
   if ((codecopy = strdup(code)) == NULL)
+  {
+    _cupsRasterAddError("Unable to duplicate code string.\n");
     return (-1);
+  }
 
   if ((st = new_stack()) == NULL)
   {
+    _cupsRasterAddError("Unable to create stack.\n");
     free(codecopy);
     return (-1);
   }
@@ -448,9 +546,8 @@ _cupsRasterExecPS(
   while ((obj = scan_ps(st, &codeptr)) != NULL)
   {
 #ifdef DEBUG
-    printf("    (%d): ", st->num_objs);
-    DEBUG_object(obj);
-    putchar('\n');
+    DEBUG_printf(("_cupsRasterExecPS: Stack (%d objects)", st->num_objs));
+    DEBUG_object("_cupsRasterExecPS", obj);
 #endif /* DEBUG */
 
     switch (obj->type)
@@ -462,11 +559,12 @@ _cupsRasterExecPS(
       case CUPS_PS_CLEARTOMARK :
           pop_stack(st);
 
-         cleartomark_stack(st);
+         if (cleartomark_stack(st))
+           _cupsRasterAddError("cleartomark: Stack underflow.\n");
 
 #ifdef DEBUG
-          fputs("    dup: ", stdout);
-         DEBUG_stack(st);
+          DEBUG_puts("1_cupsRasterExecPS:    dup");
+         DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
           break;
 
@@ -477,8 +575,8 @@ _cupsRasterExecPS(
            copy_stack(st, (int)obj->value.number);
 
 #ifdef DEBUG
-            fputs("    copy: ", stdout);
-           DEBUG_stack(st);
+            DEBUG_puts("_cupsRasterExecPS: copy");
+           DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
           }
           break;
@@ -488,8 +586,8 @@ _cupsRasterExecPS(
          copy_stack(st, 1);
 
 #ifdef DEBUG
-          fputs("    dup: ", stdout);
-         DEBUG_stack(st);
+          DEBUG_puts("_cupsRasterExecPS: dup");
+         DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
           break;
 
@@ -500,8 +598,8 @@ _cupsRasterExecPS(
            index_stack(st, (int)obj->value.number);
 
 #ifdef DEBUG
-            fputs("    index: ", stdout);
-           DEBUG_stack(st);
+            DEBUG_puts("_cupsRasterExecPS: index");
+           DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
           }
           break;
@@ -511,8 +609,8 @@ _cupsRasterExecPS(
           pop_stack(st);
 
 #ifdef DEBUG
-          fputs("    pop: ", stdout);
-         DEBUG_stack(st);
+          DEBUG_puts("_cupsRasterExecPS: pop");
+         DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
           break;
 
@@ -530,8 +628,8 @@ _cupsRasterExecPS(
              roll_stack(st, (int)obj->value.number, c);
 
 #ifdef DEBUG
-              fputs("    roll:", stdout);
-             DEBUG_stack(st);
+              DEBUG_puts("_cupsRasterExecPS: roll");
+             DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
             }
          }
@@ -542,8 +640,8 @@ _cupsRasterExecPS(
          setpagedevice(st, h, preferred_bits);
 
 #ifdef DEBUG
-          fputs("    setpagedevice: ", stdout);
-         DEBUG_stack(st);
+          DEBUG_puts("_cupsRasterExecPS: setpagedevice");
+         DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
           break;
 
@@ -554,11 +652,13 @@ _cupsRasterExecPS(
          break;
 
       case CUPS_PS_OTHER :
-          DEBUG_printf(("    Unknown operator \"%s\"!\n", obj->value.other));
+          _cupsRasterAddError("Unknown operator \"%s\".\n", obj->value.other);
+         error = 1;
+          DEBUG_printf(("_cupsRasterExecPS: Unknown operator \"%s\".", obj->value.other));
           break;
     }
 
-    if (obj->type == CUPS_PS_OTHER)
+    if (error)
       break;
   }
 
@@ -570,9 +670,11 @@ _cupsRasterExecPS(
 
   if (st->num_objs > 0)
   {
+    error_stack(st, "Stack not empty:");
+
 #ifdef DEBUG
-    fputs("    Stack not empty:", stdout);
-    DEBUG_stack(st);
+    DEBUG_puts("_cupsRasterExecPS: Stack not empty");
+    DEBUG_stack("_cupsRasterExecPS", st);
 #endif /* DEBUG */
 
     delete_stack(st);
@@ -652,6 +754,122 @@ delete_stack(_cups_ps_stack_t *st)        /* I - Stack */
 }
 
 
+/*
+ * 'error_object()' - Add an object's value to the current error message.
+ */
+
+static void
+error_object(_cups_ps_obj_t *obj)      /* I - Object to add */
+{
+  switch (obj->type)
+  {
+    case CUPS_PS_NAME :
+       _cupsRasterAddError(" /%s", obj->value.name);
+       break;
+
+    case CUPS_PS_NUMBER :
+       _cupsRasterAddError(" %g", obj->value.number);
+       break;
+
+    case CUPS_PS_STRING :
+       _cupsRasterAddError(" (%s)", obj->value.string);
+       break;
+
+    case CUPS_PS_BOOLEAN :
+       if (obj->value.boolean)
+         _cupsRasterAddError(" true");
+       else
+         _cupsRasterAddError(" false");
+       break;
+
+    case CUPS_PS_NULL :
+       _cupsRasterAddError(" null");
+       break;
+
+    case CUPS_PS_START_ARRAY :
+       _cupsRasterAddError(" [");
+       break;
+
+    case CUPS_PS_END_ARRAY :
+       _cupsRasterAddError(" ]");
+       break;
+
+    case CUPS_PS_START_DICT :
+       _cupsRasterAddError(" <<");
+       break;
+
+    case CUPS_PS_END_DICT :
+       _cupsRasterAddError(" >>");
+       break;
+
+    case CUPS_PS_START_PROC :
+       _cupsRasterAddError(" {");
+       break;
+
+    case CUPS_PS_END_PROC :
+       _cupsRasterAddError(" }");
+       break;
+
+    case CUPS_PS_COPY :
+       _cupsRasterAddError(" --copy--");
+        break;
+
+    case CUPS_PS_CLEARTOMARK :
+       _cupsRasterAddError(" --cleartomark--");
+        break;
+
+    case CUPS_PS_DUP :
+       _cupsRasterAddError(" --dup--");
+        break;
+
+    case CUPS_PS_INDEX :
+       _cupsRasterAddError(" --index--");
+        break;
+
+    case CUPS_PS_POP :
+       _cupsRasterAddError(" --pop--");
+        break;
+
+    case CUPS_PS_ROLL :
+       _cupsRasterAddError(" --roll--");
+        break;
+
+    case CUPS_PS_SETPAGEDEVICE :
+       _cupsRasterAddError(" --setpagedevice--");
+        break;
+
+    case CUPS_PS_STOPPED :
+       _cupsRasterAddError(" --stopped--");
+        break;
+
+    case CUPS_PS_OTHER :
+       _cupsRasterAddError(" --%s--", obj->value.other);
+       break;
+  }
+}
+
+
+/*
+ * 'error_stack()' - Add a stack to the current error message...
+ */
+
+static void
+error_stack(_cups_ps_stack_t *st,      /* I - Stack */
+            const char       *title)   /* I - Title string */
+{
+  int                  c;              /* Looping var */
+  _cups_ps_obj_t       *obj;           /* Current object on stack */
+
+
+  _cupsRasterAddError("%s", title);
+
+  for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
+    error_object(obj);
+
+  _cupsRasterAddError("\n");
+}
+
+
 /*
  * 'index_stack()' - Copy the Nth value on the stack.
  */
@@ -727,7 +945,7 @@ push_stack(_cups_ps_stack_t *st,    /* I - Stack */
 
     st->alloc_objs += 32;
 
-    if ((temp = realloc(st->objs, st->alloc_objs *
+    if ((temp = realloc(st->objs, (size_t)st->alloc_objs *
                                   sizeof(_cups_ps_obj_t))) == NULL)
       return (NULL);
 
@@ -757,7 +975,7 @@ roll_stack(_cups_ps_stack_t *st,    /* I - Stack */
   int                  n;              /* Index into array */
 
 
-  DEBUG_printf(("    roll_stack(st=%p, s=%d, c=%d)\n", st, s, c));
+  DEBUG_printf(("3roll_stack(st=%p, s=%d, c=%d)", st, s, c));
 
  /*
   * Range check input...
@@ -788,12 +1006,12 @@ roll_stack(_cups_ps_stack_t *st, /* I - Stack */
 
     s = -s;
 
-    if ((temp = calloc(s, sizeof(_cups_ps_obj_t))) == NULL)
+    if ((temp = calloc((size_t)s, sizeof(_cups_ps_obj_t))) == NULL)
       return (-1);
 
-    memcpy(temp, st->objs + n, s * sizeof(_cups_ps_obj_t));
-    memmove(st->objs + n, st->objs + n + s, (c - s) * sizeof(_cups_ps_obj_t));
-    memcpy(st->objs + n + c - s, temp, s * sizeof(_cups_ps_obj_t));
+    memcpy(temp, st->objs + n, (size_t)s * sizeof(_cups_ps_obj_t));
+    memmove(st->objs + n, st->objs + n + s, (size_t)(c - s) * sizeof(_cups_ps_obj_t));
+    memcpy(st->objs + n + c - s, temp, (size_t)s * sizeof(_cups_ps_obj_t));
   }
   else
   {
@@ -801,13 +1019,12 @@ roll_stack(_cups_ps_stack_t *st, /* I - Stack */
     * Shift up...
     */
 
-    if ((temp = calloc(s, sizeof(_cups_ps_obj_t))) == NULL)
+    if ((temp = calloc((size_t)s, sizeof(_cups_ps_obj_t))) == NULL)
       return (-1);
 
-    memcpy(temp, st->objs + n + c - s, s * sizeof(_cups_ps_obj_t));
-    memmove(st->objs + n + s, st->objs + n,
-            (c - s) * sizeof(_cups_ps_obj_t));
-    memcpy(st->objs + n, temp, s * sizeof(_cups_ps_obj_t));
+    memcpy(temp, st->objs + n + c - s, (size_t)s * sizeof(_cups_ps_obj_t));
+    memmove(st->objs + n + s, st->objs + n, (size_t)(c - s) * sizeof(_cups_ps_obj_t));
+    memcpy(st->objs + n, temp, (size_t)s * sizeof(_cups_ps_obj_t));
   }
 
   free(temp);
@@ -845,6 +1062,9 @@ scan_ps(_cups_ps_stack_t *st,              /* I  - Stack */
       */
 
       for (cur ++; *cur && *cur != '\n' && *cur != '\r'; cur ++);
+
+      if (!*cur)
+        cur --;
     }
     else if (!isspace(*cur & 255))
       break;
@@ -923,7 +1143,7 @@ scan_ps(_cups_ps_stack_t *st,              /* I  - Stack */
                ch = (ch << 3) + *cur - '0';
              }
 
-             *valptr++ = ch;
+             *valptr++ = (char)ch;
            }
            else if (*cur == '\r')
            {
@@ -1000,7 +1220,7 @@ scan_ps(_cups_ps_stack_t *st,             /* I  - Stack */
                ch |= tolower(*cur) - 'a' + 10;
             }
 
-           *valptr++ = ch;
+           *valptr++ = (char)ch;
           }
 
           if (*cur != '>')
@@ -1207,13 +1427,13 @@ setpagedevice(
   * Found the start of the dictionary, empty the stack to this point...
   */
 
-  st->num_objs = obj - st->objs;
+  st->num_objs = (int)(obj - st->objs);
 
  /*
   * Now pull /name and value pairs from the dictionary...
   */
 
-  DEBUG_puts("    Dictionary:");
+  DEBUG_puts("3setpagedevice: Dictionary:");
 
   for (obj ++; obj < end; obj ++)
   {
@@ -1228,9 +1448,8 @@ setpagedevice(
     obj ++;
 
 #ifdef DEBUG
-    printf("        /%s ", name);
-    DEBUG_object(obj);
-    putchar('\n');
+    DEBUG_printf(("4setpagedevice: /%s ", name));
+    DEBUG_object("setpagedevice", obj);
 #endif /* DEBUG */
 
    /*
@@ -1275,9 +1494,19 @@ setpagedevice(
       h->LeadingEdge = (unsigned)obj->value.number;
     else if (!strcmp(name, "ManualFeed") && obj->type == CUPS_PS_BOOLEAN)
       h->ManualFeed = (unsigned)obj->value.boolean;
-    else if ((!strcmp(name, "cupsMediaPosition") || /* Compatibility */
+    else if ((!strcmp(name, "cupsMediaPosition") ||
               !strcmp(name, "MediaPosition")) && obj->type == CUPS_PS_NUMBER)
+    {
+     /*
+      * cupsMediaPosition is supported for backwards compatibility only.
+      * We added it back in the Ghostscript 5.50 days to work around a
+      * bug in Ghostscript WRT handling of MediaPosition and setpagedevice.
+      *
+      * All new development should set MediaPosition...
+      */
+
       h->MediaPosition = (unsigned)obj->value.number;
+    }
     else if (!strcmp(name, "MediaWeight") && obj->type == CUPS_PS_NUMBER)
       h->MediaWeight = (unsigned)obj->value.number;
     else if (!strcmp(name, "MirrorPrint") && obj->type == CUPS_PS_BOOLEAN)
@@ -1295,8 +1524,8 @@ setpagedevice(
       if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
           obj[3].type == CUPS_PS_END_ARRAY)
       {
-        h->cupsPageSize[0] = obj[1].value.number;
-       h->cupsPageSize[1] = obj[2].value.number;
+        h->cupsPageSize[0] = (float)obj[1].value.number;
+       h->cupsPageSize[1] = (float)obj[2].value.number;
 
         h->PageSize[0] = (unsigned)obj[1].value.number;
        h->PageSize[1] = (unsigned)obj[2].value.number;
@@ -1333,7 +1562,7 @@ setpagedevice(
       h->cupsRowStep = (unsigned)obj->value.number;
     else if (!strcmp(name, "cupsBorderlessScalingFactor") &&
              obj->type == CUPS_PS_NUMBER)
-      h->cupsBorderlessScalingFactor = obj->value.number;
+      h->cupsBorderlessScalingFactor = (float)obj->value.number;
     else if (!strncmp(name, "cupsInteger", 11) && obj->type == CUPS_PS_NUMBER)
     {
       if ((i = atoi(name + 11)) < 0 || i > 15)
@@ -1346,7 +1575,7 @@ setpagedevice(
       if ((i = atoi(name + 8)) < 0 || i > 15)
         return (-1);
 
-      h->cupsReal[i] = obj->value.number;
+      h->cupsReal[i] = (float)obj->value.number;
     }
     else if (!strncmp(name, "cupsString", 10) && obj->type == CUPS_PS_STRING)
     {
@@ -1370,7 +1599,7 @@ setpagedevice(
       * Ignore unknown name+value...
       */
 
-      DEBUG_printf(("    Unknown name (\"%s\") or value...\n", name));
+      DEBUG_printf(("4setpagedevice: Unknown name (\"%s\") or value...\n", name));
 
       while (obj[1].type != CUPS_PS_NAME && obj < end)
         obj ++;
@@ -1387,91 +1616,92 @@ setpagedevice(
  */
 
 static void
-DEBUG_object(_cups_ps_obj_t *obj)      /* I - Object to print */
+DEBUG_object(const char *prefix,       /* I - Prefix string */
+             _cups_ps_obj_t *obj)      /* I - Object to print */
 {
   switch (obj->type)
   {
     case CUPS_PS_NAME :
-       printf("/%s", obj->value.name);
+       DEBUG_printf(("4%s: /%s\n", prefix, obj->value.name));
        break;
 
     case CUPS_PS_NUMBER :
-       printf("%g", obj->value.number);
+       DEBUG_printf(("4%s: %g\n", prefix, obj->value.number));
        break;
 
     case CUPS_PS_STRING :
-       printf("(%s)", obj->value.string);
+       DEBUG_printf(("4%s: (%s)\n", prefix, obj->value.string));
        break;
 
     case CUPS_PS_BOOLEAN :
        if (obj->value.boolean)
-         fputs("true", stdout);
+         DEBUG_printf(("4%s: true", prefix));
        else
-         fputs("false", stdout);
+         DEBUG_printf(("4%s: false", prefix));
        break;
 
     case CUPS_PS_NULL :
-       fputs("null", stdout);
+       DEBUG_printf(("4%s: null", prefix));
        break;
 
     case CUPS_PS_START_ARRAY :
-       fputs("[", stdout);
+       DEBUG_printf(("4%s: [", prefix));
        break;
 
     case CUPS_PS_END_ARRAY :
-       fputs("]", stdout);
+       DEBUG_printf(("4%s: ]", prefix));
        break;
 
     case CUPS_PS_START_DICT :
-       fputs("<<", stdout);
+       DEBUG_printf(("4%s: <<", prefix));
        break;
 
     case CUPS_PS_END_DICT :
-       fputs(">>", stdout);
+       DEBUG_printf(("4%s: >>", prefix));
        break;
 
     case CUPS_PS_START_PROC :
-       fputs("{", stdout);
+       DEBUG_printf(("4%s: {", prefix));
        break;
 
     case CUPS_PS_END_PROC :
-       fputs("}", stdout);
+       DEBUG_printf(("4%s: }", prefix));
        break;
 
     case CUPS_PS_CLEARTOMARK :
-       fputs("--cleartomark--", stdout);
+       DEBUG_printf(("4%s: --cleartomark--", prefix));
         break;
 
     case CUPS_PS_COPY :
-       fputs("--copy--", stdout);
+       DEBUG_printf(("4%s: --copy--", prefix));
         break;
 
     case CUPS_PS_DUP :
-       fputs("--dup--", stdout);
+       DEBUG_printf(("4%s: --dup--", prefix));
         break;
 
     case CUPS_PS_INDEX :
-       fputs("--index--", stdout);
+       DEBUG_printf(("4%s: --index--", prefix));
         break;
 
     case CUPS_PS_POP :
-       fputs("--pop--", stdout);
+       DEBUG_printf(("4%s: --pop--", prefix));
         break;
 
     case CUPS_PS_ROLL :
-       fputs("--roll--", stdout);
+       DEBUG_printf(("4%s: --roll--", prefix));
         break;
 
     case CUPS_PS_SETPAGEDEVICE :
-       fputs("--setpagedevice--", stdout);
+       DEBUG_printf(("4%s: --setpagedevice--", prefix));
         break;
 
     case CUPS_PS_STOPPED :
-       fputs("--stopped--", stdout);
+       DEBUG_printf(("4%s: --stopped--", prefix));
         break;
 
     case CUPS_PS_OTHER :
-       printf("--%s--", obj->value.other);
+       DEBUG_printf(("4%s: --%s--", prefix, obj->value.other));
        break;
   }
 }
@@ -1482,23 +1712,14 @@ DEBUG_object(_cups_ps_obj_t *obj)       /* I - Object to print */
  */
 
 static void
-DEBUG_stack(_cups_ps_stack_t *st)      /* I - Stack */
+DEBUG_stack(const char       *prefix,  /* I - Prefix string */
+            _cups_ps_stack_t *st)      /* I - Stack */
 {
   int                  c;              /* Looping var */
   _cups_ps_obj_t       *obj;           /* Current object on stack */
 
 
   for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
-  {
-    putchar(' ');
-    DEBUG_object(obj);
-  }
-
-  putchar('\n');
+    DEBUG_object(prefix, obj);
 }
 #endif /* DEBUG */
-
-
-/*
- * End of "$Id: interpret.c 6282 2007-02-14 16:33:54Z mike $".
- */