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