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