diff options
Diffstat (limited to 'pgm2')
| -rw-r--r-- | pgm2/input.txt | 5 | ||||
| -rwxr-xr-x | pgm2/makefile | 31 | ||||
| -rw-r--r-- | pgm2/p2test/d1/a.out | bin | 0 -> 10766 bytes | |||
| -rw-r--r-- | pgm2/p2test/d1/f1 | 11 | ||||
| -rw-r--r-- | pgm2/p2test/f1 | 1 | ||||
| -rw-r--r-- | pgm2/p2test/f2 | 3 | ||||
| -rw-r--r-- | pgm2/p2test/f3 | 2 | ||||
| -rw-r--r-- | pgm2/p2test/grepout | 6 | ||||
| -rw-r--r-- | pgm2/rgpp.c | 381 | 
9 files changed, 440 insertions, 0 deletions
| diff --git a/pgm2/input.txt b/pgm2/input.txt new file mode 100644 index 0000000..d879fce --- /dev/null +++ b/pgm2/input.txt @@ -0,0 +1,5 @@ +p2test/f2:2:Want to see the and, by implication, there. +p2test/f2:3:THere might work too. +p2test/d1/f1:5:only a three lines have a "the" in them +p2test/d1/f1:7:several other words +p2test/d1/f1:10:another paragraph without a match diff --git a/pgm2/makefile b/pgm2/makefile new file mode 100755 index 0000000..3486352 --- /dev/null +++ b/pgm2/makefile @@ -0,0 +1,31 @@ +all: +  gcc -Wall -o rgpp rgpp.c -lm + +clean: +  rm rgpp + +debug: +  gcc -Wall -g -o rgpp rgpp.c -lm + +test: +  gcc -Wall -o rgpp rgpp.c -lm + +  # a) [6 pts] Straightforward line mode with a banner and line numbers: +  grep -r -H -n -s -I -i the p2test | ./rgpp -l -b -n + +  # b) [7 pts] Straightforward word mode with a banner and line numbers: +  grep -r -H -n -s -I -i the p2test | ./rgpp -w the -b -n + +  # c) [4 pts] Dealing with lots of files/hits: +  grep -r -H -n -s -I -i the /usr/share/gutenprint | ./rgpp -l -b > output + +  # a) [1 pt] Invalid option (must produce error message): +  grep -r -H -n -s -I -i the p2test | ./rgpp -l -b -k + +  # b) [1 pt] Invalid first option (must produce error message): +  grep -r -H -n -s -I -i the p2test | ./rgpp -n -l -b + +  # c) [1 pt] Mismatch problems (no message and garbage out OK): +  grep -r -H -n -s -I -i se p2test | ./rgpp -w the -b -n + +  rm rgpp diff --git a/pgm2/p2test/d1/a.out b/pgm2/p2test/d1/a.outBinary files differ new file mode 100644 index 0000000..c1ea1d0 --- /dev/null +++ b/pgm2/p2test/d1/a.out diff --git a/pgm2/p2test/d1/f1 b/pgm2/p2test/d1/f1 new file mode 100644 index 0000000..3d3d722 --- /dev/null +++ b/pgm2/p2test/d1/f1 @@ -0,0 +1,11 @@ +this file has +lots of +lines +but +only a three lines have a "the" in them + +several other words +are here + +another paragraph without a match +I believe diff --git a/pgm2/p2test/f1 b/pgm2/p2test/f1 new file mode 100644 index 0000000..eeec7c2 --- /dev/null +++ b/pgm2/p2test/f1 @@ -0,0 +1 @@ +this is a one-line file diff --git a/pgm2/p2test/f2 b/pgm2/p2test/f2 new file mode 100644 index 0000000..0e029cc --- /dev/null +++ b/pgm2/p2test/f2 @@ -0,0 +1,3 @@ +Several lines in this one. +Want to see the and, by implication, there. +THere might work too. diff --git a/pgm2/p2test/f3 b/pgm2/p2test/f3 new file mode 100644 index 0000000..abd9f9e --- /dev/null +++ b/pgm2/p2test/f3 @@ -0,0 +1,2 @@ +this is a one-line file +thethea diff --git a/pgm2/p2test/grepout b/pgm2/p2test/grepout new file mode 100644 index 0000000..2f9cec5 --- /dev/null +++ b/pgm2/p2test/grepout @@ -0,0 +1,6 @@ +./f2:2:Want to see the and, by implication, there. +./f2:3:THere might work too. +./d1/f1:5:only a three lines have a "the" in them +./d1/f1:7:several other words +./d1/f1:10:another paragraph without a match +./f3:2:thethea diff --git a/pgm2/rgpp.c b/pgm2/rgpp.c new file mode 100644 index 0000000..6d7b2ee --- /dev/null +++ b/pgm2/rgpp.c @@ -0,0 +1,381 @@ +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#define TRUE 1 +#define FALSE 0 +#define BUFF_FILE 256 +#define BUFF_LINE 2048 + +struct NODE { +	char filename[BUFF_FILE]; +	char lineNumber[10]; +	char line[BUFF_LINE]; +	struct NODE *next; +}; + +int buildList(struct NODE **listHead) { +	/* +	 * buildList() reads input from stdin (the resulting output of a grep call) + 	 * and generates a linked list of nodes. Each node contains the filename, + 	 * line number, and line of text of the match that grep specified. The + 	 * function returns a hitCount to main() so that the program knows + 	 * whether or not the input (grep's output) was valid. The line number is +	 * not inserted into each node, but is available for testing purposes +	 * should this be necessary. +	 */ +	char filename[BUFF_FILE]; +	char lineNumber[4]; + 	char line[BUFF_LINE]; +	int hitCount = 0; + 	struct NODE *newNode = NULL; + + 	while (fscanf(stdin, "%256[^:]:%4[^:]:%2048[^\n]\n", filename, +			lineNumber, line) == 3) { + 		newNode = (struct NODE *) malloc(sizeof(struct NODE)); + 		strncpy(newNode->filename, filename, BUFF_FILE); + 		strncpy(newNode->line, line, BUFF_LINE); + 		newNode->next = *listHead; + 		*listHead = newNode; +		hitCount++; + 	} + +	return hitCount; +} + +int lineHunter (struct NODE **listHead, int hitCount, +		int lineNumberSwitch, int bannerSwitch) { +	/* +	 * lineHunter() iterates through the nodes built in buildList() + 	 * and looks for lines in the given files that match the lines presented + 	 * in the nodes themselves. If it finds a match, it prints an '*' next + 	 * to the line that it finds. It only opens new files (files that haven't + 	 * been opened before) and then runs through the nodes a second time to + 	 * find matches to the lines being printed. +	 */ +	char filename[BUFF_FILE]; +	char line[BUFF_LINE]; +	int tagBool; +	int lineCount; +	struct NODE *currentNode = *listHead; +	struct NODE *matchNode = NULL; +	FILE *grepFile = NULL; + +	// If args specify banner then print it. +	if (bannerSwitch) { +		printf("\nTHERE ARE %d MATCHING LINES\n", hitCount); +	} + +	// Iterate through filenames +	while (currentNode->next != NULL) { + +		if (!(grepFile = fopen(currentNode->filename, "r"))) { +			fprintf(stderr, "rgpp: error: grep filename couldn't " +				"be opened -- check input.\n"); +			exit(1); +		} + +		strcpy(filename, currentNode->filename); +		printf("\n====================%s\n", currentNode->filename); +		lineCount = 1; + +		// While in the same file print file contents. +		while (fgets(line, BUFF_LINE, grepFile)) { + +			// Strip the newline off of lines pulled from file. +			line[strlen(line) - 1] = '\0'; +			tagBool = FALSE; +			matchNode = *listHead; + +			// Search through nodes to find match to line. +			while (matchNode != NULL) { + +				if (strcmp(currentNode->filename, matchNode->filename) == 0 +					&& strcmp(currentNode->lineNumber, +						matchNode->lineNumber) == 0 +					&& strcmp(line, matchNode->line) == 0) { +					tagBool = TRUE; +				} + +				matchNode = matchNode->next; +			} + +			// Print tag if match was found in line. +			if (tagBool) { +				printf("*  "); +			} +			else { +				printf("   "); +			} + +			// If  args specify line numbering, print them. +			if (lineNumberSwitch) { +				printf("%4d: ", lineCount); +			} + +			// Print the line of text. +			printf("%s\n", line); +			lineCount++; +		} + +		fclose(grepFile); + +		// Search for next new file to open. +		while (strcmp(filename, currentNode->filename) == 0 +				&& currentNode->next != NULL) { +			currentNode = currentNode->next; +		} + +	} + +	return 0; +} + +int wordHunter (struct NODE **listHead, int lineNumberSwitch, +		int bannerSwitch, char *word) { +	/* +	 * wordHunter() iterates through the nodes created in buildList() + 	 * and looks for lines in the given files that match the lines + 	 * specified by the nodes themselves. If a match is found (aka a line + 	 * is determined to contain matches according to grep) then the function + 	 * goes through the line in the node looking for matching words, printing + 	 * them in inverse video. +	 */ +	char *matchWord[BUFF_FILE]; +	char filename[BUFF_FILE]; +	char line[BUFF_LINE]; +	int i; +	int j; +	int k; +	int hitCount = 0; +	int matchBool; +	int lineCount; +	struct NODE *currentNode = *listHead; +	struct NODE *matchNode = NULL; +	FILE *grepFile = NULL; + +	// Print out the banner based on args. +	if (bannerSwitch) { + +	    // Iterate through files to find matches for hitCount +	    while (currentNode != NULL) { +			i = 0; +			j = 0; + +			// This while loop checks the string character by character for +			// matches to the given word. +			while (currentNode->line[i] != '\0') { + +				if (word[j] == '\0') { +					j = 0; +					hitCount++; +				} +				else if (tolower(currentNode->line[i]) == tolower(word[j])) { +					j++; +				} +				else { +					j = 0; +				} + +				i++; +			} + +	        currentNode = currentNode->next; +	    } + +	    printf("\nTHERE ARE %d MATCHING WORDS\n", hitCount); +	} + +	currentNode = *listHead; + +	// Iterate through filenames +	while (currentNode->next != NULL) { + +	    if (!(grepFile = fopen(currentNode->filename, "r"))) { +	        fprintf(stderr, "rgpp: error: grep filename couldn't be " +				"opened -- check input\n"); +	        exit(1); +	    } + +	    strcpy(filename, currentNode->filename); + +		// Print out filename header. +	    printf("\n=====================%s\n", currentNode->filename); +	    lineCount = 1; + +	    // While in the same file, print file contents +	    while (fgets(line, BUFF_LINE, grepFile)) { +	        // Strip the newline off of lines pulled from file. +	        line[strlen(line) - 1] = '\0'; + +	        // If the args specify line numbering, print them. +	        if (lineNumberSwitch) { +	            printf("%4d: ", lineCount); +	        } + +			// Find if line is  a match in nodes. +			matchNode = *listHead; +			matchBool = FALSE; + +			while (matchNode != NULL) { + +				if (strcmp(line, matchNode->line) == 0) { +					matchBool = TRUE; +				} + +				matchNode = matchNode->next; +			} + +			// If the line isn't a match then print the line +			if (!matchBool) { +				printf("%s", line); +			} +			else { +				// Find and highlight the matching words in the node line. +				i = 0; +				j = 0; +				*matchWord = ""; + +				// This while loop checks the string character by character for +				// matches to the given word. If a match is not found, the +				// characters are printed to output. If a match is found, it +				// is highlighted with inverse video and then printed. +				while (line[i] != '\0') { + +					if (word[j] == '\0') { +						printf("\e[7m"); + +						for (k = i - j; k < i; k++) { +							printf("%c", line[k]); +						} + +						printf("\e[0m"); +						j = 0; +					} + +					if (tolower(line[i]) == tolower(word[j])) { +						j++; +					} + +					else { + +						if (j != 0) { + +							for (k = i - j; k <= i; k++) { +								printf("%c", line[k]); +							} + +							j = 0; +						} + +						else { +							printf("%c", line[i]); +						} + +					} + +					i++; +				} + +			} + +			lineCount++; +			printf("\n"); + +		} + +	    fclose(grepFile); + +	    // Search for next file to open. +	    while (strcmp(filename, currentNode->filename) == 0 +	            && currentNode->next != NULL) { +	        currentNode = currentNode->next; +	    } + +	} + +	return 0; +} + +int main(int argc, char *argv[]) { +	/* +	 * main()'s soul purpose is to receive the command line arguments for rgpp + 	 * and then process them and make the necessary function calls to fulfill + 	 * the user's request. It also checks to make sure that return values are + 	 * valid from those functions. +	 */ +	char word[BUFF_LINE]; +	int i = 1; +	int modeSwitch = -1; +	int lineNumberSwitch = 0; +	int bannerSwitch = 0; +	int hitCount = 0; +	struct NODE *list = NULL; + +	// Check for minimum number of required args. +	if (strcmp(argv[1], "-l") != 0 && strcmp(argv[1], "-w") != 0) { +		fprintf(stderr, "rgpp: usage: rgpp [-l | -w word] {-n} {-b}\n"); +		exit(1); +	} + +	// Read args, set variables based on switches and optional word. +	while(argv[i] != NULL) { + +		if (!strcmp(argv[i], "-l")) { +			modeSwitch = 0; +		} +		else if (!strcmp(argv[i], "-w")) { +			modeSwitch = 1; +			strncpy(word, argv[i+1], BUFF_LINE); +			i++; +		} +		else if (!strcmp(argv[i], "-b")) { +			bannerSwitch = 1; +		} +		else if (!strcmp(argv[i], "-n")) { +			lineNumberSwitch = 1; +		} +		else { +			fprintf(stderr, "rgpp: usage: rgpp [-l | -w word] {-n} {-b}\n"); +			exit(1); +		} + +		i++; +	} + +	// Call buildList to read input and build linked list. +	hitCount = buildList(&list); + +	if (hitCount == 0) { +		fprintf(stderr, "rgpp: error: no grep results found -- " +			"check grep input\n"); +		exit(1); +	} + +	if (modeSwitch) { +		if (wordHunter(&list, lineNumberSwitch, bannerSwitch, word) != 0) { +			fprintf(stderr, "rgpp: error: no word matches --" +				" check grep input and word arg\n"); +			exit(1); +		} +	} +	else { +		if (lineHunter(&list, hitCount, lineNumberSwitch, bannerSwitch) != 0) { +			fprintf(stderr, "rgpp: error: no line matches --" +				" check grep input\n"); +			exit(1); +		} +	} + +	// Free allocated memory. +	struct NODE *tmp; + +	while (list != NULL) { +		tmp = list; +		list = list->next; +		free(tmp); +	} + +	exit(0); +} |