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

Defined functions

bakcopy defined in line 998; used 1 times
getpro defined in line 1114; used 1 times
main defined in line 146; never used
nxtarg defined in line 1148; used 2 times
set_option defined in line 1040; used 2 times
set_profile defined in line 1165; used 1 times
set_var defined in line 1059; used 1 times

Defined variables

bakfile defined in line 144; used 5 times
in_name defined in line 138; used 8 times
options defined in line 114; used 4 times
out_name defined in line 141; used 4 times
sccsid defined in line 1; never used

Defined struct's

logtmpl defined in line 184; used 2 times
  • in line 205(2)
templ defined in line 105; used 2 times
  • in line 114(2)
Last modified: 1983-09-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2009
Valid CSS Valid XHTML 1.0 Strict