Commit e563d808 authored by Niels Möller's avatar Niels Möller

* tools/input.c, tools/input.h, tools/output.c, tools/output.h,

tools/parse.c, tools/parse.h, tools/misc.c, tools/misc.h: Moved
parts ov sexp-conv.c to separate files

Rev: src/nettle/tools/Makefile.am:1.3
Rev: src/nettle/tools/input.c:1.1
Rev: src/nettle/tools/input.h:1.1
Rev: src/nettle/tools/misc.c:1.1
Rev: src/nettle/tools/misc.h:1.1
Rev: src/nettle/tools/output.c:1.1
Rev: src/nettle/tools/output.h:1.1
Rev: src/nettle/tools/parse.c:1.1
Rev: src/nettle/tools/parse.h:1.1
Rev: src/nettle/tools/sexp-conv.c:1.13
parent bd7386a1
......@@ -9,4 +9,7 @@ bin_PROGRAMS = sexp-conv
LDADD = -lnettle
sexp_conv_SOURCES = sexp-conv.c getopt.c getopt1.c
EXTRA_DIST = misc.h input.h output.h parse.h
sexp_conv_SOURCES = sexp-conv.c input.c output.c parse.c \
getopt.c getopt1.c misc.c
/* input.c */
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002, 2003 Niels Mller
*
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The nettle library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "input.h"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
void
sexp_input_init(struct sexp_input *input, FILE *f)
{
input->f = f;
input->coding = NULL;
}
static void
sexp_get_raw_char(struct sexp_input *input)
{
int c = getc(input->f);
if (c < 0)
{
if (ferror(input->f))
die("Read error: %s\n", strerror(errno));
input->ctype = SEXP_EOF_CHAR;
}
else
{
input->ctype = SEXP_NORMAL_CHAR;
input->c = c;
}
}
void
sexp_get_char(struct sexp_input *input)
{
if (input->coding)
for (;;)
{
int done;
sexp_get_raw_char(input);
if (input->ctype == SEXP_EOF_CHAR)
die("Unexpected end of file in coded data.\n");
if (input->c == input->terminator)
{
input->ctype = SEXP_END_CHAR;
return;
}
done = 1;
/* Decodes in place. Should always work, when we decode one
* character at a time. */
if (!input->coding->decode_update(&input->state,
&done, &input->c,
1, &input->c))
die("Invalid coded data.\n");
if (done)
return;
}
else
sexp_get_raw_char(input);
}
static uint8_t
sexp_next_char(struct sexp_input *input)
{
sexp_get_char(input);
if (input->ctype != SEXP_NORMAL_CHAR)
die("Unexpected end of file.\n");
return input->c;
}
static void
sexp_push_char(struct sexp_input *input,
struct nettle_buffer *string)
{
assert(input->ctype == SEXP_NORMAL_CHAR);
if (!NETTLE_BUFFER_PUTC(string, input->c))
die("Virtual memory exhasuted.\n");
}
static void
sexp_input_start_coding(struct sexp_input *input,
const struct nettle_armor *coding,
uint8_t terminator)
{
assert(!input->coding);
input->coding = coding;
input->coding->decode_init(&input->state);
input->terminator = terminator;
}
static void
sexp_input_end_coding(struct sexp_input *input)
{
assert(input->coding);
if (!input->coding->decode_final(&input->state))
die("Invalid coded data.\n");
input->coding = NULL;
}
/* Return 0 at end-of-string */
static int
sexp_get_quoted_char(struct sexp_input *input)
{
sexp_next_char(input);
for (;;)
switch (input->c)
{
default:
return 1;
case '\"':
return 0;
case '\\':
sexp_next_char(input);
switch (input->c)
{
case 'b': input->c = '\b'; return 1;
case 't': input->c = '\t'; return 1;
case 'n': input->c = '\n'; return 1;
case 'f': input->c = '\f'; return 1;
case 'r': input->c = '\r'; return 1;
case '\\': input->c = '\\'; return 1;
case 'o':
case 'x':
/* FIXME: Not implemnted */
abort();
case '\n':
if (sexp_next_char(input) == '\r')
sexp_next_char(input);
break;
case '\r':
if (sexp_next_char(input) == '\n')
sexp_next_char(input);
break;
}
return 1;
}
}
static void
sexp_get_token_string(struct sexp_input *input,
struct nettle_buffer *string)
{
assert(!input->coding);
assert(input->ctype == SEXP_NORMAL_CHAR);
if (!TOKEN_CHAR(input->c))
die("Invalid token.\n");
do
{
sexp_push_char(input, string);
sexp_get_char(input);
}
while (input->ctype == SEXP_NORMAL_CHAR && TOKEN_CHAR(input->c));
assert (string->size);
}
static void
sexp_get_string(struct sexp_input *input,
struct nettle_buffer *string)
{
nettle_buffer_reset(string);
input->token = SEXP_STRING;
switch (input->c)
{
case '\"':
while (sexp_get_quoted_char(input))
sexp_push_char(input, string);
sexp_get_char(input);
break;
case '#':
sexp_input_start_coding(input, &nettle_base16, '#');
goto decode;
case '|':
sexp_input_start_coding(input, &nettle_base64, '|');
decode:
for (;;)
{
sexp_get_char(input);
switch (input->ctype)
{
case SEXP_NORMAL_CHAR:
sexp_push_char(input, string);
break;
case SEXP_EOF_CHAR:
die("Unexpected end of file in coded string.\n");
case SEXP_END_CHAR:
sexp_input_end_coding(input);
sexp_get_char(input);
return;
}
}
break;
default:
sexp_get_token_string(input, string);
break;
}
}
static void
sexp_get_string_length(struct sexp_input *input, enum sexp_mode mode,
struct nettle_buffer *string)
{
unsigned length;
nettle_buffer_reset(string);
input->token = SEXP_STRING;
length = input->c - '0';
if (!length)
/* There must be no more digits */
sexp_next_char(input);
else
{
assert(length < 10);
/* Get rest of digits */
for (;;)
{
sexp_next_char(input);
if (input->c < '0' || input->c > '9')
break;
/* FIXME: Check for overflow? */
length = length * 10 + input->c - '0';
}
}
switch(input->c)
{
case ':':
/* Verbatim */
for (; length; length--)
{
sexp_next_char(input);
sexp_push_char(input, string);
}
break;
case '"':
if (mode != SEXP_ADVANCED)
die("Encountered quoted string in canonical mode.\n");
for (; length; length--)
if (sexp_get_quoted_char(input))
sexp_push_char(input, string);
else
die("Unexpected end of string.\n");
if (sexp_get_quoted_char(input))
die("Quoted string longer than expected.\n");
break;
case '#':
sexp_input_start_coding(input, &nettle_base16, '#');
goto decode;
case '|':
sexp_input_start_coding(input, &nettle_base64, '|');
decode:
for (; length; length--)
{
sexp_next_char(input);
sexp_push_char(input, string);
}
sexp_get_char(input);
if (input->ctype != SEXP_END_CHAR)
die("Coded string too long.\n");
sexp_input_end_coding(input);
break;
default:
die("Invalid string.\n");
}
/* Skip the ending character. */
sexp_get_char(input);
}
/* When called, input->c should be the first character of the current
* token.
*
* When returning, input->c should be the first character of the next
* token. */
void
sexp_get_token(struct sexp_input *input, enum sexp_mode mode,
struct nettle_buffer *string)
{
for(;;)
switch(input->ctype)
{
case SEXP_EOF_CHAR:
input->token = SEXP_EOF;
return;
case SEXP_END_CHAR:
input->token = SEXP_CODING_END;
sexp_input_end_coding(input);
sexp_get_char(input);
return;
case SEXP_NORMAL_CHAR:
switch(input->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, mode, string);
return;
case '(':
input->token = SEXP_LIST_START;
sexp_get_char(input);
return;
case ')':
input->token = SEXP_LIST_END;
sexp_get_char(input);
return;
case '[':
input->token = SEXP_DISPLAY_START;
sexp_get_char(input);
return;
case ']':
input->token = SEXP_DISPLAY_END;
sexp_get_char(input);
return;
case '{':
if (mode == SEXP_CANONICAL)
die("Unexpected transport data in canonical mode.\n");
sexp_input_start_coding(input, &nettle_base64, '}');
sexp_get_char(input);
input->token = SEXP_TRANSPORT_START;
return;
case ' ': /* SPC, TAB, LF, CR */
case '\t':
case '\n':
case '\r':
if (mode == SEXP_CANONICAL)
die("Whitespace encountered in canonical mode.\n");
sexp_get_char(input);
break;
case ';': /* Comments */
if (mode == SEXP_CANONICAL)
die("Comment encountered in canonical mode.\n");
do
{
sexp_get_raw_char(input);
if (input->ctype != SEXP_NORMAL_CHAR)
return;
}
while (input->c != '\n');
break;
default:
/* Ought to be a string */
if (mode != SEXP_ADVANCED)
die("Encountered advanced string in canonical mode.\n");
sexp_get_string(input, string);
return;
}
}
}
/* input.h */
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002, 2003 Niels Mller
*
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The nettle library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef NETTLE_TOOLS_INPUT_H_INCLUDED
#define NETTLE_TOOLS_INPUT_H_INCLUDED
#include "misc.h"
#include "base16.h"
#include "base64.h"
#include "buffer.h"
#include "nettle-meta.h"
#include <stdio.h>
/* Special marks in the input stream */
enum sexp_char_type
{
SEXP_NORMAL_CHAR = 0,
SEXP_EOF_CHAR, SEXP_END_CHAR,
};
struct sexp_input
{
FILE *f;
/* Character stream, consisting of ordinary characters,
* SEXP_EOF_CHAR, and SEXP_END_CHAR. */
enum sexp_char_type ctype;
uint8_t c;
const struct nettle_armor *coding;
union {
struct base64_decode_ctx base64;
struct base16_decode_ctx hex;
} state;
/* Terminator for current coding */
uint8_t terminator;
/* Type of current token */
enum sexp_token token;
};
void
sexp_input_init(struct sexp_input *input, FILE *f);
void
sexp_get_char(struct sexp_input *input);
void
sexp_get_token(struct sexp_input *input, enum sexp_mode mode,
struct nettle_buffer *string);
#endif /* NETTLE_TOOLS_INPUT_H_INCLUDED */
/* misc.c */
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002, 2003 Niels Möller
*
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The nettle library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "misc.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void
die(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(EXIT_FAILURE);
}
void
werror(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(EXIT_FAILURE);
}
const char
sexp_token_chars[0x80] =
{
/* 0, ... 0x1f */
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/* SPC ! " # $ % & ' ( ) * + , - . / */
0,0,0,0,0,0,0,0, 0,0,1,1,0,1,1,1,
/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
1,1,1,1,1,1,1,1, 1,1,1,0,0,1,0,0,
/* @ A ... O */
0,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
/* P ... Z [ \ ] ^ _ */
1,1,1,1,1,1,1,1, 1,1,1,0,0,0,0,1,
/* ` a, ... o */
0,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
/* p ... z { | } ~ DEL */
1,1,1,1,1,1,1,1, 1,1,1,0,0,0,0,0,
};
/* misc.h */
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002, 2003 Niels Mller
*
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The nettle library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef NETTLE_TOOLS_MISC_H_INCLUDED
#define NETTLE_TOOLS_MISC_H_INCLUDED
#if HAVE_CONFIG_H
# include "config.h"
#endif
void
die(const char *format, ...)
#if __GNUC___
__attribute__((__format__ (__printf__,1, 2)))
__attribute__((__noreturn__))
#endif
;
void
werror(const char *format, ...)
#if __GNUC___
__attribute__((__format__ (__printf__,1, 2)))
__attribute__((__noreturn__))
#endif
;
enum sexp_mode
{
SEXP_CANONICAL = 0,
SEXP_ADVANCED = 1,
SEXP_TRANSPORT = 2,
};
enum sexp_token
{
/* Zero is used to mean "any token" in sexp_parse. */
SEXP_STRING = 1,
SEXP_DISPLAY, /* Constructed by sexp_parse */
SEXP_LIST_START,