--- /dev/null
+#include <assert.h>
+#include <string.h>
+
+typedef struct {
+ int in;
+ char input;
+ int to;
+} delta_t;
+
+typedef struct {
+ int in;
+ int to;
+} offshoot_t;
+
+typedef struct {
+ char * str;
+ std::vector<delta_t> delta_table;
+ std::vector<offshoot_t> catch_table;
+ int accepting_state;
+} regex_t;
+
+#define HALT_AND_CATCH_FIRE -1
+
+#define HOOK_ALL(from, str, to) do { \
+ for (char * s = str; *s != '\00'; s++) { \
+ reg.delta_table.push_back( \
+ delta_t{state + from, *s, state + to} \
+ ); \
+ } \
+ if (do_catch) { \
+ reg.catch_table.push_back( \
+ {state + from, state + to} \
+ ); \
+ } \
+} while (0)
+
+#define EAT(n) do { \
+ s += n; \
+} while (0)
+
+bool is_quantifier(const char c){
+ for (const char * s = "+*?"; *s != '\00'; s++) {
+ if (*s == c) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+int escape_1_to_1(const char c, char * whitelist) {
+ switch(c) {
+ case 't': {
+ strcat(whitelist, "\t");
+ } return 1;
+ case 'n': {
+ strcat(whitelist, "\n");
+ } return 1;
+ case 'r': {
+ strcat(whitelist, "\r");
+ } return 1;
+ case 'b': {
+ strcat(whitelist, "\b");
+ } return 1;
+ case '[': {
+ strcat(whitelist, "[");
+ } return 1;
+ case ']': {
+ strcat(whitelist, "]");
+ } return 1;
+ case '.': {
+ strcat(whitelist, ".");
+ } return 1;
+ case '?': {
+ strcat(whitelist, "?");
+ } return 1;
+ case '+': {
+ strcat(whitelist, "+");
+ } return 1;
+ case '*': {
+ strcat(whitelist, "*");
+ } return 1;
+ case '\\': {
+ strcat(whitelist, "\\");
+ } return 1;
+ }
+
+ return 0;
+}
+
+int escape_1_to_N(const char c, char * whitelist) {
+ switch(c) {
+ case 'i': {
+ const char identifier_chars[] = "@0123456789_\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
+ strcpy(whitelist, identifier_chars);
+ return sizeof(identifier_chars)-1;
+ };
+ case 'I': {
+ const char identifier_chars[] = "@_\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
+ strcpy(whitelist, identifier_chars);
+ return sizeof(identifier_chars)-1;
+ };
+ case 'k': {
+ const char keyword_chars[] = "@0123456789_\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
+ strcpy(whitelist, keyword_chars);
+ return sizeof(keyword_chars)-1;
+ };
+ case 'K': {
+ const char keyword_chars[] = "@_\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
+ strcpy(whitelist, keyword_chars);
+ return sizeof(keyword_chars)-1;
+ };
+ case 'f': {
+ const char filename_chars[] = "@0123456789/.-_+,#$%~=";
+ strcpy(whitelist, keyword_chars);
+ return sizeof(keyword_chars)-1;
+ };
+ case 'F': {
+ const char filename_chars[] = "@/.-_+,#$%~=";
+ strcpy(whitelist, keyword_chars);
+ return sizeof(keyword_chars)-1;
+ };
+ case 'p': {
+ const char printable_chars[] = "@\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
+ strcpy(whitelist, printable_chars);
+ return sizeof(printable_chars)-1;
+ };
+ case 'P': {
+ const char printable_chars[] = "@\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
+ strcpy(whitelist, printable_chars);
+ return sizeof(printable_chars)-1;
+ };
+ case 's': {
+ const char whitespace_chars[] = " \t\v\n";
+ strcpy(whitelist, whitespace_chars);
+ return sizeof(whitespace_chars)-1;
+ };
+ case 'd': {
+ const char digit_chars[] = "0123456789";
+ strcpy(whitelist, digit_chars);
+ return sizeof(digit_chars)-1;
+ };
+ case 'x': {
+ const char hex_chars[] = "0123456789abcdefABCDEF";
+ strcpy(whitelist, hex_chars);
+ return sizeof(hex_chars)-1;
+ };
+ case 'o': {
+ const char oct_chars[] = "01234567";
+ strcpy(whitelist, oct_chars);
+ return sizeof(oct_chars)-1;
+ };
+ case 'w': {
+ const char word_chars[] = "0123456789abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ_";
+ strcpy(whitelist, word_chars);
+ return sizeof(word_chars)-1;
+ };
+ case 'h': {
+ const char very_word_chars[] = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ_";
+ strcpy(whitelist, very_word_chars);
+ return sizeof(very_word_chars)-1;
+ };
+ case 'a': {
+ const char alpha_chars[] = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ";
+ strcpy(whitelist, alpha_chars);
+ return sizeof(alpha_chars)-1;
+ };
+ case 'l': {
+ const char lower_alpha_chars[] = "abcdefghijklmnopqrstuwxyz";
+ strcpy(whitelist, lower_alpha_chars);
+ return sizeof(lower_alpha_chars)-1;
+ };
+ case 'u': {
+ const char upper_alpha_chars[] = "ABCDEFGHIJKLMNOPQRSTUWXYZ";
+ strcpy(whitelist, upper_alpha_chars);
+ return sizeof(upper_alpha_chars)-1;
+ };
+ }
+
+ return 0;
+}
+
+int compile_range(const char * const range,
+ char * whitelist) {
+ assert(range[0] == '[' && "Not a range.");
+
+ int r = 0;
+ const char * s;
+ for (s = range+1; *s != ']'; s++) {
+ assert(*s != '\00' && "Unclosed range.");
+ char c = *s;
+ if (escape_1_to_1(c, whitelist)
+ || escape_1_to_N(c, whitelist)) {
+ ;
+ } else if (*(s+1) == '-') {
+ char end = *(s+2);
+ assert(c < end && "Endless range.");
+ for (char cc = c; cc < end+1; cc++) {
+ strncat(whitelist, &cc, 1);
+ strncat(whitelist, "\00", 1);
+ }
+ s += 2;
+ } else {
+ ++r;
+ strncat(whitelist, &c, 1);
+ strncat(whitelist, "\00", 1);
+ }
+ }
+
+ return ((s - range) + 1);
+}
+
+regex_t * regex_compile(const char * const pattern) {
+ regex_t * r = new regex_t;
+ regex_t ® = *r;
+ reg.str = strdup(pattern);
+
+ int state = 0;
+
+ char whitelist[64];
+ bool do_catch;
+ for (const char * s = pattern; *s != '\00';) {
+ // Get token
+ assert(!is_quantifier(*pattern) && "Pattern starts with quantifier.");
+ whitelist[0] = '\00';
+ do_catch = false;
+ switch (*s) {
+ case '.': {
+ do_catch = true;
+ } break;
+ case '\\': {
+ EAT(1);
+ if(escape_1_to_1(*s, whitelist)
+ || escape_1_to_N(*s, whitelist)){
+ ;
+ } else {
+ assert(!"Unknown escape.");
+ }
+ } break;
+ case '[': {
+ EAT(compile_range(s, whitelist)-1);
+ } break;
+ default: {
+ whitelist[0] = *s;
+ whitelist[1] = '\00';
+ } break;
+ }
+
+ EAT(1);
+
+ // Quantifier
+ switch (*s) {
+ case '?': {
+ HOOK_ALL(0, whitelist, +1);
+ EAT(1);
+ } break;
+ case '*': {
+ HOOK_ALL(0, whitelist, 0);
+ EAT(1);
+ } break;
+ case '+': {
+ HOOK_ALL(0, whitelist, +1);
+ state += 1;
+ HOOK_ALL(0, whitelist, 0);
+ EAT(1);
+ } break;
+ default: { // Literal
+ HOOK_ALL(0, whitelist, +1);
+ state += 1;
+ } break;
+ }
+ }
+
+ reg.accepting_state = state;
+
+ return r;
+}
+
+inline bool catch_(const regex_t * regex,
+ int & state) {
+
+ const regex_t ® = *regex;
+ for (int i = 0; i < reg.catch_table.size(); i++){
+ if (reg.catch_table[i].in == state) {
+ state = reg.catch_table[i].to;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool regex_assert(const regex_t * const regex,
+ const char * const string,
+ int state) {
+
+ const regex_t ® = *regex;
+ for (const char * s = string; *s != '\00'; s++) {
+ // delta
+ for (int i = 0; i < reg.delta_table.size(); i++) {
+ if ((reg.delta_table[i].in == state)
+ && (reg.delta_table[i].input == *s)) {
+ if(regex_assert(regex, s+1, reg.delta_table[i].to)){
+ return true;
+ }
+ }
+ }
+
+ if (catch_(regex, state)) {
+ continue;
+ }
+
+ return false;
+ }
+
+ return (state == regex->accepting_state);
+}
+
+bool regex_search( regex_t * regex,
+ const char * const string) {
+
+ if (regex == NULL) {
+ return false;
+ }
+ if (string == NULL) {
+ return true;
+ }
+
+ return regex_assert(regex, string, 0);
+}
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-typedef struct {
- char * data;
- size_t element_size;
- size_t element_count;
-} vector_t;
-
-typedef struct {
- int a;
- int b;
- char * c;
-} example_t;
-
-extern void vector_push(vector_t * vector,
- void * data);
-
-extern void vector_pop(vector_t * vector);
-
-extern void * vector_get(vector_t * vector,
- size_t element);
-
-extern void vector_free(vector_t * vector);
-
-extern void example_print(example_t * example);
-
-// Add only 1 new element to vector.
-void vector_push(vector_t * vector,
- void * data) {
- ++vector->element_count;
-
- vector->data = realloc(vector->data,
- vector->element_size * vector->element_count);
-
- if (vector->data == NULL) {
- // Handle or output error somehow?
- puts("vector_push");
- exit(EXIT_FAILURE);
- }
-
- memcpy(&vector->data[(vector->element_count - 1) * vector->element_size],
- data,
- vector->element_size);
-}
-
-void vector_pop(vector_t * vector) {
- (void) vector;
-}
-
-void * vector_get(vector_t * vector,
- size_t element) {
- if (element >= vector->element_count) {
- // Handle or output error somehow?
- puts("vector_get");
- exit(EXIT_FAILURE);
- }
-
- return &vector->data[vector->element_size * element];
-}
-
-void vector_free(vector_t * vector) {
- free(vector->data);
-}
-
-void example_print(example_t * example) {
- printf("a : %+i\n", example->a);
- printf("b : %+i\n", example->b);
- printf("c : %2s\n", example->c);
-}
-
-int main(void) {
- vector_t vector;
-
- example_t x = { 1, -1, "A" },
- y = { 2, -2, "B" },
- z = { 3, -3, "C" };
-
- vector.data = NULL; // Important to NULL it.
- vector.element_size = sizeof(example_t); // Important to type it.
- vector.element_count = 0UL; // Important to 0 it.
-
- vector_push(&vector, &x);
- vector_push(&vector, &y);
- vector_push(&vector, &z);
-
- example_print(vector_get(&vector, 0));
- example_print(vector_get(&vector, 1));
- example_print(vector_get(&vector, 2));
-
- vector_free(&vector);
-
- return (EXIT_SUCCESS);
-}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+ char * data;
+ size_t element_size;
+ size_t element_count;
+} vector_t;
+
+typedef struct {
+ int a;
+ int b;
+ char * c;
+} example_t;
+
+extern void vector_push(vector_t * vector,
+ void * data);
+
+extern void vector_pop(vector_t * vector);
+
+extern void * vector_get(vector_t * vector,
+ size_t element);
+
+extern void vector_free(vector_t * vector);
+
+extern void example_print(example_t * example);
+
+// Add only 1 new element to vector.
+void vector_push(vector_t * vector,
+ void * data) {
+ ++vector->element_count;
+
+ vector->data = realloc(vector->data,
+ vector->element_size * vector->element_count);
+
+ if (vector->data == NULL) {
+ // Handle or output error somehow?
+ puts("vector_push");
+ exit(EXIT_FAILURE);
+ }
+
+ memcpy(&vector->data[(vector->element_count - 1) * vector->element_size],
+ data,
+ vector->element_size);
+}
+
+void vector_pop(vector_t * vector) {
+ (void) vector;
+}
+
+void * vector_get(vector_t * vector,
+ size_t element) {
+ if (element >= vector->element_count) {
+ // Handle or output error somehow?
+ puts("vector_get");
+ exit(EXIT_FAILURE);
+ }
+
+ return &vector->data[vector->element_size * element];
+}
+
+void vector_free(vector_t * vector) {
+ free(vector->data);
+}
+
+void example_print(example_t * example) {
+ printf("a : %+i\n", example->a);
+ printf("b : %+i\n", example->b);
+ printf("c : %2s\n", example->c);
+}
+
+int main(void) {
+ vector_t vector;
+
+ example_t x = { 1, -1, "A" },
+ y = { 2, -2, "B" },
+ z = { 3, -3, "C" };
+
+ vector.data = NULL; // Important to NULL it.
+ vector.element_size = sizeof(example_t); // Important to type it.
+ vector.element_count = 0UL; // Important to 0 it.
+
+ vector_push(&vector, &x);
+ vector_push(&vector, &y);
+ vector_push(&vector, &z);
+
+ example_print(vector_get(&vector, 0));
+ example_print(vector_get(&vector, 1));
+ example_print(vector_get(&vector, 2));
+
+ vector_free(&vector);
+
+ return (EXIT_SUCCESS);
+}