indent.c revision 1.23 1 1.23 sevan /* $NetBSD: indent.c,v 1.23 2016/09/05 00:40:29 sevan 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.23 sevan __RCSID("$NetBSD: indent.c,v 1.23 2016/09/05 00:40:29 sevan 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.6 lukem case form_feed:
350 1.6 lukem break; /* form feeds and newlines found here
351 1.6 lukem * will be ignored */
352 1.6 lukem
353 1.6 lukem case lbrace: /* this is a brace that starts the
354 1.6 lukem * compound stmt */
355 1.6 lukem if (sc_end == 0) { /* ignore buffering if a
356 1.22 ginsbach * comment wasn't stored
357 1.6 lukem * up */
358 1.6 lukem ps.search_brace = false;
359 1.6 lukem goto check_type;
360 1.6 lukem }
361 1.6 lukem if (btype_2) {
362 1.6 lukem save_com[0] = '{'; /* we either want to put
363 1.6 lukem * the brace right after
364 1.6 lukem * the if */
365 1.6 lukem goto sw_buffer; /* go to common code to
366 1.6 lukem * get out of this loop */
367 1.6 lukem }
368 1.6 lukem case comment: /* we have a comment, so we must copy
369 1.6 lukem * it into the buffer */
370 1.6 lukem if (!flushed_nl || sc_end != 0) {
371 1.6 lukem if (sc_end == 0) { /* if this is the first
372 1.6 lukem * comment, we must set
373 1.6 lukem * up the buffer */
374 1.6 lukem save_com[0] = save_com[1] = ' ';
375 1.6 lukem sc_end = &(save_com[2]);
376 1.6 lukem } else {
377 1.6 lukem *sc_end++ = '\n'; /* add newline between
378 1.6 lukem * comments */
379 1.6 lukem *sc_end++ = ' ';
380 1.6 lukem --line_no;
381 1.6 lukem }
382 1.6 lukem *sc_end++ = '/'; /* copy in start of
383 1.6 lukem * comment */
384 1.6 lukem *sc_end++ = '*';
385 1.6 lukem
386 1.6 lukem for (;;) { /* loop until we get to
387 1.6 lukem * the end of the
388 1.6 lukem * comment */
389 1.6 lukem *sc_end = *buf_ptr++;
390 1.6 lukem if (buf_ptr >= buf_end)
391 1.6 lukem fill_buffer();
392 1.6 lukem
393 1.6 lukem if (*sc_end++ == '*' && *buf_ptr == '/')
394 1.6 lukem break; /* we are at end of
395 1.6 lukem * comment */
396 1.6 lukem
397 1.6 lukem if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer
398 1.6 lukem * overflow */
399 1.6 lukem diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
400 1.6 lukem fflush(output);
401 1.6 lukem exit(1);
402 1.6 lukem }
403 1.6 lukem }
404 1.6 lukem *sc_end++ = '/'; /* add ending slash */
405 1.6 lukem if (++buf_ptr >= buf_end) /* get past / in buffer */
406 1.6 lukem fill_buffer();
407 1.6 lukem break;
408 1.6 lukem }
409 1.6 lukem default: /* it is the start of a normal
410 1.6 lukem * statment */
411 1.6 lukem if (flushed_nl) /* if we flushed a newline,
412 1.6 lukem * make sure it is put back */
413 1.6 lukem force_nl = true;
414 1.6 lukem if ((type_code == sp_paren && *token == 'i'
415 1.6 lukem && last_else && ps.else_if) ||
416 1.6 lukem (type_code == sp_nparen && *token == 'e'
417 1.6 lukem && e_code != s_code && e_code[-1] == '}'))
418 1.6 lukem force_nl = false;
419 1.6 lukem
420 1.6 lukem if (sc_end == 0) { /* ignore buffering if
421 1.22 ginsbach * comment wasn't saved
422 1.6 lukem * up */
423 1.6 lukem ps.search_brace = false;
424 1.6 lukem goto check_type;
425 1.6 lukem }
426 1.6 lukem if (force_nl) { /* if we should insert a nl
427 1.6 lukem * here, put it into the
428 1.6 lukem * buffer */
429 1.6 lukem force_nl = false;
430 1.6 lukem --line_no; /* this will be
431 1.6 lukem * re-increased when the
432 1.6 lukem * nl is read from the
433 1.6 lukem * buffer */
434 1.6 lukem *sc_end++ = '\n';
435 1.6 lukem *sc_end++ = ' ';
436 1.6 lukem if (verbose && !flushed_nl) /* print error msg if
437 1.6 lukem * the line was not
438 1.6 lukem * already broken */
439 1.6 lukem diag(0, "Line broken");
440 1.6 lukem flushed_nl = false;
441 1.6 lukem }
442 1.6 lukem for (t_ptr = token; *t_ptr; ++t_ptr)
443 1.6 lukem *sc_end++ = *t_ptr; /* copy token into temp
444 1.6 lukem * buffer */
445 1.6 lukem ps.procname[0] = 0;
446 1.6 lukem
447 1.6 lukem sw_buffer:
448 1.6 lukem ps.search_brace = false; /* stop looking for
449 1.6 lukem * start of stmt */
450 1.6 lukem bp_save = buf_ptr; /* save current input
451 1.6 lukem * buffer */
452 1.6 lukem be_save = buf_end;
453 1.6 lukem buf_ptr = save_com; /* fix so that
454 1.6 lukem * subsequent calls to
455 1.6 lukem * lexi will take tokens
456 1.6 lukem * out of save_com */
457 1.6 lukem *sc_end++ = ' '; /* add trailing blank,
458 1.6 lukem * just in case */
459 1.6 lukem buf_end = sc_end;
460 1.6 lukem sc_end = 0;
461 1.6 lukem break;
462 1.6 lukem } /* end of switch */
463 1.6 lukem if (type_code != 0) /* we must make this check,
464 1.6 lukem * just in case there was an
465 1.6 lukem * unexpected EOF */
466 1.6 lukem type_code = lexi(); /* read another token */
467 1.6 lukem /* if (ps.search_brace) ps.procname[0] = 0; */
468 1.6 lukem if ((is_procname = ps.procname[0]) && flushed_nl
469 1.6 lukem && !procnames_start_line && ps.in_decl
470 1.6 lukem && type_code == ident)
471 1.6 lukem flushed_nl = 0;
472 1.6 lukem } /* end of while (search_brace) */
473 1.6 lukem last_else = 0;
474 1.1 cgd check_type:
475 1.6 lukem if (type_code == 0) { /* we got eof */
476 1.6 lukem if (s_lab != e_lab || s_code != e_code
477 1.6 lukem || s_com != e_com) /* must dump end of line */
478 1.6 lukem dump_line();
479 1.6 lukem if (ps.tos > 1) /* check for balanced braces */
480 1.6 lukem diag(1, "Stuff missing from end of file.");
481 1.6 lukem
482 1.6 lukem if (verbose) {
483 1.6 lukem printf("There were %d output lines and %d comments\n",
484 1.6 lukem ps.out_lines, ps.out_coms);
485 1.6 lukem printf("(Lines with comments)/(Lines with code): %6.3f\n",
486 1.6 lukem (1.0 * ps.com_lines) / code_lines);
487 1.6 lukem }
488 1.6 lukem fflush(output);
489 1.6 lukem exit(found_err);
490 1.1 cgd }
491 1.6 lukem if (
492 1.6 lukem (type_code != comment) &&
493 1.6 lukem (type_code != newline) &&
494 1.6 lukem (type_code != preesc) &&
495 1.6 lukem (type_code != form_feed)) {
496 1.6 lukem if (force_nl &&
497 1.6 lukem (type_code != semicolon) &&
498 1.6 lukem (type_code != lbrace || !btype_2)) {
499 1.6 lukem /* we should force a broken line here */
500 1.6 lukem if (verbose && !flushed_nl)
501 1.6 lukem diag(0, "Line broken");
502 1.6 lukem flushed_nl = false;
503 1.6 lukem dump_line();
504 1.22 ginsbach ps.want_blank = false; /* don't insert blank at
505 1.6 lukem * line start */
506 1.6 lukem force_nl = false;
507 1.6 lukem }
508 1.6 lukem ps.in_stmt = true; /* turn on flag which causes
509 1.6 lukem * an extra level of
510 1.6 lukem * indentation. this is turned
511 1.6 lukem * off by a ; or '}' */
512 1.6 lukem if (s_com != e_com) { /* the turkey has embedded a
513 1.6 lukem * comment in a line. fix it */
514 1.6 lukem *e_code++ = ' ';
515 1.6 lukem for (t_ptr = s_com; *t_ptr; ++t_ptr) {
516 1.6 lukem CHECK_SIZE_CODE;
517 1.6 lukem *e_code++ = *t_ptr;
518 1.6 lukem }
519 1.6 lukem *e_code++ = ' ';
520 1.6 lukem *e_code = '\0'; /* null terminate code sect */
521 1.6 lukem ps.want_blank = false;
522 1.6 lukem e_com = s_com;
523 1.6 lukem }
524 1.6 lukem } else
525 1.6 lukem if (type_code != comment) /* preserve force_nl
526 1.6 lukem * thru a comment */
527 1.6 lukem force_nl = false; /* cancel forced newline
528 1.6 lukem * after newline, form
529 1.6 lukem * feed, etc */
530 1.1 cgd
531 1.1 cgd
532 1.1 cgd
533 1.6 lukem /*-----------------------------------------------------*\
534 1.6 lukem | do switch on type of token scanned |
535 1.6 lukem \*-----------------------------------------------------*/
536 1.6 lukem CHECK_SIZE_CODE;
537 1.6 lukem switch (type_code) { /* now, decide what to do with the
538 1.6 lukem * token */
539 1.6 lukem
540 1.6 lukem case form_feed:/* found a form feed in line */
541 1.6 lukem ps.use_ff = true; /* a form feed is treated much
542 1.6 lukem * like a newline */
543 1.6 lukem dump_line();
544 1.6 lukem ps.want_blank = false;
545 1.6 lukem break;
546 1.6 lukem
547 1.6 lukem case newline:
548 1.6 lukem if (ps.last_token != comma || ps.p_l_follow > 0
549 1.6 lukem || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
550 1.6 lukem dump_line();
551 1.6 lukem ps.want_blank = false;
552 1.6 lukem }
553 1.6 lukem ++line_no; /* keep track of input line number */
554 1.6 lukem break;
555 1.1 cgd
556 1.6 lukem case lparen: /* got a '(' or '[' */
557 1.6 lukem ++ps.p_l_follow; /* count parens to make Healy
558 1.6 lukem * happy */
559 1.6 lukem if (ps.want_blank && *token != '[' &&
560 1.6 lukem (ps.last_token != ident || proc_calls_space
561 1.6 lukem || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
562 1.6 lukem *e_code++ = ' ';
563 1.10 christos if (ps.in_decl && !ps.block_init) {
564 1.6 lukem if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) {
565 1.6 lukem ps.dumped_decl_indent = 1;
566 1.6 lukem sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
567 1.6 lukem e_code += strlen(e_code);
568 1.6 lukem } else {
569 1.6 lukem while ((e_code - s_code) < dec_ind) {
570 1.6 lukem CHECK_SIZE_CODE;
571 1.6 lukem *e_code++ = ' ';
572 1.6 lukem }
573 1.6 lukem *e_code++ = token[0];
574 1.6 lukem }
575 1.10 christos } else
576 1.6 lukem *e_code++ = token[0];
577 1.6 lukem ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
578 1.6 lukem if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
579 1.6 lukem && ps.paren_indents[0] < 2 * ps.ind_size)
580 1.6 lukem ps.paren_indents[0] = 2 * ps.ind_size;
581 1.6 lukem ps.want_blank = false;
582 1.6 lukem if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
583 1.6 lukem /*
584 1.6 lukem * this is a kluge to make sure that declarations will be
585 1.6 lukem * aligned right if proc decl has an explicit type on it, i.e.
586 1.6 lukem * "int a(x) {..."
587 1.6 lukem */
588 1.6 lukem parse(semicolon); /* I said this was a
589 1.6 lukem * kluge... */
590 1.6 lukem ps.in_or_st = false; /* turn off flag for
591 1.6 lukem * structure decl or
592 1.6 lukem * initialization */
593 1.6 lukem }
594 1.6 lukem if (ps.sizeof_keyword)
595 1.6 lukem ps.sizeof_mask |= 1 << ps.p_l_follow;
596 1.1 cgd break;
597 1.6 lukem
598 1.6 lukem case rparen: /* got a ')' or ']' */
599 1.6 lukem rparen_count--;
600 1.6 lukem if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
601 1.6 lukem ps.last_u_d = true;
602 1.6 lukem ps.cast_mask &= (1 << ps.p_l_follow) - 1;
603 1.6 lukem }
604 1.6 lukem ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
605 1.6 lukem if (--ps.p_l_follow < 0) {
606 1.6 lukem ps.p_l_follow = 0;
607 1.6 lukem diag(0, "Extra %c", *token);
608 1.6 lukem }
609 1.6 lukem if (e_code == s_code) /* if the paren starts the
610 1.6 lukem * line */
611 1.6 lukem ps.paren_level = ps.p_l_follow; /* then indent it */
612 1.6 lukem
613 1.6 lukem *e_code++ = token[0];
614 1.6 lukem ps.want_blank = true;
615 1.6 lukem
616 1.6 lukem if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if
617 1.6 lukem * (...), or some such */
618 1.6 lukem sp_sw = false;
619 1.6 lukem force_nl = true; /* must force newline
620 1.6 lukem * after if */
621 1.6 lukem ps.last_u_d = true; /* inform lexi that a
622 1.6 lukem * following operator is
623 1.6 lukem * unary */
624 1.22 ginsbach ps.in_stmt = false; /* don't use stmt
625 1.6 lukem * continuation
626 1.6 lukem * indentation */
627 1.6 lukem
628 1.6 lukem parse(hd_type); /* let parser worry about if,
629 1.6 lukem * or whatever */
630 1.6 lukem }
631 1.6 lukem ps.search_brace = btype_2; /* this should insure
632 1.6 lukem * that constructs such
633 1.6 lukem * as main(){...} and
634 1.6 lukem * int[]{...} have their
635 1.6 lukem * braces put in the
636 1.6 lukem * right place */
637 1.1 cgd break;
638 1.6 lukem
639 1.6 lukem case unary_op: /* this could be any unary operation */
640 1.6 lukem if (ps.want_blank)
641 1.6 lukem *e_code++ = ' ';
642 1.6 lukem
643 1.6 lukem if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) {
644 1.6 lukem sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
645 1.6 lukem ps.dumped_decl_indent = 1;
646 1.6 lukem e_code += strlen(e_code);
647 1.6 lukem } else {
648 1.18 lukem const char *res = token;
649 1.6 lukem
650 1.6 lukem if (ps.in_decl && !ps.block_init) { /* if this is a unary op
651 1.6 lukem * in a declaration, we
652 1.6 lukem * should indent this
653 1.6 lukem * token */
654 1.6 lukem for (i = 0; token[i]; ++i); /* find length of token */
655 1.6 lukem while ((e_code - s_code) < (dec_ind - i)) {
656 1.6 lukem CHECK_SIZE_CODE;
657 1.6 lukem *e_code++ = ' '; /* pad it */
658 1.6 lukem }
659 1.6 lukem }
660 1.6 lukem if (troff && token[0] == '-' && token[1] == '>')
661 1.6 lukem res = "\\(->";
662 1.6 lukem for (t_ptr = res; *t_ptr; ++t_ptr) {
663 1.6 lukem CHECK_SIZE_CODE;
664 1.6 lukem *e_code++ = *t_ptr;
665 1.6 lukem }
666 1.6 lukem }
667 1.6 lukem ps.want_blank = false;
668 1.1 cgd break;
669 1.6 lukem
670 1.6 lukem case binary_op:/* any binary operation */
671 1.6 lukem if (ps.want_blank)
672 1.6 lukem *e_code++ = ' ';
673 1.6 lukem {
674 1.18 lukem const char *res = token;
675 1.6 lukem
676 1.6 lukem if (troff)
677 1.6 lukem switch (token[0]) {
678 1.6 lukem case '<':
679 1.6 lukem if (token[1] == '=')
680 1.6 lukem res = "\\(<=";
681 1.6 lukem break;
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 = "\\(br\\(br";
693 1.6 lukem else
694 1.6 lukem if (token[1] == 0)
695 1.6 lukem res = "\\(br";
696 1.6 lukem break;
697 1.6 lukem }
698 1.6 lukem for (t_ptr = res; *t_ptr; ++t_ptr) {
699 1.6 lukem CHECK_SIZE_CODE;
700 1.6 lukem *e_code++ = *t_ptr; /* move the operator */
701 1.6 lukem }
702 1.6 lukem }
703 1.6 lukem ps.want_blank = true;
704 1.1 cgd break;
705 1.1 cgd
706 1.6 lukem case postop: /* got a trailing ++ or -- */
707 1.6 lukem *e_code++ = token[0];
708 1.6 lukem *e_code++ = token[1];
709 1.6 lukem ps.want_blank = true;
710 1.6 lukem break;
711 1.1 cgd
712 1.6 lukem case question: /* got a ? */
713 1.6 lukem squest++; /* this will be used when a later
714 1.6 lukem * colon appears so we can distinguish
715 1.6 lukem * the <c>?<n>:<n> construct */
716 1.6 lukem if (ps.want_blank)
717 1.6 lukem *e_code++ = ' ';
718 1.6 lukem *e_code++ = '?';
719 1.6 lukem ps.want_blank = true;
720 1.6 lukem break;
721 1.1 cgd
722 1.6 lukem case casestmt: /* got word 'case' or 'default' */
723 1.6 lukem scase = true; /* so we can process the later colon
724 1.6 lukem * properly */
725 1.6 lukem goto copy_id;
726 1.6 lukem
727 1.6 lukem case colon: /* got a ':' */
728 1.6 lukem if (squest > 0) { /* it is part of the <c>?<n>:
729 1.6 lukem * <n> construct */
730 1.6 lukem --squest;
731 1.6 lukem if (ps.want_blank)
732 1.6 lukem *e_code++ = ' ';
733 1.6 lukem *e_code++ = ':';
734 1.6 lukem ps.want_blank = true;
735 1.6 lukem break;
736 1.6 lukem }
737 1.11 kleink if (ps.in_or_st) {
738 1.6 lukem *e_code++ = ':';
739 1.6 lukem ps.want_blank = false;
740 1.6 lukem break;
741 1.6 lukem }
742 1.6 lukem ps.in_stmt = false; /* seeing a label does not
743 1.6 lukem * imply we are in a stmt */
744 1.6 lukem for (t_ptr = s_code; *t_ptr; ++t_ptr)
745 1.6 lukem *e_lab++ = *t_ptr; /* turn everything so
746 1.6 lukem * far into a label */
747 1.6 lukem e_code = s_code;
748 1.6 lukem *e_lab++ = ':';
749 1.6 lukem *e_lab++ = ' ';
750 1.6 lukem *e_lab = '\0';
751 1.6 lukem
752 1.6 lukem force_nl = ps.pcase = scase; /* ps.pcase will be used
753 1.6 lukem * by dump_line to
754 1.6 lukem * decide how to indent
755 1.6 lukem * the label. force_nl
756 1.6 lukem * will force a case n:
757 1.6 lukem * to be on a line by
758 1.6 lukem * itself */
759 1.6 lukem scase = false;
760 1.6 lukem ps.want_blank = false;
761 1.6 lukem break;
762 1.1 cgd
763 1.6 lukem case semicolon:/* got a ';' */
764 1.6 lukem ps.in_or_st = false; /* we are not in an
765 1.6 lukem * initialization or structure
766 1.6 lukem * declaration */
767 1.6 lukem scase = false; /* these will only need resetting in a
768 1.6 lukem * error */
769 1.6 lukem squest = 0;
770 1.6 lukem if (ps.last_token == rparen && rparen_count == 0)
771 1.6 lukem ps.in_parameter_declaration = 0;
772 1.6 lukem ps.cast_mask = 0;
773 1.6 lukem ps.sizeof_mask = 0;
774 1.6 lukem ps.block_init = 0;
775 1.6 lukem ps.block_init_level = 0;
776 1.6 lukem ps.just_saw_decl--;
777 1.6 lukem
778 1.6 lukem if (ps.in_decl && s_code == e_code && !ps.block_init)
779 1.6 lukem while ((e_code - s_code) < (dec_ind - 1)) {
780 1.6 lukem CHECK_SIZE_CODE;
781 1.6 lukem *e_code++ = ' ';
782 1.6 lukem }
783 1.6 lukem
784 1.6 lukem ps.in_decl = (ps.dec_nest > 0); /* if we were in a first
785 1.6 lukem * level structure
786 1.22 ginsbach * declaration, we
787 1.22 ginsbach * aren't any more */
788 1.6 lukem
789 1.6 lukem if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
790 1.6 lukem
791 1.6 lukem /*
792 1.6 lukem * This should be true iff there were unbalanced parens in the
793 1.6 lukem * stmt. It is a bit complicated, because the semicolon might
794 1.6 lukem * be in a for stmt
795 1.6 lukem */
796 1.6 lukem diag(1, "Unbalanced parens");
797 1.6 lukem ps.p_l_follow = 0;
798 1.6 lukem if (sp_sw) { /* this is a check for a if,
799 1.6 lukem * while, etc. with unbalanced
800 1.6 lukem * parens */
801 1.6 lukem sp_sw = false;
802 1.22 ginsbach parse(hd_type); /* don't lose the if,
803 1.22 ginsbach * or whatever */
804 1.6 lukem }
805 1.6 lukem }
806 1.6 lukem *e_code++ = ';';
807 1.6 lukem ps.want_blank = true;
808 1.6 lukem ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in
809 1.6 lukem * the middle of a stmt */
810 1.6 lukem
811 1.6 lukem if (!sp_sw) { /* if not if for (;;) */
812 1.6 lukem parse(semicolon); /* let parser know about
813 1.6 lukem * end of stmt */
814 1.6 lukem force_nl = true; /* force newline after a
815 1.6 lukem * end of stmt */
816 1.1 cgd }
817 1.6 lukem break;
818 1.6 lukem
819 1.6 lukem case lbrace: /* got a '{' */
820 1.22 ginsbach ps.in_stmt = false; /* don't indent the {} */
821 1.6 lukem if (!ps.block_init)
822 1.6 lukem force_nl = true; /* force other stuff on
823 1.6 lukem * same line as '{' onto
824 1.6 lukem * new line */
825 1.1 cgd else
826 1.6 lukem if (ps.block_init_level <= 0)
827 1.6 lukem ps.block_init_level = 1;
828 1.6 lukem else
829 1.6 lukem ps.block_init_level++;
830 1.6 lukem
831 1.6 lukem if (s_code != e_code && !ps.block_init) {
832 1.6 lukem if (!btype_2) {
833 1.6 lukem dump_line();
834 1.6 lukem ps.want_blank = false;
835 1.6 lukem } else
836 1.6 lukem if (ps.in_parameter_declaration && !ps.in_or_st) {
837 1.6 lukem ps.i_l_follow = 0;
838 1.6 lukem dump_line();
839 1.6 lukem ps.want_blank = false;
840 1.6 lukem }
841 1.6 lukem }
842 1.6 lukem if (ps.in_parameter_declaration)
843 1.6 lukem prefix_blankline_requested = 0;
844 1.6 lukem
845 1.12 wiz if (ps.p_l_follow > 0) { /* check for preceding
846 1.6 lukem * unbalanced parens */
847 1.6 lukem diag(1, "Unbalanced parens");
848 1.6 lukem ps.p_l_follow = 0;
849 1.6 lukem if (sp_sw) { /* check for unclosed if, for,
850 1.6 lukem * etc. */
851 1.6 lukem sp_sw = false;
852 1.6 lukem parse(hd_type);
853 1.6 lukem ps.ind_level = ps.i_l_follow;
854 1.6 lukem }
855 1.6 lukem }
856 1.6 lukem if (s_code == e_code)
857 1.22 ginsbach ps.ind_stmt = false; /* don't put extra
858 1.6 lukem * indentation on line
859 1.6 lukem * with '{' */
860 1.6 lukem if (ps.in_decl && ps.in_or_st) { /* this is either a
861 1.6 lukem * structure declaration
862 1.6 lukem * or an init */
863 1.6 lukem di_stack[ps.dec_nest++] = dec_ind;
864 1.6 lukem /* ? dec_ind = 0; */
865 1.6 lukem } else {
866 1.22 ginsbach ps.decl_on_line = false; /* we can't be in the
867 1.6 lukem * middle of a
868 1.22 ginsbach * declaration, so don't
869 1.6 lukem * do special
870 1.6 lukem * indentation of
871 1.6 lukem * comments */
872 1.6 lukem if (blanklines_after_declarations_at_proctop
873 1.6 lukem && ps.in_parameter_declaration)
874 1.6 lukem postfix_blankline_requested = 1;
875 1.6 lukem ps.in_parameter_declaration = 0;
876 1.6 lukem }
877 1.6 lukem dec_ind = 0;
878 1.6 lukem parse(lbrace); /* let parser know about this */
879 1.6 lukem if (ps.want_blank) /* put a blank before '{' if
880 1.6 lukem * '{' is not at start of line */
881 1.1 cgd *e_code++ = ' ';
882 1.6 lukem ps.want_blank = false;
883 1.6 lukem *e_code++ = '{';
884 1.6 lukem ps.just_saw_decl = 0;
885 1.6 lukem break;
886 1.6 lukem
887 1.6 lukem case rbrace: /* got a '}' */
888 1.6 lukem if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be
889 1.6 lukem * omitted in
890 1.6 lukem * declarations */
891 1.6 lukem parse(semicolon);
892 1.6 lukem if (ps.p_l_follow) { /* check for unclosed if, for,
893 1.6 lukem * else. */
894 1.6 lukem diag(1, "Unbalanced parens");
895 1.6 lukem ps.p_l_follow = 0;
896 1.6 lukem sp_sw = false;
897 1.6 lukem }
898 1.6 lukem ps.just_saw_decl = 0;
899 1.6 lukem ps.block_init_level--;
900 1.6 lukem if (s_code != e_code && !ps.block_init) { /* '}' must be first on
901 1.6 lukem * line */
902 1.6 lukem if (verbose)
903 1.6 lukem diag(0, "Line broken");
904 1.6 lukem dump_line();
905 1.6 lukem }
906 1.6 lukem *e_code++ = '}';
907 1.6 lukem ps.want_blank = true;
908 1.6 lukem ps.in_stmt = ps.ind_stmt = false;
909 1.6 lukem if (ps.dec_nest > 0) { /* we are in multi-level
910 1.6 lukem * structure declaration */
911 1.6 lukem dec_ind = di_stack[--ps.dec_nest];
912 1.6 lukem if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
913 1.6 lukem ps.just_saw_decl = 2;
914 1.6 lukem ps.in_decl = true;
915 1.6 lukem }
916 1.6 lukem prefix_blankline_requested = 0;
917 1.6 lukem parse(rbrace); /* let parser know about this */
918 1.6 lukem ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
919 1.6 lukem && ps.il[ps.tos] >= ps.ind_level;
920 1.6 lukem if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
921 1.6 lukem postfix_blankline_requested = 1;
922 1.6 lukem break;
923 1.1 cgd
924 1.6 lukem case swstmt: /* got keyword "switch" */
925 1.6 lukem sp_sw = true;
926 1.6 lukem hd_type = swstmt; /* keep this for when we have
927 1.6 lukem * seen the expression */
928 1.6 lukem goto copy_id; /* go move the token into buffer */
929 1.6 lukem
930 1.6 lukem case sp_paren: /* token is if, while, for */
931 1.6 lukem sp_sw = true; /* the interesting stuff is done after
932 1.6 lukem * the expression is scanned */
933 1.6 lukem hd_type = (*token == 'i' ? ifstmt :
934 1.6 lukem (*token == 'w' ? whilestmt : forstmt));
935 1.6 lukem
936 1.6 lukem /*
937 1.6 lukem * remember the type of header for later use by parser
938 1.6 lukem */
939 1.6 lukem goto copy_id; /* copy the token into line */
940 1.6 lukem
941 1.6 lukem case sp_nparen:/* got else, do */
942 1.6 lukem ps.in_stmt = false;
943 1.6 lukem if (*token == 'e') {
944 1.6 lukem if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
945 1.6 lukem if (verbose)
946 1.6 lukem diag(0, "Line broken");
947 1.6 lukem dump_line(); /* make sure this starts
948 1.6 lukem * a line */
949 1.6 lukem ps.want_blank = false;
950 1.6 lukem }
951 1.6 lukem force_nl = true; /* also, following stuff
952 1.6 lukem * must go onto new line */
953 1.6 lukem last_else = 1;
954 1.6 lukem parse(elselit);
955 1.6 lukem } else {
956 1.6 lukem if (e_code != s_code) { /* make sure this starts
957 1.6 lukem * a line */
958 1.6 lukem if (verbose)
959 1.6 lukem diag(0, "Line broken");
960 1.6 lukem dump_line();
961 1.6 lukem ps.want_blank = false;
962 1.6 lukem }
963 1.6 lukem force_nl = true; /* also, following stuff
964 1.6 lukem * must go onto new line */
965 1.6 lukem last_else = 0;
966 1.6 lukem parse(dolit);
967 1.6 lukem }
968 1.6 lukem goto copy_id; /* move the token into line */
969 1.1 cgd
970 1.6 lukem case decl: /* we have a declaration type (int, register,
971 1.6 lukem * etc.) */
972 1.6 lukem parse(decl); /* let parser worry about indentation */
973 1.6 lukem if (ps.last_token == rparen && ps.tos <= 1) {
974 1.6 lukem ps.in_parameter_declaration = 1;
975 1.6 lukem if (s_code != e_code) {
976 1.6 lukem dump_line();
977 1.6 lukem ps.want_blank = 0;
978 1.6 lukem }
979 1.1 cgd }
980 1.6 lukem if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
981 1.6 lukem ps.ind_level = ps.i_l_follow = 1;
982 1.6 lukem ps.ind_stmt = 0;
983 1.1 cgd }
984 1.6 lukem ps.in_or_st = true; /* this might be a structure
985 1.6 lukem * or initialization
986 1.6 lukem * declaration */
987 1.6 lukem ps.in_decl = ps.decl_on_line = true;
988 1.6 lukem if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
989 1.6 lukem ps.just_saw_decl = 2;
990 1.6 lukem prefix_blankline_requested = 0;
991 1.6 lukem for (i = 0; token[i++];); /* get length of token */
992 1.6 lukem
993 1.6 lukem /*
994 1.6 lukem * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
995 1.6 lukem * : i);
996 1.6 lukem */
997 1.6 lukem dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
998 1.19 mrg tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0);
999 1.6 lukem goto copy_id;
1000 1.6 lukem
1001 1.6 lukem case ident: /* got an identifier or constant */
1002 1.6 lukem if (ps.in_decl) { /* if we are in a declaration,
1003 1.6 lukem * we must indent identifier */
1004 1.6 lukem if (ps.want_blank)
1005 1.6 lukem *e_code++ = ' ';
1006 1.6 lukem ps.want_blank = false;
1007 1.6 lukem if (is_procname == 0 || !procnames_start_line) {
1008 1.7 ross if (!ps.block_init) {
1009 1.6 lukem if (troff && !ps.dumped_decl_indent) {
1010 1.6 lukem sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
1011 1.6 lukem ps.dumped_decl_indent = 1;
1012 1.6 lukem e_code += strlen(e_code);
1013 1.19 mrg CHECK_SIZE_CODE;
1014 1.19 mrg } else {
1015 1.19 mrg int cur_dec_ind;
1016 1.19 mrg int pos, startpos;
1017 1.19 mrg
1018 1.19 mrg /*
1019 1.19 mrg * in order to get the tab math right for
1020 1.19 mrg * indentations that are not multiples of 8 we
1021 1.19 mrg * need to modify both startpos and dec_ind
1022 1.19 mrg * (cur_dec_ind) here by eight minus the
1023 1.19 mrg * remainder of the current starting column
1024 1.19 mrg * divided by eight. This seems to be a
1025 1.19 mrg * properly working fix
1026 1.19 mrg */
1027 1.19 mrg startpos = e_code - s_code;
1028 1.19 mrg cur_dec_ind = dec_ind;
1029 1.19 mrg pos = startpos;
1030 1.19 mrg if ((ps.ind_level * ps.ind_size) % 8 != 0) {
1031 1.19 mrg pos += (ps.ind_level * ps.ind_size) % 8;
1032 1.19 mrg cur_dec_ind += (ps.ind_level * ps.ind_size) % 8;
1033 1.19 mrg }
1034 1.19 mrg
1035 1.19 mrg if (tabs_to_var) {
1036 1.19 mrg while ((pos & ~7) + 8 <= cur_dec_ind) {
1037 1.19 mrg CHECK_SIZE_CODE;
1038 1.19 mrg *e_code++ = '\t';
1039 1.19 mrg pos = (pos & ~7) + 8;
1040 1.19 mrg }
1041 1.19 mrg }
1042 1.19 mrg while (pos < cur_dec_ind) {
1043 1.6 lukem CHECK_SIZE_CODE;
1044 1.6 lukem *e_code++ = ' ';
1045 1.19 mrg pos++;
1046 1.6 lukem }
1047 1.19 mrg if (ps.want_blank && e_code - s_code == startpos)
1048 1.19 mrg *e_code++ = ' ';
1049 1.19 mrg ps.want_blank = false;
1050 1.19 mrg }
1051 1.7 ross }
1052 1.6 lukem } else {
1053 1.6 lukem if (dec_ind && s_code != e_code)
1054 1.6 lukem dump_line();
1055 1.6 lukem dec_ind = 0;
1056 1.6 lukem ps.want_blank = false;
1057 1.6 lukem }
1058 1.6 lukem } else
1059 1.6 lukem if (sp_sw && ps.p_l_follow == 0) {
1060 1.6 lukem sp_sw = false;
1061 1.6 lukem force_nl = true;
1062 1.6 lukem ps.last_u_d = true;
1063 1.6 lukem ps.in_stmt = false;
1064 1.6 lukem parse(hd_type);
1065 1.6 lukem }
1066 1.6 lukem copy_id:
1067 1.6 lukem if (ps.want_blank)
1068 1.6 lukem *e_code++ = ' ';
1069 1.6 lukem if (troff && ps.its_a_keyword) {
1070 1.6 lukem e_code = chfont(&bodyf, &keywordf, e_code);
1071 1.6 lukem for (t_ptr = token; *t_ptr; ++t_ptr) {
1072 1.6 lukem CHECK_SIZE_CODE;
1073 1.16 dsl *e_code++ = keywordf.allcaps
1074 1.16 dsl ? toupper((unsigned char)*t_ptr)
1075 1.16 dsl : *t_ptr;
1076 1.6 lukem }
1077 1.6 lukem e_code = chfont(&keywordf, &bodyf, e_code);
1078 1.6 lukem } else
1079 1.6 lukem for (t_ptr = token; *t_ptr; ++t_ptr) {
1080 1.6 lukem CHECK_SIZE_CODE;
1081 1.6 lukem *e_code++ = *t_ptr;
1082 1.6 lukem }
1083 1.6 lukem ps.want_blank = true;
1084 1.1 cgd break;
1085 1.6 lukem
1086 1.6 lukem case period: /* treat a period kind of like a binary
1087 1.6 lukem * operation */
1088 1.6 lukem *e_code++ = '.'; /* move the period into line */
1089 1.22 ginsbach ps.want_blank = false; /* don't put a blank after a
1090 1.6 lukem * period */
1091 1.1 cgd break;
1092 1.6 lukem
1093 1.6 lukem case comma:
1094 1.6 lukem ps.want_blank = (s_code != e_code); /* only put blank after
1095 1.6 lukem * comma if comma does
1096 1.6 lukem * not start the line */
1097 1.6 lukem if (ps.in_decl && is_procname == 0 && !ps.block_init)
1098 1.6 lukem while ((e_code - s_code) < (dec_ind - 1)) {
1099 1.6 lukem CHECK_SIZE_CODE;
1100 1.6 lukem *e_code++ = ' ';
1101 1.6 lukem }
1102 1.6 lukem
1103 1.6 lukem *e_code++ = ',';
1104 1.6 lukem if (ps.p_l_follow == 0) {
1105 1.6 lukem if (ps.block_init_level <= 0)
1106 1.6 lukem ps.block_init = 0;
1107 1.6 lukem if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8))
1108 1.6 lukem force_nl = true;
1109 1.6 lukem }
1110 1.1 cgd break;
1111 1.6 lukem
1112 1.6 lukem case preesc: /* got the character '#' */
1113 1.6 lukem if ((s_com != e_com) ||
1114 1.6 lukem (s_lab != e_lab) ||
1115 1.6 lukem (s_code != e_code))
1116 1.6 lukem dump_line();
1117 1.6 lukem *e_lab++ = '#'; /* move whole line to 'label' buffer */
1118 1.6 lukem {
1119 1.6 lukem int in_comment = 0;
1120 1.6 lukem int com_start = 0;
1121 1.6 lukem char quote = 0;
1122 1.6 lukem int com_end = 0;
1123 1.6 lukem
1124 1.6 lukem while (*buf_ptr == ' ' || *buf_ptr == '\t') {
1125 1.6 lukem buf_ptr++;
1126 1.6 lukem if (buf_ptr >= buf_end)
1127 1.6 lukem fill_buffer();
1128 1.6 lukem }
1129 1.6 lukem while (*buf_ptr != '\n' || in_comment) {
1130 1.6 lukem CHECK_SIZE_LAB;
1131 1.6 lukem *e_lab = *buf_ptr++;
1132 1.6 lukem if (buf_ptr >= buf_end)
1133 1.6 lukem fill_buffer();
1134 1.6 lukem switch (*e_lab++) {
1135 1.6 lukem case BACKSLASH:
1136 1.6 lukem if (troff)
1137 1.6 lukem *e_lab++ = BACKSLASH;
1138 1.6 lukem if (!in_comment) {
1139 1.6 lukem *e_lab++ = *buf_ptr++;
1140 1.6 lukem if (buf_ptr >= buf_end)
1141 1.6 lukem fill_buffer();
1142 1.6 lukem }
1143 1.6 lukem break;
1144 1.6 lukem case '/':
1145 1.6 lukem if (*buf_ptr == '*' && !in_comment && !quote) {
1146 1.6 lukem in_comment = 1;
1147 1.6 lukem *e_lab++ = *buf_ptr++;
1148 1.6 lukem com_start = e_lab - s_lab - 2;
1149 1.6 lukem }
1150 1.6 lukem break;
1151 1.6 lukem case '"':
1152 1.6 lukem if (quote == '"')
1153 1.6 lukem quote = 0;
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 (*buf_ptr == '/' && in_comment) {
1161 1.6 lukem in_comment = 0;
1162 1.6 lukem *e_lab++ = *buf_ptr++;
1163 1.6 lukem com_end = e_lab - s_lab;
1164 1.6 lukem }
1165 1.6 lukem break;
1166 1.6 lukem }
1167 1.6 lukem }
1168 1.6 lukem
1169 1.6 lukem while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
1170 1.6 lukem e_lab--;
1171 1.6 lukem if (e_lab - s_lab == com_end && bp_save == 0) { /* comment on
1172 1.6 lukem * preprocessor line */
1173 1.6 lukem if (sc_end == 0) /* if this is the first
1174 1.6 lukem * comment, we must set
1175 1.6 lukem * up the buffer */
1176 1.6 lukem sc_end = &(save_com[0]);
1177 1.6 lukem else {
1178 1.6 lukem *sc_end++ = '\n'; /* add newline between
1179 1.6 lukem * comments */
1180 1.6 lukem *sc_end++ = ' ';
1181 1.6 lukem --line_no;
1182 1.6 lukem }
1183 1.6 lukem memmove(sc_end, s_lab + com_start, com_end - com_start);
1184 1.6 lukem sc_end += com_end - com_start;
1185 1.6 lukem if (sc_end >= &save_com[sc_size])
1186 1.6 lukem abort();
1187 1.6 lukem e_lab = s_lab + com_start;
1188 1.6 lukem while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
1189 1.6 lukem e_lab--;
1190 1.6 lukem bp_save = buf_ptr; /* save current input
1191 1.6 lukem * buffer */
1192 1.6 lukem be_save = buf_end;
1193 1.6 lukem buf_ptr = save_com; /* fix so that
1194 1.6 lukem * subsequent calls to
1195 1.6 lukem * lexi will take tokens
1196 1.6 lukem * out of save_com */
1197 1.6 lukem *sc_end++ = ' '; /* add trailing blank,
1198 1.6 lukem * just in case */
1199 1.6 lukem buf_end = sc_end;
1200 1.6 lukem sc_end = 0;
1201 1.6 lukem }
1202 1.6 lukem *e_lab = '\0'; /* null terminate line */
1203 1.6 lukem ps.pcase = false;
1204 1.1 cgd }
1205 1.1 cgd
1206 1.6 lukem if (strncmp(s_lab, "#if", 3) == 0) {
1207 1.6 lukem if (blanklines_around_conditional_compilation) {
1208 1.6 lukem int c;
1209 1.6 lukem prefix_blankline_requested++;
1210 1.6 lukem while ((c = getc(input)) == '\n');
1211 1.6 lukem ungetc(c, input);
1212 1.6 lukem }
1213 1.18 lukem if (ifdef_level < (int)(sizeof state_stack / sizeof state_stack[0])) {
1214 1.6 lukem match_state[ifdef_level].tos = -1;
1215 1.6 lukem state_stack[ifdef_level++] = ps;
1216 1.6 lukem } else
1217 1.6 lukem diag(1, "#if stack overflow");
1218 1.6 lukem } else
1219 1.10 christos if (strncmp(s_lab, "#else", 5) == 0) {
1220 1.6 lukem if (ifdef_level <= 0)
1221 1.6 lukem diag(1, "Unmatched #else");
1222 1.6 lukem else {
1223 1.6 lukem match_state[ifdef_level - 1] = ps;
1224 1.6 lukem ps = state_stack[ifdef_level - 1];
1225 1.6 lukem }
1226 1.10 christos } else
1227 1.6 lukem if (strncmp(s_lab, "#endif", 6) == 0) {
1228 1.6 lukem if (ifdef_level <= 0)
1229 1.6 lukem diag(1, "Unmatched #endif");
1230 1.6 lukem else {
1231 1.6 lukem ifdef_level--;
1232 1.1 cgd
1233 1.1 cgd #ifdef undef
1234 1.6 lukem /*
1235 1.6 lukem * This match needs to be more intelligent before the
1236 1.6 lukem * message is useful
1237 1.6 lukem */
1238 1.6 lukem if (match_state[ifdef_level].tos >= 0
1239 1.6 lukem && memcmp(&ps, &match_state[ifdef_level], sizeof ps))
1240 1.6 lukem diag(0, "Syntactically inconsistant #ifdef alternatives.");
1241 1.1 cgd #endif
1242 1.6 lukem }
1243 1.6 lukem if (blanklines_around_conditional_compilation) {
1244 1.6 lukem postfix_blankline_requested++;
1245 1.6 lukem n_real_blanklines = 0;
1246 1.6 lukem }
1247 1.6 lukem }
1248 1.6 lukem break; /* subsequent processing of the newline
1249 1.1 cgd * character will cause the line to be printed */
1250 1.1 cgd
1251 1.6 lukem case comment: /* we have gotten a start comment */
1252 1.6 lukem /* this is a biggie */
1253 1.6 lukem if (flushed_nl) { /* we should force a broken
1254 1.6 lukem * line here */
1255 1.6 lukem flushed_nl = false;
1256 1.6 lukem dump_line();
1257 1.22 ginsbach ps.want_blank = false; /* don't insert blank at
1258 1.6 lukem * line start */
1259 1.6 lukem force_nl = false;
1260 1.6 lukem }
1261 1.6 lukem pr_comment();
1262 1.6 lukem break;
1263 1.6 lukem } /* end of big switch stmt */
1264 1.6 lukem
1265 1.6 lukem *e_code = '\0'; /* make sure code section is null terminated */
1266 1.6 lukem if (type_code != comment && type_code != newline && type_code != preesc)
1267 1.6 lukem ps.last_token = type_code;
1268 1.6 lukem } /* end of main while (1) loop */
1269 1.1 cgd }
1270 1.1 cgd /*
1271 1.1 cgd * copy input file to backup file if in_name is /blah/blah/blah/file, then
1272 1.1 cgd * backup file will be ".Bfile" then make the backup file the input and
1273 1.1 cgd * original input file the output
1274 1.1 cgd */
1275 1.6 lukem void
1276 1.13 wiz bakcopy(void)
1277 1.1 cgd {
1278 1.6 lukem int n, bakchn;
1279 1.6 lukem char buff[8 * 1024];
1280 1.18 lukem const char *p;
1281 1.6 lukem
1282 1.6 lukem /* construct file name .Bfile */
1283 1.6 lukem for (p = in_name; *p; p++); /* skip to end of string */
1284 1.6 lukem while (p > in_name && *p != '/') /* find last '/' */
1285 1.6 lukem p--;
1286 1.6 lukem if (*p == '/')
1287 1.6 lukem p++;
1288 1.6 lukem sprintf(bakfile, "%s.BAK", p);
1289 1.6 lukem
1290 1.6 lukem /* copy in_name to backup file */
1291 1.6 lukem bakchn = creat(bakfile, 0600);
1292 1.6 lukem if (bakchn < 0)
1293 1.6 lukem err(1, "%s", bakfile);
1294 1.6 lukem while ((n = read(fileno(input), buff, sizeof buff)) > 0)
1295 1.6 lukem if (write(bakchn, buff, n) != n)
1296 1.6 lukem err(1, "%s", bakfile);
1297 1.6 lukem if (n < 0)
1298 1.6 lukem err(1, "%s", in_name);
1299 1.6 lukem close(bakchn);
1300 1.6 lukem fclose(input);
1301 1.6 lukem
1302 1.6 lukem /* re-open backup file as the input file */
1303 1.6 lukem input = fopen(bakfile, "r");
1304 1.6 lukem if (input == 0)
1305 1.6 lukem err(1, "%s", bakfile);
1306 1.6 lukem /* now the original input file will be the output */
1307 1.6 lukem output = fopen(in_name, "w");
1308 1.6 lukem if (output == 0) {
1309 1.6 lukem unlink(bakfile);
1310 1.6 lukem err(1, "%s", in_name);
1311 1.6 lukem }
1312 1.1 cgd }
1313