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