* sexp.c (sexp_sscan): Check that parenthesis are matching.
[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   int level = 0;
861
862   if (! erroff)
863     erroff = &dummy_erroff;
864
865   /* Depending on wether ARG_LIST is non-zero or not, this macro gives
866      us the next argument, either from the variable argument list as
867      specified by ARG_PTR or from the arugment array ARG_LIST.  */
868 #define ARG_NEXT(storage, type)                          \
869   do                                                     \
870     {                                                    \
871       if (! arg_list)                                    \
872         storage = va_arg (arg_ptr, type);                \
873       else                                               \
874         storage = *((type *) (arg_list[arg_counter++])); \
875     }                                                    \
876   while (0)
877
878   /* FIXME: replace all the returns by a jump to the leave label and
879    * invent better error codes. FIXME: Make sure that everything is
880    * cleaned up. */
881 #define MAKE_SPACE(n)  do { make_space ( &c, (n) ); } while (0)
882 #define STORE_LEN(p,n) do {                                                \
883                             DATALEN ashort = (n);                          \
884                             memcpy ( (p), &ashort, sizeof(ashort) );       \
885                             (p) += sizeof (ashort);                        \
886                         } while (0)
887
888   /* We assume that the internal representation takes less memory
889    * than the provided one.  However, we add space for one extra datalen
890    * so that the code which does the ST_CLOSE can use MAKE_SPACE */
891   c.allocated = length + sizeof(DATALEN);
892   c.sexp = gcry_xmalloc ( sizeof *c.sexp + c.allocated - 1 );
893   c.pos = c.sexp->d;
894
895   for(p=buffer,n=length; n; p++, n-- ) {
896     if( tokenp && !hexfmt ) {
897       if( strchr( tokenchars, *p ) )
898         continue;
899       datalen = p - tokenp;
900       MAKE_SPACE ( datalen );
901       *c.pos++ = ST_DATA;
902       STORE_LEN ( c.pos, datalen );
903       memcpy ( c.pos, tokenp, datalen );
904       c.pos += datalen;
905       tokenp = NULL;
906     }
907     if( quoted ) {
908       if( quoted_esc ) {
909         switch( *p ) {
910         case 'b': case 't': case 'v': case 'n': case 'f':
911         case 'r': case '"': case '\'': case '\\':
912           quoted_esc = 0;
913           break;
914         case '0': case '1': case '2': case '3': case '4':
915         case '5': case '6': case '7':
916           if( !(n > 2 && p[1] >= '0' && p[1] <= '7'
917                 && p[2] >= '0' && p[2] <= '7') ) {
918             *erroff = p - buffer;
919             /* Invalid octal value.  */
920             return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
921           }
922           p += 2; n -= 2;
923           quoted_esc = 0;
924           break;
925         case 'x':
926           if( !(n > 2 && isxdigit(p[1]) && isxdigit(p[2]) ) ) {
927             *erroff = p - buffer;
928             /* Invalid hex value.  */
929             return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
930           }
931           p += 2; n -= 2;
932           quoted_esc = 0;
933           break;
934         case '\r':  /* ignore CR[,LF] */
935           if( n && p[1] == '\n' ) {
936             p++; n--;
937           }
938           quoted_esc = 0;
939           break;
940         case '\n':  /* ignore LF[,CR] */
941           if( n && p[1] == '\r' ) {
942             p++; n--;
943           }
944           quoted_esc = 0;
945           break;
946         default:
947           *erroff = p - buffer;
948           /* Invalid quoted string escape.  */
949           return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
950         }
951       }
952       else if( *p == '\\' )
953         quoted_esc = 1;
954       else if( *p == '\"' ) {
955         /* keep it easy - we know that the unquoted string will
956            never be larger */
957         char *save;
958         size_t len;
959                 
960         quoted++; /* skip leading quote */
961         MAKE_SPACE (p - quoted);
962         *c.pos++ = ST_DATA;
963         save = c.pos;
964         STORE_LEN (c.pos, 0); /* will be fixed up later */
965         len = unquote_string (quoted, p - quoted, c.pos);
966         c.pos += len;
967         STORE_LEN (save, len);
968         quoted = NULL;
969       }
970     }
971     else if( hexfmt ) {
972       if( isxdigit( *p ) )
973         hexcount++;
974       else if( *p == '#' ) {
975         if( (hexcount & 1) ) {
976           *erroff = p - buffer;
977           return gcry_error (GPG_ERR_SEXP_ODD_HEX_NUMBERS);
978         }
979
980         datalen = hexcount/2;
981         MAKE_SPACE (datalen);
982         *c.pos++ = ST_DATA;
983         STORE_LEN (c.pos, datalen);
984         for( hexfmt++; hexfmt < p; hexfmt++ ) {
985           if( isspace( *hexfmt ) )
986             continue;
987           *c.pos++ = hextobyte( hexfmt );
988           hexfmt++;
989         }
990         hexfmt = NULL;
991       }
992       else if( !isspace( *p ) ) {
993         *erroff = p - buffer;
994         return gcry_error (GPG_ERR_SEXP_BAD_HEX_CHAR);
995       }
996     }
997     else if( base64 ) {
998       if( *p == '|' )
999         base64 = NULL;
1000     }
1001     else if( digptr ) {
1002       if( isdigit(*p) )
1003         ;
1004       else if( *p == ':' ) {
1005         datalen = atoi( digptr ); /* fixme: check for overflow */
1006         digptr = NULL;
1007         if( datalen > n-1 ) {
1008           *erroff = p - buffer;
1009           /* Buffer too short.  */
1010           return gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1011         }
1012         /* make a new list entry */
1013         MAKE_SPACE (datalen);
1014         *c.pos++ = ST_DATA;
1015         STORE_LEN (c.pos, datalen);
1016         memcpy (c.pos, p+1, datalen );
1017         c.pos += datalen;
1018         n -= datalen;
1019         p += datalen;
1020       }
1021       else if( *p == '\"' ) {
1022         digptr = NULL; /* we ignore the optional length */
1023         quoted = p;
1024         quoted_esc = 0;
1025       }
1026       else if( *p == '#' ) {
1027         digptr = NULL; /* we ignore the optional length */
1028         hexfmt = p;
1029         hexcount = 0;
1030       }
1031       else if( *p == '|' ) {
1032         digptr = NULL; /* we ignore the optional length */
1033         base64 = p;
1034       }
1035       else {
1036         *erroff = p - buffer;
1037         return gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1038       }
1039     }
1040     else if ( percent ) {
1041       if ( *p == 'm' ) { /* insert an MPI */
1042         gcry_mpi_t m;
1043         size_t nm = 0;
1044
1045         ARG_NEXT (m, gcry_mpi_t);
1046
1047         if ( gcry_mpi_print( GCRYMPI_FMT_STD, NULL, 0, &nm, m ) )
1048           BUG ();
1049
1050         MAKE_SPACE (nm);
1051         if ( !gcry_is_secure ( c.sexp->d )
1052              &&  gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE ) ) {
1053           /* we have to switch to secure allocation */
1054           gcry_sexp_t newsexp;
1055           byte *newhead;
1056
1057           newsexp = gcry_xmalloc_secure ( sizeof *newsexp
1058                                           + c.allocated - 1 );
1059           newhead = newsexp->d;
1060           memcpy ( newhead, c.sexp->d, (c.pos - c.sexp->d) );
1061           c.pos = newhead + ( c.pos - c.sexp->d );
1062           gcry_free ( c.sexp );
1063           c.sexp = newsexp;
1064         }
1065
1066         *c.pos++ = ST_DATA;
1067         STORE_LEN (c.pos, nm);
1068         if ( gcry_mpi_print( GCRYMPI_FMT_STD, c.pos, nm, &nm, m ) )
1069           BUG ();
1070         c.pos += nm;
1071       }
1072       else if ( *p == 's' ) { /* insert an string */
1073         const char *astr;
1074         size_t alen;
1075
1076         ARG_NEXT (astr, const char *);
1077         alen = strlen (astr);
1078
1079         MAKE_SPACE (alen);
1080         *c.pos++ = ST_DATA;
1081         STORE_LEN (c.pos, alen);
1082         memcpy ( c.pos, astr, alen );
1083         c.pos += alen;
1084       }
1085       else if ( *p == 'd' ) { /* insert an integer as string */
1086         int aint;
1087         size_t alen;
1088         char buf[20];
1089
1090         ARG_NEXT (aint, int);
1091         sprintf ( buf, "%d", aint );
1092         alen = strlen ( buf );
1093         MAKE_SPACE (alen);
1094         *c.pos++ = ST_DATA;
1095         STORE_LEN (c.pos, alen);
1096         memcpy ( c.pos, buf, alen );
1097         c.pos += alen;
1098       }
1099       else {
1100         *erroff = p - buffer;
1101         /* Invalid format specifier.  */
1102         return gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1103       }
1104       percent = NULL;
1105     }
1106     else if( *p == '(' ) {
1107       if( disphint ) {
1108         *erroff = p - buffer;
1109         /* Open display hint.  */
1110         return gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1111       }
1112       MAKE_SPACE (0);
1113       *c.pos++ = ST_OPEN;
1114       level++;
1115     }
1116     else if( *p == ')' ) { /* walk up */
1117       if( disphint ) {
1118         *erroff = p - buffer;
1119         /* Open display hint.  */
1120         return gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1121       }
1122       MAKE_SPACE (0);
1123       *c.pos++ = ST_CLOSE;
1124       level--;
1125     }
1126     else if( *p == '\"' ) {
1127       quoted = p;
1128       quoted_esc = 0;
1129     }
1130     else if( *p == '#' ) {
1131       hexfmt = p;
1132       hexcount = 0;
1133     }
1134     else if( *p == '|' )
1135       base64 = p;
1136     else if( *p == '[' ) {
1137       if( disphint ) {
1138         *erroff = p - buffer;
1139         /* Open display hint.  */
1140         return gcry_error (GPG_ERR_SEXP_NESTED_DH);
1141       }
1142       disphint = p;
1143     }
1144     else if( *p == ']' ) {
1145       if( !disphint ) {
1146         *erroff = p - buffer;
1147         /* Open display hint.  */
1148         return gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1149       }
1150       disphint = NULL;
1151     }
1152     else if( isdigit(*p) ) {
1153       if( *p == '0' ) { /* a length may not begin with zero */
1154         *erroff = p - buffer;
1155         return gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
1156       }
1157       digptr = p;
1158     }
1159     else if( strchr( tokenchars, *p ) )
1160       tokenp = p;
1161     else if( isspace(*p) )
1162       ;
1163     else if( *p == '{' ) {
1164       /* fixme: handle rescanning:
1165        * we can do this by saving our current state
1166        * and start over at p+1 -- Hmmm. At this point here
1167        * we are in a well defined state, so we don't need to save
1168        * it.  Great.
1169        */
1170       *erroff = p - buffer;
1171       return gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1172     }
1173     else if( strchr( "&\\", *p ) ) { /*reserved punctuation*/
1174       *erroff = p - buffer;
1175       return gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1176     }
1177     else if( argflag && *p == '%' ) {
1178       percent = p;
1179     }
1180     else { /* bad or unavailable*/
1181       *erroff = p - buffer;
1182       return gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
1183     }
1184
1185   }
1186   MAKE_SPACE (0);
1187   *c.pos++ = ST_STOP;
1188
1189   if (level)
1190     return gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
1191
1192   *retsexp = normalize ( c.sexp );
1193   return gcry_error (GPG_ERR_NO_ERROR);
1194 #undef MAKE_SPACE
1195 #undef STORE_LEN
1196 }
1197
1198 gcry_error_t
1199 gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
1200 {
1201   gcry_error_t rc;
1202   va_list arg_ptr;
1203   
1204   va_start (arg_ptr, format);
1205   rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
1206                    arg_ptr, NULL);
1207   va_end (arg_ptr);
1208   
1209   return rc;
1210 }
1211
1212 /* Like gcry_sexp_build, but uses an array instead of variable
1213    function arguments.  */
1214 gcry_error_t
1215 gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1216                        const char *format, void **arg_list)
1217 {
1218   /* We don't need the va_list because it is controlled by the
1219      following flag, however we have to pass it but can't initialize
1220      it as there is no portable way to do so.  volatile is needed to
1221      suppress the compiler warning */
1222   volatile va_list dummy_arg_ptr;
1223   
1224   gcry_error_t rc;
1225
1226   rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
1227                    dummy_arg_ptr, arg_list);
1228
1229   return rc;
1230 }
1231
1232 gcry_error_t
1233 gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1234                  const char *buffer, size_t length)
1235 {
1236   /* We don't need the va_list because it is controlled by the
1237      following flag, however we have to pass it but can't initialize
1238      it as there is no portable way to do so.  volatile is needed to
1239      suppress the compiler warning */
1240   volatile va_list dummy_arg_ptr;
1241
1242   return sexp_sscan (retsexp, erroff, buffer, length, 0,
1243                      dummy_arg_ptr, NULL);
1244 }
1245
1246 \f
1247 /* Figure out a suitable encoding for BUFFER of LENGTH.
1248    Returns: 0 = Binary
1249             1 = String possible
1250             2 = Token possible
1251 */
1252 static int
1253 suitable_encoding (const unsigned char *buffer, size_t length)
1254 {
1255   const unsigned char *s;
1256   int maybe_token = 1;
1257
1258   if (!length)
1259     return 1;
1260   
1261   for (s=buffer; length; s++, length--)
1262     {
1263       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1264            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1265         return 0; /*binary*/
1266       if ( maybe_token
1267            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1268         maybe_token = 0;
1269     }
1270   s = buffer;
1271   if ( maybe_token && !digitp (s) )
1272     return 2;
1273   return 1;
1274 }
1275
1276
1277 static int
1278 convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
1279 {
1280   int i;
1281
1282   if (dest)
1283     {
1284       *dest++ = '#';
1285       for (i=0; i < len; i++, dest += 2 )
1286         sprintf (dest, "%02X", src[i]);
1287       *dest++ = '#';
1288     }
1289   return len*2+2;
1290 }
1291
1292 static int
1293 convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
1294 {
1295   if (dest)
1296     {
1297       unsigned char *p = dest;
1298       *p++ = '\"';
1299       for (; len; len--, s++ )
1300         {
1301           switch (*s)
1302             {
1303             case '\b': *p++ = '\\'; *p++ = 'b';  break;
1304             case '\t': *p++ = '\\'; *p++ = 't';  break;
1305             case '\v': *p++ = '\\'; *p++ = 'v';  break;
1306             case '\n': *p++ = '\\'; *p++ = 'n';  break;
1307             case '\f': *p++ = '\\'; *p++ = 'f';  break;
1308             case '\r': *p++ = '\\'; *p++ = 'r';  break;
1309             case '\"': *p++ = '\\'; *p++ = '\"';  break;
1310             case '\'': *p++ = '\\'; *p++ = '\'';  break;
1311             case '\\': *p++ = '\\'; *p++ = '\\';  break;
1312             default: 
1313               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1314                 {
1315                   sprintf (p, "\\x%02x", *s); 
1316                   p += 4;
1317                 }
1318               else
1319                 *p++ = *s;
1320             }
1321         }
1322       *p++ = '\"';
1323       return p - dest;
1324     }
1325   else
1326     {
1327       int count = 2;
1328       for (; len; len--, s++ )
1329         {
1330           switch (*s)
1331             {
1332             case '\b': 
1333             case '\t': 
1334             case '\v': 
1335             case '\n': 
1336             case '\f': 
1337             case '\r': 
1338             case '\"':
1339             case '\'':
1340             case '\\': count += 2; break;
1341             default: 
1342               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1343                 count += 4;
1344               else
1345                 count++;
1346             }
1347         }
1348       return count;
1349     }
1350 }
1351
1352
1353
1354 static int
1355 convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
1356 {
1357   if (dest)
1358     memcpy (dest, src, len);
1359   return len;
1360 }
1361
1362
1363 /****************
1364  * Print SEXP to buffer using the MODE.  Returns the length of the
1365  * SEXP in buffer or 0 if the buffer is too short (We have at least an
1366  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
1367  * the required length is returned.
1368  */
1369 size_t
1370 gcry_sexp_sprint( const gcry_sexp_t list, int mode,
1371                                         char *buffer, size_t maxlength )
1372 {
1373   static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1374   const byte *s;
1375   char *d;
1376   DATALEN n;
1377   char numbuf[20];
1378   size_t len = 0;
1379   int i, indent = 0;
1380   
1381   s = list? list->d : empty;
1382   d = buffer;
1383   while ( *s != ST_STOP )
1384     {
1385       switch ( *s )
1386         {
1387         case ST_OPEN:
1388           s++;
1389           if ( mode != GCRYSEXP_FMT_CANON )
1390             {
1391               if (indent)
1392                 len++; 
1393               len += indent;
1394             }
1395           len++;
1396           if ( buffer ) 
1397             {
1398               if ( len >= maxlength )
1399                 return 0;
1400               if ( mode != GCRYSEXP_FMT_CANON )
1401                 {
1402                   if (indent)
1403                     *d++ = '\n'; 
1404                   for (i=0; i < indent; i++)
1405                     *d++ = ' ';
1406                 }
1407               *d++ = '(';
1408             }
1409           indent++;
1410           break;
1411         case ST_CLOSE:
1412           s++;
1413           len++;
1414           if ( buffer ) 
1415             {
1416               if ( len >= maxlength )
1417                 return 0;
1418               *d++ = ')';
1419             }
1420           indent--;
1421           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1422             {
1423               len++;
1424               len += indent;
1425               if (buffer)
1426                 {
1427                   if (len >= maxlength)
1428                     return 0;
1429                   *d++ = '\n';
1430                   for (i=0; i < indent; i++)
1431                     *d++ = ' ';
1432                 }
1433             }
1434           break;
1435         case ST_DATA:
1436           s++;
1437           memcpy ( &n, s, sizeof n ); s += sizeof n;
1438           if (mode == GCRYSEXP_FMT_ADVANCED)
1439             {
1440               int type;
1441               size_t nn;
1442
1443               switch ( (type=suitable_encoding (s, n)))
1444                 {
1445                 case 1: nn = convert_to_string (s, n, NULL); break;
1446                 case 2: nn = convert_to_token (s, n, NULL); break;
1447                 default: nn = convert_to_hex (s, n, NULL); break;
1448                 }
1449               len += nn;
1450               if (buffer)
1451                 {
1452                   if (len >= maxlength)
1453                     return 0;
1454                   switch (type)
1455                     {
1456                     case 1: convert_to_string (s, n, d); break;
1457                     case 2: convert_to_token (s, n, d); break;
1458                     default: convert_to_hex (s, n, d); break;
1459                     }
1460                   d += nn;
1461                 }
1462               if (s[n] != ST_CLOSE)
1463                 {
1464                   len++;
1465                   if (buffer)
1466                     {
1467                       if (len >= maxlength)
1468                         return 0;
1469                       *d++ = ' ';
1470                     }
1471                 }
1472             }
1473           else
1474             {
1475               sprintf (numbuf, "%u:", (unsigned int)n );
1476               len += strlen (numbuf) + n;
1477               if ( buffer ) 
1478                 {
1479                   if ( len >= maxlength )
1480                     return 0;
1481                   d = stpcpy ( d, numbuf );
1482                   memcpy ( d, s, n ); d += n;
1483                 }
1484             }
1485           s += n;
1486           break;
1487         default:
1488           BUG ();
1489         }
1490     }
1491   if ( mode != GCRYSEXP_FMT_CANON )
1492     {
1493       len++;
1494       if (buffer)
1495         {
1496           if ( len >= maxlength )
1497             return 0;
1498           *d++ = '\n'; 
1499         }
1500     }
1501   if (buffer) 
1502     {
1503       if ( len >= maxlength )
1504         return 0;
1505       *d++ = 0; /* for convenience we make a C string */
1506     }
1507   else
1508     len++; /* we need one byte more for this */
1509
1510   return len;
1511 }
1512
1513
1514 /* Scan a cannocial encoded buffer with implicit length values and
1515    return the actual length this S-expression uses.  For a valid S-Exp
1516    it should never return 0.  If LENGTH is not zero, the maximum
1517    length to scan is given - this can be used for syntax checks of
1518    data passed from outside. errorcode and erroff may both be passed as
1519    NULL.  */
1520 size_t
1521 gcry_sexp_canon_len (const unsigned char *buffer, size_t length, 
1522                      size_t *erroff, gcry_error_t *errcode)
1523 {
1524   const unsigned char *p;
1525   const char *disphint=NULL;
1526   unsigned int datalen = 0;
1527   size_t dummy_erroff;
1528   gcry_error_t dummy_errcode;
1529   size_t count = 0;
1530   int level = 0;
1531
1532   if (!erroff)
1533     erroff = &dummy_erroff;
1534   if (!errcode)
1535     errcode = &dummy_errcode;
1536
1537   *errcode = gcry_error (GPG_ERR_NO_ERROR);
1538   *erroff = 0;
1539   if (!buffer)
1540     return 0;
1541   if (*buffer != '(')
1542     {
1543       *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL);
1544       return 0;
1545     }
1546
1547   for (p=buffer; ; p++, count++ )
1548     {
1549       if (length && count >= length)
1550         {
1551           *erroff = count;
1552           *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1553           return 0;
1554         }
1555       
1556       if (datalen)
1557         {
1558           if (*p == ':')
1559             {
1560               if (length && (count+datalen) >= length)
1561                 {
1562                   *erroff = count;
1563                   *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1564                   return 0;
1565                 }
1566               count += datalen;
1567               p += datalen;
1568               datalen = 0;
1569             }
1570           else if (digitp(p))
1571             datalen = datalen*10 + atoi_1(p);
1572           else 
1573             {
1574               *erroff = count;
1575               *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1576               return 0;
1577             }
1578         }
1579       else if (*p == '(')
1580         {
1581           if (disphint)
1582             {
1583               *erroff = count;
1584               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1585               return 0;
1586             }
1587           level++;
1588         }
1589       else if (*p == ')')
1590         { /* walk up */
1591           if (!level)
1592             {
1593               *erroff = count;
1594               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
1595               return 0;
1596             }
1597           if (disphint)
1598             {
1599               *erroff = count;
1600               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1601               return 0;
1602             }
1603           if (!--level)
1604             return ++count; /* ready */
1605         }
1606       else if (*p == '[')
1607         {
1608           if (disphint) 
1609             {
1610               *erroff = count;
1611               *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH);
1612               return 0;
1613             }
1614           disphint = p;
1615         }
1616       else if (*p == ']')
1617         {
1618           if( !disphint ) 
1619             {
1620               *erroff = count;
1621               *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1622               return 0;
1623             }
1624           disphint = NULL;
1625         }
1626       else if (digitp (p) )
1627         {
1628           if (*p == '0')
1629             { 
1630               *erroff = count;
1631               *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
1632               return 0;
1633             }
1634           datalen = atoi_1 (p);
1635         }
1636       else if (*p == '&' || *p == '\\')
1637         {
1638           *erroff = count;
1639           *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1640           return 0;
1641         }
1642       else
1643         { 
1644           *erroff = count;
1645           *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
1646           return 0;
1647         }
1648     }
1649 }