1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2000 Ales V. Hvezda
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 * <B>clib</B> stands for component library.
22 * A component library is made of several directories gathering
25 * It must first be initialized with #s_clib_init(). When it is no more
26 * useful, use #s_clib_free() to free memory and reset the component
29 * To add a directory to the library, use #s_clib_add_directory().
31 * To retrieve a list of the directories that make the library, use
32 * #s_clib_get_directories(). For a list of component files in a
33 * directory of the library, use #s_clib_get_files().
35 * #s_clib_search_basename() let you find a specific component from
36 * its name. Please note that it returns a list of directories as there
37 * may be several places that contains a component with this name.
48 #ifdef HAVE_LIBDMALLOC
55 void s_clib_free (void);
57 static GList
*clib_directories
= NULL
;
59 static GHashTable
*clib_cache
= NULL
;
61 /*! \brief Initializes the component library handling code.
62 * \par Function Description
63 * Initializes the component library handling code.
64 * \warning This function must be called before any other function
67 void s_clib_init (void)
69 if (clib_directories
!= NULL
|| clib_cache
!= NULL
) {
73 clib_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
77 /*! \todo Finish function documentation!!!
79 * \par Function Description
82 static void clib_free_cache_entry (gpointer key
, gpointer value
,
87 /* value is a singly-linked list of strings */
88 g_list_foreach (value
, (GFunc
)g_free
, NULL
);
89 g_slist_free ((GSList
*)value
);
93 /*! \brief Frees memory used by the component library.
94 * \par Function Description
95 * Frees memory used by the component library.
97 void s_clib_free (void)
99 if (clib_directories
!= NULL
) {
100 g_list_foreach (clib_directories
, (GFunc
)g_free
, NULL
);
101 g_list_free (clib_directories
);
102 clib_directories
= NULL
;
105 if (clib_cache
!= NULL
) {
106 g_hash_table_foreach (clib_cache
, clib_free_cache_entry
, NULL
);
107 g_hash_table_destroy (clib_cache
);
113 /*! \brief Adds a new directory to the component library.
114 * \par Function Description
115 * Adds <B>directory</B> as a new directory for the component library.
117 * \param [in] directory Character string with the new directory name.
119 void s_clib_add_directory (const gchar
*directory
)
121 /* search for directory in clib_directories */
122 if (!g_list_find_custom (clib_directories
,
124 (GCompareFunc
) g_strcasecmp
))
126 /* directory not yet in the list of known directories */
127 /* add directory to list */
128 clib_directories
= g_list_append (clib_directories
,
129 g_strdup (directory
));
134 /*! \brief Get list of component library directories.
135 * \par Function Description
136 * This function returns the list of directories part of
137 * the component library.
139 * \return Global libgead #clib_directories variable.
141 * The returned value is owned by libgeda and must not be modified or freed.
144 const GList
*s_clib_get_directories()
146 return clib_directories
;
149 /*! \brief Get a list of files found a directory.
150 * \par Function Description
151 * This function returns a list of file names found in <B>directory</B> and
152 * that match <B>filter</B>
154 * \param [in] directory Character string with the path to search.
155 * \param [in] filter Character string to compare file names against.
156 * \return List of file name that matched <B>filter</B>, NULL otherwise.
158 GSList
*s_clib_get_files (const gchar
*directory
, const gchar
*filter
)
164 /* check directory is in clib_directories */
165 if (g_list_find_custom (clib_directories
,
167 (GCompareFunc
) g_strcasecmp
) == NULL
)
169 /* no, unknown directory: report an error */
170 s_log_message ("Directory [%s] is not part of the component library\n",
175 /* open the directory */
176 dir
= g_dir_open (directory
, 0, NULL
);
178 s_log_message ("Failed to open directory [%s]\n", directory
);
182 /* now read the entire directory */
183 /* and build a list of filenames in directory that match filter */
184 while ((entry
= g_dir_read_name (dir
)) != NULL
) {
186 if (entry
[0] == '.') {
190 /* identify filter-matching filenames */
191 if (strstr (entry
, filter
)) {
192 ret
= g_slist_append (ret
, (gpointer
)g_strdup (entry
));
197 /* finished: close the directory stream */
200 /* sort the list alphabetically */
201 ret
= g_slist_sort (ret
, (GCompareFunc
)g_strcasecmp
);
203 /* and return the sorted list of filenames */
207 /*! \brief Search for a symbol file in the component library.
208 * \par Function Description
209 * Searches in component library for a symbol file with name <B>basename</B>.
211 * \param [in] basename Character string with base symbol name to search for.
212 * \return List of directories where symbol file with this name was found,
216 * The returned value is owned by libgeda and must not be modified or freed.
219 const GSList
*s_clib_search_basename(const gchar
*basename
)
224 /* first check if basename is in cache */
225 ret
= g_hash_table_lookup (clib_cache
, basename
);
227 /* yes, found basename in cache, nothing more to do */
231 /* looks like we have to search for basename in the library */
232 for (tmp
= g_list_last(clib_directories
);
233 tmp
!= NULL
; tmp
= g_list_previous (tmp
)) {
234 gchar
*dir_name
= (gchar
*)tmp
->data
;
235 gchar
*file_name
= g_strconcat (dir_name
,
240 if (g_file_test (file_name
, G_FILE_TEST_EXISTS
)) {
241 /* add directory name to the list */
242 ret
= g_slist_append (ret
, g_strdup (dir_name
));
248 /* have we found something? */
250 /* yes, add the result to cache */
251 g_hash_table_insert (clib_cache
, g_strdup (basename
), ret
);