+/* Check if we can safely add a variable with the given type to this container. */
+
+static int
+check_variable (const char *name, ctf_file_t *fp, ctf_id_t type,
+ ctf_dvdef_t **out_dvd)
+{
+ ctf_dvdef_t *dvd;
+
+ dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
+ *out_dvd = dvd;
+ if (!dvd)
+ return 1;
+
+ if (dvd->dvd_type != type)
+ {
+ /* Variable here. Wrong type: cannot add. Just skip it, because there is
+ no way to express this in CTF. (This might be the parent, in which
+ case we'll try adding in the child first, and only then give up.) */
+ ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
+ }
+
+ return 0; /* Already exists. */
+}
+
+/* Link one variable in. */
+
+static int
+ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
+{
+ ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
+ ctf_file_t *per_cu_out_fp;
+ ctf_id_t dst_type = 0;
+ ctf_file_t *check_fp;
+ ctf_dvdef_t *dvd;
+
+ /* In unconflicted link mode, if this type is mapped to a type in the parent
+ container, we want to try to add to that first: if it reports a duplicate,
+ or if the type is in a child already, add straight to the child. */
+
+ check_fp = arg->out_fp;
+
+ dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
+ if (dst_type != 0)
+ {
+ if (check_fp == arg->out_fp)
+ {
+ if (check_variable (name, check_fp, dst_type, &dvd))
+ {
+ /* No variable here: we can add it. */
+ if (ctf_add_variable (check_fp, name, dst_type) < 0)
+ return (ctf_set_errno (arg->out_fp, ctf_errno (check_fp)));
+ return 0;
+ }
+
+ /* Already present? Nothing to do. */
+ if (dvd && dvd->dvd_type == type)
+ return 0;
+ }
+ }
+
+ /* Can't add to the parent due to a name clash, or because it references a
+ type only present in the child. Try adding to the child, creating if need
+ be. */
+
+ if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
+ arg->cu_name)) == NULL)
+ return -1; /* Errno is set for us. */
+
+ /* If the type was not found, check for it in the child too. */
+ if (dst_type == 0)
+ {
+ check_fp = per_cu_out_fp;
+ dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
+
+ if (dst_type == 0)
+ {
+ ctf_dprintf ("Type %lx for variable %s in input file %s not "
+ "found: skipped.\n", type, name, arg->file_name);
+ /* Do not terminate the link: just skip the variable. */
+ return 0;
+ }
+ }
+
+ if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
+ if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
+ return (ctf_set_errno (arg->out_fp, ctf_errno (per_cu_out_fp)));
+ return 0;
+}
+