Using __LINE__ as a string

P

Paul Shipley

Hi,

Does anyone know a way of converting the __LINE__ macro to a string at
compile time? The reason I ask it because I want to put some debug
information in to tell me if memory is not being allocated. For
example, this function will return the status of my system:

static char* get_status (void)
{
char* str_ptr;
str_ptr = mem_alloc( SIZE_OF_TEXT );

if( NULL == str_ptr )
{
str_ptr = "Out of memory in " __FILE__ " at " __LINE__ "\n";
}
else
{
str_ptr = /* blah blah blah... */
}
return( str_ptr);
}

Of course this code won't work, because __LINE__ is an integer, not a
string. Also, I can't resort to something like printf( "%u \n",
__LINE__ ) because in this case the output might not (and probably
won't) be going to stdout. Also, sprintf can't be used because there
is no memory available to sprintf to.

Any suggestions on how to convert __LINE__ to a string at compile time
will be most appreciated.

Thanks,
Paul.
 
J

Joona I Palaste

Paul Shipley said:
Does anyone know a way of converting the __LINE__ macro to a string at
compile time? The reason I ask it because I want to put some debug
information in to tell me if memory is not being allocated. For
example, this function will return the status of my system:
static char* get_status (void)
{
char* str_ptr;
str_ptr = mem_alloc( SIZE_OF_TEXT );
if( NULL == str_ptr )
{
str_ptr = "Out of memory in " __FILE__ " at " __LINE__ "\n";

sprintf(str_ptr, "Out of memory in %s at %d\n", __FILE__, __LINE__);
 
H

Hallvard B Furuseth

Paul said:
Hi,

Does anyone know a way of converting the __LINE__ macro to a string at
compile time? (...)

#define NOMEM() NOMEM__1(__LINE__)
#define NOMEM__1(li) NOMEM__2(li)
#define NOMEM__2(li) "Out of memory in " __FILE__ " at " #li "\n"

'#li' converts the _unexpanded_ argument to a string. That's why
three macros are needed: This
#define NOMEM__1(li) "Out of memory in " __FILE__ " at " #li "\n"
would produce "Out of memory in " "foo.c" " at " "__LINE__" "\n"
static char* get_status (void)
{
char* str_ptr;
str_ptr = mem_alloc( SIZE_OF_TEXT );

if( NULL == str_ptr )
{
str_ptr = "Out of memory in " __FILE__ " at " __LINE__ "\n";

str_ptr = NOMEM()
}
else
{
str_ptr = /* blah blah blah... */
}
return( str_ptr);
}

However, this program has a bug. How will the caller know whether
or not to free the returned memory? It can return either memory
from mem_alloc() or a static string.
 
H

Hallvard B Furuseth

Joona said:
sprintf(str_ptr, "Out of memory in %s at %d\n", __FILE__, __LINE__);

Not a good idea when str_ptr == NULL.
Besides, we don't know if SIZE_OF_TEXT is big enough.
 
M

Mathew Hendry

Any suggestions on how to convert __LINE__ to a string at compile time
will be most appreciated.

D:\source\clc>cat 031021_1.c
#include <stdio.h>

#define STRX(x) #x
#define STR(x) STRX(x)

int main(void)
{
const char *line = STR(__LINE__);
printf("line == %s\n", line);
return 0;
}

D:\source\clc>031021_1
line == 8

You must go through two macros to force expansion of __LINE__, otherwise

line == __LINE__

would be printed. :)

-- Mat.
 
J

Joona I Palaste

Not a good idea when str_ptr == NULL.
Besides, we don't know if SIZE_OF_TEXT is big enough.

Whoops. Misread == as !=. Thanks for the correction. Well, if we assume
that SIZE_OF_TEXT is absolute bloody big, then we could malloc() a
smaller amount here and sprintf() into it.
After all, there has to be enough memory to hold the "Out of memory"
message somewhere. If not, we're screwed even with the original
solution.
 
D

Dan Pop

In said:
Any suggestions on how to convert __LINE__ to a string at compile time
will be most appreciated.

Ever considered reading the FAQ *before* posting?

Dan
 
D

Dan Pop

In said:
Whoops. Misread == as !=. Thanks for the correction. Well, if we assume
that SIZE_OF_TEXT is absolute bloody big, then we could malloc() a
smaller amount here and sprintf() into it.
After all, there has to be enough memory to hold the "Out of memory"
message somewhere. If not, we're screwed even with the original
solution.

If not, one of two things will happen:

1. The program will fail to translate.

2. The program will fail to load.

In either case, the program cannot be executed. That's the big advantage
of static memory allocation: you don't spend hours and hours of execution
time only to be told that the program cannot allocate some memory it
needs in order to continue to execute.

Dan
 
T

Tristan Miller

Greetings.

sprintf(str_ptr, "Out of memory in %s at %d\n", __FILE__, __LINE__);

Complicated. You will need to calculate a base-10 logarithm and one or more
strlen()s to make sure that the str_ptr has enough memory allocated.
Unless you really need the string in dynamic memory, it's better to use the
preprocessor to generate a constant string on the fly.

Regards,
Tristan
 
R

rihad

str_ptr = NOMEM()


However, this program has a bug. How will the caller know whether
or not to free the returned memory? It can return either memory
from mem_alloc() or a static string.

I would only guess that it's the blah blah blah part that takes care of that :)
I saw this trick used while perusing the Apache httpd sourcecode: NULL on
success, some message on error.
 
H

Hallvard B Furuseth

rihad said:
I would only guess that it's the blah blah blah part that takes care
of that :)

I don't see how it could. I didn't look at that part of the code,
though. But that's _another_ bug: str_ptr is allocated at first, then
it is assigned again without freeing the allocated memory. The blah
blah blah code should fill in the already allocated memory, it shouldn't
set str_ptr to something else.
I saw this trick used while perusing the Apache httpd sourcecode: NULL
on success, some message on error.

That's fine. But there is no NULL to tell from any non-NULL in the OP's
code.
 
D

Dan Pop

In said:
Exactly which FAQ answers this question?

Are you merely reading impaired or a patent idiot?

11.17: I'm trying to use the ANSI "stringizing" preprocessing operator
`#' to insert the value of a symbolic constant into a message,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
but it keeps stringizing the macro's name rather than its value.

Dan
 
P

Paul Shipley

If not, one of two things will happen:

1. The program will fail to translate.

2. The program will fail to load.

In either case, the program cannot be executed. That's the big advantage
of static memory allocation: you don't spend hours and hours of execution
time only to be told that the program cannot allocate some memory it
needs in order to continue to execute.

Dan

Thanks to all for your help.

A bit about the target system: this code will eventually be running on
an embedded system where ROM and RAM are clearly defined. RAM is
limited - I've got 70K to play with. There isn't an operating system,
so we wrap the memory access functions behind mem_alloc and mem_free.
It is the responsibility of the calling function to free the memory
using mem_free. Mem_free knows that if the pointer is pointing into
ROM (i.e. is pointing at the "Out of memory message") then it doesn't
have to do anything.

I did get a solution:

#define STR(x) #x
#define XSTR(x) STR(x)
buf = "Out of memory in " __FILE__ ":" XSTR(__LINE__) "\n";

And yes, it was in the FAQ, but rest assured my chagrined head is now
perspicuously hanging in shame!!!

Thanks,
Paul.
 
P

Paul Shipley

Mathew Hendry said:
D:\source\clc>cat 031021_1.c
#include <stdio.h>

#define STRX(x) #x
#define STR(x) STRX(x)

int main(void)
{
const char *line = STR(__LINE__);
printf("line == %s\n", line);
return 0;
}

D:\source\clc>031021_1
line == 8

You must go through two macros to force expansion of __LINE__, otherwise

line == __LINE__

would be printed. :)

-- Mat.

Ah - perfect! Just what I needed. Thanks, Mathew.

Paul.
 

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
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top