67{
68 int dec_ind; /* current indentation for declarations */
69 int di_stack[20]; /* a stack of structure indentation levels */
70 int force_nl; /* when true, code must be broken */
71 int hd_type = 0; /* used to store type of stmt for if (...),
72 * for (...), etc */
73 int i;
/* local loop counter */
74 int scase; /* set to true when we see a case, so we will
75 * know what to do with the following colon */
76 int sp_sw; /* when true, we are in the expression of
77 * if(...), while(...), etc. */
78 int squest; /* when this is positive, we have seen a ?
79 * without the matching : in a <c>?<s>:<s>
80 * construct */
81 const char *t_ptr; /* used for copying tokens */
82 int tabs_to_var; /* true if using tabs to indent to var name */
83 int type_code; /* the type of token, returned by lexi */
84
85 int last_else = 0; /* true iff last keyword was an else */
86 const char *profile_name = NULL;
87 struct parser_state transient_state;
/* a copy for lookup */
88
89
90 /*-----------------------------------------------*\
91 | INITIALIZATION |
92 \*-----------------------------------------------*/
93
95
97 ps.
last_nl =
true;
/* this is true if the last thing scanned was
98 * a newline */
118 * comment buffers */
120 ps.
else_if = 1;
/* Default else-if special processing to on */
125
133 sp_sw = force_nl = false;
136 dec_ind = 0;
139
141 squest = 0;
145
147 tabs_to_var = 0;
148
149 /*--------------------------------------------------*\
150 | COMMAND LINE SCAN |
151 \*--------------------------------------------------*/
152
153#ifdef undef
164 * by an arg, we will set this equal to
165 * ps.decl_ind */
168 * by an arg, we will set this equal to
169 * ps.com_ind */
180#endif
181
182 for (
i = 1;
i < argc; ++
i)
183 if (strcmp(argv[
i],
"-npro") == 0)
184 break;
185 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'P' && argv[
i][2] !=
'0円')
186 profile_name = argv[
i];
/* non-empty -P (set profile) */
190
191 for (
i = 1;
i < argc; ++
i) {
192
193 /*
194 * look thru args (if any) for changes to defaults
195 */
196 if (argv[
i][0] !=
'-') {
/* no flag on parameter */
197 if (
input == NULL) {
/* we must have the input file */
198 in_name = argv[
i];
/* remember name of input file */
200 if (
input == NULL)
/* check for open error */
202 continue;
203 }
204 else if (
output == NULL) {
/* we have the output file */
205 out_name = argv[
i];
/* remember name of output file */
207 * the file */
208 errx(1,
"input and output files must be different");
209 }
211 if (
output == NULL)
/* check for create error */
213 continue;
214 }
215 errx(1,
"unknown parameter: %s", argv[
i]);
216 }
217 else
219 } /* end of for */
225 else {
228 }
229 }
230
232 ps.
com_ind = 2;
/* dont put normal comments before column 2 */
237 if (
ps.
decl_com_ind <= 0)
/* if not specified by user, set this */
241 fill_buffer();
/* get first batch of stuff into input buffer */
242
244 {
246 int col = 1;
247
248 while (1) {
249 if (*p == ' ')
250 col++;
251 else if (*p == '\t')
253 else
254 break;
255 p++;
256 }
259 }
260
261 /*
262 * START OF MAIN LOOP
263 */
264
265 while (1) { /* this is the main loop. it will go until we
266 * reach eof */
267 int comment_buffered = false;
268
269 type_code =
lexi(&
ps);
/* lexi reads one token. The actual
270 * characters read are stored in "token". lexi
271 * returns a code indicating the type of token */
272
273 /*
274 * The following code moves newlines and comments following an if (),
275 * while (), else, etc. up to the start of the following stmt to
276 * a buffer. This allows proper handling of both kinds of brace
277 * placement (-br, -bl) and cuddling "else" (-ce).
278 */
279
281 switch (type_code) {
287 }
289 /*
290 * We may have inherited a force_nl == true from the previous
291 * token (like a semicolon). But once we know that a newline
292 * has been scanned in this loop, force_nl should be false.
293 *
294 * However, the force_nl == true must be preserved if newline
295 * is never scanned in this loop, so this assignment cannot be
296 * done earlier.
297 */
298 force_nl = false;
300 break;
303 /*
304 * Copy everything from the start of the line, because
305 * pr_comment() will use that to calculate original
306 * indentation of a boxed comment.
307 */
312 }
313 comment_buffered = true;
314 *
sc_end++ =
'/';
/* copy in start of comment */
316 for (;;) { /* loop until we get to the end of the comment */
321 break; /* we are at end of comment */
323 * overflow */
324 diag2(1,
"Internal buffer overflow - Move big comment from right after if, while, or whatever");
326 exit(1);
327 }
328 }
329 *
sc_end++ =
'/';
/* add ending slash */
332 break;
334 /*
335 * Put KNF-style lbraces before the buffered up tokens and
336 * jump out of this loop in order to avoid copying the token
337 * again under the default case of the switch below.
338 */
341 /*
342 * Originally the lbrace may have been alone on its own
343 * line, but it will be moved into "the else's line", so
344 * if there was a newline resulting from the "{" before,
345 * it must be scanned now and ignored.
346 */
347 while (isspace((
unsigned char)*
buf_ptr)) {
351 break;
352 }
353 goto sw_buffer;
354 }
355 /* FALLTHROUGH */
356 default: /* it is the start of a normal statement */
357 {
358 int remove_newlines;
359
360 remove_newlines =
361 /* "} else" */
364 /* "else if" */
367 if (remove_newlines)
368 force_nl = false;
369 if (
sc_end == NULL) {
/* ignore buffering if
370 * comment wasn't saved up */
372 goto check_type;
373 }
376 }
378 (!comment_buffered && remove_newlines)) {
379 force_nl = !remove_newlines;
382 }
383 }
384 if (force_nl) { /* if we should insert a nl here, put
385 * it into the buffer */
386 force_nl = false;
387 --
line_no;
/* this will be re-increased when the
388 * newline is read from the buffer */
391 if (
verbose)
/* print error msg if the line was
392 * not already broken */
393 diag2(0,
"Line broken");
394 }
395 for (t_ptr =
token; *t_ptr; ++t_ptr)
397
398 sw_buffer:
400 * stmt */
404 * lexi will take tokens out of
405 * save_com */
406 *
sc_end++ =
' ';
/* add trailing blank, just in case */
409 break;
410 }
411 } /* end of switch */
412 /*
413 * We must make this check, just in case there was an unexpected
414 * EOF.
415 */
416 if (type_code != 0) {
417 /*
418 * The only intended purpose of calling lexi() below is to
419 * categorize the next token in order to decide whether to
420 * continue buffering forthcoming tokens. Once the buffering
421 * is over, lexi() will be called again elsewhere on all of
422 * the tokens - this time for normal processing.
423 *
424 * Calling it for this purpose is a bug, because lexi() also
425 * changes the parser state and discards leading whitespace,
426 * which is needed mostly for comment-related considerations.
427 *
428 * Work around the former problem by giving lexi() a copy of
429 * the current parser state and discard it if the call turned
430 * out to be just a look ahead.
431 *
432 * Work around the latter problem by copying all whitespace
433 * characters into the buffer so that the later lexi() call
434 * will read them.
435 */
440 errx(1,
"input too long");
441 }
442 }
445 }
446 }
447 transient_state =
ps;
448 type_code =
lexi(&transient_state);
/* read another token */
450 type_code !=
comment && !transient_state.search_brace) {
451 ps = transient_state;
452 }
453 }
454 } /* end of while (search_brace) */
455 last_else = 0;
456check_type:
457 if (type_code == 0) { /* we got eof */
459 ||
s_com !=
e_com)
/* must dump end of line */
461 if (
ps.
tos > 1)
/* check for balanced braces */
462 diag2(1,
"Stuff missing from end of file");
463
465 printf(
"There were %d output lines and %d comments\n",
467 printf(
"(Lines with comments)/(Lines with code): %6.3f\n",
469 }
472 }
473 if (
478 if (force_nl &&
481 /* we should force a broken line here */
483 diag2(0,
"Line broken");
485 ps.
want_blank =
false;
/* dont insert blank at line start */
486 force_nl = false;
487 }
488 ps.
in_stmt =
true;
/* turn on flag which causes an extra level of
489 * indentation. this is turned off by a ; or
490 * '}' */
491 if (
s_com !=
e_com) {
/* the turkey has embedded a comment
492 * in a line. fix it */
494
500 *
e_code =
'0円';
/* null terminate code sect */
503 }
504 }
505 else if (type_code !=
comment)
/* preserve force_nl thru a comment */
506 force_nl = false; /* cancel forced newline after newline, form
507 * feed, etc */
508
509
510
511 /*-----------------------------------------------------*\
512 | do switch on type of token scanned |
513 \*-----------------------------------------------------*/
515 * before the next CHECK_SIZE_CODE or
516 * dump_line() is 2. After that there's the
517 * final increment for the null character. */
518 switch (type_code) { /* now, decide what to do with the token */
519
520 case form_feed:
/* found a form feed in line */
521 ps.
use_ff =
true;
/* a form feed is treated much like a newline */
524 break;
525
531 }
532 ++
line_no;
/* keep track of input line number */
533 break;
534
535 case lparen:
/* got a '(' or '[' */
536 /* count parens to make Healy happy */
538 diag3(0,
"Reached internal limit of %d unclosed parens",
541 }
543 /* not a function pointer declaration or a function call */;
546 /* function pointer declarations */
549 }
552 /* offsetof (1) is never allowed a space; sizeof (2) gets
553 * one iff -bs; all other keywords (>2) always get a space
554 * before lparen */
564 /*
565 * this is a kluge to make sure that declarations will be
566 * aligned right if proc decl has an explicit type on it, i.e.
567 * "int a(x) {..."
568 */
570 ps.
in_or_st =
false;
/* turn off flag for structure decl or
571 * initialization */
572 }
573 /*
574 * parenthesized type following sizeof or offsetof is not a cast,
575 * and we assume the same for any other non-keyword identifier,
576 * to support macros that take types
577 */
581 break;
582
583 case rparen:
/* got a ')' or ']' */
588 } else
594 }
595 if (
e_code ==
s_code)
/* if the paren starts the line */
597
599
600 if (sp_sw && (
ps.
p_l_follow == 0)) {
/* check for end of if
601 * (...), or some such */
602 sp_sw = false;
603 force_nl = true;/* must force newline after if */
604 ps.
last_u_d =
true;
/* inform lexi that a following
605 * operator is unary */
606 ps.
in_stmt =
false;
/* dont use stmt continuation
607 * indentation */
608
609 parse(hd_type);
/* let parser worry about if, or whatever */
610 }
612 * such as main(){...} and int[]{...}
613 * have their braces put in the right
614 * place */
615 break;
616
617 case unary_op:
/* this could be any unary operation */
620 /* pointer declarations */
621
622 /*
623 * if this is a unary op in a declaration, we should indent
624 * this token
625 */
627 /* find length of token */;
630 }
633
634 {
636
640 }
642 break;
643
644 case binary_op:
/* any binary operation */
645 {
647
653 }
655 break;
656
657 case postop:
/* got a trailing ++ or -- */
661 break;
662
664 squest++; /* this will be used when a later colon
665 * appears so we can distinguish the
666 * <c>?<n>:<n> construct */
671 break;
672
673 case casestmt:
/* got word 'case' or 'default' */
674 scase = true; /* so we can process the later colon properly */
675 goto copy_id;
676
677 case colon:
/* got a ':' */
678 if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */
679 --squest;
684 break;
685 }
689 break;
690 }
691 ps.
in_stmt =
false;
/* seeing a label does not imply we are in a
692 * stmt */
693 /*
694 * turn everything so far into a label
695 */
696 {
698
705 }
706 force_nl =
ps.
pcase = scase;
/* ps.pcase will be used by
707 * dump_line to decide how to
708 * indent the label. force_nl
709 * will force a case n: to be
710 * on a line by itself */
711 scase = false;
713 break;
714
717 ps.
in_or_st =
false;
/* we are not in an initialization or
718 * structure declaration */
719 scase = false; /* these will only need resetting in an error */
720 squest = 0;
728
731 /* indent stray semicolons in declarations */
734 }
735
737 * structure declaration, we
738 * arent any more */
739
741
742 /*
743 * This should be true iff there were unbalanced parens in the
744 * stmt. It is a bit complicated, because the semicolon might
745 * be in a for stmt
746 */
747 diag2(1,
"Unbalanced parens");
749 if (sp_sw) { /* this is a check for an if, while, etc. with
750 * unbalanced parens */
751 sp_sw = false;
752 parse(hd_type);
/* dont lose the if, or whatever */
753 }
754 }
758 * middle of a stmt */
759
760 if (!sp_sw) { /* if not if for (;;) */
762 force_nl = true;/* force newline after an end of stmt */
763 }
764 break;
765
766 case lbrace:
/* got a '{' */
767 ps.
in_stmt =
false;
/* dont indent the {} */
769 force_nl = true;/* force other stuff on same line as '{' onto
770 * new line */
773 else
775
780 }
784 * brace ... */
787 } else /* add a space between the decl and brace */
789 }
790 }
793
794 if (
ps.
p_l_follow > 0) {
/* check for preceding unbalanced
795 * parens */
796 diag2(1,
"Unbalanced parens");
798 if (sp_sw) { /* check for unclosed if, for, etc. */
799 sp_sw = false;
802 }
803 }
805 ps.
ind_stmt =
false;
/* dont put extra indentation on line
806 * with '{' */
808 * declaration or an init */
811 diag3(0,
"Reached internal limit of %d struct levels",
814 }
815 /* ? dec_ind = 0; */
816 }
817 else {
819 * a declaration, so don't do
820 * special indentation of
821 * comments */
827 }
828 dec_ind = 0;
830 if (
ps.
want_blank)
/* put a blank before '{' if '{' is not at
831 * start of line */
836 break;
837
838 case rbrace:
/* got a '}' */
840 * omitted in
841 * declarations */
843 if (
ps.
p_l_follow) {
/* check for unclosed if, for, else. */
844 diag2(1,
"Unbalanced parens");
846 sp_sw = false;
847 }
851 * line */
853 diag2(0,
"Line broken");
855 }
859 if (
ps.
dec_nest > 0) {
/* we are in multi-level structure
860 * declaration */
865 }
872 break;
873
874 case swstmt:
/* got keyword "switch" */
875 sp_sw = true;
876 hd_type =
swstmt;
/* keep this for when we have seen the
877 * expression */
878 goto copy_id; /* go move the token into buffer */
879
880 case sp_paren:
/* token is if, while, for */
881 sp_sw = true; /* the interesting stuff is done after the
882 * expression is scanned */
885
886 /*
887 * remember the type of header for later use by parser
888 */
889 goto copy_id; /* copy the token into line */
890
896 diag2(0,
"Line broken");
897 dump_line();
/* make sure this starts a line */
899 }
900 force_nl = true;/* also, following stuff must go onto new line */
901 last_else = 1;
903 }
904 else {
905 if (
e_code !=
s_code) {
/* make sure this starts a line */
907 diag2(0,
"Line broken");
910 }
911 force_nl = true;/* also, following stuff must go onto new line */
912 last_else = 0;
914 }
915 goto copy_id; /* move the token into line */
916
920 goto copy_id;
921
924 goto copy_id;
925 /* FALLTHROUGH */
926 case decl:
/* we have a declaration type (int, etc.) */
927 parse(
decl);
/* let parser worry about indentation */
932 }
933 }
937 }
938 ps.
in_or_st =
true;
/* this might be a structure or initialization
939 * declaration */
944 for (
i = 0;
token[
i++];);
/* get length of token */
945
947 /* global variable or struct member in local variable */
950 } else {
951 /* local variable */
954 }
955 goto copy_id;
956
958 case ident:
/* got an identifier or constant */
965 }
968 }
970 }
973 * must indent identifier */
977 }
978 }
980 sp_sw = false;
981 force_nl = true;
985 }
986 copy_id:
987 {
989
995 }
998 break;
999
1001 {
1003
1009 }
1011 break;
1012
1013 case period:
/* treat a period kind of like a binary
1014 * operation */
1015 *
e_code++ =
'.';
/* move the period into line */
1016 ps.
want_blank =
false;
/* dont put a blank after a period */
1017 break;
1018
1021 * if comma does not start the
1022 * line */
1025 /* indent leading commas and not the actual identifiers */
1028 }
1036 force_nl = true;
1037 }
1038 break;
1039
1040 case preesc:
/* got the character '#' */
1046 *
e_lab++ =
'#';
/* move whole line to 'label' buffer */
1047 {
1048 int in_comment = 0;
1049 int com_start = 0;
1050 char quote = 0;
1051 int com_end = 0;
1052
1057 }
1065 if (!in_comment) {
1069 }
1070 break;
1071 case '/':
1072 if (*
buf_ptr ==
'*' && !in_comment && !quote) {
1073 in_comment = 1;
1076 }
1077 break;
1078 case '"':
1079 if (quote == '"')
1080 quote = 0;
1081 break;
1082 case '\'':
1083 if (quote == '\'')
1084 quote = 0;
1085 break;
1086 case '*':
1087 if (*
buf_ptr ==
'/' && in_comment) {
1088 in_comment = 0;
1091 }
1092 break;
1093 }
1094 }
1095
1099 /* comment on preprocessor line */
1100 if (
sc_end == NULL) {
/* if this is the first comment,
1101 * we must set up the buffer */
1104 }
1105 else {
1106 *
sc_end++ =
'\n';
/* add newline between
1107 * comments */
1110 }
1112 errx(1,
"input too long");
1113 memmove(
sc_end,
s_lab + com_start, com_end - com_start);
1114 sc_end += com_end - com_start;
1121 * lexi will take tokens out of
1122 * save_com */
1123 *
sc_end++ =
' ';
/* add trailing blank, just in case */
1126 }
1128 *
e_lab =
'0円';
/* null terminate line */
1130 }
1131
1132 if (strncmp(
s_lab,
"#if", 3) == 0) {
/* also ifdef, ifndef */
1136 }
1137 else
1138 diag2(1,
"#if stack overflow");
1139 }
1140 else if (strncmp(
s_lab,
"#el", 3) == 0) {
/* else, elif */
1142 diag2(1,
s_lab[3] ==
'i' ?
"Unmatched #elif" :
"Unmatched #else");
1143 else {
1146 }
1147 }
1148 else if (strncmp(
s_lab,
"#endif", 6) == 0) {
1150 diag2(1,
"Unmatched #endif");
1151 else
1153 } else {
1154 struct directives {
1155 int size;
1157 }
1158 recognized[] = {
1159 {7, "include"},
1160 {6, "define"},
1161 {5, "undef"},
1162 {4, "line"},
1163 {5, "error"},
1164 {6, "pragma"}
1165 };
1166 int d =
nitems(recognized);
1167 while (--d >= 0)
1168 if (strncmp(
s_lab + 1, recognized[d].
string, recognized[d].size) == 0)
1169 break;
1170 if (d < 0) {
1171 diag2(1,
"Unrecognized cpp directive");
1172 break;
1173 }
1174 }
1178 }
1179 else {
1182 }
1183 break; /* subsequent processing of the newline
1184 * character will cause the line to be printed */
1185
1186 case comment:
/* we have gotten a / followed by * this is a biggie */
1188 break;
1189 } /* end of big switch stmt */
1190
1191 *
e_code =
'0円';
/* make sure code section is null terminated */
1194 } /* end of main while (1) loop */
1195}
void set_profile(const char *profile_name)
void errx(int eval, const char *fmt,...)
static void bakcopy(void)
static void indent_declaration(int cur_dec_ind, int tabs_to_var)
int compute_code_target(void)
int lexi(struct parser_state *)
void diag2(int, const char *)
void diag3(int, const char *, int)
int count_spaces_until(int, char *, char *)
void alloc_typenames(void)
int block_comment_max_col
int blanklines_after_procs
int postfix_blankline_requested
struct parser_state state_stack[5]
int prefix_blankline_requested
int extra_expression_indent
int format_block_comments
int comment_delimiter_on_blankline
#define CHECK_SIZE_LAB(desired_size)
struct parser_state match_state[5]
int blanklines_around_conditional_compilation
int swallow_optional_blanklines
int lineup_to_parens_always
int blanklines_after_declarations_at_proctop
if(TABLE==NULL||TABLE_index==NULL)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
int in_parameter_declaration