Highlight things
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
5.1KB

  1. /* hl.h
  2. * Copyright 2023 Anon Anonson, Ognjen 'xolatile' Milan Robovic, Emil Williams
  3. * SPDX Identifier: GPL-3.0-only / NO WARRANTY / NO GUARANTEE */
  4. #include <stdio.h>
  5. #include <uthash.h>
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include "chad.h"
  9. #include "regex.h"
  10. // -------------------
  11. // ### Definitions ###
  12. // -------------------
  13. typedef enum {
  14. KEYSYMBOL,
  15. KEYWORD,
  16. MATCH,
  17. REGION
  18. } token_type_t;
  19. typedef void (*attribute_callback_t) (const char * const string,
  20. const int length,
  21. void * const attributes);
  22. typedef struct {
  23. char * key;
  24. attribute_callback_t callback;
  25. UT_hash_handle hh;
  26. } display_t;
  27. typedef struct {
  28. void * attributes;
  29. struct hl_group_t * link;
  30. } hl_group_t;
  31. typedef struct {
  32. hl_group_t * hl;
  33. token_type_t t;
  34. regex_t * syntax;
  35. } token_t;
  36. // GLOBALS
  37. token_t * token_table[1000];
  38. int token_table_top = 0;
  39. display_t * display_table = NULL;
  40. // --------------------------------
  41. // ### Constructors/Destructors ###
  42. // --------------------------------
  43. void new_display_mode(display_t * mode) {
  44. HASH_ADD_STR(display_table,
  45. key,
  46. mode);
  47. }
  48. int free_token(token_t * token) {
  49. free(token->hl);
  50. regex_free(token->syntax);
  51. return 0;
  52. }
  53. int append_token(token_t * token) {
  54. token_table[token_table_top++] = token;
  55. return 0;
  56. }
  57. token_t * new_symbol_token(const char * const c,
  58. hl_group_t * const g) {
  59. char * new_word;
  60. if (is_magic(*c)) {
  61. new_word = (char *)malloc(sizeof(char)*3);
  62. new_word[0] = '\\';
  63. new_word[1] = *c;
  64. new_word[2] = '\00';
  65. } else {
  66. new_word = strdup(c);
  67. }
  68. token_t * mt = (token_t*)malloc(sizeof(token_t));
  69. mt->hl = g;
  70. mt->t = KEYSYMBOL;
  71. mt->syntax = regex_compile(new_word);
  72. append_token(mt);
  73. return mt;
  74. }
  75. int new_symbol_tokens(const char * const * symbols,
  76. hl_group_t * const g) {
  77. int i = 0;
  78. while (*symbols) {
  79. if(new_symbol_token(*symbols, g)) {
  80. ++i;
  81. }
  82. ++symbols;
  83. }
  84. return i;
  85. }
  86. int new_char_tokens(const char * characters,
  87. hl_group_t * const g) {
  88. int i = 0;
  89. char buffer[2] = "";
  90. buffer[1] = '\00';
  91. for(const char * s = characters; *s != '\0'; s++) {
  92. buffer[0] = *s;
  93. if(new_symbol_token(buffer, g)) {
  94. ++i;
  95. }
  96. }
  97. return i;
  98. }
  99. token_t * new_keyword_token(const char * const word,
  100. hl_group_t * const g) {
  101. size_t word_length = strlen(word);
  102. char * new_word = (char*)malloc(word_length + 4 + 1);
  103. memcpy(new_word, "\\<", 2);
  104. memcpy(new_word + 2, word, word_length);
  105. strcpy(new_word + 2 + word_length, "\\>");
  106. token_t * mt = (token_t*)malloc(sizeof(token_t));
  107. mt->hl = g;
  108. mt->t = KEYWORD;
  109. mt->syntax = regex_compile(new_word);
  110. append_token(mt);
  111. return mt;
  112. }
  113. int new_keyword_tokens(const char * const * words,
  114. hl_group_t * const g) {
  115. int i = 0;
  116. while (*words) {
  117. if(new_keyword_token(*words, g)) {
  118. ++i;
  119. }
  120. ++words;
  121. }
  122. return i;
  123. }
  124. token_t * new_token(const char * const word,
  125. const token_type_t t,
  126. hl_group_t * const g) {
  127. switch (t) {
  128. case KEYSYMBOL: {
  129. return new_symbol_token(word, g);
  130. }
  131. case KEYWORD: {
  132. return new_keyword_token(word, g);
  133. }
  134. case MATCH: {
  135. } break;
  136. case REGION: {
  137. } break;
  138. }
  139. return NULL;
  140. }
  141. // --------------------
  142. // ### Highlighting ###
  143. // --------------------
  144. int token_fits(const token_t * const token,
  145. const char * const to,
  146. const int string_offset,
  147. int * match_offset) {
  148. //return regex_match(pattern, to, string_offset, match_offset);
  149. return regex_search(token->syntax, to + string_offset);
  150. }
  151. void render_string(const char * const string,
  152. const char * const mode) {
  153. for (const char * s = string; *s != '\00';) {
  154. int f;
  155. int token_index = 0;
  156. int offset;
  157. for (; token_index < token_table_top; token_index++) {
  158. f = token_fits(token_table[token_index], string, s - string, &offset);
  159. if (f) {
  160. break;
  161. }
  162. }
  163. //
  164. display_t * display;
  165. HASH_FIND_STR(display_table,
  166. mode,
  167. display);
  168. //
  169. if (f) {
  170. for (int i = 0; i < offset; i++) {
  171. display->callback(s + i,
  172. 0,
  173. token_table[token_index]->hl->attributes);
  174. }
  175. display->callback(s + offset,
  176. f,
  177. token_table[token_index]->hl->attributes);
  178. s += f + offset;
  179. } else {
  180. display->callback(s,
  181. 0,
  182. NULL);
  183. ++s;
  184. }
  185. }
  186. }
  187. // -------------------------
  188. // ### Library Mangement ###
  189. // -------------------------
  190. hl_group_t * keyword_hl = NULL;
  191. hl_group_t * preprocessor_hl = NULL;
  192. hl_group_t * symbol_hl = NULL;
  193. int hl_init(void) {
  194. return 0;
  195. }
  196. int hl_deinit(void) {
  197. for (int i = 0; i < token_table_top; i++) {
  198. free_token(token_table[i]);
  199. }
  200. return 0;
  201. }