~ubuntu-branches/ubuntu/intrepid/luatex/intrepid

« back to all changes in this revision

Viewing changes to src/texk/web2c/luatexdir/utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2008-07-07 11:01:13 UTC
  • mfrom: (1.1.5 upstream) (4.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080707110113-1y7lam37zbbb7bbt
Tags: 0.28.0-1
* two new upstream releases, see the respective ANNOUCE files
* add luasocket license statement to debian/copyright
* activate the pdfluatex format
* prepare for latex based formats
  - add the ini files from TeX Live
  - add debian/formats file
  - adjust dh_installtex incantation
  the problem is that luatex dies when loading ukrhypmp.tex from 
  texlive-lang-cyrillic, but we don't want to conflict with it by now.
* policy 3.8.0, rename README.Debian-source to README.source, and add
  notes about quilt usage
* disable patch fix-pwd-inclusion (it was from svn)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
3
 
 
4
 
This file is part of pdfTeX.
5
 
 
6
 
pdfTeX is free software; you can redistribute it and/or modify
7
 
it under the terms of the GNU General Public License as published by
8
 
the Free Software Foundation; either version 2 of the License, or
9
 
(at your option) any later version.
10
 
 
11
 
pdfTeX is distributed in the hope that it will be useful,
12
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
GNU General Public License for more details.
15
 
 
16
 
You should have received a copy of the GNU General Public License
17
 
along with pdfTeX; if not, write to the Free Software
18
 
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
 
20
 
$Id: utils.c 1013 2008-02-14 00:09:02Z oneiros $
21
 
*/
 
1
/* utils.c
 
2
   
 
3
   Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
 
4
   Copyright 2006-2008 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
#include "openbsd-compat.h"
 
22
#ifdef HAVE_ASPRINTF            /* asprintf is not defined in openbsd-compat.h, but in stdio.h */
 
23
#  include <stdio.h>
 
24
#endif
 
25
 
22
26
 
23
27
#include "sys/types.h"
24
28
#ifndef __MINGW32__
25
 
#include "sysexits.h"
 
29
#  include "sysexits.h"
26
30
#else
27
 
#define EX_SOFTWARE 70
 
31
#  define EX_SOFTWARE 70
28
32
#endif
29
33
#include "md5.h"
30
34
#include <kpathsea/c-proto.h>
36
40
#include "zlib.h"
37
41
#include "ptexlib.h"
38
42
 
39
 
#include "svnversion.h"
40
 
 
41
 
#include "openbsd-compat.h"
42
43
#include "png.h"
43
44
#include "xpdf/config.h"        /* just to get the xpdf version */
44
45
 
 
46
static const char __svn_version[] =
 
47
    "$Id: utils.c 1337 2008-06-25 07:49:26Z taco $ $URL: http://scm.foundry.supelec.fr/svn/luatex/tags/beta-0.28.0/src/texk/web2c/luatexdir/utils.c $";
 
48
 
45
49
#define check_nprintf(size_get, size_want) \
46
50
    if ((unsigned)(size_get) >= (unsigned)(size_want)) \
47
51
        pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
59
63
 
60
64
/* define fb_ptr, fb_array & fb_limit */
61
65
typedef char fb_entry;
62
 
define_array (fb);
 
66
define_array(fb);
63
67
 
64
68
/* define char_ptr, char_array & char_limit */
65
69
typedef char char_entry;
66
 
define_array (char);
 
70
define_array(char);
67
71
 
68
 
integer fb_offset (void)
 
72
integer fb_offset(void)
69
73
{
70
74
    return fb_ptr - fb_array;
71
75
}
72
76
 
73
 
void fb_seek (integer offset)
 
77
void fb_seek(integer offset)
74
78
{
75
79
    fb_ptr = fb_array + offset;
76
80
}
77
81
 
78
 
void fb_putchar (eight_bits b)
 
82
void fb_putchar(eight_bits b)
79
83
{
80
 
    alloc_array (fb, 1, SMALL_ARRAY_SIZE);
 
84
    alloc_array(fb, 1, SMALL_ARRAY_SIZE);
81
85
    *fb_ptr++ = b;
82
86
}
83
87
 
84
 
void fb_flush (void)
 
88
void fb_flush(void)
85
89
{
86
90
    fb_entry *p;
87
91
    integer n;
89
93
        n = pdf_buf_size - pdf_ptr;
90
94
        if (fb_ptr - p < n)
91
95
            n = fb_ptr - p;
92
 
        memcpy (pdf_buf + pdf_ptr, p, (unsigned) n);
 
96
        memcpy(pdf_buf + pdf_ptr, p, (unsigned) n);
93
97
        pdf_ptr += n;
94
98
        if (pdf_ptr == pdf_buf_size)
95
 
            pdf_flush ();
 
99
            pdf_flush();
96
100
        p += n;
97
101
    }
98
102
    fb_ptr = fb_array;
104
108
    int i, j = 0, a[SUBSET_TAG_LENGTH];
105
109
    md5_state_t pms;
106
110
    char *glyph;
107
 
        glw_entry *glw_glyph;
 
111
    glw_entry *glw_glyph;
108
112
    struct avl_traverser t;
109
113
    md5_byte_t digest[16];
110
114
    void **aa;
119
123
    do {
120
124
        md5_init(&pms);
121
125
        avl_t_init(&t, fd->gl_tree);
122
 
                if (is_cidkeyed(fd->fm)) { /* glw_entry items */
123
 
                  for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree); glw_glyph != NULL;
124
 
                           glw_glyph = (glw_entry *) avl_t_next(&t)) {
125
 
                        glyph = malloc(12);
126
 
                        sprintf(glyph,"%05u%05u ",glw_glyph->id,glw_glyph->wd);
127
 
            md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
128
 
                        free(glyph);
129
 
                  }
130
 
                } else {
131
 
                  for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
132
 
                           glyph = (char *) avl_t_next(&t)) {
133
 
            md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
134
 
            md5_append(&pms, (md5_byte_t *) " ", 1);
135
 
                  }
136
 
                }
 
126
        if (is_cidkeyed(fd->fm)) {      /* glw_entry items */
 
127
            for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree);
 
128
                 glw_glyph != NULL; glw_glyph = (glw_entry *) avl_t_next(&t)) {
 
129
                glyph = malloc(12);
 
130
                sprintf(glyph, "%05u%05u ", glw_glyph->id, glw_glyph->wd);
 
131
                md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
 
132
                free(glyph);
 
133
            }
 
134
        } else {
 
135
            for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
 
136
                 glyph = (char *) avl_t_next(&t)) {
 
137
                md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
 
138
                md5_append(&pms, (md5_byte_t *) " ", 1);
 
139
            }
 
140
        }
137
141
        md5_append(&pms, (md5_byte_t *) fd->fontname, strlen(fd->fontname));
138
142
        md5_append(&pms, (md5_byte_t *) & j, sizeof(int));      /* to resolve collision */
139
143
        md5_finish(&pms, digest);
156
160
             j);
157
161
}
158
162
 
159
 
void pdf_puts (const char *s)
 
163
void pdf_puts(const char *s)
160
164
{
161
 
    pdfroom (strlen (s) + 1);
 
165
    pdfroom(strlen(s) + 1);
162
166
    while (*s)
163
167
        pdf_buf[pdf_ptr++] = *s++;
164
168
}
165
169
 
166
 
__attribute__ ((format (printf, 1, 2))) 
167
 
void pdf_printf (const char *fmt, ...)
 
170
__attribute__ ((format(printf, 1, 2)))
 
171
void pdf_printf(const char *fmt, ...)
168
172
{
169
173
    va_list args;
170
 
    va_start (args, fmt);
171
 
    vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
172
 
    pdf_puts (print_buf);
173
 
    va_end (args);
 
174
    va_start(args, fmt);
 
175
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
176
    pdf_puts(print_buf);
 
177
    va_end(args);
174
178
}
175
179
 
176
 
strnumber maketexstring (const char *s)
 
180
strnumber maketexstring(const char *s)
177
181
{
178
 
  if (s == NULL || *s == 0)
179
 
    return get_nullstr ();
180
 
  return maketexlstring(s,strlen(s));
 
182
    if (s == NULL || *s == 0)
 
183
        return get_nullstr();
 
184
    return maketexlstring(s, strlen(s));
181
185
}
182
186
 
183
 
strnumber maketexlstring (const char *s, size_t l) 
 
187
strnumber maketexlstring(const char *s, size_t l)
184
188
{
185
189
    if (s == NULL || l == 0)
186
 
      return get_nullstr ();
187
 
    check_pool_overflow (pool_ptr + l);
 
190
        return get_nullstr();
 
191
    check_pool_overflow(pool_ptr + l);
188
192
    while (l-- > 0)
189
193
        str_pool[pool_ptr++] = *s++;
190
 
    last_tex_string = make_string ();
 
194
    last_tex_string = make_string();
191
195
    return last_tex_string;
192
196
}
193
197
 
194
198
 
195
199
/* print a C string through TeX */
196
 
void 
197
 
print_string (char *j) {
198
 
  while (*j) {
199
 
    print_char(*j);
200
 
        j++;
201
 
  }
 
200
void print_string(char *j)
 
201
{
 
202
    while (*j) {
 
203
        print_char(*j);
 
204
        j++;
 
205
    }
202
206
}
203
207
 
204
208
/* append a C string to a TeX string */
205
 
void 
206
 
append_string (char *s) {
207
 
  if (s == NULL || *s == 0)
208
 
        return;
209
 
  check_buf (pool_ptr + strlen(s), pool_size);
210
 
  while (*s)
211
 
        str_pool[pool_ptr++] = *s++;
212
 
  return;
 
209
void append_string(char *s)
 
210
{
 
211
    if (s == NULL || *s == 0)
 
212
        return;
 
213
    check_buf(pool_ptr + strlen(s), pool_size);
 
214
    while (*s)
 
215
        str_pool[pool_ptr++] = *s++;
 
216
    return;
213
217
}
214
218
 
215
 
__attribute__ ((format (printf, 1, 2)))
216
 
void tex_printf (const char *fmt, ...) 
 
219
__attribute__ ((format(printf, 1, 2)))
 
220
void tex_printf(const char *fmt, ...)
217
221
{
218
222
    va_list args;
219
 
    va_start (args, fmt);
220
 
    vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
221
 
    print_string (print_buf);
222
 
    xfflush (stdout);
223
 
    va_end (args);
 
223
    va_start(args, fmt);
 
224
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
225
    print_string(print_buf);
 
226
    xfflush(stdout);
 
227
    va_end(args);
224
228
}
225
229
 
226
230
/* Helper for pdftex_fail. */
227
 
static void safe_print (const char *str)
 
231
static void safe_print(const char *str)
228
232
{
229
233
    const char *c;
230
234
    for (c = str; *c; ++c)
231
 
        print (*c);
 
235
        print(*c);
232
236
}
233
237
 
234
 
void remove_pdffile (void)
 
238
void remove_pdffile(void)
235
239
{
236
240
    if (!kpathsea_debug && output_file_name && !fixed_pdf_draftmode) {
237
 
        xfclose (pdf_file, makecstring (output_file_name));
238
 
        remove (makecstring (output_file_name));
 
241
        xfclose(pdf_file, makecstring(output_file_name));
 
242
        remove(makecstring(output_file_name));
239
243
    }
240
244
}
241
245
 
247
251
   The output format of this fuction must be the same as pdf_error in
248
252
   pdftex.web! */
249
253
 
250
 
__attribute__ ((noreturn, format (printf, 1, 2)))
251
 
void pdftex_fail (const char *fmt, ...)
 
254
__attribute__ ((noreturn, format(printf, 1, 2)))
 
255
void pdftex_fail(const char *fmt, ...)
252
256
{
253
257
    va_list args;
254
 
    va_start (args, fmt);
255
 
    print_ln ();
256
 
    safe_print ("!luaTeX error");
 
258
    va_start(args, fmt);
 
259
    print_ln();
 
260
    safe_print("!luaTeX error");
257
261
    if (cur_file_name) {
258
 
        safe_print (" (file ");
259
 
        safe_print (cur_file_name);
260
 
        safe_print (")");
 
262
        safe_print(" (file ");
 
263
        safe_print(cur_file_name);
 
264
        safe_print(")");
261
265
    }
262
 
    safe_print (": ");
263
 
    vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
264
 
    safe_print (print_buf);
265
 
    va_end (args);
266
 
    print_ln ();
 
266
    safe_print(": ");
 
267
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
268
    safe_print(print_buf);
 
269
    va_end(args);
 
270
    print_ln();
267
271
    remove_pdffile();
268
 
    safe_print (" ==> Fatal error occurred, no output PDF file produced!");
269
 
    print_ln ();
 
272
    safe_print(" ==> Fatal error occurred, no output PDF file produced!");
 
273
    print_ln();
270
274
    if (kpathsea_debug) {
271
 
        abort ();
 
275
        abort();
272
276
    } else {
273
 
        exit (EX_SOFTWARE);
 
277
        exit(EX_SOFTWARE);
274
278
    }
275
279
}
276
280
 
277
281
/* The output format of this fuction must be the same as pdf_warn in
278
282
   pdftex.web! */
279
283
 
280
 
__attribute__ ((format (printf, 1, 2)))
281
 
void pdftex_warn (const char *fmt, ...) 
 
284
__attribute__ ((format(printf, 1, 2)))
 
285
void pdftex_warn(const char *fmt, ...)
282
286
{
283
287
    va_list args;
284
 
    va_start (args, fmt);
285
 
    print_ln ();
286
 
    tex_printf ("luaTeX warning");
 
288
    va_start(args, fmt);
 
289
    print_ln();
 
290
    tex_printf("luaTeX warning");
287
291
    if (cur_file_name)
288
 
        tex_printf (" (file %s)", cur_file_name);
289
 
    tex_printf (": ");
290
 
    vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args);
291
 
    print_string (print_buf);
292
 
    va_end (args);
293
 
    print_ln ();
294
 
}
295
 
 
296
 
 
297
 
void tex_error(char *msg, char **hlp) {
298
 
  strnumber aa = 0,bb = 0,cc = 0,dd = 0,ee = 0;
299
 
  int k = 0;
300
 
  while (hlp[k]!=NULL)
301
 
    k++;
302
 
  if (k>0)    aa =maketexstring(hlp[0]);
303
 
  if (k>1)    bb =maketexstring(hlp[1]);
304
 
  if (k>2)    cc =maketexstring(hlp[2]);
305
 
  if (k>3)    dd =maketexstring(hlp[3]);
306
 
  if (k>4)    ee =maketexstring(hlp[4]);
307
 
 
308
 
  do_print_err(maketexstring(msg)); 
309
 
  flush_str(last_tex_string);
310
 
 
311
 
  switch (k) {
312
 
  case 1:   dohelp1(aa); break;
313
 
  case 2:   dohelp2(aa,bb); break;
314
 
  case 3:   dohelp3(aa,bb,cc); break;
315
 
  case 4:   dohelp4(aa,bb,cc,dd); break;
316
 
  case 5:   dohelp5(aa,bb,cc,dd,ee); break;
317
 
  }
318
 
  error();
319
 
 
320
 
  if (ee)    flush_str(ee);
321
 
  if (dd)    flush_str(dd);
322
 
  if (cc)    flush_str(cc);
323
 
  if (bb)    flush_str(bb);
324
 
  if (aa)    flush_str(aa);
325
 
}
326
 
 
327
 
 
328
 
void garbage_warning (void)
329
 
{
330
 
    pdftex_warn ("dangling objects discarded, no output file produced.");
331
 
    remove_pdffile ();
332
 
}
333
 
 
334
 
char *makecstring (integer s) {
335
 
  int l;
336
 
  return makeclstring(s,&l);
337
 
}
338
 
 
339
 
 
340
 
char *makeclstring (integer s, int *len)
 
292
        tex_printf(" (file %s)", cur_file_name);
 
293
    tex_printf(": ");
 
294
    vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
 
295
    print_string(print_buf);
 
296
    va_end(args);
 
297
    print_ln();
 
298
}
 
299
 
 
300
 
 
301
void tex_error(char *msg, char **hlp)
 
302
{
 
303
    strnumber aa = 0, bb = 0, cc = 0, dd = 0, ee = 0;
 
304
    int k = 0;
 
305
    while (hlp[k] != NULL)
 
306
        k++;
 
307
    if (k > 0)
 
308
        aa = maketexstring(hlp[0]);
 
309
    if (k > 1)
 
310
        bb = maketexstring(hlp[1]);
 
311
    if (k > 2)
 
312
        cc = maketexstring(hlp[2]);
 
313
    if (k > 3)
 
314
        dd = maketexstring(hlp[3]);
 
315
    if (k > 4)
 
316
        ee = maketexstring(hlp[4]);
 
317
 
 
318
    do_print_err(maketexstring(msg));
 
319
    flush_str(last_tex_string);
 
320
 
 
321
/* *INDENT-OFF* */
 
322
    switch (k) {
 
323
    case 1: dohelp1(aa); break;
 
324
    case 2: dohelp2(aa, bb); break;
 
325
    case 3: dohelp3(aa, bb, cc); break;
 
326
    case 4: dohelp4(aa, bb, cc, dd); break;
 
327
    case 5: dohelp5(aa, bb, cc, dd, ee); break;
 
328
    }
 
329
/* *INDENT-ON* */
 
330
    error();
 
331
 
 
332
    if (ee)
 
333
        flush_str(ee);
 
334
    if (dd)
 
335
        flush_str(dd);
 
336
    if (cc)
 
337
        flush_str(cc);
 
338
    if (bb)
 
339
        flush_str(bb);
 
340
    if (aa)
 
341
        flush_str(aa);
 
342
}
 
343
 
 
344
 
 
345
void garbage_warning(void)
 
346
{
 
347
    pdftex_warn("dangling objects discarded, no output file produced.");
 
348
    remove_pdffile();
 
349
}
 
350
 
 
351
char *makecstring(integer s)
 
352
{
 
353
    int l;
 
354
    return makeclstring(s, &l);
 
355
}
 
356
 
 
357
 
 
358
char *makeclstring(integer s, int *len)
341
359
{
342
360
    static char *cstrbuf = NULL;
343
361
    char *p;
344
362
    static int allocsize;
345
363
    int allocgrow, i, l;
346
 
    if (s >=2097152) {
347
 
      s -= 2097152;
348
 
      l = str_start[s + 1] - str_start[s];
349
 
      *len = l;
350
 
      check_buf (l + 1, MAX_CSTRING_LEN);
351
 
      if (cstrbuf == NULL) {
352
 
        allocsize = l + 1;
353
 
        cstrbuf = xmallocarray (char, allocsize);
354
 
      } else if (l + 1 > allocsize) {
355
 
        allocgrow = allocsize * 0.2;
356
 
        if (l + 1 - allocgrow > allocsize)
357
 
          allocsize = l + 1;
358
 
        else if (allocsize < MAX_CSTRING_LEN - allocgrow)
359
 
          allocsize += allocgrow;
360
 
        else
361
 
          allocsize = MAX_CSTRING_LEN;
362
 
        cstrbuf = xreallocarray (cstrbuf, char, allocsize);
363
 
      }
364
 
      p = cstrbuf;
365
 
      for (i = 0; i < l; i++)
366
 
        *p++ = str_pool[i + str_start[s]];
367
 
      *p = 0;
 
364
    if (s >= 2097152) {
 
365
        s -= 2097152;
 
366
        l = str_start[s + 1] - str_start[s];
 
367
        *len = l;
 
368
        check_buf(l + 1, MAX_CSTRING_LEN);
 
369
        if (cstrbuf == NULL) {
 
370
            allocsize = l + 1;
 
371
            cstrbuf = xmallocarray(char, allocsize);
 
372
        } else if (l + 1 > allocsize) {
 
373
            allocgrow = allocsize * 0.2;
 
374
            if (l + 1 - allocgrow > allocsize)
 
375
                allocsize = l + 1;
 
376
            else if (allocsize < MAX_CSTRING_LEN - allocgrow)
 
377
                allocsize += allocgrow;
 
378
            else
 
379
                allocsize = MAX_CSTRING_LEN;
 
380
            cstrbuf = xreallocarray(cstrbuf, char, allocsize);
 
381
        }
 
382
        p = cstrbuf;
 
383
        for (i = 0; i < l; i++)
 
384
            *p++ = str_pool[i + str_start[s]];
 
385
        *p = 0;
368
386
    } else {
369
 
      if (cstrbuf == NULL) {
370
 
        allocsize = 5;
371
 
        cstrbuf = xmallocarray (char, allocsize);
372
 
      }
373
 
          if (s <= 0x7F) {
374
 
                cstrbuf[0] = s;
375
 
                cstrbuf[1] = 0;
376
 
                *len = 1;
377
 
          } else if (s <= 0x7FF ) {
378
 
                cstrbuf[0] = 0xC0 + (s / 0x40);
379
 
                cstrbuf[1] = 0x80 + (s % 0x40);
380
 
                cstrbuf[2] = 0;
381
 
                *len = 2;
382
 
          } else if (s <= 0xFFFF ) {
383
 
                cstrbuf[0] = 0xE0 + (s / 0x1000);
384
 
                cstrbuf[1] = 0x80 + ((s % 0x1000) / 0x40);
385
 
                cstrbuf[2] = 0x80 + ((s % 0x1000) % 0x40);
386
 
                cstrbuf[3] = 0;
387
 
                *len = 3;
388
 
          } else {
389
 
            if (s >= 0x10FF00) {
390
 
                  cstrbuf[0] = s-0x10FF00;
391
 
                  cstrbuf[1] = 0;
392
 
                  *len = 1;
393
 
                } else {
394
 
                  cstrbuf[0] = 0xF0 + (s / 0x40000);
395
 
                  cstrbuf[1] = 0x80 + ((s % 0x40000) / 0x1000);
396
 
                  cstrbuf[2] = 0x80 + (((s % 0x40000) % 0x1000) / 0x40);
397
 
                  cstrbuf[3] = 0x80 + (((s % 0x40000) % 0x1000) % 0x40);
398
 
                  cstrbuf[4] = 0;
399
 
                  *len = 4;
400
 
                }
401
 
          }
 
387
        if (cstrbuf == NULL) {
 
388
            allocsize = 5;
 
389
            cstrbuf = xmallocarray(char, allocsize);
 
390
        }
 
391
        if (s <= 0x7F) {
 
392
            cstrbuf[0] = s;
 
393
            cstrbuf[1] = 0;
 
394
            *len = 1;
 
395
        } else if (s <= 0x7FF) {
 
396
            cstrbuf[0] = 0xC0 + (s / 0x40);
 
397
            cstrbuf[1] = 0x80 + (s % 0x40);
 
398
            cstrbuf[2] = 0;
 
399
            *len = 2;
 
400
        } else if (s <= 0xFFFF) {
 
401
            cstrbuf[0] = 0xE0 + (s / 0x1000);
 
402
            cstrbuf[1] = 0x80 + ((s % 0x1000) / 0x40);
 
403
            cstrbuf[2] = 0x80 + ((s % 0x1000) % 0x40);
 
404
            cstrbuf[3] = 0;
 
405
            *len = 3;
 
406
        } else {
 
407
            if (s >= 0x10FF00) {
 
408
                cstrbuf[0] = s - 0x10FF00;
 
409
                cstrbuf[1] = 0;
 
410
                *len = 1;
 
411
            } else {
 
412
                cstrbuf[0] = 0xF0 + (s / 0x40000);
 
413
                cstrbuf[1] = 0x80 + ((s % 0x40000) / 0x1000);
 
414
                cstrbuf[2] = 0x80 + (((s % 0x40000) % 0x1000) / 0x40);
 
415
                cstrbuf[3] = 0x80 + (((s % 0x40000) % 0x1000) % 0x40);
 
416
                cstrbuf[4] = 0;
 
417
                *len = 4;
 
418
            }
 
419
        }
402
420
    }
403
421
    return cstrbuf;
404
422
}
405
423
 
406
 
void set_job_id (int year, int month, int day, int time)
 
424
void set_job_id(int year, int month, int day, int time)
407
425
{
408
426
    char *name_string, *format_string, *s;
409
427
    size_t slen;
410
 
        int i;
 
428
    int i;
411
429
 
412
430
    if (job_id_string != NULL)
413
431
        return;
414
432
 
415
 
    name_string = xstrdup (makecstring (job_name));
416
 
    format_string = xstrdup (makecstring (format_ident));
 
433
    name_string = xstrdup(makecstring(job_name));
 
434
    format_string = xstrdup(makecstring(format_ident));
417
435
    slen = SMALL_BUF_SIZE +
418
 
        strlen (name_string) +
419
 
        strlen (format_string) +
420
 
        strlen (ptexbanner) +
421
 
        strlen (versionstring) + strlen (kpathsea_version_string);
422
 
    s = xtalloc (slen, char);
 
436
        strlen(name_string) +
 
437
        strlen(format_string) +
 
438
        strlen(ptexbanner) +
 
439
        strlen(versionstring) + strlen(kpathsea_version_string);
 
440
    s = xtalloc(slen, char);
423
441
    /* The Web2c version string starts with a space.  */
424
 
    i = snprintf (s, slen,
425
 
             "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s%s %s",
426
 
             year, month, day, time / 60, time % 60,
427
 
             name_string, format_string, ptexbanner,
428
 
             versionstring, kpathsea_version_string);
429
 
        check_nprintf(i,slen);
430
 
    job_id_string = xstrdup (s);
431
 
    xfree (s);
432
 
    xfree (name_string);
433
 
    xfree (format_string);
434
 
}
435
 
 
436
 
int get_build_revision (void) {
437
 
  int revision;
438
 
  if(sscanf (BUILD_REVISION,"$Revision: %d $", &revision)) {
439
 
        return revision;
440
 
  }
441
 
  return 0;
442
 
}
443
 
 
444
 
void make_pdftex_banner (void)
 
442
    i = snprintf(s, slen,
 
443
                 "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s%s %s",
 
444
                 year, month, day, time / 60, time % 60,
 
445
                 name_string, format_string, ptexbanner,
 
446
                 versionstring, kpathsea_version_string);
 
447
    check_nprintf(i, slen);
 
448
    job_id_string = xstrdup(s);
 
449
    xfree(s);
 
450
    xfree(name_string);
 
451
    xfree(format_string);
 
452
}
 
453
 
 
454
void make_pdftex_banner(void)
445
455
{
446
456
    static boolean pdftexbanner_init = false;
447
457
    char *s;
448
458
    size_t slen;
449
 
        int i;
 
459
    int i;
450
460
 
451
461
    if (pdftexbanner_init)
452
462
        return;
453
463
 
454
464
    slen = SMALL_BUF_SIZE +
455
 
        strlen (ptexbanner) +
456
 
        strlen (versionstring) + strlen (kpathsea_version_string);
457
 
    s = xtalloc (slen, char);
 
465
        strlen(ptexbanner) +
 
466
        strlen(versionstring) + strlen(kpathsea_version_string);
 
467
    s = xtalloc(slen, char);
458
468
    /* The Web2c version string starts with a space.  */
459
 
    i = snprintf (s, slen,
460
 
             "%s%s %s", ptexbanner, versionstring, kpathsea_version_string);
461
 
        check_nprintf (i, slen);
462
 
    pdftex_banner = maketexstring (s);
463
 
    xfree (s);
 
469
    i = snprintf(s, slen,
 
470
                 "%s%s %s", ptexbanner, versionstring, kpathsea_version_string);
 
471
    check_nprintf(i, slen);
 
472
    pdftex_banner = maketexstring(s);
 
473
    xfree(s);
464
474
    pdftexbanner_init = true;
465
475
}
466
476
 
467
 
strnumber get_resname_prefix (void)
 
477
strnumber get_resname_prefix(void)
468
478
{
469
479
/*     static char name_str[] = */
470
480
/* "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\" */
474
484
    char prefix[7];             /* make a tag of 6 chars long */
475
485
    unsigned long crc;
476
486
    short i;
477
 
    size_t base = strlen (name_str);
478
 
    crc = crc32 (0L, Z_NULL, 0);
479
 
    crc = crc32 (crc, (Bytef *) job_id_string, strlen (job_id_string));
 
487
    size_t base = strlen(name_str);
 
488
    crc = crc32(0L, Z_NULL, 0);
 
489
    crc = crc32(crc, (Bytef *) job_id_string, strlen(job_id_string));
480
490
    for (i = 0; i < 6; i++) {
481
491
        prefix[i] = name_str[crc % base];
482
492
        crc /= base;
483
493
    }
484
494
    prefix[6] = 0;
485
 
    return maketexstring (prefix);
 
495
    return maketexstring(prefix);
486
496
}
487
497
 
488
 
size_t xfwrite (void *ptr, size_t size, size_t nmemb, FILE * stream)
 
498
size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE * stream)
489
499
{
490
 
    if (fwrite (ptr, size, nmemb, stream) != nmemb)
491
 
        pdftex_fail ("fwrite() failed");
 
500
    if (fwrite(ptr, size, nmemb, stream) != nmemb)
 
501
        pdftex_fail("fwrite() failed");
492
502
    return nmemb;
493
503
}
494
504
 
495
 
int xfflush (FILE * stream)
 
505
int xfflush(FILE * stream)
496
506
{
497
 
    if (fflush (stream) != 0)
498
 
        pdftex_fail ("fflush() failed");
 
507
    if (fflush(stream) != 0)
 
508
        pdftex_fail("fflush() failed");
499
509
    return 0;
500
510
}
501
511
 
502
 
int xgetc (FILE * stream)
 
512
int xgetc(FILE * stream)
503
513
{
504
 
    int c = getc (stream);
 
514
    int c = getc(stream);
505
515
    if (c < 0 && c != EOF)
506
 
        pdftex_fail ("getc() failed");
 
516
        pdftex_fail("getc() failed");
507
517
    return c;
508
518
}
509
519
 
510
 
int xputc (int c, FILE * stream)
 
520
int xputc(int c, FILE * stream)
511
521
{
512
 
    int i = putc (c, stream);
 
522
    int i = putc(c, stream);
513
523
    if (i < 0)
514
 
        pdftex_fail ("putc() failed");
 
524
        pdftex_fail("putc() failed");
515
525
    return i;
516
526
}
517
527
 
518
 
void write_stream_length (integer length, integer offset)
 
528
void write_stream_length(integer length, integer offset)
519
529
{
520
530
    if (jobname_cstr == NULL)
521
 
        jobname_cstr = xstrdup (makecstring (job_name));
522
 
        if (fixed_pdf_draftmode == 0) {
523
 
        xfseek (pdf_file, offset, SEEK_SET, jobname_cstr);
524
 
    fprintf (pdf_file, "%li", (long int) length);
525
 
    xfseek (pdf_file, pdfoffset (), SEEK_SET, jobname_cstr);
526
 
        }
 
531
        jobname_cstr = xstrdup(makecstring(job_name));
 
532
    if (fixed_pdf_draftmode == 0) {
 
533
        xfseek(pdf_file, offset, SEEK_SET, jobname_cstr);
 
534
        fprintf(pdf_file, "%li", (long int) length);
 
535
        xfseek(pdf_file, pdfoffset(), SEEK_SET, jobname_cstr);
 
536
    }
527
537
}
528
538
 
529
 
scaled ext_xn_over_d (scaled x, scaled n, scaled d)
 
539
scaled ext_xn_over_d(scaled x, scaled n, scaled d)
530
540
{
531
541
    double r = (((double) x) * ((double) n)) / ((double) d);
532
542
    if (r > DBL_EPSILON)
534
544
    else
535
545
        r -= 0.5;
536
546
    if (r >= (double) maxinteger || r <= -(double) maxinteger)
537
 
        pdftex_warn ("arithmetic: number too big");
 
547
        pdftex_warn("arithmetic: number too big");
538
548
    return (scaled) r;
539
549
}
540
550
 
541
 
void libpdffinish ()
 
551
void libpdffinish()
542
552
{
543
 
    xfree (fb_array);
544
 
    xfree (char_array);
545
 
    xfree (job_id_string);
546
 
    fm_free ();
547
 
    t1_free ();
548
 
    enc_free ();
549
 
    epdf_free ();
550
 
    ttf_free ();
551
 
    sfd_free ();
552
 
    glyph_unicode_free ();
553
 
        zip_free ();
 
553
    xfree(fb_array);
 
554
    xfree(char_array);
 
555
    xfree(job_id_string);
 
556
    fm_free();
 
557
    t1_free();
 
558
    enc_free();
 
559
    epdf_free();
 
560
    ttf_free();
 
561
    sfd_free();
 
562
    glyph_unicode_free();
 
563
    zip_free();
554
564
}
555
565
 
556
566
/* Converts any string given in in in an allowed PDF string which can be
559
569
 * This assumes that the string does not contain any already escaped
560
570
 * characters!
561
571
 */
562
 
char *convertStringToPDFString (const char *in, int len)
 
572
char *convertStringToPDFString(const char *in, int len)
563
573
{
564
574
    static char pstrbuf[MAX_PSTRING_LEN];
565
575
    char *out = pstrbuf;
567
577
    char buf[5];
568
578
    j = 0;
569
579
    for (i = 0; i < len; i++) {
570
 
        check_buf (j + sizeof (buf), MAX_PSTRING_LEN);
 
580
        check_buf(j + sizeof(buf), MAX_PSTRING_LEN);
571
581
        if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) {
572
582
            /* convert control characters into oct */
573
 
            k = snprintf (buf, sizeof (buf),
574
 
                     "\\%03o", (unsigned int) (unsigned char) in[i]);
575
 
                        check_nprintf (k, sizeof (buf));
 
583
            k = snprintf(buf, sizeof(buf),
 
584
                         "\\%03o", (unsigned int) (unsigned char) in[i]);
 
585
            check_nprintf(k, sizeof(buf));
576
586
            out[j++] = buf[0];
577
587
            out[j++] = buf[1];
578
588
            out[j++] = buf[2];
603
613
 *
604
614
 * See escapename for parameter description.
605
615
 */
606
 
void escapestring (poolpointer in)
 
616
void escapestring(poolpointer in)
607
617
{
608
618
    const poolpointer out = pool_ptr;
609
619
    unsigned char ch;
610
 
        int i;
 
620
    int i;
611
621
    while (in < out) {
612
622
        if (pool_ptr + 4 >= pool_size) {
613
623
            pool_ptr = pool_size;
619
629
 
620
630
        if ((ch < '!') || (ch > '~')) {
621
631
            /* convert control characters into oct */
622
 
            i = snprintf ((char *) &str_pool[pool_ptr], 5,
623
 
                     "\\%.3o", (unsigned int) ch);
624
 
                        check_nprintf (i, 5);
 
632
            i = snprintf((char *) &str_pool[pool_ptr], 5,
 
633
                         "\\%.3o", (unsigned int) ch);
 
634
            check_nprintf(i, 5);
625
635
            pool_ptr += i;
626
636
            continue;
627
637
        }
676
686
   "pool_ptr" points to the start of the output string and
677
687
   after the end when the procedure returns.
678
688
*/
679
 
void escapename (poolpointer in)
 
689
void escapename(poolpointer in)
680
690
{
681
691
    const poolpointer out = pool_ptr;
682
692
    unsigned char ch;
683
 
        int i;
 
693
    int i;
684
694
 
685
695
    while (in < out) {
686
696
        if (pool_ptr + 3 >= pool_size) {
693
703
 
694
704
        if ((ch >= 1 && ch <= 32) || ch >= 127) {
695
705
            /* escape */
696
 
            i = snprintf ((char *) &str_pool[pool_ptr], 4,
697
 
                     "#%.2X", (unsigned int) ch);
698
 
                        check_nprintf (i, 4);
 
706
            i = snprintf((char *) &str_pool[pool_ptr], 4,
 
707
                         "#%.2X", (unsigned int) ch);
 
708
            check_nprintf(i, 4);
699
709
            pool_ptr += i;
700
710
            continue;
701
711
        }
715
725
        case 123:
716
726
        case 125:
717
727
            /* escape */
718
 
            i = snprintf ((char *) &str_pool[pool_ptr], 4,
719
 
                     "#%.2X", (unsigned int) ch);
720
 
                        check_nprintf (i, 4);
 
728
            i = snprintf((char *) &str_pool[pool_ptr], 4,
 
729
                         "#%.2X", (unsigned int) ch);
 
730
            check_nprintf(i, 4);
721
731
            pool_ptr += i;
722
732
            break;
723
733
        default:
734
744
   
735
745
   See escapename for description of parameters.
736
746
*/
737
 
void escapehex (poolpointer in)
 
747
void escapehex(poolpointer in)
738
748
{
739
749
    const poolpointer out = pool_ptr;
740
750
    unsigned char ch;
741
 
        int i;
742
 
        
 
751
    int i;
 
752
 
743
753
    while (in < out) {
744
754
        if (pool_ptr + 2 >= pool_size) {
745
755
            pool_ptr = pool_size;
749
759
 
750
760
        ch = (unsigned char) str_pool[in++];
751
761
 
752
 
        i = snprintf ((char *) &str_pool[pool_ptr], 3,"%.2X", (unsigned int) ch);
753
 
                check_nprintf (i, 3);
 
762
        i = snprintf((char *) &str_pool[pool_ptr], 3, "%.2X",
 
763
                     (unsigned int) ch);
 
764
        check_nprintf(i, 3);
754
765
        pool_ptr += 2;
755
766
    }
756
767
}
764
775
 
765
776
   See escapename for description of parameters.
766
777
*/
767
 
void unescapehex (poolpointer in)
 
778
void unescapehex(poolpointer in)
768
779
{
769
780
    const poolpointer out = pool_ptr;
770
781
    unsigned char ch;
771
782
    boolean first = true;
772
 
        unsigned char a = 0;        /* to avoid warning about uninitialized use of a */
 
783
    unsigned char a = 0;        /* to avoid warning about uninitialized use of a */
773
784
    while (in < out) {
774
785
        if (pool_ptr + 1 >= pool_size) {
775
786
            pool_ptr = pool_size;
808
819
 * hexadecimal encoded;
809
820
 * sizeof(out) should be at least lin*2+1.
810
821
 */
811
 
static void convertStringToHexString (const char *in, char *out, int lin)
 
822
static void convertStringToHexString(const char *in, char *out, int lin)
812
823
{
813
 
  int i, j, k;
 
824
    int i, j, k;
814
825
    char buf[3];
815
826
    j = 0;
816
827
    for (i = 0; i < lin; i++) {
817
 
        k = snprintf (buf, sizeof (buf),
818
 
                 "%02X", (unsigned int) (unsigned char) in[i]);
819
 
                check_nprintf (k, sizeof (buf));
 
828
        k = snprintf(buf, sizeof(buf),
 
829
                     "%02X", (unsigned int) (unsigned char) in[i]);
 
830
        check_nprintf(k, sizeof(buf));
820
831
        out[j++] = buf[0];
821
832
        out[j++] = buf[1];
822
833
    }
854
865
  scanning the info dict is also difficult, we start with a simpler
855
866
  implementation using just the first two items.
856
867
 */
857
 
void print_ID (strnumber filename)
 
868
void print_ID(strnumber filename)
858
869
{
859
870
    time_t t;
860
871
    size_t size;
865
876
    char *file_name;
866
877
    char pwd[4096];
867
878
    /* start md5 */
868
 
    md5_init (&state);
 
879
    md5_init(&state);
869
880
    /* get the time */
870
 
    t = time (NULL);
871
 
    size =
872
 
        strftime (time_str, sizeof (time_str), "%Y%m%dT%H%M%SZ", gmtime (&t));
873
 
    md5_append (&state, (const md5_byte_t *) time_str, size);
 
881
    t = time(NULL);
 
882
    size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
 
883
    md5_append(&state, (const md5_byte_t *) time_str, size);
874
884
    /* get the file name */
875
 
    if (getcwd (pwd, sizeof (pwd)) == NULL)
876
 
        pdftex_fail ("getcwd() failed (path too long?)");
877
 
    file_name = makecstring (filename);
878
 
    md5_append (&state, (const md5_byte_t *) pwd, strlen (pwd));
879
 
    md5_append (&state, (const md5_byte_t *) "/", 1);
880
 
    md5_append (&state, (const md5_byte_t *) file_name, strlen (file_name));
 
885
    if (getcwd(pwd, sizeof(pwd)) == NULL)
 
886
        pdftex_fail("getcwd() failed (path too long?)");
 
887
    file_name = makecstring(filename);
 
888
    md5_append(&state, (const md5_byte_t *) pwd, strlen(pwd));
 
889
    md5_append(&state, (const md5_byte_t *) "/", 1);
 
890
    md5_append(&state, (const md5_byte_t *) file_name, strlen(file_name));
881
891
    /* finish md5 */
882
 
    md5_finish (&state, digest);
 
892
    md5_finish(&state, digest);
883
893
    /* write the IDs */
884
 
    convertStringToHexString ((char *) digest, id, 16);
885
 
    pdf_printf ("/ID [<%s> <%s>]", id, id);
 
894
    convertStringToHexString((char *) digest, id, 16);
 
895
    pdf_printf("/ID [<%s> <%s>]", id, id);
886
896
}
887
897
 
888
898
/* Print the /CreationDate entry.
938
948
static time_t start_time = 0;
939
949
#define TIME_STR_SIZE 30
940
950
static char start_time_str[TIME_STR_SIZE];
941
 
static char time_str[TIME_STR_SIZE];
942
951
    /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
943
952
 
944
 
static void makepdftime (time_t t, char *time_str)
 
953
static void makepdftime(time_t t, char *time_str)
945
954
{
946
955
 
947
956
    struct tm lt, gmt;
949
958
    int i, off, off_hours, off_mins;
950
959
 
951
960
    /* get the time */
952
 
    lt = *localtime (&t);
953
 
    size = strftime (time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
 
961
    lt = *localtime(&t);
 
962
    size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
954
963
    /* expected format: "YYYYmmddHHMMSS" */
955
964
    if (size == 0) {
956
965
        /* unexpected, contents of time_str is undefined */
968
977
    }
969
978
 
970
979
    /* get the time zone offset */
971
 
    gmt = *gmtime (&t);
 
980
    gmt = *gmtime(&t);
972
981
 
973
982
    /* this calculation method was found in exim's tod.c */
974
983
    off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
983
992
        time_str[size] = 0;
984
993
    } else {
985
994
        off_hours = off / 60;
986
 
        off_mins = abs (off - off_hours * 60);
987
 
        i = snprintf (&time_str[size], 9,
988
 
                 "%+03d'%02d'", off_hours, off_mins);
989
 
                check_nprintf (i, 9);
 
995
        off_mins = abs(off - off_hours * 60);
 
996
        i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
 
997
        check_nprintf(i, 9);
990
998
    }
991
999
}
992
1000
 
993
 
void init_start_time ()
 
1001
void init_start_time()
994
1002
{
995
1003
    if (start_time == 0) {
996
 
        start_time = time ((time_t *) NULL);
997
 
        makepdftime (start_time, start_time_str);
 
1004
        start_time = time((time_t *) NULL);
 
1005
        makepdftime(start_time, start_time_str);
998
1006
    }
999
1007
}
1000
1008
 
1001
 
void print_creation_date ()
1002
 
{
1003
 
    init_start_time ();
1004
 
    pdf_printf ("/CreationDate (%s)\n", start_time_str);
1005
 
}
1006
 
 
1007
 
void print_mod_date ()
1008
 
{
1009
 
    init_start_time ();
1010
 
    pdf_printf ("/ModDate (%s)\n", start_time_str);
1011
 
}
1012
 
 
1013
 
void getcreationdate ()
 
1009
void print_creation_date()
 
1010
{
 
1011
    init_start_time();
 
1012
    pdf_printf("/CreationDate (%s)\n", start_time_str);
 
1013
}
 
1014
 
 
1015
void print_mod_date()
 
1016
{
 
1017
    init_start_time();
 
1018
    pdf_printf("/ModDate (%s)\n", start_time_str);
 
1019
}
 
1020
 
 
1021
void getcreationdate()
1014
1022
{
1015
1023
    /* put creation date on top of string pool and update pool_ptr */
1016
 
    size_t len = strlen (start_time_str);
1017
 
 
1018
 
    init_start_time ();
1019
 
 
1020
 
    if ((unsigned)(pool_ptr + len) >= (unsigned)pool_size) {
 
1024
    size_t len = strlen(start_time_str);
 
1025
 
 
1026
    init_start_time();
 
1027
 
 
1028
    if ((unsigned) (pool_ptr + len) >= (unsigned) pool_size) {
1021
1029
        pool_ptr = pool_size;
1022
1030
        /* error by str_toks that calls str_room(1) */
1023
1031
        return;
1024
1032
    }
1025
1033
 
1026
 
    memcpy (&str_pool[pool_ptr], start_time_str, len);
 
1034
    memcpy(&str_pool[pool_ptr], start_time_str, len);
1027
1035
    pool_ptr += len;
1028
1036
}
1029
1037
 
1034
1042
    That means, file names that are legal on some operation systems
1035
1043
    cannot any more be used since pdfTeX version 1.30.4.
1036
1044
*/
1037
 
char *makecfilename (strnumber s)
 
1045
char *makecfilename(strnumber s)
1038
1046
{
1039
 
    char *name = makecstring (s);
 
1047
    char *name = makecstring(s);
1040
1048
    char *p = name;
1041
1049
    char *q = name;
1042
1050
 
1051
1059
 
1052
1060
/* function strips trailing zeros in string with numbers; */
1053
1061
/* leading zeros are not stripped (as in real life) */
1054
 
char *stripzeros (char *a)
 
1062
char *stripzeros(char *a)
1055
1063
{
1056
1064
    enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM;
1057
1065
    char *p, *q, *r;
1114
1122
        *q++ = *p++;
1115
1123
        t = s;
1116
1124
    }
1117
 
        *q = '\0';
 
1125
    *q = '\0';
1118
1126
    return a;
1119
1127
}
1120
1128
 
1121
1129
void initversionstring(char **versions)
1122
1130
{
1123
1131
    (void) asprintf(versions,
1124
 
                                        "This is build %d, created on %dT%06dZ\n"
1125
1132
                    "Compiled with libpng %s; using libpng %s\n"
1126
1133
                    "Compiled with zlib %s; using zlib %s\n"
1127
1134
                    "Compiled with xpdf version %s\n",
1128
 
                                        get_build_revision(), BUILD_DATE, (BUILD_TIME-1000000),
1129
1135
                    PNG_LIBPNG_VER_STRING, png_libpng_ver,
1130
1136
                    ZLIB_VERSION, zlib_version, xpdfVersion);
1131
1137
}
1673
1679
    matrixtransformrect(last_llx, last_lly, urx, last_ury);
1674
1680
}
1675
1681
 
1676
 
void 
1677
 
check_buffer_overflow (int wsize) {
1678
 
  int nsize;
1679
 
  if (wsize>buf_size) {
1680
 
        nsize = buf_size + buf_size/5+5;
1681
 
        if (nsize<wsize) {
1682
 
          nsize = wsize+5;
1683
 
        }
1684
 
        buffer = (unsigned char *)xreallocarray (buffer, char, nsize);
1685
 
        buf_size = nsize;
1686
 
  }
 
1682
void check_buffer_overflow(int wsize)
 
1683
{
 
1684
    int nsize;
 
1685
    if (wsize > buf_size) {
 
1686
        nsize = buf_size + buf_size / 5 + 5;
 
1687
        if (nsize < wsize) {
 
1688
            nsize = wsize + 5;
 
1689
        }
 
1690
        buffer = (unsigned char *) xreallocarray(buffer, char, nsize);
 
1691
        buf_size = nsize;
 
1692
    }
1687
1693
}
1688
1694
 
1689
1695
#define EXTRA_STRING 500
1690
1696
 
1691
 
void 
1692
 
check_pool_overflow (int wsize) {
1693
 
  int nsize ;
1694
 
  if ((wsize-1)>pool_size) {
1695
 
        nsize = pool_size + pool_size/5+EXTRA_STRING;
1696
 
        if (nsize<wsize) {
1697
 
          nsize = wsize+EXTRA_STRING;
1698
 
        }
1699
 
        str_pool = (unsigned char *)xreallocarray (str_pool, char, nsize);      
1700
 
        pool_size = nsize;
1701
 
  }
 
1697
void check_pool_overflow(int wsize)
 
1698
{
 
1699
    int nsize;
 
1700
    if ((wsize - 1) > pool_size) {
 
1701
        nsize = pool_size + pool_size / 5 + EXTRA_STRING;
 
1702
        if (nsize < wsize) {
 
1703
            nsize = wsize + EXTRA_STRING;
 
1704
        }
 
1705
        str_pool = (unsigned char *) xreallocarray(str_pool, char, nsize);
 
1706
        pool_size = nsize;
 
1707
    }
1702
1708
}
1703
1709
 
1704
1710
#define max_integer 0x7FFFFFFF
1707
1713
   |scaled_out| is the number of scaled points corresponding to that.
1708
1714
*/
1709
1715
 
1710
 
scaled divide_scaled (scaled s, scaled m, integer dd) {
1711
 
  register scaled q;
1712
 
  register scaled r;
1713
 
  int i;
1714
 
  int sign = 1;
1715
 
  if (s < 0) {
1716
 
    sign = -sign;
1717
 
    s = -s;
1718
 
  }
1719
 
  if (m < 0) {
1720
 
    sign = -sign;
1721
 
    m = -m;
1722
 
  }
1723
 
  if (m == 0) {
1724
 
    pdf_error(maketexstring("arithmetic"), maketexstring("divided by zero"));
1725
 
  } else if (m >= (max_integer / 10)) {
1726
 
    pdf_error(maketexstring("arithmetic"), maketexstring("number too big"));
1727
 
  }
1728
 
  q = s / m;
1729
 
  r = s % m;
1730
 
  for (i = 1;i<=(int)dd;i++) {
1731
 
        q = 10*q + (10*r) / m;
1732
 
        r = (10*r) % m;
1733
 
  }
1734
 
  /* rounding */
1735
 
  if (2*r >= m) {
1736
 
    q++;
1737
 
    r -= m;
1738
 
  }
1739
 
  /* set up the value of q, in scaled points */
1740
 
  switch(dd) {
1741
 
  case 0: scaled_out = sign*(s - r); break;
1742
 
  case 1: scaled_out = sign*(s - (r/10)); break;
1743
 
  case 2: scaled_out = sign*(s - (r/100)); break;
1744
 
  case 3: scaled_out = sign*(s - (r/1000)); break;
1745
 
  case 4: scaled_out = sign*(s - (r/10000)); break;
1746
 
  case 5: scaled_out = sign*(s - (r/100000)); break;
1747
 
  case 6: scaled_out = sign*(s - (r/1000000)); break;
1748
 
  case 7: scaled_out = sign*(s - (r/10000000)); break;
1749
 
  case 8: scaled_out = sign*(s - (r/100000000)); break;
1750
 
  case 9: scaled_out = sign*(s - (r/1000000000)); break;
1751
 
  }
1752
 
  return sign*q;
 
1716
scaled divide_scaled(scaled s, scaled m, integer dd)
 
1717
{
 
1718
    register scaled q;
 
1719
    register scaled r;
 
1720
    int i;
 
1721
    int sign = 1;
 
1722
    if (s < 0) {
 
1723
        sign = -sign;
 
1724
        s = -s;
 
1725
    }
 
1726
    if (m < 0) {
 
1727
        sign = -sign;
 
1728
        m = -m;
 
1729
    }
 
1730
    if (m == 0) {
 
1731
        pdf_error(maketexstring("arithmetic"),
 
1732
                  maketexstring("divided by zero"));
 
1733
    } else if (m >= (max_integer / 10)) {
 
1734
        pdf_error(maketexstring("arithmetic"), maketexstring("number too big"));
 
1735
    }
 
1736
    q = s / m;
 
1737
    r = s % m;
 
1738
    for (i = 1; i <= (int) dd; i++) {
 
1739
        q = 10 * q + (10 * r) / m;
 
1740
        r = (10 * r) % m;
 
1741
    }
 
1742
    /* rounding */
 
1743
    if (2 * r >= m) {
 
1744
        q++;
 
1745
        r -= m;
 
1746
    }
 
1747
    /* set up the value of q, in scaled points */
 
1748
/* *INDENT-OFF* */
 
1749
    switch (dd) {
 
1750
    case 0: scaled_out = sign * (s - r); break;
 
1751
    case 1: scaled_out = sign * (s - (r / 10)); break;
 
1752
    case 2: scaled_out = sign * (s - (r / 100)); break;
 
1753
    case 3: scaled_out = sign * (s - (r / 1000)); break;
 
1754
    case 4: scaled_out = sign * (s - (r / 10000)); break;
 
1755
    case 5: scaled_out = sign * (s - (r / 100000)); break;
 
1756
    case 6: scaled_out = sign * (s - (r / 1000000)); break;
 
1757
    case 7: scaled_out = sign * (s - (r / 10000000)); break;
 
1758
    case 8: scaled_out = sign * (s - (r / 100000000)); break;
 
1759
    case 9: scaled_out = sign * (s - (r / 1000000000)); break;
 
1760
    }
 
1761
/* *INDENT-ON* */
 
1762
    return sign * q;
1753
1763
}
1754
1764
 
1755
1765
 
1758
1768
 * routine is only used by the pdf backend, not for typesetting.
1759
1769
 */
1760
1770
 
1761
 
scaled 
1762
 
divide_scaled_n (double sd, double md, double n) {
1763
 
  int d = (int)(sd/md*n+0.5);
1764
 
  scaled_out = (int)(d/n*md);
1765
 
  return d;
 
1771
scaled divide_scaled_n(double sd, double md, double n)
 
1772
{
 
1773
    int d = (int) (sd / md * n + 0.5);
 
1774
    scaled_out = (int) (d / n * md);
 
1775
    return d;
1766
1776
}
1767
1777
 
1768
1778
 
1769
1779
/* C print interface */
1770
1780
 
1771
 
void tprint (char *s) {
1772
 
  while (*s) 
1773
 
    print_char(*s++); 
1774
 
}
1775
 
 
1776
 
void tprint_nl (char *s) {
1777
 
  print_nlp();
1778
 
  tprint(s);
1779
 
}
1780
 
 
1781
 
#define escape_char_code 45 /* escape character for token output */
1782
 
#define int_par(a) zeqtb[static_int_base+(a)].cint /* an integer parameter */
 
1781
void tprint(char *s)
 
1782
{
 
1783
    while (*s)
 
1784
        print_char(*s++);
 
1785
}
 
1786
 
 
1787
void tprint_nl(char *s)
 
1788
{
 
1789
    print_nlp();
 
1790
    tprint(s);
 
1791
}
 
1792
 
 
1793
#define escape_char_code 45     /* escape character for token output */
 
1794
#define int_par(a) zeqtb[static_int_base+(a)].cint      /* an integer parameter */
1783
1795
#define escape_char int_par(escape_char_code)
1784
1796
 
1785
 
void tprint_esc(char *s) { /* prints escape character, then |s| */
1786
 
  int c=-1; /* the escape character code */
1787
 
  if (zeqtb!=NULL) {
1788
 
    c=escape_char;
1789
 
    if (c>=0)
1790
 
      print_char(c);
1791
 
  }
1792
 
  tprint(s);
1793
 
}
1794
 
 
1795
 
void tconfusion(char *s) {
1796
 
  confusion(maketexstring(s));
1797
 
}
1798
 
 
 
1797
void tprint_esc(char *s)
 
1798
{                               /* prints escape character, then |s| */
 
1799
    int c = -1;                 /* the escape character code */
 
1800
    if (zeqtb != NULL) {
 
1801
        c = escape_char;
 
1802
        if (c >= 0)
 
1803
            print_char(c);
 
1804
    }
 
1805
    tprint(s);
 
1806
}
 
1807
 
 
1808
void tconfusion(char *s)
 
1809
{
 
1810
    confusion(maketexstring(s));
 
1811
}
 
1812
 
 
1813
/**********************************************************************/
 
1814
/* Page diversions */
 
1815
 
 
1816
#ifdef DEBUG
 
1817
#  define PAGES_TREE_KIDSMAX 3
 
1818
#else
 
1819
#  define PAGES_TREE_KIDSMAX 6
 
1820
#endif
 
1821
 
 
1822
static struct avl_table *divert_list_tree = NULL;
 
1823
 
 
1824
typedef struct pages_entry_ {
 
1825
    integer objnum;             /* object number of this /Pages object */
 
1826
    integer number_of_pages;    /* total number of all pages below */
 
1827
    integer number_of_kids;     /* number of direct kid objects */
 
1828
    integer kids[PAGES_TREE_KIDSMAX];   /* array of kid object numbers */
 
1829
    struct pages_entry_ *next;
 
1830
} pages_entry;
 
1831
 
 
1832
typedef struct divert_list_entry_ {
 
1833
    integer divnum;
 
1834
    pages_entry *first;
 
1835
    pages_entry *last;
 
1836
} divert_list_entry;
 
1837
 
 
1838
static int comp_divert_list_entry(const void *pa, const void *pb, void *p)
 
1839
{
 
1840
    if (((const divert_list_entry *) pa)->divnum >
 
1841
        ((const divert_list_entry *) pb)->divnum)
 
1842
        return 1;
 
1843
    if (((const divert_list_entry *) pa)->divnum <
 
1844
        ((const divert_list_entry *) pb)->divnum)
 
1845
        return -1;
 
1846
    return 0;
 
1847
}
 
1848
 
 
1849
static pages_entry *new_pages_entry()
 
1850
{
 
1851
    pages_entry *p;
 
1852
    int i;
 
1853
    p = xtalloc(1, pages_entry);
 
1854
    p->number_of_pages = p->number_of_kids = 0;
 
1855
    for (i = 0; i < PAGES_TREE_KIDSMAX; i++)
 
1856
        p->kids[i] = 0;
 
1857
    p->next = NULL;
 
1858
    pdf_create_obj(0, 0);
 
1859
    p->objnum = obj_ptr;
 
1860
    return p;
 
1861
}
 
1862
 
 
1863
static divert_list_entry *new_divert_list_entry()
 
1864
{
 
1865
    divert_list_entry *d;
 
1866
    d = xtalloc(1, divert_list_entry);
 
1867
    d->first = d->last = NULL;
 
1868
    return d;
 
1869
}
 
1870
 
 
1871
static void ensure_list_tree()
 
1872
{
 
1873
    if (divert_list_tree == NULL) {
 
1874
        divert_list_tree =
 
1875
            avl_create(comp_divert_list_entry, NULL, &avl_xallocator);
 
1876
        assert(divert_list_tree != NULL);
 
1877
    }
 
1878
}
 
1879
 
 
1880
static divert_list_entry *get_divert_list(integer divnum)
 
1881
{
 
1882
    divert_list_entry *d, tmp;
 
1883
    void **aa;
 
1884
    tmp.divnum = divnum;
 
1885
    d = (divert_list_entry *) avl_find(divert_list_tree, &tmp);
 
1886
    if (d == NULL) {
 
1887
        d = new_divert_list_entry();
 
1888
        d->divnum = divnum;
 
1889
        aa = avl_probe(divert_list_tree, d);
 
1890
        assert(aa != NULL);
 
1891
    }
 
1892
    return d;
 
1893
}
 
1894
 
 
1895
/* pdf_do_page_divert() returns the current /Parent object number */
 
1896
 
 
1897
integer pdf_do_page_divert(integer objnum, integer divnum)
 
1898
{
 
1899
    divert_list_entry *d;
 
1900
    pages_entry *p;
 
1901
#ifdef DEBUG
 
1902
    pages_entry *q;
 
1903
    struct avl_traverser t;
 
1904
    int i;
 
1905
#endif
 
1906
    // initialize the tree
 
1907
    ensure_list_tree();
 
1908
    // make sure we have a list for this diversion
 
1909
    d = get_divert_list(divnum);
 
1910
    if (d->first == NULL || d->last->number_of_kids == PAGES_TREE_KIDSMAX) {
 
1911
        // append a new pages_entry
 
1912
        p = new_pages_entry();
 
1913
        if (d->first == NULL)
 
1914
            d->first = p;
 
1915
        else
 
1916
            d->last->next = p;
 
1917
        d->last = p;
 
1918
    }
 
1919
    p = d->last;
 
1920
    p->kids[p->number_of_kids++] = objnum;
 
1921
    p->number_of_pages++;
 
1922
#ifdef DEBUG
 
1923
    printf("\n");
 
1924
    avl_t_init(&t, divert_list_tree);
 
1925
    for (d = avl_t_first(&t, divert_list_tree); d != NULL; d = avl_t_next(&t)) {
 
1926
        printf("===== D-LIST %d: ", d->divnum);
 
1927
        for (q = d->first; q != NULL; q = q->next) {
 
1928
            printf("P=%d NK=%d (", q->objnum, q->number_of_kids);
 
1929
            for (i = 0; i < q->number_of_kids; i++)
 
1930
                printf("%d ", q->kids[i]);
 
1931
            printf(") ");
 
1932
        }
 
1933
        printf("\n");
 
1934
    }
 
1935
    printf("\n");
 
1936
#endif
 
1937
    return p->objnum;
 
1938
}
 
1939
 
 
1940
static void movelist(divert_list_entry * d, divert_list_entry * dto)
 
1941
{
 
1942
    if (d != NULL && d->first != NULL && d->divnum != dto->divnum) {    /* no undivert of empty list or into self */
 
1943
        if (dto->first == NULL)
 
1944
            dto->first = d->first;
 
1945
        else
 
1946
            dto->last->next = d->first;
 
1947
        dto->last = d->last;
 
1948
        d->first = d->last = NULL;      /* one could as well remove this divert_list_entry */
 
1949
    }
 
1950
}
 
1951
 
 
1952
/* undivert from diversion <divnum> into diversion <curdivnum> */
 
1953
 
 
1954
void pdf_do_page_undivert(integer divnum, integer curdivnum)
 
1955
{
 
1956
    divert_list_entry *d, *dto, tmp;
 
1957
    struct avl_traverser t;
 
1958
#ifdef DEBUG
 
1959
    pages_entry *p;
 
1960
    int i;
 
1961
#endif
 
1962
    // initialize the tree
 
1963
    ensure_list_tree();
 
1964
    // find the diversion <curdivnum> list where diversion <divnum> should go
 
1965
    dto = get_divert_list(curdivnum);
 
1966
    if (divnum == 0) {          /* 0 = special case: undivert _all_ lists */
 
1967
        avl_t_init(&t, divert_list_tree);
 
1968
        for (d = avl_t_first(&t, divert_list_tree); d != NULL;
 
1969
             d = avl_t_next(&t))
 
1970
            movelist(d, dto);
 
1971
    } else {
 
1972
        tmp.divnum = divnum;
 
1973
        d = (divert_list_entry *) avl_find(divert_list_tree, &tmp);
 
1974
        movelist(d, dto);
 
1975
    }
 
1976
#ifdef DEBUG
 
1977
    printf("\n");
 
1978
    avl_t_init(&t, divert_list_tree);
 
1979
    for (d = avl_t_first(&t, divert_list_tree); d != NULL; d = avl_t_next(&t)) {
 
1980
        printf("===== U-LIST %d: ", d->divnum);
 
1981
        for (p = d->first; p != NULL; p = p->next) {
 
1982
            printf("P=%d NK=%d (", p->objnum, p->number_of_kids);
 
1983
            for (i = 0; i < p->number_of_kids; i++)
 
1984
                printf("%d ", p->kids[i]);
 
1985
            printf(") ");
 
1986
        }
 
1987
        printf("\n");
 
1988
    }
 
1989
    printf("\n");
 
1990
#endif
 
1991
}
 
1992
 
 
1993
/* write a /Pages object */
 
1994
 
 
1995
static void write_pages(pages_entry * p, int parent)
 
1996
{
 
1997
    int i;
 
1998
    assert(p != NULL);
 
1999
    pdf_begin_dict(p->objnum, 1);
 
2000
    pdf_printf("/Type /Pages\n");
 
2001
    if (parent == 0)            /* it's root */
 
2002
        print_pdf_pages_attr();
 
2003
    else
 
2004
        pdf_printf("/Parent %d 0 R\n", parent);
 
2005
    pdf_printf("/Count %d\n/Kids [", (int)p->number_of_pages);
 
2006
    for (i = 0; i < p->number_of_kids; i++)
 
2007
      pdf_printf("%d 0 R ", (int)p->kids[i]);
 
2008
    remove_last_space();
 
2009
    pdf_printf("]\n");
 
2010
    pdf_end_dict();
 
2011
}
 
2012
 
 
2013
/* loop over all /Pages objects, output them, create their parents,
 
2014
 * recursing bottom up, return the /Pages root object number */
 
2015
 
 
2016
static integer output_pages_list(pages_entry * pe)
 
2017
{
 
2018
    pages_entry *p, *q, *r;
 
2019
    assert(pe != NULL);
 
2020
    if (pe->next == NULL) {     /* everything fits into one pages_entry */
 
2021
        write_pages(pe, 0);     /* --> /Pages root found */
 
2022
        return pe->objnum;
 
2023
    }
 
2024
    q = r = new_pages_entry();  /* one level higher needed */
 
2025
    for (p = pe; p != NULL; p = p->next) {
 
2026
        if (q->number_of_kids == PAGES_TREE_KIDSMAX) {
 
2027
            q->next = new_pages_entry();
 
2028
            q = q->next;
 
2029
        }
 
2030
        q->kids[q->number_of_kids++] = p->objnum;
 
2031
        q->number_of_pages += p->number_of_pages;
 
2032
        write_pages(p, q->objnum);
 
2033
    }
 
2034
    return output_pages_list(r);        /* recurse through next higher level */
 
2035
}
 
2036
 
 
2037
integer output_pages_tree()
 
2038
{
 
2039
    divert_list_entry *d;
 
2040
    pdf_do_page_undivert(0, 0); /* concatenate all diversions into diversion 0 */
 
2041
    d = get_divert_list(0);     /* get diversion 0 */
 
2042
    return output_pages_list(d->first);
 
2043
}