1 /* $NetBSD: indent.c,v 1.387 2023/06/27 04:41:23 rillig Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-4-Clause 5 * 6 * Copyright (c) 1985 Sun Microsystems, Inc. 7 * Copyright (c) 1976 Board of Trustees of the University of Illinois. 8 * Copyright (c) 1980, 1993 9 * The Regents of the University of California. 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 40 #include <sys/cdefs.h> 41 __RCSID("$NetBSD: indent.c,v 1.387 2023/06/27 04:41:23 rillig Exp $"); 42 43 #include <sys/param.h> 44 #include <err.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 50 #include "indent.h" 51 52 struct options opt = { 53 .brace_same_line = true, 54 .comment_delimiter_on_blank_line = true, 55 .cuddle_else = true, 56 .comment_column = 33, 57 .decl_indent = 16, 58 .else_if_in_same_line = true, 59 .function_brace_split = true, 60 .format_col1_comments = true, 61 .format_block_comments = true, 62 .indent_parameters = true, 63 .indent_size = 8, 64 .local_decl_indent = -1, 65 .lineup_to_parens = true, 66 .procnames_start_line = true, 67 .star_comment_cont = true, 68 .tabsize = 8, 69 .max_line_length = 78, 70 .use_tabs = true, 71 }; 72 73 struct parser_state ps; 74 75 struct buffer token; 76 77 struct buffer lab; 78 struct buffer code; 79 struct buffer com; 80 81 bool found_err; 82 bool had_eof; 83 int line_no = 1; 84 85 static struct { 86 struct parser_state *item; 87 size_t len; 88 size_t cap; 89 } ifdef; 90 91 FILE *input; 92 FILE *output; 93 94 static const char *in_name = "Standard Input"; 95 static char backup_name[PATH_MAX]; 96 static const char *backup_suffix = ".BAK"; 97 98 99 void * 100 nonnull(void *p) 101 { 102 if (p == NULL) 103 err(EXIT_FAILURE, NULL); 104 return p; 105 } 106 107 static void 108 buf_expand(struct buffer *buf, size_t add_size) 109 { 110 buf->cap = buf->cap + add_size + 400; 111 buf->s = nonnull(realloc(buf->s, buf->cap)); 112 } 113 114 #ifdef debug 115 void 116 buf_terminate(struct buffer *buf) 117 { 118 if (buf->len == buf->cap) 119 buf_expand(buf, 1); 120 buf->s[buf->len] = '\0'; 121 } 122 #endif 123 124 void 125 buf_add_char(struct buffer *buf, char ch) 126 { 127 if (buf->len == buf->cap) 128 buf_expand(buf, 1); 129 buf->s[buf->len++] = ch; 130 buf_terminate(buf); 131 } 132 133 void 134 buf_add_chars(struct buffer *buf, const char *s, size_t len) 135 { 136 if (len == 0) 137 return; 138 if (len > buf->cap - buf->len) 139 buf_expand(buf, len); 140 memcpy(buf->s + buf->len, s, len); 141 buf->len += len; 142 buf_terminate(buf); 143 } 144 145 static void 146 buf_add_buf(struct buffer *buf, const struct buffer *add) 147 { 148 buf_add_chars(buf, add->s, add->len); 149 } 150 151 void 152 diag(int level, const char *msg, ...) 153 { 154 va_list ap; 155 156 if (level != 0) 157 found_err = true; 158 159 va_start(ap, msg); 160 fprintf(stderr, "%s: %s:%d: ", 161 level == 0 ? "warning" : "error", in_name, line_no); 162 vfprintf(stderr, msg, ap); 163 fprintf(stderr, "\n"); 164 va_end(ap); 165 } 166 167 /* 168 * Compute the indentation from starting at 'ind' and adding the text starting 169 * at 's'. 170 */ 171 int 172 ind_add(int ind, const char *s, size_t len) 173 { 174 for (const char *p = s; len > 0; p++, len--) { 175 if (*p == '\n') 176 ind = 0; 177 else if (*p == '\t') 178 ind = next_tab(ind); 179 else 180 ind++; 181 } 182 return ind; 183 } 184 185 static void 186 init_globals(void) 187 { 188 ps_push(psym_stmt, false); /* as a stop symbol */ 189 ps.prev_lsym = lsym_semicolon; 190 ps.lbrace_kind = psym_lbrace_block; 191 192 const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX"); 193 if (suffix != NULL) 194 backup_suffix = suffix; 195 } 196 197 static void 198 load_profiles(int argc, char **argv) 199 { 200 const char *profile_name = NULL; 201 202 for (int i = 1; i < argc; i++) { 203 const char *arg = argv[i]; 204 205 if (strcmp(arg, "-npro") == 0) 206 return; 207 if (arg[0] == '-' && arg[1] == 'P' && arg[2] != '\0') 208 profile_name = arg + 2; 209 } 210 211 load_profile_files(profile_name); 212 } 213 214 /* 215 * Copy the input file to the backup file, then make the backup file the input 216 * and the original input file the output. 217 */ 218 static void 219 copy_to_bak_file(void) 220 { 221 size_t n; 222 char buff[BUFSIZ]; 223 224 const char *last_slash = strrchr(in_name, '/'); 225 const char *base = last_slash != NULL ? last_slash + 1 : in_name; 226 snprintf(backup_name, sizeof(backup_name), "%s%s", base, backup_suffix); 227 228 /* copy the input file to the backup file */ 229 FILE *bak = fopen(backup_name, "w"); 230 if (bak == NULL) 231 err(1, "%s", backup_name); 232 233 while ((n = fread(buff, 1, sizeof(buff), input)) > 0) 234 if (fwrite(buff, 1, n, bak) != n) 235 err(1, "%s", backup_name); 236 if (fclose(input) != 0) 237 err(1, "%s", in_name); 238 if (fclose(bak) != 0) 239 err(1, "%s", backup_name); 240 241 /* re-open the backup file as the input file */ 242 input = fopen(backup_name, "r"); 243 if (input == NULL) 244 err(1, "%s", backup_name); 245 /* now the original input file will be the output */ 246 output = fopen(in_name, "w"); 247 if (output == NULL) { 248 remove(backup_name); 249 err(1, "%s", in_name); 250 } 251 } 252 253 static void 254 parse_command_line(int argc, char **argv) 255 { 256 for (int i = 1; i < argc; i++) { 257 const char *arg = argv[i]; 258 259 if (arg[0] == '-') { 260 set_option(arg, "Command line"); 261 262 } else if (input == NULL) { 263 in_name = arg; 264 if ((input = fopen(in_name, "r")) == NULL) 265 err(1, "%s", in_name); 266 267 } else if (output == NULL) { 268 if (strcmp(arg, in_name) == 0) 269 errx(1, "input and output files " 270 "must be different"); 271 if ((output = fopen(arg, "w")) == NULL) 272 err(1, "%s", arg); 273 274 } else 275 errx(1, "too many arguments: %s", arg); 276 } 277 278 if (input == NULL) { 279 input = stdin; 280 output = stdout; 281 } else if (output == NULL) 282 copy_to_bak_file(); 283 284 if (opt.comment_column <= 1) 285 opt.comment_column = 2; /* don't put normal comments in column 286 * 1, see opt.format_col1_comments */ 287 if (opt.block_comment_max_line_length <= 0) 288 opt.block_comment_max_line_length = opt.max_line_length; 289 if (opt.local_decl_indent < 0) 290 opt.local_decl_indent = opt.decl_indent; 291 if (opt.decl_comment_column <= 0) 292 opt.decl_comment_column = opt.left_justify_decl 293 ? (opt.comment_column <= 10 ? 2 : opt.comment_column - 8) 294 : opt.comment_column; 295 if (opt.continuation_indent == 0) 296 opt.continuation_indent = opt.indent_size; 297 } 298 299 static void 300 set_initial_indentation(void) 301 { 302 inp_read_line(); 303 304 int ind = 0; 305 for (const char *p = inp_p;; p++) { 306 if (*p == ' ') 307 ind++; 308 else if (*p == '\t') 309 ind = next_tab(ind); 310 else 311 break; 312 } 313 314 ps.ind_level = ps.ind_level_follow = ind / opt.indent_size; 315 } 316 317 static bool 318 should_break_line(lexer_symbol lsym) 319 { 320 if (lsym == lsym_semicolon) 321 return false; 322 if (ps.prev_lsym == lsym_lbrace || ps.prev_lsym == lsym_semicolon) 323 return true; 324 if (lsym == lsym_lbrace && opt.brace_same_line) 325 return false; 326 return true; 327 } 328 329 static void 330 move_com_to_code(lexer_symbol lsym) 331 { 332 if (ps.want_blank) 333 buf_add_char(&code, ' '); 334 buf_add_buf(&code, &com); 335 buf_clear(&com); 336 ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket; 337 } 338 339 static void 340 update_ps_lbrace_kind(lexer_symbol lsym) 341 { 342 if (lsym == lsym_tag) { 343 ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct : 344 token.s[0] == 'u' ? psym_lbrace_union : 345 psym_lbrace_enum; 346 } else if ((lsym == lsym_type && ps.paren.len == 0) 347 || lsym == lsym_word 348 || lsym == lsym_lbrace) { 349 /* Keep the current '{' kind. */ 350 } else 351 ps.lbrace_kind = psym_lbrace_block; 352 } 353 354 static void 355 update_ps_badp(lexer_symbol lsym) 356 { 357 if (lsym == lsym_lbrace && ps.lbrace_kind == psym_lbrace_block 358 && ps.psyms.len == 3) 359 ps.badp = badp_seen_lbrace; 360 if (lsym == lsym_rbrace && !ps.in_decl) 361 ps.badp = badp_none; 362 if (lsym == lsym_type && ps.paren.len == 0 363 && (ps.badp == badp_seen_lbrace || ps.badp == badp_yes)) 364 ps.badp = badp_decl; 365 if (lsym == lsym_semicolon && ps.badp == badp_decl 366 && ps.decl_level == 0) 367 ps.badp = badp_seen_decl; 368 } 369 370 static void 371 indent_declarator(int decl_ind, bool tabs_to_var) 372 { 373 int base = ps.ind_level * opt.indent_size; 374 int ind = ind_add(base, code.s, code.len); 375 int target = base + decl_ind; 376 size_t orig_code_len = code.len; 377 378 if (tabs_to_var) 379 for (int next; (next = next_tab(ind)) <= target; ind = next) 380 buf_add_char(&code, '\t'); 381 for (; ind < target; ind++) 382 buf_add_char(&code, ' '); 383 if (code.len == orig_code_len && ps.want_blank) 384 buf_add_char(&code, ' '); 385 386 ps.want_blank = false; 387 ps.decl_indent_done = true; 388 } 389 390 static bool 391 is_function_pointer_declaration(void) 392 { 393 return ps.in_decl 394 && !ps.in_typedef_decl 395 && !ps.in_init 396 && !ps.decl_indent_done 397 && !ps.line_has_func_def 398 && ps.ind_paren_level == 0; 399 } 400 401 static int 402 process_eof(void) 403 { 404 finish_output(); 405 406 if (ps.psyms.len > 2) /* check for balanced braces */ 407 diag(1, "Stuff missing from end of file"); 408 409 return found_err ? EXIT_FAILURE : EXIT_SUCCESS; 410 } 411 412 /* move the whole line to the 'label' buffer */ 413 static void 414 read_preprocessing_line(void) 415 { 416 enum { 417 PLAIN, STR, CHR, COMM 418 } state = PLAIN; 419 420 buf_add_char(&lab, '#'); 421 422 while (inp_p[0] != '\n' || (state == COMM && !had_eof)) { 423 buf_add_char(&lab, inp_next()); 424 switch (lab.s[lab.len - 1]) { 425 case '\\': 426 if (state != COMM) 427 buf_add_char(&lab, inp_next()); 428 break; 429 case '/': 430 if (inp_p[0] == '*' && state == PLAIN) { 431 state = COMM; 432 buf_add_char(&lab, *inp_p++); 433 } 434 break; 435 case '"': 436 if (state == STR) 437 state = PLAIN; 438 else if (state == PLAIN) 439 state = STR; 440 break; 441 case '\'': 442 if (state == CHR) 443 state = PLAIN; 444 else if (state == PLAIN) 445 state = CHR; 446 break; 447 case '*': 448 if (inp_p[0] == '/' && state == COMM) { 449 state = PLAIN; 450 buf_add_char(&lab, *inp_p++); 451 } 452 break; 453 } 454 } 455 456 while (lab.len > 0 && ch_isblank(lab.s[lab.len - 1])) 457 lab.len--; 458 buf_terminate(&lab); 459 } 460 461 static void 462 paren_stack_push(struct paren_stack *s, int indent, enum paren_level_cast cast) 463 { 464 if (s->len == s->cap) { 465 s->cap = 10 + s->cap; 466 s->item = nonnull(realloc(s->item, 467 sizeof(s->item[0]) * s->cap)); 468 } 469 s->item[s->len++] = (struct paren_level){indent, cast}; 470 } 471 472 static void * 473 dup_mem(const void *src, size_t size) 474 { 475 return memcpy(nonnull(malloc(size)), src, size); 476 } 477 478 #define dup_array(src, len) \ 479 dup_mem((src), sizeof((src)[0]) * (len)) 480 #define copy_array(dst, src, len) \ 481 memcpy((dst), (src), sizeof((dst)[0]) * (len)) 482 483 static_unless_debug void 484 parser_state_back_up(struct parser_state *dst) 485 { 486 *dst = ps; 487 488 dst->paren.item = dup_array(ps.paren.item, ps.paren.len); 489 dst->psyms.sym = dup_array(ps.psyms.sym, ps.psyms.len); 490 dst->psyms.ind_level = dup_array(ps.psyms.ind_level, ps.psyms.len); 491 } 492 493 static void 494 parser_state_restore(const struct parser_state *src) 495 { 496 struct paren_level *ps_paren_item = ps.paren.item; 497 size_t ps_paren_cap = ps.paren.cap; 498 enum parser_symbol *ps_psyms_sym = ps.psyms.sym; 499 int *ps_psyms_ind_level = ps.psyms.ind_level; 500 size_t ps_psyms_cap = ps.psyms.cap; 501 502 ps = *src; 503 504 ps.paren.item = ps_paren_item; 505 ps.paren.cap = ps_paren_cap; 506 ps.psyms.sym = ps_psyms_sym; 507 ps.psyms.ind_level = ps_psyms_ind_level; 508 ps.psyms.cap = ps_psyms_cap; 509 510 copy_array(ps.paren.item, src->paren.item, src->paren.len); 511 copy_array(ps.psyms.sym, src->psyms.sym, src->psyms.len); 512 copy_array(ps.psyms.ind_level, src->psyms.ind_level, src->psyms.len); 513 } 514 515 static_unless_debug void 516 parser_state_free(struct parser_state *pst) 517 { 518 free(pst->paren.item); 519 free(pst->psyms.sym); 520 free(pst->psyms.ind_level); 521 } 522 523 static void 524 process_preprocessing(void) 525 { 526 if (lab.len > 0 || code.len > 0 || com.len > 0) 527 output_line(); 528 529 read_preprocessing_line(); 530 531 const char *dir = lab.s + 1, *line_end = lab.s + lab.len; 532 while (dir < line_end && ch_isblank(*dir)) 533 dir++; 534 size_t dir_len = 0; 535 while (dir + dir_len < line_end && ch_isalpha(dir[dir_len])) 536 dir_len++; 537 538 if (dir_len >= 2 && memcmp(dir, "if", 2) == 0) { 539 if (ifdef.len >= ifdef.cap) { 540 ifdef.cap += 5; 541 ifdef.item = nonnull(realloc(ifdef.item, 542 sizeof(ifdef.item[0]) * ifdef.cap)); 543 } 544 parser_state_back_up(ifdef.item + ifdef.len++); 545 out.line_kind = lk_pre_if; 546 547 } else if (dir_len >= 2 && memcmp(dir, "el", 2) == 0) { 548 if (ifdef.len == 0) 549 diag(1, "Unmatched #%.*s", (int)dir_len, dir); 550 else 551 parser_state_restore(ifdef.item + ifdef.len - 1); 552 out.line_kind = lk_pre_other; 553 554 } else if (dir_len == 5 && memcmp(dir, "endif", 5) == 0) { 555 if (ifdef.len == 0) 556 diag(1, "Unmatched #endif"); 557 else 558 parser_state_free(ifdef.item + --ifdef.len); 559 out.line_kind = lk_pre_endif; 560 } else 561 out.line_kind = lk_pre_other; 562 } 563 564 static void 565 process_newline(void) 566 { 567 if (ps.prev_lsym == lsym_comma 568 && ps.paren.len == 0 && !ps.in_init 569 && !opt.break_after_comma && ps.break_after_comma 570 && lab.len == 0 /* for preprocessing lines */ 571 && com.len == 0) 572 goto stay_in_line; 573 if (ps.psyms.sym[ps.psyms.len - 1] == psym_switch_expr 574 && opt.brace_same_line 575 && com.len == 0) { 576 ps.want_newline = true; 577 goto stay_in_line; 578 } 579 580 output_line(); 581 582 stay_in_line: 583 line_no++; 584 } 585 586 static bool 587 want_blank_before_lparen(void) 588 { 589 if (opt.proc_calls_space) 590 return true; 591 if (ps.prev_lsym == lsym_sizeof) 592 return opt.blank_after_sizeof; 593 if (ps.prev_lsym == lsym_rparen 594 || ps.prev_lsym == lsym_rbracket 595 || ps.prev_lsym == lsym_postfix_op 596 || ps.prev_lsym == lsym_offsetof 597 || ps.prev_lsym == lsym_word 598 || ps.prev_lsym == lsym_funcname) 599 return false; 600 return true; 601 } 602 603 static void 604 process_lparen(void) 605 { 606 607 if (is_function_pointer_declaration()) 608 indent_declarator(ps.decl_ind, ps.tabs_to_var); 609 else if (ps.want_blank && want_blank_before_lparen()) 610 buf_add_char(&code, ' '); 611 ps.want_blank = false; 612 buf_add_buf(&code, &token); 613 614 if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0) 615 ps.extra_expr_indent = eei_maybe; 616 617 if (ps.in_var_decl && ps.psyms.len <= 3 && !ps.in_init) { 618 parse(psym_stmt); /* prepare for function definition */ 619 ps.in_var_decl = false; 620 } 621 622 enum paren_level_cast cast = cast_unknown; 623 if (ps.prev_lsym == lsym_offsetof 624 || ps.prev_lsym == lsym_sizeof 625 || ps.prev_lsym == lsym_for 626 || ps.prev_lsym == lsym_if 627 || ps.prev_lsym == lsym_switch 628 || ps.prev_lsym == lsym_while 629 || ps.line_has_func_def) 630 cast = cast_no; 631 632 paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast); 633 } 634 635 static bool 636 rparen_is_cast(bool paren_cast) 637 { 638 if (ps.in_func_def_params) 639 return false; 640 if (ps.line_has_decl && !ps.in_init) 641 return false; 642 if (ps.prev_lsym == lsym_unary_op) 643 return true; 644 if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) 645 return false; 646 return paren_cast || ch_isalpha(inp_p[0]) || inp_p[0] == '{'; 647 } 648 649 static void 650 process_rparen(void) 651 { 652 if (ps.paren.len == 0) 653 diag(0, "Extra '%c'", *token.s); 654 655 bool paren_cast = ps.paren.len > 0 656 && ps.paren.item[--ps.paren.len].cast == cast_maybe; 657 ps.prev_paren_was_cast = rparen_is_cast(paren_cast); 658 if (ps.prev_paren_was_cast) { 659 ps.next_unary = true; 660 ps.want_blank = opt.space_after_cast; 661 } else 662 ps.want_blank = true; 663 664 if (code.len == 0) 665 ps.ind_paren_level = (int)ps.paren.len; 666 667 buf_add_buf(&code, &token); 668 669 if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { 670 parse(ps.spaced_expr_psym); 671 ps.spaced_expr_psym = psym_0; 672 673 ps.want_newline = true; 674 ps.next_unary = true; 675 ps.in_stmt_or_decl = false; 676 ps.want_blank = true; 677 out.line_kind = lk_stmt_head; 678 if (ps.extra_expr_indent == eei_maybe) 679 ps.extra_expr_indent = eei_last; 680 } 681 } 682 683 static void 684 process_lbracket(void) 685 { 686 if (code.len > 0 687 && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op)) 688 buf_add_char(&code, ' '); 689 buf_add_buf(&code, &token); 690 ps.want_blank = false; 691 692 paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast_no); 693 } 694 695 static void 696 process_rbracket(void) 697 { 698 if (ps.paren.len == 0) 699 diag(0, "Extra '%c'", *token.s); 700 if (ps.paren.len > 0) 701 ps.paren.len--; 702 703 if (code.len == 0) 704 ps.ind_paren_level = (int)ps.paren.len; 705 706 buf_add_buf(&code, &token); 707 ps.want_blank = true; 708 } 709 710 static void 711 process_lbrace(void) 712 { 713 if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) { 714 ps.in_var_decl = true; // XXX: not really 715 ps.in_init = true; 716 } 717 718 if (out.line_kind == lk_stmt_head) 719 out.line_kind = lk_other; 720 721 ps.in_stmt_or_decl = false; /* don't indent the {} */ 722 723 if (ps.in_init) 724 ps.init_level++; 725 else 726 ps.want_newline = true; 727 728 if (code.len > 0 && !ps.in_init) { 729 if (!opt.brace_same_line || 730 (code.len > 0 && code.s[code.len - 1] == '}')) 731 output_line(); 732 else if (ps.in_func_def_params && !ps.in_var_decl) { 733 ps.ind_level_follow = 0; 734 if (opt.function_brace_split) 735 output_line(); 736 else 737 ps.want_blank = true; 738 } 739 } 740 741 if (ps.paren.len > 0 && ps.init_level == 0) { 742 diag(1, "Unbalanced parentheses"); 743 ps.paren.len = 0; 744 if (ps.spaced_expr_psym != psym_0) { 745 parse(ps.spaced_expr_psym); 746 ps.spaced_expr_psym = psym_0; 747 ps.ind_level = ps.ind_level_follow; 748 } 749 } 750 751 if (code.len == 0) 752 ps.line_is_stmt_cont = false; 753 if (ps.in_decl && ps.in_var_decl) { 754 ps.di_stack[ps.decl_level] = ps.decl_ind; 755 if (++ps.decl_level == (int)array_length(ps.di_stack)) { 756 diag(0, "Reached internal limit of %zu struct levels", 757 array_length(ps.di_stack)); 758 ps.decl_level--; 759 } 760 } else { 761 ps.line_has_decl = false; /* don't do special indentation 762 * of comments */ 763 ps.in_func_def_params = false; 764 ps.in_decl = false; 765 } 766 767 ps.decl_ind = 0; 768 parse(ps.lbrace_kind); 769 if (ps.want_blank) 770 buf_add_char(&code, ' '); 771 ps.want_blank = false; 772 buf_add_char(&code, '{'); 773 ps.declaration = decl_no; 774 } 775 776 static void 777 process_rbrace(void) 778 { 779 if (ps.paren.len > 0 && ps.init_level == 0) { 780 diag(1, "Unbalanced parentheses"); 781 ps.paren.len = 0; 782 ps.spaced_expr_psym = psym_0; 783 } 784 785 ps.declaration = decl_no; 786 if (ps.decl_level == 0) 787 ps.blank_line_after_decl = false; 788 if (ps.init_level > 0) 789 ps.init_level--; 790 791 if (code.len > 0 && !ps.in_init) 792 output_line(); 793 794 buf_add_char(&code, '}'); 795 ps.want_blank = true; 796 ps.in_stmt_or_decl = false; // XXX: Initializers don't end a stmt 797 ps.line_is_stmt_cont = false; 798 799 if (ps.decl_level > 0) { /* multi-level structure declaration */ 800 ps.decl_ind = ps.di_stack[--ps.decl_level]; 801 if (ps.decl_level == 0 && !ps.in_func_def_params) { 802 ps.declaration = decl_begin; 803 ps.decl_ind = ps.ind_level == 0 804 ? opt.decl_indent : opt.local_decl_indent; 805 } 806 ps.in_decl = true; 807 } 808 809 if (ps.psyms.len == 3) 810 out.line_kind = lk_func_end; 811 812 parse(psym_rbrace); 813 814 if (!ps.in_var_decl 815 && ps.psyms.sym[ps.psyms.len - 1] != psym_do_stmt 816 && ps.psyms.sym[ps.psyms.len - 1] != psym_if_expr_stmt) 817 ps.want_newline = true; 818 } 819 820 static void 821 process_period(void) 822 { 823 if (code.len > 0 && code.s[code.len - 1] == ',') 824 buf_add_char(&code, ' '); 825 buf_add_char(&code, '.'); 826 ps.want_blank = false; 827 } 828 829 static void 830 process_unary_op(void) 831 { 832 if (is_function_pointer_declaration()) { 833 int ind = ps.decl_ind - (int)token.len; 834 indent_declarator(ind, ps.tabs_to_var); 835 } else if ((token.s[0] == '+' || token.s[0] == '-') 836 && code.len > 0 && code.s[code.len - 1] == token.s[0]) 837 ps.want_blank = true; 838 839 if (ps.want_blank) 840 buf_add_char(&code, ' '); 841 buf_add_buf(&code, &token); 842 ps.want_blank = false; 843 } 844 845 static void 846 process_postfix_op(void) 847 { 848 buf_add_buf(&code, &token); 849 ps.want_blank = true; 850 } 851 852 static void 853 process_comma(void) 854 { 855 ps.want_blank = code.len > 0; /* only put blank after comma if comma 856 * does not start the line */ 857 858 if (ps.in_decl && ps.ind_paren_level == 0 859 && !ps.line_has_func_def && !ps.in_init && !ps.decl_indent_done) { 860 /* indent leading commas and not the actual identifiers */ 861 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); 862 } 863 864 buf_add_char(&code, ','); 865 866 if (ps.paren.len == 0) { 867 if (ps.init_level == 0) 868 ps.in_init = false; 869 int typical_varname_length = 8; 870 if (ps.break_after_comma && (opt.break_after_comma || 871 ind_add(compute_code_indent(), code.s, code.len) 872 >= opt.max_line_length - typical_varname_length)) 873 ps.want_newline = true; 874 } 875 } 876 877 static void 878 process_label_colon(void) 879 { 880 buf_add_buf(&lab, &code); 881 buf_add_char(&lab, ':'); 882 buf_clear(&code); 883 884 if (ps.seen_case) 885 out.line_kind = lk_case_or_default; 886 ps.in_stmt_or_decl = false; 887 ps.want_newline = ps.seen_case; 888 ps.seen_case = false; 889 ps.want_blank = false; 890 } 891 892 static void 893 process_other_colon(void) 894 { 895 buf_add_char(&code, ':'); 896 ps.want_blank = ps.decl_level == 0; 897 } 898 899 static void 900 process_semicolon(void) 901 { 902 if (out.line_kind == lk_stmt_head) 903 out.line_kind = lk_other; 904 if (ps.decl_level == 0) { 905 ps.in_var_decl = false; 906 ps.in_typedef_decl = false; 907 } 908 ps.seen_case = false; /* only needs to be reset on error */ 909 ps.quest_level = 0; /* only needs to be reset on error */ 910 if (ps.prev_lsym == lsym_rparen) 911 ps.in_func_def_params = false; 912 ps.in_init = false; 913 ps.init_level = 0; 914 ps.declaration = ps.declaration == decl_begin ? decl_end : decl_no; 915 916 if (ps.in_decl && code.len == 0 && !ps.in_init && 917 !ps.decl_indent_done && ps.ind_paren_level == 0) { 918 /* indent stray semicolons in declarations */ 919 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); 920 } 921 922 ps.in_decl = ps.decl_level > 0; /* if we were in a first level 923 * structure declaration before, we 924 * aren't anymore */ 925 926 if (ps.paren.len > 0 && ps.spaced_expr_psym != psym_for_exprs) { 927 diag(1, "Unbalanced parentheses"); 928 ps.paren.len = 0; 929 if (ps.spaced_expr_psym != psym_0) { 930 parse(ps.spaced_expr_psym); 931 ps.spaced_expr_psym = psym_0; 932 } 933 } 934 buf_add_char(&code, ';'); 935 ps.want_blank = true; 936 ps.in_stmt_or_decl = ps.paren.len > 0; 937 ps.decl_ind = 0; 938 939 if (ps.spaced_expr_psym == psym_0) { 940 parse(psym_stmt); 941 ps.want_newline = true; 942 } 943 } 944 945 static void 946 process_type_outside_parentheses(void) 947 { 948 parse(psym_decl); /* let the parser worry about indentation */ 949 950 if (ps.prev_lsym == lsym_rparen && ps.psyms.len <= 2 && code.len > 0) 951 output_line(); 952 953 if (ps.in_func_def_params && opt.indent_parameters && 954 ps.decl_level == 0) { 955 ps.ind_level = ps.ind_level_follow = 1; 956 ps.line_is_stmt_cont = false; 957 } 958 959 ps.in_var_decl = /* maybe */ true; 960 ps.in_decl = true; 961 ps.line_has_decl = ps.in_decl; 962 if (ps.decl_level == 0) 963 ps.declaration = decl_begin; 964 965 int ind = ps.ind_level > 0 && ps.decl_level == 0 966 ? opt.local_decl_indent /* local variable */ 967 : opt.decl_indent; /* global variable, or member */ 968 if (ind == 0) { 969 int ind0 = code.len > 0 ? ind_add(0, code.s, code.len) + 1 : 0; 970 ps.decl_ind = ind_add(ind0, token.s, token.len) + 1; 971 } else 972 ps.decl_ind = ind; 973 ps.tabs_to_var = opt.use_tabs && ind > 0; 974 } 975 976 static void 977 process_word(lexer_symbol lsym) 978 { 979 if (lsym == lsym_type /* in parentheses */ 980 && ps.paren.item[ps.paren.len - 1].cast == cast_unknown) 981 ps.paren.item[ps.paren.len - 1].cast = cast_maybe; 982 983 if (ps.in_decl) { 984 if (lsym == lsym_funcname) { 985 ps.in_decl = false; 986 if (opt.procnames_start_line 987 && code.len > (*inp_p == ')' ? 1 : 0)) 988 output_line(); 989 else if (ps.want_blank) 990 buf_add_char(&code, ' '); 991 ps.want_blank = false; 992 } else if (ps.in_typedef_decl && ps.decl_level == 0) { 993 /* Do not indent typedef declarators. */ 994 } else if (!ps.in_init && !ps.decl_indent_done && 995 ps.ind_paren_level == 0) { 996 if (opt.decl_indent == 0 997 && code.len > 0 && code.s[code.len - 1] == '}') 998 ps.decl_ind = ind_add(0, code.s, code.len) + 1; 999 indent_declarator(ps.decl_ind, ps.tabs_to_var); 1000 } 1001 1002 } else if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { 1003 parse(ps.spaced_expr_psym); 1004 ps.spaced_expr_psym = psym_0; 1005 ps.want_newline = true; 1006 ps.in_stmt_or_decl = false; 1007 ps.next_unary = true; 1008 } 1009 } 1010 1011 static void 1012 process_do(void) 1013 { 1014 ps.in_stmt_or_decl = false; 1015 ps.in_decl = false; 1016 1017 if (code.len > 0) 1018 output_line(); 1019 1020 parse(psym_do); 1021 ps.want_newline = true; 1022 } 1023 1024 static void 1025 process_else(void) 1026 { 1027 ps.in_stmt_or_decl = false; 1028 ps.in_decl = false; 1029 1030 if (code.len > 0 1031 && !(opt.cuddle_else && code.s[code.len - 1] == '}')) 1032 output_line(); 1033 1034 parse(psym_else); 1035 ps.want_newline = true; 1036 } 1037 1038 static void 1039 process_lsym(lexer_symbol lsym) 1040 { 1041 switch (lsym) { 1042 /* INDENT OFF */ 1043 case lsym_preprocessing: process_preprocessing(); break; 1044 case lsym_newline: process_newline(); break; 1045 case lsym_comment: process_comment(); break; 1046 case lsym_lparen: process_lparen(); break; 1047 case lsym_lbracket: process_lbracket(); break; 1048 case lsym_rparen: process_rparen(); break; 1049 case lsym_rbracket: process_rbracket(); break; 1050 case lsym_lbrace: process_lbrace(); break; 1051 case lsym_rbrace: process_rbrace(); break; 1052 case lsym_period: process_period(); break; 1053 case lsym_unary_op: process_unary_op(); break; 1054 case lsym_postfix_op: process_postfix_op(); break; 1055 case lsym_binary_op: goto copy_token; 1056 case lsym_question: ps.quest_level++; goto copy_token; 1057 case lsym_question_colon: goto copy_token; 1058 case lsym_label_colon: process_label_colon(); break; 1059 case lsym_other_colon: process_other_colon(); break; 1060 case lsym_comma: process_comma(); break; 1061 case lsym_semicolon: process_semicolon(); break; 1062 case lsym_typedef: ps.in_typedef_decl = true; goto copy_token; 1063 case lsym_modifier: goto copy_token; 1064 case lsym_case: ps.seen_case = true; goto copy_token; 1065 case lsym_default: ps.seen_case = true; goto copy_token; 1066 case lsym_do: process_do(); goto copy_token; 1067 case lsym_else: process_else(); goto copy_token; 1068 case lsym_for: ps.spaced_expr_psym = psym_for_exprs; goto copy_token; 1069 case lsym_if: ps.spaced_expr_psym = psym_if_expr; goto copy_token; 1070 case lsym_switch: ps.spaced_expr_psym = psym_switch_expr; goto copy_token; 1071 case lsym_while: ps.spaced_expr_psym = psym_while_expr; goto copy_token; 1072 /* INDENT ON */ 1073 1074 case lsym_tag: 1075 if (ps.paren.len > 0) 1076 goto copy_token; 1077 /* FALLTHROUGH */ 1078 case lsym_type: 1079 if (ps.paren.len == 0) { 1080 process_type_outside_parentheses(); 1081 goto copy_token; 1082 } 1083 /* FALLTHROUGH */ 1084 case lsym_sizeof: 1085 case lsym_offsetof: 1086 case lsym_word: 1087 case lsym_funcname: 1088 case lsym_return: 1089 process_word(lsym); 1090 copy_token: 1091 if (ps.want_blank) 1092 buf_add_char(&code, ' '); 1093 buf_add_buf(&code, &token); 1094 if (lsym != lsym_funcname) 1095 ps.want_blank = true; 1096 break; 1097 1098 default: 1099 break; 1100 } 1101 } 1102 1103 static int 1104 indent(void) 1105 { 1106 debug_parser_state(); 1107 1108 for (;;) { /* loop until we reach eof */ 1109 lexer_symbol lsym = lexi(); 1110 1111 debug_blank_line(); 1112 debug_printf("line %d: %s", line_no, lsym_name[lsym]); 1113 debug_print_buf("token", &token); 1114 debug_buffers(); 1115 debug_blank_line(); 1116 1117 if (lsym == lsym_eof) 1118 return process_eof(); 1119 1120 if (lsym == lsym_preprocessing || lsym == lsym_newline) 1121 ps.want_newline = false; 1122 else if (lsym == lsym_comment) { 1123 /* no special processing */ 1124 } else { 1125 if (lsym == lsym_if && ps.prev_lsym == lsym_else 1126 && opt.else_if_in_same_line) 1127 ps.want_newline = false; 1128 1129 if (ps.want_newline && should_break_line(lsym)) { 1130 ps.want_newline = false; 1131 output_line(); 1132 } 1133 ps.in_stmt_or_decl = true; 1134 if (com.len > 0) 1135 move_com_to_code(lsym); 1136 update_ps_lbrace_kind(lsym); 1137 } 1138 1139 process_lsym(lsym); 1140 1141 if (opt.blank_line_after_decl_at_top) 1142 update_ps_badp(lsym); 1143 if (lsym != lsym_preprocessing 1144 && lsym != lsym_newline 1145 && lsym != lsym_comment) 1146 ps.prev_lsym = lsym; 1147 1148 debug_parser_state(); 1149 } 1150 } 1151 1152 int 1153 main(int argc, char **argv) 1154 { 1155 init_globals(); 1156 load_profiles(argc, argv); 1157 parse_command_line(argc, argv); 1158 set_initial_indentation(); 1159 return indent(); 1160 } 1161