[BACK]Return to pr_comment.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / indent

Annotation of src/usr.bin/indent/pr_comment.c, Revision 1.127

1.127   ! rillig      1: /*     $NetBSD: pr_comment.c,v 1.126 2021/11/27 18:37:17 rillig Exp $  */
1.4       tls         2:
1.11      kamil       3: /*-
                      4:  * SPDX-License-Identifier: BSD-4-Clause
                      5:  *
                      6:  * Copyright (c) 1985 Sun Microsystems, Inc.
1.5       mrg         7:  * Copyright (c) 1980, 1993
                      8:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         9:  * All rights reserved.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the University of
                     22:  *     California, Berkeley and its contributors.
                     23:  * 4. Neither the name of the University nor the names of its contributors
                     24:  *    may be used to endorse or promote products derived from this software
                     25:  *    without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     28:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     29:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     30:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     31:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     32:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     33:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     34:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     35:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     36:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     37:  * SUCH DAMAGE.
                     38:  */
                     39:
1.11      kamil      40: #if 0
                     41: static char sccsid[] = "@(#)pr_comment.c       8.1 (Berkeley) 6/6/93";
                     42: #endif
                     43:
1.6       lukem      44: #include <sys/cdefs.h>
1.11      kamil      45: #if defined(__NetBSD__)
1.127   ! rillig     46: __RCSID("$NetBSD: pr_comment.c,v 1.126 2021/11/27 18:37:17 rillig Exp $");
1.11      kamil      47: #elif defined(__FreeBSD__)
                     48: __FBSDID("$FreeBSD: head/usr.bin/indent/pr_comment.c 334927 2018-06-10 16:44:18Z pstef $");
                     49: #endif
1.1       cgd        50:
1.68      rillig     51: #include <assert.h>
1.1       cgd        52: #include <stdio.h>
1.11      kamil      53: #include <string.h>
1.12      rillig     54:
1.11      kamil      55: #include "indent.h"
1.12      rillig     56:
1.14      rillig     57: static void
1.71      rillig     58: com_add_char(char ch)
1.14      rillig     59: {
1.89      rillig     60:     if (1 >= com.l - com.e)
1.71      rillig     61:        buf_expand(&com, 1);
                     62:     *com.e++ = ch;
                     63: }
                     64:
                     65: static void
                     66: com_add_delim(void)
                     67: {
                     68:     if (!opt.star_comment_cont)
                     69:        return;
1.125     rillig     70:     const char *delim = " * ";
                     71:     buf_add_range(&com, delim, delim + 3);
1.71      rillig     72: }
                     73:
                     74: static void
                     75: com_terminate(void)
                     76: {
1.89      rillig     77:     if (1 >= com.l - com.e)
1.71      rillig     78:        buf_expand(&com, 1);
                     79:     *com.e = '\0';
1.14      rillig     80: }
                     81:
1.77      rillig     82: static bool
1.124     rillig     83: fits_in_one_line(int com_ind, int max_line_length)
1.77      rillig     84: {
1.120     rillig     85:     for (const char *p = inp_p(); *p != '\n'; p++) {
1.77      rillig     86:        assert(*p != '\0');
1.120     rillig     87:        assert(inp_line_end() - p >= 2);
1.77      rillig     88:        if (!(p[0] == '*' && p[1] == '/'))
                     89:            continue;
                     90:
1.124     rillig     91:        int len = ind_add(com_ind + 3, inp_p(), p);
1.90      rillig     92:        len += ch_isblank(p[-1]) ? 2 : 3;
1.91      rillig     93:        return len <= max_line_length;
1.77      rillig     94:     }
                     95:     return false;
                     96: }
                     97:
1.95      rillig     98: static void
1.109     rillig     99: analyze_comment(bool *p_may_wrap, bool *p_break_delim,
                    100:     int *p_adj_max_line_length)
1.1       cgd       101: {
1.47      rillig    102:     int adj_max_line_length;   /* Adjusted max_line_length for comments that
                    103:                                 * spill over the right margin */
1.44      rillig    104:     bool break_delim = opt.comment_delimiter_on_blankline;
1.78      rillig    105:     int com_ind;
1.11      kamil     106:
1.26      rillig    107:     adj_max_line_length = opt.max_line_length;
1.75      rillig    108:     bool may_wrap = true;
1.11      kamil     109:
1.93      rillig    110:     if (ps.curr_col_1 && !opt.format_col1_comments) {
1.75      rillig    111:        may_wrap = false;
1.11      kamil     112:        break_delim = false;
1.78      rillig    113:        com_ind = 0;
1.56      rillig    114:
1.19      rillig    115:     } else {
1.119     rillig    116:        if (inp_peek() == '-' || inp_peek() == '*' ||
1.117     rillig    117:                token.e[-1] == '/' ||
1.119     rillig    118:                (inp_peek() == '\n' && !opt.format_block_comments)) {
1.75      rillig    119:            may_wrap = false;
1.11      kamil     120:            break_delim = false;
                    121:        }
1.56      rillig    122:
1.122     rillig    123:        /*
                    124:         * XXX: This condition looks suspicious since it ignores the case
                    125:         * where the end of the previous comment is still in 'com'.
                    126:         *
                    127:         * See test token_comment.c, keyword 'analyze_comment'.
                    128:         */
1.45      rillig    129:        if (lab.s == lab.e && code.s == code.e) {
1.116     rillig    130:            adj_max_line_length = opt.block_comment_max_line_length;
1.78      rillig    131:            com_ind = (ps.ind_level - opt.unindent_displace) * opt.indent_size;
                    132:            if (com_ind <= 0)
                    133:                com_ind = opt.format_col1_comments ? 0 : 1;
1.56      rillig    134:
1.19      rillig    135:        } else {
1.33      rillig    136:            break_delim = false;
1.34      rillig    137:
1.112     rillig    138:            int target_ind = code.s != code.e
                    139:                ? ind_add(compute_code_indent(), code.s, code.e)
                    140:                : ind_add(compute_label_indent(), lab.s, lab.e);
1.34      rillig    141:
1.78      rillig    142:            com_ind = ps.decl_on_line || ps.ind_level == 0
1.60      rillig    143:                ? opt.decl_comment_column - 1 : opt.comment_column - 1;
1.78      rillig    144:            if (com_ind <= target_ind)
                    145:                com_ind = next_tab(target_ind);
1.79      rillig    146:            if (com_ind + 25 > adj_max_line_length)
                    147:                adj_max_line_length = com_ind + 25;
1.11      kamil     148:        }
                    149:     }
1.56      rillig    150:
1.78      rillig    151:     ps.com_ind = com_ind;
                    152:
1.75      rillig    153:     if (!may_wrap) {
1.6       lukem     154:        /*
1.11      kamil     155:         * Find out how much indentation there was originally, because that
1.126     rillig    156:         * much will have to be ignored by output_complete_line.
1.25      rillig    157:         */
1.120     rillig    158:        const char *start = inp_line_start();
                    159:        ps.n_comment_delta = -ind_add(0, start, inp_p() - 2);
1.19      rillig    160:     } else {
1.11      kamil     161:        ps.n_comment_delta = 0;
1.119     rillig    162:        while (ch_isblank(inp_peek()))
1.120     rillig    163:            inp_skip();
1.11      kamil     164:     }
1.56      rillig    165:
1.11      kamil     166:     ps.comment_delta = 0;
1.71      rillig    167:     com_add_char('/');
                    168:     com_add_char(token.e[-1]); /* either '*' or '/' */
1.116     rillig    169:
                    170:     /* TODO: Maybe preserve a single '\t' as well. */
1.119     rillig    171:     if (inp_peek() != ' ' && may_wrap)
1.71      rillig    172:        com_add_char(' ');
1.11      kamil     173:
1.124     rillig    174:     if (break_delim && fits_in_one_line(com_ind, adj_max_line_length))
1.77      rillig    175:        break_delim = false;
1.1       cgd       176:
1.11      kamil     177:     if (break_delim) {
1.84      rillig    178:        if (opt.blanklines_before_block_comments &&
1.88      rillig    179:                ps.prev_token != lsym_lbrace)
1.127   ! rillig    180:            out.blank_line_before = true;
1.126     rillig    181:        output_line();
1.75      rillig    182:        com_add_delim();
1.11      kamil     183:     }
                    184:
1.95      rillig    185:     *p_adj_max_line_length = adj_max_line_length;
                    186:     *p_break_delim = break_delim;
                    187:     *p_may_wrap = may_wrap;
                    188: }
                    189:
1.110     rillig    190: /*
                    191:  * Copy characters from 'inp' to 'com'. Try to keep comments from going over
                    192:  * the maximum line length. To do that, remember where the last blank, tab, or
                    193:  * newline was. When a line is filled, print up to the last blank and continue
                    194:  * copying.
                    195:  */
1.95      rillig    196: static void
1.99      rillig    197: copy_comment_wrap(int adj_max_line_length, bool break_delim)
1.95      rillig    198: {
1.99      rillig    199:     ssize_t last_blank = -1;   /* index of the last blank in com.buf */
                    200:
                    201:     for (;;) {
1.119     rillig    202:        switch (inp_peek()) {
1.99      rillig    203:        case '\f':
1.126     rillig    204:            output_line_ff();
1.101     rillig    205:            last_blank = -1;
                    206:            com_add_delim();
1.120     rillig    207:            inp_skip();
1.119     rillig    208:            while (ch_isblank(inp_peek()))
1.120     rillig    209:                inp_skip();
1.99      rillig    210:            break;
                    211:
                    212:        case '\n':
                    213:            if (had_eof) {
                    214:                diag(1, "Unterminated comment");
1.126     rillig    215:                output_line();
1.99      rillig    216:                return;
                    217:            }
                    218:
                    219:            last_blank = -1;
1.101     rillig    220:            if (ps.next_col_1) {
1.99      rillig    221:                if (com.s == com.e)
1.116     rillig    222:                    com_add_char(' ');  /* force empty line of output */
1.101     rillig    223:                if (com.e - com.s > 3) {
1.126     rillig    224:                    output_line();
1.99      rillig    225:                    com_add_delim();
                    226:                }
1.126     rillig    227:                output_line();
1.101     rillig    228:                com_add_delim();
1.99      rillig    229:
                    230:            } else {
                    231:                ps.next_col_1 = true;
1.114     rillig    232:                if (!(com.e > com.s && ch_isblank(com.e[-1])))
1.99      rillig    233:                    com_add_char(' ');
                    234:                last_blank = com.e - 1 - com.buf;
                    235:            }
                    236:            ++line_no;
1.101     rillig    237:
                    238:            bool skip_asterisk = true;
                    239:            do {                /* flush any blanks and/or tabs at start of
1.99      rillig    240:                                 * next line */
1.101     rillig    241:                inp_skip();
1.119     rillig    242:                if (inp_peek() == '*' && skip_asterisk) {
1.101     rillig    243:                    skip_asterisk = false;
1.99      rillig    244:                    inp_skip();
1.119     rillig    245:                    if (inp_peek() == '/')
1.101     rillig    246:                        goto end_of_comment;
                    247:                }
1.119     rillig    248:            } while (ch_isblank(inp_peek()));
1.101     rillig    249:
1.99      rillig    250:            break;              /* end of case for newline */
                    251:
                    252:        case '*':
                    253:            inp_skip();
1.119     rillig    254:            if (inp_peek() == '/') {
1.99      rillig    255:        end_of_comment:
                    256:                inp_skip();
                    257:
                    258:                if (break_delim) {
1.116     rillig    259:                    if (com.e - com.s > 3)
1.126     rillig    260:                        output_line();
1.99      rillig    261:                    else
1.113     rillig    262:                        com.e = com.s;
1.99      rillig    263:                    com_add_char(' ');
                    264:                }
                    265:
1.114     rillig    266:                if (!(com.e > com.s && ch_isblank(com.e[-1])))
1.99      rillig    267:                    com_add_char(' ');
1.111     rillig    268:                com_add_char('*');
                    269:                com_add_char('/');
1.99      rillig    270:                com_terminate();
                    271:                return;
                    272:
                    273:            } else              /* handle isolated '*' */
                    274:                com_add_char('*');
                    275:            break;
                    276:
                    277:        default:                /* we have a random char */
                    278:            ;
                    279:            int now_len = ind_add(ps.com_ind, com.s, com.e);
                    280:            for (;;) {
                    281:                char ch = inp_next();
                    282:                if (ch_isblank(ch))
                    283:                    last_blank = com.e - com.buf;
                    284:                com_add_char(ch);
                    285:                now_len++;
1.119     rillig    286:                if (memchr("*\n\r\b\t", inp_peek(), 6) != NULL)
1.99      rillig    287:                    break;
                    288:                if (now_len >= adj_max_line_length && last_blank != -1)
                    289:                    break;
                    290:            }
                    291:
                    292:            ps.next_col_1 = false;
                    293:
1.101     rillig    294:            if (now_len <= adj_max_line_length)
1.99      rillig    295:                break;
1.121     rillig    296:            if (ch_isspace(com.e[-1]))
1.99      rillig    297:                break;
                    298:
                    299:            if (last_blank == -1) {     /* only a single word in this line */
1.126     rillig    300:                output_line();
1.99      rillig    301:                com_add_delim();
                    302:                break;
                    303:            }
                    304:
                    305:            const char *last_word_s = com.buf + last_blank + 1;
                    306:            size_t last_word_len = (size_t)(com.e - last_word_s);
                    307:            com.e = com.buf + last_blank;
1.126     rillig    308:            output_line();
1.99      rillig    309:            com_add_delim();
                    310:
                    311:            memcpy(com.e, last_word_s, last_word_len);
                    312:            com.e += last_word_len;
                    313:            last_blank = -1;
                    314:        }
                    315:     }
                    316: }
                    317:
                    318: static void
1.103     rillig    319: copy_comment_nowrap(void)
1.99      rillig    320: {
1.81      rillig    321:     for (;;) {
1.119     rillig    322:        if (inp_peek() == '\n') {
1.62      rillig    323:            if (token.e[-1] == '/')
1.105     rillig    324:                goto finish;
1.56      rillig    325:
1.54      rillig    326:            if (had_eof) {
1.67      rillig    327:                diag(1, "Unterminated comment");
1.126     rillig    328:                output_line();
1.11      kamil     329:                return;
                    330:            }
1.56      rillig    331:
1.100     rillig    332:            if (com.s == com.e)
                    333:                com_add_char(' ');      /* force output of an empty line */
1.126     rillig    334:            output_line();
1.54      rillig    335:            ++line_no;
1.100     rillig    336:            inp_skip();
1.104     rillig    337:            continue;
                    338:        }
1.1       cgd       339:
1.106     rillig    340:        com_add_char(inp_next());
1.107     rillig    341:        if (com.e[-2] == '*' && com.e[-1] == '/' && token.e[-1] == '*')
1.106     rillig    342:            goto finish;
1.11      kamil     343:     }
1.105     rillig    344:
                    345: finish:
                    346:     com_terminate();
1.1       cgd       347: }
1.95      rillig    348:
                    349: /*
                    350:  * Scan, reformat and output a single comment, which is either a block comment
                    351:  * starting with '/' '*' or an end-of-line comment starting with '//'.
                    352:  */
                    353: void
                    354: process_comment(void)
                    355: {
1.109     rillig    356:     int adj_max_line_length;
                    357:     bool may_wrap, break_delim;
1.95      rillig    358:
                    359:     ps.just_saw_decl = 0;
                    360:     ps.stats.comments++;
                    361:
1.109     rillig    362:     int saved_just_saw_decl = ps.just_saw_decl;
                    363:     analyze_comment(&may_wrap, &break_delim, &adj_max_line_length);
1.99      rillig    364:     if (may_wrap)
1.100     rillig    365:        copy_comment_wrap(adj_max_line_length, break_delim);
1.99      rillig    366:     else
1.103     rillig    367:        copy_comment_nowrap();
1.109     rillig    368:     ps.just_saw_decl = saved_just_saw_decl;
1.95      rillig    369: }

CVSweb <webmaster@jp.NetBSD.org>