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