From 21e38223d2c1869b859f61f779a73f6e22fe0c00 Mon Sep 17 00:00:00 2001 From: anon Date: Mon, 18 Dec 2023 23:08:50 +0100 Subject: [PATCH] --- patch/emil.patch | 1524 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1524 insertions(+) create mode 100644 patch/emil.patch diff --git a/patch/emil.patch b/patch/emil.patch new file mode 100644 index 0000000..37cc30d --- /dev/null +++ b/patch/emil.patch @@ -0,0 +1,1524 @@ +From 0a48ebe68bf2750ae2c8045c6341ebd3184d5e2c Mon Sep 17 00:00:00 2001 +From: Emil Williams +Date: Mon, 18 Dec 2023 21:48:58 +0000 +Subject: [PATCH] updoot + +--- + Makefile | 47 ++++--- + source/bot.c | 306 +++++++++++++++++++++++++++++++++++++++++++ + source/bot.h | 299 +----------------------------------------- + source/config.inc | 13 +- + source/log.c | 19 +++ + source/log.h | 19 +-- + source/main.c | 27 +--- + source/syntax.c | 322 +++++++++++++++++++++++++++++++++++++++++++++ + source/syntax.h | 324 +++------------------------------------------- + 9 files changed, 710 insertions(+), 666 deletions(-) + create mode 100644 source/bot.c + create mode 100644 source/log.c + create mode 100644 source/syntax.c + +diff --git a/Makefile b/Makefile +index cfc8215..49019a9 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,38 +1,43 @@ +-.PHONY: clean run test ++INSTALL_TARGET := /etc/init.d/hibot ++OUT := hibot ++ ++WRAP := valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ++CFLAGS += -std=gnu99 -fno-builtin ++CPPFLAGS += -DPROGRAM_NAME=\"${OUT}\" -D_GNU_SOURCE -I/usr/include/libircclient/ ++LDLIBS := -lircclient + +-WRAP := valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all +-CFLAGS += -fno-builtin -I/usr/include/libircclient/ + ifeq ($(DEBUG), 1) +- CFLAGS += -Wall -Wextra -Wpedantic +- CFLAGS += -DDEBUG -O0 -ggdb -fno-inline ++ CFLAGS += -Wall -Wextra -Wpedantic -O0 -ggdb -fno-inline ++ CPPFLAGS += -DDEBUG + else + CFLAGS += -O3 -fno-stack-protector + endif + +-LDLIBS := -lircclient +- +-INSTALL_TARGET := /etc/init.d/hibot +-OUT := hibot +- + SOURCE.d := source/ +-SOURCE := main.c +-SOURCE := $(addprefix ${SOURCE.d}, ${SOURCE}) ++SOURCE := main.c syntax.c bot.c log.c ++OBJECT := $(addprefix ${SOURCE.d}, ${SOURCE:.c=.o}) + HEADER := config.inc version.inc log.h bot.h syntax.h + HEADER := $(addprefix ${SOURCE.d}, ${HEADER}) + +-${OUT}: ${SOURCE} ${HEADER} +- ${CC} ${CFLAGS} -o $@ ${SOURCE} ${LDLIBS} ++CC := ${CC} ${CFLAGS} + +-run: ${OUT} +- ./${OUT} irc.rizon.net:6665 "#/g/test" ++%.o: %.c ++ ${CC} ${CPPFLAGS} -c -o $@ $< + +-test: ${OUT} +- ${WRAP} ${OUT} irc.rizon.net:6665 "#/g/test" ++${OUT}: ${HEADER} | ${OBJECT} ++ ${CC} -flto=auto -o $@ $| ${LDLIBS} ++ ++clean: ++ ${RM} ${OBJECT} ${OUT} ${INSTALL_TARGET} + + install: + m4 script/hibot.m4 > ${INSTALL_TARGET} + chmod 755 ${INSTALL_TARGET} + +-clean: +- -rm ${OUT} +- -rm ${INSTALL_TARGET} ++run: ${OUT} ++ ./${OUT} irc.rizon.net:6665 "#/g/test" ++ ++test: ${OUT} ++ ${WRAP} ${OUT} irc.rizon.net:6665 "#/g/test" ++ ++.PHONY: clean run test install +diff --git a/source/bot.c b/source/bot.c +new file mode 100644 +index 0000000..2bfe0ae +--- /dev/null ++++ b/source/bot.c +@@ -0,0 +1,306 @@ ++#include "log.h" ++#include "bot.h" ++#include "syntax.h" ++#include "config.inc" ++ ++#include ++ ++char * channel; ++char * server; ++char * port; ++ ++static inline ++void irc_message(const char * const message) { ++ irc_cmd_msg(session, channel, message); ++} ++ ++static inline ++void irc_private_message(const char * const user, const char * const message) { ++ irc_cmd_msg(session, user, message); ++} ++ ++static inline ++char * username_root(const char * const fullname){ ++ char * r = (char *)fullname; ++ while (*(r++) != '!') { ; } ++ asprintf(&r, "From %.*s:", (int)(r - fullname)-1, fullname); ++ return r; ++} ++ ++typedef struct { ++ int is_active; ++ char * user; ++ language_t language; ++ struct itimerval timer; ++ char * buffer[128]; // XXX: no overflow detection/avertion ++ unsigned int buffer_head; // is implemented on this bunch ++} request_t; ++ ++void init_request(request_t * request) { ++ request->is_active = 0; ++ request->timer.it_value.tv_sec = 0; ++ request->timer.it_value.tv_usec = 0; ++ request->timer.it_interval.tv_sec = 0; ++ request->timer.it_interval.tv_usec = 0; ++ request->buffer_head = 0; ++} ++ ++request_t request_queue__[message_queue_size]; ++request_t * request_queue[message_queue_size]; ++unsigned int request_queue_head = 0; ++ ++static inline ++void touch_request_timer(request_t * request) { ++ request->timer.it_value.tv_sec = message_timeout; ++ setitimer(ITIMER_REAL, &(request->timer), NULL); ++} ++ ++void activate_request(request_t * request) { ++ request->is_active = 1; ++ ++ /* message header */ ++ char * short_name = username_root(request->user); ++ irc_message(short_name); ++ free(short_name); ++} ++ ++request_t * take_request(const char * const user, language_t language) { ++ for (unsigned int i = 0; i < request_queue_head; i++) { ++ if(!strcmp(request_queue[i]->user, user)) { ++ return request_queue[i]; ++ } ++ } ++ ++ if (request_queue_head == message_queue_size) { ++ return NULL; ++ } ++ ++ request_t * request = request_queue[request_queue_head]; ++ ++ request->language = language; ++ request->user = strdup(user); ++ ++ if (request_queue_head == 0) { ++ activate_request(request); ++ } ++ ++ ++request_queue_head; ++ ++ char * log_message; ++ asprintf(&log_message, "Took message: %p (%d)", (void*)request, request_queue_head); ++ log_notice(log_message); ++ free(log_message); ++ ++ return request; ++} ++ ++void drop_reqest() { ++ request_t * request = request_queue[0]; ++ ++ if (message_queue_size > 1) { ++ for (unsigned int i = 0; i < request_queue_head; i++) { ++ request_queue[i] = request_queue[i+1]; ++ } ++ request_queue[request_queue_head] = request; ++ } ++ ++ --request_queue_head; ++ ++ request->is_active = 0; ++ free(request->user); ++ ++ if (request_queue_head) { ++ activate_request(request_queue[0]); ++ for (unsigned int i = 0; i < request_queue[0]->buffer_head; i++) { ++ irc_message(request_queue[0]->buffer[i]); ++ free(request_queue[0]->buffer[i]); ++ } ++ request_queue[0]->buffer_head = 0; ++ touch_request_timer(request_queue[0]); ++ } ++ ++ char * log_message; ++ asprintf(&log_message, "Dropped message: %p (%d)", (void*)request, request_queue_head); ++ log_notice(log_message); ++ free(log_message); ++} ++ ++void on_message_timeout(int unused) { ++ (void)unused; ++ ++ /* message footer */ ++ irc_message("--"); ++ ++ drop_reqest(request_queue); ++} ++ ++static ++language_t translate_language(const char * const language) { ++ if (!strcmp(language, "C") || !strcmp(language, "C++")) { ++ return C; ++ } else if (!strcmp(language, "ADA")) { ++ return ADA; ++ } ++ return -1; ++} ++ ++static ++void irc_help() { ++ irc_message(PROGRAM_NAME " " ++#include "version.inc" ++ ); ++ irc_message(PROGRAM_NAME " is a code highlighting IRC bot." ++ " You may direct message it with your code or commands." ++ ); ++ irc_message("Syntax:"); ++ irc_message(" !help // print help"); ++ irc_message(" ! // set language for next message"); ++ irc_message(" // echo this code"); ++ irc_message(" ! // set language and echo code"); ++ irc_message("--"); ++} ++ ++// XXX: msg ChanServ IDENTIFY? ++static ++void event_connect(irc_session_t * session, ++ const char * event, ++ const char * origin, ++ const char ** params, ++ unsigned int count) { ++ (void)event; ++ (void)origin; ++ (void)params; ++ (void)count; ++ ++ log_notice("IRC connection secured."); ++ irc_cmd_join(session, channel, 0); ++ char * buffer; ++ asprintf(&buffer, "Joined destination channel: `%s`.", channel); ++ log_notice(buffer); ++ free(buffer); ++} ++ ++static ++void event_privmsg(irc_session_t * session, ++ const char * event, ++ const char * origin, ++ const char ** params, ++ unsigned int count) { ++ (void)session; ++ (void)event; ++ (void)count; ++ ++ char * const message_guard = strdup(params[1]); ++ char * message = message_guard; ++ char * terminator; ++ ++ int is_code = 1; ++ ++ /* Is command */ ++ if (*message == '!') { ++ terminator = message; ++ while (*terminator != ' ') { ++ if (*terminator == '\0') { ++ is_code = 0; ++ break; ++ } ++ ++terminator; ++ } ++ *terminator = '\0'; ++ /* */ ++ if (!strcmp(message, "!help")) { ++ irc_help(); ++ goto END; ++ } ++ /* get language */ ++ for (char * s = message + 1; *s != '\0'; s++) { ++ *s = toupper(*s); ++ } ++ int l = translate_language(message + 1); ++ message = terminator + 1; ++ if (l != -1) { ++ language = l; ++ syntax_count = 0; ++ syntax_functions[language](); ++ } ++ } ++ ++ /* Is code */ ++ if (is_code) { ++ request_t * request = take_request(origin, language); ++ if (!request) { ++ irc_private_message(origin, message_queue_full_message); ++ goto END; ++ } ++ ++ if (request->is_active) { ++ touch_request_timer(request); ++ irc_message(syntax_highlight(message)); ++ } else { ++ request->buffer[request->buffer_head++] = strdup(syntax_highlight(message)); ++ } ++ } ++ ++ END: ++ free(message_guard); ++} ++ ++static ++void event_channel(irc_session_t * session, ++ const char * event, ++ const char * origin, ++ const char ** params, ++ unsigned int count) { ++ (void) session; ++ (void) event; ++ (void) origin; ++ (void) count; ++ ++ const char * const message = params[1]; ++ ++ if (!strncmp(message, "!help", sizeof("!help")-1)) { ++ irc_help(); ++ } ++} ++ ++ ++int connect_bot(const char * const server, const short port) { ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.event_connect = event_connect; ++ callbacks.event_privmsg = event_privmsg; ++ callbacks.event_channel = event_channel; ++ session = irc_create_session(&callbacks); ++ ++ if (!session) { ++ log_error("Error creating IRC session."); ++ return 1; ++ } else { ++ log_notice("IRC Session initialized."); ++ } ++ ++ for (unsigned int i = 0; i < message_queue_size; i++) { ++ request_queue[i] = &request_queue__[i]; ++ init_request(request_queue[i]); ++ } ++ signal(SIGALRM, on_message_timeout); ++ ++ irc_connect(session, ++ server, ++ port, ++ config_password, ++ config_username, ++ config_username, ++ config_username ++ ); ++ ++ return 0; ++} ++ ++int connection_loop(void) { ++ if (irc_run(session) != 0) { ++ log_error("Error running IRC session\n" ++ "Possible issue: bad URL, no network connection," ++ "bad port, or refused connection."); ++ } ++ return 0; ++} +diff --git a/source/bot.h b/source/bot.h +index 76d5512..c89987c 100644 +--- a/source/bot.h ++++ b/source/bot.h +@@ -8,304 +8,19 @@ + #include + #include + ++#include "syntax.h" ++ + extern syntax_setter_t syntax_functions[]; + + static irc_session_t * session; + static irc_callbacks_t callbacks; + +-static inline +-void irc_message(const char * const message) { +- irc_cmd_msg(session, channel, message); +-} +- +-static inline +-void irc_private_message(const char * const user, const char * const message) { +- irc_cmd_msg(session, user, message); +-} +- +-static inline +-char * username_root(const char * const fullname){ +- char * r = (char *)fullname; +- while (*(r++) != '!') { ; } +- asprintf(&r, "From %.*s:", (int)(r - fullname)-1, fullname); +- return r; +-} +- +-typedef struct { +- int is_active; +- char * user; +- language_t language; +- struct itimerval timer; +- char * buffer[128]; // XXX: no overflow detection/avertion +- unsigned int buffer_head; // is implemented on this bunch +-} request_t; +- +-void init_request(request_t * request) { +- request->is_active = 0; +- request->timer.it_value.tv_sec = 0; +- request->timer.it_value.tv_usec = 0; +- request->timer.it_interval.tv_sec = 0; +- request->timer.it_interval.tv_usec = 0; +- request->buffer_head = 0; +-} +- +-request_t request_queue__[message_queue_size]; +-request_t * request_queue[message_queue_size]; +-unsigned int request_queue_head = 0; +- +-static inline +-void touch_request_timer(request_t * request) { +- request->timer.it_value.tv_sec = message_timeout; +- setitimer(ITIMER_REAL, &(request->timer), NULL); +-} +- +-void activate_request(request_t * request) { +- request->is_active = 1; +- +- /* message header */ +- char * short_name = username_root(request->user); +- irc_message(short_name); +- free(short_name); +-} +- +-request_t * take_request(const char * const user, language_t language) { +- for (unsigned int i = 0; i < request_queue_head; i++) { +- if(!strcmp(request_queue[i]->user, user)) { +- return request_queue[i]; +- } +- } +- +- if (request_queue_head == message_queue_size) { +- return NULL; +- } +- +- request_t * request = request_queue[request_queue_head]; +- +- request->language = language; +- request->user = strdup(user); +- +- if (request_queue_head == 0) { +- activate_request(request); +- } +- +- ++request_queue_head; +- +- char * log_message; +- asprintf(&log_message, "Took message: %p (%d)", (void*)request, request_queue_head); +- log_notice(log_message); +- free(log_message); +- +- return request; +-} +- +-void drop_reqest() { +- request_t * request = request_queue[0]; +- +- if (message_queue_size > 1) { +- for (unsigned int i = 0; i < request_queue_head; i++) { +- request_queue[i] = request_queue[i+1]; +- } +- request_queue[request_queue_head] = request; +- } +- +- --request_queue_head; +- +- request->is_active = 0; +- free(request->user); +- +- if (request_queue_head) { +- activate_request(request_queue[0]); +- for (unsigned int i = 0; i < request_queue[0]->buffer_head; i++) { +- irc_message(request_queue[0]->buffer[i]); +- free(request_queue[0]->buffer[i]); +- } +- request_queue[0]->buffer_head = 0; +- touch_request_timer(request_queue[0]); +- } +- +- char * log_message; +- asprintf(&log_message, "Dropped message: %p (%d)", (void*)request, request_queue_head); +- log_notice(log_message); +- free(log_message); +-} +- +-void on_message_timeout(int unused) { +- (void)unused; +- +- /* message footer */ +- irc_message("--"); +- +- drop_reqest(request_queue); +-} +- +-static +-language_t translate_language(const char * const language) { +- if (!strcmp(language, "C") || !strcmp(language, "C++")) { +- return C; +- } else if (!strcmp(language, "ADA")) { +- return ADA; +- } +- return -1; +-} +- +-static +-void irc_help() { +- irc_message(PROGRAM_NAME " " +-#include "version.inc" +- ); +- irc_message(PROGRAM_NAME " is a code highlighting IRC bot." +- " You may direct message it with your code or commands." +- ); +- irc_message("Syntax:"); +- irc_message(" !help // print help"); +- irc_message(" ! // set language for next message"); +- irc_message(" // echo this code"); +- irc_message(" ! // set language and echo code"); +- irc_message("--"); +-} +- +-// XXX: msg ChanServ IDENTIFY? +-static +-void event_connect(irc_session_t * session, +- const char * event, +- const char * origin, +- const char ** params, +- unsigned int count) { +- (void)event; +- (void)origin; +- (void)params; +- (void)count; +- +- log_notice("IRC connection secured."); +- irc_cmd_join(session, channel, 0); +- char * buffer; +- asprintf(&buffer, "Joined destination channel: `%s`.", channel); +- log_notice(buffer); +- free(buffer); +-} +- +-static +-void event_privmsg(irc_session_t * session, +- const char * event, +- const char * origin, +- const char ** params, +- unsigned int count) { +- (void)session; +- (void)event; +- (void)count; +- +- char * const message_guard = strdup(params[1]); +- char * message = message_guard; +- char * terminator; +- int is_code = 1; +- +- /* Is command */ +- if (*message == '!') { +- terminator = message; +- while (*terminator != ' ') { +- if (*terminator == '\0') { +- is_code = 0; +- break; +- } +- ++terminator; +- } +- *terminator = '\0'; +- /* */ +- if (!strcmp(message, "!help")) { +- irc_help(); +- goto END; +- } +- /* get language */ +- for (char * s = message + 1; *s != '\0'; s++) { +- *s = toupper(*s); +- } +- int l = translate_language(message + 1); +- message = terminator + 1; +- if (l != -1) { +- language = l; +- syntax_count = 0; +- syntax_functions[language](); +- } +- } +- +- /* Is code */ +- if (is_code) { +- request_t * request = take_request(origin, language); +- if (!request) { +- irc_private_message(origin, message_queue_full_message); +- goto END; +- } +- +- if (request->is_active) { +- touch_request_timer(request); +- irc_message(syntax_highlight(message)); +- } else { +- request->buffer[request->buffer_head++] = strdup(syntax_highlight(message)); +- } +- } +- +- END: +- free(message_guard); +-} +- +-static +-void event_channel(irc_session_t * session, +- const char * event, +- const char * origin, +- const char ** params, +- unsigned int count) { +- (void) session; +- (void) event; +- (void) origin; +- (void) count; +- +- const char * const message = params[1]; +- +- if (!strncmp(message, "!help", sizeof("!help")-1)) { +- irc_help(); +- } +-} +- +- +-int connect_bot(const char * const server, const short port) { +- memset(&callbacks, 0, sizeof(callbacks)); +- callbacks.event_connect = event_connect; +- callbacks.event_privmsg = event_privmsg; +- callbacks.event_channel = event_channel; +- session = irc_create_session(&callbacks); +- +- if (!session) { +- log_error("Error creating IRC session."); +- return 1; +- } else { +- log_notice("IRC Session initialized."); +- } +- +- for (unsigned int i = 0; i < message_queue_size; i++) { +- request_queue[i] = &request_queue__[i]; +- init_request(request_queue[i]); +- } +- signal(SIGALRM, on_message_timeout); +- +- irc_connect(session, +- server, +- port, +- password, +- username, +- username, +- username +- ); +- +- return 0; +-} ++extern char * channel; ++extern char * server; ++extern char * port; + +-int connection_loop(void) { +- if (irc_run(session) != 0) { +- log_error("Error running IRC session\n" +- "Possible issue: bad URL, no network connection, bad port, refused connection."); +- } +- return 0; +-} ++extern int connect_bot(const char * const server, const short port); ++extern int connection_loop(void); + + #define BOT_H + #endif +diff --git a/source/config.inc b/source/config.inc +index a9de7c4..3ae29a3 100644 +--- a/source/config.inc ++++ b/source/config.inc +@@ -1,12 +1,17 @@ + #ifndef CONFIG_INC + +-const char * const username = PROGRAM_NAME; +-const char * const password = ""; +-const int message_timeout = 3; +-const char * const message_queue_full_message = "Air space too crowded in this area."; ++#ifndef PROGRAM_NAME ++# define PROGRAM_NAME "hibot" ++#endif ++ + #define message_queue_size 3 + #define DEFAULT_LANGUAGE C + #define LOG_FILE stdout + ++#define config_username PROGRAM_NAME ++#define config_password "" ++#define message_timeout 3 ++#define message_queue_full_message "Air space too crowded in this area." ++ + #define CONFIG_INC + #endif +diff --git a/source/log.c b/source/log.c +new file mode 100644 +index 0000000..9e9c078 +--- /dev/null ++++ b/source/log.c +@@ -0,0 +1,19 @@ ++#include "log.h" ++ ++FILE * log_file; ++ ++static ++void log(const char * const message, const char * const color) { ++ fputs(color, log_file); ++ fputs(message, log_file); ++ fputs("\033[0m\n", log_file); ++ fflush(log_file); ++} ++ ++void log_notice(const char * const message) { ++ log("", message); ++} ++ ++void log_error(const char * const message) { ++ log("\033[33m", message); ++} +diff --git a/source/log.h b/source/log.h +index 8e894b9..f983bc3 100644 +--- a/source/log.h ++++ b/source/log.h +@@ -2,23 +2,10 @@ + + #include + +-FILE * log_file; ++extern FILE * log_file; + +-static +-void log(const char * const message, const char * const color) { +- fputs(color, log_file); +- fputs(message, log_file); +- fputs("\033[0m\n", log_file); +- fflush(log_file); +-} +- +-void log_notice(const char * const message) { +- log("", message); +-} +- +-void log_error(const char * const message) { +- log("\033[33m", message); +-} ++extern void log_notice(const char * const message); ++extern void log_error(const char * const message); + + #define LOG_H + #endif +diff --git a/source/main.c b/source/main.c +index c8d1872..33d4ade 100644 +--- a/source/main.c ++++ b/source/main.c +@@ -1,31 +1,9 @@ +-#define PROGRAM_NAME "hibot" +-#define _GNU_SOURCE +- + #include "config.inc" + +-char * channel; +-char * server; +-char * port; +- +-typedef enum { +- C, +- ADA, +-} language_t; +- +-language_t language = DEFAULT_LANGUAGE; +- +-typedef void (*syntax_setter_t)(void); +- + #include "log.h" + #include "syntax.h" + #include "bot.h" + +-syntax_setter_t syntax_functions[] = { +- [C] = &syntax_c, +- [ADA] = &syntax_ada, +-}; +- +- + const char help_message[] = + PROGRAM_NAME " : " + ; +@@ -38,11 +16,10 @@ signed main(int argc, char * * argv) { + channel = argv[2]; + server = strdup(argv[1]); + port = strchr(server, ':'); +- if (port) { +- *port = '\0'; +- } else { ++ if (!port) { + goto USAGE_ERROR; + } ++ *port = '\0'; + ++port; + int port_i = 0; + if(!sscanf(port, "%hd", &port_i)) { +diff --git a/source/syntax.c b/source/syntax.c +new file mode 100644 +index 0000000..557279d +--- /dev/null ++++ b/source/syntax.c +@@ -0,0 +1,322 @@ ++#include "config.inc" ++ ++#include "syntax.h" ++ ++language_t language = DEFAULT_LANGUAGE; ++ ++size_t syntax_count = 0; ++ ++syntax_setter_t syntax_functions[] = { ++ [C] = &syntax_c, ++ [ADA] = &syntax_ada, ++}; ++ ++static int syntax_enrange [SYNTAX_LIMIT]; ++static int syntax_derange [SYNTAX_LIMIT]; ++static char syntax_begin [SYNTAX_LIMIT] [96]; ++static char syntax_end [SYNTAX_LIMIT] [96]; ++static char syntax_escape [SYNTAX_LIMIT]; ++static char * syntax_colour [SYNTAX_LIMIT]; ++ ++static int character_compare_array (char character, char * character_array) { ++ size_t i = 0; ++ ++ do { ++ if (character == character_array [i]) { ++ return (1); ++ } ++ } while (++i != strlen (character_array)); ++ ++ return (0); ++} ++ ++static void syntax_rule (int enrange, ++ int derange, ++ char * begin, ++ char * end, ++ char escape, ++ char * colour) { ++ if (syntax_count >= SYNTAX_LIMIT) { ++ return; ++ } ++ ++ strncpy (syntax_begin [syntax_count], begin, 96); ++ strncpy (syntax_end [syntax_count], end, 96); ++ ++ syntax_enrange [syntax_count] = enrange; ++ syntax_derange [syntax_count] = derange; ++ syntax_escape [syntax_count] = escape; ++ syntax_colour [syntax_count] = colour; ++ ++ ++syntax_count; ++} ++ ++static size_t syntax_loop (char * string, ++ size_t * length) { ++ size_t offset, subset, select; ++ ++ for (select = offset = 0; select != syntax_count; ++select) { ++ if (syntax_enrange [select] == 0) { ++ if (syntax_derange [select] == 0) { ++ if (strncmp (string, syntax_begin [select], strlen (syntax_begin [select])) == 0) { ++ break; ++ } ++ } else { ++ if ((strncmp (string, syntax_begin [select], strlen (syntax_begin [select])) == 0) ++ && (character_compare_array (string [offset + strlen (syntax_begin [select])], syntax_end [select]) == 1)) { ++ break; ++ } ++ } ++ } else { ++ for (subset = 0; subset != strlen (syntax_begin [select]); ++subset) { ++ if (string [offset] == syntax_begin [select] [subset]) { ++ goto selected; ++ } ++ } ++ } ++ } ++ ++ selected: ++ ++ if (select >= syntax_count) { ++ * length = 1; ++ return (select); ++ } ++ ++ for (offset = 1; string [offset - 1] != '\0'; ++offset) { ++ if (string [offset] == syntax_escape [select]) { ++ ++offset; ++ continue; ++ } ++ ++ if (syntax_derange [select] == 0) { ++ if (strncmp (& string [offset], syntax_end [select], strlen (syntax_end [select])) == 0) { ++ * length = offset + strlen (syntax_end [select]); ++ goto finished; ++ } ++ } else { ++ subset = 0; ++ if (strcmp (syntax_end [select], "")) { ++ do { ++ if (string [offset] == syntax_end [select] [subset]) { ++ * length = offset; ++ goto finished; ++ } ++ } while (++subset != strlen (syntax_end [select])); ++ } ++ } ++ } ++ ++ finished: ++ ++ return (select); ++} ++ ++void syntax_c (void) { ++ char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; ++ ++ char * keywords [] = { ++ "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" ++ }; ++ ++ size_t word; ++ ++ syntax_rule (0, 0, "/*", "*/", '\0', COLOUR_GREY); ++ syntax_rule (0, 0, "//", "\n", '\0', COLOUR_GREY); ++ syntax_rule (0, 0, "#", "\n", '\\', COLOUR_YELLOW); ++ syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); ++ syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); ++ ++ for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { ++ syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); ++ } ++ ++ syntax_rule (1, 0, "()[]{}", "", '\0', COLOUR_BLUE); ++ syntax_rule (1, 0, ".,:;<=>+*-/%!&~^?|", "", '\0', COLOUR_CYAN); ++ ++ syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); ++ syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "_", separators, '\0', COLOUR_WHITE); ++} ++ ++void syntax_ada (void) { ++ char * separators = ".,:;<=>+-*/&|()\" \t\r\n"; ++ ++ char * keywords [] = { ++ "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" ++ }; ++ ++ size_t word; ++ ++ syntax_rule (0, 0, "--", "\n", '\0', COLOUR_GREY); ++ syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); ++ syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); ++ ++ for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { ++ syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); ++ } ++ ++ syntax_rule (1, 0, "()", "", '\0', COLOUR_BLUE); ++ syntax_rule (1, 0, ".,:;<=>+-*/&|'", "", '\0', COLOUR_CYAN); ++ ++ syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); ++ syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); ++} ++ ++void syntax_cpp (void) { ++ char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; ++ ++ char * keywords [] = { ++ "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" ++ }; ++ ++ char * specials [] = { ++ "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", ++ "FILE", "std", "typeof", "cout", "cin", "endl", "timespec", "tm" ++ /* TODO: I don't really care about this, but some people do, Anon please add what you find interesting in here... */ ++ }; ++ ++ size_t word; ++ ++ syntax_rule (0, 0, "/*", "*/", '\0', COLOUR_GREY); ++ syntax_rule (0, 0, "//", "\n", '\0', COLOUR_GREY); ++ syntax_rule (0, 0, "#", "\n", '\\', COLOUR_YELLOW); ++ syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); ++ syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); ++ ++ for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { ++ syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); ++ } ++ ++ for (word = 0; word != sizeof (specials) / sizeof (specials [0]); ++word) { ++ syntax_rule (0, 1, specials [word], separators, '\0', COLOUR_CYAN); ++ } ++ ++ syntax_rule (1, 0, "()[]{}", "", '\0', COLOUR_BLUE); ++ syntax_rule (1, 0, ".,:;<=>+*-/%!&~^?|", "", '\0', COLOUR_CYAN); ++ ++ syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); ++ syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "_", separators, '\0', COLOUR_WHITE); ++} ++ ++void syntax_fasm (void) { ++ char * separators = ".,+-=:;(){}[]%$<> \t\r\n"; ++ ++ char * instructions [] = { ++ "mov", "movabs", "movapd", "movaps", "movebe", "movsd", "movsx", "movzx", ++ "movsxd", "movd", "movq", "movs", "movsb", "movsw", "movsd", "movsq", ++ "cmovmp", "cmovrcxz", "cmovc", "cmovnc", "cmove", "cmovne", "cmovz", "cmovnz", ++ "cmovg", "cmovng", "cmovge", "cmovnge", "cmovl", "cmovnl", "cmovle", "cmovnle", ++ "cmova", "cmovna", "cmovae", "cmovnae", "cmovb", "cmovnb", "cmovbe", "cmovnbe", ++ "cmovs", "cmovns", "cmovo", "cmovno", "cmovp", "cmovnp", "cmovpo", "cmovpe", ++ "cmp", "cmps", "cmpsb", "cmpsw", "cmpsd", "cmpsq", "cmpxchg", "lea", ++ "monitor", "cpuid", "in", "out", "syscall", "sysenter", "sysret", "sysexit", ++ "swap", "bswap", "pop", "push", "call", "ret", "enter", "leave", ++ "and", "or", "not", "neg", "sal", "sar", "shl", "shr", ++ "inc", "dec", "add", "sub", "mul", "div", "imul", "idiv", ++ "nop", "fnop", "adc", "sbb", "aaa", "aas", "aam", "aad", ++ "jmp", "jrcxz", "jc", "jnc", "je", "jne", "jz", "jnz", ++ "jg", "jng", "jge", "jnge", "jl", "jnl", "jle", "jnle", ++ "ja", "jna", "jae", "jnae", "jb", "jnb", "jbe", "jnbe", ++ "js", "jns", "jo", "jno", "jp", "jnp", "jpo", "jpe", ++ "rep", "repe", "repz", "repne", "repnz", "loop", "loope", "loopne" ++ }; ++ ++ char * registers [] = { ++ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", ++ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", ++ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", ++ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", ++ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", ++ "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", ++ "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", ++ "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", ++ "ah", "ch", "dh", "bh" ++ }; ++ ++ char * keywords [] = { ++ "format", "executable", "readable", "writable", "segment", "sector", "entry", "macro", ++ "db", "dw", "dd", "dq", "rb", "rw", "rd", "rq" ++ }; ++ ++ size_t word; ++ ++ syntax_rule (0, 0, ";", "\n", '\0', COLOUR_GREY); ++ syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); ++ syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); ++ ++ for (word = 0; word != sizeof (instructions) / sizeof (instructions [0]); ++word) { ++ syntax_rule (0, 1, instructions [word], separators, '\0', COLOUR_YELLOW); ++ } ++ ++ for (word = 0; word != sizeof (registers) / sizeof (registers [0]); ++word) { ++ syntax_rule (0, 1, registers [word], separators, '\0', COLOUR_CYAN); ++ } ++ ++ for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { ++ syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); ++ } ++ ++ syntax_rule (1, 0, "()[]{}", "", '\0', COLOUR_BLUE); ++ syntax_rule (1, 0, ".,+-=:;%$<>", "", '\0', COLOUR_CYAN); ++ ++ syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); ++ syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); ++ syntax_rule (1, 1, "_", separators, '\0', COLOUR_WHITE); ++} ++ ++char * syntax_highlight (char * code) { ++ static char buffer [4096] = ""; ++ static char string [4096] = ""; ++ ++ size_t select, length, offset; ++ ++ memset (buffer, 0, sizeof (buffer)); ++ memset (string, 0, sizeof (string)); ++ ++ strcpy (string, code); ++ ++ for (offset = 0; offset < strlen (string); offset += length) { ++ select = syntax_loop (& string [offset], & length); ++ ++ if (select < syntax_count) { ++ strncat (buffer, "\003", 1); ++ strncat (buffer, syntax_colour [select], 2); ++ strncat (buffer, & string [offset], length); ++ strncat (buffer, "\017", 1); ++ } else { ++ strncat (buffer, & string [offset], length); ++ } ++ } ++ ++ return (buffer); ++} +diff --git a/source/syntax.h b/source/syntax.h +index 502d202..81ddc7b 100644 +--- a/source/syntax.h ++++ b/source/syntax.h +@@ -1,3 +1,5 @@ ++#ifndef SYNTAX_H ++ + #include + + #define SYNTAX_LIMIT (256) +@@ -14,319 +16,25 @@ + #define COLOUR_PINK ("13") + #define COLOUR_GREY ("14") + ++typedef enum { ++ C, ++ ADA, ++} language_t; ++ ++typedef void (*syntax_setter_t)(void); ++ + extern void syntax_c (void); + extern void syntax_ada (void); ++extern void syntax_fasm (void); ++extern void syntax_cpp (void); + + extern char * syntax_highlight (char * string); + +-static size_t syntax_count = 0; +- +-static int syntax_enrange [SYNTAX_LIMIT]; +-static int syntax_derange [SYNTAX_LIMIT]; +-static char syntax_begin [SYNTAX_LIMIT] [96]; +-static char syntax_end [SYNTAX_LIMIT] [96]; +-static char syntax_escape [SYNTAX_LIMIT]; +-static char * syntax_colour [SYNTAX_LIMIT]; +- +-static int character_compare_array (char character, char * character_array) { +- size_t i = 0; +- +- do { +- if (character == character_array [i]) { +- return (1); +- } +- } while (++i != strlen (character_array)); +- +- return (0); +-} +- +-static void syntax_rule (int enrange, +- int derange, +- char * begin, +- char * end, +- char escape, +- char * colour) { +- if (syntax_count >= SYNTAX_LIMIT) { +- return; +- } +- +- strncpy (syntax_begin [syntax_count], begin, 96); +- strncpy (syntax_end [syntax_count], end, 96); +- +- syntax_enrange [syntax_count] = enrange; +- syntax_derange [syntax_count] = derange; +- syntax_escape [syntax_count] = escape; +- syntax_colour [syntax_count] = colour; +- +- ++syntax_count; +-} +- +-static size_t syntax_loop (char * string, +- size_t * length) { +- size_t offset, subset, select; +- +- for (select = offset = 0; select != syntax_count; ++select) { +- if (syntax_enrange [select] == 0) { +- if (syntax_derange [select] == 0) { +- if (strncmp (string, syntax_begin [select], strlen (syntax_begin [select])) == 0) { +- break; +- } +- } else { +- if ((strncmp (string, syntax_begin [select], strlen (syntax_begin [select])) == 0) +- && (character_compare_array (string [offset + strlen (syntax_begin [select])], syntax_end [select]) == 1)) { +- break; +- } +- } +- } else { +- for (subset = 0; subset != strlen (syntax_begin [select]); ++subset) { +- if (string [offset] == syntax_begin [select] [subset]) { +- goto selected; +- } +- } +- } +- } +- +- selected: +- +- if (select >= syntax_count) { +- * length = 1; +- return (select); +- } +- +- for (offset = 1; string [offset - 1] != '\0'; ++offset) { +- if (string [offset] == syntax_escape [select]) { +- ++offset; +- continue; +- } +- +- if (syntax_derange [select] == 0) { +- if (strncmp (& string [offset], syntax_end [select], strlen (syntax_end [select])) == 0) { +- * length = offset + strlen (syntax_end [select]); +- goto finished; +- } +- } else { +- subset = 0; +- if (strcmp (syntax_end [select], "") == 0) { +- break; +- } do { +- if (string [offset] == syntax_end [select] [subset]) { +- * length = offset; +- goto finished; +- } +- } while (++subset != strlen (syntax_end [select])); +- } +- } +- +- finished: +- +- return (select); +-} +- +-void syntax_c (void) { +- char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; +- +- char * keywords [] = { +- "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" +- }; +- +- size_t word; +- +- syntax_rule (0, 0, "/*", "*/", '\0', COLOUR_GREY); +- syntax_rule (0, 0, "//", "\n", '\0', COLOUR_GREY); +- syntax_rule (0, 0, "#", "\n", '\\', COLOUR_YELLOW); +- syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); +- syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); +- +- for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { +- syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); +- } +- +- syntax_rule (1, 0, "()[]{}", "", '\0', COLOUR_BLUE); +- syntax_rule (1, 0, ".,:;<=>+*-/%!&~^?|", "", '\0', COLOUR_CYAN); +- +- syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); +- syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "_", separators, '\0', COLOUR_WHITE); +-} +- +-void syntax_ada (void) { +- char * separators = ".,:;<=>+-*/&|()\" \t\r\n"; +- +- char * keywords [] = { +- "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" +- }; +- +- size_t word; +- +- syntax_rule (0, 0, "--", "\n", '\0', COLOUR_GREY); +- syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); +- syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); +- +- for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { +- syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); +- } +- +- syntax_rule (1, 0, "()", "", '\0', COLOUR_BLUE); +- syntax_rule (1, 0, ".,:;<=>+-*/&|'", "", '\0', COLOUR_CYAN); +- +- syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); +- syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); +-} +- +-void syntax_cpp (void) { +- char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n"; +- +- char * keywords [] = { +- "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" +- }; +- +- char * specials [] = { +- "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", +- "FILE", "std", "typeof", "cout", "cin", "endl", "timespec", "tm" +- /* TODO: I don't really care about this, but some people do, Anon please add what you find interesting in here... */ +- }; +- +- size_t word; +- +- syntax_rule (0, 0, "/*", "*/", '\0', COLOUR_GREY); +- syntax_rule (0, 0, "//", "\n", '\0', COLOUR_GREY); +- syntax_rule (0, 0, "#", "\n", '\\', COLOUR_YELLOW); +- syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); +- syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); +- +- for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { +- syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); +- } +- +- for (word = 0; word != sizeof (specials) / sizeof (specials [0]); ++word) { +- syntax_rule (0, 1, specials [word], separators, '\0', COLOUR_CYAN); +- } +- +- syntax_rule (1, 0, "()[]{}", "", '\0', COLOUR_BLUE); +- syntax_rule (1, 0, ".,:;<=>+*-/%!&~^?|", "", '\0', COLOUR_CYAN); +- +- syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); +- syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "_", separators, '\0', COLOUR_WHITE); +-} +- +-void syntax_fasm (void) { +- char * separators = ".,+-=:;(){}[]%$<> \t\r\n"; +- +- char * instructions [] = { +- "mov", "movabs", "movapd", "movaps", "movebe", "movsd", "movsx", "movzx", +- "movsxd", "movd", "movq", "movs", "movsb", "movsw", "movsd", "movsq", +- "cmovmp", "cmovrcxz", "cmovc", "cmovnc", "cmove", "cmovne", "cmovz", "cmovnz", +- "cmovg", "cmovng", "cmovge", "cmovnge", "cmovl", "cmovnl", "cmovle", "cmovnle", +- "cmova", "cmovna", "cmovae", "cmovnae", "cmovb", "cmovnb", "cmovbe", "cmovnbe", +- "cmovs", "cmovns", "cmovo", "cmovno", "cmovp", "cmovnp", "cmovpo", "cmovpe", +- "cmp", "cmps", "cmpsb", "cmpsw", "cmpsd", "cmpsq", "cmpxchg", "lea", +- "monitor", "cpuid", "in", "out", "syscall", "sysenter", "sysret", "sysexit", +- "swap", "bswap", "pop", "push", "call", "ret", "enter", "leave", +- "and", "or", "not", "neg", "sal", "sar", "shl", "shr", +- "inc", "dec", "add", "sub", "mul", "div", "imul", "idiv", +- "nop", "fnop", "adc", "sbb", "aaa", "aas", "aam", "aad", +- "jmp", "jrcxz", "jc", "jnc", "je", "jne", "jz", "jnz", +- "jg", "jng", "jge", "jnge", "jl", "jnl", "jle", "jnle", +- "ja", "jna", "jae", "jnae", "jb", "jnb", "jbe", "jnbe", +- "js", "jns", "jo", "jno", "jp", "jnp", "jpo", "jpe", +- "rep", "repe", "repz", "repne", "repnz", "loop", "loope", "loopne" +- }; +- +- char * registers [] = { +- "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", +- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +- "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", +- "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", +- "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", +- "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", +- "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", +- "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", +- "ah", "ch", "dh", "bh" +- }; +- +- char * keywords [] = { +- "format", "executable", "readable", "writable", "segment", "sector", "entry", "macro", +- "db", "dw", "dd", "dq", "rb", "rw", "rd", "rq" +- }; +- +- size_t word; +- +- syntax_rule (0, 0, ";", "\n", '\0', COLOUR_GREY); +- syntax_rule (0, 0, "'", "'", '\\', COLOUR_PINK); +- syntax_rule (0, 0, "\"", "\"", '\\', COLOUR_PINK); +- +- for (word = 0; word != sizeof (instructions) / sizeof (instructions [0]); ++word) { +- syntax_rule (0, 1, instructions [word], separators, '\0', COLOUR_YELLOW); +- } +- +- for (word = 0; word != sizeof (registers) / sizeof (registers [0]); ++word) { +- syntax_rule (0, 1, registers [word], separators, '\0', COLOUR_CYAN); +- } +- +- for (word = 0; word != sizeof (keywords) / sizeof (keywords [0]); ++word) { +- syntax_rule (0, 1, keywords [word], separators, '\0', COLOUR_YELLOW); +- } +- +- syntax_rule (1, 0, "()[]{}", "", '\0', COLOUR_BLUE); +- syntax_rule (1, 0, ".,+-=:;%$<>", "", '\0', COLOUR_CYAN); +- +- syntax_rule (1, 1, "0123456789", separators, '\0', COLOUR_PINK); +- syntax_rule (1, 1, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE); +- syntax_rule (1, 1, "_", separators, '\0', COLOUR_WHITE); +-} +- +-char * syntax_highlight (char * code) { +- static char buffer [4096] = ""; +- static char string [4096] = ""; +- +- size_t select, length, offset; +- +- memset (buffer, 0, sizeof (buffer)); +- memset (string, 0, sizeof (string)); +- +- strcpy (string, code); ++extern size_t syntax_count; + +- for (offset = 0; offset < strlen (string); offset += length) { +- select = syntax_loop (& string [offset], & length); ++extern language_t language; + +- if (select < syntax_count) { +- strncat (buffer, "\003", 1); +- strncat (buffer, syntax_colour [select], 2); +- strncat (buffer, & string [offset], (size_t) length); +- strncat (buffer, "\017", 1); +- } else { +- strncat (buffer, & string [offset], (size_t) length); +- } +- } ++extern syntax_setter_t syntax_functions[]; + +- return (buffer); +-} ++#define SYNTAX_H ++#endif +-- +2.39.2 +