Random comments from a drive-by read through ... just FYI,
I'll focus a bit more down the road.

I'm ecstatic to see at least a start at
        --with-rubyembed
wire-up.

hth

73 de Jeff
On Sep 18, 2010, at 12:37 PM, Eric Veith wrote:
...

> 
>  +    } 
>  +

There's a hack-o-round memset(3) that needs to go right here if you want 
calloc(3) like behavior.
The alternative is to ensure that everything gets initialized properly ... 
forget a pointer
and you WILL die. I tend to flip-flop between the two extremes depending ...

>       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);
>  +    }

I hate the unneeded braces ... no worries, my fetish, will fix.

>       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;
>  +    }
> 

WHat should be done here is to process common CLI options, i.e.
whatever options you commonly use invoking /usr/bin/ruby.

I'm not a ruby programmer so I haven't a clue (but I can guess
from using other interpreters)

If you can hint about which, say, 5 CLI options are the most important, I'll
stub those into a popt table so that the general form of the embedded macro 
syntax

        %{ruby OPTS ARGS:BODY}

can start to be used.

>  -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);

I tend to do a DBG(...) wrapping these days. If done with an I->flags bit,
it would be possible to have per-interpreter debugging.

>  +    /* 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-...@rpm5.org

______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
Developer Communication List                        rpm-devel@rpm5.org

Reply via email to