ceriel преди 34 години
родител
ревизия
2952aff355

+ 1 - 1
util/grind/c.c

@@ -45,7 +45,7 @@ static struct langdep c = {
 	"0x%lX",
 	"%lu",
 	"0x%lX",
-	"%g",
+	"%.14g",
 
 	"{",
 	"}",

+ 30 - 39
util/grind/commands.g

@@ -49,16 +49,15 @@ commands
     |	%default ';'	{ give_prompt = 0; }
     ]
 			{ if (com) {
-				if (errorgiven) {
-					freenode(com);
-					com = 0;
-				}
 				if (lastcom) {
 					freenode(lastcom);
 					lastcom = 0;
 				}
-
-				if (com) {
+				if (errorgiven) {
+					freenode(com);
+					com = 0;
+				}
+				else {
 					eval(com);
 			  		if (repeatable(com)) {
 						lastcom = com;
@@ -67,6 +66,7 @@ commands
 					        com != run_command &&
 						com != print_command) {
 						freenode(com);
+						com = 0;
 					}
 				}
 			  } else if (lastcom && ! errorgiven) {
@@ -98,7 +98,7 @@ command_line(p_tree *p;)
 | where_command(p)
 | STATUS		{ *p = mknode(OP_STATUS); }
 | DUMP			{ *p = mknode(OP_DUMP); }
-| RESTORE INTEGER	{ *p = mknode(OP_RESTORE, tok.ival); }
+| RESTORE count(p)?	{ *p = mknode(OP_RESTORE, *p); }
 | delete_command(p)
 | print_command(p)
 | display_command(p)
@@ -112,14 +112,14 @@ command_line(p_tree *p;)
 ]
 ;
 
+
 where_command(p_tree *p;)
-  { long l; }
 :
-  WHERE
-  [ INTEGER		{ l = tok.ival; }
-  | '-' INTEGER		{ l = - tok.ival; }
-  |			{ l = 0x7fffffff; }
-  ]			{ *p = mknode(OP_WHERE, l); }
+  WHERE			{ *p = mknode(OP_WHERE, (p_tree) 0); }
+  [ count(&(*p)->t_args[0])?
+  | '-' count(&(*p)->t_args[0])
+			{ (*p)->t_args[0]->t_ival = - (*p)->t_args[0]->t_ival; }
+  ]
 ;
 
 list_command(p_tree *p;)
@@ -153,9 +153,9 @@ file_command(p_tree *p;)
 help_command(p_tree *p;)
 :
   [ HELP | '?' ]
-  [			{ *p = mknode(OP_HELP, (struct idf *) 0, (char *) 0); }
-  | name(p)		{ (*p)->t_oper = OP_HELP; }
-  | '?'			{ *p = mknode(OP_HELP, str2idf("help",0), (char *) 0); }
+  			{ *p = mknode(OP_HELP, (p_tree) 0); }
+  [ name(&(*p)->t_args[0])?
+  | '?'			{ (*p)->t_args[0] = mknode(OP_NAME, str2idf("help",0), (char *) 0); }
   ]
 ;
 
@@ -210,7 +210,9 @@ when_command(p_tree *p;)
 :
   WHEN
   where(&whr)?
-  condition(&cond)?
+  condition(&cond)?	{ *p = mknode(OP_WHEN, whr, cond, (p_tree) 0); 
+			  p = &(*p)->t_args[2];
+			}
   '{' 
   command_line(p)
   [ ';'			{ if (*p) {
@@ -223,46 +225,34 @@ when_command(p_tree *p;)
   '}'
 			{ if (! whr && ! cond) {
 				error("no position or condition");
-				freenode(*p);
-				*p = 0;
 			  }
 			  else if (! *p) {
 				error("no commands given");
 			  }
-			  else *p = mknode(OP_WHEN, whr, cond, *p);
 			}
 ;
 
 step_command(p_tree *p;)
-  { long	l; }
 :
-  STEP
-  [ INTEGER		{ l = tok.ival; }
-  |			{ l = 1; }
-  ]			{ *p = mknode(OP_STEP, l); }
+  STEP			{ *p = mknode(OP_STEP, (p_tree) 0); }
+  count(&(*p)->t_args[0])?
 ;
 
 next_command(p_tree *p;)
-  { long	l; }
 :
-  NEXT
-  [ INTEGER		{ l = tok.ival; }
-  |			{ l = 1; }
-  ]			{ *p = mknode(OP_NEXT, l); }
+  NEXT			{ *p = mknode(OP_NEXT, (p_tree) 0); }
+  count(&(*p)->t_args[0])?
 ;
 
 regs_command(p_tree *p;)
-  { long	l; }
 :
-  REGS
-  [ INTEGER		{ l = tok.ival; }
-  |			{ l = 0; }
-  ]			{ *p = mknode(OP_REGS, l); }
+  REGS			{ *p = mknode(OP_REGS, (p_tree) 0); }
+  count(&(*p)->t_args[0])?
 ;
 
 delete_command(p_tree *p;)
 :
-  DELETE count_list(p)	{ *p = mknode(OP_DELETE, *p); }
+  DELETE count_list(p)?	{ *p = mknode(OP_DELETE, *p); }
 ;
 
 print_command(p_tree *p;)
@@ -323,13 +313,13 @@ able_command(p_tree *p;)
   [ ENABLE 		{ *p = mknode(OP_ENABLE, (p_tree) 0); }
   | DISABLE 		{ *p = mknode(OP_DISABLE, (p_tree) 0); }
   ]
-  count_list(&(*p)->t_args[0])
+  count_list(&(*p)->t_args[0])?
 ;
 
 count_list(p_tree *p;)
 :
   count(p)
-  [ ','			{ *p = mknode(OP_LIST, *p, (p_tree) 0); }
+  [ ','			{ *p = mknode(OP_LINK, *p, (p_tree) 0); }
     count(&(*p)->t_args[1])
   ]*
 ;
@@ -341,7 +331,8 @@ condition(p_tree *p;)
 
 where(p_tree *p;)
 :
-  IN qualified_name(p)	{ *p = mknode(OP_IN, *p); }
+  IN qualified_name(p)	{ *p = mknode(OP_IN, *p, (p_tree) 0); }
+  position(&((*p)->t_args[1]))?
 |
   position(p)
 ;

+ 45 - 62
util/grind/dbx_string.g

@@ -65,8 +65,12 @@ debugger_string
 			}
   | /* tag name (only C?) */
 			{ s = NewSymbol(str, CurrentScope, TAG, currnam); }
-	'T' tag_name(s)
-
+	'T' type_name(&(s->sy_type), s)
+			{ if (! s->sy_type->ty_sym) s->sy_type->ty_sym = s; 
+			  if (s->sy_type->ty_class != T_CROSS) {
+				resolve_cross(s->sy_type);
+			  }
+			}
   | /* end scope */
 	'E' INTEGER
 			{ close_scope(); }
@@ -105,6 +109,7 @@ debugger_string
 			{ s = Lookup(findidf(str), FileScope, VAR);
 			  if (s) {
 				tmp = s->sy_type;
+				s->sy_type = 0;
 			  } else s = NewSymbol(str, FileScope, VAR, currnam);
 			}
 	'G' type(&(s->sy_type), (int *) 0, s)
@@ -224,25 +229,21 @@ string_const
 type_name(p_type *t; p_symbol sy;)
   { int type_index[2]; p_type *p; }
 :
-  type_index(type_index)
+  type_index(type_index)	{ p = tp_lookup(type_index); }
   [
-	'='			
-	type(t, type_index, sy)
-				{ p = tp_lookup(type_index);
-				  if (*p && *p != incomplete_type) {
-					if ((*p)->ty_class != T_CROSS)
-						error("Redefining (%d,%d) %d",
-						  type_index[0],
-						  type_index[1],
-						  (*p)->ty_class);
-					if (*t && *p != *t) free_type(*p);
+				{ if (*p && (*p)->ty_class != 0 &&
+				      (*p)->ty_class != T_CROSS) {
+					error("Redefining (%d,%d) %d",
+					  type_index[0],
+					  type_index[1],
+					  (*p)->ty_class);
 				  }
-				  if (*t) *p = *t; 
 				}
+	'='			
+	type(p, type_index, sy)
   |
-				{ p = tp_lookup(type_index); }
   ]
-				{ if (*p == 0) *p = incomplete_type;
+				{ if (*p == 0) *p = new_type();
 				  *t = *p;
 				}
 ;
@@ -261,33 +262,6 @@ type_index(int *type_index;)
 				}
 ;
 
-tag_name(p_symbol t;)
-  { int type_index[2]; p_type *p; }
-:
-  type_index(type_index)
-  '='				
-  type(&(t->sy_type), type_index, t)
-				{ p = tp_lookup(type_index);
-				  if (*p && *p != incomplete_type) {
-					if ((*p)->ty_class != T_CROSS)
-						error("Redefining (%d,%d) %d",
-						  type_index[0],
-						  type_index[1],
-						  (*p)->ty_class);
-					if (t->sy_type && *p != t->sy_type) {
-						free_type(*p);
-					}
-				  }
-				  if (t->sy_type) *p = t->sy_type; 
-				  if (*p == 0) *p = incomplete_type;
-			  	  if (t->sy_type &&
-				      t->sy_type->ty_class == T_ENUM &&
-			              currnam->on_desc != 0) {
-					t->sy_type->ty_size = currnam->on_desc;
-			  	  }
-				}
-;
-
 function(p_symbol p;)
 :
   			{ p->sy_type = new_type();
@@ -335,14 +309,14 @@ routine(p_symbol p;)
 ;
 
 type(p_type *ptp; int *type_index; p_symbol sy;)
-  { register p_type tp = 0;
-    p_type t1, t2;
+  { register p_type tp = *ptp ? *ptp : new_type();
+    p_type t1 = 0, t2 = 0;
     long ic1, ic2;
     int A_used = 0;
     int tclass;
     char *str;
   }
-:			{ *ptp = 0; }
+:
   [
 	/* type cross reference */
 	/* these are used in C for references to a struct, union or
@@ -362,13 +336,14 @@ type(p_type *ptp; int *type_index; p_symbol sy;)
 			  if (sy && 
 			      (sy->sy_type->ty_class == tclass ||
 			       sy->sy_type->ty_class == T_CROSS)) {
+				if (tp != *ptp) free_type(tp);
 				tp = sy->sy_type;
 			  }
 			  else {
-				tp = new_type();
 				tp->ty_class = T_CROSS;
-				tp->ty_tag = str;
+				tp->ty_size = tclass;
 				sy = NewSymbol(str, CurrentScope, TAG, (struct outname *) 0);
+				sy->sy_type = tp;
 			  }
 			}
   |
@@ -388,7 +363,8 @@ type(p_type *ptp; int *type_index; p_symbol sy;)
 	[ 'A' integer_const(&ic2)	{ A_used |= 2; }
 	| integer_const(&ic2)
 	]
-			{ *ptp = subrange_type(A_used,
+			{ if (tp != *ptp) free_type(tp);
+			  tp = subrange_type(A_used,
 					       last_index,
 					       ic1,
 					       ic2,
@@ -399,28 +375,30 @@ type(p_type *ptp; int *type_index; p_symbol sy;)
    	 * is element type
    	 */
   	'a' type(&t1, (int *) 0, (p_symbol) 0) ';' type(&t2, (int *) 0, (p_symbol) 0)
-			{ *ptp = array_type(t1, t2); }
+			{ if (tp != *ptp) free_type(tp);
+			  tp = array_type(t1, t2); 
+			}
   |
   	/* structure type */
-  	's'		{ tp = new_type(); tp->ty_class = T_STRUCT; }
+  	's'		{ tp->ty_class = T_STRUCT; }
 	structure_type(tp, sy)
   |
   	/* union type */
-  	'u'		{ tp = new_type(); tp->ty_class = T_UNION; }
+  	'u'		{ tp->ty_class = T_UNION; }
 	structure_type(tp, sy)
   |
   	/* enumeration type */
-  	'e'		{ tp = new_type(); tp->ty_class = T_ENUM; }
+  	'e'		{ tp->ty_class = T_ENUM; }
 	enum_type(tp)
   |
   	/* pointer type */
-  	'*'		{ tp = new_type(); tp->ty_class =T_POINTER;
+  	'*'		{ tp->ty_class = T_POINTER;
 			  tp->ty_size = pointer_size;
 			}
   	type(&(tp->ty_ptrto), (int *) 0, (p_symbol) 0)
   |
   	/* function type */
-  	'f'		{ tp = new_type(); tp->ty_class = T_PROCEDURE;
+  	'f'		{ tp->ty_class = T_PROCEDURE;
 			  tp->ty_size = pointer_size;
 			}
   	type(&(tp->ty_retval), (int *) 0, (p_symbol) 0) 
@@ -432,14 +410,14 @@ type(p_type *ptp; int *type_index; p_symbol sy;)
 */
   |
   	/* procedure type */
-  	'Q'		{ tp = new_type(); tp->ty_class = T_PROCEDURE;
+  	'Q'		{ tp->ty_class = T_PROCEDURE;
 			  tp->ty_size = pointer_size;
 			}
   	type(&(tp->ty_retval), (int *) 0, (p_symbol) 0) 
 	',' param_list(tp)
   |
   	/* another procedure type */
-  	'p'		{ tp = new_type(); tp->ty_class = T_PROCEDURE;
+  	'p'		{ tp->ty_class = T_PROCEDURE;
 			  tp->ty_size = pointer_size;
 			  tp->ty_retval = void_type;
 			}
@@ -449,7 +427,7 @@ type(p_type *ptp; int *type_index; p_symbol sy;)
   	/* the first integer_const represents the size in bytes,
    	 * the second one represents the low bound
    	 */
-  	'S'		{ tp = new_type(); tp->ty_class = T_SET; }
+  	'S'		{ tp->ty_class = T_SET; }
 	type(&(tp->ty_setbase), (int *) 0, (p_symbol) 0) ';'
 	[
 		integer_const(&(tp->ty_size)) ';'
@@ -459,19 +437,23 @@ type(p_type *ptp; int *type_index; p_symbol sy;)
 	]
   |
 	/* file type of Pascal */
-	'L'		{ tp = new_type(); tp->ty_class = T_FILE; }
+	'L'		{ tp->ty_class = T_FILE; }
 	type(&(tp->ty_fileof), (int *) 0, (p_symbol) 0)
   |
   	type_name(ptp, (p_symbol) 0)
 			{ if (type_index &&
-			      *ptp == incomplete_type &&
+			      (*ptp)->ty_class == 0 &&
 			      type_index[0] == last_index[0] &&
 			      type_index[1] == last_index[1]) {
-				*ptp = void_type;
+				**ptp = *void_type;
+				if (*ptp != tp) free_type(tp);
 			  }
+			  tp = *ptp;
 			}
   ]
-			{ if (! *ptp) *ptp = tp; }
+			{ if (*ptp && *ptp != tp) **ptp = *tp;
+			  else *ptp = tp;
+			}
 ;
 
 structure_type(register p_type tp; p_symbol sy;)
@@ -676,6 +658,7 @@ get_field_space(tp, s)
   }
   p = &tp->ty_fields[tp->ty_nfields++];
   p->fld_name = s;
+  p->fld_type = 0;
   sy = NewSymbol(s, CurrentScope, FIELD, currnam);
   sy->sy_field = p;
   return p;

+ 1 - 0
util/grind/dbxread.c

@@ -188,6 +188,7 @@ DbxRead(f)
   }
   close_scope();
   add_position_addr((char *) 0, (struct outname *) 0);
+  clean_tp_tab();
   rd_close();
   return (h.oh_magic == O_CONVERTED);
 }

+ 24 - 6
util/grind/dump.c

@@ -16,8 +16,11 @@ extern p_tree	get_from_item_list();
 struct dump {
   char	*globals, *stack;
   struct message_hdr mglobal, mstack;
+  struct dump *next;
 };
 
+static struct dump	*last_dump;
+
 /* dumping and restoring of child process.
 */
 do_dump(p)
@@ -36,6 +39,8 @@ do_dump(p)
   p->t_args[0] = (struct tree *) d;
   p->t_address = (t_addr) get_int(d->mglobal.m_buf+PC_OFF*pointer_size, pointer_size, T_UNSIGNED);
   add_to_item_list(p);
+  d->next = last_dump;
+  last_dump = d;
 }
 
 /* dumping and restoring of child process.
@@ -45,16 +50,22 @@ do_restore(p)
 {
   struct dump *d;
   
-  p = get_from_item_list((int) p->t_ival);
-  if (!p || p->t_oper != OP_DUMP) {
-	error("no such dump");
-	return;
+  if (p->t_args[0]) { 
+	p = get_from_item_list((int) p->t_args[0]->t_ival);
+  	if (!p || p->t_oper != OP_DUMP) {
+		error("no such dump");
+		return;
+	}
+  	d = (struct dump *) p->t_args[0];
   }
+  else	d = last_dump;
 
-  d = (struct dump *) p->t_args[0];
+  if (! d) {
+	error("no dumps");
+	return;
+  }
 
   if (! put_dump(&d->mglobal, d->globals, &d->mstack, d->stack)) {
-	error("no debuggee");
   }
   do_items();
 }
@@ -66,5 +77,12 @@ free_dump(p)
 
   free(d->globals);
   free(d->stack);
+  if (d == last_dump) last_dump = d->next;
+  else {
+	register struct dump *d1 = last_dump;
+
+	while (d1->next != d) d1 = d1->next;
+	d1->next = d->next;
+  }
   free((char *) d);
 }

+ 4 - 10
util/grind/expr.c

@@ -65,8 +65,9 @@ long
 get_int(buf, size, class)
   char	*buf;
   long	size;
+  int	class;
 {
-  long l;
+  register long l;
 
   switch((int)size) {
   case sizeof(char):
@@ -140,8 +141,8 @@ int
 convert(pbuf, psize, ptp, tp, size)
   char	**pbuf;
   long	*psize;
-  p_type *ptp;
-  p_type tp;
+  register p_type *ptp;
+  register p_type tp;
   long size;
 {
   /* Convert the value in pbuf, of size psize and type ptp, to type
@@ -318,7 +319,6 @@ do_deref(p, pbuf, psize, ptp)
 	*pbuf = malloc((unsigned) *psize);
 	malloc_succeeded(*pbuf);
 	if (! get_bytes(*psize, addr, *pbuf)) {
-		error("could not get value");
 		free(*pbuf);
 		*pbuf = 0;
 		return 0;
@@ -918,7 +918,6 @@ array_addr(p, paddr, psize, ptp)
 	}
 	if ((*ptp)->ty_class == T_POINTER) {
 		if (! get_bytes(pointer_size, *paddr, (char *) paddr)) {
-			error("could not get value");
 			free(buf);
 			return 0;
 		}
@@ -1021,7 +1020,6 @@ do_select(p, pbuf, psize, ptp)
 	*pbuf = malloc((unsigned int) *psize);
 	malloc_succeeded(*pbuf);
 	if (! get_bytes(*psize, a, *pbuf)) {
-		error("could not get value");
 		free(*pbuf);
 		*pbuf = 0;
 		return 0;
@@ -1105,8 +1103,6 @@ eval_expr(p, pbuf, psize, ptp)
 	sym = identify(p, VAR|REGVAR|LOCVAR|VARPAR|CONST);
 	if (! sym) return 0;
 	if (! get_value(sym, pbuf, psize)) {
-		print_node(p, 0);
-		fputs(" currently not available\n", db_out);
 		break;
 	}
 	*ptp = sym->sy_type;
@@ -1180,8 +1176,6 @@ eval_desig(p, paddr, psize, ptp)
 	sym = identify(p, VAR|REGVAR|LOCVAR|VARPAR);
 	if (! sym) return 0;
 	if (! (a = get_addr(sym, psize))) {
-		print_node(p, 0);
-		fputs(" currently not available\n", db_out);
 		break;
 	}
 	*paddr = a;

+ 42 - 14
util/grind/itemlist.cc

@@ -11,6 +11,7 @@
 
 extern FILE	*db_out;
 extern int	db_ss;
+int		stop_reason;
 
 typedef struct item {
   struct item	*i_next;
@@ -51,8 +52,10 @@ pr_item(i)
 }
 
 int
-item_addr_actions(a, mess_type)
+item_addr_actions(a, mess_type, may_stop)
   t_addr	a;
+  int		mess_type;
+  int		may_stop;
 {
   /* Perform actions associated with position 'a', and return 1 if we must stop
      there, and 0 if not.
@@ -60,20 +63,46 @@ item_addr_actions(a, mess_type)
   register p_item i = item_list.il_first;
   int stopping = 0;
 
-  while (i) {
+  stop_reason = 0;
+  for (i = item_list.il_first; i != 0; i = i->i_next) {
 	register p_tree	p = i->i_node;
 
-	if (! i->i_disabled && (p->t_address == a || p->t_address == NO_ADDR)) {
+	if (! i->i_disabled
+	    && (p->t_address == a || p->t_address == NO_ADDR)) {
 		switch(p->t_oper) {
+		case OP_STOP:
+			if (mess_type != DB_SS && mess_type != OK) break;
+			if (! p->t_args[1] || eval_cond(p->t_args[1])) {
+				if (! stop_reason) stop_reason = i->i_itemno;
+				stopping = 1;
+			}
+			break;
 		case OP_TRACE:
+		case OP_WHEN:
+		case OP_DUMP:
+		case OP_DISPLAY:
+			break;
+		default:
+			assert(0);
+		}
+	}
+  }
+  for (i = item_list.il_first; i != 0; i = i->i_next) {
+	register p_tree	p = i->i_node;
+
+	if (! i->i_disabled
+	    && (p->t_address == a || p->t_address == NO_ADDR)) {
+		switch(p->t_oper) {
+		case OP_TRACE:
+			if ((! stopping && mess_type != END_SS)
+			    || p->t_args[2] || ! may_stop) {
+				perform(p, a);
+			}
+			break;
 		case OP_WHEN:
 			perform(p, a);
 			break;
 		case OP_STOP:
-			if (mess_type != DB_SS && mess_type != OK) break;
-			if (! p->t_args[1] ||
-			    eval_cond(p->t_args[1])) stopping = 1;
-			break;
 		case OP_DUMP:
 		case OP_DISPLAY:
 			break;
@@ -81,7 +110,6 @@ item_addr_actions(a, mess_type)
 			assert(0);
 		}
 	}
-	i = i->i_next;
   }
   return stopping;
 }
@@ -107,8 +135,8 @@ add_to_item_list(p)
 
   i = new_item();
   i->i_node = p;
-  if (p->t_address == NO_ADDR &&
-      (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss++;
+  if (p->t_address == NO_ADDR
+      && (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss++;
   if (item_list.il_first == 0) {
 	item_list.il_first = i;
   }
@@ -140,8 +168,8 @@ remove_from_item_list(n)
 	else item_list.il_first = i->i_next;
 	if (i == item_list.il_last) item_list.il_last = prev;
 	p = i->i_node;
-	if (p->t_address == NO_ADDR &&
-	    (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss--;
+	if (p->t_address == NO_ADDR
+	    && (p->t_oper != OP_TRACE || ! p->t_args[0])) db_ss--;
 	free_item(i);
   }
   return p;
@@ -179,8 +207,8 @@ able_item(n, kind)
 	warning("item %d already %sabled", n, kind ? "dis" : "en");
 	return;
   }
-  if (p->t_address == NO_ADDR &&
-      (p->t_oper != OP_TRACE || ! p->t_args[0])) {
+  if (p->t_address == NO_ADDR
+      && (p->t_oper != OP_TRACE || ! p->t_args[0])) {
 	db_ss += kind == 1 ? (-1) : 1;
   }
   i->i_disabled = kind;

+ 10 - 7
util/grind/main.c

@@ -19,6 +19,7 @@ int		debug;
 extern struct tokenname tkidf[];
 extern char	*strindex();
 extern int	eof_seen;
+extern int	interrupted;
 
 static struct tokenname shorts[] = {
 	{LIST, "l"},
@@ -113,14 +114,16 @@ error(va_alist)
   va_list ap;
   char *fmt;
 
-  va_start(ap);
-  {
-	fmt = va_arg(ap, char *);
-	fprintf(db_out, "%s: ", progname);
-	vfprintf(db_out, fmt, ap);
-	fprintf(db_out, "\n");
+  if (! interrupted) {
+  	va_start(ap);
+  	{
+		fmt = va_arg(ap, char *);
+		fprintf(db_out, "%s: ", progname);
+		vfprintf(db_out, fmt, ap);
+		fprintf(db_out, "\n");
+  	}
+  	va_end(ap);
   }
-  va_end(ap);
   errorgiven = 1;
 }
 

+ 1 - 1
util/grind/modula-2.c

@@ -44,7 +44,7 @@ static struct langdep m2 = {
 	"%lXH",
 	"%lu",
 	"%lXH",
-	"%G",
+	"%.14G",
 
 	"[",
 	"]",

+ 7 - 7
util/grind/operators.ot

@@ -9,22 +9,22 @@ OP_REAL		0	0
 OP_STRING	0	0
 OP_NAME		0	0
 OP_AT		0	0
-OP_IN		1	0
-OP_HELP		0	do_help
+OP_IN		2	0
+OP_HELP		1	do_help
 OP_STOP		2	do_stop
 OP_WHEN		3	do_stop
 OP_CONT		2	do_continue
-OP_STEP		0	do_step
-OP_NEXT		0	do_next
-OP_REGS		0	do_regs
-OP_WHERE	0	do_where
+OP_STEP		1	do_step
+OP_NEXT		1	do_next
+OP_REGS		1	do_regs
+OP_WHERE	1	do_where
 OP_STATUS	0	print_items
 OP_DELETE	1	do_delete
 OP_SELECT	2	0
 OP_SET		2	do_set
 OP_PRINT	1	do_print
 OP_DUMP		0	do_dump
-OP_RESTORE	0	do_restore
+OP_RESTORE	1	do_restore
 OP_TRACE	3	do_trace
 OP_FIND		1	do_find
 OP_DISPLAY	1	add_to_item_list

+ 7 - 0
util/grind/print.c

@@ -187,6 +187,13 @@ print_val(tp, tp_sz, addr, compressed, indent, format)
 
   if (indent == 0) indent = 4;
   switch(tp->ty_class) {
+  case T_CROSS:
+	if (! tp->ty_cross) {
+		error("unknown type");
+		break;
+	}
+	print_val(tp->ty_cross, tp_sz, addr, compressed, indent, format);
+	break;
   case T_SUBRANGE:
 	print_val(tp->ty_base, tp_sz, addr, compressed, indent, format);
 	break;

+ 168 - 98
util/grind/run.c

@@ -30,6 +30,8 @@ extern long	pointer_size;
 extern char	*progname;
 extern int	child_interrupted;
 extern int	interrupted;
+extern int	stop_reason;
+extern t_lineno	currline;
 
 static int	child_pid;		/* process id of child */
 static int	to_child, from_child;	/* file descriptors for communication */
@@ -39,7 +41,6 @@ static int	fild1[2], fild2[2];	/* pipe file descriptors */
 int		disable_intr = 1;
 
 int		db_ss;
-t_lineno	currline;
 
 static int	catch_sigpipe();
 static int	stopped();
@@ -64,6 +65,7 @@ init_run()
   from_child = fild2[0];
   child_pid = 0;
   if (currfile) CurrentScope = currfile->sy_file->f_scope;
+  currline = 0;
   return 1;
 }
 
@@ -191,7 +193,7 @@ start_child(p)
 	CurrentScope = get_scope_from_addr(curr_stop);
   }
   do_items();
-  if (! restoring && ! item_addr_actions(curr_stop, OK)) {
+  if (! restoring && ! item_addr_actions(curr_stop, OK, 1)) {
 	send_cont(1);
   }
   else if (! restoring) {
@@ -225,13 +227,19 @@ ureceive(p, c)
   int	i;
   char buf[0x1000];
 
-  if (! child_pid) return 0;
+  if (! child_pid) {
+	error("no process");
+  	return 0;
+  }
 
   if (! p) p = buf;
   while (c >= 0x1000) {
 	i = read(from_child, p, 0x1000);
 	if (i <= 0) {
-		if (i == 0) child_pid = 0;
+		if (i == 0) {
+			child_pid = 0;
+		}
+		else	error("read failed");
 		return 0;
 	}
 	if (p != buf) p += i;
@@ -240,13 +248,16 @@ ureceive(p, c)
   while (c > 0) {
 	i = read(from_child, p, (int)c);
 	if (i <= 0) {
-		if (i == 0) child_pid = 0;
+		if (i == 0) {
+			child_pid = 0;
+		}
+		else	error("read failed");
 		return 0;
 	}
 	p += i;
 	c -= i;
   }
-  return c == 0;
+  return 1;
 }
 
 static int
@@ -256,16 +267,25 @@ usend(p, c)
 {
   int	i;
 
-  if (! child_pid) return 0;
+  if (! child_pid) {
+	error("no process");
+	return 0;
+  }
   while (c >= 0x1000) {
 	i = write(to_child, p, 0x1000);
-	if (i < 0) return 0;
+	if (i < 0) {
+		if (child_pid) error("write failed");
+		return 0;
+	}
 	p += i;
 	c -= i;
   }
   while (c > 0) {
 	i = write(to_child, p, (int)c);
-	if (i < 0) return 0;
+	if (i < 0) {
+		if (child_pid) error("write failed");
+		return 0;
+	}
 	p += i;
 	c -= i;
   }
@@ -307,11 +327,15 @@ stopped(s, a)
   if (s && a) {
 	fprintf(db_out, "%s ", s);
 	pos = print_position(a, 1);
+	if (stop_reason) {
+		fprintf(db_out, " (status entry %d)", stop_reason);
+	}
 	fputs("\n", db_out);
 	list_position(pos);
 	handle_displays();
   }
   curr_stop = a;
+  CurrentScope = get_scope_from_addr(a);
   return 1;
 }
 
@@ -322,82 +346,84 @@ could_send(m, stop_message)
   int	type;
   t_addr a;
   static int level = 0;
+  int child_dead = 0;
 
   level++;
   for (;;) {
-  	if (child_pid) {
-		int child_dead = 0;
-		if (m->m_type & DB_RUN) disable_intr = 0;
-		if (!child_interrupted && (! uputm(m) || ! ugetm(&answer))) {
-			child_dead = 1;
-		}
-		disable_intr = 1;
-		if ((interrupted || child_interrupted) && ! child_dead) {
-			while (child_interrupted && answer.m_type != INTR) {
-				if (! ugetm(&answer)) {
-					child_dead = 1;
-					break;
-				}
-			}
-			if (interrupted && ! child_dead) {
-				level--;
-				if (! level) {
-					child_interrupted = 0;
-					CurrentScope = get_scope_from_addr((t_addr) answer.m_size);
-					interrupted = 0;
-					stopped("interrupted", (t_addr) answer.m_size);
-				}
-				return 1;
+  	if (! child_pid) {
+		error("no process");
+		return 0;
+	}
+	if (m->m_type & DB_RUN) {
+		disable_intr = 0;
+		stop_reason = 0;
+	}
+	if (!child_interrupted && (! uputm(m) || ! ugetm(&answer))) {
+		child_dead = 1;
+	}
+	disable_intr = 1;
+	if ((interrupted || child_interrupted) && ! child_dead) {
+		while (child_interrupted && answer.m_type != INTR) {
+			if (! ugetm(&answer)) {
+				child_dead = 1;
+				break;
 			}
 		}
-		if (child_dead) {
-			wait(&child_status);
-			if (child_status & 0177) {
-				fprintf(db_out,
-					"child died with signal %d\n",
-					child_status & 0177);
-			}
-			else {
-				fprintf(db_out,
-					"child terminated, exit status %d\n",
-					child_status >> 8);
-			}
-			init_run();
+		if (interrupted && ! child_dead) {
 			level--;
+			if (! level) {
+				child_interrupted = 0;
+				interrupted = 0;
+				stopped("interrupted", (t_addr) answer.m_size);
+			}
 			return 1;
 		}
-		a = answer.m_size;
-		type = answer.m_type;
-		if (m->m_type & DB_RUN) {
-			/* run command */
-			CurrentScope = get_scope_from_addr((t_addr) a);
-		    	if (! item_addr_actions(a, type) &&
-		            ( type == DB_SS || type == OK)) {
-				/* no explicit breakpoints at this position.
-				   Also, child did not stop because of
-				   SETSS or SETSSF, otherwise we would
-				   have gotten END_SS.
-				   So, continue.
-				*/
-				if ((m->m_type & ~ DB_SS) != CONT) {
-					m->m_type = CONT | (m->m_type & DB_SS);
-				}
-				continue;
-			}
-			if (type != END_SS && single_stepping) {
-				m->m_type = CLRSS;
-				uputm(m) && ugetm(&answer);
-			}
-			single_stepping = 0;
+	}
+	if (child_dead) {
+		wait(&child_status);
+		if (child_status & 0177) {
+			fprintf(db_out,
+				"child died with signal %d\n",
+				child_status & 0177);
 		}
-		if (stop_message) {
-			stopped("stopped", a);
+		else {
+			fprintf(db_out,
+				"child terminated, exit status %d\n",
+				child_status >> 8);
 		}
+		init_run();
 		level--;
-		return type;
+		return 1;
+	}
+	a = answer.m_size;
+	type = answer.m_type;
+	if (m->m_type & DB_RUN) {
+		/* run command */
+		CurrentScope = get_scope_from_addr((t_addr) a);
+	    	if (! item_addr_actions(a, type, stop_message) &&
+	            ( type == DB_SS || type == OK)) {
+			/* no explicit breakpoints at this position.
+			   Also, child did not stop because of
+			   SETSS or SETSSF, otherwise we would
+			   have gotten END_SS.
+			   So, continue.
+			*/
+			if ((m->m_type & ~ DB_SS) != CONT) {
+				m->m_type = CONT | (m->m_type & DB_SS);
+			}
+			continue;
+		}
+		if (type != END_SS && single_stepping) {
+			m->m_type = CLRSS;
+			if (! uputm(m) || ! ugetm(&answer)) return 0;
+		}
+		single_stepping = 0;
+	}
+	if (stop_message) {
+		stopped("stopped", a);
 	}
 	level--;
-	return 0;
+	return 1;
   }
   /*NOTREACHED*/
 }
@@ -415,17 +441,22 @@ getbytes(size, from, to, kind)
   put_int(m.m_buf, pointer_size, (long)from);
 
   if (! could_send(&m, 0)) {
-	error("no process");
 	return 0;
   }
 
-  if (answer.m_type == FAIL || answer.m_type == INTR) {
+  switch(answer.m_type) {
+  case FAIL:
+	error("could not get value");
 	return 0;
+  case INTR:
+	error("interrupted");
+	return 0;
+  case DATA:
+  	return ureceive(to, answer.m_size);
+  default:
+	assert(0);
   }
-
-  assert(answer.m_type == DATA);
-
-  return ureceive(to, answer.m_size);
+  /*NOTREACHED*/
 }
 
 int
@@ -449,7 +480,6 @@ get_string(size, from, to)
   return retval;
 }
 
-int
 set_bytes(size, from, to)
   long	size;
   char	*from;
@@ -461,9 +491,21 @@ set_bytes(size, from, to)
   m.m_size = size;
   put_int(m.m_buf, pointer_size, (long) to);
 
-  return uputm(&m) && usend(from, size)
-	 && ugetm(&m)
-	 && m.m_type != FAIL;
+  if (! uputm(&m) || ! usend(from, size) || ! ugetm(&m)) {
+	return;
+  }
+  switch(answer.m_type) {
+  case FAIL:
+	error("could not handle this SET request");
+	break;
+  case INTR:
+	error("interrupted");
+	break;
+  case OK:
+	break;
+  default:
+	assert(0);
+  }
 }
 
 int
@@ -475,16 +517,25 @@ get_dump(globmessage, globbuf, stackmessage, stackbuf)
 
   m.m_type = DUMP;
   if (! could_send(&m, 0)) {
-	error("no process");
 	return 0;
   }
-  if (answer.m_type == FAIL || answer.m_type == INTR) return 0;
-  assert(answer.m_type == DGLOB);
+  switch(answer.m_type) {
+  case FAIL:
+	error("request for DUMP failed");
+	return 0;
+  case INTR:
+	error("interrupted");
+	return 0;
+  case DGLOB:
+	break;
+  default:
+	assert(0);
+  }
+
   *globmessage = answer;
   *globbuf = malloc((unsigned) answer.m_size);
   if (! ureceive(*globbuf, answer.m_size) || ! ugetm(stackmessage)) {
 	if (*globbuf) free(*globbuf);
-	error("no process");
 	return 0;
   }
   assert(stackmessage->m_type == DSTACK);
@@ -492,7 +543,6 @@ get_dump(globmessage, globbuf, stackmessage, stackbuf)
   if (! ureceive(*stackbuf, stackmessage->m_size)) {
 	if (*globbuf) free(*globbuf);
 	if (*stackbuf) free(*stackbuf);
-	error("no process");
 	return 0;
   }
   put_int(globmessage->m_buf+SP_OFF*pointer_size, pointer_size,
@@ -537,10 +587,20 @@ get_EM_regs(level)
   m.m_size = level;
 
   if (! could_send(&m, 0)) {
-	error("no process");
 	return 0;
   }
-  if (answer.m_type == FAIL || answer.m_type == INTR) return 0;
+  switch(answer.m_type) {
+  case FAIL:
+	error("request for registers failed");
+	return 0;
+  case INTR:
+	error("interrupted");
+	return 0;
+  case GETEMREGS:
+	break;
+  default:
+	assert(0);
+  }
   *to++ = (t_addr) get_int(answer.m_buf, pointer_size, T_UNSIGNED);
   *to++ = (t_addr) get_int(answer.m_buf+pointer_size, pointer_size, T_UNSIGNED);
   *to++ = (t_addr) get_int(answer.m_buf+2*pointer_size, pointer_size, T_UNSIGNED);
@@ -558,7 +618,20 @@ set_pc(PC)
   m.m_type = SETEMREGS;
   m.m_size = 0;
   put_int(m.m_buf+PC_OFF*pointer_size, pointer_size, (long)PC);
-  return could_send(&m, 0) && answer.m_type != FAIL && answer.m_type != INTR;
+  if (! could_send(&m, 0)) return 0;
+  switch(answer.m_type) {
+  case FAIL:
+	error("could not set PC to %lx", (long) PC);
+	return 0;
+  case INTR:
+	error("interrupted");
+	return 0;
+  case OK:
+	return 1;
+  default:
+	assert(0);
+  }
+  /*NOTREACHED*/
 }
 
 int
@@ -569,7 +642,7 @@ send_cont(stop_message)
 
   m.m_type = (CONT | (db_ss ? DB_SS : 0));
   m.m_size = 0;
-  return could_send(&m, stop_message) && answer.m_type != FAIL;
+  return could_send(&m, stop_message) && child_pid;
 }
 
 int
@@ -582,9 +655,7 @@ do_single_step(type, count)
   m.m_type = type | (db_ss ? DB_SS : 0);
   m.m_size = count;
   single_stepping = 1;
-  if (could_send(&m, 1) && answer.m_type != FAIL && answer.m_type != INTR) {
-	return 1;
-  }
+  if (could_send(&m, 1) && child_pid) return 1;
   single_stepping = 0;
   return 0;
 }
@@ -596,12 +667,10 @@ set_or_clear_breakpoint(a, type)
 {
   struct message_hdr m;
 
-  if (a == ILL_ADDR || a == NO_ADDR) return 0;
-
   m.m_type = type;
   m.m_size = a;
   if (debug) printf("%s breakpoint at 0x%lx\n", type == SETBP ? "setting" : "clearing", (long) a);
-  if (! could_send(&m, 0)) {
+  if (child_pid && ! could_send(&m, 0)) {
   }
 
   return 1;
@@ -618,7 +687,8 @@ set_or_clear_trace(start, end, type)
   put_int(m.m_buf, pointer_size, (long)start);
   put_int(m.m_buf+pointer_size, pointer_size, (long)end);
   if (debug) printf("%s trace at [0x%lx,0x%lx]\n", type == SETTRACE ? "setting" : "clearing", (long) start, (long) end);
-  if (! could_send(&m, 0)) {
+  if (child_pid && ! could_send(&m, 0)) {
+	return 0;
   }
 
   return 1;

+ 16 - 0
util/grind/scope.cc

@@ -129,3 +129,19 @@ base_scope(sc)
   }
   return sc;
 }
+
+/* extern int	scope_encloses(p_scope scope, from_scope);
+   Returns 1 if scope encloses from from_scope, 0 otherwise.
+*/
+int
+scope_encloses(scope, from_scope)
+  p_scope	scope, from_scope;
+{
+  register p_scope sc = from_scope;
+
+  while (sc) {
+	if (sc == scope) return 1;
+	sc = sc->sc_static_encl;
+  }
+  return 0;
+}

+ 5 - 0
util/grind/scope.h

@@ -52,3 +52,8 @@ extern p_scope	get_next_scope_from_addr();
    Returns the closest enclosing scope of 'sc' that has an activation record.
 */
 extern p_scope	base_scope();
+
+/* extern int	scope_encloses(p_scope scope, from_scope);
+   Returns 1 if scope encloses from from_scope, 0 otherwise.
+*/
+extern int	scope_encloses();

+ 19 - 3
util/grind/symbol.c

@@ -221,14 +221,13 @@ identify(p, class_set)
 
   switch(p->t_oper) {
   case OP_NAME:
-	if (! p->t_sc) p->t_sc = CurrentScope;
-	sym = Lookfromscope(p->t_idf, class_set, p->t_sc);
+	sym = Lookfromscope(p->t_idf, class_set, CurrentScope);
 	if (sym) {
 		/* Found it. */
 		break;
 	}
 
-	/* We could not find it using scope p->t_sc; now we try to identify
+	/* We could not find it using the current scope; now we try to identify
 	   it using class_set. If this results in only one definition, we
 	   take this one.
 	*/
@@ -382,3 +381,20 @@ do_which(p)
 
   if ( sym) pr_sym(sym);
 }
+
+resolve_cross(tp)
+  p_type	tp;
+{
+  register p_symbol	sym = tp->ty_sym->sy_idf->id_def;
+
+  while (sym) {
+	if (sym->sy_class == TAG &&
+	    sym->sy_type->ty_class == T_CROSS &&
+	    sym->sy_type->ty_cross == (p_type) 0 &&
+	    sym->sy_type->ty_size == tp->ty_class &&
+	    scope_encloses(tp->ty_sym->sy_scope, sym->sy_scope)) {
+		sym->sy_type->ty_cross = tp;
+	}
+	sym = sym->sy_next;
+  }
+}

+ 95 - 44
util/grind/tree.c

@@ -19,11 +19,12 @@
 #include	"expr.h"
 
 extern FILE	*db_out;
-extern t_lineno	currline;
+t_lineno	currline;
 static t_lineno	listline;
 extern long	pointer_size;
 extern char	*strrindex();
 extern int	interrupted;
+extern int	stop_reason;
 
 p_tree		print_command;
 
@@ -59,11 +60,6 @@ mknode(va_alist)
 		p->t_filename = va_arg(ap, char *);
 		break;
 	case OP_INTEGER:
-	case OP_NEXT:
-	case OP_STEP:
-	case OP_REGS:
-	case OP_RESTORE:
-	case OP_WHERE:
 		p->t_ival = va_arg(ap, long);
 		break;
 	default:
@@ -120,6 +116,25 @@ get_addr_from_node(p)
 	
   case OP_IN:
 	a =  get_addr_from_node(p->t_args[0]);
+
+	if (p->t_args[1]) {
+		p_scope sc;
+
+		a = get_addr_from_node(p->t_args[1]);
+		sc = base_scope(get_scope_from_addr(a));
+		sym = identify(p->t_args[0], FUNCTION|PROC|MODULE);
+		if (! sym->sy_name.nm_scope ||
+		    ! sym->sy_name.nm_scope->sc_bp_opp) {
+			error("could not determine address of \"%s\"", p->t_str);
+			a = ILL_ADDR;
+			break;
+		}
+		if (sc->sc_definedby != sym) {
+			error("inconsistent address");
+			a = ILL_ADDR;
+			break;
+		}
+	}
 	p->t_address = a;
 	break;
 
@@ -209,13 +224,16 @@ print_node(p, top_level)
 	print_node(p->t_args[0], 0);
 	break;
   case OP_REGS:
-	fprintf(db_out, "regs %ld", p->t_ival);
+	fputs("regs ", db_out);
+	print_node(p->t_args[0], 0);
 	break;
   case OP_NEXT:
-	fprintf(db_out, "next %ld", p->t_ival);
+	fputs("next ", db_out);
+	print_node(p->t_args[0], 0);
 	break;
   case OP_STEP:
-	fprintf(db_out, "step %ld", p->t_ival);
+	fputs("step ", db_out);
+	print_node(p->t_args[0], 0);
 	break;
   case OP_STATUS:
 	fputs("status", db_out);
@@ -225,15 +243,16 @@ print_node(p, top_level)
 	print_position(p->t_address, 1);
 	break;
   case OP_RESTORE:
-	fprintf(db_out, "restore %ld", p->t_ival);
+	fputs("restore ", db_out);
+	print_node(p->t_args[0], 0);
 	break;
   case OP_WHERE:
-	fputs("where", db_out);
-	if (p->t_ival != 0x7fffffff) fprintf(db_out, " %ld", p->t_ival);
+	fputs("where ", db_out);
+	print_node(p->t_args[0], 0);
 	break;
   case OP_HELP:
-	fputs("help", db_out);
-	if (p->t_str != 0) fprintf(db_out, " %s", p->t_str);
+	fputs("help ", db_out);
+	print_node(p->t_args[0], 0);
 	break;
   case OP_CONT:
 	fputs("cont", db_out);
@@ -258,7 +277,7 @@ print_node(p, top_level)
 	}
 	p = p->t_args[2];
 	fputs(" { ", db_out);
-	while (p->t_oper == OP_LINK) {
+	while (p && p->t_oper == OP_LINK) {
 		print_node(p->t_args[0], 0);
 		fputs("; ", db_out);
 		p = p->t_args[1];
@@ -299,6 +318,8 @@ print_node(p, top_level)
   case OP_IN:
 	fputs("in ", db_out);
 	print_node(p->t_args[0], 0);
+	fputs(" ", db_out);
+	print_node(p->t_args[1], 0);
 	break;
   case OP_SELECT:
 	print_node(p->t_args[0], 0);
@@ -326,6 +347,8 @@ print_node(p, top_level)
   case OP_BINOP:
 	(*currlang->printop)(p);
 	break;
+  default:
+	assert(0);
   }
   if (top_level) fputs("\n", db_out);
 }
@@ -342,7 +365,8 @@ repeatable(com)
 	return 1;
   case OP_NEXT:
   case OP_STEP:
-	com->t_ival = 1;
+	freenode(com->t_args[0]);
+	com->t_args[0] = 0;
 	return 1;
   case OP_LIST:
 	freenode(com->t_args[0]);
@@ -428,7 +452,14 @@ do_list(p)
 do_file(p)
   p_tree	p;
 {
+  FILE	*f;
+
   if (p->t_args[0]) {
+	if ((f = fopen(p->t_args[0]->t_str, "r")) == NULL) {
+		error("could not open %s", p->t_args[0]->t_str);
+		return;
+	}
+	fclose(f);
 	newfile(p->t_args[0]->t_idf);
   }
   else if (listfile) fprintf(db_out, "%s\n", listfile->sy_idf->id_text);
@@ -461,7 +492,6 @@ setstop(p, kind)
   p->t_address = a;
   if (a != NO_ADDR) {
 	if (! set_or_clear_breakpoint(a, kind)) {
-		error("could not %s breakpoint", kind == SETBP ? "set" : "clear");
 		return 0;
 	}
   }
@@ -496,11 +526,7 @@ settrace(p, kind)
 	if (sc) e = sc->sc_start - 1;
 	else e = 0xffffffff;
   }
-  if (! set_or_clear_trace(a, e, kind)) {
-	error("could not %s trace", kind == SETTRACE ? "set" : "clear");
-	return 0;
-  }
-  return 1;
+  return set_or_clear_trace(a, e, kind);
 }
 
 do_trace(p)
@@ -518,6 +544,15 @@ able(p, kind)
   p_tree	p;
   int		kind;
 {
+  if (!p) {
+	if (stop_reason) {
+		able_item(stop_reason, kind);
+	}
+	else {
+		error("no current stopping point");
+	}
+	return;
+  }
   switch(p->t_oper) {
   case OP_LINK:
 	able(p->t_args[0], kind);
@@ -526,6 +561,8 @@ able(p, kind)
   case OP_INTEGER:
 	able_item((int)p->t_ival, kind);
 	break;
+  default:
+	assert(0);
   }
 }
 
@@ -545,7 +582,6 @@ do_continue(p)
   p_tree	p;
 {
   int count;
-  int first_time = 1;
 
   if (p) {
 	count = p->t_args[0]->t_ival;
@@ -553,38 +589,41 @@ do_continue(p)
 		t_addr	a = get_addr_from_position(&(p->t_args[1]->t_pos));
 		p_scope sc = get_scope_from_addr(a);
 
-		if (a == ILL_ADDR || base_scope(sc) != base_scope(CurrentScope) ||
-		    ! set_pc(a)) {
+		if (a == ILL_ADDR || base_scope(sc) != base_scope(CurrentScope)) {
 			error("cannot continue at line %d",
 			      p->t_args[1]->t_lino);
 			return;
 		}
+		if (! set_pc(a)) {
+			return;
+		}
 	}
   }
   else count = 1;
   while (count--) {
 	if (! send_cont(count==0)) {
-		if (first_time) error("no process");
 		break;
 	}
-	first_time = 0;
+  }
+  if (count > 0) {
+	fprintf(db_out, "Only %d breakpoints skipped\n",
+		p->t_args[0]->t_ival - count);
   }
 }
 
 do_step(p)
   p_tree	p;
 {
-  if (! do_single_step(SETSS, p->t_ival)) {
-	if (! interrupted) error("no process");
+  p = p->t_args[0];
+  if (! do_single_step(SETSS, p ? p->t_ival : 1L)) {
   }
 }
 
 do_next(p)
   p_tree	p;
 {
-
-  if (! do_single_step(SETSSF, p->t_ival)) {
-	if (! interrupted) error("no process");
+  p = p->t_args[0];
+  if (! do_single_step(SETSSF, p? p->t_ival : 1L)) {
   }
 }
 
@@ -594,10 +633,11 @@ do_regs(p)
   p_tree	p;
 {
   t_addr	*buf;
-  int		n = p->t_ival;
+  int		n = 0;
 
+  p = p->t_args[0];
+  if (p) n = p->t_ival;
   if (! (buf = get_EM_regs(n))) {
-	if (! interrupted) error("no process");
 	return;
   }
   fprintf(db_out, "EM registers %d levels back:\n", n);
@@ -615,12 +655,13 @@ do_where(p)
 {
   int i = 0;
   unsigned int cnt;
-  unsigned int maxcnt = p->t_ival;
+  unsigned int maxcnt = 0xffff;
   p_scope sc;
   t_addr *buf;
   t_addr PC;
 
-  if (p->t_ival < 0) {
+  p = p->t_args[0];
+  if (p && p->t_ival < 0) {
 	for (;;) {
 		buf = get_EM_regs(i++);
 		if (! buf || ! buf[AB_OFF]) break;
@@ -634,6 +675,7 @@ do_where(p)
 	i -= maxcnt;
 	if (i < 0) i = 0;
   }
+  else if (p) maxcnt = p->t_ival;
   for (cnt = maxcnt; cnt != 0; cnt--) {
 	t_addr AB;
 
@@ -659,7 +701,16 @@ do_delete(p)
 {
   switch(p->t_oper) {
   case OP_DELETE:
-	do_delete(p->t_args[0]);
+	if (! p->t_args[0]) {
+		if (stop_reason) {
+			remove_from_item_list(stop_reason);
+			stop_reason = 0;
+		}
+		else {
+			error("no current stopping point");
+		}
+	}
+	else do_delete(p->t_args[0]);
 	break;
   case OP_LINK:
 	do_delete(p->t_args[0]);
@@ -681,6 +732,8 @@ do_delete(p)
   	}
   	freenode(p);
 	break;
+  default:
+	assert(0);
   }
 }
 
@@ -702,7 +755,7 @@ do_print(p)
 		}
 	}
 	else if (p != print_command) {
-		freenode(print_command);
+		/* freenode(print_command); No, could be in when-list */
 		print_command = p;
 	}
 	/* fall through */
@@ -746,9 +799,7 @@ do_set(p)
 	free(buf);
 	return;
   }
-  if (! set_bytes(size, buf, a)) {
-	error("could not handle this SET request");
-  }
+  set_bytes(size, buf, a);
   free(buf);
 }
 
@@ -760,13 +811,13 @@ perform(p, a)
   case OP_WHEN:
 	if (p->t_args[1] && ! eval_cond(p->t_args[1])) break;
 	p = p->t_args[2];
-	while (p->t_oper == OP_LINK) {
+	while (p && p->t_oper == OP_LINK) {
 		if (interrupted) return;
-		eval(p->t_args[0]);
+		if (p->t_args[0]) eval(p->t_args[0]);
 		p = p->t_args[1];
 	}
 	if (interrupted) return;
-	eval(p);
+	if (p) eval(p);
 	break;
   case OP_TRACE:
 	if (p->t_args[0] && p->t_args[0]->t_oper == OP_IN) {

+ 0 - 2
util/grind/tree.hh

@@ -13,7 +13,6 @@ typedef struct tree {
 	struct {
 		struct idf *tt_idf;
 		char *tt_str;
-		struct scope *tt_scope;	
 	} tt_x;
 	struct tree *tt_args[MAXARGS];
 	t_position tt_pos;
@@ -23,7 +22,6 @@ typedef struct tree {
 #define t_fval	t_xxxx.tt_fval
 #define t_idf	t_xxxx.tt_x.tt_idf
 #define t_str	t_xxxx.tt_x.tt_str
-#define t_sc	t_xxxx.tt_x.tt_scope
 #define t_args	t_xxxx.tt_args
 #define t_lino t_xxxx.tt_pos.lineno
 #define t_filename t_xxxx.tt_pos.filename

+ 2 - 3
util/grind/type.c

@@ -15,7 +15,7 @@
 
 p_type	int_type, char_type, short_type, long_type, bool_type;
 p_type	uint_type, uchar_type, ushort_type, ulong_type;
-p_type	void_type, incomplete_type;
+p_type	void_type;
 p_type	float_type, double_type;
 p_type	string_type, address_type;
 
@@ -257,7 +257,6 @@ init_types()
   string_type = basic_type(T_STRING, 0L);
   address_type = basic_type(T_POINTER, pointer_size);
   void_type = basic_type(T_VOID, 0L);
-  incomplete_type = basic_type(T_INCOMPLETE, 0L);
   float_type = basic_type(T_REAL, float_size);
   double_type = basic_type(T_REAL, double_size);
 
@@ -324,7 +323,7 @@ clean_tp_tab()
 		if (j) {
 			while (--j > 0) {
 				p_type p = list_row[i].row[j];
-				if (p == incomplete_type) {
+				if (p && p->ty_class == 0) {
 					error("incomplete type (%d,%d) 0x%x", i, j, &list_row[i].row[j]);
 				}
 			}

+ 3 - 3
util/grind/type.hh

@@ -44,8 +44,8 @@ typedef struct type {
   struct symbol	*ty_sym;
   union {
      /* cross references */
-     char	    *typ_tag;
-#define ty_tag		ty_v.typ_tag
+     struct type    *typ_cross;
+#define ty_cross	ty_v.typ_cross
      /* procedures/functions: */
      struct {
 	int	    typ_nparams;
@@ -117,6 +117,6 @@ extern long
 
 extern p_type	char_type, uchar_type, bool_type, int_type,
 		long_type, double_type, string_type, address_type;
-extern p_type	void_type, incomplete_type;
+extern p_type	void_type;
 extern long	int_size, pointer_size, long_size, double_size;
 

+ 8 - 9
util/grind/value.c

@@ -5,6 +5,7 @@
 
 #include "position.h"
 #include "scope.h"
+#include "idf.h"
 #include "symbol.h"
 #include "type.h"
 #include "message.h"
@@ -38,7 +39,6 @@ get_addr(sym, psize)
   case VAR:
 	/* exists if child exists; nm_value contains addres */
 	return (t_addr) sym->sy_name.nm_value;
-	break;
   case VARPAR:
   case LOCVAR:
 	/* first find the stack frame in which it resides */
@@ -51,23 +51,21 @@ get_addr(sym, psize)
 	for (;;) {
 		sc = 0;
 		if (! (EM_regs = get_EM_regs(i++))) {
-			/* no child? */
-			break;
+			return 0;
 		}
 		if (! EM_regs[AB_OFF]) {
-			/* no more frames */
-			break;
+			error("%s not available", sym->sy_idf->id_text);
+			return 0;
 		}
 		sc = base_scope(get_scope_from_addr(EM_regs[PC_OFF]));
 		if (! sc || sc->sc_start > EM_regs[PC_OFF]) {
+			error("%s not available", sym->sy_idf->id_text);
 			sc = 0;
-			break;
+			return 0;
 		}
 		if (sc == symsc) break;		/* found it */
 	}
 
-	if (! sc) break;	/* not found */
-
 	if (sym->sy_class == LOCVAR) {
 		/* Either local variable or value parameter */
 		return EM_regs[sym->sy_name.nm_value < 0 ? LB_OFF : AB_OFF] +
@@ -101,6 +99,7 @@ get_addr(sym, psize)
 		return a;
 	}
   default:
+	error("%s is not a variable", sym->sy_idf->id_text);
 	break;
   }
   return 0;
@@ -162,7 +161,7 @@ get_value(sym, buf, psize)
 		size = *psize;
 		*buf = malloc((unsigned) size);
 		if (! *buf) {
-			error("Could not allocate enough memory");
+			error("could not allocate enough memory");
 			break;
 		}
 		if (get_bytes(size, a, *buf)) {