File name macro

L

Leor Zolman

I understand that some compilers define a symbol that can be used
anywhere in the code in order to find out, at run time, the name of the
file where the code corresponding to the current execution instant is
implemented. This prompts two questions:

1) Is this an ANSI C feature, or just a compiler-dependent goody?

Yes, it is an ISO C requirement. Section 6.10.8/1:

_ _FILE_ _ The presumed name of the current source file
(a character string literal)
2) If it is an ANSI C feature, is there anything equivalent for
function names, rather than file names?

Nope.
-leor
 
R

Régis Troadec

Jim Ford said:
I understand that some compilers define a symbol that can be used
anywhere in the code in order to find out, at run time, the name of the
file where the code corresponding to the current execution instant is
implemented. This prompts two questions:
Hi,


1) Is this an ANSI C feature, or just a compiler-dependent goody?

Yes, __FILE__
2) If it is an ANSI C feature, is there anything equivalent for
function names, rather than file names?

Yes, __func__, in C99.

Regis
 
C

Christopher Benson-Manica

Jim Ford said:
2) If it is an ANSI C feature, is there anything equivalent for
function names, rather than file names?

As Leor stated, the answer is no. However, you may find the __LINE__
macro to be useful.
 
J

Jim Ford

I understand that some compilers define a symbol that can be used
anywhere in the code in order to find out, at run time, the name of the
file where the code corresponding to the current execution instant is
implemented. This prompts two questions:

1) Is this an ANSI C feature, or just a compiler-dependent goody?

2) If it is an ANSI C feature, is there anything equivalent for
function names, rather than file names?
 
L

Leor Zolman

Nope.
-leor

Sorry! I guess there is. I'd never heard of it, and the Standard sneakily
hid it in a different section (6.4.2.2) than the others.
-leor
 
L

Leor Zolman

As Leor stated, the answer is no. However, you may find the __LINE__
macro to be useful.

Leor was wrong, wrong, wrong... as I just discovered to my chagrin (for
making me look ignorant) but to my pleasant surprise (because it is there
at all), __func__ is actually a "predefined identifier" rather than a
"predefined macro name"... thus in a different section :-(
-leor
 
C

Christopher Benson-Manica

Leor Zolman said:
Leor was wrong, wrong, wrong... as I just discovered to my chagrin (for
making me look ignorant) but to my pleasant surprise (because it is there
at all), __func__ is actually a "predefined identifier" rather than a
"predefined macro name"... thus in a different section :-(

How spiteful of them! The fact remains, at least, that __LINE__ is a
very nice macro. So is this the identity of this __func__ identifier
implentation-defined? Presumably it needn't always be a macro, or the
standard wouldn't have been so devious regarding it (right?).
 
E

E. Robert Tisdale

Christopher said:
Jim Ford spoke thus:



As Leor stated, the answer is no.
However, you may find the __LINE__ macro to be useful.

> cat main.c
#include <stdio.h>

void function(void) {
fprintf(stdout, "%s\n", __func__);
}

int main(int argc, char* argv[]) {
function();
return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
function
 
L

Leor Zolman

How spiteful of them! The fact remains, at least, that __LINE__ is a
very nice macro. So is this the identity of this __func__ identifier
implentation-defined? Presumably it needn't always be a macro, or the
standard wouldn't have been so devious regarding it (right?).

I don't like attempting to answer questions in this group on topics that I
don't at least /think/ I've got a handle on. Since I discovered the
existence of __func__ only a few short minutes ago, I'll pass on trying to
provide the in-depth analysis at this point...
-leor
 
A

Arthur J. O'Dwyer

How spiteful of them! The fact remains, at least, that __LINE__ is a
very nice macro. So is this the identity of this __func__ identifier
^^^^^^^
"why is," perhaps?
implementation-defined? Presumably it needn't always be a macro, or the
standard wouldn't have been so devious regarding it (right?).

Think about it. The macro-expansions of __FILE__ and __LINE__ don't
require information from the parser to work properly; they just expand
through pure preprocessor magic. __func__, on the other hand, requires
information that only the parser can give: the name of the current
function. Thus, it cannot be expanded by the C preprocessor; it's a
compile-time construct, not a "CPP-time" one. :)

I think N869 explains it really well, actually.

HTH,
-Arthur
 
C

CBFalconer

Leor said:
Yes, it is an ISO C requirement. Section 6.10.8/1:

_ _FILE_ _ The presumed name of the current source file
(a character string literal)

That's __FILE__

Yup, for C99. From N869:

6.4.2.2 Predefined identifiers

Semantics

[#1] The identifier __func__ shall be implicitly declared by
the translator as if, immediately following the opening
brace of each function definition, the declaration

static const char __func__[] = "function-name";

appeared, where function-name is the name of the lexically-
enclosing function.53)
____________________

53)Note that since the name __func__ is reserved for any use
by the implementation (7.1.3), if any other identifier is
explicitly declared using the name __func__, the behavior
is undefined.

[#2] This name is encoded as if the implicit declaration had
been written in the source character set and then translated
into the execution character set as indicated in translation
phase 5.

[#3] EXAMPLE Consider the code fragment:

#include <stdio.h>
void myfunc(void)
{
printf("%s\n", __func__);
/* ... */
}

Each time the function is called, it will print to the
standard output stream:

myfunc

Forward references: function definitions (6.9.1).
 
L

Leor Zolman

That's __FILE__
I just copied and pasted from the Standard PDF. I guess I'll have to adjust
for whatever convention they're using for readability...
Yup, for C99. From N869:

Yah, hadn't all those follow-up posts shown up for you yet at this point?
Thanks,
-leor
 
C

CBFalconer

Leor said:
.... snip ...

Yah, hadn't all those follow-up posts shown up for you yet at
this point?

Nope, I work offline, download a herd, go through it, and
eventually reconnect. My ISP then procedes to redate/time
anything I send to the moment it receives it - reasonable,
considering the number of erroneous clock setting out there.
 
I

Irrwahn Grausewitz

Régis Troadec said:
Jim Ford said:
[...]ome compilers define a symbol that can be used
[...] to find out, at run time, the [...] function names [...]?


Yes, __func__, in C99.


Indeed. Which leads to another question: is there any portable
way to find out during preprocessing, if or if not the underlying
implementation provides for __func__ ?

If e.g. I have a bunch of debugging functions that shall print
__FILE, __LINE__ and __func__ in C99 (or later ;-}), but still
compile and work with reduced functionality in pre-C99, is the
following a reasonable approach?

#if ( __STDC_VERSION__ < 199901L )
#define __func__ "<unknown>"
#endif

Opinions?

Regards
 
R

Régis Troadec

"Irrwahn Grausewitz" <[email protected]> a écrit dans le message de

Hi,
Régis Troadec said:
Jim Ford said:
[...]ome compilers define a symbol that can be used
[...] to find out, at run time, the [...] function names [...]?


Yes, __func__, in C99.


Indeed. Which leads to another question: is there any portable
way to find out during preprocessing, if or if not the underlying
implementation provides for __func__ ?


I would say no. __func__ isn't a macro but a predefined identifier.
It's like a *hidden* local variable defined in any function.
(See 6.4.2.2 of the standard and elsethread for further information )
e.g. :
void myFunc()
{
static const char __func__ = "myFunc"; /* hidden */
/*...*/
}

Therefore, there is no way I think to find out __func__ until the file is
parsed, so no way to find it out during the preprocessing phase.
If e.g. I have a bunch of debugging functions that shall print
__FILE, __LINE__ and __func__ in C99 (or later ;-}), but still
compile and work with reduced functionality in pre-C99, is the
following a reasonable approach?

#if ( __STDC_VERSION__ < 199901L )
#define __func__ "<unknown>"
#endif
Opinions?

That is exactly what I would do if I were in your case.

Regards,

Regis
 
D

Dan Pop

In said:
Sorry! I guess there is. I'd never heard of it, and the Standard sneakily
hid it in a different section (6.4.2.2) than the others.

Of course it's in a different section: it's not (and cannot be) a
preprocessor feature. There is no way to detect a function name during
translation phases 1 to 4, which constitute the preprocessing stage.

The lower case spelling of the identifier is another clue that we're
not dealing with a macro.

But the most annoying thing is that it's not a C89 feature, yet a
conforming C89 implementation can provide it, since the name is in the
implementation name space. And C99 implementations are few and far
between, so portable C code doesn't have much use for __func__.

Dan
 
D

Dan Pop

In said:
Dread; make that something like:

#if ( ( __STDC_VERSION__ +0L ) < 199901L )

What makes you think the second version is any better? If the
implementation doesn't define it, __STDC_VERSION__ is guaranteed to be
evaluated to 0 in this context and this is good enough for your purposes.

To avoid relying on this feature, I prefer the following form of the
test, which is the most readable, IMHO:

#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)

But this is not the most important point. The real problem is that you
define an identifier you have no business to define: __func__. This is
undefined behaviour under ALL the C standards. The right thing is the
equally trivial:

#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define FUNCNAME __func__
#else
#define FUNCNAME "<unknown>"
#endif

and use FUNCNAME in the rest of your code. Now, you're on as solid ground
as you could possibly be (under C89, even the defined(__STDC_VERSION__)
test is technically undefined behaviour, as this identifier could
theoretically mean "crash and burn if this pp_token is detected in
any context").

Dan
 
L

Leor Zolman

Of course it's in a different section: it's not (and cannot be) a
preprocessor feature. There is no way to detect a function name during
translation phases 1 to 4, which constitute the preprocessing stage.

I didn't say I was necessarily using my head when scanning the list of
preprocessor macro names looking for something resembling the word
"function"....
The lower case spelling of the identifier is another clue that we're
not dealing with a macro.

.... a clue I wasn't privy to before I'd ever seen its spelling.
But the most annoying thing is that it's not a C89 feature, yet a
conforming C89 implementation can provide it, since the name is in the
implementation name space. And C99 implementations are few and far
between, so portable C code doesn't have much use for __func__.

If one does happen to have a compiler that supports __func__, and wants to
use it while developing portable code, it shouldn't be too difficult to
wrap it up with the help of the preprocessor in order to selectively
disable it on other platforms. If there isn't a way to detect __func__
support automatically, then in the worst case the compiles would take a
-DFUNC_SUPPORTED (or whatever) as required, e.g.:

/*
* Portable use (or non-use) of __func__ in debug mode
*/

#include <stdio.h>

//#define FUNC_SUPPORTED
//#define NDEBUG

#ifdef FUNC_SUPPORTED
#define FUNC __func__
#else
#define FUNC ""
#endif

#ifdef NDEBUG
#define diagnose(file, line, func) ((void)0)
#else
void diagnose(const char *file, int line, const char *func)
{
printf("FILE: %s, LINE: %d", file, line);
if (*func)
printf(", Func: %s", func);
printf("\n\n");
}
#endif


int main()
{
printf("Hello, world\n");
diagnose(__FILE__, __LINE__, FUNC);

diagnose(__FILE__, __LINE__, FUNC);

diagnose(__FILE__, __LINE__, FUNC);
printf("Goodbye, world\n");
return 0;
}

-leor
 
I

Irrwahn Grausewitz

In <[email protected]> Irrwahn Grausewitz <[email protected]> writes:
[...] The real problem is that you
define an identifier you have no business to define: __func__. This is
undefined behaviour under ALL the C standards.

You're of course correct, shame on me.
The right thing is the
equally trivial:

#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define FUNCNAME __func__
#else
#define FUNCNAME "<unknown>"
#endif

and use FUNCNAME in the rest of your code. Now, you're on as solid ground
as you could possibly be (under C89, even the defined(__STDC_VERSION__)
test is technically undefined behaviour, as this identifier could
theoretically mean "crash and burn if this pp_token is detected in
any context").

Thanks, Dan.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,362
Latest member
ChandaWagn

Latest Threads

Top