| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | /* See LICENSE file for copyright and license details. */ | 
					
						
							|  |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2015-02-01 01:24:03 +01:00
										 |  |  | #include <stdint.h>
 | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2014-11-13 18:29:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | #include "util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | static int    bflag = 0; | 
					
						
							|  |  |  | static int    sflag = 0; | 
					
						
							|  |  |  | static size_t width = 80; | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | foldline(const char *str) | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	size_t i = 0, n = 0, col, j; | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 	int space; | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 	char c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		space = 0; | 
					
						
							|  |  |  | 		for (j = i, col = 0; str[j] && col <= width; j++) { | 
					
						
							|  |  |  | 			c = str[j]; | 
					
						
							|  |  |  | 			if (!UTF8_POINT(c) && !bflag) | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			if (sflag && isspace(c)) { | 
					
						
							|  |  |  | 				space = 1; | 
					
						
							|  |  |  | 				n = j + 1; | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 			} else if (!space) { | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 				n = j; | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 			if (!bflag && iscntrl(c)) { | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 				switch(c) { | 
					
						
							|  |  |  | 				case '\b': | 
					
						
							|  |  |  | 					col--; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case '\r': | 
					
						
							|  |  |  | 					col = 0; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case '\t': | 
					
						
							|  |  |  | 					col += (col + 1) % 8; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 				col++; | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 		if (fwrite(str + i, 1, n - i, stdout) != n - i) | 
					
						
							|  |  |  | 			eprintf("fwrite <stdout>:"); | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 		if (str[n]) | 
					
						
							|  |  |  | 			putchar('\n'); | 
					
						
							|  |  |  | 	} while (str[i = n] && str[i] != '\n'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | fold(FILE *fp, const char *fname) | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *buf = NULL; | 
					
						
							|  |  |  | 	size_t size = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 	while (getline(&buf, &size, fp) >= 0) | 
					
						
							|  |  |  | 		foldline(buf); | 
					
						
							|  |  |  | 	if (ferror(fp)) | 
					
						
							|  |  |  | 		eprintf("getline %s:", fname); | 
					
						
							| 
									
										
										
										
											2015-01-25 21:22:17 +01:00
										 |  |  | 	free(buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | usage(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-03-05 08:15:23 +00:00
										 |  |  | 	eprintf("usage: %s [-bs] [-w width | -width] [FILE...]\n", argv0); | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | int | 
					
						
							|  |  |  | main(int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	FILE *fp; | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 	int ret = 0; | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | 	ARGBEGIN { | 
					
						
							|  |  |  | 	case 'b': | 
					
						
							| 
									
										
										
										
											2014-11-13 21:24:47 +01:00
										 |  |  | 		bflag = 1; | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 's': | 
					
						
							| 
									
										
										
										
											2014-11-13 21:24:47 +01:00
										 |  |  | 		sflag = 1; | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 'w': | 
					
						
							| 
									
										
										
										
											2015-02-01 01:24:03 +01:00
										 |  |  | 		width = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX)); | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2013-11-11 19:53:01 +00:00
										 |  |  | 	ARGNUM: | 
					
						
							| 
									
										
										
										
											2015-01-30 16:45:44 +00:00
										 |  |  | 		width = ARGNUMF(); | 
					
						
							| 
									
										
										
										
											2013-11-11 19:53:01 +00:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		usage(); | 
					
						
							|  |  |  | 	} ARGEND; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 	if (!argc) { | 
					
						
							|  |  |  | 		fold(stdin, "<stdin>"); | 
					
						
							| 
									
										
										
										
											2015-01-25 20:26:30 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 		for (; *argv; argc--, argv++) { | 
					
						
							|  |  |  | 			if (!(fp = fopen(*argv, "r"))) { | 
					
						
							|  |  |  | 				weprintf("fopen %s:", *argv); | 
					
						
							|  |  |  | 				ret = 1; | 
					
						
							| 
									
										
										
										
											2014-04-22 13:43:01 +03:00
										 |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 			fold(fp, *argv); | 
					
						
							| 
									
										
										
										
											2014-04-22 13:43:01 +03:00
										 |  |  | 			fclose(fp); | 
					
						
							| 
									
										
										
										
											2013-11-12 10:44:37 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-14 20:20:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 23:47:41 +01:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2011-06-08 21:30:33 +01:00
										 |  |  | } |