/* Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic Xighlight is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. */ #include #include static int highlighted = 0; static void echo_version (void) { echo ("xighlight: Terminal syntax highlighter (version 144000)\n"); } static void echo_license (void) { echo ("xighlight: Terminal syntax highlighter (GNU general public license version 3)\n"); } static void highlight_common (void) { /* Should be changed to support basic GCC, Clang, Valgrind and Splint output... */ char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; if (highlighted != 0) { syntax_delete (); } syntax_define_separators (separators); syntax_define_default (COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD); syntax_define_range ("'", "'", '\\', COLOUR_PINK, EFFECT_BOLD); syntax_define_range ("`", "'", '\\', COLOUR_PINK, EFFECT_BOLD); syntax_define_operators (".,:;<=>+*-/%!&~^?|()[]{}", COLOUR_BLUE, EFFECT_BOLD); (void) syntax_insert (1, 1, "abcdefghijklmnopqrstuvwxyz", syntax_separator, '\0', COLOUR_WHITE, EFFECT_NORMAL); (void) syntax_insert (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", syntax_separator, '\0', COLOUR_WHITE, EFFECT_BOLD); (void) syntax_insert (1, 1, "_", syntax_separator, '\0', COLOUR_PINK, EFFECT_BOLD); highlighted = 1; } static void highlight_c (void) { char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; char * 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" }; if (highlighted != 0) { syntax_delete (); } syntax_define_separators (separators); syntax_define_default (COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD); syntax_define_range ("/*", "*/", '\0', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("//", "\n", '\0', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("#", "\n", '\\', COLOUR_PINK, EFFECT_NORMAL); syntax_define_range ("'", "'", '\\', COLOUR_PINK, EFFECT_BOLD); syntax_define_operators (".,:;<=>+*-/%!&~^?|()[]{}", COLOUR_BLUE, EFFECT_BOLD); syntax_define_words (1, keywords, 32, COLOUR_BLUE, EFFECT_NORMAL); highlighted = 1; } static void highlight_ada (void) { char * separators = ".,:;<=>+-*/&|()\" \t\r\n"; char * keywords [73] = { "abort", "else", "new", "return", "abs", "elsif", "not", "reverse", "abstract", "end", "null", "accept", "entry", "select", "access", "of", "separate", "aliased", "exit", "or", "some", "all", "others", "subtype", "and", "for", "out", "array", "function", "at", "tagged", "generic", "package", "task", "begin", "goto", "pragma", "body", "private", "then", "type", "case", "in", "constant", "until", "is", "raise", "use", "if", "declare", "range", "delay", "limited", "record", "when", "delta", "loop", "rem", "while", "digits", "renames", "with", "do", "mod", "requeue", "xor", "procedure", "protected", "interface", "synchronized", "exception", "overriding", "terminate" }; if (highlighted != 0) { syntax_delete (); } syntax_define_separators (separators); syntax_define_default (COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD); syntax_define_range ("--", "\n", '\0', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("'", "'", '\0', COLOUR_PINK, EFFECT_BOLD); syntax_define_operators (".,:;<=>+-*/&|()'", COLOUR_BLUE, EFFECT_BOLD); syntax_define_words (0, keywords, 73, COLOUR_BLUE, EFFECT_NORMAL); highlighted = 1; } static void highlight_cpp (void) { char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; char * keywords [102] = { "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "char8_t", "char16_t", "char32_t", "class", "compl", "concept", "const", "consteval", "constexpr", "constinit", "const_cast", "continue", "co_await", "co_return", "co_yield", "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", "public", "reflexpr", "register", "reinterpret_cast", "requires", "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq", "final", "override", "import", "module", "transaction_safe" }; if (highlighted != 0) { syntax_delete (); } syntax_define_separators (separators); syntax_define_default (COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD); syntax_define_range ("/*", "*/", '\0', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("//", "\n", '\0', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("#", "\n", '\\', COLOUR_PINK, EFFECT_NORMAL); syntax_define_range ("'", "'", '\\', COLOUR_PINK, EFFECT_BOLD); syntax_define_operators (".,:;<=>+*-/%!&~^?|()[]{}", COLOUR_BLUE, EFFECT_BOLD); syntax_define_words (1, keywords, 102, COLOUR_BLUE, EFFECT_NORMAL); highlighted = 1; } /* static void highlight_python (void) { char * separators = ".,:<=>+*-/%!&~^?|()[]'\" \t\r\n"; char * keywords [35] = { "False", "await", "else", "import", "pass", "None", "break", "except", "in", "raise", "True", "class", "finally", "is", "return", "and", "continue", "for", "lambda", "try", "as", "def", "from", "nonlocal", "while", "assert", "del", "global", "not", "with", "async", "elif", "if", "or", "yield" }; if (highlighted != 0) { syntax_delete (); } syntax_define_separators (separators); syntax_define_default (COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD); syntax_define_range ("#", "\n", '\\', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("'", "'", '\\', COLOUR_PINK, EFFECT_BOLD); syntax_define_operators (".,:<=>+*-/%!&~^?|()[]", COLOUR_BLUE, EFFECT_BOLD); syntax_define_words (0, keywords, 35, COLOUR_BLUE, EFFECT_NORMAL); highlighted = 1; } */ static void highlight_valgrind (void) { char * separators = "./-=?() \t\r\n"; char * keywords [1] = { "Invalid" }; if (highlighted != 0) { syntax_delete (); } syntax_define_separators (separators); syntax_define_default (COLOUR_RED, EFFECT_NORMAL, COLOUR_CYAN, EFFECT_BOLD); syntax_define_range ("==", "==", '\0', COLOUR_GREY, EFFECT_BOLD); syntax_define_range ("(", ")", '\0', COLOUR_PINK, EFFECT_NORMAL); syntax_define_range ("???", "\n", '\0', COLOUR_RED, EFFECT_BOLD); syntax_define_operators ("./-:", COLOUR_BLUE, EFFECT_BOLD); syntax_define_words (0, keywords, 1, COLOUR_BLUE, EFFECT_NORMAL); highlighted = 1; } int main (int argc, char * * argv) { int offset = 0; int select = 0; int length = 0; char * buffer = NULL; argument_define ("-v", "--version", echo_version); argument_define ("-l", "--license", echo_license); argument_define ("-c", "--c", highlight_c); argument_define ("-a", "--ada", highlight_ada); argument_define ("-C", "--c++", highlight_cpp); /*argument_define ("-p", "--python", highlight_python);*/ argument_define ("-V", "--valgrind", highlight_valgrind); if (argc != 1) { argument_select (argc, argv); } if (buffer == NULL) { if (argument_input == NULL) { buffer = record (); } else { select = file_type (argument_input); buffer = file_import (argument_input); } } if (highlighted == 0) { if ((select == FILE_TYPE_C_SOURCE) || (select == FILE_TYPE_C_HEADER)) { highlight_c (); } else if ((select == FILE_TYPE_ADA_BODY) || (select == FILE_TYPE_ADA_SPECIFICATION)) { highlight_ada (); } else if ((select == FILE_TYPE_CPP_SOURCE) || (select == FILE_TYPE_CPP_HEADER)) { highlight_cpp (); } else { highlight_common (); } } for (offset = 0; buffer [offset] != '\0'; offset += length) { select = syntax_select (& buffer [offset], & length); if (select >= syntax_count) { terminal_colour (COLOUR_RED, EFFECT_REVERSE); } else { terminal_colour (syntax_colour [select], syntax_effect [select]); } out (& buffer [offset], length); terminal_cancel (); } buffer = deallocate (buffer); syntax_delete (); argument_delete (); return (EXIT_SUCCESS); }