pdf-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pdf-devel] [PATCH] Token reader, with new API


From: Michael Gold
Subject: [pdf-devel] [PATCH] Token reader, with new API
Date: Wed, 20 May 2009 01:35:11 -0400
User-agent: Mutt/1.5.18 (2008-05-17)

Here's a patch to add a token reader based on the documented API.
I've also added and documented a pdf_token_equal_p function.

The code hasn't changed much since the last tokeniser patch I sent,
apart from being restructured for the new API.

-- Michael
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: address@hidden
# target_branch: file:///home/michael/src/%2Blocal/gnupdf/trunk/
# testament_sha1: 2b52a6d550745f1e76c44bb24c5ce08ea05be6e8
# timestamp: 2009-05-20 01:28:41 -0400
# base_revision_id: address@hidden
# 
# Begin patch
=== modified file 'AUTHORS'
--- AUTHORS     2009-05-19 18:03:37 +0000
+++ AUTHORS     2009-05-20 04:35:27 +0000
@@ -261,8 +261,12 @@
   torture/test-obj_dupequality.c torture/test-rectangle.c
   torture/test-stm_openclose.c
 
-Michael Gold: changed src/Makefile.am utils/Makefile.am
-  torture/unit/Makefile.am src/gnupdf.texi
+Michael Gold: wrote src/base/pdf-token-obj.c src/base/pdf-token-obj.h
+  src/base/pdf-token-reader.c src/base/pdf-token-reader.h
+  torture/unit/base/token/pdf-token-read.c
+  torture/unit/base/token/tsuite-token.c utils/toktest.c
+and changed src/Makefile.am utils/Makefile.am torture/unit/Makefile.am
+  doc/gnupdf.texi src/base/pdf-error.h torture/unit/runtests.c
 
 Yang Chang Hua: wrote src/base/pdf-stm-f-dct.h
   src/base/pdf-stm-f-dct.c

=== modified file 'ChangeLog'
--- ChangeLog   2009-05-19 20:17:49 +0000
+++ ChangeLog   2009-05-20 04:35:27 +0000
@@ -1,3 +1,33 @@
+2009-05-20  Michael Gold  <address@hidden>
+
+       Implement the token reader API.
+
+       * src/base/pdf-token-obj.c: New file, based on src/object/pdf-obj.c
+
+       * src/base/pdf-token-obj.h: Likewise
+
+       * src/base/pdf-token-reader.c: New file
+
+       * src/base/pdf-token-reader.h: New file
+
+       * src/base/pdf-error.h: Add PDF_EBADFILE, PDF_EIMPLLIMIT error codes
+
+       * src/Makefile.am: Add token reader support
+
+       * doc/gnupdf.text: Document pdf_token_equal_p
+
+       * torture/unit/base/token/pdf-token-read.c: New file
+
+       * torture/unit/base/token/tsuite-token.c: New file
+
+       * torture/unit/Makefile.am: Add token reader testcases
+
+       * torture/unit/runtests.c: Likewise
+
+       * utils/toktest.c: New file
+
+       * utils/Makefile.am: Build toktest
+
 2009-05-19  David Vazquez  <address@hidden>
 
        * src/base/pdf-crypt.h: Use STATIC_INLINE indeed of EXTERN_INLINE.

=== modified file 'doc/gnupdf.texi'
--- doc/gnupdf.texi     2009-05-19 18:03:37 +0000
+++ doc/gnupdf.texi     2009-05-20 04:35:27 +0000
@@ -10498,8 +10498,29 @@
 @end table
 @end deftypefun
 
address@hidden TODO: pdf_bool_t pdf_token_equal_p (pdf_token_t token1, 
pdf_token_t token2);
address@hidden          -- if needed
address@hidden pdf_bool_t pdf_token_equal_p (const pdf_token_t @var{token1}, 
const pdf_token_t @var{token2})
+
+Determines whether the given tokens are equivalent.
+
address@hidden @strong
address@hidden Parameters
address@hidden @var
address@hidden token1
+A token.
address@hidden token2
+Another token.
address@hidden table
address@hidden Returns
+A boolean value:
address@hidden @code
address@hidden PDF_TRUE
+The given tokens are equal.
address@hidden PDF_FALSE
+The tokens are not equal.
address@hidden table
address@hidden table
+
address@hidden deftypefun
 
 @deftypefun pdf_i32_t pdf_token_get_integer_value (const pdf_token_t 
@var{token})
 

=== modified file 'src/Makefile.am'
--- src/Makefile.am     2009-05-05 13:58:10 +0000
+++ src/Makefile.am     2009-05-20 04:50:13 +0000
@@ -82,6 +82,9 @@
 FP_MODULE_SOURCES = base/pdf-fp.h base/pdf-fp.c \
                     base/pdf-fp-func.h base/pdf-fp-func.c
 
+TOKEN_MODULE_SOURCES = base/pdf-token-obj.c base/pdf-token-obj.h \
+                       base/pdf-token-reader.c base/pdf-token-reader.h
+
 BASE_LAYER_SOURCES = base/pdf-base.c base/pdf-base.h \
                      $(ALLOC_MODULE_SOURCES) \
                      $(TYPES_MODULE_SOURCES) \
@@ -93,7 +96,8 @@
                      $(TEXT_MODULE_SOURCES) \
                      $(HASH_MODULE_SOURCES) \
                      $(TIME_MODULE_SOURCES) \
-                     $(CRYPT_MODULE_SOURCES)
+                     $(CRYPT_MODULE_SOURCES) \
+                     $(TOKEN_MODULE_SOURCES)
 
 
 # Library sources
@@ -136,7 +140,9 @@
               base/pdf-stm.h \
               base/pdf-hash-helper.h \
               base/pdf-crypt.h \
-              base/pdf-fp-func.h
+              base/pdf-fp-func.h \
+              base/pdf-token-obj.h \
+              base/pdf-token-reader.h
 
 pdf.h : $(PUBLIC_HDRS)
        chmod +x $(top_builddir)/src/extract-public-hdr

=== modified file 'src/base/pdf-error.h'
--- src/base/pdf-error.h        2009-05-11 14:47:49 +0000
+++ src/base/pdf-error.h        2009-05-19 18:19:15 +0000
@@ -144,7 +144,9 @@
   ERROR_ENTRY (PDF_ETYPE0,      "/FunctionType 0: Error"),            \
   ERROR_ENTRY (PDF_ETYPE2,      "/FunctionType 2: Error"),            \
   ERROR_ENTRY (PDF_ETYPE3,      "/FunctionType 3: Error"),            \
-  ERROR_ENTRY (PDF_ETYPE4,      "/FunctionType 4: Error")
+  ERROR_ENTRY (PDF_ETYPE4,      "/FunctionType 4: Error"),            \
+  ERROR_ENTRY (PDF_EBADFILE,    "file violates PDF specifications"),  \
+  ERROR_ENTRY (PDF_EIMPLLIMIT,  "implementation limit exceeded")
 
 #define ERROR_ENTRY(id,string) id
 enum pdf_status_e

=== added file 'src/base/pdf-token-obj.c'
--- src/base/pdf-token-obj.c    1970-01-01 00:00:00 +0000
+++ src/base/pdf-token-obj.c    2009-05-20 05:19:37 +0000
@@ -0,0 +1,405 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 04:50:13 mgold"
+ *
+ *       File:         pdf-token-obj.c
+ *       Date:         Sat Jul  7 03:04:30 2007
+ *
+ *       GNU PDF Library - PDF token objects
+ *
+ */
+
+/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. */
+
+/* This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "config.h"
+#include "pdf-token-obj.h"
+#include "pdf-alloc.h"
+
+/* Private functions */
+
+static INLINE pdf_status_t
+pdf_token_new (enum pdf_token_type_e type, pdf_token_t *token)
+{
+  pdf_token_t new;
+  assert (token);
+
+  new = (pdf_token_t) pdf_alloc (sizeof (struct pdf_token_s));
+  if (!new)
+    return PDF_ENOMEM;
+
+  new->type = type;
+  *token = new;
+  return PDF_OK;
+}
+
+pdf_status_t
+pdf_token_destroy (pdf_token_t token)
+{
+  assert (token);
+  switch (token->type)
+    {
+    case PDF_TOKEN_STRING:   /* fall through */
+    case PDF_TOKEN_NAME:     /* fall through */
+    case PDF_TOKEN_KEYWORD:  /* fall through */
+    case PDF_TOKEN_COMMENT:
+      {
+        pdf_dealloc (token->value.buffer.data);
+        break;
+      }
+    default:
+      {
+        /* NOP */
+        break;
+      }
+    }
+
+  pdf_dealloc (token);
+  return PDF_OK;
+}
+
+static pdf_status_t
+pdf_token_buffer_new (enum pdf_token_type_e type,
+                      const pdf_char_t *value,
+                      pdf_size_t size,
+                      pdf_bool_t nullterm,
+                      pdf_token_t *token)
+{
+  pdf_token_t new_obj = NULL;
+  pdf_status_t rv = pdf_token_new (type, &new_obj);
+  if (rv != PDF_OK)
+    goto fail;
+
+  rv = PDF_ENOMEM;
+  new_obj->value.buffer.data = pdf_alloc (nullterm ? size + 1 : size);
+  if (!new_obj->value.buffer.data)
+    goto fail;
+
+  new_obj->value.buffer.size = size;
+  memcpy (new_obj->value.buffer.data, value, size);
+  if (nullterm)
+    new_obj->value.buffer.data[size] = 0;
+
+  *token = new_obj;
+  return PDF_OK;
+
+fail:
+  if (new_obj)
+    pdf_dealloc (new_obj);
+  return rv;
+}
+
+
+/* General functions */
+
+enum pdf_token_type_e
+pdf_token_get_type (const pdf_token_t token)
+{
+  assert (token);
+  return token->type;
+}
+
+pdf_bool_t
+pdf_token_equal_p (const pdf_token_t token1, const pdf_token_t token2)
+{
+  assert (token1 && token2);
+  if (token1->type != token2->type)
+    return PDF_FALSE;
+
+  switch (token1->type)
+    {
+    case PDF_TOKEN_DICT_START:   /* fall through */
+    case PDF_TOKEN_DICT_END:     /* fall through */
+    case PDF_TOKEN_ARRAY_START:  /* fall through */
+    case PDF_TOKEN_ARRAY_END:    /* fall through */
+    case PDF_TOKEN_PROC_START:   /* fall through */
+    case PDF_TOKEN_PROC_END:
+      return PDF_TRUE;
+
+    case PDF_TOKEN_INTEGER:
+      return token1->value.integer == token2->value.integer;
+
+    case PDF_TOKEN_REAL:
+      return token1->value.real == token2->value.real;
+
+    case PDF_TOKEN_COMMENT:
+      if (token1->value.comment.continued != token2->value.comment.continued)
+        return PDF_FALSE;
+
+      /* fall through */
+    case PDF_TOKEN_STRING:   /* fall through */
+    case PDF_TOKEN_NAME:     /* fall through */
+    case PDF_TOKEN_KEYWORD:
+      {
+        struct pdf_token_buffer_s *buf1 = &token1->value.buffer;
+        struct pdf_token_buffer_s *buf2 = &token2->value.buffer;
+        return (buf1->size == buf2->size
+                 && ( buf1->data == buf2->data
+                      || !memcmp (buf1->data, buf2->data, buf1->size) ));
+      }
+
+    default:
+      assert (0);  /* shouldn't happen */
+      return 0;
+    }
+}
+
+pdf_status_t
+pdf_token_dup (const pdf_token_t token, pdf_token_t *new)
+{
+  assert (token);
+  switch (token->type)
+    {
+    case PDF_TOKEN_DICT_START:   /* fall through */
+    case PDF_TOKEN_DICT_END:     /* fall through */
+    case PDF_TOKEN_ARRAY_START:  /* fall through */
+    case PDF_TOKEN_ARRAY_END:    /* fall through */
+    case PDF_TOKEN_PROC_START:   /* fall through */
+    case PDF_TOKEN_PROC_END:
+      return pdf_token_valueless_new (token->type, new);
+
+    case PDF_TOKEN_INTEGER:
+      return pdf_token_integer_new (token->value.integer, new);
+
+    case PDF_TOKEN_REAL:
+      return pdf_token_real_new (token->value.real, new);
+
+    case PDF_TOKEN_STRING:
+      return pdf_token_string_new (token->value.buffer.data,
+                                   token->value.buffer.size,
+                                   new);
+    case PDF_TOKEN_NAME:
+      return pdf_token_name_new (token->value.buffer.data,
+                                 token->value.buffer.size,
+                                 new);
+    case PDF_TOKEN_KEYWORD:
+      return pdf_token_keyword_new (token->value.buffer.data,
+                                    token->value.buffer.size,
+                                    new);
+    case PDF_TOKEN_COMMENT:
+      return pdf_token_comment_new (token->value.comment.data,
+                                    token->value.comment.size,
+                                    token->value.comment.continued,
+                                    new);
+    default:
+      /* Should not be reached: make the compiler happy */
+      return PDF_EBADDATA;
+    }
+}
+
+pdf_status_t
+pdf_token_valueless_new (enum pdf_token_type_e type,
+                         pdf_token_t *token)
+{
+  switch (type)
+  {
+    case PDF_TOKEN_DICT_START:   /* fall through */
+    case PDF_TOKEN_DICT_END:     /* fall through */
+    case PDF_TOKEN_ARRAY_START:  /* fall through */
+    case PDF_TOKEN_ARRAY_END:    /* fall through */
+    case PDF_TOKEN_PROC_START:   /* fall through */
+    case PDF_TOKEN_PROC_END:
+      return pdf_token_new (type, token);
+    default:
+      return PDF_EBADDATA;
+  }
+}
+
+
+/** integers *****/
+
+pdf_status_t
+pdf_token_integer_new (pdf_i32_t value, pdf_token_t *token)
+{
+  pdf_status_t rv = pdf_token_new (PDF_TOKEN_INTEGER, token);
+  if (rv == PDF_OK)
+    (*token)->value.integer = value;
+
+  return rv;
+}
+
+pdf_i32_t
+pdf_token_get_integer_value (const pdf_token_t token)
+{
+  assert (token && token->type == PDF_TOKEN_INTEGER);
+  return token->value.integer;
+}
+
+
+/** reals *****/
+
+pdf_status_t
+pdf_token_real_new (pdf_real_t value, pdf_token_t *token)
+{
+  pdf_status_t rv;
+
+  if (isnan(value) || isinf(value))
+    return PDF_EBADDATA;
+
+  rv = pdf_token_new (PDF_TOKEN_REAL, token);
+  if (rv == PDF_OK)
+    (*token)->value.real = value;
+
+  return rv;
+}
+
+pdf_real_t
+pdf_token_get_real_value (const pdf_token_t token)
+{
+  assert (token && token->type == PDF_TOKEN_REAL);
+  return token->value.real;
+}
+
+
+/** names *****/
+
+pdf_status_t
+pdf_token_name_new (const pdf_char_t *value,
+                    pdf_size_t size,
+                    pdf_token_t *token)
+{
+  pdf_size_t i;
+  for (i = 0; i < size; ++i)
+    {
+      if (value[i] == 0)  /* names can't include null bytes */
+        return PDF_EBADDATA;
+    }
+
+  return pdf_token_buffer_new (PDF_TOKEN_NAME, value, size, 1, token);
+}
+
+pdf_size_t
+pdf_token_get_name_size (const pdf_token_t name)
+{
+  assert (name && name->type == PDF_TOKEN_NAME);
+  return name->value.buffer.size;
+}
+
+const pdf_char_t *
+pdf_token_get_name_data (const pdf_token_t name)
+{
+  assert (name && name->type == PDF_TOKEN_NAME);
+  return name->value.buffer.data;
+}
+
+
+/** strings *****/
+
+pdf_status_t
+pdf_token_string_new (const pdf_char_t *value,
+                    pdf_size_t size,
+                    pdf_token_t *token)
+{
+  return pdf_token_buffer_new (PDF_TOKEN_STRING, value, size, 0, token);
+}
+
+pdf_size_t
+pdf_token_get_string_size (const pdf_token_t token)
+{
+  assert (token && token->type == PDF_TOKEN_STRING);
+  return token->value.buffer.size;
+}
+
+const pdf_char_t *
+pdf_token_get_string_data (const pdf_token_t token)
+{
+  assert (token && token->type == PDF_TOKEN_STRING);
+  return token->value.buffer.data;
+}
+
+
+/** comments *****/
+
+pdf_status_t
+pdf_token_comment_new (const pdf_char_t *value,
+                       pdf_size_t size,
+                       pdf_bool_t continued,
+                       pdf_token_t *token)
+{
+  pdf_status_t rv;
+  pdf_size_t i;
+  for (i = 0; i < size; ++i)
+    {
+      /* comments can't span multiple lines */
+      if (pdf_is_eol_char(value[i]))
+        return PDF_EBADDATA;
+    }
+
+  rv = pdf_token_buffer_new (PDF_TOKEN_COMMENT, value, size, 0, token);
+  if (rv == PDF_OK)
+    (*token)->value.comment.continued = !!continued;
+
+  return rv;
+}
+
+pdf_size_t
+pdf_token_get_comment_size (const pdf_token_t comment)
+{
+  assert (comment && comment->type == PDF_TOKEN_COMMENT);
+  return comment->value.buffer.size;
+}
+
+const pdf_char_t *
+pdf_token_get_comment_data (const pdf_token_t comment)
+{
+  assert (comment && comment->type == PDF_TOKEN_COMMENT);
+  return comment->value.buffer.data;
+}
+
+pdf_bool_t
+pdf_token_get_comment_continued (const pdf_token_t comment)
+{
+  assert (comment && comment->type == PDF_TOKEN_COMMENT);
+  return comment->value.comment.continued;
+}
+
+
+/** keywords *****/
+
+pdf_status_t
+pdf_token_keyword_new (const pdf_char_t *value,
+                       pdf_size_t size,
+                       pdf_token_t *token)
+{
+  pdf_size_t i;
+  for (i = 0; i < size; ++i)
+    {
+      /* keywords can only include regular characters */
+      if (!pdf_is_regular_char(value[i]))
+        return PDF_EBADDATA;
+    }
+
+  return pdf_token_buffer_new (PDF_TOKEN_KEYWORD, value, size, 1, token);
+}
+
+pdf_size_t
+pdf_token_get_keyword_size (const pdf_token_t keyword)
+{
+  assert (keyword && keyword->type == PDF_TOKEN_KEYWORD);
+  return keyword->value.buffer.size;
+}
+
+const pdf_char_t *
+pdf_token_get_keyword_data (const pdf_token_t keyword)
+{
+  assert (keyword && keyword->type == PDF_TOKEN_KEYWORD);
+  return keyword->value.buffer.data;
+}
+
+
+/* End of pdf-token-obj.c */

=== added file 'src/base/pdf-token-obj.h'
--- src/base/pdf-token-obj.h    1970-01-01 00:00:00 +0000
+++ src/base/pdf-token-obj.h    2009-05-20 05:28:26 +0000
@@ -0,0 +1,210 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 04:01:14 mgold"
+ *
+ *       File:         pdf-token-obj.h
+ *       Date:         Sat Jul  7 01:10:11 2007
+ *
+ *       GNU PDF Library - PDF token objects
+ *
+ */
+
+/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. */
+
+/* This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* pdf-token-obj.{c,h} implement the token ADT, used to represent
+   all types of tokens used by the token reader and writer:
+      - Integer number
+      - Real number
+      - String
+      - Name
+      - Keyword
+      - Comment
+      - Valueless tokens:
+        - PDF_TOKEN_DICT_START
+        - PDF_TOKEN_DICT_END
+        - PDF_TOKEN_ARRAY_START
+        - PDF_TOKEN_ARRAY_END
+        - PDF_TOKEN_PROC_START
+        - PDF_TOKEN_PROC_END
+*/
+
+#ifndef PDF_TOKEN_OBJ_H
+#define PDF_TOKEN_OBJ_H
+
+#include "config.h"
+#include "pdf-types.h"
+#include "pdf-base.h"
+
+/* BEGIN PUBLIC */
+/* pdf-token-obj.h */
+
+enum pdf_token_type_e
+{
+  PDF_TOKEN_INTEGER = 1,
+  PDF_TOKEN_REAL = 2,
+  PDF_TOKEN_STRING = 3,
+  PDF_TOKEN_NAME = 4,
+  PDF_TOKEN_KEYWORD = 5,
+  PDF_TOKEN_COMMENT = 6,
+  PDF_TOKEN_DICT_START = 7,
+  PDF_TOKEN_DICT_END = 8,
+  PDF_TOKEN_ARRAY_START = 9,
+  PDF_TOKEN_ARRAY_END = 10,
+  PDF_TOKEN_PROC_START = 11,
+  PDF_TOKEN_PROC_END = 12,
+};
+
+struct pdf_token_s;  /* opaque type */
+typedef struct pdf_token_s *pdf_token_t;
+
+/* Token creation */
+pdf_status_t pdf_token_integer_new (pdf_i32_t value, pdf_token_t *token);
+pdf_status_t pdf_token_real_new (pdf_real_t value, pdf_token_t *token);
+pdf_status_t pdf_token_string_new (const pdf_char_t *value, pdf_size_t size,
+                                   pdf_token_t *token);
+pdf_status_t pdf_token_name_new (const pdf_char_t *value, pdf_size_t size,
+                                 pdf_token_t *token);
+pdf_status_t pdf_token_keyword_new (const pdf_char_t *value, pdf_size_t size,
+                                    pdf_token_t *token);
+pdf_status_t pdf_token_comment_new (const pdf_char_t *value, pdf_size_t size,
+                                    pdf_bool_t continued, pdf_token_t *token);
+pdf_status_t pdf_token_valueless_new (enum pdf_token_type_e type,
+                                      pdf_token_t *token);
+pdf_status_t pdf_token_dup (const pdf_token_t token, pdf_token_t *new);
+
+/* Token destruction */
+pdf_status_t pdf_token_destroy (pdf_token_t token);
+
+/* Common functions */
+enum pdf_token_type_e pdf_token_type (const pdf_token_t token);
+pdf_bool_t pdf_token_equal_p (const pdf_token_t token1,
+                              const pdf_token_t token2);
+
+/* Managing tokens of numeric types */
+pdf_i32_t pdf_token_get_integer_value (const pdf_token_t token);
+pdf_real_t pdf_token_get_real_value (const pdf_token_t token);
+
+/* Managing strings */
+pdf_size_t pdf_token_get_string_size (pdf_token_t token);
+const pdf_char_t *pdf_token_get_string_data (pdf_token_t token);
+
+/* Managing names */
+pdf_size_t pdf_token_get_name_size (const pdf_token_t token);
+const pdf_char_t *pdf_token_get_name_data (const pdf_token_t token);
+
+/* Managing keywords */
+pdf_size_t pdf_token_get_keyword_size (const pdf_token_t token);
+const pdf_char_t *pdf_token_get_keyword_data (const pdf_token_t token);
+
+/* Managing comments */
+pdf_size_t pdf_token_get_comment_size (const pdf_token_t token);
+const pdf_char_t *pdf_token_get_comment_data (const pdf_token_t token);
+pdf_bool_t pdf_token_get_comment_continued (const pdf_token_t token);
+
+/* END PUBLIC */
+
+
+static INLINE int
+pdf_is_wspace_char (pdf_char_t ch)
+{
+  /* ASCII codes for NUL, HT, LF, FF, CR, SP */
+  return (ch == 0 || ch == 9 || ch == 10 || ch == 12 || ch == 13 || ch == 32);
+}
+
+static INLINE int
+pdf_is_delim_char (pdf_char_t ch)
+{
+  /* ASCII codes for '%', '(', ')', '/'; '<', '>', '[', ']'; '{', '}' */
+  return (ch == 37 || ch == 40 || ch == 41 || ch == 47
+       || ch == 60 || ch == 62 || ch == 91 || ch == 93
+       || ch == 123 || ch == 125);
+}
+
+static INLINE int
+pdf_is_eol_char (pdf_char_t ch)
+{
+  return ch == 10 || ch == 13;
+}
+
+static INLINE int
+pdf_is_regular_char (pdf_char_t ch)
+{
+  return !pdf_is_wspace_char (ch) && !pdf_is_delim_char (ch);
+}
+
+/* According to the PDF reference, a PDF name object is an atomic
+   symbol uniquely defined by a sequence of non-null characters. It has
+   no internal structure.
+
+   In the practice, PDF uses name objects in order to store
+   information (such as font names). In that situation, it is
+   recommended to code such information in UTF-8. Due to this
+   stupidity we should store the entire byte sequence that conform the
+   name.
+
+   A pdf_token_buffer_s structure is used to store a name's value. */
+
+
+/* A PDF string is a sequence of bytes, in the range of 0-255. In
+   particular it may contain NULL characters (code 0 in the ASCII
+   CCS).
+
+   Corollary: NEVER NEVER NEVER EVER use a PDF string as an input
+   expecting null-terminated strings. You have been warned.
+
+   A pdf_token_buffer_s structure is used to store a string's value. */
+
+
+/* pdf_token_buffer_s is an internal structure used for tokens with an
+ * associated byte array. 'data' may or may not be null-terminated,
+ * but size never includes the trailing null. */
+struct pdf_token_buffer_s
+{
+  pdf_char_t *data;
+  pdf_size_t size;
+};
+
+struct pdf_comment_s
+{
+  pdf_char_t *data;
+  pdf_size_t size;
+  /* This structure shares a common initial sequence with pdf_token_buffer_s,
+   * so the above fields can be accessed via token->value.buffer. */
+
+  pdf_bool_t continued;  /* is data continued from a previous token? */
+};
+
+
+/* A `pdf_token_s' structure stores a PDF object. The object may be of
+   any type (including NULL). */
+
+struct pdf_token_s
+{
+  enum pdf_token_type_e type;
+
+  union
+  {
+
+    struct pdf_token_buffer_s buffer;
+    pdf_i32_t integer;
+    pdf_real_t real;
+    struct pdf_comment_s comment;
+
+  } value;
+};
+
+#endif /* PDF_TOKEN_OBJ_H */
+
+/* End of pdf-token-obj.h */

=== added file 'src/base/pdf-token-reader.c'
--- src/base/pdf-token-reader.c 1970-01-01 00:00:00 +0000
+++ src/base/pdf-token-reader.c 2009-05-20 05:19:37 +0000
@@ -0,0 +1,915 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 04:01:14 mgold"
+ *
+ *       File:         pdf-token-reader.c
+ *       Date:         Mon Dec 29 00:45:09 2008
+ *
+ *       GNU PDF Library - Stream tokeniser
+ *
+ */
+
+/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. */
+
+/* This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include "pdf-token-reader.h"
+
+static INLINE int can_store_char (pdf_token_reader_t reader);
+static INLINE pdf_status_t store_char (pdf_token_reader_t reader,
+                                       pdf_char_t ch);
+static pdf_status_t exit_state (pdf_token_reader_t reader, pdf_u32_t flags,
+                                pdf_token_t *token);
+static pdf_status_t flush_token (pdf_token_reader_t reader, pdf_u32_t flags,
+                                 pdf_token_t *token);
+static pdf_status_t handle_char (pdf_token_reader_t reader, pdf_u32_t flags,
+                                 pdf_char_t ch, pdf_token_t *token);
+static INLINE pdf_status_t handle_string_char (pdf_token_reader_t reader,
+                                               pdf_u32_t flags,
+                                               pdf_char_t ch,
+                                               pdf_token_t *token);
+static INLINE pdf_status_t handle_hexstring_char (pdf_token_reader_t reader,
+                                                  pdf_u32_t flags,
+                                                  pdf_char_t ch,
+                                                  pdf_token_t *token);
+static int recognise_number (pdf_buffer_t buffer, int *int_value);
+static INLINE int parse_integer (pdf_buffer_t buffer, int *int_value,
+                                 int *int_state);
+static INLINE pdf_status_t parse_real (pdf_buffer_t buffer,
+                                       char *locale_dec_pt,
+                                       double *value);
+static INLINE int validate_real (pdf_buffer_t buffer, int int_state);
+
+
+pdf_status_t
+pdf_token_reader_new (pdf_stm_t stm, pdf_token_reader_t *reader)
+{
+  pdf_status_t err;
+  pdf_token_reader_t new_tokr;
+
+  err = PDF_ENOMEM;
+  new_tokr = pdf_alloc (sizeof (*new_tokr));
+  if (!new_tokr)
+    goto fail;
+
+  /* determine the current locale's decimal point
+   * (avoid using localeconv since it may not be thread-safe) */
+  new_tokr->decimal_point = NULL;
+  {
+    int len;
+    char decpt[16];
+
+    err = PDF_ERROR;
+    len = snprintf (decpt, sizeof (decpt), "%#.0f", 1.0);
+    if (len <= 0 || len >= sizeof (decpt))  /* shouldn't happen */
+      goto fail;
+
+    err = PDF_ENOMEM;
+    new_tokr->decimal_point = pdf_alloc (len);
+    if (!new_tokr->decimal_point)
+      goto fail;
+
+    /* this copies the trailing '\0' due to the starting offset */
+    memcpy (new_tokr->decimal_point, &decpt[1], len);
+  }
+
+  /* max string size 32767 + terminating '\0' */
+  new_tokr->buffer = pdf_buffer_new (32768);
+  if (!new_tokr->buffer)
+    goto fail;
+
+  new_tokr->stream = stm;
+  pdf_token_reader_reset (new_tokr);
+
+  *reader = new_tokr;
+  return PDF_OK;
+
+fail:
+  if (new_tokr)
+    {
+      if (new_tokr->decimal_point)
+        pdf_dealloc (new_tokr->decimal_point);
+      pdf_dealloc (new_tokr);
+    }
+
+  return err;
+}
+
+pdf_status_t
+pdf_token_reader_reset (pdf_token_reader_t reader)
+{
+  reader->state = PDF_TOKR_STATE_NONE;
+  reader->substate = 0;
+  return PDF_OK;
+}
+
+pdf_status_t
+pdf_token_reader_destroy (pdf_token_reader_t reader)
+{
+  if (!reader) return PDF_EBADDATA;
+
+  assert (reader->buffer);
+  if (reader->buffer)
+    pdf_buffer_destroy (reader->buffer);
+  pdf_dealloc (reader->decimal_point);
+  pdf_dealloc (reader);
+
+  return PDF_OK;
+}
+
+static INLINE pdf_char_t
+hexval (pdf_char_t ch)
+{
+  if (ch >= 48 && ch <= 48+9)  /* '0'--'9' */
+    return ch - 48;
+  if (ch >= 64+1 && ch <= 64+6)  /* 'A'--'F' */
+    return ch - (64+1) + 10;
+  if (ch >= 96+1 && ch <= 96+6)  /* 'a'--'f' */
+    return ch - (96+1) + 10;
+  return 255;
+}
+
+
+/* Tries to handle the given character and possibly produce a token.
+ * Sets (*token) if a token is produced, and leaves it unmodified otherwise.
+ *
+ * Returns PDF_OK if the character was accepted. Otherwise, an error code
+ * is returned, and the call can be repeated later with the same ch value.
+ * A token may be produced even if the character isn't accepted.
+ */
+static pdf_status_t
+handle_char (pdf_token_reader_t reader, pdf_u32_t flags,
+             pdf_char_t ch, pdf_token_t *token)
+{
+  pdf_status_t rv;
+
+  /* first, handle the states that shouldn't be exited when whitespace
+   * or a delimiter is seen */
+
+  switch (reader->state)
+    {
+    case PDF_TOKR_STATE_EOF:
+      return PDF_EEOF;
+
+    case PDF_TOKR_STATE_STRING:
+      return handle_string_char (reader, flags, ch, token);
+
+    case PDF_TOKR_STATE_HEXSTRING:
+      return handle_hexstring_char (reader, flags, ch, token);
+
+    case PDF_TOKR_STATE_DICTEND:
+      if (ch != 62)  /* '>' */
+        return PDF_EBADFILE;
+      reader->substate = 1;  /* saw the closing '>' */
+      return exit_state (reader, flags, token);
+
+    case PDF_TOKR_STATE_COMMENT:
+      if (pdf_is_eol_char (ch))
+        {
+          rv = exit_state (reader, flags, token);
+          if (rv != PDF_OK)
+            return rv;
+
+          /* don't accept this character, but process it next time */
+          return PDF_EAGAIN;
+        }
+
+      if (store_char (reader, ch) != PDF_OK)
+        {
+          /* the comment buffer is full, so split the token */
+          rv = flush_token (reader, flags, token);
+          if (rv != PDF_OK)
+            return rv;
+
+          reader->intparam = 1;  /* mark the next token as a continuation */
+          return store_char (reader, ch);  /* can't fail this time */
+        }
+
+      return PDF_OK;
+
+    default: ;
+    }
+
+  /* now handle delimiters and whitespace */
+
+  if (pdf_is_wspace_char (ch))
+    {
+      if (reader->state)
+        {
+          rv = exit_state (reader, flags, token);
+          if (rv != PDF_OK)
+            return rv;
+
+          /* avoid reading this byte so PDF_TOKEN_END_AT_STREAM
+           * will work properly if it's '\r' */
+          return PDF_EAGAIN;
+        }
+
+      if ((flags & PDF_TOKEN_END_AT_STREAM) && ch == 10)  /* LF */
+        {
+          /* found the beginning of a stream */
+          reader->state = PDF_TOKR_STATE_EOF;
+        }
+      return PDF_OK;
+    }
+  else if ((flags & PDF_TOKEN_END_AT_STREAM) && ch != 37)  /* 37=='%' */
+    {
+      /* only allow whitespace/comments after the "stream" keyword */
+      return PDF_EBADFILE;
+    }
+
+  if (pdf_is_delim_char (ch))
+    {
+      /* set state 0 (UNINIT), substate 0, bufpos 0 */
+      if (reader->state)
+        {
+          rv = exit_state (reader, flags, token);
+          if (rv != PDF_OK)
+            return rv;
+          return PDF_EAGAIN;
+        }
+
+      switch (ch)
+        {
+        case 37:  /* '%' */
+          reader->state = PDF_TOKR_STATE_COMMENT;
+          reader->intparam = 0;
+          return store_char (reader, ch);
+        case 40:  /* '(' */
+          reader->state = PDF_TOKR_STATE_STRING;
+          reader->intparam = 0;
+          return PDF_OK;
+        case 41:  /* ')' */
+          /* this shouldn't occur outside the STRING and COMMENT states */
+          return PDF_EBADFILE;
+        case 47:  /* '/' */
+          reader->state = PDF_TOKR_STATE_NAME;
+          return PDF_OK;
+        case 60:  /* '<' */
+          reader->state = PDF_TOKR_STATE_HEXSTRING;
+          return PDF_OK;
+        case 62:  /* '>' */
+          reader->state = PDF_TOKR_STATE_DICTEND;
+          return PDF_OK;
+        case 91:  /* '[' */
+          /* fall through */
+        case 93:  /* ']' */
+          /* fall through */
+        case 123: /* '{' */
+          /* fall through */
+        case 125: /* '}' */
+          /* exit_state may have emitted a token, so we can't emit another
+           * one now; we'll do it when exiting the PENDING state */
+          reader->state = PDF_TOKR_STATE_PENDING;
+          reader->charparam = ch;
+          return PDF_OK;
+        }
+
+      /* not reached (all delimiter chars should be handled) */
+      assert (0);
+    }
+
+  /* ch is a regular character */
+
+  switch (reader->state)
+    {
+    case PDF_TOKR_STATE_PENDING:
+      rv = exit_state (reader, flags, token);
+      if (rv != PDF_OK)
+        return rv;
+      return PDF_EAGAIN;
+
+    case PDF_TOKR_STATE_NONE:
+      reader->state = PDF_TOKR_STATE_KEYWORD;
+      /* fall through */
+
+    case PDF_TOKR_STATE_KEYWORD:
+      return store_char (reader, ch);
+
+    case PDF_TOKR_STATE_NAME:
+      if (reader->substate == 0)
+        {
+          if (ch != 35  /* '#' */
+              || (flags & PDF_TOKEN_NO_NAME_ESCAPES) )
+            return store_char (reader, ch);
+
+          reader->substate = 1;
+          return PDF_OK;
+        }
+
+      if ( (ch = hexval (ch)) >= 16 )
+        return PDF_EBADFILE;
+
+      if (reader->substate == 1)  /* the first hex digit of an escape */
+        {
+          reader->substate = 2;
+          reader->charparam = ch;
+          return PDF_OK;
+        }
+
+      ch = (reader->charparam << 4) | ch;
+      if (ch == 0)  /* the PDF spec forbids "#00" */
+        return PDF_EBADFILE;
+
+      rv = store_char (reader, ch);
+      if (rv == PDF_OK) reader->substate = 0;
+      return rv;
+
+    default:
+      assert (0);
+  }
+
+  return store_char (reader, ch);
+}
+
+
+static INLINE int
+can_store_char (const pdf_token_reader_t reader)
+{
+  return reader->buffer->wp < (reader->buffer->size - 1);
+}
+
+static INLINE pdf_status_t
+store_char (pdf_token_reader_t reader, pdf_char_t ch)
+{
+  if (!can_store_char (reader))
+    return PDF_EIMPLLIMIT;
+  reader->buffer->data[reader->buffer->wp++] = ch;
+  return PDF_OK;
+}
+
+
+static pdf_status_t
+flush_token (pdf_token_reader_t reader, pdf_u32_t flags, pdf_token_t *token)
+{
+  pdf_status_t rv;
+  pdf_token_t new_tok;
+  pdf_char_t *data = reader->buffer->data;
+  int datasize = reader->buffer->wp;
+
+  switch (reader->state)
+    {
+    case PDF_TOKR_STATE_NONE:
+      return PDF_OK;  /* no state to exit */
+
+    case PDF_TOKR_STATE_EOF:
+      return PDF_EEOF;  /* can't continue parsing after EOF */
+
+    case PDF_TOKR_STATE_COMMENT:
+      if (!(flags & PDF_TOKEN_RET_COMMENTS))
+        goto finish;
+
+      rv = pdf_token_comment_new (data, datasize,
+          reader->intparam /*continued*/, &new_tok);
+      break;
+
+    case PDF_TOKR_STATE_KEYWORD:
+      {
+        int value;
+        int ntyp = recognise_number (reader->buffer, &value);
+        if (ntyp == 1)
+          rv = pdf_token_integer_new (value, &new_tok);
+        else if (ntyp == 2)
+          {
+            double realvalue;
+            rv = parse_real (reader->buffer,
+                             reader->decimal_point,
+                             &realvalue);
+            if (rv != PDF_OK)
+              return rv;
+            rv = pdf_token_real_new ((float)realvalue, &new_tok);
+          }
+        else
+          rv = pdf_token_keyword_new (data, datasize, &new_tok);
+      }
+      break;
+
+    case PDF_TOKR_STATE_NAME:
+      if (reader->substate != 0)  /* reading an escape sequence */
+        return PDF_EBADFILE;
+
+      rv = pdf_token_name_new (data, datasize, &new_tok);
+      break;
+
+    case PDF_TOKR_STATE_STRING:
+      if (reader->intparam >= 0)  /* didn't see the closing ')' */
+        return PDF_EBADFILE;
+
+      rv = pdf_token_string_new (data, datasize, &new_tok);
+      break;
+
+    case PDF_TOKR_STATE_HEXSTRING:
+      if (reader->substate != 3)  /* didn't see the closing '>' */
+        return PDF_EBADFILE;
+
+      rv = pdf_token_string_new (data, datasize, &new_tok);
+      break;
+
+    case PDF_TOKR_STATE_DICTEND:
+      if (reader->substate != 1)  /* didn't see a second '>' */
+        return PDF_EBADFILE;
+
+      rv = pdf_token_valueless_new (PDF_TOKEN_DICT_END, &new_tok);
+      break;
+
+    case PDF_TOKR_STATE_PENDING:
+      switch (reader->charparam)
+        {
+        case 60:  /* '<' */
+          rv = pdf_token_valueless_new (PDF_TOKEN_DICT_START, &new_tok);
+          break;
+        case 91:  /* '[' */
+          rv = pdf_token_valueless_new (PDF_TOKEN_ARRAY_START, &new_tok);
+          break;
+        case 93:  /* ']' */
+          rv = pdf_token_valueless_new (PDF_TOKEN_ARRAY_END, &new_tok);
+          break;
+        case 123: /* '{' */
+          rv = pdf_token_valueless_new (PDF_TOKEN_PROC_START, &new_tok);
+          break;
+        case 125: /* '}' */
+          rv = pdf_token_valueless_new (PDF_TOKEN_PROC_END, &new_tok);
+          break;
+        default:
+          assert (0);
+          return PDF_ERROR;
+        }
+      break;
+
+    default:
+      assert (0);
+      return PDF_ERROR;
+    }
+
+  if (rv != PDF_OK)
+    return rv;
+
+  *token = new_tok;
+finish:
+  reader->buffer->wp = 0;
+  return PDF_OK;
+}
+
+
+static pdf_status_t
+exit_state (pdf_token_reader_t reader, pdf_u32_t flags, pdf_token_t *token)
+{
+  pdf_status_t rv = flush_token (reader, flags, token);
+  if (rv == PDF_OK)
+    {
+      reader->state = PDF_TOKR_STATE_NONE;
+      reader->substate = 0;
+    }
+  return rv;
+}
+
+
+static INLINE pdf_status_t
+handle_string_char (pdf_token_reader_t reader,
+                    pdf_u32_t flags,
+                    pdf_char_t ch,
+                    pdf_token_t *token)
+{
+  pdf_status_t rv;
+start:
+  switch (reader->substate)
+    {
+      case 1:  /* ignore LF */
+        reader->substate = 0;
+        if (ch == 10)
+          return PDF_OK;
+        /* fall through */
+
+      case 0:  /* no special state */
+        if (ch == 92)  /* '\\' */
+          {
+            reader->substate = 2;  /* start an escape sequence */
+            return PDF_OK;
+          }
+        else if (ch == 41 && reader->intparam <= 0)  /* ')'; end of string */
+          {
+            reader->intparam = -1;
+            return exit_state (reader, flags, token);
+          }
+
+        if (!can_store_char (reader))
+          return PDF_EIMPLLIMIT;
+        else if (ch == 40)  /* '(' */
+          ++reader->intparam;
+        else if (ch == 41)  /* ')' */
+          --reader->intparam;
+        else if (ch == 13)  /* '\r' */
+          {
+            ch = 10;  /* treat as LF */
+            reader->substate = 1;  /* ignore the next char if it's LF */
+          }
+
+        return store_char (reader, ch);
+
+      case 2:  /* just saw a '\\' (starting an escape sequence) */
+        reader->substate = 0;
+        if (ch == 98)  /* 'b' */
+          ch = 8;  /* BS: backspace */
+        else if (ch == 102)  /* 'f' */
+          ch = 12;  /* FF: formfeed */
+        else if (ch == 110)  /* 'n' */
+          ch = 10;  /* NL: newline */
+        else if (ch == 114)  /* 'r' */
+          ch = 13;  /* CR: carriage return */
+        else if (ch == 116)  /* 't' */
+          ch = 9;  /* HT: horizontal tab */
+        else if (ch == 10)  /* NL */
+          return PDF_OK;  /* ignore the line break */
+        else if (ch == 13)  /* CR */
+        {
+          /* ignore the line break; also ignore the next byte if it's LF */
+          reader->substate = 1;
+          return PDF_OK;
+        }
+        else if (ch >= 48 && ch <= 48+7)  /* digits '0'--'7' */
+          {
+            /* starting an octal escape; we'll read three digits even if the
+             * first is '4'--'7' (and calculate the final char modulo 256),
+             * since the PDF/PS specs say to ignore high-order overflow */
+            reader->substate = 3;
+            reader->charparam = (ch-48);
+            return PDF_OK;
+          }
+
+        /* for any other character, including '(', ')', and '\\',
+         * store the same character (dropping the leading backslash) */
+        return store_char (reader, ch);
+
+      case 3:  /* saw 1 digit of an octal escape */
+        /* fall through */
+      case 4:  /* saw 2 digits of an octal escape */
+        if (ch < 48 || ch > 48+7)  /* not digits '0'--'7' */
+          {
+            rv = store_char (reader, reader->charparam);
+            if (rv != PDF_OK) return rv;
+
+            /* ch isn't part of the escape sequence, so retry */
+            reader->substate = 0;
+            goto start;
+          }
+
+        /* ch is a digit from '0'--'7' */
+        reader->charparam = ((reader->charparam & 0x1f) << 3) | (ch - 48);
+        if (reader->substate == 4)  /* this was the final digit */
+          {
+            rv = store_char (reader, reader->charparam);
+            if (rv != PDF_OK) return rv;
+
+            reader->substate = 0;
+            return PDF_OK;
+          }
+
+        reader->substate = 4;
+        return PDF_OK;
+
+      default:
+        assert (0);
+    }
+}
+
+
+static INLINE pdf_status_t
+handle_hexstring_char (pdf_token_reader_t reader,
+                       pdf_u32_t flags,
+                       pdf_char_t ch,
+                       pdf_token_t *token)
+{
+  pdf_status_t rv;
+
+  if (reader->substate == 0)
+    {
+      /* this is the first character after the initial '<' */
+      if (ch == 60)  /* '<' */
+        {
+          /* this was actually the start of a dictionary */
+          reader->state = PDF_TOKR_STATE_PENDING;
+          reader->charparam = ch;
+          return exit_state (reader, flags, token);
+        }
+
+      reader->substate = 1;
+    }
+
+  if (pdf_is_wspace_char (ch))
+    return PDF_OK;
+
+  if (ch == 62)  /* '>': end of hex string */
+    {
+      if (reader->substate == 2)
+        {
+          /* the last digit is missing; assume it's '0' */
+          rv = store_char (reader, reader->charparam << 4);
+          if (rv != PDF_OK) return rv;
+        }
+
+      reader->substate = 3;  /* saw end of string */
+      return exit_state (reader, flags, token);
+    }
+
+  if ( (ch = hexval (ch)) == 255 )
+    return PDF_EBADFILE;
+
+  if (reader->substate == 1)  /* first character in a pair */
+    {
+      reader->substate = 2;
+      reader->charparam = ch;
+      return PDF_OK;
+    }
+
+  rv = store_char (reader, (reader->charparam << 4) | ch);
+  if (rv == PDF_OK)
+    reader->substate = 1;
+  return rv;
+}
+
+pdf_status_t
+pdf_token_read (pdf_token_reader_t reader, pdf_u32_t flags, pdf_token_t *token)
+{
+  pdf_status_t rv;
+  pdf_char_t ch;
+  pdf_token_t new_token = NULL;
+
+  if (!reader || !reader->stream || !token)
+    return PDF_EBADDATA;
+
+  while ( (rv = pdf_stm_peek_char (reader->stream, &ch)) == PDF_OK )
+    {
+      rv = handle_char (reader, flags, ch, &new_token);
+      if (rv == PDF_OK)
+        {
+          /* The character we peeked at was accepted, so get rid of it. */
+          pdf_stm_read_char (reader->stream, &ch);
+        }
+
+      if (new_token)
+        {
+          /* Don't return an error code if we got a valid token.
+           * We'll probably see the same error on the next call since we
+           * didn't call read_char. */
+          assert (rv == PDF_OK || rv == PDF_EAGAIN);
+          goto ret_token;
+        }
+      else if (rv != PDF_OK && rv != PDF_EAGAIN)
+        return rv;
+    }
+
+  /* peek_char returned an error code (rv) */
+  if (rv != PDF_EEOF)
+    return rv;
+
+  rv = exit_state (reader, flags, &new_token);
+  if (rv != PDF_OK)
+    return rv;
+
+  reader->state = PDF_TOKR_STATE_EOF;
+  if (new_token)
+    goto ret_token;
+  else
+    return PDF_EEOF;
+
+ret_token:
+  assert (new_token);
+  *token = new_token;
+  return PDF_OK;
+}
+
+
+static INLINE int
+parse_integer (pdf_buffer_t buffer, int *int_value, int *int_state)
+{
+  /* Parse an ASCII integer with the given radix, at the beginning of
+   * the buffer (possibly leaving unread bytes at the end).
+   *
+   * Return value is 0 on failure, or a bitmask otherwise:
+   *  1 = valid integer
+   *  2 = signed
+   *  4 = overflowed (no value stored in *int_value)
+   */
+
+  int sign = 0, tmpint = 0, overflowed = 0, ret;
+  /* Integer states (int_state):
+   *   0 = at start (looking for sign or digits)
+   *   1 = saw sign
+   *   2 = saw digits
+   */
+
+  *int_state = 0;
+  for (; buffer->rp < buffer->wp; ++buffer->rp)
+    {
+      int chval;
+      pdf_char_t ch = buffer->data[buffer->rp];
+      if (ch == 43 || ch == 45)  /* '+','-' */
+        {
+          if (*int_state != 0)
+            goto out;
+
+          *int_state = 1;
+          sign = (ch == 43) ? 1 : -1;
+          continue;
+        }
+
+      chval = ch - 48;  /* assume this is a digit */
+      if (chval < 0 || chval > 9)
+        goto out;  /* not a valid number */
+
+      *int_state = 2;
+      if (overflowed)
+        continue;
+
+      /* convert the digits to an integer, if possible */
+      if (sign < 0)
+        {
+          chval = -chval;
+          if ( tmpint < (INT_MIN/10)
+              || (tmpint == (INT_MIN/10) && chval < (INT_MIN%10)) )
+            {
+              overflowed = 1;  /* would overflow */
+              continue;
+            }
+        }
+      else
+        {
+          if ( tmpint > (INT_MAX/10)
+              || (tmpint == (INT_MAX/10) && chval > (INT_MAX%10)) )
+            {
+              overflowed = 1;  /* would overflow */
+              continue;
+            }
+        }
+
+      tmpint += chval + (tmpint * 9);
+    }
+
+out:
+  if (*int_state != 2)
+    return 0;  /* never saw any digits */
+
+  ret = 1;
+  if (sign) ret += 2;
+  if (overflowed)
+    ret += 4;
+  else
+    *int_value = tmpint;
+
+  return ret;
+}
+
+
+static INLINE int
+validate_real (pdf_buffer_t buffer, int int_state)
+{
+  /* Determines whether the given number is a valid PS/PDF real number;
+   * assumes the initial sign was already read (if present), and any data
+   * before buffer->rp is a valid integer.
+   *
+   * Return value:
+   *   0 = not a real number
+   *   1 = valid PDF/PS real
+   */
+
+  int seen_point = 0;
+  /* Integer states (int_state):
+   *   0 = at start
+   *   1 = saw sign
+   *   2 = saw digits
+   */
+
+  for (; buffer->rp < buffer->wp; ++buffer->rp)
+    {
+      pdf_char_t ch = buffer->data[buffer->rp];
+      if (ch == 46)  /* '.' */
+        {
+          if (!seen_point)
+            seen_point = 1;
+          else
+            return 0;
+        }
+      else if (ch == 43 || ch == 45)  /* '+','-' */
+        {
+          if (int_state == 0)
+            int_state = 1;
+          else
+            return 0;
+        }
+      else if (ch >= 48+0 && ch <= 48+9)
+        int_state = 2;
+      else
+        return 0;
+    }
+
+  return (int_state == 2);  /* only valid if we saw a digit */
+}
+
+
+/* Given a buffer containing a validated PDF real (in ASCII), convert it to a
+ * double by translating it to the execution character set, replacing '.' with
+ * the locale's decimal point, and calling strtod. */
+static INLINE pdf_status_t
+parse_real (pdf_buffer_t buffer, char *locale_dec_pt, double *value)
+{
+  pdf_status_t ret;
+  size_t tmplen, wpos, ptlen;
+  char *tmp, *endptr;
+
+  ptlen = strlen (locale_dec_pt);
+  /* we may remove 1 byte ('.') and replace it with ptlen bytes */
+  tmplen = buffer->wp - 1 + ptlen;
+
+  tmp = pdf_alloc (tmplen + 1);
+  if (!tmp)
+    return PDF_ENOMEM;
+
+  wpos = 0;
+  ret = PDF_ERROR;  /* nothing should fail if the buffer was validated */
+  for (buffer->rp = 0; buffer->rp < buffer->wp; ++buffer->rp)
+    {
+      pdf_char_t ch = buffer->data[buffer->rp];
+      if (wpos >= tmplen)
+        goto out;
+
+      if (ch == 46)  /* '.' */
+        {
+          if (wpos + ptlen > tmplen)
+            goto out;
+
+          memcpy (tmp + wpos, locale_dec_pt, ptlen);
+          wpos += ptlen;
+        }
+      else if (ch == 43)  /* '+' */
+        tmp[wpos++] = '+';
+      else if (ch == 45)  /* '-' */
+        tmp[wpos++] = '-';
+      else if (ch >= 48+0 && ch <= 48+9)  /* '0'--'9' */
+        tmp[wpos++] = '0' + (ch-48);
+      else
+        goto out;
+    }
+
+  /* null-terminate the new string, and call strtod to get its value
+   * (strtof would also work if it's available) */
+  tmp[wpos] = '\0';
+  *value = strtod (tmp, &endptr);
+  if (endptr == tmp + wpos)
+    ret = PDF_OK;
+
+out:
+  pdf_dealloc (tmp);
+  return ret;
+}
+
+
+/*
+ * Return value:
+ *   0 = not a number
+ *   1 = integer (stored in *int_value)
+ *   2 = real
+ */
+static int
+recognise_number (pdf_buffer_t buffer, int *int_value)
+{
+  int rv, tmpint = 0, int_state = 0;
+
+  /* try to parse as an integer */
+
+  buffer->rp = 0;
+  rv = parse_integer (buffer, &tmpint, &int_state);
+
+  if (buffer->rp < buffer->wp)  /* didn't look at the whole buffer */
+    {
+      rv = validate_real (buffer, int_state);
+      if (rv == 1)
+        return 2;
+
+      return 0;
+    }
+
+  if (!rv) return 0;
+  else if (rv & 4)
+    return 2;  /* integer overflowed, but could be read as a real */
+
+  *int_value = tmpint;
+  return 1;
+}
+
+
+/* End of pdf-token-reader.c */

=== added file 'src/base/pdf-token-reader.h'
--- src/base/pdf-token-reader.h 1970-01-01 00:00:00 +0000
+++ src/base/pdf-token-reader.h 2009-05-20 05:28:26 +0000
@@ -0,0 +1,124 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 04:01:14 mgold"
+ *
+ *       File:         pdf-token-reader.h
+ *       Date:         Mon Dec 29 00:45:09 2008
+ *
+ *       GNU PDF Library - Stream tokeniser
+ *
+ */
+
+/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. */
+
+/* This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PDF_TOKEN_READER_H
+#define PDF_TOKEN_READER_H
+#include "pdf-types.h"
+#include "pdf-stm.h"
+#include "pdf-token-obj.h"
+
+/* BEGIN PUBLIC */
+/* pdf-token-reader.h */
+
+struct pdf_token_reader_s;  /* opaque type */
+typedef struct pdf_token_reader_s *pdf_token_reader_t;
+
+pdf_status_t pdf_token_reader_new(pdf_stm_t stm, pdf_token_reader_t *reader);
+pdf_status_t pdf_token_reader_destroy(pdf_token_reader_t reader);
+pdf_status_t pdf_token_reader_reset(pdf_token_reader_t reader);
+pdf_status_t pdf_token_read(pdf_token_reader_t reader, pdf_u32_t flags,
+                            pdf_token_t *token);
+
+enum pdf_token_rw_flags_e {
+  /* these flags are used for token_read and token_write */
+  PDF_TOKEN_NO_NAME_ESCAPES = 1,    /* read/write */
+  PDF_TOKEN_RET_COMMENTS = 2,       /* read */
+  PDF_TOKEN_END_AT_STREAM = 4,      /* read */
+  PDF_TOKEN_HEX_STRINGS = 8,        /* write */
+  PDF_TOKEN_READABLE_STRINGS = 16,  /* write */
+};
+
+/* END PUBLIC */
+
+enum pdf_token_reader_state_e
+{
+  /* PDF_TOKR_ is used as an internal prefix for the token reader. */
+  PDF_TOKR_STATE_NONE = 0,
+  PDF_TOKR_STATE_COMMENT,
+  PDF_TOKR_STATE_KEYWORD,
+  PDF_TOKR_STATE_NAME,
+  PDF_TOKR_STATE_STRING,
+  PDF_TOKR_STATE_HEXSTRING,
+  PDF_TOKR_STATE_DICTEND,
+  PDF_TOKR_STATE_PENDING,
+  PDF_TOKR_STATE_EOF
+};
+
+/* Token reader states (from pdf_token_reader_state_e):
+ * NONE - Initial state; not reading a token.
+ * COMMENT - Reading a comment.  buffer collects the comment bytes, excluding
+ *   intparam is 1 if this token is continued from a previous token,
+ *   and 0 otherwise.
+ * KEYWORD - Reading some regular characters into buffer; this could result
+ *           in a symbol like "null", or a number.
+ * NAME - Reading a name (which starts with '/').
+ *   Substates:
+ *     0 - normal state
+ *     1 - just read a '#' (escape prefix)
+ *     2 - read the first hex digit after '#'; the value is in charparam
+ *   buffer collects the name, excluding the initial '/'.
+ * STRING - Reading a literal string (enclosed in '(', ')').
+ *   Substates:
+ *     0 - normal state
+ *     1 - ignore the next byte if its value is 10 (ASCII LF;
+ *         this is used to treat CRLF as a single line ending)
+ *     2 - just saw a backslash (escape prefix)
+ *     3 - read 1 octal digit; the value is in charparam
+ *     4 - read 2 octal digits; the value is in charparam
+ *   intparam is the bracket nesting level; ')' at level 0 ends the string.
+ *   buffer collects the string.
+ * HEXSTRING - Reading a hex string.
+ *   Substates:
+ *     0 - initial state: we just saw the opening '<', and if the next byte is
+ *         also '<' this is the start of a dictionary rather than a string
+ *     1 - normal state (the next hex digit will be the first in a pair)
+ *     2 - read the first hex digit; its value is in charparam
+ *     3 - end state; saw the closing '>'
+ *   buffer collects the string.
+ * DICTEND - Just got a '>'; expecting another.
+ *   Substates:
+ *     0 - starting state
+ *     1 - saw the second '>'
+ * PENDING - Need to emit a token (determined by charparam) ASAP.
+ * EOF - Can't continue tokenising (reached EOF, or beginning of stream)
+ */
+
+/* Internal state */
+struct pdf_token_reader_s {
+  pdf_stm_t stream;  /* stream to read bytes from */
+  char *decimal_point;
+
+  /* variables used by the state machine (described above) */
+  int state;
+  int substate;
+  pdf_char_t charparam;
+  int intparam;
+  pdf_buffer_t buffer;
+  /***/
+};
+
+#endif
+
+/* End of pdf-token-reader.h */

=== modified file 'torture/unit/Makefile.am'
--- torture/unit/Makefile.am    2009-05-13 16:30:24 +0000
+++ torture/unit/Makefile.am    2009-05-20 04:01:14 +0000
@@ -209,29 +209,33 @@
 TEST_SUITE_FP = base/fp/pdf-fp-func-eval.c \
                 base/fp/pdf-fp-func-4-new.c
 
+TEST_SUITE_TOKEN = base/token/pdf-token-read.c
+
 TEST_ENVIRONMENT = CHARSETALIASDIR=$(top_srcdir)/lib
 
 TEST_FILES = $(TEST_SUITE_LIST) \
              $(TEST_SUITE_TEXT) \
              $(TEST_SUITE_HASH) \
              $(TEST_SUITE_ERROR) \
-                        $(TEST_SUITE_TYPES) \
-                        $(TEST_SUITE_TIME) \
+             $(TEST_SUITE_TYPES) \
+             $(TEST_SUITE_TIME) \
              $(TEST_SUITE_CRYPT) \
              $(TEST_SUITE_ALLOC) \
              $(TEST_SUITE_STM) \
-             $(TEST_SUITE_FP)
+             $(TEST_SUITE_FP) \
+             $(TEST_SUITE_TOKEN)
 
 TSUITE_FILES = base/alloc/tsuite-alloc.c \
                base/list/tsuite-list.c \
                base/text/tsuite-text.c \
                base/hash/tsuite-hash.c \
                base/error/tsuite-error.c \
-                      base/types/tsuite-types.c \
-                          base/time/tsuite-time.c \
+               base/types/tsuite-types.c \
+               base/time/tsuite-time.c \
                base/crypt/tsuite-crypt.c \
                base/stm/tsuite-stm.c \
-               base/fp/tsuite-fp.c
+               base/fp/tsuite-fp.c \
+               base/token/tsuite-token.c
 
 TORTUTILS_FILES = $(top_srcdir)/torture/tortutils/tortutils.h \
                   $(top_srcdir)/torture/tortutils/tortutils.c

=== added directory 'torture/unit/base/token'
=== added file 'torture/unit/base/token/pdf-token-read.c'
--- torture/unit/base/token/pdf-token-read.c    1970-01-01 00:00:00 +0000
+++ torture/unit/base/token/pdf-token-read.c    2009-05-20 04:55:54 +0000
@@ -0,0 +1,159 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 04:35:27 mgold"
+ *
+ *       File:         pdf-token-read.c
+ *       Date:         Wed Jan 14 05:44:48 2009
+ *
+ *       GNU PDF Library - Unit tests for pdf_token_read
+ *
+ */
+
+#include <string.h>
+#include <check.h>
+#include <stdlib.h>
+#include "config.h"
+#include "pdf.h"
+
+#define STR_AND_LEN(s) (s),(sizeof(s)-1)
+
+/* Initialize an in-memory reader stream (pdf_stm_t *stm)
+ * with the given string (a char* constant). */
+#define INIT_STM_STR(stm,str) do{ \
+    fail_unless(PDF_OK==pdf_stm_mem_new( STR_AND_LEN(str),  \
+        0 /*cache_size*/, PDF_STM_READ /*mode*/, (stm) ));  \
+  }while(0)
+
+#define INIT_TOKR(tokr,stm) do{ fail_unless(     \
+  PDF_OK==pdf_token_reader_new((stm),(tokr)) ); }while(0)
+#define _EXPECT_TOK(tokr,flags,tokexpr) do{               \
+    pdf_token_t _exp_tok;                                 \
+    fail_unless(PDF_OK == (tokexpr));                     \
+    fail_unless(get_token( (tokr), (flags), _exp_tok ));  \
+    pdf_token_destroy(_exp_tok);                          \
+  }while(0)
+#define EXPECT_VALUELESS(tokr,flags,val) _EXPECT_TOK((tokr),  \
+  (flags), pdf_token_valueless_new(val, &_exp_tok) )
+#define EXPECT_KEYWORD(tokr,flags,val) _EXPECT_TOK((tokr),    \
+  (flags), pdf_token_keyword_new(STR_AND_LEN(val), &_exp_tok) )
+#define EXPECT_NAME(tokr,flags,val) _EXPECT_TOK((tokr),       \
+  (flags), pdf_token_name_new(STR_AND_LEN(val), &_exp_tok) )
+#define EXPECT_INTEGER(tokr,flags,val) _EXPECT_TOK((tokr),    \
+  (flags), pdf_token_integer_new(val, &_exp_tok) )
+#define EXPECT_REAL(tokr,flags,val) _EXPECT_TOK((tokr),       \
+  (flags), pdf_token_real_new(val, &_exp_tok) )
+#define EXPECT_STRING(tokr,flags,val) _EXPECT_TOK((tokr),     \
+  (flags), pdf_token_string_new(STR_AND_LEN(val), &_exp_tok) )
+
+static void *nonnull(void *ptr)
+{
+  if (ptr) return ptr;
+
+  fprintf(stderr, "error: got unexpected null pointer; aborting");
+  abort();
+}
+
+/* Read a token; return 1 if it's equal to 'expected', or 0 otherwise. */
+static int
+get_token(pdf_token_reader_t tokr, pdf_u32_t flags, pdf_token_t expected)
+{
+  int ret = 0;
+  pdf_token_t token = NULL;
+  pdf_status_t rv = pdf_token_read(tokr, flags, &token);
+
+  nonnull(expected);
+  ret = (rv == PDF_OK) && pdf_token_equal_p(token, expected);
+
+  if (token) pdf_token_destroy(token);
+  return ret;
+}
+
+static int
+tokr_eof(pdf_token_reader_t tokr, pdf_i32_t flags)
+{
+  pdf_token_t token = NULL;
+  pdf_status_t rv = pdf_token_read(tokr, flags, &token);
+  if (token) pdf_token_destroy(token);
+  return (rv == PDF_EEOF);
+}
+
+/*
+ * Test: pdf_token_read_001
+ * Description:
+ *   Read various tokens from an in-memory stream, and check whether they
+ *   match the expected values.
+ * Success condition:
+ *   Each token matches the expected one (according to pdf_token_equal_p),
+ *   and no tokens remain afterwards.
+ */
+START_TEST(pdf_token_read_001)
+{
+  pdf_stm_t stm;
+  pdf_token_reader_t tokr;
+
+  INIT_STM_STR(&stm, "abc}{/kw/k#20w%com\n"
+      "]1 2.0[>><4142434a4F4>"
+      "(str(\\551ng(\0\r)\\60x\\\r\n)>>)"
+      "<<1208925819614629174706176"          /* 2^80 */
+      "\0\n \r\t\f"                          /* whitespace */
+      "(\\n\\r\\t\\b\\f\\)\\(\\\\\\X\08)");  /* string escapes */
+  INIT_TOKR(&tokr, stm);
+
+  EXPECT_KEYWORD( tokr, 0, "abc" );
+  EXPECT_VALUELESS( tokr, 0, PDF_TOKEN_PROC_END );
+  EXPECT_VALUELESS( tokr, 0, PDF_TOKEN_PROC_START );
+  EXPECT_NAME( tokr, 0, "kw" );
+  EXPECT_NAME( tokr, 0, "k w" );
+  EXPECT_VALUELESS( tokr, 0, PDF_TOKEN_ARRAY_END );
+  EXPECT_INTEGER( tokr, 0, 1 );
+  EXPECT_REAL( tokr, 0, 2 );
+  EXPECT_VALUELESS( tokr, 0, PDF_TOKEN_ARRAY_START );
+  EXPECT_VALUELESS( tokr, 0, PDF_TOKEN_DICT_END );
+  EXPECT_STRING( tokr, 0, "ABCJO@" );
+  EXPECT_STRING( tokr, 0, "str(ing(\0\n)0x)>>" );
+  EXPECT_VALUELESS( tokr, 0, PDF_TOKEN_DICT_START );
+  EXPECT_REAL( tokr, 0, 1208925819614629174706176.0 );  /* 2^80 */
+  EXPECT_STRING( tokr, 0, "\n\r\t\b\f)(\\X\0\070" );
+
+  fail_unless( tokr_eof(tokr, 0) );
+}
+END_TEST
+
+/*
+ * Test: pdf_token_read_002
+ * Description:
+ *   Test the PDF_TOKEN_END_AT_STREAM flag.
+ * Success condition:
+ *   The stream should be positioned after the '\n' character (at '<'), and
+ *   the token reader should act as if it reached the end of the input file.
+ */
+START_TEST(pdf_token_read_002)
+{
+  pdf_stm_t stm;
+  pdf_token_reader_t tokr;
+  pdf_char_t ch;
+
+  INIT_STM_STR(&stm, "stream    \r\t  %com  \n"
+      ">UNPARSABLE DATA IN STREAM\n\n\n\n\n\nx");
+  INIT_TOKR(&tokr, stm);
+
+  EXPECT_KEYWORD( tokr, 0, "stream" );
+  fail_unless( tokr_eof(tokr, PDF_TOKEN_END_AT_STREAM) );
+  fail_unless( PDF_OK==pdf_stm_peek_char(stm, &ch) );
+  fail_unless( ch == '>' );
+  /*TODO: verify stream position */
+}
+END_TEST
+
+/*
+ * Test case creation function
+ */
+TCase *
+test_pdf_token_read (void)
+{
+  TCase *tc = tcase_create("pdf_token_read");
+  tcase_add_test(tc, pdf_token_read_001);
+  tcase_add_test(tc, pdf_token_read_002);
+
+  return tc;
+}
+
+/* End of pdf-token-read.c */

=== added file 'torture/unit/base/token/tsuite-token.c'
--- torture/unit/base/token/tsuite-token.c      1970-01-01 00:00:00 +0000
+++ torture/unit/base/token/tsuite-token.c      2009-05-20 05:28:26 +0000
@@ -0,0 +1,43 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 04:35:27 mgold"
+ *
+ *       File:         tsuite-token.c
+ *       Date:         Wed Jan 14 05:43:09 2009
+ *
+ *       GNU PDF Library - Testcase definition for the reader module
+ *
+ */
+
+/* Copyright (C) 2009 Free Software Foundation, Inc. */
+
+/* This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <check.h>
+
+extern TCase *test_pdf_token_read (void);
+
+Suite *
+tsuite_token ()
+{
+  Suite *s;
+
+  s = suite_create("token");
+
+  suite_add_tcase (s, test_pdf_token_read ());
+
+  return s;
+}
+
+
+/* End of tsuite-token.c */

=== added directory 'torture/unit/object'
=== modified file 'torture/unit/runtests.c'
--- torture/unit/runtests.c     2009-04-16 22:13:38 +0000
+++ torture/unit/runtests.c     2009-05-20 04:01:14 +0000
@@ -19,6 +19,7 @@
 extern Suite *tsuite_crypt (void);
 extern Suite *tsuite_error (void);
 extern Suite *tsuite_fp (void);
+extern Suite *tsuite_token (void);
 
 int
 main (int argc, char **argv)
@@ -39,6 +40,7 @@
   srunner_add_suite (sr, tsuite_error ());
   srunner_add_suite (sr, tsuite_stm ());
   srunner_add_suite (sr, tsuite_fp ());
+  srunner_add_suite (sr, tsuite_token ());
 
   /* Set log file */
   srunner_set_log (sr, "ut.log");

=== modified file 'utils/Makefile.am'
--- utils/Makefile.am   2009-01-01 17:00:46 +0000
+++ utils/Makefile.am   2009-05-20 04:01:14 +0000
@@ -22,7 +22,7 @@
  ICONV_LIBS = -liconv
 endif #ICONV
 
-bin_PROGRAMS = pdf-filter
+bin_PROGRAMS = pdf-filter toktest
 
 LDADD = $(top_builddir)/src/libgnupdf.la \
         $(ICONV_LIBS)
@@ -31,5 +31,6 @@
               -I$(top_srcdir)/src/base -I $(top_srcdir)/src/object
 
 pdf_filter_SOURCES = pdf-filter.h pdf-filter.c
+toktest_SOURCES = toktest.c
 
 # End of Makefile.am

=== added file 'utils/toktest.c'
--- utils/toktest.c     1970-01-01 00:00:00 +0000
+++ utils/toktest.c     2009-05-20 05:28:26 +0000
@@ -0,0 +1,195 @@
+/* -*- mode: C -*- Time-stamp: "2009-05-20 05:25:40 mgold"
+ *
+ *       File:         toktest.c
+ *       Date:         Wed May 20 05:25:40 2009
+ *
+ *       GNU PDF Library - Read standard input using a token reader,
+ *                         and print the resulting tokens to stdout.
+ */
+
+/* Copyright (C) 2009 Free Software Foundation, Inc. */
+
+/* This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "pdf.h"
+
+static char *fmtbin(const char *data, int size)
+{
+  int i;
+  char *ret, *retp;
+
+  if (size == -1)
+    size = strlen(data);
+
+  ret = malloc(3 + (size*4));
+  if (!ret) abort();
+
+  retp = ret;
+  (*retp++) = '"';
+  for (i = 0; i < size; ++i)
+    {
+      unsigned char ch = data[i];
+      if (ch == '"' || ch == '\\')
+        {
+          *(retp++) = '\\';
+          *(retp++) = ch;
+        }
+      else if (data[i] >= 32 && data[i] < 127)
+        *(retp++) = ch;
+      else
+        {
+          sprintf(retp, "\\x%02x", (int)ch);
+          retp += 4;
+        }
+    }
+  (*retp++) = '"';
+  (*retp++) = '\0';
+  return ret;
+}
+
+static void print_tok(pdf_token_t token)
+{
+  char tmpbuf[256];
+  const char *typ, *str = NULL;
+  int strsize = -1;
+  pdf_size_t i;
+
+  switch(pdf_token_get_type(token))
+    {
+    case PDF_TOKEN_INTEGER:
+      typ = "INTEGER";
+      snprintf(tmpbuf, sizeof(tmpbuf), "%d", 
pdf_token_get_integer_value(token));
+      str = tmpbuf;
+      break;
+
+    case PDF_TOKEN_REAL:
+      typ = "REAL";
+      snprintf(tmpbuf, sizeof(tmpbuf), "%f", pdf_token_get_real_value(token));
+      str = tmpbuf;
+      break;
+
+    case PDF_TOKEN_STRING:
+      typ = "STRING";
+      str = pdf_token_get_string_data(token);
+      strsize = pdf_token_get_string_size(token);
+      break;
+
+    case PDF_TOKEN_NAME:
+      typ = "NAME";
+      str = pdf_token_get_name_data(token);
+      strsize = pdf_token_get_name_size(token);
+      break;
+
+    case PDF_TOKEN_COMMENT:
+      typ = "COMMENT";
+      str = pdf_token_get_comment_data(token);
+      strsize = pdf_token_get_comment_size(token);
+      break;
+
+    case PDF_TOKEN_KEYWORD:
+      typ = "KEYWORD";
+      str = pdf_token_get_keyword_data(token);
+      strsize = pdf_token_get_keyword_size(token);
+      break;
+
+    case PDF_TOKEN_DICT_START:
+      typ = "DICT_START";
+      break;
+    case PDF_TOKEN_DICT_END:
+      typ = "DICT_END";
+      break;
+    case PDF_TOKEN_ARRAY_START:
+      typ = "ARRAY_START";
+      break;
+    case PDF_TOKEN_ARRAY_END:
+      typ = "ARRAY_END";
+      break;
+    case PDF_TOKEN_PROC_START:
+      typ = "PROC_START";
+      break;
+    case PDF_TOKEN_PROC_END:
+      typ = "PROC_END";
+      break;
+
+    default:
+      typ = "[unknown]";
+      sprintf(tmpbuf, "%d", pdf_token_get_type(token));
+      str = tmpbuf;
+    }
+
+  if (str == NULL)
+    {
+      tmpbuf[0] = '\0';
+      str = tmpbuf;
+    }
+  if (str != tmpbuf) str = fmtbin(str, strsize);
+  printf("%s(%s)\n", typ, str);
+  if (str != tmpbuf)
+    {
+      free((void*)str);
+    }
+};
+
+void print_file(FILE *file)
+{
+  pdf_status_t rv;
+  pdf_token_reader_t reader = NULL;
+  pdf_token_t token;
+  pdf_stm_t stm = NULL;
+
+  rv = pdf_stm_cfile_new (file, 0, 0 /*cache_size*/, PDF_STM_READ, &stm);
+  if (rv != PDF_OK)
+    {
+      fprintf(stderr, "failed to create stream\n");
+      goto out;
+    }
+
+  rv = pdf_token_reader_new(stm, &reader);
+  if (rv != PDF_OK)
+    {
+      fprintf(stderr, "failed to create reader\n");
+      goto out;
+    }
+
+  while (( rv = pdf_token_read(reader, 0, &token) ) == PDF_OK)
+    {
+      print_tok(token);
+      pdf_token_destroy(token);
+    }
+
+  if (rv != PDF_EEOF)
+    {
+      fprintf(stderr, "read_token error %d\n", rv);
+      goto out;
+    }
+
+  fprintf(stderr, "done\n");
+out:
+  if (reader) pdf_token_reader_destroy(reader);
+  if (stm) pdf_stm_destroy(stm);
+}
+
+int main(int argc, char **argv)
+{
+  setlocale(LC_ALL, "");
+  print_file(stdin);
+  return 0;
+}

# Begin bundle
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
Pis5jY/+C7kinChIeWGcjIA=

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]