2003-07-30 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / src / sexp.c
1 /* sexp.c  -  S-Expression handling
2  * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include <assert.h>
29
30 #define GCRYPT_NO_MPI_MACROS 1
31 #include "g10lib.h"
32 #include "memory.h"
33
34 typedef struct gcry_sexp *NODE;
35 typedef unsigned short DATALEN;
36
37 struct gcry_sexp
38 {
39   byte d[1];
40 };
41
42 #define ST_STOP  0
43 #define ST_DATA  1  /* datalen follows */
44 #define ST_HINT  2  /* datalen follows */
45 #define ST_OPEN  3
46 #define ST_CLOSE 4
47
48 /* the atoi macros assume that the buffer has only valid digits */
49 #define atoi_1(p)   (*(p) - '0' )
50 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
51                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
52 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
53
54 #define TOKEN_SPECIALS  "-./_:*+="
55
56 static gcry_error_t
57 sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
58             const char *buffer, size_t length, int argflag,
59             va_list arg_ptr, void **arg_list);
60
61 #if 0
62 static void
63 dump_mpi( gcry_mpi_t a )
64 {
65     char buffer[1000];
66     size_t n = 1000;
67
68     if( !a )
69         fputs("[no MPI]", stderr );
70     else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
71         fputs("[MPI too large to print]", stderr );
72     else
73         fputs( buffer, stderr );
74 }
75 #endif
76
77 static void
78 dump_string (const byte *p, size_t n, int delim )
79 {
80   for (; n; n--, p++ )
81     {
82       if ((*p & 0x80) || iscntrl( *p ) || *p == delim ) 
83         {
84           if( *p == '\n' )
85             log_printf ("\\n");
86           else if( *p == '\r' )
87             log_printf ("\\r");
88           else if( *p == '\f' )
89             log_printf ("\\f");
90           else if( *p == '\v' )
91             log_printf ("\\v");
92             else if( *p == '\b' )
93               log_printf ("\\b");
94           else if( !*p )       
95             log_printf ("\\0");
96           else
97             log_printf ("\\x%02x", *p );
98         }
99       else
100         log_printf ("%c", *p);
101     }
102 }
103
104
105 void
106 gcry_sexp_dump (const gcry_sexp_t a)
107 {
108   const byte *p;
109   int indent = 0;
110   int type;
111
112   if (!a)
113     {
114       log_printf ( "[nil]\n");
115       return;
116     }
117
118   p = a->d;
119   while ( (type = *p) != ST_STOP )
120     {
121       p++;
122       switch ( type )
123         {
124         case ST_OPEN:
125           log_printf ("%*s[open]\n", 2*indent, "");
126           indent++;
127           break;
128         case ST_CLOSE:
129           if( indent )
130             indent--;
131           log_printf ("%*s[close]\n", 2*indent, "");
132           break;
133         case ST_DATA: {
134           DATALEN n;
135           memcpy ( &n, p, sizeof n );
136           p += sizeof n;
137           log_printf ("%*s[data=\"", 2*indent, "" );
138           dump_string (p, n, '\"' );
139           log_printf ("\"]\n");
140           p += n;
141         }
142         break;
143         default:
144           log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
145           break;
146         }
147     }
148 }
149
150 /****************
151  * Pass list through except when it is an empty list - in that case
152  * return NULL and release the passed list.
153  */
154 static gcry_sexp_t
155 normalize ( gcry_sexp_t list )
156 {
157     char *p;
158     if ( !list )
159         return NULL;
160     p = list->d;
161     if ( *p == ST_STOP ) {
162         /* this is "" */
163         gcry_sexp_release ( list );
164         return NULL;
165     }
166     if( *p == ST_OPEN && p[1] == ST_CLOSE ) {
167         /* this is "()" */
168         gcry_sexp_release ( list );
169         return NULL;
170     }
171
172     return list;
173 }
174
175 /* Create a new S-expression object by reading LENGTH bytes from
176    BUFFER, assuming it is canonilized encoded or autodetected encoding
177    when AUTODETECT is set to 1.  With FREEFNC not NULL, ownership of
178    the buffer is transferred to tyhe newle created object.  FREEFNC
179    should be the freefnc used to release BUFFER; there is no guarantee
180    at which point this function is called; most likey you want to use
181    free() or gcry_free(). 
182  
183    Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
184    BUFFER points to a valid canonical encoded S-expression.  A LENGTH
185    of 0 and AUTODETECT 1 indicates that buffer points to a
186    null-terminated string.
187   
188    This function returns 0 and and the pointer to the new object in
189    RETSEXP or an error code in which case RETSEXP is set to NULL.  */
190 gcry_error_t
191 gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
192                   int autodetect, void (*freefnc)(void*) )
193 {
194   gcry_error_t errcode;
195   gcry_sexp_t se;
196   volatile va_list dummy_arg_ptr;
197
198   if (!retsexp)
199     return gcry_error (GPG_ERR_INV_ARG);
200   *retsexp = NULL;
201   if (autodetect < 0 || autodetect > 1 || !buffer)
202     return gcry_error (GPG_ERR_INV_ARG);
203
204   if (!length && !autodetect)
205     { /* What a brave caller to assume that there is really a canonical
206          encoded S-expression in buffer */
207       length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
208       if (!length)
209         return errcode;
210     }
211   else if (!length && autodetect)
212     { /* buffer is a string */
213       length = strlen ((char *)buffer);
214     }
215
216   errcode = sexp_sscan (&se, NULL, buffer, length, 0, dummy_arg_ptr, NULL);
217   if (errcode)
218     return errcode;
219
220   *retsexp = se;
221   if (freefnc)
222     {
223       /* For now we release the buffer immediately.  As soon as we
224          have changed the internal represenation of S-expression to
225          the canoncial format - which has the advantage of faster
226          parsing - we will use this function as a closure in our
227          GCRYSEXP object and use the BUFFER directly */
228       freefnc (buffer);
229     }
230   return gcry_error (GPG_ERR_NO_ERROR);
231 }
232
233 /* Same as gcry_sexp_create but don't transfer ownership */
234 gcry_error_t
235 gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
236                int autodetect)
237 {
238   return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
239 }
240
241
242 /****************
243  * Release resource of the given SEXP object.
244  */
245 void
246 gcry_sexp_release( gcry_sexp_t sexp )
247 {
248     gcry_free ( sexp );
249 }
250
251
252 /****************
253  * Make a pair from lists a and b, don't use a or b later on.
254  * Special behaviour:  If one is a single element list we put the
255  * element straight into the new pair.
256  */
257 gcry_sexp_t
258 gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
259 {
260     /* NYI: Implementation should be quite easy with our new data representation */
261     BUG ();
262     return NULL;
263 }
264
265
266 /****************
267  * Make a list from all items in the array the end of the array is marked
268  * with a NULL.                                                                       y a NULL
269  */
270 gcry_sexp_t
271 gcry_sexp_alist( const gcry_sexp_t *array )
272 {
273     /* NYI: Implementaion should be quite easy with our new data representation */
274     BUG ();
275     return NULL;
276 }
277
278 /****************
279  * Make a list from all items, the end of list is indicated by a NULL
280  */
281 gcry_sexp_t
282 gcry_sexp_vlist( const gcry_sexp_t a, ... )
283 {
284     /* NYI: Implementaion should be quite easy with our new data representation */
285     BUG ();
286     return NULL;
287 }
288
289
290 /****************
291  * Append n to the list a
292  * Returns: a new ist (which maybe a)
293  */
294 gcry_sexp_t
295 gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
296 {
297     /* NYI: Implementaion should be quite easy with our new data representation */
298     BUG ();
299     return NULL;
300 }
301
302 gcry_sexp_t
303 gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
304 {
305     /* NYI: Implementaion should be quite easy with our new data representation */
306     BUG ();
307     return NULL;
308 }
309
310
311
312 /****************
313  * Locate token in a list. The token must be the car of a sublist.
314  * Returns: A new list with this sublist or NULL if not found.
315  */
316 gcry_sexp_t
317 gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
318 {
319     const byte *p;
320     DATALEN n;
321
322     if ( !list )
323         return NULL;
324
325     if( !toklen )
326         toklen = strlen(tok);
327     p = list->d;
328     while ( *p != ST_STOP ) {
329         if ( *p == ST_OPEN && p[1] == ST_DATA ) {
330             const byte *head = p;
331
332             p += 2;
333             memcpy ( &n, p, sizeof n ); p += sizeof n;
334             if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */
335                 gcry_sexp_t newlist;
336                 byte *d;
337                 int level = 1;
338
339                 /* look for the end of the list */
340                 for ( p += n; level; p++ ) {
341                     if ( *p == ST_DATA ) {
342                         memcpy ( &n, ++p, sizeof n );
343                         p += sizeof n + n;
344                         p--; /* compensate for later increment */
345                     }
346                     else if ( *p == ST_OPEN ) {
347                         level++;
348                     }
349                     else if ( *p == ST_CLOSE ) {
350                         level--;
351                     }
352                     else if ( *p == ST_STOP ) {
353                         BUG ();
354                     }
355                 } while ( level );
356                 n = p - head;
357
358                 newlist = gcry_xmalloc ( sizeof *newlist + n );
359                 d = newlist->d;
360                 memcpy ( d, head, n ); d += n;
361                 *d++ = ST_STOP;
362                 return normalize ( newlist );
363             }
364             p += n;
365         }
366         else if ( *p == ST_DATA ) {
367             memcpy ( &n, ++p, sizeof n ); p += sizeof n;
368             p += n;
369         }
370         else
371             p++;
372     }
373     return NULL;
374 }
375
376 /****************
377  * Return the length of the given list
378  */
379 int
380 gcry_sexp_length( const gcry_sexp_t list )
381 {
382     const byte *p;
383     DATALEN n;
384     int type;
385     int length = 0;
386     int level = 0;
387
388     if ( !list )
389         return 0;
390
391     p = list->d;
392     while ( (type=*p) != ST_STOP ) {
393         p++;
394         if ( type == ST_DATA ) {
395             memcpy ( &n, p, sizeof n );
396             p += sizeof n + n;
397             if ( level == 1 )
398                 length++;
399         }
400         else if ( type == ST_OPEN ) {
401             if ( level == 1 )
402                 length++;
403             level++;
404         }
405         else if ( type == ST_CLOSE ) {
406             level--;
407         }
408     }
409     return length;
410 }
411
412
413
414 /****************
415  * Extract the CAR of the given list
416  */
417 gcry_sexp_t
418 gcry_sexp_nth( const gcry_sexp_t list, int number )
419 {
420     const byte *p;
421     DATALEN n;
422     gcry_sexp_t newlist;
423     byte *d;
424     int level = 0;
425
426     if ( !list || list->d[0] != ST_OPEN )
427         return NULL;
428     p = list->d;
429
430     while ( number > 0 ) {
431         p++;
432         if ( *p == ST_DATA ) {
433             memcpy ( &n, ++p, sizeof n );
434             p += sizeof n + n;
435             p--;
436             if ( !level )
437                 number--;
438         }
439         else if ( *p == ST_OPEN ) {
440             level++;
441         }
442         else if ( *p == ST_CLOSE ) {
443             level--;
444             if ( !level )
445                 number--;
446         }
447         else if ( *p == ST_STOP ) {
448             return NULL;
449         }
450     }
451     p++;
452
453     if ( *p == ST_DATA ) {
454         memcpy ( &n, p, sizeof n ); p += sizeof n;
455         newlist = gcry_xmalloc ( sizeof *newlist + n + 1 );
456         d = newlist->d;
457         memcpy ( d, p, n ); d += n;
458         *d++ = ST_STOP;
459     }
460     else if ( *p == ST_OPEN ) {
461         const byte *head = p;
462
463         level = 1;
464         do {
465             p++;
466             if ( *p == ST_DATA ) {
467                 memcpy ( &n, ++p, sizeof n );
468                 p += sizeof n + n;
469                 p--;
470             }
471             else if ( *p == ST_OPEN ) {
472                 level++;
473             }
474             else if ( *p == ST_CLOSE ) {
475                 level--;
476             }
477             else if ( *p == ST_STOP ) {
478                 BUG ();
479             }
480         } while ( level );
481         n = p + 1 - head;
482
483         newlist = gcry_xmalloc ( sizeof *newlist + n );
484         d = newlist->d;
485         memcpy ( d, head, n ); d += n;
486         *d++ = ST_STOP;
487     }
488     else
489         newlist = NULL;
490
491     return normalize (newlist);
492 }
493
494 gcry_sexp_t
495 gcry_sexp_car( const gcry_sexp_t list )
496 {
497     return gcry_sexp_nth ( list, 0 );
498 }
499
500 /****************
501  * Get data from the car.  The returned value is valid as long as the list
502  * is not modified.
503  */
504 const char *
505 gcry_sexp_nth_data( const gcry_sexp_t list, int number, size_t *datalen )
506 {
507     const byte *p;
508     DATALEN n;
509     int level = 0;
510
511     *datalen = 0;
512     if ( !list ) {
513         return NULL;
514     }
515     p = list->d;
516     if ( *p == ST_OPEN )
517         p++;         /* yep, a list */
518     else if (number )
519         return NULL; /* not a list but an n > 0 element requested */
520
521     /* skip n elements */
522     while ( number > 0 ) {
523         if ( *p == ST_DATA ) {
524             memcpy ( &n, ++p, sizeof n );
525             p += sizeof n + n;
526             p--;
527             if ( !level )
528                 number--;
529         }
530         else if ( *p == ST_OPEN ) {
531             level++;
532         }
533         else if ( *p == ST_CLOSE ) {
534             level--;
535             if ( !level )
536                 number--;
537         }
538         else if ( *p == ST_STOP ) {
539             return NULL;
540         }
541         p++;
542     }
543
544
545     if ( *p == ST_DATA ) {
546         memcpy ( &n, ++p, sizeof n );
547         *datalen = n;
548         return p + sizeof n;
549     }
550
551     return NULL;
552 }
553
554 /****************
555  * Get a MPI from the car
556  */
557 gcry_mpi_t
558 gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt )
559 {
560     const byte *p;
561     DATALEN n;
562     int level = 0;
563
564     if ( !list )
565         return NULL;
566     if ( !mpifmt )
567         mpifmt = GCRYMPI_FMT_STD;
568
569     p = list->d;
570     if ( *p == ST_OPEN )
571         p++;         /* yep, a list */
572     else if (number )
573         return NULL; /* not a list but an n > 0 element requested */
574
575     /* skip n elements */
576     while ( number > 0 ) {
577         if ( *p == ST_DATA ) {
578             memcpy ( &n, ++p, sizeof n );
579             p += sizeof n + n;
580             p--;
581             if ( !level )
582                 number--;
583         }
584         else if ( *p == ST_OPEN ) {
585             level++;
586         }
587         else if ( *p == ST_CLOSE ) {
588             level--;
589             if ( !level )
590                 number--;
591         }
592         else if ( *p == ST_STOP ) {
593             return NULL;
594         }
595         p++;
596     }
597
598     if ( *p == ST_DATA ) {
599         gcry_mpi_t a;
600         size_t nbytes;
601
602         memcpy ( &n, ++p, sizeof n );
603         p += sizeof n;
604         nbytes = n;
605         if( !gcry_mpi_scan( &a, mpifmt, p, n, &nbytes ) )
606             return a;
607     }
608
609     return NULL;
610 }
611
612
613 /****************
614  * Get the CDR
615  */
616 gcry_sexp_t
617 gcry_sexp_cdr( const gcry_sexp_t list )
618 {
619     const byte *p;
620     const byte *head;
621     DATALEN n;
622     gcry_sexp_t newlist;
623     byte *d;
624     int level = 0;
625     int skip = 1;
626
627     if ( !list || list->d[0] != ST_OPEN )
628         return NULL;
629     p = list->d;
630
631     while ( skip > 0 ) {
632         p++;
633         if ( *p == ST_DATA ) {
634             memcpy ( &n, ++p, sizeof n );
635             p += sizeof n + n;
636             p--;
637             if ( !level )
638                 skip--;
639         }
640         else if ( *p == ST_OPEN ) {
641             level++;
642         }
643         else if ( *p == ST_CLOSE ) {
644             level--;
645             if ( !level )
646                 skip--;
647         }
648         else if ( *p == ST_STOP ) {
649             return NULL;
650         }
651     }
652     p++;
653
654     head = p;
655     level = 0;
656     do {
657         if ( *p == ST_DATA ) {
658             memcpy ( &n, ++p, sizeof n );
659             p += sizeof n + n;
660             p--;
661         }
662         else if ( *p == ST_OPEN ) {
663             level++;
664         }
665         else if ( *p == ST_CLOSE ) {
666             level--;
667         }
668         else if ( *p == ST_STOP ) {
669             return NULL;
670         }
671         p++;
672     } while ( level );
673     n = p - head;
674
675     newlist = gcry_xmalloc ( sizeof *newlist + n + 2 );
676     d = newlist->d;
677     *d++ = ST_OPEN;
678     memcpy ( d, head, n ); d += n;
679     *d++ = ST_CLOSE;
680     *d++ = ST_STOP;
681
682     return normalize (newlist);
683 }
684
685 gcry_sexp_t
686 gcry_sexp_cadr ( const gcry_sexp_t list )
687 {
688     gcry_sexp_t a, b;
689
690     a = gcry_sexp_cdr ( list );
691     b = gcry_sexp_car ( a );
692     gcry_sexp_release ( a );
693     return b;
694 }
695
696
697
698 static int
699 hextobyte( const byte *s )
700 {
701     int c=0;
702
703     if( *s >= '0' && *s <= '9' )
704         c = 16 * (*s - '0');
705     else if( *s >= 'A' && *s <= 'F' )
706         c = 16 * (10 + *s - 'A');
707     else if( *s >= 'a' && *s <= 'f' ) {
708         c = 16 * (10 + *s - 'a');
709     }
710     s++;
711     if( *s >= '0' && *s <= '9' )
712         c += *s - '0';
713     else if( *s >= 'A' && *s <= 'F' )
714         c += 10 + *s - 'A';
715     else if( *s >= 'a' && *s <= 'f' ) {
716         c += 10 + *s - 'a';
717     }
718     return c;
719 }
720
721 struct make_space_ctx {
722     gcry_sexp_t sexp;
723     size_t allocated;
724     byte *pos;
725 };
726
727 static void
728 make_space ( struct make_space_ctx *c, size_t n )
729 {
730     size_t used = c->pos - c->sexp->d;
731
732     if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) {
733         gcry_sexp_t newsexp;
734         byte *newhead;
735
736         c->allocated += 2*(n+sizeof(DATALEN)+1);
737         newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 );
738         newhead = newsexp->d;
739         c->pos = newhead + used;
740         c->sexp = newsexp;
741     }
742 }
743
744
745 /* Unquote STRING of LENGTH and store it into BUF.  The surrounding
746    quotes are must already be removed from STRING.  We assume that the
747    quoted string is syntacillay correct.  */
748 static size_t
749 unquote_string (const unsigned char *string, size_t length, unsigned char *buf)
750 {
751   int esc = 0;
752   const unsigned char *s = string;
753   unsigned char *d = buf;
754   size_t n = length;
755
756   for (; n; n--, s++)
757     {
758       if (esc)
759         {
760           switch (*s)
761             {
762             case 'b':  *d++ = '\b'; break;
763             case 't':  *d++ = '\t'; break;
764             case 'v':  *d++ = '\v'; break;
765             case 'n':  *d++ = '\n'; break;
766             case 'f':  *d++ = '\f'; break;
767             case 'r':  *d++ = '\r'; break;
768             case '"':  *d++ = '\"'; break;
769             case '\'': *d++ = '\''; break;
770             case '\\': *d++ = '\\'; break;
771
772             case '\r':  /* ignore CR[,LF] */
773               if (n>1 && s[1] == '\n')
774                 {
775                   s++; n--;
776                 }
777               esc = 0;
778               break;
779               
780             case '\n':  /* ignore LF[,CR] */
781               if (n>1 && s[1] == '\r')
782                 {
783                   s++; n--;
784                 }
785               break;
786
787             case 'x': /* hex value */
788               if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
789                 {
790                   s++; n--;
791                   *d++ = xtoi_2 (s);
792                   s++; n--;
793                 }
794               break;
795
796             default:
797               if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
798                 {
799                   *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
800                   s += 2;
801                   n -= 2;
802                 }
803               break;
804             }
805           esc = 0;
806         }
807       else if( *s == '\\' )
808         esc = 1;
809       else
810         *d++ = *s;
811     } 
812
813   return d - buf;
814 }
815
816 /****************
817  * Scan the provided buffer and return the S expression in our internal
818  * format.  Returns a newly allocated expression.  If erroff is not NULL and
819  * a parsing error has occured, the offset into buffer will be returned.
820  * If ARGFLAG is true, the function supports some printf like
821  * expressions.
822  *  These are:
823  *      %m - MPI
824  *      %s - string (no autoswitch to secure allocation)
825  *      %d - integer stored as string (no autoswitch to secure allocation)
826  *  all other format elements are currently not defined and return an error.
827  *  this includes the "%%" sequence becauce the percent sign is not an
828  *  allowed character.
829  * FIXME: We should find a way to store the secure-MPIS not in the string
830  * but as reference to somewhere - this can help us to save huge amounts
831  * of secure memory.  The problem is, that if only one element is secure, all
832  * other elements are automagicaly copied to secure meory too, so the most
833  * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
834  * regardless whether it is needed or not.
835  */
836 static gcry_error_t
837 sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
838             const char *buffer, size_t length, int argflag,
839             va_list arg_ptr, void **arg_list)
840 {
841   static const char tokenchars[] = "\
842 abcdefghijklmnopqrstuvwxyz\
843 ABCDEFGHIJKLMNOPQRSTUVWXYZ\
844 0123456789-./_:*+=";
845   const char *p;
846   size_t n;
847   const char *digptr = NULL;
848   const char *quoted = NULL;
849   const char *tokenp = NULL;
850   const char *hexfmt = NULL;
851   const char *base64 = NULL;
852   const char *disphint = NULL;
853   const char *percent = NULL;
854   int hexcount = 0;
855   int quoted_esc = 0;
856   int datalen = 0;
857   size_t dummy_erroff;
858   struct make_space_ctx c;
859   int arg_counter = 0;
860
861   if (! erroff)
862     erroff = &dummy_erroff;
863
864   /* Depending on wether ARG_LIST is non-zero or not, this macro gives
865      us the next argument, either from the variable argument list as
866      specified by ARG_PTR or from the arugment array ARG_LIST.  */
867 #define ARG_NEXT(storage, type)                          \
868   do                                                     \
869     {                                                    \
870       if (! arg_list)                                    \
871         storage = va_arg (arg_ptr, type);                \
872       else                                               \
873         storage = *((type *) (arg_list[arg_counter++])); \
874     }                                                    \
875   while (0)
876
877   /* FIXME: replace all the returns by a jump to the leave label
878    * and invent better error codes. Make sure that everything is cleaned up*/
879 #define MAKE_SPACE(n)  do { make_space ( &c, (n) ); } while (0)
880 #define STORE_LEN(p,n) do {                                                \
881                             DATALEN ashort = (n);                          \
882                             memcpy ( (p), &ashort, sizeof(ashort) );       \
883                             (p) += sizeof (ashort);                        \
884                         } while (0)
885
886   /* We assume that the internal representation takes less memory
887    * than the provided one.  However, we add space for one extra datalen
888    * so that the code which does the ST_CLOSE can use MAKE_SPACE */
889   c.allocated = length + sizeof(DATALEN);
890   c.sexp = gcry_xmalloc ( sizeof *c.sexp + c.allocated - 1 );
891   c.pos = c.sexp->d;
892
893   for(p=buffer,n=length; n; p++, n-- ) {
894     if( tokenp && !hexfmt ) {
895       if( strchr( tokenchars, *p ) )
896         continue;
897       datalen = p - tokenp;
898       MAKE_SPACE ( datalen );
899       *c.pos++ = ST_DATA;
900       STORE_LEN ( c.pos, datalen );
901       memcpy ( c.pos, tokenp, datalen );
902       c.pos += datalen;
903       tokenp = NULL;
904     }
905     if( quoted ) {
906       if( quoted_esc ) {
907         switch( *p ) {
908         case 'b': case 't': case 'v': case 'n': case 'f':
909         case 'r': case '"': case '\'': case '\\':
910           quoted_esc = 0;
911           break;
912         case '0': case '1': case '2': case '3': case '4':
913         case '5': case '6': case '7':
914           if( !(n > 2 && p[1] >= '0' && p[1] <= '7'
915                 && p[2] >= '0' && p[2] <= '7') ) {
916             *erroff = p - buffer;
917             /* Invalid octal value.  */
918             return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
919           }
920           p += 2; n -= 2;
921           quoted_esc = 0;
922           break;
923         case 'x':
924           if( !(n > 2 && isxdigit(p[1]) && isxdigit(p[2]) ) ) {
925             *erroff = p - buffer;
926             /* Invalid hex value.  */
927             return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
928           }
929           p += 2; n -= 2;
930           quoted_esc = 0;
931           break;
932         case '\r':  /* ignore CR[,LF] */
933           if( n && p[1] == '\n' ) {
934             p++; n--;
935           }
936           quoted_esc = 0;
937           break;
938         case '\n':  /* ignore LF[,CR] */
939           if( n && p[1] == '\r' ) {
940             p++; n--;
941           }
942           quoted_esc = 0;
943           break;
944         default:
945           *erroff = p - buffer;
946           /* Invalid quoted string escape.  */
947           return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
948         }
949       }
950       else if( *p == '\\' )
951         quoted_esc = 1;
952       else if( *p == '\"' ) {
953         /* keep it easy - we know that the unquoted string will
954            never be larger */
955         char *save;
956         size_t len;
957                 
958         quoted++; /* skip leading quote */
959         MAKE_SPACE (p - quoted);
960         *c.pos++ = ST_DATA;
961         save = c.pos;
962         STORE_LEN (c.pos, 0); /* will be fixed up later */
963         len = unquote_string (quoted, p - quoted, c.pos);
964         c.pos += len;
965         STORE_LEN (save, len);
966         quoted = NULL;
967       }
968     }
969     else if( hexfmt ) {
970       if( isxdigit( *p ) )
971         hexcount++;
972       else if( *p == '#' ) {
973         if( (hexcount & 1) ) {
974           *erroff = p - buffer;
975           return gcry_error (GPG_ERR_SEXP_ODD_HEX_NUMBERS);
976         }
977
978         datalen = hexcount/2;
979         MAKE_SPACE (datalen);
980         *c.pos++ = ST_DATA;
981         STORE_LEN (c.pos, datalen);
982         for( hexfmt++; hexfmt < p; hexfmt++ ) {
983           if( isspace( *hexfmt ) )
984             continue;
985           *c.pos++ = hextobyte( hexfmt );
986           hexfmt++;
987         }
988         hexfmt = NULL;
989       }
990       else if( !isspace( *p ) ) {
991         *erroff = p - buffer;
992         return gcry_error (GPG_ERR_SEXP_BAD_HEX_CHAR);
993       }
994     }
995     else if( base64 ) {
996       if( *p == '|' )
997         base64 = NULL;
998     }
999     else if( digptr ) {
1000       if( isdigit(*p) )
1001         ;
1002       else if( *p == ':' ) {
1003         datalen = atoi( digptr ); /* fixme: check for overflow */
1004         digptr = NULL;
1005         if( datalen > n-1 ) {
1006           *erroff = p - buffer;
1007           /* Buffer too short.  */
1008           return gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1009         }
1010         /* make a new list entry */
1011         MAKE_SPACE (datalen);
1012         *c.pos++ = ST_DATA;
1013         STORE_LEN (c.pos, datalen);
1014         memcpy (c.pos, p+1, datalen );
1015         c.pos += datalen;
1016         n -= datalen;
1017         p += datalen;
1018       }
1019       else if( *p == '\"' ) {
1020         digptr = NULL; /* we ignore the optional length */
1021         quoted = p;
1022         quoted_esc = 0;
1023       }
1024       else if( *p == '#' ) {
1025         digptr = NULL; /* we ignore the optional length */
1026         hexfmt = p;
1027         hexcount = 0;
1028       }
1029       else if( *p == '|' ) {
1030         digptr = NULL; /* we ignore the optional length */
1031         base64 = p;
1032       }
1033       else {
1034         *erroff = p - buffer;
1035         return gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1036       }
1037     }
1038     else if ( percent ) {
1039       if ( *p == 'm' ) { /* insert an MPI */
1040         gcry_mpi_t m;
1041         size_t nm = 0;
1042
1043         ARG_NEXT (m, gcry_mpi_t);
1044
1045         if ( gcry_mpi_print( GCRYMPI_FMT_STD, NULL, 0, &nm, m ) )
1046           BUG ();
1047
1048         MAKE_SPACE (nm);
1049         if ( !gcry_is_secure ( c.sexp->d )
1050              &&  gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE ) ) {
1051           /* we have to switch to secure allocation */
1052           gcry_sexp_t newsexp;
1053           byte *newhead;
1054
1055           newsexp = gcry_xmalloc_secure ( sizeof *newsexp
1056                                           + c.allocated - 1 );
1057           newhead = newsexp->d;
1058           memcpy ( newhead, c.sexp->d, (c.pos - c.sexp->d) );
1059           c.pos = newhead + ( c.pos - c.sexp->d );
1060           gcry_free ( c.sexp );
1061           c.sexp = newsexp;
1062         }
1063
1064         *c.pos++ = ST_DATA;
1065         STORE_LEN (c.pos, nm);
1066         if ( gcry_mpi_print( GCRYMPI_FMT_STD, c.pos, nm, &nm, m ) )
1067           BUG ();
1068         c.pos += nm;
1069       }
1070       else if ( *p == 's' ) { /* insert an string */
1071         const char *astr;
1072         size_t alen;
1073
1074         ARG_NEXT (astr, const char *);
1075         alen = strlen (astr);
1076
1077         MAKE_SPACE (alen);
1078         *c.pos++ = ST_DATA;
1079         STORE_LEN (c.pos, alen);
1080         memcpy ( c.pos, astr, alen );
1081         c.pos += alen;
1082       }
1083       else if ( *p == 'd' ) { /* insert an integer as string */
1084         int aint;
1085         size_t alen;
1086         char buf[20];
1087
1088         ARG_NEXT (aint, int);
1089         sprintf ( buf, "%d", aint );
1090         alen = strlen ( buf );
1091         MAKE_SPACE (alen);
1092         *c.pos++ = ST_DATA;
1093         STORE_LEN (c.pos, alen);
1094         memcpy ( c.pos, buf, alen );
1095         c.pos += alen;
1096       }
1097       else {
1098         *erroff = p - buffer;
1099         /* Invalid format specifier.  */
1100         return gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1101       }
1102       percent = NULL;
1103     }
1104     else if( *p == '(' ) {
1105       if( disphint ) {
1106         *erroff = p - buffer;
1107         /* Open display hint.  */
1108         return gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1109       }
1110       MAKE_SPACE (0);
1111       *c.pos++ = ST_OPEN;
1112     }
1113     else if( *p == ')' ) { /* walk up */
1114       if( disphint ) {
1115         *erroff = p - buffer;
1116         /* Open display hint.  */
1117         return gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1118       }
1119       MAKE_SPACE (0);
1120       *c.pos++ = ST_CLOSE;
1121     }
1122     else if( *p == '\"' ) {
1123       quoted = p;
1124       quoted_esc = 0;
1125     }
1126     else if( *p == '#' ) {
1127       hexfmt = p;
1128       hexcount = 0;
1129     }
1130     else if( *p == '|' )
1131       base64 = p;
1132     else if( *p == '[' ) {
1133       if( disphint ) {
1134         *erroff = p - buffer;
1135         /* Open display hint.  */
1136         return gcry_error (GPG_ERR_SEXP_NESTED_DH);
1137       }
1138       disphint = p;
1139     }
1140     else if( *p == ']' ) {
1141       if( !disphint ) {
1142         *erroff = p - buffer;
1143         /* Open display hint.  */
1144         return gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1145       }
1146       disphint = NULL;
1147     }
1148     else if( isdigit(*p) ) {
1149       if( *p == '0' ) { /* a length may not begin with zero */
1150         *erroff = p - buffer;
1151         return gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
1152       }
1153       digptr = p;
1154     }
1155     else if( strchr( tokenchars, *p ) )
1156       tokenp = p;
1157     else if( isspace(*p) )
1158       ;
1159     else if( *p == '{' ) {
1160       /* fixme: handle rescanning:
1161        * we can do this by saving our current state
1162        * and start over at p+1 -- Hmmm. At this point here
1163        * we are in a well defined state, so we don't need to save
1164        * it.  Great.
1165        */
1166       *erroff = p - buffer;
1167       return gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1168     }
1169     else if( strchr( "&\\", *p ) ) { /*reserved punctuation*/
1170       *erroff = p - buffer;
1171       return gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1172     }
1173     else if( argflag && *p == '%' ) {
1174       percent = p;
1175     }
1176     else { /* bad or unavailable*/
1177       *erroff = p - buffer;
1178       return gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
1179     }
1180
1181   }
1182   MAKE_SPACE (0);
1183   *c.pos++ = ST_STOP;
1184
1185   *retsexp = normalize ( c.sexp );
1186   return gcry_error (GPG_ERR_NO_ERROR);
1187 #undef MAKE_SPACE
1188 #undef STORE_LEN
1189 }
1190
1191 gcry_error_t
1192 gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
1193 {
1194   gcry_error_t rc;
1195   va_list arg_ptr;
1196   
1197   va_start (arg_ptr, format);
1198   rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
1199                    arg_ptr, NULL);
1200   va_end (arg_ptr);
1201   
1202   return rc;
1203 }
1204
1205 /* Like gcry_sexp_build, but uses an array instead of variable
1206    function arguments.  */
1207 gcry_error_t
1208 gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1209                        const char *format, void **arg_list)
1210 {
1211   /* We don't need the va_list because it is controlled by the
1212      following flag, however we have to pass it but can't initialize
1213      it as there is no portable way to do so.  volatile is needed to
1214      suppress the compiler warning */
1215   volatile va_list dummy_arg_ptr;
1216   
1217   gcry_error_t rc;
1218
1219   rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
1220                    dummy_arg_ptr, arg_list);
1221
1222   return rc;
1223 }
1224
1225 gcry_error_t
1226 gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1227                  const char *buffer, size_t length)
1228 {
1229   /* We don't need the va_list because it is controlled by the
1230      following flag, however we have to pass it but can't initialize
1231      it as there is no portable way to do so.  volatile is needed to
1232      suppress the compiler warning */
1233   volatile va_list dummy_arg_ptr;
1234
1235   return sexp_sscan (retsexp, erroff, buffer, length, 0,
1236                      dummy_arg_ptr, NULL);
1237 }
1238
1239 \f
1240 /* Figure out a suitable encoding for BUFFER of LENGTH.
1241    Returns: 0 = Binary
1242             1 = String possible
1243             2 = Token possible
1244 */
1245 static int
1246 suitable_encoding (const unsigned char *buffer, size_t length)
1247 {
1248   const unsigned char *s;
1249   int maybe_token = 1;
1250
1251   if (!length)
1252     return 1;
1253   
1254   for (s=buffer; length; s++, length--)
1255     {
1256       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1257            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1258         return 0; /*binary*/
1259       if ( maybe_token
1260            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1261         maybe_token = 0;
1262     }
1263   s = buffer;
1264   if ( maybe_token && !digitp (s) )
1265     return 2;
1266   return 1;
1267 }
1268
1269
1270 static int
1271 convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
1272 {
1273   int i;
1274
1275   if (dest)
1276     {
1277       *dest++ = '#';
1278       for (i=0; i < len; i++, dest += 2 )
1279         sprintf (dest, "%02X", src[i]);
1280       *dest++ = '#';
1281     }
1282   return len*2+2;
1283 }
1284
1285 static int
1286 convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
1287 {
1288   if (dest)
1289     {
1290       unsigned char *p = dest;
1291       *p++ = '\"';
1292       for (; len; len--, s++ )
1293         {
1294           switch (*s)
1295             {
1296             case '\b': *p++ = '\\'; *p++ = 'b';  break;
1297             case '\t': *p++ = '\\'; *p++ = 't';  break;
1298             case '\v': *p++ = '\\'; *p++ = 'v';  break;
1299             case '\n': *p++ = '\\'; *p++ = 'n';  break;
1300             case '\f': *p++ = '\\'; *p++ = 'f';  break;
1301             case '\r': *p++ = '\\'; *p++ = 'r';  break;
1302             case '\"': *p++ = '\\'; *p++ = '\"';  break;
1303             case '\'': *p++ = '\\'; *p++ = '\'';  break;
1304             case '\\': *p++ = '\\'; *p++ = '\\';  break;
1305             default: 
1306               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1307                 {
1308                   sprintf (p, "\\x%02x", *s); 
1309                   p += 4;
1310                 }
1311               else
1312                 *p++ = *s;
1313             }
1314         }
1315       *p++ = '\"';
1316       return p - dest;
1317     }
1318   else
1319     {
1320       int count = 2;
1321       for (; len; len--, s++ )
1322         {
1323           switch (*s)
1324             {
1325             case '\b': 
1326             case '\t': 
1327             case '\v': 
1328             case '\n': 
1329             case '\f': 
1330             case '\r': 
1331             case '\"':
1332             case '\'':
1333             case '\\': count += 2; break;
1334             default: 
1335               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1336                 count += 4;
1337               else
1338                 count++;
1339             }
1340         }
1341       return count;
1342     }
1343 }
1344
1345
1346
1347 static int
1348 convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
1349 {
1350   if (dest)
1351     memcpy (dest, src, len);
1352   return len;
1353 }
1354
1355
1356 /****************
1357  * Print SEXP to buffer using the MODE.  Returns the length of the
1358  * SEXP in buffer or 0 if the buffer is too short (We have at least an
1359  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
1360  * the required length is returned.
1361  */
1362 size_t
1363 gcry_sexp_sprint( const gcry_sexp_t list, int mode,
1364                                         char *buffer, size_t maxlength )
1365 {
1366   static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1367   const byte *s;
1368   char *d;
1369   DATALEN n;
1370   char numbuf[20];
1371   size_t len = 0;
1372   int i, indent = 0;
1373   
1374   s = list? list->d : empty;
1375   d = buffer;
1376   while ( *s != ST_STOP )
1377     {
1378       switch ( *s )
1379         {
1380         case ST_OPEN:
1381           s++;
1382           if ( mode != GCRYSEXP_FMT_CANON )
1383             {
1384               if (indent)
1385                 len++; 
1386               len += indent;
1387             }
1388           len++;
1389           if ( buffer ) 
1390             {
1391               if ( len >= maxlength )
1392                 return 0;
1393               if ( mode != GCRYSEXP_FMT_CANON )
1394                 {
1395                   if (indent)
1396                     *d++ = '\n'; 
1397                   for (i=0; i < indent; i++)
1398                     *d++ = ' ';
1399                 }
1400               *d++ = '(';
1401             }
1402           indent++;
1403           break;
1404         case ST_CLOSE:
1405           s++;
1406           len++;
1407           if ( buffer ) 
1408             {
1409               if ( len >= maxlength )
1410                 return 0;
1411               *d++ = ')';
1412             }
1413           indent--;
1414           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1415             {
1416               len++;
1417               len += indent;
1418               if (buffer)
1419                 {
1420                   if (len >= maxlength)
1421                     return 0;
1422                   *d++ = '\n';
1423                   for (i=0; i < indent; i++)
1424                     *d++ = ' ';
1425                 }
1426             }
1427           break;
1428         case ST_DATA:
1429           s++;
1430           memcpy ( &n, s, sizeof n ); s += sizeof n;
1431           if (mode == GCRYSEXP_FMT_ADVANCED)
1432             {
1433               int type;
1434               size_t nn;
1435
1436               switch ( (type=suitable_encoding (s, n)))
1437                 {
1438                 case 1: nn = convert_to_string (s, n, NULL); break;
1439                 case 2: nn = convert_to_token (s, n, NULL); break;
1440                 default: nn = convert_to_hex (s, n, NULL); break;
1441                 }
1442               len += nn;
1443               if (buffer)
1444                 {
1445                   if (len >= maxlength)
1446                     return 0;
1447                   switch (type)
1448                     {
1449                     case 1: convert_to_string (s, n, d); break;
1450                     case 2: convert_to_token (s, n, d); break;
1451                     default: convert_to_hex (s, n, d); break;
1452                     }
1453                   d += nn;
1454                 }
1455               if (s[n] != ST_CLOSE)
1456                 {
1457                   len++;
1458                   if (buffer)
1459                     {
1460                       if (len >= maxlength)
1461                         return 0;
1462                       *d++ = ' ';
1463                     }
1464                 }
1465             }
1466           else
1467             {
1468               sprintf (numbuf, "%u:", (unsigned int)n );
1469               len += strlen (numbuf) + n;
1470               if ( buffer ) 
1471                 {
1472                   if ( len >= maxlength )
1473                     return 0;
1474                   d = stpcpy ( d, numbuf );
1475                   memcpy ( d, s, n ); d += n;
1476                 }
1477             }
1478           s += n;
1479           break;
1480         default:
1481           BUG ();
1482         }
1483     }
1484   if ( mode != GCRYSEXP_FMT_CANON )
1485     {
1486       len++;
1487       if (buffer)
1488         {
1489           if ( len >= maxlength )
1490             return 0;
1491           *d++ = '\n'; 
1492         }
1493     }
1494   if (buffer) 
1495     {
1496       if ( len >= maxlength )
1497         return 0;
1498       *d++ = 0; /* for convenience we make a C string */
1499     }
1500   else
1501     len++; /* we need one byte more for this */
1502
1503   return len;
1504 }
1505
1506
1507 /* Scan a cannocial encoded buffer with implicit length values and
1508    return the actual length this S-expression uses.  For a valid S-Exp
1509    it should never return 0.  If LENGTH is not zero, the maximum
1510    length to scan is given - this can be used for syntax checks of
1511    data passed from outside. errorcode and erroff may both be passed as
1512    NULL.  */
1513 size_t
1514 gcry_sexp_canon_len (const unsigned char *buffer, size_t length, 
1515                      size_t *erroff, gcry_error_t *errcode)
1516 {
1517   const unsigned char *p;
1518   const char *disphint=NULL;
1519   unsigned int datalen = 0;
1520   size_t dummy_erroff;
1521   gcry_error_t dummy_errcode;
1522   size_t count = 0;
1523   int level = 0;
1524
1525   if (!erroff)
1526     erroff = &dummy_erroff;
1527   if (!errcode)
1528     errcode = &dummy_errcode;
1529
1530   *errcode = gcry_error (GPG_ERR_NO_ERROR);
1531   *erroff = 0;
1532   if (!buffer)
1533     return 0;
1534   if (*buffer != '(')
1535     {
1536       *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL);
1537       return 0;
1538     }
1539
1540   for (p=buffer; ; p++, count++ )
1541     {
1542       if (length && count >= length)
1543         {
1544           *erroff = count;
1545           *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1546           return 0;
1547         }
1548       
1549       if (datalen)
1550         {
1551           if (*p == ':')
1552             {
1553               if (length && (count+datalen) >= length)
1554                 {
1555                   *erroff = count;
1556                   *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1557                   return 0;
1558                 }
1559               count += datalen;
1560               p += datalen;
1561               datalen = 0;
1562             }
1563           else if (digitp(p))
1564             datalen = datalen*10 + atoi_1(p);
1565           else 
1566             {
1567               *erroff = count;
1568               *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1569               return 0;
1570             }
1571         }
1572       else if (*p == '(')
1573         {
1574           if (disphint)
1575             {
1576               *erroff = count;
1577               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1578               return 0;
1579             }
1580           level++;
1581         }
1582       else if (*p == ')')
1583         { /* walk up */
1584           if (!level)
1585             {
1586               *erroff = count;
1587               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
1588               return 0;
1589             }
1590           if (disphint)
1591             {
1592               *erroff = count;
1593               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1594               return 0;
1595             }
1596           if (!--level)
1597             return ++count; /* ready */
1598         }
1599       else if (*p == '[')
1600         {
1601           if (disphint) 
1602             {
1603               *erroff = count;
1604               *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH);
1605               return 0;
1606             }
1607           disphint = p;
1608         }
1609       else if (*p == ']')
1610         {
1611           if( !disphint ) 
1612             {
1613               *erroff = count;
1614               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1615               return 0;
1616             }
1617           disphint = NULL;
1618         }
1619       else if (digitp (p) )
1620         {
1621           if (*p == '0')
1622             { 
1623               *erroff = count;
1624               *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
1625               return 0;
1626             }
1627           datalen = atoi_1 (p);
1628         }
1629       else if (*p == '&' || *p == '\\')
1630         {
1631           *erroff = count;
1632           *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1633           return 0;
1634         }
1635       else
1636         { 
1637           *erroff = count;
1638           *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
1639           return 0;
1640         }
1641     }
1642 }