⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yydebug.c

📁 一个c语言写做的编译器的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*@A (C) 1992 Allen I. Holub                                                */
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>	 /* ANSI/UNIX time functions.			*/
#include <sys/timeb.h>	 /* ANSI/UNIX time functions.			*/
#include <signal.h>	 /* Needed by signal.				*/
#include <stdarg.h>	 /* ANSI variable-argument lists.		*/
#include <io.h>		 /* Prototypes for access().	   		*/
#include <string.h>	 /* Prototypes for string functions.		*/
#include <stdlib.h>	 /* Prototypes for other library functions.	*/
#include <tools/debug.h> /* Various macros.				*/
#include <curses.h>	 /* Window functions.				*/
#include <tools/l.h>	 /* Prototypes for all of l.lib, including all	*/
			 /* functions in the current file.		*/
extern char *yytext;	 /* Generated by LeX and lex.			*/
extern int  yylineno;
extern int  yyleng;

/* If your system doesn't have an <stdarg.h>, use the following:
 *
 * typedef char *va_list;
 * #define va_start(arg_ptr,first)  arg_ptr = (va_list)&first + sizeof(first)
 * #define va_arg(arg_ptr,type)	    ((type*)(arg_ptr += sizeof(type)))[-1]
 * #define va_end()
 *----------------------------------------------------------------------
 * The following macros take care of system dependencies. They assume a 25-line
 * screen on the IBM and a 24-line screen under Unix. Code put inside an MS()
 * macro compiles only if a MSDOS compiler is being used. Code in a UNIX()
 * macro compiles only if a UNIX compiler is being used. The NEWLINE define
 * takes care of a bug in the UNIX curses package that isn't present in the
 * DOS version presented in this book (it clears the bottom line after a
 * scroll). box.h (in Appendix A) holds #defines for the IBM Box-drawing
 * characters. #define NOT_IBM_PC to use the more portable defines in that
 * file ('+' is used for corners, '|' for vertical lines, and '-' for
 * horizontal ones) rather than the less-portable IBM graphics characters.
 * fcntl() is also used only in UNIX mode.
 */

#ifdef MSDOS				/* An MSDOS compiler is active	  */
#	include <tools/box.h>		/* Use IBM-PC graphics characters */
#	define SCRNSIZE 25
#	define NEWLINE(win) (Interactive ? waddch( win, '\n') :0)
#else
#	define NOT_IBM_PC		/* Use dashes, vertical bars, etc. */
#	include <tools/box.h>
extern  int	fputc();		/* system stuff */
extern	int	errno;
#	define SCRNSIZE 24
#	define NEWLINE(win) (Interactive ? (waddch( win, '\n'), wclrtoeol(win))\
					 : 0 )
#endif

/* Prototypes for local statics: */

#if ( 0 UNIX(+1) )			/* UNIX compilers only */
    PRIVATE	void    kbready ();
    PRIVATE	WINDOW	*boxwin ();
#else
    PRIVATE	WINDOW	*boxwin (int lines, int cols, int y_start,
						 int x_start, char *title );
#endif

/* ----------------------------------------------------------------------
 * Defines for the windows. STACK_TOP is the top line of the stack window.
 * DEFSTACK is the default size of the text area of the stack window.
 * STACK_WINSIZE is the height of the stack window, including the border. IO_TOP
 * is the top line of both the I/O and comments windows, and IO_WINSIZE is the
 * height of the text area of those windows. It should use the whole screen
 * less the area used for the stack and prompt windows.
 */

#define STACK_TOP	 0
#define DEFSTACK	 11		    /* Stacksize=DEFSTACK by default. */
#define STACK_WINSIZE    (Stacksize +2)
#define PROMPT_TOP       (SCRNSIZE - 3)
#define PROMPT_WINSIZE   3
#define	IO_TOP 	    	 (STACK_WINSIZE-1)
#define IO_WINSIZE  	 ((SCRNSIZE - (STACK_WINSIZE + PROMPT_WINSIZE)) + 2)

#define TOKEN_WIDTH	22      /* Width of token window including border. */
#define PRINTWIDTH	79	/* Only this many characters are printed on each
				 * line by the write-screen (w) command. Extra
				 * characters are truncated.
				 */

#define ESC	0x1b		/* ASCII ESC character.			*/

/* ----------------------------------------------------------------------
 * Breakpoints. A breakpoint is set with a 'b' command. It causes automatic-mode
 * operation to terminate immediately before applying a specific production or
 * when a specified symbol is on the top of stack. P_breakpoint holds the
 * production breakpoint; T_breakpoint holds the top-of-stack breakpoint;
 * I_breakpoint is the input breakpoint. The former is an int because it's
 * always a number. The latter two are strings because they can be symbolic
 * names as well as numbers. The last variable, L_breakpoint, is the input-
 * line breakpoint.
 */

#define	BRKLEN 33	/* Longest lexeme recognized in a breakpoint + 1. */

PRIVATE int	P_breakpoint		= -1 ;
PRIVATE int	L_breakpoint		= -1 ;
PRIVATE char	S_breakpoint[ BRKLEN ]	= { '\0' } ;
PRIVATE char	I_breakpoint[ BRKLEN ]	= { '\0' } ;

/*----------------------------------------------------------------------
 * I've attempted to isolate these routines as much as possible from the actual
 * parser. They do need to know where all the stacks are, however. The following
 * variables are initialized at run-time by an access routine [yy_init_debug()]
 * and are used to access static variables in the parser itself. Note that the
 * addresses of the stack pointers are stored, not the contents of the stack
 * pointers.
 */

PRIVATE int	Abort    ;	      /* Force input routine to return EOI.   */
PRIVATE char	*Vstack  ;	      /* Base address of value stack (or NULL */
				      /* if called by llama-generated parser).*/
PRIVATE int	Vsize    ;	      /* Size of one element of value stack.  */
PRIVATE char    **Dstack ;	      /* Base address of debug (symbol) stack.*/
PRIVATE char	***P_dsp ; 	      /* Pointer to debug-stack pointer.      */
PRIVATE int	*Sstack	 ; 	      /* Base address of state stack.         */
PRIVATE int	**P_sp	 ; 	      /* Pointer to state-stack pointer.      */
PRIVATE int	Depth    ;	      /* Stack depth (all three stacks).      */

/*----------------------------------------------------------------------
 * The following variables are all used internally
 */

PRIVATE WINDOW	*Stack_window   ;     /* Windows for the debugging screen     */
PRIVATE WINDOW	*Prompt_window  ;
PRIVATE WINDOW	*Code_window    ;
PRIVATE WINDOW	*Comment_window ;
PRIVATE WINDOW	*Token_window   ;
PRIVATE int     Stacksize = DEFSTACK;/* Number of active lines in the stack   */
				     /*      window (doesn't include border). */
PRIVATE int  Onumele     = 0;        /* Number of elements on the stack.      */
PRIVATE int  Interactive = 1;        /* Interactive mode (not n or N).        */
PRIVATE int  Singlestep  = 1;        /* Single step through parse if true.    */
PRIVATE long Delay       = 0L;       /* Amount of time to wait after printing */
				     /* each stack update when not single     */
				     /* stepping (milliseconds).              */
PRIVATE int  Inp_fm_file  = 0;    /* 1 if input file is open.		      */
PRIVATE FILE *Log         = NULL; /* Pointer to the log file if one is open.  */
PRIVATE int  No_comment_pix = 0;  /* 1 if no comment-window output is printed.*/
PRIVATE int  No_stack_pix   = 0;  /* 1 if no stack pictures are to be printed */
				  /* 			      in the log file.*/
PRIVATE int Horiz_stack_pix = 0;  /* 1 if stack pictures are printed horiz-   */
				  /* 		     ontally in the log file. */
PRIVATE int Parse_pix;		  /* if(Horiz_stack_pix), print state stack.  */
PRIVATE int Sym_pix;		  /* if(Horiz_stack_pix), print symbol stack. */
PRIVATE int Attr_pix;		  /* if(Horiz_stack_pix), print attrib. stack.*/

#if (0 UNIX(+1) )  /*--------------- UNIX SYSTEM V ONLY --------------------*/
					/* Since MS-DOS has a system call that
					 * gives the keyboard status, detecting
					 * if a key has been pressed without
					 * reading the character is easy. In
					 * UNIX you must use SIGIO to set a
					 * flag (Char_avail). kbready() is the
					 * SIGIO exception handler.
					 */
PRIVATE int	Char_avail = 0;
#define kbhit()	Char_avail

#else   /*-------------------- MSDOS VERSION ONLY -------------------------*/

extern int    kbhit ( void );		/* Microsoft function. returns 1 if a */
					/* character is waiting to be read    */
					/* from the keyboard buffer. This     */
					/* function is provided in most	      */
					/* MS-DOS compiler's libraries.	      */

/* The Map[] array converts IBM box-drawing characters to something that's
 * printable. The corners are converted to plus signs, horizontal lines go to
 * dashes, and vertical lines map to vertical bars. The conv() subroutine is
 * passed a character and returns a mapped character. It must be a subroutine
 * because of the way that it's used below. It would have unacceptable
 * side-effects if rewritten as a macro.
 */

PRIVATE unsigned char Map[] =
{
    '|', '+', '+', '+', '+', '+', '+', '|', '+', '+', '+', '+', '+', '+',
    '+', '+', '+', '-', '+', '+', '+', '+', '+', '+', '+', '+', '=', '+',
    '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+'
};

PRIVATE	int  conv(c)
int c;
{
    return (VERT <= c && c <= UL) ?  Map[c - VERT] : c ;
}
#endif  /*--------------------------------------------------------------*/
PUBLIC	int yy_init_debug(sstack, p_sp, dstack, p_dsp, vstack, v_ele_size, depth)

int	*sstack;	/* Base address of state stack.  		  */
int	**p_sp;		/* Address of state-stack pointer.		  */
char	**dstack;	/* Address of debug stack.			  */
char	***p_dsp;	/* Address of debug-stack pointer.		  */
void	*vstack;	/* Base address of value stack or NULL for LLama. */
int	v_ele_size;	/* Size of one element of value stack.		  */
int	depth;		/* Number of elements in all three stacks.	  */
{
    /* Initialize for interactive I/O for curses. Return 1 on a successful
     * initialization, 0 otherwise.
     */

    char buf[80];

    UNIX( int flags;					   )
    UNIX( signal( SIGIO, kbready );			   )
    UNIX( flags = fcntl( fileno(stdin), F_GETFL, 0 );	   )
    UNIX( fcntl( fileno(stdin), F_SETFL, flags | FASYNC ); )

    Sstack = sstack;
    Dstack = dstack;
    Vstack = (char *) vstack;
    Vsize  = v_ele_size;
    P_sp   = p_sp;
    P_dsp  = p_dsp;
    Depth  = depth;
    Abort  = 0;


    initscr();
    signal( SIGINT, (void (*)(int)) die_a_horrible_death );

    noecho();		/* Don't echo input characters automatically.	     */
    crmode();		/* Don't buffer input.				     */
    MS( nosave(); )	/* Don't save region under windows (my curses only). */

    Stack_window   = boxwin( STACK_WINSIZE, 80, STACK_TOP, 0, "[stack]"    );
    Comment_window = boxwin( IO_WINSIZE,    40, IO_TOP,    0, "[comments]" );
    Code_window	   = boxwin( IO_WINSIZE,    41, IO_TOP,   39, "[output]"   );

    Token_window   = boxwin(PROMPT_WINSIZE, TOKEN_WIDTH, PROMPT_TOP,
					    80 - TOKEN_WIDTH, "[lookahead]" );

    Prompt_window  = boxwin(PROMPT_WINSIZE, (80 - TOKEN_WIDTH) + 1,
					    PROMPT_TOP,  0, "[prompts]"  );
    scrollok( Stack_window,   TRUE  );
    scrollok( Comment_window, TRUE  );
    scrollok( Code_window,    TRUE  );
    scrollok( Prompt_window,  TRUE  );
    scrollok( Token_window,   FALSE );

    Onumele = 0;

    while( !Inp_fm_file )
    {
	/* If you don't have an input file yet, get one. yyprompt() prints the
	 * prompt in the PROMPT window, and fills buf with the reply.
	 */

	if( !yyprompt( "Input file name or ESC to exit: ", buf, 1 ) )
	{
	    yy_quit_debug();
	    return 0;
	}
	new_input_file( buf );
    }
    delay();   			/* Wait for a command before proceeding */
    return 1;
}

/*----------------------------------------------------------------------
 * Exception handlers:
 */

#if ( 0 UNIX(+1) )		/* UNIX compilers only */
PRIVATE	void    kbready( )  /* Called when new character is available. */
{
    Char_avail = 1;
}
#endif

PRIVATE	void die_a_horrible_death()		   /* Come here on a SIGINT */
{						   /* or 'q' command.       */
    signal( SIGINT, SIG_IGN );
    yy_quit_debug();
    exit( 0 );
}

PUBLIC	void yy_quit_debug()			      /* Normal termination. */
{
    echo();				   /* Turn echo and editing back on. */
    nocrmode();
    move( 24, 0 );	      /* Put the cursor on the bottom of the screen. */
    refresh();
    endwin();					         /* Turn off curses. */

    if( Log )
	fclose( Log );

    stop_prnt();
    signal( SIGINT, SIG_DFL );
}

/*----------------------------------------------------------------------*/

PRIVATE	WINDOW	*boxwin( lines, cols, y_start, x_start, title )
int	lines;
int	cols;
int	y_start;
int	x_start;
char	*title;
{
    /* This routine works just like the newwin() except that the window has a
     * box around it that won't be destroyed by writes to the window. It
     * accomplishes this feat by creating two windows, one inside the other,
     * with a box drawn in the outer one. It prints the optional title centered
     * on the top line of the box. Set title to NULL (or "") if you don't want
     * a title. Note that all windows are made subwindows of the default window
     * to facilitate the print-screen command.
     */

    WINDOW *outer;

    outer = subwin( stdscr, lines, cols, y_start, x_start);
    box( outer, VERT, HORIZ );

    if( title && *title )
    {
	wmove  ( outer, 0, (cols - strlen(title))/2 );
	wprintw( outer, "%s", title );
    }

    wrefresh ( outer );
    return subwin( outer, lines-2, cols-2, y_start+1, x_start+1 );
}

/*----------------------------------------------------------------------*/

PUBLIC  int	yy_get_args( argc, argv )
int	argc;
char	**argv;
{
    /* Scan argv arguments for the debugging options and remove the arguments
     * from argv. Recognized arguments are:
     *
     * -sN	Set stack-window size to N lines. The size of the other windows
     *		scale accordingly. The stack window is not permitted to get so
     *		large that the other windows will disappear, however.
     *
     * The first argument that doesn't begin with a minus sign is taken to be
     * the input file name. That name is not removed from argv. All other
     * arguments are ignored and are not removed from argv, so you can process
     * them in your own program. This routine prints an error message and
     * terminates the program if it can't open the specified input file.
     * Command-line processing stops immediately after the file name is
     * processed. So, given the line:
     *
     *  	program -x -s15 -y foo -s1 bar
     *
     * Argv is modified to:
     *
     *  	program -x -y foo -s1 bar
     *
     * The file "foo" will have been opened for input and the stack window will
     * be 15 lines high. Return new value of argc that reflects the removed
     * arguments;
     */

    char  **newargv;
    char  **oldargv = argv;
    char  *filename = NULL;
    int	  ssize     = DEFSTACK;

    newargv  = ++argv;
    for( --argc; --argc >= 0; ++argv )
    {
	if( argv[0][0] != '-' )
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -