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/rgpp.c | |
download | csci415-master.tar.xz csci415-master.zip |
Diffstat (limited to 'pgm2/rgpp.c')
-rw-r--r-- | pgm2/rgpp.c | 381 |
1 files changed, 381 insertions, 0 deletions
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); +} |