Home | History | Annotate | Download | only in postreverse
      1     0   stevel /*
      2     0   stevel  * CDDL HEADER START
      3     0   stevel  *
      4     0   stevel  * The contents of this file are subject to the terms of the
      5  6633  ps29005  * Common Development and Distribution License (the "License").
      6  6633  ps29005  * You may not use this file except in compliance with the License.
      7     0   stevel  *
      8     0   stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0   stevel  * or http://www.opensolaris.org/os/licensing.
     10     0   stevel  * See the License for the specific language governing permissions
     11     0   stevel  * and limitations under the License.
     12     0   stevel  *
     13     0   stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0   stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0   stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0   stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0   stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0   stevel  *
     19     0   stevel  * CDDL HEADER END
     20     0   stevel  */
     21     0   stevel /*
     22  6633  ps29005  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23     0   stevel  * Use is subject to license terms.
     24     0   stevel  */
     25     0   stevel 
     26     0   stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27     0   stevel 
     28     0   stevel #include <stdio.h>
     29     0   stevel #include <stdlib.h>
     30     0   stevel #include <sys/types.h>
     31     0   stevel #include <sys/file.h>
     32     0   stevel #include <sys/fcntl.h>
     33     0   stevel #include <sys/stat.h>
     34     0   stevel #include <sys/mman.h>
     35     0   stevel #include <string.h>
     36     0   stevel #include <errno.h>
     37     0   stevel #include "postreverse.h"
     38     0   stevel 
     39     0   stevel /*
     40     0   stevel  * This version of postreverse should parse any Adobe DSC conforming
     41     0   stevel  * PostScript file and most that are not conforming, but minimally have the
     42     0   stevel  * page (%%Page:) and trailer (%%Trailer) comments in them at the begining of
     43     0   stevel  * the line.
     44     0   stevel  *
     45     0   stevel  * If a document cannot be parsed (no page and trailer comments), it is passed
     46     0   stevel  * through untouched.  If you look through the code you will find that it
     47     0   stevel  * doesn't ever look for the PostScript magic (%!).  This is because it
     48     0   stevel  * assumes that PostScript is sent in.  If PostScript is in sent in, it will
     49     0   stevel  * still attempt to parse it based on DSC page and trailer comments as if it
     50     0   stevel  * were postscript.
     51     0   stevel  *
     52     0   stevel  * flow goes as follows:
     53     0   stevel  *		1)  get command line options (including parsing a page
     54     0   stevel  *			list if supplied)
     55     0   stevel  *		2)  if no filename is supplied in command line, copy
     56     0   stevel  *			stdin to temp file.
     57     0   stevel  *		3)  parse the document:
     58     0   stevel  *			start from begining looking for a DSC page comment
     59     0   stevel  *			(that is the header) start from the end looking for
     60     0   stevel  *			a DSC trailer comment (that is the trailer) start from
     61     0   stevel  *			the header until the trailer looking for DSC page
     62     0   stevel  *			comments. Each one signifies a new page.
     63     0   stevel  *			start from the header until the trailer looking for BSD
     64     0   stevel  *			global comments. Each one violates page independence and
     65     0   stevel  *			will be stored so it can be printed after the header and
     66     0   stevel  *			before any pages.
     67     0   stevel  *		4)  print the document: if there is no header, trailer, or
     68     0   stevel  *			pages, print it from start to end unaltered if they all
     69     0   stevel  *			exist, print the header, pages, and trailer the pages
     70     0   stevel  *			are compared against a page list before being printed,
     71     0   stevel  *			and are reversed if the reverse flag has been set.
     72     0   stevel  *			If global definitions were found in the pages of a
     73     0   stevel  *			document, they are printed after the header and before
     74     0   stevel  *			the pages.
     75     0   stevel  */
     76     0   stevel 
     77     0   stevel static void *
     78     0   stevel nmalloc(size_t size)
     79     0   stevel {
     80     0   stevel 	void *ret = malloc(size);
     81     0   stevel 
     82     0   stevel 	if (!ret) {
     83     0   stevel 		(void) fprintf(stderr,
     84     0   stevel 			"postreverse : malloc() failed : Out of memory\n");
     85     0   stevel 		exit(2);
     86     0   stevel 	}
     87     0   stevel 	return (ret);
     88     0   stevel }
     89     0   stevel 
     90     0   stevel static void *
     91     0   stevel nrealloc(void *ptr, size_t size)
     92     0   stevel {
     93     0   stevel 	void *ret = realloc(ptr, size);
     94     0   stevel 
     95     0   stevel 	if (!ret) {
     96     0   stevel 		(void) fprintf(stderr,
     97     0   stevel 			"postreverse : realloc() failed - Out of memory\n");
     98     0   stevel 		exit(2);
     99     0   stevel 	}
    100     0   stevel 	return (ret);
    101     0   stevel }
    102     0   stevel 
    103     0   stevel /*
    104     0   stevel  * nstrlen() provides the same functionality as strlen() while also checking
    105     0   stevel  * that the pointer does not cross the end of file.
    106     0   stevel  *
    107     0   stevel  * Returns the number of non-NULL bytes in string argument.
    108     0   stevel  */
    109     0   stevel 
    110     0   stevel static size_t
    111     0   stevel nstrlen(const char *s, char *bptr)
    112     0   stevel {
    113     0   stevel 	const char *s0 = s;
    114     0   stevel 
    115     0   stevel 	while (s < bptr && *s != '\0')
    116     0   stevel 		s++;
    117     0   stevel 	return (s - s0);
    118     0   stevel }
    119     0   stevel 
    120     0   stevel /*
    121     0   stevel  * nstrstr() provides the same functionality as strstr() while also checking
    122     0   stevel  * that the pointers do not cross the end of the file.
    123     0   stevel  *
    124     0   stevel  * nstrstr() locates the first occurrence in the string as1 of the sequence of
    125     0   stevel  * characters (excluding the terminating null character) in the string as2.
    126     0   stevel  * nstrstr() returns a pointer to the located string, or a null pointer if
    127     0   stevel  * the string is not found. If as2 is "", the function returns as1.
    128     0   stevel  */
    129     0   stevel 
    130     0   stevel static char *
    131     0   stevel nstrstr(const char *as1, const char *as2, char *bptr)
    132     0   stevel {
    133     0   stevel 	const char *s1, *s2;
    134     0   stevel 	const char *tptr;
    135     0   stevel 	char c;
    136     0   stevel 
    137     0   stevel 	s1 = as1;
    138     0   stevel 	s2 = as2;
    139     0   stevel 
    140     0   stevel 	if (s2 == NULL || *s2 == '\0')
    141     0   stevel 		return ((char *)s1);
    142     0   stevel 	c = *s2;
    143     0   stevel 
    144     0   stevel 	while (s1 < bptr && *s1)
    145     0   stevel 		if (*s1++ == c) {
    146     0   stevel 			tptr = s1;
    147     0   stevel 			while ((s1 < bptr) &&
    148     0   stevel 				(c = *++s2) == *s1++ && c);
    149     0   stevel 			if (c == 0)
    150     0   stevel 				return ((char *)tptr - 1);
    151     0   stevel 			s1 = tptr;
    152     0   stevel 			s2 = as2;
    153     0   stevel 			c = *s2;
    154     0   stevel 		}
    155     0   stevel 	return (NULL);
    156     0   stevel }
    157     0   stevel 
    158     0   stevel 
    159     0   stevel /*
    160     0   stevel  * caddr_t strrstr(caddr_t as1, caddr_t as2 char *bptr1)
    161     0   stevel  *      return the address of the beginning of the last occruence of as2
    162     0   stevel  *      in as1 or NULL if not found
    163     0   stevel  */
    164     0   stevel caddr_t
    165     0   stevel strrstr(caddr_t s1, caddr_t s2, char *bptr)
    166     0   stevel {
    167     0   stevel 	char *t1, *t2;
    168     0   stevel 	char c;
    169     0   stevel 
    170     0   stevel 
    171     0   stevel 	t1 = s1 + nstrlen(s1, bptr) - 1;
    172     0   stevel 	t2 = s2 + nstrlen(s2, bptr) - 1;
    173     0   stevel 
    174     0   stevel 	if (t2 == NULL || *t2 == '\0')
    175     0   stevel 		return ((char *)t1);
    176     0   stevel 	c = *t2;
    177     0   stevel 
    178     0   stevel 	while (s1 <= t1)
    179     0   stevel 		if (*t1-- == c) {
    180     0   stevel 			while ((c = *--t2) == *t1-- && t2 > s2);
    181     0   stevel 			if (t2 <= s2)
    182     0   stevel 				return ((char *)t1 + 1);
    183     0   stevel 			t2 = s2 + nstrlen(s2, bptr) - 1;
    184     0   stevel 			c = *t2;
    185     0   stevel 		}
    186     0   stevel 	return (NULL);
    187     0   stevel }
    188     0   stevel 
    189     0   stevel /*
    190     0   stevel  * Copy stdin to a temp file and return the name
    191     0   stevel  */
    192     0   stevel char *
    193     0   stevel StdinToFile()
    194     0   stevel {
    195     0   stevel 	char *fileName = tmpnam(NULL);
    196     0   stevel 	int fd;
    197     0   stevel 	int count;
    198     0   stevel 	char buf[BUFSIZ];
    199     0   stevel 
    200     0   stevel 	if ((fd = open(fileName, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
    201     0   stevel 		fprintf(stderr, "open(%s): %s\n", fileName,
    202     0   stevel 			strerror(errno));
    203     0   stevel 		return (NULL);
    204     0   stevel 	}
    205     0   stevel 	while ((count = read(0, buf, sizeof (buf))) > 0)
    206     0   stevel 		if (write(fd, buf, count) != count) {
    207     0   stevel 			fprintf(stderr, "write(%d, 0x%x, %d): %s\n", fd, buf,
    208     0   stevel 				count, strerror(errno));
    209     0   stevel 			close(fd);
    210     0   stevel 			unlink(fileName);
    211     0   stevel 			return (NULL);
    212     0   stevel 		}
    213     0   stevel 	return (fileName);
    214     0   stevel }
    215     0   stevel 
    216     0   stevel /*
    217     0   stevel  * Usage(char *name) - program usage
    218     0   stevel  */
    219     0   stevel void
    220     0   stevel Usage(char *name)
    221     0   stevel {
    222     0   stevel 	fprintf(stderr, "Usage: %s [ -o list ] [ -r ] [ filename ]\n", name);
    223     0   stevel 	exit(1);
    224     0   stevel }
    225     0   stevel 
    226     0   stevel 
    227     0   stevel /*
    228     0   stevel  * int **ParsePageList(char *list)
    229     0   stevel  *    This will parse as string #,#,#-#,#... into an array of pointers
    230     0   stevel  *  to integers.  This array will contain all numbers in the list including
    231     0   stevel  *  those int the range #-#.  The list returned is NULL terminated.
    232     0   stevel  *  It uses 2 passes to build the list.  pass 1 counts the # of ints and
    233     0   stevel  *  allocates the space, and pass 2 fills in the list.
    234     0   stevel  */
    235     0   stevel int **
    236     0   stevel ParsePageList(char *list)
    237     0   stevel {
    238     0   stevel 	int **pageList = NULL;
    239     0   stevel 	int pass = 0;
    240     0   stevel 
    241     0   stevel 	if (list == NULL)
    242     0   stevel 		return (NULL);
    243     0   stevel 
    244     0   stevel 	while (pass++ < 2) {
    245     0   stevel 		char *page;
    246     0   stevel 		char *tmplist;
    247     0   stevel 		int size = 0;
    248     0   stevel 
    249     0   stevel 		tmplist = strdup(list);
    250     0   stevel 		page = strtok(tmplist, ",");
    251     0   stevel 
    252     0   stevel 		do {
    253     0   stevel 			int start, end;
    254     0   stevel 			char *s1 = page, *s2;
    255     0   stevel 
    256     0   stevel 			if (s2 = strchr(page, '-')) {
    257     0   stevel 				*s2++ = NULL;
    258     0   stevel 				start = atoi(s1);
    259     0   stevel 				end = atoi(s2);
    260     0   stevel 				if (end < start) {
    261     0   stevel 					int tmp = end;
    262     0   stevel 
    263     0   stevel 					end = start;
    264     0   stevel 					start = tmp;
    265     0   stevel 				}
    266     0   stevel 			} else
    267     0   stevel 				start = end = atoi(s1);
    268     0   stevel 
    269     0   stevel 			while (start <= end)
    270     0   stevel 				if (pass == 1)
    271     0   stevel 				/* count the pages for allocation */
    272     0   stevel 					size++, start++;
    273     0   stevel 				else {	/* fill in the page list */
    274     0   stevel 					int *tmp = (int *)nmalloc(sizeof (int));
    275     0   stevel 					*tmp = start++;
    276     0   stevel 					pageList[size++] = tmp;
    277     0   stevel 				}
    278     0   stevel 		} while (page = strtok(NULL, ","));
    279     0   stevel 		free(tmplist);
    280     0   stevel 		if (pass == 1)
    281     0   stevel 			pageList = (int **)calloc(sizeof (int *), (size + 1));
    282     0   stevel 	}
    283     0   stevel 	return (pageList);
    284     0   stevel }
    285     0   stevel 
    286     0   stevel 
    287     0   stevel /*
    288     0   stevel  * int PageIsListed(int page, int **pageList)
    289     0   stevel  *    returns 1 if the pagelist is empty or if the page is in the
    290     0   stevel  *  NULL terminated pageList.  returns 0 if the page is not listed
    291     0   stevel  */
    292     0   stevel int
    293     0   stevel PageIsListed(int page, int **pageList)
    294     0   stevel {
    295     0   stevel 	int count = 0;
    296     0   stevel 
    297     0   stevel 	if (!pageList)
    298     0   stevel 		return (1);
    299     0   stevel 
    300     0   stevel 	for (count = 0; pageList[count] != NULL; count++)
    301     0   stevel 		if (*pageList[count] == page)
    302     0   stevel 			return (1);
    303     0   stevel 	return (0);
    304     0   stevel }
    305     0   stevel 
    306     0   stevel 
    307     0   stevel /*
    308     0   stevel  * Writes the document Header to the fd
    309     0   stevel  */
    310     0   stevel int
    311     0   stevel WriteDocumentHeader(int fd, DOCUMENT * d)
    312     0   stevel {
    313     0   stevel 	if (d) {
    314     0   stevel 		HEADER *h = d->header;
    315     0   stevel 
    316     0   stevel 		if (h)
    317     0   stevel 			return (write(fd, h->start, h->size));
    318     0   stevel 	}
    319     0   stevel 	errno = EINVAL;
    320     0   stevel 	return (-1);
    321     0   stevel }
    322     0   stevel 
    323     0   stevel /*
    324     0   stevel  * Writes the document global block to the fd
    325     0   stevel  */
    326     0   stevel int
    327     0   stevel WriteGlobal(int fd, GLOBAL * g)
    328     0   stevel {
    329     0   stevel 	if (g)
    330     0   stevel 		return (write(fd, g->start, g->size));
    331     0   stevel 	errno = EINVAL;
    332     0   stevel 	return (-1);
    333     0   stevel }
    334     0   stevel 
    335     0   stevel /*
    336     0   stevel  * Writes the document Trailer to the fd
    337     0   stevel  */
    338     0   stevel int
    339     0   stevel WriteDocumentTrailer(int fd, DOCUMENT * d)
    340     0   stevel {
    341     0   stevel 	if (d) {
    342     0   stevel 		TRAILER *t = d->trailer;
    343     0   stevel 
    344     0   stevel 		if (t)
    345     0   stevel 			return (write(fd, t->start, t->size));
    346     0   stevel 	}
    347     0   stevel 	errno = EINVAL;
    348     0   stevel 	return (-1);
    349     0   stevel }
    350     0   stevel 
    351     0   stevel /*
    352     0   stevel  * Writes the document page to the fd
    353     0   stevel  */
    354     0   stevel int
    355     0   stevel WritePage(int fd, PAGE * p, int global, char *bptr)
    356     0   stevel {
    357     0   stevel 	if (p) {
    358     0   stevel 		caddr_t ptr1;
    359     0   stevel 
    360     0   stevel 		if (((ptr1 = nstrstr(p->start, PS_BEGIN_GLOBAL, bptr))
    361     0   stevel 			!= NULL) && (ptr1 < p->start + p->size) &&
    362     0   stevel 			    (global != 0)) {
    363     0   stevel 			/* BeginGlobal/EndGlobal in the page... */
    364     0   stevel 			write(fd, p->start, ptr1 - p->start);
    365     0   stevel 			ptr1 = nstrstr(ptr1, PS_END_GLOBAL, bptr);
    366     0   stevel 			ptr1 += nstrlen(PS_END_GLOBAL, bptr);
    367     0   stevel 			return (write(fd, ptr1, (p->size - (ptr1 - p->start))));
    368     0   stevel 		} else
    369     0   stevel 			return (write(fd, p->start, p->size));
    370     0   stevel 	}
    371     0   stevel 	errno = EINVAL;
    372     0   stevel 	return (-1);
    373     0   stevel }
    374     0   stevel 
    375     0   stevel /*
    376     0   stevel  * Writes out the document pages in pageList (or all if NULL) and reverse
    377     0   stevel  * the output if reverse == 1
    378     0   stevel  */
    379     0   stevel void
    380     0   stevel WriteDocument(DOCUMENT * document, int reverse, int **pageList)
    381     0   stevel {
    382     0   stevel 	int count = 0;
    383     0   stevel 	int prnindex;
    384     0   stevel 
    385     0   stevel 	if (document->header && document->trailer && document->page) {
    386     0   stevel 		WriteDocumentHeader(1, document);
    387     0   stevel 
    388     0   stevel 		if (document->global != NULL) {
    389     0   stevel 			while (document->global[count] != NULL) {
    390     0   stevel 				GLOBAL *global = document->global[count++];
    391     0   stevel 
    392     0   stevel 				if (global)
    393     0   stevel 					WriteGlobal(1, global);
    394     0   stevel 			}
    395     0   stevel 		}
    396     0   stevel 		count = reverse ? (document->pages-1) : 0;
    397     0   stevel 
    398     0   stevel 		for (prnindex = 0; prnindex < document->pages; prnindex++) {
    399     0   stevel 			PAGE *page = document->page[count];
    400     0   stevel 
    401     0   stevel 			if (page && PageIsListed(page->number, pageList))
    402     0   stevel 				WritePage(1, page, document->global != NULL,
    403     0   stevel 					document->start + document->size);
    404     0   stevel 
    405     0   stevel 			count = reverse ? count - 1 : count + 1;
    406     0   stevel 		}
    407     0   stevel 
    408     0   stevel 		WriteDocumentTrailer(1, document);
    409     0   stevel 	} else {
    410     0   stevel 		write(1, document->start, document->size);
    411     0   stevel 	}
    412     0   stevel }
    413     0   stevel 
    414     0   stevel /*
    415     0   stevel  * get a document header from document and return a pointer to a HEADER
    416     0   stevel  * structure.
    417     0   stevel  */
    418     0   stevel HEADER *
    419     0   stevel DocumentHeader(DOCUMENT * document)
    420     0   stevel {
    421     0   stevel 	HEADER *header;
    422     0   stevel 	caddr_t start;
    423     0   stevel 
    424     0   stevel 	header = (HEADER *) nmalloc(sizeof (*header));
    425     0   stevel 	memset(header, 0, sizeof (*header));
    426     0   stevel 	if (start = nstrstr(document->start, PS_PAGE,
    427     0   stevel 			    document->start + document->size)) {
    428     0   stevel 		header->label = "Document Header";
    429     0   stevel 		header->start = document->start;
    430     0   stevel 		header->size = (start - document->start + 1);
    431     0   stevel 	} else {
    432     0   stevel 		free(header);
    433     0   stevel 		header = NULL;
    434     0   stevel 	}
    435     0   stevel 	return (header);
    436     0   stevel }
    437     0   stevel 
    438     0   stevel 
    439     0   stevel /*
    440     0   stevel  * get a document trailer from document and return a pointer to a trailer
    441     0   stevel  * structure.
    442     0   stevel  */
    443     0   stevel TRAILER *
    444     0   stevel DocumentTrailer(DOCUMENT * document)
    445     0   stevel {
    446     0   stevel 	TRAILER *trailer;
    447     0   stevel 
    448     0   stevel 	trailer = (TRAILER *) nmalloc(sizeof (*trailer));
    449     0   stevel 	memset(trailer, 0, sizeof (trailer));
    450     0   stevel 	if (trailer->start = strrstr(document->start, PS_TRAILER,
    451     0   stevel 		document->start + document->size)) {
    452     0   stevel 		trailer->label = "Document Trailer";
    453     0   stevel 		trailer->start += 1;
    454     0   stevel 		trailer->size = nstrlen(trailer->start,
    455     0   stevel 			document->start + document->size);
    456     0   stevel 	} else {
    457     0   stevel 		free(trailer);
    458     0   stevel 		trailer = NULL;
    459     0   stevel 	}
    460     0   stevel 	return (trailer);
    461     0   stevel }
    462     0   stevel 
    463     0   stevel GLOBAL **
    464     0   stevel DocumentGlobals(DOCUMENT * document)
    465     0   stevel {
    466     0   stevel 	GLOBAL **globals = NULL, *global;
    467     0   stevel 	caddr_t start, ptr1;
    468     0   stevel 	int count = 0;
    469     0   stevel 	char *bptr = document->start + document->size;
    470     0   stevel 	long allocated_slots = 0;
    471     0   stevel 	caddr_t global_end;
    472     0   stevel 
    473     0   stevel 	start = nstrstr(document->start, PS_PAGE, bptr);
    474     0   stevel 	if (start != NULL) {
    475     0   stevel 		for (ptr1 = nstrstr(start, PS_BEGIN_GLOBAL, bptr); ptr1 != NULL;
    476     0   stevel 			ptr1 = nstrstr(++ptr1, PS_BEGIN_GLOBAL, bptr)) {
    477     0   stevel 			count++;
    478     0   stevel 
    479     0   stevel 			global = (GLOBAL *) nmalloc(sizeof (GLOBAL));
    480     0   stevel 			if ((global_end = nstrstr(++ptr1, PS_END_GLOBAL, bptr))
    481     0   stevel 				== NULL) {
    482     0   stevel 				fprintf(stderr,
    483     0   stevel 					"DSC violation: %%%%BeginGlobal "
    484     0   stevel 						"with no %%%%EndGlobal\n");
    485     0   stevel 				exit(-1);
    486     0   stevel 			}
    487     0   stevel 			memset(global, 0, sizeof (GLOBAL));
    488     0   stevel 			global->start = ptr1;
    489     0   stevel 			global->size = strchr(++global_end, '\n') - ptr1 + 1;
    490     0   stevel 
    491     0   stevel 			if (count > allocated_slots) {
    492     0   stevel 				globals = (GLOBAL **) nrealloc(globals,
    493     0   stevel 					(allocated_slots + BLOCKSIZE) *
    494     0   stevel 						sizeof (GLOBAL *));
    495     0   stevel 				memset(globals +
    496     0   stevel 					allocated_slots * sizeof (GLOBAL *), 0,
    497     0   stevel 						BLOCKSIZE *
    498     0   stevel 							sizeof (GLOBAL *));
    499     0   stevel 				allocated_slots += BLOCKSIZE;
    500     0   stevel 			}
    501     0   stevel 
    502     0   stevel 			globals[count - 1] = global;
    503     0   stevel 			ptr1 = global->start + global->size;
    504     0   stevel 		}
    505     0   stevel 	}
    506     0   stevel 	return (globals);
    507     0   stevel }
    508     0   stevel 
    509     0   stevel 
    510     0   stevel /*
    511     0   stevel  * get the pages from a document and return a pointer a list of PAGE
    512     0   stevel  * structures.
    513     0   stevel  */
    514     0   stevel PAGE **
    515     0   stevel DocumentPages(DOCUMENT * document)
    516     0   stevel {
    517     0   stevel 	PAGE **pages = NULL, *page;
    518     0   stevel 	caddr_t ptr1, page_end;
    519     0   stevel 	char *bptr = document->start + document->size;
    520     0   stevel 	long allocated_slots = 0;
    521     0   stevel 	long no_pages = 0;
    522     0   stevel 	long number;
    523     0   stevel 	char *label, *tmp, *tmp_end;
    524     0   stevel 
    525     0   stevel 	for (ptr1 = nstrstr(document->start, PS_PAGE, bptr); ptr1 != NULL;
    526  6633  ps29005 	    ptr1 = nstrstr(++ptr1, PS_PAGE, bptr)) {
    527     0   stevel 		no_pages++;
    528     0   stevel 
    529     0   stevel 		if (no_pages > allocated_slots) {
    530     0   stevel 			pages = (PAGE **) nrealloc(pages,
    531  6633  ps29005 			    (allocated_slots + BLOCKSIZE) * sizeof (PAGE *));
    532  6633  ps29005 			memset(pages + allocated_slots, 0,
    533  6633  ps29005 			    BLOCKSIZE * sizeof (PAGE *));
    534     0   stevel 			allocated_slots += BLOCKSIZE;
    535     0   stevel 		}
    536     0   stevel 		page = (PAGE *) nmalloc(sizeof (PAGE));
    537     0   stevel 		label = NULL;
    538     0   stevel 		number = -1;
    539     0   stevel 
    540     0   stevel 		/* page start & end */
    541     0   stevel 		if ((page_end = nstrstr(++ptr1, PS_PAGE, bptr)) == NULL)
    542     0   stevel 			if (document->trailer)
    543     0   stevel 				page_end = document->trailer->start - 1;
    544     0   stevel 			else
    545     0   stevel 				page_end = document->start + document->size;
    546     0   stevel 
    547     0   stevel 		/* page label & number */
    548     0   stevel 		if (tmp = strchr(ptr1, ' ')) {
    549     0   stevel 
    550     0   stevel 			if (tmp_end = strchr(++tmp, ' ')) {
    551     0   stevel 				label = (char *)nmalloc((tmp_end - tmp) + 1);
    552     0   stevel 				memset(label, 0, (tmp_end - tmp) + 1);
    553     0   stevel 				strncpy(label, tmp, (tmp_end - tmp));
    554     0   stevel 				number = atol(++tmp_end);
    555     0   stevel 			}
    556     0   stevel 		}
    557     0   stevel 		memset(page, 0, sizeof (PAGE));
    558     0   stevel 		page->label = label;
    559     0   stevel 		page->number = number;
    560     0   stevel 		page->start = ptr1;
    561     0   stevel 		page->size = page_end - ptr1 + 1;
    562     0   stevel 
    563     0   stevel 		pages[document->pages++] = page;
    564     0   stevel 	}
    565     0   stevel 	return (pages);
    566     0   stevel }
    567     0   stevel 
    568     0   stevel /*
    569     0   stevel  * parse a document and return a pointer to a DOCUMENT structure
    570     0   stevel  */
    571     0   stevel DOCUMENT *
    572     0   stevel DocumentParse(char *name)
    573     0   stevel {
    574     0   stevel 	DOCUMENT *document = NULL;
    575     0   stevel 	int fd;
    576     0   stevel 	struct stat st;
    577     0   stevel 
    578     0   stevel 	if (stat(name, &st) < 0) {
    579     0   stevel 		fprintf(stderr, "stat(%s): %s\n", name, strerror(errno));
    580     0   stevel 		return (NULL);
    581     0   stevel 	}
    582     0   stevel 	if (st.st_size == 0) {
    583     0   stevel 		fprintf(stderr, "%s: empty file\n", name);
    584     0   stevel 		return (NULL);
    585     0   stevel 	}
    586     0   stevel 	if ((fd = open(name, O_RDONLY)) < 0) {
    587     0   stevel 		fprintf(stderr, "open(%s, O_RDONLY): %s\n", name,
    588     0   stevel 			strerror(errno));
    589     0   stevel 		return (NULL);
    590     0   stevel 	}
    591     0   stevel 	document = (DOCUMENT *) nmalloc(sizeof (DOCUMENT));
    592     0   stevel 	memset(document, 0, sizeof (DOCUMENT));
    593     0   stevel 	if ((document->start = mmap((void *)0, (size_t)st.st_size, PROT_READ,
    594     0   stevel 		MAP_SHARED, fd, (off_t)0)) == MAP_FAILED) {
    595     0   stevel 		fprintf(stderr, "mmap(0, %ld, PROT_READ,"
    596     0   stevel 			" MAP_SHARED, %d, 0): %s\n",
    597     0   stevel 				st.st_size, fd, strerror(errno));
    598     0   stevel 		free(document);
    599     0   stevel 		document = NULL;
    600     0   stevel 	} else {
    601     0   stevel 		/* order in important */
    602     0   stevel 		document->name = strdup(name);
    603     0   stevel 		document->size = nstrlen(document->start,
    604     0   stevel 			document->start + st.st_size);
    605     0   stevel 		document->header = DocumentHeader(document);
    606     0   stevel 		document->trailer = DocumentTrailer(document);
    607     0   stevel 		document->page = DocumentPages(document);
    608     0   stevel 		document->global = DocumentGlobals(document);
    609     0   stevel 	}
    610     0   stevel 	close(fd);
    611     0   stevel 	return (document);
    612     0   stevel }
    613     0   stevel 
    614     0   stevel 
    615     0   stevel #if defined(DEBUG)
    616     0   stevel /*
    617     0   stevel  * Print out the contents of the document structure
    618     0   stevel  */
    619     0   stevel void
    620     0   stevel PrintDocumentInfo(DOCUMENT * d)
    621     0   stevel {
    622     0   stevel 	if (d) {
    623     0   stevel 		printf("Document:\n\tname:  %s\n\tstart: 0x%x\n\tsize:  %ld\n",
    624     0   stevel 			d->name, d->start, d->size);
    625     0   stevel 		if (d->header) {
    626     0   stevel 			HEADER *h = d->header;
    627     0   stevel 
    628     0   stevel 			printf("\tHeader: %s (0x%x, %ld)\n",
    629     0   stevel 				h->label, h->start, h->size);
    630     0   stevel 		}
    631     0   stevel 		if (d->global) {
    632     0   stevel 			int count = 0;
    633     0   stevel 
    634     0   stevel 			while (d->global[count++] != NULL);
    635     0   stevel 			printf("\tDSC violating BeginGlobals: %d\n", count);
    636     0   stevel 		}
    637     0   stevel 		if (d->page) {
    638     0   stevel 			PAGE *p;
    639     0   stevel 			int count = 0;
    640     0   stevel 
    641     0   stevel 			printf("\tPages: (%d)\n", d->pages);
    642     0   stevel 			for (p = d->page[0]; p != NULL; p = d->page[++count])
    643     0   stevel 				printf("\t\t %4d (%s) - (0x%x, %ld)\n",
    644     0   stevel 					p->number,
    645     0   stevel 						(p->label ? p->label : "Page"),
    646     0   stevel 							p->start, p->size);
    647     0   stevel 		}
    648     0   stevel 		if (d->trailer) {
    649     0   stevel 			TRAILER *t = d->trailer;
    650     0   stevel 
    651     0   stevel 			printf("\tTrailer: %s (0x%x, %ld)\n",
    652     0   stevel 				t->label, t->start, t->size);
    653     0   stevel 		}
    654     0   stevel 	}
    655     0   stevel }
    656     0   stevel #endif				/* DEBUG */
    657     0   stevel 
    658     0   stevel 
    659   320  ceastha int
    660     0   stevel main(int ac, char *av[])
    661     0   stevel {
    662     0   stevel 	DOCUMENT *document;
    663     0   stevel 	char *fileName = NULL;
    664     0   stevel 	char *programName = NULL;
    665     0   stevel 	char *unlinkFile = NULL;
    666     0   stevel 	int reversePages = 1;
    667     0   stevel 	int **pageList = NULL;
    668     0   stevel 	int option;
    669     0   stevel 
    670     0   stevel 	if (programName = strrchr(av[0], '/'))
    671     0   stevel 		programName++;
    672     0   stevel 	else
    673     0   stevel 		programName = av[0];
    674     0   stevel 
    675     0   stevel 	while ((option = getopt(ac, av, "o:r")) != EOF)
    676     0   stevel 		switch (option) {
    677     0   stevel 		case 'o':
    678     0   stevel 			pageList = ParsePageList(optarg);
    679     0   stevel 			break;
    680     0   stevel 		case 'r':
    681     0   stevel 			reversePages = 0;
    682     0   stevel 			break;
    683     0   stevel 		case '?':
    684     0   stevel 			Usage(programName);
    685     0   stevel 			break;
    686     0   stevel 		default:
    687     0   stevel 			fprintf(stderr, "missing case for option %c\n", option);
    688     0   stevel 			Usage(programName);
    689     0   stevel 			break;
    690     0   stevel 		}
    691     0   stevel 
    692     0   stevel 	ac -= optind;
    693     0   stevel 	av += optind;
    694     0   stevel 
    695     0   stevel 	switch (ac) {
    696     0   stevel 	case 0:
    697     0   stevel 		unlinkFile = fileName = StdinToFile();
    698     0   stevel 		break;
    699     0   stevel 	case 1:
    700     0   stevel 		fileName = av[0];
    701     0   stevel 		break;
    702     0   stevel 	default:
    703     0   stevel 		Usage(programName);
    704     0   stevel 	}
    705     0   stevel 
    706     0   stevel 	if ((document = DocumentParse(fileName)) == NULL) {
    707     0   stevel 		fprintf(stderr, "Unable to parse document (%s)\n", fileName);
    708     0   stevel 		exit(0);
    709     0   stevel 	}
    710     0   stevel #if defined(DEBUG) && defined(NOTDEF)
    711     0   stevel 	PrintDocumentInfo(document);
    712     0   stevel #endif				/* DEBUG */
    713     0   stevel 
    714     0   stevel 	WriteDocument(document, reversePages, pageList);
    715     0   stevel 
    716     0   stevel 	if (unlinkFile)
    717     0   stevel 		unlink(unlinkFile);
    718     0   stevel 
    719   320  ceastha 	return (0);
    720     0   stevel }
    721