3 /* layout_simple - a dumb log layout */
5 /* Copyright (c) 2003, 2004 Martin Quinson. All rights reserved. */
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. */
10 #include "portable.h" /* execinfo when available */
11 #include "xbt/sysdep.h"
12 #include "xbt/strbuff.h"
13 #include "xbt/log_private.h"
14 #include "gras/virtu.h" /* gras_os_myname (KILLME) */
15 #include "xbt/synchro.h" /* xbt_thread_self_name */
18 extern const char *xbt_log_priority_names[7];
20 static double begin_of_time = -1;
22 #define append1(fmt,fmt2,elm) \
24 if (precision == -1) { \
25 xbt_strbuff_append(buff, tmp=bprintf(fmt,elm)); \
28 xbt_strbuff_append(buff, tmp=bprintf(fmt2,precision,elm)); \
33 #define append2(fmt,elm,elm2) \
35 xbt_strbuff_append(buff, tmp=bprintf(fmt,elm,elm2)); \
40 static void xbt_log_layout_format_dynamic(xbt_log_layout_t l,
43 xbt_log_appender_t app) {
44 xbt_strbuff_t buff = xbt_strbuff_new();
56 fprintf(stderr,"Layout format (%s) ending with %%\n",(char*)l->data);
59 xbt_strbuff_append(buff,"%");
61 case 'n': /* platform-dependant line separator (LOG4J compliant) */
62 xbt_strbuff_append(buff,"\n");
64 case 'e': /* plain space (SimGrid extension) */
65 xbt_strbuff_append(buff," ");
68 case '.': /* precision specifyier */
70 q += sscanf(q,"%d",&precision);
73 case 'c': /* category name; LOG4J compliant
74 should accept a precision postfix to show the hierarchy */
75 append1("%s","%.*s",ev->cat->name);
77 case 'p': /* priority name; LOG4J compliant */
78 append1("%s","%.*s",xbt_log_priority_names[ev->priority]);
81 case 'h': /* host name; SimGrid extension */
82 append1("%s","%.*s",gras_os_myname());
84 case 't': /* thread name; LOG4J compliant */
85 append1("%s","%.*s",xbt_thread_self_name());
87 case 'P': /* process name; SimGrid extension */
88 append1("%s","%.*s",xbt_procname());
90 case 'i': /* process PID name; SimGrid extension */
91 append1("%d","%.*d",(*xbt_getpid)());
94 case 'F': /* file name; LOG4J compliant */
95 append1("%s","%.*s",ev->fileName);
97 case 'l': /* location; LOG4J compliant */
98 append2("%s:%d",ev->fileName,ev->lineNum);
99 precision = -1; /* Ignored */
101 case 'L': /* line number; LOG4J compliant */
102 append1("%d","%.*d",ev->lineNum);
104 case 'M': /* method (ie, function) name; LOG4J compliant */
105 append1("%s","%.*s",ev->functionName);
107 case 'b': /* backtrace; called %throwable in LOG4J */
108 case 'B': /* short backtrace; called %throwable{short} in LOG4J */
109 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
114 e.used = backtrace((void**)e.bt,XBT_BACKTRACE_SIZE);
118 xbt_backtrace_current(&e);
120 append1("%s","%.*s",e.bt_strings[2]+8);
122 for (i=2; i<e.used; i++)
123 append1("%s\n","%.*s\n",e.bt_strings[i]+8);
129 append1("%s","%.*s","(no backtrace on this arch)");
133 case 'd': /* date; LOG4J compliant */
134 append1("%f","%.*f", gras_os_time());
136 case 'r': /* application age; LOG4J compliant */
137 append1("%f","%.*f", gras_os_time()-begin_of_time);
140 case 'm': /* user-provided message; LOG4J compliant */
141 vasprintf(&tmp2, fmt, ev->ap_copy);
142 append1("%s","%.*s",tmp2);
147 fprintf(stderr,"Unknown %%%c sequence in layout format (%s)\n",
156 xbt_strbuff_append(buff,tmp2);
159 app->do_append(app,buff->data);
160 xbt_strbuff_free(buff);
163 #define check_overflow \
164 if (p-ev->buffer > XBT_LOG_BUFF_SIZE) { /* buffer overflow */ \
165 xbt_log_layout_format_dynamic(l,ev,msg_fmt,app); \
168 static void xbt_log_layout_format_doit(xbt_log_layout_t l,
171 xbt_log_appender_t app) {
176 begin_of_time=gras_os_time();
187 fprintf(stderr,"Layout format (%s) ending with %%\n",(char*)l->data);
192 case 'n': /* platform-dependant line separator (LOG4J compliant) */
193 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"\n");
196 case 'e': /* plain space (SimGrid extension) */
197 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer)," ");
201 case '.': /* precision specifyier */
203 q += sscanf(q,"%d",&precision);
204 goto handle_modifier;
206 case 'c': /* category name; LOG4J compliant
207 should accept a precision postfix to show the hierarchy */
208 if (precision == -1) {
209 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"%s",ev->cat->name);
212 p += sprintf(p,"%.*s",(int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision),ev->cat->name);
217 case 'p': /* priority name; LOG4J compliant */
218 if (precision == -1) {
219 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%s", xbt_log_priority_names[ev->priority] );
222 p += sprintf(p, "%.*s", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), xbt_log_priority_names[ev->priority] );
228 case 'h': /* host name; SimGrid extension */
229 if (precision == -1) {
230 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%s", gras_os_myname());
233 p += sprintf(p, "%.*s", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), gras_os_myname());
238 case 't': /* thread name; LOG4J compliant */
239 if (precision == -1) {
240 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%s", xbt_thread_self_name());
243 p += sprintf(p, "%.*s", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), xbt_thread_self_name());
248 case 'P': /* process name; SimGrid extension */
249 if (precision == -1) {
250 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%s", xbt_procname());
253 p += sprintf(p, "%.*s", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision),xbt_procname());
258 case 'i': /* process PID name; SimGrid extension */
259 if (precision == -1) {
260 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%d", (*xbt_getpid)());
263 p += sprintf(p, "%.*d", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), (*xbt_getpid)());
269 case 'F': /* file name; LOG4J compliant */
270 if (precision == -1) {
271 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"%s",ev->fileName);
274 p += sprintf(p,"%.*s",(int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), ev->fileName);
279 case 'l': /* location; LOG4J compliant */
280 if (precision == -1) {
281 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%s:%d", ev->fileName, ev->lineNum);
284 p += snprintf(p, (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), "%s:%d", ev->fileName, ev->lineNum);
289 case 'L': /* line number; LOG4J compliant */
290 if (precision == -1) {
291 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%d", ev->lineNum);
294 p += sprintf(p, "%.*d", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), ev->lineNum);
299 case 'M': /* method (ie, function) name; LOG4J compliant */
300 if (precision == -1) {
301 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), "%s", ev->functionName);
304 p += sprintf(p, "%.*s", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), ev->functionName);
309 case 'b': /* backtrace; called %throwable in LOG4J */
310 case 'B': /* short backtrace; called %throwable{short} in LOG4J */
311 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
316 e.used = backtrace((void**)e.bt,XBT_BACKTRACE_SIZE);
320 xbt_backtrace_current(&e);
322 if (precision == -1) {
323 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"%s",e.bt_strings[2]+8);
326 p += sprintf(p,"%.*s",(int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), e.bt_strings[2]+8);
331 for (i=2; i<e.used; i++)
332 if (precision == -1) {
333 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"%s\n",e.bt_strings[i]+8);
336 p += sprintf(p,"%.*s\n",(int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision),e.bt_strings[i]+8);
345 p+=snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"(no backtrace on this arch)");
350 case 'd': /* date; LOG4J compliant */
351 if (precision == -1) {
352 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"%f", gras_os_time());
355 p += sprintf(p,"%.*f", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), gras_os_time());
360 case 'r': /* application age; LOG4J compliant */
361 if (precision == -1) {
362 p += snprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer),"%f", gras_os_time()-begin_of_time);
365 p += sprintf(p,"%.*f", (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), gras_os_time()-begin_of_time);
371 case 'm': /* user-provided message; LOG4J compliant */
372 if (precision == -1) {
373 p += vsnprintf(p,XBT_LOG_BUFF_SIZE-(p-ev->buffer), msg_fmt, ev->ap);
376 p += vsnprintf(p, (int)MIN(XBT_LOG_BUFF_SIZE-(p-ev->buffer),precision), msg_fmt, ev->ap);
383 fprintf(stderr,"Unknown %%%c sequence in layout format (%s)\n",
393 app->do_append(app,ev->buffer);
396 static void xbt_log_layout_format_free(xbt_log_layout_t lay) {
399 xbt_log_layout_t xbt_log_layout_format_new(char *arg) {
400 xbt_log_layout_t res = xbt_new0(s_xbt_log_layout_t,1);
401 res->do_layout = xbt_log_layout_format_doit;
402 res->free_ = xbt_log_layout_format_free;
403 res->data = xbt_strdup((char*)arg);