Print this page
11545 Want configurable output field separator for libofmt
Portions contributed by: Cody Peter Mello <cody.mello@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
*** 23,32 ****
--- 23,33 ----
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
+ * Copyright (c) 2015 by Delphix. All rights reserved.
* Copyright 2017 Joyent, Inc.
*/
#include <errno.h>
#include <sys/types.h>
*** 51,60 ****
--- 52,63 ----
uint_t s_nfields; /* the number of fields in s_buf */
uint_t s_currfield; /* the current field being processed */
} split_t;
static void splitfree(split_t *);
+ static split_t *split_str(const char *, uint_t);
+ static split_t *split_fields(const ofmt_field_t *, uint_t, uint_t);
/*
* The state of the output is tracked in a ofmt_state_t structure.
* Each os_fields[i] entry points at an ofmt_field_t array for
* the sub-command whose contents are provided by the caller, with
*** 69,78 ****
--- 72,82 ----
int os_nrow;
uint_t os_flags;
int os_nbad;
char **os_badfields;
int os_maxnamelen; /* longest name (f. multiline) */
+ char os_fs; /* field seperator */
} ofmt_state_t;
/*
* A B_TRUE return value from the callback function will print out the contents
* of the output buffer, except when the buffer is returned with the empty
* string "", in which case the OFMT_VAL_UNDEF will be printed.
*** 80,95 ****
* If the callback function returns B_FALSE, the "?" string will be emitted.
*/
#define OFMT_VAL_UNDEF "--"
#define OFMT_VAL_UNKNOWN "?"
/*
* The maximum number of rows supported by the OFMT_WRAP option.
*/
#define OFMT_MAX_ROWS 128
- static void ofmt_print_header(ofmt_state_t *);
static void ofmt_print_field(ofmt_state_t *, ofmt_field_t *, const char *,
boolean_t);
/*
* Split `str' into at most `maxfields' fields, Return a pointer to a
--- 84,100 ----
* If the callback function returns B_FALSE, the "?" string will be emitted.
*/
#define OFMT_VAL_UNDEF "--"
#define OFMT_VAL_UNKNOWN "?"
+ #define OFMT_DEFAULT_FS ':'
+
/*
* The maximum number of rows supported by the OFMT_WRAP option.
*/
#define OFMT_MAX_ROWS 128
static void ofmt_print_field(ofmt_state_t *, ofmt_field_t *, const char *,
boolean_t);
/*
* Split `str' into at most `maxfields' fields, Return a pointer to a
*** 125,158 ****
splitfree(sp);
return (NULL);
}
/*
! * Split a template into its maximum number of fields (capped by the maxcols
! * if it's non-zero). Return a pointer to a split_t containing the split
! * fields, or NULL on failure. Invoked when all fields are implicitly
! * selected at handle creation.
*/
static split_t *
! split_max(const ofmt_field_t *template, uint_t maxcols)
{
- const ofmt_field_t *ofp;
split_t *sp;
! int i, cols, nfields = 0;
sp = calloc(sizeof (split_t), 1);
if (sp == NULL)
return (NULL);
! for (ofp = template; ofp->of_name != NULL; ofp++)
! nfields++;
!
! sp->s_fields = malloc(sizeof (char *) * nfields);
if (sp->s_fields == NULL)
goto fail;
cols = 0;
! for (i = 0; i < nfields; i++) {
cols += template[i].of_width;
/*
* If all fields are implied without explicitly passing
* in a fields_str, build a list of field names, stopping
* when we run out of columns.
--- 130,159 ----
splitfree(sp);
return (NULL);
}
/*
! * Split `fields' into at most `maxfields' fields. Return a pointer to
! * a split_t containing the split fields, or NULL on failure. Invoked
! * when all fields are implicitly selected at handle creation by
! * passing in a NULL fields_str
*/
static split_t *
! split_fields(const ofmt_field_t *template, uint_t maxfields, uint_t maxcols)
{
split_t *sp;
! int i, cols;
sp = calloc(sizeof (split_t), 1);
if (sp == NULL)
return (NULL);
! sp->s_fields = malloc(sizeof (char *) * maxfields);
if (sp->s_fields == NULL)
goto fail;
cols = 0;
! for (i = 0; i < maxfields; i++) {
cols += template[i].of_width;
/*
* If all fields are implied without explicitly passing
* in a fields_str, build a list of field names, stopping
* when we run out of columns.
*** 186,199 ****
ofmt_status_t
ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
uint_t maxcols, ofmt_handle_t *ofmt)
{
split_t *sp;
! uint_t i, of_index;
const ofmt_field_t *ofp;
ofmt_field_t *of;
ofmt_state_t *os = NULL;
ofmt_status_t error = OFMT_SUCCESS;
boolean_t parsable = (flags & OFMT_PARSABLE);
boolean_t wrap = (flags & OFMT_WRAP);
boolean_t multiline = (flags & OFMT_MULTILINE);
--- 187,201 ----
ofmt_status_t
ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
uint_t maxcols, ofmt_handle_t *ofmt)
{
split_t *sp;
! uint_t i, j, of_index;
const ofmt_field_t *ofp;
ofmt_field_t *of;
ofmt_state_t *os = NULL;
+ uint_t nfields = 0;
ofmt_status_t error = OFMT_SUCCESS;
boolean_t parsable = (flags & OFMT_PARSABLE);
boolean_t wrap = (flags & OFMT_WRAP);
boolean_t multiline = (flags & OFMT_MULTILINE);
*** 213,245 ****
if (wrap)
return (OFMT_EPARSEWRAP);
}
if (template == NULL)
return (OFMT_ENOTEMPLATE);
!
/*
* split str into the columns selected, or construct the
* full set of columns (equivalent to -o all).
*/
if (str != NULL && strcasecmp(str, "all") != 0) {
- const char *c;
- int nfields = 1;
-
- /*
- * Get an upper bound on the number of fields by counting
- * the commas.
- */
- for (c = str; *c != '\0'; c++) {
- if (*c == ',')
- nfields++;
- }
-
sp = split_str(str, nfields);
} else {
if (parsable || (str != NULL && strcasecmp(str, "all") == 0))
maxcols = 0;
! sp = split_max(template, maxcols);
}
if (sp == NULL)
goto nomem;
os = calloc(sizeof (ofmt_state_t) +
--- 215,236 ----
if (wrap)
return (OFMT_EPARSEWRAP);
}
if (template == NULL)
return (OFMT_ENOTEMPLATE);
! for (ofp = template; ofp->of_name != NULL; ofp++)
! nfields++;
/*
* split str into the columns selected, or construct the
* full set of columns (equivalent to -o all).
*/
if (str != NULL && strcasecmp(str, "all") != 0) {
sp = split_str(str, nfields);
} else {
if (parsable || (str != NULL && strcasecmp(str, "all") == 0))
maxcols = 0;
! sp = split_fields(template, nfields, maxcols);
}
if (sp == NULL)
goto nomem;
os = calloc(sizeof (ofmt_state_t) +
*** 247,270 ****
if (os == NULL)
goto nomem;
*ofmt = os;
os->os_fields = (ofmt_field_t *)&os[1];
os->os_flags = flags;
of = os->os_fields;
of_index = 0;
/*
* sp->s_nfields is the number of fields requested in fields_str.
* nfields is the number of fields in template.
*/
for (i = 0; i < sp->s_nfields; i++) {
! for (ofp = template; ofp->of_name != NULL; ofp++) {
! if (strcasecmp(sp->s_fields[i], ofp->of_name) == 0)
break;
}
!
! if (ofp->of_name == NULL) {
int nbad = os->os_nbad++;
error = OFMT_EBADFIELDS;
if (os->os_badfields == NULL) {
os->os_badfields = malloc(sp->s_nfields *
--- 238,263 ----
if (os == NULL)
goto nomem;
*ofmt = os;
os->os_fields = (ofmt_field_t *)&os[1];
os->os_flags = flags;
+ os->os_fs = OFMT_DEFAULT_FS;
of = os->os_fields;
of_index = 0;
/*
* sp->s_nfields is the number of fields requested in fields_str.
* nfields is the number of fields in template.
*/
for (i = 0; i < sp->s_nfields; i++) {
! for (j = 0; j < nfields; j++) {
! if (strcasecmp(sp->s_fields[i],
! template[j].of_name) == 0) {
break;
}
! }
! if (j == nfields) {
int nbad = os->os_nbad++;
error = OFMT_EBADFIELDS;
if (os->os_badfields == NULL) {
os->os_badfields = malloc(sp->s_nfields *
*** 275,295 ****
os->os_badfields[nbad] = strdup(sp->s_fields[i]);
if (os->os_badfields[nbad] == NULL)
goto nomem;
continue;
}
! of[of_index].of_name = strdup(ofp->of_name);
if (of[of_index].of_name == NULL)
goto nomem;
if (multiline) {
int n = strlen(of[of_index].of_name);
os->os_maxnamelen = MAX(n, os->os_maxnamelen);
}
! of[of_index].of_width = ofp->of_width;
! of[of_index].of_id = ofp->of_id;
! of[of_index].of_cb = ofp->of_cb;
of_index++;
}
splitfree(sp);
if (of_index == 0) /* all values in str are bogus */
return (OFMT_ENOFIELDS);
--- 268,288 ----
os->os_badfields[nbad] = strdup(sp->s_fields[i]);
if (os->os_badfields[nbad] == NULL)
goto nomem;
continue;
}
! of[of_index].of_name = strdup(template[j].of_name);
if (of[of_index].of_name == NULL)
goto nomem;
if (multiline) {
int n = strlen(of[of_index].of_name);
os->os_maxnamelen = MAX(n, os->os_maxnamelen);
}
! of[of_index].of_width = template[j].of_width;
! of[of_index].of_id = template[j].of_id;
! of[of_index].of_cb = template[j].of_cb;
of_index++;
}
splitfree(sp);
if (of_index == 0) /* all values in str are bogus */
return (OFMT_ENOFIELDS);
*** 303,312 ****
--- 296,311 ----
*ofmt = NULL;
splitfree(sp);
return (error);
}
+ void
+ ofmt_set_fs(ofmt_handle_t ofmt, char fs)
+ {
+ ((ofmt_state_t *)ofmt)->os_fs = fs;
+ }
+
/*
* free resources associated with the ofmt_handle_t
*/
void
ofmt_close(ofmt_handle_t ofmt)
*** 339,363 ****
boolean_t multiline = (os->os_flags & OFMT_MULTILINE);
boolean_t rightjust = (os->os_flags & OFMT_RIGHTJUST);
char c;
/*
! * Parsable fields are separated by ':'. If such a field contains
! * a ':' or '\', this character is prefixed by a '\'.
*/
if (parsable) {
if (os->os_nfields == 1) {
(void) printf("%s", value);
return;
}
while ((c = *value++) != '\0') {
! if (escsep && ((c == ':' || c == '\\')))
(void) putchar('\\');
(void) putchar(c);
}
if (!os->os_lastfield)
! (void) putchar(':');
} else if (multiline) {
if (value[0] == '\0')
value = OFMT_VAL_UNDEF;
(void) printf("%*.*s: %s", os->os_maxnamelen,
os->os_maxnamelen, ofp->of_name, value);
--- 338,362 ----
boolean_t multiline = (os->os_flags & OFMT_MULTILINE);
boolean_t rightjust = (os->os_flags & OFMT_RIGHTJUST);
char c;
/*
! * Parsable fields are separated by os_fs. os_fs and '\' are escaped
! * (prefixed by a) '\'.
*/
if (parsable) {
if (os->os_nfields == 1) {
(void) printf("%s", value);
return;
}
while ((c = *value++) != '\0') {
! if (escsep && ((c == os->os_fs || c == '\\')))
(void) putchar('\\');
(void) putchar(c);
}
if (!os->os_lastfield)
! (void) putchar(os->os_fs);
} else if (multiline) {
if (value[0] == '\0')
value = OFMT_VAL_UNDEF;
(void) printf("%*.*s: %s", os->os_maxnamelen,
os->os_maxnamelen, ofp->of_name, value);
*** 453,462 ****
--- 452,462 ----
return;
}
if ((os->os_nrow++ % os->os_winsize.ws_row) == 0 &&
!parsable && !multiline) {
+ if (!(os->os_flags & OFMT_NOHEADER))
ofmt_print_header(os);
os->os_nrow++;
}
if (multiline && os->os_nrow > 1)
*** 519,531 ****
}
/*
* Print the field headers
*/
! static void
! ofmt_print_header(ofmt_state_t *os)
{
int i;
ofmt_field_t *of = os->os_fields;
boolean_t escsep = (os->os_nfields > 1);
for (i = 0; i < os->os_nfields; i++) {
--- 519,532 ----
}
/*
* Print the field headers
*/
! void
! ofmt_print_header(ofmt_handle_t ofmt)
{
+ ofmt_state_t *os = ofmt;
int i;
ofmt_field_t *of = os->os_fields;
boolean_t escsep = (os->os_nfields > 1);
for (i = 0; i < os->os_nfields; i++) {