# 2.11BSD#431 - /usr/src/ucb/indent/indent.c

##### Functions

    bakcopy           X
    main              X

##### Variables

    bakfile           X
    copyright         X
    in_name           X
    out_name          X

       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

- in line 183

main defined in line 56; never used

#### Defined variables

bakfile defined in line 54; used 6 times

- in line 1070-1075(3), 1081, 1092, 1101

copyright defined in line 8; never used
in_name defined in line 50; used 11 times

- in line 147-148(2), 156, 182, 222-223(2), 1066-1069(2), 1085, 1098-1100(2)

out_name defined in line 52; used 4 times

- in line 155-161(3), 182

sccsid defined in line 14; never used

Last modified: 1987-02-17 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2695 |