Sida 1 av 1

TRACE Makron?

Postat: 2 maj 2010, 10:14:21
av AndersG
En sak som man är bortskämd med från MFC etc är makrot TRACE, typ TRACE("%S:%d","Send", rx_ptr);

Tanken är att TRACE() sedan försvinner då man inte har _DEBUG definierat. Lekte litet med att sända outputten till serieporten:

Kod: Markera allt

/* 
	Trace.h
*/

#ifndef __TRACE_H__
#define __TRACE_H__

#ifdef _DEBUG
#define TRACE Trace
#else
#define TRACE
#endif


#endif // __TRACE_H__

// trace.c

#include <stdio.h>
#include <stdarg.h>
#define TRACEMAXSTRING	64

char szBuffer[TRACEMAXSTRING];
void Trace(const char* format,...)
{
 	va_list args;
 	va_start(args,format);
 	
 	vsprintf(szBuffer, format, args);
 	va_end(args);

	sio_puts(szBuffer);
}
Synpunkter?? (sio_puts() är min egen, men man kan givetvis använda C18's egen i stället, eller motsvarande för USBUSART.

Re: TRACE Makron?

Postat: 2 maj 2010, 10:43:43
av mri
Inga andra synpunkter än att TRACE makrot automatiskt kunde lägga till __FILE__, __FUNCTION__ (om kompilatorn har det) och __LINE__. Ibland är det nyttigt att veta varifrån debug texten kommer ifrån ifall projektet är stort.

Re: TRACE Makron?

Postat: 2 maj 2010, 11:19:41
av AndersG
Jo, men å andra sidan har man ganska ont on plats och vill hålla strängen kort, men....

Kod: Markera allt

// trace.c

#include <stdio.h>
#include <stdarg.h>
#define TRACEMAXSTRING	64

char szBuffer[TRACEMAXSTRING];
void Trace(const char* format,...)
{
	int offset;
 	va_list args;
 	va_start(args,format);
 	
	offset=sprintf(szBuffer, "%S %d ", __FILE__, __LINE__);
 	offset=vsprintf(szBuffer+offset, format, args);
 	va_end(args);

	sio_puts(szBuffer);
}

Re: TRACE Makron?

Postat: 2 maj 2010, 11:59:56
av mri
Inte helt klart utgående från din källkod, men __FILE__ och __LINE__ ger inte meningsfull info om du sätter in dem i trace.c filen. De måste finnas i själva makrot. Och jo, de stjäl plats, men jag brukar ha olika "options" man kan slå på och av för TRACE makrot, beroende på vad man är intresserad av.

Re: TRACE Makron?

Postat: 2 maj 2010, 13:39:03
av AndersG
Naturligtvis! Måste lägga in dem i makror.

Re: TRACE Makron?

Postat: 2 maj 2010, 14:30:37
av Migrus
Jag får varningar i ditt exempel när _DEBUG inte är definierat. Eftersom du bara sätter TRACE till "" så blir argumenten kvar, dvs TRACE("test: %d", 42); ger att kompilatorn ser ("test: %d", 42); men det beror säkert på kompilator och varningsnivå.

Jag brukar använda följande konstruktion som jag kopierat någonstans ifrån:

Kod: Markera allt

#ifdef _DEBUG
#define TRACE(f, ...) \
    do { fprintf(stderr, "%s: " f, __FUNCTION__ , ## __VA_ARGS__ ); } while(0)
#else
#define TRACE(f, ...) \
    do { } while(0)
#endif
Trivialt lägga till FILE, LINE osv vad man nu vill ha.
fprintf(stderr får så klart bytas ut mot något printf-likande du har i din miljö.

"do {} while (0)" ser till att programflödet inte ändras när man slår på och av macrot, om man tex har en if-sats och att saker stämmer med semi-colon.

Konstruktionen "%s: " f utnyttjar att två strängkonstanter intill varandra slås ihop för att bygga formatsträngen.

## __VA_ARGS__ är eventuellt gcc-specifikt och måste vad jag förstår skrivas som bara __VA_ARGS__ för att vara ISO C99 men då kommer macro:t inte att fungera med bara ett argument, dvs TRACE("foo") är inte längre ok.

Re: TRACE Makron?

Postat: 2 maj 2010, 17:42:50
av AndersG
Tack! Funkade busbra. %S är för att MPLAB lägger statiska strängar i ROM och casten av radnumret till (int) är för att slippa problem med integer promotions.

Så här då?

Kod: Markera allt

/* 
	Trace.h
*/

#ifndef __TRACE_H__
#define __TRACE_H__
//
// Just output the message
//
#ifdef _DEBUG
#define TRACE(f, ...) \
    do { Trace( f ,## __VA_ARGS__ ); } while(0)
#else
#define TRACE(f, ...) \
    do { } while(0)
#endif
//
// Output module filename, line and message
//
#ifdef _DEBUG
#define TRACE2(f, ...) \
    do { Trace( "%S %d " f, __FILE__, (int)__LINE__ ,## __VA_ARGS__ ); } while(0)
#else
#define TRACE2(f, ...) \
    do { } while(0)
#endif


#endif // __TRACE_H__

// trace.c

#include <stdio.h>
#include <stdarg.h>
#define TRACEMAXSTRING	64

char szBuffer[TRACEMAXSTRING];
void Trace(const char* format,...)
{
 	va_list args;
 	va_start(args,format);
  	vsprintf(szBuffer,format, args);
 	va_end(args);
	sio_puts(szBuffer);
}


Re: TRACE Makron?

Postat: 2 maj 2010, 18:53:38
av mri
Migrus: "Jag får varningar i ditt exempel när _DEBUG inte är definierat. Eftersom du bara sätter TRACE till "" så blir argumenten kvar, dvs TRACE("test: %d", 42); ger att kompilatorn ser ("test: %d", 42); men det beror säkert på kompilator och varningsnivå."

Kan lösas med:

Kod: Markera allt

#ifdef _DEBUG
#define TRACE Trace
#else
#define TRACE(...)
#endif
men det som du föreslog med "do { } while(0)" var ju faktiskt bättre eftersom programlogiken inte ändar.

AndersG: Att ha olika TRACE och TRACE2 är inte så elegant egentligen. Det jag menade med "options" var något i stil med:

Kod: Markera allt

#ifdef _DEBUG

  #ifdef EXTENDED_TRACE
    #define TRACE(f, ...) do { Trace( "%S %d " f, __FILE__, (int)__LINE__ ,## __VA_ARGS__ ); } while(0)
  #else
    #define TRACE(f, ...) do { Trace( f ,## __VA_ARGS__ ); } while(0)
  #endif

#else

  #define TRACE(...) do { } while(0)

#endif
Dvs, man använder ett enda TRACE() makro i sin kod, men kan enkelt hänga på mera debug info bara genom att ända lite i Trace.h filen och kompilera om.

Edit: stavfel

Re: TRACE Makron?

Postat: 2 maj 2010, 20:14:55
av AndersG
OK. Det är litet elegantare jo.