Skip to content
Snippets Groups Projects
Commit d4a193cf authored by Niels Möller's avatar Niels Möller
Browse files

* format.c (ssh_vformat_length): Added 'd' modifier, for

sexp-style length prefixes.
(ssh_vformat_write): -"-

Rev: src/format.c:1.22
Rev: src/format.h:1.17
parent 8a3724a0
No related branches found
No related tags found
No related merge requests found
...@@ -74,6 +74,8 @@ void ssh_format_write(const char *format, UINT32 length, UINT8 *buffer, ...) ...@@ -74,6 +74,8 @@ void ssh_format_write(const char *format, UINT32 length, UINT8 *buffer, ...)
va_end(args); va_end(args);
} }
static int size_in_decimal(UINT32 n);
static int write_decimal_length(UINT8 *buffer, UINT32 n);
UINT32 ssh_vformat_length(const char *f, va_list args) UINT32 ssh_vformat_length(const char *f, va_list args)
{ {
...@@ -84,20 +86,29 @@ UINT32 ssh_vformat_length(const char *f, va_list args) ...@@ -84,20 +86,29 @@ UINT32 ssh_vformat_length(const char *f, va_list args)
if (*f == '%') if (*f == '%')
{ {
int literal = 0; int literal = 0;
f++; int decimal = 0;
while(*f)
while(*++f)
{ {
if (*f == 'l') switch (*f)
{ {
case 'l':
literal = 1; literal = 1;
f++; break;
} case 'd':
else if (*f == 'f') decimal = 1;
{ break;
f++; case 'f':
/* Do nothing */
break;
default:
goto end_options;
} }
else break;
} }
end_options:
if (literal && decimal)
fatal("Internal error!\n");
switch(*f) switch(*f)
{ {
...@@ -118,54 +129,83 @@ UINT32 ssh_vformat_length(const char *f, va_list args) ...@@ -118,54 +129,83 @@ UINT32 ssh_vformat_length(const char *f, va_list args)
f++; f++;
length += 4; length += 4;
break; break;
#if 0
case 'd':
length += size_in_decimal(va_arg(args, UINT32));
break;
#endif
case 's': case 's':
{ {
length += va_arg(args, UINT32); /* String length */ UINT32 l = va_arg(args, UINT32); /* String length */
(void) va_arg(args, UINT8 *); /* data */ (void) va_arg(args, UINT8 *); /* data */
f++; f++;
if (!literal) length += l;
if (decimal)
length += size_in_decimal(l) + 1;
else if (!literal)
length += 4; length += 4;
break; break;
} }
case 'S': case 'S':
length += va_arg(args, struct lsh_string *)->length; {
struct lsh_string *s = va_arg(args, struct lsh_string *);
length += s->length;
f++; f++;
if (!literal) if (decimal)
length += size_in_decimal(s->length) + 1;
else if (!literal)
length += 4; length += 4;
break; break;
}
case 'z': case 'z':
length += strlen(va_arg(args, char*)); {
unsigned l = strlen(va_arg(args, char*));
length += l
f++; f++;
if (!literal) if (decimal)
length += size_in_decimal(l) + 1;
else if (!literal)
length += 4; length += 4;
break; break;
}
case 'r': case 'r':
length += va_arg(args, UINT32); {
UINT32 l = va_arg(args, UINT32);
length += l
(void) va_arg(args, UINT8 **); /* pointer */ (void) va_arg(args, UINT8 **); /* pointer */
f++; f++;
if (!literal) if (decimal)
length += size_in_decimal(l) + 1;
else if (!literal)
length += 4; length += 4;
break; break;
}
case 'a': case 'a':
{ {
int atom = va_arg(args, int); int atom = va_arg(args, int);
int l;
assert(atom); assert(atom);
length += get_atom_length(atom); l = get_atom_length(l);
length += l;
if (!literal) if (decimal)
length += size_in_decimal(l) + 1;
else if (!literal)
length += 4; length += 4;
f++; f++;
break; break;
} }
...@@ -174,6 +214,9 @@ UINT32 ssh_vformat_length(const char *f, va_list args) ...@@ -174,6 +214,9 @@ UINT32 ssh_vformat_length(const char *f, va_list args)
struct int_list *l = va_arg(args, struct int_list *); struct int_list *l = va_arg(args, struct int_list *);
UINT32 n, i; UINT32 n, i;
if (decimal)
fatal("ssh_format: Decimal lengths not supported for %A\n");
for(n = i =0; i < LIST_LENGTH(l); i++) for(n = i =0; i < LIST_LENGTH(l); i++)
{ {
if (LIST(l)[i]) if (LIST(l)[i])
...@@ -198,8 +241,11 @@ UINT32 ssh_vformat_length(const char *f, va_list args) ...@@ -198,8 +241,11 @@ UINT32 ssh_vformat_length(const char *f, va_list args)
/* Calculate length of written number */ /* Calculate length of written number */
length += bignum_format_s_length(n); length += bignum_format_s_length(n);
if (!literal) if (decimal)
length += size_in_decimal(l) + 1;
else if (!literal)
length += 4; length += 4;
f++; f++;
break; break;
} }
...@@ -265,12 +311,16 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -265,12 +311,16 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
break; break;
} }
case 's': case 's':
{ {
UINT32 length = va_arg(args, UINT32); UINT32 length = va_arg(args, UINT32);
UINT8 *data = va_arg(args, UINT8 *); UINT8 *data = va_arg(args, UINT8 *);
if (!literal) if (decimal)
buffer += write_decimal_length(buffer, length);
else if (!literal)
{ {
WRITE_UINT32(buffer, length); WRITE_UINT32(buffer, length);
buffer += 4; buffer += 4;
...@@ -286,7 +336,10 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -286,7 +336,10 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
{ {
struct lsh_string *s = va_arg(args, struct lsh_string *); struct lsh_string *s = va_arg(args, struct lsh_string *);
if (!literal) if (decimal)
buffer += write_decimal_length(buffer, length);
else if (!literal)
{ {
WRITE_UINT32(buffer, s->length); WRITE_UINT32(buffer, s->length);
buffer += 4; buffer += 4;
...@@ -305,6 +358,10 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -305,6 +358,10 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
{ {
char *s = va_arg(args, char *); char *s = va_arg(args, char *);
UINT32 length = strlen(s); UINT32 length = strlen(s);
if (decimal)
buffer += write_decimal_length(buffer, length);
if (!literal) if (!literal)
{ {
WRITE_UINT32(buffer, length); WRITE_UINT32(buffer, length);
...@@ -322,7 +379,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -322,7 +379,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
UINT32 length = va_arg(args, UINT32); UINT32 length = va_arg(args, UINT32);
UINT8 **p = va_arg(args, UINT8 **); UINT8 **p = va_arg(args, UINT8 **);
if (!literal) if (decimal)
buffer += write_decimal_length(buffer, length);
else if (!literal)
{ {
WRITE_UINT32(buffer, length); WRITE_UINT32(buffer, length);
buffer += 4; buffer += 4;
...@@ -345,7 +404,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -345,7 +404,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
length = get_atom_length(atom); length = get_atom_length(atom);
if (!literal) if (decimal)
buffer += write_decimal_length(buffer, length);
else if (!literal)
{ {
WRITE_UINT32(buffer, length); WRITE_UINT32(buffer, length);
buffer += 4; buffer += 4;
...@@ -363,6 +424,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -363,6 +424,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
UINT8 *start = buffer; /* Where to store the length */ UINT8 *start = buffer; /* Where to store the length */
UINT32 n, i; UINT32 n, i;
if (decimal)
fatal("ssh_format: Decimal lengths not supported for %A\n");
if (!literal) if (!literal)
buffer += 4; buffer += 4;
...@@ -397,7 +461,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -397,7 +461,9 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
UINT32 length; UINT32 length;
UINT8 *start = buffer; /* Where to store the length */ UINT8 *start = buffer; /* Where to store the length */
if (!literal) if (decimal)
buffer += write_decimal_length(buffer, length);
else if (!literal)
buffer += 4; buffer += 4;
length = bignum_format_s(n, buffer); length = bignum_format_s(n, buffer);
...@@ -421,6 +487,47 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args) ...@@ -421,6 +487,47 @@ void ssh_vformat_write(const char *f, UINT32 size, UINT8 *buffer, va_list args)
assert(buffer == start + size); assert(buffer == start + size);
} }
static int size_in_decimal(UINT32 n)
{
int i;
int e;
/* Table of 10^(2^n) */
static UINT32 powers[] = { 10UL, 100UL, 10000UL, 100000000UL };
#define SIZE (sizeof(powers) / sizeof(powers[0]))
/* Determine the smallest e such that n < 10^e */
for (i = SIZE - 1 , e = 0; i >= 0; i--)
{
if (n >= powers[i])
{
e += 1UL << i;
n /= powers[i];
}
}
#undef SIZE
return e+1;
}
static int write_decimal_length(UINT8 *buffer, UINT32 n)
{
int length = size_in_decimal(n);
int i;
for (i = 0; i<length; i++)
{
buffer[length - i - 1] = '0' + n % 10;
n /= 10;
}
buffer[length] = ':';
return length + 1;
}
/* These functions add an extra NUL-character at the end of the string /* These functions add an extra NUL-character at the end of the string
* (not included in the length), to make it possible to pass the * (not included in the length), to make it possible to pass the
* string directly to C library functions. */ * string directly to C library functions. */
...@@ -454,3 +561,4 @@ struct lsh_string *make_cstring(struct lsh_string *s, int free) ...@@ -454,3 +561,4 @@ struct lsh_string *make_cstring(struct lsh_string *s, int free)
lsh_string_free(s); lsh_string_free(s);
return res; return res;
} }
...@@ -37,7 +37,9 @@ ...@@ -37,7 +37,9 @@
* *
* %c Insert an 8-bit character * %c Insert an 8-bit character
* *
* %i Insert an 32-bit integer, in network byte order * %i Insert a 32-bit integer, in network byte order
*
* %d Insert a 32-bit integer, in decimal
* *
* %s Insert a string, given by a length and a pointer. * %s Insert a string, given by a length and a pointer.
* *
...@@ -58,13 +60,17 @@ ...@@ -58,13 +60,17 @@
* *
* %n Insert a string containing a bignum. * %n Insert a string containing a bignum.
* *
* There are two valid modifiers: * There are three valid modifiers:
* *
* "l" (as in literal). It is applicable to the s, a, A, n and r * "l" (as in literal). It is applicable to the s, a, A, n and r
* specifiers, and outputs strings *without* a length field. * specifiers, and outputs strings *without* a length field.
* *
* "e" (as in expression). Formats the input string using sexp syntax;
* i.e. prefixed with the length in decimal.
*
* "f" (as in free). Frees the input string after it has been copied. * "f" (as in free). Frees the input string after it has been copied.
* Applicable to %S only. */ * Applicable to %S only.
*/
struct lsh_string *ssh_format(const char *format, ...); struct lsh_string *ssh_format(const char *format, ...);
UINT32 ssh_format_length(const char *format, ...); UINT32 ssh_format_length(const char *format, ...);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment