1 /* Copyright (C) 2000-2002, Ghostgum Software Pty Ltd.  All rights reserved.
2 
3   This file is part of GSview.
4 
5   This program is distributed with NO WARRANTY OF ANY KIND.  No author
6   or distributor accepts any responsibility for the consequences of using it,
7   or for whether it serves any particular purpose or works at all, unless he
8   or she says so in writing.  Refer to the GSview Licence (the "Licence")
9   for full details.
10 
11   Every copy of GSview must include a copy of the Licence, normally in a
12   plain ASCII text file named LICENCE.  The Licence grants you the right
13   to copy, modify and redistribute GSview, but only under certain conditions
14   described in the Licence.  Among other things, the Licence requires that
15   the copyright notice and this notice be preserved on all copies.
16 */
17 
18 /* dscutil.c - text messages for DSC parser and standalone test code */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #if defined(STANDALONE) && !defined(UNIX)
24 #include <io.h>
25 #endif
26 
27 #include "dscparse.h"
28 
29 #define MAXSTR 256
30 
31 int dsc_error_fn(void *caller_data, CDSC *dsc, unsigned int explanation,
32 	const char *line, unsigned int line_len);
33 void dsc_display(CDSC *dsc, void (*dfn)(void *ptr, const char *str));
34 
35 
36 /* We always include the English version of this text in
37  * an array for debug reporting.  Language specific versions
38  * are stored in resources.
39  */
40 
41 const char * const dsc_message[] = {
42 /* CDSC_MESSAGE_BBOX */
43  "This line is incorrect.\n\
44 The bounding box must be in integer coordinates,\n\
45 not floating point. A floating point bounding box should\n\
46 be specified using %%HiResBoundingBox:\n\
47 A %%BoundingBox: should still be provided with integer values.\n\
48 \n\
49 'OK' will convert the coordinates to integers,\n\
50 rounding them outwards.\n\
51 'Cancel' will ignore this line\n",
52 
53 /* CDSC_MESSAGE_EARLY_TRAILER */
54 "The trailer is normally at the end of a document.\n\
55 This line was found more than 32k bytes from the end\n\
56 of the file.  Trailers are not usually this long.\n\
57 It is more likely that another PostScript file has been included,\n\
58 without enclosing it in %%BeginDocument / %%EndDocument.\n\
59 \n\
60 'OK' will assume this is part of an included file.\n\
61 'Cancel' will assume this is the trailer\n",
62 
63 /* CDSC_MESSAGE_EARLY_EOF */
64 "This line normally occurs at the end of a document.\n\
65 This line was found more than 100 bytes from the end\n\
66 of the file.\n\
67 It is more likely that another PostScript file has been included,\n\
68 without enclosing it in %%BeginDocument / %%EndDocument.\n\
69 \n\
70 'OK' will assume this is part of an included file.\n\
71 'Cancel' will assume this is part of the trailer\n",
72 
73 /* CDSC_MESSAGE_PAGE_IN_TRAILER */
74 "This %%Page: line occurred in the trailer, which is not legal.\n\
75 EPS files should be encapsulated in %%BeginDocument / %%EndDocument.\n\
76 If is possible that an EPS file was incorrectly encapsulated,\n\
77 and that we have been confused by the %%Trailer in an EPS file.\n\
78 \n\
79 'OK' will process more pages.\n\
80 'Cancel' will ignore this page comment\n",
81 
82 /* CDSC_MESSAGE_PAGE_ORDINAL */
83 "This line is incorrect.\n\
84 The two arguments should be a label and an ordinal.\n\
85 The ordinal should be 1 for the first page and should\n\
86 increase by 1 for each following page.\n\
87 The page ordinal is missing or is not in sequence.\n\
88 \n\
89 It is likely that this line is part of an included file that\n\
90 was not enclosed in %%BeginDocument / %%EndDocument.\n\
91 \n\
92 'OK' will ignore this page, assuming it is part of an\n\
93 incorrectly encapsulated EPS file.\n\
94 'Cancel' will treat this as a valid page\n",
95 
96 /* CDSC_MESSAGE_PAGES_WRONG */
97 "%%Pages: doesn't match number of %%Page:\n\
98 \n\
99 'OK' will adjust the page count to match the number of %%Page:\n\
100 comments found\n\
101 'Cancel' will set the page count from %%Pages:\n",
102 
103 /* CDSC_MESSAGE_EPS_NO_BBOX */
104 "This EPS file is missing the required %%BoundingBox:\n\
105 See the GSview help for details of how to add/adjust the\n\
106 bounding box.\n\
107 \n\
108 'OK' will assume this as an EPS file\n\
109 'Cancel' will assume this is NOT an EPS file.\n",
110 
111 /* CDSC_MESSAGE_EPS_PAGES */
112 "EPS files may have 0 or 1 pages.  This 'EPS' file has\n\
113 more than this and so is not an EPS file.\n\
114 You cannot use `Print To` `Encapsulated PostScript File` for\n\
115 printing multipage files.  The correct method is to connect\n\
116 the printer to FILE: or to select 'Print to File'.\n\
117 \n\
118 'OK' will assume this as an EPS file\n\
119 'Cancel' will assume this is NOT an EPS file.\n",
120 
121 /* CDSC_MESSAGE_NO_MEDIA */
122 "Media was specified with %%DocumentMedia:, but no default\n\
123 media was specified with %%PageMedia:.\n\
124 \n\
125 'OK' will set the default media to the first listed media.\n\
126 'Cancel' will not set a default media.\n",
127 
128 /* CDSC_MESSAGE_ATEND */
129 "This line is incorrect\n\
130 To defer a value, you must use '(atend)', not 'atend'\n\
131 \n\
132 'OK' will assume that (atend) was meant.\n\
133 'Cancel' will ignore this line.\n",
134 
135 /* CDSC_MESSAGE_DUP_COMMENT */
136 "This comment is duplicated in the header, which is unnecessary.\n\
137 The first occurence of a header line takes precedence.\n\
138 \n\
139 'OK' or 'Cancel' will ignore the duplicate line.\n",
140 
141 /* CDSC_MESSAGE_DUP_TRAILER */
142 "This comment is duplicated in the trailer, which is unnecessary.\n\
143 The last occurence of a trailer line takes precedence.\n\
144 \n\
145 'OK' or 'Cancel' will use the duplicate line.\n",
146 
147 /* CDSC_MESSAGE_BEGIN_END */
148 "The number of Begin and End comments do not match.\n\
149 \n\
150 'OK' or 'Cancel' will ignore this mismatch.\n",
151 
152 /* CDSC_MESSAGE_BAD_SECTION */
153 "This line is incorrect because it should not occur\n\
154 within a page.  This probably indicates that an EPS file\n\
155 was incorrectly encapsulated.  The line will be ignored.\n\
156 \n\
157 'OK' or 'Cancel' will ignore this line.\n",
158 
159 /* CDSC_MESSAGE_LONG_LINE */
160 "\n\nLines in DSC documents must be shorter than 255 characters.\n",
161 
162 /* CDSC_MESSAGE_INCORRECT_USAGE */
163 "This DSC comment line is incorrect.\n\
164 Please refer to the DSC specification.\n\
165 'OK' or 'Cancel' will ignore this mismatch.\n",
166 
167    NULL
168 };
169 
170 int
dsc_error_fn(void * caller_data,CDSC * dsc,unsigned int explanation,const char * line,unsigned int line_len)171 dsc_error_fn(void *caller_data, CDSC *dsc, unsigned int explanation,
172 	const char *line, unsigned int line_len)
173 {
174     int response;
175     int severity;
176     char buf[MAXSTR];
177     if (explanation > dsc->max_error)
178 	return CDSC_RESPONSE_OK;
179 
180     if (caller_data == NULL)	 	/* ignore unused parameter */
181 	dsc_debug_print(dsc, "");	/* do nothing */
182 
183     severity = dsc->severity[explanation];
184 
185     /* If debug function provided, copy messages there */
186     if (dsc->debug_print_fn) {
187 	switch (severity) {
188 	    case CDSC_ERROR_INFORM:
189 		dsc_debug_print(dsc, "\nDSC Information");
190 		break;
191 	    case CDSC_ERROR_WARN:
192 		dsc_debug_print(dsc, "\nDSC Warning");
193 		break;
194 	    case CDSC_ERROR_ERROR:
195 		dsc_debug_print(dsc, "\nDSC Error");
196 	}
197 	dsc_debug_print(dsc, "\n");
198 	if (explanation <= dsc->max_error) {
199 	    if (line && line_len) {
200 		int length = min(line_len, sizeof(buf)-1);
201 		sprintf(buf, "At line %d:\n", dsc->line_count);
202 		dsc_debug_print(dsc, buf);
203 		strncpy(buf, line, length);
204 		buf[length]='\0';
205 		dsc_debug_print(dsc, "  ");
206 		dsc_debug_print(dsc, buf);
207 	    }
208 	    dsc_debug_print(dsc, dsc_message[explanation]);
209 	}
210     }
211 
212     /* Here you could prompt user for OK, Cancel, Ignore ALL DSC */
213     /* In this version, we treat DSC as being correct and return Cancel */
214     response = CDSC_RESPONSE_CANCEL;
215 
216     if (dsc->debug_print_fn) {
217 	switch (response) {
218 	    case CDSC_RESPONSE_OK:
219 		dsc_debug_print(dsc, "Response = OK\n");
220 		break;
221 	    case CDSC_RESPONSE_CANCEL:
222 		dsc_debug_print(dsc, "Response = Cancel\n");
223 		break;
224 	    case CDSC_RESPONSE_IGNORE_ALL:
225 		dsc_debug_print(dsc, "Response = Ignore All DSC\n");
226 		break;
227 	}
228     }
229 
230     return response;
231 }
232 
233 void
dsc_display(CDSC * dsc,void (* dfn)(void * ptr,const char * str))234 dsc_display(CDSC *dsc, void (*dfn)(void *ptr, const char *str))
235 {
236     unsigned int i;
237     const char *p;
238     char buf[MAXSTR];
239     void *ptr = dsc->caller_data;
240     CDCS2 *pdcs = dsc->dcs2;
241     CDSCCOLOUR *colour = dsc->colours;
242     char fmtbuf[MAXSTR];
243     const char *offset_fmt = DSC_OFFSET_FORMAT;
244     (*dfn)(ptr, "== DSC dump ==\n");
245     if (dsc->dsc)
246         (*dfn)(ptr, "DSC ");
247     if (dsc->epsf)
248         (*dfn)(ptr, "EPSF ");
249     if (dsc->doseps)
250         (*dfn)(ptr, "DOSEPS ");
251     if (dsc->macbin)
252         (*dfn)(ptr, "MacBinary ");
253     if (dsc->pdf)
254         (*dfn)(ptr, "PDF ");
255     if (dsc->pjl)
256         (*dfn)(ptr, "PJL ");
257     if (dsc->ctrld)
258         (*dfn)(ptr, "CTRLD ");
259     if (dsc->dcs2)
260         (*dfn)(ptr, "DCS2.0 ");
261     (*dfn)(ptr, "\n");
262 
263     if (dsc->dsc_version) {
264 	(*dfn)(ptr, "version ");
265 	(*dfn)(ptr, dsc->dsc_version);
266 	(*dfn)(ptr, "\n");
267     }
268     if (dsc->dsc_title) {
269 	(*dfn)(ptr, "title ");
270 	(*dfn)(ptr, dsc->dsc_title);
271 	(*dfn)(ptr, "\n");
272     }
273     if (dsc->dsc_creator) {
274 	(*dfn)(ptr, "creator ");
275 	(*dfn)(ptr, dsc->dsc_creator);
276 	(*dfn)(ptr, "\n");
277     }
278     if (dsc->dsc_date) {
279 	(*dfn)(ptr, "date ");
280 	(*dfn)(ptr, dsc->dsc_date);
281 	(*dfn)(ptr, "\n");
282     }
283     if (dsc->dsc_for) {
284 	(*dfn)(ptr, "for ");
285 	(*dfn)(ptr, dsc->dsc_for);
286 	(*dfn)(ptr, "\n");
287     }
288 
289     if (dsc->doseps) {
290 	sprintf(buf, "doseps: ps=%ld %ld  wmf=%ld %ld  tiff=%ld %ld\n",
291 	    dsc->doseps->ps_begin, dsc->doseps->ps_length,
292 	    dsc->doseps->wmf_begin, dsc->doseps->wmf_length,
293 	    dsc->doseps->tiff_begin, dsc->doseps->tiff_length);
294 	(*dfn)(ptr, buf);
295     }
296     if (dsc->macbin) {
297 	sprintf(buf, "macbin ps=%ld %ld  resource=%ld %ld\n",
298 	    dsc->macbin->data_begin, dsc->macbin->data_length,
299 	    dsc->macbin->resource_begin, dsc->macbin->resource_length);
300 	(*dfn)(ptr, buf);
301     }
302     if (dsc->bbox) {
303 	sprintf(buf, "boundingbox %d %d %d %d\n",
304 	    dsc->bbox->llx, dsc->bbox->lly, dsc->bbox->urx, dsc->bbox->ury);
305         (*dfn)(ptr, buf);
306     }
307     if (dsc->hires_bbox) {
308 	sprintf(buf, "hiresboundingbox %f %f %f %f\n",
309 	    dsc->hires_bbox->fllx, dsc->hires_bbox->flly,
310 	    dsc->hires_bbox->furx, dsc->hires_bbox->fury);
311         (*dfn)(ptr, buf);
312     }
313     if (dsc->crop_box) {
314 	sprintf(buf, "cropbox %f %f %f %f\n",
315 	    dsc->crop_box->fllx, dsc->crop_box->flly,
316 	    dsc->crop_box->furx, dsc->crop_box->fury);
317         (*dfn)(ptr, buf);
318     }
319     if (dsc->language_level != 0) {
320         sprintf(buf, "language level %d\n", dsc->language_level);
321         (*dfn)(ptr, buf);
322     }
323     if (dsc->preview != CDSC_NOPREVIEW) {
324 	switch (dsc->preview) {
325 	    case CDSC_NOPREVIEW:
326 		    p = "None";
327 		    break;
328 	    case CDSC_EPSI:
329 		    p = "Interchange";
330 		    break;
331 	    case CDSC_TIFF:
332 		    p = "TIFF";
333 		    break;
334 	    case CDSC_WMF:
335 		    p = "Windows MetaFile";
336 		    break;
337 	    case CDSC_PICT:
338 		    p = "Mac PICT";
339 		    break;
340 	    default:
341 		    p = "Unknown";
342 	}
343 	sprintf(buf, "preview type %s\n", p);
344 	(*dfn)(ptr, buf);
345     }
346 
347     if (dsc->document_data != CDSC_DATA_UNKNOWN) {
348 	switch (dsc->document_data) {
349 	    case CDSC_CLEAN7BIT:
350 		    p = "Clean7Bit";
351 		    break;
352 	    case CDSC_CLEAN8BIT:
353 		    p = "Clean8Bit";
354 		    break;
355 	    case CDSC_BINARY:
356 		    p = "Binary";
357 		    break;
358 	    default:
359 		    p = "Unknown";
360 	}
361 	sprintf(buf, "document data %s\n", p);
362 	(*dfn)(ptr, buf);
363     }
364 
365 
366     if (dsc->page_order != CDSC_ORDER_UNKNOWN) {
367 	switch (dsc->page_order) {
368 	    case CDSC_ASCEND:
369 		    p = "Ascend";
370 		    break;
371 	    case CDSC_DESCEND:
372 		    p = "Descend";
373 		    break;
374 	    case CDSC_SPECIAL:
375 		    p = "Special";
376 		    break;
377 	    default:
378 		    p = "Unknown";
379 	}
380 	sprintf(buf, "page order %s\n", p);
381 	(*dfn)(ptr, buf);
382     }
383 
384     if (dsc->page_orientation != CDSC_ORIENT_UNKNOWN) {
385 	switch (dsc->page_orientation) {
386 	    case CDSC_PORTRAIT:
387 		    p = "Portrait";
388 		    break;
389 	    case CDSC_LANDSCAPE:
390 		    p = "Landscape";
391 		    break;
392 	    default:
393 		    p = "Unknown";
394 	}
395 	sprintf(buf, "page orientation %s\n", p);
396 	(*dfn)(ptr, buf);
397     }
398     if (dsc->page_bbox) {
399 	sprintf(buf, "default page boundingbox %d %d %d %d\n",
400 	    dsc->page_bbox->llx, dsc->page_bbox->lly,
401 	    dsc->page_bbox->urx, dsc->page_bbox->ury);
402         (*dfn)(ptr, buf);
403     }
404 
405     for (i=0; dsc->media && (i<dsc->media_count); i++) {
406 	if (dsc->media[i]) {
407 	    sprintf(buf, "media %d   (%.50s) %g %g %g (%.50s) (%.50s)\n", i,
408 		dsc->media[i]->name ? dsc->media[i]->name : "",
409 		dsc->media[i]->width, dsc->media[i]->height,
410 		dsc->media[i]->weight,
411 		dsc->media[i]->colour ? dsc->media[i]->colour : "",
412 		dsc->media[i]->type ? dsc->media[i]->type : "");
413 	    (*dfn)(ptr, buf);
414 	    if (dsc->media[i]->mediabox) {
415 	        sprintf(buf, "  mediabox %d %d %d %d\n",
416 		    dsc->media[i]->mediabox->llx,
417 		    dsc->media[i]->mediabox->llx,
418 		    dsc->media[i]->mediabox->llx,
419 		    dsc->media[i]->mediabox->llx);
420 		    (*dfn)(ptr, buf);
421 		}
422 	}
423     }
424     if (dsc->page_media) {
425 	sprintf(buf, "default page media %.50s\n", dsc->page_media->name);
426         (*dfn)(ptr, buf);
427     }
428 
429     if (dsc->viewing_orientation) {
430 	sprintf(buf, "default viewing orientation %f %f %f %f\n",
431 	    dsc->viewing_orientation->xx,
432 	    dsc->viewing_orientation->xy,
433 	    dsc->viewing_orientation->yx,
434 	    dsc->viewing_orientation->yy);
435         (*dfn)(ptr, buf);
436     }
437 
438     sprintf(fmtbuf, "comments %%%s %%%s\n", offset_fmt, offset_fmt);
439     sprintf(buf, fmtbuf, dsc->begincomments, dsc->endcomments);
440     (*dfn)(ptr, buf);
441     sprintf(fmtbuf, "preview %%%s %%%s\n", offset_fmt, offset_fmt);
442     sprintf(buf, fmtbuf, dsc->beginpreview, dsc->endpreview);
443     (*dfn)(ptr, buf);
444     sprintf(fmtbuf, "defaults %%%s %%%s\n", offset_fmt, offset_fmt);
445     sprintf(buf, fmtbuf, dsc->begindefaults, dsc->enddefaults);
446     (*dfn)(ptr, buf);
447     sprintf(fmtbuf, "prolog %%%s %%%s\n", offset_fmt, offset_fmt);
448     sprintf(buf, fmtbuf, dsc->beginprolog, dsc->endprolog);
449     (*dfn)(ptr, buf);
450     sprintf(fmtbuf, "setup %%%s %%%s\n", offset_fmt, offset_fmt);
451     sprintf(buf, fmtbuf, dsc->beginsetup, dsc->endsetup);
452     (*dfn)(ptr, buf);
453     sprintf(buf, "pages %d\n", dsc->page_pages);
454     (*dfn)(ptr, buf);
455     for (i=0; i<dsc->page_count; i++) {
456         sprintf(fmtbuf, "page %%.20s %%d  %%%s %%%s\n", offset_fmt, offset_fmt);
457 	sprintf(buf, fmtbuf,
458 	    dsc->page[i].label, dsc->page[i].ordinal,
459 	    dsc->page[i].begin, dsc->page[i].end);
460         (*dfn)(ptr, buf);
461 	if (dsc->page[i].media) {
462 	    sprintf(buf, "  page media %s\n", dsc->page[i].media->name);
463             (*dfn)(ptr, buf);
464 	}
465 	if (dsc->page[i].orientation != CDSC_ORIENT_UNKNOWN) {
466 	    switch (dsc->page[i].orientation) {
467 		case CDSC_PORTRAIT:
468 			p = "Portrait";
469 			break;
470 		case CDSC_LANDSCAPE:
471 			p = "Landscape";
472 			break;
473 		default:
474 			p = "Unknown";
475 	    }
476 	    sprintf(buf, "  page orientation %s\n", p);
477 	    (*dfn)(ptr, buf);
478 	}
479 	if (dsc->page[i].viewing_orientation) {
480 	    sprintf(buf, "  viewing orientation %f %f %f %f\n",
481 		dsc->page[i].viewing_orientation->xx,
482 		dsc->page[i].viewing_orientation->xy,
483 		dsc->page[i].viewing_orientation->yx,
484 		dsc->page[i].viewing_orientation->yy);
485 	    (*dfn)(ptr, buf);
486 	}
487 	if (dsc->page[i].crop_box) {
488 	    sprintf(buf, "pagecropbox %f %f %f %f\n",
489 		dsc->page[i].crop_box->fllx, dsc->page[i].crop_box->flly,
490 		dsc->page[i].crop_box->furx, dsc->page[i].crop_box->fury);
491 	    (*dfn)(ptr, buf);
492 	}
493     }
494     sprintf(fmtbuf, "trailer %%%s %%%s\n", offset_fmt, offset_fmt);
495     sprintf(buf, fmtbuf, dsc->begintrailer, dsc->endtrailer);
496     (*dfn)(ptr, buf);
497     if (pdcs) {
498 	if (dsc->dcs1)
499 	    sprintf(buf, "DCS 1.0 separations\n");
500 	else
501 	    sprintf(buf, "DCS 2.0 separations\n");
502 	(*dfn)(ptr, buf);
503     }
504     while (pdcs) {
505 	if (pdcs->location && (dsc_stricmp(pdcs->location, "Local") == 0))
506 	    sprintf(buf, " %s %s\n", pdcs->colourname, pdcs->filename);
507 	else {
508             sprintf(fmtbuf, " %%s #%%%s %%%s\n", offset_fmt, offset_fmt);
509 	    sprintf(buf, fmtbuf, pdcs->colourname, pdcs->begin, pdcs->end);
510 	}
511         (*dfn)(ptr, buf);
512 	pdcs = pdcs->next;
513     }
514     if (colour) {
515 	sprintf(buf, "colours\n");
516 	(*dfn)(ptr, buf);
517     }
518     while (colour) {
519 	const char *type;
520 	switch (colour->type) {
521 	    case CDSC_COLOUR_PROCESS:
522 		type = "Process";
523 		break;
524 	    case CDSC_COLOUR_CUSTOM:
525 		type = "Custom";
526 		break;
527 	    default:
528 		type = "Unknown";
529 	}
530 	sprintf(buf, " %s %s", colour->name, type);
531         (*dfn)(ptr, buf);
532 	switch (colour->custom) {
533 	    case CDSC_CUSTOM_COLOUR_CMYK:
534 		sprintf(buf, " CMYK %g %g %g %g\n", colour->cyan,
535 		    colour->magenta, colour->yellow, colour->black);
536 		break;
537 	    case CDSC_CUSTOM_COLOUR_RGB:
538 		sprintf(buf, " RGB %g %g %g\n",
539 		    colour->red, colour->green, colour->blue);
540 		break;
541 	    default:
542 		sprintf(buf, "\n");
543 	}
544         (*dfn)(ptr, buf);
545 	colour = colour->next;
546     }
547     for (i=0; dsc->media && (i<dsc->media_count); i++) {
548 	if (dsc->media[i]) {
549 	    sprintf(buf, "media %d   (%.50s) %g %g %g (%.50s) (%.50s)\n", i,
550 		dsc->media[i]->name ? dsc->media[i]->name : "",
551 		dsc->media[i]->width, dsc->media[i]->height,
552 		dsc->media[i]->weight,
553 		dsc->media[i]->colour ? dsc->media[i]->colour : "",
554 		dsc->media[i]->type ? dsc->media[i]->type : "");
555 	    (*dfn)(ptr, buf);
556 	    if (dsc->media[i]->mediabox) {
557 	        sprintf(buf, "  mediabox %d %d %d %d\n",
558 		    dsc->media[i]->mediabox->llx,
559 		    dsc->media[i]->mediabox->llx,
560 		    dsc->media[i]->mediabox->llx,
561 		    dsc->media[i]->mediabox->llx);
562 		    (*dfn)(ptr, buf);
563 		}
564 	}
565     }
566     (*dfn)(ptr, "== END DSC dump ==\n");
567 }
568 
569 
570 #ifdef STANDALONE
571 /****************************************************************/
572 /* TESTING CODE */
573 /****************************************************************/
574 
575 #include <fcntl.h>
576 
577 
dump_fn(void * caller_data,const char * str)578 void dump_fn(void *caller_data, const char *str)
579 {
580     fputs(str, stdout);
581 }
582 
583 #define COPY_BUF_SIZE 4096
584 void
ps_copy(FILE * outfile,FILE * infile,long begin,long end)585 ps_copy(FILE *outfile, FILE *infile, long begin, long end)
586 {
587     char *buf;
588     int count;
589     buf = (char *)malloc(COPY_BUF_SIZE);
590     if (buf == (char *)NULL)
591 	return;
592     if (begin >= 0)
593 	fseek(infile, begin, SEEK_SET);
594     begin = ftell(infile);
595     while (begin < end) {
596         count = min(end-begin, COPY_BUF_SIZE);
597 	if ((count = fread(buf, 1, count, infile)) > 0) {
598 	    fwrite(buf, 1, count, outfile);
599 	    begin += count;
600 	}
601 	else
602 	    begin = end;	/* EOF or error */
603     }
604     free(buf);
605 }
606 
607 long mem_allocated = 0;
608 long mem_signature = 0x5aa5f00f;
609 FILE *mem_file = NULL;
610 #define MEM_FILE "c:/gsview.txt"
611 
612 
debug_memalloc(size_t size,void * closure_data)613 void *debug_memalloc(size_t size, void *closure_data)
614 {
615     void *p = malloc(size + 3 * sizeof(long));
616     long *pl = (long *)p;
617     if (pl) {
618 	pl[0] = mem_signature;
619 	pl[1] = (long)closure_data;
620 	pl[2] = size;
621 	mem_allocated += size;
622 	p = (void *)(pl + 3);
623     }
624 
625     if (mem_file == (FILE *)NULL)
626 	mem_file = fopen(MEM_FILE, "w");
627     if (mem_file != (FILE *)NULL) {
628 	fprintf(mem_file, "memalloc(%d) allocated=%ld ptr=0x%lx\n",
629 	    size, mem_allocated, (long)p);
630 	fflush(mem_file);
631     }
632     return p;
633 }
634 
debug_memfree(void * ptr,void * closure_data)635 void debug_memfree(void *ptr, void *closure_data)
636 {
637     long *pl = (long *)ptr;
638     long oldsize = 0;
639     int corrupted = 0;
640     int closure_mismatch = 0;
641     if (pl) {
642 	pl -= 3;
643 	oldsize = pl[2];
644 	mem_allocated -= oldsize;
645 	if (pl[1] != (long)closure_data)
646 	    closure_mismatch = 1;
647 	if (pl[0] != mem_signature)
648 	    corrupted = 1;
649 	else
650 	    free((void *)pl);
651     }
652 
653     if (mem_file == (FILE *)NULL)
654 	mem_file = fopen(MEM_FILE, "w");
655     if (mem_file != (FILE *)NULL) {
656 	fprintf(mem_file, "memfree(%ld) allocated=%ld ptr=0x%lx\n",
657 	    oldsize, mem_allocated, (long)ptr);
658 	if (closure_mismatch)
659 	    fprintf(mem_file, "memsfree closure_data MISMATCH\n");
660 	if (corrupted)
661 	    fprintf(mem_file, "memfree HEAP IS CORRUPTED\n");
662 	fflush(mem_file);
663     }
664 }
665 
main(int argc,char * argv[])666 int main(int argc, char *argv[])
667 {
668     CDSC *dsc;
669     FILE *infile;
670     char buf[256];
671     char bigbuf[4096];
672     int count;
673     int code;
674     unsigned int i;
675     const char *filename = NULL;
676 
677     if (argc >= 2)
678 	filename = argv[1];
679     if (filename == NULL)
680 	filename = "t.ps";
681     /* file must be opened in BINARY mode */
682     infile = fopen(filename, "rb");
683 
684     if (infile == NULL)
685 	return 1;
686 
687     /* test 1 - write single byte at a time */
688     fprintf(stdout, "TEST 1 - SINGLE BYTE\n");
689     fseek(infile, 0, SEEK_SET);
690     dsc = dsc_init(NULL);
691     dsc_set_debug_function(dsc, dump_fn);
692     dsc_set_error_function(dsc, dsc_error_fn);
693     while ((count = fread(buf, 1, 1, infile))!=0) {
694 	dsc_scan_data(dsc, buf, count);
695     }
696     dsc_fixup(dsc);
697     dsc_display(dsc, dump_fn);
698     dsc_free(dsc);
699 
700     /* test 2 - write multiple bytes at a time */
701     fprintf(stdout, "TEST 2 - %d BYTES\n", sizeof(buf));
702     fseek(infile, 0, SEEK_SET);
703     dsc = dsc_init(NULL);
704     dsc_set_debug_function(dsc, dump_fn);
705     dsc_set_error_function(dsc, dsc_error_fn);
706     while ((count = fread(buf, 1, sizeof(buf), infile))!=0) {
707 	dsc_scan_data(dsc, buf, count);
708     }
709     dsc_fixup(dsc);
710     dsc_display(dsc, dump_fn);
711     dsc_free(dsc);
712 
713     /* test 3 - write one line at a time a time */
714     /* Only works if the file does not contain null characters */
715     fprintf(stdout, "TEST 3 - LINE\n");
716     fseek(infile, 0, SEEK_SET);
717     dsc = dsc_init(NULL);
718     dsc_set_debug_function(dsc, dump_fn);
719     dsc_set_error_function(dsc, dsc_error_fn);
720     memset(buf, 0, sizeof(buf));
721     while (fgets(buf, sizeof(buf)-1, infile) != NULL) {
722 	code  = dsc_scan_data(dsc, buf, strlen(buf));
723 	if (code != CDSC_OK)
724 	    fprintf(stdout, "Line %d, DSC %d\n", dsc->line_count, code);
725     }
726     dsc_fixup(dsc);
727     dsc_display(dsc, dump_fn);
728 
729 
730     fflush(stdout);
731 
732 #ifndef UNIX
733     setmode(fileno(stdout), O_BINARY);
734 #endif
735     fputs("==== COMMENTS ====\r\n", stdout);
736     ps_copy(stdout, infile, dsc->begincomments, dsc->endcomments);
737     fputs("==== PREVIEW ====\r\n", stdout);
738     ps_copy(stdout, infile, dsc->beginpreview, dsc->endpreview);
739     fputs("==== DEFAULTS ====\r\n", stdout);
740     ps_copy(stdout, infile, dsc->begindefaults, dsc->enddefaults);
741     fputs("==== PROLOG ====\r\n", stdout);
742     ps_copy(stdout, infile, dsc->beginprolog, dsc->endprolog);
743     fputs("==== SETUP ====\r\n", stdout);
744     ps_copy(stdout, infile, dsc->beginsetup, dsc->endsetup);
745     for (i=0; i<dsc->page_count; i++) {
746 	fprintf(stdout, "==== PAGE %d ====\r\n", i+1);
747 	ps_copy(stdout, infile, dsc->page[i].begin, dsc->page[i].end);
748     }
749     fputs("==== TRAILER ====\r\n", stdout);
750     ps_copy(stdout, infile, dsc->begintrailer, dsc->endtrailer);
751     fputs("==== EOF ====\r\n", stdout);
752     dsc_free(dsc);
753 
754     /* test 4 - write multiple bytes at a time, debug memalloc */
755     fprintf(stdout, "TEST 4 - %d BYTES, DEBUG MALLOC\n", sizeof(buf));
756     fseek(infile, 0, SEEK_SET);
757     dsc = dsc_init_with_alloc(NULL, debug_memalloc, debug_memfree, NULL);
758     dsc_set_debug_function(dsc, dump_fn);
759     dsc_set_error_function(dsc, dsc_error_fn);
760     while ((count = fread(buf, 1, sizeof(buf), infile))!=0) {
761 	dsc_scan_data(dsc, buf, count);
762     }
763     dsc_fixup(dsc);
764     dsc_display(dsc, dump_fn);
765     dsc_free(dsc);
766     if (mem_file)
767 	fclose(mem_file);
768 
769     /* test 5 - write multiple bytes at a time */
770     fprintf(stdout, "TEST 5 - %d BYTES\n", sizeof(bigbuf));
771     fseek(infile, 0, SEEK_SET);
772     dsc = dsc_init(NULL);
773     dsc_set_debug_function(dsc, dump_fn);
774     dsc_set_error_function(dsc, dsc_error_fn);
775     while ((count = fread(bigbuf, 1, sizeof(bigbuf), infile))!=0) {
776 	dsc_scan_data(dsc, bigbuf, count);
777     }
778     dsc_fixup(dsc);
779     dsc_display(dsc, dump_fn);
780     dsc_free(dsc);
781 
782     dsc = NULL;
783     return 0;
784 }
785 #endif
786