1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 1985 Sun Microsystems, Inc. 5 * Copyright (c) 1980, 1993 6 * The Regents of the University of California. All rights reserved. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #if 0 39 #ifndef lint 40 static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; 41 #endif /* not lint */ 42 #endif 43 44 #include <sys/cdefs.h> 45 __FBSDID("$FreeBSD$"); 46 47 #include <err.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include "indent_globs.h" 52 #include "indent_codes.h" 53 #include "indent.h" 54 /* 55 * NAME: 56 * pr_comment 57 * 58 * FUNCTION: 59 * This routine takes care of scanning and printing comments. 60 * 61 * ALGORITHM: 62 * 1) Decide where the comment should be aligned, and if lines should 63 * be broken. 64 * 2) If lines should not be broken and filled, just copy up to end of 65 * comment. 66 * 3) If lines should be filled, then scan thru input_buffer copying 67 * characters to com_buf. Remember where the last blank, tab, or 68 * newline was. When line is filled, print up to last blank and 69 * continue copying. 70 * 71 * HISTORY: 72 * November 1976 D A Willcox of CAC Initial coding 73 * 12/6/76 D A Willcox of CAC Modification to handle 74 * UNIX-style comments 75 * 76 */ 77 78 /* 79 * this routine processes comments. It makes an attempt to keep comments from 80 * going over the max line length. If a line is too long, it moves everything 81 * from the last blank to the next comment line. Blanks and tabs from the 82 * beginning of the input line are removed 83 */ 84 85 void 86 pr_comment(void) 87 { 88 int now_col; /* column we are in now */ 89 int adj_max_col; /* Adjusted max_col for when we decide to 90 * spill comments over the right margin */ 91 char *last_bl; /* points to the last blank in the output 92 * buffer */ 93 char *t_ptr; /* used for moving string */ 94 int break_delim = comment_delimiter_on_blankline; 95 int l_just_saw_decl = ps.just_saw_decl; 96 adj_max_col = max_col; 97 ps.just_saw_decl = 0; 98 last_bl = NULL; /* no blanks found so far */ 99 ps.box_com = false; /* at first, assume that we are not in 100 * a boxed comment or some other 101 * comment that should not be touched */ 102 ++ps.out_coms; /* keep track of number of comments */ 103 104 /* Figure where to align and how to treat the comment */ 105 106 if (ps.col_1 && !format_col1_comments) { /* if comment starts in column 107 * 1 it should not be touched */ 108 ps.box_com = true; 109 break_delim = false; 110 ps.com_col = 1; 111 } 112 else { 113 if (*buf_ptr == '-' || *buf_ptr == '*' || 114 (*buf_ptr == '\n' && !format_block_comments)) { 115 ps.box_com = true; /* A comment with a '-' or '*' immediately 116 * after the /+* is assumed to be a boxed 117 * comment. A comment with a newline 118 * immediately after the /+* is assumed to 119 * be a block comment and is treated as a 120 * box comment unless format_block_comments 121 * is nonzero (the default). */ 122 break_delim = false; 123 } 124 if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { 125 /* klg: check only if this line is blank */ 126 /* 127 * If this (*and previous lines are*) blank, dont put comment way 128 * out at left 129 */ 130 ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; 131 adj_max_col = block_comment_max_col; 132 if (ps.com_col <= 1) 133 ps.com_col = 1 + !format_col1_comments; 134 } 135 else { 136 int target_col; 137 break_delim = false; 138 if (s_code != e_code) 139 target_col = count_spaces(compute_code_target(), s_code); 140 else { 141 target_col = 1; 142 if (s_lab != e_lab) 143 target_col = count_spaces(compute_label_target(), s_lab); 144 } 145 ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; 146 if (ps.com_col <= target_col) 147 ps.com_col = tabsize * (1 + (target_col - 1) / tabsize) + 1; 148 if (ps.com_col + 24 > adj_max_col) 149 adj_max_col = ps.com_col + 24; 150 } 151 } 152 if (ps.box_com) { 153 /* 154 * Find out how much indentation there was originally, because that 155 * much will have to be ignored by pad_output() in dump_line(). This 156 * is a box comment, so nothing changes -- not even indentation. 157 * 158 * The comment we're about to read usually comes from in_buffer, 159 * unless it has been copied into save_com. 160 */ 161 char *start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? bp_save : buf_ptr; 162 ps.n_comment_delta = 1 - count_spaces_until(1, in_buffer, start - 2); 163 } 164 else { 165 ps.n_comment_delta = 0; 166 while (*buf_ptr == ' ' || *buf_ptr == '\t') 167 buf_ptr++; 168 } 169 ps.comment_delta = 0; 170 *e_com++ = '/'; /* put '/' followed by '*' into buffer */ 171 *e_com++ = '*'; 172 if (*buf_ptr != ' ' && !ps.box_com) 173 *e_com++ = ' '; 174 175 /* 176 * Don't put a break delimiter if this is a one-liner that won't wrap. 177 */ 178 if (break_delim) 179 for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) { 180 if (t_ptr >= buf_end) 181 fill_buffer(); 182 if (t_ptr[0] == '*' && t_ptr[1] == '/') { 183 if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2)) 184 break_delim = false; 185 break; 186 } 187 } 188 189 if (break_delim) { 190 char *t = e_com; 191 e_com = s_com + 2; 192 *e_com = 0; 193 if (blanklines_before_blockcomments && ps.last_token != lbrace) 194 prefix_blankline_requested = 1; 195 dump_line(); 196 e_com = s_com = t; 197 if (!ps.box_com && star_comment_cont) 198 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 199 } 200 201 if (troff) 202 adj_max_col = 80; 203 204 /* Start to copy the comment */ 205 206 while (1) { /* this loop will go until the comment is 207 * copied */ 208 CHECK_SIZE_COM; 209 switch (*buf_ptr) { /* this checks for various spcl cases */ 210 case 014: /* check for a form feed */ 211 if (!ps.box_com) { /* in a text comment, break the line here */ 212 ps.use_ff = true; 213 /* fix so dump_line uses a form feed */ 214 dump_line(); 215 last_bl = NULL; 216 if (!ps.box_com && star_comment_cont) 217 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 218 while (*++buf_ptr == ' ' || *buf_ptr == '\t') 219 ; 220 } 221 else { 222 if (++buf_ptr >= buf_end) 223 fill_buffer(); 224 *e_com++ = 014; 225 } 226 break; 227 228 case '\n': 229 if (had_eof) { /* check for unexpected eof */ 230 printf("Unterminated comment\n"); 231 dump_line(); 232 return; 233 } 234 last_bl = NULL; 235 if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, 236 * we dont ignore the newline */ 237 if (s_com == e_com) 238 *e_com++ = ' '; 239 if (!ps.box_com && e_com - s_com > 3) { 240 dump_line(); 241 if (star_comment_cont) 242 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 243 } 244 dump_line(); 245 if (!ps.box_com && star_comment_cont) 246 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 247 } 248 else { 249 ps.last_nl = 1; 250 if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') 251 last_bl = e_com - 1; 252 /* 253 * if there was a space at the end of the last line, remember 254 * where it was 255 */ 256 else { /* otherwise, insert one */ 257 last_bl = e_com; 258 CHECK_SIZE_COM; 259 *e_com++ = ' '; 260 } 261 } 262 ++line_no; /* keep track of input line number */ 263 if (!ps.box_com) { 264 int nstar = 1; 265 do { /* flush any blanks and/or tabs at start of 266 * next line */ 267 if (++buf_ptr >= buf_end) 268 fill_buffer(); 269 if (*buf_ptr == '*' && --nstar >= 0) { 270 if (++buf_ptr >= buf_end) 271 fill_buffer(); 272 if (*buf_ptr == '/') 273 goto end_of_comment; 274 } 275 } while (*buf_ptr == ' ' || *buf_ptr == '\t'); 276 } 277 else if (++buf_ptr >= buf_end) 278 fill_buffer(); 279 break; /* end of case for newline */ 280 281 case '*': /* must check for possibility of being at end 282 * of comment */ 283 if (++buf_ptr >= buf_end) /* get to next char after * */ 284 fill_buffer(); 285 286 if (*buf_ptr == '/') { /* it is the end!!! */ 287 end_of_comment: 288 if (++buf_ptr >= buf_end) 289 fill_buffer(); 290 CHECK_SIZE_COM; 291 if (break_delim) { 292 if (e_com > s_com + 3) { 293 dump_line(); 294 } 295 else 296 s_com = e_com; 297 *e_com++ = ' '; 298 } 299 if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com) 300 *e_com++ = ' '; /* ensure blank before end */ 301 *e_com++ = '*', *e_com++ = '/', *e_com = '\0'; 302 ps.just_saw_decl = l_just_saw_decl; 303 return; 304 } 305 else /* handle isolated '*' */ 306 *e_com++ = '*'; 307 break; 308 default: /* we have a random char */ 309 now_col = count_spaces_until(ps.com_col, s_com, e_com); 310 do { 311 *e_com = *buf_ptr++; 312 if (buf_ptr >= buf_end) 313 fill_buffer(); 314 if (*e_com == ' ' || *e_com == '\t') 315 last_bl = e_com; /* remember we saw a blank */ 316 ++e_com; 317 now_col++; 318 } while (!memchr("*\n\r\b\t", *buf_ptr, 6) && 319 (now_col <= adj_max_col || !last_bl)); 320 ps.last_nl = false; 321 if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') { 322 /* 323 * the comment is too long, it must be broken up 324 */ 325 if (last_bl == NULL) { 326 dump_line(); 327 if (!ps.box_com && star_comment_cont) 328 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 329 break; 330 } 331 *e_com = '\0'; 332 e_com = last_bl; 333 dump_line(); 334 if (!ps.box_com && star_comment_cont) 335 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 336 for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t'; 337 t_ptr++) 338 ; 339 last_bl = NULL; 340 while (*t_ptr != '\0') { 341 if (*t_ptr == ' ' || *t_ptr == '\t') 342 last_bl = e_com; 343 *e_com++ = *t_ptr++; 344 } 345 } 346 break; 347 } 348 } 349 } 350