Add enum lens, drop ARGTYPE_ENUM
diff --git a/ChangeLog b/ChangeLog
index fbaa9dc..cd35662 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2012-01-09 Petr Machata <pmachata@redhat.com>
+ * lens_enum.c, lens_enum.h: New files
+ * type.c, type.h (enum arg_type): Drop ARGTYPE_ENUM
+ (type_is_integral, type_is_signed): New functions
+ * read_config_file.c: Rewrite enum parsing
+ * testsuite/ltrace.main/parameters*: Test it
+ * lens_default.c: Drop support for ARGTYPE_ENUM
+ * sysdeps/linux-gnu/x86_64/trace.c: Likewise
+
+2012-01-09 Petr Machata <pmachata@redhat.com>
+
* sysdeps/linux-gnu/*/arch.h
(ARCH_ENDIAN_BIG, ARCH_ENDIAN_LITTLE): Declare either at each backend
diff --git a/Makefile.am b/Makefile.am
index ceafdf1..c47e851 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,7 +39,8 @@
printf.c \
zero.c \
lens.c \
- lens_default.c
+ lens_default.c \
+ lens_enum.c
libltrace_la_LIBADD = \
$(libelf_LIBS) \
@@ -88,7 +89,8 @@
printf.h \
zero.h \
lens.h \
- lens_default.h
+ lens_default.h \
+ lens_enum.h
dist_man1_MANS = \
ltrace.1
diff --git a/lens_default.c b/lens_default.c
index 75b8abe..afda095 100644
--- a/lens_default.c
+++ b/lens_default.c
@@ -107,20 +107,6 @@
#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
acc_fprintf(int *countp, FILE *stream, const char *format, ...)
{
va_list pa;
@@ -350,9 +336,6 @@
return format_array(stream, value, arguments,
value->type->u.array_info.length,
options.arraylen, 1, "[ ", " ]", ", ");
-
- case ARGTYPE_ENUM:
- return format_enum(stream, value, arguments);
}
abort();
}
@@ -433,7 +416,6 @@
arguments, INT_FMT_i);
int zero;
- case ARGTYPE_ENUM:
case ARGTYPE_SHORT:
case ARGTYPE_INT:
case ARGTYPE_LONG:
@@ -498,7 +480,6 @@
case ARGTYPE_USHORT:
case ARGTYPE_UINT:
case ARGTYPE_ULONG:
- case ARGTYPE_ENUM:
return toplevel_format_lens(lens, stream, value,
arguments, INT_FMT_i);
diff --git a/lens_enum.c b/lens_enum.c
new file mode 100644
index 0000000..1af94d2
--- /dev/null
+++ b/lens_enum.c
@@ -0,0 +1,163 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011 Petr Machata, Red Hat Inc.
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "arch.h"
+#include "lens_enum.h"
+#include "lens_default.h"
+#include "value.h"
+#include "type.h"
+
+struct enum_entry {
+ char *key;
+ int own_key;
+ struct value *value;
+ int own_value;
+};
+
+static void
+enum_entry_dtor(struct enum_entry *entry, void *data)
+{
+ if (entry->own_key)
+ free(entry->key);
+ if (entry->own_value) {
+ value_destroy(entry->value);
+ free(entry->value);
+ }
+}
+
+static void
+enum_lens_destroy_cb(struct lens *lens)
+{
+ struct enum_lens *self = (void *)lens;
+
+ VECT_DESTROY(&self->entries, struct enum_entry,
+ enum_entry_dtor, NULL);
+}
+
+enum {
+#ifdef ARCH_ENDIAN_BIG
+ big_endian = 1,
+#elif defined (ARCH_ENDIAN_LITTLE)
+ big_endian = 0,
+#else
+# error Undefined endianness.
+#endif
+};
+
+/* Returns 0 if they are not equal, >0 if they are, and <0 if there
+ * was an error. */
+static int
+enum_values_equal(struct value *inf_value, struct value *enum_value,
+ struct value_dict *arguments)
+{
+ /* Width may not match between what's defined in config file
+ * and what arrives from the back end. Typically, if there is
+ * a mismatch, the config file size will be larger, as we are
+ * in a situation where 64-bit tracer traces 32-bit process.
+ * But opposite situation can occur e.g. on PPC, where it's
+ * apparently possible for 32-bit tracer to trace 64-bit
+ * inferior, or hypothetically in a x32/x86_64 situation. */
+
+ unsigned char *inf_data = value_get_data(inf_value, arguments);
+ size_t inf_sz = value_size(inf_value, arguments);
+ if (inf_data == NULL || inf_sz == (size_t)-1)
+ return -1;
+
+ assert(inf_value->type->type == enum_value->type->type);
+
+ unsigned char *enum_data = value_get_data(enum_value, arguments);
+ size_t enum_sz = value_size(enum_value, arguments);
+ if (enum_data == NULL || enum_sz == (size_t)-1)
+ return -1;
+
+ size_t sz = enum_sz > inf_sz ? inf_sz : enum_sz;
+
+ if (big_endian)
+ return memcmp(enum_data + enum_sz - sz,
+ inf_data + inf_sz - sz, sz) == 0;
+ else
+ return memcmp(enum_data, inf_data, sz) == 0;
+}
+
+static const char *
+enum_get(struct enum_lens *lens, struct value *value,
+ struct value_dict *arguments)
+{
+ size_t i;
+ for (i = 0; i < vect_size(&lens->entries); ++i) {
+ struct enum_entry *entry = VECT_ELEMENT(&lens->entries,
+ struct enum_entry, i);
+ int st = enum_values_equal(value, entry->value, arguments);
+ if (st < 0)
+ return NULL;
+ else if (st != 0)
+ return entry->key;
+ }
+ return NULL;
+}
+
+static int
+enum_lens_format_cb(struct lens *lens, FILE *stream,
+ struct value *value, struct value_dict *arguments)
+{
+ struct enum_lens *self = (void *)lens;
+
+ long l;
+ if (value_extract_word(value, &l, arguments) < 0)
+ return -1;
+
+ const char *name = enum_get(self, value, arguments);
+ if (name != NULL)
+ return fprintf(stream, "%s", name);
+
+ return lens_format(&default_lens, stream, value, arguments);
+}
+
+
+void
+lens_init_enum(struct enum_lens *lens)
+{
+ *lens = (struct enum_lens){
+ {
+ .format_cb = enum_lens_format_cb,
+ .destroy_cb = enum_lens_destroy_cb,
+ },
+ };
+ VECT_INIT(&lens->entries, struct enum_entry);
+}
+
+int
+lens_enum_add(struct enum_lens *lens,
+ const char *key, int own_key,
+ struct value *value, int own_value)
+{
+ struct enum_entry entry = { (char *)key, own_key, value, own_value };
+ return VECT_PUSHBACK(&lens->entries, &entry);
+}
+
+size_t
+lens_enum_size(struct enum_lens *lens)
+{
+ return vect_size(&lens->entries);
+}
diff --git a/lens_enum.h b/lens_enum.h
new file mode 100644
index 0000000..de7b386
--- /dev/null
+++ b/lens_enum.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011 Petr Machata, Red Hat Inc.
+ *
+ * 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
+ */
+
+#ifndef LENS_ENUM_H
+#define LENS_ENUM_H
+
+#include "lens.h"
+#include "vect.h"
+
+struct enum_lens {
+ struct lens super;
+ struct vect entries;
+ int own;
+};
+
+/* Init enumeration LENS. */
+void lens_init_enum(struct enum_lens *lens);
+
+/* Push another member of the enumeration, named KEY, with given
+ * VALUE. If OWN_KEY, KEY is owned and released after the type is
+ * destroyed. KEY is typed as const char *, but note that if OWN_KEY,
+ * this value will be freed. If OWN_VALUE, then VALUE is owned and
+ * destroyed by LENS. */
+int lens_enum_add(struct enum_lens *lens,
+ const char *key, int own_key,
+ struct value *value, int own_value);
+
+/* Return number of enum elements of type INFO. */
+size_t lens_enum_size(struct enum_lens *lens);
+
+#endif /* LENS_ENUM_H */
diff --git a/read_config_file.c b/read_config_file.c
index 9faa5cf..058a857 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -38,6 +38,8 @@
#include "zero.h"
#include "type.h"
#include "lens.h"
+#include "lens_default.h"
+#include "lens_enum.h"
static int line_no;
static char *filename;
@@ -49,6 +51,7 @@
size_t param_num, int *ownp);
static struct arg_type_info *parse_lens(char **str, struct param **extra_param,
size_t param_num, int *ownp);
+static int parse_enum(char **str, struct arg_type_info **retp, int *ownp);
Function *list_of_functions = NULL;
@@ -78,7 +81,6 @@
KEYWORD("float", ARGTYPE_FLOAT);
KEYWORD("double", ARGTYPE_DOUBLE);
KEYWORD("array", ARGTYPE_ARRAY);
- KEYWORD("enum", ARGTYPE_ENUM);
KEYWORD("struct", ARGTYPE_STRUCT);
assert(rest == NULL);
@@ -633,6 +635,10 @@
return build_printf_pack(extra_param, param_num);
+ } else if (try_parse_kwd(str, "enum") >=0) {
+
+ return parse_enum(str, retp, ownp);
+
} else {
*retp = NULL;
return 0;
@@ -673,17 +679,64 @@
return 0;
}
-/* Syntax: enum ( keyname=value,keyname=value,... ) */
+/* Syntax:
+ * enum (keyname[=value],keyname[=value],... )
+ * enum<type> (keyname[=value],keyname[=value],... )
+ */
static int
-parse_enum(char **str, struct arg_type_info *info)
+parse_enum(char **str, struct arg_type_info **retp, int *ownp)
{
+ /* Optional type argument. */
+ eat_spaces(str);
+ if (**str == '[') {
+ parse_char(str, '[');
+ eat_spaces(str);
+ *retp = parse_nonpointer_type(str, NULL, 0, ownp);
+ if (*retp == NULL)
+ return -1;
+
+ if (!type_is_integral((*retp)->type)) {
+ report_error(filename, line_no,
+ "integral type required as enum argument");
+ fail:
+ if (*ownp) {
+ /* This also releases associated lens
+ * if any was set so far. */
+ type_destroy(*retp);
+ free(*retp);
+ }
+ return -1;
+ }
+
+ eat_spaces(str);
+ if (parse_char(str, ']') < 0)
+ goto fail;
+
+ } else {
+ *retp = type_get_simple(ARGTYPE_INT);
+ *ownp = 0;
+ }
+
+ /* We'll need to set the lens, so unshare. */
+ if (unshare_type_info(retp, ownp) < 0)
+ goto fail;
+
eat_spaces(str);
if (parse_char(str, '(') < 0)
+ goto fail;
+
+ struct enum_lens *lens = malloc(sizeof(*lens));
+ if (lens == NULL) {
+ report_error(filename, line_no,
+ "malloc enum lens: %s", strerror(errno));
return -1;
+ }
- type_init_enum(info);
+ lens_init_enum(lens);
+ (*retp)->lens = &lens->super;
+ (*retp)->own_lens = 1;
- int last_val = 0;
+ long last_val = 0;
while (1) {
eat_spaces(str);
if (**str == 0 || **str == ')') {
@@ -694,7 +747,7 @@
/* Field delimiter. XXX should we support the C
* syntax, where the enumeration can end in pending
* comma? */
- if (type_enum_size(info) > 0)
+ if (lens_enum_size(lens) > 0)
parse_char(str, ',');
eat_spaces(str);
@@ -702,23 +755,26 @@
if (key == NULL) {
err:
free(key);
- return -1;
+ goto fail;
}
if (**str == '=') {
++*str;
eat_spaces(str);
- long l;
- if (parse_int(str, &l) < 0 || check_int(l) < 0)
+ if (parse_int(str, &last_val) < 0)
goto err;
- last_val = l;
-
- } else {
- last_val++;
}
- if (type_enum_add(info, key, 1, last_val) < 0)
+ struct value *value = malloc(sizeof(*value));
+ if (value == NULL)
goto err;
+ value_init_detached(value, NULL, *retp, 0);
+ value_set_long(value, last_val);
+
+ if (lens_enum_add(lens, key, 1, value, 1) < 0)
+ goto err;
+
+ last_val++;
}
return 0;
@@ -766,10 +822,6 @@
parser = parse_array;
break;
- case ARGTYPE_ENUM:
- parser = parse_enum;
- break;
-
case ARGTYPE_STRUCT:
parser = parse_struct;
break;
diff --git a/sysdeps/linux-gnu/x86_64/trace.c b/sysdeps/linux-gnu/x86_64/trace.c
index eaae05e..8e89ae7 100644
--- a/sysdeps/linux-gnu/x86_64/trace.c
+++ b/sysdeps/linux-gnu/x86_64/trace.c
@@ -455,7 +455,6 @@
case ARGTYPE_UINT:
case ARGTYPE_LONG:
case ARGTYPE_ULONG:
- case ARGTYPE_ENUM:
case ARGTYPE_POINTER:
/* and LONGLONG */
@@ -612,7 +611,6 @@
case ARGTYPE_CHAR:
case ARGTYPE_SHORT:
case ARGTYPE_USHORT:
- case ARGTYPE_ENUM:
case ARGTYPE_POINTER:
cls = allocate_integer(context, valuep, sz, 0, POOL_RETVAL);
assert(cls == CLASS_INTEGER);
@@ -858,7 +856,6 @@
case ARGTYPE_LONG:
case ARGTYPE_ULONG:
case ARGTYPE_POINTER:
- case ARGTYPE_ENUM:
return 4;
}
abort();
@@ -890,7 +887,6 @@
case ARGTYPE_LONG:
case ARGTYPE_ULONG:
case ARGTYPE_POINTER:
- case ARGTYPE_ENUM:
return 4;
case ARGTYPE_VOID:
diff --git a/testsuite/ltrace.main/parameters-lib.c b/testsuite/ltrace.main/parameters-lib.c
index d3ad69c..f9a869d 100644
--- a/testsuite/ltrace.main/parameters-lib.c
+++ b/testsuite/ltrace.main/parameters-lib.c
@@ -219,6 +219,24 @@
{
}
+long *
+func_short_enums(short values[])
+{
+ static long retvals[4];
+ retvals[0] = values[0];
+ retvals[1] = values[1];
+ retvals[2] = values[2];
+ retvals[3] = values[3];
+ return retvals;
+}
+
+long
+func_negative_enum(short a, unsigned short b, int c, unsigned d,
+ long e, unsigned long f)
+{
+ return -1;
+}
+
void
func_charp_string(char *p)
{
diff --git a/testsuite/ltrace.main/parameters.c b/testsuite/ltrace.main/parameters.c
index 5a3f6b2..e8207fe 100644
--- a/testsuite/ltrace.main/parameters.c
+++ b/testsuite/ltrace.main/parameters.c
@@ -207,6 +207,14 @@
void func_hide(int a, int b, int c, int d, int e, int f);
func_hide(1, 2, 3, 4, 5, 6);
+ enum ab { A, B };
+ long *func_short_enums(short abs[]);
+ func_short_enums((short[]){ A, B, A, A });
+
+ long func_negative_enum(short a, unsigned short b, int c, unsigned d,
+ long e, unsigned long f);
+ func_negative_enum(-1, -1, -1, -1, -1, -1);
+
void func_charp_string(char *p);
func_charp_string("null-terminated string");
diff --git a/testsuite/ltrace.main/parameters.conf b/testsuite/ltrace.main/parameters.conf
index 419ad1f..9e0c967 100644
--- a/testsuite/ltrace.main/parameters.conf
+++ b/testsuite/ltrace.main/parameters.conf
@@ -26,4 +26,6 @@
void func_lens(octal, octal(long), hex(short), hex(long));
bool(int) func_bool(int, bool(int));
void func_hide(int, hide(int), hide(int), int, hide(int), int);
+array(enum[long](A,B), 4) *func_short_enums(array(enum[short](A,B), 4));
+enum[long](A=-1) func_negative_enum(enum[short](A=-1), enum[ushort](A=-1), enum[int](A=-1), enum[uint](A=-1), enum[long](A=-1), enum[ulong](A=-1));
void func_charp_string(string(char *));
diff --git a/testsuite/ltrace.main/parameters.exp b/testsuite/ltrace.main/parameters.exp
index 9be7b58..62991e9 100644
--- a/testsuite/ltrace.main/parameters.exp
+++ b/testsuite/ltrace.main/parameters.exp
@@ -127,5 +127,11 @@
set pattern "func_hide(1, 4, 6)"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+set pattern "func_short_enums(. A, B, A, A .).*= . A, B, A, A ."
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+
+set pattern "func_negative_enum(A, A, A, A, A, A).*= A"
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+
set pattern "func_charp_string(\\\"null-terminated string\\\")"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
diff --git a/type.c b/type.c
index 00775aa..6341042 100644
--- a/type.c
+++ b/type.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <stdlib.h>
+#include <limits.h>
#include "type.h"
#include "sysdep.h"
@@ -51,7 +52,6 @@
#undef HANDLE
case ARGTYPE_ARRAY:
- case ARGTYPE_ENUM:
case ARGTYPE_STRUCT:
case ARGTYPE_POINTER:
assert(!"Not a simple type!");
@@ -67,63 +67,6 @@
info->own_lens = 0;
}
-struct enum_entry {
- char *key;
- int own_key;
- int value;
-};
-
-void
-type_init_enum(struct arg_type_info *info)
-{
- type_init_common(info, ARGTYPE_ENUM);
- VECT_INIT(&info->u.entries, struct enum_entry);
-}
-
-int
-type_enum_add(struct arg_type_info *info,
- const char *key, int own_key, int value)
-{
- assert(info->type == ARGTYPE_ENUM);
- struct enum_entry entry = { (char *)key, own_key, value };
- return VECT_PUSHBACK(&info->u.entries, &entry);
-}
-
-size_t
-type_enum_size(struct arg_type_info *info)
-{
- assert(info->type == ARGTYPE_ENUM);
- return vect_size(&info->u.entries);
-}
-
-const char *
-type_enum_get(struct arg_type_info *info, int value)
-{
- assert(info->type == ARGTYPE_ENUM);
- size_t i;
- for (i = 0; i < vect_size(&info->u.entries); ++i) {
- struct enum_entry *entry = VECT_ELEMENT(&info->u.entries,
- struct enum_entry, i);
- if (value == entry->value)
- return entry->key;
- }
- return NULL;
-}
-
-static void
-enum_entry_dtor(struct enum_entry *entry, void *data)
-{
- if (entry->own_key)
- free(entry->key);
-}
-
-static void
-type_enum_destroy(struct arg_type_info *info)
-{
- VECT_DESTROY(&info->u.entries, struct enum_entry,
- enum_entry_dtor, NULL);
-}
-
struct struct_field {
struct arg_type_info *info;
int own_info;
@@ -279,10 +222,6 @@
return;
switch (info->type) {
- case ARGTYPE_ENUM:
- type_enum_destroy(info);
- break;
-
case ARGTYPE_STRUCT:
type_struct_destroy(info);
break;
@@ -367,7 +306,6 @@
case ARGTYPE_INT:
case ARGTYPE_UINT:
- case ARGTYPE_ENUM:
return sizeof(int);
case ARGTYPE_LONG:
@@ -521,3 +459,57 @@
abort();
}
}
+
+int
+type_is_integral(enum arg_type type)
+{
+ switch (type) {
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ return 1;
+
+ case ARGTYPE_VOID:
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ case ARGTYPE_POINTER:
+ return 0;
+ }
+ abort();
+}
+
+int
+type_is_signed(enum arg_type type)
+{
+ assert(type_is_integral(type));
+
+ switch (type) {
+ case ARGTYPE_CHAR:
+ return CHAR_MIN != 0;
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_LONG:
+ return 1;
+
+ case ARGTYPE_UINT:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_USHORT:
+ return 0;
+
+ case ARGTYPE_VOID:
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ case ARGTYPE_POINTER:
+ abort();
+ }
+ abort();
+}
diff --git a/type.h b/type.h
index d0b106f..545173c 100644
--- a/type.h
+++ b/type.h
@@ -38,7 +38,6 @@
ARGTYPE_FLOAT,
ARGTYPE_DOUBLE,
ARGTYPE_ARRAY, /* Series of values in memory */
- ARGTYPE_ENUM, /* Enumeration */
ARGTYPE_STRUCT, /* Structure of values */
ARGTYPE_POINTER, /* Pointer to some other type */
};
@@ -68,27 +67,10 @@
};
/* Return a type info for simple type TYPE (which shall not be array,
- * struct, enum or pointer. Each call with the same TYPE yields the
- * same arg_type_info pointer. */
+ * struct, or pointer. Each call with the same TYPE yields the same
+ * arg_type_info pointer. */
struct arg_type_info *type_get_simple(enum arg_type type);
-/* Initialize INFO so it becomes ARGTYPE_ENUM. Returns 0 on success
- * or negative value on failure. */
-void type_init_enum(struct arg_type_info *info);
-
-/* Push another member of the enumeration, named KEY, with given
- * VALUE. If OWN_KEY, KEY is owned and released after the type is
- * destroyed. KEY is typed as const char *, but note that if
- * OWN_KEY, this value will be freed. */
-int type_enum_add(struct arg_type_info *info,
- const char *key, int own_key, int value);
-
-/* Return number of enum elements of type INFO. */
-size_t type_enum_size(struct arg_type_info *info);
-
-/* Look up enum key with given VALUE in INFO. */
-const char *type_enum_get(struct arg_type_info *info, int value);
-
/* Initialize INFO so it becomes ARGTYPE_STRUCT. The created
* structure contains no fields. Use type_struct_add to populate the
* structure. */
@@ -142,4 +124,10 @@
size_t type_offsetof(struct Process *proc,
struct arg_type_info *type, size_t elt);
+/* Whether TYPE is an integral type as defined by the C standard. */
+int type_is_integral(enum arg_type type);
+
+/* Whether TYPE, which shall be integral, is a signed type. */
+int type_is_signed(enum arg_type type);
+
#endif /* TYPE_H */