I rock.

Discussion in 'Ruby' started by Eric Hodel, May 3, 2005.

  1. Eric Hodel

    Eric Hodel Guest

    Yup, rb_intern needs to be cached. Yup, the __self thing is wrong (it
    was late, and I forgot about NODE_SELF). No, it doesn't let you
    directly call C code either (yet?).

    $ cat demo/factorial.rb
    class F
    def factorial(n)
    f = 1
    n.downto(2) { |x| f *= x }
    return f
    end

    def main # horrid but funny hack
    return factorial(5)
    end
    end
    $ ./translate2.rb demo/factorial.rb > f.c
    $ cc -dynamic -bundle -undefined suppress -flat_namespace -g -O2 -pipe
    -fno-common -I /usr/local/lib/ruby/1.8/powerpc-darwin7.9.0 f.c -o
    F.bundle
    $ ruby -I. -rF -e 'p F.new.factorial(5)'
    120
    $ time ruby -Idemo -rfactorial -e 'p F.new.factorial(9999)' > /dev/null

    real 0m3.938s
    user 0m3.360s
    sys 0m0.080s
    $ time ruby -I. -rF -e 'p F.new.factorial(9999)' > /dev/null

    real 0m3.751s
    user 0m3.340s
    sys 0m0.060s

    (but I don't expect a speed increase, the way it works)

    $ cat f.c
    // BEGIN METARUBY PREAMBLE
    #include <ruby.h>
    #define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
    (y)))
    // END METARUBY PREAMBLE
    // class F < Object

    static VALUE
    rrc_cF_factorial(VALUE __self, VALUE n) {
    VALUE f;
    VALUE x;
    f = LONG2FIX(1);
    x = n;
    while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
    f = rb_funcall(f, rb_intern("*"), 1, x);
    x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
    };
    return f;
    }

    static VALUE
    rrc_cF_main(VALUE __self) {
    return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
    }

    void
    Init_F() {
    VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));

    rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
    rb_define_method(rrc_cF, "main", rrc_cF_main, 0);

    }

    --
    Eric Hodel - - http://segment7.net
    FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
    Eric Hodel, May 3, 2005
    #1
    1. Advertising

  2. Eric Hodel

    Phil Tomson Guest

    In article <>,
    Eric Hodel <> wrote:
    >Yup, rb_intern needs to be cached. Yup, the __self thing is wrong (it
    >was late, and I forgot about NODE_SELF). No, it doesn't let you
    >directly call C code either (yet?).
    >
    >$ cat demo/factorial.rb
    >class F
    > def factorial(n)
    > f = 1
    > n.downto(2) { |x| f *= x }
    > return f
    > end
    >
    > def main # horrid but funny hack
    > return factorial(5)
    > end
    >end
    >$ ./translate2.rb demo/factorial.rb > f.c
    >$ cc -dynamic -bundle -undefined suppress -flat_namespace -g -O2 -pipe
    >-fno-common -I /usr/local/lib/ruby/1.8/powerpc-darwin7.9.0 f.c -o
    >F.bundle
    >$ ruby -I. -rF -e 'p F.new.factorial(5)'
    >120
    >$ time ruby -Idemo -rfactorial -e 'p F.new.factorial(9999)' > /dev/null
    >
    >real 0m3.938s
    >user 0m3.360s
    >sys 0m0.080s
    >$ time ruby -I. -rF -e 'p F.new.factorial(9999)' > /dev/null
    >
    >real 0m3.751s
    >user 0m3.340s
    >sys 0m0.060s
    >
    >(but I don't expect a speed increase, the way it works)
    >
    >$ cat f.c
    >// BEGIN METARUBY PREAMBLE
    >#include <ruby.h>
    >#define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
    >(y)))
    >// END METARUBY PREAMBLE
    >// class F < Object
    >
    >static VALUE
    >rrc_cF_factorial(VALUE __self, VALUE n) {
    >VALUE f;
    >VALUE x;
    >f = LONG2FIX(1);
    >x = n;
    >while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
    >f = rb_funcall(f, rb_intern("*"), 1, x);
    >x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
    >};
    >return f;
    >}
    >
    >static VALUE
    >rrc_cF_main(VALUE __self) {
    >return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
    >}
    >
    >void
    >Init_F() {
    >VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));
    >
    >rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
    >rb_define_method(rrc_cF, "main", rrc_cF_main, 0);
    >
    >}
    >



    How does this differ from the current RubyToC stuff?
    Is this newer version available for download yet?

    Phil
    Phil Tomson, May 3, 2005
    #2
    1. Advertising

  3. Eric Hodel

    Eric Hodel Guest

    On 03 May 2005, at 11:09, Phil Tomson wrote:

    > In article <>,
    > Eric Hodel <> wrote:
    >> $ cat f.c
    >> // BEGIN METARUBY PREAMBLE
    >> #include <ruby.h>
    >> #define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
    >> (y)))
    >> // END METARUBY PREAMBLE
    >> // class F < Object
    >>
    >> static VALUE
    >> rrc_cF_factorial(VALUE __self, VALUE n) {
    >> VALUE f;
    >> VALUE x;
    >> f = LONG2FIX(1);
    >> x = n;
    >> while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
    >> f = rb_funcall(f, rb_intern("*"), 1, x);
    >> x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
    >> };
    >> return f;
    >> }
    >>
    >> static VALUE
    >> rrc_cF_main(VALUE __self) {
    >> return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
    >> }
    >>
    >> void
    >> Init_F() {
    >> VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));
    >>
    >> rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
    >> rb_define_method(rrc_cF, "main", rrc_cF_main, 0);
    >>
    >> }
    >>

    >
    >
    > How does this differ from the current RubyToC stuff?


    This one (Ruby2RubyC) generates a C extension, where the other tail
    generates raw, type inferenced C code.

    I think Ruby2RubyC can make optimizations for Fixnum math and other
    boolean logic, but I haven't explored that yet.

    Ruby2RubyC is also dynamic code safe. It automatically converts from
    Fixnum to Bignum, thanks to the Ruby C runtime. (I snipped the output
    of factorial(9999), but it outputs a handful of lines of numbers.)

    For example, the other tail could not handle factorial(9999) because C
    doesn't have Bignums.

    > Is this newer version available for download yet?


    No, not yet. Maybe after Thursday hacking.

    --
    Eric Hodel - - http://segment7.net
    FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
    Eric Hodel, May 3, 2005
    #3
  4. > This one (Ruby2RubyC) generates a C extension, where the other tail
    > generates raw, type inferenced C code.


    Sounds like a nice way to obfuscate code a bit, for those that are
    inclined that way.
    Linus Sellberg, May 3, 2005
    #4
  5. On 5/4/05, Eric Hodel <> wrote:
    > On 03 May 2005, at 11:09, Phil Tomson wrote:
    >
    > > In article <>,
    > > Eric Hodel <> wrote:
    > >> $ cat f.c
    > >> // BEGIN METARUBY PREAMBLE
    > >> #include <ruby.h>
    > >> #define case_equal_long(x, y) (rb_funcall((x), rb_intern("==="), 1,
    > >> (y)))
    > >> // END METARUBY PREAMBLE
    > >> // class F < Object
    > >>
    > >> static VALUE
    > >> rrc_cF_factorial(VALUE __self, VALUE n) {
    > >> VALUE f;
    > >> VALUE x;
    > >> f = LONG2FIX(1);
    > >> x = n;
    > >> while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
    > >> f = rb_funcall(f, rb_intern("*"), 1, x);
    > >> x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
    > >> };
    > >> return f;
    > >> }
    > >>
    > >> static VALUE
    > >> rrc_cF_main(VALUE __self) {
    > >> return rb_funcall(__self, rb_intern("factorial"), 1, LONG2FIX(5));
    > >> }
    > >>
    > >> void
    > >> Init_F() {
    > >> VALUE rrc_cF = rb_define_class("F", rb_path2class("Object"));
    > >>
    > >> rb_define_method(rrc_cF, "factorial", rrc_cF_factorial, 1);
    > >> rb_define_method(rrc_cF, "main", rrc_cF_main, 0);
    > >>
    > >> }
    > >>

    > >
    > >
    > > How does this differ from the current RubyToC stuff?

    >
    > This one (Ruby2RubyC) generates a C extension, where the other tail
    > generates raw, type inferenced C code.
    >
    > I think Ruby2RubyC can make optimizations for Fixnum math and other
    > boolean logic, but I haven't explored that yet.
    >
    > Ruby2RubyC is also dynamic code safe. It automatically converts from
    > Fixnum to Bignum, thanks to the Ruby C runtime. (I snipped the output
    > of factorial(9999), but it outputs a handful of lines of numbers.)
    >
    > For example, the other tail could not handle factorial(9999) because C
    > doesn't have Bignums.
    >
    > > Is this newer version available for download yet?

    >
    > No, not yet. Maybe after Thursday hacking.
    >
    > --
    > Eric Hodel - - http://segment7.net
    > FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
    >
    >


    Python has PyRex which enables writing CPython extensions
    with python-like syntax. I guess Ruby2RubyC can do a foundation
    role for future great works such as writing extensions with ruby
    syntax, enhancing performance easily with type conversion,
    or can be used as intermediate format for translating Ruby to C.

    Cheers,

    --
    http://nohmad.sub-port.net
    Gyoung-Yoon Noh, May 3, 2005
    #5
  6. Eric Hodel

    Ryan Davis Guest

    On May 3, 2005, at 10:23 AM, Eric Hodel wrote:

    > Yup, rb_intern needs to be cached. Yup, the __self thing is wrong (it
    > was late, and I forgot about NODE_SELF). No, it doesn't let you
    > directly call C code either (yet?).

    ...
    > $ cat f.c
    > ...
    > static VALUE
    > rrc_cF_factorial(VALUE __self, VALUE n) {
    > VALUE f;
    > VALUE x;
    > f = LONG2FIX(1);
    > x = n;
    > while (RTEST(rb_funcall(x, rb_intern(">="), 1, LONG2FIX(2)))) {
    > f = rb_funcall(f, rb_intern("*"), 1, x);
    > x = rb_funcall(x, rb_intern("-"), 1, LONG2FIX(1));
    > };
    > return f;


    YAY! You do rock! And no, "__self" doesn't suck, but most of the C impl
    I've seen just calls it "self" straight up. This is really cool and I
    can't wait to read the code.
    Ryan Davis, May 3, 2005
    #6
  7. Eric Hodel

    Ryan Davis Guest

    On May 3, 2005, at 1:32 PM, Gyoung-Yoon Noh wrote:

    > Python has PyRex which enables writing CPython extensions
    > with python-like syntax. I guess Ruby2RubyC can do a foundation
    > role for future great works such as writing extensions with ruby
    > syntax, enhancing performance easily with type conversion,
    > or can be used as intermediate format for translating Ruby to C.


    Ruby2RubyC will probably not, for the first few months at least,
    improve performance with any sort of type conversion at all. In fact, I
    suspect that Eric's current version will start to get fairly severe
    penalties until we move away from using rb_funcall for everything. If
    you want performance then you should either hand write (using
    RubyInline!) or take a peek at zenoptimizer when it gets released in my
    ZenHacks package (it uses a combination of ruby2c and rubyinline with a
    custom lightweight profiler I wrote last week).

    --
    - Seattle.rb -
    http://www.zenspider.com/seattle.rb
    http://blog.zenspider.com/ - http://rubyforge.org/projects/ruby2c
    Ryan Davis, May 3, 2005
    #7
  8. Eric Hodel

    Eric Hodel Guest

    On 03 May 2005, at 15:21, Ryan Davis wrote:

    > On May 3, 2005, at 1:32 PM, Gyoung-Yoon Noh wrote:
    >
    >> Python has PyRex which enables writing CPython extensions
    >> with python-like syntax. I guess Ruby2RubyC can do a foundation
    >> role for future great works such as writing extensions with ruby
    >> syntax, enhancing performance easily with type conversion,
    >> or can be used as intermediate format for translating Ruby to C.

    >
    > Ruby2RubyC will probably not, for the first few months at least,
    > improve performance with any sort of type conversion at all. In fact,
    > I suspect that Eric's current version will start to get fairly severe
    > penalties until we move away from using rb_funcall for everything.


    Yup, it only bypasses the fast parts of eval.c (AST walking), and none
    of the slow parts (rb_funcall) so you get almost zero speed benefit out
    of it currently. (See the "time factorial(9999)" output further up the
    thread).

    > If you want performance then you should either hand write (using
    > RubyInline!) or take a peek at zenoptimizer when it gets released in
    > my ZenHacks package (it uses a combination of ruby2c and rubyinline
    > with a custom lightweight profiler I wrote last week).


    Yes. When you find a slow part, you could use this as your template.
    You'll have working Ruby/C code to refactor into faster C code in no
    time at all.

    I should be able to skip rb_funcall for places where I know the types,
    and directly call the C implementation of a method. That will be more
    work though, because I'll have to fall back in case a TypeError is
    raised in addition to pulling the right bits from the VALUE.

    Or something.

    --
    Eric Hodel - - http://segment7.net
    FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
    Eric Hodel, May 3, 2005
    #8
  9. Eric Hodel

    Ryan Davis Guest

    On May 3, 2005, at 3:45 PM, Eric Hodel wrote:

    > On 03 May 2005, at 15:21, Ryan Davis wrote:
    >
    >> If you want performance then you should either hand write (using
    >> RubyInline!) or take a peek at zenoptimizer when it gets released in
    >> my ZenHacks package (it uses a combination of ruby2c and rubyinline
    >> with a custom lightweight profiler I wrote last week).

    >
    > Yes. When you find a slow part, you could use this as your template.
    > You'll have working Ruby/C code to refactor into faster C code in no
    > time at all.


    oooh. I didn't think of that. Not sure why. :p

    > I should be able to skip rb_funcall for places where I know the types,
    > and directly call the C implementation of a method. That will be more
    > work though, because I'll have to fall back in case a TypeError is
    > raised in addition to pulling the right bits from the VALUE.


    *nod*

    I expect that we'll do a version down the line that includes
    TypeChecker in the SexpProcessor pipeline and we'll have better sends
    in that version.

    Isn't it cool that we have these discussions out on a public list like
    ruby-talk??? It is almost like, oh I dunno, we want people to look at
    the software! ;)

    --
    - Seattle.rb -
    http://www.zenspider.com/seattle.rb
    http://blog.zenspider.com/ - http://rubyforge.org/projects/ruby2c
    Ryan Davis, May 4, 2005
    #9
  10. On 5/4/05, Eric Hodel <> wrote:
    > On 03 May 2005, at 15:21, Ryan Davis wrote:
    >
    > > On May 3, 2005, at 1:32 PM, Gyoung-Yoon Noh wrote:
    > >
    > >> Python has PyRex which enables writing CPython extensions
    > >> with python-like syntax. I guess Ruby2RubyC can do a foundation
    > >> role for future great works such as writing extensions with ruby
    > >> syntax, enhancing performance easily with type conversion,
    > >> or can be used as intermediate format for translating Ruby to C.

    > >
    > > Ruby2RubyC will probably not, for the first few months at least,
    > > improve performance with any sort of type conversion at all. In fact,
    > > I suspect that Eric's current version will start to get fairly severe
    > > penalties until we move away from using rb_funcall for everything.

    >
    > Yup, it only bypasses the fast parts of eval.c (AST walking), and none
    > of the slow parts (rb_funcall) so you get almost zero speed benefit out
    > of it currently. (See the "time factorial(9999)" output further up the
    > thread).



    Oops, by 'type conversion', I meant PyRex-style C types usage.
    PyRex enables feeding native C types, instead of PythonC types,
    easily within its python-like syntax anywhere. In case of ruby, I think
    it will be much greater if it's possible to use RubyDL's type wrapper
    against native C types.

    --
    http://nohmad.sub-port.net
    Gyoung-Yoon Noh, May 4, 2005
    #10
  11. Eric Hodel

    Bill Guindon Guest

    On 5/3/05, Ryan Davis <> wrote:
    >
    > On May 3, 2005, at 3:45 PM, Eric Hodel wrote:
    >
    > > On 03 May 2005, at 15:21, Ryan Davis wrote:
    > >
    > >> If you want performance then you should either hand write (using
    > >> RubyInline!) or take a peek at zenoptimizer when it gets released in
    > >> my ZenHacks package (it uses a combination of ruby2c and rubyinline
    > >> with a custom lightweight profiler I wrote last week).

    > >
    > > Yes. When you find a slow part, you could use this as your template.
    > > You'll have working Ruby/C code to refactor into faster C code in no
    > > time at all.

    >
    > oooh. I didn't think of that. Not sure why. :p
    >
    > > I should be able to skip rb_funcall for places where I know the types,
    > > and directly call the C implementation of a method. That will be more
    > > work though, because I'll have to fall back in case a TypeError is
    > > raised in addition to pulling the right bits from the VALUE.

    >
    > *nod*
    >
    > I expect that we'll do a version down the line that includes
    > TypeChecker in the SexpProcessor pipeline and we'll have better sends
    > in that version.
    >
    > Isn't it cool that we have these discussions out on a public list like
    > ruby-talk??? It is almost like, oh I dunno, we want people to look at
    > the software! ;)


    Not being a c programmer, I've been watching this thread (and some
    others) mostly out of curiousity. But I'm beginning to get the
    impression that the two of you are on the verge of having a full Ruby
    to C converter. Is that an overestimate?

    If a full conversion is likely, any idea on a time line? What would
    be the likely limitations?

    Write it in Ruby, convert it to c, compile it, distribute it. That
    really would be something. Especially for the non c programmers like
    myself :)

    --
    Bill Guindon (aka aGorilla)
    Bill Guindon, May 4, 2005
    #11
  12. Eric Hodel

    Eric Hodel Guest

    On 04 May 2005, at 08:14, Bill Guindon wrote:

    > On 5/3/05, Ryan Davis <> wrote:
    >>
    >> On May 3, 2005, at 3:45 PM, Eric Hodel wrote:
    >>
    >>> On 03 May 2005, at 15:21, Ryan Davis wrote:
    >>>
    >>>> If you want performance then you should either hand write (using
    >>>> RubyInline!) or take a peek at zenoptimizer when it gets released in
    >>>> my ZenHacks package (it uses a combination of ruby2c and rubyinline
    >>>> with a custom lightweight profiler I wrote last week).
    >>>
    >>> Yes. When you find a slow part, you could use this as your template.
    >>> You'll have working Ruby/C code to refactor into faster C code in no
    >>> time at all.

    >>
    >> oooh. I didn't think of that. Not sure why. :p
    >>
    >>> I should be able to skip rb_funcall for places where I know the
    >>> types,
    >>> and directly call the C implementation of a method. That will be
    >>> more
    >>> work though, because I'll have to fall back in case a TypeError is
    >>> raised in addition to pulling the right bits from the VALUE.

    >>
    >> *nod*
    >>
    >> I expect that we'll do a version down the line that includes
    >> TypeChecker in the SexpProcessor pipeline and we'll have better sends
    >> in that version.
    >>
    >> Isn't it cool that we have these discussions out on a public list like
    >> ruby-talk??? It is almost like, oh I dunno, we want people to look at
    >> the software! ;)

    >
    > Not being a c programmer, I've been watching this thread (and some
    > others) mostly out of curiousity. But I'm beginning to get the
    > impression that the two of you are on the verge of having a full Ruby
    > to C converter. Is that an overestimate?


    I think that is on-target.

    > If a full conversion is likely, any idea on a time line? What would
    > be the likely limitations?


    For Ruby2RubyC, you trade safety for speed (but I may be able to do
    something about that), and you are limited in what is translatable.
    Code in a class or module, or at the top level can't be translated.

    The translator isn't fully done yet, I don't know if things like
    constant lookup actually works, and I didn't do anything to make global
    variables work. Those things can be fixed.

    It may do different things with scoping of variables too.

    > Write it in Ruby, convert it to c, compile it, distribute it. That
    > really would be something. Especially for the non c programmers like
    > myself :)


    For a Ruby subset, yes, you can do that. Just for a larger subset than
    Ruby2C.

    --
    Eric Hodel - - http://segment7.net
    FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
    Eric Hodel, May 4, 2005
    #12
  13. Eric Hodel

    Bill Guindon Guest

    On 5/4/05, Eric Hodel <> wrote:
    > > On 5/3/05, Ryan Davis <> wrote:
    > >> Isn't it cool that we have these discussions out on a public list like
    > >> ruby-talk??? It is almost like, oh I dunno, we want people to look at
    > >> the software! ;)

    > >
    > > Not being a c programmer, I've been watching this thread (and some
    > > others) mostly out of curiousity. But I'm beginning to get the
    > > impression that the two of you are on the verge of having a full Ruby
    > > to C converter. Is that an overestimate?

    >
    > I think that is on-target.
    >
    > > If a full conversion is likely, any idea on a time line? What would
    > > be the likely limitations?

    >
    > For Ruby2RubyC, you trade safety for speed (but I may be able to do
    > something about that), and you are limited in what is translatable.
    > Code in a class or module, or at the top level can't be translated.
    >
    > The translator isn't fully done yet, I don't know if things like
    > constant lookup actually works, and I didn't do anything to make global
    > variables work. Those things can be fixed.
    >
    > It may do different things with scoping of variables too.
    >
    > > Write it in Ruby, convert it to c, compile it, distribute it. That
    > > really would be something. Especially for the non c programmers like
    > > myself :)

    >
    > For a Ruby subset, yes, you can do that. Just for a larger subset than
    > Ruby2C.


    Eric, you and Ryan have impressed me before, but this takes the cake.

    I'll keep watching, and I hope others can do more than just watch. I
    expect that subset will be growing, and I look forward to it.

    I've used Erik Veenstra's RubyScript2Exe a couple times to share toys
    with non-ruby coders, and I think it's a great tool, but this would be
    much more impressive (losing size/speed issues).

    Keep up the great work. I imagine many others feel the same way.
    Consider this an 'advocacy bump' ;-)

    --
    Bill Guindon (aka aGorilla)
    Bill Guindon, May 5, 2005
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Max Stayner \(Avignon Solutions\)

    Between a rock and a hard place!

    Max Stayner \(Avignon Solutions\), Jan 7, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    338
    Max Stayner \(Avignon Solutions\)
    Jan 12, 2004
  2. TooNaive

    Building Paper, Rock, Scissors

    TooNaive, Jun 14, 2004, in forum: C Programming
    Replies:
    7
    Views:
    544
    T.M. Sommers
    Jun 14, 2004
  3. Bryan Olson

    Does my RE rock, or suck?

    Bryan Olson, Jul 8, 2004, in forum: Python
    Replies:
    8
    Views:
    323
    Bryan Olson
    Jul 10, 2004
  4. gc

    Rock Program

    gc, May 5, 2006, in forum: C Programming
    Replies:
    12
    Views:
    565
  5. Replies:
    2
    Views:
    622
Loading...

Share This Page