Logo AND Algorithmique Numérique Distribuée

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