/* gEDA - GPL Electronic Design Automation * libgeda - gEDA's library * Copyright (C) 1998-2000 Ales V. Hvezda * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA */ /*! slib stands for source (project/schematic/hdl/model source) library */ #include #include #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_DIRENT_H #include #endif #include #include #include "defines.h" #include "struct.h" #include "globals.h" #include "../include/prototype.h" #ifdef HAVE_LIBDMALLOC #include #endif /* need to test everything at boundary conditions (exceed cache size etc...) */ /*! \brief */ struct st_slib { char *dir_name; }; /*! \brief */ static int slib_index=0; /*! \brief */ #define MAX_SLIBS 128 /*! \brief * and eventually make this unlimited * hack hack */ static struct st_slib slib[MAX_SLIBS]; /*! \todo Finish function documentation!!! * \brief * \par Function Description * */ int s_slib_add_entry(char *new_path) { if (new_path == NULL) { return(-1); } if (slib_index >= MAX_SLIBS) { return(-1); } slib[slib_index].dir_name = (char *) g_malloc(sizeof(char)*strlen(new_path)+1); strcpy(slib[slib_index].dir_name, new_path); slib_index++; return(slib_index); } /*! \todo Finish function documentation!!! * \brief * \par Function Description * * \return 1 if directory is found, zero otherwise. */ int s_slib_search_for_dirname(char *dir_name) { int i; for (i = 0; i < slib_index; i++) { if (strcmp(slib[i].dir_name, dir_name) == 0) { return(1); } } return(0); } /*! \todo Finish function documentation!!! * \brief * \par Function Description * * \warning * Caller must free returned pointer. */ char *s_slib_search_dirs(const char *basename) { int i; int len; DIR *ptr=NULL; struct dirent *dptr; char *slib_path=NULL; /* search slib paths backwards */ for (i = slib_index-1 ; i >= 0; i--) { /* for (i = 0 ; i < slib_index; i++) {*/ #if DEBUG printf("searching: %d %s\n", i, slib[i].dir_name); #endif ptr = opendir(slib[i].dir_name); if (ptr == NULL) { fprintf(stderr, "Oops got a null dir_name!\n"); exit(-1); } dptr = readdir(ptr); while(dptr != NULL) { /* Do a substring comp for a match */ if (strstr(dptr->d_name, basename) != NULL) { len = strlen(slib[i].dir_name); slib_path = (char *) g_malloc(sizeof(char)*len+1); strcpy(slib_path, slib[i].dir_name); if (ptr) { closedir(ptr); ptr = NULL; } return(slib_path); } dptr = readdir(ptr); } if (ptr) { closedir(ptr); ptr = NULL; } } if (ptr) { closedir(ptr); ptr = NULL; } return(NULL); } /*! \todo Finish function documentation!!! * \brief * \par Function Description * * \warning * Caller must free returned pointer. */ char *s_slib_search_lowlevel(const char *basename) { char *slib_path=NULL; char *full_path=NULL; int len; slib_path = s_slib_search_dirs(basename); if (slib_path) { /* return type */ s_log_message("Found [%s]\n", basename); /* s_log_message("Found [%s] in [%s]\n", basename, slib_path);*/ len = strlen(basename)+strlen(slib_path); /* The 2 is for NULL char and the slash inbetween the two */ /* strings */ full_path = (char *) g_malloc(sizeof(char)*(len+2)); sprintf(full_path, "%s%c%s", slib_path, G_DIR_SEPARATOR, basename); g_free(slib_path); return(full_path); } else { s_log_message("Could not find [%s] in any SourceLibrary\n", basename); #if DEBUG fprintf(stderr, "Could not find [%s] in any SourceLibrary\n", basename); #endif return(NULL); } } /*! \todo Finish function documentation!!! * \brief Get the base file name from a raw file name string. * \par Function Description * This function takes a raw file name and returns a processed file name. * It takes the raw file name and copies everything up to the first period * and removes any _# (where # is any number of digits. * * \param [in] rawname Character string with the raw file name to parse. * \return The base file name in a character string. * * \warning * Caller must free returned pointer. */ char *s_slib_getbasename(const char *rawname) { char *return_filename; char *copy; int i; int done=0; int lastchar; int valid=0; int len; int seen_underscore=0; if (!rawname) return(NULL); len = strlen(rawname)+1; return_filename = (char *) g_malloc(sizeof(char)*len); i = 0; /* first get everything up to the leading dot */ while(rawname[i] != '\0' && rawname[i] != '.') { return_filename[i] = rawname[i]; i++; } return_filename[i] = '\0'; /* keep filename for safe keeping */ copy = return_filename; /* skip null terminator */ i--; lastchar=i; /* this is a quick and dirty state machine to */ /* go back and strip off any _#'s */ /* if there is a better way let me know */ while (i >= 0 && !done) { /* first we need to check to see if we have seen the first '_' */ /* if we have then we already removing chars, continue with that */ if ( seen_underscore ) { if (return_filename[i] == '_') { done = 1; } return_filename[i] = '\0'; } else { /* we are still searching for the first underscore */ /* first make sure char is a number */ if (isdigit((int) return_filename[i])) { valid=1; } else if (return_filename[i] == '_' && valid) { /* yes it is okay to delete the chars */ seen_underscore=1; /* incremented, since it is then */ /* decremented */ i = lastchar+1; } else { valid = 0; done = 1; } } i--; } /* be sure to free this somewhere */ return(return_filename); } /*! \todo Finish function documentation!!! * \brief Search SLIB for a particular file name. * \par Function Description * This function will search the SLIB for a particular file name starting * at a location specified by the flag parameter. * * \param [in] filename Character string with file name to search for. * \param [in] flag Specifies search start location. (See below...) * * The flag parameter can be one of the following values: *
*
SLIB_SEARCH_START
Starts a new search for a source file. *
SLIB_SEARCH_NEXT
Returns the next instance of the file if * one exists. *
SLIB_SEARCH_DONE
Finish searching. *
* * Filename is the raw symbol/whatever file name. This function does all the * required stripping (up to the first period). * * \warning * Caller must free returned pointer. */ char *s_slib_search(const char *filename, int flag) { char *processed_name=NULL; char *new_filename=NULL; char *string=NULL; char *number_suffix; int len; int len2; static int count; switch(flag) { case(SLIB_SEARCH_START): count = 0; string=NULL; break; case(SLIB_SEARCH_NEXT): count++; /* be sure to free processed_name */ processed_name = s_slib_getbasename(filename); #if DEBUG printf("proced: %s\n", processed_name); #endif len = strlen(processed_name); /* for now only look for .sch's */ /* this needs to be *MUCH* more flexible */ /* number_suffix is large enough ? */ number_suffix = g_strdup_printf("_%d.sch", count); len2 = strlen(number_suffix); new_filename = (char *) g_malloc (sizeof(char)*(len+len2+1)); sprintf(new_filename, "%s%s", processed_name, number_suffix); string = s_slib_search_lowlevel(new_filename); g_free(new_filename); g_free(number_suffix); break; case(SLIB_SEARCH_DONE): count = 0; string=NULL; break; } if (processed_name) g_free(processed_name); /* don't forget to free this string */ return(string); } /*! \todo Finish function documentation!!! * \brief Search SLIB for a particular file name. * \par Function Description * This function will search the SLIB for a particular file name starting * at a location specified by the flag parameter. * * \param [in] filename Character string with file name to search for. * * Filename is the raw symbol/whatever file name. This function only looks * for the file name as is and does no other changes to it. * * \warning * Caller must free returned pointer. */ char *s_slib_search_single(const char *filename) { char *string=NULL; string = s_slib_search_lowlevel(filename); /* don't forget to free this string */ return(string); } /*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void s_slib_free() { int i; for (i = 0; i < slib_index; i++) { if (slib[i].dir_name) g_free(slib[i].dir_name); } slib_index=0; } /*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void s_slib_init() { int i; for (i = 0; i < MAX_SLIBS; i++) { slib[i].dir_name = NULL; } } /*! \todo Finish function documentation!!! * \brief * \par Function Description * * \warning * Caller must free returned pointer. */ /* returns slibs */ char *s_slib_getdir(int index) { if (slib[index].dir_name != NULL) return(slib[index].dir_name); else return(NULL); } /*! \todo Finish function documentation!!! * \brief * \par Function Description * * \param [in] directory Character string with directory to get files from. * \param [in] flag Search control flag. (See below...) * \return A file name if one is found, NULL otherwise. * * \warning * Caller must free returned pointer. * * The flag parameter can be one of the following values: *
*
OPEN_DIR
Opens the directory and returns NULL. *
READ_DIR
Returns the next non "." entry. *
CLOSE_DIR
Closes the directory. *
* \bug This is TOTTALLY BROKEN! * statics are not allowed anymore * \warning * this function is not reentrant */ char *s_slib_getfiles(char *directory, int flag) { static DIR *ptr; static struct dirent *dptr; static char *whole_dir[256]; /* make this dynamic hack */ static int count=0; static int current=0; int j; int len; switch(flag) { case(CLOSE_DIR): if (ptr) { closedir(ptr); } ptr = NULL; for (j = 0 ; j < count ;j++) { if (whole_dir[j]) g_free(whole_dir[j]); } count = current = 0 ; return(NULL); break; /* open the directory and return first element (after if) */ case(OPEN_DIR): if (ptr) { closedir(ptr); } ptr = NULL; for (j = 0 ; j < count ;j++) { if (whole_dir[j]) g_free(whole_dir[j]); } count = current = 0 ; ptr = opendir(directory); /* hack check for existance */ if (ptr == NULL) return(NULL); /* now read the entire directory */ dptr = readdir(ptr); while (dptr != NULL) { /* skip .'s */ while (dptr != NULL) { if (dptr->d_name[0] == '.') { dptr = readdir(ptr); } else { break; } } if (dptr == NULL) { break; } if (dptr->d_name != NULL) { len = strlen(dptr->d_name); /* hack */ if (count < 256) { whole_dir[count] = (char *) g_malloc(sizeof(char)*len+1); strcpy(whole_dir[count], dptr->d_name); count++; } else { fprintf(stderr, "uggg. too many files in s_slib_getfiles!\n"); exit(-1); } } dptr = readdir(ptr); } return(NULL); break; case(READ_DIR): if (whole_dir[current] && current < count) { return(whole_dir[current++]); } else { return(NULL); } break; default: return(NULL); } #if DEBUG for (j = 0;j < count; j++) { printf("string: %s\n", whole_dir[j]); } #endif } /*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void s_slib_print(void) { int i; for (i = 0; i < slib_index; i++) { printf("%s\n", slib[i].dir_name); } } /*! \todo Finish function documentation!!! * \brief * \par Function Description * */ int s_slib_uniq(char *path) { if (s_slib_search_for_dirname(path)) { #if DEBUG printf("found\n"); #endif return(0); } else { #if DEBUG printf("NOT found\n"); #endif return(1); } } /*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void s_slib_print_dirs(void) { int i; char *string; char *file; i = 0; string = s_slib_getdir(i); while(string != NULL) { s_slib_getfiles(string, OPEN_DIR); printf("Opened %s\n", string); file = (char *) s_slib_getfiles(string, READ_DIR); while(file != NULL) { printf("file: %s\n", file); file = (char *) s_slib_getfiles(string, READ_DIR); } printf("Closed %s\n", string); s_slib_getfiles(string, CLOSE_DIR); i++; string = s_slib_getdir(i); } }