Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Don't use %t in log format, but %P; revalidate the output after listener introduction
[simgrid.git] / src / xbt / xbt_log_layout_format.c
1 /* $Id$ */
2
3 /* layout_simple - a dumb log layout                                        */
4
5 /* Copyright (c) 2003, 2004 Martin Quinson. All rights reserved.            */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "portable.h" /* execinfo when available */
11 #include "xbt/sysdep.h"
12 #include "xbt/log.h"
13 #include "gras/virtu.h" /* gras_os_myname (KILLME) */
14 #include "xbt/synchro.h" /* xbt_thread_self_name */
15 #include <stdio.h>
16
17 extern const char *xbt_log_priority_names[7];
18
19
20 static char *xbt_log_layout_format_doit(xbt_log_layout_t l,
21                                         xbt_log_event_t ev, 
22                                         const char *msg_fmt) {
23   static char res[2048];
24   static double begin_of_time = -1;
25   char *p,*q;
26   int precision=-1;
27
28   if (begin_of_time<0) 
29     begin_of_time=gras_os_time();
30
31   p = res;
32   q = l->data;
33
34   while (*q != '\0') {
35     if (*q == '%') {
36       q++;
37        handle_modifier:
38       switch (*q) {
39       case '\0':
40         fprintf(stderr,"Layout format (%s) ending with %%\n",(char*)l->data);
41         abort();
42       case '%':
43         *p++ = '%';
44         break;
45       case 'n': /* platform-dependant line separator (LOG4J compliant) */
46         p += sprintf(p,"\n");
47         break;
48       case 'e': /* plain space (SimGrid extension) */
49         p += sprintf(p," ");
50         break;
51          
52       case '.': /* precision specifyier */
53         q++;
54         q += sscanf(q,"%d",&precision);
55         goto handle_modifier;
56
57       case 'c': /* category name; LOG4J compliant
58                    should accept a precision postfix to show the hierarchy */
59         if (precision == -1)
60            p += sprintf(p,"%s",ev->cat->name);
61         else {        
62            p += sprintf(p,"%.*s",precision,ev->cat->name);
63            precision = -1;
64         }        
65         break;
66       case 'p': /* priority name; LOG4J compliant */    
67         if (precision == -1)
68            p += sprintf(p, "%s", xbt_log_priority_names[ev->priority] );
69         else {        
70            p += sprintf(p, "%.*s", precision, xbt_log_priority_names[ev->priority] );
71            precision = -1;
72         }        
73         break;
74
75       case 'h': /* host name; SimGrid extension */
76         if (precision == -1)
77            p += sprintf(p, "%s", gras_os_myname());
78         else {        
79            p += sprintf(p, "%.*s", precision, gras_os_myname());
80            precision = -1;
81         }        
82         break;
83       case 't': /* thread name; LOG4J compliant */
84         if (precision == -1)
85            p += sprintf(p, "%s", xbt_thread_self_name());
86         else {        
87            p += sprintf(p, "%.*s", precision, xbt_thread_self_name());
88            precision = -1;
89         }        
90         break;
91       case 'P': /* process name; SimGrid extension */
92         if (precision == -1)
93            p += sprintf(p, "%s", xbt_procname());
94         else {        
95            p += sprintf(p, "%.*s", precision,xbt_procname());
96            precision = -1;
97         }        
98         break;
99       case 'i': /* process PID name; SimGrid extension */
100         if (precision == -1)
101            p += sprintf(p, "%d", (*xbt_getpid)());
102         else {        
103            p += sprintf(p, "%.*d", precision, (*xbt_getpid)());
104            precision = -1;
105         }        
106         break;
107
108       case 'F': /* file name; LOG4J compliant */
109         if (precision == -1)
110            p += sprintf(p,"%s",ev->fileName);
111         else {        
112            p += sprintf(p,"%.*s",precision, ev->fileName);
113            precision = -1;
114         }        
115         break;
116       case 'l': /* location; LOG4J compliant */
117         if (precision == -1)
118            p += sprintf(p, "%s:%d", ev->fileName, ev->lineNum);
119         else {        
120            p += snprintf(p, precision, "%s:%d", ev->fileName, ev->lineNum);
121            precision = -1;
122         }        
123         break;
124       case 'L': /* line number; LOG4J compliant */
125         if (precision == -1)
126            p += sprintf(p, "%d", ev->lineNum);
127         else {        
128            p += sprintf(p, "%.*d", precision, ev->lineNum);
129            precision = -1;
130         }        
131         break;
132       case 'M': /* method (ie, function) name; LOG4J compliant */
133         if (precision == -1)
134            p += sprintf(p, "%s", ev->functionName);
135         else {        
136            p += sprintf(p, "%.*s", precision, ev->functionName);
137            precision = -1;
138         }        
139         break;
140       case 'b': /* backtrace; called %throwable in LOG4J */
141       case 'B': /* short backtrace; called %throwable{short} in LOG4J */
142 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
143         {
144           xbt_ex_t e;
145           int i;
146           
147           e.used     = backtrace((void**)e.bt,XBT_BACKTRACE_SIZE);
148           e.bt_strings = NULL;
149           e.msg=NULL;
150           e.remote=0;
151           xbt_backtrace_current(&e);
152           if (*q=='B') {
153              if (precision == -1)
154                p += sprintf(p,"%s",e.bt_strings[2]+8);
155              else {           
156                 p += sprintf(p,"%.*s",precision, e.bt_strings[2]+8);
157                 precision = -1;
158              }   
159           } else {
160             for (i=2; i<e.used; i++)
161                if (precision == -1)
162                  p += sprintf(p,"%s\n",e.bt_strings[i]+8);
163              else {           
164                  p += sprintf(p,"%.*s\n",precision,e.bt_strings[i]+8);
165                 precision = -1;
166              }   
167           }
168            
169           xbt_ex_free(e);
170         }
171 #else
172         p+=sprintf(p,"(no backtrace on this arch)");
173 #endif
174         break;
175
176       case 'd': /* date; LOG4J compliant */
177         if (precision == -1)
178            p += sprintf(p,"%f", gras_os_time());
179         else {        
180            p += sprintf(p,"%.*f", precision, gras_os_time());
181            precision = -1;
182         }        
183         break;
184       case 'r': /* application age; LOG4J compliant */
185         if (precision == -1)
186            p += sprintf(p,"%f", gras_os_time()-begin_of_time);
187         else {        
188            p += sprintf(p,"%.*f", precision, gras_os_time()-begin_of_time);
189            precision = -1;
190         }        
191         break;
192         
193       case 'm': /* user-provided message; LOG4J compliant */
194         if (precision == -1)
195            p += vsprintf(p, msg_fmt, ev->ap);
196         else {        
197            p += vsnprintf(p, precision, msg_fmt, ev->ap);
198            precision = -1;
199         }        
200         break;
201
202       default:
203         fprintf(stderr,"Unknown %%%c sequence in layout format (%s)\n",
204                 *q,(char*)l->data);
205         abort();
206       }
207       q++;
208     } else {
209       *(p++) = *(q++);
210     }
211   }
212   *p = '\0';
213   return res;
214 }
215
216 static void xbt_log_layout_format_free(xbt_log_layout_t lay) {
217   free(lay->data);
218 }
219 xbt_log_layout_t xbt_log_layout_format_new(char *arg) {
220   xbt_log_layout_t res = xbt_new0(s_xbt_log_layout_t,1);
221   res->do_layout = xbt_log_layout_format_doit;
222   res->free_     = xbt_log_layout_format_free;
223   res->data = xbt_strdup((char*)arg);
224   return res;
225 }