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