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