Logo AND Algorithmique Numérique Distribuée

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