source: trunk/minix/commands/indent/indent.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

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