Make grep more memory-efficient
This commit is contained in:
		
							
								
								
									
										38
									
								
								grep.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								grep.c
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ | |||||||
| enum { Match = 0, NoMatch = 1, Error = 2 }; | enum { Match = 0, NoMatch = 1, Error = 2 }; | ||||||
|  |  | ||||||
| static void addpattern(const char *); | static void addpattern(const char *); | ||||||
| static bool grep(FILE *, const char *); | static bool grep(FILE *, const char *, int); | ||||||
|  |  | ||||||
| static bool eflag = false; | static bool eflag = false; | ||||||
| static bool vflag = false; | static bool vflag = false; | ||||||
| @@ -20,7 +20,6 @@ static char mode = 0; | |||||||
|  |  | ||||||
| static struct plist { | static struct plist { | ||||||
| 	char *pattern; | 	char *pattern; | ||||||
| 	regex_t preg; |  | ||||||
| 	struct plist *next; | 	struct plist *next; | ||||||
| } *phead; | } *phead; | ||||||
|  |  | ||||||
| @@ -35,7 +34,7 @@ main(int argc, char *argv[]) | |||||||
| { | { | ||||||
| 	bool match = false; | 	bool match = false; | ||||||
| 	struct plist *pnode, *tmp; | 	struct plist *pnode, *tmp; | ||||||
| 	int i, n, flags = REG_NOSUB; | 	int i, flags = REG_NOSUB; | ||||||
| 	FILE *fp; | 	FILE *fp; | ||||||
|  |  | ||||||
| 	ARGBEGIN { | 	ARGBEGIN { | ||||||
| @@ -62,8 +61,9 @@ main(int argc, char *argv[]) | |||||||
| 		usage(); | 		usage(); | ||||||
| 	} ARGEND; | 	} ARGEND; | ||||||
|  |  | ||||||
|  | 	/* no pattern */ | ||||||
| 	if(argc == 0 && !eflag) | 	if(argc == 0 && !eflag) | ||||||
| 		usage(); /* no pattern */ | 		usage(); | ||||||
|  |  | ||||||
| 	/* If -e is not specified treat it as if it were */ | 	/* If -e is not specified treat it as if it were */ | ||||||
| 	if(!eflag) { | 	if(!eflag) { | ||||||
| @@ -72,23 +72,14 @@ main(int argc, char *argv[]) | |||||||
| 		argv++; | 		argv++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Compile regex for all search patterns */ |  | ||||||
| 	for(pnode = phead; pnode; pnode = pnode->next) { |  | ||||||
| 		if((n = regcomp(&pnode->preg, pnode->pattern, flags)) != 0) { |  | ||||||
| 			char buf[BUFSIZ]; |  | ||||||
|  |  | ||||||
| 			regerror(n, &pnode->preg, buf, sizeof buf); |  | ||||||
| 			enprintf(Error, "invalid pattern: %s\n", buf); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	many = (argc > 1); | 	many = (argc > 1); | ||||||
| 	if(argc == 0) { | 	if(argc == 0) { | ||||||
| 		match = grep(stdin, "<stdin>"); | 		match = grep(stdin, "<stdin>", flags); | ||||||
| 	} else { | 	} else { | ||||||
| 		for(i = 0; i < argc; i++) { | 		for(i = 0; i < argc; i++) { | ||||||
| 			if(!(fp = fopen(argv[i], "r"))) | 			if(!(fp = fopen(argv[i], "r"))) | ||||||
| 				enprintf(Error, "fopen %s:", argv[i]); | 				enprintf(Error, "fopen %s:", argv[i]); | ||||||
| 			if(grep(fp, argv[i])) | 			if(grep(fp, argv[i], flags)) | ||||||
| 				match = true; | 				match = true; | ||||||
| 			fclose(fp); | 			fclose(fp); | ||||||
| 		} | 		} | ||||||
| @@ -96,7 +87,6 @@ main(int argc, char *argv[]) | |||||||
| 	pnode = phead; | 	pnode = phead; | ||||||
| 	while(pnode) { | 	while(pnode) { | ||||||
| 		tmp = pnode->next; | 		tmp = pnode->next; | ||||||
| 		regfree(&pnode->preg); |  | ||||||
| 		free(pnode->pattern); | 		free(pnode->pattern); | ||||||
| 		free(pnode); | 		free(pnode); | ||||||
| 		pnode = tmp; | 		pnode = tmp; | ||||||
| @@ -120,20 +110,30 @@ addpattern(const char *pattern) | |||||||
| } | } | ||||||
|  |  | ||||||
| bool | bool | ||||||
| grep(FILE *fp, const char *str) | grep(FILE *fp, const char *str, int flags) | ||||||
| { | { | ||||||
| 	char *buf = NULL; | 	char *buf = NULL; | ||||||
| 	long n, c = 0; | 	long n, c = 0; | ||||||
|  | 	int r; | ||||||
|  | 	static regex_t preg; | ||||||
| 	size_t size = 0, len; | 	size_t size = 0, len; | ||||||
| 	struct plist *pnode; | 	struct plist *pnode; | ||||||
| 	bool match = false; | 	bool match = false; | ||||||
|  |  | ||||||
| 	for(n = 1; afgets(&buf, &size, fp); n++) { | 	for(n = 1; afgets(&buf, &size, fp); n++) { | ||||||
| 		for(pnode = phead; pnode; pnode = pnode->next) { | 		for(pnode = phead; pnode; pnode = pnode->next) { | ||||||
|  | 			if((r = regcomp(&preg, pnode->pattern, flags)) != 0) { | ||||||
|  | 				char err[BUFSIZ]; | ||||||
|  |  | ||||||
|  | 				regerror(r, &preg, err, sizeof err); | ||||||
|  | 				enprintf(Error, "invalid pattern: %s\n", err); | ||||||
|  | 			} | ||||||
| 			if(buf[(len = strlen(buf))-1] == '\n') | 			if(buf[(len = strlen(buf))-1] == '\n') | ||||||
| 				buf[--len] = '\0'; | 				buf[--len] = '\0'; | ||||||
| 			if(regexec(&pnode->preg, buf, 0, NULL, 0) ^ vflag) | 			if(regexec(&preg, buf, 0, NULL, 0) ^ vflag){ | ||||||
|  | 				regfree(&preg); | ||||||
| 				continue; | 				continue; | ||||||
|  | 			} | ||||||
| 			switch(mode) { | 			switch(mode) { | ||||||
| 			case 'c': | 			case 'c': | ||||||
| 				c++; | 				c++; | ||||||
| @@ -159,7 +159,7 @@ grep(FILE *fp, const char *str) | |||||||
| end: | end: | ||||||
| 	if(ferror(fp)) | 	if(ferror(fp)) | ||||||
| 		enprintf(Error, "%s: read error:", str); | 		enprintf(Error, "%s: read error:", str); | ||||||
|  | 	regfree(&preg); | ||||||
| 	free(buf); | 	free(buf); | ||||||
| 	return match; | 	return match; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user