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