Пример #1
0
/*
 * 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);
}
Пример #2
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;
                }
            }
        }
    }
}