|  | /* 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; | 
|  | } |