Does the standard specify calling conventions?

Discussion in 'C++' started by Stuart Redmann, Sep 13, 2010.

  1. Hello newsgroup,

    does the C++ standard say anything about calling conventions (http://
    en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    implementation detail?

    Thanks in advance,
    Stuart
     
    Stuart Redmann, Sep 13, 2010
    #1
    1. Advertising

  2. Stuart Redmann

    Ian Collins Guest

    On 09/13/10 07:58 PM, Stuart Redmann wrote:
    > Hello newsgroup,
    >
    > does the C++ standard say anything about calling conventions (http://
    > en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > implementation detail?


    The latter unfortunately.

    --
    Ian Collins
     
    Ian Collins, Sep 13, 2010
    #2
    1. Advertising

  3. "Stuart Redmann" <> wrote in message
    news:...
    > Hello newsgroup,
    >
    > does the C++ standard say anything about calling conventions (http://
    > en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > implementation detail?
    >


    technically, it is an implementation detail, as far as any standards are
    concerned...

    FWIW, that code actually runs on computers is an implementation detail.

    however, these calling conventions are generally well accepted, and often
    used across language boundaries as well.
     
    BGB / cr88192, Sep 13, 2010
    #3
  4. Stuart Redmann wrote:
    > does the C++ standard say anything about calling conventions (http://
    > en.wikipedia.org/wiki/X86_calling_conventions)


    No, and it will never. Note that a calling convention that works on
    Hardware X may not even exist on Hardware Y, e.g because there are less
    registers available or the stack alignment is different.

    If you need to rely on calling conventions (most probably for
    callbacks), you have to deal with platform specific extensions.


    Marcel
     
    Marcel Müller, Sep 13, 2010
    #4
  5. Stuart Redmann

    Goran Pusic Guest

    On Sep 13, 9:58 am, Stuart Redmann <> wrote:
    > Hello newsgroup,
    >
    > does the C++ standard say anything about calling conventions (http://
    > en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > implementation detail?


    The latter. Standard can't possibly specify calling conventions, not
    unless it wants to make massive presumptions about the underlying
    hardware. Take a look e.g. at i960 CPU (http://en.wikipedia.org/wiki/
    Intel_i960#Architecture) and register windows featured by this CPU
    (http://en.wikipedia.org/wiki/Register_window). Compiling for this is
    wildly different from anything one would want to do on x86. What good
    would it be trying to standardize in such a situation? That's why
    (among other things) why standard talks about abstract execution
    machine or what's it named.

    OTOH, calling conventions are hardware- and system- specific, so
    system and hardware is what one should be looking at. Tool chains are
    in practice obliged to adhere to that, and to the prevailing tool
    chain's way of working (e.g. gcc on linux, msc on windows).

    Goran.
     
    Goran Pusic, Sep 13, 2010
    #5
  6. On 13 Sep., Stuart Redmann wrote:
    > Hello newsgroup,
    >
    > does the C++ standard say anything about calling conventions (http://
    > en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > implementation detail?


    Thanks for the quick answer Ian, BGB, Marcel and Goran.
    [The answer I received was that the later is the case.]

    I stumbled over this when someone in this newsgroup asked about IO
    manipulators for his ostream-derived class (see
    ). I
    posted some code that works under MS Visual C, and would be standard-
    conformant WRT calling conventions, but still does work on his
    machine:
    std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
    (std::eek:stream&));
    cannot be compiled with his version of the STL because it doesn't know
    __cdecl.

    Am I getting this 100% right: Above definition of IO manipulators is
    standard-conformant? Or are IO manipulators not part of the standard?

    Thanks,
    Stuart
     
    Stuart Redmann, Sep 13, 2010
    #6
  7. Stuart Redmann

    Ian Collins Guest

    On 09/13/10 09:07 PM, Stuart Redmann wrote:
    > On 13 Sep., Stuart Redmann wrote:
    >> Hello newsgroup,
    >>
    >> does the C++ standard say anything about calling conventions (http://
    >> en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    >> implementation detail?

    >
    > Thanks for the quick answer Ian, BGB, Marcel and Goran.
    > [The answer I received was that the later is the case.]
    >
    > I stumbled over this when someone in this newsgroup asked about IO
    > manipulators for his ostream-derived class (see
    > ). I
    > posted some code that works under MS Visual C, and would be standard-
    > conformant WRT calling conventions, but still does work on his
    > machine:
    > std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
    > (std::eek:stream&));
    > cannot be compiled with his version of the STL because it doesn't know
    > __cdecl.
    >
    > Am I getting this 100% right: Above definition of IO manipulators is
    > standard-conformant? Or are IO manipulators not part of the standard?


    "__cdecl" is a windows thingy, not used elsewhere.

    --
    Ian Collins
     
    Ian Collins, Sep 13, 2010
    #7
  8. > On 09/13/10 Stuart Redmann wrote:
    > > On 13 Sep., Stuart Redmann wrote:
    > >> Hello newsgroup,

    >
    > >> does the C++ standard say anything about calling conventions (http://
    > >> en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > >> implementation detail?

    >
    > > Thanks for the quick answer Ian, BGB, Marcel and Goran.
    > > [The answer I received was that the later is the case.]

    >
    > > I stumbled over this when someone in this newsgroup asked about IO
    > > manipulators for his ostream-derived class (see
    > > ). I
    > > posted some code that works under MS Visual C, and would be standard-
    > > conformant WRT calling conventions, but still does work on his
    > > machine:
    > > std::eek:stream&  operator<<  (std::eek:stream&  (__cdecl *_F)
    > > (std::eek:stream&));
    > > cannot be compiled with his version of the STL because it doesn't know
    > > __cdecl.

    >
    > > Am I getting this 100% right: Above definition of IO manipulators is
    > > standard-conformant? Or are IO manipulators not part of the standard?



    On 13 Sep., Ian Collins wrote:
    > "__cdecl" is a windows thingy, not used elsewhere.


    Right. But is it standard-compliant? According to
    http://www.cplusplus.com/reference/iostream/ostream/operator<</ I
    would say no. However, the answers I got this far give me the
    impression that the standard does not disallow the usage of calling
    convention modifiers. This would mean that above code would be
    standard-conformant.

    What I actually want is the clarity that the standard disallows above
    code (at best with section number and everything) because else I'll
    become a LabView programmer (shudder). Or rather join the forces and
    become a Ada95 programmer ;-)

    Thanks,
    Stuart
     
    Stuart Redmann, Sep 13, 2010
    #8
  9. Stuart Redmann

    Ian Collins Guest

    On 09/13/10 09:25 PM, Stuart Redmann wrote:
    >> On 09/13/10 Stuart Redmann wrote:
    >>> On 13 Sep., Stuart Redmann wrote:
    >>>> Hello newsgroup,

    >>
    >>>> does the C++ standard say anything about calling conventions (http://
    >>>> en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    >>>> implementation detail?

    >>
    >>> Thanks for the quick answer Ian, BGB, Marcel and Goran.
    >>> [The answer I received was that the later is the case.]

    >>
    >>> I stumbled over this when someone in this newsgroup asked about IO
    >>> manipulators for his ostream-derived class (see
    >>> ). I
    >>> posted some code that works under MS Visual C, and would be standard-
    >>> conformant WRT calling conventions, but still does work on his
    >>> machine:
    >>> std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
    >>> (std::eek:stream&));
    >>> cannot be compiled with his version of the STL because it doesn't know
    >>> __cdecl.

    >>
    >>> Am I getting this 100% right: Above definition of IO manipulators is
    >>> standard-conformant? Or are IO manipulators not part of the standard?

    >
    >
    > On 13 Sep., Ian Collins wrote:
    >> "__cdecl" is a windows thingy, not used elsewhere.

    >
    > Right. But is it standard-compliant? According to
    > http://www.cplusplus.com/reference/iostream/ostream/operator<</ I
    > would say no. However, the answers I got this far give me the
    > impression that the standard does not disallow the usage of calling
    > convention modifiers. This would mean that above code would be
    > standard-conformant.


    The only calling convention modifier cites in the standard is
    extern "C". Anything else is a compiler specific extension.

    > What I actually want is the clarity that the standard disallows above
    > code (at best with section number and everything) because else I'll
    > become a LabView programmer (shudder). Or rather join the forces and
    > become a Ada95 programmer ;-)


    It can't disallow something it knows nothing about. As soon as you
    start using compiler specific extensions, your code is no longer
    standard C++.

    --
    Ian Collins
     
    Ian Collins, Sep 13, 2010
    #9
  10. [snipped original question about calling convention modifiers like
    MS's __cdecl in STL code]

    On 13 Sep., Ian Collins wrote:
    > The only calling convention modifier cites in the standard is
    > extern "C".  Anything else is a compiler specific extension.


    On 09/13/10 Stuart Redmann wrote:
    > > What I actually want is the clarity that the standard disallows above
    > > code (at best with section number and everything) because else I'll
    > > become a LabView programmer (shudder). Or rather join the forces and
    > > become a Ada95 programmer ;-)


    On 13 Sep., Ian Collins wrote:
    > It can't disallow something it knows nothing about.  As soon as you
    > start using compiler specific extensions, your code is no longer
    > standard C++.


    Thanks for the clarification. I guess that this is another item on
    MS's list where the product is not standard-conformant.

    Thanks,
    Stuart
     
    Stuart Redmann, Sep 13, 2010
    #10
  11. Stuart Redmann

    gwowen Guest

    On Sep 13, 10:52 am, Stuart Redmann <> wrote:
    > Thanks for the clarification. I guess that this is another item on
    > MS's list where the product is not standard-conformant.


    Well, global identifiers that start with an underscore are reserved
    for the implementation, so any user code that utilises them is non-
    standard compliant. The compiler can decided __cdecl means whatever it
    wants it to.
     
    gwowen, Sep 13, 2010
    #11
  12. Stuart Redmann

    Guest

    On Sep 13, 4:52 am, Stuart Redmann <> wrote:
    > [snipped original question about calling convention modifiers like
    > MS's __cdecl in STL code]
    >
    > On 13 Sep., Ian Collins wrote:
    >
    > > It can't disallow something it knows nothing about.  As soon as you
    > > start using compiler specific extensions, your code is no longer
    > > standard C++.

    >
    > Thanks for the clarification. I guess that this is another item on
    > MS's list where the product is not standard-conformant.



    No, it's perfectly allowed for MS to add non-standard extensions to
    the language, particularly if the keep them in the implementation
    namespace, as __cdecl is. GCC, for example, provides similar function
    via __attribute__. Neither is part of the standard.

    It's not quite clear what the function in question is doing, but it
    appears you're trying to define a an insertion operator in a template
    that uses a funcion that uses __cdecl calling conventions. Why? What
    is being accomplished by that? Inherently this code is doing
    something platform specific, and is non-portable.

    Where is this coding coming from? What's the context?
     
    , Sep 13, 2010
    #12
  13. Stuart Redmann

    Bo Persson Guest

    wrote:
    > On Sep 13, 4:52 am, Stuart Redmann <> wrote:
    >> [snipped original question about calling convention modifiers like
    >> MS's __cdecl in STL code]
    >>
    >> On 13 Sep., Ian Collins wrote:
    >>
    >>> It can't disallow something it knows nothing about. As soon as you
    >>> start using compiler specific extensions, your code is no longer
    >>> standard C++.

    >>
    >> Thanks for the clarification. I guess that this is another item on
    >> MS's list where the product is not standard-conformant.

    >
    >
    > No, it's perfectly allowed for MS to add non-standard extensions to
    > the language, particularly if the keep them in the implementation
    > namespace, as __cdecl is. GCC, for example, provides similar
    > function via __attribute__. Neither is part of the standard.
    >
    > It's not quite clear what the function in question is doing, but it
    > appears you're trying to define a an insertion operator in a
    > template that uses a funcion that uses __cdecl calling conventions.
    > Why? What is being accomplished by that? Inherently this code is
    > doing something platform specific, and is non-portable.
    >
    > Where is this coding coming from? What's the context?


    The __cdecl is the default calling convention. It is there in headers
    for precompiled library code, just in case the user code is compiled
    with some other calling convention.

    If you compile with a non-MS compiler, you cannot likely use the same
    precompiled library anyway, so a quick

    #define __cdecl /*nothing*/

    would fix that.


    Bo Persson
     
    Bo Persson, Sep 13, 2010
    #13
  14. Stuart Redmann wrote:

    > Hello newsgroup,
    >
    > does the C++ standard say anything about calling conventions (http://
    > en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > implementation detail?
    >


    The only thing the Standard says is that linkage specifications may affect
    calling conventions.

    Effectively, that has to be done by changing the linkage specification on
    the underlying function type:

    extern "C" typedef void ccalling();

    ccalling f; // c calling convention
    void f(); // c++ calling convention

    These two have different types: Bases on the type of a function type
    expression, the compiler can figure out what calling convention to use.
     
    Johannes Schaub (litb), Sep 13, 2010
    #14
  15. Stuart Redmann

    James Kanze Guest

    On Sep 13, 9:09 am, Ian Collins <> wrote:
    > On 09/13/10 07:58 PM, Stuart Redmann wrote:


    > > does the C++ standard say anything about calling conventions (http://
    > > en.wikipedia.org/wiki/X86_calling_conventions) or is this an
    > > implementation detail?


    > The latter unfortunately.


    Just curious about the "unfortunately": how could it be
    otherwise?

    --
    James Kanze
     
    James Kanze, Sep 13, 2010
    #15
  16. Stuart Redmann

    James Kanze Guest

    On Sep 13, 10:25 am, Stuart Redmann <> wrote:
    > > On 09/13/10 Stuart Redmann wrote:
    > > > On 13 Sep., Stuart Redmann wrote:


    > > > I stumbled over this when someone in this newsgroup asked about IO
    > > > manipulators for his ostream-derived class (see
    > > > ). I
    > > > posted some code that works under MS Visual C, and would be standard-
    > > > conformant WRT calling conventions, but still does work on his
    > > > machine:
    > > > std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
    > > > (std::eek:stream&));
    > > > cannot be compiled with his version of the STL because it doesn't know
    > > > __cdecl.


    > > > Am I getting this 100% right: Above definition of IO
    > > > manipulators is standard-conformant? Or are IO
    > > > manipulators not part of the standard?


    > On 13 Sep., Ian Collins wrote:


    > > "__cdecl" is a windows thingy, not used elsewhere.


    > Right. But is it standard-compliant? According
    > tohttp://www.cplusplus.com/reference/iostream/ostream/operator<</
    > I would say no. However, the answers I got this far give me
    > the impression that the standard does not disallow the usage
    > of calling convention modifiers. This would mean that above
    > code would be standard-conformant.


    It depends on your point of view. The standard says that
    identifiers beginning with __ are "undefined behavior". In
    other words, an implementation can do whatever it wants when
    a program contains one. In this case, the "undefined behavior"
    is there precisely to allow compilers to create extensions
    without running the risk of breaking standard conformant
    code---both VC++ and g++ make extensive use of this feature.
    From a compiler implementor's point of view: adding additional
    keywords does not render the compiler non compliant, as long as
    the keywords start with __. From a user's point of view: if you
    have a symbol in your code which starts with __, that code is
    not compliant. It is using an implementation defined extension.

    > What I actually want is the clarity that the standard
    > disallows above code (at best with section number and
    > everything) because else I'll become a LabView programmer
    > (shudder). Or rather join the forces and become a Ada95
    > programmer ;-)


    §17.4.3.1.2: "Each name that contains a double underscore (__)
    or begins with an underscore followed by an uppercase letter
    (2.11) is reserved to the implementation for any use."

    --
    James Kanze
     
    James Kanze, Sep 13, 2010
    #16
  17. Stuart Redmann

    Guest

    On Sep 13, 10:47 am, "Bo Persson" <> wrote:
    > wrote:
    > > On Sep 13, 4:52 am, Stuart Redmann <> wrote:
    > >> [snipped original question about calling convention modifiers like
    > >> MS's __cdecl in STL code]

    >
    > >> On 13 Sep., Ian Collins wrote:

    >
    > >>> It can't disallow something it knows nothing about. As soon as you
    > >>> start using compiler specific extensions, your code is no longer
    > >>> standard C++.

    >
    > >> Thanks for the clarification. I guess that this is another item on
    > >> MS's list where the product is not standard-conformant.

    >
    > > No, it's perfectly allowed for MS to add non-standard extensions to
    > > the language, particularly if the keep them in the implementation
    > > namespace, as __cdecl is.  GCC, for example, provides similar
    > > function via __attribute__.  Neither is part of the standard.

    >
    > > It's not quite clear what the function in question is doing, but it
    > > appears you're trying to define a an insertion operator in a
    > > template that uses a funcion that uses __cdecl calling conventions.
    > > Why?  What is being accomplished by that?  Inherently this code is
    > > doing something platform specific, and is non-portable.

    >
    > > Where is this coding coming from?  What's the context?

    >
    > The __cdecl is the default calling convention. It is there in headers
    > for precompiled library code, just in case the user code is compiled
    > with some other calling convention.



    For MSVC, for a member function, the default calling conventions is
    __thiscall. Basically you cannot pass a this pointer with __cdecl.


    > If you compile with a non-MS compiler, you cannot likely use the same
    > precompiled library anyway, so a quick
    >
    > #define __cdecl  /*nothing*/
    >
    > would fix that.



    It's still unclear where this code is coming from. If the OP is
    trying to use a Windows specific header file, the associated library
    is unlikely to be available in binary form on other platforms in a
    form intended to be used with the Windows specific header. And I'm
    still having trouble trying to understand what the function is
    supposed to do in practical terms.
     
    , Sep 13, 2010
    #17
  18. [snipped discussion about whether calling convention modifiers make
    STL code non-compliant]

    On 13 Sep., robertwess wrote:

    > It's still unclear where this code is coming from. If the OP is
    > trying to use a Windows specific header file, the associated library
    > is unlikely to be available in binary form on other platforms in a
    > form intended to be used with the Windows specific header. And I'm
    > still having trouble trying to understand what the function is
    > supposed to do in practical terms.


    The code in question is from MS's ostream header (in the code I have
    posted recently I took the liberty to replace the type _Myt with
    std::eek:stream, but it is actually typedef'ed as basic_ostream<_E,
    _Tr>):

    template<class _E, class _Tr = char_traits<_E> >
    class basic_ostream : virtual public basic_ios<_E, _Tr> {
    public:
    typedef basic_ostream<_E, _Tr> _Myt;

    [snip]

    _Myt& operator<<(_Myt& (__cdecl *_F)(_Myt&))
    {
    return ((*_F)(*this));
    }
    [snip]
    };

    I understand that above definition adds a definition that is not part
    of the standard. So it would be still right to say that MS's iostream
    header is not standard-conformant because it lacks the required
    operator that takes standard IO manipulators, wouldn't it?

    Thanks,
    Stuart
     
    Stuart Redmann, Sep 15, 2010
    #18
  19. Stuart Redmann

    Guest

    On Sep 15, 1:08 am, Stuart Redmann <> wrote:
    > [snipped discussion about whether calling convention modifiers make
    > STL code non-compliant]
    >
    > On 13 Sep., robertwess wrote:
    >
    > > It's still unclear where this code is coming from.  If the OP is
    > > trying to use a Windows specific header file, the associated library
    > > is unlikely to be available in binary form on other platforms in a
    > > form intended to be used with the Windows specific header.  And I'm
    > > still having trouble trying to understand what the function is
    > > supposed to do in practical terms.

    >
    > The code in question is from MS's ostream header (in the code I have
    > posted recently I took the liberty to replace the type _Myt with
    > std::eek:stream, but it is actually typedef'ed as basic_ostream<_E,
    > _Tr>):
    >
    > template<class _E, class _Tr = char_traits<_E> >
    >         class basic_ostream : virtual public basic_ios<_E, _Tr> {
    > public:
    >         typedef basic_ostream<_E, _Tr> _Myt;
    >
    > [snip]
    >
    >         _Myt& operator<<(_Myt& (__cdecl *_F)(_Myt&))
    >         {
    >                 return ((*_F)(*this));
    >         }
    > [snip]
    >
    > };
    >
    > I understand that above definition adds a definition that is not part
    > of the standard. So it would be still right to say that MS's iostream
    > header is not standard-conformant because it lacks the required
    > operator that takes standard IO manipulators, wouldn't it?



    The *contents* of the ostream header (and any other standard header)
    should largely be considered totally non-portable. IOW, you cannot
    expect MS's ostream for VC++ to do anything, even compile, on another
    platform, even another MS platform, or even a different version of VC+
    +.

    Nor does what you posted look quite like the code in VC++'s headers,
    at least the couple of current versions that I took a look at. From
    which version are you getting this? In any event, several definitions
    of similar form are passing an explicit this pointer to the passed
    function.

    Is this MSVC 6? Looking back at that it looks like you pulled the
    code from the MSVC6 headers. Note that MSVC6 has a number of
    significant deviations in its template support from the final C++
    standard. MS, along with several other compiler vendors, got hit by a
    late, and significant, change in the standard's definition of
    templates. Basically MSVC6 was released before the C++98 standard was
    finalized. They implemented template support as it was in the draft
    standard, and then (along with several other vendors) got hit when the
    standard changed. MS's policy is that they try to avoid source-code-
    breaking changes *within* a release, so they never "fixed" the
    template support in MSVC6. But they did in the next release (MSVC7
    aka "Visual C++ .NET 2.0").

    But again, where are you going with this? Have you found some flaw in
    VC++'s ostream implementation? Remember, *how* ostream (or anything
    else) is implemented is implementation specific, just so long as it
    does the right thing, as specified by the standard. How is this
    (MSVC internal)code with the calling convention attribute impacting
    your code? Or at least a problem from a compiler less than a dozen
    years old, and from after the C++ standard was finished?
     
    , Sep 15, 2010
    #19
  20. Stuart Redmann

    Bo Persson Guest

    Stuart Redmann wrote:
    > [snipped discussion about whether calling convention modifiers make
    > STL code non-compliant]
    >
    > On 13 Sep., robertwess wrote:
    >
    >> It's still unclear where this code is coming from. If the OP is
    >> trying to use a Windows specific header file, the associated
    >> library is unlikely to be available in binary form on other
    >> platforms in a form intended to be used with the Windows specific
    >> header. And I'm still having trouble trying to understand what
    >> the function is supposed to do in practical terms.

    >
    > The code in question is from MS's ostream header (in the code I have
    > posted recently I took the liberty to replace the type _Myt with
    > std::eek:stream, but it is actually typedef'ed as basic_ostream<_E,
    > _Tr>):
    >
    > template<class _E, class _Tr = char_traits<_E> >
    > class basic_ostream : virtual public basic_ios<_E, _Tr> {
    > public:
    > typedef basic_ostream<_E, _Tr> _Myt;
    >
    > [snip]
    >
    > _Myt& operator<<(_Myt& (__cdecl *_F)(_Myt&))
    > {
    > return ((*_F)(*this));
    > }
    > [snip]
    > };
    >
    > I understand that above definition adds a definition that is not
    > part of the standard. So it would be still right to say that MS's
    > iostream header is not standard-conformant because it lacks the
    > required operator that takes standard IO manipulators, wouldn't it?
    >


    No, __cdecl is the default calling convention, so if you provide a
    function with a stream reference parameter and return value, it will
    be usable as a stream manipulator (inserting the function into the
    stream, calls the function with the stream as a parameter).


    Bo Persson
     
    Bo Persson, Sep 15, 2010
    #20
    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. Muthu
    Replies:
    8
    Views:
    385
    Pete Becker
    Aug 3, 2004
  2. C calling conventions

    , Jun 21, 2005, in forum: C Programming
    Replies:
    16
    Views:
    635
  3. RainBow
    Replies:
    13
    Views:
    924
  4. calling conventions

    , Jun 4, 2008, in forum: C Programming
    Replies:
    10
    Views:
    530
    christian.bau
    Jun 5, 2008
  5. pachl
    Replies:
    1
    Views:
    97
    Henrik Nyh
    Oct 19, 2008
Loading...

Share This Page