RPM Community Forums

Mailing List Message of <rpm-cvs>

[CVS] RPM: rpm/rpmio/ rpmruby.c rpmruby.h

From: Eric Veith <eveith@rpm5.org>
Date: Sat 18 Sep 2010 - 18:37:06 CEST
Message-Id: <20100918163706.B6F40C1A29@rpm5.org>
  RPM Package Manager, CVS Repository
  /cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Eric Veith
  Root:   /v/rpm/cvs                       Email:  eveith@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 */
  +
  @@ .
Received on Sat Sep 18 18:37:06 2010
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.