From fd6af34b297f7773b582af575d23256981289873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Sun, 29 Sep 2002 20:06:20 +0200 Subject: [PATCH] New file, implementing an sexp canonical syntax formatter. Rev: src/nettle/sexp_format.c:1.1 --- sexp_format.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 sexp_format.c diff --git a/sexp_format.c b/sexp_format.c new file mode 100644 index 00000000..50fe6cfa --- /dev/null +++ b/sexp_format.c @@ -0,0 +1,154 @@ +/* sexp-output.c + * + * Writing s-expressions. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2002 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. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "sexp.h" +#include "buffer.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if HAVE_LIBGMP +# include "bignum.h" +#endif + +static int +format_prefix(struct nettle_buffer *output, + unsigned length) +{ + unsigned prefix_length; + char prefix[10]; + + /* NOTE: Using the return value of sprintf is not entirely + * portable. */ + prefix_length = snprintf(prefix, sizeof(prefix), "%u:", length); + if (prefix_length >= sizeof(prefix)) + return 0; + + return nettle_buffer_write(buffer, prefix_length, prefix); +} + +static int +format_length_string(struct nettle_buffer *buffer, + unsigned length, const char *s) +{ + return format_prefix(buffer, length) + && nettle_buffer_write(buffer, length, s); +} + +static uint8_t * +format_space(struct nettle_buffer *buffer, + unsigned length) +{ + return format_prefix(output, length) + ? nettle_buffer_space(output, length) : NULL; +} + +static int +format_string(struct nettle_buffer *buffer, + const char *s) +{ + return format_length_string(buffer, strlen(s), s); +} + +int +sexp_format(struct nettle_buffer *buffer, const char *format, ...) +{ + va_list args; + va_start(args, format); + + unsigned nesting = 0; + + for (;;) + switch (*format++) + { + case '\0': + if (nesting) + { + fail: + va_end(args); + return 0; + } + else + { + va_end(args); + return 1; + } + case '(': + if (!NETTLE_BUFFER_PUTC(buffer, '(')) + goto fail; + + nesting++; + break; + + case ')': + if (!nesting) + abort(); + if (!NETTLE_BUFFER_PUTC(buffer, ')')) + goto fail; + + nesting--; + break; + + case '%': + switch (*format++) + { + case 's': + { + const char *s = va_arg(args, const char *); + format_string(buffer, s); + break; + } + case 'b': + { +#if HAVE_LIBGMP + const MP_INT *n = va_arg(args, const MP_INT *); + uint8_t *space; + unsigned length; + + if (mpz_sgn(n) < 0) + goto fail; + + length = nettle_mpz_sizeinbase_256(n); + + space = format_space(buffer, length); + if (!space) + goto fail; + nettle_mpz_get_str_256(length, space, n); +#else /* ! HAVE_LIBGMP */ + abort(); +#endif /* ! HAVE_LIBGMP */ + break; + } + default: + abort(); + } + } +} -- GitLab