Is this legal C?

Discussion in 'C Programming' started by Max, Jun 28, 2008.

  1. Max

    Max Guest

    This was asked in a C test. Is the following code legal C?
    Is it legal in C90? C99?

    #define main()
    int main
    #define mainbody () { return 0; }
    mainbody
    Max, Jun 28, 2008
    #1
    1. Advertising

  2. pete <> writes:
    > Max wrote:
    > > This was asked in a C test. Is the following code legal C?
    > > Is it legal in C90? C99?

    >
    > Yes. Yes.
    >
    > > #define main()
    > > int main
    > > #define mainbody () { return 0; }
    > > mainbody

    >
    > It's as legal as
    >
    > int main(){return 0;}
    >
    > is.


    There's a fairly subtle argument that "int main()" is not actually
    required to be supported, but for all practical purposes it's ok.
    "int main(void)" is better, though.

    Note that "main" is defined as a function-like macro, and "mainbody"
    is defined as an object-like macro.

    Compiling the code and/or examining the preprocessor output (assuming
    your compiler supports this) won't definitively answer the question,
    but it will give some good hints.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 28, 2008
    #2
    1. Advertising

  3. In article <>,
    Richard Heathfield <> wrote:
    >Keith Thompson said:
    >
    ><snip>
    >
    >> There's a fairly subtle argument that "int main()" is not actually
    >> required to be supported,

    >
    >I remember that this has come up before. I wasn't completely convinced
    >then, and I'm not completely convinced now.
    >
    >A function definition that has no parameter list takes no parameters, and
    >is thus precisely equivalent to int main(void) in semantic terms. (Note
    >that we're not talking about mere definitions here.)
    >
    >Since the Standard only requires of main that it be equivalent to int
    >main(void) or int main(int argc, char **argv), and since int main() is
    >equivalent to int main(void), it seems to me that int main() is perfectly
    >acceptable - to the compiler, at least, even though the stylist might
    >object.


    Nice to see clc regulars returning to their home territory.

    Coming soon: Casting the return value of malloc().
    Kenny McCormack, Jun 28, 2008
    #3
  4. Max

    Max Guest

    pete wrote:

    >Max wrote:
    >> This was asked in a C test. Is the following code legal C?
    >> Is it legal in C90? C99?

    >
    >Yes. Yes.


    Thanks.

    >> #define main()
    >> int main
    >> #define mainbody () { return 0; }
    >> mainbody

    >
    >It's as legal as
    >
    > int main(){return 0;}
    >
    >is.
    Max, Jun 28, 2008
    #4
  5. Richard Heathfield <> writes:
    > Keith Thompson said:
    > <snip>
    >
    > > There's a fairly subtle argument that "int main()" is not actually
    > > required to be supported,

    >
    > I remember that this has come up before. I wasn't completely convinced
    > then, and I'm not completely convinced now.
    >
    > A function definition that has no parameter list takes no parameters, and
    > is thus precisely equivalent to int main(void) in semantic terms. (Note
    > that we're not talking about mere definitions here.)
    >
    > Since the Standard only requires of main that it be equivalent to int
    > main(void) or int main(int argc, char **argv), and since int main() is
    > equivalent to int main(void), it seems to me that int main() is perfectly
    > acceptable - to the compiler, at least, even though the stylist might
    > object.
    >
    > <snip>


    Reference: C99 5.1.2.2.1 Program startup

    For this definition:

    int main() { return 0; }

    to be valid (by "valid" here, I mean that an implementation is
    required to support it with well-defined behavior), it must be
    "equivalent" to this definition, which is undeniably valid:

    int main(void) { return 0; }

    It's equivalent by itself, when considered only as a self-contained
    function definition. However, the definition also provides a
    *declaration*. I assert that the two definitions are *not*
    equivalent, because they provide non-equivalent declarations.

    Assume an implementation that does accept "int main() { return 0; }"
    with the obvious meaning (this is allowed by the "or in some other
    implementation-defined manner" clause if not by the "or equivalent"
    clause). Or, if you prefer, assume that "int main() { return 0; }" is
    valid. Then this program:

    int main() { return 0; }

    void foo(void) { main(42); }

    is valid (the declaration of main requires an unspecified number and
    type of arguments; the call to main would invoke undefined behavior if
    it were executed, but it never is). But this program:

    int main(void) { return 0; }

    void foo(void) { main(42); }

    violates the constraint in C99 6.5.2.2p2.

    Therefore, a definition using "int main()" is not equivalent to one
    using "int main(void)", and thus an implementation needn't support it.

    Note that, assuming my reasoning is correct, "int main()" doesn't
    violate any constraint. A program that uses it merely invokes
    undefined behavior. As it happens, every implementation I know of
    responds to this undefined behavior by quietly accepting the
    definition.

    I'm not convinced that this was the intent, and I'd be unsurprised to
    find that the members of the committee either intended "int main()" to
    be valid, or just didn't think about it.

    Implementers can avoid the issue by accepting "int main()", and
    programmers can avoid the issue by using not using "int main()", so
    it's not a huge deal either way.

    I see I posted a similar question to comp.std.c last July,
    subject "Is 'int main() { /* ... */ }' valid?":

    http://groups.google.com/group/comp.std.c/browse_frm/thread/fef53cc781d555a4/41630179750145a9

    but re-reading that thread I see I was actually asking about a
    different subtle issue.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 28, 2008
    #5
  6. pete <> writes:
    > Keith Thompson wrote:
    > > pete <> writes:
    > >> Max wrote:
    > >>> This was asked in a C test. Is the following code legal C?
    > >>> Is it legal in C90? C99?
    > >> Yes. Yes.
    > >>
    > >>> #define main()
    > >>> int main
    > >>> #define mainbody () { return 0; }
    > >>> mainbody
    > >> It's as legal as
    > >>
    > >> int main(){return 0;}
    > >>
    > >> is.

    > > There's a fairly subtle argument that "int main()" is not actually
    > > required to be supported, but for all practical purposes it's ok.
    > > "int main(void)" is better, though.
    > > Note that "main" is defined as a function-like macro, and "mainbody"
    > > is defined as an object-like macro.

    >
    > main isn't defined as a macro.
    > main() is defined as a macro.


    I understand what you mean, but a macro name is an identifier; the
    parentheses aren't part of the name.

    See also the standard's definitions of "object-like macro" and
    "function-like macro".

    #include <stdio.h>

    void Keith_Is_Right(void);

    #define main()
    int main
    #define mainbody () { Keith_Is_Right(); return 0; }
    mainbody

    void Keith_Is_Right(void)
    {
    #ifdef main
    puts("Yes, main is defined as a macro.");
    #else
    puts("Never mind.");
    #endif
    }

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 28, 2008
    #6
  7. Richard Heathfield <> writes:
    > Keith Thompson said:

    [...]
    > > Reference: C99 5.1.2.2.1 Program startup
    > >
    > > For this definition:
    > >
    > > int main() { return 0; }
    > >
    > > to be valid (by "valid" here, I mean that an implementation is
    > > required to support it with well-defined behavior), it must be
    > > "equivalent" to this definition, which is undeniably valid:
    > >
    > > int main(void) { return 0; }
    > >
    > > It's equivalent by itself, when considered only as a self-contained
    > > function definition. However, the definition also provides a
    > > *declaration*. I assert that the two definitions are *not*
    > > equivalent, because they provide non-equivalent declarations.

    >
    > I disagree, because of 3.5.4.3 (C89):
    >
    > "An identifier list declares only the identifiers of the parameters of the
    > function. An empty list in a function declarator that is part of a
    > function definition specifies that the function has no parameters. The
    > empty list in a function declarator that is not part of a function
    > definition specifies that no information about the number or types of the
    > parameters is supplied."
    >
    > The wording is almost identical in C99:
    >
    > 6.7.5.3(14) (C99):
    > "An identifier list declares only the identifiers of the parameters of the
    > function. An empty list in a function declarator that is part of a
    > definition of that function specifies that the function has no parameters.
    > The empty list in a function declarator that is not part of a definition
    > of that function specifies that no information about the number or types
    > of the parameters is supplied."
    >
    > So the empty list in int main() { return 0; } specifies that the function
    > has no parameters, which means that it is semantically equivalent to int
    > main(void), QED.


    Yes, the empty list specifies, for purposes of the definition (the
    body of the function), that the function has no parameters. So the
    two definitions are equivalent in what they say about main's
    parameters.

    But they are not equivalent in other ways.

    An empty list doesn't specify that a caller must pass no arguments,
    because it doesn't provide a prototype.

    Given "int main(void) { ... }", an attempt to call "main(42)" violates
    a constraint. Given "int main(void) { ... }", such a call does not
    violate a constraint (though it does invoke undefined behavior).

    A prototype is not equivalent to the absence of a prototype.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 28, 2008
    #7
  8. Max

    Willem Guest

    Max wrote:
    ) This was asked in a C test. Is the following code legal C?
    ) Is it legal in C90? C99?
    )
    ) #define main()
    ) int main
    ) #define mainbody () { return 0; }
    ) mainbody

    Correct me if I'm wrong, but after preprocessing, doesn't this expand to:

    ---
    int main

    { return 0; }
    ---

    Which is missing the parens after main, and so is illegal ?


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
    Willem, Jun 28, 2008
    #8
  9. Willem <> wrote:
    > Max wrote:
    > ) This was asked in a C test. Is the following code legal C?
    > ) Is it legal in C90? C99?
    > )
    > ) #define main()
    > ) int main
    > ) #define mainbody () { return 0; }
    > ) mainbody
    >
    > Correct me if I'm wrong, but after preprocessing, doesn't this expand to:
    >
    > ---
    > int main
    >
    > { return 0; }
    > ---
    >
    > Which is missing the parens after main, and so is illegal ?


    You are wrong. 'main' is defined as a function-like macro taking no arguments
    and expanding to an empty string. The 'main' in "int main" does not match an
    invocation of this macro and is thus not replaced.
    'mainbody' on the other hand is an object-like macro which is defined as "()
    { return 0; }".

    (It makes a great deal of difference if there is a space or not between the
    macro name and a '(' when defining a macro.)

    After preprocessing it should thus expand to:

    ---

    int main

    () { return 0; }
    ---

    Which is of course equivalent to
    ---
    int main() { return 0; }
    ---
    which is quite legal.


    --
    <Insert your favourite quote here.>
    Erik Trulsson
    Erik Trulsson, Jun 28, 2008
    #9
  10. pete schrieb:

    > Max wrote:
    >> This was asked in a C test. Is the following code legal C?
    >> Is it legal in C90? C99?

    >
    > Yes. Yes.
    >
    >> #define main()
    >> int main
    >> #define mainbody () { return 0; }
    >> mainbody


    Must be some gcc extension. This compiles not even with LCC-WIN32:

    lc -ansic -O -c main.c
    Error main.c: 4 Syntax error; missing semicolon before `mainbody'
    Warning main.c: 4 no type specified. Defaulting to int
    Error main.c: 5 Syntax error; missing semicolon before `end of input'
    2 errors, 1 warning
    1 error

    >
    > It's as legal as
    >
    > int main(){return 0;}
    >
    > is.
    Hans Schneider, Jun 28, 2008
    #10
  11. Hans Schneider <> writes:

    > pete schrieb:
    >
    >> Max wrote:
    >>> This was asked in a C test. Is the following code legal C?
    >>> Is it legal in C90? C99?

    >>
    >> Yes. Yes.
    >>
    >>> #define main()
    >>> int main
    >>> #define mainbody () { return 0; }
    >>> mainbody

    >
    > Must be some gcc extension.


    The reference is to check the standard, not to try various
    implementations. The standard is clear that main does not get
    expanded and that mainbody should be because mainbody is an
    object-like macro, not a function-like one.

    > This compiles not even with LCC-WIN32:


    Then file a bug report if you are interested. lcc-win32 fails to see
    mainbody as a macro that should be expanded. If we remove the
    entirely unused #define main() the lcc-win32 gets it right. That
    unused definition of main is throwing it. I can guess why -- the
    pre-processor must look to see if 'main' is followed by '(', and this
    must be done without expanding macros. However, having seen that
    'main' is not followed by a '(', the token that was looked at needs to
    checked to see if it *does* expand. A simple example of the bug is
    this:

    #define F()
    #define M
    F M

    which should expand to 'F' but with lcc-win32 you get 'F M'.

    --
    Ben.
    Ben Bacarisse, Jun 28, 2008
    #11
  12. Max

    CBFalconer Guest

    Hans Schneider wrote:
    > pete schrieb:
    >> Max wrote:
    >>
    >>> This was asked in a C test. Is the following code legal C?
    >>> Is it legal in C90? C99?

    >>
    >> Yes. Yes.
    >>
    >>> #define main()
    >>> int main
    >>> #define mainbody () { return 0; }
    >>> mainbody

    >
    > Must be some gcc extension. This compiles not even with LCC-WIN32:
    >
    > lc -ansic -O -c main.c
    > Error main.c: 4 Syntax error; missing semicolon before `mainbody'
    > Warning main.c: 4 no type specified. Defaulting to int
    > Error main.c: 5 Syntax error; missing semicolon before `end of input'
    > 2 errors, 1 warning
    > 1 error


    That does tend to indicate some failings in lcc-win32.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Jun 28, 2008
    #12
  13. Erik Trulsson <> writes:
    [...]
    > (It makes a great deal of difference if there is a space or not between the
    > macro name and a '(' when defining a macro.)

    [...]

    Right. But it *doesn't* matter whether there's a space between the
    macro name and a '(' when *invoking* a macro.

    Terminology: an "object-like macro" is one that takes no arguments; a
    "function-like macro" is one that does take arguments.

    For example:

    #define OBJ () /* an object-like macro expanding to () */
    #define FUNC() /* a function-like macro expanding to nothing */

    FUNC /* Not replaced */
    FUNC() /* Replaced by nothing */
    FUNC () /* Also replaced by nothing; the space is irrelevant */

    This isn't relevant to the example we're discussing, but I have
    seen it trip up some people.

    In most C syntax, whitespace is irrelevant (except as part of a
    literal or to separate two tokens that otherwise might be a single
    token). An exception is made in macro definitions; this special
    case allows the expansion of an object-like macro to start with
    '(', while allowing for function-like macros. There's no need
    for such an exception for invocations of function-like macros.
    If there were, it would defeat the purpose of making function-like
    macros act (more or less) like function calls.

    (And let me remind everyone to compile your code before posting it.
    I made a really embarrassing mistake in the initial version of
    the above example; I wouldn't have caught it if I hadn't tried it
    out first. No, I'm not going to tell you what the mistake was.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 28, 2008
    #13
  14. On Sat, 28 Jun 2008 00:25:39 UTC, Richard Heathfield
    <> wrote:

    > Keith Thompson said:
    >
    > <snip>
    >
    > > There's a fairly subtle argument that "int main()" is not actually
    > > required to be supported,

    >
    > I remember that this has come up before. I wasn't completely convinced
    > then, and I'm not completely convinced now.
    >
    > A function definition that has no parameter list takes no parameters, and
    > is thus precisely equivalent to int main(void) in semantic terms. (Note
    > that we're not talking about mere definitions here.)
    >
    > Since the Standard only requires of main that it be equivalent to int
    > main(void) or int main(int argc, char **argv), and since int main() is
    > equivalent to int main(void), it seems to me that int main() is perfectly
    > acceptable - to the compiler, at least, even though the stylist might
    > object.


    No, its not equivalent.

    int main(void) ia a function returning int and receiving no
    parameters.

    Whereas int main() is a function returning int an receiving an unknown
    number of parameters of unknown types.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2R Deutsch ist da!
    Herbert Rosenau, Jun 28, 2008
    #14
  15. Max

    CBFalconer Guest

    Keith Thompson wrote:
    >

    .... snip ...
    >
    > Right. But it *doesn't* matter whether there's a space between
    > the macro name and a '(' when *invoking* a macro.
    >
    > Terminology: an "object-like macro" is one that takes no
    > arguments; a "function-like macro" is one that does take arguments.
    >
    > For example:
    >
    > #define OBJ () /* an object-like macro expanding to () */
    > #define FUNC() /* a function-like macro expanding to nothing */
    >
    > FUNC /* Not replaced */
    > FUNC() /* Replaced by nothing */
    > FUNC () /* Also replaced by nothing; the space is irrelevant */
    >
    > This isn't relevant to the example we're discussing, but I have
    > seen it trip up some people.


    Where do you see this in the standard? I always considered it as
    separated by the lexer, which can find the "FUNC(" in the stream,
    and expand it. However the stream "FUNC (" is textually
    different. If I am full of it I want to find out.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Jun 29, 2008
    #15
  16. On Sat, 28 Jun 2008 21:17:59 -0400, CBFalconer wrote:
    > Keith Thompson wrote:
    >> [...]
    >> #define FUNC() /* a function-like macro expanding to nothing */
    >> [...]
    >> FUNC () /* Also replaced by nothing; the space is irrelevant */

    >
    > Where do you see this in the standard? I always considered it as
    > separated by the lexer, which can find the "FUNC(" in the stream, and
    > expand it. However the stream "FUNC (" is textually different. If I am
    > full of it I want to find out.


    6.10.3p10:
    "[...] Each subsequent instance of the function-like macro name followed
    by a ( as the next preprocessing token introduces the sequence of
    preprocessing tokens that is replaced by the replacement list in the
    definition (an invocation of the macro). [...]"

    5.1.1.2p1[3]:
    "3. The source file is decomposed into preprocessing tokens and sequences
    of white-space characters (including comments). [...]"

    Whitespace is retained by the lexer, but not as pp tokens. In FUNC (), the
    next pp token after FUNC is (.
    Harald van Dijk, Jun 29, 2008
    #16
  17. Max

    Willem Guest

    Erik Trulsson wrote:
    ) You are wrong. 'main' is defined as a function-like macro taking no arguments
    ) and expanding to an empty string. The 'main' in "int main" does not match an
    ) invocation of this macro and is thus not replaced.
    ) 'mainbody' on the other hand is an object-like macro which is defined as "()
    ) { return 0; }".

    Oh right, I overlooked the parens after the mainbody macro.
    My bad.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
    Willem, Jun 29, 2008
    #17
  18. Max

    CBFalconer Guest

    Harald van D?k wrote:
    > CBFalconer wrote:
    >> Keith Thompson wrote:
    >>> [...]
    >>> #define FUNC() /* a function-like macro expanding to nothing */
    >>> [...]
    >>> FUNC () /* Also replaced by nothing; the space is irrelevant */

    >>
    >> Where do you see this in the standard? I always considered it as
    >> separated by the lexer, which can find the "FUNC(" in the stream,
    >> and expand it. However the stream "FUNC (" is textually different.
    >> If I am full of it I want to find out.

    >
    > 6.10.3p10:
    > "[...] Each subsequent instance of the function-like macro name
    > followed by a ( as the next preprocessing token introduces the
    > sequence of preprocessing tokens that is replaced by the
    > replacement list in the definition (an invocation of the macro).
    > [...]"
    >
    > 5.1.1.2p1[3]:
    > "3. The source file is decomposed into preprocessing tokens and
    > sequences of white-space characters (including comments). [...]"
    >
    > Whitespace is retained by the lexer, but not as pp tokens. In
    > FUNC (), the next pp token after FUNC is (.


    I guess I am full of it. My technique is easier to parse, but may
    not fit into doing it with lex and yacc. Time to forget that
    mistake.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Jun 29, 2008
    #18
  19. On Sun, 29 Jun 2008 03:50:36 UTC, Richard Heathfield
    <> wrote:

    > Herbert Rosenau said:
    >
    > <snip>
    >
    > > int main(void) ia a function returning int and receiving no
    > > parameters.

    >
    > Right.
    >
    > > Whereas int main() is a function returning int an receiving an unknown
    > > number of parameters of unknown types.

    >
    > Wrong for a definition of int main(), for reasons that I have posted
    > elsethread.
    >

    You need a prototype to specifiy the type(s) and number of parameters.
    Without a prototype you can't do so.

    int main() is noways a prototype because it does not specifiy a bit of
    type or number of parameters. Yes, it is legal C, but gives no
    information about the parameters.

    int main(void) as declaration is a prototype. As definition without
    preceeding declaration it works as declaration too.

    There is no difference between anay function and main(). Either you
    defines a prototype (implicity by definition) or you does not. Without
    a prototype the compiler will not able to gather the number of
    parameters and theyr type. Saying in a prototype the number of
    parameters is void is clearly different from having number and type of
    parameters is unknown. Without prototype but with declaration you can
    call a function differently in a translation unit, with a prototype
    you can't. This is why prototypes are introduced in the standard.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2R Deutsch ist da!
    Herbert Rosenau, Jun 29, 2008
    #19
  20. On Sun, 29 Jun 2008 10:07:19 +0000, Herbert Rosenau wrote:
    > On Sun, 29 Jun 2008 03:50:36 UTC, Richard Heathfield
    > <> wrote:
    >> Herbert Rosenau said:
    >> > Whereas int main() is a function returning int an receiving an
    >> > unknown number of parameters of unknown types.

    >>
    >> Wrong for a definition of int main(), for reasons that I have posted
    >> elsethread.
    >>

    > You need a prototype to specifiy the type(s) and number of parameters.
    > Without a prototype you can't do so.


    Do you believe this code:

    int main() {
    static int dummy = 0;
    if (dummy < 42)
    {
    dummy++;
    return main(0, 1, 2, 3, 4, 5);
    }
    return 0;
    }

    is valid? I'm _not_ asking if you expect compilers to complain about the
    code, I'm asking if you believe this code is guaranteed to behave the same
    way on all current and future C implementations.
    Harald van Dijk, Jun 29, 2008
    #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. Valentin Tihomirov

    Is this legal?

    Valentin Tihomirov, Oct 21, 2003, in forum: VHDL
    Replies:
    20
    Views:
    1,251
    Jan Decaluwe
    Oct 29, 2003
  2. Divyang M
    Replies:
    9
    Views:
    626
    Divyang M
    May 18, 2005
  3. Divyang M
    Replies:
    1
    Views:
    572
    Jerzy Gbur
    May 15, 2005
  4. Weng Tianxiang
    Replies:
    12
    Views:
    1,400
  5. =?Utf-8?B?RGF2ZQ==?=

    Legal ViewState Characters

    =?Utf-8?B?RGF2ZQ==?=, May 24, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    369
    Patrice
    May 24, 2004
Loading...

Share This Page