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