]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
(sexp_input_init): Initialize input->string
authorNiels Möller <nisse@lysator.liu.se>
Wed, 23 Oct 2002 20:11:37 +0000 (22:11 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Wed, 23 Oct 2002 20:11:37 +0000 (22:11 +0200)
properly.
(sexp_get_char): Fixed non-transport case.
(sexp_get_quoted_char): Fixed default case.
(sexp_get_token): Loop over sexp_get_char (needed for handling of
white space). Don't modify input->level. Fixed the code that skips
comments.
(sexp_put_char): Fixed off-by-one bug in assertion.
(sexp_put_string): Fixed escape handling for output of quoted
strings.
(sexp_convert_list): Prettier output, hanging indent after the
first list element.
(sexp_skip_token): New function.
(sexp_convert_item): Use sexp_skip_token to skip the end of a
"[display-type]".

Rev: src/nettle/examples/sexp-conv.c:1.3

examples/sexp-conv.c

index 7a96fff298314ef0261d88a0fe6c16b714a1d6c5..4fddd4516284f2c0212794bf9667c2009ff8c7b1 100644 (file)
@@ -56,6 +56,8 @@ sexp_input_init(struct sexp_input *input, FILE *f, enum sexp_mode mode)
   input->f = f;
   input->mode = mode;
   input->level = 0;
+
+  nettle_buffer_init(&input->string);
 }
 
 struct sexp_output
@@ -114,19 +116,21 @@ sexp_get_char(struct sexp_input *input, uint8_t *out)
        }
     }
   else
-    for (;;)
-      {
-       int c = getc(input->f);
+    {
+      int c = getc(input->f);
       
-       if (c < 0)
-         {
-           if (ferror(input->f))
-             return -1;
-           
-           input->token = SEXP_EOF;
-           return 0;
-         }
-      }
+      if (c < 0)
+       {
+         if (ferror(input->f))
+           return -1;
+         
+         input->token = SEXP_EOF;
+         return 0;
+       }
+
+      *out = c;
+      return 1;
+    }
 }
 
 static const char
@@ -188,6 +192,8 @@ sexp_get_quoted_char(struct sexp_input *input, uint8_t *c)
   for (;;)
     switch (*c)
       {
+      default:
+       return 1;
       case '\"':
        return 0;
       case '\\':
@@ -382,76 +388,73 @@ static int
 sexp_get_token(struct sexp_input *input)
 {
   uint8_t c;
-  switch (sexp_get_char(input, &c))
-    {
-    case -1:
-      return 0;
-    case 0:
-      return 1;
-    case 1:
-      switch(c)
-       {
-       case '0': case '1': case '2': case '3': case '4':
-       case '5': case '6': case '7': case '8': case '9':
-         return sexp_get_string_length(input, c - '0');
-         
-       case '(':
-         input->token = SEXP_LIST_START;
-         return 1;
-       case ')':
-         input->token = SEXP_LIST_END;
 
-         if (!input->level)
-           return 0;
+  for(;;)
+    switch (sexp_get_char(input, &c))
+      {
+      case -1:
+       return 0;
+      case 0:
+       return 1;
+      case 1:
+       switch(c)
+         {
+         case '0': case '1': case '2': case '3': case '4':
+         case '5': case '6': case '7': case '8': case '9':
+           return sexp_get_string_length(input, c - '0');
+         
+         case '(':
+           input->token = SEXP_LIST_START;
+           return 1;
+         case ')':
+           input->token = SEXP_LIST_END;
 
-         input->level--;
-         return 1;
+           return 1;
 
-       case '[':
-         input->token = SEXP_DISPLAY_START;
-         return 1;
+         case '[':
+           input->token = SEXP_DISPLAY_START;
+           return 1;
 
-       case ']':
-         input->token = SEXP_DISPLAY_END;
-         return 1;
+         case ']':
+           input->token = SEXP_DISPLAY_END;
+           return 1;
 
-       case ' ':  /* SPC, TAB, LF, CR */
-       case '\t':
-       case '\n':
-       case '\r':
-         if (input->mode != SEXP_ADVANCED)
-           return 0;
-         break;
+         case ' ':  /* SPC, TAB, LF, CR */
+         case '\t':
+         case '\n':
+         case '\r':
+           if (input->mode != SEXP_ADVANCED)
+             return 0;
+           break;
 
-       case ';': /* Comments */
-         if (input->mode != SEXP_ADVANCED)
-           return 0;
+         case ';': /* Comments */
+           if (input->mode != SEXP_ADVANCED)
+             return 0;
 
-         for (;;)
-           {
-             int c = getc(input->f);
-             if (c < 0)
-               {
-                 if (ferror(input->f))
-                   return 0;
-                 else
-                   {
-                     input->token = SEXP_EOF;
-                     return 1;
-                   }
-               }
-             if (c != '\n')
-               break;
-           }
-         break;
+           for (;;)
+             {
+               int c = getc(input->f);
+               if (c < 0)
+                 {
+                   if (ferror(input->f))
+                     return 0;
+                   else
+                     {
+                       input->token = SEXP_EOF;
+                       return 1;
+                     }
+                 }
+               if (c == '\n')
+                 break;
+             }
+           break;
          
-       default:
-         /* Ought to be a string */
-         return (input->mode == SEXP_ADVANCED)
-           && sexp_get_string(input, c);
-       }
-    }
-  abort();
+         default:
+           /* Ought to be a string */
+           return (input->mode == SEXP_ADVANCED)
+             && sexp_get_string(input, c);
+         }
+      }
 }
 
 
@@ -577,7 +580,7 @@ sexp_put_base64_end(struct sexp_output *output, uint8_t c)
 
   done = base64_encode_final(&output->base64, encoded);
 
-  assert(done < sizeof(encoded));
+  assert(done <= sizeof(encoded));
   
   output->mode &= ~ SEXP_TRANSPORT;
 
@@ -598,7 +601,9 @@ sexp_put_string(struct sexp_output *output, unsigned indent,
       unsigned i;
       int token = (string->contents[0] < '0' || string->contents[0] > '9');
       int quote_friendly = 1;
-      
+      static const char escape_names[0x10] =
+       { 0,0,0,0,0,0,0,0, 'b','t','n',0,'f','r',0,0 };
+
       for (i = 0; i<string->size; i++)
        {
          uint8_t c = string->contents[i];
@@ -606,8 +611,13 @@ sexp_put_string(struct sexp_output *output, unsigned indent,
          if (token & !TOKEN_CHAR(c))
            token = 0;
          
-         if (quote_friendly && (c < 0x20 || c >= 0x7f))
-           quote_friendly = 0;
+         if (quote_friendly)
+           {
+             if (c >= 0x7f)
+               quote_friendly = 0;
+             else if (c < 0x20 && !escape_names[c])
+               quote_friendly = 0;
+           }
        }
       
       if (token)
@@ -615,9 +625,31 @@ sexp_put_string(struct sexp_output *output, unsigned indent,
 
       else if (quote_friendly)
        {
-         return sexp_put_char(output, indent, '"')
-           && sexp_put_data(output, indent, string->size, string->contents)
-           && sexp_put_char(output, indent, '"');
+         if (!sexp_put_char(output, indent, '"'))
+           return 0;
+         for (i = 0; i<string->size; i++)
+           {
+             int escape = 0;
+             uint8_t c = string->contents[i];
+
+             assert(c < 0x7f);
+             
+             if (c == '\\' || c == '"')
+               escape = 1;
+             else if (c < 0x20)
+               {
+                 escape = 1;
+                 c = escape_names[c];
+                 assert(c);
+               }
+             if (escape && !sexp_put_char(output, indent, '\\'))
+               return 0;
+
+             if (!sexp_put_char(output, indent, c))
+               return 0;
+           }
+               
+         return sexp_put_char(output, indent, '"');
        }
       else
        return (sexp_put_base64_start(output, '|')
@@ -677,36 +709,52 @@ static int
 sexp_convert_list(struct sexp_input *input, struct sexp_output *output,
                  unsigned indent)
 {
-  if (!sexp_get_token(input))
-    return 0;
+  unsigned item;
   
-  switch (sexp_convert_item(input, output, indent))
-    {
-    case 0:
-      return 1;
-    case -1:
-      return 0;
-    case 1:
-      break;
-    }
-
-  indent = output->pos;
-
-  for (;;)
+  for (item = 0;; item++)
     {
       if (!sexp_get_token(input))
        return 0;
-      
+
+      /* Check for end of list */
       if (input->token == SEXP_LIST_END
          || input->token == SEXP_EOF
          || input->token == SEXP_TRANSPORT_END)
        return 1;
 
-      sexp_put_newline(output, indent);
-      sexp_convert_item(input, output, indent);
+      if (output->mode == SEXP_ADVANCED)
+       {
+         /* FIXME: Adapt pretty printing to handle a big first
+          * element. */
+         if (item == 1)
+           {
+             if (!sexp_put_char(output, indent, ' '))
+               return 0;
+             indent = output->pos;
+           }
+         else if (item > 1 && !sexp_put_newline(output, indent))
+           return 0;
+       }
+      
+      switch (sexp_convert_item(input, output, indent))
+       {
+       case 0:
+         /* Should be detected above */
+         abort();
+       case -1:
+         return 0;
+       case 1:
+         break;
+       }
     }
 }
 
+static int
+sexp_skip_token(struct sexp_input *input, enum sexp_token token)
+{
+  return sexp_get_token(input) && input->token == token;
+}
+
 /* Returns 1 on success, -1 on error, and 0 at end of list/file.
  *
  * Should be called after getting the first token. */
@@ -750,6 +798,7 @@ sexp_convert_item(struct sexp_input *input, struct sexp_output *output,
     case SEXP_DISPLAY_START:
       return (sexp_put_display_start(output, indent)
              && sexp_convert_string(input, output, indent)
+             && sexp_skip_token(input, SEXP_DISPLAY_END)
              && sexp_put_display_end(output, indent)
              && sexp_convert_string(input, output, indent)) ? 1 : -1;