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