1151497Sru/* Copyright (C) 1992, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. 279543Sru Written by James Clark (jjc@jclark.com) 379543Sru 479543SruThis file is part of groff. 579543Sru 679543Srugroff is free software; you can redistribute it and/or modify it under 779543Sruthe terms of the GNU General Public License as published by the Free 879543SruSoftware Foundation; either version 2, or (at your option) any later 979543Sruversion. 1079543Sru 1179543Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 1279543SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 1379543SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1479543Srufor more details. 1579543Sru 1679543SruYou should have received a copy of the GNU General Public License along 1779543Sruwith groff; see the file COPYING. If not, write to the Free Software 18151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 1979543Sru 2075584Sru/* This translates ps fonts in .pfb format to ASCII ps files. */ 2175584Sru 22104862Sru#ifdef HAVE_CONFIG_H 23104862Sru#include <config.h> 24104862Sru#endif 25104862Sru 2675584Sru#include <stdio.h> 27104862Sru#include <stdlib.h> 2875584Sru#include <limits.h> 2975584Sru 30151497Sru#define __GETOPT_PREFIX groff_ 31151497Sru#include <getopt.h> 32151497Sru 3375584Sru#include "nonposix.h" 3475584Sru 3575584Sru/* Binary bytes per output line. */ 3675584Sru#define BYTES_PER_LINE (64/2) 37114402Sru#define MAX_LINE_LENGTH 78 3875584Sru#define HEX_DIGITS "0123456789abcdef" 3975584Sru 40151497Sruextern const char *Version_string; 41151497Sru 4275584Srustatic char *program_name; 4375584Sru 44151497Srustatic void error(const char *s) 4575584Sru{ 4675584Sru fprintf(stderr, "%s: %s\n", program_name, s); 4775584Sru exit(2); 4875584Sru} 4975584Sru 5075584Srustatic void usage(FILE *stream) 5175584Sru{ 5275584Sru fprintf(stream, "usage: %s [-v] [pfb_file]\n", program_name); 5375584Sru} 5475584Sru 55114402Srustatic void get_text(int n) 56114402Sru{ 57151497Sru int c = 0, c1; 58114402Sru int in_string = 0; 59114402Sru int is_comment = 0; 60114402Sru int count = 0; 61114402Sru 62114402Sru while (--n >= 0) { 63114402Sru c = getchar(); 64114402Sru if (c == '(' && !is_comment) 65114402Sru in_string++; 66114402Sru else if (c == ')' && !is_comment) 67114402Sru in_string--; 68114402Sru else if (c == '%' && !in_string) 69114402Sru is_comment = 1; 70114402Sru else if (c == '\\' && in_string) { 71114402Sru count++; 72114402Sru putchar(c); 73151497Sru if (n-- == 0) 74151497Sru break; 75114402Sru c = getchar(); 76114402Sru /* don't split octal character representations */ 77114402Sru if (c >= '0' && c <= '7') { 78114402Sru count++; 79114402Sru putchar(c); 80151497Sru if (n-- == 0) 81151497Sru break; 82114402Sru c = getchar(); 83114402Sru if (c >= '0' && c <= '7') { 84114402Sru count++; 85114402Sru putchar(c); 86151497Sru if (n-- == 0) 87151497Sru break; 88114402Sru c = getchar(); 89114402Sru if (c >= '0' && c <= '7') { 90114402Sru count++; 91114402Sru putchar(c); 92151497Sru if (n-- == 0) 93151497Sru break; 94114402Sru c = getchar(); 95114402Sru } 96114402Sru } 97114402Sru } 98114402Sru } 99114402Sru if (c == EOF) 100114402Sru error("end of file in text packet"); 101114402Sru else if (c == '\r') { 102151497Sru if (n-- == 0) 103151497Sru break; 104114402Sru c1 = getchar(); 105151497Sru if (c1 != '\n') { 106114402Sru ungetc(c1, stdin); 107151497Sru n++; 108151497Sru } 109114402Sru c = '\n'; 110114402Sru } 111114402Sru if (c == '\n') { 112114402Sru count = 0; 113114402Sru is_comment = 0; 114114402Sru } 115114402Sru else if (count >= MAX_LINE_LENGTH) { 116114402Sru if (in_string > 0) { 117114402Sru count = 1; 118114402Sru putchar('\\'); 119114402Sru putchar('\n'); 120114402Sru } 121114402Sru else if (is_comment) { 122114402Sru count = 2; 123114402Sru putchar('\n'); 124114402Sru putchar('%'); 125114402Sru } 126114402Sru else { 127114402Sru /* split at the next whitespace character */ 128114402Sru while (c != ' ' && c != '\t' && c != '\f') { 129114402Sru putchar(c); 130151497Sru if (n-- == 0) 131151497Sru break; 132114402Sru c = getchar(); 133114402Sru } 134114402Sru count = 0; 135114402Sru putchar('\n'); 136114402Sru continue; 137114402Sru } 138114402Sru } 139114402Sru count++; 140114402Sru putchar(c); 141114402Sru } 142114402Sru if (c != '\n') 143114402Sru putchar('\n'); 144114402Sru} 145114402Sru 146114402Srustatic void get_binary(int n) 147114402Sru{ 148114402Sru int c; 149114402Sru int count = 0; 150114402Sru 151114402Sru while (--n >= 0) { 152114402Sru c = getchar(); 153114402Sru if (c == EOF) 154114402Sru error("end of file in binary packet"); 155114402Sru if (count >= BYTES_PER_LINE) { 156114402Sru putchar('\n'); 157114402Sru count = 0; 158114402Sru } 159114402Sru count++; 160114402Sru putchar(HEX_DIGITS[(c >> 4) & 0xf]); 161114402Sru putchar(HEX_DIGITS[c & 0xf]); 162114402Sru } 163114402Sru putchar('\n'); 164114402Sru} 165114402Sru 166151497Sruint main(int argc, char **argv) 16775584Sru{ 16875584Sru int opt; 16975584Sru static const struct option long_options[] = { 17075584Sru { "help", no_argument, 0, CHAR_MAX + 1 }, 17175584Sru { "version", no_argument, 0, 'v' }, 17275584Sru { NULL, 0, 0, 0 } 17375584Sru }; 17475584Sru 17575584Sru program_name = argv[0]; 17675584Sru 17775584Sru while ((opt = getopt_long(argc, argv, "v", long_options, NULL)) != EOF) { 17875584Sru switch (opt) { 17975584Sru case 'v': 180151497Sru printf("GNU pfbtops (groff) version %s\n", Version_string); 181151497Sru exit(0); 182151497Sru break; 18379543Sru case CHAR_MAX + 1: /* --help */ 18475584Sru usage(stdout); 18575584Sru exit(0); 18675584Sru break; 18775584Sru case '?': 18875584Sru usage(stderr); 18975584Sru exit(1); 19075584Sru break; 19175584Sru } 19275584Sru } 19375584Sru 19475584Sru if (argc - optind > 1) { 19575584Sru usage(stderr); 19675584Sru exit(1); 19775584Sru } 198114402Sru if (argc > optind && !freopen(argv[optind], "r", stdin)) { 199114402Sru perror(argv[optind]); 200114402Sru exit(1); 201114402Sru } 20275584Sru SET_BINARY(fileno(stdin)); 203114402Sru for (;;) { 204114402Sru int type, c, i; 205114402Sru long n; 20675584Sru 207114402Sru c = getchar(); 208114402Sru if (c != 0x80) 209114402Sru error("first byte of packet not 0x80"); 210114402Sru type = getchar(); 211114402Sru if (type == 3) 212114402Sru break; 213114402Sru if (type != 1 && type != 2) 214114402Sru error("bad packet type"); 215114402Sru n = 0; 216114402Sru for (i = 0; i < 4; i++) { 21775584Sru c = getchar(); 218114402Sru if (c == EOF) 219114402Sru error("end of file in packet header"); 220114402Sru n |= (long)c << (i << 3); 22175584Sru } 222114402Sru if (n < 0) 223114402Sru error("negative packet length"); 224114402Sru if (type == 1) 225114402Sru get_text(n); 226114402Sru else 227114402Sru get_binary(n); 228114402Sru } 22975584Sru exit(0); 23075584Sru} 231