xref: /freebsd-11-stable/contrib/groff/src/utils/addftinfo/addftinfo.cpp (revision 22e7cbb8744990e63e02dc3985780d932c67b1a4)
1 // -*- C++ -*-
2 /* Copyright (C) 1989-1992, 2000, 2001 Free Software Foundation, Inc.
3      Written by James Clark (jjc@jclark.com)
4 
5 This file is part of groff.
6 
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11 
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING.  If not, write to the Free Software
19 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
20 
21 #include "lib.h"
22 
23 #include <ctype.h>
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include "errarg.h"
28 #include "error.h"
29 #include "stringclass.h"
30 #include "cset.h"
31 #include "guess.h"
32 
33 extern "C" const char *Version_string;
34 
35 static void usage(FILE *stream);
36 static void usage();
37 static void version();
38 static void convert_font(const font_params &, FILE *, FILE *);
39 
40 typedef int font_params::*param_t;
41 
42 static struct {
43   const char *name;
44   param_t par;
45 } param_table[] = {
46   { "x-height", &font_params::x_height },
47   { "fig-height", &font_params::fig_height },
48   { "asc-height", &font_params::asc_height },
49   { "body-height", &font_params::body_height },
50   { "cap-height", &font_params::cap_height },
51   { "comma-depth", &font_params::comma_depth },
52   { "desc-depth", &font_params::desc_depth },
53   { "body-depth", &font_params::body_depth },
54 };
55 
56 // These are all in thousandths of an em.
57 // These values are correct for PostScript Times Roman.
58 
59 #define DEFAULT_X_HEIGHT 448
60 #define DEFAULT_FIG_HEIGHT 676
61 #define DEFAULT_ASC_HEIGHT 682
62 #define DEFAULT_BODY_HEIGHT 676
63 #define DEFAULT_CAP_HEIGHT 662
64 #define DEFAULT_COMMA_DEPTH 143
65 #define DEFAULT_DESC_DEPTH 217
66 #define DEFAULT_BODY_DEPTH 177
67 
main(int argc,char ** argv)68 int main(int argc, char **argv)
69 {
70   program_name = argv[0];
71   int i;
72   for (i = 1; i < argc; i++) {
73     if (!strcmp(argv[i], "-v") || !strcmp(argv[i],"--version"))
74       version();
75     if (!strcmp(argv[i],"--help")) {
76       usage(stdout);
77       exit(0);
78     }
79   }
80   if (argc < 4)
81     usage();
82   int resolution;
83   if (sscanf(argv[argc-3], "%d", &resolution) != 1)
84     usage();
85   if (resolution <= 0)
86     fatal("resolution must be > 0");
87   int unitwidth;
88   if (sscanf(argv[argc-2], "%d", &unitwidth) != 1)
89     usage();
90   if (unitwidth <= 0)
91     fatal("unitwidth must be > 0");
92   font_params param;
93   const char *font = argv[argc-1];
94   param.italic = (font[0] != '\0' && strchr(font, '\0')[-1] == 'I');
95   param.em = (resolution*unitwidth)/72;
96   param.x_height = DEFAULT_X_HEIGHT;
97   param.fig_height = DEFAULT_FIG_HEIGHT;
98   param.asc_height = DEFAULT_ASC_HEIGHT;
99   param.body_height = DEFAULT_BODY_HEIGHT;
100   param.cap_height = DEFAULT_CAP_HEIGHT;
101   param.comma_depth = DEFAULT_COMMA_DEPTH;
102   param.desc_depth = DEFAULT_DESC_DEPTH;
103   param.body_depth = DEFAULT_BODY_DEPTH;
104   for (i = 1; i < argc && argv[i][0] == '-'; i++) {
105     if (argv[i][1] == '-' && argv[i][2] == '\0') {
106       i++;
107       break;
108     }
109     if (i + 1 >= argc)
110       usage();
111     size_t j;
112     for (j = 0;; j++) {
113       if (j >= sizeof(param_table)/sizeof(param_table[0]))
114 	fatal("parameter `%1' not recognized", argv[i] + 1);
115       if (strcmp(param_table[j].name, argv[i] + 1) == 0)
116 	break;
117     }
118     if (sscanf(argv[i+1], "%d", &(param.*(param_table[j].par))) != 1)
119       fatal("invalid argument `%1'", argv[i+1]);
120     i++;
121   }
122   if (argc - i != 3)
123     usage();
124   errno = 0;
125   FILE *infp = fopen(font, "r");
126   if (infp == 0)
127     fatal("can't open `%1': %2", font, strerror(errno));
128   convert_font(param, infp, stdout);
129   return 0;
130 }
131 
usage(FILE * stream)132 static void usage(FILE *stream)
133 {
134   fprintf(stream, "usage: %s [-v] [-param value] ... "
135 		  "resolution unitwidth font\n",
136 	  program_name);
137 }
usage()138 static void usage()
139 {
140   usage(stderr);
141   exit(1);
142 }
143 
version()144 static void version()
145 {
146   printf("GNU addftinfo (groff) version %s\n", Version_string);
147   exit(0);
148 }
149 
get_line(FILE * fp,string * p)150 static int get_line(FILE *fp, string *p)
151 {
152   int c;
153   p->clear();
154   while ((c = getc(fp)) != EOF) {
155     *p += char(c);
156     if (c == '\n')
157       break;
158   }
159   return p->length() > 0;
160 }
161 
convert_font(const font_params & param,FILE * infp,FILE * outfp)162 static void convert_font(const font_params &param, FILE *infp, FILE *outfp)
163 {
164   string s;
165   while (get_line(infp, &s)) {
166     put_string(s, outfp);
167     if (s.length() >= 8
168 	&& strncmp(&s[0], "charset", 7))
169       break;
170   }
171   while (get_line(infp, &s)) {
172     s += '\0';
173     string name;
174     const char *p = s.contents();
175     while (csspace(*p))
176       p++;
177     while (*p != '\0' && !csspace(*p))
178       name += *p++;
179     while (csspace(*p))
180       p++;
181     for (const char *q = s.contents(); q < p; q++)
182       putc(*q, outfp);
183     char *next;
184     char_metric metric;
185     metric.width = (int)strtol(p, &next, 10);
186     if (next != p) {
187       printf("%d", metric.width);
188       p = next;
189       metric.type = (int)strtol(p, &next, 10);
190       if (next != p) {
191 	name += '\0';
192 	guess(name.contents(), param, &metric);
193 	if (metric.sk == 0) {
194 	  if (metric.left_ic == 0) {
195 	    if (metric.ic == 0) {
196 	      if (metric.depth == 0) {
197 		if (metric.height != 0)
198 		  printf(",%d", metric.height);
199 	      }
200 	      else
201 		printf(",%d,%d", metric.height, metric.depth);
202 	    }
203 	    else
204 	      printf(",%d,%d,%d", metric.height, metric.depth, metric.ic);
205 	  }
206 	  else
207 	    printf(",%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
208 		   metric.left_ic);
209 	}
210 	else
211 	  printf(",%d,%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
212 		 metric.left_ic, metric.sk);
213       }
214     }
215     fputs(p, outfp);
216   }
217 }
218 
219