~ubuntu-branches/ubuntu/wily/luatex/wily

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/utils/utils.w

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2010-04-29 00:47:19 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100429004719-o42etkqe90n97b9e
Tags: 0.60.1-1
* new upstream release, adapt build-script patch
* disable patch: upstream-epstopdf_cc_no_xpdf_patching, included upstream
* disable patch: libpoppler-0.12, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
% utils.w
 
2
 
 
3
% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
 
4
% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
 
5
 
 
6
% This file is part of LuaTeX.
 
7
 
 
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.
 
12
 
 
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.
 
17
 
 
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/>. 
 
20
 
 
21
@ @c
 
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 $";
 
25
 
 
26
@ @c
 
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 */
 
31
#  include <stdio.h>
 
32
#endif
 
33
 
 
34
#include "sys/types.h"
 
35
#ifndef __MINGW32__
 
36
#  include "sysexits.h"
 
37
#else
 
38
#  define EX_SOFTWARE 70
 
39
#endif
 
40
#include <kpathsea/c-stat.h>
 
41
#include <kpathsea/c-fopen.h>
 
42
#include <string.h>
 
43
#include <time.h>
 
44
#include <float.h>              /* for |DBL_EPSILON| */
 
45
#include "zlib.h"
 
46
#include "ptexlib.h"
 
47
#include "md5.h"
 
48
 
 
49
#include "lua/luatex-api.h"     /* for ptexbanner */
 
50
 
 
51
#include "png.h"
 
52
#ifdef POPPLER_VERSION
 
53
#  define xpdfString "poppler"
 
54
#  include "poppler-config.h"
 
55
#  define xpdfVersion POPPLER_VERSION
 
56
#else
 
57
#  define xpdfString "xpdf"
 
58
#  include "xpdf/config.h"      /* just to get the xpdf version */
 
59
#endif
 
60
 
 
61
@ @c
 
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__);
 
65
 
 
66
char *cur_file_name = NULL;
 
67
static char print_buf[PRINTF_BUF_SIZE];
 
68
int epochseconds;
 
69
int microseconds;
 
70
 
 
71
/* define |char_ptr|, |char_array|, and |char_limit| */
 
72
typedef char char_entry;
 
73
define_array(char);
 
74
 
 
75
@ @c
 
76
#define SUBSET_TAG_LENGTH 6
 
77
void make_subset_tag(fd_entry * fd)
 
78
{
 
79
    int i, j = 0, a[SUBSET_TAG_LENGTH];
 
80
    md5_state_t pms;
 
81
    char *glyph;
 
82
    glw_entry *glw_glyph;
 
83
    struct avl_traverser t;
 
84
    md5_byte_t digest[16];
 
85
    void **aa;
 
86
    static struct avl_table *st_tree = NULL;
 
87
    if (st_tree == NULL)
 
88
        st_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
 
89
    assert(fd != NULL);
 
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);
 
94
    do {
 
95
        md5_init(&pms);
 
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)) {
 
100
                glyph = malloc(24);
 
101
                sprintf(glyph, "%05u%05u ", glw_glyph->id, glw_glyph->wd);
 
102
                md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph));
 
103
                free(glyph);
 
104
            }
 
105
        } else {
 
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);
 
110
            }
 
111
        }
 
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++)
 
117
            a[0] += digest[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';
 
123
        j++;
 
124
        assert(j < 100);
 
125
    }
 
126
    while ((char *) avl_find(st_tree, fd->subset_tag) != NULL);
 
127
    aa = avl_probe(st_tree, fd->subset_tag);
 
128
    assert(aa != NULL);
 
129
    if (j > 2)
 
130
        pdftex_warn
 
131
            ("\nmake_subset_tag(): subset-tag collision, resolved in round %d.\n",
 
132
             j);
 
133
}
 
134
 
 
135
@ @c
 
136
__attribute__ ((format(printf, 1, 2)))
 
137
void tex_printf(const char *fmt, ...)
 
138
{
 
139
    va_list args;
 
140
    va_start(args, fmt);
 
141
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
142
    tprint(print_buf);
 
143
    xfflush(stdout);
 
144
    va_end(args);
 
145
}
 
146
 
 
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.
 
151
 
 
152
   The output format of this fuction must be the same as |pdf_error| in
 
153
   pdftex.web! 
 
154
 
 
155
@c
 
156
__attribute__ ((noreturn, format(printf, 1, 2)))
 
157
void pdftex_fail(const char *fmt, ...)
 
158
{
 
159
    va_list args;
 
160
    va_start(args, fmt);
 
161
    print_ln();
 
162
    tprint("!LuaTeX error");
 
163
    if (cur_file_name) {
 
164
        tprint(" (file ");
 
165
        tprint(cur_file_name);
 
166
        tprint(")");
 
167
    }
 
168
    tprint(": ");
 
169
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
170
    tprint(print_buf);
 
171
    va_end(args);
 
172
    print_ln();
 
173
    remove_pdffile(static_pdf);
 
174
    tprint(" ==> Fatal error occurred, no output PDF file produced!");
 
175
    print_ln();
 
176
    if (kpathsea_debug) {
 
177
        abort();
 
178
    } else {
 
179
        exit(EX_SOFTWARE);
 
180
    }
 
181
}
 
182
 
 
183
@ The output format of this fuction must be the same as |pdf_warn| in
 
184
   pdftex.web!
 
185
@c
 
186
__attribute__ ((format(printf, 1, 2)))
 
187
void pdftex_warn(const char *fmt, ...)
 
188
{
 
189
    va_list args;
 
190
    va_start(args, fmt);
 
191
    print_ln();
 
192
    tex_printf("LuaTeX warning");
 
193
    if (cur_file_name)
 
194
        tex_printf(" (file %s)", cur_file_name);
 
195
    tex_printf(": ");
 
196
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
197
    tprint(print_buf);
 
198
    va_end(args);
 
199
    print_ln();
 
200
}
 
201
 
 
202
@ @c
 
203
void garbage_warning(void)
 
204
{
 
205
    pdftex_warn("dangling objects discarded, no output file produced.");
 
206
    remove_pdffile(static_pdf);
 
207
}
 
208
 
 
209
@ @c
 
210
char *pdftex_banner = NULL;
 
211
 
 
212
@ @c
 
213
void make_pdftex_banner(void)
 
214
{
 
215
    char *s;
 
216
    unsigned int slen;
 
217
    int i;
 
218
 
 
219
    if (pdftex_banner != NULL)
 
220
        return;
 
221
 
 
222
    slen = (unsigned int) (SMALL_BUF_SIZE +
 
223
                           strlen(ptexbanner) +
 
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);
 
231
    pdftex_banner = s;
 
232
}
 
233
 
 
234
@ @c
 
235
size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE * stream)
 
236
{
 
237
    if (fwrite(ptr, size, nmemb, stream) != nmemb)
 
238
        pdftex_fail("fwrite() failed");
 
239
    return nmemb;
 
240
}
 
241
 
 
242
@ @c
 
243
int xfflush(FILE * stream)
 
244
{
 
245
    if (fflush(stream) != 0)
 
246
        pdftex_fail("fflush() failed (%s)", strerror(errno));
 
247
    return 0;
 
248
}
 
249
 
 
250
@ @c
 
251
int xgetc(FILE * stream)
 
252
{
 
253
    int c = getc(stream);
 
254
    if (c < 0 && c != EOF)
 
255
        pdftex_fail("getc() failed (%s)", strerror(errno));
 
256
    return c;
 
257
}
 
258
 
 
259
@ @c
 
260
int xputc(int c, FILE * stream)
 
261
{
 
262
    int i = putc(c, stream);
 
263
    if (i < 0)
 
264
        pdftex_fail("putc() failed (%s)", strerror(errno));
 
265
    return i;
 
266
}
 
267
 
 
268
@ @c
 
269
scaled ext_xn_over_d(scaled x, scaled n, scaled d)
 
270
{
 
271
    double r = (((double) x) * ((double) n)) / ((double) d);
 
272
    if (r > DBL_EPSILON)
 
273
        r += 0.5;
 
274
    else
 
275
        r -= 0.5;
 
276
    if (r >= (double) max_integer || r <= -(double) max_integer)
 
277
        pdftex_warn("arithmetic: number too big");
 
278
    return (scaled) r;
 
279
}
 
280
 
 
281
@ function strips trailing zeros in string with numbers; 
 
282
leading zeros are not stripped (as in real life) 
 
283
@c
 
284
char *stripzeros(char *a)
 
285
{
 
286
    enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM;
 
287
    char *p, *q, *r;
 
288
    for (p = q = r = a; *p != '\0';) {
 
289
        switch (s) {
 
290
        case NONUM:
 
291
            if (*p >= '0' && *p <= '9')
 
292
                s = INT;
 
293
            else if (*p == '.')
 
294
                s = LEADDOT;
 
295
            break;
 
296
        case DOTNONUM:
 
297
            if (*p != '.' && (*p < '0' || *p > '9'))
 
298
                s = NONUM;
 
299
            break;
 
300
        case INT:
 
301
            if (*p == '.')
 
302
                s = DOT;
 
303
            else if (*p < '0' || *p > '9')
 
304
                s = NONUM;
 
305
            break;
 
306
        case DOT:
 
307
        case LEADDOT:
 
308
            if (*p >= '0' && *p <= '9')
 
309
                s = FRAC;
 
310
            else if (*p == '.')
 
311
                s = DOTNONUM;
 
312
            else
 
313
                s = NONUM;
 
314
            break;
 
315
        case FRAC:
 
316
            if (*p == '.')
 
317
                s = DOTNONUM;
 
318
            else if (*p < '0' || *p > '9')
 
319
                s = NONUM;
 
320
            break;
 
321
        default:;
 
322
        }
 
323
        switch (s) {
 
324
        case DOT:
 
325
            r = q;
 
326
            break;
 
327
        case LEADDOT:
 
328
            r = q + 1;
 
329
            break;
 
330
        case FRAC:
 
331
            if (*p > '0')
 
332
                r = q + 1;
 
333
            break;
 
334
        case NONUM:
 
335
            if ((t == FRAC || t == DOT) && r != a) {
 
336
                q = r--;
 
337
                if (*r == '.')  /* was a LEADDOT */
 
338
                    *r = '0';
 
339
                r = a;
 
340
            }
 
341
            break;
 
342
        default:;
 
343
        }
 
344
        *q++ = *p++;
 
345
        t = s;
 
346
    }
 
347
    *q = '\0';
 
348
    return a;
 
349
}
 
350
 
 
351
@ @c
 
352
void initversionstring(char **versions)
 
353
{
 
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);
 
360
}
 
361
 
 
362
@ @c
 
363
void check_buffer_overflow(int wsize)
 
364
{
 
365
    if (wsize > buf_size) {
 
366
        int nsize = buf_size + buf_size / 5 + 5;
 
367
        if (nsize < wsize) {
 
368
            nsize = wsize + 5;
 
369
        }
 
370
        buffer =
 
371
            (unsigned char *) xreallocarray(buffer, char, (unsigned) nsize);
 
372
        buf_size = nsize;
 
373
    }
 
374
}
 
375
 
 
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.
 
378
 
 
379
@c
 
380
#define max_integer 0x7FFFFFFF
 
381
 
 
382
scaled divide_scaled(scaled s, scaled m, int dd)
 
383
{
 
384
    register scaled q;
 
385
    register scaled r;
 
386
    int i;
 
387
    int sign = 1;
 
388
    if (s < 0) {
 
389
        sign = -sign;
 
390
        s = -s;
 
391
    }
 
392
    if (m < 0) {
 
393
        sign = -sign;
 
394
        m = -m;
 
395
    }
 
396
    if (m == 0) {
 
397
        pdf_error("arithmetic", "divided by zero");
 
398
    } else if (m >= (max_integer / 10)) {
 
399
        pdf_error("arithmetic", "number too big");
 
400
    }
 
401
    q = s / m;
 
402
    r = s % m;
 
403
    for (i = 1; i <= (int) dd; i++) {
 
404
        q = 10 * q + (10 * r) / m;
 
405
        r = (10 * r) % m;
 
406
    }
 
407
    /* rounding */
 
408
    if (2 * r >= m) {
 
409
        q++;
 
410
        r -= m;
 
411
    }
 
412
    return sign * q;
 
413
}
 
414
 
 
415
@ Same function, but using doubles instead of integers (faster) 
 
416
@c
 
417
scaled divide_scaled_n(double sd, double md, double n)
 
418
{
 
419
    double dd, di = 0.0;
 
420
    dd = sd / md * n;
 
421
    if (dd > 0.0)
 
422
        di = floor(dd + 0.5);
 
423
    else if (dd < 0.0)
 
424
        di = -floor((-dd) + 0.5);
 
425
    return (scaled) di;
 
426
}
 
427
 
 
428
@ @c
 
429
int do_zround(double r)
 
430
{
 
431
    int i;
 
432
 
 
433
    if (r > 2147483647.0)
 
434
        i = 2147483647;
 
435
    else if (r < -2147483647.0)
 
436
        i = -2147483647;
 
437
    else if (r >= 0.0)
 
438
        i = (int) (r + 0.5);
 
439
    else
 
440
        i = (int) (r - 0.5);
 
441
 
 
442
    return i;
 
443
}
 
444
 
 
445
 
 
446
@ MSVC doesn't have |rind|.
 
447
@c
 
448
#ifdef MSVC
 
449
 
 
450
#  include <math.h>
 
451
double rint(double x)
 
452
{
 
453
    double c, f, d1, d2;
 
454
 
 
455
    c = ceil(x);
 
456
    f = floor(x);
 
457
    d1 = fabs(c - x);
 
458
    d2 = fabs(x - f);
 
459
    if (d1 > d2)
 
460
        return f;
 
461
    else
 
462
        return c;
 
463
}
 
464
 
 
465
#endif