/* * The real main loop of the debugger: create a new execution frame on the * debugger stack, and while we have input available, call into the parser. */ int mdb_run(void) { volatile int err; mdb_frame_t f; mdb_intr_disable(); mdb_frame_push(&f); /* * This is a fresh mdb context, so ignore any pipe command we may have * inherited from the previous frame. */ f.f_pcmd = NULL; if ((err = setjmp(f.f_pcb)) != 0) { int pop = (mdb.m_in != NULL && (mdb_iob_isapipe(mdb.m_in) || mdb_iob_isastr(mdb.m_in))); int fromcmd = (f.f_cp != NULL); mdb_dprintf(MDB_DBG_DSTK, "frame <%u> caught event %s\n", f.f_id, mdb_err2str(err)); /* * If a syntax error or other failure has occurred, pop all * input buffers pushed by commands executed in this frame. */ while (mdb_iob_stack_size(&f.f_istk) != 0) { if (mdb.m_in != NULL) mdb_iob_destroy(mdb.m_in); mdb.m_in = mdb_iob_stack_pop(&f.f_istk); yylineno = mdb_iob_lineno(mdb.m_in); } /* * Reset standard output and the current frame to a known, * clean state, so we can continue execution. */ mdb_iob_margin(mdb.m_out, MDB_IOB_DEFMARGIN); mdb_iob_clrflags(mdb.m_out, MDB_IOB_INDENT); mdb_iob_discard(mdb.m_out); mdb_frame_reset(&f); /* * If there was an error writing to output, display a warning * message if this is the topmost frame. */ if (err == MDB_ERR_OUTPUT && mdb.m_depth == 1 && errno != EPIPE) mdb_warn("write failed"); /* * If an interrupt or quit signal is reported, we may have been * in the middle of typing or processing the command line: * print a newline and discard everything in the parser's iob. * Note that we do this after m_out has been reset, otherwise * we could trigger a pipe context switch or cause a write * to a broken pipe (in the case of a shell command) when * writing the newline. */ if (err == MDB_ERR_SIGINT || err == MDB_ERR_QUIT) { mdb_iob_nl(mdb.m_out); yydiscard(); } /* * If we quit or abort using the output pager, reset the * line count on standard output back to zero. */ if (err == MDB_ERR_PAGER || MDB_ERR_IS_FATAL(err)) mdb_iob_clearlines(mdb.m_out); /* * If the user requested the debugger quit or abort back to * the top, or if standard input is a pipe or mdb_eval("..."), * then propagate the error up the debugger stack. */ if (MDB_ERR_IS_FATAL(err) || pop != 0 || (err == MDB_ERR_PAGER && mdb.m_fmark != &f) || (err == MDB_ERR_NOMEM && !fromcmd)) { mdb_frame_pop(&f, err); return (err); } /* * If we've returned here from a context where signals were * blocked (e.g. a signal handler), we can now unblock them. */ if (err == MDB_ERR_SIGINT) (void) mdb_signal_unblock(SIGINT); } else mdb_intr_enable(); for (;;) { while (mdb.m_in != NULL && (mdb_iob_getflags(mdb.m_in) & (MDB_IOB_ERR | MDB_IOB_EOF)) == 0) { if (mdb.m_depth == 1 && mdb_iob_stack_size(&f.f_istk) == 0) { mdb_iob_clearlines(mdb.m_out); mdb_tgt_periodic(mdb.m_target); } (void) yyparse(); } if (mdb.m_in != NULL) { if (mdb_iob_err(mdb.m_in)) { warn("error reading input stream %s\n", mdb_iob_name(mdb.m_in)); } mdb_iob_destroy(mdb.m_in); mdb.m_in = NULL; } if (mdb_iob_stack_size(&f.f_istk) == 0) break; /* return when we're out of input */ mdb.m_in = mdb_iob_stack_pop(&f.f_istk); yylineno = mdb_iob_lineno(mdb.m_in); } mdb_frame_pop(&f, 0); /* * The value of '.' is a per-frame attribute, to preserve it properly * when switching frames. But in the case of calling mdb_run() * explicitly (such as through mdb_eval), we want to propagate the value * of '.' to the parent. */ mdb_nv_set_value(mdb.m_dot, f.f_dot); return (0); }
int yycparser::yywork() { int errorpop = 0; while (1) { yystack_t state = yypeek(); // get top state int index = yycstateaction[state]; while (1) { if (yyctokenaction[index].token == YYTK_ALL) { if (yyctokenaction[index].type == YYAT_DEFAULT) { state = yyctokenaction[index].sr; index = yycstateaction[state]; continue; } break; } if (!yylookahead) { yychar = yygettoken(); if (yychar < 0) { yychar = 0; } yylookahead = 1; #ifdef YYDEBUG yydgettoken(yychar); #endif } if (yyctokenaction[index].token == yychar) { break; } index++; } unsigned char type = yyctokenaction[index].type; short sr = yyctokenaction[index].sr; // action switch (type) { case YYAT_SHIFT: #ifdef YYDEBUG yydshift(yychar); #endif if (yyskip > 0) { yysetskip(yyskip - 1); } if (!yypush(sr)) { #ifdef YYDEBUG yydabort(); #endif if (yywipeflg) { yywipe(); // clean up } return 1; } memcpy(&((char YYFAR*)yyattributestackptr)[yytop * yyattribute_size], yylvalptr, yyattribute_size); yylookahead = 0; continue; // go to top of while loop case YYAT_REDUCE: #ifdef YYDEBUG yydreduce(sr); #endif yyretireflg = 0; if (yyreduction[sr].action != -1) { // user actions in here if (yyreduction[sr].length > 0) { memcpy(yyvalptr, &((char YYFAR*)yyattributestackptr) [(yytop + 1 - yyreduction[sr].length) * yyattribute_size], yyattribute_size); } yyerrorflg = 0; yyexitflg = 0; yyaction(yyreduction[sr].action); // check for special user requected actions if (yyexitflg) { #ifdef YYDEBUG yydexit(yyexitcode); #endif return yyexitcode; } if (yyerrorflg) { errorpop = yyerrorpop; #ifdef YYDEBUG yydthrowerror(yyerrorpop); #endif yyerrorcount++; break; // go to error handler } } yypop(yyreduction[sr].length); { yystack_t state = yypeek(); // get top state int index = yycnontermgoto[yyreduction[sr].rule]; while (yycstategoto[index].current != YYST_ALL && yycstategoto[index].current != state) { index++; } short next = yycstategoto[index].next; assert(next != YYST_ERROR); if (!yypush(next)) { #ifdef YYDEBUG yydabort(); #endif if (yywipeflg) { yywipe(); // clean up } return 1; } } if (yyreduction[sr].action != -1) { memcpy(&((char YYFAR*)yyattributestackptr)[yytop * yyattribute_size], yyvalptr, yyattribute_size); } if (yyretireflg) { #ifdef YYDEBUG yydretire(yyretirecode); #endif return yyretirecode; } continue; // go to top of while loop case YYAT_ERROR: #ifdef YYDEBUG yydsyntaxerror(); #endif if (yyskip == 0) { yyerrorcount++; yysyntaxerror(); } break; // go to error handler default: yyassert(type == YYAT_ACCEPT); #ifdef YYDEBUG yydaccept(); #endif return 0; } // error handler if (yyskip < 3 || yyerrorpop > 0) { #ifdef YYDEBUG yydattemptrecovery(); #endif yypopflg = 0; // clear flag while (yytop >= 0) { state = yypeek(); // get top state index = yycstateaction[state]; while (1) { if (yyctokenaction[index].token == YYTK_ALL) { if (yyctokenaction[index].type == YYAT_DEFAULT) { state = yyctokenaction[index].sr; index = yycstateaction[state]; continue; } break; } if (yyctokenaction[index].token == YYTK_ERROR) { break; } index++; } type = yyctokenaction[index].type; sr = yyctokenaction[index].sr; if (type == YYAT_SHIFT) { if (errorpop <= 0) { #ifdef YYDEBUG yydshift(YYTK_ERROR); #endif if (!yypush(sr)) { #ifdef YYDEBUG yydabort(); #endif if (yywipeflg) { yywipe(); // clean up } return 1; } yysetskip(3); // skip 3 erroneous characters break; } errorpop--; } yypopflg = 1; // clean up any symbol attributes if (yydestructorptr != NULL) { state = yypeek(); int action = yydestructorptr[state]; if (action != -1) { // user actions in here memcpy(yyvalptr, &((char YYFAR*)yyattributestackptr) [yytop * yyattribute_size], yyattribute_size); yyaction(action); memcpy(&((char YYFAR*)yyattributestackptr) [yytop * yyattribute_size], yyvalptr, yyattribute_size); } } yypop(1); if (yytop < 0) { #ifdef YYDEBUG yydabort(); #endif if (yywipeflg) { yywipe(); // clean up } return 1; } } } else { if (yylookahead) { if (yychar != 0) { #ifdef YYDEBUG yyddiscard(yychar); #endif yydiscard(yychar); // clean up any token attributes if (yyctokendestptr != NULL) { const yyctokendest_t YYNEARFAR *tokendestptr = yyctokendestptr; while (tokendestptr->token != 0) { if (tokendestptr->token == yychar) { // user actions in here memcpy(yyvalptr, yylvalptr, yyattribute_size); yyaction(tokendestptr->action); memcpy(yylvalptr, yyvalptr, yyattribute_size); break; } tokendestptr++; } } yylookahead = 0; // skip erroneous character } else { #ifdef YYDEBUG yydabort(); #endif if (yywipeflg) { yywipe(); // clean up } return 1; } } } } }