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: }

Defined functions

bakcopy defined in line 1058; used 1 times
main defined in line 56; never used

Defined variables

bakfile defined in line 54; used 6 times
copyright defined in line 8; never used
in_name defined in line 50; used 11 times
out_name defined in line 52; used 4 times
sccsid defined in line 14; never used
Last modified: 1987-02-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3000
Valid CSS Valid XHTML 1.0 Strict