/*! \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);
}
示例#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;
}
示例#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;
          }
       }
    }
}
示例#4
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);
}
示例#5
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);
}