RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Eric Veith
  Root:   /v/rpm/cvs                       Email:  eve...@rpm5.org
  Module: rpm                              Date:   18-Sep-2010 18:37:06
  Branch: HEAD                             Handle: 2010091816370600

  Modified files:
    rpm/rpmio               rpmruby.c rpmruby.h

  Log:
    Prevented embedded Ruby interpreter from being initialized twice

  Summary:
    Revision    Changes     Path
    2.16        +101 -71    rpm/rpmio/rpmruby.c
    2.9         +110 -53    rpm/rpmio/rpmruby.h
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmruby.c
  ============================================================================
  $ cvs diff -u -r2.15 -r2.16 rpmruby.c
  --- rpm/rpmio/rpmruby.c       16 Aug 2010 13:17:41 -0000      2.15
  +++ rpm/rpmio/rpmruby.c       18 Sep 2010 16:37:06 -0000      2.16
  @@ -1,28 +1,28 @@
   #include "system.h"
   #include <argv.h>
   
  -/* XXX grrr, ruby.h includes its own config.h too. */
   #ifdef       HAVE_CONFIG_H
   #include "config.h"
   #endif
  -#undef       PACKAGE_NAME
  -#undef       PACKAGE_TARNAME
  -#undef       PACKAGE_VERSION
  -#undef       PACKAGE_STRING
  -#undef       PACKAGE_BUGREPORT
  +
   
   #if defined(WITH_RUBYEMBED)
  +
  +/* Make sure Ruby's fun stuff has its own xmalloc & Co functions available */
  +
  +#undef xmalloc
  +#undef xcalloc
  +#undef xrealloc
  +
   #include <ruby.h>
   
  -#if !defined(RSTRING_PTR)
  -/* XXX retrofit for ruby-1.8.5 in CentOS5 */
  -#define RSTRING_PTR(s) (RSTRING(s)->ptr)
  -#define RSTRING_LEN(s) (RSTRING(s)->len)
   #endif
   
  -#endif
   
  -#define _RPMRUBY_INTERNAL
  +/**
  + * Allows access to the gory details of rpmruby pool items.
  + */
  +#define _RPMRUBY_INTERNAL 1
   #include "rpmruby.h"
   
   #include "debug.h"
  @@ -33,22 +33,42 @@
   /*...@unchecked@*/ /*...@relnull@*/
   rpmruby _rpmrubyI = NULL;
   
  -static void rpmrubyFini(void * _ruby)
  +
  +
  +/**
  + * Finalizes a Ruby interpreter instance/pool item
  + */
  +static void rpmrubyFini(void *_ruby)
           /*...@globals fileSystem @*/
           /*...@modifies *_ruby, fileSystem @*/
   {
       rpmruby ruby = _ruby;
   
  -#if defined(WITH_RUBYEMBED)
  -    ruby_finalize();
  -    ruby_cleanup(0);
  -#endif
  +#   if defined(WITH_RUBYEMBED)
  +        ruby_cleanup(0); 
  +#   endif
       ruby->I = NULL;
   }
   
  +
  +/**
  +* The pool of Ruby interpreter instances
  +* @see rpmioPool
  +*/
   /*...@unchecked@*/ /*...@only@*/ /*...@null@*/
   rpmioPool _rpmrubyPool;
   
  +
  +/**
  + * Returns the current rpmio pool responsible for Ruby interpreter instances
  + *
  + * This is a wrapper function that returns the current rpmio pool responsible
  + * for embedded Ruby interpreters. It creates and initializes a new pool when
  + * there is no current pool.
  + *
  + * @return The current pool
  + * @see rpmioNewPool
  + */
   static rpmruby rpmrubyGetPool(/*...@null@*/ rpmioPool pool)
           /*...@globals _rpmrubyPool, fileSystem @*/
           /*...@modifies pool, _rpmrubyPool, fileSystem @*/
  @@ -57,90 +77,100 @@
   
       if (_rpmrubyPool == NULL) {
           _rpmrubyPool = rpmioNewPool("ruby", sizeof(*ruby), -1, 
_rpmruby_debug,
  -                        NULL, NULL, rpmrubyFini);
  +            NULL, NULL, rpmrubyFini);
           pool = _rpmrubyPool;
  -    }
  +    } 
  +
       return (rpmruby) rpmioGetPool(pool, sizeof(*ruby));
   }
   
  +
   /*...@unchecked@*/
   #if defined(WITH_RUBYEMBED)
  +
  +/** Initializes Ruby's StringIO for storing output in a string. */
   static const char * rpmrubyInitStringIO = "\
   require 'stringio'\n\
   $stdout = StringIO.new($result, \"w+\")\n\
   ";
  +
   #endif
   
  -static rpmruby rpmrubyI(void)
  -     /*...@globals _rpmrubyI @*/
  -     /*...@modifies _rpmrubyI @*/
  +
  +static rpmruby rpmrubyI()
  +        /*...@globals _rpmrubyI @*/
  +        /*...@modifies _rpmrubyI @*/
   {
  -    if (_rpmrubyI == NULL)
  -     _rpmrubyI = rpmrubyNew(NULL, 0);
  +    if (NULL == _rpmrubyI) {
  +        _rpmrubyI = rpmrubyNew(NULL, 0);
  +    }
       return _rpmrubyI;
   }
   
  -rpmruby rpmrubyNew(char ** av, uint32_t flags)
  -{
  -    rpmruby ruby =
  -#ifdef       NOTYET
  -     (flags & 0x80000000) ? rpmrubyI() :
  -#endif
  -     rpmrubyGetPool(_rpmrubyPool);
  -
  -    static char * _av[] = { "rpmruby", NULL };
   
  -    if (av == NULL) av = _av;
  +rpmruby rpmrubyNew(char **av, uint32_t flags)
  +{
  +    /* TODO: Once Ruby allows several interpreter instances, distinguish
  +     * between the global interpreter (1<<31 flag) and a new one.
  +     */
  +    
  +    if (NULL != _rpmrubyI) {
  +        return _rpmrubyI;
  +    }
   
  -#if defined(WITH_RUBYEMBED)
  -    ruby_init();
  -    ruby_init_loadpath();
  -    ruby_script((char *)av[0]);
  -    ruby_set_argv(argvCount((ARGV_t)av)-1, av+1);
  -    rb_gv_set("$result", rb_str_new2(""));
  -    (void) rpmrubyRun(ruby, rpmrubyInitStringIO, NULL);
  -#endif
  +    rpmruby ruby = rpmrubyGetPool(_rpmrubyPool);
   
  -    return rpmrubyLink(ruby);
  -}
  +    static char *_av[] = { "rpmruby", NULL };
  +    if (NULL == av) {
  +        av = _av;
  +    }
   
  -rpmRC rpmrubyRunFile(rpmruby ruby, const char * fn, const char ** resultp)
  -{
  -    rpmRC rc = RPMRC_FAIL;
   
  -if (_rpmruby_debug)
  -fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, ruby, fn);
  +    /* Set up embedded Ruby interpreter if embedded Ruby is enabled. */
   
  -    if (ruby == NULL) ruby = rpmrubyI();
  +#   if defined(WITH_RUBYEMBED)
  +        RUBY_INIT_STACK;
  +        ruby_init();
  +        ruby_init_loadpath();
  +
  +        ruby_script((char *)av[0]);
  +        rb_gv_set("$result", rb_str_new2(""));
  +        (void) rpmrubyRun(ruby, rpmrubyInitStringIO, NULL);
  +#   endif
   
  -    if (fn != NULL) {
  -#if defined(WITH_RUBYEMBED)
  -     rb_load_file(fn);
  -     ruby->state = ruby_exec();
  -     if (resultp != NULL)
  -         *resultp = RSTRING_PTR(rb_gv_get("$result"));
  -     rc = RPMRC_OK;
  -#endif
  -    }
  -    return rc;
  +    return rpmrubyLink(ruby);
   }
   
  -rpmRC rpmrubyRun(rpmruby ruby, const char * str, const char ** resultp)
  +
  +rpmRC rpmrubyRun(rpmruby ruby, const char *str, const char **resultp)
   {
       rpmRC rc = RPMRC_FAIL;
   
  -if (_rpmruby_debug)
  -fprintf(stderr, "==> %s(%p,%s,%p)\n", __FUNCTION__, ruby, str, resultp);
  +    if (_rpmruby_debug) {
  +        fprintf(stderr, "==> %s(%p,%s,%p)\n",
  +            __FUNCTION__, ruby, str, resultp);
  +    }
   
  -    if (ruby == NULL) ruby = rpmrubyI();
  +    if (NULL == ruby) {
  +        ruby = rpmrubyI();
  +    }
   
  -    if (str != NULL) {
  -#if defined(WITH_RUBYEMBED)
  -     ruby->state = rb_eval_string(str);
  -     if (resultp != NULL)
  -         *resultp = RSTRING_PTR(rb_gv_get("$result"));
  -     rc = RPMRC_OK;
  -#endif
  +    if (NULL != str) {
  +#       if defined(WITH_RUBYEMBED)
  +            int state = -1;
  +            ruby->state = rb_eval_string_protect(str, &state);
  +
  +            /* Check whether the evaluation was successful or not */
  +
  +            if(0 == state) {
  +                rc = RPMRC_OK;
  +                if (resultp != NULL) {
  +                    *resultp = RSTRING_PTR(rb_gv_get("$result"));
  +                }
  +            }
  +#       endif
       }
  +
       return rc;
   }
  +
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmruby.h
  ============================================================================
  $ cvs diff -u -r2.8 -r2.9 rpmruby.h
  --- rpm/rpmio/rpmruby.h       7 Apr 2010 03:20:06 -0000       2.8
  +++ rpm/rpmio/rpmruby.h       18 Sep 2010 16:37:06 -0000      2.9
  @@ -1,108 +1,165 @@
   #ifndef RPMRUBY_H
   #define RPMRUBY_H
   
  -/** \ingroup rpmio
  +
  +/**
    * \file rpmio/rpmruby.h
  + * \ingroup rpmio
  + *
  + * Embedded Ruby interpreter
  + *
  + * This allows the embedding of the Ruby interpreter into RPM5. It can be
  + * used, for example, for expanding in the fashion of
  + * <tt>%%expand{ruby ...}</tt>.
  + *
  + * Currently (as of ruby-1.9.2), the Ruby interpreter allows only one 
instance
  + * of itself per process. As such, rpmio's pooling mechanism will also always
  + * contain only one ::rpmruby instance. Calling rpmrubyNew() will initialize
  + * a new interpreter, while rpmrubyFree() beds this instance. Make sure you
  + * keep things in order, that is, call rpmrubyNew() exactly once, and don't
  + * forget to call rpmrubyFree() when you're done. Repeatedly calling
  + * rpmrubyNew will have no effect while an interpreter is allocated.
  + *
  + * You can use rpmrubyRun() to evaluate Ruby code and get the result back.
    */
   
  +
   #include <rpmiotypes.h>
   #include <rpmio.h>
   
  -typedef /*...@abstract@*/ /*...@refcounted@*/ struct rpmruby_s * rpmruby;
   
  +/** Triggers printing of debugging information */
   /*...@unchecked@*/
   extern int _rpmruby_debug;
   
  +typedef /*...@abstract@*/ /*...@refcounted@*/ struct rpmruby_s* rpmruby;
  +
  +/**
  + * Current (global) interpreter instance
  + *
  + * At the moment, this variable is merely a safeguard against initializing 
the
  + * Ruby interpreter over and over again. In the future, when there is Ruby
  + * support for multiple interpreter instances, a flag given to rpmrubyNew()
  + * will use this variable and return the global interpreter instance.
  + */
   /*...@unchecked@*/ /*...@relnull@*/
   extern rpmruby _rpmrubyI;
   
  +
   #if defined(_RPMRUBY_INTERNAL)
  +
  +/**
  + * Instances of this struct carry an embedded Ruby interpreter and the state
  + * associated with it.
  + */
   struct rpmruby_s {
  -    struct rpmioItem_s _item;        /*!< usage mutex and pool identifier. */
  -    void * I;
  +
  +    /**
  +     * Pool identifier, including usage mutex, etc.
  +     * \see rpmioItem_s
  +     */
  +    struct rpmioItem_s _item;
  +
  +    /** The actual interpreter instance */
  +    void *I;
  +
  +    /**
  +     * Carries the interpreter's current state, e.g. the latest return code.
  +     * */
       unsigned long state;
  +
   #if defined(__LCLINT__)
  -/*...@refs@*/
  -    int nrefs;                       /*!< (unused) keep splint happy */
  +    /** Reference count: Currently unused, only to keep splint happy. */
  +    /*...@refs@*/
  +    int nrefs;
   #endif
   };
  +
   #endif /* _RPMRUBY_INTERNAL */
   
  +
   #ifdef __cplusplus
   extern "C" {
   #endif
   
  +
   /**
  - * Unreference a ruby interpreter instance.
  - * @param ruby               ruby interpreter
  - * @return           NULL on last dereference
  + * Dereferences a Ruby interpreter instance in the rpmio pool
  + *
  + * @param ruby Ruby interpreter pool item
  + * @return NULL on last dereference
  + * @see rpmUnlinkPoolItem
    */
   /*...@unused@*/ /*...@null@*/
   rpmruby rpmrubyUnlink (/*...@killref@*/ /*...@only@*/ /*...@null@*/ rpmruby 
ruby)
  -     /*...@modifies ruby @*/;
  -#define      rpmrubyUnlink(_ruby)    \
  -    ((rpmruby)rpmioUnlinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, 
__FILE__, __LINE__))
  +    /*...@modifies ruby @*/;
  +#define      rpmrubyUnlink(_ruby) \
  +    ((rpmruby)rpmioUnlinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, \
  +        __FILE__, __LINE__))
  +
   
   /**
  - * Reference a ruby interpreter instance.
  - * @param ruby               ruby interpreter
  - * @return           new ruby interpreter reference
  + * References a Ruby interpreter instance in the rpmio pool
  + *
  + * @param ruby Ruby interpreter
  + * @return A new ruby interpreter reference
  + * @see rpmioLinkPoolItem
    */
   /*...@unused@*/ /*...@newref@*/ /*...@null@*/
   rpmruby rpmrubyLink (/*...@null@*/ rpmruby ruby)
        /*...@modifies ruby @*/;
  -#define      rpmrubyLink(_ruby)      \
  -    ((rpmruby)rpmioLinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, __FILE__, 
__LINE__))
  +#define      rpmrubyLink(_ruby) \
  +    ((rpmruby)rpmioLinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, \
  +        __FILE__, __LINE__))
  +
   
   /**
  - * Destroy a ruby interpreter.
  - * @param ruby               ruby interpreter
  - * @return           NULL on last dereference
  + * Destroys a Ruby interpreter instance in the rpmio pool
  + *
  + * @param ruby The Ruby interpreter to be destroyed
  + * @return NULL on last dereference
  + * @see rpmioFreePoolItem
    */
   /*...@null@*/
  -rpmruby rpmrubyFree(/*...@killref@*/ /*...@null@*/rpmruby ruby)
  +rpmruby rpmrubyFree(/*...@killref@*/ /*...@null@*/ rpmruby ruby)
        /*...@globals fileSystem @*/
        /*...@modifies ruby, fileSystem @*/;
   #define      rpmrubyFree(_ruby)      \
  -    ((rpmruby)rpmioFreePoolItem((rpmioItem)(_ruby), __FUNCTION__, __FILE__, 
__LINE__))
  +    ((rpmruby)rpmioFreePoolItem((rpmioItem)(_ruby), __FUNCTION__, \
  +        __FILE__, __LINE__))
  +
   
   /**
  - * Create and load a ruby interpreter.
  - * @param av         ruby interpreter args (or NULL)
  - * @param flags              ruby interpreter flags ((1<<31): use global 
interpreter)
  - * @return           new ruby interpreter
  + * Creates and initializes a Ruby interpreter
  + *
  + * @param av Arguments to the Ruby interpreter (may be NULL)
  + * @param flags      Ruby interpreter flags; ((1<<31): use global 
interpreter)
  + * @return A new Ruby interpreter
    */
   /*...@newref@*/ /*...@null@*/
  -rpmruby rpmrubyNew(/*...@null@*/ char ** av, uint32_t flags)
  -     /*...@globals fileSystem, internalState @*/
  -     /*...@modifies fileSystem, internalState @*/;
  -
  -/**
  - * Execute ruby from a file.
  - * @param ruby               ruby interpreter (NULL uses global interpreter)
  - * @param fn         ruby file to run (NULL returns RPMRC_FAIL)
  - * @param *resultp   ruby exec result
  - * @return           RPMRC_OK on success
  - */
  -rpmRC rpmrubyRunFile(rpmruby ruby, /*...@null@*/ const char * fn,
  -             /*...@null@*/ const char ** resultp)
  -     /*...@globals fileSystem, internalState @*/
  -     /*...@modifies ruby, fileSystem, internalState @*/;
  -
  -/**
  - * Execute ruby string.
  - * @param ruby               ruby interpreter (NULL uses global interpreter)
  - * @param str                ruby string to execute (NULL returns RPMRC_FAIL)
  - * @param *resultp   ruby exec result
  - * @return           RPMRC_OK on success
  - */
  -rpmRC rpmrubyRun(rpmruby ruby, /*...@null@*/ const char * str,
  -             /*...@null@*/ const char ** resultp)
  -     /*...@globals fileSystem, internalState @*/
  -     /*...@modifies ruby, *resultp, fileSystem, internalState @*/;
  +rpmruby rpmrubyNew(/*...@null@*/ char **av, uint32_t flags)
  +    /*...@globals fileSystem, internalState @*/
  +    /*...@modifies fileSystem, internalState @*/;
  +
  +
  +/**
  + * Evaluates Ruby code stored in a string
  + *
  + * @param ruby The Ruby interpreter that is to be used 
  + *  (NULL uses global interpreter)
  + * @param str Ruby code to evaluate (NULL forces return of RPMRC_FAIL)
  + * @param *resultp Result of the evaluation
  + * @return RPMRC_OK on success
  + */
  +rpmRC rpmrubyRun(rpmruby ruby, /*...@null@*/ const char *str,
  +        /*...@null@*/ const char **resultp)
  +    /*...@globals fileSystem, internalState @*/
  +    /*...@modifies ruby, *resultp, fileSystem, internalState @*/;
  +
   
   #ifdef __cplusplus
   }
   #endif
   
   #endif /* RPMRUBY_H */
  +
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to