You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5243 lines
130 KiB
5243 lines
130 KiB
7 years ago
|
diff -up util-linux-2.23.2/configure.ac.kzak util-linux-2.23.2/configure.ac
|
||
|
--- util-linux-2.23.2/configure.ac.kzak 2013-07-30 10:39:26.188738061 +0200
|
||
|
+++ util-linux-2.23.2/configure.ac 2014-09-25 14:41:48.980843829 +0200
|
||
|
@@ -46,6 +46,13 @@ LIBMOUNT_LT_MINOR=1
|
||
|
LIBMOUNT_LT_MICRO=0
|
||
|
LIBMOUNT_VERSION_INFO=`expr $LIBMOUNT_LT_MAJOR + $LIBMOUNT_LT_MINOR`:$LIBMOUNT_LT_MICRO:$LIBMOUNT_LT_MINOR
|
||
|
|
||
|
+dnl libsmartcols version
|
||
|
+LIBSMARTCOLS_VERSION="$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_RELEASE"
|
||
|
+LIBSMARTCOLS_LT_MAJOR=1
|
||
|
+LIBSMARTCOLS_LT_MINOR=1
|
||
|
+LIBSMARTCOLS_LT_MICRO=0
|
||
|
+LIBSMARTCOLS_VERSION_INFO=`expr $LIBSMARTCOLS_LT_MAJOR + $LIBSMARTCOLS_LT_MINOR`:$LIBSMARTCOLS_LT_MICRO:$LIBSMARTCOLS_LT_MINOR
|
||
|
+
|
||
|
# Check whether exec_prefix=/usr:
|
||
|
case $exec_prefix:$prefix in
|
||
|
NONE:NONE | NONE:/usr | /usr:*)
|
||
|
@@ -765,6 +772,18 @@ AC_DEFINE_UNQUOTED(LIBMOUNT_VERSION, "$L
|
||
|
|
||
|
|
||
|
dnl
|
||
|
+dnl libsmartcols
|
||
|
+dnl
|
||
|
+UL_BUILD_INIT([libsmartcols], [yes])
|
||
|
+AM_CONDITIONAL([BUILD_LIBSMARTCOLS], [test "x$build_libsmartcols" = xyes])
|
||
|
+AM_CONDITIONAL([BUILD_LIBSMARTCOLS_TESTS], [test "x$build_libsmartcols" = xyes -a "x$enable_static" = xyes])
|
||
|
+
|
||
|
+AC_SUBST([LIBSMARTCOLS_VERSION])
|
||
|
+AC_SUBST([LIBSMARTCOLS_VERSION_INFO])
|
||
|
+AC_DEFINE_UNQUOTED([LIBSMARTCOLS_VERSION], ["$LIBSMARTCOLS_VERSION"], [libsmartcols version string])
|
||
|
+
|
||
|
+
|
||
|
+dnl
|
||
|
dnl libfdisk is enabled all time if possible
|
||
|
dnl
|
||
|
UL_BUILD_INIT([libfdisk], [check])
|
||
|
@@ -1500,6 +1519,9 @@ libblkid/src/blkid.h
|
||
|
libmount/docs/Makefile
|
||
|
libmount/docs/version.xml
|
||
|
libmount/src/libmount.h
|
||
|
+libsmartcols/docs/Makefile
|
||
|
+libsmartcols/docs/version.xml
|
||
|
+libsmartcols/src/libsmartcols.h
|
||
|
po/Makefile.in
|
||
|
])
|
||
|
|
||
|
diff -up util-linux-2.23.2/include/carefulputc.h.kzak util-linux-2.23.2/include/carefulputc.h
|
||
|
--- util-linux-2.23.2/include/carefulputc.h.kzak 2012-11-29 16:18:33.956147961 +0100
|
||
|
+++ util-linux-2.23.2/include/carefulputc.h 2014-09-25 14:41:48.980843829 +0200
|
||
|
@@ -26,4 +26,39 @@ static inline int carefulputc(int c, FIL
|
||
|
return (ret < 0) ? EOF : 0;
|
||
|
}
|
||
|
|
||
|
+static inline void fputs_quoted(const char *data, FILE *out)
|
||
|
+{
|
||
|
+ const char *p;
|
||
|
+
|
||
|
+ fputc('"', out);
|
||
|
+ for (p = data; p && *p; p++) {
|
||
|
+ if ((unsigned char) *p == 0x22 || /* " */
|
||
|
+ (unsigned char) *p == 0x5c || /* \ */
|
||
|
+ !isprint((unsigned char) *p) ||
|
||
|
+ iscntrl((unsigned char) *p)) {
|
||
|
+
|
||
|
+ fprintf(out, "\\x%02x", (unsigned char) *p);
|
||
|
+ } else
|
||
|
+ fputc(*p, out);
|
||
|
+ }
|
||
|
+ fputc('"', out);
|
||
|
+}
|
||
|
+
|
||
|
+static inline void fputs_nonblank(const char *data, FILE *out)
|
||
|
+{
|
||
|
+ const char *p;
|
||
|
+
|
||
|
+ for (p = data; p && *p; p++) {
|
||
|
+ if (isblank((unsigned char) *p) ||
|
||
|
+ (unsigned char) *p == 0x5c || /* \ */
|
||
|
+ !isprint((unsigned char) *p) ||
|
||
|
+ iscntrl((unsigned char) *p)) {
|
||
|
+
|
||
|
+ fprintf(out, "\\x%02x", (unsigned char) *p);
|
||
|
+
|
||
|
+ } else
|
||
|
+ fputc(*p, out);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
#endif /* _CAREFUULPUTC_H */
|
||
|
diff -up util-linux-2.23.2/include/debug.h.kzak util-linux-2.23.2/include/debug.h
|
||
|
--- util-linux-2.23.2/include/debug.h.kzak 2014-09-25 14:41:48.981843839 +0200
|
||
|
+++ util-linux-2.23.2/include/debug.h 2014-09-25 14:41:48.981843839 +0200
|
||
|
@@ -0,0 +1,126 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be distributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+#ifndef UTIL_LINUX_DEBUG_H
|
||
|
+#define UTIL_LINUX_DEBUG_H
|
||
|
+
|
||
|
+#include <stdarg.h>
|
||
|
+#include <string.h>
|
||
|
+
|
||
|
+struct dbg_mask { char *mname; int val; };
|
||
|
+#define UL_DEBUG_EMPTY_MASKNAMES {{ NULL, 0 }}
|
||
|
+
|
||
|
+#define UL_DEBUG_DEFINE_MASK(m) int m ## _debug_mask
|
||
|
+#define UL_DEBUG_DECLARE_MASK(m) extern UL_DEBUG_DEFINE_MASK(m)
|
||
|
+#define UL_DEBUG_DEFINE_MASKANEMS(m) static const struct dbg_mask m ## _masknames[]
|
||
|
+
|
||
|
+/* p - flag prefix, m - flag postfix */
|
||
|
+#define UL_DEBUG_DEFINE_FLAG(p, m) p ## m
|
||
|
+
|
||
|
+/* l - library name, p - flag prefix, m - flag postfix, x - function */
|
||
|
+#define __UL_DBG(l, p, m, x) \
|
||
|
+ do { \
|
||
|
+ if ((p ## m) & l ## _debug_mask) { \
|
||
|
+ fprintf(stderr, "%d: %s: %8s: ", getpid(), # l, # m); \
|
||
|
+ x; \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+
|
||
|
+#define __UL_DBG_CALL(l, p, m, x) \
|
||
|
+ do { \
|
||
|
+ if ((p ## m) & l ## _debug_mask) { \
|
||
|
+ x; \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+
|
||
|
+#define __UL_DBG_FLUSH(l, p) \
|
||
|
+ do { \
|
||
|
+ if (l ## _debug_mask && \
|
||
|
+ l ## _debug_mask != p ## INIT) { \
|
||
|
+ fflush(stderr); \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+
|
||
|
+
|
||
|
+#define __UL_INIT_DEBUG(lib, pref, mask, env) \
|
||
|
+ do { \
|
||
|
+ if (lib ## _debug_mask & pref ## INIT) \
|
||
|
+ ; \
|
||
|
+ else if (!mask) { \
|
||
|
+ char *str = getenv(# env); \
|
||
|
+ if (str) \
|
||
|
+ lib ## _debug_mask = parse_envmask(lib ## _masknames, str); \
|
||
|
+ } else \
|
||
|
+ lib ## _debug_mask = mask; \
|
||
|
+ lib ## _debug_mask |= pref ## INIT; \
|
||
|
+ if (lib ## _debug_mask != pref ## INIT) { \
|
||
|
+ __UL_DBG(lib, pref, INIT, ul_debug("library debug mask: 0x%04x", \
|
||
|
+ lib ## _debug_mask)); \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+
|
||
|
+
|
||
|
+static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
|
||
|
+ul_debug(const char *mesg, ...)
|
||
|
+{
|
||
|
+ va_list ap;
|
||
|
+ va_start(ap, mesg);
|
||
|
+ vfprintf(stderr, mesg, ap);
|
||
|
+ va_end(ap);
|
||
|
+ fputc('\n', stderr);
|
||
|
+}
|
||
|
+
|
||
|
+static inline void __attribute__ ((__format__ (__printf__, 2, 3)))
|
||
|
+ul_debugobj(void *handler, const char *mesg, ...)
|
||
|
+{
|
||
|
+ va_list ap;
|
||
|
+
|
||
|
+ if (handler)
|
||
|
+ fprintf(stderr, "[%p]: ", handler);
|
||
|
+ va_start(ap, mesg);
|
||
|
+ vfprintf(stderr, mesg, ap);
|
||
|
+ va_end(ap);
|
||
|
+ fputc('\n', stderr);
|
||
|
+}
|
||
|
+
|
||
|
+static inline int parse_envmask(const struct dbg_mask const flagnames[],
|
||
|
+ const char *mask)
|
||
|
+{
|
||
|
+ int res;
|
||
|
+ char *ptr;
|
||
|
+
|
||
|
+ /* let's check for a numeric mask first */
|
||
|
+ res = strtoul(mask, &ptr, 0);
|
||
|
+
|
||
|
+ /* perhaps it's a comma-separated string? */
|
||
|
+ if (*ptr != '\0' && flagnames) {
|
||
|
+ char *msbuf, *ms, *name;
|
||
|
+ res = 0;
|
||
|
+
|
||
|
+ ms = msbuf = strdup(mask);
|
||
|
+ if (!ms)
|
||
|
+ return res;
|
||
|
+
|
||
|
+ while ((name = strtok_r(ms, ",", &ptr))) {
|
||
|
+ size_t i = 0;
|
||
|
+ ms = ptr;
|
||
|
+
|
||
|
+ while (flagnames[i].mname) {
|
||
|
+ if (!strcmp(name, flagnames[i].mname)) {
|
||
|
+ res |= flagnames[i].val;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ ++i;
|
||
|
+ }
|
||
|
+ /* nothing else we can do by OR-ing the mask */
|
||
|
+ if (res == 0xffff)
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ free(msbuf);
|
||
|
+ }
|
||
|
+ return res;
|
||
|
+}
|
||
|
+#endif /* UTIL_LINUX_DEBUG_H */
|
||
|
diff -up util-linux-2.23.2/include/list.h.kzak util-linux-2.23.2/include/list.h
|
||
|
--- util-linux-2.23.2/include/list.h.kzak 2013-06-13 09:46:10.396650417 +0200
|
||
|
+++ util-linux-2.23.2/include/list.h 2014-09-25 14:41:48.981843839 +0200
|
||
|
@@ -212,14 +212,16 @@ _INLINE_ void list_splice(struct list_he
|
||
|
* sentinel head node, "prev" links not maintained.
|
||
|
*/
|
||
|
_INLINE_ struct list_head *merge(int (*cmp)(struct list_head *a,
|
||
|
- struct list_head *b),
|
||
|
+ struct list_head *b,
|
||
|
+ void *data),
|
||
|
+ void *data,
|
||
|
struct list_head *a, struct list_head *b)
|
||
|
{
|
||
|
struct list_head head, *tail = &head;
|
||
|
|
||
|
while (a && b) {
|
||
|
/* if equal, take 'a' -- important for sort stability */
|
||
|
- if ((*cmp)(a, b) <= 0) {
|
||
|
+ if ((*cmp)(a, b, data) <= 0) {
|
||
|
tail->next = a;
|
||
|
a = a->next;
|
||
|
} else {
|
||
|
@@ -240,7 +242,9 @@ _INLINE_ struct list_head *merge(int (*c
|
||
|
* throughout.
|
||
|
*/
|
||
|
_INLINE_ void merge_and_restore_back_links(int (*cmp)(struct list_head *a,
|
||
|
- struct list_head *b),
|
||
|
+ struct list_head *b,
|
||
|
+ void *data),
|
||
|
+ void *data,
|
||
|
struct list_head *head,
|
||
|
struct list_head *a, struct list_head *b)
|
||
|
{
|
||
|
@@ -248,7 +252,7 @@ _INLINE_ void merge_and_restore_back_lin
|
||
|
|
||
|
while (a && b) {
|
||
|
/* if equal, take 'a' -- important for sort stability */
|
||
|
- if ((*cmp)(a, b) <= 0) {
|
||
|
+ if ((*cmp)(a, b, data) <= 0) {
|
||
|
tail->next = a;
|
||
|
a->prev = tail;
|
||
|
a = a->next;
|
||
|
@@ -268,7 +272,7 @@ _INLINE_ void merge_and_restore_back_lin
|
||
|
* element comparison is needed, so the client's cmp()
|
||
|
* routine can invoke cond_resched() periodically.
|
||
|
*/
|
||
|
- (*cmp)(tail->next, tail->next);
|
||
|
+ (*cmp)(tail->next, tail->next, data);
|
||
|
|
||
|
tail->next->prev = tail;
|
||
|
tail = tail->next;
|
||
|
@@ -294,7 +298,9 @@ _INLINE_ void merge_and_restore_back_lin
|
||
|
*/
|
||
|
_INLINE_ void list_sort(struct list_head *head,
|
||
|
int (*cmp)(struct list_head *a,
|
||
|
- struct list_head *b))
|
||
|
+ struct list_head *b,
|
||
|
+ void *data),
|
||
|
+ void *data)
|
||
|
{
|
||
|
struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
|
||
|
-- last slot is a sentinel */
|
||
|
@@ -316,7 +322,7 @@ _INLINE_ void list_sort(struct list_head
|
||
|
cur->next = NULL;
|
||
|
|
||
|
for (lev = 0; part[lev]; lev++) {
|
||
|
- cur = merge(cmp, part[lev], cur);
|
||
|
+ cur = merge(cmp, data, part[lev], cur);
|
||
|
part[lev] = NULL;
|
||
|
}
|
||
|
if (lev > max_lev) {
|
||
|
@@ -330,11 +336,12 @@ _INLINE_ void list_sort(struct list_head
|
||
|
|
||
|
for (lev = 0; lev < max_lev; lev++)
|
||
|
if (part[lev])
|
||
|
- list = merge(cmp, part[lev], list);
|
||
|
+ list = merge(cmp, data, part[lev], list);
|
||
|
|
||
|
- merge_and_restore_back_links(cmp, head, part[max_lev], list);
|
||
|
+ merge_and_restore_back_links(cmp, data, head, part[max_lev], list);
|
||
|
}
|
||
|
|
||
|
+
|
||
|
#undef _INLINE_
|
||
|
|
||
|
#endif /* UTIL_LINUX_LIST_H */
|
||
|
diff -up util-linux-2.23.2/include/mbsalign.h.kzak util-linux-2.23.2/include/mbsalign.h
|
||
|
--- util-linux-2.23.2/include/mbsalign.h.kzak 2013-06-13 09:46:10.397650425 +0200
|
||
|
+++ util-linux-2.23.2/include/mbsalign.h 2014-09-25 14:41:48.981843839 +0200
|
||
|
@@ -1,5 +1,6 @@
|
||
|
/* Align/Truncate a string in a given screen width
|
||
|
Copyright (C) 2009-2010 Free Software Foundation, Inc.
|
||
|
+ Copyright (C) 2010-2013 Karel Zak <kzak@redhat.com>
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
@@ -13,8 +14,9 @@
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
-
|
||
|
-#include <stddef.h>
|
||
|
+#ifndef UTIL_LINUX_MBSALIGN_H
|
||
|
+# define UTIL_LINUX_MBSALIGN_H
|
||
|
+# include <stddef.h>
|
||
|
|
||
|
typedef enum { MBS_ALIGN_LEFT, MBS_ALIGN_RIGHT, MBS_ALIGN_CENTER } mbs_align_t;
|
||
|
|
||
|
@@ -43,3 +45,12 @@ extern size_t mbs_truncate(char *str, si
|
||
|
extern size_t mbsalign (const char *src, char *dest,
|
||
|
size_t dest_size, size_t *width,
|
||
|
mbs_align_t align, int flags);
|
||
|
+
|
||
|
+extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz);
|
||
|
+extern size_t mbs_safe_width(const char *s);
|
||
|
+
|
||
|
+extern char *mbs_safe_encode(const char *s, size_t *width);
|
||
|
+extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf);
|
||
|
+extern size_t mbs_safe_encode_size(size_t bytes);
|
||
|
+
|
||
|
+#endif /* UTIL_LINUX_MBSALIGN_H */
|
||
|
diff -up util-linux-2.23.2/lib/mbsalign.c.kzak util-linux-2.23.2/lib/mbsalign.c
|
||
|
--- util-linux-2.23.2/lib/mbsalign.c.kzak 2013-07-30 10:39:26.203738210 +0200
|
||
|
+++ util-linux-2.23.2/lib/mbsalign.c 2014-09-25 14:41:48.982843848 +0200
|
||
|
@@ -23,17 +23,193 @@
|
||
|
#include <stdio.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <limits.h>
|
||
|
+#include <ctype.h>
|
||
|
|
||
|
#include "c.h"
|
||
|
#include "mbsalign.h"
|
||
|
#include "widechar.h"
|
||
|
|
||
|
-
|
||
|
#ifdef HAVE_WIDECHAR
|
||
|
/* Replace non printable chars.
|
||
|
Note \t and \n etc. are non printable.
|
||
|
Return 1 if replacement made, 0 otherwise. */
|
||
|
|
||
|
+/*
|
||
|
+ * Counts number of cells in multibyte string. For all control and
|
||
|
+ * non-printable chars is the result width enlarged to store \x?? hex
|
||
|
+ * sequence. See mbs_safe_encode().
|
||
|
+ *
|
||
|
+ * Returns: number of cells, @sz returns number of bytes.
|
||
|
+ */
|
||
|
+size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz)
|
||
|
+{
|
||
|
+ mbstate_t st;
|
||
|
+ const char *p = buf, *last = buf;
|
||
|
+ size_t width = 0, bytes = 0;
|
||
|
+
|
||
|
+ memset(&st, 0, sizeof(st));
|
||
|
+
|
||
|
+ if (p && *p && bufsz)
|
||
|
+ last = p + (bufsz - 1);
|
||
|
+
|
||
|
+ while (p && *p && p <= last) {
|
||
|
+ if (iscntrl((unsigned char) *p)) {
|
||
|
+ width += 4, bytes += 4; /* *p encoded to \x?? */
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+#ifdef HAVE_WIDECHAR
|
||
|
+ else {
|
||
|
+ wchar_t wc;
|
||
|
+ size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
|
||
|
+
|
||
|
+ if (len == 0)
|
||
|
+ break;
|
||
|
+
|
||
|
+ if (len == (size_t) -1 || len == (size_t) -2) {
|
||
|
+ len = 1;
|
||
|
+ if (isprint((unsigned char) *p))
|
||
|
+ width += 1, bytes += 1;
|
||
|
+ else
|
||
|
+ width += 4, bytes += 4;
|
||
|
+
|
||
|
+ } else if (!iswprint(wc)) {
|
||
|
+ width += len * 4; /* hex encode whole sequence */
|
||
|
+ bytes += len * 4;
|
||
|
+ } else {
|
||
|
+ width += wcwidth(wc); /* number of cells */
|
||
|
+ bytes += len; /* number of bytes */
|
||
|
+ }
|
||
|
+ p += len;
|
||
|
+ }
|
||
|
+#else
|
||
|
+ else if (!isprint((unsigned char) *p)) {
|
||
|
+ width += 4, bytes += 4; /* *p encoded to \x?? */
|
||
|
+ p++;
|
||
|
+ } else {
|
||
|
+ width++, bytes++;
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ if (sz)
|
||
|
+ *sz = bytes;
|
||
|
+ return width;
|
||
|
+}
|
||
|
+
|
||
|
+size_t mbs_safe_width(const char *s)
|
||
|
+{
|
||
|
+ if (!s || !*s)
|
||
|
+ return 0;
|
||
|
+ return mbs_safe_nwidth(s, strlen(s), NULL);
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Copy @s to @buf and replace control and non-printable chars with
|
||
|
+ * \x?? hex sequence. The @width returns number of cells.
|
||
|
+ *
|
||
|
+ * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
|
||
|
+ * bytes.
|
||
|
+ */
|
||
|
+char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
|
||
|
+{
|
||
|
+ mbstate_t st;
|
||
|
+ const char *p = s;
|
||
|
+ char *r;
|
||
|
+ size_t sz = s ? strlen(s) : 0;
|
||
|
+
|
||
|
+ if (!sz || !buf)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ memset(&st, 0, sizeof(st));
|
||
|
+
|
||
|
+ r = buf;
|
||
|
+ *width = 0;
|
||
|
+
|
||
|
+ while (p && *p) {
|
||
|
+ if (iscntrl((unsigned char) *p)) {
|
||
|
+ sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
+ r += 4;
|
||
|
+ *width += 4;
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+#ifdef HAVE_WIDECHAR
|
||
|
+ else {
|
||
|
+ wchar_t wc;
|
||
|
+ size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
|
||
|
+
|
||
|
+ if (len == 0)
|
||
|
+ break; /* end of string */
|
||
|
+
|
||
|
+ if (len == (size_t) -1 || len == (size_t) -2) {
|
||
|
+ len = 1;
|
||
|
+ /*
|
||
|
+ * Not valid multibyte sequence -- maybe it's
|
||
|
+ * printable char according to the current locales.
|
||
|
+ */
|
||
|
+ if (!isprint((unsigned char) *p)) {
|
||
|
+ sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
+ r += 4;
|
||
|
+ *width += 4;
|
||
|
+ } else {
|
||
|
+ width++;
|
||
|
+ *r++ = *p;
|
||
|
+ }
|
||
|
+ } else if (!iswprint(wc)) {
|
||
|
+ size_t i;
|
||
|
+ for (i = 0; i < len; i++) {
|
||
|
+ sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
+ r += 4;
|
||
|
+ *width += 4;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ memcpy(r, p, len);
|
||
|
+ r += len;
|
||
|
+ *width += wcwidth(wc);
|
||
|
+ }
|
||
|
+ p += len;
|
||
|
+ }
|
||
|
+#else
|
||
|
+ else if (!isprint((unsigned char) *p)) {
|
||
|
+ sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
+ p++;
|
||
|
+ r += 4;
|
||
|
+ *width += 4;
|
||
|
+ } else {
|
||
|
+ *r++ = *p++;
|
||
|
+ *width++;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ *r = '\0';
|
||
|
+
|
||
|
+ return buf;
|
||
|
+}
|
||
|
+
|
||
|
+size_t mbs_safe_encode_size(size_t bytes)
|
||
|
+{
|
||
|
+ return (bytes * 4) + 1;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Returns allocated string where all control and non-printable chars are
|
||
|
+ * replaced with \x?? hex sequence.
|
||
|
+ */
|
||
|
+char *mbs_safe_encode(const char *s, size_t *width)
|
||
|
+{
|
||
|
+ size_t sz = s ? strlen(s) : 0;
|
||
|
+ char *buf;
|
||
|
+
|
||
|
+ if (!sz)
|
||
|
+ return NULL;
|
||
|
+ buf = malloc(mbs_safe_encode_size(sz));
|
||
|
+ if (!buf)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ return mbs_safe_encode_to_buffer(s, width, buf);
|
||
|
+}
|
||
|
+
|
||
|
static bool
|
||
|
wc_ensure_printable (wchar_t *wchars)
|
||
|
{
|
||
|
@@ -254,8 +430,8 @@ mbsalign_unibyte:
|
||
|
if (dest_size != 0)
|
||
|
{
|
||
|
char *dest_end = dest + dest_size - 1;
|
||
|
- size_t start_spaces = n_spaces / 2 + n_spaces % 2;
|
||
|
- size_t end_spaces = n_spaces / 2;
|
||
|
+ size_t start_spaces;
|
||
|
+ size_t end_spaces;
|
||
|
|
||
|
switch (align)
|
||
|
{
|
||
|
diff -up util-linux-2.23.2/libsmartcols/COPYING.kzak util-linux-2.23.2/libsmartcols/COPYING
|
||
|
--- util-linux-2.23.2/libsmartcols/COPYING.kzak 2014-09-25 14:41:48.983843858 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/COPYING 2014-09-25 14:41:48.983843858 +0200
|
||
|
@@ -0,0 +1,8 @@
|
||
|
+This library is free software; you can redistribute it and/or
|
||
|
+modify it under the terms of the GNU Lesser General Public
|
||
|
+License as published by the Free Software Foundation; either
|
||
|
+version 2.1 of the License, or (at your option) any later
|
||
|
+version.
|
||
|
+
|
||
|
+The complete text of the license is available in the
|
||
|
+../Documentation/licenses/COPYING.LGPLv2.1 file.
|
||
|
diff -up util-linux-2.23.2/libsmartcols/docs/.gitignore.kzak util-linux-2.23.2/libsmartcols/docs/.gitignore
|
||
|
--- util-linux-2.23.2/libsmartcols/docs/.gitignore.kzak 2014-09-25 14:41:48.983843858 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/docs/.gitignore 2014-09-25 14:41:48.983843858 +0200
|
||
|
@@ -0,0 +1,18 @@
|
||
|
+*-decl-list.txt
|
||
|
+*-decl.txt
|
||
|
+*-overrides.txt
|
||
|
+*-undeclared.txt
|
||
|
+*-undocumented.txt
|
||
|
+*-unused.txt
|
||
|
+*.args
|
||
|
+*.bak
|
||
|
+*.hierarchy
|
||
|
+*.interfaces
|
||
|
+*.prerequisites
|
||
|
+*.signals
|
||
|
+*.stamp
|
||
|
+*.types
|
||
|
+html/*
|
||
|
+tmpl/*
|
||
|
+version.xml
|
||
|
+xml/*
|
||
|
diff -up util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml.kzak util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml
|
||
|
--- util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml.kzak 2014-09-25 14:41:48.984843867 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml 2014-09-25 14:41:48.984843867 +0200
|
||
|
@@ -0,0 +1,52 @@
|
||
|
+<?xml version="1.0"?>
|
||
|
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||
|
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
|
||
|
+[
|
||
|
+ <!ENTITY version SYSTEM "version.xml">
|
||
|
+]>
|
||
|
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||
|
+ <bookinfo>
|
||
|
+ <title>libsmartcols Reference Manual</title>
|
||
|
+ <releaseinfo>for libsmartcols version &version;</releaseinfo>
|
||
|
+ <copyright>
|
||
|
+ <year>2014</year>
|
||
|
+ <holder>Karel Zak <kzak@redhat.com></holder>
|
||
|
+ </copyright>
|
||
|
+ </bookinfo>
|
||
|
+
|
||
|
+ <part id="gtk">
|
||
|
+ <title>libsmartcols Overview</title>
|
||
|
+ <partintro>
|
||
|
+ <para>
|
||
|
+The libsmartcols library is used for smart adaptive formatting of tabular data.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+The library is part of the util-linux package since version 2.25 and is
|
||
|
+available from ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
|
||
|
+ </para>
|
||
|
+ </partintro>
|
||
|
+ </part>
|
||
|
+
|
||
|
+ <part>
|
||
|
+ <title>Data manipulation</title>
|
||
|
+ <xi:include href="xml/table.xml"/>
|
||
|
+ <xi:include href="xml/column.xml"/>
|
||
|
+ <xi:include href="xml/line.xml"/>
|
||
|
+ <xi:include href="xml/cell.xml"/>
|
||
|
+ <xi:include href="xml/symbols.xml"/>
|
||
|
+ </part>
|
||
|
+ <part>
|
||
|
+ <title>Printing</title>
|
||
|
+ <xi:include href="xml/table_print.xml"/>
|
||
|
+ </part>
|
||
|
+ <part>
|
||
|
+ <title>Misc</title>
|
||
|
+ <xi:include href="xml/iter.xml"/>
|
||
|
+ <xi:include href="xml/version-utils.xml"/>
|
||
|
+ <xi:include href="xml/init.xml"/>
|
||
|
+ </part>
|
||
|
+ <index id="api-index-full">
|
||
|
+ <title>API Index</title>
|
||
|
+ <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
||
|
+ </index>
|
||
|
+</book>
|
||
|
diff -up util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt.kzak util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt
|
||
|
--- util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt.kzak 2014-09-25 14:41:48.984843867 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt 2014-09-25 14:41:48.984843867 +0200
|
||
|
@@ -0,0 +1,146 @@
|
||
|
+<SECTION>
|
||
|
+<FILE>cell</FILE>
|
||
|
+libscols_cell
|
||
|
+scols_cell_copy_content
|
||
|
+scols_cell_get_color
|
||
|
+scols_cell_get_data
|
||
|
+scols_cell_get_userdata
|
||
|
+scols_cell_refer_data
|
||
|
+scols_cell_set_color
|
||
|
+scols_cell_set_data
|
||
|
+scols_cell_set_userdata
|
||
|
+scols_cmpstr_cells
|
||
|
+scols_reset_cell
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>column</FILE>
|
||
|
+libscols_column
|
||
|
+scols_column_get_color
|
||
|
+scols_column_get_flags
|
||
|
+scols_column_get_header
|
||
|
+scols_column_get_whint
|
||
|
+scols_column_is_noextremes
|
||
|
+scols_column_is_right
|
||
|
+scols_column_is_strict_width
|
||
|
+scols_column_is_tree
|
||
|
+scols_column_is_trunc
|
||
|
+scols_column_set_cmpfunc
|
||
|
+scols_column_set_color
|
||
|
+scols_column_set_flags
|
||
|
+scols_column_set_whint
|
||
|
+scols_copy_column
|
||
|
+scols_new_column
|
||
|
+scols_ref_column
|
||
|
+scols_unref_column
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>iter</FILE>
|
||
|
+libscols_iter
|
||
|
+scols_free_iter
|
||
|
+scols_iter_get_direction
|
||
|
+scols_new_iter
|
||
|
+scols_reset_iter
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>line</FILE>
|
||
|
+libscols_line
|
||
|
+scols_copy_line
|
||
|
+scols_line_add_child
|
||
|
+scols_line_alloc_cells
|
||
|
+scols_line_free_cells
|
||
|
+scols_line_get_cell
|
||
|
+scols_line_get_color
|
||
|
+scols_line_get_column_cell
|
||
|
+scols_line_get_ncells
|
||
|
+scols_line_get_parent
|
||
|
+scols_line_get_userdata
|
||
|
+scols_line_has_children
|
||
|
+scols_line_next_child
|
||
|
+scols_line_refer_data
|
||
|
+scols_line_remove_child
|
||
|
+scols_line_set_color
|
||
|
+scols_line_set_data
|
||
|
+scols_line_set_userdata
|
||
|
+scols_new_line
|
||
|
+scols_ref_line
|
||
|
+scols_unref_line
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>symbols</FILE>
|
||
|
+libscols_symbols
|
||
|
+scols_copy_symbols
|
||
|
+scols_new_symbols
|
||
|
+scols_ref_symbols
|
||
|
+scols_symbols_set_branch
|
||
|
+scols_symbols_set_right
|
||
|
+scols_symbols_set_vertical
|
||
|
+scols_unref_symbols
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>table</FILE>
|
||
|
+libscols_table
|
||
|
+scols_copy_table
|
||
|
+scols_new_table
|
||
|
+scols_ref_table
|
||
|
+scols_table_add_column
|
||
|
+scols_table_add_line
|
||
|
+scols_table_colors_wanted
|
||
|
+scols_table_enable_ascii
|
||
|
+scols_table_enable_colors
|
||
|
+scols_table_enable_export
|
||
|
+scols_table_enable_maxout
|
||
|
+scols_table_enable_noheadings
|
||
|
+scols_table_enable_raw
|
||
|
+scols_table_get_column
|
||
|
+scols_table_get_column_separator
|
||
|
+scols_table_get_line
|
||
|
+scols_table_get_line_separator
|
||
|
+scols_table_get_ncols
|
||
|
+scols_table_get_nlines
|
||
|
+scols_table_get_stream
|
||
|
+scols_table_is_ascii
|
||
|
+scols_table_is_empty
|
||
|
+scols_table_is_export
|
||
|
+scols_table_is_maxout
|
||
|
+scols_table_is_noheadings
|
||
|
+scols_table_is_raw
|
||
|
+scols_table_is_tree
|
||
|
+scols_table_new_column
|
||
|
+scols_table_new_line
|
||
|
+scols_table_next_column
|
||
|
+scols_table_next_line
|
||
|
+scols_table_reduce_termwidth
|
||
|
+scols_table_remove_column
|
||
|
+scols_table_remove_columns
|
||
|
+scols_table_remove_line
|
||
|
+scols_table_remove_lines
|
||
|
+scols_table_set_column_separator
|
||
|
+scols_table_set_line_separator
|
||
|
+scols_table_set_stream
|
||
|
+scols_table_set_symbols
|
||
|
+scols_sort_table
|
||
|
+scols_unref_table
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>table_print</FILE>
|
||
|
+scols_print_table
|
||
|
+scols_print_table_to_string
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>version-utils</FILE>
|
||
|
+scols_get_library_version
|
||
|
+scols_parse_version_string
|
||
|
+LIBSMARTCOLS_VERSION
|
||
|
+</SECTION>
|
||
|
+
|
||
|
+<SECTION>
|
||
|
+<FILE>init</FILE>
|
||
|
+scols_init_debug
|
||
|
+</SECTION>
|
||
|
diff -up util-linux-2.23.2/libsmartcols/docs/Makefile.am.kzak util-linux-2.23.2/libsmartcols/docs/Makefile.am
|
||
|
--- util-linux-2.23.2/libsmartcols/docs/Makefile.am.kzak 2014-09-25 14:41:48.984843867 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/docs/Makefile.am 2014-09-25 14:41:48.984843867 +0200
|
||
|
@@ -0,0 +1,93 @@
|
||
|
+## Process this file with automake to produce Makefile.in
|
||
|
+
|
||
|
+# We require automake 1.10 at least.
|
||
|
+AUTOMAKE_OPTIONS = 1.10
|
||
|
+
|
||
|
+# This is a blank Makefile.am for using gtk-doc.
|
||
|
+# Copy this to your project's API docs directory and modify the variables to
|
||
|
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
|
||
|
+# of using the various options.
|
||
|
+
|
||
|
+# The name of the module, e.g. 'glib'.
|
||
|
+DOC_MODULE=libsmartcols
|
||
|
+
|
||
|
+# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
|
||
|
+#DOC_MODULE_VERSION=2
|
||
|
+
|
||
|
+# The top-level SGML file. You can change this if you want to.
|
||
|
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
|
||
|
+
|
||
|
+# The directory containing the source code. Relative to $(srcdir).
|
||
|
+# gtk-doc will search all .c & .h files beneath here for inline comments
|
||
|
+# documenting the functions and macros.
|
||
|
+# e.g. DOC_SOURCE_DIR=../../../gtk
|
||
|
+DOC_SOURCE_DIR=../src
|
||
|
+
|
||
|
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
||
|
+SCANGOBJ_OPTIONS=
|
||
|
+
|
||
|
+# Extra options to supply to gtkdoc-scan.
|
||
|
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
||
|
+SCAN_OPTIONS=
|
||
|
+
|
||
|
+# Extra options to supply to gtkdoc-mkdb.
|
||
|
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
|
||
|
+MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space mnt
|
||
|
+
|
||
|
+# Extra options to supply to gtkdoc-mktmpl
|
||
|
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
|
||
|
+MKTMPL_OPTIONS=
|
||
|
+
|
||
|
+# Extra options to supply to gtkdoc-mkhtml
|
||
|
+MKHTML_OPTIONS=
|
||
|
+
|
||
|
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
|
||
|
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
|
||
|
+FIXXREF_OPTIONS=
|
||
|
+
|
||
|
+# Used for dependencies. The docs will be rebuilt if any of these change.
|
||
|
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
|
||
|
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
|
||
|
+HFILE_GLOB=$(top_builddir)/libsmartcols/src/libsmartcols.h
|
||
|
+CFILE_GLOB=$(top_srcdir)/libsmartcols/src/*.c
|
||
|
+
|
||
|
+# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
|
||
|
+# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
|
||
|
+EXTRA_HFILES=
|
||
|
+
|
||
|
+# Header files to ignore when scanning. Use base file name, no paths
|
||
|
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
|
||
|
+IGNORE_HFILES=smartcolsP.h
|
||
|
+
|
||
|
+# Images to copy into HTML directory.
|
||
|
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
||
|
+HTML_IMAGES=
|
||
|
+
|
||
|
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
||
|
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
||
|
+content_files = $(builddir)/version.xml
|
||
|
+
|
||
|
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
|
||
|
+# These files must be listed here *and* in content_files
|
||
|
+# e.g. expand_content_files=running.sgml
|
||
|
+expand_content_files=
|
||
|
+
|
||
|
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
|
||
|
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
|
||
|
+# signals and properties.
|
||
|
+# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
||
|
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
||
|
+GTKDOC_CFLAGS=
|
||
|
+GTKDOC_LIBS=
|
||
|
+
|
||
|
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
||
|
+include $(top_srcdir)/config/gtk-doc.make
|
||
|
+
|
||
|
+# Other files to distribute
|
||
|
+# e.g. EXTRA_DIST += version.xml.in
|
||
|
+EXTRA_DIST += version.xml.in
|
||
|
+
|
||
|
+# Files not to distribute
|
||
|
+# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
|
||
|
+# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
|
||
|
+DISTCLEANFILES += version.xml
|
||
|
diff -up util-linux-2.23.2/libsmartcols/docs/version.xml.in.kzak util-linux-2.23.2/libsmartcols/docs/version.xml.in
|
||
|
--- util-linux-2.23.2/libsmartcols/docs/version.xml.in.kzak 2014-09-25 14:41:48.985843877 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/docs/version.xml.in 2014-09-25 14:41:48.984843867 +0200
|
||
|
@@ -0,0 +1 @@
|
||
|
+@VERSION@
|
||
|
diff -up util-linux-2.23.2/libsmartcols/Makemodule.am.kzak util-linux-2.23.2/libsmartcols/Makemodule.am
|
||
|
--- util-linux-2.23.2/libsmartcols/Makemodule.am.kzak 2014-09-25 14:41:48.983843858 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/Makemodule.am 2014-09-25 14:41:48.983843858 +0200
|
||
|
@@ -0,0 +1,14 @@
|
||
|
+if BUILD_LIBSMARTCOLS
|
||
|
+
|
||
|
+include libsmartcols/src/Makemodule.am
|
||
|
+
|
||
|
+if ENABLE_GTK_DOC
|
||
|
+# Docs uses separate Makefiles
|
||
|
+SUBDIRS += libsmartcols/docs
|
||
|
+endif
|
||
|
+
|
||
|
+# noinst for RHEL7: pkgconfig_DATA += libsmartcols/smartcols.pc
|
||
|
+PATHFILES += libsmartcols/smartcols.pc
|
||
|
+EXTRA_DIST += libsmartcols/COPYING
|
||
|
+
|
||
|
+endif # BUILD_LIBSMARTCOLS
|
||
|
diff -up util-linux-2.23.2/libsmartcols/smartcols.pc.in.kzak util-linux-2.23.2/libsmartcols/smartcols.pc.in
|
||
|
--- util-linux-2.23.2/libsmartcols/smartcols.pc.in.kzak 2014-09-25 14:41:48.985843877 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/smartcols.pc.in 2014-09-25 14:41:48.985843877 +0200
|
||
|
@@ -0,0 +1,10 @@
|
||
|
+prefix=@prefix@
|
||
|
+exec_prefix=@exec_prefix@
|
||
|
+libdir=@usrlib_execdir@
|
||
|
+includedir=@includedir@
|
||
|
+
|
||
|
+Name: smartcols
|
||
|
+Description: table or tree library
|
||
|
+Version: @LIBSMARTCOLS_VERSION@
|
||
|
+Cflags: -I${includedir}/libsmartcols
|
||
|
+Libs: -L${libdir} -lsmartcols
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/cell.c.kzak util-linux-2.23.2/libsmartcols/src/cell.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/cell.c.kzak 2014-09-25 14:41:48.986843886 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/cell.c 2014-09-25 14:41:48.986843886 +0200
|
||
|
@@ -0,0 +1,242 @@
|
||
|
+/*
|
||
|
+ * cell.c - functions for table handling at the cell level
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: cell
|
||
|
+ * @title: Cell
|
||
|
+ * @short_description: cell API
|
||
|
+ *
|
||
|
+ * An API to access and modify per-cell data and information. Note that cell is
|
||
|
+ * always part of the line. If you destroy (un-reference) a line than it
|
||
|
+ * destroys all line cells too.
|
||
|
+ */
|
||
|
+
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+#include <ctype.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+/*
|
||
|
+ * The cell has no ref-counting, free() and new() functions. All is
|
||
|
+ * handled by libscols_line.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_reset_cell:
|
||
|
+ * @ce: pointer to a struct libscols_cell instance
|
||
|
+ *
|
||
|
+ * Frees the cell's internal data and resets its status.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_reset_cell(struct libscols_cell *ce)
|
||
|
+{
|
||
|
+ assert(ce);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ /*DBG(CELL, ul_debugobj(ce, "reset"));*/
|
||
|
+ free(ce->data);
|
||
|
+ free(ce->color);
|
||
|
+ memset(ce, 0, sizeof(*ce));
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_set_data:
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ * @str: data (used for scols_printtable())
|
||
|
+ *
|
||
|
+ * Stores a copy of the @str in @ce.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_cell_set_data(struct libscols_cell *ce, const char *str)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(ce);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+ if (str) {
|
||
|
+ p = strdup(str);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ free(ce->data);
|
||
|
+ ce->data = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_refer_data:
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ * @str: data (used for scols_printtable())
|
||
|
+ *
|
||
|
+ * Adds a reference to @str to @ce. The pointer is deallocated by
|
||
|
+ * scols_reset_cell() or scols_unref_line(). This function is mostly designed
|
||
|
+ * for situations when the data for the cell are already composed in allocated
|
||
|
+ * memory (e.g. asprintf()) to avoid extra unnecessary strdup().
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_cell_refer_data(struct libscols_cell *ce, char *str)
|
||
|
+{
|
||
|
+ assert(ce);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+ free(ce->data);
|
||
|
+ ce->data = str;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_get_data:
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ *
|
||
|
+ * Returns: data in @ce or NULL.
|
||
|
+ */
|
||
|
+const char *scols_cell_get_data(const struct libscols_cell *ce)
|
||
|
+{
|
||
|
+ assert(ce);
|
||
|
+ return ce ? ce->data : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_set_userdata:
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ * @data: private user data
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_cell_set_userdata(struct libscols_cell *ce, void *data)
|
||
|
+{
|
||
|
+ assert(ce);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+ ce->userdata = data;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_get_userdata
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ *
|
||
|
+ * Returns: user data
|
||
|
+ */
|
||
|
+void *scols_cell_get_userdata(struct libscols_cell *ce)
|
||
|
+{
|
||
|
+ return ce ? ce->userdata : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cmpstr_cells:
|
||
|
+ * @a: pointer to cell
|
||
|
+ * @b: pointer to cell
|
||
|
+ * @data: unused pointer to private data (defined by API)
|
||
|
+ *
|
||
|
+ * Compares cells data by strcmp(). The function is designed for
|
||
|
+ * scols_column_set_cmpfunc() and scols_sort_table().
|
||
|
+ *
|
||
|
+ * Returns: follows strcmp() return values.
|
||
|
+ */
|
||
|
+int scols_cmpstr_cells(struct libscols_cell *a,
|
||
|
+ struct libscols_cell *b,
|
||
|
+ __attribute__((__unused__)) void *data)
|
||
|
+{
|
||
|
+ const char *adata, *bdata;
|
||
|
+
|
||
|
+ if (a == b)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ adata = scols_cell_get_data(a);
|
||
|
+ bdata = scols_cell_get_data(b);
|
||
|
+
|
||
|
+ if (adata == NULL && bdata == NULL)
|
||
|
+ return 0;
|
||
|
+ if (adata == NULL)
|
||
|
+ return -1;
|
||
|
+ if (bdata == NULL)
|
||
|
+ return 1;
|
||
|
+ return strcmp(adata, bdata);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_set_color:
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ * @color: ESC sequence
|
||
|
+ *
|
||
|
+ * Set the color of @ce to @color.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_cell_set_color(struct libscols_cell *ce, const char *color)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(ce);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+ if (color) {
|
||
|
+ p = strdup(color);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ free(ce->color);
|
||
|
+ ce->color = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_get_color:
|
||
|
+ * @ce: a pointer to a struct libscols_cell instance
|
||
|
+ *
|
||
|
+ * Returns: the current color of @ce.
|
||
|
+ */
|
||
|
+const char *scols_cell_get_color(const struct libscols_cell *ce)
|
||
|
+{
|
||
|
+ assert(ce);
|
||
|
+ return ce ? ce->color : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_cell_copy_content:
|
||
|
+ * @dest: a pointer to a struct libscols_cell instance
|
||
|
+ * @src: a pointer to an immutable struct libscols_cell instance
|
||
|
+ *
|
||
|
+ * Copy the contents of @src into @dest.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_cell_copy_content(struct libscols_cell *dest,
|
||
|
+ const struct libscols_cell *src)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ assert(dest);
|
||
|
+ assert(src);
|
||
|
+
|
||
|
+ rc = scols_cell_set_data(dest, scols_cell_get_data(src));
|
||
|
+ if (!rc)
|
||
|
+ rc = scols_cell_set_color(dest, scols_cell_get_color(src));
|
||
|
+ if (!rc)
|
||
|
+ dest->userdata = src->userdata;
|
||
|
+
|
||
|
+ DBG(CELL, ul_debugobj((void *) src, "copy into %p", dest));
|
||
|
+ return rc;
|
||
|
+}
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/column.c.kzak util-linux-2.23.2/libsmartcols/src/column.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/column.c.kzak 2014-09-25 14:41:48.986843886 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/column.c 2014-09-25 14:41:48.986843886 +0200
|
||
|
@@ -0,0 +1,337 @@
|
||
|
+/*
|
||
|
+ * column.c - functions for table handling at the column level
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: column
|
||
|
+ * @title: Column
|
||
|
+ * @short_description: column API
|
||
|
+ *
|
||
|
+ * An API to access and modify per-column data and information.
|
||
|
+ */
|
||
|
+
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+#include <ctype.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_new_column:
|
||
|
+ *
|
||
|
+ * Allocates space for a new column.
|
||
|
+ *
|
||
|
+ * Returns: a pointer to a new struct libscols_cell instance, NULL in case of an ENOMEM error.
|
||
|
+ */
|
||
|
+struct libscols_column *scols_new_column(void)
|
||
|
+{
|
||
|
+ struct libscols_column *cl;
|
||
|
+
|
||
|
+ cl = calloc(1, sizeof(*cl));
|
||
|
+ if (!cl)
|
||
|
+ return NULL;
|
||
|
+ DBG(COL, ul_debugobj(cl, "alloc"));
|
||
|
+ cl->refcount = 1;
|
||
|
+ INIT_LIST_HEAD(&cl->cl_columns);
|
||
|
+ return cl;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_ref_column:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Increases the refcount of @cl.
|
||
|
+ */
|
||
|
+void scols_ref_column(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ if (cl)
|
||
|
+ cl->refcount++;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_unref_column:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Decreases the refcount of @cl. When the count falls to zero, the instance
|
||
|
+ * is automatically deallocated.
|
||
|
+ */
|
||
|
+void scols_unref_column(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ if (cl && --cl->refcount <= 0) {
|
||
|
+ DBG(COL, ul_debugobj(cl, "dealloc"));
|
||
|
+ list_del(&cl->cl_columns);
|
||
|
+ scols_reset_cell(&cl->header);
|
||
|
+ free(cl->color);
|
||
|
+ free(cl);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_copy_column:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Creates a new column and copies @cl's data over to it.
|
||
|
+ *
|
||
|
+ * Returns: a pointer to a new struct libscols_column instance.
|
||
|
+ */
|
||
|
+struct libscols_column *scols_copy_column(const struct libscols_column *cl)
|
||
|
+{
|
||
|
+ struct libscols_column *ret;
|
||
|
+
|
||
|
+ assert (cl);
|
||
|
+ if (!cl)
|
||
|
+ return NULL;
|
||
|
+ ret = scols_new_column();
|
||
|
+ if (!ret)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ DBG(COL, ul_debugobj((void *) cl, "copy to %p", ret));
|
||
|
+
|
||
|
+ if (scols_column_set_color(ret, cl->color))
|
||
|
+ goto err;
|
||
|
+ if (scols_cell_copy_content(&ret->header, &cl->header))
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ ret->width = cl->width;
|
||
|
+ ret->width_min = cl->width_min;
|
||
|
+ ret->width_max = cl->width_max;
|
||
|
+ ret->width_avg = cl->width_avg;
|
||
|
+ ret->width_hint = cl->width_hint;
|
||
|
+ ret->flags = cl->flags;
|
||
|
+ ret->is_extreme = cl->is_extreme;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+err:
|
||
|
+ scols_unref_column(ret);
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_set_whint:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ * @whint: a width hint
|
||
|
+ *
|
||
|
+ * Sets the width hint of column @cl to @whint.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_set_whint(struct libscols_column *cl, double whint)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ cl->width_hint = whint;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_get_whint:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Returns: The width hint of column @cl, a negative value in case of an error.
|
||
|
+ */
|
||
|
+double scols_column_get_whint(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ return cl ? cl->width_hint : -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_set_flags:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ * @flags: a flag mask
|
||
|
+ *
|
||
|
+ * Sets the flags of @cl to @flags.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_set_flags(struct libscols_column *cl, int flags)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ cl->flags = flags;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_get_flags:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Returns: The flag mask of @cl, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_get_flags(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ return cl ? cl->flags : -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_get_header:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Returns: A pointer to a struct libscols_cell instance, representing the
|
||
|
+ * header info of column @cl or NULL in case of an error.
|
||
|
+ */
|
||
|
+struct libscols_cell *scols_column_get_header(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ return cl ? &cl->header : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_set_color:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ * @color: ESC sequence
|
||
|
+ *
|
||
|
+ * The default color for data cells and column header.
|
||
|
+ *
|
||
|
+ * If you want to set header specific color then use scols_column_get_header()
|
||
|
+ * and scols_cell_set_color().
|
||
|
+ *
|
||
|
+ * If you want to set data cell specific color the use scols_line_get_cell() +
|
||
|
+ * scols_cell_set_color().
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_set_color(struct libscols_column *cl, const char *color)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+ if (color) {
|
||
|
+ p = strdup(color);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ free(cl->color);
|
||
|
+ cl->color = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_get_color:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Returns: The current color setting of the column @cl.
|
||
|
+ */
|
||
|
+const char *scols_column_get_color(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ return cl ? cl->color : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_set_cmpfunc:
|
||
|
+ * @cl: column
|
||
|
+ * @cmp: pointer to compare function
|
||
|
+ * @data: private data for cmp function
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_set_cmpfunc(struct libscols_column *cl,
|
||
|
+ int (*cmp)(struct libscols_cell *,
|
||
|
+ struct libscols_cell *,
|
||
|
+ void *),
|
||
|
+ void *data)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ cl->cmpfunc = cmp;
|
||
|
+ cl->cmpfunc_data = data;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_column_is_trunc:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Gets the value of @cl's flag trunc.
|
||
|
+ *
|
||
|
+ * Returns: trunc flag value, negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_is_trunc(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+ return cl->flags & SCOLS_FL_TRUNC;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * scols_column_is_tree:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Gets the value of @cl's flag tree.
|
||
|
+ *
|
||
|
+ * Returns: tree flag value, negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_is_tree(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+ return cl->flags & SCOLS_FL_TREE;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * scols_column_is_right:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Gets the value of @cl's flag right.
|
||
|
+ *
|
||
|
+ * Returns: right flag value, negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_is_right(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+ return cl->flags & SCOLS_FL_RIGHT;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * scols_column_is_strict_width:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Gets the value of @cl's flag strict_width.
|
||
|
+ *
|
||
|
+ * Returns: strict_width flag value, negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_is_strict_width(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+ return cl->flags & SCOLS_FL_STRICTWIDTH;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * scols_column_is_noextremes:
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Gets the value of @cl's flag no_extremes.
|
||
|
+ *
|
||
|
+ * Returns: no_extremes flag value, negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_column_is_noextremes(struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(cl);
|
||
|
+ if (!cl)
|
||
|
+ return -EINVAL;
|
||
|
+ return cl->flags & SCOLS_FL_NOEXTREMES;
|
||
|
+}
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/.gitignore.kzak util-linux-2.23.2/libsmartcols/src/.gitignore
|
||
|
--- util-linux-2.23.2/libsmartcols/src/.gitignore.kzak 2014-09-25 14:41:48.985843877 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/.gitignore 2014-09-25 14:41:48.985843877 +0200
|
||
|
@@ -0,0 +1 @@
|
||
|
+libsmartcols.h
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/init.c.kzak util-linux-2.23.2/libsmartcols/src/init.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/init.c.kzak 2014-09-25 14:41:48.987843896 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/init.c 2014-09-25 14:41:48.987843896 +0200
|
||
|
@@ -0,0 +1,52 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: init
|
||
|
+ * @title: Library initialization
|
||
|
+ * @short_description: initialize debugging
|
||
|
+ *
|
||
|
+ * The library debug stuff.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <stdarg.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+UL_DEBUG_DEFINE_MASK(libsmartcols);
|
||
|
+
|
||
|
+static const struct dbg_mask libsmartcols_masknames [] = {
|
||
|
+ { "all", SCOLS_DEBUG_ALL },
|
||
|
+ { "cell", SCOLS_DEBUG_CELL },
|
||
|
+ { "line", SCOLS_DEBUG_LINE },
|
||
|
+ { "tab", SCOLS_DEBUG_TAB },
|
||
|
+ { "col", SCOLS_DEBUG_COL },
|
||
|
+ { "buff", SCOLS_DEBUG_BUFF },
|
||
|
+ { NULL, 0 }
|
||
|
+};
|
||
|
+/**
|
||
|
+ * scols_init_debug:
|
||
|
+ * @mask: debug mask (0xffff to enable full debugging)
|
||
|
+ *
|
||
|
+ * If the @mask is not specified, then this function reads
|
||
|
+ * the LIBSMARTCOLS_DEBUG environment variable to get the mask.
|
||
|
+ *
|
||
|
+ * Already initialized debugging stuff cannot be changed. Calling
|
||
|
+ * this function twice has no effect.
|
||
|
+ */
|
||
|
+void scols_init_debug(int mask)
|
||
|
+{
|
||
|
+ __UL_INIT_DEBUG(libsmartcols, SCOLS_DEBUG_, mask, LIBSMARTCOLS_DEBUG);
|
||
|
+
|
||
|
+ if (libsmartcols_debug_mask != SCOLS_DEBUG_INIT) {
|
||
|
+ const char *ver = NULL;
|
||
|
+
|
||
|
+ scols_get_library_version(&ver);
|
||
|
+
|
||
|
+ DBG(INIT, ul_debug("library version: %s", ver));
|
||
|
+ }
|
||
|
+}
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/iter.c.kzak util-linux-2.23.2/libsmartcols/src/iter.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/iter.c.kzak 2014-09-25 14:41:48.987843896 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/iter.c 2014-09-25 14:41:48.987843896 +0200
|
||
|
@@ -0,0 +1,74 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2009-2014 Karel Zak <kzak@redhat.com>
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: iter
|
||
|
+ * @title: Iterator
|
||
|
+ * @short_description: unified iterator
|
||
|
+ *
|
||
|
+ * The iterator keeps the direction and the last position
|
||
|
+ * for access to the internal library tables/lists.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <string.h>
|
||
|
+#include <stdlib.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_new_iter:
|
||
|
+ * @direction: SCOLS_INTER_{FOR,BACK}WARD direction
|
||
|
+ *
|
||
|
+ * Returns: newly allocated generic libmount iterator.
|
||
|
+ */
|
||
|
+struct libscols_iter *scols_new_iter(int direction)
|
||
|
+{
|
||
|
+ struct libscols_iter *itr = calloc(1, sizeof(*itr));
|
||
|
+ if (!itr)
|
||
|
+ return NULL;
|
||
|
+ itr->direction = direction;
|
||
|
+ return itr;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_free_iter:
|
||
|
+ * @itr: iterator pointer
|
||
|
+ *
|
||
|
+ * Deallocates the iterator.
|
||
|
+ */
|
||
|
+void scols_free_iter(struct libscols_iter *itr)
|
||
|
+{
|
||
|
+ free(itr);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_reset_iter:
|
||
|
+ * @itr: iterator pointer
|
||
|
+ * @direction: SCOLS_INTER_{FOR,BACK}WARD or -1 to keep the direction unchanged
|
||
|
+ *
|
||
|
+ * Resets the iterator.
|
||
|
+ */
|
||
|
+void scols_reset_iter(struct libscols_iter *itr, int direction)
|
||
|
+{
|
||
|
+ if (direction == -1)
|
||
|
+ direction = itr->direction;
|
||
|
+
|
||
|
+ memset(itr, 0, sizeof(*itr));
|
||
|
+ itr->direction = direction;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_iter_get_direction:
|
||
|
+ * @itr: iterator pointer
|
||
|
+ *
|
||
|
+ * Returns: SCOLS_INTER_{FOR,BACK}WARD
|
||
|
+ */
|
||
|
+int scols_iter_get_direction(struct libscols_iter *itr)
|
||
|
+{
|
||
|
+ return itr->direction;
|
||
|
+}
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in.kzak util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in
|
||
|
--- util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in.kzak 2014-09-25 14:41:48.988843905 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in 2014-09-25 14:41:48.988843905 +0200
|
||
|
@@ -0,0 +1,229 @@
|
||
|
+/*
|
||
|
+ * Prints table or tree.
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+#ifndef _LIBSMARTCOLS_H
|
||
|
+#define _LIBSMARTCOLS_H
|
||
|
+
|
||
|
+#ifdef __cplusplus
|
||
|
+extern "C" {
|
||
|
+#endif
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <stdio.h>
|
||
|
+#include <sys/types.h>
|
||
|
+
|
||
|
+/**
|
||
|
+ * LIBSMARTCOLS_VERSION:
|
||
|
+ *
|
||
|
+ * Library version string
|
||
|
+ */
|
||
|
+#define LIBSMARTCOLS_VERSION "@LIBSMARTCOLS_VERSION@"
|
||
|
+
|
||
|
+/**
|
||
|
+ * libscols_iter:
|
||
|
+ *
|
||
|
+ * Generic iterator
|
||
|
+ */
|
||
|
+struct libscols_iter;
|
||
|
+
|
||
|
+/**
|
||
|
+ * libscols_symbols:
|
||
|
+ *
|
||
|
+ * Symbol groups for printing tree hierarchies
|
||
|
+ */
|
||
|
+struct libscols_symbols;
|
||
|
+
|
||
|
+/**
|
||
|
+ * libscols_cell:
|
||
|
+ *
|
||
|
+ * A cell - the smallest library object
|
||
|
+ */
|
||
|
+struct libscols_cell;
|
||
|
+
|
||
|
+/**
|
||
|
+ * libscols_line:
|
||
|
+ *
|
||
|
+ * A line - an array of cells
|
||
|
+ */
|
||
|
+struct libscols_line;
|
||
|
+
|
||
|
+/**
|
||
|
+ * libscols_table:
|
||
|
+ *
|
||
|
+ * A table - The most abstract object, encapsulating lines, columns, symbols and cells
|
||
|
+ */
|
||
|
+struct libscols_table;
|
||
|
+
|
||
|
+/**
|
||
|
+ * libscols_column:
|
||
|
+ *
|
||
|
+ * A column - defines the number of columns and column names
|
||
|
+ */
|
||
|
+struct libscols_column;
|
||
|
+
|
||
|
+/* iter.c */
|
||
|
+enum {
|
||
|
+
|
||
|
+ SCOLS_ITER_FORWARD = 0,
|
||
|
+ SCOLS_ITER_BACKWARD
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * Column flags
|
||
|
+ */
|
||
|
+enum {
|
||
|
+ SCOLS_FL_TRUNC = (1 << 0), /* truncate fields data if necessary */
|
||
|
+ SCOLS_FL_TREE = (1 << 1), /* use tree "ascii art" */
|
||
|
+ SCOLS_FL_RIGHT = (1 << 2), /* align to the right */
|
||
|
+ SCOLS_FL_STRICTWIDTH = (1 << 3), /* don't reduce width if column is empty */
|
||
|
+ SCOLS_FL_NOEXTREMES = (1 << 4), /* ignore extreme fields when count column width*/
|
||
|
+};
|
||
|
+
|
||
|
+extern struct libscols_iter *scols_new_iter(int direction);
|
||
|
+extern void scols_free_iter(struct libscols_iter *itr);
|
||
|
+extern void scols_reset_iter(struct libscols_iter *itr, int direction);
|
||
|
+extern int scols_iter_get_direction(struct libscols_iter *itr);
|
||
|
+
|
||
|
+/* init.c */
|
||
|
+extern void scols_init_debug(int mask);
|
||
|
+
|
||
|
+/* version.c */
|
||
|
+extern int scols_parse_version_string(const char *ver_string);
|
||
|
+extern int scols_get_library_version(const char **ver_string);
|
||
|
+
|
||
|
+/* symbols.c */
|
||
|
+extern struct libscols_symbols *scols_new_symbols(void);
|
||
|
+extern void scols_ref_symbols(struct libscols_symbols *sy);
|
||
|
+extern void scols_unref_symbols(struct libscols_symbols *sy);
|
||
|
+extern struct libscols_symbols *scols_copy_symbols(const struct libscols_symbols *sb);
|
||
|
+extern int scols_symbols_set_branch(struct libscols_symbols *sb, const char *str);
|
||
|
+extern int scols_symbols_set_vertical(struct libscols_symbols *sb, const char *str);
|
||
|
+extern int scols_symbols_set_right(struct libscols_symbols *sb, const char *str);
|
||
|
+
|
||
|
+/* cell.c */
|
||
|
+extern int scols_reset_cell(struct libscols_cell *ce);
|
||
|
+extern int scols_cell_copy_content(struct libscols_cell *dest,
|
||
|
+ const struct libscols_cell *src);
|
||
|
+extern int scols_cell_set_data(struct libscols_cell *ce, const char *str);
|
||
|
+extern int scols_cell_refer_data(struct libscols_cell *ce, char *str);
|
||
|
+extern const char *scols_cell_get_data(const struct libscols_cell *ce);
|
||
|
+extern int scols_cell_set_color(struct libscols_cell *ce, const char *color);
|
||
|
+extern const char *scols_cell_get_color(const struct libscols_cell *ce);
|
||
|
+
|
||
|
+extern void *scols_cell_get_userdata(struct libscols_cell *ce);
|
||
|
+extern int scols_cell_set_userdata(struct libscols_cell *ce, void *data);
|
||
|
+
|
||
|
+extern int scols_cmpstr_cells(struct libscols_cell *a,
|
||
|
+ struct libscols_cell *b, void *data);
|
||
|
+/* column.c */
|
||
|
+extern int scols_column_is_tree(struct libscols_column *cl);
|
||
|
+extern int scols_column_is_trunc(struct libscols_column *cl);
|
||
|
+extern int scols_column_is_right(struct libscols_column *cl);
|
||
|
+extern int scols_column_is_strict_width(struct libscols_column *cl);
|
||
|
+extern int scols_column_is_noextremes(struct libscols_column *cl);
|
||
|
+
|
||
|
+extern int scols_column_set_flags(struct libscols_column *cl, int flags);
|
||
|
+extern int scols_column_get_flags(struct libscols_column *cl);
|
||
|
+extern struct libscols_column *scols_new_column(void);
|
||
|
+extern void scols_ref_column(struct libscols_column *cl);
|
||
|
+extern void scols_unref_column(struct libscols_column *cl);
|
||
|
+extern struct libscols_column *scols_copy_column(const struct libscols_column *cl);
|
||
|
+extern int scols_column_set_whint(struct libscols_column *cl, double whint);
|
||
|
+extern double scols_column_get_whint(struct libscols_column *cl);
|
||
|
+extern struct libscols_cell *scols_column_get_header(struct libscols_column *cl);
|
||
|
+extern int scols_column_set_color(struct libscols_column *cl, const char *color);
|
||
|
+extern const char *scols_column_get_color(struct libscols_column *cl);
|
||
|
+
|
||
|
+extern int scols_column_set_cmpfunc(struct libscols_column *cl,
|
||
|
+ int (*cmp)(struct libscols_cell *a,
|
||
|
+ struct libscols_cell *b, void *),
|
||
|
+ void *data);
|
||
|
+
|
||
|
+/* line.c */
|
||
|
+extern struct libscols_line *scols_new_line(void);
|
||
|
+extern void scols_ref_line(struct libscols_line *ln);
|
||
|
+extern void scols_unref_line(struct libscols_line *ln);
|
||
|
+extern int scols_line_alloc_cells(struct libscols_line *ln, size_t n);
|
||
|
+extern void scols_line_free_cells(struct libscols_line *ln);
|
||
|
+extern int scols_line_set_userdata(struct libscols_line *ln, void *data);
|
||
|
+extern void *scols_line_get_userdata(struct libscols_line *ln);
|
||
|
+extern int scols_line_remove_child(struct libscols_line *ln, struct libscols_line *child);
|
||
|
+extern int scols_line_add_child(struct libscols_line *ln, struct libscols_line *child);
|
||
|
+extern int scols_line_has_children(struct libscols_line *ln);
|
||
|
+extern int scols_line_next_child(struct libscols_line *ln,
|
||
|
+ struct libscols_iter *itr, struct libscols_line **chld);
|
||
|
+extern struct libscols_line *scols_line_get_parent(struct libscols_line *ln);
|
||
|
+extern int scols_line_set_color(struct libscols_line *ln, const char *color);
|
||
|
+extern const char *scols_line_get_color(struct libscols_line *ln);
|
||
|
+extern size_t scols_line_get_ncells(struct libscols_line *ln);
|
||
|
+extern struct libscols_cell *scols_line_get_cell(struct libscols_line *ln, size_t n);
|
||
|
+extern struct libscols_cell *scols_line_get_column_cell(
|
||
|
+ struct libscols_line *ln,
|
||
|
+ struct libscols_column *cl);
|
||
|
+extern int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data);
|
||
|
+extern int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data);
|
||
|
+extern struct libscols_line *scols_copy_line(struct libscols_line *ln);
|
||
|
+
|
||
|
+/* table */
|
||
|
+extern int scols_table_colors_wanted(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_raw(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_ascii(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_noheadings(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_empty(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_export(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_maxout(struct libscols_table *tb);
|
||
|
+extern int scols_table_is_tree(struct libscols_table *tb);
|
||
|
+
|
||
|
+extern int scols_table_enable_colors(struct libscols_table *tb, int enable);
|
||
|
+extern int scols_table_enable_raw(struct libscols_table *tb, int enable);
|
||
|
+extern int scols_table_enable_ascii(struct libscols_table *tb, int enable);
|
||
|
+extern int scols_table_enable_noheadings(struct libscols_table *tb, int enable);
|
||
|
+extern int scols_table_enable_export(struct libscols_table *tb, int enable);
|
||
|
+extern int scols_table_enable_maxout(struct libscols_table *tb, int enable);
|
||
|
+
|
||
|
+extern int scols_table_set_column_separator(struct libscols_table *tb, const char *sep);
|
||
|
+extern int scols_table_set_line_separator(struct libscols_table *tb, const char *sep);
|
||
|
+
|
||
|
+extern struct libscols_table *scols_new_table(void);
|
||
|
+extern void scols_ref_table(struct libscols_table *tb);
|
||
|
+extern void scols_unref_table(struct libscols_table *tb);
|
||
|
+extern int scols_table_add_column(struct libscols_table *tb, struct libscols_column *cl);
|
||
|
+extern int scols_table_remove_column(struct libscols_table *tb, struct libscols_column *cl);
|
||
|
+extern int scols_table_remove_columns(struct libscols_table *tb);
|
||
|
+extern struct libscols_column *scols_table_new_column(struct libscols_table *tb, const char *name, double whint, int flags);
|
||
|
+extern int scols_table_next_column(struct libscols_table *tb, struct libscols_iter *itr, struct libscols_column **cl);
|
||
|
+extern char *scols_table_get_column_separator(struct libscols_table *tb);
|
||
|
+extern char *scols_table_get_line_separator(struct libscols_table *tb);
|
||
|
+extern int scols_table_get_ncols(struct libscols_table *tb);
|
||
|
+extern int scols_table_get_nlines(struct libscols_table *tb);
|
||
|
+extern struct libscols_column *scols_table_get_column(struct libscols_table *tb, size_t n);
|
||
|
+extern int scols_table_add_line(struct libscols_table *tb, struct libscols_line *ln);
|
||
|
+extern int scols_table_remove_line(struct libscols_table *tb, struct libscols_line *ln);
|
||
|
+extern void scols_table_remove_lines(struct libscols_table *tb);
|
||
|
+extern int scols_table_next_line(struct libscols_table *tb, struct libscols_iter *itr, struct libscols_line **ln);
|
||
|
+extern struct libscols_line *scols_table_new_line(struct libscols_table *tb, struct libscols_line *parent);
|
||
|
+extern struct libscols_line *scols_table_get_line(struct libscols_table *tb, size_t n);
|
||
|
+extern struct libscols_table *scols_copy_table(struct libscols_table *tb);
|
||
|
+extern int scols_table_set_symbols(struct libscols_table *tb, struct libscols_symbols *sy);
|
||
|
+
|
||
|
+extern int scols_table_set_stream(struct libscols_table *tb, FILE *stream);
|
||
|
+extern FILE *scols_table_get_stream(struct libscols_table *tb);
|
||
|
+extern int scols_table_reduce_termwidth(struct libscols_table *tb, size_t reduce);
|
||
|
+
|
||
|
+extern int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl);
|
||
|
+
|
||
|
+/* table_print.c */
|
||
|
+extern int scols_print_table(struct libscols_table *tb);
|
||
|
+extern int scols_print_table_to_string(struct libscols_table *tb, char **data);
|
||
|
+
|
||
|
+#ifdef __cplusplus
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+#endif /* _LIBSMARTCOLS_H */
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/libsmartcols.sym.kzak util-linux-2.23.2/libsmartcols/src/libsmartcols.sym
|
||
|
--- util-linux-2.23.2/libsmartcols/src/libsmartcols.sym.kzak 2014-09-25 14:41:48.988843905 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/libsmartcols.sym 2014-09-25 14:41:48.988843905 +0200
|
||
|
@@ -0,0 +1,112 @@
|
||
|
+/*
|
||
|
+ * symbols since util-linux 2.25
|
||
|
+ */
|
||
|
+SMARTCOLS_2.25 {
|
||
|
+global:
|
||
|
+ scols_cell_copy_content;
|
||
|
+ scols_cell_get_color;
|
||
|
+ scols_cell_get_data;
|
||
|
+ scols_cell_get_userdata;
|
||
|
+ scols_cell_refer_data;
|
||
|
+ scols_cell_set_color;
|
||
|
+ scols_cell_set_data;
|
||
|
+ scols_cell_set_userdata;
|
||
|
+ scols_cmpstr_cells;
|
||
|
+ scols_column_get_color;
|
||
|
+ scols_column_get_flags;
|
||
|
+ scols_column_get_header;
|
||
|
+ scols_column_get_whint;
|
||
|
+ scols_column_is_noextremes;
|
||
|
+ scols_column_is_right;
|
||
|
+ scols_column_is_strict_width;
|
||
|
+ scols_column_is_tree;
|
||
|
+ scols_column_is_trunc;
|
||
|
+ scols_column_set_cmpfunc;
|
||
|
+ scols_column_set_color;
|
||
|
+ scols_column_set_flags;
|
||
|
+ scols_column_set_whint;
|
||
|
+ scols_copy_column;
|
||
|
+ scols_copy_line;
|
||
|
+ scols_copy_symbols;
|
||
|
+ scols_copy_table;
|
||
|
+ scols_free_iter;
|
||
|
+ scols_get_library_version;
|
||
|
+ scols_init_debug;
|
||
|
+ scols_iter_get_direction;
|
||
|
+ scols_line_add_child;
|
||
|
+ scols_line_alloc_cells;
|
||
|
+ scols_line_free_cells;
|
||
|
+ scols_line_get_cell;
|
||
|
+ scols_line_get_color;
|
||
|
+ scols_line_get_column_cell;
|
||
|
+ scols_line_get_ncells;
|
||
|
+ scols_line_get_parent;
|
||
|
+ scols_line_get_userdata;
|
||
|
+ scols_line_has_children;
|
||
|
+ scols_line_next_child;
|
||
|
+ scols_line_refer_data;
|
||
|
+ scols_line_remove_child;
|
||
|
+ scols_line_set_color;
|
||
|
+ scols_line_set_data;
|
||
|
+ scols_line_set_userdata;
|
||
|
+ scols_new_column;
|
||
|
+ scols_new_iter;
|
||
|
+ scols_new_line;
|
||
|
+ scols_new_symbols;
|
||
|
+ scols_new_table;
|
||
|
+ scols_parse_version_string;
|
||
|
+ scols_print_table;
|
||
|
+ scols_print_table_to_string;
|
||
|
+ scols_ref_column;
|
||
|
+ scols_ref_line;
|
||
|
+ scols_ref_symbols;
|
||
|
+ scols_ref_table;
|
||
|
+ scols_reset_cell;
|
||
|
+ scols_reset_iter;
|
||
|
+ scols_sort_table;
|
||
|
+ scols_symbols_set_branch;
|
||
|
+ scols_symbols_set_right;
|
||
|
+ scols_symbols_set_vertical;
|
||
|
+ scols_table_add_column;
|
||
|
+ scols_table_add_line;
|
||
|
+ scols_table_colors_wanted;
|
||
|
+ scols_table_enable_ascii;
|
||
|
+ scols_table_enable_colors;
|
||
|
+ scols_table_enable_export;
|
||
|
+ scols_table_enable_maxout;
|
||
|
+ scols_table_enable_noheadings;
|
||
|
+ scols_table_enable_raw;
|
||
|
+ scols_table_get_column;
|
||
|
+ scols_table_get_column_separator;
|
||
|
+ scols_table_get_line;
|
||
|
+ scols_table_get_line_separator;
|
||
|
+ scols_table_get_ncols;
|
||
|
+ scols_table_get_nlines;
|
||
|
+ scols_table_get_stream;
|
||
|
+ scols_table_is_ascii;
|
||
|
+ scols_table_is_empty;
|
||
|
+ scols_table_is_export;
|
||
|
+ scols_table_is_maxout;
|
||
|
+ scols_table_is_noheadings;
|
||
|
+ scols_table_is_raw;
|
||
|
+ scols_table_is_tree;
|
||
|
+ scols_table_new_column;
|
||
|
+ scols_table_new_line;
|
||
|
+ scols_table_next_column;
|
||
|
+ scols_table_next_line;
|
||
|
+ scols_table_reduce_termwidth;
|
||
|
+ scols_table_remove_column;
|
||
|
+ scols_table_remove_columns;
|
||
|
+ scols_table_remove_line;
|
||
|
+ scols_table_remove_lines;
|
||
|
+ scols_table_set_column_separator;
|
||
|
+ scols_table_set_line_separator;
|
||
|
+ scols_table_set_stream;
|
||
|
+ scols_table_set_symbols;
|
||
|
+ scols_unref_column;
|
||
|
+ scols_unref_line;
|
||
|
+ scols_unref_symbols;
|
||
|
+ scols_unref_table;
|
||
|
+local:
|
||
|
+ *;
|
||
|
+};
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/line.c.kzak util-linux-2.23.2/libsmartcols/src/line.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/line.c.kzak 2014-09-25 14:41:48.989843915 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/line.c 2014-09-25 14:41:48.989843915 +0200
|
||
|
@@ -0,0 +1,456 @@
|
||
|
+/*
|
||
|
+ * line.c - functions for table handling at the line level
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: line
|
||
|
+ * @title: Line
|
||
|
+ * @short_description: line API
|
||
|
+ *
|
||
|
+ * An API to access and modify per-line data and information.
|
||
|
+ */
|
||
|
+
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+#include <ctype.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_new_line:
|
||
|
+ *
|
||
|
+ * Note that the line is allocated without cells, the cells will be allocated
|
||
|
+ * later when you add the line to the table. If you want to use the line
|
||
|
+ * without table then you have to explicitly allocate the cells by
|
||
|
+ * scols_line_alloc_cells().
|
||
|
+ *
|
||
|
+ * Returns: a pointer to a new struct libscols_line instance.
|
||
|
+ */
|
||
|
+struct libscols_line *scols_new_line(void)
|
||
|
+{
|
||
|
+ struct libscols_line *ln;
|
||
|
+
|
||
|
+ ln = calloc(1, sizeof(*ln));
|
||
|
+ if (!ln)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ DBG(LINE, ul_debugobj(ln, "alloc"));
|
||
|
+ ln->refcount = 1;
|
||
|
+ INIT_LIST_HEAD(&ln->ln_lines);
|
||
|
+ INIT_LIST_HEAD(&ln->ln_children);
|
||
|
+ INIT_LIST_HEAD(&ln->ln_branch);
|
||
|
+ return ln;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_ref_line:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Increases the refcount of @ln.
|
||
|
+ */
|
||
|
+void scols_ref_line(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ if (ln)
|
||
|
+ ln->refcount++;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_unref_line:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Decreases the refcount of @ln. When the count falls to zero, the instance
|
||
|
+ * is automatically deallocated.
|
||
|
+ */
|
||
|
+void scols_unref_line(struct libscols_line *ln)
|
||
|
+{
|
||
|
+
|
||
|
+ if (ln && --ln->refcount <= 0) {
|
||
|
+ DBG(CELL, ul_debugobj(ln, "dealloc"));
|
||
|
+ list_del(&ln->ln_lines);
|
||
|
+ list_del(&ln->ln_children);
|
||
|
+ scols_line_free_cells(ln);
|
||
|
+ free(ln->color);
|
||
|
+ free(ln);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_free_cells:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Frees the allocated cells referenced to by @ln.
|
||
|
+ */
|
||
|
+void scols_line_free_cells(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ if (!ln || !ln->cells)
|
||
|
+ return;
|
||
|
+
|
||
|
+ DBG(LINE, ul_debugobj(ln, "free cells"));
|
||
|
+
|
||
|
+ for (i = 0; i < ln->ncells; i++)
|
||
|
+ scols_reset_cell(&ln->cells[i]);
|
||
|
+
|
||
|
+ free(ln->cells);
|
||
|
+ ln->ncells = 0;
|
||
|
+ ln->cells = NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_alloc_cells:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @n: the number of elements
|
||
|
+ *
|
||
|
+ * Allocates space for @n cells. This function is optional,
|
||
|
+ * and libsmartcols automatically allocates necessary cells
|
||
|
+ * according to number of columns in the table when you add
|
||
|
+ * the line to the table. See scols_table_add_line().
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_alloc_cells(struct libscols_line *ln, size_t n)
|
||
|
+{
|
||
|
+ struct libscols_cell *ce;
|
||
|
+
|
||
|
+ assert(ln);
|
||
|
+
|
||
|
+ if (!ln)
|
||
|
+ return -EINVAL;
|
||
|
+ if (ln->ncells == n)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (!n) {
|
||
|
+ scols_line_free_cells(ln);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ DBG(LINE, ul_debugobj(ln, "alloc %zu cells", n));
|
||
|
+
|
||
|
+ ce = realloc(ln->cells, n * sizeof(struct libscols_cell));
|
||
|
+ if (!ce)
|
||
|
+ return -errno;
|
||
|
+
|
||
|
+ if (n > ln->ncells)
|
||
|
+ memset(ce + ln->ncells, 0,
|
||
|
+ (n - ln->ncells) * sizeof(struct libscols_cell));
|
||
|
+
|
||
|
+ ln->cells = ce;
|
||
|
+ ln->ncells = n;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_set_userdata:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @data: user data
|
||
|
+ *
|
||
|
+ * Binds @data to @ln.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_set_userdata(struct libscols_line *ln, void *data)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ if (!ln)
|
||
|
+ return -EINVAL;
|
||
|
+ ln->userdata = data;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_get_userdata:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+void *scols_line_get_userdata(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ return ln ? ln->userdata : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_remove_child:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @child: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Removes @child as a child of @ln.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_remove_child(struct libscols_line *ln, struct libscols_line *child)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ assert(child);
|
||
|
+
|
||
|
+ if (!ln || !child)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(LINE, ul_debugobj(ln, "remove child %p", child));
|
||
|
+
|
||
|
+ list_del_init(&child->ln_children);
|
||
|
+ child->parent = NULL;
|
||
|
+ scols_unref_line(child);
|
||
|
+
|
||
|
+ scols_unref_line(ln);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_add_child:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @child: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Sets @child as a child of @ln.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_add_child(struct libscols_line *ln, struct libscols_line *child)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ assert(child);
|
||
|
+
|
||
|
+ if (!ln || !child)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ /* unref old<->parent */
|
||
|
+ if (child->parent)
|
||
|
+ scols_line_remove_child(child->parent, child);
|
||
|
+
|
||
|
+ DBG(LINE, ul_debugobj(ln, "add child %p", child));
|
||
|
+
|
||
|
+ /* new reference from parent to child */
|
||
|
+ list_add_tail(&child->ln_children, &ln->ln_branch);
|
||
|
+ scols_ref_line(child);
|
||
|
+
|
||
|
+ /* new reference from child to parent */
|
||
|
+ child->parent = ln;
|
||
|
+ scols_ref_line(ln);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_get_parent:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Returns: a pointer to @ln's parent, NULL in case it has no parent or if there was an error.
|
||
|
+ */
|
||
|
+struct libscols_line *scols_line_get_parent(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ return ln ? ln->parent : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_has_children:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Returns: 1 if @ln has any children, otherwise 0.
|
||
|
+ */
|
||
|
+int scols_line_has_children(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ return ln ? !list_empty(&ln->ln_branch) : 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_next_child:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @itr: a pointer to a struct libscols_iter instance
|
||
|
+ * @chld: a pointer to a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Finds the next child and returns a pointer to it via @chld.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_next_child(struct libscols_line *ln,
|
||
|
+ struct libscols_iter *itr,
|
||
|
+ struct libscols_line **chld)
|
||
|
+{
|
||
|
+ int rc = 1;
|
||
|
+
|
||
|
+ if (!ln || !itr || !chld)
|
||
|
+ return -EINVAL;
|
||
|
+ *chld = NULL;
|
||
|
+
|
||
|
+ if (!itr->head)
|
||
|
+ SCOLS_ITER_INIT(itr, &ln->ln_branch);
|
||
|
+ if (itr->p != itr->head) {
|
||
|
+ SCOLS_ITER_ITERATE(itr, *chld, struct libscols_line, ln_children);
|
||
|
+ rc = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_set_color:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @color: ESC sequence
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_set_color(struct libscols_line *ln, const char *color)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(ln);
|
||
|
+ if (!ln)
|
||
|
+ return -EINVAL;
|
||
|
+ if (color) {
|
||
|
+ p = strdup(color);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ free(ln->color);
|
||
|
+ ln->color = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_get_color:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Returns: @ln's color string, NULL in case of an error.
|
||
|
+ */
|
||
|
+const char *scols_line_get_color(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ return ln ? ln->color : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_get_ncells:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Returns: @ln's number of cells
|
||
|
+ */
|
||
|
+size_t scols_line_get_ncells(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ return ln ? ln->ncells : 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_get_cell:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @n: cell number to retrieve
|
||
|
+ *
|
||
|
+ * Returns: the @n-th cell in @ln, NULL in case of an error.
|
||
|
+ */
|
||
|
+struct libscols_cell *scols_line_get_cell(struct libscols_line *ln,
|
||
|
+ size_t n)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+
|
||
|
+ if (!ln || n >= ln->ncells)
|
||
|
+ return NULL;
|
||
|
+ return &ln->cells[n];
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_get_column_cell:
|
||
|
+ * @ln: a pointer to a struct libscols_line instance
|
||
|
+ * @cl: pointer to cell
|
||
|
+ *
|
||
|
+ * Like scols_line_get_cell() by cell is referenced by column.
|
||
|
+ *
|
||
|
+ * Returns: the @n-th cell in @ln, NULL in case of an error.
|
||
|
+ */
|
||
|
+struct libscols_cell *scols_line_get_column_cell(
|
||
|
+ struct libscols_line *ln,
|
||
|
+ struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(ln);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ return scols_line_get_cell(ln, cl->seqnum);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_set_data:
|
||
|
+ * @ln: a pointer to a struct libscols_cell instance
|
||
|
+ * @n: number of the cell, whose data is to be set
|
||
|
+ * @data: actual data to set
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data)
|
||
|
+{
|
||
|
+ struct libscols_cell *ce = scols_line_get_cell(ln, n);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+ return scols_cell_set_data(ce, data);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_line_refer_data:
|
||
|
+ * @ln: a pointer to a struct libscols_cell instance
|
||
|
+ * @n: number of the cell which will refer to @data
|
||
|
+ * @data: actual data to refer to
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data)
|
||
|
+{
|
||
|
+ struct libscols_cell *ce = scols_line_get_cell(ln, n);
|
||
|
+
|
||
|
+ if (!ce)
|
||
|
+ return -EINVAL;
|
||
|
+ return scols_cell_refer_data(ce, data);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_copy_line:
|
||
|
+ * @ln: a pointer to a struct libscols_cell instance
|
||
|
+ *
|
||
|
+ * Returns: A newly allocated copy of @ln, NULL in case of an error.
|
||
|
+ */
|
||
|
+struct libscols_line *scols_copy_line(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ struct libscols_line *ret;
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ assert (ln);
|
||
|
+ if (!ln)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ ret = scols_new_line();
|
||
|
+ if (!ret)
|
||
|
+ return NULL;
|
||
|
+ if (scols_line_set_color(ret, ln->color))
|
||
|
+ goto err;
|
||
|
+ if (scols_line_alloc_cells(ret, ln->ncells))
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ ret->userdata = ln->userdata;
|
||
|
+ ret->ncells = ln->ncells;
|
||
|
+ ret->seqnum = ln->seqnum;
|
||
|
+
|
||
|
+ DBG(LINE, ul_debugobj(ln, "copy to %p", ret));
|
||
|
+
|
||
|
+ for (i = 0; i < ret->ncells; ++i) {
|
||
|
+ if (scols_cell_copy_content(&ret->cells[i], &ln->cells[i]))
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+err:
|
||
|
+ scols_unref_line(ret);
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/Makemodule.am.kzak util-linux-2.23.2/libsmartcols/src/Makemodule.am
|
||
|
--- util-linux-2.23.2/libsmartcols/src/Makemodule.am.kzak 2014-09-25 14:41:48.985843877 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/Makemodule.am 2014-09-25 14:42:10.471048869 +0200
|
||
|
@@ -0,0 +1,75 @@
|
||
|
+
|
||
|
+
|
||
|
+## smartcols.h is generated, so it's stored in builddir! (no distribute in RHEL7)
|
||
|
+#smartcolsincdir = $(includedir)/libsmartcols
|
||
|
+#nodist_smartcolsinc_HEADERS = $(top_builddir)/libsmartcols/src/libsmartcols.h
|
||
|
+
|
||
|
+noinst_LTLIBRARIES += libsmartcols.la
|
||
|
+libsmartcols_la_SOURCES= \
|
||
|
+ include/list.h \
|
||
|
+ \
|
||
|
+ libsmartcols/src/smartcolsP.h \
|
||
|
+ libsmartcols/src/iter.c \
|
||
|
+ libsmartcols/src/symbols.c \
|
||
|
+ libsmartcols/src/cell.c \
|
||
|
+ libsmartcols/src/column.c \
|
||
|
+ libsmartcols/src/line.c \
|
||
|
+ libsmartcols/src/table.c \
|
||
|
+ libsmartcols/src/table_print.c \
|
||
|
+ libsmartcols/src/version.c \
|
||
|
+ libsmartcols/src/init.c \
|
||
|
+ $(nodist_smartcolsinc_HEADERS)
|
||
|
+
|
||
|
+nodist_libsmartcols_la_SOURCES = libsmartcols/src/smartcolsP.h
|
||
|
+
|
||
|
+libsmartcols_la_LIBADD = libcommon.la
|
||
|
+
|
||
|
+libsmartcols_la_CFLAGS = \
|
||
|
+ $(SOLIB_CFLAGS) \
|
||
|
+ -I$(ul_libsmartcols_incdir) \
|
||
|
+ -I$(top_srcdir)/libsmartcols/src
|
||
|
+
|
||
|
+libsmartcols_la_DEPENDENCIES = \
|
||
|
+ libcommon.la \
|
||
|
+ libsmartcols/src/libsmartcols.sym \
|
||
|
+ libsmartcols/src/libsmartcols.h.in
|
||
|
+
|
||
|
+libsmartcols_la_LDFLAGS = \
|
||
|
+ $(SOLIB_LDFLAGS) \
|
||
|
+ -Wl,--version-script=$(top_srcdir)/libsmartcols/src/libsmartcols.sym \
|
||
|
+ -version-info $(LIBSMARTCOLS_VERSION_INFO)
|
||
|
+
|
||
|
+EXTRA_DIST += \
|
||
|
+ libsmartcols/src/libsmartcols.sym \
|
||
|
+ libsmartcols/src/libsmartcols.h.in
|
||
|
+
|
||
|
+
|
||
|
+if BUILD_LIBSMARTCOLS_TESTS
|
||
|
+check_PROGRAMS += test_smartcols
|
||
|
+
|
||
|
+libsmartcols_tests_cflags = $(libsmartcols_la_CFLAGS)
|
||
|
+libsmartcols_tests_ldadd = libsmartcols.la libcommon.la
|
||
|
+
|
||
|
+test_smartcols_SOURCES = libsmartcols/src/test.c
|
||
|
+test_smartcols_CFLAGS = $(libsmartcols_tests_cflags)
|
||
|
+test_smartcols_LDADD = $(libsmartcols_tests_ldadd)
|
||
|
+endif # BUILD_LIBSMARTCOLS_TESTS
|
||
|
+
|
||
|
+
|
||
|
+# move lib from $(usrlib_execdir) to $(libdir) if needed
|
||
|
+install-exec-hook-libsmartcols:
|
||
|
+ if test "$(usrlib_execdir)" != "$(libdir)" -a -f "$(DESTDIR)$(usrlib_execdir)/libsmartcols.so"; then \
|
||
|
+ mkdir -p $(DESTDIR)$(libdir); \
|
||
|
+ mv $(DESTDIR)$(usrlib_execdir)/libsmartcols.so.* $(DESTDIR)$(libdir); \
|
||
|
+ so_img_name=$$(readlink $(DESTDIR)$(usrlib_execdir)/libsmartcols.so); \
|
||
|
+ so_img_rel_target=$$(echo $(usrlib_execdir) | sed 's,\(^/\|\)[^/][^/]*,..,g'); \
|
||
|
+ (cd $(DESTDIR)$(usrlib_execdir) && \
|
||
|
+ rm -f libsmartcols.so && \
|
||
|
+ $(LN_S) $$so_img_rel_target$(libdir)/$$so_img_name libsmartcols.so); \
|
||
|
+ fi
|
||
|
+
|
||
|
+uninstall-hook-libsmartcols:
|
||
|
+ rm -f $(DESTDIR)$(libdir)/libsmartcols.so*
|
||
|
+
|
||
|
+INSTALL_EXEC_HOOKS += install-exec-hook-libsmartcols
|
||
|
+UNINSTALL_HOOKS += uninstall-hook-libsmartcols
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/smartcolsP.h.kzak util-linux-2.23.2/libsmartcols/src/smartcolsP.h
|
||
|
--- util-linux-2.23.2/libsmartcols/src/smartcolsP.h.kzak 2014-09-25 14:41:48.989843915 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/smartcolsP.h 2014-09-25 14:41:48.989843915 +0200
|
||
|
@@ -0,0 +1,173 @@
|
||
|
+/*
|
||
|
+ * smartcolsP.h - private library header file
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef _LIBSMARTCOLS_PRIVATE_H
|
||
|
+#define _LIBSMARTCOLS_PRIVATE_H
|
||
|
+
|
||
|
+#include "c.h"
|
||
|
+#include "list.h"
|
||
|
+#include "colors.h"
|
||
|
+#include "debug.h"
|
||
|
+
|
||
|
+#include "libsmartcols.h"
|
||
|
+
|
||
|
+/* features */
|
||
|
+#define CONFIG_LIBSMARTCOLS_ASSERT
|
||
|
+
|
||
|
+#ifdef CONFIG_LIBSMARTCOLS_ASSERT
|
||
|
+# include <assert.h>
|
||
|
+#else
|
||
|
+# define assert(x)
|
||
|
+#endif
|
||
|
+
|
||
|
+/*
|
||
|
+ * Debug
|
||
|
+ */
|
||
|
+#define SCOLS_DEBUG_INIT (1 << 1)
|
||
|
+#define SCOLS_DEBUG_CELL (1 << 2)
|
||
|
+#define SCOLS_DEBUG_LINE (1 << 3)
|
||
|
+#define SCOLS_DEBUG_TAB (1 << 4)
|
||
|
+#define SCOLS_DEBUG_COL (1 << 5)
|
||
|
+#define SCOLS_DEBUG_BUFF (1 << 6)
|
||
|
+#define SCOLS_DEBUG_ALL 0xFFFF
|
||
|
+
|
||
|
+UL_DEBUG_DECLARE_MASK(libsmartcols);
|
||
|
+#define DBG(m, x) __UL_DBG(libsmartcols, SCOLS_DEBUG_, m, x)
|
||
|
+#define ON_DBG(m, x) __UL_DBG_CALL(libsmartcols, SCOLS_DEBUG_, m, x)
|
||
|
+#define DBG_FLUSH __UL_DBG_FLUSH(libsmartcols, SCOLS_DEBUG_)
|
||
|
+
|
||
|
+/*
|
||
|
+ * Generic iterator
|
||
|
+ */
|
||
|
+struct libscols_iter {
|
||
|
+ struct list_head *p; /* current position */
|
||
|
+ struct list_head *head; /* start position */
|
||
|
+ int direction; /* SCOLS_ITER_{FOR,BACK}WARD */
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * Tree symbols
|
||
|
+ */
|
||
|
+struct libscols_symbols {
|
||
|
+ int refcount;
|
||
|
+ char *branch;
|
||
|
+ char *vert;
|
||
|
+ char *right;
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * Table cells
|
||
|
+ */
|
||
|
+struct libscols_cell {
|
||
|
+ char *data;
|
||
|
+ char *color;
|
||
|
+ void *userdata;
|
||
|
+};
|
||
|
+
|
||
|
+
|
||
|
+/*
|
||
|
+ * Table column
|
||
|
+ */
|
||
|
+struct libscols_column {
|
||
|
+ int refcount; /* reference counter */
|
||
|
+ size_t seqnum; /* column index */
|
||
|
+
|
||
|
+ size_t width; /* real column width */
|
||
|
+ size_t width_min; /* minimal width (usually header width) */
|
||
|
+ size_t width_max; /* maximal width */
|
||
|
+ size_t width_avg; /* average width, used to detect extreme fields */
|
||
|
+ double width_hint; /* hint (N < 1 is in percent of termwidth) */
|
||
|
+
|
||
|
+ int flags;
|
||
|
+ int is_extreme;
|
||
|
+ char *color; /* default column color */
|
||
|
+
|
||
|
+ int (*cmpfunc)(struct libscols_cell *,
|
||
|
+ struct libscols_cell *,
|
||
|
+ void *); /* cells comparison function */
|
||
|
+ void *cmpfunc_data;
|
||
|
+
|
||
|
+ struct libscols_cell header;
|
||
|
+ struct list_head cl_columns;
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * Table line
|
||
|
+ */
|
||
|
+struct libscols_line {
|
||
|
+ int refcount;
|
||
|
+ size_t seqnum;
|
||
|
+
|
||
|
+ void *userdata;
|
||
|
+ char *color; /* default line color */
|
||
|
+
|
||
|
+ struct libscols_cell *cells; /* array with data */
|
||
|
+ size_t ncells; /* number of cells */
|
||
|
+
|
||
|
+ struct list_head ln_lines; /* table lines */
|
||
|
+ struct list_head ln_branch; /* begin of branch (head of ln_children) */
|
||
|
+ struct list_head ln_children;
|
||
|
+
|
||
|
+ struct libscols_line *parent;
|
||
|
+};
|
||
|
+
|
||
|
+enum {
|
||
|
+ SCOLS_FMT_HUMAN = 0, /* default, human readable */
|
||
|
+ SCOLS_FMT_RAW, /* space separated */
|
||
|
+ SCOLS_FMT_EXPORT /* COLNAME="data" ... */
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * The table
|
||
|
+ */
|
||
|
+struct libscols_table {
|
||
|
+ int refcount;
|
||
|
+ size_t ncols; /* number of columns */
|
||
|
+ size_t ntreecols; /* number of columns with SCOLS_FL_TREE */
|
||
|
+ size_t nlines; /* number of lines */
|
||
|
+ size_t termwidth; /* terminal width */
|
||
|
+ size_t termreduce; /* extra blank space */
|
||
|
+ FILE *out; /* output stream */
|
||
|
+
|
||
|
+ char *colsep; /* column separator */
|
||
|
+ char *linesep; /* line separator */
|
||
|
+
|
||
|
+ struct list_head tb_columns;
|
||
|
+ struct list_head tb_lines;
|
||
|
+ struct libscols_symbols *symbols;
|
||
|
+
|
||
|
+ int format; /* SCOLS_FMT_* */
|
||
|
+
|
||
|
+ /* flags */
|
||
|
+ unsigned int ascii :1, /* don't use unicode */
|
||
|
+ colors_wanted :1, /* enable colors */
|
||
|
+ is_term :1, /* isatty() */
|
||
|
+ maxout :1, /* maximalize output */
|
||
|
+ no_headings :1; /* don't print header */
|
||
|
+};
|
||
|
+
|
||
|
+#define IS_ITER_FORWARD(_i) ((_i)->direction == SCOLS_ITER_FORWARD)
|
||
|
+#define IS_ITER_BACKWARD(_i) ((_i)->direction == SCOLS_ITER_BACKWARD)
|
||
|
+
|
||
|
+#define SCOLS_ITER_INIT(itr, list) \
|
||
|
+ do { \
|
||
|
+ (itr)->p = IS_ITER_FORWARD(itr) ? \
|
||
|
+ (list)->next : (list)->prev; \
|
||
|
+ (itr)->head = (list); \
|
||
|
+ } while(0)
|
||
|
+
|
||
|
+#define SCOLS_ITER_ITERATE(itr, res, restype, member) \
|
||
|
+ do { \
|
||
|
+ res = list_entry((itr)->p, restype, member); \
|
||
|
+ (itr)->p = IS_ITER_FORWARD(itr) ? \
|
||
|
+ (itr)->p->next : (itr)->p->prev; \
|
||
|
+ } while(0)
|
||
|
+
|
||
|
+#endif /* _LIBSMARTCOLS_PRIVATE_H */
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/symbols.c.kzak util-linux-2.23.2/libsmartcols/src/symbols.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/symbols.c.kzak 2014-09-25 14:41:48.989843915 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/symbols.c 2014-09-25 14:41:48.989843915 +0200
|
||
|
@@ -0,0 +1,175 @@
|
||
|
+/*
|
||
|
+ * symbols.c - routines for symbol handling
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: symbols
|
||
|
+ * @title: Symbols
|
||
|
+ * @short_description: symbols API
|
||
|
+ *
|
||
|
+ * An API to access and modify data and information per symbol/symbol group.
|
||
|
+ */
|
||
|
+
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_new_symbols:
|
||
|
+ *
|
||
|
+ * Returns: a pointer to a newly allocated struct libscols_symbols instance.
|
||
|
+ */
|
||
|
+struct libscols_symbols *scols_new_symbols(void)
|
||
|
+{
|
||
|
+ struct libscols_symbols *sy = calloc(1, sizeof(struct libscols_symbols));
|
||
|
+
|
||
|
+ if (!sy)
|
||
|
+ return NULL;
|
||
|
+ sy->refcount = 1;
|
||
|
+ return sy;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_ref_symbols:
|
||
|
+ * @sy: a pointer to a struct libscols_symbols instance
|
||
|
+ *
|
||
|
+ * Increases the refcount of @sy.
|
||
|
+ */
|
||
|
+void scols_ref_symbols(struct libscols_symbols *sy)
|
||
|
+{
|
||
|
+ if (sy)
|
||
|
+ sy->refcount++;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_unref_symbols:
|
||
|
+ * @sy: a pointer to a struct libscols_symbols instance
|
||
|
+ *
|
||
|
+ * Decreases the refcount of @sy.
|
||
|
+ */
|
||
|
+void scols_unref_symbols(struct libscols_symbols *sy)
|
||
|
+{
|
||
|
+ if (sy && --sy->refcount <= 0) {
|
||
|
+ free(sy->branch);
|
||
|
+ free(sy->vert);
|
||
|
+ free(sy->right);
|
||
|
+ free(sy);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_symbols_set_branch:
|
||
|
+ * @sb: a pointer to a struct libscols_symbols instance
|
||
|
+ * @str: a string which will represent the branch part of a tree output
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_symbols_set_branch(struct libscols_symbols *sb, const char *str)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(sb);
|
||
|
+
|
||
|
+ if (!sb)
|
||
|
+ return -EINVAL;
|
||
|
+ if (str) {
|
||
|
+ p = strdup(str);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ free(sb->branch);
|
||
|
+ sb->branch = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_symbols_set_vertical:
|
||
|
+ * @sb: a pointer to a struct libscols_symbols instance
|
||
|
+ * @str: a string which will represent the vertical part of a tree output
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_symbols_set_vertical(struct libscols_symbols *sb, const char *str)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(sb);
|
||
|
+
|
||
|
+ if (!sb)
|
||
|
+ return -EINVAL;
|
||
|
+ if (str) {
|
||
|
+ p = strdup(str);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ free(sb->vert);
|
||
|
+ sb->vert = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_symbols_set_right:
|
||
|
+ * @sb: a pointer to a struct libscols_symbols instance
|
||
|
+ * @str: a string which will represent the right part of a tree output
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_symbols_set_right(struct libscols_symbols *sb, const char *str)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert(sb);
|
||
|
+
|
||
|
+ if (!sb)
|
||
|
+ return -EINVAL;
|
||
|
+ if (str) {
|
||
|
+ p = strdup(str);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ free(sb->right);
|
||
|
+ sb->right = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_copy_symbols:
|
||
|
+ * @sb: a pointer to a struct libscols_symbols instance
|
||
|
+ *
|
||
|
+ * Returns: a newly allocated copy of the @sb symbol group or NULL in caes of an error.
|
||
|
+ */
|
||
|
+struct libscols_symbols *scols_copy_symbols(const struct libscols_symbols *sb)
|
||
|
+{
|
||
|
+ struct libscols_symbols *ret;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ assert(sb);
|
||
|
+ if (!sb)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ ret = scols_new_symbols();
|
||
|
+ if (!ret)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ rc = scols_symbols_set_branch(ret, sb->branch);
|
||
|
+ if (!rc)
|
||
|
+ rc = scols_symbols_set_vertical(ret, sb->vert);
|
||
|
+ if (!rc)
|
||
|
+ rc = scols_symbols_set_right(ret, sb->right);
|
||
|
+ if (!rc)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ scols_unref_symbols(ret);
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/table.c.kzak util-linux-2.23.2/libsmartcols/src/table.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/table.c.kzak 2014-09-25 14:41:48.991843934 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/table.c 2014-09-25 14:41:48.991843934 +0200
|
||
|
@@ -0,0 +1,1049 @@
|
||
|
+/*
|
||
|
+ * table.c - functions handling the data at the table level
|
||
|
+ *
|
||
|
+ * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
|
||
|
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: table
|
||
|
+ * @title: Table
|
||
|
+ * @short_description: table data API
|
||
|
+ *
|
||
|
+ * Table data manipulation API.
|
||
|
+ */
|
||
|
+
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+#include <termios.h>
|
||
|
+#include <ctype.h>
|
||
|
+
|
||
|
+#include "nls.h"
|
||
|
+#include "widechar.h"
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+#ifdef HAVE_WIDECHAR
|
||
|
+#define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char */
|
||
|
+#define UTF_VR "\342\224\234" /* U+251C, Vertical and right */
|
||
|
+#define UTF_H "\342\224\200" /* U+2500, Horizontal */
|
||
|
+#define UTF_UR "\342\224\224" /* U+2514, Up and right */
|
||
|
+#endif /* !HAVE_WIDECHAR */
|
||
|
+
|
||
|
+#define is_last_column(_tb, _cl) \
|
||
|
+ list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns)
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_new_table:
|
||
|
+ *
|
||
|
+ * Returns: A newly allocated table.
|
||
|
+ */
|
||
|
+struct libscols_table *scols_new_table(void)
|
||
|
+{
|
||
|
+ struct libscols_table *tb;
|
||
|
+
|
||
|
+ tb = calloc(1, sizeof(struct libscols_table));
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ tb->refcount = 1;
|
||
|
+ tb->out = stdout;
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&tb->tb_lines);
|
||
|
+ INIT_LIST_HEAD(&tb->tb_columns);
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "alloc"));
|
||
|
+ return tb;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_ref_table:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ *
|
||
|
+ * Increases the refcount of @tb.
|
||
|
+ */
|
||
|
+void scols_ref_table(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ if (tb)
|
||
|
+ tb->refcount++;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_unref_table:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ *
|
||
|
+ * Decreases the refcount of @tb. When the count falls to zero, the instance
|
||
|
+ * is automatically deallocated.
|
||
|
+ */
|
||
|
+void scols_unref_table(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ if (tb && (--tb->refcount <= 0)) {
|
||
|
+ DBG(TAB, ul_debugobj(tb, "dealloc"));
|
||
|
+ scols_table_remove_lines(tb);
|
||
|
+ scols_table_remove_columns(tb);
|
||
|
+ scols_unref_symbols(tb->symbols);
|
||
|
+ free(tb->linesep);
|
||
|
+ free(tb->colsep);
|
||
|
+ free(tb);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_add_column:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Adds @cl to @tb's column list.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_add_column(struct libscols_table *tb, struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ if (!tb || !cl || !list_empty(&tb->tb_lines))
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ if (cl->flags & SCOLS_FL_TREE)
|
||
|
+ tb->ntreecols++;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "add column %p", cl));
|
||
|
+ list_add_tail(&cl->cl_columns, &tb->tb_columns);
|
||
|
+ cl->seqnum = tb->ncols++;
|
||
|
+ scols_ref_column(cl);
|
||
|
+
|
||
|
+ /* TODO:
|
||
|
+ *
|
||
|
+ * Currently it's possible to add/remove columns only if the table is
|
||
|
+ * empty (see list_empty(tb->tb_lines) above). It would be nice to
|
||
|
+ * enlarge/reduce lines cells[] always when we add/remove a new column.
|
||
|
+ */
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_remove_column:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ * @cl: a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Removes @cl from @tb.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_remove_column(struct libscols_table *tb,
|
||
|
+ struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ if (!tb || !cl || !list_empty(&tb->tb_lines))
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ if (cl->flags & SCOLS_FL_TREE)
|
||
|
+ tb->ntreecols--;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "remove column %p", cl));
|
||
|
+ list_del_init(&cl->cl_columns);
|
||
|
+ tb->ncols--;
|
||
|
+ scols_unref_column(cl);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_remove_columns:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ *
|
||
|
+ * Removes all of @tb's columns.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_remove_columns(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+
|
||
|
+ if (!tb || !list_empty(&tb->tb_lines))
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "remove all columns"));
|
||
|
+ while (!list_empty(&tb->tb_columns)) {
|
||
|
+ struct libscols_column *cl = list_entry(tb->tb_columns.next,
|
||
|
+ struct libscols_column, cl_columns);
|
||
|
+ scols_table_remove_column(tb, cl);
|
||
|
+ }
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_new_column:
|
||
|
+ * @tb: table
|
||
|
+ * @name: column header
|
||
|
+ * @whint: column width hint (absolute width: N > 1; relative width: N < 1)
|
||
|
+ * @flags: flags integer
|
||
|
+ *
|
||
|
+ * This is shortcut for
|
||
|
+ *
|
||
|
+ * cl = scols_new_column();
|
||
|
+ * scols_column_set_....(cl, ...);
|
||
|
+ * scols_table_add_column(tb, cl);
|
||
|
+ *
|
||
|
+ * The column width is possible to define by three ways:
|
||
|
+ *
|
||
|
+ * @whint = 0..1 : relative width, percent of terminal width
|
||
|
+ *
|
||
|
+ * @whint = 1..N : absolute width, empty colum will be truncated to
|
||
|
+ * the column header width
|
||
|
+ *
|
||
|
+ * @whint = 1..N
|
||
|
+ *
|
||
|
+ * The column is necessary to address by
|
||
|
+ * sequential number. The first defined column has the colnum = 0. For example:
|
||
|
+ *
|
||
|
+ * scols_table_new_column(tab, "FOO", 0.5, 0); // colnum = 0
|
||
|
+ * scols_table_new_column(tab, "BAR", 0.5, 0); // colnum = 1
|
||
|
+ * .
|
||
|
+ * .
|
||
|
+ * scols_line_get_cell(line, 0); // FOO column
|
||
|
+ * scols_line_get_cell(line, 1); // BAR column
|
||
|
+ *
|
||
|
+ * Returns: newly allocated column
|
||
|
+ */
|
||
|
+struct libscols_column *scols_table_new_column(struct libscols_table *tb,
|
||
|
+ const char *name,
|
||
|
+ double whint,
|
||
|
+ int flags)
|
||
|
+{
|
||
|
+ struct libscols_column *cl;
|
||
|
+ struct libscols_cell *hr;
|
||
|
+
|
||
|
+ assert (tb);
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "new column name=%s, whint=%g, flags=%d",
|
||
|
+ name, whint, flags));
|
||
|
+ cl = scols_new_column();
|
||
|
+ if (!cl)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ /* set column name */
|
||
|
+ hr = scols_column_get_header(cl);
|
||
|
+ if (!hr)
|
||
|
+ goto err;
|
||
|
+ if (scols_cell_set_data(hr, name))
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ scols_column_set_whint(cl, whint);
|
||
|
+ scols_column_set_flags(cl, flags);
|
||
|
+
|
||
|
+ if (scols_table_add_column(tb, cl)) /* this increments column ref-counter */
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ scols_unref_column(cl);
|
||
|
+ return cl;
|
||
|
+err:
|
||
|
+ scols_unref_column(cl);
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_next_column:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ * @itr: a pointer to a struct libscols_iter instance
|
||
|
+ * @cl: a pointer to a pointer to a struct libscols_column instance
|
||
|
+ *
|
||
|
+ * Returns the next column of @tb via @cl.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_next_column(struct libscols_table *tb,
|
||
|
+ struct libscols_iter *itr,
|
||
|
+ struct libscols_column **cl)
|
||
|
+{
|
||
|
+ int rc = 1;
|
||
|
+
|
||
|
+ if (!tb || !itr || !cl)
|
||
|
+ return -EINVAL;
|
||
|
+ *cl = NULL;
|
||
|
+
|
||
|
+ if (!itr->head)
|
||
|
+ SCOLS_ITER_INIT(itr, &tb->tb_columns);
|
||
|
+ if (itr->p != itr->head) {
|
||
|
+ SCOLS_ITER_ITERATE(itr, *cl, struct libscols_column, cl_columns);
|
||
|
+ rc = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_ncols:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: the ncols table member, a negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_get_ncols(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb ? tb->ncols : -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_nlines:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: the nlines table member, a negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_get_nlines(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb ? tb->nlines : -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_set_stream:
|
||
|
+ * @tb: table
|
||
|
+ * @stream: output stream
|
||
|
+ *
|
||
|
+ * Sets the output stream for table @tb.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_set_stream(struct libscols_table *tb, FILE *stream)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "setting alternative stream"));
|
||
|
+ tb->out = stream;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_stream:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Gets the output stream for table @tb.
|
||
|
+ *
|
||
|
+ * Returns: stream pointer, NULL in case of an error or an unset stream.
|
||
|
+ */
|
||
|
+FILE *scols_table_get_stream(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb ? tb->out: NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_reduce_termwidth:
|
||
|
+ * @tb: table
|
||
|
+ * @reduce: width
|
||
|
+ *
|
||
|
+ * Reduce the output width to @reduce.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_reduce_termwidth(struct libscols_table *tb, size_t reduce)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "reduce terminal width: %zu", reduce));
|
||
|
+ tb->termreduce = reduce;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_column:
|
||
|
+ * @tb: table
|
||
|
+ * @n: number of column (0..N)
|
||
|
+ *
|
||
|
+ * Returns: pointer to column or NULL
|
||
|
+ */
|
||
|
+struct libscols_column *scols_table_get_column(struct libscols_table *tb,
|
||
|
+ size_t n)
|
||
|
+{
|
||
|
+ struct libscols_iter itr;
|
||
|
+ struct libscols_column *cl;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+ if (n >= tb->ncols)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ if (cl->seqnum == n)
|
||
|
+ return cl;
|
||
|
+ }
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_add_line:
|
||
|
+ * @tb: table
|
||
|
+ * @ln: line
|
||
|
+ *
|
||
|
+ * Note that this function calls scols_line_alloc_cells() if number
|
||
|
+ * of the cells in the line is too small for @tb.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_add_line(struct libscols_table *tb, struct libscols_line *ln)
|
||
|
+{
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ assert(ln);
|
||
|
+
|
||
|
+ if (!tb || !ln)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ if (tb->ncols > ln->ncells) {
|
||
|
+ int rc = scols_line_alloc_cells(ln, tb->ncols);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "add line %p", ln));
|
||
|
+ list_add_tail(&ln->ln_lines, &tb->tb_lines);
|
||
|
+ ln->seqnum = tb->nlines++;
|
||
|
+ scols_ref_line(ln);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_remove_line:
|
||
|
+ * @tb: table
|
||
|
+ * @ln: line
|
||
|
+ *
|
||
|
+ * Note that this function does not destroy the parent<->child relationship between lines.
|
||
|
+ * You have to call scols_line_remove_child()
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_remove_line(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ assert(ln);
|
||
|
+
|
||
|
+ if (!tb || !ln)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "remove line %p", ln));
|
||
|
+ list_del_init(&ln->ln_lines);
|
||
|
+ tb->nlines--;
|
||
|
+ scols_unref_line(ln);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_remove_lines:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * This empties the table and also destroys all the parent<->child relationships.
|
||
|
+ */
|
||
|
+void scols_table_remove_lines(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "remove all lines"));
|
||
|
+ while (!list_empty(&tb->tb_lines)) {
|
||
|
+ struct libscols_line *ln = list_entry(tb->tb_lines.next,
|
||
|
+ struct libscols_line, ln_lines);
|
||
|
+ if (ln->parent)
|
||
|
+ scols_line_remove_child(ln->parent, ln);
|
||
|
+ scols_table_remove_line(tb, ln);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_next_line:
|
||
|
+ * @tb: a pointer to a struct libscols_table instance
|
||
|
+ * @itr: a pointer to a struct libscols_iter instance
|
||
|
+ * @ln: a pointer to a pointer to a struct libscols_line instance
|
||
|
+ *
|
||
|
+ * Finds the next line and returns a pointer to it via @ln.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_next_line(struct libscols_table *tb,
|
||
|
+ struct libscols_iter *itr,
|
||
|
+ struct libscols_line **ln)
|
||
|
+{
|
||
|
+ int rc = 1;
|
||
|
+
|
||
|
+ if (!tb || !itr || !ln)
|
||
|
+ return -EINVAL;
|
||
|
+ *ln = NULL;
|
||
|
+
|
||
|
+ if (!itr->head)
|
||
|
+ SCOLS_ITER_INIT(itr, &tb->tb_lines);
|
||
|
+ if (itr->p != itr->head) {
|
||
|
+ SCOLS_ITER_ITERATE(itr, *ln, struct libscols_line, ln_lines);
|
||
|
+ rc = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_new_line:
|
||
|
+ * @tb: table
|
||
|
+ * @parent: parental line or NULL
|
||
|
+ *
|
||
|
+ * This is shortcut for
|
||
|
+ *
|
||
|
+ * ln = scols_new_line();
|
||
|
+ * scols_table_add_line(tb, ln);
|
||
|
+ * scols_line_add_child(parent, ln);
|
||
|
+ *
|
||
|
+ *
|
||
|
+ * Returns: newly allocate line
|
||
|
+ */
|
||
|
+struct libscols_line *scols_table_new_line(struct libscols_table *tb,
|
||
|
+ struct libscols_line *parent)
|
||
|
+{
|
||
|
+ struct libscols_line *ln;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ assert(tb->ncols);
|
||
|
+
|
||
|
+ if (!tb || !tb->ncols)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ ln = scols_new_line();
|
||
|
+ if (!ln)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ if (scols_table_add_line(tb, ln))
|
||
|
+ goto err;
|
||
|
+ if (parent)
|
||
|
+ scols_line_add_child(parent, ln);
|
||
|
+
|
||
|
+ scols_unref_line(ln); /* ref-counter incremented by scols_table_add_line() */
|
||
|
+ return ln;
|
||
|
+err:
|
||
|
+ scols_unref_line(ln);
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_line:
|
||
|
+ * @tb: table
|
||
|
+ * @n: column number (0..N)
|
||
|
+ *
|
||
|
+ * This is a shortcut for
|
||
|
+ *
|
||
|
+ * ln = scols_new_line();
|
||
|
+ * scols_line_set_....(cl, ...);
|
||
|
+ * scols_table_add_line(tb, ln);
|
||
|
+ *
|
||
|
+ * Returns: a newly allocate line
|
||
|
+ */
|
||
|
+struct libscols_line *scols_table_get_line(struct libscols_table *tb,
|
||
|
+ size_t n)
|
||
|
+{
|
||
|
+ struct libscols_iter itr;
|
||
|
+ struct libscols_line *ln;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+ if (n >= tb->nlines)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_line(tb, &itr, &ln) == 0) {
|
||
|
+ if (ln->seqnum == n)
|
||
|
+ return ln;
|
||
|
+ }
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_copy_table:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Creates a new independent table copy, except struct libscols_symbols that
|
||
|
+ * are shared between the tables.
|
||
|
+ *
|
||
|
+ * Returns: a newly allocated copy of @tb
|
||
|
+ */
|
||
|
+struct libscols_table *scols_copy_table(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ struct libscols_table *ret;
|
||
|
+ struct libscols_line *ln;
|
||
|
+ struct libscols_column *cl;
|
||
|
+ struct libscols_iter itr;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+ ret = scols_new_table();
|
||
|
+ if (!ret)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "copy into %p", ret));
|
||
|
+
|
||
|
+ if (tb->symbols)
|
||
|
+ scols_table_set_symbols(ret, tb->symbols);
|
||
|
+
|
||
|
+ /* columns */
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ cl = scols_copy_column(cl);
|
||
|
+ if (!cl)
|
||
|
+ goto err;
|
||
|
+ if (scols_table_add_column(ret, cl))
|
||
|
+ goto err;
|
||
|
+ scols_unref_column(cl);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* lines */
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_line(tb, &itr, &ln) == 0) {
|
||
|
+ struct libscols_line *newln = scols_copy_line(ln);
|
||
|
+ if (!newln)
|
||
|
+ goto err;
|
||
|
+ if (scols_table_add_line(ret, newln))
|
||
|
+ goto err;
|
||
|
+ if (ln->parent) {
|
||
|
+ struct libscols_line *p =
|
||
|
+ scols_table_get_line(ret, ln->parent->seqnum);
|
||
|
+ if (p)
|
||
|
+ scols_line_add_child(p, newln);
|
||
|
+ }
|
||
|
+ scols_unref_line(newln);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* separators */
|
||
|
+ if (scols_table_set_column_separator(ret, tb->colsep) ||
|
||
|
+ scols_table_set_line_separator(ret, tb->linesep))
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+err:
|
||
|
+ scols_unref_table(ret);
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_set_symbols:
|
||
|
+ * @tb: table
|
||
|
+ * @sy: symbols or NULL
|
||
|
+ *
|
||
|
+ * Add a reference to @sy from the table. The symbols are used by library to
|
||
|
+ * draw tree output. If no symbols are specified then library checks the
|
||
|
+ * current environment to select ASCII or UTF8 symbols. This default behavior
|
||
|
+ * could be controlled by scols_table_enable_ascii().
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_set_symbols(struct libscols_table *tb,
|
||
|
+ struct libscols_symbols *sy)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "setting alternative symbols %p", sy));
|
||
|
+
|
||
|
+ if (tb->symbols) /* unref old */
|
||
|
+ scols_unref_symbols(tb->symbols);
|
||
|
+ if (sy) { /* ref user defined */
|
||
|
+ tb->symbols = sy;
|
||
|
+ scols_ref_symbols(sy);
|
||
|
+ } else { /* default symbols */
|
||
|
+ tb->symbols = scols_new_symbols();
|
||
|
+ if (!tb->symbols)
|
||
|
+ return -ENOMEM;
|
||
|
+#if defined(HAVE_WIDECHAR)
|
||
|
+ if (!scols_table_is_ascii(tb) &&
|
||
|
+ !strcmp(nl_langinfo(CODESET), "UTF-8")) {
|
||
|
+ scols_symbols_set_branch(tb->symbols, UTF_VR UTF_H);
|
||
|
+ scols_symbols_set_vertical(tb->symbols, UTF_V " ");
|
||
|
+ scols_symbols_set_right(tb->symbols, UTF_UR UTF_H);
|
||
|
+ } else
|
||
|
+#endif
|
||
|
+ {
|
||
|
+ scols_symbols_set_branch(tb->symbols, "|-");
|
||
|
+ scols_symbols_set_vertical(tb->symbols, "| ");
|
||
|
+ scols_symbols_set_right(tb->symbols, "`-");
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * scols_table_enable_colors:
|
||
|
+ * @tb: table
|
||
|
+ * @enable: 1 or 0
|
||
|
+ *
|
||
|
+ * Enable/disable colors.
|
||
|
+ *
|
||
|
+ * Returns: 0 on success, negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_enable_colors(struct libscols_table *tb, int enable)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "colors: %s", enable ? "ENABLE" : "DISABLE"));
|
||
|
+ tb->colors_wanted = enable;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * scols_table_enable_raw:
|
||
|
+ * @tb: table
|
||
|
+ * @enable: 1 or 0
|
||
|
+ *
|
||
|
+ * Enable/disable raw output format. The parsable output formats
|
||
|
+ * (export and raw) are mutually exclusive.
|
||
|
+ *
|
||
|
+ * Returns: 0 on success, negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_enable_raw(struct libscols_table *tb, int enable)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "raw: %s", enable ? "ENABLE" : "DISABLE"));
|
||
|
+ if (enable)
|
||
|
+ tb->format = SCOLS_FMT_RAW;
|
||
|
+ else if (tb->format == SCOLS_FMT_RAW)
|
||
|
+ tb->format = 0;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_enable_export:
|
||
|
+ * @tb: table
|
||
|
+ * @enable: 1 or 0
|
||
|
+ *
|
||
|
+ * Enable/disable export output format (COLUMNAME="value" ...).
|
||
|
+ * The parsable output formats (export and raw) are mutually exclusive.
|
||
|
+ *
|
||
|
+ * Returns: 0 on success, negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_enable_export(struct libscols_table *tb, int enable)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "export: %s", enable ? "ENABLE" : "DISABLE"));
|
||
|
+ if (enable)
|
||
|
+ tb->format = SCOLS_FMT_EXPORT;
|
||
|
+ else if (tb->format == SCOLS_FMT_EXPORT)
|
||
|
+ tb->format = 0;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_enable_ascii:
|
||
|
+ * @tb: table
|
||
|
+ * @enable: 1 or 0
|
||
|
+ *
|
||
|
+ * The ASCII-only output is relevant for tree-like outputs. The library
|
||
|
+ * checks if the current environment is UTF8 compatible by default. This
|
||
|
+ * function overrides this check and force the library to use ASCII chars
|
||
|
+ * for the tree.
|
||
|
+ *
|
||
|
+ * If a custom libcols_symbols are specified (see scols_table_set_symbols()
|
||
|
+ * then ASCII flag setting is ignored.
|
||
|
+ *
|
||
|
+ * Returns: 0 on success, negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_enable_ascii(struct libscols_table *tb, int enable)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "ascii: %s", enable ? "ENABLE" : "DISABLE"));
|
||
|
+ tb->ascii = enable ? 1 : 0;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_enable_noheadings:
|
||
|
+ * @tb: table
|
||
|
+ * @enable: 1 or 0
|
||
|
+ *
|
||
|
+ * Enable/disable header line.
|
||
|
+ *
|
||
|
+ * Returns: 0 on success, negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_enable_noheadings(struct libscols_table *tb, int enable)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+ DBG(TAB, ul_debugobj(tb, "noheading: %s", enable ? "ENABLE" : "DISABLE"));
|
||
|
+ tb->no_headings = enable ? 1 : 0;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_enable_maxout:
|
||
|
+ * @tb: table
|
||
|
+ * @enable: 1 or 0
|
||
|
+ *
|
||
|
+ * The extra space after last column is ignored by default. The output
|
||
|
+ * maximization use the extra space for all columns.
|
||
|
+ *
|
||
|
+ * Returns: 0 on success, negative number in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_enable_maxout(struct libscols_table *tb, int enable)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+ DBG(TAB, ul_debugobj(tb, "maxout: %s", enable ? "ENABLE" : "DISABLE"));
|
||
|
+ tb->maxout = enable ? 1 : 0;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_colors_wanted:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if colors are enabled.
|
||
|
+ */
|
||
|
+int scols_table_colors_wanted(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->colors_wanted;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_empty:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if the table is empty.
|
||
|
+ */
|
||
|
+int scols_table_is_empty(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return !tb || !tb->nlines;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_ascii:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if ASCII tree is enabled.
|
||
|
+ */
|
||
|
+int scols_table_is_ascii(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->ascii;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_noheadings:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if header output is disabled.
|
||
|
+ */
|
||
|
+int scols_table_is_noheadings(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->no_headings;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_export:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if export output format is enabled.
|
||
|
+ */
|
||
|
+int scols_table_is_export(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->format == SCOLS_FMT_EXPORT;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_raw:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if raw output format is enabled.
|
||
|
+ */
|
||
|
+int scols_table_is_raw(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->format == SCOLS_FMT_RAW;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_maxout
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: 1 if output maximization is enabled, negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_is_maxout(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->maxout;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_is_tree:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: returns 1 tree-like output is expected.
|
||
|
+ */
|
||
|
+int scols_table_is_tree(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ return tb && tb->ntreecols > 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_set_column_separator:
|
||
|
+ * @tb: table
|
||
|
+ * @sep: separator
|
||
|
+ *
|
||
|
+ * Sets the column separator of @tb to @sep.
|
||
|
+ * Please note that @sep should always take up a single cell in the output.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_set_column_separator(struct libscols_table *tb, const char *sep)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert (tb);
|
||
|
+
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ if (sep) {
|
||
|
+ p = strdup(sep);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "new columns separator: %s", sep));
|
||
|
+ free(tb->colsep);
|
||
|
+ tb->colsep = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_set_line_separator:
|
||
|
+ * @tb: table
|
||
|
+ * @sep: separator
|
||
|
+ *
|
||
|
+ * Sets the line separator of @tb to @sep.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_table_set_line_separator(struct libscols_table *tb, const char *sep)
|
||
|
+{
|
||
|
+ char *p = NULL;
|
||
|
+
|
||
|
+ assert (tb);
|
||
|
+
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ if (sep) {
|
||
|
+ p = strdup(sep);
|
||
|
+ if (!p)
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "new lines separator: %s", sep));
|
||
|
+ free(tb->linesep);
|
||
|
+ tb->linesep = p;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_column_separator:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: @tb column separator, NULL in case of an error
|
||
|
+ */
|
||
|
+char *scols_table_get_column_separator(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert (tb);
|
||
|
+
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+ return tb->colsep;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_table_get_line_separator:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Returns: @tb line separator, NULL in case of an error
|
||
|
+ */
|
||
|
+char *scols_table_get_line_separator(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ assert (tb);
|
||
|
+
|
||
|
+ if (!tb)
|
||
|
+ return NULL;
|
||
|
+ return tb->linesep;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+static int cells_cmp_wrapper(struct list_head *a, struct list_head *b, void *data)
|
||
|
+{
|
||
|
+ struct libscols_column *cl = (struct libscols_column *) data;
|
||
|
+ struct libscols_line *ra, *rb;
|
||
|
+ struct libscols_cell *ca, *cb;
|
||
|
+
|
||
|
+ assert(a);
|
||
|
+ assert(b);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ ra = list_entry(a, struct libscols_line, ln_lines);
|
||
|
+ rb = list_entry(b, struct libscols_line, ln_lines);
|
||
|
+ ca = scols_line_get_cell(ra, cl->seqnum);
|
||
|
+ cb = scols_line_get_cell(rb, cl->seqnum);
|
||
|
+
|
||
|
+ return cl->cmpfunc(ca, cb, cl->cmpfunc_data);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_sort_table:
|
||
|
+ * @tb: table
|
||
|
+ * @cl: order by this column
|
||
|
+ *
|
||
|
+ * Orders the table by the column. See also scols_column_set_cmpfunc().
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl)
|
||
|
+{
|
||
|
+ assert(tb);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ if (!tb || !cl)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "sorting table"));
|
||
|
+ list_sort(&tb->tb_lines, cells_cmp_wrapper, cl);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/table_print.c.kzak util-linux-2.23.2/libsmartcols/src/table_print.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/table_print.c.kzak 2014-09-25 14:41:48.992843944 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/table_print.c 2014-09-25 14:41:48.992843944 +0200
|
||
|
@@ -0,0 +1,841 @@
|
||
|
+/*
|
||
|
+ * table.c - functions handling the data at the table level
|
||
|
+ *
|
||
|
+ * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: table_print
|
||
|
+ * @title: Table print
|
||
|
+ * @short_description: table print API
|
||
|
+ *
|
||
|
+ * Table output API.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+#include <termios.h>
|
||
|
+#include <ctype.h>
|
||
|
+
|
||
|
+#include "nls.h"
|
||
|
+#include "mbsalign.h"
|
||
|
+#include "widechar.h"
|
||
|
+#include "ttyutils.h"
|
||
|
+#include "carefulputc.h"
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+/* This is private struct to work with output data */
|
||
|
+struct libscols_buffer {
|
||
|
+ char *begin; /* begin of the buffer */
|
||
|
+ char *cur; /* current end of the buffer */
|
||
|
+ char *encdata; /* encoded buffer mbs_safe_encode() */
|
||
|
+
|
||
|
+ size_t bufsz; /* size of the buffer */
|
||
|
+ size_t art_idx; /* begin of the tree ascii art or zero */
|
||
|
+};
|
||
|
+
|
||
|
+static struct libscols_buffer *new_buffer(size_t sz)
|
||
|
+{
|
||
|
+ struct libscols_buffer *buf = malloc(sz + sizeof(struct libscols_buffer));
|
||
|
+
|
||
|
+ if (!buf)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ buf->cur = buf->begin = ((char *) buf) + sizeof(struct libscols_buffer);
|
||
|
+ buf->encdata = NULL;
|
||
|
+ buf->bufsz = sz;
|
||
|
+
|
||
|
+ DBG(BUFF, ul_debugobj(buf, "alloc (size=%zu)", sz));
|
||
|
+ return buf;
|
||
|
+}
|
||
|
+
|
||
|
+static void free_buffer(struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ if (!buf)
|
||
|
+ return;
|
||
|
+ DBG(BUFF, ul_debugobj(buf, "dealloc"));
|
||
|
+ free(buf->encdata);
|
||
|
+ free(buf);
|
||
|
+}
|
||
|
+
|
||
|
+static int buffer_reset_data(struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ if (!buf)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ /*DBG(BUFF, ul_debugobj(buf, "reset data"));*/
|
||
|
+ buf->begin[0] = '\0';
|
||
|
+ buf->cur = buf->begin;
|
||
|
+ buf->art_idx = 0;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int buffer_append_data(struct libscols_buffer *buf, const char *str)
|
||
|
+{
|
||
|
+ size_t maxsz, sz;
|
||
|
+
|
||
|
+ if (!buf)
|
||
|
+ return -EINVAL;
|
||
|
+ if (!str || !*str)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ sz = strlen(str);
|
||
|
+ maxsz = buf->bufsz - (buf->cur - buf->begin);
|
||
|
+
|
||
|
+ if (maxsz <= sz)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ memcpy(buf->cur, str, sz + 1);
|
||
|
+ buf->cur += sz;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int buffer_set_data(struct libscols_buffer *buf, const char *str)
|
||
|
+{
|
||
|
+ int rc = buffer_reset_data(buf);
|
||
|
+ return rc ? rc : buffer_append_data(buf, str);
|
||
|
+}
|
||
|
+
|
||
|
+/* save the current buffer possition to art_idx */
|
||
|
+static void buffer_set_art_index(struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ if (buf) {
|
||
|
+ buf->art_idx = buf->cur - buf->begin;
|
||
|
+ /*DBG(BUFF, ul_debugobj(buf, "art index: %zu", buf->art_idx));*/
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static char *buffer_get_data(struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ return buf ? buf->begin : NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/* encode data by mbs_safe_encode() to avoid control and non-printable chars */
|
||
|
+static char *buffer_get_safe_data(struct libscols_buffer *buf, size_t *cells)
|
||
|
+{
|
||
|
+ char *data = buffer_get_data(buf);
|
||
|
+ char *res = NULL;
|
||
|
+
|
||
|
+ if (!data)
|
||
|
+ goto nothing;
|
||
|
+
|
||
|
+ if (!buf->encdata) {
|
||
|
+ buf->encdata = malloc(mbs_safe_encode_size(buf->bufsz) + 1);
|
||
|
+ if (!buf->encdata)
|
||
|
+ goto nothing;
|
||
|
+ }
|
||
|
+
|
||
|
+ res = mbs_safe_encode_to_buffer(data, cells, buf->encdata);
|
||
|
+ if (!res || !*cells || *cells == (size_t) -1)
|
||
|
+ goto nothing;
|
||
|
+ return res;
|
||
|
+nothing:
|
||
|
+ *cells = 0;
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+/* returns size in bytes of the ascii art (according to art_idx) in safe encoding */
|
||
|
+static size_t buffer_get_safe_art_size(struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ char *data = buffer_get_data(buf);
|
||
|
+ size_t bytes = 0;
|
||
|
+
|
||
|
+ if (!data || !buf->art_idx)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ mbs_safe_nwidth(data, buf->art_idx, &bytes);
|
||
|
+ return bytes;
|
||
|
+}
|
||
|
+
|
||
|
+#define is_last_column(_tb, _cl) \
|
||
|
+ list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns)
|
||
|
+
|
||
|
+#define colsep(tb) ((tb)->colsep ? (tb)->colsep : " ")
|
||
|
+#define linesep(tb) ((tb)->linesep ? (tb)->linesep : "\n")
|
||
|
+
|
||
|
+static int print_data(struct libscols_table *tb,
|
||
|
+ struct libscols_column *cl,
|
||
|
+ struct libscols_line *ln, /* optional */
|
||
|
+ struct libscols_cell *ce, /* optional */
|
||
|
+ struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ size_t len = 0, i, width, bytes;
|
||
|
+ const char *color = NULL;
|
||
|
+ char *data;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb,
|
||
|
+ " -> data, column=%p, line=%p, cell=%p, buff=%p",
|
||
|
+ cl, ln, ce, buf));
|
||
|
+
|
||
|
+ data = buffer_get_data(buf);
|
||
|
+ if (!data)
|
||
|
+ data = "";
|
||
|
+
|
||
|
+ /* raw mode */
|
||
|
+ if (scols_table_is_raw(tb)) {
|
||
|
+ fputs_nonblank(data, tb->out);
|
||
|
+ if (!is_last_column(tb, cl))
|
||
|
+ fputs(colsep(tb), tb->out);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* NAME=value mode */
|
||
|
+ if (scols_table_is_export(tb)) {
|
||
|
+ fprintf(tb->out, "%s=", scols_cell_get_data(&cl->header));
|
||
|
+ fputs_quoted(data, tb->out);
|
||
|
+ if (!is_last_column(tb, cl))
|
||
|
+ fputs(colsep(tb), tb->out);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (tb->colors_wanted) {
|
||
|
+ if (ce && !color)
|
||
|
+ color = ce->color;
|
||
|
+ if (ln && !color)
|
||
|
+ color = ln->color;
|
||
|
+ if (!color)
|
||
|
+ color = cl->color;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* encode, note that 'len' and 'width' are number of cells, not bytes */
|
||
|
+ data = buffer_get_safe_data(buf, &len);
|
||
|
+ if (!data)
|
||
|
+ data = "";
|
||
|
+ width = cl->width;
|
||
|
+ bytes = strlen(data);
|
||
|
+
|
||
|
+ if (is_last_column(tb, cl) && len < width && !scols_table_is_maxout(tb))
|
||
|
+ width = len;
|
||
|
+
|
||
|
+ /* truncate data */
|
||
|
+ if (len > width && scols_column_is_trunc(cl)) {
|
||
|
+ len = width;
|
||
|
+ bytes = mbs_truncate(data, &len); /* updates 'len' */
|
||
|
+
|
||
|
+ if (!data || bytes == (size_t) -1) {
|
||
|
+ bytes = len = 0;
|
||
|
+ data = NULL;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (data) {
|
||
|
+ if (scols_column_is_right(cl)) {
|
||
|
+ size_t xw = cl->width;
|
||
|
+ if (color)
|
||
|
+ fputs(color, tb->out);
|
||
|
+ fprintf(tb->out, "%*s", (int) xw, data);
|
||
|
+ if (color)
|
||
|
+ fputs(UL_COLOR_RESET, tb->out);
|
||
|
+ if (len < xw)
|
||
|
+ len = xw;
|
||
|
+ } else if (color) {
|
||
|
+ char *p = data;
|
||
|
+ size_t art = buffer_get_safe_art_size(buf);
|
||
|
+
|
||
|
+ /* we don't want to colorize tree ascii art */
|
||
|
+ if (scols_column_is_tree(cl) && art && art < bytes) {
|
||
|
+ fwrite(p, 1, art, tb->out);
|
||
|
+ p += art;
|
||
|
+ }
|
||
|
+
|
||
|
+ fputs(color, tb->out);
|
||
|
+ fputs(p, tb->out);
|
||
|
+ fputs(UL_COLOR_RESET, tb->out);
|
||
|
+ } else
|
||
|
+ fputs(data, tb->out);
|
||
|
+ }
|
||
|
+ for (i = len; i < width; i++)
|
||
|
+ fputs(" ", tb->out); /* padding */
|
||
|
+
|
||
|
+ if (!is_last_column(tb, cl)) {
|
||
|
+ if (len > width && !scols_column_is_trunc(cl)) {
|
||
|
+ fputs(linesep(tb), tb->out);
|
||
|
+ for (i = 0; i <= (size_t) cl->seqnum; i++) {
|
||
|
+ struct libscols_column *x = scols_table_get_column(tb, i);
|
||
|
+ fprintf(tb->out, "%*s ", -((int)x->width), " ");
|
||
|
+ }
|
||
|
+ } else
|
||
|
+ fputs(colsep(tb), tb->out); /* columns separator */
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/* returns pointer to the end of used data */
|
||
|
+static int line_ascii_art_to_buffer(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln,
|
||
|
+ struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ const char *art;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ assert(ln);
|
||
|
+ assert(buf);
|
||
|
+
|
||
|
+ if (!ln->parent)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ rc = line_ascii_art_to_buffer(tb, ln->parent, buf);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch))
|
||
|
+ art = " ";
|
||
|
+ else
|
||
|
+ art = tb->symbols->vert;
|
||
|
+
|
||
|
+ return buffer_append_data(buf, art);
|
||
|
+}
|
||
|
+
|
||
|
+static int cell_to_buffer(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln,
|
||
|
+ struct libscols_column *cl,
|
||
|
+ struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ const char *data;
|
||
|
+ struct libscols_cell *ce;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ assert(ln);
|
||
|
+ assert(cl);
|
||
|
+ assert(buf);
|
||
|
+ assert(cl->seqnum <= tb->ncols);
|
||
|
+
|
||
|
+ buffer_reset_data(buf);
|
||
|
+
|
||
|
+ ce = scols_line_get_cell(ln, cl->seqnum);
|
||
|
+ data = ce ? scols_cell_get_data(ce) : NULL;
|
||
|
+ if (!data)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (!scols_column_is_tree(cl))
|
||
|
+ return buffer_set_data(buf, data);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Tree stuff
|
||
|
+ */
|
||
|
+ if (ln->parent) {
|
||
|
+ rc = line_ascii_art_to_buffer(tb, ln->parent, buf);
|
||
|
+
|
||
|
+ if (!rc && list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch))
|
||
|
+ rc = buffer_append_data(buf, tb->symbols->right);
|
||
|
+ else if (!rc)
|
||
|
+ rc = buffer_append_data(buf, tb->symbols->branch);
|
||
|
+ if (!rc)
|
||
|
+ buffer_set_art_index(buf);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!rc)
|
||
|
+ rc = buffer_append_data(buf, data);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Prints data, data maybe be printed in more formats (raw, NAME=xxx pairs) and
|
||
|
+ * control and non-printable chars maybe encoded in \x?? hex encoding.
|
||
|
+ */
|
||
|
+static int print_line(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln,
|
||
|
+ struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ int rc = 0;
|
||
|
+ struct libscols_column *cl;
|
||
|
+ struct libscols_iter itr;
|
||
|
+
|
||
|
+ assert(ln);
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "printing line, line=%p, buff=%p", ln, buf));
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ rc = cell_to_buffer(tb, ln, cl, buf);
|
||
|
+ if (!rc)
|
||
|
+ rc = print_data(tb, cl, ln,
|
||
|
+ scols_line_get_cell(ln, cl->seqnum),
|
||
|
+ buf);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (rc == 0)
|
||
|
+ fputs(linesep(tb), tb->out);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int print_header(struct libscols_table *tb, struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ int rc = 0;
|
||
|
+ struct libscols_column *cl;
|
||
|
+ struct libscols_iter itr;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+
|
||
|
+ if (scols_table_is_noheadings(tb) ||
|
||
|
+ scols_table_is_export(tb) ||
|
||
|
+ list_empty(&tb->tb_lines))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "printing header"));
|
||
|
+
|
||
|
+ /* set width according to the size of data
|
||
|
+ */
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ rc = buffer_set_data(buf, scols_cell_get_data(&cl->header));
|
||
|
+ if (!rc)
|
||
|
+ rc = print_data(tb, cl, NULL, &cl->header, buf);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (rc == 0)
|
||
|
+ fputs(linesep(tb), tb->out);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int print_table(struct libscols_table *tb, struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ struct libscols_line *ln;
|
||
|
+ struct libscols_iter itr;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+
|
||
|
+ rc = print_header(tb, buf);
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0)
|
||
|
+ rc = print_line(tb, ln, buf);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int print_tree_line(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln,
|
||
|
+ struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ struct list_head *p;
|
||
|
+
|
||
|
+ rc = print_line(tb, ln, buf);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+ if (list_empty(&ln->ln_branch))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ /* print all children */
|
||
|
+ list_for_each(p, &ln->ln_branch) {
|
||
|
+ struct libscols_line *chld =
|
||
|
+ list_entry(p, struct libscols_line, ln_children);
|
||
|
+ rc = print_tree_line(tb, chld, buf);
|
||
|
+ if (rc)
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int print_tree(struct libscols_table *tb, struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ struct libscols_line *ln;
|
||
|
+ struct libscols_iter itr;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "printing tree"));
|
||
|
+
|
||
|
+ rc = print_header(tb, buf);
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0) {
|
||
|
+ if (ln->parent)
|
||
|
+ continue;
|
||
|
+ rc = print_tree_line(tb, ln, buf);
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static void dbg_column(struct libscols_table *tb, struct libscols_column *cl)
|
||
|
+{
|
||
|
+ DBG(COL, ul_debugobj(cl, "%15s seq=%zu, width=%zd, "
|
||
|
+ "hint=%d, avg=%zu, max=%zu, min=%zu, "
|
||
|
+ "extreme=%s",
|
||
|
+
|
||
|
+ cl->header.data, cl->seqnum, cl->width,
|
||
|
+ cl->width_hint > 1 ? (int) cl->width_hint :
|
||
|
+ (int) (cl->width_hint * tb->termwidth),
|
||
|
+ cl->width_avg,
|
||
|
+ cl->width_max,
|
||
|
+ cl->width_min,
|
||
|
+ cl->is_extreme ? "yes" : "not"));
|
||
|
+}
|
||
|
+
|
||
|
+static void dbg_columns(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ struct libscols_iter itr;
|
||
|
+ struct libscols_column *cl;
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0)
|
||
|
+ dbg_column(tb, cl);
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * This function counts column width.
|
||
|
+ *
|
||
|
+ * For the SCOLS_FL_NOEXTREMES columns is possible to call this function two
|
||
|
+ * times. The first pass counts width and average width. If the column
|
||
|
+ * contains too large fields (width greater than 2 * average) then the column
|
||
|
+ * is marked as "extreme". In the second pass all extreme fields are ignored
|
||
|
+ * and column width is counted from non-extreme fields only.
|
||
|
+ */
|
||
|
+static int count_column_width(struct libscols_table *tb,
|
||
|
+ struct libscols_column *cl,
|
||
|
+ struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ struct libscols_line *ln;
|
||
|
+ struct libscols_iter itr;
|
||
|
+ int count = 0, rc = 0;
|
||
|
+ size_t sum = 0;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ assert(cl);
|
||
|
+
|
||
|
+ cl->width = 0;
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_line(tb, &itr, &ln) == 0) {
|
||
|
+ size_t len;
|
||
|
+ char *data;
|
||
|
+
|
||
|
+ rc = cell_to_buffer(tb, ln, cl, buf);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ data = buffer_get_data(buf);
|
||
|
+ len = data ? mbs_safe_width(data) : 0;
|
||
|
+
|
||
|
+ if (len == (size_t) -1) /* ignore broken multibyte strings */
|
||
|
+ len = 0;
|
||
|
+ if (len > cl->width_max)
|
||
|
+ cl->width_max = len;
|
||
|
+
|
||
|
+ if (cl->is_extreme && len > cl->width_avg * 2)
|
||
|
+ continue;
|
||
|
+ else if (scols_column_is_noextremes(cl)) {
|
||
|
+ sum += len;
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+ if (len > cl->width)
|
||
|
+ cl->width = len;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (count && cl->width_avg == 0) {
|
||
|
+ cl->width_avg = sum / count;
|
||
|
+
|
||
|
+ if (cl->width_max > cl->width_avg * 2)
|
||
|
+ cl->is_extreme = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* check and set minimal column width */
|
||
|
+ if (scols_cell_get_data(&cl->header))
|
||
|
+ cl->width_min = mbs_safe_width(scols_cell_get_data(&cl->header));
|
||
|
+
|
||
|
+ /* enlarge to minimal width */
|
||
|
+ if (cl->width < cl->width_min && !scols_column_is_strict_width(cl))
|
||
|
+ cl->width = cl->width_min;
|
||
|
+
|
||
|
+ /* use relative size for large columns */
|
||
|
+ else if (cl->width_hint >= 1 && cl->width < (size_t) cl->width_hint
|
||
|
+ && cl->width_min < (size_t) cl->width_hint)
|
||
|
+
|
||
|
+ cl->width = (size_t) cl->width_hint;
|
||
|
+
|
||
|
+ ON_DBG(COL, dbg_column(tb, cl));
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/*
|
||
|
+ * This is core of the scols_* voodo...
|
||
|
+ */
|
||
|
+static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf)
|
||
|
+{
|
||
|
+ struct libscols_column *cl;
|
||
|
+ struct libscols_iter itr;
|
||
|
+ size_t width = 0; /* output width */
|
||
|
+ int trunc_only, rc = 0;
|
||
|
+ int extremes = 0;
|
||
|
+
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "recounting widths (termwidth=%zu)", tb->termwidth));
|
||
|
+
|
||
|
+ /* set basic columns width
|
||
|
+ */
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ rc = count_column_width(tb, cl, buf);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ width += cl->width + (is_last_column(tb, cl) ? 0 : 1);
|
||
|
+ extremes += cl->is_extreme;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!tb->is_term)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ /* reduce columns with extreme fields
|
||
|
+ */
|
||
|
+ if (width > tb->termwidth && extremes) {
|
||
|
+ DBG(TAB, ul_debugobj(tb, " reduce width (extreme columns)"));
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ size_t org_width;
|
||
|
+
|
||
|
+ if (!cl->is_extreme)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ org_width = cl->width;
|
||
|
+ rc = count_column_width(tb, cl, buf);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ if (org_width > cl->width)
|
||
|
+ width -= org_width - cl->width;
|
||
|
+ else
|
||
|
+ extremes--; /* hmm... nothing reduced */
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (width < tb->termwidth) {
|
||
|
+ if (extremes) {
|
||
|
+ DBG(TAB, ul_debugobj(tb, " enlarge width (extreme columns)"));
|
||
|
+
|
||
|
+ /* enlarge the first extreme column */
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ size_t add;
|
||
|
+
|
||
|
+ if (!cl->is_extreme)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ /* this column is tooo large, ignore?
|
||
|
+ if (cl->width_max - cl->width >
|
||
|
+ (tb->termwidth - width))
|
||
|
+ continue;
|
||
|
+ */
|
||
|
+
|
||
|
+ add = tb->termwidth - width;
|
||
|
+ if (add && cl->width + add > cl->width_max)
|
||
|
+ add = cl->width_max - cl->width;
|
||
|
+
|
||
|
+ cl->width += add;
|
||
|
+ width += add;
|
||
|
+
|
||
|
+ if (width == tb->termwidth)
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (width < tb->termwidth && scols_table_is_maxout(tb)) {
|
||
|
+ DBG(TAB, ul_debugobj(tb, " enlarge width (max-out)"));
|
||
|
+
|
||
|
+ /* try enlarge all columns */
|
||
|
+ while (width < tb->termwidth) {
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ cl->width++;
|
||
|
+ width++;
|
||
|
+ if (width == tb->termwidth)
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } else if (width < tb->termwidth) {
|
||
|
+ /* enlarge the last column */
|
||
|
+ struct libscols_column *cl = list_entry(
|
||
|
+ tb->tb_columns.prev, struct libscols_column, cl_columns);
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, " enlarge width (last column)"));
|
||
|
+
|
||
|
+ if (!scols_column_is_right(cl) && tb->termwidth - width > 0) {
|
||
|
+ cl->width += tb->termwidth - width;
|
||
|
+ width = tb->termwidth;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* bad, we have to reduce output width, this is done in two steps:
|
||
|
+ * 1/ reduce columns with a relative width and with truncate flag
|
||
|
+ * 2) reduce columns with a relative width without truncate flag
|
||
|
+ */
|
||
|
+ trunc_only = 1;
|
||
|
+ while (width > tb->termwidth) {
|
||
|
+ size_t org = width;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, " reduce width (current=%zu, "
|
||
|
+ "wanted=%zu, mode=%s)",
|
||
|
+ width, tb->termwidth,
|
||
|
+ trunc_only ? "trunc-only" : "all-relative"));
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_column(tb, &itr, &cl) == 0) {
|
||
|
+ if (width <= tb->termwidth)
|
||
|
+ break;
|
||
|
+ if (cl->width_hint > 1 && !scols_column_is_trunc(cl))
|
||
|
+ continue; /* never truncate columns with absolute sizes */
|
||
|
+ if (scols_column_is_tree(cl))
|
||
|
+ continue; /* never truncate the tree */
|
||
|
+ if (trunc_only && !scols_column_is_trunc(cl))
|
||
|
+ continue;
|
||
|
+ if (cl->width == cl->width_min)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ /* truncate column with relative sizes */
|
||
|
+ if (cl->width_hint < 1 && cl->width > 0 && width > 0 &&
|
||
|
+ cl->width > cl->width_hint * tb->termwidth) {
|
||
|
+ cl->width--;
|
||
|
+ width--;
|
||
|
+ }
|
||
|
+ /* truncate column with absolute size */
|
||
|
+ if (cl->width_hint > 1 && cl->width > 0 && width > 0 &&
|
||
|
+ !trunc_only) {
|
||
|
+ cl->width--;
|
||
|
+ width--;
|
||
|
+ }
|
||
|
+
|
||
|
+ }
|
||
|
+ if (org == width) {
|
||
|
+ if (trunc_only)
|
||
|
+ trunc_only = 0;
|
||
|
+ else
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, " result: %zu", width));
|
||
|
+ ON_DBG(TAB, dbg_columns(tb));
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static size_t strlen_line(struct libscols_line *ln)
|
||
|
+{
|
||
|
+ size_t i, sz = 0;
|
||
|
+
|
||
|
+ assert(ln);
|
||
|
+
|
||
|
+ for (i = 0; i < ln->ncells; i++) {
|
||
|
+ struct libscols_cell *ce = scols_line_get_cell(ln, i);
|
||
|
+ const char *data = ce ? scols_cell_get_data(ce) : NULL;
|
||
|
+
|
||
|
+ sz += data ? strlen(data) : 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return sz;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_print_table:
|
||
|
+ * @tb: table
|
||
|
+ *
|
||
|
+ * Prints the table to the output stream.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_print_table(struct libscols_table *tb)
|
||
|
+{
|
||
|
+ int rc = 0;
|
||
|
+ size_t bufsz;
|
||
|
+ struct libscols_line *ln;
|
||
|
+ struct libscols_iter itr;
|
||
|
+ struct libscols_buffer *buf;
|
||
|
+
|
||
|
+ assert(tb);
|
||
|
+ if (!tb)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "printing"));
|
||
|
+ if (!tb->symbols)
|
||
|
+ scols_table_set_symbols(tb, NULL); /* use default */
|
||
|
+
|
||
|
+ tb->is_term = isatty(STDOUT_FILENO) ? 1 : 0;
|
||
|
+ tb->termwidth = tb->is_term ? get_terminal_width() : 0;
|
||
|
+ if (tb->termwidth <= 0)
|
||
|
+ tb->termwidth = 80;
|
||
|
+ tb->termwidth -= tb->termreduce;
|
||
|
+
|
||
|
+ bufsz = tb->termwidth;
|
||
|
+
|
||
|
+ scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
|
||
|
+ while (scols_table_next_line(tb, &itr, &ln) == 0) {
|
||
|
+ size_t sz = strlen_line(ln);
|
||
|
+ if (sz > bufsz)
|
||
|
+ bufsz = sz;
|
||
|
+ }
|
||
|
+
|
||
|
+ buf = new_buffer(bufsz + 1); /* data + space for \0 */
|
||
|
+ if (!buf)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ if (!(scols_table_is_raw(tb) || scols_table_is_export(tb))) {
|
||
|
+ rc = recount_widths(tb, buf);
|
||
|
+ if (rc != 0)
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (scols_table_is_tree(tb))
|
||
|
+ rc = print_tree(tb, buf);
|
||
|
+ else
|
||
|
+ rc = print_table(tb, buf);
|
||
|
+
|
||
|
+done:
|
||
|
+ free_buffer(buf);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_print_table_to_string:
|
||
|
+ * @tb: table
|
||
|
+ * @data: pointer to the beginning of a memory area to print to
|
||
|
+ *
|
||
|
+ * Prints the table to @data.
|
||
|
+ *
|
||
|
+ * Returns: 0, a negative value in case of an error.
|
||
|
+ */
|
||
|
+int scols_print_table_to_string(struct libscols_table *tb, char **data)
|
||
|
+{
|
||
|
+#ifdef HAVE_OPEN_MEMSTREAM
|
||
|
+ FILE *stream;
|
||
|
+ size_t sz;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ if (!tb)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ DBG(TAB, ul_debugobj(tb, "printing to string"));
|
||
|
+
|
||
|
+ /* create a stream for output */
|
||
|
+ stream = open_memstream(data, &sz);
|
||
|
+ if (!stream)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ scols_table_set_stream(tb, stream);
|
||
|
+ rc = scols_print_table(tb);
|
||
|
+ fclose(stream);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+#else
|
||
|
+ return -ENOSYS;
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/test.c.kzak util-linux-2.23.2/libsmartcols/src/test.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/test.c.kzak 2014-09-25 14:41:48.993843953 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/test.c 2014-09-25 14:41:48.993843953 +0200
|
||
|
@@ -0,0 +1,218 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * This file may be redistributed under the terms of the
|
||
|
+ * GNU Lesser General Public License.
|
||
|
+ */
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <string.h>
|
||
|
+#include <errno.h>
|
||
|
+#include <sys/types.h>
|
||
|
+#include <sys/stat.h>
|
||
|
+#include <dirent.h>
|
||
|
+#include <getopt.h>
|
||
|
+
|
||
|
+#include "c.h"
|
||
|
+#include "nls.h"
|
||
|
+#include "strutils.h"
|
||
|
+
|
||
|
+#include "libsmartcols.h"
|
||
|
+
|
||
|
+static int add_children(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln, int fd);
|
||
|
+
|
||
|
+
|
||
|
+enum { COL_MODE, COL_SIZE, COL_NAME };
|
||
|
+
|
||
|
+/* add columns to the @tb */
|
||
|
+static void setup_columns(struct libscols_table *tb, int notree)
|
||
|
+{
|
||
|
+ if (!scols_table_new_column(tb, "MODE", 0.3, 0))
|
||
|
+ goto fail;
|
||
|
+ if (!scols_table_new_column(tb, "SIZE", 5, SCOLS_FL_RIGHT))
|
||
|
+ goto fail;
|
||
|
+ if (!scols_table_new_column(tb, "NAME", 0.5,
|
||
|
+ (notree ? 0 : SCOLS_FL_TREE) | SCOLS_FL_NOEXTREMES))
|
||
|
+ goto fail;
|
||
|
+
|
||
|
+ return;
|
||
|
+fail:
|
||
|
+ scols_unref_table(tb);
|
||
|
+ err(EXIT_FAILURE, "faild to create output columns");
|
||
|
+}
|
||
|
+
|
||
|
+/* add a new line to @tb, the content is based on @st */
|
||
|
+static int add_line_from_stat(struct libscols_table *tb,
|
||
|
+ struct libscols_line *parent,
|
||
|
+ int parent_fd,
|
||
|
+ struct stat *st,
|
||
|
+ const char *name)
|
||
|
+{
|
||
|
+ struct libscols_line *ln;
|
||
|
+ char modbuf[11], *p;
|
||
|
+ mode_t mode = st->st_mode;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ ln = scols_table_new_line(tb, parent);
|
||
|
+ if (!ln)
|
||
|
+ err(EXIT_FAILURE, "failed to create output line");
|
||
|
+
|
||
|
+ /* MODE; local buffer, use scols_line_set_data() that calls strdup() */
|
||
|
+ strmode(mode, modbuf);
|
||
|
+ if (scols_line_set_data(ln, COL_MODE, modbuf))
|
||
|
+ goto fail;
|
||
|
+
|
||
|
+ /* SIZE; already allocated string, use scols_line_refer_data() */
|
||
|
+ p = size_to_human_string(0, st->st_size);
|
||
|
+ if (!p || scols_line_refer_data(ln, COL_SIZE, p))
|
||
|
+ goto fail;
|
||
|
+
|
||
|
+ /* NAME */
|
||
|
+ if (scols_line_set_data(ln, COL_NAME, name))
|
||
|
+ goto fail;
|
||
|
+
|
||
|
+ /* colors */
|
||
|
+ if (scols_table_colors_wanted(tb)) {
|
||
|
+ struct libscols_cell *ce = scols_line_get_cell(ln, COL_NAME);
|
||
|
+
|
||
|
+ if (S_ISDIR(mode))
|
||
|
+ scols_cell_set_color(ce, "blue");
|
||
|
+ else if (S_ISLNK(mode))
|
||
|
+ scols_cell_set_color(ce, "cyan");
|
||
|
+ else if (S_ISBLK(mode))
|
||
|
+ scols_cell_set_color(ce, "magenta");
|
||
|
+ else if ((mode & S_IXOTH) || (mode & S_IXGRP) || (mode & S_IXUSR))
|
||
|
+ scols_cell_set_color(ce, "green");
|
||
|
+ }
|
||
|
+
|
||
|
+ if (S_ISDIR(st->st_mode)) {
|
||
|
+ int fd;
|
||
|
+
|
||
|
+ if (parent_fd >= 0)
|
||
|
+ fd = openat(parent_fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
|
||
|
+ else
|
||
|
+ fd = open(name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
|
||
|
+ if (fd >= 0) {
|
||
|
+ rc = add_children(tb, ln, fd);
|
||
|
+ close(fd);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return rc;
|
||
|
+fail:
|
||
|
+ err(EXIT_FAILURE, "failed to create cell data");
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+/* read all entrines from directory addressed by @fd */
|
||
|
+static int add_children(struct libscols_table *tb,
|
||
|
+ struct libscols_line *ln,
|
||
|
+ int fd)
|
||
|
+{
|
||
|
+ DIR *dir;
|
||
|
+ struct dirent *d;
|
||
|
+
|
||
|
+ dir = fdopendir(fd);
|
||
|
+ if (!dir)
|
||
|
+ return -errno;
|
||
|
+
|
||
|
+ while ((d = readdir(dir))) {
|
||
|
+ struct stat st;
|
||
|
+
|
||
|
+ if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0)
|
||
|
+ continue;
|
||
|
+ if (fstatat(fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0)
|
||
|
+ continue;
|
||
|
+ add_line_from_stat(tb, ln, fd, &st, d->d_name);
|
||
|
+ }
|
||
|
+ closedir(dir);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void add_lines(struct libscols_table *tb, const char *dirname)
|
||
|
+{
|
||
|
+ struct stat st;
|
||
|
+
|
||
|
+ if (lstat(dirname, &st))
|
||
|
+ err(EXIT_FAILURE, "%s", dirname);
|
||
|
+
|
||
|
+ add_line_from_stat(tb, NULL, -1, &st, dirname);
|
||
|
+}
|
||
|
+
|
||
|
+static void __attribute__((__noreturn__)) usage(FILE *out)
|
||
|
+{
|
||
|
+ fprintf(out, " %s [options] [<dir> ...]\n\n", program_invocation_short_name);
|
||
|
+ fputs(" -c, --csv display a csv-like output\n", out);
|
||
|
+ fputs(" -i, --ascii use ascii characters only\n", out);
|
||
|
+ fputs(" -l, --list use list format output\n", out);
|
||
|
+ fputs(" -n, --noheadings don't print headings\n", out);
|
||
|
+ fputs(" -p, --pairs use key=\"value\" output format\n", out);
|
||
|
+ fputs(" -r, --raw use raw output format\n", out);
|
||
|
+
|
||
|
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||
|
+}
|
||
|
+
|
||
|
+int main(int argc, char *argv[])
|
||
|
+{
|
||
|
+ struct libscols_table *tb;
|
||
|
+ int c, notree = 0;
|
||
|
+
|
||
|
+ static const struct option longopts[] = {
|
||
|
+ { "ascii", 0, 0, 'i' },
|
||
|
+ { "csv", 0, 0, 'c' },
|
||
|
+ { "list", 0, 0, 'l' },
|
||
|
+ { "noheadings", 0, 0, 'n' },
|
||
|
+ { "pairs", 0, 0, 'p' },
|
||
|
+ { "raw", 0, 0, 'r' },
|
||
|
+
|
||
|
+ { NULL, 0, 0, 0 },
|
||
|
+ };
|
||
|
+
|
||
|
+ setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */
|
||
|
+
|
||
|
+ scols_init_debug(0);
|
||
|
+
|
||
|
+ tb = scols_new_table();
|
||
|
+ if (!tb)
|
||
|
+ err(EXIT_FAILURE, "faild to create output table");
|
||
|
+
|
||
|
+ while((c = getopt_long(argc, argv, "cilnpr", longopts, NULL)) != -1) {
|
||
|
+ switch(c) {
|
||
|
+ case 'c':
|
||
|
+ scols_table_set_column_separator(tb, ",");
|
||
|
+ scols_table_enable_raw(tb, 1);
|
||
|
+ notree = 1;
|
||
|
+ break;
|
||
|
+ case 'i':
|
||
|
+ scols_table_enable_ascii(tb, 1);
|
||
|
+ break;
|
||
|
+ case 'l':
|
||
|
+ notree = 1;
|
||
|
+ break;
|
||
|
+ case 'n':
|
||
|
+ scols_table_enable_noheadings(tb, 1);
|
||
|
+ break;
|
||
|
+ case 'p':
|
||
|
+ scols_table_enable_export(tb, 1);
|
||
|
+ notree = 1;
|
||
|
+ break;
|
||
|
+ case 'r':
|
||
|
+ scols_table_enable_raw(tb, 1);
|
||
|
+ notree = 1;
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ usage(stderr);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ scols_table_enable_colors(tb, 1);
|
||
|
+ setup_columns(tb, notree);
|
||
|
+
|
||
|
+ while (optind < argc)
|
||
|
+ add_lines(tb, argv[optind++]);
|
||
|
+
|
||
|
+ scols_print_table(tb);
|
||
|
+ scols_unref_table(tb);
|
||
|
+
|
||
|
+ return EXIT_SUCCESS;
|
||
|
+}
|
||
|
diff -up util-linux-2.23.2/libsmartcols/src/version.c.kzak util-linux-2.23.2/libsmartcols/src/version.c
|
||
|
--- util-linux-2.23.2/libsmartcols/src/version.c.kzak 2014-09-25 14:41:48.993843953 +0200
|
||
|
+++ util-linux-2.23.2/libsmartcols/src/version.c 2014-09-25 14:41:48.993843953 +0200
|
||
|
@@ -0,0 +1,62 @@
|
||
|
+/*
|
||
|
+ * version.c - Return the version of the library
|
||
|
+ *
|
||
|
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
||
|
+ *
|
||
|
+ * See COPYING.libmount for the License of this software.
|
||
|
+ */
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: version-utils
|
||
|
+ * @title: Version functions
|
||
|
+ * @short_description: functions to get the library version.
|
||
|
+ *
|
||
|
+ * Note that library version is not the same thing as SONAME version. The
|
||
|
+ * libsmarcols uses symbols versioning and SONAME is not modified for releases.
|
||
|
+ *
|
||
|
+ * The library version and symbols version follow util-linux package versioning.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <ctype.h>
|
||
|
+
|
||
|
+#include "smartcolsP.h"
|
||
|
+
|
||
|
+static const char *lib_version = LIBSMARTCOLS_VERSION;
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_parse_version_string:
|
||
|
+ * @ver_string: version string (e.g "2.18.0")
|
||
|
+ *
|
||
|
+ * Returns: release version code.
|
||
|
+ */
|
||
|
+int scols_parse_version_string(const char *ver_string)
|
||
|
+{
|
||
|
+ const char *cp;
|
||
|
+ int version = 0;
|
||
|
+
|
||
|
+ assert(ver_string);
|
||
|
+
|
||
|
+ for (cp = ver_string; *cp; cp++) {
|
||
|
+ if (*cp == '.')
|
||
|
+ continue;
|
||
|
+ if (!isdigit(*cp))
|
||
|
+ break;
|
||
|
+ version = (version * 10) + (*cp - '0');
|
||
|
+ }
|
||
|
+ return version;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * scols_get_library_version:
|
||
|
+ * @ver_string: return pointer to the static library version string if not NULL
|
||
|
+ *
|
||
|
+ * Returns: release version number.
|
||
|
+ */
|
||
|
+int scols_get_library_version(const char **ver_string)
|
||
|
+{
|
||
|
+ if (ver_string)
|
||
|
+ *ver_string = lib_version;
|
||
|
+
|
||
|
+ return scols_parse_version_string(lib_version);
|
||
|
+}
|
||
|
+
|
||
|
diff -up util-linux-2.23.2/lib/tt.c.kzak util-linux-2.23.2/lib/tt.c
|
||
|
--- util-linux-2.23.2/lib/tt.c.kzak 2013-07-15 10:25:46.280049032 +0200
|
||
|
+++ util-linux-2.23.2/lib/tt.c 2014-09-25 14:41:48.982843848 +0200
|
||
|
@@ -52,140 +52,6 @@ static const struct tt_symbols utf8_tt_s
|
||
|
#define is_last_column(_tb, _cl) \
|
||
|
list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns)
|
||
|
|
||
|
-/*
|
||
|
- * Counts number of cells in multibyte string. For all control and
|
||
|
- * non-printable chars is the result width enlarged to store \x?? hex
|
||
|
- * sequence. See mbs_safe_encode().
|
||
|
- */
|
||
|
-static size_t mbs_safe_width(const char *s)
|
||
|
-{
|
||
|
- mbstate_t st;
|
||
|
- const char *p = s;
|
||
|
- size_t width = 0;
|
||
|
-
|
||
|
- memset(&st, 0, sizeof(st));
|
||
|
-
|
||
|
- while (p && *p) {
|
||
|
- if (iscntrl((unsigned char) *p)) {
|
||
|
- width += 4; /* *p encoded to \x?? */
|
||
|
- p++;
|
||
|
- }
|
||
|
-#ifdef HAVE_WIDECHAR
|
||
|
- else {
|
||
|
- wchar_t wc;
|
||
|
- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
|
||
|
-
|
||
|
- if (len == 0)
|
||
|
- break;
|
||
|
-
|
||
|
- if (len == (size_t) -1 || len == (size_t) -2) {
|
||
|
- len = 1;
|
||
|
- width += (isprint((unsigned char) *p) ? 1 : 4);
|
||
|
-
|
||
|
- } if (!iswprint(wc))
|
||
|
- width += len * 4; /* hex encode whole sequence */
|
||
|
- else
|
||
|
- width += wcwidth(wc); /* number of cells */
|
||
|
- p += len;
|
||
|
- }
|
||
|
-#else
|
||
|
- else if (!isprint((unsigned char) *p)) {
|
||
|
- width += 4; /* *p encoded to \x?? */
|
||
|
- p++;
|
||
|
- } else {
|
||
|
- width++;
|
||
|
- p++;
|
||
|
- }
|
||
|
-#endif
|
||
|
- }
|
||
|
-
|
||
|
- return width;
|
||
|
-}
|
||
|
-
|
||
|
-/*
|
||
|
- * Returns allocated string where all control and non-printable chars are
|
||
|
- * replaced with \x?? hex sequence.
|
||
|
- */
|
||
|
-static char *mbs_safe_encode(const char *s, size_t *width)
|
||
|
-{
|
||
|
- mbstate_t st;
|
||
|
- const char *p = s;
|
||
|
- char *res, *r;
|
||
|
- size_t sz = s ? strlen(s) : 0;
|
||
|
-
|
||
|
-
|
||
|
- if (!sz)
|
||
|
- return NULL;
|
||
|
-
|
||
|
- memset(&st, 0, sizeof(st));
|
||
|
-
|
||
|
- res = malloc((sz * 4) + 1);
|
||
|
- if (!res)
|
||
|
- return NULL;
|
||
|
-
|
||
|
- r = res;
|
||
|
- *width = 0;
|
||
|
-
|
||
|
- while (p && *p) {
|
||
|
- if (iscntrl((unsigned char) *p)) {
|
||
|
- sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
- r += 4;
|
||
|
- *width += 4;
|
||
|
- p++;
|
||
|
- }
|
||
|
-#ifdef HAVE_WIDECHAR
|
||
|
- else {
|
||
|
- wchar_t wc;
|
||
|
- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
|
||
|
-
|
||
|
- if (len == 0)
|
||
|
- break; /* end of string */
|
||
|
-
|
||
|
- if (len == (size_t) -1 || len == (size_t) -2) {
|
||
|
- len = 1;
|
||
|
- /*
|
||
|
- * Not valid multibyte sequence -- maybe it's
|
||
|
- * printable char according to the current locales.
|
||
|
- */
|
||
|
- if (!isprint((unsigned char) *p)) {
|
||
|
- sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
- r += 4;
|
||
|
- *width += 4;
|
||
|
- } else {
|
||
|
- width++;
|
||
|
- *r++ = *p;
|
||
|
- }
|
||
|
- } else if (!iswprint(wc)) {
|
||
|
- size_t i;
|
||
|
- for (i = 0; i < len; i++) {
|
||
|
- sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
- r += 4;
|
||
|
- *width += 4;
|
||
|
- }
|
||
|
- } else {
|
||
|
- memcpy(r, p, len);
|
||
|
- r += len;
|
||
|
- *width += wcwidth(wc);
|
||
|
- }
|
||
|
- p += len;
|
||
|
- }
|
||
|
-#else
|
||
|
- else if (!isprint((unsigned char) *p)) {
|
||
|
- sprintf(r, "\\x%02x", (unsigned char) *p);
|
||
|
- p++;
|
||
|
- r += 4;
|
||
|
- *width += 4;
|
||
|
- } else {
|
||
|
- *r++ = *p++;
|
||
|
- *width++;
|
||
|
- }
|
||
|
-#endif
|
||
|
- }
|
||
|
-
|
||
|
- *r = '\0';
|
||
|
-
|
||
|
- return res;
|
||
|
-}
|
||
|
|
||
|
/*
|
||
|
* @flags: TT_FL_* flags (usually TT_FL_{ASCII,RAW})
|
||
|
diff -up util-linux-2.23.2/Makefile.am.kzak util-linux-2.23.2/Makefile.am
|
||
|
--- util-linux-2.23.2/Makefile.am.kzak 2013-06-13 09:46:10.334649886 +0200
|
||
|
+++ util-linux-2.23.2/Makefile.am 2014-09-25 14:41:48.979843819 +0200
|
||
|
@@ -22,6 +22,7 @@ dist_noinst_DATA = $(dist_man_MANS)
|
||
|
#
|
||
|
ul_libblkid_incdir = $(top_builddir)/libblkid/src
|
||
|
ul_libmount_incdir = $(top_builddir)/libmount/src
|
||
|
+ul_libsmartcols_incdir = $(top_builddir)/libsmartcols/src
|
||
|
ul_libuuid_incdir = $(top_srcdir)/libuuid/src
|
||
|
ul_libfdisk_incdir = $(top_srcdir)/libfdisk/src
|
||
|
|
||
|
@@ -77,6 +78,7 @@ include lib/Makemodule.am
|
||
|
include libuuid/Makemodule.am
|
||
|
include libblkid/Makemodule.am
|
||
|
include libmount/Makemodule.am
|
||
|
+include libsmartcols/Makemodule.am
|
||
|
include libfdisk/Makemodule.am
|
||
|
|
||
|
include schedutils/Makemodule.am
|