v2003-06-09 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 gpg_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 gpg_error_t
191 gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
192                   int autodetect, void (*freefnc)(void*) )
193 {
194   gpg_error_t errcode;
195   gcry_sexp_t se;
196   volatile va_list dummy_arg_ptr;
197
198   if (!retsexp)
199     return gpg_error (GPG_ERR_INV_ARG);
200   *retsexp = NULL;
201   if (autodetect < 0 || autodetect > 1 || !buffer)
202     return gpg_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 gpg_error (GPG_ERR_NO_ERROR);
231 }
232
233 /* Same as gcry_sexp_create but don't transfer ownership */
234 gpg_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         MPI 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, &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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_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, &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, 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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_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 gpg_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1168     }
1169     else if( strchr( "&\\", *p ) ) { /*reserved punctuation*/
1170       *erroff = p - buffer;
1171       return gpg_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 gpg_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 gpg_error (GPG_ERR_NO_ERROR);
1187 #undef MAKE_SPACE
1188 #undef STORE_LEN
1189 }
1190
1191 gpg_error_t
1192 gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
1193 {
1194   gpg_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 gpg_error_t
1208 gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1209                        const char *format, void **arg_list)
1210 {
1211   
1212   gpg_error_t rc;
1213
1214   rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
1215                    NULL, arg_list);
1216
1217   return rc;
1218 }
1219
1220 gpg_error_t
1221 gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1222                  const char *buffer, size_t length)
1223 {
1224   /* We don't need the va_list because it is controlled by the
1225      following flag, however we have to pass it but can't initialize
1226      it as there is no portable way to do so.  volatile is needed to
1227      suppress the compiler warning */
1228   volatile va_list dummy_arg_ptr;
1229
1230   return sexp_sscan (retsexp, erroff, buffer, length, 0,
1231                      dummy_arg_ptr, NULL);
1232 }
1233
1234 \f
1235 /* Figure out a suitable encoding for BUFFER of LENGTH.
1236    Returns: 0 = Binary
1237             1 = String possible
1238             2 = Token possible
1239 */
1240 static int
1241 suitable_encoding (const unsigned char *buffer, size_t length)
1242 {
1243   const unsigned char *s;
1244   int maybe_token = 1;
1245
1246   if (!length)
1247     return 1;
1248   
1249   for (s=buffer; length; s++, length--)
1250     {
1251       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1252            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1253         return 0; /*binary*/
1254       if ( maybe_token
1255            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1256         maybe_token = 0;
1257     }
1258   s = buffer;
1259   if ( maybe_token && !digitp (s) )
1260     return 2;
1261   return 1;
1262 }
1263
1264
1265 static int
1266 convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
1267 {
1268   int i;
1269
1270   if (dest)
1271     {
1272       *dest++ = '#';
1273       for (i=0; i < len; i++, dest += 2 )
1274         sprintf (dest, "%02X", src[i]);
1275       *dest++ = '#';
1276     }
1277   return len*2+2;
1278 }
1279
1280 static int
1281 convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
1282 {
1283   if (dest)
1284     {
1285       unsigned char *p = dest;
1286       *p++ = '\"';
1287       for (; len; len--, s++ )
1288         {
1289           switch (*s)
1290             {
1291             case '\b': *p++ = '\\'; *p++ = 'b';  break;
1292             case '\t': *p++ = '\\'; *p++ = 't';  break;
1293             case '\v': *p++ = '\\'; *p++ = 'v';  break;
1294             case '\n': *p++ = '\\'; *p++ = 'n';  break;
1295             case '\f': *p++ = '\\'; *p++ = 'f';  break;
1296             case '\r': *p++ = '\\'; *p++ = 'r';  break;
1297             case '\"': *p++ = '\\'; *p++ = '\"';  break;
1298             case '\'': *p++ = '\\'; *p++ = '\'';  break;
1299             case '\\': *p++ = '\\'; *p++ = '\\';  break;
1300             default: 
1301               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1302                 {
1303                   sprintf (p, "\\x%02x", *s); 
1304                   p += 4;
1305                 }
1306               else
1307                 *p++ = *s;
1308             }
1309         }
1310       *p++ = '\"';
1311       return p - dest;
1312     }
1313   else
1314     {
1315       int count = 2;
1316       for (; len; len--, s++ )
1317         {
1318           switch (*s)
1319             {
1320             case '\b': 
1321             case '\t': 
1322             case '\v': 
1323             case '\n': 
1324             case '\f': 
1325             case '\r': 
1326             case '\"':
1327             case '\'':
1328             case '\\': count += 2; break;
1329             default: 
1330               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1331                 count += 4;
1332               else
1333                 count++;
1334             }
1335         }
1336       return count;
1337     }
1338 }
1339
1340
1341
1342 static int
1343 convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
1344 {
1345   if (dest)
1346     memcpy (dest, src, len);
1347   return len;
1348 }
1349
1350
1351 /****************
1352  * Print SEXP to buffer using the MODE.  Returns the length of the
1353  * SEXP in buffer or 0 if the buffer is too short (We have at least an
1354  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
1355  * the required length is returned.
1356  */
1357 size_t
1358 gcry_sexp_sprint( const gcry_sexp_t list, int mode,
1359                                         char *buffer, size_t maxlength )
1360 {
1361   static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1362   const byte *s;
1363   char *d;
1364   DATALEN n;
1365   char numbuf[20];
1366   size_t len = 0;
1367   int i, indent = 0;
1368   
1369   s = list? list->d : empty;
1370   d = buffer;
1371   while ( *s != ST_STOP )
1372     {
1373       switch ( *s )
1374         {
1375         case ST_OPEN:
1376           s++;
1377           if ( mode != GCRYSEXP_FMT_CANON )
1378             {
1379               if (indent)
1380                 len++; 
1381               len += indent;
1382             }
1383           len++;
1384           if ( buffer ) 
1385             {
1386               if ( len >= maxlength )
1387                 return 0;
1388               if ( mode != GCRYSEXP_FMT_CANON )
1389                 {
1390                   if (indent)
1391                     *d++ = '\n'; 
1392                   for (i=0; i < indent; i++)
1393                     *d++ = ' ';
1394                 }
1395               *d++ = '(';
1396             }
1397           indent++;
1398           break;
1399         case ST_CLOSE:
1400           s++;
1401           len++;
1402           if ( buffer ) 
1403             {
1404               if ( len >= maxlength )
1405                 return 0;
1406               *d++ = ')';
1407             }
1408           indent--;
1409           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1410             {
1411               len++;
1412               len += indent;
1413               if (buffer)
1414                 {
1415                   if (len >= maxlength)
1416                     return 0;
1417                   *d++ = '\n';
1418                   for (i=0; i < indent; i++)
1419                     *d++ = ' ';
1420                 }
1421             }
1422           break;
1423         case ST_DATA:
1424           s++;
1425           memcpy ( &n, s, sizeof n ); s += sizeof n;
1426           if (mode == GCRYSEXP_FMT_ADVANCED)
1427             {
1428               int type;
1429               size_t nn;
1430
1431               switch ( (type=suitable_encoding (s, n)))
1432                 {
1433                 case 1: nn = convert_to_string (s, n, NULL); break;
1434                 case 2: nn = convert_to_token (s, n, NULL); break;
1435                 default: nn = convert_to_hex (s, n, NULL); break;
1436                 }
1437               len += nn;
1438               if (buffer)
1439                 {
1440                   if (len >= maxlength)
1441                     return 0;
1442                   switch (type)
1443                     {
1444                     case 1: convert_to_string (s, n, d); break;
1445                     case 2: convert_to_token (s, n, d); break;
1446                     default: convert_to_hex (s, n, d); break;
1447                     }
1448                   d += nn;
1449                 }
1450               if (s[n] != ST_CLOSE)
1451                 {
1452                   len++;
1453                   if (buffer)
1454                     {
1455                       if (len >= maxlength)
1456                         return 0;
1457                       *d++ = ' ';
1458                     }
1459                 }
1460             }
1461           else
1462             {
1463               sprintf (numbuf, "%u:", (unsigned int)n );
1464               len += strlen (numbuf) + n;
1465               if ( buffer ) 
1466                 {
1467                   if ( len >= maxlength )
1468                     return 0;
1469                   d = stpcpy ( d, numbuf );
1470                   memcpy ( d, s, n ); d += n;
1471                 }
1472             }
1473           s += n;
1474           break;
1475         default:
1476           BUG ();
1477         }
1478     }
1479   if ( mode != GCRYSEXP_FMT_CANON )
1480     {
1481       len++;
1482       if (buffer)
1483         {
1484           if ( len >= maxlength )
1485             return 0;
1486           *d++ = '\n'; 
1487         }
1488     }
1489   if (buffer) 
1490     {
1491       if ( len >= maxlength )
1492         return 0;
1493       *d++ = 0; /* for convenience we make a C string */
1494     }
1495   else
1496     len++; /* we need one byte more for this */
1497
1498   return len;
1499 }
1500
1501
1502 /* Scan a cannocial encoded buffer with implicit length values and
1503    return the actual length this S-expression uses.  For a valid S-Exp
1504    it should never return 0.  If LENGTH is not zero, the maximum
1505    length to scan is given - this can be used for syntax checks of
1506    data passed from outside. errorcode and erroff may both be passed as
1507    NULL.  */
1508 size_t
1509 gcry_sexp_canon_len (const unsigned char *buffer, size_t length, 
1510                      size_t *erroff, gpg_error_t *errcode)
1511 {
1512   const unsigned char *p;
1513   const char *disphint=NULL;
1514   unsigned int datalen = 0;
1515   size_t dummy_erroff;
1516   gpg_error_t dummy_errcode;
1517   size_t count = 0;
1518   int level = 0;
1519
1520   if (!erroff)
1521     erroff = &dummy_erroff;
1522   if (!errcode)
1523     errcode = &dummy_errcode;
1524
1525   *errcode = gpg_error (GPG_ERR_NO_ERROR);
1526   *erroff = 0;
1527   if (!buffer)
1528     return 0;
1529   if (*buffer != '(')
1530     {
1531       *errcode = gpg_error (GPG_ERR_SEXP_NOT_CANONICAL);
1532       return 0;
1533     }
1534
1535   for (p=buffer; ; p++, count++ )
1536     {
1537       if (length && count >= length)
1538         {
1539           *erroff = count;
1540           *errcode = gpg_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1541           return 0;
1542         }
1543       
1544       if (datalen)
1545         {
1546           if (*p == ':')
1547             {
1548               if (length && (count+datalen) >= length)
1549                 {
1550                   *erroff = count;
1551                   *errcode = gpg_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1552                   return 0;
1553                 }
1554               count += datalen;
1555               p += datalen;
1556               datalen = 0;
1557             }
1558           else if (digitp(p))
1559             datalen = datalen*10 + atoi_1(p);
1560           else 
1561             {
1562               *erroff = count;
1563               *errcode = gpg_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1564               return 0;
1565             }
1566         }
1567       else if (*p == '(')
1568         {
1569           if (disphint)
1570             {
1571               *erroff = count;
1572               *errcode = gpg_error (GPG_ERR_SEXP_UNMATCHED_DH);
1573               return 0;
1574             }
1575           level++;
1576         }
1577       else if (*p == ')')
1578         { /* walk up */
1579           if (!level)
1580             {
1581               *erroff = count;
1582               *errcode = gpg_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
1583               return 0;
1584             }
1585           if (disphint)
1586             {
1587               *erroff = count;
1588               *errcode = gpg_error (GPG_ERR_SEXP_UNMATCHED_DH);
1589               return 0;
1590             }
1591           if (!--level)
1592             return ++count; /* ready */
1593         }
1594       else if (*p == '[')
1595         {
1596           if (disphint) 
1597             {
1598               *erroff = count;
1599               *errcode = gpg_error (GPG_ERR_SEXP_NESTED_DH);
1600               return 0;
1601             }
1602           disphint = p;
1603         }
1604       else if (*p == ']')
1605         {
1606           if( !disphint ) 
1607             {
1608               *erroff = count;
1609               *errcode = gpg_error (GPG_ERR_SEXP_UNMATCHED_DH);
1610               return 0;
1611             }
1612           disphint = NULL;
1613         }
1614       else if (digitp (p) )
1615         {
1616           if (*p == '0')
1617             { 
1618               *erroff = count;
1619               *errcode = gpg_error (GPG_ERR_SEXP_ZERO_PREFIX);
1620               return 0;
1621             }
1622           datalen = atoi_1 (p);
1623         }
1624       else if (*p == '&' || *p == '\\')
1625         {
1626           *erroff = count;
1627           *errcode = gpg_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
1628           return 0;
1629         }
1630       else
1631         { 
1632           *erroff = count;
1633           *errcode = gpg_error (GPG_ERR_SEXP_BAD_CHARACTER);
1634           return 0;
1635         }
1636     }
1637 }