Audit cols(1)
1) Refactor manpage. 2) De-globalize local values. 3) update usage(). 4) sort local variable declarations. 5) fix wrong argument in strtonum (3 -> 1). 6) argc-argv style, boolean style. 7) check bytes > 0 before accessing b.lines[i][bytes - 1] relying on len only makes sense but let's not push it. 7) don't break on maxlen > (chars - 1) / 2. This didn't even make sense. 8) _correctly_ calculate cols and rows in a readable way. 9) Rewrite loop over rows and cols in a readable way and using putchar in a loop instead of printf-magic or fputs where not necessary.
This commit is contained in:
		
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							| @@ -18,7 +18,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support, | ||||
| =*| chroot          non-posix                    none | ||||
| =*  cksum           yes                          none | ||||
| =*  cmp             yes                          none | ||||
| #*  cols            non-posix                    none | ||||
| #*| cols            non-posix                    none | ||||
|     col             yes                          none | ||||
| =*  comm            yes                          none | ||||
| =*| cp              yes                          none (-i) | ||||
|   | ||||
							
								
								
									
										19
									
								
								cols.1
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								cols.1
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| .Dd February 19, 2015 | ||||
| .Dd March 8, 2015 | ||||
| .Dt COLS 1 | ||||
| .Os sbase | ||||
| .Sh NAME | ||||
| @@ -15,7 +15,8 @@ reads each | ||||
| in sequence and writes them to stdout, in as many vertical | ||||
| columns as will fit in | ||||
| .Ar num | ||||
| character columns. If no | ||||
| character columns. | ||||
| If no | ||||
| .Ar file | ||||
| is given, | ||||
| .Nm | ||||
| @@ -27,17 +28,15 @@ tries to figure out the width of the output | ||||
| device. If that fails, it defaults to 65 chars. | ||||
| .Sh OPTIONS | ||||
| .Bl -tag -width Ds | ||||
| .It Fl c Ar chars | ||||
| Set the maximum number of character columns to use | ||||
| (unless the input contains lines longer than | ||||
| .Ar num | ||||
| characters). | ||||
| .It Fl c Ar num | ||||
| Set maximum number of character columns to | ||||
| .Ar num , | ||||
| unless input lines exceed this limit. | ||||
| .El | ||||
| .Sh ENVIRONMENT | ||||
| .Bl -tag -width COLUMNS | ||||
| .Bl -tag -width Ds | ||||
| .It COLUMNS | ||||
| If this variable is set, the value is used as the | ||||
| width of the output device. | ||||
| The width of the output device. | ||||
| .El | ||||
| .Sh HISTORY | ||||
| .Nm | ||||
|   | ||||
							
								
								
									
										74
									
								
								cols.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								cols.c
									
									
									
									
									
								
							| @@ -12,82 +12,74 @@ | ||||
| #include "utf.h" | ||||
| #include "util.h" | ||||
|  | ||||
| static size_t chars = 65; | ||||
| static int    cflag; | ||||
| static struct linebuf b = EMPTY_LINEBUF; | ||||
|  | ||||
| static size_t n_columns; | ||||
| static size_t n_rows; | ||||
|  | ||||
| static void | ||||
| usage(void) | ||||
| { | ||||
| 	eprintf("usage: %s [-c chars] [file ...]\n", argv0); | ||||
| 	eprintf("usage: %s [-c num] [file ...]\n", argv0); | ||||
| } | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	size_t i, l, col, len, bytes, maxlen = 0; | ||||
| 	struct winsize w; | ||||
| 	FILE *fp; | ||||
| 	struct winsize w; | ||||
| 	struct linebuf b = EMPTY_LINEBUF; | ||||
| 	size_t chars = 65, maxlen = 0, i, j, k, len, bytes, cols, rows; | ||||
| 	int cflag = 0; | ||||
| 	char *p; | ||||
|  | ||||
| 	ARGBEGIN { | ||||
| 	case 'c': | ||||
| 		cflag = 1; | ||||
| 		chars = estrtonum(EARGF(usage()), 3, MIN(LLONG_MAX, SIZE_MAX)); | ||||
| 		chars = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX)); | ||||
| 		break; | ||||
| 	default: | ||||
| 		usage(); | ||||
| 	} ARGEND; | ||||
|  | ||||
| 	if (cflag == 0) { | ||||
| 	if (!cflag) { | ||||
| 		if ((p = getenv("COLUMNS"))) | ||||
| 			chars = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX)); | ||||
| 		else if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) && w.ws_col > 0) | ||||
| 			chars = w.ws_col; | ||||
| 	} | ||||
|  | ||||
| 	if (argc == 0) { | ||||
| 	if (!argc) { | ||||
| 		getlines(stdin, &b); | ||||
| 	} else for (; argc > 0; argc--, argv++) { | ||||
| 		if (!(fp = fopen(argv[0], "r"))) | ||||
| 			eprintf("fopen %s:", argv[0]); | ||||
| 		getlines(fp, &b); | ||||
| 		fclose(fp); | ||||
| 	} else { | ||||
| 		for (; *argv; argc--, argv++) { | ||||
| 			if (!(fp = fopen(*argv, "r"))) { | ||||
| 				weprintf("fopen %s:", *argv); | ||||
| 				continue; | ||||
| 			} | ||||
| 			getlines(fp, &b); | ||||
| 			fclose(fp); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for (l = 0; l < b.nlines; ++l) { | ||||
| 		len = utflen(b.lines[l]); | ||||
| 		bytes = strlen(b.lines[l]); | ||||
| 		if (len > 0 && b.lines[l][bytes - 1] == '\n') { | ||||
| 			b.lines[l][bytes - 1] = '\0'; | ||||
| 			--len; | ||||
| 	for (i = 0; i < b.nlines; i++) { | ||||
| 		len = utflen(b.lines[i]); | ||||
| 		bytes = strlen(b.lines[i]); | ||||
| 		if (len && bytes && b.lines[i][bytes - 1] == '\n') { | ||||
| 			b.lines[i][bytes - 1] = '\0'; | ||||
| 			len--; | ||||
| 		} | ||||
| 		if (len > maxlen) | ||||
| 			maxlen = len; | ||||
| 		if (maxlen > (chars - 1) / 2) | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	n_columns = (chars + 1) / (maxlen + 1); | ||||
| 	if (n_columns <= 1) { | ||||
| 		for (l = 0; l < b.nlines; ++l) { | ||||
| 			fputs(b.lines[l], stdout); | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
| 	for (cols = 1; (cols + 1) * maxlen + cols <= chars; cols++); | ||||
| 	rows = b.nlines / cols + (b.nlines % cols > 0); | ||||
|  | ||||
| 	n_rows = (b.nlines + (n_columns - 1)) / n_columns; | ||||
| 	for (i = 0; i < n_rows; ++i) { | ||||
| 		for (l = i, col = 1; l < b.nlines; l += n_rows, ++col) { | ||||
| 			len = utflen(b.lines[l]); | ||||
| 			fputs(b.lines[l], stdout); | ||||
| 			if (col < n_columns) | ||||
| 				printf("%*s", (int)(maxlen + 1 - len), ""); | ||||
| 	for (i = 0; i < rows; i++) { | ||||
| 		for (j = 0; j < cols && i + j * rows < b.nlines; j++) { | ||||
| 			len = utflen(b.lines[i + j * rows]); | ||||
| 			fputs(b.lines[i + j * rows], stdout); | ||||
| 			if (j < cols - 1) | ||||
| 				for (k = len; k < maxlen + 1; k++) | ||||
| 					putchar(' '); | ||||
| 		} | ||||
| 		fputs("\n", stdout); | ||||
| 		putchar('\n'); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user