Nice! There's a _LOT_ that can be with a macro context object as a bag of KEY:VALUE string pairs for templating.
There's a fair amount of work to use multiple macro contexts with RPM itself for hysterical reasons. But macro expansions are a cheap means to use any of the embeddings, and there's always %(...) to fire up helpers. hth 73 de Jeff On Oct 30, 2010, at 7:31 PM, Eric Veith wrote: > 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: 31-Oct-2010 01:31:26 > Branch: HEAD Handle: 2010103023312600 > > Modified files: > rpm/ruby rpmmc-rb.c > > Log: > Add macro name/opts/body split code from lua to rpmmc-rb.c's list code > - Add split code from rpmio/rpmlua.c > - Add more type checking with Ruby's Check_Type macro > > Summary: > Revision Changes Path > 1.4 +127 -29 rpm/ruby/rpmmc-rb.c > ____________________________________________________________________________ > > patch -p0 <<'@@ .' > Index: rpm/ruby/rpmmc-rb.c > ============================================================================ > $ cvs diff -u -r1.3 -r1.4 rpmmc-rb.c > --- rpm/ruby/rpmmc-rb.c 2 May 2009 17:16:25 -0000 1.3 > +++ rpm/ruby/rpmmc-rb.c 30 Oct 2010 23:31:26 -0000 1.4 > @@ -9,9 +9,11 @@ > > #define _MACRO_INTERNAL > #include <rpmmacro.h> > +#include <rpmio/argv.h> > > #include "../debug.h" > > + > typedef MacroContext rpmmc; > > VALUE rpmmcClass; > @@ -19,7 +21,9 @@ > /*...@unchecked@*/ > static int _debug = 0; > > + > /* --- helpers */ > + > static void * > rpmmc_ptr(VALUE s) > { > @@ -28,65 +32,142 @@ > return ptr; > } > > + > /* --- Object methods */ > + > +/** > + * Adds a new macro definition to the Macro Context. > + * > + * call-seq: > + * RPM::Mc#add(macro) -> nil > + * > + * @param macro The macro definition in string form just like it would be > done > + * in a macro definition file, but minus the %define stanza. > + * @see rpmDefineMacro() > + */ > static VALUE > rpmmc_add(VALUE s, VALUE v) > { > + Check_Type(v, T_STRING); > + > void *ptr = rpmmc_ptr(s); > rpmmc mc = ptr; > int lvl = 0; > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx, 0x%lx) ptr %p\n", __FUNCTION__, s, v, ptr); > + > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx, 0x%lx) ptr %p\n", > + __FUNCTION__, s, v, ptr); > + > (void) rpmDefineMacro(mc, StringValueCStr(v), lvl); > - return Qtrue; > + return Qnil; > } > > + > +/** > + * Deletes a macro definition. > + * > + * call-seq: > + * RPM::Mc#del(macro) -> nil > + * > + * @param macro The macro name > + * @see rpmUndefineMacro() > + */ > static VALUE > rpmmc_del(VALUE s, VALUE v) > { > + Check_Type(v, T_STRING); > + > void *ptr = rpmmc_ptr(s); > rpmmc mc = ptr; > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx, 0x%lx) ptr %p\n", __FUNCTION__, s, v, ptr); > + > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx, 0x%lx) ptr %p\n", > + __FUNCTION__, s, v, ptr); > + > (void) rpmUndefineMacro(mc, StringValueCStr(v)); > - return Qtrue; > + return Qnil; > } > > + > +/** > + * List all macro definitions in the corresponding Macro Context. > + * > + * call-seq: > + * RPM::Mc#list() -> Array > + * > + * @return A list of all macro definitions in form of an array of arrays, > + * where each nested arry contains the macro's name, arguments (or an empty > + * string) and the macro body. > + */ > static VALUE > rpmmc_list(VALUE s) > { > void *ptr = rpmmc_ptr(s); > rpmmc mc = ptr; > - VALUE v = rb_ary_new(); > void * _mire = NULL; > + VALUE v = rb_ary_new(); > int used = -1; > const char ** av = NULL; > int ac = rpmGetMacroEntries(mc, _mire, used, &av); > > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx) ptr %p\n", __FUNCTION__, s, ptr); > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx) ptr %p\n", __FUNCTION__, s, ptr); > > if (ac > 0 && av != NULL && av[0] != NULL) { > - int i; > - for (i = 0; i < ac; i++) { > - /* XXX lua splits into {name,opts,body} triple. */ > - rb_ary_push(v, rb_str_new2(av[i])); > - } > + int i; > + for (i = 0; i < ac; i++) { > + /* Parse out "%name(opts)\tbody" into n/o/b strings. */ > + > + char *name = (char *)av[i]; > + char *body = strchr(name, '\t'); > + assert(body != NULL); > + char *opts = ((body > name && body[-1] == ')') ? > + strchr(name, '(') : NULL); > + > + if (*name == '%') name++; > + if (opts != NULL && *opts == '(') { > + body[-1] = '\0'; > + opts++; > + opts[-1] = '\0'; > + } else { > + body[0] = '\0'; > + opts = ""; > + } > + body++; > + > + VALUE nob_ary = rb_ary_new3(3, rb_str_new2(name), > + rb_str_new2(opts), rb_str_new2(body)); > + rb_ary_push(v, nob_ary); > + } > } > + > + argvFree(av); > return v; > } > > + > +/** > + * Expands a macro. > + * > + * call-seq: > + * RPM::Mc#expand(macro) -> String > + * > + * @param macro The macro name (with leading % sign) > + * @return The result of the expansion > + */ > static VALUE > rpmmc_expand(VALUE s, VALUE v) > { > void *ptr = rpmmc_ptr(s); > rpmmc mc = ptr; > char * vstr = StringValueCStr(v); > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx, 0x%lx) ptr %p \"%s\"\n", __FUNCTION__, s, v, > ptr, vstr); > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx, 0x%lx) ptr %p \"%s\"\n", > + __FUNCTION__, s, v, ptr, vstr); > return rb_str_new2(rpmMCExpand(mc, vstr, NULL)); > } > > + > static void > initMethods(VALUE klass) > { > @@ -96,23 +177,35 @@ > rb_define_method(klass, "expand", rpmmc_expand, 1); > } > > + > /* --- Object properties */ > + > +/** > + * Get debugging log level > + * > + * call-seq: > + * RPM::Mc#debug -> Fixnum > + * > + * @return The debugging level > + */ > static VALUE > rpmmc_debug_get(VALUE s) > { > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx)\n", __FUNCTION__, s); > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx)\n", __FUNCTION__, s); > return INT2FIX(_debug); > } > > + > static VALUE > rpmmc_debug_set(VALUE s, VALUE v) > { > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx, 0x%lx)\n", __FUNCTION__, s, v); > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx, 0x%lx)\n", __FUNCTION__, s, v); > return INT2FIX(_debug = FIX2INT(v)); > } > > + > static void > initProperties(VALUE klass) > { > @@ -120,37 +213,42 @@ > rb_define_method(klass, "debug=", rpmmc_debug_set, 1); > } > > + > /* --- Object ctors/dtors */ > + > static void > rpmmc_free(rpmmc mc) > { > -if (_debug) > -fprintf(stderr, "==> %s(%p)\n", __FUNCTION__, mc); > + if (_debug) > + fprintf(stderr, "==> %s(%p)\n", __FUNCTION__, mc); > > if (!(mc == rpmGlobalMacroContext || mc == rpmCLIMacroContext)) { > - rpmFreeMacros(mc); > - mc = _free(mc); > + rpmFreeMacros(mc); > + mc = _free(mc); > } > } > > + > static VALUE > rpmmc_alloc(VALUE klass) > { > rpmmc mc = xcalloc(1, sizeof(*mc)); > VALUE obj = Data_Wrap_Struct(klass, 0, rpmmc_free, mc); > -if (_debug) > -fprintf(stderr, "==> %s(0x%lx) obj 0x%lx mc %p\n", __FUNCTION__, klass, > obj, mc); > + if (_debug) > + fprintf(stderr, "==> %s(0x%lx) obj 0x%lx mc %p\n", > + __FUNCTION__, klass, obj, mc); > return obj; > } > > + > /* --- Class initialization */ > > void > Init_rpmmc(void) > { > - rpmmcClass = rb_define_class("Mc", rb_cObject); > -if (_debug) > -fprintf(stderr, "==> %s() rpmmcClass 0x%lx\n", __FUNCTION__, rpmmcClass); > + rpmmcClass = rb_define_class_under(rpmModule, "Mc", rb_cObject); > + if (_debug) > + fprintf(stderr, "==> %s() rpmmcClass 0x%lx\n", __FUNCTION__, > rpmmcClass); > rb_define_alloc_func(rpmmcClass, rpmmc_alloc); > initProperties(rpmmcClass); > initMethods(rpmmcClass); > @@ . > ______________________________________________________________________ > 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