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