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)  

lpdfscannerlib.c
Go to the documentation of this file.
1 /* lpdfscannerlib.c
2 
3  Copyright 2013 Taco Hoekwater <taco@luatex.org>
4 
5  This file is part of LuaTeX.
6 
7  LuaTeX is free software; you can redistribute it and/or modify it under
8  the terms of the GNU General Public License as published by the Free
9  Software Foundation; either version 2 of the License, or (at your
10  option) any later version.
11 
12  LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License for more details.
16 
17  You should have received a copy of the GNU General Public License along
18  with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 /*tex
23 
24  The scanner can read from a string or stream. Streams can be given directly as
25  |ppstream| object or as a |pparray| of streams. Here is an example of usage:
26 
27  \starttyping
28  local operatortable = { }
29 
30  operatortable.Do = function(scanner,info)
31  local resources = info.resources
32  if resources then
33  local val = scanner:pop()
34  local name = val[2]
35  local xobject = resources.XObject
36  print(info.space .. "Uses XObject " .. name)
37  local resources = xobject.Resources
38  if resources then
39  local newinfo = {
40  space = info.space .. " ",
41  resources = resources,
42  }
43  pdfscanner.scan(entry, operatortable, newinfo)
44  end
45  end
46  end
47 
48  local function Analyze(filename)
49  local doc = pdfe.open(filename)
50  if doc then
51  local pages = doc.Pages
52  for i=1,#pages do
53  local page = pages[i]
54  local info = {
55  space = " " ,
56  resources = page.Resources,
57  }
58  print("Page " .. i)
59  pdfscanner.scan(page.Contents,operatortable,info)
60  pdfscanner.scan(page.Contents(),operatortable,info)
61  end
62  end
63  end
64 
65  Analyze("foo.pdf")
66  \stoptyping
67 
68 */
69 
70 #include <stdlib.h>
71 #include <stdio.h>
72 #include <stdarg.h>
73 #include <string.h>
74 #include <assert.h>
75 #include <math.h>
76 
77 #include <lua.h>
78 #include <lauxlib.h>
79 #include <lualib.h>
80 
81 #include "pplib.h"
82 
83 #include <lua/luatex-api.h>
84 
85 #define SCANNER "pdfscanner"
86 
87 #define MAXOPERANDS 1000
88 
89 typedef enum {
101 
102 typedef struct Token {
104  double value;
105  char *string;
107 
108 typedef struct ObjectList {
109  struct ObjectList *next;
112 
113 typedef struct scannerdata {
119  const char *buffer;
120  size_t position;
121  size_t size;
124 
125 #define PDFE_METATABLE_ARRAY "luatex.pdfe.array"
126 #define PDFE_METATABLE_STREAM "luatex.pdfe.stream"
127 
128 typedef struct {
129  void *d;
130  /*tex reference to |PdfDocument|, or |NULL| */
131  void *pd;
132  /*tex counter to detect |PDFDoc| change */
133  unsigned long pc;
134 } udstruct;
135 
136 static void clear_operand_stack(scannerdata * self, int from);
137 static Token *_parseToken(scannerdata * self, int c);
138 static void push_token(lua_State * L, scannerdata * self);
139 
140 static void *priv_xmalloc(size_t size)
141 {
142  void *new_mem = (void *) malloc(size);
143  if (new_mem == NULL) {
144  luaL_error(Luas, "no room for <pdfscanned> stream");
145  }
146  return new_mem;
147 }
148 
149 static void *priv_xrealloc(void *old_ptr, size_t size)
150 {
151  void *new_mem = (void *) realloc(old_ptr, size);
152  if (new_mem == NULL) {
153  luaL_error(Luas, "no room for <pdfscanned> stream");
154  }
155  return new_mem;
156 }
157 
158 #define xreallocarray(ptr,type,size) ((type*)priv_xrealloc(ptr,(size+1)*sizeof(type)))
159 
160 #define INITBUFSIZE 64
161 
162 #define define_buffer(a) \
163  char *a = (char *)priv_xmalloc (INITBUFSIZE); \
164  int a##_size = INITBUFSIZE; \
165  int a##index = 0; \
166  memset (a,0,INITBUFSIZE)
167 
168 #define check_overflow(a, wsize) do { \
169  if (wsize >= a##_size) { \
170  int nsize = a##_size + a##_size / 4; \
171  a = (char *) xreallocarray(a, char, (unsigned) nsize); \
172  memset (a+a##_size, 0, a##_size / 4); \
173  a##_size = nsize; \
174  } \
175 } while (0)
176 
177 
179 {
182  lua_setmetatable(L, -2);
183  return a;
184 }
185 
187 {
188  scannerdata *bar;
191  if (bar == NULL)
192  luaL_argerror(L, index, SCANNER " expected");
193  return bar;
194 }
195 
196 static void free_token(Token * token)
197 {
198  if (token->string) {
199  free(token->string);
200  }
201  free(token);
202 }
203 
204 static void clear_operand_stack(scannerdata * self, int from)
205 {
206  int i = self->_nextoperand - 1;
207  while (i >= from) {
208  if (self->_operandstack[i]) {
209  free_token(self->_operandstack[i]);
210  self->_operandstack[i] = NULL;
211  }
212  i--;
213  }
214  self->_nextoperand = from;
215 }
216 
217 static void push_operand(scannerdata * self, Token * token)
218 {
219  if (self->_nextoperand + 1 > MAXOPERANDS) {
220  fprintf(stderr, "out of operand stack space");
221  exit(1);
222  }
223  self->_operandstack[self->_nextoperand++] = token;
224 }
225 
227 {
228  Token *token = (Token *) priv_xmalloc(sizeof(Token));
229  memset(token, 0, sizeof(Token));
230  token->type = c;
231  return token;
232 }
233 
234 static void _nextStream(scannerdata * self)
235 {
236  ObjectList *rover = NULL;
237  if (self->uses_stream && self->buffer != NULL) {
238  if (self->uses_stream) {
239  ppstream_done(self->_stream);
240  } else {
241  free(self->_stream);
242  }
243  }
244  rover = self->_streams;
245  self->_stream = rover->stream;
246  if (self->uses_stream) {
247  self->buffer = (const char *) ppstream_all(self->_stream, &self->size, 1);
248  }
249  self->position = 0;
250  self->_streams = rover->next;
251  free(rover);
252 }
253 
254 static int streamGetChar(scannerdata * self)
255 {
256  int i = EOF;
257  if (self->position < self->size) {
258  const char c = self->buffer[self->position];
259  ++self->position;
260  i = (int) c;
261  }
262  if (i < 0 && self->_streams) {
263  _nextStream(self);
264  i = streamGetChar(self);
265  }
266  return i;
267 }
268 
269 static int streamLookChar(scannerdata * self)
270 {
271  int i = EOF;
272  if (self->position < self->size) {
273  const char c = self->buffer[self->position];
274  /*not |++self->position;| */
275  i = (int) c;
276  }
277  if (i < 0 && self->_streams) {
278  _nextStream(self);
279  i = streamGetChar(self);
280  }
281  return i;
282 }
283 
284 static void streamReset(scannerdata * self)
285 {
286  if (self->uses_stream) {
287  self->buffer = (const char *) ppstream_all(self->_stream, &self->size, 1);
288  }
289  self->position = 0;
290 }
291 
292 static void streamClose(scannerdata * self)
293 {
294  if (self->uses_stream) {
295  ppstream_done(self->_stream);
296  } else {
297  free(self->_stream);
298  }
299  self->buffer = NULL;
300  self->_stream = NULL;
301 }
302 
303 /*tex end of stream interface */
304 
306 {
307  return _parseToken(self, streamGetChar(self));
308 }
309 
310 static Token *_parseString(scannerdata * self, int c)
311 {
312  int level;
313  Token *token = NULL;
315  level = 1;
316  while (1) {
317  c = streamGetChar(self);
318  if (c == '(') {
319  level = level + 1;
320  } else if (c == ')') {
321  level = level - 1;
322  if (level < 1)
323  break;
324  } else if (c == '\\') {
325  int next = streamGetChar(self);
326  if (next == '(' || next == ')' || next == '\\') {
327  c = next;
328  } else if (next == '\n' || next == '\r') {
329  c = '\0';
330  } else if (next == 'n') {
331  c = '\n';
332  } else if (next == 'r') {
333  c = '\r';
334  } else if (next == 't') {
335  c = '\t';
336  } else if (next == 'b') {
337  c = '\b';
338  } else if (next == 'f') {
339  c = '\f';
340  } else if (next >= '0' && next <= '7') {
341  int next2;
342  next = next - '0';
343  next2 = streamLookChar(self);
344  if (next2 >= '0' && next2 <= '7') {
345  int next3;
346  next2 = streamGetChar(self);
347  next2 = next2 - '0';
348  next3 = streamLookChar(self);
349  if (next3 >= '0' && next3 <= '7') {
350  next3 = streamGetChar(self);
351  next3 = next3 - '0';
352  c = (next * 64 + next2 * 8 + next3);
353  } else {
354  c = (next * 8 + next2);
355  }
356  } else {
357  c = next;
358  }
359  } else {
360  c = next;
361  }
362  }
363  check_overflow(found, foundindex);
364  if (c >= 0) {
365  found[foundindex++] = c;
366  }
367  }
369  token->value = foundindex;
370  token->string = found;
371  return token;
372 }
373 
374 static Token *_parseNumber(scannerdata * self, int c)
375 {
376  double value = 0;
378  int isfraction = 0;
379  int isnegative = 0;
380  int i = 0;
381  Token *token = NULL;
382  if (c == '-') {
383  isnegative = 1;
384  c = streamGetChar(self);
385  }
386  if (c == '.') {
387  type = pdf_real;
388  isfraction = 1;
389  } else {
390  value = c - '0';
391  }
392  c = streamLookChar(self);
393  if ((c >= '0' && c <= '9') || c == '.') {
394  c = streamGetChar(self);
395  while (1) {
396  if (c == '.') {
397  type = pdf_real;
398  isfraction = 1;
399  } else {
400  i = c - '0';
401  if (isfraction > 0) {
402  value = value + (i / (pow(10.0, isfraction)));
403  isfraction = isfraction + 1;
404  } else {
405  value = (value * 10) + i;
406  }
407  }
408  c = streamLookChar(self);
409  if (!((c >= '0' && c <= '9') || c == '.'))
410  break;
411  c = streamGetChar(self);
412  }
413  }
414  if (isnegative) {
415  value = -value;
416  }
418  token->value = value;
419  return token;
420 }
421 
422 static Token *_parseName(scannerdata * self, int c)
423 {
424  Token *token = NULL;
426  c = streamGetChar(self);
427  while (1) {
428  check_overflow(found, foundindex);
429  found[foundindex++] = c;
430  c = streamLookChar(self);
431  if (c == ' ' || c == '\n' || c == '\r' || c == '\t' ||
432  c == '/' || c == '[' || c == '(' || c == '<')
433  break;
434  c = streamGetChar(self);
435  }
437  token->string = found;
438  token->value = strlen(found);
439  return token;
440 }
441 
442 #define hexdigit(c) \
443  (c>= '0' && c<= '9') ? (c - '0') : ((c>= 'A' && c<= 'F') ? (c - 'A' + 10) : (c - 'a' + 10))
444 
445 static Token *_parseHexstring(scannerdata * self, int c)
446 {
447  int isodd = 1;
448  int hexval = 0;
449  Token *token = NULL;
451  while (c != '>') {
452  if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
453  if (isodd == 1) {
454  int v = hexdigit(c);
455  hexval = 16 * v;
456  } else {
457  hexval += hexdigit(c);
458  check_overflow(found, foundindex);
459  found[foundindex++] = hexval;
460  }
461  isodd = (isodd == 1 ? 0 : 1);
462  }
463  c = streamGetChar(self);
464  }
466  token->value = foundindex;
467  token->string = found;
468  return token;
469 }
470 
471 #define pdf_isspace(a) (a == '\0' || a == ' ' || a == '\n' || a == '\r' || a == '\t' || a == '\v')
472 
473 /*tex this is rather horrible */
474 
475 static Token *_parseInlineImage(scannerdata * self, int c)
476 {
477  Token *token = NULL;
479  if (c == ' ') {
480  /*tex first space can be ignored */
481  c = streamGetChar(self);
482  }
483  check_overflow(found, foundindex);
484  found[foundindex++] = c;
485  while (1) {
486  c = streamLookChar(self);
487  if (c == 'E'
488  && (found[foundindex - 1] == '\n'
489  || found[foundindex - 1] == '\r')) {
490  c = streamGetChar(self);
491  check_overflow(found, foundindex);
492  found[foundindex++] = c;
493  c = streamLookChar(self);
494  if (c == 'I') {
495  c = streamGetChar(self);
496  check_overflow(found, foundindex);
497  found[foundindex++] = c;
498  c = streamLookChar(self);
499  if (pdf_isspace(c)) {
500  /*tex |I| */
501  found[--foundindex] = '\0';
502  /*tex |E| */
503  found[--foundindex] = '\0';
504  /*tex remove end-of-line before |EI| */
505  if (found[foundindex - 1] == '\n') {
506  found[--foundindex] = '\0';
507  }
508  if (found[foundindex - 1] == '\r') {
509  found[--foundindex] = '\0';
510  }
511  break;
512  } else {
513  c = streamGetChar(self);
514  check_overflow(found, foundindex);
515  found[foundindex++] = c;
516  }
517  } else {
518  c = streamGetChar(self);
519  check_overflow(found, foundindex);
520  found[foundindex++] = c;
521  }
522  } else {
523  c = streamGetChar(self);
524  check_overflow(found, foundindex);
525  found[foundindex++] = c;
526  }
527  }
529  token->value = foundindex;
530  token->string = found;
531  return token;
532 }
533 
534 static Token *_parseOperator(scannerdata * self, int c)
535 {
537  while (1) {
538  check_overflow(found, foundindex);
539  found[foundindex++] = c;
540  c = streamLookChar(self);
541  if ((c < 0) || (c == ' ' || c == '\n' || c == '\r' || c == '\t' ||
542  c == '/' || c == '[' || c == '(' || c == '<'))
543  break;
544  c = streamGetChar(self);
545  }
546  /*tex |print| (found) */
547  if (strcmp(found, "ID") == 0) {
548  self->_ininlineimage = 1;
549  }
550  if (strcmp(found, "false") == 0) {
552  token->value = 0;
553  free(found);
554  return token;
555  } else if (strcmp(found, "true") == 0) {
557  token->value = 1.0;
558  free(found);
559  return token;
560  } else {
562  token->string = found;
563  return token;
564  }
565 }
566 
567 static Token *_parseComment(scannerdata * self, int c)
568 {
569  do {
570  c = streamGetChar(self);
571  } while (c != '\n' && c != '\r' && c != -1);
572  return _parseToken(self, streamGetChar(self));
573 }
574 
575 static Token *_parseLt(scannerdata * self, int c)
576 {
577  c = streamGetChar(self);
578  if (c == '<') {
579  return new_operand(pdf_startdict);
580  } else {
581  return _parseHexstring(self, c);
582  }
583 }
584 
585 static Token *_parseGt(scannerdata * self, int c)
586 {
587  c = streamGetChar(self);
588  if (c == '>') {
589  return new_operand(pdf_stopdict);
590  } else {
591  fprintf(stderr, "stray > in stream");
592  return NULL;
593  }
594 }
595 
596 static Token *_parseError(int c)
597 {
598  fprintf(stderr, "stray %c [%d] in stream", c, c);
599  return NULL;
600 }
601 
602 static Token *_parseStartarray(void)
603 {
604  return new_operand(pdf_startarray);
605 }
606 
607 static Token *_parseStoparray(void)
608 {
609  return new_operand(pdf_stoparray);
610 }
611 
612 static Token *_parseToken(scannerdata * self, int c)
613 {
614  if (self->_ininlineimage == 1) {
615  self->_ininlineimage = 2;
616  return _parseInlineImage(self, c);
617  } else if (self->_ininlineimage == 2) {
618  Token *token = NULL;
619  self->_ininlineimage = 0;
621  token->string = strdup("EI");
622  return token;
623  }
624  if (c < 0)
625  return NULL;
626  switch (c) {
627  case '(':
628  return _parseString(self, c);
629  break;
630  case ')':
631  return _parseError(c);
632  break;
633  case '[':
634  return _parseStartarray();
635  break;
636  case ']':
637  return _parseStoparray();
638  break;
639  case '/':
640  return _parseName(self, c);
641  break;
642  case '<':
643  return _parseLt(self, c);
644  break;
645  case '>':
646  return _parseGt(self, c);
647  break;
648  case '%':
649  return _parseComment(self, c);
650  break;
651  case ' ':
652  case '\r':
653  case '\n':
654  case '\t':
655  return _parseSpace(self);
656  break;
657  case '0':
658  case '1':
659  case '2':
660  case '3':
661  case '4':
662  case '5':
663  case '6':
664  case '7':
665  case '8':
666  case '9':
667  case '-':
668  case '.':
669  return _parseNumber(self, c);
670  break;
671  default:
672  if (c <= 127) {
673  return _parseOperator(self, c);
674  } else {
675  return _parseError(c);
676  }
677  }
678 }
679 
680 static int scanner_scan(lua_State * L)
681 {
682  Token *token;
683  scannerdata *self;
684  if (lua_gettop(L) != 3) {
685  return 0;
686  }
689  self = scanner_push(L);
690  memset(self, 0, sizeof(scannerdata));
691  self->_operandstack = (Token **) priv_xmalloc(MAXOPERANDS * sizeof(Token));
692  memset(self->_operandstack, 0, (MAXOPERANDS * sizeof(Token)));
693  /*tex stack slot 4 = self */
694  self->uses_stream = 1;
695  if (lua_type(L, 1) == LUA_TSTRING) {
696  /*tex
697  We could make a temporary copy on the stack (or in the registry)
698  which saves memory.
699  */
700  char *buf = NULL;
701  const char *s = lua_tolstring(L, 1, &self->size);
702  if (s==NULL){
703  fprintf(stderr,"fatal: cannot convert the token to string.");
704  exit(1);
705  }
706  buf = priv_xmalloc(self->size+1);
707  buf[self->size]='\0';
708  self->uses_stream = 0;
709  memcpy(buf,s,self->size);
710  self->buffer = buf;
711  } else if (lua_type(L, 1) == LUA_TTABLE) {
712  udstruct *uin;
713  void *ud;
714  int i = 1;
715  while (1) {
716  lua_rawgeti(L, 1, i);
717  if (lua_type(L, -1) == LUA_TUSERDATA) {
719  if (ud != NULL) {
720  ObjectList *rover = NULL;
721  ObjectList *item = NULL;
722  uin = (udstruct *) ud;
723  rover = self->_streams;
724  item = (ObjectList *) priv_xmalloc(sizeof(ObjectList));
725  item->stream = ((ppstream *) uin->d);
726  item->next = NULL;
727  if (!rover) {
728  rover = item;
729  self->_streams = rover;
730  } else {
731  while (rover->next)
732  rover = rover->next;
733  rover->next = item;
734  }
735  }
736  } else {
737  ObjectList *rover = self->_streams;
738  self->_stream = rover->stream;
739  self->_streams = rover->next;
740  free(rover);
741  lua_pop(L, 1);
742  break;
743  }
744  lua_pop(L, 1);
745  i++;
746  }
747  } else {
748  udstruct *uin;
749  void *ud;
752  if (ud != NULL) {
753  uin = (udstruct *) ud;
754  self->_stream = ((ppstream *) uin->d);
755  } else {
757  if (ud != NULL) {
758  ObjectList *rover = NULL;
759  pparray *array = NULL;
760  int count;
761  int i;
762  uin = (udstruct *) ud;
763  array = (pparray *) uin->d;
764  count = array->size;
765  for (i = 0; i < count; i++) {
766  ppobj *obj = pparray_at(array, i);
767  if (obj->type == PPSTREAM) {
768  ObjectList *rover = self->_streams;
769  ObjectList *item =
770  (ObjectList *)
771  priv_xmalloc(sizeof(ObjectList));
772  item->stream = obj->stream;
773  item->next = NULL;
774  if (!rover) {
775  rover = item;
776  self->_streams = rover;
777  } else {
778  while (rover->next)
779  rover = rover->next;
780  rover->next = item;
781  }
782  }
783  }
784  rover = self->_streams;
785  self->_stream = rover->stream;
786  self->_streams = rover->next;
787  }
788  }
789  }
790  streamReset(self);
791  token = _parseToken(self, streamGetChar(self));
792  while (token) {
793  if (token->type == pdf_operator) {
794  lua_pushstring(L, token->string);
795  free_token(token);
796  /*tex fetch operator table */
797  lua_rawget(L, 2);
798  if (lua_isfunction(L, -1)) {
799  lua_pushvalue(L, 4);
800  lua_pushvalue(L, 3);
801  (void) lua_call(L, 2, 0);
802  } else {
803  /*tex nil */
804  lua_pop(L, 1);
805  }
806  clear_operand_stack(self, 0);
807  } else {
808  push_operand(self, token);
809  }
810  if (self->uses_stream) {
811  if (!self->_stream) {
812  break;
813  }
814  } else {
815  if (self->buffer == NULL) {
816  break;
817  }
818  }
819  token = _parseToken(self, streamGetChar(self));
820  }
821  /*tex wrap up */
822  if (self->_stream) {
823  streamClose(self);
824  }
825  clear_operand_stack(self, 0);
826  free(self->_operandstack);
827  return 0;
828 }
829 
830 static int scanner_done(lua_State * L)
831 {
832  int c;
833  scannerdata *self = scanner_check(L, 1);
834  while ((c = streamGetChar(self)) >= 0);
835  return 0;
836 }
837 
838 /*tex here are the stack popping functions, and their helpers */
839 
840 static void operandstack_backup(scannerdata * self)
841 {
842  int i = self->_nextoperand - 1;
843  int balance = 0;
844  int backupstart = 0;
845  int backupstop = self->_operandstack[i]->type;
846  if (backupstop == pdf_stopdict) {
847  backupstart = pdf_startdict;
848  } else if (backupstop == pdf_stoparray) {
849  backupstart = pdf_startarray;
850  } else {
851  return;
852  }
853  for (; i >= 0; i--) {
854  if (self->_operandstack[i]->type == backupstop) {
855  balance++;
856  } else if (self->_operandstack[i]->type == backupstart) {
857  balance--;
858  }
859  if (balance == 0) {
860  break;
861  }
862  }
863  self->_nextoperand = i + 1;
864 }
865 
866 static void push_array(lua_State * L, scannerdata * self)
867 {
868  /*tex nesting tracking */
869  int balance = 1;
870  /*tex \LUA\ array index */
871  int index = 1;
872  Token *token = self->_operandstack[self->_nextoperand++];
873  lua_newtable(L);
874  while (token) {
875  if (token->type == pdf_stoparray)
876  balance--;
877  if (token->type == pdf_startarray)
878  balance++;
879  if (!balance) {
880  break;
881  } else {
882  push_token(L, self);
883  lua_rawseti(L, -2, index++);
884  }
885  token = self->_operandstack[self->_nextoperand++];
886  }
887 }
888 
889 
890 static void push_dict(lua_State * L, scannerdata * self)
891 {
892  /*tex nesting tracking */
893  int balance = 1;
894  /*tex toggle between \LUA\ value and \LUA\ key */
895  int needskey = 1;
896  Token *token = self->_operandstack[self->_nextoperand++];
897  lua_newtable(L);
898  while (token) {
899  if (token->type == pdf_stopdict)
900  balance--;
901  if (token->type == pdf_startdict)
902  balance++;
903  if (!balance) {
904  break;
905  } else if (needskey) {
906  lua_pushlstring(L, token->string, token->value);
907  needskey = 0;
908  } else {
909  push_token(L, self);
910  needskey = 1;
911  lua_rawset(L, -3);
912  }
913  token = self->_operandstack[self->_nextoperand++];
914  }
915 }
916 
917 const char *typenames[pdf_stopdict + 1] = {
918  "unknown", "integer", "real", "boolean", "name", "operator",
919  "string", "array", "array", "dict", "dict"
920 };
921 
922 static void push_token(lua_State * L, scannerdata * self)
923 {
924  Token *token = self->_operandstack[self->_nextoperand - 1];
925  lua_createtable(L, 2, 0);
927  lua_rawseti(L, -2, 1);
928  if (token->type == pdf_string || token->type == pdf_name) {
929  lua_pushlstring(L, token->string, token->value);
930  } else if (token->type == pdf_real || token->type == pdf_integer) {
931  /*tex This is an integer or float. */
932  lua_pushnumber(L, token->value);
933  } else if (token->type == pdf_boolean) {
934  lua_pushboolean(L, (int) token->value);
935  } else if (token->type == pdf_startarray) {
936  push_array(L, self);
937  } else if (token->type == pdf_startdict) {
938  push_dict(L, self);
939  } else {
940  lua_pushnil(L);
941  }
942  lua_rawseti(L, -2, 2);
943 }
944 
946 {
947  Token *token = NULL;
948  /*tex this keeps track of how much of the operand stack needs deleting: */
949  int clear = 0;
950  scannerdata *self = scanner_check(L, 1);
951  if (self->_nextoperand == 0) {
952  return 0;
953  }
954  clear = self->_nextoperand - 1;
955  token = self->_operandstack[self->_nextoperand - 1];
956  if (token == NULL || (token->type != token_type)) {
957  return 0;
958  }
959  /*tex
960  The simple cases can be written out directly, but dicts and
961  arrays are better done via the recursive function.
962  */
964  operandstack_backup(self);
965  clear = self->_nextoperand - 1;
966  push_token(L, self);
967  lua_rawgeti(L, -1, 2);
968  } else if (token_type == pdf_real || token_type == pdf_integer) {
969  /*tex the number can be an integer or float */
970  lua_pushnumber(L, token->value);
971  } else if (token_type == pdf_boolean) {
972  lua_pushboolean(L, (int) token->value);
973  } else if (token_type == pdf_name || token_type == pdf_string) {
974  lua_pushlstring(L, token->string, token->value);
975  } else {
976  return 0;
977  }
978  clear_operand_stack(self, clear);
979  return 1;
980 }
981 
983 {
984  Token *token = NULL;
985  /*tex how much of the operand stack needs deleting: */
986  int clear = 0;
987  int token_type;
988  scannerdata *self = scanner_check(L, 1);
989  if (self->_nextoperand == 0) {
990  return 0;
991  }
992  clear = self->_nextoperand - 1;
993  token = self->_operandstack[self->_nextoperand - 1];
994  if (token == NULL) {
995  return 0;
996  }
997  token_type = token->type;
998  /*tex
999  The simple cases can be written out directly, but dicts and
1000  arrays are better done via the recursive function.
1001  */
1003  operandstack_backup(self);
1004  clear = self->_nextoperand - 1;
1005  push_token(L, self);
1006  } else {
1007  push_token(L, self);
1008  }
1009  clear_operand_stack(self, clear);
1010  return 1;
1011 }
1012 
1014 {
1016  return 1;
1018  return 1;
1019  lua_pushnil(L);
1020  return 1;
1021 }
1022 
1024 {
1026  return 1;
1027  lua_pushnil(L);
1028  return 1;
1029 }
1030 
1032 {
1034  return 1;
1035  lua_pushnil(L);
1036  return 1;
1037 }
1038 
1040 {
1042  return 1;
1043  lua_pushnil(L);
1044  return 1;
1045 }
1046 
1048 {
1050  return 1;
1051  lua_pushnil(L);
1052  return 1;
1053 }
1054 
1056 {
1058  return 1;
1059  lua_pushnil(L);
1060  return 1;
1061 }
1062 
1064 {
1065  if (scanner_popanything(L))
1066  return 1;
1067  lua_pushnil(L);
1068  return 1;
1069 }
1070 
1071 static const luaL_Reg scannerlib_meta[] = {
1072  {0, 0}
1073 };
1074 
1075 static const struct luaL_Reg scannerlib_m[] = {
1076  { "done", scanner_done },
1077  { "pop", scanner_popany },
1078  { "popnumber", scanner_popnumber },
1079  { "popname", scanner_popname },
1080  { "popstring", scanner_popstring },
1081  { "poparray", scanner_poparray },
1082  { "popdictionary", scanner_popdictionary },
1083  { "popboolean", scanner_popboolean },
1084  /*tex For old times sake: */
1085  { "popNumber", scanner_popnumber },
1086  { "popName", scanner_popname },
1087  { "popString", scanner_popstring },
1088  { "popArray", scanner_poparray },
1089  { "popDict", scanner_popdictionary },
1090  { "popBool", scanner_popboolean },
1091  /*tex Sentinel: */
1092  { NULL, NULL }
1093 };
1094 
1095 static const luaL_Reg scannerlib[] = {
1096  { "scan", scanner_scan },
1097  /*tex Sentinel: */
1098  { NULL, NULL }
1099 };
1100 
1101 #ifdef _WIN32 /* --ak */
1103 #else /* --ak */
1105 #endif /* _WIN32 --ak */
1106 {
1108  luaL_openlib(L, 0, scannerlib_meta, 0);
1109  lua_pushvalue(L, -1);
1110  lua_setfield(L, -2, "__index");
1112  luaL_openlib(L, "pdfscanner", scannerlib, 0);
1113  return 1;
1114 }
double __cdecl pow(double _X, double _Y)
#define strdup
Definition: Utility.h:167
int level
Definition: afm2pl.c:1694
#define type(a)
Definition: aptex-macros.h:171
#define count(a)
Definition: aptex-macros.h:781
#define next(a)
Definition: aptex-macros.h:924
#define token_type
static int item
Definition: brushtopbm.c:66
#define free(a)
Definition: decNumber.cpp:310
int v
Definition: dviconv.c:10
int strcmp()
Definition: coll.cpp:143
static void
Definition: fpif.c:118
#define s
Definition: afcover.h:80
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define memcpy(d, s, n)
Definition: gsftopk.c:64
static void clear()
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
for(n=0;n< outline->n_points;n++)
Definition: ftbbox.c:494
void exit()
#define EOF
Definition: afmparse.c:59
static int hexval(int c)
Definition: writet1.c:387
#define buf
#define fprintf
Definition: mendex.h:64
#define malloc
Definition: alloca.c:91
static Token * _parseHexstring(scannerdata *self, int c)
static Token * _parseSpace(scannerdata *self)
static Token * _parseStartarray(void)
#define MAXOPERANDS
static void * priv_xrealloc(void *old_ptr, size_t size)
static int scanner_popdictionary(lua_State *L)
static int scanner_done(lua_State *L)
static void streamClose(scannerdata *self)
#define SCANNER
static Token * _parseString(scannerdata *self, int c)
static int scanner_popstring(lua_State *L)
static const luaL_Reg scannerlib_meta[]
static Token * _parseError(int c)
#define pdf_isspace(a)
static int scanner_popname(lua_State *L)
static int scanner_poparray(lua_State *L)
static void push_dict(lua_State *L, scannerdata *self)
static void push_array(lua_State *L, scannerdata *self)
static int scanner_popboolean(lua_State *L)
static void operandstack_backup(scannerdata *self)
pdf_token_type
@ pdf_startarray
@ pdf_name
@ pdf_integer
@ pdf_operator
@ pdf_string
@ pdf_startdict
@ pdf_real
@ pdf_boolean
@ pdf_stopdict
@ pdf_stoparray
static void push_token(lua_State *L, scannerdata *self)
static Token * _parseNumber(scannerdata *self, int c)
struct ObjectList ObjectList
#define PDFE_METATABLE_STREAM
static scannerdata * scanner_check(lua_State *L, int index)
#define check_overflow(a, wsize)
static void clear_operand_stack(scannerdata *self, int from)
int luaopen_pdfscanner(lua_State *L)
static const struct luaL_Reg scannerlib_m[]
static void * priv_xmalloc(size_t size)
static void free_token(Token *token)
static Token * _parseStoparray(void)
static Token * _parseComment(scannerdata *self, int c)
static Token * _parseToken(scannerdata *self, int c)
static const luaL_Reg scannerlib[]
static Token * _parseInlineImage(scannerdata *self, int c)
static int scanner_scan(lua_State *L)
static int scanner_popanything(lua_State *L)
static Token * _parseLt(scannerdata *self, int c)
static void _nextStream(scannerdata *self)
#define define_buffer(a)
static Token * _parseName(scannerdata *self, int c)
static int scanner_popany(lua_State *L)
static Token * _parseOperator(scannerdata *self, int c)
static Token * _parseGt(scannerdata *self, int c)
struct scannerdata scannerdata
static int scanner_popnumber(lua_State *L)
static void push_operand(scannerdata *self, Token *token)
static void streamReset(scannerdata *self)
#define PDFE_METATABLE_ARRAY
static Token * new_operand(pdf_token_type c)
static int streamLookChar(scannerdata *self)
struct Token Token
static int scanner_popsingular(lua_State *L, int token_type)
const char * typenames[pdf_stopdict+1]
#define hexdigit(c)
static scannerdata * scanner_push(lua_State *L)
static int streamGetChar(scannerdata *self)
token_type
Definition: scripting.h:54
#define realloc
Definition: glob.c:206
static lua_State * Luas[1]
Definition: mfluac.c:37
union value value
Definition: obx.h:44
static int size
Definition: ppmlabel.c:24
bstring c int memset(void *s, int c, int length)
void ppstream_done(ppstream *stream)
Definition: ppstream.c:241
uint8_t * ppstream_all(ppstream *stream, size_t *size, int decode)
Definition: ppstream.c:229
@ PPSTREAM
Definition: ppapi.h:111
#define pparray_at(array, index)
Definition: ppapi.h:221
void() luaL_openlib(lua_State *L, const char *libname, const luaL_Reg *l, int nup)
Definition: lib_aux.c:128
int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.c:846
int lua_gettop(lua_State *L)
Definition: lapi.c:167
void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.c:777
void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.c:458
void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.c:237
int lua_rawget(lua_State *L, int idx)
Definition: lapi.c:647
int lua_type(lua_State *L, int idx)
Definition: lapi.c:251
void lua_pushnil(lua_State *L)
Definition: lapi.c:450
const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.c:491
const char * lua_tolstring(lua_State *L, int idx, size_t *len)
Definition: lapi.c:373
void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.c:684
int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.c:658
void lua_rawset(lua_State *L, int idx)
Definition: lapi.c:801
void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.c:817
void lua_pushboolean(lua_State *L, int b)
Definition: lapi.c:557
void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.c:1184
const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.c:479
int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.c:164
int luaL_error(lua_State *L, const char *fmt,...)
Definition: lauxlib.c:223
int luaL_newmetatable(lua_State *L, const char *tname)
Definition: lauxlib.c:299
void luaL_checktype(lua_State *L, int arg, int t)
Definition: lauxlib.c:378
void * luaL_checkudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.c:333
#define luaL_getmetatable(L, n)
Definition: lauxlib.h:135
#define LUA_TTABLE
Definition: lua.h:68
#define LUA_TSTRING
Definition: lua.h:67
#define lua_isfunction(L, n)
Definition: lua.h:351
#define LUA_TUSERDATA
Definition: lua.h:70
#define lua_call(L, n, r)
Definition: lua.h:273
#define lua_newtable(L)
Definition: lua.h:345
#define lua_pop(L, n)
Definition: lua.h:343
#define LUALIB_API
Definition: luaconf.h:265
static _ts_NODE_t * balance(_ts_NODE_t **, _ts_NODE_t *, int)
Definition: sh12.c:338
token
Definition: strexpr.c:17
struct ObjectList * next
ppstream * stream
Definition: llex.h:50
double value
char * string
pdf_token_type type
Definition: mendex.h:20
Definition: ppapi.h:43
Definition: ppapi.h:117
ppstream * stream
Definition: ppapi.h:125
ppobjtp type
Definition: ppapi.h:129
Definition: ppapi.h:73
ppstream * _stream
ObjectList * _streams
const char * buffer
Token ** _operandstack
Definition: parser.c:43
enum etoken type
Definition: parser.c:44
unsigned long pc
*job_name strlen((char *) job_name) - 4)
found
Definition: tex4ht.c:5000
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
halfword rover
Definition: texnodes.c:45
@ L
Definition: ubidiimp.h:45
Definition: obx.h:51