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