1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
/* Test enumerator iteration and querying. Because
ctf_arc_lookup_enumerator_next uses ctf_lookup_enumerator_next internally, we
only need to test the former. */
#include "config.h"
#include <ctf-api.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void
print_constants (ctf_archive_t *ctf, const char *name)
{
ctf_next_t *i = NULL;
int err;
ctf_dict_t *fp;
ctf_id_t type;
int64_t val;
while ((type = ctf_arc_lookup_enumerator_next (ctf, name, &i,
&val, &fp, &err)) != CTF_ERR)
{
char *foo;
printf ("%s in %s has value %li\n", name,
foo = ctf_type_aname (fp, type), (long int) val);
free (foo);
ctf_dict_close (fp);
}
if (err != ECTF_NEXT_END)
{
fprintf (stderr, "iteration failed: %s\n", ctf_errmsg (err));
exit (1);
}
}
int
main (int argc, char *argv[])
{
ctf_archive_t *ctf;
ctf_dict_t *fp;
int err;
ctf_id_t type;
ctf_next_t *i = NULL;
int64_t val;
int counter = 0;
if (argc != 2)
{
fprintf (stderr, "Syntax: %s PROGRAM\n", argv[0]);
exit(1);
}
if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
goto open_err;
/* Look for all instances of ENUMSAMPLE2_2, and add some new enums to all
dicts found, to test dynamic enum iteration as well as static.
Add two enums with a different name and constants to any that should
already be there (one hidden), and one with the same constants, but hidden,
to test ctf_lookup_enumerator_next()'s multiple-lookup functionality and
ctf_lookup_enumerator() in the presence of hidden types.
This also tests that you can add to enums under iteration without causing
disaster. */
printf ("First iteration: addition of enums.\n");
while ((type = ctf_arc_lookup_enumerator_next (ctf, "IENUMSAMPLE2_2", &i,
&val, &fp, &err)) != CTF_ERR)
{
char *foo;
int dynadd2_value;
int old_dynadd2_flag;
/* Make sure that getting and setting a garbage flag, and setting one to a
garbage value, fails properly. */
if (ctf_dict_set_flag (fp, CTF_STRICT_NO_DUP_ENUMERATORS, 666) >= 0
|| ctf_errno (fp) != ECTF_BADFLAG)
fprintf (stderr, "Invalid flag value setting did not fail as it ought to\n");
if (ctf_dict_set_flag (fp, 0, 1) >= 0 || ctf_errno (fp) != ECTF_BADFLAG)
fprintf (stderr, "Invalid flag setting did not fail as it ought to\n");
if (ctf_dict_get_flag (fp, 0) >= 0 || ctf_errno (fp) != ECTF_BADFLAG)
fprintf (stderr, "Invalid flag getting did not fail as it ought to\n");
/* Set it strict for now. */
if (ctf_dict_set_flag (fp, CTF_STRICT_NO_DUP_ENUMERATORS, 1) < 0)
goto set_flag_err;
printf ("IENUMSAMPLE2_2 in %s has value %li\n",
foo = ctf_type_aname (fp, type), (long int) val);
free (foo);
if ((type = ctf_add_enum (fp, CTF_ADD_ROOT, "ie3")) == CTF_ERR)
goto enum_add_err;
if (ctf_add_enumerator (fp, type, "DYNADD", counter += 10) < 0)
goto enumerator_add_err;
if (ctf_add_enumerator (fp, type, "DYNADD2", counter += 10) < 0)
goto enumerator_add_err;
dynadd2_value = counter;
/* Make sure that overlapping enumerator addition fails as it should. */
if (ctf_add_enumerator (fp, type, "IENUMSAMPLE2_2", 666) >= 0
|| ctf_errno (fp) != ECTF_DUPLICATE)
fprintf (stderr, "Duplicate enumerator addition did not fail as it ought to\n");
/* Make sure that it still fails if you set an enum value to the value it
already has. */
if (ctf_add_enumerator (fp, type, "DYNADD2", dynadd2_value) >= 0
|| ctf_errno (fp) != ECTF_DUPLICATE)
fprintf (stderr, "Duplicate enumerator addition did not fail as it ought to\n");
/* Flip the strict flag and try again. This time, it should succeed. */
if ((old_dynadd2_flag = ctf_dict_get_flag (fp, CTF_STRICT_NO_DUP_ENUMERATORS)) < 0)
goto get_flag_err;
if (ctf_dict_set_flag (fp, CTF_STRICT_NO_DUP_ENUMERATORS, 0) < 0)
goto set_flag_err;
if (ctf_add_enumerator (fp, type, "DYNADD2", dynadd2_value) < 0)
goto enumerator_add_err;
/* Flip it again and try *again*. This time it should fail again. */
if (ctf_dict_set_flag (fp, CTF_STRICT_NO_DUP_ENUMERATORS, old_dynadd2_flag) < 0)
goto set_flag_err;
if (ctf_add_enumerator (fp, type, "DYNADD2", dynadd2_value) >= 0
|| ctf_errno (fp) != ECTF_DUPLICATE)
fprintf (stderr, "Duplicate enumerator addition did not fail as it ought to\n");
if ((type = ctf_add_enum (fp, CTF_ADD_NONROOT, "ie4_hidden")) == CTF_ERR)
goto enum_add_err;
if (ctf_add_enumerator (fp, type, "DYNADD3", counter += 10) < 0)
goto enumerator_add_err;
if (ctf_add_enumerator (fp, type, "DYNADD4", counter += 10) < 0)
goto enumerator_add_err;
if ((type = ctf_add_enum (fp, CTF_ADD_NONROOT, "ie3_hidden")) == CTF_ERR)
goto enum_add_err;
if (ctf_add_enumerator (fp, type, "DYNADD", counter += 10) < 0)
goto enumerator_add_err;
if (ctf_add_enumerator (fp, type, "DYNADD2", counter += 10) < 0)
goto enumerator_add_err;
/* Look them up via ctf_lookup_enumerator. DYNADD2 should fail because
it has duplicate enumerators. */
if (ctf_lookup_enumerator (fp, "DYNADD", &val) == CTF_ERR)
goto enumerator_lookup_err;
printf ("direct lookup: DYNADD value: %i\n", (int) val);
if ((err = ctf_lookup_enumerator (fp, "DYNADD2", &val)) >= 0 ||
ctf_errno (fp) != ECTF_DUPLICATE)
fprintf (stderr, "Duplicate enumerator lookup did not fail as it ought to: %i, %s\n",
err, ctf_errmsg (ctf_errno (fp)));
if ((type = ctf_lookup_enumerator (fp, "DYNADD3", &val) != CTF_ERR) ||
ctf_errno (fp) != ECTF_NOENUMNAM)
{
if (type != CTF_ERR)
{
char *foo;
printf ("direct lookup: hidden lookup did not return ECTF_NOENUMNAM but rather %li in %s\n",
(long int) val, foo = ctf_type_aname (fp, type));
free (foo);
}
else
printf ("direct lookup: hidden lookup did not return ECTF_NOENUMNAM but rather %s\n",
ctf_errmsg (ctf_errno (fp)));
}
ctf_dict_close (fp);
}
if (err != ECTF_NEXT_END)
{
fprintf (stderr, "iteration failed: %s\n", ctf_errmsg (err));
return 1;
}
/* Look for (and print out) some enumeration constants. */
printf ("Second iteration: printing of enums.\n");
print_constants (ctf, "ENUMSAMPLE_1");
print_constants (ctf, "IENUMSAMPLE_1");
print_constants (ctf, "ENUMSAMPLE_2");
print_constants (ctf, "DYNADD");
print_constants (ctf, "DYNADD3");
ctf_close (ctf);
printf ("All done.\n");
return 0;
open_err:
fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
return 1;
enum_add_err:
fprintf (stderr, "Cannot add enum to dict \"%s\": %s\n",
ctf_cuname (fp) ? ctf_cuname (fp) : "(null: parent)", ctf_errmsg (ctf_errno (fp)));
return 1;
enumerator_add_err:
fprintf (stderr, "Cannot add enumerator to dict \"%s\": %s\n",
ctf_cuname (fp) ? ctf_cuname (fp) : "(null: parent)", ctf_errmsg (ctf_errno (fp)));
return 1;
enumerator_lookup_err:
fprintf (stderr, "Cannot look up enumerator in dict \"%s\": %s\n",
ctf_cuname (fp) ? ctf_cuname (fp) : "(null: parent)", ctf_errmsg (ctf_errno (fp)));
return 1;
get_flag_err:
fprintf (stderr, "ctf_dict_get_flag failed: %s\n", ctf_errmsg (ctf_errno (fp)));
return 1;
set_flag_err:
fprintf (stderr, "ctf_dict_set_flag failed: %s\n", ctf_errmsg (ctf_errno (fp)));
return 1;
}
|