Called as method or subroutine?

Discussion in 'Perl Misc' started by ed, Jul 24, 2003.

  1. ed

    ed Guest

    Hi is there a way to make a sub/method compatible with
    the two following calling methods?

    1. MyClass::mySub();
    2. MyClass->mySub();

    Using the first method gives me one less argument in my argument list.
    How do you deal with both situations?
    Is there an easy way to find out if you're being invoked a method or
    subroutine?

    tia,
    --ed
     
    ed, Jul 24, 2003
    #1
    1. Advertising

  2. ed <> wrote:
    > Hi is there a way to make a sub/method compatible with
    > the two following calling methods?
    >
    > 1. MyClass::mySub();
    > 2. MyClass->mySub();


    Not a good way.

    You'd have to look at the number of arguments and the value
    of the first argument and take a guess.

    These are going to look awfully similar, though:

    Class->sub;
    Class::sub("Class");

    --
    Steve
     
    Steve Grazzini, Jul 24, 2003
    #2
    1. Advertising

  3. On Wed, 23 Jul 2003 21:51:23 -0500,
    Eric J. Roode <> wrote:
    >
    > ed <> wrote in
    > news::
    >
    >> Hi is there a way to make a sub/method compatible with
    >> the two following calling methods?
    >>
    >> 1. MyClass::mySub();
    >> 2. MyClass->mySub();
    >>
    >> Using the first method gives me one less argument in my argument list.
    >> How do you deal with both situations?
    >> Is there an easy way to find out if you're being invoked a method or
    >> subroutine?

    >
    > Well, you could check the first argument and see if it's equal to
    > __PACKAGE__. But that's not a good solution, because it breaks
    > inheritance.


    The notation MyClass::mySub() is not subject to inheritance in any
    way. In other words, the above two calls cannot be equivalent, because
    of Perl's magical treatment of that arrow. If you use that arrow, Perl
    will search through @ISA. If you don't, then it won't.

    The only way in which these two calls can ever be reasonably the same
    is if the first argument were ignored when it's called as
    MyClass->mySub(), and that can be done by simply discarding the first
    argument when it's equal to __PACKAGE__.

    sub MyClass::mySub
    {
    shift if $_[0] eq __PACKAGE__;
    # do stuff...
    }

    Of course, if someone does:

    MyClass::mySub("MyClass");

    and expect that that argument won't get discarded, they will get a
    nasty surprise.

    I'd agree with Eric that it's a bad idea. it's misleading to call
    something that can only be a regular sub with the arrow notation,
    which strongly hints at class method implementation details. If you
    really want this method to act as a class method, then you should
    not call it without the arrow notation. Perl will not look for the
    method in any superclasses unless you use that arrow, and if you
    always need to call it with the arrow, then you don't need them to be
    "equivalent".

    Martien
    --
    |
    Martien Verbruggen | Failure is not an option. It comes bundled
    Trading Post Australia | with your Microsoft product.
    |
     
    Martien Verbruggen, Jul 24, 2003
    #3
  4. Also sprach Martien Verbruggen:

    > On Wed, 23 Jul 2003 21:51:23 -0500,
    > Eric J. Roode <> wrote:
    >>
    >> ed <> wrote in
    >> news::
    >>
    >>> Hi is there a way to make a sub/method compatible with
    >>> the two following calling methods?
    >>>
    >>> 1. MyClass::mySub();
    >>> 2. MyClass->mySub();
    >>>
    >>> Using the first method gives me one less argument in my argument list.
    >>> How do you deal with both situations?
    >>> Is there an easy way to find out if you're being invoked a method or
    >>> subroutine?

    >>
    >> Well, you could check the first argument and see if it's equal to
    >> __PACKAGE__. But that's not a good solution, because it breaks
    >> inheritance.

    >
    > The notation MyClass::mySub() is not subject to inheritance in any
    > way. In other words, the above two calls cannot be equivalent, because
    > of Perl's magical treatment of that arrow. If you use that arrow, Perl
    > will search through @ISA. If you don't, then it won't.


    Which, as far as I understand, was Eric's point. The comparison with
    __PACKAGE__ should not be done in a class-method because otherwise the
    package of this method cannot be used as a superclass. This distinction
    between class-method and plain function (or lack thereof) is one of the
    true Perl-oddities. CGI.pm fell into this trap:

    ethan@ethan:~$ perl -lMCGI=b1
    print CGI->b1("CGI");
    print b1("CGI");
    print b1("cgi");
    <b1>CGI</b1>
    <b1></b1>
    <b1>cgi</b1>

    Lincoln fixed that in the latest release, though.

    > The only way in which these two calls can ever be reasonably the same
    > is if the first argument were ignored when it's called as
    > MyClass->mySub(), and that can be done by simply discarding the first
    > argument when it's equal to __PACKAGE__.
    >
    > sub MyClass::mySub
    > {
    > shift if $_[0] eq __PACKAGE__;
    > # do stuff...
    > }
    >
    > Of course, if someone does:
    >
    > MyClass::mySub("MyClass");
    >
    > and expect that that argument won't get discarded, they will get a
    > nasty surprise.


    Yes, as the above CGI-bug shows.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jul 24, 2003
    #4
  5. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Martien Verbruggen <> wrote in
    news::

    > The only way in which these two calls can ever be reasonably the same
    > is if the first argument were ignored when it's called as
    > MyClass->mySub(), and that can be done by simply discarding the first
    > argument when it's equal to __PACKAGE__.
    >
    > sub MyClass::mySub
    > {
    > shift if $_[0] eq __PACKAGE__;
    > # do stuff...
    > }


    And this is where it breaks inheritance. If I later write a new class
    MyOtherClass and expect to inherit mySub, and someone invokes it as:

    MyOtherClass->mySub(@arguments);

    the package name will not be removed.

    - --
    Eric
    $_ = reverse sort qw p ekca lre Js reh ts
    p, $/.r, map $_.$", qw e p h tona e; print

    -----BEGIN PGP SIGNATURE-----
    Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

    iQA/AwUBPx+1tGPeouIeTNHoEQKIeACfQHGZkS3VywQ/ctUIiGldcn70JsEAoJJN
    58XdGCDNN/ZhqA2grkziZLoP
    =9109
    -----END PGP SIGNATURE-----
     
    Eric J. Roode, Jul 24, 2003
    #5
  6. Eric J. Roode <> wrote:
    > Martien Verbruggen <> wrote:
    > > The only way in which these two calls can ever be reasonably the same
    > > is if the first argument were ignored when it's called as
    > > MyClass->mySub(), and that can be done by simply discarding the first
    > > argument when it's equal to __PACKAGE__.
    > >
    > > sub MyClass::mySub
    > > {
    > > shift if $_[0] eq __PACKAGE__;
    > > # do stuff...
    > > }

    >
    > And this is where it breaks inheritance. If I later write a new class
    > MyOtherClass and expect to inherit mySub, and someone invokes it as:
    >
    > MyOtherClass->mySub(@arguments);
    >
    > the package name will not be removed.


    You could use

    shift if UNIVERSAL::isa($_[0], __PACKAGE__);

    But that still doesn't handle Class::sub("Class").

    > - --


    And what's that supposed to be? :)

    --
    Steve
     
    Steve Grazzini, Jul 24, 2003
    #6
  7. ed

    Jay Tilton Guest

    ed <> wrote:

    : Hi is there a way to make a sub/method compatible with
    : the two following calling methods?
    :
    : 1. MyClass::mySub();
    : 2. MyClass->mySub();

    The File::Spec::Functions module may be worth study. It wraps the
    methods from the File::Spec class into plain subroutines that can be
    exported to other packages. It's a pretty simple thing to do, and it
    doesn't require the methods to have any magical awareness of whether
    they're being called as subroutines.
     
    Jay Tilton, Jul 24, 2003
    #7
  8. ed

    Uri Guttman Guest

    >>>>> "JT" == Jay Tilton <> writes:

    JT> ed <> wrote:
    JT> : Hi is there a way to make a sub/method compatible with
    JT> : the two following calling methods?
    JT> :
    JT> : 1. MyClass::mySub();
    JT> : 2. MyClass->mySub();

    JT> The File::Spec::Functions module may be worth study. It wraps the
    JT> methods from the File::Spec class into plain subroutines that can be
    JT> exported to other packages. It's a pretty simple thing to do, and it
    JT> doesn't require the methods to have any magical awareness of whether
    JT> they're being called as subroutines.

    and i proposed a module for a TPF grant that would allow a module author
    do have that feature with little effort. it would allow an OO module to
    have a default object and it would export subs into the user space which
    would do call the same methods on that default object. this is similar
    to what cgi,pm does but it would be generic and support any OO
    module. it would also allow prefixes or renaming of the subs by the user
    code.

    the grant was accepted but i have since been put on the TPF committee so
    i can't take the funding. if someone wants to take this project on, i
    will help out with the design (as i have done most of it already) and
    they can earn some grant money. the grant was approved but not formally
    issued. you have to have serious understanding of OO perl, closures,
    exporting to do this. it is not for newbies or the faint of heart. :)

    email me if you are interested.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Jul 24, 2003
    #8
  9. On 24 Jul 2003 06:21:58 GMT,
    Tassilo v. Parseval <> wrote:
    > Also sprach Martien Verbruggen:
    >
    >> On Wed, 23 Jul 2003 21:51:23 -0500,
    >> Eric J. Roode <> wrote:
    >>>
    >>> ed <> wrote in
    >>> news::
    >>>
    >>>> Hi is there a way to make a sub/method compatible with
    >>>> the two following calling methods?
    >>>>
    >>>> 1. MyClass::mySub();
    >>>> 2. MyClass->mySub();


    [snip]

    >>> Well, you could check the first argument and see if it's equal to
    >>> __PACKAGE__. But that's not a good solution, because it breaks
    >>> inheritance.

    >>
    >> The notation MyClass::mySub() is not subject to inheritance in any
    >> way. In other words, the above two calls cannot be equivalent, because
    >> of Perl's magical treatment of that arrow. If you use that arrow, Perl
    >> will search through @ISA. If you don't, then it won't.

    >
    > Which, as far as I understand, was Eric's point.


    The point that I was trying to make is that with a call like
    MyClass::mySub() it is not even really possible to talk about
    inheritance, since it's not a method call, but rather a regular
    subroutine call, and therefore never subject to Perl's inheritance
    mechanisms. You do need the arrow for that.

    If Eric was indeed saying the same thing, then I apologise for
    misreading what he said. The only thing I read in his post was that
    using a hardcoded package name in a method breaks inheritance, because
    you'll always be working in the __PACKAGE__ class, as opposed to the
    class that was actually passed via the arrow, in calls like
    Class->method();

    Martien
    --
    |
    Martien Verbruggen | Useful Statistic: 75% of the people make up
    | 3/4 of the population.
    |
     
    Martien Verbruggen, Jul 25, 2003
    #9
  10. Also sprach Martien Verbruggen:

    > On 24 Jul 2003 06:21:58 GMT,
    > Tassilo v. Parseval <> wrote:
    >> Also sprach Martien Verbruggen:


    >>> The notation MyClass::mySub() is not subject to inheritance in any
    >>> way. In other words, the above two calls cannot be equivalent, because
    >>> of Perl's magical treatment of that arrow. If you use that arrow, Perl
    >>> will search through @ISA. If you don't, then it won't.

    >>
    >> Which, as far as I understand, was Eric's point.

    >
    > The point that I was trying to make is that with a call like
    > MyClass::mySub() it is not even really possible to talk about
    > inheritance, since it's not a method call, but rather a regular
    > subroutine call, and therefore never subject to Perl's inheritance
    > mechanisms. You do need the arrow for that.


    Hmmh, just a sec. Plain functions are subject to inheritance in Perl
    (they also trigger AUTOLOAD if it exists):

    ethan@ethan:~$ perl -l
    package t;
    require CGI;
    @ISA = qw/CGI/;
    package main;
    print t::h1("test");
    __END__
    <h1>test</h1>

    That makes class-methods and function look even more indistinguishable.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jul 26, 2003
    #10
  11. On 26 Jul 2003 06:13:12 GMT,
    Tassilo v. Parseval <> wrote:
    > Also sprach Martien Verbruggen:
    >
    >> On 24 Jul 2003 06:21:58 GMT,
    >> Tassilo v. Parseval <> wrote:
    >>> Also sprach Martien Verbruggen:

    >
    >>>> The notation MyClass::mySub() is not subject to inheritance in any
    >>>> way. In other words, the above two calls cannot be equivalent, because
    >>>> of Perl's magical treatment of that arrow. If you use that arrow, Perl
    >>>> will search through @ISA. If you don't, then it won't.
    >>>
    >>> Which, as far as I understand, was Eric's point.

    >>
    >> The point that I was trying to make is that with a call like
    >> MyClass::mySub() it is not even really possible to talk about
    >> inheritance, since it's not a method call, but rather a regular
    >> subroutine call, and therefore never subject to Perl's inheritance
    >> mechanisms. You do need the arrow for that.

    >
    > Hmmh, just a sec. Plain functions are subject to inheritance in Perl
    > (they also trigger AUTOLOAD if it exists):
    >
    > ethan@ethan:~$ perl -l
    > package t;
    > require CGI;
    > @ISA = qw/CGI/;
    > package main;
    > print t::h1("test");
    > __END__
    > <h1>test</h1>
    >
    > That makes class-methods and function look even more indistinguishable.


    $ cat /tmp/foo.pl
    use strict;
    use warnings;

    package Foo;
    sub foo { print "Foo::foo called\n"; }

    package Bar;
    @Bar::ISA = qw/Foo/;

    package main;
    Bar->foo();
    eval { Bar::foo() };
    print "$@" if $@;
    eval { Bar::foo("Bar") };
    print "$@" if $@;
    eval { Bar::foo("Foo") };
    print "$@" if $@;
    # Indirect syntax:
    Bar::foo Bar;

    $ perl /tmp/foo.pl
    Foo::foo called
    Undefined subroutine &Bar::foo called at /tmp/foo.pl line 12.
    Undefined subroutine &Bar::foo called at /tmp/foo.pl line 14.
    Undefined subroutine &Bar::foo called at /tmp/foo.pl line 16.
    Foo::foo called

    I don't know what extra work CGI.pm does, but to me that looks like @ISA
    does not come into play unless the arrow notation is used (ignoring the
    horror of indirect calling).

    Martien
    --
    | Yes; Windows is great for running &
    Martien Verbruggen | developing viruses, for instance. It's also
    | very popular, but then again, so is the
    | common cold. -- Dave Hinz
     
    Martien Verbruggen, Jul 27, 2003
    #11
  12. Martien Verbruggen <> wrote:
    > Tassilo v. Parseval <> wrote:
    > > Hmmh, just a sec. Plain functions are subject to inheritance in Perl
    > > (they also trigger AUTOLOAD if it exists):

    >
    > $ cat /tmp/foo.pl
    > use strict;
    > use warnings;
    >
    > package Foo;
    > sub foo { print "Foo::foo called\n"; }


    If you had defined Foo::AUTOLOAD() then all the examples would
    have succeeded -- albeit with this warning:

    % perldoc perldiag
    Use of inherited AUTOLOAD for non-method %s() is deprecated
    (D deprecated) As an (ahem) accidental feature, "AUTOLOAD" subrou-
    tines are looked up as methods (using the @ISA hierarchy) even when
    the subroutines to be autoloaded were called as plain functions
    (e.g. "Foo::bar()"), not as methods (e.g. "Foo->bar()" or
    "$obj->bar()").

    This bug will be rectified in future by using method lookup only
    for methods' "AUTOLOAD"s. However, there is a significant base of
    existing code that may be using the old behavior. So, as an
    interim step, Perl currently issues an optional warning when non-
    methods use inherited "AUTOLOAD"s.

    The simple rule is: Inheritance will not work when autoloading
    non-methods. The simple fix for old code is: In any module that
    used to depend on inheriting "AUTOLOAD" for non-methods from a base
    class named "BaseClass", execute "*AUTOLOAD = \&Base-
    Class::AUTOLOAD" during startup.

    In code that currently says "use AutoLoader; @ISA =
    qw(AutoLoader);" you should remove AutoLoader from @ISA and change
    "use AutoLoader;" to "use AutoLoader 'AUTOLOAD';".

    --
    Steve
     
    Steve Grazzini, Jul 27, 2003
    #12
  13. On Sun, 27 Jul 2003 05:51:01 GMT,
    Steve Grazzini <> wrote:
    > Martien Verbruggen <> wrote:
    >> Tassilo v. Parseval <> wrote:
    >> > Hmmh, just a sec. Plain functions are subject to inheritance in Perl
    >> > (they also trigger AUTOLOAD if it exists):

    >>
    >> $ cat /tmp/foo.pl
    >> use strict;
    >> use warnings;
    >>
    >> package Foo;
    >> sub foo { print "Foo::foo called\n"; }

    >
    > If you had defined Foo::AUTOLOAD() then all the examples would
    > have succeeded -- albeit with this warning:


    I know. And as that warning explains, that's by accident, and should
    never be relied on. Even if it was not accidental, that still doesn't
    mean that a normal subroutine call is subject to inheritance.

    So my point remains: A normal subroutine call is not subject to the
    inheritance mechanism in the way a method call is. AUTOLOAD's accidental
    features don't alter that point.

    Martien
    --
    |
    Martien Verbruggen | If it isn't broken, it doesn't have enough
    | features yet.
    |
     
    Martien Verbruggen, Jul 27, 2003
    #13
  14. Also sprach Martien Verbruggen:

    > On 26 Jul 2003 06:13:12 GMT,
    > Tassilo v. Parseval <> wrote:


    >> Hmmh, just a sec. Plain functions are subject to inheritance in Perl
    >> (they also trigger AUTOLOAD if it exists):
    >>
    >> ethan@ethan:~$ perl -l
    >> package t;
    >> require CGI;
    >> @ISA = qw/CGI/;
    >> package main;
    >> print t::h1("test");
    >> __END__
    >> <h1>test</h1>
    >>
    >> That makes class-methods and function look even more indistinguishable.

    >
    > $ cat /tmp/foo.pl
    > use strict;
    > use warnings;
    >
    > package Foo;
    > sub foo { print "Foo::foo called\n"; }
    >
    > package Bar;
    > @Bar::ISA = qw/Foo/;
    >
    > package main;
    > Bar->foo();
    > eval { Bar::foo() };
    > print "$@" if $@;
    > eval { Bar::foo("Bar") };
    > print "$@" if $@;
    > eval { Bar::foo("Foo") };
    > print "$@" if $@;
    > # Indirect syntax:
    > Bar::foo Bar;
    >
    > $ perl /tmp/foo.pl
    > Foo::foo called
    > Undefined subroutine &Bar::foo called at /tmp/foo.pl line 12.
    > Undefined subroutine &Bar::foo called at /tmp/foo.pl line 14.
    > Undefined subroutine &Bar::foo called at /tmp/foo.pl line 16.
    > Foo::foo called


    Hmmh, ok, no inheritance involved here. What I find irritating is that
    AUTOLOAD is still involved. The search-sequence of Perl for a method is
    usually from left to right @ISA, then UNIVERSAL::method(). Only after
    these searches failed AUTOLOAD is triggered (albeit with a warning).
    UNIVERSAL::AUTOLOAD() is last in this chain.

    When reading the explanation to this warning in perldiag.pod, the
    intended behaviour still sounds fishy to me. The only thing that will be
    removed in future is the inherited AUTOLOAD, but not the invocation of
    AUTOLOAD of the package from which a non-existing function was
    requested. Provided that functions do not obey inheritance, they
    shouldn't involve AUTOLOAD either IMHO.

    > I don't know what extra work CGI.pm does, but to me that looks like @ISA
    > does not come into play unless the arrow notation is used (ignoring the
    > horror of indirect calling).


    In case of CGI, @ISA does come into play in some way:

    ethan@ethan:~$ perl
    package t;
    require CGI;
    package main;
    t::test();
    __END__
    Undefined subroutine &t::test called at - line 4.

    I haven't been able to figure out why CGI.pm is special. I used require
    on purpose to not invoke CGI::import(). I suppose CGI.pm is always a bad
    candidate when trying to exhibit Perl's standard behaviour.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jul 27, 2003
    #14
  15. Also sprach Bart Lateur:

    > Tassilo v. Parseval wrote:
    >
    >>This distinction
    >>between class-method and plain function (or lack thereof) is one of the
    >>true Perl-oddities. CGI.pm fell into this trap:
    >>
    >> ethan@ethan:~$ perl -lMCGI=b1
    >> print CGI->b1("CGI");
    >> print b1("CGI");
    >> print b1("cgi");
    >> <b1>CGI</b1>
    >> <b1></b1>
    >> <b1>cgi</b1>
    >>
    >>Lincoln fixed that in the latest release, though.

    >
    > He did?


    Hrrmpfh, no, apparently he did not. I saw it in the changelog but
    testing the latest release gives me:

    ethan@ethan:~$ perl -lMCGI=b1
    print b1("CGI");
    __END__
    <b1 />

    So he replaced one bug with another one.

    > It's too sad Perl provides no official way to distinguish whether a sub
    > has been called as a function, or as a method. Like by setting a special
    > variable with the same dynamic behaviour as @_, for example.


    As the sub-thread on inheritance-or-not has shown, perl knows to
    distinguish these cases internally. So perhaps this information could be
    retrieved using some XS-trickery. The op-tree looks different, too:

    ethan@ethan:~$ perl -MO=Terse
    t::test();
    t->test();
    __END__
    LISTOP (0x8121f78) leave [1]
    OP (0x8122068) enter
    COP (0x8121f38) nextstate
    UNOP (0x8121f18) entersub [1]
    UNOP (0x8121ef0) null [141]
    OP (0x812be50) pushmark
    UNOP (0x8125368) null [17]
    SVOP (0x8159220) gv GV (0x8128ac0) *t::test
    COP (0x8121fc0) nextstate
    UNOP (0x8122020) entersub [2]
    OP (0x8122048) pushmark
    SVOP (0x8121fa0) const PV (0x8128b50) "t"
    SVOP (0x8122000) method_named PVIV (0x8128b20) "test"
    - syntax OK

    Not sure whether retrieving this information might invoke inspecting
    this op-tree, though. In this case, there'd be no way to turn this
    functionality in a little module (other than a compiler-backend).

    > And with every pointing towards CGI.pm on how it handled this: it's not
    > a good example, IMO.


    Traditionally, CGI.pm is given as example when one needs a justification
    for contorting Perl's object-model to its outer bounds. :)

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jul 28, 2003
    #15
    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. Magne Bergfjord
    Replies:
    1
    Views:
    464
  2. Daniel S.
    Replies:
    4
    Views:
    171
    Ben Morrow
    Jul 15, 2004
  3. Matthias Urlichs
    Replies:
    2
    Views:
    279
    Matthias Urlichs
    Aug 11, 2004
  4. king
    Replies:
    5
    Views:
    204
  5. Replies:
    2
    Views:
    677
    Dave Weaver
    Feb 18, 2009
Loading...

Share This Page