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

📄 ccdbug.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
字号:
/*	CCDBUG.C - Support for Source Language Debugging / Profiling
**
**	(c) Copyright CompuServe Incorporated, Columbus Ohio, 1990
**
**	Facility: KCC Compiler
**
**	Abstract: This module of the compiler provides features added
**		  at CompuServe: it is called by the parsing and code
**		  generating phases, to generate "hooks" into various
**		  debugging and profiling programs from the user code.
**
**	Environment: Host C Language
**
**	Author: Michael V. Snyder
**
**	Revision History:
**	1.0	May 18, 1990	-Initial Revision
*/

/*
**	External Interfaces:
*/

#include "cc.h"

extern void  outstr(char *);			/* CCOUT */
extern void  flushcode(void);			/* CCCODE */
extern void  codgolab(SYMBOL *);		/* CCCODE */
extern SYMBOL *creatsym(char *);		/* CCSYM */

/*
** Global Data
*/

#define BUFFSIZE	6 /* Labels have 6 chars, 1<<18 exec.stmts overflows*/
static char buff[BUFFSIZE];
static int stmt_index;

/*
 *	Table of Contents:
 */

NODE *debug_node(NODE *s, int lineno, int stmt_number, int type);
void  code_debugcall(NODE *n);
void  dbginit(void);
static char *otoa(int i);

/*
** How it works:
** 
** If "debcsi" is greater than zero, the parser will call debug_node()
** when it recognizes appropriate points in the source code [function
** entry points, function exits, and statement breaks].  debug_node()
** will add a node to the parse tree representing a goto label with 
** an automatically generated name: the '%' character followed by 
** the source line number.
**
** Later, when the code generation phase recognizes one of these nodes,
** it will call code_debugcall() to output both the label and a pseudo-
** op representing a call to the appropriate debugger or profiler 
** function at runtime.  Each call generated to the debugger or profiler
** will have a parameter "stmt_index", which will have a unique value.
** At runtime, this unique value can be used to quickly identify the
** source of the call.
**
** At compile time, the calling of these functions is controlled by a 
** variable "debcsi".  Command line options to the compiler will assign
** debcsi a positive value associated with either source debugging, 
** statement profiling or function profiling.  However, a #pragma
** "nodebug" can make the value of debcsi negative, in which case the
** debugger hooks will no longer be generated.  A second #pragma "debug"
** can later make debcsi positive.  Neither #pragma should change debcsi
** if its value is zero (default).
*/

NODE *
debug_node(NODE *n, int this_line, int stmt_number, int calltype)

/*
 * Functional Description:
 *	 
 *	Generates an extra node to be inserted into the parse tree.
 *	This node will contain information about the line number of
 *	the statement being generated.  The code generation phase 
 *	will recognize this node, and generate an appropriate hook
 *	for a statement debugger or profiler.
 *
 * Formal Parameters:
 *
 * n:         the parent node of the statement being parsed.
 * this_line: current line number from lexer.
 * calltype:  one of FN_ENTRY, FN_EXIT, or STMT
 *
 * Implicit Parameters:	none.
 *
 * Return Value: pointer to a new node.
 *
 * Side Effects: updates several static variables.
 */
{
    static int last_line = 0;
    static char label_str[40];

    switch (debcsi)
	{

	/*
	 * FW 2A(42) PPS4575: added case KCC_DBG_FBDG
	 */

	case KCC_DBG_FDBG:		    /* function debugging */
	case KCC_DBG_FPRF:		    /* function profiling */

	    /*
	     * If this is only a statement break, skip it.
	     */

	    if (calltype == STMT)
		break;			    /* else fall thru */


	case KCC_DBG_SDBG:		    /* statement debugging */
	case KCC_DBG_SPRF:		    /* statement profiling */
	    
	    if (last_line != this_line)
		{

		/*
		 * Make a node if we have moved onto a new source line.
		 *
		 * FUTURE:
		 * 
		 * Break the source-line connection and hook per statement.
		 */

		last_line = this_line;
		sprintf (label_str, "%%%d", this_line);
		n = ndefl (N_LABEL, n);
		n->Nxfsym = creatsym (label_str);
		n->Nxfsym->Sflags |= SF_LABEL;
		n->Nxfsym->Sclass = SC_LABEL;
		n->Nxfsym->Skey = calltype;
		sprintf (n->Nxfsym->Sname + 7, "%d", stmt_number);
		}
	    break;


	default:
	    break;			    /* turned off (0 or negative) */
	}	/* end switch */
    return n;
}

void
code_debugcall(NODE *n)

/*
 * Functional Description: 
 *
 *	Generates an instruction into the output file, which will be 
 *	translated into a transfer of control to a controlling program
 *	such as a debugger.
 *
 * Formal Parameters: 
 *	n: node containing line number information
 *
 * Implicit Parameters:	stmt_index.
 *
 * Return Value:	none.
 *
 * Side Effects:	increments stmt_index.
 */
{
    char *str;

    flushcode();
    codgolab(n->Nxfsym);		/* send goto label */
    switch (n->Nleft->Nop)			/* decoration for .MAC file */
	{
	case Q_CASE:
	    str = "\t; case stmt\n";
	    break;
	case Q_DEFAULT:
	    str = "\t; default stmt\n";
	    break;
	case N_LABEL:
	    str = "\t; label stmt\n";
	    break;
	case Q_BREAK:
	    str = "\t; break\n";
	    break;
	case Q_GOTO:
	    str = "\t; goto\n";
	    break;
	case Q_CONTINUE:
	    str = "\t; continue\n";
	    break;
	case Q_SWITCH:
	    str = "\t; switch\n";
	    break;
	case N_EXPRLIST:
	    str = "\t; expr list\n";
	    break;
	case Q_IF:
	    str = "\t; if stmt\n";
	    break;
	case Q_WHILE:
	    str = "\t; while loop\n";
	    break;
	case Q_DO:
	    str = "\t; do loop\n";
	    break;
	case Q_FOR:
	    str = "\t; for loop\n";
	    break;
	case Q_RETURN:
	    str = "\t; return\n";
	    break;
	case N_STATEMENT:
	    str= "\t; fn entry\n";
	    break;
	default:
	    str = "\t; expr stmt\n";
	    break;
	}
    switch (n->Nxfsym->Skey)
	{
	case FN_ENTRY:
	    outstr("\tDEBUGP	0, ");
	    break;
	case FN_EXIT:
	    outstr("\tDEBUGE	1, ");
	    break;
	case STMT:
	    outstr("\tDEBUGS	2, ");
	    break;
	default:
	    int_error("code_debugcall: invalid debug call %d",
		    n->Nxfsym->Skey);
	    break;
	}

    outstr(otoa(++stmt_index));
    outstr(str);
}

void dbginit(void)

/*
 * Functional Description: Initialize debug output and label buffer for new 
 *	source module.
 *
 * Formal Parameters:	none.
 *
 * Implicit Parameters:	none.
 *
 * Return Value:	none.
 *
 * Side Effects:	Zeroes a static variable.
 */
{
    stmt_index = 0;
    buff[BUFFSIZE-1] = '\0';
}

/* 6/91, change octal values to strings. Example: 9 becomes "11" */
static char *otoa(int i)
{
    int j = BUFFSIZE - 2;

    while (i > 0)
	{
	buff[j--] = i % 8 + '0';
	i /= 8;
	}
    return &buff[j+1];
}

⌨️ 快捷键说明

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