From: ceriel Date: Fri, 21 Sep 1990 16:58:20 +0000 (+0000) Subject: added manual page, some improvements X-Git-Tag: release-5-5~1526 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=096e8368c5588d11db1342ce17a3c9c8516d5964;p=ack.git added manual page, some improvements --- diff --git a/util/grind/commands.g b/util/grind/commands.g index 51e52d072..84da6d5aa 100644 --- a/util/grind/commands.g +++ b/util/grind/commands.g @@ -19,7 +19,6 @@ #include "expr.h" extern char *Salloc(); -extern t_lineno currline; extern FILE *db_in; int errorgiven; @@ -126,6 +125,7 @@ list_command(p_tree *p;) [ ',' lin_num(&t2) | { t2 = mknode(OP_INTEGER, t1->t_ival); } ] + | qualified_name(&t1) ] { *p = mknode(OP_LIST, t1, t2); } ; @@ -348,8 +348,8 @@ position(p_tree *p;) AT [ STRING { str = tok.str; } ':' - | { if (! currfile) str = 0; - else str = currfile->sy_idf->id_text; + | { if (! listfile) str = 0; + else str = listfile->sy_idf->id_text; } ] lin_num(&lin) { *p = mknode(OP_AT, lin->t_ival, str); diff --git a/util/grind/dbx_string.g b/util/grind/dbx_string.g index bf777a7ad..ce7aaa001 100644 --- a/util/grind/dbx_string.g +++ b/util/grind/dbx_string.g @@ -55,7 +55,7 @@ debugger_string | /* type name */ { s = NewSymbol(str, CurrentScope, TYPE, currnam); } - 't' type_name(&(s->sy_type)) + 't' type_name(&(s->sy_type), s) { if (! s->sy_type->ty_sym) s->sy_type->ty_sym = s; } | /* tag name (only C?) */ @@ -102,43 +102,43 @@ debugger_string tmp = s->sy_type; } else s = NewSymbol(str, FileScope, VAR, currnam); } - 'G' type(&(s->sy_type), (int *) 0) + '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' type(&(s->sy_type), (int *) 0, s) | /* static variable, local scope */ { s = NewSymbol(str, CurrentScope, VAR, currnam); } - 'V' type(&(s->sy_type), (int *) 0) + 'V' type(&(s->sy_type), (int *) 0, s) | /* register variable */ { s = NewSymbol(str, CurrentScope, REGVAR, currnam); } - 'r' type(&(s->sy_type), (int *) 0) + 'r' type(&(s->sy_type), (int *) 0, s) | /* value parameter */ { s = NewSymbol(str, CurrentScope, LOCVAR, currnam); } - 'p' type(&(s->sy_type), (int *) 0) + '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) + '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) + '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)) + type_name(&(s->sy_type), s) | /* function result in Pascal; ignore ??? */ { s = NewSymbol(str, CurrentScope, LOCVAR, currnam); } - 'X' type_name(&(s->sy_type)) + 'X' type_name(&(s->sy_type), s) ] ';'? ; @@ -216,13 +216,13 @@ string_const STRING /* has SINGLE quotes! */ ; -type_name(p_type *t;) +type_name(p_type *t; p_symbol sy;) { int type_index[2]; p_type *p; } : type_index(type_index) [ '=' - type(t, type_index) + type(t, type_index, sy) { p = tp_lookup(type_index); if (*p && *p != incomplete_type) { if (!((*p)->ty_flags & T_CROSS)) @@ -261,7 +261,7 @@ tag_name(p_symbol t;) : type_index(type_index) '=' - type(&(t->sy_type), type_index) + type(&(t->sy_type), type_index, t) { p = tp_lookup(type_index); if (*p && *p != incomplete_type) { if (!((*p)->ty_flags & T_CROSS)) @@ -284,7 +284,7 @@ function(p_symbol p;) p->sy_type->ty_class = T_PROCEDURE; p->sy_type->ty_size = pointer_size; } - type(&(p->sy_type->ty_retval), (int *) 0) + 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 @@ -321,10 +321,10 @@ routine(p_symbol p;) CurrentScope->sc_proclevel = currnam->on_desc; } INTEGER ';' - type(&(p->sy_type->ty_retval), (int *) 0) + type(&(p->sy_type->ty_retval), (int *) 0, (p_symbol) 0) ; -type(p_type *ptp; int *type_index;) +type(p_type *ptp; int *type_index; p_symbol sy;) { register p_type tp = 0; p_type t1, t2; long ic1, ic2; @@ -355,7 +355,7 @@ type(p_type *ptp; int *type_index;) * integer_const. * Upperbound -1 means unsigned int or unsigned long. */ - 'r' type_name(&t1) ';' + 'r' type_name(&t1, (p_symbol) 0) ';' [ 'A' integer_const(&ic1) { A_used = 1; } | integer_const(&ic1) ] @@ -373,16 +373,16 @@ type(p_type *ptp; int *type_index;) /* array; first type is bound type, next type * is element type */ - 'a' type(&t1, (int *) 0) ';' type(&t2, (int *) 0) + 'a' type(&t1, (int *) 0, (p_symbol) 0) ';' type(&t2, (int *) 0, (p_symbol) 0) { *ptp = array_type(t1, t2); } | /* structure type */ 's' { tp = new_type(); tp->ty_class = T_STRUCT; } - structure_type(tp) + structure_type(tp, sy) | /* union type */ 'u' { tp = new_type(); tp->ty_class = T_UNION; } - structure_type(tp) + structure_type(tp, sy) | /* enumeration type */ 'e' { tp = new_type(); tp->ty_class = T_ENUM; } @@ -392,13 +392,13 @@ type(p_type *ptp; int *type_index;) '*' { tp = new_type(); tp->ty_class =T_POINTER; tp->ty_size = pointer_size; } - type(&(tp->ty_ptrto), (int *) 0) + type(&(tp->ty_ptrto), (int *) 0, (p_symbol) 0) | /* function type */ 'f' { tp = new_type(); tp->ty_class = T_PROCEDURE; tp->ty_size = pointer_size; } - type(&(tp->ty_retval), (int *) 0) + type(&(tp->ty_retval), (int *) 0, (p_symbol) 0) /* [ %prefer ',' param_list(tp) @@ -410,7 +410,7 @@ type(p_type *ptp; int *type_index;) 'Q' { tp = new_type(); tp->ty_class = T_PROCEDURE; tp->ty_size = pointer_size; } - type(&(tp->ty_retval), (int *) 0) + type(&(tp->ty_retval), (int *) 0, (p_symbol) 0) ',' param_list(tp) | /* another procedure type */ @@ -425,7 +425,7 @@ type(p_type *ptp; int *type_index;) * the second one represents the low bound */ 'S' { tp = new_type(); tp->ty_class = T_SET; } - type(&(tp->ty_setbase), (int *) 0) ';' + type(&(tp->ty_setbase), (int *) 0, (p_symbol) 0) ';' [ integer_const(&(tp->ty_size)) ';' integer_const(&(tp->ty_setlow)) ';' @@ -435,9 +435,9 @@ type(p_type *ptp; int *type_index;) | /* file type of Pascal */ 'L' { tp = new_type(); tp->ty_class = T_FILE; } - type(&(tp->ty_fileof), (int *) 0) + type(&(tp->ty_fileof), (int *) 0, (p_symbol) 0) | - type_name(ptp) + type_name(ptp, (p_symbol) 0) { if (type_index && *ptp == incomplete_type && type_index[0] == last_index[0] && @@ -449,19 +449,18 @@ type(p_type *ptp; int *type_index;) { if (! *ptp) *ptp = tp; } ; -structure_type(register p_type tp;) +structure_type(register p_type tp; p_symbol sy;) { register struct fields *fldp; - register p_symbol s; + char *str; } : integer_const(&(tp->ty_size)) /* size in bytes */ - { open_scope((p_symbol) 0, 0); } - [ { fldp = get_field_space(tp); } - name(&(fldp->fld_name)) - { s = NewSymbol(fldp->fld_name, CurrentScope, FIELD, currnam); - s->sy_field = fldp; + { open_scope(sy, 0); + if (sy) sy->sy_name.nm_scope = CurrentScope; } - type(&(fldp->fld_type), (int *) 0) ',' + [ + 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 */ ]* @@ -504,7 +503,7 @@ param_list(p_type t;) | 'v' { p->par_kind = 'v'; } | 'i' { p->par_kind = 'i'; } ] - type(&(p->par_type), (int *) 0) ';' + type(&(p->par_type), (int *) 0, (p_symbol) 0) ';' { t->ty_nbparams += param_size(p->par_type, p->par_kind); p++; @@ -638,15 +637,23 @@ DBSlex() } static struct fields * -get_field_space(tp) +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)); } - return &tp->ty_fields[tp->ty_nfields++]; + p = &tp->ty_fields[tp->ty_nfields++]; + p->fld_name = s; + sy = NewSymbol(s, CurrentScope, FIELD, currnam); + sy->sy_field = p; + return p; } static diff --git a/util/grind/dbxread.c b/util/grind/dbxread.c index 62ef146fd..255680394 100644 --- a/util/grind/dbxread.c +++ b/util/grind/dbxread.c @@ -99,7 +99,7 @@ DbxRead(f) saw_code = 0; sym = add_file(n->on_mptr); - if (! currfile) newfile(sym->sy_idf); + if (! listfile) newfile(sym->sy_idf); open_scope(sym, 0); sym->sy_file->f_scope = CurrentScope; FileScope = CurrentScope; diff --git a/util/grind/grind.1 b/util/grind/grind.1 new file mode 100644 index 000000000..be8c400ab --- /dev/null +++ b/util/grind/grind.1 @@ -0,0 +1,293 @@ +.\" $Header$ +.TH GRIND 1ACK +.SH NAME +grind \- source-level debugger for ACK +.SH SYNOPSIS +.B grind +[ +.I +] +[ +.I +] +.SH DESCRIPTION +.B Grind +is a utility for source-level debugging and execution of +programs written in C or Modula-2 (Pascal will be added later). +Its operation resembles the operation of +.IR dbx , +a source-level debugger +available on many Unix systems. However, some +.B Grind +commands are not available in +.IR dbx , +and some more +.I dbx +commands are not available in +.BR grind , +and some things are just plain different. +.LP +.I +is an object file, produced by +.IR ack (1ACK) +with the +.B \-g +option to include a symbol table. +.LP +If no +.I +is specified, "a.out" is used. +.LP +For some machines, the debugger does not recognize the object file +format. For these machines, the result of the +.IR led (6ACK) +program must be saved and offered to +.BR grind . +.SH USAGE +Some +.B grind +commands take an expression argument. +.SS Expressions +.B Grind expressions +are combinations of variables, constants, and operators. +The syntax and the operators depend on the source language of the program +being debugged. However, the type rules are probably less strict than the +rules of this language. For instance, in Modula-2 one cannot combine +values of type INTEGER with values of type REAL in an expression without +using conversion routines. In +.BR grind , +the conversions needed are performed automatically. +Expressions cannot involve strings, structures, or +arrays, although elements of structures or arrays may be used. +.SS Operators +.LP +.B Grind +supports operators for addition, subtraction, multiplication, division, +remainder, bitwise or, bitwise xor, bitwise and, boolean or, +boolean and, left-shift, right-shift, address-of, dereference, less than, +less than or equal, equal, not equal, greater than, greater than or equal, +selection. +.LP +The syntax and priority of these operators depends on the source language. +Parentheses can be used for grouping. +.SS "Scope Rules" +.LP +.B dbx +uses the current file and function to resolve scope conflicts. +Their values are updated as files and functions are entered and exited +during execution. +Names can also be qualified with procedure- or module names, as in +\fImodule\fP`\fIproc\fP`\fIname\fP. +.B Grind +tries to be intelligent about names, so qualification is only needed when +names are used for more than one object in a program and the current scope +does not help. +.SS "Positions" +In general, there are two ways to specify a position; the first way is +to specify filename and linenumber, in a so-called at-clause, like this: +.RS +\fBat\fP [ "\fIfilename\fP": ] \fIlinenumber\fP +.RE +The +.I filename +part is optional. +The second way is to specify a function name, like this: +.RS +\fBin \fIfunction\fP +.RE +This indicates the first statement within the named function (except for +the trace command discussed later). +.SS "Commands" +.TP +.B \s+2^\s0C +Interrupt. Stop the program being debugged and enter +.BR grind . +.TP +\fBrun\fP [ \fIargs\fP ] [ < \fIinfile\fP ] [ > \fIoutfile\fP ] +Start executing +.I +with command line arguments +.IR args , +and possible redirection of standard input and/or standard output. +.TP +.B rerun +Repeats the last +.B run +command. +\fBcont\fP [ \fBat\fP \fIsourceline\fP ] +Continue execution from where it stopped, or, if \fIsourceline\fP is +given, at that source line. +.TP +\fBtrace\fP [ \fBon\fP \fIexpression\fP ] [ \fIposition\fP ] [ \fBif\fP \fIcondition\fP ] +Display tracing information. +If no argument is specified, each source line is displayed before +execution. +In addition, if an \fBon\fP-clause is given, the value of the expression +is printed. +If a position is given there are two possibilities: if the position is +given as \fBin\fP \fIfunction\fP, then the tracing information is +displayed only while executing the function or +procedure +.IR function . +If the position is given as \fBat\fP \fIlinenumber\fP, +then the tracing information is displayed only whenever the source line +indicated is reached. +If a condition is given, tracing information is only displayed when +.I condition +is true. +.TP +\fBstop\fP [ \fIposition\fP ] [ \fBif\fP \fIcondition\fP ] +Stop execution when the +.I position +is reached, and then when +.I condition +becomes true. +If no position is given, stop when +.I condition +becomes true. +If no condition is given, stop when +.I position +is reached. +Either a position or a condition (or both) must be given. +.TP +\fBwhen\fP [ \fIposition\fP ] [ \fBif\fP \fIcondition\fP ] { \fIcommand\fP [ ; \fIcommand ] ... } +Execute the +.B grind +.IR command (s) +when the +.I position +is reached, and then when +.I condition +becomes true. +If no position is given, stop when +.I condition +becomes true. +If no condition is given, stop when +.I position +is reached. +Either a position or a condition (or both) must be given. +.TP +\fBprint\fP \fIexpression\fP [ ',' \fIexpression\fP ] ... +Print the value of each expression. +.TP +\fBdisplay\fP \fIexpression\fP [ ',' \fIexpression\fP ] ... +Print the value of each expression whenever the program stops. +.TP +.B dump +Saves the data (global data + stack) of the program. These data can +be restore with the +.B restore +command discussed later. +.B Dump +and +.B restore +combinations can be used as a poor man's implementation of an "undo" +facility. +.TP +.B status +Display active +.BR trace , +.BR stop , +.BR when , +and +.B display +commands, and associated command numbers. +Also display current +.B dump +records. +.TP +\fBdelete\fP \fIcommandnumber\fP +Remove the command corresponding to \fIcommandnumber\fP +(as displayed by +.BR status ). +.TP +\fBrestore\fP \fIcommandnumber\fP +Restore the data corresponding to the dump of \fIcommandnumber\fP +(as displayed by +.BR status ). +This restores the values of all variables of the program to the values +at the time the dump was made. The program counter is also restored. +This effectively puts the program back into the state it was when the +dump was made, except for file-handling: the state of the files that +the program handles is not changed. +Apart from this, +.B restore +even works when the program is finished. +.TP +\fBstep\fP [ \fIn\fP ] +Execute the next +.I n +source lines. +If omitted, +.I n +is taken to be 1. +This command steps into functions. +.TP +\fBnext\fP [ \fIn\fP ] +Execute the next +.I n +source lines. +If omitted, +.I n +is taken to be 1. +.B Next +steps past function-calls. +.TP +\fBwhich\fP \fIname\fP +Print the fully-qualified name of the given name. +.TP +\fBfind\fP \fIname\fP +Print the fully qualified name of all symbols matching +.IR name . +.TP +\fBset\fP \fIexpression\fP \fBto\fP \fIexpression\fP +Assign the value of the second +.I expression +to the designator indicated by the first +.IR expression . +Needless to say, the first +.I expression +must indicate a designator (something that can be assigned to). +If the types do not match, +.B grind +tries to apply conversions. +.TP +\fBwhere\fP [ \fIn\fP ] +List all, or the top +.IR n , +active functions on the stack. +.TP +\fBfile\fP [ \fIfilename\fP ] +.br +Print the name of the current source file, or +change the current source file to +.IR filename . +.TP +\fBlist\fP [ \fIstartline\fP [ , \fIendline\fP ] | \fIfunction\fP ] +If no arguments are given, list the next ten lines from current source file, +if a +.I startline +is given, list from +.I startline +through +.IR endline , +or +list from five lines above, to five lines below +the first statement of +.IR function . +.TP +.B quit +Exit +.BR grind . +.SH ENVIRONMENT +P.M. +.SH SEE ALSO +.BR ack (1ACK). +.BR led (6ACK). +.SH BUGS +.LP +.B Grind +does not correctly handle bit-fields. +.LP +.B Grind +does not understand WITH statements. diff --git a/util/grind/list.c b/util/grind/list.c index 5beaa4935..b93db10e5 100644 --- a/util/grind/list.c +++ b/util/grind/list.c @@ -13,7 +13,6 @@ extern char *dirs[]; extern FILE *fopen(); extern FILE *db_out; extern t_lineno currline; -#define window_size 21 static int mk_filnm(dir, file, newname) @@ -55,6 +54,7 @@ open_file(fn, mode, ffn) return NULL; } +#define window_size 21 /* Print a window of window_size lines around line "line" of file "file". */ @@ -103,7 +103,7 @@ lines(file, l1, l2) for (n = l1; n <= l2; n++) { register int c; - fprintf(db_out, "%c%5d\t", n == currline ? '>' : ' ', n); + fprintf(db_out, "%c%5d\t", currfile && file == currfile->sy_file && n == currline ? '>' : ' ', n); do { c = getc(f); if (c != EOF) putc(c, db_out); diff --git a/util/grind/main.c b/util/grind/main.c index f00e2207f..4862e4e7c 100644 --- a/util/grind/main.c +++ b/util/grind/main.c @@ -7,14 +7,13 @@ #include "symbol.h" #include "scope.h" -static char *usage = "Usage: %s [-d] [] []"; +static char *usage = "Usage: %s [] []"; static char *progname; char *AckObj; char *AObj; char *dirs[] = { "", 0 }; FILE *db_out; FILE *db_in; -t_lineno currline; int debug; extern struct tokenname tkidf[]; extern char *strindex(); diff --git a/util/grind/run.c b/util/grind/run.c index a686178cb..7feb0f825 100644 --- a/util/grind/run.c +++ b/util/grind/run.c @@ -19,24 +19,25 @@ #define MAXARG 128 extern char *strncpy(); +extern struct idf *str2idf(); + extern char *AObj; -extern t_lineno currline; extern FILE *db_out; extern int debug; -extern struct idf *str2idf(); extern long pointer_size; static int child_pid; /* process id of child */ static int to_child, from_child; /* file descriptors for communication */ static int child_status; static int restoring; +static int fild1[2], fild2[2]; /* pipe file descriptors */ int db_ss; +t_lineno currline, listline; static int catch_sigpipe(); static int stopped(); static int uputm(), ugetm(); -static int fild1[2], fild2[2]; /* pipe file descriptors */ int init_run() @@ -289,10 +290,8 @@ stopped(s, a) if (s) { fprintf(db_out, "%s ", s); pos = print_position((t_addr) a, 1); - newfile(str2idf(pos->filename, 1)); - currline = pos->lineno; fputs("\n", db_out); - lines(currfile->sy_file, (int)currline, (int)currline); + list_position(pos); } return 1; } diff --git a/util/grind/symbol.c b/util/grind/symbol.c index ae2bac64b..2592e7c3c 100644 --- a/util/grind/symbol.c +++ b/util/grind/symbol.c @@ -17,7 +17,7 @@ #include "tree.h" #include "operator.h" -p_symbol currfile; +p_symbol currfile, listfile; extern FILE *db_out; @@ -141,6 +141,11 @@ def_scope(s) case PROC: case FUNCTION: case MODULE: + case TYPE: + case VAR: + case REGVAR: + case LOCVAR: + case VARPAR: return s->sy_name.nm_scope; } return 0; @@ -163,7 +168,8 @@ consistent(p, sc) switch(p->t_oper) { case OP_NAME: - sym = Lookfromscope(p->t_idf, FILELINK|FILESYM|PROC|FUNCTION|MODULE, sc->sc_static_encl); +#define CLASS (FILELINK|FILESYM|PROC|FUNCTION|MODULE|TYPE|VAR|REGVAR|LOCVAR|VARPAR) + sym = Lookfromscope(p->t_idf, CLASS, sc->sc_static_encl); if (sym) { target_sc = def_scope(sym); while (sc && sc != target_sc) { @@ -175,7 +181,7 @@ consistent(p, sc) case OP_SELECT: arg = p->t_args[1]; - sym = Lookfromscope(arg->t_idf, FILELINK|FILESYM|PROC|FUNCTION|MODULE, sc->sc_static_encl); + sym = Lookfromscope(arg->t_idf, CLASS, sc->sc_static_encl); if (sym) { target_sc = def_scope(sym); while (sc && sc != target_sc) { @@ -322,7 +328,6 @@ pr_sym(s) do_find(p) p_tree p; { - p_symbol sym = 0; register p_symbol s; p_tree arg; @@ -340,7 +345,6 @@ do_find(p) arg = p->t_args[1]; assert(arg->t_oper == OP_NAME); s = arg->t_idf->id_def; - sym = 0; while (s) { if (consistent(p, s->sy_scope)) { pr_sym(s); diff --git a/util/grind/symbol.hh b/util/grind/symbol.hh index 6ca2d2cc4..4fa89ba68 100644 --- a/util/grind/symbol.hh +++ b/util/grind/symbol.hh @@ -56,4 +56,4 @@ typedef struct symbol { extern p_symbol NewSymbol(), Lookup(), Lookfromscope(), add_file(); extern p_symbol identify(); -extern p_symbol currfile; +extern p_symbol currfile, listfile; diff --git a/util/grind/tree.c b/util/grind/tree.c index e443cc9fb..df84b78fe 100644 --- a/util/grind/tree.c +++ b/util/grind/tree.c @@ -19,11 +19,13 @@ #include "expr.h" extern FILE *db_out; -extern t_lineno currline; +extern t_lineno currline, listline; extern long pointer_size; extern char *strrindex(); p_tree run_command; +t_lineno list_line; + /*VARARGS1*/ p_tree @@ -104,6 +106,55 @@ freenode(p) free_tree(p); } +static t_addr +get_addr(p) + p_tree p; +{ + t_addr a = ILL_ADDR; + register p_symbol sym; + + if (! p) return NO_ADDR; + if (p->t_address != 0) return p->t_address; + switch(p->t_oper) { + case OP_AT: + if (! p->t_filename && + (! listfile || ! (p->t_filename = listfile->sy_idf->id_text))) { + error("no current file"); + break; + } + a = get_addr_from_position(&(p->t_pos)); + if (a == ILL_ADDR) { + error("could not determine address of \"%s\":%d", + p->t_filename, p->t_lino); + break; + } + p->t_address = a; + break; + + case OP_IN: + a = get_addr(p->t_args[0]); + p->t_address = a; + break; + + case OP_NAME: + case OP_SELECT: + sym = identify(p, FUNCTION|PROC|MODULE); + if (! sym) { + break; + } + if (! sym->sy_name.nm_scope || ! sym->sy_name.nm_scope->sc_bp_opp) { + error("could not determine address of \"%s\"", p->t_str); + break; + } + a = sym->sy_name.nm_scope->sc_bp_opp; + break; + + default: + assert(0); + } + return a; +} + print_node(p, top_level) register p_tree p; { @@ -169,7 +220,7 @@ print_node(p, top_level) break; case OP_WHERE: fputs("where", db_out); - if (p->t_ival != 0x7fffffff) fprintf(" %ld", p->t_ival); + if (p->t_ival != 0x7fffffff) fprintf(db_out, " %ld", p->t_ival); break; case OP_CONT: fputs("cont", db_out); @@ -301,11 +352,36 @@ eval(p) do_list(p) p_tree p; { - if (currfile) { - lines(currfile->sy_file, - p->t_args[0] ? (int) p->t_args[0]->t_ival : (int) currline-4, - p->t_args[1] ? (int) p->t_args[1]->t_ival : (int) currline+5); - currline = p->t_args[1] ? p->t_args[1]->t_ival + 1 : currline + 10; + int l1, l2; + + if (! p->t_args[0]) { + l1 = listline; + l2 = listline + 9; + } + else { + if (p->t_args[0]->t_oper == OP_INTEGER) { + l1 = p->t_args[0]->t_ival; + assert(p->t_args[1] != 0); + l2 = p->t_args[1]->t_ival; + } + else { + t_addr a = get_addr(p->t_args[0]); + p_position pos; + + if (a == ILL_ADDR) { + error("could not determine address"); + return; + } + pos = get_position_from_addr(a); + newfile(str2idf(pos->filename, 1)); + l1 = pos->lineno - 5; + if (l1 < 1) l1 = 1; + l2 = l1+9; + } + } + if (listfile) { + lines(listfile->sy_file, l1, l2); + listline = l2+1; } else fprintf(db_out, "no current file\n"); } @@ -316,7 +392,7 @@ do_file(p) if (p->t_args[0]) { newfile(p->t_args[0]->t_idf); } - else if (currfile) fprintf(db_out, "%s\n", currfile->sy_idf->id_text); + else if (listfile) fprintf(db_out, "%s\n", listfile->sy_idf->id_text); else fprintf(db_out, "no current file\n"); } @@ -325,69 +401,20 @@ newfile(id) { register p_symbol sym = Lookup(id, PervasiveScope, FILESYM); - if (currfile != sym) currline = 1; - currfile = sym; - if (! currfile) { - currline = 1; - currfile = add_file(id->id_text); - currfile->sy_file->f_scope = FileScope; + if (listfile != sym) listline = 1; + listfile = sym; + if (! listfile) { + listline = 1; + listfile = add_file(id->id_text); + listfile->sy_file->f_scope = FileScope; } find_language(strrindex(id->id_text, '.')); } -static t_addr -get_pos(p) - p_tree p; -{ - t_addr a = ILL_ADDR; - register p_symbol sym; - - if (! p) return NO_ADDR; - if (p->t_address != 0) return p->t_address; - switch(p->t_oper) { - case OP_AT: - if (! p->t_filename && - (! currfile || ! (p->t_filename = currfile->sy_idf->id_text))) { - error("no current file"); - break; - } - a = get_addr_from_position(&(p->t_pos)); - if (a == ILL_ADDR) { - error("could not determine address of \"%s\":%d", - p->t_filename, p->t_lino); - break; - } - p->t_address = a; - break; - - case OP_IN: - a = get_pos(p->t_args[0]); - p->t_address = a; - break; - - case OP_NAME: - case OP_SELECT: - sym = identify(p, FUNCTION|PROC|MODULE); - if (! sym) { - break; - } - if (! sym->sy_name.nm_scope || ! sym->sy_name.nm_scope->sc_bp_opp) { - error("could not determine address of \"%s\"", p->t_str); - break; - } - a = sym->sy_name.nm_scope->sc_bp_opp; - break; - - default: - assert(0); - } - return a; -} - do_stop(p) p_tree p; { - t_addr a = get_pos(p->t_args[0]); + t_addr a = get_addr(p->t_args[0]); if (a == ILL_ADDR) { return; @@ -410,7 +437,7 @@ do_trace(p) p->t_address = NO_ADDR; if (p->t_args[0]) { - a = get_pos(p->t_args[0]); + a = get_addr(p->t_args[0]); if (a == ILL_ADDR) return; if (p->t_args[0]->t_oper == OP_AT) { e = a; @@ -542,7 +569,7 @@ do_delete(p) if (p) switch(p->t_oper) { case OP_WHEN: case OP_STOP: { - t_addr a = get_pos(p->t_args[0]); + t_addr a = get_addr(p->t_args[0]); if (a != ILL_ADDR && a != NO_ADDR) { set_or_clear_breakpoint(a, CLRBP); @@ -550,7 +577,7 @@ do_delete(p) break; } case OP_TRACE: { - t_addr a = get_pos(p->t_args[0]); + t_addr a = get_addr(p->t_args[0]); if (a != ILL_ADDR && a != NO_ADDR) { t_addr e; @@ -642,16 +669,20 @@ perform(p, a) break; } } - { - p_position pos = get_position_from_addr(a); - - newfile(str2idf(pos->filename, 1)); - currline = pos->lineno; - lines(currfile->sy_file, (int)currline, (int)currline); - if (p->t_args[2]) do_print(p->t_args[2]); - } + list_position(get_position_from_addr(a)); + if (p->t_args[2]) do_print(p->t_args[2]); break; default: assert(0); } } + +list_position(pos) + p_position pos; +{ + newfile(str2idf(pos->filename, 1)); + currfile = listfile; + currline = pos->lineno; + listline = currline-5; + lines(currfile->sy_file, (int)currline, (int)currline); +}