Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

howto: MACRO doesnt work 3

Status
Not open for further replies.

AMosmann

Programmer
May 27, 2003
82
DE
Try to write a macro ZTRACE, that I would use instead of TRACE
This Macro should, depending on TRACELEVEL and TRACEFILE of a paragraph, write the Information into a file. The file should be cloded after each writing.
Background is, that in my Debug-Process I got to write some data, so that 200 lines of a TRACE-Window are not enough.
When parts of code are debugged I want to set TRACELEVEL to zero, so that only important things are written into the file. The neg. TRACELEVELs are reserved for New Lines, with time and line.

#define ZTRACE(LEVEL,STRING) #ifndef TRACELEVEL #define TRACELEVEL 0#endif#ifndef TRACEFILE #define TRACEFILE STANDARDTRACEFILE #define ZTRACEKILLMACROTRACEFILE#endif#if LEVEL < 0 #define TRACEFULL XTraceInt1=-LEVEL#else XTraceInt1=LEVEL #ifdef TRACEFULL #undef TRACEFULL #endif#endif#ifdef TRACELEVEL #if TRACELEVEL>=XTraceInt1 XTraceStreamOnlyInMacro.open(TRACEFILE,ios::eek:ut | ios::app ); #ifdef TRACEFULL
XTraceStringOnlyInMacro.Format(&quot;\n%s\t%s\t%5i\t&quot;, __TIME__,__FILE__,__LINE__); #endif XTraceStringOnlyInMacro+=STRING; XTraceStreamOnlyInMacro.close(); #endif#endif#ifdef ZTRACEKILLMACROTRACEFILE #undef ZTRACEKILLMACROTRACEFILE #undef TRACEFILE#endif#ifdef TRACEFULL #undef TRACEFULL
Doesn't compile ...
Where can I find stuff about MACROWriting, the MSDN doesn't really help ...

#endif

Greetings Andreas
 
>Doesn't compile ...

1) Try to be more specific
2) #endif\ <---- skip the
>MSDN doesn't really help ...

To bad because that's what I'd recommend. I've get all my macro questions answered by it anyway.

/Per
Nerdy signatures are as lame as the inconsistent stardates of STTNG.
 
Or more general...

the \ is to expand a macro definition to the next line.

ie
Code:
#define Foo(b) if (b)               {                  Bar();               }

Your
#ifdef TRACELEVEL#if TRACELEVEL>=XTraceInt1etc shouldn't have any trailing \'s, only the #defines that span multiple lines.






/Per
Nerdy signatures are as lame as the inconsistent stardates of STTNG.
 
Thanx for your answer,

You are right, I should be more specific.
At first: All the text is one #define-Macro
The error is:

error C2162
and the help to it is:

expected macro formal parameter

The token following a stringizing operator (#) was not a formal parameter name.

The following is an example of this error:

#define print(a) printf(#b) // error

The line is:
#ifndef TRACELEVEL
Maybe you cant use Compiler directives like #define ... in #define- directives?

But, what else could I do?



Greetings Andreas
 
How about this one :


#ifdef _DEBUG
#define ZTRACE(lvl, str) TraceLog(__FILE__, __LINE__, __TIME__, lvl, str)
#else
#define ZTRACE
#endif

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/* global */
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
int g_tracelevel = 3;
char g_tracefile[128];


/******************************************************************/
/* main */
/******************************************************************/
int main(void)
{
strcpy(g_tracefile, &quot;TRACE_01.log&quot;);

ZTRACE(1, &quot;Here 1&quot;);
printf(&quot;\nWorking (hard ...) &quot;);
ZTRACE(3, &quot;Here 3&quot;);
ZTRACE(-3, &quot;Here -3&quot;);


g_tracelevel = 7;
strcpy(g_tracefile, &quot;TRACE_43.log&quot;);
ZTRACE(7, &quot;Here 43&quot;);

g_tracelevel = 6;
strcpy(g_tracefile, &quot;TRACE_56.log&quot;);
ZTRACE(7, &quot;Here 56&quot;);

return(0);
}

/******************************************************************/
/* TraceLog */
/******************************************************************/
void TraceLog(const char * f,
int l,
const char * t, // This is compilation time !!
int lvl,
const char * pstr)
{
FILE * flog;
bool fFullLog = false;

if(lvl < 0) {
lvl = -lvl;
fFullLog = true;
}

if(g_tracelevel >= lvl) {
flog = fopen(g_tracefile, &quot;a+&quot;);
if(flog) {
if(fFullLog)
fprintf(flog, &quot;\n [%s, %d, %s] %s&quot;, f,l,t, pstr);
else
fprintf(flog, &quot;\n %s&quot;, pstr);
fclose(flog);
}
else {
printf(&quot;\n** Failed to open file %s&quot;, g_tracefile);
}
}
}

/JOlesen
 
Thanks /JOlesen,

nice idea, I like it, but how to give different tracelevels to different functions?, like

#undef TRACEFILE //All lines put to Standard-TRACEFILE
#define TRACELEVEL 1
void f(){
ZTRACE (2,&quot;show this only in Tracelevel 2 or higher);//will not be shown
ZTRACE (1,&quot;show this only in Tracelevel 1 or higher);//will be shown
};

#define TRACEFILE &quot;FN_G.TXT&quot; //All Lines put to &quot;FN_G.TXT&quot;
#define TRACELEVEL 2
void g(){
ZTRACE (2,&quot;show this only in Tracelevel 2 or higher);//will be shown
ZTRACE (1,&quot;show this only in Tracelevel 1 or higher);//will be shown
};

Is it possible to use a #define-statement inside a #define-statement?
[profile]




Greetings Andreas
 
>>Is it possible to use a #define-statement inside a #define-statement?

I don't think it is. Wouldn't it require the preprocessor to parse the input several times ? (You have to twist your mind when working with macros - I don't like it !)
As far as I know, this preprocessing thing is very simple (Almost text substitution only) - and is a 1-phase thing.

I have to agree with you : The documentation is not really impressing. However it may be possible to get info on a 'std' Ansi C Preprocessor .... I don't know,


/JOlesen



 
Could moving the tracelever parameter to the macro name solve the problem?

ie
ZTRACE2 (&quot;show this only in Tracelevel 2 or higher);//will be shown
ZTRACE1 (&quot;show this only in Tracelevel 1 or higher);//will be shown

With a proper TRACELEVEL defined somewhere:

#if TRACELEVEL>1
#define ZTRACE2(str) TraceLog(__FILE__, __LINE__, __TIME__, 2, str)
#else
#define ZTRACE2
#endif

#if TRACELEVEL>0
#define ZTRACE1(str) TraceLog(__FILE__, __LINE__, __TIME__, 1, str)
#else
#define ZTRACE1
#endif


/Per
Nerdy signatures are as lame as the inconsistent stardates of STTNG.
 
Thanx to both of you, I mixed it up.

I wrote a Log-Procedure:
void LogToFile(int Level, CString sMessage, int Tracelevel, CString Time, int Line, CString File)

and a MACRO:
#define ZTRACE(LEVEL,STRING) LogToFile(LEVEL, STRING, TRACELEVEL, __TIME__ , __LINE__ , TRACEFILE)

the only bad is, that TRACELEVEL and TRACEFILE must be defined at the position you use ZTRACE.
So I defined a STANDARDTRACEFILE in the stdafx.h and set TRACEFILE to it, and I set TRACELEVEL there too.
So I only have to pay attantion, not to undef these.

I saw source-files with lots of macros, that you had some problems to understand all. So I can understand your reservations.
But a macro is the only way I know, to write a line-number of a call into a file. And the normal TRACE with its 200 lines or so is to unflexible for my intend.

So many thanks again, hope, my answer can help you a bit.
[sunshine]


Greetings Andreas
 
Yes, tracing with LINE is preferably done with macros, but that doeasn't mean you have to build a big tracing mechanism using macros.

Another approach could be to switch on/off (ie set trace level) at runtime.

Then it'd be a single macro just to invoke the call, the rest would be a &quot;normal&quot; function/method call.

Sure, you'd have to make tests in runtime (if (gTraceLevel>someting) but the performance impact on this is negligible (it's at least been it on those systems I've worked with, some with quite tough real-time performance requirements).


/Per
Nerdy signatures are as lame as the inconsistent stardates of STTNG.
 
Just one comment :

This __TIME__ stuff is the time when the source-file was last editet / compiled - Not time of day. Not really useful.


/JOlesen
 
yet another question:

TRACE (&quot;%i %s&quot;, 1 ,&quot;any String&quot;);
TRACE (&quot;%i %s %s&quot;, 1 ,&quot;any String&quot;, anotherString);

how to write such a macro??
[spin]

(by the way, changed this with __TIME__, thx /JOlesen)




Greetings Andreas
 
Something like this (I don't like ellipses, but anyway...):


void MyTraceFunction(const char* format, ...)
{
va_list args;
va_start(args, format);

char buffer[SOME_MAX_BUFFER_SIZE];
_vsntprintf(buffer, SOME_MAX_BUFFER_SIZE, format, args);

WriteBufferToSomething(buffer);
va_end(args);
}


#define TRACE MyTraceFunction




/Per
Nerdy signatures are as lame as the inconsistent stardates of STTNG.
 
if there is anyone who wants to know how I solved my problem:

in a seperate module I defined a function like
LogToFile(TraceFileName, TraceLevel, ThisLevel, SourceFile, SourceLine, Text);

in stdafx.cpp
CString ZTraceString0815;

in stdafx.h
extern CString ZTraceString0815;

#define STANDARDTRACELEVEL 0
#define STANDARDTRACEFILE &quot;ZTraceLog.txt&quot;
#define TRACELEVEL STANDARDTRACELEVEL
#define TRACEFILE STANDARDTRACEFILE

#define ZTRACE2(LEVEL,FORMAT,S1,S2)ZTraceString0815.Format(FORMAT,S1,S2);ZTRACE(LEVEL,ZTraceString0815)

#define ZTRACE1(LEVEL,FORMAT,S1)ZTraceString0815.Format(FORMAT,S1);ZTRACE(LEVEL,ZTraceString0815)

#define ZTRACE(LEVEL,STRING) LogToFile(TRACEFILE, TRACELEVEL, LEVEL, __FILE__, __LINE__, STRING)


and in any other file using stdafx:

#define TRACELEVEL 2
#define TRACEFILE &quot;WhereEverYouWant.txt&quot;

void AnyFunction(void){
ZTRACE(0,&quot;void AnyFunction(void)&quot;);
ZTRACE2(1,&quot;2 Params %3i %10s&quot;,
127,&quot;a string&quot;);
}

#define TRACELEVEL STANDARDTRACELEVEL
#define TRACEFILE STANDARDTRACEFILE

can be combined with
#ifdef _DEBUG
ZTRACE(...) LogTo....
ZTRACE2(...) ....
#else
ZTRACE
ZTRACE2
#endif

there is no elegance, but its very useful

Thanx to Per and JOlesen
[cheers]


Greetings Andreas
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top