advance c questions

I'm looking for a site with some harder code expamles and questions
than the ones that usually in c tutorials.
I need this for a job interview wich wil take place next week.
Wish me good luck!!!
«1

Comments

  • : I'm looking for a site with some harder code expamles and questions
    : than the ones that usually in c tutorials.

    Go through the C FAQ (second link in my signature) and study each question, I wouldn't be surprised if you were asked alot of them. Steve Summit (the maintainer of the C FAQ) has a tutorial site that you can Google for. Tom Torf's has another one that is pretty good, but I don't know if it is still up. IIRC, Mr. Summit also had a pretty exhaustive list of interview questions, try the Google archives for comp.lang.c. Peter Van Der Linden's book "Expert C Programming: Deep C Secrets" has a section on job interviews for C programmers, as well as many other things you should know. That's about all I can think of right now. I seem to remember a small program that had all kinds of subtle errors, and it was used for interviews. If I find it, I will post it.


    : I need this for a job interview wich wil take place next week.
    : Wish me good luck!!!

    Good luck! :-) Let us know if it worked out, and maybe you can post some of the questions that you found interesting from your interview.


    HTH,
    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/


  • Apologies for replying to my own post, but here is that program I said I would post. It's kind of fun to try it, it should compile (with some warnings), but there are some really obscure bugs in it. I think the average for most people is 4 or 5 bugs found. I believe this was originally developed by a New Zealand programming consultant named Edmund Stephen-Smith, be careful! ;-)

    [code=ffffff]
    #include
    #include

    #define SWAP(x, y) x^= y^= x;

    int
    main()
    {
    char *s="uvwxyz";
    char *t;
    unsigned long a, b, c;
    int i;

    printf("String: %s (%d entries).
    "
    "Change which character to '1'? ", s,
    strlen(s));
    scanf("%d", &a);

    assert((0 <= a) && (a < strlen(s)));
    s[a]= '1';

    printf("Original changed to %s
    ", s);
    printf("Reverse which range of characters (from-to)? ",
    b, c);

    scanf("%lu%lu", &a, &b);
    assert(a<=b);

    t= malloc(strlen(s+1));

    strcpy(t, s);
    for (i=b; i<(b+c)/2; i++)
    SWAP(t[b+i], t[c-i]);

    printf("Result of reverse is %s -> %s
    ", s, t);
    return 0;
    }
    [/code]

    If I am feeling brave tomorrow night (and I don't get sent out of town on business), I will post my list. Have fun!


    HTH,
    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/


  • I found 9 of which 2 are the same ones. I would like to know which test and which compiler will actually be able to run without errors. The code is so smashed that one has to laugh. Did this guy make is as a test or as an example of string manipulation?
  • : Apologies for replying to my own post, but here is that program I said I would post. It's kind of fun to try it, it should compile (with some warnings), but there are some really obscure bugs in it. I think the average for most people is 4 or 5 bugs found. I believe this was originally developed by a New Zealand programming consultant named Edmund Stephen-Smith, be careful! ;-)
    :
    : [code=ffffff]
    : #include
    : #include
    :
    : #define SWAP(x, y) x^= y^= x;
    :
    : int
    : main()
    : {
    : char *s="uvwxyz";
    : char *t;
    : unsigned long a, b, c;
    : int i;
    :
    : printf("String: %s (%d entries).
    "
    : "Change which character to '1'? ", s,
    : strlen(s));
    : scanf("%d", &a);
    :
    : assert((0 <= a) && (a < strlen(s)));
    : s[a]= '1';
    :
    : printf("Original changed to %s
    ", s);
    : printf("Reverse which range of characters (from-to)? ",
    : b, c);
    :
    : scanf("%lu%lu", &a, &b);
    : assert(a<=b);
    :
    : t= malloc(strlen(s+1));
    :
    : strcpy(t, s);
    : for (i=b; i<(b+c)/2; i++)
    : SWAP(t[b+i], t[c-i]);
    :
    : printf("Result of reverse is %s -> %s
    ", s, t);
    : return 0;
    : }
    : [/code]
    :
    : If I am feeling brave tomorrow night (and I don't get sent out of town on business), I will post my list. Have fun!
    :
    :
    : HTH,
    : Will
    : --
    : http://www.tuxedo.org/~esr/faqs/smart-questions.html
    : http://www.eskimo.com/~scs/C-faq/top.html
    : http://www.parashift.com/c++-faq-lite/
    : http://www.accu.org/
    :
    :
    :

    22 :-)
  • [code=ffffff]
    #include
    #include

    #define SWAP(x, y) x^= y^= x;

    /*
    ** The swap isn't correct, and the quick fix:
    **
    ** #define SWAP(x, y) x ^= y ^= x ^= y;
    **
    ** ...is undefined because it modifies x
    ** more than once between sequence points
    */

    int
    main()
    /*
    ** Non-portable declaration of main. (very pedantic, should specify void)
    */
    {
    char *s="uvwxyz";
    char *t;
    unsigned long a, b, c;
    int i;

    printf("String: %s (%d entries).
    "
    "Change which character to '1'? ", s,
    strlen(s));
    /*
    ** The format string is missing either the last '
    '
    ** or an explicit call to fflush(stdout) after printf().
    **
    ** strlen(s) is the wrong type (size_t) for a "%d" format specifier,
    ** but with a lack of a prototype in scope, it defaults to int,
    ** which is undefined.
    */

    scanf("%d", &a);
    /*
    ** &a is a pointer to unsigned long, but the "%d" designates
    ** a pointer to int for the argument.
    */
    assert((0 <= a) && (a < strlen(s)));
    /*
    ** The assert macro is for program diagnostics, not run-time input.
    **
    ** 0 <= a will always be true, a is unsigned.
    **
    ** the return value of scanf() was never checked, so we don't know
    ** whether 'a' was ever assigned a value, that is undefined behavior.
    */
    s[a]= '1';
    /*
    ** Modifying a non-modifiable lvalue, undefined behavior.
    */

    printf("Original changed to %s
    ", s);
    printf("Reverse which range of characters (from-to)? ",
    b, c);
    /*
    ** Again, no terminating '
    ' or fflush(stdout).
    **
    ** Excess arguments to printf(), which isn't bad in itself, but they
    ** are uninitialzed, so when they are evaluated by printf(), we get
    ** undefined behavior.
    */

    scanf("%lu%lu", &a, &b);
    /*
    ** Return value of scanf() is not checked to make sure that both
    ** 'a' and 'b' were assigned values.
    */

    assert(a<=b);
    /*
    ** Again, assert is not used for this.
    **
    ** The test itself is wrong, because a and b are not checked for
    ** even being within range of the array they are to index.
    */

    t= malloc(strlen(s+1));
    /*
    ** No prototype in scope for malloc(), so it defaults to int, and
    ** now we have a bug from the conversion.
    **
    ** The argument isn't calculating the length of 's' and then adding
    ** one for the '' terminator. It is actually going to end up being
    ** two elements too short.
    */

    strcpy(t, s);
    /*
    ** Boom! undefined behavior for writing into memory we don't own.
    */
    for (i=b; i<(b+c)/2; i++)
    /*
    ** i is being assigned a value from an object whose value is
    ** indeterminate, and is of the wrong type.
    **
    ** i<(b+c)/2 is comparing a signed value to an unsigned value which is
    ** always a major source of bugs because of integral promotion.
    **
    ** The calculation itself is incorrect, because 'c' was never initialized,
    ** and it doesn't have any apparent relation to the code flow so far.
    */
    SWAP(t[b+i], t[c-i]);
    /*
    ** Aside from the superfluous semi-colon (there is already one in the
    ** macro definition), who knows if the value of any of 'b', 'i', or 'c' is
    ** anything meaningful.
    **
    ** Also, if i = b (from the first statement of the for loop) then the
    ** addition couldn't be indexing the intended element of the array.
    ** I am too tired to guess about the second one!
    */

    printf("Result of reverse is %s -> %s
    ", s, t);
    return 0;
    }
    [/code]
    Total: 22, but with some duplicates. I can't say whether any of them are correct, because I don't have an answer key or anything. However, I am sure I will be corrected if I was wrong! :-)


    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/


  • I was going to post my own list, but combing over yours in more fun... if only to once again expose my ignorance. ;)

    [code=ffffdd]
    int
    main()
    /*
    ** Non-portable declaration of main. (very pedantic, should specify void)
    */
    [/code]
    I'm assuming that was a joke.



    [code=ffffdd]
    printf("String: %s (%d entries).
    "
    "Change which character to '1'? ", s,
    strlen(s));
    /*
    ** The format string is missing either the last '
    '
    ** or an explicit call to fflush(stdout) after printf().
    */
    [/code]
    Why would it be an error for the format to not end in '
    '?!



    [code=ffffdd]
    /*
    ** the return value of scanf() was never checked, so we don't know
    ** whether 'a' was ever assigned a value, that is undefined behavior.
    */
    [/code]
    [italic][grey][/grey][/italic]
    It's only undefined if you [italic]use[/italic] 'a' before properly initializing it.
    [italic][grey][/grey][/italic]




    [code=ffffdd]
    printf("Original changed to %s
    ", s);
    printf("Reverse which range of characters (from-to)? ",
    b, c);
    /*
    ** Again, no terminating '
    ' or fflush(stdout).
    */
    [/code]
    Again, why is that a problem? Similar code is use throughout the standard.




    [code=ffffdd]
    /*
    ** but they are uninitialzed, so when they are evaluated by printf(), we get
    ** undefined behavior.
    */
    [/code]
    [italic][grey][/grey][/italic]
    The arguments are not evaluted by printf, they are evaluated before printf is even called.
    [italic][grey][/grey][/italic]

    Cheers,
    Eric

  • : I was going to post my own list, but combing over yours in more fun... if only to once again expose my ignorance. ;)

    Or mine, as the case may be (see below). ;)


    : [code=ffffdd]
    : int
    : main()
    : /*
    : ** Non-portable declaration of main. (very pedantic, should specify void)
    : */
    : [/code]
    : I'm assuming that was a joke.

    It wasn't a joke, but I did blow it. What I meant to say, was that the parameter list should specify void, not the return type. I cannot think of a more enlightening experience, than to be confronted with my own shortcomings. If I keep saying that, maybe the blush will leave my face ;).

    Additionally, I don't think that my non-portable qualification is correct. In the case of an unspecified parameter list, you can actually call main recursively with an argument, and it won't generate a diagnostic. Obviously this is C only, C++ does not allow recursive calls to main(). The only reason I could give for having said it was not portable, was that the standard specifies int main(void) as one of the two forms for main. It serves me right for trying to be too pedantic, and my apologies to the peanut gallery.


    : [code=ffffdd]
    : printf("String: %s (%d entries).
    "
    : "Change which character to '1'? ", s,
    : strlen(s));
    : /*
    : ** The format string is missing either the last '
    '
    : ** or an explicit call to fflush(stdout) after printf().
    : */
    : [/code]
    : Why would it be an error for the format to not end in '
    '?!

    It wouldn't be an error, unless I had gone on to mention that the "un-newlined" portion was the actual prompt, so the user might not see it while the program was blocking for input. Here is the standard text:

    ...When a stream is [italic]line buffered[/italic], characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered...

    Of course, fflush(stdout) will keep the prompt on the same line as the input.


    : [code=ffffdd]
    : /*
    : ** the return value of scanf() was never checked, so we don't know
    : ** whether 'a' was ever assigned a value, that is undefined behavior.
    : */
    : [/code]
    : [italic][grey][/grey][/italic]
    : It's only undefined if you [italic]use[/italic] 'a' before properly initializing it.
    : [italic][grey][/grey][/italic]

    That's right, but in that assert macro, 'a' was being used in a comparison. I think it would have been better for me to also have said "as long as NDEBUG is not defined".


    : [code=ffffdd]
    : printf("Original changed to %s
    ", s);
    : printf("Reverse which range of characters (from-to)? ",
    : b, c);
    : /*
    : ** Again, no terminating '
    ' or fflush(stdout).
    : */
    : [/code]
    : Again, why is that a problem? Similar code is use throughout the standard.

    Again, you are correct in your impression, because what I said was not what I meant. Did you miss out on telepathy or something? j/k of course, and the point is taken.


    : [code=ffffdd]
    : /*
    : ** but they are uninitialzed, so when they are evaluated by printf(), we get
    : ** undefined behavior.
    : */
    : [/code]
    : [italic][grey][/grey][/italic]
    : The arguments are not evaluted by printf, they are evaluated before printf is even called.
    : [italic][grey][/grey][/italic]

    Absolutely right. Thank you for the corrections, and for taking the time to review my responses.
  • : : Why would it be an error for the format to not end in '
    '?!
    :
    : It wouldn't be an error, unless I had gone on to mention that the "un-newlined" portion was the actual prompt, so the user might not see it while the program was blocking for input. Here is the standard text:
    :
    : ...When a stream is [italic]line buffered[/italic], characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered...


    It goes on to say, in the same paragraph: "...[italic]or[/italic] when input is requested on a line buffered stream..." (my emphasis).


    : Of course, fflush(stdout) will keep the prompt on the same line as the input.

    So would the next call for input on that stream (i.e. the scanf call on the next line).


    : : the return value of scanf() was never checked, so we don't know
    : : whether 'a' was ever assigned a value, that is undefined behavior.
    : [italic][grey][/grey][/italic]
    : It's only undefined if you [italic]use[/italic] 'a' before properly initializing it.
    : [italic][grey][/grey][/italic]
    :
    : That's right, but in that assert macro, 'a' was being used in a comparison. I think it would have been better for me to also have said "as long as NDEBUG is not defined".

    Oh, clearly 'a' [italic]was[/italic] used later, and that was undefined. I just meant to say that it's not undefined for 'a' to [italic]have[/italic] an undefined value, as the wording of your comment suggested, "so we don't know whether 'a' was ever assigned a value, that is undefined behavior". I did label that nitpick 'pedantic', right? ;)

    Cheers,
    Eric




  • Eric/Will,

    Witnessing your exchange of thoughts was education and thanks for the same. Both of you were referring to the "standard text" in your messsages. Could you be more specific? Can I download the document from somewhere?
    thanks
    pv
  • : : : Why would it be an error for the format to not end in '
    '?!
    : :
    : : It wouldn't be an error, unless I had gone on to mention that the "un-newlined" portion was the actual prompt, so the user might not see it while the program was blocking for input. Here is the standard text:
    : :
    : : ...When a stream is [italic]line buffered[/italic], characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered...
    :
    :
    : It goes on to say, in the same paragraph: "...[italic]or[/italic] when input is requested on a line buffered stream..." (my emphasis).

    That's my bad, and it's quite inexcusable. Normally I try to be much more attentive when quoting the standard, I won't be so careless in the future.

    That having been said, the entire quote is this (from 7.19.3, subparagraph 3, line 4):

    When a stream is [italic]line buffered[/italic], characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment.

    There is another section (5.1.2.3, subparagraph 5) which goes on to say (my emphasis):

    The input and output dynamics of interactive devices shall take place as specified in 7.19.3. [italic]The intent of these requirements is that unbuffered or line buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.[/italic]

    Which is great indeed, and likely to enable very restful sleep. *Buuuut* (brakes screech), an interactive device is implementation defined, and doesn't have to be what we want it to be , and either stdin or stdout can be redirected to another file or program. In that case, the flushing mechanisms may not work, and the only (portable) guarantee is an explicit call fflush(stdout). See the FAQ 12.4. Upon doing some further research on this subject (Google archives), I find that a '
    ' isn't a guarantee either. It is more like a belt, and fflush(stdout) is the suspenders. Perhaps the reliance on the standards' intent is more like well-fitting pants.


    : : Of course, fflush(stdout) will keep the prompt on the same line as the input.
    :
    : So would the next call for input on that stream (i.e. the scanf call on the next line).

    Agreed, as long as both stdin and stdout are opened for the same interactive device.


    : : : the return value of scanf() was never checked, so we don't know
    : : : whether 'a' was ever assigned a value, that is undefined behavior.
    : : [italic][grey][/grey][/italic]
    : : It's only undefined if you [italic]use[/italic] 'a' before properly initializing it.
    : : [italic][grey][/grey][/italic]
    : :
    : : That's right, but in that assert macro, 'a' was being used in a comparison. I think it would have been better for me to also have said "as long as NDEBUG is not defined".
    :
    : Oh, clearly 'a' [italic]was[/italic] used later, and that was undefined. I just meant to say that it's not undefined for 'a' to [italic]have[/italic] an undefined value, as the wording of your comment suggested, "so we don't know whether 'a' was ever assigned a value, that is undefined behavior".

    Sometimes it isn't just one layer of dense haze over my eyes, but 2 or 10. In this case (fortunately) it is only 2, and I definitely see your point now. Again, I thank you for the clarification.


    : I did label that nitpick 'pedantic', right? ;)

    Yes, you did, but I think it was pedantically important. :)


    Thanks again,
    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/


  • : I found 9 of which 2 are the same ones. I would like to know which test and which compiler will actually be able to run without errors.

    Any [b]C[/b] compiler *should* compile it. You will likely get a few warnings. Here is the output from GCC:
    [code=000000][color=ffffff]
    C:Csrcb>gcc -v
    Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs
    gcc version 2.95.3-5 (cygwin special)

    C:Csrcb>gcc -W -Wall -ansi -pedantic -c foo.c
    foo.c: In function `main':
    foo.c:17: warning: int format, long int arg (arg 2)
    foo.c:19: warning: comparison of unsigned expression >= 0 is always true
    foo.c:24: warning: too many arguments for format
    foo.c:29: warning: implicit declaration of function `malloc'
    foo.c:29: warning: assignment makes pointer from integer without a cast
    foo.c:32: warning: comparison between signed and unsigned
    [/color][/code]



    : The code is so smashed that one has to laugh. Did this guy make is as a test or as an example of string manipulation?
    :

    OMG, No! On purpose! On purpose! I should have stated that this was designed this way. Thank you for letting me clarify that. Sorry!


    HTH,
    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/


  • : Witnessing your exchange of thoughts was education and thanks for the same.

    It's always nice to hear that my ineptitude can be educational. Any way I can be of service! ;)


    : Both of you were referring to the "standard text" in your messsages. Could you be more specific? Can I download the document from somewhere?

    Sure, it is all in the C FAQ. Check question 11.2. You can also get a copy of the standard [italic]draft[/italic] in pdf format. I posted a link a couple of days ago in a thread called "BOOLEAN TYPE". You should note that it is not the actual standard, but it does come in quite handy for quick checks. If you intend on becoming a professional programmer, I highly recommend the true version. Of course, having a copy of the standard does not make one a professional programmer, nor an expert, and I am a perfect example of that. :)


    HTH,
    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/


  • thank you for all the replys and links.
    now an example question

    you need to write 2 function set and call.
    set will just get a function pointer void (*func)() and the time this function sould be
    executed.
    call will start to execute each function in time.
    for example:
    void func1()
    {/*do something*/*}

    void func2()
    {/*do something*/*}

    void main(void)
    {
    set(func1,5);
    set(func2,3);
    call();
    }

    now 3 minutes after call begin execution it will execute func2 and two minutes later
    (5 minutes from the start) it will execute func1.

    suppose:
    void func1()
    {set(func2,4);}

    in case you set another function during call execution func2 sholud be execute 4 minutes
    from the point of time it was set.
    please send your answer to the site or to my email ofer_2002@yahoo.com

  • A C++ solution (quite concise B-)):
    [code]
    #include
    #include
    #include
    #include

    using namespace std;

    const int SEC_PER_MIN = 60; // use 1 for debugging ;-)

    struct Callback {
    void (*func)();
    time_t sec;

    bool operator<(const Callback &c) const { return sec > c.sec; }
    };

    vector v_callbacks;

    void set(void (*func)(), time_t min)
    {
    Callback c = { func, time(0) + SEC_PER_MIN * min };

    v_callbacks.insert(lower_bound(v_callbacks.begin(), v_callbacks.end(), c), c);
    }

    void call()
    {
    while (v_callbacks.size()) {

    while (time(0) < v_callbacks.back().sec);

    v_callbacks.back().func();
    v_callbacks.pop_back();
    }
    }

    void func2();

    void func1()
    {
    cout << "func1()
    ";
    set(func2, 4);
    }

    void func2()
    {
    cout << "func2()
    ";
    }

    int main()
    {
    set(func1, 5);
    set(func2, 3);
    call();

    return 0;
    }
    [/code]
  • [b][red]This message was edited by the whoie at 2002-4-11 0:35:56[/red][/b][hr]
    : A C++ solution (quite concise B-)):

    Concise indeed! It is considerably shorter than my C version, perhaps only half as long. However, I do think that there is some room for improvement (see below).


    : [code]
    : #include
    : #include
    : #include
    : #include
    :
    : using namespace std;
    :
    : const int SEC_PER_MIN = 60; // use 1 for debugging ;-)
    :
    : struct Callback {
    : void (*func)();
    : time_t sec;
    :
    : bool operator<(const Callback &c) const { return sec > c.sec; }
    : };
    [/code]

    The first thing that we might want to look at, is that time_t is only guaranteed to be an arithmetic type that represents a period in time. That means that we can't really be certain on any given implementation that time_t represents seconds. The C Standard Library gives us a way to work around it by using difftime():
    [code=ffffff]
    const double SEC_PER_INTERVAL = 60;

    double intervals_remaining(double nintervals, time_t set_time)
    {
    double intervals_elapsed = difftime(time(0), set_time) / SEC_PER_INTERVAL;

    return nintervals - intervals_elapsed;
    }
    [/code]
    Also, we can redefine the timing simply by changing the number of seconds per interval.
    [code]
    :
    : vector v_callbacks;
    [/code]

    The specs make it sound like these set() and call() functions are part of a task scheduler, which makes me think that a [italic]std::priority_queue[/italic] might be a better data structure than a std::vector for this. You have already defined operator<, which is what a priority queue uses to determine the order.

    If we do that right, then our set() and call() functions become rather trivial:
    [code=ffffff]

    priority_queue<Callback> task_schedule;

    void set(void (*func)(), double interval)
    {
    // the return value from time() should
    // be checked for time_t(-1)...this
    // is omitted
    Callback c = { func, interval, time(0) }; // definition changed appropriately

    task_schedule.push(c);
    }

    void call(void)
    {
    while ( !task_schedule.empty() ) {
    const Callback& c = task_schedule.top();

    while ( intervals_remaining(c.nintervals, c.set_time) > 0 ) {
    continue;
    }

    // we have a problem if func
    // was a null pointer...ouch!
    c.func();

    task_schedule.pop();
    }
    }
    [/code]

    Of course, we might want to make the intervals_remaining() function a method of our class, as well as SEC_PER_INTERVAL. That way, we can make call() even cleaner, and less effected by changing the class. All depending on how much we really want to do with this. ;)

    HTH,
    Will
    --
    http://www.tuxedo.org/~esr/faqs/smart-questions.html
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/
    http://www.accu.org/




Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories