libgeda: Remove some exit() calls and assertions.
[geda-gaf/peter-b.git] / libgeda / src / s_slib.c
blobd97a1d9b9ea54f6d2ef43fcd6414b34a27f4b6ef
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /*! slib stands for source (project/schematic/hdl/model source) library */
22 #include <config.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <ctype.h>
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #include <dirent.h>
35 #include "libgeda_priv.h"
37 #ifdef HAVE_LIBDMALLOC
38 #include <dmalloc.h>
39 #endif
41 /* need to test everything at boundary conditions (exceed cache size etc...) */
43 /*! \brief */
44 struct st_slib {
45 char *dir_name;
48 /*! \brief */
49 static int slib_index=0;
51 /*! \brief */
52 #define MAX_SLIBS 128
54 /*! \brief
55 * and eventually make this unlimited
56 * hack hack
58 static struct st_slib slib[MAX_SLIBS];
60 /*! \todo Finish function documentation!!!
61 * \brief
62 * \par Function Description
65 int s_slib_add_entry(char *new_path)
67 if (new_path == NULL) {
68 return(-1);
71 if (slib_index >= MAX_SLIBS) {
72 return(-1);
75 slib[slib_index].dir_name = g_strdup (new_path);
77 slib_index++;
78 return(slib_index);
81 /*! \todo Finish function documentation!!!
82 * \brief
83 * \par Function Description
85 * \return 1 if directory is found, zero otherwise.
87 int s_slib_search_for_dirname(char *dir_name)
89 int i;
91 for (i = 0; i < slib_index; i++) {
92 if (strcmp(slib[i].dir_name, dir_name) == 0) {
93 return(1);
97 return(0);
100 /*! \todo Finish function documentation!!!
101 * \brief
102 * \par Function Description
104 * \warning
105 * Caller must g_free returned pointer.
107 char *s_slib_search_dirs(const char *basename)
109 int i;
110 DIR *ptr=NULL;
111 struct dirent *dptr;
112 char *slib_path=NULL;
114 /* search slib paths backwards */
115 for (i = slib_index-1 ; i >= 0; i--) {
116 /* for (i = 0 ; i < slib_index; i++) {*/
118 #if DEBUG
119 printf("searching: %d %s\n", i, slib[i].dir_name);
120 #endif
122 ptr = opendir(slib[i].dir_name);
124 g_return_val_if_fail ((ptr != NULL), NULL);
126 dptr = readdir(ptr);
128 while(dptr != NULL) {
130 /* Do a substring comp for a match */
131 if (strstr(dptr->d_name, basename) != NULL) {
132 slib_path = g_strdup (slib[i].dir_name);
134 if (ptr) {
135 closedir(ptr);
136 ptr = NULL;
139 return(slib_path);
141 dptr = readdir(ptr);
144 if (ptr) {
145 closedir(ptr);
146 ptr = NULL;
151 if (ptr) {
152 closedir(ptr);
153 ptr = NULL;
156 return(NULL);
159 /*! \todo Finish function documentation!!!
160 * \brief
161 * \par Function Description
163 * \warning
164 * Caller must g_free returned pointer.
166 char *s_slib_search_lowlevel(const char *basename)
168 char *slib_path=NULL;
169 char *full_path=NULL;
171 slib_path = s_slib_search_dirs(basename);
173 if (slib_path) {
174 /* return type */
176 s_log_message(_("Found [%s]\n"), basename);
177 /* s_log_message("Found [%s] in [%s]\n", basename, slib_path);*/
179 full_path = g_build_filename (slib_path, basename, NULL);
181 g_free(slib_path);
183 return(full_path);
184 } else {
186 s_log_message(_("Could not find [%s] in any SourceLibrary\n"), basename);
188 return(NULL);
192 /*! \todo Finish function documentation!!!
193 * \brief Get the base file name from a raw file name string.
194 * \par Function Description
195 * This function takes a raw file name and returns a processed file name.
196 * It takes the raw file name and copies everything up to the first period
197 * and removes any _# (where # is any number of digits.
199 * \param [in] rawname Character string with the raw file name to parse.
200 * \return The base file name in a character string.
202 * \warning
203 * Caller must g_free returned pointer.
205 char *s_slib_getbasename(const char *rawname)
207 char *return_filename;
208 int i;
209 int done=0;
210 int lastchar;
211 int valid=0;
212 int len;
213 int seen_underscore=0;
215 if (!rawname)
216 return(NULL);
218 len = strlen(rawname)+1;
220 return_filename = (char *) g_malloc(sizeof(char)*len);
222 i = 0;
223 /* first get everything up to the leading dot */
224 while(rawname[i] != '\0' && rawname[i] != '.') {
225 return_filename[i] = rawname[i];
226 i++;
230 return_filename[i] = '\0';
232 /* skip null terminator */
233 i--;
235 lastchar=i;
237 /* this is a quick and dirty state machine to */
238 /* go back and strip off any _#'s */
239 /* if there is a better way let me know */
240 while (i >= 0 && !done) {
242 /* first we need to check to see if we have seen the first '_' */
243 /* if we have then we already removing chars, continue with that */
244 if ( seen_underscore ) {
245 if (return_filename[i] == '_') {
246 done = 1;
249 return_filename[i] = '\0';
250 } else {
251 /* we are still searching for the first underscore */
253 /* first make sure char is a number */
254 if (isdigit((int) return_filename[i])) {
255 valid=1;
256 } else if (return_filename[i] == '_' && valid) {
257 /* yes it is okay to delete the chars */
258 seen_underscore=1;
259 /* incremented, since it is then */
260 /* decremented */
261 i = lastchar+1;
262 } else {
263 valid = 0;
264 done = 1;
268 i--;
271 /* be sure to g_free this somewhere */
272 return(return_filename);
275 /*! \todo Finish function documentation!!!
276 * \brief Search SLIB for a particular file name.
277 * \par Function Description
278 * This function will search the SLIB for a particular file name starting
279 * at a location specified by the <B>flag</B> parameter.
281 * \param [in] filename Character string with file name to search for.
282 * \param [in] flag Specifies search start location. (See below...)
284 * The <B>flag</B> parameter can be one of the following values:
285 * <DL>
286 * <DT>SLIB_SEARCH_START</DT><DD>Starts a new search for a source file.
287 * <DT>SLIB_SEARCH_NEXT</DT><DD>Returns the next instance of the file if
288 * one exists.
289 * <DT>SLIB_SEARCH_DONE</DT><DD>Finish searching.
290 * </DL>
292 * Filename is the raw symbol/whatever file name. This function does all the
293 * required stripping (up to the first period).
295 * \warning
296 * Caller must g_free returned pointer.
298 char *s_slib_search(const char *filename, int flag)
300 char *processed_name=NULL;
301 char *new_filename=NULL;
302 char *string=NULL;
303 static int count;
305 switch(flag) {
306 case(SLIB_SEARCH_START):
307 count = 0;
308 string=NULL;
309 break;
311 case(SLIB_SEARCH_NEXT):
312 count++;
314 /* be sure to g_free processed_name */
315 processed_name = s_slib_getbasename(filename);
317 #if DEBUG
318 printf("proced: %s\n", processed_name);
319 #endif
321 /* for now only look for .sch's */
322 /* this needs to be *MUCH* more flexible */
323 /* number_suffix is large enough ? */
324 new_filename = g_strdup_printf ("%s_%d.sch", processed_name, count);
326 string = s_slib_search_lowlevel(new_filename);
328 g_free(new_filename);
329 break;
331 case(SLIB_SEARCH_DONE):
332 count = 0;
333 string=NULL;
334 break;
337 g_free(processed_name);
339 /* don't forget to g_free this string */
340 return(string);
343 /*! \todo Finish function documentation!!!
344 * \brief Search SLIB for a particular file name.
345 * \par Function Description
346 * This function will search the SLIB for a particular file name starting
347 * at a location specified by the <B>flag</B> parameter.
349 * \param [in] filename Character string with file name to search for.
351 * Filename is the raw symbol/whatever file name. This function only looks
352 * for the file name as is and does no other changes to it.
354 * \warning
355 * Caller must g_free returned pointer.
357 char *s_slib_search_single(const char *filename)
359 char *string=NULL;
361 string = s_slib_search_lowlevel(filename);
363 /* don't forget to g_free this string */
364 return(string);
367 /*! \todo Finish function documentation!!!
368 * \brief
369 * \par Function Description
372 void s_slib_free()
374 int i;
376 for (i = 0; i < slib_index; i++) {
377 g_free(slib[i].dir_name);
380 slib_index=0;
383 /*! \todo Finish function documentation!!!
384 * \brief
385 * \par Function Description
388 void s_slib_init()
390 int i;
391 for (i = 0; i < MAX_SLIBS; i++) {
392 slib[i].dir_name = NULL;
396 /*! \todo Finish function documentation!!!
397 * \brief
398 * \par Function Description
400 * \warning
401 * Caller must not free the returned pointer.
403 /* returns slibs */
404 char *s_slib_getdir(int index)
406 if (slib[index].dir_name != NULL)
407 return(slib[index].dir_name);
408 else
409 return(NULL);
412 /*! \todo Finish function documentation!!!
413 * \brief
414 * \par Function Description
416 * \param [in] directory Character string with directory to get files from.
417 * \param [in] flag Search control flag. (See below...)
418 * \return A file name if one is found, NULL otherwise.
420 * \warning
421 * Caller must g_free returned pointer.
423 * The flag parameter can be one of the following values:
424 * <DL>
425 * <DT>OPEN_DIR</DT><DD>Opens the directory and returns NULL.
426 * <DT>READ_DIR</DT><DD>Returns the next non "." entry.
427 * <DT>CLOSE_DIR</DT><DD>Closes the directory.
428 * </DL>
429 * \bug This is TOTTALLY BROKEN!
430 * statics are not allowed anymore
431 * \warning
432 * this function is not reentrant
434 char *s_slib_getfiles(char *directory, int flag)
436 static DIR *ptr;
437 static struct dirent *dptr;
438 static char *whole_dir[256]; /* make this dynamic hack */
439 static int count=0;
440 static int current=0;
442 int j;
444 switch(flag) {
446 case(CLOSE_DIR):
447 if (ptr) {
448 closedir(ptr);
451 ptr = NULL;
453 for (j = 0 ; j < count ;j++) {
454 g_free(whole_dir[j]);
456 count = current = 0 ;
458 return(NULL);
459 break;
461 /* open the directory and return first element (after if) */
462 case(OPEN_DIR):
464 if (ptr) {
465 closedir(ptr);
468 ptr = NULL;
470 for (j = 0 ; j < count ;j++) {
471 g_free(whole_dir[j]);
473 count = current = 0 ;
475 ptr = opendir(directory); /* hack check for existance */
477 if (ptr == NULL)
478 return(NULL);
481 /* now read the entire directory */
482 dptr = readdir(ptr);
484 while (dptr != NULL) {
486 /* skip .'s */
487 while (dptr != NULL) {
488 if (dptr->d_name[0] == '.') {
489 dptr = readdir(ptr);
490 } else {
491 break;
495 if (dptr == NULL) {
496 break;
499 if (dptr->d_name != NULL) {
500 /* hack */
501 if (count < 256) {
503 whole_dir[count] = g_strdup (dptr->d_name);
504 count++;
505 } else {
506 g_error ("uggg. too many files in s_slib_getfiles!\n");
510 dptr = readdir(ptr);
512 return(NULL);
514 break;
516 case(READ_DIR):
519 if (whole_dir[current] && current < count) {
520 return(whole_dir[current++]);
521 } else {
522 return(NULL);
525 break;
527 default:
528 return(NULL);
531 #if DEBUG
532 for (j = 0;j < count; j++) {
533 printf("string: %s\n", whole_dir[j]);
535 #endif
539 /*! \todo Finish function documentation!!!
540 * \brief
541 * \par Function Description
544 void s_slib_print(void)
546 int i;
548 for (i = 0; i < slib_index; i++) {
549 printf("%s\n", slib[i].dir_name);
553 /*! \todo Finish function documentation!!!
554 * \brief
555 * \par Function Description
558 int s_slib_uniq(char *path)
560 if (s_slib_search_for_dirname(path)) {
562 #if DEBUG
563 printf("found\n");
564 #endif
565 return(0);
566 } else {
568 #if DEBUG
569 printf("NOT found\n");
570 #endif
572 return(1);
576 /*! \todo Finish function documentation!!!
577 * \brief
578 * \par Function Description
581 void s_slib_print_dirs(void)
583 int i;
584 char *string;
585 char *file;
587 i = 0;
588 string = s_slib_getdir(i);
589 while(string != NULL) {
591 s_slib_getfiles(string, OPEN_DIR);
592 printf("Opened %s\n", string);
594 file = (char *) s_slib_getfiles(string, READ_DIR);
596 while(file != NULL) {
597 printf("file: %s\n", file);
598 file = (char *) s_slib_getfiles(string, READ_DIR);
601 printf("Closed %s\n", string);
602 s_slib_getfiles(string, CLOSE_DIR);
603 i++;
604 string = s_slib_getdir(i);