From 99327046d40658068460e07d9a52c6fac01ccc23 Mon Sep 17 00:00:00 2001 From: Emil Date: Wed, 16 Aug 2023 00:08:15 -0600 Subject: [PATCH] Improved CLI --- src/main.c | 477 +++++++++++++++++++++++++++++--------------------- tests/extra.c | 4 + tests/main.c | 1 + 3 files changed, 283 insertions(+), 199 deletions(-) create mode 100644 tests/extra.c diff --git a/src/main.c b/src/main.c index 90e0f2d..d0a6b2a 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,10 @@ #define ALLOCATION_CHUNK (1024UL) #define ALLOCATION_LIMIT (1024UL * 1024UL) +#ifndef PROGN +# define PROGN "hl" +#endif + enum { NORMAL, BOLD, DARKNESS, ITALIC, UNDERLINE, BLINK, DUNNO_6, REVERSE, INVISIBLE }; enum { GREY, RED, GREEN, YELLOW, BLUE, PINK, CYAN, WHITE, CANCEL }; @@ -30,281 +34,356 @@ static int effect_keyword = BOLD; static int effect_preprocessor = BOLD; static int effect_default = BOLD; -static char * buffer = NULL; - static unsigned long int buffer_size = 0; static void render_character ( - char character + char character ) { - putchar (character); + putchar (character); } static void render_string ( - char * string + char * string ) { - while (* string) render_character (* string++); + while (* string) render_character (* string++); } static void render_colour ( - int colour, - int effect + int colour, + int effect ) { - if (colour == CANCEL) { - render_string ("\033[0m"); - return; - } - - render_string ("\033["); - render_character ((char) (effect % 9) + '0'); - render_string (";3"); - render_character ((char) (colour % 8) + '0'); - render_character ('m'); + if (colour == CANCEL) { + render_string ("\033[0m"); + return; + } + + render_string ("\033["); + render_character ((char) (effect % 9) + '0'); + render_string (";3"); + render_character ((char) (colour % 8) + '0'); + render_character ('m'); } static int is_space ( - char character + char character ) { - if ((character == ' ') || (character == '\t') || (character == '\r') || (character == '\n')) { - return (1); - } else { - return (0); - } + switch (character) + { + case ' ': case '\t': case '\r': case '\n': + return (1); + default: + return (0); + } } static int is_separator ( - char character + char character ) { - if ((character == ' ') || (character == '\t') || (character == '\r') || (character == '\n') || - (character == '+') || (character == '-') || (character == '*') || (character == '/') || - (character == '(') || (character == ')') || (character == '[') || (character == ']') || - (character == '{') || (character == '}') || (character == '<') || (character == '>') || - (character == ';') || (character == ':') || (character == ',') || (character == '.') || - (character == '!') || (character == '&') || (character == '|') || (character == '?') || - (character == '~') || (character == '^') || (character == '%') || (character == '=')) { - return (1); - } else { - return (0); - } + switch (character) + { + case ' ': case '\t': case '\r': case '\n': + case '+': case '-': case '*': case '/': + case '(': case ')': case '[': case ']': + case '{': case '}': case '<': case '>': + case ';': case ':': case ',': case '.': + case '!': case '&': case '|': case '?': + case '~': case '^': case '%': case '=': + return (1); + default: + return (0); + } } static int compare_multiple_strings ( - char * string, - const char * * strings, - const int count + char * string, + const char ** strings, + const int count ) { - int i = 0; + int i = 0; - do { - if (strcmp (string, strings [i]) == 0) { - return (1); - } - ++i; - } while (i != count); + do { + if (strcmp (string, strings [i]) == 0) { + return (1); + } + ++i; + } while (i != count); - return (0); + return (0); } static int render_short_comment ( - int data_offset + char * buffer, + int data_offset ) { - render_colour (colour_short_comment, effect_short_comment); + render_colour (colour_short_comment, effect_short_comment); - do { - render_character (buffer [data_offset]); - ++data_offset; - } while ((buffer [data_offset] != '\n') && (buffer [data_offset] != '\0')); + do { + render_character (buffer [data_offset]); + ++data_offset; + } while ((buffer [data_offset] != '\n') && (buffer [data_offset] != '\0')); - render_character (buffer [data_offset]); - ++data_offset; + render_character (buffer [data_offset]); + ++data_offset; - return (data_offset); + return (data_offset); } static int render_long_comment ( - int data_offset + char * buffer, + int data_offset ) { - render_colour (colour_long_comment, effect_long_comment); + render_colour (colour_long_comment, effect_long_comment); - do { - render_character (buffer [data_offset]); - ++data_offset; - } while (((buffer [data_offset] != '/') || - (buffer [data_offset - 1] != '*')) && - (buffer [data_offset] != '\0')); + do { + render_character (buffer [data_offset]); + ++data_offset; + } while (((buffer [data_offset] != '/') || + (buffer [data_offset - 1] != '*')) && + (buffer [data_offset] != '\0')); - render_character (buffer [data_offset]); - ++data_offset; + render_character (buffer [data_offset]); + ++data_offset; - return (data_offset); + return (data_offset); } static int render_short_string ( - int data_offset + char * buffer, + int data_offset ) { - render_colour (colour_short_string, effect_short_string); + render_colour (colour_short_string, effect_short_string); - do { - render_character (buffer [data_offset]); - ++data_offset; - if (buffer [data_offset - 1] == '\\') { - render_character (buffer [data_offset]); - ++data_offset; - } - } while ((buffer [data_offset] != '\'') && (buffer [data_offset] != '\0')); + do { + render_character (buffer [data_offset]); + ++data_offset; + if (buffer [data_offset - 1] == '\\') { + render_character (buffer [data_offset]); + ++data_offset; + } + } while ((buffer [data_offset] != '\'') && (buffer [data_offset] != '\0')); - render_character (buffer [data_offset]); - ++data_offset; + render_character (buffer [data_offset]); + ++data_offset; - return (data_offset); + return (data_offset); } static int render_long_string ( - int data_offset + char * buffer, + int data_offset ) { - render_colour (colour_long_string, effect_long_string); + render_colour (colour_long_string, effect_long_string); - do { - render_character (buffer [data_offset]); - ++data_offset; - if (buffer [data_offset - 1] == '\\') { - render_character (buffer [data_offset]); - ++data_offset; - } - } while ((buffer [data_offset] != '"') && (buffer [data_offset] != '\0')); + do { + render_character (buffer [data_offset]); + ++data_offset; + if (buffer [data_offset - 1] == '\\') { + render_character (buffer [data_offset]); + ++data_offset; + } + } while ((buffer [data_offset] != '"') && (buffer [data_offset] != '\0')); - render_character (buffer [data_offset]); - ++data_offset; + render_character (buffer [data_offset]); + ++data_offset; - return (data_offset); + return (data_offset); } static int render_separator ( - int data_offset + char * buffer, + int data_offset ) { - if (is_space (buffer [data_offset]) != 0) { - render_colour (WHITE, NORMAL); - } else { - render_colour (colour_separator, effect_separator); - } + if (is_space (buffer [data_offset]) != 0) { + render_colour (WHITE, NORMAL); + } else { + render_colour (colour_separator, effect_separator); + } - render_character (buffer [data_offset]); - ++data_offset; + render_character (buffer [data_offset]); + ++data_offset; - return (data_offset); + return (data_offset); } static int render_number ( - int data_offset + char * buffer, + int data_offset ) { - render_colour (colour_number, effect_number); + render_colour (colour_number, effect_number); - do { - render_character (buffer [data_offset]); - ++data_offset; - } while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); + do { + render_character (buffer [data_offset]); + ++data_offset; + } while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); - return (data_offset); + return (data_offset); } static int render_word ( - int data_offset + char * buffer, + int data_offset +) { + const char * c_keywords [32] = { + "register", "volatile", "auto", "const", "static", "extern", "if", "else", + "do", "while", "for", "continue", "switch", "case", "default", "break", + "enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof", + "char", "short", "int", "long", "signed", "unsigned", "float", "double" + }; + + const char * preprocessor_keywords [16] = { + "#include", "#pragma", "#define", "#undef", "#ifdef", "#ifndef", "#elifdef", "#elifndef", + "#if", "#elif", "#else", "#endif", "#embed", "#line", "#error", "#warning" + }; + + char * word = NULL; + + int i = 0; + + do { + word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); + word [i] = buffer [data_offset + i]; + ++i; + } while ((is_separator (buffer [data_offset + i]) == 0) && (buffer [data_offset + i] != '\0')); + + word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); + word [i] = '\0'; + + if (compare_multiple_strings (word, c_keywords, 32) != 0) { + render_colour (colour_keyword, effect_keyword); + } else if (compare_multiple_strings (word, preprocessor_keywords, 16) != 0) { + render_colour (colour_preprocessor, effect_preprocessor); + } else { + render_colour (colour_default, effect_default); + } + + do { + render_character (buffer [data_offset]); + ++data_offset; + } while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); + + free (word); + + return (data_offset); +} + +void +handle_buffer( + char * buffer ) { - const char * c_keywords [32] = { - "register", "volatile", "auto", "const", "static", "extern", "if", "else", - "do", "while", "for", "continue", "switch", "case", "default", "break", - "enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof", - "char", "short", "int", "long", "signed", "unsigned", "float", "double" - }; - - const char * preprocessor_keywords [16] = { - "#include", "#pragma", "#define", "#undef", "#ifdef", "#ifndef", "#elifdef", "#elifndef", - "#if", "#elif", "#else", "#endif", "#embed", "#line", "#error", "#warning" - }; - - char * word = NULL; - - int i = 0; - - do { - word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); - word [i] = buffer [data_offset + i]; - ++i; - } while ((is_separator (buffer [data_offset + i]) == 0) && (buffer [data_offset + i] != '\0')); - - word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); - word [i] = '\0'; - - if (compare_multiple_strings (word, c_keywords, 32) != 0) { - render_colour (colour_keyword, effect_keyword); - } else if (compare_multiple_strings (word, preprocessor_keywords, 16) != 0) { - render_colour (colour_preprocessor, effect_preprocessor); - } else { - render_colour (colour_default, effect_default); - } - - do { - render_character (buffer [data_offset]); - ++data_offset; - } while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); - - free (word); - - return (data_offset); + int offset = 0; + while (buffer [offset] != '\0') { + if ((buffer [offset] == '/') && (buffer [offset + 1] == '/')) { + offset = render_short_comment (buffer, offset); + } else if ((buffer [offset] == '/') && (buffer [offset + 1] == '*')) { + offset = render_long_comment (buffer, offset); + } else if (buffer [offset] == '\'') { + offset = render_short_string (buffer, offset); + } else if (buffer [offset] == '"') { + offset = render_long_string (buffer, offset); + } else if (is_separator (buffer [offset]) != 0) { + offset = render_separator (buffer, offset); + } else if ((buffer [offset] >= '0') && (buffer [offset] <= '9')) { + offset = render_number (buffer, offset); + } else { + offset = render_word (buffer, offset); + } + render_colour (CANCEL, NORMAL); + } } + +static char * +slurp(const char * fn) +{ + size_t len; + char * b; + FILE * fp = fopen(fn, "r"); + if (fp) + { + fseek(fp, 0, SEEK_END); + len = ftell(fp); + rewind(fp); + b = malloc(len); + if (b && + len != fread(b, 1, len, fp)) + { perror(PROGN); } + fclose(fp); + return b; + } + else + { return NULL; } +} + +#define OPT(c,s) \ + if ((c == argv[0][0] && argv[0][1] == '\0') || \ + 0 == strncmp(argv[0], s, strlen(s))) + +#define SOPT(s) \ + if (0 == strncmp(argv[0], s, strlen(s))) + /* Valgrind: Depends on uninitialized value (buffer [0])...? 280 : } while ((buffer [buffer_size - 1] != '\0') || (buffer_size != ALLOCATION_LIMIT)); 285 : while (buffer [offset] != '\0') { */ int main ( - int argc, - char * * argv + int argc, + char ** argv ) { - int offset = 0; - - if (argc != 1) { - (void) argv; - puts ("ARGUMENTS \"Heyo world!\""); - return (-1); - } - - buffer = realloc (buffer, ALLOCATION_CHUNK); - - do { - if ((buffer_size + 1) % ALLOCATION_CHUNK == 0) { - buffer = realloc (buffer, ((buffer_size + 1) / ALLOCATION_CHUNK + 1) * ALLOCATION_CHUNK); - } - buffer [buffer_size] = '\0'; /* Fixing Valgrind warnings... */ - read (STDIN_FILENO, & buffer [buffer_size], sizeof (* buffer)); - ++buffer_size; - } while ((buffer [buffer_size - 1] != '\0') /*|| (buffer_size != ALLOCATION_LIMIT)*/); - - buffer [buffer_size - 1] = '\0'; - - /* Checking if long comments work... */ - // Checking if short comments work... - - while (buffer [offset] != '\0') { - if ((buffer [offset] == '/') && (buffer [offset + 1] == '/')) { - offset = render_short_comment (offset); - } else if ((buffer [offset] == '/') && (buffer [offset + 1] == '*')) { - offset = render_long_comment (offset); - } else if (buffer [offset] == '\'') { - offset = render_short_string (offset); - } else if (buffer [offset] == '"') { - offset = render_long_string (offset); - } else if (is_separator (buffer [offset]) != 0) { - offset = render_separator (offset); - } else if ((buffer [offset] >= '0') && (buffer [offset] <= '9')) { - offset = render_number (offset); - } else { - offset = render_word (offset); - } - render_colour (CANCEL, NORMAL); - } - - free (buffer); - - return (0); + char * buffer = NULL; + + if (argc != 1) { + (void) argv; + while (++argv, --argc) { + if (argv[0][0] == '-') { + argv[0]++; + OPT ('?',"help") { + fprintf (stderr, PROGN ": ... | hl [OPTIONS] FILES ...\n"); + return (0); + } + SOPT ("version") { + fprintf(stderr, PROGN ": Version 9000\n"); + return (0); + } + else { + fprintf (stderr, PROGN ": Unrecognized option '%s'\n", argv [0]); + return (1); + } + } else { + if ((buffer = slurp (argv [0]))) { + handle_buffer (buffer); + free (buffer); + } + } + } + } + + buffer = realloc (buffer, ALLOCATION_CHUNK); + +#define MEMFAIL(v) if (v == NULL) { perror(PROGN); return (1); } + MEMFAIL(buffer); + + do { + if ((buffer_size + 1) % ALLOCATION_CHUNK == 0) { + buffer = realloc (buffer, + ((buffer_size + 1) + / ALLOCATION_CHUNK + 1) + * ALLOCATION_CHUNK); + MEMFAIL(buffer); + } + buffer [buffer_size] = '\0'; /* Fixing Valgrind warnings... */ + read (STDIN_FILENO, & buffer [buffer_size], sizeof (* buffer)); + ++buffer_size; + } while ((buffer [buffer_size - 1] != '\0') /*|| + (buffer_size != ALLOCATION_LIMIT)*/); + + buffer [buffer_size - 1] = '\0'; + + // Checking if short comments work... + /* Checking if long comments work... */ + + handle_buffer(buffer); + + free (buffer); + + return (0); } diff --git a/tests/extra.c b/tests/extra.c new file mode 100644 index 0000000..6905cce --- /dev/null +++ b/tests/extra.c @@ -0,0 +1,4 @@ +int +main(void) + +{nothing.} diff --git a/tests/main.c b/tests/main.c index f599c2b..0efd417 100644 --- a/tests/main.c +++ b/tests/main.c @@ -319,3 +319,4 @@ signed main(){ return 0; } + -- 2.39.5