indent.c revision 330633
1/* 2 * Copyright (c) 1985 Sun Microsystems, Inc. 3 * Copyright (c) 1976 Board of Trustees of the University of Illinois. 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#ifndef lint 37static const char copyright[] = 38"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\ 39@(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ 40@(#) Copyright (c) 1980, 1993\n\ 41 The Regents of the University of California. All rights reserved.\n"; 42#endif /* not lint */ 43 44#if 0 45#ifndef lint 46static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; 47#endif /* not lint */ 48#endif 49 50#include <sys/cdefs.h> 51__FBSDID("$FreeBSD: stable/11/usr.bin/indent/indent.c 330633 2018-03-08 06:54:33Z eadler $"); 52 53#include <sys/param.h> 54#include <err.h> 55#include <fcntl.h> 56#include <unistd.h> 57#include <stdio.h> 58#include <stdlib.h> 59#include <string.h> 60#include <ctype.h> 61#include "indent_globs.h" 62#include "indent_codes.h" 63#include "indent.h" 64 65static void bakcopy(void); 66 67const char *in_name = "Standard Input"; /* will always point to name of input 68 * file */ 69const char *out_name = "Standard Output"; /* will always point to name 70 * of output file */ 71const char *simple_backup_suffix = ".BAK"; /* Suffix to use for backup 72 * files */ 73char bakfile[MAXPATHLEN] = ""; 74 75int 76main(int argc, char **argv) 77{ 78 79 int dec_ind; /* current indentation for declarations */ 80 int di_stack[20]; /* a stack of structure indentation levels */ 81 int flushed_nl; /* used when buffering up comments to remember 82 * that a newline was passed over */ 83 int force_nl; /* when true, code must be broken */ 84 int hd_type = 0; /* used to store type of stmt for if (...), 85 * for (...), etc */ 86 int i; /* local loop counter */ 87 int scase; /* set to true when we see a case, so we will 88 * know what to do with the following colon */ 89 int sp_sw; /* when true, we are in the expression of 90 * if(...), while(...), etc. */ 91 int squest; /* when this is positive, we have seen a ? 92 * without the matching : in a <c>?<s>:<s> 93 * construct */ 94 const char *t_ptr; /* used for copying tokens */ 95 int tabs_to_var; /* true if using tabs to indent to var name */ 96 int type_code; /* the type of token, returned by lexi */ 97 98 int last_else = 0; /* true iff last keyword was an else */ 99 const char *envval = NULL; 100 101 /*-----------------------------------------------*\ 102 | INITIALIZATION | 103 \*-----------------------------------------------*/ 104 105 found_err = 0; 106 107 ps.p_stack[0] = stmt; /* this is the parser's stack */ 108 ps.last_nl = true; /* this is true if the last thing scanned was 109 * a newline */ 110 ps.last_token = semicolon; 111 combuf = (char *) malloc(bufsize); 112 if (combuf == NULL) 113 err(1, NULL); 114 labbuf = (char *) malloc(bufsize); 115 if (labbuf == NULL) 116 err(1, NULL); 117 codebuf = (char *) malloc(bufsize); 118 if (codebuf == NULL) 119 err(1, NULL); 120 tokenbuf = (char *) malloc(bufsize); 121 if (tokenbuf == NULL) 122 err(1, NULL); 123 l_com = combuf + bufsize - 5; 124 l_lab = labbuf + bufsize - 5; 125 l_code = codebuf + bufsize - 5; 126 l_token = tokenbuf + bufsize - 5; 127 combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and 128 * comment buffers */ 129 combuf[1] = codebuf[1] = labbuf[1] = '\0'; 130 ps.else_if = 1; /* Default else-if special processing to on */ 131 s_lab = e_lab = labbuf + 1; 132 s_code = e_code = codebuf + 1; 133 s_com = e_com = combuf + 1; 134 s_token = e_token = tokenbuf + 1; 135 136 in_buffer = (char *) malloc(10); 137 if (in_buffer == NULL) 138 err(1, NULL); 139 in_buffer_limit = in_buffer + 8; 140 buf_ptr = buf_end = in_buffer; 141 line_no = 1; 142 had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; 143 sp_sw = force_nl = false; 144 ps.in_or_st = false; 145 ps.bl_line = true; 146 dec_ind = 0; 147 di_stack[ps.dec_nest = 0] = 0; 148 ps.want_blank = ps.in_stmt = ps.ind_stmt = false; 149 150 scase = ps.pcase = false; 151 squest = 0; 152 sc_end = 0; 153 bp_save = 0; 154 be_save = 0; 155 156 output = 0; 157 tabs_to_var = 0; 158 159 envval = getenv("SIMPLE_BACKUP_SUFFIX"); 160 if (envval) 161 simple_backup_suffix = envval; 162 163 /*--------------------------------------------------*\ 164 | COMMAND LINE SCAN | 165 \*--------------------------------------------------*/ 166 167#ifdef undef 168 max_col = 78; /* -l78 */ 169 lineup_to_parens = 1; /* -lp */ 170 ps.ljust_decl = 0; /* -ndj */ 171 ps.com_ind = 33; /* -c33 */ 172 star_comment_cont = 1; /* -sc */ 173 ps.ind_size = 8; /* -i8 */ 174 verbose = 0; 175 ps.decl_indent = 16; /* -di16 */ 176 ps.local_decl_indent = -1; /* if this is not set to some nonnegative value 177 * by an arg, we will set this equal to 178 * ps.decl_ind */ 179 ps.indent_parameters = 1; /* -ip */ 180 ps.decl_com_ind = 0; /* if this is not set to some positive value 181 * by an arg, we will set this equal to 182 * ps.com_ind */ 183 btype_2 = 1; /* -br */ 184 cuddle_else = 1; /* -ce */ 185 ps.unindent_displace = 0; /* -d0 */ 186 ps.case_indent = 0; /* -cli0 */ 187 format_block_comments = 1; /* -fcb */ 188 format_col1_comments = 1; /* -fc1 */ 189 procnames_start_line = 1; /* -psl */ 190 proc_calls_space = 0; /* -npcs */ 191 comment_delimiter_on_blankline = 1; /* -cdb */ 192 ps.leave_comma = 1; /* -nbc */ 193#endif 194 195 for (i = 1; i < argc; ++i) 196 if (strcmp(argv[i], "-npro") == 0) 197 break; 198 set_defaults(); 199 if (i >= argc) 200 set_profile(); 201 202 for (i = 1; i < argc; ++i) { 203 204 /* 205 * look thru args (if any) for changes to defaults 206 */ 207 if (argv[i][0] != '-') {/* no flag on parameter */ 208 if (input == NULL) { /* we must have the input file */ 209 in_name = argv[i]; /* remember name of input file */ 210 input = fopen(in_name, "r"); 211 if (input == NULL) /* check for open error */ 212 err(1, "%s", in_name); 213 continue; 214 } 215 else if (output == NULL) { /* we have the output file */ 216 out_name = argv[i]; /* remember name of output file */ 217 if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite 218 * the file */ 219 errx(1, "input and output files must be different"); 220 } 221 output = fopen(out_name, "w"); 222 if (output == NULL) /* check for create error */ 223 err(1, "%s", out_name); 224 continue; 225 } 226 errx(1, "unknown parameter: %s", argv[i]); 227 } 228 else 229 set_option(argv[i]); 230 } /* end of for */ 231 if (input == NULL) 232 input = stdin; 233 if (output == NULL) { 234 if (troff || input == stdin) 235 output = stdout; 236 else { 237 out_name = in_name; 238 bakcopy(); 239 } 240 } 241 if (ps.com_ind <= 1) 242 ps.com_ind = 2; /* dont put normal comments before column 2 */ 243 if (troff) { 244 if (bodyf.font[0] == 0) 245 parsefont(&bodyf, "R"); 246 if (scomf.font[0] == 0) 247 parsefont(&scomf, "I"); 248 if (blkcomf.font[0] == 0) 249 blkcomf = scomf, blkcomf.size += 2; 250 if (boxcomf.font[0] == 0) 251 boxcomf = blkcomf; 252 if (stringf.font[0] == 0) 253 parsefont(&stringf, "L"); 254 if (keywordf.font[0] == 0) 255 parsefont(&keywordf, "B"); 256 writefdef(&bodyf, 'B'); 257 writefdef(&scomf, 'C'); 258 writefdef(&blkcomf, 'L'); 259 writefdef(&boxcomf, 'X'); 260 writefdef(&stringf, 'S'); 261 writefdef(&keywordf, 'K'); 262 } 263 if (block_comment_max_col <= 0) 264 block_comment_max_col = max_col; 265 if (ps.local_decl_indent < 0) /* if not specified by user, set this */ 266 ps.local_decl_indent = ps.decl_indent; 267 if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ 268 ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; 269 if (continuation_indent == 0) 270 continuation_indent = ps.ind_size; 271 fill_buffer(); /* get first batch of stuff into input buffer */ 272 273 parse(semicolon); 274 { 275 char *p = buf_ptr; 276 int col = 1; 277 278 while (1) { 279 if (*p == ' ') 280 col++; 281 else if (*p == '\t') 282 col = ((col - 1) & ~7) + 9; 283 else 284 break; 285 p++; 286 } 287 if (col > ps.ind_size) 288 ps.ind_level = ps.i_l_follow = col / ps.ind_size; 289 } 290 if (troff) { 291 const char *p = in_name, 292 *beg = in_name; 293 294 while (*p) 295 if (*p++ == '/') 296 beg = p; 297 fprintf(output, ".Fn \"%s\"\n", beg); 298 } 299 /* 300 * START OF MAIN LOOP 301 */ 302 303 while (1) { /* this is the main loop. it will go until we 304 * reach eof */ 305 int is_procname; 306 307 type_code = lexi(); /* lexi reads one token. The actual 308 * characters read are stored in "token". lexi 309 * returns a code indicating the type of token */ 310 is_procname = ps.procname[0]; 311 312 /* 313 * The following code moves everything following an if (), while (), 314 * else, etc. up to the start of the following stmt to a buffer. This 315 * allows proper handling of both kinds of brace placement. 316 */ 317 318 flushed_nl = false; 319 while (ps.search_brace) { /* if we scanned an if(), while(), 320 * etc., we might need to copy stuff 321 * into a buffer we must loop, copying 322 * stuff into save_com, until we find 323 * the start of the stmt which follows 324 * the if, or whatever */ 325 switch (type_code) { 326 case newline: 327 ++line_no; 328 flushed_nl = true; 329 case form_feed: 330 break; /* form feeds and newlines found here will be 331 * ignored */ 332 333 case lbrace: /* this is a brace that starts the compound 334 * stmt */ 335 if (sc_end == 0) { /* ignore buffering if a comment wasn't 336 * stored up */ 337 ps.search_brace = false; 338 goto check_type; 339 } 340 if (btype_2) { 341 save_com[0] = '{'; /* we either want to put the brace 342 * right after the if */ 343 goto sw_buffer; /* go to common code to get out of 344 * this loop */ 345 } 346 case comment: /* we have a comment, so we must copy it into 347 * the buffer */ 348 if (!flushed_nl || sc_end != 0) { 349 if (sc_end == 0) { /* if this is the first comment, we 350 * must set up the buffer */ 351 save_com[0] = save_com[1] = ' '; 352 sc_end = &(save_com[2]); 353 } 354 else { 355 *sc_end++ = '\n'; /* add newline between 356 * comments */ 357 *sc_end++ = ' '; 358 --line_no; 359 } 360 *sc_end++ = '/'; /* copy in start of comment */ 361 *sc_end++ = '*'; 362 363 for (;;) { /* loop until we get to the end of the comment */ 364 *sc_end = *buf_ptr++; 365 if (buf_ptr >= buf_end) 366 fill_buffer(); 367 368 if (*sc_end++ == '*' && *buf_ptr == '/') 369 break; /* we are at end of comment */ 370 371 if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer 372 * overflow */ 373 diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); 374 fflush(output); 375 exit(1); 376 } 377 } 378 *sc_end++ = '/'; /* add ending slash */ 379 if (++buf_ptr >= buf_end) /* get past / in buffer */ 380 fill_buffer(); 381 break; 382 } 383 default: /* it is the start of a normal statement */ 384 if (flushed_nl) /* if we flushed a newline, make sure it is 385 * put back */ 386 force_nl = true; 387 if ((type_code == sp_paren && *token == 'i' 388 && last_else && ps.else_if) 389 || (type_code == sp_nparen && *token == 'e' 390 && e_code != s_code && e_code[-1] == '}')) 391 force_nl = false; 392 393 if (sc_end == 0) { /* ignore buffering if comment wasn't 394 * saved up */ 395 ps.search_brace = false; 396 goto check_type; 397 } 398 if (force_nl) { /* if we should insert a nl here, put it into 399 * the buffer */ 400 force_nl = false; 401 --line_no; /* this will be re-increased when the nl is 402 * read from the buffer */ 403 *sc_end++ = '\n'; 404 *sc_end++ = ' '; 405 if (verbose && !flushed_nl) /* print error msg if the line 406 * was not already broken */ 407 diag2(0, "Line broken"); 408 flushed_nl = false; 409 } 410 for (t_ptr = token; *t_ptr; ++t_ptr) 411 *sc_end++ = *t_ptr; /* copy token into temp buffer */ 412 ps.procname[0] = 0; 413 414 sw_buffer: 415 ps.search_brace = false; /* stop looking for start of 416 * stmt */ 417 bp_save = buf_ptr; /* save current input buffer */ 418 be_save = buf_end; 419 buf_ptr = save_com; /* fix so that subsequent calls to 420 * lexi will take tokens out of 421 * save_com */ 422 *sc_end++ = ' ';/* add trailing blank, just in case */ 423 buf_end = sc_end; 424 sc_end = 0; 425 break; 426 } /* end of switch */ 427 if (type_code != 0) /* we must make this check, just in case there 428 * was an unexpected EOF */ 429 type_code = lexi(); /* read another token */ 430 /* if (ps.search_brace) ps.procname[0] = 0; */ 431 if ((is_procname = ps.procname[0]) && flushed_nl 432 && !procnames_start_line && ps.in_decl 433 && type_code == ident) 434 flushed_nl = 0; 435 } /* end of while (search_brace) */ 436 last_else = 0; 437check_type: 438 if (type_code == 0) { /* we got eof */ 439 if (s_lab != e_lab || s_code != e_code 440 || s_com != e_com) /* must dump end of line */ 441 dump_line(); 442 if (ps.tos > 1) /* check for balanced braces */ 443 diag2(1, "Stuff missing from end of file"); 444 445 if (verbose) { 446 printf("There were %d output lines and %d comments\n", 447 ps.out_lines, ps.out_coms); 448 printf("(Lines with comments)/(Lines with code): %6.3f\n", 449 (1.0 * ps.com_lines) / code_lines); 450 } 451 fflush(output); 452 exit(found_err); 453 } 454 if ( 455 (type_code != comment) && 456 (type_code != newline) && 457 (type_code != preesc) && 458 (type_code != form_feed)) { 459 if (force_nl && 460 (type_code != semicolon) && 461 (type_code != lbrace || !btype_2)) { 462 /* we should force a broken line here */ 463 if (verbose && !flushed_nl) 464 diag2(0, "Line broken"); 465 flushed_nl = false; 466 dump_line(); 467 ps.want_blank = false; /* dont insert blank at line start */ 468 force_nl = false; 469 } 470 ps.in_stmt = true; /* turn on flag which causes an extra level of 471 * indentation. this is turned off by a ; or 472 * '}' */ 473 if (s_com != e_com) { /* the turkey has embedded a comment 474 * in a line. fix it */ 475 *e_code++ = ' '; 476 for (t_ptr = s_com; *t_ptr; ++t_ptr) { 477 CHECK_SIZE_CODE; 478 *e_code++ = *t_ptr; 479 } 480 *e_code++ = ' '; 481 *e_code = '\0'; /* null terminate code sect */ 482 ps.want_blank = false; 483 e_com = s_com; 484 } 485 } 486 else if (type_code != comment) /* preserve force_nl thru a comment */ 487 force_nl = false; /* cancel forced newline after newline, form 488 * feed, etc */ 489 490 491 492 /*-----------------------------------------------------*\ 493 | do switch on type of token scanned | 494 \*-----------------------------------------------------*/ 495 CHECK_SIZE_CODE; 496 switch (type_code) { /* now, decide what to do with the token */ 497 498 case form_feed: /* found a form feed in line */ 499 ps.use_ff = true; /* a form feed is treated much like a newline */ 500 dump_line(); 501 ps.want_blank = false; 502 break; 503 504 case newline: 505 if (ps.last_token != comma || ps.p_l_follow > 0 506 || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { 507 dump_line(); 508 ps.want_blank = false; 509 } 510 ++line_no; /* keep track of input line number */ 511 break; 512 513 case lparen: /* got a '(' or '[' */ 514 ++ps.p_l_follow; /* count parens to make Healy happy */ 515 if (ps.want_blank && *token != '[' && 516 (ps.last_token != ident || proc_calls_space 517 || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) 518 *e_code++ = ' '; 519 if (ps.in_decl && !ps.block_init) 520 if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) { 521 ps.dumped_decl_indent = 1; 522 sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); 523 e_code += strlen(e_code); 524 } 525 else { 526 while ((e_code - s_code) < dec_ind) { 527 CHECK_SIZE_CODE; 528 *e_code++ = ' '; 529 } 530 *e_code++ = token[0]; 531 } 532 else 533 *e_code++ = token[0]; 534 ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; 535 if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent 536 && ps.paren_indents[0] < 2 * ps.ind_size) 537 ps.paren_indents[0] = 2 * ps.ind_size; 538 ps.want_blank = false; 539 if (ps.in_or_st && *token == '(' && ps.tos <= 2) { 540 /* 541 * this is a kluge to make sure that declarations will be 542 * aligned right if proc decl has an explicit type on it, i.e. 543 * "int a(x) {..." 544 */ 545 parse(semicolon); /* I said this was a kluge... */ 546 ps.in_or_st = false; /* turn off flag for structure decl or 547 * initialization */ 548 } 549 if (ps.sizeof_keyword) 550 ps.sizeof_mask |= 1 << ps.p_l_follow; 551 break; 552 553 case rparen: /* got a ')' or ']' */ 554 rparen_count--; 555 if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) { 556 ps.last_u_d = true; 557 ps.cast_mask &= (1 << ps.p_l_follow) - 1; 558 ps.want_blank = false; 559 } else 560 ps.want_blank = true; 561 ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; 562 if (--ps.p_l_follow < 0) { 563 ps.p_l_follow = 0; 564 diag3(0, "Extra %c", *token); 565 } 566 if (e_code == s_code) /* if the paren starts the line */ 567 ps.paren_level = ps.p_l_follow; /* then indent it */ 568 569 *e_code++ = token[0]; 570 571 if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if 572 * (...), or some such */ 573 sp_sw = false; 574 force_nl = true;/* must force newline after if */ 575 ps.last_u_d = true; /* inform lexi that a following 576 * operator is unary */ 577 ps.in_stmt = false; /* dont use stmt continuation 578 * indentation */ 579 580 parse(hd_type); /* let parser worry about if, or whatever */ 581 } 582 ps.search_brace = btype_2; /* this should insure that constructs 583 * such as main(){...} and int[]{...} 584 * have their braces put in the right 585 * place */ 586 break; 587 588 case unary_op: /* this could be any unary operation */ 589 if (ps.want_blank) 590 *e_code++ = ' '; 591 592 if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) { 593 sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); 594 ps.dumped_decl_indent = 1; 595 e_code += strlen(e_code); 596 } 597 else { 598 const char *res = token; 599 600 if (ps.in_decl && !ps.block_init) { /* if this is a unary op 601 * in a declaration, we 602 * should indent this 603 * token */ 604 for (i = 0; token[i]; ++i); /* find length of token */ 605 while ((e_code - s_code) < (dec_ind - i)) { 606 CHECK_SIZE_CODE; 607 *e_code++ = ' '; /* pad it */ 608 } 609 } 610 if (troff && token[0] == '-' && token[1] == '>') 611 res = "\\(->"; 612 for (t_ptr = res; *t_ptr; ++t_ptr) { 613 CHECK_SIZE_CODE; 614 *e_code++ = *t_ptr; 615 } 616 } 617 ps.want_blank = false; 618 break; 619 620 case binary_op: /* any binary operation */ 621 if (ps.want_blank) 622 *e_code++ = ' '; 623 { 624 const char *res = token; 625 626 if (troff) 627 switch (token[0]) { 628 case '<': 629 if (token[1] == '=') 630 res = "\\(<="; 631 break; 632 case '>': 633 if (token[1] == '=') 634 res = "\\(>="; 635 break; 636 case '!': 637 if (token[1] == '=') 638 res = "\\(!="; 639 break; 640 case '|': 641 if (token[1] == '|') 642 res = "\\(br\\(br"; 643 else if (token[1] == 0) 644 res = "\\(br"; 645 break; 646 } 647 for (t_ptr = res; *t_ptr; ++t_ptr) { 648 CHECK_SIZE_CODE; 649 *e_code++ = *t_ptr; /* move the operator */ 650 } 651 } 652 ps.want_blank = true; 653 break; 654 655 case postop: /* got a trailing ++ or -- */ 656 *e_code++ = token[0]; 657 *e_code++ = token[1]; 658 ps.want_blank = true; 659 break; 660 661 case question: /* got a ? */ 662 squest++; /* this will be used when a later colon 663 * appears so we can distinguish the 664 * <c>?<n>:<n> construct */ 665 if (ps.want_blank) 666 *e_code++ = ' '; 667 *e_code++ = '?'; 668 ps.want_blank = true; 669 break; 670 671 case casestmt: /* got word 'case' or 'default' */ 672 scase = true; /* so we can process the later colon properly */ 673 goto copy_id; 674 675 case colon: /* got a ':' */ 676 if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */ 677 --squest; 678 if (ps.want_blank) 679 *e_code++ = ' '; 680 *e_code++ = ':'; 681 ps.want_blank = true; 682 break; 683 } 684 if (ps.in_or_st) { 685 *e_code++ = ':'; 686 ps.want_blank = false; 687 break; 688 } 689 ps.in_stmt = false; /* seeing a label does not imply we are in a 690 * stmt */ 691 for (t_ptr = s_code; *t_ptr; ++t_ptr) 692 *e_lab++ = *t_ptr; /* turn everything so far into a label */ 693 e_code = s_code; 694 *e_lab++ = ':'; 695 *e_lab++ = ' '; 696 *e_lab = '\0'; 697 698 force_nl = ps.pcase = scase; /* ps.pcase will be used by 699 * dump_line to decide how to 700 * indent the label. force_nl 701 * will force a case n: to be 702 * on a line by itself */ 703 scase = false; 704 ps.want_blank = false; 705 break; 706 707 case semicolon: /* got a ';' */ 708 ps.in_or_st = false;/* we are not in an initialization or 709 * structure declaration */ 710 scase = false; /* these will only need resetting in an error */ 711 squest = 0; 712 if (ps.last_token == rparen && rparen_count == 0) 713 ps.in_parameter_declaration = 0; 714 ps.cast_mask = 0; 715 ps.sizeof_mask = 0; 716 ps.block_init = 0; 717 ps.block_init_level = 0; 718 ps.just_saw_decl--; 719 720 if (ps.in_decl && s_code == e_code && !ps.block_init) 721 while ((e_code - s_code) < (dec_ind - 1)) { 722 CHECK_SIZE_CODE; 723 *e_code++ = ' '; 724 } 725 726 ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level 727 * structure declaration, we 728 * arent any more */ 729 730 if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { 731 732 /* 733 * This should be true iff there were unbalanced parens in the 734 * stmt. It is a bit complicated, because the semicolon might 735 * be in a for stmt 736 */ 737 diag2(1, "Unbalanced parens"); 738 ps.p_l_follow = 0; 739 if (sp_sw) { /* this is a check for an if, while, etc. with 740 * unbalanced parens */ 741 sp_sw = false; 742 parse(hd_type); /* dont lose the if, or whatever */ 743 } 744 } 745 *e_code++ = ';'; 746 ps.want_blank = true; 747 ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the 748 * middle of a stmt */ 749 750 if (!sp_sw) { /* if not if for (;;) */ 751 parse(semicolon); /* let parser know about end of stmt */ 752 force_nl = true;/* force newline after an end of stmt */ 753 } 754 break; 755 756 case lbrace: /* got a '{' */ 757 ps.in_stmt = false; /* dont indent the {} */ 758 if (!ps.block_init) 759 force_nl = true;/* force other stuff on same line as '{' onto 760 * new line */ 761 else if (ps.block_init_level <= 0) 762 ps.block_init_level = 1; 763 else 764 ps.block_init_level++; 765 766 if (s_code != e_code && !ps.block_init) { 767 if (!btype_2) { 768 dump_line(); 769 ps.want_blank = false; 770 } 771 else if (ps.in_parameter_declaration && !ps.in_or_st) { 772 ps.i_l_follow = 0; 773 if (function_brace_split) { /* dump the line prior to the 774 * brace ... */ 775 dump_line(); 776 ps.want_blank = false; 777 } else /* add a space between the decl and brace */ 778 ps.want_blank = true; 779 } 780 } 781 if (ps.in_parameter_declaration) 782 prefix_blankline_requested = 0; 783 784 if (ps.p_l_follow > 0) { /* check for preceding unbalanced 785 * parens */ 786 diag2(1, "Unbalanced parens"); 787 ps.p_l_follow = 0; 788 if (sp_sw) { /* check for unclosed if, for, etc. */ 789 sp_sw = false; 790 parse(hd_type); 791 ps.ind_level = ps.i_l_follow; 792 } 793 } 794 if (s_code == e_code) 795 ps.ind_stmt = false; /* dont put extra indentation on line 796 * with '{' */ 797 if (ps.in_decl && ps.in_or_st) { /* this is either a structure 798 * declaration or an init */ 799 di_stack[ps.dec_nest++] = dec_ind; 800 /* ? dec_ind = 0; */ 801 } 802 else { 803 ps.decl_on_line = false; /* we can't be in the middle of 804 * a declaration, so don't do 805 * special indentation of 806 * comments */ 807 if (blanklines_after_declarations_at_proctop 808 && ps.in_parameter_declaration) 809 postfix_blankline_requested = 1; 810 ps.in_parameter_declaration = 0; 811 } 812 dec_ind = 0; 813 parse(lbrace); /* let parser know about this */ 814 if (ps.want_blank) /* put a blank before '{' if '{' is not at 815 * start of line */ 816 *e_code++ = ' '; 817 ps.want_blank = false; 818 *e_code++ = '{'; 819 ps.just_saw_decl = 0; 820 break; 821 822 case rbrace: /* got a '}' */ 823 if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be 824 * omitted in 825 * declarations */ 826 parse(semicolon); 827 if (ps.p_l_follow) {/* check for unclosed if, for, else. */ 828 diag2(1, "Unbalanced parens"); 829 ps.p_l_follow = 0; 830 sp_sw = false; 831 } 832 ps.just_saw_decl = 0; 833 ps.block_init_level--; 834 if (s_code != e_code && !ps.block_init) { /* '}' must be first on 835 * line */ 836 if (verbose) 837 diag2(0, "Line broken"); 838 dump_line(); 839 } 840 *e_code++ = '}'; 841 ps.want_blank = true; 842 ps.in_stmt = ps.ind_stmt = false; 843 if (ps.dec_nest > 0) { /* we are in multi-level structure 844 * declaration */ 845 dec_ind = di_stack[--ps.dec_nest]; 846 if (ps.dec_nest == 0 && !ps.in_parameter_declaration) 847 ps.just_saw_decl = 2; 848 ps.in_decl = true; 849 } 850 prefix_blankline_requested = 0; 851 parse(rbrace); /* let parser know about this */ 852 ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead 853 && ps.il[ps.tos] >= ps.ind_level; 854 if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) 855 postfix_blankline_requested = 1; 856 break; 857 858 case swstmt: /* got keyword "switch" */ 859 sp_sw = true; 860 hd_type = swstmt; /* keep this for when we have seen the 861 * expression */ 862 goto copy_id; /* go move the token into buffer */ 863 864 case sp_paren: /* token is if, while, for */ 865 sp_sw = true; /* the interesting stuff is done after the 866 * expression is scanned */ 867 hd_type = (*token == 'i' ? ifstmt : 868 (*token == 'w' ? whilestmt : forstmt)); 869 870 /* 871 * remember the type of header for later use by parser 872 */ 873 goto copy_id; /* copy the token into line */ 874 875 case sp_nparen: /* got else, do */ 876 ps.in_stmt = false; 877 if (*token == 'e') { 878 if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { 879 if (verbose) 880 diag2(0, "Line broken"); 881 dump_line();/* make sure this starts a line */ 882 ps.want_blank = false; 883 } 884 force_nl = true;/* also, following stuff must go onto new line */ 885 last_else = 1; 886 parse(elselit); 887 } 888 else { 889 if (e_code != s_code) { /* make sure this starts a line */ 890 if (verbose) 891 diag2(0, "Line broken"); 892 dump_line(); 893 ps.want_blank = false; 894 } 895 force_nl = true;/* also, following stuff must go onto new line */ 896 last_else = 0; 897 parse(dolit); 898 } 899 goto copy_id; /* move the token into line */ 900 901 case decl: /* we have a declaration type (int, register, 902 * etc.) */ 903 parse(decl); /* let parser worry about indentation */ 904 if (ps.last_token == rparen && ps.tos <= 1) { 905 ps.in_parameter_declaration = 1; 906 if (s_code != e_code) { 907 dump_line(); 908 ps.want_blank = 0; 909 } 910 } 911 if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { 912 ps.ind_level = ps.i_l_follow = 1; 913 ps.ind_stmt = 0; 914 } 915 ps.in_or_st = true; /* this might be a structure or initialization 916 * declaration */ 917 ps.in_decl = ps.decl_on_line = true; 918 if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) 919 ps.just_saw_decl = 2; 920 prefix_blankline_requested = 0; 921 for (i = 0; token[i++];); /* get length of token */ 922 923 if (ps.ind_level == 0 || ps.dec_nest > 0) { 924 /* global variable or struct member in local variable */ 925 dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; 926 tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); 927 } else { 928 /* local variable */ 929 dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; 930 tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); 931 } 932 goto copy_id; 933 934 case ident: /* got an identifier or constant */ 935 if (ps.in_decl) { /* if we are in a declaration, we must indent 936 * identifier */ 937 if (is_procname == 0 || !procnames_start_line) { 938 if (!ps.block_init) { 939 if (troff && !ps.dumped_decl_indent) { 940 if (ps.want_blank) 941 *e_code++ = ' '; 942 ps.want_blank = false; 943 sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); 944 ps.dumped_decl_indent = 1; 945 e_code += strlen(e_code); 946 } else { 947 int cur_dec_ind; 948 int pos, startpos; 949 950 /* 951 * in order to get the tab math right for 952 * indentations that are not multiples of 8 we 953 * need to modify both startpos and dec_ind 954 * (cur_dec_ind) here by eight minus the 955 * remainder of the current starting column 956 * divided by eight. This seems to be a 957 * properly working fix 958 */ 959 startpos = e_code - s_code; 960 cur_dec_ind = dec_ind; 961 pos = startpos; 962 if ((ps.ind_level * ps.ind_size) % 8 != 0) { 963 pos += (ps.ind_level * ps.ind_size) % 8; 964 cur_dec_ind += (ps.ind_level * ps.ind_size) % 8; 965 } 966 967 if (tabs_to_var) { 968 while ((pos & ~7) + 8 <= cur_dec_ind) { 969 CHECK_SIZE_CODE; 970 *e_code++ = '\t'; 971 pos = (pos & ~7) + 8; 972 } 973 } 974 while (pos < cur_dec_ind) { 975 CHECK_SIZE_CODE; 976 *e_code++ = ' '; 977 pos++; 978 } 979 if (ps.want_blank && e_code - s_code == startpos) 980 *e_code++ = ' '; 981 ps.want_blank = false; 982 } 983 } 984 } else { 985 if (ps.want_blank) 986 *e_code++ = ' '; 987 ps.want_blank = false; 988 if (dec_ind && s_code != e_code) 989 dump_line(); 990 dec_ind = 0; 991 } 992 } 993 else if (sp_sw && ps.p_l_follow == 0) { 994 sp_sw = false; 995 force_nl = true; 996 ps.last_u_d = true; 997 ps.in_stmt = false; 998 parse(hd_type); 999 } 1000 copy_id: 1001 if (ps.want_blank) 1002 *e_code++ = ' '; 1003 if (troff && ps.its_a_keyword) { 1004 e_code = chfont(&bodyf, &keywordf, e_code); 1005 for (t_ptr = token; *t_ptr; ++t_ptr) { 1006 CHECK_SIZE_CODE; 1007 *e_code++ = keywordf.allcaps && islower(*t_ptr) 1008 ? toupper(*t_ptr) : *t_ptr; 1009 } 1010 e_code = chfont(&keywordf, &bodyf, e_code); 1011 } 1012 else 1013 for (t_ptr = token; *t_ptr; ++t_ptr) { 1014 CHECK_SIZE_CODE; 1015 *e_code++ = *t_ptr; 1016 } 1017 ps.want_blank = true; 1018 break; 1019 1020 case strpfx: 1021 if (ps.want_blank) 1022 *e_code++ = ' '; 1023 for (t_ptr = token; *t_ptr; ++t_ptr) { 1024 CHECK_SIZE_CODE; 1025 *e_code++ = *t_ptr; 1026 } 1027 ps.want_blank = false; 1028 break; 1029 1030 case period: /* treat a period kind of like a binary 1031 * operation */ 1032 *e_code++ = '.'; /* move the period into line */ 1033 ps.want_blank = false; /* dont put a blank after a period */ 1034 break; 1035 1036 case comma: 1037 ps.want_blank = (s_code != e_code); /* only put blank after comma 1038 * if comma does not start the 1039 * line */ 1040 if (ps.in_decl && is_procname == 0 && !ps.block_init) 1041 while ((e_code - s_code) < (dec_ind - 1)) { 1042 CHECK_SIZE_CODE; 1043 *e_code++ = ' '; 1044 } 1045 1046 *e_code++ = ','; 1047 if (ps.p_l_follow == 0) { 1048 if (ps.block_init_level <= 0) 1049 ps.block_init = 0; 1050 if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8)) 1051 force_nl = true; 1052 } 1053 break; 1054 1055 case preesc: /* got the character '#' */ 1056 if ((s_com != e_com) || 1057 (s_lab != e_lab) || 1058 (s_code != e_code)) 1059 dump_line(); 1060 *e_lab++ = '#'; /* move whole line to 'label' buffer */ 1061 { 1062 int in_comment = 0; 1063 int com_start = 0; 1064 char quote = 0; 1065 int com_end = 0; 1066 1067 while (*buf_ptr == ' ' || *buf_ptr == '\t') { 1068 buf_ptr++; 1069 if (buf_ptr >= buf_end) 1070 fill_buffer(); 1071 } 1072 while (*buf_ptr != '\n' || (in_comment && !had_eof)) { 1073 CHECK_SIZE_LAB; 1074 *e_lab = *buf_ptr++; 1075 if (buf_ptr >= buf_end) 1076 fill_buffer(); 1077 switch (*e_lab++) { 1078 case BACKSLASH: 1079 if (troff) 1080 *e_lab++ = BACKSLASH; 1081 if (!in_comment) { 1082 *e_lab++ = *buf_ptr++; 1083 if (buf_ptr >= buf_end) 1084 fill_buffer(); 1085 } 1086 break; 1087 case '/': 1088 if (*buf_ptr == '*' && !in_comment && !quote) { 1089 in_comment = 1; 1090 *e_lab++ = *buf_ptr++; 1091 com_start = e_lab - s_lab - 2; 1092 } 1093 break; 1094 case '"': 1095 if (quote == '"') 1096 quote = 0; 1097 break; 1098 case '\'': 1099 if (quote == '\'') 1100 quote = 0; 1101 break; 1102 case '*': 1103 if (*buf_ptr == '/' && in_comment) { 1104 in_comment = 0; 1105 *e_lab++ = *buf_ptr++; 1106 com_end = e_lab - s_lab; 1107 } 1108 break; 1109 } 1110 } 1111 1112 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) 1113 e_lab--; 1114 if (e_lab - s_lab == com_end && bp_save == 0) { /* comment on 1115 * preprocessor line */ 1116 if (sc_end == 0) /* if this is the first comment, we 1117 * must set up the buffer */ 1118 sc_end = &(save_com[0]); 1119 else { 1120 *sc_end++ = '\n'; /* add newline between 1121 * comments */ 1122 *sc_end++ = ' '; 1123 --line_no; 1124 } 1125 bcopy(s_lab + com_start, sc_end, com_end - com_start); 1126 sc_end += com_end - com_start; 1127 if (sc_end >= &save_com[sc_size]) 1128 abort(); 1129 e_lab = s_lab + com_start; 1130 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) 1131 e_lab--; 1132 bp_save = buf_ptr; /* save current input buffer */ 1133 be_save = buf_end; 1134 buf_ptr = save_com; /* fix so that subsequent calls to 1135 * lexi will take tokens out of 1136 * save_com */ 1137 *sc_end++ = ' '; /* add trailing blank, just in case */ 1138 buf_end = sc_end; 1139 sc_end = 0; 1140 } 1141 *e_lab = '\0'; /* null terminate line */ 1142 ps.pcase = false; 1143 } 1144 1145 if (strncmp(s_lab, "#if", 3) == 0) { 1146 if (blanklines_around_conditional_compilation) { 1147 int c; 1148 prefix_blankline_requested++; 1149 while ((c = getc(input)) == '\n'); 1150 ungetc(c, input); 1151 } 1152 if ((size_t)ifdef_level < nitems(state_stack)) { 1153 match_state[ifdef_level].tos = -1; 1154 state_stack[ifdef_level++] = ps; 1155 } 1156 else 1157 diag2(1, "#if stack overflow"); 1158 } 1159 else if (strncmp(s_lab, "#else", 5) == 0) 1160 if (ifdef_level <= 0) 1161 diag2(1, "Unmatched #else"); 1162 else { 1163 match_state[ifdef_level - 1] = ps; 1164 ps = state_stack[ifdef_level - 1]; 1165 } 1166 else if (strncmp(s_lab, "#endif", 6) == 0) { 1167 if (ifdef_level <= 0) 1168 diag2(1, "Unmatched #endif"); 1169 else { 1170 ifdef_level--; 1171 1172#ifdef undef 1173 /* 1174 * This match needs to be more intelligent before the 1175 * message is useful 1176 */ 1177 if (match_state[ifdef_level].tos >= 0 1178 && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) 1179 diag2(0, "Syntactically inconsistent #ifdef alternatives"); 1180#endif 1181 } 1182 if (blanklines_around_conditional_compilation) { 1183 postfix_blankline_requested++; 1184 n_real_blanklines = 0; 1185 } 1186 } 1187 break; /* subsequent processing of the newline 1188 * character will cause the line to be printed */ 1189 1190 case comment: /* we have gotten a / followed by * this is a biggie */ 1191 if (flushed_nl) { /* we should force a broken line here */ 1192 flushed_nl = false; 1193 dump_line(); 1194 ps.want_blank = false; /* dont insert blank at line start */ 1195 force_nl = false; 1196 } 1197 pr_comment(); 1198 break; 1199 } /* end of big switch stmt */ 1200 1201 *e_code = '\0'; /* make sure code section is null terminated */ 1202 if (type_code != comment && type_code != newline && type_code != preesc) 1203 ps.last_token = type_code; 1204 } /* end of main while (1) loop */ 1205} 1206 1207/* 1208 * copy input file to backup file if in_name is /blah/blah/blah/file, then 1209 * backup file will be ".Bfile" then make the backup file the input and 1210 * original input file the output 1211 */ 1212static void 1213bakcopy(void) 1214{ 1215 int n, 1216 bakchn; 1217 char buff[8 * 1024]; 1218 const char *p; 1219 1220 /* construct file name .Bfile */ 1221 for (p = in_name; *p; p++); /* skip to end of string */ 1222 while (p > in_name && *p != '/') /* find last '/' */ 1223 p--; 1224 if (*p == '/') 1225 p++; 1226 sprintf(bakfile, "%s%s", p, simple_backup_suffix); 1227 1228 /* copy in_name to backup file */ 1229 bakchn = creat(bakfile, 0600); 1230 if (bakchn < 0) 1231 err(1, "%s", bakfile); 1232 while ((n = read(fileno(input), buff, sizeof buff)) != 0) 1233 if (write(bakchn, buff, n) != n) 1234 err(1, "%s", bakfile); 1235 if (n < 0) 1236 err(1, "%s", in_name); 1237 close(bakchn); 1238 fclose(input); 1239 1240 /* re-open backup file as the input file */ 1241 input = fopen(bakfile, "r"); 1242 if (input == NULL) 1243 err(1, "%s", bakfile); 1244 /* now the original input file will be the output */ 1245 output = fopen(in_name, "w"); 1246 if (output == NULL) { 1247 unlink(bakfile); 1248 err(1, "%s", in_name); 1249 } 1250} 1251