Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Nettle
nettle
Commits
e1bf1800
Commit
e1bf1800
authored
Oct 21, 2002
by
Niels Möller
Browse files
New sexp conversion program.
Rev: src/nettle/examples/sexp-conv.c:1.1
parent
2316a12d
Changes
1
Hide whitespace changes
Inline
Side-by-side
examples/sexp-conv.c
0 → 100644
View file @
e1bf1800
/* sexp-conv.c
*
* Conversion tool for handling the different flavours of sexp
* syntax. */
#include
"base64.h"
enum
sexp_mode
{
SEXP_CANONICAL
=
0
,
SEXP_ADVANCED
=
1
,
/* OR:ed with SEXP_CANONICAL or SEXP_ADVANCED when reading
* transport data. */
SEXP_TRANSPORT
=
2
,
};
enum
sexp_token
{
SEXP_LIST
,
SEXP_STRING
,
SEXP_DISPLAY_START
,
SEXP_DISPLAY_END
,
SEXP_LIST_START
,
SEXP_LIST_END
,
SEXP_TRANSPORT_START
,
SEXP_TRANSPORT_END
,
SEXP_EOF
,
};
struct
sexp_input
{
FILE
*
f
;
enum
sexp_mode
mode
;
/* Used in transport mode */
struct
base64_decode_ctx
base64
;
/* Type of current token */
enum
sexp_token
token
;
/* Current token */
struct
nettle_buffer
string
;
/* Nesting level */
unsigned
level
;
};
struct
sexp_output
{
FILE
*
f
;
enum
sexp_mode
mode
;
unsigned
indent
;
unsigned
pos
;
};
/* Returns 1 on success. On failure, return -1. For special tokens,
* return 0 and set input->token accordingly. */
static
int
sexp_get_char
(
struct
sexp_input
*
input
,
uint8_t
*
out
)
{
if
(
input
->
mode
&
SEXP_TRANSPORT
)
{
/* Base64 decode */
for
(;;)
{
int
done
;
int
c
=
getc
(
input
->
f
);
if
(
c
<
0
)
return
-
1
;
if
(
c
==
'}'
)
{
if
(
base64_decode_status
(
&
input
->
ctx
))
{
input
->
token
=
SEXP_TRANSPORT_END
;
return
0
;
}
else
return
-
1
;
}
done
=
base64_decode_single
(
&
input
->
ctx
,
out
,
c
);
if
(
done
)
return
1
;
}
}
else
for
(;;)
{
int
c
=
getc
(
input
->
f
);
if
(
c
<
0
)
{
if
(
ferror
(
input
->
f
))
return
-
1
;
input
->
token
=
SEXP_EOF
;
return
0
;
}
}
}
static
const
char
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
,
};
#define TOKEN_CHAR(c) ((c) < 0x80 && token_chars[(c)])
/* Returns 0 at end of token */
static
uint8_t
sexp_get_token_char
(
struct
sexp_input
*
input
)
{
int
c
=
getc
(
input
->
f
);
if
(
c
>=
0
&&
TOKEN_CHAR
(
c
))
return
c
;
ungetc
(
input
->
f
,
c
);
return
0
;
}
#if 0
static void
sexp_unget_char(struct sexp_input *input, uint8_t c)
{
assert(input->mode == SEXP_ADVANCED);
ungetc(c, input->f);
}
#endif
static
int
sexp_get_string_char
(
struct
sexp_input
*
input
)
{
assert
(
input
->
mode
==
SEXP_ADVANCED
);
}
static
int
sexp_get_quoted_char
(
struct
sexp_input
*
input
,
uint8_t
*
c
)
{
if
(
sexp_get_char
(
input
,
c
)
<=
0
)
return
-
1
;
for
(;;)
switch
(
*
c
)
{
case
'\"'
:
return
0
;
case
'\\'
:
if
(
sexp_get_char
(
input
,
c
)
<=
0
)
return
-
1
;
switch
(
*
c
)
{
case
'b'
:
*
c
=
'\b'
;
return
1
;
case
't'
:
*
c
=
'\t'
;
return
1
;
case
'n'
:
*
c
=
'\n'
;
return
1
;
case
'f'
:
*
c
=
'\f'
;
return
1
;
case
'r'
:
*
c
=
'\r'
;
return
1
;
case
'\\'
:
*
c
=
'\\'
;
return
1
;
case
'o'
:
case
'x'
:
/* Not implemnted */
abort
();
case
'\n'
:
if
(
sexp_get_char
(
input
,
c
)
<=
0
)
return
-
1
;
if
(
*
c
==
'\r'
&&
sexp_get_char
(
input
,
c
)
<=
0
)
return
-
1
;
break
;
case
'\r'
:
if
(
sexp_get_char
(
input
,
c
)
<=
0
)
return
-
1
;
if
(
*
c
==
'\n'
&&
sexp_get_char
(
input
,
c
)
<=
0
)
return
-
1
;
break
;
}
}
}
static
int
sexp_get_quoted_string
(
struct
sexp_input
*
input
)
{
assert
(
input
->
mode
==
SEXP_ADVANCED
);
for
(;;)
{
uint8_t
c
;
switch
(
sexp_get_quoted_char
(
input
,
&
c
))
{
case
0
:
return
1
;
case
-
1
:
return
0
;
default:
if
(
!
NETTLE_BUFFER_PUTC
(
&
input
->
string
,
c
))
return
0
;
}
}
}
static
int
sexp_get_hex_string
(
struct
sexp_input
*
input
)
{
/* Not implemented */
abort
();
}
static
int
sexp_get_base64_string
(
struct
sexp_input
*
input
)
{
struct
base64_decode_ctx
ctx
;
assert
(
input
->
mode
==
SEXP_ADVANCED
);
base64_decode_init
(
&
ctx
);
for
(;;)
{
uint8_t
c
;
uint8_t
decoded
;
if
(
sexp_get_char
(
input
,
&
c
)
<=
0
)
return
-
1
;
if
(
c
==
'|'
)
return
base64_decode_status
(
&
ctx
);
if
(
base64_decode_single
(
&
ctx
,
&
decoded
,
c
))
if
(
!
NETTLE_BUFFER_PUTC
(
&
input
->
string
,
decoded
))
return
0
;
}
}
static
int
sexp_get_atom_string
(
struct
sexp_input
*
input
,
uint8_t
c
)
{
assert
(
input
->
mode
==
SEXP_ADVANCED
);
if
(
!
TOKEN_CHAR
(
c
)
||
!
NETTLE_BUFFER_PUTC
(
&
input
->
string
,
c
))
return
0
;
while
(
(
c
=
sexp_get_token_char
(
input
))
>
0
)
{
if
(
!
NETTLE_BUFFER_PUTC
(
&
input
->
string
,
c
))
return
0
;
}
assert
(
input
->
string
.
size
);
return
1
;
}
static
int
sexp_get_string
(
struct
sexp_input
*
input
,
uint8_t
c
)
{
assert
(
input
->
mode
==
SEXP_ADVANCED
);
input
->
string
.
size
=
0
;
input
->
token
=
SEXP_STRING
;
switch
(
c
)
{
case
'\"'
:
return
sexp_get_quoted_string
(
input
);
case
'#'
:
return
sexp_get_hex_string
(
input
);
case
'|'
:
return
sexp_get_base64_string
(
input
);
default:
return
sexp_get_token_string
(
input
,
c
);
}
}
static
int
sexp_get_string_length
(
struct
sexp_input
*
input
,
unsigned
length
)
{
uint8_t
c
;
input
->
string
.
size
=
0
;
input
->
token
=
SEXP_STRING
;
if
(
!
length
)
{
/* There must ne no more digits */
if
(
sexp_get_char
(
input
,
&
c
)
<=
0
)
return
0
;
}
else
/* Get rest of digits */
for
(;;)
{
if
(
sexp_get_char
(
input
,
&
c
)
<=
0
)
return
0
;
if
(
c
<
0
||
<
>
9
)
break
;
/* FIXME: Check for overflow? */
length
=
length
*
10
+
c
-
'0'
;
}
switch
(
c
)
{
case
':'
:
/* Verbatim */
for
(;
length
;
length
--
)
if
(
sexp_get_char
(
input
,
&
c
)
<=
0
||
!
NETTLE_BUFFER_PUTC
(
&
input
->
string
,
c
))
return
0
;
return
1
;
case
'"'
:
if
(
input
->
mode
!=
SEXP_ADVANCED
)
return
0
;
for
(;
length
;
length
--
)
if
(
sexp_get_quoted_char
(
input
,
&
c
)
!=
1
||
!
NETTLE_BUFFER_PUTC
(
&
input
->
string
,
c
))
return
0
;
return
sexp_get_quoted_char
(
input
,
&
c
)
==
0
;
case
'#'
:
case
'|'
:
/* Not yet implemented */
abort
();
default:
return
0
;
}
}
/* Returns 1 on success, zero on failure */
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_START_LIST
;
return
1
;
case
')'
:
input
->
token
=
SEXP_END_LIST
;
return
1
;
case
'['
:
input
->
token
=
SEXP_DISPLAY_START
;
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
';'
:
/* 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
;
default:
/* Ought to be a string */
return
(
input
->
mode
==
SEXP_ADVANCED
)
&&
sexp_get_string
(
input
,
c
);
}
}
}
static
int
sexp_put_newline
(
struct
sexp_output
*
output
)
{
unsigned
i
;
if
(
putc
(
'\n'
,
output
->
f
)
<
0
)
return
0
;
for
(
i
=
0
;
i
<
output
->
indent
)
if
(
putc
(
' '
,
output
->
f
)
<
0
)
return
0
;
output
->
pos
=
output
->
indent
;
return
1
;
}
static
int
sexp_put_char
(
struct
sexp_output
*
output
,
uint8_t
c
)
{
output
->
pos
++
;
return
fputc
(
c
,
output
->
file
)
>=
0
;
}
static
int
sexp_put_data
(
struct
sexp_output
*
output
,
unsigned
length
,
uint8_t
data
)
{
if
(
fwrite
(
data
,
1
,
length
,
output
->
f
)
==
length
)
{
output
->
pos
+=
length
;
return
1
;
}
else
return
0
;
}
static
int
sexp_put_string
(
struct
sexp_output
*
output
,
struct
nettle_buffer
*
string
)
{
if
(
!
string
->
size
)
{
const
char
*
s
=
(
output
->
mode
==
SEXP_ADVANCED
)
?
"
\"\"
"
:
"0:"
;
output
->
pos
+=
2
;
return
2
==
fputs
(
s
,
output
->
f
);
}
if
(
output
->
mode
==
SEXP_ADVANCED
)
{
unsigned
i
;
int
token
=
(
string
.
buffer
[
0
]
<
'0'
||
string
.
buffer
[
0
]
>
'9'
);
int
quote_friendly
=
1
;
for
(
i
=
0
;
i
<
string
.
size
;
i
++
)
{
uint8_t
c
=
string
.
buffer
[
i
];
if
(
token
&
!
TOKEN_CHAR
(
c
))
token
=
0
;
if
(
quote_friendly
&&
(
c
<
0x20
||
c
>=
0x7f
))
quote_friendly
=
0
;
}
if
(
token
)
return
sexp_put_buffer
(
output
,
string
.
size
,
string
.
buffer
);
else
if
(
quote_friendly
)
{
output
->
pos
+=
2
;
return
sexp_put_char
(
output
,
'"'
)
&&
sexp_put_buffer
(
output
,
string
.
size
,
string
.
buffer
)
&&
sexp_put_char
(
output
,
'"'
);
}
else
{
#define DATA_PER_LINE 40
uint8_t
line
[
BASE64_ENCODE_LENGTH
(
DATA_PER_LINE
)
+
BASE64_ENCODE_FINAL_LENGTH
];
struct
base64_encode_ctx
ctx
;
unsigned
old_indent
=
output
->
indent
;
unsigned
i
;
output
->
indent
=
output
->
pos
+
1
;
if
(
!
sexp_put_char
(
output
,
'|'
))
return
0
;
base64_encode_init
(
&
ctx
);
for
(
i
=
0
;
i
+
DATA_PER_LINE
<
string
.
size
)
{
unsigned
done
=
base64_encode_update
(
&
ctx
,
line
,
DATA_PER_LINE
,
string
->
buffer
+
i
);
assert
(
done
<=
BASE64_ENCODE_LENGTH
(
DATA_PER_LINE
));
sexp_put_data
(
output
,
done
,
line
);
sexp_put_newline
(
output
);
}
output
->
indent
=
old_indent
;
done
=
base64_encode_update
(
&
ctx
,
line
,
string
.
size
-
i
,
string
->
buffer
+
i
);
done
+=
base64_encode_final
(
&
ctx
,
line
+
done
);
assert
(
done
<=
sizeof
(
line
));
return
sexp_put_data
(
output
,
done
,
line
)
&&
sexp_put_char
(
output
,
'}'
);
}
}
else
/* FIXME: Support transport mode */
return
fprintf
(
output
->
f
,
"%d:"
,
string
.
length
)
>
0
&&
sexp_put_string
(
output
,
string
.
size
,
string
.
buffer
);
}
static
void
sexp_put_start_list
(
struct
sexp_output
*
output
)
{
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment