diff --git a/Makefile b/Makefile index 788f0ef..ad91fa5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,13 @@ -defualt: all +defualt: build -all: - gcc -O2 morse.c -o morse +morse.o: + gcc -O2 morse.c -c -o morse.o + +build: morse.o + gcc -O2 morse.o main.c -o morse + +tests: morse.o + gcc -O2 test.c morse.o -o test install: cp morse ~/.local/bin/ @@ -10,4 +16,7 @@ uninstll: rm ~/.local/bin/morse clean: - rm morse + rm morse || echo "No file 'morse' to delete" + rm *out || echo "No \*.out files to delete" + rm *o || echo "No \*.o files to delete" + rm test || echo "No file 'test' to delete" diff --git a/main.c b/main.c new file mode 100644 index 0000000..891f417 --- /dev/null +++ b/main.c @@ -0,0 +1,88 @@ +#include "morse.h" +#include +#include +#include + +const long DEFAULT_DASH_PAUSE = 300000; +const long DEFAULT_DOT_PAUSE = 150000; + +int main(int argc, char *argv[]){ + long dash_delay = DEFAULT_DASH_PAUSE; + long dot_delay = DEFAULT_DOT_PAUSE; + + bool addLetterBeforeMorse = false; + bool isSlow = false; + bool convertFromMorse = false; + + size_t buflen = 0; + ssize_t lengthOfInputString; + + for (int argi = 0; argi < argc; argi++){ + char* arg = argv[argi]; + if (strcmp(arg, "--slow") == 0 || strcmp(arg, "-s") == 0){ + isSlow = true; + } else if (strcmp(arg, "--verbose") == 0 || strcmp(arg, "-v") == 0){ + addLetterBeforeMorse = true; + } else if (strcmp(arg, "--reverse") == 0 || strcmp(arg, "-x") == 0){ + convertFromMorse = true; + } else if (strcmp(arg, "--dash-delay") == 0 || strcmp(arg, "-hd") == 0){ + if (argc > argi+1){ + dash_delay = strtol(argv[argi+1], NULL, 10); + } else { + printf("No --dash-delay argument provided.\nIgnoring!\n"); + } + } else if (strcmp(arg, "--dot-delay") == 0 || strcmp(arg, "-td") == 0){ + if (argc > argi+1){ + dot_delay = strtol(argv[argi+1], NULL, 10); + } else { + printf("Not --dot-delay argument provited.\nIgnoring!\n"); + } + } + } + + if (convertFromMorse){ + char* inputString; + char* wordToken; + char* letterToken; + // for every line in the input, until the end of file + while ((getline(&inputString, &buflen, stdin))!=EOF){ + // find the next double space (produces in this program by default when outputting morse code) + wordToken = multi_tok(inputString, " "); + // While there is another block of text after a double space + while (wordToken){ + // find the next space or newline (newlines are not consumed by the getline function) + letterToken = strtok(wordToken, " \n"); + // while there is another block of text after a space (a newline will not have text after it, as we're using getline) + while (letterToken){ + // convert morse to ascii + reverse_morse(letterToken); + // set letterToken to new string after NEXT space/newline + letterToken = strtok(NULL, " \n"); + } + // set word token (all the characters that make up a word in morse) to the next block after a double space + wordToken = multi_tok(NULL, " "); + // this puts a space after every morse converted character. + // because strtok consumes the space it is not printed, or passed around + printf(" "); + } + // add a newline for every line consumed by getline + printf("\n"); + // force-flush the input buffer just in case the user is in interactive mode + fflush(stdin); + } + } else { + char* inputString; + // for each line of input + while ((getline(&inputString, &buflen, stdin))!=EOF){ + // print the morse code of the line + // by default it is passthrough, meaning any non [a-zA-Z0-9] characters are printed as they are. + // the only exception is dashes and dots, which are removed from the ouptut to avoid confusing the input veriosn of the program + print_morse(inputString, isSlow, addLetterBeforeMorse, dot_delay, dash_delay); + // add a newline becuase it will not be printed otherwise + printf("\n"); + // force flush the buffer incase user is in interactive mode + fflush(stdin); + } + } + return 0; +} diff --git a/minunit.h b/minunit.h new file mode 100644 index 0000000..55318b7 --- /dev/null +++ b/minunit.h @@ -0,0 +1,9 @@ + /* file: minunit.h */ +#include + #define mu_assert_str(function_name, input, output) do{ char* result = function_name(input);tests_run++; if (!(strcmp(result, output)==0)){printf("[FAILED] ");tests_failed++;}else{printf("[PASSED] ");tests_passed++;}; printf("%s(\"%s\"): \"%s\" == \"%s\"\n", function_name, input, result, output); } while (0) + #define mu_assert(message, test) do { if (!(test)) return message; } while (0) + + #define mu_assert_neg(message, test) do { if ((test)){tests_failed++;return message;} else {tests_passed++;} } while (0) + #define mu_run_test(test) do { char *message = test(); tests_run++; \ + if (message) return message; } while (0) + extern int tests_run; diff --git a/morse.c b/morse.c index 7967280..69b112d 100644 --- a/morse.c +++ b/morse.c @@ -1,23 +1,41 @@ +#include "morse.h" #include #include #include #include -#include #include #include #define NUM_OF_LETTERS 36 -const long DEFAULT_DASH_PAUSE = 300000; -const long DEFAULT_DOT_PAUSE = 150000; - static char LOWERCASE_LETTERS[NUM_OF_LETTERS] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; -static char UPPERCASE_LETTERS[NUM_OF_LETTERS] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; +static char UPPERCASE_LETTERS[NUM_OF_LETTERS] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; // 6 spaces are needed to store the null terminator :) // C is fun? static char MORSE[NUM_OF_LETTERS][6] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", "-----"}; +char* char_to_morse(char letter){ + char result[6]; + for (int i = 0; i < NUM_OF_LETTERS; i++){ + if (letter == UPPERCASE_LETTERS[i] || letter == LOWERCASE_LETTERS[i]){ + strcpy(&result, MORSE[i]); + //result = MORSE[i]; + } + } + return result; +} + +char * to_morse(char* string){ + int string_len = strlen(string); + // worse possible case is 6 times the length (assuming all numbers) + char* result; + for (int i = 0; i < strlen(string); i++){ + strcat(result, char_to_morse(string[i])); + } + return result; +} + char *multi_tok(char *input, char *delimiter) { static char *string; if (input != NULL) @@ -116,84 +134,3 @@ void reverse_morse(char* morseToNormalize){ printf("%s", morseToNormalize); } } - -int main(int argc, char *argv[]){ - long dash_delay = DEFAULT_DASH_PAUSE; - long dot_delay = DEFAULT_DOT_PAUSE; - - bool addLetterBeforeMorse = false; - bool isSlow = false; - bool convertFromMorse = false; - - size_t buflen = 0; - ssize_t lengthOfInputString; - - for (int argi = 0; argi < argc; argi++){ - char* arg = argv[argi]; - if (strcmp(arg, "--slow") == 0 || strcmp(arg, "-s") == 0){ - isSlow = true; - } else if (strcmp(arg, "--verbose") == 0 || strcmp(arg, "-v") == 0){ - addLetterBeforeMorse = true; - } else if (strcmp(arg, "--reverse") == 0 || strcmp(arg, "-x") == 0){ - convertFromMorse = true; - } else if (strcmp(arg, "--dash-delay") == 0 || strcmp(arg, "-hd") == 0){ - if (argc > argi+1){ - dash_delay = strtol(argv[argi+1], NULL, 10); - } else { - printf("No --dash-delay argument provided.\nIgnoring!\n"); - } - } else if (strcmp(arg, "--dot-delay") == 0 || strcmp(arg, "-td") == 0){ - if (argc > argi+1){ - dot_delay = strtol(argv[argi+1], NULL, 10); - } else { - printf("Not --dot-delay argument provited.\nIgnoring!\n"); - } - } - } - - if (convertFromMorse){ - char* inputString; - char* wordToken; - char* letterToken; - // for every line in the input, until the end of file - while ((getline(&inputString, &buflen, stdin))!=EOF){ - // find the next double space (produces in this program by default when outputting morse code) - wordToken = multi_tok(inputString, " "); - // While there is another block of text after a double space - while (wordToken){ - // find the next space or newline (newlines are not consumed by the getline function) - letterToken = strtok(wordToken, " \n"); - // while there is another block of text after a space (a newline will not have text after it, as we're using getline) - while (letterToken){ - // convert morse to ascii - reverse_morse(letterToken); - // set letterToken to new string after NEXT space/newline - letterToken = strtok(NULL, " \n"); - } - // set word token (all the characters that make up a word in morse) to the next block after a double space - wordToken = multi_tok(NULL, " "); - // this puts a space after every morse converted character. - // because strtok consumes the space it is not printed, or passed around - printf(" "); - } - // add a newline for every line consumed by getline - printf("\n"); - // force-flush the input buffer just in case the user is in interactive mode - fflush(stdin); - } - } else { - char* inputString; - // for each line of input - while ((getline(&inputString, &buflen, stdin))!=EOF){ - // print the morse code of the line - // by default it is passthrough, meaning any non [a-zA-Z0-9] characters are printed as they are. - // the only exception is dashes and dots, which are removed from the ouptut to avoid confusing the input veriosn of the program - print_morse(inputString, isSlow, addLetterBeforeMorse, dot_delay, dash_delay); - // add a newline becuase it will not be printed otherwise - printf("\n"); - // force flush the buffer incase user is in interactive mode - fflush(stdin); - } - } - return 0; -} diff --git a/morse.h b/morse.h new file mode 100644 index 0000000..21fa125 --- /dev/null +++ b/morse.h @@ -0,0 +1,9 @@ +#include + +char * char_to_morse(char letter); +char * to_morse(char* string); +char * from_morse(char* string); + +void print_morse(char* string, bool b1, bool b2, long s1, long s2); +void reverse_morse(char* string); +char *multi_tok(char *input, char *delimiter); diff --git a/test.c b/test.c new file mode 100644 index 0000000..99289de --- /dev/null +++ b/test.c @@ -0,0 +1,74 @@ +#include +#include "minunit.h" +#include "morse.h" + +int tests_run = 0; +int tests_passed = 0; +int tests_failed = 0; + +static char * test_tests1(){ + mu_assert("Error, - != -", "-" == "-"); + return 0; +} + +static char * test_tests2(){ + mu_assert_neg("Error, - == .", "-" == "."); + return 0; +} + +static char * test_to_morse(){ + char_to_morse('a'); + printf("trying to run ctm\n"); + char* r1; + r1 = char_to_morse('a'); + printf("ctm('a') works!"); + mu_assert_str(char_to_morse, 'a', ".-"); + mu_assert_str(char_to_morse, 'b', "-..."); + mu_assert_str(char_to_morse, 'c', "-.-."); + mu_assert_str(char_to_morse, 'd', "-.."); + mu_assert_str(char_to_morse, 'e', "."); + mu_assert_str(char_to_morse, 'f', "..-."); + mu_assert_str(char_to_morse, 'g', "--."); + mu_assert_str(char_to_morse, 'h', "...."); + mu_assert_str(char_to_morse, 'i', ".."); + mu_assert_str(char_to_morse, 'j', ".---"); + mu_assert_str(char_to_morse, 'k', "-.-"); + mu_assert_str(char_to_morse, 'l', ".-.."); + mu_assert_str(char_to_morse, 'm', "--"); + mu_assert_str(char_to_morse, 'n', "-."); + mu_assert_str(char_to_morse, 'o', "---"); + mu_assert_str(char_to_morse, 'p', ".--."); + mu_assert_str(char_to_morse, 'q', "--.-"); + mu_assert_str(char_to_morse, 'r', ".-."); + mu_assert_str(char_to_morse, 's', "..."); + mu_assert_str(char_to_morse, 't', "-"); + mu_assert_str(char_to_morse, 'u', "..-"); + mu_assert_str(char_to_morse, 'v', "...-"); + mu_assert_str(char_to_morse, 'w', ".--"); + mu_assert_str(char_to_morse, 'x', "-..-"); + mu_assert_str(char_to_morse, 'y', "-.--"); + mu_assert_str(char_to_morse, 'z', "--.."); + return 0; +} + +static char * all_tests(){ + mu_run_test(test_tests1); + printf("test_tests1 complete!\n"); + mu_run_test(test_tests2); + printf("test_tests2 complete!\n"); + mu_run_test(test_to_morse); + printf("test_to_morse complete!\n"); + return 0; +} + +int main(int argc, char **argv) { + char *result = all_tests(); + if (tests_run == tests_passed){ + printf("ALL TESTS PASSED\n"); + } + printf("Tests run: %d\n", tests_run); + printf("Tests passed: %d\n", tests_passed); + printf("Tests failed: %d\n", tests_failed); + return 0; +} +