[comp.lang.c] C SYNTAX QUESTION

marcap@concour.CS.Concordia.CA (Marc Pawlowsky) (05/22/89)

I am looking for a public-domain trace utility for C. e.g. say when a
statement is about to execute.  The normal way of doing this of course
is to insert fprintf statements where appropriate.  I also want to know
which sections of code have or have not been entered.

I am constructing my own tool to do this but have run into a problem.
How can I tell where the first executable statement is in a complex
statement.

e.g.

    ....
    void foo(int a)
    {
      declaration list     
      statement list
    }

How do I know where the statement list begins?  In PASCAL it would be
after a BEGIN.  

Is there a quick way of doing this, other than to write the first
pass of a compiler?

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/23/89)

In article <821@clyde.Concordia.CA> marcap@concour.CS.Concordia.CA (Marc Pawlowsky) writes:
>I am looking for a public-domain trace utility for C. e.g. say when a
>statement is about to execute.  ...  I also want to know
>which sections of code have or have not been entered.

If you have access to UNIX System V, check out the "ctrace" utility which
does pretty much what you ask for.  (That reminds me, I've devised a
ctrace output postprocessor shell procedure that I use to instrument code.
I suppose I should clean it up and post it.)

dlovell@dasys1.UUCP (Douglas Lovell) (05/31/89)

>In article <821@clyde.Concordia.CA> marcap@concour.CS.Concordia.CA (Marc Pawlowsky) writes:
>>I am looking for a public-domain trace utility for C. e.g. say when a
>>statement is about to execute.  ...  I also want to know
>>which sections of code have or have not been entered.

I use some code written by Fred Fish called "debug."
Statements are coded directly into the program and selectively compiled.
They look like--

DBUG_ENTER("functionName");

DBUG_PRINT("keyword", ("printf format control string", varargs));

DBUG_RETURN(functionReturnValue); /* or DBUG_VOID_RETURN; */

These are macros which invoke the debug functions.  They do nothing
if DBUG_OFF is defined.

DBUG_ENTER/DBUG_RETURN enable function entry and exit tracing.
DBUG_PRINT only gets printed if "keyword" is in the keyword list.
keywords, printing, tracing, etc. is controled with -# argument in
the argument list when you run the program.

There are other features.  If this is what you're after, say so and I'll
rustle it up.

 

-- 
Douglas Lovell
Big Electric Cat Public UNIX
..!cmcl2!hombre!dasys1!dlovell

gwyn@smoke.BRL.MIL (Doug Gwyn) (06/01/89)

In article <9838@dasys1.UUCP> dlovell@dasys1.UUCP (Douglas Lovell) writes:
>>In article <821@clyde.Concordia.CA> marcap@concour.CS.Concordia.CA (Marc Pawlowsky) writes:
>>>I am looking for a public-domain trace utility for C. e.g. say when a
>>>statement is about to execute.  ...  I also want to know
>>>which sections of code have or have not been entered.

This reminded me that I still hadn't posted the way I use "ctrace" to
get source code listings with statement execution counts in the margin.
The following excerpt from one of our Makefiles should be adaptable to
your particular System V environment; the biggest change for those who
don't have "sam" will be to change the editing commands to work with
"ed", "ex", or some such editor instead.  ("sam" is available from the
UNIX System ToolChest; you don't need the bitmap terminal-dependent
part for this application.)

CFILES	= one.c two.c # etc.
HFILES	= foo.h # etc.
OBJS	= one.o two.o # etc.
PCFILES	= P.one.c P.two.c # etc.
TEST	= test_driver # or some such
TLIBES	= /usr/local/ourlib.a -lm # etc.

PRFLAGS	= -f
PRINT	= pr $(PRFLAGS)

DEFS	= -DDEBUG # or whatever
INCS	= -I. -I/usr/local/include # etc.
LDFLAGS	= -n # etc.
PKGDEFS	= # more -D options
SYSTEM	= -DSYSV # or whatever

CC	= cc

CTFLAGS	= -b -l0 -p'fprintf(&_iob[2],' -P
CTRACE	= ctrace $(CTFLAGS) $(DEFS) $(PKGDEFS) $(SYSTEM) $(INCS)

trace:		$(PCFILES)
	@for c in $(CFILES); \
	do	$(PRINT) -h "$(TEST) coverage of \"$$c\"" P.$$c; \
	done

# CAUTION: The following procedure requires Rob Pike's "sam" text editor.
$(PCFILES):	$(HFILES) $(CFILES) $(OBJS) $(TEST).o	# $(CFILES) is overkill
	@(	c=`echo $@ | sed 's/^P\.//'`; \
		o=`basename $$c .c`.o; \
		$(CTRACE) $$c > T.$$c; \
		$(CC) -c T.$$c; \
		mv $$o B.$$o && mv T.$$o $$o; \
		$(CC) $(LDFLAGS) -o $(TEST) $(TEST).o $(OBJS) $(TLIBES); \
		./$(TEST) $(TEST).out 2> X.$$c; \
		rm -f T.$$o && mv B.$$o $$o; \
		grep '^ *[1-9][0-9]* ' < X.$$c \
		| sed 's/^ *\([1-9][0-9]*\).*/\1/' \
		| sort -n > L.$$c; \
		rm -f X.$$c; \
		( echo ',x/t_ct_\("\\\\n *[1-9][0-9]* /{'; \
		  echo 'x/[1-9][0-9]*/p\n/\\n/p'; \
		  echo '}\nq\n' \
		) | sam -d T.$$c | sort -n -u > A.$$c; \
		( echo f P.$$c; \
		  echo ',x/^/c/	/'; \
		  uniq -c L.$$c \
		  | sed 's;^\( *[1-9][0-9]*\) \([1-9][0-9]*\);\2i/\1/;'; \
		  uniq L.$$c | comm -13 - A.$$c | sed 's;.*;&i/   0/;'; \
		  echo 'w\nq\n' \
		) | sam -d $$c; \
		rm -f [ALT].$$c \
	)

fnf@estinc.UUCP (Fred Fish) (06/07/89)

In article <9838@dasys1.UUCP> dlovell@dasys1.UUCP (Douglas Lovell) writes:
>I use some code written by Fred Fish called "debug."

Actually it's called "dbug", but you're close...  :-)

>There are other features.  If this is what you're after, say so and I'll
>rustle it up.

One new feature which is not in any of the widely distributed versions
is stack accounting.  It can now keep track of your stack usage on a per
function basis, and provide you with information about your dynamic stack
usage.  This helped me cut the stack usage of one of my programs by about
a factor of 4.  Perhaps it's time for another posting to comp.sources.misc?

-Fred
-- 
# Fred Fish, 1835 E. Belmont Drive, Tempe, AZ 85284,  USA
# 1-602-491-0048           asuvax!{nud,mcdphx}!estinc!fnf

kls@ditka.Chicago.COM (Karl Swartz) (02/04/91)

In article <43415@nigel.ee.udel.edu> HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) writes:
>Is this correct, and if so, why?

(all but critical fragments deleted)

>void void_function();

>i ?  void_function() : 0;

>In GNU GAS, file obstack.h, many macros of such type are declared, and
>my c68/c386 compiler [K&R] complains about that..

>i ? void_function() : (void) 0;

>works.

For a strictly K&R compiler the question is irrelevant since there is
no void type in K&R.  If c68/c386 is a "K&R+" compiler, with a few
additions such as void, the rules are whatever the compiler writers
decided made sense to them.

For ANSI C, going by the old draft that I have at hand, the first
version of the code (without the cast to void on the third operand)
is not legal C.  The conditional operator is described in section
3.3.15, with the following constraints:

    The first operand shall have scalar type.

    One of the following shall hold for the second and third operands:

  * both operands have arithmetic type;

  * both operands have the same structure or union type;

  * both operands are pointers to the same type;

  * both operands are pointers to objects that have qualified or
    unqualified versions of the same type;

  * both operands have void type;

  * one operand is a pointer and the other is a null pointer constant;
    or

  * one operand is a pointer to an object or incomplete type and the
    other is a pointer to void.

One operand of type void and the other of type int don't meet these
constraints.

One compiler that I encountered (an older version of VAX-11 C for VMS)
didn't even allow a void *result* from a conditional expression, which
required a bit of hackery along the lines of:

    void void_function();

    (void) i ? (void_function(), 0) : 0;

Blech!

-- 
Karl Swartz		|INet	kls@ditka.chicago.com
1-408/223-1308		|UUCP	{uunet,decwrl}!daver!ditka!kls
			|Snail	1738 Deer Creek Ct., San Jose CA 95148
"It's psychosomatic.  You need a lobotomy.  I'll get a saw." (Calvin)