];
DBS_LLTARGETS = {
- dbx_string.c[type=C-src],
+ db_symtab.c[type=C-src],
DBSpars.c[type=C-src],
DBSpars.h[type=C-incl]
} ;
DBS_LLSRC = {
- dbx_string.g
+ db_symtab.g
} ;
CMD_LLTARGETS = {
} ;
CSRC = {
- dbxread.c,
main.c,
list.c,
tree.c,
position.c,
idf.c,
run.c,
- dump.c,
symbol.c,
print.c,
value.c,
type.c,
rd.c,
- help.c,
+ do_comm.c,
modula-2.c,
c.c
} ;
print_char(c)
int c;
{
- fputc('\'', db_out);
+ putc('\'', db_out);
printchar(c, '\'');
- fputc('\'', db_out);
+ putc('\'', db_out);
}
static int
{
register char *str = s;
- fputc('"', db_out);
+ putc('"', db_out);
while (*str && len-- > 0) printchar(*str++, '"');
- fputc('"', db_out);
+ putc('"', db_out);
}
extern long int_size;
case E_MIN:
fputs("-(", db_out);
print_node(p->t_args[0], 0);
- fputc(')', db_out);
+ putc(')', db_out);
break;
case E_PLUS:
fputs("+(", db_out);
print_node(p->t_args[0], 0);
- fputc(')', db_out);
+ putc(')', db_out);
break;
case E_NOT:
fputs("!(", db_out);
print_node(p->t_args[0], 0);
- fputc(')', db_out);
+ putc(')', db_out);
break;
case E_DEREF:
fputs("*(", db_out);
print_node(p->t_args[0], 0);
- fputc(')', db_out);
+ putc(')', db_out);
break;
case E_BNOT:
fputs("~(", db_out);
print_node(p->t_args[0], 0);
- fputc(')', db_out);
+ putc(')', db_out);
break;
case E_ADDR:
fputs("&(", db_out);
print_node(p->t_args[0], 0);
- fputc(')', db_out);
+ putc(')', db_out);
break;
}
break;
STSTR:"'
STDOT:.
STNUM:0-9
-STSIMP:-,<>{}:`?\\
+STSIMP:-,!<>{}:`?\\
%T#include "class.h"
%Tchar tkclass[] = {
%p
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- * Author: Ceriel J.H. Jacobs
- */
-
-/* U S E O F C H A R A C T E R C L A S S E S */
-
/* $Header$ */
/* As a starter, chars are divided into classes, according to which
token they can be the start of.
- At present such a class number is supposed to fit in 4 bits.
*/
#define class(ch) (tkclass[ch])
-/* Being the start of a token is, fortunately, a mutual exclusive
- property, so, as there are less than 16 classes they can be
- packed in 4 bits.
-*/
-
#define STSKIP 0 /* spaces and so on: skipped characters */
#define STNL 1 /* newline character(s): update linenumber etc. */
#define STGARB 2 /* garbage ascii character: not allowed */
#define STEOI 9 /* End-Of-Information mark */
#define STSIMP 10 /* this character can occur as token */
-/* But occurring inside a token is not, so we need 1 bit for each
- class. This is implemented as a collection of tables to speed up
+/* But occurring inside a token is not an exclusive property,
+ so we need 1 bit for each class.
+ This is implemented as a collection of tables to speed up
the decision whether a character has a special meaning.
*/
#define in_idf(ch) ((unsigned)ch < 0177 && inidf[ch])
| FIND qualified_name(p){ *p = mknode(OP_FIND, *p); }
| WHICH qualified_name(p){ *p = mknode(OP_WHICH, *p); }
| able_command(p)
+| '!' { shellescape(); }
|
]
;
:
LIST
[
- | count(&t1)
+ | position(&t1)
| qualified_name(&t1)
]
[ ',' count(&t2)
[ INTEGER { l = tok.ival; }
| { l = 1; }
]
- position(&pos)?
+ [ AT position(&pos) ]?
{ *p = mknode(OP_CONT, mknode(OP_INTEGER, l), pos); }
;
where(p_tree *p;)
:
IN qualified_name(p) { *p = mknode(OP_IN, *p, (p_tree) 0); }
- position(&((*p)->t_args[1]))?
+ [ AT position(&((*p)->t_args[1])) ]?
|
- position(p)
+ AT position(p)
;
expression(p_tree *p; int level;)
char *str;
}
:
- AT
[ STRING { str = tok.str; }
':'
| { if (! listfile) str = 0;
{
signal(SIGINT, catch_del);
}
+
+static int
+ctch()
+{
+ /* Only for shell escapes ... */
+ signal(SIGINT, ctch);
+}
+
+#define SHBUFSIZ 512
+
+int
+shellescape()
+{
+ register char *p; /* walks through command */
+ static char previous[SHBUFSIZ]; /* previous command */
+ char comm[SHBUFSIZ]; /* space for command */
+ register int cnt; /* prevent array bound errors */
+ register int c; /* current char */
+ register int lastc = 0; /* will contain the previous char */
+
+ p = comm;
+ cnt = SHBUFSIZ-2;
+ while (c = getc(db_in), c != '\n') {
+ switch(c) {
+ case '!':
+ /*
+ * An unescaped ! expands to the previous
+ * command, but disappears if there is none
+ */
+ if (lastc != '\\') {
+ if (*previous) {
+ int len = strlen(previous);
+ if ((cnt -= len) <= 0) break;
+ strcpy(p,previous);
+ p += len;
+ }
+ }
+ else {
+ *p++ = c;
+ }
+ continue;
+ case '%':
+ /*
+ * An unescaped % will expand to the current
+ * filename, but disappears is there is none
+ */
+ if (lastc != '\\') {
+ if (listfile) {
+ int len = strlen(listfile->sy_idf->id_text);
+ if ((cnt -= len) <= 0) break;
+ strcpy(p,listfile->sy_idf->id_text);
+ p += len;
+ }
+ }
+ else {
+ *p++ = c;
+ }
+ continue;
+ default:
+ lastc = c;
+ if (cnt-- <= 0) break;
+ *p++ = c;
+ continue;
+ }
+ break;
+ }
+ *p = '\0';
+ if (c != '\n') {
+ warning("shell command too long");
+ while (c != '\n') c = getc(db_in);
+ }
+ ungetc(c, db_in);
+ strcpy(previous, comm);
+ signal(SIGINT, ctch);
+ cnt = system(comm);
+ signal(SIGINT, catch_del);
+ return cnt;
+}
}
--- /dev/null
+/* $Header$ */
+
+/* Symbol table reader
+*/
+
+{
+#include <alloc.h>
+#include <stb.h>
+#include <assert.h>
+
+#include "position.h"
+#include "file.h"
+#include "type.h"
+#include "symbol.h"
+#include "scope.h"
+#include "class.h"
+#include "idf.h"
+#include "rd.h"
+
+extern char *strindex();
+extern long str2long();
+extern double atof();
+
+extern long pointer_size;
+
+static char *DbPtr; /* current pointer in DBX string */
+static int AllowName; /* set if NAME legal at this point */
+static long ival;
+static double fval;
+static char *strval;
+static int last_index[2];
+static struct outname *currnam;
+static int saw_code;
+
+static struct literal *get_literal_space();
+static struct fields *get_field_space();
+static end_field();
+static char *string_val();
+}
+
+%start DbParser, debugger_string;
+
+%prefix DBS;
+
+%lexical DBSlex;
+
+%onerror DBSonerror;
+
+%token INTEGER, REAL, STRING, NAME;
+
+debugger_string
+ { register p_symbol s;
+ char *str;
+ p_type tmp = 0;
+ }
+:
+ name(&str)
+ [ /* constant name */
+ { s = NewSymbol(str, CurrentScope, CONST, currnam); }
+ 'c' const_name(s)
+
+ | /* type name */
+ { s = NewSymbol(str, CurrentScope, TYPE, currnam); }
+ '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_ENUM ||
+ s->sy_type->ty_class == T_SUBRANGE) &&
+ currnam->on_desc != 0) {
+ s->sy_type->ty_size = currnam->on_desc;
+ }
+ }
+ | /* tag name (only C?) */
+ { s = NewSymbol(str, CurrentScope, TAG, currnam); }
+ '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(); }
+
+ | /* module begin */
+ { s = NewSymbol(str, CurrentScope, MODULE, currnam); }
+ 'M' INTEGER
+ { open_scope(s, 1);
+ s->sy_name.nm_scope = CurrentScope;
+ CurrentScope->sc_start = currnam->on_valu;
+ CurrentScope->sc_proclevel = currnam->on_desc;
+ add_scope_addr(CurrentScope);
+ }
+
+ | /* external procedure */
+ { s = NewSymbol(str, FileScope, PROC, currnam); }
+ 'P' routine(s)
+
+ | /* private procedure */
+ { s = NewSymbol(str, CurrentScope, PROC, currnam); }
+ 'Q' routine(s)
+
+ | /* external function */
+ { s = NewSymbol(str, FileScope, FUNCTION, currnam); }
+ 'F' function(s)
+
+ | /* private function */
+ { s = NewSymbol(str, CurrentScope, FUNCTION, currnam); }
+ 'f' function(s)
+
+ | /* global variable, external */
+ /* maybe we already know it; but we need
+ the type information anyway for other
+ types.
+ */
+ { 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)
+ { if (tmp) s->sy_type = tmp; }
+
+ | /* static variable */
+ { s = NewSymbol(str, CurrentScope, VAR, currnam); }
+ 'S' type(&(s->sy_type), (int *) 0, s)
+
+ | /* static variable, local scope */
+ { s = NewSymbol(str, CurrentScope, VAR, currnam); }
+ 'V' type(&(s->sy_type), (int *) 0, s)
+
+ | /* register variable */
+ { s = NewSymbol(str, CurrentScope, REGVAR, currnam); }
+ 'r' type(&(s->sy_type), (int *) 0, s)
+
+ | /* value parameter */
+ { s = NewSymbol(str, CurrentScope, LOCVAR, currnam); }
+ 'p' type(&(s->sy_type), (int *) 0, s)
+ { add_param_type('p', s); }
+
+ | /* value parameter but address passed */
+ { s = NewSymbol(str, CurrentScope, VARPAR, currnam); }
+ 'i' type(&(s->sy_type), (int *) 0, s)
+ { add_param_type('i', s); }
+
+ | /* variable parameter */
+ { s = NewSymbol(str, CurrentScope, VARPAR, currnam); }
+ 'v' type(&(s->sy_type), (int *) 0, s)
+ { add_param_type('v', s); }
+
+ | /* local variable */
+ { s = NewSymbol(str, CurrentScope, LOCVAR, currnam); }
+ type_name(&(s->sy_type), s)
+
+ | /* function result in Pascal; ignore ??? */
+ { s = NewSymbol(str, CurrentScope, LOCVAR, currnam); }
+ 'X' type_name(&(s->sy_type), s)
+ ]
+ ';'?
+;
+
+name(char **s;)
+:
+ /* anything up to a ':' */
+ NAME { *s = strval; }
+;
+
+const_name(p_symbol cst;)
+ { int type_index[2];
+ long iconst;
+ register char *p;
+ }
+:
+ '='
+ [
+/*
+ 'b' integer_const(&(cst->sy_const.co_ival)) /* boolean */
+/* |
+*/
+ 'c' integer_const(&(cst->sy_const.co_ival)) /* character */
+ { cst->sy_type = char_type; }
+ |
+ 'i' integer_const(&(cst->sy_const.co_ival)) /* integer */
+ { cst->sy_type = long_type; }
+ |
+ 'r' real_const(&(cst->sy_const.co_rval)) /* real */
+ { cst->sy_type = double_type; }
+ |
+ 's' string_const /* string */
+ { cst->sy_const.co_sval = string_val(strval);
+ cst->sy_type = string_type;
+ }
+ |
+ 'e' type_index(type_index) ',' integer_const(&(cst->sy_const.co_ival))
+ /* enumeration constant;
+ * enumeration type, value
+ */
+ { cst->sy_type = *tp_lookup(type_index); }
+
+ |
+ 'S' type_index(type_index)
+ { cst->sy_type = *tp_lookup(type_index);
+ cst->sy_const.co_setval = p =
+ Malloc((unsigned) cst->sy_type->ty_size);
+ }
+ [ ',' integer_const(&iconst)
+ { *p++ = iconst; }
+ ]+
+ /* set constant:
+ * settype, values of the bytes
+ * in the set.
+ */
+ ]
+;
+
+integer_const(long *iconst;)
+ { int sign = 0; }
+:
+ [ '+' | '-' { sign = 1; } ]?
+ INTEGER { *iconst = sign ? -ival : ival; }
+;
+
+real_const(double *f;)
+ { int sign = 0; }
+:
+ [ '+' | '-' { sign = 1; } ]?
+ REAL { *f = sign ? fval : -fval; }
+;
+
+string_const
+:
+ STRING /* has SINGLE quotes! */
+;
+
+type_name(p_type *t; p_symbol sy;)
+ { int type_index[2]; p_type *p; }
+:
+ type_index(type_index) { p = tp_lookup(type_index); }
+ [
+ { 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);
+ }
+ }
+ '='
+ type(p, type_index, sy)
+ |
+ ]
+ { if (*p == 0) *p = new_type();
+ *t = *p;
+ }
+;
+
+type_index(int *type_index;)
+:
+[
+ INTEGER { type_index[0] = 0; type_index[1] = ival; }
+|
+ '(' INTEGER { type_index[0] = ival; }
+ ',' INTEGER { type_index[1] = ival; }
+ ')'
+]
+ { last_index[0] = type_index[0];
+ last_index[1] = type_index[1];
+ }
+;
+
+function(p_symbol p;)
+:
+ { p->sy_type = new_type();
+ p->sy_type->ty_class = T_PROCEDURE;
+ p->sy_type->ty_size = pointer_size;
+ }
+ type(&(p->sy_type->ty_retval), (int *) 0, (p_symbol) 0)
+ { if (CurrentScope != FileScope &&
+ saw_code) {
+ /* if saw_code is not set, it is a nested
+ procedure
+ */
+ close_scope();
+ }
+ saw_code = 0;
+ open_scope(p, 1);
+ p->sy_name.nm_scope = CurrentScope;
+ CurrentScope->sc_start = currnam->on_valu;
+ add_scope_addr(CurrentScope);
+ CurrentScope->sc_proclevel = currnam->on_desc;
+ }
+;
+
+routine(p_symbol p;)
+:
+ { p->sy_type = new_type();
+ p->sy_type->ty_class = T_PROCEDURE;
+ p->sy_type->ty_size = pointer_size;
+ if (CurrentScope != FileScope &&
+ saw_code) {
+ /* if saw_code is not set, it is a nested
+ procedure
+ */
+ close_scope();
+ }
+ saw_code = 0;
+ open_scope(p, 1);
+ p->sy_name.nm_scope = CurrentScope;
+ CurrentScope->sc_start = currnam->on_valu;
+ add_scope_addr(CurrentScope);
+ CurrentScope->sc_proclevel = currnam->on_desc;
+ }
+ INTEGER ';'
+ type(&(p->sy_type->ty_retval), (int *) 0, (p_symbol) 0)
+;
+
+type(p_type *ptp; int *type_index; p_symbol sy;)
+ { register p_type tp = *ptp ? *ptp : new_type();
+ p_type t1 = 0, t2 = 0;
+ long ic1, ic2;
+ int A_used = 0;
+ int tclass;
+ int tp_index[2];
+ char *str;
+ }
+:
+ [
+ /* type cross reference */
+ /* these are used in C for references to a struct, union or
+ * enum that has not been declared (yet)
+ */
+ 'x'
+ [ 's' /* struct */
+ { tclass = T_STRUCT; }
+ | 'u' /* union */
+ { tclass = T_UNION; }
+ | 'e' /* enum */
+ { tclass = T_ENUM; }
+ ]
+ { AllowName = 1; }
+ name(&str)
+ { sy = Lookfromscope(str2idf(str,0),TAG,CurrentScope);
+ 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->ty_class = T_CROSS;
+ tp->ty_size = tclass;
+ sy = NewSymbol(str, CurrentScope, TAG, (struct outname *) 0);
+ sy->sy_type = tp;
+ }
+ }
+ |
+ /* subrange */
+ /* the integer_const's represent the lower and the upper bound.
+ * A subrange type defined as subrange of itself is an integer type.
+ * If the second integer_const == 0, but the first is not, we
+ * have a floating point type with size equal to the first
+ * integer_const.
+ * Upperbound -1 means unsigned int or unsigned long.
+ */
+ 'r' type_index(tp_index) ';'
+ [ 'A' integer_const(&ic1) { A_used = 1; }
+ | integer_const(&ic1)
+ ]
+ ';'
+ [ 'A' integer_const(&ic2) { A_used |= 2; }
+ | integer_const(&ic2)
+ ]
+ { if (tp != *ptp) free_type(tp);
+ tp = subrange_type(A_used,
+ tp_index,
+ ic1,
+ ic2,
+ type_index);
+ }
+ |
+ /* array; first type is bound type, next type
+ * is element type
+ */
+ 'a' type(&t1, (int *) 0, (p_symbol) 0) ';' type(&t2, (int *) 0, (p_symbol) 0)
+ { if (tp != *ptp) free_type(tp);
+ tp = array_type(t1, t2);
+ }
+ |
+ /* structure type */
+ 's' { tp->ty_class = T_STRUCT; }
+ structure_type(tp, sy)
+ |
+ /* union type */
+ 'u' { tp->ty_class = T_UNION; }
+ structure_type(tp, sy)
+ |
+ /* enumeration type */
+ 'e' { tp->ty_class = T_ENUM; }
+ enum_type(tp)
+ |
+ /* pointer type */
+ '*' { tp->ty_class = T_POINTER;
+ tp->ty_size = pointer_size;
+ }
+ type(&(tp->ty_ptrto), (int *) 0, (p_symbol) 0)
+ |
+ /* function type */
+ 'f' { tp->ty_class = T_PROCEDURE;
+ tp->ty_size = pointer_size;
+ }
+ type(&(tp->ty_retval), (int *) 0, (p_symbol) 0)
+/*
+ [ %prefer
+ ',' param_list(tp)
+ |
+ ]
+*/
+ |
+ /* procedure type */
+ '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->ty_class = T_PROCEDURE;
+ tp->ty_size = pointer_size;
+ tp->ty_retval = void_type;
+ }
+ param_list(tp)
+ |
+ /* set type */
+ /* the first integer_const represents the size in bytes,
+ * the second one represents the low bound
+ */
+ 'S' { tp->ty_class = T_SET; }
+ type(&(tp->ty_setbase), (int *) 0, (p_symbol) 0) ';'
+ [
+ integer_const(&(tp->ty_size)) ';'
+ integer_const(&(tp->ty_setlow)) ';'
+ |
+ { set_bounds(tp); }
+ ]
+ |
+ /* file type of Pascal */
+ '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)->ty_class == 0 &&
+ type_index[0] == last_index[0] &&
+ type_index[1] == last_index[1]) {
+ **ptp = *void_type;
+ if (*ptp != tp) free_type(tp);
+ }
+ tp = *ptp;
+ }
+ ]
+ { if (*ptp && *ptp != tp) **ptp = *tp;
+ else *ptp = tp;
+ }
+;
+
+structure_type(register p_type tp; p_symbol sy;)
+ { register struct fields *fldp;
+ char *str;
+ }
+:
+ integer_const(&(tp->ty_size)) /* size in bytes */
+ { open_scope(sy, 0);
+ if (sy) sy->sy_name.nm_scope = CurrentScope;
+ }
+ [
+ name(&str) { fldp = get_field_space(tp, str); }
+ type(&(fldp->fld_type), (int *) 0, (p_symbol) 0) ','
+ integer_const(&(fldp->fld_pos)) ',' /* offset in bits */
+ integer_const(&(fldp->fld_bitsize)) ';' /* size in bits */
+ ]*
+ ';' { end_field(tp);
+ close_scope();
+ }
+;
+
+enum_type(register p_type tp;)
+ { register struct literal *litp;
+ long maxval = 0;
+ register p_symbol s;
+ }
+:
+ [ { litp = get_literal_space(tp); }
+ name(&(litp->lit_name))
+ integer_const(&(litp->lit_val)) ','
+ { if (maxval < litp->lit_val) maxval = litp->lit_val;
+ AllowName = 1;
+ s = NewSymbol(litp->lit_name, CurrentScope, CONST, (struct outname *) 0);
+ s->sy_const.co_ival = litp->lit_val;
+ s->sy_type = tp;
+ }
+ ]*
+ ';' { end_literal(tp, maxval); }
+;
+
+param_list(p_type t;)
+ { register struct param *p;
+ long iconst;
+ }
+:
+ integer_const(&iconst) ';' /* number of parameters */
+ { t->ty_nparams = iconst;
+ t->ty_params = p = (struct param *)
+ Malloc((unsigned)(t->ty_nparams * sizeof(struct param)));
+ }
+ [
+ [ 'p' { p->par_kind = 'p'; }
+ | 'v' { p->par_kind = 'v'; }
+ | 'i' { p->par_kind = 'i'; }
+ ]
+ type(&(p->par_type), (int *) 0, (p_symbol) 0) ';'
+ { t->ty_nbparams +=
+ param_size(p->par_type, p->par_kind);
+ p++;
+ }
+ ]*
+;
+
+{
+static char *db_string;
+static char *DbOldPtr;
+
+static struct outname *
+DbString(n)
+ struct outname *n;
+{
+ currnam = n;
+ DbPtr = n->on_mptr;
+ db_string = DbPtr;
+ AllowName = 1;
+ DbParser();
+ return currnam;
+}
+
+/*ARGSUSED*/
+DBSmessage(n)
+{
+ fatal("error in symbol table string \"%s\", DbPtr = \"%s\", DbOldPtr = \"%s\"",
+ db_string,
+ DbPtr,
+ DbOldPtr);
+
+}
+
+DBSonerror(tk, p)
+ int *p;
+{
+ DbPtr = DbOldPtr;
+/* ??? if (DBSsymb < 0) {
+ while (*p && *p != ';') p++;
+ if (*p) DbPtr = ";";
+ return;
+ }
+*/
+ if (! tk) {
+ while (*p && *p != NAME) p++;
+ if (*p) {
+ AllowName = 1;
+ }
+ }
+ else if (tk == NAME) AllowName = 1;
+}
+
+DBSlex()
+{
+ register char *cp = DbPtr;
+ int allow_name = AllowName;
+ register int c;
+
+ AllowName = 0;
+ DbOldPtr = cp;
+ c = *cp;
+ if (c == '\\' && *(cp+1) == '\0') {
+ currnam++;
+ cp = currnam->on_mptr;
+ DbOldPtr = cp;
+ c = *cp;
+ }
+ if (! c) {
+ DbPtr = cp;
+ return -1;
+ }
+ if ((! allow_name && is_token(c)) || c == ';') {
+ DbPtr = cp+1;
+ return c;
+ }
+ if (is_dig(c)) {
+ int retval = INTEGER;
+
+ while (++cp, is_dig(*cp)) /* nothing */;
+ c = *cp;
+ if (c == '.') {
+ retval = REAL;
+ while (++cp, is_dig(*cp)) /* nothing */;
+ c = *cp;
+ }
+ if (c == 'e' || c == 'E') {
+ char *oldcp = cp;
+
+ cp++;
+ c = *cp;
+ if (c == '-' || c == '+') {
+ cp++;
+ c = *cp;
+ }
+ if (is_dig(c)) {
+ retval = REAL;
+ while (++cp, is_dig(*cp)) /* nothing */;
+ }
+ else cp = oldcp;
+ }
+ c = *cp;
+ *cp = 0;
+ if (retval == INTEGER) {
+ ival = str2long(DbOldPtr, 10);
+ }
+ else {
+ fval = atof(DbOldPtr);
+ }
+ *cp = c;
+ DbPtr = cp;
+ return retval;
+ }
+ if (c == '\'') {
+ cp++;
+ strval = cp;
+ while ((c = *cp) && c != '\'') {
+ if (c == '\\') cp++; /* backslash escapes next character */
+ if (!(c = *cp)) break; /* but not a null byte */
+ cp++;
+ }
+ if (! c) DBSmessage(0); /* no return */
+ *cp = 0;
+ DbPtr = cp + 1;
+ return STRING;
+ }
+ strval = cp;
+ while ((c = *cp) && c != ':' && c != ',') cp++;
+ DbPtr = *cp ? cp+1 : cp;
+ *cp = 0;
+ return NAME;
+}
+
+static struct fields *
+get_field_space(tp, s)
+ register p_type tp;
+ char *s;
+{
+ register struct fields *p;
+ p_symbol sy;
+
+ if (! (tp->ty_nfields & 07)) {
+ tp->ty_fields = (struct fields *)
+ Realloc((char *) tp->ty_fields,
+ (tp->ty_nfields+8)*sizeof(struct fields));
+ }
+ 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;
+}
+
+static
+end_field(tp)
+ register p_type tp;
+{
+ tp->ty_fields = (struct fields *)
+ Realloc((char *) tp->ty_fields,
+ tp->ty_nfields * sizeof(struct fields));
+}
+
+static struct literal *
+get_literal_space(tp)
+ register p_type tp;
+{
+ if (! (tp->ty_nenums & 07)) {
+ tp->ty_literals = (struct literal *)
+ Realloc((char *) tp->ty_literals,
+ (tp->ty_nenums+8)*sizeof(struct literal));
+ }
+ return &tp->ty_literals[tp->ty_nenums++];
+}
+
+static char *
+string_val(s)
+ char *s;
+{
+ register char *ns = s, *os = s;
+ register unsigned int i = 1;
+
+ for (;;) {
+ if (!*os) break;
+ i++;
+ if (*os == '\\') {
+ os++;
+ *ns++ = *os++;
+ }
+ else *ns++ = *os++;
+ }
+ *ns = '\0';
+ return Salloc(s, i);
+}
+
+static char *AckStrings; /* ACK a.out string table */
+static struct outname *AckNames; /* ACK a.out symbol table entries */
+static unsigned int NAckNames; /* Number of ACK symbol table entries */
+static struct outname *EndAckNames; /* &AckNames[NAckNames] */
+
+/* Read the symbol table from file 'f', which is supposed to be an
+ ACK a.out format file. Offer DBX strings to the DBX string parser.
+*/
+int
+DbRead(f)
+ char *f;
+{
+ struct outhead h;
+ register struct outname *n;
+ register struct outname *line_file = 0;
+ long OffsetStrings;
+ int had_lbrac = 0;
+
+ /* Open file, read header, and check magic word */
+ if (! rd_open(f)) {
+ fatal("%s: could not open", f);
+ }
+ rd_ohead(&h);
+ if (BADMAGIC(h) && h.oh_magic != O_CONVERTED) {
+ fatal("%s: not an object file", f);
+ }
+
+ /* Allocate space for name table and read it */
+ AckNames = (struct outname *)
+ Malloc((unsigned)(sizeof(struct outname) * h.oh_nname));
+ AckStrings = Malloc((unsigned) h.oh_nchar);
+ rd_name(AckNames, h.oh_nname);
+ rd_string(AckStrings, h.oh_nchar);
+
+ /* Adjust file offsets in name table to point at strings */
+ OffsetStrings = OFF_CHAR(h);
+ NAckNames = h.oh_nname;
+ EndAckNames = &AckNames[h.oh_nname];
+ for (n = EndAckNames; --n >= AckNames;) {
+ if (n->on_foff) {
+ if ((unsigned)(n->on_foff - OffsetStrings) >= h.oh_nchar) {
+ fatal("%s: error in object file", f);
+ }
+ n->on_mptr = AckStrings + (n->on_foff - OffsetStrings);
+ }
+ else n->on_mptr = 0;
+ }
+
+ /* Offer strings to the DBX string parser if they contain a ':'.
+ Also offer filename-line number information to add_position_addr().
+ Here, the order may be important.
+ */
+ for (n = &AckNames[0]; n < EndAckNames; n++) {
+ int tp = n->on_type >> 8;
+ register p_symbol sym;
+
+ if (tp & (S_STB >> 8)) {
+ switch(tp) {
+#ifdef N_BINCL
+ case N_BINCL:
+ n->on_valu = (long) line_file;
+ line_file = n;
+ break;
+ case N_EINCL:
+ if (line_file) {
+ line_file = (struct outname *) line_file->on_valu;
+ }
+ break;
+#endif
+ case N_SO:
+ if (n->on_mptr[strlen(n->on_mptr)-1] == '/') {
+ /* another N_SO follows ... */
+ break;
+ }
+ while (CurrentScope != PervasiveScope) {
+ close_scope();
+ }
+ saw_code = 0;
+ sym = add_file(n->on_mptr);
+
+ if (! listfile) newfile(sym->sy_idf);
+ open_scope(sym, 0);
+ sym->sy_file->f_scope = CurrentScope;
+ FileScope = CurrentScope;
+ clean_tp_tab();
+ /* fall through */
+ case N_SOL:
+ if (! line_file) line_file = n;
+ else line_file->on_mptr = n->on_mptr;
+ break;
+ case N_MAIN:
+ newfile(FileScope->sc_definedby->sy_idf);
+ break;
+ case N_SLINE:
+ assert(line_file);
+ if (! saw_code && !CurrentScope->sc_bp_opp) {
+ CurrentScope->sc_bp_opp = n->on_valu;
+ if (! CurrentScope->sc_start) {
+ CurrentScope->sc_start = n->on_valu;
+ if (CurrentScope->sc_has_activation_record) {
+ add_scope_addr(CurrentScope);
+ }
+ }
+ }
+ saw_code = 1;
+ add_position_addr(line_file->on_mptr, n);
+ break;
+ case N_LBRAC: /* block, desc = nesting level */
+ if (had_lbrac) {
+ open_scope((p_symbol) 0, 0);
+ saw_code = 0;
+ }
+ else {
+ register p_scope sc =
+ get_scope_from_addr(n->on_valu);
+
+ if (!sc || sc->sc_bp_opp) {
+ had_lbrac = 1;
+ }
+ else CurrentScope = sc;
+ }
+ break;
+#ifdef N_SCOPE
+ case N_SCOPE:
+ if (n->on_mptr && strindex(n->on_mptr, ':')) {
+ n = DbString(n);
+ }
+ break;
+#endif
+ case N_RBRAC: /* end block, desc = nesting level */
+ had_lbrac = 0;
+ if (CurrentScope != FileScope) close_scope();
+ saw_code = 0;
+ break;
+ case N_FUN: /* function, value = address */
+ case N_GSYM: /* global variable */
+ case N_STSYM: /* data, static, value = address */
+ case N_LCSYM: /* bss, static, value = address */
+ case N_RSYM: /* register var, value = reg number */
+ case N_SSYM: /* struct/union el, value = offset */
+ case N_PSYM: /* parameter, value = offset from AP */
+ case N_LSYM: /* local sym, value = offset from FP */
+ if (had_lbrac) {
+ open_scope((p_symbol) 0, 0);
+ saw_code = 0;
+ had_lbrac = 0;
+ }
+ if (n->on_mptr && strindex(n->on_mptr, ':')) {
+ n = DbString(n);
+ }
+ break;
+ default:
+/*
+ if (n->on_mptr && (n->on_type&S_TYP) >= S_MIN) {
+ struct idf *id = str2idf(n->on_mptr, 0);
+
+ sym = new_symbol();
+ sym->sy_next = id->id_def;
+ id->id_def = sym;
+ sym->sy_class = SYMENTRY;
+ sym->sy_onam = *n;
+ sym->sy_idf = id;
+ }
+*/
+ break;
+ }
+ }
+ }
+ close_scope();
+ add_position_addr((char *) 0, (struct outname *) 0);
+ clean_tp_tab();
+ rd_close();
+ return (h.oh_magic == O_CONVERTED);
+}
+}
--- /dev/null
+/* $Header$ */
+
+/* Implementation of the do_ routines */
+
+#include <stdio.h>
+#include <assert.h>
+#include <alloc.h>
+
+#include "operator.h"
+#include "position.h"
+#include "tree.h"
+#include "idf.h"
+#include "Lpars.h"
+#include "type.h"
+#include "expr.h"
+#include "symbol.h"
+#include "scope.h"
+#include "file.h"
+#include "message.h"
+
+extern FILE *db_out;
+extern t_lineno listline, currline;
+extern int stop_reason;
+extern int interrupted;
+
+p_tree print_command;
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the help command */
+
+do_help(p)
+ p_tree p;
+{
+ p = p->t_args[0];
+ if (p && p->t_idf) switch(p->t_idf->id_reserved) {
+ case HELP:
+ fputs("help [ <commandname> ]\n", db_out);
+ fputs("? [ <commandname> ]\n", db_out);
+ fputs(" Print a command summary, or some more help on <commandname>.\n", db_out);
+ return;
+ case LIST:
+ fputs("list [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
+ fputs("l [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
+ fputs(" List lines from the current source file, starting with either\n", db_out);
+ fputs(" line <start> or some lines before the first statement of <func> or\n", db_out);
+ fputs(" the current line. Either list <cnt> lines or <wsize> lines,\n", db_out);
+ fputs(" except when a range is given.\n", db_out);
+ fputs(" <wsize> is the last <cnt> given, or 10.\n", db_out);
+ return;
+ case XFILE:
+ fputs("file [ <name> ]\n", db_out);
+ fputs(" Print the name of the current source file, or change the\n", db_out);
+ fputs(" current source file to <name>.\n", db_out);
+ return;
+ case RUN:
+ fputs("run [ <args> ] [ < <infile> ] [ > <outfile> ]\n", db_out);
+ fputs(" Start executing debuggee with command line arguments <args> and\n", db_out);
+ fputs(" possible redirection of standard input and/or standard output.\n", db_out);
+ return;
+ case RERUN:
+ fputs("rerun\n", db_out);
+ fputs(" repeats the last run command.\n", db_out);
+ return;
+ case STOP:
+ fputs("stop [ <pos> ] [ if <cond> ]\n", db_out);
+ fputs(" Stop execution when position <pos> is reached, and then when\n", db_out);
+ fputs(" <cond> becomes true. If no <pos> is given, stop when <cond>\n", db_out);
+ fputs(" becomes true. If no <cond> is given, stop when <pos> is reached.\n", db_out);
+ fputs(" Either a position or a condition (or both) must be given.\n", db_out);
+ return;
+ case WHEN:
+ fputs("when [ <pos> ] [ if <cond> ] { <command> [ ; <command> ] ... } \n", db_out);
+ fputs(" Execute the <command>s when position <pos> is reached, and then when\n", db_out);
+ fputs(" <cond> becomes true. If no <pos> is given, do this when <cond>\n", db_out);
+ fputs(" becomes true. If no <cond> is given, do this when <pos> is reached.\n", db_out);
+ fputs(" Either a position or a condition (or both) must be given.\n", db_out);
+ return;
+ case CONT:
+ fputs("cont [ <cnt> ] [ at <line> ]\n", db_out);
+ fputs("c [ <cnt> ] [ at <line> ]\n", db_out);
+ fputs(" Continue execution, skipping <cnt> or 1 breakpoints;a\n", db_out);
+ fputs(" if <line> is given, continue at <line>.\n", db_out);
+ return;
+ case STEP:
+ case NEXT:
+ fputs("step [ <cnt> ]\n", db_out);
+ fputs("s [ <cnt> ]\n", db_out);
+ fputs("next [ <cnt> ]\n", db_out);
+ fputs("n [ <cnt> ]\n", db_out);
+ fputs(" Execute the next <cnt> or 1 source line(s).\n", db_out);
+ fputs(" Step (s) steps into function-calls.\n", db_out);
+ fputs(" Next (n) steps past function-calls.\n", db_out);
+ return;
+ case WHERE:
+ fputs("where [ <cnt> ]\n", db_out);
+ fputs("w [ <cnt> ]\n", db_out);
+ fputs(" List all, or the top <cnt> or the bottom -<cnt> active functions.\n", db_out);
+ return;
+ case STATUS:
+ fputs("status\n", db_out);
+ fputs(" display active traces, stops, whens, displays, and dumps.\n", db_out);
+ return;
+ case DELETE:
+ fputs("delete [ <num> [ , <num> ] ... ]\n", db_out);
+ fputs("d [ <num> [ , <num> ] ...] \n", db_out);
+ fputs(" Remove the command(s) corresponding to <num> (as displayed by 'status').\n", db_out);
+ fputs(" If no <num> is given, remove the current stopping point.\n", db_out);
+ return;
+ case SET:
+ fputs("set <desig> to <exp>\n", db_out);
+ fputs(" Assign the value of <exp> to <desig>.\n", db_out);
+ return;
+ case PRINT:
+ fputs("print <exp> [ , <exp> ] ...\n", db_out);
+ fputs("p <exp> [ , <exp> ] ...\n", db_out);
+ fputs(" Print the value of each <exp>.\n", db_out);
+ return;
+ case DISPLAY:
+ fputs("display <exp> [ , <exp> ] ...\n", db_out);
+ fputs(" Print the value of each <exp> whenever the debuggee stops.\n", db_out);
+ return;
+ case DUMP:
+ fputs("dump\n", db_out);
+ fputs(" Saves the state of the debuggee; it can be restored with the restore command.\n", db_out);
+ return;
+ case RESTORE:
+ fputs("restore [ <num> ]\n", db_out);
+ fputs("r [ <num> ]\n", db_out);
+ fputs(" Restore the state of the dump associated with <num>,\n", db_out);
+ fputs(" or restore the state of the last dump.\n", db_out);
+ return;
+ case TRACE:
+ fputs("trace [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
+ fputs("t [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
+ fputs(" Without args, display each source line before execution.\n", db_out);
+ fputs(" In addition, display <exp> in the on-clause.\n", db_out);
+ fputs(" If <pos> is given and indicates a function, only display\n", db_out);
+ fputs(" tracing information while executing this function.\n", db_out);
+ fputs(" If it indicates a line number, only display tracing information\n", db_out);
+ fputs(" whenever the source line is reached.\n", db_out);
+ fputs(" If <cond> is given, only display tracing info when it evaluates to non-zero.\n", db_out);
+ return;
+ case FIND:
+ fputs("find <name>\n", db_out);
+ fputs(" Prints the fully qualified name of all symbols matching <name>.\n", db_out);
+ return;
+ case WHICH:
+ fputs("which <name>\n", db_out);
+ fputs(" Prints the fully qualified name of <name>.\n", db_out);
+ return;
+ case DISABLE:
+ fputs("disable [ <num> [ , <num> ] ... ]\n", db_out);
+ fputs(" Disable the command(s) corresponding to <num> (as displayed by 'status').\n", db_out);
+ fputs(" If no <num> is given, disable the current stopping point.\n", db_out);
+ return;
+ case ENABLE:
+ fputs("enable [ <num> [ , <num> ] ... ]\n", db_out);
+ fputs(" Enable the command(s) corresponding to <num> (as displayed by 'status'.)\n", db_out);
+ fputs(" If no <num> is given, enable the current stopping point (not effective).\n", db_out);
+ return;
+ }
+ fputs("cont [ <cnt> ] [ at <line> ]\n", db_out);
+ fputs("delete [ <num> [ , <num> ] ... ]\n", db_out);
+ fputs("disable [ <num> [ , <num> ] ... ]\n", db_out);
+ fputs("display <exp> [ , <exp> ] ...\n", db_out);
+ fputs("dump\n", db_out);
+ fputs("enable [ <num> [ , <num> ] ... ]\n", db_out);
+ fputs("file [ <name> ]\n", db_out);
+ fputs("find <name>\n", db_out);
+ fputs("help [ <commandname> ]\n", db_out);
+ fputs("list [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
+ fputs("next [ <cnt> ]\n", db_out);
+ fputs("print <exp> [ , <exp> ] ...\n", db_out);
+ fputs("rerun\n", db_out);
+ fputs("restore <num>\n", db_out);
+ fputs("run [ <args> ] [ < <infile> ] [ > <outfile> ]\n", db_out);
+ fputs("set <desig> to <exp>\n", db_out);
+ fputs("status\n", db_out);
+ fputs("step [ <cnt> ]\n", db_out);
+ fputs("stop [ <pos> ] [ if <cond> ]\n", db_out);
+ fputs("trace [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
+ fputs("when [ <pos> ] [ if <cond> ] { <command> [ ; <command> ] ... } \n", db_out);
+ fputs("where [ <cnt> ]\n", db_out);
+ fputs("which <name>\n", db_out);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of dump/restore commands */
+
+extern long pointer_size;
+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;
+
+do_dump(p)
+ p_tree p;
+{
+ struct dump *d = (struct dump *) malloc(sizeof(struct dump));
+
+ if (! d) {
+ error("could not allocate enough memory");
+ return;
+ }
+ if (! get_dump(&d->mglobal, &d->globals, &d->mstack, &d->stack)) {
+ free((char *) d);
+ return;
+ }
+ 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;
+}
+
+do_restore(p)
+ p_tree p;
+{
+ struct dump *d;
+
+ 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;
+
+ if (! d) {
+ error("no dumps");
+ return;
+ }
+
+ if (! put_dump(&d->mglobal, d->globals, &d->mstack, d->stack)) {
+ }
+ perform_items();
+}
+
+free_dump(p)
+ p_tree p;
+{
+ struct dump *d = (struct dump *) p->t_args[0];
+
+ 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);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the find command */
+
+do_find(p)
+ p_tree p;
+{
+ /* Print all identifications of p->t_args[0]. */
+ register p_symbol s;
+ p_tree arg;
+
+ p = p->t_args[0];
+ switch(p->t_oper) {
+ case OP_NAME:
+ s = p->t_idf->id_def;
+ while (s) {
+ pr_sym(s);
+ s = s->sy_next;
+ }
+ break;
+
+ case OP_SELECT:
+ arg = p->t_args[1];
+ assert(arg->t_oper == OP_NAME);
+ s = arg->t_idf->id_def;
+ while (s) {
+ if (consistent(p, s->sy_scope)) {
+ pr_sym(s);
+ }
+ s = s->sy_next;
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the which command */
+
+do_which(p)
+ p_tree p;
+{
+ p_symbol sym = identify(p->t_args[0], 0xffff);
+
+ if ( sym) pr_sym(sym);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the list command */
+
+extern t_addr get_addr_from_node();
+
+do_list(p)
+ p_tree p;
+{
+ int l1, l2;
+ static int wsize = 10;
+
+ if (p->t_args[1]) {
+ l2 = p->t_args[1]->t_ival;
+ if (l2 >= 0) {
+ if (l2 == 0) l2 = 1;
+ wsize = l2;
+ }
+ }
+ else l2 = wsize;
+
+ if (! p->t_args[0]) {
+ l1 = listline;
+ if (! l1) {
+ listline = currline - (wsize/2);
+ l1 = listline;
+ }
+ }
+ else {
+ if (p->t_args[0]->t_oper == OP_AT) {
+ l1 = p->t_args[0]->t_lino;
+ if (p->t_args[0]->t_filename) {
+ newfile(str2idf(p->t_args[0]->t_filename, 0));
+ }
+ }
+ else {
+ t_addr a = get_addr_from_node(p->t_args[0]);
+ p_position pos;
+ p_symbol oldlistfile = listfile;
+
+ if (a == ILL_ADDR) {
+ return;
+ }
+ pos = get_position_from_addr(a);
+ newfile(str2idf(pos->filename, 1));
+ if (listfile != oldlistfile) {
+ warning("switching to file %s", listfile->sy_idf->id_text);
+ }
+ l1 = pos->lineno - (l2 > 0 ? l2 : wsize)/2;
+ if (l1 < 1) l1 = 1;
+ }
+ }
+ if (listfile) {
+ if (l2 < 0) {
+ l2 = -l2;
+ if (l1 > l2) l2 = 1;
+ else l2 -= l1 - 1;
+ }
+ lines(listfile->sy_file, l1, l2);
+ listline = l1 + l2;
+ }
+ else error("no current file");
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the file command */
+
+do_file(p)
+ p_tree p;
+{
+ FILE *f;
+
+ if (p->t_args[0]) {
+ if (! strcmp(p->t_args[0]->t_str, "?")) {
+ register p_symbol sym = PervasiveScope->sc_symbs;
+
+ while (sym) {
+ if (sym->sy_class == FILESYM) {
+ fprintf(db_out, "%s\n", sym->sy_idf->id_text);
+ }
+ sym = sym->sy_prev_sc;
+ }
+ return;
+ }
+ 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);
+ else error("no current file");
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of stop/when command */
+
+setstop(p, kind)
+ p_tree p;
+ int kind;
+{
+ t_addr a = get_addr_from_node(p->t_args[0]);
+
+ if (a == ILL_ADDR) return 0;
+
+ p->t_address = a;
+ if (a != NO_ADDR) {
+ if (! set_or_clear_breakpoint(a, kind)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+do_stop(p)
+ p_tree p;
+{
+ if (! setstop(p, M_SETBP)) {
+ return;
+ }
+ add_to_item_list(p);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the trace command */
+
+settrace(p, kind)
+ p_tree p;
+ int kind;
+{
+ t_addr a, e;
+
+ a = get_addr_from_node(p->t_args[0]);
+ if (a == NO_ADDR) return 1;
+ if (a == ILL_ADDR) return 0;
+ if (p->t_args[0]->t_oper == OP_AT) {
+ e = a;
+ p->t_address = a;
+ }
+ else {
+ p_scope sc = get_next_scope_from_addr(a+1);
+
+ if (sc) e = sc->sc_start - 1;
+ else e = 0xffffffff;
+ }
+ return set_or_clear_trace(a, e, kind);
+}
+
+do_trace(p)
+ p_tree p;
+{
+ p->t_address = NO_ADDR;
+ if (! settrace(p, M_SETTRACE)) {
+ return;
+ }
+ add_to_item_list(p);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the enable/disable commands */
+
+static
+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);
+ able(p->t_args[1], kind);
+ break;
+ case OP_INTEGER:
+ able_item((int)p->t_ival, kind);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+do_enable(p)
+ p_tree p;
+{
+ able(p->t_args[0], 0);
+}
+
+do_disable(p)
+ p_tree p;
+{
+ able(p->t_args[0], 1);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the cont command */
+
+do_continue(p)
+ p_tree p;
+{
+ int count;
+
+ if (p) {
+ count = p->t_args[0]->t_ival;
+ if (p->t_args[1]) {
+ 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)) {
+ 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)) {
+ break;
+ }
+ }
+ if (count > 0) {
+ fprintf(db_out, "Only %d breakpoints skipped\n",
+ p->t_args[0]->t_ival - count);
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the step command */
+
+do_step(p)
+ p_tree p;
+{
+ p = p->t_args[0];
+ if (! singlestep(M_SETSS, p ? p->t_ival : 1L)) {
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the next command */
+
+do_next(p)
+ p_tree p;
+{
+ p = p->t_args[0];
+ if (! singlestep(M_SETSSF, p? p->t_ival : 1L)) {
+ }
+}
+
+extern t_addr *get_EM_regs();
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the regs command (temporarily) */
+
+do_regs(p)
+ p_tree p;
+{
+ t_addr *buf;
+ int n = 0;
+
+ p = p->t_args[0];
+ if (p) n = p->t_ival;
+ if (! (buf = get_EM_regs(n))) {
+ return;
+ }
+ fprintf(db_out, "EM registers %d levels back:\n", n);
+ fprintf(db_out, "\tLocalBase =\t0x%lx\n\tArgumentBase =\t0x%lx\n",
+ (long) buf[LB_OFF], (long) buf[AB_OFF]);
+ fprintf(db_out, "\tProgramCounter=\t0x%lx\n\tHeapPointer = \t0x%lx\n",
+ (long) buf[PC_OFF],
+ (long) buf[HP_OFF]);
+ fprintf(db_out, "\tStackPointer =\t0x%lx\n", (long) buf[SP_OFF]);
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the where command */
+
+/*ARGSUSED*/
+do_where(p)
+ p_tree p;
+{
+ int i = 0;
+ unsigned int cnt;
+ unsigned int maxcnt = 0xffff;
+ p_scope sc;
+ t_addr *buf;
+ t_addr PC;
+
+ p = p->t_args[0];
+ if (p && p->t_ival < 0) {
+ for (;;) {
+ buf = get_EM_regs(i++);
+ if (! buf || ! buf[AB_OFF]) break;
+ PC = buf[PC_OFF];
+ sc = base_scope(get_scope_from_addr(PC));
+ if (! sc || sc->sc_start > PC) break;
+ if (interrupted) return;
+ }
+ i--;
+ maxcnt = - p->t_ival;
+ i -= maxcnt;
+ if (i < 0) i = 0;
+ }
+ else if (p) maxcnt = p->t_ival;
+ for (cnt = maxcnt; cnt != 0; cnt--) {
+ t_addr AB;
+
+ if (interrupted) return;
+ if (! (buf = get_EM_regs(i++))) break;
+ AB = buf[AB_OFF];
+ PC = buf[PC_OFF];
+ if (! AB) break;
+ sc = base_scope(get_scope_from_addr(PC));
+ if (! sc || sc->sc_start > PC) break;
+ fprintf(db_out, "%s(", sc->sc_definedby->sy_idf->id_text);
+ print_params(sc->sc_definedby->sy_type, AB, has_static_link(sc));
+ fputs(") ", db_out);
+ print_position(PC, 0);
+ fputs("\n", db_out);
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the delete command */
+
+extern p_tree remove_from_item_list();
+
+do_delete(p)
+ p_tree p;
+{
+ switch(p->t_oper) {
+ case OP_DELETE:
+ 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]);
+ do_delete(p->t_args[1]);
+ break;
+ case OP_INTEGER:
+ p = remove_from_item_list((int) p->t_ival);
+
+ if (p) switch(p->t_oper) {
+ case OP_WHEN:
+ case OP_STOP:
+ setstop(p, M_CLRBP);
+ break;
+ case OP_TRACE:
+ settrace(p, M_CLRTRACE);
+ break;
+ case OP_DUMP:
+ free_dump(p);
+ }
+ freenode(p);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the print command */
+
+do_print(p)
+ p_tree p;
+{
+ char *buf = 0;
+ char *format = 0;
+ long size;
+ p_type tp;
+
+ switch(p->t_oper) {
+ case OP_PRINT:
+ if (p->t_args[0] == 0) {
+ p = print_command;
+ if (p == 0) {
+ error("no previous print command");
+ break;
+ }
+ }
+ else if (p != print_command) {
+ /* freenode(print_command); No, could be in when-list */
+ print_command = p;
+ }
+ /* fall through */
+ case OP_DISPLAY:
+ do_print(p->t_args[0]);
+ break;
+ case OP_LINK:
+ do_print(p->t_args[0]);
+ do_print(p->t_args[1]);
+ break;
+ default:
+ if (interrupted || ! eval_expr(p, &buf, &size, &tp)) return;
+ print_node(p, 0);
+ fputs(" = ", db_out);
+ if (p->t_oper == OP_FORMAT) {
+ format = p->t_args[1]->t_str;
+ }
+ print_val(tp, size, buf, 0, 0, format);
+ if (buf) free(buf);
+ fputs("\n", db_out);
+ break;
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+/* implementation of the set command */
+
+do_set(p)
+ p_tree p;
+{
+ char *buf = 0;
+ long size, size2;
+ p_type tp, tp2;
+ t_addr a;
+
+ if (interrupted || ! eval_desig(p->t_args[0], &a, &size, &tp) ||
+ ! eval_expr(p->t_args[1], &buf, &size2, &tp2) ||
+ ! convert(&buf, &size2, &tp2, tp, size)) {
+ if (buf) free(buf);
+ return;
+ }
+
+ if (interrupted) {
+ free(buf);
+ return;
+ }
+ set_bytes(size, buf, a);
+ free(buf);
+}
+
/* one routine for each unary operator */
static int
-do_not(p, pbuf, psize, ptp)
+not_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_bnot(p, pbuf, psize, ptp)
+bnot_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_deref(p, pbuf, psize, ptp)
+deref_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_addr(p, pbuf, psize, ptp)
+addr_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_unmin(p, pbuf, psize, ptp)
+unmin_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_unplus(p, pbuf, psize, ptp)
+unplus_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
static int (*un_op[])() = {
0,
- do_not,
- do_deref,
+ not_op,
+ deref_op,
0,
0,
0,
0,
0,
0,
- do_unplus,
- do_unmin,
+ unplus_op,
+ unmin_op,
0,
0,
0,
0,
0,
0,
- do_bnot,
+ bnot_op,
0,
0,
0,
- do_addr
+ addr_op
};
static p_type
}
static int
-do_andor(p, pbuf, psize, ptp)
+andor_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_arith(p, pbuf, psize, ptp)
+arith_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_sft(p, pbuf, psize, ptp)
+sft_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_cmp(p, pbuf, psize, ptp)
+cmp_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_in(p, pbuf, psize, ptp)
+in_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_array(p, pbuf, psize, ptp)
+array_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_select(p, pbuf, psize, ptp)
+select_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
}
static int
-do_derselect(p, pbuf, psize, ptp)
+derselect_op(p, pbuf, psize, ptp)
p_tree p;
char **pbuf;
long *psize;
0,
0,
0,
- do_andor,
- do_andor,
- do_arith,
- do_arith,
- do_arith,
- do_arith,
- do_in,
- do_array,
- do_arith,
- do_arith,
- do_arith,
- do_cmp,
- do_cmp,
- do_cmp,
- do_cmp,
- do_cmp,
- do_cmp,
- do_select,
- do_arith,
- do_arith,
- do_arith,
+ andor_op,
+ andor_op,
+ arith_op,
+ arith_op,
+ arith_op,
+ arith_op,
+ in_op,
+ array_op,
+ arith_op,
+ arith_op,
+ arith_op,
+ cmp_op,
+ cmp_op,
+ cmp_op,
+ cmp_op,
+ cmp_op,
+ cmp_op,
+ select_op,
+ arith_op,
+ arith_op,
+ arith_op,
0,
- do_derselect,
- do_sft,
- do_sft,
+ derselect_op,
+ sft_op,
+ sft_op,
0
};
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- * Author: Ceriel J.H. Jacobs
- */
-
-/* I N S T A N T I A T I O N O F I D F P A C K A G E */
-
/* $Header$ */
+/* Instantiation of idf package */
+
#include "position.h"
#include "file.h"
#include "idf.h"
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- * Author: Ceriel J.H. Jacobs
- */
-
-/* U S E R D E C L A R E D P A R T O F I D F */
-
/* $Header$ */
+/* User-declared part of idf structure */
+
struct id_u {
int id_res;
struct symbol *id_df;
&& (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 (mess_type != M_DB_SS && mess_type != M_OK) break;
if (! p->t_args[1] || eval_cond(p->t_args[1])) {
if (! stop_reason) stop_reason = i->i_itemno;
stopping = 1;
&& (p->t_address == a || p->t_address == NO_ADDR)) {
switch(p->t_oper) {
case OP_TRACE:
- if ((! stopping && mess_type != END_SS)
+ if ((! stopping && mess_type != M_END_SS)
|| p->t_args[2] || ! may_stop) {
perform(p, a);
}
int n;
{
register p_item i = item_list.il_first, prev = 0;
- p_tree p = 0;
+ p_tree p;
while (i) {
if (i->i_itemno == n) break;
prev = i;
i = i->i_next;
}
- if (i) {
- if (prev) {
- prev->i_next = i->i_next;
- }
- 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--;
- free_item(i);
+ if (! i) {
+ error("no item %d in current status", n);
+ return 0;
}
+ if (i->i_itemno == stop_reason) stop_reason = 0;
+ if (prev) {
+ prev->i_next = i->i_next;
+ }
+ 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--;
+ free_item(i);
return p;
}
switch(p->t_oper) {
case OP_STOP:
case OP_WHEN:
- setstop(p, kind ? CLRBP : SETBP);
+ setstop(p, kind ? M_CLRBP : M_SETBP);
break;
case OP_TRACE:
- settrace(p, kind ? CLRTRACE : SETTRACE);
+ settrace(p, kind ? M_CLRTRACE : M_SETTRACE);
break;
}
}
}
}
-do_items()
+perform_items()
{
register p_item i = item_list.il_first;
+/* $Header$ */
+
#include <stdio.h>
#include <varargs.h>
init_types();
init_scope();
init_languages();
- if (DbxRead(AckObj) && AObj == 0) AObj = AckObj;
+ if (DbRead(AckObj) && AObj == 0) AObj = AckObj;
else if (AObj == 0) AObj = "a.out";
reserve(tkidf);
reserve(shorts);
}
prompt();
Commands();
- if (eof_seen) fputc('\n', db_out);
+ if (eof_seen) putc('\n', db_out);
exit(0);
}
}
}
-/*VARARGS1*/
+/*VARARGS*/
fatal(va_alist)
va_dcl
{
extern int errorgiven;
-/*VARARGS1*/
+/*VARARGS*/
error(va_alist)
va_dcl
{
errorgiven = 1;
}
-/*VARARGS1*/
+/*VARARGS*/
warning(va_alist)
va_dcl
{
struct message_hdr {
int m_type;
/* Possible values of m_type: */
-#define DB_RUN 020000 /* set for commands that cause child to run */
-#define SETBP 0 /* set breakpoint at address in m_size */
-#define CLRBP 1 /* clear breakpoint at address in m_size */
-#define SETSS (2|DB_RUN) /* set single stepping, # of steps in m_size */
-#define SETSSF (3|DB_RUN) /* set single stepping, counting calls as one step */
-#define GETEMREGS 4 /* get EM registers, m_size contains level */
-#define GETBYTES 5 /* get data; m_size contains size, m_buf contains address */
-#define GETSTR 6 /* get string; m_buf contains address */
-#define SETBYTES 7 /* set data; m_buf contains address, m_size contains size */
-#define CALL 8 /* call function;
+#define M_DB_RUN 020000 /* set for commands that cause child to run */
+#define M_SETBP 0 /* set breakpoint at address in m_size */
+#define M_CLRBP 1 /* clear breakpoint at address in m_size */
+#define M_SETSS (2|M_DB_RUN) /* set single stepping, # of steps in m_size */
+#define M_SETSSF (3|M_DB_RUN) /* set single stepping, counting calls as one step */
+#define M_GETEMREGS 4 /* get EM registers, m_size contains level */
+#define M_GETBYTES 5 /* get data; m_size contains size, m_buf contains address */
+#define M_GETSTR 6 /* get string; m_buf contains address */
+#define M_SETBYTES 7 /* set data; m_buf contains address, m_size contains size */
+#define M_CALL 8 /* call function;
m_size contains size of parameter buffer,
m_buf contains address + size of function result
*/
-#define CONT (9|DB_RUN) /* continue */
-#define SETEMREGS 10 /* set EM registers, m_size contains level
+#define M_CONT (9|M_DB_RUN) /* continue */
+#define M_SETEMREGS 10 /* set EM registers, m_size contains level
Actually, only the program counter is set.
*/
-#define DB_SS 040000 /* debugger wants single stepping (to be orred with
+#define M_DB_SS 040000 /* debugger wants single stepping (to be orred with
SETSS(F) or CONT
*/
-#define CLRSS 12 /* clear single stepping */
-#define DUMP 13 /* dump command */
-#define DGLOB 14 /* data area */
-#define DSTACK 15 /* stack area */
-#define SETTRACE 16 /* start tracing; range in m_mes */
-#define CLRTRACE 17 /* end tracing */
+#define M_CLRSS 12 /* clear single stepping */
+#define M_DUMP 13 /* dump command */
+#define M_DGLOB 14 /* data area */
+#define M_DSTACK 15 /* stack area */
+#define M_SETTRACE 16 /* start tracing; range in m_mes */
+#define M_CLRTRACE 17 /* end tracing */
-#define OK 50 /* answer of child to most messages */
-#define FAIL 51 /* answer of child when something goes wrong */
-#define DATA 52 /* answer of child when data requested */
-#define END_SS 53 /* when stopped because of user single stepping */
-#define INTR 54 /* sent on interrupt */
+#define M_OK 50 /* answer of child to most messages */
+#define M_FAIL 51 /* answer of child when something goes wrong */
+#define M_DATA 52 /* answer of child when data requested */
+#define M_END_SS 53 /* when stopped because of user single stepping */
+#define M_INTR 54 /* sent on interrupt */
long m_size; /* size */
char m_buf[BUFLEN]; /* some of the data required included in message */
};
break;
}
if (i > 1) {
- fputc(',', db_out);
+ putc(',', db_out);
}
fprintf(db_out, "\n%*c", i > 1 ? indent : indent - 4, ' ');
}
break;
}
if (i > 1) {
- fputc(',', db_out);
+ putc(',', db_out);
}
fprintf(db_out, "\n%*c", i > 1 ? indent : indent - 4, ' ');
}
curr_stop = m.m_size;
CurrentScope = get_scope_from_addr(curr_stop);
}
- do_items();
- if (! restoring && ! item_addr_actions(curr_stop, OK, 1)) {
+ perform_items();
+ if (! restoring && ! item_addr_actions(curr_stop, M_OK, 1)) {
send_cont(1);
}
else if (! restoring) {
error("no process");
return 0;
}
- if (m->m_type & DB_RUN) {
+ if (m->m_type & M_DB_RUN) {
disable_intr = 0;
stop_reason = 0;
}
}
disable_intr = 1;
if ((interrupted || child_interrupted) && ! child_dead) {
- while (child_interrupted && answer.m_type != INTR) {
+ while (child_interrupted && answer.m_type != M_INTR) {
if (! ugetm(&answer)) {
child_dead = 1;
break;
}
a = answer.m_size;
type = answer.m_type;
- if (m->m_type & DB_RUN) {
+ if (m->m_type & M_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)) {
+ ( type == M_DB_SS || type == M_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);
+ if ((m->m_type & ~ M_DB_SS) != M_CONT) {
+ m->m_type = M_CONT | (m->m_type & M_DB_SS);
}
continue;
}
- if (type != END_SS && single_stepping) {
- m->m_type = CLRSS;
+ if (type != M_END_SS && single_stepping) {
+ m->m_type = M_CLRSS;
if (! uputm(m) || ! ugetm(&answer)) return 0;
}
single_stepping = 0;
}
switch(answer.m_type) {
- case FAIL:
+ case M_FAIL:
error("could not get value");
return 0;
- case INTR:
+ case M_INTR:
error("interrupted");
return 0;
- case DATA:
+ case M_DATA:
return ureceive(to, answer.m_size);
default:
assert(0);
t_addr from;
char *to;
{
- return getbytes(size, from, to, GETBYTES);
+ return getbytes(size, from, to, M_GETBYTES);
}
int
t_addr from;
char *to;
{
- int retval = getbytes(size, from, to, GETSTR);
+ int retval = getbytes(size, from, to, M_GETSTR);
to[(int)answer.m_size] = 0;
return retval;
{
struct message_hdr m;
- m.m_type = SETBYTES;
+ m.m_type = M_SETBYTES;
m.m_size = size;
put_int(m.m_buf, pointer_size, (long) to);
return;
}
switch(answer.m_type) {
- case FAIL:
+ case M_FAIL:
error("could not handle this SET request");
break;
- case INTR:
+ case M_INTR:
error("interrupted");
break;
- case OK:
+ case M_OK:
break;
default:
assert(0);
{
struct message_hdr m;
- m.m_type = DUMP;
+ m.m_type = M_DUMP;
if (! could_send(&m, 0)) {
return 0;
}
switch(answer.m_type) {
- case FAIL:
+ case M_FAIL:
error("request for DUMP failed");
return 0;
- case INTR:
+ case M_INTR:
error("interrupted");
return 0;
- case DGLOB:
+ case M_DGLOB:
break;
default:
assert(0);
if (*globbuf) free(*globbuf);
return 0;
}
- assert(stackmessage->m_type == DSTACK);
+ assert(stackmessage->m_type == M_DSTACK);
*stackbuf = malloc((unsigned) stackmessage->m_size);
if (! ureceive(*stackbuf, stackmessage->m_size)) {
if (*globbuf) free(*globbuf);
static t_addr buf[5];
register t_addr *to = &buf[0];
- m.m_type = GETEMREGS;
+ m.m_type = M_GETEMREGS;
m.m_size = level;
if (! could_send(&m, 0)) {
return 0;
}
switch(answer.m_type) {
- case FAIL:
+ case M_FAIL:
error("request for registers failed");
return 0;
- case INTR:
+ case M_INTR:
error("interrupted");
return 0;
- case GETEMREGS:
+ case M_GETEMREGS:
break;
default:
assert(0);
{
struct message_hdr m;
- m.m_type = SETEMREGS;
+ m.m_type = M_SETEMREGS;
m.m_size = 0;
put_int(m.m_buf+PC_OFF*pointer_size, pointer_size, (long)PC);
if (! could_send(&m, 0)) return 0;
switch(answer.m_type) {
- case FAIL:
+ case M_FAIL:
error("could not set PC to %lx", (long) PC);
return 0;
- case INTR:
+ case M_INTR:
error("interrupted");
return 0;
- case OK:
+ case M_OK:
return 1;
default:
assert(0);
{
struct message_hdr m;
- m.m_type = (CONT | (db_ss ? DB_SS : 0));
+ m.m_type = (M_CONT | (db_ss ? M_DB_SS : 0));
m.m_size = 0;
return could_send(&m, stop_message) && child_pid;
}
int
-do_single_step(type, count)
+singlestep(type, count)
int type;
long count;
{
struct message_hdr m;
- m.m_type = type | (db_ss ? DB_SS : 0);
+ m.m_type = type | (db_ss ? M_DB_SS : 0);
m.m_size = count;
single_stepping = 1;
if (could_send(&m, 1) && child_pid) return 1;
m.m_type = type;
m.m_size = a;
- if (debug) printf("%s breakpoint at 0x%lx\n", type == SETBP ? "setting" : "clearing", (long) a);
+ if (debug) printf("%s breakpoint at 0x%lx\n", type == M_SETBP ? "setting" : "clearing", (long) a);
if (child_pid && ! could_send(&m, 0)) {
}
m.m_type = 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 (debug) printf("%s trace at [0x%lx,0x%lx]\n", type == M_SETTRACE ? "setting" : "clearing", (long) start, (long) end);
if (child_pid && ! could_send(&m, 0)) {
return 0;
}
-/* Scope mechanism */
-
/* $Header$ */
+/* Scope mechanism */
+
#include <assert.h>
#include <alloc.h>
#include <out.h>
-/* scope structure */
-
/* $Header$ */
+/* scope structure */
+
typedef struct scope {
struct scope *sc_static_encl; /* linked list of enclosing scopes */
struct symbol *sc_symbs; /* symbols defined in this scope */
+/* $Header$ */
+
/* For the time being ... */
#define SZ_INT 4
/* Determine if the OP_SELECT tree indicated by 'p' could lead to scope 'sc'.
*/
-static int
+int
consistent(p, sc)
p_tree p;
p_scope sc;
}
}
-static
pr_sym(s)
p_symbol s;
{
fprintf(db_out, "%s\n", s->sy_idf->id_text);
}
-/* Print all identifications of p->t_args[0].
-*/
-do_find(p)
- p_tree p;
-{
- register p_symbol s;
- p_tree arg;
-
- p = p->t_args[0];
- switch(p->t_oper) {
- case OP_NAME:
- s = p->t_idf->id_def;
- while (s) {
- pr_sym(s);
- s = s->sy_next;
- }
- break;
-
- case OP_SELECT:
- arg = p->t_args[1];
- assert(arg->t_oper == OP_NAME);
- s = arg->t_idf->id_def;
- while (s) {
- if (consistent(p, s->sy_scope)) {
- pr_sym(s);
- }
- s = s->sy_next;
- }
- break;
-
- default:
- assert(0);
- }
-}
-
-do_which(p)
- p_tree p;
-{
- p_symbol sym = identify(p->t_args[0], 0xffff);
-
- if ( sym) pr_sym(sym);
-}
-
resolve_cross(tp)
p_type tp;
{
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- * Author: Ceriel J.H. Jacobs
- */
-
-/* T O K E N D E F I N I T I O N S */
-
/* $Header$ */
#include "tokenname.h"
-/*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- * Author: Ceriel J.H. Jacobs
- */
-
-/* T O K E N N A M E S T R U C T U R E */
-
/* $Header$ */
struct tokenname { /* Used for defining the name of a
extern FILE *db_out;
t_lineno currline;
-static t_lineno listline;
-extern long pointer_size;
+t_lineno listline;
extern char *strrindex();
extern int interrupted;
-extern int stop_reason;
-
-p_tree print_command;
-
-static int wsize = 10;
/*VARARGS1*/
p_tree
free_tree(p);
}
-static t_addr
+t_addr
get_addr_from_node(p)
p_tree p;
{
if (p && operators[p->t_oper].op_fun) (*operators[p->t_oper].op_fun)(p);
}
-do_list(p)
- p_tree p;
-{
- int l1, l2;
-
- if (p->t_args[1]) {
- l2 = p->t_args[1]->t_ival;
- if (l2 >= 0) {
- if (l2 == 0) l2 = 1;
- wsize = l2;
- }
- }
- else l2 = wsize;
-
- if (! p->t_args[0]) {
- l1 = listline;
- if (! l1) {
- listline = currline - (wsize/2);
- l1 = listline;
- }
- }
- else {
- if (p->t_args[0]->t_oper == OP_INTEGER) {
- l1 = p->t_args[0]->t_ival;
- }
- else {
- t_addr a = get_addr_from_node(p->t_args[0]);
- p_position pos;
-
- if (a == ILL_ADDR) {
- return;
- }
- pos = get_position_from_addr(a);
- newfile(str2idf(pos->filename, 1));
- l1 = pos->lineno - (l2 > 0 ? l2 : wsize)/2;
- if (l1 < 1) l1 = 1;
- }
- }
- if (listfile) {
- if (l2 < 0) {
- l2 = -l2;
- if (l1 > l2) l2 = 1;
- else l2 -= l1 - 1;
- }
- lines(listfile->sy_file, l1, l2);
- listline = l1 + l2;
- }
- else error("no current file");
-}
-
-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);
- else error("no current file");
-}
-
newfile(id)
register struct idf *id;
{
find_language(strrindex(id->id_text, '.'));
}
-setstop(p, kind)
- p_tree p;
- int kind;
-{
- t_addr a = get_addr_from_node(p->t_args[0]);
-
- if (a == ILL_ADDR) return 0;
-
- p->t_address = a;
- if (a != NO_ADDR) {
- if (! set_or_clear_breakpoint(a, kind)) {
- return 0;
- }
- }
- return 1;
-}
-
-do_stop(p)
- p_tree p;
-{
- if (! setstop(p, SETBP)) {
- return;
- }
- add_to_item_list(p);
-}
-
-settrace(p, kind)
- p_tree p;
- int kind;
-{
- t_addr a, e;
-
- a = get_addr_from_node(p->t_args[0]);
- if (a == NO_ADDR) return 1;
- if (a == ILL_ADDR) return 0;
- if (p->t_args[0]->t_oper == OP_AT) {
- e = a;
- p->t_address = a;
- }
- else {
- p_scope sc = get_next_scope_from_addr(a+1);
-
- if (sc) e = sc->sc_start - 1;
- else e = 0xffffffff;
- }
- return set_or_clear_trace(a, e, kind);
-}
-
-do_trace(p)
- p_tree p;
-{
- p->t_address = NO_ADDR;
- if (! settrace(p, SETTRACE)) {
- return;
- }
- add_to_item_list(p);
-}
-
-static
-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);
- able(p->t_args[1], kind);
- break;
- case OP_INTEGER:
- able_item((int)p->t_ival, kind);
- break;
- default:
- assert(0);
- }
-}
-
-do_enable(p)
- p_tree p;
-{
- able(p->t_args[0], 0);
-}
-
-do_disable(p)
- p_tree p;
-{
- able(p->t_args[0], 1);
-}
-
-do_continue(p)
- p_tree p;
-{
- int count;
-
- if (p) {
- count = p->t_args[0]->t_ival;
- if (p->t_args[1]) {
- 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)) {
- 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)) {
- break;
- }
- }
- if (count > 0) {
- fprintf(db_out, "Only %d breakpoints skipped\n",
- p->t_args[0]->t_ival - count);
- }
-}
-
-do_step(p)
- p_tree p;
-{
- p = p->t_args[0];
- if (! do_single_step(SETSS, p ? p->t_ival : 1L)) {
- }
-}
-
-do_next(p)
- p_tree p;
-{
- p = p->t_args[0];
- if (! do_single_step(SETSSF, p? p->t_ival : 1L)) {
- }
-}
-
-extern t_addr *get_EM_regs();
-
-do_regs(p)
- p_tree p;
-{
- t_addr *buf;
- int n = 0;
-
- p = p->t_args[0];
- if (p) n = p->t_ival;
- if (! (buf = get_EM_regs(n))) {
- return;
- }
- fprintf(db_out, "EM registers %d levels back:\n", n);
- fprintf(db_out, "\tLocalBase =\t0x%lx\n\tArgumentBase =\t0x%lx\n",
- (long) buf[LB_OFF], (long) buf[AB_OFF]);
- fprintf(db_out, "\tProgramCounter=\t0x%lx\n\tHeapPointer = \t0x%lx\n",
- (long) buf[PC_OFF],
- (long) buf[HP_OFF]);
- fprintf(db_out, "\tStackPointer =\t0x%lx\n", (long) buf[SP_OFF]);
-}
-
-/*ARGSUSED*/
-do_where(p)
- p_tree p;
-{
- int i = 0;
- unsigned int cnt;
- unsigned int maxcnt = 0xffff;
- p_scope sc;
- t_addr *buf;
- t_addr PC;
-
- p = p->t_args[0];
- if (p && p->t_ival < 0) {
- for (;;) {
- buf = get_EM_regs(i++);
- if (! buf || ! buf[AB_OFF]) break;
- PC = buf[PC_OFF];
- sc = base_scope(get_scope_from_addr(PC));
- if (! sc || sc->sc_start > PC) break;
- if (interrupted) return;
- }
- i--;
- maxcnt = - p->t_ival;
- i -= maxcnt;
- if (i < 0) i = 0;
- }
- else if (p) maxcnt = p->t_ival;
- for (cnt = maxcnt; cnt != 0; cnt--) {
- t_addr AB;
-
- if (interrupted) return;
- if (! (buf = get_EM_regs(i++))) break;
- AB = buf[AB_OFF];
- PC = buf[PC_OFF];
- if (! AB) break;
- sc = base_scope(get_scope_from_addr(PC));
- if (! sc || sc->sc_start > PC) break;
- fprintf(db_out, "%s(", sc->sc_definedby->sy_idf->id_text);
- print_params(sc->sc_definedby->sy_type, AB, has_static_link(sc));
- fputs(") ", db_out);
- print_position(PC, 0);
- fputs("\n", db_out);
- }
-}
-
-extern p_tree remove_from_item_list();
-
-do_delete(p)
- p_tree p;
-{
- switch(p->t_oper) {
- case OP_DELETE:
- 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]);
- do_delete(p->t_args[1]);
- break;
- case OP_INTEGER:
- p = remove_from_item_list((int) p->t_ival);
-
- if (p) switch(p->t_oper) {
- case OP_WHEN:
- case OP_STOP:
- setstop(p, CLRBP);
- break;
- case OP_TRACE:
- settrace(p, CLRTRACE);
- break;
- case OP_DUMP:
- free_dump(p);
- }
- freenode(p);
- break;
- default:
- assert(0);
- }
-}
-
-do_print(p)
- p_tree p;
-{
- char *buf = 0;
- char *format = 0;
- long size;
- p_type tp;
-
- switch(p->t_oper) {
- case OP_PRINT:
- if (p->t_args[0] == 0) {
- p = print_command;
- if (p == 0) {
- error("no previous print command");
- break;
- }
- }
- else if (p != print_command) {
- /* freenode(print_command); No, could be in when-list */
- print_command = p;
- }
- /* fall through */
- case OP_DISPLAY:
- do_print(p->t_args[0]);
- break;
- case OP_LINK:
- do_print(p->t_args[0]);
- do_print(p->t_args[1]);
- break;
- default:
- if (interrupted || ! eval_expr(p, &buf, &size, &tp)) return;
- print_node(p, 0);
- fputs(" = ", db_out);
- if (p->t_oper == OP_FORMAT) {
- format = p->t_args[1]->t_str;
- }
- print_val(tp, size, buf, 0, 0, format);
- if (buf) free(buf);
- fputs("\n", db_out);
- break;
- }
-}
-
-do_set(p)
- p_tree p;
-{
- char *buf = 0;
- long size, size2;
- p_type tp, tp2;
- t_addr a;
-
- if (interrupted || ! eval_desig(p->t_args[0], &a, &size, &tp) ||
- ! eval_expr(p->t_args[1], &buf, &size2, &tp2) ||
- ! convert(&buf, &size2, &tp2, tp, size)) {
- if (buf) free(buf);
- return;
- }
-
- if (interrupted) {
- free(buf);
- return;
- }
- set_bytes(size, buf, a);
- free(buf);
-}
-
perform(p, a)
register p_tree p;
t_addr a;