Add expr.c, expr.h, plug in properly
- in callstack_pop, we don't free arch_ptr. That's because this doesn't
get copied over the clone. It's a mere coincidence that fork() doesn't
need to save register arguments, and this works.
- added copyright notices to files that this touches. This is based on
git blame. Only contributors of 10+ lines are added
- test suite adjusted to not include "void" type as "don't show this int".
Back ends in general need to know the exact type, so this never worked
anyway.
diff --git a/display_args.c b/display_args.c
index 872b1c9..8848b35 100644
--- a/display_args.c
+++ b/display_args.c
@@ -1,465 +1,429 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ * Copyright (C) 2006 Steve Fink
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <ctype.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
#include "common.h"
#include "proc.h"
+#include "value.h"
+#include "expr.h"
#include "type.h"
+#include "common.h"
-static int display_char(int what);
-static int display_string(enum tof type, Process *proc,
- void* addr, size_t maxlen);
-static int display_value(enum tof type, Process *proc,
- long value, struct arg_type_info *info,
- void *st, struct arg_type_info *st_info);
-static int display_unknown(enum tof type, Process *proc, long value);
-static int display_format(enum tof type, Process *proc, int arg_num);
+static int format_argument_2(FILE *stream, struct value *value,
+ struct value_dict *arguments);
-static size_t string_maxlength = INT_MAX;
-static size_t array_maxlength = INT_MAX;
-
-static long
-get_length(enum tof type, Process *proc, int len_spec,
- void *st, struct arg_type_info *st_info)
-{
- long len;
- struct arg_type_info info;
-
- if (len_spec > 0)
- return len_spec;
- if (type == LT_TOF_STRUCT) {
- umovelong(proc, st + st_info->u.struct_info.offset[-len_spec-1],
- &len, st_info->u.struct_info.fields[-len_spec-1]);
- return len;
+#define READER(NAME, TYPE) \
+ static int \
+ NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
+ { \
+ union { \
+ TYPE val; \
+ unsigned char buf[0]; \
+ } u; \
+ if (value_extract_buf(value, u.buf, arguments) < 0) \
+ return -1; \
+ *ret = u.val; \
+ return 0; \
}
- info.type = ARGTYPE_INT;
- return gimme_arg(type, proc, -len_spec-1, &info);
+READER(read_float, float)
+READER(read_double, double)
+
+#undef READER
+
+#define HANDLE_WIDTH(BITS) \
+ do { \
+ long l; \
+ if (value_extract_word(value, &l, arguments) < 0) \
+ return -1; \
+ int##BITS##_t i = l; \
+ switch (format) { \
+ case INT_FMT_unknown: \
+ if (i < -10000 || i > 10000) \
+ case INT_FMT_x: \
+ return fprintf(stream, "%#"PRIx##BITS, i); \
+ case INT_FMT_i: \
+ return fprintf(stream, "%"PRIi##BITS, i); \
+ case INT_FMT_u: \
+ return fprintf(stream, "%"PRIu##BITS, i); \
+ case INT_FMT_o: \
+ return fprintf(stream, "%"PRIo##BITS, i); \
+ } \
+ } while (0)
+
+enum int_fmt_t
+{
+ INT_FMT_i,
+ INT_FMT_u,
+ INT_FMT_o,
+ INT_FMT_x,
+ INT_FMT_unknown,
+};
+
+static int
+format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
+ struct value_dict *arguments)
+{
+ switch (type_sizeof(value->inferior, value->type)) {
+
+ case 1: HANDLE_WIDTH(8);
+ case 2: HANDLE_WIDTH(16);
+ case 4: HANDLE_WIDTH(32);
+ case 8: HANDLE_WIDTH(64);
+
+ default:
+ assert(!"unsupported integer width");
+ abort();
+
+ case -1:
+ return -1;
+ }
+}
+
+#undef HANDLE_WIDTH
+
+static int
+format_enum(FILE *stream, struct value *value, struct value_dict *arguments)
+{
+ long l;
+ if (value_extract_word(value, &l, arguments) < 0)
+ return -1;
+
+ const char *name = type_enum_get(value->type, l);
+ if (name != NULL)
+ return fprintf(stream, "%s", name);
+
+ return format_integer(stream, value, INT_FMT_i, arguments);
}
static int
-display_ptrto(enum tof type, Process *proc, long item,
- struct arg_type_info * info,
- void *st, struct arg_type_info *st_info) {
- struct arg_type_info temp;
- temp.type = ARGTYPE_POINTER;
- temp.u.ptr_info.info = info;
- return display_value(type, proc, item, &temp, st, st_info);
+acc_fprintf(int *countp, FILE *stream, const char *format, ...)
+{
+ va_list pa;
+ va_start(pa, format);
+ int i = vfprintf(stream, format, pa);
+ va_end(pa);
+
+ if (i >= 0)
+ *countp += i;
+ return i;
+}
+
+static int
+format_char(FILE *stream, struct value *value, struct value_dict *arguments)
+{
+ long lc;
+ if (value_extract_word(value, &lc, arguments) < 0)
+ return -1;
+ int c = (int)lc;
+
+ /* If this value is not wrapped in array, then this is not a
+ * string, and we need to display quotes. */
+ int quote = !(value->parent != NULL
+ && (value->parent->type->type == ARGTYPE_ARRAY
+ || value->parent->type->type == ARGTYPE_STRING
+ || value->parent->type->type == ARGTYPE_STRING_N));
+ int written = 0;
+ if (quote && acc_fprintf(&written, stream, "'") < 0)
+ return -1;
+
+ const char *fmt;
+ switch (c) {
+ case -1:
+ fmt = "EOF";
+ break;
+ case 0:
+ fmt = "\\0";
+ break;
+ case '\a':
+ fmt = "\\a";
+ break;
+ case '\b':
+ fmt = "\\b";
+ break;
+ case '\t':
+ fmt = "\\t";
+ break;
+ case '\n':
+ fmt = "\\n";
+ break;
+ case '\v':
+ fmt = "\\v";
+ break;
+ case '\f':
+ fmt = "\\f";
+ break;
+ case '\r':
+ fmt = "\\r";
+ break;
+ case '\\':
+ fmt = "\\\\";
+ break;
+ default:
+ if (isprint(c) || c == ' ')
+ fmt = "%c";
+ else if (acc_fprintf(&written, stream, "\\%03o",
+ (unsigned char)c) < 0)
+ return -1;
+ else
+ fmt = NULL;
+ }
+
+ if (fmt != NULL && acc_fprintf(&written, stream, fmt, c) < 0)
+ return -1;
+ if (quote && acc_fprintf(&written, stream, "'") < 0)
+ return -1;
+ return written;
+}
+
+static int
+format_floating(FILE *stream, struct value *value, struct value_dict *arguments)
+{
+ switch (value->type->type) {
+ float f;
+ double d;
+ case ARGTYPE_FLOAT:
+ if (read_float(value, &f, arguments) < 0)
+ return -1;
+ return fprintf(stream, "%f", (double)f);
+ case ARGTYPE_DOUBLE:
+ if (read_double(value, &d, arguments) < 0)
+ return -1;
+ return fprintf(stream, "%f", d);
+ default:
+ abort();
+ }
+}
+
+static int
+format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
+{
+ int written = 0;
+ if (acc_fprintf(&written, stream, "{ ") < 0)
+ return -1;
+ size_t i;
+ for (i = 0; i < type_struct_size(value->type); ++i) {
+ if (i > 0 && acc_fprintf(&written, stream, ", ") < 0)
+ return -1;
+
+ struct value element;
+ if (value_init_element(&element, value, i) < 0)
+ return -1;
+ int o = format_argument_2(stream, &element, arguments);
+ if (o < 0)
+ return -1;
+ written += o;
+ }
+ if (acc_fprintf(&written, stream, " }") < 0)
+ return -1;
+ return written;
+}
+
+int
+format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
+{
+ struct value element;
+ if (value_init_deref(&element, value) < 0)
+ return -1;
+ return format_argument_2(stream, &element, arguments);
}
/*
- * addr - A pointer to the first element of the array
+ * LENGTH is an expression whose evaluation will yield the actual
+ * length of the array.
*
- * The function name is used to indicate that we're not actually
- * looking at an 'array', which is a contiguous region of memory
- * containing a sequence of elements of some type; instead, we have a
- * pointer to that region of memory.
+ * MAXLEN is the actual maximum length that we care about
+ *
+ * BEFORE if LENGTH>MAXLEN, we display ellipsis. We display it before
+ * the closing parenthesis if BEFORE, otherwise after it.
+ *
+ * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
+ * delimiter.
*/
-static int
-display_arrayptr(enum tof type, Process *proc,
- void *addr, struct arg_type_info * info,
- void *st, struct arg_type_info *st_info) {
- int len = 0;
- size_t i;
- size_t array_len;
-
- if (addr == NULL)
- return fprintf(options.output, "NULL");
-
- array_len = get_length(type, proc, info->u.array_info.len_spec,
- st, st_info);
- len += fprintf(options.output, "[ ");
- for (i = 0; i < options.arraylen && i < array_maxlength && i < array_len; i++) {
- struct arg_type_info *elt_type = info->u.array_info.elt_type;
- size_t elt_size = info->u.array_info.elt_size;
- if (i != 0)
- len += fprintf(options.output, ", ");
- if (options.debug)
- len += fprintf(options.output, "%p=", addr);
- len +=
- display_ptrto(type, proc, (long) addr, elt_type, st, st_info);
- addr += elt_size;
- }
- if (i < array_len)
- len += fprintf(options.output, "...");
- len += fprintf(options.output, " ]");
- return len;
-}
-
-/* addr - A pointer to the beginning of the memory region occupied by
- * the struct (aka a pointer to the struct)
- */
-static int
-display_structptr(enum tof type, Process *proc,
- void *addr, struct arg_type_info * info) {
- int i;
- struct arg_type_info *field;
- int len = 0;
-
- if (addr == NULL)
- return fprintf(options.output, "NULL");
-
- len += fprintf(options.output, "{ ");
- for (i = 0; (field = info->u.struct_info.fields[i]) != NULL; i++) {
- if (i != 0)
- len += fprintf(options.output, ", ");
- if (options.debug)
- len +=
- fprintf(options.output, "%p=",
- addr + info->u.struct_info.offset[i]);
- len +=
- display_ptrto(LT_TOF_STRUCT, proc,
- (long) addr + info->u.struct_info.offset[i],
- field, addr, info);
- }
- len += fprintf(options.output, " }");
-
- return len;
-}
-
-static int
-display_pointer(enum tof type, Process *proc, long value,
- struct arg_type_info * info,
- void *st, struct arg_type_info *st_info) {
- long pointed_to;
- struct arg_type_info *inner = info->u.ptr_info.info;
-
- if (inner->type == ARGTYPE_ARRAY) {
- return display_arrayptr(type, proc, (void*) value, inner,
- st, st_info);
- } else if (inner->type == ARGTYPE_STRUCT) {
- return display_structptr(type, proc, (void *) value, inner);
- } else {
- if (value == 0)
- return fprintf(options.output, "NULL");
- else if (umovelong (proc, (void *) value, &pointed_to,
- info->u.ptr_info.info) < 0)
- return fprintf(options.output, "?");
- else
- return display_value(type, proc, pointed_to, inner,
- st, st_info);
- }
-}
-
-static int
-display_enum(enum tof type, Process *proc,
- struct arg_type_info *info, long value) {
- size_t ii;
- for (ii = 0; ii < info->u.enum_info.entries; ++ii) {
- if (info->u.enum_info.values[ii] == value)
- return fprintf(options.output, "%s", info->u.enum_info.keys[ii]);
- }
-
- return display_unknown(type, proc, value);
-}
-
-/* Args:
- type - syscall or shared library function or memory
- proc - information about the traced process
- value - the value to display
- info - the description of the type to display
- st - if the current value is a struct member, the address of the struct
- st_info - type of the above struct
-
- Those last two parameters are used for structs containing arrays or
- strings whose length is given by another structure element.
-*/
int
-display_value(enum tof type, Process *proc,
- long value, struct arg_type_info *info,
- void *st, struct arg_type_info *st_info) {
- int tmp;
-
- switch (info->type) {
- case ARGTYPE_VOID:
- return 0;
- case ARGTYPE_INT:
- return fprintf(options.output, "%d", (int) value);
- case ARGTYPE_UINT:
- return fprintf(options.output, "%u", (unsigned) value);
- case ARGTYPE_LONG:
- if (proc->mask_32bit)
- return fprintf(options.output, "%d", (int) value);
- else
- return fprintf(options.output, "%ld", value);
- case ARGTYPE_ULONG:
- if (proc->mask_32bit)
- return fprintf(options.output, "%u", (unsigned) value);
- else
- return fprintf(options.output, "%lu", (unsigned long) value);
- case ARGTYPE_OCTAL:
- return fprintf(options.output, "0%o", (unsigned) value);
- case ARGTYPE_CHAR:
- tmp = fprintf(options.output, "'");
- tmp += display_char(value == -1 ? value : (char) value);
- tmp += fprintf(options.output, "'");
- return tmp;
- case ARGTYPE_SHORT:
- return fprintf(options.output, "%hd", (short) value);
- case ARGTYPE_USHORT:
- return fprintf(options.output, "%hu", (unsigned short) value);
- case ARGTYPE_FLOAT: {
- union { long l; float f; double d; } cvt;
- cvt.l = value;
- return fprintf(options.output, "%f", cvt.f);
- }
- case ARGTYPE_DOUBLE: {
- union { long l; float f; double d; } cvt;
- cvt.l = value;
- return fprintf(options.output, "%lf", cvt.d);
- }
- case ARGTYPE_ADDR:
- if (!value)
- return fprintf(options.output, "NULL");
- else
- return fprintf(options.output, "0x%08lx", value);
- case ARGTYPE_FORMAT:
- fprintf(stderr, "Should never encounter a format anywhere but at the top level (for now?)\n");
- exit(1);
- case ARGTYPE_STRING:
- return display_string(type, proc, (void*) value,
- string_maxlength);
- case ARGTYPE_STRING_N:
- return display_string(type, proc, (void*) value,
- get_length(type, proc,
- info->u.string_n_info.size_spec, st, st_info));
- case ARGTYPE_ARRAY:
- return fprintf(options.output, "<array without address>");
- case ARGTYPE_ENUM:
- return display_enum(type, proc, info, value);
- case ARGTYPE_STRUCT:
- return fprintf(options.output, "<struct without address>");
- case ARGTYPE_POINTER:
- return display_pointer(type, proc, value, info,
- st, st_info);
- case ARGTYPE_UNKNOWN:
- default:
- return display_unknown(type, proc, value);
- }
-}
-
-int
-display_arg(enum tof type, Process *proc, int arg_num,
- struct arg_type_info * info)
+format_array(FILE *stream, struct value *value, struct value_dict *arguments,
+ struct expr_node *length, size_t maxlen, int before,
+ const char *open, const char *close, const char *delim)
{
- long arg;
+ /* We need "long" to be long enough to cover the whole address
+ * space. */
+ typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
+ long l = options.strlen;
+ if (length != NULL) /* XXX emulate node ZERO before it lands */
+ if (expr_eval_word(length, value, arguments, &l) < 0)
+ return -1;
+ size_t len = (size_t)l;
- if (info->type == ARGTYPE_VOID) {
- return 0;
- } else if (info->type == ARGTYPE_FORMAT) {
- return display_format(type, proc, arg_num);
- } else {
- arg = gimme_arg(type, proc, arg_num, info);
- return display_value(type, proc, arg, info, NULL, NULL);
- }
-}
+ int written = 0;
+ if (acc_fprintf(&written, stream, "%s", open) < 0)
+ return -1;
-static int
-display_char(int what) {
- switch (what) {
- case -1:
- return fprintf(options.output, "EOF");
- case '\r':
- return fprintf(options.output, "\\r");
- case '\n':
- return fprintf(options.output, "\\n");
- case '\t':
- return fprintf(options.output, "\\t");
- case '\b':
- return fprintf(options.output, "\\b");
- case '\\':
- return fprintf(options.output, "\\\\");
- default:
- if (isprint(what)) {
- return fprintf(options.output, "%c", what);
- } else {
- return fprintf(options.output, "\\%03o", (unsigned char)what);
- }
- }
-}
-
-#define MIN(a,b) (((a)<(b)) ? (a) : (b))
-
-static int
-display_string(enum tof type, Process *proc, void *addr,
- size_t maxlength) {
- unsigned char *str1;
size_t i;
- int len = 0;
-
- if (!addr) {
- return fprintf(options.output, "NULL");
- }
-
- str1 = malloc(MIN(options.strlen, maxlength) + 3);
- if (!str1) {
- return fprintf(options.output, "???");
- }
- umovestr(proc, addr, MIN(options.strlen, maxlength) + 1, str1);
- len = fprintf(options.output, "\"");
- for (i = 0; i < MIN(options.strlen, maxlength); i++) {
- if (str1[i]) {
- len += display_char(str1[i]);
- } else {
+ for (i = 0; i < len && i <= maxlen; ++i) {
+ if (i == maxlen) {
+ if (before && acc_fprintf(&written, stream, "...") < 0)
+ return -1;
break;
}
+
+ if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
+ return -1;
+
+ struct value element;
+ if (value_init_element(&element, value, i) < 0)
+ return -1;
+ if (value_is_zero(&element, arguments)) /* XXX emulate ZERO */
+ break;
+ int o = format_argument_2(stream, &element, arguments);
+ if (o < 0)
+ return -1;
+ written += o;
}
- len += fprintf(options.output, "\"");
- if (str1[i] && (options.strlen <= maxlength)) {
- len += fprintf(options.output, "...");
- }
- free(str1);
- return len;
+ if (acc_fprintf(&written, stream, "%s", close) < 0)
+ return -1;
+ if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
+ return -1;
+
+ return written;
}
static int
-display_unknown(enum tof type, Process *proc, long value) {
- if (proc->mask_32bit) {
- if ((int)value < 1000000 && (int)value > -1000000)
- return fprintf(options.output, "%d", (int)value);
- else
- return fprintf(options.output, "%p", (void *)value);
- } else if (value < 1000000 && value > -1000000) {
- return fprintf(options.output, "%ld", value);
+format_argument_2(FILE *stream, struct value *value,
+ struct value_dict *arguments)
+{
+ struct expr_node *length = NULL;
+ switch (value->type->type) {
+ case ARGTYPE_VOID:
+ return fprintf(stream, "<void>");
+
+ case ARGTYPE_UNKNOWN:
+ return format_integer(stream, value, INT_FMT_unknown,
+ arguments);
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_LONG:
+ return format_integer(stream, value, INT_FMT_i, arguments);
+
+ case ARGTYPE_USHORT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_ULONG:
+ return format_integer(stream, value, INT_FMT_u, arguments);
+
+ case ARGTYPE_OCTAL:
+ return format_integer(stream, value, INT_FMT_o, arguments);
+
+ case ARGTYPE_CHAR:
+ return format_char(stream, value, arguments);
+
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ return format_floating(stream, value, arguments);
+
+ case ARGTYPE_STRUCT:
+ return format_struct(stream, value, arguments);
+
+ case ARGTYPE_POINTER:
+ if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
+ return format_pointer(stream, value, arguments);
+ case ARGTYPE_ADDR:
+ case ARGTYPE_FILE:
+ return format_integer(stream, value, INT_FMT_x, arguments);
+
+ case ARGTYPE_ARRAY:
+ if (value->type->u.array_info.elt_type->type != ARGTYPE_CHAR)
+ return format_array(stream, value, arguments,
+ value->type->u.array_info.length,
+ options.arraylen, 1,
+ "[ ", " ]", ", ");
+
+ return format_array(stream, value, arguments,
+ value->type->u.array_info.length,
+ options.strlen, 0, "\"", "\"", "");
+
+ case ARGTYPE_STRING_N:
+ length = value->type->u.string_n_info.length;
+ /* fall-through */
+ case ARGTYPE_FORMAT:
+ case ARGTYPE_STRING: {
+ /* Strings are in fact char pointers. Smuggle in the
+ * pointer here. */
+
+ struct arg_type_info info[2];
+ type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0,
+ length, 0);
+ type_init_pointer(&info[0], &info[1], 0);
+
+ struct value tmp;
+ value_clone(&tmp, value);
+ value_set_type(&tmp, info, 0);
+
+ int ret = format_argument_2(stream, &tmp, arguments);
+
+ value_destroy(&tmp);
+ type_destroy(&info[0]);
+ type_destroy(&info[1]);
+ return ret;
+ }
+
+ case ARGTYPE_ENUM:
+ return format_enum(stream, value, arguments);
+
+ case ARGTYPE_COUNT:
+ abort();
+ }
+ abort();
+}
+
+int
+format_argument(FILE *stream, struct value *value, struct value_dict *arguments)
+{
+ /* Arrays decay into pointers for purposes of argument
+ * passing. Before the proper support for this lands, wrap
+ * top-level arrays in pointers here. */
+ if (value->type->type == ARGTYPE_ARRAY) {
+
+ struct arg_type_info info;
+ type_init_pointer(&info, value->type, 0);
+
+ struct value tmp;
+ value_clone(&tmp, value);
+ value_set_type(&tmp, &info, 0);
+
+ int ret = format_argument_2(stream, &tmp, arguments);
+
+ value_destroy(&tmp);
+ type_destroy(&info);
+
+ return ret;
+
} else {
- return fprintf(options.output, "%p", (void *)value);
+ return format_argument_2(stream, value, arguments);
}
}
-
-static int
-display_format(enum tof type, Process *proc, int arg_num) {
- void *addr;
- unsigned char *str1;
- int i;
- size_t len = 0;
- struct arg_type_info info;
-
- info.type = ARGTYPE_POINTER;
- addr = (void *)gimme_arg(type, proc, arg_num, &info);
- if (!addr) {
- return fprintf(options.output, "NULL");
- }
-
- str1 = malloc(MIN(options.strlen, string_maxlength) + 3);
- if (!str1) {
- return fprintf(options.output, "???");
- }
- umovestr(proc, addr, MIN(options.strlen, string_maxlength) + 1, str1);
- len = fprintf(options.output, "\"");
- for (i = 0; len < MIN(options.strlen, string_maxlength) + 1; i++) {
- if (str1[i]) {
- len += display_char(str1[i]);
- } else {
- break;
- }
- }
- len += fprintf(options.output, "\"");
- if (str1[i] && (options.strlen <= string_maxlength)) {
- len += fprintf(options.output, "...");
- }
- for (i = 0; str1[i]; i++) {
- if (str1[i] == '%') {
- int is_long = 0;
- while (1) {
- unsigned char c = str1[++i];
- if (c == '%') {
- break;
- } else if (!c) {
- break;
- } else if (strchr("lzZtj", c)) {
- is_long++;
- if (c == 'j')
- is_long++;
- if (is_long > 1
- && (sizeof(long) < sizeof(long long)
- || proc->mask_32bit)) {
- len += fprintf(options.output, ", ...");
- str1[i + 1] = '\0';
- break;
- }
- } else if (c == 'd' || c == 'i') {
- info.type = ARGTYPE_LONG;
- if (!is_long || proc->mask_32bit)
- len +=
- fprintf(options.output, ", %d",
- (int)gimme_arg(type, proc, ++arg_num, &info));
- else
- len +=
- fprintf(options.output, ", %ld",
- gimme_arg(type, proc, ++arg_num, &info));
- break;
- } else if (c == 'u') {
- info.type = ARGTYPE_LONG;
- if (!is_long || proc->mask_32bit)
- len +=
- fprintf(options.output, ", %u",
- (int)gimme_arg(type, proc, ++arg_num, &info));
- else
- len +=
- fprintf(options.output, ", %lu",
- gimme_arg(type, proc, ++arg_num, &info));
- break;
- } else if (c == 'o') {
- info.type = ARGTYPE_LONG;
- if (!is_long || proc->mask_32bit)
- len +=
- fprintf(options.output, ", 0%o",
- (int)gimme_arg(type, proc, ++arg_num, &info));
- else
- len +=
- fprintf(options.output, ", 0%lo",
- gimme_arg(type, proc, ++arg_num, &info));
- break;
- } else if (c == 'x' || c == 'X') {
- info.type = ARGTYPE_LONG;
- if (!is_long || proc->mask_32bit)
- len +=
- fprintf(options.output, ", %#x",
- (int)gimme_arg(type, proc, ++arg_num, &info));
- else
- len +=
- fprintf(options.output, ", %#lx",
- gimme_arg(type, proc, ++arg_num, &info));
- break;
- } else if (strchr("eEfFgGaACS", c)
- || (is_long
- && (c == 'c' || c == 's'))) {
- len += fprintf(options.output, ", ...");
- str1[i + 1] = '\0';
- break;
- } else if (c == 'c') {
- info.type = ARGTYPE_LONG;
- len += fprintf(options.output, ", '");
- len +=
- display_char((int)
- gimme_arg(type, proc, ++arg_num, &info));
- len += fprintf(options.output, "'");
- break;
- } else if (c == 's') {
- info.type = ARGTYPE_POINTER;
- len += fprintf(options.output, ", ");
- len +=
- display_string(type, proc,
- (void *)gimme_arg(type, proc, ++arg_num, &info),
- string_maxlength);
- break;
- } else if (c == 'p' || c == 'n') {
- info.type = ARGTYPE_POINTER;
- len +=
- fprintf(options.output, ", %p",
- (void *)gimme_arg(type, proc, ++arg_num, &info));
- break;
- } else if (c == '*') {
- info.type = ARGTYPE_LONG;
- len +=
- fprintf(options.output, ", %d",
- (int)gimme_arg(type, proc, ++arg_num, &info));
- }
- }
- }
- }
- free(str1);
- return len;
-}