📄 dscparse.cpp
字号:
/* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved. This file is part of GSview. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public Licence for full details. Everyone is granted permission to copy, modify and redistribute this file, but only under the conditions described in the GNU General Public Licence. A copy of this license is supposed to have been given to you along with this file so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies.*//* $Id: dscparse.cpp 420737 2005-06-01 09:09:35Z wgreven $ *//* dscparse.c - DSC parser *//* * This is a DSC parser, based on the DSC 3.0 spec, * with a few DSC 2.1 additions for page size. * * Current limitations: * %%+ may be used after any comment in the comment or trailer, * but is currently only supported by * %%DocumentMedia * * DSC 2.1 additions (discontinued in DSC 3.0): * %%DocumentPaperColors: * %%DocumentPaperForms: * %%DocumentPaperSizes: * %%DocumentPaperWeights: * %%PaperColor: (ignored) * %%PaperForm: (ignored) * %%PaperSize: * %%PaperWeight: (ignored) * * DSC 3.0 additions * %%Copyright * * Other additions for defaults or page section % %%ViewingOrientation: xx xy yx yy*/#include <stdio.h> /* for sprintf(), not file I/O */#include <stdlib.h>#include <string.h>#include <ctype.h>#define MAXSTR 256#include "dscparse.h"/* Macros for comparing string literals * For maximum speed, the length of the second macro argument is * computed at compile time. * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL. */#define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)#define IS_DSC(line, str) (COMPARE((line), (str)))/* Macros for comparing the first one or two characters */#define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))#define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))#define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))#define IS_BLANK(str) (IS_EOL(str[0]))#define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))/* Macros for document offset to start and end of line */#define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)#define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)/* dsc_scan_SECTION() functions return one of * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC * or one of the following *//* The line should be passed on to the next section parser. */#define CDSC_PROPAGATE 10/* If document is DOS EPS and we haven't read 30 bytes, ask for more. */#define CDSC_NEEDMORE 11/* local prototypes */dsc_private void * dsc_memalloc(P2(CDSC *dsc, size_t size));dsc_private void dsc_memfree(P2(CDSC*dsc, void *ptr));dsc_private CDSC * dsc_init2(P1(CDSC *dsc));dsc_private void dsc_reset(P1(CDSC *dsc));dsc_private void dsc_section_join(P3(unsigned long begin, unsigned long *pend, unsigned long **pplast));dsc_private int dsc_read_line(P1(CDSC *dsc));dsc_private int dsc_read_doseps(P1(CDSC *dsc));dsc_private char * dsc_alloc_string(P3(CDSC *dsc, const char *str, int len));dsc_private char * dsc_add_line(P3(CDSC *dsc, const char *line, unsigned int len));dsc_private char * dsc_copy_string(P5(char *str, unsigned int slen, char *line, unsigned int len, unsigned int *offset));dsc_private GSDWORD dsc_get_dword(P1(const unsigned char *buf));dsc_private GSWORD dsc_get_word(P1(const unsigned char *buf));dsc_private int dsc_get_int(P3(const char *line, unsigned int len, unsigned int *offset));dsc_private float dsc_get_real(P3(const char *line, unsigned int len, unsigned int *offset));dsc_private int dsc_stricmp(P2(const char *s, const char *t));dsc_private void dsc_unknown(P1(CDSC *dsc)); dsc_private GSBOOL dsc_is_section(char *line);dsc_private int dsc_parse_pages(P1(CDSC *dsc));dsc_private int dsc_parse_bounding_box(P3(CDSC *dsc, CDSCBBOX** pbbox, int offset));dsc_private int dsc_parse_float_bounding_box(P3(CDSC *dsc, CDSCFBBOX** pfbbox, int offset));dsc_private int dsc_parse_orientation(P3(CDSC *dsc, unsigned int *porientation, int offset));dsc_private int dsc_parse_order(P1(CDSC *dsc));dsc_private int dsc_parse_media(P2(CDSC *dsc, const CDSCMEDIA **page_media));dsc_private int dsc_parse_document_media(P1(CDSC *dsc));dsc_private int dsc_parse_viewing_orientation(P2(CDSC *dsc, CDSCCTM **pctm));dsc_private int dsc_parse_page(P1(CDSC *dsc));dsc_private void dsc_save_line(P1(CDSC *dsc));dsc_private int dsc_scan_type(P1(CDSC *dsc));dsc_private int dsc_scan_comments(P1(CDSC *dsc));dsc_private int dsc_scan_preview(P1(CDSC *dsc));dsc_private int dsc_scan_defaults(P1(CDSC *dsc));dsc_private int dsc_scan_prolog(P1(CDSC *dsc));dsc_private int dsc_scan_setup(P1(CDSC *dsc));dsc_private int dsc_scan_page(P1(CDSC *dsc));dsc_private int dsc_scan_trailer(P1(CDSC *dsc));dsc_private int dsc_error(P4(CDSC *dsc, unsigned int explanation, char *line, unsigned int line_len));/* DSC error reporting */dsc_private const int dsc_severity[] = { CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */ 0};#define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = { /* These sizes taken from Ghostscript gs_statd.ps */ {"11x17", 792, 1224, 0, NULL, NULL, NULL}, {"A0", 2380, 3368, 0, NULL, NULL, NULL}, {"A1", 1684, 2380, 0, NULL, NULL, NULL}, {"A2", 1190, 1684, 0, NULL, NULL, NULL}, {"A3", 842, 1190, 0, NULL, NULL, NULL}, {"A4", 595, 842, 0, NULL, NULL, NULL}, {"A5", 421, 595, 0, NULL, NULL, NULL}, {"A6", 297, 421, 0, NULL, NULL, NULL}, {"A7", 210, 297, 0, NULL, NULL, NULL}, {"A8", 148, 210, 0, NULL, NULL, NULL}, {"A9", 105, 148, 0, NULL, NULL, NULL}, {"A10", 74, 105, 0, NULL, NULL, NULL}, {"B0", 2836, 4008, 0, NULL, NULL, NULL}, {"B1", 2004, 2836, 0, NULL, NULL, NULL}, {"B2", 1418, 2004, 0, NULL, NULL, NULL}, {"B3", 1002, 1418, 0, NULL, NULL, NULL}, {"B4", 709, 1002, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */ {"B5", 501, 709, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */ {"B6", 354, 501, 0, NULL, NULL, NULL}, {"C0", 2600, 3677, 0, NULL, NULL, NULL}, {"C1", 1837, 2600, 0, NULL, NULL, NULL}, {"C2", 1298, 1837, 0, NULL, NULL, NULL}, {"C3", 918, 1298, 0, NULL, NULL, NULL}, {"C4", 649, 918, 0, NULL, NULL, NULL}, {"C5", 459, 649, 0, NULL, NULL, NULL}, {"C6", 323, 459, 0, NULL, NULL, NULL}, {"Ledger", 1224, 792, 0, NULL, NULL, NULL}, {"Legal", 612, 1008, 0, NULL, NULL, NULL}, {"Letter", 612, 792, 0, NULL, NULL, NULL}, {"Note", 612, 792, 0, NULL, NULL, NULL},// ISO and JIS B sizes are different.... {"jisb0", 2916, 4128, 0, NULL, NULL, NULL}, {"jisb1", 2064, 2916, 0, NULL, NULL, NULL}, {"jisb2", 1458, 2064, 0, NULL, NULL, NULL}, {"jisb3", 1032, 1458, 0, NULL, NULL, NULL}, {"jisb4", 729, 1032, 0, NULL, NULL, NULL}, {"jisb5", 516, 729, 0, NULL, NULL, NULL}, {"jisb6", 363, 516, 0, NULL, NULL, NULL}, // U.S. CAD standard paper sizes {"archE", 2592, 3456, 0, NULL, NULL, NULL}, {"archD", 1728, 2592, 0, NULL, NULL, NULL}, {"archC", 1296, 1728, 0, NULL, NULL, NULL}, {"archB", 864, 1296, 0, NULL, NULL, NULL}, {"archA", 648, 864, 0, NULL, NULL, NULL}, // Other paper sizes {"flsa", 612, 936, 0, NULL, NULL, NULL}, /* U.S. foolscap */ {"flse", 612, 936, 0, NULL, NULL, NULL}, /* European foolscap */ {"halfletter", 396, 612, 0, NULL, NULL, NULL}, {NULL, 0, 0, 0, NULL, NULL, NULL}};/* parser state */enum CDSC_SCAN_SECTION { scan_none = 0, scan_comments = 1, scan_pre_preview = 2, scan_preview = 3, scan_pre_defaults = 4, scan_defaults = 5, scan_pre_prolog = 6, scan_prolog = 7, scan_pre_setup = 8, scan_setup = 9, scan_pre_pages = 10, scan_pages = 11, scan_pre_trailer = 12, scan_trailer = 13, scan_eof = 14};static const char * const dsc_scan_section_name[15] = { "Type", "Comments", "pre-Preview", "Preview", "pre-Defaults", "Defaults", "pre-Prolog", "Prolog", "pre-Setup", "Setup", "pre-Page", "Page", "pre-Trailer", "Trailer", "EOF"};/******************************************************************//* Public functions *//******************************************************************//* constructor */CDSC *dsc_init(void *caller_data){ CDSC *dsc = (CDSC *)malloc(sizeof(CDSC)); if (dsc == NULL) return NULL; memset(dsc, 0, sizeof(CDSC)); dsc->caller_data = caller_data; return dsc_init2(dsc);}/* constructor, with caller supplied memalloc */CDSC *dsc_init_with_alloc( void *caller_data, void *(*memalloc)(size_t size, void *closure_data), void (*memfree)(void *ptr, void *closure_data), void *closure_data){ CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data); if (dsc == NULL) return NULL; memset(dsc, 0, sizeof(CDSC)); dsc->caller_data = caller_data; dsc->memalloc = memalloc; dsc->memfree = memfree; dsc->mem_closure_data = closure_data; return dsc_init2(dsc);}/* destructor */void dsc_free(CDSC *dsc){ if (dsc == NULL) return; dsc_reset(dsc); dsc_memfree(dsc, dsc);}/* Tell DSC parser how long document will be, to allow ignoring * of early %%Trailer and %%EOF. This is optional. */void dsc_set_length(CDSC *dsc, unsigned long len){ dsc->file_length = len;}/* Process a buffer containing DSC comments and PostScript *//* Return value is < 0 for error, >=0 for OK. * CDSC_ERROR * CDSC_OK * CDSC_NOTDSC (DSC will be ignored) * other values indicate the last DSC comment read */ intdsc_scan_data(CDSC *dsc, const char *data, int length){ int bytes_read; int code = 0; if (dsc == NULL) return CDSC_ERROR; if (dsc->id == CDSC_NOTDSC) return CDSC_NOTDSC; dsc->id = CDSC_OK; if (dsc->eof) return CDSC_OK; /* ignore */ if (length == 0) { /* EOF, so process what remains */ dsc->eof = TRUE; } do { if (dsc->id == CDSC_NOTDSC) break; if (length != 0) { /* move existing data if needed */ if (dsc->data_length > CDSC_DATA_LENGTH/2) { memmove(dsc->data, dsc->data + dsc->data_index, dsc->data_length - dsc->data_index); dsc->data_offset += dsc->data_index; dsc->data_length -= dsc->data_index; dsc->data_index = 0; } /* append to buffer */ bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length)); memcpy(dsc->data + dsc->data_length, data, bytes_read); dsc->data_length += bytes_read; data += bytes_read; length -= bytes_read; } if (dsc->scan_section == scan_none) { code = dsc_scan_type(dsc); if (code == CDSC_NEEDMORE) { /* need more characters before we can identify type */ code = CDSC_OK; break; } dsc->id = code; } if (code == CDSC_NOTDSC) { dsc->id = CDSC_NOTDSC; break; } while ((code = dsc_read_line(dsc)) > 0) { if (dsc->id == CDSC_NOTDSC) break; if (dsc->doseps_end && (dsc->data_offset + dsc->data_index > dsc->doseps_end)) { /* have read past end of DOS EPS PostScript section */ return CDSC_OK; /* ignore */ } if (dsc->eof) return CDSC_OK; if (dsc->skip_document) continue; /* embedded document */ if (dsc->skip_lines) continue; /* embedded lines */ if (IS_DSC(dsc->line, "%%BeginData:")) continue; if (IS_DSC(dsc->line, "%%BeginBinary:")) continue; if (IS_DSC(dsc->line, "%%EndDocument")) continue; if (IS_DSC(dsc->line, "%%EndData")) continue; if (IS_DSC(dsc->line, "%%EndBinary")) continue; do { switch (dsc->scan_section) { case scan_comments: code = dsc_scan_comments(dsc); break; case scan_pre_preview: case scan_preview: code = dsc_scan_preview(dsc); break; case scan_pre_defaults: case scan_defaults: code = dsc_scan_defaults(dsc); break; case scan_pre_prolog: case scan_prolog: code = dsc_scan_prolog(dsc); break; case scan_pre_setup: case scan_setup: code = dsc_scan_setup(dsc); break; case scan_pre_pages: case scan_pages: code = dsc_scan_page(dsc); break; case scan_pre_trailer: case scan_trailer: code = dsc_scan_trailer(dsc); break; case scan_eof: code = CDSC_OK; break; default: /* invalid state */ code = CDSC_ERROR; } /* repeat if line is start of next section */ } while (code == CDSC_PROPAGATE); /* if DOS EPS header not complete, ask for more */ if (code == CDSC_NEEDMORE) { code = CDSC_OK; break; } if (code == CDSC_NOTDSC) { dsc->id = CDSC_NOTDSC; break; } } } while (length != 0); return (code < 0) ? code : dsc->id;}/* Tidy up from incorrect DSC comments */int dsc_fixup(CDSC *dsc){ unsigned int i; char buf[32]; unsigned long *last; if (dsc->id == CDSC_NOTDSC) return 0; /* flush last partial line */ dsc_scan_data(dsc, NULL, 0); /* Fix DSC error: code between %%EndSetup and %%Page */ if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup) && (dsc->endsetup != dsc->beginsetup)) { dsc->endsetup = dsc->page[0].begin; dsc_debug_print(dsc, "Warning: code included between setup and first page\n"); } /* Last page contained a false trailer, */ /* so extend last page to start of trailer */ if (dsc->page_count && (dsc->begintrailer != 0) && (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) { dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n"); dsc_debug_print(dsc, "and extending last page to start of trailer\n"); dsc->page[dsc->page_count-1].end = dsc->begintrailer; } /* * Join up all sections. * There might be extra code between them, or we might have * missed including the \n which followed \r. */ last = &dsc->endcomments; dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last); dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last); dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last); dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -