diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2013-03-21 09:16:59 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2013-03-21 09:16:59 +0000 |
commit | 388463b9fa865c3b2311508c41647b0f3c532031 (patch) | |
tree | 1cdfbf5552d0783ecbcc52017e49567e5042af33 /Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc | |
parent | abd0b00a4e8c1ac6f5b20c7474d70ef579129991 (diff) |
Import MetaPost 1.800 and LuaTeX beta-0.75.0 from LuaTeX repository r4604
git-svn-id: svn://tug.org/texlive/trunk@29453 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc | 952 |
1 files changed, 952 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc b/Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc new file mode 100644 index 00000000000..2b36d106234 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc @@ -0,0 +1,952 @@ +/* lcallbacklib.c + + Copyright 2012 Taco Hoekwater <taco@luatex.org> + + This file is part of LuaTeX. + + LuaTeX is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + LuaTeX is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU General Public License along + with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ + +# include <stdlib.h> +# include <stdio.h> +# include <stdarg.h> +# include <string.h> +# include <assert.h> +# include <math.h> + +extern "C" { +# include <lua52/lua.h> +# include <lua52/lauxlib.h> +# include <lua52/lualib.h> +} + +# include <poppler/poppler-config.h> +# include <goo/GooString.h> +# include <goo/gmem.h> +# include <goo/gfile.h> +# include <Object.h> +# include <Stream.h> +# include <Gfx.h> +# include <Annot.h> +# include <Array.h> +# include <Dict.h> +# include <XRef.h> +# include <Catalog.h> +# include <Link.h> +# include <Page.h> +# include <GfxFont.h> +# include <PDFDoc.h> +# include <GlobalParams.h> +# include <Error.h> + +# include <lua/luatex-api.h> + +static const char _svn_version[] = + "$Id: lpdfscannerlib.cc 4524 2012-12-20 15:38:02Z taco $ $URL: http://foundry.supelec.fr/svn/luatex/trunk/source/texk/web2c/luatexdir/lua/lpdfscannerlib.cc $"; + +#define SCANNER "pdfscanner" + +#define MAXOPERANDS 1000 + +typedef enum { + pdf_integer = 1, + pdf_real, + pdf_boolean, + pdf_name, + pdf_operator, + pdf_string, + pdf_startarray, + pdf_stoparray, + pdf_startdict, + pdf_stopdict, +} pdf_token_type ; + + +typedef struct Token { + pdf_token_type type; + double value; + const char *string; +} Token; + +typedef struct ObjectList { + struct ObjectList *next; + Object *stream; +} ObjectList; + +typedef struct scannerdata { + int _ininlineimage; + int _nextoperand; + Token ** _operandstack; + Object * _stream; + ObjectList * _streams; +} scannerdata; + +typedef enum { ALLOC_POPPLER, ALLOC_LEPDF } alloctype; + +#define M_Object "Object" +#define M_Stream "Stream" + +typedef struct { + void *d; + alloctype atype; // was it allocated by poppler or the lepdflib.cc? + void *pd; // reference to PdfDocument, or NULL + unsigned long pc; // counter to detect PDFDoc change +} udstruct; + +static void clear_operand_stack (scannerdata *self, int from); +static Token *_parseToken (scannerdata *self, int c); +static void push_token (lua_State *L, scannerdata *self); + +void *xmalloc (size_t size) +{ + void *new_mem = (void *)malloc(size); + if (new_mem == NULL) { + fprintf(stderr, "fatal: memory exhausted (xmalloc of %lu bytes).\n", (unsigned long)size); + exit(1); + } + return new_mem; +} + +void *xrealloc (void *old_ptr, size_t size) +{ + void *new_mem = (void *)realloc(old_ptr, size); + if (new_mem == NULL) { + fprintf(stderr,"fatal: memory exhausted (realloc of %lu bytes).\n", (unsigned long)size); + exit(EXIT_FAILURE); + } + return new_mem; +} + +#define xreallocarray(ptr,type,size) ((type*)xrealloc(ptr,(size+1)*sizeof(type))) + +#define INITBUFSIZE 64 + +#define define_buffer(a) \ + char *a = (char *)xmalloc (INITBUFSIZE); \ + int a##_size = INITBUFSIZE; \ + int a##index = 0; \ + memset (a,0,INITBUFSIZE) + +#define check_overflow(a, wsize) do { \ + if (wsize >= a##_size) { \ + int nsize = a##_size + a##_size / 4; \ + a = (char *) xreallocarray(a, char, (unsigned) nsize); \ + memset (a+a##_size, 0, a##_size / 4); \ + a##_size = nsize; \ + } \ + } while (0) + + +static scannerdata * scanner_push(lua_State * L) +{ + scannerdata *a = (scannerdata *)lua_newuserdata(L, sizeof(scannerdata)); + luaL_getmetatable(L, SCANNER); + lua_setmetatable(L, -2); + return a; +} + +static scannerdata *scanner_check (lua_State *L, int index) +{ + scannerdata *bar; + luaL_checktype(L, index, LUA_TUSERDATA); + bar = (scannerdata *)luaL_checkudata(L, index, SCANNER); + return bar; +} + +static void free_token (Token *token) +{ + if (token->string) { + free((void *)token->string); + } + free(token); +} + +static void clear_operand_stack (scannerdata *self, int from) +{ + int i = self->_nextoperand-1; + while (i>=from) { + if (self->_operandstack[i]) { + free_token(self->_operandstack[i]); + self->_operandstack[i] = NULL; + } + i--; + } + self->_nextoperand = from; +} + +static void push_operand (scannerdata *self, Token *token) +{ + if (self->_nextoperand+1> MAXOPERANDS) { + fprintf(stderr, "out of operand stack space"); + exit(1); + } + self->_operandstack[self->_nextoperand++] = token; +} + +static Token * new_operand (pdf_token_type c) +{ + Token *token = (Token *)xmalloc(sizeof(Token)); + memset (token, 0, sizeof(Token)); + token->type = c; + return token; +} + +static void _nextStream (scannerdata *self) { + self->_stream->streamClose(); + ObjectList *rover = self->_streams; + self->_stream = rover->stream; + self->_stream->streamReset(); + self->_streams = rover->next; + free(rover); +} + +static int streamGetChar (scannerdata *self) { + int i = self->_stream->streamGetChar(); + if (i<0 && self->_streams) { + _nextStream(self); + i = streamGetChar(self); + } + return i; +} + +static int streamLookChar (scannerdata *self) { + int i= self->_stream->streamLookChar(); + if (i<0 && self->_streams) { + _nextStream(self); + i = streamLookChar(self); + } + return i; +} + +static Token * _parseSpace (scannerdata *self) +{ + return _parseToken (self,streamGetChar(self)); +} + +static Token * _parseString (scannerdata *self, int c) +{ + // local token = {type = pdf_string,value = ''} + define_buffer(found); + int level = 1; + while (1) { + c = streamGetChar(self); + if (c == '(') { + level = level + 1 ; + } + if (c == ')') { + level = level - 1 ; + if (level < 1) break; + } + if (c == '\\') { + int next = streamGetChar(self); + if (next == '(' || next == ')' || next == '\\') { + c = next; + } else if (next == '\n' || next == '\r') { + c = '\0'; + } else if (next == 'n') { + c = '\n'; + } else if (next == 'r') { + c = '\r'; + } else if (next == 't') { + c = '\t'; + } else if (next == 'b') { + c = '\b'; + } else if (next == 'f') { + c = '\f'; + } else if (next >= '0' && next <= '7') { + next = next - '0'; + int next2 = streamLookChar(self); + if (next2 >= '0' && next2 <= '7') { + next2 = streamGetChar(self); + next2 = next2 - '0'; + int next3 = streamLookChar(self); + if (next3 >= '0' && next3 <= '7') { + next3 = streamGetChar(self); + next3 = next3 - '0'; + c = (next*64+next2*8+next3); + } else { + c = (next*8+next2); + } + } else { + c = next; + } + } else { + c = next; + } + } + check_overflow(found,foundindex); + if (c>=0) { + found[foundindex++] = c; + } + } + Token *token = new_operand(pdf_string); + token->value = foundindex; + token->string = found; + return token; +} + + +static Token * _parseNumber (scannerdata *self, int c) +{ + double value = 0; + pdf_token_type type = pdf_integer; + int isfraction = 0; + int isnegative = 0; + int i = 0; + if (c == '-') { + isnegative = 1; + c = streamGetChar(self); + } + if (c == '.') { + type = pdf_real; + isfraction = 1; + } else { + value = c - '0'; + } + c = streamLookChar(self); + if ((c>= '0'&& c<= '9') || c == '.') { + c = streamGetChar(self); + while (1) { + if (c == '.') { + type = pdf_real; + isfraction = 1; + } else { + i = c - '0'; + if (isfraction>0) { + value = value + (i/(pow(10.0,isfraction))); + isfraction = isfraction + 1; + } else { + value = (value * 10) + i; + } + } + c = streamLookChar(self); + if (! ((c>= '0' && c<= '9') || c == '.')) break ; + c = streamGetChar(self); + } + } + if (isnegative) { + value = -value; + } + Token *token = new_operand(type); + token->value = value; + return token; +} + + +static Token *_parseName (scannerdata *self, int c) +{ + define_buffer(found); + c = streamGetChar(self); + while (1) { + check_overflow(found,foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if (c == ' ' || c == '\n' || c == '\r' || c == '\t' || + c == '/' || c == '[' || c == '(' || c == '<') break ; + c = streamGetChar(self); + } + Token *token = new_operand(pdf_name); + token->string = found; + token->value = strlen(found); + return token; +} + +#define hexdigit(c) \ + (c>= '0' && c<= '9') ? (c - '0') : ((c>= 'A' && c<= 'F') ? (c - 'A' + 10) : (c - 'a' + 10)) + +static Token *_parseHexstring (scannerdata *self, int c) +{ + int isodd = 1; + int hexval = 0; + define_buffer(found); + while (1) { + if ((c>= '0' && c<= '9') || + (c>= 'A' && c<= 'F') || + (c>= 'a' && c<= 'f')) { + if (isodd==1) { + int v = hexdigit(c); + hexval = 16 * v; + } else { + hexval += hexdigit(c); + check_overflow(found,foundindex); + found[foundindex++] = hexval; + } + isodd = (isodd==1 ? 0 : 1); + } + c = streamGetChar(self); + if (c == '>') break; + } + Token *token = new_operand(pdf_string); + token->value = foundindex; + token->string = found; + return token; +} + + +// -- this is rather horrible +static Token *_parseInlineImage (scannerdata *self, int c) +{ + define_buffer(found); + if (c == ' ') { // first space can be ignored + c = streamGetChar(self); + } + check_overflow(found, foundindex); + found[foundindex++] = c; + while (1) { + c = streamLookChar(self); + while (c == ' ' || c == '\n' || c == '\r' || c == '\t') { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + } + if (c == 'E') { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if (c == 'I') { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if (c == ' ' || c == '\n' || c == '\r' || c == '\t') { + found[--foundindex] = '\0'; + found[--foundindex] = '\0'; + /* remove optional end-of-line */ + if (found[foundindex-1] == '\n') { + found[--foundindex] = '\0'; + } + if (found[foundindex-1] == '\r') { + found[--foundindex] = '\0'; + } + break; + } + } else { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + } + } else { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + } + } + Token *token = new_operand(pdf_string); + token->value = foundindex; + token->string = found; + return token; +} + +static Token *_parseOperator (scannerdata *self, int c) +{ + define_buffer(found); + while (1) { + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if ((c<0) || (c == ' ' || c == '\n' || c == '\r' || c == '\t' || + c == '/' || c == '[' || c == '(' || c == '<')) + break ; + c = streamGetChar(self); + } + // print (found) + if (strcmp(found, "ID") == 0) { + self->_ininlineimage = 1; + } + if (strcmp(found,"false") == 0) { + Token *token = new_operand(pdf_boolean); + token->value = 0; + return token; + } else if (strcmp(found,"true") == 0) { + Token *token = new_operand(pdf_boolean); + token->value = 1.0; + return token; + } else { + Token *token = new_operand(pdf_operator); + token->string = found; + return token; + } +} + + +static Token * _parseComment (scannerdata *self, int c) +{ + do { + c = streamGetChar(self); + } while (c != '\n' && c != '\r'); + return _parseToken(self,streamGetChar(self)); +} + +static Token *_parseLt (scannerdata *self, int c) +{ + c = streamGetChar(self); + if (c == '<') { + return new_operand(pdf_startdict); + } else { + return _parseHexstring(self,c); + } +} + +static Token * _parseGt (scannerdata *self, int c) +{ + c = streamGetChar(self); + if (c== '>') { + return new_operand(pdf_stopdict); + } else { + fprintf(stderr,"stray > in stream"); + return NULL; + } +} + + +static Token *_parseError (int c) +{ + fprintf(stderr, "stray %c [%d] in stream", c, c); + return NULL; +} + +static Token *_parseStartarray () +{ + return new_operand (pdf_startarray); +} + +static Token *_parseStoparray () +{ + return new_operand (pdf_stoparray); +} + + +static Token *_parseToken (scannerdata *self, int c) +{ + if (self->_ininlineimage==1) { + self->_ininlineimage = 2; + return _parseInlineImage(self,c); + } else if (self->_ininlineimage==2) { + self->_ininlineimage = 0; + Token *token = new_operand(pdf_operator); + token->string = strdup("EI"); + return token; + } + if (c<0) return NULL ; + switch (c) { + case '(': return _parseString(self,c); break; + case ')': return _parseError(c); break; + case '[': return _parseStartarray(); break; + case ']': return _parseStoparray(); break; + case '/': return _parseName(self,c); break; + case '<': return _parseLt(self,c); break; + case '>': return _parseGt(self,c); break; + case '%': return _parseComment(self,c); break; + case ' ': + case '\r': + case '\n': + case '\t': + return _parseSpace(self); break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '.': + return _parseNumber(self,c); break; + default: + if (c<=127) { + return _parseOperator(self,c); + } else { + return _parseError(c); + } + } +} + +static int scanner_scan(lua_State * L) +{ + Token *token; + scannerdata *self; + if (lua_gettop(L) != 3) { + return 0; + } + luaL_checktype(L, 2, LUA_TTABLE); + luaL_checktype(L, 3, LUA_TTABLE); + self = scanner_push(L); + memset(self,0,sizeof(scannerdata)); + self->_operandstack = (Token **)xmalloc (MAXOPERANDS * sizeof (Token)); + memset (self->_operandstack,0,(MAXOPERANDS * sizeof (Token))); + // 4 = self + if (lua_type(L,1)== LUA_TTABLE) { + udstruct *uin; + int i = 1; + while (1) { + lua_rawgeti(L,1,i); + if (lua_type(L,-1)== LUA_TUSERDATA) { + uin = (udstruct *) luaL_checkudata(L, -1, M_Object); + if (((Object *) uin->d)->isStream()) { + ObjectList *rover = self->_streams; + ObjectList *item = (ObjectList *)xmalloc (sizeof(ObjectList)); + item->stream = ((Object *) uin->d); + item->next = NULL; + if (!rover) { + rover = item; + self->_streams = rover; + } else { + while (rover->next) + rover = rover->next; + rover->next = item; + } + } + } else { // done + ObjectList *rover = self->_streams; + self->_stream = rover->stream; + self->_streams = rover->next; + free(rover); + lua_pop(L,1); + break; + } + lua_pop(L,1); + i++; + } + + } else { + udstruct *uin; + luaL_checktype(L, 1, LUA_TUSERDATA); + uin = (udstruct *) luaL_checkudata(L, 1, M_Object); + if (((Object *) uin->d)->isStream()) { + self->_stream = ((Object *) uin->d); + } else if (((Object *) uin->d)->isArray()) { + Array *arrayref = ((Object *) uin->d)->getArray(); + int count = arrayref->getLength(); + int i; + for (i=0;i<count;i++) { + Object *val = new Object(); + arrayref->get(i, val); + if (val->isStream()) { + ObjectList *rover = self->_streams; + ObjectList *item = (ObjectList *)xmalloc (sizeof(ObjectList)); + item->stream = val; + item->next = NULL; + if (!rover) { + rover = item; + self->_streams = rover; + } else { + while (rover->next) + rover = rover->next; + rover->next = item; + } + } + } + ObjectList *rover = self->_streams; + self->_stream = rover->stream; + self->_streams = rover->next; + } + + } + assert (lua_gettop(L) == 4); + self->_stream->streamReset(); + token = _parseToken(self,streamGetChar(self)); + while (token) { + if (token->type == pdf_operator) { + lua_pushstring(L, token->string); + free_token(token); + lua_rawget(L,2); // operator table + if (lua_isfunction(L,-1)) { + lua_pushvalue(L,4); + lua_pushvalue(L,3); + (void)lua_call(L,2,0); + } else { + lua_pop(L,1); // nil + } + clear_operand_stack(self,0); + } else { + push_operand(self, token); + } + if (!self->_stream) { + break; + } + token = _parseToken(self,streamGetChar(self)); + } + /* wrap up */ + if (self->_stream) { + self->_stream->streamClose(); + self->_stream = NULL; + } + clear_operand_stack(self,0); + free(self->_operandstack); + return 0; +} + +static int scanner_done(lua_State * L) +{ + int c; + scannerdata *self = scanner_check(L,1); + while ((c=streamGetChar(self))>=0) + ; + return 0; +} + +// here are the stack popping functions, and their helpers + +static void operandstack_backup (scannerdata *self) { + int i = self->_nextoperand-1; + int balance = 0; + int backupstart = 0; + int backupstop = self->_operandstack[i]->type; + if (backupstop == pdf_stopdict) { + backupstart = pdf_startdict; + } else if (backupstop == pdf_stoparray) { + backupstart = pdf_startarray; + } else { + return; + } + for (;i>=0;i--) { + if (self->_operandstack[i]->type == backupstop) { + balance++; + } else if (self->_operandstack[i]->type == backupstart) { + balance--; + } + if (balance==0) { + break; + } + } + self->_nextoperand = i+1; +} + +static void push_array (lua_State *L, scannerdata *self) +{ + int balance = 1; // nesting tracking + int index = 1; // lua array index + Token *token = self->_operandstack[self->_nextoperand++]; + lua_newtable(L); + while (token) { + if (token->type == pdf_stoparray) + balance --; + if (token->type == pdf_startarray) + balance ++; + if (!balance) { + break; + } else { + push_token(L,self); + lua_rawseti(L,-2, index++); + } + token = self->_operandstack[self->_nextoperand++]; + } +} + + +static void push_dict (lua_State *L, scannerdata *self) +{ + int balance = 1; // nesting tracking + int needskey = 1; // toggle between lua value and lua key + Token *token = self->_operandstack[self->_nextoperand++]; + lua_newtable(L); + while (token) { + if (token->type == pdf_stopdict) + balance --; + if (token->type == pdf_startdict) + balance ++; + if (!balance) { + break; + } else { + if (needskey) { + lua_pushlstring(L, token->string, token->value); + needskey = 0; + } else { + push_token(L,self); + needskey = 1; + lua_rawset(L,-3); + } + } + token = self->_operandstack[self->_nextoperand++]; + } +} + +const char *typenames[pdf_stopdict+1] = + { "unknown", "integer", "real", "boolean", "name", "operator", + "string", "array", "array", "dict", "dict" }; + +static void push_token (lua_State *L, scannerdata *self) +{ + Token *token = self->_operandstack[self->_nextoperand-1]; + lua_createtable(L,2,0); + lua_pushstring (L, typenames[token->type]); + lua_rawseti(L,-2,1); + if (token->type == pdf_string || token->type == pdf_name) { + lua_pushlstring(L, token->string, token->value); + } else if (token->type == pdf_real || token->type == pdf_integer) { + lua_pushnumber(L, token->value); + } else if (token->type == pdf_boolean) { + lua_pushboolean(L, (int)token->value); + } else if (token->type == pdf_startarray) { + push_array(L, self); + } else if (token->type == pdf_startdict) { + push_dict(L, self); + } else { + lua_pushnil(L); + } + lua_rawseti(L,-2, 2); +} + +static int scanner_popsingular (lua_State * L, int token_type) { + int clear = 0; // how much of the operand stack needs deleting + scannerdata *self = scanner_check(L,1); + if (self->_nextoperand==0) { + return 0; + } + clear = self->_nextoperand-1; + Token *token = self->_operandstack[self->_nextoperand-1]; + if (token ==NULL || (token->type != token_type )) { + return 0; + } + // the simple cases can be written out directly, but dicts and + // arrays are better done via the recursive function + if (token_type == pdf_stoparray || token_type == pdf_stopdict) { + operandstack_backup(self); + clear = self->_nextoperand-1; + push_token(L, self); + lua_rawgeti(L,-1,2); + } else if (token_type == pdf_real || token_type == pdf_integer) { + lua_pushnumber(L, token->value); + } else if (token_type == pdf_boolean) { + lua_pushboolean(L,(int)token->value); + } else if (token_type == pdf_name || token_type == pdf_string) { + lua_pushlstring(L, token->string, token->value); + } else { + return 0; + } + clear_operand_stack(self,clear); + return 1; +} + +static int scanner_popanything (lua_State * L) { + int clear = 0; // how much of the operand stack needs deleting + scannerdata *self = scanner_check(L,1); + if (self->_nextoperand==0) { + return 0; + } + clear = self->_nextoperand-1; + Token *token = self->_operandstack[self->_nextoperand-1]; + if (token ==NULL) { + return 0; + } + int token_type = token->type; + // the simple cases can be written out directly, but dicts and + // arrays are better done via the recursive function + if (token_type == pdf_stoparray || token_type == pdf_stopdict) { + operandstack_backup(self); + clear = self->_nextoperand-1; + push_token(L, self); + } else { + push_token(L, self); + } + clear_operand_stack(self,clear); + return 1; +} + + +static int scanner_popnumber(lua_State * L) +{ + if(scanner_popsingular(L,pdf_real)) + return 1; + if (scanner_popsingular(L,pdf_integer)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popboolean(lua_State * L) +{ + if(scanner_popsingular(L,pdf_boolean)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popstring(lua_State * L) +{ + if (scanner_popsingular(L,pdf_string)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popname(lua_State * L) +{ + if (scanner_popsingular(L,pdf_name)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_poparray(lua_State * L) +{ + if (scanner_popsingular(L,pdf_stoparray)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popdictionary(lua_State * L) +{ + if (scanner_popsingular(L,pdf_stopdict)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popany(lua_State * L) +{ + if (scanner_popanything(L)) + return 1; + lua_pushnil(L); + return 1; +} + +static const luaL_Reg scannerlib_meta[] = { + {0, 0} +}; + +static const struct luaL_Reg scannerlib_m[] = { + {"done", scanner_done}, + {"popNumber", scanner_popnumber}, + {"popName", scanner_popname}, + {"popString", scanner_popstring}, + {"popArray", scanner_poparray}, + {"popDict", scanner_popdictionary}, + {"popBool", scanner_popboolean}, + {"pop", scanner_popany}, + {NULL, NULL} /* sentinel */ +}; + + +static const luaL_Reg scannerlib[] = { + {"scan", scanner_scan}, + {NULL, NULL} +}; + +LUALIB_API int luaopen_pdfscanner(lua_State * L) +{ + luaL_newmetatable(L, SCANNER); + luaL_openlib(L, 0, scannerlib_meta, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_register(L, NULL, scannerlib_m); + luaL_register(L, "pdfscanner", scannerlib); + return 1; +} + |