]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - text-utils/column.c
79ebb115b7763649b0619486a8bc9156c043e732
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@misiek.eu.org>
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 void c_columnate
__P((void));
66 void *emalloc
__P((int));
67 void input
__P((FILE *));
68 void maketbl
__P((void));
69 void print
__P((void));
70 void r_columnate
__P((void));
71 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
)
93 extern char *__progname
;
96 setlocale(LC_ALL
, "");
97 bindtextdomain(PACKAGE
, LOCALEDIR
);
100 if (ioctl(1, TIOCGWINSZ
, &win
) == -1 || !win
.ws_col
) {
101 if ((p
= getenv("COLUMNS")) != NULL
)
104 termwidth
= win
.ws_col
;
107 while ((ch
= getopt(argc
, argv
, "c:s:tx")) != EOF
)
110 termwidth
= atoi(optarg
);
113 separator
= mbs_to_wcs(optarg
);
130 else for (; *argv
; ++argv
)
131 if ((fp
= fopen(*argv
, "r")) != NULL
) {
144 else if (maxlength
>= termwidth
)
150 if (ferror(stdout
) || fclose(stdout
))
159 int chcnt
, col
, cnt
, endcol
, numcols
;
162 maxlength
= (maxlength
+ TAB
) & ~(TAB
- 1);
163 numcols
= termwidth
/ maxlength
;
165 for (chcnt
= col
= 0, lp
= list
;; ++lp
) {
167 chcnt
+= wcs_width(*lp
);
170 if (++col
== numcols
) {
175 while ((cnt
= ((chcnt
+ TAB
) & ~(TAB
- 1))) <= endcol
) {
189 int base
, chcnt
, cnt
, col
, endcol
, numcols
, numrows
, row
;
191 maxlength
= (maxlength
+ TAB
) & ~(TAB
- 1);
192 numcols
= termwidth
/ maxlength
;
195 numrows
= entries
/ numcols
;
196 if (entries
% numcols
)
199 for (row
= 0; row
< numrows
; ++row
) {
201 for (base
= row
, chcnt
= col
= 0; col
< numcols
; ++col
) {
202 fputws(list
[base
], stdout
);
203 chcnt
+= wcs_width(list
[base
]);
204 if ((base
+= numrows
) >= entries
)
206 while ((cnt
= ((chcnt
+ TAB
) & ~(TAB
- 1))) <= endcol
) {
222 for (cnt
= entries
, lp
= list
; cnt
--; ++lp
) {
228 typedef struct _tbl
{
243 wchar_t *wcstok_state
;
245 t
= tbl
= emalloc(entries
* sizeof(TBL
));
246 cols
= emalloc((maxcols
= DEFCOLS
) * sizeof(wchar_t *));
247 lens
= emalloc(maxcols
* sizeof(int));
248 for (cnt
= 0, lp
= list
; cnt
< entries
; ++cnt
, ++lp
, ++t
) {
249 for (coloff
= 0, p
= *lp
;
250 (cols
[coloff
] = wcstok(p
, separator
, &wcstok_state
)) != NULL
;
252 if (++coloff
== maxcols
) {
253 if (!(cols
= realloc(cols
, ((u_int
)maxcols
+ DEFCOLS
)
254 * sizeof(wchar_t *))) ||
255 !(lens
= realloc(lens
, ((u_int
)maxcols
+ DEFCOLS
)
258 memset((char *)lens
+ maxcols
* sizeof(int),
259 0, DEFCOLS
* sizeof(int));
262 t
->list
= emalloc(coloff
* sizeof(wchar_t *));
263 t
->len
= emalloc(coloff
* sizeof(int));
264 for (t
->cols
= coloff
; --coloff
>= 0;) {
265 t
->list
[coloff
] = cols
[coloff
];
266 t
->len
[coloff
] = wcs_width(cols
[coloff
]);
267 if (t
->len
[coloff
] > lens
[coloff
])
268 lens
[coloff
] = t
->len
[coloff
];
271 for (cnt
= 0, t
= tbl
; cnt
< entries
; ++cnt
, ++t
) {
272 for (coloff
= 0; coloff
< t
->cols
- 1; ++coloff
) {
273 fputws(t
->list
[coloff
], stdout
);
274 for (i
= lens
[coloff
] - t
->len
[coloff
] + 2; i
> 0; i
--)
277 fputws(t
->list
[coloff
], stdout
);
283 #define MAXLINELEN (LINE_MAX + 1)
291 wchar_t *p
, buf
[MAXLINELEN
];
294 list
= emalloc((maxentry
= DEFNUM
) * sizeof(wchar_t *));
295 while (fgetws(buf
, MAXLINELEN
, fp
)) {
296 for (p
= buf
; *p
&& iswspace(*p
); ++p
);
299 if (!(p
= wcschr(p
, '\n'))) {
300 warnx(_("line too long"));
305 len
= wcs_width(buf
); /* len = p - buf; */
308 if (entries
== maxentry
) {
310 if (!(list
= realloc(list
,
311 (u_int
)maxentry
* sizeof(wchar_t *))))
314 list
[entries
++] = wcsdup(buf
);
318 #ifdef ENABLE_WIDECHAR
319 static wchar_t *mbs_to_wcs(const char *s
)
324 n
= mbstowcs((wchar_t *)0, s
, 0);
327 wcs
= malloc((n
+ 1) * sizeof(wchar_t));
330 if (mbstowcs(wcs
, s
, n
+ 1) < 0)
336 #ifndef ENABLE_WIDECHAR
337 static char *mtsafe_strtok(char *str
, const char *delim
, char **ptr
)
344 str
+= strspn(str
, delim
);
349 char *token_end
= strpbrk(str
, delim
);
352 *ptr
= token_end
+ 1;
366 if (!(p
= malloc(size
)))
376 (void)fprintf(stderr
,
377 _("usage: column [-tx] [-c columns] [file ...]\n"));