w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

ppload.c
Go to the documentation of this file.
1 
2 #include "pplib.h"
3 
4 #ifdef _WIN32 /* --ak */
5 extern FILE *ppu8open(const char *filename, const char *mode);
6 #define fopen ppu8open
7 #endif /* _WIN32 --ak */
8 
9 const char * ppobj_kind[] = { "none", "null", "bool", "integer", "number", "name", "string", "array", "dict", "stream", "ref" };
10 
11 #define ignored_char(c) (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09 || c == 0x00)
12 #define newline_char(c) (c == 0x0A || c == 0x0D)
13 #define IGNORED_CHAR_CASE 0x20: case 0x0A: case 0x0D: case 0x09: case 0x00
14 #define NEWLINE_CHAR_CASE 0x0A: case 0x0D
15 #define DIGIT_CHAR_CASE '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
16 #define OCTAL_CHAR_CASE '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7'
17 
18 #define MAX_INT_DIGITS 32
19 
20 #define PP_LENGTH_UNKNOWN ((size_t)-1)
21 
22 static const char * ppref_str (ppuint refnumber, ppuint refversion)
23 {
24  static char buffer[MAX_INT_DIGITS + 1 + MAX_INT_DIGITS + 1 + 1 + 1];
25  sprintf(buffer, "%lu %lu R", (unsigned long)(refnumber), (unsigned long)(refversion));
26  return buffer;
27 }
28 
29 /* name */
30 
31 /*
32 pdf spec page 57:
33 "The name may include any regular characters, but not delimiter or white-space characters (see Section 3.1, “Lexical Conventions”)."
34 "The token / (a slash followed by no regular characters) is a valid name"
35 "Beginning with PDF 1.2, any character except null (character code 0) may be included in a name by writing its 2-digit hexadecimal code,
36 preceded by the number sign character (#); see implementation notes 3 and 4 in Appendix H. This syntax is required to represent any of the
37 delimiter or white-space characters or the number sign character itself; it is recommended but not required for characters whose codes
38 are outside the range 33 (!) to 126 (~)."
39 
40 This suggests we should accept bytes 128..255 as a part of the name.
41 */
42 
43 // pdf name delimiters: 0..32, ()<>[]{}/%
44 // # treated specially
45 // .+- are valid part of name; keep in mind names such as -| | |- .notdef ABCDEF+Font etc.
46 static const int8_t ppname_byte_lookup[] = {
47  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49  0, 1, 1, '#', 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0,
50  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
51  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
52  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1,
53  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
54  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1,
55  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
57  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
58  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
59  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
60  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
61  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
62  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
63 };
64 
65 /*
66 20190827: The end of the name is any byte with 0 lookup value. When reading a ref object or objstm stream containing
67 a single name, we may get input byte IOFEOF (-1), which must not be treated as 255. So a check for (c >= 0) is needed,
68 otherwise we keep writing byte 255 to the output buffer until not enough memory.
69 */
70 
71 #define ppnamebyte(c) (c >= 0 && ppname_byte_lookup[(uint8_t)(c)])
72 
73 static const int8_t pphex_byte_lookup[] = {
74  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
75  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
76  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
77  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
78  -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
79  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
80  -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
81  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
82  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
83  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
84  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
85  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
86  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
87  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
88  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
89  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
90 };
91 
92 /* no need for (c >= 0) check here */
93 
94 #define pphex(c) pphex_byte_lookup[(uint8_t)(c)]
95 
96 #define PPNAME_INIT (7 + 1)
97 
98 static ppname * ppscan_name (iof *I, ppheap *heap)
99 {
100  ppname *encoded, *decoded;
101  iof *O;
102  int decode, c;
103  uint8_t *p, *e;
104  int8_t h1, h2;
105 
106  O = ppbytes_buffer(heap, PPNAME_INIT);
107  for (decode = 0, c = iof_char(I); ppnamebyte(c); c = iof_next(I))
108  {
109  if (c == '#') decode = 1;
110  iof_put(O, c);
111  }
112  encoded = (ppname *)ppstruct_take(heap, sizeof(ppname));
113  encoded->data = ppbytes_flush(heap, O, &encoded->size);
114  if (decode)
115  {
116  O = ppbytes_buffer(heap, encoded->size); // decoded always a bit smaller
117  for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p)
118  {
119  if (*p == '#' && p + 2 < e && (h1 = pphex(p[1])) >= 0 && (h2 = pphex(p[2])) >= 0)
120  {
121  iof_set(O, ((h1 << 4)|h2));
122  p += 2;
123  }
124  else
125  iof_set(O, *p);
126  }
127  decoded = (ppname *)ppstruct_take(heap, sizeof(ppname));
128  decoded->data = ppbytes_flush(heap, O, &decoded->size);
129  encoded->flags = PPNAME_ENCODED;
130  decoded->flags = PPNAME_DECODED;
131  encoded->alterego = decoded, decoded->alterego = encoded;
132  }
133  else
134  {
135  encoded->flags = 0;
136  encoded->alterego = encoded;
137  }
138  return encoded;
139 }
140 
141 static ppname * ppscan_exec (iof *I, ppheap *heap, uint8_t firstbyte)
142 {
143  ppname *encoded, *decoded;
144  iof *O;
145  int decode, c;
146  uint8_t *p, *e;
147  int8_t h1, h2;
148 
149  O = ppbytes_buffer(heap, PPNAME_INIT);
150  iof_put(O, firstbyte);
151  for (decode = 0, c = iof_char(I); ppnamebyte(c); c = iof_next(I))
152  {
153  if (c == '#') decode = 1;
154  iof_put(O, c);
155  }
156  encoded = (ppname *)ppstruct_take(heap, sizeof(ppname));
157  encoded->data = ppbytes_flush(heap, O, &encoded->size);
158  if (decode)
159  {
160  O = ppbytes_buffer(heap, encoded->size);
161  for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p)
162  {
163  if (*p == '#' && p + 2 < e && (h1 = pphex(p[1])) >= 0 && (h2 = pphex(p[2])) >= 0)
164  {
165  iof_set(O, ((h1 << 4)|h2));
166  p += 2;
167  }
168  else
169  iof_set(O, *p);
170  }
171  decoded = (ppname *)ppstruct_take(heap, sizeof(ppname));
172  decoded->data = ppbytes_flush(heap, O, &decoded->size);
173  encoded->flags = PPNAME_EXEC|PPNAME_ENCODED;
174  decoded->flags = PPNAME_EXEC|PPNAME_DECODED;
175  encoded->alterego = decoded, decoded->alterego = encoded;
176  }
177  else
178  {
179  encoded->flags = PPNAME_EXEC;
180  encoded->alterego = encoded;
181  }
182  return encoded;
183 }
184 
185 static ppname * ppname_internal (const void *data, size_t size, int flags, ppheap *heap)
186 { // so far needed only for 'EI' operator
187  ppname *encoded;
188  encoded = (ppname *)ppstruct_take(heap, sizeof(ppname));
189  encoded->data = (ppbyte *)ppbytes_take(heap, size + 1);
190  memcpy(encoded->data, data, size);
191  encoded->data[size] = '\0';
192  encoded->size = size;
193  encoded->alterego = encoded;
194  encoded->flags = flags;
195  return encoded;
196 }
197 
198 #define ppexec_internal(data, size, heap) ppname_internal(data, size, PPNAME_EXEC, heap)
199 
201 {
202  return (name->flags & PPNAME_ENCODED) ? name->alterego : name;
203 }
204 
206 {
207  return (name->flags & PPNAME_DECODED) ? name->alterego : name;
208 }
209 
211 {
212  return (name->flags & PPNAME_ENCODED) ? name->alterego->data : name->data;
213 }
214 
216 {
217  return (name->flags & PPNAME_DECODED) ? name->alterego->data : name->data;
218 }
219 
220 /* string */
221 
222 static const int8_t ppstring_byte_escape[] = { /* -1 escaped with octal, >0 escaped with \\, 0 left intact*/
223  -1,-1,-1,-1,-1,-1,-1,-1,'b','t','n',-1,'f','r',-1,-1,
224  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
225  0, 0, 0, 0, 0, 0, 0, 0,'(',')', 0, 0, 0, 0, 0, 0,
226  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
227  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
229  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
230  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
231  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
232  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
233  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
234  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
235  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
236  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
237  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
238  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
239 };
240 
241 //// pp string
242 
243 #define PPSTRING_INIT (7 + 1)
244 
245 #define ppstring_check_bom(decoded) ((void)\
246  (decoded->size >= 2 ? (ppstring_utf16be_bom(decoded->data) ? (decoded->flags |= PPSTRING_UTF16BE) : \
247  (ppstring_utf16le_bom(decoded->data) ? (decoded->flags |= PPSTRING_UTF16LE) : 0)) : 0))
248 
249 #define ppstring_check_bom2(decoded, encoded) ((void)\
250  (decoded->size >= 2 ? (ppstring_utf16be_bom(decoded->data) ? ((decoded->flags |= PPSTRING_UTF16BE), (encoded->flags |= PPSTRING_UTF16BE)) : \
251  (ppstring_utf16le_bom(decoded->data) ? ((decoded->flags |= PPSTRING_UTF16LE), (encoded->flags |= PPSTRING_UTF16LE)) : 0)) : 0))
252 
253 #define ppstring_utf16be_bom(data) (data[0] == '\xFE' && data[1] == '\xFF')
254 #define ppstring_utf16le_bom(data) (data[0] == '\xFF' && data[1] == '\xFE')
255 
256 #define ppstringesc(c) ppstring_byte_escape[(uint8_t)(c)]
257 
258 static ppstring * ppscan_string (iof *I, ppheap *heap)
259 {
260  ppstring *encoded, *decoded;
261  iof *O;
262  int c, decode, balance;
263  uint8_t *p, *e;
264 
265  O = ppbytes_buffer(heap, PPSTRING_INIT);
266  for (decode = 0, balance = 0, c = iof_char(I); c >= 0; )
267  {
268  switch (c)
269  {
270  case '\\':
271  decode = 1;
272  iof_put(O, '\\');
273  if ((c = iof_next(I)) >= 0)
274  {
275  iof_put(O, c);
276  c = iof_next(I);
277  }
278  break;
279  case '(': // may be unescaped if balanced
280  ++balance;
281  iof_put(O, '(');
282  c = iof_next(I);
283  break;
284  case ')':
285  if (balance == 0)
286  {
287  c = IOFEOF;
288  ++I->pos;
289  break;
290  }
291  --balance;
292  iof_put(O, ')');
293  c = iof_next(I);
294  break;
295  default:
296  iof_put(O, c);
297  c = iof_next(I);
298  }
299  }
300  encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
301  encoded->data = ppbytes_flush(heap, O, &encoded->size);
302  if (decode)
303  {
304  O = ppbytes_buffer(heap, encoded->size); // decoded can only be smaller
305  for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p)
306  {
307  if (*p == '\\')
308  {
309  if (++p >= e)
310  break;
311  switch (*p)
312  {
313  case OCTAL_CHAR_CASE:
314  c = *p - '0';
315  if (++p < e && *p >= '0' && *p <= '7')
316  {
317  c = (c << 3) + *p - '0';
318  if (++p < e && *p >= '0' && *p <= '7')
319  c = (c << 3) + *p - '0';
320  }
321  iof_set(O, c);
322  break;
323  case 'n':
324  iof_set(O, '\n');
325  break;
326  case 'r':
327  iof_set(O, '\r');
328  break;
329  case 't':
330  iof_set(O, '\t');
331  break;
332  case 'b':
333  iof_set(O, '\b');
334  break;
335  case 'f':
336  iof_set(O, '\f');
337  break;
338  case NEWLINE_CHAR_CASE: // not a part of the string, ignore (pdf spec page 55)
339  break;
340  case '(': case ')': case '\\':
341  default: // for anything else backslash is ignored (pdf spec page 54)
342  iof_set(O, *p);
343  break;
344  }
345  }
346  else
347  iof_set(O, *p);
348  }
349  decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
350  decoded->data = ppbytes_flush(heap, O, &decoded->size);
351  encoded->flags = PPSTRING_ENCODED;
352  decoded->flags = PPSTRING_DECODED;
353  encoded->alterego = decoded, decoded->alterego = encoded;
354  ppstring_check_bom2(decoded, encoded);
355  }
356  else
357  {
358  encoded->flags = 0;
359  encoded->alterego = encoded;
360  ppstring_check_bom(encoded);
361  }
362  return encoded;
363 }
364 
365 static ppstring * ppscan_base16 (iof *I, ppheap *heap)
366 {
367  ppstring *encoded, *decoded;
368  iof *O;
369  int c;
370  uint8_t *p, *e;
371  int8_t h1, h2;
372 
373  O = ppbytes_buffer(heap, PPSTRING_INIT);
374  for (c = iof_char(I); (pphex(c) >= 0 || ignored_char(c)); c = iof_next(I))
375  iof_put(O, c);
376  if (c == '>')
377  ++I->pos;
378  encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
379  encoded->data = ppbytes_flush(heap, O, &encoded->size);
380 
381  O = ppbytes_buffer(heap, ((encoded->size + 1) >> 1) + 1); // decoded can only be smaller
382  for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p)
383  {
384  if ((h1 = pphex(*p)) < 0) // ignored
385  continue;
386  for (h2 = 0, ++p; p < e && (h2 = pphex(*p)) < 0; ++p);
387  iof_set(O, (h1 << 4)|h2);
388  }
389  decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
390  decoded->data = ppbytes_flush(heap, O, &decoded->size);
391 
394  encoded->alterego = decoded, decoded->alterego = encoded;
395 
396  ppstring_check_bom2(decoded, encoded);
397  return encoded;
398 }
399 
400 static ppstring * ppstring_buffer (iof *O, ppheap *heap)
401 {
402  ppstring *encoded, *decoded;
403  uint8_t *p, *e;
404 
405  decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
406  decoded->data = ppbytes_flush(heap, O, &decoded->size);
407 
408  O = ppbytes_buffer(heap, (decoded->size << 1) + 1); // the exact size known
409  for (p = (uint8_t *)decoded->data, e = p + decoded->size; p < e; ++p)
410  iof_set2(O, base16_uc_alphabet[(*p) >> 4], base16_uc_alphabet[(*p) & 0xF]);
411  encoded = ppstruct_take(heap, sizeof(ppstring));
412  encoded->data = ppbytes_flush(heap, O, &encoded->size);
415  encoded->alterego = decoded, decoded->alterego = encoded;
416  // ppstring_check_bom2(decoded, encoded); // ?
417  return encoded;
418 }
419 
420 ppstring * ppstring_internal (const void *data, size_t size, ppheap *heap)
421 { // so far used only for crypt key
422  iof *O;
423  O = ppbytes_buffer(heap, size);
424  memcpy(O->buf, data, size);
425  O->pos = O->buf + size;
426  return ppstring_buffer(O, heap);
427 }
428 
429 /* base85; local function for that to make that part independent from utilbasexx */
430 
431 static const int8_t ppstring_base85_lookup[] = {
432  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
433  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
434  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
435  15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
436  31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,
437  47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,
438  63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,
439  79,80,81,82,83,84,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
440  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
441  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
442  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
443  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
444  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
445  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
446  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
447  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
448 };
449 
450 #define base85_value(c) ppstring_base85_lookup[(uint8_t)(c)]
451 
452 #define base85_code(c1, c2, c3, c4, c5) ((((c1 * 85 + c2) * 85 + c3) * 85 + c4) * 85 + c5)
453 #define base85_eof(c) (c == '~' || c < 0)
454 
456 {
457  int c1, c2, c3, c4, c5;
458  uint32_t code;
459  while (iof_ensure(O, 4))
460  {
461  do { c1 = iof_get(I); } while (ignored_char(c1));
462  if (base85_eof(c1))
463  return IOFEOF;
464  switch (c1)
465  {
466  case 'z':
467  iof_set4(O, '\0', '\0', '\0', '\0');
468  continue;
469  case 'y':
470  iof_set4(O, ' ', ' ', ' ', ' ');
471  continue;
472  }
473  do { c2 = iof_get(I); } while (ignored_char(c2));
474  if (base85_eof(c2))
475  return IOFERR;
476  do { c3 = iof_get(I); } while (ignored_char(c3));
477  if (base85_eof(c3))
478  {
479  if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0)
480  return IOFERR;
481  code = base85_code(c1, c2, 84, 84, 84); /* padding with 'u' (117); 117-33 = 84 */
482  iof_set(O, (code >> 24));
483  return IOFEOF;
484  }
485  do { c4 = iof_get(I); } while (ignored_char(c4));
486  if (base85_eof(c4))
487  {
488  if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0)
489  return IOFERR;
490  code = base85_code(c1, c2, c3, 84, 84);
491  iof_set2(O, code>>24, ((code>>16) & 0xff));
492  return IOFEOF;
493  }
494  do { c5 = iof_get(I); } while (ignored_char(c5));
495  if (base85_eof(c5))
496  {
497  if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 ||
498  (c3 = base85_value(c3)) < 0 || (c4 = base85_value(c4)) < 0)
499  return IOFERR;
500  code = base85_code(c1, c2, c3, c4, 84);
501  iof_set3(O, (code >> 24), ((code >> 16) & 0xff), ((code >> 8) & 0xff));
502  return IOFEOF;
503  }
504  if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0 ||
505  (c4 = base85_value(c4)) < 0 || (c5 = base85_value(c5)) < 0)
506  return IOFERR;
507  code = base85_code(c1, c2, c3, c4, c5);
508  iof_set4(O, (code >> 24), ((code >> 16) & 0xff), ((code >> 8) & 0xff), (code & 0xff));
509  }
510  return IOFFULL;
511 }
512 
513 static ppstring * ppscan_base85 (iof *I, ppheap *heap)
514 { // base85 alphabet is 33..117, adobe also hires 'z' and 'y' for compression
515  ppstring *encoded, *decoded;
516  iof *O, B;
517  int c;
518 
519  O = ppbytes_buffer(heap, PPSTRING_INIT);
520  for (c = iof_char(I); (c >= '!' && c <= 'u') || c == 'z' || c == 'y'; c = iof_next(I))
521  iof_put(O, c);
522  if (c == '~')
523  if ((c = iof_next(I)) == '>')
524  ++I->pos;
525  encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
526  encoded->data = ppbytes_flush(heap, O, &encoded->size);
527 
528  iof_string_reader(&B, encoded->data, encoded->size);
529  O = ppbytes_buffer(heap, (encoded->size * 5 / 4) + 1); // may be larger that that because of 'z' and 'y'
531  decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
532  decoded->data = ppbytes_flush(heap, O, &decoded->size);
533 
536  encoded->alterego = decoded, decoded->alterego = encoded;
537 
538  ppstring_check_bom2(decoded, encoded);
539  return encoded;
540 }
541 
543 {
544  return (string->flags & PPSTRING_ENCODED) ? string->alterego : string;
545 }
546 
548 {
549  return (string->flags & PPSTRING_DECODED) ? string->alterego : string;
550 }
551 
553 {
554  return (string->flags & PPSTRING_ENCODED) ? string->alterego->data : string->data;
555 }
556 
558 {
559  return (string->flags & PPSTRING_DECODED) ? string->alterego->data : string->data;
560 }
561 
562 
563 /* encrypted string */
564 
566 {
567  ppstring *encoded, *decoded;
568  iof *O;
569  int c, b, balance, encode;
570  uint8_t *p, *e;
571  size_t size;
572 
573  O = ppbytes_buffer(heap, PPSTRING_INIT);
574  for (balance = 0, encode = 0, c = iof_char(I); c >= 0; )
575  {
576  switch (c)
577  {
578  case '\\':
579  if ((c = iof_next(I)) < 0)
580  break;
581  encode = 1;
582  switch (c)
583  {
584  case OCTAL_CHAR_CASE:
585  b = c - '0';
586  if ((c = iof_next(I)) >= 0 && c >= '0' && c <= '7')
587  {
588  b = (b << 3) + c - '0';
589  if ((c = iof_next(I)) >= 0 && c >= '0' && c <= '7')
590  {
591  b = (b << 3) + c - '0';
592  c = iof_next(I);
593  }
594  }
595  iof_put(O, b);
596  // c is set to the next char
597  break;
598  case 'n':
599  iof_put(O, '\n');
600  c = iof_next(I);
601  break;
602  case 'r':
603  iof_put(O, '\r');
604  c = iof_next(I);
605  break;
606  case 't':
607  iof_put(O, '\t');
608  c = iof_next(I);
609  break;
610  case 'b':
611  iof_put(O, '\b');
612  c = iof_next(I);
613  break;
614  case 'f':
615  iof_put(O, '\f');
616  c = iof_next(I);
617  break;
618  case NEWLINE_CHAR_CASE: // not a part of the string, ignore (pdf spec page 55)
619  c = iof_next(I);
620  break;
621  case '(': case ')': case '\\':
622  default: // for enything else backslash is ignored (pdf spec page 54)
623  iof_put(O, c);
624  c = iof_next(I);
625  break;
626  }
627  break;
628  case '(':
629  ++balance;
630  encode = 1;
631  iof_put(O, '(');
632  c = iof_next(I);
633  break;
634  case ')':
635  if (balance == 0)
636  {
637  c = IOFEOF;
638  ++I->pos;
639  }
640  else
641  {
642  --balance;
643  //encode = 1;
644  iof_put(O, ')');
645  c = iof_next(I);
646  }
647  break;
648  default:
649  if (ppstringesc(c) != 0)
650  encode = 1;
651  iof_put(O, c);
652  c = iof_next(I);
653  }
654  }
655  /* decrypt the buffer in place, update size */
656  if (ppstring_decrypt(crypt, O->buf, iof_size(O), O->buf, &size))
657  O->pos = O->buf + size;
658  decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
659  decoded->data = ppbytes_flush(heap, O, &decoded->size);
660  /* make encoded counterpart */
661  if (encode)
662  {
663  O = ppbytes_buffer(heap, decoded->size + 1); // we don't know
664  for (p = (uint8_t *)decoded->data, e = p + decoded->size; p < e; ++p)
665  {
666  b = ppstringesc(*p);
667  switch (b)
668  {
669  case 0:
670  iof_put(O, *p);
671  break;
672  case -1:
673  iof_put4(O, '\\', ((*p) >> 6) + '0', (((*p) >> 3) & 7) + '0', ((*p) & 7) + '0');
674  break;
675  default:
676  iof_put2(O, '\\', b);
677  break;
678  }
679  }
680  encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
681  encoded->data = ppbytes_flush(heap, O, &encoded->size);
682  encoded->flags = PPSTRING_ENCODED;
683  decoded->flags = PPSTRING_DECODED;
684  encoded->alterego = decoded, decoded->alterego = encoded;
685  ppstring_check_bom2(decoded, encoded);
686  }
687  else
688  {
689  decoded->flags = 0;
690  decoded->alterego = decoded;
691  ppstring_check_bom(decoded);
692  encoded = decoded;
693  }
694  return encoded;
695 }
696 
698 {
699  ppstring *encoded, *decoded;
700  iof *O;
701  int c;
702  uint8_t *p, *e;
703  int8_t h1, h2;
704  size_t size;
705 
706  O = ppbytes_buffer(heap, PPSTRING_INIT);
707  for (c = iof_char(I); c != '>'; )
708  {
709  if ((h1 = pphex(c)) < 0)
710  {
711  if (ignored_char(c))
712  {
713  c = iof_next(I);
714  continue;
715  }
716  break;
717  }
718  do {
719  c = iof_next(I);
720  if ((h2 = pphex(c)) >= 0)
721  {
722  c = iof_next(I);
723  break;
724  }
725  if (!ignored_char(c)) // c == '>' || c < 0 or some crap
726  {
727  h2 = 0;
728  break;
729  }
730  } while (1);
731  iof_put(O, (h1 << 4)|h2);
732  }
733  if (c == '>')
734  ++I->pos;
735  /* decrypt the buffer in place, update size */
736  if (ppstring_decrypt(crypt, O->buf, iof_size(O), O->buf, &size))
737  O->pos = O->buf + size;
738  decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
739  decoded->data = ppbytes_flush(heap, O, &decoded->size);
740 
741  O = ppbytes_buffer(heap, (decoded->size << 1) + 1);
742  for (p = (uint8_t *)decoded->data, e = p + decoded->size; p < e; ++p)
743  iof_set2(O, base16_uc_alphabet[(*p) >> 4], base16_uc_alphabet[(*p) & 0xF]);
744  encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring));
745  encoded->data = ppbytes_flush(heap, O, &encoded->size);
746 
749  encoded->alterego = decoded, decoded->alterego = encoded;
750 
751  ppstring_check_bom2(decoded, encoded);
752  return encoded;
753 }
754 
755 /* scanner stack */
756 
757 #define PPSTACK_BUFFER 512
758 
759 static void ppstack_init (ppstack *stack, ppheap *heap)
760 {
761  stack->buf = stack->pos = (ppobj *)pp_malloc(PPSTACK_BUFFER * sizeof(ppobj));
762  stack->size = 0;
763  stack->space = PPSTACK_BUFFER;
764  stack->heap = heap;
765 }
766 
767 #define ppstack_free_buffer(stack) (pp_free((stack)->buf))
768 
770 {
771  ppobj *newbuffer;
772  stack->space <<= 1;
773  newbuffer = (ppobj *)pp_malloc(stack->space * sizeof(ppobj));
774  memcpy(newbuffer, stack->buf, stack->size * sizeof(ppobj));
776  stack->buf = newbuffer;
777  stack->pos = newbuffer + stack->size;
778 }
779 
780 #define ppstack_push(stack) ((void)((stack)->size < (stack)->space || (ppstack_resize(stack), 0)), ++(stack)->size, (stack)->pos++)
781 #define ppstack_pop(stack, n) ((stack)->size -= (n), (stack)->pos -= (n))
782 #define ppstack_at(stack, i) ((stack)->buf + i)
783 #define ppstack_clear(stack) ((stack)->pos = (stack)->buf, (stack)->size = 0)
784 
785 /* scanner commons */
786 
787 #define ppscan_uint(I, u) iof_get_usize(I, u)
788 #define ppread_uint(s, u) string_to_usize((const char *)(s), u)
789 
790 static ppobj * ppscan_numobj (iof *I, ppobj *obj, int negative)
791 {
792  ppint integer;
793  ppnum number;
794  int exponent;
795  int c;
796  c = iof_char(I);
798  switch(c)
799  {
800  case '.':
801  {
802  number = (ppnum)integer;
803  c = iof_next(I);
804  iof_scan_fraction(I, c, number, exponent);
805  double_negative_exp10(number, exponent);
806  obj->type = PPNUM, obj->number = negative ? -number : number;
807  break;
808  }
809  default:
810  obj->type = PPINT, obj->integer = negative ? -integer : integer;
811  break;
812  }
813  return obj;
814 }
815 
816 static ppobj * ppscan_numobj_frac (iof *I, ppobj *obj, int negative)
817 {
818  ppnum number;
819  int c, exponent;
820 
821  number = 0.0;
822  c = iof_next(I);
823  iof_scan_fraction(I, c, number, exponent);
824  double_negative_exp10(number, exponent);
825  obj->type = PPNUM, obj->number = negative ? -number : number;
826  return obj;
827 }
828 
829 static int ppscan_find (iof *I)
830 { // skips whitechars and comments
831  int c;
832  for (c = iof_char(I); ; c = iof_next(I))
833  {
834  switch (c)
835  {
836  case IGNORED_CHAR_CASE:
837  break;
838  case '%': {
839  do {
840  if ((c = iof_next(I)) < 0)
841  return c;
842  } while (!newline_char(c));
843  break;
844  }
845  default:
846  return c;
847  }
848  }
849  return c; // never reached
850 }
851 
852 static int ppscan_keyword (iof *I, const char *keyword, size_t size)
853 {
854  size_t i;
855  int c;
856  if ((size_t)iof_left(I) >= size)
857  {
858  if (memcmp(I->pos, keyword, size) != 0)
859  return 0;
860  I->pos += size;
861  return 1;
862  }
863  // sticky case, we can't go back
864  for (i = 0, c = iof_char(I); i < size; ++i, ++keyword, c = iof_next(I))
865  if (c < 0 || *keyword != c) /* PJ20190503 bugfix: there was (i!=c), we actually never get here anyway */
866  return 0;
867  return 1;
868 }
869 
870 #define ppscan_key(I, literal) ppscan_keyword(I, "" literal, sizeof(literal) - 1)
871 
872 /* objects parser */
873 
874 static ppref * ppref_unresolved (ppheap *heap, ppuint refnumber, ppuint refversion)
875 {
876  ppref *ref = (ppref *)ppstruct_take(heap, sizeof(ppref));
877  memset(ref, 0, sizeof(ppref));
878  ref->object.type = PPNONE;
879  ref->number = refnumber;
880  ref->version = refversion;
881  return ref;
882 }
883 
884 #define PPMARK PPNONE
885 
887 {
888  int c;
889  ppobj *obj;
890  size_t mark, size;
891  ppuint refnumber, refversion;
892  ppref *ref;
893  ppstack *stack;
894  ppcrypt *crypt;
895 
896  stack = &pdf->stack;
897  c = iof_char(I);
898  switch (c)
899  {
900  case DIGIT_CHAR_CASE:
901  return ppscan_numobj(I, ppstack_push(stack), 0);
902  case '.':
903  return ppscan_numobj_frac(I, ppstack_push(stack), 0);
904  case '+':
905  ++I->pos;
906  return ppscan_numobj(I, ppstack_push(stack), 0);
907  case '-':
908  ++I->pos;
909  return ppscan_numobj(I, ppstack_push(stack), 1);
910  case '/':
911  ++I->pos;
912  obj = ppstack_push(stack);
913  obj->type = PPNAME;
914  obj->name = ppscan_name(I, &pdf->heap);
915  return obj;
916  case '(':
917  ++I->pos;
918  obj = ppstack_push(stack);
919  obj->type = PPSTRING;
920  if (ppcrypt_ref(pdf, crypt))
921  obj->string = ppscan_crypt_string(I, crypt, &pdf->heap);
922  else
923  obj->string = ppscan_string(I, &pdf->heap);
924  return obj;
925  case '[':
926  mark = stack->size;
927  obj = ppstack_push(stack);
928  obj->type = PPMARK; // ppscan_obj() checks types backward for 'R', so set the type immediatelly (reserved for PPARRAY)
929  obj->any = NULL;
930  ++I->pos;
931  for (c = ppscan_find(I); c != ']'; c = ppscan_find(I))
932  {
933  if (ppscan_obj(I, pdf, xref) == NULL)
934  { // callers assume that NULL returns means nothing pushed
935  size = stack->size - mark; // pop items AND the obj reserved for array
937  return NULL;
938  }
939  }
940  ++I->pos;
941  size = stack->size - mark - 1;
942  obj = ppstack_at(stack, mark); // stack might have been realocated
943  obj->type = PPARRAY;
944  obj->array = pparray_create(ppstack_at(stack, mark + 1), size, &pdf->heap);
945  ppstack_pop(stack, size); // pop array items, leave the array on top
946  return obj;
947  case '<':
948  if ((c = iof_next(I)) == '<')
949  {
950  mark = stack->size;
951  obj = ppstack_push(stack);
952  obj->type = PPMARK;
953  obj->any = NULL;
954  ++I->pos;
955  for (c = ppscan_find(I); c != '>'; c = ppscan_find(I))
956  {
957  if (ppscan_obj(I, pdf, xref) == NULL)
958  {
959  size = stack->size - mark;
961  return NULL;
962  }
963  }
964  if (iof_next(I) == '>')
965  ++I->pos;
966  size = stack->size - mark - 1;
967  obj = ppstack_at(stack, mark);
968  obj->type = PPDICT;
969  obj->dict = ppdict_create(ppstack_at(stack, mark + 1), size, &pdf->heap);
971  return obj;
972  }
973  obj = ppstack_push(stack);
974  obj->type = PPSTRING;
975  if (ppcrypt_ref(pdf, crypt))
976  obj->string = ppscan_crypt_base16(I, crypt, &pdf->heap);
977  else
978  obj->string = ppscan_base16(I, &pdf->heap);
979  return obj;
980  case 'R':
981  if (stack->size >= 2 && stack->pos[-1].type == PPINT && stack->pos[-2].type == PPINT)
982  {
983  ++I->pos;
984  obj = &stack->pos[-2];
985  refnumber = (ppuint)obj->integer;
986  ppstack_pop(stack, 1); // pop version number, retype obj to a reference
987  if (xref == NULL || (ref = ppxref_find(xref, refnumber)) == NULL)
988  { /* pdf spec page 64: unresolvable reference is not an error, should just be treated as a reference to null.
989  we also need this to read trailer, where refs can't be resolved yet */
990  refversion = (obj + 1)->integer;
991  //if (xref != NULL)
992  // loggerf("unresolved reference %s", ppref_str(refnumber, refversion));
993  ref = ppref_unresolved(stack->heap, refnumber, refversion);
994  }
995  obj->type = PPREF;
996  obj->ref = ref;
997  return obj;
998  }
999  break;
1000  case 't':
1001  if (iof_next(I) == 'r' && iof_next(I) == 'u' && iof_next(I) == 'e')
1002  {
1003  ++I->pos;
1004  obj = ppstack_push(stack);
1005  obj->type = PPBOOL;
1006  obj->integer = 1;
1007  return obj;
1008  }
1009  break;
1010  case 'f':
1011  if (iof_next(I) == 'a' && iof_next(I) == 'l' && iof_next(I) == 's' && iof_next(I) == 'e')
1012  {
1013  ++I->pos;
1014  obj = ppstack_push(stack);
1015  obj->type = PPBOOL;
1016  obj->integer = 0;
1017  return obj;
1018  }
1019  break;
1020  case 'n':
1021  if (iof_next(I) == 'u' && iof_next(I) == 'l' && iof_next(I) == 'l')
1022  {
1023  ++I->pos;
1024  obj = ppstack_push(stack);
1025  obj->type = PPNULL;
1026  obj->any = NULL;
1027  return obj;
1028  }
1029  break;
1030  }
1031  return NULL;
1032 }
1033 
1034 /*
1035 A variant for contents streams (aka postscript); wise of operators, blind to references.
1036 We are still PDF, so we don't care about postscript specific stuff such as radix numbers
1037 and scientific numbers notation. It takes ppstack * as context (no ppdoc *) to be able
1038 to run contents parser beyond the scope of ppdoc heap.
1039 */
1040 
1041 static ppstring * ppstring_inline (iof *I, ppdict *imagedict, ppheap *heap);
1042 
1044 {
1045  int c;
1046  ppobj *obj, *op;
1047  size_t size, mark;
1048  ppname *exec;
1049  ppbyte *data;
1050 
1051  c = iof_char(I);
1052  switch (c)
1053  {
1054  case DIGIT_CHAR_CASE:
1055  return ppscan_numobj(I, ppstack_push(stack), 0);
1056  case '.':
1057  return ppscan_numobj_frac(I, ppstack_push(stack), 0);
1058  case '+':
1059  c = iof_next(I);
1060  if (base10_digit(c)) // '+.abc' is probably an executable name, but we are not in postscript
1061  return ppscan_numobj(I, ppstack_push(stack), 0);
1062  else if (c == '.')
1063  return ppscan_numobj_frac(I, ppstack_push(stack), 0);
1064  obj = ppstack_push(stack);
1065  obj->type = PPNAME;
1066  obj->name = ppscan_exec(I, stack->heap, '+');
1067  return obj;
1068  case '-':
1069  c = iof_next(I);
1070  if (base10_digit(c)) // ditto, we would handle type1 '-|' '|-' operators though
1071  return ppscan_numobj(I, ppstack_push(stack), 1);
1072  else if (c == '.')
1073  return ppscan_numobj_frac(I, ppstack_push(stack), 1);
1074  obj = ppstack_push(stack);
1075  obj->type = PPNAME;
1076  obj->name = ppscan_exec(I, stack->heap, '-');
1077  return obj;
1078  case '/':
1079  ++I->pos;
1080  obj = ppstack_push(stack);
1081  obj->type = PPNAME;
1082  obj->name = ppscan_name(I, stack->heap);
1083  return obj;
1084  case '(':
1085  ++I->pos;
1086  obj = ppstack_push(stack);
1087  obj->type = PPSTRING;
1088  obj->string = ppscan_string(I, stack->heap);
1089  return obj;
1090  case '[':
1091  mark = stack->size;
1092  obj = ppstack_push(stack);
1093  obj->type = PPMARK;
1094  obj->any = NULL;
1095  ++I->pos;
1096  for (c = ppscan_find(I); c != ']'; c = ppscan_find(I))
1097  {
1098  if (ppscan_psobj(I, stack) == NULL)
1099  {
1100  size = stack->size - mark;
1102  return NULL;
1103  }
1104  }
1105  ++I->pos;
1106  size = stack->size - mark - 1;
1107  obj = ppstack_at(stack, mark);
1108  obj->type = PPARRAY;
1109  obj->array = pparray_create(ppstack_at(stack, mark + 1), size, stack->heap);
1111  return obj;
1112  case '<':
1113  if ((c = iof_next(I)) == '<')
1114  {
1115  mark = stack->size;
1116  obj = ppstack_push(stack);
1117  obj->type = PPMARK;
1118  obj->any = NULL;
1119  ++I->pos;
1120  for (c = ppscan_find(I); c != '>'; c = ppscan_find(I))
1121  {
1122  if (ppscan_psobj(I, stack) == NULL)
1123  {
1124  size = stack->size - mark;
1126  return NULL;
1127  }
1128  }
1129  if (iof_next(I) == '>')
1130  ++I->pos;
1131  size = stack->size - mark - 1;
1132  obj = ppstack_at(stack, mark);
1133  obj->type = PPDICT;
1134  obj->dict = ppdict_create(ppstack_at(stack, mark + 1), size, stack->heap);
1136  return obj;
1137  }
1138  obj = ppstack_push(stack);
1139  obj->type = PPSTRING;
1140  if (c == '~')
1141  ++I->pos, obj->string = ppscan_base85(I, stack->heap);
1142  else
1143  obj->string = ppscan_base16(I, stack->heap);
1144  return obj;
1145  default:
1146  if (!ppnamebyte(c))
1147  break; // forbid empty names; dead loop otherwise
1148  ++I->pos;
1149  /* true false null practically don't occur in streams so it makes sense to assume that we get an operator name here.
1150  If it happen to be a keyword we could give back those several bytes to the heap but.. heap buffer is tricky enough. */
1151  exec = ppscan_exec(I, stack->heap, (uint8_t)c);
1152  data = exec->data;
1153  obj = ppstack_push(stack);
1154  switch (data[0])
1155  {
1156  case 't':
1157  if (data[1] == 'r' && data[2] == 'u' && data[3] == 'e' && data[4] == '\0')
1158  {
1159  obj->type = PPBOOL;
1160  obj->integer = 1;
1161  return obj;
1162  }
1163  break;
1164  case 'f':
1165  if (data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e' && data[5] == '\0')
1166  {
1167  obj->type = PPBOOL;
1168  obj->integer = 0;
1169  return obj;
1170  }
1171  break;
1172  case 'n':
1173  if (data[1] == 'u' && data[2] == 'l' && data[3] == 'l' && data[4] == '\0')
1174  {
1175  obj->type = PPNULL;
1176  obj->any = NULL;
1177  return obj;
1178  }
1179  break;
1180  case 'B':
1181  /*
1182  Inline images break rules of operand/operator syntax, so 'BI/ID' operators need to be treated as special syntactic keywords.
1183 
1184  BI <keyval pairs> ID<whitechar?><imagedata><whitechar?>EI
1185 
1186  We treat the image as a single syntactic token; BI starts collecting a dict, ID is the beginning of the data. Effectively EI
1187  operator obtains two operands - dict and string. It is ok to put three items onto the stack, callers dont't assume there is just one.
1188  */
1189  if (data[1] == 'I' && data[2] == '\0')
1190  {
1191  ppdict *imagedict;
1192  ppname *name;
1193  /* key val pairs -> dict */
1194  mark = stack->size - 1;
1195  obj->type = PPMARK;
1196  obj->any = NULL;
1197  for (c = ppscan_find(I); ; c = ppscan_find(I))
1198  {
1199  if ((op = ppscan_psobj(I, stack)) == NULL)
1200  {
1201  size = stack->size - mark;
1203  return NULL;
1204  }
1205  if (op->type == PPNAME)
1206  {
1207  name = op->name;
1208  if (name->flags & PPNAME_EXEC)
1209  {
1210  if (name->size != 2 || name->data[0] != 'I' || name->data[1] != 'D')
1211  { // weird
1212  size = stack->size - mark;
1214  return NULL;
1215  }
1216  break;
1217  }
1218  }
1219  }
1220  size = stack->size - mark - 1;
1221  obj = ppstack_at(stack, mark);
1222  obj->type = PPDICT;
1223  obj->dict = imagedict = ppdict_create(ppstack_at(stack, mark + 1), size, stack->heap);
1225  /* put image data string */
1226  obj = ppstack_push(stack);
1227  obj->type = PPSTRING;
1228  obj->string = ppstring_inline(I, imagedict, stack->heap);;
1229  /* put EI operator name */
1230  obj = ppstack_push(stack);
1231  obj->type = PPNAME;
1232  obj->name = ppexec_internal("EI", 2, stack->heap);
1233  return obj;
1234  }
1235  break;
1236  }
1237  obj->type = PPNAME;
1238  obj->name = exec;
1239  return obj;
1240  }
1241  return NULL;
1242 }
1243 
1244 /*
1245 We try to get the exact inline image length from its dict params. If cannot predict the length, we have to scan the input until 'EI'.
1246 I've checked on may examples that it gives the same results but one can never be sure, as 'EI' might happen to be a part of the data.
1247 Stripping white char is also very heuristic; \0 is a white char in PDF and very likely to be a data byte.. weak method (pdf spec page 352).
1248 
1249 Revision 20190327: inline images may be compressed, in which case we can't predict the length.
1250 */
1251 
1252 static size_t inline_image_length (ppdict *dict)
1253 {
1254  ppuint w, h, bpc, colors;
1255  ppname *cs;
1256 
1257  if (ppdict_get_name(dict, "F") == NULL)
1258  {
1259  if (ppdict_get_uint(dict, "W", &w) && ppdict_get_uint(dict, "H", &h) && ppdict_get_uint(dict, "BPC", &bpc) && (cs = ppdict_get_name(dict, "CS")) != NULL)
1260  {
1261  if (ppname_is(cs, "DeviceGray"))
1262  colors = 1;
1263  else if (ppname_is(cs, "DeviceRGB"))
1264  colors = 3;
1265  else if (ppname_is(cs, "DeviceCMYK"))
1266  colors = 4;
1267  else
1268  return PP_LENGTH_UNKNOWN;
1269  return (w * h * bpc * colors + 7) >> 3;
1270  }
1271  }
1272  return PP_LENGTH_UNKNOWN;
1273 }
1274 
1275 static ppstring * ppstring_inline (iof *I, ppdict *imagedict, ppheap *heap)
1276 {
1277  iof *O;
1278  int c, d, e;
1279  size_t length, leftin, leftout, bytes;
1280 
1281  c = iof_char(I);
1282  if (ignored_char(c))
1283  c = iof_next(I);
1284 
1285  length = inline_image_length(imagedict);
1286  if (length != PP_LENGTH_UNKNOWN)
1287  {
1288  O = ppbytes_buffer(heap, length);
1289  while (length > 0 && iof_readable(I) && iof_writable(O))
1290  {
1291  leftin = iof_left(I);
1292  leftout = iof_left(O);
1293  bytes = length;
1294  if (bytes > leftin) bytes = leftin;
1295  if (bytes > leftout) bytes = leftout;
1296  memcpy(O->pos, I->pos, bytes);
1297  I->pos += bytes;
1298  O->pos += bytes;
1299  length -= bytes;
1300  }
1301  // gobble EI
1302  if (ppscan_find(I) == 'E')
1303  if (iof_next(I) == 'I')
1304  ++I->pos;
1305  }
1306  else
1307  {
1308  O = ppbytes_buffer(heap, PPSTRING_INIT); // ?
1309  while (c >= 0)
1310  {
1311  if (c == 'E')
1312  {
1313  d = iof_next(I);
1314  if (d == 'I')
1315  {
1316  e = iof_next(I);
1317  if (!ppnamebyte(e))
1318  { /* strip one newline from the end and stop */
1319  if (O->pos - 2 >= O->buf) // sanity
1320  {
1321  c = *(O->pos - 1);
1322  if (ignored_char(c))
1323  {
1324  if (c == 0x0A && *(O->pos - 2) == 0x0D)
1325  O->pos -= 2;
1326  else
1327  O->pos -= 1;
1328  }
1329  }
1330  break;
1331  }
1332  iof_put2(O, c, d);
1333  c = e;
1334  }
1335  else
1336  {
1337  iof_put(O, c);
1338  c = d;
1339  }
1340  }
1341  else
1342  {
1343  iof_put(O, c);
1344  c = iof_next(I);
1345  }
1346  }
1347  }
1348  return ppstring_buffer(O, heap);
1349 }
1350 
1351 /* input reader */
1352 
1353 /*
1354 PDF input is a pseudo file that either keeps FILE * or data. Reader iof * is a proxy to input
1355 that provides byte-by-byte interface. Our iof structure is capable to link iof_file *input,
1356 but t avoid redundant checks on IOF_DATA flag, here we link iof *I directly to FILE * or mem buffer.
1357 When reading from file we need an internal buffer, which should be kept rather small, as it is
1358 only used to parse xrefs and objects (no streams). We allocate the buffer from a private heap
1359 (not static) to avoid conflicts when processing >1 pdfs at once. Besides, the input buffer may be
1360 needed after loading the document, eg. to access references raw data.
1361 */
1362 
1363 #define PPDOC_BUFFER 0xFFF // keep that small, it is only used to parse body objects
1364 
1366 {
1367  iof *I;
1368  pdf->input = *input;
1369  input = &pdf->input;
1370  input->refcount = 1;
1371  I = &pdf->reader;
1372  if (input->flags & IOF_DATA)
1373  {
1374  pdf->buffer = NULL; // input iof_file is the buffer
1375  iof_string_reader(I, NULL, 0);
1376  }
1377  else
1378  {
1379  pdf->buffer = (uint8_t *)ppbytes_take(&pdf->heap, PPDOC_BUFFER);
1380  iof_setup_file_handle_reader(I, NULL, 0, iof_file_get_fh(input)); // gets IOF_FILE_HANDLE flag and FILE *
1381  I->space = PPDOC_BUFFER; // used on refill
1382  }
1383 }
1384 
1385 /*
1386 Whenever we need to read the input file, we fseek the to the given offset and fread to the private buffer.
1387 The length we need is not always predictable, in which case PPDOC_BUFFER bytes are read (keep it small).
1388 I->buf = I->pos is set to the beginning, I->end set to the end (end is the first byte one shouldn't read).
1389 */
1390 
1391 static iof * ppdoc_reader (ppdoc *pdf, size_t offset, size_t length)
1392 {
1393  iof_file *input;
1394  iof *I;
1395  input = &pdf->input;
1396  I = &pdf->reader;
1397  if (iof_file_seek(input, (long)offset, SEEK_SET) != 0)
1398  return NULL;
1399  I->flags &= ~~IOF_STOPPED;
1400  if (input->flags & IOF_DATA)
1401  {
1402  I->buf = I->pos = input->pos;
1403  I->end = (length == PP_LENGTH_UNKNOWN || I->pos + length >= input->end) ? input->end : (I->pos + length);
1404  }
1405  else
1406  {
1407  I->buf = I->pos = pdf->buffer; // ->buf is actually permanently equal pdf->buffer but we might need some tricks
1409  length = PPDOC_BUFFER;
1410  length = fread(I->buf, 1, length, I->file);
1411  I->end = I->buf + length;
1412  }
1413  return I;
1414 }
1415 
1416 /* The position from the beginning of input
1417 - for data buffer: (pdf->input.pos - pdf->input.buf) + (I->pos - I->buf)
1418  I->buf == pdf->input.pos, so this resolves to (I->pos - pdf->input.buf), independent from I->buf
1419 - for file buffer: ftell(pdf->input.file) - (I->end - I->pos)
1420 */
1421 
1422 #define ppdoc_reader_tell(pdf, I) ((size_t)(((pdf)->input.flags & IOF_DATA) ? ((I)->pos - (pdf)->input.buf) : (ftell(iof_file_get_fh(&(pdf)->input)) - ((I)->end - (I)->pos))))
1423 
1424 /* pdf */
1425 
1426 #define PPDOC_HEADER 10 // "%PDF-?.??\n"
1427 
1429 {
1430  size_t i;
1431  if (memcmp(header, "%PDF-", 5) != 0)
1432  return 0;
1433  for (i = 5; i < PPDOC_HEADER - 1 && !ignored_char(header[i]); ++i)
1434  pdf->version[i - 5] = header[i];
1435  pdf->version[i - 5] = '\0';
1436  return 1;
1437 }
1438 
1439 static int ppdoc_tail (ppdoc *pdf, iof_file *input, size_t *pxrefoffset)
1440 {
1441  int c;
1442  uint8_t tail[4*10], *p, back, tailbytes;
1443 
1444  if (iof_file_seek(input, 0, SEEK_END) != 0)
1445  return 0;
1446  pdf->filesize = (size_t)iof_file_tell(input);
1447  // simple heuristic to avoid fgetc() / fseek(-2) hiccup: keep seeking back by len(startxref) + 1 == 10
1448  // until a letter found (assuming liberal white characters and tail length)
1449  for (back = 1, tailbytes = 0; ; ++back)
1450  {
1451  if (iof_file_seek(input, -10, SEEK_CUR) != 0)
1452  return 0;
1453  tailbytes += 10;
1454  c = iof_file_getc(input);
1455  tailbytes -= 1;
1456  switch (c)
1457  {
1458  case IGNORED_CHAR_CASE:
1459  case DIGIT_CHAR_CASE:
1460  case '%': case 'E': case 'O': case 'F':
1461  if (back > 4) // 2 should be enough
1462  return 0;
1463  continue;
1464  case 's': case 't': case 'a': case 'r': case 'x': case 'e': case 'f':
1465  if (iof_file_read(tail, 1, tailbytes, input) != tailbytes)
1466  return 0;
1467  tail[tailbytes] = '\0';
1468  for (p = &tail[0]; ; ++p)
1469  {
1470  if (*p == '\0')
1471  return 0;
1472  if ((c = base10_value(*p)) >= 0)
1473  break;
1474  }
1475  ppread_uint(p, pxrefoffset);
1476  return 1;
1477  default:
1478  return 0;
1479  }
1480  }
1481  return 0; // never reached
1482 }
1483 
1484 /* xref/body */
1485 
1487 {
1488  ppuint u;
1489  ppscan_find(I); if (!ppscan_uint(I, &u) || u != ref->number) return 0;
1490  ppscan_find(I); if (!ppscan_uint(I, &u) || u != ref->version) return 0;
1491  ppscan_find(I); if (!ppscan_key(I, "obj")) return 0;
1492  ppscan_find(I);
1493  return 1;
1494 }
1495 
1496 static int ppscan_skip_entry (iof *I)
1497 {
1498  ppuint u;
1499  ppscan_find(I); if (!ppscan_uint(I, &u)) return 0;
1500  ppscan_find(I); if (!ppscan_uint(I, &u)) return 0;
1501  ppscan_find(I); if (!ppscan_key(I, "obj")) return 0;
1502  ppscan_find(I);
1503  return 1;
1504 }
1505 
1506 static int ppscan_start_stream (iof *I, ppdoc *pdf, size_t *streamoffset)
1507 {
1508  int c;
1509  ppscan_find(I);
1510  if (ppscan_key(I, "stream"))
1511  { // PJ20180912 bugfix: we were gobbling white characters (also null byte), while "stream" may be followed by EOL
1512  // pdf spec page 60: "CARRIAGE RETURN and a LINE FEED or just a LINE FEED, and not by a CARRIAGE RETURN alone"
1513  c = iof_char(I);
1514  if (c == 0x0D)
1515  {
1516  if (iof_next(I) == 0x0A) // should be
1517  ++I->pos;
1518  }
1519  else if (c == 0x0A)
1520  {
1521  ++I->pos;
1522  }
1523  *streamoffset = ppdoc_reader_tell(pdf, I);
1524  return 1;
1525  }
1526  return 0;
1527 }
1528 
1529 static ppxref * ppxref_load (ppdoc *pdf, size_t xrefoffset);
1531 
1532 /* Parsing xref table
1533 
1534  1 10 // first ref number and refs count
1535  0000000000 00000 n // 10-digits offset, 5 digits version, type identifier
1536  0000000000 00000 n // n states for normal I guess
1537  0000000000 00000 f // f states for free (not used)
1538  ...
1539 
1540 Free entries seem to be a relic of ancient times, completelly useless for us. To avoid parsing xref table twice,
1541 we waste some space on free entries by allocating one plane of refs for each section. Later on we slice sections,
1542 so that effectively free entries are not involved in map.
1543 
1544 Subsequent refs gets number, version and offset. Other fields initialized when parsing PDF body.
1545 
1546 Having xref table loaded, we sort sections for future binary search (xref with objects count == 0 is considered invalid).
1547 
1548 Then we have to deal with the trailer dict. In general, to load objects and resolve references we need a complete chain
1549 of xrefs (not only the top). To load the previous xref, we need its offset, which is given in trailer. So we have to
1550 parse the trailer ignoring references, which might be unresolvable at this point (objects parser makes a dummy check
1551 for xref != NULL on refs resolving ppscan_obj(), which irritates me but I don't want a separate parser for trailer..).
1552 The same applies to xref streams, in which we have parse the trailer not having xref map at all. So the procedure is:
1553 
1554  - load xref map, initialize references, make it ready to search
1555  - parse trailer ignoring references
1556  - get /Prev xref offset and load older xref (linked list via ->prev)
1557  - sort all refs in all xrefs by offset
1558  - parse refs in order resolving references in contained objects
1559  - fix trailer references
1560 
1561 First created xref becomes a pdf->xref (top xref). We link that early to control offsets already read (insane loops?).
1562 */
1563 
1564 // Every xref table item "0000000000 00000 n" is said to be terminated with 2-byte EOL but we don't like relying on whites.
1565 #define xref_item_length (10 + 1 + 5 + 1 + 1)
1566 
1567 static ppxref * ppxref_load_table (iof *I, ppdoc *pdf, size_t xrefoffset)
1568 {
1569  ppxref *xref;
1570  ppxsec *xrefsection;
1571  ppref *ref;
1572  ppuint first, count, refindex;
1574  const char *p;
1575  const ppobj *obj;
1576 
1577  buffer[xref_item_length] = '\0';
1578  xref = ppxref_create(pdf, 0, xrefoffset);
1579  if (pdf->xref == NULL) pdf->xref = xref;
1580 
1582  {
1583  ppscan_find(I);
1584  if (!ppscan_uint(I, &count))
1585  return NULL;
1586  if (count == 0) // weird
1587  continue;
1588  xref->count += count;
1589  xrefsection = NULL;
1590  ref = (ppref *)ppstruct_take(&pdf->heap, count * sizeof(ppref));
1591  for (refindex = 0; refindex < count; ++refindex, ++ref)
1592  {
1593  ref->xref = xref;
1594  ref->number = first + refindex;
1595  ppscan_find(I);
1597  switch (buffer[xref_item_length - 1])
1598  {
1599  case 'n':
1600  if (xrefsection == NULL)
1601  {
1602  xrefsection = ppxref_push_section(xref, &pdf->heap);
1603  xrefsection->first = ref->number;
1604  xrefsection->refs = ref;
1605  }
1606  xrefsection->last = ref->number;
1607  for (p = (const char *)buffer; *p == '0'; ++p);
1608  p = ppread_uint(p, &ref->offset);
1609  for ( ; *p == ' ' || *p == '0'; ++p);
1610  p = ppread_uint(p, &ref->version);
1611  ref->object.type = PPNONE; // init for sanity
1612  ref->object.any = NULL;
1613  ref->length = 0;
1614  break;
1615  case 'f':
1616  default:
1617  --ref;
1618  xrefsection = NULL;
1619  --xref->count;
1620  }
1621  }
1622  }
1623  /* sort section */
1624  ppxref_sort(xref); // case of xref->size == 0 handled by ppxref_load_chain()
1625  /* get trailer ignoring refs */
1626  if (!ppscan_key(I, "trailer"))
1627  return NULL;
1628  ppscan_find(I);
1629  if ((obj = ppscan_obj(I, pdf, NULL)) == NULL)
1630  return NULL;
1631  ppstack_pop(&pdf->stack, 1);
1632  if (obj->type != PPDICT)
1633  return NULL;
1634  xref->trailer = *obj;
1635  return ppxref_load_chain(pdf, xref);
1636 }
1637 
1638 /* Parsing xref stream
1639 First we load the trailer, ignoring references. Dict defines sections and fields lengths:
1640 
1641  /Size % max ref number plus 1
1642  /Index [ first count first count ... ] % a pair of numbers for every section, defaults to [0 Size]
1643  /W [w1 w2 w3] % fields lengths, 0 states for omitted field
1644 
1645 xref stream data is a continuous stream of binary number triplets. First number is a type:
1646 
1647  0 - free entry (as 'f' in xref table)
1648  1 - normal entry, followed by offset an version (as 'n' in xref table)
1649  2 - compressed entry, followed by parent object stream number and entry index
1650 
1651 0 and 1 are handled as 'n' and 'f' entries in xref table. For type 2 we normally initialize
1652 ref->number and ref->version (the later is implicitly 0). ref->offset is set to 0 (invalid offset),
1653 which is recognized by objects loader.
1654 */
1655 
1656 #define XREF_STREAM_MAX_FIELD 4
1657 
1658 static ppxref * ppxref_load_stream (iof *I, ppdoc *pdf, size_t xrefoffset)
1659 {
1660  ppxref *xref;
1661  ppxsec *xrefsection;
1662  ppref *ref;
1663  ppobj *obj;
1664  ppstream *xrefstream;
1665  size_t streamoffset;
1666  ppuint w1, w2, w3, w, bufferbytes;
1668  ppuint first, count, f1, f2, f3;
1669  pparray *fieldwidths, *sectionindices;
1670  ppobj sectionmock[2], *sectionfirst, *sectioncount;
1671  size_t sections, sectionindex, refindex;
1672 
1673  if (!ppscan_skip_entry(I))
1674  return NULL;
1675  if ((obj = ppscan_obj(I, pdf, NULL)) == NULL)
1676  return NULL;
1677  ppstack_pop(&pdf->stack, 1);
1678  if (obj->type != PPDICT || !ppscan_start_stream(I, pdf, &streamoffset))
1679  return NULL;
1680  xrefstream = ppstream_create(pdf, obj->dict, streamoffset);
1681  ppstream_info(xrefstream, pdf);
1682  if ((fieldwidths = ppdict_get_array(xrefstream->dict, "W")) != NULL)
1683  {
1684  if (!pparray_get_uint(fieldwidths, 0, &w1)) w1 = 0;
1685  if (!pparray_get_uint(fieldwidths, 1, &w2)) w2 = 0;
1686  if (!pparray_get_uint(fieldwidths, 2, &w3)) w3 = 0;
1687  }
1688  else
1689  w1 = w2 = w3 = 0;
1691  return NULL;
1692  bufferbytes = w1 + w2 + w3;
1693  if ((sectionindices = ppdict_get_array(xrefstream->dict, "Index")) != NULL)
1694  {
1695  sections = sectionindices->size >> 1;
1696  sectionfirst = sectionindices->data;
1697  }
1698  else
1699  {
1700  sections = 1;
1701  sectionmock[0].type = PPINT;
1702  sectionmock[0].integer = 0;
1703  sectionmock[1].type = PPINT;
1704  if (!ppdict_get_int(xrefstream->dict, "Size", &sectionmock[1].integer))
1705  sectionmock[1].integer = 0;
1706  sectionfirst = &sectionmock[0];
1707  }
1708  if ((I = ppstream_read(xrefstream, 1, 0)) == NULL)
1709  return NULL; // we fseek() so original I is useless anyway
1710  xref = ppxref_create(pdf, sections, xrefoffset);
1711  if (pdf->xref == NULL) pdf->xref = xref;
1712  xref->trailer.type = PPSTREAM;
1713  xref->trailer.stream = xrefstream;
1714  for (sectionindex = 0; sectionindex < sections; ++sectionindex, sectionfirst += 2)
1715  {
1716  sectioncount = sectionfirst + 1;
1717  first = 0, count = 0; // warnings
1718  if (!ppobj_get_uint(sectionfirst, first) || !ppobj_get_uint(sectioncount, count))
1719  goto xref_stream_error;
1720  if (count == 0)
1721  continue;
1722  xref->count += count;
1723  xrefsection = NULL;
1724  ref = (ppref *)ppstruct_take(&pdf->heap, count * sizeof(ppref));
1725  for (refindex = 0; refindex < count; ++refindex, ++ref)
1726  {
1727  ref->xref = xref;
1728  ref->number = first + refindex;
1729  if (iof_read(I, buffer, bufferbytes) != bufferbytes)
1730  goto xref_stream_error;
1731  b = buffer;
1732  if (w1 == 0)
1733  f1 = 1; // default type is 1
1734  else
1735  for (f1 = 0, w = 0; w < w1; f1 = (f1 << 8)|(*b), ++w, ++b);
1736  for (f2 = 0, w = 0; w < w2; f2 = (f2 << 8)|(*b), ++w, ++b);
1737  for (f3 = 0, w = 0; w < w3; f3 = (f3 << 8)|(*b), ++w, ++b);
1738  switch (f1)
1739  {
1740  case 0:
1741  //--ref;
1742  xrefsection = NULL;
1743  --xref->count;
1744  break;
1745  case 1:
1746  if (xrefsection == NULL)
1747  {
1748  xrefsection = ppxref_push_section(xref, &pdf->heap);
1749  xrefsection->first = ref->number;
1750  xrefsection->refs = ref;
1751  }
1752  xrefsection->last = ref->number;
1753  ref->offset = f2;
1754  ref->version = f3;
1755  ref->object.type = PPNONE;
1756  ref->object.any = NULL;
1757  ref->length = 0;
1758  break;
1759  case 2:
1760  if (xrefsection == NULL)
1761  {
1762  xrefsection = ppxref_push_section(xref, &pdf->heap);
1763  xrefsection->first = ref->number;
1764  xrefsection->refs = ref;
1765  }
1766  xrefsection->last = ref->number;
1767  ref->offset = 0; // f2 is parent objstm, f3 is index in parent, both useless
1768  ref->version = 0; // compressed objects has implicit version == 0
1769  ref->object.type = PPNONE;
1770  ref->object.any = NULL;
1771  ref->length = 0;
1772  break;
1773  default:
1774  goto xref_stream_error;
1775  }
1776  }
1777  }
1778  /* sort sections */
1779  ppxref_sort(xref); // case of xref->size == 0 handled by ppxref_load_chain()
1780  /* close the stream _before_ loading prev xref */
1781  ppstream_done(xrefstream);
1782  /* load prev and return */
1783  return ppxref_load_chain(pdf, xref);
1784 xref_stream_error:
1785  ppstream_done(xrefstream);
1786  return NULL;
1787 }
1788 
1789 /*
1790 The following procedure loads xref /Prev, links xref->prev and typically returns xref.
1791 Some docs contain empty xref (one section with zero objects) that is actually a proxy
1792 to xref stream referred as /XRefStm (genuine concept of xrefs old/new style xrefs in
1793 the same doc). In case of 0-length xref we ignore the proxy and return the target xref
1794 (otherwise we would need annoying sanity check for xref->size > 0 on every ref search).
1795 */
1796 
1798 {
1799  ppdict *trailer;
1800  ppuint xrefoffset;
1801  ppxref *prevxref, *nextxref;
1802 
1804  if (!ppdict_get_uint(trailer, "Prev", &xrefoffset)) // XRefStm is useless
1805  return xref;
1806  for (nextxref = pdf->xref; nextxref != NULL; nextxref = nextxref->prev)
1807  if (nextxref->offset == xrefoffset) // insane
1808  return NULL;
1809  if ((prevxref = ppxref_load(pdf, (size_t)xrefoffset)) == NULL)
1810  return NULL;
1811  if (xref->size > 0)
1812  {
1813  xref->prev = prevxref;
1814  return xref;
1815  }
1816  if (pdf->xref == xref)
1817  pdf->xref = prevxref;
1818  return prevxref;
1819 }
1820 
1821 static ppxref * ppxref_load (ppdoc *pdf, size_t xrefoffset)
1822 {
1823  iof *I;
1824 
1825  if ((I = ppdoc_reader(pdf, xrefoffset, PP_LENGTH_UNKNOWN)) == NULL)
1826  return NULL;
1827  ppscan_find(I);
1828  if (ppscan_key(I, "xref"))
1829  return ppxref_load_table(I, pdf, xrefoffset);
1830  return ppxref_load_stream(I, pdf, xrefoffset);
1831  // iof_close(I) does nothing here
1832 }
1833 
1834 static void ppoffmap_sort (ppref **left, ppref **right)
1835 {
1836  ppref **l, **r, *t;
1837  ppuint pivot;
1838  l = left, r = right;
1839  pivot = (*(l + ((r - l) / 2)))->offset;
1840  do
1841  { // don't read from pointer!
1842  while ((*l)->offset < pivot) ++l;
1843  while ((*r)->offset > pivot) --r;
1844  if (l <= r)
1845  {
1846  t = *l;
1847  *l = *r;
1848  *r = t;
1849  ++l, --r;
1850  }
1851  } while (l <= r);
1852  if (left < r)
1853  ppoffmap_sort(left, r);
1854  if (l < right)
1855  ppoffmap_sort(l, right);
1856 }
1857 
1858 
1860 {
1861  ppxref *xref;
1862  ppdict *trailer;
1863  ppname **pkey;
1864  ppobj *obj;
1865  ppref *ref;
1866  for (xref = pdf->xref; xref != NULL; xref = xref->prev)
1867  {
1868  if ((trailer = ppxref_trailer(xref)) == NULL)
1869  continue;
1870  for (ppdict_first(trailer, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
1871  { // no need to go deeper in structs, all items in trailer except info and root must be direct refs
1872  if (obj->type != PPREF)
1873  continue;
1874  ref = obj->ref;
1875  if (ref->offset == 0) // unresolved?
1876  if ((ref = ppxref_find(xref, ref->number)) != NULL)
1877  obj->ref = ref; // at this moment the reference still points nothing, but should be the one with the proper offset
1878  }
1879  }
1880 }
1881 
1882 /*
1883 Here comes a procedure that loads all entries from all document bodies. We resolve references while
1884 parsing objects and to make resolving correct, we need a complete chain of xref maps, and a knowledge
1885 about possible linearized dict (first offset). So loading refs sorted by offsets makes sense (not sure
1886 if it matters nowadays but we also avoid fseek() by large offsets).
1887 
1888 Here is the proc:
1889 
1890  - create a list of all refs in all bodies
1891  - sort the list by offsets
1892  - for every ref from the sorted list:
1893  - estimate object length to avoid fread-ing more than necessary (not perfect but enough)
1894  - fseek() to the proper offset, fread() entry data or its part
1895  - parse the object with ppscan_obj(I, pdf, xref), where xref is not necessarily top pdf->xref
1896  (since v0.98 xref actually no longer matters, see xref_find() notes)
1897  - save the actual ref->length (not used so far, but we keep that so..)
1898  - make a stream if a dict is followed by "stream" keyword, also save the stream offset
1899  - free the list
1900 
1901 PJ2080916: Luigi and Hans fixeed a bug (rev 6491); a document having a stream with /Length being
1902 a reference, that was stored in /ObjStm, and therefore not yet resolved when caching /Length key
1903 value as stream->offset (ppstream_info()). At the end, references were resolved propertly, but
1904 the stream was no readable; stream->offset == 0. In rev6491 ObjStm streams are loaded before
1905 others streams.
1906 */
1907 
1909 
1910 #define ppref_is_objstm(ref, stream, type) \
1911  ((ref)->xref->trailer.type == PPSTREAM && (type = ppdict_get_name((stream)->dict, "Type")) != NULL && ppname_is(type, "ObjStm"))
1912 
1913 
1915 {
1916  size_t objects, sectionindex, refnumber, offindex;
1917  size_t streams = 0, object_streams = 0, redundant_indirections = 0;
1918  ppnum linearized;
1919  ppref **offmap, **pref, *ref;
1920  ppxref *xref;
1921  ppxsec *xsec;
1922  ppobj *obj;
1923  ppname *type;
1924  ppcrypt *crypt;
1925  ppstream *stream;
1926 
1927  if ((objects = (size_t)ppdoc_objects(pdf)) == 0) // can't happen
1928  return;
1929  pref = offmap = (ppref **)pp_malloc(objects * sizeof(ppref *));
1930  objects = 0; // recount refs with offset > 0
1931  for (xref = pdf->xref; xref != NULL; xref = xref->prev)
1932  for (sectionindex = 0, xsec = xref->sects; sectionindex < xref->size; ++sectionindex, ++xsec)
1933  for (refnumber = xsec->first, ref = xsec->refs; refnumber <= xsec->last; ++refnumber, ++ref)
1934  if (ref->offset > 0) // 0 means compressed or insane
1935  *pref++ = ref, ++objects;
1936  ppoffmap_sort(offmap, offmap + objects - 1);
1937 
1938  crypt = pdf->crypt;
1939  for (offindex = 0, pref = offmap; offindex < objects; )
1940  {
1941  ref = *pref;
1942  ++pref;
1943  ++offindex;
1944  if (ref->object.type != PPNONE) // might be preloaded already (/Encrypt dict, stream filter dicts, stream /Length..)
1945  continue;
1946  if (offindex < objects)
1947  ref->length = (*pref)->offset - ref->offset;
1948  else
1949  ref->length = pdf->filesize > ref->offset ? pdf->filesize - ref->offset : 0;
1950  if (crypt != NULL)
1951  {
1953  obj = ppdoc_load_entry(pdf, ref);
1955  }
1956  else
1957  {
1958  obj = ppdoc_load_entry(pdf, ref);
1959  }
1960  switch (obj->type)
1961  {
1962  case PPDICT: /* Check if the object at first offset is linearized dict. We need that to resolve all references properly. */
1963  if (offindex == 1 && ppdict_get_num(obj->dict, "Linearized", &linearized)) // /Linearized value is a version number, default 1.0
1964  pdf->flags |= PPDOC_LINEARIZED;
1965  break;
1966  case PPSTREAM:
1967  ++streams;
1968  if (ppref_is_objstm(ref, obj->stream, type))
1969  ++object_streams;
1970  break;
1971  case PPREF:
1972  ++redundant_indirections;
1973  break;
1974  default:
1975  break;
1976  }
1977  }
1978 
1979  /* cut references pointing to references (rare). doing for all effectively cuts all insane chains */
1980  for (pref = offmap; redundant_indirections > 0; )
1981  {
1982  ref = *pref++;
1983  if (ref->object.type == PPREF)
1984  {
1985  --redundant_indirections;
1986  ref->object = ref->object.ref->object;
1987  }
1988  }
1989 
1990  /* load pdf 1.5 object streams _before_ other streams */
1991  for (pref = offmap; object_streams > 0; )
1992  {
1993  ref = *pref++;
1994  obj = &ref->object;
1995  if (obj->type != PPSTREAM)
1996  continue;
1997  stream = obj->stream;
1998  if (ppref_is_objstm(ref, stream, type))
1999  {
2000  --object_streams;
2001  if (crypt != NULL)
2002  {
2006  }
2007  else
2008  {
2010  }
2011  if (!ppdoc_load_objstm(stream, pdf, ref->xref))
2012  loggerf("invalid objects stream %s at offset " PPSIZEF, ppref_str(ref->number, ref->version), ref->offset);
2013 
2014  }
2015  }
2016 
2017  /* now handle other streams */
2018  for (pref = offmap; streams > 0; )
2019  {
2020  ref = *pref++;
2021  obj = &ref->object;
2022  if (obj->type != PPSTREAM)
2023  continue;
2024  --streams;
2025  stream = obj->stream;
2026  if (crypt != NULL)
2027  {
2031  }
2032  else
2033  {
2035  }
2036  }
2037  pp_free(offmap);
2038 }
2039 
2041 {
2042  iof *I;
2043  size_t length;
2044  ppxref *xref;
2045  ppobj *obj;
2046  ppstack *stack;
2047  size_t streamoffset;
2048  ppref *refref;
2049  ppuint refnumber, refversion;
2050 
2051  length = ref->length > 0 ? ref->length : PP_LENGTH_UNKNOWN; // estimated or unknown
2052  if ((I = ppdoc_reader(pdf, ref->offset, length)) == NULL || !ppscan_start_entry(I, ref))
2053  {
2054  loggerf("invalid %s offset " PPSIZEF, ppref_str(ref->number, ref->version), ref->offset);
2055  return &ref->object; // PPNONE
2056  }
2057  stack = &pdf->stack;
2058  xref = ref->xref;
2059  if ((obj = ppscan_obj(I, pdf, xref)) == NULL)
2060  {
2061  loggerf("invalid %s object at offset " PPSIZEF, ppref_str(ref->number, ref->version), ref->offset);
2062  return &ref->object; // PPNONE
2063  }
2064  ref->object = *obj;
2065  ppstack_pop(stack, 1);
2066  obj = &ref->object;
2067  ref->length = ppdoc_reader_tell(pdf, I) - ref->offset;
2068  if (obj->type == PPDICT)
2069  {
2070  if (ppscan_start_stream(I, pdf, &streamoffset))
2071  {
2072  obj->type = PPSTREAM;
2073  obj->stream = ppstream_create(pdf, obj->dict, streamoffset);
2074  }
2075  }
2076  else if (obj->type == PPINT)
2077  {
2078  ppscan_find(I);
2079  if (ppscan_uint(I, &refversion) && ppscan_find(I) == 'R')
2080  {
2081  refnumber = (ppuint)obj->integer;
2082  if ((refref = ppxref_find(xref, refnumber)) != NULL)
2083  {
2084  obj->type = PPREF;
2085  obj->ref = refref;
2086  }
2087  else
2088  {
2089  obj->type = PPNONE; // as ppref_unresolved()
2090  obj->any = NULL;
2091  }
2092  }
2093  }
2094  return obj;
2095 }
2096 
2097 /* Loading entries from object stream
2098 
2099  /N is the number of contained entries
2100  /First is the offset of the first item
2101 
2102 The stream consists of N pairs of numbers <objnum> <offset> <objnum> <offset> ...
2103 Offsets are ascending (relative to the first), but ref numbers order is arbitrary.
2104 PDF spec says there might be some additional data between objects, so we should obey offsets.
2105 Which means we should basically load the stream at once (may be needed anyway to grab the stream [...]).
2106 */
2107 
2109 {
2110  ppdict *dict; // stream dict, actually still on stack
2111  ppref *ref;
2112  ppobj *obj;
2113  ppuint items, firstoffset, offset, objnum, i, invalid = 0;
2114  iof *I;
2115  uint8_t *firstdata, *indexdata;
2116  ppstack *stack;
2117 
2118  dict = stream->dict;
2119  if (!ppdict_rget_uint(dict, "N", &items) || !ppdict_rget_uint(dict, "First", &firstoffset))
2120  return 0;
2121  if ((I = ppstream_read(stream, 1, 1)) == NULL)
2122  return 0;
2123  firstdata = I->pos + firstoffset;
2124  if (firstdata >= I->end)
2125  goto invalid_objstm;
2126  stack = &pdf->stack;
2127  //if (pdf->crypt != NULL)
2128  // ppcrypt_end_ref(pdf->crypt); // objects are not encrypted, pdf->crypt->ref ensured NULL
2129  for (i = 0; i < items; ++i)
2130  {
2131  ppscan_find(I);
2132  if (!ppscan_uint(I, &objnum))
2133  goto invalid_objstm;
2134  ppscan_find(I);
2135  if (!ppscan_uint(I, &offset))
2136  goto invalid_objstm;
2137  if ((ref = ppxref_find_local(xref, objnum)) == NULL || ref->object.type != PPNONE)
2138  {
2139  loggerf("invalid compressed object number " PPUINTF " at position " PPUINTF, objnum, i);
2140  ++invalid;
2141  continue;
2142  }
2143  if (firstdata + offset >= I->end)
2144  {
2145  loggerf("invalid compressed object offset " PPUINTF " at position " PPUINTF, offset, i);
2146  ++invalid;
2147  continue;
2148  }
2149  indexdata = I->pos; // save position
2150  I->pos = firstdata + offset; // go to the object
2151  ppscan_find(I);
2152  if ((obj = ppscan_obj(I, pdf, xref)) != NULL)
2153  {
2154  ref->object = *obj;
2155  ppstack_pop(stack, 1);
2156  // nothing more needed, as obj can never be indirect ref or stream
2157  }
2158  else
2159  {
2160  ++invalid;
2161  loggerf("invalid compressed object %s at stream offset " PPUINTF, ppref_str(objnum, 0), offset);
2162  }
2163  I->pos = indexdata; // restore position and read next from index
2164  }
2166  return invalid == 0;
2167 invalid_objstm:
2169  return 0;
2170 }
2171 
2172 /* main PDF loader proc */
2173 
2174 ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength, const void *ownerpass, size_t ownerpasslength)
2175 {
2176  switch (pdf->cryptstatus)
2177  {
2178  case PPCRYPT_NONE:
2179  case PPCRYPT_DONE:
2180  case PPCRYPT_FAIL:
2181  break;
2182  case PPCRYPT_PASS: // initial status or really needs password
2183  pdf->cryptstatus = ppdoc_crypt_init(pdf, userpass, userpasslength, ownerpass, ownerpasslength);
2184  switch (pdf->cryptstatus)
2185  {
2186  case PPCRYPT_NONE:
2187  case PPCRYPT_DONE:
2189  break;
2190  case PPCRYPT_PASS: // user needs to check ppdoc_crypt_status() and recall ppdoc_crypt_pass() with the proper password
2191  case PPCRYPT_FAIL: // hopeless..
2192  break;
2193  }
2194  break;
2195  }
2196  return pdf->cryptstatus;
2197 }
2198 
2200 {
2202  size_t xrefoffset;
2203 
2204  input = &pdf->input;
2206  return NULL;
2207  if (!ppdoc_tail(pdf, input, &xrefoffset))
2208  return NULL;
2209  if (ppxref_load(pdf, xrefoffset) == NULL)
2210  return NULL;
2211  fix_trailer_references(pdf); // after loading xrefs but before accessing trailer refs (/Encrypt might be a reference)
2212  // check encryption, if any, try empty password
2213  switch (ppdoc_crypt_pass(pdf, "", 0, NULL, 0))
2214  {
2215  case PPCRYPT_NONE: // no encryption
2216  case PPCRYPT_DONE: // encryption with an empty password
2217  case PPCRYPT_PASS: // the user needs to check ppdoc_crypt_status() and call ppdoc_crypt_pass()
2218  break;
2219  case PPCRYPT_FAIL: // hopeless
2220  //loggerf("decryption failed");
2221  //return NULL;
2222  break;
2223  }
2224  return pdf;
2225 }
2226 
2227 static void ppdoc_pages_init (ppdoc *pdf);
2228 
2229 /*
2230 20191214: We used to allocate ppdoc, as all other structs, from the internal heap:
2231 
2232  ppheap heap;
2233  ppheap_init(&heap);
2234  pdf = (ppdoc *)ppstruct_take(&heap, sizeof(ppdoc));
2235  pdf->heap = heap;
2236  ppbytes_buffer_init(&pdf->heap);
2237  ...
2238 
2239 So ppdoc pdf was allocated from the heap owned by the pdf itself. Somewhat tricky, but should work fine,
2240 as from that point nothing refered to a local heap variable addres. For some reason that causes a crash
2241 on openbsd.
2242 */
2243 
2245 {
2246  ppdoc *pdf;
2247 
2248  pdf = (ppdoc *)pp_malloc(sizeof(ppdoc));
2249  ppheap_init(&pdf->heap);
2250  ppbytes_buffer_init(&pdf->heap);
2251  ppstack_init(&pdf->stack, &pdf->heap);
2254  pdf->xref = NULL;
2255  pdf->crypt = NULL;
2256  pdf->cryptstatus = PPCRYPT_PASS; // check on ppdoc_read() -> ppdoc_crypt_pass()
2257  pdf->flags = 0;
2258  pdf->version[0] = '\0';
2259  if (ppdoc_read(pdf, &pdf->input) != NULL)
2260  return pdf;
2261  ppdoc_free(pdf);
2262  return NULL;
2263 }
2264 
2265 ppdoc * ppdoc_load (const char *filename)
2266 {
2267  FILE *file;
2268  iof_file input;
2269  if ((file = fopen(filename, "rb")) == NULL)
2270  return NULL;
2272  input.flags |= IOF_CLOSE_FILE;
2273  return ppdoc_create(&input);
2274 }
2275 
2276 ppdoc * ppdoc_filehandle (FILE *file, int closefile)
2277 {
2278  iof_file input;
2279  if (file == NULL)
2280  return NULL;
2282  if (closefile)
2283  input.flags |= IOF_CLOSE_FILE;
2284  return ppdoc_create(&input);
2285 }
2286 
2287 ppdoc * ppdoc_mem (const void *data, size_t size)
2288 {
2289  iof_file input;
2291  input.flags |= IOF_BUFFER_ALLOC;
2292  return ppdoc_create(&input);
2293 }
2294 
2296 {
2297  iof_file_decref(&pdf->input);
2298  ppstack_free_buffer(&pdf->stack);
2299  ppheap_free(&pdf->heap);
2300  pp_free(pdf);
2301 }
2302 
2304 {
2305  return pdf->cryptstatus;
2306 }
2307 
2309 {
2310  return pdf->crypt != NULL ? pdf->crypt->permissions : (ppint)0xFFFFFFFFFFFFFFFF;
2311 }
2312 
2313 /* pages access */
2314 
2316 {
2317  ppname **pkey, *key;
2318  ppobj *obj;
2319  pparray *kids = NULL;
2320  *count = 0;
2321  *type = NULL;
2322  for (ppdict_first(dict, pkey, obj); (key = *pkey) != NULL; ppdict_next(pkey, obj))
2323  {
2324  switch (key->data[0])
2325  {
2326  case 'T':
2327  if (ppname_is(key, "Type"))
2328  *type = ppobj_get_name(obj);
2329  break;
2330  case 'C':
2331  if (ppname_is(key, "Count"))
2332  ppobj_rget_uint(obj, *count);
2333  break;
2334  case 'K':
2335  if (ppname_is(key, "Kids"))
2336  kids = ppobj_rget_array(obj);
2337  break;
2338  }
2339  }
2340  return kids;
2341 }
2342 
2343 #define ppname_is_page(type) (type != NULL && ppname_is(type, "Page"))
2344 
2346 {
2347  ppref *ref;
2348  ppname *type;
2349  ppuint count;
2350  if ((ref = ppxref_pages(pdf->xref)) == NULL)
2351  return 0;
2352  if (pppage_node(ref->object.dict, &count, &type) == NULL)
2353  return ppname_is_page(type) ? 1 : 0; // acrobat and ghostscript accept documents with root /Pages entry being a reference to a sole /Page object
2354  return count;
2355 }
2356 
2358 {
2359  ppdict *dict;
2360  ppuint count;
2361  pparray *kids;
2362  size_t size, i;
2363  ppobj *r, *o;
2364  ppref *ref;
2365  ppname *type;
2366 
2367  if ((ref = ppxref_pages(pdf->xref)) == NULL)
2368  return NULL;
2369  dict = ref->object.dict;
2370  if ((kids = pppage_node(dict, &count, &type)) != NULL)
2371  {
2373  return NULL;
2374  }
2375  else
2376  {
2377  return index == 1 && ppname_is_page(type) ? ref : NULL;
2378  }
2379 scan_array:
2380  if (index <= count / 2)
2381  { // probably shorter way from the beginning
2382  for (i = 0, size = kids->size, r = pparray_at(kids, 0); i < size; ++i, ++r)
2383  {
2384  if (r->type != PPREF)
2385  return NULL;
2386  o = &r->ref->object;
2387  if (o->type != PPDICT)
2388  return NULL;
2389  dict = o->dict;
2390  if ((kids = pppage_node(dict, &count, &type)) != NULL)
2391  {
2392  if (index <= count)
2393  goto scan_array;
2394  index -= count;
2395  continue;
2396  }
2397  if (index == 1 && ppname_is_page(type))
2398  return r->ref;
2399  --index;
2400  }
2401  }
2402  else if ((size = kids->size) > 0) // for safe (size-1)
2403  { // probably shorter way from the end
2404  index = count - index + 1;
2405  for (i = 0, r = pparray_at(kids, size - 1); i < size; ++i, --r)
2406  {
2407  if (r->type != PPREF)
2408  return NULL;
2409  o = &r->ref->object;
2410  if (o->type != PPDICT)
2411  return NULL;
2412  dict = o->dict;
2413  if ((kids = pppage_node(dict, &count, &type)) != NULL)
2414  {
2415  if (index <= count) {
2416  index = count - index + 1;
2417  goto scan_array;
2418  }
2419  index -= count;
2420  continue;
2421  }
2422  if (index == 1 && ppname_is_page(type))
2423  return r->ref;
2424  --index;
2425  }
2426  }
2427  return NULL;
2428 }
2429 
2430 /*
2431 Through pages iterator. Iterating over pages tree just on the base of /Kids and /Parent keys
2432 is ineffective, as to get next pageref we need to take parent, find the pageref in /Kids,
2433 take next (or go upper).. Annoying. We use a dedicated stack for pages iterator. This could
2434 actually be done with pdf->stack, but some operations may clear it, so safer to keep it independent
2435 Besides, its depth is constant (set on first use), so no need for allocs.
2436 */
2437 
2439 {
2440  pppages *pages;
2441  pages = &pdf->pages;
2442  pages->root = pages->parent = &pages->buffer[0];
2443  pages->depth = 0;
2444  pages->space = PPPAGES_STACK_DEPTH;
2445 }
2446 
2448 {
2449  ppkids *newroot, *bounds;
2450  pppages *pages;
2451  pages = &pdf->pages;
2452  if (pages->depth == pages->space)
2453  {
2454  pages->space <<= 1;
2455  newroot = (ppkids *)ppstruct_take(&pdf->heap, pages->space * sizeof(ppkids));
2456  memcpy(newroot, pages->root, pages->depth * sizeof(ppkids));
2457  pages->root = newroot;
2458  }
2459  bounds = pages->parent = &pages->root[pages->depth++];
2460  bounds->current = pparray_at(kids, 0);
2461  bounds->sentinel = pparray_at(kids, kids->size);
2462  return bounds;
2463 }
2464 
2465 #define pppages_pop(pages) (--((pages)->parent), --((pages)->depth))
2466 
2468 {
2469  ppdict *dict;
2470  pparray *kids;
2471  ppuint count;
2472  ppname *type;
2473  ppobj *o;
2474 
2475  dict = ref->object.dict; // typecheck made by callers
2476  while ((kids = pppage_node(dict, &count, &type)) != NULL)
2477  {
2478  if ((o = pparray_get_obj(kids, 0)) == NULL) // empty /Kids
2479  return ppdoc_next_page(pdf);
2480  if ((ref = ppobj_get_ref(o)) == NULL || ref->object.type != PPDICT)
2481  return NULL;
2482  pppages_push(pdf, kids);
2483  dict = ref->object.dict;
2484  }
2485  return ppname_is_page(type) ? ref : NULL;
2486 }
2487 
2489 {
2490  ppref *ref;
2491  pppages *pages;
2492  if ((ref = ppdoc_pages(pdf)) == NULL)
2493  return NULL;
2494  pages = &pdf->pages;
2495  pages->parent = pages->root;
2496  pages->depth = 0;
2497  return ppdoc_pages_group_first(pdf, ref);
2498 }
2499 
2501 {
2502  pppages *pages;
2503  ppkids *bounds;
2504  ppref *ref;
2505  ppobj *obj;
2506  pages = &pdf->pages;
2507  while (pages->depth > 0)
2508  {
2509  bounds = pages->parent;
2510  obj = ++bounds->current;
2511  if (obj < bounds->sentinel)
2512  {
2513  if (obj->type != PPREF)
2514  return NULL;
2515  ref = obj->ref;
2516  if (ref->object.type != PPDICT)
2517  return NULL;
2518  return ppdoc_pages_group_first(pdf, ref);
2519  }
2520  else
2521  { // no next node, go upper
2522  pppages_pop(pages);
2523  }
2524  }
2525  return NULL;
2526 }
2527 
2528 /* context */
2529 
2531 {
2532  ppcontext *context;
2533  context = (ppcontext *)pp_malloc(sizeof(ppcontext));
2534  ppheap_init(&context->heap);
2535  ppbytes_buffer_init(&context->heap);
2536  ppstack_init(&context->stack, &context->heap);
2537  return context;
2538 }
2539 
2541 {
2542  ppheap_renew(&context->heap);
2543  ppstack_clear(&context->stack);
2544 }
2545 
2547 {
2548  ppstack_free_buffer(&context->stack);
2549  ppheap_free(&context->heap);
2550  pp_free(context);
2551 }
2552 
2553 /* page contents streams */
2554 
2555 //#define ppcontents_first_stream(array) pparray_rget_stream(array, 0)
2556 
2558 {
2559  size_t i;
2560  ppobj *obj;
2561  ppref *ref;
2562  for (pparray_first(array, i, obj); i < array->size; pparray_next(i, obj))
2563  if ((ref = ppobj_get_ref(obj)) != NULL && ref->object.type == PPSTREAM)
2564  return ref->object.stream;
2565  return NULL;
2566 }
2567 
2569 {
2570  size_t i;
2571  ppobj *obj;
2572  ppref *ref;
2573  for (pparray_first(array, i, obj); i < array->size; pparray_next(i, obj))
2574  if ((ref = ppobj_get_ref(obj)) != NULL && ref->object.type == PPSTREAM && ref->object.stream == stream)
2575  if (++i < array->size && (ref = ppobj_get_ref(obj + 1)) != NULL && ref->object.type == PPSTREAM)
2576  return ref->object.stream;
2577  return NULL;
2578 }
2579 
2581 {
2582  ppobj *contentsobj;
2583  if ((contentsobj = ppdict_rget_obj(dict, "Contents")) == NULL)
2584  return NULL;
2585  switch (contentsobj->type)
2586  {
2587  case PPARRAY:
2588  return ppcontents_first_stream(contentsobj->array);
2589  case PPSTREAM:
2590  return contentsobj->stream;
2591  default:
2592  break;
2593  }
2594  return NULL;
2595 }
2596 
2598 {
2599  ppobj *contentsobj;
2600  if ((contentsobj = ppdict_rget_obj(dict, "Contents")) == NULL)
2601  return NULL;
2602  switch (contentsobj->type)
2603  {
2604  case PPARRAY:
2605  return ppcontents_next_stream(contentsobj->array, stream);
2606  case PPSTREAM:
2607  break;
2608  default:
2609  break;
2610  }
2611  return NULL;
2612 }
2613 
2614 static ppobj * ppcontents_op (iof *I, ppstack *stack, size_t *psize, ppname **pname)
2615 {
2616  ppobj *obj;
2618  do {
2619  if (ppscan_find(I) < 0)
2620  return NULL;
2621  if ((obj = ppscan_psobj(I, stack)) == NULL)
2622  return NULL;
2623  } while (obj->type != PPNAME || !ppname_exec(obj->name));
2624  *pname = obj->name;
2625  *psize = stack->size - 1;
2626  return stack->buf;
2627 }
2628 
2630 {
2631  iof *I;
2632  if ((I = ppstream_read(stream, 1, 0)) == NULL)
2633  return NULL;
2634  return ppcontents_op(I, &context->stack, psize, pname);
2635 }
2636 
2638 {
2639  return ppcontents_op(ppstream_iof(stream), &context->stack, psize, pname);
2640 }
2641 
2643 {
2644  iof *I;
2645  ppstack *stack;
2646  ppobj *obj;
2647  stack = &context->stack;
2649  if ((I = ppstream_read(stream, 1, 0)) == NULL)
2650  return NULL;
2651  while (ppscan_find(I) >= 0)
2652  if ((obj = ppscan_psobj(I, stack)) == NULL)
2653  goto error;
2654  *psize = stack->size;
2656  return stack->buf;
2657 error:
2659  return NULL;
2660 }
2661 
2662 /* boxes */
2663 
2665 {
2666  ppobj *obj;
2667  if (array->size != 4)
2668  return NULL;
2669  obj = pparray_at(array, 0);
2670  if (!ppobj_get_num(obj, rect->lx)) return NULL;
2671  obj = pparray_at(array, 1);
2672  if (!ppobj_get_num(obj, rect->ly)) return NULL;
2673  obj = pparray_at(array, 2);
2674  if (!ppobj_get_num(obj, rect->rx)) return NULL;
2675  obj = pparray_at(array, 3);
2676  if (!ppobj_get_num(obj, rect->ry)) return NULL;
2677  return rect;
2678 }
2679 
2680 pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect)
2681 {
2682  pparray *array;
2683  return (array = ppdict_rget_array(dict, name)) != NULL ? pparray_to_rect(array, rect) : NULL;
2684 }
2685 
2686 pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect)
2687 {
2688  do {
2689  if (ppdict_get_rect(dict, name, rect) != NULL)
2690  return rect;
2691  dict = ppdict_rget_dict(dict, "Parent");
2692  } while (dict != NULL);
2693  return NULL;
2694 }
2695 
2697 {
2698  ppobj *obj;
2699  if (array->size != 6)
2700  return NULL;
2701  obj = pparray_at(array, 0);
2702  if (!ppobj_get_num(obj, matrix->xx)) return NULL;
2703  obj = pparray_at(array, 1);
2704  if (!ppobj_get_num(obj, matrix->xy)) return NULL;
2705  obj = pparray_at(array, 2);
2706  if (!ppobj_get_num(obj, matrix->yx)) return NULL;
2707  obj = pparray_at(array, 3);
2708  if (!ppobj_get_num(obj, matrix->yy)) return NULL;
2709  obj = pparray_at(array, 4);
2710  if (!ppobj_get_num(obj, matrix->x)) return NULL;
2711  obj = pparray_at(array, 5);
2712  if (!ppobj_get_num(obj, matrix->y)) return NULL;
2713  return matrix;
2714 }
2715 
2717 {
2718  pparray *array;
2719  return (array = ppdict_rget_array(dict, name)) != NULL ? pparray_to_matrix(array, matrix) : NULL;
2720 }
2721 
2722 /* logger */
2723 
2725 {
2727 }
2728 
2729 int pplog_prefix (const char *prefix)
2730 {
2731  return logger_prefix(prefix);
2732 }
2733 
2734 /* version */
2735 
2737 {
2738  return pdf->version;
2739 }
2740 
2742 {
2743  *minor = pdf->version[2] - '0';
2744  return pdf->version[0] - '0';
2745 }
2746 
2747 /* doc info */
2748 
2750 {
2751  return pdf->filesize;
2752 }
2753 
2755 {
2756  ppuint count;
2757  ppxref *xref;
2758  for (count = 0, xref = pdf->xref; xref != NULL; xref = xref->prev)
2759  count += xref->count;
2760  return count;
2761 }
2762 
2763 size_t ppdoc_memory (ppdoc *pdf, size_t *waste)
2764 {
2765  mem_info info;
2766  size_t used;
2767  ppbytes_heap_info(&pdf->heap, &info, 0);
2768  ppstruct_heap_info(&pdf->heap, &info, 1);
2769 
2770  *waste = info.ghosts + info.blockghosts + info.left; // info.ghosts == 0
2771  used = info.used + *waste;
2772  used += pdf->stack.space * sizeof(ppobj);
2773  return used;
2774 }
int code
Definition: aftopl.c:52
#define mark
Definition: aptex-macros.h:374
#define type(a)
Definition: aptex-macros.h:171
#define count(a)
Definition: aptex-macros.h:781
#define name
#define w1
#define tail
Definition: aptex-macros.h:514
#define mode
Definition: aptex-macros.h:510
#define b
Definition: jpegint.h:372
void invalid(int opcode)
Definition: disdvi.c:818
int w
Definition: dviconv.c:26
int h
Definition: dviconv.c:9
#define fopen
Definition: xxstdio.h:21
#define fread
Definition: xxstdio.h:25
struct pagespec pages[(32)]
#define info
Definition: dviinfo.c:42
#define error(a)
Definition: dviinfo.c:48
struct rect data
Definition: dvipdfm.c:64
struct rect rect
Definition: dvipdfm.c:59
sectiontype * sections
Definition: dvips.c:94
#define t
Definition: afcover.h:96
#define w3
#define w2
#define c(n)
Definition: gpos-common.c:150
#define d(n)
Definition: gpos-common.c:151
#define memcmp(s1, s2, n)
Definition: gsftopk.c:66
#define memcpy(d, s, n)
Definition: gsftopk.c:64
static void decode()
#define SEEK_SET
Definition: jmemansi.c:26
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
#define I(x, y, z)
Definition: md5.c:55
#define SEEK_CUR
Definition: ftzconf.h:250
#define SEEK_END
Definition: ftzconf.h:251
@ right
Definition: annotate.c:15
unsigned int uint32_t
Definition: stdint.h:80
unsigned char uint8_t
Definition: stdint.h:78
signed char int8_t
Definition: stdint.h:75
int minor
Definition: pdfcolor.c:527
char * string
Definition: simpletypes.h:55
#define input
Definition: cpascal.h:53
#define string
Definition: ctangleboot.c:111
#define length(c)
Definition: ctangleboot.c:65
#define sprintf
Definition: snprintf.c:44
static int crypt(lua_State *L)
Definition: md5lib.c:117
#define size_t
Definition: glob.c:257
#define O(_t, _a, _f)
Definition: makeint.h:501
def ref(x)
Definition: pdf-org.py:104
Definition: pdf.py:1
int integer
Definition: pbmtopk.c:38
char * filename[256]
Definition: pbmtopk.c:46
static bool pdf
Definition: pdftocairo.cc:93
float ** matrix()
static int items
Definition: pgmtofs.c:86
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
#define index(s, c)
Definition: plain2.h:351
static int32_t last
Definition: ppagelist.c:29
static int32_t first
Definition: ppagelist.c:29
static struct colourSystem * cs
Definition: ppmcie.c:241
#define B(x, y)
static int size
Definition: ppmlabel.c:24
int r
Definition: ppmqvga.c:68
static int offset
Definition: ppmtogif.c:642
int colors
Definition: ppmtogif.c:51
bstring c int memset(void *s, int c, int length)
static long bytes
Definition: psutil.c:35
#define objects(p)
Definition: gc.c:219
struct stream_s stream
Definition: pts_fax.h:93
#define flags
pparray * ppdict_rget_array(ppdict *dict, const char *name)
Definition: ppdict.c:124
char ppbyte
Definition: ppapi.h:19
#define ppobj_get_num(o, v)
Definition: ppapi.h:150
#define ppdict_first(dict, pkey, obj)
Definition: ppapi.h:282
ppref * ppxref_pages(ppxref *xref)
Definition: ppxref.c:207
void ppstream_done(ppstream *stream)
Definition: ppstream.c:241
#define ppdoc_pages(pdf)
Definition: ppapi.h:322
int pparray_get_uint(pparray *array, size_t index, ppuint *v)
Definition: pparray.c:49
#define PPSTRING_ENCODED
Definition: ppapi.h:199
#define ppobj_rget_array(o)
Definition: ppapi.h:166
pparray * ppdict_get_array(ppdict *dict, const char *name)
Definition: ppdict.c:118
int ppdict_get_int(ppdict *dict, const char *name, ppint *v)
Definition: ppdict.c:58
#define ppname_exec(name)
Definition: ppapi.h:181
void(* pplogger_callback)(const char *message, void *alien)
Definition: ppapi.h:389
int ppdict_get_uint(ppdict *dict, const char *name, ppuint *v)
Definition: ppdict.c:70
ppname * ppdict_get_name(ppdict *dict, const char *name)
Definition: ppdict.c:94
#define pparray_first(array, index, obj)
Definition: ppapi.h:223
#define ppdict_next(pkey, obj)
Definition: ppapi.h:283
#define PPNAME_DECODED
Definition: ppapi.h:185
int64_t ppint
Definition: ppapi.h:16
#define pparray_next(index, obj)
Definition: ppapi.h:224
#define PPSTRING_BASE85
Definition: ppapi.h:204
size_t ppuint
Definition: ppapi.h:17
int ppdict_get_num(ppdict *dict, const char *name, ppnum *v)
Definition: ppdict.c:82
ppobj * pparray_get_obj(pparray *array, size_t index)
Definition: pparray.c:14
ppcrypt_status
Definition: ppapi.h:334
@ PPCRYPT_DONE
Definition: ppapi.h:336
@ PPCRYPT_FAIL
Definition: ppapi.h:337
@ PPCRYPT_PASS
Definition: ppapi.h:338
@ PPCRYPT_NONE
Definition: ppapi.h:335
#define PPSTRING_BASE16
Definition: ppapi.h:203
@ PPDICT
Definition: ppapi.h:110
@ PPREF
Definition: ppapi.h:112
@ PPSTRING
Definition: ppapi.h:108
@ PPNULL
Definition: ppapi.h:103
@ PPARRAY
Definition: ppapi.h:109
@ PPSTREAM
Definition: ppapi.h:111
@ PPNUM
Definition: ppapi.h:106
@ PPNONE
Definition: ppapi.h:102
@ PPNAME
Definition: ppapi.h:107
@ PPBOOL
Definition: ppapi.h:104
#define pparray_at(array, index)
Definition: ppapi.h:221
double ppnum
Definition: ppapi.h:21
#define ppobj_get_uint(o, v)
Definition: ppapi.h:149
#define ppobj_get_name(o)
Definition: ppapi.h:151
struct ppobj ppobj
Definition: ppapi.h:40
ppref * ppxref_find(ppxref *xref, ppuint refnumber)
Definition: ppxref.c:158
ppdict * ppxref_trailer(ppxref *xref)
Definition: ppxref.c:171
ppobj * ppdict_rget_obj(ppdict *dict, const char *name)
Definition: ppdict.c:40
#define ppobj_get_ref(o)
Definition: ppapi.h:156
ppdict * ppdict_rget_dict(ppdict *dict, const char *name)
Definition: ppdict.c:136
int ppdict_rget_uint(ppdict *dict, const char *name, ppuint *v)
Definition: ppdict.c:76
#define PPNAME_ENCODED
Definition: ppapi.h:184
#define ppobj_rget_uint(o, v)
Definition: ppapi.h:162
#define PPSTRING_DECODED
Definition: ppapi.h:200
#define ppname_is(name, s)
Definition: ppapi.h:177
#define PPNAME_EXEC
Definition: ppapi.h:186
pparray * pparray_create(const ppobj *stackpos, size_t size, ppheap *heap)
Definition: pparray.c:4
#define PPUINTF
Definition: ppconf.h:71
#define PPINT(N)
Definition: ppconf.h:68
#define PPSIZEF
Definition: ppconf.h:74
ppcrypt_status ppdoc_crypt_init(ppdoc *pdf, const void *userpass, size_t userpasslength, const void *ownerpass, size_t ownerpasslength)
Definition: ppcrypt.c:196
int ppstring_decrypt(ppcrypt *crypt, const void *input, size_t size, void *output, size_t *newsize)
Definition: ppcrypt.c:459
#define ppcrypt_end_ref(crypt)
Definition: ppcrypt.h:61
#define ppcrypt_start_ref(crypt, r)
Definition: ppcrypt.h:60
#define ppcrypt_ref(pdf, crypt)
Definition: ppcrypt.h:62
ppdict * ppdict_create(const ppobj *stackpos, size_t size, ppheap *heap)
Definition: ppdict.c:4
void ppheap_free(ppheap *heap)
Definition: ppheap.c:15
void ppheap_init(ppheap *heap)
Definition: ppheap.c:9
ppbyte * ppbytes_flush(ppheap *heap, iof *O, size_t *psize)
Definition: ppheap.c:28
void ppheap_renew(ppheap *heap)
Definition: ppheap.c:21
#define ppbytes_buffer_init(heap)
Definition: ppheap.h:24
#define ppbytes_buffer(heap, atleast)
Definition: ppheap.h:25
#define pp_free
Definition: ppheap.h:10
#define ppstruct_take(heap, size)
Definition: ppheap.h:32
#define ppbytes_heap_info(heap, info, append)
Definition: ppheap.h:21
#define pp_malloc
Definition: ppheap.h:7
#define ppbytes_take(heap, size)
Definition: ppheap.h:23
#define ppstruct_heap_info(heap, info, append)
Definition: ppheap.h:31
ppstream * ppcontents_next(ppdict *dict, ppstream *stream)
Definition: ppload.c:2597
ppref * ppdoc_next_page(ppdoc *pdf)
Definition: ppload.c:2500
void ppdoc_free(ppdoc *pdf)
Definition: ppload.c:2295
const char * ppobj_kind[]
Definition: ppload.c:9
ppint ppdoc_permissions(ppdoc *pdf)
Definition: ppload.c:2308
ppuint ppdoc_page_count(ppdoc *pdf)
Definition: ppload.c:2345
void ppcontext_free(ppcontext *context)
Definition: ppload.c:2546
ppstring * ppstring_encoded(ppstring *string)
Definition: ppload.c:547
void pplog_callback(pplogger_callback logger, void *alien)
Definition: ppload.c:2724
ppdoc * ppdoc_mem(const void *data, size_t size)
Definition: ppload.c:2287
ppstring * ppstring_internal(const void *data, size_t size, ppheap *heap)
Definition: ppload.c:420
ppuint ppdoc_objects(ppdoc *pdf)
Definition: ppload.c:2754
ppobj * ppcontents_first_op(ppcontext *context, ppstream *stream, size_t *psize, ppname **pname)
Definition: ppload.c:2629
ppobj * ppdoc_load_entry(ppdoc *pdf, ppref *ref)
Definition: ppload.c:2040
int pplog_prefix(const char *prefix)
Definition: ppload.c:2729
pprect * pparray_to_rect(pparray *array, pprect *rect)
Definition: ppload.c:2664
ppobj * ppcontents_next_op(ppcontext *context, ppstream *stream, size_t *psize, ppname **pname)
Definition: ppload.c:2637
ppcontext * ppcontext_new(void)
Definition: ppload.c:2530
ppcrypt_status ppdoc_crypt_pass(ppdoc *pdf, const void *userpass, size_t userpasslength, const void *ownerpass, size_t ownerpasslength)
Definition: ppload.c:2174
size_t ppdoc_memory(ppdoc *pdf, size_t *waste)
Definition: ppload.c:2763
size_t ppdoc_file_size(ppdoc *pdf)
Definition: ppload.c:2749
ppobj * ppcontents_parse(ppcontext *context, ppstream *stream, size_t *psize)
Definition: ppload.c:2642
ppmatrix * pparray_to_matrix(pparray *array, ppmatrix *matrix)
Definition: ppload.c:2696
ppname * ppname_encoded(ppname *name)
Definition: ppload.c:205
ppdoc * ppdoc_load(const char *filename)
Definition: ppload.c:2265
ppstring * ppstring_decoded(ppstring *string)
Definition: ppload.c:542
void ppcontext_done(ppcontext *context)
Definition: ppload.c:2540
ppbyte * ppstring_encoded_data(ppstring *string)
Definition: ppload.c:557
int ppdoc_version_number(ppdoc *pdf, int *minor)
Definition: ppload.c:2741
ppref * ppdoc_page(ppdoc *pdf, ppuint index)
Definition: ppload.c:2357
ppstream * ppcontents_first(ppdict *dict)
Definition: ppload.c:2580
ppref * ppdoc_first_page(ppdoc *pdf)
Definition: ppload.c:2488
ppname * ppname_decoded(ppname *name)
Definition: ppload.c:200
ppbyte * ppstring_decoded_data(ppstring *string)
Definition: ppload.c:552
ppmatrix * ppdict_get_matrix(ppdict *dict, const char *name, ppmatrix *matrix)
Definition: ppload.c:2716
ppbyte * ppname_decoded_data(ppname *name)
Definition: ppload.c:210
ppbyte * ppname_encoded_data(ppname *name)
Definition: ppload.c:215
const char * ppdoc_version_string(ppdoc *pdf)
Definition: ppload.c:2736
pprect * ppdict_get_box(ppdict *dict, const char *name, pprect *rect)
Definition: ppload.c:2686
ppdoc * ppdoc_filehandle(FILE *file, int closefile)
Definition: ppload.c:2276
ppcrypt_status ppdoc_crypt_status(ppdoc *pdf)
Definition: ppload.c:2303
pprect * ppdict_get_rect(ppdict *dict, const char *name, pprect *rect)
Definition: ppload.c:2680
#define PPDOC_LINEARIZED
Definition: ppload.h:46
#define PPPAGES_STACK_DEPTH
Definition: ppload.h:18
iof * ppstream_read(ppstream *stream, int decode, int all)
Definition: ppstream.c:134
void ppstream_info(ppstream *stream, ppdoc *pdf)
Definition: ppstream.c:303
ppstream * ppstream_create(ppdoc *pdf, ppdict *dict, size_t offset)
Definition: ppstream.c:5
#define ppstream_iof(stream)
Definition: ppstream.h:7
ppxref * ppxref_create(ppdoc *pdf, size_t initsize, size_t xrefoffset)
Definition: ppxref.c:6
ppref * ppxref_find_local(ppxref *xref, ppuint refnumber)
Definition: ppxref.c:89
ppxsec * ppxref_push_section(ppxref *xref, ppheap *heap)
Definition: ppxref.c:25
int ppxref_sort(ppxref *xref)
Definition: ppxref.c:81
iof * iof_setup_file_handle_reader(iof *I, void *buffer, size_t space, FILE *f)
Definition: utiliof.c:842
iof * iof_string_reader(iof *I, const void *s, size_t bytes)
Definition: utiliof.c:977
iof_file * iof_file_rdata_init(iof_file *iofile, const void *data, size_t size)
Definition: utiliof.c:128
size_t iof_read(iof *I, void *to, size_t size)
Definition: utiliof.c:1122
int iof_file_getc(iof_file *iofile)
Definition: utiliof.c:502
long iof_file_tell(iof_file *iofile)
Definition: utiliof.c:391
size_t iof_file_read(void *ptr, size_t size, size_t items, iof_file *iofile)
Definition: utiliof.c:424
int iof_file_seek(iof_file *iofile, long offset, int whence)
Definition: utiliof.c:356
iof_file * iof_file_init(iof_file *iofile, FILE *file)
Definition: utiliof.c:104
#define iof_set4(O, c1, c2, c3, c4)
Definition: utiliof.h:456
#define iof_char(I)
Definition: utiliof.h:389
#define iof_file_decref(iofile)
Definition: utiliof.h:253
#define iof_ensure(O, n)
Definition: utiliof.h:352
#define iof_put(O, c)
Definition: utiliof.h:462
#define iof_set2(O, c1, c2)
Definition: utiliof.h:454
iof_status
Definition: utiliof.h:25
@ IOFEOF
Definition: utiliof.h:26
@ IOFFULL
Definition: utiliof.h:28
@ IOFERR
Definition: utiliof.h:29
#define iof_readable(I)
Definition: utiliof.h:338
#define iof_file_get_fh(iofile)
Definition: utiliof.h:221
#define iof_set3(O, c1, c2, c3)
Definition: utiliof.h:455
#define iof_writable(O)
Definition: utiliof.h:339
#define IOF_CLOSE_FILE
Definition: utiliof.h:107
#define iof_set(O, c)
Definition: utiliof.h:453
#define iof_scan_integer(I, c, number)
Definition: utiliof.h:481
#define IOF_DATA
Definition: utiliof.h:103
#define IOF_BUFFER_ALLOC
Definition: utiliof.h:93
#define iof_left(I)
Definition: utiliof.h:169
#define iof_size(I)
Definition: utiliof.h:170
#define iof_scan_fraction(I, c, number, exponent10)
Definition: utiliof.h:487
#define iof_put4(O, c1, c2, c3, c4)
Definition: utiliof.h:465
#define iof_put2(O, c1, c2)
Definition: utiliof.h:463
#define iof_next(I)
Definition: utiliof.h:393
#define iof_get(I)
Definition: utiliof.h:385
void loggerf(const char *format,...)
Definition: utillog.c:20
static logger_struct logger
Definition: utillog.c:16
void logger_callback(logger_function callback, void *context)
Definition: utillog.c:45
int logger_prefix(const char *prefix)
Definition: utillog.c:51
void(* logger_function)(const char *message, void *alien)
Definition: utillog.h:5
#define double_negative_exp10(number, exponent)
Definition: utilnumber.h:409
#define base10_value(c)
Definition: utilnumber.h:97
#define base16_uc_alphabet
Definition: utilnumber.h:84
#define base10_digit(c)
Definition: utilnumber.h:96
#define sentinel
Definition: lib_package.c:437
#define ppstringesc(c)
Definition: ppload.c:256
static ppxref * ppxref_load(ppdoc *pdf, size_t xrefoffset)
Definition: ppload.c:1821
#define ppdoc_reader_tell(pdf, I)
Definition: ppload.c:1422
#define DIGIT_CHAR_CASE
Definition: ppload.c:15
#define ppstack_pop(stack, n)
Definition: ppload.c:781
#define ppstring_check_bom2(decoded, encoded)
Definition: ppload.c:249
static ppstream * ppcontents_next_stream(pparray *array, ppstream *stream)
Definition: ppload.c:2568
#define ppstack_push(stack)
Definition: ppload.c:780
static iof_status ppscan_base85_decode(iof *I, iof *O)
Definition: ppload.c:455
#define MAX_INT_DIGITS
Definition: ppload.c:18
#define newline_char(c)
Definition: ppload.c:12
static ppkids * pppages_push(ppdoc *pdf, pparray *kids)
Definition: ppload.c:2447
#define PPDOC_BUFFER
Definition: ppload.c:1363
#define NEWLINE_CHAR_CASE
Definition: ppload.c:14
static ppobj * ppscan_numobj_frac(iof *I, ppobj *obj, int negative)
Definition: ppload.c:816
static ppref * ppref_unresolved(ppheap *heap, ppuint refnumber, ppuint refversion)
Definition: ppload.c:874
static int ppdoc_tail(ppdoc *pdf, iof_file *input, size_t *pxrefoffset)
Definition: ppload.c:1439
static void ppstack_init(ppstack *stack, ppheap *heap)
Definition: ppload.c:759
static int ppdoc_header(ppdoc *pdf, uint8_t header[10])
Definition: ppload.c:1428
#define ignored_char(c)
Definition: ppload.c:11
static void fix_trailer_references(ppdoc *pdf)
Definition: ppload.c:1859
static ppstring * ppscan_crypt_string(iof *I, ppcrypt *crypt, ppheap *heap)
Definition: ppload.c:565
#define pphex(c)
Definition: ppload.c:94
static ppobj * ppscan_psobj(iof *I, ppstack *stack)
Definition: ppload.c:1043
static ppname * ppscan_name(iof *I, ppheap *heap)
Definition: ppload.c:98
static void ppstack_resize(ppstack *stack)
Definition: ppload.c:769
#define OCTAL_CHAR_CASE
Definition: ppload.c:16
#define ppexec_internal(data, size, heap)
Definition: ppload.c:198
static void ppdoc_reader_init(ppdoc *pdf, iof_file *input)
Definition: ppload.c:1365
static ppdoc * ppdoc_create(iof_file *input)
Definition: ppload.c:2244
static ppobj * ppscan_obj(iof *I, ppdoc *pdf, ppxref *xref)
Definition: ppload.c:886
static iof * ppdoc_reader(ppdoc *pdf, size_t offset, size_t length)
Definition: ppload.c:1391
static void ppoffmap_sort(ppref **left, ppref **right)
Definition: ppload.c:1834
static ppref * ppdoc_pages_group_first(ppdoc *pdf, ppref *ref)
Definition: ppload.c:2467
#define base85_code(c1, c2, c3, c4, c5)
Definition: ppload.c:452
static int ppscan_find(iof *I)
Definition: ppload.c:829
static ppstring * ppscan_crypt_base16(iof *I, ppcrypt *crypt, ppheap *heap)
Definition: ppload.c:697
static void ppdoc_load_entries(ppdoc *pdf)
Definition: ppload.c:1914
static int ppscan_start_stream(iof *I, ppdoc *pdf, size_t *streamoffset)
Definition: ppload.c:1506
#define IGNORED_CHAR_CASE
Definition: ppload.c:13
static ppxref * ppxref_load_stream(iof *I, ppdoc *pdf, size_t xrefoffset)
Definition: ppload.c:1658
#define ppstring_check_bom(decoded)
Definition: ppload.c:245
static int ppscan_start_entry(iof *I, ppref *ref)
Definition: ppload.c:1486
static int ppscan_keyword(iof *I, const char *keyword, size_t size)
Definition: ppload.c:852
static int ppscan_skip_entry(iof *I)
Definition: ppload.c:1496
#define pppages_pop(pages)
Definition: ppload.c:2465
#define base85_value(c)
Definition: ppload.c:450
#define ppread_uint(s, u)
Definition: ppload.c:788
#define ppnamebyte(c)
Definition: ppload.c:71
#define PPSTRING_INIT
Definition: ppload.c:243
static size_t inline_image_length(ppdict *dict)
Definition: ppload.c:1252
#define PP_LENGTH_UNKNOWN
Definition: ppload.c:20
static ppobj * ppscan_numobj(iof *I, ppobj *obj, int negative)
Definition: ppload.c:790
static void ppdoc_pages_init(ppdoc *pdf)
Definition: ppload.c:2438
#define PPNAME_INIT
Definition: ppload.c:96
#define PPMARK
Definition: ppload.c:884
static const int8_t ppname_byte_lookup[]
Definition: ppload.c:46
static pparray * pppage_node(ppdict *dict, ppuint *count, ppname **type)
Definition: ppload.c:2315
#define PPDOC_HEADER
Definition: ppload.c:1426
static ppdoc * ppdoc_read(ppdoc *pdf, iof_file *input)
Definition: ppload.c:2199
static ppxref * ppxref_load_table(iof *I, ppdoc *pdf, size_t xrefoffset)
Definition: ppload.c:1567
#define ppstack_at(stack, i)
Definition: ppload.c:782
#define base85_eof(c)
Definition: ppload.c:453
static ppxref * ppxref_load_chain(ppdoc *pdf, ppxref *xref)
Definition: ppload.c:1797
static ppname * ppscan_exec(iof *I, ppheap *heap, uint8_t firstbyte)
Definition: ppload.c:141
static ppname * ppname_internal(const void *data, size_t size, int flags, ppheap *heap)
Definition: ppload.c:185
#define XREF_STREAM_MAX_FIELD
Definition: ppload.c:1656
#define PPSTACK_BUFFER
Definition: ppload.c:757
static ppstring * ppscan_string(iof *I, ppheap *heap)
Definition: ppload.c:258
#define ppstack_clear(stack)
Definition: ppload.c:783
static int ppdoc_load_objstm(ppstream *stream, ppdoc *pdf, ppxref *xref)
Definition: ppload.c:2108
#define xref_item_length
Definition: ppload.c:1565
static ppstring * ppscan_base16(iof *I, ppheap *heap)
Definition: ppload.c:365
static ppstring * ppstring_buffer(iof *O, ppheap *heap)
Definition: ppload.c:400
static const int8_t pphex_byte_lookup[]
Definition: ppload.c:73
#define ppscan_uint(I, u)
Definition: ppload.c:787
static ppstring * ppstring_inline(iof *I, ppdict *imagedict, ppheap *heap)
Definition: ppload.c:1275
static const int8_t ppstring_byte_escape[]
Definition: ppload.c:222
static const char * ppref_str(ppuint refnumber, ppuint refversion)
Definition: ppload.c:22
static ppstream * ppcontents_first_stream(pparray *array)
Definition: ppload.c:2557
#define ppscan_key(I, literal)
Definition: ppload.c:870
static ppstring * ppscan_base85(iof *I, ppheap *heap)
Definition: ppload.c:513
static const int8_t ppstring_base85_lookup[]
Definition: ppload.c:431
#define ppref_is_objstm(ref, stream, type)
Definition: ppload.c:1910
#define ppstack_free_buffer(stack)
Definition: ppload.c:767
#define ppname_is_page(type)
Definition: ppload.c:2343
static ppobj * ppcontents_op(iof *I, ppstack *stack, size_t *psize, ppname **pname)
Definition: ppload.c:2614
lft_cell * left
Definition: routines.h:73
static _ts_NODE_t * balance(_ts_NODE_t **, _ts_NODE_t *, int)
Definition: sh12.c:338
ShellFileEnvironment e
Definition: sh6.c:388
Definition: utils.c:300
Definition: inftrees.h:24
Definition: pst1form.c:310
Definition: filedef.h:30
Definition: mendex.h:20
Definition: execute.c:108
Definition: utiliof.h:83
Definition: sh.h:1226
int type
Definition: sh.h:1227
Definition: pdfdoc.c:79
Definition: ppapi.h:43
size_t size
Definition: ppapi.h:45
ppobj * data
Definition: ppapi.h:44
Definition: ppcrypt.h:9
Definition: ppapi.h:48
Definition: ppload.h:28
Definition: ppheap.h:34
Definition: ppload.h:13
ppobj * sentinel
Definition: ppload.h:15
ppobj * current
Definition: ppload.h:14
Definition: ppapi.h:26
size_t size
Definition: ppapi.h:28
ppbyte * data
Definition: ppapi.h:27
ppname * alterego
Definition: ppapi.h:29
int flags
Definition: ppapi.h:30
Definition: ppapi.h:117
void * any
Definition: ppapi.h:127
ppstring * string
Definition: ppapi.h:122
ppdict * dict
Definition: ppapi.h:124
ppstream * stream
Definition: ppapi.h:125
ppobjtp type
Definition: ppapi.h:129
ppref * ref
Definition: ppapi.h:126
ppname * name
Definition: ppapi.h:121
ppint integer
Definition: ppapi.h:119
ppnum number
Definition: ppapi.h:120
pparray * array
Definition: ppapi.h:123
Definition: ppload.h:20
Definition: ppapi.h:372
Definition: ppapi.h:134
Definition: ppload.h:5
Definition: ppapi.h:73
ppdict * dict
Definition: ppapi.h:74
Definition: ppapi.h:33
size_t size
Definition: ppapi.h:35
ppbyte * data
Definition: ppapi.h:34
ppstring * alterego
Definition: ppapi.h:36
int flags
Definition: ppapi.h:37
Definition: ppxref.h:18
size_t offset
Definition: ppxref.h:26
ppxref * prev
Definition: ppxref.h:24
Definition: ppxref.h:12
ppref * refs
Definition: ppxref.h:15
ppuint first
Definition: ppxref.h:13
ppuint last
Definition: ppxref.h:14
Definition: dvipdfm.c:55
Definition: spc_misc.c:56
Definition: dvips.h:235
Definition: exec.h:58
#define c2
Definition: t1io.c:53
#define c1
Definition: t1io.c:52
static int encode
Definition: t1part.c:199
int number
Definition: t1part.c:207
def_key keyword[6]
Definition: t1part.c:256
#define FILE
Definition: t1stdio.h:34
char * file
Definition: t4ht.c:931
#define xref
Definition: tex2xindy.c:758
#define key
Definition: tex2xindy.c:753
back
Definition: tex4ht.c:3533
op
Definition: tex4ht.c:3129
#define stack
Definition: stack.c:10
#define buffer
Definition: xmlparse.c:611