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