diff options
author | 53hornet <53hornet@gmail.com> | 2019-02-02 22:59:54 -0500 |
---|---|---|
committer | 53hornet <53hornet@gmail.com> | 2019-02-02 22:59:54 -0500 |
commit | 379c2c17e68d5d471a6a9673b7e9cd1fb9d99bbb (patch) | |
tree | eed499da8211a5eece757639331a2d82bce4fa4c /pgm2 | |
download | csci415-379c2c17e68d5d471a6a9673b7e9cd1fb9d99bbb.tar.xz csci415-379c2c17e68d5d471a6a9673b7e9cd1fb9d99bbb.zip |
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.out Binary files differnew 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); +} |