No scoring code is changed, so this probably needs more work to be fully
functional.
| ... | ... |
@@ -11,19 +11,83 @@ |
| 11 | 11 |
|
| 12 | 12 |
#include "../config.h" |
| 13 | 13 |
|
| 14 |
+const char *ignore_escapes(const char *haystack) {
|
|
| 15 |
+ enum {
|
|
| 16 |
+ state_default, |
|
| 17 |
+ state_escaped, |
|
| 18 |
+ state_in_csi, |
|
| 19 |
+ state_start_osc, |
|
| 20 |
+ state_in_osc, |
|
| 21 |
+ state_ignore_next, |
|
| 22 |
+ } state = state_default; |
|
| 23 |
+ do switch (state) {
|
|
| 24 |
+ case state_default: switch (*haystack) {
|
|
| 25 |
+ case '\x1b': |
|
| 26 |
+ state = state_escaped; break; |
|
| 27 |
+ case '\x7': |
|
| 28 |
+ return ++haystack; |
|
| 29 |
+ default: |
|
| 30 |
+ return haystack; |
|
| 31 |
+ }; break; |
|
| 32 |
+ case state_escaped: switch (*haystack) {
|
|
| 33 |
+ case '[': |
|
| 34 |
+ state = state_in_csi; break; |
|
| 35 |
+ case ']': |
|
| 36 |
+ state = state_start_osc; break; |
|
| 37 |
+ case '%': case '(': case ')': case '#':
|
|
| 38 |
+ case '0': case '3': case '5': case '6': |
|
| 39 |
+ state = state_ignore_next; break; |
|
| 40 |
+ case '<': case '=': case '>': case '\x7': |
|
| 41 |
+ case '1': case '2': case '7': case '8': |
|
| 42 |
+ case 'c': case 's': case 'u': |
|
| 43 |
+ case 'A': case 'B': case 'C': case 'D': case 'E': |
|
| 44 |
+ case 'H': case 'I': case 'J': case 'K': case 'M': |
|
| 45 |
+ case 'N': case 'O': case 'S': case 'T': case 'Z': |
|
| 46 |
+ return ++haystack; |
|
| 47 |
+ default: |
|
| 48 |
+ return haystack; |
|
| 49 |
+ }; break; |
|
| 50 |
+ case state_in_csi: switch (*haystack) {
|
|
| 51 |
+ case ';': case '?': |
|
| 52 |
+ case '0': case '1': case '2': case '3': case '4': |
|
| 53 |
+ case '5': case '6': case '7': case '8': case '9': |
|
| 54 |
+ break; |
|
| 55 |
+ default: |
|
| 56 |
+ return ++haystack; |
|
| 57 |
+ }; break; |
|
| 58 |
+ case state_start_osc: switch (*haystack) {
|
|
| 59 |
+ case '0': case '1': case '2': case '3': case '4': |
|
| 60 |
+ case '5': case '6': case '7': case '8': case '9': |
|
| 61 |
+ state = state_in_osc; break; |
|
| 62 |
+ default: |
|
| 63 |
+ return ++haystack; |
|
| 64 |
+ }; break; |
|
| 65 |
+ case state_in_osc: switch (*haystack) {
|
|
| 66 |
+ case '\x7': |
|
| 67 |
+ return ++haystack; |
|
| 68 |
+ case '\x1b': |
|
| 69 |
+ state = state_ignore_next; break; |
|
| 70 |
+ }; break; |
|
| 71 |
+ case state_ignore_next: |
|
| 72 |
+ return ++haystack; |
|
| 73 |
+ } while (*++haystack); |
|
| 74 |
+ return haystack; |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 14 | 77 |
char *strcasechr(const char *s, char c) {
|
| 15 | 78 |
const char accept[3] = {c, toupper(c), 0};
|
| 16 | 79 |
return strpbrk(s, accept); |
| 17 | 80 |
} |
| 18 | 81 |
|
| 19 | 82 |
int has_match(const char *needle, const char *haystack) {
|
| 83 |
+ haystack = ignore_escapes(haystack); |
|
| 20 | 84 |
while (*needle) {
|
| 21 | 85 |
char nch = *needle++; |
| 22 | 86 |
|
| 23 | 87 |
if (!(haystack = strcasechr(haystack, nch))) {
|
| 24 | 88 |
return 0; |
| 25 | 89 |
} |
| 26 |
- haystack++; |
|
| 90 |
+ haystack = ignore_escapes(++haystack); |
|
| 27 | 91 |
} |
| 28 | 92 |
return 1; |
| 29 | 93 |
} |