SEXP_EOF,
};
+enum sexp_coding
+ {
+ SEXP_PLAIN,
+ SEXP_BASE64,
+ SEXP_HEX,
+ };
+
struct sexp_input
{
FILE *f;
- enum sexp_mode mode;
+ enum sexp_coding coding;
/* Used in transport mode */
struct base64_decode_ctx base64;
};
static void
-sexp_input_init(struct sexp_input *input, FILE *f, enum sexp_mode mode)
+sexp_input_init(struct sexp_input *input, FILE *f)
{
input->f = f;
- input->mode = mode;
+ input->coding = SEXP_PLAIN;
input->level = 0;
nettle_buffer_init(&input->string);
static int
sexp_get_char(struct sexp_input *input, uint8_t *out)
{
- if (input->mode & SEXP_TRANSPORT)
+ switch (input->coding)
{
- /* Base64 decode */
+ case SEXP_BASE64:
for (;;)
{
int done;
if (done)
return 1;
}
- }
- else
- {
- int c = getc(input->f);
+ case SEXP_PLAIN:
+ {
+ int c = getc(input->f);
- if (c < 0)
- {
- if (ferror(input->f))
- die("Read error: %s\n", strerror(errno));
+ if (c < 0)
+ {
+ if (ferror(input->f))
+ die("Read error: %s\n", strerror(errno));
- input->token = SEXP_EOF;
- return 0;
- }
+ input->token = SEXP_EOF;
+ return 0;
+ }
- *out = c;
- return 1;
+ *out = c;
+ return 1;
+ }
+ case SEXP_HEX:
+ /* Not yet implemented */
+ abort();
}
}
static int
sexp_get_quoted_char(struct sexp_input *input, uint8_t *c)
{
- if (sexp_get_char(input, c) <= 0)
+ if (!sexp_get_char(input, c))
die("Unexpected end of file in quoted string.\n");
for (;;)
static void
sexp_get_quoted_string(struct sexp_input *input)
{
- assert(input->mode == SEXP_ADVANCED);
-
uint8_t c;
+ assert(input->coding == SEXP_PLAIN);
+
while (sexp_get_quoted_char(input, &c))
if (!NETTLE_BUFFER_PUTC(&input->string, c))
die("Virtual memory exhasuted.\n");
{
struct base64_decode_ctx ctx;
- assert(input->mode == SEXP_ADVANCED);
+ assert(input->coding == SEXP_PLAIN);
base64_decode_init(&ctx);
static void
sexp_get_token_string(struct sexp_input *input, uint8_t c)
{
- assert(input->mode == SEXP_ADVANCED);
+ assert(input->coding == SEXP_PLAIN);
if (!TOKEN_CHAR(c) || ! NETTLE_BUFFER_PUTC(&input->string, c))
die("Invalid token.\n");
static void
sexp_get_string(struct sexp_input *input, uint8_t c)
{
- assert(input->mode == SEXP_ADVANCED);
input->string.size = 0;
input->token = SEXP_STRING;
case '|':
sexp_get_base64_string(input);
break;
+
default:
sexp_get_token_string(input, c);
break;
}
static void
-sexp_get_string_length(struct sexp_input *input, unsigned length)
+sexp_get_string_length(struct sexp_input *input, enum sexp_mode mode,
+ unsigned length)
{
uint8_t c;
return;
case '"':
- if (input->mode != SEXP_ADVANCED)
+ if (mode != SEXP_ADVANCED)
die("Encountered quoted string in canonical mode.\n");
for (; length; length--)
}
static void
-sexp_get_token(struct sexp_input *input)
+sexp_get_token(struct sexp_input *input, enum sexp_mode mode)
{
uint8_t c;
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- sexp_get_string_length(input, c - '0');
+ sexp_get_string_length(input, mode, c - '0');
return;
case '(':
case '\t':
case '\n':
case '\r':
- if (input->mode != SEXP_ADVANCED)
+ if (mode == SEXP_CANONICAL)
die("Whitespace encountered in canonical mode.\n");
break;
case ';': /* Comments */
- if (input->mode != SEXP_ADVANCED)
+ if (mode == SEXP_CANONICAL)
die("Comment encountered in canonical mode.\n");
for (;;)
default:
/* Ought to be a string */
- if (input->mode != SEXP_ADVANCED)
+ if (mode != SEXP_ADVANCED)
die("Encountered advanced string in canonical mode.\n");
sexp_get_string(input, c);
}
static void
-sexp_convert_string(struct sexp_input *input, struct sexp_output *output,
- unsigned indent)
+sexp_convert_string(struct sexp_input *input, enum sexp_mode mode,
+ struct sexp_output *output, unsigned indent)
{
- sexp_get_token(input);
+ sexp_get_token(input, mode);
if (input->token == SEXP_STRING)
sexp_put_string(output, indent, &input->string);
else
}
static int
-sexp_convert_item(struct sexp_input *input, struct sexp_output *output,
- unsigned indent);
+sexp_convert_item(struct sexp_input *input, enum sexp_mode mode,
+ struct sexp_output *output, unsigned indent);
static void
-sexp_convert_list(struct sexp_input *input, struct sexp_output *output,
+sexp_convert_list(struct sexp_input *input, enum sexp_mode mode,
+ struct sexp_output *output,
unsigned indent)
{
unsigned item;
for (item = 0;; item++)
{
- sexp_get_token(input);
+ sexp_get_token(input, mode);
/* Check for end of list */
if (input->token == SEXP_LIST_END
sexp_put_newline(output, indent);
}
- if (!sexp_convert_item(input, output, indent))
+ if (!sexp_convert_item(input, mode, output, indent))
/* Should be detected above */
abort();
}
static void
sexp_convert_file(struct sexp_input *input, struct sexp_output *output)
{
- sexp_get_token(input);
+ sexp_get_token(input, SEXP_ADVANCED);
while (input->token != SEXP_EOF)
{
- sexp_convert_item(input, output, 0);
+ sexp_convert_item(input, SEXP_ADVANCED, output, 0);
if (output->mode == SEXP_ADVANCED)
sexp_put_newline(output, 0);
- sexp_get_token(input);
+ sexp_get_token(input, SEXP_ADVANCED);
}
if (fflush(output->f) < 0)
static void
-sexp_skip_token(struct sexp_input *input, enum sexp_token token)
+sexp_skip_token(struct sexp_input *input, enum sexp_mode mode,
+ enum sexp_token token)
{
- sexp_get_token(input);
+ sexp_get_token(input, mode);
if (input->token != token)
die("Syntax error.\n");
}
*
* Should be called after getting the first token. */
static int
-sexp_convert_item(struct sexp_input *input, struct sexp_output *output,
- unsigned indent)
+sexp_convert_item(struct sexp_input *input, enum sexp_mode mode,
+ struct sexp_output *output, unsigned indent)
{
switch(input->token)
{
input->level++;
sexp_put_list_start(output, indent);
- sexp_convert_list(input, output, indent);
+ sexp_convert_list(input, mode, output, indent);
sexp_put_list_end(output, indent);
if (input->level)
break;
case SEXP_DISPLAY_START:
sexp_put_display_start(output, indent);
- sexp_convert_string(input, output, indent);
- sexp_skip_token(input, SEXP_DISPLAY_END);
+ sexp_convert_string(input, mode, output, indent);
+ sexp_skip_token(input, mode, SEXP_DISPLAY_END);
sexp_put_display_end(output, indent);
- sexp_convert_string(input, output, indent);
+ sexp_convert_string(input, mode, output, indent);
break;
case SEXP_TRANSPORT_START:
- if (input->mode != SEXP_ADVANCED)
+ if (mode != SEXP_ADVANCED)
die("Base64 not allowed in canonical mode.\n");
else
{
unsigned old_level = input->level;
- input->mode = SEXP_TRANSPORT;
+ assert(input->coding == SEXP_PLAIN);
+
+ input->coding = SEXP_BASE64;
input->level = 0;
base64_decode_init(&input->base64);
+
+ /* FIXME: sexp_convert_list is wrong. */
+ sexp_convert_list(input, SEXP_CANONICAL, output, indent);
- sexp_convert_list(input, output, indent);
-
- input->mode = SEXP_ADVANCED;
+ input->coding = SEXP_PLAIN;
input->level = old_level;
break;
}
case SEXP_TRANSPORT_END:
- if (input->mode != SEXP_TRANSPORT
- || input->level || !base64_decode_status(&input->base64))
+ /* FIXME: Should be moved do sexp_convert_transport */
+ if ( (input->coding != SEXP_BASE64)
+ || input->level || !base64_decode_status(&input->base64))
die("Invalid base64.\n");
break;
struct sexp_input input;
struct sexp_output output;
- sexp_input_init(&input, stdin, SEXP_ADVANCED);
+ sexp_input_init(&input, stdin);
sexp_output_init(&output, stdout, SEXP_ADVANCED);
sexp_convert_file(&input, &output);