diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/utils/utils.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/utils/utils.w | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/utils/utils.w b/Build/source/texk/web2c/luatexdir/utils/utils.w new file mode 100644 index 00000000000..777f153ddf4 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/utils/utils.w @@ -0,0 +1,465 @@ +% utils.w + +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. + +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: utils.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/utils/utils.w $"; + +@ @c +#include "openbsd-compat.h" +#include <kpathsea/config.h> /* this is a trick to load mingw32's io.h early, + using a macro redefinition of |eof()|. */ +#ifdef HAVE_ASPRINTF /* asprintf is not defined in openbsd-compat.h, but in stdio.h */ +# include <stdio.h> +#endif + +#include "sys/types.h" +#ifndef __MINGW32__ +# include "sysexits.h" +#else +# define EX_SOFTWARE 70 +#endif +#include <kpathsea/c-stat.h> +#include <kpathsea/c-fopen.h> +#include <string.h> +#include <time.h> +#include <float.h> /* for |DBL_EPSILON| */ +#include "zlib.h" +#include "ptexlib.h" +#include "md5.h" + +#include "lua/luatex-api.h" /* for ptexbanner */ + +#include "png.h" +#ifdef POPPLER_VERSION +# define xpdfString "poppler" +# include "poppler-config.h" +# define xpdfVersion POPPLER_VERSION +#else +# define xpdfString "xpdf" +# include "xpdf/config.h" /* just to get the xpdf version */ +#endif + +@ @c +#define check_nprintf(size_get, size_want) \ + if ((unsigned)(size_get) >= (unsigned)(size_want)) \ + pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__); + +char *cur_file_name = NULL; +static char print_buf[PRINTF_BUF_SIZE]; +int epochseconds; +int microseconds; + +/* define |char_ptr|, |char_array|, and |char_limit| */ +typedef char char_entry; +define_array(char); + +@ @c +#define SUBSET_TAG_LENGTH 6 +void make_subset_tag(fd_entry * fd) +{ + int i, j = 0, a[SUBSET_TAG_LENGTH]; + md5_state_t pms; + char *glyph; + glw_entry *glw_glyph; + struct avl_traverser t; + md5_byte_t digest[16]; + void **aa; + static struct avl_table *st_tree = NULL; + if (st_tree == NULL) + st_tree = avl_create(comp_string_entry, NULL, &avl_xallocator); + assert(fd != NULL); + assert(fd->gl_tree != NULL); + assert(fd->fontname != NULL); + assert(fd->subset_tag == NULL); + fd->subset_tag = xtalloc(SUBSET_TAG_LENGTH + 1, char); + do { + md5_init(&pms); + avl_t_init(&t, fd->gl_tree); + if (is_cidkeyed(fd->fm)) { /* |glw_entry| items */ + for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree); + glw_glyph != NULL; glw_glyph = (glw_entry *) avl_t_next(&t)) { + glyph = malloc(24); + sprintf(glyph, "%05u%05u ", glw_glyph->id, glw_glyph->wd); + md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph)); + free(glyph); + } + } else { + for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL; + glyph = (char *) avl_t_next(&t)) { + md5_append(&pms, (md5_byte_t *) glyph, (int) strlen(glyph)); + md5_append(&pms, (const md5_byte_t *) " ", 1); + } + } + md5_append(&pms, (md5_byte_t *) fd->fontname, + (int) strlen(fd->fontname)); + md5_append(&pms, (md5_byte_t *) & j, sizeof(int)); /* to resolve collision */ + md5_finish(&pms, digest); + for (a[0] = 0, i = 0; i < 13; i++) + a[0] += digest[i]; + for (i = 1; i < SUBSET_TAG_LENGTH; i++) + a[i] = a[i - 1] - digest[i - 1] + digest[(i + 12) % 16]; + for (i = 0; i < SUBSET_TAG_LENGTH; i++) + fd->subset_tag[i] = (char) (a[i] % 26 + 'A'); + fd->subset_tag[SUBSET_TAG_LENGTH] = '\0'; + j++; + assert(j < 100); + } + while ((char *) avl_find(st_tree, fd->subset_tag) != NULL); + aa = avl_probe(st_tree, fd->subset_tag); + assert(aa != NULL); + if (j > 2) + pdftex_warn + ("\nmake_subset_tag(): subset-tag collision, resolved in round %d.\n", + j); +} + +@ @c +__attribute__ ((format(printf, 1, 2))) +void tex_printf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args); + tprint(print_buf); + xfflush(stdout); + va_end(args); +} + +@ |pdftex_fail| may be called when a buffer overflow has happened/is + happening, therefore may not call mktexstring. However, with the + current implementation it appears that error messages are misleading, + possibly because pool overflows are detected too late. + + The output format of this fuction must be the same as |pdf_error| in + pdftex.web! + +@c +__attribute__ ((noreturn, format(printf, 1, 2))) +void pdftex_fail(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + print_ln(); + tprint("!LuaTeX error"); + if (cur_file_name) { + tprint(" (file "); + tprint(cur_file_name); + tprint(")"); + } + tprint(": "); + vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args); + tprint(print_buf); + va_end(args); + print_ln(); + remove_pdffile(static_pdf); + tprint(" ==> Fatal error occurred, no output PDF file produced!"); + print_ln(); + if (kpathsea_debug) { + abort(); + } else { + exit(EX_SOFTWARE); + } +} + +@ The output format of this fuction must be the same as |pdf_warn| in + pdftex.web! +@c +__attribute__ ((format(printf, 1, 2))) +void pdftex_warn(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + print_ln(); + tex_printf("LuaTeX warning"); + if (cur_file_name) + tex_printf(" (file %s)", cur_file_name); + tex_printf(": "); + vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args); + tprint(print_buf); + va_end(args); + print_ln(); +} + +@ @c +void garbage_warning(void) +{ + pdftex_warn("dangling objects discarded, no output file produced."); + remove_pdffile(static_pdf); +} + +@ @c +char *pdftex_banner = NULL; + +@ @c +void make_pdftex_banner(void) +{ + char *s; + unsigned int slen; + int i; + + if (pdftex_banner != NULL) + return; + + slen = (unsigned int) (SMALL_BUF_SIZE + + strlen(ptexbanner) + + strlen(versionstring) + + strlen(kpathsea_version_string)); + s = xtalloc(slen, char); + /* The Web2c version string starts with a space. */ + i = snprintf(s, slen, + "%s%s %s", ptexbanner, versionstring, kpathsea_version_string); + check_nprintf(i, slen); + pdftex_banner = s; +} + +@ @c +size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE * stream) +{ + if (fwrite(ptr, size, nmemb, stream) != nmemb) + pdftex_fail("fwrite() failed"); + return nmemb; +} + +@ @c +int xfflush(FILE * stream) +{ + if (fflush(stream) != 0) + pdftex_fail("fflush() failed (%s)", strerror(errno)); + return 0; +} + +@ @c +int xgetc(FILE * stream) +{ + int c = getc(stream); + if (c < 0 && c != EOF) + pdftex_fail("getc() failed (%s)", strerror(errno)); + return c; +} + +@ @c +int xputc(int c, FILE * stream) +{ + int i = putc(c, stream); + if (i < 0) + pdftex_fail("putc() failed (%s)", strerror(errno)); + return i; +} + +@ @c +scaled ext_xn_over_d(scaled x, scaled n, scaled d) +{ + double r = (((double) x) * ((double) n)) / ((double) d); + if (r > DBL_EPSILON) + r += 0.5; + else + r -= 0.5; + if (r >= (double) max_integer || r <= -(double) max_integer) + pdftex_warn("arithmetic: number too big"); + return (scaled) r; +} + +@ function strips trailing zeros in string with numbers; +leading zeros are not stripped (as in real life) +@c +char *stripzeros(char *a) +{ + enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM; + char *p, *q, *r; + for (p = q = r = a; *p != '\0';) { + switch (s) { + case NONUM: + if (*p >= '0' && *p <= '9') + s = INT; + else if (*p == '.') + s = LEADDOT; + break; + case DOTNONUM: + if (*p != '.' && (*p < '0' || *p > '9')) + s = NONUM; + break; + case INT: + if (*p == '.') + s = DOT; + else if (*p < '0' || *p > '9') + s = NONUM; + break; + case DOT: + case LEADDOT: + if (*p >= '0' && *p <= '9') + s = FRAC; + else if (*p == '.') + s = DOTNONUM; + else + s = NONUM; + break; + case FRAC: + if (*p == '.') + s = DOTNONUM; + else if (*p < '0' || *p > '9') + s = NONUM; + break; + default:; + } + switch (s) { + case DOT: + r = q; + break; + case LEADDOT: + r = q + 1; + break; + case FRAC: + if (*p > '0') + r = q + 1; + break; + case NONUM: + if ((t == FRAC || t == DOT) && r != a) { + q = r--; + if (*r == '.') /* was a LEADDOT */ + *r = '0'; + r = a; + } + break; + default:; + } + *q++ = *p++; + t = s; + } + *q = '\0'; + return a; +} + +@ @c +void initversionstring(char **versions) +{ + (void) asprintf(versions, + "Compiled with libpng %s; using libpng %s\n" + "Compiled with zlib %s; using zlib %s\n" + "Compiled with %s version %s\n", + PNG_LIBPNG_VER_STRING, png_libpng_ver, + ZLIB_VERSION, zlib_version, xpdfString, xpdfVersion); +} + +@ @c +void check_buffer_overflow(int wsize) +{ + if (wsize > buf_size) { + int nsize = buf_size + buf_size / 5 + 5; + if (nsize < wsize) { + nsize = wsize + 5; + } + buffer = + (unsigned char *) xreallocarray(buffer, char, (unsigned) nsize); + buf_size = nsize; + } +} + +@ the return value is a decimal number with the point |dd| places from the back, + |scaled_out| is the number of scaled points corresponding to that. + +@c +#define max_integer 0x7FFFFFFF + +scaled divide_scaled(scaled s, scaled m, int dd) +{ + register scaled q; + register scaled r; + int i; + int sign = 1; + if (s < 0) { + sign = -sign; + s = -s; + } + if (m < 0) { + sign = -sign; + m = -m; + } + if (m == 0) { + pdf_error("arithmetic", "divided by zero"); + } else if (m >= (max_integer / 10)) { + pdf_error("arithmetic", "number too big"); + } + q = s / m; + r = s % m; + for (i = 1; i <= (int) dd; i++) { + q = 10 * q + (10 * r) / m; + r = (10 * r) % m; + } + /* rounding */ + if (2 * r >= m) { + q++; + r -= m; + } + return sign * q; +} + +@ Same function, but using doubles instead of integers (faster) +@c +scaled divide_scaled_n(double sd, double md, double n) +{ + double dd, di = 0.0; + dd = sd / md * n; + if (dd > 0.0) + di = floor(dd + 0.5); + else if (dd < 0.0) + di = -floor((-dd) + 0.5); + return (scaled) di; +} + +@ @c +int do_zround(double r) +{ + int i; + + if (r > 2147483647.0) + i = 2147483647; + else if (r < -2147483647.0) + i = -2147483647; + else if (r >= 0.0) + i = (int) (r + 0.5); + else + i = (int) (r - 0.5); + + return i; +} + + +@ MSVC doesn't have |rind|. +@c +#ifdef MSVC + +# include <math.h> +double rint(double x) +{ + double c, f, d1, d2; + + c = ceil(x); + f = floor(x); + d1 = fabs(c - x); + d2 = fabs(x - f); + if (d1 > d2) + return f; + else + return c; +} + +#endif |