summaryrefslogtreecommitdiffstats
path: root/text-utils/column.c
diff options
context:
space:
mode:
authorKarel Zak2011-05-26 09:54:13 +0200
committerKarel Zak2011-05-26 09:54:13 +0200
commit35b6076b8c245172b51c4148e7f89eefdcc1f45a (patch)
tree5e04a338d5c427b6c7a9991065652a3fefe6d0d7 /text-utils/column.c
parentbuild-sys: cleanup lib/ tests (diff)
parenttests: add column tests (diff)
downloadkernel-qcow2-util-linux-35b6076b8c245172b51c4148e7f89eefdcc1f45a.tar.gz
kernel-qcow2-util-linux-35b6076b8c245172b51c4148e7f89eefdcc1f45a.tar.xz
kernel-qcow2-util-linux-35b6076b8c245172b51c4148e7f89eefdcc1f45a.zip
Merge branch 'column' of git://github.com/kerolasa/lelux-utiliteetit into column
* 'column' of git://github.com/kerolasa/lelux-utiliteetit: tests: add column tests column.c: global variables removed column.c: validate numeric user inputs column.c: free memory before exit column.c: make table function clarification column.c: coding style fixes column.c: add version printing column.c: replace emalloc with xcalloc
Diffstat (limited to 'text-utils/column.c')
-rw-r--r--text-utils/column.c214
1 files changed, 118 insertions, 96 deletions
diff --git a/text-utils/column.c b/text-utils/column.c
index ffc91df65..bb6147cf9 100644
--- a/text-utils/column.c
+++ b/text-utils/column.c
@@ -54,6 +54,7 @@
#include "widechar.h"
#include "c.h"
#include "xalloc.h"
+#include "strutils.h"
#ifdef HAVE_WIDECHAR
#define wcs_width(s) wcswidth(s,wcslen(s))
@@ -70,37 +71,17 @@ static char *mtsafe_strtok(char *, const char *, char **);
#define DEFNUM 1000
#define MAXLINELEN (LINE_MAX + 1)
-static void c_columnate __P((void));
-static void *emalloc __P((int));
-static void input __P((FILE *));
-static void maketbl __P((void));
-static void print __P((void));
-static void r_columnate __P((void));
+static int input(FILE *fp, int *maxlength, wchar_t ***list, int *entries);
+static void c_columnate(int maxlength, long termwidth, wchar_t **list, int entries);
+static void r_columnate(int maxlength, long termwidth, wchar_t **list, int entries);
+static void maketbl(wchar_t **list, int entries, wchar_t *separator);
+static void print(wchar_t **list, int entries);
typedef struct _tbl {
wchar_t **list;
int cols, *len;
} TBL;
-int termwidth = 80; /* default terminal width */
-
-int entries; /* number of records */
-int eval; /* exit value */
-int maxlength; /* longest record */
-wchar_t **list; /* array of pointers to records */
-wchar_t default_separator[] = { '\t', ' ', 0 };
-wchar_t *separator = default_separator; /* field separator for table option */
-
-static const struct option longopts[] =
-{
- { "help", 0, 0, 'h' },
- { "columns", 0, 0, 'c' },
- { "table", 0, 0, 't' },
- { "separator", 0, 0, 's' },
- { "fillrows", 0, 0, 'x' },
- { NULL, 0, 0, 0 },
-};
-
static void __attribute__((__noreturn__)) usage(int rc)
{
FILE *out = rc == EXIT_FAILURE ? stderr : stdout;
@@ -111,6 +92,7 @@ static void __attribute__((__noreturn__)) usage(int rc)
fprintf(out, _(
" -h, --help displays this help text\n"
+ " -V, --version output version information and exit\n"
" -c, --columns <width> width of output in number of characters\n"
" -t, --table create a table\n"
" -s, --separator <string> table delimeter\n"
@@ -119,33 +101,61 @@ static void __attribute__((__noreturn__)) usage(int rc)
fprintf(out, _("\nFor more information see column(1).\n"));
exit(rc);
}
-int
-main(int argc, char **argv)
+
+int main(int argc, char **argv)
{
struct winsize win;
FILE *fp;
int ch, tflag, xflag;
char *p;
+ long termwidth;
+ int entries = 0; /* number of records */
+ unsigned int eval = 0; /* exit value */
+ int maxlength; /* longest record */
+ wchar_t **list = NULL; /* array of pointers to records */
+ /* field separator for table option */
+ wchar_t default_separator[] = { '\t', ' ', 0 };
+ wchar_t *separator = default_separator;
+
+ static const struct option longopts[] =
+ {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ { "columns", 0, 0, 'c' },
+ { "table", 0, 0, 't' },
+ { "separator", 0, 0, 's' },
+ { "fillrows", 0, 0, 'x' },
+ { NULL, 0, 0, 0 },
+ };
+
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
if ((p = getenv("COLUMNS")) != NULL)
- termwidth = atoi(p);
+ termwidth = strtol_or_err(p,
+ _("terminal environment COLUMNS failed"));
} else
termwidth = win.ws_col;
tflag = xflag = 0;
- while ((ch = getopt_long(argc, argv, "h?c:s:tx", longopts, NULL)) != -1)
+ while ((ch = getopt_long(argc, argv, "hVc:s:tx", longopts, NULL)) != -1)
switch(ch) {
case 'h':
- case '?':
usage(EXIT_SUCCESS);
break;
+ case 'V':
+ printf(_("%s from %s\n"), program_invocation_short_name,
+ PACKAGE_STRING);
+ return EXIT_SUCCESS;
case 'c':
- termwidth = atoi(optarg);
+ termwidth = strtol_or_err(optarg,
+ _("bad columns width value"));
+ if (termwidth < 1)
+ errx(EXIT_FAILURE,
+ _("-%c positive integer expected as an argument"), ch);
break;
case 's':
separator = mbs_to_wcs(optarg);
@@ -158,42 +168,49 @@ main(int argc, char **argv)
break;
default:
usage(EXIT_FAILURE);
- }
+ }
argc -= optind;
argv += optind;
if (!*argv)
- input(stdin);
- else {
+ eval += input(stdin, &maxlength, &list, &entries);
+ else
for (; *argv; ++argv) {
if ((fp = fopen(*argv, "r")) != NULL) {
- input(fp);
- (void)fclose(fp);
+ eval += input(fp, &maxlength, &list, &entries);
+ fclose(fp);
} else {
warn("%s", *argv);
- eval = EXIT_FAILURE;
+ eval += EXIT_FAILURE;
}
}
- }
if (!entries)
exit(eval);
if (tflag)
- maketbl();
+ maketbl(list, entries, separator);
else if (maxlength >= termwidth)
- print();
+ print(list, entries);
else if (xflag)
- c_columnate();
+ c_columnate(maxlength, termwidth, list, entries);
else
- r_columnate();
+ r_columnate(maxlength, termwidth, list, entries);
+
+ for (int i = 0; i < entries; i++)
+ free(list[i]);
+ free(list);
+
if (ferror(stdout) || fclose(stdout))
- eval = EXIT_FAILURE;
- exit(eval);
+ eval += EXIT_FAILURE;
+
+ if (eval == 0)
+ return EXIT_SUCCESS;
+ else
+ return EXIT_FAILURE;
}
-static void
-c_columnate()
+static void c_columnate(int maxlength, long termwidth, wchar_t **list, int entries)
{
int chcnt, col, cnt, endcol, numcols;
wchar_t **lp;
@@ -222,8 +239,7 @@ c_columnate()
putwchar('\n');
}
-static void
-r_columnate()
+static void r_columnate(int maxlength, long termwidth, wchar_t **list, int entries)
{
int base, chcnt, cnt, col, endcol, numcols, numrows, row;
@@ -252,8 +268,7 @@ r_columnate()
}
}
-static void
-print()
+static void print(wchar_t **list, int entries)
{
int cnt;
wchar_t **lp;
@@ -264,36 +279,37 @@ print()
}
}
-static void
-maketbl()
+static void maketbl(wchar_t **list, int entries, wchar_t *separator)
{
TBL *t;
- int coloff, cnt, i;
+ int cnt, i;
wchar_t *p, **lp;
- int *lens, maxcols;
+ ssize_t *lens;
+ ssize_t maxcols = DEFCOLS, coloff;
TBL *tbl;
wchar_t **cols;
wchar_t *wcstok_state;
- t = tbl = emalloc(entries * sizeof(TBL));
- cols = emalloc((maxcols = DEFCOLS) * sizeof(wchar_t *));
- lens = emalloc(maxcols * sizeof(int));
- for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
- for (coloff = 0, p = *lp;
- (cols[coloff] = wcstok(p, separator, &wcstok_state)) != NULL;
- p = NULL) {
+ t = tbl = xcalloc(entries, sizeof(TBL));
+ cols = xcalloc(maxcols, sizeof(wchar_t *));
+ lens = xcalloc(maxcols, sizeof(ssize_t));
+
+ for (lp = list, cnt = 0; cnt < entries; ++cnt, ++lp, ++t) {
+ coloff = 0;
+ p = *lp;
+ while ((cols[coloff] = wcstok(p, separator, &wcstok_state)) != NULL) {
if (++coloff == maxcols) {
- cols = xrealloc(cols, ((u_int)maxcols + DEFCOLS)
- * sizeof(wchar_t *));
- lens = xrealloc(lens, ((u_int)maxcols + DEFCOLS)
- * sizeof(int));
- memset((char *)lens + maxcols * sizeof(int),
- 0, DEFCOLS * sizeof(int));
maxcols += DEFCOLS;
+ cols = xrealloc(cols, maxcols * sizeof(wchar_t *));
+ lens = xrealloc(lens, maxcols * sizeof(ssize_t));
+ /* zero fill only new memory */
+ memset(lens + ((maxcols - DEFCOLS) * sizeof(ssize_t)), 0,
+ DEFCOLS * sizeof(int));
}
+ p = NULL;
}
- t->list = emalloc(coloff * sizeof(wchar_t *));
- t->len = emalloc(coloff * sizeof(int));
+ t->list = xcalloc(coloff, sizeof(wchar_t *));
+ t->len = xcalloc(coloff, sizeof(int));
for (t->cols = coloff; --coloff >= 0;) {
t->list[coloff] = cols[coloff];
t->len[coloff] = wcs_width(cols[coloff]);
@@ -301,7 +317,8 @@ maketbl()
lens[coloff] = t->len[coloff];
}
}
- for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
+
+ for (t = tbl, cnt = 0; cnt < entries; ++cnt, ++t) {
for (coloff = 0; coloff < t->cols - 1; ++coloff) {
fputws(t->list[coloff], stdout);
for (i = lens[coloff] - t->len[coloff] + 2; i > 0; i--)
@@ -312,20 +329,30 @@ maketbl()
putwchar('\n');
}
}
+
+ for (cnt = 0; cnt < entries; ++cnt) {
+ free((tbl+cnt)->list);
+ free((tbl+cnt)->len);
+ }
+ free(cols);
+ free(lens);
+ free(tbl);
}
-static void
-input(fp)
- FILE *fp;
+static int input(FILE *fp, int *maxlength, wchar_t ***list, int *entries)
{
- static int maxentry;
- int len, lineno = 1, reportedline = 0;
+ static int maxentry = DEFNUM;
+ int len, lineno = 1, reportedline = 0, eval = 0;
wchar_t *p, buf[MAXLINELEN];
+ wchar_t **local_list;
+ int local_entries = *entries;
+
+ if (!local_list)
+ local_list = xcalloc(maxentry, sizeof(wchar_t *));
- if (!list)
- list = emalloc((maxentry = DEFNUM) * sizeof(wchar_t *));
while (fgetws(buf, MAXLINELEN, fp)) {
- for (p = buf; *p && iswspace(*p); ++p);
+ for (p = buf; *p && iswspace(*p); ++p)
+ ;
if (!*p)
continue;
if (!(p = wcschr(p, '\n')) && !feof(fp)) {
@@ -334,21 +361,27 @@ input(fp)
lineno);
reportedline = lineno;
}
- eval = EXIT_FAILURE;
+ eval = 1;
continue;
}
lineno++;
if (!feof(fp))
*p = '\0';
len = wcs_width(buf); /* len = p - buf; */
- if (maxlength < len)
- maxlength = len;
- if (entries == maxentry) {
+ if (*maxlength < len)
+ *maxlength = len;
+ if (local_entries == maxentry) {
maxentry += DEFNUM;
- list = xrealloc(list, (u_int)maxentry * sizeof(wchar_t *));
+ local_list = xrealloc(local_list,
+ (u_int)maxentry * sizeof(wchar_t *));
}
- list[entries++] = wcsdup(buf);
+ local_list[local_entries++] = wcsdup(buf);
}
+
+ *list = local_list;
+ *entries = local_entries;
+
+ return eval;
}
#ifdef HAVE_WIDECHAR
@@ -393,14 +426,3 @@ static char *mtsafe_strtok(char *str, const char *delim, char **ptr)
}
}
#endif
-
-static void *
-emalloc(size)
- int size;
-{
- char *p;
-
- p = xmalloc(size);
- memset(p, 0, size);
- return (p);
-}