3
% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4
% Copyright 2006-2010 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/>.
22
static const char _svn_version[] =
23
"$Id: utils.w 3584 2010-04-02 17:45:55Z hhenkel $ "
24
"$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.1/source/texk/web2c/luatexdir/utils/utils.w $";
27
#include "openbsd-compat.h"
28
#include <kpathsea/config.h> /* this is a trick to load mingw32's io.h early,
29
using a macro redefinition of |eof()|. */
30
#ifdef HAVE_ASPRINTF /* asprintf is not defined in openbsd-compat.h, but in stdio.h */
34
#include "sys/types.h"
36
# include "sysexits.h"
38
# define EX_SOFTWARE 70
40
#include <kpathsea/c-stat.h>
41
#include <kpathsea/c-fopen.h>
44
#include <float.h> /* for |DBL_EPSILON| */
49
#include "lua/luatex-api.h" /* for ptexbanner */
52
#ifdef POPPLER_VERSION
53
# define xpdfString "poppler"
54
# include "poppler-config.h"
55
# define xpdfVersion POPPLER_VERSION
57
# define xpdfString "xpdf"
58
# include "xpdf/config.h" /* just to get the xpdf version */
62
#define check_nprintf(size_get, size_want) \
63
if ((unsigned)(size_get) >= (unsigned)(size_want)) \
64
pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
66
char *cur_file_name = NULL;
67
static char print_buf[PRINTF_BUF_SIZE];
71
/* define |char_ptr|, |char_array|, and |char_limit| */
72
typedef char char_entry;
76
#define SUBSET_TAG_LENGTH 6
77
void make_subset_tag(fd_entry * fd)
79
int i, j = 0, a[SUBSET_TAG_LENGTH];
83
struct avl_traverser t;
84
md5_byte_t digest[16];
86
static struct avl_table *st_tree = NULL;
88
st_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
90
assert(fd->gl_tree != NULL);
91
assert(fd->fontname != NULL);
92
assert(fd->subset_tag == NULL);
93
fd->subset_tag = xtalloc(SUBSET_TAG_LENGTH + 1, char);
96
avl_t_init(&t, fd->gl_tree);
97
if (is_cidkeyed(fd->fm)) { /* |glw_entry| items */
98
for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree);
99
glw_glyph != NULL; glw_glyph = (glw_entry *) avl_t_next(&t)) {
101
sprintf(glyph, "%05u%05u ", glw_glyph->id, glw_glyph->wd);
102
md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph));
106
for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
107
glyph = (char *) avl_t_next(&t)) {
108
md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph));
109
md5_append(&pms, (const md5_byte_t *) " ", 1);
112
md5_append(&pms, (md5_byte_t *) fd->fontname,
113
(int) strlen(fd->fontname));
114
md5_append(&pms, (md5_byte_t *) & j, sizeof(int)); /* to resolve collision */
115
md5_finish(&pms, digest);
116
for (a[0] = 0, i = 0; i < 13; i++)
118
for (i = 1; i < SUBSET_TAG_LENGTH; i++)
119
a[i] = a[i - 1] - digest[i - 1] + digest[(i + 12) % 16];
120
for (i = 0; i < SUBSET_TAG_LENGTH; i++)
121
fd->subset_tag[i] = (char) (a[i] % 26 + 'A');
122
fd->subset_tag[SUBSET_TAG_LENGTH] = '\0';
126
while ((char *) avl_find(st_tree, fd->subset_tag) != NULL);
127
aa = avl_probe(st_tree, fd->subset_tag);
131
("\nmake_subset_tag(): subset-tag collision, resolved in round %d.\n",
136
__attribute__ ((format(printf, 1, 2)))
137
void tex_printf(const char *fmt, ...)
141
vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
147
@ |pdftex_fail| may be called when a buffer overflow has happened/is
148
happening, therefore may not call mktexstring. However, with the
149
current implementation it appears that error messages are misleading,
150
possibly because pool overflows are detected too late.
152
The output format of this fuction must be the same as |pdf_error| in
156
__attribute__ ((noreturn, format(printf, 1, 2)))
157
void pdftex_fail(const char *fmt, ...)
162
tprint("!LuaTeX error");
165
tprint(cur_file_name);
169
vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
173
remove_pdffile(static_pdf);
174
tprint(" ==> Fatal error occurred, no output PDF file produced!");
176
if (kpathsea_debug) {
183
@ The output format of this fuction must be the same as |pdf_warn| in
186
__attribute__ ((format(printf, 1, 2)))
187
void pdftex_warn(const char *fmt, ...)
192
tex_printf("LuaTeX warning");
194
tex_printf(" (file %s)", cur_file_name);
196
vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
203
void garbage_warning(void)
205
pdftex_warn("dangling objects discarded, no output file produced.");
206
remove_pdffile(static_pdf);
210
char *pdftex_banner = NULL;
213
void make_pdftex_banner(void)
219
if (pdftex_banner != NULL)
222
slen = (unsigned int) (SMALL_BUF_SIZE +
224
strlen(versionstring) +
225
strlen(kpathsea_version_string));
226
s = xtalloc(slen, char);
227
/* The Web2c version string starts with a space. */
228
i = snprintf(s, slen,
229
"%s%s %s", ptexbanner, versionstring, kpathsea_version_string);
230
check_nprintf(i, slen);
235
size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE * stream)
237
if (fwrite(ptr, size, nmemb, stream) != nmemb)
238
pdftex_fail("fwrite() failed");
243
int xfflush(FILE * stream)
245
if (fflush(stream) != 0)
246
pdftex_fail("fflush() failed (%s)", strerror(errno));
251
int xgetc(FILE * stream)
253
int c = getc(stream);
254
if (c < 0 && c != EOF)
255
pdftex_fail("getc() failed (%s)", strerror(errno));
260
int xputc(int c, FILE * stream)
262
int i = putc(c, stream);
264
pdftex_fail("putc() failed (%s)", strerror(errno));
269
scaled ext_xn_over_d(scaled x, scaled n, scaled d)
271
double r = (((double) x) * ((double) n)) / ((double) d);
276
if (r >= (double) max_integer || r <= -(double) max_integer)
277
pdftex_warn("arithmetic: number too big");
281
@ function strips trailing zeros in string with numbers;
282
leading zeros are not stripped (as in real life)
284
char *stripzeros(char *a)
286
enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM;
288
for (p = q = r = a; *p != '\0';) {
291
if (*p >= '0' && *p <= '9')
297
if (*p != '.' && (*p < '0' || *p > '9'))
303
else if (*p < '0' || *p > '9')
308
if (*p >= '0' && *p <= '9')
318
else if (*p < '0' || *p > '9')
335
if ((t == FRAC || t == DOT) && r != a) {
337
if (*r == '.') /* was a LEADDOT */
352
void initversionstring(char **versions)
354
(void) asprintf(versions,
355
"Compiled with libpng %s; using libpng %s\n"
356
"Compiled with zlib %s; using zlib %s\n"
357
"Compiled with %s version %s\n",
358
PNG_LIBPNG_VER_STRING, png_libpng_ver,
359
ZLIB_VERSION, zlib_version, xpdfString, xpdfVersion);
363
void check_buffer_overflow(int wsize)
365
if (wsize > buf_size) {
366
int nsize = buf_size + buf_size / 5 + 5;
371
(unsigned char *) xreallocarray(buffer, char, (unsigned) nsize);
376
@ the return value is a decimal number with the point |dd| places from the back,
377
|scaled_out| is the number of scaled points corresponding to that.
380
#define max_integer 0x7FFFFFFF
382
scaled divide_scaled(scaled s, scaled m, int dd)
397
pdf_error("arithmetic", "divided by zero");
398
} else if (m >= (max_integer / 10)) {
399
pdf_error("arithmetic", "number too big");
403
for (i = 1; i <= (int) dd; i++) {
404
q = 10 * q + (10 * r) / m;
415
@ Same function, but using doubles instead of integers (faster)
417
scaled divide_scaled_n(double sd, double md, double n)
422
di = floor(dd + 0.5);
424
di = -floor((-dd) + 0.5);
429
int do_zround(double r)
433
if (r > 2147483647.0)
435
else if (r < -2147483647.0)
446
@ MSVC doesn't have |rind|.
451
double rint(double x)