libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 00022 #include <stdio.h> 00023 #ifdef HAVE_STDLIB_H 00024 #include <stdlib.h> 00025 #endif 00026 00027 #include "libgeda_priv.h" 00028 00029 #ifdef HAVE_LIBDMALLOC 00030 #include <dmalloc.h> 00031 #endif 00032 00034 static int page_control_counter=0; 00035 00062 PAGE * 00063 s_hierarchy_down_schematic_single(TOPLEVEL *toplevel, const gchar *filename, 00064 PAGE *parent, int page_control, int flag) 00065 { 00066 gchar *string; 00067 PAGE *found = NULL; 00068 PAGE *forbear; 00069 00070 g_return_val_if_fail ((toplevel != NULL), NULL); 00071 g_return_val_if_fail ((filename != NULL), NULL); 00072 g_return_val_if_fail ((parent != NULL), NULL); 00073 00074 string = s_slib_search_single(filename); 00075 if (string == NULL) { 00076 return NULL; 00077 } 00078 00079 switch (flag) { 00080 case HIERARCHY_NORMAL_LOAD: 00081 { 00082 gchar *filename = f_normalize_filename (string, NULL); 00083 found = s_page_search (toplevel, filename); 00084 g_free (filename); 00085 00086 if (found) { 00087 /* check whether this page is in the parents list */ 00088 for (forbear = parent; 00089 forbear != NULL && found->pid != forbear->pid && forbear->up >= 0; 00090 forbear = s_page_search_by_page_id (toplevel->pages, forbear->up)) 00091 ; /* void */ 00092 00093 if (forbear != NULL && found->pid == forbear->pid) { 00094 s_log_message(_("hierarchy loop detected while visiting page:\n" 00095 " \"%s\"\n"), found->page_filename); 00096 return NULL; /* error signal */ 00097 } 00098 s_page_goto (toplevel, found); 00099 if (page_control != 0) { 00100 found->page_control = page_control; 00101 } 00102 found->up = parent->pid; 00103 g_free (string); 00104 return found; 00105 } 00106 00107 found = s_page_new (toplevel, string); 00108 00109 f_open (toplevel, found, found->page_filename, NULL); 00110 } 00111 break; 00112 00113 case HIERARCHY_FORCE_LOAD: 00114 { 00115 found = s_page_new (toplevel, string); 00116 f_open (toplevel, found, found->page_filename, NULL); 00117 } 00118 break; 00119 00120 default: 00121 g_return_val_if_reached (NULL); 00122 } 00123 00124 if (page_control == 0) { 00125 page_control_counter++; 00126 found->page_control = page_control_counter; 00127 } else { 00128 found->page_control = page_control; 00129 } 00130 00131 found->up = parent->pid; 00132 00133 g_free (string); 00134 00135 return found; 00136 } 00137 00143 void 00144 s_hierarchy_down_symbol (TOPLEVEL *toplevel, const CLibSymbol *symbol, 00145 PAGE *parent) 00146 { 00147 PAGE *page; 00148 gchar *filename; 00149 00150 filename = s_clib_symbol_get_filename (symbol); 00151 00152 page = s_page_search (toplevel, filename); 00153 if (page) { 00154 /* change link to parent page since we 00155 * can come here from any parent and must 00156 * come back to the same page */ 00157 page->up = parent->pid; 00158 s_page_goto (toplevel, page); 00159 g_free (filename); 00160 return; 00161 } 00162 00163 page = s_page_new (toplevel, filename); 00164 g_free(filename); 00165 00166 s_page_goto (toplevel, page); 00167 00168 f_open(toplevel, page, page->page_filename, NULL); 00169 00170 page->up = parent->pid; 00171 page_control_counter++; 00172 page->page_control = page_control_counter; 00173 00174 } 00175 00190 PAGE * 00191 s_hierarchy_find_up_page (GedaPageList *page_list, PAGE *current_page) 00192 { 00193 if (current_page->up < 0) { 00194 s_log_message(_("There are no schematics above the current one!\n")); 00195 return NULL; 00196 } 00197 00198 return s_page_search_by_page_id (page_list, current_page->up); 00199 } 00200 00218 GList * 00219 s_hierarchy_traversepages (TOPLEVEL *toplevel, PAGE *p_current, gint flags) 00220 { 00221 OBJECT *o_current; 00222 PAGE *child_page; 00223 char *filename = NULL; 00224 static GList *pages = NULL; 00225 const GList *iter; 00226 00227 g_return_val_if_fail ((toplevel != NULL), NULL); 00228 g_return_val_if_fail ((p_current != NULL), NULL); 00229 00230 /* init static variables the first time*/ 00231 if (!(flags & HIERARCHY_INNERLOOP)) { 00232 pages = NULL; 00233 } 00234 00235 /* preorder traversing */ 00236 if (!(flags & HIERARCHY_POSTORDER)) { 00237 /* check whether we already visited this page */ 00238 if ((flags & HIERARCHY_NODUPS) 00239 && (g_list_find (pages, p_current) != NULL)) { 00240 return pages; /* drop the page subtree */ 00241 } 00242 pages = g_list_append (pages, p_current); 00243 } 00244 00245 /* walk throught the page objects and search for underlaying schematics */ 00246 for (iter = s_page_objects (p_current); 00247 iter != NULL ; 00248 iter = g_list_next (iter)) { 00249 o_current = (OBJECT *)iter->data; 00250 00251 /* only complex things like symbols can contain attributes */ 00252 if (o_current->type != OBJ_COMPLEX) continue; 00253 00254 filename = 00255 o_attrib_search_attached_attribs_by_name (o_current, "source", 0); 00256 00257 /* if above is NULL, then look inside symbol */ 00258 if (filename == NULL) { 00259 filename = 00260 o_attrib_search_inherited_attribs_by_name (o_current, "source", 0); 00261 } 00262 00263 if (filename == NULL) continue; 00264 00265 /* we got a schematic source attribute 00266 lets load the page and dive into it */ 00267 child_page = 00268 s_hierarchy_down_schematic_single (toplevel, filename, p_current, 0, 00269 HIERARCHY_NORMAL_LOAD); 00270 if (child_page != NULL) { 00271 /* call the recursive function */ 00272 s_hierarchy_traversepages (toplevel, child_page, flags | HIERARCHY_INNERLOOP); 00273 } else { 00274 s_log_message (_("ERROR in s_hierarchy_traverse: " 00275 "schematic not found: %s\n"), 00276 filename); 00277 } 00278 00279 g_free (filename); 00280 filename = NULL; 00281 } 00282 00283 /* postorder traversing */ 00284 if (flags & HIERARCHY_POSTORDER) { 00285 /* check whether we already visited this page */ 00286 if ((flags & HIERARCHY_NODUPS) 00287 && (g_list_find (pages, p_current) != NULL)) { 00288 return pages; /* don't append it */ 00289 } 00290 pages = g_list_append (pages, p_current); 00291 } 00292 00293 return pages; 00294 } 00295 00303 gint 00304 s_hierarchy_print_page (PAGE *p_current, void * data) 00305 { 00306 printf("pagefilename: %s pageid: %d\n", 00307 p_current->page_filename, p_current->pid); 00308 return 0; 00309 } 00310 00326 PAGE * 00327 s_hierarchy_find_prev_page (GedaPageList *page_list, PAGE *current_page) 00328 { 00329 const GList *iter; 00330 00331 iter = g_list_find (geda_list_get_glist (page_list), current_page); 00332 for (iter = g_list_previous (iter); 00333 iter != NULL; 00334 iter = g_list_previous (iter)) { 00335 00336 PAGE *page = (PAGE *)iter->data; 00337 if (page->page_control == current_page->page_control) { 00338 return page; 00339 } 00340 } 00341 00342 return NULL; 00343 } 00344 00360 PAGE * 00361 s_hierarchy_find_next_page (GedaPageList *page_list, PAGE *current_page) 00362 { 00363 const GList *iter; 00364 00365 iter = g_list_find (geda_list_get_glist (page_list), current_page); 00366 for (iter = g_list_next (iter); 00367 iter != NULL; 00368 iter = g_list_next (iter)) { 00369 00370 PAGE *page = (PAGE *)iter->data; 00371 if (page->page_control == current_page->page_control) { 00372 return page; 00373 } 00374 } 00375 00376 return NULL; 00377 }