PRINT_HEADER4(args, _("Current"), _("Average"), _("Minimum"), _("Maximum"));
// Entries
- DRAW_AREA_WITH_LABEL(args, "count", NULL, GREEN, _("Entries"));
+ DRAW_AREA_WITH_LABEL(args, "count", NULL, GREEN, 0, _("Entries"));
PRINT_CAMM(args, "count", NULL, LARGE_INTEGER);
// Limit
- DRAW_LINE_WITH_LABEL(args, 1, "max", NULL, LIMIT, _("Limit"), DASHES SKIPSCALE);
+ DRAW_LINE_WITH_LABEL(args, 1, "max", NULL, LIMIT, DASHED|SKIPSCALE, _("Limit"));
PRINT(args, FIELD_CURRENT("max_cur"), NULL, LARGE_INTEGER);
PRINT_NOTHING(args);
PRINT_NOTHING(args);
PRINT_HEADER4(args, _("Current"), _("Average"), _("Minimum"), _("Maximum"));
// Context Switches
- DRAW_AREA_WITH_LABEL(args, "ctxt", NULL, GREEN, _("Context Switches"));
+ DRAW_AREA_WITH_LABEL(args, "ctxt", NULL, GREEN, 0, _("Context Switches"));
PRINT_CAMM(args, "ctxt", NULL, LARGE_INTEGER);
return 0;
return r;
// Draw the line
- DRAW_LINE_WITH_LABEL(args, 1, "freq_cur", object, COLOR_CPU(i), _("CPU Core %ld"));
+ DRAW_LINE_WITH_LABEL(args, 1, "freq_cur", object, COLOR_CPU(i), 0, _("CPU Core %ld"), i);
PRINT_CAMM(args, "freq_cur", object, HZ);
// Draw the minimum
- DRAW_LINE(args, 2, "freq_min", object, MINIMUM);
+ DRAW_LINE(args, 2, "freq_min", object, MINIMUM, 0);
// Draw the maximum
- DRAW_LINE(args, 2, "freq_max", object, MAXIMUM);
+ DRAW_LINE(args, 2, "freq_max", object, MAXIMUM, 0);
}
return 0;
// Include translation
#include "../i18n.h"
-// Include utils
+// Include misc.
+#include "../args.h"
+#include "../strings.h"
#include "../util.h"
-#define SCRIPT(args, def, ...) \
+typedef enum flags {
+ STACKED = (1 << 0),
+ DASHED = (1 << 1),
+ SKIPSCALE = (1 << 2),
+} draw_flags;
+
+// Calls a function (with arguments) and returns on error
+#define CALL(func, ...) \
do { \
- int __r = td_args_push(args, def, ##__VA_ARGS__); \
+ int __r = func(__VA_ARGS__); \
if (__r < 0) \
return __r; \
- } while(0)
+ } while (0)
+
+// Appends a line to the script
+#define SCRIPT(args, def, ...) CALL(td_args_push, args, def, ##__VA_ARGS__)
#define GRAPH_TITLE(args, format, ...) SCRIPT(args, "--title=" format, __VA_ARGS__)
// Labels are 30 characters wide
#define LABEL "%-30s"
+#define LABEL_MAX 32
// A column is exactly 16 characters wide
#define COLUMN "%16s"
#define FIELD "%s%s%s"
#define FIELD_AND_OBJECT(field, object) field, CONSTANT_OR_EMPTY(object, "_"), MAYBE_EMPTY(object)
+static inline int __DRAW(td_args* args, const char* what, const char* field,
+ const char* object, const char* color, const draw_flags flags, const char* format, ...)
+ __attribute__((format(printf, 7, 8)));
+
+static inline int __DRAW(td_args* args, const char* what, const char* field,
+ const char* object, const char* color, const draw_flags flags, const char* format, ...) {
+ char label[LABEL_MAX] = "";
+ const char* skipscale = "";
+ const char* stacked = "";
+ const char* dashed = "";
+ va_list __args;
+ int r;
+
+ // Format the label
+ if (format) {
+ va_start(__args, format);
+ r = td_string_vformat(label, format, __args);
+ va_end(__args);
+
+ // Handle errors
+ if (r < 0)
+ return r;
+ }
+
+ // Select flags
+ if (flags) {
+ if (flags & DASHED)
+ dashed = ":dashes";
+
+ if (flags & STACKED)
+ stacked = ":STACK";
+
+ if (flags & SKIPSCALE)
+ skipscale = ":skipscale";
+ }
+
+ // Include the label if set
+ if (format)
+ return td_args_push(args, "%s:" FIELD "%s:" LABEL "%s%s%s",
+ what, FIELD_AND_OBJECT(field, object), color, label, dashed, stacked, skipscale);
+
+ return td_args_push(args, "%s:" FIELD "%s%s%s%s%s",
+ what, FIELD_AND_OBJECT(field, object), color, (flags) ? "::" : "", dashed, stacked, skipscale);
+}
+
// Draw a LINE, AREA, etc.
-#define DRAW(args, what, field, object, color, ...) \
- SCRIPT(args, what ":" FIELD "%s" __VA_ARGS__, FIELD_AND_OBJECT(field, object), color)
+#define DRAW(args, what, field, object, color, flags) \
+ DRAW_WITH_LABEL(args, what, field, object, color, flags, NULL)
-#define DRAW_WITH_LABEL(args, what, field, object, color, label, ...) \
- SCRIPT(args, what ":" FIELD "%s:" LABEL __VA_ARGS__, FIELD_AND_OBJECT(field, object), color, label)
+#define DRAW_WITH_LABEL(args, what, field, object, color, flags, label, ...) \
+ CALL(__DRAW, args, what, field, object, color, flags, label, ##__VA_ARGS__)
// Draw lines
-#define DRAW_LINE(args, strength, field, object, color, ...) \
- DRAW(args, "LINE" TOSTRING(strength), field, object, color, __VA_ARGS__)
-#define DRAW_LINE_WITH_LABEL(args, strength, field, object, color, label, ...) \
- DRAW_WITH_LABEL(args, "LINE" TOSTRING(strength), field, object, color, label, __VA_ARGS__)
+#define DRAW_LINE(args, strength, field, object, color, flags) \
+ DRAW(args, "LINE" TOSTRING(strength), field, object, color, flags)
+#define DRAW_LINE_WITH_LABEL(args, strength, field, object, color, flags, label, ...) \
+ DRAW_WITH_LABEL(args, "LINE" TOSTRING(strength), field, object, color, flags, label, ##__VA_ARGS__)
// Macros to draw the background of an area
-#define DRAW_AREA_BACKGROUND(args, field, object, color, ...) \
- DRAW(args, "AREA", field, object, COLOR_WITH_ALPHA(color, OPACITY_AREA), __VA_ARGS__)
+#define DRAW_AREA_BACKGROUND(args, field, object, color, flags) \
+ DRAW(args, "AREA", field, object, COLOR_WITH_ALPHA(color, OPACITY_AREA), flags)
// Macros to draw the area's outline
-#define DRAW_AREA_OUTLINE(args, field, object, color) \
- DRAW_LINE(args, 1, field, object, color)
-#define DRAW_AREA_OUTLINE_WITH_LABEL(args, field, object, color, label, ...) \
- DRAW_LINE_WITH_LABEL(args, 1, field, object, color, label, __VA_ARGS__)
+#define DRAW_AREA_OUTLINE(args, field, object, color, flags) \
+ DRAW_LINE(args, 1, field, object, color, flags)
+#define DRAW_AREA_OUTLINE_WITH_LABEL(args, field, object, color, flags, label, ...) \
+ DRAW_LINE_WITH_LABEL(args, 1, field, object, color, flags, label, ##__VA_ARGS__)
-#define DRAW_AREA(args, field, object, color) \
+#define DRAW_AREA(args, field, object, color, flags) \
do { \
- DRAW_AREA_BACKGROUND(args, field, object, color); \
- DRAW_AREA_OUTLINE(args, field, object, color); \
+ DRAW_AREA_BACKGROUND(args, field, object, color, flags); \
+ DRAW_AREA_OUTLINE(args, field, object, color, flags); \
} while(0)
// Areas are being drawn with an outline
-#define DRAW_AREA_WITH_LABEL(args, field, object, color, label, ...) \
+#define DRAW_AREA_WITH_LABEL(args, field, object, color, flags, label, ...) \
do { \
- DRAW_AREA_BACKGROUND(args, field, object, color); \
- DRAW_AREA_OUTLINE_WITH_LABEL(args, field, object, color, label, __VA_ARGS__); \
+ DRAW_AREA_BACKGROUND(args, field, object, color, flags); \
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, field, object, color, flags, label, ##__VA_ARGS__); \
} while(0)
// Horizontal lines
#define DRAW_HRULE_WITH_LABEL(args, value, color, label) \
SCRIPT(args, "HRULE:%lf" color ":" COLUMN, (double)value, label)
-// Modifiers
-#define STACK ":STACK"
-
-// Modifiers for lines
-#define DASHES ":dashes"
-#define SKIPSCALE ":skipscale"
-
// Add something to the legend of the graph
#define PRINT_EMPTY_LINE(args) SCRIPT(args, "COMMENT: \\n")
#define PRINT_HEADER(args, label) SCRIPT(args, "COMMENT:" COLUMN, label)
} while (0)
#define DRAW_BANDWIDTH_INCOMING(args, object, rx_bytes) \
- __DRAW_BANDWIDTH(args, object, rx_bytes, COLOR_RX, _("Incoming Traffic"))
+ __DRAW_BANDWIDTH(args, object, rx_bytes, COLOR_RX, "%s", _("Incoming Traffic"))
#define DRAW_BANDWIDTH_OUTGOING(args, object, tx_bytes) \
- __DRAW_BANDWIDTH(args, object, tx_bytes, COLOR_TX, _("Outgoing Traffic"))
+ __DRAW_BANDWIDTH(args, object, tx_bytes, COLOR_TX, "%s", _("Outgoing Traffic"))
-#define __DRAW_BANDWIDTH(args, object, bytes, color, label) \
+#define __DRAW_BANDWIDTH(args, object, bytes, color, label, ...) \
do { \
COMPUTE_BITS(args, FIELD_BITS(bytes), object, bytes); \
- DRAW_AREA_WITH_LABEL(args, FIELD_BITS(bytes), object, color, label); \
+ DRAW_AREA_WITH_LABEL(args, FIELD_BITS(bytes), object, color, 0, label, __VA_ARGS__); \
PRINT_CAMM(args, bytes, object, BPS); \
} while (0)
PRINT_HEADER4(args, _("Current"), _("Average"), _("Minimum"), _("Maximum"));
// Receive Rate
- DRAW_LINE_WITH_LABEL(args, 2, "rx_rate", object, COLOR_RX, _("Receive Rate"));
+ DRAW_LINE_WITH_LABEL(args, 2, "rx_rate", object, COLOR_RX, 0, _("Receive Rate"));
PRINT_CAMM(args, "rx_rate", object, BPS);
// Transmit Rate
- DRAW_LINE_WITH_LABEL(args, 2, "tx_rate", object, COLOR_TX, _("Transmit Rate"));
+ DRAW_LINE_WITH_LABEL(args, 2, "tx_rate", object, COLOR_TX, 0, _("Transmit Rate"));
PRINT_CAMM(args, "tx_rate", object, BPS);
return 0;
PRINT_HEADER4(args, _("Current"), _("Average"), _("Minimum"), _("Maximum"));
// Draw signal
- DRAW_LINE_WITH_LABEL(args, 2, "signal", object, GREEN, _("Signal"));
+ DRAW_LINE_WITH_LABEL(args, 2, "signal", object, GREEN, 0, _("Signal"));
PRINT_CAMM(args, "signal", object, FLOAT_WITH_UNIT, _("dBm"));
// Draw the lower signal quality in different colors
- DRAW_LINE(args, 2, "signal_good", object, YELLOW);
- DRAW_LINE(args, 2, "signal_fair", object, ORANGE);
- DRAW_LINE(args, 2, "signal_poor", object, RED);
+ DRAW_LINE(args, 2, "signal_good", object, YELLOW, 0);
+ DRAW_LINE(args, 2, "signal_fair", object, ORANGE, 0);
+ DRAW_LINE(args, 2, "signal_poor", object, RED, 0);
// Draw last ACK signal
- DRAW_LINE_WITH_LABEL(args, 2, "last_ack_signal", object, GREY, _("Last ACK Signal"));
+ DRAW_LINE_WITH_LABEL(args, 2, "last_ack_signal", object, GREY, 0, _("Last ACK Signal"));
PRINT_CAMM(args, "last_ack_signal", object, FLOAT_WITH_UNIT, _("dBm"));
return 0;
COMPUTE_CDEF(args, "delta1+=delta1,0,delta1,LIMIT");
// Draw the area backgrouns
- DRAW_AREA_BACKGROUND(args, "load15", NULL, COLOR_LOAD15);
- DRAW_AREA_BACKGROUND(args, "delta5+", NULL, COLOR_LOAD5, STACK);
- DRAW_AREA_BACKGROUND(args, "delta1+", NULL, COLOR_LOAD1, STACK);
+ DRAW_AREA_BACKGROUND(args, "load15", NULL, COLOR_LOAD15, 0);
+ DRAW_AREA_BACKGROUND(args, "delta5+", NULL, COLOR_LOAD5, STACKED);
+ DRAW_AREA_BACKGROUND(args, "delta1+", NULL, COLOR_LOAD1, STACKED);
- DRAW_AREA_OUTLINE_WITH_LABEL(args, "load15", NULL, COLOR_LOAD15, _("15 Minutes"));
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, "load15", NULL, COLOR_LOAD15, 0, _("15 Minutes"));
PRINT_CAMM(args, "load15", NULL, FLOAT);
- DRAW_AREA_OUTLINE_WITH_LABEL(args, "load5", NULL, COLOR_LOAD5, _("5 Minutes"));
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, "load5", NULL, COLOR_LOAD5, 0, _("5 Minutes"));
PRINT_CAMM(args, "load5", NULL, FLOAT);
- DRAW_AREA_OUTLINE_WITH_LABEL(args, "load1", NULL, COLOR_LOAD1, _("1 Minute"));
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, "load1", NULL, COLOR_LOAD1, 0, _("1 Minute"));
PRINT_CAMM(args, "load1", NULL, FLOAT);
// Header
COMPUTE_PERCENTAGE(args, "swap_used", NULL, "swap_total", NULL);
// Draw the stacked background first
- DRAW_AREA_BACKGROUND(args, "mem_used", NULL, COLOR_MEM_USED);
- DRAW_AREA_BACKGROUND(args, "buffers", NULL, COLOR_BUFFERS, STACK);
- DRAW_AREA_BACKGROUND(args, "cached", NULL, COLOR_CACHED, STACK);
+ DRAW_AREA_BACKGROUND(args, "mem_used", NULL, COLOR_MEM_USED, 0);
+ DRAW_AREA_BACKGROUND(args, "buffers", NULL, COLOR_BUFFERS, STACKED);
+ DRAW_AREA_BACKGROUND(args, "cached", NULL, COLOR_CACHED, STACKED);
// Draw the area outlines afterwards
- DRAW_AREA_OUTLINE_WITH_LABEL(args, "mem_used", NULL, COLOR_MEM_USED, _("Used Memory"));
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, "mem_used", NULL, COLOR_MEM_USED, 0, _("Used Memory"));
PRINT_CAMM(args, "mem_used", NULL, LARGE_FLOAT);
PRINT_EMPTY_LABEL(args);
PRINT_CAMM(args, "mem_used", NULL, PERCENTAGE);
- DRAW_AREA_OUTLINE_WITH_LABEL(args, "buffers", NULL, COLOR_BUFFERS, _("Buffers"), STACK);
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, "buffers", NULL, COLOR_BUFFERS, STACKED, _("Buffers"));
PRINT_CAMM(args, "buffers", NULL, LARGE_FLOAT);
- DRAW_AREA_OUTLINE_WITH_LABEL(args, "cached", NULL, COLOR_CACHED, _("Cached"), STACK);
+ DRAW_AREA_OUTLINE_WITH_LABEL(args, "cached", NULL, COLOR_CACHED, STACKED, _("Cached"));
PRINT_CAMM(args, "cached", NULL, LARGE_FLOAT);
// Draw the total memory as a line
- DRAW_LINE(args, 1, "mem_total", NULL, COLOR_MEM_TOTAL);
+ DRAW_LINE(args, 1, "mem_total", NULL, COLOR_MEM_TOTAL, 0);
// Make some space for swap
PRINT_EMPTY_LINE(args);
- DRAW_LINE_WITH_LABEL(args, 1, "swap_used", NULL, COLOR_SWAP_USED, _("Used Swap"), DASHES);
+ DRAW_LINE_WITH_LABEL(args, 1, "swap_used", NULL, COLOR_SWAP_USED, DASHED, _("Used Swap"));
PRINT_CAMM(args, "swap_used", NULL, LARGE_FLOAT);
PRINT_EMPTY_LABEL(args);
PRINT_CAMM(args, "swap_used", NULL, PERCENTAGE);
- DRAW_LINE_WITH_LABEL(args, 1, "swap_total", NULL, COLOR_SWAP_TOTAL, _("Total Swap"), DASHES);
+ DRAW_LINE_WITH_LABEL(args, 1, "swap_total", NULL, COLOR_SWAP_TOTAL, DASHED, _("Total Swap"));
PRINT(args, FIELD_CURRENT("swap_used"), NULL, LARGE_FLOAT);
PRINT_NOTHING(args);
PRINT_NOTHING(args);
PRINT_EMPTY_LINE(args);
// Draw the stacked background first
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("user"), NULL, COLOR_USER);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("nice"), NULL, COLOR_NICE, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("sys"), NULL, COLOR_SYS, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("wait"), NULL, COLOR_WAIT, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("irq"), NULL, COLOR_IRQ, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("softirq"), NULL, COLOR_SOFTIRQ, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("steal"), NULL, COLOR_STEAL, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("guest"), NULL, COLOR_GUEST, STACK);
- DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("guest_nice"), NULL, COLOR_GUEST_NICE, STACK);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("user"), NULL, COLOR_USER, 0);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("nice"), NULL, COLOR_NICE, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("sys"), NULL, COLOR_SYS, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("wait"), NULL, COLOR_WAIT, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("irq"), NULL, COLOR_IRQ, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("softirq"), NULL, COLOR_SOFTIRQ, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("steal"), NULL, COLOR_STEAL, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("guest"), NULL, COLOR_GUEST, STACKED);
+ DRAW_AREA_BACKGROUND(args, FIELD_PERCENT("guest_nice"), NULL, COLOR_GUEST_NICE, STACKED);
// Draw the area outlines afterwards
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("user"), NULL, COLOR_USER, _("User"));
+ FIELD_PERCENT("user"), NULL, COLOR_USER, 0, _("User"));
PRINT_CAMM(args, "user", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("nice"), NULL, COLOR_NICE, _("Nice"), STACK);
+ FIELD_PERCENT("nice"), NULL, COLOR_NICE, STACKED, _("Nice"));
PRINT_CAMM(args, "nice", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("sys"), NULL, COLOR_SYS, _("Sys"), STACK);
+ FIELD_PERCENT("sys"), NULL, COLOR_SYS, STACKED, _("Sys"));
PRINT_CAMM(args, "sys", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("wait"), NULL, COLOR_WAIT, _("Wait"), STACK);
+ FIELD_PERCENT("wait"), NULL, COLOR_WAIT, STACKED, _("Wait"));
PRINT_CAMM(args, "wait", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("irq"), NULL, COLOR_IRQ, _("Interrupt"), STACK);
+ FIELD_PERCENT("irq"), NULL, COLOR_IRQ, STACKED, _("Interrupt"));
PRINT_CAMM(args, "irq", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("softirq"), NULL, COLOR_SOFTIRQ, _("Soft Interrupt"), STACK);
+ FIELD_PERCENT("softirq"), NULL, COLOR_SOFTIRQ, STACKED, _("Soft Interrupt"));
PRINT_CAMM(args, "softirq", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("steal"), NULL, COLOR_STEAL, _("Steal"), STACK);
+ FIELD_PERCENT("steal"), NULL, COLOR_STEAL, STACKED, _("Steal"));
PRINT_CAMM(args, "steal", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("guest"), NULL, COLOR_GUEST, _("Guest"), STACK);
+ FIELD_PERCENT("guest"), NULL, COLOR_GUEST, STACKED, _("Guest"));
PRINT_CAMM(args, "guest", NULL, PERCENTAGE);
DRAW_AREA_OUTLINE_WITH_LABEL(args,
- FIELD_PERCENT("guest_nice"), NULL, COLOR_GUEST_NICE, _("Guest Nice"), STACK);
+ FIELD_PERCENT("guest_nice"), NULL, COLOR_GUEST_NICE, STACKED, _("Guest Nice"));
PRINT_CAMM(args, "guest_nice", NULL, PERCENTAGE);
return 0;
PRINT_HEADER1(args, _("Current"));
// Draw the uptime
- DRAW_AREA_WITH_LABEL(args, "uptime_days", NULL, DEFAULT, _("Uptime"));
+ DRAW_AREA_WITH_LABEL(args, "uptime_days", NULL, DEFAULT, 0, _("Uptime"));
PRINT(args, "uptime_days_cur", NULL, INTEGER);
PRINT_EOL(args);