I wrote: > Piotr Stefaniak <postg...@piotr-stefaniak.me> writes: >> Sorry, but GNU indent already uses -kr for something else and I would >> like FreeBSD indent have something like that under the same name. >> Besides, indent has too many options and this one doesn't look like >> particularly desired by anyone. It's possible that someone will complain >> some day, but I don't think we should assume that they'll do or that >> they're more important than the other users who benefit from your change >> being the default behavior and no additional options.
> Huh. OK, I'll rip the switch back out again. Here's a proposed patch for you. regards, tom lane
diff --git a/args.c b/args.c index f79de75..1850542 100644 --- a/args.c +++ b/args.c @@ -55,7 +55,7 @@ static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; #include "indent_globs.h" #include "indent.h" -#define INDENT_VERSION "2.0" +#define INDENT_VERSION "2.1" /* profile types */ #define PRO_SPECIAL 1 /* special case */ diff --git a/indent.h b/indent.h index 0fffd89..1708dbc 100644 --- a/indent.h +++ b/indent.h @@ -41,6 +41,8 @@ void diag2(int, const char *); void diag3(int, const char *, int); void diag4(int, const char *, int, int); void dump_line(void); +int lookahead(void); +void lookahead_reset(void); void fill_buffer(void); void parse(int); void pr_comment(void); diff --git a/io.c b/io.c index df11094..fbaa5dd 100644 --- a/io.c +++ b/io.c @@ -51,6 +51,14 @@ static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; int comment_open; static int paren_target; + +static char *lookahead_buf; /* malloc'd buffer, or NULL initially */ +static char *lookahead_buf_end; /* end+1 of allocated space */ +static char *lookahead_start; /* => next char for fill_buffer() to fetch */ +static char *lookahead_ptr; /* => next char for lookahead() to fetch */ +static char *lookahead_end; /* last+1 valid char in lookahead_buf */ +static char *lookahead_bp_save; /* lookahead position in bp_save, if any */ + static int pad_output(int current, int target); void @@ -252,6 +260,73 @@ compute_label_target(void) : ps.ind_size * (ps.ind_level - label_offset) + 1; } +/* + * Read data ahead of what has been collected into in_buffer. + * + * Successive calls get further and further ahead, until we hit EOF. + * Call lookahead_reset() to rescan from just beyond in_buffer. + * + * Lookahead is automatically reset whenever fill_buffer() reads beyond + * the lookahead buffer, i.e., you can't use this for "look behind". + * + * The standard pattern for potentially multi-line lookahead is to call + * lookahead_reset(), then enter a loop that scans forward from buf_ptr + * to buf_end, then (if necessary) calls lookahead() to read additional + * characters from beyond the end of the current line. + */ +int +lookahead(void) +{ + /* First read whatever's in bp_save area */ + if (lookahead_bp_save != NULL && lookahead_bp_save < be_save) + return (unsigned char) *lookahead_bp_save++; + /* Else, we have to examine and probably fill the main lookahead buffer */ + while (lookahead_ptr >= lookahead_end) { + int i = getc(input); + + if (i == EOF) + return i; + if (i == '\0') + continue; /* fill_buffer drops nulls, and so do we */ + + if (lookahead_end >= lookahead_buf_end) { + /* Need to allocate or enlarge lookahead_buf */ + char *new_buf; + size_t req; + + if (lookahead_buf == NULL) { + req = 64; + new_buf = malloc(req); + } else { + req = (lookahead_buf_end - lookahead_buf) * 2; + new_buf = realloc(lookahead_buf, req); + } + if (new_buf == NULL) + errx(1, "too much lookahead required"); + lookahead_start = new_buf + (lookahead_start - lookahead_buf); + lookahead_ptr = new_buf + (lookahead_ptr - lookahead_buf); + lookahead_end = new_buf + (lookahead_end - lookahead_buf); + lookahead_buf = new_buf; + lookahead_buf_end = new_buf + req; + } + + *lookahead_end++ = i; + } + return (unsigned char) *lookahead_ptr++; +} + +/* + * Reset so that lookahead() will again scan from just beyond what's in + * in_buffer. + */ +void +lookahead_reset(void) +{ + /* Reset the main lookahead buffer */ + lookahead_ptr = lookahead_start; + /* If bp_save isn't NULL, we need to scan that first */ + lookahead_bp_save = bp_save; +} /* * Copyright (C) 1976 by the Board of Trustees of the University of Illinois @@ -261,7 +336,9 @@ compute_label_target(void) * * NAME: fill_buffer * - * FUNCTION: Reads one block of input into input_buffer + * FUNCTION: Reads one line of input into in_buffer, + * sets up buf_ptr and buf_end to point to the line's start and end+1. + * (Note that the buffer does not get null-terminated.) * * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A * Willcox of CAC Added check for switch back to partly full input @@ -279,6 +356,7 @@ fill_buffer(void) buf_ptr = bp_save; /* do not read anything, just switch buffers */ buf_end = be_save; bp_save = be_save = NULL; + lookahead_bp_save = NULL; if (buf_ptr < buf_end) return; /* only return if there is really something in * this buffer */ @@ -293,16 +371,21 @@ fill_buffer(void) p = in_buffer + offset; in_buffer_limit = in_buffer + size - 2; } - if ((i = getc(f)) == EOF) { + if (lookahead_start < lookahead_end) { + i = (unsigned char) *lookahead_start++; + } else { + lookahead_start = lookahead_ptr = lookahead_end = lookahead_buf; + if ((i = getc(f)) == EOF) { *p++ = ' '; *p++ = '\n'; had_eof = true; break; + } } if (i != '\0') *p++ = i; if (i == '\n') - break; + break; } buf_ptr = in_buffer; buf_end = p; diff --git a/lexi.c b/lexi.c index 3c7bfef..d43723c 100644 --- a/lexi.c +++ b/lexi.c @@ -148,6 +148,74 @@ strcmp_type(const void *e1, const void *e2) return (strcmp(e1, *(const char * const *)e2)); } +/* + * Decide whether "foo(..." is a function definition or declaration. + * + * At call, we are looking at the '('. Look ahead to find the first + * '{', ';' or ',' that is not within parentheses or comments; then + * it's a definition if we found '{', otherwise a declaration. + * Note that this rule is fooled by K&R-style parameter declarations, + * but telling the difference between those and function attributes + * seems like more trouble than it's worth. This code could also be + * fooled by mismatched parens or apparent comment starts within string + * literals, but that seems unlikely in the context it's used in. + */ +static int +is_func_definition(char *tp) +{ + int paren_depth = 0; + int in_comment = false; + int in_slash_comment = false; + int lastc = 0; + + /* We may need to look past the end of the current buffer. */ + lookahead_reset(); + for (;;) { + int c; + + /* Fetch next character. */ + if (tp < buf_end) + c = *tp++; + else { + c = lookahead(); + if (c == EOF) + break; + } + /* Handle comments. */ + if (in_comment) { + if (lastc == '*' && c == '/') + in_comment = false; + } else if (lastc == '/' && c == '*' && !in_slash_comment) + in_comment = true; + else if (in_slash_comment) { + if (c == '\n') + in_slash_comment = false; + } else if (lastc == '/' && c == '/') + in_slash_comment = true; + /* Count nested parens properly. */ + else if (c == '(') + paren_depth++; + else if (c == ')') { + paren_depth--; + /* + * If we find unbalanced parens, we must have started inside a + * declaration. + */ + if (paren_depth < 0) + return false; + } else if (paren_depth == 0) { + /* We are outside any parentheses or comments. */ + if (c == '{') + return true; + else if (c == ';' || c == ',') + return false; + } + lastc = c; + } + /* Hit EOF --- for lack of anything better, assume "not a definition". */ + return false; +} + int lexi(struct parser_state *state) { @@ -348,15 +416,12 @@ lexi(struct parser_state *state) } /* end of if (found_it) */ if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 && state->in_parameter_declaration == 0 && state->block_init == 0) { - char *tp = buf_ptr; - while (tp < buf_end) - if (*tp++ == ')' && (*tp == ';' || *tp == ',')) - goto not_proc; - strncpy(state->procname, token, sizeof state->procname - 1); - if (state->in_decl) - state->in_parameter_declaration = 1; - return (funcname); - not_proc:; + if (is_func_definition(buf_ptr)) { + strncpy(state->procname, token, sizeof state->procname - 1); + if (state->in_decl) + state->in_parameter_declaration = 1; + return (funcname); + } } /* * The following hack attempts to guess whether or not the current diff --git a/tests/declarations.0 b/tests/declarations.0 index 6d668b1..8419494 100644 --- a/tests/declarations.0 +++ b/tests/declarations.0 @@ -70,10 +70,10 @@ static int ald_shutingdown = 0; struct thread *ald_thread; static int -do_execve(td, args, mac_p) - struct thread *td; - struct image_args *args; - struct mac *mac_p; +do_execve( +struct thread *td, +struct image_args *args, +struct mac *mac_p) { } diff --git a/tests/declarations.0.stdout b/tests/declarations.0.stdout index e97e447..ab5a447 100644 --- a/tests/declarations.0.stdout +++ b/tests/declarations.0.stdout @@ -64,10 +64,10 @@ static int ald_shutingdown = 0; struct thread *ald_thread; static int -do_execve(td, args, mac_p) - struct thread *td; - struct image_args *args; - struct mac *mac_p; +do_execve( + struct thread *td, + struct image_args *args, + struct mac *mac_p) { } diff --git a/tests/list_head.0 b/tests/list_head.0 index 3a186ca..35874eb 100644 --- a/tests/list_head.0 +++ b/tests/list_head.0 @@ -1,10 +1,9 @@ /* $FreeBSD$ */ /* See r309380 */ static int -do_execve(td, args, mac_p) - struct thread *td; - struct image_args *args; - struct mac *mac_p; +do_execve(struct thread *td, +struct image_args *args, +struct mac *mac_p) { } diff --git a/tests/list_head.0.stdout b/tests/list_head.0.stdout index b6f0762..2ebcca5 100644 --- a/tests/list_head.0.stdout +++ b/tests/list_head.0.stdout @@ -1,10 +1,9 @@ /* $FreeBSD$ */ /* See r309380 */ static int -do_execve(td, args, mac_p) - struct thread *td; - struct image_args *args; - struct mac *mac_p; +do_execve(struct thread *td, + struct image_args *args, + struct mac *mac_p) { }