No subject was specified. 
Author Message
 No subject was specified.

I've been starting back into C after a long exodus in other languages
(notably Perl) and while I'm at it, I'd like to set up some "standard"
testing scheme for my code (along with a few libraries for data
structures I can't live without like hashes and sets).

My current idea is to have a simple preprocessor to either,

(a) if (DEBUG == 1)

convert all return's to return_val = ... ; goto onExit ;

(b) if (DEBUG == 0)

strip all onEntry and onExit blocks and leave return's as they are.

so that subroutine would be coded:

mysub( paras )
{
  onEntry:
  {
  }  /* onEntry block */

  subroutine code

  onExit:
  {
  }

Quote:
}

This way I can place checking code (eg asserts and the like) into the
onEntry and onExit blocks so:

- I don't have #if's scatterred all over the code, which in my
experience can introduce bugs
- have some means of "collecting" returns to a common exit point for
testing purposes
- an easy means of removing the debugging code once testing is over

Obvious any number of refinements are possible, but first things first!

I'd welcome anyone's comments on this. There may be a better way of
doing this. I realise that onEntry is a little redundant, but its tidy
and clear :-)

Bear in mind I want this to work in C, not C++, so using try, etc., is
out of the frame.

Grant
--



Fri, 29 Aug 2003 07:32:41 GMT  
 No subject was specified.
Sorry for omitting the subject -- I didn't notice... might have to start
this as a new thread again... we'll see.

Grant

Quote:

> I've been starting back into C after a long exodus in other languages
> (notably Perl) and while I'm at it, I'd like to set up some "standard"
> testing scheme for my code (along with a few libraries for data
> structures I can't live without like hashes and sets).

> My current idea is to have a simple preprocessor to either,

> (a) if (DEBUG == 1)

> convert all return's to return_val = ... ; goto onExit ;

> (b) if (DEBUG == 0)

> strip all onEntry and onExit blocks and leave return's as they are.

> so that subroutine would be coded:

> mysub( paras )
> {
>   onEntry:
>   {
>   }  /* onEntry block */

>   subroutine code

>   onExit:
>   {
>   }
> }

> This way I can place checking code (eg asserts and the like) into the
> onEntry and onExit blocks so:

> - I don't have #if's scatterred all over the code, which in my
> experience can introduce bugs
> - have some means of "collecting" returns to a common exit point for
> testing purposes
> - an easy means of removing the debugging code once testing is over

> Obvious any number of refinements are possible, but first things first!

> I'd welcome anyone's comments on this. There may be a better way of
> doing this. I realise that onEntry is a little redundant, but its tidy
> and clear :-)

> Bear in mind I want this to work in C, not C++, so using try, etc., is
> out of the frame.

> Grant
> --


--



Sat, 30 Aug 2003 10:52:07 GMT  
 No subject was specified.
...

Quote:
>My current idea is to have a simple preprocessor to either,

>(a) if (DEBUG == 1)

>convert all return's to return_val = ... ; goto onExit ;

#if (DEBUG == 1)
# define return(x)  do { return_val = x; goto onExit; } while (0)
#else
# define return(x)  return x
#endif

Disadvantage: you have to get used to writing parentheses around
return values. I personally don't like it.

BTW, I suppose that eventually you /will/ want to return some value
from the function. How do you want to do that if you replace /all/
return statements?

Quote:
>(b) if (DEBUG == 0)

>strip all onEntry and onExit blocks and leave return's as they are.

#if (DEBUG == 0)
# define onEntry(x) onEntry: do {x} while(0)
# define onExit(x)  onExit: do {x} while(0)
#else
# define onEntry(x) ((void)0)
# define onExit(x)  ((void)0)
#endif

Use with caution.

Quote:
>so that subroutine would be coded:

>mysub( paras )
>{
>  onEntry:
>  {
>  }  /* onEntry block */

>  subroutine code

>  onExit:
>  {
>  }
>}

It would look more like:

/*return value type*/ mysub( paras )
{
  onEntry( /* <-- normal left parenthesis, not a [curly] bracket */
    /* your funky stuff */
  )        /* <-- normal right parenthesis */

  /* subroutine code */

  onExit(
    /* more funky stuff */
  )

  return whatever;

Quote:
}
>This way I can place checking code (eg asserts and the like) into the
>onEntry and onExit blocks so:

>- I don't have #if's scatterred all over the code, which in my
>experience can introduce bugs
>- have some means of "collecting" returns to a common exit point for
>testing purposes
>- an easy means of removing the debugging code once testing is over

>Obvious any number of refinements are possible, but first things first!

>I'd welcome anyone's comments on this. There may be a better way of
>doing this. I realise that onEntry is a little redundant, but its tidy
>and clear :-)

>Bear in mind I want this to work in C, not C++, so using try, etc., is
>out of the frame.

--
Peter Pichler (Increment my "From:" address if your email bounces.)
--



Sat, 30 Aug 2003 11:07:55 GMT  
 No subject was specified.

Quote:

> I've been starting back into C after a long exodus in other languages
> (notably Perl) and while I'm at it, I'd like to set up some "standard"
> testing scheme for my code (along with a few libraries for data
> structures I can't live without like hashes and sets).

> My current idea is to have a simple preprocessor to either,

> (a) if (DEBUG == 1)

> convert all return's to return_val = ... ; goto onExit ;

> (b) if (DEBUG == 0)

> strip all onEntry and onExit blocks and leave return's as they are.

> so that subroutine would be coded:

> mysub( paras )
> {

    if (DEBUG){

Quote:
>   onEntry:
>   {
>   }  /* onEntry block */

    }

Quote:
>   subroutine code

    if (DEBUG){

Quote:
>   onExit:
>   {
>   }

    }

Quote:
> }

> This way I can place checking code (eg asserts and the like) into the
> onEntry and onExit blocks so:

> - I don't have #if's scatterred all over the code, which in my
> experience can introduce bugs
> - have some means of "collecting" returns to a common exit point for
> testing purposes
> - an easy means of removing the debugging code once testing is over

    Where DEBUG would be #define'd in debug.h.  The code could be
left after debugging and simply compiled away.  Or you could write a
Perl script :).

--Jeff Turner
--



Sat, 30 Aug 2003 11:08:25 GMT  
 No subject was specified.
I was actually trying to get other ideas for debugging schemes, rather than
exactly how to implement this particular one, but having said that its
useful, so lets stick with it... I've added comments below:

Quote:


> ...
> >My current idea is to have a simple preprocessor to either,

> >(a) if (DEBUG == 1)

> >convert all return's to return_val = ... ; goto onExit ;

> #if (DEBUG == 1)
> # define return(x)  do { return_val = x; goto onExit; } while (0)
> #else
> # define return(x)  return x
> #endif

(I presume I remove the space after the #'s ;-)

I was kind-of hoping to avoid using macros actually -- I forgot to say
that. Partly because I hear too many horror stories about macros and the
like.

The main reason was that I'd rather avoid adding a lot of #if's is
potentially they are another source of error in that the debugging and
non-debugging versions could wind up running differently -- not something
anyone wants (even if just at a level of causing the optimiser to have a
different task in front of it. I don't want to explain that right now, but
I'm sure you get the drift).

But having said that it is simpler in macros that I suspected it'd be! --
so perhaps a restricted used of the macros might be OK, we'll see.

Why'd you put a do { ... } while (0) around the block, btw -- can't you
just leave it as a block? Or would a simple block cause some syntax
problems in some circumstances? I always thought a block statement can go
anywhere a simple statement can...

Their were other reasons for considering a separate pre-processor (ie., not
using macros, but writing a small program to filter my C source code),
although they are a bit more vain and not actually related to the debugging
stuff :-) I thought for fun I could try making up a little language of my
own which generated C, but thats another story entirely!

Quote:
> Disadvantage: you have to get used to writing parentheses around
> return values. I personally don't like it.

No big deal, I'm sure I'd get used to it.

Quote:
> BTW, I suppose that eventually you /will/ want to return some value
> from the function. How do you want to do that if you replace /all/
> return statements?

Surely just add to the definitions above -- ??, eg:

#if (DEBUG == 1)
#define return(x)  do { return_val = x; goto onExit; } while (0)
#define exit_fn return return_val
#else
#define return(x)  return x
#endif

and use whatever exit function you defined to return the return value at
the end of onExit "block". (Or alternatively, add it to the end ofthe
definition of onExit somehow.)

If I was to write a small preprocessor, I always always consider returns
within the onExit block to act normally. The reason I choose onExit: { }
with curly braces was that is ought to be legal C as it stands, btw -- so
that it'd be easy for a pre-processor to handle.

Quote:
> >(b) if (DEBUG == 0)

> >strip all onEntry and onExit blocks and leave return's as they are.

> #if (DEBUG == 0)
> # define onEntry(x) onEntry: do {x} while(0)
> # define onExit(x)  onExit: do {x} while(0)
> #else
> # define onEntry(x) ((void)0)
> # define onExit(x)  ((void)0)
> #endif

> Use with caution.

Hmm... would this work with all C compilers?

Quote:
> >so that subroutine would be coded:

> >mysub( paras )
> >{
> >  onEntry:
> >  {
> >  }  /* onEntry block */

> >  subroutine code

> >  onExit:
> >  {
> >  }
> >}

> It would look more like:

> /*return value type*/ mysub( paras )
> {
>   onEntry( /* <-- normal left parenthesis, not a [curly] bracket */
>     /* your funky stuff */
>   )        /* <-- normal right parenthesis */

>   /* subroutine code */

>   onExit(
>     /* more funky stuff */
>   )

>   return whatever;
> }

> >This way I can place checking code (eg asserts and the like) into the
> >onEntry and onExit blocks so:

> >- I don't have #if's scatterred all over the code, which in my
> >experience can introduce bugs
> >- have some means of "collecting" returns to a common exit point for
> >testing purposes
> >- an easy means of removing the debugging code once testing is over

> >Obvious any number of refinements are possible, but first things first!

> >I'd welcome anyone's comments on this. There may be a better way of
> >doing this. I realise that onEntry is a little redundant, but its tidy
> >and clear :-)

> >Bear in mind I want this to work in C, not C++, so using try, etc., is
> >out of the frame.

> --
> Peter Pichler (Increment my "From:" address if your email bounces.)
> --

In principle I supposed I could replace onEntry with a #if (DEBUG) and
leave the onExit: { } as I defined it, then define return to goto onExit:
appropriately... I'd ahve to always leave on return before the onExit block
though. A bit of a mismash, but it ought to work. No need to strip out the
onEntry/Exit blocks in this case; they ought to be removed as dead code by
the compiler.

Grant
--



Mon, 01 Sep 2003 05:23:17 GMT  
 No subject was specified.
This looks a bit cleaner in that I'd avoid the macros to remove the blocks;
fewer things to potentially go wrong and all that. I'd have to deal with
returns in/outside the onExit block differently though, so I'd have to
define a new return function/macro as I mentioned in my reply to Peter.

But I have to admit i hate all those #if's... a weird irrational personal
thing I know, but...

Grant
-------

Quote:


> > I've been starting back into C after a long exodus in other languages
> > (notably Perl) and while I'm at it, I'd like to set up some "standard"
> > testing scheme for my code (along with a few libraries for data
> > structures I can't live without like hashes and sets).

> > My current idea is to have a simple preprocessor to either,

> > (a) if (DEBUG == 1)

> > convert all return's to return_val = ... ; goto onExit ;

> > (b) if (DEBUG == 0)

> > strip all onEntry and onExit blocks and leave return's as they are.

> > so that subroutine would be coded:

> > mysub( paras )
> > {

>     if (DEBUG){

> >   onEntry:
> >   {
> >   }  /* onEntry block */

>     }

> >   subroutine code

>     if (DEBUG){

> >   onExit:
> >   {
> >   }

>     }

> > }

> > This way I can place checking code (eg asserts and the like) into the
> > onEntry and onExit blocks so:

> > - I don't have #if's scatterred all over the code, which in my
> > experience can introduce bugs
> > - have some means of "collecting" returns to a common exit point for
> > testing purposes
> > - an easy means of removing the debugging code once testing is over

>     Where DEBUG would be #define'd in debug.h.  The code could be
> left after debugging and simply compiled away.  Or you could write a
> Perl script :).

> --Jeff Turner
> --


--



Mon, 01 Sep 2003 05:24:11 GMT  
 No subject was specified.

Quote:


>> I've been starting back into C after a long exodus in other languages
>> (notably Perl) and while I'm at it, I'd like to set up some "standard"
>> testing scheme for my code (along with a few libraries for data
>> structures I can't live without like hashes and sets).

>> My current idea is to have a simple preprocessor to either,

>> (a) if (DEBUG == 1)

>> convert all return's to return_val = ... ; goto onExit ;

>> (b) if (DEBUG == 0)

>> strip all onEntry and onExit blocks and leave return's as they are.

>> so that subroutine would be coded:

>> mysub( paras )
>> {
>    if (DEBUG){

No.
The OP wanted to do it at compile time. One possible approach would be

#if DEBUG

Quote:
>>   onEntry:
>>   {
>>   }  /* onEntry block */

#endif
...

But the OP also wanted to get rid of all #ifs and #endifs.

Quote:
>[...] Or you could write a Perl script :).

Or you could cook an omelette. That has about the same relevance to the
OP's question.

--
Peter Pichler (Increment my "From:" address if your email bounces.)
--



Mon, 01 Sep 2003 05:25:19 GMT  
 No subject was specified.

Quote:


...
>(I presume I remove the space after the #'s ;-)

Do if you like :-) They ar eokay according to ANSI, but you are right
that some compilers have problems with them.

Quote:
>The main reason was that I'd rather avoid adding a lot of #if's is
>potentially they are another source of error in that the debugging and
>non-debugging versions could wind up running differently -- not something
>anyone wants (even if just at a level of causing the optimiser to have a
>different task in front of it. I don't want to explain that right now, but
>I'm sure you get the drift).

The very nature of your task is such that the code will behave diferently
in debug and release build.

Quote:
>Why'd you put a do { ... } while (0) around the block, btw -- can't you
>just leave it as a block? Or would a simple block cause some syntax
>problems in some circumstances? I always thought a block statement can go
>anywhere a simple statement can...

This is a comp.lang.c FAQ (http://www.eskimo.com/~scs/C-faq/top.html).
In short, the difference between a simple statement and the block is that
the latter is not terminated by a semicolon, so if you really need multi-
statement macros, try to make them a simple statements if at all possible.
As an illustration, consider

if (foo)
  my_groovy_macro(...);
else
  my_other_groovy_macro(...);

Quote:
>Their were other reasons for considering a separate pre-processor (ie., not
>using macros, but writing a small program to filter my C source code),
>although they are a bit more vain and not actually related to the debugging
>stuff :-) I thought for fun I could try making up a little language of my
>own which generated C, but thats another story entirely!

It seems that I would have to apologise to Jeffrey. However, if you are
so worried about a possibility to introduce extra errors, consider that
in case of using an external program, the code you'll eventually compile
is not the one you wrote, but the one produced by the separate program
(or script, whatever).

Quote:
>> BTW, I suppose that eventually you /will/ want to return some value
>> from the function. How do you want to do that if you replace /all/
>> return statements?

>Surely just add to the definitions above -- ??, eg:

>#if (DEBUG == 1)
>#define return(x)  do { return_val = x; goto onExit; } while (0)
>#define exit_fn return return_val
>#else
>#define return(x)  return x
>#endif

Good idea.

Quote:
>> >(b) if (DEBUG == 0)

>> >strip all onEntry and onExit blocks and leave return's as they are.

>> #if (DEBUG == 0)
>> # define onEntry(x) onEntry: do {x} while(0)
>> # define onExit(x)  onExit: do {x} while(0)
>> #else
>> # define onEntry(x) ((void)0)
>> # define onExit(x)  ((void)0)
>> #endif

>> Use with caution.

>Hmm... would this work with all C compilers?

Hence my "use with caution". But I cannot think of circumstances when
it could possibly not work. It quite certainly works on every compiler
that my company uses, and the range is not just two versions of MSVC :-)

Quote:
>> /*return value type*/ mysub( paras )
>> {
>>   onEntry( /* <-- normal left parenthesis, not a [curly] bracket */
>>     /* your funky stuff */
>>   )        /* <-- normal right parenthesis */

...

The normal parens are there because onEntry is now a macro and everything
inside the parens is a parameter of that macro. Ahhh, it occurred to me
now that you could have a problem with using comma operators in the macro
parameter list, but I think you knew that.

Quote:
>In principle I supposed I could replace onEntry with a #if (DEBUG) and
>leave the onExit: { } as I defined it, then define return to goto onExit:
>appropriately... I'd ahve to always leave on return before the onExit block
>though. A bit of a mismash, but it ought to work. No need to strip out the
>onEntry/Exit blocks in this case; they ought to be removed as dead code by
>the compiler.

By some compilers. Others may leave it in and others yet may (and probably
will) issue a warning along the lines of "code never reached".

Of course, the decision is yours. You have asked the audience, but you
still have 50:50 and you can call a friend :-) [A popular British TV show]

--
Peter Pichler (Increment my "From:" address if your email bounces.)
--



Mon, 01 Sep 2003 22:54:50 GMT  
 No subject was specified.

Quote:



> ...
> >(I presume I remove the space after the #'s ;-)

> Do if you like :-) They ar eokay according to ANSI, but you are right
> that some compilers have problems with them.

All this talk about C's little variants make me worry if its really possible to
write truly portable code sometimes... I'll have to wait and see...

Quote:

> >The main reason was that I'd rather avoid adding a lot of #if's is
> >potentially they are another source of error in that the debugging and
> >non-debugging versions could wind up running differently -- not something
> >anyone wants (even if just at a level of causing the optimiser to have a
> >different task in front of it. I don't want to explain that right now, but
> >I'm sure you get the drift).

> The very nature of your task is such that the code will behave diferently
> in debug and release build.

Hmm, perhaps I ought to explain. What I meant was that I'd like to affect the
core code of the subroutines as little as possible (the bit between the onEntry
and onExit blocks, that is). Optional compilation in principle at least not
only affects the code included or exlcuded but also the optimisation of
neighbouring code that is always present. Imagine two adjacent lines of code,
the first always present the second only sometimes. Optimisation can result in
different code for the resulting machine code of the first statement if the
second statement is present than when the second statement isn't present. But
really this is just getting a little paranoid: it'd like to think that
optimisers aren't *that* buggy! (The point being that you could get paranoid
and try avoid all sources of different code & hence bugs. In particular in this
senario you code without the debugging options could have bugs introduced into
it...)

Quote:

> >Why'd you put a do { ... } while (0) around the block, btw -- can't you
> >just leave it as a block? Or would a simple block cause some syntax
> >problems in some circumstances? I always thought a block statement can go
> >anywhere a simple statement can...

> This is a comp.lang.c FAQ (http://www.eskimo.com/~scs/C-faq/top.html).
> In short, the difference between a simple statement and the block is that
> the latter is not terminated by a semicolon, so if you really need multi-
> statement macros, try to make them a simple statements if at all possible.
> As an illustration, consider

> if (foo)
>   my_groovy_macro(...);
> else
>   my_other_groovy_macro(...);

Quite right -- ought to have seen that for myself. FWIW I always include braces
out of habit (or at least I *try* to do that!) -- better than getting bugs from
missing semicolons...

Quote:

> >Their were other reasons for considering a separate pre-processor (ie., not
> >using macros, but writing a small program to filter my C source code),
> >although they are a bit more vain and not actually related to the debugging
> >stuff :-) I thought for fun I could try making up a little language of my
> >own which generated C, but thats another story entirely!

> It seems that I would have to apologise to Jeffrey. However, if you are
> so worried about a possibility to introduce extra errors, consider that
> in case of using an external program, the code you'll eventually compile
> is not the one you wrote, but the one produced by the separate program
> (or script, whatever).

No -- any comments are useful. I'm coming around to the point of view that if
its simple enough, I probably am better off using the C preprocessor. After all
it is part of its purpose in life... i still like writing preprocessor
though... silly me. One of these I must satisfy this urge to write my own
little programming language (which I'm sure to be the sole user of :-).

- Show quoted text -

Quote:

> >> BTW, I suppose that eventually you /will/ want to return some value
> >> from the function. How do you want to do that if you replace /all/
> >> return statements?

> >Surely just add to the definitions above -- ??, eg:

> >#if (DEBUG == 1)
> >#define return(x)  do { return_val = x; goto onExit; } while (0)
> >#define exit_fn return return_val
> >#else
> >#define return(x)  return x
> >#endif

> Good idea.

> >> >(b) if (DEBUG == 0)

> >> >strip all onEntry and onExit blocks and leave return's as they are.

> >> #if (DEBUG == 0)
> >> # define onEntry(x) onEntry: do {x} while(0)
> >> # define onExit(x)  onExit: do {x} while(0)
> >> #else
> >> # define onEntry(x) ((void)0)
> >> # define onExit(x)  ((void)0)
> >> #endif

> >> Use with caution.

> >Hmm... would this work with all C compilers?

> Hence my "use with caution". But I cannot think of circumstances when
> it could possibly not work. It quite certainly works on every compiler
> that my company uses, and the range is not just two versions of MSVC :-)

It seems assert() is defined a bit like this according to the ISO standard, so
I guess it _ought_ to be OK. (Got myself a copy of Harbison & Steele, 4th Ed.)

Quote:

> >> /*return value type*/ mysub( paras )
> >> {
> >>   onEntry( /* <-- normal left parenthesis, not a [curly] bracket */
> >>     /* your funky stuff */
> >>   )        /* <-- normal right parenthesis */
> ...

> The normal parens are there because onEntry is now a macro and everything
> inside the parens is a parameter of that macro. Ahhh, it occurred to me
> now that you could have a problem with using comma operators in the macro
> parameter list, but I think you knew that.

Originally I only wanted onEntry & onExit (in particular) to be labels; they
aren't supposed to be "called" as such as they are within the same subroutine
as their "callers" (jumps). Its just a fancy goto after all -- so in pratice
this ought not to happen.

Quote:

> >In principle I supposed I could replace onEntry with a #if (DEBUG) and
> >leave the onExit: { } as I defined it, then define return to goto onExit:
> >appropriately... I'd ahve to always leave on return before the onExit block
> >though. A bit of a mismash, but it ought to work. No need to strip out the
> >onEntry/Exit blocks in this case; they ought to be removed as dead code by
> >the compiler.

> By some compilers. Others may leave it in and others yet may (and probably
> will) issue a warning along the lines of "code never reached".

Thats interresting: I always assumed dead code elemination would be one of the
earlier optimisation steps.

Quote:

> Of course, the decision is yours. You have asked the audience, but you
> still have 50:50 and you can call a friend :-) [A popular British TV show]

Funny, I think I saw a bit of one episode of this in NZ -- can't remember the
name of the show. I'd have turned it off -- I'm not a game show fan. The phrase
is oddly familiar at any rate.

Grant
--



Sun, 07 Sep 2003 01:10:48 GMT  
 
 [ 33 post ]  Go to page: [1] [2] [3]

 Relevant Pages 

1. I am having problems setting up that a specified dialog is displayed before any others

2. Subject: Top 10 subjects in comp.lang.c {From: mikey@ontek.com (Mike Lee)}

3. Subject: Top 10 subjects in comp.lang.c {From Mike Lee, via me}

4. I am new to programming and am lost

5. I am trying to convert a C program to UNICODE. I specify

6. Do my homework, I'm lazy [submitted without subject -mod]

7. (no subject)

8. Newbie Question [came in with no subject line -mod]

9. matrix determinant code [submitted with no subject]

10. (no subject)

11. (no subject)

12. <sent to mod without subject>

 

 
Powered by phpBB® Forum Software