xref: /netbsd-src/external/gpl2/groff/dist/src/utils/pfbtops/pfbtops.c (revision 89a07cf815a29524268025a1139fac4c5190f765)
1 /*	$NetBSD: pfbtops.c,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $	*/
2 
3 /* Copyright (C) 1992, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
4      Written by James Clark (jjc@jclark.com)
5 
6 This file is part of groff.
7 
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12 
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING.  If not, write to the Free Software
20 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
21 
22 /* This translates ps fonts in .pfb format to ASCII ps files. */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <limits.h>
31 
32 #define __GETOPT_PREFIX groff_
33 #include <getopt.h>
34 
35 #include "nonposix.h"
36 
37 /* Binary bytes per output line. */
38 #define BYTES_PER_LINE (64/2)
39 #define MAX_LINE_LENGTH 78
40 #define HEX_DIGITS "0123456789abcdef"
41 
42 extern const char *Version_string;
43 
44 static char *program_name;
45 
error(const char * s)46 static void error(const char *s)
47 {
48   fprintf(stderr, "%s: %s\n", program_name, s);
49   exit(2);
50 }
51 
usage(FILE * stream)52 static void usage(FILE *stream)
53 {
54   fprintf(stream, "usage: %s [-v] [pfb_file]\n", program_name);
55 }
56 
get_text(int n)57 static void get_text(int n)
58 {
59   int c = 0, c1;
60   int in_string = 0;
61   int is_comment = 0;
62   int count = 0;
63 
64   while (--n >= 0) {
65     c = getchar();
66     if (c == '(' && !is_comment)
67       in_string++;
68     else if (c == ')' && !is_comment)
69       in_string--;
70     else if (c == '%' && !in_string)
71       is_comment = 1;
72     else if (c == '\\' && in_string) {
73       count++;
74       putchar(c);
75       if (n-- == 0)
76 	break;
77       c = getchar();
78       /* don't split octal character representations */
79       if (c >= '0' && c <= '7') {
80 	count++;
81 	putchar(c);
82 	if (n-- == 0)
83 	  break;
84 	c = getchar();
85 	if (c >= '0' && c <= '7') {
86 	  count++;
87 	  putchar(c);
88 	  if (n-- == 0)
89 	    break;
90 	  c = getchar();
91 	  if (c >= '0' && c <= '7') {
92 	    count++;
93 	    putchar(c);
94 	    if (n-- == 0)
95 	      break;
96 	    c = getchar();
97 	  }
98 	}
99       }
100     }
101     if (c == EOF)
102       error("end of file in text packet");
103     else if (c == '\r') {
104       if (n-- == 0)
105 	break;
106       c1 = getchar();
107       if (c1 != '\n') {
108 	ungetc(c1, stdin);
109 	n++;
110       }
111       c = '\n';
112     }
113     if (c == '\n') {
114       count = 0;
115       is_comment = 0;
116     }
117     else if (count >= MAX_LINE_LENGTH) {
118       if (in_string > 0) {
119 	count = 1;
120 	putchar('\\');
121 	putchar('\n');
122       }
123       else if (is_comment) {
124 	count = 2;
125 	putchar('\n');
126 	putchar('%');
127       }
128       else {
129 	/* split at the next whitespace character */
130 	while (c != ' ' && c != '\t' && c != '\f') {
131 	  putchar(c);
132 	  if (n-- == 0)
133 	    break;
134 	  c = getchar();
135 	}
136 	count = 0;
137 	putchar('\n');
138 	continue;
139       }
140     }
141     count++;
142     putchar(c);
143   }
144   if (c != '\n')
145     putchar('\n');
146 }
147 
get_binary(int n)148 static void get_binary(int n)
149 {
150   int c;
151   int count = 0;
152 
153   while (--n >= 0) {
154     c = getchar();
155     if (c == EOF)
156       error("end of file in binary packet");
157     if (count >= BYTES_PER_LINE) {
158       putchar('\n');
159       count = 0;
160     }
161     count++;
162     putchar(HEX_DIGITS[(c >> 4) & 0xf]);
163     putchar(HEX_DIGITS[c & 0xf]);
164   }
165   putchar('\n');
166 }
167 
main(int argc,char ** argv)168 int main(int argc, char **argv)
169 {
170   int opt;
171   static const struct option long_options[] = {
172     { "help", no_argument, 0, CHAR_MAX + 1 },
173     { "version", no_argument, 0, 'v' },
174     { NULL, 0, 0, 0 }
175   };
176 
177   program_name = argv[0];
178 
179   while ((opt = getopt_long(argc, argv, "v", long_options, NULL)) != EOF) {
180     switch (opt) {
181     case 'v':
182       printf("GNU pfbtops (groff) version %s\n", Version_string);
183       exit(0);
184       break;
185     case CHAR_MAX + 1: /* --help */
186       usage(stdout);
187       exit(0);
188       break;
189     case '?':
190       usage(stderr);
191       exit(1);
192       break;
193     }
194   }
195 
196   if (argc - optind > 1) {
197     usage(stderr);
198     exit(1);
199   }
200   if (argc > optind && !freopen(argv[optind], "r", stdin)) {
201     perror(argv[optind]);
202     exit(1);
203   }
204   SET_BINARY(fileno(stdin));
205   for (;;) {
206     int type, c, i;
207     long n;
208 
209     c = getchar();
210     if (c != 0x80)
211       error("first byte of packet not 0x80");
212     type = getchar();
213     if (type == 3)
214       break;
215     if (type != 1 && type != 2)
216       error("bad packet type");
217     n = 0;
218     for (i = 0; i < 4; i++) {
219       c = getchar();
220       if (c == EOF)
221 	error("end of file in packet header");
222       n |= (long)c << (i << 3);
223     }
224     if (n < 0)
225       error("negative packet length");
226     if (type == 1)
227       get_text(n);
228     else
229       get_binary(n);
230   }
231   exit(0);
232 }
233