pfbtops.c revision 75584
178556Sobrien/* This translates ps fonts in .pfb format to ASCII ps files. */
278556Sobrien
378556Sobrien#include <stdio.h>
478556Sobrien#include <getopt.h>
578556Sobrien#include <limits.h>
678556Sobrien
778556Sobrien#include "nonposix.h"
878556Sobrien
978556Sobrien/* Binary bytes per output line. */
10146293Sobrien#define BYTES_PER_LINE (64/2)
1178556Sobrien#define HEX_DIGITS "0123456789abcdef"
1278556Sobrien
1378556Sobrienstatic char *program_name;
1478556Sobrien
1578556Sobrienstatic void error(s)
1678556Sobrien     char *s;
1778556Sobrien{
1878556Sobrien  fprintf(stderr, "%s: %s\n", program_name, s);
1978556Sobrien  exit(2);
2078556Sobrien}
2178556Sobrien
2278556Sobrienstatic void usage(FILE *stream)
2378556Sobrien{
2478556Sobrien  fprintf(stream, "usage: %s [-v] [pfb_file]\n", program_name);
2578556Sobrien}
2678556Sobrien
2778556Sobrienint main(argc, argv)
2878556Sobrien     int argc;
2978556Sobrien     char **argv;
3078556Sobrien{
3178556Sobrien  int opt;
3278556Sobrien  extern int optind;
3378556Sobrien  static const struct option long_options[] = {
3478556Sobrien    { "help", no_argument, 0, CHAR_MAX + 1 },
3578556Sobrien    { "version", no_argument, 0, 'v' },
3678556Sobrien    { NULL, 0, 0, 0 }
3778556Sobrien  };
3878556Sobrien
3978556Sobrien  program_name = argv[0];
4078556Sobrien
4178556Sobrien  while ((opt = getopt_long(argc, argv, "v", long_options, NULL)) != EOF) {
4278556Sobrien    switch (opt) {
4378556Sobrien    case 'v':
44146293Sobrien      {
4578556Sobrien	extern char *Version_string;
4678556Sobrien	printf("GNU pfbtops (groff) version %s\n", Version_string);
4778556Sobrien	exit(0);
4878556Sobrien	break;
4978556Sobrien      }
5078556Sobrien    case CHAR_MAX + 1: // --help
5178556Sobrien      usage(stdout);
5278556Sobrien      exit(0);
5378556Sobrien      break;
5478556Sobrien    case '?':
5578556Sobrien      usage(stderr);
5678556Sobrien      exit(1);
5778556Sobrien      break;
5878556Sobrien    }
5978556Sobrien  }
6078556Sobrien
6178556Sobrien  if (argc - optind > 1) {
6278556Sobrien    usage(stderr);
6378556Sobrien    exit(1);
6478556Sobrien  }
6578556Sobrien  if (argc > optind && !freopen(argv[optind], "r", stdin))
6678556Sobrien    {
6778556Sobrien      perror(argv[optind]);
6878556Sobrien      exit(1);
6978556Sobrien    }
7078556Sobrien#ifdef SET_BINARY
7178556Sobrien  SET_BINARY(fileno(stdin));
7278556Sobrien#endif
7378556Sobrien  for (;;)
7478556Sobrien    {
7578556Sobrien      int type, c, i;
7678556Sobrien      long n;
7778556Sobrien
7878556Sobrien      c = getchar();
7978556Sobrien      if (c != 0x80)
8078556Sobrien	error("first byte of packet not 0x80");
8178556Sobrien      type = getchar();
8278556Sobrien      if (type == 3)
8378556Sobrien	break;
8478556Sobrien      if (type != 1 && type != 2)
8578556Sobrien	error("bad packet type");
8678556Sobrien      n = 0;
8778556Sobrien      for (i = 0; i < 4; i++)
8878556Sobrien	{
8978556Sobrien	  c = getchar();
9078556Sobrien	  if (c == EOF)
9178556Sobrien	    error("end of file in packet header");
9278556Sobrien	  n |= (long)c << (i << 3);
9378556Sobrien	}
9478556Sobrien      if (n < 0)
9578556Sobrien	error("negative packet length");
9678556Sobrien      if (type == 1)
9778556Sobrien	{
9878556Sobrien	  while (--n >= 0)
9978556Sobrien	    {
10078556Sobrien	      c = getchar();
10178556Sobrien	      if (c == EOF)
102147666Ssimon		error("end of file in text packet");
10378556Sobrien	      if (c == '\r')
10478556Sobrien		c = '\n';
10578556Sobrien	      putchar(c);
10678556Sobrien	    }
10778556Sobrien	  if (c != '\n')
10878556Sobrien	    putchar('\n');
10978556Sobrien	}
11078556Sobrien      else
11178556Sobrien	{
11278556Sobrien	  int count = 0;
11378556Sobrien	  while (--n >= 0)
11478556Sobrien	    {
11578556Sobrien	      c = getchar();
11678556Sobrien	      if (c == EOF)
11790067Ssobomax		error("end of file in binary packet");
11878556Sobrien	      if (count >= BYTES_PER_LINE)
11978556Sobrien		{
12078556Sobrien		  putchar('\n');
12178556Sobrien		  count = 0;
12278556Sobrien		}
12378556Sobrien	      count++;
12490067Ssobomax	      putchar(HEX_DIGITS[(c >> 4) & 0xf]);
12590067Ssobomax	      putchar(HEX_DIGITS[c & 0xf]);
12690067Ssobomax	    }
12778556Sobrien	  putchar('\n');
12878556Sobrien	}
12978556Sobrien    }
13078556Sobrien  exit(0);
13178556Sobrien}
13278556Sobrien