Complete.Org: Mailing Lists: Archives: freeciv-dev: May 1999:
Re: [Freeciv-Dev] freelog and LOG_DEBUG
Home

Re: [Freeciv-Dev] freelog and LOG_DEBUG

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: Re: [Freeciv-Dev] freelog and LOG_DEBUG
From: Markus Linnala <maage@xxxxxxxxx>
Date: 20 May 1999 14:11:48 +0300
Reply-to: Markus Linnala <maage@xxxxxxxxx>

David Pfitzner <dwp@xxxxxxxxxxxxxx> writes:

> Or a more sophisticated system where one can turn on or off
> debugs based on __FILE__. Some sort of macro system to avoid
> excessive unnecessary function calls may be appropriate for
> efficiency (like your patch).

How about this:

------------------------------------------------------------------------
1999-05-20  Markus Linnala  <maage@xxxxxxxxx>

        * server/civserver.c (main): added filespecific debugging
        -d 2            - set debug log level to 2 (debug level)
                          print every debug message
        -d 2:file       - print debugging only from file `file'
        -d 2:file:file2
                        - print debugging from files `file' and `file2'
        -d 2:file,100,200
                        - print debugging from file `file' if
                          source code line is >= 100 and <= 200

        * common/log.h: new global variables log_files and log_files_cnt
        (freelog_debug_check_ok): new function, tell if we need to
        print message
        (freelog): wrapper macro around real_freelog
        
        * common/log.(c|h> (freelog): change to real_freelog
------------------------------------------------------------------------

I tested the macrosystem agains gcc optimization levels. With
-O3 gcc optimizes out all 'freelog(LOG_DEBUG, message, ...);'
calls if you don't define DEBUG. -O2 does not do so.

This macro system uses GNUC extension to handle ellipsis at
function argument.

gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)

I think this system is powerful enough (with some general shell
magic) to suit all practical needs. 

gcc -DHAVE_CONFIG_H -I. -I/usr/src/freeciv/freeciv/client/gui-gtk -I../.. 
-I/usr/src/freeciv/freeciv/client/gui-gtk/../include 
-I/usr/src/freeciv/freeciv/common -I/usr/X11R6/include -I/usr/lib/glib/include 
-I/usr/X11R6/include  -DDEBUG  -g -Wall -c 
/usr/src/freeciv/freeciv/client/gui-gtk/clinet.c

Examples:
civserver -d 2
civserver -d 2:civserver.c
civserver -d 2:civserver.c,700,800
civserver -d 2:`find /usr/src/freeciv/freeciv/ai -name \*.c|tr '\012' ':'|sed 
's/:$//'`

From my compilation:
gcc -DHAVE_CONFIG_H -I. -I/usr/src/freeciv/freeciv/client/gui-gtk -I../.. 
-I/usr/src/freeciv/freeciv/client/gui-gtk/../include 
-I/usr/src/freeciv/freeciv/common -I/usr/X11R6/include -I/usr/lib/glib/include 
-I/usr/X11R6/include  -DDEBUG  -g -Wall -c 
/usr/src/freeciv/freeciv/client/gui-gtk/clinet.c

If I want to debug the file you have to give:
civserver -d 2:/usr/src/freeciv/freeciv/client/gui-gtk/clinet.c

-- 
//Markus

--- freeciv-cvs/common/log.c    Tue Apr 27 15:17:52 1999
+++ freeciv-maage/common/log.c  Thu May 20 05:41:51 1999
@@ -63,7 +63,7 @@
 "last message repeated ..." at some later time.
 Calls log_callback if non-null, else prints to stderr.
 **************************************************************************/
-int freelog(int level, char *message, ...)
+int real_freelog(int level, char *message, ...)
 {
   static char bufbuf[2][512];
   char buf[512];
--- freeciv-cvs/common/log.h    Tue Apr 27 15:17:53 1999
+++ freeciv-maage/common/log.h  Thu May 20 14:10:40 1999
@@ -14,6 +14,7 @@
 #define FC__LOG_H
 
 #include "attribute.h"
+#include <stdarg.h>
 
 #define LOG_FATAL  0
 #define LOG_NORMAL 1
@@ -28,7 +29,70 @@
 void log_init(char *filename, int initial_level, log_callback_fn callback);
 void log_set_level(int level);
 
-int freelog(int level, char *message, ...)
+int real_freelog(int level, char *message, ...)
             fc__attribute((format (printf, 2, 3)));
+
+typedef struct _t_log_files t_log_files;
+
+struct _t_log_files {
+    char *file;
+    int min;
+    int max;
+};
+
+int log_files_cnt;
+t_log_files **log_files;
+
+/* Internal function to check if we need to print debugging information */
+static int freelog_debug_check_ok(const char *file, int line, int level)
+{
+    int i, ok = 1;
+    if(level == LOG_DEBUG)
+    {
+       if (log_files_cnt > 0) ok = 0;
+       for (i = 0; i < log_files_cnt; i++)
+       {
+           if(strcmp(file,log_files[i]->file) == 0
+              && (log_files[i]->max == 0
+                  || (log_files[i]->min <= line
+                      && log_files[i]->max >= line)))
+           {
+               ok = 1;
+               break;
+           }
+       }
+    }
+    return (ok);
+}
+
+#ifdef ___GNUC__
+#ifdef DEBUG
+#define freelog(level, args...) do {                           \
+    if (freelog_debug_check_ok(__FILE__, __LINE__, (level)))   \
+       real_freelog((level), ##args);                          \
+} while(0)
+#else
+#define freelog(level, args...) do {           \
+    if ((level) != LOG_DEBUG)                  \
+       real_freelog((level), ##args);          \
+} while(0)
+#endif
+#else /* __GNUC__ */
+
+/* Too bad, seems it is not possible to have macro here, so we
+ * lose some functionality in compilers without GNUC extensions. */
+static void freelog (int level, char *message, ...)
+{
+#ifndef DEBUG
+    if ((level) != LOG_DEBUG)
+#endif
+    {
+       va_list args;
+       va_start (args, message);
+       real_freelog(level, message, args);
+       va_end (args);
+    }
+}
+#endif /* __GNUC__ */
 
 #endif
--- freeciv-cvs/server/civserver.c      Tue Apr 27 15:17:56 1999
+++ freeciv-maage/server/civserver.c    Thu May 20 06:28:52 1999
@@ -81,6 +81,9 @@
 
 extern struct connection connections[];
 
+extern int log_files_cnt;
+extern t_log_files **log_files;
+
 enum server_states server_state;
 
 /* this global is checked deep down the netcode. 
@@ -204,13 +207,72 @@
       }
     }
     else if(!strcmp("-d", argv[i]) || !strcmp("--debug", argv[i])) { 
-      if(++i<argc) 
-       log_level=atoi(argv[i]);
-      else {
-       fprintf(stderr, "Error: no debug log level specified.\n");
-       h=1;
-       break;
-      }
+       if(++i<argc) {
+           /* 
+              Debug argument can be:
+              0-2
+              2:file
+              2:file,min1,max1
+              2:file,min1,max1:file2,min2,max2
+           */
+           char *c, *ar;
+           int cnt;
+           cnt = 0;
+           c = argv[i];
+           while((c = index(c, ':')) != NULL) { c++; cnt++; }
+           if (cnt == 0) {
+               log_level=atoi(argv[i]);
+           } else {
+               log_files_cnt = cnt;
+               log_files = (t_log_files **) malloc(log_files_cnt * 
sizeof(t_log_files *));
+               /* Clean memory */
+               for (cnt = 0; cnt < log_files_cnt; cnt++)
+                   log_files[cnt] = NULL;
+               c = argv[i];
+               if (c[0] == '2' && c[1] == ':') { 
+                   log_level = 2;
+                   ar = strdup(c+2);
+               } else {
+                   fprintf(stderr, "Error: no debug log argument 
specified.\n");
+                   h=1;
+                   break;
+               }
+               cnt = 0;
+               while (ar != NULL) {
+                   char *pc;
+
+                   c = ar;
+                   ar = index(ar, ':');
+                   if (ar != NULL) {
+                       ar[0] = '\0';
+                       ar++;
+                   }
+                   log_files[cnt] = (t_log_files *) 
malloc(sizeof(t_log_files));
+                   log_files[cnt]->file = c;
+                   log_files[cnt]->min = 0;
+                   log_files[cnt]->max = 0;
+
+                   c = index(c, ',');
+                   if (c != NULL) {
+                       c[0] = '\0';
+                       c++;
+                       pc = c;
+                       c = index(c, ',');
+                       if (c != NULL) {
+                           c[0] = '\0';
+                           c++;
+                           log_files[cnt]->min = atoi(pc);
+                           log_files[cnt]->max = atoi(c);
+                       }
+                   }
+                   cnt++;
+               }
+           }
+       } else {
+           fprintf(stderr, "Error: no debug log level specified.\n");
+           h=1;
+           break;
+       }
     }
     else if(!strcmp("-v", argv[i]) || !strcmp("--version", argv[i])) { 
       v=1;
@@ -420,17 +482,17 @@
   
   while(server_state==RUN_GAME_STATE) {
     force_end_of_sniff=0;
-    if(0) freelog(LOG_DEBUG, "Shuffleplayers");
+    freelog(LOG_DEBUG, "Shuffleplayers");
     shuffle_players();
-    if(0) freelog(LOG_DEBUG, "Aistartturn");
+    freelog(LOG_DEBUG, "Aistartturn");
     ai_start_turn();
 
-    if(0) freelog(LOG_DEBUG, "sniffingpackets");
+    freelog(LOG_DEBUG, "sniffingpackets");
     while(sniff_packets()==1);
     
     for(i=0;i<game.nplayers;i++)
       connection_do_buffer(game.players[i].conn);
-    if(0) freelog(LOG_DEBUG, "Autosettlers");
+    freelog(LOG_DEBUG, "Autosettlers");
     auto_settlers(); /* moved this after ai_start_turn for efficiency -- Syela 
*/
     /* moved after sniff_packets for even more efficiency.
        What a guy I am. -- Syela */
@@ -438,20 +500,20 @@
     /* and now, we must manage our remaining units BEFORE the cities that are
        empty get to refresh and defend themselves.  How totally stupid. */
     ai_start_turn(); /* Misleading name for manage_units -- Syela */
-    if(0) freelog(LOG_DEBUG, "Auto-Attack phase");
+    freelog(LOG_DEBUG, "Auto-Attack phase");
     auto_attack();
-    if(0) freelog(LOG_DEBUG, "Endturn");
+    freelog(LOG_DEBUG, "Endturn");
     end_turn();
-    if(0) freelog(LOG_DEBUG, "Gamenextyear");
+    freelog(LOG_DEBUG, "Gamenextyear");
     game_next_year();
     check_spaceship_arrivals();
-    if(0) freelog(LOG_DEBUG, "Sendplayerinfo");
+    freelog(LOG_DEBUG, "Sendplayerinfo");
     send_player_info(0, 0);
-    if(0) freelog(LOG_DEBUG, "Sendgameinfo");
+    freelog(LOG_DEBUG, "Sendgameinfo");
     send_game_info(0);
-    if(0) freelog(LOG_DEBUG, "Sendyeartoclients");
+    freelog(LOG_DEBUG, "Sendyeartoclients");
     send_year_to_clients(game.year);
-    if(0) freelog(LOG_DEBUG, "Sendinfotometaserver");
+    freelog(LOG_DEBUG, "Sendinfotometaserver");
     send_server_info_to_metaserver(0);
     for(i=0;i<game.nplayers;i++)
       connection_do_unbuffer(game.players[i].conn);
@@ -716,7 +778,7 @@
     */
     struct player *pplayer = shuffled[i];
     if (pplayer==NULL) pplayer = &game.players[i];
-    if(0) freelog(LOG_DEBUG, "updating player activities for #%d (%s)",
+    freelog(LOG_DEBUG, "updating player activities for #%d (%s)",
                  i, pplayer->name);
     update_player_activities(pplayer);
          /* ai unit activity has been moved UP -- Syela */
@@ -729,7 +791,7 @@
   update_pollution();
   do_apollo_program();
   make_history_report();
-  if(0) freelog(LOG_DEBUG, "Turn ended.");
+  freelog(LOG_DEBUG, "Turn ended.");
   return 1;
 }
 

[Prev in Thread] Current Thread [Next in Thread]