]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/interpret.c
Merge changes from CUPS 1.6svn-r9968.
[thirdparty/cups.git] / filter / interpret.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: interpret.c 7852 2008-08-21 04:19:45Z mike $"
ef416fc2 3 *
71e16022 4 * PPD command interpreter for CUPS.
ef416fc2 5 *
a4845881 6 * Copyright 2007-2011 by Apple Inc.
b86bc4cf 7 * Copyright 1993-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * cupsRasterInterpretPPD() - Interpret PPD commands to create a page header.
b86bc4cf 20 * _cupsRasterExecPS() - Execute PostScript code to initialize a page
21 * header.
22 * cleartomark_stack() - Clear to the last mark ([) on the stack.
23 * copy_stack() - Copy the top N stack objects.
24 * delete_stack() - Free memory used by a stack.
f7deaa1a 25 * error_object() - Add an object's value to the current error
26 * message.
27 * error_stack() - Add a stack to the current error message.
b86bc4cf 28 * index_stack() - Copy the Nth value on the stack.
29 * new_stack() - Create a new stack.
30 * pop_stock() - Pop the top object off the stack.
31 * push_stack() - Push an object on the stack.
32 * roll_stack() - Rotate stack objects.
33 * scan_ps() - Scan a string for the next PS object.
34 * setpagedevice() - Simulate the PostScript setpagedevice operator.
35 * DEBUG_object() - Print an object value.
36 * DEBUG_stack() - Print a stack.
ef416fc2 37 */
38
39/*
40 * Include necessary headers...
41 */
42
a4845881 43#include <cups/raster-private.h>
ef416fc2 44
45
46/*
b86bc4cf 47 * Stack values for the PostScript mini-interpreter...
ef416fc2 48 */
49
b86bc4cf 50typedef enum
51{
52 CUPS_PS_NAME,
53 CUPS_PS_NUMBER,
54 CUPS_PS_STRING,
55 CUPS_PS_BOOLEAN,
56 CUPS_PS_NULL,
57 CUPS_PS_START_ARRAY,
58 CUPS_PS_END_ARRAY,
59 CUPS_PS_START_DICT,
60 CUPS_PS_END_DICT,
61 CUPS_PS_START_PROC,
62 CUPS_PS_END_PROC,
63 CUPS_PS_CLEARTOMARK,
64 CUPS_PS_COPY,
65 CUPS_PS_DUP,
66 CUPS_PS_INDEX,
67 CUPS_PS_POP,
68 CUPS_PS_ROLL,
69 CUPS_PS_SETPAGEDEVICE,
70 CUPS_PS_STOPPED,
71 CUPS_PS_OTHER
72} _cups_ps_type_t;
73
74typedef struct
75{
76 _cups_ps_type_t type; /* Object type */
77 union
78 {
79 int boolean; /* Boolean value */
80 char name[64]; /* Name value */
81 double number; /* Number value */
82 char other[64]; /* Other operator */
83 char string[64]; /* Sring value */
84 } value; /* Value */
85} _cups_ps_obj_t;
86
87typedef struct
88{
89 int num_objs, /* Number of objects on stack */
90 alloc_objs; /* Number of allocated objects */
91 _cups_ps_obj_t *objs; /* Objects in stack */
92} _cups_ps_stack_t;
ef416fc2 93
94
95/*
96 * Local functions...
97 */
98
b86bc4cf 99static int cleartomark_stack(_cups_ps_stack_t *st);
100static int copy_stack(_cups_ps_stack_t *st, int count);
101static void delete_stack(_cups_ps_stack_t *st);
f7deaa1a 102static void error_object(_cups_ps_obj_t *obj);
103static void error_stack(_cups_ps_stack_t *st, const char *title);
b86bc4cf 104static _cups_ps_obj_t *index_stack(_cups_ps_stack_t *st, int n);
105static _cups_ps_stack_t *new_stack(void);
106static _cups_ps_obj_t *pop_stack(_cups_ps_stack_t *st);
107static _cups_ps_obj_t *push_stack(_cups_ps_stack_t *st,
108 _cups_ps_obj_t *obj);
109static int roll_stack(_cups_ps_stack_t *st, int c, int s);
110static _cups_ps_obj_t *scan_ps(_cups_ps_stack_t *st, char **ptr);
111static int setpagedevice(_cups_ps_stack_t *st,
112 cups_page_header2_t *h,
113 int *preferred_bits);
114#ifdef DEBUG
115static void DEBUG_object(_cups_ps_obj_t *obj);
116static void DEBUG_stack(_cups_ps_stack_t *st);
117#endif /* DEBUG */
ef416fc2 118
119
120/*
121 * 'cupsRasterInterpretPPD()' - Interpret PPD commands to create a page header.
122 *
db0bd74a
MS
123 * This function is used by raster image processing (RIP) filters like
124 * cgpdftoraster and imagetoraster when writing CUPS raster data for a page.
125 * It is not used by raster printer driver filters which only read CUPS
126 * raster data.
127 *
128 *
129 * @code cupsRasterInterpretPPD@ does not mark the options in the PPD using
130 * the "num_options" and "options" arguments. Instead, mark the options with
131 * @code cupsMarkOptions@ and @code ppdMarkOption@ prior to calling it -
132 * this allows for per-page options without manipulating the options array.
923edb68 133 *
a74454a7 134 * The "func" argument specifies an optional callback function that is
135 * called prior to the computation of the final raster data. The function
5a738aea 136 * can make changes to the @link cups_page_header2_t@ data as needed to use a
a74454a7 137 * supported raster format and then returns 0 on success and -1 if the
138 * requested attributes cannot be supported.
139 *
db0bd74a 140 *
5a738aea
MS
141 * @code cupsRasterInterpretPPD@ supports a subset of the PostScript language.
142 * Currently only the @code [@, @code ]@, @code <<@, @code >>@, @code {@,
143 * @code }@, @code cleartomark@, @code copy@, @code dup@, @code index@,
144 * @code pop@, @code roll@, @code setpagedevice@, and @code stopped@ operators
145 * are supported.
b86bc4cf 146 *
db0bd74a 147 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 148 */
149
150int /* O - 0 on success, -1 on failure */
151cupsRasterInterpretPPD(
db0bd74a 152 cups_page_header2_t *h, /* O - Page header to create */
923edb68 153 ppd_file_t *ppd, /* I - PPD file */
154 int num_options, /* I - Number of options */
a74454a7 155 cups_option_t *options, /* I - Options */
db0bd74a 156 cups_interpret_cb_t func) /* I - Optional page header callback (@code NULL@ for none) */
ef416fc2 157{
ef416fc2 158 int status; /* Cummulative status */
b86bc4cf 159 char *code; /* Code to run */
923edb68 160 const char *val; /* Option value */
ef416fc2 161 ppd_size_t *size; /* Current size */
162 float left, /* Left position */
163 bottom, /* Bottom position */
164 right, /* Right position */
165 top; /* Top position */
a74454a7 166 int preferred_bits; /* Preferred bits per color */
ef416fc2 167
168
169 /*
170 * Range check input...
171 */
172
f7deaa1a 173 _cupsRasterClearError();
174
ef416fc2 175 if (!h)
f7deaa1a 176 {
177 _cupsRasterAddError("Page header cannot be NULL!\n");
ef416fc2 178 return (-1);
f7deaa1a 179 }
ef416fc2 180
181 /*
182 * Reset the page header to the defaults...
183 */
184
185 memset(h, 0, sizeof(cups_page_header2_t));
186
923edb68 187 h->NumCopies = 1;
188 h->PageSize[0] = 612;
189 h->PageSize[1] = 792;
190 h->HWResolution[0] = 100;
191 h->HWResolution[1] = 100;
192 h->cupsBitsPerColor = 1;
193 h->cupsColorOrder = CUPS_ORDER_CHUNKED;
194 h->cupsColorSpace = CUPS_CSPACE_K;
195 h->cupsBorderlessScalingFactor = 1.0f;
196 h->cupsPageSize[0] = 612.0f;
197 h->cupsPageSize[1] = 792.0f;
198 h->cupsImagingBBox[0] = 0.0f;
199 h->cupsImagingBBox[1] = 0.0f;
200 h->cupsImagingBBox[2] = 612.0f;
201 h->cupsImagingBBox[3] = 792.0f;
fa73b229 202
203 strcpy(h->cupsPageSizeName, "Letter");
ef416fc2 204
e38f5e9c
MS
205#ifdef __APPLE__
206 /*
207 * cupsInteger0 is also used for the total page count on Mac OS X; set an
208 * uncommon default value so we can tell if the driver is using cupsInteger0.
209 */
210
211 h->cupsInteger[0] = 0x80000000;
212#endif /* __APPLE__ */
213
ef416fc2 214 /*
215 * Apply patches and options to the page header...
216 */
217
a74454a7 218 status = 0;
219 preferred_bits = 0;
ef416fc2 220
221 if (ppd)
222 {
223 /*
224 * Apply any patch code (used to override the defaults...)
225 */
226
227 if (ppd->patches)
b86bc4cf 228 status |= _cupsRasterExecPS(h, &preferred_bits, ppd->patches);
ef416fc2 229
230 /*
231 * Then apply printer options in the proper order...
232 */
233
b86bc4cf 234 if ((code = ppdEmitString(ppd, PPD_ORDER_DOCUMENT, 0.0)) != NULL)
ef416fc2 235 {
b86bc4cf 236 status |= _cupsRasterExecPS(h, &preferred_bits, code);
237 free(code);
ef416fc2 238 }
239
b86bc4cf 240 if ((code = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL)
ef416fc2 241 {
b86bc4cf 242 status |= _cupsRasterExecPS(h, &preferred_bits, code);
243 free(code);
ef416fc2 244 }
245
b86bc4cf 246 if ((code = ppdEmitString(ppd, PPD_ORDER_PROLOG, 0.0)) != NULL)
ef416fc2 247 {
b86bc4cf 248 status |= _cupsRasterExecPS(h, &preferred_bits, code);
249 free(code);
ef416fc2 250 }
251
b86bc4cf 252 if ((code = ppdEmitString(ppd, PPD_ORDER_PAGE, 0.0)) != NULL)
ef416fc2 253 {
b86bc4cf 254 status |= _cupsRasterExecPS(h, &preferred_bits, code);
255 free(code);
ef416fc2 256 }
257 }
258
923edb68 259 /*
260 * Allow option override for page scaling...
261 */
262
263 if ((val = cupsGetOption("cupsBorderlessScalingFactor", num_options,
264 options)) != NULL)
265 {
c8fef167 266 double sc = atof(val); /* Scale factor */
923edb68 267
06d4e77b 268 if (sc >= 0.1 && sc <= 2.0)
c8fef167 269 h->cupsBorderlessScalingFactor = (float)sc;
923edb68 270 }
271
ef416fc2 272 /*
273 * Get the margins for the current size...
274 */
275
276 if ((size = ppdPageSize(ppd, NULL)) != NULL)
277 {
278 /*
279 * Use the margins from the PPD file...
280 */
281
282 left = size->left;
283 bottom = size->bottom;
284 right = size->right;
285 top = size->top;
fa73b229 286
287 strlcpy(h->cupsPageSizeName, size->name, sizeof(h->cupsPageSizeName));
07725fee 288
289 h->cupsPageSize[0] = size->width;
290 h->cupsPageSize[1] = size->length;
ef416fc2 291 }
292 else
293 {
294 /*
295 * Use the default margins...
296 */
297
298 left = 0.0f;
299 bottom = 0.0f;
300 right = 612.0f;
301 top = 792.0f;
302 }
303
c8fef167
MS
304 h->PageSize[0] = (unsigned)(h->cupsPageSize[0] *
305 h->cupsBorderlessScalingFactor);
306 h->PageSize[1] = (unsigned)(h->cupsPageSize[1] *
307 h->cupsBorderlessScalingFactor);
308 h->Margins[0] = (unsigned)(left *
309 h->cupsBorderlessScalingFactor);
310 h->Margins[1] = (unsigned)(bottom *
311 h->cupsBorderlessScalingFactor);
312 h->ImagingBoundingBox[0] = (unsigned)(left *
313 h->cupsBorderlessScalingFactor);
314 h->ImagingBoundingBox[1] = (unsigned)(bottom *
315 h->cupsBorderlessScalingFactor);
316 h->ImagingBoundingBox[2] = (unsigned)(right *
317 h->cupsBorderlessScalingFactor);
318 h->ImagingBoundingBox[3] = (unsigned)(top *
319 h->cupsBorderlessScalingFactor);
320 h->cupsImagingBBox[0] = (float)left;
321 h->cupsImagingBBox[1] = (float)bottom;
322 h->cupsImagingBBox[2] = (float)right;
323 h->cupsImagingBBox[3] = (float)top;
ef416fc2 324
a74454a7 325 /*
326 * Use the callback to validate the page header...
327 */
328
329 if (func && (*func)(h, preferred_bits))
f7deaa1a 330 {
331 _cupsRasterAddError("Page header callback returned error.\n");
a74454a7 332 return (-1);
f7deaa1a 333 }
a74454a7 334
a9252913 335 /*
336 * Check parameters...
337 */
338
339 if (!h->HWResolution[0] || !h->HWResolution[1] ||
340 !h->PageSize[0] || !h->PageSize[1] ||
341 (h->cupsBitsPerColor != 1 && h->cupsBitsPerColor != 2 &&
342 h->cupsBitsPerColor != 4 && h->cupsBitsPerColor != 8 &&
343 h->cupsBitsPerColor != 16) ||
06d4e77b 344 h->cupsBorderlessScalingFactor < 0.1 ||
b86bc4cf 345 h->cupsBorderlessScalingFactor > 2.0)
f7deaa1a 346 {
347 _cupsRasterAddError("Page header uses unsupported values.\n");
a9252913 348 return (-1);
f7deaa1a 349 }
a9252913 350
ef416fc2 351 /*
352 * Compute the bitmap parameters...
353 */
354
923edb68 355 h->cupsWidth = (int)((right - left) * h->cupsBorderlessScalingFactor *
fa73b229 356 h->HWResolution[0] / 72.0f + 0.5f);
923edb68 357 h->cupsHeight = (int)((top - bottom) * h->cupsBorderlessScalingFactor *
fa73b229 358 h->HWResolution[1] / 72.0f + 0.5f);
ef416fc2 359
360 switch (h->cupsColorSpace)
361 {
362 case CUPS_CSPACE_W :
363 case CUPS_CSPACE_K :
364 case CUPS_CSPACE_WHITE :
365 case CUPS_CSPACE_GOLD :
366 case CUPS_CSPACE_SILVER :
88f9aafc 367 case CUPS_CSPACE_SW :
ef416fc2 368 h->cupsNumColors = 1;
369 h->cupsBitsPerPixel = h->cupsBitsPerColor;
370 break;
371
372 default :
373 /*
374 * Ensure that colorimetric colorspaces use at least 8 bits per
375 * component...
376 */
377
378 if (h->cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
379 h->cupsBitsPerColor < 8)
380 h->cupsBitsPerColor = 8;
381
382 /*
383 * Figure out the number of bits per pixel...
384 */
385
386 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
387 {
388 if (h->cupsBitsPerColor >= 8)
389 h->cupsBitsPerPixel = h->cupsBitsPerColor * 3;
390 else
391 h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
392 }
393 else
394 h->cupsBitsPerPixel = h->cupsBitsPerColor;
395
396 h->cupsNumColors = 3;
397 break;
398
399 case CUPS_CSPACE_KCMYcm :
f301802f 400 if (h->cupsBitsPerColor == 1)
ef416fc2 401 {
402 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
403 h->cupsBitsPerPixel = 8;
404 else
405 h->cupsBitsPerPixel = 1;
406
407 h->cupsNumColors = 6;
408 break;
409 }
410
411 /*
412 * Fall through to CMYK code...
413 */
414
415 case CUPS_CSPACE_RGBA :
a74454a7 416 case CUPS_CSPACE_RGBW :
ef416fc2 417 case CUPS_CSPACE_CMYK :
418 case CUPS_CSPACE_YMCK :
419 case CUPS_CSPACE_KCMY :
420 case CUPS_CSPACE_GMCK :
421 case CUPS_CSPACE_GMCS :
422 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
423 h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
424 else
425 h->cupsBitsPerPixel = h->cupsBitsPerColor;
426
427 h->cupsNumColors = 4;
428 break;
88f9aafc
MS
429
430 case CUPS_CSPACE_DEVICE1 :
431 case CUPS_CSPACE_DEVICE2 :
432 case CUPS_CSPACE_DEVICE3 :
433 case CUPS_CSPACE_DEVICE4 :
434 case CUPS_CSPACE_DEVICE5 :
435 case CUPS_CSPACE_DEVICE6 :
436 case CUPS_CSPACE_DEVICE7 :
437 case CUPS_CSPACE_DEVICE8 :
438 case CUPS_CSPACE_DEVICE9 :
439 case CUPS_CSPACE_DEVICEA :
440 case CUPS_CSPACE_DEVICEB :
441 case CUPS_CSPACE_DEVICEC :
442 case CUPS_CSPACE_DEVICED :
443 case CUPS_CSPACE_DEVICEE :
444 case CUPS_CSPACE_DEVICEF :
445 h->cupsNumColors = h->cupsColorSpace - CUPS_CSPACE_DEVICE1 + 1;
446
447 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
448 h->cupsBitsPerPixel = h->cupsBitsPerColor * h->cupsNumColors;
449 else
450 h->cupsBitsPerPixel = h->cupsBitsPerColor;
451 break;
ef416fc2 452 }
453
454 h->cupsBytesPerLine = (h->cupsBitsPerPixel * h->cupsWidth + 7) / 8;
455
456 if (h->cupsColorOrder == CUPS_ORDER_BANDED)
457 h->cupsBytesPerLine *= h->cupsNumColors;
458
459 return (status);
460}
461
462
463/*
b86bc4cf 464 * '_cupsRasterExecPS()' - Execute PostScript code to initialize a page header.
ef416fc2 465 */
466
b86bc4cf 467int /* O - 0 on success, -1 on error */
468_cupsRasterExecPS(
a74454a7 469 cups_page_header2_t *h, /* O - Page header */
470 int *preferred_bits,/* O - Preferred bits per color */
b86bc4cf 471 const char *code) /* I - PS code to execute */
ef416fc2 472{
b86bc4cf 473 _cups_ps_stack_t *st; /* PostScript value stack */
474 _cups_ps_obj_t *obj; /* Object from top of stack */
475 char *codecopy, /* Copy of code */
476 *codeptr; /* Pointer into copy of code */
477
ef416fc2 478
b86bc4cf 479 DEBUG_printf(("_cupsRasterExecPS(h=%p, preferred_bits=%p, code=\"%s\")\n",
480 h, preferred_bits, code ? code : "(null)"));
ef416fc2 481
482 /*
b86bc4cf 483 * Copy the PostScript code and create a stack...
ef416fc2 484 */
485
b86bc4cf 486 if ((codecopy = strdup(code)) == NULL)
f7deaa1a 487 {
488 _cupsRasterAddError("Unable to duplicate code string.\n");
b86bc4cf 489 return (-1);
f7deaa1a 490 }
b86bc4cf 491
492 if ((st = new_stack()) == NULL)
493 {
f7deaa1a 494 _cupsRasterAddError("Unable to create stack.\n");
b86bc4cf 495 free(codecopy);
ef416fc2 496 return (-1);
b86bc4cf 497 }
ef416fc2 498
499 /*
b86bc4cf 500 * Parse the PS string until we run out of data...
ef416fc2 501 */
502
b86bc4cf 503 codeptr = codecopy;
504
505 while ((obj = scan_ps(st, &codeptr)) != NULL)
ef416fc2 506 {
b86bc4cf 507#ifdef DEBUG
ae71f5de 508 DEBUG_printf(("_cupsRasterExecPS: Stack (%d objects)\n", st->num_objs));
b86bc4cf 509 DEBUG_object(obj);
b86bc4cf 510#endif /* DEBUG */
511
512 switch (obj->type)
513 {
514 default :
515 /* Do nothing for regular values */
516 break;
517
518 case CUPS_PS_CLEARTOMARK :
519 pop_stack(st);
520
f7deaa1a 521 if (cleartomark_stack(st))
522 _cupsRasterAddError("cleartomark: Stack underflow!\n");
b86bc4cf 523
524#ifdef DEBUG
ae71f5de 525 DEBUG_puts(" dup: ");
b86bc4cf 526 DEBUG_stack(st);
527#endif /* DEBUG */
528 break;
529
530 case CUPS_PS_COPY :
531 pop_stack(st);
532 if ((obj = pop_stack(st)) != NULL)
533 {
534 copy_stack(st, (int)obj->value.number);
535
536#ifdef DEBUG
ae71f5de 537 DEBUG_puts("_cupsRasterExecPS: copy");
b86bc4cf 538 DEBUG_stack(st);
539#endif /* DEBUG */
540 }
541 break;
542
543 case CUPS_PS_DUP :
544 pop_stack(st);
545 copy_stack(st, 1);
546
547#ifdef DEBUG
ae71f5de 548 DEBUG_puts("_cupsRasterExecPS: dup");
b86bc4cf 549 DEBUG_stack(st);
550#endif /* DEBUG */
551 break;
552
553 case CUPS_PS_INDEX :
554 pop_stack(st);
555 if ((obj = pop_stack(st)) != NULL)
556 {
557 index_stack(st, (int)obj->value.number);
558
559#ifdef DEBUG
ae71f5de 560 DEBUG_puts("_cupsRasterExecPS: index");
b86bc4cf 561 DEBUG_stack(st);
562#endif /* DEBUG */
563 }
564 break;
565
566 case CUPS_PS_POP :
567 pop_stack(st);
568 pop_stack(st);
569
570#ifdef DEBUG
ae71f5de 571 DEBUG_puts("_cupsRasterExecPS: pop");
b86bc4cf 572 DEBUG_stack(st);
573#endif /* DEBUG */
574 break;
575
576 case CUPS_PS_ROLL :
577 pop_stack(st);
578 if ((obj = pop_stack(st)) != NULL)
579 {
580 int c; /* Count */
ef416fc2 581
ef416fc2 582
b86bc4cf 583 c = (int)obj->value.number;
584
585 if ((obj = pop_stack(st)) != NULL)
586 {
587 roll_stack(st, (int)obj->value.number, c);
588
589#ifdef DEBUG
ae71f5de 590 DEBUG_puts("_cupsRasterExecPS: roll");
b86bc4cf 591 DEBUG_stack(st);
592#endif /* DEBUG */
593 }
594 }
595 break;
596
597 case CUPS_PS_SETPAGEDEVICE :
598 pop_stack(st);
599 setpagedevice(st, h, preferred_bits);
600
601#ifdef DEBUG
ae71f5de 602 DEBUG_puts("_cupsRasterExecPS: setpagedevice");
b86bc4cf 603 DEBUG_stack(st);
604#endif /* DEBUG */
605 break;
606
607 case CUPS_PS_START_PROC :
608 case CUPS_PS_END_PROC :
609 case CUPS_PS_STOPPED :
610 pop_stack(st);
611 break;
612
613 case CUPS_PS_OTHER :
f7deaa1a 614 _cupsRasterAddError("Unknown operator \"%s\"!\n", obj->value.other);
ae71f5de
MS
615 DEBUG_printf(("_cupsRasterExecPS: Unknown operator \"%s\"!\n",
616 obj->value.other));
b86bc4cf 617 break;
618 }
619
91c84a35 620 if (obj && obj->type == CUPS_PS_OTHER)
ef416fc2 621 break;
b86bc4cf 622 }
623
624 /*
625 * Cleanup...
626 */
627
628 free(codecopy);
629
630 if (st->num_objs > 0)
631 {
f7deaa1a 632 error_stack(st, "Stack not empty:");
633
b86bc4cf 634#ifdef DEBUG
ae71f5de 635 DEBUG_puts("_cupsRasterExecPS: Stack not empty:");
b86bc4cf 636 DEBUG_stack(st);
637#endif /* DEBUG */
ef416fc2 638
b86bc4cf 639 delete_stack(st);
640
641 return (-1);
642 }
643
644 delete_stack(st);
645
646 /*
647 * Return success...
648 */
649
650 return (0);
651}
652
653
654/*
655 * 'cleartomark_stack()' - Clear to the last mark ([) on the stack.
656 */
657
658static int /* O - 0 on success, -1 on error */
659cleartomark_stack(_cups_ps_stack_t *st) /* I - Stack */
660{
661 _cups_ps_obj_t *obj; /* Current object on stack */
662
663
664 while ((obj = pop_stack(st)) != NULL)
665 if (obj->type == CUPS_PS_START_ARRAY)
666 break;
667
668 return (obj ? 0 : -1);
669}
670
671
672/*
673 * 'copy_stack()' - Copy the top N stack objects.
674 */
675
676static int /* O - 0 on success, -1 on error */
677copy_stack(_cups_ps_stack_t *st, /* I - Stack */
678 int c) /* I - Number of objects to copy */
679{
680 int n; /* Index */
681
682
683 if (c < 0)
684 return (-1);
685 else if (c == 0)
686 return (0);
687
688 if ((n = st->num_objs - c) < 0)
689 return (-1);
690
691 while (c > 0)
692 {
693 if (!push_stack(st, st->objs + n))
694 return (-1);
695
696 n ++;
697 c --;
698 }
699
700 return (0);
701}
702
703
704/*
705 * 'delete_stack()' - Free memory used by a stack.
706 */
707
708static void
709delete_stack(_cups_ps_stack_t *st) /* I - Stack */
710{
711 free(st->objs);
712 free(st);
713}
714
715
f7deaa1a 716/*
717 * 'error_object()' - Add an object's value to the current error message.
718 */
719
720static void
721error_object(_cups_ps_obj_t *obj) /* I - Object to add */
722{
723 switch (obj->type)
724 {
725 case CUPS_PS_NAME :
726 _cupsRasterAddError(" /%s", obj->value.name);
727 break;
728
729 case CUPS_PS_NUMBER :
730 _cupsRasterAddError(" %g", obj->value.number);
731 break;
732
733 case CUPS_PS_STRING :
734 _cupsRasterAddError(" (%s)", obj->value.string);
735 break;
736
737 case CUPS_PS_BOOLEAN :
738 if (obj->value.boolean)
739 _cupsRasterAddError(" true");
740 else
741 _cupsRasterAddError(" false");
742 break;
743
744 case CUPS_PS_NULL :
745 _cupsRasterAddError(" null");
746 break;
747
748 case CUPS_PS_START_ARRAY :
749 _cupsRasterAddError(" [");
750 break;
751
752 case CUPS_PS_END_ARRAY :
753 _cupsRasterAddError(" ]");
754 break;
755
756 case CUPS_PS_START_DICT :
757 _cupsRasterAddError(" <<");
758 break;
759
760 case CUPS_PS_END_DICT :
761 _cupsRasterAddError(" >>");
762 break;
763
764 case CUPS_PS_START_PROC :
765 _cupsRasterAddError(" {");
766 break;
767
768 case CUPS_PS_END_PROC :
769 _cupsRasterAddError(" }");
770 break;
771
772 case CUPS_PS_COPY :
773 _cupsRasterAddError(" --copy--");
774 break;
775
776 case CUPS_PS_CLEARTOMARK :
777 _cupsRasterAddError(" --cleartomark--");
778 break;
779
780 case CUPS_PS_DUP :
781 _cupsRasterAddError(" --dup--");
782 break;
783
784 case CUPS_PS_INDEX :
785 _cupsRasterAddError(" --index--");
786 break;
787
788 case CUPS_PS_POP :
789 _cupsRasterAddError(" --pop--");
790 break;
791
792 case CUPS_PS_ROLL :
793 _cupsRasterAddError(" --roll--");
794 break;
795
796 case CUPS_PS_SETPAGEDEVICE :
797 _cupsRasterAddError(" --setpagedevice--");
798 break;
799
800 case CUPS_PS_STOPPED :
801 _cupsRasterAddError(" --stopped--");
802 break;
803
804 case CUPS_PS_OTHER :
805 _cupsRasterAddError(" --%s--", obj->value.other);
806 break;
807 }
808}
809
810
811/*
812 * 'error_stack()' - Add a stack to the current error message...
813 */
814
815static void
816error_stack(_cups_ps_stack_t *st, /* I - Stack */
817 const char *title) /* I - Title string */
818{
819 int c; /* Looping var */
820 _cups_ps_obj_t *obj; /* Current object on stack */
821
822
85dda01c 823 _cupsRasterAddError("%s", title);
f7deaa1a 824
825 for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
826 error_object(obj);
827
828 _cupsRasterAddError("\n");
829}
830
831
b86bc4cf 832/*
833 * 'index_stack()' - Copy the Nth value on the stack.
834 */
835
836static _cups_ps_obj_t * /* O - New object */
837index_stack(_cups_ps_stack_t *st, /* I - Stack */
838 int n) /* I - Object index */
839{
840 if (n < 0 || (n = st->num_objs - n - 1) < 0)
841 return (NULL);
842
843 return (push_stack(st, st->objs + n));
844}
845
846
847/*
848 * 'new_stack()' - Create a new stack.
849 */
850
851static _cups_ps_stack_t * /* O - New stack */
852new_stack(void)
853{
854 _cups_ps_stack_t *st; /* New stack */
855
856
857 if ((st = calloc(1, sizeof(_cups_ps_stack_t))) == NULL)
858 return (NULL);
859
860 st->alloc_objs = 32;
861
862 if ((st->objs = calloc(32, sizeof(_cups_ps_obj_t))) == NULL)
863 {
864 free(st);
865 return (NULL);
866 }
867 else
868 return (st);
869}
870
871
872/*
873 * 'pop_stock()' - Pop the top object off the stack.
874 */
875
876static _cups_ps_obj_t * /* O - Object */
877pop_stack(_cups_ps_stack_t *st) /* I - Stack */
878{
879 if (st->num_objs > 0)
880 {
881 st->num_objs --;
882
883 return (st->objs + st->num_objs);
884 }
885 else
886 return (NULL);
887}
888
889
890/*
891 * 'push_stack()' - Push an object on the stack.
892 */
893
894static _cups_ps_obj_t * /* O - New object */
895push_stack(_cups_ps_stack_t *st, /* I - Stack */
896 _cups_ps_obj_t *obj) /* I - Object */
897{
898 _cups_ps_obj_t *temp; /* New object */
899
900
901 if (st->num_objs >= st->alloc_objs)
902 {
903
904
905 st->alloc_objs += 32;
906
907 if ((temp = realloc(st->objs, st->alloc_objs *
908 sizeof(_cups_ps_obj_t))) == NULL)
909 return (NULL);
910
911 st->objs = temp;
912 memset(temp + st->num_objs, 0, 32 * sizeof(_cups_ps_obj_t));
913 }
914
915 temp = st->objs + st->num_objs;
916 st->num_objs ++;
917
918 memcpy(temp, obj, sizeof(_cups_ps_obj_t));
919
920 return (temp);
921}
922
923
924/*
925 * 'roll_stack()' - Rotate stack objects.
926 */
927
928static int /* O - 0 on success, -1 on error */
929roll_stack(_cups_ps_stack_t *st, /* I - Stack */
930 int c, /* I - Number of objects */
931 int s) /* I - Amount to shift */
932{
933 _cups_ps_obj_t *temp; /* Temporary array of objects */
934 int n; /* Index into array */
935
936
937 DEBUG_printf((" roll_stack(st=%p, s=%d, c=%d)\n", st, s, c));
938
939 /*
940 * Range check input...
941 */
942
943 if (c < 0)
944 return (-1);
945 else if (c == 0)
946 return (0);
947
948 if ((n = st->num_objs - c) < 0)
949 return (-1);
950
951 s %= c;
952
953 if (s == 0)
954 return (0);
955
956 /*
957 * Copy N objects and move things around...
958 */
959
960 if (s < 0)
961 {
ef416fc2 962 /*
b86bc4cf 963 * Shift down...
ef416fc2 964 */
965
b86bc4cf 966 s = -s;
ef416fc2 967
b86bc4cf 968 if ((temp = calloc(s, sizeof(_cups_ps_obj_t))) == NULL)
969 return (-1);
ef416fc2 970
b86bc4cf 971 memcpy(temp, st->objs + n, s * sizeof(_cups_ps_obj_t));
972 memmove(st->objs + n, st->objs + n + s, (c - s) * sizeof(_cups_ps_obj_t));
973 memcpy(st->objs + n + c - s, temp, s * sizeof(_cups_ps_obj_t));
974 }
975 else
976 {
ef416fc2 977 /*
b86bc4cf 978 * Shift up...
ef416fc2 979 */
980
b86bc4cf 981 if ((temp = calloc(s, sizeof(_cups_ps_obj_t))) == NULL)
982 return (-1);
ef416fc2 983
b86bc4cf 984 memcpy(temp, st->objs + n + c - s, s * sizeof(_cups_ps_obj_t));
985 memmove(st->objs + n + s, st->objs + n,
986 (c - s) * sizeof(_cups_ps_obj_t));
987 memcpy(st->objs + n, temp, s * sizeof(_cups_ps_obj_t));
988 }
ef416fc2 989
b86bc4cf 990 free(temp);
991
992 return (0);
993}
ef416fc2 994
ef416fc2 995
b86bc4cf 996/*
997 * 'scan_ps()' - Scan a string for the next PS object.
998 */
999
1000static _cups_ps_obj_t * /* O - New object or NULL on EOF */
1001scan_ps(_cups_ps_stack_t *st, /* I - Stack */
1002 char **ptr) /* IO - String pointer */
1003{
1004 _cups_ps_obj_t obj; /* Current object */
1005 char *start, /* Start of object */
1006 *cur, /* Current position */
1007 *valptr, /* Pointer into value string */
1008 *valend; /* End of value string */
1009 int parens; /* Parenthesis nesting level */
ef416fc2 1010
ef416fc2 1011
b86bc4cf 1012 /*
1013 * Skip leading whitespace...
1014 */
1015
1016 for (cur = *ptr; *cur; cur ++)
1017 {
1018 if (*cur == '%')
ef416fc2 1019 {
1020 /*
b86bc4cf 1021 * Comment, skip to end of line...
ef416fc2 1022 */
1023
b86bc4cf 1024 for (cur ++; *cur && *cur != '\n' && *cur != '\r'; cur ++);
b0f6947b
MS
1025
1026 if (!*cur)
1027 cur --;
b86bc4cf 1028 }
1029 else if (!isspace(*cur & 255))
1030 break;
1031 }
ef416fc2 1032
b86bc4cf 1033 if (!*cur)
1034 {
1035 *ptr = NULL;
ef416fc2 1036
b86bc4cf 1037 return (NULL);
1038 }
ef416fc2 1039
b86bc4cf 1040 /*
1041 * See what we have...
1042 */
ef416fc2 1043
b86bc4cf 1044 memset(&obj, 0, sizeof(obj));
ef416fc2 1045
b86bc4cf 1046 switch (*cur)
1047 {
1048 case '(' : /* (string) */
1049 obj.type = CUPS_PS_STRING;
1050 start = cur;
1051
1052 for (cur ++, parens = 1, valptr = obj.value.string,
1053 valend = obj.value.string + sizeof(obj.value.string) - 1;
1054 *cur;
1055 cur ++)
1056 {
1057 if (*cur == ')' && parens == 1)
1058 break;
1059
1060 if (*cur == '(')
1061 parens ++;
1062 else if (*cur == ')')
1063 parens --;
1064
1065 if (valptr >= valend)
1066 {
1067 *ptr = start;
1068
1069 return (NULL);
1070 }
1071
1072 if (*cur == '\\')
1073 {
1074 /*
1075 * Decode escaped character...
1076 */
1077
1078 cur ++;
1079
1080 if (*cur == 'b')
1081 *valptr++ = '\b';
1082 else if (*cur == 'f')
1083 *valptr++ = '\f';
1084 else if (*cur == 'n')
1085 *valptr++ = '\n';
1086 else if (*cur == 'r')
1087 *valptr++ = '\r';
1088 else if (*cur == 't')
1089 *valptr++ = '\t';
1090 else if (*cur >= '0' && *cur <= '7')
1091 {
1092 int ch = *cur - '0';
1093
1094 if (cur[1] >= '0' && cur[1] <= '7')
1095 {
1096 cur ++;
1097 ch = (ch << 3) + *cur - '0';
1098 }
1099
1100 if (cur[1] >= '0' && cur[1] <= '7')
1101 {
1102 cur ++;
1103 ch = (ch << 3) + *cur - '0';
1104 }
1105
1106 *valptr++ = ch;
1107 }
1108 else if (*cur == '\r')
1109 {
1110 if (cur[1] == '\n')
1111 cur ++;
1112 }
1113 else if (*cur != '\n')
1114 *valptr++ = *cur;
1115 }
1116 else
1117 *valptr++ = *cur;
1118 }
1119
1120 if (*cur != ')')
1121 {
1122 *ptr = start;
1123
1124 return (NULL);
1125 }
1126
1127 cur ++;
1128 break;
1129
1130 case '[' : /* Start array */
1131 obj.type = CUPS_PS_START_ARRAY;
1132 cur ++;
1133 break;
1134
1135 case ']' : /* End array */
1136 obj.type = CUPS_PS_END_ARRAY;
1137 cur ++;
1138 break;
1139
1140 case '<' : /* Start dictionary or hex string */
1141 if (cur[1] == '<')
1142 {
1143 obj.type = CUPS_PS_START_DICT;
1144 cur += 2;
1145 }
ef416fc2 1146 else
b86bc4cf 1147 {
1148 obj.type = CUPS_PS_STRING;
1149 start = cur;
1150
1151 for (cur ++, valptr = obj.value.string,
1152 valend = obj.value.string + sizeof(obj.value.string) - 1;
1153 *cur;
1154 cur ++)
1155 {
1156 int ch; /* Current character */
1157
1158
1159
1160 if (*cur == '>')
1161 break;
1162 else if (valptr >= valend || !isxdigit(*cur & 255))
1163 {
1164 *ptr = start;
1165 return (NULL);
1166 }
1167
1168 if (*cur >= '0' && *cur <= '9')
1169 ch = (*cur - '0') << 4;
1170 else
1171 ch = (tolower(*cur) - 'a' + 10) << 4;
1172
1173 if (isxdigit(cur[1] & 255))
1174 {
1175 cur ++;
1176
1177 if (*cur >= '0' && *cur <= '9')
1178 ch |= *cur - '0';
1179 else
1180 ch |= tolower(*cur) - 'a' + 10;
1181 }
1182
1183 *valptr++ = ch;
1184 }
1185
1186 if (*cur != '>')
1187 {
1188 *ptr = start;
1189 return (NULL);
1190 }
1191
1192 cur ++;
1193 }
1194 break;
ef416fc2 1195
b86bc4cf 1196 case '>' : /* End dictionary? */
1197 if (cur[1] == '>')
1198 {
1199 obj.type = CUPS_PS_END_DICT;
1200 cur += 2;
1201 }
1202 else
1203 {
1204 obj.type = CUPS_PS_OTHER;
1205 obj.value.other[0] = *cur;
1206
1207 cur ++;
1208 }
1209 break;
1210
1211 case '{' : /* Start procedure */
1212 obj.type = CUPS_PS_START_PROC;
1213 cur ++;
1214 break;
1215
1216 case '}' : /* End procedure */
1217 obj.type = CUPS_PS_END_PROC;
1218 cur ++;
1219 break;
1220
1221 case '-' : /* Possible number */
1222 case '+' :
1223 if (!isdigit(cur[1] & 255) && cur[1] != '.')
1224 {
1225 obj.type = CUPS_PS_OTHER;
1226 obj.value.other[0] = *cur;
1227
1228 cur ++;
1229 break;
1230 }
1231
1232 case '0' : /* Number */
1233 case '1' :
1234 case '2' :
1235 case '3' :
1236 case '4' :
1237 case '5' :
1238 case '6' :
1239 case '7' :
1240 case '8' :
1241 case '9' :
1242 case '.' :
1243 obj.type = CUPS_PS_NUMBER;
1244
1245 start = cur;
1246 for (cur ++; *cur; cur ++)
1247 if (!isdigit(*cur & 255))
1248 break;
1249
1250 if (*cur == '#')
1251 {
1252 /*
1253 * Integer with radix...
1254 */
1255
1256 obj.value.number = strtol(cur + 1, &cur, atoi(start));
1257 break;
1258 }
1259 else if (strchr(".Ee()<>[]{}/%", *cur) || isspace(*cur & 255))
1260 {
1261 /*
1262 * Integer or real number...
1263 */
ef416fc2 1264
b86bc4cf 1265 obj.value.number = _cupsStrScand(start, &cur, localeconv());
1266 break;
1267 }
1268 else
1269 cur = start;
ef416fc2 1270
b86bc4cf 1271 default : /* Operator/variable name */
1272 start = cur;
1273
1274 if (*cur == '/')
1275 {
1276 obj.type = CUPS_PS_NAME;
1277 valptr = obj.value.name;
1278 valend = obj.value.name + sizeof(obj.value.name) - 1;
1279 cur ++;
1280 }
ef416fc2 1281 else
b86bc4cf 1282 {
1283 obj.type = CUPS_PS_OTHER;
1284 valptr = obj.value.other;
1285 valend = obj.value.other + sizeof(obj.value.other) - 1;
1286 }
ef416fc2 1287
b86bc4cf 1288 while (*cur)
1289 {
1290 if (strchr("()<>[]{}/%", *cur) || isspace(*cur & 255))
1291 break;
1292 else if (valptr < valend)
1293 *valptr++ = *cur++;
1294 else
1295 {
1296 *ptr = start;
1297 return (NULL);
1298 }
1299 }
1300
1301 if (obj.type == CUPS_PS_OTHER)
1302 {
1303 if (!strcmp(obj.value.other, "true"))
1304 {
1305 obj.type = CUPS_PS_BOOLEAN;
1306 obj.value.boolean = 1;
1307 }
1308 else if (!strcmp(obj.value.other, "false"))
1309 {
1310 obj.type = CUPS_PS_BOOLEAN;
1311 obj.value.boolean = 0;
1312 }
1313 else if (!strcmp(obj.value.other, "null"))
1314 obj.type = CUPS_PS_NULL;
1315 else if (!strcmp(obj.value.other, "cleartomark"))
1316 obj.type = CUPS_PS_CLEARTOMARK;
1317 else if (!strcmp(obj.value.other, "copy"))
1318 obj.type = CUPS_PS_COPY;
1319 else if (!strcmp(obj.value.other, "dup"))
1320 obj.type = CUPS_PS_DUP;
1321 else if (!strcmp(obj.value.other, "index"))
1322 obj.type = CUPS_PS_INDEX;
1323 else if (!strcmp(obj.value.other, "pop"))
1324 obj.type = CUPS_PS_POP;
1325 else if (!strcmp(obj.value.other, "roll"))
1326 obj.type = CUPS_PS_ROLL;
1327 else if (!strcmp(obj.value.other, "setpagedevice"))
1328 obj.type = CUPS_PS_SETPAGEDEVICE;
1329 else if (!strcmp(obj.value.other, "stopped"))
1330 obj.type = CUPS_PS_STOPPED;
1331 }
1332 break;
1333 }
1334
1335 /*
1336 * Save the current position in the string and return the new object...
1337 */
1338
1339 *ptr = cur;
1340
1341 return (push_stack(st, &obj));
1342}
1343
1344
1345/*
1346 * 'setpagedevice()' - Simulate the PostScript setpagedevice operator.
1347 */
1348
1349static int /* O - 0 on success, -1 on error */
1350setpagedevice(
1351 _cups_ps_stack_t *st, /* I - Stack */
1352 cups_page_header2_t *h, /* O - Page header */
1353 int *preferred_bits)/* O - Preferred bits per color */
1354{
1355 int i; /* Index into array */
1356 _cups_ps_obj_t *obj, /* Current object */
1357 *end; /* End of dictionary */
1358 const char *name; /* Attribute name */
1359
1360
1361 /*
1362 * Make sure we have a dictionary on the stack...
1363 */
1364
1365 if (st->num_objs == 0)
1366 return (-1);
1367
1368 obj = end = st->objs + st->num_objs - 1;
1369
1370 if (obj->type != CUPS_PS_END_DICT)
1371 return (-1);
1372
1373 obj --;
1374
1375 while (obj > st->objs)
1376 {
1377 if (obj->type == CUPS_PS_START_DICT)
1378 break;
1379
1380 obj --;
1381 }
1382
1383 if (obj < st->objs)
1384 return (-1);
ef416fc2 1385
b86bc4cf 1386 /*
1387 * Found the start of the dictionary, empty the stack to this point...
1388 */
1389
1390 st->num_objs = obj - st->objs;
1391
1392 /*
1393 * Now pull /name and value pairs from the dictionary...
1394 */
1395
ae71f5de 1396 DEBUG_puts("setpagedevice: Dictionary:");
b86bc4cf 1397
1398 for (obj ++; obj < end; obj ++)
1399 {
ef416fc2 1400 /*
b86bc4cf 1401 * Grab the name...
ef416fc2 1402 */
1403
b86bc4cf 1404 if (obj->type != CUPS_PS_NAME)
1405 return (-1);
1406
1407 name = obj->value.name;
1408 obj ++;
1409
1410#ifdef DEBUG
ae71f5de 1411 DEBUG_printf(("setpagedevice: /%s ", name));
b86bc4cf 1412 DEBUG_object(obj);
b86bc4cf 1413#endif /* DEBUG */
1414
1415 /*
1416 * Then grab the value...
1417 */
1418
1419 if (!strcmp(name, "MediaClass") && obj->type == CUPS_PS_STRING)
1420 strlcpy(h->MediaClass, obj->value.string, sizeof(h->MediaClass));
1421 else if (!strcmp(name, "MediaColor") && obj->type == CUPS_PS_STRING)
1422 strlcpy(h->MediaColor, obj->value.string, sizeof(h->MediaColor));
1423 else if (!strcmp(name, "MediaType") && obj->type == CUPS_PS_STRING)
1424 strlcpy(h->MediaType, obj->value.string, sizeof(h->MediaType));
1425 else if (!strcmp(name, "OutputType") && obj->type == CUPS_PS_STRING)
1426 strlcpy(h->OutputType, obj->value.string, sizeof(h->OutputType));
1427 else if (!strcmp(name, "AdvanceDistance") && obj->type == CUPS_PS_NUMBER)
1428 h->AdvanceDistance = (unsigned)obj->value.number;
1429 else if (!strcmp(name, "AdvanceMedia") && obj->type == CUPS_PS_NUMBER)
1430 h->AdvanceMedia = (unsigned)obj->value.number;
1431 else if (!strcmp(name, "Collate") && obj->type == CUPS_PS_BOOLEAN)
1432 h->Collate = (unsigned)obj->value.boolean;
1433 else if (!strcmp(name, "CutMedia") && obj->type == CUPS_PS_NUMBER)
1434 h->CutMedia = (cups_cut_t)(unsigned)obj->value.number;
1435 else if (!strcmp(name, "Duplex") && obj->type == CUPS_PS_BOOLEAN)
1436 h->Duplex = (unsigned)obj->value.boolean;
1437 else if (!strcmp(name, "HWResolution") && obj->type == CUPS_PS_START_ARRAY)
ef416fc2 1438 {
b86bc4cf 1439 if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
1440 obj[3].type == CUPS_PS_END_ARRAY)
1441 {
1442 h->HWResolution[0] = (unsigned)obj[1].value.number;
1443 h->HWResolution[1] = (unsigned)obj[2].value.number;
1444 obj += 3;
1445 }
1446 else
ef416fc2 1447 return (-1);
1448 }
b86bc4cf 1449 else if (!strcmp(name, "InsertSheet") && obj->type == CUPS_PS_BOOLEAN)
1450 h->InsertSheet = (unsigned)obj->value.boolean;
1451 else if (!strcmp(name, "Jog") && obj->type == CUPS_PS_NUMBER)
1452 h->Jog = (unsigned)obj->value.number;
1453 else if (!strcmp(name, "LeadingEdge") && obj->type == CUPS_PS_NUMBER)
1454 h->LeadingEdge = (unsigned)obj->value.number;
1455 else if (!strcmp(name, "ManualFeed") && obj->type == CUPS_PS_BOOLEAN)
1456 h->ManualFeed = (unsigned)obj->value.boolean;
09a101d6 1457 else if ((!strcmp(name, "cupsMediaPosition") ||
b86bc4cf 1458 !strcmp(name, "MediaPosition")) && obj->type == CUPS_PS_NUMBER)
09a101d6 1459 {
1460 /*
1461 * cupsMediaPosition is supported for backwards compatibility only.
1462 * We added it back in the Ghostscript 5.50 days to work around a
1463 * bug in Ghostscript WRT handling of MediaPosition and setpagedevice.
1464 *
1465 * All new development should set MediaPosition...
1466 */
1467
b86bc4cf 1468 h->MediaPosition = (unsigned)obj->value.number;
09a101d6 1469 }
b86bc4cf 1470 else if (!strcmp(name, "MediaWeight") && obj->type == CUPS_PS_NUMBER)
1471 h->MediaWeight = (unsigned)obj->value.number;
1472 else if (!strcmp(name, "MirrorPrint") && obj->type == CUPS_PS_BOOLEAN)
1473 h->MirrorPrint = (unsigned)obj->value.boolean;
1474 else if (!strcmp(name, "NegativePrint") && obj->type == CUPS_PS_BOOLEAN)
1475 h->NegativePrint = (unsigned)obj->value.boolean;
1476 else if (!strcmp(name, "NumCopies") && obj->type == CUPS_PS_NUMBER)
1477 h->NumCopies = (unsigned)obj->value.number;
1478 else if (!strcmp(name, "Orientation") && obj->type == CUPS_PS_NUMBER)
1479 h->Orientation = (unsigned)obj->value.number;
1480 else if (!strcmp(name, "OutputFaceUp") && obj->type == CUPS_PS_BOOLEAN)
1481 h->OutputFaceUp = (unsigned)obj->value.boolean;
1482 else if (!strcmp(name, "PageSize") && obj->type == CUPS_PS_START_ARRAY)
ef416fc2 1483 {
b86bc4cf 1484 if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
1485 obj[3].type == CUPS_PS_END_ARRAY)
1486 {
c8fef167
MS
1487 h->cupsPageSize[0] = (float)obj[1].value.number;
1488 h->cupsPageSize[1] = (float)obj[2].value.number;
b86bc4cf 1489
1490 h->PageSize[0] = (unsigned)obj[1].value.number;
1491 h->PageSize[1] = (unsigned)obj[2].value.number;
1492
1493 obj += 3;
1494 }
1495 else
fa73b229 1496 return (-1);
ef416fc2 1497 }
b86bc4cf 1498 else if (!strcmp(name, "Separations") && obj->type == CUPS_PS_BOOLEAN)
1499 h->Separations = (unsigned)obj->value.boolean;
1500 else if (!strcmp(name, "TraySwitch") && obj->type == CUPS_PS_BOOLEAN)
1501 h->TraySwitch = (unsigned)obj->value.boolean;
1502 else if (!strcmp(name, "Tumble") && obj->type == CUPS_PS_BOOLEAN)
1503 h->Tumble = (unsigned)obj->value.boolean;
1504 else if (!strcmp(name, "cupsMediaType") && obj->type == CUPS_PS_NUMBER)
1505 h->cupsMediaType = (unsigned)obj->value.number;
1506 else if (!strcmp(name, "cupsBitsPerColor") && obj->type == CUPS_PS_NUMBER)
1507 h->cupsBitsPerColor = (unsigned)obj->value.number;
1508 else if (!strcmp(name, "cupsPreferredBitsPerColor") &&
1509 obj->type == CUPS_PS_NUMBER)
1510 *preferred_bits = (int)obj->value.number;
1511 else if (!strcmp(name, "cupsColorOrder") && obj->type == CUPS_PS_NUMBER)
1512 h->cupsColorOrder = (cups_order_t)(unsigned)obj->value.number;
1513 else if (!strcmp(name, "cupsColorSpace") && obj->type == CUPS_PS_NUMBER)
1514 h->cupsColorSpace = (cups_cspace_t)(unsigned)obj->value.number;
1515 else if (!strcmp(name, "cupsCompression") && obj->type == CUPS_PS_NUMBER)
1516 h->cupsCompression = (unsigned)obj->value.number;
1517 else if (!strcmp(name, "cupsRowCount") && obj->type == CUPS_PS_NUMBER)
1518 h->cupsRowCount = (unsigned)obj->value.number;
1519 else if (!strcmp(name, "cupsRowFeed") && obj->type == CUPS_PS_NUMBER)
1520 h->cupsRowFeed = (unsigned)obj->value.number;
1521 else if (!strcmp(name, "cupsRowStep") && obj->type == CUPS_PS_NUMBER)
1522 h->cupsRowStep = (unsigned)obj->value.number;
923edb68 1523 else if (!strcmp(name, "cupsBorderlessScalingFactor") &&
b86bc4cf 1524 obj->type == CUPS_PS_NUMBER)
c8fef167 1525 h->cupsBorderlessScalingFactor = (float)obj->value.number;
b86bc4cf 1526 else if (!strncmp(name, "cupsInteger", 11) && obj->type == CUPS_PS_NUMBER)
ef416fc2 1527 {
b86bc4cf 1528 if ((i = atoi(name + 11)) < 0 || i > 15)
ef416fc2 1529 return (-1);
1530
b86bc4cf 1531 h->cupsInteger[i] = (unsigned)obj->value.number;
ef416fc2 1532 }
b86bc4cf 1533 else if (!strncmp(name, "cupsReal", 8) && obj->type == CUPS_PS_NUMBER)
ef416fc2 1534 {
b86bc4cf 1535 if ((i = atoi(name + 8)) < 0 || i > 15)
ef416fc2 1536 return (-1);
1537
c8fef167 1538 h->cupsReal[i] = (float)obj->value.number;
ef416fc2 1539 }
b86bc4cf 1540 else if (!strncmp(name, "cupsString", 10) && obj->type == CUPS_PS_STRING)
ef416fc2 1541 {
b86bc4cf 1542 if ((i = atoi(name + 10)) < 0 || i > 15)
ef416fc2 1543 return (-1);
1544
b86bc4cf 1545 strlcpy(h->cupsString[i], obj->value.string, sizeof(h->cupsString[i]));
ef416fc2 1546 }
b86bc4cf 1547 else if (!strcmp(name, "cupsMarkerType") && obj->type == CUPS_PS_STRING)
1548 strlcpy(h->cupsMarkerType, obj->value.string, sizeof(h->cupsMarkerType));
1549 else if (!strcmp(name, "cupsPageSizeName") && obj->type == CUPS_PS_STRING)
1550 strlcpy(h->cupsPageSizeName, obj->value.string,
1551 sizeof(h->cupsPageSizeName));
1552 else if (!strcmp(name, "cupsRenderingIntent") &&
1553 obj->type == CUPS_PS_STRING)
1554 strlcpy(h->cupsRenderingIntent, obj->value.string,
1555 sizeof(h->cupsRenderingIntent));
1556 else
ef416fc2 1557 {
b86bc4cf 1558 /*
1559 * Ignore unknown name+value...
1560 */
1561
1562 DEBUG_printf((" Unknown name (\"%s\") or value...\n", name));
1563
1564 while (obj[1].type != CUPS_PS_NAME && obj < end)
1565 obj ++;
ef416fc2 1566 }
ef416fc2 1567 }
1568
ef416fc2 1569 return (0);
1570}
1571
1572
b86bc4cf 1573#ifdef DEBUG
1574/*
1575 * 'DEBUG_object()' - Print an object's value...
1576 */
1577
1578static void
1579DEBUG_object(_cups_ps_obj_t *obj) /* I - Object to print */
1580{
1581 switch (obj->type)
1582 {
1583 case CUPS_PS_NAME :
ae71f5de 1584 DEBUG_printf(("/%s\n", obj->value.name));
b86bc4cf 1585 break;
1586
1587 case CUPS_PS_NUMBER :
ae71f5de 1588 DEBUG_printf(("%g\n", obj->value.number));
b86bc4cf 1589 break;
1590
1591 case CUPS_PS_STRING :
ae71f5de 1592 DEBUG_printf(("(%s)\n", obj->value.string));
b86bc4cf 1593 break;
1594
1595 case CUPS_PS_BOOLEAN :
1596 if (obj->value.boolean)
ae71f5de 1597 DEBUG_puts("true");
b86bc4cf 1598 else
ae71f5de 1599 DEBUG_puts("false");
b86bc4cf 1600 break;
1601
1602 case CUPS_PS_NULL :
ae71f5de 1603 DEBUG_puts("null");
b86bc4cf 1604 break;
1605
1606 case CUPS_PS_START_ARRAY :
ae71f5de 1607 DEBUG_puts("[");
b86bc4cf 1608 break;
1609
1610 case CUPS_PS_END_ARRAY :
ae71f5de 1611 DEBUG_puts("]");
b86bc4cf 1612 break;
1613
1614 case CUPS_PS_START_DICT :
ae71f5de 1615 DEBUG_puts("<<");
b86bc4cf 1616 break;
1617
1618 case CUPS_PS_END_DICT :
ae71f5de 1619 DEBUG_puts(">>");
b86bc4cf 1620 break;
1621
1622 case CUPS_PS_START_PROC :
ae71f5de 1623 DEBUG_puts("{");
b86bc4cf 1624 break;
1625
1626 case CUPS_PS_END_PROC :
ae71f5de 1627 DEBUG_puts("}");
b86bc4cf 1628 break;
1629
1630 case CUPS_PS_CLEARTOMARK :
ae71f5de 1631 DEBUG_puts("--cleartomark--");
b86bc4cf 1632 break;
1633
1634 case CUPS_PS_COPY :
ae71f5de 1635 DEBUG_puts("--copy--");
b86bc4cf 1636 break;
1637
1638 case CUPS_PS_DUP :
ae71f5de 1639 DEBUG_puts("--dup--");
b86bc4cf 1640 break;
1641
1642 case CUPS_PS_INDEX :
ae71f5de 1643 DEBUG_puts("--index--");
b86bc4cf 1644 break;
1645
1646 case CUPS_PS_POP :
ae71f5de 1647 DEBUG_puts("--pop--");
b86bc4cf 1648 break;
1649
1650 case CUPS_PS_ROLL :
ae71f5de 1651 DEBUG_puts("--roll--");
b86bc4cf 1652 break;
1653
1654 case CUPS_PS_SETPAGEDEVICE :
ae71f5de 1655 DEBUG_puts("--setpagedevice--");
b86bc4cf 1656 break;
1657
1658 case CUPS_PS_STOPPED :
ae71f5de 1659 DEBUG_puts("--stopped--");
b86bc4cf 1660 break;
1661
1662 case CUPS_PS_OTHER :
ae71f5de 1663 DEBUG_printf(("--%s--\n", obj->value.other));
b86bc4cf 1664 break;
1665 }
1666}
1667
1668
1669/*
1670 * 'DEBUG_stack()' - Print a stack...
1671 */
1672
1673static void
1674DEBUG_stack(_cups_ps_stack_t *st) /* I - Stack */
1675{
1676 int c; /* Looping var */
1677 _cups_ps_obj_t *obj; /* Current object on stack */
1678
1679
1680 for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
b86bc4cf 1681 DEBUG_object(obj);
b86bc4cf 1682}
1683#endif /* DEBUG */
1684
1685
ef416fc2 1686/*
b19ccc9e 1687 * End of "$Id: interpret.c 7852 2008-08-21 04:19:45Z mike $".
ef416fc2 1688 */