Commit 1a73894a authored by Niels Möller's avatar Niels Möller
Browse files

Bugfixes. Moved parser to a separate file.

Rev: src/sexp.c:1.5
parent 20c72696
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "sexp.h" #include "sexp.h"
#include "format.h" #include "format.h"
#include "list.h"
#include "werror.h" #include "werror.h"
#include "xalloc.h" #include "xalloc.h"
...@@ -184,31 +185,35 @@ static struct sexp *make_sexp_string(struct lsh_string *d, struct lsh_string *c) ...@@ -184,31 +185,35 @@ static struct sexp *make_sexp_string(struct lsh_string *d, struct lsh_string *c)
static struct lsh_string * static struct lsh_string *
do_format_sexp_nil(struct sexp *ignored UNUSED, int style) do_format_sexp_nil(struct sexp *ignored UNUSED, int style UNUSED)
{ {
return ssh_format("()"); return ssh_format("()");
} }
/* Forward declaration */
static struct sexp_iterator *make_iter_cons(struct sexp *s);
struct sexp_cons sexp_nil = struct sexp_cons sexp_nil =
{ { STATIC_HEADER, do_format_sexp_nil }, &sexp_nil.super, &sexp_nil }; { { STATIC_HEADER, make_iter_cons, do_format_sexp_nil },
&sexp_nil.super, &sexp_nil };
#define SEXP_NIL (&sexp_nil.super) #define SEXP_NIL (&sexp_nil.super)
/* CLASS: /* CLASS:
(class (class
(name sexp_iter_cons) (name sexp_iter_cons)
(super sexp_iter) (super sexp_iterator)
(vars (vars
(p object sexp_cons))) (p object sexp_cons)))
*/ */
static struct sexp *do_cons_get(struct sexp_iter *c) static struct sexp *do_cons_get(struct sexp_iterator *c)
{ {
CAST(sexp_iter_cons, i, c); CAST(sexp_iter_cons, i, c);
return (i->p != &sexp_nil) ? NULL : i->p->car; return (i->p != &sexp_nil) ? NULL : i->p->car;
} }
static struct sexp *do_cons_set(struct sexp_iter *c, struct sexp *e) static void do_cons_set(struct sexp_iterator *c, struct sexp *e)
{ {
CAST(sexp_iter_cons, i, c); CAST(sexp_iter_cons, i, c);
assert (i->p != &sexp_nil); assert (i->p != &sexp_nil);
...@@ -216,21 +221,21 @@ static struct sexp *do_cons_set(struct sexp_iter *c, struct sexp *e) ...@@ -216,21 +221,21 @@ static struct sexp *do_cons_set(struct sexp_iter *c, struct sexp *e)
i->p->car = e; i->p->car = e;
} }
static void do_cons_advance(struct sexp_iter *c) static void do_cons_next(struct sexp_iterator *c)
{ {
CAST(sexp_iter_cons, i, c); CAST(sexp_iter_cons, i, c);
i->p = i->p->cdr; i->p = i->p->cdr;
} }
static make_iter_cons(struct sexp *s) static struct sexp_iterator *make_iter_cons(struct sexp *s)
{ {
CAST(sexp_cons, c, s); CAST(sexp_cons, c, s);
NEW(sexp_iter_cons, iter); NEW(sexp_iter_cons, iter);
iter->super.get = do_cons_get; iter->super.get = do_cons_get;
iter->super.set = do_cons_set; iter->super.set = do_cons_set;
iter->super.advance = do_cons_advance; iter->super.next = do_cons_next;
iter->p = s; iter->p = c;
return &iter->super; return &iter->super;
} }
...@@ -302,13 +307,13 @@ struct sexp *sexp_c(struct sexp *car, struct sexp_cons *cdr) ...@@ -302,13 +307,13 @@ struct sexp *sexp_c(struct sexp *car, struct sexp_cons *cdr)
/* CLASS: /* CLASS:
(class (class
(name sexp_iter_vector) (name sexp_iter_vector)
(super sexp_iter) (super sexp_iterator)
(vars (vars
(l object sexp_list) (l object object_list)
(i . unsigned))) (i . unsigned)))
*/ */
static struct sexp *do_vector_get(struct sexp_iter *c) static struct sexp *do_vector_get(struct sexp_iterator *c)
{ {
CAST(sexp_iter_vector, i, c); CAST(sexp_iter_vector, i, c);
if (i->i < LIST_LENGTH(i->l)) if (i->i < LIST_LENGTH(i->l))
...@@ -319,7 +324,7 @@ static struct sexp *do_vector_get(struct sexp_iter *c) ...@@ -319,7 +324,7 @@ static struct sexp *do_vector_get(struct sexp_iter *c)
return NULL; return NULL;
} }
static void do_vector_set(struct sexp_iter *c, struct sexp *e) static void do_vector_set(struct sexp_iterator *c, struct sexp *e)
{ {
CAST(sexp_iter_vector, i, c); CAST(sexp_iter_vector, i, c);
assert(i->i < LIST_LENGTH(i->l)); assert(i->i < LIST_LENGTH(i->l));
...@@ -327,24 +332,26 @@ static void do_vector_set(struct sexp_iter *c, struct sexp *e) ...@@ -327,24 +332,26 @@ static void do_vector_set(struct sexp_iter *c, struct sexp *e)
LIST(i->l)[i->i] = &e->super; LIST(i->l)[i->i] = &e->super;
} }
static void do_vector_advance(struct sexp_iter *c) static void do_vector_next(struct sexp_iterator *c)
{ {
CAST(sexp_iter_vector, i, c); CAST(sexp_iter_vector, i, c);
if (i->i < LIST_LENGTH(i->l)) if (i->i < LIST_LENGTH(i->l))
i->i++; i->i++;
} }
static void make_iter_vector(struct sexp *s) static struct sexp_iterator *make_iter_vector(struct sexp *s)
{ {
CAST(sexp_vector, v, s); CAST(sexp_vector, v, s);
NEW(sexp_iter_vector, iter); NEW(sexp_iter_vector, iter);
iter->super.get = do_vector_get; iter->super.get = do_vector_get;
iter->super.set = do_vector_set; iter->super.set = do_vector_set;
iter->super.advance = do_vector_advance; iter->super.next = do_vector_next;
iter->l = v->l; iter->l = v->elements;
iter->i = 0; iter->i = 0;
return &iter->super;
} }
static struct lsh_string *do_format_sexp_vector(struct sexp *e, int style) static struct lsh_string *do_format_sexp_vector(struct sexp *e, int style)
...@@ -435,24 +442,25 @@ struct sexp *sexp_l(unsigned n, ...) ...@@ -435,24 +442,25 @@ struct sexp *sexp_l(unsigned n, ...)
} }
} }
struct sexp *sexp_a(int a) struct sexp *sexp_a(const int a)
{ {
return make_sexp_string(NULL, ssh_format("%la", a)); return make_sexp_string(NULL, ssh_format("%la", a));
} }
struct sexp *sexp_z(char *s) struct sexp *sexp_z(const char *s)
{ {
return make_sexp_string(NULL, ssh_format("%lz", s)); return make_sexp_string(NULL, ssh_format("%lz", s));
} }
/* mpz->atom */ /* mpz->atom */
struct sexp *sexp_n(mpz_t n) struct sexp *sexp_n(const mpz_t n)
{ {
return make_sexp_string(NULL, ssh_format("%ln", n)); return make_sexp_string(NULL, ssh_format("%ln", n));
} }
struct sexp *sexp_sn(mpz_t n) struct sexp *sexp_sn(const mpz_t n)
{ {
(void) n;
fatal("sexp_sn: Signed numbers are not supported.\n"); fatal("sexp_sn: Signed numbers are not supported.\n");
} }
...@@ -487,7 +495,7 @@ static void encode_base64_group(UINT32 n, UINT8 *dest) ...@@ -487,7 +495,7 @@ static void encode_base64_group(UINT32 n, UINT8 *dest)
} }
struct lsh_string *encode_base64(struct lsh_string *s, struct lsh_string *encode_base64(struct lsh_string *s,
char *delimiters, const char *delimiters,
int free) int free)
{ {
UINT32 full_groups = (s->length) / 3; UINT32 full_groups = (s->length) / 3;
...@@ -542,323 +550,15 @@ struct lsh_string *encode_base64(struct lsh_string *s, ...@@ -542,323 +550,15 @@ struct lsh_string *encode_base64(struct lsh_string *s,
return res; return res;
} }
int sexp_nullp(struct sexp *e) int sexp_nullp(const struct sexp *e)
{ {
return (e == SEXP_NIL); return (e == SEXP_NIL);
} }
int sexp_atomp(struct sexp *e) int sexp_atomp(const struct sexp *e)
{ {
return !e->iter; return !e->iter;
} }
/* PARSER */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Ron Rivest, Niels Mller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if 0
/* The first level decoder. Handles base-64 and hex codes,
* and passes octets on to the scanner. */
#define SCAN_OCTET 1
#define SCAN_HEX 2
#define SCAN_BASE64 3
#define SCAN_TRANSPORT 4
/* CLASS:
(class
(name sexp_decode)
(super read_handler)
(vars
;; Scanning mode
(mode . int)
(next object scanner)))
*/
#endif
/* CLASS:
(class
(name string_handler)
(vars
(handler method "struct scanner *" "struct lsh_string *s")))
*/
#define HANDLE_STRING(h,s) ((h)->handler((h), (s)))
/* CLASS:
(class
(name parse_s)
(super scanner)
(vars
(c object string_handler)))
/* CLASS:
(class
(name parse_literal)
(super parse_s)
(vars
(i . UINT32)
(data string)))
*/
static int do_parse_literal(struct scanner **s, int token)
{
CAST(parse_literal, closure, *s);
if (token < 0)
return HANDLE_STRING(closure->super.c, NULL);
closure->data->string[closure->i++] = token;
if (closure->data->length == closure->i)
{
struct lsh_string *res = closure->data;
res->data = NULL;
*s = NULL;
return HANDLE_STRING(closure->super.c, res);
}
return LSH_OK;
}
static struct scanner *make_parse_literal(UINT32 length,
struct string_handler *c)
{
NEW(parse_literal, closure);
closure->super.super->scan = do_parse_literal;
closure->super.c = c;
closure->i = 0;
closure->data = lsh_String_alloc(length);
return &closure->super.super;
}
/* FIXME: Arbitrary limit. */
#define SEXP_MAX_STRING 100000
/* CLASS:
(class
(name parse_literal_length)
(super parse_s)
(vars
(length . UINT32)))
*/
static int do_parse_literal_length(struct scanner **s, int token)
{
CAST(parse_literal_length, closure, *s);
if (token < 0) goto fail;
if (char_classes[token] & CHAR_DIGIT)
{
closure->length = closure->length * 10 + (token - '0');
if (closure->length > SEXP_MAX_STRING)
goto fail;
return LSH_OK;
}
else if (token == ':')
{
*s = make_parse_literal(closure->length, closure->super.c);
return LSH_OK;
}
fail:
*s = NULL;
return HANDLE_STRING(closure->super.c, NULL);
}
static struct scanner *make_parse_literal_length(UINT32 start,
struct string_handler *c)
{
NEW(parse_literal_length, closure);
assert(start);
closure->super.super.scan = do_parse_literal_length;
closure->super.c = c;
closure->length = start;
return &closure->super.super;
}
/* CLASS:
(class
(name return_string)
(super string_handler)
(vars
(c object sexp_handler)))
*/
static int do_return_string(struct string_handler *h, struct lsh_string *s)
{
CAST(return_string, closure, h);
return HANDLE_SEXP(closure->c, make_sexp_string(NULL, s));
}
static struct string_handler *make_return_string(struct sexp_handler *c)
{
NEW(return_string, closure);
closure->super.handler = do_return_string;
closure->c = c;
return &closure->super;
}
/* For stateless parsing */
/* CLASS:
(class
(name parse_c)
(super scanner)
(vars
(c object sexp_handler)))
*/
#define MAKE_PARSE(name) \
static int do_parse##name(struct scanner **s, int token); \
\
static struct scanner *make_parse_##name(struct sexp_handler *c) \
{ \
NEW(parse_c, closure); \
\
closure->super.scan = do_parse##name; \
closure->c = c; \
\
return &closure->super; \
} \
\
static int do_parse##name(struct scanner **s, int token)
/* CLASS:
(class
(name parse_skip)
(super parse_c)
(vars
(expect . int)
(value object sexp)
(next object scanner))
*/
static int do_parse_skip(struct scanner **s, int token)
{
CAST(parse_skip, closure, *s);
/* FIXME: If the token doesn't match, perhaps we should install NULL
* instead? */
*s = closure->next;
return HANDLE_SEXP(closure->super.c,
( (token == closure->expect)
? closure->value
: NULL));
}
static struct scanner *make_parse_skip(int token,
struct scanner *next,
struct sexp *value,
struct sexp_handler *c)
{
NEW(parse_skip, closure);
closure->super.super.scan = do_parse_skip;
closure->super.c = c;
closure->next = next;
closure->expect = token;
closure->value = value;
return &closure->super.super;
}
/* CLASS:
(class
(name end_display)
(super string_handler)
(vars )))
*/
static int do_end_display(
MAKE_PARSE(simple_string)
{
CAST(parse_c, closure, *s);
switch(token)
{
case TOKEN_EOS:
fatal("Internal error!\n");
case '0':
/* This should be a single zero digit, as there mustn't be unneccessary
* leading zeros. */
*s = make_parse_skip(':', closure->next, sexp_z(""), closure->c);
return LSH_OK:
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
*s = make_parse_literal_length(token - '0',
make_return_string(closure->c));
return LSH_OK;
default:
/* Syntax error */
return HANDLE_SEXP(closure->c, NULL);
}
}
/* Parser for the canonical and transport formats. */
MAKE_PARSE(sexp)
{
CAST(parse_c, closure, *s);
switch (token)
{
case TOKEN_EOS:
fatal("Internal error!\n");
case '[':
*s = make_parse_simple_string(make_end_display(closure->c));
return LSH_OK:
case '(':
*s = make_parse_list(closure->c);
return LSH_OK;
default:
/* Should be a string */
*s = make_parse_string(closure->c);
return SCAN(*s, token);
}
}
/* CLASS:
(class
(parse_skip
static int do_
switch (char_classes[token])
{
case CHAR_DIGIT
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment