2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2021 Alessio Chiapperini
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #ifndef _POSIX_C_SOURCE
29 # define _POSIX_C_SOURCE 200112L
30 #elif _POSIX_C_SOURCE < 200112L
31 # error incompatible _POSIX_C_SOURCE level
43 char **list
; /* Columns */
44 int *width
; /* Width of each column */
45 size_t cols
; /* Number of columns */
48 static char **list
; /* Array of records */
49 static size_t entries
; /* Number of records */
50 static size_t maxentries
= BUFSIZ
; /* Upper bound on number of records */
55 (void)fprintf(stderr
, "usage: tabular [-s sep] [files ...]\n");
60 input(const char *path
)
68 fp
= fopen(path
, "r");
77 list
= calloc(maxentries
, sizeof *list
);
85 while ((buf
= parser_readline(fp
)) != 0) {
86 if (entries
== maxentries
) {
87 nlist
= realloc(list
, (maxentries
+ BUFSIZ
) *
96 (void)memset(nlist
+ maxentries
, 0, (sizeof *nlist
) *
101 list
[entries
++] = buf
;
111 maketbl(const char *sep
)
114 char **cols
, **ncols
;
125 maxcols
= MAX_FIELDS
;
126 t
= tbl
= calloc(entries
, sizeof *t
);
127 cols
= calloc(maxcols
, sizeof *cols
);
128 width
= calloc(maxcols
, sizeof *width
);
129 if (tbl
== 0 || cols
== 0 || width
== 0) {
136 for (cnt
= 0, nfields
= 0; cnt
< entries
; cnt
++, lp
++, t
++) {
137 nfields
= parser_parse(list
[cnt
], sep
, cols
, &pstat
);
139 if (nfields
> maxcols
) {
140 ncols
= realloc(cols
, (maxcols
+ MAX_FIELDS
) *
142 nwidth
= realloc(width
, (maxcols
+ MAX_FIELDS
) *
145 if (ncols
== 0 || nwidth
== 0) {
154 (void)memset(cols
+ maxcols
, 0, MAX_FIELDS
*
156 (void)memset(width
+ maxcols
, 0, MAX_FIELDS
*
159 maxcols
+= MAX_FIELDS
;
162 if (pstat
== ENOMEM
) {
170 t
->list
= calloc(nfields
, sizeof *(t
->list
));
171 t
->width
= calloc(nfields
, sizeof *(t
->width
));
173 if (t
->list
== 0 || t
->width
== 0) {
179 for (coloff
= 0; coloff
< nfields
; coloff
++) {
180 t
->list
[coloff
] = cols
[coloff
];
181 t
->width
[coloff
] = (int)strlen(cols
[coloff
]);
183 if (t
->width
[coloff
] > width
[coloff
]) {
184 width
[coloff
] = t
->width
[coloff
];
189 for (cnt
= 0, t
= tbl
; cnt
< entries
; cnt
++, t
++) {
191 for (coloff
= 0; coloff
< t
->cols
; coloff
++) {
192 if (coloff
< t
->cols
- 1) {
193 (void)printf("%s%*s", t
->list
[coloff
],
194 width
[coloff
] - t
->width
[coloff
] +
197 (void)printf("%s\n", t
->list
[coloff
]);
205 for (cnt
= 0, t
= tbl
; cnt
< entries
; cnt
++, t
++) {
218 for (size_t i
= 0; i
< maxentries
; i
++) {
227 main(int argc
, char *argv
[])
233 while ((opt
= getopt(argc
, argv
, "s:")) != -1) {
236 len
= strlen(optarg
);
242 (void)memcpy(sep
, optarg
, len
);
254 char *def
[] = { "-" };
260 for (int i
= 0; i
< argc
; i
++) {
261 if (input(argv
[i
]) == 0) {
264 if (maketbl(sep
) == 0) {