File indexing completed on 2024-05-12 04:20:03
0001 /* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved. 0002 0003 This file is part of GSview. 0004 0005 This file is distributed in the hope that it will be useful, but 0006 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility 0007 to anyone for the consequences of using it or for whether it serves any 0008 particular purpose or works at all, unless he says so in writing. Refer 0009 to the GNU General Public License for full details. 0010 0011 Everyone is granted permission to copy, modify and redistribute this 0012 file, but only under the conditions described in the GNU General 0013 Public License. A copy of this license is supposed to have been given 0014 to you along with this file so you can know your rights and 0015 responsibilities. It should be in a file named COPYING. Among other 0016 things, the copyright notice and this notice must be preserved on all 0017 copies. 0018 */ 0019 0020 /* $Id$ */ 0021 0022 /* dscparse.c - DSC parser */ 0023 0024 /* 0025 * This is a DSC parser, based on the DSC 3.0 spec, 0026 * with a few DSC 2.1 additions for page size. 0027 * 0028 * Current limitations: 0029 * %%+ may be used after any comment in the comment or trailer, 0030 * but is currently only supported by 0031 * %%DocumentMedia 0032 * 0033 * DSC 2.1 additions (discontinued in DSC 3.0): 0034 * %%DocumentPaperColors: 0035 * %%DocumentPaperForms: 0036 * %%DocumentPaperSizes: 0037 * %%DocumentPaperWeights: 0038 * %%PaperColor: (ignored) 0039 * %%PaperForm: (ignored) 0040 * %%PaperSize: 0041 * %%PaperWeight: (ignored) 0042 * 0043 * Other additions for defaults or page section 0044 % %%ViewingOrientation: xx xy yx yy 0045 */ 0046 0047 #include <stdio.h> /* for sprintf(), not file I/O */ 0048 #include <stdlib.h> 0049 #include <string.h> 0050 #include <ctype.h> 0051 0052 #define MAXSTR 256 0053 0054 #include "dscparse.h" 0055 0056 /* Macros for comparing string literals 0057 * For maximum speed, the length of the second macro argument is 0058 * computed at compile time. 0059 * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL. 0060 */ 0061 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0) 0062 #define IS_DSC(line, str) (COMPARE((line), (str))) 0063 0064 /* Macros for comparing the first one or two characters */ 0065 #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t')) 0066 #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n')) 0067 #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch)) 0068 #define IS_BLANK(str) (IS_EOL(str[0])) 0069 #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%')) 0070 0071 /* Macros for document offset to start and end of line */ 0072 #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length) 0073 #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index) 0074 0075 /* dsc_scan_SECTION() functions return one of 0076 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC 0077 * or one of the following 0078 */ 0079 /* The line should be passed on to the next section parser. */ 0080 #define CDSC_PROPAGATE 10 0081 0082 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */ 0083 #define CDSC_NEEDMORE 11 0084 0085 /* local prototypes */ 0086 dsc_private void * dsc_memalloc(P2(CDSC *dsc, size_t size)); 0087 dsc_private void dsc_memfree(P2(CDSC*dsc, void *ptr)); 0088 dsc_private CDSC * dsc_init2(P1(CDSC *dsc)); 0089 dsc_private void dsc_reset(P1(CDSC *dsc)); 0090 dsc_private void dsc_section_join(P3(unsigned long begin, unsigned long *pend, unsigned long **pplast)); 0091 dsc_private int dsc_read_line(P1(CDSC *dsc)); 0092 dsc_private int dsc_read_doseps(P1(CDSC *dsc)); 0093 dsc_private char * dsc_alloc_string(P3(CDSC *dsc, const char *str, int len)); 0094 dsc_private char * dsc_add_line(P3(CDSC *dsc, const char *line, unsigned int len)); 0095 dsc_private char * dsc_copy_string(P5(char *str, unsigned int slen, 0096 char *line, unsigned int len, unsigned int *offset)); 0097 dsc_private GSDWORD dsc_get_dword(P1(const unsigned char *buf)); 0098 dsc_private GSWORD dsc_get_word(P1(const unsigned char *buf)); 0099 dsc_private int dsc_get_int(P3(const char *line, unsigned int len, unsigned int *offset)); 0100 dsc_private float dsc_get_real(P3(const char *line, unsigned int len, 0101 unsigned int *offset)); 0102 dsc_private int dsc_stricmp(P2(const char *s, const char *t)); 0103 dsc_private void dsc_unknown(P1(CDSC *dsc)); 0104 dsc_private GSBOOL dsc_is_section(char *line); 0105 dsc_private int dsc_parse_pages(P1(CDSC *dsc)); 0106 dsc_private int dsc_parse_bounding_box(P3(CDSC *dsc, CDSCBBOX** pbbox, int offset)); 0107 dsc_private int dsc_parse_float_bounding_box(P3(CDSC *dsc, CDSCFBBOX** pfbbox, int offset)); 0108 dsc_private int dsc_parse_orientation(P3(CDSC *dsc, unsigned int *porientation, 0109 int offset)); 0110 dsc_private int dsc_parse_order(P1(CDSC *dsc)); 0111 dsc_private int dsc_parse_media(P2(CDSC *dsc, const CDSCMEDIA **page_media)); 0112 dsc_private int dsc_parse_document_media(P1(CDSC *dsc)); 0113 dsc_private int dsc_parse_viewing_orientation(P2(CDSC *dsc, CDSCCTM **pctm)); 0114 dsc_private int dsc_parse_page(P1(CDSC *dsc)); 0115 dsc_private void dsc_save_line(P1(CDSC *dsc)); 0116 dsc_private int dsc_scan_type(P1(CDSC *dsc)); 0117 dsc_private int dsc_scan_comments(P1(CDSC *dsc)); 0118 dsc_private int dsc_scan_preview(P1(CDSC *dsc)); 0119 dsc_private int dsc_scan_defaults(P1(CDSC *dsc)); 0120 dsc_private int dsc_scan_prolog(P1(CDSC *dsc)); 0121 dsc_private int dsc_scan_setup(P1(CDSC *dsc)); 0122 dsc_private int dsc_scan_page(P1(CDSC *dsc)); 0123 dsc_private int dsc_scan_trailer(P1(CDSC *dsc)); 0124 dsc_private int dsc_error(P4(CDSC *dsc, unsigned int explanation, 0125 char *line, unsigned int line_len)); 0126 0127 /* DSC error reporting */ 0128 dsc_private const int dsc_severity[] = { 0129 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */ 0130 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */ 0131 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */ 0132 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */ 0133 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */ 0134 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */ 0135 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */ 0136 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */ 0137 CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */ 0138 CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */ 0139 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */ 0140 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */ 0141 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */ 0142 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */ 0143 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */ 0144 CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */ 0145 0 0146 }; 0147 0148 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2) 0149 0150 const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = { 0151 /* These sizes taken from Ghostscript gs_statd.ps */ 0152 {"11x17", 792, 1224, 0, NULL, NULL, NULL}, 0153 {"A0", 2380, 3368, 0, NULL, NULL, NULL}, 0154 {"A1", 1684, 2380, 0, NULL, NULL, NULL}, 0155 {"A2", 1190, 1684, 0, NULL, NULL, NULL}, 0156 {"A3", 842, 1190, 0, NULL, NULL, NULL}, 0157 {"A4", 595, 842, 0, NULL, NULL, NULL}, 0158 {"A5", 421, 595, 0, NULL, NULL, NULL}, 0159 {"A6", 297, 421, 0, NULL, NULL, NULL}, 0160 {"A7", 210, 297, 0, NULL, NULL, NULL}, 0161 {"A8", 148, 210, 0, NULL, NULL, NULL}, 0162 {"A9", 105, 148, 0, NULL, NULL, NULL}, 0163 {"A10", 74, 105, 0, NULL, NULL, NULL}, 0164 {"B0", 2836, 4008, 0, NULL, NULL, NULL}, 0165 {"B1", 2004, 2836, 0, NULL, NULL, NULL}, 0166 {"B2", 1418, 2004, 0, NULL, NULL, NULL}, 0167 {"B3", 1002, 1418, 0, NULL, NULL, NULL}, 0168 {"B4", 709, 1002, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */ 0169 {"B5", 501, 709, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */ 0170 {"B6", 354, 501, 0, NULL, NULL, NULL}, 0171 {"C0", 2600, 3677, 0, NULL, NULL, NULL}, 0172 {"C1", 1837, 2600, 0, NULL, NULL, NULL}, 0173 {"C2", 1298, 1837, 0, NULL, NULL, NULL}, 0174 {"C3", 918, 1298, 0, NULL, NULL, NULL}, 0175 {"C4", 649, 918, 0, NULL, NULL, NULL}, 0176 {"C5", 459, 649, 0, NULL, NULL, NULL}, 0177 {"C6", 323, 459, 0, NULL, NULL, NULL}, 0178 {"Ledger", 1224, 792, 0, NULL, NULL, NULL}, 0179 {"Legal", 612, 1008, 0, NULL, NULL, NULL}, 0180 {"Letter", 612, 792, 0, NULL, NULL, NULL}, 0181 {"Note", 612, 792, 0, NULL, NULL, NULL}, 0182 // ISO and JIS B sizes are different.... 0183 {"jisb0", 2916, 4128, 0, NULL, NULL, NULL}, 0184 {"jisb1", 2064, 2916, 0, NULL, NULL, NULL}, 0185 {"jisb2", 1458, 2064, 0, NULL, NULL, NULL}, 0186 {"jisb3", 1032, 1458, 0, NULL, NULL, NULL}, 0187 {"jisb4", 729, 1032, 0, NULL, NULL, NULL}, 0188 {"jisb5", 516, 729, 0, NULL, NULL, NULL}, 0189 {"jisb6", 363, 516, 0, NULL, NULL, NULL}, 0190 // U.S. CAD standard paper sizes 0191 {"archE", 2592, 3456, 0, NULL, NULL, NULL}, 0192 {"archD", 1728, 2592, 0, NULL, NULL, NULL}, 0193 {"archC", 1296, 1728, 0, NULL, NULL, NULL}, 0194 {"archB", 864, 1296, 0, NULL, NULL, NULL}, 0195 {"archA", 648, 864, 0, NULL, NULL, NULL}, 0196 // Other paper sizes 0197 {"flsa", 612, 936, 0, NULL, NULL, NULL}, /* U.S. foolscap */ 0198 {"flse", 612, 936, 0, NULL, NULL, NULL}, /* European foolscap */ 0199 {"halfletter", 396, 612, 0, NULL, NULL, NULL}, 0200 {NULL, 0, 0, 0, NULL, NULL, NULL} 0201 }; 0202 0203 /* parser state */ 0204 enum CDSC_SCAN_SECTION { 0205 scan_none = 0, 0206 scan_comments = 1, 0207 scan_pre_preview = 2, 0208 scan_preview = 3, 0209 scan_pre_defaults = 4, 0210 scan_defaults = 5, 0211 scan_pre_prolog = 6, 0212 scan_prolog = 7, 0213 scan_pre_setup = 8, 0214 scan_setup = 9, 0215 scan_pre_pages = 10, 0216 scan_pages = 11, 0217 scan_pre_trailer = 12, 0218 scan_trailer = 13, 0219 scan_eof = 14 0220 }; 0221 0222 static const char * const dsc_scan_section_name[15] = { 0223 "Type", "Comments", 0224 "pre-Preview", "Preview", 0225 "pre-Defaults", "Defaults", 0226 "pre-Prolog", "Prolog", 0227 "pre-Setup", "Setup", 0228 "pre-Page", "Page", 0229 "pre-Trailer", "Trailer", 0230 "EOF" 0231 }; 0232 0233 /******************************************************************/ 0234 /* Public functions */ 0235 /******************************************************************/ 0236 0237 /* constructor */ 0238 CDSC * 0239 dsc_init(void *caller_data) 0240 { 0241 CDSC *dsc = (CDSC *)malloc(sizeof(CDSC)); 0242 if (dsc == NULL) 0243 return NULL; 0244 memset(dsc, 0, sizeof(CDSC)); 0245 dsc->caller_data = caller_data; 0246 0247 return dsc_init2(dsc); 0248 } 0249 0250 /* constructor, with caller supplied memalloc */ 0251 CDSC * 0252 dsc_init_with_alloc( 0253 void *caller_data, 0254 void *(*memalloc)(size_t size, void *closure_data), 0255 void (*memfree)(void *ptr, void *closure_data), 0256 void *closure_data) 0257 { 0258 CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data); 0259 if (dsc == NULL) 0260 return NULL; 0261 memset(dsc, 0, sizeof(CDSC)); 0262 dsc->caller_data = caller_data; 0263 0264 dsc->memalloc = memalloc; 0265 dsc->memfree = memfree; 0266 dsc->mem_closure_data = closure_data; 0267 0268 return dsc_init2(dsc); 0269 } 0270 0271 0272 0273 /* destructor */ 0274 void 0275 dsc_free(CDSC *dsc) 0276 { 0277 if (dsc == NULL) 0278 return; 0279 dsc_reset(dsc); 0280 dsc_memfree(dsc, dsc); 0281 } 0282 0283 0284 /* Tell DSC parser how long document will be, to allow ignoring 0285 * of early %%Trailer and %%EOF. This is optional. 0286 */ 0287 void 0288 dsc_set_length(CDSC *dsc, unsigned long len) 0289 { 0290 dsc->file_length = len; 0291 } 0292 0293 /* Process a buffer containing DSC comments and PostScript */ 0294 /* Return value is < 0 for error, >=0 for OK. 0295 * CDSC_ERROR 0296 * CDSC_OK 0297 * CDSC_NOTDSC (DSC will be ignored) 0298 * other values indicate the last DSC comment read 0299 */ 0300 int 0301 dsc_scan_data(CDSC *dsc, const char *data, int length) 0302 { 0303 int bytes_read; 0304 int code = 0; 0305 0306 if (dsc == NULL) 0307 return CDSC_ERROR; 0308 0309 if (dsc->id == CDSC_NOTDSC) 0310 return CDSC_NOTDSC; 0311 dsc->id = CDSC_OK; 0312 if (dsc->eof) 0313 return CDSC_OK; /* ignore */ 0314 0315 if (length == 0) { 0316 /* EOF, so process what remains */ 0317 dsc->eof = TRUE; 0318 } 0319 0320 do { 0321 if (dsc->id == CDSC_NOTDSC) 0322 break; 0323 0324 if (length != 0) { 0325 /* move existing data if needed */ 0326 if (dsc->data_length > CDSC_DATA_LENGTH/2) { 0327 memmove(dsc->data, dsc->data + dsc->data_index, 0328 dsc->data_length - dsc->data_index); 0329 dsc->data_offset += dsc->data_index; 0330 dsc->data_length -= dsc->data_index; 0331 dsc->data_index = 0; 0332 } 0333 /* append to buffer */ 0334 bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length)); 0335 memcpy(dsc->data + dsc->data_length, data, bytes_read); 0336 dsc->data_length += bytes_read; 0337 data += bytes_read; 0338 length -= bytes_read; 0339 } 0340 if (dsc->scan_section == scan_none) { 0341 code = dsc_scan_type(dsc); 0342 if (code == CDSC_NEEDMORE) { 0343 /* need more characters before we can identify type */ 0344 code = CDSC_OK; 0345 break; 0346 } 0347 dsc->id = code; 0348 } 0349 0350 if (code == CDSC_NOTDSC) { 0351 dsc->id = CDSC_NOTDSC; 0352 break; 0353 } 0354 0355 while ((code = dsc_read_line(dsc)) > 0) { 0356 if (dsc->id == CDSC_NOTDSC) 0357 break; 0358 if (dsc->doseps_end && 0359 (dsc->data_offset + dsc->data_index > dsc->doseps_end)) { 0360 /* have read past end of DOS EPS PostScript section */ 0361 return CDSC_OK; /* ignore */ 0362 } 0363 if (dsc->eof) 0364 return CDSC_OK; 0365 if (dsc->skip_document) 0366 continue; /* embedded document */ 0367 if (dsc->skip_lines) 0368 continue; /* embedded lines */ 0369 if (IS_DSC(dsc->line, "%%BeginData:")) 0370 continue; 0371 if (IS_DSC(dsc->line, "%%BeginBinary:")) 0372 continue; 0373 if (IS_DSC(dsc->line, "%%EndDocument")) 0374 continue; 0375 if (IS_DSC(dsc->line, "%%EndData")) 0376 continue; 0377 if (IS_DSC(dsc->line, "%%EndBinary")) 0378 continue; 0379 0380 do { 0381 switch (dsc->scan_section) { 0382 case scan_comments: 0383 code = dsc_scan_comments(dsc); 0384 break; 0385 case scan_pre_preview: 0386 case scan_preview: 0387 code = dsc_scan_preview(dsc); 0388 break; 0389 case scan_pre_defaults: 0390 case scan_defaults: 0391 code = dsc_scan_defaults(dsc); 0392 break; 0393 case scan_pre_prolog: 0394 case scan_prolog: 0395 code = dsc_scan_prolog(dsc); 0396 break; 0397 case scan_pre_setup: 0398 case scan_setup: 0399 code = dsc_scan_setup(dsc); 0400 break; 0401 case scan_pre_pages: 0402 case scan_pages: 0403 code = dsc_scan_page(dsc); 0404 break; 0405 case scan_pre_trailer: 0406 case scan_trailer: 0407 code = dsc_scan_trailer(dsc); 0408 break; 0409 case scan_eof: 0410 code = CDSC_OK; 0411 break; 0412 default: 0413 /* invalid state */ 0414 code = CDSC_ERROR; 0415 } 0416 /* repeat if line is start of next section */ 0417 } while (code == CDSC_PROPAGATE); 0418 0419 /* if DOS EPS header not complete, ask for more */ 0420 if (code == CDSC_NEEDMORE) { 0421 code = CDSC_OK; 0422 break; 0423 } 0424 if (code == CDSC_NOTDSC) { 0425 dsc->id = CDSC_NOTDSC; 0426 break; 0427 } 0428 } 0429 } while (length != 0); 0430 0431 return (code < 0) ? code : dsc->id; 0432 } 0433 0434 /* Tidy up from incorrect DSC comments */ 0435 int 0436 dsc_fixup(CDSC *dsc) 0437 { 0438 unsigned int i; 0439 char buf[32]; 0440 unsigned long *last; 0441 0442 if (dsc->id == CDSC_NOTDSC) 0443 return 0; 0444 0445 /* flush last partial line */ 0446 dsc_scan_data(dsc, NULL, 0); 0447 0448 /* Fix DSC error: code between %%EndSetup and %%Page */ 0449 if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup) 0450 && (dsc->endsetup != dsc->beginsetup)) { 0451 dsc->endsetup = dsc->page[0].begin; 0452 dsc_debug_print(dsc, "Warning: code included between setup and first page\n"); 0453 } 0454 0455 /* Last page contained a false trailer, */ 0456 /* so extend last page to start of trailer */ 0457 if (dsc->page_count && (dsc->begintrailer != 0) && 0458 (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) { 0459 dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n"); 0460 dsc_debug_print(dsc, "and extending last page to start of trailer\n"); 0461 dsc->page[dsc->page_count-1].end = dsc->begintrailer; 0462 } 0463 0464 /* 0465 * Join up all sections. 0466 * There might be extra code between them, or we might have 0467 * missed including the \n which followed \r. 0468 */ 0469 last = &dsc->endcomments; 0470 dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last); 0471 dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last); 0472 dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last); 0473 dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last); 0474 for (i=0; i<dsc->page_count; i++) 0475 dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last); 0476 if (dsc->begintrailer) 0477 *last = dsc->begintrailer; 0478 0479 if ((dsc->page_pages == 0) && (dsc->page_count == 1)) { 0480 /* don't flag an error if %%Pages absent but one %%Page found */ 0481 /* adjust incorrect page count */ 0482 dsc->page_pages = dsc->page_count; 0483 } 0484 0485 /* Warnings and Errors that we can now identify */ 0486 if ((dsc->page_count != dsc->page_pages)) { 0487 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0); 0488 switch (rc) { 0489 case CDSC_RESPONSE_OK: 0490 /* adjust incorrect page count */ 0491 dsc->page_pages = dsc->page_count; 0492 break; 0493 case CDSC_RESPONSE_CANCEL: 0494 break;; 0495 case CDSC_RESPONSE_IGNORE_ALL: 0496 return CDSC_NOTDSC; 0497 } 0498 } 0499 0500 if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) { 0501 /* EPS files MUST include a BoundingBox */ 0502 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0); 0503 switch (rc) { 0504 case CDSC_RESPONSE_OK: 0505 /* Assume that it is EPS */ 0506 break; 0507 case CDSC_RESPONSE_CANCEL: 0508 /* Is NOT an EPS file */ 0509 dsc->epsf = FALSE; 0510 case CDSC_RESPONSE_IGNORE_ALL: 0511 return CDSC_NOTDSC; 0512 } 0513 } 0514 0515 if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) { 0516 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0); 0517 switch (rc) { 0518 case CDSC_RESPONSE_OK: 0519 /* Is an EPS file */ 0520 break; 0521 case CDSC_RESPONSE_CANCEL: 0522 /* Is NOT an EPS file */ 0523 dsc->epsf = FALSE; 0524 break; 0525 case CDSC_RESPONSE_IGNORE_ALL: 0526 return CDSC_NOTDSC; 0527 } 0528 } 0529 0530 if ((dsc->media_count == 1) && (dsc->page_media == NULL)) { 0531 /* if one only media was specified, and default page media */ 0532 /* was not specified, assume that default is the only media. */ 0533 dsc->page_media = dsc->media[0]; 0534 } 0535 0536 if ((dsc->media_count != 0) && (dsc->page_media == NULL)) { 0537 int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0); 0538 switch (rc) { 0539 case CDSC_RESPONSE_OK: 0540 /* default media is first listed */ 0541 dsc->page_media = dsc->media[0]; 0542 break; 0543 case CDSC_RESPONSE_CANCEL: 0544 /* No default media */ 0545 break; 0546 case CDSC_RESPONSE_IGNORE_ALL: 0547 return CDSC_NOTDSC; 0548 } 0549 } 0550 0551 /* make sure all pages have a label */ 0552 for (i=0; i<dsc->page_count; i++) { 0553 if (strlen(dsc->page[i].label) == 0) { 0554 sprintf(buf, "%d", i+1); 0555 if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, strlen(buf))) 0556 == (char *)NULL) 0557 return CDSC_ERROR; /* no memory */ 0558 } 0559 } 0560 return CDSC_OK; 0561 } 0562 0563 /* Install a function to be used for displaying messages about 0564 * DSC errors and warnings, and to request advice from user. 0565 * Installing an error function is optional. 0566 */ 0567 void 0568 dsc_set_error_function(CDSC *dsc, 0569 int (*fn)(P5(void *caller_data, CDSC *dsc, 0570 unsigned int explanation, const char *line, unsigned int line_len))) 0571 { 0572 dsc->dsc_error_fn = fn; 0573 } 0574 0575 0576 /* Install a function for printing debug messages */ 0577 /* This is optional */ 0578 void 0579 dsc_set_debug_function(CDSC *dsc, 0580 void (*debug_fn)(P2(void *caller_data, const char *str))) 0581 { 0582 dsc->debug_print_fn = debug_fn; 0583 } 0584 0585 /* Doesn't need to be public for PostScript documents */ 0586 /* Made public so GSview can add pages when processing PDF files */ 0587 int 0588 dsc_add_page(CDSC *dsc, int ordinal, char *label) 0589 { 0590 dsc->page[dsc->page_count].ordinal = ordinal; 0591 dsc->page[dsc->page_count].label = 0592 dsc_alloc_string(dsc, label, strlen(label)+1); 0593 dsc->page[dsc->page_count].begin = 0; 0594 dsc->page[dsc->page_count].end = 0; 0595 dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN; 0596 dsc->page[dsc->page_count].media = NULL; 0597 dsc->page[dsc->page_count].bbox = NULL; 0598 dsc->page[dsc->page_count].viewing_orientation = NULL; 0599 0600 dsc->page_count++; 0601 if (dsc->page_count >= dsc->page_chunk_length) { 0602 CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc, 0603 (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE)); 0604 if (new_page == NULL) 0605 return CDSC_ERROR; /* out of memory */ 0606 memcpy(new_page, dsc->page, 0607 dsc->page_count * sizeof(CDSCPAGE)); 0608 dsc_memfree(dsc, dsc->page); 0609 dsc->page= new_page; 0610 dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count; 0611 } 0612 return CDSC_OK; 0613 } 0614 0615 /* Doesn't need to be public for PostScript documents */ 0616 /* Made public so GSview can store PDF MediaBox */ 0617 int 0618 dsc_add_media(CDSC *dsc, CDSCMEDIA *media) 0619 { 0620 CDSCMEDIA **newmedia_array; 0621 CDSCMEDIA *newmedia; 0622 0623 /* extend media array */ 0624 newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc, 0625 (dsc->media_count + 1) * sizeof(CDSCMEDIA *)); 0626 if (newmedia_array == NULL) 0627 return CDSC_ERROR; /* out of memory */ 0628 if (dsc->media != NULL) { 0629 memcpy(newmedia_array, dsc->media, 0630 dsc->media_count * sizeof(CDSCMEDIA *)); 0631 dsc_memfree(dsc, dsc->media); 0632 } 0633 dsc->media = newmedia_array; 0634 0635 /* allocate new media */ 0636 newmedia = dsc->media[dsc->media_count] = 0637 (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA)); 0638 if (newmedia == NULL) 0639 return CDSC_ERROR; /* out of memory */ 0640 newmedia->name = NULL; 0641 newmedia->width = 595.0; 0642 newmedia->height = 842.0; 0643 newmedia->weight = 80.0; 0644 newmedia->colour = NULL; 0645 newmedia->type = NULL; 0646 newmedia->mediabox = NULL; 0647 0648 dsc->media_count++; 0649 0650 if (media->name) { 0651 newmedia->name = dsc_alloc_string(dsc, media->name, 0652 strlen(media->name)); 0653 if (newmedia->name == NULL) 0654 return CDSC_ERROR; /* no memory */ 0655 } 0656 newmedia->width = media->width; 0657 newmedia->height = media->height; 0658 newmedia->weight = media->weight; 0659 if (media->colour) { 0660 newmedia->colour = dsc_alloc_string(dsc, media->colour, 0661 strlen(media->colour)); 0662 if (newmedia->colour == NULL) 0663 return CDSC_ERROR; /* no memory */ 0664 } 0665 if (media->type) { 0666 newmedia->type = dsc_alloc_string(dsc, media->type, 0667 strlen(media->type)); 0668 if (newmedia->type == NULL) 0669 return CDSC_ERROR; /* no memory */ 0670 } 0671 newmedia->mediabox = NULL; 0672 0673 if (media->mediabox) { 0674 newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); 0675 if (newmedia->mediabox == NULL) 0676 return CDSC_ERROR; /* no memory */ 0677 *newmedia->mediabox = *media->mediabox; 0678 } 0679 return CDSC_OK; 0680 } 0681 0682 /* Doesn't need to be public for PostScript documents */ 0683 /* Made public so GSview can store PDF CropBox */ 0684 int 0685 dsc_set_page_bbox(CDSC *dsc, unsigned int page_number, 0686 int llx, int lly, int urx, int ury) 0687 { 0688 CDSCBBOX *bbox; 0689 if (page_number >= dsc->page_count) 0690 return CDSC_ERROR; 0691 bbox = dsc->page[page_number].bbox; 0692 if (bbox == NULL) 0693 dsc->page[page_number].bbox = bbox = 0694 (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); 0695 if (bbox == NULL) 0696 return CDSC_ERROR; 0697 bbox->llx = llx; 0698 bbox->lly = lly; 0699 bbox->urx = urx; 0700 bbox->ury = ury; 0701 return CDSC_OK; 0702 } 0703 0704 0705 /******************************************************************/ 0706 /* Private functions below here. */ 0707 /******************************************************************/ 0708 0709 dsc_private void * 0710 dsc_memalloc(CDSC *dsc, size_t size) 0711 { 0712 if (dsc->memalloc) 0713 return dsc->memalloc(size, dsc->mem_closure_data); 0714 return malloc(size); 0715 } 0716 0717 dsc_private void 0718 dsc_memfree(CDSC*dsc, void *ptr) 0719 { 0720 if (dsc->memfree) 0721 dsc->memfree(ptr, dsc->mem_closure_data); 0722 else 0723 free(ptr); 0724 } 0725 0726 /* private constructor */ 0727 dsc_private CDSC * 0728 dsc_init2(CDSC *dsc) 0729 { 0730 dsc_reset(dsc); 0731 0732 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING)); 0733 if (dsc->string_head == NULL) { 0734 dsc_free(dsc); 0735 return NULL; /* no memory */ 0736 } 0737 dsc->string = dsc->string_head; 0738 dsc->string->next = NULL; 0739 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK); 0740 if (dsc->string->data == NULL) { 0741 dsc_free(dsc); 0742 return NULL; /* no memory */ 0743 } 0744 dsc->string->index = 0; 0745 dsc->string->length = CDSC_STRING_CHUNK; 0746 0747 dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE)); 0748 if (dsc->page == NULL) { 0749 dsc_free(dsc); 0750 return NULL; /* no memory */ 0751 } 0752 dsc->page_chunk_length = CDSC_PAGE_CHUNK; 0753 dsc->page_count = 0; 0754 0755 dsc->line = NULL; 0756 dsc->data_length = 0; 0757 dsc->data_index = dsc->data_length; 0758 0759 return dsc; 0760 } 0761 0762 0763 dsc_private void 0764 dsc_reset(CDSC *dsc) 0765 { 0766 unsigned int i; 0767 /* Clear public members */ 0768 dsc->dsc = FALSE; 0769 dsc->ctrld = FALSE; 0770 dsc->pjl = FALSE; 0771 dsc->epsf = FALSE; 0772 dsc->pdf = FALSE; 0773 dsc->epsf = FALSE; 0774 dsc->preview = CDSC_NOPREVIEW; 0775 dsc->dsc_version = NULL; /* stored in dsc->string */ 0776 dsc->language_level = 0; 0777 dsc->document_data = CDSC_DATA_UNKNOWN; 0778 dsc->begincomments = 0; 0779 dsc->endcomments = 0; 0780 dsc->beginpreview = 0; 0781 dsc->endpreview = 0; 0782 dsc->begindefaults = 0; 0783 dsc->enddefaults = 0; 0784 dsc->beginprolog = 0; 0785 dsc->endprolog = 0; 0786 dsc->beginsetup = 0; 0787 dsc->endsetup = 0; 0788 dsc->begintrailer = 0; 0789 dsc->endtrailer = 0; 0790 0791 for (i=0; i<dsc->page_count; i++) { 0792 /* page media is pointer to an element of media or dsc_known_media */ 0793 /* do not free it. */ 0794 0795 if (dsc->page[i].bbox) 0796 dsc_memfree(dsc, dsc->page[i].bbox); 0797 if (dsc->page[i].viewing_orientation) 0798 dsc_memfree(dsc, dsc->page[i].viewing_orientation); 0799 } 0800 if (dsc->page) 0801 dsc_memfree(dsc, dsc->page); 0802 dsc->page = NULL; 0803 0804 dsc->page_count = 0; 0805 dsc->page_pages = 0; 0806 dsc->page_order = CDSC_ORDER_UNKNOWN; 0807 dsc->page_orientation = CDSC_ORIENT_UNKNOWN; 0808 if (dsc->viewing_orientation) 0809 dsc_memfree(dsc, dsc->viewing_orientation); 0810 dsc->viewing_orientation = NULL; 0811 0812 if (dsc->media) { 0813 for (i=0; i<dsc->media_count; i++) { 0814 if (dsc->media[i]) { 0815 if (dsc->media[i]->mediabox) 0816 dsc_memfree(dsc, dsc->media[i]->mediabox); 0817 dsc_memfree(dsc, dsc->media[i]); 0818 } 0819 } 0820 dsc_memfree(dsc, dsc->media); 0821 } 0822 dsc->media_count = 0; 0823 dsc->media = NULL; 0824 0825 /* page_media is pointer to an element of media or dsc_known_media */ 0826 /* do not free it. */ 0827 dsc->page_media = NULL; 0828 0829 if (dsc->bbox) 0830 dsc_memfree(dsc, dsc->bbox); 0831 dsc->bbox = NULL; 0832 if (dsc->page_bbox) 0833 dsc_memfree(dsc, dsc->page_bbox); 0834 dsc->page_bbox = NULL; 0835 if (dsc->doseps) 0836 dsc_memfree(dsc, dsc->doseps); 0837 dsc->doseps = NULL; 0838 0839 dsc->dsc_title = NULL; 0840 dsc->dsc_creator = NULL; 0841 dsc->dsc_date = NULL; 0842 dsc->dsc_for = NULL; 0843 0844 0845 dsc->max_error = DSC_MAX_ERROR; 0846 dsc->severity = dsc_severity; 0847 0848 /* Clear private members */ 0849 /* Don't touch dsc->caller_data */ 0850 dsc->id = CDSC_OK; 0851 dsc->scan_section = scan_none; 0852 dsc->doseps_end = 0; 0853 dsc->page_chunk_length = 0; 0854 dsc->file_length = 0; 0855 dsc->skip_document = 0; 0856 dsc->skip_bytes = 0; 0857 dsc->skip_lines = 0; 0858 dsc->skip_pjl = 0; 0859 dsc->begin_font_count = 0; 0860 dsc->begin_feature_count = 0; 0861 dsc->begin_resource_count = 0; 0862 dsc->begin_procset_count = 0; 0863 0864 dsc->data_length = 0; 0865 dsc->data_index = 0; 0866 dsc->data_offset = 0; 0867 0868 dsc->eof = 0; 0869 0870 dsc->line = 0; 0871 dsc->line_length = 0; 0872 dsc->eol = 0; 0873 dsc->last_cr = FALSE; 0874 dsc->line_count = 1; 0875 dsc->long_line = FALSE; 0876 memset(dsc->last_line, 0, sizeof(dsc->last_line)); 0877 0878 dsc->string = dsc->string_head; 0879 while (dsc->string != (CDSCSTRING *)NULL) { 0880 if (dsc->string->data) 0881 dsc_memfree(dsc, dsc->string->data); 0882 dsc->string_head = dsc->string; 0883 dsc->string = dsc->string->next; 0884 dsc_memfree(dsc, dsc->string_head); 0885 } 0886 dsc->string_head = NULL; 0887 dsc->string = NULL; 0888 0889 /* don't touch caller functions */ 0890 0891 /* public data */ 0892 if (dsc->hires_bbox) 0893 dsc_memfree(dsc, dsc->hires_bbox); 0894 dsc->hires_bbox = NULL; 0895 if (dsc->crop_box) 0896 dsc_memfree(dsc, dsc->crop_box); 0897 dsc->crop_box = NULL; 0898 } 0899 0900 /* 0901 * Join up all sections. 0902 * There might be extra code between them, or we might have 0903 * missed including the \n which followed \r. 0904 * begin is the start of this section 0905 * pend is a pointer to the end of this section 0906 * pplast is a pointer to a pointer of the end of the previous section 0907 */ 0908 dsc_private void 0909 dsc_section_join(unsigned long begin, unsigned long *pend, unsigned long **pplast) 0910 { 0911 if (begin) 0912 **pplast = begin; 0913 if (*pend > begin) 0914 *pplast = pend; 0915 } 0916 0917 0918 /* return value is 0 if no line available, or length of line */ 0919 dsc_private int 0920 dsc_read_line(CDSC *dsc) 0921 { 0922 char *p, *last; 0923 dsc->line = NULL; 0924 0925 if (dsc->eof) { 0926 /* return all that remains, even if line incomplete */ 0927 dsc->line = dsc->data + dsc->data_index; 0928 dsc->line_length = dsc->data_length - dsc->data_index; 0929 dsc->data_index = dsc->data_length; 0930 return dsc->line_length; 0931 } 0932 0933 /* ignore embedded bytes */ 0934 if (dsc->skip_bytes) { 0935 int cnt = min(dsc->skip_bytes, 0936 (int)(dsc->data_length - dsc->data_index)); 0937 dsc->skip_bytes -= cnt; 0938 dsc->data_index += cnt; 0939 if (dsc->skip_bytes != 0) 0940 return 0; 0941 } 0942 0943 do { 0944 dsc->line = dsc->data + dsc->data_index; 0945 last = dsc->data + dsc->data_length; 0946 if (dsc->data_index == dsc->data_length) { 0947 dsc->line_length = 0; 0948 return 0; 0949 } 0950 if (dsc->eol) { 0951 /* if previous line was complete, increment line count */ 0952 dsc->line_count++; 0953 if (dsc->skip_lines) 0954 dsc->skip_lines--; 0955 } 0956 0957 /* skip over \n which followed \r */ 0958 if (dsc->last_cr && dsc->line[0] == '\n') { 0959 dsc->data_index++; 0960 dsc->line++; 0961 } 0962 dsc->last_cr = FALSE; 0963 0964 /* look for EOL */ 0965 dsc->eol = FALSE; 0966 for (p = dsc->line; p < last; p++) { 0967 if (*p == '\r') { 0968 p++; 0969 if ((p<last) && (*p == '\n')) 0970 p++; /* include line feed also */ 0971 else 0972 dsc->last_cr = TRUE; /* we might need to skip \n */ 0973 dsc->eol = TRUE; /* dsc->line is a complete line */ 0974 break; 0975 } 0976 if (*p == '\n') { 0977 p++; 0978 dsc->eol = TRUE; /* dsc->line is a complete line */ 0979 break; 0980 } 0981 if (*p == '\032') { /* MS-DOS Ctrl+Z */ 0982 dsc->eol = TRUE; 0983 } 0984 } 0985 if (dsc->eol == FALSE) { 0986 /* we haven't got a complete line yet */ 0987 if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) { 0988 /* buffer is less than half full, ask for some more */ 0989 dsc->line_length = 0; 0990 return 0; 0991 } 0992 } 0993 dsc->data_index += dsc->line_length = (p - dsc->line); 0994 } while (dsc->skip_lines && dsc->line_length); 0995 0996 if (dsc->line_length == 0) 0997 return 0; 0998 0999 if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) { 1000 /* handle recursive %%BeginDocument */ 1001 if ((dsc->skip_document) && dsc->line_length && 1002 COMPARE(dsc->line, "%%EndDocument")) { 1003 dsc->skip_document--; 1004 } 1005 1006 /* handle embedded lines or binary data */ 1007 if (COMPARE(dsc->line, "%%BeginData:")) { 1008 /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ] 1009 * <numberof> ::= <uint> (Lines or physical bytes) 1010 * <type> ::= Hex | Binary | ASCII (Type of data) 1011 * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines) 1012 */ 1013 char begindata[MAXSTR+1]; 1014 int cnt; 1015 unsigned int num; 1016 const char *numberof, *bytesorlines; 1017 if ((num = dsc->line_length) >= sizeof(begindata)-1) 1018 num = sizeof(begindata)-1; 1019 1020 memcpy(begindata, dsc->line, num); 1021 begindata[num] = '\0'; 1022 numberof = strtok(begindata+12, " \r\n"); 1023 strtok(NULL, " \r\n"); /* dump type */ 1024 bytesorlines = strtok(NULL, " \r\n"); 1025 if (bytesorlines == NULL) 1026 bytesorlines = "Bytes"; 1027 1028 if ( (numberof == NULL) || (bytesorlines == NULL) ) { 1029 /* invalid usage of %%BeginData */ 1030 /* ignore that we ever saw it */ 1031 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, 1032 dsc->line, dsc->line_length); 1033 switch (rc) { 1034 case CDSC_RESPONSE_OK: 1035 case CDSC_RESPONSE_CANCEL: 1036 break; 1037 case CDSC_RESPONSE_IGNORE_ALL: 1038 return 0; 1039 } 1040 } 1041 else { 1042 cnt = atoi(numberof); 1043 if (cnt) { 1044 if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) { 1045 /* skip cnt lines */ 1046 if (dsc->skip_lines == 0) { 1047 /* we are not already skipping lines */ 1048 dsc->skip_lines = cnt+1; 1049 } 1050 } 1051 else { 1052 /* byte count doesn't includes \n or \r\n */ 1053 /* or \r of %%BeginData: */ 1054 /* skip cnt bytes */ 1055 if (dsc->skip_bytes == 0) { 1056 /* we are not already skipping lines */ 1057 dsc->skip_bytes = cnt; 1058 } 1059 1060 } 1061 } 1062 } 1063 } 1064 else if (COMPARE(dsc->line, "%%BeginBinary:")) { 1065 /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/ 1066 unsigned long cnt = atoi(dsc->line + 14); 1067 if (dsc->skip_bytes == 0) { 1068 /* we are not already skipping lines */ 1069 dsc->skip_bytes = cnt; 1070 } 1071 } 1072 } 1073 1074 if ((dsc->line[0]=='%') && (dsc->line[1]=='%') && 1075 COMPARE(dsc->line, "%%BeginDocument:") ) { 1076 /* Skip over embedded document, recursively */ 1077 dsc->skip_document++; 1078 } 1079 1080 if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) { 1081 dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length); 1082 dsc->long_line = TRUE; 1083 } 1084 1085 return dsc->line_length; 1086 } 1087 1088 1089 /* Save last DSC line, for use with %%+ */ 1090 dsc_private void 1091 dsc_save_line(CDSC *dsc) 1092 { 1093 int len = min(sizeof(dsc->last_line), dsc->line_length); 1094 memcpy(dsc->last_line, dsc->line, len); 1095 } 1096 1097 /* display unknown DSC line */ 1098 dsc_private void 1099 dsc_unknown(CDSC *dsc) 1100 { 1101 if (dsc->debug_print_fn) { 1102 char line[DSC_LINE_LENGTH]; 1103 unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length); 1104 sprintf(line, "Unknown in %s section at line %d:\n ", 1105 dsc_scan_section_name[dsc->scan_section], dsc->line_count); 1106 dsc_debug_print(dsc, line); 1107 strncpy(line, dsc->line, length); 1108 line[length] = '\0'; 1109 dsc_debug_print(dsc, line); 1110 } 1111 } 1112 1113 1114 dsc_private GSBOOL 1115 dsc_is_section(char *line) 1116 { 1117 if ( !((line[0]=='%') && (line[1]=='%')) ) 1118 return FALSE; 1119 if (IS_DSC(line, "%%BeginPreview")) 1120 return TRUE; 1121 if (IS_DSC(line, "%%BeginDefaults")) 1122 return TRUE; 1123 if (IS_DSC(line, "%%BeginProlog")) 1124 return TRUE; 1125 if (IS_DSC(line, "%%BeginSetup")) 1126 return TRUE; 1127 if (IS_DSC(line, "%%Page:")) 1128 return TRUE; 1129 if (IS_DSC(line, "%%Trailer")) 1130 return TRUE; 1131 if (IS_DSC(line, "%%EOF")) 1132 return TRUE; 1133 return FALSE; 1134 } 1135 1136 1137 dsc_private GSDWORD 1138 dsc_get_dword(const unsigned char *buf) 1139 { 1140 GSDWORD dw; 1141 dw = (GSDWORD)buf[0]; 1142 dw += ((GSDWORD)buf[1])<<8; 1143 dw += ((GSDWORD)buf[2])<<16; 1144 dw += ((GSDWORD)buf[3])<<24; 1145 return dw; 1146 } 1147 1148 dsc_private GSWORD 1149 dsc_get_word(const unsigned char *buf) 1150 { 1151 GSWORD w; 1152 w = (GSWORD)buf[0]; 1153 w |= (GSWORD)(buf[1]<<8); 1154 return w; 1155 } 1156 1157 dsc_private int 1158 dsc_read_doseps(CDSC *dsc) 1159 { 1160 unsigned char *line = (unsigned char *)dsc->line; 1161 if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL) 1162 return CDSC_ERROR; /* no memory */ 1163 1164 dsc->doseps->ps_begin = dsc_get_dword(line+4); 1165 dsc->doseps->ps_length = dsc_get_dword(line+8); 1166 dsc->doseps->wmf_begin = dsc_get_dword(line+12); 1167 dsc->doseps->wmf_length = dsc_get_dword(line+16); 1168 dsc->doseps->tiff_begin = dsc_get_dword(line+20); 1169 dsc->doseps->tiff_length = dsc_get_dword(line+24); 1170 dsc->doseps->checksum = dsc_get_word(line+28); 1171 1172 dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length; 1173 1174 /* move data_index backwards to byte after doseps header */ 1175 dsc->data_index -= dsc->line_length - 30; 1176 /* we haven't read a line of PostScript code yet */ 1177 dsc->line_count = 0; 1178 /* skip from current position to start of PostScript section */ 1179 dsc->skip_bytes = dsc->doseps->ps_begin - 30; 1180 1181 if (dsc->doseps->tiff_begin) 1182 dsc->preview = CDSC_TIFF; 1183 if (dsc->doseps->wmf_begin) 1184 dsc->preview = CDSC_WMF; 1185 1186 return CDSC_OK; 1187 } 1188 1189 1190 1191 dsc_private int 1192 dsc_parse_pages(CDSC *dsc) 1193 { 1194 int ip, io; 1195 unsigned int i; 1196 char *p; 1197 int n; 1198 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) { 1199 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1200 dsc->line_length); 1201 switch (rc) { 1202 case CDSC_RESPONSE_OK: 1203 case CDSC_RESPONSE_CANCEL: 1204 return CDSC_OK; /* ignore duplicate comments in header */ 1205 case CDSC_RESPONSE_IGNORE_ALL: 1206 return CDSC_NOTDSC; 1207 } 1208 } 1209 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) { 1210 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, 1211 dsc->line_length); 1212 switch (rc) { 1213 case CDSC_RESPONSE_OK: 1214 case CDSC_RESPONSE_CANCEL: 1215 break; /* use duplicate comments in header */ 1216 case CDSC_RESPONSE_IGNORE_ALL: 1217 return CDSC_NOTDSC; 1218 } 1219 } 1220 1221 n = IS_DSC(dsc->line, "%%+") ? 3 : 8; 1222 while (IS_WHITE(dsc->line[n])) 1223 n++; 1224 p = dsc->line + n; 1225 if (COMPARE(p, "atend")) { 1226 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); 1227 switch (rc) { 1228 case CDSC_RESPONSE_OK: 1229 /* assume (atend) */ 1230 /* we should mark it as deferred */ 1231 break; 1232 case CDSC_RESPONSE_CANCEL: 1233 /* ignore it */ 1234 break; 1235 case CDSC_RESPONSE_IGNORE_ALL: 1236 return CDSC_NOTDSC; 1237 } 1238 } 1239 else if (COMPARE(p, "(atend)")) { 1240 /* do nothing */ 1241 /* we should mark it as deferred */ 1242 } 1243 else { 1244 ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 1245 if (i) { 1246 n+=i; 1247 dsc->page_pages = ip; 1248 io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 1249 if (i) { 1250 /* DSC 2 uses extra integer to indicate page order */ 1251 /* DSC 3 uses %%PageOrder: */ 1252 if (dsc->page_order == CDSC_ORDER_UNKNOWN) 1253 switch (io) { 1254 case -1: 1255 dsc->page_order = CDSC_DESCEND; 1256 break; 1257 case 0: 1258 dsc->page_order = CDSC_SPECIAL; 1259 break; 1260 case 1: 1261 dsc->page_order = CDSC_ASCEND; 1262 break; 1263 } 1264 } 1265 } 1266 else { 1267 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line, 1268 dsc->line_length); 1269 switch (rc) { 1270 case CDSC_RESPONSE_OK: 1271 case CDSC_RESPONSE_CANCEL: 1272 /* ignore it */ 1273 break; 1274 case CDSC_RESPONSE_IGNORE_ALL: 1275 return CDSC_NOTDSC; 1276 } 1277 } 1278 } 1279 return CDSC_OK; 1280 } 1281 1282 dsc_private int 1283 dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset) 1284 { 1285 unsigned int i, n; 1286 int llx, lly, urx, ury; 1287 float fllx, flly, furx, fury; 1288 char *p; 1289 /* Process first %%BoundingBox: in comments, and last in trailer */ 1290 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) { 1291 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1292 dsc->line_length); 1293 switch (rc) { 1294 case CDSC_RESPONSE_OK: 1295 case CDSC_RESPONSE_CANCEL: 1296 return CDSC_OK; /* ignore duplicate comments in header */ 1297 case CDSC_RESPONSE_IGNORE_ALL: 1298 return CDSC_NOTDSC; 1299 } 1300 } 1301 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) { 1302 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1303 dsc->line_length); 1304 switch (rc) { 1305 case CDSC_RESPONSE_OK: 1306 case CDSC_RESPONSE_CANCEL: 1307 return CDSC_OK; /* ignore duplicate comments in header */ 1308 case CDSC_RESPONSE_IGNORE_ALL: 1309 return CDSC_NOTDSC; 1310 } 1311 } 1312 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) { 1313 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, 1314 dsc->line_length); 1315 switch (rc) { 1316 case CDSC_RESPONSE_OK: 1317 case CDSC_RESPONSE_CANCEL: 1318 break; /* use duplicate comments in trailer */ 1319 case CDSC_RESPONSE_IGNORE_ALL: 1320 return CDSC_NOTDSC; 1321 } 1322 } 1323 if (*pbbox != NULL) { 1324 dsc_memfree(dsc, *pbbox); 1325 *pbbox = NULL; 1326 } 1327 1328 /* should only process first %%BoundingBox: */ 1329 1330 while (IS_WHITE(dsc->line[offset])) 1331 offset++; 1332 p = dsc->line + offset; 1333 1334 if (COMPARE(p, "atend")) { 1335 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, 1336 dsc->line_length); 1337 switch (rc) { 1338 case CDSC_RESPONSE_OK: 1339 /* assume (atend) */ 1340 /* we should mark it as deferred */ 1341 break; 1342 case CDSC_RESPONSE_CANCEL: 1343 /* ignore it */ 1344 break; 1345 case CDSC_RESPONSE_IGNORE_ALL: 1346 return CDSC_NOTDSC; 1347 } 1348 } 1349 else if (COMPARE(p, "(atend)")) { 1350 /* do nothing */ 1351 /* we should mark it as deferred */ 1352 } 1353 else { 1354 /* llx = */ lly = urx = ury = 0; 1355 n = offset; 1356 llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 1357 n += i; 1358 if (i) 1359 lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 1360 n += i; 1361 if (i) 1362 urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 1363 n += i; 1364 if (i) 1365 ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 1366 if (i) { 1367 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); 1368 if (*pbbox == NULL) 1369 return CDSC_ERROR; /* no memory */ 1370 (*pbbox)->llx = llx; 1371 (*pbbox)->lly = lly; 1372 (*pbbox)->urx = urx; 1373 (*pbbox)->ury = ury; 1374 } 1375 else { 1376 int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line, 1377 dsc->line_length); 1378 switch (rc) { 1379 case CDSC_RESPONSE_OK: 1380 /* fllx = */ flly = furx = fury = 0.0; 1381 n = offset; 1382 n += i; 1383 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1384 n += i; 1385 if (i) 1386 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1387 n += i; 1388 if (i) 1389 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1390 n += i; 1391 if (i) 1392 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1393 if (i) { 1394 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); 1395 if (*pbbox == NULL) { 1396 return CDSC_ERROR; /* no memory */ 1397 } 1398 (*pbbox)->llx = (int)fllx; 1399 (*pbbox)->lly = (int)flly; 1400 (*pbbox)->urx = (int)(furx+0.999); 1401 (*pbbox)->ury = (int)(fury+0.999); 1402 } 1403 return CDSC_OK; 1404 case CDSC_RESPONSE_CANCEL: 1405 return CDSC_OK; 1406 case CDSC_RESPONSE_IGNORE_ALL: 1407 return CDSC_NOTDSC; 1408 } 1409 } 1410 } 1411 return CDSC_OK; 1412 } 1413 1414 dsc_private int 1415 dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset) 1416 { 1417 unsigned int i, n; 1418 float fllx, flly, furx, fury; 1419 char *p; 1420 /* Process first %%HiResBoundingBox: or %%CropBox: in comments, 1421 * and last in trailer. 1422 */ 1423 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) { 1424 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1425 dsc->line_length); 1426 switch (rc) { 1427 case CDSC_RESPONSE_OK: 1428 case CDSC_RESPONSE_CANCEL: 1429 return CDSC_OK; /* ignore duplicate comments in header */ 1430 case CDSC_RESPONSE_IGNORE_ALL: 1431 return CDSC_NOTDSC; 1432 } 1433 } 1434 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) { 1435 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1436 dsc->line_length); 1437 switch (rc) { 1438 case CDSC_RESPONSE_OK: 1439 case CDSC_RESPONSE_CANCEL: 1440 return CDSC_OK; /* ignore duplicate comments in header */ 1441 case CDSC_RESPONSE_IGNORE_ALL: 1442 return CDSC_NOTDSC; 1443 } 1444 } 1445 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) { 1446 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, 1447 dsc->line_length); 1448 switch (rc) { 1449 case CDSC_RESPONSE_OK: 1450 case CDSC_RESPONSE_CANCEL: 1451 break; /* use duplicate comments in trailer */ 1452 case CDSC_RESPONSE_IGNORE_ALL: 1453 return CDSC_NOTDSC; 1454 } 1455 } 1456 if (*pbbox != NULL) { 1457 dsc_memfree(dsc, *pbbox); 1458 *pbbox = NULL; 1459 } 1460 1461 /* should only process first %%BoundingBox: */ 1462 1463 while (IS_WHITE(dsc->line[offset])) 1464 offset++; 1465 p = dsc->line + offset; 1466 1467 if (COMPARE(p, "atend")) { 1468 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, 1469 dsc->line_length); 1470 switch (rc) { 1471 case CDSC_RESPONSE_OK: 1472 /* assume (atend) */ 1473 /* we should mark it as deferred */ 1474 break; 1475 case CDSC_RESPONSE_CANCEL: 1476 /* ignore it */ 1477 break; 1478 case CDSC_RESPONSE_IGNORE_ALL: 1479 return CDSC_NOTDSC; 1480 } 1481 } 1482 else if (COMPARE(p, "(atend)")) { 1483 /* do nothing */ 1484 /* we should mark it as deferred */ 1485 } 1486 else { 1487 /* fllx = */ flly = furx = fury = 0.0; 1488 n = offset; 1489 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1490 n += i; 1491 if (i) 1492 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1493 n += i; 1494 if (i) 1495 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1496 n += i; 1497 if (i) 1498 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1499 if (i) { 1500 *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX)); 1501 if (*pbbox == NULL) 1502 return CDSC_ERROR; /* no memory */ 1503 (*pbbox)->fllx = fllx; 1504 (*pbbox)->flly = flly; 1505 (*pbbox)->furx = furx; 1506 (*pbbox)->fury = fury; 1507 } 1508 } 1509 return CDSC_OK; 1510 } 1511 1512 dsc_private int 1513 dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset) 1514 { 1515 char *p; 1516 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) && 1517 (dsc->scan_section == scan_comments)) { 1518 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1519 dsc->line_length); 1520 switch (rc) { 1521 case CDSC_RESPONSE_OK: 1522 case CDSC_RESPONSE_CANCEL: 1523 return CDSC_OK; /* ignore duplicate comments in header */ 1524 case CDSC_RESPONSE_IGNORE_ALL: 1525 return CDSC_NOTDSC; 1526 } 1527 } 1528 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) && 1529 (dsc->scan_section == scan_trailer)) { 1530 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, 1531 dsc->line_length); 1532 switch (rc) { 1533 case CDSC_RESPONSE_OK: 1534 case CDSC_RESPONSE_CANCEL: 1535 break; /* use duplicate comments in header; */ 1536 case CDSC_RESPONSE_IGNORE_ALL: 1537 return CDSC_NOTDSC; 1538 } 1539 } 1540 p = dsc->line + offset; 1541 while (IS_WHITE(*p)) 1542 p++; 1543 if (COMPARE(p, "atend")) { 1544 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); 1545 switch (rc) { 1546 case CDSC_RESPONSE_OK: 1547 /* assume (atend) */ 1548 /* we should mark it as deferred */ 1549 break; 1550 case CDSC_RESPONSE_CANCEL: 1551 /* ignore it */ 1552 break; 1553 case CDSC_RESPONSE_IGNORE_ALL: 1554 return CDSC_NOTDSC; 1555 } 1556 } 1557 else if (COMPARE(p, "(atend)")) { 1558 /* do nothing */ 1559 /* we should mark it as deferred */ 1560 } 1561 else if (COMPARE(p, "Portrait")) { 1562 *porientation = CDSC_PORTRAIT; 1563 } 1564 else if (COMPARE(p, "Landscape")) { 1565 *porientation = CDSC_LANDSCAPE; 1566 } 1567 else { 1568 dsc_unknown(dsc); 1569 } 1570 return CDSC_OK; 1571 } 1572 1573 dsc_private int 1574 dsc_parse_order(CDSC *dsc) 1575 { 1576 char *p; 1577 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) && 1578 (dsc->scan_section == scan_comments)) { 1579 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, 1580 dsc->line_length); 1581 switch (rc) { 1582 case CDSC_RESPONSE_OK: 1583 case CDSC_RESPONSE_CANCEL: 1584 return CDSC_OK; /* ignore duplicate comments in header */ 1585 case CDSC_RESPONSE_IGNORE_ALL: 1586 return CDSC_NOTDSC; 1587 } 1588 } 1589 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) && 1590 (dsc->scan_section == scan_trailer)) { 1591 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, 1592 dsc->line_length); 1593 switch (rc) { 1594 case CDSC_RESPONSE_OK: 1595 case CDSC_RESPONSE_CANCEL: 1596 break; /* use duplicate comments in trailer */ 1597 case CDSC_RESPONSE_IGNORE_ALL: 1598 return CDSC_NOTDSC; 1599 } 1600 } 1601 1602 p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13); 1603 while (IS_WHITE(*p)) 1604 p++; 1605 if (COMPARE(p, "atend")) { 1606 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, 1607 dsc->line_length); 1608 switch (rc) { 1609 case CDSC_RESPONSE_OK: 1610 /* assume (atend) */ 1611 /* we should mark it as deferred */ 1612 break; 1613 case CDSC_RESPONSE_CANCEL: 1614 /* ignore it */ 1615 break; 1616 case CDSC_RESPONSE_IGNORE_ALL: 1617 return CDSC_NOTDSC; 1618 } 1619 } 1620 else if (COMPARE(p, "(atend)")) { 1621 /* do nothing */ 1622 /* we should mark it as deferred */ 1623 } 1624 else if (COMPARE(p, "Ascend")) { 1625 dsc->page_order = CDSC_ASCEND; 1626 } 1627 else if (COMPARE(p, "Descend")) { 1628 dsc->page_order = CDSC_DESCEND; 1629 } 1630 else if (COMPARE(p, "Special")) { 1631 dsc->page_order = CDSC_SPECIAL; 1632 } 1633 else { 1634 dsc_unknown(dsc); 1635 } 1636 return CDSC_OK; 1637 } 1638 1639 1640 dsc_private int 1641 dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media) 1642 { 1643 char media_name[MAXSTR]; 1644 int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */ 1645 unsigned int i; 1646 1647 if (dsc_copy_string(media_name, sizeof(media_name)-1, 1648 dsc->line+n, dsc->line_length-n, NULL)) { 1649 for (i=0; i<dsc->media_count; i++) { 1650 if (dsc->media[i]->name && 1651 (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) { 1652 *page_media = dsc->media[i]; 1653 return CDSC_OK; 1654 } 1655 } 1656 } 1657 dsc_unknown(dsc); 1658 1659 return CDSC_OK; 1660 } 1661 1662 1663 dsc_private int 1664 dsc_parse_document_media(CDSC *dsc) 1665 { 1666 unsigned int i, n; 1667 CDSCMEDIA lmedia; 1668 GSBOOL blank_line; 1669 1670 if (IS_DSC(dsc->line, "%%DocumentMedia:")) 1671 n = 16; 1672 else if (IS_DSC(dsc->line, "%%+")) 1673 n = 3; 1674 else 1675 return CDSC_ERROR; /* error */ 1676 1677 /* check for blank remainder of line */ 1678 blank_line = TRUE; 1679 for (i=n; i<dsc->line_length; i++) { 1680 if (!IS_WHITE_OR_EOL(dsc->line[i])) { 1681 blank_line = FALSE; 1682 break; 1683 } 1684 } 1685 1686 if (!blank_line) { 1687 char name[MAXSTR]; 1688 char colour[MAXSTR]; 1689 char type[MAXSTR]; 1690 lmedia.name = lmedia.colour = lmedia.type = (char *)NULL; 1691 lmedia.width = lmedia.height = lmedia.weight = 0; 1692 lmedia.mediabox = (CDSCBBOX *)NULL; 1693 lmedia.name = dsc_copy_string(name, sizeof(name)-1, 1694 dsc->line+n, dsc->line_length-n, &i); 1695 n+=i; 1696 if (i) 1697 lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1698 n+=i; 1699 if (i) 1700 lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1701 n+=i; 1702 if (i) 1703 lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1704 n+=i; 1705 if (i) 1706 lmedia.colour = dsc_copy_string(colour, sizeof(colour)-1, 1707 dsc->line+n, dsc->line_length-n, &i); 1708 n+=i; 1709 if (i) 1710 lmedia.type = dsc_copy_string(type, sizeof(type)-1, 1711 dsc->line+n, dsc->line_length-n, &i); 1712 1713 if (i==0) 1714 dsc_unknown(dsc); /* we didn't get all fields */ 1715 else { 1716 if (dsc_add_media(dsc, &lmedia)) 1717 return CDSC_ERROR; /* out of memory */ 1718 } 1719 } 1720 return CDSC_OK; 1721 } 1722 1723 /* viewing orientation is believed to be the first four elements of 1724 * a CTM matrix 1725 */ 1726 dsc_private int 1727 dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm) 1728 { 1729 CDSCCTM ctm; 1730 unsigned int i, n; 1731 1732 if (*pctm != NULL) { 1733 dsc_memfree(dsc, *pctm); 1734 *pctm = NULL; 1735 } 1736 1737 n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */ 1738 while (IS_WHITE(dsc->line[n])) 1739 n++; 1740 1741 /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0; 1742 ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1743 n += i; 1744 if (i) 1745 ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1746 n += i; 1747 if (i) 1748 ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1749 n += i; 1750 if (i) 1751 ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 1752 if (i==0) { 1753 dsc_unknown(dsc); /* we didn't get all fields */ 1754 } 1755 else { 1756 *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM)); 1757 if (*pctm == NULL) 1758 return CDSC_ERROR; /* no memory */ 1759 **pctm = ctm; 1760 } 1761 return CDSC_OK; 1762 } 1763 1764 1765 /* This is called before dsc_read_line(), since we may 1766 * need to skip a binary header which contains a new line 1767 * character 1768 */ 1769 dsc_private int 1770 dsc_scan_type(CDSC *dsc) 1771 { 1772 unsigned char *p; 1773 unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index); 1774 int length = dsc->data_length - dsc->data_index; 1775 1776 /* Types that should be known: 1777 * DSC 1778 * EPSF 1779 * PJL + any of above 1780 * ^D + any of above 1781 * DOS EPS 1782 * PDF 1783 * non-DSC 1784 */ 1785 1786 /* First process any non PostScript headers */ 1787 /* At this stage we do not have a complete line */ 1788 1789 if (length == 0) 1790 return CDSC_NEEDMORE; 1791 1792 if (dsc->skip_pjl) { 1793 /* skip until first PostScript comment */ 1794 while (length >= 2) { 1795 while (length && !IS_EOL(line[0])) { 1796 /* skip until EOL character */ 1797 line++; 1798 dsc->data_index++; 1799 length--; 1800 } 1801 while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) { 1802 /* skip until EOL followed by non-EOL */ 1803 line++; 1804 dsc->data_index++; 1805 length--; 1806 } 1807 if (length < 2) 1808 return CDSC_NEEDMORE; 1809 1810 if (IS_EOL(line[0]) && line[1]=='%') { 1811 line++; 1812 dsc->data_index++; 1813 length--; 1814 dsc->skip_pjl = FALSE; 1815 break; 1816 } 1817 else { 1818 /* line++; */ 1819 dsc->data_index++; 1820 /* length--; */ 1821 return CDSC_NEEDMORE; 1822 } 1823 } 1824 if (dsc->skip_pjl) 1825 return CDSC_NEEDMORE; 1826 } 1827 1828 if (length == 0) 1829 return CDSC_NEEDMORE; 1830 1831 if (line[0] == '\004') { 1832 line++; 1833 dsc->data_index++; 1834 length--; 1835 dsc->ctrld = TRUE; 1836 } 1837 1838 if (line[0] == '\033') { 1839 /* possibly PJL */ 1840 if (length < 9) 1841 return CDSC_NEEDMORE; 1842 if (COMPARE(line, "\033%-12345X")) { 1843 dsc->skip_pjl = TRUE; /* skip until first PostScript comment */ 1844 dsc->pjl = TRUE; 1845 dsc->data_index += 9; 1846 return dsc_scan_type(dsc); 1847 } 1848 } 1849 1850 if ((line[0]==0xc5) && (length < 4)) 1851 return CDSC_NEEDMORE; 1852 if ((line[0]==0xc5) && (line[1]==0xd0) && 1853 (line[2]==0xd3) && (line[3]==0xc6) ) { 1854 /* id is "EPSF" with bit 7 set */ 1855 /* read DOS EPS header, then ignore all bytes until the PS section */ 1856 if (length < 30) 1857 return CDSC_NEEDMORE; 1858 dsc->line = (char *)line; 1859 if (dsc_read_doseps(dsc)) 1860 return CDSC_ERROR; 1861 } 1862 else { 1863 if (length < 2) 1864 return CDSC_NEEDMORE; 1865 if ((line[0] == '%') && (line[1] == 'P')) { 1866 if (length < 5) 1867 return CDSC_NEEDMORE; 1868 if (COMPARE(line, "%PDF-")) { 1869 dsc->pdf = TRUE; 1870 dsc->scan_section = scan_comments; 1871 return CDSC_OK; 1872 } 1873 } 1874 } 1875 1876 /* Finally process PostScript headers */ 1877 1878 if (dsc_read_line(dsc) <= 0) 1879 return CDSC_NEEDMORE; 1880 1881 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length); 1882 if (COMPARE(dsc->line, "%!PS-Adobe")) { 1883 dsc->dsc = TRUE; 1884 dsc->begincomments = DSC_START(dsc); 1885 if (dsc->dsc_version == NULL) 1886 return CDSC_ERROR; /* no memory */ 1887 p = (unsigned char *)dsc->line + 14; 1888 while (IS_WHITE(*p)) 1889 p++; 1890 if (COMPARE(p, "EPSF-")) 1891 dsc->epsf = TRUE; 1892 dsc->scan_section = scan_comments; 1893 return CDSC_PSADOBE; 1894 } 1895 if (COMPARE(dsc->line, "%!")) { 1896 dsc->scan_section = scan_comments; 1897 return CDSC_NOTDSC; 1898 } 1899 1900 dsc->scan_section = scan_comments; 1901 return CDSC_NOTDSC; /* unrecognised */ 1902 } 1903 1904 1905 1906 dsc_private int 1907 dsc_scan_comments(CDSC *dsc) 1908 { 1909 /* Comments section ends at */ 1910 /* %%EndComments */ 1911 /* another section */ 1912 /* line that does not start with %% */ 1913 /* Save a few important lines */ 1914 1915 char *line = dsc->line; 1916 GSBOOL continued = FALSE; 1917 dsc->id = CDSC_OK; 1918 if (IS_DSC(line, "%%EndComments")) { 1919 dsc->id = CDSC_ENDCOMMENTS; 1920 dsc->endcomments = DSC_END(dsc); 1921 dsc->scan_section = scan_pre_preview; 1922 return CDSC_OK; 1923 } 1924 else if (IS_DSC(line, "%%BeginComments")) { 1925 /* ignore because we are in this section */ 1926 dsc->id = CDSC_BEGINCOMMENTS; 1927 } 1928 else if (dsc_is_section(line)) { 1929 dsc->endcomments = DSC_START(dsc); 1930 dsc->scan_section = scan_pre_preview; 1931 return CDSC_PROPAGATE; 1932 } 1933 else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) { 1934 dsc->endcomments = DSC_START(dsc); 1935 dsc->scan_section = scan_pre_preview; 1936 return CDSC_PROPAGATE; 1937 } 1938 else if (line[0] != '%') { 1939 dsc->id = CDSC_OK; 1940 dsc->endcomments = DSC_START(dsc); 1941 dsc->scan_section = scan_pre_preview; 1942 return CDSC_PROPAGATE; 1943 } 1944 else if (IS_DSC(line, "%%Begin")) { 1945 dsc->endcomments = DSC_START(dsc); 1946 dsc->scan_section = scan_pre_preview; 1947 return CDSC_PROPAGATE; 1948 } 1949 1950 /* Handle continuation lines. 1951 * To simply processing, we assume that contination lines 1952 * will only occur if repeat parameters are allowed and that 1953 * a complete set of these parameters appears on each line. 1954 * This is more restrictive than the DSC specification, but 1955 * is valid for the DSC comments understood by this parser 1956 * for all documents that we have seen. 1957 */ 1958 if (IS_DSC(line, "%%+")) { 1959 line = dsc->last_line; 1960 continued = TRUE; 1961 } 1962 else 1963 dsc_save_line(dsc); 1964 1965 if (IS_DSC(line, "%%Pages:")) { 1966 dsc->id = CDSC_PAGES; 1967 if (dsc_parse_pages(dsc) != 0) 1968 return CDSC_ERROR; 1969 } 1970 else if (IS_DSC(line, "%%Creator:")) { 1971 dsc->id = CDSC_CREATOR; 1972 dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10); 1973 if (dsc->dsc_creator==NULL) 1974 return CDSC_ERROR; 1975 } 1976 else if (IS_DSC(line, "%%CreationDate:")) { 1977 dsc->id = CDSC_CREATIONDATE; 1978 dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15); 1979 if (dsc->dsc_date==NULL) 1980 return CDSC_ERROR; 1981 } 1982 else if (IS_DSC(line, "%%Title:")) { 1983 dsc->id = CDSC_TITLE; 1984 dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8); 1985 if (dsc->dsc_title==NULL) 1986 return CDSC_ERROR; 1987 } 1988 else if (IS_DSC(line, "%%For:")) { 1989 dsc->id = CDSC_FOR; 1990 dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6); 1991 if (dsc->dsc_for==NULL) 1992 return CDSC_ERROR; 1993 } 1994 else if (IS_DSC(line, "%%LanguageLevel:")) { 1995 unsigned int n = continued ? 3 : 16; 1996 unsigned int i; 1997 int ll; 1998 dsc->id = CDSC_LANGUAGELEVEL; 1999 ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); 2000 if (i) { 2001 if ( (ll==1) || (ll==2) || (ll==3) ) 2002 dsc->language_level = ll; 2003 else { 2004 dsc_unknown(dsc); 2005 } 2006 } 2007 else 2008 dsc_unknown(dsc); 2009 } 2010 else if (IS_DSC(line, "%%BoundingBox:")) { 2011 dsc->id = CDSC_BOUNDINGBOX; 2012 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14)) 2013 return CDSC_ERROR; 2014 } 2015 else if (IS_DSC(line, "%%HiResBoundingBox:")) { 2016 dsc->id = CDSC_HIRESBOUNDINGBOX; 2017 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox), 2018 continued ? 3 : 19)) 2019 return CDSC_ERROR; 2020 } 2021 else if (IS_DSC(line, "%%CropBox:")) { 2022 dsc->id = CDSC_CROPBOX; 2023 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box), 2024 continued ? 3 : 10)) 2025 return CDSC_ERROR; 2026 } 2027 else if (IS_DSC(line, "%%Orientation:")) { 2028 dsc->id = CDSC_ORIENTATION; 2029 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 2030 continued ? 3 : 14)) 2031 return CDSC_ERROR; 2032 } 2033 else if (IS_DSC(line, "%%PageOrder:")) { 2034 dsc->id = CDSC_PAGEORDER; 2035 if (dsc_parse_order(dsc)) 2036 return CDSC_ERROR; 2037 } 2038 else if (IS_DSC(line, "%%DocumentMedia:")) { 2039 dsc->id = CDSC_DOCUMENTMEDIA; 2040 if (dsc_parse_document_media(dsc)) 2041 return CDSC_ERROR; 2042 } 2043 else if (IS_DSC(line, "%%DocumentPaperSizes:")) { 2044 /* DSC 2.1 */ 2045 unsigned int n = continued ? 3 : 21; 2046 unsigned int count = 0; 2047 unsigned int i = 1; 2048 char name[MAXSTR]; 2049 char *p; 2050 dsc->id = CDSC_DOCUMENTPAPERSIZES; 2051 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { 2052 p = dsc_copy_string(name, sizeof(name)-1, 2053 dsc->line+n, dsc->line_length-n, &i); 2054 if (i && p) { 2055 const CDSCMEDIA *m = dsc_known_media; 2056 if (count >= dsc->media_count) { 2057 /* set some default values */ 2058 CDSCMEDIA lmedia; 2059 lmedia.name = p; 2060 lmedia.width = 595.0; 2061 lmedia.height = 842.0; 2062 lmedia.weight = 80.0; 2063 lmedia.colour = NULL; 2064 lmedia.type = NULL; 2065 lmedia.mediabox = NULL; 2066 if (dsc_add_media(dsc, &lmedia)) 2067 return CDSC_ERROR; 2068 } 2069 else 2070 dsc->media[count]->name = 2071 dsc_alloc_string(dsc, p, strlen(p)); 2072 /* find in list of known media */ 2073 while (m && m->name) { 2074 if (dsc_stricmp(p, m->name)==0) { 2075 dsc->media[count]->width = m->width; 2076 dsc->media[count]->height = m->height; 2077 break; 2078 } 2079 m++; 2080 } 2081 } 2082 n+=i; 2083 count++; 2084 } 2085 } 2086 else if (IS_DSC(line, "%%DocumentPaperForms:")) { 2087 /* DSC 2.1 */ 2088 unsigned int n = continued ? 3 : 21; 2089 unsigned int count = 0; 2090 unsigned int i = 1; 2091 char type[MAXSTR]; 2092 char *p; 2093 dsc->id = CDSC_DOCUMENTPAPERFORMS; 2094 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { 2095 p = dsc_copy_string(type, sizeof(type)-1, 2096 dsc->line+n, dsc->line_length-n, &i); 2097 if (i && p) { 2098 if (count >= dsc->media_count) { 2099 /* set some default values */ 2100 CDSCMEDIA lmedia; 2101 lmedia.name = NULL; 2102 lmedia.width = 595.0; 2103 lmedia.height = 842.0; 2104 lmedia.weight = 80.0; 2105 lmedia.colour = NULL; 2106 lmedia.type = p; 2107 lmedia.mediabox = NULL; 2108 if (dsc_add_media(dsc, &lmedia)) 2109 return CDSC_ERROR; 2110 } 2111 else 2112 dsc->media[count]->type = 2113 dsc_alloc_string(dsc, p, strlen(p)); 2114 } 2115 n+=i; 2116 count++; 2117 } 2118 } 2119 else if (IS_DSC(line, "%%DocumentPaperColors:")) { 2120 /* DSC 2.1 */ 2121 unsigned int n = continued ? 3 : 22; 2122 unsigned int count = 0; 2123 unsigned int i = 1; 2124 char colour[MAXSTR]; 2125 char *p; 2126 dsc->id = CDSC_DOCUMENTPAPERCOLORS; 2127 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { 2128 p = dsc_copy_string(colour, sizeof(colour)-1, 2129 dsc->line+n, dsc->line_length-n, &i); 2130 if (i && p) { 2131 if (count >= dsc->media_count) { 2132 /* set some default values */ 2133 CDSCMEDIA lmedia; 2134 lmedia.name = NULL; 2135 lmedia.width = 595.0; 2136 lmedia.height = 842.0; 2137 lmedia.weight = 80.0; 2138 lmedia.colour = p; 2139 lmedia.type = NULL; 2140 lmedia.mediabox = NULL; 2141 if (dsc_add_media(dsc, &lmedia)) 2142 return CDSC_ERROR; 2143 } 2144 else 2145 dsc->media[count]->colour = 2146 dsc_alloc_string(dsc, p, strlen(p)); 2147 } 2148 n+=i; 2149 count++; 2150 } 2151 } 2152 else if (IS_DSC(line, "%%DocumentPaperWeights:")) { 2153 /* DSC 2.1 */ 2154 unsigned int n = continued ? 3 : 23; 2155 unsigned int count = 0; 2156 unsigned int i = 1; 2157 float w; 2158 dsc->id = CDSC_DOCUMENTPAPERWEIGHTS; 2159 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { 2160 w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); 2161 if (i) { 2162 if (count >= dsc->media_count) { 2163 /* set some default values */ 2164 CDSCMEDIA lmedia; 2165 lmedia.name = NULL; 2166 lmedia.width = 595.0; 2167 lmedia.height = 842.0; 2168 lmedia.weight = w; 2169 lmedia.colour = NULL; 2170 lmedia.type = NULL; 2171 lmedia.mediabox = NULL; 2172 if (dsc_add_media(dsc, &lmedia)) 2173 return CDSC_ERROR; 2174 } 2175 else 2176 dsc->media[count]->weight = w; 2177 } 2178 n+=i; 2179 count++; 2180 } 2181 } 2182 else if (IS_DSC(line, "%%DocumentData:")) { 2183 unsigned int n = continued ? 3 : 15; 2184 char *p = dsc->line + n; 2185 while (IS_WHITE(*p)) 2186 p++; 2187 dsc->id = CDSC_DOCUMENTDATA; 2188 if (COMPARE(p, "Clean7Bit")) 2189 dsc->document_data = CDSC_CLEAN7BIT; 2190 else if (COMPARE(p, "Clean8Bit")) 2191 dsc->document_data = CDSC_CLEAN8BIT; 2192 else if (COMPARE(p, "Binary")) 2193 dsc->document_data = CDSC_BINARY; 2194 else 2195 dsc_unknown(dsc); 2196 } 2197 else if (IS_DSC(line, "%%Requirements:")) { 2198 dsc->id = CDSC_REQUIREMENTS; 2199 /* ignore */ 2200 } 2201 else if (IS_DSC(line, "%%DocumentNeededFonts:")) { 2202 dsc->id = CDSC_DOCUMENTNEEDEDFONTS; 2203 /* ignore */ 2204 } 2205 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) { 2206 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS; 2207 /* ignore */ 2208 } 2209 else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) { 2210 dsc->id = CDSC_OK; 2211 /* ignore */ 2212 } 2213 else { 2214 dsc->id = CDSC_UNKNOWNDSC; 2215 dsc_unknown(dsc); 2216 } 2217 2218 dsc->endcomments = DSC_END(dsc); 2219 return CDSC_OK; 2220 } 2221 2222 2223 dsc_private int 2224 dsc_scan_preview(CDSC *dsc) 2225 { 2226 /* Preview section ends at */ 2227 /* %%EndPreview */ 2228 /* another section */ 2229 /* Preview section must start with %%BeginPreview */ 2230 char *line = dsc->line; 2231 dsc->id = CDSC_OK; 2232 2233 if (dsc->scan_section == scan_pre_preview) { 2234 if (IS_BLANK(line)) 2235 return CDSC_OK; /* ignore blank lines before preview */ 2236 else if (IS_DSC(line, "%%BeginPreview")) { 2237 dsc->id = CDSC_BEGINPREVIEW; 2238 dsc->beginpreview = DSC_START(dsc); 2239 dsc->endpreview = DSC_END(dsc); 2240 dsc->scan_section = scan_preview; 2241 /* Don't mark the preview as EPSI if a DOS EPS header is present */ 2242 if (dsc->preview == CDSC_NOPREVIEW) 2243 dsc->preview = CDSC_EPSI; 2244 return CDSC_OK; 2245 } 2246 else { 2247 dsc->scan_section = scan_pre_defaults; 2248 return CDSC_PROPAGATE; 2249 } 2250 } 2251 2252 if (IS_DSC(line, "%%BeginPreview")) { 2253 /* ignore because we are in this section */ 2254 } 2255 else if (dsc_is_section(line)) { 2256 dsc->endpreview = DSC_START(dsc); 2257 dsc->scan_section = scan_pre_defaults; 2258 return CDSC_PROPAGATE; 2259 } 2260 else if (IS_DSC(line, "%%EndPreview")) { 2261 dsc->id = CDSC_ENDPREVIEW; 2262 dsc->endpreview = DSC_END(dsc); 2263 dsc->scan_section = scan_pre_defaults; 2264 return CDSC_OK; 2265 } 2266 else if (line[0] == '%' && line[1] != '%') { 2267 /* Ordinary comments are OK */ 2268 } 2269 else { 2270 dsc->id = CDSC_UNKNOWNDSC; 2271 /* DSC comments should not occur in preview */ 2272 dsc_unknown(dsc); 2273 } 2274 2275 dsc->endpreview = DSC_END(dsc); 2276 return CDSC_OK; 2277 } 2278 2279 dsc_private int 2280 dsc_scan_defaults(CDSC *dsc) 2281 { 2282 /* Defaults section ends at */ 2283 /* %%EndDefaults */ 2284 /* another section */ 2285 /* Defaults section must start with %%BeginDefaults */ 2286 char *line = dsc->line; 2287 dsc->id = CDSC_OK; 2288 2289 if (dsc->scan_section == scan_pre_defaults) { 2290 if (IS_BLANK(line)) 2291 return CDSC_OK; /* ignore blank lines before defaults */ 2292 else if (IS_DSC(line, "%%BeginDefaults")) { 2293 dsc->id = CDSC_BEGINDEFAULTS; 2294 dsc->begindefaults = DSC_START(dsc); 2295 dsc->enddefaults = DSC_END(dsc); 2296 dsc->scan_section = scan_defaults; 2297 return CDSC_OK; 2298 } 2299 else { 2300 dsc->scan_section = scan_pre_prolog; 2301 return CDSC_PROPAGATE; 2302 } 2303 } 2304 2305 if (NOT_DSC_LINE(line)) { 2306 /* ignore */ 2307 } 2308 else if (IS_DSC(line, "%%BeginPreview")) { 2309 /* ignore because we have already processed this section */ 2310 } 2311 else if (IS_DSC(line, "%%BeginDefaults")) { 2312 /* ignore because we are in this section */ 2313 } 2314 else if (dsc_is_section(line)) { 2315 dsc->enddefaults = DSC_START(dsc); 2316 dsc->scan_section = scan_pre_prolog; 2317 return CDSC_PROPAGATE; 2318 } 2319 else if (IS_DSC(line, "%%EndDefaults")) { 2320 dsc->id = CDSC_ENDDEFAULTS; 2321 dsc->enddefaults = DSC_END(dsc); 2322 dsc->scan_section = scan_pre_prolog; 2323 return CDSC_OK; 2324 } 2325 else if (IS_DSC(line, "%%PageMedia:")) { 2326 dsc->id = CDSC_PAGEMEDIA; 2327 dsc_parse_media(dsc, &dsc->page_media); 2328 } 2329 else if (IS_DSC(line, "%%PageOrientation:")) { 2330 dsc->id = CDSC_PAGEORIENTATION; 2331 /* This can override %%Orientation: */ 2332 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18)) 2333 return CDSC_ERROR; 2334 } 2335 else if (IS_DSC(line, "%%PageBoundingBox:")) { 2336 dsc->id = CDSC_PAGEBOUNDINGBOX; 2337 if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18)) 2338 return CDSC_ERROR; 2339 } 2340 else if (IS_DSC(line, "%%ViewingOrientation:")) { 2341 dsc->id = CDSC_VIEWINGORIENTATION; 2342 if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation)) 2343 return CDSC_ERROR; 2344 } 2345 else { 2346 dsc->id = CDSC_UNKNOWNDSC; 2347 /* All other DSC comments are unknown, but not an error */ 2348 dsc_unknown(dsc); 2349 } 2350 dsc->enddefaults = DSC_END(dsc); 2351 return CDSC_OK; 2352 } 2353 2354 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the 2355 * mismatch (default) */ 2356 dsc_private int 2357 dsc_check_match_prompt(CDSC *dsc, const char *str, int count) 2358 { 2359 if (count != 0) { 2360 char buf[MAXSTR+MAXSTR] = ""; 2361 if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) { 2362 strncpy(buf, dsc->line, dsc->line_length); 2363 buf[dsc->line_length] = '\0'; 2364 } 2365 sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str); 2366 return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, strlen(buf)); 2367 } 2368 return CDSC_RESPONSE_CANCEL; 2369 } 2370 2371 dsc_private int 2372 dsc_check_match_type(CDSC *dsc, const char *str, int count) 2373 { 2374 if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL) 2375 return CDSC_NOTDSC; 2376 return CDSC_OK; 2377 } 2378 2379 /* complain if Begin/End blocks didn't match */ 2380 /* return non-zero if we should ignore all DSC */ 2381 dsc_private int 2382 dsc_check_match(CDSC *dsc) 2383 { 2384 int rc = 0; 2385 const char *font = "Font"; 2386 const char *feature = "Feature"; 2387 const char *resource = "Resource"; 2388 const char *procset = "ProcSet"; 2389 2390 if (!rc) 2391 rc = dsc_check_match_type(dsc, font, dsc->begin_font_count); 2392 if (!rc) 2393 rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count); 2394 if (!rc) 2395 rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count); 2396 if (!rc) 2397 rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count); 2398 2399 dsc->begin_font_count = 0; 2400 dsc->begin_feature_count = 0; 2401 dsc->begin_resource_count = 0; 2402 dsc->begin_procset_count = 0; 2403 return rc; 2404 } 2405 2406 2407 dsc_private int 2408 dsc_scan_prolog(CDSC *dsc) 2409 { 2410 /* Prolog section ends at */ 2411 /* %%EndProlog */ 2412 /* another section */ 2413 /* Prolog section may start with %%BeginProlog or non-dsc line */ 2414 char *line = dsc->line; 2415 dsc->id = CDSC_OK; 2416 2417 if (dsc->scan_section == scan_pre_prolog) { 2418 if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) { 2419 dsc->scan_section = scan_pre_setup; 2420 return CDSC_PROPAGATE; 2421 } 2422 dsc->id = CDSC_BEGINPROLOG; 2423 dsc->beginprolog = DSC_START(dsc); 2424 dsc->endprolog = DSC_END(dsc); 2425 dsc->scan_section = scan_prolog; 2426 if (IS_DSC(line, "%%BeginProlog")) 2427 return CDSC_OK; 2428 } 2429 2430 if (NOT_DSC_LINE(line)) { 2431 /* ignore */ 2432 } 2433 else if (IS_DSC(line, "%%BeginPreview")) { 2434 /* ignore because we have already processed this section */ 2435 } 2436 else if (IS_DSC(line, "%%BeginDefaults")) { 2437 /* ignore because we have already processed this section */ 2438 } 2439 else if (IS_DSC(line, "%%BeginProlog")) { 2440 /* ignore because we are in this section */ 2441 } 2442 else if (dsc_is_section(line)) { 2443 dsc->endprolog = DSC_START(dsc); 2444 dsc->scan_section = scan_pre_setup; 2445 if (dsc_check_match(dsc)) 2446 return CDSC_NOTDSC; 2447 return CDSC_PROPAGATE; 2448 } 2449 else if (IS_DSC(line, "%%EndProlog")) { 2450 dsc->id = CDSC_ENDPROLOG; 2451 dsc->endprolog = DSC_END(dsc); 2452 dsc->scan_section = scan_pre_setup; 2453 if (dsc_check_match(dsc)) 2454 return CDSC_NOTDSC; 2455 return CDSC_OK; 2456 } 2457 else if (IS_DSC(line, "%%BeginFont:")) { 2458 dsc->id = CDSC_BEGINFONT; 2459 /* ignore Begin/EndFont, apart form making sure */ 2460 /* that they are matched. */ 2461 dsc->begin_font_count++; 2462 } 2463 else if (IS_DSC(line, "%%EndFont")) { 2464 dsc->id = CDSC_ENDFONT; 2465 dsc->begin_font_count--; 2466 } 2467 else if (IS_DSC(line, "%%BeginFeature:")) { 2468 dsc->id = CDSC_BEGINFEATURE; 2469 /* ignore Begin/EndFeature, apart form making sure */ 2470 /* that they are matched. */ 2471 dsc->begin_feature_count++; 2472 } 2473 else if (IS_DSC(line, "%%EndFeature")) { 2474 dsc->id = CDSC_ENDFEATURE; 2475 dsc->begin_feature_count--; 2476 } 2477 else if (IS_DSC(line, "%%BeginResource:")) { 2478 dsc->id = CDSC_BEGINRESOURCE; 2479 /* ignore Begin/EndResource, apart form making sure */ 2480 /* that they are matched. */ 2481 dsc->begin_resource_count++; 2482 } 2483 else if (IS_DSC(line, "%%EndResource")) { 2484 dsc->id = CDSC_ENDRESOURCE; 2485 dsc->begin_resource_count--; 2486 } 2487 else if (IS_DSC(line, "%%BeginProcSet:")) { 2488 dsc->id = CDSC_BEGINPROCSET; 2489 /* ignore Begin/EndProcSet, apart form making sure */ 2490 /* that they are matched. */ 2491 dsc->begin_procset_count++; 2492 } 2493 else if (IS_DSC(line, "%%EndProcSet")) { 2494 dsc->id = CDSC_ENDPROCSET; 2495 dsc->begin_procset_count--; 2496 } 2497 else { 2498 /* All other DSC comments are unknown, but not an error */ 2499 dsc->id = CDSC_UNKNOWNDSC; 2500 dsc_unknown(dsc); 2501 } 2502 2503 dsc->endprolog = DSC_END(dsc); 2504 return CDSC_OK; 2505 } 2506 2507 dsc_private int 2508 dsc_scan_setup(CDSC *dsc) 2509 { 2510 /* Setup section ends at */ 2511 /* %%EndSetup */ 2512 /* another section */ 2513 /* Setup section must start with %%BeginSetup */ 2514 2515 char *line = dsc->line; 2516 dsc->id = CDSC_OK; 2517 2518 if (dsc->scan_section == scan_pre_setup) { 2519 if (IS_BLANK(line)) 2520 return CDSC_OK; /* ignore blank lines before setup */ 2521 else if (IS_DSC(line, "%%BeginSetup")) { 2522 dsc->id = CDSC_BEGINSETUP; 2523 dsc->beginsetup = DSC_START(dsc); 2524 dsc->endsetup = DSC_END(dsc); 2525 dsc->scan_section = scan_setup; 2526 return CDSC_OK; 2527 } 2528 else { 2529 dsc->scan_section = scan_pre_pages; 2530 return CDSC_PROPAGATE; 2531 } 2532 } 2533 2534 if (NOT_DSC_LINE(line)) { 2535 /* ignore */ 2536 } 2537 else if (IS_DSC(line, "%%BeginPreview")) { 2538 /* ignore because we have already processed this section */ 2539 } 2540 else if (IS_DSC(line, "%%BeginDefaults")) { 2541 /* ignore because we have already processed this section */ 2542 } 2543 else if (IS_DSC(line, "%%BeginProlog")) { 2544 /* ignore because we have already processed this section */ 2545 } 2546 else if (IS_DSC(line, "%%BeginSetup")) { 2547 /* ignore because we are in this section */ 2548 } 2549 else if (dsc_is_section(line)) { 2550 dsc->endsetup = DSC_START(dsc); 2551 dsc->scan_section = scan_pre_pages; 2552 if (dsc_check_match(dsc)) 2553 return CDSC_NOTDSC; 2554 return CDSC_PROPAGATE; 2555 } 2556 else if (IS_DSC(line, "%%EndSetup")) { 2557 dsc->id = CDSC_ENDSETUP; 2558 dsc->endsetup = DSC_END(dsc); 2559 dsc->scan_section = scan_pre_pages; 2560 if (dsc_check_match(dsc)) 2561 return CDSC_NOTDSC; 2562 return CDSC_OK; 2563 } 2564 else if (IS_DSC(line, "%%BeginFeature:")) { 2565 dsc->id = CDSC_BEGINFEATURE; 2566 /* ignore Begin/EndFeature, apart form making sure */ 2567 /* that they are matched. */ 2568 dsc->begin_feature_count++; 2569 } 2570 else if (IS_DSC(line, "%%EndFeature")) { 2571 dsc->id = CDSC_ENDFEATURE; 2572 dsc->begin_feature_count--; 2573 } 2574 else if (IS_DSC(line, "%%Feature:")) { 2575 dsc->id = CDSC_FEATURE; 2576 /* ignore */ 2577 } 2578 else if (IS_DSC(line, "%%BeginResource:")) { 2579 dsc->id = CDSC_BEGINRESOURCE; 2580 /* ignore Begin/EndResource, apart form making sure */ 2581 /* that they are matched. */ 2582 dsc->begin_resource_count++; 2583 } 2584 else if (IS_DSC(line, "%%EndResource")) { 2585 dsc->id = CDSC_ENDRESOURCE; 2586 dsc->begin_resource_count--; 2587 } 2588 else if (IS_DSC(line, "%%PaperColor:")) { 2589 dsc->id = CDSC_PAPERCOLOR; 2590 /* ignore */ 2591 } 2592 else if (IS_DSC(line, "%%PaperForm:")) { 2593 dsc->id = CDSC_PAPERFORM; 2594 /* ignore */ 2595 } 2596 else if (IS_DSC(line, "%%PaperWeight:")) { 2597 dsc->id = CDSC_PAPERWEIGHT; 2598 /* ignore */ 2599 } 2600 else if (IS_DSC(line, "%%PaperSize:")) { 2601 /* DSC 2.1 */ 2602 GSBOOL found_media = FALSE; 2603 int i; 2604 int n = 12; 2605 char buf[MAXSTR]; 2606 buf[0] = '\0'; 2607 dsc->id = CDSC_PAPERSIZE; 2608 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n, 2609 NULL); 2610 for (i=0; i<(int)dsc->media_count; i++) { 2611 if (dsc->media[i] && dsc->media[i]->name && 2612 (dsc_stricmp(buf, dsc->media[i]->name)==0)) { 2613 dsc->page_media = dsc->media[i]; 2614 found_media = TRUE; 2615 break; 2616 } 2617 } 2618 if (!found_media) { 2619 /* It didn't match %%DocumentPaperSizes: */ 2620 /* Try our known media */ 2621 const CDSCMEDIA *m = dsc_known_media; 2622 while (m->name) { 2623 if (dsc_stricmp(buf, m->name)==0) { 2624 dsc->page_media = m; 2625 break; 2626 } 2627 m++; 2628 } 2629 if (m->name == NULL) 2630 dsc_unknown(dsc); 2631 } 2632 } 2633 else { 2634 /* All other DSC comments are unknown, but not an error */ 2635 dsc->id = CDSC_UNKNOWNDSC; 2636 dsc_unknown(dsc); 2637 } 2638 2639 dsc->endsetup = DSC_END(dsc); 2640 return CDSC_OK; 2641 } 2642 2643 dsc_private int 2644 dsc_scan_page(CDSC *dsc) 2645 { 2646 /* Page section ends at */ 2647 /* %%Page */ 2648 /* %%Trailer */ 2649 /* %%EOF */ 2650 char *line = dsc->line; 2651 dsc->id = CDSC_OK; 2652 2653 if (dsc->scan_section == scan_pre_pages) { 2654 if (IS_DSC(line, "%%Page:")) { 2655 dsc->scan_section = scan_pages; 2656 /* fall through */ 2657 } 2658 else { 2659 /* %%Page: didn't follow %%EndSetup 2660 * Keep reading until reach %%Page or %%Trailer 2661 * and add it to previous section. 2662 */ 2663 unsigned long *last; 2664 if (dsc->endsetup != 0) 2665 last = &dsc->endsetup; 2666 else if (dsc->endprolog != 0) 2667 last = &dsc->endprolog; 2668 else if (dsc->enddefaults != 0) 2669 last = &dsc->enddefaults; 2670 else if (dsc->endpreview != 0) 2671 last = &dsc->endpreview; 2672 else if (dsc->endcomments != 0) 2673 last = &dsc->endcomments; 2674 else 2675 last = &dsc->begincomments; 2676 *last = DSC_START(dsc); 2677 if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) { 2678 dsc->scan_section = scan_pre_trailer; 2679 return CDSC_PROPAGATE; 2680 } 2681 return CDSC_OK; 2682 } 2683 } 2684 2685 if (NOT_DSC_LINE(line)) { 2686 /* ignore */ 2687 } 2688 else if (IS_DSC(line, "%%Page:")) { 2689 dsc->id = CDSC_PAGE; 2690 if (dsc->page_count) { 2691 dsc->page[dsc->page_count-1].end = DSC_START(dsc); 2692 if (dsc_check_match(dsc)) 2693 return CDSC_NOTDSC; 2694 } 2695 2696 if (dsc_parse_page(dsc) != 0) 2697 return CDSC_ERROR; 2698 2699 return CDSC_OK; 2700 } 2701 else if (IS_DSC(line, "%%BeginPreview")) { 2702 /* ignore because we have already processed this section */ 2703 } 2704 else if (IS_DSC(line, "%%BeginDefaults")) { 2705 /* ignore because we have already processed this section */ 2706 } 2707 else if (IS_DSC(line, "%%BeginProlog")) { 2708 /* ignore because we have already processed this section */ 2709 } 2710 else if (IS_DSC(line, "%%BeginSetup")) { 2711 /* ignore because we have already processed this section */ 2712 } 2713 else if (dsc_is_section(line)) { 2714 if (IS_DSC(line, "%%Trailer")) { 2715 dsc->page[dsc->page_count-1].end = DSC_START(dsc); 2716 if (dsc->file_length) { 2717 if ((!dsc->doseps && 2718 ((DSC_END(dsc) + 32768) < dsc->file_length)) || 2719 ((dsc->doseps) && 2720 ((DSC_END(dsc) + 32768) < dsc->doseps_end))) { 2721 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER, 2722 dsc->line, dsc->line_length); 2723 switch (rc) { 2724 case CDSC_RESPONSE_OK: 2725 /* ignore early trailer */ 2726 break; 2727 case CDSC_RESPONSE_CANCEL: 2728 /* this is the trailer */ 2729 dsc->scan_section = scan_pre_trailer; 2730 if (dsc_check_match(dsc)) 2731 return CDSC_NOTDSC; 2732 return CDSC_PROPAGATE; 2733 case CDSC_RESPONSE_IGNORE_ALL: 2734 return CDSC_NOTDSC; 2735 } 2736 } 2737 else { 2738 dsc->scan_section = scan_pre_trailer; 2739 if (dsc_check_match(dsc)) 2740 return CDSC_NOTDSC; 2741 return CDSC_PROPAGATE; 2742 } 2743 } 2744 else { 2745 dsc->scan_section = scan_pre_trailer; 2746 if (dsc_check_match(dsc)) 2747 return CDSC_NOTDSC; 2748 return CDSC_PROPAGATE; 2749 } 2750 } 2751 else if (IS_DSC(line, "%%EOF")) { 2752 dsc->page[dsc->page_count-1].end = DSC_START(dsc); 2753 if (dsc->file_length) { 2754 if ((DSC_END(dsc)+100 < dsc->file_length) || 2755 (dsc->doseps && (DSC_END(dsc) + 100 < dsc->doseps_end))) { 2756 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF, 2757 dsc->line, dsc->line_length); 2758 switch (rc) { 2759 case CDSC_RESPONSE_OK: 2760 /* %%EOF is wrong, ignore it */ 2761 break; 2762 case CDSC_RESPONSE_CANCEL: 2763 /* %%EOF is correct */ 2764 dsc->scan_section = scan_eof; 2765 dsc->eof = TRUE; 2766 if (dsc_check_match(dsc)) 2767 return CDSC_NOTDSC; 2768 return CDSC_PROPAGATE; 2769 case CDSC_RESPONSE_IGNORE_ALL: 2770 return CDSC_NOTDSC; 2771 } 2772 } 2773 } 2774 else { 2775 /* ignore it */ 2776 if (dsc_check_match(dsc)) 2777 return CDSC_NOTDSC; 2778 return CDSC_OK; 2779 } 2780 } 2781 else { 2782 /* Section comment, probably from a badly */ 2783 /* encapsulated EPS file. */ 2784 int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION, 2785 dsc->line, dsc->line_length); 2786 if (rc == CDSC_RESPONSE_IGNORE_ALL) 2787 return CDSC_NOTDSC; 2788 } 2789 } 2790 else if (IS_DSC(line, "%%PageTrailer")) { 2791 dsc->id = CDSC_PAGETRAILER; 2792 /* ignore */ 2793 } 2794 else if (IS_DSC(line, "%%BeginPageSetup")) { 2795 dsc->id = CDSC_BEGINPAGESETUP; 2796 /* ignore */ 2797 } 2798 else if (IS_DSC(line, "%%EndPageSetup")) { 2799 dsc->id = CDSC_ENDPAGESETUP; 2800 /* ignore */ 2801 } 2802 else if (IS_DSC(line, "%%PageMedia:")) { 2803 dsc->id = CDSC_PAGEMEDIA; 2804 dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media)); 2805 } 2806 else if (IS_DSC(line, "%%PaperColor:")) { 2807 dsc->id = CDSC_PAPERCOLOR; 2808 /* ignore */ 2809 } 2810 else if (IS_DSC(line, "%%PaperForm:")) { 2811 dsc->id = CDSC_PAPERFORM; 2812 /* ignore */ 2813 } 2814 else if (IS_DSC(line, "%%PaperWeight:")) { 2815 dsc->id = CDSC_PAPERWEIGHT; 2816 /* ignore */ 2817 } 2818 else if (IS_DSC(line, "%%PaperSize:")) { 2819 /* DSC 2.1 */ 2820 GSBOOL found_media = FALSE; 2821 int i; 2822 int n = 12; 2823 char buf[MAXSTR]; 2824 buf[0] = '\0'; 2825 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, 2826 dsc->line_length-n, NULL); 2827 for (i=0; i<(int)dsc->media_count; i++) { 2828 if (dsc->media[i] && dsc->media[i]->name && 2829 (dsc_stricmp(buf, dsc->media[i]->name)==0)) { 2830 dsc->page_media = dsc->media[i]; 2831 found_media = TRUE; 2832 break; 2833 } 2834 } 2835 if (!found_media) { 2836 /* It didn't match %%DocumentPaperSizes: */ 2837 /* Try our known media */ 2838 const CDSCMEDIA *m = dsc_known_media; 2839 while (m->name) { 2840 if (dsc_stricmp(buf, m->name)==0) { 2841 dsc->page[dsc->page_count-1].media = m; 2842 break; 2843 } 2844 m++; 2845 } 2846 if (m->name == NULL) 2847 dsc_unknown(dsc); 2848 } 2849 } 2850 else if (IS_DSC(line, "%%PageOrientation:")) { 2851 dsc->id = CDSC_PAGEORIENTATION; 2852 if (dsc_parse_orientation(dsc, 2853 &(dsc->page[dsc->page_count-1].orientation) ,18)) 2854 return CDSC_NOTDSC; 2855 } 2856 else if (IS_DSC(line, "%%PageBoundingBox:")) { 2857 dsc->id = CDSC_PAGEBOUNDINGBOX; 2858 if (dsc_parse_bounding_box(dsc, &dsc->page[dsc->page_count-1].bbox, 18)) 2859 return CDSC_NOTDSC; 2860 } 2861 else if (IS_DSC(line, "%%ViewingOrientation:")) { 2862 dsc->id = CDSC_VIEWINGORIENTATION; 2863 if (dsc_parse_viewing_orientation(dsc, 2864 &dsc->page[dsc->page_count-1].viewing_orientation)) 2865 return CDSC_ERROR; 2866 } 2867 else if (IS_DSC(line, "%%BeginFont:")) { 2868 dsc->id = CDSC_BEGINFONT; 2869 /* ignore Begin/EndFont, apart form making sure */ 2870 /* that they are matched. */ 2871 dsc->begin_font_count++; 2872 } 2873 else if (IS_DSC(line, "%%EndFont")) { 2874 dsc->id = CDSC_BEGINFONT; 2875 dsc->begin_font_count--; 2876 } 2877 else if (IS_DSC(line, "%%BeginFeature:")) { 2878 dsc->id = CDSC_BEGINFEATURE; 2879 /* ignore Begin/EndFeature, apart form making sure */ 2880 /* that they are matched. */ 2881 dsc->begin_feature_count++; 2882 } 2883 else if (IS_DSC(line, "%%EndFeature")) { 2884 dsc->id = CDSC_ENDFEATURE; 2885 dsc->begin_feature_count--; 2886 } 2887 else if (IS_DSC(line, "%%BeginResource:")) { 2888 dsc->id = CDSC_BEGINRESOURCE; 2889 /* ignore Begin/EndResource, apart form making sure */ 2890 /* that they are matched. */ 2891 dsc->begin_resource_count++; 2892 } 2893 else if (IS_DSC(line, "%%EndResource")) { 2894 dsc->id = CDSC_ENDRESOURCE; 2895 dsc->begin_resource_count--; 2896 } 2897 else if (IS_DSC(line, "%%BeginProcSet:")) { 2898 dsc->id = CDSC_BEGINPROCSET; 2899 /* ignore Begin/EndProcSet, apart form making sure */ 2900 /* that they are matched. */ 2901 dsc->begin_procset_count++; 2902 } 2903 else if (IS_DSC(line, "%%EndProcSet")) { 2904 dsc->id = CDSC_ENDPROCSET; 2905 dsc->begin_procset_count--; 2906 } 2907 else if (IS_DSC(line, "%%IncludeFont:")) { 2908 dsc->id = CDSC_INCLUDEFONT; 2909 /* ignore */ 2910 } 2911 else { 2912 /* All other DSC comments are unknown, but not an error */ 2913 dsc->id = CDSC_UNKNOWNDSC; 2914 dsc_unknown(dsc); 2915 } 2916 2917 dsc->page[dsc->page_count-1].end = DSC_END(dsc); 2918 return CDSC_OK; 2919 } 2920 2921 /* Valid Trailer comments are 2922 * %%Trailer 2923 * %%EOF 2924 * or the following deferred with (atend) 2925 * %%BoundingBox: 2926 * %%DocumentCustomColors: 2927 * %%DocumentFiles: 2928 * %%DocumentFonts: 2929 * %%DocumentNeededFiles: 2930 * %%DocumentNeededFonts: 2931 * %%DocumentNeededProcSets: 2932 * %%DocumentNeededResources: 2933 * %%DocumentProcSets: 2934 * %%DocumentProcessColors: 2935 * %%DocumentSuppliedFiles: 2936 * %%DocumentSuppliedFonts: 2937 * %%DocumentSuppliedProcSets: 2938 * %%DocumentSuppliedResources: 2939 * %%Orientation: 2940 * %%Pages: 2941 * %%PageOrder: 2942 * 2943 * Our supported subset is 2944 * %%Trailer 2945 * %%EOF 2946 * %%BoundingBox: 2947 * %%Orientation: 2948 * %%Pages: 2949 * %%PageOrder: 2950 * In addition to these, we support 2951 * %%DocumentMedia: 2952 * 2953 * A %%PageTrailer can have the following: 2954 * %%PageBoundingBox: 2955 * %%PageCustomColors: 2956 * %%PageFiles: 2957 * %%PageFonts: 2958 * %%PageOrientation: 2959 * %%PageProcessColors: 2960 * %%PageResources: 2961 */ 2962 2963 dsc_private int 2964 dsc_scan_trailer(CDSC *dsc) 2965 { 2966 /* Trailer section start at */ 2967 /* %%Trailer */ 2968 /* and ends at */ 2969 /* %%EOF */ 2970 char *line = dsc->line; 2971 GSBOOL continued = FALSE; 2972 dsc->id = CDSC_OK; 2973 2974 if (dsc->scan_section == scan_pre_trailer) { 2975 if (IS_DSC(line, "%%Trailer")) { 2976 dsc->id = CDSC_TRAILER; 2977 dsc->begintrailer = DSC_START(dsc); 2978 dsc->endtrailer = DSC_END(dsc); 2979 dsc->scan_section = scan_trailer; 2980 return CDSC_OK; 2981 } 2982 else if (IS_DSC(line, "%%EOF")) { 2983 dsc->id = CDSC_EOF; 2984 dsc->begintrailer = DSC_START(dsc); 2985 dsc->endtrailer = DSC_END(dsc); 2986 dsc->scan_section = scan_trailer; 2987 /* Continue, in case we found %%EOF in an embedded document */ 2988 return CDSC_OK; 2989 } 2990 else { 2991 /* %%Page: didn't follow %%EndSetup 2992 * Keep reading until reach %%Page or %%Trailer 2993 * and add it to setup section 2994 */ 2995 /* append to previous section */ 2996 if (dsc->beginsetup) 2997 dsc->endsetup = DSC_END(dsc); 2998 else if (dsc->beginprolog) 2999 dsc->endprolog = DSC_END(dsc); 3000 else { 3001 /* horribly confused */ 3002 } 3003 return CDSC_OK; 3004 } 3005 } 3006 3007 /* Handle continuation lines. 3008 * See comment above about our restrictive processing of 3009 * continuation lines 3010 */ 3011 if (IS_DSC(line, "%%+")) { 3012 line = dsc->last_line; 3013 continued = TRUE; 3014 } 3015 else 3016 dsc_save_line(dsc); 3017 3018 if (NOT_DSC_LINE(line)) { 3019 /* ignore */ 3020 } 3021 else if (IS_DSC(dsc->line, "%%EOF")) { 3022 /* Keep scanning, in case we have a false trailer */ 3023 dsc->id = CDSC_EOF; 3024 } 3025 else if (IS_DSC(dsc->line, "%%Trailer")) { 3026 /* Cope with no pages with code after setup and before trailer. */ 3027 /* Last trailer is the correct one. */ 3028 dsc->id = CDSC_TRAILER; 3029 dsc->begintrailer = DSC_START(dsc); 3030 } 3031 else if (IS_DSC(line, "%%Pages:")) { 3032 dsc->id = CDSC_PAGES; 3033 if (dsc_parse_pages(dsc) != 0) 3034 return CDSC_ERROR; 3035 } 3036 else if (IS_DSC(line, "%%BoundingBox:")) { 3037 dsc->id = CDSC_BOUNDINGBOX; 3038 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14)) 3039 return CDSC_ERROR; 3040 } 3041 else if (IS_DSC(line, "%%HiResBoundingBox:")) { 3042 dsc->id = CDSC_HIRESBOUNDINGBOX; 3043 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox), 3044 continued ? 3 : 19)) 3045 return CDSC_ERROR; 3046 } 3047 else if (IS_DSC(line, "%%CropBox:")) { 3048 dsc->id = CDSC_CROPBOX; 3049 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box), 3050 continued ? 3 : 10)) 3051 return CDSC_ERROR; 3052 } 3053 else if (IS_DSC(line, "%%Orientation:")) { 3054 dsc->id = CDSC_ORIENTATION; 3055 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14)) 3056 return CDSC_ERROR; 3057 } 3058 else if (IS_DSC(line, "%%PageOrder:")) { 3059 dsc->id = CDSC_PAGEORDER; 3060 if (dsc_parse_order(dsc)) 3061 return CDSC_ERROR; 3062 } 3063 else if (IS_DSC(line, "%%DocumentMedia:")) { 3064 dsc->id = CDSC_DOCUMENTMEDIA; 3065 if (dsc_parse_document_media(dsc)) 3066 return CDSC_ERROR; 3067 } 3068 else if (IS_DSC(dsc->line, "%%Page:")) { 3069 /* This should not occur in the trailer, but we might see 3070 * this if a document has been incorrectly embedded. 3071 */ 3072 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER, 3073 dsc->line, dsc->line_length); 3074 switch (rc) { 3075 case CDSC_RESPONSE_OK: 3076 /* Assume that we are really in the previous */ 3077 /* page, not the trailer */ 3078 dsc->scan_section = scan_pre_pages; 3079 if (dsc->page_count) 3080 dsc->page[dsc->page_count-1].end = DSC_START(dsc); 3081 return CDSC_PROPAGATE; /* try again */ 3082 case CDSC_RESPONSE_CANCEL: 3083 /* ignore pages in trailer */ 3084 break; 3085 case CDSC_RESPONSE_IGNORE_ALL: 3086 return CDSC_NOTDSC; 3087 } 3088 } 3089 else if (IS_DSC(line, "%%DocumentNeededFonts:")) { 3090 dsc->id = CDSC_DOCUMENTNEEDEDFONTS; 3091 /* ignore */ 3092 } 3093 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) { 3094 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS; 3095 /* ignore */ 3096 } 3097 else { 3098 /* All other DSC comments are unknown, but not an error */ 3099 dsc->id = CDSC_UNKNOWNDSC; 3100 dsc_unknown(dsc); 3101 } 3102 3103 dsc->endtrailer = DSC_END(dsc); 3104 return CDSC_OK; 3105 } 3106 3107 3108 dsc_private char * 3109 dsc_alloc_string(CDSC *dsc, const char *str, int len) 3110 { 3111 char *p; 3112 if (dsc->string_head == NULL) { 3113 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING)); 3114 if (dsc->string_head == NULL) 3115 return NULL; /* no memory */ 3116 dsc->string = dsc->string_head; 3117 dsc->string->next = NULL; 3118 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK); 3119 if (dsc->string->data == NULL) { 3120 dsc_reset(dsc); 3121 return NULL; /* no memory */ 3122 } 3123 dsc->string->index = 0; 3124 dsc->string->length = CDSC_STRING_CHUNK; 3125 } 3126 if ( dsc->string->index + len + 1 > dsc->string->length) { 3127 /* allocate another string block */ 3128 CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING)); 3129 if (newstring == NULL) { 3130 dsc_debug_print(dsc, "Out of memory\n"); 3131 return NULL; 3132 } 3133 newstring->next = NULL; 3134 newstring->length = 0; 3135 newstring->index = 0; 3136 newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK); 3137 if (newstring->data == NULL) { 3138 dsc_memfree(dsc, newstring); 3139 dsc_debug_print(dsc, "Out of memory\n"); 3140 return NULL; /* no memory */ 3141 } 3142 newstring->length = CDSC_STRING_CHUNK; 3143 dsc->string->next = newstring; 3144 dsc->string = newstring; 3145 } 3146 if ( dsc->string->index + len + 1 > dsc->string->length) 3147 return NULL; /* failed */ 3148 p = dsc->string->data + dsc->string->index; 3149 memcpy(p, str, len); 3150 *(p+len) = '\0'; 3151 dsc->string->index += len + 1; 3152 return p; 3153 } 3154 3155 /* store line, ignoring leading spaces */ 3156 dsc_private char * 3157 dsc_add_line(CDSC *dsc, const char *line, unsigned int len) 3158 { 3159 char *newline; 3160 unsigned int i; 3161 while (len && (IS_WHITE(*line))) { 3162 len--; 3163 line++; 3164 } 3165 newline = dsc_alloc_string(dsc, line, len); 3166 if (newline == NULL) 3167 return NULL; 3168 3169 for (i=0; i<len; i++) { 3170 if (newline[i] == '\r') { 3171 newline[i]='\0'; 3172 break; 3173 } 3174 if (newline[i] == '\n') { 3175 newline[i]='\0'; 3176 break; 3177 } 3178 } 3179 return newline; 3180 } 3181 3182 3183 /* Copy string on line to new allocated string str */ 3184 /* String is always null terminated */ 3185 /* String is no longer than len */ 3186 /* Return pointer to string */ 3187 /* Store number of used characters from line */ 3188 /* Don't copy enclosing () */ 3189 dsc_private char * 3190 dsc_copy_string(char *str, unsigned int slen, char *line, 3191 unsigned int len, unsigned int *offset) 3192 { 3193 int quoted = FALSE; 3194 int instring=0; 3195 unsigned int newlength = 0; 3196 unsigned int i = 0; 3197 unsigned char ch; 3198 if (len > slen) 3199 len = slen-1; 3200 while ( (i<len) && IS_WHITE(line[i])) 3201 i++; /* skip leading spaces */ 3202 if (line[i]=='(') { 3203 quoted = TRUE; 3204 instring++; 3205 i++; /* don't copy outside () */ 3206 } 3207 while (i < len) { 3208 str[newlength] = ch = line[i]; 3209 i++; 3210 if (quoted) { 3211 if (ch == '(') 3212 instring++; 3213 if (ch == ')') 3214 instring--; 3215 if (instring==0) 3216 break; 3217 } 3218 else if (ch == ' ') 3219 break; 3220 3221 if (ch == '\r') 3222 break; 3223 if (ch == '\n') 3224 break; 3225 else if ( (ch == '\\') && (i+1 < len) ) { 3226 ch = line[i]; 3227 if ((ch >= '0') && (ch <= '9')) { 3228 /* octal coded character */ 3229 int j = 3; 3230 ch = 0; 3231 while (j && (i < len) && line[i]>='0' && line[i]<='7') { 3232 ch = (unsigned char)((ch<<3) + (line[i]-'0')); 3233 i++; 3234 j--; 3235 } 3236 str[newlength] = ch; 3237 } 3238 else if (ch == '(') { 3239 str[newlength] = ch; 3240 i++; 3241 } 3242 else if (ch == ')') { 3243 str[newlength] = ch; 3244 i++; 3245 } 3246 else if (ch == 'b') { 3247 str[newlength] = '\b'; 3248 i++; 3249 } 3250 else if (ch == 'f') { 3251 str[newlength] = '\b'; 3252 i++; 3253 } 3254 else if (ch == 'n') { 3255 str[newlength] = '\n'; 3256 i++; 3257 } 3258 else if (ch == 'r') { 3259 str[newlength] = '\r'; 3260 i++; 3261 } 3262 else if (ch == 't') { 3263 str[newlength] = '\t'; 3264 i++; 3265 } 3266 else if (ch == '\\') { 3267 str[newlength] = '\\'; 3268 i++; 3269 } 3270 } 3271 newlength++; 3272 } 3273 str[newlength] = '\0'; 3274 if (offset != (unsigned int *)NULL) 3275 *offset = i; 3276 return str; 3277 } 3278 3279 dsc_private int 3280 dsc_get_int(const char *line, unsigned int len, unsigned int *offset) 3281 { 3282 char newline[MAXSTR]; 3283 int newlength = 0; 3284 unsigned int i = 0; 3285 unsigned char ch; 3286 3287 len = min(len, sizeof(newline)-1); 3288 while ((i<len) && IS_WHITE(line[i])) 3289 i++; /* skip leading spaces */ 3290 while (i < len) { 3291 newline[newlength] = ch = line[i]; 3292 if (!(isdigit(ch) || (ch=='-') || (ch=='+'))) 3293 break; /* not part of an integer number */ 3294 i++; 3295 newlength++; 3296 } 3297 while ((i<len) && IS_WHITE(line[i])) 3298 i++; /* skip trailing spaces */ 3299 newline[newlength] = '\0'; 3300 if (offset != (unsigned int *)NULL) 3301 *offset = i; 3302 return atoi(newline); 3303 } 3304 3305 dsc_private float 3306 dsc_get_real(const char *line, unsigned int len, unsigned int *offset) 3307 { 3308 char newline[MAXSTR]; 3309 int newlength = 0; 3310 unsigned int i = 0; 3311 unsigned char ch; 3312 3313 len = min(len, sizeof(newline)-1); 3314 while ((i<len) && IS_WHITE(line[i])) 3315 i++; /* skip leading spaces */ 3316 while (i < len) { 3317 newline[newlength] = ch = line[i]; 3318 if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+') 3319 || (ch=='e') || (ch=='E'))) 3320 break; /* not part of a real number */ 3321 i++; 3322 newlength++; 3323 } 3324 while ((i<len) && IS_WHITE(line[i])) 3325 i++; /* skip trailing spaces */ 3326 3327 newline[newlength] = '\0'; 3328 3329 if (offset != (unsigned int *)NULL) 3330 *offset = i; 3331 return (float)atof(newline); 3332 } 3333 3334 dsc_private int 3335 dsc_stricmp(const char *s, const char *t) 3336 { 3337 while (toupper(*s) == toupper(*t)) { 3338 if (*s == '\0') 3339 return 0; 3340 s++; 3341 t++; 3342 } 3343 return (toupper(*s) - toupper(*t)); 3344 } 3345 3346 3347 dsc_private int 3348 dsc_parse_page(CDSC *dsc) 3349 { 3350 char *p; 3351 unsigned int i; 3352 char page_label[MAXSTR]; 3353 char *pl; 3354 int page_ordinal; 3355 int page_number; 3356 3357 p = dsc->line + 7; 3358 pl = dsc_copy_string(page_label, sizeof(page_label)-1, p, dsc->line_length-7, &i); 3359 if (pl == NULL) 3360 return CDSC_ERROR; 3361 p += i; 3362 page_ordinal = atoi(p); 3363 3364 if ( (page_ordinal == 0) || (strlen(page_label) == 0) || 3365 (dsc->page_count && 3366 (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) { 3367 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line, 3368 dsc->line_length); 3369 switch (rc) { 3370 case CDSC_RESPONSE_OK: 3371 /* ignore this page */ 3372 return CDSC_OK; 3373 case CDSC_RESPONSE_CANCEL: 3374 /* accept the page */ 3375 break; 3376 case CDSC_RESPONSE_IGNORE_ALL: 3377 return CDSC_NOTDSC; 3378 } 3379 } 3380 3381 page_number = dsc->page_count; 3382 dsc_add_page(dsc, page_ordinal, page_label); 3383 dsc->page[page_number].begin = DSC_START(dsc); 3384 dsc->page[page_number].end = DSC_START(dsc); 3385 3386 if (dsc->page[page_number].label == NULL) 3387 return CDSC_ERROR; /* no memory */ 3388 3389 return CDSC_OK; 3390 } 3391 3392 3393 3394 /* DSC error reporting */ 3395 3396 void 3397 dsc_debug_print(CDSC *dsc, const char *str) 3398 { 3399 if (dsc->debug_print_fn) 3400 dsc->debug_print_fn(dsc->caller_data, str); 3401 } 3402 3403 3404 /* Display a message about a problem with the DSC comments. 3405 * 3406 * explanation = an index to to a multiline explanation in dsc_message[] 3407 * line = pointer to the offending DSC line (if any) 3408 * return code = 3409 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what 3410 * was really meant. 3411 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it 3412 * is misplaced. 3413 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC. 3414 */ 3415 /* Silent operation. Don't display errors. */ 3416 dsc_private int 3417 dsc_error(CDSC *dsc, unsigned int explanation, 3418 char *line, unsigned int line_len) 3419 { 3420 /* if error function provided, use it */ 3421 if (dsc->dsc_error_fn) 3422 return dsc->dsc_error_fn(dsc->caller_data, dsc, 3423 explanation, line, line_len); 3424 3425 /* treat DSC as being correct */ 3426 return CDSC_RESPONSE_CANCEL; 3427 } 3428 3429 3430 // vim:sw=4:sts=4:ts=8:noet