/*
    COMPILE WITH:
        avr-gcc -g -Os -Wall -mmcu=atxmega128a4u -std=gnu99 -c insn-bug-minimal.c -o bug.o
        // gcc version 14.0.0 20230604 (experimental) (Gentoo 14.0.0_pre20230604 p1)

    BUG:
        during RTL pass: jump
        bug-minimal.c: In function ‘cmd_parse’:
        bug-minimal.c:159:1: internal compiler error: in patch_jump_insn, at cfgrtl.cc:1295
          159 | }
              | ^
        0x9529ef7 internal_error(char const*, ...)
                ???:0
        0x83c6995 fancy_abort(char const*, int, char const*)
                ???:0
        0x854e69e redirect_edge_and_branch(edge_def*, basic_block_def*)
                ???:0
        0x91c1ccb cleanup_cfg(int)
                ???:0
        Please submit a full bug report, with preprocessed source (by using -freport-bug).
        Please include the complete backtrace with any bug report.
        See <https://bugs.gentoo.org/> for instructions.
*/

// #include <stdint.h>
typedef unsigned char uint8_t;
typedef unsigned char bool;

// globals
volatile char *cmd_line;
volatile uint8_t cmd_last;
void* cmd_data = ((void *)0);

// remove this function, not related to bug
#define str_shift_left(s)

void cmd_parse(uint8_t suggest) {
    uint8_t argc = 0;
//    char *argv[10];
    char *p = (char*)cmd_line;

    bool in = 0;
    enum { SPC, STD, ESC, SQ, SQE, DQ, DQE } state = SPC;

    if (p)
    while(*p) {
        char c = *p++;

        bool o = in;        

        switch(state) {


            case SPC: switch(c) {
                        case 0x09:
                        case 0x0A:
                        case 0x0D:
                        case 0x20:
                            break;
                        case '\'':
                            state = SQ;
                            break;
                        case '"':
                            state = DQ;
                            break;
                        case '\\':
                            state = ESC;

                            str_shift_left(p-1);
                            p--;
                            break;
                        default:
                            in = 1; 
                            state = STD;
                            break;
                      }
                      break;

            case STD:
                      switch(c) {
                        case 0x09:
                        case 0x0A:
                        case 0x0D:
                        case 0x20:
                            in = 0;
                            state = SPC;
                            break;
                        case '\'':
                            state = SQ;

                            str_shift_left(p-1);
                            p--;
                            break;
                        case '"':
                            state = DQ;

                            str_shift_left(p-1);
                            p--;
                            break;
                        case '\\':
                            state = ESC;

                            str_shift_left(p-1);
                            p--;
                            break;
                        default:
                            in = 1;
                            break;
                      }
                      break;

            case ESC: state = STD;
                      in = 1;
                      break;


            case SQ: switch(c) {
                        case '\'':
                            state = STD;

                            str_shift_left(p-1);
                            p--;
                            break;
                        case '\\':
                            state = SQE;

                            str_shift_left(p-1);
                            p--;
                            break;
                        default:
                            in = 1;
                            break;
                      }
                      break;

            case SQE: state = SQ;
                      in = 1;
                      break;


            case DQ: switch(c) {
                        case '"':
                            state = STD;

                            str_shift_left(p-1);
                            p--;
                            break;
                        case '\\':
                            state = DQE;

                            str_shift_left(p-1);
                            p--;
                            break;
                        default:
                            in = 1; 
                            break;
                      }
                      break;

            case DQE: state = DQ;
                      in = 1;
                      break;
        }
        if ((!o) && in) {
            if (argc==10) {
                // puts: too many arguments
                return;
            }

//            argv[argc]=p-1;
            argc++;
        }


        if (o && (!in)) {
            *(p-1) = 0;
        }

    }

//    argv[argc] = 0;

}


int main(void) {
    return 0;
}

