[comp.sys.ibm.pc.rt] Fix for dbx, part 4 of 5, IBM/4.3

brunner@bullhead.uucp (10/21/89)

Subject: Fix for dbx (part 4)
Index: /usr/src/ucb/dbx IBM/4.3

Description:
	Several problems (too numerous to mention) exist
	with the December release of dbx. This is part 1 
	of a 5 part patch installation kit. The contents
	of the kit are:

part 1	shar file containing help.c
part 2	patchs to the following files:
	dbx/ibmrt/{coredump.c,decode.c,frame.c,procinfo.c}
part 3	patchs to the following files:
	dbx/{object.c,eval.c,commands.y,c.c,tree.c}
part 4	patchs to the following files:
	dbx/{runtime.c,symbols.c,execute.c,events.c,mappings.c}
part 5	patches to the following files:
	dbx/{stabstring.c,printsym.c,operators.c,process.c,
	     keywords.c,pascal.c,fortran.c,main.c,Makefile,
	     examine.c,scanner.c,source.c,library.c}


Fix:	Change directories to /usr/src/ucb/dbx and
	apply this patch file, e.g.,

		patch < this_file

	Proceede to the next part of the kit.

	Inconsistencies between the several compilers (hc,
	pp, f77) and the loader exist, stabs in particular.
	These will be corrected in a following patch to dbx,
	or in corrective releases of the compilers, or both.

*** /usr/src/ucb/dbx/runtime.c	Fri Dec  9 11:57:34 1988
--- runtime.c	Thu Oct 12 14:37:24 1989
***************
*** 1,9 ****
! /* $Header:runtime.c 12.0$ */
! /* $ACIS:runtime.c 12.0$ */
! /* $Source: /ibm/acis/usr/src/ucb/dbx/RCS/runtime.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:runtime.c 12.0$";
  #endif
  
  
--- 1,8 ----
! /* $Header: runtime.c,v 12.1 89/10/12 17:37:23 brunner Locked $ */
! /* $Source: /fish/dbx/RCS/runtime.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: runtime.c,v 12.1 89/10/12 17:37:23 brunner Locked $";
  #endif
  
  
***************
*** 49,55 ****
   * associated function in the given value-result parameter.
   */
  
! private getcurfunc (frp, fp)
  Frame frp;
  Symbol *fp;
  {
--- 48,54 ----
   * associated function in the given value-result parameter.
   */
  
! getcurfunc (frp, fp)
  Frame frp;
  Symbol *fp;
  {
***************
*** 94,101 ****
   *
   * Static allocation for the frame.
   */
! 
! public Frame findframe (f)
  Symbol f;
  {
      register Frame frp;
--- 93,99 ----
   *
   * Static allocation for the frame.
   */
! public Frame findframe(f)
  Symbol f;
  {
      register Frame frp;
***************
*** 102,130 ****
      static struct Frame frame;
      Symbol p;
  
      frp = &frame;
!     getcurframe(frp);
!     if (f != nil) {
! 	if (f == curfunc and curframe != nil) {
! 	    *frp = *curframe;
! 	} else {
! 	    p = whatblock(savepc(frp));
! 	    for (;;) {
! 		if (p == f) {
! 		    break;
! 		} else if (p == program) {
! 		    frp = nil;
! 		    break;
! 		} else {
! 		    frp = nextfunc(frp, &p);
! 		    if (frp == nil) {
! 			break;
! 		    }
! 		}
! 	    }
! 	}
      }
!     return frp;
  }
  
  /*
--- 100,130 ----
      static struct Frame frame;
      Symbol p;
  
+     if ( !f )
+       return nil;
+ 
      frp = &frame;
!     if ( getcurfunc(frp,&p) < 0 ){
! 	return nil;
      }
!     if (f == curfunc && curframe ){
!        *frp = *curframe;
!        return frp;
!     } 
!     if ( p == f )
!       return frp;
! 
!     for (;;) {
! 
!        frp = nextfunc(frp, &p);
! 
!        if ( p == program )
! 	 frp = nil;
! 
!        if ( p == f || !frp )
! 	 return frp;
!     }
! /*NOTREACHED*/
  }
  
  /*
***************
*** 137,142 ****
--- 137,149 ----
      Address addr;
      struct Frame frame;
  
+ 	/*
+ 	 * curblock = whatblock(pc) -- get current block
+ 	 * if in prologue, use reg 15, it contains the return address.
+ 	 * else get the return address out of the current frame save area
+ 	 * for reg 15.
+ 	 */
+ 
      frp = &frame;
      getcurframe(frp);
      frp = nextframe(frp);
***************
*** 478,492 ****
  {
      Boolean b;
  
!     if (isfinished(process)) {
  	b = false;
!     } else {
! 	if (walkingstack or f == program or f == nil or
! 	  (ismodule(f) and isactive(container(f)))) {
  	    b = true;
! 	} else {
  	    b = (Boolean) (findframe(f) != nil);
- 	}
      }
      return b;
  }
--- 485,499 ----
  {
      Boolean b;
  
!     if (isfinished(process) || notstarted(process) ) {
  	b = false;
!     } 
!     else {
! 	if (walkingstack || f == program || f == nil ||
! 	  ((isinline(f) || ismodule(f)) && isactive(container(f))))
  	    b = true;
! 	else
  	    b = (Boolean) (findframe(f) != nil);
      }
      return b;
  }
***************
*** 501,510 ****
  {
      Node procnode, arglist;
      Symbol proc;
!     integer argc;
  
      procnode = exprnode->value.arg[0];
      arglist = exprnode->value.arg[1];
      if (procnode->op != O_SYM) {
  	beginerrmsg();
  	fprintf(stderr, "can't call \"");
--- 508,518 ----
  {
      Node procnode, arglist;
      Symbol proc;
!     Word call_pc, call_sp;
  
      procnode = exprnode->value.arg[0];
      arglist = exprnode->value.arg[1];
+ 
      if (procnode->op != O_SYM) {
  	beginerrmsg();
  	fprintf(stderr, "can't call \"");
***************
*** 521,545 ****
      endproc.callnode = exprnode;
      endproc.cmdnode = topnode;
      pushenv();
      pc = codeloc(proc);
!     argc = pushargs(proc, arglist);
!     beginproc(proc, argc);
!     event_once(
! 	build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)),
! 	buildcmdlist(build(O_PROCRTN, proc))
      );
      isstopped = false;
      if (not bpact()) {
  	isstopped = true;
  	cont(0);
      }
-     /*
-      * bpact() won't return true, it will call printstatus() and go back
-      * to command input if a breakpoint is found.
-      */
-     /* NOTREACHED */
  }
  
  /*
   * Check to see if an expression is correct for a given parameter.
   * If the given parameter is false, don't worry about type inconsistencies.
--- 529,619 ----
      endproc.callnode = exprnode;
      endproc.cmdnode = topnode;
      pushenv();
+ 
+     call_pc = reg(PROGCTR);
      pc = codeloc(proc);
!     pushargs(proc, arglist);
!     call_sp = reg(1);
!     beginproc(proc);
! 
!     push(Word,call_pc);
!     push(Word,call_sp);
! 
!     event_alloc(true,
! 	  build(O_EQ, 
! 	     build(O_SYM, pcsym), 
! 	     build(O_LCON,call_pc)
! 	  ),
!           buildcmdlist(build(O_PROCRTN, proc))
      );
+ 
      isstopped = false;
      if (not bpact()) {
  	isstopped = true;
  	cont(0);
      }
  }
  
+ public procreturn (f)
+ Symbol f;
+ {
+     int r;
+     Node tmp;
+     char *copy;
+     Word call_sp, call_pc;
+ 
+     /* if SP < call_sp we are in a recursive call, continue */
+ 
+     call_sp = pop(Word);
+     call_pc = pop(Word);
+ 
+     if ( reg(1) < call_sp ){
+        push(Word,call_pc);
+        push(Word,call_sp);
+        event_alloc(true,
+ 		  build(O_EQ, 
+ 			build(O_SYM, pcsym), 
+ 			build(O_LCON,call_pc)
+ 		  ),
+ 		  buildcmdlist(build(O_PROCRTN, f)));
+        return;
+     }
+ 
+     /* grab the endproc struct early */
+ 
+     endproc = pop(CallEnv);
+     push(CallEnv,endproc);
+     flushoutput();
+ 
+     if ( endproc.isfunc ){
+ 
+        pushretval(f->type);
+ 
+ 	r = size(f->type);
+ 	if ( r > sizeof(long) ){
+ 	   copy = newarr(char, r);
+ 	   popn(r,copy);
+ 	   tmp = build(O_SCON, copy);
+ 	}
+ 	else
+ 	  tmp = build(O_LCON, (long) popsmall(f->type));
+ 
+ 	tmp->nodetype = f->type;
+ 
+ /****	tfree(endproc.callnode); ***/
+ 
+ 	*(endproc.callnode) = *tmp;
+         dispose(tmp);
+ 	eval(endproc.cmdnode);
+     } 
+     else {
+ 	printf("%s returns successfully\n", symname(f));
+     }
+     popenv();
+     getsrcpos();
+     erecover();	/* blast out, kills pending events */
+ }
+ 
  /*
   * Check to see if an expression is correct for a given parameter.
   * If the given parameter is false, don't worry about type inconsistencies.
***************
*** 653,692 ****
      return count;
  }
  
- public procreturn (f)
- Symbol f;
- {
-     int r;
-     Node n;
-     char *data;
- 
-     popenv();
-     if (endproc.isfunc) {
- 	r = size(f->type);
- 	if (r > sizeof(long)) {
- 	    pushretval(r, true);
- 	    data = newarr(char, r);
- 	    popn(r, data);
- 	    n = build(O_SCON, data);
- 	} else {
- 	    pushretval(r, false);
- 	    n = build(O_LCON, (long) popsmall(f->type));
- 	}
- 	flushoutput();
- 	n->nodetype = f->type;
- 	tfree(endproc.callnode);
- 	*endproc.callnode = *n;
- 	dispose(n);
- 	eval(endproc.cmdnode);
-     } else {
- 	flushoutput();
- 	putchar('\n');
- 	printname(stdout, f);
- 	printf(" returns successfully\n", symname(f));
-     }
-     erecover();
- }
- 
  /*
   * Push the current environment.
   */
--- 727,732 ----
***************
*** 693,698 ****
--- 733,769 ----
  
  public pushenv ()
  {
+    Word framebase[4];
+ 
+    push(Word,reg(0));
+    push(Word,reg(1));
+    push(Word,reg(2));
+    push(Word,reg(3));
+    push(Word,reg(4));
+    push(Word,reg(5));
+    push(Word,reg(6));
+    push(Word,reg(7));
+    push(Word,reg(8));
+    push(Word,reg(9));
+    push(Word,reg(10));
+    push(Word,reg(11));
+    push(Word,reg(12));
+    push(Word,reg(13));
+    push(Word,reg(14));
+    push(Word,reg(15));
+ 
+    dread(framebase,reg(1),sizeof(framebase));
+    push(Word,framebase[0]);
+    push(Word,framebase[1]);
+    push(Word,framebase[2]);
+    push(Word,framebase[3]);
+ 
+    push(Word,reg(1));
+    push(Word, reg(PROGCTR));
+    push(int, (int) isstopped);
+    push(CallEnv, endproc);
+ 
+ /*****
      push(Address, pc);
      push(Lineno, curline);
      push(String, cursource);
***************
*** 704,709 ****
--- 775,781 ----
      push(Word, reg(PROGCTR));
      push(Word, reg(STKP));
      push(Word, reg(FRP));
+ *****/
  }
  
  /*
***************
*** 712,717 ****
--- 784,821 ----
  
  public popenv ()
  {
+     Word framebase[4];
+ 
+     endproc = pop(CallEnv);
+     isstopped = (Boolean) pop(int);
+ 
+     setreg(PROGCTR, pop(Word));
+     setreg(1,pop(Word));
+ 
+     framebase[3] = pop(Word);
+     framebase[2] = pop(Word);
+     framebase[1] = pop(Word);
+     framebase[0] = pop(Word);
+     dwrite(framebase,reg(1),sizeof(framebase));
+ 
+     setreg(15,pop(Word));
+     setreg(14,pop(Word));
+     setreg(13,pop(Word));
+     setreg(12,pop(Word));
+     setreg(11,pop(Word));
+     setreg(10,pop(Word));
+     setreg(9,pop(Word));
+     setreg(8,pop(Word));
+     setreg(7,pop(Word));
+     setreg(6,pop(Word));
+     setreg(5,pop(Word));
+     setreg(4,pop(Word));
+     setreg(3,pop(Word));
+     setreg(2,pop(Word));
+     setreg(1,pop(Word));
+     setreg(0,pop(Word));
+ 
+ /****
      String filename;
  
      setreg(FRP, pop(Word));
***************
*** 726,729 ****
--- 830,868 ----
      curline = pop(Lineno);
      pc = pop(Address);
      setsource(filename);
+ ****/
  }
+ /*
+  * Flush the debuggee's standard output.
+  *
+  * This is VERY dependent on the use of stdio.
+  */
+ 
+ public flushoutput()
+ {
+   Address addr;
+     Symbol p, iob;
+ 
+     p = lookup(identname("fflush", true));
+     while (p != nil and not isblock(p)) {
+ 	p = p->next_sym;
+     }
+     if (p != nil) {
+ 	iob = lookup(identname("_iob", true));
+ 	if (iob != nil) {
+ 	    pushenv();
+ 	    pc = codeloc(p);
+ 	    setreg(2, address(iob, nil) + sizeof(*stdout));
+ 	    beginproc(p);
+ 	    stepto(reg(15));
+ /*
+ 	    addr = reg(15);
+ 	    setbp(addr);
+ 	    resume(-1, addr);
+ 	    unsetbp(addr);
+ */
+ 	    popenv();
+ 	}
+     }
+ }
+ 
*** /usr/src/ucb/dbx/symbols.c	Fri Dec  9 11:57:47 1988
--- symbols.c	Thu Oct 12 14:37:30 1989
***************
*** 1,9 ****
! /* $Header:symbols.c 12.0$ */
! /* $ACIS:symbols.c 12.0$ */
! /* $Source: /ibm/acis/usr/src/ucb/dbx/RCS/symbols.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:symbols.c 12.0$";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
--- 1,8 ----
! /* $Header: symbols.c,v 12.1 89/10/12 17:37:28 brunner Locked $ */
! /* $Source: /fish/dbx/RCS/symbols.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: symbols.c,v 12.1 89/10/12 17:37:28 brunner Locked $";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
***************
*** 35,40 ****
--- 34,40 ----
  #include "languages.h"
  #include "tree.h"
  
+ 
  /*
   * Symbol classes
   */
***************
*** 90,95 ****
--- 90,96 ----
  	    Boolean intern : 1; /* internal calling sequence */
  	    int unused : 13;
  	    Address beginaddr;	/* address of function code */
+ 	    Address dataaddr;  /* function data address */
  	} funcv;
  	struct {		/* variant record info */
  	    int size;
***************
*** 121,126 ****
--- 122,128 ----
  
  #define symname(s) ident(s->name)
  #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
+ #define dataloc(f) ((f)->symvalue.funcv.dataaddr)
  #define isblock(s) (Boolean) ( \
      s->class == FUNC || s->class == PROC || \
      s->class == MODULE || s->class == PROG \
***************
*** 563,568 ****
--- 565,571 ----
   *	locals		- take offset from locals base
   *	arguments	- take offset from argument base
   *	register	- offset is register number
+  *	functions/procedures - return the DATA address
   */
  
  public Address address (s, frame)
***************
*** 576,617 ****
  
      checkref(s);
      addr = s->symvalue.offset;
!     if (!isactive(s->block)) {
  	error("\"%s\" is not currently defined", symname(s));
!     } else if (s->storage != EXT) {
! 	frp = frame;
! 	if (frp == nil) {
! 	    cur = s->block;
! 	    while (cur != nil && cur->class == MODULE) {
! 		cur = cur->block;
! 	    }
! 	    if (cur == nil) {
! 		frp = nil;
! 	    } else {
! 		frp = findframe(cur);
! 		if (frp == nil) {
! 		    error("[internal error: unexpected nil frame for \"%s\"]",
! 			symname(s)
! 		    );
! 		}
! 	    }
! 	}
! 	if (s->param) {
! 	    r = preg(s, frp);
! 	    if (r != -1) {
! 		addr = r;
! 	    } else if (s->storage == STK) {
! 		addr += args_base(frp);
! 		if (multiword(s->block)) {
! 		    addr += sizeof(Word);
! 		}
! 	    }
! 	} else if (s->storage == STK) {
! 	    addr += locals_base(frp);
! 	} else if (s->storage != INREG) {
! 	    panic("address: bad symbol \"%s\"", symname(s));
! 	}
      }
      return addr;
  }
  
--- 579,625 ----
  
      checkref(s);
      addr = s->symvalue.offset;
! 
! 	if ( s->class == FUNC || s->class == PROC && !isinline(s) )
! 		return dataloc(s);
! 
!     if ( s->storage == EXT )
!       return addr;
! 
!     if ( s->block == nil && s->storage == INREG )
!       return addr;
! 
!     if ( !isactive(s->block) ){
  	error("\"%s\" is not currently defined", symname(s));
!     } 
! 
!     frp = frame;
!     if ( !frp ){
!        for ( cur = s->block; ( cur && (ismodule(cur) || isinline(cur)) );
! 	     cur = cur->block )
! 	 ;
!        frp = ( cur ) ? findframe(cur) : nil;
      }
+     if ( !frp ){
+        error("[internal error: unexpected nil frame for \"%s\"]",
+ 	     symname(s));
+     }
+ 
+     if ( isparam(s) ){
+        r = preg(s, frp);
+        if ( r != NOADDR )
+ 	  addr = r;
+        else if ( s->storage == STK )
+ 	  addr += args_base(frp);
+        else {
+ 	  panic("address: invalid symbol \"%s\"", symname(s));
+        }
+     } 
+     else if ( s->storage == STK )
+        addr += locals_base(frp);
+     else if ( s->storage != INREG )
+        panic("address: invalid symbol \"%s\"", symname(s));
+ 
      return addr;
  }
  
***************
*** 649,660 ****
      s->language = t_addr->language;
      s->class = VAR;
      s->storage = INREG;
!     s->level = 3;
      s->type = t_addr;
      s->symvalue.offset = r;
  }
  
  /*
   * Resolve an "abstract" type reference.
   *
   * It is possible in C to define a pointer to a type, but never define
--- 657,693 ----
      s->language = t_addr->language;
      s->class = VAR;
      s->storage = INREG;
!     s->block = nil;
!     s->level = 1;
      s->type = t_addr;
      s->symvalue.offset = r;
  }
  
+ 
  /*
+  * Define a symbol used to access floating point register values.
+  */
+ 
+ public deffregname (n, regno, rsize)
+    Name n;
+    int regno, rsize;
+ {
+     Symbol s;
+ 
+     s = insert(n);
+     s->language = t_real->language;
+     s->class = VAR;
+     s->storage = INREG;
+     s->level = 1;
+     s->block = nil;
+     if ( rsize == 4 )
+       s->type = t_real;
+     else
+       s->type = t_real;
+     s->symvalue.offset = regno;
+ }
+ 
+ /*
   * Resolve an "abstract" type reference.
   *
   * It is possible in C to define a pointer to a type, but never define
***************
*** 759,764 ****
--- 792,800 ----
      if (t->class == TYPEREF) {
  	resolveRef(t);
      }
+ 
+     r = 0;
+ 
      switch (t->class) {
  	case RANGE:
  	    lower = t->symvalue.rangev.lower;
***************
*** 826,832 ****
  		findtype(t);
  	    }
  #	    endif
! 	    r = size(t->type);
  	    break;
  
  	case FIELD:
--- 862,871 ----
  		findtype(t);
  	    }
  #	    endif
! 	    if( t->type == t)
! 	      r = 0;
! 	    else
! 	      r = size(t->type);
  	    break;
  
  	case FIELD:
***************
*** 1221,1227 ****
  	    p1 = p->value.arg[0];
  	    p->nodetype = p1->nodetype;
  	    if (p1->op == O_SYM) {
! 		if (p1->nodetype->class == PROC || p->nodetype->class == FUNC) {
  		    p->op = p1->op;
  		    p->value.sym = p1->value.sym;
  		    p->nodetype = p1->nodetype;
--- 1260,1268 ----
  	    p1 = p->value.arg[0];
  	    p->nodetype = p1->nodetype;
  	    if (p1->op == O_SYM) {
! 		if (p1->nodetype->class == PROC ||
! 		    p1->nodetype->class == FUNC ||
! 		    p1->nodetype->class == MODULE) {
  		    p->op = p1->op;
  		    p->value.sym = p1->value.sym;
  		    p->nodetype = p1->nodetype;
***************
*** 1522,1527 ****
--- 1563,1569 ----
      dispose(s->chain);
  }
  
+ #ifdef 0
  /*
   * Figure out the "current" variable or function being referred to
   * by the name n.
***************
*** 1631,1637 ****
      }
      return b;
  }
! 
  /*
   * Find the symbol that has the same name and scope as the
   * given symbol but is of the given field.  Return nil if there is none.
--- 1673,1679 ----
      }
      return b;
  }
! #endif
  /*
   * Find the symbol that has the same name and scope as the
   * given symbol but is of the given field.  Return nil if there is none.
***************
*** 1683,1686 ****
--- 1725,1902 ----
      }
      dread(valp, addr, sizeof(long));
      return true;
+ }
+ 
+ 
+ boolean Search_block(var_s,f)
+    Symbol *var_s, f;
+ {
+     Name n;
+     Symbol s;
+ 
+     s = *var_s;
+     n = s->name;
+ 
+     for ( ; s; s = s->next_sym ){
+        if ( s->name == n ){
+ 	  if ( s->class == FIELD || s->class == TAG )
+ 	    continue;
+ 	  if ( f == s->block || f == s ){
+ 	     *var_s = s;
+ 	     return true;
+ 	  }
+        }
+     }
+     return false;
+ }
+ 
+ boolean Search_active_blocks(var_s)
+    Symbol *var_s;
+ {
+     Symbol f;		/* iteration variable for active functions */
+     Frame frp;		/* frame associated with stack walk */
+     struct Frame frame;
+ 
+     frp = &frame;
+     if ( getcurfunc(frp,&f) < 0 )
+       return false;
+ 
+     for ( ; frp; frp = nextfunc(frp,&f) ){
+        if ( f == program )
+ 	 break;
+        if ( Search_block(var_s,f) )
+ 	 return true;
+     }
+     return false;
+ }
+ 
+ 
+ boolean Search_globals(var_s)
+    Symbol *var_s;
+ {
+     Name n;
+     Symbol s;
+     boolean found;
+ 
+     n = (*var_s)->name;
+     found = false;
+ 
+     for ( s = *var_s; s; s = s->next_sym ){
+        if ( s->name == n && 
+ 	   (s->block == nil || 
+ 	    (ismodule(s->block) || s->block->class == PROG)) ){
+ 	  if ( !found ){
+ 	     *var_s = s;
+ 	     found = true;
+ 	  }
+ 	  else if ( priority(s) > priority(*var_s) )
+ 	    *var_s = s;
+        }
+     }
+     return found;
+ }
+ 
+ /* 
+  *  Return the priority associated with a symbol class
+  */
+ 
+ priority(s)
+ Symbol s;
+ {
+ 
+    switch (s->class)
+    {
+       case PROC:
+       case FUNC:
+          return(7);
+ 
+       case VAR:
+       case ARRAY:
+       case OPENARRAY:
+       case DYNARRAY:
+       case SUBARRAY:
+          return(6);
+ 
+       case COMMON:
+          return(5);
+ 
+       case PROG:
+       case MODULE:
+          return(4);
+ 
+       case CONST:
+       case PTRFILE:
+       case FILET:
+       case SET:
+       case LABEL:
+       case WITHPTR:
+       case SCAL:
+       case STR:
+       case EXTREF:
+       case TYPE:
+       case TYPEREF:
+          return(3);
+ 
+       case RECORD:
+       case FIELD:
+       case FVAR:
+       case REF:
+       case PTR:
+       case RANGE:
+       case VARNT:
+       case FPROC:
+       case FFUNC:
+       case TAG:
+          return(2);
+ 
+       case IMPROPER:
+       case BADUSE:
+       default:
+          return(1);
+    }
+ }
+ 
+ /*
+  * Figure out the "current" variable or function being referred to
+  * by the name n.
+  */
+ 
+ public Symbol which (n)
+ Name n;
+ {
+     Symbol s;
+ 
+     s = lookup(n);
+     if (s == nil) {
+ 	error("\"%s\" is not defined", ident(n));
+     } 
+ 
+     if (!isactive(program) || !Search_block(&s,curfunc) ) {
+        if(isactive(program) && Search_active_blocks(&s) )
+        {
+ 	  if(isambiguous(s))
+ 	  {
+ 	     printf("[using ");
+ 	     printwhich(stdout, s);
+ 	     printf("]\n"); 
+ 	  }       
+        }
+        else if( Search_globals(&s) )
+        {
+ 	  if(isambiguous(s))
+ 	  {
+ 	     printf("[using ");
+ 	     printwhich(stdout, s);
+ 	     printf("]\n"); 
+ 	  }       
+        }
+        else
+        {
+ 	  printf("[inactive ");
+ 	  printwhich(stdout, s);
+ 	  printf("]\n"); 
+        }
+     }
+ 
+     return s;
  }
*** /usr/src/ucb/dbx/execute.c	Fri Dec  9 11:56:54 1988
--- execute.c	Thu Oct 12 14:37:02 1989
***************
*** 1,9 ****
! /* $Header:execute.c 12.0$ */
! /* $ACIS:execute.c 12.0$ */
! /* $Source: /ibm/acis/usr/src/ucb/dbx/RCS/execute.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:execute.c 12.0$";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
--- 1,8 ----
! /* $Header: execute.c,v 12.1 89/10/12 17:37:01 brunner Locked $ */
! /* $Source: /fish/dbx/RCS/execute.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: execute.c,v 12.1 89/10/12 17:37:01 brunner Locked $";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
***************
*** 26,31 ****
--- 25,31 ----
  #include "mappings.h"
  #include "coredump.h"
  #include "runtime.h"
+ #include "frame.h"
  #include <signal.h>
  #include <errno.h>
  #include <sys/types.h>
***************
*** 32,40 ****
  #include <sys/stat.h>
  
  #ifndef public
- 
  #define DEFSIG -1
- 
  #endif
  
  #define MAXNCMDARGS 1000         /* maximum number of arguments to RUN */
--- 32,38 ----
***************
*** 60,70 ****
      String pargv[4];
      Node cond;
  
!     if (coredump) {
! 	coredump = false;
! 	fclose(corefile);
  	coredump_close();
!     }
      if (argv == nil) {
  	argv = pargv;
  	pargv[0] = objname;
--- 58,66 ----
      String pargv[4];
      Node cond;
  
!     if (coredump) 
  	coredump_close();
! 
      if (argv == nil) {
  	argv = pargv;
  	pargv[0] = objname;
***************
*** 205,214 ****
  	    printnews();
  	} else {
  	    setallbps();
! 	    resume(s);
  	    unsetallbps();
  	    s = DEFSIG;
! 	    if (not isbperr() or not bpact()) {
  		printstatus();
  	    }
  	}
--- 201,210 ----
  	    printnews();
  	} else {
  	    setallbps();
! 	    resume(s, 0);
  	    unsetallbps();
  	    s = DEFSIG;
! 	    if ( !isbperr() || !bpact()) {
  		printstatus();
  	    }
  	}
***************
*** 222,235 ****
   * but actually in the debugger.  Could happen, for example, while
   * processing breakpoints.
   *
!  * We basically just want to keep going; the assumption is
!  * that when the process resumes it will get the interrupt,
!  * which will then be handled.
   */
  
  private intr ()
  {
!     signal(SIGINT, intr);
  }
  
  public fixintr ()
--- 218,229 ----
   * but actually in the debugger.  Could happen, for example, while
   * processing breakpoints.
   *
!  * To avoid HANGING, just stop.
   */
  
  private intr ()
  {
! 	isstopped = true;
  }
  
  public fixintr ()
***************
*** 241,263 ****
   * Resume execution.
   */
  
! public resume (signo)
  int signo;
  {
      register Process p;
  
      p = process;
      pcont(p, signo);
      pc = reg(PROGCTR);
!     if (p->status != STOPPED) {
! 	if (p->signo != 0) {
  	    error("program terminated by signal %d", p->signo);
! 	} else if (not runfirst) {
! 	    if (p->exitval == 0) {
  		error("program exited");
! 	    } else {
  		error("program exited with code %d", p->exitval);
- 	    }
  	}
      }
  }
--- 235,274 ----
   * Resume execution.
   */
  
! public resume (signo, last_bp)
  int signo;
+ Address last_bp;
  {
      register Process p;
  
      p = process;
      pcont(p, signo);
+ 
      pc = reg(PROGCTR);
! 
!     if (p->status != STOPPED)
!     {
! 	/*
! 	 * Must unset all the breakpoints here since we won't be going 
! 	 * back to continue from here. First we set status to STOPPED 
! 	 * so that we can unset all the breakpoints, once we return we
! 	 * set it back so that we represent our true condition.
! 	 */
!         p->status = STOPPED;
! 	if (last_bp > 0)
! 	    unsetbp(last_bp);
! 	else
! 	    unsetallbps();
!         p->status = FINISHED;
! 
! 	if (p->signo != 0)
  	    error("program terminated by signal %d", p->signo);
! 	else if ( !runfirst) 
! 	{
! 	    if (p->exitval == 0)
  		error("program exited");
! 	    else
  		error("program exited with code %d", p->exitval);
  	}
      }
  }
***************
*** 295,337 ****
      isstopped = true;
  }
  
  /*
!  * Continue execution until the current function returns, or,
!  * if the given argument is non-nil, until execution returns to
!  * somewhere within the given function.
!  */
! 
! public rtnfunc (f)
! Symbol f;
  {
!     Address addr;
!     Symbol t;
  
!     if (not isstopped) {
! 	error("can't continue execution");
!     } else if (f != nil and not isactive(f)) {
! 	error("%s is not active", symname(f));
!     } else {
! 	addr = return_addr();
! 	if (addr == nil) {
! 	    error("no place to return to");
! 	} else {
! 	    isstopped = false;
! 	    contto(addr);
! 	    if (f != nil) {
! 		for (;;) {
! 		    t = whatblock(pc);
! 		    addr = return_addr();
! 		if (t == f or addr == nil) break;
! 		    contto(addr);
! 		}
! 	    }
! 	    if (not bpact()) {
! 		isstopped = true;
! 		printstatus();
! 	    }
! 	}
!     }
  }
  
  /*
--- 306,424 ----
      isstopped = true;
  }
  
+ rtnfunc(f)
  /*
!   This routine returns from the current function if f == NULL
!   or to the function named by f, provided it is on the
!   stack.  If there is source info, it steps ahead to stop
!   at the next source line in the same manner as dostep.
!   Note:  in routines with no source, this code will give
!   incorrect results in the prolog and in the epilog because
!   the current frame hasn't been set up or the registers have
!   be changed, respectively. Fixup for entry point done though.
! */
!    Symbol f;
  {
!    Address of, nf, addr;
!    int line;
!    Symbol s, g;
!    struct Frame frame;
!    Frame frp = &frame;
  
!    if (!isstopped) error("can't continue execution");
! 
!    isstopped = false;
! 
!    of = reg(1);
!    nf = reg(1);
! 
!    if(!f)
!    {
!       /* if at entry point, do something special */
!       if(isprolog(reg(PROGCTR)))
!       {
! 	  of = reg(1);
! 	  addr = reg(15);
!       }
!       else 
!       {
! 	  getcurfunc(frp,&g);
! 	  of = frp->reg[1];
! 	  addr = frp->reg[15];
! 
!           /* find the function to return to, if there */
!           for(; g && g != program && isinline(g) ; )
!           {
! 	     frp = nextfunc(frp,&g);
!              of = frp->reg[1];
!              addr = frp->reg[15];
!           }   
!        }
!    }
!    else 
!    {
!       /* if at entry point, do something special */
!       if(isprolog(reg(PROGCTR))) 
!       {
! 	 addr = reg(15);
! 	 of = reg(1);
! 	 g = whatblock(addr);
! 	 if(f == g) goto foundit;
! 	 else getcurfunc(frp,&g);
!       }
!       else
!       {
! 	 /* get the current function info */
! 	 getcurfunc(frp,&g);
! 	 addr = frp->reg[15];
! 	 of = frp->reg[1];
!       }
! 
!       /* find the function to return to, if there */
!       for(; g && g != program && g != f; )
!       {
!          frp = nextfunc(frp,&g);
!          of = frp->reg[1];
!          addr = frp->reg[15];
!       }   
!    }
! 
!  /* C doesn't have a break from an if so we need a goto to here */
!  foundit:
! 
!    if(f && f != g || !of)
!    {
!       error("can't return to function");
!       isstopped = true;
!       return;
!    }
! 
!    /* crank until we get to the right stack level */
!    do 
!    {
!       /* continue to that address */
!       xto(addr,true);
! 
!       pc = reg(PROGCTR);
!       nf = reg(1);
!    }
!    while ( nf < of && nf != 0 );
! 
!    /* did we stop at a line with line info ? */
!    line = linelookup(addr);
! 
!    /* crank ahead until we find an addr with a line or no source info */
!    while (line == 0 && (s = whatblock(addr)) && (isinline(s) || !nosource(s))) 
!    {
!       addr = nextaddr(addr, false);
!       line = linelookup(addr);
!       xto(addr,false);
!    }
! 
!    isstopped = true;
! 
!    if(s = whatblock(addr)) useInstLoc = (Boolean) nosource(s);
!    printnews();
  }
  
  /*
***************
*** 374,380 ****
      xto(addr, false);
  }
  
! private contto (addr)
  Address addr;
  {
      xto(addr, true);
--- 461,467 ----
      xto(addr, false);
  }
  
! public contto (addr)
  Address addr;
  {
      xto(addr, true);
***************
*** 398,409 ****
  	    setallbps();
  	}
  	setbp(addr);
! 	resume(DEFSIG);
  	unsetbp(addr);
  	if (catchbps) {
  	    unsetallbps();
  	}
! 	if (not isbperr()) {
  	    printstatus();
  	}
      }
--- 485,496 ----
  	    setallbps();
  	}
  	setbp(addr);
! 	resume(DEFSIG, addr);
  	unsetbp(addr);
  	if (catchbps) {
  	    unsetallbps();
  	}
! 	if ( !isbperr() ) {
  	    printstatus();
  	}
      }
***************
*** 565,571 ****
      if (coredump) {
  	coredump_readtext(buff, addr, nbytes);
      } else {
! 	pio(process, PREAD, TEXTSEG, buff, addr, nbytes);
      }
      onsyserr(EIO, f);
  }
--- 652,658 ----
      if (coredump) {
  	coredump_readtext(buff, addr, nbytes);
      } else {
! 	pio(process, PREAD, buff, addr, nbytes);
      }
      onsyserr(EIO, f);
  }
***************
*** 587,593 ****
      }
      f = onsyserr(EIO, write_err);
      badaddr = addr;
!     pio(process, PWRITE, TEXTSEG, buff, addr, nbytes);
      onsyserr(EIO, f);
  }
  
--- 674,680 ----
      }
      f = onsyserr(EIO, write_err);
      badaddr = addr;
!     pio(process, PWRITE, buff, addr, nbytes);
      onsyserr(EIO, f);
  }
  
***************
*** 609,615 ****
  	onsyserr(EFAULT, f);
      } else {
  	f = onsyserr(EIO, read_err);
! 	pio(process, PREAD, DATASEG, buff, addr, nbytes);
  	onsyserr(EIO, f);
      }
  }
--- 696,702 ----
  	onsyserr(EFAULT, f);
      } else {
  	f = onsyserr(EIO, read_err);
! 	pio(process, PREAD, buff, addr, nbytes);
  	onsyserr(EIO, f);
      }
  }
***************
*** 630,636 ****
      }
      f = onsyserr(EIO, write_err);
      badaddr = addr;
!     pio(process, PWRITE, DATASEG, buff, addr, nbytes);
      onsyserr(EIO, f);
  }
  
--- 717,723 ----
      }
      f = onsyserr(EIO, write_err);
      badaddr = addr;
!     pio(process, PWRITE, buff, addr, nbytes);
      onsyserr(EIO, f);
  }
  
*** /usr/src/ucb/dbx/events.c	Fri Dec  9 11:56:50 1988
--- events.c	Thu Oct 12 14:36:59 1989
***************
*** 1,9 ****
! /* $Header:events.c 12.0$ */
! /* $ACIS:events.c 12.0$ */
! /* $Source: /ibm/acis/usr/src/ucb/dbx/RCS/events.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:events.c 12.0$";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
--- 1,8 ----
! /* $Header: events.c,v 12.1 89/10/12 17:36:58 brunner Locked $ */
! /* $Source: /fish/dbx/RCS/events.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: events.c,v 12.1 89/10/12 17:36:58 brunner Locked $";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
***************
*** 48,53 ****
--- 47,53 ----
  public boolean inst_tracing;
  public boolean single_stepping;
  public boolean isstopped;
+ public boolean hexaddr = false;
  
  public Symbol linesym;
  public Symbol procsym;
***************
*** 229,235 ****
--- 229,263 ----
  			line = pop(long);
  			addr = objaddr(line, cursource);
  		    }
+ 
+ 		    /*
+ 		     * Scan ahead, see if there is a decent line
+ 		     * around.
+ 		     */
+ 
+ 	            if ( addr == NOADDR ) 
+                     {
+ 		       addr = nearobjaddr(line, cursource);
+ 		       if ( addr != NOADDR )
+ 		       {
+ 			  fprintf(stderr, "no executable code at line ");
+ 			  prtree(stderr, place);
+ 			  line = srcline(addr);
+ 			  fprintf(stderr,"; using line %d instead.\n",line);
+ 			  if ( place->op == O_QLINE )
+ 			  {
+ 			     (place->value.arg[1])->value.lcon = line;
+ 			     (place->value.arg[1])->op = O_LCON;
+ 			  }
+ 		       }
+ 		    }
+ 
+ 		    /*
+ 		     * Nope, delete the event
+ 		     */
+ 
  		    if (addr == NOADDR) {
+ 
  			if (not delevent(e->id)) {
  			    printf("!! dbx.translate: can't undo event %d?\n",
  				e->id);
***************
*** 371,376 ****
--- 399,464 ----
      endfor
  }
  
+ /*
+  *  Delete all of the breakpoints.
+  */
+ 
+ public deleteall()
+ {
+     Event e;
+ 
+     foreach (Event, e, eventlist)
+ 	if (not e->temporary) {
+ 	    delevent(e->id);
+ 	}
+     endfor
+ }
+ 
+ 
+ /*
+  *  Delete all of the breakpoints at a given line.
+  */
+ 
+ public clearbps (place)
+ Node place;
+ {
+     Breakpoint bp;
+     Lineno line;
+     Address addr;
+ 
+     line = place->value.arg[1]->value.lcon;
+     addr = objaddr(line, place->value.arg[0]->value.scon);
+     if ( addr == NOADDR )
+        return;
+ 
+     foreach (Breakpoint, bp, bplist)
+ 	if ( !bp->temporary ){
+ 	   if ( bp->bpaddr == addr )
+ 	         delevent(bp->event->id);
+ 	}
+     endfor
+ }
+ 
+ /*
+  *  Delete all of the breakpoints at a given address.
+  */
+ 
+ public clearbps_i (place)
+ Node place;
+ {
+     Breakpoint bp;
+     Address addr;
+ 
+     eval(place->value.arg[0]);
+     addr = pop(long);
+     foreach (Breakpoint, bp, bplist)
+ 	if (not bp->temporary) {
+ 	    if (bp->bpaddr == addr)
+ 	         delevent(bp->event->id);
+ 	}
+     endfor
+ }
+ 
  public printevent (e)
  Event e;
  {
***************
*** 430,436 ****
--- 518,526 ----
  	    prtree(stdout, place);
  	} else if (s == pcsym or s == retaddrsym) {
  	    printf("i at ");
+             hexaddr = true;
  	    prtree(stdout, place);
+             hexaddr = false;
  	} else {
  	    printf(" when ");
  	    prtree(stdout, cond);
***************
*** 645,651 ****
--- 735,746 ----
  public printnews ()
  {
      register Trcmd t;
+     Symbol s;
  
+     /* skip over initialization and exit code */
+     s = whatblock(reg(PROGCTR));
+     if(!s || !strcmp(symname(s),"") || !strcmp(symname(s),"_exit")) return;
+ 
      foreach (Trcmd, t, eachline)
  	evalcmdlist(t->cmdlist);
      endfor
***************
*** 749,756 ****
   * last time we checked.
   */
  
! public printifchanged (p)
  Node p;
  {
      register Trinfo tp;
      register int n;
--- 844,852 ----
   * last time we checked.
   */
  
! public printifchanged (p, trace)
  Node p;
+ Boolean trace;
  {
      register Trinfo tp;
      register int n;
***************
*** 758,763 ****
--- 854,860 ----
      Filename curfile;
      static Lineno prevline;
      static Filename prevfile;
+     static Address prevaddr;
  
      tp = findtrinfo(p);
      n = size(p->nodetype);
***************
*** 767,773 ****
      if (tp->trvalue == nil) {
  	tp->trvalue = newarr(char, n);
  	mov(v, tp->trvalue, n);
! 	printf("initially (at line %d in \"%s\"):\t", curline, curfile);
  	prtree(stdout, p);
  	printf(" = ");
  	printval(p->nodetype);
--- 864,872 ----
      if (tp->trvalue == nil) {
  	tp->trvalue = newarr(char, n);
  	mov(v, tp->trvalue, n);
! 	if(!trace || nosource(whatblock(reg(PROGCTR))))
! 	    printf("initially (at address 0x%x in \"%s\"):\t", reg(PROGCTR), curfile);
! 	else printf("initially (at line %d in \"%s\"):\t", srcline(reg(PROGCTR)), curfile);
  	prtree(stdout, p);
  	printf(" = ");
  	printval(p->nodetype);
***************
*** 774,786 ****
  	putchar('\n');
      } else if (cmp(tp->trvalue, v, n) != 0) {
  	mov(v, tp->trvalue, n);
! 	printf("after line %d in \"%s\":\t", prevline, prevfile);
  	prtree(stdout, p);
  	printf(" = ");
  	printval(p->nodetype);
  	putchar('\n');
      }
!     prevline = curline;
      prevfile = curfile;
  }
  
--- 873,889 ----
  	putchar('\n');
      } else if (cmp(tp->trvalue, v, n) != 0) {
  	mov(v, tp->trvalue, n);
! 	if(!trace || !prevline)
! 	  printf("after address 0x%x in \"%s\":\t", prevaddr, prevfile);
! 	else printf("after line %d in \"%s\":\t", prevline, prevfile);
  	prtree(stdout, p);
  	printf(" = ");
  	printval(p->nodetype);
  	putchar('\n');
      }
!     prevaddr = reg(PROGCTR);
!     if(nosource(whatblock(reg(PROGCTR)))) prevline = 0;
!     else prevline = srcline(reg(PROGCTR));
      prevfile = curfile;
  }
  
***************
*** 788,800 ****
   * Stop if the value of the given expression has changed.
   */
  
! public stopifchanged (p)
  Node p;
  {
      register Trinfo tp;
      register int n;
      char *v;
      static Lineno prevline;
  
      tp = findtrinfo(p);
      n = size(p->nodetype);
--- 891,905 ----
   * Stop if the value of the given expression has changed.
   */
  
! public stopifchanged (p, stop)
  Node p;
+ Boolean stop;
  {
      register Trinfo tp;
      register int n;
      char *v;
      static Lineno prevline;
+     static Address prevaddr;
  
      tp = findtrinfo(p);
      n = size(p->nodetype);
***************
*** 803,819 ****
      if (tp->trvalue == nil) {
  	tp->trvalue = newarr(char, n);
  	mov(v, tp->trvalue, n);
! 	sp = v;
      } else if (cmp(tp->trvalue, v, n) != 0) {
  	mov(v, tp->trvalue, n);
! 	printf("after line %d:\t", prevline);
  	prtree(stdout, p);
  	printf(" = ");
  	printval(p->nodetype);
  	putchar('\n');
  	isstopped = true;
      }
!     prevline = curline;
  }
  
  /*
--- 908,936 ----
      if (tp->trvalue == nil) {
  	tp->trvalue = newarr(char, n);
  	mov(v, tp->trvalue, n);
! 	printf("initially:\t");
! 	prtree(stdout, p);
! 	printf(" = ");
! 	printval(p->nodetype);
! 	putchar('\n');
! 	if(!stop || nosource(whatblock(reg(PROGCTR)))) useInstLoc = true;
! 	else useInstLoc = false;
! 	isstopped = true;
      } else if (cmp(tp->trvalue, v, n) != 0) {
  	mov(v, tp->trvalue, n);
! 	if(!stop || !prevline) printf("after address 0x%x:\t", prevaddr);
! 	else printf("after line %d:\t", prevline);
  	prtree(stdout, p);
  	printf(" = ");
  	printval(p->nodetype);
  	putchar('\n');
+ 	if(!stop || nosource(whatblock(reg(PROGCTR)))) useInstLoc = true;
+ 	else useInstLoc = false;
  	isstopped = true;
      }
!     prevaddr = reg(PROGCTR);
!     if(nosource(whatblock(reg(PROGCTR)))) prevline = 0;
!     else prevline = srcline(reg(PROGCTR));
  }
  
  /*
*** /usr/src/ucb/dbx/mappings.c	Fri Dec  9 11:57:11 1988
--- mappings.c	Thu Oct 12 14:37:13 1989
***************
*** 1,9 ****
! /* $Header:mappings.c 12.0$ */
! /* $ACIS:mappings.c 12.0$ */
! /* $Source: /ibm/acis/usr/src/ucb/dbx/RCS/mappings.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:mappings.c 12.0$";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
--- 1,8 ----
! /* $Header: mappings.c,v 12.1 89/10/12 17:37:12 brunner Locked $ */
! /* $Source: /fish/dbx/RCS/mappings.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: mappings.c,v 12.1 89/10/12 17:37:12 brunner Locked $";
  #endif
  
  /* Copyright (c) 1982 Regents of the University of California */
***************
*** 38,47 ****
--- 37,56 ----
  Filetab *filetab;
  Linetab *linetab;
  
+ #define nearobjaddr(l,f)	findobjaddr(l,f,false)
+ #define objaddr(l,f)		findobjaddr(l,f,true)
  #define NOADDR ((Address) -1)	/* no address for line or procedure */
  
+ /* if <values.h> exists, then these are not needed */
+ #ifndef _h_VALUES
+ #define BITSPERBYTE	8
+ #define BITS(type)	(BITSPERBYTE * (int)sizeof(type))
+ #define HIBITI	(1 << (BITS(int) - 1))
+ #define MAXINT	(~HIBITI)
  #endif
  
+ #endif
+ 
  /*
   * Get the source file name associated with a given address.
   */
***************
*** 213,218 ****
--- 222,305 ----
   * more than once in the file table (caused by includes).
   */
  
+ public Address findobjaddr(line, name, exact)
+ Lineno line;
+ String name;
+ boolean exact;
+ {
+     register Filetab *ftp;
+     register Lineno i, j;
+     Boolean foundfile;
+     int current, prev, follow, follow_i, prev_i;
+ 
+ 
+     if ( nlhdr.nlines == 0  || line <= 0 )
+ 	return NOADDR;
+ 
+     if ( !name )
+ 	name = cursource;
+ 
+     foundfile = false;
+     prev = 0;
+     follow = MAXINT;
+ 
+     /* 
+      * try for an exact match first, but remember closest prev and
+      * closest follow in case exact fails.
+      */
+ 
+     for ( ftp = filetab; ftp <= &filetab[nlhdr.nfiles]; ftp++ ){
+ 	if ( !streq(ftp->filename, name) )
+ 	    continue;
+ 
+ 	foundfile = true;
+ 	i = ftp->lineindex;
+ 	j = ( ftp == &filetab[nlhdr.nfiles-1] ) 
+ 	  ? nlhdr.nlines
+ 	  : (ftp + 1)->lineindex;
+ 
+ 	for ( ; i < j; i++ ){
+ 
+ 	   if ( linetab[i].line == line )
+ 	      return linetab[i].addr;
+ 
+ 	   if ( !exact ){
+ 	      current = linetab[i].line;
+ 
+ 	      if ( current < line && current > 0 && prev < current ){
+ 		 prev = current;
+ 		 prev_i = i;
+ 	      }
+ 
+ 	      if ( current > line && current > 0 && current < follow ){
+ 		 follow = current;
+ 		 follow_i = i;
+ 	      }
+ 	   }
+ 	}
+     }
+ 
+     if ( !foundfile ){
+ 	error("source file \"%s\" not compiled with -g", name);
+ 	return NOADDR;
+      }
+ 
+     /*
+      * Check for nearest line, if non-exact search requested.
+      */
+ 
+     if ( !exact ){
+        if ( follow != MAXINT ){
+ 	  return linetab[follow_i].addr;
+        }
+        else if ( prev ){
+ 	  return linetab[prev_i].addr;
+        }
+     }
+     return NOADDR;
+ }
+ 
+ #ifdef TEST
  public Address objaddr(line, name)
  Lineno line;
  String name;
***************
*** 250,256 ****
      }
      return NOADDR;
  }
! 
  /*
   * Table for going from object addresses to the functions in which they belong.
   */
--- 337,343 ----
      }
      return NOADDR;
  }
! #endif
  /*
   * Table for going from object addresses to the functions in which they belong.
   */
***************
*** 277,282 ****
--- 364,370 ----
      register AddrOfFunc *af;
      AddrOfFunc *newfunctab;
  
+ 
      if (nfuncs >= functablesize) {
  	if (functablesize == 0) {
  	    functab = newarr(AddrOfFunc, NFUNCS);
***************
*** 296,305 ****
  }
  
  /*
!  * Return the function that begins at the given address.
   */
  
! public Symbol whatblock(addr)
  Address addr;
  {
      register int i, j, k;
--- 384,393 ----
  }
  
  /*
!  * func_index: return the index of a function in the function table.
   */
  
! private int func_index(addr)
  Address addr;
  {
      register int i, j, k;
***************
*** 307,324 ****
  
      i = 0;
      j = nfuncs - 1;
!     if (addr < functab[i].addr) {
! 	return program;
!     } else if (addr == functab[i].addr) {
! 	return functab[i].func;
      } else if (addr >= functab[j].addr) {
! 	return functab[j].func;
      }
      while (i <= j) {
  	k = (i + j) / 2;
  	a = functab[k].addr;
  	if (a == addr) {
! 	    return functab[k].func;
  	} else if (addr > a) {
  	    i = k+1;
  	} else {
--- 395,410 ----
  
      i = 0;
      j = nfuncs - 1;
!     if (addr <= functab[i].addr) {
! 	return i;
      } else if (addr >= functab[j].addr) {
! 	return j;
      }
      while (i <= j) {
  	k = (i + j) / 2;
  	a = functab[k].addr;
  	if (a == addr) {
! 	    return k;
  	} else if (addr > a) {
  	    i = k+1;
  	} else {
***************
*** 325,336 ****
  	    j = k-1;
  	}
      }
!     if (addr > functab[i].addr) {
! 	return functab[i].func;
!     } else {
! 	return functab[i-1].func;
!     }
!     /* NOTREACHED */
  }
  
  /*
--- 411,465 ----
  	    j = k-1;
  	}
      }
!     if (addr > functab[i].addr)
! 	return i;
!     else
! 	return i-1;
! }
! 
! /*
!  * Return the function that begins at the given address.
!  */
! 
! public Symbol whatblock(addr)
! Address addr;
! {
!     int i, j;
! 
!     j = nfuncs - 1;
!     if (addr < functab[0].addr)
! 	return program;
!     else if (addr == functab[0].addr)
! 	return functab[0].func;
!     else if (addr >= functab[j].addr) 
! 	return functab[j].func;
! 
!     i = func_index(addr);
!     return functab[i].func;
! }
! 
! /*
!  * tracetable_addr:
!  * Return the start of the trace table for some function.
!  * The trace table immediately follows the code in the function,
!  * so for all functions but the last we can get the start address 
!  * of the next function in the table and back off by 10 bytes or so.
!  * --This would have worked except the raving morons also allow random
!  * data to be inserted anywhere in text, so we have to forget the whole idea.
!  */
! 
! public Address tracetable_addr(addr)
! Address addr;
! {
!     register int i, j, k;
!     Address a;
! 
!     i = func_index(addr);
! 	return functab[i].addr;
! #ifdef LOSE
!     a = ( i >= nfuncs - 1 ) ? functab[i].addr : functab[i+1].addr - 16;
!     return a;
! #endif
  }
  
  /*

Eric Brunner, IBM AWD Palo Alto
inet: brunner@monet.berkeley.edu or brunner%ibmsupt@uunet.uu.net
uucp: uunet!ibmsupt!brunner		(415) 855-4486