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