Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / groff / src / utils / pfbtops / pfbtops.c
1 /* Copyright (C) 1992, 2001 Free Software Foundation, Inc.
2      Written by James Clark (jjc@jclark.com)
3
4 This file is part of groff.
5
6 groff is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with groff; see the file COPYING.  If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <getopt.h>
29 #include <limits.h>
30
31 #include "nonposix.h"
32
33 /* Binary bytes per output line. */
34 #define BYTES_PER_LINE (64/2)
35 #define HEX_DIGITS "0123456789abcdef"
36
37 static char *program_name;
38
39 static void error(s)
40      char *s;
41 {
42   fprintf(stderr, "%s: %s\n", program_name, s);
43   exit(2);
44 }
45
46 static void usage(FILE *stream)
47 {
48   fprintf(stream, "usage: %s [-v] [pfb_file]\n", program_name);
49 }
50
51 int main(argc, argv)
52      int argc;
53      char **argv;
54 {
55   int opt;
56   extern int optind;
57   static const struct option long_options[] = {
58     { "help", no_argument, 0, CHAR_MAX + 1 },
59     { "version", no_argument, 0, 'v' },
60     { NULL, 0, 0, 0 }
61   };
62
63   program_name = argv[0];
64
65   while ((opt = getopt_long(argc, argv, "v", long_options, NULL)) != EOF) {
66     switch (opt) {
67     case 'v':
68       {
69         extern const char *Version_string;
70         printf("GNU pfbtops (groff) version %s\n", Version_string);
71         exit(0);
72         break;
73       }
74     case CHAR_MAX + 1: /* --help */
75       usage(stdout);
76       exit(0);
77       break;
78     case '?':
79       usage(stderr);
80       exit(1);
81       break;
82     }
83   }
84
85   if (argc - optind > 1) {
86     usage(stderr);
87     exit(1);
88   }
89   if (argc > optind && !freopen(argv[optind], "r", stdin))
90     {
91       perror(argv[optind]);
92       exit(1);
93     }
94 #ifdef SET_BINARY
95   SET_BINARY(fileno(stdin));
96 #endif
97   for (;;)
98     {
99       int type, c, i;
100       long n;
101
102       c = getchar();
103       if (c != 0x80)
104         error("first byte of packet not 0x80");
105       type = getchar();
106       if (type == 3)
107         break;
108       if (type != 1 && type != 2)
109         error("bad packet type");
110       n = 0;
111       for (i = 0; i < 4; i++)
112         {
113           c = getchar();
114           if (c == EOF)
115             error("end of file in packet header");
116           n |= (long)c << (i << 3);
117         }
118       if (n < 0)
119         error("negative packet length");
120       if (type == 1)
121         {
122           while (--n >= 0)
123             {
124               c = getchar();
125               if (c == EOF)
126                 error("end of file in text packet");
127               if (c == '\r')
128                 c = '\n';
129               putchar(c);
130             }
131           if (c != '\n')
132             putchar('\n');
133         }
134       else
135         {
136           int count = 0;
137           while (--n >= 0)
138             {
139               c = getchar();
140               if (c == EOF)
141                 error("end of file in binary packet");
142               if (count >= BYTES_PER_LINE)
143                 {
144                   putchar('\n');
145                   count = 0;
146                 }
147               count++;
148               putchar(HEX_DIGITS[(c >> 4) & 0xf]);
149               putchar(HEX_DIGITS[c & 0xf]);
150             }
151           putchar('\n');
152         }
153     }
154   exit(0);
155 }