~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/zdscpars.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied, modified
8
 
   or distributed except as expressly authorized under the terms of that
9
 
   license.  Refer to licensing information at http://www.artifex.com/
10
 
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11
 
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
 
*/
13
 
 
14
 
/* $Id: zdscpars.c 8653 2008-04-20 23:40:49Z alexcher $ */
15
 
/* C language interface routines to DSC parser */
16
 
 
17
 
/*
18
 
 * The DSC parser consists of three pieces.  The first piece is a DSC parser
19
 
 * which was coded by Russell Lang (dscparse.c and dscparse.h).  The second
20
 
 * piece is this module.  These two are sufficient to parse DSC comments
21
 
 * and make them available to a client written in PostScript.  The third
22
 
 * piece is a PostScript language module (gs_dscp.ps) that uses certain
23
 
 * comments to affect the interpretation of the file.
24
 
 *
25
 
 * The .initialize_dsc_parser operator defined in this file creates an
26
 
 * instance of Russell's parser, and puts it in a client-supplied dictionary
27
 
 * under a known name (/DSC_struct).
28
 
 *
29
 
 * When the PostScript scanner sees a possible DSC comment (first characters
30
 
 * in a line are %%), it calls the procedure that is the value of the user
31
 
 * parameter ProcessDSCComments.  This procedure should loads the dictionary
32
 
 * that was passed to .initialize_dsc_parser, and then call the
33
 
 * .parse_dsc_comments operator defined in this file.
34
 
 *
35
 
 * These two operators comprise the interface between PostScript and C code.
36
 
 *
37
 
 * There is a "feature" named usedsc that loads a PostScript file
38
 
 * (gs_dscp.ps), which installs a simple framework for processing DSC
39
 
 * comments and having them affect interpretation of the file (e.g., by
40
 
 * setting page device parameters).  See gs_dscp.ps for more information.
41
 
 *
42
 
 * .parse_dsc_comments pulls the comment string off of the stack and passes
43
 
 * it to Russell's parser.  That parser parses the comment and puts any
44
 
 * parameter values into a DSC structure.  That parser also returns a code
45
 
 * which indicates which type of comment was found.  .parse_dsc_comments
46
 
 * looks at the return code and transfers any interesting parameters from
47
 
 * the DSC structure into key value pairs in the dsc_dict dictionary.  It
48
 
 * also translates the comment type code into a key name (comment name).
49
 
 * The key name is placed on the operand stack.  Control then returns to
50
 
 * PostScript code, which can pull the key name from the operand stack and
51
 
 * use it to determine what further processing needs to be done at the PS
52
 
 * language level.
53
 
 *
54
 
 * To add support for new DSC comments:
55
 
 *
56
 
 * 1. Verify that Russell's parser supports the comment.  If not, then add
57
 
 *    the required support.
58
 
 *
59
 
 * 2. Add an entry into DSCcmdlist.  This table contains three values for
60
 
 *    each command that we support.  The first is Russell's return code for
61
 
 *    the command. The second is the key name that we pass back on the
62
 
 *    operand stack.  (Thus this table translates Russell's codes into key
63
 
 *    names for the PostScript client.)  The third entry is a pointer to a
64
 
 *    local function for transferring values from Russell's DSC structure
65
 
 *    into key/value pairs in dsc_dict.
66
 
 *
67
 
 * 3. Create the local function described at the end of the last item.
68
 
 *    There are some support routines like dsc_put_integer() and
69
 
 *    dsc_put_string() to help implement these functions.
70
 
 *
71
 
 * 4. If the usedsc feature should recognize and process the new comments,
72
 
 *    add a processing routine into the dictionary DSCparserprocs in
73
 
 *    gs_dscp.ps.  The keys in this dictionary are the key names described
74
 
 *    in item 2 above.
75
 
 */
76
 
 
77
 
#include "ghost.h"
78
 
#include "string_.h"
79
 
#include "memory_.h"
80
 
#include "gsstruct.h"
81
 
#include "ialloc.h"
82
 
#include "iname.h"
83
 
#include "istack.h"             /* for iparam.h */
84
 
#include "iparam.h"
85
 
#include "ivmspace.h"
86
 
#include "oper.h"
87
 
#include "estack.h"
88
 
#include "store.h"
89
 
#include "idict.h"
90
 
#include "iddict.h"
91
 
#include "dscparse.h"
92
 
 
93
 
/*
94
 
 * Declare the structure we use to represent an instance of the parser
95
 
 * as a t_struct.  Currently it just saves a pointer to Russell's
96
 
 * data structure.
97
 
 */
98
 
typedef struct dsc_data_s {
99
 
    CDSC *dsc_data_ptr;
100
 
    int document_level;
101
 
} dsc_data_t;
102
 
 
103
 
/* Structure descriptors */
104
 
static void dsc_finalize(void *vptr);
105
 
gs_private_st_simple_final(st_dsc_data_t, dsc_data_t, "dsc_data_struct", dsc_finalize);
106
 
 
107
 
/* Define the key name for storing the instance pointer in a dictionary. */
108
 
static const char * const dsc_dict_name = "DSC_struct";
109
 
 
110
 
/* ---------------- Initialization / finalization ---------------- */
111
 
 
112
 
/*
113
 
 * If we return CDSC_OK then Russell's parser will make it best guess when
114
 
 * it encounters unexpected comment situations.
115
 
 */
116
 
static int
117
 
dsc_error_handler(void *caller_data, CDSC *dsc, unsigned int explanation,
118
 
                  const char *line, unsigned int line_len)
119
 
{
120
 
    return CDSC_OK;
121
 
}
122
 
 
123
 
/*
124
 
 * This operator creates a new, initialized instance of the DSC parser.
125
 
 */
126
 
/* <dict> .initialize_dsc_parser - */
127
 
static int
128
 
zinitialize_dsc_parser(i_ctx_t *i_ctx_p)
129
 
{
130
 
    ref local_ref;
131
 
    int code;
132
 
    os_ptr const op = osp;
133
 
    dict * const pdict = op->value.pdict;
134
 
    gs_memory_t * const mem = (gs_memory_t *)dict_memory(pdict);
135
 
    dsc_data_t * const data =
136
 
        gs_alloc_struct(mem, dsc_data_t, &st_dsc_data_t, "DSC parser init");
137
 
 
138
 
    if (!data)
139
 
        return_error(e_VMerror);
140
 
    data->document_level = 0;
141
 
    data->dsc_data_ptr = dsc_init((void *) "Ghostscript DSC parsing");
142
 
    if (!data->dsc_data_ptr)
143
 
        return_error(e_VMerror);
144
 
    dsc_set_error_function(data->dsc_data_ptr, dsc_error_handler);
145
 
    make_astruct(&local_ref, a_readonly | r_space(op), (byte *) data);
146
 
    code = idict_put_string(op, dsc_dict_name, &local_ref);
147
 
    if (code >= 0)
148
 
        pop(1);
149
 
    return code;
150
 
}
151
 
 
152
 
/*
153
 
 * This routine will free the memory associated with Russell's parser.
154
 
 */
155
 
static void
156
 
dsc_finalize(void *vptr)
157
 
{
158
 
    dsc_data_t * const st = vptr;
159
 
 
160
 
    if (st->dsc_data_ptr)
161
 
        dsc_free(st->dsc_data_ptr);
162
 
    st->dsc_data_ptr = NULL;
163
 
}
164
 
 
165
 
 
166
 
/* ---------------- Parsing ---------------- */
167
 
 
168
 
/* ------ Utilities for returning values ------ */
169
 
 
170
 
/* Return an integer value. */
171
 
static int
172
 
dsc_put_int(gs_param_list *plist, const char *keyname, int value)
173
 
{
174
 
    return param_write_int(plist, keyname, &value);
175
 
}
176
 
 
177
 
/* Return a string value. */
178
 
static int
179
 
dsc_put_string(gs_param_list *plist, const char *keyname,
180
 
               const char *string)
181
 
{
182
 
    gs_param_string str;
183
 
 
184
 
    param_string_from_transient_string(str, string);
185
 
    return param_write_string(plist, keyname, &str);
186
 
}
187
 
 
188
 
/* Return a BoundingBox value. */
189
 
static int
190
 
dsc_put_bounding_box(gs_param_list *plist, const char *keyname,
191
 
                     const CDSCBBOX *pbbox)
192
 
{
193
 
    /* pbbox is NULL iff the bounding box values was "(atend)". */
194
 
    int values[4];
195
 
    gs_param_int_array va;
196
 
 
197
 
    if (!pbbox)
198
 
        return 0;
199
 
    values[0] = pbbox->llx;
200
 
    values[1] = pbbox->lly;
201
 
    values[2] = pbbox->urx;
202
 
    values[3] = pbbox->ury;
203
 
    va.data = values;
204
 
    va.size = 4;
205
 
    va.persistent = false;
206
 
    return param_write_int_array(plist, keyname, &va);
207
 
}
208
 
 
209
 
/* ------ Return values for individual comment types ------ */
210
 
 
211
 
/*
212
 
 * These routines transfer data from the C structure into Postscript
213
 
 * key/value pairs in a dictionary.
214
 
 */
215
 
static int
216
 
dsc_adobe_header(gs_param_list *plist, const CDSC *pData)
217
 
{
218
 
    return dsc_put_int(plist, "EPSF", (int)(pData->epsf? 1: 0));
219
 
}
220
 
 
221
 
static int
222
 
dsc_creator(gs_param_list *plist, const CDSC *pData)
223
 
{
224
 
    return dsc_put_string(plist, "Creator", pData->dsc_creator );
225
 
}
226
 
 
227
 
static int
228
 
dsc_creation_date(gs_param_list *plist, const CDSC *pData)
229
 
{
230
 
    return dsc_put_string(plist, "CreationDate", pData->dsc_date );
231
 
}
232
 
 
233
 
static int
234
 
dsc_title(gs_param_list *plist, const CDSC *pData)
235
 
{
236
 
    return dsc_put_string(plist, "Title", pData->dsc_title );
237
 
}
238
 
 
239
 
static int
240
 
dsc_for(gs_param_list *plist, const CDSC *pData)
241
 
{
242
 
    return dsc_put_string(plist, "For", pData->dsc_for);
243
 
}
244
 
 
245
 
static int
246
 
dsc_bounding_box(gs_param_list *plist, const CDSC *pData)
247
 
{
248
 
    return dsc_put_bounding_box(plist, "BoundingBox", pData->bbox);
249
 
}
250
 
 
251
 
static int
252
 
dsc_page(gs_param_list *plist, const CDSC *pData)
253
 
{
254
 
    int page_num = pData->page_count;
255
 
 
256
 
    if (page_num)               /* If we have page information */
257
 
        return dsc_put_int(plist, "PageNum",
258
 
                       pData->page[page_num - 1].ordinal );
259
 
    else                        /* No page info - so return page=0 */
260
 
        return dsc_put_int(plist, "PageNum", 0 );
261
 
}
262
 
 
263
 
static int
264
 
dsc_pages(gs_param_list *plist, const CDSC *pData)
265
 
{
266
 
    return dsc_put_int(plist, "NumPages", pData->page_pages);
267
 
}
268
 
 
269
 
static int
270
 
dsc_page_bounding_box(gs_param_list *plist, const CDSC *pData)
271
 
{
272
 
    return dsc_put_bounding_box(plist, "PageBoundingBox", pData->page_bbox);
273
 
}
274
 
 
275
 
/*
276
 
 * Translate Russell's defintions of orientation into Postscript's.
277
 
 */
278
 
static int
279
 
convert_orient(CDSC_ORIENTATION_ENUM orient)
280
 
{
281
 
    switch (orient) {
282
 
    case CDSC_PORTRAIT: return 0;
283
 
    case CDSC_LANDSCAPE: return 1;
284
 
    case CDSC_UPSIDEDOWN: return 2;
285
 
    case CDSC_SEASCAPE: return 3;
286
 
    default: return -1;
287
 
    }
288
 
}
289
 
 
290
 
static int
291
 
dsc_page_orientation(gs_param_list *plist, const CDSC *pData)
292
 
{
293
 
    int page_num = pData->page_count;
294
 
 
295
 
    /*
296
 
     * The PageOrientation comment might be either in the 'defaults'
297
 
     * section or in a page section.  If in the defaults then fhe value
298
 
     * will be in page_orientation.
299
 
     */
300
 
    if (page_num && pData->page[page_num - 1].orientation != CDSC_ORIENT_UNKNOWN)
301
 
        return dsc_put_int(plist, "PageOrientation",
302
 
                        convert_orient(pData->page[page_num - 1].orientation));
303
 
    else
304
 
        return dsc_put_int(plist, "Orientation",
305
 
                           convert_orient(pData->page_orientation));
306
 
}
307
 
 
308
 
static int
309
 
dsc_orientation(gs_param_list *plist, const CDSC *pData)
310
 
{
311
 
    return dsc_put_int(plist, "Orientation", 
312
 
                           convert_orient(pData->page_orientation));
313
 
}
314
 
 
315
 
static int
316
 
dsc_viewing_orientation(gs_param_list *plist, const CDSC *pData)
317
 
{
318
 
    int page_num = pData->page_count;
319
 
    const char *key;
320
 
    const CDSCCTM *pctm;
321
 
    float values[4];
322
 
    gs_param_float_array va;
323
 
 
324
 
    /*
325
 
     * As for PageOrientation, ViewingOrientation may be either in the
326
 
     * 'defaults' section or in a page section.
327
 
     */
328
 
    if (page_num && pData->page[page_num - 1].viewing_orientation != NULL) {
329
 
        key = "PageViewingOrientation";
330
 
        pctm = pData->page[page_num - 1].viewing_orientation;
331
 
    } else {
332
 
        key = "ViewingOrientation";
333
 
        pctm = pData->viewing_orientation;
334
 
    }
335
 
    values[0] = pctm->xx;
336
 
    values[1] = pctm->xy;
337
 
    values[2] = pctm->yx;
338
 
    values[3] = pctm->yy;
339
 
    va.data = values;
340
 
    va.size = 4;
341
 
    va.persistent = false;
342
 
    return param_write_float_array(plist, key, &va);
343
 
}
344
 
 
345
 
/*
346
 
 * This list is used to translate the commment code returned
347
 
 * from Russell's DSC parser, define a name, and a parameter procedure.
348
 
 */
349
 
typedef struct cmdlist_s {
350
 
    int code;                   /* Russell's DSC parser code (see dsc.h) */
351
 
    const char *comment_name;   /* A name to be returned to postscript caller */
352
 
    int (*dsc_proc) (gs_param_list *, const CDSC *);
353
 
                                /* A routine for transferring parameter values
354
 
                                   from C data structure to postscript dictionary
355
 
                                   key/value pairs. */
356
 
} cmdlist_t;
357
 
 
358
 
static const cmdlist_t DSCcmdlist[] = { 
359
 
    { CDSC_PSADOBE,         "Header",           dsc_adobe_header },
360
 
    { CDSC_CREATOR,         "Creator",          dsc_creator },
361
 
    { CDSC_CREATIONDATE,    "CreationDate",     dsc_creation_date },
362
 
    { CDSC_TITLE,           "Title",            dsc_title },
363
 
    { CDSC_FOR,             "For",              dsc_for },
364
 
    { CDSC_BOUNDINGBOX,     "BoundingBox",      dsc_bounding_box },
365
 
    { CDSC_ORIENTATION,     "Orientation",      dsc_orientation },
366
 
    { CDSC_BEGINDEFAULTS,   "BeginDefaults",    NULL },
367
 
    { CDSC_ENDDEFAULTS,     "EndDefaults",      NULL },
368
 
    { CDSC_PAGE,            "Page",             dsc_page },
369
 
    { CDSC_PAGES,           "Pages",            dsc_pages },
370
 
    { CDSC_PAGEORIENTATION, "PageOrientation",  dsc_page_orientation },
371
 
    { CDSC_PAGEBOUNDINGBOX, "PageBoundingBox",  dsc_page_bounding_box },
372
 
    { CDSC_VIEWINGORIENTATION, "ViewingOrientation", dsc_viewing_orientation },
373
 
    { CDSC_EOF,             "EOF",              NULL },
374
 
    { 0,                    "NOP",              NULL }  /* Table terminator */
375
 
};
376
 
 
377
 
/* ------ Parser interface ------ */
378
 
 
379
 
/*
380
 
 * There are a few comments that we do not want to send to Russell's
381
 
 * DSC parser.  If we send the data block type comments, Russell's
382
 
 * parser will want to skip the specified block of data.  This is not
383
 
 * appropriate for our situation.  So we use this list to check for this
384
 
 * type of comment and do not send it to Russell's parser if found.
385
 
 */
386
 
static const char * const BadCmdlist[] = {
387
 
    "%%BeginData:",
388
 
    "%%EndData",
389
 
    "%%BeginBinary:",
390
 
    "%%EndBinary",
391
 
    NULL                            /* List terminator */
392
 
};
393
 
 
394
 
/* See comments at start of module for description. */
395
 
/* <dict> <string> .parse_dsc_comments <dict> <dsc code> */
396
 
static int
397
 
zparse_dsc_comments(i_ctx_t *i_ctx_p)
398
 
{
399
 
#define MAX_DSC_MSG_SIZE (DSC_LINE_LENGTH + 4)  /* Allow for %% and CR/LF */
400
 
    os_ptr const opString = osp;
401
 
    os_ptr const opDict = opString - 1;
402
 
    uint ssize;
403
 
    int comment_code, code;
404
 
    char dsc_buffer[MAX_DSC_MSG_SIZE + 2];
405
 
    const cmdlist_t *pCmdList = DSCcmdlist;
406
 
    const char * const *pBadList = BadCmdlist;
407
 
    ref * pvalue;
408
 
    dsc_data_t * dsc_state = NULL;
409
 
    dict_param_list list;
410
 
 
411
 
    /*
412
 
     * Verify operand types and length of DSC comment string.  If a comment
413
 
     * is too long then we simply truncate it.  Russell's parser gets to
414
 
     * handle any errors that may result.  (Crude handling but the comment
415
 
     * is bad, so ...).
416
 
     */
417
 
    check_type(*opString, t_string);
418
 
    check_dict_write(*opDict);
419
 
    ssize = r_size(opString);
420
 
    if (ssize > MAX_DSC_MSG_SIZE)   /* need room for EOL + \0 */
421
 
        ssize = MAX_DSC_MSG_SIZE;
422
 
    /*
423
 
     * Retrieve our state.
424
 
     */
425
 
    code = dict_find_string(opDict, dsc_dict_name, &pvalue);
426
 
    if (code < 0)
427
 
        return code;
428
 
    dsc_state = r_ptr(pvalue, dsc_data_t);
429
 
    /*
430
 
     * Pick up the comment string to be parsed.
431
 
     */
432
 
    memcpy(dsc_buffer, opString->value.bytes, ssize);
433
 
    dsc_buffer[ssize] = 0x0d;       /* Russell wants a 'line end' */
434
 
    dsc_buffer[ssize + 1] = 0;      /* Terminate string */
435
 
    /*
436
 
     * Skip data block comments (see comments in front of BadCmdList).
437
 
     */
438
 
    while (*pBadList && strncmp(*pBadList, dsc_buffer, strlen(*pBadList)))
439
 
        pBadList++;
440
 
    if (*pBadList) {                /* If found in list, then skip comment */   
441
 
        comment_code = 0;           /* Ignore */
442
 
        if (dsc_buffer[2] == 'B') {
443
 
            dsc_state->document_level++;
444
 
        } else if (dsc_state->document_level > 0) {
445
 
            dsc_state->document_level--;
446
 
        }
447
 
    }
448
 
    else if (dsc_state->document_level > 0) {
449
 
       comment_code = 0;            /* Ignore */
450
 
    } else {
451
 
        /*
452
 
         * Parse comments - use Russell Lang's DSC parser.  We need to get
453
 
         * data area for Russell Lang's parser.  Note: We have saved the
454
 
         * location of the data area for the parser in our DSC dict.
455
 
         */
456
 
        comment_code = dsc_scan_data(dsc_state->dsc_data_ptr, dsc_buffer, ssize + 1);
457
 
        if_debug1('%', "[%%].parse_dsc_comments: code = %d\n", comment_code);
458
 
        /*
459
 
         * We ignore any errors from Russell's parser.  The only value that
460
 
         * it will return for an error is -1 so there is very little information.
461
 
         * We also do not want bad DSC comments to abort processing of an
462
 
         * otherwise valid PS file.
463
 
         */
464
 
        if (comment_code < 0)
465
 
            comment_code = 0;
466
 
    }
467
 
    /*
468
 
     * Transfer data from DSC structure to postscript variables.
469
 
     * Look up proper handler in the local cmd decode list.
470
 
     */
471
 
    while (pCmdList->code && pCmdList->code != comment_code )
472
 
        pCmdList++;
473
 
    if (pCmdList->dsc_proc) {
474
 
        code = dict_param_list_write(&list, opDict, NULL, iimemory);
475
 
        if (code < 0)
476
 
            return code;
477
 
        code = (pCmdList->dsc_proc)((gs_param_list *)&list, dsc_state->dsc_data_ptr);
478
 
        iparam_list_release(&list);
479
 
        if (code < 0)
480
 
            return code;
481
 
    }
482
 
 
483
 
    /* Put DSC comment name onto operand stack (replace string). */
484
 
 
485
 
    return name_enter_string(imemory, pCmdList->comment_name, opString);
486
 
}
487
 
 
488
 
/* ------ Initialization procedure ------ */
489
 
 
490
 
const op_def zdscpars_op_defs[] = {
491
 
    {"1.initialize_dsc_parser", zinitialize_dsc_parser},
492
 
    {"2.parse_dsc_comments", zparse_dsc_comments},
493
 
    op_def_end(0)
494
 
};