Logo AND Algorithmique Numérique Distribuée

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