Support NUL containing lines in join(1)
while also simplyfing the line-field-parser.
This commit is contained in:
		
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							| @@ -43,7 +43,7 @@ The following tools are implemented: | |||||||
| 0=*|o head            . | 0=*|o head            . | ||||||
| 0=*|x hostname        . | 0=*|x hostname        . | ||||||
| 0=*|x install         . | 0=*|x install         . | ||||||
|  =* o join            . | 0=* o join            . | ||||||
| 0=*|o kill            . | 0=*|o kill            . | ||||||
| 0=*|o link            . | 0=*|o link            . | ||||||
| 0=*|o ln              . | 0=*|o ln              . | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								join.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								join.c
									
									
									
									
									
								
							| @@ -27,7 +27,7 @@ struct field { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| struct jline { | struct jline { | ||||||
| 	char *text; | 	struct line text; | ||||||
| 	size_t nf; | 	size_t nf; | ||||||
| 	size_t maxf; | 	size_t maxf; | ||||||
| 	struct field *fields; | 	struct field *fields; | ||||||
| @@ -144,18 +144,14 @@ prjoin(struct jline *la, struct jline *lb, size_t jfa, size_t jfb) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	putchar('\n'); | 	putchar('\n'); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| prline(struct jline *lp) | prline(struct jline *lp) | ||||||
| { | { | ||||||
| 	size_t len = strlen(lp->text); | 	if (fwrite(lp->text.data, 1, lp->text.len, stdout) != lp->text.len) | ||||||
|  |  | ||||||
| 	if (fwrite(lp->text, 1, len, stdout) != len) |  | ||||||
| 		eprintf("fwrite:"); | 		eprintf("fwrite:"); | ||||||
|  |  | ||||||
| 	putchar('\n'); | 	putchar('\n'); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -166,12 +162,12 @@ jlinecmp(struct jline *la, struct jline *lb, size_t jfa, size_t jfb) | |||||||
|  |  | ||||||
| 	/* return FIELD_ERROR if both lines are short */ | 	/* return FIELD_ERROR if both lines are short */ | ||||||
| 	if (jfa >= la->nf) { | 	if (jfa >= la->nf) { | ||||||
| 		status = jfb >= lb->nf ? FIELD_ERROR : -1; | 		status = (jfb >= lb->nf) ? FIELD_ERROR : -1; | ||||||
| 	} else if (jfb >= lb->nf) { | 	} else if (jfb >= lb->nf) { | ||||||
| 		status = 1; | 		status = 1; | ||||||
| 	} else { | 	} else { | ||||||
| 		status = memcmp(la->fields[jfa].s, lb->fields[jfb].s, | 		status = memcmp(la->fields[jfa].s, lb->fields[jfb].s, | ||||||
| 		MAX (la->fields[jfa].len, lb->fields[jfb].len)); | 		                MAX(la->fields[jfa].len, lb->fields[jfb].len)); | ||||||
| 		LIMIT(status, -1, 1); | 		LIMIT(status, -1, 1); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -205,53 +201,43 @@ static struct jline * | |||||||
| makeline(char *s, size_t len) | makeline(char *s, size_t len) | ||||||
| { | { | ||||||
| 	struct jline *lp; | 	struct jline *lp; | ||||||
| 	char *sp, *beg, *end; | 	char *tmp; | ||||||
| 	size_t i; | 	size_t i, end; | ||||||
| 	int eol = 0; |  | ||||||
|  |  | ||||||
| 	if (s[len-1] == '\n') | 	if (s[len - 1] == '\n') | ||||||
| 		s[len-1] = '\0'; | 		s[--len] = '\0'; | ||||||
|  |  | ||||||
| 	lp = ereallocarray(NULL, INIT, sizeof(struct jline)); | 	lp = ereallocarray(NULL, INIT, sizeof(struct jline)); | ||||||
| 	lp->text = s; | 	lp->text.data = s; | ||||||
|  | 	lp->text.len = len; | ||||||
| 	lp->fields = ereallocarray(NULL, INIT, sizeof(struct field)); | 	lp->fields = ereallocarray(NULL, INIT, sizeof(struct field)); | ||||||
| 	lp->nf = 0; | 	lp->nf = 0; | ||||||
| 	lp->maxf = INIT; | 	lp->maxf = INIT; | ||||||
|  |  | ||||||
| 	for (sp = lp->text; isblank(*sp); sp++) | 	for (i = 0; i < lp->text.len && isblank(lp->text.data[i]); i++) | ||||||
| 		; | 		; | ||||||
|  | 	while (i < lp->text.len) { | ||||||
| 	while (!eol) { |  | ||||||
| 		beg = sp; |  | ||||||
|  |  | ||||||
| 		if (sep) { | 		if (sep) { | ||||||
| 			if (!(end = utfutf(sp, sep))) | 			if ((lp->text.len - i) < seplen || | ||||||
| 				eol = 1; | 			    !(tmp = memmem(lp->text.data + i, | ||||||
|  | 			                   lp->text.len - i, sep, seplen))) { | ||||||
| 			if (!eol) { | 				goto eol; | ||||||
| 				addfield(lp, beg, end - beg); |  | ||||||
| 				for (i = 0; i < seplen; i++) |  | ||||||
| 					end++; |  | ||||||
| 			} | 			} | ||||||
|  | 			end = tmp - lp->text.data; | ||||||
|  | 			addfield(lp, lp->text.data + i, end - i); | ||||||
|  | 			i = end + seplen; | ||||||
| 		} else { | 		} else { | ||||||
| 			for (end = sp; !(isblank(*end)); end++) { | 			for (end = i; !(isblank(lp->text.data[end])); end++) { | ||||||
| 				if (*end == '\0') { | 				if (end + 1 == lp->text.len) | ||||||
| 					eol = 1; | 					goto eol; | ||||||
| 					break; |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
|  | 			addfield(lp, lp->text.data + i, end - i); | ||||||
| 			if (!eol) | 			for (i = end; isblank(lp->text.data[i]); i++) | ||||||
| 				addfield(lp, beg, end - beg); |  | ||||||
| 			while (isblank(*++end)) |  | ||||||
| 				; | 				; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (eol) |  | ||||||
| 			addfield(lp, beg, strlen(sp)); |  | ||||||
|  |  | ||||||
| 		sp = end; |  | ||||||
| 	} | 	} | ||||||
|  | eol: | ||||||
|  | 	addfield(lp, lp->text.data + i, lp->text.len - i); | ||||||
|  |  | ||||||
| 	return lp; | 	return lp; | ||||||
| } | } | ||||||
| @@ -260,9 +246,10 @@ static int | |||||||
| addtospan(struct span *sp, FILE *fp, int reset) | addtospan(struct span *sp, FILE *fp, int reset) | ||||||
| { | { | ||||||
| 	char *newl = NULL; | 	char *newl = NULL; | ||||||
| 	size_t len, size = 0; | 	ssize_t len; | ||||||
|  | 	size_t size = 0; | ||||||
|  |  | ||||||
| 	if ((len = getline(&newl, &size, fp)) == (size_t)-1) { | 	if ((len = getline(&newl, &size, fp)) < 0) { | ||||||
| 		if (ferror(fp)) | 		if (ferror(fp)) | ||||||
| 			eprintf("getline:"); | 			eprintf("getline:"); | ||||||
| 		else | 		else | ||||||
| @@ -298,9 +285,8 @@ freespan(struct span *sp) | |||||||
|  |  | ||||||
| 	for (i = 0; i < sp->nl; i++) { | 	for (i = 0; i < sp->nl; i++) { | ||||||
| 		free(sp->lines[i]->fields); | 		free(sp->lines[i]->fields); | ||||||
| 		free(sp->lines[i]->text); | 		free(sp->lines[i]->text.data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	free(sp->lines); | 	free(sp->lines); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user