diff --git a/user/ansi_parser.c b/user/ansi_parser.c index 37d30cf..49450d9 100644 --- a/user/ansi_parser.c +++ b/user/ansi_parser.c @@ -142,6 +142,13 @@ ansi_parser(char newchar) history[HISTORY_LEN-1] = newchar; #endif + // THose should work always, even inside a string + if (newchar == CAN || newchar == SUB) { + // Cancel the active sequence + cs = ansi_start; + return; + } + // Handle simple characters immediately (bypass parser) if (newchar < ' ' && !inside_string) { switch (newchar) { @@ -183,12 +190,6 @@ ansi_parser(char newchar) apars_handle_enq(); return; - // Cancel the active sequence - case CAN: - case SUB: - cs = ansi_start; - return; - default: // Discard all other control codes return; @@ -208,7 +209,7 @@ ansi_parser(char newchar) // The parser -/* #line 212 "user/ansi_parser.c" */ +/* #line 213 "user/ansi_parser.c" */ { const char *_acts; unsigned int _nacts; @@ -398,7 +399,7 @@ execFuncs: while ( _nacts-- > 0 ) { switch ( *_acts++ ) { case 0: -/* #line 188 "user/ansi_parser.rl" */ +/* #line 189 "user/ansi_parser.rl" */ { ansi_warn("Parser error."); apars_show_context(); @@ -407,7 +408,7 @@ execFuncs: } break; case 1: -/* #line 197 "user/ansi_parser.rl" */ +/* #line 198 "user/ansi_parser.rl" */ { if ((*p) != 0) { apars_handle_plainchar((*p)); @@ -415,7 +416,7 @@ execFuncs: } break; case 2: -/* #line 205 "user/ansi_parser.rl" */ +/* #line 206 "user/ansi_parser.rl" */ { // Reset the CSI builder leadchar = NUL; @@ -432,13 +433,13 @@ execFuncs: } break; case 3: -/* #line 220 "user/ansi_parser.rl" */ +/* #line 221 "user/ansi_parser.rl" */ { leadchar = (*p); } break; case 4: -/* #line 224 "user/ansi_parser.rl" */ +/* #line 225 "user/ansi_parser.rl" */ { if (arg_cnt == 0) arg_cnt = 1; // x10 + digit @@ -448,7 +449,7 @@ execFuncs: } break; case 5: -/* #line 232 "user/ansi_parser.rl" */ +/* #line 233 "user/ansi_parser.rl" */ { if (arg_cnt == 0) arg_cnt = 1; // handle case when first arg is empty arg_cnt++; @@ -456,20 +457,20 @@ execFuncs: } break; case 6: -/* #line 238 "user/ansi_parser.rl" */ +/* #line 239 "user/ansi_parser.rl" */ { interchar = (*p); } break; case 7: -/* #line 242 "user/ansi_parser.rl" */ +/* #line 243 "user/ansi_parser.rl" */ { apars_handle_csi(leadchar, arg, arg_cnt, interchar, (*p)); {cs = 1;goto _again;} } break; case 8: -/* #line 254 "user/ansi_parser.rl" */ +/* #line 255 "user/ansi_parser.rl" */ { leadchar = (*p); str_ni = 0; @@ -479,13 +480,13 @@ execFuncs: } break; case 9: -/* #line 262 "user/ansi_parser.rl" */ +/* #line 263 "user/ansi_parser.rl" */ { string_buffer[str_ni++] = (*p); } break; case 10: -/* #line 266 "user/ansi_parser.rl" */ +/* #line 267 "user/ansi_parser.rl" */ { inside_string = false; string_buffer[str_ni++] = '\0'; @@ -494,41 +495,41 @@ execFuncs: } break; case 11: -/* #line 279 "user/ansi_parser.rl" */ +/* #line 280 "user/ansi_parser.rl" */ { apars_handle_hash_cmd((*p)); {cs = 1;goto _again;} } break; case 12: -/* #line 284 "user/ansi_parser.rl" */ +/* #line 285 "user/ansi_parser.rl" */ { apars_handle_short_cmd((*p)); {cs = 1;goto _again;} } break; case 13: -/* #line 289 "user/ansi_parser.rl" */ +/* #line 290 "user/ansi_parser.rl" */ { apars_handle_space_cmd((*p)); {cs = 1;goto _again;} } break; case 14: -/* #line 296 "user/ansi_parser.rl" */ +/* #line 297 "user/ansi_parser.rl" */ { leadchar = (*p); {cs = 10;goto _again;} } break; case 15: -/* #line 301 "user/ansi_parser.rl" */ +/* #line 302 "user/ansi_parser.rl" */ { apars_handle_chs_designate(leadchar, (*p)); {cs = 1;goto _again;} } break; -/* #line 532 "user/ansi_parser.c" */ +/* #line 533 "user/ansi_parser.c" */ } } goto _again; @@ -546,7 +547,7 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -/* #line 188 "user/ansi_parser.rl" */ +/* #line 189 "user/ansi_parser.rl" */ { ansi_warn("Parser error."); apars_show_context(); @@ -556,7 +557,7 @@ _again: goto _again;} } break; -/* #line 560 "user/ansi_parser.c" */ +/* #line 561 "user/ansi_parser.c" */ } } } @@ -564,6 +565,6 @@ goto _again;} _out: {} } -/* #line 324 "user/ansi_parser.rl" */ +/* #line 325 "user/ansi_parser.rl" */ } diff --git a/user/ansi_parser.rl b/user/ansi_parser.rl index c2042c7..cd1ec26 100644 --- a/user/ansi_parser.rl +++ b/user/ansi_parser.rl @@ -111,6 +111,13 @@ ansi_parser(char newchar) history[HISTORY_LEN-1] = newchar; #endif + // THose should work always, even inside a string + if (newchar == CAN || newchar == SUB) { + // Cancel the active sequence + cs = ansi_start; + return; + } + // Handle simple characters immediately (bypass parser) if (newchar < ' ' && !inside_string) { switch (newchar) { @@ -152,12 +159,6 @@ ansi_parser(char newchar) apars_handle_enq(); return; - // Cancel the active sequence - case CAN: - case SUB: - cs = ansi_start; - return; - default: // Discard all other control codes return; diff --git a/user/ansi_parser_callbacks.c b/user/ansi_parser_callbacks.c index fa6173f..37c9914 100644 --- a/user/ansi_parser_callbacks.c +++ b/user/ansi_parser_callbacks.c @@ -12,6 +12,13 @@ #include "uart_buffer.h" #include "screen.h" +volatile bool enquiry_suppressed = false; +ETSTimer enqTimer; +void ICACHE_FLASH_ATTR enqTimerCb(void *unused) +{ + enquiry_suppressed = false; +} + /** * Send a response to UART0 * @param str @@ -37,8 +44,16 @@ apars_handle_bel(void) void ICACHE_FLASH_ATTR apars_handle_enq(void) { + if (enquiry_suppressed) return; + // version encased in SOS and ST apars_respond("\x1bXESPTerm " FIRMWARE_VERSION "\x1b\\"); + + // Throttle enquiry - this is a single-character-invoked response, + // so it tends to happen randomly when throwing garbage at the ESP. + // We don't want to fill the output buffer with dozens of enquiry responses + enquiry_suppressed = true; + TIMER_START(&enqTimer, enqTimerCb, 500, 0); } void ICACHE_FLASH_ATTR diff --git a/user/apars_pm.c b/user/apars_pm.c new file mode 100644 index 0000000..6defb03 --- /dev/null +++ b/user/apars_pm.c @@ -0,0 +1,34 @@ +// +// Created by MightyPork on 2017/08/20. +// +// Handle privacy messages +// PM Pt ST +// (PM = ESC ^) +// +// Those are used for device-to-device communication. +// They were not used for anything in the original VT100 and are not +// used by Xterm or any other common emulator, but they should be safely discarded. +// + +#include +#include "apars_pm.h" +#include "ansi_parser_callbacks.h" +#include "screen.h" +#include "apars_logging.h" + +/** + * Helper function to parse incoming DCS (Device Control String) + * @param buffer - the DCS body (after DCS and before ST) + */ +void ICACHE_FLASH_ATTR +apars_handle_pm(const char *buffer) +{ + size_t len = strlen(buffer); + if (false) { + // + } + else { + ansi_warn("Bad DCS: %s", buffer); + apars_show_context(); + } +} diff --git a/user/apars_pm.h b/user/apars_pm.h new file mode 100644 index 0000000..92f7b44 --- /dev/null +++ b/user/apars_pm.h @@ -0,0 +1,10 @@ +// +// Created by MightyPork on 2017/08/20. +// + +#ifndef ESP_VT100_FIRMWARE_APARS_PM_H +#define ESP_VT100_FIRMWARE_APARS_PM_H + +void apars_handle_pm(const char *buffer); + +#endif //ESP_VT100_FIRMWARE_APARS_PM_H diff --git a/user/apars_string.c b/user/apars_string.c index dbd2382..a4a8781 100644 --- a/user/apars_string.c +++ b/user/apars_string.c @@ -17,6 +17,7 @@ #include "apars_logging.h" #include "ansi_parser_callbacks.h" #include "screen.h" +#include "apars_pm.h" // ----- Generic String cmd - disambiguation ----- @@ -37,6 +38,7 @@ apars_handle_string_cmd(char leadchar, char *buffer) break; case '^': // PM - Privacy Message + apars_handle_pm(buffer); break; case '_': // APC - Application Program Command