libgeda

s_hierarchy.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines