I've updated the token writer based on Jose's comments, and made a few
other minor changes.  This version is ready for merging.

I'm working on updating the architecture guide, and will document the
new constants there.

-- Michael
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [email protected]
# target_branch: file:///home/michael/src/%2Blocal/gnupdf/trunk/
# testament_sha1: fb266394f7c26838f80b89354244f5ab02057eea
# timestamp: 2009-10-29 15:41:19 -0400
# base_revision_id: [email protected]
# 
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog	2009-10-28 22:23:59 +0000
+++ ChangeLog	2009-10-29 08:13:10 +0000
@@ -1,3 +1,21 @@
+2009-10-29  Michael Gold  <[email protected]>
+
+	* src/base/pdf-token-writer.c: New file.
+
+	* src/base/pdf-token-writer.h: New file.
+
+	* src/Makefile.am: Build the token writer.
+
+	* src/base/pdf-stm.c (pdf_stm_write): Mark 'buf' as const.
+
+	* src/base/pdf-stm.h: Likewise.
+
+	* doc/gnupdf.texi: Update tokeniser documentation.
+
+	* utils/pdf-tokeniser.c: Optionally use the token writer for output.
+
+	* utils/pdf-tokeniser.h: Likewise.
+
 2009-10-28  Jose E. Marchesi  <[email protected]>
 
 	* gnulib modules updated and unistr/u8-check imported.

=== modified file 'doc/gnupdf.texi'
--- doc/gnupdf.texi	2009-10-28 20:45:55 +0000
+++ doc/gnupdf.texi	2009-10-29 08:13:10 +0000
@@ -4506,7 +4506,7 @@
 @end table
 @end deftypefun
 
-...@deftypefun pdf_status_t pdf_stm_write (pdf_stm_t @var{stm}, pdf_char_t *...@var{buf}, pdf_size_t @var{bytes}, pdf_size_t *...@var{written_bytes})
+...@deftypefun pdf_status_t pdf_stm_write (pdf_stm_t @var{stm}, const pdf_char_t *...@var{buf}, pdf_size_t @var{bytes}, pdf_size_t *...@var{written_bytes})
 
 Write a chunk of data into a given stream.
 
@@ -10113,6 +10113,8 @@
 @table @code
 @item PDF_OK
 The token reader was destroyed.
+...@item PDF_EBADDATA
+...@var{reader} was NULL.
 @end table
 @item Usage example
 @example
@@ -10141,6 +10143,8 @@
 @table @code
 @item PDF_OK
 The token writer was destroyed.
+...@item PDF_EBADDATA
+...@var{writer} was NULL.
 @end table
 @item Usage example
 @example
@@ -10276,6 +10280,25 @@
 @end table
 @end deftypefun
 
+...@deftypefun pdf_status_t pdf_token_writer_reset (pdf_token_writer_t @var{writer})
+
+Reset the state of the token writer.
+
+...@table @strong
+...@item Parameters
+...@table @var
+...@item reader
+A token writer.
+...@end table
+...@item Returns
+A PDF status value:
+...@table @code
+...@item PDF_OK
+The operation succeeded.
+...@end table
+...@end table
+...@end deftypefun
+
 @node Creating and destroying tokens
 @subsection Creating and destroying tokens
 

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2009-06-27 23:19:51 +0000
+++ src/Makefile.am	2009-10-25 18:06:21 +0000
@@ -84,7 +84,8 @@
                     base/pdf-fp-func.h base/pdf-fp-func.c
 
 TOKEN_MODULE_SOURCES = base/pdf-token.c base/pdf-token.h \
-                       base/pdf-token-reader.c base/pdf-token-reader.h
+                       base/pdf-token-reader.c base/pdf-token-reader.h \
+                       base/pdf-token-writer.c base/pdf-token-writer.h
 
 BASE_LAYER_SOURCES = base/pdf-base.c base/pdf-base.h \
                      $(ALLOC_MODULE_SOURCES) \
@@ -143,7 +144,8 @@
               base/pdf-crypt.h \
               base/pdf-fp-func.h \
               base/pdf-token.h \
-              base/pdf-token-reader.h
+              base/pdf-token-reader.h \
+              base/pdf-token-writer.h
 
 pdf.h : $(PUBLIC_HDRS)
 	chmod +x $(top_builddir)/src/extract-public-hdr

=== modified file 'src/base/pdf-stm.c'
--- src/base/pdf-stm.c	2009-10-28 20:45:55 +0000
+++ src/base/pdf-stm.c	2009-10-29 08:13:10 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/10/28 21:28:26 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-10-29 03:45:34 mgold"
  *
  *       File:         pdf-stm.c
  *       Date:         Fri Jul  6 18:43:15 2007
@@ -212,7 +212,7 @@
 
 pdf_status_t
 pdf_stm_write (pdf_stm_t stm,
-               pdf_char_t *buf,
+               const pdf_char_t *buf,
                pdf_size_t bytes,
                pdf_size_t *written_bytes)
 {

=== modified file 'src/base/pdf-stm.h'
--- src/base/pdf-stm.h	2009-10-28 20:45:55 +0000
+++ src/base/pdf-stm.h	2009-10-29 08:13:10 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/10/28 21:26:53 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-10-29 03:45:34 mgold"
  *
  *       File:         pdf-stm.h
  *       Date:         Fri Jul  6 18:37:57 2007
@@ -111,7 +111,7 @@
                            pdf_size_t bytes,
                            pdf_size_t *read_bytes);
 pdf_status_t pdf_stm_write (pdf_stm_t stm,
-                            pdf_char_t *buf,
+                            const pdf_char_t *buf,
                             pdf_size_t bytes,
                             pdf_size_t *written_bytes);
 pdf_status_t pdf_stm_read_char (pdf_stm_t stm, pdf_char_t *c);

=== added file 'src/base/pdf-token-writer.c'
--- src/base/pdf-token-writer.c	1970-01-01 00:00:00 +0000
+++ src/base/pdf-token-writer.c	2009-10-29 16:52:54 +0000
@@ -0,0 +1,887 @@
+/* -*- mode: C -*- Time-stamp: "2009-10-29 16:51:18 mgold"
+ *
+ *       File:         pdf-token-writer.c
+ *       Date:         Wed Sep 23 04:37:51 2009
+ *
+ *       GNU PDF Library - Stream token writer
+ *
+ */
+
+/* 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 <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include <pdf-token-writer.h>
+#include <unistr.h>
+
+pdf_status_t
+pdf_token_writer_new (pdf_stm_t stm, pdf_token_writer_t *writer)
+{
+  pdf_status_t err;
+  pdf_token_writer_t new_tokw;
+
+  err = PDF_ENOMEM;
+  new_tokw = pdf_alloc (sizeof (*new_tokw));
+  if (!new_tokw)
+    goto fail;
+
+  /* determine the current locale's decimal point
+   * (avoid using localeconv since it may not be thread-safe) */
+  new_tokw->decimal_point = NULL;
+  {
+    int len;
+    char decpt[16];
+
+    err = PDF_ERROR;
+    len = snprintf (decpt, sizeof (decpt), "%#.0f", 1.0);
+    if (len <= 0 || (pdf_size_t)len >= sizeof (decpt))  /* shouldn't happen */
+      goto fail;
+
+    err = PDF_ENOMEM;
+    new_tokw->decimal_point = pdf_alloc (len);
+    if (!new_tokw->decimal_point)
+      goto fail;
+
+    /* this copies the trailing '\0' due to the starting offset */
+    memcpy (new_tokw->decimal_point, &decpt[1], len);
+  }
+
+  /* set max_line_length to 0 for no maximum */
+  new_tokw->max_line_length = PDF_TOKW_MAX_LINE_LENGTH;
+
+  err = PDF_ENOMEM;
+  new_tokw->buffer = pdf_buffer_new (PDF_TOKW_BUFFER_SIZE);
+  if (!new_tokw->buffer)
+    goto fail;
+
+  err = PDF_EBADDATA;
+  if (!stm || pdf_stm_get_mode (stm) != PDF_STM_WRITE)
+    goto fail;
+  new_tokw->stream = stm;
+
+  pdf_token_writer_reset (new_tokw);
+
+  *writer = new_tokw;
+  return PDF_OK;
+
+fail:
+  if (new_tokw)
+    pdf_dealloc (new_tokw->decimal_point);
+  pdf_dealloc (new_tokw);
+
+  return err;
+}
+
+pdf_status_t
+pdf_token_writer_reset (pdf_token_writer_t writer)
+{
+  writer->stage = 0;
+  writer->in_keyword = PDF_FALSE;
+  writer->line_length = 0;
+  return PDF_OK;
+}
+
+pdf_status_t
+pdf_token_writer_destroy (pdf_token_writer_t writer)
+{
+  if (!writer) return PDF_EBADDATA;
+
+  assert (writer->buffer);
+  if (writer->buffer)
+    pdf_buffer_destroy (writer->buffer);
+  pdf_dealloc (writer->decimal_point);
+  pdf_dealloc (writer);
+
+  return PDF_OK;
+}
+
+
+/***** Unbuffered output *****/
+
+/* Write data to the stream.  All output passes through this function. */
+static pdf_status_t
+write_data (pdf_token_writer_t writer, const pdf_char_t *data,
+            pdf_size_t len, pdf_size_t *written)
+{
+  pdf_size_t i;
+  pdf_status_t rv;
+
+  rv = pdf_stm_write (writer->stream, data, len, written);
+  if (rv != PDF_OK)
+    return rv;
+
+  for (i = 0; i < *written; ++i)
+    {
+      pdf_char_t ch = data[i];
+      ++writer->line_length;
+      if (pdf_is_eol_char (ch))
+        writer->line_length = 0;
+
+      writer->in_keyword = pdf_is_regular_char (ch);
+    }
+  return PDF_OK;
+}
+
+/* Write a single character. */
+static INLINE pdf_status_t
+write_char (pdf_token_writer_t writer, pdf_char_t ch)
+{
+  pdf_size_t written;
+  return write_data (writer, &ch, 1, &written);
+}
+
+/* Write data starting at writer->pos, incrementing writer->pos as needed. */
+static INLINE pdf_status_t
+write_data_using_pos (pdf_token_writer_t writer,
+                      const pdf_char_t *data, pdf_size_t len)
+{
+  pdf_status_t rv;
+  pdf_size_t written;
+  if (writer->pos > len)
+    return PDF_EBADDATA;
+
+  while (writer->pos < len)
+    {
+      rv = write_data (writer, data + writer->pos, len - writer->pos,
+                       &written);
+      if (rv != PDF_OK)
+        return rv;
+
+      writer->pos += written;
+    }
+  return PDF_OK;
+}
+
+
+/***** Buffered output, buffer management *****/
+
+/* Write all buffered data to the stream. */
+static pdf_status_t
+flush_buffer (pdf_token_writer_t writer)
+{
+  pdf_buffer_t buf = writer->buffer;
+  pdf_size_t len;
+  while ( (len = buf->wp - buf->rp) > 0 )
+    {
+      pdf_size_t written;
+      pdf_status_t rv = write_data (writer,
+                                    buf->data + buf->rp,
+                                    len, &written);
+      if (rv != PDF_OK)
+        return rv;
+
+      buf->rp += written;
+    }
+  return pdf_buffer_rewind (buf);
+}
+
+/* Flush the buffer if there are less than 'len' bytes free. */
+static INLINE pdf_status_t
+reserve_buffer_space (pdf_token_writer_t writer, pdf_size_t len)
+{
+  if (writer->buffer->wp + len > writer->buffer->size)
+    {
+      pdf_status_t rv = flush_buffer (writer);
+      if (rv != PDF_OK)
+        return rv;
+
+      assert (len < writer->buffer->size);
+      assert (writer->buffer->wp == 0);
+    }
+  return PDF_OK;
+}
+
+/* Write a character into the buffer; this assumes it will fit. */
+static INLINE void
+write_buffered_char_nocheck (pdf_token_writer_t writer, pdf_char_t ch)
+{
+  writer->buffer->data[writer->buffer->wp++] = ch;
+  if (pdf_is_eol_char(ch))
+    writer->buffered_line_length = 0;
+  else
+    ++writer->buffered_line_length;
+}
+
+/* Write a character into the buffer.  The buffer is flushed only if
+ * there's no room to write the character. */
+static INLINE pdf_status_t
+write_buffered_char (pdf_token_writer_t writer, pdf_char_t ch)
+{
+  pdf_status_t rv = reserve_buffer_space (writer, 1);
+  if (rv == PDF_OK)
+    write_buffered_char_nocheck (writer, ch);
+  return rv;
+}
+
+
+/***** Misc. utility functions *****/
+
+/* Takes a number from 0 to 15 and returns the ASCII code for the
+ * corresponding hexadecimal digit. */
+static INLINE pdf_char_t
+hexchar (pdf_char_t value)
+{
+  if (value < 10)
+    return 48 + value;       /* '0'--'9' */
+  else if (value < 16)
+    return 65 + value - 10;  /* 'A'--'F' */
+  return 255;
+}
+
+/* Prepare to write a new token, adding some whitespace if necessary. */
+static pdf_status_t
+start_token (pdf_token_writer_t writer, pdf_bool_t need_wspace,
+             pdf_size_t len)
+{
+  pdf_bool_t add_wspace = (need_wspace && writer->in_keyword);
+  pdf_char_t wspace_char = 32;  /* space */
+
+  if (add_wspace)
+    ++len;
+
+  /* If the token would make this line too long, start a new line. */
+  if (writer->line_length + len > writer->max_line_length
+       && writer->max_line_length > 0)
+    {
+      add_wspace = PDF_TRUE;
+      wspace_char = 10;  /* newline */
+    }
+
+  if (add_wspace)
+    {
+      pdf_status_t rv = write_char (writer, wspace_char);
+      if (rv != PDF_OK) return rv;
+    }
+
+  return PDF_OK;
+}
+
+
+/***** Numeric tokens *****/
+
+/* Encode snprintf output for PDF.  'len' is the return value of snprintf.
+ * Re-encodes bytes 0 to 'len' of writer->buffer and resets buffer->rp/wp. */
+static pdf_bool_t
+encode_buffer_number (pdf_token_writer_t writer, int len)
+{
+  pdf_buffer_t buf = writer->buffer;
+  if (len < 0 || len >= buf->size)
+    return PDF_FALSE;  /* snprintf failed, or truncated its output. */
+
+  buf->wp = buf->rp = 0;
+  while (buf->rp < len)
+    {
+      char ch = (char)buf->data[buf->rp];
+      if (ch == '-')
+        {
+          ++buf->rp;
+          buf->data[buf->wp++] = 45;  /* '-' */
+        }
+      else if (ch >= '0' && ch <= '9')
+        {
+          ++buf->rp;
+          buf->data[buf->wp++] = 48 + (ch - '0');
+        }
+      else
+        {
+          /* This should be a decimal point; check it. */
+          pdf_size_t declen = strlen (writer->decimal_point);
+          int cmp = memcmp (buf->data + buf->rp,
+                            writer->decimal_point, declen);
+          if (cmp != 0)
+            return PDF_FALSE;  /* unexpected char */
+
+          buf->rp += declen;
+          buf->data[buf->wp++] = 46;  /* '.' */
+        }
+    }
+  buf->rp = 0;
+  return PDF_TRUE;  /* success */
+}
+
+static INLINE pdf_status_t
+write_integer_token (pdf_token_writer_t writer, pdf_token_t token)
+{
+  pdf_status_t rv;
+  switch (writer->stage)
+    {
+      case 0:
+        {
+          pdf_i32_t value = pdf_token_get_integer_value (token);
+          int len = snprintf ((char*)writer->buffer->data,
+                              writer->buffer->size, "%"PRId32, value);
+          if (!encode_buffer_number (writer, len)) return PDF_ERROR;
+        }
+        ++writer->stage;  /* fall through */
+      case 1:
+        rv = start_token (writer, PDF_TRUE /*need_wspace*/,
+                          writer->buffer->wp);
+        if (rv != PDF_OK) return rv;
+        ++writer->stage;  /* fall through */
+      case 2:
+        return flush_buffer (writer);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+static INLINE pdf_status_t
+write_real_token (pdf_token_writer_t writer, pdf_token_t token)
+{
+  pdf_status_t rv;
+  switch (writer->stage)
+    {
+      case 0:
+        {
+          pdf_buffer_t buf = writer->buffer;
+          pdf_real_t value = pdf_token_get_real_value (token);
+          if (isnan(value) || isinf(value))
+            return PDF_EBADDATA;
+
+          /* The '#' flag forces snprintf to write a decimal point. */
+          int len = snprintf ((char*)buf->data,
+                              buf->size, "%#f", (double)value);
+          if (!encode_buffer_number (writer, len)) return PDF_ERROR;
+
+          /* strip trailing zeroes */
+          while (buf->wp && buf->data[buf->wp-1] == 48 /* '0' */)
+            --buf->wp;
+        }
+        ++writer->stage;  /* fall through */
+      case 1:
+        rv = start_token (writer, PDF_TRUE /*need_wspace*/,
+                          writer->buffer->wp);
+        if (rv != PDF_OK) return rv;
+        ++writer->stage;  /* fall through */
+      case 2:
+        return flush_buffer (writer);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+
+/***** String tokens *****/
+
+static INLINE pdf_bool_t
+should_escape_strchar (pdf_u32_t flags, pdf_char_t ch,
+                       pdf_bool_t quote_parens, pdf_bool_t is_utf8)
+{
+  if (ch == 92 /* '\\' */ || ch == 13 /* CR */)
+    return PDF_TRUE;
+  if (ch == 40 /* '(' */ || ch == 41 /* ')' */)
+    return quote_parens;
+
+  if (flags & PDF_TOKEN_READABLE_STRINGS)
+    {
+      if (ch == 127 || (ch < 32 && ch != 10)
+           || (ch >= 128 && !is_utf8))
+        return PDF_TRUE;
+    }
+
+  return PDF_FALSE;
+}
+
+static INLINE int
+str_escape_len (const pdf_char_t *data, pdf_size_t len, pdf_size_t pos)
+{
+  switch (data[pos])
+    {
+      /* characters with two-character escape codes */
+      case  8:
+      case  9:
+      case 10:
+      case 12:
+      case 13:
+      case 40:
+      case 41:
+      case 92:
+        return 2;
+    }
+
+  if (data[pos] >= 0100)
+    return 4;  /* escaped using a backslash and 3 octal characters */
+
+  if (pos+1 < len)
+    {
+      if (data[pos+1] >= 48 && data[pos+1] <= 57)  /* '0'..'9' */
+        return 4;  /* need to write a 3-character octal number */
+    }
+
+  return (data[pos] >= 010) ? 3 : 2;
+}
+
+static void
+scan_string (pdf_token_writer_t writer, pdf_u32_t flags,
+             const pdf_char_t *data, pdf_size_t len, pdf_bool_t *use_hex)
+{
+  /* Match parentheses, and determine the portion of the string
+   * in which they should be quoted. */
+  writer->paren_quoting_start = 0;
+  writer->paren_quoting_end = len;
+  pdf_size_t i, j;
+  for (i = 0; i < len; ++i)
+    {
+      if (data[i] == 40)       /* '(' */
+        {
+          for (j = writer->paren_quoting_end - 1; j > i; --j)
+            {
+              /* find a matching ')' */
+              if (data[j] == 41)
+                {
+                  writer->paren_quoting_end = j;
+                  writer->paren_quoting_start = i + 1;
+                  break;
+                }
+            }
+        }
+    }
+
+  /* Determine the size of the escaped string. */
+  writer->utf8 = (flags & PDF_TOKEN_READABLE_STRINGS)
+                   && (u8_check (data, len) == NULL);
+  pdf_size_t enc_bytes = 0;
+  for (i = 0; i < len; ++i)
+    {
+      pdf_bool_t quote_parens = (i >= writer->paren_quoting_start
+                                  && i < writer->paren_quoting_end);
+      if (should_escape_strchar (flags, data[i], quote_parens, writer->utf8))
+        enc_bytes += str_escape_len (data, len, i);
+      else
+        ++enc_bytes;
+    }
+  *use_hex = (enc_bytes > len*2);
+}
+
+static INLINE pdf_status_t
+write_string_char (pdf_token_writer_t writer, pdf_u32_t flags,
+                   const pdf_char_t *data, pdf_char_t len,
+                   pdf_size_t pos)
+{
+  assert (len > 0);
+  pdf_status_t rv;
+  const pdf_char_t *output = data + pos;
+  pdf_size_t outlen = 1;
+  pdf_char_t esc[4] = {92 /* '\\' */, 0, 0, 0};
+
+  pdf_char_t ch = data[pos];
+  pdf_bool_t quote_parens = (pos >= writer->paren_quoting_start
+                              && pos < writer->paren_quoting_end);
+  if (should_escape_strchar (flags, ch, quote_parens, writer->utf8))
+    {
+      /* escape the character */
+      output = esc;
+      outlen = 2;
+      switch (ch)
+        {
+          case  8: esc[1] =  98; break; /* 'b' */
+          case  9: esc[1] = 116; break; /* 't' */
+          case 10: esc[1] = 110; break; /* 'n' */
+          case 12: esc[1] = 102; break; /* 'f' */
+          case 13: esc[1] = 114; break; /* 'r' */
+          case 40:  /* '('; fall through */
+          case 41:  /* ')'; fall through */
+          case 92:  /* '\\' */
+            esc[1] = ch;
+            break;
+          default: /* use an octal escape */
+            {
+              pdf_size_t digits;
+              pdf_char_t nextch = (pos+1 < len) ? data[pos+1] : 0;
+              if (nextch >= 48 && nextch <= 57)  /* '0'..'9' */
+                digits = 3;  /* must use 3 octal characters */
+              else if (ch > 0100) digits = 3;
+              else if (ch > 010) digits = 2;
+              else digits = 1;
+
+              outlen = 1;
+              switch (digits)
+                {
+                  /* fall through each case */
+                  case 3: esc[outlen++] = hexchar (ch / 0100);
+                  case 2: esc[outlen++] = hexchar ((ch % 0100) / 010);
+                  case 1: esc[outlen++] = hexchar (ch % 010);
+                }
+              }
+        }
+    }
+
+  /* If the line will be too long, split it (the length cannot be equal to
+   * the maximum, since this would leave no room for the backslash). */
+  if (writer->max_line_length > 0 && !pdf_is_eol_char (output[0])
+       && writer->buffered_line_length + outlen >= writer->max_line_length)
+    {
+      rv = reserve_buffer_space (writer, 2);
+      if (rv != PDF_OK) return rv;
+      write_buffered_char_nocheck (writer, 92);  /* '\\' */
+      write_buffered_char_nocheck (writer, 10);  /* newline */
+      assert (writer->buffered_line_length == 0);
+    }
+
+  rv = reserve_buffer_space (writer, outlen);
+  if (rv == PDF_OK)
+    {
+      pdf_size_t i;
+      for (i = 0; i < outlen; ++i)
+        write_buffered_char_nocheck (writer, output[i]);
+    }
+  return rv;
+}
+
+static INLINE pdf_status_t
+write_string_token (pdf_token_writer_t writer, pdf_u32_t flags,
+                    pdf_token_t token)
+{
+  pdf_status_t rv;
+  const pdf_char_t *data = pdf_token_get_string_data (token);
+  pdf_size_t size = pdf_token_get_string_size (token);
+
+  switch (writer->stage)
+    {
+      case 0:
+        {
+          pdf_bool_t use_hex = (flags & PDF_TOKEN_HEX_STRINGS);
+          if (!use_hex)
+            scan_string (writer, flags, data, size, &use_hex);
+
+          if (use_hex)
+            goto hexstring_start;
+        }
+        ++writer->stage;  /* fall through */
+      case 1:
+        {
+          /* Passing a correct length to start_token isn't important
+           * since we can split the string across multiple lines. */
+          pdf_size_t dummy_len = PDF_MIN(20, 2 + size);
+          rv = start_token (writer, PDF_FALSE /*need_wspace*/, dummy_len);
+          if (rv != PDF_OK) return rv;
+        }
+
+        pdf_buffer_rewind (writer->buffer);
+        writer->buffered_line_length = writer->line_length;
+        write_buffered_char_nocheck (writer, 40 /* '(' */);
+        writer->pos = 0;
+        ++writer->stage;  /* fall through */
+      case 2:
+        while (writer->pos < size)
+          {
+            rv = write_string_char (writer, flags, data, size, writer->pos);
+            if (rv != PDF_OK) return rv;
+
+            ++writer->pos;
+          }
+        ++writer->stage;  /* fall through */
+      case 3:
+        rv = write_buffered_char (writer, 41 /* ')' */);
+        if (rv != PDF_OK) return rv;
+        ++writer->stage;  /* fall through */
+      case 4:
+        return flush_buffer (writer);
+
+      /*** hex strings ***/
+hexstring_start:
+      writer->stage = 101;
+      case 101:
+        {
+          pdf_size_t dummy_len = PDF_MIN(20, 2 + size*2);
+          rv = start_token (writer, PDF_FALSE /*need_wspace*/, dummy_len);
+          if (rv != PDF_OK) return rv;
+        }
+
+        pdf_buffer_rewind (writer->buffer);
+        writer->buffered_line_length = writer->line_length;
+        write_buffered_char_nocheck (writer, 60 /* '<' */);
+        writer->pos = 0;
+        ++writer->stage;  /* fall through */
+      case 102:
+        while (writer->pos < size)
+          {
+            /* If this line would be too long, start a new one. */
+            if (writer->buffered_line_length + 2 > writer->max_line_length
+                 && writer->max_line_length > 0)
+              {
+                rv = write_buffered_char (writer, 10);  /* newline */
+                if (rv != PDF_OK) return rv;
+                assert (writer->buffered_line_length == 0);
+              }
+
+            pdf_char_t ch = data[writer->pos];
+            rv = reserve_buffer_space (writer, 2);
+            if (rv != PDF_OK) return rv;
+
+            write_buffered_char_nocheck (writer, hexchar (ch / 16));
+            if (writer->pos == size-1 && (ch%16) == 0)
+              ;  /* don't write a final 0 */
+            else
+              write_buffered_char_nocheck (writer, hexchar (ch % 16));
+            ++writer->pos;
+          }
+        ++writer->stage;  /* fall through */
+      case 103:
+        rv = write_buffered_char (writer, 62 /* '>' */);
+        if (rv != PDF_OK) return rv;
+        ++writer->stage;  /* fall through */
+      case 104:
+        return flush_buffer (writer);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+
+/***** Other tokens *****/
+
+static INLINE pdf_status_t
+should_escape_namechar (pdf_u32_t flags, pdf_char_t ch, pdf_bool_t *escape)
+{
+  if (!ch)
+    return PDF_EBADDATA;
+
+  *escape = !pdf_is_regular_char (ch);
+  if (flags & PDF_TOKEN_NO_NAME_ESCAPES)
+    {
+      if (*escape)
+        return PDF_EBADDATA;
+    }
+  else
+    {
+      *escape = *escape || ch == 35 /* '#' */
+                || ch < 33 || ch >= 127;
+    }
+  return PDF_OK;
+}
+
+static INLINE pdf_status_t
+write_name_token (pdf_token_writer_t writer, pdf_u32_t flags,
+                  pdf_token_t token)
+{
+  pdf_status_t rv;
+  pdf_size_t size = pdf_token_get_name_size (token);
+  const pdf_char_t *data = pdf_token_get_name_data (token);
+  switch (writer->stage)
+    {
+      case 0:
+        /* Validate the name; also calculate the encoded size
+         * and store it in ->pos temporarily. */
+        writer->pos = 1 + size;
+        {
+          pdf_size_t i;
+          for (i = 0; i < size; ++i)
+            {
+              pdf_bool_t escape;
+              rv = should_escape_namechar (flags, data[i], &escape);
+              if (rv != PDF_OK) return rv;  /* bad name */
+
+              if (escape)
+                writer->pos += 2;  /* 2 hex characters */
+            }
+        }
+        pdf_buffer_rewind (writer->buffer);
+        write_buffered_char_nocheck (writer, 47 /* '/' */);
+        ++writer->stage;  /* fall through */
+      case 1:
+        rv = start_token (writer, PDF_FALSE /*need_wspace*/,
+                          writer->pos /* encoded token length */);
+        if (rv != PDF_OK) return rv;
+
+        writer->pos = 0;
+        ++writer->stage;  /* fall through */
+      case 2:
+        while (writer->pos < size)
+          {
+            pdf_bool_t escape;
+            pdf_char_t ch = data[writer->pos];
+            rv = should_escape_namechar (flags, ch, &escape);
+            if (rv != PDF_OK) return rv;  /* bad name */
+
+            if (escape)
+              {
+                rv = reserve_buffer_space (writer, 3);
+                if (rv != PDF_OK) return rv;
+
+                write_buffered_char_nocheck (writer, 35 /* '#' */);
+                write_buffered_char_nocheck (writer, hexchar (ch / 16));
+                write_buffered_char_nocheck (writer, hexchar (ch % 16));
+              }
+            else
+              {
+                rv = write_buffered_char (writer, ch);
+                if (rv != PDF_OK) return rv;
+              }
+            ++writer->pos;
+          }
+        ++writer->stage;  /* fall through */
+      case 3:
+        return flush_buffer (writer);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+static INLINE pdf_status_t
+write_keyword_token (pdf_token_writer_t writer, pdf_token_t token)
+{
+  const pdf_char_t *data = pdf_token_get_keyword_data (token);
+  pdf_size_t size = pdf_token_get_keyword_size (token);
+  pdf_status_t rv;
+  switch (writer->stage)
+    {
+      case 0:
+        if (memchr (data, 0, size))
+          return PDF_EBADDATA;  /* data contains a null byte */
+        ++writer->stage;  /* fall through */
+      case 1:
+        rv = start_token (writer, PDF_TRUE /*need_wspace*/, size);
+        if (rv != PDF_OK) return rv;
+
+        writer->pos = 0;
+        ++writer->stage;  /* fall through */
+      case 2:
+        return write_data_using_pos (writer,
+                                     pdf_token_get_keyword_data (token),
+                                     size);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+static INLINE pdf_status_t
+write_comment_token (pdf_token_writer_t writer, pdf_token_t token)
+{
+  const pdf_char_t *data = pdf_token_get_comment_data (token);
+  pdf_size_t size = pdf_token_get_comment_size (token);
+  pdf_status_t rv;
+  switch (writer->stage)
+    {
+      case 0:
+        {
+          /* A comment can't span multiple lines. */
+          pdf_size_t i;
+          for (i = 0; i < size; ++i)
+            {
+              if (pdf_is_eol_char(data[i]))
+              return PDF_EBADDATA;
+            }
+        }
+        ++writer->stage;  /* fall through */
+      case 1:
+        rv = start_token (writer, PDF_FALSE /*need_wspace*/, size+1);
+        if (rv != PDF_OK) return rv;
+        ++writer->stage;  /* fall through */
+      case 2:
+        rv = write_char (writer, 37 /* '%' */);
+        if (rv != PDF_OK) return rv;
+
+        writer->pos = 0;
+        ++writer->stage;  /* fall through */
+      case 3:
+        rv = write_data_using_pos (writer, data, size);
+        if (rv != PDF_OK) return rv;
+        ++writer->stage;  /* fall through */
+      case 4:
+        return write_char (writer, 10 /* '\n' */);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+static INLINE pdf_status_t
+write_valueless_token (pdf_token_writer_t writer,
+                       pdf_char_t ch, pdf_size_t len)
+{
+  pdf_char_t buf[2] = {ch,ch};
+  pdf_status_t rv;
+  assert (len == 1 || len == 2);
+
+  switch (writer->stage)
+    {
+      case 0:
+        rv = start_token (writer, PDF_FALSE /*need_wspace*/, len);
+        if (rv != PDF_OK) return rv;
+
+        writer->pos = 0;
+        ++writer->stage;  /* fall through */
+      case 1:
+        return write_data_using_pos (writer, buf, len);
+      default:
+        return PDF_EBADDATA;
+    }
+}
+
+
+/***** Token dispatching *****/
+
+pdf_status_t
+pdf_token_write (pdf_token_writer_t writer, pdf_u32_t flags, pdf_token_t token)
+{
+  pdf_status_t rv;
+  switch (pdf_token_get_type (token))
+    {
+      case PDF_TOKEN_INTEGER:
+        rv = write_integer_token (writer, token);
+        break;
+      case PDF_TOKEN_REAL:
+        rv = write_real_token (writer, token);
+        break;
+      case PDF_TOKEN_STRING:
+        rv = write_string_token (writer, flags, token);
+        break;
+      case PDF_TOKEN_NAME:
+        rv = write_name_token (writer, flags, token);
+        break;
+      case PDF_TOKEN_KEYWORD:
+        rv = write_keyword_token (writer, token);
+        break;
+      case PDF_TOKEN_COMMENT:
+        rv = write_comment_token (writer, token);
+        break;
+      case PDF_TOKEN_DICT_START:
+        rv = write_valueless_token (writer, 60 /* '<' */, 2);
+        break;
+      case PDF_TOKEN_DICT_END:
+        rv = write_valueless_token (writer, 62 /* '>' */, 2);
+        break;
+      case PDF_TOKEN_ARRAY_START:
+        rv = write_valueless_token (writer, 91 /* '[' */, 1);
+        break;
+      case PDF_TOKEN_ARRAY_END:
+        rv = write_valueless_token (writer, 93 /* ']' */, 1);
+        break;
+      case PDF_TOKEN_PROC_START:
+        rv = write_valueless_token (writer, 123 /* '{' */, 1);
+        break;
+      case PDF_TOKEN_PROC_END:
+        rv = write_valueless_token (writer, 125 /* '}' */, 1);
+        break;
+      default:
+        assert (0);
+        return PDF_ERROR;
+    }
+
+  if (rv == PDF_OK)
+    writer->stage = 0;
+  return rv;
+}
+
+/* End of pdf-token-writer.c */

=== added file 'src/base/pdf-token-writer.h'
--- src/base/pdf-token-writer.h	1970-01-01 00:00:00 +0000
+++ src/base/pdf-token-writer.h	2009-10-29 17:07:37 +0000
@@ -0,0 +1,76 @@
+/* -*- mode: C -*- Time-stamp: "2009-10-25 18:06:21 mgold"
+ *
+ *       File:         pdf-token-writer.h
+ *       Date:         Wed Sep 23 04:30:26 2009
+ *
+ *       GNU PDF Library - Stream token writer
+ *
+ */
+
+/* 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/>.
+ */
+
+#ifndef PDF_TOKEN_WRITER_H
+#define PDF_TOKEN_WRITER_H
+
+#include <config.h>
+
+#include <pdf-types.h>
+#include <pdf-stm.h>
+#include <pdf-token.h>
+#include <pdf-token-reader.h>
+
+/* BEGIN PUBLIC */
+/* pdf-token-writer.h */
+
+struct pdf_token_writer_s;  /* opaque type */
+typedef struct pdf_token_writer_s *pdf_token_writer_t;
+
+pdf_status_t pdf_token_writer_new (pdf_stm_t stm, pdf_token_writer_t *writer);
+pdf_status_t pdf_token_writer_destroy (pdf_token_writer_t writer);
+pdf_status_t pdf_token_writer_reset (pdf_token_writer_t writer);
+pdf_status_t pdf_token_write (pdf_token_writer_t writer, pdf_u32_t flags,
+                              pdf_token_t token);
+
+/* END PUBLIC */
+
+/* Internal state */
+struct pdf_token_writer_s {
+  pdf_stm_t stream;  /* stream to read bytes from */
+  char *decimal_point;
+
+  pdf_bool_t in_keyword;
+  pdf_size_t line_length, buffered_line_length, max_line_length;
+
+  int stage;
+  pdf_size_t pos;
+  pdf_size_t paren_quoting_start, paren_quoting_end;
+  pdf_bool_t utf8;
+  pdf_buffer_t buffer;
+};
+
+/* PDF32000 7.5.1: "lines that are not part of stream object data
+ * are limited to no more than 255 characters"... */
+#define PDF_TOKW_MAX_LINE_LENGTH 255
+
+/* The buffer size is mostly arbitrary, but the buffer must be large
+ * enough for snprintf to write any possible floating point value.
+ * Any number over 50 should be fine. */
+#define PDF_TOKW_BUFFER_SIZE 32768
+
+#endif
+
+/* End of pdf-token-writer.h */

=== modified file 'utils/pdf-tokeniser.c'
--- utils/pdf-tokeniser.c	2009-10-21 12:59:20 +0000
+++ utils/pdf-tokeniser.c	2009-10-29 16:52:54 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/10/21 14:57:10 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-10-29 15:43:35 mgold"
  *
  *       File:         pdf-tokeniser.c
  *       Date:         Wed May 20 05:25:40 2009
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <getopt.h>
+#include <errno.h>
 #include <pdf.h>
 
 #include <pdf-tokeniser.h>
@@ -43,6 +44,9 @@
     {"help", no_argument, NULL, HELP_ARG},
     {"usage", no_argument, NULL, USAGE_ARG},
     {"version", no_argument, NULL, VERSION_ARG},
+    {"token-writer", no_argument, NULL, TOKW_ARG},
+    {"reader-flags", required_argument, NULL, READER_FLAGS_ARG},
+    {"writer-flags", required_argument, NULL, WRITER_FLAGS_ARG},
     {NULL, 0, NULL, 0}
   };
 
@@ -59,6 +63,9 @@
   --help                              print a help message and exit\n\
   --usage                             print a usage message and exit\n\
   --version                           show pdf-tokeniser version and exit\n\
+  --token-writer                      generate output using the token writer\n\
+  --reader-flags=INTEGER              specify token reader flags\n\
+  --writer-flags=INTEGER              specify token writer flags\n\
 ";
 
 char *pdf_tokeniser_help_msg = "";
@@ -183,30 +190,62 @@
 };
 
 void
-print_file (FILE *file)
+print_file (FILE *file, pdf_bool_t use_tokw,
+            pdf_u32_t reader_flags, pdf_u32_t writer_flags)
 {
   pdf_status_t rv;
   pdf_token_reader_t reader = NULL;
+  pdf_token_writer_t writer = NULL;
   pdf_token_t token;
-  pdf_stm_t stm = NULL;
+  pdf_stm_t stm_in = NULL;
+  pdf_stm_t stm_out = NULL;
 
-  rv = pdf_stm_cfile_new (file, 0, 0 /*cache_size*/, PDF_STM_READ, &stm);
+  rv = pdf_stm_cfile_new (file, 0, 0 /*cache_size*/, PDF_STM_READ, &stm_in);
   if (rv != PDF_OK)
     {
-      fprintf(stderr, "failed to create stream\n");
+      fprintf(stderr, "failed to create input stream\n");
       goto out;
     }
 
-  rv = pdf_token_reader_new(stm, &reader);
+  rv = pdf_token_reader_new(stm_in, &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);
+  if (use_tokw)
+    {
+      rv = pdf_stm_cfile_new (stdout, 0, 0 /*cache_size*/,
+                              PDF_STM_WRITE, &stm_out);
+      if (rv != PDF_OK)
+        {
+          fprintf(stderr, "failed to create output stream\n");
+          goto out;
+        }
+
+      rv = pdf_token_writer_new(stm_out, &writer);
+      if (rv != PDF_OK)
+        {
+          fprintf(stderr, "failed to create writer\n");
+          goto out;
+        }
+    }
+
+  while (( rv = pdf_token_read(reader, reader_flags, &token) ) == PDF_OK)
+    {
+      if (use_tokw)
+        {
+          rv = pdf_token_write(writer, writer_flags, token);
+          if (rv != PDF_OK)
+            {
+              fprintf(stderr, "pdf_token_write error %d\n", rv);
+              goto out;
+            }
+        }
+      else
+        print_tok(token);
+
       pdf_token_destroy(token);
     }
 
@@ -218,14 +257,37 @@
 
   fprintf(stderr, "done\n");
 out:
+  if (writer) pdf_token_writer_destroy(writer);
+  if (stm_out) pdf_stm_destroy(stm_out);
   if (reader) pdf_token_reader_destroy(reader);
-  if (stm) pdf_stm_destroy(stm);
+  if (stm_in) pdf_stm_destroy(stm_in);
+}
+
+pdf_u32_t
+parse_u32_arg (const char *argvalue, const char *argname, const char *appname)
+{
+  char *end;
+  pdf_u32_t ret;
+  unsigned long int tmp;
+
+  errno = 0;
+  tmp = strtoul (argvalue, &end, 0);
+  ret = (pdf_u32_t)tmp;
+  if (errno || *end != '\0' || tmp != ret)
+    {
+      fprintf (stderr, "%s: invalid argument `%s' for `--%s'\n",
+               appname, argvalue, argname);
+      exit (1);
+    }
+  return ret;
 }
 
 int
 main (int argc, char **argv)
 {
   char c;
+  pdf_bool_t use_tokw = PDF_FALSE;
+  pdf_u32_t reader_flags = 0, writer_flags = 0;
 
   /*  set_program_name (argv[0]); */
 
@@ -256,6 +318,21 @@
             exit (0);
             break;
           }
+        case TOKW_ARG:
+          {
+            use_tokw = 1;
+            break;
+          }
+        case READER_FLAGS_ARG:
+          {
+            reader_flags = parse_u32_arg (optarg, "reader-flags", argv[0]);
+            break;
+          }
+        case WRITER_FLAGS_ARG:
+          {
+            writer_flags = parse_u32_arg (optarg, "writer-flags", argv[0]);
+            break;
+          }
         default:
           {
             break;
@@ -264,6 +341,6 @@
     }
 
   setlocale(LC_ALL, "");
-  print_file(stdin);
+  print_file(stdin, use_tokw, reader_flags, writer_flags);
   return 0;
 }

=== modified file 'utils/pdf-tokeniser.h'
--- utils/pdf-tokeniser.h	2009-06-28 09:20:53 +0000
+++ utils/pdf-tokeniser.h	2009-10-29 08:13:10 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/06/24 20:56:43 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-10-25 18:06:21 mgold"
  *
  *       File:         pdf-tokeniser.h
  *       Date:         Wed Jun 24 20:54:49 2009
@@ -35,7 +35,10 @@
 {
   HELP_ARG,
   USAGE_ARG,
-  VERSION_ARG
+  VERSION_ARG,
+  TOKW_ARG,
+  READER_FLAGS_ARG,
+  WRITER_FLAGS_ARG
 };
 
 #endif /* pdf-tokeniser.h */

# Begin bundle
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

Attachment: signature.asc
Description: Digital signature

Reply via email to