/contrib/groff/src/utils/pfbtops/pfbtops.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 230 lines · 189 code · 19 blank · 22 comment · 82 complexity · 6ae156d1a40ca5a04d5e39a54751b5c7 MD5 · raw file

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