summaryrefslogtreecommitdiff
path: root/printf.c
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2013-11-11 02:24:42 +0100
committerChanho Park <chanho61.park@samsung.com>2014-08-22 20:38:23 +0900
commite6c25f6799825812e2b87990333c649ba796f600 (patch)
tree8d68002e600f53c912433310ced3b13fb2883b95 /printf.c
parentf292cf4e52c73fcc3b63ba2b032d17822f63e6e8 (diff)
downloadltrace-e6c25f6799825812e2b87990333c649ba796f600.tar.gz
ltrace-e6c25f6799825812e2b87990333c649ba796f600.tar.bz2
ltrace-e6c25f6799825812e2b87990333c649ba796f600.zip
Support wide character strings
- "string" lens and "format" pack were extended such that using an integer as underlying array type denotes a wide character string. - several prototypes from wchar.h were added to libc.so.conf. - ltrace.conf.5 was updated
Diffstat (limited to 'printf.c')
-rw-r--r--printf.c61
1 files changed, 49 insertions, 12 deletions
diff --git a/printf.c b/printf.c
index 52b212c..daa3683 100644
--- a/printf.c
+++ b/printf.c
@@ -22,7 +22,9 @@
*/
#include <assert.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include "printf.h"
#include "type.h"
@@ -39,6 +41,7 @@ struct param_enum {
char *format;
char const *ptr;
char const *end;
+ size_t width;
};
static struct param_enum *
@@ -47,12 +50,30 @@ param_printf_init(struct value *cb_args, size_t nargs,
{
assert(nargs == 1);
- /* We expect a char array pointer. */
+ struct process *proc = cb_args[0].inferior;
+ assert(proc != NULL);
+
+ /* We expect a pointer to array. */
if (cb_args->type->type != ARGTYPE_POINTER
- || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY
- || (cb_args->type->u.ptr_info.info->u.array_info.elt_type->type
- != ARGTYPE_CHAR))
+ || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY)
+ return NULL;
+
+ /* The element type should be either character (for narrow
+ * strings) or an integral type (for wide strings). */
+ struct arg_type_info *et
+ = cb_args->type->u.ptr_info.info->u.array_info.elt_type;
+ switch (et->type) {
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ break;
+ default:
return NULL;
+ }
struct param_enum *self = malloc(sizeof(*self));
if (self == NULL) {
@@ -60,10 +81,12 @@ param_printf_init(struct value *cb_args, size_t nargs,
free(self);
return NULL;
}
+ self->width = type_sizeof(proc, et);
+ if (self->width == (size_t) -1)
+ goto fail;
if (value_init_deref(&self->array, cb_args) < 0)
goto fail;
-
assert(self->array.type->type == ARGTYPE_ARRAY);
self->format = (char *)value_get_data(&self->array, arguments);
@@ -189,14 +212,29 @@ param_printf_next(struct param_enum *self, struct arg_type_info *infop,
size_t len_buf_len = 0;
struct lens *lens = NULL;
- for (; self->ptr < self->end; ++self->ptr) {
+ for (; self->ptr < self->end; self->ptr += self->width) {
+ union {
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ char buf[0];
+ } u;
+ memcpy(u.buf, self->ptr, self->width);
+ switch (self->width) {
+ case 1: u.u64 = u.u8; break;
+ case 2: u.u64 = u.u16; break;
+ case 4: u.u64 = u.u32; break;
+ }
+ uint64_t c = u.u64;
+
if (!self->percent) {
- if (*self->ptr == '%')
+ if (c == '%')
self->percent = 1;
continue;
}
- switch (*self->ptr) {
+ switch (c) {
case '#': case ' ': case '-':
case '+': case 'I': case '\'':
/* These are only important for formatting,
@@ -214,7 +252,7 @@ param_printf_next(struct param_enum *self, struct arg_type_info *infop,
= malloc(sizeof(*self->future_length));
if (self->future_length != NULL) {
- ++self->ptr;
+ self->ptr += self->width;
format_type = ARGTYPE_INT;
break;
}
@@ -227,7 +265,7 @@ param_printf_next(struct param_enum *self, struct arg_type_info *infop,
* this to attach the appropriate string
* length expression. */
if (len_buf_len < sizeof(len_buf) - 1)
- len_buf[len_buf_len++] = *self->ptr;
+ len_buf[len_buf_len++] = c;
continue;
case 'h':
@@ -299,8 +337,7 @@ param_printf_next(struct param_enum *self, struct arg_type_info *infop,
lng++;
case 's':
format_type = ARGTYPE_ARRAY;
- /* XXX "ls" means wchar_t string. */
- elt_type = ARGTYPE_CHAR;
+ elt_type = lng == 0 ? ARGTYPE_CHAR : ARGTYPE_INT;
self->percent = 0;
lens = &string_lens;
break;