From 1009bf5ef4bc6572488c3f1fd3bbf0a2037596e4 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Wed, 28 Aug 1985 20:52:06 -0800 Subject: [PATCH] kernel normal form (from sun!shannon) SCCS-vsn: usr.bin/indent/indent.c 5.2 SCCS-vsn: usr.bin/indent/indent_codes.h 5.2 SCCS-vsn: usr.bin/indent/indent_globs.h 5.2 SCCS-vsn: usr.bin/indent/io.c 5.2 SCCS-vsn: usr.bin/indent/lexi.c 5.2 SCCS-vsn: usr.bin/indent/parse.c 5.2 SCCS-vsn: usr.bin/indent/pr_comment.c 5.2 SCCS-vsn: usr.bin/indent/Makefile 5.2 SCCS-vsn: usr.bin/indent/indent.1 6.2 --- usr/src/usr.bin/indent/Makefile | 20 +- usr/src/usr.bin/indent/indent.1 | 554 ++++--- usr/src/usr.bin/indent/indent.c | 1971 +++++++++++++------------ usr/src/usr.bin/indent/indent_codes.h | 2 +- usr/src/usr.bin/indent/indent_globs.h | 250 ++-- usr/src/usr.bin/indent/io.c | 945 ++++++------ usr/src/usr.bin/indent/lexi.c | 632 ++++---- usr/src/usr.bin/indent/parse.c | 543 +++---- usr/src/usr.bin/indent/pr_comment.c | 575 ++++---- 9 files changed, 2898 insertions(+), 2594 deletions(-) diff --git a/usr/src/usr.bin/indent/Makefile b/usr/src/usr.bin/indent/Makefile index 38b7163e10..13e82b4350 100644 --- a/usr/src/usr.bin/indent/Makefile +++ b/usr/src/usr.bin/indent/Makefile @@ -3,17 +3,27 @@ # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # -# @(#)Makefile 5.1 (Berkeley) %G% +# @(#)Makefile 5.2 (Berkeley) %G% # DESTDIR= -CFLAGS= -O +CFLAGS= -g OBJS= indent.o io.o lexi.o parse.o pr_comment.o indent: indent.o io.o lexi.o parse.o pr_comment.o - cc -o indent ${OBJS} + cc ${CFLAGS} -o indent ${OBJS} clean: rm -f ${OBJS} indent -install: - install -s indent ${DESTDIR}/usr/ucb/indent +indent.o: indent.c +io.o: io.c +lexi.o: lexi.c +parse.o: parse.c +pr_comment.o: pr_comment.c +$(OBJS): indent_globs.h indent_codes.h + +.DEFAULT: + sccs get $< + +install: indent + install -s indent ${DESTDIR}/usr/bin/indent diff --git a/usr/src/usr.bin/indent/indent.1 b/usr/src/usr.bin/indent/indent.1 index 40973a5193..be98676759 100644 --- a/usr/src/usr.bin/indent/indent.1 +++ b/usr/src/usr.bin/indent/indent.1 @@ -2,250 +2,402 @@ .\" All rights reserved. The Berkeley software License Agreement .\" specifies the terms and conditions for redistribution. .\" -.\" @(#)indent.1 6.1 (Berkeley) %G% +.\" @(#)indent.1 6.2 (Berkeley) %G% .\" .TH INDENT 1 "" .UC 5 .SH NAME indent \- indent and format C program source .SH SYNOPSIS -.B indent -.I input -[ -.I output -] [ -.I flags -] +.in +\w'\fBindent \fR'u +.ti -\w'\fBindent \fR'u +\fBindent \fR [ \fIinput-file\fR [ \fIoutput-file\fR ] ] +[\ \fB\-bad\fR\ |\ \fB\-nbad\fR\ ] +[\ \fB\-bap\fR\ |\ \fB\-nbap\fR\ ] +[\ \fB\-bbb\fR\ |\ \fB\-nbbb\fR\ ] +[\ \fB\-bc\fR\ |\ \fB\-nbc\fR\ ] +[\ \fB\-bl\fR\ ] +[\ \fB\-br\fR\ ] +[\ \fB\-c\fIn\fR\ ] +[\ \fB\-cd\fIn\fR\ ] +[\ \fB\-cdb\fR\ |\ \fB\-ncdb\fR\ ] +[\ \fB\-ce\fR\ |\ \fB\-nce\fR\ ] +[\ \fB\-ci\fIn\fR\ ] +[\ \fB\-cli\fIn\fR\ ] +[\ \fB\-d\fIn\fR\ ] +[\ \fB\-di\fIn\fR\ ] +[\ \fB\-fc1\fR\ |\ \fB\-nfc1\fR\ ] +[\ \fB\-i\fIn\fR\ ] +[\ \fB\-ip\fR\ |\ \fB\-nip\fR\ ] +[\ \fB\-l\fIn\fR\ ] +[\ \fB\-lc\fIn\fR\ ] +[\ \fB\-lp\fR\ |\ \fB\-nlp\fR\ ] +[\ \fB\-pcs\fR\ |\ \fB\-npcs\fR\ ] +[\ \fB\-npro\fR\ ] +[\ \fB\-psl\fR\ |\ \fB\-npsl\fR\ ] +[\ \fB\-sc\fR\ |\ \fB\-nsc\fR\ ] +[\ \fB\-sob\fR\ |\ \fB\-nsob\fR\ ] +[\ \fB\-st\fR\ ] +[\ \fB\-troff\fR\ ] +[\ \fB\-v\fR\ |\ \fB\-nv\fR\ ] .SH DESCRIPTION +.IX indent "" "\fLindent\fP \(em format C source" +.IX "programming tools" "indent" "" "\fLindent\fP \(em format C source" +.IX "languages" "indent" "" "\fLindent\fP \(em format C source" +.IX "C programming language" "indent" "" "\fLindent\fP \(em format C source" +.IX "pretty printer" "indent" "" "\fLindent\fP \(em format C source" +.IX "format C programs" "" "format C programs \(em \fLindent\fP" +.IX "code formatter" "indent" "" "\fLindent\fP \(em format C source" +.IX "cb" "indent" "\fLcb\fP" "try \fLindent\fP \(em format C source" .I Indent -is intended primarily as a C program formatter. -Specifically, -.I indent -will: -.IP \(bu -indent code lines -.IP \(bu -align comments -.IP \(bu -insert spaces around operators where necessary -.IP \(bu -break up declaration lists as in ``int a,b,c;''. -.PP -.I Indent -will not break up long statements to make them fit within the -maximum line length, but it will flag lines that are too long. Lines -will be broken so that each statement starts a new line, and braces -will appear alone on a line. (See the \-br option to inhibit this.) -Also, an attempt is made to line up identifiers in declarations. -.PP -The -.I flags -which can be specified follow. They -may appear before or after the file names. -If the -.I output -file is omitted, the formatted file will be written -back into -.I input -and a ``backup'' copy of -.I input -will be written in the current directory. -If -.I input -is named ``/blah/blah/file'', -the backup file will be -named ``.Bfile''. +is a \fBC\fR program formatter. It reformats the \fBC\fR program in the +\fIinput-file\fR according to the switches. The switches which can be +specified are described below. They may appear before or after the file +names. +.LP +\fBNOTE\fP: If you only specify an \fIinput-file\fR, the formatting is +done `in-place', that is, the formatted file is written back into +.I input-file +and a backup copy of +.I input-file +is written in the current directory. If +.I input-file +is named `/blah/blah/file', the backup file is named +.RI file .BAK. +.LP If -.I output +.I output-file is specified, .I indent checks to make sure it is different from -.IR input . -.PP -The following flags may be used to control the formatting -style imposed by +.IR input-file . +.SH OPTIONS +.LP +The options listed below control the formatting style imposed by .IR indent . -.TP 10 -.BI \-l nnn -Maximum length of an output line. The default is 75. -.TP 10 -.BI \-c nnn -The column in which comments will start. The default is 33. -.TP 10 -.BI \-cd nnn -The column in which comments on declarations will start. The default -is for these comments to start in the same column as other comments. -.TP 10 -.BI \-i nnn -The number of spaces for one indentation level. The default is 4. -.TP 10 -.BR \-dj , \-ndj -.B \-dj -will cause declarations to be left justified. -.B \-ndj -will cause -them to be indented the same as code. The default is -.BR \-ndj . -.TP 10 -.BR \-v , \-nv -.B \-v turns on ``verbose'' mode, -.B \-nv -turns it off. When in verbose mode, -.I indent -will report when it -splits one line of input into two or more lines of output, -and it will give some size statistics at completion. -The default is -.BR \-nv . -.TP 10 +.TP 15 +.BR \-bap , \-nbap +If +.B \-bap +is specified, a blank line is forced after every procedure body. Default: +.B \-nbap. +.TP 15 +.BR \-bad , \-nbad +If +.B \-bad +is specified, a blank line is forced after every block of +declarations. Default: +.B \-nbad. +.TP 15 +.BR \-bbb , \-nbbb +If +.B \-bbb +is specified, a blank line is forced before every block comment. Default: +.B \-nbbb. +.TP 15 .BR \-bc , \-nbc If .B \-bc -is specified, then a newline will be forced after each -comma in a declaration. +is specified, then a newline is forced after each comma in a declaration. .B \-nbc -will turn off this option. The default is +turns off this option. The default is .BR \-bc . -.TP 10 -.BI \-d nnn -This option controls the placement of comments -which are not to the right of code. -Specifying -.B \-d2 -means that such comments will be placed two -indentation levels to the left of code. -The default -.B \-d0 -lines up these comments with the code. -See the section on comment indentation below. -.TP 10 +.TP 15 .BR \-br , \-bl Specifying .B \-bl -will cause -complex statements to be lined up like this: +lines up compound statements like this: .ne 4 .nf +.ft L if (...) { code } +.ft R .fi Specifying .B \-br -(the default) will make them look like this: +(the default) makes them look like this: .ne 3 .nf +.ft L if (...) { code } +.ft R .fi -.PP -You may set up your own ``profile'' of defaults to -.I indent -by creating the file ``.indent.pro'' in your login directory -and including whatever switches you like. -If -.I indent -is run and a profile file exists, then it is read -to set up the program's defaults. -Switches on the command line, though, -will always override profile switches. -The profile -file must be a single line of not more than 127 characters. -The switches should be separated on the line by spaces or tabs. -.PP -.B Multi-line expressions -.PP -.I Indent -will not break up complicated expressions that extend over multiple -lines, but it will usually correctly indent such expressions which have -already been broken up. Such an expression might end up looking like this: -.ne 10 -.in +4 +.LP +.TP 15 +.BI \-c n +The column in which comments on code start. The default is 33. +.TP 15 +.BI \-cd n +The column in which comments on declarations start. The default +is for these comments to start in the same column as those on code. +.TP 15 +.BI \-cdb , \-ncdb +Enables (disables) the placement of comment delimiters on blank lines. With +this option enabled, comments look like this: .nf -x = - ( - (Arbitrary parenthesized expression) - + - ( - (Parenthesized expression) - * - (Parenthesized expression) - ) - ); - +.ft L +.ne 3 + /* + * this is a comment + */ +.ft R +.fi +Rather than like this: +.nf +.ft L + /* this is a comment */ +.ft R +.fi +This only affects block comments, not comments to the right of code. The default is +.B \-cdb . +.TP 15 +.BI \-ce , \-nce +Enables (disables) forcing `else's to cuddle up to the immediatly preceeding +`}'. The default is +.B \-ce . +.TP 15 +.BI \-ci n +Sets the continuation indent to be \fIn\fR. Continuation +lines will be indented that far from the beginning of the first line of the +statement. Parenthesized expressions have extra indentation added to +indicate the nesting, unless \fB\-lp\fR is in effect. +\fB\-ci\fR defaults to the same value as \fB\-i\fR. +.TP 15 +.BI \-cli n +Causes case labels to be indented +.I n +tab stops to the right of the containing \fBswitch\fR statement. +\fB-cli0.5\fR causes case labels to be indented half a tab stop. The +default is +.B \-cli0 . +.TP 15 +.BI \-d n +Controls the placement of comments which are not to the +right of code. The default +.B \-d1 +means that such comments are placed one indentation level to the +left of code. Specifying +.B \-d0 +lines up these comments with the code. See the section on comment +indentation below. +.TP 15 +.BI \-di n +Specifies the indentation, in character positions, from a declaration keyword +to the following identifier. The default is +.B \-di16 . +.if 0 \{.TP 15 +.BR \-dj , \-ndj +.B \-dj +left justifies declarations. +.B \-ndj +indents declarations the same as code. The default is +.BR \-ndj . +.TP 15 +.BI \-ei , \-nei +Enables (disables) special +.B else-if +processing. If it's enabled, +.BR if "s" +following +.BR else "s" +will have the same indendation as the preceeding +.B if +statement.\} +.TP 15 +.BI \-fc1 , \-nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. In such cases, \fB\-nfc1\fR should be +used. The default is \fB\-fc1\fR. +.TP 15 +.BI \-i n +The number of spaces for one indentation level. The default is 4. +.TP 15 +.BI \-ip , \-nip +Enables (disables) the indentation of parameter declarations from the left +margin. The default is +.B \-ip . +.TP 15 +.BI \-l n +Maximum length of an output line. The default is 75. +.TP 15 +.B \-npro +Causes the profile files, `./.indent.pro' and `~/.indent.pro', to be ignored. +.TP 15 +.BI \-lp , \-nlp +Lines up code surrounded by parenthesis in continuation lines. If a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. For example, here is how a piece of continued code looks with -nlp +in effect: +.ne 2 +.nf +.ft L + p1 = first_procedure(second_procedure(p2, p3), + third_procedure(p4, p5)); +.ft R .fi -.PP +.ne 5 +With \fB-lp\fR in effect (the default) the code looks somewhat clearer: +.nf +.ft L + p1 = first_procedure(second_procedure(p2, p3), + third_procedure(p4, p5)); +.ft R +.fi +.ne 5 +Inserting a couple more newlines we get: +.nf +.ft L + p1 = first_procedure(second_procedure(p2, + p3), + third_procedure(p4, + p5)); +.ft R +.fi +.TP 15 +.B \-pcs , \-npcs +If true (\fB-pcs\fR) all procedure calls will have a space inserted between +the name and the '('. The default is +.B \-npcs +.TP 15 +.B \-psl , \-npsl +If true (\fB-psl\fR) the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. The +default is +.B -psl +.TP 15 +.BI \-sc , \-nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +.TP 15 +.BR \-sob , \-nsob +If +.B \-sob +is specified, indent will swallow optional blank lines. You can use this to +get rid of blank lines after declarations. Default: +.B \-nsob +.TP 15 +.B \-st +Causes +.B indent +to take its input from stdin, and put its output to stdout. +.TP 15 +.BI \-T typename +Adds +.I typename +to the list of type keywords. Names accumulate: +.B \-T +can be specified more than once. You need to specify all the typenames that +appear in your program that are defined by \fBtypedef\fRs \- nothing will be +harmed if you miss a few, but the program won't be formatted as nicely as +it should. This sounds like a painful thing to have to do, but it's really +a symptom of a problem in C: \fBtypedef\fR causes a syntactic change in the +laguage and \fIindent\fR can't find all \fBtypedef\fRs. +.TP 15 +.B \-troff +Causes +.B indent +to format the program for processing by troff. It will produce a fancy +listing in much the same spirit as +.BR vgrind. +If the output file is not specified, the default is standard output, +rather than formatting in place. +.TP 15 +.BR \-v , \-nv +.B \-v +turns on `verbose' mode, +.B \-nv +turns it off. When in verbose mode, +.I indent +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. The default is +.BR \-nv . +.SH "FURTHER DESCRIPTION" +.LP +You may set up your own `profile' of defaults to +.I indent +by creating a file called +.BI . indent . pro +in either your login directory or the current directory and including +whatever switches you like. A `.indent.pro' in the current directory takes +precedence over the one in your login directory. If +.I indent +is run and a profile file exists, then it is read to set up the program's +defaults. Switches on the command line, though, always override profile +switches. The switches should be separated by spaces, tabs or newlines. +.LP .B Comments -.PP +.LP +.IR "`Box' comments" . .I Indent -recognizes four kinds of comments. -They are: straight text, ``box'' comments, -UNIX-style comments, -and comments that should be passed through unchanged. -The action taken with these -various types are as follows: -.PP -.I ``Box'' comments.\ \ +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.LP +.IR "Straight text" . +All other comments are treated as straight text. .I Indent -assumes that any comment with a dash -immediately after the start of comment (i.e. ``/*\-'') -is a comment surrounded by a box of stars. Each line -of such a comment will be left unchanged, -except that the first non-blank -character of each successive line will be lined up with the beginning -slash of the first line. Box comments will be indented (see below). -.PP -.I ``Unix-style'' comments.\ \ -This is the type of section header which is used -extensively in the UNIX system source. If the start -of comment (``/*'') appears on a -line by itself, indent assumes that it is a -UNIX-style comment. These will be -treated similarly to box comments, except -the first non-blank character on each -line will be lined up with the `*' of the ``/*''. -.PP -.I Unchanged comments.\ \ -Any comment which starts in column 1 will be left completely -unchanged. This is intended primarily for documentation header pages. -The check for unchanged comments is made before -the check for UNIX-style comments. -.PP -.I Straight text.\ \ -All other comments are treated as straight text. -.I Indent -will fit -as many words (separated by blanks, tabs, or newlines) on a line as possible. -Straight text comments will be indented. -.PP +fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. Blank lines break paragraphs. +.LP .B Comment indentation -.PP -Box, UNIX-style, and straight text comments may be indented. -If a comment is on a line -with code it will be started in the ``comment -column'', which is set by the -.B \-cnnn -command line parameter. -Otherwise, the -comment will be started at -.I nnn -indentation levels less than where code is -currently being placed, where -.I nnn +.LP +If a comment is on a line with code it is started in the `comment column', +which is set by the +.BI \-c n +command line parameter. Otherwise, the comment is started at +.I n +indentation levels less than where code is currently being placed, where +.I n is specified by the -.B \-dnnn -command line parameter. (Indented -comments will never be placed in column 1.) -If the code on a line extends past the comment column, -the comment will be moved to the next line. -.SH DIAGNOSTICS -Diagnostic error messages, mostly to -tell that a text line has been broken -or is too long for the output line. +.BI \-d n +command line parameter. If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.LP +.B Preprocessor lines +.LP +In general, \fIindent\fR leaves preprocessor lines alone. The only +reformmatting that it will do is to straighten up trailing comments. It +leaves imbedded comments alone. Conditional compilation +(\fB#ifdef...#endif\fR) is recognized and \fIindent\fR attempts to correctly +compensate for the syntactic peculiarites introduced. +.LP +.B C syntax +.LP +\fIIndent\fR understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. It attempts to cope with the usual sorts of +incomplete and misformed syntax. In particular, the use of macros like: +.nf +.ft L + #define forever for(;;) +.ft R +.fi +is handled properly. .SH FILES .DT -\&.indent.pro profile file +.br +\&./.indent.pro profile file +.br +~/.indent.pro profile file .SH BUGS -Does not know how to format ``long'' declarations. +.I Indent +has even more switches than \fIls\fR. + +.ne 5 +A common mistake that often causes grief is typing: +.nf +.ft L + indent *.c +.ft R +.fi +to the shell in an attempt to indent all the \fBC\fR programs in a directory. +This is probably a bug, not a feature. diff --git a/usr/src/usr.bin/indent/indent.c b/usr/src/usr.bin/indent/indent.c index e0ce3e74c6..681eee3108 100644 --- a/usr/src/usr.bin/indent/indent.c +++ b/usr/src/usr.bin/indent/indent.c @@ -11,1163 +11,1286 @@ char copyright[] = #endif not lint #ifndef lint -static char sccsid[] = "@(#)indent.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)indent.c 5.2 (Berkeley) %G%"; #endif not lint -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - +/*- + + Copyright (C) 1976 + by the + Board of Trustees + of the + University of Illinois + + All rights reserved + + NAME: - indent main program - +indent main program + FUNCTION: - This is the main program of the indent program. Indent will take a C - program source and reformat it into a semi-reasonable form. - +This is the main program of the indent program. Indent will take a C +program source and reformat it into a semi-reasonable form. + ALGORITHM: - The routine lexi scans tokens and passes them back one at a time to the - main routine. The subroutine parse takes care of much of the work of - figuring indentation level. - - 1) Call lexi - 2) Enter a monster switch statement on the code returned by lexi. If - the indentation level for the line yet to be printed should be - changed, set the variable ind_level. If the indentation level for - the following line should be changed, set the variable i_l_follow. - -PARAMETERS: - None - -RETURNS: - Nothing - -GLOBALS: - be_save = - break_comma - bp_save = - btype_2 = - code_lines - com_ind = - com_lines - dec_nest = - decl_com_ind = - decl_on_line = - i_l_follow = - in_decl = - ind_level = - ind_size = - ind_stmt = - last_u_d = - leave_comma = - line_no = - ljust_decl = - max_col = - out_coms - out_lines - p_l_follow = - paren_level = - pcase = - sc_end = - unindent_displace = - use_ff = - verbose = - -CALLS: - atoi (lib) - cmp - creat (lib) - dump_line - eqin - fill_buffer - lexi - open (lib) - parse - pr_comment - printf (lib) - seek (lib) - time (lib) - -CALLED BY: - No one (main routine) - -HISTORY: - November 1976 D A Willcox of CAC Initial coding - 12/9/76 D A Willcox of CAC Fixed defaults for decl_com_ind - to be 8 less than com_ind if - left justifying declarations - 12/9/76 D A Willcox of CAC Fixed processing of nested - ?: constructs - 1/7/77 D A Willcox of CAC Added check for overwrite of - input file - Added code to handle -br and -bl - parameters - */ +The routine lexi scans tokens and passes them back one at a time to the +main routine. The subroutine parse takes care of much of the work of +figuring indentation level. + +1) Call lexi +2) Enter a monster switch statement on the code returned by lexi. If +the indentation level for the line yet to be printed should be +changed, set the variable ps.ind_level. If the indentation level for +the following line should be changed, set the variable ps.i_l_follow. + +*/ #include "indent_globs.h"; #include "indent_codes.h"; -/* #define dolog 1 /* if this define is removed, then the code to - produce a log file will be removed */ - -struct templ { /* this is a template for the list of - command line args */ - char *str; /* pointer to string which is a valid - command line arg */ - int code; /* code to be used in switch for processing - this arg */ -}; - - -struct templ options[] = -{ /* warning - because of the way that this - table is scanned, if one entry is an - initial substring of another, then the - longer entry should occur first */ - "-cd", 4, - "-c", 2, - "-l", 1, - "-i", 3, - "-v", 5, - "-nv", 6, - "-dj", 7, - "-d", 13, /* unindented comment placement */ - "-ndj", 8, - "-bc", 10, /* break after command in decl */ - "-nbc", 9, /* don't break after comma */ - "-br", 14, /* put brace on right of stmt */ - "-bl", 15, /* put brace on left by itself */ - "-st", 16, /* use the standard input and output - files */ - 0, 0 -}; - +char *in_name = "Standard Input"; /* will always point to name of + * input file */ +char *out_name = "Standard Output"; /* will always point to + * name of output file */ +char bakfile[32] = ""; -char *in_name = "Standard Input"; - /* will always point to name of input file - */ -char *out_name = "Standard Output"; - /* will always point to name of output file - */ -char bakfile[32] = ""; - -main (argc, argv) -int argc; -char **argv; +main(argc, argv) + int argc; + char **argv; { - int dec_ind; /* current indentation for declarations */ - int di_stack[20]; /* a stack of structure indentation levels - */ - int flushed_nl; /* used when buffering up comments to - remember that a newline was passed over - */ - int force_nl; /* when true, code must be broken */ - int hd_type; /* used to store type of stmt for if (...), - for (...), etc */ - register int i; /* local loop counter */ - int in_or_st; /* Will be true iff there has been a - declarator (e.g. int or char) and no - left paren since the last semicolon. - When true, a { is starting a structure - definition or an initialization list */ - register int j; /* local loop counter */ - int scase; /* set to true when we see a case, so we - will know what to do with the following - colon */ - int sp_sw; /* when true, we are in the expressin of - if(...), while(...), etc. */ - int squest; /* when this is positive, we have seen a ? - without the matching : in a ?: - construct */ - register char *t_ptr; /* used for copying tokens */ - int type_code; /* the type of token, returned by lexi */ - int want_blank; /* set to true when the following token - should be prefixed by a blank. (Said - prefixing is ignored in some cases.) */ - -#ifdef dolog /* include declarations needed for log */ - int log_fid; /* fid of log file */ - - struct logtmpl { /* structure of a log entry */ - int tvec[2]; /* time of execution */ - char inp; /* input fid */ - char outp; /* output fid */ - int nout; /* # output lines */ - int ncom; /* # comments */ - int wcom; /* # lines w/ comments */ - int wcode; /* # lines w/code */ - char mc; /* max line size */ - char ci; /* comment indentation */ - char inds; /* indent size */ - char dci; /* decl comment indentation */ - char verb; /* verbose */ - char ljus; /* left just */ - char lvcom; /* leave commas */ - char unin; /* unindented comment indentation */ - char uid; /* the user id */ - char bropt; /* btype_2 */ - int reserved[2]; - }; - - struct logtmpl logent; -#endif - -/*-----------------------------------------------*\ -| INITIALIZATION + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int flushed_nl; /* used when buffering up comments to + * remember that a newline was passed over */ + int force_nl; /* when true, code must be broken */ + int hd_type; /* used to store type of stmt for if + * (...), for (...), etc */ + register int i; /* local loop counter */ + register int j; /* local loop counter */ + int scase; /* set to true when we see a case, so we + * will know what to do with the following + * colon */ + int sp_sw; /* when true, we are in the expressin of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a ?: + * construct */ + register char *t_ptr; /* used for copying tokens */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + + + /*-----------------------------------------------*\ +| INITIALIZATION | \*-----------------------------------------------*/ - combuf[0] = codebuf[0] = labbuf[0] = ' '; - /* set up code, label, and comment buffers */ + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned + * was a newline */ + ps.last_token = semicolon; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to + * on */ s_lab = e_lab = labbuf + 1; s_code = e_code = codebuf + 1; s_com = e_com = combuf + 1; buf_ptr = buf_end = in_buffer; line_no = 1; - had_eof = in_decl = decl_on_line = break_comma = false; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; sp_sw = force_nl = false; - in_or_st = false; - bl_line = true; + ps.in_or_st = false; + ps.bl_line = true; dec_ind = 0; - di_stack[dec_nest = 0] = 0; - want_blank = in_stmt = ind_stmt = false; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; - scase = pcase = false; + scase = ps.pcase = false; squest = 0; sc_end = 0; bp_save = 0; be_save = 0; - input = -1; - output = -1; - ljust_decl = d_ljust; + output = 0; -/*--------------------------------------------------*\ + /*--------------------------------------------------*\ | COMMAND LINE SCAN -\*--------------------------------------------------*/ - - max_col = d_max_col; /* set up some default values */ - com_ind = d_com_ind; - ind_size = d_ind_size; - verbose = d_verbose; - decl_com_ind = 0; /* if this is not set to some positive - value by an arg, we will set this equal - to com_ind */ - btype_2 = d_btype_2; - unindent_displace = d_unindent; - leave_comma = d_leave_comma; - - set_profile (); +\*-------------------------------------------------- +*/ + + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive + * value by an arg, we will set this equal + * to ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + if (i >= argc) + set_profile(); for (i = 1; i < argc; ++i) { - /* look thru args (if any) for changes to defaults */ + + /* + * look thru args (if any) for changes to defaults + */ if (argv[i][0] != '-') {/* no flag on parameter */ - if (input < 0) { /* we must have the input file */ - in_name = argv[i]; /* remember name of input - file */ - input = open (in_name, 0); - if (input < 0) { /* check for open error */ - printf ("Can't open %s\n", argv[i]); - exit (); + if (input == 0) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == 0) { /* check for open error */ + printf("Can't open %s\n", argv[i]); + exit(); } continue; - } - else - if (output < 0) { /* we have the output file */ - out_name = argv[i]; /* remember name of output file */ - if (cmp (in_name, out_name) == 0) { /* attempt to - overwright the file */ - printf ("Input and output files must be different\n"); - exit (); - } - output = creat (out_name, 0644); - if (output < 0) { /* check for create error */ - printf ("Can't create %s\n", argv[i]); - exit (); - } - continue; + } else if (output == 0) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + printf("Input and output files must be different\n"); + exit(); } - - printf ("Unknown parameter: %s\n", argv[i]); - exit (); + output = fopen(out_name, "w"); + if (output == 0) { /* check for create error */ + printf("Can't create %s\n", argv[i]); + exit(); + } + continue; + } + printf("Unknown parameter: %s\n", argv[i]); + exit(); + } else + set_option(argv[i]); + + } /* end of for */ + if (input == 0) { + printf("Usage: indent file [ outfile ] [ options ]\n"); + exit(); + } + if (output == 0) + if (troff) + output = stdout; + else { + out_name = in_name; + bakcopy(); } - else - set_option (argv[i]); - - } /* end of for */ - - if (input < 0) { - printf ("Usage: indent file [ outfile ] [ options ]\n"); - exit (); + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column + * 2 */ + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input + * buffer */ + + parse(semicolon); + { + register char *p = buf_ptr; + register col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = ((col - 1) & ~7) + 9; + else + break; + p++; + }; + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; } - if (output < 0) { - out_name = in_name; - bakcopy (); + if (troff) { + register char *p = in_name, + *beg = in_name; + + while (*p) + if (*p++ == '/') + beg = p; + fprintf(output, ".Fn \"%s\"\n", beg); } - if (com_ind <= 1) - com_ind = 2; /* don't put normal comments before column - 2 */ - - if (decl_com_ind <= 0) /* if not specified by user, set this */ - decl_com_ind = ljust_decl ? (com_ind <= 10 ? 2 : com_ind - 8) : com_ind; + /* + * START OF MAIN LOOP + */ - fill_buffer (); /* get first batch of stuff into input - buffer */ + while (1) { /* this is the main loop. it will go + * until we reach eof */ + int is_procname; - parse (semicolon); - /*----------------------------------------------------- -| START OF MAIN LOOP -\*----------------------------------------------------*/ + type_code = lexi(); /* lexi reads one token. The actual + * characters read are stored in "token". + * lexi returns a code indicating the type + * of token */ + is_procname = ps.procname[0]; - while (1) { /* this is the main loop. it will go until - we reach eof */ - type_code = lexi (); /* lexi reads one token. The actual - characters read are stored in "token". - lexi returns a code indicating the type - of token */ - - /* - * The following code moves everything following an if (), while (), - * else, etc. up to the start of the following stmt to a buffer. This - * allows proper handling of both kinds of brace placement. - */ + /* + * The following code moves everything following an if (), while + * (), else, etc. up to the start of the following stmt to a + * buffer. This allows proper handling of both kinds of brace + * placement. + */ flushed_nl = false; - while (search_brace) { /* if we scanned an if(), while(), etc., we - might need to copy stuff into a buffer - *//* we must loop, copying stuff into save_com, until we find the - start of the stmt which follows the if, or whatever */ + while (ps.search_brace) { /* if we scanned an if(), while(), + * etc., we might need to copy + * stuff into a buffer we must + * loop, copying stuff into + * save_com, until we find the + * start of the stmt which follows + * the if, or whatever */ switch (type_code) { - case newline: + case newline: ++line_no; flushed_nl = true; - case form_feed: - break; /* form feeds and newlines found here will - be ignored */ - - case lbrace: /* this is a brace that starts the compound - stmt */ - if (sc_end == 0) { - /* ignore buffering if a comment wasn't stored up */ - search_brace = false; + case form_feed: + break; /* form feeds and newlines found here will + * be ignored */ + + case lbrace: /* this is a brace that starts the + * compound stmt */ + if (sc_end == 0) { /* ignore buffering if a comment + * wasnt stored up */ + ps.search_brace = false; goto check_type; } - if (btype_2) { - save_com[0] = '{'; - /* we either want to put the brace right after the if - */ - goto sw_buffer; - /* go to common code to get out of this loop */ + save_com[0] = '{'; /* we either want to put + * the brace right after + * the if */ + goto sw_buffer; /* go to common code to get out of + * this loop */ } - - default: /* it is the start of a normal statment */ - if (flushed_nl) - /* if we flushed a newline, make sure it is - put back */ + case comment: /* we have a comment, so we must copy it + * into the buffer */ + if (!flushed_nl) { + if (sc_end == 0) { /* if this is the first + * comment, we must set up + * the buffer */ + save_com[0] = save_com[1] = ' '; + sc_end = &(save_com[2]); + } else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + *sc_end++ = '/'; /* copy in start of + * comment */ + *sc_end++ = '*'; + + for (;;) { /* loop until we get to the end of + * the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + + if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer + * overflow */ + diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever."); + fflush(output); + exit(); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + } + default: /* it is the start of a normal statment */ + if (flushed_nl) /* if we flushed a newline, make + * sure it is put back */ force_nl = true; + if (type_code == sp_paren && *token == 'i' + && last_else && ps.else_if + || type_code == sp_nparen && *token == 'e' + && e_code != s_code && e_code[-1] == '}') + force_nl = false; - if (sc_end == 0) { - /* ignore buffering if comment wasn't saved up */ - search_brace = false; + if (sc_end == 0) { /* ignore buffering if comment + * wasnt saved up */ + ps.search_brace = false; goto check_type; } - - if (force_nl) { - /* if we should insert a nl here, put it into the - buffer */ + if (force_nl) { /* if we should insert a nl here, + * put it into the buffer */ force_nl = false; - --line_no; - /* this will be re-increased when the nl is read from - the buffer */ + --line_no; /* this will be re-increased when + * the nl is read from the buffer */ *sc_end++ = '\n'; *sc_end++ = ' '; - if (verbose && !flushed_nl) - /* print error msg if the line was not - already broken */ - printf ("%d: Line broken\n", line_no); + if (verbose && !flushed_nl) /* print error msg if + * the line was not + * already broken */ + diag(0, "Line broken"); flushed_nl = false; } - for (t_ptr = token; *t_ptr; ++t_ptr) - *sc_end++ = *t_ptr; - /* copy token into temp buffer */ - - sw_buffer: - search_brace = false; - /* stop looking for start of stmt */ - bp_save = buf_ptr; - /* save current input buffer */ + *sc_end++ = *t_ptr; /* copy token into temp + * buffer */ + + sw_buffer: + ps.search_brace = false; /* stop looking for start + * of stmt */ + bp_save = buf_ptr; /* save current input buffer */ be_save = buf_end; - buf_ptr = save_com; - /* fix so that subsequent calls to lexi will take tokens - out of save_com */ - *sc_end++ = ' '; - /* add trailing blank, just in case */ + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in + * case */ buf_end = sc_end; sc_end = 0; break; - - case comment: /* we have a comment, so we must copy it - into the buffer */ - if (sc_end == 0) { - /* if this is the first comment, we must set up the - buffer */ - save_com[0] = save_com[1] = ' '; - sc_end = &(save_com[2]); - } - else { - *sc_end++ = '\n'; - /* add newline between comments */ - *sc_end++ = ' '; - --line_no; - } - - *sc_end++ = '/'; - /* copy in start of comment */ - *sc_end++ = '*'; - - for (;;) { /* loop until we get to the end of the - comment */ - *sc_end = *buf_ptr++; - if (buf_ptr >= buf_end) - fill_buffer (); - - if (*sc_end++ == '*' && *buf_ptr == '/') - break; - /* we are at end of comment */ - - if (sc_end >= &(save_com[sc_size])) { - /* check for temp buffer overflow */ - printf ("%d: Internal buffer overflow.\n", - line_no); - printf ("Move big comment from right after if,\ - while, or whatever.\n"); - exit (); - } - } - - *sc_end++ = '/'; - /* add ending slash */ - if (++buf_ptr >= buf_end)/* get past / in buffer */ - fill_buffer (); - break; - } /* end of switch */ - - if (type_code != 0)/* we must make this check, just in case - there was an unexpected EOF */ - type_code = lexi (); - /* read another token */ - } /* end of while (serach_brace) */ -check_type: - - if (type_code == 0) { /* we got eof */ + } /* end of switch */ + if (type_code != 0) /* we must make this check, just in case + * there was an unexpected EOF */ + type_code = lexi(); /* read another token */ + is_procname = ps.procname[0]; + } /* end of while (serach_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ if (s_lab != e_lab || s_code != e_code - || s_com != e_com)/* must dump end of line */ - dump_line (); - if (i_l_follow != 0)/* check for balanced braces */ - printf ("%d too few }'s\n", i_l_follow); - -#ifdef dolog /* only include this stuff if we want to - keep a log */ - log_fid = open ("/mnt/net/willcox/indent/indent_log", 1); - /* open the log file */ - if (log_fid >= 0) { - seek (log_fid, 0, 2); - /* point to end of log */ - time (logent.tvec); - /* get current time */ - logent.inp = input; - /* set up the log entry */ - logent.outp = output; - logent.nout = out_lines; - logent.ncom = out_coms; - logent.wcom = com_lines; - logent.wcode = code_lines; - logent.mc = max_col; - logent.ci = com_ind; - logent.inds = ind_size; - logent.dci = decl_com_ind; - logent.verb = verbose; - logent.ljus = ljust_decl; - logent.lvcom = leave_comma; - logent.unin = unindent_displace; - logent.uid = getuid (); - logent.bropt = btype_2; - write (log_fid, &logent, sizeof logent); - } -#endif + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag(1, "Stuff missing from end of file."); + if (verbose) { - printf ("There were %d output lines and %d comments\n", - out_lines, out_coms); - printf ("(Lines with comments)/(Lines with code): %6.3f\n", - (1.0 * com_lines) / code_lines); + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); } - - exit (); + fflush(output); + exit(); } - if ( - (type_code != comment) && - (type_code != newline) && - (type_code != preesc) && - (type_code != form_feed)) { + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { if ( - force_nl - && - (type_code != semicolon) && - ( - type_code != lbrace - || - !btype_2 - )) { /* we should force a broken line here */ + force_nl + && + (type_code != semicolon) && + ( + type_code != lbrace + || + !btype_2 + )) { /* we should force a broken line here */ if (verbose && !flushed_nl) - printf ("%d: Line broken\n", line_no); + diag(0, "Line broken"); flushed_nl = false; - dump_line (); - want_blank = false; - /* don't insert blank at line start */ + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ force_nl = false; } - - in_stmt = true; /* turn on flag which causes an extra level - of indentation. this is turned off by a - ; or } */ - if (s_com != e_com) { - /* the turkey has embedded a comment in a line. fix it */ + ps.in_stmt = true; /* turn on flag which causes an extra + * level of indentation. this is turned + * off by a ; or '}' */ + if (s_com != e_com) { /* the turkey has embedded a + * comment in a line. fix it */ *e_code++ = ' '; for (t_ptr = s_com; *t_ptr; ++t_ptr) *e_code++ = *t_ptr; *e_code++ = ' '; - *e_code = '\0';/* null terminate code sect */ - want_blank = false; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; e_com = s_com; } - } - else - if (type_code != comment) - /* preserve force_nl thru a comment */ - force_nl = false; - /* cancel forced newline after newline, form feed, etc */ + } else if (type_code != comment) /* preserve force_nl thru + * a comment */ + force_nl = false; + + /* + * cancel forced newline after newline, form feed, etc + */ - /*----------------------------------------------------*\ - | do switch on type of token scanned - \*----------------------------------------------------*/ - switch (type_code) { /* now, decide what to do with the token */ + /*----------------------------------------------------*\ +| do switch on type of token scanned +\*----------------------------------------------------*/ + switch (type_code) { /* now, decide what to do with the token */ - case form_feed: /* found a form feed in line */ - use_ff = true; /* a form feed is treated much like a - newline */ - dump_line (); - want_blank = false; + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much + * like a newline */ + dump_line(); + ps.want_blank = false; break; - case newline: - dump_line (); - ++line_no; /* keep track of input line number */ - want_blank = false; + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ break; - case lparen: /* got a ( or [ */ - ++p_l_follow; /* count parens to make Healy happy */ - if (want_blank && *token != '[') - /* don't put space in front of square - bracket */ + case lparen: /* got a '(' or '[' */ + ++ps.p_l_follow;/* count parens to make Healy happy */ + if (ps.want_blank && *token != '[' && + (ps.last_token != ident || proc_calls_space + || (ps.its_a_keyword && !ps.sizeof_keyword))) *e_code++ = ' '; - - if (in_decl) - while ((e_code - s_code) < dec_ind) - *e_code++ = ' '; - - *e_code++ = token[0]; - want_blank = false; - if (in_or_st && *token == '(') { - /* this is a kluge to make sure that declarations will be - aaigned right if proc decl has an explicit type on it, - i.e. "int a(x) {..." */ - parse (semicolon); - /* I said this was a kluge... */ - in_or_st = false; - /* turn off flag for structure decl or initialization */ + if (ps.in_decl && !ps.block_init) + if (troff && !ps.dumped_decl_indent) { + ps.dumped_decl_indent = 1; + sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + e_code += strlen(e_code); + } else { + while ((e_code - s_code) < dec_ind) + *e_code++ = ' '; + *e_code++ = token[0]; + } else + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; + ps.want_blank = false; + if (ps.in_or_st && *token == '(') { + + /* + * this is a kluge to make sure that declarations will + * be aligned right if proc decl has an explicit type + * on it, i.e. "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for + * structure decl or + * initialization */ } - + if (ps.sizeof_keyword) ps.sizeof_mask |= 1<') + res = "\\(->"; + for (t_ptr = res; *t_ptr; ++t_ptr) + *e_code++ = *t_ptr; } - - for (t_ptr = token; *t_ptr; ++t_ptr) - *e_code++ = *t_ptr; - /* move the token to buffer */ - want_blank = false; + ps.want_blank = false; break; - case binary_op: /* any binary operation */ - do_binary: - if (want_blank) + case binary_op: /* any binary operation */ + do_binary: + if (ps.want_blank) *e_code++ = ' '; - for (t_ptr = token; *t_ptr; ++t_ptr) - *e_code++ = *t_ptr; - /* move the operator */ - want_blank = true; + { + char *res = token; + + if (troff) + switch (token[0]) { + case '<': + if (token[1] == '=') + res = "\\(<="; + break; + case '>': + if (token[1] == '=') + res = "\\(>="; + break; + case '!': + if (token[1] == '=') + res = "\\(!="; + break; + case '|': + if (token[1] == '|') + res = "\\(br\\(br"; + else if (token[1] == 0) + res = "\\(br"; + break; + } + for (t_ptr = res; *t_ptr; ++t_ptr) + *e_code++ = *t_ptr; /* move the operator */ + } + ps.want_blank = true; break; - case postop: /* got a trailing ++ or -- */ + case postop: /* got a trailing ++ or -- */ *e_code++ = token[0]; *e_code++ = token[1]; - want_blank = true; + ps.want_blank = true; break; - case question: /* got a ? */ - squest++; /* this will be used when a later colon - appears so we can distinguish the - ?: construct */ - if (want_blank) + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * ?: construct */ + if (ps.want_blank) *e_code++ = ' '; *e_code++ = '?'; - want_blank = true; + ps.want_blank = true; break; - case casestmt: /* got word 'case' or 'default' */ - scase = true; /* so we can process the later colon - properly */ - if (want_blank) - *e_code++ = ' '; - for (t_ptr = token; *t_ptr; ++t_ptr) - *e_code++ = *t_ptr; - want_blank = true; - break; + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon + * properly */ + goto copy_id; - case colon: /* got a ':' */ - if (squest > 0) { - /* it is part of the ?: construct */ + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the ?: + * construct */ --squest; - if (want_blank) + if (ps.want_blank) *e_code++ = ' '; *e_code++ = ':'; - want_blank = true; + ps.want_blank = true; break; } - - in_stmt = false; - /* seeing a label does not imply we are in a stmt */ + if (ps.in_decl) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply + * we are in a stmt */ for (t_ptr = s_code; *t_ptr; ++t_ptr) - *e_lab++ = *t_ptr; - /* turn everything so far into a label */ + *e_lab++ = *t_ptr; /* turn everything so far into a + * label */ e_code = s_code; *e_lab++ = ':'; *e_lab++ = ' '; *e_lab = '\0'; - force_nl = pcase = scase; - /* pcase will be used by dump_line to decide how to indent the - label. force_nl will force a case n: to be on a line by - itself */ + force_nl = ps.pcase = scase; /* ps.pcase will be used + * by dump_line to decide + * how to indent the + * label. force_nl will + * force a case n: to be + * on a line by itself */ scase = false; - want_blank = false; + ps.want_blank = false; break; - case semicolon: /* got a ';' */ - in_or_st = false; - /* we are not in an initialization or structure declaration */ - scase = false; /* these will only need resetting in a - error */ + case semicolon: /* got a ';' */ + ps.in_or_st = false; /* we are not in an initialization + * or structure declaration */ + scase = false; /* these will only need resetting in a + * error */ squest = 0; - - if (in_decl && s_code == e_code) - /* align this in a declaration */ + if (ps.last_token == rparen) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.sizeof_mask = 0; + ps.block_init = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init) while ((e_code - s_code) < (dec_ind - 1)) *e_code++ = ' '; - in_decl = (dec_nest > 0); - /* if we were in a first level structure declaration, we - aren't any more */ - - if ((!sp_sw || hd_type != forstmt) && p_l_follow > 0) { - /* This should be true iff there were unbalanced parens in - the stmt. It is a bit complicated, because the - semicolon might be in a for stmt */ - printf ("%d: Unbalanced parens\n", line_no); - p_l_follow = 0; - if (sp_sw) { - /* this is a check for a if, while, etc. with - unbalanced parens */ + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first + * level structure + * declaration, we arent + * any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced + * parens in the stmt. It is a bit complicated, + * because the semicolon might be in a for stmt + */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) {/* this is a check for a if, while, etc. + * with unbalanced parens */ sp_sw = false; - parse (hd_type); - /* don't lose the if, or whatever */ + parse(hd_type); /* dont lose the if, or whatever */ } } - *e_code++ = ';'; - want_blank = true; - in_stmt = (p_l_follow > 0); - /* we are no longer in the middle of a stmt */ - - if (!sp_sw) { /* if not if for (;;) */ - parse (semicolon); - /* let parser know about end of stmt */ - force_nl = true; - /* force newline after a end of stmt */ + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in + * the middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of + * stmt */ + force_nl = true; /* force newline after a end of + * stmt */ } - break; - case lbrace: /* got a { */ - in_stmt = false; - /* don't indent the { */ - force_nl = true; - /* force other stuff on same line as { onto new line */ - - if (s_code != e_code && !btype_2) { - /* bracket is not alone on line */ - if (verbose) - printf ("%d: Line broken\n", line_no); - dump_line (); - want_blank = false; + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true; /* force other stuff on same line + * as '{' onto new line */ + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + dump_line(); + ps.want_blank = false; + } } - - if (p_l_follow > 0) { - /* check for preceeding unbalanced parens */ - printf ("%d: Unbalanced parens\n", line_no); - p_l_follow = 0; - if (sp_sw) { - /* check for unclosed if, for, etc. */ + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceeding + * unbalanced parens */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) {/* check for unclosed if, for, etc. */ sp_sw = false; - parse (hd_type); - ind_level = i_l_follow; + parse(hd_type); + ps.ind_level = ps.i_l_follow; } } - if (s_code == e_code) - ind_stmt = false; - /* don't put extra indentation on line with '{' */ - if (in_decl && in_or_st) { - /* this is either a structure declaration or an init */ - di_stack[dec_nest++] = dec_ind; + ps.ind_stmt = false; /* dont put extra + * indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a + * structure declaration + * or an init */ + di_stack[ps.dec_nest++] = dec_ind; dec_ind = 0; + } else { + ps.decl_on_line = false; /* we cant be in the + * middle of a + * declaration, so dont do + * special indentation of + * comments */ + ps.in_parameter_declaration = 0; } - else - decl_on_line = false; - /* we can't be in the middle of a declaration, so don't do - special indentation of comments */ - - parse (lbrace);/* let parser know about this */ - if (want_blank)/* put a blank before { if { is not at - start of line */ + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' + * is not at start of line */ *e_code++ = ' '; - want_blank = false; + ps.want_blank = false; *e_code++ = '{'; + ps.just_saw_decl = 0; break; - case rbrace: /* got a } */ - if (p_l_follow) { - /* check for unclosed if, for, else. */ - printf ("%d: Unbalanced parens\n", line_no); - p_l_follow = 0; + case rbrace: /* got a '}' */ + if (ps.p_l_follow) { /* check for unclosed if, for, + * else. */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; sp_sw = false; } - - if (s_code != e_code) { - /* } must be first on line */ + ps.just_saw_decl = 0; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ if (verbose) - printf ("%d: Line broken\n", line_no); - dump_line (); + diag(0, "Line broken"); + dump_line(); } - *e_code++ = '}'; - want_blank = true; - in_stmt = ind_stmt = false; - - if (dec_nest > 0) { - /* we are in multi-level structure declaration */ - dec_ind = di_stack[--dec_nest]; - in_decl = true; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; } - - parse (rbrace);/* let parser know about this */ + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; break; - case swstmt: /* got keyword "switch" */ + case swstmt: /* got keyword "switch" */ sp_sw = true; - hd_type = swstmt; - /* keep this for when we have seen the expression */ - goto copy_id; /* go move the token into buffer */ + hd_type = swstmt; /* keep this for when we have seen + * the expression */ + goto copy_id; /* go move the token into buffer */ - case sp_paren: /* token is if, while, for */ - sp_sw = true; /* the interesting stuff is done after the - expression is scanned */ + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ hd_type = (*token == 'i' ? ifstmt : - (*token == 'w' ? whilestmt : forstmt)); - /* remember the type of header for later use by parser */ - goto copy_id; /* copy the token into line */ - - case sp_nparen: /* got else, do */ - in_stmt = false; - if (e_code != s_code) { - /* make sure this starts a line */ - if (verbose) - printf ("%d: Line broken\n", line_no); - dump_line (); - want_blank = false; + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag(0, "Line broken"); + dump_line(); /* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true; /* also, following stuff must go + * onto new line */ + last_else = 1; + parse(elselit); + } else { + if (e_code != s_code) { /* make sure this starts a + * line */ + if (verbose) + diag(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true; /* also, following stuff must go + * onto new line */ + last_else = 0; + parse(dolit); } - - force_nl = true; - /* also, following stuff must go onto new line */ - parse (*token == 'e' ? elselit : dolit); - /* pass token on to parser */ - goto copy_id; /* move the token into line */ - - case decl: /* we have a declaration type (int, - register, etc.) */ - parse (decl); /* let parser worry about indentation */ - in_or_st = true; - /* this might be a structure or initialization declaration */ - in_decl = decl_on_line = true; - for (i = 0; token[i++];); - /* get length of token */ - - if (i <= 3) - i = 4; - - dec_ind = ((e_code - s_code + i) / ind_size + 1) * ind_size; - /* this will tell us how far to indent subsequent identifiers - */ + goto copy_id; /* move the token into line */ + + case decl: /* we have a declaration type (int, + * register, etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) + ps.in_parameter_declaration = 1; + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or + * initialization declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + /* + * dec_ind = e_code - s_code + (ps.decl_indent>i ? + * ps.decl_indent : i); + */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; goto copy_id; - case ident: /* got an identifier or constant */ - if (in_decl) { /* if we are in a declaration, we must - indent identifier */ - if (want_blank) - *e_code++ = ' '; - want_blank = false; - - while ((e_code - s_code) < dec_ind) + case ident: /* got an identifier or constant */ + if (ps.in_decl) { /* if we are in a declaration, we + * must indent identifier */ + if (ps.want_blank) *e_code++ = ' '; - } - else - if (sp_sw && p_l_follow == 0) { - /* check for if expr w/o parens *//* this will make - JRM's obsurd "for ever" statements work */ - sp_sw = false; - force_nl = true; - last_u_d = true; - in_stmt = false; - parse (hd_type); + ps.want_blank = false; + if (is_procname == 0 || !procnames_start_line) { + if (!ps.block_init) + if (troff && !ps.dumped_decl_indent) { + sprintf(e_code, "\\c\n.De %dp+\200p\n", dec_ind * 7); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } else + while ((e_code - s_code) < dec_ind) + *e_code++ = ' '; + } else { + if (dec_ind && s_code != e_code) + dump_line(); + dec_ind = 0; + ps.want_blank = false; } - - copy_id: - if (want_blank) + } else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + if (ps.want_blank) *e_code++ = ' '; + if (troff && ps.its_a_keyword) { + *e_code++ = BACKSLASH; + *e_code++ = 'f'; + *e_code++ = 'B'; + } for (t_ptr = token; *t_ptr; ++t_ptr) *e_code++ = *t_ptr; - want_blank = true; + if (troff && ps.its_a_keyword) { + *e_code++ = BACKSLASH; + *e_code++ = 'f'; + *e_code++ = 'R'; + } + ps.want_blank = true; break; - case period: /* treat a period kind of like a binary - operation */ - *e_code++ = '.'; - /* move the period into line */ - want_blank = false; - /* don't put a blank after a period */ + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.';/* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ break; - case comma: - want_blank = (s_code != e_code); - /* only put blank after comma if comma does not start the line - */ - if (in_decl) /* align these in a declaration */ + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after + * comma if comma does + * not start the line */ + if (ps.in_decl && is_procname == 0 && !ps.block_init) while ((e_code - s_code) < (dec_ind - 1)) *e_code++ = ' '; *e_code++ = ','; - - if (break_comma && p_l_follow == 0 && !leave_comma) - force_nl = true; - + if (ps.p_l_follow == 0) { + ps.block_init = 0; + if (break_comma && !ps.leave_comma) + force_nl = true; + } break; - case preesc: /* got the character '#' */ - if ( - (s_com != e_com) || - (s_lab != e_lab) || - (s_code != e_code)) { - /* true iff the '#' was not at start of the line */ - printf ("%d: What is this # doing here?\n", line_no); - goto do_binary; - /* treat it as a binary operator */ + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + char *com_start = 0; + char quote = 0; + char *com_end = 0; + + while (*buf_ptr != '\n' || in_comment) { + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (troff) + *e_lab++ = BACKSLASH; + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab; + } + break; + } + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab == com_end && bp_save == 0) { /* comment on + * preprocessor line */ + if (sc_end == 0) /* if this is the first + * comment, we must set up + * the buffer */ + sc_end = &(save_com[0]); + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + bcopy(com_start, sc_end, com_end - com_start); + sc_end += com_end - com_start; + e_lab = com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input + * buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent + * calls to lexi will take + * tokens out of save_com */ + *sc_end++ = ' '; /* add trailing blank, + * just in case */ + buf_end = sc_end; + sc_end = 0; + } + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; } - - *e_lab++ = '#';/* move whole line to 'label' buffer */ - while (*buf_ptr != '\n') { - *e_lab = *buf_ptr++; - if (buf_ptr >= buf_end) - fill_buffer (); - - if (*e_lab++ == '/' && *buf_ptr == '*') { - /* check for comment on preprocessor line */ - e_lab - = 2; - /* skip back over slash */ - while (*e_lab == '\t' || *e_lab == ' ') - --e_lab; - /* strip off trailing blanks and tabs */ - *(++e_lab) = '\0'; - /* null terminate the line */ - if (++buf_ptr >= buf_end) - /* space past start of comment */ - fill_buffer (); - col_1 = false; - /* don't let pr_comment think that this comment starts - in column 1 */ - decl_on_line = true; - /* treat this as a declaration for comment placement - purposes */ - goto proc_comment; - /* go process the comment */ + if (strncmp(s_lab, "#if", 3) == 0) + if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } else + diag(1, "#if stack overflow"); + else if (strncmp(s_lab, "#else", 5) == 0) + if (ifdef_level <= 0) + diag(1, "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } else if (strncmp(s_lab, "#endif", 6) == 0) + if (ifdef_level <= 0) + diag(1, "Unmatched #endif"); + else { + ifdef_level--; +#ifdef undef + + /* + * This match needs to be more intelligent before + * the message is useful + */ + if (match_state[ifdef_level].tos >= 0 + && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) + diag(0, "Syntactically inconsistant #ifdef alternatives."); +#endif } + break; /* subsequent processing of the newline + * character will cause the line to be + * printed */ + + case comment: /* we have gotten a /* this is a biggie */ + proc_comment: + if (flushed_nl) { /* we should force a broken line + * here */ + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at + * line start */ + force_nl = false; } - - *e_lab = '\0'; /* null terminate line */ - pcase = false; - break; /* subsequent processing of the newline - character will cause the line to be - printed */ - - case comment: /* we have gotten a /* this is a biggie */ - proc_comment: - pr_comment (); + pr_comment(); break; - } /* end of big switch stmt */ - - *e_code = '\0'; /* make sure code section is null - terminated */ - - } /* end of main while (1) loop */ + } /* end of big switch stmt */ + *e_code = '\0'; /* make sure code section is null + * terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ }; /* - * copy input file to backup file - * if in_name is /blah/blah/blah/file, then backup file - * will be ".Bfile" - * then make the backup file the input and original - * input file the output + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output */ -bakcopy () { - int n, - bakchn; - char buff[512]; - register char *p; - - /* construct file name .Bfile */ - for (p = in_name; *p; p++);/* skip to end of string */ - while (p > in_name && *p != '/')/* find last '/' */ +bakcopy() +{ + int n, + bakchn; + char buff[512]; + register char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ p--; if (*p == '/') p++; - sprintf (bakfile, ".B%s", p); + sprintf(bakfile, "%s.BAK", p); - /* copy in_name to backup file */ - bakchn = creat (bakfile, 0600); + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); if (bakchn < 0) { - printf ("can't create backup file \"%s\"\n", bakfile); - exit (); + printf("can't create backup file \"%s\"\n", bakfile); + exit(); } - while (n = read (input, buff, 512)) - write (bakchn, buff, n); - close (bakchn); - close (input); + while (n = read(fileno(input), buff, 512)) + write(bakchn, buff, n); + close(bakchn); + fclose(input); - /* re-open backup file as the input file */ - input = open (bakfile, 0); + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); if (input < 0) { - printf ("can't re-open backup file\n"); - exit (); + printf("can't re-open backup file\n"); + exit(); } - - /* now the original input file will be the output */ - output = creat (in_name, 0644); - if (output < 0) { - printf ("can't create %s\n", in_name); - unlink (bakfile); - exit (); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == 0) { + printf("can't create %s\n", in_name); + unlink(bakfile); + exit(); } } -set_option (arg) -char *arg; -{ - register j; - for (j = 0; options[j].str != 0; ++j) { - /* look thru list of possible options */ - if (eqin (options[j].str, arg)) { - set_var (j, arg); - break; /* get out of for loop */ - } - } +char *param_start; - if (options[j].str == 0) { /* illegal arg given */ - printf ("Unknown parameter: %s\n", arg); - exit (); +eqin(s1, s2) + register char *s1; + register char *s2; +{ + while (*s1) { + if (*s1++ != *s2++) + return (false); } + param_start = s2; + return (true); } -set_var (j, arg) -char *arg; +set_option(arg) + char *arg; { - switch (options[j].code) { - case 1: /* have -lnnn */ - max_col = atoi (&arg[2]); - break; - case 2: /* have -cnnn */ - com_ind = atoi (&arg[2]); - break; - case 3: /* have -innn */ - ind_size = atoi (&arg[2]); - break; - case 4: /* have -cdnnn */ - decl_com_ind = atoi (&arg[3]); - break; - case 5: /* have -v */ + if (!eqin("-npro", arg)) + if (eqin("-lc", arg)) /* comment line length */ + block_comment_max_col = atoi(param_start); + else if (eqin("-lp", arg)) + lineup_to_parens = 1; + else if (eqin("-nlp", arg)) + lineup_to_parens = 0; + else if (eqin("-l", arg)) /* line length */ + max_col = atoi(param_start); + else if (eqin("-psl", arg)) /* if true, the names of + * procedures being defined get + * placed in column 1 (ie. a + * newline is placed between the + * type of the procedure and its + * name) */ + procnames_start_line = 1; + else if (eqin("-npsl", arg)) + procnames_start_line = 0; + else if (eqin("-fc1", arg)) + format_col1_comments = 1; + else if (eqin("-nfc1", arg)) + format_col1_comments = 0; + else if (eqin("-pcs", arg)) /* If true, procedure calls look + * like: foo(bar) rather than foo + * (bar) */ + proc_calls_space = 1; + else if (eqin("-npcs", arg)) + proc_calls_space = 0; + else if (eqin("-ip", arg)) /* indent parameters */ + ps.indent_parameters = 1; + else if (eqin("-nip", arg)) /* no indent parameters */ + ps.indent_parameters = 0; + else if (eqin("-cli", arg)) { /* case label indent */ + extern float atof(); + + ps.case_indent = atof(param_start); + } + else if (eqin("-ci",arg)) + continuation_indent = atoi(param_start); + else if (eqin("-cdb", arg)) /* comment delimiters should be on + * lines by themselves */ + comment_delimiter_on_blankline = 1; + else if (eqin("-ncdb", arg)) /* comment delimiters shouldnt be + * on lines by themselves */ + comment_delimiter_on_blankline = 0; + else if (eqin("-i", arg)) /* indent width */ + ps.ind_size = atoi(param_start); + else if (eqin("-cd", arg)) /* indent for comments on + * declarations */ + ps.decl_com_ind = atoi(param_start); + else if (eqin("-ce", arg)) /* true iff 'else' should cuddle + * up to '}' */ + cuddle_else = 1; + else if (eqin("-c", arg)) /* comment indent */ + ps.com_ind = atoi(param_start); + else if (eqin("-v", arg)) /* spew out rubbish */ verbose = true; - break; - case 6: /* have -nv */ + else if (eqin("-nv", arg)) /* keep quiet */ verbose = false; - break; - case 7: /* have -dj */ - ljust_decl = true; - break; - case 8: /* have -ndj */ - ljust_decl = false; - break; - case 9: /* -nbc */ - leave_comma = true; - break; - case 10: /* -bc */ - leave_comma = false; - break; - case 13: /* -dnnn */ - unindent_displace = atoi (&arg[2]); - break; - case 14: /* -br */ + else if (eqin("-dj", arg)) + ps.ljust_decl = true; + else if (eqin("-ndj", arg)) + ps.ljust_decl = false; + else if (eqin("-nbc", arg)) /* dont break after commas in + * declarations */ + ps.leave_comma = true; + else if (eqin("-bc", arg)) /* break after commas in + * declarations */ + ps.leave_comma = false; + else if (eqin("-di", arg)) /* indent from type to varname in + * a declaration */ + ps.decl_indent = atoi(param_start); + else if (eqin("-d", arg)) + ps.unindent_displace = atoi(param_start); + else if (eqin("-br", arg)) btype_2 = true; - break; - case 15: /* -bl */ + else if (eqin("-bl", arg)) btype_2 = false; - break; - case 16: - if(input<0) input = 0; - if(output<0) output = 1; - break; - } + else if (eqin("-st", arg)) { /* input and output on standard IO */ + if (input == 0) + input = stdin; + if (output == 0) + output = stdout; + } else if (eqin("-ei", arg)) /* else-ifs should be stuck + * together */ + ps.else_if = 1; + else if (eqin("-nei", arg)) /* else-ifs should be broken apart */ + ps.else_if = 0; + else if (eqin("-nce", arg)) /* else should always start a line */ + cuddle_else = 0; + else if (eqin("-sc", arg)) /* comment continuations should + * start with a * */ + star_comment_cont = 1; + else if (eqin("-nsc", arg)) + star_comment_cont = 0; /* comments shouldnt start with a + * star */ + else if (eqin("-bap", arg)) /* blanklines after procedures */ + blanklines_after_procs = 1; + else if (eqin("-nbap", arg)) /* blanklines after procedures */ + blanklines_after_procs = 0; + else if (eqin("-sob", arg)) /* swallow optional blanklines */ + swallow_optional_blanklines = 1; + else if (eqin("-nsob", arg)) /* swallow optional blanklines */ + swallow_optional_blanklines = 0; + else if (eqin("-bad", arg)) /* blanklines after declarations */ + blanklines_after_declarations = 1; + else if (eqin("-nbad", arg)) /* blanklines after declarations */ + blanklines_after_declarations = 0; + else if (eqin("-bbb", arg)) /* blanklines before blockcomments */ + blanklines_before_blockcomments = 1; + else if (eqin("-nbbb", arg)) /* blanklines before blockcomments */ + blanklines_before_blockcomments = 0; + else if (eqin("-troff", arg)) + troff = 1; + else if (arg[0] == '-' && arg[1] == 'T') /* -Ttypename */ + addkey(arg + 2, 4); + else { /* illegal arg given */ + printf("Unknown parameter: %s\n", arg); + exit(); + } } /* - * GETPRO - get profile file - * profile file is max 127 characters + * GETPRO - get profile file profile file is max 127 characters */ -getpro (name, buf) -char *name, /* profile file name, as in '.indent.pro' - */ - *buf; /* will receive contents of .pro file */ +getpro(name, buf, len) + char *name, /* profile file name, as in '.indent.pro' */ + *buf; /* will receive contents of .pro file */ { register chn, n; - char file[32]; + char file[100]; file[0] = 0; - strcat (file, getenv ("HOME")); - strcat (file, "/"); - strcat (file, name); - chn = open (file, 0); + strcat(file, getenv("HOME")); + strcat(file, "/"); + strcat(file, name); + if ((chn = open(name, 0)) < 0) + chn = open(file, 0); if (chn < 0) return (-1); - n = read (chn, buf, 127); + n = read(chn, buf, len); if (n < 0) return (-1); - buf[n--] = 0; /* null terminate line */ + buf[n--] = 0; /* null terminate line */ if (buf[n] == '\n') buf[n] = 0; - close (chn); + close(chn); return (0); } /* - * strip off arguments in a string: - * p is address of a character pointer - * nextchr returns pointer to front of first arg - * arg is null terminated. - * p is reset to after arg for subsequent calls + * strip off arguments in a string: p is address of a character pointer + * nextchr returns pointer to front of first arg arg is null terminated. p + * is reset to after arg for subsequent calls */ -char *nxtarg (p) -char **p; +char * +nxtarg(p) + char **p; { - register char *f, - *b; - f = b = *p; - while (*f && (*f == ' ' || *f == '\t')) + register char *f, + *b; + + f = *p; + while (*f && *f <= ' ') f++; - while (*b && (*b != ' ' && *b != '\t')) + b = f; + while (*b > ' ') b++; if (*b != 0) *b++ = 0; @@ -1176,16 +1299,18 @@ char **p; } -set_profile () { - char line[128], - *b; - register char *f; - extern char *nxtarg (); +set_profile() +{ + char line[1000], + *b; + register char *f; + extern char *nxtarg(); - if (getpro (".indent.pro", line) < 0) + if (getpro(".indent.pro", line, sizeof line) < 0) return; b = line; - if(verbose) printf ("profile: %s\n", b); - while (*(f = nxtarg (&b))) - set_option (f); + if (verbose) + printf("profile: %s\n", b); + while (*(f = nxtarg(&b))) + set_option(f); } diff --git a/usr/src/usr.bin/indent/indent_codes.h b/usr/src/usr.bin/indent/indent_codes.h index 34f790b4bf..42b740e54c 100644 --- a/usr/src/usr.bin/indent/indent_codes.h +++ b/usr/src/usr.bin/indent/indent_codes.h @@ -3,7 +3,7 @@ * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * - * @(#)indent_codes.h 5.1 (Berkeley) %G% + * @(#)indent_codes.h 5.2 (Berkeley) %G% */ /* diff --git a/usr/src/usr.bin/indent/indent_globs.h b/usr/src/usr.bin/indent/indent_globs.h index 02762a7956..89ba25ec8a 100644 --- a/usr/src/usr.bin/indent/indent_globs.h +++ b/usr/src/usr.bin/indent/indent_globs.h @@ -3,10 +3,10 @@ * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * - * @(#)indent_globs.h 5.1 (Berkeley) %G% + * @(#)indent_globs.h 5.2 (Berkeley) %G% */ -/* +/*- Copyright (C) 1976 by the @@ -29,64 +29,45 @@ GLOBALS: FUNCTIONS: None -*/ -#define bufsize 600/* size of internal buffers */ -#define inp_bufs 512 - /* size of input buffer */ -#define sc_size 5000 - /* size of save_com buffer */ -#define label_offset 2 - /* number of levels a label is placed to left of code - */ +*/ -#define d_ljust 0 /* default for ljust_decl */ -#define d_max_col 75 - /* default for max_col */ -#define d_com_ind 33 - /* default com_ind */ -#define d_ind_size 4 - /* default ind_size */ -#define d_verbose 0/* default verbose */ -#define d_unindent 1 - /* default value for unindent_displace */ -#define d_leave_comma 0 - /* default value for leave_comma */ -#define d_btype_2 1/* default value for btype_2 */ +#include + +#define BACKSLASH '\\' +#define bufsize 600 /* size of internal buffers */ +#define inp_bufs 600 /* size of input buffer */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left of code + */ #define tabsize 8 /* the size of a tab */ -#define tabmask 0177770 - /* mask used when figuring length of lines with tabs */ +#define tabmask 0177770 /* mask used when figuring length of lines with tabs */ #define false 0 #define true 1 -int input; /* the fid for the input file */ -int output; /* the fid for the output file */ +FILE *input; /* the fid for the input file */ +FILE *output; /* the output file */ -char labbuf[bufsize]; - /* buffer for label */ +char labbuf[bufsize]; /* buffer for label */ char *s_lab; /* start ... */ char *e_lab; /* .. and end of stored label */ -char codebuf[bufsize]; - /* buffer for code section */ +char codebuf[bufsize]; /* buffer for code section */ char *s_code; /* start ... */ char *e_code; /* .. and end of stored code */ -char combuf[bufsize]; - /* buffer for comments */ +char combuf[bufsize]; /* buffer for comments */ char *s_com; /* start ... */ char *e_com; /* ... and end of stored comments */ -char in_buffer[inp_bufs]; - /* input buffer */ +char in_buffer[inp_bufs]; /* input buffer */ char *buf_ptr; /* ptr to next character to be taken from in_buffer */ char *buf_end; /* ptr to first after last char in in_buffer */ -char save_com[sc_size]; - /* input text is saved here when looking for the brace +char save_com[sc_size]; /* input text is saved here when looking for the brace after an if, while, etc */ char *sc_end; /* pointer into save_com buffer */ @@ -94,69 +75,152 @@ char *bp_save; /* saved value of buf_ptr when taking input from save_com */ char *be_save; /* similarly saved value of buf_end */ -char token[bufsize]; - /* the last token scanned */ - +char token[bufsize]; /* the last token scanned */ -int bl_line; /* set to 1 by dump_line if the line is blank */ -int break_comma; - /* when true and not in parens, break after a comma */ +int blanklines_after_declarations; +int blanklines_before_blockcomments; +int blanklines_after_procs; +int swallow_optional_blanklines; +int n_real_blanklines; +int prefix_blankline_requested; +int postfix_blankline_requested; +int break_comma; /* when true and not in parens, break after a comma */ int btype_2; /* when true, brace should be on same line as if, while, etc */ -int case_ind; /* indentation level to be used for a "case n:" */ +float case_ind; /* indentation level to be used for a "case n:" */ int code_lines;/* count of lines with code */ -int col_1; /* set to true if the last token started in column 1 */ -int com_col; /* this is the column in which the current coment - should start */ -int com_ind; /* the column in which comments to the right of code - should start */ -int com_lines; /* the number of lines with comments, set by dump_line - */ -int dec_nest; /* current nesting level for structure or init */ -int decl_com_ind; - /* the column in which comments after declarations - should be put */ -int decl_on_line; - /* set to true if this line of code has part of a - declaration on it */ int had_eof; /* set to true when input is exhausted */ -int i_l_follow;/* the level to which ind_level should be set after the - current line is printed */ -int in_decl; /* set to true when we are in a declaration stmt. The - processing of braces is then slightly different */ -int in_stmt; /* set to 1 while in a stmt */ -int ind_level; /* the current indentation level */ -int ind_size; /* the size of one indentation level */ -int ind_stmt; /* set to 1 if next line should have an extra - indentation level because we are in the middle of a - stmt */ -int last_u_d; /* set to true after scanning a token which forces a - following operator to be unary */ -int leave_comma; - /* if true, never break declarations after commas */ int line_no; /* the current line number. */ -int ljust_decl;/* true if declarations should be left justified */ int max_col; /* the maximum allowable line length */ -int out_coms; /* the number of comments processed, set by pr_comment - */ -int out_lines; /* the number of lines written, set by dump_line */ -int p_l_follow;/* used to remember how to indent following statement - */ -int paren_level; - /* parenthesization level. used to indent within stmts - */ -int pcase; /* set to 1 if the current line label is a case. It is - printed differently from a regular label */ -int search_brace; - /* set to true by parse when it is necessary to buffer - up all info up to the start of a stmt after an if, - while, etc */ -int unindent_displace; - /* comments not to the right of code will be placed - this many indentation levels to the left of code */ -int use_ff; /* set to one if the current line should be terminated - with a form feed */ int verbose; /* when true, non-essential error messages are printed */ +int cuddle_else; /* true if else should cuddle up to '}' */ +int star_comment_cont; /* true iff comment continuation lines should + have stars at the beginning of each line. + */ +int comment_delimiter_on_blankline; +int troff; /* true iff were generating troff input */ +int procnames_start_line; /* if true, the names of procedures being + defined get placed in column 1 (ie. a + newline is placed between the type of the + procedure and its name) */ +int proc_calls_space; /* If true, procedure calls look like: + foo(bar) rather than foo (bar) */ +int format_col1_comments; /* If comments which start in column 1 are to + be magically reformatted (just like comments that + begin in later columns) */ +int inhibit_formatting; /* true if INDENT OFF is in effect */ +int suppress_blanklines; /* set iff following blanklines should be + suppressed */ +int continuation_indent; /* set to the indentation between the edge of + code and continuation lines */ +int lineup_to_parens; /* if true, continued code within parens will + be lined up to the open paren */ +int block_comment_max_col; + + +struct parser_state { + int last_token; + int p_stack[50]; /* this is the parsers stack */ + int il[50]; /* this stack stores indentation levels */ + float cstk[50]; /* used to store case stmt indentation + * levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first + * non-blank char should be lined up with + * the / in /* */ + int comment_delta, + n_comment_delta; + int cast_mask; /* indicates which close parens close off + * casts */ + int sizeof_mask; /* indicates which close parens close off + sizeof''s */ + int block_init; /* true iff inside a block initialization */ + int last_nl; /* this is true if the last thing scanned + * was a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no + * left paren since the last semicolon. + * When true, a '{' is starting a + * structure definition or an + * initialization list */ + int bl_line; /* set to 1 by dump_line if the line is + * blank */ + int col_1; /* set to true if the last token started + * in column 1 */ + int com_col; /* this is the column in which the current + * coment should start */ + int com_ind; /* the column in which comments to the + * right of code should start */ + int com_lines; /* the number of lines with comments, set + * by dump_line */ + int dec_nest; /* current nesting level for structure or + * init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has + * part of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be + * set after the current line is printed */ + int in_decl; /* set to true when we are in a + * declaration stmt. The processing of + * braces is then slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an + * extra indentation level because we are + * in the middle of a stmt */ + int last_u_d; /* set to true after scanning a token + * which forces a following operator to be + * unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set + * by pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent + * following statement */ + int paren_level; /* parenthesization level. used to indent + * within stmts */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from + * a regular label */ + int search_brace; /* set to true by parse when it is + * necessary to buffer up all info up to + * the start of a stmt after an if, while, + * etc */ + int unindent_displace; /* comments not to the right of + * code will be placed this many + * indentation levels to the left + * of code */ + int use_ff; /* set to one if the current line should + * be terminated with a form feed */ + int want_blank; /* set to true when the following token + * should be prefixed by a blank. (Said + * prefixing is ignored in some cases.) */ + int else_if; /* True iff else if pairs should be + * handled specially */ + int decl_indent; /* column to indent declared identifiers + * to */ + int its_a_keyword; + int sizeof_keyword; + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from + * the switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +} ps; + +int ifdef_level; +struct parser_state state_stack[5]; +struct parser_state match_state[5]; diff --git a/usr/src/usr.bin/indent/io.c b/usr/src/usr.bin/indent/io.c index e86f3cc77b..8d7ad3a8d7 100644 --- a/usr/src/usr.bin/indent/io.c +++ b/usr/src/usr.bin/indent/io.c @@ -5,571 +5,512 @@ */ #ifndef lint -static char sccsid[] = "@(#)io.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)io.c 5.2 (Berkeley) %G%"; #endif not lint -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -FILE NAME: - io.c - -PURPOSE: - Contains routines to handle i/o related stuff for indent. - -GLOBALS: - None - -FUNCTIONS: - dump_line - fill_buffer - pad_output - count_spaces - eqin - cmp - -*/ -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - dump_line - -FUNCTION: - Does the actual printing of the stored up line - -ALGORITHM: - For each of the label, code, and comment sections which are used on - this line: - - 1) Use pad_output to get the section aligned properly. - 2) write the section - - The indentation level used for the code is set by ind_level. After - printing, ind_level is set to i_l_follow. - - An extra level of indentation is added if ind_stmt is 1. After - printing, ind_stmt is set to 1 iff the line just printed has an - unterminated, non-declaration statement. - -PARAMETERS: - None - -RETURNS: - Nothing - -GLOBALS: - labbuf - s_lab - e_lab = Reset to s_lab - - codebuf - s_code - e_code = Reset to s_code - - combuf - s_com - e_com = Reset to s_com - - bl_line = Set to true iff the line was blank - case_ind - code_lines = Count lines with code - com_col - com_lines = Keep track of lines with comments - decl_on_line = Set to in_decl after line is printed - i_l_follow - in_decl - in_stmt - ind_level = Set to i_l_follow at completion - ind_size - ind_stmt = Set to in_stmt at completion if not in declaration - out_lines = Count output lines - p_l_follow - paren_level = Set to p_l_follow at completion - pcase - use_ff = Reset to false - -CALLS: - pad_output - printf (lib) - write (lib) - -CALLED BY: - main - pr_comment - -HISTORY: - initial coding November 1976 D A Willcox of CAC - -*/ +/*- + * Copyright (C) 1976 + * by the + * Board of Trustees + * of the + * University of Illinois + * All rights reserved + * FILE NAME: + * io.c + * PURPOSE: + * Contains routines to handle i/o related stuff for indent. + * GLOBALS: + * None + * FUNCTIONS: + * dump_line + * fill_buffer + * pad_output + * count_spaces + * eqin + * cmp + * + */ +/*- + * + * Copyright (C) 1976 + * by the + * Board of Trustees + * of the + * University of Illinois + * + * All rights reserved + * + * + * NAME: + * dump_line + * + * FUNCTION: + * Does the actual printing of the stored up line + * + * ALGORITHM: + * For each of the label, code, and comment sections which are used on + * this line: + * + * 1) Use pad_output to get the section aligned properly. + * 2) write the section + * + * The indentation level used for the code is set by ps.ind_level. After + * printing, ps.ind_level is set to ps.i_l_follow. + * + * An extra level of indentation is added if ps.ind_stmt is 1. After + * printing, ps.ind_stmt is set to 1 iff the line just printed has an + * unterminated, non-declaration statement. + * + * HISTORY: + * initial coding November 1976 D A Willcox of CAC + * + */ #include "indent_globs.h"; -int ff = 014; /* used to write a form feed */ - - -dump_line () { /* dump_line is the routine that actually - effects the printing of the new source. - It prints the label section, followed by - the code section with the appropriate - nesting level, followed by any comments - */ - register int cur_col, - temp_col, - target_col; - - bl_line = true; /* if we don't find otherwise, assume a - blank line */ +int ff = 014; /* used to write a form feed */ +int comment_open; +static paren_target; - if (ind_level == 0) - ind_stmt = 0; /* this is a class A kludge. don't do - additional statement indentation if we - are at bracket level 0 */ +dump_line() +{ /* dump_line is the routine that actually + * effects the printing of the new source. + * It prints the label section, followed + * by the code section with the + * appropriate nesting level, followed by + * any comments */ + register int cur_col, + temp_col, + target_col; - if (e_lab != s_lab || e_code != s_code) - ++code_lines; /* keep count of lines with code */ - - if (e_lab != s_lab) { /* print lab, if any */ - if (pcase) /* if the label is really a case, we must - indent */ - cur_col = pad_output (1, case_ind * ind_size + 1); + if (ps.procname[0]) { + if (troff) + fprintf(output, ".Pr \"%s\"\n", ps.procname); + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines>0) suppress_blanklines--; else { - if (*s_lab == '#') /* check for #define, etc */ - cur_col = 1; - else - cur_col = pad_output (1, ind_size * (ind_level - label_offset) + 1); + ps.bl_line = true; + n_real_blanklines++; } - - write (output, s_lab, e_lab - s_lab); - cur_col = count_spaces (cur_col, s_lab); - /* count_spaces gives number of characters, considering tabs */ - bl_line = false; /* line not blank after all */ - } - else - cur_col = 1; /* there is no label section */ - - pcase = false; - - if (s_code != e_code) { /* print code section, if any */ - target_col = ind_size * (ind_level + paren_level + ind_stmt) + 1; - - cur_col = pad_output (cur_col, target_col); - /* pad_output writes enough tabs and spaces to get the current char - position up to target_col */ - write (output, s_code, e_code - s_code); - cur_col = count_spaces (cur_col, s_code); - bl_line = false; /* line not blank */ } - - if ((cur_col - 1) > max_col && output!=1)/* check for line too long */ - printf ("%d: Code has %d chars, max is %d\n", line_no, (cur_col - 1), max_col); - - if (s_com != e_com) { /* print comment, if any */ - if (cur_col > com_col && count_spaces (cur_col, s_com) >= max_col) { - /* if comment can't fit on this line, put it on next line */ - write (output, "\n", 1); - cur_col = 1; - ++out_lines; + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested) + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we + * are at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + cur_col = pad_output(1, compute_label_target()); + fprintf(output, "%.*s", e_lab - s_lab, s_lab); + cur_col = count_spaces(cur_col, s_lab); } - cur_col = pad_output (cur_col, com_col); - write (output, s_com, e_com - s_com); - - cur_col = count_spaces (cur_col, s_com); - if ((cur_col - 1) > max_col && output!=1)/* check for too long comment */ - printf ("%d: Comment goes to column %d. Max is %d\n", - line_no, (cur_col - 1), max_col); - - bl_line = false; - ++com_lines; /* count lines with comments */ + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + register char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + register i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) + if (troff) { + register char *p; + + if (e_com[-1] == '/' && e_com[-2] == '*') + e_com -= 2; + while (e_com > s_com && e_com[-1] == ' ') + e_com--; + *e_com = 0; + p = s_com; + while (*p == ' ') + p++; + if (p[0] == '/' && p[1] == '*') + p += 2; + else if (p[0] == '*') + p += p[1] == '/' ? 2 : 1; + while (*p == ' ') + p++; + if (*p == 0) + goto inhibit_newline; + if (!comment_open) { + if ('a' <= *p && *p <= 'z') + *p = *p + 'A' - 'a'; + if (s_code != e_code || s_lab != e_lab) { + fprintf(output, "\\c\n./* %dp 1 %dp\n", + ps.com_col * 7, target_col * 7); + } + else + fprintf(output, "./* %dp 0 %dp\n", + ps.com_col * 7, target_col * 7); + } + comment_open = 1; + while (*p) { + if (*p == BACKSLASH) + putc(BACKSLASH, output); + putc(*p++, output); + } + } + else { /* print comment, if any */ + register target = ps.com_col; + register char *com_st = s_com; + + target += ps.comment_delta; + while (target <= 0) + if (*s_com == ' ') + target++, s_com++; + else if (*s_com == '\t') + target = ((target - 1) & ~7) + 9, s_com++; + else + target = 1; + if (cur_col > target) { /* if comment cant fit on this + * line, put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + cur_col = pad_output(cur_col, target); + if (!ps.box_com) { + if (star_comment_cont && com_st[1] != '*') + if (com_st[1] == ' ' && com_st[0] == ' ') + com_st[1] = '*'; + else + fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); + } + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + cur_col = count_spaces(cur_col, com_st); + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); +inhibit_newline: + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; } - - if (use_ff) - write (output, &ff, 1);/* end the output with a ff */ - else - write (output, "\n", 1); /* or a newline */ - use_ff = false; - *(e_lab = s_lab) = '\0'; /* reset buffers */ + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact + * for proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and + * if we are not in the + * middle of a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ *(e_code = s_code) = '\0'; *(e_com = s_com) = '\0'; - - ind_level = i_l_follow; - paren_level = p_l_follow; - ++out_lines; - decl_on_line = in_decl; /* if we are in the middle of a - declaration, remember that fact for - proper comment indentation */ - ind_stmt = in_stmt & ~in_decl; - /* next line should be indented if we have not completed this stmt and if - we are not in the middle of a declaration */ - + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + paren_target = -ps.paren_indents[ps.paren_level - 1]; return; }; - /* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - fill_buffer -FUNCTION: - Reads one block of input into input_buffer +compute_code_target() { + register target_col = ps.ind_size * ps.ind_level + 1; -ALGORITHM: - Trivial - -PARAMETERS: - None - -RETURNS: - Nothing - -GLOBALS: - in_buffer = - buf_end = Set to 1 past last character read in - buf_ptr = Set to start of buffer - be_save = Set to zero if it was non-zero - bp_save = Set to zero - -CALLS: - read (lib) - -CALLED BY: - lexi - main - pr_comment + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent * ps.paren_level; + else { + register w; + register t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} -HISTORY: - initial coding November 1976 D A Willcox of CAC - 1/7/77 D A Willcox of CAC Added check for switch back to - partly full input buffer from - temporary buffer +compute_label_target() +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) +1 + : *s_lab == '#' ? 1 + : ps.ind_size * (ps.ind_level - label_offset) +1; +} -*/ -int fill_buffer () { /* this routine reads stuff from the input */ - int count; - register int i; - if (bp_save != 0) { /* there is a partly filled input buffer - left */ - buf_ptr = bp_save; /* don't read anything, just switch buffers - */ +/* + * Copyright (C) 1976 by the Board of Trustees of the University of + * Illinois + * + * All rights reserved + * + * + * NAME: fill_buffer + * + * FUNCTION: Reads one block of input into input_buffer + * + * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 + * A Willcox of CAC Added check for switch back to partly full input + * buffer from temporary buffer + * + */ +int +fill_buffer() +{ /* this routine reads stuff from the input */ + int count; + register char *p; + register int i; + register FILE *f = input; + + if (bp_save != 0) { /* there is a partly filled input buffer + * left */ + buf_ptr = bp_save; /* dont read anything, just switch buffers */ buf_end = be_save; bp_save = be_save = 0; if (buf_ptr < buf_end) - return; /* only return if there is really something - in this buffer */ + return; /* only return if there is really + * something in this buffer */ } - - count = read (input, in_buffer, inp_bufs); - - buf_end = in_buffer + count; - buf_ptr = in_buffer; - - if (count == 0) { /* count of zero means eof */ + p = in_buffer; + buf_ptr = p; + while ((*p++ = i = getc(f)) != EOF && i != '\n'); + if (i == EOF) { + p[-1] = ' '; + *p++ = '\n'; had_eof = true; - *buf_end++ = ' '; - *buf_end++ = '\n'; /* insert extra newline. it will - eventually get indent to stop */ } - + buf_end = p; + if (p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } return; }; - /* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - All rights reserved - - -NAME: - pad_output - -FUNCTION: - Writes tabs and spaces to move the current column up to the - desired position. - -ALGORITHM: - Put tabs and/or blanks into pobuf, then write pobuf. - -PARAMETERS: - current integer The current column - target integer The desired column - -RETURNS: - Integer value of the new column. (If current >= target, - no action is taken, and current is returned. - -GLOBALS: - None - -CALLS: - write (sys) - -CALLED BY: - dump_line - -HISTORY: - initial coding November 1976 D A Willcox of CAC - -*/ -int pad_output (current, target)/* writes tabs and blanks (if necessary) to - get the current output position up to - the target column */ -int current; /* the current column value */ -int target; /* position we want it at */ +/* + * Copyright (C) 1976 by the Board of Trustees of the University of + * Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the + * desired position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column target + * nteger The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no + * action is taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +pad_output(current, target) /* writes tabs and blanks (if necessary) + * to get the current output position up + * to the target column */ + int current; /* the current column value */ + int target; /* position we want it at */ { - register int curr; /* internal column pointer */ - register char *p; /* pointer into buffer of characters to be written */ - char pobuf[256]; /* pad characters are stored here before writing */ + register int curr; /* internal column pointer */ register int tcur; - if (current >= target) - return (current); /* line is already long enough */ - - curr = current; - p = pobuf; - while (curr < target) { - if ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target){ - *p++ = '\t'; /* put a tab into buffer */ + if (troff) + fprintf(output, "\\h'|%dp'", (target - 1) * 7); + else { + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) { + putc('\t', output); curr = tcur; } - else { - while (curr++ < target) - *p++ = ' '; /* pad with final blanks */ - } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ } - - write (output, pobuf, p - pobuf); /* write the characters we saved */ return (target); }; - /* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - count_spaces - -FUNCTION: - Find out where printing of a given string will leave the current - character position on output. -ALGORITHM: - Run thru input string and add appropriate values to current position. - -PARAMETERS: - current integer The current line character position - buffer ptr to character Pointer to input string - -RETURNS: - Integer value of position after printing "buffer" starting in - column "current". - -GLOBALS: - None - -CALLS: - None - -CALLED BY: - pr_comment - -HISTORY: - initial coding November 1976 D A Willcox of CAC +/* + * Copyright (C) 1976 by the Board of Trustees of the University of + * Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in + * column "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces(current, buffer) -*/ -int count_spaces (current, buffer) - /* this routine figures out where the - character position will be after - printing the text in buffer starting at - column "current" */ -int current; -char *buffer; +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ + int current; + char *buffer; { - register char *buf; /* used to look thru buffer */ - register int cur; /* current character counter */ + register char *buf; /* used to look thru buffer */ + register int cur; /* current character counter */ cur = current; for (buf = buffer; *buf != '\0'; ++buf) { switch (*buf) { - case '\n': - case 014: /* form feed */ + case '\n': + case 014: /* form feed */ cur = 1; break; - case '\t': + case '\t': cur = ((cur - 1) & tabmask) + tabsize + 1; break; - case '': /* this is a backspace */ + case '': /* this is a backspace */ --cur; break; - default: + default: ++cur; break; - } /* end of switch */ - } /* end of for loop */ - + } /* end of switch */ + } /* end of for loop */ return (cur); }; - /* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - eqin - -FUNCTION: - Returns true if the first arg matches the beginning of the second arg. - -ALGORITHM: - Trivial - -PARAMETERS: - str1 pointer to character - str2 pointer to character - -RETURNS: - 1 if first string matches start of second string - 0 otherwise - -GLOBALS: - None - -CALLS: - None - -CALLED BY: - lexi - main -HISTORY: - initial coding November 1976 by D A Willcox of CAC - -*/ -eqin (str1, str2) -char *str1; -char *str2; +diag(level, msg, a, b) { - register char *s1; /* local pointer into first string */ - register char *s2; /* local pointer into second string */ - - s1 = str1; - s2 = str2; - while (*s1) { /* compare no further than end of first - string */ - if (*s2 == 0) /* check that second string isn't too short - */ - return (false); - if (*s1++ != *s2++) - return (false); + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); } - - return (true); -} - /* - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - -NAME: - cmp - -FUNCTION: - Compares two strings - -ALGORITHM: - Trivial - -PARAMETERS: - a Pointer to char First string to compare - b Pointer to char Second string to compare - -RETURNS: - -1 if a < b - 0 if a = b - 1 if a > b - -GLOBALS: - None - -CALLS: - None - -CALLED BY: - main - -HISTORY: - 1/7/77 D A Willcox of CAC Initial Coding -*/ -int cmp (a, b) -char *a; -char *b; -{ - register char *ta, - *tb; - - ta = a; - tb = b; - - while (*ta) { - if (*ta > *tb) - return (1); - if (*ta < *tb) - return (-1); - ++ta; - ++tb; + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); } - if (*tb) - return (1); - else - return (0); } diff --git a/usr/src/usr.bin/indent/lexi.c b/usr/src/usr.bin/indent/lexi.c index c18a544aeb..577ea5e6d7 100644 --- a/usr/src/usr.bin/indent/lexi.c +++ b/usr/src/usr.bin/indent/lexi.c @@ -5,88 +5,92 @@ */ #ifndef lint -static char sccsid[] = "@(#)lexi.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)lexi.c 5.2 (Berkeley) %G%"; #endif not lint -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - lexi - -FUNCTION: - This is the token scanner for indent - -ALGORITHM: - 1) Strip off intervening blanks and/or tabs. - 2) If it is an alphanumeric token, move it to the token buffer "token". - Check if it is a special reserved word that indent will want to - know about. - 3) Non-alphanumeric tokens are handled with a big switch statement. A - flag is kept to remember if the last token was a "unary delimiter", - which forces a following operator to be unary as opposed to binary. - -PARAMETERS: - None - -RETURNS: - An integer code indicating the type of token scanned. - -GLOBALS: - buf_ptr = - had_eof - last_u_d = Set to true iff this token is a "unary delimiter" - -CALLS: - fill_buffer - printf (lib) - -CALLED BY: - main - -NOTES: - Start of comment is passed back so that the comment can be scanned by - pr_comment. - - Strings and character literals are returned just like identifiers. - -HISTORY: - initial coding November 1976 D A Willcox of CAC - 1/7/77 D A Willcox of CAC Fix to provide proper handling - of "int a -1;" - -*/ +/*- + * + * Copyright (C) 1976 + * by the + * Board of Trustees + * of the + * University of Illinois + * + * All rights reserved + * + * + * NAME: + * lexi + * + * FUNCTION: + * This is the token scanner for indent + * + * ALGORITHM: + * 1) Strip off intervening blanks and/or tabs. + * 2) If it is an alphanumeric token, move it to the token buffer "token". + * Check if it is a special reserved word that indent will want to + * know about. + * 3) Non-alphanumeric tokens are handled with a big switch statement. A + * flag is kept to remember if the last token was a "unary delimiter", + * which forces a following operator to be unary as opposed to binary. + * + * PARAMETERS: + * None + * + * RETURNS: + * An integer code indicating the type of token scanned. + * + * GLOBALS: + * buf_ptr = + * had_eof + * ps.last_u_d = Set to true iff this token is a "unary delimiter" + * + * CALLS: + * fill_buffer + * printf (lib) + * + * CALLED BY: + * main + * + * NOTES: + * Start of comment is passed back so that the comment can be scanned by + * pr_comment. + * + * Strings and character literals are returned just like identifiers. + * + * HISTORY: + * initial coding November 1976 D A Willcox of CAC + * 1/7/77 D A Willcox of CAC Fix to provide proper handling + * of "int a -1;" + * + */ -/* Here we have the token scanner for indent. It scans off one token and - puts it in the global variable "token". It returns a code, indicating the - type of token scanned. */ +/* + * Here we have the token scanner for indent. It scans off one token and + * puts it in the global variable "token". It returns a code, indicating + * the type of token scanned. + */ #include "indent_globs.h"; #include "indent_codes.h"; - - +#include "ctype.h" #define alphanum 1 #define opchar 3 struct templ { - char *rwd; - int rwcode; + char *rwd; + int rwcode; }; -struct templ specials[] = +struct templ specials[100] = { "switch", 1, "case", 2, + "break", 0, "struct", 3, + "union", 3, + "enum", 3, "default", 2, "int", 4, "char", 4, @@ -100,18 +104,22 @@ struct templ specials[] = "static", 4, "global", 4, "extern", 4, + "void", 4, + "goto", 0, + "return", 0, "if", 5, "while", 5, "for", 5, "else", 6, "do", 6, - "sizeof", 0, + "sizeof", 7, 0, 0 }; -char chartype[128] = -{ /* this is used to facilitate the decision of what type - (alphanumeric, operator) each character is */ +char chartype[128] = +{ /* this is used to facilitate the decision + * of what type (alphanumeric, operator) + * each character is */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -130,336 +138,402 @@ char chartype[128] = 1, 1, 1, 0, 3, 0, 3, 0 }; -int last_nl = true; - /* this is true if the last thing scanned was a newline */ - - - -int lexi () { - register char *tok; - /* local pointer to next char in token */ - register int i; - /* local loop counter */ - register char *j; - /* used for searching thru list of reserved words */ - int unary_delim; - /* this is set to 1 if the current token forces a following operator to be - unary */ - static int last_code; - /* the last token type returned */ - static int l_struct; - /* set to 1 if the last token was 'struct' */ - int found_it; - int code; /* internal code to be returned */ - char qchar; /* the delimiter character for a string */ - - tok = token; /* point to start of place to save token */ + + + +int +lexi() +{ + register char *tok; /* local pointer to next char in token */ + int unary_delim; /* this is set to 1 if the current token + * + * forces a following operator to be unary */ + static int last_code; /* the last token type returned */ + static int l_struct; /* set to 1 if the last token was 'struct' */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + tok = token; /* point to start of place to save token */ unary_delim = false; - col_1 = last_nl; /* tell world that this token started in column - 1 iff the last thing scanned was nl */ - last_nl = false; - - while (*buf_ptr == ' ' || *buf_ptr == '\t') { - /* get rid of blanks */ - col_1 = false; /* leading blanks imply token is not in column 1 - */ + ps.col_1 = ps.last_nl; /* tell world that this token started in + * column 1 iff the last thing scanned was + * nl */ + ps.last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + ps.col_1 = false; /* leading blanks imply token is not in + * column 1 */ if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); } -/*----------------------------------------------------------*\ -| Scan an alphanumeric token -\*----------------------------------------------------------*/ + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr & 0177] == alphanum) { /* we have a character + * or number */ + register char *j; /* used for searching thru list of + * + * reserved words */ + register struct templ *p; - if (chartype[*buf_ptr & 0177] == alphanum) { - /* we have a character or number */ - while (chartype[*buf_ptr & 0177] == alphanum) { - /* copy it over */ + while (chartype[*buf_ptr & 0177] == alphanum) { /* copy it over */ *tok++ = *buf_ptr++; if (buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); } - *tok++ = '\0'; - - if (l_struct) { /* if last token was 'struct', then this token - should be treated as a declaration */ + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + ps.its_a_keyword = false; + ps.sizeof_keyword = false; + if (l_struct) { /* if last token was 'struct', then this + * token should be treated as a + * declaration */ l_struct = false; last_code = ident; - last_u_d = true; + ps.last_u_d = true; return (decl); } - - last_u_d = false; /* operator after indentifier is binary */ - - for (i = 0; specials[i].rwd != 0; ++i) { - /* this loop will check if the token is a keyword. if so, a following - operator is unary */ - last_code = ident; /* remember that this is the code we will return - */ - j = specials[i].rwd; - /* point at ith reserved word */ - tok = token; /* point at scanned toekn */ - found_it = true; /* set to false if not found */ - do { - if (*tok++ != *j) { - found_it = false; - break; - } - } while (*j++); - - if (found_it) { /* we have a keyword */ - last_u_d = true; - switch (specials[i].rwcode) { - case 1: /* it is a switch */ - return (swstmt); - case 2: /* a case or default */ - return (casestmt); - - case 3: /* a "struct" */ - l_struct = true; - /* Next time around, we will want to know that we have had - a 'struct' */ - case 4: /* one of the declaration keywords */ - if(p_l_follow) break; /* inside parens: cast */ - last_code = decl; - return (decl); - - case 5: /* if, while, for */ - return (sp_paren); - - case 6: /* do, else */ - return (sp_nparen); - - default: /* all others are treated like any other - identifier */ - return (ident); - } /* end of switch */ - } /* end of if (found_it) */ - + ps.last_u_d = false; /* Operator after indentifier is binary */ + last_code = ident; /* Remember that this is the code we will + * return */ + + /* + * This loop will check if the token is a keyword. + */ + for (p = specials; (j = p->rwd) != 0; p++) { + tok = token; /* point at scanned token */ + if (*j++ != *tok++ || *j++ != *tok++) + continue; /* This test depends on the fact that + * identifiers are always at least 1 + * character long (ie. the first two bytes + * of the identifier are always + * meaningful) */ + if (tok[-1] == 0) + break; /* If its a one-character identifier */ + while (*tok++ == *j) + if (*j++ == 0) + goto found_keyword; /* I wish that C had a multi-level + * break... */ + } + if (p->rwd) { /* we have a keyword */ + found_keyword: + ps.its_a_keyword = true; + ps.last_u_d = true; + switch (p->rwcode) { + case 1: /* it is a switch */ + return (swstmt); + case 2: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + if (ps.p_l_follow) + break; /* inside parens: cast */ + l_struct = true; + + /* + * Next time around, we will want to know that we have + * had a 'struct' + */ + case 4: /* one of the declaration keywords */ + if (ps.p_l_follow) { + ps.cast_mask |= 1 << ps.p_l_follow; + break; /* inside parens: cast */ + } + last_code = decl; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 7: + ps.sizeof_keyword = true; + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0 + && (buf_ptr[1] != ')' || buf_ptr[2] != ';')) { + strncpy(ps.procname, token, sizeof ps.procname - 1); + ps.in_parameter_declaration = 1; } - if (last_code == decl) /* if this is a declared variable, then - following sign is unary */ - last_u_d = true; /* will make "int a -1" work */ + /* + * The following hack attempts to guess whether or not the current + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr)) + && !ps.p_l_follow + && (ps.last_token == rparen || ps.last_token == semicolon || + ps.last_token == decl || + ps.last_token == lbrace || ps.last_token == rbrace)) { + ps.its_a_keyword = true; + ps.last_u_d = true; + last_code = decl; + return decl; + } + if (last_code == decl) /* if this is a declared variable, then + * following sign is unary */ + ps.last_u_d = true; /* will make "int a -1" work */ last_code = ident; - return (ident); /* the ident is not in the list */ - } /* end of procesing for alpanum character */ - - - -/*----------------------------------------------------------*\ -| Scan a non-alphanumeric token -\*----------------------------------------------------------*/ + return (ident); /* the ident is not in the list */ + } /* end of procesing for alpanum character */ + /* l l Scan a non-alphanumeric token */ - *tok++ = *buf_ptr; /* if it is only a one-character token, it is - moved here */ + *tok++ = *buf_ptr; /* if it is only a one-character token, it + * is moved here */ *tok = '\0'; if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); switch (*token) { - case '\n': - unary_delim = last_u_d; - last_nl = true; /* remember that we just had a newline */ + case '\n': + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember that we just had a newline */ code = (had_eof ? 0 : newline); - /* if data has been exausted, the newline is a dummy, and we should - return code to stop */ - break; - - case '\'': /* start of quoted character */ - qchar = '\''; /* remember final delimiter */ - goto copy_lit; /* and go to common literal code */ - case '"': /* start of string */ - qchar = '"'; + /* + * if data has been exausted, the newline is a dummy, and we + * should return code to stop + */ + break; - copy_lit: - do { /* copy the string */ - while (1) { /* move one character or [/] */ + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + if (troff) { + tok[-1] = '`'; + if (qchar == '"') + *tok++ = '`'; + *tok++ = BACKSLASH; + *tok++ = 'f'; + *tok++ = 'L'; + } + do { /* copy the string */ + while (1) { /* move one character or [/] */ if (*buf_ptr == '\n') { - /* check for unterminated literal */ - printf ("%d: Unterminated literal\n", line_no); + printf("%d: Unterminated literal\n", line_no); goto stop_lit; - /* Don't copy any more */ } - *tok = *buf_ptr++; if (buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); if (had_eof || ((tok - token) > (bufsize - 2))) { - printf ("Unterminated literal\n"); + printf("Unterminated literal\n"); ++tok; goto stop_lit; - /* get outof literal copying loop */ + /* get outof literal copying loop */ } - - if (*tok == '\\') { - /* if escape, copy extra char */ - if (*buf_ptr == '\n') - /* check for escaped newline */ + if (*tok == BACKSLASH) { /* if escape, copy extra + * char */ + if (*buf_ptr == '\n') /* check for escaped + * newline */ ++line_no; - *(++tok) = *buf_ptr++; - ++tok; /* we must increment this again because we - copied two chars */ + if (troff) { + *++tok = BACKSLASH; + if (*buf_ptr == BACKSLASH) + *++tok = BACKSLASH; + } + *++tok = *buf_ptr++; + ++tok; /* we must increment this again because we + * copied two chars */ if (buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); } else - break; /* we copied one character */ - } /* end of while (1) */ + break; /* we copied one character */ + } /* end of while (1) */ } while (*tok++ != qchar); - - stop_lit: + if (troff) { + tok[-1] = BACKSLASH; + *tok++ = 'f'; + *tok++ = 'R'; + *tok++ = '\''; + if (qchar == '"') + *tok++ = '\''; + } + stop_lit: code = ident; break; - case ('('): - case ('['): + case ('('): + case ('['): unary_delim = true; code = lparen; break; - case (')'): - case (']'): + case (')'): + case (']'): code = rparen; break; - case '#': - unary_delim = last_u_d; + case '#': + unary_delim = ps.last_u_d; code = preesc; break; - case '?': + case '?': unary_delim = true; code = question; break; - case (':'): + case (':'): code = colon; unary_delim = true; break; - case (';'): + case (';'): unary_delim = true; code = semicolon; break; - case ('{'): + case ('{'): unary_delim = true; - code = lbrace; + + /* + * if (ps.in_or_st) ps.block_init = 1; + */ + code = ps.block_init ? lparen : lbrace; break; - case ('}'): + case ('}'): unary_delim = true; - code = rbrace; + code = ps.block_init ? rparen : rbrace; break; - case 014: /* a form feed */ - unary_delim = last_u_d; - last_nl = true; /* remember this so we can set 'col_1' right */ + case 014: /* a form feed */ + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember this so we can set 'ps.col_1' + * right */ code = form_feed; break; - case (','): + case (','): unary_delim = true; code = comma; break; - case '.': + case '.': unary_delim = false; code = period; break; - case '-': - case '+': /* check for -, +, --, ++ */ - code = (last_u_d ? unary_op : binary_op); + case '-': + case '+': /* check for -, +, --, ++ */ + code = (ps.last_u_d ? unary_op : binary_op); unary_delim = true; if (*buf_ptr == token[0]) { - /* check for doubled character */ + /* check for doubled character */ *tok++ = *buf_ptr++; - /* buffer overflow will be checked at end of loop */ + /* buffer overflow will be checked at end of loop */ if (last_code == ident || last_code == rparen) { - code = (last_u_d ? unary_op : postop); - /* check for following ++ or -- */ + code = (ps.last_u_d ? unary_op : postop); + /* check for following ++ or -- */ unary_delim = false; } } - else - if (*buf_ptr == '>' || *buf_ptr == '=') - /* check for operator -> or += */ - *tok++ = *buf_ptr++; - /* buffer overflow will be checked at end of switch */ + else if (*buf_ptr == '=') + /* check for operator += */ + *tok++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *tok++ = *buf_ptr++; + code = unary_op; + unary_delim = false; + ps.want_blank = false; + } + /* buffer overflow will be checked at end of switch */ break; - case '=': - if (chartype[*buf_ptr] == opchar) { - /* we have two char assignment */ - *tok++ = *buf_ptr; - /* move second character */ - if (++buf_ptr >= buf_end) - fill_buffer (); + case '=': + if (ps.in_or_st) + ps.block_init = 1; + if (chartype[*buf_ptr] == opchar) { /* we have two char + * assignment */ + tok[-1] = *buf_ptr++; + if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr) + *tok++ = *buf_ptr++; + *tok++ = '='; /* Flip =+ to += */ + *tok = 0; } - code = binary_op; unary_delim = true; - if (token[1] != '<' && token[1] != '>') - /* check for possible 3 char operator */ - break; - /* can drop thru!!! */ + break; + /* can drop thru!!! */ - case '>': - case '<': - case '!': /* ops like <, <<, <=, !=, etc */ + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { *tok++ = *buf_ptr; if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); } - if (*buf_ptr == '=') - *tok++ = *buf_ptr++; - code = (last_u_d ? unary_op : binary_op); + *tok++ = *buf_ptr++; + code = (ps.last_u_d ? unary_op : binary_op); unary_delim = true; break; - default: + default: if (token[0] == '/' && *buf_ptr == '*') { - /* it is start of comment */ + /* it is start of comment */ *tok++ = '*'; if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); code = comment; - unary_delim = last_u_d; + unary_delim = ps.last_u_d; break; } - - while (*(tok - 1) == *buf_ptr || *buf_ptr=='=') { - /* handle ||, &&, etc, and also things as in int *****i */ + while (*(tok - 1) == *buf_ptr || *buf_ptr == '=') { + /* handle ||, &&, etc, and also things as in int *****i */ *tok++ = *buf_ptr; if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); } - - - code = (last_u_d ? unary_op : binary_op); + code = (ps.last_u_d ? unary_op : binary_op); unary_delim = true; - } /* end of switch */ - + } /* end of switch */ if (code != newline) { l_struct = false; last_code = code; } - - if (buf_ptr >= buf_end) /* check for input buffer empty */ - fill_buffer (); - last_u_d = unary_delim; - *tok = '\0'; /* null terminate the token */ + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + ps.last_u_d = unary_delim; + *tok = '\0'; /* null terminate the token */ return (code); }; + +/* Add the given keyword to the keyword table, using val as the keyword type + */ +addkey (key, val) +char *key; +{ + register struct templ *p = specials; + while (p->rwd) + if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) + return; + else + p++; + if (p >= specials + sizeof specials / sizeof specials[0]) + return; /* For now, table overflows are silently + ignored */ + p->rwd = key; + p->rwcode = val; + p[1].rwd = 0; + p[1].rwcode = 0; + return; +} diff --git a/usr/src/usr.bin/indent/parse.c b/usr/src/usr.bin/indent/parse.c index 89d8de2022..dcd929fb71 100644 --- a/usr/src/usr.bin/indent/parse.c +++ b/usr/src/usr.bin/indent/parse.c @@ -5,410 +5,331 @@ */ #ifndef lint -static char sccsid[] = "@(#)parse.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)parse.c 5.2 (Berkeley) %G%"; #endif not lint -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -FILE NAME: - parse.c - -PURPOSE: - Contains the routines which keep track of the parse stack. - -GLOBALS: - p_stack = The parse stack, set by both routines - il = Stack of indentation levels, set by parse - cstk = Stack of case statement indentation levels, set by parse - tos = Pointer to top of stack, set by both routines. - -FUNCTIONS: - parse - reduce -*/ -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - parse - -FUNCTION: - Parse is given one input which is a "maxi token" just scanned from - input. Maxi tokens are signifigant constructs such as else, {, do, - if (...), etc. Parse works with reduce to maintain a parse stack - of these constructs. Parse is responsible for the "shift" portion - of the parse algorithm, and reduce handles the "reduce" portion. - -ALGORITHM: - 1) If there is "ifstmt" on the stack and input is anything other than - an else, then change the top of stack (TOS) to . Do a reduce. - 2) Use a switch statement to implement the following shift operations: - - TOS___ Input_____ Stack_____ Note____ - decl decl nothing - anything else decl decl - "dostmt" while (..) Change TOS to - anything else while (..) while - "ifstmt" else Change TOS to "ifelse" - { } Change { - to - switch (..) switch - do do - for(..) for - ; - { { - -PARAMETERS: - tk An integer code for the maxi token scanned - -RETURNS: - Nothing - -GLOBALS: - break_comma = Set to true when in a declaration but not initialization - btype_2 - case_ind = - cstk = - i_l_follow = - il = Stack of indentation levels - ind_level = - p_stack = Stack of token codes - search_brace = Set to true if we must look for possibility of moving a - brace - tos = Pointer to top of p_stack, il, and cstk - -CALLS: - printf (lib) - reduce - -CALLED BY: - main - -HISTORY: - initial coding November 1976 D A Willcox of CAC - -*/ +/*- + * + * Copyright (C) 1976 + * by the + * Board of Trustees + * of the + * University of Illinois + * + * All rights reserved + * + * + * FILE NAME: + * parse.c + * + * PURPOSE: + * Contains the routines which keep track of the parse stack. + * + * GLOBALS: + * ps.p_stack = The parse stack, set by both routines + * ps.il = Stack of indentation levels, set by parse + * ps.cstk = Stack of case statement indentation levels, set by parse + * ps.tos = Pointer to top of stack, set by both routines. + * + * FUNCTIONS: + * parse + * reduce + */ +/*- + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: parse + * + * FUNCTION: Parse is given one input which is a "maxi token" just scanned + * from input. Maxi tokens are signifigant constructs such as else, {, + * do, if (...), etc. Parse works with reduce to maintain a parse stack + * of these constructs. Parse is responsible for the "shift" portion of + * the parse algorithm, and reduce handles the "reduce" portion. + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ #include "./indent_globs.h"; #include "./indent_codes.h"; -int p_stack[50] = stmt; - /* this is the parser's stack */ -int il[50]; /* this stack stores indentation levels */ -int cstk[50]; /* used to store case stmt indentation levels */ -int tos = 0; /* pointer to top of stack */ -parse (tk) -int tk; /* the code for the construct scanned */ +parse(tk) + int tk; /* the code for the construct scanned */ { - int i; + int i; #ifdef debug - printf ("%2d - %s\n", tk, token); + printf("%2d - %s\n", tk, token); #endif - while (p_stack[tos] == ifhead && tk != elselit) { - /* true if we have an if without an else */ - p_stack[tos] = stmt; /* apply the if(..) stmt ::= stmt reduction */ - reduce (); /* see if this allows any reduction */ + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ } - switch (tk) { /* go on and figure out what to do with the - input */ - - case decl: /* scanned a declaration word */ - search_brace = btype_2; - /* indicate that following brace should be on same line */ - if (p_stack[tos] != decl) { - /* only put one declaration onto stack */ - break_comma = true; - /* while in declaration, newline should be forced after comma */ - p_stack[++tos] = decl; - il[tos] = i_l_follow; - - if (ljust_decl) { - /* only do if we want left justified declarations */ - ind_level = 0; - for (i = tos - 1; i > 0; --i) - if (p_stack[i] == decl) - ++ind_level; - /* indentation is number of declaration levels deep we are */ - i_l_follow = ind_level; + switch (tk) { /* go on and figure out what to do with + * the input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration onto + * stack */ + break_comma = true; /* while in declaration, newline + * should be forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) { /* only do if we want left + * justified declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number + * of declaration levels + * deep we are */ + ps.i_l_follow = ps.ind_level; } } break; - case ifstmt: /* scanned if (...) */ - case dolit: /* 'do' */ - case forstmt: /* for (...) */ - p_stack[++tos] = tk; - il[tos] = ind_level = i_l_follow; - ++i_l_follow; /* subsequent statements should be indented 1 */ - search_brace = btype_2; + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + ps.i_l_follow = ps.il[ps.tos]; + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be + * indented 1 */ + ps.search_brace = btype_2; break; - case lbrace: /* scanned { */ - break_comma = false; - /* don't break comma in an initial list */ - if (p_stack[tos] == stmt || p_stack[tos] == decl - || p_stack[tos] == stmtl) - ++i_l_follow; /* it is a random, isolated stmt group or a - declaration */ + case lbrace: /* scanned { */ + break_comma = false;/* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or + * a declaration */ else { if (s_code == e_code) { - /* only do this if there is nothing on the line */ - --ind_level; - /* it is a group as part of a while, for, etc. */ - if (p_stack[tos] == swstmt) - --ind_level; - /* for a switch, brace should be two levels out from the code - */ + /* only do this if there is nothing on the line */ + --ps.ind_level; + /* it is a group as part of a while, for, etc. */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from + * the code + */ } } - p_stack[++tos] = lbrace; - il[tos] = ind_level; - p_stack[++tos] = stmt; - /* allow null stmt between braces */ - il[tos] = i_l_follow; + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; break; - case whilestmt: /* scanned while (...) */ - if (p_stack[tos] == dohead) { - /* it is matched with do stmt */ - ind_level = i_l_follow = il[tos]; - p_stack[++tos] = whilestmt; - il[tos] = ind_level = i_l_follow; + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; } - else { /* it is a while loop */ - p_stack[++tos] = whilestmt; - il[tos] = i_l_follow; - ++i_l_follow; - search_brace = btype_2; + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; } break; - case elselit: /* scanned an else */ + case elselit: /* scanned an else */ - if (p_stack[tos] != ifhead) { - printf ("%d: Unmatched else\n", line_no); - } + if (ps.p_stack[ps.tos] != ifhead) + diag(1,"Unmatched 'else'"); else { - ind_level = il[tos]; - /* indentation for else should be same as for if */ - i_l_follow = ind_level + 1; - /* everything following should be in 1 level */ - p_stack[tos] = elsehead; - /* remember if with else */ - search_brace = btype_2; + ps.ind_level = ps.il[ps.tos]; /* indentation for else should be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2; } break; - case rbrace: /* scanned a } */ - /* stack should have or */ - if (p_stack[tos - 1] == lbrace) { - ind_level = i_l_follow = il[--tos]; - p_stack[tos] = stmt; + case rbrace: /* scanned a } */ + /* stack should have or */ + if (ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; } - else { - printf ("%d: Stmt nesting error\n", line_no); - } - + else + diag(1,"Stmt nesting error."); break; - case swstmt: /* had switch (...) */ - p_stack[++tos] = swstmt; - cstk[tos] = case_ind; - /* save current case indent level */ - il[tos] = i_l_follow; - case_ind = i_l_follow + 1; - /* cases should be one level down from switch */ - i_l_follow + = 2; /* statements should be two levels in */ - search_brace = btype_2; + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow + = ps.case_indent + 1; /* statements should be + * two levels in */ + ps.search_brace = btype_2; break; - case semicolon: /* this indicates a simple stmt */ - break_comma = false; - /* turn off flag to break after commas in a declaration */ - p_stack[++tos] = stmt; - il[tos] = ind_level; + case semicolon: /* this indicates a simple stmt */ + break_comma = false;/* turn off flag to break after commas in + * a declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; break; - default: /* this is an error */ - printf ("%d: Unknown code to parser - %d\n", line_no, tk); + default: /* this is an error */ + diag(1,"Unknown code to parser"); return; - } /* end of switch */ + } /* end of switch */ - reduce (); /* see if any reduction can be done */ + reduce(); /* see if any reduction can be done */ #ifdef debug - for (i = 1; i <= tos; ++i) - printf ("(%d %d)", p_stack[i], il[i]); - printf ("\n"); + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); #endif return; } - /* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - reduce - -FUNCTION: - Implements the reduce part of the parsing algorithm - -ALGORITHM: - The following reductions are done. Reductions are repeated until no - more are possible. - - Old___ TOS___ New___ TOS___ - - - do "dostmt" - if "ifstmt" - switch - decl - "ifelse" - for - while - "dostmt" while - - On each reduction, i_l_follow (the indentation for the following line) - is set to the indentation level associated with the old TOS. - -PARAMETERS: - None - -RETURNS: - Nothing - -GLOBALS: - cstk - i_l_follow = - il - p_stack = - tos = - -CALLS: - None - -CALLED BY: - parse - -HISTORY: - initial coding November 1976 D A Willcox of CAC - -*/ + /* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS do + * "dostmt" if "ifstmt" switch + * decl "ifelse" for + * while "dostmt" while + * + * On each reduction, ps.i_l_follow (the indentation for the following line) is + * set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse  + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ /*----------------------------------------------*\ -| REDUCTION PHASE + * | REDUCTION PHASE \*----------------------------------------------*/ -reduce () { +reduce() { - register int i; - /* local looping variable */ + register int i; - for (;;) { /* keep looping until there is nothing left to - reduce */ + for (;;) { /* keep looping until there is nothing + * left to reduce */ - switch (p_stack[tos]) { + switch (ps.p_stack[ps.tos]) { case stmt: - switch (p_stack[tos - 1]) { + switch (ps.p_stack[ps.tos - 1]) { case stmt: case stmtl: - /* stmtl stmt or stmt stmt */ - p_stack[--tos] = stmtl; + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; break; - case dolit: - /* */ - p_stack[--tos] = dohead; - i_l_follow = il[tos]; + case dolit: /* */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; break; case ifstmt: - /* */ - p_stack[--tos] = ifhead; - for (i = tos - 1; + /* */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; ( - p_stack[i] != stmt + ps.p_stack[i] != stmt && - p_stack[i] != stmtl + ps.p_stack[i] != stmtl && - p_stack[i] != lbrace + ps.p_stack[i] != lbrace ); --i); - i_l_follow = il[i]; - /* for the time being, we will assume that there is no else - on this if, and set the indentation level accordingly. - If an else is scanned, it will be fixed up later */ + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there + * is no else on this if, and set the indentation + * level accordingly. If an else is scanned, it + * will be fixed up later + */ break; case swstmt: - /* */ - case_ind = cstk[tos - 1]; + /* */ + case_ind = ps.cstk[ps.tos - 1]; - case decl: /* finish of a declaration */ + case decl: /* finish of a declaration */ case elsehead: - /* < else> */ + /* < else> */ case forstmt: - /* */ + /* */ case whilestmt: - /* */ - p_stack[--tos] = stmt; - i_l_follow = il[tos]; + /* */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; break; - default: /* */ + default: /* */ return; - } /* end of section for on top of stack */ + } /* end of section for on top of + * stack */ break; - case whilestmt: /* while (...) on top */ - if (p_stack[tos - 1] == dohead) { - /* it is termination of a do while */ - p_stack[--tos] = stmt; + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.p_stack[--ps.tos] = stmt; break; } else return; - default: /* anything else on top */ + default: /* anything else on top */ return; - } /* end of big switch */ - - } /* end of reduction phase for (;;) */ + } + } } diff --git a/usr/src/usr.bin/indent/pr_comment.c b/usr/src/usr.bin/indent/pr_comment.c index 2032a303fd..9c08f5c202 100644 --- a/usr/src/usr.bin/indent/pr_comment.c +++ b/usr/src/usr.bin/indent/pr_comment.c @@ -5,364 +5,381 @@ */ #ifndef lint -static char sccsid[] = "@(#)pr_comment.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)pr_comment.c 5.2 (Berkeley) %G%"; #endif not lint -/* - - Copyright (C) 1976 - by the - Board of Trustees - of the - University of Illinois - - All rights reserved - - -NAME: - pr_comment - -FUNCTION: - This routine takes care of scanning and printing comments. - -ALGORITHM: - 1) Decide where the comment should be aligned, and if lines should - be broken. - 2) If lines should not be broken and filled, just copy up to end of - comment. - 3) If lines should be filled, then scan thru input_buffer copying - characters to com_buf. Remember where the last blank, tab, or - newline was. When line is filled, print up to last blank and - continue copying. - -PARAMETERS: - None - -RETURNS: - Nothing - -GLOBALS: - combuf = - s_com - e_com = - - buf_ptr = - buf_end +/*- + * + * Copyright (C) 1976 + * by the + * Board of Trustees + * of the + * University of Illinois + * + * All rights reserved + * + * + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ - bl_line - col_1 - com_col = - com_ind - decl_com_ind - decl_on_line - had_eof - ind_level - ind_size - line_no = - max_col - out_com = Count number of comments - unindent_displace - use_ff = - -CALLS: - count_spaces - dump_line - fill_buffer - printf (lib) - -CALLED BY: - main - -HISTORY: - November 1976 D A Willcox of CAC Initial coding - 12/6/76 D A Willcox of CAC Modification to handle - UNIX-style comments - -*/ - -/* this routine processes comments. It makes an attempt to keep comments from - going over the max line length. If a line is too long, it moves everything - from the last blank to the next comment line. Blanks and tabs from the - beginning of the input line are removed */ +/* + * this routine processes comments. It makes an attempt to keep comments + * from going over the max line length. If a line is too long, it moves + * everything from the last blank to the next comment line. Blanks and + * tabs from the beginning of the input line are removed + */ #include "indent_globs.h"; -pr_comment () { - int now_col; - /* column we are in now */ - int box_com; - /* set to true when we are in a "boxed" comment. In that case, the first - non-blank char should be lined up with the / in /* */ - int col_1_com; - /* this comment should not be touched */ - char *last_bl; - /* points to the last blank in the output buffer */ - char achar; - char *t_ptr; /* used for movinf string */ - int unix_comment; - /* tri-state variable used to decide if it is a unix-style comment. 0 means - only blanks since /*, 1 means regular style comment, 2 means unix style - comment */ - - - last_bl = 0; /* no blanks found so far */ - box_com = col_1_com = false; - /* at first, assume that we are not in a boxed comment or some other comment - that should not be touched */ - ++out_coms; /* keep track of number of comments */ - unix_comment = 0; /* set flag to let us figure out if there is a - unix-style comment */ - -/*----------------------------------------------------------*\ -| Figure where to align and how to treat the comment -\*----------------------------------------------------------*/ - - if (col_1) { /* if comment starts in column 1 it should not - be touched */ - col_1_com = box_com = true; - com_col = 1; - } - else { - if (*buf_ptr == '-') - box_com = true; /* a comment with a '-' immediately after the /* - is assumed to be a boxed comment */ - if ( /* bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { - /* klg: check only if this line is blank */ - /* - * If this (*and previous lines are*) blank, - * don't put comment way out at left - */ - com_col = (ind_level - unindent_displace) * ind_size + 1; - if (com_col <= 1) - com_col = 2; +pr_comment() +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + int col_1_com; /* this comment should not be touched */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char achar; + char *t_ptr; /* used for moving string */ + int unix_comment; /* tri-state variable used to decide if it + * is a unix-style comment. 0 means only + * blanks since /*, 1 means regular style + * comment, 2 means unix style comment */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + /* + * int ps.last_nl = 0; /* true iff the last significant + * thing weve seen is a newline + */ + int one_liner = 1; /* true iff this comment is a one-liner */ + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = 0; /* no blanks found so far */ + ps.box_com = col_1_com = false; /* at first, assume that we are + * not in a boxed comment or some + * other comment that should not + * be touched */ + ++ps.out_coms; /* keep track of number of comments */ + unix_comment = 1; /* set flag to let us figure out if there + * is a unix-style comment ** DISABLED: + * use 0 to reenable this hack! */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in + * column 1 it should not + * be touched */ + col_1_com = ps.box_com = true; + ps.com_col = 1; + } else { + if (*buf_ptr == '-' || *buf_ptr == '*') { + ps.box_com = true; /* a comment with a '-' or '*' immediately + * after the /* is assumed to be a boxed + * comment */ + col_1_com = true; + break_delim = 0; } - else { - com_col = (decl_on_line || ind_level == 0 ? decl_com_ind : com_ind); + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment + * way out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } else { + register target_col; + break_delim = 0; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col < target_col) + ps.com_col = ((target_col + 7) & ~7) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; } } - - *e_com++ = '/'; /* put '/*' into buffer */ + if (ps.box_com) { + buf_ptr[-2] = 0; + ps.n_comment_delta = 1 - count_spaces(1, in_buffer); + ps.comment_delta = 0; + buf_ptr[-2] = '/'; + } else { + ps.n_comment_delta = 0; + ps.comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/*' into buffer */ *e_com++ = '*'; - if (*buf_ptr != ' ' && !box_com) + if (*buf_ptr != ' ' && !ps.box_com) *e_com++ = ' '; *e_com = '\0'; - now_col = count_spaces (com_col, s_com); - /* figure where what column we would be in if we printed the comment now */ - - -/*----------------------------------------------------------*\ -| Start to copy the comment -\*----------------------------------------------------------*/ - - while (1) { /* this loop will go until the comment is copied - */ - switch (*buf_ptr) { /* this checks for various spcl cases */ - case 014: /* check for a form feed */ - if (!box_com) {/* in a text comment, break the line here */ - use_ff = true; - /* fix so dump_line uses a form feed */ - dump_line (); + now_col = count_spaces(ps.com_col, s_com); /* figure what column we + * would be in if we + * printed the comment now */ + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + if (*buf_ptr > 040 && *buf_ptr != '*') + ps.last_nl = 0; + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + if (!ps.box_com) { /* in a text comment, break the + * line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); last_bl = 0; *e_com++ = ' '; + *e_com++ = '*'; *e_com++ = ' '; - *e_com++ = ' '; - do { /* get rid of leading blanks */ - if (++buf_ptr >= buf_end) - fill_buffer (); - } while (*buf_ptr == ' ' || *buf_ptr == '\t'); - } - else { + while (*++buf_ptr == ' ' || *buf_ptr == '\t'); + } else { if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); *e_com++ = 014; } - break; - case '\n': - if (had_eof) { /* check for unexpected eof */ - printf ("Unterminated comment\n"); + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); *e_com = '\0'; - dump_line (); + dump_line(); return; } - - if (box_com) { /* if this is a boxed comment, we don't ignore - the newline */ - *e_com = '\0'; - dump_line (); - ++line_no; - now_col = com_col; - - if (!col_1_com) { - /* if merely a boxed comment, we should line up first - non-blank character */ - do { /* flush leading non-blanks */ - if (++buf_ptr >= buf_end) - fill_buffer (); - } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + one_liner = 0; + if (ps.box_com || ps.last_nl) { /* if this is a boxed + * comment, we dont ignore + * the newline */ + if (s_com == e_com) { + *e_com++ = ' '; + *e_com++ = ' '; } - else { /* make sure we at least flush the blank */ - if (++buf_ptr >= buf_end) - fill_buffer (); + *e_com = '\0'; + if (!ps.box_com && e_com - s_com > 3) { + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + dump_line(); + *e_com++ = ' '; + *e_com++ = ' '; } - - break; - } - - if (unix_comment != 1) { - /* we are in unix_style comment */ + dump_line(); + now_col = ps.com_col; + } else { + ps.last_nl = 1; + if (unix_comment != 1) { /* we not are in + * unix_style comment */ if (unix_comment == 0 && s_code == e_code) { - /* if it is a UNIX-style comment, ignore the requirement - that pervious line be blank for unindention */ - com_col = (ind_level - unindent_displace) * ind_size + 1; - if (com_col <= 1) - com_col = 2; + /* + * if it is a UNIX-style comment, ignore the + * requirement that previous line be blank for + * unindention + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + if (ps.com_col <= 1) + ps.com_col = 2; } - - unix_comment = 2; - /* permanently remember that we are in this type of comment */ - dump_line (); + unix_comment = 2; /* permanently remember that we + * are in this type of comment */ + dump_line(); ++line_no; - now_col = com_col; + now_col = ps.com_col; *e_com++ = ' '; - /* fix so that the star at the start of the line will line up - */ - do /* flush leading white space */ + /* + * fix so that the star at the start of the line will + * line up + */ + do /* flush leading white space */ if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); while (*buf_ptr == ' ' || *buf_ptr == '\t'); break; } - if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') last_bl = e_com - 1; - /* if there was a space at the end of the last line, remember where - it was */ - else { /* otherwise, insert one */ + /* + * if there was a space at the end of the last line, + * remember where it was + */ + else { /* otherwise, insert one */ last_bl = e_com; *e_com++ = ' '; ++now_col; } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start + * of next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } else if (++buf_ptr >= buf_end) fill_buffer(); + break; /* end of case for newline */ - ++line_no; /* keep track of input line number */ - do { /* copy any blanks and/or tabs at start of next - line */ - if (++buf_ptr >= buf_end) - fill_buffer (); - } while (*buf_ptr == ' ' || *buf_ptr == '\t'); - - break; /* end of case for newline */ - - case '*': /* must check for possibility of being at end of - comment */ - if (++buf_ptr >= buf_end) - /* get to next char after * */ - fill_buffer (); + case '*': /* must check for possibility of being at + * end of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); - if (unix_comment == 0) - /* set flag to show we are not in unix-style - comment */ + if (unix_comment == 0) /* set flag to show we are not in + * unix-style comment */ unix_comment = 1; - if (*buf_ptr == '/') { - /* it is the end!!! */ + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: if (++buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); - if (*(e_com - 1) != ' ' && !box_com) { - /* insure blank before end */ + if (*(e_com - 1) != ' ' && !ps.box_com) { /* insure blank before + * end */ *e_com++ = ' '; ++now_col; } - - if (now_col > max_col - 2 && !box_com) { - /* check if star-slash will go over line */ + if (break_delim == 1 && !one_liner && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (break_delim == 2 && e_com > s_com + 3 + /* now_col > adj_max_col - 2 && !ps.box_com */ ) { *e_com = '\0'; - /* it will */ - dump_line (); - now_col = com_col; + dump_line(); + now_col = ps.com_col; } - *e_com++ = '*'; - /* move end of comment */ *e_com++ = '/'; *e_com = '\0'; - return; /* we is done */ - } /* end of end of comment */ - - - else { /* handle isolated '*' */ + ps.just_saw_decl = l_just_saw_decl; + return; + } else { /* handle isolated '*' */ *e_com++ = '*'; ++now_col; - break; } - /* end of processing of * */ - - default: /* we have a random char */ + break; + default: /* we have a random char */ if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') - unix_comment = 1; - /* we are not in unix-style comment */ + unix_comment = 1; /* we are not in unix-style + * comment */ *e_com = *buf_ptr++; if (buf_ptr >= buf_end) - fill_buffer (); + fill_buffer(); - if (*e_com == '\t') - /* keep track of column */ + if (*e_com == '\t') /* keep track of column */ now_col = ((now_col - 1) & tabmask) + tabsize + 1; + else if (*e_com == '\b') /* this is a backspace */ + --now_col; else - if (*e_com == '') - /* this is a backspace */ - --now_col; - else - ++now_col; + ++now_col; if (*e_com == ' ' || *e_com == '\t') last_bl = e_com; - /* remember we saw a blank */ + /* remember we saw a blank */ ++e_com; - if (now_col > max_col && !box_com && unix_comment == 1) { - /* the comment is too long, it must be broken up */ - if (last_bl == 0) { - /* we have seen no blanks */ - printf ("%d: Comment too long\n", line_no); - last_bl = e_com; - /* fake it */ + if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') { + /* the comment is too long, it must be broken up */ + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (last_bl == 0) { /* we have seen no blanks */ + last_bl = e_com; /* fake it */ *e_com++ = ' '; } - - *e_com = '\0'; - /* print what we have */ + *e_com = '\0'; /* print what we have */ *last_bl = '\0'; + while (last_bl > s_com && last_bl[-1] < 040) + *--last_bl = 0; e_com = last_bl; - dump_line (); + dump_line(); - *e_com++ = ' '; - /* add blanks for continuation */ + *e_com++ = ' '; /* add blanks for continuation */ *e_com++ = ' '; *e_com++ = ' '; t_ptr = last_bl + 1; last_bl = 0; - while (*t_ptr != '\0') { - /* move unprinted pare of comment down in buffer */ - if (*t_ptr == ' ' || *t_ptr == '\t') - last_bl = e_com; - *e_com++ = *t_ptr++; + if (t_ptr >= e_com) { + while (*t_ptr == ' ' || *t_ptr == '\t') + t_ptr++; + while (*t_ptr != '\0') { /* move unprinted part + * of comment down in + * buffer */ + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } } - *e_com = '\0'; - now_col = count_spaces (com_col, s_com); - /* recompute current position */ - } /* end of code for splitting a comment */ - break; /* end of default case */ - - - } /* end of switch */ - - } /* end of while (1) */ -} /* end of pr_comment */ + now_col = count_spaces(ps.com_col, s_com); /* recompute current + * position */ + } + break; + } + } +} -- 2.20.1