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