Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Funktionsaufruf soll sich "in Luft auflösen"

0 views
Skip to first unread message

Dirk Haun

unread,
Oct 7, 2003, 5:15:17 PM10/7/03
to
Das Problem ist wohl nicht gerade neu, aber irgendwie konnte ich bisher
keine gute (= praktikable) Lösung dafür finden.

Gegeben ist eine printf-artige Debug-Funktion

Trace("bla=%d", bla);

Diese soll sich bei Release-Builds "in Luft auflösen", so dass
ausgelieferte Binaries eben keine Aufrufe dieser Funktion mehr
enthalten. Derzeit ist das wie folgt gelöst: Intern heißt die Funktion
tatsächlich _Trace und wird per #define in Abhängigkeit vom gewünschten
Build umdefiniert:

#if defined(DEBUG)
# define Trace _Trace
#else
# define Trace
#endif

Da so nur der Funktionsname "wegdefiniert" wird, verursachen die
übriggebliebenen Funktionsparameter natürlich Warnings, z.B. mit GCC

| warning: left-hand operand of comma expression has no effect
| warning: statement with no effect

Die korrekte Lösung wäre wohl

# define Trace(...)

was leider einen C99-Compiler (bzw. einen älteren mit entsprechenden
Erweiterungen) erfordert. Davon kann aber bei den diversen
Zielplattformen, die unterstützt werden müssen (die Palette reicht von
Windows bis AS/400), nicht immer ausgegangen werden.

Hat dazu jemand eine kreative Lösung?

Das Umschreiben der Aufrufe ist, angesichts mehrerer 10000 Zeilen
existierenden Codes (auf diverse Projekte verteilt), keine Option (und
nein, ich weiss auch nicht, warum das bisher nicht aufgefallen ist - ich
habe das Problem auch nur geerbt ...).

Bin für Vorschläge dankbar ...

bye, Dirk


--
http://www.haun-online.de/
http://www.haun.info/

Ralf Schneeweiß

unread,
Oct 7, 2003, 5:35:19 PM10/7/03
to
> #if defined(DEBUG)
> # define Trace _Trace
> #else
> # define Trace
> #endif
>
> Da so nur der Funktionsname "wegdefiniert" wird, verursachen die
> übriggebliebenen Funktionsparameter natürlich Warnings, z.B. mit GCC
>
> | warning: left-hand operand of comma expression has no effect
> | warning: statement with no effect
>
> Die korrekte Lösung wäre wohl
>
> # define Trace(...)


Möglicherweise habe ich das Problem nicht ganz verstanden und mein Vorschlag
greift zu kurz. Aber hast Du schon daran gedacht?

#if defined(DEBUG)
# define Trace(x,y) _Trace(x,y)
#else
# define Trace(x,y)
#endif

Da dürfte doch nichts übrigbleiben. Bleibt nur das Problem mit der variablen
Parameteranzahl in Makros. Gibt es dazu nicht einen Standard? Ich meine,
davon
schon gehört zu haben. Allerdings unterstützen es noch nicht alle Compiler.

Ralf

http://www.oop-trainer.de

Florian Kreidler

unread,
Oct 7, 2003, 5:40:30 PM10/7/03
to
Dirk Haun schrieb im Artikel <1g29pus.1ulfghm7avczkN%spam...@haun-online.de>:

> Das Problem ist wohl nicht gerade neu, aber irgendwie konnte ich bisher
> keine gute (= praktikable) Lösung dafür finden.
>
> Gegeben ist eine printf-artige Debug-Funktion
>
> Trace("bla=%d", bla);
>
> Diese soll sich bei Release-Builds "in Luft auflösen", so dass
> ausgelieferte Binaries eben keine Aufrufe dieser Funktion mehr
> enthalten. Derzeit ist das wie folgt gelöst: Intern heißt die Funktion
> tatsächlich _Trace und wird per #define in Abhängigkeit vom gewünschten
> Build umdefiniert:
>
> #if defined(DEBUG)
> # define Trace _Trace
> #else
> # define Trace
> #endif
>
> Da so nur der Funktionsname "wegdefiniert" wird, verursachen die
> übriggebliebenen Funktionsparameter natürlich Warnings, z.B. mit GCC
...

#if defined(DEBUG)
# define Trace _Trace
#else

# define Trace if(0)_Trace
#endif

und dann mit Code-Optimierung compilieren?

Falk Hueffner

unread,
Oct 7, 2003, 5:56:00 PM10/7/03
to
Florian Kreidler <flo_kr...@yahoo.de> writes:

> #if defined(DEBUG)
> # define Trace _Trace
> #else
> # define Trace if(0)_Trace
> #endif
>
> und dann mit Code-Optimierung compilieren?

Viel Spass dann mit Code wie

int f(int x) {
if (x)
Trace("foo");
else
g();
}

--
Falk

Florian Kreidler

unread,
Oct 7, 2003, 6:50:07 PM10/7/03
to
Falk Hueffner schrieb im Artikel <87r81on...@student.uni-tuebingen.de>:

hmm, ist ein Argument.

Davon abgesehen: Wenn man den Aufruf mitsamt der Parameter eliminiert,
verschwinden auch die Seiteneffekte, die bei der Berechnung jener
auftreten könnten. Um ganz auf der sicheren Seite zu sein, müßte man
wohl sowas machen:

void _Tunix(){}


#if defined(DEBUG)
# define Trace _Trace
#else

# define Trace _Tunix
#endif

Den Aufruf kriegt aber nicht jeder Compiler weg. (gcc 3.2 braucht
dafür -O3, wenn ich das hier mal erwähnen darf.) Also ist die beste
Lösung wohl die, die bereits verwendet wird.


Florian Kreidler

unread,
Oct 7, 2003, 6:50:48 PM10/7/03
to
Falk Hueffner schrieb im Artikel <87r81on...@student.uni-tuebingen.de>:

hmm, ist ein Argument.

Davon abgesehen: Wenn man den Aufruf mitsamt der Parameter eliminiert,
verschwinden auch die Seiteneffekte, die bei der Berechnung jener
auftreten könnten. Um ganz auf der sicheren Seite zu sein, müßte man
wohl sowas machen:

static void _Tunix(){}


#if defined(DEBUG)
# define Trace _Trace
#else

Florian Kreidler

unread,
Oct 7, 2003, 6:53:58 PM10/7/03
to
Falk Hueffner schrieb im Artikel <87r81on...@student.uni-tuebingen.de>:

hmm, ist ein Argument.

Davon abgesehen: Wenn man den Aufruf mitsamt der Parameter eliminiert,
verschwinden auch die Seiteneffekte, die bei der Berechnung jener
auftreten könnten. Um ganz auf der sicheren Seite zu sein, müßte man
wohl sowas machen:

static inline void _Tunix(){}


#if defined(DEBUG)
# define Trace _Trace
#else

# define Trace _Tunix
#endif


Florian Kreidler

unread,
Oct 7, 2003, 6:54:29 PM10/7/03
to
Falk Hueffner schrieb im Artikel <87r81on...@student.uni-tuebingen.de>:

hmm, ist ein Argument.

Davon abgesehen: Wenn man den Aufruf mitsamt der Parameter eliminiert,
verschwinden auch die Seiteneffekte, die bei der Berechnung jener
auftreten könnten. Um ganz auf der sicheren Seite zu sein, müßte man
wohl sowas machen:

static inline void _Tunix(){}


#if defined(DEBUG)
# define Trace _Trace
#else

# define Trace _Tunix
#endif

und auf den Optimizer hoffen

Andreas Burmester

unread,
Oct 7, 2003, 11:44:56 PM10/7/03
to
spam...@haun-online.de (Dirk Haun) writes:

>Gegeben ist eine printf-artige Debug-Funktion

> Trace("bla=%d", bla);

>Diese soll sich bei Release-Builds "in Luft auflösen", so dass
>ausgelieferte Binaries eben keine Aufrufe dieser Funktion mehr
>enthalten. Derzeit ist das wie folgt gelöst: Intern heißt die Funktion
>tatsächlich _Trace und wird per #define in Abhängigkeit vom gewünschten
>Build umdefiniert:

> #if defined(DEBUG)
> # define Trace _Trace
> #else
> # define Trace
> #endif

>Da so nur der Funktionsname "wegdefiniert" wird, verursachen die
>übriggebliebenen Funktionsparameter natürlich Warnings, z.B. mit GCC

>| warning: left-hand operand of comma expression has no effect
>| warning: statement with no effect

>Die korrekte Lösung wäre wohl

> # define Trace(...)

>was leider einen C99-Compiler (bzw. einen älteren mit entsprechenden
>Erweiterungen) erfordert. Davon kann aber bei den diversen
>Zielplattformen, die unterstützt werden müssen (die Palette reicht von
>Windows bis AS/400), nicht immer ausgegangen werden.

>Hat dazu jemand eine kreative Lösung [ohne Umschreiben der Aufrufe]?

Gleich 2.

#1: Definiere Trace unkonditional nach _Trace um und umklammere den
gesamten Code von _Trace() mit

#ifdef DEBUG
...
#endif.

Oder fuege an fruehest moeglicher Stelle

#ifndef DEBUG
return;
#endif

dazu. Hat den Nachteil, dass ueberfluessigerweise die Argumente immer
noch bewertet werden (erwuenschte Nebeneffekte mal ausgeschlossen) und
ein Funktionsruf stattfindet.

#2 und mein Favorit: Bemuehe m4(1) und ein schlichtes

define(Trace,ifdef(DEBUG,_Trace($*)))

Vorteil: Die Trace()-Rufe sind komplett, weil textuell weg. Nachteile:
Aus dem CPP-Macro DEBUG muss ein m4(1)-Macro werden (oder ein
aehnliches ersteres spiegeln); zusaetzliche Uebersetzungsphase
benoetigt.

b.

Wolfgang Zogalla

unread,
Oct 8, 2003, 2:47:08 AM10/8/03
to
Dirk Haun wrote:
>
> Gegeben ist eine printf-artige Debug-Funktion
>
> Trace("bla=%d", bla);
>
> Diese soll sich bei Release-Builds "in Luft auflösen", ...

> Die korrekte Lösung wäre wohl
>
> # define Trace(...)
>
> was leider einen C99-Compiler (bzw. einen älteren mit entsprechenden

> Erweiterungen) erfordert. Davon kann aber ...
> nicht immer ausgegangen werden.

Wenn Makros nur eine feste Parameteranzahl unterstuetzen, muss man ihnen
halt eine feste Anzahl von Parametern geben. Tatsaechlich ist in deinem
Fall der einzige Parameter, den du hast, die Parameterliste der Funktion
"Trace". Dein Trace-Aufruf muss dazu nur leicht veraendert werden:

TRACE(("bla=%d", bla));

Dazu die Definition des Makros TRACE:

#if defined(DEBUG)
# define TRACE(x) Trace x
#else
# define TRACE(x)
#endif

Wolfgang

Michael Schikora

unread,
Oct 8, 2003, 4:46:27 AM10/8/03
to
Falk Hueffner wrote:
> Florian Kreidler <flo_kr...@yahoo.de> writes:
>
>> #if defined(DEBUG)
>> # define Trace _Trace
>> #else
>> # define Trace if(0)_Trace

# define Trace if(1);else _Trace

>> #endif
>>
>> und dann mit Code-Optimierung compilieren?
>
> Viel Spass dann mit Code wie
>
> int f(int x) {
> if (x)
> Trace("foo");
> else
> g();
> }

IMHO nicht unüblich.

--
MfG Samples: http://www.codeproject.com
Schiko [MVP] Samples: http://codeguru.earthweb.com
FAQ: http://www.mpdvc.de
Privat: http://www.schikos.de/MFC.html
Für Fragen per E-Mail bitte Kreditkartennummer mit angeben :-)

Dirk Clemens

unread,
Oct 8, 2003, 6:21:21 AM10/8/03
to
Dirk Haun wrote:
> Das Problem ist wohl nicht gerade neu, aber irgendwie konnte ich bisher
> keine gute (= praktikable) Lösung dafür finden.
>
> Gegeben ist eine printf-artige Debug-Funktion
>
> Trace("bla=%d", bla);
>
> Diese soll sich bei Release-Builds "in Luft auflösen", so dass
> ausgelieferte Binaries eben keine Aufrufe dieser Funktion mehr
> enthalten. Derzeit ist das wie folgt gelöst: Intern heißt die Funktion
> tatsächlich _Trace und wird per #define in Abhängigkeit vom gewünschten
> Build umdefiniert:
>
> #if defined(DEBUG)
> # define Trace _Trace
> #else
> # define Trace
> #endif
>


Ich verwende:

void _Trace ( ccp format, ... );

#if defined(DEBUG) || defined(FORCE_TRACE)
#define dcTRACE(parm) _Trace parm
#define dcTRACEIF(cond,parm) if (cond) _Trace parm
#else
#define dcTRACE(parm)
#define dcTRACEIF(cond,parm)
#endif

Die Aufrufe benötigen dann aber zwei Klammern:
dcTRACE(("abc %d def %s",num,text));
dcTRACEIF(condition,("abc %d def %s",num,text));

Das ganze funktioniert dann auch in IF, FOR, WHILE, ...

if (a) dcTRACE((...));
else dcTRACE((...));

for (i=0;...) dcTRACE((...));

Lemmi

--
mailto: d...@18xx.de
homepage: http://www.18xx.de

Dirk Haun

unread,
Oct 12, 2003, 5:07:44 PM10/12/03
to
Dirk Haun <spam...@haun-online.de> wrote:

[Problem: printf-artige Funktion soll per #define so definiert werden,
dass sie sich für Release-Builds warnings- und rückstandsfrei auflöst]

Erst einmal Danke für die kreativen Ideen (und sorry für die späte
Antwort). Ich fasse mal zusammen:

Persönlich gefällt mir die Lösung von Wolfgang Zogalla am besten:

TRACE(("bla=%d", bla));

Zumal ich mich (jetzt ...) erinnere, die schon einmal in einem früheren
Projekt verwendet zu haben. Leider lässt sie sich für den hier
beschriebenen Fall nicht anwenden, da, wie gesagt, schon ein paar 10.000
Zeilen Code existieren, die mit Trace-Aufrufen mit nur einem
Klammernpaar durchsetzt sind.


Die Idee von Florian Kreidler,

#if defined(DEBUG)
# define Trace _Trace
#else

# define Trace if(0)_Trace
#endif

würde im beschriebenen Kontext sogar funktionieren, da die Coding Styles
vorschreiben, dass if immer mit geschweiften Klammern zu verwenden ist,
auch wenn nur eine Zeile folgt. Stellt sich natürlich die Frage, ob man
das Risiko eingehen will, dass die geschweiften Klammern doch irgendwo
einmal vergessen wurden und (nach Murphy) prompt für Ärger sorgen (und
das im Release Build, also dem, was zum Kunden rausgeht ...).


Bliebe also die Idee von Andreas Burmester, ein m4-Makro zu definieren.
m4 kenne ich bisher nur vom Hörensagen - da muss ich mich also erst
einlesen. Klingt aber nicht uninteressant und ein zusätzliches Tool in
den Buildprozess einzubinden, dürfte auch nicht das Problem sein
(vorausgesetzt, er lässt sich auf alle Zielplattformen portieren, wovon
ich jetzt einfach mal ausgehe).


Nochmal schänen Dank an alle.

Falk Hueffner

unread,
Oct 12, 2003, 5:12:25 PM10/12/03
to
spam...@haun-online.de (Dirk Haun) writes:

> [Problem: printf-artige Funktion soll per #define so definiert werden,
> dass sie sich für Release-Builds warnings- und rückstandsfrei auflöst]
>

> Persönlich gefällt mir die Lösung von Wolfgang Zogalla am besten:
>
> TRACE(("bla=%d", bla));

> [...]


>
> Bliebe also die Idee von Andreas Burmester, ein m4-Makro zu definieren.

Wenn du schon m4 einsetzt, kannst du auch gleich alle TRACE(x) durch
TRACE((x)) ersetzen lassen, dann brauchst du's nicht in den
Buildprozess einbinden.

--
Falk

Erich Fruehstueck

unread,
Oct 12, 2003, 11:25:25 PM10/12/03
to
spam...@haun-online.de (Dirk Haun) wrote:
> Persönlich gefällt mir die Lösung von Wolfgang Zogalla am besten:
>
> TRACE(("bla=%d", bla));
>
> Zumal ich mich (jetzt ...) erinnere, die schon einmal in einem früheren
> Projekt verwendet zu haben. Leider lässt sie sich für den hier
> beschriebenen Fall nicht anwenden, da, wie gesagt, schon ein paar 10.000
> Zeilen Code existieren, die mit Trace-Aufrufen mit nur einem
> Klammernpaar durchsetzt sind.

<OT>
Ich habe für solche Aufgaben ein Shellskript, mit dem ich
rekursiv in eimem Verzeichnisbaum alle Dateien mit dem
Streameditor überarbeitet.

rsed -name '*.c' . -e 's/TRACE\((.*)\)/TRACE(\1)/'

rsed ist Teil von EFEU, siehe Signatur.
<OT>

Grüße
Erich
--
New Version of EFEU released, More fun with Tk support.
Get the open source from http://efeu.cybertec.at now.

Andreas Burmester

unread,
Oct 13, 2003, 12:33:45 AM10/13/03
to
>Dirk Haun <spam...@haun-online.de> wrote:

>[Problem: printf-artige Funktion soll per #define so definiert werden,
>dass sie sich für Release-Builds warnings- und rückstandsfrei auflöst]

>Bliebe also die Idee von Andreas Burmester, ein m4-Makro zu definieren.

Der hatte Dir 2 1/2 Vorschlaege unterbreitet; fuer der ersten 1 1/2
reichte der CPP.

>m4 kenne ich bisher nur vom Hörensagen - da muss ich mich also erst
>einlesen. Klingt aber nicht uninteressant und ein zusätzliches Tool in
>den Buildprozess einzubinden, dürfte auch nicht das Problem sein
>(vorausgesetzt, er lässt sich auf alle Zielplattformen portieren, wovon
>ich jetzt einfach mal ausgehe).

Also, *den* m4(1) gibt es nicht, sondern unterschiedliche Implementa-
tionen. Ich habe vor Jahrenden den sogenannten "PD-m4" von Ozan Yigit
mal mit Turbo-C nach MSDOS gebracht. Ging ohne Probleme. Quellen sind
in jeder FreeBSD-Distribution in /usr/src/usr.bin/m4 zu finden.

Fuer solch', 'tschuldigung, Pippifax reicht der voellig aus. Wenn's
allerdings an's Eingemachte geht und auf Feinheiten ankommt, hat er
eine ganze Reihe von Macken, Fehlern, Unzulaeng- und Unvertraeglich-
keiten mit anderen m4(1)s.

Ob GNUs m4 portabel ist, weiss ich nicht.

Mein Leib- und Magen-m4 ist der, den Richard O'Keefe vor einiger Zeit
aus dem Ur-PD-m4 gemacht hatte. Von dessen Mankos ist nichts mehr zu
finden und er hat ihn an vielen Stellen sinnvoll erweitert. War auch
einiges Hin und Her, bis wir ihn so weit hatten, dass alles Garstiges,
was im Laufe der Jahre entstanden ist, genau so, wie z.B. von SysV-m4
geschluckt wurde... Sollte auch fuer Windows und Macs uebersetzbar
sein.

Wenn er Dich interessiert, schick' mir 'ne Mail.

b.

Bodo Thiesen

unread,
Oct 13, 2003, 6:18:56 PM10/13/03
to
spam...@haun-online.de (Dirk Haun) wrote:

>Dirk Haun <spam...@haun-online.de> wrote:
>
>[Problem: printf-artige Funktion soll per #define so definiert werden,
>dass sie sich für Release-Builds warnings- und rückstandsfrei auflöst]
>

>Persönlich gefällt mir die Lösung von Wolfgang Zogalla am besten:
>
> TRACE(("bla=%d", bla));

#ifndef NDEBUG
int inline TRACE(const char * fmt,...) {
// printf-Code hier
}
#else
inf inline TRACE(const char * fmt,...) { }
#endif

HTH

Gruß, Bodo
--
MS Outlook Express?->[DE: http://piology.org/ILOVEYOU-Signature-FAQ.html]

@@@@@ GEGEN TCG aka. TCPA: @@@@@ [DE: http://www.againsttcpa.com]
Probleme mit Spam? [EN: http://www.spamhaus.org/globalremove.html]

Dirk Clemens

unread,
Oct 15, 2003, 3:55:16 AM10/15/03
to
Bodo Thiesen wrote:

> spam...@haun-online.de (Dirk Haun) wrote:
>
>
>
> #ifndef NDEBUG
> int inline TRACE(const char * fmt,...) {
> // printf-Code hier
> }
> #else
> inf inline TRACE(const char * fmt,...) { }
> #endif

Das führt aber zu ineffizienten Code, Beispiel:
TRACE("x=%g sin(x)=%g\n",x,sin(x));
wird im Release Mode zu
sin(x);
optimiert.

Ich selbst favorisiere/verwende die Lösung:
int Trace( const char format, ... );
#if defined(DEBUG)
#define TRACE(x) Trace x
#define TRACEIF(c,x) if (c) Trace x
#else
#define TRACE(x)
#define TRACEIF(c,x)
#endif
#define noTRACE(x)
#define noTRACEIF(c,x)

a) Variablen, die nur im Debug-Modus existieren, können ,getract' werden und führen im Release-Mode nicht zu einem
'undefined error'.

b) Das TRACEIF eignet sich an den Stellen, wo nur in bestimmten Situationen eine Ausgabe erfolgen soll.

c) Ein (insbesondere mehrzeiliges) TRACE kann durch Voranstellen der beiden Buchstaben 'no' deaktivier werden.
Das ist halt einfache/bequemer als /* ... */

Falk Hueffner

unread,
Oct 15, 2003, 4:10:54 AM10/15/03
to
Dirk Clemens <d...@18xx.de> writes:

> Ich selbst favorisiere/verwende die Lösung:
> int Trace( const char format, ... );
> #if defined(DEBUG)
> #define TRACE(x) Trace x
> #define TRACEIF(c,x) if (c) Trace x
>

> b) Das TRACEIF eignet sich an den Stellen, wo nur in bestimmten
> Situationen eine Ausgabe erfolgen soll.

Den Sinn sehe ich nicht ganz ein (warum nicht gleich if(c)
TRACE... schreiben?), und es ergibt sich wieder das alte
Makro-Problem:

if (x)
TRACE_IF(x, (y));
else
f();

--
Falk

Dirk Clemens

unread,
Oct 15, 2003, 7:05:18 AM10/15/03
to

Ich kann z.B. schreiben: TRACEIF(sin(x)==cos(y),("..."))
In deinem Beispiel muß jetzt die Berechnung sin(x) und cos(y) auch im release-Modus durchgeführt werden,
in meinem nicht.

>
> if (x)
> TRACE_IF(x, (y));
> else
> f();
>

Da sehe ich nicht als Problem, da ich obiges if-Konstrukt für Trace-Ausgaben unsinnig halte:
Trace-Ausgaben sollten sich mit Ausnahme der Ausgabe neutral zum Programm-Fluß halten.
Daher würde ich obiges immer wie folgt schreiben:
TRACEIF(x,(y));
if (!x) f();

Bodo Thiesen

unread,
Oct 15, 2003, 2:56:18 PM10/15/03
to
Dirk Clemens <d...@18xx.de> wrote:

>Bodo Thiesen wrote:
>
>> #ifndef NDEBUG
>> int inline TRACE(const char * fmt,...) {
>> // printf-Code hier
>> }
>> #else
>> inf inline TRACE(const char * fmt,...) { }
>> #endif
>
> Das führt aber zu ineffizienten Code, Beispiel:
> TRACE("x=%g sin(x)=%g\n",x,sin(x));
> wird im Release Mode zu
> sin(x);
> optimiert.

Den Preis bin ich gerne bereit zu zahlen, um Heisenbugs zu vermeiden.

Andreas Burmester

unread,
Oct 17, 2003, 11:47:27 AM10/17/03
to
"Erich Fruehstueck" <e...@synthesis.co.at> writes:
>spam...@haun-online.de (Dirk Haun) wrote:

>> Persönlich gefällt mir die Lösung von Wolfgang Zogalla am besten:
>>
>> TRACE(("bla=%d", bla));
>>
>> Zumal ich mich (jetzt ...) erinnere, die schon einmal in einem früheren
>> Projekt verwendet zu haben. Leider lässt sie sich für den hier
>> beschriebenen Fall nicht anwenden, da, wie gesagt, schon ein paar 10.000
>> Zeilen Code existieren, die mit Trace-Aufrufen mit nur einem
>> Klammernpaar durchsetzt sind.

><OT>
>Ich habe für solche Aufgaben ein Shellskript, mit dem ich
>rekursiv in eimem Verzeichnisbaum alle Dateien mit dem
>Streameditor überarbeitet.

>rsed -name '*.c' . -e 's/TRACE\((.*)\)/TRACE(\1)/'

>rsed ist Teil von EFEU, siehe Signatur.

Erstmal: Was soll daran OT sein? Ich meine, ausser der Eigenwerbung?
Zumal dieses `rsed' eh nur ein 2-Zeiler mit 'nem `find', `sed' und
einem Dateiumbenenen sein kann...

Davon ab, ist der Vorschlag gefaehrlich und untauglich.

"Gefaehrlich", weil man nach einem ersten Blick meinen koennte, dass er
funktioniert, und - schlimmer - dass er vielleicht sogar oft funktio-
niert. Bis er irgendwo in den Tiefen der Subdirectories, und erst mal
unerkannt Ungewolltes produziert...

"Untauglich", weil man mit REs grundsaetzlich keine C-Phrasen erkennen
kann. Die lassen sich nur auf Typ 3-Sprachen anwenden, waehrend C
bekannlich eine Typ 2-, oder kontextfreie Sprache ist (na ja, auch
nicht ganz und wirklich). Wo doch gerade geklammerte Texte gerne als
Beispiel fuer nicht-regulaere Sprachen genommen werden. Da sind
Stolpersteine, wie Char- und Strings-Literals, und Kommentare noch
nicht einmal einbezogen.

Als waere das nicht Einwand genug, kann man mit Deinem Vorschlag -
wegen `sed's Zeilenorientierung - auch dadurch auf die Nase fallen,
dass gar keine Ersetzung vorgenommen wird: Lasse sich ein `TRACE(...)'
doch mal ueber mehr, als 1 Zeile hinziehen.

b.

Erich Fruehstueck

unread,
Oct 17, 2003, 3:40:28 PM10/17/03
to
Andreas Burmester <a.bur...@hamburg.de> wrote:

> "Erich Fruehstueck" <e...@synthesis.co.at> writes:
>>spam...@haun-online.de (Dirk Haun) wrote:
>
>>> Persönlich gefällt mir die Lösung von Wolfgang Zogalla am besten:
>>>
>>> TRACE(("bla=%d", bla));
>>>
>>> Zumal ich mich (jetzt ...) erinnere, die schon einmal in einem früheren
>>> Projekt verwendet zu haben. Leider lässt sie sich für den hier
>>> beschriebenen Fall nicht anwenden, da, wie gesagt, schon ein paar 10.000
>>> Zeilen Code existieren, die mit Trace-Aufrufen mit nur einem
>>> Klammernpaar durchsetzt sind.
>
>><OT>
>>Ich habe für solche Aufgaben ein Shellskript, mit dem ich
>>rekursiv in eimem Verzeichnisbaum alle Dateien mit dem
>>Streameditor überarbeitet.
>
>>rsed -name '*.c' . -e 's/TRACE\((.*)\)/TRACE(\1)/'
>
>>rsed ist Teil von EFEU, siehe Signatur.
>
> Erstmal: Was soll daran OT sein? Ich meine, ausser der Eigenwerbung?
> Zumal dieses `rsed' eh nur ein 2-Zeiler mit 'nem `find', `sed' und
> einem Dateiumbenenen sein kann...

OT weil shell, Posix und nicht C.

> Davon ab, ist der Vorschlag gefaehrlich und untauglich.
>
> "Gefaehrlich", weil man nach einem ersten Blick meinen koennte, dass er
> funktioniert, und - schlimmer - dass er vielleicht sogar oft funktio-
> niert. Bis er irgendwo in den Tiefen der Subdirectories, und erst mal
> unerkannt Ungewolltes produziert...

Gefährlich gebe ich dir recht, aber dafür gibt es auch einen
Testmodus: Anzeige der Änderungen, ohne sie durchzuführen.



> "Untauglich", weil man mit REs grundsaetzlich keine C-Phrasen erkennen
> kann. Die lassen sich nur auf Typ 3-Sprachen anwenden, waehrend C
> bekannlich eine Typ 2-, oder kontextfreie Sprache ist (na ja, auch
> nicht ganz und wirklich). Wo doch gerade geklammerte Texte gerne als
> Beispiel fuer nicht-regulaere Sprachen genommen werden. Da sind
> Stolpersteine, wie Char- und Strings-Literals, und Kommentare noch
> nicht einmal einbezogen.

Beschränkt tauglich, nicht untauglich.

> Als waere das nicht Einwand genug, kann man mit Deinem Vorschlag -
> wegen `sed's Zeilenorientierung - auch dadurch auf die Nase fallen,
> dass gar keine Ersetzung vorgenommen wird: Lasse sich ein `TRACE(...)'
> doch mal ueber mehr, als 1 Zeile hinziehen.

Das kontrolliere ich mit einem grep -r nach.

Bodo Thiesen

unread,
Oct 21, 2003, 2:07:36 PM10/21/03
to
"Erich Fruehstueck" <e...@synthesis.co.at> wrote:

> Andreas Burmester <a.bur...@hamburg.de> wrote:
>> "Erich Fruehstueck" <e...@synthesis.co.at> writes:
>>> spam...@haun-online.de (Dirk Haun) wrote:
>>

>>>> TRACE(("bla=%d", bla));


>>>>
>>>> Leider lässt sie sich für den hier
>>>> beschriebenen Fall nicht anwenden, da, wie gesagt, schon ein paar 10.000
>>>> Zeilen Code existieren, die mit Trace-Aufrufen mit nur einem
>>>> Klammernpaar durchsetzt sind.
>>

>>> [Shellskript]


>>> rsed -name '*.c' . -e 's/TRACE\((.*)\)/TRACE(\1)/'
>>

>> [Vorschlag gefaehrlich und untauglich].


>
> Gefährlich gebe ich dir recht, aber dafür gibt es auch einen
> Testmodus: Anzeige der Änderungen, ohne sie durchzuführen.

Ehm, es ging un 10 Tausend Änderungen. Glaubst Du wirklich, daß Du wirklich
jeden Eingelfall anschaust? Oder wirst Du nicht vielleicht auch nach der
500ten Änderungen nur noch ein paar Stichproben machen? Dann lieber von
Hand ändern (auch wenn es länger dauert), und dabei dann bis zum Schluß
wenigstens halbwegs konzentriert bleiben (natürlich leidet die Konzentration
bei sowas auch, aber immerhin macht man da selber etwas).

Erich Fruehstueck

unread,
Oct 22, 2003, 12:02:35 AM10/22/03
to
Bodo Thiesen <bot...@gmx.de> wrote:

> "Erich Fruehstueck" <e...@synthesis.co.at> wrote:
>
>> Andreas Burmester <a.bur...@hamburg.de> wrote:
>>> "Erich Fruehstueck" <e...@synthesis.co.at> writes:
>>>> spam...@haun-online.de (Dirk Haun) wrote:
>>>
>>>>> TRACE(("bla=%d", bla));
>>>>>
>>>>> Leider lässt sie sich für den hier
>>>>> beschriebenen Fall nicht anwenden, da, wie gesagt, schon ein paar 10.000
>>>>> Zeilen Code existieren, die mit Trace-Aufrufen mit nur einem
>>>>> Klammernpaar durchsetzt sind.
>>>
>>>> [Shellskript]
>>>> rsed -name '*.c' . -e 's/TRACE\((.*)\)/TRACE(\1)/'
>>>
>>> [Vorschlag gefaehrlich und untauglich].
>>
>> Gefährlich gebe ich dir recht, aber dafür gibt es auch einen
>> Testmodus: Anzeige der Änderungen, ohne sie durchzuführen.
>
> Ehm, es ging un 10 Tausend Änderungen. Glaubst Du wirklich, daß Du wirklich
> jeden Eingelfall anschaust? Oder wirst Du nicht vielleicht auch nach der
> 500ten Änderungen nur noch ein paar Stichproben machen? Dann lieber von
> Hand ändern (auch wenn es länger dauert), und dabei dann bis zum Schluß
> wenigstens halbwegs konzentriert bleiben (natürlich leidet die Konzentration
> bei sowas auch, aber immerhin macht man da selber etwas).

Bei einer großen Änderung werde ich zunächst einige Analysen machen. Dazu
genügt es, alle Zeilen mit TRACE in eine Datei zu schreiben. Die Problemfälle
sind Zeilen mit mehr als einer öffnenden Klammer, ohne schließender Klammer
(TRACE-Aufruf erstrekt sich über mehrer Zeilen).

Gibt es keine Problemfälle, ist alles paletti.

Gibt es nur wenige Problemfälle und kann ich sie leicht isolieren
(Ersetzungsdefinition eventuell auf 's/TRACE\(([^(]*)\)/TRACE(\1)/' ändern),
werde ich zunächst die einfachen Fälle abarbeiten und die Problemfälle händisch
korrigieren. Zur Arbeitserleichterung empfiehlt es sich, den Makronamen
bei der Ersetzung zu ändern. Nachträglich wird der Makroname wieder
vereinheitlicht. Ein Name, der nicht Teil eines anderen Namens ist, läßt sich
problemlos mit rsed ändern.

Gibt es zuviele Problemfälle, nehme ich das rsed-Skript als Vorlage und
ersetze den sed-Aufruf durch einen auf das Problem zugeschnittenen Filter
(eventuell auch ein kleines C-Hilfsprogramm).

PS: Ich arbeite mit Revisionskontrolle (cvs). Da habe ich ein Sicherheitsnetz,
falls ich mich bei einer Großänderung vertue.

Andreas Burmester

unread,
Oct 24, 2003, 12:05:38 PM10/24/03
to
"Erich Fruehstueck" <e...@synthesis.co.at> writes:
>Andreas Burmester <a.bur...@hamburg.de> wrote:
>> "Erich Fruehstueck" <e...@synthesis.co.at> writes:

[ spam...@haun-online.de (Dirk Haun) will aus einer printf()-aehn-
lichen Funktion ein C89- und Vargs-taugliches Macro basteln ...
Lösung von Wolfgang Zogalla ...

TRACE(("bla=%d", bla));
]

>>><OT>

>>>rsed -name '*.c' . -e 's/TRACE\((.*)\)/TRACE(\1)/'
>>
>>>rsed ist Teil von EFEU, siehe Signatur.
>>
>> Erstmal: Was soll daran OT sein? Ich meine, ausser der Eigenwerbung?
>> Zumal dieses `rsed' eh nur ein 2-Zeiler mit 'nem `find', `sed' und
>> einem Dateiumbenenen sein kann...

>OT weil shell, Posix und nicht C.

Thema war und ist astreiner C-Code im Sinn von dclc, und wie man ihn
mit einer Intention manipuliert. Naturgemaess benutzt man dafuer, und
redet dann auch hier ueber irgendwelche Werkzeuge, wie Editoren und
anderes. Das ist nicht OT, so lange nicht die Werkzeuge selbst das
Thema werden.

Im Uebrigen ist Dein `rsed' weder "shell", noch "Posix", sondern war
nur eine Leimrute, mit der Du Traffic auf Deine Site locken wolltest.
Wenn meine Vermutung, dass das eh nur ein paar Zeilen rund um ein
find(1) und sed(1) sind, dann waer's vielleicht "shell und Posix"...

>> Davon ab, ist der Vorschlag gefaehrlich und untauglich.
>>
>> "Gefaehrlich", weil man nach einem ersten Blick meinen koennte, dass er
>> funktioniert, und - schlimmer - dass er vielleicht sogar oft funktio-
>> niert. Bis er irgendwo in den Tiefen der Subdirectories, und erst mal
>> unerkannt Ungewolltes produziert...

>Gefährlich gebe ich dir recht, aber dafür gibt es auch einen
>Testmodus: Anzeige der Änderungen, ohne sie durchzuführen.

Du wusstest also schon, dass Dein Vorschlag nicht funktioniert.

>> "Untauglich", weil man mit REs grundsaetzlich keine C-Phrasen erkennen
>> kann. Die lassen sich nur auf Typ 3-Sprachen anwenden, waehrend C
>> bekannlich eine Typ 2-, oder kontextfreie Sprache ist (na ja, auch
>> nicht ganz und wirklich). Wo doch gerade geklammerte Texte gerne als
>> Beispiel fuer nicht-regulaere Sprachen genommen werden. Da sind
>> Stolpersteine, wie Char- und Strings-Literals, und Kommentare noch
>> nicht einmal einbezogen.

>Beschränkt tauglich, nicht untauglich.

Ach was, und ich frage mich, ob Du den Text 'drueber gelesen und
verstanden hast, und warum Du ihn zitierst. Da steht doch ganz
eindeutig, dass Dein Vorschlag grundsaetzlich nicht funktionieren
*kann*. Er ist also nicht nur "untauglich", sondern schlicht Murks.

Wenn man's nicht besser kann oder aus Zeitgruenden nicht machen will,
sind Dein "Testmodus" und Protokollieren und Ueberpruefen und
haendische Nacharbeit, wie Du's im anderen Artikel beschreibst, ja
vielleicht noch im stillen Kaemmerchen tragbar, nichts aber zum Posten,
also oeffentlich machen.

Ich habe mir ja auch verkniffen, z.B. ein m4(1)-Makro, wie

define(TRACE,``TRACE'(($*))')

als Heilung zu propagieren, obwohl's in vielerlei Beziehung deutlich
besser, als Deine RE, samt sed(1) funktioniert (denn dazu im Gegensatz
findet's sicher Klammerpaerchen und kommt mit Zeilenvorschueben klar).
Bis ein Char- oder Stringliteral mit einer Klammer in den Argumenten
auftaucht. Das "schraenkt" vielleicht die Benutzung ein, versagt aber
nicht prinzipiell und konzeptuell, wie REs.

>> Als waere das nicht Einwand genug, kann man mit Deinem Vorschlag -
>> wegen `sed's Zeilenorientierung - auch dadurch auf die Nase fallen,
>> dass gar keine Ersetzung vorgenommen wird: Lasse sich ein `TRACE(...)'
>> doch mal ueber mehr, als 1 Zeile hinziehen.

>Das kontrolliere ich mit einem grep -r nach.

Eine zu einem Klammerpaar gehoerende schliessende laesst sich nicht mit
Gemurkse, wie "letzte in der Zeile", "naechste", "3. folgende" Klammer
oder aehnlich finden. Man weiss schon vorher, dass man mit solchen
Methoden auf die Nase faellt; man laesst sie sein, anstatt hinterher zu
gucken, ob sie auch noch blutet.

b.

0 new messages