summaryrefslogtreecommitdiff
path: root/pgm2
diff options
context:
space:
mode:
Diffstat (limited to 'pgm2')
-rw-r--r--pgm2/input.txt5
-rwxr-xr-xpgm2/makefile31
-rw-r--r--pgm2/p2test/d1/a.outbin0 -> 10766 bytes
-rw-r--r--pgm2/p2test/d1/f111
-rw-r--r--pgm2/p2test/f11
-rw-r--r--pgm2/p2test/f23
-rw-r--r--pgm2/p2test/f32
-rw-r--r--pgm2/p2test/grepout6
-rw-r--r--pgm2/rgpp.c381
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
new file mode 100644
index 0000000..c1ea1d0
--- /dev/null
+++ b/pgm2/p2test/d1/a.out
Binary files differ
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);
+}