diff --git a/diff-rcm b/diff-rcm index 0f23846..05284d2 100755 Binary files a/diff-rcm and b/diff-rcm differ diff --git a/diff.c b/diff.c index 389d315..4a69f5a 100644 --- a/diff.c +++ b/diff.c @@ -1,3 +1,7 @@ +#include +#include +#include + #include "diff.h" // ========================================================================== // @@ -17,8 +21,11 @@ void printright(const char* right); FILE* openfile(const char* filename, const char* openflags); //char* yesorno(int condition); -void prereq(const char* argv[]); -void end(FILE *fin1, FILE *fin2); +void init(int argc, const char* argv[]); +void setoption(const char* arg, const char* s, const char* t, int* value); +void diff_output_conflict_error(void); + +void loadfiles(const char* filename1, const char* filename2); void version(); void todo(); @@ -26,51 +33,87 @@ void todo(); void quiet(const char* argv[]); void loud(const char* argv[]); int sideside(const char* argv[]); -int normal(const char* argv[]); +int normal(const char* filename1, const char* filename2); -// ========================================================================== // +// ================================================================= // int main(int argc, const char* argv[]) { - if (argc != 3 && (*argv)[0] == '-') { fprintf(stderr, "Usage: ./diff file1 file2\n"); exit(ARGC_ERROR); } - if (argc < 3) { fprintf(stderr, "Usage: ./diff file1 file2\n"); exit(ARGC_ERROR); } - if (argc == 3) { prereq(argv); normal(argv); return 0; } - - while (*++argv) - switch ((*argv)[1]) { - default: break; - case 'v': version(); return 0; // 100% implemented (unless I want to enhance) - case 't': todo(); return 0; // Only for me. To be deprecated later. - case 'q': prereq(argv); quiet(argv); break; // 100% implemented - case 'y': prereq(argv); sideside(argv); break; // 50% implemented - case 'i': printf("i done\n"); break; - case 'c': printf("c done\n"); break; - case 'u': printf("u done\n"); break; - case 's': prereq(argv); loud(argv); break; - } + init(--argc, ++argv); + loadfiles(files[0], files[1]); + if (!showcontext && !showunified && !showsidebyside && !showleftcolumn) { normal(files[0], files[1]); } return 0; } -// ====================================================== // +// =============================================================== // -void prereq(const char* argv[]) { - fin1 = openfile(argv[1], "r"); - fin2 = openfile(argv[2], "r"); +void init(int argc, const char* argv[]) { + int count = 0; + const char* files[2] = { NULL, NULL }; + while (argc-- > 0) { + const char* arg = *argv; + + setoption(arg, "-v", "--version", &showversion); + setoption(arg, "-q", "--brief", &showbrief); + setoption(arg, "-i", "--ignore-case", &ignorecase); + setoption(arg, "-s", "--report-identical-files", &report_identical); + setoption(arg, "--normal", NULL, &diffnormal); + setoption(arg, "-y", "--side-by-side", &showsidebyside); + setoption(arg, "--left-column", NULL, &showleftcolumn); + setoption(arg, "--suppress-common-lines", NULL, &suppresscommon); + setoption(arg, "-c", "--context", &showcontext); + setoption(arg, "-u", "showunified", &showunified); + setoption(arg, "-h", "--help", &showhelp); + + if (arg[0] != '-') { + if (cnt == 2) { + fprintf(stderr, "apologies, this version of diff only handles two files\n"); + fprintf(stderr, "Usage: ./diff [options] file1 file2\n"); + exit(TOOMANYFILES_ERROR); + } else { files[cnt++] = arg; } + } + ++argv; + } + + if (showversion) { version(); exit(0); } + + if (!showcontext && !showunified && + !showsidebyside && !showleftcolumn) { diffnormal = 1; } + + if (((showsidebyside || showleftcolumn) && + (diffnormal || showcontext || showunified)) || + (showcontext && showunified) || (diffnormal && + (showcontext || showunified))) { diff_output_conflict_error(); } +} + +void setoption(const char* arg, const char* s, const char* t, int* value) { + if ((strcmp(arg, s) == 0) || ((t != NULL && strcmp(arg, t) == 0))) { *value = 1; } +} +void diff_output_conflict_error(void) { + + fprintf(stderr, "diff: conflicting output style options\n"); + fprintf(stderr, "diff: Try `diff --help' for more information.)\n"); + exit(CONFLICTING_OUTPUT_OPTIONS); + +} + +void loadfiles(const char* filename1, const char* filename2) { memset(buf, 0, sizeof(buf)); memset(strings1, 0, sizeof(strings1)); memset(strings2, 0, sizeof(strings2)); - while (!feof(fin1) && fgets(buf, BUFLEN, fin1) != NULL) { strings1[count1++] = strdup(buf); } - while (!feof(fin2) && fgets(buf, BUFLEN, fin2) != NULL) { strings2[count2++] = strdup(buf); } + FILE *fin1 = openfile(filename1, "r"); + FILE *fin2 = openfile(filename2, "r"); + + while (!feof(fin1) && fgets(buf, BUFLEN, fin1) != NULL) { strings1[count1++] = strdup(buf); } fclose(fin1); + while (!feof(fin2) && fgets(buf, BUFLEN, fin2) != NULL) { strings2[count2++] = strdup(buf); } fclose(fin2); p = pa_first(strings1, count1); q = pa_first(strings2, count2); -} -void end(FILE* fin1, FILE* fin2) { - fclose(fin1); - fclose(fin2); + + int foundmatch = 0; } void version() { @@ -89,11 +132,11 @@ void todo() { printf("\nTODO: check line by line in a pagraph, using '|' for differences"); printf("\nTODO: this starter code does not yet handle printing all of fin1's pagraphs."); printf("\nTODO: handle the rest of diff's options"); - printf("\nTODO: fix standard printing with no parameters"); - printf("\nTODO: implement multiple types of parameters\n"); + printf("\nTODO: fix standard printing with no pameters"); + printf("\nTODO: implement multiple types of pameters\n"); } -int normal(const char* argv[]) { +int normal(const char* filename1, const char* filename2) { printf("\nTHIS IS NOT NORMAL FOR NOW. THIS IS PLACEHOLDER. MMKAY.\n"); printf("THIS IS NOT NORMAL FOR NOW. THIS IS PLACEHOLDER. MMKAY.\n\n\n"); @@ -197,7 +240,3 @@ FILE* openfile(const char* filename, const char* openflags) { if ((f = fopen(filename, openflags)) == NULL) { printf("can't open '%s'\n", filename); exit(1); } return f; } - -// ============================ LEFTOVERS ============================ // - -// if ((*argv)[0] == '-') diff --git a/diff.h b/diff.h index 7c373f0..d274da6 100644 --- a/diff.h +++ b/diff.h @@ -3,10 +3,14 @@ #include #define ARGC_ERROR 1 -#define BUFLEN 256 -#define MAXSTRINGS 1024 +#define TOOMANYFILES_ERROR 2 +#define CONFLICTING_OUTPUT_OPTIONS 3 -#define HASHLEN 256 +#define MAXSTRINGS 1024 +#define MAXPARAS 4096 + +#define HASHLEN 200 +#define BUFLEN 256 typedef struct pa pa; struct pa { @@ -18,9 +22,19 @@ struct pa { FILE *fin1, *fin2; -int count1 = 0, count2 = 0, equal = 0; +const char* files[2] = { NULL, NULL }; + char buf[BUFLEN]; char *strings1[MAXSTRINGS], *strings2[MAXSTRINGS]; +int showversion = 0, showbrief = 0, ignorecase = 0, report_identical = 0, showsidebyside = 0; +int showleftcolumn = 0, showunified = 0, showcontext = 0, suppresscommon = 0, diffnormal = 0; +int showhelp = 0; + +int equal = 0; + +int cnt = 0; +int count1 = 0, count2 = 0; + pa* p; pa* q; diff --git a/diff_dep.c b/diff_dep.c new file mode 100644 index 0000000..513dd29 --- /dev/null +++ b/diff_dep.c @@ -0,0 +1,25 @@ +int main(int argc, const char* argv[]) { + + //if (argc != 3 && (*argv)[0] == '-') { fprintf(stderr, "Usage: ./diff file1 file2\n"); exit(ARGC_ERROR); } + //if (argc < 3) { fprintf(stderr, "Usage: ./diff file1 file2\n"); exit(ARGC_ERROR); } + //if (argc == 3) { loadfiles(argv); normal(argv); return 0; } + + init(--argc, ++argv); + loadfiles(files[0], files[1]); + if (!showcontext && !showunified && !showsidebyside && !showleftcolumn) { normal(files[0], files[1]); } + + // while (*++argv) + // switch ((*argv)[1]) { + // default: break; + // case 'v': version(); return 0; // 100% implemented (unless I want to enhance) + // case 't': todo(); return 0; // Only for me. To be deprecated later. + // case 'q': loadfiles(argv); quiet(argv); break; // 100% implemented + // case 'y': loadfiles(argv); sideside(argv); break; // 50% implemented + // case 'i': printf("i done\n"); break; + // case 'c': printf("c done\n"); break; + // case 'u': printf("u done\n"); break; + // case 's': loadfiles(argv); loud(argv); break; + // } + + return 0; +} diff --git a/newfiles/__MACOSX/._diff_02.c b/newfiles/__MACOSX/._diff_02.c new file mode 100644 index 0000000..cca5a7d Binary files /dev/null and b/newfiles/__MACOSX/._diff_02.c differ diff --git a/newfiles/__MACOSX/._left.txt b/newfiles/__MACOSX/._left.txt new file mode 100644 index 0000000..21263e9 Binary files /dev/null and b/newfiles/__MACOSX/._left.txt differ diff --git a/newfiles/__MACOSX/._para.c b/newfiles/__MACOSX/._para.c new file mode 100644 index 0000000..cbfd2c1 Binary files /dev/null and b/newfiles/__MACOSX/._para.c differ diff --git a/newfiles/__MACOSX/._para.h b/newfiles/__MACOSX/._para.h new file mode 100644 index 0000000..a459444 Binary files /dev/null and b/newfiles/__MACOSX/._para.h differ diff --git a/newfiles/__MACOSX/._right.txt b/newfiles/__MACOSX/._right.txt new file mode 100644 index 0000000..c24fbbd Binary files /dev/null and b/newfiles/__MACOSX/._right.txt differ diff --git a/newfiles/__MACOSX/._util.c b/newfiles/__MACOSX/._util.c new file mode 100644 index 0000000..84cc988 Binary files /dev/null and b/newfiles/__MACOSX/._util.c differ diff --git a/newfiles/__MACOSX/._util.h b/newfiles/__MACOSX/._util.h new file mode 100644 index 0000000..ec18b79 Binary files /dev/null and b/newfiles/__MACOSX/._util.h differ diff --git a/newfiles/diff_02.c b/newfiles/diff_02.c new file mode 100644 index 0000000..30b0d70 --- /dev/null +++ b/newfiles/diff_02.c @@ -0,0 +1,175 @@ +// +// diff_02.c +// diff +// +// Created by William McCarthy on 4/29/19. +// Copyright © 2019 William McCarthy. All rights reserved. +// + +#include +#include +#include + +#define ARGC_ERROR 1 +#define TOOMANYFILES_ERROR 2 +#define CONFLICTING_OUTPUT_OPTIONS 3 + +#define MAXSTRINGS 1024 +#define MAXPARAS 4096 + +#define HASHLEN 200 + +#include "para.h" +#include "util.h" + + +void version(void) { + printf("\n\n\ndiff (CSUF diffutils) 1.0.0\n"); + printf("Copyright (C) 2014 CSUF\n"); + printf("This program comes with NO WARRANTY, to the extent permitted by law.\n"); + printf("You may redistribute copies of this program\n"); + printf("under the terms of the GNU General Public License.\n"); + printf("For more information about these matters, see the file named COPYING.\n"); + printf("Written by William McCarthy, Tony Stark, and Dr. Steven Strange\n"); +} + +void todo_list(void) { + printf("\n\n\nTODO: check line by line in a paragraph, using '|' for differences"); + printf("\nTODO: this starter code does not yet handle printing all of fin1's paragraphs."); + printf("\nTODO: handle the rest of diff's options\n"); +} + +char buf[BUFLEN]; +char *strings1[MAXSTRINGS], *strings2[MAXSTRINGS]; +int showversion = 0, showbrief = 0, ignorecase = 0, report_identical = 0, showsidebyside = 0; +int showleftcolumn = 0, showunified = 0, showcontext = 0, suppresscommon = 0, diffnormal = 0; + +int count1 = 0, count2 = 0; + + +void loadfiles(const char* filename1, const char* filename2) { + memset(buf, 0, sizeof(buf)); + memset(strings1, 0, sizeof(strings1)); + memset(strings2, 0, sizeof(strings2)); + + FILE *fin1 = openfile(filename1, "r"); + FILE *fin2 = openfile(filename2, "r"); + + while (!feof(fin1) && fgets(buf, BUFLEN, fin1) != NULL) { strings1[count1++] = strdup(buf); } fclose(fin1); + while (!feof(fin2) && fgets(buf, BUFLEN, fin2) != NULL) { strings2[count2++] = strdup(buf); } fclose(fin2); +} + +void print_option(const char* name, int value) { printf("%17s: %s\n", name, yesorno(value)); } + +void diff_output_conflict_error(void) { + fprintf(stderr, "diff: conflicting output style options\n"); + fprintf(stderr, "diff: Try `diff --help' for more information.)\n"); + exit(CONFLICTING_OUTPUT_OPTIONS); +} + +void setoption(const char* arg, const char* s, const char* t, int* value) { + if ((strcmp(arg, s) == 0) || ((t != NULL && strcmp(arg, t) == 0))) { + *value = 1; + } +} + +void showoptions(const char* file1, const char* file2) { + printf("diff options...\n"); + print_option("diffnormal", diffnormal); + print_option("show_version", showversion); + print_option("show_brief", showbrief); + print_option("ignorecase", ignorecase); + print_option("report_identical", report_identical); + print_option("show_sidebyside", showsidebyside); + print_option("show_leftcolumn", showleftcolumn); + print_option("suppresscommon", suppresscommon); + print_option("showcontext", showcontext); + print_option("show_unified", showunified); + + printf("file1: %s, file2: %s\n\n\n", file1, file2); + + printline(); +} + +void init_options_files(int argc, const char* argv[]) { + int cnt = 0; + const char* files[2] = { NULL, NULL }; + + while (argc-- > 0) { + const char* arg = *argv; + setoption(arg, "-v", "--version", &showversion); + setoption(arg, "-q", "--brief", &showbrief); + setoption(arg, "-i", "--ignore-case", &ignorecase); + setoption(arg, "-s", "--report-identical-files", &report_identical); + setoption(arg, "--normal", NULL, &diffnormal); + setoption(arg, "-y", "--side-by-side", &showsidebyside); + setoption(arg, "--left-column", NULL, &showleftcolumn); + setoption(arg, "--suppress-common-lines", NULL, &suppresscommon); + setoption(arg, "-c", "--context", &showcontext); + setoption(arg, "-u", "showunified", &showunified); + if (arg[0] != '-') { + if (cnt == 2) { + fprintf(stderr, "apologies, this version of diff only handles two files\n"); + fprintf(stderr, "Usage: ./diff [options] file1 file2\n"); + exit(TOOMANYFILES_ERROR); + } else { files[cnt++] = arg; } + } + ++argv; // DEBUG only; move increment up to top of switch at release + } + + if (!showcontext && !showunified && !showsidebyside && !showleftcolumn) { + diffnormal = 1; + } + + if (showversion) { version(); exit(0); } + + if (((showsidebyside || showleftcolumn) && (diffnormal || showcontext || showunified)) || + (showcontext && showunified) || (diffnormal && (showcontext || showunified))) { + + diff_output_conflict_error(); + } + +// showoptions(files[0], files[1]); + loadfiles(files[0], files[1]); +} + +int main(int argc, const char * argv[]) { + init_options_files(--argc, ++argv); + +// para_printfile(strings1, count1, printleft); +// para_printfile(strings2, count2, printright); + + para* p = para_first(strings1, count1); + para* q = para_first(strings2, count2); + int foundmatch = 0; + + para* qlast = q; + while (p != NULL) { + qlast = q; + foundmatch = 0; + while (q != NULL && (foundmatch = para_equal(p, q)) == 0) { + q = para_next(q); + } + q = qlast; + + if (foundmatch) { + while ((foundmatch = para_equal(p, q)) == 0) { + para_print(q, printright); + q = para_next(q); + qlast = q; + } + para_print(q, printboth); + p = para_next(p); + q = para_next(q); + } else { + para_print(p, printleft); + p = para_next(p); + } + } + while (q != NULL) { + para_print(q, printright); + q = para_next(q); + } + + return 0; +} diff --git a/newfiles/diff_02.zip b/newfiles/diff_02.zip new file mode 100644 index 0000000..5d47385 Binary files /dev/null and b/newfiles/diff_02.zip differ diff --git a/newfiles/left.txt b/newfiles/left.txt new file mode 100644 index 0000000..bbae935 --- /dev/null +++ b/newfiles/left.txt @@ -0,0 +1,25 @@ +This part of the +document has stayed the +sme from version to +version. It shouldn't +be shown if it doesn't +change. Otherwise, that +would not be helping to +compress the size of the +changes. + +This paragraph contains +text that is outdated. +It will be deleted in the +near future. + +It is important to spell +check this dokument. On +the other hand, a +misspelled word isn't +the end of the world. +Nothing in the rest of +this paragraph needs to +be changed. Things can +be added after it. + diff --git a/newfiles/para.c b/newfiles/para.c new file mode 100644 index 0000000..dd07454 --- /dev/null +++ b/newfiles/para.c @@ -0,0 +1,85 @@ +// +// para.c +// diff +// +// Created by William McCarthy on 5/9/19. +// Copyright © 2019 William McCarthy. All rights reserved. +// + +#include +#include +#include "para.h" +#include "util.h" + +#define BUFLEN 256 + + +para* para_make(char* base[], int filesize, int start, int stop) { + para* p = (para*) malloc(sizeof(para)); + p->base = base; + p->filesize = filesize; + p->start = start; + p->stop = stop; + p->firstline = (p == NULL || start < 0) ? NULL : p->base[start]; + p->secondline = (p == NULL || start < 0 || filesize < 2) ? NULL : p->base[start + 1]; + + return p; +} + +para* para_first(char* base[], int size) { + para* p = para_make(base, size, 0, -1); + return para_next(p); +} + +void para_destroy(para* p) { free(p); } + +para* para_next(para* p) { + if (p == NULL || p->stop == p->filesize) { return NULL; } + + int i; + para* pnew = para_make(p->base, p->filesize, p->stop + 1, p->stop + 1); + for (i = pnew->start; i < p->filesize && strcmp(p->base[i], "\n") != 0; ++i) { } + pnew->stop = i; + + if (pnew->start >= p->filesize) { + free(pnew); + pnew = NULL; + } + return pnew; +} +size_t para_filesize(para* p) { return p == NULL ? 0 : p->filesize; } + +size_t para_size(para* p) { return p == NULL || p->stop < p->start ? 0 : p->stop - p->start + 1; } + +char** para_base(para* p) { return p->base; } + +char* para_info(para* p) { + static char buf[BUFLEN]; // static for a reason + snprintf(buf, sizeof(buf), "base: %p, filesize: %d, start: %d, stop: %d\n", + p->base, p->filesize, p->start, p->stop); + return buf; // buf MUST be static +} + +int para_equal(para* p, para* q) { + if (p == NULL || q == NULL) { return 0; } + if (para_size(p) != para_size(q)) { return 0; } + if (p->start >= p->filesize || q->start >= q->filesize) { return 0; } + int i = p->start, j = q->start, equal = 0; + while ((equal = strcmp(p->base[i], q->base[i])) == 0) { ++i; ++j; } + return 1; +} + +void para_print(para* p, void (*fp)(const char*)) { + if (p == NULL) { return; } + for (int i = p->start; i <= p->stop && i != p->filesize; ++i) { fp(p->base[i]); } +} + +void para_printfile(char* base[], int count, void (*fp)(const char*)) { + para* p = para_first(base, count); + while (p != NULL) { + para_print(p, fp); + p = para_next(p); + } + printline(); +} + diff --git a/newfiles/para.h b/newfiles/para.h new file mode 100644 index 0000000..e54444c --- /dev/null +++ b/newfiles/para.h @@ -0,0 +1,36 @@ +// +// para.h +// diff +// +// Created by William McCarthy on 5/9/19. +// Copyright © 2019 William McCarthy. All rights reserved. +// + +#ifndef para_h +#define para_h + +#include + +typedef struct para para; +struct para { + char** base; + int filesize; + int start; + int stop; + char* firstline; // DEBUG only + char* secondline; +}; + +para* para_make(char* base[], int size, int start, int stop); +para* para_first(char* base[], int size); +para* para_next(para* p); +size_t para_filesize(para* p); +size_t para_size(para* p); +char** para_base(para* p); +char* para_info(para* p); +int para_equal(para* p, para* q); +void para_print(para* p, void (*fp)(const char*)); +void para_printfile(char* base[], int count, void (*fp)(const char*)); + + +#endif /* para_h */ diff --git a/newfiles/right.txt b/newfiles/right.txt new file mode 100644 index 0000000..2d7f33d --- /dev/null +++ b/newfiles/right.txt @@ -0,0 +1,31 @@ +This is an important +notice! It should +therefore be located at +the beginning of this +document! + +This part of the +document has stayed the +sme from version to +version. It shouldn't +be shown if it doesn't +change. Otherwise, that +would not be helping to +compress the size of the +changes. + +It is important to spell +check this document. On +the other hand, a +misspelled word isn't +the end of the world. +Nothing in the rest of +this paragraph needs to +be changed. Things can +be added after it. + +This pragraph contains +important new additions +to this document. + + diff --git a/newfiles/util.c b/newfiles/util.c new file mode 100644 index 0000000..2c4b9f1 --- /dev/null +++ b/newfiles/util.c @@ -0,0 +1,53 @@ +// +// util.c +// diff +// +// Created by William McCarthy on 5/9/19. +// Copyright © 2019 William McCarthy. All rights reserved. +// + +#include +#include +#include "util.h" + +#define BUFLEN 256 + + +char* yesorno(int condition) { return condition == 0 ? "no" : "YES"; } + +FILE* openfile(const char* filename, const char* openflags) { + FILE* f; + if ((f = fopen(filename, openflags)) == NULL) { printf("can't open '%s'\n", filename); exit(1); } + return f; +} + +void printline(void) { + for (int i = 0; i < 10; ++i) { printf("=========="); } + printf("\n"); +} + + +void printleft(const char* left) { + char buf[BUFLEN]; + + strcpy(buf, left); + int j = 0, len = (int)strlen(buf) - 1; + for (j = 0; j <= 48 - len ; ++j) { buf[len + j] = ' '; } + buf[len + j++] = '<'; + buf[len + j++] = '\0'; + printf("%s\n", buf); +} + +void printright(const char* right) { + if (right == NULL) { return; } + printf("%50s %s", ">", right); +} + +void printboth(const char* left_right) { + char buf[BUFLEN]; + size_t len = strlen(left_right); + if (len > 0) { strncpy(buf, left_right, len); } + buf[len - 1] = '\0'; + printf("%-50s %s", buf, left_right); +} + diff --git a/newfiles/util.h b/newfiles/util.h new file mode 100644 index 0000000..6ff3302 --- /dev/null +++ b/newfiles/util.h @@ -0,0 +1,24 @@ +// +// util.h +// diff +// +// Created by William McCarthy on 5/9/19. +// Copyright © 2019 William McCarthy. All rights reserved. +// + +#ifndef util_h +#define util_h + +#include +#define BUFLEN 256 + +char* yesorno(int condition); +FILE* openfile(const char* filename, const char* openflags); + +void printleft(const char* left); +void printright(const char* right); +void printboth(const char* left_right); + +void printline(void); + +#endif /* util_h */