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