On Wed, May 09, 2018 at 11:35:42AM +0200, Martin Pieuchot wrote:
> On 09/05/18(Wed) 12:13, Artturi Alm wrote:
> > On Wed, May 09, 2018 at 10:23:41AM +0200, Martin Pieuchot wrote:
> > > On 09/05/18(Wed) 07:48, Artturi Alm wrote:
> > > > On Tue, May 08, 2018 at 01:44:39AM +0300, Artturi Alm wrote:
> > > 
> > > 
> > > No bug are irrelevant to fix.  But working with you is hard, really
> > > hard.  You never explain what the problem is.  Reading your email is
> > > an exercise in frustration because you can do some good work but you
> > > fail to communicate.
> > > 
> > > > > (manual "copypaste"):
> > > > > nc2k4hp# sysctl ddb.trigger=1
> > > > > Stopped at    db_enter+0x4:   popl    %ebp
> > > > > ddb{0}> print/x "eax = " $eax "\necx = " $ecx "\n"
> > > > >       3
> > > > > ddb{0}> c
> > > > > ddb.trigger: 0 -> 1
> > > > > 
> > > > > so, for reasons yet unknown to me, p[rint] doesn't seem to work at all
> > > > > like described in the man page, tested on i386.
> > > 
> > > What do no work?  What does the man page describe?  Do you expect us to
> > > read the man page, then look at your mail again, then try to understand
> > > what is not working? 
> > > 
> > 
> >         For example,
> > 
> >               print/x "eax = " $eax "\necx = " $ecx "\n"
> > 
> >         will print something like this:
> > 
> >               eax = xxxxxx
> >               ecx = yyyyyy
> > 
> > Now I did install 5.0 into a VM, and there the result for above example
> > would of have been just "Ambiguous", and I'm guessing now that this
> > has not been working as in the example since import.
> > My fix is limited to producing output just like in the example, but
> > input requires more, as it needs escapes for everything not a-z,A-Z,0-9.
> > 
> > > > > Should it work? I hope it would.
> > > 
> > > What should work?  Why do you hope?  Maybe the manpage should be fixed?
> > > 
> > 
> > Multiple [addr] arguments to p[rint], including support for strings,
> > and i hope so because i would find it useful while testing/writing/porting
> > drivers. Maybe, I do like "show struct", and have more than just
> > the filtering diff for it, but it doesn't really work for the ad hoc
> > usecases p[rint] seems so excellent for.
> > 
> > > > Does feel like waste of time to go any further fixing this, if this is
> > > > yet another bug too irrelevant for anyone to ack for, so _any_ input
> > > > here would be great.
> > > 
> > > Like I said, no bug are irrelevant but if the one finding the bug, you
> > > in that case, is not willing to properly explain the problem, then
> > > better not send an email at all ;)
> > 
> > Will try in the future.
> 
> Thanks for the explanation!
> 
> > haven't tested the diff below yet, but compared to previous, it should
> > have working /modifierS.
> 
> IMHO we should just amend the man page and keep ddb(4) code simple. 

Well, that's what I was expecting. I still think even the multiple args
support should be fixed before the man page is updated to match reality,
which i think is better dealt by someone with better english too.

As an example I think the possibility to give another user instructions
remotely for:
"p /xxxu $base $roff $shft (*($base+$roff))>>$shft"
vs.
"p /x $base
 p $off
 p $shft
 p /u (*($base+$off))>>$shft"
alone is enough to outweight the added code, but that's just my opinion.
The string support is indeed questionable, given:
#define DB_LINE_MAXLEN          120

diff below just as an lazybackup, not what i pushed to my swiss-army-debug
branch, and with dubious aim at keeping the diff with max two --, for easy
'rebase' in the future if i ever loose the branches i have it in.

-Artturi



 sys/ddb/db_command.c |  4 +--
 sys/ddb/db_examine.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 92 insertions(+), 2 deletions(-)

diff --git sys/ddb/db_command.c sys/ddb/db_command.c
index a275023dc58..27cda0ba641 100644
--- sys/ddb/db_command.c
+++ sys/ddb/db_command.c
@@ -612,8 +612,8 @@ struct db_command db_command_table[] = {
        { "machine",    NULL,                   0,              NULL},
 #endif
        { "kill",       db_kill_cmd,            0,              NULL },
-       { "print",      db_print_cmd,           0,              NULL },
-       { "p",          db_print_cmd,           0,              NULL },
+       { "print",      db_print_cmd,           CS_OWN,         NULL },
+       { "p",          db_print_cmd,           CS_OWN,         NULL },
        { "pprint",     db_ctf_pprint_cmd,      CS_OWN,         NULL },
        { "examine",    db_examine_cmd,         CS_SET_DOT,     NULL },
        { "x",          db_examine_cmd,         CS_SET_DOT,     NULL },
diff --git sys/ddb/db_examine.c sys/ddb/db_examine.c
index d8fec8219f1..d50039d7779 100644
--- sys/ddb/db_examine.c
+++ sys/ddb/db_examine.c
@@ -46,6 +46,7 @@
 char   db_examine_format[TOK_STRING_SIZE] = "x";
 
 void db_examine(db_addr_t, char *, int);
+void db_print_cmd_value(db_expr_t, db_expr_t);
 void db_search(db_addr_t, int, db_expr_t, db_expr_t, db_expr_t);
 
 /*
@@ -237,8 +238,21 @@ db_examine(db_addr_t addr, char *fmt, int count)
 
 /*
  * Print value.
+ * Syntax is:
+ *     p/[acdoruxz]*
+ *
+ * Where * can be values (expressions), or literal "string"s.
+ * Strings do not consume modifiers(format).
+ *
+ * For example, the command:
+ *     p/xux "log\\t\=" $log "\\n\\t\=" $radix "\\nexpr\\t\=" ($radix-1)<<$log
+ * should print:
+ *     log     =       1
+ *             =      16
+ *     expr    =      1e
  */
 char   db_print_format = 'x';
+char   db__print_format[TOK_STRING_SIZE] = "x";
 
 /*ARGSUSED*/
 void
@@ -246,9 +260,83 @@ db_print_cmd(db_expr_t addr, int have_addr, db_expr_t 
count, char *modif)
 {
        db_expr_t       value;
        char            tmpfmt[28];
+       char            *s;
+       int             i, m, t;
 
+       /* check input for modifiers */
+       t = db_read_token();
+       if (t == tSLASH) {
+               t = db_read_token();
+               if (t != tIDENT) {
+                       db_printf("\nBad modifier\n");
+                       db_flush_lex();
+                       return;
+               }
+               db_strlcpy(db__print_format, db_tok_string,
+                   sizeof(db__print_format));
+               /* read next token, to match the else{}-path of this if(){} */
+               t = db_read_token();
+       }
+       /* default to old/default modifiers */
+       modif = &db__print_format[(m = 0)];
        if (modif[0] != '\0')
                db_print_format = modif[0];
+       /* default to printing a newline in db_print_cmd_value() */
+       value = 0;      /* if we print any strings, we'll change this to 1 */
+       do {
+               if (t != tDITTO) {              /* [addr] */
+                       /* put back the token, for later db_expression() */
+                       db_unread_token(t);
+                       db_print_cmd_value(addr, value);
+                       /* update modifier for the next value */
+                       if (db__print_format[m + 1] != '\0')
+                               m++;
+                       db_print_format = db__print_format[m];
+               } else {                        /* literal "string" */
+                       /* read+copy the string token */
+                       t = db_read_token();
+                       db_strlcpy(tmpfmt, db_tok_string, sizeof(tmpfmt));
+                       /* check for a closing " */
+                       t = db_read_token();
+                       if (t != tDITTO) {
+                               db_printf("\nBad string, missing \"\n");
+                               db_flush_lex();
+                               return;
+                       }
+                       /* print the string while dealing with escapes */
+                       s = tmpfmt;
+                       value = TOK_STRING_SIZE;
+                       for (i = 0; i < TOK_STRING_SIZE && s[i] != '\0'; i++) {
+                               if (i < (TOK_STRING_SIZE - 1) &&
+                                   s[i] == '\\') {
+                                       switch (s[++i]) {
+                                       case 'n':
+                                               db_putchar('\n');
+                                               continue;
+                                       case 't':
+                                               db_putchar('\t');
+                                               continue;
+                                       }
+                               }
+                               db_putchar(s[i]);
+                       }
+                       /* we've had an "string", so.. */
+                       value = 1;      /* ..the user is in charge of "\n" */
+               }
+       } while ((t = db_read_token()) != tEOL);
+}
+
+void
+db_print_cmd_value(db_expr_t addr, db_expr_t no_newline)
+{
+       db_expr_t       value;
+       char            tmpfmt[28];
+
+       if (db_expression(&addr)) {
+               db_dot = (db_addr_t) addr;
+               db_last_addr = db_dot;
+       } else
+               addr = (db_expr_t) db_dot;
 
        switch (db_print_format) {
        case 'a':
@@ -282,6 +370,8 @@ db_print_cmd(db_expr_t addr, int have_addr, db_expr_t 
count, char *modif)
                        db_printf("\\%03o", (int)value);
                break;
        }
+       if (no_newline)
+               return;
        db_printf("\n");
 }
 

Reply via email to