[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: CVS update: g_rc.c



  User: peterb  
  Date: 07/05/28 03:56:47

  Modified:    .        g_rc.c g_register.c s_clib.c
  Log:
  Add component sources based on Scheme procedures.
  
  
  
  Add the ability to use a set of Scheme procedures which list and
  
  return component symbols as the backend of a component library.  Adds
  
  the g_rc_component_library_funcs() and s_clib_add_scm() functions to
  
  libgeda, as well as the component-library-funcs rc file function.
  
  
  
  
  Revision  Changes    Path
  1.5                  eda/geda/gaf/libgeda/src/g_rc.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: g_rc.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/libgeda/src/g_rc.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -b -r1.4 -r1.5
  --- g_rc.c	28 May 2007 07:48:31 -0000	1.4
  +++ g_rc.c	28 May 2007 07:56:47 -0000	1.5
  @@ -426,6 +426,37 @@
     return SCM_BOOL_T;
   }
   
  +/*! \brief Guile callback for adding library functions.
  + *  \par Function Description
  + *  Callback function for the "component-library-funcs" Guile
  + *  function, which can be used in the rc files to add a set of Guile
  + *  procedures for listing and generating symbols.
  + *
  + *  \param [in] listfunc A Scheme procedure which takes no arguments
  + *                       and returns a Scheme list of component names.
  + *  \param [in] getfunc A Scheme procedure which takes a component
  + *                      name as an argument and returns a symbol
  + *                      encoded in a string in gEDA format, or the \b
  + *                      \#f if the component name is unknown.
  + *
  + *  \returns SCM_BOOL_T on success, SCM_BOOL_F otherwise.
  + */
  +SCM g_rc_component_library_funcs (SCM listfunc, SCM getfunc, SCM name)
  +{
  +  SCM_ASSERT (scm_is_true (scm_procedure_p (listfunc)), listfunc, SCM_ARG1,
  +	      "component-library-funcs");
  +  SCM_ASSERT (scm_is_true (scm_procedure_p (getfunc)), getfunc, SCM_ARG2,
  +	      "component-library-funcs");
  +  SCM_ASSERT (SCM_STRINGP (name), name, SCM_ARG1, 
  +	      "component-library-funcs");
  +
  +  if (s_clib_add_scm (listfunc, getfunc, SCM_STRING_CHARS (name)) != NULL) {
  +    return SCM_BOOL_T;
  +  } else {
  +    return SCM_BOOL_F;
  +  }
  +}
  +
   /*! \todo Finish function description!!!
    *  \brief
    *  \par Function Description
  
  
  
  1.4                  eda/geda/gaf/libgeda/src/g_register.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: g_register.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/libgeda/src/g_register.c,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -b -r1.3 -r1.4
  --- g_register.c	28 May 2007 07:48:31 -0000	1.3
  +++ g_register.c	28 May 2007 07:56:47 -0000	1.4
  @@ -59,6 +59,7 @@
   static struct gsubr_t libgeda_funcs[] = {
     { "component-library",        1, 1, 0, g_rc_component_library },
     { "component-library-command", 1, 1, 0, g_rc_component_library_command },
  +  { "component-library-funcs",  3, 0, 0, g_rc_component_library_funcs },
     { "component-library-search", 1, 0, 0, g_rc_component_library_search },
     { "source-library",           1, 0, 0, g_rc_source_library },
     { "source-library-search",    1, 0, 0, g_rc_source_library_search },
  
  
  
  1.24                 eda/geda/gaf/libgeda/src/s_clib.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: s_clib.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/libgeda/src/s_clib.c,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -b -r1.23 -r1.24
  --- s_clib.c	28 May 2007 07:53:25 -0000	1.23
  +++ s_clib.c	28 May 2007 07:56:47 -0000	1.24
  @@ -158,10 +158,14 @@
   
   /*! Valid types of component source */
   enum CLibSourceType { 
  +  CLIB_NONE = 0,
     /*! Directory source */
     CLIB_DIR, 
     /*! Command source */
  -  CLIB_CMD };
  +  CLIB_CMD,
  +  /*! Guile function source */
  +  CLIB_SCM,
  +};
   
   /*! Stores data about a particular component source */
   struct _CLibSource {
  @@ -173,6 +177,9 @@
     gchar *name;
     /*! Available symbols (CLibSymbol) */
     GList *symbols;
  +
  +  SCM list_fn;
  +  SCM get_fn;
   };
   
   /*! Stores data about a particular symbol */
  @@ -203,8 +210,10 @@
   				      const gchar *name);
   static void refresh_directory (CLibSource *source);
   static void refresh_command (CLibSource *source);
  +static void refresh_scm (CLibSource *source);
   static gchar *get_data_directory (const CLibSymbol *symbol);
   static gchar *get_data_command (const CLibSymbol *symbol);
  +static gchar *get_data_scm (const CLibSymbol *symbol);
   
   /*! \brief Initialise the component library.
    *  \par Function Description
  @@ -259,6 +268,10 @@
         g_list_free (source->symbols);
         source->symbols = NULL;
       }
  +    if (source->type == CLIB_SCM) {
  +      scm_gc_unprotect_object (source->list_fn);
  +      scm_gc_unprotect_object (source->get_fn);
  +    }
     }
   }
   
  @@ -566,6 +579,59 @@
   				 (GCompareFunc) compare_symbol_name);
   }
   
  +/*! \brief Re-poll a scheme procedure for symbols.
  + *  \par Function Description
  + *  Calls a Scheme procedure to obtain a list of available symbols,
  + *  and updates the source with the new list
  + *
  + *  Private function used only in s_clib.c.
  + */
  +static void refresh_scm (CLibSource *source)
  +{
  +  SCM symlist;
  +  SCM symname;
  +  CLibSymbol *symbol;
  +
  +  g_assert (source != NULL);
  +  g_assert (source->type == CLIB_SCM);
  +
  +  /* Clear the current symbol list */
  +  g_list_foreach (source->symbols, (GFunc) free_symbol, NULL);
  +  g_list_free (source->symbols);
  +  source->symbols = NULL;
  +
  +  symlist = scm_call_0 (source->list_fn);
  +
  +  if (SCM_NCONSP (symlist) && (symlist != SCM_EOL)) {
  +    s_log_message ("Failed to scan library [%s]: Scheme function returned non-list\n",
  +		   source->name);
  +    return;
  +  }
  +
  +  while (symlist != SCM_EOL) {
  +    symname = SCM_CAR (symlist);
  +    if (!SCM_STRINGP (symname)) {
  +      s_log_message ("Non-string symbol name while scanning library [%s]\n",
  +		     source->name);
  +    } else {
  +      symbol = g_new0 (CLibSymbol, 1);
  +      symbol->source = source;
  +      symbol->name = g_strdup(SCM_STRING_CHARS (symname));
  +      
  +
  +      /* Prepend because it's faster and it doesn't matter what order we
  +       * add them. */
  +      source->symbols = g_list_prepend (source->symbols, symbol);
  +    }
  + 
  +    symlist = SCM_CDR (symlist);
  +  }
  +
  +  /* Now sort the list of symbols by name. */
  +  source->symbols = g_list_sort (source->symbols, 
  +				 (GCompareFunc) compare_symbol_name);
  +}
  +
   /*! \brief Rescan all available component libraries.
    *  \par Function Description
    *  Resets the list of symbols available from each source, and
  @@ -594,6 +660,9 @@
         case CLIB_CMD:
   	refresh_command (source);
   	break;
  +      case CLIB_SCM:
  +	refresh_scm (source);
  +	break;
         default:
   	g_assert_not_reached();
         }
  @@ -643,6 +712,7 @@
   const CLibSource *s_clib_add_directory (const gchar *directory, 
   					const gchar *name)
   {
  +  const CLibSource *oldsource;
     CLibSource *source;
     gchar *realname;
   
  @@ -656,8 +726,8 @@
       realname = g_strdup(name);
     }  
   
  -  source = s_clib_get_source_by_name (realname);
  -  if (source != NULL) {
  +  oldsource = s_clib_get_source_by_name (realname);
  +  if (oldsource != NULL) {
       s_log_message ("Cannot add library [%s]: name in use.",
   		   realname);
       g_free (realname);
  @@ -692,6 +762,7 @@
   const CLibSource *s_clib_add_command (const gchar *command,
   				      const gchar *name)
   {
  +  const CLibSource *oldsource;
     CLibSource *source;
     gchar *realname;
   
  @@ -705,9 +776,9 @@
       realname = g_strdup (name);
     }
     
  -  source = s_clib_get_source_by_name (realname);
  -  if (source != NULL) {
  -    s_log_message ("Cannot add library [%s]: name in use.",
  +  oldsource = s_clib_get_source_by_name (realname);
  +  if (oldsource != NULL) {
  +    s_log_message ("Cannot add library [%s]: name in use.\n",
   		   realname);
       g_free (realname);
       return NULL;
  @@ -720,12 +791,60 @@
   
     refresh_command (source);
   
  -  /* Sources added later get scanned earlier */
  +  /* Sources added later get sacnned earlier */
     clib_sources = g_list_prepend (clib_sources, source);
   
     return source;
   }
   
  +/*! \brief Add symbol-generating Scheme procedures to the library.
  + *  \par Function Description
  + *  Adds a source to the library based on Scheme procedures.  Two
  + *  procedures are required: \a listfunc must return a Scheme list of
  + *  symbol names, and \a getfunc must return a string containing
  + *  symbol data when passed a symbol name.
  + *
  + *  \param listfunc A Scheme function returning a list of symbols.
  + *  \param getfunc  A Scheme function returning symbol data.
  + *  \param name     A descriptive name for the component source.
  + *
  + *  \return         The new CLibSource.
  + */
  +const CLibSource *s_clib_add_scm (SCM listfunc, SCM getfunc, const gchar *name)
  +{
  +  const CLibSource *oldsource;
  +  CLibSource *source;
  +
  +  if (name == NULL) {
  +    s_log_message ("Cannot add library: name not specified\n");
  +    return NULL;
  +  }  
  +  
  +  oldsource = s_clib_get_source_by_name (name);
  +  if (oldsource != NULL) {
  +    s_log_message ("Cannot add library [%s]: name in use.\n", name);
  +    return NULL;
  +  }
  +
  +  if (scm_is_false (scm_procedure_p (listfunc)) 
  +      && scm_is_false (scm_procedure_p (getfunc))) {
  +    s_log_message ("Cannot add Scheme-library [%s]: callbacks must be closures\n",
  +		   name);
  +    return NULL;
  +  }
  +
  +  source = g_new0 (CLibSource, 1);
  +  source->type = CLIB_SCM;
  +  source->name = g_strdup (name);
  +  source->list_fn = scm_gc_protect_object (listfunc);
  +  source->get_fn = scm_gc_protect_object (getfunc);
  +
  +  refresh_scm (source);
  +
  +  clib_sources = g_list_prepend (clib_sources, source);
  +
  +  return source;
  +}
   
   /*! \brief Get the name of a source.
    *  \par Function Description
  @@ -873,6 +992,25 @@
     return run_source_command ( argv );
   }
   
  +static gchar *get_data_scm (const CLibSymbol *symbol)
  +{
  +  SCM symdata;
  +
  +  g_assert (symbol != NULL);
  +  g_assert (symbol->source->type == CLIB_SCM);
  +
  +  symdata = scm_call_1 (symbol->source->get_fn, 
  +			scm_from_locale_string (symbol->name));
  +
  +  if (!SCM_STRINGP (symdata)) {
  +    s_log_message ("Failed to load symbol data [%s] from source [%s]\n",
  +		   symbol->name, symbol->source->name);
  +    return NULL;
  +  }
  +
  +  return g_strdup (SCM_STRING_CHARS (symdata));
  +}
  +
   /*! \brief Get symbol data.
    *  \par Function Description
    *  Get the unparsed gEDA-format data corresponding to a symbol from
  @@ -894,6 +1032,8 @@
         return get_data_directory (symbol);
       case CLIB_CMD:
         return get_data_command (symbol);
  +    case CLIB_SCM:
  +      return get_data_scm (symbol);
       default:
         g_assert_not_reached();
       }
  
  
  


_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs