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