From 0784187d141f1889dca331312c4c668502d0f4bb Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 1 Mar 2017 15:05:47 +0100 Subject: column: make input() more generic * remove line size limit * use multi-byte rather than wchar when read input * prepare for future libsmartcols use in input() for table Signed-off-by: Karel Zak --- text-utils/column.c | 115 ++++++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 62 deletions(-) (limited to 'text-utils/column.c') diff --git a/text-utils/column.c b/text-utils/column.c index 4831eddac..51a5b8efd 100644 --- a/text-utils/column.c +++ b/text-utils/column.c @@ -61,7 +61,6 @@ static char *mtsafe_strtok(char *, const char *, char **); #define DEFCOLS 25 #define TAB 8 -#define DEFNUM 1000 #define MAXLINELEN (LINE_MAX + 1) typedef struct _tbl { @@ -79,11 +78,11 @@ enum { struct column_control { int mode; /* COLUMN_MODE_* */ - int termwidth; + size_t termwidth; - int entries; /* number of records */ - int maxlength; /* longest input record (line) */ - wchar_t **list; /* array of pointers to records */ + wchar_t **ents; /* input entries */ + size_t nents; /* number of entries */ + size_t maxlength; /* longest input record (line) */ }; static int input(struct column_control *ctl, FILE *fp); @@ -152,7 +151,6 @@ int main(int argc, char **argv) }; int ch; - int i; unsigned int eval = 0; /* exit value */ int greedy = 1; wchar_t *colsep; /* table column output separator */ @@ -228,7 +226,7 @@ int main(int argc, char **argv) } } - if (!ctl.entries) + if (!ctl.nents) exit(eval); if (ctl.mode != COLUMN_MODE_TABLE && ctl.maxlength >= ctl.termwidth) @@ -249,25 +247,21 @@ int main(int argc, char **argv) break; } - for (i = 0; i < ctl.entries; i++) - free(ctl.list[i]); - free(ctl.list); - return eval == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } static void columnate_fillrows(struct column_control *ctl) { - int chcnt, col, cnt, endcol, numcols; + size_t chcnt, col, cnt, endcol, numcols; wchar_t **lp; ctl->maxlength = (ctl->maxlength + TAB) & ~(TAB - 1); numcols = ctl->termwidth / ctl->maxlength; endcol = ctl->maxlength; - for (chcnt = col = 0, lp = ctl->list;; ++lp) { + for (chcnt = col = 0, lp = ctl->ents;; ++lp) { fputws(*lp, stdout); chcnt += width(*lp); - if (!--ctl->entries) + if (!--ctl->nents) break; if (++col == numcols) { chcnt = col = 0; @@ -287,22 +281,22 @@ static void columnate_fillrows(struct column_control *ctl) static void columnate_fillcols(struct column_control *ctl) { - int base, chcnt, cnt, col, endcol, numcols, numrows, row; + size_t base, chcnt, cnt, col, endcol, numcols, numrows, row; ctl->maxlength = (ctl->maxlength + TAB) & ~(TAB - 1); numcols = ctl->termwidth / ctl->maxlength; if (!numcols) numcols = 1; - numrows = ctl->entries / numcols; - if (ctl->entries % numcols) + numrows = ctl->nents / numcols; + if (ctl->nents % numcols) ++numrows; for (row = 0; row < numrows; ++row) { endcol = ctl->maxlength; for (base = row, chcnt = col = 0; col < numcols; ++col) { - fputws(ctl->list[base], stdout); - chcnt += width(ctl->list[base]); - if ((base += numrows) >= ctl->entries) + fputws(ctl->ents[base], stdout); + chcnt += width(ctl->ents[base]); + if ((base += numrows) >= ctl->nents) break; while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol) { putwchar('\t'); @@ -319,7 +313,7 @@ static void print(struct column_control *ctl) int cnt; wchar_t **lp; - for (cnt = ctl->entries, lp = ctl->list; cnt--; ++lp) { + for (cnt = ctl->nents, lp = ctl->ents; cnt--; ++lp) { fputws(*lp, stdout); putwchar('\n'); } @@ -352,7 +346,7 @@ static wchar_t *local_wcstok(wchar_t *p, const wchar_t *separator, int greedy, static void maketbl(struct column_control *ctl, wchar_t *separator, int greedy, wchar_t *colsep) { TBL *t; - int cnt; + size_t cnt; wchar_t *p, **lp; ssize_t *lens; ssize_t maxcols = DEFCOLS, coloff; @@ -360,11 +354,11 @@ static void maketbl(struct column_control *ctl, wchar_t *separator, int greedy, wchar_t **cols; wchar_t *wcstok_state = NULL; - t = tbl = xcalloc(ctl->entries, sizeof(TBL)); + t = tbl = xcalloc(ctl->nents, sizeof(TBL)); cols = xcalloc(maxcols, sizeof(wchar_t *)); lens = xcalloc(maxcols, sizeof(ssize_t)); - for (lp = ctl->list, cnt = 0; cnt < ctl->entries; ++cnt, ++lp, ++t) { + for (lp = ctl->ents, cnt = 0; cnt < ctl->nents; ++cnt, ++lp, ++t) { coloff = 0; p = *lp; while ((cols[coloff] = local_wcstok(p, separator, greedy, &wcstok_state)) != NULL) { @@ -388,7 +382,7 @@ static void maketbl(struct column_control *ctl, wchar_t *separator, int greedy, } } - for (t = tbl, cnt = 0; cnt < ctl->entries; ++cnt, ++t) { + for (t = tbl, cnt = 0; cnt < ctl->nents; ++cnt, ++t) { for (coloff = 0; coloff < t->cols - 1; ++coloff) { fputws(t->list[coloff], stdout); #ifdef HAVE_WIDECHAR @@ -404,7 +398,7 @@ static void maketbl(struct column_control *ctl, wchar_t *separator, int greedy, } } - for (cnt = 0; cnt < ctl->entries; ++cnt) { + for (cnt = 0; cnt < ctl->nents; ++cnt) { free((tbl+cnt)->list); free((tbl+cnt)->len); } @@ -415,53 +409,50 @@ static void maketbl(struct column_control *ctl, wchar_t *separator, int greedy, static int input(struct column_control *ctl, FILE *fp) { - static int maxentry = DEFNUM; - int len, lineno = 1, reportedline = 0, eval = 0; - wchar_t *p, buf[MAXLINELEN]; - wchar_t **local_list = ctl->list; - int local_entries = ctl->entries; + char *buf = NULL; + size_t bufsz = 0; + size_t maxents = 0; - if (!local_list) - local_list = xcalloc(maxentry, sizeof(wchar_t *)); + do { + char *str, *p; + size_t len; - while (1) { - if (fgetws(buf, MAXLINELEN, fp) == NULL) { + if (getline(&buf, &bufsz, fp) < 0) { if (feof(fp)) break; else err(EXIT_FAILURE, _("read failed")); } - for (p = buf; *p && iswspace(*p); ++p) - ; - if (!*p) + str = (char *) skip_space(buf); + if (str) { + p = strchr(str, '\n'); + if (p) + *p = '\0'; + } + if (!str || !*str) continue; - if (!(p = wcschr(p, '\n')) && !feof(fp)) { - if (reportedline < lineno) { - warnx(_("line %d is too long, output will be truncated"), - lineno); - reportedline = lineno; + + switch (ctl->mode) { + case COLUMN_MODE_TABLE: + /* TODO: fill libsmartcols */ + + case COLUMN_MODE_FILLCOLS: + case COLUMN_MODE_FILLROWS: + if (ctl->nents <= maxents) { + maxents += 1000; + ctl->ents = xrealloc(ctl->ents, + maxents * sizeof(wchar_t *)); } - eval = 1; - continue; - } - lineno++; - if (!feof(fp) && p) - *p = '\0'; - len = width(buf); /* len = p - buf; */ - if (ctl->maxlength < len) - ctl->maxlength = len; - if (local_entries == maxentry) { - maxentry += DEFNUM; - local_list = xrealloc(local_list, - (u_int)maxentry * sizeof(wchar_t *)); + ctl->ents[ctl->nents] = mbs_to_wcs(str); + len = width(ctl->ents[ctl->nents]); + if (ctl->maxlength < len) + ctl->maxlength = len; + ctl->nents++; + break; } - local_list[local_entries++] = wcsdup(buf); - } - - ctl->list = local_list; - ctl->entries = local_entries; + } while (1); - return eval; + return 0; } #ifdef HAVE_WIDECHAR -- cgit v1.2.3-55-g7522