1 /* layout_simple - a dumb log layout */
3 /* Copyright (c) 2007-2011. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "portable.h" /* execinfo when available */
10 #include "xbt/sysdep.h"
11 #include "xbt/strbuff.h"
12 #include "xbt/log_private.h"
13 #include "gras/virtu.h" /* gras_os_myname (KILLME) */
14 #include "xbt/synchro.h" /* xbt_thread_self_name */
17 extern const char *xbt_log_priority_names[8];
19 static double format_begin_of_time = -1;
21 #define ERRMSG "Unknown %%%c sequence in layout format (%s).\nKnown sequences:\n" \
22 " what: %%m: user message %%c: log category %%p: log priority\n" \
24 " source: %%F: file %%L: line %%M: function %%l: location (%%F:%%L)\n" \
25 " runtime: %%h: hostname %%t: thread %%P: process %%i: PID\n" \
26 " backtrace: %%b: full %%B: short\n" \
27 " when: %%d: date %%r: app. age\n" \
28 " other: %%%%: %% %%n: new line %%e: plain space\n"
30 #define XBT_LOG_BUFF_SIZE (ev->buffer_size)
33 #define check_overflow \
34 if (p - ev->buffer >= XBT_LOG_BUFF_SIZE) { /* buffer overflow */ \
38 #define show_it(data,letter) \
40 if (precision == -1 && length == -1) { \
41 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%" letter, data); \
42 } else if (precision == -1) { \
43 sprintf(tmpfmt,"%%%d" letter,length); \
44 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), tmpfmt, data); \
46 } else if (length == -1) { \
47 p += sprintf(p, "%.*" letter, \
48 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer), precision), \
52 sprintf(tmpfmt,"%%%d.%d" letter,length, \
53 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer), precision));\
54 p += sprintf(p, tmpfmt, data);\
55 length = precision = -1; \
60 #define show_string(data) show_it(data, "s")
61 #define show_int(data) show_it(data, "d")
62 #define show_double(data) show_it(data, "f")
64 static int xbt_log_layout_format_doit(xbt_log_layout_t l,
83 fprintf(stderr, "Layout format (%s) ending with %%\n",
89 case 'n': /* platform-dependant line separator (LOG4J compliant) */
90 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "\n");
93 case 'e': /* plain space (SimGrid extension) */
94 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), " ");
98 case '.': /* precision specifyier */
100 sscanf(q, "%d", &precision);
101 q += (precision>9?2:1);
102 goto handle_modifier;
113 case '9': /* length modifier */
114 sscanf(q, "%d", &length);
116 goto handle_modifier;
118 case 'c': /* category name; LOG4J compliant
119 should accept a precision postfix to show the hierarchy */
120 show_string(ev->cat->name);
122 case 'p': /* priority name; LOG4J compliant */
123 show_string(xbt_log_priority_names[ev->priority]);
126 case 'h': /* host name; SimGrid extension */
127 show_string(gras_os_myname());
129 case 't': /* thread name; LOG4J compliant */
130 show_string(xbt_thread_self_name());
132 case 'P': /* process name; SimGrid extension */
133 show_string(xbt_procname());
135 case 'i': /* process PID name; SimGrid extension */
136 show_int((*xbt_getpid) ());
139 case 'F': /* file name; LOG4J compliant */
140 show_string(ev->fileName);
142 case 'l': /* location; LOG4J compliant */
143 if (precision == -1) {
144 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s:%d",
145 ev->fileName, ev->lineNum);
149 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
150 precision), "%s:%d", ev->fileName,
156 case 'L': /* line number; LOG4J compliant */
157 show_int(ev->lineNum);
159 case 'M': /* method (ie, function) name; LOG4J compliant */
160 show_string(ev->functionName);
162 case 'b': /* backtrace; called %throwable in LOG4J */
163 case 'B': /* short backtrace; called %throwable{short} in LOG4J */
164 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
169 e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
173 xbt_backtrace_current(&e);
175 show_string(e.bt_strings[2] + 8);
177 for (i = 2; i < e.used; i++)
178 if (precision == -1) {
179 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer),
180 "%s\n", e.bt_strings[i] + 8);
183 p += sprintf(p, "%.*s\n",
184 (int) MIN(XBT_LOG_BUFF_SIZE -
185 (p - ev->buffer), precision),
186 e.bt_strings[i] + 8);
195 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer),
196 "(no backtrace on this arch)");
201 case 'd': /* date; LOG4J compliant */
202 show_double(gras_os_time());
204 case 'r': /* application age; LOG4J compliant */
205 show_double(gras_os_time() - format_begin_of_time);
208 case 'm': /* user-provided message; LOG4J compliant */
209 if (precision == -1) {
210 p += vsnprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), msg_fmt,
215 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
216 precision), msg_fmt, ev->ap);
223 fprintf(stderr, ERRMSG, *q, (char *) l->data);
237 static void xbt_log_layout_format_free(xbt_log_layout_t lay)
242 xbt_log_layout_t xbt_log_layout_format_new(char *arg)
244 xbt_log_layout_t res = xbt_new0(s_xbt_log_layout_t, 1);
245 res->do_layout = xbt_log_layout_format_doit;
246 res->free_ = xbt_log_layout_format_free;
247 res->data = xbt_strdup((char *) arg);
249 if (format_begin_of_time < 0)
250 format_begin_of_time = gras_os_time();