1
2 /* Copyright (c) 1992, Free Software Foundation, Inc. All rights reserved.
3
4 Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
5 of the University of California. Copyright (c) 1976 Board of Trustees of
6 the University of Illinois. All rights reserved.
7
8 Redistribution and use in source and binary forms are permitted
9 provided that
10 the above copyright notice and this paragraph are duplicated in all such
11 forms and that any documentation, advertising materials, and other
12 materials related to such distribution and use acknowledge that the
13 software was developed by the University of California, Berkeley, the
14 University of Illinois, Urbana, and Sun Microsystems, Inc. The name of
15 either University or Sun Microsystems may not be used to endorse or
16 promote products derived from this software without specific prior written
17 permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
19 OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
20
21 #include "sys.h"
22 #include "indent.h"
23 #include <ctype.h>
24
25 void
usage()26 usage ()
27 {
28 fprintf (stderr, "usage: indent file [-o outfile ] [ options ]\n");
29 fprintf (stderr, " indent file1 file2 ... fileN [ options ]\n");
30 exit (1);
31 }
32
33
34 /* Stuff that needs to be shared with the rest of indent.
35 Documented in indent.h. */
36 char *labbuf;
37 char *s_lab;
38 char *e_lab;
39 char *l_lab;
40 char *codebuf;
41 char *s_code;
42 char *e_code;
43 char *l_code;
44 char *combuf;
45 char *s_com;
46 char *e_com;
47 char *l_com;
48 struct buf save_com;
49 char *bp_save;
50 char *be_save;
51 int code_lines;
52 int line_no;
53 struct fstate keywordf;
54 struct fstate stringf;
55 struct fstate boxcomf;
56 struct fstate blkcomf;
57 struct fstate scomf;
58 struct fstate bodyf;
59 int break_comma;
60
61 /* Insure that BUFSTRUC has at least REQ more chars left, if not extend it.
62 Note: This may change bufstruc.ptr. */
63 #define need_chars(bufstruc, req) \
64 if ((bufstruc.end - bufstruc.ptr + (req)) >= bufstruc.size) \
65 {\
66 int cur_chars = bufstruc.end - bufstruc.ptr;\
67 bufstruc.size *= 2;\
68 bufstruc.ptr = xrealloc(bufstruc.ptr,bufstruc.size);\
69 bufstruc.end = bufstruc.ptr + cur_chars;\
70 }
71
72 int else_or_endif;
73
74 /* true iff last keyword was an else */
75 int last_else;
76
77 /* True if we have just encountered the end of an if (...), etc. (i.e. the
78 ')' of the if (...) was the last token). The variable is set to 2 in
79 the middle of the main token reading loop and is decremented at the
80 beginning of the loop, so it will reach zero when the second token after
81 the ')' is read. */
82 int last_token_ends_sp;
83
84 /* current indentation for declarations */
85 int dec_ind;
86
87 /* structure indentation levels */
88 int *di_stack;
89
90 /* Currently allocated size of di_stack. */
91 int di_stack_alloc;
92
93 /* used when buffering up comments to remember that
94 a newline was passed over */
95 int flushed_nl;
96 int force_nl;
97
98 /* set to true when we see a case, so we will know what to do
99 with the following colon */
100 int scase;
101
102 /* when true, we are in the expressin of if(...), while(...), etc. */
103 int sp_sw;
104
105 /* when this is positive, we have seen a ? without
106 the matching : in a <c>?<s>:<s> construct */
107 int squest;
108
109 static void
indent(this_file)110 indent (this_file)
111 struct file_buffer *this_file;
112 {
113 register int i;
114 enum codes hd_type;
115 register char *t_ptr;
116 enum codes type_code;
117 int dec_ind; /* current indentation for declarations */
118 int flushed_nl;
119 int force_nl;
120 int scase; /* true when we've just see a case */
121 int sp_sw; /* when true, we are in the expressin of
122 if(...), while(...), etc. */
123
124 /* True if we have just encountered the end of an if (...), etc. (i.e. the
125 ')' of the if (...) was the last token). The variable is set to 2 in
126 the middle of the main token reading loop and is decremented at the
127 beginning of the loop, so it will reach zero when the second token after
128 the ')' is read. */
129 int last_token_ends_sp;
130
131 int squest; /* when this is positive, we have seen a ?
132 without the matching : in a <c>?<s>:<s>
133 construct */
134 int last_else; /* true iff last keyword was an else */
135
136
137 in_prog = in_prog_pos = this_file->data;
138 in_prog_size = this_file->size;
139
140 hd_type = code_eof;
141 dec_ind = 0;
142 last_token_ends_sp = false;
143 last_else = false;
144 sp_sw = force_nl = false;
145 scase = false;
146
147 if (com_ind <= 1)
148 com_ind = 2; /* dont put normal comments before column 2 */
149 if (troff)
150 {
151 if (bodyf.font[0] == 0)
152 parsefont (&bodyf, "R");
153 if (scomf.font[0] == 0)
154 parsefont (&scomf, "I");
155 if (blkcomf.font[0] == 0)
156 blkcomf = scomf, blkcomf.size += 2;
157 if (boxcomf.font[0] == 0)
158 boxcomf = blkcomf;
159 if (stringf.font[0] == 0)
160 parsefont (&stringf, "L");
161 if (keywordf.font[0] == 0)
162 parsefont (&keywordf, "B");
163 writefdef (&bodyf, 'B');
164 writefdef (&scomf, 'C');
165 writefdef (&blkcomf, 'L');
166 writefdef (&boxcomf, 'X');
167 writefdef (&stringf, 'S');
168 writefdef (&keywordf, 'K');
169 }
170 if (block_comment_max_col <= 0)
171 block_comment_max_col = max_col;
172 if (decl_com_ind <= 0) /* if not specified by user, set this */
173 decl_com_ind =
174 ljust_decl ? (com_ind <= 10 ? 2 : com_ind - 8) : com_ind;
175 if (continuation_indent == 0)
176 continuation_indent = ind_size;
177 fill_buffer (); /* get first batch of stuff into input buffer */
178
179 parse (semicolon);
180 {
181 register char *p = buf_ptr;
182 register col = 1;
183
184 while (1)
185 {
186 if (*p == ' ')
187 col++;
188 else if (*p == '\t')
189 col = ((col - 1) & ~7) + 9;
190 else
191 break;
192 p++;
193 }
194 if (col > ind_size)
195 parser_state_tos->ind_level = parser_state_tos->i_l_follow = col;
196 }
197 if (troff)
198 {
199 register char *p = in_name, *beg = in_name;
200
201 while (*p)
202 if (*p++ == '/')
203 beg = p;
204 fprintf (output, ".Fn \"%s\"\n", beg);
205 }
206 /* START OF MAIN LOOP */
207
208 while (1)
209 { /* this is the main loop. it will go until
210 we reach eof */
211 int is_procname;
212
213 type_code = lexi (); /* lexi reads one token. "token" points to
214 the actual characters. lexi returns a code
215 indicating the type of token */
216
217 if (last_token_ends_sp > 0)
218 last_token_ends_sp--;
219 is_procname = parser_state_tos->procname[0];
220
221 /* The following code moves everything following an if (), while (),
222 else, etc. up to the start of the following stmt to a buffer. This
223 allows proper handling of both kinds of brace placement. */
224
225 flushed_nl = false;
226 while (parser_state_tos->search_brace)
227 {
228 /* After scanning an if(), while (), etc., it might be necessary to
229 keep track of the text between the if() and the start of the
230 statement which follows. Use save_com to do so. */
231
232 switch (type_code)
233 {
234 case newline:
235 ++line_no;
236 flushed_nl = true;
237 case form_feed:
238 break; /* form feeds and newlines found here will be
239 ignored */
240
241 case lbrace: /* this is a brace that starts the compound
242 stmt */
243 if (save_com.end == save_com.ptr)
244 {
245 /* ignore buffering if a comment wasnt stored up */
246 parser_state_tos->search_brace = false;
247 goto check_type;
248 }
249 /* We need to put the '{' back into save_com somewhere. */
250 if (btype_2)
251 /* Put it at the beginning, e.g. if (foo) { / * comment here *
252 / */
253
254 save_com.ptr[0] = '{';
255
256 else
257 {
258 /* Put it at the end, e.g. if (foo) / * comment here * / { */
259
260 /* Putting in this newline causes a dump_line to occur
261 right after the comment, thus insuring that it will be
262 put in the correct column. */
263 *save_com.end++ = '\n';
264 *save_com.end++ = '{';
265 }
266
267 /* Go to common code to get out of this loop. */
268 goto sw_buffer;
269
270 case comment: /* we have a comment, so we must copy it into
271 the buffer */
272 if (!flushed_nl || save_com.end != save_com.ptr)
273 {
274 need_chars (save_com, 10);
275 if (save_com.end == save_com.ptr)
276 { /* if this is the first comment, we must set
277 up the buffer */
278 save_com.ptr[0] = save_com.ptr[1] = ' ';
279 save_com.end = save_com.ptr + 2;
280 }
281 else
282 {
283 *save_com.end++ = '\n'; /* add newline between
284 comments */
285 *save_com.end++ = ' ';
286 --line_no;
287 }
288 *save_com.end++ = '/'; /* copy in start of comment */
289 *save_com.end++ = '*';
290
291 for (;;)
292 { /* loop until we get to the end of the
293 comment */
294 /* make sure there is room for this character and
295 (while we're at it) the '/' we might add at the end
296 of the loop. */
297 need_chars (save_com, 2);
298 *save_com.end = *buf_ptr++;
299 if (buf_ptr >= buf_end)
300 {
301 fill_buffer ();
302 if (had_eof)
303 {
304 diag (1, "Unclosed comment");
305 exit (1);
306 }
307 }
308
309 if (*save_com.end++ == '*' && *buf_ptr == '/')
310 break; /* we are at end of comment */
311
312 }
313 *save_com.end++ = '/'; /* add ending slash */
314 if (++buf_ptr >= buf_end) /* get past / in buffer */
315 fill_buffer ();
316 break;
317 }
318 default: /* it is the start of a normal statment */
319 if (flushed_nl) /* if we flushed a newline, make sure it is
320 put back */
321 force_nl = true;
322 if ((type_code == sp_paren && *token == 'i'
323 && last_else && else_if)
324 ||
325 (type_code == sp_nparen && *token == 'e'
326 && e_code != s_code && e_code[-1] == '}'))
327 force_nl = false;
328
329 if (save_com.end == save_com.ptr)
330 {
331 /* ignore buffering if comment wasnt saved up */
332 parser_state_tos->search_brace = false;
333 goto check_type;
334 }
335 if (force_nl)
336 { /* if we should insert a nl here, put it into
337 the buffer */
338 force_nl = false;
339 --line_no; /* this will be re-increased when the nl is
340 read from the buffer */
341 need_chars (save_com, 2);
342 *save_com.end++ = '\n';
343 *save_com.end++ = ' ';
344 if (verbose && !flushed_nl) /* print error msg if the
345 line was not already
346 broken */
347 diag (0, "Line broken");
348 flushed_nl = false;
349 }
350 for (t_ptr = token; t_ptr < token_end; ++t_ptr)
351 {
352 need_chars (save_com, 1);
353 *save_com.end++ = *t_ptr; /* copy token into temp
354 buffer */
355 }
356 parser_state_tos->procname = "\0";
357
358 sw_buffer:
359 parser_state_tos->search_brace = false; /* stop looking for
360 start of stmt */
361 bp_save = buf_ptr;/* save current input buffer */
362 be_save = buf_end;
363 buf_ptr = save_com.ptr; /* fix so that subsequent calls to
364 lexi will take tokens out of
365 save_com */
366 need_chars (save_com, 1);
367 *save_com.end++ = ' '; /* add trailing blank, just in case */
368 buf_end = save_com.end;
369 save_com.end = save_com.ptr; /* make save_com empty */
370 break;
371 } /* end of switch */
372 /* we must make this check, just in case there was an unexpected
373 EOF */
374 if (type_code != code_eof)
375 type_code = lexi ();/* read another token */
376 /* if (parser_state_tos->search_brace)
377 parser_state_tos->procname[0] = 0; */
378 if ((is_procname = parser_state_tos->procname[0]) && flushed_nl
379 && !procnames_start_line && parser_state_tos->in_decl
380 && type_code == ident)
381 flushed_nl = 0;
382 } /* end of while (search_brace) */
383 last_else = 0;
384
385 check_type:
386 if (type_code == code_eof)
387 { /* we got eof */
388 if (s_lab != e_lab || s_code != e_code
389 || s_com != e_com)/* must dump end of line */
390 dump_line ();
391 if (parser_state_tos->tos > 1) /* check for balanced braces */
392 diag (1, "Stuff missing from end of file.");
393
394 if (verbose)
395 {
396 printf ("There were %d output lines and %d comments\n",
397 out_lines, out_coms);
398 printf ("(Lines with comments)/(Lines with code): %6.3f\n",
399 (1.0 * com_lines) / code_lines);
400 }
401 fflush (output);
402 if (found_err)
403 exit (found_err);
404
405 return;
406 }
407
408 if ((type_code != comment) &&
409 (type_code != newline) &&
410 (type_code != preesc) &&
411 (type_code != form_feed))
412 {
413 if (force_nl &&
414 (type_code != semicolon) &&
415 (type_code != lbrace || !btype_2))
416 {
417 /* we should force a broken line here */
418 if (verbose && !flushed_nl)
419 diag (0, "Line broken");
420 flushed_nl = false;
421 dump_line ();
422 parser_state_tos->want_blank = false; /* dont insert blank at
423 line start */
424 force_nl = false;
425 }
426 parser_state_tos->in_stmt = true; /* turn on flag which causes
427 an extra level of
428 indentation. this is
429 turned off by a ; or } */
430 if (s_com != e_com)
431 { /* the turkey has embedded a comment in a
432 line. Move it from the com buffer to the
433 code buffer. */
434 /* Do not add a space before the comment if it is the first
435 thing on the line. */
436 if (e_code != s_code)
437 {
438 *e_code++ = ' ';
439 }
440 for (t_ptr = s_com; *t_ptr; ++t_ptr)
441 {
442 check_code_size;
443 *e_code++ = *t_ptr;
444 }
445 *e_code++ = ' ';
446 *e_code = '\0'; /* null terminate code sect */
447 parser_state_tos->want_blank = false;
448 e_com = s_com;
449 }
450 }
451 else if (type_code != comment) /* preserve force_nl thru a comment */
452 force_nl = false; /* cancel forced newline after newline, form
453 feed, etc */
454
455
456
457 /*-----------------------------------------------------*\
458 | do switch on type of token scanned |
459 \*-----------------------------------------------------*/
460 check_code_size;
461 switch (type_code)
462 { /* now, decide what to do with the token */
463
464 case form_feed: /* found a form feed in line */
465 parser_state_tos->use_ff = true; /* a form feed is treated
466 much like a newline */
467 dump_line ();
468 parser_state_tos->want_blank = false;
469 break;
470
471 case newline:
472 if (parser_state_tos->last_token != comma
473 || parser_state_tos->p_l_follow > 0
474 || !leave_comma || parser_state_tos->block_init
475 || !break_comma || s_com != e_com)
476 {
477 dump_line ();
478 parser_state_tos->want_blank = false;
479 }
480 /* If we were on the line with a #else or a #endif, we aren't
481 anymore. */
482 else_or_endif = false;
483 ++line_no; /* keep track of input line number */
484 break;
485
486 case lparen:
487 /* Braces in initializer lists should be put on new lines. This is
488 necessary so that -gnu does not cause things like char
489 *this_is_a_string_array[] = { "foo", "this_string_does_not_fit",
490 "nor_does_this_rather_long_string" } which is what happens
491 because we are trying to line the strings up with the
492 parentheses, and those that are too long are moved to the right
493 an ugly amount.
494
495 However, if the current line is empty, the left brace is
496 already on a new line, so don't molest it. */
497 if (token[0] == '{'
498 && (s_code != e_code || s_com != e_com || s_lab != e_lab))
499 {
500 dump_line ();
501 /* Do not put a space before the '{'. */
502 parser_state_tos->want_blank = false;
503 }
504
505 /* Count parens so we know how deep we are. */
506 if (++parser_state_tos->p_l_follow
507 >= parser_state_tos->paren_indents_size)
508 {
509 parser_state_tos->paren_indents_size *= 2;
510 parser_state_tos->paren_indents = (short *)
511 xrealloc (parser_state_tos->paren_indents,
512 parser_state_tos->paren_indents_size
513 * sizeof (short));
514 }
515 parser_state_tos->paren_depth++;
516 if (parser_state_tos->want_blank && *token != '['
517 && (parser_state_tos->last_token != ident || proc_calls_space
518 || (parser_state_tos->its_a_keyword
519 && (!parser_state_tos->sizeof_keyword
520 || blank_after_sizeof))))
521 *e_code++ = ' ';
522
523 if (parser_state_tos->in_decl && !parser_state_tos->block_init)
524 if (troff
525 && !parser_state_tos->dumped_decl_indent
526 && !is_procname
527 && parser_state_tos->last_token == decl)
528 {
529 parser_state_tos->dumped_decl_indent = 1;
530 sprintf (e_code, "\n.Du %dp+\200p \"%.*s\"\n", dec_ind * 7,
531 token_end - token, token);
532 e_code += strlen (e_code);
533 }
534 else
535 {
536 while ((e_code - s_code) < dec_ind)
537 {
538 check_code_size;
539 *e_code++ = ' ';
540 }
541 *e_code++ = token[0];
542 }
543 else
544 *e_code++ = token[0];
545
546 parser_state_tos->paren_indents[parser_state_tos->p_l_follow - 1]
547 = e_code - s_code;
548 if (sp_sw && parser_state_tos->p_l_follow == 1
549 && extra_expression_indent
550 && parser_state_tos->paren_indents[0] < 2 * ind_size)
551 parser_state_tos->paren_indents[0] = 2 * ind_size;
552 parser_state_tos->want_blank = false;
553
554 if (parser_state_tos->in_or_st
555 && *token == '('
556 && parser_state_tos->tos <= 2)
557 {
558 /* this is a kluge to make sure that declarations will be
559 aligned right if proc decl has an explicit type on it, i.e.
560 "int a(x) {..." */
561 parse_lparen_in_decl ();
562
563 /* Turn off flag for structure decl or initialization. */
564 parser_state_tos->in_or_st = false;
565 }
566 if (parser_state_tos->sizeof_keyword)
567 parser_state_tos->sizeof_mask |= 1 << parser_state_tos->p_l_follow;
568
569 /* The '(' that starts a cast can never be preceeded by an
570 indentifier or decl. */
571 if (parser_state_tos->last_token == decl
572 || (parser_state_tos->last_token == ident
573 && parser_state_tos->last_rw != rw_return))
574 parser_state_tos->noncast_mask |=
575 1 << parser_state_tos->p_l_follow;
576 else
577 parser_state_tos->noncast_mask &=
578 ~(1 << parser_state_tos->p_l_follow);
579
580 break;
581
582 case rparen:
583 if (parser_state_tos->cast_mask
584 & (1 << parser_state_tos->p_l_follow)
585 & ~parser_state_tos->sizeof_mask)
586 {
587 parser_state_tos->last_u_d = true;
588 parser_state_tos->cast_mask &=
589 (1 << parser_state_tos->p_l_follow) - 1;
590 if (!parser_state_tos->cast_mask && cast_space)
591 parser_state_tos->want_blank = true;
592 else
593 parser_state_tos->want_blank = false;
594 }
595 parser_state_tos->sizeof_mask
596 &= (1 << parser_state_tos->p_l_follow) - 1;
597 if (--parser_state_tos->p_l_follow < 0)
598 {
599 parser_state_tos->p_l_follow = 0;
600 diag (0, "Extra %c", *token);
601 }
602
603 parser_state_tos->paren_depth--;
604 /* if the paren starts the line, then indent it */
605 if (e_code == s_code)
606 {
607 int level = parser_state_tos->p_l_follow;
608 parser_state_tos->paren_level = level;
609 if (level > 0)
610 paren_target = -parser_state_tos->paren_indents[level - 1];
611 else
612 paren_target = 0;
613 }
614 else if (parser_state_tos->in_decl
615 && parser_state_tos->paren_depth == 0)
616 parser_state_tos->want_blank = true;
617 *e_code++ = token[0];
618
619 #if 0
620 if (!parser_state_tos->cast_mask || cast_space)
621 parser_state_tos->want_blank = true;
622 #endif
623
624 /* check for end of if (...), or some such */
625 if (sp_sw && (parser_state_tos->p_l_follow == 0))
626 {
627
628 /* Indicate that we have just left the parenthesized expression
629 of a while, if, or for, unless we are getting out of the
630 parenthesized expression of the while of a do-while loop.
631 (do-while is different because a semicolon immediately
632 following this will not indicate a null loop body). */
633 if (parser_state_tos->p_stack[parser_state_tos->tos]
634 != dohead)
635 last_token_ends_sp = 2;
636 sp_sw = false;
637 force_nl = true; /* must force newline after if */
638 parser_state_tos->last_u_d = true; /* inform lexi that a
639 following operator is
640 unary */
641 parser_state_tos->in_stmt = false; /* dont use stmt
642 continuation
643 indentation */
644
645 parse (hd_type); /* let parser worry about if, or whatever */
646 }
647 parser_state_tos->search_brace = btype_2; /* this should insure
648 that constructs such
649 as main(){...} and
650 int[]{...} have their
651 braces put in the
652 right place */
653 break;
654
655 case unary_op: /* this could be any unary operation */
656 if (parser_state_tos->want_blank)
657 *e_code++ = ' ';
658
659 if (troff
660 && !parser_state_tos->dumped_decl_indent
661 && parser_state_tos->in_decl && !is_procname)
662 {
663 sprintf (e_code, "\n.Du %dp+\200p \"%.*s\"\n", dec_ind * 7,
664 token_end - token, token);
665 parser_state_tos->dumped_decl_indent = 1;
666 e_code += strlen (e_code);
667 }
668 else
669 {
670 char *res = token;
671 char *res_end = token_end;
672
673 /* if this is a unary op in a declaration, we should
674 indent this token */
675 if (parser_state_tos->paren_depth == 0
676 && parser_state_tos->in_decl
677 && !parser_state_tos->block_init)
678 {
679 while ((e_code - s_code) < (dec_ind - (token_end - token)))
680 {
681 check_code_size;
682 *e_code++ = ' ';
683 }
684 }
685
686 if (troff && token[0] == '-' && token[1] == '>')
687 {
688 static char resval[] = "\\(->";
689 res = resval;
690 res_end = res + sizeof (resval);
691 }
692
693 for (t_ptr = res; t_ptr < res_end; ++t_ptr)
694 {
695 check_code_size;
696 *e_code++ = *t_ptr;
697 }
698 }
699 parser_state_tos->want_blank = false;
700 break;
701
702 case binary_op: /* any binary operation */
703 if (parser_state_tos->want_blank
704 || (e_code > s_code && *e_code != ' '))
705 *e_code++ = ' ';
706
707 {
708 char *res = token;
709 char *res_end = token_end;
710 #define set_res(str) \
711 {\
712 static char resval[] = str;\
713 res = resval;\
714 res_end = res + sizeof(resval);\
715 }
716
717 if (troff)
718 switch (token[0])
719 {
720 case '<':
721 if (token[1] == '=')
722 set_res ("\\(<=");
723 break;
724 case '>':
725 if (token[1] == '=')
726 set_res ("\\(>=");
727 break;
728 case '!':
729 if (token[1] == '=')
730 set_res ("\\(!=");
731 break;
732 case '|':
733 if (token[1] == '|')
734 {
735 set_res ("\\(br\\(br");
736 }
737 else if (token[1] == 0)
738 set_res ("\\(br");
739 break;
740 }
741
742 for (t_ptr = res; t_ptr < res_end; ++t_ptr)
743 {
744 check_code_size;
745 *e_code++ = *t_ptr; /* move the operator */
746 }
747 }
748 parser_state_tos->want_blank = true;
749 break;
750
751 case postop: /* got a trailing ++ or -- */
752 *e_code++ = token[0];
753 *e_code++ = token[1];
754 parser_state_tos->want_blank = true;
755 break;
756
757 case question: /* got a ? */
758 squest++; /* this will be used when a later colon
759 appears so we can distinguish the
760 <c>?<n>:<n> construct */
761 if (parser_state_tos->want_blank)
762 *e_code++ = ' ';
763 *e_code++ = '?';
764 parser_state_tos->want_blank = true;
765 break;
766
767 case casestmt: /* got word 'case' or 'default' */
768 scase = true; /* so we can process the later colon properly */
769 goto copy_id;
770
771 case colon: /* got a ':' */
772 if (squest > 0)
773 { /* it is part of the <c>?<n>: <n> construct */
774 --squest;
775 if (parser_state_tos->want_blank)
776 *e_code++ = ' ';
777 *e_code++ = ':';
778 parser_state_tos->want_blank = true;
779 break;
780 }
781 if (parser_state_tos->in_decl)
782 {
783 *e_code++ = ':';
784 parser_state_tos->want_blank = false;
785 break;
786 }
787 parser_state_tos->in_stmt = false; /* seeing a label does not
788 imply we are in a stmt */
789 for (t_ptr = s_code; *t_ptr; ++t_ptr)
790 *e_lab++ = *t_ptr; /* turn everything so far into a label */
791 e_code = s_code;
792 *e_lab++ = ':';
793 *e_lab++ = ' ';
794 *e_lab = '\0';
795 /* parser_state_tos->pcas e will be used by dump_line to decide
796 how to indent the label. force_nl will force a case n: to be
797 on a line by itself */
798 force_nl = parser_state_tos->pcase = scase;
799 scase = false;
800 parser_state_tos->want_blank = false;
801 break;
802
803 case semicolon:
804 /* we are not in an initialization or structure declaration */
805 parser_state_tos->in_or_st = false;
806 scase = false;
807 squest = 0;
808 /* The following code doesn't seem to do much good. Just because
809 we've found something like extern int foo(); or int (*foo)();
810 doesn't mean we are out of a declaration. Now if it was serving
811 some purpose we'll have to address that.... if
812 (parser_state_tos->last_token == rparen)
813 parser_state_tos->in_parameter_declaration = 0; */
814 parser_state_tos->cast_mask = 0;
815 parser_state_tos->sizeof_mask = 0;
816 parser_state_tos->block_init = 0;
817 parser_state_tos->block_init_level = 0;
818 parser_state_tos->just_saw_decl--;
819
820 if (parser_state_tos->in_decl
821 && s_code == e_code
822 && !parser_state_tos->block_init)
823 while ((e_code - s_code) < (dec_ind - 1))
824 {
825 check_code_size;
826 *e_code++ = ' ';
827 }
828
829 /* if we were in a first level structure declaration,
830 we aren't any more */
831 parser_state_tos->in_decl = (parser_state_tos->dec_nest > 0);
832 if ((!sp_sw || hd_type != forstmt)
833 && parser_state_tos->p_l_follow > 0)
834 {
835
836 /* This should be true iff there were unbalanced parens in the
837 stmt. It is a bit complicated, because the semicolon might
838 be in a for stmt */
839 diag (1, "Unbalanced parens");
840 parser_state_tos->p_l_follow = 0;
841 if (sp_sw)
842 { /* this is a check for a if, while, etc. with
843 unbalanced parens */
844 sp_sw = false;
845 parse (hd_type); /* dont lose the if, or whatever */
846 }
847 }
848
849 /* If we have a semicolon following an if, while, or for, and the
850 user wants us to, we should insert a space (to show that there
851 is a null statement there). */
852 if (last_token_ends_sp && space_sp_semicolon)
853 {
854 *e_code++ = ' ';
855 }
856 *e_code++ = ';';
857 parser_state_tos->want_blank = true;
858 /* we are no longer in the middle of a stmt */
859 parser_state_tos->in_stmt = (parser_state_tos->p_l_follow > 0);
860
861 if (!sp_sw)
862 { /* if not if for (;;) */
863 parse (semicolon);/* let parser know about end of stmt */
864 force_nl = true; /* force newline after a end of stmt */
865 }
866 break;
867
868 case lbrace: /* got a '{' */
869 parser_state_tos->in_stmt = false; /* dont indent the {} */
870 if (!parser_state_tos->block_init)
871 force_nl = true; /* force other stuff on same line as '{' onto
872 new line */
873 else if (parser_state_tos->block_init_level <= 0)
874 parser_state_tos->block_init_level = 1;
875 else
876 parser_state_tos->block_init_level++;
877
878 if (s_code != e_code && !parser_state_tos->block_init)
879 {
880 if (!btype_2)
881 {
882 dump_line ();
883 parser_state_tos->want_blank = false;
884 }
885 else
886 {
887 if (parser_state_tos->in_parameter_declaration
888 && !parser_state_tos->in_or_st)
889 {
890 parser_state_tos->i_l_follow = 0;
891 dump_line ();
892 parser_state_tos->want_blank = false;
893 }
894 else
895 parser_state_tos->want_blank = true;
896 }
897 }
898 if (parser_state_tos->in_parameter_declaration)
899 prefix_blankline_requested = 0;
900
901 if (parser_state_tos->p_l_follow > 0)
902 { /* check for preceeding unbalanced parens */
903 diag (1, "Unbalanced parens");
904 parser_state_tos->p_l_follow = 0;
905 if (sp_sw)
906 { /* check for unclosed if, for, etc. */
907 sp_sw = false;
908 parse (hd_type);
909 parser_state_tos->ind_level = parser_state_tos->i_l_follow;
910 }
911 }
912 if (s_code == e_code)
913 parser_state_tos->ind_stmt = false; /* dont put extra indentation
914 on line with '{' */
915 if (parser_state_tos->in_decl && parser_state_tos->in_or_st)
916 {
917 /* This is a structure declaration. */
918 if (parser_state_tos->dec_nest >= di_stack_alloc)
919 {
920 di_stack_alloc *= 2;
921 di_stack = (int *)
922 xrealloc (di_stack,
923 di_stack_alloc * sizeof (*di_stack));
924 }
925 di_stack[parser_state_tos->dec_nest++] = dec_ind;
926 /* ? dec_ind = 0; */
927 }
928 else
929 {
930 parser_state_tos->decl_on_line = false; /* we cant be in the
931 middle of a
932 declaration, so dont
933 do special
934 indentation of
935 comments */
936
937 #if 0 /* Doesn't work currently. */
938 if (blanklines_after_declarations_at_proctop
939 && parser_state_tos->in_parameter_declaration)
940 postfix_blankline_requested = 1;
941 #endif
942 parser_state_tos->in_parameter_declaration = 0;
943 }
944 dec_ind = 0;
945
946 /* We are no longer looking for an initializer or structure. Needed
947 so that the '=' in "enum bar {a = 1" does not get interpreted as
948 the start of an initializer. */
949 parser_state_tos->in_or_st = false;
950
951 parse (lbrace); /* let parser know about this */
952 if (parser_state_tos->want_blank) /* put a blank before '{' if
953 '{' is not at start of
954 line */
955 *e_code++ = ' ';
956 parser_state_tos->want_blank = false;
957 *e_code++ = '{';
958 parser_state_tos->just_saw_decl = 0;
959 break;
960
961 case rbrace: /* got a '}' */
962 /* semicolons can be omitted in declarations */
963 if (parser_state_tos->p_stack[parser_state_tos->tos] == decl
964 && !parser_state_tos->block_init)
965 parse (semicolon);
966 if (parser_state_tos->p_l_follow)
967 { /* check for unclosed if, for, else. */
968 diag (1, "Unbalanced parens");
969 parser_state_tos->p_l_follow = 0;
970 sp_sw = false;
971 }
972 parser_state_tos->just_saw_decl = 0;
973 parser_state_tos->block_init_level--;
974 if (s_code != e_code && !parser_state_tos->block_init)
975 { /* '}' must be first on line */
976 if (verbose)
977 diag (0, "Line broken");
978 dump_line ();
979 }
980 *e_code++ = '}';
981 parser_state_tos->want_blank = true;
982 parser_state_tos->in_stmt = parser_state_tos->ind_stmt = false;
983 if (parser_state_tos->dec_nest > 0)
984 { /* we are in multi-level structure
985 declaration */
986 dec_ind = di_stack[--parser_state_tos->dec_nest];
987 if (parser_state_tos->dec_nest == 0
988 && !parser_state_tos->in_parameter_declaration)
989 parser_state_tos->just_saw_decl = 2;
990 parser_state_tos->in_decl = true;
991 }
992 prefix_blankline_requested = 0;
993 parse (rbrace); /* let parser know about this */
994 if (parser_state_tos->p_stack[parser_state_tos->tos] == dohead
995 && !btype_2)
996 force_nl = true;
997 parser_state_tos->search_brace
998 = (cuddle_else
999 && parser_state_tos->p_stack[parser_state_tos->tos] == ifhead);
1000
1001 #if 0
1002 parser_state_tos->search_brace
1003 = (cuddle_else
1004 && parser_state_tos->p_stack[parser_state_tos->tos] == ifhead
1005 && (parser_state_tos->il[parser_state_tos->tos] >= parser_state_tos->ind_level));
1006 #endif
1007
1008 if (parser_state_tos->tos <= 1
1009 && blanklines_after_procs
1010 && parser_state_tos->dec_nest <= 0)
1011 postfix_blankline_requested = 1;
1012 break;
1013
1014 case swstmt: /* got keyword "switch" */
1015 sp_sw = true;
1016 hd_type = swstmt; /* keep this for when we have seen the
1017 expression */
1018 goto copy_id; /* go move the token into buffer */
1019
1020 case sp_paren: /* token is if, while, for */
1021 sp_sw = true; /* the interesting stuff is done after the
1022 expression is scanned */
1023 hd_type = (*token == 'i' ? ifstmt :
1024 (*token == 'w' ? whilestmt : forstmt));
1025
1026 /* remember the type of header for later use by parser */
1027 goto copy_id; /* copy the token into line */
1028
1029 case sp_nparen: /* got else, do */
1030 parser_state_tos->in_stmt = false;
1031 if (*token == 'e')
1032 {
1033 if (e_code != s_code && (!cuddle_else || e_code[-1] != '}'))
1034 {
1035 if (verbose)
1036 diag (0, "Line broken");
1037 dump_line (); /* make sure this starts a line */
1038 parser_state_tos->want_blank = false;
1039 }
1040 force_nl = true; /* also, following stuff must go onto new
1041 line */
1042 last_else = 1;
1043 parse (elselit);
1044 }
1045 else
1046 {
1047 if (e_code != s_code)
1048 { /* make sure this starts a line */
1049 if (verbose)
1050 diag (0, "Line broken");
1051 dump_line ();
1052 parser_state_tos->want_blank = false;
1053 }
1054 force_nl = true; /* also, following stuff must go onto new
1055 line */
1056 last_else = 0;
1057 parse (dolit);
1058 }
1059 goto copy_id; /* move the token into line */
1060
1061 case decl: /* we have a declaration type (int, register,
1062 etc.) */
1063
1064 parse (decl); /* let parser worry about indentation */
1065 if (parser_state_tos->last_token == rparen
1066 && parser_state_tos->tos <= 1)
1067 {
1068 parser_state_tos->in_parameter_declaration = 1;
1069 if (s_code != e_code)
1070 {
1071 dump_line ();
1072 parser_state_tos->want_blank = false;
1073 }
1074 }
1075 if (parser_state_tos->in_parameter_declaration
1076 && indent_parameters
1077 && parser_state_tos->dec_nest == 0
1078 && parser_state_tos->p_l_follow == 0)
1079 {
1080 parser_state_tos->ind_level = parser_state_tos->i_l_follow = indent_parameters;
1081 parser_state_tos->ind_stmt = 0;
1082 }
1083
1084 /* in_or_st set for struct or initialization decl. Don't set it if
1085 we're in ansi prototype */
1086 if (!parser_state_tos->paren_depth)
1087 parser_state_tos->in_or_st = true;
1088
1089 parser_state_tos->in_decl = parser_state_tos->decl_on_line = true;
1090 #if 0
1091 if (!parser_state_tos->in_or_st && parser_state_tos->dec_nest <= 0)
1092 #endif
1093 if (parser_state_tos->dec_nest <= 0)
1094 parser_state_tos->just_saw_decl = 2;
1095 if (prefix_blankline_requested
1096 && (parser_state_tos->block_init != 0
1097 || parser_state_tos->block_init_level != -1
1098 || parser_state_tos->last_token != rbrace
1099 || e_code != s_code
1100 || e_lab != s_lab
1101 || e_com != s_com))
1102 prefix_blankline_requested = 0;
1103 i = token_end - token + 1; /* get length of token plus 1 */
1104
1105 /* dec_ind = e_code - s_code + (parser_state_tos->decl_indent>i ?
1106 parser_state_tos->decl_indent : i); */
1107 dec_ind = decl_indent > 0 ? decl_indent : i;
1108 goto copy_id;
1109
1110 case ident: /* got an identifier or constant */
1111 /* If we are in a declaration, we must indent identifier. But not
1112 inside the parentheses of an ANSI function declaration. */
1113 if (parser_state_tos->in_decl
1114 && parser_state_tos->p_l_follow == 0
1115 && parser_state_tos->last_token != rbrace)
1116 {
1117 if (parser_state_tos->want_blank)
1118 *e_code++ = ' ';
1119 parser_state_tos->want_blank = false;
1120 if (is_procname == 0 || !procnames_start_line)
1121 {
1122 if (!parser_state_tos->block_init)
1123 if (troff && !parser_state_tos->dumped_decl_indent)
1124 {
1125 sprintf (e_code, "\n.De %dp+\200p\n", dec_ind * 7);
1126 parser_state_tos->dumped_decl_indent = 1;
1127 e_code += strlen (e_code);
1128 }
1129 else
1130 while ((e_code - s_code) < dec_ind)
1131 {
1132 check_code_size;
1133 *e_code++ = ' ';
1134 }
1135 }
1136 else
1137 {
1138 if (dec_ind && s_code != e_code)
1139 dump_line ();
1140 dec_ind = 0;
1141 parser_state_tos->want_blank = false;
1142 }
1143 }
1144 else if (sp_sw && parser_state_tos->p_l_follow == 0)
1145 {
1146 sp_sw = false;
1147 force_nl = true;
1148 parser_state_tos->last_u_d = true;
1149 parser_state_tos->in_stmt = false;
1150 parse (hd_type);
1151 }
1152 copy_id:
1153 if (parser_state_tos->want_blank)
1154 *e_code++ = ' ';
1155 if (troff && parser_state_tos->its_a_keyword)
1156 {
1157 e_code = chfont (&bodyf, &keywordf, e_code);
1158 for (t_ptr = token; t_ptr < token_end; ++t_ptr)
1159 {
1160 check_code_size;
1161 *e_code++ = keywordf.allcaps && islower (*t_ptr)
1162 ? toupper (*t_ptr) : *t_ptr;
1163 }
1164 e_code = chfont (&keywordf, &bodyf, e_code);
1165 }
1166 else
1167 {
1168 /* Troff mode requires that strings be processed specially. */
1169 if (troff && (*token == '"' || *token == '\''))
1170 {
1171 char qchar;
1172
1173 qchar = *token;
1174 *e_code++ = '`';
1175 if (qchar == '"')
1176 *e_code++ = '`';
1177 e_code = chfont (&bodyf, &stringf, e_code);
1178
1179 t_ptr = token + 1;
1180 while (t_ptr < token_end)
1181 {
1182 *e_code = *t_ptr++;
1183 if (*e_code == '\\')
1184 {
1185 *++e_code = '\\';
1186 if (*t_ptr == '\\')
1187 *++e_code = '\\';
1188 /* Copy char after backslash. */
1189 *++e_code = *t_ptr++;
1190 /* Point after the last char we copied. */
1191 e_code++;
1192 }
1193 }
1194 e_code = chfont (&stringf, &bodyf, e_code - 1);
1195 if (qchar == '"')
1196 *e_code++ = '\'';
1197 }
1198 else
1199 for (t_ptr = token; t_ptr < token_end; ++t_ptr)
1200 {
1201 check_code_size;
1202 *e_code++ = *t_ptr;
1203 }
1204 }
1205 parser_state_tos->want_blank = true;
1206
1207 /* If the token is va_dcl, it appears without a semicolon, so we
1208 need to pretend that one was there. */
1209 if ((token_end - token) == 6
1210 && strncmp (token, "va_dcl", 6) == 0)
1211 {
1212 parser_state_tos->in_or_st = false;
1213 parser_state_tos->just_saw_decl--;
1214 parser_state_tos->in_decl = 0;
1215 parse (semicolon);
1216 force_nl = true;
1217 }
1218 break;
1219
1220 case period: /* treat a period kind of like a binary
1221 operation */
1222 *e_code++ = '.'; /* move the period into line */
1223 parser_state_tos->want_blank = false; /* dont put a blank after a
1224 period */
1225 break;
1226
1227 case comma:
1228 /* only put blank after comma if comma does not start the line */
1229 parser_state_tos->want_blank = (s_code != e_code);
1230 if (parser_state_tos->paren_depth == 0
1231 && parser_state_tos->in_decl
1232 && is_procname == 0
1233 && !parser_state_tos->block_init)
1234 while ((e_code - s_code) < (dec_ind - 1))
1235 {
1236 check_code_size;
1237 *e_code++ = ' ';
1238 }
1239
1240 *e_code++ = ',';
1241 if (parser_state_tos->p_l_follow == 0)
1242 {
1243 if (parser_state_tos->block_init_level <= 0)
1244 parser_state_tos->block_init = 0;
1245 /* If we are in a declaration, and either the user wants all
1246 comma'd declarations broken, or the line is getting too
1247 long, break the line. */
1248 if (break_comma &&
1249 (!leave_comma
1250 || (compute_code_target () + (e_code - s_code)
1251 > max_col - 8)
1252 ))
1253 force_nl = true;
1254 }
1255 break;
1256
1257 case preesc: /* got the character '#' */
1258 if ((s_com != e_com) ||
1259 (s_lab != e_lab) ||
1260 (s_code != e_code))
1261 dump_line ();
1262 *e_lab++ = '#'; /* move whole line to 'label' buffer */
1263 {
1264 int in_comment = 0;
1265 int com_start = 0;
1266 char quote = 0;
1267 int com_end = 0;
1268
1269 /* ANSI allows spaces between '#' and preprocessor directives.
1270 Remove such spaces unless user has specified "-lpb". */
1271 while (*buf_ptr == ' ' || *buf_ptr == '\t')
1272 {
1273 if (leave_preproc_space)
1274 *e_lab++ = *buf_ptr;
1275 buf_ptr++;
1276 if (buf_ptr >= buf_end)
1277 fill_buffer ();
1278 }
1279 while (*buf_ptr != '\n' || (in_comment && !had_eof))
1280 {
1281 check_lab_size;
1282 *e_lab = *buf_ptr++;
1283 if (buf_ptr >= buf_end)
1284 fill_buffer ();
1285 switch (*e_lab++)
1286 {
1287 case BACKSLASH:
1288 if (troff)
1289 *e_lab++ = BACKSLASH;
1290 if (!in_comment)
1291 {
1292 *e_lab++ = *buf_ptr++;
1293 if (buf_ptr >= buf_end)
1294 fill_buffer ();
1295 }
1296 break;
1297 case '/':
1298 if (*buf_ptr == '*' && !in_comment && !quote)
1299 {
1300 in_comment = 1;
1301 *e_lab++ = *buf_ptr++;
1302 com_start = e_lab - s_lab - 2;
1303 }
1304 break;
1305 case '"':
1306 if (quote == '"')
1307 quote = 0;
1308 break;
1309 case '\'':
1310 if (quote == '\'')
1311 quote = 0;
1312 break;
1313 case '*':
1314 if (*buf_ptr == '/' && in_comment)
1315 {
1316 in_comment = 0;
1317 *e_lab++ = *buf_ptr++;
1318 com_end = e_lab - s_lab;
1319 }
1320 break;
1321 }
1322 }
1323
1324 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
1325 e_lab--;
1326 if (e_lab - s_lab == com_end && bp_save == 0)
1327 { /* comment on preprocessor line */
1328 if (save_com.end != save_com.ptr)
1329 {
1330 need_chars (save_com, 2);
1331 *save_com.end++ = '\n'; /* add newline between
1332 comments */
1333 *save_com.end++ = ' ';
1334 --line_no;
1335 }
1336 need_chars (save_com, com_end - com_start);
1337 strncpy (save_com.end, s_lab + com_start,
1338 com_end - com_start);
1339 save_com.end += com_end - com_start;
1340
1341 e_lab = s_lab + com_start;
1342 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
1343 e_lab--;
1344 bp_save = buf_ptr; /* save current input buffer */
1345 be_save = buf_end;
1346 buf_ptr = save_com.ptr; /* fix so that subsequent calls to
1347 lexi will take tokens out of
1348 save_com */
1349 need_chars (save_com, 1);
1350 *save_com.end++ = ' '; /* add trailing blank, just in case */
1351 buf_end = save_com.end;
1352 save_com.end = save_com.ptr; /* make save_com empty */
1353 }
1354 *e_lab = '\0'; /* null terminate line */
1355 parser_state_tos->pcase = false;
1356 }
1357
1358 if (strncmp (s_lab + 1, "if", 2) == 0)
1359 {
1360 if (blanklines_around_conditional_compilation)
1361 {
1362 register c;
1363 prefix_blankline_requested++;
1364 while ((c = *in_prog_pos++) == '\n');
1365 in_prog_pos--;
1366 }
1367 {
1368 /* Push a copy of the parser_state onto the stack. All
1369 manipulations will use the copy at the top of stack, and
1370 then we can return to the previous state by popping the
1371 stack. */
1372 struct parser_state *new;
1373
1374 new = (struct parser_state *)
1375 xmalloc (sizeof (struct parser_state));
1376 memcpy (new, parser_state_tos, sizeof (struct parser_state));
1377
1378 /* We need to copy the dynamically allocated arrays in the
1379 struct parser_state too. */
1380 new->p_stack = (enum codes *)
1381 xmalloc (parser_state_tos->p_stack_size
1382 * sizeof (enum codes));
1383 memcpy (new->p_stack, parser_state_tos->p_stack,
1384 parser_state_tos->p_stack_size * sizeof (enum codes));
1385
1386 new->il = (int *)
1387 xmalloc (parser_state_tos->p_stack_size * sizeof (int));
1388 memcpy (new->il, parser_state_tos->il,
1389 parser_state_tos->p_stack_size * sizeof (int));
1390
1391 new->cstk = (int *)
1392 xmalloc (parser_state_tos->p_stack_size
1393 * sizeof (int));
1394 memcpy (new->cstk, parser_state_tos->cstk,
1395 parser_state_tos->p_stack_size * sizeof (int));
1396
1397 new->paren_indents = (short *) xmalloc
1398 (parser_state_tos->paren_indents_size * sizeof (short));
1399 memcpy (new->paren_indents, parser_state_tos->paren_indents,
1400 parser_state_tos->paren_indents_size * sizeof (short));
1401
1402 new->next = parser_state_tos;
1403 parser_state_tos = new;
1404 }
1405 }
1406 else if (strncmp (s_lab + 1, "else", 4) == 0)
1407 {
1408 /* When we get #else, we want to restore the parser state to
1409 what it was before the matching #if, so that things get
1410 lined up with the code before the #if. However, we do not
1411 want to pop the stack; we just want to copy the second to
1412 top elt of the stack because when we encounter the #endif,
1413 it will pop the stack. */
1414 else_or_endif = true;
1415 if (parser_state_tos->next)
1416 {
1417 /* First save the addresses of the arrays for the top of
1418 stack. */
1419 enum codes *tos_p_stack = parser_state_tos->p_stack;
1420 int *tos_il = parser_state_tos->il;
1421 int *tos_cstk = parser_state_tos->cstk;
1422 short *tos_paren_indents =
1423 parser_state_tos->paren_indents;
1424 struct parser_state *second =
1425 parser_state_tos->next;
1426
1427 memcpy (parser_state_tos, second,
1428 sizeof (struct parser_state));
1429 parser_state_tos->next = second;
1430
1431 /* Now copy the arrays from the second to top of stack to
1432 the top of stack. */
1433 /* Since the p_stack, etc. arrays only grow, never shrink,
1434 we know that they will be big enough to fit the array
1435 from the second to top of stack. */
1436 parser_state_tos->p_stack = tos_p_stack;
1437 memcpy (parser_state_tos->p_stack,
1438 parser_state_tos->next->p_stack,
1439 parser_state_tos->p_stack_size
1440 * sizeof (enum codes));
1441
1442 parser_state_tos->il = tos_il;
1443 memcpy (parser_state_tos->il,
1444 parser_state_tos->next->il,
1445 parser_state_tos->p_stack_size * sizeof (int));
1446
1447 parser_state_tos->cstk = tos_cstk;
1448 memcpy (parser_state_tos->cstk,
1449 parser_state_tos->next->cstk,
1450 parser_state_tos->p_stack_size * sizeof (int));
1451
1452 parser_state_tos->paren_indents = tos_paren_indents;
1453 memcpy (parser_state_tos->paren_indents,
1454 parser_state_tos->next->paren_indents,
1455 parser_state_tos->paren_indents_size
1456 * sizeof (short));
1457 }
1458 else
1459 diag (1, "Unmatched #else");
1460 }
1461 else if (strncmp (s_lab + 1, "endif", 5) == 0)
1462 {
1463 else_or_endif = true;
1464 /* We want to remove the second to top elt on the stack, which
1465 was put there by #if and was used to restore the stack at
1466 the #else (if there was one). We want to leave the top of
1467 stack unmolested so that the state which we have been using
1468 is unchanged. */
1469 if (parser_state_tos->next)
1470 {
1471 struct parser_state *second = parser_state_tos->next;
1472
1473 parser_state_tos->next = second->next;
1474 free (second->p_stack);
1475 free (second->il);
1476 free (second->cstk);
1477 free (second->paren_indents);
1478 free (second);
1479 }
1480 else
1481 diag (1, "Unmatched #endif");
1482 if (blanklines_around_conditional_compilation)
1483 {
1484 postfix_blankline_requested++;
1485 n_real_blanklines = 0;
1486 }
1487 }
1488
1489 /* Normally, subsequent processing of the newline character
1490 causes the line to be printed. The following clause handles
1491 a special case (comma-separated declarations separated
1492 by the preprocessor lines) where this doesn't happen. */
1493 if (parser_state_tos->last_token == comma
1494 && parser_state_tos->p_l_follow <= 0
1495 && leave_comma && !parser_state_tos->block_init
1496 && break_comma && s_com == e_com)
1497 {
1498 dump_line ();
1499 parser_state_tos->want_blank = false;
1500 }
1501 break;
1502
1503 case comment: /* we have gotten a /* this is a biggie */
1504 if (flushed_nl)
1505 { /* we should force a broken line here */
1506 flushed_nl = false;
1507 dump_line ();
1508 parser_state_tos->want_blank = false; /* dont insert blank at
1509 line start */
1510 force_nl = false;
1511 }
1512 pr_comment ();
1513 break;
1514 } /* end of big switch stmt */
1515
1516 *e_code = '\0'; /* make sure code section is null terminated */
1517 if (type_code != comment
1518 && type_code != newline
1519 && type_code != preesc
1520 && type_code != form_feed)
1521 parser_state_tos->last_token = type_code;
1522
1523 } /* end of main while (1) loop */
1524 }
1525
1526
1527
1528 char *set_profile ();
1529 void set_defaults ();
1530 int set_option ();
1531
1532 /* Points to current input file */
1533 char *in_name = 0;
1534
1535 /* Points to the name of the output file */
1536 char *out_name = 0;
1537
1538 /* How many input files were specified */
1539 int input_files;
1540
1541 /* Names of all input files */
1542 char **in_file_names;
1543
1544 /* Initial number of input filenames to allocate. */
1545 int max_input_files = 128;
1546
1547
1548 #ifdef DEBUG
1549 int debug;
1550 #endif
1551
main(argc,argv)1552 main (argc, argv)
1553 int argc;
1554 char **argv;
1555 {
1556 register int i;
1557 struct file_buffer *current_input;
1558 char *profile_pathname = 0;
1559 int using_stdin = false;
1560
1561 #ifdef DEBUG
1562 if (debug)
1563 debug_init ();
1564 #endif
1565
1566 init_parser ();
1567 initialize_backups ();
1568
1569 output = 0;
1570 input_files = 0;
1571 in_file_names = (char **) xmalloc (max_input_files * sizeof (char *));
1572
1573 set_defaults ();
1574 for (i = 1; i < argc; ++i)
1575 if (strcmp (argv[i], "-npro") == 0
1576 || strcmp (argv[i], "--ignore-profile") == 0
1577 || strcmp (argv[i], "+ignore-profile") == 0)
1578 break;
1579 if (i >= argc)
1580 profile_pathname = set_profile ();
1581
1582 for (i = 1; i < argc; ++i)
1583 {
1584 if (argv[i][0] != '-' && argv[i][0] != '+') /* Filename */
1585 {
1586 if (expect_output_file == true) /* Last arg was "-o" */
1587 {
1588 if (out_name != 0)
1589 {
1590 fprintf (stderr, "indent: only one output file (2nd was %s)\n", argv[i]);
1591 exit (1);
1592 }
1593
1594 if (input_files > 1)
1595 {
1596 fprintf (stderr, "indent: only one input file when output file is specified\n");
1597 exit (1);
1598 }
1599
1600 out_name = argv[i];
1601 expect_output_file = false;
1602 continue;
1603 }
1604 else
1605 {
1606 if (using_stdin)
1607 {
1608 fprintf (stderr, "indent: can't have filenames when specifying standard input\n");
1609 exit (1);
1610 }
1611
1612 input_files++;
1613 if (input_files > 1)
1614 {
1615 if (out_name != 0)
1616 {
1617 fprintf (stderr, "indent: only one input file when output file is specified\n");
1618 exit (1);
1619 }
1620
1621 if (use_stdout != 0)
1622 {
1623 fprintf (stderr, "indent: only one input file when stdout is used\n");
1624 exit (1);
1625 }
1626
1627 if (input_files > max_input_files)
1628 {
1629 max_input_files = 2 * max_input_files;
1630 in_file_names = (char **) xrealloc (in_file_names,
1631 (max_input_files * sizeof (char *)));
1632 }
1633 }
1634
1635 in_file_names[input_files - 1] = argv[i];
1636 }
1637 }
1638 else
1639 {
1640 /* '-' as filename means stdin. */
1641 if (argv[i][0] == '-' && argv[i][1] == '\0')
1642 {
1643 if (input_files > 0)
1644 {
1645 fprintf (stderr, "indent: can't have filenames when specifying standard input\n");
1646 exit (1);
1647 }
1648
1649 using_stdin = true;
1650 }
1651 else
1652 i += set_option (argv[i], (i < argc ? argv[i + 1] : 0), 1);
1653 }
1654 }
1655
1656 if (verbose && profile_pathname)
1657 fprintf (stderr, "Read profile %s\n", profile_pathname);
1658
1659 if (input_files > 1)
1660 {
1661 /* When multiple input files are specified, make a backup copy
1662 and then output the indented code into the same filename. */
1663
1664 for (i = 0; input_files; i++, input_files--)
1665 {
1666 current_input = read_file (in_file_names[i]);
1667 in_name = out_name = in_file_names[i];
1668 output = fopen (out_name, "w");
1669 if (output == 0)
1670 {
1671 fprintf (stderr, "indent: can't create %s\n", out_name);
1672 exit (1);
1673 }
1674
1675 make_backup (current_input);
1676 reset_parser ();
1677 indent (current_input);
1678 if (fclose (output) != 0)
1679 sys_error (out_name);
1680 }
1681 }
1682 else
1683 {
1684 /* One input stream -- specified file, or stdin */
1685
1686 if (input_files == 0 || using_stdin)
1687 {
1688 input_files = 1;
1689 in_file_names[0] = "Standard input";
1690 current_input = read_stdin ();
1691 }
1692 else
1693 /* 1 input file */
1694 {
1695 current_input = read_file (in_file_names[0]);
1696 if (!out_name && !use_stdout)
1697 {
1698 out_name = in_file_names[0];
1699 make_backup (current_input);
1700 }
1701 }
1702 in_name = in_file_names[0];
1703
1704 /* Uset stdout if it was specified ("-st"), or neither input
1705 nor output file was specified, or we're doing troff. */
1706 if (use_stdout || !out_name || troff)
1707 output = stdout;
1708 else
1709 {
1710 output = fopen (out_name, "w");
1711 if (output == 0)
1712 {
1713 fprintf (stderr, "indent: can't create %s\n", out_name);
1714 exit (1);
1715 }
1716 }
1717
1718 reset_parser ();
1719 indent (current_input);
1720 }
1721
1722 exit (0);
1723 }
1724