/*! \brief get the subpages of a schematic page
 *
 *  if any subpages are not loaded, this function will load them.
 *
 *  \param [in] page the parent page
 *  \return a list of all the subpages
 */
static GList*
get_subpages (PAGE *page)
{
  const GList *object_iter;
  GList *page_list = NULL;

  g_return_val_if_fail (page != NULL, NULL);

  object_iter = s_page_objects (page);

  while (object_iter != NULL) {
    char *attrib;
    char **filenames;
    char **iter;
    OBJECT *object = (OBJECT*) object_iter->data;

    object_iter = g_list_next (object_iter);

    if (object == NULL) {
      g_warning ("NULL object encountered");
      continue;
    }

    if (object->type != OBJ_COMPLEX) {
      continue;
    }

    attrib = o_attrib_search_attached_attribs_by_name (object,
                                                       "source",
                                                       0);

    if (attrib == NULL) {
      attrib = o_attrib_search_inherited_attribs_by_name (object,
                                                          "source",
                                                          0);
    }

    if (attrib == NULL) {
      continue;
    }

    filenames = g_strsplit (attrib, ",", 0);

    if (filenames == NULL) {
      continue;
    }

    for (iter = filenames; *iter != NULL; iter++) {
      PAGE *subpage = s_hierarchy_load_subpage (page, *iter, NULL);

      if (subpage != NULL) {
        page_list = g_list_prepend (page_list, subpage);
      }
    }

    g_strfreev (filenames);
  }

  return g_list_reverse (page_list);
}
Esempio n. 2
0
/*! \brief Find page hierarchy below a page.
 *  \par Function Description
 *  This function traverses the hierarchy tree of pages and returns a
 *  flat list of pages that are below \a p_current. There are two \a
 *  flags that can be used to control the way that the return value is
 *  constructed: <B>HIERARCHY_NODUPS</B> returns a list without
 *  duplicate pages, and <B>HIERARCHY_POSTORDER</B> traverses the
 *  hierarchy tree and returns a postorder list instead of preorder.
 *
 *  \param toplevel The TOPLEVEL structure.
 *  \param p_current The PAGE to traverse hierarchy for.
 *  \param flags Flags controlling form of return value.
 *  \return A GList of PAGE pointers.
 *
 *  \warning
 *  Caller must destroy returned GList with g_list_free().
 */
GList *
s_hierarchy_traversepages (TOPLEVEL *toplevel, PAGE *p_current, gint flags)
{
  OBJECT *o_current;
  PAGE *child_page;
  char *filename = NULL;
  static GList *pages = NULL;
  const GList *iter;

  g_return_val_if_fail ((toplevel != NULL), NULL);
  g_return_val_if_fail ((p_current != NULL), NULL);

  /* init static variables the first time*/
  if (!(flags & HIERARCHY_INNERLOOP)) {
    pages = NULL;
  }

  /* preorder traversing */
  if (!(flags & HIERARCHY_POSTORDER)) {
    /* check whether we already visited this page */
    if ((flags & HIERARCHY_NODUPS)
        && (g_list_find (pages, p_current) != NULL)) {
      return pages;  /* drop the page subtree */
      }
    pages = g_list_append (pages, p_current);
  }

  /* walk throught the page objects and search for underlaying schematics */
  for (iter = s_page_objects (p_current);
       iter != NULL ;
       iter = g_list_next (iter)) {
    o_current = (OBJECT *)iter->data;

    /* only complex things like symbols can contain attributes */
    if (o_current->type != OBJ_COMPLEX) continue;

    filename =
      o_attrib_search_attached_attribs_by_name (o_current, "source", 0);

    /* if above is NULL, then look inside symbol */
    if (filename == NULL) {
      filename =
        o_attrib_search_inherited_attribs_by_name (o_current, "source", 0);
    }

    if (filename == NULL) continue;

    /* we got a schematic source attribute
       lets load the page and dive into it */
    GError *err = NULL;
    child_page =
      s_hierarchy_down_schematic_single (toplevel, filename, p_current, 0,
                                         HIERARCHY_NORMAL_LOAD, &err);
    if (child_page != NULL) {
      /* call the recursive function */
      s_hierarchy_traversepages (toplevel, child_page, flags | HIERARCHY_INNERLOOP);
    } else {
      s_log_message (_("Failed to descend hierarchy into '%1$s': %2$s"),
                     filename, err->message);
      g_error_free (err);
    }

    g_free (filename);
    filename = NULL;
  }

  /* postorder traversing */
  if (flags & HIERARCHY_POSTORDER) {
    /* check whether we already visited this page */
    if ((flags & HIERARCHY_NODUPS)
        && (g_list_find (pages, p_current) != NULL)) {
      return pages;  /* don't append it */
    }
    pages = g_list_append (pages, p_current);
  }

  return pages;
}
Esempio n. 3
0
void
s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
		     NETLIST * netlist)
{
    char *attrib;
    int page_control=-1;
    PAGE *p_current;
    PAGE *child_page;
    int count = 0;
    int pcount = 0;
    int looking_inside = FALSE;
    int loaded_flag = FALSE;
    char *current_filename;
    int graphical=FALSE;

    attrib = o_attrib_search_attached_attribs_by_name (o_current, "source", 0);

    /* if above is null, then look inside symbol */
    if (attrib == NULL) {
	attrib = o_attrib_search_inherited_attribs_by_name (o_current,
	                                                    "source", count);

	looking_inside = TRUE;
#if DEBUG
	printf("going to look inside now\n");
#endif
    }

    graphical = s_hierarchy_graphical_search(o_current, count);
    if (graphical) {
	/* Do not bother traversing the hierarchy if the symbol has an */
	/* graphical attribute attached to it. */
	if (attrib) {
	    g_free(attrib);
 	    attrib = NULL;
	}
    }

    while (attrib) {

	/* look for source=filename,filename, ... */
	pcount = 0;
	current_filename = u_basic_breakup_string(attrib, ',', pcount);

	/* loop over all filenames */
	while (current_filename != NULL) {

	    s_log_message(_("Going to traverse source [%1$s]"),
			  current_filename);

	    /* guts here */
	    /* guts for a single filename */
	    p_current = pr_current->page_current;
#if DEBUG
	    printf("Going down %s\n", current_filename);
#endif
            GError *err = NULL;
	    child_page =
		s_hierarchy_down_schematic_single(pr_current,
						  current_filename,
						  pr_current->page_current,
						  page_control,
                                                  HIERARCHY_FORCE_LOAD,
                                                  &err);

	    if (child_page == NULL) {
              g_warning (_("Failed to load subcircuit '%1$s': %2$s\n"),
                         current_filename, err->message);
              fprintf(stderr, _("ERROR: Failed to load subcircuit '%1$s': %2$s\n"),
                      current_filename, err->message);
              g_error_free (err);
              exit (2);

	    } else {
              page_control = child_page->page_control;
              s_page_goto (pr_current, child_page);

		loaded_flag = TRUE;

		verbose_print("v\n");
		verbose_reset_index();

		netlist->composite_component = TRUE;
		/* can't do the following, don't know why... HACK TODO */
		/*netlist->hierarchy_tag = u_basic_strdup (netlist->component_uref);*/
		s_traverse_sheet (pr_current,
		                  s_page_objects (pr_current->page_current),
		                  netlist->component_uref);

		verbose_print("^");
	    }

	    pr_current->page_current = p_current;

	    g_free(current_filename);
	    pcount++;
	    current_filename = u_basic_breakup_string(attrib, ',', pcount);
	}

	g_free(attrib);

	g_free(current_filename);

	count++;

	/* continue looking outside first */
	if (!looking_inside) {
	    attrib =
		o_attrib_search_attached_attribs_by_name (o_current, "source",
		                                          count);
	}

	/* okay we were looking outside and didn't */
	/* find anything, so now we need to look */
	/* inside the symbol */
	if (!looking_inside && attrib == NULL && !loaded_flag) {
	    looking_inside = TRUE;
#if DEBUG
	    printf("switching to go to look inside\n");
#endif
	}

	if (looking_inside) {
#if DEBUG
	    printf("looking inside\n");
#endif
	    attrib =
	        o_attrib_search_inherited_attribs_by_name (o_current,
	                                                   "source", count);
	}

        graphical = s_hierarchy_graphical_search(o_current, count);
        if (graphical) {
	  /* Do not bother looking further in the hierarchy if the symbol */
          /* has an graphical attribute attached to it. */
	  if (attrib) {
	     g_free(attrib);
	     attrib = NULL;
          }
       }
    }
}
Esempio n. 4
0
/*! \brief Update a component.
 *
 * \par Function Description
 * Updates \a o_current to the latest version of the symbol available
 * in the symbol library, while preserving any attributes set in the
 * current schematic. On success, returns the new OBJECT which
 * replaces \a o_current on the page; \a o_current is deleted. On
 * failure, returns NULL, and \a o_current is left unchanged.
 *
 * \param [in]     w_current The GSCHEM_TOPLEVEL object.
 * \param [in,out] o_current The OBJECT to be updated.
 *
 * \return the new OBJECT that replaces \a o_current.
 */
OBJECT *
o_update_component (GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  OBJECT *o_new;
  PAGE *page;
  GList *new_attribs;
  GList *old_attribs;
  GList *iter;
  const CLibSymbol *clib;

  g_return_val_if_fail (o_current != NULL, NULL);
  g_return_val_if_fail (o_current->type == OBJ_COMPLEX, NULL);
  g_return_val_if_fail (o_current->complex_basename != NULL, NULL);

  page = o_get_page (toplevel, o_current);

  /* This should be replaced with API to invalidate only the specific
   * symbol name we want to update */
  s_clib_flush_symbol_cache ();
  clib = s_clib_get_symbol_by_name (o_current->complex_basename);

  if (clib == NULL) {
    s_log_message (_("Could not find symbol [%s] in library. Update failed.\n"),
                   o_current->complex_basename);
    return NULL;
  }

  /* Unselect the old object. */
  o_selection_remove (toplevel, page->selection_list, o_current);

  /* Create new object and set embedded */
  o_new = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR,
                         o_current->complex->x,
                         o_current->complex->y,
                         o_current->complex->angle,
                         o_current->complex->mirror,
                         clib, o_current->complex_basename,
                         1);
  if (o_complex_is_embedded (o_current)) {
    o_embed (toplevel, o_new);
  }

  new_attribs = o_complex_promote_attribs (toplevel, o_new);

  /* Cull any attributes from new COMPLEX that are already attached to
   * old COMPLEX. Note that the new_attribs list is kept consistent by
   * setting GList data pointers to NULL if their OBJECTs are
   * culled. At the end, the new_attribs list is updated by removing
   * all list items with NULL data. This is slightly magic, but
   * works. */
  for (iter = new_attribs; iter != NULL; iter = g_list_next (iter)) {
    OBJECT *attr_new = iter->data;
    gchar *name;
    gchar *value;

    g_assert (attr_new->type == OBJ_TEXT);

    o_attrib_get_name_value (attr_new, &name, NULL);

    value = o_attrib_search_attached_attribs_by_name (o_current, name, 0);
    if (value != NULL) {
      o_attrib_remove (toplevel, &o_new->attribs, attr_new);
      s_delete_object (toplevel, attr_new);
      iter->data = NULL;
    }

    g_free (name);
    g_free (value);
  }
  new_attribs = g_list_remove_all (new_attribs, NULL);

  /* Detach attributes from old OBJECT and attach to new OBJECT */
  old_attribs = g_list_copy (o_current->attribs);
  o_attrib_detach_all (toplevel, o_current);
  o_attrib_attach_list (toplevel, old_attribs, o_new, 1);
  g_list_free (old_attribs);

  /* Add new attributes to page */
  s_page_append_list (toplevel, page, new_attribs);

  /* Update pinnumbers for current slot */
  s_slot_update_object (toplevel, o_new);

  /* Replace old OBJECT with new OBJECT */
  s_page_replace (toplevel, page, o_current, o_new);
  s_delete_object (toplevel, o_current);

  /* Select new OBJECT */
  o_selection_add (toplevel, page->selection_list, o_new);

  /* mark the page as modified */
  toplevel->page_current->CHANGED = 1;
  o_undo_savestate (w_current, UNDO_ALL);

  return o_new;
}
Esempio n. 5
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *  \todo Only descends into the first source schematic
 *
 */
int o_edit_find_text (GSCHEM_TOPLEVEL *w_current, const GList *o_list,
                      char *stext, int descend, int skip)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  char *attrib = NULL;
  int count = 0;
  PAGE *parent = NULL;
  char *current_filename = NULL;
  int page_control = 0;
  int pcount = 0;
  int rv;
  int x1, y1, x2, y2;
  int text_screen_height;
  const GList *iter;

  OBJECT *o_current;

  skiplast = skip;

  iter = o_list;
  while (iter != NULL) {
    o_current = (OBJECT *)iter->data;

    if (descend) {
      if (o_current->type == OBJ_COMPLEX) {
        parent = toplevel->page_current;
        attrib = o_attrib_search_attached_attribs_by_name (o_current,
                                                           "source", count);

        /* if above is null, then look inside symbol */
        if (attrib == NULL) {
          attrib = o_attrib_search_inherited_attribs_by_name (o_current,
                                                              "source", count);
          /*          looking_inside = TRUE; */
        }

        if (attrib) {
          pcount = 0;
          current_filename = u_basic_breakup_string(attrib, ',', pcount);
          if (current_filename != NULL) {
            PAGE *child_page =
              s_hierarchy_down_schematic_single(toplevel,
                                                current_filename,
                                                parent,
                                                page_control,
                                                HIERARCHY_NORMAL_LOAD);

            if (child_page != NULL) {
              page_control = child_page->page_control;
              rv = o_edit_find_text (w_current,
                                     s_page_objects (child_page),
                                     stext, descend, skiplast);
              if (!rv) {
                s_page_goto( toplevel, child_page );
                return 0;
              }
            }
          }
        }
      }
    }

    if (o_current->type == OBJ_TEXT) {
      const gchar *str = o_text_get_string (toplevel, o_current);
     /* replaced strcmp with strstr to simplify the search */
      if (strstr (str,stext)) {
        if (!skiplast) {
          a_zoom(w_current, ZOOM_FULL, DONTCARE, A_PAN_DONT_REDRAW);
          world_get_single_object_bounds (toplevel, o_current, &x1, &y1, &x2, &y2);
          text_screen_height = SCREENabs (w_current, y2 - y1);
          /* this code will zoom/pan till the text screen height is about */
          /* 50 pixels high, perhaps a future enhancement will be to make */
          /* this number configurable */
          while (text_screen_height < 50) {
            a_zoom(w_current, ZOOM_IN, DONTCARE, A_PAN_DONT_REDRAW);
            text_screen_height = SCREENabs (w_current, y2 - y1);
          }
          a_pan_general(w_current,
                        o_current->text->x, o_current->text->y,
                        1, 0);

	  /* Make sure the titlebar and scrollbars are up-to-date */
	  x_window_set_current_page(w_current, 
                                    w_current->toplevel->page_current );

          last_o = o_current;
          break;
        }
        if (last_o == o_current) {
          skiplast = 0;
        }

      } /* if (strstr(o_current->text->string,stext)) */
    } /* if (o_current->type == OBJ_TEXT) */
    iter = g_list_next (iter);

    if (iter == NULL) {
      return 1;
    }
  }
  return (iter == NULL);
}
Esempio n. 6
0
/*! \brief check the symversion of a complex object
 *  \par Function Description
 *  This function compares the symversion of a symbol with it's 
 *  earlier saved symversion in a schematic.
 *  Major symversion changes are added to the toplevel object 
 *  (toplevel->major_changed_refdes), minor changes are reported
 *  to the messaging system.
 *  
 *  \param toplevel  The TOPLEVEL object
 *  \param object    The complex OBJECT
 */
void
o_complex_check_symversion(TOPLEVEL* toplevel, OBJECT* object)
{
  char *inside = NULL;
  char *outside = NULL;
  char *refdes = NULL;
  double inside_value = -1.0;
  double outside_value = -1.0;
  char *err_check = NULL;
  int inside_present = FALSE;
  int outside_present = FALSE;
  double inside_major, inside_minor;
  double outside_major, outside_minor;
  
  g_return_if_fail (object != NULL);
  g_return_if_fail ((object->type == OBJ_COMPLEX || 
		     object->type == OBJ_PLACEHOLDER));
  g_return_if_fail (object->complex != NULL);

  /* first look on the inside for the symversion= attribute */
  inside = o_attrib_search_inherited_attribs_by_name (object, "symversion", 0);

  /* now look for the symversion= attached to object */
  outside = o_attrib_search_attached_attribs_by_name (object, "symversion", 0);

  /* get the uref for future use */
  refdes = o_attrib_search_object_attribs_by_name(object, "refdes", 0);
  if (!refdes)
  {
    refdes = g_strdup ("unknown");
  }
  
  if (inside)
  {
    inside_value = strtod(inside, &err_check);
    if (inside_value == 0 && inside == err_check)
    {
      if (inside)
      { 
        s_log_message(_("WARNING: Symbol version parse error on refdes %s:\n"
                        "\tCould not parse symbol file symversion=%s\n"),
                      refdes, inside);
      } else {
        s_log_message(_("WARNING: Symbol version parse error on refdes %s:\n"
                        "\tCould not parse symbol file symversion=\n"),
                      refdes);
      }
      goto done;
    }
    inside_present = TRUE;
  } else {
    inside_present = FALSE;  /* attribute not inside */
  }

  if (outside)
  {
    outside_value = strtod(outside, &err_check);
    if (outside_value == 0 && outside == err_check)
    {
      s_log_message(_("WARNING: Symbol version parse error on refdes %s:\n"
                      "\tCould not parse attached symversion=%s\n"),
                    refdes, outside);
      goto done;
    }
    outside_present = TRUE; 
  } else {
    outside_present = FALSE;  /* attribute not outside */
  }

#if DEBUG
  printf("%s:\n\tinside: %.1f outside: %.1f\n\n", object->name,
         inside_value, outside_value);
#endif
  
  /* symversion= is not present anywhere */
  if (!inside_present && !outside_present)
  {
    /* symbol is legacy and versioned okay */
    goto done;
  }

  /* No symversion inside, but a version is outside, this is a weird case */
  if (!inside_present && outside_present)
  {
    s_log_message(_("WARNING: Symbol version oddity on refdes %s:\n"
                    "\tsymversion=%s attached to instantiated symbol, "
                    "but no symversion= inside symbol file\n"),
                  refdes, outside);
    goto done;
  }

  /* inside & not outside is a valid case, means symbol in library is newer */
  /* also if inside_value is greater than outside_value, then symbol in */
  /* library is newer */
  if ((inside_present && !outside_present) ||
      ((inside_present && outside_present) && (inside_value > outside_value)))
  {
    
    s_log_message(_("WARNING: Symbol version mismatch on refdes %s (%s):\n"
                    "\tSymbol in library is newer than "
                    "instantiated symbol\n"),
                  refdes, object->complex_basename);

    /* break up the version values into major.minor numbers */
    inside_major = floor(inside_value);
    inside_minor = inside_value - inside_major;

    if (outside_present)
    {
      outside_major = floor(outside_value);
      outside_minor = outside_value - outside_major;
    } else {
      /* symversion was not attached to the symbol, set all to zero */
      outside_major = 0.0;
      outside_minor = 0.0;
      outside_value = 0.0;
    }

#if DEBUG
    printf("i: %f %f %f\n", inside_value, inside_major, inside_minor);
    printf("o: %f %f %f\n", outside_value, outside_major, outside_minor);
#endif
    
    if (inside_major > outside_major)
    {
      char* refdes_copy;
      s_log_message(_("\tMAJOR VERSION CHANGE (file %.3f, "
                      "instantiated %.3f, %s)!\n"),
                    inside_value, outside_value, refdes);

      /* add the refdes to the major_changed_refdes GList */
      /* make sure refdes_copy is freed somewhere */
      refdes_copy = g_strconcat (refdes, " (",
                                 object->complex_basename,
                                 ")", NULL);
      toplevel->major_changed_refdes =
        g_list_append(toplevel->major_changed_refdes, refdes_copy);

      /* don't bother checking minor changes if there are major ones*/
      goto done; 
    }

    if (inside_minor > outside_minor)
    {
      s_log_message(_("\tMinor version change (file %.3f, "
                      "instantiated %.3f)\n"),
                    inside_value, outside_value);
    }

    goto done;
  }

  /* outside value is greater than inside value, this is weird case */
  if ((inside_present && outside_present) && (outside_value > inside_value))
  {
    s_log_message(_("WARNING: Symbol version oddity on refdes %s:\n"
                    "\tInstantiated symbol is newer than "
                    "symbol in library\n"),
                  refdes);
    goto done;
  }

  /* if inside_value and outside_value match, then symbol versions are okay */

done:
  g_free(inside);
  g_free(outside);
  g_free(refdes);
}
Esempio n. 7
0
/*! \brief Update pin attributes in toplevel
 *
 * For each attrib string attached to the pin, update it using the value
 * held in new_pin_attrib_list.  Algorithm:
 * -# Loop over name=value pairs held in new_pin_attrib_list.
 * -# For each name=value pair, look for corresponding attrib on pin.
 * -# If the attrib exists on pin and in name=value pair, write the
 *    new value in.
 * -# If the attrib exists on pin, but is null in name=value pair,
 *    delete the attrib.
 * -# If the attribs doesn't exist on pin, but is non-null in
 *    the name=value pair, create an attrib object and add it to the pin.
 * \param toplevel TOPLEVEL structure
 * \param refdes Unused - needs refactored out
 * \param [in,out] o_pin pin to update
 * \param [in] new_pin_attrib_list New pin attribute list to apply
 */
void
s_toplevel_update_pin_attribs_in_toplevel (TOPLEVEL *toplevel,
        char *refdes,
        OBJECT *o_pin,
        STRING_LIST *new_pin_attrib_list)
{
    STRING_LIST *local_list;
    char *new_name_value_pair;
    char *new_attrib_name;
    char *new_attrib_value;
    char *old_attrib_value;

#if DEBUG
    printf("-----  Entering s_toplevel_update_pin_attribs_in_toplevel.\n");
#endif

    /* loop on name=value pairs held in new_pin_attrib_list */
    local_list = new_pin_attrib_list;
    while (local_list != NULL) {
        new_name_value_pair = g_strdup(local_list->data);
#if DEBUG
        printf("        In s_toplevel_update_pin_attribs_in_toplevel, handling entry in master list %s .\n", new_name_value_pair);
#endif

        new_attrib_name = u_basic_breakup_string(new_name_value_pair, '=', 0);
        new_attrib_value = u_basic_breakup_string(new_name_value_pair, '=', 1);

        if (strlen(new_attrib_value) == 0) {
            g_free(new_attrib_value);
            new_attrib_value = NULL;  /* s_misc_remaining_string doesn't return NULL for empty substring. */
        }
        old_attrib_value = o_attrib_search_attached_attribs_by_name (o_pin, new_attrib_name, 0);

        /* -------  Four cases to consider: Case 1: old and new attribs exist ----- */
        if ( (old_attrib_value != NULL) && (new_attrib_value != NULL) && (strlen(new_attrib_value) != 0) ) {
            /* simply write new attrib into place of old one. */
#if DEBUG
            printf("In s_toplevel_update_pin_attribs_in_toplevel, about to replace old attrib with new one: name= %s, value= %s\n",
                   new_attrib_name, new_attrib_value);
#endif
            s_object_replace_attrib_in_object(toplevel,
                                              o_pin,
                                              new_attrib_name,
                                              new_attrib_value,
                                              LEAVE_VISIBILITY_ALONE,
                                              LEAVE_NAME_VALUE_ALONE);
        }

        /* -------  Four cases to consider: Case 2: old attrib exists, new one doesn't ----- */
        else if ( (old_attrib_value != NULL) && (new_attrib_value == NULL) ) {
            /* remove attrib from pin */
#if DEBUG
            printf("In s_toplevel_update_pin_attribs_in_toplevel, about to remove old attrib with name= %s, value= %s\n",
                   new_attrib_name, old_attrib_value);
#endif
            s_object_remove_attrib_in_object (toplevel, o_pin, new_attrib_name);
        }

        /* -------  Four cases to consider: Case 3: No old attrib, new one exists. ----- */
        else if ( (old_attrib_value == NULL) && (new_attrib_value != NULL) ) {
            /* add new attrib to pin. */

#if DEBUG
            printf("In s_toplevel_update_pin_attribs_in_toplevel, about to add new attrib with name= %s, value= %s\n",
                   new_attrib_name, new_attrib_value);
#endif

            s_object_add_pin_attrib_to_object (toplevel,
                                               o_pin,
                                               new_attrib_name,
                                               new_attrib_value);

            /* -------  Four cases to consider: Case 4 ----- */
        } else {
            /* Do nothing. */
#if DEBUG
            printf("In s_toplevel_update_pin_attribs_in_toplevel, nothing needs to be done.\n");
#endif
        }

        /* free everything and iterate */
        g_free(new_name_value_pair);
        g_free(new_attrib_name);
        g_free(new_attrib_value);
        g_free(old_attrib_value);
        local_list = local_list->next;
    }   /*   while (local_list != NULL)  */

    return;
}
Esempio n. 8
0
/*! \brief Update component attributes in TOP_LEVEL
 *
 * For each attrib string attached to the component, update it using the value
 * held in new_comp_attrib_list.  Algorithm:
 * -# Form list of all component attribs held on both the component
 *    (o_current), as well as in the attrib list (SHEET_DATA).
 * -# Loop over name=value pairs held in complete_comp_attrib_list.
 * -# For each name=value pair, look for corresponding attrib on o_current.
 * -# For each name=value pair, look for the corresponding attrib in
 *    new_comp_attrib_list.
 * -# If the attrib exists on o_current and in new_comp_attrib_list, write the
 *    new value (from new_comp_attrib_list) into o_current.
 * -# If the attrib exists on o_current, but is null in name=value pair,
 *    delete the attrib from o_current.
 * -# If the attribs doesn't exist on o_current, but is non-null in
 *    the name=value pair, create an attrib object and add it to the part
 *    on o_current.
 * \param toplevel TOPLEVEL structure
 * \param o_current Component (complex) to be updated.
 * \param new_comp_attrib_list list of name=value attribute pairs
 *                             from SHEET_DATA.
 */
void
s_toplevel_update_component_attribs_in_toplevel (
    TOPLEVEL *toplevel,
    OBJECT *o_current,
    STRING_LIST *new_comp_attrib_list)
{
    STRING_LIST *local_list;
    STRING_LIST *complete_comp_attrib_list;
    char *old_name_value_pair;
    char *new_attrib_name;
    char *new_attrib_value;
    char *old_attrib_name;
    char *old_attrib_value;
    gchar *refdes;
    GList *a_iter;
    OBJECT *a_current;
    int count = 0;  /* This is to fake out a function called later */
    gint row, col;
    gint visibility = 0;
    gint show_name_value = 0;

#if DEBUG
    printf("-----  Entering s_toplevel_update_component_attribs_in_toplevel.\n");
#endif

    /*
     * To remove dead attribs from o_current, we need to form a complete list of unique
     * attribs by taking the union of the new attribs from the SHEET_DATA, and
     * the old attribs living on o_current.  That's what we're doing here.
     * Later, we can delete those attribs in o_current which don't apear in
     * new_comp_attrib_list.
     */
    /* First duplicate new_comp_attrib_list */
    complete_comp_attrib_list = s_string_list_duplicate_string_list(new_comp_attrib_list);

    /* Now create a complete list of unique attribute names.  This will be used in
    *  the loop below when updating attributes.  */
    a_iter = o_current->attribs;
    while (a_iter != NULL) {
        a_current = a_iter->data;
        if (a_current->type == OBJ_TEXT
                && a_current->text != NULL) {  /* found a name=value attribute pair. */
            /* may need to check more thoroughly here. . . . */
            old_name_value_pair = g_strdup(a_current->text->string);

            /* Else clause is suggestion from Ales */
#if 1
            old_attrib_name = u_basic_breakup_string(old_name_value_pair, '=', 0);
            if ( (strcmp(old_attrib_name, "refdes") != 0) &&
                    (strcmp(old_attrib_name, "net") != 0) &&
                    (strcmp(old_attrib_name, "slot") != 0) &&
                    (s_attrib_name_in_list(new_comp_attrib_list, old_attrib_name) == FALSE) ) {
                s_string_list_add_item(complete_comp_attrib_list, &count, old_name_value_pair);
            }
#else
            /* might now compile now, but this #if'd out branch isn't being built */
            gint status;
            status = o_attrib_get_name_value (a_current, &old_attrib_name, &old_attrib_value);
            if (status == 0) {
                /* Don't put "refdes" or "slot" into list.  Don't put old name=value pair into list if a new
                 * one is already in there. */
                if ( (strcmp(old_attrib_name, "refdes") != 0) &&
                        (strcmp(old_attrib_name, "net") != 0) &&
                        (strcmp(old_attrib_name, "slot") != 0) &&
                        (s_attrib_name_in_list(new_comp_attrib_list, old_attrib_name) == FALSE) ) {
                    s_string_list_add_item(complete_comp_attrib_list, &count, old_name_value_pair);
                }
                g_free (old_attrib_name);
                g_free (old_attrib_value);
            }
#endif
            g_free(old_name_value_pair);
            g_free(old_attrib_name);
        }
        a_iter = g_list_next (a_iter);
    }  /* while (a_current != NULL) */


    /*
     *Now the main business of this function:  updating the attribs attached to this o_current.
     * Loop on name=value pairs held in complete_comp_attrib_list , and then use this to get the
     * name=value pairs out of new_comp_attrib_list and from o_current.
     */

    /* First handle a special case: the component has no attribs (beside refdes). */
    if (complete_comp_attrib_list->data == NULL)
        return;

    /* Now the normal case. . . . */
    local_list = complete_comp_attrib_list;
    while (local_list != NULL) {

#if DEBUG
        printf("\n\n");
        printf("        In s_toplevel_update_component_attribs_in_toplevel, handling entry in complete list %s .\n",
               local_list->data);
#endif

        /*  Now get the old attrib name & value from complete_comp_attrib_list
         *  and value from o_current  */
        old_attrib_name = u_basic_breakup_string(local_list->data, '=', 0);
        old_attrib_value = o_attrib_search_attached_attribs_by_name (o_current, old_attrib_name, 0);

#if DEBUG
        printf("        In s_toplevel_update_component_attribs_in_toplevel, old name = \"%s\" .\n",
               old_attrib_name);
        printf("        In s_toplevel_update_component_attribs_in_toplevel, old value = \"%s\" .\n",
               old_attrib_value);
#endif

        /*  Next try to get this attrib from new_comp_attrib_list  */
        new_attrib_name = u_basic_breakup_string(local_list->data, '=', 0);
        if (s_string_list_in_list(new_comp_attrib_list, local_list->data)) {
            new_attrib_value = s_misc_remaining_string(local_list->data, '=', 1);
        } else {
            new_attrib_value = NULL;
        }
#if DEBUG
        printf("        In s_toplevel_update_component_attribs_in_toplevel, new name = \"%s\" .\n",
               new_attrib_name);
        printf("        In s_toplevel_update_component_attribs_in_toplevel, new value = \"%s\" .\n",
               new_attrib_value);
#endif

        /* Now get row and col where this new attrib lives.  Then get
         * visibility of the new attrib stored in the component table */
        /* We'll need this later */
        refdes = g_strdup(s_attrib_get_refdes(o_current));
        row = s_table_get_index(sheet_head->master_comp_list_head, refdes);
        col = s_table_get_index(sheet_head->master_comp_attrib_list_head, new_attrib_name);
        /* if attribute has been deleted from the sheet, here is where we detect that */
        if ( (row == -1) || (col == -1) ) {
            new_attrib_value = NULL;  /* attrib will be deleted below */
        } else { /* we need a better place to get this info since the TABLE can be out of date */
            visibility = sheet_head->component_table[row][col].visibility;
            show_name_value = sheet_head->component_table[row][col].show_name_value;
        }
        g_free(refdes);


        /* -------  Four cases to consider: Case 1 ----- */
        if ( (old_attrib_value != NULL) && (new_attrib_value != NULL) && (strlen(new_attrib_value) != 0) ) {
            /* simply write new attrib into place of old one. */
#if DEBUG
            printf("     -- In s_toplevel_update_component_attribs_in_toplevel,\n");
            printf("               about to replace old attrib with name= %s, value= %s\n",
                   new_attrib_name, new_attrib_value);
            printf("               visibility = %d, show_name_value = %d.\n",
                   visibility, show_name_value);
#endif
            s_object_replace_attrib_in_object(toplevel,
                                              o_current,
                                              new_attrib_name,
                                              new_attrib_value,
                                              visibility,
                                              show_name_value);
        }

        /* -------  Four cases to consider: Case 2 ----- */
        else if ( (old_attrib_value != NULL) && (new_attrib_value == NULL) ) {
            /* remove attrib from component*/
#if DEBUG
            printf("     -- In s_toplevel_update_component_attribs_in_toplevel, about to remove old attrib with name= %s, value= %s\n",
                   old_attrib_name, old_attrib_value);
#endif
            s_object_remove_attrib_in_object (toplevel, o_current, old_attrib_name);
        }

        /* -------  Four cases to consider: Case 3 ----- */
        else if ( (old_attrib_value == NULL) && (new_attrib_value != NULL) ) {
            /* add new attrib to component. */

#if DEBUG
            printf("     -- In s_toplevel_update_component_attribs_in_toplevel, about to add new attrib with name= %s, value= %s\n",
                   new_attrib_name, new_attrib_value);
#endif

            s_object_add_comp_attrib_to_object (toplevel,
                                                o_current,
                                                new_attrib_name,
                                                new_attrib_value,
                                                visibility,
                                                show_name_value);

            /* -------  Four cases to consider: Case 4 ----- */
        } else {
            /* Do nothing. */
#if DEBUG
            printf("     -- In s_toplevel_update_component_attribs_in_toplevel, nothing needs to be done.\n");
#endif
        }

        /* Toggle attribute visibility and name/value setting */


        /* free everything and iterate */
        g_free(new_attrib_name);
        g_free(new_attrib_value);
        g_free(old_attrib_name);
        g_free(old_attrib_value);
        local_list = local_list->next;
    }   /*   while (local_list != NULL)  */
    return;
}