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