1 /* $NetBSD: pr_comment.c,v 1.8 2003/06/19 15:45:22 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1976 Board of Trustees of the University of Illinois. 7 * Copyright (c) 1985 Sun Microsystems, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; 43 #else 44 __RCSID("$NetBSD: pr_comment.c,v 1.8 2003/06/19 15:45:22 christos Exp $"); 45 #endif 46 #endif /* not lint */ 47 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <ctype.h> 51 #include "indent_globs.h" 52 53 /* 54 * NAME: 55 * pr_comment 56 * 57 * FUNCTION: 58 * This routine takes care of scanning and printing comments. 59 * 60 * ALGORITHM: 61 * 1) Decide where the comment should be aligned, and if lines should 62 * be broken. 63 * 2) If lines should not be broken and filled, just copy up to end of 64 * comment. 65 * 3) If lines should be filled, then scan thru input_buffer copying 66 * characters to com_buf. Remember where the last blank, tab, or 67 * newline was. When line is filled, print up to last blank and 68 * continue copying. 69 * 70 * HISTORY: 71 * November 1976 D A Willcox of CAC Initial coding 72 * 12/6/76 D A Willcox of CAC Modification to handle 73 * UNIX-style comments 74 * 75 */ 76 77 /* 78 * this routine processes comments. It makes an attempt to keep comments from 79 * going over the max line length. If a line is too long, it moves everything 80 * from the last blank to the next comment line. Blanks and tabs from the 81 * beginning of the input line are removed 82 */ 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 unix_comment; /* tri-state variable used to decide if it is 95 * a unix-style comment. 0 means only blanks 96 * since start, 1 means regular style comment, 97 * 2 means unix style comment */ 98 int break_delim = comment_delimiter_on_blankline; 99 int l_just_saw_decl = ps.just_saw_decl; 100 /* 101 * int ps.last_nl = 0; / * true iff the last significant thing 102 * weve seen is a newline 103 */ 104 int one_liner = 1; /* true iff this comment is a one-liner */ 105 adj_max_col = max_col; 106 ps.just_saw_decl = 0; 107 last_bl = 0; /* no blanks found so far */ 108 ps.box_com = false; /* at first, assume that we are not in a boxed 109 * comment or some other comment that should 110 * not be touched */ 111 ++ps.out_coms; /* keep track of number of comments */ 112 unix_comment = 1; /* set flag to let us figure out if there is a 113 * unix-style comment ** DISABLED: use 0 to 114 * reenable this hack! */ 115 116 /* Figure where to align and how to treat the comment */ 117 118 if (ps.col_1 && !format_col1_comments) { /* if comment starts in 119 * column 1 it should 120 * not be touched */ 121 ps.box_com = true; 122 ps.com_col = 1; 123 } else { 124 if (*buf_ptr == '-' || *buf_ptr == '*' || *buf_ptr == '\n') { 125 ps.box_com = true; /* a comment with a '-', '*' 126 * or newline immediately 127 * after the start comment is 128 * assumed to be a boxed 129 * comment */ 130 break_delim = 0; 131 } 132 if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { 133 /* klg: check only if this line is blank */ 134 /* 135 * If this (*and previous lines are*) blank, dont put comment way 136 * out at left 137 */ 138 ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; 139 adj_max_col = block_comment_max_col; 140 if (ps.com_col <= 1) 141 ps.com_col = 1 + !format_col1_comments; 142 } else { 143 int target_col; 144 break_delim = 0; 145 if (s_code != e_code) 146 target_col = count_spaces(compute_code_target(), s_code); 147 else { 148 target_col = 1; 149 if (s_lab != e_lab) 150 target_col = count_spaces(compute_label_target(), s_lab); 151 } 152 ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; 153 if (ps.com_col < target_col) 154 ps.com_col = ((target_col + 7) & ~7) + 1; 155 if (ps.com_col + 24 > adj_max_col) 156 adj_max_col = ps.com_col + 24; 157 } 158 } 159 if (ps.box_com) { 160 buf_ptr[-2] = 0; 161 ps.n_comment_delta = 1 - count_spaces(1, in_buffer); 162 buf_ptr[-2] = '/'; 163 } else { 164 ps.n_comment_delta = 0; 165 while (*buf_ptr == ' ' || *buf_ptr == '\t') 166 buf_ptr++; 167 } 168 ps.comment_delta = 0; 169 *e_com++ = '/'; /* put '/' + '*' into buffer */ 170 *e_com++ = '*'; 171 if (*buf_ptr != ' ' && !ps.box_com) 172 *e_com++ = ' '; 173 174 *e_com = '\0'; 175 if (troff) { 176 now_col = 1; 177 adj_max_col = 80; 178 } else 179 now_col = count_spaces(ps.com_col, s_com); /* figure what column we 180 * would be in if we 181 * printed the comment 182 * now */ 183 184 /* Start to copy the comment */ 185 186 while (1) { /* this loop will go until the comment is 187 * copied */ 188 if (!iscntrl((unsigned char)*buf_ptr) && *buf_ptr != '*') 189 ps.last_nl = 0; 190 CHECK_SIZE_COM; 191 switch (*buf_ptr) { /* this checks for various spcl cases */ 192 case 014: /* check for a form feed */ 193 if (!ps.box_com) { /* in a text comment, break 194 * the line here */ 195 ps.use_ff = true; 196 /* fix so dump_line uses a form feed */ 197 dump_line(); 198 last_bl = 0; 199 *e_com++ = ' '; 200 *e_com++ = '*'; 201 *e_com++ = ' '; 202 while (*++buf_ptr == ' ' || *buf_ptr == '\t'); 203 } else { 204 if (++buf_ptr >= buf_end) 205 fill_buffer(); 206 *e_com++ = 014; 207 } 208 break; 209 210 case '\n': 211 if (had_eof) { /* check for unexpected eof */ 212 printf("Unterminated comment\n"); 213 *e_com = '\0'; 214 dump_line(); 215 return; 216 } 217 one_liner = 0; 218 if (ps.box_com || ps.last_nl) { /* if this is a boxed 219 * comment, we dont 220 * ignore the newline */ 221 if (s_com == e_com) { 222 *e_com++ = ' '; 223 *e_com++ = ' '; 224 } 225 *e_com = '\0'; 226 if (!ps.box_com && e_com - s_com > 3) { 227 if (break_delim == 1 && s_com[0] == '/' 228 && s_com[1] == '*' && s_com[2] == ' ') { 229 char *t = e_com; 230 break_delim = 2; 231 e_com = s_com + 2; 232 *e_com = 0; 233 if (blanklines_before_blockcomments) 234 prefix_blankline_requested = 1; 235 dump_line(); 236 e_com = t; 237 s_com[0] = s_com[1] = s_com[2] = ' '; 238 } 239 dump_line(); 240 CHECK_SIZE_COM; 241 *e_com++ = ' '; 242 *e_com++ = ' '; 243 } 244 dump_line(); 245 now_col = ps.com_col; 246 } else { 247 ps.last_nl = 1; 248 if (unix_comment != 1) { /* we not are in 249 * unix_style comment */ 250 if (unix_comment == 0 && s_code == e_code) { 251 /* 252 * if it is a UNIX-style comment, ignore the 253 * requirement that previous line be blank for 254 * unindention 255 */ 256 ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; 257 if (ps.com_col <= 1) 258 ps.com_col = 2; 259 } 260 unix_comment = 2; /* permanently remember 261 * that we are in this 262 * type of comment */ 263 dump_line(); 264 ++line_no; 265 now_col = ps.com_col; 266 *e_com++ = ' '; 267 /* 268 * fix so that the star at the start of the line will line 269 * up 270 */ 271 do /* flush leading white space */ 272 if (++buf_ptr >= buf_end) 273 fill_buffer(); 274 while (*buf_ptr == ' ' || *buf_ptr == '\t'); 275 break; 276 } 277 if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') 278 last_bl = e_com - 1; 279 /* 280 * if there was a space at the end of the last line, remember 281 * where it was 282 */ 283 else { /* otherwise, insert one */ 284 last_bl = e_com; 285 CHECK_SIZE_COM; 286 *e_com++ = ' '; 287 ++now_col; 288 } 289 } 290 ++line_no; /* keep track of input line number */ 291 if (!ps.box_com) { 292 int nstar = 1; 293 do { /* flush any blanks and/or tabs at 294 * start of next line */ 295 if (++buf_ptr >= buf_end) 296 fill_buffer(); 297 if (*buf_ptr == '*' && --nstar >= 0) { 298 if (++buf_ptr >= buf_end) 299 fill_buffer(); 300 if (*buf_ptr == '/') 301 goto end_of_comment; 302 } 303 } while (*buf_ptr == ' ' || *buf_ptr == '\t'); 304 } else 305 if (++buf_ptr >= buf_end) 306 fill_buffer(); 307 break; /* end of case for newline */ 308 309 case '*': /* must check for possibility of being at end 310 * of comment */ 311 if (++buf_ptr >= buf_end) /* get to next char 312 * after * */ 313 fill_buffer(); 314 315 if (unix_comment == 0) /* set flag to show we are not 316 * in unix-style comment */ 317 unix_comment = 1; 318 319 if (*buf_ptr == '/') { /* it is the end!!! */ 320 end_of_comment: 321 if (++buf_ptr >= buf_end) 322 fill_buffer(); 323 324 if (*(e_com - 1) != ' ' && !ps.box_com) { /* insure blank before 325 * end */ 326 *e_com++ = ' '; 327 ++now_col; 328 } 329 if (break_delim == 1 && !one_liner && s_com[0] == '/' 330 && s_com[1] == '*' && s_com[2] == ' ') { 331 char *t = e_com; 332 break_delim = 2; 333 e_com = s_com + 2; 334 *e_com = 0; 335 if (blanklines_before_blockcomments) 336 prefix_blankline_requested = 1; 337 dump_line(); 338 e_com = t; 339 s_com[0] = s_com[1] = s_com[2] = ' '; 340 } 341 if (break_delim == 2 && e_com > s_com + 3 342 /* now_col > adj_max_col - 2 && !ps.box_com */ ) { 343 *e_com = '\0'; 344 dump_line(); 345 now_col = ps.com_col; 346 } 347 CHECK_SIZE_COM; 348 *e_com++ = '*'; 349 *e_com++ = '/'; 350 *e_com = '\0'; 351 ps.just_saw_decl = l_just_saw_decl; 352 return; 353 } else {/* handle isolated '*' */ 354 *e_com++ = '*'; 355 ++now_col; 356 } 357 break; 358 default: /* we have a random char */ 359 if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') 360 unix_comment = 1; /* we are not in 361 * unix-style comment */ 362 363 *e_com = *buf_ptr++; 364 if (buf_ptr >= buf_end) 365 fill_buffer(); 366 367 if (*e_com == '\t') /* keep track of column */ 368 now_col = ((now_col - 1) & tabmask) + tabsize + 1; 369 else 370 if (*e_com == '\b') /* this is a backspace */ 371 --now_col; 372 else 373 ++now_col; 374 375 if (*e_com == ' ' || *e_com == '\t') 376 last_bl = e_com; 377 /* remember we saw a blank */ 378 379 ++e_com; 380 if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 381 && !iscntrl((unsigned char)e_com[-1]) 382 && !isblank((unsigned char)e_com[-1])) { 383 /* 384 * the comment is too long, it must be broken up 385 */ 386 if (break_delim == 1 && s_com[0] == '/' 387 && s_com[1] == '*' && s_com[2] == ' ') { 388 char *t = e_com; 389 break_delim = 2; 390 e_com = s_com + 2; 391 *e_com = 0; 392 if (blanklines_before_blockcomments) 393 prefix_blankline_requested = 1; 394 dump_line(); 395 e_com = t; 396 s_com[0] = s_com[1] = s_com[2] = ' '; 397 } 398 if (last_bl == 0) { /* we have seen no 399 * blanks */ 400 last_bl = e_com; /* fake it */ 401 *e_com++ = ' '; 402 } 403 *e_com = '\0'; /* print what we have */ 404 *last_bl = '\0'; 405 while (last_bl > s_com && iscntrl((unsigned char)last_bl[-1]) ) 406 *--last_bl = 0; 407 e_com = last_bl; 408 dump_line(); 409 410 *e_com++ = ' '; /* add blanks for continuation */ 411 *e_com++ = ' '; 412 *e_com++ = ' '; 413 414 t_ptr = last_bl + 1; 415 last_bl = 0; 416 if (t_ptr >= e_com) { 417 while (*t_ptr == ' ' || *t_ptr == '\t') 418 t_ptr++; 419 while (*t_ptr != '\0') { /* move unprinted part 420 * of comment down in 421 * buffer */ 422 if (*t_ptr == ' ' || *t_ptr == '\t') 423 last_bl = e_com; 424 *e_com++ = *t_ptr++; 425 } 426 } 427 *e_com = '\0'; 428 now_col = count_spaces(ps.com_col, s_com); /* recompute current 429 * position */ 430 } 431 break; 432 } 433 } 434 } 435