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