beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / utils / utils.w
blob2c23b1d3268550ff0b92c72a64bda89dbc13cad5
1 % utils.w
3 % Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4 % Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software; you can redistribute it and/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation; either version 2 of the License, or (at your
11 % option) any later version.
13 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
21 @ @c
24 @ @c
25 #include "ptexlib.h"
27 #include <kpathsea/config.h> /* this is a trick to load mingw32's io.h early,
28 using a macro redefinition of |eof()|. */
29 #include "sys/types.h"
30 #include <kpathsea/c-stat.h>
31 #include <kpathsea/c-fopen.h>
32 #include <string.h>
33 #include <time.h>
34 #include <float.h> /* for |DBL_EPSILON| */
35 #include "zlib.h"
36 #include "md5.h"
38 #include "lua/luatex-api.h" /* for luatex_banner */
40 #include "png.h"
41 #include "mplib.h"
43 /* POPPLER_VERSION is defined in poppler-config.h for poppler from
44 * the TeX Live tree, or in the Makefile for an installed version. */
45 #include "poppler-config.h"
47 @ @c
48 #define check_nprintf(size_get, size_want) \
49 if ((unsigned)(size_get) >= (unsigned)(size_want)) \
50 formatted_error("internal","snprintf failed: file %s, line %d", __FILE__, __LINE__);
52 char *cur_file_name = NULL;
53 static char print_buf[PRINTF_BUF_SIZE];
54 int epochseconds;
55 int microseconds;
57 /* define |char_ptr|, |char_array|, and |char_limit| */
58 typedef char char_entry;
59 define_array(char);
61 @ @c
62 #define SUBSET_TAG_LENGTH 6
63 void make_subset_tag(fd_entry * fd)
65 int i, j = 0, a[SUBSET_TAG_LENGTH];
66 md5_state_t pms;
67 char *glyph;
68 glw_entry *glw_glyph;
69 struct avl_traverser t;
70 md5_byte_t digest[16];
71 void **aa;
72 static struct avl_table *st_tree = NULL;
73 if (st_tree == NULL)
74 st_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
75 assert(fd != NULL);
76 assert(fd->gl_tree != NULL);
77 assert(fd->fontname != NULL);
78 assert(fd->subset_tag == NULL);
79 fd->subset_tag = xtalloc(SUBSET_TAG_LENGTH + 1, char);
80 do {
81 md5_init(&pms);
82 avl_t_init(&t, fd->gl_tree);
83 if (is_cidkeyed(fd->fm)) { /* |glw_entry| items */
84 for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree);
85 glw_glyph != NULL; glw_glyph = (glw_entry *) avl_t_next(&t)) {
86 glyph = malloc(24);
87 sprintf(glyph, "%05u%05u ", glw_glyph->id, glw_glyph->wd);
88 md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph));
89 free(glyph);
91 } else {
92 for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
93 glyph = (char *) avl_t_next(&t)) {
94 md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph));
95 md5_append(&pms, (const md5_byte_t *) " ", 1);
98 md5_append(&pms, (md5_byte_t *) fd->fontname,
99 (int) strlen(fd->fontname));
100 md5_append(&pms, (md5_byte_t *) & j, sizeof(int)); /* to resolve collision */
101 md5_finish(&pms, digest);
102 for (a[0] = 0, i = 0; i < 13; i++)
103 a[0] += digest[i];
104 for (i = 1; i < SUBSET_TAG_LENGTH; i++)
105 a[i] = a[i - 1] - digest[i - 1] + digest[(i + 12) % 16];
106 for (i = 0; i < SUBSET_TAG_LENGTH; i++)
107 fd->subset_tag[i] = (char) (a[i] % 26 + 'A');
108 fd->subset_tag[SUBSET_TAG_LENGTH] = '\0';
109 j++;
110 assert(j < 100);
112 while ((char *) avl_find(st_tree, fd->subset_tag) != NULL);
113 aa = avl_probe(st_tree, fd->subset_tag);
114 assert(aa != NULL);
115 if (j > 2)
116 formatted_warning("subsets","subset-tag collision, resolved in round %d",j);
119 @ @c
120 __attribute__ ((format(printf, 1, 2)))
121 void tex_printf(const char *fmt, ...)
123 va_list args;
124 va_start(args, fmt);
125 vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
126 tprint(print_buf);
127 xfflush(stdout);
128 va_end(args);
131 @ @c
132 size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE * stream)
134 if (fwrite(ptr, size, nmemb, stream) != nmemb)
135 formatted_error("file io","fwrite() failed");
136 return nmemb;
139 @ @c
140 int xfflush(FILE * stream)
142 if (fflush(stream) != 0)
143 formatted_error("file io","fflush() failed (%s)", strerror(errno));
144 return 0;
147 @ @c
148 int xgetc(FILE * stream)
150 int c = getc(stream);
151 if (c < 0 && c != EOF)
152 formatted_error("file io","getc() failed (%s)", strerror(errno));
153 return c;
156 @ @c
157 int xputc(int c, FILE * stream)
159 int i = putc(c, stream);
160 if (i < 0)
161 formatted_error("file io","putc() failed (%s)", strerror(errno));
162 return i;
165 @ @c
166 scaled ext_xn_over_d(scaled x, scaled n, scaled d)
168 double r = (((double) x) * ((double) n)) / ((double) d);
169 if (r > DBL_EPSILON)
170 r += 0.5;
171 else
172 r -= 0.5;
173 if (r >= (double) max_integer || r <= -(double) max_integer)
174 normal_warning("internal","arithmetic number too big");
175 return (scaled) r;
178 @ function strips trailing zeros in string with numbers;
179 leading zeros are not stripped (as in real life)
181 #if 0
182 char *stripzeros(char *a)
184 enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM;
185 char *p, *q, *r;
186 for (p = q = r = a; *p != '\0';) {
187 switch (s) {
188 case NONUM:
189 if (*p >= '0' && *p <= '9')
190 s = INT;
191 else if (*p == '.')
192 s = LEADDOT;
193 break;
194 case DOTNONUM:
195 if (*p != '.' && (*p < '0' || *p > '9'))
196 s = NONUM;
197 break;
198 case INT:
199 if (*p == '.')
200 s = DOT;
201 else if (*p < '0' || *p > '9')
202 s = NONUM;
203 break;
204 case DOT:
205 case LEADDOT:
206 if (*p >= '0' && *p <= '9')
207 s = FRAC;
208 else if (*p == '.')
209 s = DOTNONUM;
210 else
211 s = NONUM;
212 break;
213 case FRAC:
214 if (*p == '.')
215 s = DOTNONUM;
216 else if (*p < '0' || *p > '9')
217 s = NONUM;
218 break;
219 default:;
221 switch (s) {
222 case DOT:
223 r = q;
224 break;
225 case LEADDOT:
226 r = q + 1;
227 break;
228 case FRAC:
229 if (*p > '0')
230 r = q + 1;
231 break;
232 case NONUM:
233 if ((t == FRAC || t == DOT) && r != a) {
234 q = r--;
235 if (*r == '.') /* was a LEADDOT */
236 *r = '0';
237 r = a;
239 break;
240 default:;
242 *q++ = *p++;
243 t = s;
245 *q = '\0';
246 return a;
248 #endif
250 @ @c
251 void initversionstring(char **versions)
253 const_string fmt =
254 "Compiled with libpng %s; using %s\n"
255 "Compiled with zlib %s; using %s\n"
256 "Compiled with poppler version %s\n"
257 "Compiled with mplib version %s\n";
258 size_t len = strlen(fmt)
259 + strlen(PNG_LIBPNG_VER_STRING) + strlen(png_libpng_ver)
260 + strlen(ZLIB_VERSION) + strlen(zlib_version)
261 + strlen(POPPLER_VERSION)
262 + strlen(mp_metapost_version())
263 + 1;
265 /* len will be more than enough, because of the placeholder chars in fmt
266 that get replaced by the arguments. */
267 *versions = xmalloc(len);
268 sprintf(*versions, fmt,
269 PNG_LIBPNG_VER_STRING, png_libpng_ver,
270 ZLIB_VERSION, zlib_version, POPPLER_VERSION, mp_metapost_version());
273 @ @c
274 void check_buffer_overflow(int wsize)
276 if (wsize > buf_size) {
277 int nsize = buf_size + buf_size / 5 + 5;
278 if (nsize < wsize) {
279 nsize = wsize + 5;
281 buffer =
282 (unsigned char *) xreallocarray(buffer, char, (unsigned) nsize);
283 buf_size = nsize;
287 @ the return value is a decimal number with the point |dd| places from the back,
288 |scaled_out| is the number of scaled points corresponding to that.
291 #define max_integer 0x7FFFFFFF
293 scaled divide_scaled(scaled s, scaled m, int dd)
295 register scaled q;
296 register scaled r;
297 int i;
298 int sign = 1;
299 if (s < 0) {
300 sign = -sign;
301 s = -s;
303 if (m < 0) {
304 sign = -sign;
305 m = -m;
307 if (m == 0) {
308 normal_error("arithmetic", "divided by zero");
309 } else if (m >= (max_integer / 10)) {
310 normal_error("arithmetic", "number too big");
312 q = s / m;
313 r = s % m;
314 for (i = 1; i <= (int) dd; i++) {
315 q = 10 * q + (10 * r) / m;
316 r = (10 * r) % m;
318 /* rounding */
319 if (2 * r >= m) {
320 q++;
322 return sign * q;
325 @ Same function, but using doubles instead of integers (faster)
327 scaled divide_scaled_n(double sd, double md, double n)
329 double dd, di = 0.0;
330 dd = sd / md * n;
331 if (dd > 0.0)
332 di = floor(dd + 0.5);
333 else if (dd < 0.0)
334 di = -floor((-dd) + 0.5);
335 return (scaled) di;
338 @ @c
339 int do_zround(double r)
341 int i;
343 if (r > 2147483647.0)
344 i = 2147483647;
345 else if (r < -2147483647.0)
346 i = -2147483647;
347 else if (r >= 0.0)
348 i = (int) (r + 0.5);
349 else
350 i = (int) (r - 0.5);
352 return i;
356 @ MSVC doesn't have |rint|.
358 #ifdef _MSC_VER
360 # include <math.h>
361 double rint(double x)
363 return floor(x+0.5);
366 #endif