]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - text-utils/column.c
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
36 * added Native Language Support
37 * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
38 * modified to work correctly in multi-byte locales
41 #include <sys/types.h>
42 #include <sys/ioctl.h>
55 #ifdef ENABLE_WIDECHAR
56 #define wcs_width(s) wcswidth(s,wcslen(s))
57 static wchar_t *mbs_to_wcs(const char *);
59 #define wcs_width(s) strlen(s)
60 #define mbs_to_wcs(s) strdup(s)
61 static char *mtsafe_strtok(char *, const char *, char **);
62 #define wcstok mtsafe_strtok
65 static void c_columnate
__P((void));
66 static void *emalloc
__P((int));
67 static void input
__P((FILE *));
68 static void maketbl
__P((void));
69 static void print
__P((void));
70 static void r_columnate
__P((void));
71 static void usage
__P((void));
73 int termwidth
= 80; /* default terminal width */
75 int entries
; /* number of records */
76 int eval
; /* exit value */
77 int maxlength
; /* longest record */
78 wchar_t **list
; /* array of pointers to records */
79 wchar_t default_separator
[] = { '\t', ' ', 0 };
80 wchar_t *separator
= default_separator
; /* field separator for table option */
83 main(int argc
, char **argv
)
90 extern char *__progname
;
93 setlocale(LC_ALL
, "");
94 bindtextdomain(PACKAGE
, LOCALEDIR
);
97 if (ioctl(1, TIOCGWINSZ
, &win
) == -1 || !win
.ws_col
) {
98 if ((p
= getenv("COLUMNS")) != NULL
)
101 termwidth
= win
.ws_col
;
104 while ((ch
= getopt(argc
, argv
, "c:s:tx")) != -1)
107 termwidth
= atoi(optarg
);
110 separator
= mbs_to_wcs(optarg
);
127 else for (; *argv
; ++argv
)
128 if ((fp
= fopen(*argv
, "r")) != NULL
) {
141 else if (maxlength
>= termwidth
)
147 if (ferror(stdout
) || fclose(stdout
))
156 int chcnt
, col
, cnt
, endcol
, numcols
;
159 maxlength
= (maxlength
+ TAB
) & ~(TAB
- 1);
160 numcols
= termwidth
/ maxlength
;
162 for (chcnt
= col
= 0, lp
= list
;; ++lp
) {
164 chcnt
+= wcs_width(*lp
);
167 if (++col
== numcols
) {
172 while ((cnt
= ((chcnt
+ TAB
) & ~(TAB
- 1))) <= endcol
) {
186 int base
, chcnt
, cnt
, col
, endcol
, numcols
, numrows
, row
;
188 maxlength
= (maxlength
+ TAB
) & ~(TAB
- 1);
189 numcols
= termwidth
/ maxlength
;
192 numrows
= entries
/ numcols
;
193 if (entries
% numcols
)
196 for (row
= 0; row
< numrows
; ++row
) {
198 for (base
= row
, chcnt
= col
= 0; col
< numcols
; ++col
) {
199 fputws(list
[base
], stdout
);
200 chcnt
+= wcs_width(list
[base
]);
201 if ((base
+= numrows
) >= entries
)
203 while ((cnt
= ((chcnt
+ TAB
) & ~(TAB
- 1))) <= endcol
) {
219 for (cnt
= entries
, lp
= list
; cnt
--; ++lp
) {
225 typedef struct _tbl
{
240 wchar_t *wcstok_state
;
242 t
= tbl
= emalloc(entries
* sizeof(TBL
));
243 cols
= emalloc((maxcols
= DEFCOLS
) * sizeof(wchar_t *));
244 lens
= emalloc(maxcols
* sizeof(int));
245 for (cnt
= 0, lp
= list
; cnt
< entries
; ++cnt
, ++lp
, ++t
) {
246 for (coloff
= 0, p
= *lp
;
247 (cols
[coloff
] = wcstok(p
, separator
, &wcstok_state
)) != NULL
;
249 if (++coloff
== maxcols
) {
250 if (!(cols
= realloc(cols
, ((u_int
)maxcols
+ DEFCOLS
)
251 * sizeof(wchar_t *))) ||
252 !(lens
= realloc(lens
, ((u_int
)maxcols
+ DEFCOLS
)
255 memset((char *)lens
+ maxcols
* sizeof(int),
256 0, DEFCOLS
* sizeof(int));
259 t
->list
= emalloc(coloff
* sizeof(wchar_t *));
260 t
->len
= emalloc(coloff
* sizeof(int));
261 for (t
->cols
= coloff
; --coloff
>= 0;) {
262 t
->list
[coloff
] = cols
[coloff
];
263 t
->len
[coloff
] = wcs_width(cols
[coloff
]);
264 if (t
->len
[coloff
] > lens
[coloff
])
265 lens
[coloff
] = t
->len
[coloff
];
268 for (cnt
= 0, t
= tbl
; cnt
< entries
; ++cnt
, ++t
) {
269 for (coloff
= 0; coloff
< t
->cols
- 1; ++coloff
) {
270 fputws(t
->list
[coloff
], stdout
);
271 for (i
= lens
[coloff
] - t
->len
[coloff
] + 2; i
> 0; i
--)
274 fputws(t
->list
[coloff
], stdout
);
280 #define MAXLINELEN (LINE_MAX + 1)
288 wchar_t *p
, buf
[MAXLINELEN
];
291 list
= emalloc((maxentry
= DEFNUM
) * sizeof(wchar_t *));
292 while (fgetws(buf
, MAXLINELEN
, fp
)) {
293 for (p
= buf
; *p
&& iswspace(*p
); ++p
);
296 if (!(p
= wcschr(p
, '\n'))) {
297 warnx(_("line too long"));
302 len
= wcs_width(buf
); /* len = p - buf; */
305 if (entries
== maxentry
) {
307 if (!(list
= realloc(list
,
308 (u_int
)maxentry
* sizeof(wchar_t *))))
311 list
[entries
++] = wcsdup(buf
);
315 #ifdef ENABLE_WIDECHAR
316 static wchar_t *mbs_to_wcs(const char *s
)
321 n
= mbstowcs((wchar_t *)0, s
, 0);
324 wcs
= malloc((n
+ 1) * sizeof(wchar_t));
327 if (mbstowcs(wcs
, s
, n
+ 1) < 0)
333 #ifndef ENABLE_WIDECHAR
334 static char *mtsafe_strtok(char *str
, const char *delim
, char **ptr
)
341 str
+= strspn(str
, delim
);
346 char *token_end
= strpbrk(str
, delim
);
349 *ptr
= token_end
+ 1;
363 if (!(p
= malloc(size
)))
373 (void)fprintf(stderr
,
374 _("usage: column [-tx] [-c columns] [file ...]\n"));