- int i;
- struct disr_info ret;
- struct type *disr_type;
- struct ui_file *temp_file;
- struct value_print_options opts;
- struct cleanup *cleanup;
- const char *name_segment;
-
- get_no_prettyformat_print_options (&opts);
-
- ret.field_no = -1;
- ret.is_encoded = 0;
-
- if (TYPE_NFIELDS (type) == 0)
- error (_("Encountered void enum value"));
-
- /* If an enum has two values where one is empty and the other holds
- a pointer that cannot be zero; then the Rust compiler optimizes
- away the discriminant and instead uses a zero value in the
- pointer field to indicate the empty variant. */
- if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
- strlen (RUST_ENUM_PREFIX)) == 0)
- {
- char *tail, *token, *name, *saveptr = NULL;
- unsigned long fieldno;
- struct type *member_type;
- LONGEST value;
-
- ret.is_encoded = 1;
-
- if (TYPE_NFIELDS (type) != 1)
- error (_("Only expected one field in %s type"), RUST_ENUM_PREFIX);
-
- /* Optimized enums have only one field. */
- member_type = TYPE_FIELD_TYPE (type, 0);
-
- name = xstrdup (TYPE_FIELD_NAME (type, 0));
- cleanup = make_cleanup (xfree, name);
- tail = name + strlen (RUST_ENUM_PREFIX);
-
- /* The location of the value that doubles as a discriminant is
- stored in the name of the field, as
- RUST$ENCODED$ENUM$<fieldno>$<fieldno>$...$<variantname>
- where the fieldnos are the indices of the fields that should be
- traversed in order to find the field (which may be several fields deep)
- and the variantname is the name of the variant of the case when the
- field is zero. */
- for (token = strtok_r (tail, "$", &saveptr);
- token != NULL;
- token = strtok_r (NULL, "$", &saveptr))
- {
- if (sscanf (token, "%lu", &fieldno) != 1)
- {
- /* We have reached the enum name, which cannot start
- with a digit. */
- break;
- }
- if (fieldno >= TYPE_NFIELDS (member_type))
- error (_("%s refers to field after end of member type"),
- RUST_ENUM_PREFIX);
-
- embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8;
- member_type = TYPE_FIELD_TYPE (member_type, fieldno);
- }
-
- if (token == NULL)
- error (_("Invalid form for %s"), RUST_ENUM_PREFIX);
- value = unpack_long (member_type, valaddr + embedded_offset);
-
- if (value == 0)
- {
- ret.field_no = RUST_ENCODED_ENUM_HIDDEN;
- ret.name = concat (TYPE_NAME (type), "::", token, (char *) NULL);
- }
- else
- {
- ret.field_no = RUST_ENCODED_ENUM_REAL;
- ret.name = concat (TYPE_NAME (type), "::",
- rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))),
- (char *) NULL);
- }
-
- do_cleanups (cleanup);
- return ret;
- }