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