From 9260b4c9675ca59f7935c1273c2df93f3ec4ba9f Mon Sep 17 00:00:00 2001 From: Alden Hart Date: Fri, 2 Sep 2016 12:13:29 -0400 Subject: [PATCH] Checkpoint $ej work --- g2core/asciitable.txt | 131 +++++++++++++++++++++-------------------- g2core/config.cpp | 10 ++-- g2core/config.h | 18 +++--- g2core/config_app.cpp | 22 ++++--- g2core/controller.cpp | 30 ++++++---- g2core/controller.h | 10 ++-- g2core/g2core.cppproj | 5 +- g2core/g2core_info.h | 2 +- g2core/json_parser.cpp | 24 +++++++- g2core/json_parser.h | 14 +++-- g2core/text_parser.cpp | 8 +-- 11 files changed, 153 insertions(+), 121 deletions(-) diff --git a/g2core/asciitable.txt b/g2core/asciitable.txt index 87e12bb6..b4a851e5 100755 --- a/g2core/asciitable.txt +++ b/g2core/asciitable.txt @@ -1,53 +1,53 @@ Decimal Octal Hex Binary Value ------- ----- --- ------ ----- - 000 000 000 00000000 NUL (Null char.) - 001 001 001 00000001 SOH (Start of Header) - 002 002 002 00000010 STX (Start of Text) - 003 003 003 00000011 ETX (End of Text) - 004 004 004 00000100 EOT (End of Transmission) - 005 005 005 00000101 ENQ (Enquiry) - 006 006 006 00000110 ACK (Acknowledgment) - 007 007 007 00000111 BEL (Bell) - 008 010 008 00001000 BS (Backspace) - 009 011 009 00001001 HT (Horizontal Tab) - 010 012 00A 00001010 LF (Line Feed) - 011 013 00B 00001011 VT (Vertical Tab) - 012 014 00C 00001100 FF (Form Feed) - 013 015 00D 00001101 CR (Carriage Return) - 014 016 00E 00001110 SO (Shift Out) - 015 017 00F 00001111 SI (Shift In) - 016 020 010 00010000 DLE (Data Link Escape) - 017 021 011 00010001 DC1 (XON) (Device Control 1) - 018 022 012 00010010 DC2 (Device Control 2) - 019 023 013 00010011 DC3 (XOFF)(Device Control 3) - 020 024 014 00010100 DC4 (Device Control 4) - 021 025 015 00010101 NAK (Negative Acknowledgemnt) - 022 026 016 00010110 SYN (Synchronous Idle) - 023 027 017 00010111 ETB (End of Trans. Block) - 024 030 018 00011000 CAN (Cancel) - 025 031 019 00011001 EM (End of Medium) - 026 032 01A 00011010 SUB (Substitute) - 027 033 01B 00011011 ESC (Escape) - 028 034 01C 00011100 FS (File Separator) - 029 035 01D 00011101 GS (Group Separator) - 030 036 01E 00011110 RS (Reqst to Send)(Rec. Sep.) - 031 037 01F 00011111 US (Unit Separator) - 032 040 020 00100000 SP (Space) - 033 041 021 00100001 ! (exclamation mark) - 034 042 022 00100010 " (double quote) - 035 043 023 00100011 # (number sign) - 036 044 024 00100100 $ (dollar sign) - 037 045 025 00100101 % (percent) - 038 046 026 00100110 & (ampersand) - 039 047 027 00100111 ' (single quote) - 040 050 028 00101000 ( (left/open parenthesis) - 041 051 029 00101001 ) (right/closing parenth.) - 042 052 02A 00101010 * (asterisk) - 043 053 02B 00101011 + (plus) - 044 054 02C 00101100 , (comma) - 045 055 02D 00101101 - (minus or dash) - 046 056 02E 00101110 . (dot) - 047 057 02F 00101111 / (forward slash) + 000 000 000 00000000 NUL (Null char.) + 001 001 001 00000001 SOH (Start of Header) + 002 002 002 00000010 STX (Start of Text) + 003 003 003 00000011 ETX (End of Text) + 004 004 004 00000100 EOT (End of Transmission) + 005 005 005 00000101 ENQ (Enquiry) + 006 006 006 00000110 ACK (Acknowledgment) + 007 007 007 00000111 BEL (Bell) + 008 010 008 00001000 BS (Backspace) + 009 011 009 00001001 HT (Horizontal Tab) + 010 012 00A 00001010 LF (Line Feed) + 011 013 00B 00001011 VT (Vertical Tab) + 012 014 00C 00001100 FF (Form Feed) + 013 015 00D 00001101 CR (Carriage Return) + 014 016 00E 00001110 SO (Shift Out) + 015 017 00F 00001111 SI (Shift In) + 016 020 010 00010000 DLE (Data Link Escape) + 017 021 011 00010001 DC1 (XON) (Device Control 1) + 018 022 012 00010010 DC2 (Device Control 2) + 019 023 013 00010011 DC3 (XOFF)(Device Control 3) + 020 024 014 00010100 DC4 (Device Control 4) + 021 025 015 00010101 NAK (Negative Acknowledgemnt) + 022 026 016 00010110 SYN (Synchronous Idle) + 023 027 017 00010111 ETB (End of Trans. Block) + 024 030 018 00011000 CAN (Cancel) + 025 031 019 00011001 EM (End of Medium) + 026 032 01A 00011010 SUB (Substitute) + 027 033 01B 00011011 ESC (Escape) + 028 034 01C 00011100 FS (File Separator) + 029 035 01D 00011101 GS (Group Separator) + 030 036 01E 00011110 RS (Reqst to Send)(Rec. Sep.) + 031 037 01F 00011111 US (Unit Separator) + 032 040 020 00100000 SP (Space) + 033 041 021 00100001 ! (exclamation mark) + 034 042 022 00100010 " (double quote) + 035 043 023 00100011 # (number sign) + 036 044 024 00100100 $ (dollar sign) + 037 045 025 00100101 % (percent) + 038 046 026 00100110 & (ampersand) + 039 047 027 00100111 ' (single quote) + 040 050 028 00101000 ( (left/open parenthesis) + 041 051 029 00101001 ) (right/closing parenth.) + 042 052 02A 00101010 * (asterisk) + 043 053 02B 00101011 + (plus) + 044 054 02C 00101100 , (comma) + 045 055 02D 00101101 - (minus or dash) + 046 056 02E 00101110 . (dot) + 047 057 02F 00101111 / (forward slash) 048 060 030 00110000 0 049 061 031 00110001 1 050 062 032 00110010 2 @@ -58,13 +58,13 @@ Decimal Octal Hex Binary Value 055 067 037 00110111 7 056 070 038 00111000 8 057 071 039 00111001 9 - 058 072 03A 00111010 : (colon) - 059 073 03B 00111011 ; (semi-colon) - 060 074 03C 00111100 < (less than) - 061 075 03D 00111101 = (equal sign) - 062 076 03E 00111110 > (greater than) - 063 077 03F 00111111 ? (question mark) - 064 100 040 01000000 @ (AT symbol) + 058 072 03A 00111010 : (colon) + 059 073 03B 00111011 ; (semi-colon) + 060 074 03C 00111100 < (less than) + 061 075 03D 00111101 = (equal sign) + 062 076 03E 00111110 > (greater than) + 063 077 03F 00111111 ? (question mark) + 064 100 040 01000000 @ (AT symbol) 065 101 041 01000001 A 066 102 042 01000010 B 067 103 043 01000011 C @@ -91,11 +91,11 @@ Decimal Octal Hex Binary Value 088 130 058 01011000 X 089 131 059 01011001 Y 090 132 05A 01011010 Z - 091 133 05B 01011011 [ (left/opening bracket) - 092 134 05C 01011100 \ (back slash) - 093 135 05D 01011101 ] (right/closing bracket) - 094 136 05E 01011110 ^ (caret/circumflex) - 095 137 05F 01011111 _ (underscore) + 091 133 05B 01011011 [ (left/opening bracket) + 092 134 05C 01011100 \ (back slash) + 093 135 05D 01011101 ] (right/closing bracket) + 094 136 05E 01011110 ^ (caret/circumflex) + 095 137 05F 01011111 _ (underscore) 096 140 060 01100000 ` 097 141 061 01100001 a 098 142 062 01100010 b @@ -123,8 +123,9 @@ Decimal Octal Hex Binary Value 120 170 078 01111000 x 121 171 079 01111001 y 122 172 07A 01111010 z - 123 173 07B 01111011 { (left/opening brace) - 124 174 07C 01111100 | (vertical bar) - 125 175 07D 01111101 } (right/closing brace) - 126 176 07E 01111110 ~ (tilde) - 127 177 07F 01111111 DEL (delet \ No newline at end of file + 123 173 07B 01111011 { (left/opening brace) + 124 174 07C 01111100 | (vertical bar) + 125 175 07D 01111101 } (right/closing brace) + 126 176 07E 01111110 ~ (tilde) + 127 177 07F 01111111 DEL (delete) + diff --git a/g2core/config.cpp b/g2core/config.cpp index c12608e0..d2203fd3 100755 --- a/g2core/config.cpp +++ b/g2core/config.cpp @@ -88,14 +88,12 @@ void nv_print(nvObj_t *nv) stat_t nv_persist(nvObj_t *nv) { -#ifndef __DISABLE_PERSISTENCE // cutout for faster simulation in test if (nv_index_lt_groups(nv->index) == false) { return(STAT_INTERNAL_RANGE_ERROR); } if (GET_TABLE_BYTE(flags) & F_PERSIST) { return(write_persistent_value(nv)); } -#endif return (STAT_OK); } @@ -115,7 +113,7 @@ void config_init() { nvObj_t *nv = nv_reset_nv_list(); config_init_assertions(); - cs.comm_mode = JSON_MODE; // initial value until persistence is read + js.json_mode = JSON_MODE; // initial value until persistence is read _set_defa(nv, false); rpt_print_loading_configs_message(); } @@ -384,7 +382,7 @@ stat_t get_grp(nvObj_t *nv) stat_t set_grp(nvObj_t *nv) { - if (cs.comm_mode == TEXT_MODE) { + if (js.json_mode == TEXT_MODE) { return (STAT_UNRECOGNIZED_NAME); } for (uint8_t i=0; i 255 indexed o #define NO_MATCH (index_t)0xFFFF typedef enum { - TEXT_MODE = 0, // text command line mode - JSON_MODE, // strict JSON construction - JSON_MODE_RELAXED // relaxed JSON construction (future) -} tgCommunicationsMode; + TEXT_MODE = 0, // sticky text mode + JSON_MODE, // sticky JSON mode + AUTO_MODE // auto-configure communications mode +} commMode; typedef enum { FLOW_CONTROL_OFF = 0, // flow control disabled @@ -310,11 +310,11 @@ stat_t nv_persist(nvObj_t *nv); // main entry point for persistence // helpers uint8_t nv_get_type(nvObj_t *nv); index_t nv_get_index(const char *group, const char *token); -index_t nv_index_max(void); // (see config_app.c) -uint8_t nv_index_is_single(index_t index); // (see config_app.c) -uint8_t nv_index_is_group(index_t index); // (see config_app.c) -uint8_t nv_index_lt_groups(index_t index); // (see config_app.c) -uint8_t nv_group_is_prefixed(char *group); +index_t nv_index_max(void); // (see config_app.c) +bool nv_index_is_single(index_t index); // (see config_app.c) +bool nv_index_is_group(index_t index); // (see config_app.c) +bool nv_index_lt_groups(index_t index); // (see config_app.c) +bool nv_group_is_prefixed(char *group); // generic internal functions and accessors stat_t set_nul(nvObj_t *nv); // set nothing diff --git a/g2core/config_app.cpp b/g2core/config_app.cpp index 7f3cd357..156aac79 100755 --- a/g2core/config_app.cpp +++ b/g2core/config_app.cpp @@ -619,7 +619,7 @@ const cfgItem_t cfgArray[] = { #ifdef __TEXT_MODE { "sys","tv", _fipn, 0, tx_print_tv, get_ui8, set_01, (float *)&txt.text_verbosity, TEXT_VERBOSITY }, #endif - { "sys","ej", _fipn, 0, js_print_ej, get_ui8, set_01, (float *)&cs.comm_mode, COMM_MODE }, + { "sys","ej", _fipn, 0, js_print_ej, get_ui8, json_set_ej,(float *)&cs.comm_mode, COMM_MODE }, { "sys","jv", _fipn, 0, js_print_jv, get_ui8, json_set_jv,(float *)&js.json_verbosity, JSON_VERBOSITY }, { "sys","qv", _fipn, 0, qr_print_qv, get_ui8, set_0123, (float *)&qr.queue_report_verbosity, QUEUE_REPORT_VERBOSITY }, { "sys","sv", _fipn, 0, sr_print_sv, get_ui8, set_012, (float *)&sr.status_report_verbosity,STATUS_REPORT_VERBOSITY }, @@ -945,10 +945,10 @@ const cfgItem_t cfgArray[] = { #define NV_INDEX_START_UBER_GROUPS (NV_INDEX_MAX - NV_COUNT_UBER_GROUPS) /* */ -index_t nv_index_max() { return ( NV_INDEX_MAX );} -uint8_t nv_index_is_single(index_t index) { return ((index <= NV_INDEX_END_SINGLES) ? true : false);} -uint8_t nv_index_is_group(index_t index) { return (((index >= NV_INDEX_START_GROUPS) && (index < NV_INDEX_START_UBER_GROUPS)) ? true : false);} -uint8_t nv_index_lt_groups(index_t index) { return ((index <= NV_INDEX_START_GROUPS) ? true : false);} +index_t nv_index_max() { return ( NV_INDEX_MAX );} +bool nv_index_is_single(index_t index) { return ((index <= NV_INDEX_END_SINGLES) ? true : false);} +bool nv_index_is_group(index_t index) { return (((index >= NV_INDEX_START_GROUPS) && (index < NV_INDEX_START_UBER_GROUPS)) ? true : false);} +bool nv_index_lt_groups(index_t index) { return ((index <= NV_INDEX_START_GROUPS) ? true : false);} /***** APPLICATION SPECIFIC CONFIGS AND EXTENSIONS TO GENERIC FUNCTIONS *****/ @@ -1008,12 +1008,16 @@ void preprocess_float(nvObj_t *nv) * nv_group_is_prefixed() - hack * * This little function deals with the exception cases that some groups don't use - * the parent token as a prefix to the child elements; SR being a good example. + * the parent token as a prefix to the child elements; SYS being a good example. */ -uint8_t nv_group_is_prefixed(char *group) +bool nv_group_is_prefixed(char *group) { - if (strcmp("sr", group) == 0) return (false); - if (strcmp("sys", group) == 0) return (false); + if (strcmp("sys", group) == 0) { + return (false); + } + if (strcmp("sr", group) == 0) { + return (false); + } return (true); } diff --git a/g2core/controller.cpp b/g2core/controller.cpp index 9a5263c1..46256eff 100755 --- a/g2core/controller.cpp +++ b/g2core/controller.cpp @@ -87,13 +87,12 @@ static Motate::OutputPin safe_pin; void controller_init() { // preserve settable parameters that may have already been set up - uint8_t comm_mode = cs.comm_mode; + commMode comm_mode = cs.comm_mode; memset(&cs, 0, sizeof(controller_t)); // clear all values, job_id's, pointers and status _init_assertions(); cs.comm_mode = comm_mode; // restore parameters - cs.fw_build = G2CORE_FIRMWARE_BUILD; // set up identification cs.fw_version = G2CORE_FIRMWARE_VERSION; cs.hw_platform = G2CORE_HARDWARE_PLATFORM; // NB: HW version is set from EEPROM @@ -211,13 +210,15 @@ static stat_t _dispatch_command() static void _dispatch_kernel() { + stat_t status; + while ((*cs.bufp == SPC) || (*cs.bufp == TAB)) { // position past any leading whitespace cs.bufp++; } - strncpy(cs.saved_buf, cs.bufp, SAVED_BUFFER_LEN-1); // save input buffer for reporting + strncpy(cs.saved_buf, cs.bufp, SAVED_BUFFER_LEN-1); // save input buffer for reporting - if (*cs.bufp == NUL) { // blank line - just a CR or the 2nd termination in a CRLF - if (cs.comm_mode == TEXT_MODE) { + if (*cs.bufp == NUL) { // blank line - just a CR or the 2nd termination in a CRLF + if (js.json_mode == TEXT_MODE) { text_response(STAT_OK, cs.saved_buf); return; } @@ -232,15 +233,22 @@ static void _dispatch_kernel() else if (*cs.bufp == CAN) { hw_hard_reset(); } // reset immediately else if (*cs.bufp == '{') { // process as JSON mode - cs.comm_mode = JSON_MODE; // switch to JSON mode + if (cs.comm_mode == AUTO_MODE) { + js.json_mode = JSON_MODE; // switch to JSON mode + } json_parser(cs.bufp); } #ifdef __TEXT_MODE else if (strchr("$?Hh", *cs.bufp) != NULL) { // process as text mode - cs.comm_mode = TEXT_MODE; // switch to text mode - text_response(text_parser(cs.bufp), cs.saved_buf); + if (cs.comm_mode == AUTO_MODE) { + js.json_mode = TEXT_MODE; // switch to text mode + } + status = text_parser(cs.bufp); + if (js.json_mode == TEXT_MODE) { // needed in case mode was changed by $EJ=1 + text_response(status, cs.saved_buf); + } } - else if (cs.comm_mode == TEXT_MODE) { // anything else is interpreted as Gcode + else if (js.json_mode == TEXT_MODE) { // anything else is interpreted as Gcode text_response(gcode_parser(cs.bufp), cs.saved_buf); } #endif @@ -251,7 +259,7 @@ static void _dispatch_kernel() strcpy(nv->token, "gc"); // label is as a Gcode block (do not get an index - not necessary) nv_copy_string(nv, cs.bufp); // copy the Gcode line nv->valuetype = TYPE_STRING; - float status = gcode_parser(cs.bufp); + status = gcode_parser(cs.bufp); nv_print_list(status, TEXT_NO_PRINT, JSON_RESPONSE_FORMAT); sr_request_status_report(SR_REQUEST_TIMED); // generate incremental status report to show any changes } @@ -445,3 +453,5 @@ stat_t _test_system_assertions() xio_test_assertions(); return (STAT_OK); } + + \ No newline at end of file diff --git a/g2core/controller.h b/g2core/controller.h index 980a2837..0d19e78d 100755 --- a/g2core/controller.h +++ b/g2core/controller.h @@ -62,12 +62,10 @@ typedef struct controllerSingleton { // main TG controller struct uint32_t led_timer; // used to flash indicator LED uint32_t led_blink_rate; // used to flash indicator LED - // communications (and other) state variables - uint8_t comm_mode; // 0=text mode, 1=JSON mode - -// uint8_t state_usb0; -// uint8_t state_usb1; -// bool shared_buf_overrun; // flag for shared string buffer overrun condition + // communications state variables + // cs.comm_mode is the setting for the communications more + // js.json_mode is the actual current mode (see also js.json_now) + commMode comm_mode; // ej: 0=text mode sticky, 1=JSON mode sticky, 2=auto mode // controller serial buffers char *bufp; // pointer to primary or secondary in buffer diff --git a/g2core/g2core.cppproj b/g2core/g2core.cppproj index 0197d7db..2b1f1c3d 100755 --- a/g2core/g2core.cppproj +++ b/g2core/g2core.cppproj @@ -76,7 +76,7 @@ J41800030015 Atmel-ICE - False + True 84000000 @@ -115,7 +115,8 @@ Custom Programming Tool False - Z:\PersonalProjects\TinyG2\Motate\Tools\win32\gcc-arm-none-eabi\bin\arm-none-eabi-gdb.exe + + diff --git a/g2core/g2core_info.h b/g2core/g2core_info.h index 067a5929..53dc5aad 100755 --- a/g2core/g2core_info.h +++ b/g2core/g2core_info.h @@ -21,7 +21,7 @@ #ifndef G2CORE_INFO_H_ONCE #define G2CORE_INFO_H_ONCE -#define G2CORE_FIRMWARE_BUILD 100.06 // Disable heaters and fans on M2 and M30 +#define G2CORE_FIRMWARE_BUILD 100.07 // Sticky EJ mode #ifdef GIT_VERSION #define G2CORE_FIRMWARE_BUILD_STRING GIT_VERSION #else diff --git a/g2core/json_parser.cpp b/g2core/json_parser.cpp index 86f335d3..4196aac9 100755 --- a/g2core/json_parser.cpp +++ b/g2core/json_parser.cpp @@ -94,7 +94,7 @@ void json_parser(char *str) nv = nv_body; status = _json_parser_execute(nv); } - if (status == STAT_COMPLETE) { // skip the print if returning from something that already did it. + if (status == STAT_COMPLETE) { // skip the print if returning from something that already did it. return; } nv_print_list(status, TEXT_NO_PRINT, JSON_RESPONSE_FORMAT); @@ -615,7 +615,7 @@ void json_print_response(uint8_t status) stat_t json_set_jv(nvObj_t *nv) { if ((uint8_t)nv->value >= JV_MAX_VALUE) { return (STAT_INPUT_EXCEEDS_MAX_VALUE);} - js.json_verbosity = nv->value; + js.json_verbosity = (jsonVerbosity)nv->value; js.echo_json_footer = false; js.echo_json_messages = false; @@ -637,6 +637,24 @@ stat_t json_set_jv(nvObj_t *nv) return(STAT_OK); } +/* + * json_set_ej() - set JSON communications mode + */ + +stat_t json_set_ej(nvObj_t *nv) +{ + if ((nv->value < TEXT_MODE) || (nv->value > AUTO_MODE)) { + nv->valuetype = TYPE_NULL; + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (uint8_t(nv->value) == TEXT_MODE) { + js.json_mode = TEXT_MODE; + } else { + js.json_mode = JSON_MODE; + } + return (set_ui8(nv)); +} + /*********************************************************************************** * TEXT MODE SUPPORT * Functions to print variables from the cfgArray table @@ -651,7 +669,7 @@ stat_t json_set_jv(nvObj_t *nv) * js_print_jf() */ -static const char fmt_ej[] = "[ej] enable json mode%13d [0=text,1=JSON]\n"; +static const char fmt_ej[] = "[ej] enable json mode%13d [0=text,1=JSON,2=auto]\n"; static const char fmt_jv[] = "[jv] json verbosity%15d [0=silent,1=footer,2=messages,3=configs,4=linenum,5=verbose]\n"; static const char fmt_js[] = "[js] json serialize style%9d [0=relaxed,1=strict]\n"; static const char fmt_jf[] = "[jf] json footer style%12d [1=checksum,2=window report]\n"; diff --git a/g2core/json_parser.h b/g2core/json_parser.h index 3e8b10fa..e379ede3 100755 --- a/g2core/json_parser.h +++ b/g2core/json_parser.h @@ -63,12 +63,13 @@ typedef enum { // json output print modes typedef struct jsSingleton { /*** config values (PUBLIC) ***/ - uint8_t json_verbosity; // see enum in this file for settings - uint8_t echo_json_footer; // flags for JSON responses serialization - uint8_t echo_json_messages; - uint8_t echo_json_configs; - uint8_t echo_json_linenum; - uint8_t echo_json_gcode_block; + commMode json_mode; // 0=text mode, 1=JSON mode (loaded from cs.comm_mode) + jsonVerbosity json_verbosity; // see enum in this file for settings + bool echo_json_footer; // flags for JSON responses serialization + bool echo_json_messages; + bool echo_json_configs; + bool echo_json_linenum; + bool echo_json_gcode_block; /*** runtime values (PRIVATE) ***/ @@ -88,6 +89,7 @@ void json_print_response(uint8_t status); void json_print_list(stat_t status, uint8_t flags); stat_t json_set_jv(nvObj_t *nv); +stat_t json_set_ej(nvObj_t *nv); #ifdef __TEXT_MODE diff --git a/g2core/text_parser.cpp b/g2core/text_parser.cpp index 1e7aaf24..715ef0d3 100755 --- a/g2core/text_parser.cpp +++ b/g2core/text_parser.cpp @@ -133,8 +133,8 @@ static stat_t _text_parser_kernal(char *str, nvObj_t *nv) } strcpy(nv->group, cfgArray[nv->index].group); // capture the group string if there is one - // see if you need to strip the token - if (nv->group[0] != NUL) { + // see if you need to strip the token - but only if in text mode + if ((js.json_mode == TEXT_MODE) && (nv_group_is_prefixed(nv->group))) { wr = nv->token; rd = nv->token + strlen(nv->group); while (*rd != NUL) { *(wr)++ = *(rd)++;} @@ -146,8 +146,8 @@ static stat_t _text_parser_kernal(char *str, nvObj_t *nv) /************************************************************************************ * text_response() - text mode responses */ -static const char prompt_ok[] = "g2 [%s] ok> "; -static const char prompt_err[] = "g2 [%s] err[%d]: %s: %s "; +static const char prompt_ok[] = "g2core[%s] ok> "; +static const char prompt_err[] = "g2core[%s] err[%d]: %s: %s "; void text_response(const stat_t status, char *buf) {