1268
|
1 /* tex-make.c: Run external programs to make TeX-related files. |
|
2 |
|
3 Copyright (C) 1993, 94 Karl Berry. |
|
4 |
|
5 This program is free software; you can redistribute it and/or modify |
|
6 it under the terms of the GNU General Public License as published by |
|
7 the Free Software Foundation; either version 2, or (at your option) |
|
8 any later version. |
|
9 |
|
10 This program is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 GNU General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU General Public License |
|
16 along with this program; if not, write to the Free Software |
1315
|
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
1268
|
18 |
|
19 #include <kpathsea/config.h> |
|
20 |
|
21 #include <kpathsea/c-fopen.h> |
|
22 #include <kpathsea/c-pathch.h> |
|
23 #include <kpathsea/concatn.h> |
|
24 #include <kpathsea/db.h> |
|
25 #include <kpathsea/fn.h> |
|
26 #include <kpathsea/magstep.h> |
|
27 #include <kpathsea/readable.h> |
|
28 #include <kpathsea/tex-make.h> |
|
29 #include <kpathsea/variable.h> |
|
30 |
|
31 |
|
32 /* We never throw away stdout, since that is supposed to be the filename |
|
33 found, if all is successful. This variable controls whether stderr |
|
34 is thrown away. */ |
|
35 boolean kpse_make_tex_discard_errors = false; |
|
36 |
|
37 /* We set the envvar MAKETEX_MAG, which is part of the default spec for |
|
38 MakeTeXPK above, based on KPATHSEA_DPI and MAKETEX_BASE_DPI. */ |
|
39 |
|
40 static void |
|
41 set_maketex_mag P1H(void) |
|
42 { |
|
43 char q[MAX_INT_LENGTH * 3 + 3]; |
|
44 int m; |
|
45 string dpi_str = getenv ("KPATHSEA_DPI"); |
|
46 string bdpi_str = getenv ("MAKETEX_BASE_DPI"); |
|
47 unsigned dpi = dpi_str ? atoi (dpi_str) : 0; |
|
48 unsigned bdpi = bdpi_str ? atoi (bdpi_str) : 0; |
|
49 |
|
50 /* If the environment variables aren't set, it's a bug. */ |
|
51 assert (dpi != 0 && bdpi != 0); |
|
52 |
|
53 /* Fix up for roundoff error. Hopefully the driver has already fixed |
|
54 up DPI, but may as well be safe, and also get the magstep number. */ |
|
55 (void) kpse_magstep_fix (dpi, bdpi, &m); |
|
56 |
|
57 /* Have to do something different for DOS? */ |
|
58 if (m == 0) |
|
59 sprintf (q, "%d+%d/%d", dpi / bdpi, dpi % bdpi, bdpi); |
|
60 else |
|
61 { /* m is encoded with LSB being a ``half'' bit (see magstep.h). Are |
|
62 we making an assumption here about two's complement? Probably. |
|
63 In any case, if m is negative, we have to put in the sign |
|
64 explicitly, since m/2==0 if m==-1. */ |
|
65 const_string sign = ""; |
|
66 if (m < 0) |
|
67 { |
|
68 m *= -1; |
|
69 sign = "-"; |
|
70 } |
|
71 sprintf (q, "magstep\\(%s%d.%d\\)", sign, m / 2, (m & 1) * 5); |
|
72 } |
|
73 xputenv ("MAKETEX_MAG", q); |
|
74 } |
|
75 |
|
76 /* This MakeTeX... program was disabled, or the script failed. If this |
|
77 was a font creation (according to FORMAT), append CMD |
|
78 to a file missfont.log in the current directory. */ |
|
79 |
|
80 static void |
|
81 misstex P2C(kpse_file_format_type, format, const_string, cmd) |
|
82 { |
|
83 static FILE *missfont = NULL; |
|
84 |
|
85 /* If we weren't trying to make a font, do nothing. Maybe should |
|
86 allow people to specify what they want recorded? */ |
|
87 if (format > kpse_any_glyph_format && format != kpse_tfm_format |
|
88 && format != kpse_vf_format) |
|
89 return; |
|
90 |
|
91 /* If this is the first time, have to open the log file. */ |
|
92 if (!missfont) |
|
93 { |
|
94 const_string missfont_name = "missfont.log"; |
|
95 missfont = fopen (missfont_name, FOPEN_A_MODE); |
|
96 if (!missfont && getenv ("TEXMFOUTPUT")) |
|
97 { |
|
98 missfont_name = concat3 (getenv ("TEXMFOUTPUT"), DIR_SEP_STRING, |
|
99 missfont_name); |
|
100 missfont = fopen (missfont_name, FOPEN_A_MODE); |
|
101 } |
|
102 |
|
103 /* Should we really be unconditionally shouting this message? */ |
|
104 if (missfont) |
|
105 fprintf (stderr, "kpathsea: Appending font creation commands to %s.\n", |
|
106 missfont_name); |
|
107 } |
|
108 |
|
109 /* Write the command if we have a log file. */ |
|
110 if (missfont) |
|
111 { |
|
112 fputs (cmd, missfont); |
|
113 putc ('\n', missfont); |
|
114 } |
|
115 } |
|
116 |
|
117 |
|
118 /* Assume the script outputs the filename it creates (and nothing |
|
119 else) on standard output; hence, we run the script with `popen'. */ |
|
120 |
|
121 static string |
|
122 maketex P2C(kpse_file_format_type, format, const_string, cmd) |
|
123 { |
|
124 string ret; |
|
125 FILE *f; |
|
126 |
|
127 /* Tell the user we are running the script, so they have a clue as to |
|
128 what's going on if something messes up. */ |
|
129 fprintf (stderr, "kpathsea: Running %s\n", cmd); |
|
130 |
|
131 /* Run the script. */ |
|
132 f = popen (cmd, FOPEN_R_MODE); |
|
133 |
|
134 if (f) |
|
135 { |
|
136 int c; |
|
137 string fn; /* The final filename. */ |
|
138 unsigned len; /* And its length. */ |
|
139 fn_type output; |
|
140 output = fn_init (); /* Collect the script output. */ |
|
141 |
|
142 /* Read all the output and terminate with a null. */ |
|
143 while ((c = getc (f)) != EOF) |
|
144 fn_1grow (&output, c); |
|
145 fn_1grow (&output, 0); |
|
146 |
|
147 /* Maybe should check for `EXIT_SUCCESS' status before even |
|
148 looking at the output? */ |
|
149 if (pclose (f) == -1) |
|
150 FATAL_PERROR (cmd); |
|
151 |
|
152 len = FN_LENGTH (output); |
|
153 fn = FN_STRING (output); |
|
154 |
|
155 /* Remove trailing newlines and returns. */ |
|
156 while (len > 1 && (fn[len - 2] == '\n' || fn[len - 2] == '\r')) |
|
157 { |
|
158 fn[len - 2] = 0; |
|
159 len--; |
|
160 } |
|
161 |
|
162 /* If no output from script, return NULL. Otherwise check |
|
163 what it output. */ |
|
164 ret = len == 1 ? NULL : kpse_readable_file (fn); |
|
165 |
|
166 /* Free the name if we're not returning it. */ |
|
167 if (fn != ret) |
|
168 free (fn); |
|
169 } |
|
170 else |
|
171 /* popen failed. Maybe should give error (optionally), but for |
|
172 now be silent, to avoid annoying people who purposefully |
|
173 don't have the script installed. */ |
|
174 ret = NULL; |
|
175 |
|
176 if (ret == NULL) |
|
177 misstex (format, cmd); |
|
178 else |
|
179 db_insert (ret); |
|
180 |
|
181 return ret; |
|
182 } |
|
183 |
|
184 |
|
185 /* Create BASE in FORMAT and return the generated filename, or |
|
186 return NULL. */ |
|
187 |
|
188 string |
|
189 kpse_make_tex P2C(kpse_file_format_type, format, const_string, base) |
|
190 { |
|
191 kpse_format_info_type spec; /* some compilers lack struct initialization */ |
|
192 string ret = NULL; |
|
193 |
|
194 spec = kpse_format_info[format]; |
|
195 |
|
196 if (spec.program) |
|
197 { |
|
198 /* See the documentation for the envvars we're dealing with here. */ |
|
199 string args, cmd; |
|
200 const_string prog = spec.program; /* MakeTeXPK */ |
|
201 string PROG = uppercasify (prog); /* MAKETEXPK */ |
|
202 string progenv = getenv (PROG); /* ENV{"MAKETEXPK"} */ |
|
203 const_string arg_spec = progenv ? progenv : spec.program_args; |
|
204 string mode = getenv ("MAKETEX_MODE"); |
|
205 boolean unset_mode = false; |
|
206 |
|
207 set_maketex_mag (); |
|
208 |
|
209 /* Here's an awful kludge: if the mode is `/', unset it for the |
|
210 call and then reset it. We could ignore a mode of / in |
|
211 MakeTeXPK, but then everyone's MakeTeXPK would have to handle |
|
212 that special case, which seems too onerous. `kpse_prog_init' |
|
213 sets it to this in the first place when no mode is otherwise |
|
214 specified; this is so when the user defines a resolution, they |
|
215 don't also have to specify a mode; instead, MakeTeXPK's guesses |
|
216 will take over. They use / for the value because then when it |
|
217 is expanded as part of the PKFONTS et al. path values, we'll |
|
218 wind up searching all the pk directories. We put $MAKETEX_MODE |
|
219 in the path values in the first place so that sites with two |
|
220 different devices with the same resolution can find the right |
|
221 fonts; but such sites are uncommon, so they shouldn't make |
|
222 things harder for everyone else. */ |
|
223 if (mode && STREQ (mode, DIR_SEP_STRING)) |
|
224 { |
|
225 xputenv ("MAKETEX_MODE", ""); |
|
226 unset_mode = true; |
|
227 } |
|
228 args = arg_spec ? kpse_var_expand (arg_spec) : (string) ""; |
|
229 if (unset_mode) |
|
230 xputenv ("MAKETEX_MODE", DIR_SEP_STRING); |
|
231 |
|
232 /* The command is the program name plus the arguments. */ |
|
233 cmd = concatn (prog, " ", base, " ", args, NULL); |
|
234 |
|
235 if (spec.program_enabled_p) |
|
236 { |
|
237 /* Only way to discard errors is redirect stderr inside another |
|
238 shell; otherwise, if the MakeTeX... script doesn't exist, we |
|
239 will see the `sh: MakeTeX...: not found' error. No point in |
|
240 doing this if we're not actually going to run anything. */ |
|
241 if (kpse_make_tex_discard_errors) |
|
242 { |
|
243 string old_cmd = cmd; |
|
244 cmd = concat3 ("sh -c \"", cmd, "\" 2>/dev/null"); |
|
245 free (old_cmd); |
|
246 } |
|
247 |
|
248 ret = maketex (format, cmd); |
|
249 } |
|
250 else |
|
251 misstex (format, cmd); |
|
252 |
|
253 free (PROG); |
|
254 free (cmd); |
|
255 if (*args) |
|
256 free (args); |
|
257 } |
|
258 |
|
259 return ret; |
|
260 } |
|
261 |
|
262 #ifdef TEST |
|
263 |
|
264 void |
|
265 test_make_tex (kpse_file_format_type fmt, const_string base) |
|
266 { |
|
267 string answer; |
|
268 |
|
269 printf ("\nAttempting %s in format %d:\n", base, fmt); |
|
270 |
|
271 answer = kpse_make_tex (fmt, base); |
|
272 puts (answer ? answer : "(null)"); |
|
273 } |
|
274 |
|
275 |
|
276 int |
|
277 main () |
|
278 { |
|
279 xputenv ("KPATHSEA_DPI", "781"); /* call MakeTeXPK */ |
|
280 xputenv ("MAKETEX_BASE_DPI", "300"); /* call MakeTeXPK */ |
|
281 KPSE_MAKE_SPEC_ENABLED (kpse_make_specs[kpse_pk_format]) = true; |
|
282 test_make_tex (kpse_pk_format, "cmr10"); |
|
283 |
|
284 /* Fail with MakeTeXTFM. */ |
|
285 KPSE_MAKE_SPEC_ENABLED (kpse_make_specs[kpse_tfm_format]) = true; |
|
286 test_make_tex (kpse_tfm_format, "foozler99"); |
|
287 |
|
288 /* Call something disabled. */ |
|
289 test_make_tex (kpse_bst_format, "no-way"); |
|
290 |
|
291 return 0; |
|
292 } |
|
293 |
|
294 #endif /* TEST */ |
|
295 |
|
296 |
|
297 /* |
|
298 Local variables: |
|
299 test-compile-command: "gcc -g -I. -I.. -DTEST tex-make.c kpathsea.a" |
|
300 End: |
|
301 */ |