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 46 static void error(const char *s) 47 { 48 fprintf(stderr, "%s: %s\n", program_name, s); 49 exit(2); 50 } 51 52 static void usage(FILE *stream) 53 { 54 fprintf(stream, "usage: %s [-v] [pfb_file]\n", program_name); 55 } 56 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 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 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