Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/indent indent: in debug mode, output detailed token ...



details:   https://anonhg.NetBSD.org/src/rev/7c85d0fd2005
branches:  trunk
changeset: 953367:7c85d0fd2005
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sun Mar 07 11:32:05 2021 +0000

description:
indent: in debug mode, output detailed token information

The main ingredient for understanding how indent works is the tokenizer
and the 4 buffers in which the text is collected.

Inspecting this debug log for the test comment-line-end makes it obvious
why indent messes up code that contains '//' comments.  The cause is
that indent interprets '//' as an operator, just like '&&' or '||'.  The
sequence '/////' is interpreted as a single operator as well, by the
way.

Since '//' is interpreted as an ordinary operator, any words following
it are plain identifiers, usually several of them in a row, which is a
syntax error.  Depending on the context, the operator '//' is either a
unary operator (no space around) or a binary operator (space around).
This explains why the word 'line-end' is expanded to 'line - end'.

No functional change outside of debug mode.

diffstat:

 usr.bin/indent/indent.h |   7 ++-
 usr.bin/indent/lexi.c   |  91 +++++++++++++++++++++++++++++++++++++++---------
 usr.bin/indent/parse.c  |  11 +++--
 3 files changed, 85 insertions(+), 24 deletions(-)

diffs (249 lines):

diff -r 3ad3bbbe7660 -r 7c85d0fd2005 usr.bin/indent/indent.h
--- a/usr.bin/indent/indent.h   Sun Mar 07 10:56:18 2021 +0000
+++ b/usr.bin/indent/indent.h   Sun Mar 07 11:32:05 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: indent.h,v 1.4 2021/03/07 10:56:18 rillig Exp $        */
+/*     $NetBSD: indent.h,v 1.5 2021/03/07 11:32:05 rillig Exp $        */
 
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
@@ -30,7 +30,7 @@
 
 #if 0
 #if defined(__NetBSD__)
-__RCSID("$NetBSD: indent.h,v 1.4 2021/03/07 10:56:18 rillig Exp $");
+__RCSID("$NetBSD: indent.h,v 1.5 2021/03/07 11:32:05 rillig Exp $");
 #elif defined(__FreeBSD__)
 __FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 336333 2018-07-16 05:46:50Z pstef $");
 #endif
@@ -50,6 +50,9 @@
 int    count_spaces(int, char *);
 int    count_spaces_until(int, char *, char *);
 void   init_constant_tt(void);
+#ifdef debug
+const char *token_type_name(token_type);
+#endif
 token_type lexi(struct parser_state *);
 void   diag(int, const char *, ...) __printflike(2, 3);
 void   dump_line(void);
diff -r 3ad3bbbe7660 -r 7c85d0fd2005 usr.bin/indent/lexi.c
--- a/usr.bin/indent/lexi.c     Sun Mar 07 10:56:18 2021 +0000
+++ b/usr.bin/indent/lexi.c     Sun Mar 07 11:32:05 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lexi.c,v 1.19 2021/03/07 10:56:18 rillig Exp $ */
+/*     $NetBSD: lexi.c,v 1.20 2021/03/07 11:32:05 rillig Exp $ */
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
@@ -46,7 +46,7 @@
 #include <sys/cdefs.h>
 #ifndef lint
 #if defined(__NetBSD__)
-__RCSID("$NetBSD: lexi.c,v 1.19 2021/03/07 10:56:18 rillig Exp $");
+__RCSID("$NetBSD: lexi.c,v 1.20 2021/03/07 11:32:05 rillig Exp $");
 #elif defined(__FreeBSD__)
 __FBSDID("$FreeBSD: head/usr.bin/indent/lexi.c 337862 2018-08-15 18:19:45Z pstef $");
 #endif
@@ -58,6 +58,7 @@
  * of token scanned.
  */
 
+#include <assert.h>
 #include <err.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -176,6 +177,62 @@
     return (strcmp(e1, *(const char * const *)e2));
 }
 
+#ifdef debug
+const char *
+token_type_name(token_type tk)
+{
+    static const char *const name[] = {
+       "end_of_file", "newline", "lparen", "rparen", "unary_op",
+       "binary_op", "postop", "question", "casestmt", "colon",
+       "semicolon", "lbrace", "rbrace", "ident", "comma",
+       "comment", "swstmt", "preesc", "form_feed", "decl",
+       "sp_paren", "sp_nparen", "ifstmt", "whilestmt", "forstmt",
+       "stmt", "stmtl", "elselit", "dolit", "dohead",
+       "ifhead", "elsehead", "period", "strpfx", "storage",
+       "funcname", "type_def", "structure"
+    };
+
+    assert(0 <= tk && tk < sizeof name / sizeof name[0]);
+
+    return name[tk];
+}
+
+static void
+print_buf(const char *name, const char *s, const char *e)
+{
+    if (s == e)
+       return;
+
+    printf(" %s \"", name);
+    for (const char *p = s; p < e; p++) {
+       if (isprint((unsigned char)*p) && *p != '\\' && *p != '"')
+           printf("%c", *p);
+       else if (*p == '\n')
+           printf("\\n");
+       else if (*p == '\t')
+           printf("\\t");
+       else
+           printf("\\x%02x", *p);
+    }
+    printf("\"");
+}
+
+static token_type
+lexi_end(token_type code)
+{
+    printf("in line %d, lexi returns '%s'", line_no, token_type_name(code));
+    print_buf("token", s_token, e_token);
+    print_buf("label", s_lab, e_lab);
+    print_buf("code", s_code, e_code);
+    print_buf("comment", s_com, e_com);
+    printf("\n");
+
+    return code;
+}
+#else
+#  define lexi_end(tk) (tk)
+#endif
+
 token_type
 lexi(struct parser_state *state)
 {
@@ -250,7 +307,7 @@
 
        if (s_token[0] == 'L' && s_token[1] == '\0' &&
              (*buf_ptr == '"' || *buf_ptr == '\''))
-           return (strpfx);
+           return lexi_end(strpfx);
 
        while (*buf_ptr == ' ' || *buf_ptr == '\t') {   /* get rid of blanks */
            if (++buf_ptr >= buf_end)
@@ -262,7 +319,7 @@
                                 * in parentheses, then this token
                                 * should be treated as a declaration */
            state->last_u_d = true;
-           return (decl);
+           return lexi_end(decl);
        }
        /*
         * Operator after identifier is binary unless last token was 'struct'
@@ -291,9 +348,9 @@
            state->last_u_d = true;
            switch (p->rwcode) {
            case 7:             /* it is a switch */
-               return (swstmt);
+               return lexi_end(swstmt);
            case 8:             /* a case or default */
-               return (casestmt);
+               return lexi_end(casestmt);
 
            case 3:             /* a "struct" */
                /* FALLTHROUGH */
@@ -308,26 +365,26 @@
                    break;
                }
                if (p != NULL && p->rwcode == 3)
-                   return (structure);
+                   return lexi_end(structure);
                if (state->p_l_follow)
                    break;
-               return (decl);
+               return lexi_end(decl);
 
            case 5:             /* if, while, for */
-               return (sp_paren);
+               return lexi_end(sp_paren);
 
            case 6:             /* do, else */
-               return (sp_nparen);
+               return lexi_end(sp_nparen);
 
            case 10:            /* storage class specifier */
-               return (storage);
+               return lexi_end(storage);
 
            case 11:            /* typedef */
-               return (type_def);
+               return lexi_end(type_def);
 
            default:            /* all others are treated like any other
                                 * identifier */
-               return (ident);
+               return lexi_end(ident);
            }                   /* end of switch */
        }                       /* end of if (found_it) */
        if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
@@ -339,7 +396,7 @@
            strncpy(state->procname, token, sizeof state->procname - 1);
            if (state->in_decl)
                state->in_parameter_declaration = 1;
-           return (funcname);
+           return lexi_end(funcname);
     not_proc:;
        }
        /*
@@ -355,12 +412,12 @@
                state->last_token == rbrace)) {
            state->keyword = 4; /* a type name */
            state->last_u_d = true;
-           return decl;
+           return lexi_end(decl);
        }
        if (state->last_token == decl)  /* if this is a declared variable,
                                         * then following sign is unary */
            state->last_u_d = true;     /* will make "int a -1" work */
-       return (ident);         /* the ident is not in the list */
+       return lexi_end(ident);         /* the ident is not in the list */
     }                          /* end of procesing for alpanum character */
 
     /* Scan a non-alphanumeric token */
@@ -594,7 +651,7 @@
     state->last_u_d = unary_delim;
     CHECK_SIZE_TOKEN(1);
     *e_token = '\0';           /* null terminate the token */
-    return (code);
+    return lexi_end(code);
 }
 
 /* Initialize constant transition table */
diff -r 3ad3bbbe7660 -r 7c85d0fd2005 usr.bin/indent/parse.c
--- a/usr.bin/indent/parse.c    Sun Mar 07 10:56:18 2021 +0000
+++ b/usr.bin/indent/parse.c    Sun Mar 07 11:32:05 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parse.c,v 1.13 2021/03/07 10:56:18 rillig Exp $        */
+/*     $NetBSD: parse.c,v 1.14 2021/03/07 11:32:05 rillig Exp $        */
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
@@ -65,7 +65,7 @@
     int         i;
 
 #ifdef debug
-    printf("%2d - %s\n", tk, token);
+    printf("parse token: '%s' \"%s\"\n", token_type_name(tk), token);
 #endif
 
     while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
@@ -223,12 +223,13 @@
     reduce();                  /* see if any reduction can be done */
 
 #ifdef debug
+    printf("parse stack:");
     for (i = 1; i <= ps.tos; ++i)
-       printf("(%d %d)", ps.p_stack[i], ps.il[i]);
+       printf(" ('%s' at %d)", token_type_name(ps.p_stack[i]), ps.il[i]);
+    if (ps.tos == 0)
+        printf(" empty");
     printf("\n");
 #endif
-
-    return;
 }
 
 /*



Home | Main Index | Thread Index | Old Index