#include <cups/raster-private.h>
#include <cups/ppd.h>
typedef enum
{
CUPS_PS_NAME,
CUPS_PS_NUMBER,
CUPS_PS_STRING,
CUPS_PS_BOOLEAN,
CUPS_PS_NULL,
CUPS_PS_START_ARRAY,
CUPS_PS_END_ARRAY,
CUPS_PS_START_DICT,
CUPS_PS_END_DICT,
CUPS_PS_START_PROC,
CUPS_PS_END_PROC,
CUPS_PS_CLEARTOMARK,
CUPS_PS_COPY,
CUPS_PS_DUP,
CUPS_PS_INDEX,
CUPS_PS_POP,
CUPS_PS_ROLL,
CUPS_PS_SETPAGEDEVICE,
CUPS_PS_STOPPED,
CUPS_PS_OTHER
} _cups_ps_type_t;
typedef struct
{
_cups_ps_type_t type;
union
{
int boolean;
char name[64];
double number;
char other[64];
char string[64];
} value;
} _cups_ps_obj_t;
typedef struct
{
int num_objs,
alloc_objs;
_cups_ps_obj_t *objs;
} _cups_ps_stack_t;
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);
static _cups_ps_obj_t *push_stack(_cups_ps_stack_t *st,
_cups_ps_obj_t *obj);
static int roll_stack(_cups_ps_stack_t *st, int c, int s);
static _cups_ps_obj_t *scan_ps(_cups_ps_stack_t *st, char **ptr);
static int setpagedevice(_cups_ps_stack_t *st,
cups_page_header2_t *h,
int *preferred_bits);
#ifdef DEBUG
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
int
cupsRasterInterpretPPD(
cups_page_header2_t *h,
ppd_file_t *ppd,
int num_options,
cups_option_t *options,
cups_interpret_cb_t func)
{
int status;
char *code;
const char *val;
ppd_size_t *size;
float left,
bottom,
right,
top,
temp1, temp2;
int preferred_bits;
_cupsRasterClearError();
if (!h)
{
_cupsRasterAddError("Page header cannot be NULL!\n");
return (-1);
}
memset(h, 0, sizeof(cups_page_header2_t));
h->NumCopies = 1;
h->PageSize[0] = 612;
h->PageSize[1] = 792;
h->HWResolution[0] = 100;
h->HWResolution[1] = 100;
h->cupsBitsPerColor = 1;
h->cupsColorOrder = CUPS_ORDER_CHUNKED;
h->cupsColorSpace = CUPS_CSPACE_K;
h->cupsBorderlessScalingFactor = 1.0f;
h->cupsPageSize[0] = 612.0f;
h->cupsPageSize[1] = 792.0f;
h->cupsImagingBBox[0] = 0.0f;
h->cupsImagingBBox[1] = 0.0f;
h->cupsImagingBBox[2] = 612.0f;
h->cupsImagingBBox[3] = 792.0f;
strlcpy(h->cupsPageSizeName, "Letter", sizeof(h->cupsPageSizeName));
#ifdef __APPLE__
h->cupsInteger[0] = 0x80000000;
#endif
status = 0;
preferred_bits = 0;
if (ppd)
{
if (ppd->patches)
status |= _cupsRasterExecPS(h, &preferred_bits, ppd->patches);
if ((code = ppdEmitString(ppd, PPD_ORDER_DOCUMENT, 0.0)) != NULL)
{
status |= _cupsRasterExecPS(h, &preferred_bits, code);
free(code);
}
if ((code = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL)
{
status |= _cupsRasterExecPS(h, &preferred_bits, code);
free(code);
}
if ((code = ppdEmitString(ppd, PPD_ORDER_PROLOG, 0.0)) != NULL)
{
status |= _cupsRasterExecPS(h, &preferred_bits, code);
free(code);
}
if ((code = ppdEmitString(ppd, PPD_ORDER_PAGE, 0.0)) != NULL)
{
status |= _cupsRasterExecPS(h, &preferred_bits, code);
free(code);
}
}
if ((val = cupsGetOption("cupsBorderlessScalingFactor", num_options,
options)) != NULL)
{
double sc = atof(val);
if (sc >= 0.1 && sc <= 2.0)
h->cupsBorderlessScalingFactor = (float)sc;
}
if ((size = ppdPageSize(ppd, NULL)) != NULL)
{
left = size->left;
bottom = size->bottom;
right = size->right;
top = size->top;
strlcpy(h->cupsPageSizeName, size->name, sizeof(h->cupsPageSizeName));
h->cupsPageSize[0] = size->width;
h->cupsPageSize[1] = size->length;
}
else
{
left = 0.0f;
bottom = 0.0f;
right = 612.0f;
top = 792.0f;
}
switch (h->Orientation)
{
case CUPS_ORIENT_0 :
default :
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;
if (func && (*func)(h, preferred_bits))
{
_cupsRasterAddError("Page header callback returned error.\n");
return (-1);
}
if (!h->HWResolution[0] || !h->HWResolution[1] ||
!h->PageSize[0] || !h->PageSize[1] ||
(h->cupsBitsPerColor != 1 && h->cupsBitsPerColor != 2 &&
h->cupsBitsPerColor != 4 && h->cupsBitsPerColor != 8 &&
h->cupsBitsPerColor != 16) ||
h->cupsBorderlessScalingFactor < 0.1 ||
h->cupsBorderlessScalingFactor > 2.0)
{
_cupsRasterAddError("Page header uses unsupported values.\n");
return (-1);
}
h->cupsWidth = (unsigned)((right - left) * h->cupsBorderlessScalingFactor *
h->HWResolution[0] / 72.0f + 0.5f);
h->cupsHeight = (unsigned)((top - bottom) * h->cupsBorderlessScalingFactor *
h->HWResolution[1] / 72.0f + 0.5f);
switch (h->cupsColorSpace)
{
case CUPS_CSPACE_W :
case CUPS_CSPACE_K :
case CUPS_CSPACE_WHITE :
case CUPS_CSPACE_GOLD :
case CUPS_CSPACE_SILVER :
case CUPS_CSPACE_SW :
h->cupsNumColors = 1;
h->cupsBitsPerPixel = h->cupsBitsPerColor;
break;
default :
if (h->cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
h->cupsBitsPerColor < 8)
h->cupsBitsPerColor = 8;
if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
if (h->cupsBitsPerColor >= 8)
h->cupsBitsPerPixel = h->cupsBitsPerColor * 3;
else
h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
}
else
h->cupsBitsPerPixel = h->cupsBitsPerColor;
h->cupsNumColors = 3;
break;
case CUPS_CSPACE_KCMYcm :
if (h->cupsBitsPerColor == 1)
{
if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
h->cupsBitsPerPixel = 8;
else
h->cupsBitsPerPixel = 1;
h->cupsNumColors = 6;
break;
}
case CUPS_CSPACE_RGBA :
case CUPS_CSPACE_RGBW :
case CUPS_CSPACE_CMYK :
case CUPS_CSPACE_YMCK :
case CUPS_CSPACE_KCMY :
case CUPS_CSPACE_GMCK :
case CUPS_CSPACE_GMCS :
if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
else
h->cupsBitsPerPixel = h->cupsBitsPerColor;
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;
if (h->cupsColorOrder == CUPS_ORDER_BANDED)
h->cupsBytesPerLine *= h->cupsNumColors;
return (status);
}
int
_cupsRasterExecPS(
cups_page_header2_t *h,
int *preferred_bits,
const char *code)
{
int error = 0;
_cups_ps_stack_t *st;
_cups_ps_obj_t *obj;
char *codecopy,
*codeptr;
DEBUG_printf(("_cupsRasterExecPS(h=%p, preferred_bits=%p, code=\"%s\")\n",
h, preferred_bits, code));
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);
}
codeptr = codecopy;
while ((obj = scan_ps(st, &codeptr)) != NULL)
{
#ifdef DEBUG
DEBUG_printf(("_cupsRasterExecPS: Stack (%d objects)", st->num_objs));
DEBUG_object("_cupsRasterExecPS", obj);
#endif
switch (obj->type)
{
default :
break;
case CUPS_PS_CLEARTOMARK :
pop_stack(st);
if (cleartomark_stack(st))
_cupsRasterAddError("cleartomark: Stack underflow.\n");
#ifdef DEBUG
DEBUG_puts("1_cupsRasterExecPS: dup");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
break;
case CUPS_PS_COPY :
pop_stack(st);
if ((obj = pop_stack(st)) != NULL)
{
copy_stack(st, (int)obj->value.number);
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: copy");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
}
break;
case CUPS_PS_DUP :
pop_stack(st);
copy_stack(st, 1);
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: dup");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
break;
case CUPS_PS_INDEX :
pop_stack(st);
if ((obj = pop_stack(st)) != NULL)
{
index_stack(st, (int)obj->value.number);
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: index");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
}
break;
case CUPS_PS_POP :
pop_stack(st);
pop_stack(st);
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: pop");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
break;
case CUPS_PS_ROLL :
pop_stack(st);
if ((obj = pop_stack(st)) != NULL)
{
int c;
c = (int)obj->value.number;
if ((obj = pop_stack(st)) != NULL)
{
roll_stack(st, (int)obj->value.number, c);
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: roll");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
}
}
break;
case CUPS_PS_SETPAGEDEVICE :
pop_stack(st);
setpagedevice(st, h, preferred_bits);
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: setpagedevice");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
break;
case CUPS_PS_START_PROC :
case CUPS_PS_END_PROC :
case CUPS_PS_STOPPED :
pop_stack(st);
break;
case CUPS_PS_OTHER :
_cupsRasterAddError("Unknown operator \"%s\".\n", obj->value.other);
error = 1;
DEBUG_printf(("_cupsRasterExecPS: Unknown operator \"%s\".", obj->value.other));
break;
}
if (error)
break;
}
free(codecopy);
if (st->num_objs > 0)
{
error_stack(st, "Stack not empty:");
#ifdef DEBUG
DEBUG_puts("_cupsRasterExecPS: Stack not empty");
DEBUG_stack("_cupsRasterExecPS", st);
#endif
delete_stack(st);
return (-1);
}
delete_stack(st);
return (0);
}
static int
cleartomark_stack(_cups_ps_stack_t *st)
{
_cups_ps_obj_t *obj;
while ((obj = pop_stack(st)) != NULL)
if (obj->type == CUPS_PS_START_ARRAY)
break;
return (obj ? 0 : -1);
}
static int
copy_stack(_cups_ps_stack_t *st,
int c)
{
int n;
if (c < 0)
return (-1);
else if (c == 0)
return (0);
if ((n = st->num_objs - c) < 0)
return (-1);
while (c > 0)
{
if (!push_stack(st, st->objs + n))
return (-1);
n ++;
c --;
}
return (0);
}
static void
delete_stack(_cups_ps_stack_t *st)
{
free(st->objs);
free(st);
}
static void
error_object(_cups_ps_obj_t *obj)
{
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;
}
}
static void
error_stack(_cups_ps_stack_t *st,
const char *title)
{
int c;
_cups_ps_obj_t *obj;
_cupsRasterAddError("%s", title);
for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
error_object(obj);
_cupsRasterAddError("\n");
}
static _cups_ps_obj_t *
index_stack(_cups_ps_stack_t *st,
int n)
{
if (n < 0 || (n = st->num_objs - n - 1) < 0)
return (NULL);
return (push_stack(st, st->objs + n));
}
static _cups_ps_stack_t *
new_stack(void)
{
_cups_ps_stack_t *st;
if ((st = calloc(1, sizeof(_cups_ps_stack_t))) == NULL)
return (NULL);
st->alloc_objs = 32;
if ((st->objs = calloc(32, sizeof(_cups_ps_obj_t))) == NULL)
{
free(st);
return (NULL);
}
else
return (st);
}
static _cups_ps_obj_t *
pop_stack(_cups_ps_stack_t *st)
{
if (st->num_objs > 0)
{
st->num_objs --;
return (st->objs + st->num_objs);
}
else
return (NULL);
}
static _cups_ps_obj_t *
push_stack(_cups_ps_stack_t *st,
_cups_ps_obj_t *obj)
{
_cups_ps_obj_t *temp;
if (st->num_objs >= st->alloc_objs)
{
st->alloc_objs += 32;
if ((temp = realloc(st->objs, (size_t)st->alloc_objs *
sizeof(_cups_ps_obj_t))) == NULL)
return (NULL);
st->objs = temp;
memset(temp + st->num_objs, 0, 32 * sizeof(_cups_ps_obj_t));
}
temp = st->objs + st->num_objs;
st->num_objs ++;
memcpy(temp, obj, sizeof(_cups_ps_obj_t));
return (temp);
}
static int
roll_stack(_cups_ps_stack_t *st,
int c,
int s)
{
_cups_ps_obj_t *temp;
int n;
DEBUG_printf(("3roll_stack(st=%p, s=%d, c=%d)", st, s, c));
if (c < 0)
return (-1);
else if (c == 0)
return (0);
if ((n = st->num_objs - c) < 0)
return (-1);
s %= c;
if (s == 0)
return (0);
if (s < 0)
{
s = -s;
if ((temp = calloc((size_t)s, sizeof(_cups_ps_obj_t))) == NULL)
return (-1);
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
{
if ((temp = calloc((size_t)s, sizeof(_cups_ps_obj_t))) == NULL)
return (-1);
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);
return (0);
}
static _cups_ps_obj_t *
scan_ps(_cups_ps_stack_t *st,
char **ptr)
{
_cups_ps_obj_t obj;
char *start,
*cur,
*valptr,
*valend;
int parens;
for (cur = *ptr; *cur; cur ++)
{
if (*cur == '%')
{
for (cur ++; *cur && *cur != '\n' && *cur != '\r'; cur ++);
if (!*cur)
cur --;
}
else if (!isspace(*cur & 255))
break;
}
if (!*cur)
{
*ptr = NULL;
return (NULL);
}
memset(&obj, 0, sizeof(obj));
switch (*cur)
{
case '(' :
obj.type = CUPS_PS_STRING;
start = cur;
for (cur ++, parens = 1, valptr = obj.value.string,
valend = obj.value.string + sizeof(obj.value.string) - 1;
*cur;
cur ++)
{
if (*cur == ')' && parens == 1)
break;
if (*cur == '(')
parens ++;
else if (*cur == ')')
parens --;
if (valptr >= valend)
{
*ptr = start;
return (NULL);
}
if (*cur == '\\')
{
cur ++;
if (*cur == 'b')
*valptr++ = '\b';
else if (*cur == 'f')
*valptr++ = '\f';
else if (*cur == 'n')
*valptr++ = '\n';
else if (*cur == 'r')
*valptr++ = '\r';
else if (*cur == 't')
*valptr++ = '\t';
else if (*cur >= '0' && *cur <= '7')
{
int ch = *cur - '0';
if (cur[1] >= '0' && cur[1] <= '7')
{
cur ++;
ch = (ch << 3) + *cur - '0';
}
if (cur[1] >= '0' && cur[1] <= '7')
{
cur ++;
ch = (ch << 3) + *cur - '0';
}
*valptr++ = (char)ch;
}
else if (*cur == '\r')
{
if (cur[1] == '\n')
cur ++;
}
else if (*cur != '\n')
*valptr++ = *cur;
}
else
*valptr++ = *cur;
}
if (*cur != ')')
{
*ptr = start;
return (NULL);
}
cur ++;
break;
case '[' :
obj.type = CUPS_PS_START_ARRAY;
cur ++;
break;
case ']' :
obj.type = CUPS_PS_END_ARRAY;
cur ++;
break;
case '<' :
if (cur[1] == '<')
{
obj.type = CUPS_PS_START_DICT;
cur += 2;
}
else
{
obj.type = CUPS_PS_STRING;
start = cur;
for (cur ++, valptr = obj.value.string,
valend = obj.value.string + sizeof(obj.value.string) - 1;
*cur;
cur ++)
{
int ch;
if (*cur == '>')
break;
else if (valptr >= valend || !isxdigit(*cur & 255))
{
*ptr = start;
return (NULL);
}
if (*cur >= '0' && *cur <= '9')
ch = (*cur - '0') << 4;
else
ch = (tolower(*cur) - 'a' + 10) << 4;
if (isxdigit(cur[1] & 255))
{
cur ++;
if (*cur >= '0' && *cur <= '9')
ch |= *cur - '0';
else
ch |= tolower(*cur) - 'a' + 10;
}
*valptr++ = (char)ch;
}
if (*cur != '>')
{
*ptr = start;
return (NULL);
}
cur ++;
}
break;
case '>' :
if (cur[1] == '>')
{
obj.type = CUPS_PS_END_DICT;
cur += 2;
}
else
{
obj.type = CUPS_PS_OTHER;
obj.value.other[0] = *cur;
cur ++;
}
break;
case '{' :
obj.type = CUPS_PS_START_PROC;
cur ++;
break;
case '}' :
obj.type = CUPS_PS_END_PROC;
cur ++;
break;
case '-' :
case '+' :
if (!isdigit(cur[1] & 255) && cur[1] != '.')
{
obj.type = CUPS_PS_OTHER;
obj.value.other[0] = *cur;
cur ++;
break;
}
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
case '.' :
obj.type = CUPS_PS_NUMBER;
start = cur;
for (cur ++; *cur; cur ++)
if (!isdigit(*cur & 255))
break;
if (*cur == '#')
{
obj.value.number = strtol(cur + 1, &cur, atoi(start));
break;
}
else if (strchr(".Ee()<>[]{}/%", *cur) || isspace(*cur & 255))
{
obj.value.number = _cupsStrScand(start, &cur, localeconv());
break;
}
else
cur = start;
default :
start = cur;
if (*cur == '/')
{
obj.type = CUPS_PS_NAME;
valptr = obj.value.name;
valend = obj.value.name + sizeof(obj.value.name) - 1;
cur ++;
}
else
{
obj.type = CUPS_PS_OTHER;
valptr = obj.value.other;
valend = obj.value.other + sizeof(obj.value.other) - 1;
}
while (*cur)
{
if (strchr("()<>[]{}/%", *cur) || isspace(*cur & 255))
break;
else if (valptr < valend)
*valptr++ = *cur++;
else
{
*ptr = start;
return (NULL);
}
}
if (obj.type == CUPS_PS_OTHER)
{
if (!strcmp(obj.value.other, "true"))
{
obj.type = CUPS_PS_BOOLEAN;
obj.value.boolean = 1;
}
else if (!strcmp(obj.value.other, "false"))
{
obj.type = CUPS_PS_BOOLEAN;
obj.value.boolean = 0;
}
else if (!strcmp(obj.value.other, "null"))
obj.type = CUPS_PS_NULL;
else if (!strcmp(obj.value.other, "cleartomark"))
obj.type = CUPS_PS_CLEARTOMARK;
else if (!strcmp(obj.value.other, "copy"))
obj.type = CUPS_PS_COPY;
else if (!strcmp(obj.value.other, "dup"))
obj.type = CUPS_PS_DUP;
else if (!strcmp(obj.value.other, "index"))
obj.type = CUPS_PS_INDEX;
else if (!strcmp(obj.value.other, "pop"))
obj.type = CUPS_PS_POP;
else if (!strcmp(obj.value.other, "roll"))
obj.type = CUPS_PS_ROLL;
else if (!strcmp(obj.value.other, "setpagedevice"))
obj.type = CUPS_PS_SETPAGEDEVICE;
else if (!strcmp(obj.value.other, "stopped"))
obj.type = CUPS_PS_STOPPED;
}
break;
}
*ptr = cur;
return (push_stack(st, &obj));
}
static int
setpagedevice(
_cups_ps_stack_t *st,
cups_page_header2_t *h,
int *preferred_bits)
{
int i;
_cups_ps_obj_t *obj,
*end;
const char *name;
if (st->num_objs == 0)
return (-1);
obj = end = st->objs + st->num_objs - 1;
if (obj->type != CUPS_PS_END_DICT)
return (-1);
obj --;
while (obj > st->objs)
{
if (obj->type == CUPS_PS_START_DICT)
break;
obj --;
}
if (obj < st->objs)
return (-1);
st->num_objs = (int)(obj - st->objs);
DEBUG_puts("3setpagedevice: Dictionary:");
for (obj ++; obj < end; obj ++)
{
if (obj->type != CUPS_PS_NAME)
return (-1);
name = obj->value.name;
obj ++;
#ifdef DEBUG
DEBUG_printf(("4setpagedevice: /%s ", name));
DEBUG_object("setpagedevice", obj);
#endif
if (!strcmp(name, "MediaClass") && obj->type == CUPS_PS_STRING)
strlcpy(h->MediaClass, obj->value.string, sizeof(h->MediaClass));
else if (!strcmp(name, "MediaColor") && obj->type == CUPS_PS_STRING)
strlcpy(h->MediaColor, obj->value.string, sizeof(h->MediaColor));
else if (!strcmp(name, "MediaType") && obj->type == CUPS_PS_STRING)
strlcpy(h->MediaType, obj->value.string, sizeof(h->MediaType));
else if (!strcmp(name, "OutputType") && obj->type == CUPS_PS_STRING)
strlcpy(h->OutputType, obj->value.string, sizeof(h->OutputType));
else if (!strcmp(name, "AdvanceDistance") && obj->type == CUPS_PS_NUMBER)
h->AdvanceDistance = (unsigned)obj->value.number;
else if (!strcmp(name, "AdvanceMedia") && obj->type == CUPS_PS_NUMBER)
h->AdvanceMedia = (unsigned)obj->value.number;
else if (!strcmp(name, "Collate") && obj->type == CUPS_PS_BOOLEAN)
h->Collate = (unsigned)obj->value.boolean;
else if (!strcmp(name, "CutMedia") && obj->type == CUPS_PS_NUMBER)
h->CutMedia = (cups_cut_t)(unsigned)obj->value.number;
else if (!strcmp(name, "Duplex") && obj->type == CUPS_PS_BOOLEAN)
h->Duplex = (unsigned)obj->value.boolean;
else if (!strcmp(name, "HWResolution") && obj->type == CUPS_PS_START_ARRAY)
{
if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
obj[3].type == CUPS_PS_END_ARRAY)
{
h->HWResolution[0] = (unsigned)obj[1].value.number;
h->HWResolution[1] = (unsigned)obj[2].value.number;
obj += 3;
}
else
return (-1);
}
else if (!strcmp(name, "InsertSheet") && obj->type == CUPS_PS_BOOLEAN)
h->InsertSheet = (unsigned)obj->value.boolean;
else if (!strcmp(name, "Jog") && obj->type == CUPS_PS_NUMBER)
h->Jog = (unsigned)obj->value.number;
else if (!strcmp(name, "LeadingEdge") && obj->type == CUPS_PS_NUMBER)
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") ||
!strcmp(name, "MediaPosition")) && obj->type == CUPS_PS_NUMBER)
{
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)
h->MirrorPrint = (unsigned)obj->value.boolean;
else if (!strcmp(name, "NegativePrint") && obj->type == CUPS_PS_BOOLEAN)
h->NegativePrint = (unsigned)obj->value.boolean;
else if (!strcmp(name, "NumCopies") && obj->type == CUPS_PS_NUMBER)
h->NumCopies = (unsigned)obj->value.number;
else if (!strcmp(name, "Orientation") && obj->type == CUPS_PS_NUMBER)
h->Orientation = (unsigned)obj->value.number;
else if (!strcmp(name, "OutputFaceUp") && obj->type == CUPS_PS_BOOLEAN)
h->OutputFaceUp = (unsigned)obj->value.boolean;
else if (!strcmp(name, "PageSize") && obj->type == CUPS_PS_START_ARRAY)
{
if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
obj[3].type == CUPS_PS_END_ARRAY)
{
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;
obj += 3;
}
else
return (-1);
}
else if (!strcmp(name, "Separations") && obj->type == CUPS_PS_BOOLEAN)
h->Separations = (unsigned)obj->value.boolean;
else if (!strcmp(name, "TraySwitch") && obj->type == CUPS_PS_BOOLEAN)
h->TraySwitch = (unsigned)obj->value.boolean;
else if (!strcmp(name, "Tumble") && obj->type == CUPS_PS_BOOLEAN)
h->Tumble = (unsigned)obj->value.boolean;
else if (!strcmp(name, "cupsMediaType") && obj->type == CUPS_PS_NUMBER)
h->cupsMediaType = (unsigned)obj->value.number;
else if (!strcmp(name, "cupsBitsPerColor") && obj->type == CUPS_PS_NUMBER)
h->cupsBitsPerColor = (unsigned)obj->value.number;
else if (!strcmp(name, "cupsPreferredBitsPerColor") &&
obj->type == CUPS_PS_NUMBER)
*preferred_bits = (int)obj->value.number;
else if (!strcmp(name, "cupsColorOrder") && obj->type == CUPS_PS_NUMBER)
h->cupsColorOrder = (cups_order_t)(unsigned)obj->value.number;
else if (!strcmp(name, "cupsColorSpace") && obj->type == CUPS_PS_NUMBER)
h->cupsColorSpace = (cups_cspace_t)(unsigned)obj->value.number;
else if (!strcmp(name, "cupsCompression") && obj->type == CUPS_PS_NUMBER)
h->cupsCompression = (unsigned)obj->value.number;
else if (!strcmp(name, "cupsRowCount") && obj->type == CUPS_PS_NUMBER)
h->cupsRowCount = (unsigned)obj->value.number;
else if (!strcmp(name, "cupsRowFeed") && obj->type == CUPS_PS_NUMBER)
h->cupsRowFeed = (unsigned)obj->value.number;
else if (!strcmp(name, "cupsRowStep") && obj->type == CUPS_PS_NUMBER)
h->cupsRowStep = (unsigned)obj->value.number;
else if (!strcmp(name, "cupsBorderlessScalingFactor") &&
obj->type == CUPS_PS_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)
return (-1);
h->cupsInteger[i] = (unsigned)obj->value.number;
}
else if (!strncmp(name, "cupsReal", 8) && obj->type == CUPS_PS_NUMBER)
{
if ((i = atoi(name + 8)) < 0 || i > 15)
return (-1);
h->cupsReal[i] = (float)obj->value.number;
}
else if (!strncmp(name, "cupsString", 10) && obj->type == CUPS_PS_STRING)
{
if ((i = atoi(name + 10)) < 0 || i > 15)
return (-1);
strlcpy(h->cupsString[i], obj->value.string, sizeof(h->cupsString[i]));
}
else if (!strcmp(name, "cupsMarkerType") && obj->type == CUPS_PS_STRING)
strlcpy(h->cupsMarkerType, obj->value.string, sizeof(h->cupsMarkerType));
else if (!strcmp(name, "cupsPageSizeName") && obj->type == CUPS_PS_STRING)
strlcpy(h->cupsPageSizeName, obj->value.string,
sizeof(h->cupsPageSizeName));
else if (!strcmp(name, "cupsRenderingIntent") &&
obj->type == CUPS_PS_STRING)
strlcpy(h->cupsRenderingIntent, obj->value.string,
sizeof(h->cupsRenderingIntent));
else
{
DEBUG_printf(("4setpagedevice: Unknown name (\"%s\") or value...\n", name));
while (obj[1].type != CUPS_PS_NAME && obj < end)
obj ++;
}
}
return (0);
}
#ifdef DEBUG
static void
DEBUG_object(const char *prefix,
_cups_ps_obj_t *obj)
{
switch (obj->type)
{
case CUPS_PS_NAME :
DEBUG_printf(("4%s: /%s\n", prefix, obj->value.name));
break;
case CUPS_PS_NUMBER :
DEBUG_printf(("4%s: %g\n", prefix, obj->value.number));
break;
case CUPS_PS_STRING :
DEBUG_printf(("4%s: (%s)\n", prefix, obj->value.string));
break;
case CUPS_PS_BOOLEAN :
if (obj->value.boolean)
DEBUG_printf(("4%s: true", prefix));
else
DEBUG_printf(("4%s: false", prefix));
break;
case CUPS_PS_NULL :
DEBUG_printf(("4%s: null", prefix));
break;
case CUPS_PS_START_ARRAY :
DEBUG_printf(("4%s: [", prefix));
break;
case CUPS_PS_END_ARRAY :
DEBUG_printf(("4%s: ]", prefix));
break;
case CUPS_PS_START_DICT :
DEBUG_printf(("4%s: <<", prefix));
break;
case CUPS_PS_END_DICT :
DEBUG_printf(("4%s: >>", prefix));
break;
case CUPS_PS_START_PROC :
DEBUG_printf(("4%s: {", prefix));
break;
case CUPS_PS_END_PROC :
DEBUG_printf(("4%s: }", prefix));
break;
case CUPS_PS_CLEARTOMARK :
DEBUG_printf(("4%s: --cleartomark--", prefix));
break;
case CUPS_PS_COPY :
DEBUG_printf(("4%s: --copy--", prefix));
break;
case CUPS_PS_DUP :
DEBUG_printf(("4%s: --dup--", prefix));
break;
case CUPS_PS_INDEX :
DEBUG_printf(("4%s: --index--", prefix));
break;
case CUPS_PS_POP :
DEBUG_printf(("4%s: --pop--", prefix));
break;
case CUPS_PS_ROLL :
DEBUG_printf(("4%s: --roll--", prefix));
break;
case CUPS_PS_SETPAGEDEVICE :
DEBUG_printf(("4%s: --setpagedevice--", prefix));
break;
case CUPS_PS_STOPPED :
DEBUG_printf(("4%s: --stopped--", prefix));
break;
case CUPS_PS_OTHER :
DEBUG_printf(("4%s: --%s--", prefix, obj->value.other));
break;
}
}
static void
DEBUG_stack(const char *prefix,
_cups_ps_stack_t *st)
{
int c;
_cups_ps_obj_t *obj;
for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
DEBUG_object(prefix, obj);
}
#endif