1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)column.c 5.6 (Berkeley) 06/01/90"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/ioctl.h> 20 #include <stdio.h> 21 #include <string.h> 22 #include <ctype.h> 23 24 int termwidth = 80; /* default terminal width */ 25 26 int entries; /* number of records */ 27 int eval; /* exit value */ 28 int maxlength; /* longest record */ 29 char **list; /* array of pointers to records */ 30 char *separator = "\t "; /* field separator for table option */ 31 32 main(argc, argv) 33 int argc; 34 char **argv; 35 { 36 extern char *optarg; 37 extern int errno, optind; 38 struct winsize win; 39 FILE *fp; 40 int ch, tflag, xflag; 41 char *p, *getenv(); 42 43 if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) { 44 if (p = getenv("COLUMNS")) 45 termwidth = atoi(p); 46 } else 47 termwidth = win.ws_col; 48 49 xflag = 0; 50 while ((ch = getopt(argc, argv, "c:s:tx")) != EOF) 51 switch(ch) { 52 case 'c': 53 termwidth = atoi(optarg); 54 break; 55 case 's': 56 separator = optarg; 57 break; 58 case 't': 59 tflag = 1; 60 break; 61 case 'x': 62 xflag = 1; 63 break; 64 case '?': 65 default: 66 usage(); 67 } 68 argc -= optind; 69 argv += optind; 70 71 if (!*argv) 72 input(stdin); 73 else for (; *argv; ++argv) 74 if (fp = fopen(*argv, "r")) { 75 input(fp); 76 (void)fclose(fp); 77 } else { 78 (void)fprintf(stderr, "column: %s: %s\n", *argv, 79 strerror(errno)); 80 eval = 1; 81 } 82 83 if (!entries) 84 exit(eval); 85 86 if (tflag) 87 maketbl(); 88 else { 89 if (maxlength >= termwidth) 90 print(); 91 if (xflag) 92 c_columnate(); 93 else 94 r_columnate(); 95 } 96 exit(eval); 97 } 98 99 #define TAB 8 100 c_columnate() 101 { 102 register int chcnt, col, cnt, numcols; 103 int endcol; 104 char **lp; 105 106 maxlength = (maxlength + TAB) & ~(TAB - 1); 107 numcols = termwidth / maxlength; 108 endcol = maxlength; 109 for (chcnt = col = 0, lp = list;; ++lp) { 110 chcnt += printf("%s", *lp); 111 if (!--entries) 112 break; 113 if (++col == numcols) { 114 chcnt = col = 0; 115 endcol = maxlength; 116 putchar('\n'); 117 } else { 118 while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { 119 (void)putchar('\t'); 120 chcnt = cnt; 121 } 122 endcol += maxlength; 123 } 124 } 125 if (chcnt) 126 putchar('\n'); 127 } 128 129 r_columnate() 130 { 131 register int base, chcnt, cnt, col; 132 int endcol, numcols, numrows, row; 133 134 maxlength = (maxlength + TAB) & ~(TAB - 1); 135 numcols = termwidth / maxlength; 136 numrows = entries / numcols; 137 if (entries % numcols) 138 ++numrows; 139 140 for (row = 0; row < numrows; ++row) { 141 endcol = maxlength; 142 for (base = row, chcnt = col = 0; col < numcols; ++col) { 143 chcnt += printf("%s", list[base]); 144 if ((base += numrows) >= entries) 145 break; 146 while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { 147 (void)putchar('\t'); 148 chcnt = cnt; 149 } 150 endcol += maxlength; 151 } 152 putchar('\n'); 153 } 154 } 155 156 print() 157 { 158 register int cnt; 159 register char **lp; 160 161 for (cnt = entries, lp = list; cnt--; ++lp) 162 (void)printf("%s\n", *lp); 163 } 164 165 typedef struct _tbl { 166 char **list; 167 int cols, *len; 168 } TBL; 169 #define DEFCOLS 25 170 171 maketbl() 172 { 173 register TBL *t; 174 register int coloff, cnt; 175 register char *p, **lp; 176 int *lens, maxcols; 177 TBL *tbl; 178 char **cols, *emalloc(), *realloc(); 179 180 t = tbl = (TBL *)emalloc(entries * sizeof(TBL)); 181 cols = (char **)emalloc((maxcols = DEFCOLS) * sizeof(char *)); 182 lens = (int *)emalloc(maxcols * sizeof(int)); 183 for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) { 184 for (coloff = 0, p = *lp; cols[coloff] = strtok(p, separator); 185 p = NULL) 186 if (++coloff == maxcols) { 187 if (!(cols = (char **)realloc((char *)cols, 188 (u_int)maxcols + DEFCOLS * sizeof(char *))) || 189 !(lens = (int *)realloc((char *)lens, 190 (u_int)maxcols + DEFCOLS * sizeof(int)))) 191 nomem(); 192 bzero((char *)lens + maxcols * sizeof(int), 193 DEFCOLS * sizeof(int)); 194 maxcols += DEFCOLS; 195 } 196 t->list = (char **)emalloc(coloff * sizeof(char *)); 197 t->len = (int *)emalloc(coloff * sizeof(int)); 198 for (t->cols = coloff; --coloff >= 0;) { 199 t->list[coloff] = cols[coloff]; 200 t->len[coloff] = strlen(cols[coloff]); 201 if (t->len[coloff] > lens[coloff]) 202 lens[coloff] = t->len[coloff]; 203 } 204 } 205 for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) { 206 for (coloff = 0; coloff < t->cols - 1; ++coloff) 207 (void)printf("%s%*s", t->list[coloff], 208 lens[coloff] - t->len[coloff] + 2, " "); 209 (void)printf("%s\n", t->list[coloff]); 210 } 211 } 212 213 #define DEFNUM 1000 214 #define MAXLINELEN (2048 + 1) 215 216 input(fp) 217 register FILE *fp; 218 { 219 static int maxentry; 220 register int len; 221 register char *p; 222 char buf[MAXLINELEN], *emalloc(), *realloc(); 223 224 if (!list) 225 list = (char **)emalloc((maxentry = DEFNUM) * sizeof(char *)); 226 while (fgets(buf, MAXLINELEN, fp)) { 227 for (p = buf; *p && isspace(*p); ++p); 228 if (!*p) 229 continue; 230 if (!(p = index(p, '\n'))) { 231 (void)fprintf(stderr, "column: line too long.\n"); 232 eval = 1; 233 continue; 234 } 235 *p = '\0'; 236 len = p - buf; 237 if (maxlength < len) 238 maxlength = len; 239 if (entries == maxentry) { 240 maxentry += DEFNUM; 241 if (!(list = 242 (char **)realloc((char *)list, 243 (u_int)maxentry * sizeof(char *)))) 244 nomem(); 245 } 246 list[entries++] = strdup(buf); 247 } 248 } 249 250 char * 251 emalloc(size) 252 int size; 253 { 254 char *p, *malloc(); 255 256 /* NOSTRICT */ 257 if (!(p = malloc((u_int)size))) 258 nomem(); 259 bzero(p, size); 260 return(p); 261 } 262 263 nomem() 264 { 265 (void)fprintf(stderr, "column: out of memory.\n"); 266 exit(1); 267 } 268 269 usage() 270 { 271 (void)fprintf(stderr, 272 "usage: column [-tx] [-c columns] [file ...]\n"); 273 exit(1); 274 } 275