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

📄 dbg.c

📁 Linux下的tcl语言调试器
💻 C
📖 第 1 页 / 共 3 页
字号:
		argc--; argv++;		if (argc > 0) {		    b->re = 1;		    savestr(&b->pat,argv[0]);		    if (Tcl_GetRegExpFromObj(interp, b->pat, TCL_REG_ADVANCED)			    == NULL) {			breakpoint_destroy(b);			return TCL_ERROR;		    }		    argc--; argv++;		} else {			breakpoint_fail("bad regular expression")		}	} else if (flageq("-glob",argv[0],2)) {		argc--; argv++;		if (argc > 0) {			savestr(&b->pat,argv[0]);			argc--; argv++;		} else {			breakpoint_fail("no pattern?");		}	} else if ((!(flageq("if",*argv,1)) && (!(flageq("then",*argv,1))))) {		/* look for [file:]line */		char *colon;		char *linep;	/* pointer to beginning of line number */		colon = strchr(argv[0],':');		if (colon) {			*colon = '\0';			savestr(&b->file,argv[0]);			*colon = ':';			linep = colon + 1;		} else {			linep = argv[0];			/* get file from current scope */			/* savestr(&b->file, ?); */		}		if (TCL_OK == Tcl_GetInt(interp,linep,&b->line)) {			argc--; argv++;			print(interp,"setting breakpoints by line number is currently unimplemented - use patterns or expressions\n");		} else {			/* not an int? - unwind & assume it is an expression */			if (b->file) Tcl_DecrRefCount(b->file);		}	}	if (argc > 0) {		int do_if = FALSE;		if (flageq("if",argv[0],1)) {			argc--; argv++;			do_if = TRUE;		} else if (!flageq("then",argv[0],1)) {			do_if = TRUE;		}		if (do_if) {			if (argc < 1) {				breakpoint_fail("if what");			}			savestr(&b->expr,argv[0]);			argc--; argv++;		}	}	if (argc > 0) {		if (flageq("then",argv[0],1)) {			argc--; argv++;		}		if (argc < 1) {			breakpoint_fail("then what?");		}		savestr(&b->cmd,argv[0]);	}	sprintf(interp->result,"%d",b->id);	return(TCL_OK); break_fail:	breakpoint_destroy(b);	Tcl_SetResult(interp,error_msg,TCL_STATIC);	return(TCL_ERROR);}static char *help[] = {"s [#]		step into procedure","n [#]		step over procedure","N [#]		step over procedures, commands, and arguments","c		continue","r		continue until return to caller","u [#]		move scope up level","d [#]		move scope down level","		go to absolute frame if # is prefaced by \"#\"","w		show stack (\"where\")","w -w [#]	show/set width","w -c [0|1]	show/set compress","b		show breakpoints","b [-r regexp-pattern] [if expr] [then command]","b [-g glob-pattern]   [if expr] [then command]","b [[file:]#]          [if expr] [then command]","		if pattern given, break if command resembles pattern","		if # given, break on line #","		if expr given, break if expr true","		if command given, execute command at breakpoint","b -#		delete breakpoint","b -		delete all breakpoints",0};/*ARGSUSED*/staticintcmdHelp(clientData, interp, argc, argv)ClientData clientData;Tcl_Interp *interp;int argc;char **argv;{	char **hp;	for (hp=help;*hp;hp++) {		print(interp,"%s\n",*hp);	}	return(TCL_OK);}/* occasionally, we print things larger buf_max but not by much *//* see print statements in PrintStack routines for examples */#define PAD 80/*VARARGS*/static voidprint TCL_VARARGS_DEF(Tcl_Interp *,arg1){	Tcl_Interp *interp;	char *fmt;	va_list args;	interp = TCL_VARARGS_START(Tcl_Interp *,arg1,args);	fmt = va_arg(args,char *);	if (!printproc) vprintf(fmt,args);	else {		static int buf_width_max = DEFAULT_WIDTH+PAD;		static char buf_basic[DEFAULT_WIDTH+PAD+1];		static char *buf = buf_basic;		if (buf_width+PAD > buf_width_max) {			if (buf && (buf != buf_basic)) ckfree(buf);			buf = (char *)ckalloc(buf_width+PAD+1);			buf_width_max = buf_width+PAD;		}		vsprintf(buf,fmt,args);		(*printproc)(interp,buf,printdata);	}	va_end(args);}/*ARGSUSED*/Dbg_InterStructDbg_Interactor(interp,inter_proc,data)Tcl_Interp *interp;Dbg_InterProc *inter_proc;ClientData data;{	Dbg_InterStruct tmp;	tmp.func = interactor;	tmp.data = interdata;	interactor = (inter_proc?inter_proc:simple_interactor);	interdata = data;	return tmp;}/*ARGSUSED*/Dbg_IgnoreFuncsProc *Dbg_IgnoreFuncs(interp,proc)Tcl_Interp *interp;Dbg_IgnoreFuncsProc *proc;{	Dbg_IgnoreFuncsProc *tmp = ignoreproc;	ignoreproc = (proc?proc:zero);	return tmp;}/*ARGSUSED*/Dbg_OutputStructDbg_Output(interp,proc,data)Tcl_Interp *interp;Dbg_OutputProc *proc;ClientData data;{	Dbg_OutputStruct tmp;	tmp.func = printproc;	tmp.data = printdata;	printproc = proc;	printdata = data;	return tmp;}/*ARGSUSED*/intDbg_Active(interp)Tcl_Interp *interp;{	return debugger_active;}char **Dbg_ArgcArgv(argc,argv,copy)int argc;char *argv[];int copy;{	char **alloc;	main_argc = argc;	if (!copy) {		main_argv = argv;		alloc = 0;	} else {		main_argv = alloc = (char **)ckalloc((argc+1)*sizeof(char *));		while (argc-- >= 0) {			*main_argv++ = *argv++;		}		main_argv = alloc;	}	return alloc;}static struct cmd_list {	char *cmdname;	Tcl_CmdProc *cmdproc;	enum debug_cmd cmdtype;} cmd_list[]  = {		{"n", cmdNext,   next},		{"s", cmdNext,   step},		{"N", cmdNext,   Next},		{"c", cmdSimple, cont},		{"r", cmdSimple, ret},		{"w", cmdWhere,  none},		{"b", cmdBreak,  none},		{"u", cmdDir,    up},		{"d", cmdDir,    down},		{"h", cmdHelp,   none},		{0}};/* this may seem excessive, but this avoids the explicit test for non-zero *//* in the caller, and chances are that that test will always be pointless *//*ARGSUSED*/static int zero(interp,string)Tcl_Interp *interp;char *string;{	return 0;}static intsimple_interactor(interp)Tcl_Interp *interp;{	int rc;	char *ccmd;		/* pointer to complete command */	char line[BUFSIZ+1];	/* space for partial command */	int newcmd = TRUE;	Interp *iPtr = (Interp *)interp;	Tcl_DString dstring;	Tcl_DStringInit(&dstring);	newcmd = TRUE;	while (TRUE) {		struct cmd_list *c;		if (newcmd) {#if TCL_MAJOR_VERSION < 8			print(interp,"dbg%d.%d> ",iPtr->numLevels,iPtr->curEventNum+1);#else			/* unncessarily tricky coding - if nextid			   isn't defined, maintain our own static			   version */			static int nextid = 0;			char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0);			if (nextidstr) {				sscanf(nextidstr,"%d",&nextid);			}			print(interp,"dbg%d.%d> ",iPtr->numLevels,nextid++);#endif		} else {			print(interp,"dbg+> ");		}		fflush(stdout);		if (0 >= (rc = read(0,line,BUFSIZ))) {			if (!newcmd) line[0] = 0;			else exit(0);		} else line[rc] = '\0';		ccmd = Tcl_DStringAppend(&dstring,line,rc);		if (!Tcl_CommandComplete(ccmd)) {			newcmd = FALSE;			continue;	/* continue collecting command */		}		newcmd = TRUE;		/* if user pressed return with no cmd, use previous one */		if ((ccmd[0] == '\n' || ccmd[0] == '\r') && ccmd[1] == '\0') {			/* this loop is guaranteed to exit through break */			for (c = cmd_list;c->cmdname;c++) {				if (c->cmdtype == last_action_cmd) break;			}			/* recreate textual version of command */			Tcl_DStringAppend(&dstring,c->cmdname,-1);			if (c->cmdtype == step ||			    c->cmdtype == next ||			    c->cmdtype == Next) {				char num[10];				sprintf(num," %d",last_step_count);				Tcl_DStringAppend(&dstring,num,-1);			}		}#if TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION < 4		rc = Tcl_RecordAndEval(interp,ccmd,0);#else		rc = Tcl_RecordAndEval(interp,ccmd,TCL_NO_EVAL);		rc = Tcl_Eval(interp,ccmd);#endif		Tcl_DStringFree(&dstring);		switch (rc) {		case TCL_OK:			if (*interp->result != 0)				print(interp,"%s\n",interp->result);			continue;		case TCL_ERROR:			print(interp,"%s\n",Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY));			/* since user is typing by hand, we expect lots			   of errors, and want to give another chance */			continue;		case TCL_BREAK:		case TCL_CONTINUE:#define finish(x)	{rc = x; goto done;}			finish(rc);		case TCL_RETURN:			finish(TCL_OK);		default:			/* note that ccmd has trailing newline */			print(interp,"error %d: %s\n",rc,ccmd);			continue;		}	}	/* cannot fall thru here, must jump to label */ done:	Tcl_DStringFree(&dstring);	return(rc);}static char init_auto_path[] = "lappend auto_path $dbg_library";static voidinit_debugger(interp)Tcl_Interp *interp;{	struct cmd_list *c;	for (c = cmd_list;c->cmdname;c++) {		Tcl_CreateCommand(interp,c->cmdname,c->cmdproc,			(ClientData)&c->cmdtype,(Tcl_CmdDeleteProc *)0);	}	debug_handle = Tcl_CreateTrace(interp,				10000,debugger_trap,(ClientData)0);	debugger_active = TRUE;	Tcl_SetVar2(interp,Dbg_VarName,"active","1",0);#ifdef DBG_SCRIPTDIR	Tcl_SetVar(interp,"dbg_library",DBG_SCRIPTDIR,0);#endif	Tcl_Eval(interp,init_auto_path);}/* allows any other part of the application to jump to the debugger *//*ARGSUSED*/voidDbg_On(interp,immediate)Tcl_Interp *interp;int immediate;		/* if true, stop immediately */			/* should only be used in safe places */			/* i.e., when Tcl_Eval can be called */{	if (!debugger_active) init_debugger(interp);	/* intuitively, it would seem natural to initialize the	debugger with the step command.  However, it's too late at	this point.  It must be done before the command reader	(whatever it is) has gotten control. */	/* debug_cmd = step;*/	step_count = 1;	if (immediate) {		static char *fake_cmd = "--interrupted-- (command_unknown)";		debugger_trap((ClientData)0,interp,-1,fake_cmd,(int (*)())0,					(ClientData)0,1,&fake_cmd);/*		(*interactor)(interp);*/	}}voidDbg_Off(interp)Tcl_Interp *interp;{	struct cmd_list *c;	if (!debugger_active) return;	for (c = cmd_list;c->cmdname;c++) {		Tcl_DeleteCommand(interp,c->cmdname);	}	Tcl_DeleteTrace(interp,debug_handle);	debugger_active = FALSE;	Tcl_UnsetVar(interp,Dbg_VarName,TCL_GLOBAL_ONLY);	/* initialize for next use */	debug_cmd = step;	step_count = 1;}

⌨️ 快捷键说明

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