added manual page, some improvements
authorceriel <none@none>
Fri, 21 Sep 1990 16:58:20 +0000 (16:58 +0000)
committerceriel <none@none>
Fri, 21 Sep 1990 16:58:20 +0000 (16:58 +0000)
util/grind/commands.g
util/grind/dbx_string.g
util/grind/dbxread.c
util/grind/grind.1 [new file with mode: 0644]
util/grind/list.c
util/grind/main.c
util/grind/run.c
util/grind/symbol.c
util/grind/symbol.hh
util/grind/tree.c

index 51e52d0..84da6d5 100644 (file)
@@ -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);
index bf777a7..ce7aaa0 100644 (file)
@@ -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
index 62ef146..2556803 100644 (file)
@@ -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 (file)
index 0000000..be8c400
--- /dev/null
@@ -0,0 +1,293 @@
+.\" $Header$
+.TH GRIND 1ACK
+.SH NAME
+grind \- source-level debugger for ACK
+.SH SYNOPSIS
+.B grind
+[
+.I <ACK object file>
+]
+[
+.I <object file>
+]
+.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 <object file>
+is an object file, produced by
+.IR ack (1ACK)
+with the
+.B \-g
+option to include a symbol table.
+.LP
+If no
+.I <object file>
+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 <object file>
+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.
index 5beaa49..b93db10 100644 (file)
@@ -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);
index f00e220..4862e4e 100644 (file)
@@ -7,14 +7,13 @@
 #include "symbol.h"
 #include "scope.h"
 
-static char    *usage = "Usage: %s [-d] [<ack.out>] [<a.out>]";
+static char    *usage = "Usage: %s [<ack.out>] [<a.out>]";
 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();
index a686178..7feb0f8 100644 (file)
 #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;
 }
index ae2bac6..2592e7c 100644 (file)
@@ -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);
index 6ca2d2c..4fa89ba 100644 (file)
@@ -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;
index e443cc9..df84b78 100644 (file)
 #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);
+}