17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55699d47bSps  * Common Development and Distribution License (the "License").
65699d47bSps  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
225699d47bSps  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/file.h>
307c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
317c478bd9Sstevel@tonic-gate #include <sys/stat.h>
327c478bd9Sstevel@tonic-gate #include <sys/mman.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <errno.h>
357c478bd9Sstevel@tonic-gate #include "postreverse.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * This version of postreverse should parse any Adobe DSC conforming
397c478bd9Sstevel@tonic-gate  * PostScript file and most that are not conforming, but minimally have the
407c478bd9Sstevel@tonic-gate  * page (%%Page:) and trailer (%%Trailer) comments in them at the begining of
417c478bd9Sstevel@tonic-gate  * the line.
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * If a document cannot be parsed (no page and trailer comments), it is passed
447c478bd9Sstevel@tonic-gate  * through untouched.  If you look through the code you will find that it
457c478bd9Sstevel@tonic-gate  * doesn't ever look for the PostScript magic (%!).  This is because it
467c478bd9Sstevel@tonic-gate  * assumes that PostScript is sent in.  If PostScript is in sent in, it will
477c478bd9Sstevel@tonic-gate  * still attempt to parse it based on DSC page and trailer comments as if it
487c478bd9Sstevel@tonic-gate  * were postscript.
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * flow goes as follows:
517c478bd9Sstevel@tonic-gate  *		1)  get command line options (including parsing a page
527c478bd9Sstevel@tonic-gate  *			list if supplied)
537c478bd9Sstevel@tonic-gate  *		2)  if no filename is supplied in command line, copy
547c478bd9Sstevel@tonic-gate  *			stdin to temp file.
557c478bd9Sstevel@tonic-gate  *		3)  parse the document:
567c478bd9Sstevel@tonic-gate  *			start from begining looking for a DSC page comment
577c478bd9Sstevel@tonic-gate  *			(that is the header) start from the end looking for
587c478bd9Sstevel@tonic-gate  *			a DSC trailer comment (that is the trailer) start from
597c478bd9Sstevel@tonic-gate  *			the header until the trailer looking for DSC page
607c478bd9Sstevel@tonic-gate  *			comments. Each one signifies a new page.
617c478bd9Sstevel@tonic-gate  *			start from the header until the trailer looking for BSD
627c478bd9Sstevel@tonic-gate  *			global comments. Each one violates page independence and
637c478bd9Sstevel@tonic-gate  *			will be stored so it can be printed after the header and
647c478bd9Sstevel@tonic-gate  *			before any pages.
657c478bd9Sstevel@tonic-gate  *		4)  print the document: if there is no header, trailer, or
667c478bd9Sstevel@tonic-gate  *			pages, print it from start to end unaltered if they all
677c478bd9Sstevel@tonic-gate  *			exist, print the header, pages, and trailer the pages
687c478bd9Sstevel@tonic-gate  *			are compared against a page list before being printed,
697c478bd9Sstevel@tonic-gate  *			and are reversed if the reverse flag has been set.
707c478bd9Sstevel@tonic-gate  *			If global definitions were found in the pages of a
717c478bd9Sstevel@tonic-gate  *			document, they are printed after the header and before
727c478bd9Sstevel@tonic-gate  *			the pages.
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static void *
nmalloc(size_t size)767c478bd9Sstevel@tonic-gate nmalloc(size_t size)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	void *ret = malloc(size);
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (!ret) {
817c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
827c478bd9Sstevel@tonic-gate 			"postreverse : malloc() failed : Out of memory\n");
837c478bd9Sstevel@tonic-gate 		exit(2);
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 	return (ret);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static void *
nrealloc(void * ptr,size_t size)897c478bd9Sstevel@tonic-gate nrealloc(void *ptr, size_t size)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	void *ret = realloc(ptr, size);
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	if (!ret) {
947c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
957c478bd9Sstevel@tonic-gate 			"postreverse : realloc() failed - Out of memory\n");
967c478bd9Sstevel@tonic-gate 		exit(2);
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 	return (ret);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * nstrlen() provides the same functionality as strlen() while also checking
1037c478bd9Sstevel@tonic-gate  * that the pointer does not cross the end of file.
1047c478bd9Sstevel@tonic-gate  *
1057c478bd9Sstevel@tonic-gate  * Returns the number of non-NULL bytes in string argument.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate static size_t
nstrlen(const char * s,char * bptr)1097c478bd9Sstevel@tonic-gate nstrlen(const char *s, char *bptr)
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate 	const char *s0 = s;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	while (s < bptr && *s != '\0')
1147c478bd9Sstevel@tonic-gate 		s++;
1157c478bd9Sstevel@tonic-gate 	return (s - s0);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * nstrstr() provides the same functionality as strstr() while also checking
1207c478bd9Sstevel@tonic-gate  * that the pointers do not cross the end of the file.
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  * nstrstr() locates the first occurrence in the string as1 of the sequence of
1237c478bd9Sstevel@tonic-gate  * characters (excluding the terminating null character) in the string as2.
1247c478bd9Sstevel@tonic-gate  * nstrstr() returns a pointer to the located string, or a null pointer if
1257c478bd9Sstevel@tonic-gate  * the string is not found. If as2 is "", the function returns as1.
1267c478bd9Sstevel@tonic-gate  */
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate static char *
nstrstr(const char * as1,const char * as2,char * bptr)1297c478bd9Sstevel@tonic-gate nstrstr(const char *as1, const char *as2, char *bptr)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	const char *s1, *s2;
1327c478bd9Sstevel@tonic-gate 	const char *tptr;
1337c478bd9Sstevel@tonic-gate 	char c;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	s1 = as1;
1367c478bd9Sstevel@tonic-gate 	s2 = as2;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	if (s2 == NULL || *s2 == '\0')
1397c478bd9Sstevel@tonic-gate 		return ((char *)s1);
1407c478bd9Sstevel@tonic-gate 	c = *s2;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	while (s1 < bptr && *s1)
1437c478bd9Sstevel@tonic-gate 		if (*s1++ == c) {
1447c478bd9Sstevel@tonic-gate 			tptr = s1;
1457c478bd9Sstevel@tonic-gate 			while ((s1 < bptr) &&
1467c478bd9Sstevel@tonic-gate 				(c = *++s2) == *s1++ && c);
1477c478bd9Sstevel@tonic-gate 			if (c == 0)
1487c478bd9Sstevel@tonic-gate 				return ((char *)tptr - 1);
1497c478bd9Sstevel@tonic-gate 			s1 = tptr;
1507c478bd9Sstevel@tonic-gate 			s2 = as2;
1517c478bd9Sstevel@tonic-gate 			c = *s2;
1527c478bd9Sstevel@tonic-gate 		}
1537c478bd9Sstevel@tonic-gate 	return (NULL);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * caddr_t strrstr(caddr_t as1, caddr_t as2 char *bptr1)
1597c478bd9Sstevel@tonic-gate  *      return the address of the beginning of the last occruence of as2
1607c478bd9Sstevel@tonic-gate  *      in as1 or NULL if not found
1617c478bd9Sstevel@tonic-gate  */
1627c478bd9Sstevel@tonic-gate caddr_t
strrstr(caddr_t s1,caddr_t s2,char * bptr)1637c478bd9Sstevel@tonic-gate strrstr(caddr_t s1, caddr_t s2, char *bptr)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	char *t1, *t2;
1667c478bd9Sstevel@tonic-gate 	char c;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	t1 = s1 + nstrlen(s1, bptr) - 1;
1707c478bd9Sstevel@tonic-gate 	t2 = s2 + nstrlen(s2, bptr) - 1;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	if (t2 == NULL || *t2 == '\0')
1737c478bd9Sstevel@tonic-gate 		return ((char *)t1);
1747c478bd9Sstevel@tonic-gate 	c = *t2;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	while (s1 <= t1)
1777c478bd9Sstevel@tonic-gate 		if (*t1-- == c) {
1787c478bd9Sstevel@tonic-gate 			while ((c = *--t2) == *t1-- && t2 > s2);
1797c478bd9Sstevel@tonic-gate 			if (t2 <= s2)
1807c478bd9Sstevel@tonic-gate 				return ((char *)t1 + 1);
1817c478bd9Sstevel@tonic-gate 			t2 = s2 + nstrlen(s2, bptr) - 1;
1827c478bd9Sstevel@tonic-gate 			c = *t2;
1837c478bd9Sstevel@tonic-gate 		}
1847c478bd9Sstevel@tonic-gate 	return (NULL);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate  * Copy stdin to a temp file and return the name
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate char *
StdinToFile()1917c478bd9Sstevel@tonic-gate StdinToFile()
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	char *fileName = tmpnam(NULL);
1947c478bd9Sstevel@tonic-gate 	int fd;
1957c478bd9Sstevel@tonic-gate 	int count;
1967c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	if ((fd = open(fileName, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
1997c478bd9Sstevel@tonic-gate 		fprintf(stderr, "open(%s): %s\n", fileName,
2007c478bd9Sstevel@tonic-gate 			strerror(errno));
2017c478bd9Sstevel@tonic-gate 		return (NULL);
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 	while ((count = read(0, buf, sizeof (buf))) > 0)
2047c478bd9Sstevel@tonic-gate 		if (write(fd, buf, count) != count) {
2057c478bd9Sstevel@tonic-gate 			fprintf(stderr, "write(%d, 0x%x, %d): %s\n", fd, buf,
2067c478bd9Sstevel@tonic-gate 				count, strerror(errno));
2077c478bd9Sstevel@tonic-gate 			close(fd);
2087c478bd9Sstevel@tonic-gate 			unlink(fileName);
2097c478bd9Sstevel@tonic-gate 			return (NULL);
2107c478bd9Sstevel@tonic-gate 		}
2117c478bd9Sstevel@tonic-gate 	return (fileName);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * Usage(char *name) - program usage
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate void
Usage(char * name)2187c478bd9Sstevel@tonic-gate Usage(char *name)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	fprintf(stderr, "Usage: %s [ -o list ] [ -r ] [ filename ]\n", name);
2217c478bd9Sstevel@tonic-gate 	exit(1);
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * int **ParsePageList(char *list)
2277c478bd9Sstevel@tonic-gate  *    This will parse as string #,#,#-#,#... into an array of pointers
2287c478bd9Sstevel@tonic-gate  *  to integers.  This array will contain all numbers in the list including
2297c478bd9Sstevel@tonic-gate  *  those int the range #-#.  The list returned is NULL terminated.
2307c478bd9Sstevel@tonic-gate  *  It uses 2 passes to build the list.  pass 1 counts the # of ints and
2317c478bd9Sstevel@tonic-gate  *  allocates the space, and pass 2 fills in the list.
2327c478bd9Sstevel@tonic-gate  */
2337c478bd9Sstevel@tonic-gate int **
ParsePageList(char * list)2347c478bd9Sstevel@tonic-gate ParsePageList(char *list)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	int **pageList = NULL;
2377c478bd9Sstevel@tonic-gate 	int pass = 0;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if (list == NULL)
2407c478bd9Sstevel@tonic-gate 		return (NULL);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	while (pass++ < 2) {
2437c478bd9Sstevel@tonic-gate 		char *page;
2447c478bd9Sstevel@tonic-gate 		char *tmplist;
2457c478bd9Sstevel@tonic-gate 		int size = 0;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 		tmplist = strdup(list);
2487c478bd9Sstevel@tonic-gate 		page = strtok(tmplist, ",");
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 		do {
2517c478bd9Sstevel@tonic-gate 			int start, end;
2527c478bd9Sstevel@tonic-gate 			char *s1 = page, *s2;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 			if (s2 = strchr(page, '-')) {
255*e4fb8a5fSToomas Soome 				*s2++ = '\0';
2567c478bd9Sstevel@tonic-gate 				start = atoi(s1);
2577c478bd9Sstevel@tonic-gate 				end = atoi(s2);
2587c478bd9Sstevel@tonic-gate 				if (end < start) {
2597c478bd9Sstevel@tonic-gate 					int tmp = end;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 					end = start;
2627c478bd9Sstevel@tonic-gate 					start = tmp;
2637c478bd9Sstevel@tonic-gate 				}
2647c478bd9Sstevel@tonic-gate 			} else
2657c478bd9Sstevel@tonic-gate 				start = end = atoi(s1);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 			while (start <= end)
2687c478bd9Sstevel@tonic-gate 				if (pass == 1)
2697c478bd9Sstevel@tonic-gate 				/* count the pages for allocation */
2707c478bd9Sstevel@tonic-gate 					size++, start++;
2717c478bd9Sstevel@tonic-gate 				else {	/* fill in the page list */
2727c478bd9Sstevel@tonic-gate 					int *tmp = (int *)nmalloc(sizeof (int));
2737c478bd9Sstevel@tonic-gate 					*tmp = start++;
2747c478bd9Sstevel@tonic-gate 					pageList[size++] = tmp;
2757c478bd9Sstevel@tonic-gate 				}
2767c478bd9Sstevel@tonic-gate 		} while (page = strtok(NULL, ","));
2777c478bd9Sstevel@tonic-gate 		free(tmplist);
2787c478bd9Sstevel@tonic-gate 		if (pass == 1)
2797c478bd9Sstevel@tonic-gate 			pageList = (int **)calloc(sizeof (int *), (size + 1));
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 	return (pageList);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate  * int PageIsListed(int page, int **pageList)
2877c478bd9Sstevel@tonic-gate  *    returns 1 if the pagelist is empty or if the page is in the
2887c478bd9Sstevel@tonic-gate  *  NULL terminated pageList.  returns 0 if the page is not listed
2897c478bd9Sstevel@tonic-gate  */
2907c478bd9Sstevel@tonic-gate int
PageIsListed(int page,int ** pageList)2917c478bd9Sstevel@tonic-gate PageIsListed(int page, int **pageList)
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate 	int count = 0;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	if (!pageList)
2967c478bd9Sstevel@tonic-gate 		return (1);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	for (count = 0; pageList[count] != NULL; count++)
2997c478bd9Sstevel@tonic-gate 		if (*pageList[count] == page)
3007c478bd9Sstevel@tonic-gate 			return (1);
3017c478bd9Sstevel@tonic-gate 	return (0);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate /*
3067c478bd9Sstevel@tonic-gate  * Writes the document Header to the fd
3077c478bd9Sstevel@tonic-gate  */
3087c478bd9Sstevel@tonic-gate int
WriteDocumentHeader(int fd,DOCUMENT * d)3097c478bd9Sstevel@tonic-gate WriteDocumentHeader(int fd, DOCUMENT * d)
3107c478bd9Sstevel@tonic-gate {
3117c478bd9Sstevel@tonic-gate 	if (d) {
3127c478bd9Sstevel@tonic-gate 		HEADER *h = d->header;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 		if (h)
3157c478bd9Sstevel@tonic-gate 			return (write(fd, h->start, h->size));
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 	errno = EINVAL;
3187c478bd9Sstevel@tonic-gate 	return (-1);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate  * Writes the document global block to the fd
3237c478bd9Sstevel@tonic-gate  */
3247c478bd9Sstevel@tonic-gate int
WriteGlobal(int fd,GLOBAL * g)3257c478bd9Sstevel@tonic-gate WriteGlobal(int fd, GLOBAL * g)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate 	if (g)
3287c478bd9Sstevel@tonic-gate 		return (write(fd, g->start, g->size));
3297c478bd9Sstevel@tonic-gate 	errno = EINVAL;
3307c478bd9Sstevel@tonic-gate 	return (-1);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate  * Writes the document Trailer to the fd
3357c478bd9Sstevel@tonic-gate  */
3367c478bd9Sstevel@tonic-gate int
WriteDocumentTrailer(int fd,DOCUMENT * d)3377c478bd9Sstevel@tonic-gate WriteDocumentTrailer(int fd, DOCUMENT * d)
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate 	if (d) {
3407c478bd9Sstevel@tonic-gate 		TRAILER *t = d->trailer;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		if (t)
3437c478bd9Sstevel@tonic-gate 			return (write(fd, t->start, t->size));
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 	errno = EINVAL;
3467c478bd9Sstevel@tonic-gate 	return (-1);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate /*
3507c478bd9Sstevel@tonic-gate  * Writes the document page to the fd
3517c478bd9Sstevel@tonic-gate  */
3527c478bd9Sstevel@tonic-gate int
WritePage(int fd,PAGE * p,int global,char * bptr)3537c478bd9Sstevel@tonic-gate WritePage(int fd, PAGE * p, int global, char *bptr)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate 	if (p) {
3567c478bd9Sstevel@tonic-gate 		caddr_t ptr1;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		if (((ptr1 = nstrstr(p->start, PS_BEGIN_GLOBAL, bptr))
3597c478bd9Sstevel@tonic-gate 			!= NULL) && (ptr1 < p->start + p->size) &&
3607c478bd9Sstevel@tonic-gate 			    (global != 0)) {
3617c478bd9Sstevel@tonic-gate 			/* BeginGlobal/EndGlobal in the page... */
3627c478bd9Sstevel@tonic-gate 			write(fd, p->start, ptr1 - p->start);
3637c478bd9Sstevel@tonic-gate 			ptr1 = nstrstr(ptr1, PS_END_GLOBAL, bptr);
3647c478bd9Sstevel@tonic-gate 			ptr1 += nstrlen(PS_END_GLOBAL, bptr);
3657c478bd9Sstevel@tonic-gate 			return (write(fd, ptr1, (p->size - (ptr1 - p->start))));
3667c478bd9Sstevel@tonic-gate 		} else
3677c478bd9Sstevel@tonic-gate 			return (write(fd, p->start, p->size));
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 	errno = EINVAL;
3707c478bd9Sstevel@tonic-gate 	return (-1);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate  * Writes out the document pages in pageList (or all if NULL) and reverse
3757c478bd9Sstevel@tonic-gate  * the output if reverse == 1
3767c478bd9Sstevel@tonic-gate  */
3777c478bd9Sstevel@tonic-gate void
WriteDocument(DOCUMENT * document,int reverse,int ** pageList)3787c478bd9Sstevel@tonic-gate WriteDocument(DOCUMENT * document, int reverse, int **pageList)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	int count = 0;
3817c478bd9Sstevel@tonic-gate 	int prnindex;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if (document->header && document->trailer && document->page) {
3847c478bd9Sstevel@tonic-gate 		WriteDocumentHeader(1, document);
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 		if (document->global != NULL) {
3877c478bd9Sstevel@tonic-gate 			while (document->global[count] != NULL) {
3887c478bd9Sstevel@tonic-gate 				GLOBAL *global = document->global[count++];
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 				if (global)
3917c478bd9Sstevel@tonic-gate 					WriteGlobal(1, global);
3927c478bd9Sstevel@tonic-gate 			}
3937c478bd9Sstevel@tonic-gate 		}
3947c478bd9Sstevel@tonic-gate 		count = reverse ? (document->pages-1) : 0;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 		for (prnindex = 0; prnindex < document->pages; prnindex++) {
3977c478bd9Sstevel@tonic-gate 			PAGE *page = document->page[count];
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 			if (page && PageIsListed(page->number, pageList))
4007c478bd9Sstevel@tonic-gate 				WritePage(1, page, document->global != NULL,
4017c478bd9Sstevel@tonic-gate 					document->start + document->size);
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 			count = reverse ? count - 1 : count + 1;
4047c478bd9Sstevel@tonic-gate 		}
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		WriteDocumentTrailer(1, document);
4077c478bd9Sstevel@tonic-gate 	} else {
4087c478bd9Sstevel@tonic-gate 		write(1, document->start, document->size);
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate  * get a document header from document and return a pointer to a HEADER
4147c478bd9Sstevel@tonic-gate  * structure.
4157c478bd9Sstevel@tonic-gate  */
4167c478bd9Sstevel@tonic-gate HEADER *
DocumentHeader(DOCUMENT * document)4177c478bd9Sstevel@tonic-gate DocumentHeader(DOCUMENT * document)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate 	HEADER *header;
4207c478bd9Sstevel@tonic-gate 	caddr_t start;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	header = (HEADER *) nmalloc(sizeof (*header));
4237c478bd9Sstevel@tonic-gate 	memset(header, 0, sizeof (*header));
4247c478bd9Sstevel@tonic-gate 	if (start = nstrstr(document->start, PS_PAGE,
4257c478bd9Sstevel@tonic-gate 			    document->start + document->size)) {
4267c478bd9Sstevel@tonic-gate 		header->label = "Document Header";
4277c478bd9Sstevel@tonic-gate 		header->start = document->start;
4287c478bd9Sstevel@tonic-gate 		header->size = (start - document->start + 1);
4297c478bd9Sstevel@tonic-gate 	} else {
4307c478bd9Sstevel@tonic-gate 		free(header);
4317c478bd9Sstevel@tonic-gate 		header = NULL;
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 	return (header);
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate  * get a document trailer from document and return a pointer to a trailer
4397c478bd9Sstevel@tonic-gate  * structure.
4407c478bd9Sstevel@tonic-gate  */
4417c478bd9Sstevel@tonic-gate TRAILER *
DocumentTrailer(DOCUMENT * document)4427c478bd9Sstevel@tonic-gate DocumentTrailer(DOCUMENT * document)
4437c478bd9Sstevel@tonic-gate {
4447c478bd9Sstevel@tonic-gate 	TRAILER *trailer;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	trailer = (TRAILER *) nmalloc(sizeof (*trailer));
4477c478bd9Sstevel@tonic-gate 	memset(trailer, 0, sizeof (trailer));
4487c478bd9Sstevel@tonic-gate 	if (trailer->start = strrstr(document->start, PS_TRAILER,
4497c478bd9Sstevel@tonic-gate 		document->start + document->size)) {
4507c478bd9Sstevel@tonic-gate 		trailer->label = "Document Trailer";
4517c478bd9Sstevel@tonic-gate 		trailer->start += 1;
4527c478bd9Sstevel@tonic-gate 		trailer->size = nstrlen(trailer->start,
4537c478bd9Sstevel@tonic-gate 			document->start + document->size);
4547c478bd9Sstevel@tonic-gate 	} else {
4557c478bd9Sstevel@tonic-gate 		free(trailer);
4567c478bd9Sstevel@tonic-gate 		trailer = NULL;
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 	return (trailer);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate GLOBAL **
DocumentGlobals(DOCUMENT * document)4627c478bd9Sstevel@tonic-gate DocumentGlobals(DOCUMENT * document)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	GLOBAL **globals = NULL, *global;
4657c478bd9Sstevel@tonic-gate 	caddr_t start, ptr1;
4667c478bd9Sstevel@tonic-gate 	int count = 0;
4677c478bd9Sstevel@tonic-gate 	char *bptr = document->start + document->size;
4687c478bd9Sstevel@tonic-gate 	long allocated_slots = 0;
4697c478bd9Sstevel@tonic-gate 	caddr_t global_end;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	start = nstrstr(document->start, PS_PAGE, bptr);
4727c478bd9Sstevel@tonic-gate 	if (start != NULL) {
4737c478bd9Sstevel@tonic-gate 		for (ptr1 = nstrstr(start, PS_BEGIN_GLOBAL, bptr); ptr1 != NULL;
4747c478bd9Sstevel@tonic-gate 			ptr1 = nstrstr(++ptr1, PS_BEGIN_GLOBAL, bptr)) {
4757c478bd9Sstevel@tonic-gate 			count++;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 			global = (GLOBAL *) nmalloc(sizeof (GLOBAL));
4787c478bd9Sstevel@tonic-gate 			if ((global_end = nstrstr(++ptr1, PS_END_GLOBAL, bptr))
4797c478bd9Sstevel@tonic-gate 				== NULL) {
4807c478bd9Sstevel@tonic-gate 				fprintf(stderr,
4817c478bd9Sstevel@tonic-gate 					"DSC violation: %%%%BeginGlobal "
4827c478bd9Sstevel@tonic-gate 						"with no %%%%EndGlobal\n");
4837c478bd9Sstevel@tonic-gate 				exit(-1);
4847c478bd9Sstevel@tonic-gate 			}
4857c478bd9Sstevel@tonic-gate 			memset(global, 0, sizeof (GLOBAL));
4867c478bd9Sstevel@tonic-gate 			global->start = ptr1;
4877c478bd9Sstevel@tonic-gate 			global->size = strchr(++global_end, '\n') - ptr1 + 1;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 			if (count > allocated_slots) {
4907c478bd9Sstevel@tonic-gate 				globals = (GLOBAL **) nrealloc(globals,
4917c478bd9Sstevel@tonic-gate 					(allocated_slots + BLOCKSIZE) *
4927c478bd9Sstevel@tonic-gate 						sizeof (GLOBAL *));
4937c478bd9Sstevel@tonic-gate 				memset(globals +
4947c478bd9Sstevel@tonic-gate 					allocated_slots * sizeof (GLOBAL *), 0,
4957c478bd9Sstevel@tonic-gate 						BLOCKSIZE *
4967c478bd9Sstevel@tonic-gate 							sizeof (GLOBAL *));
4977c478bd9Sstevel@tonic-gate 				allocated_slots += BLOCKSIZE;
4987c478bd9Sstevel@tonic-gate 			}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 			globals[count - 1] = global;
5017c478bd9Sstevel@tonic-gate 			ptr1 = global->start + global->size;
5027c478bd9Sstevel@tonic-gate 		}
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	return (globals);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate  * get the pages from a document and return a pointer a list of PAGE
5107c478bd9Sstevel@tonic-gate  * structures.
5117c478bd9Sstevel@tonic-gate  */
5127c478bd9Sstevel@tonic-gate PAGE **
DocumentPages(DOCUMENT * document)5137c478bd9Sstevel@tonic-gate DocumentPages(DOCUMENT * document)
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate 	PAGE **pages = NULL, *page;
5167c478bd9Sstevel@tonic-gate 	caddr_t ptr1, page_end;
5177c478bd9Sstevel@tonic-gate 	char *bptr = document->start + document->size;
5187c478bd9Sstevel@tonic-gate 	long allocated_slots = 0;
5197c478bd9Sstevel@tonic-gate 	long no_pages = 0;
5207c478bd9Sstevel@tonic-gate 	long number;
5217c478bd9Sstevel@tonic-gate 	char *label, *tmp, *tmp_end;
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	for (ptr1 = nstrstr(document->start, PS_PAGE, bptr); ptr1 != NULL;
5245699d47bSps 	    ptr1 = nstrstr(++ptr1, PS_PAGE, bptr)) {
5257c478bd9Sstevel@tonic-gate 		no_pages++;
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 		if (no_pages > allocated_slots) {
5287c478bd9Sstevel@tonic-gate 			pages = (PAGE **) nrealloc(pages,
5295699d47bSps 			    (allocated_slots + BLOCKSIZE) * sizeof (PAGE *));
5305699d47bSps 			memset(pages + allocated_slots, 0,
5315699d47bSps 			    BLOCKSIZE * sizeof (PAGE *));
5327c478bd9Sstevel@tonic-gate 			allocated_slots += BLOCKSIZE;
5337c478bd9Sstevel@tonic-gate 		}
5347c478bd9Sstevel@tonic-gate 		page = (PAGE *) nmalloc(sizeof (PAGE));
5357c478bd9Sstevel@tonic-gate 		label = NULL;
5367c478bd9Sstevel@tonic-gate 		number = -1;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 		/* page start & end */
5397c478bd9Sstevel@tonic-gate 		if ((page_end = nstrstr(++ptr1, PS_PAGE, bptr)) == NULL)
5407c478bd9Sstevel@tonic-gate 			if (document->trailer)
5417c478bd9Sstevel@tonic-gate 				page_end = document->trailer->start - 1;
5427c478bd9Sstevel@tonic-gate 			else
5437c478bd9Sstevel@tonic-gate 				page_end = document->start + document->size;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 		/* page label & number */
5467c478bd9Sstevel@tonic-gate 		if (tmp = strchr(ptr1, ' ')) {
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 			if (tmp_end = strchr(++tmp, ' ')) {
5497c478bd9Sstevel@tonic-gate 				label = (char *)nmalloc((tmp_end - tmp) + 1);
5507c478bd9Sstevel@tonic-gate 				memset(label, 0, (tmp_end - tmp) + 1);
5517c478bd9Sstevel@tonic-gate 				strncpy(label, tmp, (tmp_end - tmp));
5527c478bd9Sstevel@tonic-gate 				number = atol(++tmp_end);
5537c478bd9Sstevel@tonic-gate 			}
5547c478bd9Sstevel@tonic-gate 		}
5557c478bd9Sstevel@tonic-gate 		memset(page, 0, sizeof (PAGE));
5567c478bd9Sstevel@tonic-gate 		page->label = label;
5577c478bd9Sstevel@tonic-gate 		page->number = number;
5587c478bd9Sstevel@tonic-gate 		page->start = ptr1;
5597c478bd9Sstevel@tonic-gate 		page->size = page_end - ptr1 + 1;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 		pages[document->pages++] = page;
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 	return (pages);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate  * parse a document and return a pointer to a DOCUMENT structure
5687c478bd9Sstevel@tonic-gate  */
5697c478bd9Sstevel@tonic-gate DOCUMENT *
DocumentParse(char * name)5707c478bd9Sstevel@tonic-gate DocumentParse(char *name)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	DOCUMENT *document = NULL;
5737c478bd9Sstevel@tonic-gate 	int fd;
5747c478bd9Sstevel@tonic-gate 	struct stat st;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	if (stat(name, &st) < 0) {
5777c478bd9Sstevel@tonic-gate 		fprintf(stderr, "stat(%s): %s\n", name, strerror(errno));
5787c478bd9Sstevel@tonic-gate 		return (NULL);
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate 	if (st.st_size == 0) {
5817c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: empty file\n", name);
5827c478bd9Sstevel@tonic-gate 		return (NULL);
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 	if ((fd = open(name, O_RDONLY)) < 0) {
5857c478bd9Sstevel@tonic-gate 		fprintf(stderr, "open(%s, O_RDONLY): %s\n", name,
5867c478bd9Sstevel@tonic-gate 			strerror(errno));
5877c478bd9Sstevel@tonic-gate 		return (NULL);
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 	document = (DOCUMENT *) nmalloc(sizeof (DOCUMENT));
5907c478bd9Sstevel@tonic-gate 	memset(document, 0, sizeof (DOCUMENT));
5917c478bd9Sstevel@tonic-gate 	if ((document->start = mmap((void *)0, (size_t)st.st_size, PROT_READ,
5927c478bd9Sstevel@tonic-gate 		MAP_SHARED, fd, (off_t)0)) == MAP_FAILED) {
5937c478bd9Sstevel@tonic-gate 		fprintf(stderr, "mmap(0, %ld, PROT_READ,"
5947c478bd9Sstevel@tonic-gate 			" MAP_SHARED, %d, 0): %s\n",
5957c478bd9Sstevel@tonic-gate 				st.st_size, fd, strerror(errno));
5967c478bd9Sstevel@tonic-gate 		free(document);
5977c478bd9Sstevel@tonic-gate 		document = NULL;
5987c478bd9Sstevel@tonic-gate 	} else {
5997c478bd9Sstevel@tonic-gate 		/* order in important */
6007c478bd9Sstevel@tonic-gate 		document->name = strdup(name);
6017c478bd9Sstevel@tonic-gate 		document->size = nstrlen(document->start,
6027c478bd9Sstevel@tonic-gate 			document->start + st.st_size);
6037c478bd9Sstevel@tonic-gate 		document->header = DocumentHeader(document);
6047c478bd9Sstevel@tonic-gate 		document->trailer = DocumentTrailer(document);
6057c478bd9Sstevel@tonic-gate 		document->page = DocumentPages(document);
6067c478bd9Sstevel@tonic-gate 		document->global = DocumentGlobals(document);
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate 	close(fd);
6097c478bd9Sstevel@tonic-gate 	return (document);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate #if defined(DEBUG)
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate  * Print out the contents of the document structure
6167c478bd9Sstevel@tonic-gate  */
6177c478bd9Sstevel@tonic-gate void
PrintDocumentInfo(DOCUMENT * d)6187c478bd9Sstevel@tonic-gate PrintDocumentInfo(DOCUMENT * d)
6197c478bd9Sstevel@tonic-gate {
6207c478bd9Sstevel@tonic-gate 	if (d) {
6217c478bd9Sstevel@tonic-gate 		printf("Document:\n\tname:  %s\n\tstart: 0x%x\n\tsize:  %ld\n",
6227c478bd9Sstevel@tonic-gate 			d->name, d->start, d->size);
6237c478bd9Sstevel@tonic-gate 		if (d->header) {
6247c478bd9Sstevel@tonic-gate 			HEADER *h = d->header;
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 			printf("\tHeader: %s (0x%x, %ld)\n",
6277c478bd9Sstevel@tonic-gate 				h->label, h->start, h->size);
6287c478bd9Sstevel@tonic-gate 		}
6297c478bd9Sstevel@tonic-gate 		if (d->global) {
6307c478bd9Sstevel@tonic-gate 			int count = 0;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 			while (d->global[count++] != NULL);
6337c478bd9Sstevel@tonic-gate 			printf("\tDSC violating BeginGlobals: %d\n", count);
6347c478bd9Sstevel@tonic-gate 		}
6357c478bd9Sstevel@tonic-gate 		if (d->page) {
6367c478bd9Sstevel@tonic-gate 			PAGE *p;
6377c478bd9Sstevel@tonic-gate 			int count = 0;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 			printf("\tPages: (%d)\n", d->pages);
6407c478bd9Sstevel@tonic-gate 			for (p = d->page[0]; p != NULL; p = d->page[++count])
6417c478bd9Sstevel@tonic-gate 				printf("\t\t %4d (%s) - (0x%x, %ld)\n",
6427c478bd9Sstevel@tonic-gate 					p->number,
6437c478bd9Sstevel@tonic-gate 						(p->label ? p->label : "Page"),
6447c478bd9Sstevel@tonic-gate 							p->start, p->size);
6457c478bd9Sstevel@tonic-gate 		}
6467c478bd9Sstevel@tonic-gate 		if (d->trailer) {
6477c478bd9Sstevel@tonic-gate 			TRAILER *t = d->trailer;
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 			printf("\tTrailer: %s (0x%x, %ld)\n",
6507c478bd9Sstevel@tonic-gate 				t->label, t->start, t->size);
6517c478bd9Sstevel@tonic-gate 		}
6527c478bd9Sstevel@tonic-gate 	}
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate #endif				/* DEBUG */
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 
657f928ce67Sceastha int
main(int ac,char * av[])6587c478bd9Sstevel@tonic-gate main(int ac, char *av[])
6597c478bd9Sstevel@tonic-gate {
6607c478bd9Sstevel@tonic-gate 	DOCUMENT *document;
6617c478bd9Sstevel@tonic-gate 	char *fileName = NULL;
6627c478bd9Sstevel@tonic-gate 	char *programName = NULL;
6637c478bd9Sstevel@tonic-gate 	char *unlinkFile = NULL;
6647c478bd9Sstevel@tonic-gate 	int reversePages = 1;
6657c478bd9Sstevel@tonic-gate 	int **pageList = NULL;
6667c478bd9Sstevel@tonic-gate 	int option;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (programName = strrchr(av[0], '/'))
6697c478bd9Sstevel@tonic-gate 		programName++;
6707c478bd9Sstevel@tonic-gate 	else
6717c478bd9Sstevel@tonic-gate 		programName = av[0];
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	while ((option = getopt(ac, av, "o:r")) != EOF)
6747c478bd9Sstevel@tonic-gate 		switch (option) {
6757c478bd9Sstevel@tonic-gate 		case 'o':
6767c478bd9Sstevel@tonic-gate 			pageList = ParsePageList(optarg);
6777c478bd9Sstevel@tonic-gate 			break;
6787c478bd9Sstevel@tonic-gate 		case 'r':
6797c478bd9Sstevel@tonic-gate 			reversePages = 0;
6807c478bd9Sstevel@tonic-gate 			break;
6817c478bd9Sstevel@tonic-gate 		case '?':
6827c478bd9Sstevel@tonic-gate 			Usage(programName);
6837c478bd9Sstevel@tonic-gate 			break;
6847c478bd9Sstevel@tonic-gate 		default:
6857c478bd9Sstevel@tonic-gate 			fprintf(stderr, "missing case for option %c\n", option);
6867c478bd9Sstevel@tonic-gate 			Usage(programName);
6877c478bd9Sstevel@tonic-gate 			break;
6887c478bd9Sstevel@tonic-gate 		}
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	ac -= optind;
6917c478bd9Sstevel@tonic-gate 	av += optind;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	switch (ac) {
6947c478bd9Sstevel@tonic-gate 	case 0:
6957c478bd9Sstevel@tonic-gate 		unlinkFile = fileName = StdinToFile();
6967c478bd9Sstevel@tonic-gate 		break;
6977c478bd9Sstevel@tonic-gate 	case 1:
6987c478bd9Sstevel@tonic-gate 		fileName = av[0];
6997c478bd9Sstevel@tonic-gate 		break;
7007c478bd9Sstevel@tonic-gate 	default:
7017c478bd9Sstevel@tonic-gate 		Usage(programName);
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	if ((document = DocumentParse(fileName)) == NULL) {
7057c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Unable to parse document (%s)\n", fileName);
7067c478bd9Sstevel@tonic-gate 		exit(0);
7077c478bd9Sstevel@tonic-gate 	}
7087c478bd9Sstevel@tonic-gate #if defined(DEBUG) && defined(NOTDEF)
7097c478bd9Sstevel@tonic-gate 	PrintDocumentInfo(document);
7107c478bd9Sstevel@tonic-gate #endif				/* DEBUG */
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	WriteDocument(document, reversePages, pageList);
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	if (unlinkFile)
7157c478bd9Sstevel@tonic-gate 		unlink(unlinkFile);
7167c478bd9Sstevel@tonic-gate 
717f928ce67Sceastha 	return (0);
7187c478bd9Sstevel@tonic-gate }
719