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