How about a predefined #FILE, #PATH and #FUNCTION for C?
Joseph S. D. Yao
jsdy at hadron.UUCP
Tue Jan 28 23:36:29 AEST 1986
In article <312 at yale.ARPA> grace at yale.ARPA (Joseph Grace) writes:
> error.h:
> #define TEST printf ("FILE: error has occurred\n");
>...
> output of test (on BSD 4.2 Pyramid):
> FILE: error has occurred
> /* not "test: error has occurred" as I would prefer */
>#FILE, #PATH and #FUNCTION would solve these problems.
First, let's drop the '#', otherwise we'll have to re-define our
concept of "identifier". If you want uniqueness, let's go for
__FILE__ (which, along with __LINE__ does exist in many C
implementations, including 4.2BSD).
Second, for better compatibility, let's define TEST to be:
printf("%s: ...\n", __FILE__);
Indeed, this won't work otherwise.
Now, for other things, you can sometimes use your SCCS and RCS
keywords. Because you mentioned that this is a software project
under ongoing development, I assume you are using SCCS or RCS,
unless this is an undergrad programming project and your teachers
have not showed you SCCS or RCS (and shame on them if so!!!).
I routinely include something like:
#ifndef lint
# ifdef SCCS
static char SCCS_id[] = "%W%";
# else
static char RCS_id[] =
"@(#)$Header:$";
# endif /*SCCS*/
#endif/*lint*/
ifndef lint so that lint won't complain. SCCS is defined or not
in <local.h>. "@(#)" prefix to $Header:$ because RCS doesn't do
it and I want what(1) to recognise the header. Now, the second
word in each of these is the module name. In SCCS, you can have
a separate string containing just "%M%" that is the module name.
In RCS, "$Source:$" will be the full path name (also in $Header:$
instead of module name in older RCS's).
BTW, <local.h> is what we're using to include bsd_4, bsd_4_2,
s5, s5r2, s5r2v2, SCCS, RCS, vax_785, m68020, and whatever other
configuration-dependent defines aren't already in the compiler
(like vax, m68k) or other files like <sys/param.h>.
I routinely want to use the command name (rather than the module
name) in my fprintf(stderr,...)'s. This is especially true when
one command is linked with several names. I do this:
#define DIRC '/'
#ifdef s5
# define rindex strrchr
# define index strchr
#endif/*s5*/
char *myname;
main(argc, argv, envp)
int argc;
char **argv;
char **envp;
{
extern char *rindex();
if (argc > 0) {
myname = rindex(*argv, DIRC);
if (myname == (char *) NULL)
myname = *argv;
else
++myname;
}
...
}
'myname' is available to the whole program.
I have occasionally wanted to know at all times what function I
was in. Here is one way:
#ifdef EBUG
# define FUNBEG(fname) \
char *last_fnname;\
extern char *fnname;\
last_fnname = fnname;\
fnname = "FUNCTION fname()";
# define FUNEND fnname = last_fnname;
# define FUNCHG(fname,newstr) \
fnname = "IN FUNCTION fname(): newstr";
# else
# define FUNBEG(fname)
# define FUNEND
# define FUNCHG(fname,newstr)
#endif/*EBUG*/
Then inside a function:
func(a, b, c)
int a, b, c;
{
<decls>
FUNBEG(func) /* This must be right after decls! */
...
FUNCHG(func, this has just happened)
...
FUNEND /* Before any explicit or implicit return */
}
Now, when you compile this -DEBUG you will always have a string
that reflects where you are (you d i d put this in main(), too,
didn't you?); while if you drop -DEBUG you get more space! Note
that this must be re-written for ANSI C:
fnname = "FUNCTION " fname "()";
fnname = "IN FUNCTION " fname "(): " newstr;
FUNBEG("func") /* This must be right after decls! */
FUNCHG("func", "this has just happened")
[In some ways, this is preferable. The old way, you could get:
#define f(s) printf("%s:" s)
f(cp); -> printf("%cp", cp);]
--
Joe Yao hadron!jsdy at seismo.{CSS.GOV,ARPA,UUCP}
More information about the Comp.lang.c
mailing list