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