[OpenPGP:SDK svn] r320 - in openpgpsdk/trunk: examples include/openpgpsdk src

Subversion ben at algroup.co.uk
Wed Dec 7 09:39:46 GMT 2005


Author: ben
Date: 2005-12-07 09:39:44 +0000 (Wed, 07 Dec 2005)
New Revision: 320

Modified:
   openpgpsdk/trunk/examples/common.c
   openpgpsdk/trunk/examples/packet-dump.c
   openpgpsdk/trunk/examples/verify.c
   openpgpsdk/trunk/examples/verify2.c
   openpgpsdk/trunk/include/openpgpsdk/armour.h
   openpgpsdk/trunk/include/openpgpsdk/errors.h
   openpgpsdk/trunk/include/openpgpsdk/packet-parse.h
   openpgpsdk/trunk/include/openpgpsdk/util.h
   openpgpsdk/trunk/src/accumulate.c
   openpgpsdk/trunk/src/armour.c
   openpgpsdk/trunk/src/compress.c
   openpgpsdk/trunk/src/create.c
   openpgpsdk/trunk/src/errors.c
   openpgpsdk/trunk/src/packet-parse.c
   openpgpsdk/trunk/src/util.c
   openpgpsdk/trunk/src/validate.c
Log:
Out of time - hopefully a working refactoring of readers and callbacks.

Armour has not been tested.


Modified: openpgpsdk/trunk/examples/common.c
===================================================================
--- openpgpsdk/trunk/examples/common.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/examples/common.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -4,10 +4,10 @@
 #include <fcntl.h>
 #include <assert.h>
 
-static ops_parse_callback_return_t
-callback(const ops_parser_content_t *content,void *arg_)
+static ops_parse_cb_return_t
+callback(const ops_parser_content_t *content,ops_parse_cb_info_t *cbinfo)
     {
-    ops_secret_key_t **skey=arg_;
+    ops_secret_key_t **skey=ops_parse_cb_get_arg(cbinfo);
 
     if(content->tag == OPS_PTAG_CT_SECRET_KEY)
 	{
@@ -21,22 +21,20 @@
     
 ops_secret_key_t *get_secret_key(const char *keyfile)
     {
-    ops_reader_fd_arg_t arg;
-    ops_parse_info_t parse_info;
+    ops_parse_info_t *pinfo;
     ops_secret_key_t *skey;
+    int fd;
 
-    ops_parse_info_init(&parse_info);
-    parse_info.cb=callback;
+    pinfo=ops_parse_info_new();
 
-    arg.fd=open(keyfile,O_RDONLY);
-    assert(arg.fd >= 0);
-    parse_info.reader_arg=&arg;
-    parse_info.reader=ops_reader_fd;
-
     skey=NULL;
-    parse_info.cb_arg=&skey;
+    ops_parse_cb_set(pinfo,callback,&skey);
 
-    ops_parse(&parse_info);
+    fd=open(keyfile,O_RDONLY);
+    assert(fd >= 0);
+    ops_reader_set_fd(pinfo,fd);
 
+    ops_parse(pinfo);
+
     return skey;
     }

Modified: openpgpsdk/trunk/examples/packet-dump.c
===================================================================
--- openpgpsdk/trunk/examples/packet-dump.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/examples/packet-dump.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -312,14 +312,14 @@
 	}
     }
 
-static ops_parse_callback_return_t
-callback(const ops_parser_content_t *content_,void *arg_)
+static ops_parse_cb_return_t callback(const ops_parser_content_t *content_,
+				      ops_parse_cb_info_t *cbinfo)
     {
     const ops_parser_content_union_t *content=&content_->content;
     ops_text_t *text;
     char *str;
 
-    OPS_USED(arg_);
+    OPS_USED(cbinfo);
 
     switch(content_->tag)
 	{
@@ -848,8 +848,7 @@
 
 int main(int argc,char **argv)
     {
-    ops_parse_info_t parse_info;
-    ops_reader_fd_arg_t arg;
+    ops_parse_info_t *pinfo;
     ops_boolean_t armour=ops_false;
     int ret;
     int ch;
@@ -873,27 +872,22 @@
 	    }
 
 
-    ops_parse_info_init(&parse_info);
+    pinfo=ops_parse_info_new();
     //    ops_parse_packet_options(&opt,OPS_PTAG_SS_ALL,OPS_PARSE_RAW);
-    ops_parse_options(&parse_info,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED);
-    parse_info.cb=callback;
+    ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED);
 
-    arg.fd=0;
-    parse_info.reader_arg=&arg;
-    parse_info.reader=ops_reader_fd;
+    ops_parse_cb_set(pinfo,callback,NULL);
 
+    ops_reader_set_fd(pinfo,0);
+
     if(armour)
-	{
-	parse_info.armour_allow_no_gap=ops_true;
-	parse_info.armour_allow_headers_without_gap=ops_true;
-	ops_reader_push_dearmour(&parse_info);
-	}
+	ops_reader_push_dearmour(pinfo,ops_true,ops_true);
 
-    ret=ops_parse(&parse_info);
+    ret=ops_parse(pinfo);
     if (!ret)
-	{
-	print_errors(parse_info.errors);
-	}
+	ops_print_errors(ops_parse_info_get_errors(pinfo));
 
+    ops_parse_info_delete(pinfo);
+
     return 0;
     }

Modified: openpgpsdk/trunk/examples/verify.c
===================================================================
--- openpgpsdk/trunk/examples/verify.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/examples/verify.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -10,10 +10,10 @@
 
 int main(int argc,char **argv)
     {
-    ops_parse_info_t parse_info;
+    ops_parse_info_t *pinfo;
     ops_keyring_t keyring;
-    ops_reader_fd_arg_t arg;
     const char *target;
+    int fd;
 
     if(argc != 2)
 	{
@@ -26,17 +26,18 @@
     ops_init();
 
     memset(&keyring,'\0',sizeof keyring);
-    ops_parse_info_init(&parse_info);
-    arg.fd=open(target,O_RDONLY);
-    if(arg.fd < 0)
+
+    pinfo=ops_parse_info_new();
+
+    fd=open(target,O_RDONLY);
+    if(fd < 0)
 	{
 	perror(target);
 	exit(2);
 	}
-    parse_info.reader_arg=&arg;
-    parse_info.reader=ops_reader_fd;
+    ops_reader_set_fd(pinfo,fd);
 
-    ops_parse_and_accumulate(&keyring,&parse_info);
+    ops_parse_and_accumulate(&keyring,pinfo);
 
     ops_dump_keyring(&keyring);
 

Modified: openpgpsdk/trunk/examples/verify2.c
===================================================================
--- openpgpsdk/trunk/examples/verify2.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/examples/verify2.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -25,13 +25,13 @@
 static ops_hash_t *signed_hash;
 
 // FIXME: should this be a part of the library?
-static ops_parse_callback_return_t
-callback(const ops_parser_content_t *content_,void *arg_)
+static ops_parse_cb_return_t
+callback(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
     {
     const ops_parser_content_union_t *content=&content_->content;
     const ops_key_data_t *signer;
 
-    OPS_USED(arg_);
+    OPS_USED(cbinfo);
 
     switch(content_->tag)
 	{
@@ -121,8 +121,8 @@
 
 int main(int argc,char **argv)
     {
-    ops_parse_info_t parse_info;
-    ops_reader_fd_arg_t arg;
+    ops_parse_info_t *pinfo;
+    int fd;
     const char *keyfile;
     const char *verify;
     int ch;
@@ -152,46 +152,46 @@
     ops_init();
 
     memset(&keyring,'\0',sizeof keyring);
-    ops_parse_info_init(&parse_info);
 
-    arg.fd=open(keyfile,O_RDONLY);
-    if(arg.fd < 0)
+    pinfo=ops_parse_info_new();
+
+    fd=open(keyfile,O_RDONLY);
+    if(fd < 0)
 	{
 	perror(keyfile);
 	exit(1);
 	}
 
-    parse_info.reader_arg=&arg;
-    parse_info.reader=ops_reader_fd;
+    ops_reader_set_fd(pinfo,fd);
 
-    ops_parse_and_accumulate(&keyring,&parse_info);
+    ops_parse_and_accumulate(&keyring,pinfo);
 
-    close(arg.fd);
+    close(fd);
 
     if(verbose)
 	ops_dump_keyring(&keyring);
 
-    ops_parse_info_init(&parse_info);
+    ops_parse_info_delete(pinfo);
+    pinfo=ops_parse_info_new();
 
-    arg.fd=open(verify,O_RDONLY);
-    if(arg.fd < 0)
+    fd=open(verify,O_RDONLY);
+    if(fd < 0)
 	{
 	perror(verify);
 	exit(2);
 	}
 
-    parse_info.reader_arg=&arg;
-    parse_info.reader=ops_reader_fd;
+    ops_reader_set_fd(pinfo,fd);
 
-    parse_info.cb=callback;
+    ops_parse_cb_set(pinfo,callback,NULL);
 
     if(armour)
-	ops_reader_push_dearmour(&parse_info);
+	ops_reader_push_dearmour(pinfo,ops_false,ops_false);
 
-    ops_parse(&parse_info);
+    ops_parse(pinfo);
 
     if(armour)
-	ops_reader_pop_dearmour(&parse_info);
+	ops_reader_pop_dearmour(pinfo);
 
     if(signed_data)
 	free(signed_data);

Modified: openpgpsdk/trunk/include/openpgpsdk/armour.h
===================================================================
--- openpgpsdk/trunk/include/openpgpsdk/armour.h	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/include/openpgpsdk/armour.h	2005-12-07 09:39:44 UTC (rev 320)
@@ -1,7 +1,9 @@
 #include "packet-parse.h"
 #include "signature.h"
 
-void ops_reader_push_dearmour(ops_parse_info_t *parse_info);
+void ops_reader_push_dearmour(ops_parse_info_t *parse_info,
+			      ops_boolean_t without_gap,ops_boolean_t no_gap);
+
 void ops_reader_pop_dearmour(ops_parse_info_t *parse_info);
 void ops_writer_push_dash_escaped(ops_create_info_t *info,
 				  ops_create_signature_t *sig);

Modified: openpgpsdk/trunk/include/openpgpsdk/errors.h
===================================================================
--- openpgpsdk/trunk/include/openpgpsdk/errors.h	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/include/openpgpsdk/errors.h	2005-12-07 09:39:44 UTC (rev 320)
@@ -48,12 +48,12 @@
 
 char *ops_errcode(const ops_errcode_t errcode);
 
-void push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
+void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
 		const char *file,int line,const char *comment,...);
-void print_error(ops_error_t *err);
-void print_errors(ops_error_t *errstack);
+void ops_print_error(ops_error_t *err);
+void ops_print_errors(ops_error_t *errstack);
 
-#define ops_system_error_1(err,code,syscall,fmt,arg)	do { push_error(err,OPS_E_SYSTEM_ERROR,errno,__FILE__,__LINE__,syscall); push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
-#define ops_error_1(err,code,fmt,arg)	do { push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
+#define OPS_SYSTEM_ERROR_1(err,code,syscall,fmt,arg)	do { ops_push_error(err,OPS_E_SYSTEM_ERROR,errno,__FILE__,__LINE__,syscall); ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
+#define OPS_ERROR_1(err,code,fmt,arg)	do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
 
 #endif /* OPS_ERRORS */

Modified: openpgpsdk/trunk/include/openpgpsdk/packet-parse.h
===================================================================
--- openpgpsdk/trunk/include/openpgpsdk/packet-parse.h	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/include/openpgpsdk/packet-parse.h	2005-12-07 09:39:44 UTC (rev 320)
@@ -41,69 +41,42 @@
     {
     OPS_RELEASE_MEMORY,
     OPS_KEEP_MEMORY
-    } ops_parse_callback_return_t;
+    } ops_parse_cb_return_t;
 
-typedef ops_parse_callback_return_t
-ops_packet_parse_callback_t(const ops_parser_content_t *content,void *arg);
+typedef struct ops_parse_cb_info ops_parse_cb_info_t;
 
-struct ops_parse_info;
-typedef ops_reader_ret_t ops_packet_reader_t(unsigned char *dest,
-					     unsigned *plength,
-					     ops_reader_flags_t flags,
-					     struct ops_parse_info *parse_info);
+typedef ops_parse_cb_return_t
+ops_parse_cb_t(const ops_parser_content_t *content,
+	       ops_parse_cb_info_t *cbinfo);
 
-/** \brief Structure to hold information about a packet parse.
- *
- *  This information includes options about the parse:
- *  - whether the packet contents should be accumulated or not
- *  - whether signature subpackets should be parsed or left raw
- *
- *  It contains options specific to the parsing of armoured data:
- *  - whether headers are allowed in armoured data without a gap
- *  - whether a blank line is allowed at the start of the armoured data
- *  
- *  It also specifies :
- *  - the callback function to use and its arguments
- *  - the reader function to use and its arguments
- *
- *  It also contains information about the current state of the parse:
- *  - offset from the beginning
- *  - the accumulated data, if any
- *  - the size of the buffer, and how much has been used
- *
- *  It has a linked list of errors.
- */
+typedef struct ops_parse_info ops_parse_info_t;
+typedef struct ops_reader_info ops_reader_info_t;
 
-struct ops_parse_info
-    {
-    unsigned char ss_raw[256/8]; /*!< one bit per signature-subpacket type; 
-				    set to get raw data */
-    unsigned char ss_parsed[256/8]; /*!< one bit per signature-subpacket type;
-				       set to get parsed data */
+typedef ops_reader_ret_t ops_reader_t(unsigned char *dest,
+				      unsigned *plength,
+				      ops_reader_flags_t flags,
+				      ops_error_t **errors,
+				      ops_reader_info_t *rinfo,
+				      ops_parse_cb_info_t *cbinfo);
+typedef void ops_reader_destroyer_t(ops_reader_info_t *rinfo);
 
-    ops_packet_parse_callback_t *cb; /*!< the callback function to use when parsing */
-    void *cb_arg; /*!< the args to pass to the callback function */
+ops_parse_info_t *ops_parse_info_new(void);
+void ops_parse_info_delete(ops_parse_info_t *pinfo);
+ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo);
 
-    ops_packet_reader_t *reader; /*!< the reader function to use to get the data to be parsed */
-    void *reader_arg; /*!< the args to pass to the reader function */
-    /* XXX: what do we do about offsets into compressed packets? */
-    unsigned position; /*!< the offset from the beginning (with this reader) */
+void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg);
+void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg);
+void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,void *arg);
+void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,void *arg);
 
-    unsigned accumulate:1;	/*!< set to accumulate packet data */
-    unsigned char *accumulated;	/*!< the accumulated data */
-    unsigned asize;	/*!< size of the buffer */
-    unsigned alength;	/*!< used buffer */
-    unsigned armour_allow_headers_without_gap:1; /*!< allow headers in
-						  armoured data that
-						  are not separated
-						  from the data by a
-						  blank line */
-    unsigned armour_allow_no_gap:1; /*!< allow no blank line at the
-				       start of armoured data */
-    ops_error_t * errors;
-    };
+void *ops_reader_get_arg(ops_reader_info_t *rinfo);
+void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo);
 
-typedef struct ops_parse_info ops_parse_info_t;
+ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content,
+				   ops_parse_cb_info_t *cbinfo);
+ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content,
+					   ops_parse_cb_info_t *cbinfo);
+ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo);
 
 int ops_parse(ops_parse_info_t *parse_info);
 int ops_parse_and_save_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs);
@@ -120,15 +93,23 @@
     OPS_PARSE_IGNORE 	/*!< Ignore - Return Nothing*/
     };
 
-/** Initialise structure 
- */
-#define ops_parse_info_init(parse_info) memset(parse_info,'\0',sizeof *parse_info)
-
 void ops_parse_options(ops_parse_info_t *parse_info,ops_content_tag_t tag,
 		       ops_parse_type_t type);
 
-int ops_limited_read(unsigned char *dest,unsigned length,
-		     ops_region_t *region,ops_parse_info_t *parse_info);
+ops_boolean_t ops_limited_read(unsigned char *dest,unsigned length,
+			       ops_region_t *region,ops_error_t **errors,
+			       ops_reader_info_t *rinfo,
+			       ops_parse_cb_info_t *cbinfo);
+ops_boolean_t ops_stacked_limited_read(unsigned char *dest,unsigned length,
+				       ops_region_t *region,
+				       ops_error_t **errors,
+				       ops_reader_info_t *rinfo,
+				       ops_parse_cb_info_t *cbinfo);
+ops_reader_ret_t ops_stacked_read(unsigned char *dest,unsigned *length,
+			       ops_reader_flags_t flags,
+			       ops_error_t **errors,
+			       ops_reader_info_t *rinfo,
+			       ops_parse_cb_info_t *cbinfo);
 
 /* vim:set textwidth=120: */
 /* vim:set ts=8: */

Modified: openpgpsdk/trunk/include/openpgpsdk/util.h
===================================================================
--- openpgpsdk/trunk/include/openpgpsdk/util.h	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/include/openpgpsdk/util.h	2005-12-07 09:39:44 UTC (rev 320)
@@ -12,16 +12,8 @@
 #define ops_false	0
 #define ops_true	1
 
-/** Arguments for reader_fd
- */
-typedef struct
-    {
-    int fd; /*!< file descriptor */
-    } ops_reader_fd_arg_t;
-
 void hexdump(const unsigned char *src,size_t length);
-ops_reader_ret_t ops_reader_fd(unsigned char *dest,unsigned *plength,
-			       ops_reader_flags_t flags,ops_parse_info_t *parse_info);
+void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd);
 
 /* typesafe deconstification */
 static inline void *_deconst(const void *p)

Modified: openpgpsdk/trunk/src/accumulate.c
===================================================================
--- openpgpsdk/trunk/src/accumulate.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/accumulate.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -6,6 +6,7 @@
 #include <openpgpsdk/util.h>
 #include <openpgpsdk/accumulate.h>
 #include "keyring_local.h"
+#include "parse_local.h"
 #include <openpgpsdk/signature.h>
 #include <assert.h>
 #include <stdlib.h>
@@ -13,18 +14,16 @@
 
 typedef struct
     {
-    ops_packet_parse_callback_t *cb;
-    void *cb_arg;
     ops_keyring_t *keyring;
     } accumulate_arg_t;
 
 /**
  * \ingroup Callbacks
  */
-static ops_parse_callback_return_t
-accumulate_cb(const ops_parser_content_t *content_,void *arg_)
+static ops_parse_cb_return_t
+accumulate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
     {
-    accumulate_arg_t *arg=arg_;
+    accumulate_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
     const ops_parser_content_union_t *content=&content_->content;
     ops_keyring_t *keyring=arg->keyring;
     ops_key_data_t *cur=&keyring->keys[keyring->nkeys];
@@ -67,9 +66,7 @@
 
     // XXX: we now exclude so many things, we should either drop this or
     // do something to pass on copies of the stuff we keep
-    if(arg->cb)
-	return arg->cb(content_,arg->cb_arg);
-    return OPS_RELEASE_MEMORY;
+    return ops_parse_stacked_cb(content_,cbinfo);
     }
 
 /**
@@ -83,23 +80,23 @@
  * \param opt Options to use when parsing
 */
 
-void ops_parse_and_accumulate(ops_keyring_t *keyring,ops_parse_info_t *parse_info)
+void ops_parse_and_accumulate(ops_keyring_t *keyring,
+			      ops_parse_info_t *parse_info)
     {
     accumulate_arg_t arg;
 
-    assert(!parse_info->accumulate);
+    assert(!parse_info->rinfo.accumulate);
 
     memset(&arg,'\0',sizeof arg);
 
     arg.keyring=keyring;
     /* Kinda weird, but to do with counting, and we put it back after */
     --keyring->nkeys;
-    arg.cb=parse_info->cb;
-    arg.cb_arg=parse_info->cb_arg;
 
-    parse_info->cb=accumulate_cb;
-    parse_info->cb_arg=&arg;
-    parse_info->accumulate=1;
+    ops_parse_cb_push(parse_info,accumulate_cb,&arg);
+
+    parse_info->rinfo.accumulate=ops_true;
+
     ops_parse(parse_info);
     ++keyring->nkeys;
     }

Modified: openpgpsdk/trunk/src/armour.c
===================================================================
--- openpgpsdk/trunk/src/armour.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/armour.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -14,8 +14,6 @@
 
 typedef struct
     {
-    ops_packet_reader_t *reader;
-    void *reader_arg;
     enum
 	{
 	OUTSIDE_BLOCK=0,
@@ -23,8 +21,16 @@
 	AT_TRAILER_NAME,
 	} state;
     ops_parse_info_t *parse_info;
-    ops_boolean_t seen_nl;
-    ops_boolean_t prev_nl;
+    ops_boolean_t seen_nl:1;
+    ops_boolean_t prev_nl:1;
+    ops_boolean_t allow_headers_without_gap:1; /*!< allow headers in
+						  armoured data that
+						  are not separated
+						  from the data by a
+						  blank line */
+    ops_boolean_t allow_no_gap:1; /*!< allow no blank line at the
+				       start of armoured data */
+
     // base64 stuff
     unsigned buffered;
     unsigned char buffer[3];
@@ -42,8 +48,8 @@
     } dearmour_arg_t;
 
 // FIXME: move these to a common header
-#define CB(t,pc)	do { (pc)->tag=(t); if(arg->parse_info->cb(pc,arg->parse_info->cb_arg) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
-#define ERR(err)	do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; arg->parse_info->cb(&content,arg->parse_info->cb_arg); return OPS_R_EARLY_EOF; } while(0)
+#define CB(cbinfo,t,pc)	do { (pc)->tag=(t); if(ops_parse_cb((pc),(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
+#define ERR(cbinfo,err)	do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,(cbinfo)); return OPS_R_EARLY_EOF; } while(0)
 
 static void push_back(dearmour_arg_t *arg,const unsigned char *buf,
 		      unsigned length)
@@ -57,17 +63,13 @@
     arg->npushed_back=length;
     }
     
-static int read_char(dearmour_arg_t *arg,ops_boolean_t skip)
+static int read_char(dearmour_arg_t *arg,ops_error_t **errors,
+		     ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo,
+		     ops_boolean_t skip)
     {
     unsigned char c[1];
-    ops_packet_reader_t *reader;
-    ops_reader_ret_t ret;
     unsigned length=1;
 
-    reader=arg->parse_info->reader;
-    arg->parse_info->reader=arg->reader;
-    arg->parse_info->reader_arg=arg->reader_arg;
-
     do
 	{
 	if(arg->npushed_back)
@@ -79,26 +81,19 @@
 		arg->pushed_back=NULL;
 		}
 	    }
-	else if((ret=arg->reader(c,&length,0,arg->reader_arg)) != OPS_R_OK)
-	    {
-	    arg->parse_info->reader=reader;
-	    arg->parse_info->reader_arg=arg;
-
+	/* XXX: should ops_stacked_read exist? Shouldn't this be a limited_read? */
+	else if(ops_stacked_read(c,&length,0,errors,rinfo,cbinfo) != OPS_R_OK)
 	    return -1;
-	    }
 	}
     while(skip && c[0] == '\r');
 
-    arg->parse_info->reader=reader;
-    arg->parse_info->reader_arg=arg;
-
     arg->prev_nl=arg->seen_nl;
     arg->seen_nl=c[0] == '\n';
 
     return c[0];
     }
 
-static void flush(dearmour_arg_t *arg)
+static void flush(dearmour_arg_t *arg,ops_parse_cb_info_t *cbinfo)
     {
     ops_parser_content_t content;
 
@@ -107,22 +102,25 @@
 
     content.content.unarmoured_text.data=arg->unarmoured;
     content.content.unarmoured_text.length=arg->num_unarmoured;
-    CB(OPS_PTAG_CT_UNARMOURED_TEXT,&content);
+    CB(cbinfo,OPS_PTAG_CT_UNARMOURED_TEXT,&content);
     arg->num_unarmoured=0;
     }
 
-static int unarmoured_read_char(dearmour_arg_t *arg,ops_boolean_t skip)
+static int unarmoured_read_char(dearmour_arg_t *arg,ops_error_t **errors,
+				ops_reader_info_t *rinfo,
+				ops_parse_cb_info_t *cbinfo,
+				ops_boolean_t skip)
     {
     int c;
 
     do
 	{
-	c=read_char(arg,ops_false);
+	c=read_char(arg,errors,rinfo,cbinfo,ops_false);
 	if(c < 0)
 	    return c;
 	arg->unarmoured[arg->num_unarmoured++]=c;
 	if(arg->num_unarmoured == sizeof arg->unarmoured)
-	    flush(arg);
+	    flush(arg,cbinfo);
 	}
     while(skip && c == '\r');
 
@@ -155,7 +153,10 @@
 
 /* Note that this skips CRs so implementations always see just
    straight LFs as line terminators */
-static ops_reader_ret_t process_dash_escaped(dearmour_arg_t *arg)
+static ops_reader_ret_t process_dash_escaped(dearmour_arg_t *arg,
+					     ops_error_t **errors,
+					     ops_reader_info_t *rinfo,
+					     ops_parse_cb_info_t *cbinfo)
     {
     ops_parser_content_t content;
     ops_parser_content_t content2;
@@ -175,7 +176,7 @@
 	if(alg == OPS_HASH_UNKNOWN)
 	    {
 	    free(hash);
-	    ERR("Unknown hash algorithm");
+	    ERR(cbinfo,"Unknown hash algorithm");
 	    }
 	ops_hash_any(hash,alg);
 	}
@@ -190,29 +191,29 @@
 	int c;
 	unsigned count;
 
-	if((c=read_char(arg,ops_true)) < 0)
+	if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0)
 	    return OPS_R_EARLY_EOF;
 	if(arg->prev_nl && c == '-')
 	    {
-	    if((c=read_char(arg,ops_false)) < 0)
+	    if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
 		return OPS_R_EARLY_EOF;
 	    if(c != ' ')
 		{
 		/* then this had better be a trailer! */
 		if(c != '-')
-		    ERR("Bad dash-escaping");
+		    ERR(cbinfo,"Bad dash-escaping");
 		for(count=2 ; count < 5 ; ++count)
 		    {
-		    if((c=read_char(arg,ops_false)) < 0)
+		    if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
 			return OPS_R_EARLY_EOF;
 		    if(c != '-')
-			ERR("Bad dash-escaping (2)");
+			ERR(cbinfo,"Bad dash-escaping (2)");
 		    }
 		arg->state=AT_TRAILER_NAME;
 		break;
 		}
 	    /* otherwise we read the next character */
-	    if((c=read_char(arg,ops_false)) < 0)
+	    if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
 		return OPS_R_EARLY_EOF;
 	    }
 	if(c == '\n' && body->length)
@@ -221,14 +222,14 @@
 	    if(body->data[0] == '\n')
 		hash->add(hash,(unsigned char *)"\r",1);
 	    hash->add(hash,body->data,body->length);
-	    CB(OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content);
+	    CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content);
 	    body->length=0;
 	    }
 		
 	body->data[body->length++]=c;
 	if(body->length == sizeof body->data)
 	    {
-	    CB(OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content);
+	    CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content);
 	    body->length=0;
 	    }
 	}
@@ -238,7 +239,7 @@
     /* don't send that one character, because its part of the trailer. */
 
     trailer->hash=hash;
-    CB(OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER,&content2);
+    CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER,&content2);
 
     return OPS_R_OK;
     }
@@ -254,7 +255,9 @@
     ++arg->headers.nheaders;
     }
 
-static ops_reader_ret_t parse_headers(dearmour_arg_t *arg)
+static ops_reader_ret_t parse_headers(dearmour_arg_t *arg,ops_error_t **errors,
+				      ops_reader_info_t *rinfo,
+				      ops_parse_cb_info_t *cbinfo)
     {
     char *buf;
     unsigned nbuf;
@@ -269,7 +272,7 @@
 	{
 	int c;
 
-	if((c=read_char(arg,ops_true)) < 0)
+	if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0)
 	    return OPS_R_EARLY_EOF;
 
 	if(c == '\n')
@@ -284,15 +287,14 @@
 
 	    s=strchr(buf,':');
 	    if(!s)
-		if(!first && !arg->parse_info->armour_allow_headers_without_gap)
+		if(!first && !arg->allow_headers_without_gap)
 		    // then we have seriously malformed armour
-		    ERR("No colon in armour header");
+		    ERR(cbinfo,"No colon in armour header");
 		else
 		    {
 		    if(first &&
-		       !(arg->parse_info->armour_allow_headers_without_gap
-			 || arg->parse_info->armour_allow_no_gap))
-			ERR("No colon in armour header (2)");
+		       !(arg->allow_headers_without_gap || arg->allow_no_gap))
+			ERR(cbinfo,"No colon in armour header (2)");
 		    // then we have a nasty armoured block with no
 		    // headers, not even a blank line.
 		    buf[nbuf]='\n';
@@ -303,7 +305,7 @@
 		{
 		*s='\0';
 		if(s[1] != ' ')
-		    ERR("No space in armour header");
+		    ERR(cbinfo,"No space in armour header");
 		add_header(arg,buf,s+2);
 		nbuf=0;
 		}
@@ -325,7 +327,9 @@
     return OPS_R_OK;
     }
 
-static ops_reader_ret_t read4(dearmour_arg_t *arg,int *pc,unsigned *pn,
+static ops_reader_ret_t read4(dearmour_arg_t *arg,ops_error_t **errors,
+			      ops_reader_info_t *rinfo,
+			      ops_parse_cb_info_t *cbinfo,int *pc,unsigned *pn,
 			      unsigned long *pl)
     {
     int n,c;
@@ -333,7 +337,7 @@
 
     for(n=0 ; n < 4 ; ++n)
 	{
-	c=read_char(arg,ops_true);
+	c=read_char(arg,errors,rinfo,cbinfo,ops_true);
 	if(c < 0)
 	    {
 	    arg->eof64=ops_true;
@@ -382,7 +386,9 @@
     return checksum&0xffffffL;
     }
 
-static ops_reader_ret_t decode64(dearmour_arg_t *arg)
+static ops_reader_ret_t decode64(dearmour_arg_t *arg,ops_error_t **errors,
+				 ops_reader_info_t *rinfo,
+				 ops_parse_cb_info_t *cbinfo)
     {
     unsigned n;
     int n2;
@@ -393,9 +399,9 @@
 
     assert(arg->buffered == 0);
 
-    ret=read4(arg,&c,&n,&l);
+    ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&l);
     if(ret != OPS_R_OK)
-	ERR("Badly formed base64");
+	ERR(cbinfo,"Badly formed base64");
 
     if(n == 3)
 	{
@@ -410,9 +416,9 @@
 	arg->buffered=1;
 	arg->eof64=ops_true;
 	l >>= 4;
-	c=read_char(arg,ops_false);
+	c=read_char(arg,errors,rinfo,cbinfo,ops_false);
 	if(c != '=')
-	    ERR("Badly terminated base64");
+	    ERR(cbinfo,"Badly terminated base64");
 	}
     else if(n == 0)
 	{
@@ -430,33 +436,33 @@
 	{
 	// then we saw padding
 	assert(c == '=');
-	c=read_char(arg,ops_true);
+	c=read_char(arg,errors,rinfo,cbinfo,ops_true);
 	if(c != '\n')
-	    ERR("No newline at base64 end");
-	c=read_char(arg,ops_false);
+	    ERR(cbinfo,"No newline at base64 end");
+	c=read_char(arg,errors,rinfo,cbinfo,ops_false);
 	if(c != '=')
-	    ERR("No checksum at base64 end");
+	    ERR(cbinfo,"No checksum at base64 end");
 	}
 
     if(c == '=')
 	{
 	// now we are at the checksum
-	ret=read4(arg,&c,&n,&arg->read_checksum);
+	ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&arg->read_checksum);
 	if(ret != OPS_R_OK || n != 4)
-	    ERR("Error in checksum");
-	c=read_char(arg,ops_true);
+	    ERR(cbinfo,"Error in checksum");
+	c=read_char(arg,errors,rinfo,cbinfo,ops_true);
 	if(c != '\n')
-	    ERR("Badly terminated checksum");
-	c=read_char(arg,ops_false);
+	    ERR(cbinfo,"Badly terminated checksum");
+	c=read_char(arg,errors,rinfo,cbinfo,ops_false);
 	if(c != '-')
-	    ERR("Bad base64 trailer (2)");
+	    ERR(cbinfo,"Bad base64 trailer (2)");
 	}
 
     if(c == '-')
 	{
 	for(n=0 ; n < 4 ; ++n)
-	    if(read_char(arg,ops_false) != '-')
-		ERR("Bad base64 trailer");
+	    if(read_char(arg,errors,rinfo,cbinfo,ops_false) != '-')
+		ERR(cbinfo,"Bad base64 trailer");
 	arg->eof64=ops_true;
 	}
     else
@@ -472,7 +478,7 @@
 	arg->checksum=crc24(arg->checksum,arg->buffer[n2]);
 
     if(arg->eof64 && arg->read_checksum != arg->checksum)
-	ERR("Checksum mismatch");
+	ERR(cbinfo,"Checksum mismatch");
 
     return OPS_R_OK;
     }
@@ -492,191 +498,193 @@
 static ops_reader_ret_t armoured_data_reader(unsigned char *dest,
 					     unsigned *plength,
 					     ops_reader_flags_t flags,
-					     ops_parse_info_t *parse_info)
-    {
-    dearmour_arg_t *arg=parse_info->reader_arg;
-    unsigned length=*plength;
-    ops_parser_content_t content;
-    ops_reader_ret_t ret;
-    ops_boolean_t first;
+					     ops_error_t **errors,
+					     ops_reader_info_t *rinfo,
+					     ops_parse_cb_info_t *cbinfo)
+     {
+     dearmour_arg_t *arg=ops_reader_get_arg(rinfo);
+     unsigned length=*plength;
+     ops_parser_content_t content;
+     ops_reader_ret_t ret;
+     ops_boolean_t first;
 
-    OPS_USED(flags);
+     OPS_USED(flags);
 
-    if(arg->eof64 && !arg->buffered)
-	assert(arg->state == OUTSIDE_BLOCK || arg->state == AT_TRAILER_NAME);
+     if(arg->eof64 && !arg->buffered)
+	 assert(arg->state == OUTSIDE_BLOCK || arg->state == AT_TRAILER_NAME);
 
-    while(length > 0)
-	{
-	unsigned count;
-	unsigned n;
-	char buf[1024];
-	int c;
+     while(length > 0)
+	 {
+	 unsigned count;
+	 unsigned n;
+	 char buf[1024];
+	 int c;
 
-	flush(arg);
-	switch(arg->state)
-	    {
-	case OUTSIDE_BLOCK:
-	    /* This code returns EOF rather than EARLY_EOF because if
-	       we don't see a header line at all, then it is just an
-	       EOF (and not a BLOCK_END) */
-	    while(!arg->seen_nl)
-		if((c=unarmoured_read_char(arg,ops_true)) < 0)
-		    return OPS_R_EOF;
+	 flush(arg,cbinfo);
+	 switch(arg->state)
+	     {
+	 case OUTSIDE_BLOCK:
+	     /* This code returns EOF rather than EARLY_EOF because if
+		we don't see a header line at all, then it is just an
+		EOF (and not a BLOCK_END) */
+	     while(!arg->seen_nl)
+		 if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0)
+		     return OPS_R_EOF;
 
-	    /* flush at this point so we definitely have room for the
-	       header, and so we can easily erase it from the buffer */
-	    flush(arg);
-	    /* Find and consume the 5 leading '-' */
-	    for(count=0 ; count < 5 ; ++count)
-		{
-		if((c=unarmoured_read_char(arg,ops_false)) < 0)
-		    return OPS_R_EOF;
-		if(c != '-')
-		    goto reloop;
-		}
+	     /* flush at this point so we definitely have room for the
+		header, and so we can easily erase it from the buffer */
+	     flush(arg,cbinfo);
+	     /* Find and consume the 5 leading '-' */
+	     for(count=0 ; count < 5 ; ++count)
+		 {
+		 if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
+		     return OPS_R_EOF;
+		 if(c != '-')
+		     goto reloop;
+		 }
 
-	    /* Now find the block type */
-	    for(n=0 ; n < sizeof buf-1 ; )
-		{
-		if((c=unarmoured_read_char(arg,ops_false)) < 0)
-		    return OPS_R_EOF;
-		if(c == '-')
-		    goto got_minus;
-		buf[n++]=c;
-		}
-	    /* then I guess this wasn't a proper header */
-	    break;
+	     /* Now find the block type */
+	     for(n=0 ; n < sizeof buf-1 ; )
+		 {
+		 if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
+		     return OPS_R_EOF;
+		 if(c == '-')
+		     goto got_minus;
+		 buf[n++]=c;
+		 }
+	     /* then I guess this wasn't a proper header */
+	     break;
 
-	got_minus:
-	    buf[n]='\0';
+	 got_minus:
+	     buf[n]='\0';
 
-	    /* Consume trailing '-' */
-	    for(count=1 ; count < 5 ; ++count)
-		{
-		if((c=unarmoured_read_char(arg,ops_false)) < 0)
-		    return OPS_R_EOF;
-		if(c != '-')
-		    /* wasn't a header after all */
-		    goto reloop;
-		}
+	     /* Consume trailing '-' */
+	     for(count=1 ; count < 5 ; ++count)
+		 {
+		 if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
+		     return OPS_R_EOF;
+		 if(c != '-')
+		     /* wasn't a header after all */
+		     goto reloop;
+		 }
 
-	    /* Consume final NL */
-	    if((c=unarmoured_read_char(arg,ops_true)) < 0)
-		return OPS_R_EOF;
-	    if(c != '\n')
-		/* wasn't a header line after all */
-		break;
+	     /* Consume final NL */
+	     if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0)
+		 return OPS_R_EOF;
+	     if(c != '\n')
+		 /* wasn't a header line after all */
+		 break;
 
-	    /* Now we've seen the header, scrub it from the buffer */
-	    arg->num_unarmoured=0;
+	     /* Now we've seen the header, scrub it from the buffer */
+	     arg->num_unarmoured=0;
 
-	    /* But now we've seen a header line, then errors are
-	       EARLY_EOF */
-	    if((ret=parse_headers(arg)) != OPS_R_OK)
-		return OPS_R_EARLY_EOF;
+	     /* But now we've seen a header line, then errors are
+		EARLY_EOF */
+	     if((ret=parse_headers(arg,errors,rinfo,cbinfo)) != OPS_R_OK)
+		 return OPS_R_EARLY_EOF;
 
-	    if(!strcmp(buf,"BEGIN PGP SIGNED MESSAGE"))
-		{
-		ops_reader_ret_t ret;
+	     if(!strcmp(buf,"BEGIN PGP SIGNED MESSAGE"))
+		 {
+		 ops_reader_ret_t ret;
 
-		ops_dup_headers(&content.content.signed_cleartext_header.headers,&arg->headers);
-		CB(OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER,&content);
+		 ops_dup_headers(&content.content.signed_cleartext_header.headers,&arg->headers);
+		 CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER,&content);
 
-		ret=process_dash_escaped(arg);
-		if(ret != OPS_R_OK)
-		    return ret;
-		}
-	    else
-		{
-		content.content.armour_header.type=buf;
-		content.content.armour_header.headers=arg->headers;
-		memset(&arg->headers,'\0',sizeof arg->headers);
-		CB(OPS_PTAG_CT_ARMOUR_HEADER,&content);
-		base64(arg);
-		}
-	    break;
+		 ret=process_dash_escaped(arg,errors,rinfo,cbinfo);
+		 if(ret != OPS_R_OK)
+		     return ret;
+		 }
+	     else
+		 {
+		 content.content.armour_header.type=buf;
+		 content.content.armour_header.headers=arg->headers;
+		 memset(&arg->headers,'\0',sizeof arg->headers);
+		 CB(cbinfo,OPS_PTAG_CT_ARMOUR_HEADER,&content);
+		 base64(arg);
+		 }
+	     break;
 
-	case BASE64:
-	    first=ops_true;
-	    while(length > 0)
-		{
-		if(!arg->buffered)
-		    {
-		    if(!arg->eof64)
-			{
-			ret=decode64(arg);
-			if(ret != OPS_R_OK)
-			    return ret;
-			}
-		    if(!arg->buffered)
-			{
-			assert(arg->eof64);
-			if(first)
-			    {
-			    arg->state=AT_TRAILER_NAME;
-			    goto reloop;
-			    }
-			return OPS_R_EARLY_EOF;
-			}
-		    }
-		
-		assert(arg->buffered);
-		*dest=arg->buffer[--arg->buffered];
-		++dest;
-		--length;
-		first=ops_false;
-		}
-	    if(arg->eof64 && !arg->buffered)
-		arg->state=AT_TRAILER_NAME;
-	    break;
+	 case BASE64:
+	     first=ops_true;
+	     while(length > 0)
+		 {
+		 if(!arg->buffered)
+		     {
+		     if(!arg->eof64)
+			 {
+			 ret=decode64(arg,errors,rinfo,cbinfo);
+			 if(ret != OPS_R_OK)
+			     return ret;
+			 }
+		     if(!arg->buffered)
+			 {
+			 assert(arg->eof64);
+			 if(first)
+			     {
+			     arg->state=AT_TRAILER_NAME;
+			     goto reloop;
+			     }
+			 return OPS_R_EARLY_EOF;
+			 }
+		     }
 
-	case AT_TRAILER_NAME:
-	    for(n=0 ; n < sizeof buf-1 ; )
-		{
-		if((c=read_char(arg,ops_false)) < 0)
-		    return OPS_R_EARLY_EOF;
-		if(c == '-')
-		    goto got_minus2;
-		buf[n++]=c;
-		}
-	    /* then I guess this wasn't a proper trailer */
-	    ERR("Bad ASCII armour trailer");
-	    break;
+		 assert(arg->buffered);
+		 *dest=arg->buffer[--arg->buffered];
+		 ++dest;
+		 --length;
+		 first=ops_false;
+		 }
+	     if(arg->eof64 && !arg->buffered)
+		 arg->state=AT_TRAILER_NAME;
+	     break;
 
-	got_minus2:
-	    buf[n]='\0';
+	 case AT_TRAILER_NAME:
+	     for(n=0 ; n < sizeof buf-1 ; )
+		 {
+		 if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
+		     return OPS_R_EARLY_EOF;
+		 if(c == '-')
+		     goto got_minus2;
+		 buf[n++]=c;
+		 }
+	     /* then I guess this wasn't a proper trailer */
+	     ERR(cbinfo,"Bad ASCII armour trailer");
+	     break;
 
-	    /* Consume trailing '-' */
-	    for(count=1 ; count < 5 ; ++count)
-		{
-		if((c=read_char(arg,ops_false)) < 0)
-		    return OPS_R_EARLY_EOF;
-		if(c != '-')
-		    /* wasn't a trailer after all */
-		    ERR("Bad ASCII armour trailer (2)");
-		}
+	 got_minus2:
+	     buf[n]='\0';
 
-	    /* Consume final NL */
-	    if((c=read_char(arg,ops_true)) < 0)
-		return OPS_R_EARLY_EOF;
-	    if(c != '\n')
-		/* wasn't a trailer line after all */
-		ERR("Bad ASCII armour trailer (3)");
+	     /* Consume trailing '-' */
+	     for(count=1 ; count < 5 ; ++count)
+		 {
+		 if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0)
+		     return OPS_R_EARLY_EOF;
+		 if(c != '-')
+		     /* wasn't a trailer after all */
+		     ERR(cbinfo,"Bad ASCII armour trailer (2)");
+		 }
 
-	    if(!strncmp(buf,"BEGIN ",6))
-		{
-		if((ret=parse_headers(arg)) != OPS_R_OK)
-		    return ret;
-		content.content.armour_header.type=buf;
-		content.content.armour_header.headers=arg->headers;
-		memset(&arg->headers,'\0',sizeof arg->headers);
-		CB(OPS_PTAG_CT_ARMOUR_HEADER,&content);
-		base64(arg);
-		}
-	    else
-		{
-		content.content.armour_trailer.type=buf;
-		CB(OPS_PTAG_CT_ARMOUR_TRAILER,&content);
+	     /* Consume final NL */
+	     if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0)
+		 return OPS_R_EARLY_EOF;
+	     if(c != '\n')
+		 /* wasn't a trailer line after all */
+		 ERR(cbinfo,"Bad ASCII armour trailer (3)");
+
+	     if(!strncmp(buf,"BEGIN ",6))
+		 {
+		 if((ret=parse_headers(arg,errors,rinfo,cbinfo)) != OPS_R_OK)
+		     return ret;
+		 content.content.armour_header.type=buf;
+		 content.content.armour_header.headers=arg->headers;
+		 memset(&arg->headers,'\0',sizeof arg->headers);
+		 CB(cbinfo,OPS_PTAG_CT_ARMOUR_HEADER,&content);
+		 base64(arg);
+		 }
+	     else
+		 {
+		 content.content.armour_trailer.type=buf;
+		 CB(cbinfo,OPS_PTAG_CT_ARMOUR_TRAILER,&content);
 		arg->state=OUTSIDE_BLOCK;
 		}
 	    break;
@@ -688,28 +696,23 @@
     return OPS_R_OK;
     }
 
-void ops_reader_push_dearmour(ops_parse_info_t *parse_info)
+void ops_reader_push_dearmour(ops_parse_info_t *parse_info,
+			      ops_boolean_t without_gap,ops_boolean_t no_gap)
     {
     dearmour_arg_t *arg;
 
     arg=ops_mallocz(sizeof *arg);
-
-    arg->reader_arg=parse_info->reader_arg;
-    arg->reader=parse_info->reader;
-    arg->parse_info=parse_info;
     arg->seen_nl=ops_true;
+    arg->allow_headers_without_gap=without_gap;
+    arg->allow_no_gap=no_gap;
 
-    parse_info->reader=armoured_data_reader;
-    parse_info->reader_arg=arg;
+    ops_reader_push(parse_info,armoured_data_reader,arg);
     }
 
 void ops_reader_pop_dearmour(ops_parse_info_t *parse_info)
     {
-    dearmour_arg_t *arg=parse_info->reader_arg;
+    dearmour_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(parse_info));
 
-    parse_info->reader_arg=arg->reader_arg;
-    parse_info->reader=arg->reader;
-
     free(arg);
     }
 

Modified: openpgpsdk/trunk/src/compress.c
===================================================================
--- openpgpsdk/trunk/src/compress.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/compress.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -10,9 +10,6 @@
 
 typedef struct
     {
-    ops_packet_reader_t *reader;
-    void *reader_arg;
-    ops_parse_info_t *parse_info;
     ops_region_t *region;
     unsigned char in[DECOMPRESS_BUFFER];
     unsigned char out[DECOMPRESS_BUFFER];
@@ -21,14 +18,16 @@
     int inflate_ret;
     } decompress_arg_t;
 
-#define ERR(err)	do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; arg->parse_info->cb(&content,arg->parse_info->cb_arg); return OPS_R_EARLY_EOF; } while(0)
+#define ERR(err)	do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,cbinfo); return OPS_R_EARLY_EOF; } while(0)
 
 static ops_reader_ret_t compressed_data_reader(unsigned char *dest,
 					       unsigned *plength,
 					       ops_reader_flags_t flags,
-					       ops_parse_info_t *parse_info)
+					       ops_error_t **errors,
+					       ops_reader_info_t *rinfo,
+					       ops_parse_cb_info_t *cbinfo)
     {
-    decompress_arg_t *arg=parse_info->reader_arg;
+    decompress_arg_t *arg=ops_reader_get_arg(rinfo);
     ops_parser_content_t content;
     unsigned length=*plength;
 
@@ -70,15 +69,10 @@
 		else
 		    n=sizeof arg->in;
 
-		arg->parse_info->reader=arg->reader;
-		arg->parse_info->reader_arg=arg->reader_arg;
-
-		if(!ops_limited_read(arg->in,n,arg->region,arg->parse_info))
+		if(!ops_stacked_limited_read(arg->in,n,arg->region,
+					     errors,rinfo,cbinfo))
 		    return OPS_R_EARLY_EOF;
 
-		arg->parse_info->reader=compressed_data_reader;
-		arg->parse_info->reader_arg=arg;
-
 		arg->stream.next_in=arg->in;
 		arg->stream.avail_in=arg->region->indeterminate
 		    ? arg->region->last_read : n;
@@ -124,10 +118,8 @@
 
     memset(&arg,'\0',sizeof arg);
 
-    arg.reader_arg=parse_info->reader_arg;
-    arg.reader=parse_info->reader;
+
     arg.region=region;
-    arg.parse_info=parse_info;
 
     arg.stream.next_in=Z_NULL;
     arg.stream.avail_in=0;
@@ -143,8 +135,7 @@
 	return 0;
 	}
 
-    parse_info->reader=compressed_data_reader;
-    parse_info->reader_arg=&arg;
+    ops_reader_push(parse_info,compressed_data_reader,&arg);
 
     return ops_parse(parse_info);
     }

Modified: openpgpsdk/trunk/src/create.c
===================================================================
--- openpgpsdk/trunk/src/create.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/create.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -566,14 +566,14 @@
 
     if(n == -1)
 	{
-	ops_system_error_1(errors,OPS_E_W_WRITE_FAILED,"write",
+	OPS_SYSTEM_ERROR_1(errors,OPS_E_W_WRITE_FAILED,"write",
 			   "file descriptor %d",arg->fd);
 	return ops_false;
 	}
 
     if((unsigned)n != length)
 	{
-	ops_error_1(errors,OPS_E_W_WRITE_TOO_SHORT,
+	OPS_ERROR_1(errors,OPS_E_W_WRITE_TOO_SHORT,
 		    "file descriptor %d",arg->fd);
 	return ops_false;
 	}

Modified: openpgpsdk/trunk/src/errors.c
===================================================================
--- openpgpsdk/trunk/src/errors.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/errors.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -57,7 +57,7 @@
  *
  */
 
-void push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
+void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
 		const char *file,int line,const char *fmt,...)
     {
     // first get the varargs and generate the comment
@@ -90,19 +90,20 @@
     err->comment=comment;
     }
 
-void print_error(ops_error_t *err)
+void ops_print_error(ops_error_t *err)
     {
     printf("%s:%d: ",err->file,err->line);
-    if (err->errcode==OPS_E_SYSTEM_ERROR)
+    if(err->errcode==OPS_E_SYSTEM_ERROR)
 	printf("system error %d returned from %s()\n",err->sys_errno,
 	       err->comment);
     else
 	printf("%s, %s\n",ops_errcode(err->errcode),err->comment);
     }
 
-void print_errors(ops_error_t *errstack)
+void ops_print_errors(ops_error_t *errstack)
     {
     ops_error_t *err;
-    for (err=errstack; err!=NULL; err=err->next)
-	print_error(err);
+
+    for(err=errstack ; err!=NULL ; err=err->next)
+	ops_print_error(err);
     }

Modified: openpgpsdk/trunk/src/packet-parse.c
===================================================================
--- openpgpsdk/trunk/src/packet-parse.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/packet-parse.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -2,12 +2,12 @@
  * \brief Parser for OpenPGP packets
  */
 
-
 #include <openpgpsdk/packet.h>
 #include <openpgpsdk/packet-parse.h>
 #include <openpgpsdk/util.h>
 #include <openpgpsdk/compress.h>
 #include <openpgpsdk/errors.h>
+#include "parse_local.h"
 
 #include <assert.h>
 #include <stdarg.h>
@@ -38,7 +38,9 @@
     if (!data->contents)
 	return 0;
 
-    if (!ops_limited_read(data->contents, data->len,subregion,parse_info))
+    if (!ops_limited_read(data->contents, data->len,subregion,
+			  &parse_info->errors,&parse_info->rinfo,
+			  &parse_info->cbinfo))
 	return 0;
     
     return 1;
@@ -69,7 +71,8 @@
  * It is the user's responsibility to free the memory allocated here.
  */
 
-static int read_unsigned_string(unsigned char **str, ops_region_t *subregion, ops_parse_info_t *parse_info)
+static int read_unsigned_string(unsigned char **str,ops_region_t *subregion,
+				ops_parse_info_t *pinfo)
     {
     int len=0;
 
@@ -79,7 +82,8 @@
     if(!(*str))
 	return 0;
 
-    if(len && !ops_limited_read(*str,len,subregion,parse_info))
+    if(len && !ops_limited_read(*str,len,subregion,&pinfo->errors,
+				&pinfo->rinfo,&pinfo->cbinfo))
 	return 0;
 
     /*! ensure the string is NULL-terminated */
@@ -101,19 +105,20 @@
     }
 
 /*! \todo descr for CB macro */
-#define CB(t,pc)	do { (pc)->tag=(t); if(parse_info->cb(pc,parse_info->cb_arg) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
+#define CB(cbinfo,t,pc)	do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)->arg) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
+#define CBP(info,t,pc) CB(&(info)->cbinfo,t,pc)
 /*! macro to save typing */
 #define C		content.content
-/*! macro to run CallBack function specifying a parser error has occurred */
-#define E		CB(OPS_PARSER_ERROR,&content); return 0
 /*! set error code in content and run CallBack to handle error */
-#define ERRCODE(err)	do { C.errcode.errcode=err; CB(OPS_PARSER_ERRCODE,&content); } while(0)
+#define ERRCODE(cbinfo,err)	do { C.errcode.errcode=err; CB(cbinfo,OPS_PARSER_ERRCODE,&content); } while(0)
 /*! set error text in content and run CallBack to handle error, then return */
-#define ERR(err)	do { C.error.error=err; E; } while(0)
+#define ERR(cbinfo,err)	do { C.error.error=err; CB(cbinfo,OPS_PARSER_ERROR,&content); return ops_false; } while(0)
+#define ERRP(info,err)	do { C.error.error=err; CBP(info,OPS_PARSER_ERROR,&content); return ops_false; } while(0)
 /*! set error text in content and run CallBack to handle warning, do not return */
 #define WARN(warn)	do { C.error.error=warn; CB(OPS_PARSER_ERROR,&content);; } while(0)
+#define WARNP(info,warn)	do { C.error.error=warn; CBP(info,OPS_PARSER_ERROR,&content); } while(0)
 /*! \todo descr ERR1 macro */
-#define ERR1(fmt,x)	do { format_error(&content,(fmt),(x)); E; } while(0)
+#define ERR1P(info,fmt,x)	do { format_error(&content,(fmt),(x)); CBP(info,OPS_PARSER_ERROR,&content); return ops_false; } while(0)
 
 /* XXX: replace ops_ptag_t with something more appropriate for limiting
    reads */
@@ -156,33 +161,51 @@
  * \sa #ops_reader_ret_t, ops_reader_fd() for details of return codes
  */
 
-static ops_reader_ret_t base_read(unsigned char *dest,unsigned *plength,
-				  ops_reader_flags_t flags,
-				  ops_parse_info_t *parse_info)
+static ops_reader_ret_t sub_base_read(unsigned char *dest,unsigned *plength,
+				      ops_reader_flags_t flags,
+				      ops_error_t **errors,
+				      ops_reader_info_t *rinfo,
+				      ops_parse_cb_info_t *cbinfo)
     {
-    ops_reader_ret_t ret=parse_info->reader(dest,plength,flags,parse_info); 
+    ops_reader_ret_t ret=rinfo->reader(dest,plength,flags,errors,rinfo,cbinfo);
+
     if(ret != OPS_R_OK && ret != OPS_R_PARTIAL_READ)
 	return ret;
 
-    if(parse_info->accumulate)
+    if(rinfo->accumulate)
 	{
-	assert(parse_info->asize >= parse_info->alength);
-	if(parse_info->alength+*plength > parse_info->asize)
+	assert(rinfo->asize >= rinfo->alength);
+	if(rinfo->alength+*plength > rinfo->asize)
 	    {
-	    parse_info->asize=parse_info->asize*2+*plength;
-	    parse_info->accumulated=realloc(parse_info->accumulated,parse_info->asize);
+	    rinfo->asize=rinfo->asize*2+*plength;
+	    rinfo->accumulated=realloc(rinfo->accumulated,rinfo->asize);
 	    }
-	assert(parse_info->asize >= parse_info->alength+*plength);
-	memcpy(parse_info->accumulated+parse_info->alength,dest,*plength);
+	assert(rinfo->asize >= rinfo->alength+*plength);
+	memcpy(rinfo->accumulated+rinfo->alength,dest,*plength);
 	}
     // we track length anyway, because it is used for packet offsets
-    parse_info->alength+=*plength;
+    rinfo->alength+=*plength;
     // and also the position
-    parse_info->position+=*plength;
+    rinfo->position+=*plength;
 
     return ret;
     }
 
+ops_reader_ret_t ops_stacked_read(unsigned char *dest,unsigned *length,
+				  ops_reader_flags_t flags,
+				  ops_error_t **errors,
+				  ops_reader_info_t *rinfo,
+				  ops_parse_cb_info_t *cbinfo)
+    { return sub_base_read(dest,length,flags,errors,rinfo->next,cbinfo); }
+
+static ops_reader_ret_t base_read(unsigned char *dest,unsigned *plength,
+				  ops_reader_flags_t flags,
+				  ops_parse_info_t *info)
+    {
+    return sub_base_read(dest,plength,flags,&info->errors,&info->rinfo,
+			 &info->cbinfo);
+    }
+
 /** Read a scalar value of selected length from reader.
  *
  * Read an unsigned scalar value from reader in Big Endian representation.
@@ -235,24 +258,27 @@
  * \param *parse_info	How to parse, including callback function
  * \return		1 on success, 0 on error
  */
-int ops_limited_read(unsigned char *dest,unsigned length,
-		     ops_region_t *region,ops_parse_info_t *parse_info)
+ops_boolean_t ops_limited_read(unsigned char *dest,unsigned length,
+			       ops_region_t *region,ops_error_t **errors,
+			       ops_reader_info_t *rinfo,
+			       ops_parse_cb_info_t *cbinfo)
     {
     ops_parser_content_t content;
     ops_reader_ret_t ret;
 
     if(!region->indeterminate && region->length_read+length > region->length)
 	{
-	ERRCODE(OPS_E_P_NOT_ENOUGH_DATA);
+	ERRCODE(cbinfo,OPS_E_P_NOT_ENOUGH_DATA);
 	return 0;
 	}
 
-    ret=base_read(dest,&length,region->indeterminate ? OPS_RETURN_LENGTH : 0,
-		  parse_info);
+    ret=sub_base_read(dest,&length,
+		      region->indeterminate ? OPS_RETURN_LENGTH : 0,errors,
+		      rinfo,cbinfo);
 
     if(ret != OPS_R_OK && ret != OPS_R_PARTIAL_READ)
 	{
-	ERRCODE(OPS_E_R_READ_FAILED);
+	ERRCODE(cbinfo,OPS_E_R_READ_FAILED);
 	return 0;
 	}
 
@@ -267,6 +293,20 @@
     return 1;
     }
 
+ops_boolean_t ops_stacked_limited_read(unsigned char *dest,unsigned length,
+				       ops_region_t *region,
+				       ops_error_t **errors,
+				       ops_reader_info_t *rinfo,
+				       ops_parse_cb_info_t *cbinfo)
+    { return ops_limited_read(dest,length,region,errors,rinfo->next,cbinfo); }
+
+static ops_boolean_t limited_read(unsigned char *dest,unsigned length,
+				  ops_region_t *region,ops_parse_info_t *info)
+    {
+    return ops_limited_read(dest,length,region,&info->errors,&info->rinfo,
+			    &info->cbinfo);
+    }
+
 /** Skip over length bytes of this packet.
  *
  * Calls limited_read() to skip over some data.
@@ -286,7 +326,7 @@
     while(length)
 	{
 	int n=length%8192;
-	if(!ops_limited_read(buf,n,region,parse_info))
+	if(!limited_read(buf,n,region,parse_info))
 	    return 0;
 	length-=n;
 	}
@@ -319,7 +359,7 @@
 
     assert(length <= 4);
     assert(sizeof(*dest) >= 4);
-    if(!ops_limited_read(c,length,region,parse_info))
+    if(!limited_read(c,length,region,parse_info))
 	return 0;
 
     for(t=0,n=0 ; n < length ; ++n)
@@ -429,11 +469,11 @@
     length=(length+7)/8;
 
     assert(length <= 8192);
-    if(!ops_limited_read(buf,length,region,parse_info))
+    if(!limited_read(buf,length,region,parse_info))
 	return 0;
 
     if((buf[0] >> nonzero) != 0 || !(buf[0]&(1 << (nonzero-1))))
-	ERR("MPI format error");  /* XXX: Ben, one part of this constraint does not apply to encrypted MPIs the draft says. -- peter */
+	ERRP(parse_info,"MPI format error");  /* XXX: Ben, one part of this constraint does not apply to encrypted MPIs the draft says. -- peter */
 
     *pbn=BN_bin2bn(buf,length,NULL);
     return 1;
@@ -495,7 +535,7 @@
     {
     unsigned char c[1];
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     if(c[0] < 192)
 	{
@@ -506,7 +546,7 @@
 	{
 	unsigned t=(c[0]-192) << 8;
 
-	if(!ops_limited_read(c,1,region,parse_info))
+	if(!limited_read(c,1,region,parse_info))
 	    return 0;
 	*length=t+c[0]+192;
 	return 1;
@@ -740,11 +780,11 @@
 
     assert (region->length_read == 0);  /* We should not have read anything so far */
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     key->version=c[0];
     if(key->version < 2 || key->version > 4)
-	ERR1("Bad public key version (0x%02x)",key->version);
+	ERR1P(parse_info,"Bad public key version (0x%02x)",key->version);
 
     if(!limited_read_time(&key->creation_time,region,parse_info))
 	return 0;
@@ -754,7 +794,7 @@
        && !limited_read_scalar(&key->days_valid,2,region,parse_info))
 	return 0;
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
 
     key->algorithm=c[0];
@@ -786,7 +826,7 @@
 	break;
 
     default:
-	ERR1("Unknown public key algorithm (%d)",key->algorithm);
+	ERR1P(parse_info,"Unknown public key algorithm (%d)",key->algorithm);
 	}
 
     return 1;
@@ -816,9 +856,10 @@
 
     // XXX: this test should be done for all packets, surely?
     if(region->length_read != region->length)
-	ERR1("Unconsumed data (%d)",region->length-region->length_read);
+	ERR1P(parse_info,"Unconsumed data (%d)",
+	      region->length-region->length_read);
 
-    CB(tag,&content);
+    CBP(parse_info,tag,&content);
 
     return 1;
     }
@@ -867,7 +908,7 @@
     if(!read_data(&C.user_attribute.data,region,parse_info))
 	return 0;
 
-    CB(OPS_PTAG_CT_USER_ATTRIBUTE,&content);
+    CBP(parse_info,OPS_PTAG_CT_USER_ATTRIBUTE,&content);
 
     return 1;
     }
@@ -904,13 +945,13 @@
 
     C.user_id.user_id=malloc(region->length+1);  /* XXX should we not like check malloc's return value? */
 
-    if(region->length && !ops_limited_read(C.user_id.user_id,region->length,
-					   region,parse_info))
+    if(region->length && !limited_read(C.user_id.user_id,region->length,region,
+				       parse_info))
 	return 0;
 
     C.user_id.user_id[region->length]='\0'; /* terminate the string */
 
-    CB(OPS_PTAG_CT_USER_ID,&content);
+    CBP(parse_info,OPS_PTAG_CT_USER_ID,&content);
 
     return 1;
     }
@@ -985,7 +1026,8 @@
  *
  * \see RFC2440bis-12 5.2.2
  */
-static int parse_v3_signature(ops_region_t *region,ops_parse_info_t *parse_info)
+static int parse_v3_signature(ops_region_t *region,
+			      ops_parse_info_t *parse_info)
     {
     unsigned char c[1];
     ops_parser_content_t content;
@@ -993,12 +1035,12 @@
     C.signature.version=OPS_V3;
 
     /* hash info length */
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     if(c[0] != 5)
-	ERR("bad hash info length");
+	ERRP(parse_info,"bad hash info length");
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.signature.type=c[0];
     /* XXX: check signature type */
@@ -1007,21 +1049,21 @@
 	return 0;
     C.signature.creation_time_set=ops_true;
 
-    if(!ops_limited_read(C.signature.signer_id,OPS_KEY_ID_SIZE,region,parse_info))
+    if(!limited_read(C.signature.signer_id,OPS_KEY_ID_SIZE,region,parse_info))
 	return 0;
     C.signature.signer_id_set=ops_true;
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.signature.key_algorithm=c[0];
     /* XXX: check algorithm */
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.signature.hash_algorithm=c[0];
     /* XXX: check algorithm */
     
-    if(!ops_limited_read(C.signature.hash2,2,region,parse_info))
+    if(!limited_read(C.signature.hash2,2,region,parse_info))
 	return 0;
 
     switch(C.signature.key_algorithm)
@@ -1045,13 +1087,13 @@
 	break;
 
     default:
-	ERR1("Bad signature key algorithm (%d)",C.signature.key_algorithm);
+	ERR1P(parse_info,"Bad signature key algorithm (%d)",C.signature.key_algorithm);
 	}
 
     if(region->length_read != region->length)
-	ERR1("Unconsumed data (%d)",region->length-region->length_read);
+	ERR1P(parse_info,"Unconsumed data (%d)",region->length-region->length_read);
 
-    CB(OPS_PTAG_CT_SIGNATURE,&content);
+    CBP(parse_info,OPS_PTAG_CT_SIGNATURE,&content);
 
     return 1;
     }
@@ -1088,9 +1130,9 @@
 	return 0;
 
     if(subregion.length > region->length)
-	ERR("Subpacket too long");
+	ERRP(parse_info,"Subpacket too long");
 
-    if(!ops_limited_read(c,1,&subregion,parse_info))
+    if(!limited_read(c,1,&subregion,parse_info))
 	return 0;
 
     t8=(c[0]&0x7f)/8;
@@ -1105,9 +1147,9 @@
 	C.ss_raw.tag=content.tag;
 	C.ss_raw.length=subregion.length-1;
 	C.ss_raw.raw=malloc(C.ss_raw.length);
-	if(!ops_limited_read(C.ss_raw.raw,C.ss_raw.length,&subregion,parse_info))
+	if(!limited_read(C.ss_raw.raw,C.ss_raw.length,&subregion,parse_info))
 	    return 0;
-	CB(OPS_PTAG_RAW_SS,&content);
+	CBP(parse_info,OPS_PTAG_RAW_SS,&content);
 	return 1;
 	}
 
@@ -1126,19 +1168,19 @@
 	break;
 
     case OPS_PTAG_SS_TRUST:
-	if(!ops_limited_read(&C.ss_trust.level,1,&subregion,parse_info)
-	   || !ops_limited_read(&C.ss_trust.amount,1,&subregion,parse_info))
+	if(!limited_read(&C.ss_trust.level,1,&subregion,parse_info)
+	   || !limited_read(&C.ss_trust.amount,1,&subregion,parse_info))
 	    return 0;
 	break;
 
     case OPS_PTAG_SS_REVOCABLE:
-	if(!ops_limited_read(bool,1,&subregion,parse_info))
+	if(!limited_read(bool,1,&subregion,parse_info))
 	    return 0;
 	C.ss_revocable.revocable=!!bool;
 	break;
 
     case OPS_PTAG_SS_ISSUER_KEY_ID:
-	if(!ops_limited_read(C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE,
+	if(!limited_read(C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE,
 			     &subregion,parse_info))
 	    return 0;
 	memcpy(sig->signer_id,C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE);
@@ -1161,7 +1203,7 @@
 	break;
 			    	
     case OPS_PTAG_SS_PRIMARY_USER_ID:
-	if(!ops_limited_read (bool,1,&subregion,parse_info))
+	if(!limited_read (bool,1,&subregion,parse_info))
 	    return 0;
 	C.ss_primary_user_id.primary_user_id = !!bool;
 	break;
@@ -1240,7 +1282,7 @@
 
     case OPS_PTAG_SS_REVOCATION_REASON:
 	/* first byte is the machine-readable code */
-	if(!ops_limited_read(&C.ss_revocation_reason.code,1,&subregion,parse_info))
+	if(!limited_read(&C.ss_revocation_reason.code,1,&subregion,parse_info))
 	    return 0;
 
 	/* the rest is a human-readable UTF-8 string */
@@ -1250,7 +1292,7 @@
 
     case OPS_PTAG_SS_REVOCATION_KEY:
 	/* octet 0 = class. Bit 0x80 must be set */
-	if(!ops_limited_read (&C.ss_revocation_key.class,1,&subregion,parse_info))
+	if(!limited_read (&C.ss_revocation_key.class,1,&subregion,parse_info))
 	    return 0;
 	if(!(C.ss_revocation_key.class&0x80))
 	    {
@@ -1260,18 +1302,19 @@
 	    }
  
 	/* octet 1 = algid */
-	if(!ops_limited_read(&C.ss_revocation_key.algid,1,&subregion,parse_info))
+	if(!limited_read(&C.ss_revocation_key.algid,1,&subregion,parse_info))
 	    return 0;
  
 	/* octets 2-21 = fingerprint */
-	if(!ops_limited_read(&C.ss_revocation_key.fingerprint[0],20,&subregion,
-			     parse_info))
+	if(!limited_read(&C.ss_revocation_key.fingerprint[0],20,&subregion,
+			 parse_info))
 	    return 0;
 	break;
  
     default:
 	if(parse_info->ss_parsed[t8]&t7)
-	    ERR1("Unknown signature subpacket type (%d)",c[0]&0x7f);
+	    ERR1P(parse_info,"Unknown signature subpacket type (%d)",
+		  c[0]&0x7f);
 	read=ops_false;
 	break;
 	}
@@ -1280,7 +1323,8 @@
     if(!(parse_info->ss_parsed[t8]&t7))
 	{
 	if(content.critical)
-	    ERR1("Critical signature subpacket ignored (%d)",c[0]&0x7f);
+	    ERR1P(parse_info,"Critical signature subpacket ignored (%d)",
+		  c[0]&0x7f);
 	if(!read && !limited_skip(subregion.length-1,&subregion,parse_info))
 	    return 0;
 	//	printf("skipped %d length %d\n",c[0]&0x7f,subregion.length);
@@ -1290,9 +1334,9 @@
 	}
 
     if(read && subregion.length_read != subregion.length)
-	ERR1("Unconsumed data (%d)", subregion.length-subregion.length_read);
+	ERR1P(parse_info,"Unconsumed data (%d)", subregion.length-subregion.length_read);
  
-    CB(content.tag,&content);
+    CBP(parse_info,content.tag,&content);
 
     return 1;
     }
@@ -1360,7 +1404,7 @@
 	return 0;
 
     if(subregion.length > region->length)
-	ERR("Subpacket set too long");
+	ERRP(parse_info,"Subpacket set too long");
 
     while(subregion.length_read < subregion.length)
 	if(!parse_one_signature_subpacket(sig,&subregion,parse_info))
@@ -1370,8 +1414,8 @@
 	{
 	if(!limited_skip(subregion.length-subregion.length_read,&subregion,
 			 parse_info))
-	    ERR("Read failed while recovering from subpacket length mismatch");
-	ERR("Subpacket length mismatch");
+	    ERRP(parse_info,"Read failed while recovering from subpacket length mismatch");
+	ERRP(parse_info,"Subpacket length mismatch");
 	}
 
     return 1;
@@ -1400,32 +1444,32 @@
     C.signature.version=OPS_V4;
     C.signature.v4_hashed_data_start=v4_hashed_data_start;
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.signature.type=c[0];
     /* XXX: check signature type */
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.signature.key_algorithm=c[0];
     /* XXX: check algorithm */
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.signature.hash_algorithm=c[0];
     /* XXX: check algorithm */
 
-    CB(OPS_PTAG_CT_SIGNATURE_HEADER,&content);
+    CBP(parse_info,OPS_PTAG_CT_SIGNATURE_HEADER,&content);
 
     if(!parse_signature_subpackets(&C.signature,region,parse_info))
 	return 0;
-    C.signature.v4_hashed_data_length=parse_info->alength
+    C.signature.v4_hashed_data_length=parse_info->rinfo.alength
 	-C.signature.v4_hashed_data_start;
 
     if(!parse_signature_subpackets(&C.signature,region,parse_info))
 	return 0;
     
-    if(!ops_limited_read(C.signature.hash2,2,region,parse_info))
+    if(!limited_read(C.signature.hash2,2,region,parse_info))
 	return 0;
 
     switch(C.signature.key_algorithm)
@@ -1437,9 +1481,9 @@
 
     case OPS_PKA_DSA:
 	if(!limited_read_mpi(&C.signature.signature.dsa.r,region,parse_info)) 
-	    ERR("Error reading DSA r field in signature");
+	    ERRP(parse_info,"Error reading DSA r field in signature");
 	if (!limited_read_mpi(&C.signature.signature.dsa.s,region,parse_info))
-	    ERR("Error reading DSA s field in signature");
+	    ERRP(parse_info,"Error reading DSA s field in signature");
 	break;
 
     case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
@@ -1464,13 +1508,15 @@
 	break;
 
     default:
-	ERR1("Bad v4 signature key algorithm (%d)",C.signature.key_algorithm);
+	ERR1P(parse_info,"Bad v4 signature key algorithm (%d)",
+	      C.signature.key_algorithm);
 	}
 
     if(region->length_read != region->length)
-	ERR1("Unconsumed data (%d)",region->length-region->length_read);
+	ERR1P(parse_info,"Unconsumed data (%d)",
+	      region->length-region->length_read);
 
-    CB(OPS_PTAG_CT_SIGNATURE_FOOTER,&content);
+    CBP(parse_info,OPS_PTAG_CT_SIGNATURE_FOOTER,&content);
 
     return 1;
     }
@@ -1496,17 +1542,15 @@
 
     memset(&content,'\0',sizeof content);
 
-    v4_hashed_data_start=parse_info->alength;
-    if(!ops_limited_read(c,1,region,parse_info))
+    v4_hashed_data_start=parse_info->rinfo.alength;
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
 
-    /* XXX: More V2 issues!  - Ben*/
-    /* XXX: are there v2 signatures? - Peter */
     if(c[0] == 2 || c[0] == 3)
 	return parse_v3_signature(region,parse_info);
     else if(c[0] == 4)
 	return parse_v4_signature(region,parse_info,v4_hashed_data_start);
-    ERR1("Bad signature version (%d)",c[0]);
+    ERR1P(parse_info,"Bad signature version (%d)",c[0]);
     }
 
 static int parse_compressed(ops_region_t *region,ops_parse_info_t *parse_info)
@@ -1514,12 +1558,12 @@
     unsigned char c[1];
     ops_parser_content_t content;
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
 
     C.compressed.type=c[0];
 
-    CB(OPS_PTAG_CT_COMPRESSED,&content);
+    CBP(parse_info,OPS_PTAG_CT_COMPRESSED,&content);
 
     /* The content of a compressed data packet is more OpenPGP packets
        once decompressed, so recursively handle them */
@@ -1532,33 +1576,33 @@
     unsigned char c[1];
     ops_parser_content_t content;
 
-    if(!ops_limited_read(&C.one_pass_signature.version,1,region,parse_info))
+    if(!limited_read(&C.one_pass_signature.version,1,region,parse_info))
 	return 0;
     if(C.one_pass_signature.version != 3)
-	ERR1("Bad one-pass signature version (%d)",
+	ERR1P(parse_info,"Bad one-pass signature version (%d)",
 	     C.one_pass_signature.version);
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.one_pass_signature.sig_type=c[0];
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.one_pass_signature.hash_algorithm=c[0];
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.one_pass_signature.key_algorithm=c[0];
 
-    if(!ops_limited_read(C.one_pass_signature.keyid,
+    if(!limited_read(C.one_pass_signature.keyid,
 			 sizeof C.one_pass_signature.keyid,region,parse_info))
 	return 0;
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.one_pass_signature.nested=!!c[0];
 
-    CB(OPS_PTAG_CT_ONE_PASS_SIGNATURE,&content);
+    CBP(parse_info,OPS_PTAG_CT_ONE_PASS_SIGNATURE,&content);
 
     return 1;
     }
@@ -1602,7 +1646,7 @@
     if(!read_data(&C.trust.data,region,parse_info))
 	    return 0;
 
-    CB(OPS_PTAG_CT_TRUST, &content);
+    CBP(parse_info,OPS_PTAG_CT_TRUST, &content);
 
     return 1;
     }
@@ -1612,20 +1656,21 @@
     ops_parser_content_t content;
     unsigned char c[1];
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.literal_data_header.format=c[0];
 
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
-    if(!ops_limited_read((unsigned char *)C.literal_data_header.filename,c[0],region,parse_info))
+    if(!limited_read((unsigned char *)C.literal_data_header.filename,c[0],
+		     region,parse_info))
 	return 0;
     C.literal_data_header.filename[c[0]]='\0';
 
     if(!limited_read_time(&C.literal_data_header.modification_time,region,parse_info))
 	return 0;
 
-    CB(OPS_PTAG_CT_LITERAL_DATA_HEADER,&content);
+    CBP(parse_info,OPS_PTAG_CT_LITERAL_DATA_HEADER,&content);
 
     while(region->length_read < region->length)
 	{
@@ -1634,12 +1679,12 @@
 	if(l > sizeof C.literal_data_body.data)
 	    l=sizeof C.literal_data_body.data;
 
-	if(!ops_limited_read(C.literal_data_body.data,l,region,parse_info))
+	if(!limited_read(C.literal_data_body.data,l,region,parse_info))
 	    return 0;
 
 	C.literal_data_body.length=l;
 
-	CB(OPS_PTAG_CT_LITERAL_DATA_BODY,&content);
+	CBP(parse_info,OPS_PTAG_CT_LITERAL_DATA_BODY,&content);
 	}
 
     return 1;
@@ -1681,7 +1726,7 @@
 
     if(!parse_public_key_data(&C.secret_key.public_key,region,parse_info))
 	return 0;
-    if(!ops_limited_read(c,1,region,parse_info))
+    if(!limited_read(c,1,region,parse_info))
 	return 0;
     C.secret_key.s2k_usage=c[0];
     assert(C.secret_key.s2k_usage == OPS_S2K_NONE);
@@ -1706,7 +1751,7 @@
 	return 0;
     // XXX: check the checksum
 
-    CB(OPS_PTAG_CT_SECRET_KEY,&content);
+    CBP(parse_info,OPS_PTAG_CT_SECRET_KEY,&content);
 
     return 1;
     }
@@ -1720,7 +1765,8 @@
  * \param *parse_info	How to parse
  * \param *pktlen	On return, will contain number of bytes in packet
  * \return 1 on success, 0 on error, -1 on EOF */
-static int ops_parse_one_packet(ops_parse_info_t *parse_info,unsigned long *pktlen)
+static int ops_parse_one_packet(ops_parse_info_t *parse_info,
+				unsigned long *pktlen)
     {
     unsigned char ptag[1];
     ops_reader_ret_t ret;
@@ -1730,7 +1776,7 @@
     unsigned one=1;
     ops_boolean_t indeterminate=ops_false;
 
-    C.ptag.position=parse_info->position;
+    C.ptag.position=parse_info->rinfo.position;
 
     ret=base_read(ptag,&one,0,parse_info);
     if(ret == OPS_R_EOF || ret == OPS_R_EARLY_EOF)
@@ -1742,7 +1788,7 @@
     if(!(*ptag&OPS_PTAG_ALWAYS_SET))
 	{
 	C.error.error="Format error (ptag bit not set)";
-	CB(OPS_PARSER_ERROR,&content);
+	CBP(parse_info,OPS_PARSER_ERROR,&content);
 	return 0;
 	}
     C.ptag.new_format=!!(*ptag&OPS_PTAG_NEW_FORMAT);
@@ -1783,7 +1829,7 @@
 	    return -1;
 	}
 
-    CB(OPS_PARSER_PTAG,&content);
+    CBP(parse_info,OPS_PARSER_PTAG,&content);
 
     ops_init_subregion(&region,NULL);
     region.length=C.ptag.length;
@@ -1830,7 +1876,7 @@
     default:
 	format_error(&content,"Format error (unknown content tag %d)",
 		     C.ptag.content_tag);
-	CB(OPS_PARSER_ERROR,&content);
+	CBP(parse_info,OPS_PARSER_ERROR,&content);
 	r=0;
 	}
 
@@ -1845,27 +1891,27 @@
 	    {
 	    /* now throw it away */
 	    data_free(&remainder);
-	    WARN("Remainder of packet consumed and discarded.");
+	    WARNP(parse_info,"Remainder of packet consumed and discarded.");
 	    }
 	else
-	    WARN("Problem consuming remainder of error packet.");
+	    WARNP(parse_info,"Problem consuming remainder of error packet.");
 	}
 
     /* set pktlen */
 
-    *pktlen=parse_info->alength;
+    *pktlen=parse_info->rinfo.alength;
 
     /* do callback on entire packet, if desired */
 
-    if(parse_info->accumulate)
+    if(parse_info->rinfo.accumulate)
 	{
-	C.packet.length=parse_info->alength;
-	C.packet.raw=parse_info->accumulated;
-	parse_info->accumulated=NULL;
-	parse_info->asize=0;
-	CB(OPS_PARSER_PACKET_END,&content);
+	C.packet.length=parse_info->rinfo.alength;
+	C.packet.raw=parse_info->rinfo.accumulated;
+	parse_info->rinfo.accumulated=NULL;
+	parse_info->rinfo.asize=0;
+	CBP(parse_info,OPS_PARSER_PACKET_END,&content);
 	}
-    parse_info->alength=0;
+    parse_info->rinfo.alength=0;
 	
     return r ? 1 : 0;
     }
@@ -1907,6 +1953,7 @@
     return parse_info->errors ? 0 : 1;
     }
 
+#if 0
 /**
  *
  * \return 1 if success, 0 otherwise
@@ -1923,21 +1970,21 @@
 
     /* can only handle ops_reader_fd for now */
 
-    if (parse_info->reader != ops_reader_fd)
+    if (parse_info->rinfo.reader != ops_reader_fd)
 	{
 	fprintf(stderr,"ops_parse_errs: can only handle ops_reader_fd\n");
 	return 0;
 	}
 
-    arg=parse_info->reader_arg;
+    arg=parse_info->rinfo.arg;
 
     /* store current state of accumulate flag */
 
-    orig_acc=parse_info->accumulate;
+    orig_acc=parse_info->rinfo.accumulate;
 
     /* set accumulate flag */
 
-    parse_info->accumulate=1;
+    parse_info->rinfo.accumulate=1;
 
     /* now parse each error in turn. */
 
@@ -1962,10 +2009,11 @@
 	}
 
     /* restore accumulate flag original value */
-    parse_info->accumulate=orig_acc;
+    parse_info->rinfo.accumulate=orig_acc;
 
     return 1;
     }
+#endif
 
 /**
  * \ingroup Parse
@@ -2016,6 +2064,61 @@
 	}
     }
 
+ops_parse_info_t *ops_parse_info_new(void)
+    { return ops_mallocz(sizeof(ops_parse_info_t)); }
 
+void ops_parse_info_delete(ops_parse_info_t *pinfo)
+    { free(pinfo); }
+
+ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo)
+    { return &pinfo->rinfo; }
+
+void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg)
+    {
+    pinfo->cbinfo.cb=cb;
+    pinfo->cbinfo.arg=arg;
+    }
+
+void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg)
+    {
+    ops_parse_cb_info_t *cbinfo=malloc(sizeof *cbinfo);
+
+    *cbinfo=pinfo->cbinfo;
+    pinfo->cbinfo.next=cbinfo;
+    ops_parse_cb_set(pinfo,cb,arg);
+    }
+
+void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo)
+    { return cbinfo->arg; }
+
+ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content,
+				   ops_parse_cb_info_t *cbinfo)
+    { return cbinfo->cb(content,cbinfo); }
+
+ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content,
+					   ops_parse_cb_info_t *cbinfo)
+    { return ops_parse_cb(content,cbinfo->next); }
+
+void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,void *arg)
+    {
+    pinfo->rinfo.reader=reader;
+    pinfo->rinfo.arg=arg;
+    }
+
+void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,void *arg)
+    {
+    ops_reader_info_t *rinfo=malloc(sizeof *rinfo);
+
+    *rinfo=pinfo->rinfo;
+    pinfo->rinfo.next=rinfo;
+    ops_reader_set(pinfo,reader,arg);
+    }
+
+void *ops_reader_get_arg(ops_reader_info_t *rinfo)
+    { return rinfo->arg; }
+
+ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo)
+    { return pinfo->errors; }
+
 /* vim:set textwidth=120: */
 /* vim:set ts=8: */

Modified: openpgpsdk/trunk/src/util.c
===================================================================
--- openpgpsdk/trunk/src/util.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/util.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -78,6 +78,13 @@
     ops_crypto_finish();
     }
 
+/** Arguments for reader_fd
+ */
+typedef struct
+    {
+    int fd; /*!< file descriptor */
+    } reader_fd_arg_t;
+
 /**
  * \ingroup Parse
  *
@@ -102,19 +109,23 @@
  *
  * \todo change arg_ to typesafe? 
  */
-ops_reader_ret_t ops_reader_fd(unsigned char *dest,unsigned *plength,
-			       ops_reader_flags_t flags,
-			       ops_parse_info_t *parse_info)
+static ops_reader_ret_t reader_fd(unsigned char *dest,unsigned *plength,
+				  ops_reader_flags_t flags,
+				  ops_error_t **errors,
+				  ops_reader_info_t *rinfo,
+				  ops_parse_cb_info_t *cbinfo)
     {
-    ops_reader_fd_arg_t *arg=parse_info->reader_arg;
+    reader_fd_arg_t *arg=ops_reader_get_arg(rinfo);
     int n=read(arg->fd,dest,*plength);
 
+    OPS_USED(cbinfo);
+
     if(n == 0)
 	return OPS_R_EOF;
 
     if(n == -1)
 	{
-	ops_system_error_1(&parse_info->errors,OPS_E_R_READ_FAILED,"read",
+	OPS_SYSTEM_ERROR_1(errors,OPS_E_R_READ_FAILED,"read",
 			   "file descriptor %d",arg->fd);
 	return OPS_R_ERROR;
 	}
@@ -128,8 +139,7 @@
 	    }
 	else
 	    {
-	    ops_error_1(&parse_info->errors,OPS_E_R_EARLY_EOF,
-			       "file descriptor %d",arg->fd);
+	    OPS_ERROR_1(errors,OPS_E_R_EARLY_EOF,"file descriptor %d",arg->fd);
 	    return OPS_R_EARLY_EOF;
 	    }
 	}
@@ -141,6 +151,14 @@
     return OPS_R_OK;
     }
 
+void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd)
+    {
+    reader_fd_arg_t *arg=malloc(sizeof *arg);
+
+    arg->fd=fd;
+    ops_reader_set(pinfo,reader_fd,arg);
+    }
+
 void *ops_mallocz(size_t n)
     {
     void *m=malloc(n);

Modified: openpgpsdk/trunk/src/validate.c
===================================================================
--- openpgpsdk/trunk/src/validate.c	2005-12-01 13:38:12 UTC (rev 319)
+++ openpgpsdk/trunk/src/validate.c	2005-12-07 09:39:44 UTC (rev 320)
@@ -6,9 +6,6 @@
 #include <assert.h>
 #include <string.h>
 
-/* XXX: because we might well use this reader with different callbacks
-   it would make sense to split the arguments for callbacks, one for the reader
-   and one for the callback */
 typedef struct
     {
     const ops_key_data_t *key;
@@ -27,11 +24,15 @@
 
 static ops_reader_ret_t key_data_reader(unsigned char *dest,unsigned *plength,
 					ops_reader_flags_t flags,
-					ops_parse_info_t *parse_info)
+					ops_error_t **errors,
+					ops_reader_info_t *rinfo,
+					ops_parse_cb_info_t *cbinfo)
     {
-    validate_reader_arg_t *arg=parse_info->reader_arg;
+    validate_reader_arg_t *arg=ops_reader_get_arg(rinfo);
 
     OPS_USED(flags);
+    OPS_USED(errors);
+    OPS_USED(cbinfo);
     if(arg->offset == arg->key->packets[arg->packet].length)
 	{
 	++arg->packet;
@@ -54,11 +55,11 @@
  * \ingroup Callbacks
  */
 
-static ops_parse_callback_return_t
-validate_cb(const ops_parser_content_t *content_,void *arg_)
+static ops_parse_cb_return_t
+validate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
      {
      const ops_parser_content_union_t *content=&content_->content;
-     validate_cb_arg_t *arg=arg_;
+     validate_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
      const ops_key_data_t *signer;
      ops_boolean_t valid;
 
@@ -136,17 +137,15 @@
 static void validate_key_signatures(const ops_key_data_t *key,
 				    const ops_keyring_t *keyring)
     {
-    ops_parse_info_t parse_info;
+    ops_parse_info_t *pinfo;
     validate_cb_arg_t carg;
     validate_reader_arg_t rarg;
 
     memset(&rarg,'\0',sizeof rarg);
     memset(&carg,'\0',sizeof carg);
 
-    ops_parse_info_init(&parse_info);
+    pinfo=ops_parse_info_new();
     //    ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED);
-    parse_info.cb=validate_cb;
-    parse_info.reader=key_data_reader;
 
     rarg.key=key;
     rarg.packet=0;
@@ -155,10 +154,10 @@
     carg.keyring=keyring;
     carg.rarg=&rarg;
 
-    parse_info.cb_arg=&carg;
-    parse_info.reader_arg=&rarg;
+    ops_parse_cb_set(pinfo,validate_cb,&carg);
+    ops_reader_set(pinfo,key_data_reader,&rarg);
 
-    ops_parse(&parse_info);
+    ops_parse(pinfo);
 
     ops_public_key_free(&carg.pkey);
     if(carg.subkey.version)



More information about the OpenPGPsdk-svn mailing list